You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lenya.apache.org by an...@apache.org on 2007/08/10 18:27:23 UTC

svn commit: r564653 - in /lenya/trunk/src: java/org/apache/lenya/cms/repository/ java/org/apache/lenya/transaction/ modules-core/usecase/java/src/org/apache/lenya/cms/usecase/

Author: andreas
Date: Fri Aug 10 09:27:21 2007
New Revision: 564653

URL: http://svn.apache.org/viewvc?view=rev&rev=564653
Log:
Introduced global transaction lock

Added:
    lenya/trunk/src/java/org/apache/lenya/transaction/TransactionLock.java
Modified:
    lenya/trunk/src/java/org/apache/lenya/cms/repository/SessionImpl.java
    lenya/trunk/src/java/org/apache/lenya/transaction/UnitOfWorkImpl.java
    lenya/trunk/src/modules-core/usecase/java/src/org/apache/lenya/cms/usecase/AbstractUsecase.java

Modified: lenya/trunk/src/java/org/apache/lenya/cms/repository/SessionImpl.java
URL: http://svn.apache.org/viewvc/lenya/trunk/src/java/org/apache/lenya/cms/repository/SessionImpl.java?view=diff&rev=564653&r1=564652&r2=564653
==============================================================================
--- lenya/trunk/src/java/org/apache/lenya/cms/repository/SessionImpl.java (original)
+++ lenya/trunk/src/java/org/apache/lenya/cms/repository/SessionImpl.java Fri Aug 10 09:27:21 2007
@@ -54,7 +54,8 @@
     /**
      * Ctor.
      * @param identity The identity.
-     * @param modifiable Determins if the repository items in this session can be modified. 
+     * @param modifiable Determins if the repository items in this session can
+     *        be modified.
      * @param manager The service manager.
      * @param logger The logger.
      */
@@ -67,13 +68,13 @@
 
         this.identityMap = new IdentityMapImpl(logger);
         this.identity = identity;
-        
+
         ObservationRegistry registry = null;
         UUIDGenerator generator = null;
         try {
             registry = (ObservationRegistry) this.manager.lookup(ObservationRegistry.ROLE);
             addListener(registry);
-            
+
             generator = (UUIDGenerator) this.manager.lookup(UUIDGenerator.ROLE);
             this.id = generator.nextUUID();
         } catch (Exception e) {
@@ -86,7 +87,7 @@
                 this.manager.release(generator);
             }
         }
-        
+
         if (modifiable) {
             this.unitOfWork = new UnitOfWorkImpl(this.identityMap, this.identity, getLogger());
         }
@@ -109,6 +110,8 @@
         return this.unitOfWork;
     }
 
+    private boolean committed = false;
+
     /**
      * Commits the transaction.
      * @throws RepositoryException if an error occurs.
@@ -126,6 +129,8 @@
             throw new RepositoryException(e);
         }
 
+        this.committed = true;
+
         for (Iterator i = this.events.iterator(); i.hasNext();) {
             RepositoryEvent event = (RepositoryEvent) i.next();
             for (Iterator l = this.listeners.iterator(); l.hasNext();) {
@@ -148,7 +153,7 @@
         }
         this.events.clear();
     }
-    
+
     protected SharedItemStore getSharedItemStore() {
         if (this.sharedItemStore == null) {
             try {
@@ -166,11 +171,10 @@
      */
     public RepositoryItem getRepositoryItem(RepositoryItemFactory factory, String key)
             throws RepositoryException {
-        
+
         if (!isModifiable() && factory.isSharable()) {
             return getSharedItemStore().getRepositoryItem(factory, key);
-        }
-        else {
+        } else {
             RepositoryItemFactoryWrapper wrapper = new RepositoryItemFactoryWrapper(factory, this);
             return (RepositoryItem) getIdentityMap().get(wrapper, key);
         }
@@ -224,10 +228,15 @@
     private List events = new ArrayList();
     private IdentityMap identityMap;
 
-    public void enqueueEvent(RepositoryEvent event) {
+    public synchronized void enqueueEvent(RepositoryEvent event) {
         if (!isModifiable()) {
             throw new RuntimeException("Can't enqueue event in unmodifiable session!");
         }
+        if (committed) {
+            throw new RuntimeException(
+                    "No events can be queued after the session has been committed. Event: ["
+                            + event.getDescriptor() + "]");
+        }
         Assert.isTrue("event belongs to session", event.getSession() == this);
         this.events.add(event);
     }
@@ -239,7 +248,7 @@
     public boolean isModifiable() {
         return this.unitOfWork != null;
     }
-    
+
     private String id;
 
     public String getId() {

Added: lenya/trunk/src/java/org/apache/lenya/transaction/TransactionLock.java
URL: http://svn.apache.org/viewvc/lenya/trunk/src/java/org/apache/lenya/transaction/TransactionLock.java?view=auto&rev=564653
==============================================================================
--- lenya/trunk/src/java/org/apache/lenya/transaction/TransactionLock.java (added)
+++ lenya/trunk/src/java/org/apache/lenya/transaction/TransactionLock.java Fri Aug 10 09:27:21 2007
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+package org.apache.lenya.transaction;
+
+/**
+ * Global transaction lock.
+ */
+public class TransactionLock {
+
+    public static final Object LOCK = TransactionLock.class;
+    
+}

Modified: lenya/trunk/src/java/org/apache/lenya/transaction/UnitOfWorkImpl.java
URL: http://svn.apache.org/viewvc/lenya/trunk/src/java/org/apache/lenya/transaction/UnitOfWorkImpl.java?view=diff&rev=564653&r1=564652&r2=564653
==============================================================================
--- lenya/trunk/src/java/org/apache/lenya/transaction/UnitOfWorkImpl.java (original)
+++ lenya/trunk/src/java/org/apache/lenya/transaction/UnitOfWorkImpl.java Fri Aug 10 09:27:21 2007
@@ -88,8 +88,6 @@
         this.removedObjects.add(object);
     }
 
-    private static Object classLock = UnitOfWorkImpl.class;
-
     /**
      * Commit the transaction. We lock this method for the whole class to avoid
      * synchronization problems.
@@ -100,7 +98,7 @@
             getLogger().debug("UnitOfWorkImpl::commit() called");
         }
 
-        synchronized (classLock) {
+        synchronized (TransactionLock.LOCK) {
 
             Set lockedObjects = this.locks.keySet();
 
@@ -186,7 +184,7 @@
         if (getLogger().isDebugEnabled()) {
             getLogger().debug("UnitOfWorkImpl::rollback() called");
         }
-        synchronized (classLock) {
+        synchronized (TransactionLock.LOCK) {
             if (getIdentityMap() != null) {
                 Object[] objects = getIdentityMap().getObjects();
                 for (int i = 0; i < objects.length; i++) {

Modified: lenya/trunk/src/modules-core/usecase/java/src/org/apache/lenya/cms/usecase/AbstractUsecase.java
URL: http://svn.apache.org/viewvc/lenya/trunk/src/modules-core/usecase/java/src/org/apache/lenya/cms/usecase/AbstractUsecase.java?view=diff&rev=564653&r1=564652&r2=564653
==============================================================================
--- lenya/trunk/src/modules-core/usecase/java/src/org/apache/lenya/cms/usecase/AbstractUsecase.java (original)
+++ lenya/trunk/src/modules-core/usecase/java/src/org/apache/lenya/cms/usecase/AbstractUsecase.java Fri Aug 10 09:27:21 2007
@@ -47,6 +47,7 @@
 import org.apache.lenya.cms.repository.Session;
 import org.apache.lenya.transaction.ConcurrentModificationException;
 import org.apache.lenya.transaction.LockException;
+import org.apache.lenya.transaction.TransactionLock;
 
 /**
  * Abstract usecase implementation.
@@ -305,8 +306,8 @@
                     getSession().rollback();
                 }
             } catch (ConcurrentModificationException e) {
-                getLogger().error(
-                        "Could not commit usecase [" + getName() + "]: " + e.getMessage());
+                getLogger()
+                        .error("Could not commit usecase [" + getName() + "]: " + e.getMessage());
                 addErrorMessage(e.getMessage());
             } catch (Exception e1) {
                 getLogger().error("Could not commit/rollback usecase [" + getName() + "]: ", e1);
@@ -729,6 +730,10 @@
     }
 
     /**
+     * <p>
+     * This method is locked via the class lock to avoid inter-usecase
+     * synchronization issues.
+     * </p>
      * @see org.apache.lenya.cms.usecase.Usecase#lockInvolvedObjects()
      */
     public final void lockInvolvedObjects() throws UsecaseException {
@@ -738,7 +743,9 @@
         } catch (RepositoryException e) {
             throw new UsecaseException(e);
         }
-        lockInvolvedObjects(getNodesToLock());
+        synchronized (TransactionLock.LOCK) {
+            lockInvolvedObjects(getNodesToLock());
+        }
     }
 
     protected void startTransaction() throws RepositoryException {
@@ -748,11 +755,13 @@
     }
 
     /**
+     * <p>
      * Lock the objects, for example when you need to change them (for example,
      * delete). If you know when entering the usecase what these objects are,
      * you do not need to call this, the framework will take of it if you
      * implement getObjectsToLock(). If you do not know in advance what the
      * objects are, you can call this method explicitly when appropriate.
+     * </p>
      * 
      * @param objects the transactionable objects to lock
      * @throws UsecaseException if an error occurs.
@@ -760,18 +769,9 @@
      * @see #getNodesToLock()
      */
     public final void lockInvolvedObjects(Node[] objects) throws UsecaseException {
-
-        if (getLogger().isDebugEnabled())
-            getLogger().debug(
-                    "AbstractUsecase::lockInvolvedObjects() called, are there objects to lock ? "
-                            + (objects != null));
-
         try {
             for (int i = 0; i < objects.length; i++) {
                 if (!objects[i].isLocked()) {
-                    if (getLogger().isDebugEnabled())
-                        getLogger().debug(
-                                "AbstractUsecase::lockInvolvedObjects() locking " + objects[i]);
                     objects[i].lock();
                 }
                 if (!isOptimistic() && !objects[i].isCheckedOutBySession()) {
@@ -788,11 +788,11 @@
 
         for (int i = 0; i < objects.length; i++) {
             if (objects[i].isCheckedOut() && !objects[i].isCheckedOutBySession()) {
-                if (getLogger().isDebugEnabled())
+                if (getLogger().isDebugEnabled()) {
                     getLogger().debug(
                             "AbstractUsecase::lockInvolvedObjects() can not execute, object ["
                                     + objects[i] + "] is already checked out");
-
+                }
                 canExecute = false;
             }
         }



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@lenya.apache.org
For additional commands, e-mail: commits-help@lenya.apache.org