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/

[email protected]
Newsgroups gmane.comp.cms.lenya.cvs
Message-ID <[email protected]>
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;
             }
         }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.