[infinispan-commits] Infinispan SVN: r990 - in trunk: core/src/main/java/org/infinispan/factories and 2 other directories.

infinispan-commits at lists.jboss.org infinispan-commits at lists.jboss.org
Fri Oct 23 10:10:13 EDT 2009


Author: mircea.markus
Date: 2009-10-23 10:10:13 -0400 (Fri, 23 Oct 2009)
New Revision: 990

Added:
   trunk/core/src/main/java/org/infinispan/container/EntryFactory.java
   trunk/core/src/main/java/org/infinispan/container/EntryFactoryImpl.java
Removed:
   trunk/core/src/main/java/org/infinispan/factories/EntryFactory.java
   trunk/core/src/main/java/org/infinispan/factories/EntryFactoryImpl.java
Modified:
   trunk/core/src/main/java/org/infinispan/factories/EmptyConstructorNamedCacheFactory.java
   trunk/core/src/main/java/org/infinispan/interceptors/CacheLoaderInterceptor.java
   trunk/core/src/main/java/org/infinispan/interceptors/LockingInterceptor.java
   trunk/lucene-directory/src/main/java/org/infinispan/lucene/InfinispanLockFactory.java
Log:
moved EntryFactory in the package

Copied: trunk/core/src/main/java/org/infinispan/container/EntryFactory.java (from rev 988, trunk/core/src/main/java/org/infinispan/factories/EntryFactory.java)
===================================================================
--- trunk/core/src/main/java/org/infinispan/container/EntryFactory.java	                        (rev 0)
+++ trunk/core/src/main/java/org/infinispan/container/EntryFactory.java	2009-10-23 14:10:13 UTC (rev 990)
@@ -0,0 +1,55 @@
+/*
+ * 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.infinispan.container;
+
+import org.infinispan.container.entries.CacheEntry;
+import org.infinispan.container.entries.MVCCEntry;
+import org.infinispan.context.InvocationContext;
+import org.infinispan.util.concurrent.TimeoutException;
+
+/**
+ * // TODO: MANIK: Document this
+ *
+ * @author Manik Surtani (<a href="mailto:manik at jboss.org">manik at jboss.org</a>)
+ * @since 4.0
+ */
+public interface EntryFactory {
+   void releaseLock(Object key);
+
+   /**
+    * Attempts to lock an entry if the lock isn't already held in the current scope, and records the lock in the
+    * context.
+    *
+    * @param ctx context
+    * @param key Key to lock
+    * @return true if a lock was needed and acquired, false if it didn't need to acquire the lock (i.e., lock was
+    *         already held)
+    * @throws InterruptedException if interrupted
+    * @throws org.infinispan.util.concurrent.TimeoutException
+    *                              if we are unable to acquire the lock after a specified timeout.
+    */
+   boolean acquireLock(InvocationContext ctx, Object key) throws InterruptedException, TimeoutException;
+
+   MVCCEntry wrapEntryForWriting(InvocationContext ctx, Object key, boolean createIfAbsent, boolean forceLockIfAbsent, boolean alreadyLocked, boolean forRemoval) throws InterruptedException;
+
+   CacheEntry wrapEntryForReading(InvocationContext ctx, Object key) throws InterruptedException;
+}


Property changes on: trunk/core/src/main/java/org/infinispan/container/EntryFactory.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Copied: trunk/core/src/main/java/org/infinispan/container/EntryFactoryImpl.java (from rev 989, trunk/core/src/main/java/org/infinispan/factories/EntryFactoryImpl.java)
===================================================================
--- trunk/core/src/main/java/org/infinispan/container/EntryFactoryImpl.java	                        (rev 0)
+++ trunk/core/src/main/java/org/infinispan/container/EntryFactoryImpl.java	2009-10-23 14:10:13 UTC (rev 990)
@@ -0,0 +1,238 @@
+/*
+ * 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.infinispan.container;
+
+import org.infinispan.config.Configuration;
+import org.infinispan.container.entries.CacheEntry;
+import org.infinispan.container.entries.MVCCEntry;
+import org.infinispan.container.entries.NullMarkerEntry;
+import org.infinispan.container.entries.NullMarkerEntryForRemoval;
+import org.infinispan.container.entries.ReadCommittedEntry;
+import org.infinispan.container.entries.RepeatableReadEntry;
+import org.infinispan.context.Flag;
+import org.infinispan.context.InvocationContext;
+import org.infinispan.factories.annotations.Inject;
+import org.infinispan.factories.annotations.Start;
+import org.infinispan.notifications.cachelistener.CacheNotifier;
+import org.infinispan.util.Util;
+import org.infinispan.util.concurrent.IsolationLevel;
+import org.infinispan.util.concurrent.TimeoutException;
+import org.infinispan.util.concurrent.locks.LockManager;
+import org.infinispan.util.logging.Log;
+import org.infinispan.util.logging.LogFactory;
+
+public class EntryFactoryImpl implements EntryFactory {
+   private boolean useRepeatableRead;
+   DataContainer container;
+   boolean writeSkewCheck;
+   LockManager lockManager;
+   Configuration configuration;
+   CacheNotifier notifier;
+
+   private static final Log log = LogFactory.getLog(EntryFactoryImpl.class);
+   private static final boolean trace = log.isTraceEnabled();
+
+   @Inject
+   public void injectDependencies(DataContainer dataContainer, LockManager lockManager, Configuration configuration, CacheNotifier notifier) {
+      this.container = dataContainer;
+      this.configuration = configuration;
+      this.lockManager = lockManager;
+      this.notifier = notifier;
+   }
+
+   @Start
+   public void init() {
+      useRepeatableRead = configuration.getIsolationLevel() == IsolationLevel.REPEATABLE_READ;
+      writeSkewCheck = configuration.isWriteSkewCheck();
+   }
+
+   private MVCCEntry createWrappedEntry(Object key, Object value, boolean isForInsert, boolean forRemoval, long lifespan) {
+      if (value == null && !isForInsert) return useRepeatableRead ?
+            forRemoval ? new NullMarkerEntryForRemoval(key) : NullMarkerEntry.getInstance()
+            : null;
+
+      return useRepeatableRead ? new RepeatableReadEntry(key, value, lifespan) : new ReadCommittedEntry(key, value, lifespan);
+   }
+
+   public final CacheEntry wrapEntryForReading(InvocationContext ctx, Object key) throws InterruptedException {
+      CacheEntry cacheEntry;
+      if (ctx.hasFlag(Flag.FORCE_WRITE_LOCK)) {
+         if (trace) log.trace("Forcing lock on reading");
+         return wrapEntryForWriting(ctx, key, false, false, false, false);
+      } else if ((cacheEntry = ctx.lookupEntry(key)) == null) {
+         if (trace) log.trace("Key {0} is not in context, fetching from container.", key);
+         // simple implementation.  Peek the entry, wrap it, put wrapped entry in the context.
+         cacheEntry = container.get(key);
+
+         // do not bother wrapping though if this is not in a tx.  repeatable read etc are all meaningless unless there is a tx.
+         if (useRepeatableRead && ctx.isInTxScope()) {
+            MVCCEntry mvccEntry = cacheEntry == null ?
+                     createWrappedEntry(key, null, false, false, -1) :
+                     createWrappedEntry(key, cacheEntry.getValue(), false, false, cacheEntry.getLifespan());
+               if (mvccEntry != null) ctx.putLookedUpEntry(key, mvccEntry);
+               return mvccEntry;
+         }
+         // if not in transaction and repeatable read, or simply read committed (regardless of whether in TX or not), do not wrap
+         if (cacheEntry != null) ctx.putLookedUpEntry(key, cacheEntry);
+            return cacheEntry;
+      } else {
+         if (trace) log.trace("Key is already in context");
+         return cacheEntry;
+      }
+   }
+
+   public final MVCCEntry wrapEntryForWriting(InvocationContext ctx, Object key, boolean createIfAbsent, boolean forceLockIfAbsent, boolean alreadyLocked, boolean forRemoval) throws InterruptedException {
+      CacheEntry cacheEntry = ctx.lookupEntry(key);
+      MVCCEntry mvccEntry = null;
+      if (createIfAbsent && cacheEntry != null && cacheEntry.isNull()) cacheEntry = null;
+      if (cacheEntry != null) // exists in context!  Just acquire lock if needed, and wrap.
+      {
+         if (trace) log.trace("Exists in context.");
+         // acquire lock if needed
+         if (alreadyLocked || acquireLock(ctx, key)) {
+
+            if (cacheEntry instanceof MVCCEntry && (!forRemoval || !(cacheEntry instanceof NullMarkerEntry))) {
+               mvccEntry = (MVCCEntry) cacheEntry;
+            } else {
+               // this is a read-only entry that needs to be copied to a proper read-write entry!!
+               mvccEntry = createWrappedEntry(key, cacheEntry.getValue(), false, forRemoval, cacheEntry.getLifespan());
+               cacheEntry = mvccEntry;
+               ctx.putLookedUpEntry(key, cacheEntry);
+            }
+
+            // create a copy of the underlying entry
+            mvccEntry.copyForUpdate(container, writeSkewCheck);
+         }
+
+         if (cacheEntry.isRemoved() && createIfAbsent) {
+            if (trace) log.trace("Entry is deleted in current scope.  Need to un-delete.");
+            if (mvccEntry != cacheEntry) mvccEntry = (MVCCEntry) cacheEntry;
+            mvccEntry.setRemoved(false);
+            mvccEntry.setValid(true);
+         }
+
+         return mvccEntry;
+
+      } else {
+         // else, fetch from dataContainer.
+         cacheEntry = container.get(key);
+         if (cacheEntry != null) {
+            if (trace) log.trace("Retrieved from container.");
+            // exists in cache!  Just acquire lock if needed, and wrap.
+            // do we need a lock?
+            boolean lockAcquired = acquireLock(ctx, key);
+            mvccEntry = wrapExistingEntryForWriting(ctx, key, alreadyLocked, cacheEntry, lockAcquired);
+         } else if (createIfAbsent) {
+            // this is the *only* point where new entries can be created!!
+            if (trace) log.trace("Creating new entry.");
+
+            boolean lockAcquired = false;
+            // now to lock and create the entry.  Lock first to prevent concurrent creation!
+            if (!alreadyLocked)  {
+               lockAcquired = acquireLock(ctx, key);
+            }
+            if (lockAcquired) {
+               //double check existance, as the prev lock owner might have created a cache entry for the same key
+               cacheEntry = container.get(key);
+               if (cacheEntry != null) {
+                 mvccEntry = wrapExistingEntryForWriting(ctx, key, true, cacheEntry, lockAcquired);
+               } else {
+                  mvccEntry = createAndWrapEntryForWriting(ctx, key);
+               }
+            } else {
+               mvccEntry = createAndWrapEntryForWriting(ctx, key);
+            }
+         }
+      }
+
+      // see if we need to force the lock on nonexistent entries.
+      if (mvccEntry == null && forceLockIfAbsent) {
+         // make sure we record this! Null value since this is a forced lock on the key
+         if (acquireLock(ctx, key)) ctx.putLookedUpEntry(key, null);
+      }
+
+      return mvccEntry;
+   }
+
+   private MVCCEntry createAndWrapEntryForWriting(InvocationContext ctx, Object key) {
+      MVCCEntry mvccEntry;
+      notifier.notifyCacheEntryCreated(key, true, ctx);
+      mvccEntry = createWrappedEntry(key, null, true, false, -1);
+      mvccEntry.setCreated(true);
+      ctx.putLookedUpEntry(key, mvccEntry);
+      mvccEntry.copyForUpdate(container, writeSkewCheck);
+      notifier.notifyCacheEntryCreated(key, false, ctx);
+      return mvccEntry;
+   }
+
+   private MVCCEntry wrapExistingEntryForWriting(InvocationContext ctx, Object key, boolean alreadyLocked, CacheEntry cacheEntry, boolean lockAquired) {
+      MVCCEntry mvccEntry;
+      mvccEntry = createWrappedEntry(key, cacheEntry.getValue(), false, false, cacheEntry.getLifespan());
+      ctx.putLookedUpEntry(key, mvccEntry);
+      boolean needToCopy = alreadyLocked || lockAquired || ctx.hasFlag(Flag.SKIP_LOCKING); // even if we do not acquire a lock, if skip-locking is enabled we should copy
+      if (needToCopy) mvccEntry.copyForUpdate(container, writeSkewCheck);
+      return mvccEntry;
+   }
+
+   /**
+    * Attempts to lock an entry if the lock isn't already held in the current scope, and records the lock in the
+    * context.
+    *
+    * @param ctx context
+    * @param key Key to lock
+    * @return true if a lock was needed and acquired, false if it didn't need to acquire the lock (i.e., lock was
+    *         already held)
+    * @throws InterruptedException if interrupted
+    * @throws org.infinispan.util.concurrent.TimeoutException
+    *                              if we are unable to acquire the lock after a specified timeout.
+    */
+   public final boolean acquireLock(InvocationContext ctx, Object key) throws InterruptedException, TimeoutException {
+      // don't EVER use lockManager.isLocked() since with lock striping it may be the case that we hold the relevant
+      // lock which may be shared with another key that we have a lock for already.
+      // nothing wrong, just means that we fail to record the lock.  And that is a problem.
+      // Better to check our records and lock again if necessary.
+
+      boolean shouldSkipLocking = ctx.hasFlag(Flag.SKIP_LOCKING);
+
+      if (!ctx.hasLockedKey(key) && !shouldSkipLocking) {
+         if (lockManager.lockAndRecord(key, ctx)) {
+            // successfully locked!
+            return true;
+         } else {
+            Object owner = lockManager.getOwner(key);
+            throw new TimeoutException("Unable to acquire lock after [" + Util.prettyPrintTime(getLockAcquisitionTimeout(ctx)) + "] on key [" + key + "] for requestor [" +
+                  ctx.getLockOwner() + "]! Lock held by [" + owner + "]");
+         }
+      }
+
+      return false;
+   }
+
+   private long getLockAcquisitionTimeout(InvocationContext ctx) {
+      return ctx.hasFlag(Flag.ZERO_LOCK_ACQUISITION_TIMEOUT) ?
+            0 : configuration.getLockAcquisitionTimeout();
+   }
+
+   public final void releaseLock(Object key) {
+      lockManager.unlock(key, lockManager.getOwner(key));
+   }
+}


Property changes on: trunk/core/src/main/java/org/infinispan/container/EntryFactoryImpl.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Modified: trunk/core/src/main/java/org/infinispan/factories/EmptyConstructorNamedCacheFactory.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/factories/EmptyConstructorNamedCacheFactory.java	2009-10-23 12:45:59 UTC (rev 989)
+++ trunk/core/src/main/java/org/infinispan/factories/EmptyConstructorNamedCacheFactory.java	2009-10-23 14:10:13 UTC (rev 990)
@@ -35,6 +35,7 @@
 import org.infinispan.notifications.cachelistener.CacheNotifier;
 import org.infinispan.transaction.TransactionLog;
 import org.infinispan.util.Util;
+import org.infinispan.container.EntryFactory;
 
 /**
  * Simple factory that just uses reflection and an empty constructor of the component type.

Deleted: trunk/core/src/main/java/org/infinispan/factories/EntryFactory.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/factories/EntryFactory.java	2009-10-23 12:45:59 UTC (rev 989)
+++ trunk/core/src/main/java/org/infinispan/factories/EntryFactory.java	2009-10-23 14:10:13 UTC (rev 990)
@@ -1,55 +0,0 @@
-/*
- * 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.infinispan.factories;
-
-import org.infinispan.container.entries.CacheEntry;
-import org.infinispan.container.entries.MVCCEntry;
-import org.infinispan.context.InvocationContext;
-import org.infinispan.util.concurrent.TimeoutException;
-
-/**
- * // TODO: MANIK: Document this
- *
- * @author Manik Surtani (<a href="mailto:manik at jboss.org">manik at jboss.org</a>)
- * @since 4.0
- */
-public interface EntryFactory {
-   void releaseLock(Object key);
-
-   /**
-    * Attempts to lock an entry if the lock isn't already held in the current scope, and records the lock in the
-    * context.
-    *
-    * @param ctx context
-    * @param key Key to lock
-    * @return true if a lock was needed and acquired, false if it didn't need to acquire the lock (i.e., lock was
-    *         already held)
-    * @throws InterruptedException if interrupted
-    * @throws org.infinispan.util.concurrent.TimeoutException
-    *                              if we are unable to acquire the lock after a specified timeout.
-    */
-   boolean acquireLock(InvocationContext ctx, Object key) throws InterruptedException, TimeoutException;
-
-   MVCCEntry wrapEntryForWriting(InvocationContext ctx, Object key, boolean createIfAbsent, boolean forceLockIfAbsent, boolean alreadyLocked, boolean forRemoval) throws InterruptedException;
-
-   CacheEntry wrapEntryForReading(InvocationContext ctx, Object key) throws InterruptedException;
-}

Deleted: trunk/core/src/main/java/org/infinispan/factories/EntryFactoryImpl.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/factories/EntryFactoryImpl.java	2009-10-23 12:45:59 UTC (rev 989)
+++ trunk/core/src/main/java/org/infinispan/factories/EntryFactoryImpl.java	2009-10-23 14:10:13 UTC (rev 990)
@@ -1,239 +0,0 @@
-/*
- * 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.infinispan.factories;
-
-import org.infinispan.config.Configuration;
-import org.infinispan.container.DataContainer;
-import org.infinispan.container.entries.CacheEntry;
-import org.infinispan.container.entries.MVCCEntry;
-import org.infinispan.container.entries.NullMarkerEntry;
-import org.infinispan.container.entries.NullMarkerEntryForRemoval;
-import org.infinispan.container.entries.ReadCommittedEntry;
-import org.infinispan.container.entries.RepeatableReadEntry;
-import org.infinispan.context.Flag;
-import org.infinispan.context.InvocationContext;
-import org.infinispan.factories.annotations.Inject;
-import org.infinispan.factories.annotations.Start;
-import org.infinispan.notifications.cachelistener.CacheNotifier;
-import org.infinispan.util.Util;
-import org.infinispan.util.concurrent.IsolationLevel;
-import org.infinispan.util.concurrent.TimeoutException;
-import org.infinispan.util.concurrent.locks.LockManager;
-import org.infinispan.util.logging.Log;
-import org.infinispan.util.logging.LogFactory;
-
-public class EntryFactoryImpl implements EntryFactory {
-   private boolean useRepeatableRead;
-   DataContainer container;
-   boolean writeSkewCheck;
-   LockManager lockManager;
-   Configuration configuration;
-   CacheNotifier notifier;
-
-   private static final Log log = LogFactory.getLog(EntryFactoryImpl.class);
-   private static final boolean trace = log.isTraceEnabled();
-
-   @Inject
-   public void injectDependencies(DataContainer dataContainer, LockManager lockManager, Configuration configuration, CacheNotifier notifier) {
-      this.container = dataContainer;
-      this.configuration = configuration;
-      this.lockManager = lockManager;
-      this.notifier = notifier;
-   }
-
-   @Start
-   public void init() {
-      useRepeatableRead = configuration.getIsolationLevel() == IsolationLevel.REPEATABLE_READ;
-      writeSkewCheck = configuration.isWriteSkewCheck();
-   }
-
-   private MVCCEntry createWrappedEntry(Object key, Object value, boolean isForInsert, boolean forRemoval, long lifespan) {
-      if (value == null && !isForInsert) return useRepeatableRead ?
-            forRemoval ? new NullMarkerEntryForRemoval(key) : NullMarkerEntry.getInstance()
-            : null;
-
-      return useRepeatableRead ? new RepeatableReadEntry(key, value, lifespan) : new ReadCommittedEntry(key, value, lifespan);
-   }
-
-   public final CacheEntry wrapEntryForReading(InvocationContext ctx, Object key) throws InterruptedException {
-      CacheEntry cacheEntry;
-      if (ctx.hasFlag(Flag.FORCE_WRITE_LOCK)) {
-         if (trace) log.trace("Forcing lock on reading");
-         return wrapEntryForWriting(ctx, key, false, false, false, false);
-      } else if ((cacheEntry = ctx.lookupEntry(key)) == null) {
-         if (trace) log.trace("Key {0} is not in context, fetching from container.", key);
-         // simple implementation.  Peek the entry, wrap it, put wrapped entry in the context.
-         cacheEntry = container.get(key);
-
-         // do not bother wrapping though if this is not in a tx.  repeatable read etc are all meaningless unless there is a tx.
-         if (useRepeatableRead && ctx.isInTxScope()) {
-            MVCCEntry mvccEntry = cacheEntry == null ?
-                     createWrappedEntry(key, null, false, false, -1) :
-                     createWrappedEntry(key, cacheEntry.getValue(), false, false, cacheEntry.getLifespan());
-               if (mvccEntry != null) ctx.putLookedUpEntry(key, mvccEntry);
-               return mvccEntry;
-         }
-         // if not in transaction and repeatable read, or simply read committed (regardless of whether in TX or not), do not wrap
-         if (cacheEntry != null) ctx.putLookedUpEntry(key, cacheEntry);
-            return cacheEntry;
-      } else {
-         if (trace) log.trace("Key is already in context");
-         return cacheEntry;
-      }
-   }
-
-   public final MVCCEntry wrapEntryForWriting(InvocationContext ctx, Object key, boolean createIfAbsent, boolean forceLockIfAbsent, boolean alreadyLocked, boolean forRemoval) throws InterruptedException {
-      CacheEntry cacheEntry = ctx.lookupEntry(key);
-      MVCCEntry mvccEntry = null;
-      if (createIfAbsent && cacheEntry != null && cacheEntry.isNull()) cacheEntry = null;
-      if (cacheEntry != null) // exists in context!  Just acquire lock if needed, and wrap.
-      {
-         if (trace) log.trace("Exists in context.");
-         // acquire lock if needed
-         if (alreadyLocked || acquireLock(ctx, key)) {
-
-            if (cacheEntry instanceof MVCCEntry && (!forRemoval || !(cacheEntry instanceof NullMarkerEntry))) {
-               mvccEntry = (MVCCEntry) cacheEntry;
-            } else {
-               // this is a read-only entry that needs to be copied to a proper read-write entry!!
-               mvccEntry = createWrappedEntry(key, cacheEntry.getValue(), false, forRemoval, cacheEntry.getLifespan());
-               cacheEntry = mvccEntry;
-               ctx.putLookedUpEntry(key, cacheEntry);
-            }
-
-            // create a copy of the underlying entry
-            mvccEntry.copyForUpdate(container, writeSkewCheck);
-         }
-
-         if (cacheEntry.isRemoved() && createIfAbsent) {
-            if (trace) log.trace("Entry is deleted in current scope.  Need to un-delete.");
-            if (mvccEntry != cacheEntry) mvccEntry = (MVCCEntry) cacheEntry;
-            mvccEntry.setRemoved(false);
-            mvccEntry.setValid(true);
-         }
-
-         return mvccEntry;
-
-      } else {
-         // else, fetch from dataContainer.
-         cacheEntry = container.get(key);
-         if (cacheEntry != null) {
-            if (trace) log.trace("Retrieved from container.");
-            // exists in cache!  Just acquire lock if needed, and wrap.
-            // do we need a lock?
-            boolean lockAcquired = acquireLock(ctx, key);
-            mvccEntry = wrapExistingEntryForWriting(ctx, key, alreadyLocked, cacheEntry, lockAcquired);
-         } else if (createIfAbsent) {
-            // this is the *only* point where new entries can be created!!
-            if (trace) log.trace("Creating new entry.");
-
-            boolean lockAcquired = false;
-            // now to lock and create the entry.  Lock first to prevent concurrent creation!
-            if (!alreadyLocked)  {
-               lockAcquired = acquireLock(ctx, key);
-            }
-            if (lockAcquired) {
-               //double check existance, as the prev lock owner might have created a cache entry for the same key
-               cacheEntry = container.get(key);
-               if (cacheEntry != null) {
-                 mvccEntry = wrapExistingEntryForWriting(ctx, key, true, cacheEntry, lockAcquired);
-               } else {
-                  mvccEntry = createAndWrapEntryForWriting(ctx, key);
-               }
-            } else {
-               mvccEntry = createAndWrapEntryForWriting(ctx, key);
-            }
-         }
-      }
-
-      // see if we need to force the lock on nonexistent entries.
-      if (mvccEntry == null && forceLockIfAbsent) {
-         // make sure we record this! Null value since this is a forced lock on the key
-         if (acquireLock(ctx, key)) ctx.putLookedUpEntry(key, null);
-      }
-
-      return mvccEntry;
-   }
-
-   private MVCCEntry createAndWrapEntryForWriting(InvocationContext ctx, Object key) {
-      MVCCEntry mvccEntry;
-      notifier.notifyCacheEntryCreated(key, true, ctx);
-      mvccEntry = createWrappedEntry(key, null, true, false, -1);
-      mvccEntry.setCreated(true);
-      ctx.putLookedUpEntry(key, mvccEntry);
-      mvccEntry.copyForUpdate(container, writeSkewCheck);
-      notifier.notifyCacheEntryCreated(key, false, ctx);
-      return mvccEntry;
-   }
-
-   private MVCCEntry wrapExistingEntryForWriting(InvocationContext ctx, Object key, boolean alreadyLocked, CacheEntry cacheEntry, boolean lockAquired) {
-      MVCCEntry mvccEntry;
-      mvccEntry = createWrappedEntry(key, cacheEntry.getValue(), false, false, cacheEntry.getLifespan());
-      ctx.putLookedUpEntry(key, mvccEntry);
-      boolean needToCopy = alreadyLocked || lockAquired || ctx.hasFlag(Flag.SKIP_LOCKING); // even if we do not acquire a lock, if skip-locking is enabled we should copy
-      if (needToCopy) mvccEntry.copyForUpdate(container, writeSkewCheck);
-      return mvccEntry;
-   }
-
-   /**
-    * Attempts to lock an entry if the lock isn't already held in the current scope, and records the lock in the
-    * context.
-    *
-    * @param ctx context
-    * @param key Key to lock
-    * @return true if a lock was needed and acquired, false if it didn't need to acquire the lock (i.e., lock was
-    *         already held)
-    * @throws InterruptedException if interrupted
-    * @throws org.infinispan.util.concurrent.TimeoutException
-    *                              if we are unable to acquire the lock after a specified timeout.
-    */
-   public final boolean acquireLock(InvocationContext ctx, Object key) throws InterruptedException, TimeoutException {
-      // don't EVER use lockManager.isLocked() since with lock striping it may be the case that we hold the relevant
-      // lock which may be shared with another key that we have a lock for already.
-      // nothing wrong, just means that we fail to record the lock.  And that is a problem.
-      // Better to check our records and lock again if necessary.
-
-      boolean shouldSkipLocking = ctx.hasFlag(Flag.SKIP_LOCKING);
-
-      if (!ctx.hasLockedKey(key) && !shouldSkipLocking) {
-         if (lockManager.lockAndRecord(key, ctx)) {
-            // successfully locked!
-            return true;
-         } else {
-            Object owner = lockManager.getOwner(key);
-            throw new TimeoutException("Unable to acquire lock after [" + Util.prettyPrintTime(getLockAcquisitionTimeout(ctx)) + "] on key [" + key + "] for requestor [" +
-                  ctx.getLockOwner() + "]! Lock held by [" + owner + "]");
-         }
-      }
-
-      return false;
-   }
-
-   private long getLockAcquisitionTimeout(InvocationContext ctx) {
-      return ctx.hasFlag(Flag.ZERO_LOCK_ACQUISITION_TIMEOUT) ?
-            0 : configuration.getLockAcquisitionTimeout();
-   }
-
-   public final void releaseLock(Object key) {
-      lockManager.unlock(key, lockManager.getOwner(key));
-   }
-}

Modified: trunk/core/src/main/java/org/infinispan/interceptors/CacheLoaderInterceptor.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/interceptors/CacheLoaderInterceptor.java	2009-10-23 12:45:59 UTC (rev 989)
+++ trunk/core/src/main/java/org/infinispan/interceptors/CacheLoaderInterceptor.java	2009-10-23 14:10:13 UTC (rev 990)
@@ -31,7 +31,7 @@
 import org.infinispan.container.entries.InternalCacheEntry;
 import org.infinispan.container.entries.MVCCEntry;
 import org.infinispan.context.InvocationContext;
-import org.infinispan.factories.EntryFactory;
+import org.infinispan.container.EntryFactory;
 import org.infinispan.factories.annotations.Inject;
 import org.infinispan.factories.annotations.Start;
 import org.infinispan.interceptors.base.JmxStatsCommandInterceptor;

Modified: trunk/core/src/main/java/org/infinispan/interceptors/LockingInterceptor.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/interceptors/LockingInterceptor.java	2009-10-23 12:45:59 UTC (rev 989)
+++ trunk/core/src/main/java/org/infinispan/interceptors/LockingInterceptor.java	2009-10-23 14:10:13 UTC (rev 990)
@@ -34,11 +34,11 @@
 import org.infinispan.commands.write.RemoveCommand;
 import org.infinispan.commands.write.ReplaceCommand;
 import org.infinispan.container.DataContainer;
+import org.infinispan.container.EntryFactory;
 import org.infinispan.container.entries.CacheEntry;
 import org.infinispan.context.Flag;
 import org.infinispan.context.InvocationContext;
 import org.infinispan.context.impl.TxInvocationContext;
-import org.infinispan.factories.EntryFactory;
 import org.infinispan.factories.annotations.Inject;
 import org.infinispan.factories.annotations.Start;
 import org.infinispan.interceptors.base.CommandInterceptor;

Modified: trunk/lucene-directory/src/main/java/org/infinispan/lucene/InfinispanLockFactory.java
===================================================================
--- trunk/lucene-directory/src/main/java/org/infinispan/lucene/InfinispanLockFactory.java	2009-10-23 12:45:59 UTC (rev 989)
+++ trunk/lucene-directory/src/main/java/org/infinispan/lucene/InfinispanLockFactory.java	2009-10-23 14:10:13 UTC (rev 990)
@@ -21,21 +21,19 @@
  */
 package org.infinispan.lucene;
 
-import java.io.IOException;
-import javax.transaction.RollbackException;
-import javax.transaction.Transaction;
-import javax.transaction.TransactionManager;
-
-import org.apache.lucene.store.Lock;
+import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.store.LockFactory;
 import org.infinispan.Cache;
-import org.infinispan.CacheException;
 import org.infinispan.util.logging.Log;
 import org.infinispan.util.logging.LogFactory;
 
+import javax.transaction.TransactionManager;
+import java.io.IOException;
+
 /**
  * Factory for locks obtained in <code>InfinispanDirectory</code>
  * 
+ * @author Sanne Grinovero
  * @since 4.0
  * @author Lukasz Moren
  * @see org.infinispan.lucene.InfinispanDirectory
@@ -44,183 +42,60 @@
 public class InfinispanLockFactory extends LockFactory {
 
    private static final Log log = LogFactory.getLog(InfinispanLockFactory.class);
+   static final String DEF_LOCK_NAME = IndexWriter.WRITE_LOCK_NAME;
 
-   private Cache<CacheKey, Object> cache;
-   private String indexName;
+   private final Cache<CacheKey, Object> cache;
+   private final String indexName;
+   private final TransactionManager tm;
+   private final InfinispanLock defLock;
 
    public InfinispanLockFactory(Cache<CacheKey, Object> cache, String indexName) {
       this.cache = cache;
       this.indexName = indexName;
+//      tm = cache.getAdvancedCache().getComponentRegistry().getComponent(TransactionManager.class);
+//      if (tm == null) {
+//         throw new CacheException(
+//                  "Failed looking up TransactionManager, check if any transaction manager is associated with Infinispan cache: "
+//                           + cache.getName());
+//      }
+      tm = null;
+      defLock = new InfinispanLock(cache, indexName, DEF_LOCK_NAME, tm);
    }
 
    /**
     * {@inheritDoc}
     */
-   public Lock makeLock(String lockName) {
-      try {
-         return new InfinispanLock(cache, indexName, lockName);
-      } finally {
-         if (log.isTraceEnabled()) {
-            log.trace("Created new lock: {0} for index {1}", lockName, indexName);
-         }
+   public InfinispanLock makeLock(String lockName) {
+      InfinispanLock lock;
+      //It appears Lucene always uses the same name so we give locks
+      //having this name a special treatment:
+      if (DEF_LOCK_NAME.equals(lockName)) {
+         lock = defLock;
       }
+      else {
+         // this branch is never taken with current Lucene version.
+         lock = new InfinispanLock(cache, indexName, lockName, tm);
+      }
+      if (log.isTraceEnabled()) {
+         log.trace("Lock prepared, not acquired: {0} for index {1}", lockName, indexName);
+      }
+      return lock;
    }
 
    /**
     * {@inheritDoc}
     */
    public void clearLock(String lockName) throws IOException {
-      try {
-         cache.remove(new FileCacheKey(indexName, lockName, true));
-      } finally {
-         if (log.isTraceEnabled()) {
-            log.trace("Removed lock: {0} for index {1}", lockName, indexName);
-         }
+      //Same special care as above for locks named DEF_LOCK_NAME:
+      if (DEF_LOCK_NAME.equals(lockName)) {
+         defLock.clearLock();
       }
-   }
-
-   /**
-    * Interprocess Lucene index lock
-    * 
-    * @see org.apache.lucene.store.Directory#makeLock(String)
-    */
-   public static class InfinispanLock extends Lock {
-
-      private static final Log log = LogFactory.getLog(InfinispanLock.class);
-
-      private final Cache<CacheKey, Object> cache;
-      private String lockName;
-      private String indexName;
-
-      final TransactionManager tm;
-
-      InfinispanLock(Cache<CacheKey, Object> cache, String indexName, String lockName) {
-         this.cache = cache;
-         this.lockName = lockName;
-         this.indexName = indexName;
-
-         tm = cache.getAdvancedCache().getComponentRegistry().getComponent(TransactionManager.class);
-         if (tm == null) {
-            throw new CacheException(
-                     "Failed looking up TransactionManager, check if any transaction manager is associated with Infinispan cache: "
-                              + cache.getName());
-         }
+      else {
+         new InfinispanLock(cache, indexName, lockName, tm).clearLock();
       }
-
-      /**
-       * {@inheritDoc}
-       */
-      public boolean obtain() throws IOException {
-         boolean acquired = false;
-
-         synchronized (cache) {
-            try {
-               // begin transaction for lock obtaining
-               tm.begin();
-               CacheKey lock = new FileCacheKey(indexName, lockName, true);
-               if (!cache.containsKey(lock)) {
-                  cache.put(lock, lock);
-                  acquired = true;
-               }
-            } catch (Exception e) {
-               log.error("Cannot obtain lock for: " + indexName, e);
-            } finally {
-               try {
-                  if (tm.getTransaction() != null) {
-                     if (acquired) {
-                        tm.commit();
-                        if (log.isTraceEnabled()) {
-                           log.trace("Lock: {0} acquired for index: {1} ", lockName, indexName);
-                        }
-                     } else {
-                        tm.rollback();
-                     }
-                  }
-               } catch (RollbackException e) {
-                  log.error("Cannot obtain lock for: " + indexName, e);
-                  acquired = false;
-               } catch (Exception e) {
-                  throw new CacheException(e);
-               }
-            }
-
-            if (acquired) {
-               try {
-                  // begin new transaction to batch all changes, tx commited when lock is released.
-                  tm.begin();
-                  if (log.isTraceEnabled()) {
-                     log.trace("Batch transaction started for index: {0}", indexName);
-                  }
-               } catch (Exception e) {
-                  log.error("Unable to start transaction", e);
-               }
-            }
-         }
-
-         return acquired;
+      if (log.isTraceEnabled()) {
+         log.trace("Removed lock: {0} for index {1}", lockName, indexName);
       }
-
-      /**
-       * {@inheritDoc}
-       */
-      public void release() throws IOException {
-         boolean removed = false;
-         synchronized (cache) {
-            try {
-               // commit changes in batch, transaction was started when lock was acquired
-               tm.commit();
-               if (log.isTraceEnabled()) {
-                  log.trace("Batch transaction commited for index: {0}", indexName);
-               }
-
-               tm.begin();
-               removed = cache.remove(new FileCacheKey(indexName, lockName, true)) != null;
-            } catch (Exception e) {
-               throw new CacheException("Unable to commit work done or release lock!", e);
-            } finally {
-               try {
-                  if (removed) {
-                     tm.commit();
-                     if (log.isTraceEnabled()) {
-                        log.trace("Lock: {0} removed for index: {1} ", lockName, indexName);
-                     }
-                  } else {
-                     tm.rollback();
-                  }
-               } catch (Exception e) {
-                  throw new CacheException("Unable to release lock!", e);
-               }
-            }
-         }
-      }
-
-      /**
-       * {@inheritDoc}
-       */
-      public boolean isLocked() {
-         boolean locked = false;
-         synchronized (cache) {
-            Transaction tx = null;
-            try {
-               // if there is an ongoing transaction we need to suspend it
-               if ((tx = tm.getTransaction()) != null) {
-                  tm.suspend();
-               }
-               locked = cache.containsKey(new FileCacheKey(indexName, lockName, true));
-            } catch (Exception e) {
-               log.error("Error in suspending transaction", e);
-            } finally {
-               if (tx != null) {
-                  try {
-                     tm.resume(tx);
-                  } catch (Exception e) {
-                     throw new CacheException("Unable to resume suspended transaction " + tx, e);
-                  }
-               }
-            }
-         }
-         return locked;
-      }
    }
-
+   
 }



More information about the infinispan-commits mailing list