Permalink
Browse files

MODE-1822 Improved how the transactional caches handle persisted-but-…

…not-committed events

This commit includes some minor changes to ensure that all events resulting from a save within
the context of a transaction are properly handled by all transactional workspace caches associated
with that transaction. This will hopefully improve performance by clearing the workspace cache
less frequently.
  • Loading branch information...
1 parent b8e2a0b commit 93b1c48711ffee39ede4d95a14628da0b7f6de5f @rhauch rhauch committed Mar 8, 2013
@@ -24,10 +24,13 @@
package org.modeshape.jcr.cache.document;
import java.util.concurrent.ConcurrentHashMap;
+import javax.transaction.Transaction;
import org.modeshape.jcr.cache.CachedNode;
import org.modeshape.jcr.cache.NodeKey;
import org.modeshape.jcr.cache.RepositoryCache;
import org.modeshape.jcr.cache.change.ChangeSet;
+import org.modeshape.jcr.cache.document.TransactionalWorkspaceCaches.OnEachTransactionalCache;
+import org.modeshape.jcr.txn.SynchronizedTransactions;
/**
* A special WorkspaceCache implementation that should be used by sessions running within user transactions.
@@ -51,22 +54,58 @@
public class TransactionalWorkspaceCache extends WorkspaceCache {
private final WorkspaceCache sharedWorkspaceCache;
+ private final TransactionalWorkspaceCaches cacheManager;
+ private final Transaction txn;
- protected TransactionalWorkspaceCache( WorkspaceCache sharedWorkspaceCache ) {
+ protected TransactionalWorkspaceCache( WorkspaceCache sharedWorkspaceCache,
+ TransactionalWorkspaceCaches cacheManager,
+ Transaction txn ) {
// Use a new in-memory map for the transactional cache ...
super(sharedWorkspaceCache, new ConcurrentHashMap<NodeKey, CachedNode>(), null);
this.sharedWorkspaceCache = sharedWorkspaceCache;
+ this.txn = txn;
+ this.cacheManager = cacheManager;
}
@Override
public void changed( ChangeSet changes ) {
// Delegate to the shared ...
sharedWorkspaceCache.changed(changes);
- // And then handle it ourselves ...
- super.changed(changes);
+ // And then delegate so that all transactional workspace caches are notified ...
+ changedWithinTransaction(changes);
+ }
+
+ /**
+ * Signal that this transaction-specific workspace cache needs to reflect recent changes that have been persisted but not yet
+ * committed. Generally, the transactional workspace cache will clear any cached nodes that were included in the change set
+ *
+ * @param changes the changes that were persisted but not yet committed
+ * @see SynchronizedTransactions#updateCache(WorkspaceCache, ChangeSet, org.modeshape.jcr.txn.Transactions.Transaction)
+ */
+ public void changedWithinTransaction( final ChangeSet changes ) {
+ cacheManager.onAllWorkspacesInTransaction(txn, new OnEachTransactionalCache() {
+ @Override
+ public void execute( TransactionalWorkspaceCache cache ) {
+ cache.internalChangedWithinTransaction(changes);
+ }
+ });
+ }
+
+ @Override
+ public void clear() {
+ cacheManager.onAllWorkspacesInTransaction(txn, new OnEachTransactionalCache() {
+ @Override
+ public void execute( TransactionalWorkspaceCache cache ) {
+ cache.internalClear();
+ }
+ });
+ }
+
+ void internalClear() {
+ super.clear();
}
- public void changedWithinTransaction( ChangeSet changes ) {
+ void internalChangedWithinTransaction( ChangeSet changes ) {
// Handle it ourselves ...
super.changed(changes);
}
@@ -71,7 +71,6 @@ public WorkspaceCache getTransactionalWorkspaceCache( WorkspaceCache sharedWorks
TransactionalWorkspaceCache cache = workspaceCachesForTransaction.get(workspaceName);
if (cache != null) {
- cache.clear();
return cache;
}
@@ -109,9 +108,40 @@ protected synchronized void remove( Transaction txn ) {
transactionalCachesByTransaction.remove(txn);
}
+ /**
+ * Invoke the supplied operation on each of the transactional workspace caches associated with the supplied transaction.
+ *
+ * @param txn the transaction; may not be null
+ * @param operation the operation to call on each {@link TransactionalWorkspaceCache} in the given transaction; may not be
+ * null
+ */
+ synchronized void onAllWorkspacesInTransaction( final Transaction txn,
+ final OnEachTransactionalCache operation ) {
+ assert operation != null;
+ assert txn != null;
+ Map<String, TransactionalWorkspaceCache> cachesForTxn = transactionalCachesByTransaction.get(txn);
+ if (cachesForTxn != null) {
+ for (TransactionalWorkspaceCache cache : cachesForTxn.values()) {
+ if (cache != null) operation.execute(cache);
+ }
+ }
+ }
+
+ /**
+ * See #onAllWorkspacesInTransaction
+ */
+ static interface OnEachTransactionalCache {
+ /**
+ * Invoke the operation on the supplied cache
+ *
+ * @param cache the transactional workspace cache; never null
+ */
+ void execute( TransactionalWorkspaceCache cache );
+ }
+
protected TransactionalWorkspaceCache createCache( WorkspaceCache sharedWorkspaceCache,
final Transaction txn ) throws SystemException, RollbackException {
- final TransactionalWorkspaceCache cache = new TransactionalWorkspaceCache(sharedWorkspaceCache);
+ final TransactionalWorkspaceCache cache = new TransactionalWorkspaceCache(sharedWorkspaceCache, this, txn);
txn.registerSynchronization(new Synchronization() {
@Override

0 comments on commit 93b1c48

Please sign in to comment.