1 20 package org.enhydra.barracuda.core.event; 21 22 import java.util.*; 23 import java.lang.reflect.*; 24 25 import org.apache.log4j.*; 26 27 31 public class DefaultEventPool implements EventPool { 32 33 protected static final Logger logger = Logger.getLogger(DefaultEventPool.class.getName()); 35 36 public static int DEFAULT_POOL_SIZE = 50; public static long DEFAULT_TIMEOUT = 60000; public static long DEFAULT_RETRY_INTERVAL = 50; public static int DEFAULT_MAX_RETRIES = 3; public static long DEFAULT_CLEANUP_INTERVAL = 600000; 43 protected Map eventMap = null; 45 protected int poolSize = -1; 46 protected long timeout = -1; 47 protected long retryInterval = -1; 48 protected int maxRetries = -1; 49 protected long cleanupInterval = -1; 50 protected long lastUpdate = -1; 51 protected long lastCleanup = -1; 52 protected Object sync = new Object (); 53 private Thread thread = null; 54 private boolean stayAlive = true; 55 56 62 public DefaultEventPool() { 63 this(DEFAULT_POOL_SIZE, DEFAULT_TIMEOUT, DEFAULT_RETRY_INTERVAL, DEFAULT_MAX_RETRIES, DEFAULT_CLEANUP_INTERVAL); } 67 68 80 public DefaultEventPool(int ipoolSize, long itimeout, long iretryInterval, int imaxRetries, long icleanupInterval) { 81 eventMap = new HashMap(); 83 poolSize = ipoolSize; 85 timeout = itimeout; 86 retryInterval = iretryInterval; 87 maxRetries = imaxRetries; 88 cleanupInterval = icleanupInterval; 89 if (logger.isInfoEnabled()) logger.info("Instantiating EventPool:"+this+" Pool size:"+poolSize+" Timeout:"+timeout+" Retry Interval:"+retryInterval+" Max Retries:"+maxRetries+" Cleanup Interval:"+cleanupInterval); 90 91 thread = new Thread (new EventListCleanerUpper()); 93 thread.setName("Barracuda event pool cleanup thread"); 94 thread.start(); 95 } 96 97 105 public BaseEvent checkoutEvent(Class event) throws NoAvailableEventsException, InvalidClassException { 106 if (logger.isInfoEnabled()) logger.info("Checking out event "+event.getName()); 107 if (!((BaseEvent.class).isAssignableFrom(event))) throw new InvalidClassException ("Class "+event.getName()+" is not a BaseEvent"); 108 109 int cntr = 1; 113 BaseEvent be = null; 114 while (be==null) try { 115 synchronized (sync) { 116 EventList el = (EventList) eventMap.get(event); 117 if (el==null) { 118 el = new EventList(); 119 eventMap.put(event, el); 120 } 121 be = el.lock(event); 122 } 123 } catch (NoAvailableEventsException e) { 124 try { 126 if (++cntr>maxRetries) { 127 logger.warn("ALERT: EventPool timeout. You might want to consider upping your pool size to avoid this condition"); 128 throw e; 129 } 130 if (logger.isDebugEnabled()) logger.debug("Waiting "+cntr+" for next available event "+event.getName()); 131 Thread.yield(); 132 Thread.sleep(retryInterval); 133 } catch (InterruptedException ie) {} 134 } 135 136 return be; 137 } 138 139 145 public void releaseEvent(BaseEvent event) { 146 if (logger.isInfoEnabled()) logger.info("Releasing event "+event); 147 synchronized (sync) { 148 EventList el = (EventList) eventMap.get(event.getClass()); 149 if (el==null) return; 150 el.release(event); 151 } 152 } 153 154 160 public void cleanupLockedEvents() { 161 lastCleanup = System.currentTimeMillis(); 162 if (logger.isInfoEnabled()) logger.info("Cleaning up locked events @"+lastCleanup); 163 synchronized (sync) { 164 Iterator it = eventMap.values().iterator(); 165 while (it.hasNext()) { 166 EventList el = (EventList) it.next(); 167 el.cleanup(); 168 } 169 } 170 } 171 172 180 public void shutdown() { 181 stayAlive = false; 182 if (thread!=null) { 183 thread.interrupt(); 184 thread = null; 186 } 187 } 188 190 191 195 class EventList { 196 String name = null; 197 List freeList = new ArrayList(poolSize); 198 List lockedList = new ArrayList(poolSize); 199 200 206 public BaseEvent lock(Class event) throws InvalidClassException, NoAvailableEventsException { 207 if (name==null) name = event.getName(); 209 if (logger.isDebugEnabled()) logger.debug("Attempting to lock event "+name); 210 211 if (freeList.size()<1 && lockedList.size()>=poolSize) throw new NoAvailableEventsException("No available events:"+event); 217 218 BaseEvent be = null; 220 if (freeList.size()>0) { 221 if (logger.isDebugEnabled()) logger.debug("Looking up next event "+name); 222 be = (BaseEvent) freeList.get(0); 223 freeList.remove(0); 224 } 225 226 if (be==null) { 228 if (logger.isDebugEnabled()) logger.debug("Instantiating event "+name); 229 try { 230 if (logger.isDebugEnabled()) logger.debug("Instantiating Event"); 233 be = (BaseEvent) event.newInstance(); 234 } catch (Exception e) { 235 throw new InvalidClassException ("Error instantiating event:"+event, e); 236 } 237 } 238 239 if (logger.isDebugEnabled()) logger.debug("Locking event "+be+" in EventList: "+name); 242 be.touch(); 243 lockedList.add(be); 244 lastUpdate = be.getTimestamp(); 245 return be; 246 } 247 248 253 public void release(BaseEvent be) { 254 if (logger.isDebugEnabled()) logger.debug("Releasing event "+be+" in EventList: "+name); 255 lockedList.remove(be); 256 be.reset(); 257 freeList.add(be); 258 } 259 260 263 public void cleanup() { 264 if (logger.isDebugEnabled()) logger.debug("Cleaning up EventList: "+name); 265 boolean gotSome = false; 266 Iterator it = lockedList.iterator(); 267 long curTime = System.currentTimeMillis(); 268 while (it.hasNext()) { 269 BaseEvent be = (BaseEvent) it.next(); 270 if (be.getTimestamp()-curTime>timeout) { 271 if (logger.isDebugEnabled()) logger.debug("Forcing release for event:"+be); 272 release(be); 273 gotSome = true; 274 } 275 } 276 if (logger.isDebugEnabled() && !gotSome) logger.debug("All was clean...no events needed to be released"); 277 } 278 279 protected void finalize() { 280 if (logger.isInfoEnabled()) logger.info("Finalizing event pool..."); 281 stayAlive = false; 282 283 if (thread!=null) { 289 thread.interrupt(); 290 thread = null; 292 } 293 } 295 } 296 297 298 302 class EventListCleanerUpper implements Runnable { 303 304 public void run() { 305 if (logger.isInfoEnabled()) logger.info("Starting EventListCleanerUpper (ELCU)..."); 306 307 while (stayAlive) { 309 try { 310 if (logger.isDebugEnabled()) logger.debug("ELCU...Going to sleep"); 312 Thread.yield(); 313 Thread.sleep(cleanupInterval); 314 315 if (logger.isDebugEnabled()) logger.debug("ELCU...Checking to see if cleanup necessary"); 317 if (lastCleanup>=lastUpdate) continue; 318 319 if (logger.isDebugEnabled()) logger.debug("ELCU...Running cleanup"); 321 cleanupLockedEvents(); 322 } catch (InterruptedException e) {} 323 } 324 if (logger.isInfoEnabled()) logger.info("Shutting down ELCU...Goodbye."); 325 } 326 } 327 328 329 } 330 | Popular Tags |