[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