001 /*
002 * Copyright 2001-2004 The Apache Software Foundation
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package org.apache.commons.cache;
017
018 import java.io.ByteArrayOutputStream;
019 import java.io.FileOutputStream;
020 import java.io.FileInputStream;
021 import java.io.ObjectOutputStream;
022 import java.io.ObjectInputStream;
023 import java.io.BufferedOutputStream;
024 import java.io.BufferedInputStream;
025 import java.io.Serializable;
026 import java.io.IOException;
027 import java.io.File;
028
029 /**
030 * tk.
031 * @version $Id: SimpleCache.java 155435 2005-02-26 13:17:27Z dirkv $
032 * @author Rodney Waldhoff
033 */
034 public class SimpleCache extends BaseCache implements Cache {
035 protected GroupMap _gm = null;
036 protected EvictionPolicy _ep = null;
037 protected StashPolicy _sp = null;
038 protected Stash _stash = null;
039 protected boolean _wantsSerialized = false;
040 protected File _persistFile = null;
041
042 protected long _numRetrieveRequested = 0;
043 protected long _numRetrieveFound = 0;
044 protected long _numStoreRequested = 0;
045 protected long _numStoreStored = 0;
046 protected long _numCleared = 0;
047
048 public SimpleCache(Stash stash) {
049 this(stash,null,null,null);
050 }
051
052 public SimpleCache(Stash stash, EvictionPolicy ep) {
053 this(stash,ep,null,null);
054 }
055
056 public SimpleCache(Stash stash, EvictionPolicy ep, StashPolicy sp) {
057 this(stash,ep,sp,null,null);
058 }
059
060 public SimpleCache(Stash stash, EvictionPolicy ep, StashPolicy sp, GroupMap tm) {
061 this(stash,ep,sp,tm,null);
062 }
063
064 public SimpleCache(Stash stash, EvictionPolicy ep, StashPolicy sp, GroupMap tm, File persistFile) {
065 _gm = tm;
066 if(null != _gm) { tm.setCache(this); }
067 _stash = stash;
068 _stash.setCache(this); // stash cannot be null
069 _ep = ep;
070 if(null != _ep) { _ep.setCache(this); }
071 _sp = sp;
072 if(null != _sp) { _sp.setCache(this); }
073 _wantsSerialized = _stash.wantsSerializedForm() || ((null == _sp) ? false : _sp.wantsSerializedForm());
074 _persistFile = persistFile;
075 }
076
077 public synchronized long getStat(CacheStat stat) throws UnsupportedOperationException {
078 if(stat.equals(CacheStat.CUR_CAPACITY)) {
079 try {
080 return (long)(1000F * _stash.capacity());
081 } catch(Exception e) {
082 throw new UnsupportedOperationException();
083 }
084 } else if(stat.equals(CacheStat.NUM_CLEARED)) {
085 throw new UnsupportedOperationException();
086 } else if(stat.equals(CacheStat.NUM_RETRIEVE_FOUND)) {
087 return _numRetrieveFound;
088 } else if(stat.equals(CacheStat.NUM_RETRIEVE_NOT_FOUND)) {
089 return (_numRetrieveRequested - _numRetrieveFound);
090 } else if(stat.equals(CacheStat.NUM_RETRIEVE_REQUESTED)) {
091 return _numRetrieveRequested;
092 } else if(stat.equals(CacheStat.NUM_STORE_NOT_STORED)) {
093 return (_numStoreRequested - _numStoreStored);
094 } else if(stat.equals(CacheStat.NUM_STORE_REQUESTED)) {
095 return _numStoreRequested;
096 } else if(stat.equals(CacheStat.NUM_STORE_STORED)) {
097 return _numStoreStored;
098 } else {
099 throw new UnsupportedOperationException("CacheStat \"" + stat.toString() + "\" not recoginzed.");
100 }
101 }
102
103 public static SimpleCache readFromFile(String f) throws IOException, ClassNotFoundException {
104 return SimpleCache.readFromFile(new File(f));
105 }
106
107 public static SimpleCache readFromFile(File f) throws IOException, ClassNotFoundException {
108 ObjectInputStream in = null;
109 try {
110 in = new ObjectInputStream(new BufferedInputStream(new FileInputStream(f)));
111 return (SimpleCache)(in.readObject());
112 } catch(ClassNotFoundException e) {
113 e.fillInStackTrace();
114 throw e;
115 } catch(IOException e) {
116 e.fillInStackTrace();
117 throw e;
118 } finally {
119 try { in.close(); } catch(Exception e) { }
120 }
121 }
122
123 protected synchronized void writeToFile() {
124 if(null == _persistFile) {
125 return;
126 } else {
127 ObjectOutputStream out = null;
128 try {
129 out = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(_persistFile)));
130 out.writeObject(this);
131 out.flush();
132 } catch(Exception e) {
133 e.printStackTrace();
134 } finally {
135 try { out.close(); } catch(Exception e) { }
136 }
137 }
138 }
139
140 public Serializable[] getKeysForGroup(Serializable group) {
141 if(null == _gm) {
142 throw new IllegalStateException("no group map right now");
143 } else {
144 return _gm.getKeysForGroup(group);
145 }
146 }
147
148 public synchronized boolean store(Serializable key, Serializable val, Long expiry, Long cost, Serializable group) {
149 if(contains(key)) {
150 clear(key);
151 }
152 _numStoreRequested++;
153 if(null != expiry) {
154 if(expiry.longValue() <= System.currentTimeMillis()) {
155 return false;
156 }
157 }
158
159 broadcastStoreRequested(key,val,expiry,cost,group);
160 byte[] serform = null;
161 if(_wantsSerialized) {
162 ByteArrayOutputStream byout = null;
163 ObjectOutputStream out = null;
164 try {
165 byout = new ByteArrayOutputStream();
166 out = new ObjectOutputStream(byout);
167 out.writeObject(val);
168 out.flush();
169 serform = byout.toByteArray();
170 } catch(IOException e) {
171 serform = null;
172 } finally {
173 try { byout.close(); } catch(Exception e) { }
174 try { out.close(); } catch(Exception e) { }
175 }
176 }
177 if(_sp == null || _sp.shouldStore(key,val,expiry,cost,serform)) {
178 switch(_stash.canStore(key,val,expiry,cost,group,serform)) {
179 case Stash.YES:
180 _stash.store(key,val,expiry,cost,group,serform);
181 broadcastStored(key,val,expiry,cost,group);
182 _numStoreStored++;
183 writeToFile();
184 return true;
185 case Stash.NO_FULL:
186 if(tryToEvict()) {
187 return store(key,val,expiry,cost,group);
188 } else {
189 broadcastNotStored(key,val,expiry,cost,group);
190 return false;
191 }
192 case Stash.NO_NOT_STORABLE:
193 case Stash.NO:
194 default:
195 broadcastNotStored(key,val,expiry,cost,group);
196 return false;
197 }
198 } else {
199 broadcastNotStored(key,val,expiry,cost,group);
200 return false;
201 }
202 }
203
204 public synchronized Serializable retrieve(Serializable key) {
205 _numRetrieveRequested++;
206 broadcastRetrieveRequested(key);
207 Serializable obj = _stash.retrieve(key);
208 if(null == obj) {
209 broadcastNotRetrieved(key);
210 return null;
211 } else {
212 broadcastRetrieved(key);
213 _numRetrieveFound++;
214 return obj;
215 }
216 }
217
218 public synchronized boolean contains(Serializable key) {
219 return _stash.contains(key);
220 }
221
222 public synchronized void clear(Serializable key) {
223 _numCleared++;
224 _stash.clear(key);
225 broadcastCleared(key);
226 writeToFile();
227 }
228
229 public synchronized void clear() {
230 _stash.clear();
231 broadcastCleared();
232 writeToFile();
233 }
234
235 protected synchronized boolean tryToEvict() {
236 if(null == _ep) {
237 return false;
238 } else {
239 Serializable key = _ep.getEvictionCandidate();
240 if(null == key) {
241 return false;
242 } else {
243 clear(key);
244 return true;
245 }
246 }
247 }
248
249 public static void main(String[] args) throws Exception {
250 File cfile = null;
251 SimpleCache cache = null;
252 if(args.length > 0) {
253 ObjectInputStream in = null;
254 try {
255 in = new ObjectInputStream(new FileInputStream(new File(args[0])));
256 cache = (SimpleCache)(in.readObject());
257 } catch(Exception e) {
258 cache = null;
259 e.printStackTrace();
260 } finally {
261 try { in.close(); } catch(Exception e) { }
262 }
263 }
264
265 if(null == cache) {
266 LRUEvictionPolicy ep = new LRUEvictionPolicy();
267 Stash s = new FileStash(10000L);
268 cache = new SimpleCache(s,ep,null,null,new File("persitent.ser"));
269
270 System.out.println(cache.store("Key1","Value1",null,null));
271 System.out.println(cache.store("Key2","Value2",new Long(System.currentTimeMillis() + 10000),null));
272 System.out.println(cache.store("Key3","Value3",new Long(System.currentTimeMillis() + 9000),null));
273 System.out.println(cache.store("Key4","Value4",new Long(System.currentTimeMillis() + 8000),null));
274 System.out.println(cache.store("Key5","Value5",new Long(System.currentTimeMillis() + 7000),null));
275 System.out.println(cache.store("Key6","Value6",new Long(System.currentTimeMillis() + 6000),null));
276 System.out.println(cache.store("Key7","Value7",new Long(System.currentTimeMillis() + 5000),null));
277 System.out.println(cache.store("Key8","Value8",new Long(System.currentTimeMillis() + 4000),null));
278 System.out.println(cache.store("Key9","Value9",new Long(System.currentTimeMillis() + 3000),null));
279 System.out.println(cache.store("Key10","Value10",new Long(System.currentTimeMillis() + 40000),null));
280 System.out.println(cache.store("Key11","Value11",new Long(System.currentTimeMillis() + 30000),null));
281 System.out.println(cache.store("Key12","Value12",new Long(System.currentTimeMillis() + 20000),null));
282
283 if(args.length > 0) {
284 ObjectOutputStream out = null;
285 try {
286 out = new ObjectOutputStream(new FileOutputStream(new File(args[0])));
287 out.writeObject(cache);
288 } catch(Exception e) {
289 e.printStackTrace();
290 } finally {
291 try { out.close(); } catch(Exception e) { }
292 }
293 }
294 }
295
296 for(int i=0;i<12;i++) {
297 System.out.println("Key1\t" + cache.retrieve("Key1"));
298 System.out.println("Key2\t" + cache.retrieve("Key2"));
299 System.out.println("Key3\t" + cache.retrieve("Key3"));
300 System.out.println("Key4\t" + cache.retrieve("Key4"));
301 System.out.println("Key5\t" + cache.retrieve("Key5"));
302 System.out.println("Key6\t" + cache.retrieve("Key6"));
303 System.out.println("Key7\t" + cache.retrieve("Key7"));
304 System.out.println("Key8\t" + cache.retrieve("Key8"));
305 System.out.println("Key9\t" + cache.retrieve("Key9"));
306 System.out.println("Key10\t" + cache.retrieve("Key10"));
307 System.out.println("Key11\t" + cache.retrieve("Key11"));
308 System.out.println("Key12\t" + cache.retrieve("Key12"));
309
310 System.out.println();
311 Thread.sleep(1000L);
312 }
313 }
314 }