You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by sb...@apache.org on 2017/04/22 06:56:33 UTC

ignite git commit: ignite-2893 Restored explicit tx usages to avoid issues when there are no classes on servers

Repository: ignite
Updated Branches:
  refs/heads/ignite-2.0 a4e8296f3 -> 3a5c6f359


ignite-2893 Restored explicit tx usages to avoid issues when there are no classes on servers


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/3a5c6f35
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/3a5c6f35
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/3a5c6f35

Branch: refs/heads/ignite-2.0
Commit: 3a5c6f3590f9355cb63045bf0dea91b92b96b1c4
Parents: a4e8296
Author: sboikov <sb...@gridgain.com>
Authored: Sat Apr 22 09:55:17 2017 +0300
Committer: sboikov <sb...@gridgain.com>
Committed: Sat Apr 22 09:55:17 2017 +0300

----------------------------------------------------------------------
 .../IgniteCacheDatabaseSharedManager.java       |   4 +-
 .../CacheDataStructuresManager.java             |  34 +++
 .../GridCacheAtomicReferenceImpl.java           | 108 +++++++--
 .../GridCacheAtomicStampedImpl.java             |  70 +++++-
 .../GridCacheCountDownLatchImpl.java            |   2 +-
 .../datastructures/GridCacheSemaphoreImpl.java  | 240 +++++++++----------
 ...CacheAtomicReferenceApiSelfAbstractTest.java |   4 +-
 ...IgniteDataStructuresNoClassOnServerTest.java |  30 +++
 .../CacheNoValueClassOnServerNodeTest.java      | 112 +--------
 .../IgniteNoClassOnServerAbstractTest.java      | 135 +++++++++++
 ...ObjectsCacheDataStructuresSelfTestSuite.java |   7 +-
 modules/extdata/p2p/pom.xml                     |   6 +
 .../p2p/NoValueClassOnServerAbstractClient.java |  90 +++++++
 .../CacheNoValueClassOnServerTestClient.java    |  79 +++---
 ...DataStructuresNoClassOnServerTestClient.java | 181 ++++++++++++++
 15 files changed, 798 insertions(+), 304 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/3a5c6f35/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/IgniteCacheDatabaseSharedManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/IgniteCacheDatabaseSharedManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/IgniteCacheDatabaseSharedManager.java
index e6fe7cd..705e74c 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/IgniteCacheDatabaseSharedManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/IgniteCacheDatabaseSharedManager.java
@@ -706,12 +706,12 @@ public class IgniteCacheDatabaseSharedManager extends GridCacheSharedManagerAdap
 
     /** {@inheritDoc} */
     @Override public void onActivate(GridKernalContext kctx) throws IgniteCheckedException {
-
+        // No-op.
     }
 
     /** {@inheritDoc} */
     @Override public void onDeActivate(GridKernalContext kctx) throws IgniteCheckedException {
-
+        // No-op.
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/3a5c6f35/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/datastructures/CacheDataStructuresManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/datastructures/CacheDataStructuresManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/datastructures/CacheDataStructuresManager.java
index d864d3c..45f0cee 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/datastructures/CacheDataStructuresManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/datastructures/CacheDataStructuresManager.java
@@ -21,8 +21,10 @@ import java.io.Externalizable;
 import java.io.IOException;
 import java.io.ObjectInput;
 import java.io.ObjectOutput;
+import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.UUID;
@@ -35,6 +37,7 @@ import javax.cache.event.CacheEntryUpdatedListener;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.IgniteSet;
+import org.apache.ignite.binary.BinaryObject;
 import org.apache.ignite.cache.CacheEntryEventSerializableFilter;
 import org.apache.ignite.cluster.ClusterNode;
 import org.apache.ignite.internal.IgniteKernal;
@@ -75,6 +78,29 @@ import static org.apache.ignite.internal.GridClosureCallMode.BROADCAST;
  *
  */
 public class CacheDataStructuresManager extends GridCacheManagerAdapter {
+    /** Known classes which are safe to use on server nodes. */
+    private static final Collection<Class<?>> KNOWN_CLS = new HashSet<>();
+
+    /**
+     *
+     */
+    static {
+        KNOWN_CLS.add(String.class);
+        KNOWN_CLS.add(Boolean.class);
+        KNOWN_CLS.add(Byte.class);
+        KNOWN_CLS.add(Short.class);
+        KNOWN_CLS.add(Character.class);
+        KNOWN_CLS.add(Integer.class);
+        KNOWN_CLS.add(Long.class);
+        KNOWN_CLS.add(Float.class);
+        KNOWN_CLS.add(Double.class);
+        KNOWN_CLS.add(String.class);
+        KNOWN_CLS.add(UUID.class);
+        KNOWN_CLS.add(IgniteUuid.class);
+        KNOWN_CLS.add(BigDecimal.class);
+        KNOWN_CLS.add(BinaryObject.class);
+    }
+
     /** Sets map. */
     private final ConcurrentMap<IgniteUuid, GridCacheSetProxy> setsMap;
 
@@ -419,6 +445,14 @@ public class CacheDataStructuresManager extends GridCacheManagerAdapter {
     }
 
     /**
+     * @param obj Object.
+     * @return {@code True}
+     */
+    public boolean knownType(Object obj) {
+        return obj == null || KNOWN_CLS.contains(obj.getClass());
+    }
+
+    /**
      * @param id Set ID.
      * @return Data for given set.
      */

http://git-wip-us.apache.org/repos/asf/ignite/blob/3a5c6f35/modules/core/src/main/java/org/apache/ignite/internal/processors/datastructures/GridCacheAtomicReferenceImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/datastructures/GridCacheAtomicReferenceImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/datastructures/GridCacheAtomicReferenceImpl.java
index b7dc007..0b0c202 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/datastructures/GridCacheAtomicReferenceImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/datastructures/GridCacheAtomicReferenceImpl.java
@@ -23,6 +23,7 @@ import java.io.InvalidObjectException;
 import java.io.ObjectInput;
 import java.io.ObjectOutput;
 import java.io.ObjectStreamException;
+import java.util.concurrent.Callable;
 import javax.cache.processor.EntryProcessorException;
 import javax.cache.processor.EntryProcessorResult;
 import javax.cache.processor.MutableEntry;
@@ -32,16 +33,22 @@ import org.apache.ignite.cache.CacheEntryProcessor;
 import org.apache.ignite.internal.GridKernalContext;
 import org.apache.ignite.internal.processors.cache.GridCacheContext;
 import org.apache.ignite.internal.processors.cache.IgniteInternalCache;
+import org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxLocal;
+import org.apache.ignite.internal.processors.cluster.IgniteChangeGlobalStateSupport;
 import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.internal.CU;
 import org.apache.ignite.internal.util.typedef.internal.S;
 import org.apache.ignite.internal.util.typedef.internal.U;
-import org.apache.ignite.internal.processors.cluster.IgniteChangeGlobalStateSupport;
 import org.apache.ignite.lang.IgniteBiTuple;
 
+import static org.apache.ignite.transactions.TransactionConcurrency.PESSIMISTIC;
+import static org.apache.ignite.transactions.TransactionIsolation.REPEATABLE_READ;
+
 /**
  * Cache atomic reference implementation.
  */
-public final class GridCacheAtomicReferenceImpl<T> implements GridCacheAtomicReferenceEx<T>, IgniteChangeGlobalStateSupport, Externalizable {
+public final class GridCacheAtomicReferenceImpl<T> implements GridCacheAtomicReferenceEx<T>,
+    IgniteChangeGlobalStateSupport, Externalizable {
     /** */
     private static final long serialVersionUID = 0L;
 
@@ -124,11 +131,30 @@ public final class GridCacheAtomicReferenceImpl<T> implements GridCacheAtomicRef
     }
 
     /** {@inheritDoc} */
-    @Override public void set(T val) {
+    @Override public void set(final T val) {
         checkRemoved();
 
         try {
-            atomicView.invoke(key, new ReferenceSetEntryProcessor<>(val));
+            if (ctx.dataStructures().knownType(val))
+                atomicView.invoke(key, new ReferenceSetEntryProcessor<>(val));
+            else {
+                CU.retryTopologySafe(new Callable<Void>() {
+                    @Override public Void call() throws Exception {
+                        try (GridNearTxLocal tx = CU.txStartInternal(ctx, atomicView, PESSIMISTIC, REPEATABLE_READ)) {
+                            GridCacheAtomicReferenceValue<T> ref = atomicView.get(key);
+
+                            if (ref == null)
+                                throw new IgniteException("Failed to find atomic reference with given name: " + name);
+
+                            atomicView.put(key, new GridCacheAtomicReferenceValue<>(val));
+
+                            tx.commit();
+                        }
+
+                        return null;
+                    }
+                });
+            }
         }
         catch (EntryProcessorException e) {
             throw new IgniteException(e.getMessage(), e);
@@ -139,14 +165,40 @@ public final class GridCacheAtomicReferenceImpl<T> implements GridCacheAtomicRef
     }
 
     /** {@inheritDoc} */
-    @Override public boolean compareAndSet(T expVal, T newVal) {
+    @Override public boolean compareAndSet(final T expVal, final T newVal) {
         try {
-            EntryProcessorResult<Boolean> res =
-                atomicView.invoke(key, new ReferenceCompareAndSetEntryProcessor<>(expVal, newVal));
+            if (ctx.dataStructures().knownType(expVal) && ctx.dataStructures().knownType(newVal)) {
+                EntryProcessorResult<Boolean> res =
+                    atomicView.invoke(key, new ReferenceCompareAndSetEntryProcessor<>(expVal, newVal));
+
+                assert res != null && res.get() != null : res;
+
+                return res.get();
+            }
+            else {
+                return CU.retryTopologySafe(new Callable<Boolean>() {
+                    @Override public Boolean call() throws Exception {
+                        try (GridNearTxLocal tx = CU.txStartInternal(ctx, atomicView, PESSIMISTIC, REPEATABLE_READ)) {
+                            GridCacheAtomicReferenceValue<T> ref = atomicView.get(key);
+
+                            if (ref == null)
+                                throw new IgniteException("Failed to find atomic reference with given name: " + name);
 
-            assert res != null && res.get() != null : res;
+                            T curVal = ref.get();
 
-            return res.get();
+                            if (!F.eq(expVal, curVal))
+                                return false;
+                            else {
+                                atomicView.put(key, new GridCacheAtomicReferenceValue<>(newVal));
+
+                                tx.commit();
+
+                                return true;
+                            }
+                        }
+                    }
+                });
+            }
         }
         catch (EntryProcessorException e) {
             throw new IgniteException(e.getMessage(), e);
@@ -163,16 +215,42 @@ public final class GridCacheAtomicReferenceImpl<T> implements GridCacheAtomicRef
      * @param expVal Expected value.
      * @return Original value.
      */
-    public T compareAndSetAndGet(T newVal, T expVal) {
+    public T compareAndSetAndGet(final T newVal, final T expVal) {
         checkRemoved();
 
         try {
-            EntryProcessorResult<T> res =
-                atomicView.invoke(key, new ReferenceCompareAndSetAndGetEntryProcessor<T>(expVal, newVal));
+            if (ctx.dataStructures().knownType(expVal) && ctx.dataStructures().knownType(newVal)) {
+                EntryProcessorResult<T> res =
+                    atomicView.invoke(key, new ReferenceCompareAndSetAndGetEntryProcessor<T>(expVal, newVal));
+
+                assert res != null;
+
+                return res.get();
+            }
+            else {
+                return CU.retryTopologySafe(new Callable<T>() {
+                    @Override public T call() throws Exception {
+                        try (GridNearTxLocal tx = CU.txStartInternal(ctx, atomicView, PESSIMISTIC, REPEATABLE_READ)) {
+                            GridCacheAtomicReferenceValue<T> ref = atomicView.get(key);
 
-            assert res != null;
+                            if (ref == null)
+                                throw new IgniteException("Failed to find atomic reference with given name: " + name);
 
-            return res.get();
+                            T curVal = ref.get();
+
+                            if (!F.eq(expVal, curVal))
+                                return curVal;
+                            else {
+                                atomicView.put(key, new GridCacheAtomicReferenceValue<>(newVal));
+
+                                tx.commit();
+
+                                return expVal;
+                            }
+                        }
+                    }
+                });
+            }
         }
         catch (EntryProcessorException e) {
             throw new IgniteException(e.getMessage(), e);
@@ -251,8 +329,6 @@ public final class GridCacheAtomicReferenceImpl<T> implements GridCacheAtomicRef
                 throw removedError();
             }
         }
-
-
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/3a5c6f35/modules/core/src/main/java/org/apache/ignite/internal/processors/datastructures/GridCacheAtomicStampedImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/datastructures/GridCacheAtomicStampedImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/datastructures/GridCacheAtomicStampedImpl.java
index 3f14942..9449995 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/datastructures/GridCacheAtomicStampedImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/datastructures/GridCacheAtomicStampedImpl.java
@@ -23,6 +23,7 @@ import java.io.InvalidObjectException;
 import java.io.ObjectInput;
 import java.io.ObjectOutput;
 import java.io.ObjectStreamException;
+import java.util.concurrent.Callable;
 import javax.cache.processor.EntryProcessorException;
 import javax.cache.processor.EntryProcessorResult;
 import javax.cache.processor.MutableEntry;
@@ -32,12 +33,17 @@ import org.apache.ignite.cache.CacheEntryProcessor;
 import org.apache.ignite.internal.GridKernalContext;
 import org.apache.ignite.internal.processors.cache.GridCacheContext;
 import org.apache.ignite.internal.processors.cache.IgniteInternalCache;
+import org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxLocal;
+import org.apache.ignite.internal.processors.cluster.IgniteChangeGlobalStateSupport;
 import org.apache.ignite.internal.util.tostring.GridToStringBuilder;
 import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.internal.CU;
 import org.apache.ignite.internal.util.typedef.internal.U;
-import org.apache.ignite.internal.processors.cluster.IgniteChangeGlobalStateSupport;
 import org.apache.ignite.lang.IgniteBiTuple;
 
+import static org.apache.ignite.transactions.TransactionConcurrency.PESSIMISTIC;
+import static org.apache.ignite.transactions.TransactionIsolation.REPEATABLE_READ;
+
 /**
  * Cache atomic stamped implementation.
  */
@@ -124,11 +130,30 @@ public final class GridCacheAtomicStampedImpl<T, S> implements GridCacheAtomicSt
     }
 
     /** {@inheritDoc} */
-    @Override public void set(T val, S stamp) {
+    @Override public void set(final T val, final S stamp) {
         checkRemoved();
 
         try {
-            atomicView.invoke(key, new StampedSetEntryProcessor<>(val, stamp));
+            if (ctx.dataStructures().knownType(val) && ctx.dataStructures().knownType(stamp))
+                atomicView.invoke(key, new StampedSetEntryProcessor<>(val, stamp));
+            else {
+                CU.retryTopologySafe(new Callable<Void>() {
+                    @Override public Void call() throws Exception {
+                        try (GridNearTxLocal tx = CU.txStartInternal(ctx, atomicView, PESSIMISTIC, REPEATABLE_READ)) {
+                            GridCacheAtomicStampedValue<T, S> ref = atomicView.get(key);
+
+                            if (ref == null)
+                                throw new IgniteException("Failed to find atomic stamped with given name: " + name);
+
+                            atomicView.put(key, new GridCacheAtomicStampedValue<>(val, stamp));
+
+                            tx.commit();
+                        }
+
+                        return null;
+                    }
+                });
+            }
         }
         catch (EntryProcessorException e) {
             throw new IgniteException(e.getMessage(), e);
@@ -139,16 +164,43 @@ public final class GridCacheAtomicStampedImpl<T, S> implements GridCacheAtomicSt
     }
 
     /** {@inheritDoc} */
-    @Override public boolean compareAndSet(T expVal, T newVal, S expStamp, S newStamp) {
+    @Override public boolean compareAndSet(final T expVal, final T newVal, final S expStamp, final S newStamp) {
         checkRemoved();
 
         try {
-            EntryProcessorResult<Boolean> res =
-                atomicView.invoke(key, new StampedCompareAndSetEntryProcessor<>(expVal, expStamp, newVal, newStamp));
+            if (ctx.dataStructures().knownType(expVal) &&
+                ctx.dataStructures().knownType(newVal) &&
+                ctx.dataStructures().knownType(expStamp) &&
+                ctx.dataStructures().knownType(newStamp)) {
+                EntryProcessorResult<Boolean> res =
+                    atomicView.invoke(key, new StampedCompareAndSetEntryProcessor<>(expVal, expStamp, newVal, newStamp));
 
-            assert res != null && res.get() != null : res;
+                assert res != null && res.get() != null : res;
 
-            return res.get();
+                return res.get();
+            }
+            else {
+                return CU.retryTopologySafe(new Callable<Boolean>() {
+                    @Override public Boolean call() throws Exception {
+                        try (GridNearTxLocal tx = CU.txStartInternal(ctx, atomicView, PESSIMISTIC, REPEATABLE_READ)) {
+                            GridCacheAtomicStampedValue<T, S> val = atomicView.get(key);
+
+                            if (val == null)
+                                throw new IgniteException("Failed to find atomic stamped with given name: " + name);
+
+                            if (F.eq(expVal, val.value()) && F.eq(expStamp, val.stamp())) {
+                                atomicView.put(key, new GridCacheAtomicStampedValue<>(newVal, newStamp));
+
+                                tx.commit();
+
+                                return true;
+                            }
+
+                            return false;
+                        }
+                    }
+                });
+            }
         }
         catch (EntryProcessorException e) {
             throw new IgniteException(e.getMessage(), e);
@@ -295,7 +347,7 @@ public final class GridCacheAtomicStampedImpl<T, S> implements GridCacheAtomicSt
 
     /** {@inheritDoc} */
     @Override public void onDeActivate(GridKernalContext kctx) throws IgniteCheckedException {
-
+        // No-op.
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/3a5c6f35/modules/core/src/main/java/org/apache/ignite/internal/processors/datastructures/GridCacheCountDownLatchImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/datastructures/GridCacheCountDownLatchImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/datastructures/GridCacheCountDownLatchImpl.java
index 86e99a9..b93e600 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/datastructures/GridCacheCountDownLatchImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/datastructures/GridCacheCountDownLatchImpl.java
@@ -344,7 +344,7 @@ public final class GridCacheCountDownLatchImpl implements GridCacheCountDownLatc
 
     /** {@inheritDoc} */
     @Override public void onDeActivate(GridKernalContext kctx) throws IgniteCheckedException {
-
+        // No-op.
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/3a5c6f35/modules/core/src/main/java/org/apache/ignite/internal/processors/datastructures/GridCacheSemaphoreImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/datastructures/GridCacheSemaphoreImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/datastructures/GridCacheSemaphoreImpl.java
index edc322e..2d5147b 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/datastructures/GridCacheSemaphoreImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/datastructures/GridCacheSemaphoreImpl.java
@@ -288,61 +288,61 @@ public final class GridCacheSemaphoreImpl implements GridCacheSemaphoreEx, Ignit
         boolean compareAndSetGlobalState(final int expVal, final int newVal, final boolean draining) {
             try {
                 return retryTopologySafe(new Callable<Boolean>() {
-                        @Override public Boolean call() throws Exception {
-                            try (GridNearTxLocal tx = CU.txStartInternal(ctx,
-                                semView,
-                                PESSIMISTIC, REPEATABLE_READ)
-                            ) {
-                                GridCacheSemaphoreState val = semView.get(key);
-
-                                if (val == null)
-                                    throw new IgniteCheckedException("Failed to find semaphore with given name: " +
-                                        name);
+                    @Override public Boolean call() throws Exception {
+                        try (GridNearTxLocal tx = CU.txStartInternal(ctx,
+                            semView,
+                            PESSIMISTIC, REPEATABLE_READ)
+                        ) {
+                            GridCacheSemaphoreState val = semView.get(key);
 
-                                // Abort if state is already broken.
-                                if (val.isBroken()) {
-                                    tx.rollback();
+                            if (val == null)
+                                throw new IgniteCheckedException("Failed to find semaphore with given name: " +
+                                    name);
 
-                                    return true;
-                                }
+                            // Abort if state is already broken.
+                            if (val.isBroken()) {
+                                tx.rollback();
 
-                                boolean retVal = val.getCount() == expVal;
+                                return true;
+                            }
 
-                                if (retVal) {
-                                    // If this is not a call to drain permits,
-                                    // Modify global permission count for the calling node.
-                                    if (!draining) {
-                                        UUID nodeID = ctx.localNodeId();
+                            boolean retVal = val.getCount() == expVal;
 
-                                        Map<UUID, Integer> map = val.getWaiters();
+                            if (retVal) {
+                                // If this is not a call to drain permits,
+                                // Modify global permission count for the calling node.
+                                if (!draining) {
+                                    UUID nodeID = ctx.localNodeId();
 
-                                        int waitingCnt = expVal - newVal;
+                                    Map<UUID, Integer> map = val.getWaiters();
 
-                                        if (map.containsKey(nodeID))
-                                            waitingCnt += map.get(nodeID);
+                                    int waitingCnt = expVal - newVal;
 
-                                        map.put(nodeID, waitingCnt);
+                                    if (map.containsKey(nodeID))
+                                        waitingCnt += map.get(nodeID);
 
-                                        val.setWaiters(map);
-                                    }
+                                    map.put(nodeID, waitingCnt);
 
-                                    val.setCount(newVal);
+                                    val.setWaiters(map);
+                                }
 
-                                    semView.put(key, val);
+                                val.setCount(newVal);
 
-                                    tx.commit();
-                                }
+                                semView.put(key, val);
 
-                                return retVal;
+                                tx.commit();
                             }
-                            catch (Error | Exception e) {
-                                if (!ctx.kernalContext().isStopping())
-                                    U.error(log, "Failed to compare and set: " + this, e);
 
-                                throw e;
-                            }
+                            return retVal;
+                        }
+                        catch (Error | Exception e) {
+                            if (!ctx.kernalContext().isStopping())
+                                U.error(log, "Failed to compare and set: " + this, e);
+
+                            throw e;
                         }
-                    });
+                    }
+                });
             }
             catch (IgniteCheckedException e) {
                 if (ctx.kernalContext().isStopping()) {
@@ -367,70 +367,70 @@ public final class GridCacheSemaphoreImpl implements GridCacheSemaphoreEx, Ignit
         boolean releaseFailedNode(final UUID nodeId, final boolean broken) {
             try {
                 return retryTopologySafe(new Callable<Boolean>() {
-                        @Override public Boolean call() throws Exception {
-                            try (
-                                GridNearTxLocal tx = CU.txStartInternal(ctx,
-                                    semView,
-                                    PESSIMISTIC, REPEATABLE_READ)
-                            ) {
-                                GridCacheSemaphoreState val = semView.get(key);
-
-                                if (val == null)
-                                    throw new IgniteCheckedException("Failed to find semaphore with given name: " +
-                                        name);
-
-                                // Quit early if semaphore is already broken.
-                                if( val.isBroken()) {
-                                    tx.rollback();
-
-                                    return false;
-                                }
+                    @Override public Boolean call() throws Exception {
+                        try (
+                            GridNearTxLocal tx = CU.txStartInternal(ctx,
+                                semView,
+                                PESSIMISTIC, REPEATABLE_READ)
+                        ) {
+                            GridCacheSemaphoreState val = semView.get(key);
 
-                                // Mark semaphore as broken. No permits are released,
-                                // since semaphore is useless from now on.
-                                if (broken) {
-                                    val.setBroken(true);
+                            if (val == null)
+                                throw new IgniteCheckedException("Failed to find semaphore with given name: " +
+                                    name);
 
-                                    semView.put(key, val);
+                            // Quit early if semaphore is already broken.
+                            if( val.isBroken()) {
+                                tx.rollback();
 
-                                    tx.commit();
+                                return false;
+                            }
 
-                                    return true;
-                                }
+                            // Mark semaphore as broken. No permits are released,
+                            // since semaphore is useless from now on.
+                            if (broken) {
+                                val.setBroken(true);
 
-                                Map<UUID, Integer> map = val.getWaiters();
+                                semView.put(key, val);
 
-                                if (!map.containsKey(nodeId)) {
-                                    tx.rollback();
+                                tx.commit();
 
-                                    return false;
-                                }
+                                return true;
+                            }
 
-                                int numPermits = map.get(nodeId);
+                            Map<UUID, Integer> map = val.getWaiters();
 
-                                if (numPermits > 0)
-                                    val.setCount(val.getCount() + numPermits);
+                            if (!map.containsKey(nodeId)) {
+                                tx.rollback();
 
-                                map.remove(nodeId);
+                                return false;
+                            }
 
-                                val.setWaiters(map);
+                            int numPermits = map.get(nodeId);
 
-                                semView.put(key, val);
+                            if (numPermits > 0)
+                                val.setCount(val.getCount() + numPermits);
 
-                                sync.nodeMap = map;
+                            map.remove(nodeId);
 
-                                tx.commit();
+                            val.setWaiters(map);
 
-                                return true;
-                            }
-                            catch (Error | Exception e) {
-                                if (!ctx.kernalContext().isStopping())
-                                    U.error(log, "Failed to compare and set: " + this, e);
+                            semView.put(key, val);
 
-                                throw e;
-                            }
+                            sync.nodeMap = map;
+
+                            tx.commit();
+
+                            return true;
+                        }
+                        catch (Error | Exception e) {
+                            if (!ctx.kernalContext().isStopping())
+                                U.error(log, "Failed to compare and set: " + this, e);
+
+                            throw e;
                         }
-                    });
+                    }
+                });
             }
             catch (IgniteCheckedException e) {
                 if (ctx.kernalContext().isStopping()) {
@@ -479,34 +479,34 @@ public final class GridCacheSemaphoreImpl implements GridCacheSemaphoreEx, Ignit
         if (!initGuard.get() && initGuard.compareAndSet(false, true)) {
             try {
                 sync = retryTopologySafe(new Callable<Sync>() {
-                        @Override public Sync call() throws Exception {
-                            try (GridNearTxLocal tx = CU.txStartInternal(ctx,
-                                semView, PESSIMISTIC, REPEATABLE_READ)) {
-                                GridCacheSemaphoreState val = semView.get(key);
+                    @Override public Sync call() throws Exception {
+                        try (GridNearTxLocal tx = CU.txStartInternal(ctx,
+                            semView, PESSIMISTIC, REPEATABLE_READ)) {
+                            GridCacheSemaphoreState val = semView.get(key);
 
-                                if (val == null) {
-                                    if (log.isDebugEnabled())
-                                        log.debug("Failed to find semaphore with given name: " + name);
+                            if (val == null) {
+                                if (log.isDebugEnabled())
+                                    log.debug("Failed to find semaphore with given name: " + name);
 
-                                    return null;
-                                }
+                                return null;
+                            }
 
-                                final int cnt = val.getCount();
+                            final int cnt = val.getCount();
 
-                                Map<UUID, Integer> waiters = val.getWaiters();
+                            Map<UUID, Integer> waiters = val.getWaiters();
 
-                                final boolean failoverSafe = val.isFailoverSafe();
+                            final boolean failoverSafe = val.isFailoverSafe();
 
-                                tx.commit();
+                            tx.commit();
 
-                                Sync sync = new Sync(cnt, waiters, failoverSafe);
+                            Sync sync = new Sync(cnt, waiters, failoverSafe);
 
-                                sync.setBroken(val.isBroken());
+                            sync.setBroken(val.isBroken());
 
-                                return sync;
-                            }
+                            return sync;
                         }
-                    });
+                    }
+                });
 
                 if (log.isDebugEnabled())
                     log.debug("Initialized internal sync structure: " + sync);
@@ -722,24 +722,24 @@ public final class GridCacheSemaphoreImpl implements GridCacheSemaphoreEx, Ignit
             initializeSemaphore();
 
             ret = retryTopologySafe(new Callable<Integer>() {
-                    @Override public Integer call() throws Exception {
-                        try (
-                            GridNearTxLocal tx = CU.txStartInternal(ctx,
-                                semView, PESSIMISTIC, REPEATABLE_READ)
-                        ) {
-                            GridCacheSemaphoreState val = semView.get(key);
+                @Override public Integer call() throws Exception {
+                    try (
+                        GridNearTxLocal tx = CU.txStartInternal(ctx,
+                            semView, PESSIMISTIC, REPEATABLE_READ)
+                    ) {
+                        GridCacheSemaphoreState val = semView.get(key);
 
-                            if (val == null)
-                                throw new IgniteException("Failed to find semaphore with given name: " + name);
+                        if (val == null)
+                            throw new IgniteException("Failed to find semaphore with given name: " + name);
 
-                            int cnt = val.getCount();
+                        int cnt = val.getCount();
 
-                            tx.rollback();
+                        tx.rollback();
 
-                            return cnt;
-                        }
+                        return cnt;
                     }
-                });
+                }
+            });
         }
         catch (IgniteCheckedException e) {
             throw U.convertException(e);
@@ -875,7 +875,7 @@ public final class GridCacheSemaphoreImpl implements GridCacheSemaphoreEx, Ignit
         try {
             initializeSemaphore();
 
-            boolean result = sync.tryAcquireSharedNanos(permits, unit.toNanos(timeout));
+            boolean res = sync.tryAcquireSharedNanos(permits, unit.toNanos(timeout));
 
             if (isBroken()) {
                 Thread.interrupted();
@@ -883,7 +883,7 @@ public final class GridCacheSemaphoreImpl implements GridCacheSemaphoreEx, Ignit
                 throw new InterruptedException();
             }
 
-            return result;
+            return res;
         }
         catch (IgniteCheckedException e) {
             throw U.convertException(e);
@@ -972,7 +972,7 @@ public final class GridCacheSemaphoreImpl implements GridCacheSemaphoreEx, Ignit
 
     /** {@inheritDoc} */
     @Override public void onDeActivate(GridKernalContext kctx) throws IgniteCheckedException {
-
+        // No-op.
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/3a5c6f35/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/datastructures/GridCacheAtomicReferenceApiSelfAbstractTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/datastructures/GridCacheAtomicReferenceApiSelfAbstractTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/datastructures/GridCacheAtomicReferenceApiSelfAbstractTest.java
index 3c4b3a7..b82da58 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/datastructures/GridCacheAtomicReferenceApiSelfAbstractTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/datastructures/GridCacheAtomicReferenceApiSelfAbstractTest.java
@@ -43,10 +43,10 @@ public abstract class GridCacheAtomicReferenceApiSelfAbstractTest extends Ignite
      * @throws Exception If failed.
      */
     public void testPrepareAtomicReference() throws Exception {
-        /** Name of first atomic. */
+        /* Name of first atomic. */
         String atomicName1 = UUID.randomUUID().toString();
 
-        /** Name of second atomic. */
+        /* Name of second atomic. */
         String atomicName2 = UUID.randomUUID().toString();
 
         String initVal = "1";

http://git-wip-us.apache.org/repos/asf/ignite/blob/3a5c6f35/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/datastructures/IgniteDataStructuresNoClassOnServerTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/datastructures/IgniteDataStructuresNoClassOnServerTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/datastructures/IgniteDataStructuresNoClassOnServerTest.java
new file mode 100644
index 0000000..9808107
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/datastructures/IgniteDataStructuresNoClassOnServerTest.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.cache.datastructures;
+
+import org.apache.ignite.internal.processors.cache.distributed.IgniteNoClassOnServerAbstractTest;
+
+/**
+ *
+ */
+public class IgniteDataStructuresNoClassOnServerTest extends IgniteNoClassOnServerAbstractTest {
+    /** {@inheritDoc} */
+    @Override protected String clientClassName() {
+        return "org.apache.ignite.tests.p2p.datastructures.DataStructuresNoClassOnServerTestClient";
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/3a5c6f35/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/CacheNoValueClassOnServerNodeTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/CacheNoValueClassOnServerNodeTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/CacheNoValueClassOnServerNodeTest.java
index c6ce81e..625a95b 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/CacheNoValueClassOnServerNodeTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/CacheNoValueClassOnServerNodeTest.java
@@ -17,116 +17,12 @@
 
 package org.apache.ignite.internal.processors.cache.distributed;
 
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.concurrent.CountDownLatch;
-import org.apache.ignite.Ignite;
-import org.apache.ignite.Ignition;
-import org.apache.ignite.configuration.CacheConfiguration;
-import org.apache.ignite.configuration.IgniteConfiguration;
-import org.apache.ignite.internal.util.GridJavaProcess;
-import org.apache.ignite.internal.util.typedef.CI1;
-import org.apache.ignite.internal.util.typedef.internal.U;
-import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
-import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
-import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
-
-import static java.util.concurrent.TimeUnit.SECONDS;
-
 /**
  *
  */
-public class CacheNoValueClassOnServerNodeTest extends GridCommonAbstractTest {
-    /** */
-    public static final String NODE_START_MSG = "Test external node started";
-
-    /** */
-    private static final String CLIENT_CLS_NAME =
-        "org.apache.ignite.tests.p2p.cache.CacheNoValueClassOnServerTestClient";
-
-    /**
-     * @return Configuration.
-     */
-    private IgniteConfiguration createConfiguration() {
-        IgniteConfiguration cfg = new IgniteConfiguration();
-
-        cfg.setPeerClassLoadingEnabled(false);
-
-        cfg.setLocalHost("127.0.0.1");
-
-        TcpDiscoverySpi disco = new TcpDiscoverySpi();
-
-        disco.setIpFinderCleanFrequency(1000);
-
-        TcpDiscoveryVmIpFinder ipFinder = new TcpDiscoveryVmIpFinder();
-
-        ipFinder.setAddresses(Arrays.asList("127.0.0.1:47500..47509"));
-
-        disco.setIpFinder(ipFinder);
-
-        cfg.setDiscoverySpi(disco);
-
-        return cfg;
+public class CacheNoValueClassOnServerNodeTest extends IgniteNoClassOnServerAbstractTest {
+    /** {@inheritDoc} */
+    @Override protected String clientClassName() {
+        return "org.apache.ignite.tests.p2p.cache.CacheNoValueClassOnServerTestClient";
     }
-
-    /**
-     * @throws Exception If failed.
-     */
-    public void testNoValueClassOnServerNode() throws Exception {
-        // Check class is really not available.
-        try {
-            Class.forName("org.apache.ignite.tests.p2p.cache.Person");
-
-            fail();
-        }
-        catch (ClassNotFoundException ignore) {
-            // Expected exception.
-        }
-
-        try (Ignite ignite = Ignition.start(createConfiguration())) {
-            CacheConfiguration cfg = new CacheConfiguration();
-
-            cfg.setCopyOnRead(true); // To store only value bytes.
-
-            ignite.createCache(cfg);
-
-            final CountDownLatch clientReadyLatch = new CountDownLatch(1);
-
-            Collection<String> jvmArgs = Arrays.asList("-ea", "-DIGNITE_QUIET=false");
-
-            GridJavaProcess clientNode = null;
-
-            try {
-                String cp = U.getIgniteHome() + "/modules/extdata/p2p/target/classes/";
-
-                clientNode = GridJavaProcess.exec(
-                    CLIENT_CLS_NAME, null,
-                    log,
-                    new CI1<String>() {
-                        @Override public void apply(String s) {
-                            info("Client node: " + s);
-
-                            if (s.contains(NODE_START_MSG))
-                                clientReadyLatch.countDown();
-                        }
-                    },
-                    null,
-                    null,
-                    jvmArgs,
-                    cp
-                );
-
-                assertTrue(clientReadyLatch.await(60, SECONDS));
-
-                int exitCode = clientNode.getProcess().waitFor();
-
-                assertEquals("Unexpected exit code", 0, exitCode);
-            }
-            finally {
-                if (clientNode != null)
-                    clientNode.killProcess();
-            }
-        }
-    }
-
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/3a5c6f35/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/IgniteNoClassOnServerAbstractTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/IgniteNoClassOnServerAbstractTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/IgniteNoClassOnServerAbstractTest.java
new file mode 100644
index 0000000..4357ae7
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/IgniteNoClassOnServerAbstractTest.java
@@ -0,0 +1,135 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.cache.distributed;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.concurrent.CountDownLatch;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.Ignition;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.util.GridJavaProcess;
+import org.apache.ignite.internal.util.typedef.CI1;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+
+import static java.util.concurrent.TimeUnit.SECONDS;
+
+/**
+ *
+ */
+public abstract class IgniteNoClassOnServerAbstractTest extends GridCommonAbstractTest {
+    /** */
+    private static final String NODE_START_MSG = "Test external node started";
+
+    /**
+     * @return Client class name.
+     */
+    protected abstract String clientClassName();
+
+    /**
+     * @return Configuration.
+     */
+    private IgniteConfiguration createConfiguration() {
+        IgniteConfiguration cfg = new IgniteConfiguration();
+
+        cfg.setPeerClassLoadingEnabled(false);
+
+        cfg.setLocalHost("127.0.0.1");
+
+        TcpDiscoverySpi disco = new TcpDiscoverySpi();
+
+        disco.setIpFinderCleanFrequency(1000);
+
+        TcpDiscoveryVmIpFinder ipFinder = new TcpDiscoveryVmIpFinder();
+
+        ipFinder.setAddresses(Arrays.asList("127.0.0.1:47500..47509"));
+
+        disco.setIpFinder(ipFinder);
+
+        cfg.setDiscoverySpi(disco);
+
+        return cfg;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public final void testNoClassOnServerNode() throws Exception {
+        info("Run test with client: " + clientClassName());
+
+        // Check class is really not available.
+        try {
+            Class.forName("org.apache.ignite.tests.p2p.cache.Person");
+
+            fail();
+        }
+        catch (ClassNotFoundException ignore) {
+            // Expected exception.
+        }
+
+        try (Ignite ignite = Ignition.start(createConfiguration())) {
+            CacheConfiguration cfg = new CacheConfiguration();
+
+            cfg.setCopyOnRead(true); // To store only value bytes.
+
+            ignite.createCache(cfg);
+
+            final CountDownLatch clientReadyLatch = new CountDownLatch(1);
+
+            Collection<String> jvmArgs = Arrays.asList("-ea", "-DIGNITE_QUIET=false");
+
+            GridJavaProcess clientNode = null;
+
+            try {
+                String cp = U.getIgniteHome() + "/modules/extdata/p2p/target/classes/";
+
+                clientNode = GridJavaProcess.exec(
+                    clientClassName(), null,
+                    log,
+                    new CI1<String>() {
+                        @Override public void apply(String s) {
+                            info("Client node: " + s);
+
+                            if (s.contains(NODE_START_MSG))
+                                clientReadyLatch.countDown();
+                        }
+                    },
+                    null,
+                    null,
+                    jvmArgs,
+                    cp
+                );
+
+                assertTrue(clientReadyLatch.await(60, SECONDS));
+
+                int exitCode = clientNode.getProcess().waitFor();
+
+                assertEquals("Unexpected exit code", 0, exitCode);
+            }
+            finally {
+                if (clientNode != null)
+                    clientNode.killProcess();
+            }
+        }
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/3a5c6f35/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBinaryObjectsCacheDataStructuresSelfTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBinaryObjectsCacheDataStructuresSelfTestSuite.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBinaryObjectsCacheDataStructuresSelfTestSuite.java
index e15540a..f8769a0 100644
--- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBinaryObjectsCacheDataStructuresSelfTestSuite.java
+++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBinaryObjectsCacheDataStructuresSelfTestSuite.java
@@ -19,6 +19,7 @@ package org.apache.ignite.testsuites;
 
 import junit.framework.TestSuite;
 import org.apache.ignite.internal.binary.BinaryMarshaller;
+import org.apache.ignite.internal.processors.cache.datastructures.IgniteDataStructuresNoClassOnServerTest;
 import org.apache.ignite.testframework.config.GridTestProperties;
 
 /**
@@ -32,6 +33,10 @@ public class IgniteBinaryObjectsCacheDataStructuresSelfTestSuite {
     public static TestSuite suite() throws Exception {
         GridTestProperties.setProperty(GridTestProperties.MARSH_CLASS_NAME, BinaryMarshaller.class.getName());
 
-        return IgniteCacheDataStructuresSelfTestSuite.suite();
+        TestSuite suite = IgniteCacheDataStructuresSelfTestSuite.suite();
+
+        suite.addTestSuite(IgniteDataStructuresNoClassOnServerTest.class);
+
+        return suite;
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/3a5c6f35/modules/extdata/p2p/pom.xml
----------------------------------------------------------------------
diff --git a/modules/extdata/p2p/pom.xml b/modules/extdata/p2p/pom.xml
index 4863fdd..ec14930 100644
--- a/modules/extdata/p2p/pom.xml
+++ b/modules/extdata/p2p/pom.xml
@@ -39,6 +39,12 @@
             <artifactId>ignite-core</artifactId>
             <version>${project.version}</version>
         </dependency>
+
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>4.11</version>
+        </dependency>
     </dependencies>
 
     <build>

http://git-wip-us.apache.org/repos/asf/ignite/blob/3a5c6f35/modules/extdata/p2p/src/main/java/org/apache/ignite/tests/p2p/NoValueClassOnServerAbstractClient.java
----------------------------------------------------------------------
diff --git a/modules/extdata/p2p/src/main/java/org/apache/ignite/tests/p2p/NoValueClassOnServerAbstractClient.java b/modules/extdata/p2p/src/main/java/org/apache/ignite/tests/p2p/NoValueClassOnServerAbstractClient.java
new file mode 100644
index 0000000..9c9338b
--- /dev/null
+++ b/modules/extdata/p2p/src/main/java/org/apache/ignite/tests/p2p/NoValueClassOnServerAbstractClient.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.tests.p2p;
+
+import java.util.Arrays;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteLogger;
+import org.apache.ignite.Ignition;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
+
+/**
+ *
+ */
+public abstract class NoValueClassOnServerAbstractClient implements AutoCloseable {
+    /** */
+    protected final Ignite ignite;
+
+    /** */
+    private final IgniteLogger log;
+
+    /**
+     * @param args Command line arguments.
+     * @throws Exception If failed.
+     */
+    public NoValueClassOnServerAbstractClient(String[] args) throws Exception {
+        System.out.println("Starting test client node.");
+
+        IgniteConfiguration cfg = new IgniteConfiguration();
+
+        cfg.setPeerClassLoadingEnabled(false);
+
+        cfg.setClientMode(true);
+
+        cfg.setLocalHost("127.0.0.1");
+
+        TcpDiscoverySpi disco = new TcpDiscoverySpi();
+
+        TcpDiscoveryVmIpFinder ipFinder = new TcpDiscoveryVmIpFinder();
+
+        ipFinder.setAddresses(Arrays.asList("127.0.0.1:47500..47509"));
+
+        disco.setIpFinder(ipFinder);
+
+        cfg.setDiscoverySpi(disco);
+
+        ignite = Ignition.start(cfg);
+
+        System.out.println("Test external node started");
+
+        log = ignite.log().getLogger(getClass());
+
+        log.info("Started node [id=" + ignite.cluster().localNode().id() +
+            ", marsh=" + ignite.configuration().getMarshaller().getClass().getSimpleName() + ']');
+    }
+
+    /**
+     * @param msg Message.
+     */
+    protected final void info(String msg) {
+        log.info(msg);
+    }
+
+
+    /** {@inheritDoc} */
+    @Override public void close() throws Exception {
+        ignite.close();
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    protected abstract void runTest() throws Exception;
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/3a5c6f35/modules/extdata/p2p/src/main/java/org/apache/ignite/tests/p2p/cache/CacheNoValueClassOnServerTestClient.java
----------------------------------------------------------------------
diff --git a/modules/extdata/p2p/src/main/java/org/apache/ignite/tests/p2p/cache/CacheNoValueClassOnServerTestClient.java b/modules/extdata/p2p/src/main/java/org/apache/ignite/tests/p2p/cache/CacheNoValueClassOnServerTestClient.java
index bbf8abf..c1f3ff6 100644
--- a/modules/extdata/p2p/src/main/java/org/apache/ignite/tests/p2p/cache/CacheNoValueClassOnServerTestClient.java
+++ b/modules/extdata/p2p/src/main/java/org/apache/ignite/tests/p2p/cache/CacheNoValueClassOnServerTestClient.java
@@ -17,70 +17,59 @@
 
 package org.apache.ignite.tests.p2p.cache;
 
-import java.util.Arrays;
-import org.apache.ignite.Ignite;
 import org.apache.ignite.IgniteCache;
-import org.apache.ignite.Ignition;
-import org.apache.ignite.configuration.IgniteConfiguration;
-import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
-import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
+import org.apache.ignite.tests.p2p.NoValueClassOnServerAbstractClient;
+
+import static junit.framework.TestCase.assertEquals;
 
 /**
  *
  */
-public class CacheNoValueClassOnServerTestClient {
+public class CacheNoValueClassOnServerTestClient extends NoValueClassOnServerAbstractClient {
     /**
      * @param args Arguments.
      * @throws Exception If failed.
      */
-    public static void main(String[] args) throws Exception {
-        System.out.println("Starting test client node.");
-
-        IgniteConfiguration cfg = new IgniteConfiguration();
-
-        cfg.setPeerClassLoadingEnabled(false);
-
-        cfg.setClientMode(true);
-
-        cfg.setLocalHost("127.0.0.1");
-
-        TcpDiscoverySpi disco = new TcpDiscoverySpi();
-
-        TcpDiscoveryVmIpFinder ipFinder = new TcpDiscoveryVmIpFinder();
-
-        ipFinder.setAddresses(Arrays.asList("127.0.0.1:47500..47509"));
-
-        disco.setIpFinder(ipFinder);
-
-        cfg.setDiscoverySpi(disco);
+    private CacheNoValueClassOnServerTestClient(String[] args) throws Exception {
+        super(args);
+    }
 
-        try (Ignite ignite = Ignition.start(cfg)) {
-            System.out.println("Test external node started");
+    /** {@inheritDoc} */
+    @Override protected void runTest() throws Exception {
+        IgniteCache<Integer, Person> cache = ignite.cache(null);
 
-            int nodes = ignite.cluster().nodes().size();
+        for (int i = 0; i < 100; i++)
+            cache.put(i, new Person("name-" + i));
 
-            if (nodes != 2)
-                throw new Exception("Unexpected nodes number: " + nodes);
+        for (int i = 0; i < 100; i++) {
+            Person p = cache.get(i);
 
-            IgniteCache<Integer, Person> cache = ignite.cache(null);
+            if (p == null)
+                throw new Exception("Null result key: " + i);
 
-            for (int i = 0; i < 100; i++)
-                cache.put(i, new Person("name-" + i));
+            String expName = "name-" + i;
 
-            for (int i = 0; i < 100; i++) {
-                Person p = cache.get(i);
+            assertEquals(expName, p.getName());
 
-                if (p == null)
-                    throw new Exception("Null result key: " + i);
+            if (i % 10 == 0)
+                System.out.println("Get expected value: " + p.name());
+        }
+    }
 
-                String expName = "name-" + i;
+    /**
+     * @param args Arguments.
+     * @throws Exception If failed.
+     */
+    public static void main(String[] args) throws Exception {
+        try (CacheNoValueClassOnServerTestClient client = new CacheNoValueClassOnServerTestClient(args)) {
+            client.runTest();
+        }
+        catch (Throwable e) {
+            System.out.println("Unexpected error: " + e);
 
-                if (!expName.equals(p.name()))
-                    throw new Exception("Unexpected data: " + p.name());
+            e.printStackTrace(System.out);
 
-                if (i % 10 == 0)
-                    System.out.println("Get expected value: " + p.name());
-            }
+            System.exit(1);
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/3a5c6f35/modules/extdata/p2p/src/main/java/org/apache/ignite/tests/p2p/datastructures/DataStructuresNoClassOnServerTestClient.java
----------------------------------------------------------------------
diff --git a/modules/extdata/p2p/src/main/java/org/apache/ignite/tests/p2p/datastructures/DataStructuresNoClassOnServerTestClient.java b/modules/extdata/p2p/src/main/java/org/apache/ignite/tests/p2p/datastructures/DataStructuresNoClassOnServerTestClient.java
new file mode 100644
index 0000000..7cf2cc7
--- /dev/null
+++ b/modules/extdata/p2p/src/main/java/org/apache/ignite/tests/p2p/datastructures/DataStructuresNoClassOnServerTestClient.java
@@ -0,0 +1,181 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.tests.p2p.datastructures;
+
+import org.apache.ignite.IgniteAtomicReference;
+import org.apache.ignite.IgniteAtomicStamped;
+import org.apache.ignite.lang.IgniteBiTuple;
+import org.apache.ignite.tests.p2p.NoValueClassOnServerAbstractClient;
+import org.apache.ignite.tests.p2p.cache.Person;
+import org.apache.ignite.tests.p2p.cache.PersonKey;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ *
+ */
+public class DataStructuresNoClassOnServerTestClient extends NoValueClassOnServerAbstractClient {
+    /**
+     * @param args Arguments.
+     * @throws Exception If failed.
+     */
+    private DataStructuresNoClassOnServerTestClient(String[] args) throws Exception {
+        super(args);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void runTest() throws Exception {
+        testAtomicReference();
+
+        testAtomicStamped();
+    }
+
+    /**
+     *
+     */
+    private void testAtomicReference() {
+        info("Test atomic reference");
+
+        IgniteAtomicReference<Person> ref = ignite.atomicReference("ref1", null, true);
+
+        assertNull(ref.get());
+
+        ref.set(person("p1"));
+
+        assertEquals(person("p1"), ref.get());
+
+        assertTrue(ref.compareAndSet(person("p1"), person("p2")));
+
+        assertEquals(person("p2"), ref.get());
+
+        assertFalse(ref.compareAndSet(person("p1"), person("p3")));
+
+        assertEquals(person("p2"), ref.get());
+
+        assertTrue(ref.compareAndSet(person("p2"), null));
+
+        assertNull(ref.get());
+
+        assertTrue(ref.compareAndSet(null, person("p2")));
+
+        assertEquals(person("p2"), ref.get());
+
+        ref.close();
+
+        ref = ignite.atomicReference("ref2", person("p1"), true);
+
+        assertEquals(person("p1"), ref.get());
+    }
+
+    /**
+     *
+     */
+    private void testAtomicStamped() {
+        info("Test atomic stamped");
+
+        IgniteAtomicStamped<Person, PersonKey> stamped = ignite.atomicStamped("s1", null, null, true);
+
+        stamped.set(person("p1"), key(1));
+
+        checkStamped(stamped, "p1", 1);
+
+        assertTrue(stamped.compareAndSet(person("p1"), person("p2"), key(1), key(2)));
+
+        checkStamped(stamped, "p2", 2);
+
+        assertFalse(stamped.compareAndSet(person("p1"), person("p3"), key(1), key(3)));
+
+        checkStamped(stamped, "p2", 2);
+
+        assertFalse(stamped.compareAndSet(person("p2"), person("p3"), key(1), key(3)));
+
+        checkStamped(stamped, "p2", 2);
+
+        assertTrue(stamped.compareAndSet(person("p2"), null, key(2), key(3)));
+
+        checkStamped(stamped, null, 3);
+
+        assertTrue(stamped.compareAndSet(null, person("p2"), key(3), key(4)));
+
+        checkStamped(stamped, "p2", 4);
+
+        stamped.close();
+
+        stamped = ignite.atomicStamped("s2", person("p5"), key(5), true);
+
+        checkStamped(stamped, "p5", 5);
+    }
+
+    /**
+     * @param stamped Stamped.
+     * @param personName Expected person name.
+     * @param id Expected stamp.
+     */
+    private void checkStamped(IgniteAtomicStamped<Person, PersonKey> stamped, String personName, int id) {
+        assertEquals(person(personName), stamped.value());
+        assertEquals(key(id), stamped.stamp());
+
+        IgniteBiTuple<Person, PersonKey> t = stamped.get();
+
+        assertEquals(person(personName), t.get1());
+        assertEquals(key(id), t.get2());
+    }
+
+    /**
+     * @param name Person name.
+     * @return Person instance.
+     */
+    private Person person(String name) {
+        if (name == null)
+            return null;
+
+        Person p = new Person();
+
+        p.setName(name);
+
+        return p;
+    }
+
+    /**
+     * @param id Key ID.
+     * @return Key.
+     */
+    private PersonKey key(int id) {
+        return new PersonKey(id);
+    }
+
+    /**
+     * @param args Arguments.
+     * @throws Exception If failed.
+     */
+    public static void main(String[] args) throws Exception {
+        try (DataStructuresNoClassOnServerTestClient client = new DataStructuresNoClassOnServerTestClient(args)) {
+            client.runTest();
+        }
+        catch (Throwable e) {
+            System.out.println("Unexpected error: " + e);
+
+            e.printStackTrace(System.out);
+
+            System.exit(1);
+        }
+    }
+}