1 | |
|
2 | |
|
3 | |
|
4 | |
|
5 | |
|
6 | |
|
7 | |
|
8 | |
|
9 | |
|
10 | |
|
11 | |
|
12 | |
|
13 | |
|
14 | |
|
15 | |
|
16 | |
package org.apache.commons.cache; |
17 | |
|
18 | |
import java.io.ByteArrayOutputStream; |
19 | |
import java.io.FileOutputStream; |
20 | |
import java.io.FileInputStream; |
21 | |
import java.io.ObjectOutputStream; |
22 | |
import java.io.ObjectInputStream; |
23 | |
import java.io.BufferedOutputStream; |
24 | |
import java.io.BufferedInputStream; |
25 | |
import java.io.Serializable; |
26 | |
import java.io.IOException; |
27 | |
import java.io.File; |
28 | |
|
29 | |
|
30 | |
|
31 | |
|
32 | |
|
33 | |
|
34 | |
public class SimpleCache extends BaseCache implements Cache { |
35 | 0 | protected GroupMap _gm = null; |
36 | 0 | protected EvictionPolicy _ep = null; |
37 | 0 | protected StashPolicy _sp = null; |
38 | 0 | protected Stash _stash = null; |
39 | 0 | protected boolean _wantsSerialized = false; |
40 | 0 | protected File _persistFile = null; |
41 | |
|
42 | 0 | protected long _numRetrieveRequested = 0; |
43 | 0 | protected long _numRetrieveFound = 0; |
44 | 0 | protected long _numStoreRequested = 0; |
45 | 0 | protected long _numStoreStored = 0; |
46 | 0 | protected long _numCleared = 0; |
47 | |
|
48 | |
public SimpleCache(Stash stash) { |
49 | 0 | this(stash,null,null,null); |
50 | 0 | } |
51 | |
|
52 | |
public SimpleCache(Stash stash, EvictionPolicy ep) { |
53 | 0 | this(stash,ep,null,null); |
54 | 0 | } |
55 | |
|
56 | |
public SimpleCache(Stash stash, EvictionPolicy ep, StashPolicy sp) { |
57 | 0 | this(stash,ep,sp,null,null); |
58 | 0 | } |
59 | |
|
60 | |
public SimpleCache(Stash stash, EvictionPolicy ep, StashPolicy sp, GroupMap tm) { |
61 | 0 | this(stash,ep,sp,tm,null); |
62 | 0 | } |
63 | |
|
64 | 0 | public SimpleCache(Stash stash, EvictionPolicy ep, StashPolicy sp, GroupMap tm, File persistFile) { |
65 | 0 | _gm = tm; |
66 | 0 | if(null != _gm) { tm.setCache(this); } |
67 | 0 | _stash = stash; |
68 | 0 | _stash.setCache(this); |
69 | 0 | _ep = ep; |
70 | 0 | if(null != _ep) { _ep.setCache(this); } |
71 | 0 | _sp = sp; |
72 | 0 | if(null != _sp) { _sp.setCache(this); } |
73 | 0 | _wantsSerialized = _stash.wantsSerializedForm() || ((null == _sp) ? false : _sp.wantsSerializedForm()); |
74 | 0 | _persistFile = persistFile; |
75 | 0 | } |
76 | |
|
77 | |
public synchronized long getStat(CacheStat stat) throws UnsupportedOperationException { |
78 | 0 | if(stat.equals(CacheStat.CUR_CAPACITY)) { |
79 | |
try { |
80 | 0 | return (long)(1000F * _stash.capacity()); |
81 | 0 | } catch(Exception e) { |
82 | 0 | throw new UnsupportedOperationException(); |
83 | |
} |
84 | 0 | } else if(stat.equals(CacheStat.NUM_CLEARED)) { |
85 | 0 | throw new UnsupportedOperationException(); |
86 | 0 | } else if(stat.equals(CacheStat.NUM_RETRIEVE_FOUND)) { |
87 | 0 | return _numRetrieveFound; |
88 | 0 | } else if(stat.equals(CacheStat.NUM_RETRIEVE_NOT_FOUND)) { |
89 | 0 | return (_numRetrieveRequested - _numRetrieveFound); |
90 | 0 | } else if(stat.equals(CacheStat.NUM_RETRIEVE_REQUESTED)) { |
91 | 0 | return _numRetrieveRequested; |
92 | 0 | } else if(stat.equals(CacheStat.NUM_STORE_NOT_STORED)) { |
93 | 0 | return (_numStoreRequested - _numStoreStored); |
94 | 0 | } else if(stat.equals(CacheStat.NUM_STORE_REQUESTED)) { |
95 | 0 | return _numStoreRequested; |
96 | 0 | } else if(stat.equals(CacheStat.NUM_STORE_STORED)) { |
97 | 0 | return _numStoreStored; |
98 | |
} else { |
99 | 0 | throw new UnsupportedOperationException("CacheStat \"" + stat.toString() + "\" not recoginzed."); |
100 | |
} |
101 | |
} |
102 | |
|
103 | |
public static SimpleCache readFromFile(String f) throws IOException, ClassNotFoundException { |
104 | 0 | return SimpleCache.readFromFile(new File(f)); |
105 | |
} |
106 | |
|
107 | |
public static SimpleCache readFromFile(File f) throws IOException, ClassNotFoundException { |
108 | 0 | ObjectInputStream in = null; |
109 | |
try { |
110 | 0 | in = new ObjectInputStream(new BufferedInputStream(new FileInputStream(f))); |
111 | 0 | return (SimpleCache)(in.readObject()); |
112 | 0 | } catch(ClassNotFoundException e) { |
113 | 0 | e.fillInStackTrace(); |
114 | 0 | throw e; |
115 | 0 | } catch(IOException e) { |
116 | 0 | e.fillInStackTrace(); |
117 | 0 | throw e; |
118 | |
} finally { |
119 | 0 | try { in.close(); } catch(Exception e) { } |
120 | |
} |
121 | |
} |
122 | |
|
123 | |
protected synchronized void writeToFile() { |
124 | 0 | if(null == _persistFile) { |
125 | 0 | return; |
126 | |
} else { |
127 | 0 | ObjectOutputStream out = null; |
128 | |
try { |
129 | 0 | out = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(_persistFile))); |
130 | 0 | out.writeObject(this); |
131 | 0 | out.flush(); |
132 | 0 | } catch(Exception e) { |
133 | 0 | e.printStackTrace(); |
134 | |
} finally { |
135 | 0 | try { out.close(); } catch(Exception e) { } |
136 | 0 | } |
137 | |
} |
138 | 0 | } |
139 | |
|
140 | |
public Serializable[] getKeysForGroup(Serializable group) { |
141 | 0 | if(null == _gm) { |
142 | 0 | throw new IllegalStateException("no group map right now"); |
143 | |
} else { |
144 | 0 | return _gm.getKeysForGroup(group); |
145 | |
} |
146 | |
} |
147 | |
|
148 | |
public synchronized boolean store(Serializable key, Serializable val, Long expiry, Long cost, Serializable group) { |
149 | 0 | if(contains(key)) { |
150 | 0 | clear(key); |
151 | |
} |
152 | 0 | _numStoreRequested++; |
153 | 0 | if(null != expiry) { |
154 | 0 | if(expiry.longValue() <= System.currentTimeMillis()) { |
155 | 0 | return false; |
156 | |
} |
157 | |
} |
158 | |
|
159 | 0 | broadcastStoreRequested(key,val,expiry,cost,group); |
160 | 0 | byte[] serform = null; |
161 | 0 | if(_wantsSerialized) { |
162 | 0 | ByteArrayOutputStream byout = null; |
163 | 0 | ObjectOutputStream out = null; |
164 | |
try { |
165 | 0 | byout = new ByteArrayOutputStream(); |
166 | 0 | out = new ObjectOutputStream(byout); |
167 | 0 | out.writeObject(val); |
168 | 0 | out.flush(); |
169 | 0 | serform = byout.toByteArray(); |
170 | 0 | } catch(IOException e) { |
171 | 0 | serform = null; |
172 | |
} finally { |
173 | 0 | try { byout.close(); } catch(Exception e) { } |
174 | 0 | try { out.close(); } catch(Exception e) { } |
175 | 0 | } |
176 | |
} |
177 | 0 | if(_sp == null || _sp.shouldStore(key,val,expiry,cost,serform)) { |
178 | 0 | switch(_stash.canStore(key,val,expiry,cost,group,serform)) { |
179 | |
case Stash.YES: |
180 | 0 | _stash.store(key,val,expiry,cost,group,serform); |
181 | 0 | broadcastStored(key,val,expiry,cost,group); |
182 | 0 | _numStoreStored++; |
183 | 0 | writeToFile(); |
184 | 0 | return true; |
185 | |
case Stash.NO_FULL: |
186 | 0 | if(tryToEvict()) { |
187 | 0 | return store(key,val,expiry,cost,group); |
188 | |
} else { |
189 | 0 | broadcastNotStored(key,val,expiry,cost,group); |
190 | 0 | return false; |
191 | |
} |
192 | |
case Stash.NO_NOT_STORABLE: |
193 | |
case Stash.NO: |
194 | |
default: |
195 | 0 | broadcastNotStored(key,val,expiry,cost,group); |
196 | 0 | return false; |
197 | |
} |
198 | |
} else { |
199 | 0 | broadcastNotStored(key,val,expiry,cost,group); |
200 | 0 | return false; |
201 | |
} |
202 | |
} |
203 | |
|
204 | |
public synchronized Serializable retrieve(Serializable key) { |
205 | 0 | _numRetrieveRequested++; |
206 | 0 | broadcastRetrieveRequested(key); |
207 | 0 | Serializable obj = _stash.retrieve(key); |
208 | 0 | if(null == obj) { |
209 | 0 | broadcastNotRetrieved(key); |
210 | 0 | return null; |
211 | |
} else { |
212 | 0 | broadcastRetrieved(key); |
213 | 0 | _numRetrieveFound++; |
214 | 0 | return obj; |
215 | |
} |
216 | |
} |
217 | |
|
218 | |
public synchronized boolean contains(Serializable key) { |
219 | 0 | return _stash.contains(key); |
220 | |
} |
221 | |
|
222 | |
public synchronized void clear(Serializable key) { |
223 | 0 | _numCleared++; |
224 | 0 | _stash.clear(key); |
225 | 0 | broadcastCleared(key); |
226 | 0 | writeToFile(); |
227 | 0 | } |
228 | |
|
229 | |
public synchronized void clear() { |
230 | 0 | _stash.clear(); |
231 | 0 | broadcastCleared(); |
232 | 0 | writeToFile(); |
233 | 0 | } |
234 | |
|
235 | |
protected synchronized boolean tryToEvict() { |
236 | 0 | if(null == _ep) { |
237 | 0 | return false; |
238 | |
} else { |
239 | 0 | Serializable key = _ep.getEvictionCandidate(); |
240 | 0 | if(null == key) { |
241 | 0 | return false; |
242 | |
} else { |
243 | 0 | clear(key); |
244 | 0 | return true; |
245 | |
} |
246 | |
} |
247 | |
} |
248 | |
|
249 | |
public static void main(String[] args) throws Exception { |
250 | 0 | File cfile = null; |
251 | 0 | SimpleCache cache = null; |
252 | 0 | if(args.length > 0) { |
253 | 0 | ObjectInputStream in = null; |
254 | |
try { |
255 | 0 | in = new ObjectInputStream(new FileInputStream(new File(args[0]))); |
256 | 0 | cache = (SimpleCache)(in.readObject()); |
257 | 0 | } catch(Exception e) { |
258 | 0 | cache = null; |
259 | 0 | e.printStackTrace(); |
260 | |
} finally { |
261 | 0 | try { in.close(); } catch(Exception e) { } |
262 | 0 | } |
263 | |
} |
264 | |
|
265 | 0 | if(null == cache) { |
266 | 0 | LRUEvictionPolicy ep = new LRUEvictionPolicy(); |
267 | 0 | Stash s = new FileStash(10000L); |
268 | 0 | cache = new SimpleCache(s,ep,null,null,new File("persitent.ser")); |
269 | |
|
270 | 0 | System.out.println(cache.store("Key1","Value1",null,null)); |
271 | 0 | System.out.println(cache.store("Key2","Value2",new Long(System.currentTimeMillis() + 10000),null)); |
272 | 0 | System.out.println(cache.store("Key3","Value3",new Long(System.currentTimeMillis() + 9000),null)); |
273 | 0 | System.out.println(cache.store("Key4","Value4",new Long(System.currentTimeMillis() + 8000),null)); |
274 | 0 | System.out.println(cache.store("Key5","Value5",new Long(System.currentTimeMillis() + 7000),null)); |
275 | 0 | System.out.println(cache.store("Key6","Value6",new Long(System.currentTimeMillis() + 6000),null)); |
276 | 0 | System.out.println(cache.store("Key7","Value7",new Long(System.currentTimeMillis() + 5000),null)); |
277 | 0 | System.out.println(cache.store("Key8","Value8",new Long(System.currentTimeMillis() + 4000),null)); |
278 | 0 | System.out.println(cache.store("Key9","Value9",new Long(System.currentTimeMillis() + 3000),null)); |
279 | 0 | System.out.println(cache.store("Key10","Value10",new Long(System.currentTimeMillis() + 40000),null)); |
280 | 0 | System.out.println(cache.store("Key11","Value11",new Long(System.currentTimeMillis() + 30000),null)); |
281 | 0 | System.out.println(cache.store("Key12","Value12",new Long(System.currentTimeMillis() + 20000),null)); |
282 | |
|
283 | 0 | if(args.length > 0) { |
284 | 0 | ObjectOutputStream out = null; |
285 | |
try { |
286 | 0 | out = new ObjectOutputStream(new FileOutputStream(new File(args[0]))); |
287 | 0 | out.writeObject(cache); |
288 | 0 | } catch(Exception e) { |
289 | 0 | e.printStackTrace(); |
290 | |
} finally { |
291 | 0 | try { out.close(); } catch(Exception e) { } |
292 | 0 | } |
293 | |
} |
294 | |
} |
295 | |
|
296 | 0 | for(int i=0;i<12;i++) { |
297 | 0 | System.out.println("Key1\t" + cache.retrieve("Key1")); |
298 | 0 | System.out.println("Key2\t" + cache.retrieve("Key2")); |
299 | 0 | System.out.println("Key3\t" + cache.retrieve("Key3")); |
300 | 0 | System.out.println("Key4\t" + cache.retrieve("Key4")); |
301 | 0 | System.out.println("Key5\t" + cache.retrieve("Key5")); |
302 | 0 | System.out.println("Key6\t" + cache.retrieve("Key6")); |
303 | 0 | System.out.println("Key7\t" + cache.retrieve("Key7")); |
304 | 0 | System.out.println("Key8\t" + cache.retrieve("Key8")); |
305 | 0 | System.out.println("Key9\t" + cache.retrieve("Key9")); |
306 | 0 | System.out.println("Key10\t" + cache.retrieve("Key10")); |
307 | 0 | System.out.println("Key11\t" + cache.retrieve("Key11")); |
308 | 0 | System.out.println("Key12\t" + cache.retrieve("Key12")); |
309 | |
|
310 | 0 | System.out.println(); |
311 | 0 | Thread.sleep(1000L); |
312 | |
} |
313 | 0 | } |
314 | |
} |