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

[53/53] [abbrv] ignite git commit: IGNITE-4851 - Fixed partition destroy race

IGNITE-4851 - Fixed partition destroy race


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

Branch: refs/heads/ignite-3477-master
Commit: baa3835ee60f9c9a0c7229b78c4603504fb5e522
Parents: 54213d6 6e67866
Author: Ilya Lantukh <il...@gridgain.com>
Authored: Mon Apr 10 18:55:00 2017 +0300
Committer: Alexey Goncharuk <al...@gmail.com>
Committed: Mon Apr 10 18:55:00 2017 +0300

----------------------------------------------------------------------
 .../processors/cache/GridCacheAdapter.java      |   2 +-
 .../cache/GridCacheConcurrentMap.java           |   5 +-
 .../cache/GridCacheConcurrentMapImpl.java       | 218 +++++++++++--------
 .../cache/GridCacheLocalConcurrentMap.java      |  54 +++++
 .../processors/cache/GridCacheMapEntry.java     |  14 +-
 .../dht/GridCachePartitionedConcurrentMap.java  |  15 +-
 .../distributed/dht/GridDhtLocalPartition.java  | 204 ++++++++++++-----
 .../distributed/near/GridNearCacheAdapter.java  |   3 +-
 .../cache/GridCacheAbstractFullApiSelfTest.java |   1 +
 ...ledAtomicOnheapMultiNodeFullApiSelfTest.java |  10 +
 ...nedAtomicOnheapMultiNodeFullApiSelfTest.java |  10 +
 .../cache/hibernate/HibernateCacheProxy.java    |   2 +-
 .../cache/hibernate/HibernateCacheProxy.java    |   2 +-
 13 files changed, 380 insertions(+), 160 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/baa3835e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheConcurrentMapImpl.java
----------------------------------------------------------------------
diff --cc modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheConcurrentMapImpl.java
index 10f5ca3,15a688b..0ef1fdb
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheConcurrentMapImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheConcurrentMapImpl.java
@@@ -120,103 -116,148 +116,158 @@@ public abstract class GridCacheConcurre
          GridCacheMapEntry doomed = null;
  
          boolean done = false;
 -
+         boolean reserved = false;
++        int sizeChange = 0;
  
-         while (!done) {
-             GridCacheMapEntry entry = map.get(key);
-             created = null;
-             doomed = null;
- 
-             if (entry == null) {
-                 if (create) {
-                     if (created0 == null)
-                         created0 = factory.create(ctx, topVer, key, key.hashCode(), val);
+         try {
+             while (!done) {
+                 GridCacheMapEntry entry = map.get(key);
+                 created = null;
+                 doomed = null;
  
-                     cur = created = created0;
+                 if (entry == null) {
+                     if (create) {
+                         if (created0 == null) {
+                             if (!reserved) {
+                                 if (!reserve())
+                                     return null;
  
-                     done = map.putIfAbsent(created.key(), created) == null;
-                 }
-                 else
-                     done = true;
-             }
-             else {
-                 if (entry.obsolete()) {
-                     doomed = entry;
+                                 reserved = true;
+                             }
  
-                     if (create) {
-                         if (created0 == null)
                              created0 = factory.create(ctx, topVer, key, key.hashCode(), val);
+                         }
  
                          cur = created = created0;
  
-                         done = map.replace(entry.key(), doomed, created);
+                         done = map.putIfAbsent(created.key(), created) == null;
                      }
                      else
-                         done = map.remove(entry.key(), doomed);
+                         done = true;
                  }
                  else {
-                     cur = entry;
+                     if (entry.obsolete()) {
+                         doomed = entry;
+ 
+                         if (create) {
+                             if (created0 == null) {
+                                 if (!reserved) {
+                                     if (!reserve())
+                                         return null;
+ 
+                                     reserved = true;
+                                 }
+ 
+                                 created0 = factory.create(ctx, topVer, key, key.hashCode(), val);
+                             }
+ 
+                             cur = created = created0;
  
-                     done = true;
+                             done = map.replace(entry.key(), doomed, created);
+                         }
+                         else
+                             done = map.remove(entry.key(), doomed);
+                     }
+                     else {
+                         cur = entry;
+ 
+                         done = true;
+                     }
                  }
              }
-         }
  
-         int sizeChange = 0;
 -            int sizeChange = 0;
++            sizeChange = 0;
+ 
+             if (doomed != null) {
+                 synchronized (doomed) {
+                     if (!doomed.deleted())
+                         sizeChange--;
+                 }
  
-         if (doomed != null) {
-             synchronized (doomed) {
-                 if (!doomed.deleted())
-                     sizeChange--;
+                 if (ctx.events().isRecordable(EVT_CACHE_ENTRY_DESTROYED))
+                     ctx.events().addEvent(doomed.partition(),
+                         doomed.key(),
+                         ctx.localNodeId(),
+                         (IgniteUuid)null,
+                         null,
+                         EVT_CACHE_ENTRY_DESTROYED,
+                         null,
+                         false,
+                         null,
+                         false,
+                         null,
+                         null,
+                         null,
+                         true);
              }
  
-             if (ctx.events().isRecordable(EVT_CACHE_ENTRY_DESTROYED))
-                 ctx.events().addEvent(doomed.partition(),
-                     doomed.key(),
-                     ctx.localNodeId(),
-                     (IgniteUuid)null,
-                     null,
-                     EVT_CACHE_ENTRY_DESTROYED,
-                     null,
-                     false,
-                     null,
-                     false,
-                     null,
-                     null,
-                     null,
-                     true);
+             if (created != null) {
+                 sizeChange++;
+ 
+                 if (ctx.events().isRecordable(EVT_CACHE_ENTRY_CREATED))
+                     ctx.events().addEvent(created.partition(),
+                         created.key(),
+                         ctx.localNodeId(),
+                         (IgniteUuid)null,
+                         null,
+                         EVT_CACHE_ENTRY_CREATED,
+                         null,
+                         false,
+                         null,
+                         false,
+                         null,
+                         null,
+                         null,
+                         true);
+ 
+                 if (touch)
+                     ctx.evicts().touch(
+                         cur,
+                         topVer);
+             }
+ 
+             assert Math.abs(sizeChange) <= 1;
+ 
 -            if (sizeChange == -1)
 -                decrementPublicSize(cur);
 -            else if (sizeChange == 1) {
 -                assert reserved;
 -
 -                incrementPublicSize(cur);
 -            }
 -
+             return cur;
          }
+         finally {
+             if (reserved)
 -                release();
++                release(sizeChange, cur);
++            else {
++                if (sizeChange != 0) {
++                    assert sizeChange == -1;
 +
-         if (created != null) {
-             sizeChange++;
- 
-             if (ctx.events().isRecordable(EVT_CACHE_ENTRY_CREATED))
-                 ctx.events().addEvent(created.partition(),
-                     created.key(),
-                     ctx.localNodeId(),
-                     (IgniteUuid)null,
-                     null,
-                     EVT_CACHE_ENTRY_CREATED,
-                     null,
-                     false,
-                     null,
-                     false,
-                     null,
-                     null,
-                     null,
-                     true);
- 
-             if (touch)
-                 ctx.evicts().touch(
-                     cur,
-                     topVer);
++                    decrementPublicSize(cur);
++                }
++            }
          }
+     }
  
-         if (sizeChange != 0)
-             pubSize.addAndGet(sizeChange);
+     /**
+      *
+      */
+     protected boolean reserve() {
+         return true;
+     }
  
-         return cur;
+     /**
+      *
+      */
+     protected void release() {
+         // No-op.
+     }
+ 
++    /**
++     * @param sizeChange Size delta.
++     * @param e Map entry.
++     */
++    protected void release(int sizeChange, GridCacheEntryEx e) {
++        if (sizeChange == 1)
++            incrementPublicSize(e);
++        else if (sizeChange == -1)
++            decrementPublicSize(e);
 +    }
 +
      /** {@inheritDoc} */
      @Override public boolean removeEntry(final GridCacheEntryEx entry) {
          boolean removed = map.remove(entry.key(), entry);

http://git-wip-us.apache.org/repos/asf/ignite/blob/baa3835e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtLocalPartition.java
----------------------------------------------------------------------
diff --cc modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtLocalPartition.java
index 46b2bf8,5c2445a..8566b35
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtLocalPartition.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtLocalPartition.java
@@@ -435,17 -426,21 +426,35 @@@ public class GridDhtLocalPartition exte
       * Releases previously reserved partition.
       */
      @Override public void release() {
++        release0(0);
++    }
++
++    @Override protected void release(int sizeChange, GridCacheEntryEx e) {
++        release0(sizeChange);
++    }
++
++    /**
++     * @param sizeChange Size change delta.
++     */
++    private void release0(int sizeChange) {
          while (true) {
-             long reservations = state.get();
+             long state = this.state.get();
  
-             if ((int)(reservations & 0xFFFF) == 0)
+             int reservations = getReservations(state);
+ 
+             if (reservations == 0)
                  return;
  
-             assert (int)(reservations >> 32) != EVICTED.ordinal();
+             assert getPartState(state) != EVICTED;
+ 
+             long newState = setReservations(state, --reservations);
++            newState = setSize(newState, getSize(newState) + sizeChange);
++
++            assert getSize(newState) == getSize(state) + sizeChange;
  
              // Decrement reservations.
-             if (state.compareAndSet(reservations, --reservations)) {
-                 if ((reservations & 0xFFFF) == 0 && shouldBeRenting)
+             if (this.state.compareAndSet(state, newState)) {
+                 if (reservations == 0 && shouldBeRenting)
                      rent(true);
  
                  try {
@@@ -965,6 -963,57 +977,84 @@@
              "createTime", U.format(createTime));
      }
  
+     /** {@inheritDoc} */
+     @Override public int publicSize() {
+         return getSize(state.get());
+     }
+ 
+     /** {@inheritDoc} */
+     @Override public void incrementPublicSize(GridCacheEntryEx e) {
+         while (true) {
+             long state = this.state.get();
+ 
+             if (this.state.compareAndSet(state, setSize(state, getSize(state) + 1)))
+                 return;
+         }
+     }
+ 
+     /** {@inheritDoc} */
+     @Override public void decrementPublicSize(GridCacheEntryEx e) {
+         while (true) {
+             long state = this.state.get();
+ 
+             assert getPartState(state) != EVICTED;
+ 
+             if (this.state.compareAndSet(state, setSize(state, getSize(state) - 1)))
+                 return;
+         }
+     }
+ 
++    /**
++     * @param state Composite state.
++     * @return Partition state.
++     */
+     private static GridDhtPartitionState getPartState(long state) {
+         return GridDhtPartitionState.fromOrdinal((int)(state & (0x0000000000000007L)));
+     }
+ 
++    /**
++     * @param state Composite state to update.
++     * @param partState Partition state.
++     * @return Updated composite state.
++     */
+     private static long setPartState(long state, GridDhtPartitionState partState) {
+         return (state & (~0x0000000000000007L)) | partState.ordinal();
+     }
+ 
++    /**
++     * @param state Composite state.
++     * @return Reservations.
++     */
+     private static int getReservations(long state) {
+         return (int)((state & 0x00000000FFFF0000L) >> 16);
+     }
+ 
++    /**
++     * @param state Composite state to update.
++     * @param reservations Reservations to set.
++     * @return Updated composite state.
++     */
+     private static long setReservations(long state, int reservations) {
+         return (state & (~0x00000000FFFF0000L)) | (reservations << 16);
+     }
+ 
++    /**
++     * @param state Composite state.
++     * @return Size.
++     */
+     private static int getSize(long state) {
+         return (int)((state & 0xFFFFFFFF00000000L) >> 32);
+     }
+ 
++    /**
++     * @param state Composite state to update.
++     * @param size Size to set.
++     * @return Updated composite state.
++     */
+     private static long setSize(long state, int size) {
+         return (state & (~0xFFFFFFFF00000000L)) | ((long)size << 32);
+     }
+ 
      /**
       * Removed entry holder.
       */

http://git-wip-us.apache.org/repos/asf/ignite/blob/baa3835e/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheAbstractFullApiSelfTest.java
----------------------------------------------------------------------
diff --cc modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheAbstractFullApiSelfTest.java
index b70ca6a,b70ca6a..af80e00
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheAbstractFullApiSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheAbstractFullApiSelfTest.java
@@@ -400,6 -400,6 +400,7 @@@ public abstract class GridCacheAbstract
  
          assertEquals(0, cache.localSize());
          assertEquals(0, cache.size());
++        assertEquals(0, cache.size(ONHEAP));
  
          dfltIgnite = null;
      }

http://git-wip-us.apache.org/repos/asf/ignite/blob/baa3835e/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridCachePartitionedNearDisabledAtomicOnheapMultiNodeFullApiSelfTest.java
----------------------------------------------------------------------
diff --cc modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridCachePartitionedNearDisabledAtomicOnheapMultiNodeFullApiSelfTest.java
index 20e7b7a,20e7b7a..eb5a1dd
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridCachePartitionedNearDisabledAtomicOnheapMultiNodeFullApiSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridCachePartitionedNearDisabledAtomicOnheapMultiNodeFullApiSelfTest.java
@@@ -25,4 -25,4 +25,14 @@@ public class GridCachePartitionedNearDi
      @Override protected CacheAtomicityMode atomicityMode() {
          return CacheAtomicityMode.ATOMIC;
      }
++
++    /** {@inheritDoc} */
++    @Override protected boolean lockingEnabled() {
++        return false;
++    }
++
++    /** {@inheritDoc} */
++    @Override protected boolean txShouldBeUsed() {
++        return false;
++    }
  }

http://git-wip-us.apache.org/repos/asf/ignite/blob/baa3835e/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/GridCachePartitionedAtomicOnheapMultiNodeFullApiSelfTest.java
----------------------------------------------------------------------
diff --cc modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/GridCachePartitionedAtomicOnheapMultiNodeFullApiSelfTest.java
index 703d88c,703d88c..573c5a4
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/GridCachePartitionedAtomicOnheapMultiNodeFullApiSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/GridCachePartitionedAtomicOnheapMultiNodeFullApiSelfTest.java
@@@ -25,4 -25,4 +25,14 @@@ public class GridCachePartitionedAtomic
      @Override protected CacheAtomicityMode atomicityMode() {
          return CacheAtomicityMode.ATOMIC;
      }
++
++    /** {@inheritDoc} */
++    @Override protected boolean lockingEnabled() {
++        return false;
++    }
++
++    /** {@inheritDoc} */
++    @Override protected boolean txShouldBeUsed() {
++        return false;
++    }
  }

http://git-wip-us.apache.org/repos/asf/ignite/blob/baa3835e/modules/hibernate/src/main/java/org/apache/ignite/cache/hibernate/HibernateCacheProxy.java
----------------------------------------------------------------------
diff --cc modules/hibernate/src/main/java/org/apache/ignite/cache/hibernate/HibernateCacheProxy.java
index 69d9097,69d9097..c814f9a
--- a/modules/hibernate/src/main/java/org/apache/ignite/cache/hibernate/HibernateCacheProxy.java
+++ b/modules/hibernate/src/main/java/org/apache/ignite/cache/hibernate/HibernateCacheProxy.java
@@@ -50,7 -50,7 +50,7 @@@ import org.apache.ignite.transactions.T
  import org.jetbrains.annotations.Nullable;
  
  /**
-- * Hibernate cache proxy.
++ * Hibernate cache proxy used to substitute hibernate keys with ignite keys.
   */
  public class HibernateCacheProxy implements IgniteInternalCache<Object, Object> {
      /** Delegate. */

http://git-wip-us.apache.org/repos/asf/ignite/blob/baa3835e/modules/hibernate5/src/main/java/org/apache/ignite/cache/hibernate/HibernateCacheProxy.java
----------------------------------------------------------------------
diff --cc modules/hibernate5/src/main/java/org/apache/ignite/cache/hibernate/HibernateCacheProxy.java
index 69d9097,69d9097..c814f9a
--- a/modules/hibernate5/src/main/java/org/apache/ignite/cache/hibernate/HibernateCacheProxy.java
+++ b/modules/hibernate5/src/main/java/org/apache/ignite/cache/hibernate/HibernateCacheProxy.java
@@@ -50,7 -50,7 +50,7 @@@ import org.apache.ignite.transactions.T
  import org.jetbrains.annotations.Nullable;
  
  /**
-- * Hibernate cache proxy.
++ * Hibernate cache proxy used to substitute hibernate keys with ignite keys.
   */
  public class HibernateCacheProxy implements IgniteInternalCache<Object, Object> {
      /** Delegate. */