Author: manik.surtani(a)jboss.com
Date: 2008-10-08 05:30:07 -0400 (Wed, 08 Oct 2008)
New Revision: 6858
Added:
core/branches/flat/src/main/java/org/jboss/starobrno/lock/
core/branches/flat/src/main/java/org/jboss/starobrno/lock/LockManager.java
core/branches/flat/src/main/java/org/jboss/starobrno/lock/StripedLockManager.java
Log:
Updated lock manager
Added: core/branches/flat/src/main/java/org/jboss/starobrno/lock/LockManager.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/lock/LockManager.java
(rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/lock/LockManager.java 2008-10-08
09:30:07 UTC (rev 6858)
@@ -0,0 +1,136 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2000 - 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.jboss.starobrno.lock;
+
+import org.jboss.starobrno.context.InvocationContext;
+
+/**
+ * An interface to deal with all aspects of acquiring and releasing locks for nodes in
the cache.
+ *
+ * @author Manik Surtani (<a
href="mailto:manik@jboss.org">manik@jboss.org</a>)
+ * @since 2.2.0
+ */
+public interface LockManager
+{
+ /**
+ * Determines the owner to be used when obtaining locks, given an invocation context.
This is typically a {@link org.jboss.cache.transaction.GlobalTransaction} if one
+ * is present in the context, or {@link Thread#currentThread()} if one is not
present.
+ *
+ * @param ctx invocation context
+ * @return owner to be used for acquiring locks.
+ */
+ Object getLockOwner(InvocationContext ctx);
+
+ /**
+ * Acquires a lock of type lockType, for a given owner, on a specific Node in the
cache, denoted by fqn. This
+ * method will try for {@link
org.jboss.cache.config.Configuration#getLockAcquisitionTimeout()} milliseconds and give up
if it is unable to acquire the required lock.
+ *
+ * @param fqn Fqn to lock
+ * @param lockType type of lock to acquire
+ * @param owner owner to acquire the lock for
+ * @return true if the lock was acquired, false otherwise.
+ */
+ boolean lock(Object key, Object owner) throws InterruptedException;
+
+ /**
+ * Acquires a lock of type lockType, for a given owner, on a specific Node in the
cache, denoted by fqn. This
+ * method will try for timeout milliseconds and give up if it is unable to acquire the
required lock.
+ *
+ * @param fqn Fqn to lock
+ * @param lockType type of lock to acquire
+ * @param owner owner to acquire the lock for
+ * @param timeout maximum length of time to wait for (in millis)
+ * @return true if the lock was acquired, false otherwise.
+ */
+ boolean lock(Object key, Object owner, long timeout) throws InterruptedException;
+
+ /**
+ * Acquires a lock of type lockType, on a specific Node in the cache, denoted by fqn.
This
+ * method will try for a period of time and give up if it is unable to acquire the
required lock. The period of time
+ * is specified in {@link org.jboss.cache.config.Option#getLockAcquisitionTimeout()}
and, if this is unset, the default timeout
+ * set in {@link org.jboss.cache.config.Configuration#getLockAcquisitionTimeout()} is
used.
+ * <p/>
+ * In addition, any locks acquired are added to the context OR transaction entry using
{@link org.jboss.cache.InvocationContext#addLock(Object)}.
+ * <p/>
+ * The owner for the lock is determined by passing the invocation context to {@link
#getLockOwner(org.jboss.cache.InvocationContext)}.
+ * <p/>
+ *
+ * @param fqn Fqn to lock
+ * @param lockType type of lock to acquire
+ * @param ctx invocation context associated with this invocation
+ * @return true if the lock was acquired, false otherwise.
+ */
+ boolean lockAndRecord(Object key, InvocationContext ctx) throws InterruptedException;
+
+ /**
+ * Releases the lock passed in, held by the specified owner
+ *
+ * @param fqn Fqn of the node to unlock
+ * @param owner lock owner
+ */
+ void unlock(Object key, Object owner);
+
+ /**
+ * Releases locks present in an invocation context and transaction entry, if one is
available.
+ * <p/>
+ * Locks are released in reverse order of which they are acquired and registered.
+ * <p/>
+ * Lock owner is determined by passing the invocation context to {@link
#getLockOwner(org.jboss.cache.InvocationContext)}
+ * <p/>
+ *
+ * @param ctx invocation context to inspect
+ */
+ void unlock(InvocationContext ctx);
+
+ /**
+ * Tests whether a given owner owns a lock of lockType on a particular Fqn.
+ *
+ * @param fqn fqn to test
+ * @param lockType type of lock to test for
+ * @param owner owner
+ * @return true if the owner does own the specified lock type on the specified node,
false otherwise.
+ */
+ boolean ownsLock(Object key, Object owner);
+
+ /**
+ * Returns true if the node is locked (either for reading or writing) by anyone, and
false otherwise.
+ *
+ * @param n node to inspect
+ * @return true of locked; false if not.
+ */
+ boolean isLocked(Object key);
+
+ /**
+ * Retrieves the write lock owner, if any, for the current Fqn.
+ *
+ * @param f Fqn to inspect
+ * @return the owner of the lock, or null if not locked.
+ */
+ Object getOwner(Object key);
+
+ /**
+ * Prints lock information for all locks.
+ *
+ * @return lock information
+ */
+ String printLockInfo();
+}
Added: core/branches/flat/src/main/java/org/jboss/starobrno/lock/StripedLockManager.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/lock/StripedLockManager.java
(rev 0)
+++
core/branches/flat/src/main/java/org/jboss/starobrno/lock/StripedLockManager.java 2008-10-08
09:30:07 UTC (rev 6858)
@@ -0,0 +1,164 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.jboss.starobrno.lock;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.cache.config.Configuration;
+import org.jboss.cache.factories.annotations.Inject;
+import org.jboss.cache.factories.annotations.Start;
+import org.jboss.cache.invocation.InvocationContextContainer;
+import org.jboss.cache.lock.MVCCLockManager;
+import org.jboss.cache.util.concurrent.locks.LockContainer;
+import org.jboss.cache.util.concurrent.locks.OwnableReentrantLock;
+import org.jboss.cache.util.concurrent.locks.OwnableReentrantLockContainer;
+import org.jboss.cache.util.concurrent.locks.ReentrantLockContainer;
+import org.jboss.starobrno.context.InvocationContext;
+
+import javax.transaction.TransactionManager;
+import java.util.List;
+import java.util.ListIterator;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import java.util.concurrent.locks.Lock;
+
+/**
+ * // TODO: MANIK: Document this
+ *
+ * @author Manik Surtani (<a
href="mailto:manik@jboss.org">manik@jboss.org</a>)
+ * @since 3.0
+ */
+public class StripedLockManager implements LockManager
+{
+ protected Configuration configuration;
+ protected long lockAcquisitionTimeout;
+ LockContainer<Object> lockContainer;
+ private TransactionManager transactionManager;
+ private InvocationContextContainer invocationContextContainer;
+ private static final Log log = LogFactory.getLog(MVCCLockManager.class);
+ private static final boolean trace = log.isTraceEnabled();
+
+ @Inject
+ public void injectDependencies(Configuration configuration, TransactionManager
transactionManager, InvocationContextContainer invocationContextContainer)
+ {
+ this.configuration = configuration;
+ this.transactionManager = transactionManager;
+ this.invocationContextContainer = invocationContextContainer;
+ }
+
+ @Start
+ public void startLockManager()
+ {
+ this.lockAcquisitionTimeout = configuration.getLockAcquisitionTimeout();
+ lockContainer = transactionManager == null ? new
ReentrantLockContainer<Object>(configuration.getConcurrencyLevel()) : new
OwnableReentrantLockContainer<Object>(configuration.getConcurrencyLevel(),
invocationContextContainer);
+ }
+
+ public Object getLockOwner(InvocationContext ctx)
+ {
+ return ctx.getGlobalTransaction() != null ? ctx.getGlobalTransaction() :
Thread.currentThread();
+ }
+
+ public boolean lock(Object key, Object owner) throws InterruptedException
+ {
+ if (trace) log.trace("Attempting to lock " + key);
+ Lock lock = lockContainer.getLock(key);
+ return lock.tryLock(lockAcquisitionTimeout, MILLISECONDS);
+ }
+
+ public boolean lock(Object key, Object owner, long timeoutMillis) throws
InterruptedException
+ {
+ if (trace) log.trace("Attempting to lock " + key);
+ Lock lock = lockContainer.getLock(key);
+ return lock.tryLock(timeoutMillis, MILLISECONDS);
+ }
+
+ public boolean lockAndRecord(Object key, InvocationContext ctx) throws
InterruptedException
+ {
+ if (trace) log.trace("Attempting to lock " + key);
+ Lock lock = lockContainer.getLock(key);
+ if (lock.tryLock(ctx.getLockAcquisitionTimeout(lockAcquisitionTimeout),
MILLISECONDS))
+ {
+ ctx.addKeyLocked(key);
+ return true;
+ }
+
+ // couldn't acquire lock!
+ return false;
+ }
+
+ public void unlock(Object key, Object owner)
+ {
+ if (trace) log.trace("Attempting to unlock " + key);
+ Lock lock = lockContainer.getLock(key);
+ lock.unlock();
+ }
+
+ @SuppressWarnings("unchecked")
+ public void unlock(InvocationContext ctx)
+ {
+ List<Object> locks = ctx.getKeysLocked();
+ if (!locks.isEmpty())
+ {
+ // unlocking needs to be done in reverse order.
+ ListIterator<Object> it = locks.listIterator(locks.size());
+ while (it.hasPrevious())
+ {
+ Object k = it.previous();
+ if (trace) log.trace("Attempting to unlock " + k);
+ lockContainer.getLock(k).unlock();
+ }
+ }
+ }
+
+ public boolean ownsLock(Object key, Object owner)
+ {
+ return lockContainer.ownsLock(key, owner);
+ }
+
+ public boolean isLocked(Object key)
+ {
+ return lockContainer.isLocked(key);
+ }
+
+ public Object getOwner(Object key)
+ {
+ if (lockContainer.isLocked(key))
+ {
+ Lock l = lockContainer.getLock(key);
+
+ if (l instanceof OwnableReentrantLock)
+ {
+ return ((OwnableReentrantLock) l).getOwner();
+ }
+ else
+ {
+ // cannot determine owner.
+ return null;
+ }
+ }
+ else return null;
+ }
+
+ public String printLockInfo()
+ {
+ return lockContainer.toString();
+ }
+}