[infinispan-commits] Infinispan SVN: r2150 - trunk/core/src/main/java/org/infinispan/atomic.

infinispan-commits at lists.jboss.org infinispan-commits at lists.jboss.org
Wed Aug 4 06:54:20 EDT 2010


Author: manik.surtani at jboss.com
Date: 2010-08-04 06:54:19 -0400 (Wed, 04 Aug 2010)
New Revision: 2150

Modified:
   trunk/core/src/main/java/org/infinispan/atomic/AtomicHashMap.java
   trunk/core/src/main/java/org/infinispan/atomic/AtomicHashMapProxy.java
   trunk/core/src/main/java/org/infinispan/atomic/AtomicMap.java
   trunk/core/src/main/java/org/infinispan/atomic/AtomicMapLookup.java
   trunk/core/src/main/java/org/infinispan/atomic/Delta.java
   trunk/core/src/main/java/org/infinispan/atomic/DeltaAware.java
Log:
[ISPN-563] (Document AtomicMap APis)

Modified: trunk/core/src/main/java/org/infinispan/atomic/AtomicHashMap.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/atomic/AtomicHashMap.java	2010-08-04 09:58:48 UTC (rev 2149)
+++ trunk/core/src/main/java/org/infinispan/atomic/AtomicHashMap.java	2010-08-04 10:54:19 UTC (rev 2150)
@@ -28,6 +28,7 @@
 import org.infinispan.marshall.Ids;
 import org.infinispan.marshall.Marshallable;
 import org.infinispan.util.FastCopyHashMap;
+import org.infinispan.atomic.AtomicMapLookup;
 
 import java.io.IOException;
 import java.io.ObjectInput;
@@ -37,13 +38,23 @@
 import java.util.Set;
 
 /**
- * Note that for replication to work properly, this class <b><i>requires</i></b> that all writes take place within the
- * scope of an ongoing transaction or batch.
+ * The default implementation of {@link AtomicMap}.  Note that this map cannot be constructed directly, and callers
+ * should obtain references to AtomicHashMaps via the {@link AtomicMapLookup} helper.  This helper will ensure proper
+ * concurrent construction and registration of AtomicMaps in Infinispan's data container.  E.g.:
+ * <br /><br />
+ * <code>
+ *    AtomicMap&lt;String, Integer&gt; map = AtomicMapLookup.getAtomicMap(cache, "my_atomic_map_key");
+ * </code>
+ * <br /><br />
+ * Note that for replication to work properly, AtomicHashMap updates <b><i>must always</i></b> take place within the
+ * scope of an ongoing JTA transaction or batch (see {@link Cache#startBatch()}).
  * <p/>
  *
  * @author (various)
- * @param <K>
- * @param <V>
+ * @param <K> the type of keys maintained by this map
+ * @param <V> the type of mapped values
+ * @see AtomicMap
+ * @see AtomicMapLookup
  * @since 4.0
  */
 @NotThreadSafe
@@ -56,7 +67,7 @@
 
    /**
     * Construction only allowed through this factory method.  This factory is intended for use internally by the
-    * CacheDelegate.  User code should use {@link org.infinispan.atomic.AtomicMapLookup#getAtomicMap(Cache, Object)}.
+    * CacheDelegate.  User code should use {@link AtomicMapLookup#getAtomicMap(Cache, Object)}.
     */
    public static AtomicHashMap newInstance(Cache cache, Object cacheKey) {
       AtomicHashMap value = new AtomicHashMap();
@@ -141,7 +152,11 @@
       delegate.clear();
    }
 
-   public AtomicMap<K, V> getProxy(Cache cache, Object mapKey,
+   /**
+    * Builds a thread-safe proxy for this instance so that concurrent reads are isolated from writes.
+    * @return an instance of AtomicHashMapProxy
+    */
+   AtomicMap<K, V> getProxy(Cache cache, Object mapKey,
                              BatchContainer batchContainer, InvocationContextContainer icc) {
       // construct the proxy lazily
       if (proxy == null)  // DCL is OK here since proxy is volatile (and we live in a post-JDK 5 world)

Modified: trunk/core/src/main/java/org/infinispan/atomic/AtomicHashMapProxy.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/atomic/AtomicHashMapProxy.java	2010-08-04 09:58:48 UTC (rev 2149)
+++ trunk/core/src/main/java/org/infinispan/atomic/AtomicHashMapProxy.java	2010-08-04 10:54:19 UTC (rev 2150)
@@ -37,9 +37,21 @@
 import java.util.Set;
 
 /**
- * A layer of indirection around an {@link AtomicHashMap} to provide reader consistency
+ * A layer of indirection around an {@link AtomicHashMap} to provide consistency and isolation for concurrent readers
+ * while writes may also be going on.  The techniques used in this implementation are very similar to the lock-free
+ * reader MVCC model used in the {@link org.infinispan.container.entries.MVCCEntry} implementations for the core data
+ * container, which closely follow software transactional memory approaches to dealing with concurrency.
+ * <br /><br />
+ * Implementations of this class are rarely created on their own; {@link AtomicHashMap#getProxy(org.infinispan.Cache, Object, org.infinispan.batch.BatchContainer, org.infinispan.context.InvocationContextContainer)}
+ * should be used to retrieve an instance of this proxy.
+ * <br /><br />
+ * Typically proxies are only created by the {@link AtomicMapLookup} helper, and would not be created by end-user code
+ * directly.
  *
- * @author Manik Surtani (<a href="mailto:manik AT jboss DOT org">manik AT jboss DOT org</a>)
+ * @author Manik Surtani
+ * @param <K> the type of keys maintained by this map
+ * @param <V> the type of mapped values
+ * @see AtomicHashMap
  * @since 4.0
  */
 public class AtomicHashMapProxy<K, V> extends AutoBatchSupport implements AtomicMap<K, V> {
@@ -49,7 +61,7 @@
    Cache cache;
    InvocationContextContainer icc;
 
-   public AtomicHashMapProxy(Cache cache, Object deltaMapKey, BatchContainer batchContainer, InvocationContextContainer icc) {
+   AtomicHashMapProxy(Cache cache, Object deltaMapKey, BatchContainer batchContainer, InvocationContextContainer icc) {
       this.cache = cache;
       this.deltaMapKey = deltaMapKey;
       this.batchContainer = batchContainer;

Modified: trunk/core/src/main/java/org/infinispan/atomic/AtomicMap.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/atomic/AtomicMap.java	2010-08-04 09:58:48 UTC (rev 2149)
+++ trunk/core/src/main/java/org/infinispan/atomic/AtomicMap.java	2010-08-04 10:54:19 UTC (rev 2150)
@@ -22,19 +22,58 @@
 package org.infinispan.atomic;
 
 import java.util.Map;
+import org.infinispan.util.concurrent.IsolationLevel;
+import org.infinispan.atomic.AtomicMapLookup;
 
 /**
- * This is a special type of Map geared for use in Infinispan.  This map type supports Infinispan atomicizing writes
- * on the cache such that a coarse grained locking is used if this map is stored in the cache, such that the entire map
- * is locked for writes or is isolated for safe concurrent read.
- * <p/>
- * This is, for all practical purposes, a marker interface that indicates that Maps of this type will be locked
- * atomically in the cache and replicated in a fine grained manner.
- * <p/>
+ * This is a special type of Map geared for use in Infinispan.  AtomicMaps have two major characteristics:
  *
- * @author Manik Surtani (<a href="mailto:manik AT jboss DOT org">manik AT jboss DOT org</a>)
+ * <ol>
+ *    <li>Atomic locking and isolation over the entire collection</li>
+ *    <li>Fine-grained serialization of deltas</li>
+ * </ol>
+ *
+ * <b><u>1.  Atomic locking and isolation over the entire collection</u></b>
+ * <p>
+ * This allows the entire AtomicMap to be locked when making changes even to certain entries within the map, and also
+ * isolates the map for safe reading (see {@link IsolationLevel} while concurrent writes may be going on.
+ * </p>
+ * <br />
+ * <b><u>2.  Fine-grained serialization of deltas</u></b>
+ * <p>
+ * AtomicMap implementations also implement the {@link DeltaAware} interface.  This powerful interface allows the
+ * generation and application of deltas, and requires that implementations are capable of tracking changes made to it
+ * during the course of a transaction.  This helps since when performing replications to update remote nodes, the
+ * <i>entire</i> map need not be serialized and transported all the time, as serializing and transporting {@link Delta}
+ * instances would work just as well, and typically be much smaller and hence faster to serialize and transport.
+ * </p>
+ * <br />
+ * <p>
+ * Applications requiring either or both of the characteristics described above are encouraged to use AtomicMaps with
+ * Infinispan, however the real benefit is often only seen where a combination of both characteristics are required.
+ * </p>
+ * <br />
+ * <b><u>Usage</u></b>
+ * <p>
+ * AtomicMaps should be constructed and "registered" with Infinispan using the {@link AtomicMapLookup} helper.  This
+ * helper ensures threadsafe construction and registration of AtomicMap instances in Infinispan's data container.  E.g.:
+ * <br />
+ * <code>
+ *    AtomicMap&lt;String, Integer&gt; map = AtomicMapLookup.getAtomicMap(cache, "my_atomic_map_key");
+ * </code>
+ * </p>
+ * <br />
+ * <p>
+ * This interface, for all practical purposes, is just a marker interface that indicates that maps of this type will
+ * be locked atomically in the cache and replicated in a fine grained manner, as it does not add any additional methods
+ * to {@link java.util.Map}.
+ * </p>
+ *
+ * @author Manik Surtani
  * @see DeltaAware
+ * @see Delta
  * @see AtomicHashMap
+ * @see AtomicMapLookup
  * @since 4.0
  */
 public interface AtomicMap<K, V> extends Map<K, V> {

Modified: trunk/core/src/main/java/org/infinispan/atomic/AtomicMapLookup.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/atomic/AtomicMapLookup.java	2010-08-04 09:58:48 UTC (rev 2149)
+++ trunk/core/src/main/java/org/infinispan/atomic/AtomicMapLookup.java	2010-08-04 10:54:19 UTC (rev 2150)
@@ -9,9 +9,12 @@
 import static org.infinispan.util.Immutables.immutableMapWrap;
 
 /**
- * A helper that locates atomic maps within a given cache.  This should be the <b>only</b> way AtomicMaps are created/retrieved.
+ * A helper that locates or safely constructs and registers atomic maps with a given cache.  This should be the
+ * <b>only</b> way AtomicMaps are created/retrieved, to prevent concurrent creation, registration and possibly
+ * overwriting of such a map within the cache.
  *
  * @author Manik Surtani
+ * @see AtomicMap
  * @since 4.0
  */
 public class AtomicMapLookup {
@@ -37,7 +40,7 @@
     *
     * @param cache underlying cache
     * @param key key under which the atomic map exists
-    * @param createIfAbsent if true, a new atomic map is created if one did not exist.
+    * @param createIfAbsent if true, a new atomic map is created if one doesn't exist; otherwise null is returned if the map didn't exist.
     * @param <MK> key param of the cache
     * @param <K> key param of the AtomicMap
     * @param <V> value param of the AtomicMap

Modified: trunk/core/src/main/java/org/infinispan/atomic/Delta.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/atomic/Delta.java	2010-08-04 09:58:48 UTC (rev 2149)
+++ trunk/core/src/main/java/org/infinispan/atomic/Delta.java	2010-08-04 10:54:19 UTC (rev 2150)
@@ -22,14 +22,16 @@
 package org.infinispan.atomic;
 
 /**
- * Represents changes made to a {@link DeltaAware} implementation.  Should be efficiently externalizable.
+ * Represents changes made to a {@link DeltaAware} implementation.  Implementations should be efficiently
+ * {@link java.io.Externalizable} rather than just {@link java.io.Serializable}.
  *
- * @author Manik Surtani (<a href="mailto:manik AT jboss DOT org">manik AT jboss DOT org</a>)
+ * @see DeltaAware
+ * @author Manik Surtani
  * @since 4.0
  */
 public interface Delta {
    /**
-    * Merge the current set of deltas with a given {@link DeltaAware} instance, and return a coherent and complete
+    * Merge the current Delta instance with a given {@link DeltaAware} instance, and return a coherent and complete
     * {@link DeltaAware} instance.  Implementations should be able to deal with null values passed in, or values of a
     * different type from the expected DeltaAware instance.  Usually the approach would be to ignore what is passed in,
     * create a new instance of the DeltaAware implementation that the current Delta implementation is written for, apply

Modified: trunk/core/src/main/java/org/infinispan/atomic/DeltaAware.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/atomic/DeltaAware.java	2010-08-04 09:58:48 UTC (rev 2149)
+++ trunk/core/src/main/java/org/infinispan/atomic/DeltaAware.java	2010-08-04 10:54:19 UTC (rev 2150)
@@ -22,21 +22,30 @@
 package org.infinispan.atomic;
 
 /**
- * This interface allows the extraction of deltas.
- * <p/>
+ * This interface allows the extraction of {@link Delta}s.
+ * <br/>
  * Implementations would be closely coupled to a corresponding {@link Delta} implementation, since {@link
  * Delta#merge(DeltaAware)}  would need to know how to recreate this instance of DeltaAware if needed.
- * <p/>
+ * <br/>
+ * Implementations of DeltaAware automatically gain the ability to perform fine-grained replication in Infinispan,
+ * since Infinispan's data container is able to detect these types and only serialize and transport Deltas around
+ * the network rather than the entire, serialized object.
+ * <br />
+ * Using DeltaAware makes sense if your custom object is large in size and often only sees small portions of the
+ * object being updated in a transaction.  Implementations would need to be able to track these changes during the
+ * course of a transaction though, to be able to produce a {@link Delta} instance, so this too is a consideration
+ * for implementations.
+ * <br />
  *
- * @author Manik Surtani (<a href="mailto:manik AT jboss DOT org">manik AT jboss DOT org</a>)
+ * @author Manik Surtani
  * @see Delta
  * @since 4.0
  */
 public interface DeltaAware {
    /**
     * Extracts changes made to implementations, in an efficient format that can easily and cheaply be serialized and
-    * deserialized.  This method can only be called once for each changeset as it wipes its internal changelog when
-    * generating and submitting the delta to the caller.
+    * deserialized.  This method will only be called once for each changeset as it is assumed that any implementation's
+    * internal changelog is wiped and reset after generating and submitting the delta to the caller.
     *
     * @return an instance of Delta
     */
@@ -44,7 +53,8 @@
 
    /**
     * Indicate that all deltas collected to date has been extracted (via a call to {@link #delta()}) and can be
-    * discarded.
+    * discarded.  Often used as an optimization if the delta isn't really needed, but the cleaning and resetting of
+    * internal state is desirable.
     */
    void commit();
 }



More information about the infinispan-commits mailing list