[infinispan-commits] Infinispan SVN: r2151 - branches/4.1.x/core/src/main/java/org/infinispan/atomic.
infinispan-commits at lists.jboss.org
infinispan-commits at lists.jboss.org
Wed Aug 4 06:58:53 EDT 2010
Author: manik.surtani at jboss.com
Date: 2010-08-04 06:58:52 -0400 (Wed, 04 Aug 2010)
New Revision: 2151
Modified:
branches/4.1.x/core/src/main/java/org/infinispan/atomic/AtomicHashMap.java
branches/4.1.x/core/src/main/java/org/infinispan/atomic/AtomicHashMapProxy.java
branches/4.1.x/core/src/main/java/org/infinispan/atomic/AtomicMap.java
branches/4.1.x/core/src/main/java/org/infinispan/atomic/AtomicMapLookup.java
branches/4.1.x/core/src/main/java/org/infinispan/atomic/Delta.java
branches/4.1.x/core/src/main/java/org/infinispan/atomic/DeltaAware.java
Log:
[ISPN-563] (Document AtomicMap APis)
Modified: branches/4.1.x/core/src/main/java/org/infinispan/atomic/AtomicHashMap.java
===================================================================
--- branches/4.1.x/core/src/main/java/org/infinispan/atomic/AtomicHashMap.java 2010-08-04 10:54:19 UTC (rev 2150)
+++ branches/4.1.x/core/src/main/java/org/infinispan/atomic/AtomicHashMap.java 2010-08-04 10:58:52 UTC (rev 2151)
@@ -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<String, Integer> 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: branches/4.1.x/core/src/main/java/org/infinispan/atomic/AtomicHashMapProxy.java
===================================================================
--- branches/4.1.x/core/src/main/java/org/infinispan/atomic/AtomicHashMapProxy.java 2010-08-04 10:54:19 UTC (rev 2150)
+++ branches/4.1.x/core/src/main/java/org/infinispan/atomic/AtomicHashMapProxy.java 2010-08-04 10:58:52 UTC (rev 2151)
@@ -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: branches/4.1.x/core/src/main/java/org/infinispan/atomic/AtomicMap.java
===================================================================
--- branches/4.1.x/core/src/main/java/org/infinispan/atomic/AtomicMap.java 2010-08-04 10:54:19 UTC (rev 2150)
+++ branches/4.1.x/core/src/main/java/org/infinispan/atomic/AtomicMap.java 2010-08-04 10:58:52 UTC (rev 2151)
@@ -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<String, Integer> 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: branches/4.1.x/core/src/main/java/org/infinispan/atomic/AtomicMapLookup.java
===================================================================
--- branches/4.1.x/core/src/main/java/org/infinispan/atomic/AtomicMapLookup.java 2010-08-04 10:54:19 UTC (rev 2150)
+++ branches/4.1.x/core/src/main/java/org/infinispan/atomic/AtomicMapLookup.java 2010-08-04 10:58:52 UTC (rev 2151)
@@ -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: branches/4.1.x/core/src/main/java/org/infinispan/atomic/Delta.java
===================================================================
--- branches/4.1.x/core/src/main/java/org/infinispan/atomic/Delta.java 2010-08-04 10:54:19 UTC (rev 2150)
+++ branches/4.1.x/core/src/main/java/org/infinispan/atomic/Delta.java 2010-08-04 10:58:52 UTC (rev 2151)
@@ -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: branches/4.1.x/core/src/main/java/org/infinispan/atomic/DeltaAware.java
===================================================================
--- branches/4.1.x/core/src/main/java/org/infinispan/atomic/DeltaAware.java 2010-08-04 10:54:19 UTC (rev 2150)
+++ branches/4.1.x/core/src/main/java/org/infinispan/atomic/DeltaAware.java 2010-08-04 10:58:52 UTC (rev 2151)
@@ -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