00001
package com.quadcap.util.collections;
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
import java.io.IOException;
00042
import java.io.PrintWriter;
00043
00044
import java.util.Enumeration;
00045
import java.util.Hashtable;
00046
00047
import com.quadcap.util.Debug;
00048
import com.quadcap.util.DList;
00049
import com.quadcap.util.DListItem;
00050
import com.quadcap.util.ListException;
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060 public abstract class Cache {
00061 Object
store;
00062 Object
lock;
00063 int size;
00064
00065 Hashtable
t;
00066 DList lru =
new DList();
00067
00068
00069
00070
00071
00072
00073
00074 public void init(Object store,
int size) {
00075
this.store = store;
00076
this.size = size;
00077
this.lock =
this;
00078
lru.
resize(size);
00079
t =
new Hashtable();
00080 }
00081
00082
00083
00084
00085
00086
00087
00088
00089 public void setLock(Object lock) {
00090
this.lock = lock;
00091 }
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101 public Cacheable getCacheable(Object key)
throws IOException {
00102
00103
synchronized (
lock) {
00104
00105
Cacheable c = (
Cacheable)
t.get(key);
00106
if (c == null) {
00107
00108
00109 c =
getCacheable();
00110 c.
init(
store, key);
00111
t.put(key, c);
00112 }
00113
00114
00115
try {
00116
lru.
moveFront(c.
getDListItem());
00117 }
catch (
ListException e) {
00118
Debug.print(e);
00119 }
00120 c.
incrRefCount();
00121
00122
return c;
00123 }
00124 }
00125
00126 void checkCache() {
00127
synchronized (
lock) {
00128 Hashtable s =
new Hashtable();
00129
00130
try {
00131
boolean started =
false;
00132
for (
DListItem d =
lru.
head(); !started || d !=
lru.
head();
00133 d = d.
next) {
00134 started =
true;
00135
Cacheable c = (
Cacheable)d.
obj;
00136
if (c == null)
continue;
00137 Object key = c.
getKey();
00138
Cacheable c1 = (
Cacheable)
t.get(key);
00139
if (c1 != c) {
00140 System.out.println(
"lru item not in hashtable: " +
00141 key);
00142 }
00143 s.put(key, c);
00144 }
00145 }
catch (
ListException e) {
00146
Debug.print(e);
00147 }
00148
00149
00150
for (Enumeration e =
t.keys(); e.hasMoreElements(); ) {
00151 Object key = e.nextElement();
00152
if (s.get(key) == null) {
00153 System.out.println(
"hashtable item not in lru: " + key);
00154 }
00155 }
00156 }
00157 }
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173 public Object
get(Object key)
throws IOException {
00174 Object data = null;
00175
synchronized (
lock) {
00176
Cacheable c =
getCacheable(key);
00177
try {
00178 data = c.
getData();
00179 } finally {
00180 c.
decrRefCount();
00181 }
00182 }
00183
return data;
00184 }
00185
00186
00187
00188
00189
00190 public void put(Object key, Object val)
throws IOException {
00191
synchronized (
lock) {
00192
Cacheable c =
getCacheable(key);
00193
try {
00194 c.
setData(val);
00195 } finally {
00196 c.
decrRefCount();
00197 }
00198 }
00199 }
00200
00201
00202
00203
00204
00205
00206
abstract public Cacheable makeCacheable();
00207
00208
00209
00210
00211
00212
00213
00214 Cacheable getCacheable() throws IOException {
00215
Cacheable c = null;
00216
DListItem d =
lru.
tail();
00217
00218
while (d != null) {
00219 c = (
Cacheable)d.
obj;
00220
if (c != null && c.
getRefCount() > 0) {
00221
if (d ==
lru.
head()) {
00222
show(
new PrintWriter(
Debug.debugStream));
00223
throw new RuntimeException(
"no free cache item");
00224 }
00225 d = d.
prev;
00226 }
else {
00227
break;
00228 }
00229 }
00230
00231
if (c == null) {
00232 d.
obj = c =
makeCacheable();
00233 c.
setDListItem(d);
00234 }
else {
00235 Object key = c.
getKey();
00236
if (key != null) {
00237
00238
t.remove(key);
00239 }
00240
if (c.
isDirty()) c.
flush();
00241 }
00242
return c;
00243 }
00244
00245
00246
00247
00248 public void flush() throws IOException {
00249
synchronized (
lock) {
00250
boolean started =
false;
00251
for (
DListItem d =
lru.
head(); !started || d !=
lru.
head();
00252 d = d.
next) {
00253 started =
true;
00254
Cacheable c = (
Cacheable)d.
obj;
00255
if (c != null) {
00256
00257
00258
00259
00260 c.
flush();
00261 }
00262 }
00263 }
00264 }
00265
00266 public void show(PrintWriter os) {
00267
synchronized (
lock) {
00268
lru.
show(os,
"\n");
00269 }
00270 }
00271 }