[jbosscache-commits] JBoss Cache SVN: r6872 - in core/branches/flat/src/main/java/org/jboss/starobrno: interceptors and 1 other directory.
jbosscache-commits at lists.jboss.org
jbosscache-commits at lists.jboss.org
Wed Oct 8 09:26:45 EDT 2008
Author: manik.surtani at jboss.com
Date: 2008-10-08 09:26:45 -0400 (Wed, 08 Oct 2008)
New Revision: 6872
Added:
core/branches/flat/src/main/java/org/jboss/starobrno/interceptors/LockingInterceptor.java
Modified:
core/branches/flat/src/main/java/org/jboss/starobrno/commands/write/PutMapCommand.java
Log:
Fixed locking interceptor
Modified: core/branches/flat/src/main/java/org/jboss/starobrno/commands/write/PutMapCommand.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/commands/write/PutMapCommand.java 2008-10-08 13:04:49 UTC (rev 6871)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/commands/write/PutMapCommand.java 2008-10-08 13:26:45 UTC (rev 6872)
@@ -62,6 +62,11 @@
return null;
}
+ public Map<Object, Object> getMap()
+ {
+ return map;
+ }
+
public int getCommandId()
{
return METHOD_ID;
Added: core/branches/flat/src/main/java/org/jboss/starobrno/interceptors/LockingInterceptor.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/interceptors/LockingInterceptor.java (rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/interceptors/LockingInterceptor.java 2008-10-08 13:26:45 UTC (rev 6872)
@@ -0,0 +1,266 @@
+/*
+ * 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.interceptors;
+
+import org.jboss.starobrno.DataContainer;
+import org.jboss.starobrno.commands.VisitableCommand;
+import org.jboss.starobrno.commands.read.GetKeyValueCommand;
+import org.jboss.starobrno.commands.read.GravitateDataCommand;
+import org.jboss.starobrno.commands.read.SizeCommand;
+import org.jboss.starobrno.commands.tx.CommitCommand;
+import org.jboss.starobrno.commands.tx.PrepareCommand;
+import org.jboss.starobrno.commands.tx.RollbackCommand;
+import org.jboss.starobrno.commands.write.ClearCommand;
+import org.jboss.starobrno.commands.write.EvictCommand;
+import org.jboss.starobrno.commands.write.PutKeyValueCommand;
+import org.jboss.starobrno.commands.write.PutMapCommand;
+import org.jboss.starobrno.commands.write.RemoveCommand;
+import org.jboss.starobrno.commands.write.ReplaceCommand;
+import org.jboss.starobrno.context.InvocationContext;
+import org.jboss.starobrno.factories.annotations.Inject;
+import org.jboss.starobrno.interceptors.base.PrePostProcessingCommandInterceptor;
+import org.jboss.starobrno.lock.LockManager;
+import org.jboss.starobrno.mvcc.MVCCEntry;
+import org.jboss.starobrno.mvcc.MVCCEntryWrapper;
+
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map.Entry;
+
+/**
+ * Interceptor to implement <a href="http://wiki.jboss.org/wiki/JBossCacheMVCC">MVCC</a> functionality.
+ *
+ * @author Manik Surtani (<a href="mailto:manik at jboss.org">manik at jboss.org</a>)
+ * @see <a href="http://wiki.jboss.org/wiki/JBossCacheMVCC">MVCC designs</a>
+ * @since 3.0
+ */
+public class LockingInterceptor extends PrePostProcessingCommandInterceptor
+{
+ LockManager lockManager;
+ DataContainer dataContainer;
+ MVCCEntryWrapper entryWrapper;
+
+ @Inject
+ public void setDependencies(LockManager lockManager, DataContainer dataContainer, MVCCEntryWrapper entryWrapper)
+ {
+ this.lockManager = lockManager;
+ this.dataContainer = dataContainer;
+ this.entryWrapper = entryWrapper;
+ }
+
+ @Override
+ protected boolean doBeforeCall(InvocationContext ctx, VisitableCommand command)
+ {
+ if (ctx.getOptionOverrides().isSuppressLocking())
+ {
+ if (log.isWarnEnabled()) log.warn("Lock suppression not supported with MVCC!");
+ }
+ return true;
+ }
+
+ @Override
+ public Object handleCommitCommand(InvocationContext ctx, CommitCommand command) throws Throwable
+ {
+ try
+ {
+ return invokeNextInterceptor(ctx, command);
+ }
+ finally
+ {
+ transactionalCleanup(true, ctx);
+ }
+ }
+
+ @Override
+ public Object handleRollbackCommand(InvocationContext ctx, RollbackCommand command) throws Throwable
+ {
+ try
+ {
+ return invokeNextInterceptor(ctx, command);
+ }
+ finally
+ {
+ transactionalCleanup(false, ctx);
+ }
+ }
+
+ @Override
+ public Object handlePrepareCommand(InvocationContext ctx, PrepareCommand command) throws Throwable
+ {
+ try
+ {
+ return invokeNextInterceptor(ctx, command);
+ }
+ finally
+ {
+ if (command.isOnePhaseCommit()) transactionalCleanup(true, ctx);
+ }
+ }
+
+ // read commands
+
+ @Override
+ public Object handleGetKeyValueCommand(InvocationContext ctx, GetKeyValueCommand command) throws Throwable
+ {
+ entryWrapper.wrapEntryForReading(ctx, command.getKey(), true);
+ return invokeNextInterceptor(ctx, command);
+ }
+
+ @Override
+ public Object handleSizeCommand(InvocationContext ctx, SizeCommand command) throws Throwable
+ {
+ if (log.isDebugEnabled()) log.debug("No locking performed for SizeCommands");
+ return invokeNextInterceptor(ctx, command);
+ }
+
+ // write commands
+
+ @Override
+ public Object handleClearCommand(InvocationContext ctx, ClearCommand command) throws Throwable
+ {
+ // get a snapshot of all keys in the data container
+ for (Object o : dataContainer.getEntries())
+ {
+ Object key = ((Entry) o).getKey();
+ entryWrapper.wrapEntryForWriting(ctx, key, false, false);
+ }
+
+ return invokeNextInterceptor(ctx, command);
+ }
+
+ @Override
+ public Object handleEvictCommand(InvocationContext ctx, EvictCommand command) throws Throwable
+ {
+ entryWrapper.wrapEntryForWriting(ctx, command.getKey(), false, true);
+ return invokeNextInterceptor(ctx, command);
+ }
+
+ @Override
+ public Object handlePutKeyValueCommand(InvocationContext ctx, PutKeyValueCommand command) throws Throwable
+ {
+ entryWrapper.wrapEntryForWriting(ctx, command.getKey(), true, false);
+ return invokeNextInterceptor(ctx, command);
+ }
+
+ @Override
+ public Object handlePutMapCommand(InvocationContext ctx, PutMapCommand command) throws Throwable
+ {
+ for (Object key : command.getMap().keySet())
+ {
+ entryWrapper.wrapEntryForWriting(ctx, key, true, false);
+ }
+ return invokeNextInterceptor(ctx, command);
+ }
+
+ @Override
+ public Object handleRemoveCommand(InvocationContext ctx, RemoveCommand command) throws Throwable
+ {
+ entryWrapper.wrapEntryForWriting(ctx, command.getKey(), false, true);
+ return invokeNextInterceptor(ctx, command);
+ }
+
+ @Override
+ public Object handleReplaceCommand(InvocationContext ctx, ReplaceCommand command) throws Throwable
+ {
+ entryWrapper.wrapEntryForWriting(ctx, command.getKey(), false, true);
+ return invokeNextInterceptor(ctx, command);
+ }
+
+ @Override
+ public Object handleGravitateDataCommand(InvocationContext ctx, GravitateDataCommand command) throws Throwable
+ {
+ entryWrapper.wrapEntryForReading(ctx, command.getKey(), true);
+ return invokeNextInterceptor(ctx, command);
+ }
+
+
+ @SuppressWarnings("unchecked")
+ protected void doAfterCall(InvocationContext ctx, VisitableCommand command)
+ {
+ // for non-transactional stuff.
+ if (ctx.getTransactionContext() == null)
+ {
+ List<Object> locks;
+ if (!(locks = ctx.getKeysLocked()).isEmpty())
+ {
+ cleanupLocks(locks, ctx, Thread.currentThread(), true);
+ }
+ else
+ {
+ if (trace) log.trace("Nothing to do since there are no modifications in scope.");
+ }
+ }
+ else
+ {
+ if (trace) log.trace("Nothing to do since there is a transaction in scope.");
+ }
+ }
+
+ private void cleanupLocks(List<Object> keysLocked, InvocationContext ctx, Object owner, boolean commit)
+ {
+ // clean up.
+ // unlocking needs to be done in reverse order.
+ ListIterator<Object> it = keysLocked.listIterator(keysLocked.size());
+
+ if (commit)
+ {
+ while (it.hasPrevious())
+ {
+ Object key = it.previous();
+ MVCCEntry entry = ctx.lookupEntry(key);
+ // could be null with read-committed
+ if (entry != null) entry.commitUpdate(ctx, dataContainer);
+ // and then unlock
+ if (trace) log.trace("Releasing lock on [" + key + "] for owner " + owner);
+ lockManager.unlock(key, owner);
+ }
+ }
+ else
+ {
+ while (it.hasPrevious())
+ {
+ Object key = it.previous();
+ MVCCEntry entry = ctx.lookupEntry(key);
+ // could be null with read-committed
+ if (entry != null) entry.rollbackUpdate();
+ // and then unlock
+ if (trace) log.trace("Releasing lock on [" + key + "] for owner " + owner);
+ lockManager.unlock(key, owner);
+ }
+ }
+ ctx.clearKeysLocked();
+ }
+
+ @SuppressWarnings("unchecked")
+ private void transactionalCleanup(boolean commit, InvocationContext ctx)
+ {
+ if (ctx.getTransactionContext() != null)
+ {
+ List<Object> locks = ctx.getTransactionContext().getKeysLocked();
+ if (!locks.isEmpty()) cleanupLocks(locks, ctx, ctx.getGlobalTransaction(), commit);
+ }
+ else
+ {
+ throw new IllegalStateException("Attempting to do a commit or rollback but there is no transactional context in scope. " + ctx);
+ }
+ }
+}
More information about the jbosscache-commits
mailing list