[jbosscache-commits] JBoss Cache SVN: r4825 - in core/trunk/src/main/java/org/jboss/cache: interceptors and 1 other directories.

jbosscache-commits at lists.jboss.org jbosscache-commits at lists.jboss.org
Mon Dec 10 18:47:41 EST 2007


Author: mircea.markus
Date: 2007-12-10 18:47:41 -0500 (Mon, 10 Dec 2007)
New Revision: 4825

Modified:
   core/trunk/src/main/java/org/jboss/cache/InvocationContext.java
   core/trunk/src/main/java/org/jboss/cache/interceptors/MethodDispacherInterceptor.java
   core/trunk/src/main/java/org/jboss/cache/interceptors/PessimisticLockInterceptor.java
   core/trunk/src/main/java/org/jboss/cache/transaction/TransactionTable.java
Log:
code cleanups in PesimisticInterceptor

Modified: core/trunk/src/main/java/org/jboss/cache/InvocationContext.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/InvocationContext.java	2007-12-10 21:57:40 UTC (rev 4824)
+++ core/trunk/src/main/java/org/jboss/cache/InvocationContext.java	2007-12-10 23:47:41 UTC (rev 4825)
@@ -250,4 +250,18 @@
       ctx.methodCall = methodCall;
       return ctx;
    }
+
+   /**
+    * If the acq timeout if overwritten for current call, then return that one.
+    * If not overwritten return default value.
+    */
+   public long getContextLockAcquisitionTimeout(long defaultFalue) {
+      long timeout = defaultFalue;
+      if (getOptionOverrides() != null
+              && getOptionOverrides().getLockAcquisitionTimeout() >= 0)
+      {
+         timeout = getOptionOverrides().getLockAcquisitionTimeout();
+      }
+      return timeout;
+   }
 }

Modified: core/trunk/src/main/java/org/jboss/cache/interceptors/MethodDispacherInterceptor.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/interceptors/MethodDispacherInterceptor.java	2007-12-10 21:57:40 UTC (rev 4824)
+++ core/trunk/src/main/java/org/jboss/cache/interceptors/MethodDispacherInterceptor.java	2007-12-10 23:47:41 UTC (rev 4825)
@@ -32,9 +32,6 @@
  *
  * @author Mircea.Markus at jboss.com
  * @version 2.2
- *          todo - gtx is contained in InvocationContext. Check wheter passing method calls is or isn't redundant
- *          todo - check wheter is possible to group methods, e.g. MethodDeclarations.putMethods, treansationableMethods?
- *          todo - Refactor stuff in pessimistic lock interceptor
  *          todo - Refactor stuff in txint
  *          todo - revisit backward compatibility
  */
@@ -50,67 +47,7 @@
       processOverwritternMethods();
    }
 
-   /**
-    * Builds the list of methods that are overwiritten.
-    */
-   private void processOverwritternMethods()
-   {
-         checkIfOverwritten(MethodDeclarations.putDataEraseMethodLocal_id,  "handlePutDataEraseMethod",InvocationContext.class, GlobalTransaction.class, Fqn.class, Map.class, boolean.class, boolean.class);
-         checkIfOverwritten(MethodDeclarations.putDataMethodLocal_id,  "handlePutDataMethod", InvocationContext.class, GlobalTransaction.class, Fqn.class, Map.class, boolean.class);
-         checkIfOverwritten(MethodDeclarations.putForExternalReadMethodLocal_id,  "handlePutForExternalReadMethod",InvocationContext.class, GlobalTransaction.class, Fqn.class, Object.class, Object.class);
-         checkIfOverwritten(MethodDeclarations.putKeyValMethodLocal_id,  "handlePutKeyValueMethod", InvocationContext.class, GlobalTransaction.class, Fqn.class, Object.class, Object.class, boolean.class);
-         checkIfOverwritten(MethodDeclarations.moveMethodLocal_id,  "handleMoveMethod",InvocationContext.class, Fqn.class, Fqn.class);
-         checkIfOverwritten(MethodDeclarations.addChildMethodLocal_id,  "handleAddChildMethod",InvocationContext.class, GlobalTransaction.class, Fqn.class, Object.class, Node.class, boolean.class);
-         checkIfOverwritten(MethodDeclarations.getKeyValueMethodLocal_id,  "handleGetKeyValueMethod", InvocationContext.class, Fqn.class, Object.class, boolean.class);
-         checkIfOverwritten(MethodDeclarations.getNodeMethodLocal_id,  "handleGetNodeMethod", InvocationContext.class, Fqn.class);
-         checkIfOverwritten(MethodDeclarations.getChildrenNamesMethodLocal_id,  "handleGetChildrenNamesMethod",InvocationContext.class, Fqn.class);
-         checkIfOverwritten(MethodDeclarations.releaseAllLocksMethodLocal_id,  "handleReleaseAllLocksMethod",InvocationContext.class, Fqn.class);
-         checkIfOverwritten(MethodDeclarations.printMethodLocal_id,  "handlePrintMethod",InvocationContext.class, Fqn.class);
-         checkIfOverwritten(MethodDeclarations.getKeysMethodLocal_id,  "handleGetKeysMethod", InvocationContext.class, Fqn.class);
-         checkIfOverwritten(MethodDeclarations.getDataMapMethodLocal_id,  "handleGetDataMapMethod", InvocationContext.class, Fqn.class);
-         checkIfOverwritten(MethodDeclarations.rollbackMethod_id,  "handleRollbackMethod", InvocationContext.class, GlobalTransaction.class);
-         checkIfOverwritten(MethodDeclarations.removeNodeMethodLocal_id,  "handleRemoveNodeMethod", InvocationContext.class, GlobalTransaction.class, Fqn.class, boolean.class);
-         checkIfOverwritten(MethodDeclarations.removeKeyMethodLocal_id,  "handleRemoveKeyMethod",InvocationContext.class, GlobalTransaction.class, Fqn.class, Object.class, boolean.class);
-         checkIfOverwritten(MethodDeclarations.removeDataMethodLocal_id,  "handleRemoveDataMethod", InvocationContext.class, GlobalTransaction.class, Fqn.class, boolean.class);
-         checkIfOverwritten(MethodDeclarations.commitMethod_id,  "handleCommitMethod",InvocationContext.class, GlobalTransaction.class);
-         checkIfOverwritten(MethodDeclarations.optimisticPrepareMethod_id,  "handleOptimisticPrepareMethod", InvocationContext.class, GlobalTransaction.class, List.class, Map.class, Address.class, boolean.class);
-         checkIfOverwritten(MethodDeclarations.prepareMethod_id,  "handlePrepareMethod", InvocationContext.class, GlobalTransaction.class, List.class, Address.class, boolean.class);
-         checkIfOverwritten(MethodDeclarations.evictNodeMethodLocal_id,  "handleEvictMethod", InvocationContext.class, Fqn.class);
-         checkIfOverwritten(MethodDeclarations.evictVersionedNodeMethodLocal_id,  "handleEvictVersionedNodeMethod", InvocationContext.class, Fqn.class, DataVersion.class);
-         checkIfOverwritten(MethodDeclarations.existsMethod_id,  "handleExistsMethod", InvocationContext.class, Fqn.class);
-         checkIfOverwritten(MethodDeclarations.putDataEraseVersionedMethodLocal_id,  "handlePutDataEraseVersionedMethod",InvocationContext.class, GlobalTransaction.class, Fqn.class, Map.class, boolean.class, boolean.class, DataVersion.class);
-         checkIfOverwritten(MethodDeclarations.putDataVersionedMethodLocal_id,  "handlePutDataVersionedMethod", InvocationContext.class, GlobalTransaction.class, Fqn.class, Map.class, Boolean.class, DataVersion.class);
-         checkIfOverwritten(MethodDeclarations.putKeyValVersionedMethodLocal_id,  "handlePutKeyValueVersionedMethod", InvocationContext.class, GlobalTransaction.class, Fqn.class, Object.class, Object.class, boolean.class, DataVersion.class);
-         checkIfOverwritten(MethodDeclarations.putForExternalReadVersionedMethodLocal_id,  "handlePutForExternalReadVersionedMethod", InvocationContext.class, GlobalTransaction.class, Fqn.class, Object.class, Object.class, DataVersion.class);
-         checkIfOverwritten(MethodDeclarations.dataGravitationCleanupMethod_id,  "handleDataGravitationCleanupMethod", InvocationContext.class, GlobalTransaction.class, Fqn.class, Fqn.class);
-         checkIfOverwritten(MethodDeclarations.removeNodeVersionedMethodLocal_id,  "handleRemoveNodeVersionedMethod", InvocationContext.class, GlobalTransaction.class, Fqn.class, boolean.class, DataVersion.class);
-         checkIfOverwritten(MethodDeclarations.removeKeyVersionedMethodLocal_id,  "handleRemoveKeyVersionedMethod",InvocationContext.class, GlobalTransaction.class, Fqn.class, Object.class, boolean.class, DataVersion.class);
-         checkIfOverwritten(MethodDeclarations.removeDataVersionedMethodLocal_id,  "handleRemoveDataVersionedMethod", InvocationContext.class, GlobalTransaction.class, Fqn.class, boolean.class, DataVersion.class);
-         checkIfOverwritten(MethodDeclarations.blockChannelMethodLocal_id,  "handleBlockChannelMethod",InvocationContext.class);
-         checkIfOverwritten(MethodDeclarations.unblockChannelMethodLocal_id,  "handleUnblockChannelMethod", InvocationContext.class);
-         checkIfOverwritten(MethodDeclarations.lockMethodLocal_id,  "handleLockMethod", InvocationContext.class, Fqn.class, NodeLock.LockType.class, boolean.class);
-
-   }
-
-   private void checkIfOverwritten(int putDataEraseMethodLocal_id, String methodName, Class... args)
-   {
-      Class currentClass = getClass();
-      //if this is a > 1 inheritace deepth and the method was overwritten in the parent. We also have to look into parents
-      while (currentClass != MethodDispacherInterceptor.class)
-      {
-         try
-         {
-            currentClass.getDeclaredMethod(methodName, args);
-            this.overwrittenMethods.add(putDataEraseMethodLocal_id);
-         } catch (NoSuchMethodException e)
-         {
-            //ignore
-         }
-         currentClass = (Class) currentClass.getGenericSuperclass();
-      }
-   }
-
-   /**
+    /**
     * Acts like a 'switch case' that delegates the call to the appropriate method.
     */
    public Object invoke(InvocationContext ctx) throws Throwable
@@ -240,7 +177,7 @@
       return result;
    }
 
-   /**
+    /**
     * Handles {@link org.jboss.cache.CacheImpl#_lock(org.jboss.cache.Fqn, org.jboss.cache.lock.NodeLock.LockType, boolean)}
     */
    protected Object handleLockMethod(InvocationContext ctx, Fqn fqn, NodeLock.LockType lockType, boolean recursive) throws Throwable
@@ -248,7 +185,7 @@
       return defaultHandlersBehavior();
    }
 
-   /**
+    /**
     * Handles {@link org.jboss.cache.CacheImpl#_unblock()}
     */
    protected Object handleUnblockChannelMethod(InvocationContext ctx) throws Throwable
@@ -256,7 +193,7 @@
       return defaultHandlersBehavior();
    }
 
-   /**
+    /**
     * Handles {@link org.jboss.cache.CacheImpl#_block()}
     */
    protected Object handleBlockChannelMethod(InvocationContext ctx) throws Throwable
@@ -264,7 +201,7 @@
       return defaultHandlersBehavior();
    }
 
-   /**
+    /**
     * Handles {@link org.jboss.cache.CacheImpl#_removeData(org.jboss.cache.transaction.GlobalTransaction, org.jboss.cache.Fqn, boolean, org.jboss.cache.optimistic.DataVersion)}
     */
    protected Object handleRemoveDataVersionedMethod(InvocationContext ctx, GlobalTransaction gtx, Fqn fqn, boolean createUndoOps, DataVersion dv) throws Throwable
@@ -272,7 +209,7 @@
       return defaultHandlersBehavior();
    }
 
-   /**
+    /**
     * Handles {@link org.jboss.cache.CacheImpl#_remove(org.jboss.cache.transaction.GlobalTransaction, org.jboss.cache.Fqn, Object, boolean, org.jboss.cache.optimistic.DataVersion)}
     */
    protected Object handleRemoveKeyVersionedMethod(InvocationContext ctx, GlobalTransaction gtx, Fqn fqn, Object key, boolean createUndoOps, DataVersion dv) throws Throwable
@@ -280,7 +217,7 @@
       return defaultHandlersBehavior();
    }
 
-   /**
+    /**
     * Handles {@link org.jboss.cache.CacheImpl#_remove(org.jboss.cache.transaction.GlobalTransaction, org.jboss.cache.Fqn, boolean, org.jboss.cache.optimistic.DataVersion)}
     */
    protected Object handleRemoveNodeVersionedMethod(InvocationContext ctx, GlobalTransaction gtx, Fqn fqn, boolean createUndoOps, DataVersion dv) throws Throwable
@@ -288,7 +225,7 @@
       return defaultHandlersBehavior();
    }
 
-   /**
+    /**
     * Handles {@link org.jboss.cache.CacheImpl#_dataGravitationCleanup(org.jboss.cache.transaction.GlobalTransaction, org.jboss.cache.Fqn, org.jboss.cache.Fqn)}
     */
    protected Object handleDataGravitationCleanupMethod(InvocationContext ctx, GlobalTransaction globalTransaction, Fqn primary, Fqn backup) throws Throwable
@@ -296,7 +233,7 @@
       return defaultHandlersBehavior();
    }
 
-   /**
+    /**
     * Handles {@link org.jboss.cache.CacheImpl#_putForExternalRead(org.jboss.cache.transaction.GlobalTransaction, org.jboss.cache.Fqn, Object, Object, org.jboss.cache.optimistic.DataVersion)}
     */
    protected Object handlePutForExternalReadVersionedMethod(InvocationContext ctx, GlobalTransaction gtx, Fqn fqn, Object key, Object value, DataVersion dv) throws Throwable
@@ -304,7 +241,7 @@
       return defaultHandlersBehavior();
    }
 
-   /**
+    /**
     * Handles {@link org.jboss.cache.CacheImpl#_put(org.jboss.cache.transaction.GlobalTransaction, org.jboss.cache.Fqn, Object, Object, boolean, org.jboss.cache.optimistic.DataVersion)}
     */
    protected Object handlePutKeyValueVersionedMethod(InvocationContext ctx, GlobalTransaction gtx, Fqn fqn, Object key, Object value, boolean createUndoOps, DataVersion dv) throws Throwable
@@ -312,7 +249,7 @@
       return defaultHandlersBehavior();
    }
 
-   /**
+    /**
     * Handles {@link org.jboss.cache.CacheImpl#_put(org.jboss.cache.transaction.GlobalTransaction, org.jboss.cache.Fqn, java.util.Map, boolean, org.jboss.cache.optimistic.DataVersion)}
     */
    protected Object handlePutDataVersionedMethod(InvocationContext ctx, GlobalTransaction globalTransaction, Fqn fqn, Map map, Boolean createUndoOps, DataVersion dataVersion) throws Throwable
@@ -320,7 +257,7 @@
       return defaultHandlersBehavior();
    }
 
-   /**
+    /**
     * Handles {@link org.jboss.cache.CacheImpl#_put(org.jboss.cache.transaction.GlobalTransaction, org.jboss.cache.Fqn, java.util.Map, boolean, boolean, org.jboss.cache.optimistic.DataVersion)}
     */
    protected Object handlePutDataEraseVersionedMethod(InvocationContext ctx, GlobalTransaction gtx, Fqn fqn, Map data, boolean createUndoOps, boolean eraseContent, DataVersion dv) throws Throwable
@@ -328,7 +265,7 @@
       return defaultHandlersBehavior();
    }
 
-   /**
+    /**
     * Handles {@link org.jboss.cache.CacheImpl#exists(String)}
     */
    protected Object handleExistsMethod(InvocationContext ctx, Fqn fqn) throws Throwable
@@ -336,22 +273,22 @@
       return defaultHandlersBehavior();
    }
 
-   /**
+    /**
     * used for logging various steps. if null is returned than nothing is logged.
     */
    protected abstract Log getLog();
 
-   /**
+    /**
     * Each interceptor should extend this if it does not need any processing for current call.
     * An sample usage would be: this interceptor is only interested if thre is one transaction going on. If so all
-    * handleXYZ would know that we have a transaction going and would not check its state. 
+    * handleXYZ would know that we have a transaction going and would not check its state.
     */
    protected boolean skipMethodCall(InvocationContext ctx)
    {
       return false;
    }
 
-   /**
+    /**
     * Handles {@link org.jboss.cache.CacheImpl#_evict(org.jboss.cache.Fqn, org.jboss.cache.optimistic.DataVersion)}
     */
    protected Object handleEvictVersionedNodeMethod(InvocationContext ctx, Fqn fqn, DataVersion dataVersion) throws Throwable
@@ -359,7 +296,7 @@
       return defaultHandlersBehavior();
    }
 
-   /**
+    /**
     * Handles {@link org.jboss.cache.CacheImpl#evict(org.jboss.cache.Fqn)}
     */
    protected Object handleEvictMethod(InvocationContext ctx, Fqn fqn) throws Throwable
@@ -367,7 +304,7 @@
       return defaultHandlersBehavior();
    }
 
-   /**
+    /**
     * Handles {@link org.jboss.cache.CacheImpl#prepare(org.jboss.cache.transaction.GlobalTransaction, java.util.List, org.jgroups.Address, boolean)}
     */
    protected Object handlePrepareMethod(InvocationContext ctx, GlobalTransaction gtx, List modification, Address coordinator, boolean onePhaseCommit) throws Throwable
@@ -375,7 +312,7 @@
       return defaultHandlersBehavior();
    }
 
-   /**
+    /**
     * Handles {@link org.jboss.cache.CacheImpl#optimisticPrepare(org.jboss.cache.transaction.GlobalTransaction, java.util.List, java.util.Map, org.jgroups.Address, boolean)}
     */
    protected Object handleOptimisticPrepareMethod(InvocationContext ctx, GlobalTransaction gtx, List modifications, Map data, Address address, boolean onePhaseCommit) throws Throwable
@@ -383,7 +320,7 @@
       return defaultHandlersBehavior();
    }
 
-   /**
+    /**
     * Handles {@link org.jboss.cache.CacheImpl#commit(org.jboss.cache.transaction.GlobalTransaction)}
     */
    protected Object handleCommitMethod(InvocationContext ctx, GlobalTransaction globalTransaction) throws Throwable
@@ -391,7 +328,7 @@
       return defaultHandlersBehavior();
    }
 
-   /**
+    /**
     * Handles {@link org.jboss.cache.CacheImpl#_removeData(org.jboss.cache.transaction.GlobalTransaction, Fqn, boolean)}
     */
    protected Object handleRemoveDataMethod(InvocationContext ctx, GlobalTransaction tx, Fqn fqn, boolean createUndoOps) throws Throwable
@@ -399,7 +336,7 @@
       return defaultHandlersBehavior();
    }
 
-   /**
+    /**
     * Handles {@link org.jboss.cache.CacheImpl#_remove(org.jboss.cache.transaction.GlobalTransaction, String, Object, boolean)}
     */
    protected Object handleRemoveKeyMethod(InvocationContext ctx, GlobalTransaction tx, Fqn fqn, Object key, boolean createUndoOps) throws Throwable
@@ -407,8 +344,7 @@
       return defaultHandlersBehavior();
    }
 
-
-   /**
+    /**
     * Handles {@link org.jboss.cache.CacheImpl#_remove(org.jboss.cache.transaction.GlobalTransaction, String, boolean)}
     */
    protected Object handleRemoveNodeMethod(InvocationContext ctx, GlobalTransaction tx, Fqn fqn, boolean createUndoOps) throws Throwable
@@ -416,7 +352,8 @@
       return defaultHandlersBehavior();
    }
 
-   /**
+
+    /**
     * Handles {@link org.jboss.cache.CacheImpl#rollback(org.jboss.cache.transaction.GlobalTransaction)}
     */
    protected Object handleRollbackMethod(InvocationContext ctx, GlobalTransaction globalTransaction) throws Throwable
@@ -424,7 +361,7 @@
       return defaultHandlersBehavior();
    }
 
-   /**
+    /**
     * Handles {@link org.jboss.cache.CacheImpl#_getData(org.jboss.cache.Fqn)}
     */
    protected Object handleGetDataMapMethod(InvocationContext ctx, Fqn fqn) throws Throwable
@@ -432,7 +369,7 @@
       return defaultHandlersBehavior();
    }
 
-   /**
+    /**
     * Handles {@link org.jboss.cache.CacheImpl#getKeys(Fqn)}
     */
    protected Object handleGetKeysMethod(InvocationContext ctx, Fqn fqn) throws Throwable
@@ -440,7 +377,7 @@
       return defaultHandlersBehavior();
    }
 
-   /**
+    /**
     * Handles {@link org.jboss.cache.CacheImpl#_print(org.jboss.cache.Fqn)}
     */
    protected Object handlePrintMethod(InvocationContext ctx, Fqn fqn) throws Throwable
@@ -448,7 +385,7 @@
       return defaultHandlersBehavior();
    }
 
-   /**
+    /**
     * Handles {@link org.jboss.cache.CacheImpl#_releaseAllLocks(org.jboss.cache.Fqn)}
     */
    protected Object handleReleaseAllLocksMethod(InvocationContext ctx, Fqn fqn) throws Throwable
@@ -456,7 +393,7 @@
       return defaultHandlersBehavior();
    }
 
-   /**
+    /**
     * Handles {@link org.jboss.cache.CacheImpl#_getChildrenNames(org.jboss.cache.Fqn)}
     */
    protected Object handleGetChildrenNamesMethod(InvocationContext ctx, Fqn fqn) throws Throwable
@@ -464,7 +401,7 @@
       return defaultHandlersBehavior();
    }
 
-   /**
+    /**
     * Handles {@link org.jboss.cache.CacheImpl#_get(org.jboss.cache.Fqn)}
     */
    protected Object handleGetNodeMethod(InvocationContext ctx, Fqn fqn) throws Throwable
@@ -472,7 +409,7 @@
       return defaultHandlersBehavior();
    }
 
-   /**
+    /**
     * Handles {@link org.jboss.cache.CacheImpl#_get(org.jboss.cache.Fqn, Object, boolean)}
     */
    protected Object handleGetKeyValueMethod(InvocationContext ctx, Fqn fqn, Object key, boolean sendNodeEvent) throws Throwable
@@ -480,8 +417,7 @@
       return defaultHandlersBehavior();
    }
 
-
-   /**
+    /**
     * Handles {@link org.jboss.cache.CacheImpl#_addChild(org.jboss.cache.transaction.GlobalTransaction, org.jboss.cache.Fqn, Object, org.jboss.cache.Node, boolean)}
     */
    protected Object handleAddChildMethod(InvocationContext ctx, GlobalTransaction tx, Fqn parentFqn, Object childName, Node cn, boolean createUndoOps) throws Throwable
@@ -489,7 +425,8 @@
       return defaultHandlersBehavior();
    }
 
-   /**
+
+    /**
     * Handles {@link org.jboss.cache.CacheImpl#_move(org.jboss.cache.Fqn, org.jboss.cache.Fqn)}
     */
    protected Object handleMoveMethod(InvocationContext ctx, Fqn from, Fqn to) throws Throwable
@@ -497,7 +434,7 @@
       return defaultHandlersBehavior();
    }
 
-   /**
+    /**
     * Handles {@link org.jboss.cache.CacheImpl#_put(org.jboss.cache.transaction.GlobalTransaction, String, Object, Object, boolean)}
     */
    protected Object handlePutKeyValueMethod(InvocationContext ctx, GlobalTransaction gtx, Fqn fqn, Object key, Object value, boolean createUndoOps) throws Throwable
@@ -505,7 +442,7 @@
       return defaultHandlersBehavior();
    }
 
-   /**
+    /**
     * Handles {@link org.jboss.cache.CacheImpl#_putForExternalRead(org.jboss.cache.transaction.GlobalTransaction, org.jboss.cache.Fqn, Object, Object)}
     */
    protected Object handlePutForExternalReadMethod(InvocationContext ctx, GlobalTransaction tx, Fqn fqn, Object key, Object value) throws Throwable
@@ -513,7 +450,7 @@
       return defaultHandlersBehavior();
    }
 
-   /**
+    /**
     * Handles {@link org.jboss.cache.CacheImpl#_put(org.jboss.cache.transaction.GlobalTransaction, String, java.util.Map, boolean)}
     */
    protected Object handlePutDataMethod(InvocationContext ctx, GlobalTransaction tx, Fqn fqn, Map data, boolean createUndoOps) throws Throwable
@@ -521,7 +458,7 @@
       return defaultHandlersBehavior();
    }
 
-   /**
+    /**
     * Handles {@link org.jboss.cache.CacheImpl#_put(org.jboss.cache.transaction.GlobalTransaction, org.jboss.cache.Fqn, java.util.Map, boolean, boolean)}
     */
    protected Object handlePutDataEraseMethod(InvocationContext ctx, GlobalTransaction gt, Fqn fqn, Map newData, boolean createUndoOps, boolean eraseContents) throws Throwable
@@ -529,7 +466,7 @@
       return defaultHandlersBehavior();
    }
 
-   /**
+    /**
     * Handlers defined here should not be called directlly. There are two scenarios in which a handler might be called:
     * 1 - DerivedInterceptor.super - pointless call
     * 2 - if the logic that determines that an handler is overwritten fails. Throwing an exception by default is for
@@ -538,5 +475,65 @@
    private Object defaultHandlersBehavior()
    {
       throw new IllegalStateException("this is either called from a derived class or nt overwritten and accidentally called. Either way, is not correct.");
-   }   
+   }
+
+    /**
+     * Builds the list of methods that are overwiritten.
+     */
+    private void processOverwritternMethods()
+    {
+        checkIfOverwritten(MethodDeclarations.putDataEraseMethodLocal_id,  "handlePutDataEraseMethod",InvocationContext.class, GlobalTransaction.class, Fqn.class, Map.class, boolean.class, boolean.class);
+        checkIfOverwritten(MethodDeclarations.putDataMethodLocal_id,  "handlePutDataMethod", InvocationContext.class, GlobalTransaction.class, Fqn.class, Map.class, boolean.class);
+        checkIfOverwritten(MethodDeclarations.putForExternalReadMethodLocal_id,  "handlePutForExternalReadMethod",InvocationContext.class, GlobalTransaction.class, Fqn.class, Object.class, Object.class);
+        checkIfOverwritten(MethodDeclarations.putKeyValMethodLocal_id,  "handlePutKeyValueMethod", InvocationContext.class, GlobalTransaction.class, Fqn.class, Object.class, Object.class, boolean.class);
+        checkIfOverwritten(MethodDeclarations.moveMethodLocal_id,  "handleMoveMethod",InvocationContext.class, Fqn.class, Fqn.class);
+        checkIfOverwritten(MethodDeclarations.addChildMethodLocal_id,  "handleAddChildMethod",InvocationContext.class, GlobalTransaction.class, Fqn.class, Object.class, Node.class, boolean.class);
+        checkIfOverwritten(MethodDeclarations.getKeyValueMethodLocal_id,  "handleGetKeyValueMethod", InvocationContext.class, Fqn.class, Object.class, boolean.class);
+        checkIfOverwritten(MethodDeclarations.getNodeMethodLocal_id,  "handleGetNodeMethod", InvocationContext.class, Fqn.class);
+        checkIfOverwritten(MethodDeclarations.getChildrenNamesMethodLocal_id,  "handleGetChildrenNamesMethod",InvocationContext.class, Fqn.class);
+        checkIfOverwritten(MethodDeclarations.releaseAllLocksMethodLocal_id,  "handleReleaseAllLocksMethod",InvocationContext.class, Fqn.class);
+        checkIfOverwritten(MethodDeclarations.printMethodLocal_id,  "handlePrintMethod",InvocationContext.class, Fqn.class);
+        checkIfOverwritten(MethodDeclarations.getKeysMethodLocal_id,  "handleGetKeysMethod", InvocationContext.class, Fqn.class);
+        checkIfOverwritten(MethodDeclarations.getDataMapMethodLocal_id,  "handleGetDataMapMethod", InvocationContext.class, Fqn.class);
+        checkIfOverwritten(MethodDeclarations.rollbackMethod_id,  "handleRollbackMethod", InvocationContext.class, GlobalTransaction.class);
+        checkIfOverwritten(MethodDeclarations.removeNodeMethodLocal_id,  "handleRemoveNodeMethod", InvocationContext.class, GlobalTransaction.class, Fqn.class, boolean.class);
+        checkIfOverwritten(MethodDeclarations.removeKeyMethodLocal_id,  "handleRemoveKeyMethod",InvocationContext.class, GlobalTransaction.class, Fqn.class, Object.class, boolean.class);
+        checkIfOverwritten(MethodDeclarations.removeDataMethodLocal_id,  "handleRemoveDataMethod", InvocationContext.class, GlobalTransaction.class, Fqn.class, boolean.class);
+        checkIfOverwritten(MethodDeclarations.commitMethod_id,  "handleCommitMethod",InvocationContext.class, GlobalTransaction.class);
+        checkIfOverwritten(MethodDeclarations.optimisticPrepareMethod_id,  "handleOptimisticPrepareMethod", InvocationContext.class, GlobalTransaction.class, List.class, Map.class, Address.class, boolean.class);
+        checkIfOverwritten(MethodDeclarations.prepareMethod_id,  "handlePrepareMethod", InvocationContext.class, GlobalTransaction.class, List.class, Address.class, boolean.class);
+        checkIfOverwritten(MethodDeclarations.evictNodeMethodLocal_id,  "handleEvictMethod", InvocationContext.class, Fqn.class);
+        checkIfOverwritten(MethodDeclarations.evictVersionedNodeMethodLocal_id,  "handleEvictVersionedNodeMethod", InvocationContext.class, Fqn.class, DataVersion.class);
+        checkIfOverwritten(MethodDeclarations.existsMethod_id,  "handleExistsMethod", InvocationContext.class, Fqn.class);
+        checkIfOverwritten(MethodDeclarations.putDataEraseVersionedMethodLocal_id,  "handlePutDataEraseVersionedMethod",InvocationContext.class, GlobalTransaction.class, Fqn.class, Map.class, boolean.class, boolean.class, DataVersion.class);
+        checkIfOverwritten(MethodDeclarations.putDataVersionedMethodLocal_id,  "handlePutDataVersionedMethod", InvocationContext.class, GlobalTransaction.class, Fqn.class, Map.class, Boolean.class, DataVersion.class);
+        checkIfOverwritten(MethodDeclarations.putKeyValVersionedMethodLocal_id,  "handlePutKeyValueVersionedMethod", InvocationContext.class, GlobalTransaction.class, Fqn.class, Object.class, Object.class, boolean.class, DataVersion.class);
+        checkIfOverwritten(MethodDeclarations.putForExternalReadVersionedMethodLocal_id,  "handlePutForExternalReadVersionedMethod", InvocationContext.class, GlobalTransaction.class, Fqn.class, Object.class, Object.class, DataVersion.class);
+        checkIfOverwritten(MethodDeclarations.dataGravitationCleanupMethod_id,  "handleDataGravitationCleanupMethod", InvocationContext.class, GlobalTransaction.class, Fqn.class, Fqn.class);
+        checkIfOverwritten(MethodDeclarations.removeNodeVersionedMethodLocal_id,  "handleRemoveNodeVersionedMethod", InvocationContext.class, GlobalTransaction.class, Fqn.class, boolean.class, DataVersion.class);
+        checkIfOverwritten(MethodDeclarations.removeKeyVersionedMethodLocal_id,  "handleRemoveKeyVersionedMethod",InvocationContext.class, GlobalTransaction.class, Fqn.class, Object.class, boolean.class, DataVersion.class);
+        checkIfOverwritten(MethodDeclarations.removeDataVersionedMethodLocal_id,  "handleRemoveDataVersionedMethod", InvocationContext.class, GlobalTransaction.class, Fqn.class, boolean.class, DataVersion.class);
+        checkIfOverwritten(MethodDeclarations.blockChannelMethodLocal_id,  "handleBlockChannelMethod",InvocationContext.class);
+        checkIfOverwritten(MethodDeclarations.unblockChannelMethodLocal_id,  "handleUnblockChannelMethod", InvocationContext.class);
+        checkIfOverwritten(MethodDeclarations.lockMethodLocal_id,  "handleLockMethod", InvocationContext.class, Fqn.class, NodeLock.LockType.class, boolean.class);
+
+    }
+
+    private void checkIfOverwritten(int putDataEraseMethodLocal_id, String methodName, Class... args)
+    {
+        Class currentClass = getClass();
+        //if this is a > 1 inheritace deepth and the method was overwritten in the parent. We also have to look into parents
+        while (currentClass != MethodDispacherInterceptor.class)
+        {
+            try
+            {
+                currentClass.getDeclaredMethod(methodName, args);
+                this.overwrittenMethods.add(putDataEraseMethodLocal_id);
+            } catch (NoSuchMethodException e)
+            {
+                //ignore
+            }
+            currentClass = (Class) currentClass.getGenericSuperclass();
+        }
+    }
 }

Modified: core/trunk/src/main/java/org/jboss/cache/interceptors/PessimisticLockInterceptor.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/interceptors/PessimisticLockInterceptor.java	2007-12-10 21:57:40 UTC (rev 4824)
+++ core/trunk/src/main/java/org/jboss/cache/interceptors/PessimisticLockInterceptor.java	2007-12-10 23:47:41 UTC (rev 4825)
@@ -19,6 +19,14 @@
 
 import java.util.*;
 
+/*
+* todo refactorings ideas
+*      - thre are many places in code that handles that coputes the lock owners: either GTX or Thread.local. The
+*      lockOwner can be abstractised  as a LockOwner that can be extended by CurrentThreadLock owner and
+       GlobalTransaction owner. This would make the code nicer.
+*/
+
+
 /**
  * An interceptor that handles locking. When a TX is associated, we register
  * for TX completion and unlock the locks acquired within the scope of the TX.
@@ -27,7 +35,6 @@
  *
  * @author Bela Ban
  * @version $Id$
- * //todo = try to see how acquireLuckWithTimeout works inline
  */
 public class PessimisticLockInterceptor extends MethodDispacherInterceptor
 {
@@ -38,9 +45,7 @@
     */
    private Map<Thread, List<NodeLock>> lock_table;
    private long lock_acquisition_timeout;
-   private LockManager lockManager = new LockManager();
 
-
    public void setCache(CacheSPI cache)
    {
       super.setCache(cache);
@@ -76,17 +81,31 @@
       if (ctx.getOptionOverrides() != null && ctx.getOptionOverrides().isSuppressLocking())
       {
          log.trace("Creating nodes if necessary");
-         createNodes(fqn, ctx.getGlobalTransaction());
+         int treeNodeSize = fqn.size();
+         NodeSPI n = cache.getRoot();
+         for (int i = 0; i < treeNodeSize; i++)
+         {
+            Object childName = fqn.get(i);
+            Fqn childFqn = new Fqn(childName);
+            NodeSPI child_node = n.getChildDirect(childFqn);
+            if (child_node == null) child_node = n.addChildDirect(childFqn);
+            manageReverseRemove(ctx.getGlobalTransaction(), child_node, true);
+            n = child_node;
+         }
       } else
       {
-         acquireLocksWithTimeout(ctx, fqn, NodeLock.LockType.WRITE, false, true, false, false, false, false);
+         acquireLocksWithTimeout(ctx, fqn, NodeLock.LockType.READ, true, false, false, true);
       }
       return nextInterceptor(ctx);
    }
 
    protected Object handleLockMethod(InvocationContext ctx, Fqn fqn, NodeLock.LockType lockType, boolean recursive) throws Throwable
    {
-      acquireLocksWithTimeout(ctx, fqn, lockType, recursive, false, false, false, false, false);
+      acquireLocksWithTimeout(ctx, fqn, lockType, false, false, false, false);
+      if (recursive)
+      {
+         acquireLocksOnChildren(cache.peek(fqn, false), lockType, ctx);
+      }
       return null;
    }
 
@@ -95,7 +114,7 @@
       // commit propagated up from the tx interceptor
       commit(ctx.getGlobalTransaction());
       Object retVal = nextInterceptor(ctx);
-      cleanup(ctx.getGlobalTransaction());
+      tx_table.cleanup(ctx.getGlobalTransaction());
       return retVal;
    }
 
@@ -112,44 +131,83 @@
          log.trace("bypassed locking as method commit() doesn't require locking");
       }
       Object retVal = nextInterceptor(ctx);
-      cleanup(globalTransaction);
+      tx_table.cleanup(globalTransaction);
       return retVal;
    }
 
    protected Object handleRollbackMethod(InvocationContext ctx, GlobalTransaction globalTransaction) throws Throwable
    {
-      rollback(globalTransaction);
+      TransactionEntry entry = tx_table.get(globalTransaction);
       if (log.isTraceEnabled())
       {
+         log.trace("called to rollback cache with GlobalTransaction=" + globalTransaction);
+      }
+
+      if (entry == null)
+      {
+         log.error("entry for transaction " + globalTransaction + " not found (transaction has possibly already been rolled back)");
+      }
+      else
+      {
+         Iterator removedNodes = entry.getRemovedNodes().iterator();
+         CacheImpl cacheImpl = (CacheImpl) cache;
+         while (removedNodes.hasNext())
+         {
+            Fqn f = (Fqn) removedNodes.next();
+            cacheImpl.realRemove(f, false);
+
+         }
+         // 1. Revert the modifications by running the undo-op list in reverse. This *cannot* throw any exceptions !
+         entry.undoOperations(cache);
+      }
+      if (log.isTraceEnabled())
+      {
          log.trace("bypassed locking as method rollback() doesn't require locking");
       }
       Object retVal = nextInterceptor(ctx);
-      cleanup(globalTransaction);
+      tx_table.cleanup(globalTransaction);
       return retVal;
    }
 
    protected Object handleMoveMethod(InvocationContext ctx, Fqn from, Fqn to) throws Throwable
    {
-      long timeout = getLockAcquisitionTimeout(ctx);
+      long timeout = ctx.getContextLockAcquisitionTimeout(lock_acquisition_timeout);
       // this call will ensure the node gets a WL and it's current parent gets RL.
       if (log.isTraceEnabled()) log.trace("Attempting to get WL on node to be moved [" + from + "]");
-      lock(ctx, from, NodeLock.LockType.WRITE, true, false, timeout, true, false, false);
-      //now for an RL for the new parent.
-      if (log.isTraceEnabled()) log.trace("Attempting to get RL on new parent [" + to + "]");
-      lock(ctx, to, NodeLock.LockType.READ, true, false, timeout, false, false, false);
+      if (from != null && ! (configuration.getIsolationLevel() == IsolationLevel.NONE))
+      {
+         lock(ctx, from, NodeLock.LockType.WRITE, false, timeout, true, false);
+         if (ctx.getGlobalTransaction() != null)
+         {
+            cache.getTransactionTable().get(ctx.getGlobalTransaction()).addRemovedNode(from);
+         }
+         acquireLocksOnChildren(cache.peek(from, true), NodeLock.LockType.WRITE, ctx);
+      }
+      if (to != null && !(configuration.getIsolationLevel() == IsolationLevel.NONE))
+      {
+         //now for an RL for the new parent.
+         if (log.isTraceEnabled()) log.trace("Attempting to get RL on new parent [" + to + "]");
+         lock(ctx, to, NodeLock.LockType.READ, false, timeout, false, false);
+         acquireLocksOnChildren(cache.peek(to, true), NodeLock.LockType.READ, ctx);
+      }
       Object retValue = nextInterceptor(ctx);
       // do a REAL remove here.
       NodeSPI n = cache.peek(from, true);
       if (n != null)
       {
-         lockManager.getLock(n).releaseAll(Thread.currentThread());
+          n.getLock().releaseAll(Thread.currentThread());
       }
       return retValue;
    }
 
    protected Object handleRemoveNodeMethod(InvocationContext ctx, GlobalTransaction tx, Fqn fqn, boolean createUndoOps) throws Throwable
    {
-      boolean created = acquireLocksWithTimeout(ctx, fqn, NodeLock.LockType.WRITE, true, true, false, true, false, false);
+      boolean created = acquireLocksWithTimeout(ctx, fqn, NodeLock.LockType.WRITE, true, false, true, false);
+      if (ctx.getGlobalTransaction() != null)
+      {
+         cache.getTransactionTable().get(ctx.getGlobalTransaction()).addRemovedNode(fqn);
+      }
+      acquireLocksOnChildren(cache.getRoot().getChildDirect(fqn), NodeLock.LockType.WRITE, ctx);
       Object retVal = nextInterceptor(ctx);
       if (ctx.getGlobalTransaction() == null)
       {
@@ -157,7 +215,7 @@
          NodeSPI n = cache.peek(fqn, true);
          if (n != null)
          {
-            lockManager.getLock(n).releaseAll(Thread.currentThread());
+             n.getLock().releaseAll(Thread.currentThread());
          }
       }
       // if this is a delete op and we had to create the node, return a FALSE as nothing *really* was deleted!
@@ -166,7 +224,7 @@
 
    protected Object handlePutForExternalReadMethod(InvocationContext ctx, GlobalTransaction tx, Fqn fqn, Object key, Object value) throws Throwable
    {
-      acquireLocksWithTimeout(ctx, fqn, NodeLock.LockType.WRITE, false, true, true, false, false, false);
+      acquireLocksWithTimeout(ctx, fqn, NodeLock.LockType.READ, true, true, false, true);
       return nextInterceptor(ctx);
    }
 
@@ -177,104 +235,99 @@
 
    protected Object handleRemoveDataMethod(InvocationContext ctx, GlobalTransaction tx, Fqn fqn, boolean createUndoOps) throws Throwable
    {
-      acquireLocksWithTimeout(ctx, fqn, NodeLock.LockType.WRITE, false, false, false, false, false, true);
+      acquireLocksWithTimeout(ctx, fqn, NodeLock.LockType.WRITE, false, false, false, false);
       return nextInterceptor(ctx);
    }
 
    protected Object handleAddChildMethod(InvocationContext ctx, GlobalTransaction tx, Fqn parentFqn, Object childName, Node cn, boolean createUndoOps) throws Throwable
    {
-      acquireLocksWithTimeout(ctx, parentFqn, NodeLock.LockType.WRITE, false, false, false, false, false, false);
+      acquireLocksWithTimeout(ctx, parentFqn, NodeLock.LockType.READ, false, false, false, false);
       return nextInterceptor(ctx);
    }
 
    protected Object handleEvictMethod(InvocationContext ctx, Fqn fqn) throws Throwable
    {
-      acquireLocksWithTimeout(ctx, fqn, NodeLock.LockType.WRITE, false, false, true, false, true, false);
+      acquireLocksWithTimeout(ctx, fqn, NodeLock.LockType.WRITE, false, true, false, false);
       return nextInterceptor(ctx);
    }
 
    protected Object handleGetKeyValueMethod(InvocationContext ctx, Fqn fqn, Object key, boolean sendNodeEvent) throws Throwable
    {
-      return acquireNonRecursiveReadLock(ctx, fqn);
+       acquireLocksWithTimeout(ctx, fqn, NodeLock.LockType.READ, false, false, false, false);
+       return nextInterceptor(ctx);
    }
 
-   private Object acquireNonRecursiveReadLock(InvocationContext ctx, Fqn fqn)
-      throws Throwable
+    protected Object handleGetNodeMethod(InvocationContext ctx, Fqn fqn) throws Throwable
    {
-      acquireLocksWithTimeout(ctx, fqn, NodeLock.LockType.READ, false, false, false, false, false, false);
-      return nextInterceptor(ctx);
+       acquireLocksWithTimeout(ctx, fqn, NodeLock.LockType.READ, false, false, false, false);
+       return nextInterceptor(ctx);
    }
 
-   protected Object handleGetNodeMethod(InvocationContext ctx, Fqn fqn) throws Throwable
-   {
-      return acquireNonRecursiveReadLock(ctx, fqn);
-   }
-
    protected Object handleGetKeysMethod(InvocationContext ctx, Fqn fqn) throws Throwable
    {
-      return acquireNonRecursiveReadLock(ctx, fqn);
+       acquireLocksWithTimeout(ctx, fqn, NodeLock.LockType.READ, false, false, false, false);
+       return nextInterceptor(ctx);
    }
 
    protected Object handleGetChildrenNamesMethod(InvocationContext ctx, Fqn fqn) throws Throwable
    {
-      return acquireNonRecursiveReadLock(ctx, fqn);
+       acquireLocksWithTimeout(ctx, fqn, NodeLock.LockType.READ, false, false, false, false);
+       return nextInterceptor(ctx);
    }
 
    protected Object handlePrintMethod(InvocationContext ctx, Fqn fqn) throws Throwable
    {
-      return acquireNonRecursiveReadLock(ctx, fqn);
+       acquireLocksWithTimeout(ctx, fqn, NodeLock.LockType.READ, false, false, false, false);
+       return nextInterceptor(ctx);
    }
 
    protected Object handleReleaseAllLocksMethod(InvocationContext ctx, Fqn fqn) throws Throwable
    {
-      return acquireNonRecursiveReadLock(ctx, fqn);
+       acquireLocksWithTimeout(ctx, fqn, NodeLock.LockType.READ, false, false, false, false);
+       return nextInterceptor(ctx);
    }
 
-   private boolean acquireLocksWithTimeout(InvocationContext ctx, Fqn fqn, NodeLock.LockType lock_type, boolean recursive, boolean createIfNotExists, boolean zeroLockTimeout, boolean deleteOperation, boolean evictOperation, boolean removeDataOperation)
+   private boolean acquireLocksWithTimeout(InvocationContext ctx, Fqn fqn, NodeLock.LockType lockType,
+                                           boolean createIfNotExists, boolean zeroLockTimeout,
+                                           boolean acquireLockOnParent, boolean reverseRemoveCheck)
       throws InterruptedException
    {
+      if (fqn == null || configuration.getIsolationLevel() == IsolationLevel.NONE)
+      {
+         return false;
+      }      
       boolean created;
-      long timeout = zeroLockTimeout ? 0 : getLockAcquisitionTimeout(ctx);
+      long timeout = zeroLockTimeout ? 0 : ctx.getContextLockAcquisitionTimeout(lock_acquisition_timeout);
       // make sure we can bail out of this loop
       long cutoffTime = System.currentTimeMillis() + timeout;
       boolean firstTry = true;
       do
-            {
-               // this is an additional check to make sure we don't try for too long.
-         if (!firstTry && System.currentTimeMillis() > cutoffTime) throw new TimeoutException("Unable to acquire lock on Fqn " + fqn + " after " + timeout + " millis");
-         created = lock(ctx, fqn, lock_type, recursive, createIfNotExists, timeout, deleteOperation, evictOperation, removeDataOperation);
+      {
+         // this is an additional check to make sure we don't try for too long.
+         if (!firstTry && System.currentTimeMillis() > cutoffTime)
+         {
+            throw new TimeoutException("Unable to acquire lock on Fqn " + fqn + " after " + timeout + " millis");
+         }
+         created = lock(ctx, fqn, lockType, createIfNotExists, timeout, acquireLockOnParent, reverseRemoveCheck);
          firstTry = false;
       }
       while (createIfNotExists && cache.peek(fqn, true) == null);// keep trying until we have the lock (fixes concurrent remove())
       return created;
    }
 
-   //todo move to InvocationContext as it is information expert
-   private long getLockAcquisitionTimeout(InvocationContext ctx)
-   {
-      long timeout = lock_acquisition_timeout;
-      if (ctx.getOptionOverrides() != null
-              && ctx.getOptionOverrides().getLockAcquisitionTimeout() >= 0)
-      {
-         timeout = ctx.getOptionOverrides().getLockAcquisitionTimeout();
-      }
-      return timeout;
-   }
-
-
    /**
-    * Locks a given node.
-    *
-    * @param lock_type DataNode.LOCK_TYPE_READ, DataNode.LOCK_TYPE_WRITE or DataNode.LOCK_TYPE_NONE
-    * @param recursive Lock children recursively
-    * @return true if the node had to be created
+    * Acquires locks on the node and on its parrents. Read locks are acquired for exsiting ancestors, with two exceptions:
+    * 1) createIfNotExists is true. If an ancestor is created on the fly, then an WL is acquired by default
+    * 2) acquireWriteLockOnParent is true. If so AND {@link org.jboss.cache.Node#isLockForChildInsertRemove()} then a read
+    *  lock will be aquired for the parent of the node.
+    * @param createIfNotExists if true, then missing nodes will be cretaed on the fly. If false, method returns if we
+    * reach a node that does not exists
+    * @param reverseRemoveCheck see {@link #manageReverseRemove(org.jboss.cache.transaction.GlobalTransaction, org.jboss.cache.NodeSPI, boolean)}
     */
-   private boolean lock(InvocationContext ctx, Fqn fqn, NodeLock.LockType lock_type, boolean recursive, boolean createIfNotExists, long timeout, boolean isDeleteOperation, boolean isEvictionOperation, boolean isRemoveDataOperation)
+   private boolean lock(InvocationContext ctx, Fqn fqn, NodeLock.LockType lockType, boolean createIfNotExists, long timeout,
+                        boolean acquireWriteLockOnParent, boolean reverseRemoveCheck)
            throws TimeoutException, LockingException, InterruptedException
    {
-      NodeSPI n;
-      NodeSPI child_node;
-      Object child_name;
       Thread currentThread = Thread.currentThread();
       GlobalTransaction gtx = ctx.getGlobalTransaction();
       boolean created = false;
@@ -283,240 +336,164 @@
       {
          assertTransactionValid(ctx);
       }
-
       Object owner = (gtx != null) ? gtx : currentThread;
-      int treeNodeSize;
-
+      NodeSPI currentNode;
       if (log.isTraceEnabled()) log.trace("Attempting to lock node " + fqn + " for owner " + owner);
-
-      if (fqn == null)
-      {
-         log.error("fqn is null - this should not be the case");
-         return false;
-      }
-
-      if (configuration.getIsolationLevel() == IsolationLevel.NONE)
-      {
-         lock_type = NodeLock.LockType.NONE;
-      }
-
-      // we need to make sure this loop doesn't take forever (under a lot of concurrency) either as this can seem like a deadlock.
-      // apply a similar timeout check as is done in the loop that calls this lock() method.
       long expiryTime = System.currentTimeMillis() + timeout;
-      boolean reAcquisitionOnSameNode = false, rerunLoop = true;
-
-      while (rerunLoop)
+      currentNode = cache.getRoot();
+      NodeSPI parent = null;
+      String childName = null;
+      int currentIndex = -1;
+      do
       {
-         n = cache.getRoot();
-         treeNodeSize = fqn.size();
-
-         for (int i = -1; i < treeNodeSize; i++)
+         if (currentNode == null)
          {
-            if (rerunLoop) rerunLoop = false;
-            created = false;
-            if (i == -1)
+            if (createIfNotExists)
             {
-               // this is the root node
-               child_name = Fqn.ROOT.getLastElement();
-               child_node = n;
+               currentNode = parent.addChildDirect(new Fqn(childName));
+               created = true;
+               if (log.isTraceEnabled()) log.trace("Child node was null, so created child node " + childName);
             }
             else
             {
-               child_name = fqn.get(i);
-               child_node = n.getChildDirect(child_name);
-            }
-
-            // timeout check
-            if (reAcquisitionOnSameNode && System.currentTimeMillis() > expiryTime) throw new TimeoutException("Unable to acquire lock on child node " + new Fqn(n.getFqn(), child_name) + " after " + timeout + " millis.");
-
-            if (log.isTraceEnabled()) log.trace("Directly got child node " + child_name);
-            if (child_node == null && createIfNotExists)
-            {
-               child_node = n.addChildDirect(new Fqn(child_name));
-               created = true;
-               if (log.isTraceEnabled()) log.trace("Child node was null, so created child node " + child_name);
-            }
-
-            if (child_node == null)
-            {
-               if (log.isTraceEnabled())
-               {
-                  log.trace("failed to find or create child " + child_name + " of node " + n);
-               }
+               if (log.isTraceEnabled()) log.trace("failed to find or create child " + childName + " of node " + currentNode);
                return false;
             }
+         }
+         NodeLock.LockType lockTypeRequired = NodeLock.LockType.READ;
+         if (created || writeLockNeeded(ctx, lockType, currentIndex, acquireWriteLockOnParent, createIfNotExists, fqn, currentNode))
+         {
+            lockTypeRequired = NodeLock.LockType.WRITE;
+         }
 
-            NodeLock.LockType lockTypeRequired;
-            if (lock_type == NodeLock.LockType.NONE)
-            {
-               n = child_node;
-               continue;
-            }
-            else
-            {
-               if (created || writeLockNeeded(ctx, lock_type, i, treeNodeSize, isEvictionOperation, isDeleteOperation, createIfNotExists, isRemoveDataOperation, fqn, child_node))
-               {
-                  lockTypeRequired = NodeLock.LockType.WRITE;
+         manageReverseRemove(gtx, currentNode, reverseRemoveCheck);
 
-               }
-               else
-               {
-                  lockTypeRequired = NodeLock.LockType.READ;
-               }
-            }
+         // actually acquire the lock we need.  This method blocks.
+         acquireNodeLock(currentNode, owner, gtx, lockTypeRequired, timeout);
 
-            // reverse the "remove" if the node has been previously removed in the same tx, if this operation is a put()
-            if (gtx != null && needToReverseRemove(child_node, tx_table.get(gtx), lock_type, isDeleteOperation, createIfNotExists))
-            {
-               reverseRemove(child_node);
-            }
-
-            // actually acquire the lock we need.  This method blocks.
-            acquireNodeLock(child_node, owner, gtx, lockTypeRequired, timeout);
-
-            // make sure the lock we acquired isn't on a deleted node/is an orphan!!
+         // make sure the lock we acquired isn't on a deleted node/is an orphan!!
+         // look into invalidated nodes as well
+         NodeSPI repeek = cache.peek(currentNode.getFqn(), true, true);
+         if (currentNode != repeek)
+         {
+            if (log.isTraceEnabled()) log.trace("Was waiting for and obtained a lock on a node that doesn't exist anymore!  Attempting lock acquisition again.");
+            // we have an orphan!! Lose the unnecessary lock and re-acquire the lock (and potentially recreate the node).
+            // check if the parent exists!!
             // look into invalidated nodes as well
-            NodeSPI repeek = cache.peek(child_node.getFqn(), true, true);
-            if (child_node != repeek)//repeek != null && child_node != repeek)// || repeek == null && created)
+            currentNode.getLock().releaseAll(owner);
+            if (cache.peek(parent.getFqn(), true, true) == null)
             {
-               log.trace("Was waiting for and obtained a lock on a node that doesn't exist anymore!  Attempting lock acquisition again.");
-               // we have an orphan!! Lose the unnecessary lock and re-acquire the lock (and potentially recreate the node).
-               // check if the parent exists!!
-               // look into invalidated nodes as well
-               if (cache.peek(n.getFqn(), true, true) == null)
-               {
-                  // crap!
-                  log.trace("Parent has been deleted again.  Go through the lock method all over again.");
-                  child_node.getLock().releaseAll(owner);
-                  rerunLoop = true;
-                  i = treeNodeSize;
-               }
-               else
-               {
-                  child_node.getLock().releaseAll(owner);
-
-                  // do the loop again, but don't assign child_node to n so that child_node is processed again.
-                  i--;
-                  reAcquisitionOnSameNode = true;
-               }
-
-               continue;
+               // crap!
+               if (log.isTraceEnabled()) log.trace("Parent has been deleted again.  Go through the lock method all over again.");
+               currentNode = cache.getRoot();
+               parent = null;
             }
             else
             {
-               reAcquisitionOnSameNode = false;
-            }
-
-            if (recursive && isTargetNode(i, treeNodeSize))
-            {
-               Set<NodeLock> acquired_locks = lockManager.acquireAll(child_node, owner, lock_type, timeout);
-               if (acquired_locks.size() > 0)
+               // do the loop again, but don't assign child_node to currentNode so that child_node is processed again.
+               if (System.currentTimeMillis() > expiryTime)
                {
-                  if (gtx != null)
-                  {
-                     cache.getTransactionTable().addLocks(gtx, acquired_locks);
-                  }
-                  else
-                  {
-                     List<NodeLock> locks = getLocks(currentThread);
-                     locks.addAll(acquired_locks);
-                  }
+                  throw new TimeoutException("Unable to acquire lock on child node " + new Fqn(currentNode.getFqn(), childName) + " after " + timeout + " millis.");
                }
             }
-            n = child_node;
          }
-      }
-
-      // Add the Fqn to be removed to the transaction entry so we can clean up after ourselves during commit/rollback
-      if (isDeleteOperation && gtx != null) cache.getTransactionTable().get(gtx).addRemovedNode(fqn);
-
+         else
+         {
+            if (currentNode.getFqn().equals(fqn))//we've just processed the last child
+            {
+               break;
+            }
+            parent = currentNode;
+            currentIndex = currentNode.getFqn().size();
+            currentNode = currentNode.getChildDirect(fqn.get(currentIndex));
+            childName = (String) fqn.get(currentIndex);
+         }
+      } while (true);
       return created;
    }
 
-   private boolean needToReverseRemove(NodeSPI n, TransactionEntry te, NodeLock.LockType lockTypeRequested, boolean isRemoveOperation, boolean createIfNotExists)
-   {
-      return !isRemoveOperation && createIfNotExists && lockTypeRequested == NodeLock.LockType.WRITE && n.isDeleted() && te.getRemovedNodes().contains(n.getFqn());
-   }
 
-   private void reverseRemove(NodeSPI n)
+    /**
+     * Acquires nodes on the children of this node. nodes on the node itself are not aquired.
+     * If the supplied parent node is null the method returns(no op).
+     */
+   private void acquireLocksOnChildren(NodeSPI parentNode, NodeLock.LockType lockType, InvocationContext ctx)
+      throws InterruptedException
    {
-      n.markAsDeleted(false);
+      if (parentNode == null)
+      {
+          return;
+      }
+      long timeout = ctx.getContextLockAcquisitionTimeout(lock_acquisition_timeout);
+      GlobalTransaction gtx = ctx.getGlobalTransaction();
+      Object owner = (gtx != null) ? gtx : Thread.currentThread();
+
+       Set<NodeLock> acquiredLocks = parentNode.getLock().acquireAll(owner, timeout, lockType);
+      if (acquiredLocks.size() > 0)
+      {
+         if (gtx != null)
+         {
+            cache.getTransactionTable().addLocks(gtx, acquiredLocks);
+         }
+         else
+         {
+            List<NodeLock> locks = getLocks(Thread.currentThread());
+            locks.addAll(acquiredLocks);
+         }
+      }
    }
 
-   private boolean writeLockNeeded(InvocationContext ctx, NodeLock.LockType lock_type, int currentNodeIndex, int treeNodeSize, boolean isEvictOperation, boolean isRemoveOperation, boolean isPutOperation, boolean isRemoveDataOperation, Fqn targetFqn, NodeSPI currentNode)
+    /**
+     * Used by {@link #lock(org.jboss.cache.InvocationContext, org.jboss.cache.Fqn, org.jboss.cache.lock.NodeLock.LockType, boolean, long, boolean, boolean)}.
+     * Determins whter an arbitrary node from the supplied fqn needs an write lock.
+     */
+   private boolean writeLockNeeded(InvocationContext ctx, NodeLock.LockType lockType, int currentNodeIndex, boolean acquireWriteLockOnParent, boolean createIfNotExists, Fqn targetFqn, NodeSPI currentNode)
    {
+      int treeNodeSize = targetFqn.size();
       // write lock forced!!
-      boolean isTargetNode = isTargetNode(currentNodeIndex, treeNodeSize);
-
-      if (ctx.getOptionOverrides().isForceWriteLock() && isTargetNode) return true;
-
+       boolean isTargetNode = currentNodeIndex == (treeNodeSize - 1);
+       if (ctx.getOptionOverrides().isForceWriteLock() && isTargetNode) return true;
+      //this can be injected, from the caller as a param named wlParent
       if (currentNode.isLockForChildInsertRemove())
       {
-         if (isRemoveOperation && currentNodeIndex == treeNodeSize - 2)
+         if (acquireWriteLockOnParent && currentNodeIndex == treeNodeSize - 2)
          {
             return true;// we're doing a remove and we've reached the PARENT node of the target to be removed.
          }
-
          if (!isTargetNode && cache.peek(new Fqn(currentNode.getFqn(), targetFqn.get(currentNodeIndex + 1)), false) == null)
          {
-            return isPutOperation;// we're at a node in the tree, not yet at the target node, and we need to create the nextInterceptor node.  So we need a WL here.
+            return createIfNotExists;// we're at a node in the tree, not yet at the target node, and we need to create the next node.  So we need a WL here.
          }
       }
-      return lock_type == NodeLock.LockType.WRITE && isTargetNode && (isPutOperation || isRemoveOperation || isEvictOperation || isRemoveDataOperation);//normal operation, write lock explicitly requested and this is the target to be written to.
+      return lockType == NodeLock.LockType.WRITE && isTargetNode;//write lock explicitly requested and this is the target to be written to.
    }
 
-   private boolean isTargetNode(int nodePosition, int treeNodeSize)
+    private void acquireNodeLock(NodeSPI node, Object owner, GlobalTransaction gtx, NodeLock.LockType lockType, long lockTimeout) throws LockingException, TimeoutException, InterruptedException
    {
-      return nodePosition == (treeNodeSize - 1);
-   }
-
-   private void acquireNodeLock(NodeSPI node, Object owner, GlobalTransaction gtx, NodeLock.LockType lock_type, long lock_timeout) throws LockingException, TimeoutException, InterruptedException
-   {
-      boolean acquired = lockManager.acquire(node, owner, lock_type, lock_timeout);
+      boolean acquired = node.getLock().acquire(owner, lockTimeout, lockType);
       if (acquired)
       {
          // Record the lock for release on method return or tx commit/rollback
-         recordNodeLock(gtx, lockManager.getLock(node));
+          NodeLock lock = node.getLock();
+          if (gtx != null)
+          {
+             cache.getTransactionTable().recordNodeLock(gtx, lock);
+          }
+          else
+          {
+             Thread currentThread = Thread.currentThread();
+             List<NodeLock> locks = getLocks(currentThread);
+             if (!locks.contains(lock))
+             {
+                locks.add(lock);
+                lock_table.put(currentThread, locks);
+             }
+          }
       }
-      else
-      {
-         //if (log.isDebugEnabled()) log.debug("Unable to acquire lock on node " + node.getFqn());
-         //throw new LockingException("Could not acquite lock for " + node.getFqn());
-      }
    }
 
-   private void recordNodeLock(GlobalTransaction gtx, NodeLock lock)
+    private List<NodeLock> getLocks(Thread currentThread)
    {
-      if (gtx != null)
-      {
-         // add the lock to the list of locks maintained for this transaction
-         // (needed for release of locks on commit or rollback)
-         try
-         {
-            cache.getTransactionTable().addLock(gtx, lock);
-         }
-         catch (CacheException e)
-         {
-            // may happen, if the transaction entry does not exist
-            lock.release(gtx);
-            throw e;
-         }
-      }
-      else
-      {
-         Thread currentThread = Thread.currentThread();
-         List<NodeLock> locks = getLocks(currentThread);
-         if (!locks.contains(lock))
-         {
-            locks.add(lock);
-            lock_table.put(currentThread, locks);
-         }
-      }
-   }
-
-   //todo move to lock tabe as it is information xprt
-   private List<NodeLock> getLocks(Thread currentThread)
-   {
       // This sort of looks like a get/put race condition, but
       // since we key off the Thread, it's not
       List<NodeLock> locks = lock_table.get(currentThread);
@@ -529,50 +506,25 @@
    }
 
 
-   private void createNodes(Fqn fqn, GlobalTransaction gtx)
+    /**
+     * Test if this node needs to be 'undeleted'
+     * reverse the "remove" if the node has been previously removed in the same tx, if this operation is a put()
+     */
+   private void manageReverseRemove(GlobalTransaction gtx, NodeSPI childNode, boolean reverseRemoveCheck)
    {
-      int treeNodeSize;
-      if ((treeNodeSize = fqn.size()) == 0) return;
-      NodeSPI n = cache.getRoot();
-      for (int i = 0; i < treeNodeSize; i++)
+      boolean needToReverseRemove = reverseRemoveCheck && childNode.isDeleted() && tx_table.get(gtx).getRemovedNodes().contains(childNode.getFqn());
+      if (gtx != null && needToReverseRemove)
       {
-         Object child_name = fqn.get(i);
-         Fqn childFqn = new Fqn(child_name);
-
-         NodeSPI child_node = n.getChildDirect(childFqn);
-         if (child_node == null) child_node = n.addChildDirect(childFqn);
-         // test if this node needs to be 'undeleted'
-         // reverse the "remove" if the node has been previously removed in the same tx, if this operation is a put()
-         if (gtx != null && needToReverseRemove(child_node, tx_table.get(gtx), NodeLock.LockType.WRITE, false, true))
-         {
-            reverseRemove(child_node);
-         }
-
-         if (child_node == null)
-         {
-            if (log.isTraceEnabled())
-            {
-               log.trace("failed to find or create child " + child_name + " of node " + n.getFqn());
-            }
-            return;
-         }
-         n = child_node;
+          childNode.markAsDeleted(false);
       }
    }
 
    /**
     * Remove all locks held by <tt>tx</tt>, remove the transaction from the transaction table
-    *
-    * @param gtx
-    * todo move this logic in txTable as it is information expert for this class (this looks procedural)
     */
    private void commit(GlobalTransaction gtx)
    {
-      if (log.isTraceEnabled())
-      {
-         log.trace("committing cache with gtx " + gtx);
-      }
-
+      if (log.isTraceEnabled()) log.trace("committing cache with gtx " + gtx);
       TransactionEntry entry = tx_table.get(gtx);
       if (entry == null)
       {
@@ -590,104 +542,4 @@
       }
    }
 
-   /**
-    * todo move this logic in txTable as it is information expert for this class (this looks procedural)
-    */
-   private void cleanup(GlobalTransaction gtx)
-   {
-      if (log.isTraceEnabled()) log.trace("Cleaning up locks for gtx " + gtx);
-      TransactionEntry entry = tx_table.get(gtx);
-      // Let's do it in stack style, LIFO
-      if (entry != null)
-         entry.releaseAllLocksLIFO(gtx);
-      else
-         log.error("No transaction entry present!!", new Throwable());
-
-/*
-      Transaction ltx = entry.getTransaction();
-      if (log.isTraceEnabled())
-      {
-         log.trace("removing local transaction " + ltx + " and global transaction " + gtx);
-      }
-      tx_table.remove(ltx);
-      tx_table.remove(gtx);
-*/
-   }
-
-   /**
-    * Revert all changes made inside this TX: invoke all method calls of the undo-ops
-    * list. Then release all locks and remove the TX from the transaction table.
-    * <ol>
-    * <li>Revert all modifications done in the current TX<li/>
-    * <li>Release all locks held by the current TX</li>
-    * <li>Remove all temporary nodes created by the current TX</li>
-    * </ol>
-    *
-    * todo move this logic in txTable as it is information expert for this class (this looks procedural)
-    */
-   private void rollback(GlobalTransaction tx)
-   {
-      TransactionEntry entry = tx_table.get(tx);
-
-      if (log.isTraceEnabled())
-      {
-         log.trace("called to rollback cache with GlobalTransaction=" + tx);
-      }
-
-      if (entry == null)
-      {
-         log.error("entry for transaction " + tx + " not found (transaction has possibly already been rolled back)");
-         return;
-      }
-
-      Iterator removedNodes = entry.getRemovedNodes().iterator();
-      CacheImpl cacheImpl = (CacheImpl) cache;
-      while (removedNodes.hasNext())
-      {
-         Fqn f = (Fqn) removedNodes.next();
-         cacheImpl.realRemove(f, false);
-
-      }
-
-      // 1. Revert the modifications by running the undo-op list in reverse. This *cannot* throw any exceptions !
-      entry.undoOperations(cache);
-
-      // This was removed as we don't use temporary nodes anymore; we now create undo-operations on put(), e.g.
-      // put(/a/b/c) on /a, create b and c, plus undo operations _remove(a/b/c) and _remove(/a/b)
-
-      // 2. Remove all temporary nodes. Need to do it backwards since node is LIFO.
-      //      for(ListIterator it=new LinkedList(entry.getNodes()).listIterator(entry.getNodes().size());
-      //          it.hasPrevious();) {
-      //         node_name=(Fqn)it.previous();
-      //         try {
-      //            cache._remove(tx, node_name, false);
-      //         }
-      //         catch(Throwable t) {
-      //            log.error("failed removing node \"" + node_name + "\"", t);
-      //         }
-      //      }
-
-      // 3. Finally, release all locks held by this TX
-      // Let's do it in stack style, LIFO
-      // Note that the lock could have been released already so don't panic.
-   }
-
-   private static class LockManager
-   {
-      boolean acquire(NodeSPI node, Object owner, NodeLock.LockType lockType, long timeout) throws InterruptedException
-      {
-         return getLock(node).acquire(owner, timeout, lockType);
-      }
-
-      NodeLock getLock(NodeSPI node)
-      {
-         return node.getLock();
-      }
-
-      public Set<NodeLock> acquireAll(NodeSPI node, Object owner, NodeLock.LockType lockType, long timeout) throws InterruptedException
-      {
-         return getLock(node).acquireAll(owner, timeout, lockType);
-      }
-   }
-
 }

Modified: core/trunk/src/main/java/org/jboss/cache/transaction/TransactionTable.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/transaction/TransactionTable.java	2007-12-10 21:57:40 UTC (rev 4824)
+++ core/trunk/src/main/java/org/jboss/cache/transaction/TransactionTable.java	2007-12-10 23:47:41 UTC (rev 4825)
@@ -230,6 +230,18 @@
       entry.addLocks(locks);
    }
 
+   public void cleanup(GlobalTransaction gtx)
+   {
+      if (log.isTraceEnabled()) log.trace("Cleaning up locks for gtx " + gtx);
+      TransactionEntry entry = this.get(gtx);
+      // Let's do it in stack style, LIFO
+      if (entry != null)
+         entry.releaseAllLocksLIFO(gtx);
+      else
+         log.error("No transaction entry present!!", new Throwable());
+   }
+
+
    /**
     * Returns summary debug information.
     */
@@ -264,4 +276,21 @@
       return sb.toString();
    }
 
+   /**
+    * Add the lock to the list of locks maintained for this transaction
+    * (needed for release of locks on commit or rollback)
+     */
+   public void recordNodeLock(GlobalTransaction gtx, NodeLock lock)
+   {
+      try
+      {
+         addLock(gtx, lock);
+      }
+      catch (CacheException e)
+      {
+         // may happen, if the transaction entry does not exist
+         lock.release(gtx);
+         throw e;
+      }
+   }
 }




More information about the jbosscache-commits mailing list