[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