Where is BeanLockSupport?
--jason
On Thu, 2 Aug 2001, marc fleury wrote:
> User: mnf999
> Date: 01/08/02 19:59:04
>
> Added: src/main/org/jboss/ejb/plugins/lock
> SimplePessimisticEJBLock.java
> Log:
> nuff said
>
> Revision Changes Path
> 1.1
>jboss/src/main/org/jboss/ejb/plugins/lock/SimplePessimisticEJBLock.java
>
> Index: SimplePessimisticEJBLock.java
> ===================================================================
> /*
> * JBoss, the OpenSource EJB server
> *
> * Distributable under LGPL license.
> * See terms of license at gnu.org.
> */
>
> package org.jboss.ejb.plugins.lock;
>
> import java.util.LinkedList;
> import java.util.HashMap;
> import java.util.Collections;
> import java.lang.reflect.Method;
>
> import javax.transaction.Transaction;
> import javax.transaction.Status;
> import javax.transaction.Synchronization;
> import javax.transaction.TransactionManager;
> import javax.transaction.RollbackException;
> import javax.ejb.EJBObject;
>
> import org.jboss.ejb.MethodInvocation;
> import org.jboss.logging.log4j.JBossCategory;
>
> /**
> * Holds all locks for entity beans, not used for stateful. <p>
> *
> * All BeanLocks have a reference count.
> * When the reference count goes to 0, the lock is released from the
> * id -> lock mapping.
> *
> * @author <a href="[EMAIL PROTECTED]">Bill Burke</a>
> * @author <a href="[EMAIL PROTECTED]">Marc Fleury</a>
> *
> * @version $Revision: 1.1 $
> *
> * <p><b>Revisions:</b><br>
> * <p><b>2001/07/29: billb</b>
> * <ol>
> * <li>Initial revision
> * </ol>
> * <p><b>2001/08/01: marcf</b>
> * <ol>
> * <li>Added the schedule method
> * <li>The bean lock is now responsible for implementing the locking policies, it
>was before in the
> * interceptor code it is now factored out allowing for pluggable lock policies
>(optimistic for ex)
> * <li>Implemented pessimistic locking and straight spec requirement in the
>schedule method
> * would need to factor this in an abstract class for the BeanLock that extending
>policies can use
> * </ol>
> <p><b>2001/08/02: marcf</b>
> * <ol>
> * <li>Did what was said above, moved to an extension based mech with an abstract
>base class.
> * <li>This is the simple lock, won't scale well (imho) but is robust in normal
>operation
> * <li>The class must now implement schedule and the various notification calls.
>EndTransaction
> * wontSynchronize can be radically different (N-Lock)
> * </ol>
> */
> public class SimplePessimisticEJBLock extends BeanLockSupport
> {
> /**
> * Schedule(MethodInvocation)
> *
> * Schedule implements a particular policy for scheduling the threads coming in.
> * There is always the spec required "serialization" but we can add custom
>scheduling in here
> *
> * Synchronizing on lock: a failure to get scheduled must result in a wait()
>call and a
> * release of the lock. Schedulation must return with lock.
> *
> * @return boolean returns true if the thread is scheduled to go through the
>rest of the
> * interceptors. Returns false if the interceptor must try the scheduling
>again.
> */
> public boolean schedule(MethodInvocation mi)
> throws Exception
> {
> this.sync();
> boolean syncAlreadyReleased = false;
> try
> {
>
> Transaction miTx = mi.getTransaction();
> boolean trace = true;//log.isTraceEnabled();
>
> if( trace ) log.trace("Begin schedule, key="+mi.getId());
>
> // Maybe my transaction already expired?
> if (miTx != null && miTx.getStatus() == Status.STATUS_MARKED_ROLLBACK)
> {
> log.error("Saw rolled back tx="+miTx);
>
> //Wake up the next ones, this won't scale, under
>stress we will wake everyone...
> //synchronized(lock) {lock.notifyAll();}
>
> //and get out of here
> throw new RuntimeException("Transaction marked for rollback, possibly
>a timeout");
> }
>
> //Next test is independent of whether the context is locked or not, it is
>purely transactional
> // Is the instance involved with another transaction? if so we implement
>pessimistic locking
>
> // Do we have a running transaction with the context?
> if (tx != null &&
> // And are we trying to enter with another transaction?
> !tx.equals(miTx))
> {
> // That's no good, only one transaction per context
> // Let's put the thread to sleep the transaction demarcation will wake
>them up
> if( trace ) log.trace("Transactional contention on context"+id);
>
> try
> {
> if( trace ) log.trace("Begin wait on Tx="+tx);
>
> // And lock the threads on the lock corresponding to the Tx in MI
> synchronized(lock)
> {
> // We are going to wait on one of the implementation locks
>therefore
> // we need to release the sync on the BeanLock object itself
> syncAlreadyReleased = true;
>
> releaseSync();
>
> //Wait a thread coming out will wake
>you up
> //lock.wait(txTimeout);
> lock.wait(5000);
>
> }
> if( trace ) log.trace("End wait on TxLock="+tx);
> }
>
> // We need to try again
> finally {return false;}
> }
>
> // The following code should really be done in a superclass of the lock
> // it implements the default serialization from the specification
>
> // The next test is the pure serialization from the EJB specification.
> // If we are here we either did not have a tx(tx == null) or this is a
> // recursive call and the current ctx.tx == mi.tx
>
> // The transaction is good and current.
>
> //Is the context used already (with or without a transaction), is it
>locked?
> if (isMethodLocked())
> {
> // It is locked but re-entrant calls permitted (reentrant home ones
>are ok as well)
> if (!isCallAllowed(mi))
> {
> // This instance is in use and you are not permitted to reenter
> // Go to sleep and wait for the lock to be released
> if( trace ) log.trace("Thread contention on lock"+id);
>
> // Threads finishing invocation will notify() on the lock
> try
> {
>
> if( trace ) log.trace("Begin lock.wait(), id="+mi.getId());
>
> synchronized(lock)
> {
> // we're about to wait on a different object, so release
>synch on beanlock
> // Also, this notify should always be within the synch(lock)
>block
> syncAlreadyReleased = true;
> releaseSync();
>
> //lock.wait(txTimeout);
> lock.wait(5000);
> }
> }
>
> catch (InterruptedException ignored) {}
> // We need to try again
> finally
> {
> if( trace ) log.trace("End lock.wait(), id="+mi.getId()+",
>isLocked="+isMethodLocked());
> return false;
> }
> }
> else
> {
> //We are in a valid reentrant call so add a method lock
> addMethodLock();
> }
> }
> // No one is using that instance
> else
> {
> // We are now using the instance
> addMethodLock();
> }
>
> // keep track of the transaction in the lock
> tx = miTx;
> }
> finally
> {
> if (!syncAlreadyReleased) this.releaseSync();
> }
>
> //If we reach here we are properly scheduled to go through so return true
> return true;
> }
>
> //This is called if the synchronization missed registration (Sync interceptor)
> public void wontSynchronize(Transaction transaction)
> {
> tx = null;
>
> synchronized(lock) {lock.notifyAll();}
> }
>
> // This is called up synchronization to notify the end of the transaction
> public void endTransaction(Transaction transaction)
> {
> //The tx is done
> tx = null;
>
> synchronized(lock) {lock.notifyAll();}
> }
>
>
> /**
> * releaseMethodLock
> *
> * if we reach the count of zero it means the instance is free from threads
>(and reentrency)
> * we wake up the next thread in the currentLock
> */
> public void releaseMethodLock()
> {
> numMethodLocks--;
>
> //Wake up a thread to do work on the instance within the current
>transaction
> if (numMethodLocks ==0) synchronized(lock) {lock.notifyAll();}
>
> }
> }
>
>
>
>
> _______________________________________________
> Jboss-development mailing list
> [EMAIL PROTECTED]
> http://lists.sourceforge.net/lists/listinfo/jboss-development
>
_______________________________________________
Jboss-development mailing list
[EMAIL PROTECTED]
http://lists.sourceforge.net/lists/listinfo/jboss-development