JTimer.java

00001 
00026 package org.objectweb.jonas_ejb.container;
00027 
00028 import java.io.Serializable;
00029 import java.util.Date;
00030 
00031 import javax.ejb.EJBException;
00032 import javax.ejb.NoSuchObjectLocalException;
00033 import javax.ejb.Timer;
00034 import javax.ejb.TimerHandle;
00035 import javax.transaction.RollbackException;
00036 import javax.transaction.Status;
00037 import javax.transaction.Synchronization;
00038 import javax.transaction.SystemException;
00039 import javax.transaction.Transaction;
00040 import javax.transaction.TransactionManager;
00041 
00042 import org.objectweb.jonas_timer.TimerEvent;
00043 import org.objectweb.jonas_timer.TimerEventListener;
00044 import org.objectweb.jonas_timer.TimerManager;
00045 import org.objectweb.jonas_timer.TraceTimer;
00046 import org.objectweb.util.monolog.api.BasicLevel;
00047 
00054 public class JTimer implements Timer, TimerEventListener, Synchronization {
00055 
00059     private boolean oneshot;
00060 
00064     private long period;
00065 
00069     private long initial;
00070 
00074     private JTimerService timerservice;
00075 
00079     private Serializable info;
00080 
00084     private TimerManager tim = TimerManager.getInstance();
00085 
00089     private TimerEvent te1 = null;
00090 
00094     private TimerEvent te2 = null;
00095 
00099     private long starttime;
00100 
00104     private long endtime;
00105 
00109     private boolean createdInTx = false;
00110 
00114     private boolean cancelledInTx = false;
00115     
00119     private boolean cancelled = false;
00120 
00124     private TimerHandle myHandle = null;
00125 
00129     public JTimer(JTimerService timerservice, long initial, long period, Serializable info) {
00130         TraceTimer.logger.log(BasicLevel.DEBUG, "New JTimer initial = " + initial + ", period = " + period);
00131         this.timerservice = timerservice;
00132         this.info = info;
00133         this.period = period;
00134         this.initial = initial;
00135         oneshot = (period == 0);
00136         
00137     }
00138 
00142     public long getStartTime() {
00143         return starttime;
00144     }
00145 
00149     public long getInitial() {
00150         return initial;
00151     }
00152 
00156     public long getPeriod() {
00157         return period;
00158     }
00159 
00163     public JTimerService getTimerService() {
00164         return timerservice;
00165     }
00166 
00170     public void startTimer() {
00171         
00172         // If this is created inside a transaction, register this object as a synchronization.
00173         TransactionManager tm = timerservice.getTransactionManager();
00174         try {
00175                         Transaction tx = tm.getTransaction();
00176                         if (tx != null) {
00177                                 tx.registerSynchronization(this);
00178                                 createdInTx = true;
00179                         }
00180                 } catch (SystemException e) {
00181             TraceTimer.logger.log(BasicLevel.ERROR, "Cannot get Transaction");
00182                 } catch (IllegalStateException e) {
00183             TraceTimer.logger.log(BasicLevel.ERROR, "Cannot register synchronization:" + e);
00184                 } catch (RollbackException e) {
00185             TraceTimer.logger.log(BasicLevel.ERROR, "transaction already rolled back");
00186                 }
00187                 
00188                 // init time
00189         starttime = System.currentTimeMillis();
00190         endtime = starttime + initial;
00191         
00192         // Create the jonas timer
00193         te1 = tim.addTimerMs(this, initial, null, false);
00194     }
00195 
00199     public void stopTimer() {
00200         TraceTimer.logger.log(BasicLevel.DEBUG, "Stop JTimer");
00201         cancelled = true;
00202         if (te1 != null) {
00203             te1.unset();
00204             te1 = null;
00205         }
00206         if (te2 != null) {
00207             te2.unset();
00208             te2 = null;
00209         }
00210     }
00211 
00212     // ------------------------------------------------------------------------------------
00213     // The container must implement suitable equals() and hashCode() methods
00214     // ------------------------------------------------------------------------------------
00215 
00222     public boolean equals(Object obj) {
00223         if (obj instanceof JTimer) {
00224             JTimer timer2 = (JTimer) obj;
00225             if (timer2.getInitial() != getInitial()) {
00226                 TraceTimer.logger.log(BasicLevel.DEBUG, "different initial duration");
00227                 return false;
00228             }
00229             if (timer2.getPeriod() != getPeriod()) {
00230                 TraceTimer.logger.log(BasicLevel.DEBUG, "different period");
00231                 return false;
00232             }
00233             if (timer2.getTimerService() != getTimerService()) {
00234                 TraceTimer.logger.log(BasicLevel.DEBUG, "different timerservice");
00235                 return false;
00236             }
00237             TraceTimer.logger.log(BasicLevel.DEBUG, "timers are equal");
00238             return true;
00239         } else {
00240             TraceTimer.logger.log(BasicLevel.DEBUG, "not a Timer");
00241             return false;
00242         }
00243     }
00244 
00249     public int hashCode() {
00250         return (int) (getPeriod() / 1000);
00251     }
00252 
00253     // ------------------------------------------------------------------------------------
00254     // TimerEventListener implemetation
00255     // ------------------------------------------------------------------------------------
00256 
00260     public void timeoutExpired(Object arg) {
00261         TraceTimer.logger.log(BasicLevel.DEBUG, "JTimer expires");
00262         // propagate the timeout
00263         timerservice.notify(this);
00264         if (cancelled) {
00265             TraceTimer.logger.log(BasicLevel.DEBUG, "JTimer cancelled during timeout");
00266             return;
00267         }
00268         if (te2 == null) {
00269             te1 = null;
00270             if (oneshot) {
00271                 timerservice.remove(this);
00272                 cancelled = true;
00273             } else {
00274                 // start a new jonas timer (periodic)
00275                 TraceTimer.logger.log(BasicLevel.DEBUG, "Start periodic jonas timer");
00276                 endtime = System.currentTimeMillis() + period;
00277                 te2 = tim.addTimerMs(this, period, null, true);
00278             }
00279         } else {
00280             // recompute time of next expiration
00281             endtime = System.currentTimeMillis() + period;
00282         }
00283     }
00284 
00285     // ------------------------------------------------------------------------------------
00286     // Timer implemetation
00287     // ------------------------------------------------------------------------------------
00288 
00299     public void cancel() throws IllegalStateException, NoSuchObjectLocalException, EJBException {
00300         if (cancelled || cancelledInTx) {
00301             TraceTimer.logger.log(BasicLevel.ERROR, "Timer cancelled");
00302             throw new NoSuchObjectLocalException("Timer already cancelled");
00303         }
00304         TraceTimer.logger.log(BasicLevel.DEBUG, "");
00305 
00306         // If this is called inside a transaction, register this object as a synchronization.
00307         TransactionManager tm = timerservice.getTransactionManager();
00308         try {
00309                         Transaction tx = tm.getTransaction();
00310                         if (tx != null) {
00311                             // will be cancelled at commit.
00312                                 tx.registerSynchronization(this);
00313                                 cancelledInTx = true;
00314                         } else {
00315                             doCancel();
00316                         }
00317                 } catch (SystemException e) {
00318             TraceTimer.logger.log(BasicLevel.ERROR, "Cannot get Transaction");
00319                 } catch (IllegalStateException e) {
00320             TraceTimer.logger.log(BasicLevel.ERROR, "Cannot register synchronization:" + e);
00321                 } catch (RollbackException e) {
00322             TraceTimer.logger.log(BasicLevel.ERROR, "transaction already rolled back");
00323                 }
00324     }
00325     
00326     private void doCancel() {
00327         stopTimer();
00328         timerservice.remove(this);
00329     }
00330 
00343     public long getTimeRemaining() throws IllegalStateException, NoSuchObjectLocalException, EJBException {
00344         if (cancelled || cancelledInTx) {
00345             TraceTimer.logger.log(BasicLevel.ERROR, "Timer cancelled");
00346             throw new NoSuchObjectLocalException("Timer cancelled or expired");
00347         }
00348         TraceTimer.logger.log(BasicLevel.DEBUG, "");
00349         return endtime - System.currentTimeMillis();
00350     }
00351 
00364     public Date getNextTimeout() throws IllegalStateException, NoSuchObjectLocalException, EJBException {
00365         if (cancelled || cancelledInTx) {
00366             TraceTimer.logger.log(BasicLevel.ERROR, "Timer cancelled");
00367             throw new NoSuchObjectLocalException("Timer cancelled or expired");
00368         }
00369         TraceTimer.logger.log(BasicLevel.DEBUG, "");
00370         return new Date(endtime);
00371     }
00372 
00384     public Serializable getInfo() throws IllegalStateException, NoSuchObjectLocalException, EJBException {
00385         if (cancelled || cancelledInTx) {
00386             TraceTimer.logger.log(BasicLevel.ERROR, "Timer cancelled");
00387             throw new NoSuchObjectLocalException("Timer cancelled or expired");
00388         }
00389         TraceTimer.logger.log(BasicLevel.DEBUG, "");
00390         return info;
00391     }
00392 
00404     public TimerHandle getHandle() throws IllegalStateException, NoSuchObjectLocalException, EJBException {
00405         if (cancelled || cancelledInTx) {
00406             TraceTimer.logger.log(BasicLevel.ERROR, "Timer cancelled");
00407             throw new NoSuchObjectLocalException("Timer cancelled or expired");
00408         }
00409         TraceTimer.logger.log(BasicLevel.DEBUG, "");
00410         if (myHandle == null) {
00411             myHandle = new JTimerHandle(initial, period, info, timerservice.getEjbName(), 
00412                                         timerservice.getContainer(), timerservice.getPK());
00413         }
00414         return myHandle;
00415     }
00416 
00417     // ------------------------------------------------------------------------------------
00418     // Synchronization implemetation
00419     // ------------------------------------------------------------------------------------
00420 
00427     public void afterCompletion(int status) {
00428         TraceEjb.tx.log(BasicLevel.DEBUG, "");
00429 
00430         // Timers created in a transaction that is rolled back must be removed.
00431         if (createdInTx) {
00432             if (status != Status.STATUS_COMMITTED && !cancelled) {
00433                 doCancel();
00434             }
00435             createdInTx = false;
00436         }
00437         
00438         // Cancel timers only if transaction is committed
00439         if (cancelledInTx) {
00440             if (status == Status.STATUS_COMMITTED && !cancelled) {
00441                 doCancel();
00442             }
00443             cancelledInTx = false;
00444         }
00445     }
00446 
00447         /* 
00448          * @see javax.transaction.Synchronization#beforeCompletion()
00449          */
00450         public void beforeCompletion() {
00451                 // nothing to do 
00452         }
00453 
00454 }

Generated on Tue Feb 15 15:05:43 2005 for JOnAS by  doxygen 1.3.9.1