[seam-commits] Seam SVN: r8642 - trunk/examples/wiki/src/main/org/jboss/seam/wiki/core/nestedset/listener.

seam-commits at lists.jboss.org seam-commits at lists.jboss.org
Fri Aug 8 13:26:13 EDT 2008


Author: christian.bauer at jboss.com
Date: 2008-08-08 13:26:13 -0400 (Fri, 08 Aug 2008)
New Revision: 8642

Added:
   trunk/examples/wiki/src/main/org/jboss/seam/wiki/core/nestedset/listener/NestedSetMonitor.java
Modified:
   trunk/examples/wiki/src/main/org/jboss/seam/wiki/core/nestedset/listener/NestedSetOperation.java
   trunk/examples/wiki/src/main/org/jboss/seam/wiki/core/nestedset/listener/NestedSetPostDeleteEventListener.java
   trunk/examples/wiki/src/main/org/jboss/seam/wiki/core/nestedset/listener/NestedSetPostInsertEventListener.java
Log:
Nested set modifications require some form of locking, serializing in-memory for now

Added: trunk/examples/wiki/src/main/org/jboss/seam/wiki/core/nestedset/listener/NestedSetMonitor.java
===================================================================
--- trunk/examples/wiki/src/main/org/jboss/seam/wiki/core/nestedset/listener/NestedSetMonitor.java	                        (rev 0)
+++ trunk/examples/wiki/src/main/org/jboss/seam/wiki/core/nestedset/listener/NestedSetMonitor.java	2008-08-08 17:26:13 UTC (rev 8642)
@@ -0,0 +1,49 @@
+package org.jboss.seam.wiki.core.nestedset.listener;
+
+import org.hibernate.event.EventSource;
+
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * An alternative to table locking, we serialize nested set insert/updates in memory.
+ *
+ * <p>
+ * Any nested set tree modification potentially updates all rows in a database table. This
+ * requires several <tt>UPDATE</tt> statements, and also <tt>INSERT</tt> and <tt>DELETE</tt>.
+ * Any concurrent commit to the rows betwen <tt>UPDATE</tt> statements would be fatal and
+ * corrupt the tree information. The usual solution is to lock the whole table(s). Because
+ * MySQL has a compleltey unusable locking system (locking a table commits the current transaction, you
+ * need to lock all tables you are going to use from that point on, etc.), and because portability is
+ * a concern of this Nested Set implementation, we work around the problem with an in-memory exclusive lock.
+ * </p>
+ * <p>
+ * <b>NOTE:</b> This does NOT work if several applications modify the nested set
+ * tree in the same tables!
+ * </p>
+ *
+ * @author Christian Bauer
+ */
+public class NestedSetMonitor {
+
+    private static final int LOCK_TIMEOUT_SECONDS = 10;
+
+    private static final Lock lock = new ReentrantLock(true);
+
+    public static void executeOperation(NestedSetOperation operation, EventSource session) {
+        try {
+            if (lock.tryLock(LOCK_TIMEOUT_SECONDS, TimeUnit.SECONDS)) {
+                try {
+                    operation.execute(session);
+                } finally {
+                    lock.unlock();
+                }
+            } else {
+                throw new RuntimeException("Could not aquire lock to update nested set tree");
+            }
+        } catch (InterruptedException ex) {
+            throw new RuntimeException("Current thread could not aquire lock, has been interrupted");
+        }
+    }
+}

Modified: trunk/examples/wiki/src/main/org/jboss/seam/wiki/core/nestedset/listener/NestedSetOperation.java
===================================================================
--- trunk/examples/wiki/src/main/org/jboss/seam/wiki/core/nestedset/listener/NestedSetOperation.java	2008-08-08 16:02:46 UTC (rev 8641)
+++ trunk/examples/wiki/src/main/org/jboss/seam/wiki/core/nestedset/listener/NestedSetOperation.java	2008-08-08 17:26:13 UTC (rev 8642)
@@ -43,7 +43,7 @@
  * for the deprecated <tt>Session#connection()</tt> method.
  * </p>
  *
- * TODO: We should lock the tables!
+ * TODO: We should lock the tables! Instead we are using the NestedSetMonitor as a workaround...
  *
  * @author Christian Bauer
  */

Modified: trunk/examples/wiki/src/main/org/jboss/seam/wiki/core/nestedset/listener/NestedSetPostDeleteEventListener.java
===================================================================
--- trunk/examples/wiki/src/main/org/jboss/seam/wiki/core/nestedset/listener/NestedSetPostDeleteEventListener.java	2008-08-08 16:02:46 UTC (rev 8641)
+++ trunk/examples/wiki/src/main/org/jboss/seam/wiki/core/nestedset/listener/NestedSetPostDeleteEventListener.java	2008-08-08 17:26:13 UTC (rev 8642)
@@ -26,7 +26,10 @@
 
         if ( NestedSetNode.class.isAssignableFrom(event.getEntity().getClass())) {
             log.debug("executing nested set delete operation, recalculating the tree");
-            new DeleteNestedSetOperation( (NestedSetNode)event.getEntity() ).execute(event.getSession());
+            NestedSetMonitor.executeOperation(
+                new DeleteNestedSetOperation( (NestedSetNode)event.getEntity() ),
+                event.getSession()
+            );
         }
     }
 

Modified: trunk/examples/wiki/src/main/org/jboss/seam/wiki/core/nestedset/listener/NestedSetPostInsertEventListener.java
===================================================================
--- trunk/examples/wiki/src/main/org/jboss/seam/wiki/core/nestedset/listener/NestedSetPostInsertEventListener.java	2008-08-08 16:02:46 UTC (rev 8641)
+++ trunk/examples/wiki/src/main/org/jboss/seam/wiki/core/nestedset/listener/NestedSetPostInsertEventListener.java	2008-08-08 17:26:13 UTC (rev 8642)
@@ -26,7 +26,10 @@
 
         if ( NestedSetNode.class.isAssignableFrom(event.getEntity().getClass())) {
             log.debug("executing nested set insert operation, recalculating the tree");
-            new InsertNestedSetOperation( (NestedSetNode)event.getEntity() ).execute(event.getSession());
+            NestedSetMonitor.executeOperation(
+                new InsertNestedSetOperation((NestedSetNode)event.getEntity()),
+                event.getSession()
+            );
         }
     }
 




More information about the seam-commits mailing list