1 17 18 package org.apache.avalon.cornerstone.blocks.scheduler; 19 20 import java.util.ArrayList ; 21 import java.util.Collection ; 22 import java.util.Hashtable ; 23 import java.util.Iterator ; 24 import java.util.NoSuchElementException ; 25 import java.util.Vector ; 26 import java.util.List ; 27 import java.util.Map ; 28 29 import org.apache.avalon.cornerstone.services.scheduler.Target; 30 import org.apache.avalon.cornerstone.services.scheduler.TimeScheduler; 31 import org.apache.avalon.cornerstone.services.scheduler.TimeTrigger; 32 import org.apache.avalon.cornerstone.services.scheduler.TriggerFailureListener; 33 import org.apache.avalon.cornerstone.services.threads.ThreadManager; 34 35 import org.apache.avalon.framework.activity.Disposable; 36 import org.apache.avalon.framework.activity.Startable; 37 import org.apache.avalon.framework.logger.AbstractLogEnabled; 38 import org.apache.avalon.framework.service.ServiceException; 39 import org.apache.avalon.framework.service.ServiceManager; 40 import org.apache.avalon.framework.service.Serviceable; 41 42 49 public class DefaultTimeScheduler 50 extends AbstractLogEnabled 51 implements TimeScheduler, Serviceable, Startable, Disposable, Runnable , MonitorableTimeSchedulerMBean 52 { 53 private final Hashtable m_entries = new Hashtable (); 57 private final PriorityQueue m_priorityQueue = 58 new SynchronizedPriorityQueue( new BinaryHeap() ); 59 private ThreadManager m_threadManager; 60 private boolean m_running; 61 private ArrayList m_triggerFailureListeners = new ArrayList (); 62 63 73 protected final ThreadManager getThreadManager() 74 { 75 return m_threadManager; 76 } 77 78 protected final boolean isRunning() 79 { 80 return m_running; 81 } 82 83 protected final void setRunning( boolean running ) 84 { 85 m_running = running; 86 } 87 88 protected final List getTriggerFailureListeners() 89 { 90 return m_triggerFailureListeners; 91 } 92 93 protected final Map getEntryMap() 94 { 95 return m_entries; 96 } 97 98 protected final PriorityQueue getPriorityQueue() 99 { 100 return m_priorityQueue; 101 } 102 103 107 112 public void service( final ServiceManager serviceManager ) 113 throws ServiceException 114 { 115 m_threadManager = (ThreadManager)serviceManager.lookup( ThreadManager.ROLE ); 116 } 117 118 public void dispose() 119 { 120 if( getLogger().isDebugEnabled() ) 121 { 122 getLogger().debug( "disposal" ); 123 } 124 m_entries.clear(); 125 m_priorityQueue.clear(); 126 } 127 128 public void start() 129 throws Exception 130 { 131 getThreadManager().getDefaultThreadPool().execute( this ); 133 } 134 135 public void stop() 136 { 137 m_running = false; 138 synchronized( this ) 139 { 140 notifyAll(); 141 } 142 } 143 144 151 public void run() 152 { 153 m_running = true; 154 155 while( m_running ) 156 { 157 long duration = 0; 158 159 if( !getPriorityQueue().isEmpty() ) 160 { 161 TimeScheduledEntry entry = null; 162 synchronized( this ) 163 { 164 entry = getNextEntry(); 165 if( null == entry ) continue; 166 167 duration = entry.getNextTime() - System.currentTimeMillis(); 168 169 if( duration < 0 ) 170 { 171 getPriorityQueue().pop(); 174 175 } 181 } 182 183 if( duration < 0 ) 184 { 185 runEntry( entry ); 187 continue; 188 } 189 else if( 0 == duration ) 190 { 191 duration = 1; 196 } 197 } 198 199 try 203 { 204 synchronized( this ) 205 { 206 wait( duration ); 207 } 208 } 209 catch( final InterruptedException ie ) 210 { 211 } 212 } 213 } 214 215 222 public void addTriggerFailureListener( TriggerFailureListener listener ) 223 { 224 getTriggerFailureListeners().add( listener ); 225 } 226 227 231 public void removeTriggerFailureListener( TriggerFailureListener listener ) 232 { 233 getTriggerFailureListeners().remove( listener ); 234 } 235 236 244 public synchronized void addTrigger( final String name, 245 final TimeTrigger trigger, 246 final Target target ) 247 { 248 try 249 { 250 removeTrigger( name ); 251 } 252 catch( final NoSuchElementException nse ) 253 { 254 } 255 256 final TimeScheduledEntry entry = new TimeScheduledEntry( name, trigger, target ); 257 getEntryMap().put( name, entry ); 258 final boolean added = rescheduleEntry( entry, false ); 259 260 if( !added ) return; 261 262 try 263 { 264 if( entry == getPriorityQueue().peek() ) 265 { 266 notifyAll(); 267 } 268 } 269 catch( final NoSuchElementException nse ) 270 { 271 final String message = 272 "Unexpected exception when peek() on priority queue for " + 273 entry.getName(); 274 getLogger().warn( message, nse ); 275 } 276 } 277 278 284 public synchronized void removeTrigger( String name ) 285 throws NoSuchElementException 286 { 287 final TimeScheduledEntry entry = getEntry( name ); 289 entry.invalidate(); 290 getEntryMap().remove( name ); 291 } 292 293 299 public synchronized void resetTrigger( final String name ) 300 throws NoSuchElementException 301 { 302 final TimeScheduledEntry entry = getEntry( name ); 303 entry.getTimeTrigger().reset(); 304 rescheduleEntry( entry, true ); 305 } 306 307 311 315 public synchronized Collection getEntries() 316 { 317 Collection coll = getEntryMap().keySet(); 318 Vector retval = new Vector (); 319 for( Iterator iterator = coll.iterator(); iterator.hasNext(); ) 320 { 321 TimeScheduledEntry tse = (TimeScheduledEntry)getEntryMap().get( iterator.next() ); 322 retval.add( tse.toString() ); 323 } 324 return retval; 325 } 326 327 331 340 protected synchronized boolean rescheduleEntry( final TimeScheduledEntry timeEntry, 341 final boolean clone ) 342 { 343 TimeScheduledEntry entry = timeEntry; 344 345 if( clone ) 346 { 347 entry = new TimeScheduledEntry( timeEntry.getName(), 348 timeEntry.getTimeTrigger(), 349 timeEntry.getTarget() ); 350 timeEntry.invalidate(); 351 352 getEntryMap().remove( timeEntry.getName() ); 355 getEntryMap().put( timeEntry.getName(), entry ); 356 } 357 358 final long next = entry.getTimeTrigger().getTimeAfter( System.currentTimeMillis() ); 360 361 if( 0 < next ) 362 { 363 entry.setNextTime( next ); 364 getPriorityQueue().insert( entry ); 365 366 if( entry == getPriorityQueue().peek() ) 367 { 368 notify(); 369 } 370 371 return true; 372 } 373 else 374 { 375 return false; 376 } 377 } 378 379 386 protected TimeScheduledEntry getEntry( final String name ) 387 throws NoSuchElementException 388 { 389 final TimeScheduledEntry entry = (TimeScheduledEntry)getEntryMap().get( name ); 391 if( null != entry ) 392 { 393 return entry; 394 } 395 else 396 { 397 throw new NoSuchElementException (); 398 } 399 } 400 401 406 protected void runEntry( final TimeScheduledEntry entry ) 407 { 408 final Runnable runnable = new Runnable () 409 { 410 public void run() 411 { 412 doRunEntry( entry ); 413 } 423 }; 424 425 try 427 { 428 getThreadManager().getDefaultThreadPool().execute( runnable ); 429 } 430 catch( final Exception e ) 431 { 432 final String message = "Error executing trigger " + entry.getName(); 433 getLogger().warn( message, e ); 434 } 435 436 rescheduleEntry( entry, false ); 438 } 439 440 445 protected void doRunEntry( final TimeScheduledEntry entry ) 446 { 447 try 448 { 449 entry.getTarget().targetTriggered( entry.getName() ); 450 } 451 catch( final Error e ) 452 { 453 final String message = "Error occured executing trigger " + entry.getName(); 454 getLogger().error( message, e ); 455 notifyFailedTriggers( e ); 456 457 } 458 catch( final Exception e ) 459 { 460 final String message = "Exception occured executing trigger " + entry.getName(); 461 getLogger().warn( message, e ); 462 notifyFailedTriggers( e ); 463 } 464 } 465 466 473 protected synchronized TimeScheduledEntry getNextEntry() 474 { 475 TimeScheduledEntry entry = 476 (TimeScheduledEntry)getPriorityQueue().peek(); 477 478 while( !entry.isValid() ) 480 { 481 getPriorityQueue().pop(); 482 483 if( getPriorityQueue().isEmpty() ) 484 { 485 return null; 486 } 487 488 entry = (TimeScheduledEntry)getPriorityQueue().peek(); 489 } 490 491 return entry; 492 } 493 494 protected void notifyFailedTriggers( Throwable t ) 495 { 496 for( int i = 0; i < getTriggerFailureListeners().size(); i++ ) 497 { 498 TriggerFailureListener triggerFailureListener = (TriggerFailureListener)m_triggerFailureListeners.get( i ); 499 triggerFailureListener.triggerFailure( t ); 500 } 501 502 } 503 } 504 505 | Popular Tags |