From jbosscache-commits at lists.jboss.org Wed Jun 25 09:23:13 2008 Content-Type: multipart/mixed; boundary="===============6437236348717531897==" MIME-Version: 1.0 From: jbosscache-commits at lists.jboss.org To: jbosscache-commits at lists.jboss.org Subject: [jbosscache-commits] JBoss Cache SVN: r6028 - in core/trunk/src/main/java/org/jboss/cache: transaction and 1 other directory. Date: Wed, 25 Jun 2008 09:23:13 -0400 Message-ID: --===============6437236348717531897== Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Author: manik.surtani(a)jboss.com Date: 2008-06-25 09:23:13 -0400 (Wed, 25 Jun 2008) New Revision: 6028 Modified: core/trunk/src/main/java/org/jboss/cache/InvocationContext.java core/trunk/src/main/java/org/jboss/cache/transaction/TransactionEntry.ja= va Log: Updated interface methods to simplify collection and recording of locks. Modified: core/trunk/src/main/java/org/jboss/cache/InvocationContext.java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- core/trunk/src/main/java/org/jboss/cache/InvocationContext.java 2008-06= -25 13:21:38 UTC (rev 6027) +++ core/trunk/src/main/java/org/jboss/cache/InvocationContext.java 2008-06= -25 13:23:13 UTC (rev 6028) @@ -18,8 +18,11 @@ = import javax.transaction.Transaction; import java.util.ArrayList; -import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashSet; import java.util.List; +import java.util.Map; = /** * This context holds information specific to a method invocation. @@ -27,7 +30,7 @@ * @author Manik Surtani (manik(a)jbo= ss.org) */ @SuppressWarnings("deprecation") -public class InvocationContext implements Cloneable +public class InvocationContext { private static final Log log =3D LogFactory.getLog(InvocationContext.cl= ass); private static final boolean trace =3D log.isTraceEnabled(); @@ -44,46 +47,39 @@ private MethodCall methodCall; @Deprecated private VisitableCommand command; - List invocationLocks; = - // used to store cache peeks within the scope of a single context. Perf= orming a cache peek can be a huge bottle neck. - // See JBCACHE-811 - // backing out for now - //private Map peekedNodes =3D new HashMap(); - /** - * Retrieves a node that may have previously been "peeked" within the s= cope of the same invocation. - * - * @param f fqn of node to find - * @return node, if previously peeked, or null if not. - * @since 2.1.0 + * LinkedHashSet of locks acquired by the invocation. We use a LinkedHa= shSet because we need efficient Set semantics + * but also need guaranteed ordering for use by lock release code (see = JBCCACHE-874). + *

+ * This needs to be unchecked since we support both MVCC (Fqns held her= e) or legacy Opt/Pess locking (NodeLocks held here). + * once we drop support for opt/pess locks we can genericise this to co= ntain Fqns. - Manik Surtani, June 2008 */ -// public NodeSPI getPeekedNode(Fqn f) -// { -// return peekedNodes.get(f); -// } + private LinkedHashSet invocationLocks; = - /** - * Adds a node to the previously peeked list. - * - * @param n node to add - * @param f fqn of node - * @since 2.1.0 - */ -// public void savePeekedNode(NodeSPI n, Fqn f) -// { -// peekedNodes.put(f, n); -// } + private final Map lookedUpNodes =3D new HashMap(); = - /** - * Wipe list of previously peeked nodes. - * - * @since 2.1.0 - */ -// public void wipePeekedNodes() -// { -// peekedNodes.clear(); -// } + public NodeSPI lookUpNode(Fqn fqn) + { + // TODO: should delegate to TransactionEntry if one is in scope + return lookedUpNodes.get(fqn); + } + + public void putLookedUpNode(Fqn f, NodeSPI n) + { + lookedUpNodes.put(f, n); + } + + public void clearLookedUpNodes() + { + lookedUpNodes.clear(); + } + + public Map getLookedUpNodes() + { + return lookedUpNodes; + } + public void setLocalRollbackOnly(boolean localRollbackOnly) { this.localRollbackOnly =3D localRollbackOnly; @@ -188,26 +184,139 @@ return originLocal; } = - public List getInvocationLocksAcquired() + /** + * Returns an immutable, defensive copy of the List of locks currently= maintained for the current scope. + *

+ * Note that if a transaction is in scope, these locks are retrieved fr= om the {@link org.jboss.cache.transaction.TransactionEntry} rather than + * this {@link org.jboss.cache.InvocationContext}. Retrieving locks fr= om here will ensure they are retrieved from the appropriate + * scope. + *

+ * Note that currently (as of 3.0.0) this list is unchecked. This is t= o allow support for both MVCC (which uses Fqns as locks) + * as well as legacy Optimistic and Pessimistic Locking schemes (which = use {@link NodeLock} as locks). Once support for + * legacy node locking schemes are dropped, this method will be more st= rongly typed to return List. + * + * @return locks held in current scope. + */ + @SuppressWarnings("unchecked") + public List getLocks() { - return invocationLocks; + // first check transactional scope + if (transactionEntry !=3D null) return transactionEntry.getLocks(); + return Collections.unmodifiableList(new ArrayList(invocationLocks)); } = - public void addInvocationLocksAcquired(Collection locks) + /** + * Adds a List of locks to the currently maintained collection of locks= acquired. + *

+ * Note that if a transaction is in scope, these locks are recorded on = the {@link org.jboss.cache.transaction.TransactionEntry} rather than + * this {@link org.jboss.cache.InvocationContext}. Adding locks here w= ill ensure they are promoted to the appropriate + * scope. + *

+ * Note that currently (as of 3.0.0) this list is unchecked. This is t= o allow support for both MVCC (which uses Fqns as locks) + * as well as legacy Optimistic and Pessimistic Locking schemes (which = use {@link NodeLock} as locks). Once support for + * legacy node locking schemes are dropped, this method will be more st= rongly typed to accept List. + * + * @param locks locks to add + */ + @SuppressWarnings("unchecked") + public void addAllLocks(List locks) { - // no need to worry about concurrency here - a context is only valid= for a single thread. - if (invocationLocks =3D=3D null) invocationLocks =3D new ArrayList(5); - invocationLocks.addAll(locks); + // first check transactional scope + if (transactionEntry !=3D null) + { + transactionEntry.addAllLocks(locks); + } + else + { + // no need to worry about concurrency here - a context is only va= lid for a single thread. + if (invocationLocks =3D=3D null) invocationLocks =3D new LinkedHa= shSet(5); + invocationLocks.addAll(locks); + } } = - public void addInvocationLockAcquired(NodeLock l) + /** + * Adds a lock to the currently maintained collection of locks acquired. + *

+ * Note that if a transaction is in scope, this lock is recorded on the= {@link org.jboss.cache.transaction.TransactionEntry} rather than + * this {@link org.jboss.cache.InvocationContext}. Adding a lock here = will ensure it is promoted to the appropriate + * scope. + *

+ * Note that currently (as of 3.0.0) this lock is weakly typed. This i= s to allow support for both MVCC (which uses {@link Fqn}s as locks) + * as well as legacy Optimistic and Pessimistic Locking schemes (which = use {@link NodeLock} as locks). Once support for + * legacy node locking schemes are dropped, this method will be more st= rongly typed to accept {@link Fqn}. + * + * @param lock lock to add + */ + @SuppressWarnings("unchecked") + public void addLock(Object lock) { - // no need to worry about concurrency here - a context is only valid= for a single thread. - if (invocationLocks =3D=3D null) invocationLocks =3D new ArrayList(5); - invocationLocks.add(l); + // first check transactional scope + if (transactionEntry !=3D null) + { + transactionEntry.addLock(lock); + } + else + { + // no need to worry about concurrency here - a context is only va= lid for a single thread. + if (invocationLocks =3D=3D null) invocationLocks =3D new LinkedHa= shSet(5); + invocationLocks.add(lock); + } } = /** + * Removes a lock from the currently maintained collection of locks acq= uired. + *

+ * Note that if a transaction is in scope, this lock is removed from th= e {@link org.jboss.cache.transaction.TransactionEntry} rather than + * this {@link org.jboss.cache.InvocationContext}. Removing a lock her= e will ensure it is removed in the appropriate + * scope. + *

+ * Note that currently (as of 3.0.0) this lock is weakly typed. This i= s to allow support for both MVCC (which uses {@link Fqn}s as locks) + * as well as legacy Optimistic and Pessimistic Locking schemes (which = use {@link NodeLock} as locks). Once support for + * legacy node locking schemes are dropped, this method will be more st= rongly typed to accept {@link Fqn}. + * + * @param lock lock to remove + */ + @SuppressWarnings("unchecked") + public void removeLock(Object lock) + { + // first check transactional scope + if (transactionEntry !=3D null) + { + transactionEntry.removeLock(lock); + } + else + { + // no need to worry about concurrency here - a context is only va= lid for a single thread. + if (invocationLocks !=3D null) invocationLocks.remove(lock); + } + } + + /** + * Clears all locks from the currently maintained collection of locks a= cquired. + *

+ * Note that if a transaction is in scope, locks are cleared from the {= @link org.jboss.cache.transaction.TransactionEntry} rather than + * this {@link org.jboss.cache.InvocationContext}. Clearing locks here= will ensure they are cleared in the appropriate + * scope. + *

+ * Note that currently (as of 3.0.0) this lock is weakly typed. This i= s to allow support for both MVCC (which uses {@link Fqn}s as locks) + * as well as legacy Optimistic and Pessimistic Locking schemes (which = use {@link NodeLock} as locks). Once support for + * legacy node locking schemes are dropped, this method will be more st= rongly typed to accept {@link Fqn}. + */ + public void clearLocks() + { + // first check transactional scope + if (transactionEntry !=3D null) + { + transactionEntry.clearLocks(); + } + else + { + // no need to worry about concurrency here - a context is only va= lid for a single thread. + if (invocationLocks !=3D null) invocationLocks.clear(); + } + } + + /** * @return true if options exist to suppress locking - false otherwise.= Note that this is only used by the {@link org.jboss.cache.interceptors.Pe= ssimisticLockInterceptor}. */ public boolean isLockingSuppressed() @@ -268,12 +377,20 @@ command =3D null; } = - @Override - public InvocationContext clone() throws CloneNotSupportedException + /** + * This is a "copy-factory-method" that should be used whenever a clone= of this class is needed. The resulting instance + * is equal() to, but not =3D=3D, to the template passed in. + * + * @param template template to copy + * @return a new InvocationContext + */ + public static InvocationContext copy(InvocationContext template) { - InvocationContext clone =3D (InvocationContext) super.clone(); - clone.setOptionOverrides(getOptionOverrides().clone()); - return clone; + // TODO: Remove all use of cloning and replace with copy factory met= hods. +// InvocationContext clone =3D (InvocationContext) super.clone(); +// clone.setOptionOverrides(getOptionOverrides().clone()); +// return clone; + return null; } = /** Modified: core/trunk/src/main/java/org/jboss/cache/transaction/TransactionE= ntry.java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- core/trunk/src/main/java/org/jboss/cache/transaction/TransactionEntry.j= ava 2008-06-25 13:21:38 UTC (rev 6027) +++ core/trunk/src/main/java/org/jboss/cache/transaction/TransactionEntry.j= ava 2008-06-25 13:23:13 UTC (rev 6028) @@ -12,6 +12,7 @@ import org.apache.commons.logging.LogFactory; import org.jboss.cache.Fqn; import org.jboss.cache.Modification; +import org.jboss.cache.NodeSPI; import org.jboss.cache.commands.ReversibleCommand; import org.jboss.cache.config.Option; import org.jboss.cache.interceptors.OrderedSynchronizationHandler; @@ -22,12 +23,13 @@ import javax.transaction.SystemException; import javax.transaction.Transaction; import java.util.ArrayList; -import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.ListIterator; +import java.util.Map; = /** * Information associated with a {@link GlobalTransaction} about the trans= action state. @@ -72,13 +74,16 @@ private List localModifications; = /** - * LinkedHashSet of locks acquired by the transaction. We= use - * a LinkedHashSet because we need efficient Set semantics (same lock c= an - * be added multiple times) but also need guaranteed ordering for use - * by lock release code (see JBCCACHE-874). + * LinkedHashSet of locks acquired by the transaction. We use a LinkedH= ashSet because we need efficient Set semantics + * but also need guaranteed ordering for use by lock release code (see = JBCCACHE-874). + *

+ * This needs to be unchecked since we support both MVCC (Fqns held her= e) or legacy Opt/Pess locking (NodeLocks held here). + * once we drop support for opt/pess locks we can genericise this to co= ntain Fqns. - Manik Surtani, June 2008 */ - private final LinkedHashSet locks =3D new LinkedHashSet(); + private LinkedHashSet transactionLocks; + private final Map lookedUpNodes =3D new HashMap(); = + /** * A list of dummy uninitialised nodes created by the cache loader inte= rceptor to load data for a * given node in this tx. @@ -170,49 +175,106 @@ } = /** - * Adds a lock to the end of the lock list, if it isn't already present. + * Adds a lock to the currently maintained collection of locks acquired. + *

+ * Most code could not use this method directly, but use {@link org.jbo= ss.cache.InvocationContext#addLock(Object)} instead, + * which would delegate to this method if a transaction is in scope or = otherwise use invocation-specific locks. + *

+ * Note that currently (as of 3.0.0) this lock is weakly typed. This i= s to allow support for both MVCC (which uses {@link Fqn}s as locks) + * as well as legacy Optimistic and Pessimistic Locking schemes (which = use {@link NodeLock} as locks). Once support for + * legacy node locking schemes are dropped, this method will be more st= rongly typed to accept {@link Fqn}. + * + * @param lock lock to add + * @see org.jboss.cache.InvocationContext#addLock(Object) */ - public void addLock(NodeLock l) + @SuppressWarnings("unchecked") + public void addLock(Object lock) { - if (l !=3D null) - { - synchronized (locks) - { - locks.add(l); - } - } + // no need to worry about concurrency here - a context is only valid= for a single thread. + if (transactionLocks =3D=3D null) transactionLocks =3D new LinkedHas= hSet(5); + transactionLocks.add(lock); } = /** - * Add multiple locks to the lock list. + * Removes a lock from the currently maintained collection of locks acq= uired. + *

+ * Most code could not use this method directly, but use {@link org.jbo= ss.cache.InvocationContext#removeLock(Object)} instead, + * which would delegate to this method if a transaction is in scope or = otherwise use invocation-specific locks. + *

+ * Note that currently (as of 3.0.0) this lock is weakly typed. This i= s to allow support for both MVCC (which uses {@link Fqn}s as locks) + * as well as legacy Optimistic and Pessimistic Locking schemes (which = use {@link NodeLock} as locks). Once support for + * legacy node locking schemes are dropped, this method will be more st= rongly typed to accept {@link Fqn}. * - * @param newLocks Collection + * @param lock lock to remove + * @see org.jboss.cache.InvocationContext#removeLock(Object) */ - public void addLocks(Collection newLocks) + @SuppressWarnings("unchecked") + public void removeLock(Object lock) { - if (newLocks !=3D null) - { - synchronized (locks) - { - locks.addAll(newLocks); - } - } + // no need to worry about concurrency here - a context is only valid= for a single thread. + if (transactionLocks !=3D null) transactionLocks.remove(lock); } = /** - * Returns the locks in use. + * Clears all locks from the currently maintained collection of locks a= cquired. + *

+ * Most code could not use this method directly, but use {@link org.jbo= ss.cache.InvocationContext#clearLocks()} instead, + * which would delegate to this method if a transaction is in scope or = otherwise use invocation-specific locks. + *

+ * Note that currently (as of 3.0.0) this lock is weakly typed. This i= s to allow support for both MVCC (which uses {@link Fqn}s as locks) + * as well as legacy Optimistic and Pessimistic Locking schemes (which = use {@link NodeLock} as locks). Once support for + * legacy node locking schemes are dropped, this method will be more st= rongly typed to accept {@link Fqn}. * - * @return a defensive copy of the internal data structure. + * @see org.jboss.cache.InvocationContext#clearLocks() */ - public List getLocks() + public void clearLocks() { - synchronized (locks) - { - return new ArrayList(locks); - } + if (transactionLocks !=3D null) transactionLocks.clear(); } = + /** + * Adds a List of locks to the currently maintained collection of locks= acquired. + *

+ * Most code could not use this method directly, but use {@link org.jbo= ss.cache.InvocationContext#addAllLocks(java.util.List)} instead, + * which would delegate to this method if a transaction is in scope or = otherwise use invocation-specific locks. + *

+ * Note that currently (as of 3.0.0) this list is unchecked. This is t= o allow support for both MVCC (which uses Fqns as locks) + * as well as legacy Optimistic and Pessimistic Locking schemes (which = use {@link NodeLock} as locks). Once support for + * legacy node locking schemes are dropped, this method will be more st= rongly typed to accept List. + * + * @param newLocks locks to add + * @see org.jboss.cache.InvocationContext#addAllLocks(java.util.List) + */ + @SuppressWarnings("unchecked") + public void addAllLocks(List newLocks) + { + // no need to worry about concurrency here - a context is only valid= for a single thread. + if (transactionLocks =3D=3D null) transactionLocks =3D new LinkedHas= hSet(5); + transactionLocks.addAll(newLocks); + } + + /** + * Returns an immutable, defensive copy of the List of locks currently= maintained for the transaction. + *

+ * Most code could not use this method directly, but use {@link org.jbo= ss.cache.InvocationContext#getLocks()} instead, + * which would delegate to this method if a transaction is in scope or = otherwise use invocation-specific locks. + *

+ * Note that currently (as of 3.0.0) this list is unchecked. This is t= o allow support for both MVCC (which uses Fqns as locks) + * as well as legacy Optimistic and Pessimistic Locking schemes (which = use {@link NodeLock} as locks). Once support for + * legacy node locking schemes are dropped, this method will be more st= rongly typed to return List. + * + * @return locks held in current scope. + * @see org.jboss.cache.InvocationContext#getLocks() + */ + @SuppressWarnings("unchecked") + public List getLocks() + { + return Collections.unmodifiableList(new ArrayList(transactionLocks)); + } + + + /** * Gets the value of the forceAsyncReplication flag. Used by Replicati= onInterceptor and OptimisticReplicationInterceptor * when dealing with {@link org.jboss.cache.Cache#putForExternalRead(or= g.jboss.cache.Fqn,Object,Object)} within * a transactional context. @@ -305,12 +367,8 @@ @Override public String toString() { - StringBuffer sb =3D new StringBuffer(); + StringBuilder sb =3D new StringBuilder(); sb.append("TransactionEntry\nmodificationList: ").append(modificatio= nList); - synchronized (locks) - { - sb.append("\nlocks: ").append(locks); - } return sb.toString(); } = @@ -370,7 +428,27 @@ return localModifications !=3D null && !localModifications.isEmpty(); } = + public NodeSPI lookUpNode(Fqn fqn) + { + return lookedUpNodes.get(fqn); + } = + public void putLookedUpNode(Fqn f, NodeSPI n) + { + lookedUpNodes.put(f, n); + } + + public void clearLookedUpNodes() + { + lookedUpNodes.clear(); + } + + public Map getLookedUpNodes() + { + return lookedUpNodes; + } + + /** * Cleans up internal state */ @@ -380,7 +458,7 @@ if (modificationList !=3D null) modificationList =3D null; if (localModifications !=3D null) localModifications =3D null; option =3D null; - locks.clear(); + transactionLocks.clear(); if (dummyNodesCreatedByCacheLoader !=3D null) dummyNodesCreatedByCac= heLoader.clear(); removedNodes.clear(); } --===============6437236348717531897==--