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 }