Index: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/ClusterNode.java =================================================================== --- jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/ClusterNode.java (revision 537603) +++ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/ClusterNode.java (working copy) @@ -1125,4 +1126,22 @@ record.writeString(owner); } } + + /** + * @throws JournalException + * + */ + public void beginUpdate() throws JournalException + { + journal.lockAndSync(); + } + + /** + * + */ + public void endUpdate(boolean sucessfull) + { + journal.unlock(sucessfull); + + } } Index: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/LockManagerImpl.java =================================================================== --- jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/LockManagerImpl.java (revision 537603) +++ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/LockManagerImpl.java (working copy) @@ -25,11 +25,13 @@ import org.apache.jackrabbit.core.SessionImpl; import org.apache.jackrabbit.core.SessionListener; import org.apache.jackrabbit.core.util.Dumpable; +import org.apache.jackrabbit.core.cluster.ClusterNode; import org.apache.jackrabbit.core.cluster.LockEventChannel; import org.apache.jackrabbit.core.cluster.LockEventListener; import org.apache.jackrabbit.core.fs.FileSystem; import org.apache.jackrabbit.core.fs.FileSystemException; import org.apache.jackrabbit.core.fs.FileSystemResource; +import org.apache.jackrabbit.core.journal.JournalException; import org.apache.jackrabbit.core.observation.EventImpl; import org.apache.jackrabbit.core.observation.SynchronousEventListener; import org.apache.jackrabbit.name.MalformedPathException; @@ -109,19 +111,23 @@ */ private LockEventChannel eventChannel; + private ClusterNode clusterNode; + /** * Create a new instance of this class. * * @param session system session * @param fs file system for persisting locks + * @param clusterNode * @throws RepositoryException if an error occurs */ - public LockManagerImpl(SessionImpl session, FileSystem fs) + public LockManagerImpl(SessionImpl session, FileSystem fs, ClusterNode clusterNode) throws RepositoryException { this.session = session; this.nsResolver = session.getNamespaceResolver(); this.locksFile = new FileSystemResource(fs, FileSystem.SEPARATOR + LOCKS_FILE); + this.clusterNode = clusterNode; session.getWorkspace().getObservationManager(). addEventListener(this, Event.NODE_ADDED | Event.NODE_REMOVED, @@ -261,6 +267,26 @@ LockInfo info = new LockInfo(new LockToken(node.getNodeId()), isSessionScoped, isDeep, session.getUserID()); + if (!info.sessionScoped && eventChannel != null && clusterNode != null) + { + for (int i = 0;; i++) + { + try + { + clusterNode.beginUpdate(); + break; + } + catch (JournalException e) + { + if (i >= 10) + { + throw new RepositoryException("Unable to get cluster Lock ", e); + } + } + } + } + try { + acquire(); try { @@ -299,17 +325,50 @@ } finally { release(); } + } + finally + { + if (!info.sessionScoped && eventChannel != null && clusterNode != null) + { + clusterNode.endUpdate(true); + } + } } /** - * Unlock a node (internal implementation) - * @param node node to unlock - * @throws LockException if the node can not be unlocked - * @throws RepositoryException if another error occurs - */ + * Unlock a node (internal implementation) + * + * @param node + * node to unlock + * @throws LockException + * if the node can not be unlocked + * @throws RepositoryException + * if another error occurs + */ void internalUnlock(NodeImpl node) throws LockException, RepositoryException { + if (eventChannel != null && clusterNode != null) + { + for (int i = 0;; i++) + { + try + { + clusterNode.beginUpdate(); + break; + } + catch (JournalException e) + { + if (i >= 10) + { + throw new RepositoryException("Unable to get cluster Lock ", e); + } + } + } + } + try { + + acquire(); try { @@ -343,6 +402,11 @@ } finally { release(); } + } finally { + if (eventChannel != null && clusterNode != null ) { + clusterNode.endUpdate(true); + } + } } /** Index: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java =================================================================== --- jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java (revision 537603) +++ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java (working copy) @@ -1668,7 +1668,7 @@ // lock manager is lazily instantiated in order to avoid // 'chicken & egg' bootstrap problems if (lockMgr == null) { - lockMgr = new LockManagerImpl(getSystemSession(), fs); + lockMgr = new LockManagerImpl(getSystemSession(), fs, (clusterNode != null && config.isClustered())?clusterNode:null ); if (clusterNode != null && config.isClustered()) { lockChannel = clusterNode.createLockChannel(getName()); lockMgr.setEventChannel(lockChannel); Index: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/journal/Journal.java =================================================================== --- jackrabbit-core/src/main/java/org/apache/jackrabbit/core/journal/Journal.java (revision 537772) +++ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/journal/Journal.java (working copy) @@ -71,4 +71,24 @@ * Close this journal. This should release any resources still held by this journal. */ public void close(); + + /** + * Unlock the journal + * @param sucessfull + */ + public void unlock(boolean sucessfull); + + /** + * Lock the journal with a read lock and then + * Synchronize contents from journal. This will compare the journal's + * revision with the revisions of all registered consumers and invoke + * their {@link RecordConsumer#consume} method when their identifier + * matches the one found in the records. + * + * The jornal will remain locked and must explicitly be unlocked + * + * @throws JournalException if an error occurs + * + */ + public void lockAndSync() throws JournalException; } \ No newline at end of file