This is an automated email from the ASF dual-hosted git repository.

agoncharuk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git

commit 281b41ed6d25d0ea95585ca44ff62095a5135534
Author: Sergey Chugunov <schugu...@gridgain.com>
AuthorDate: Thu Jan 30 14:02:22 2020 +0300

    IGNITE-12594 Fix deadlock between GridCacheDataStore#purgeExpiredInternal 
and GridNearTxLocal#enlistWriteEntry - Fixes #7325.
---
 .../cache/CacheOffheapEvictionManager.java         |  5 ++++
 .../processors/cache/GridCacheMapEntry.java        | 27 ++++++++++------------
 .../distributed/dht/GridPartitionedGetFuture.java  |  5 ++++
 .../dht/GridPartitionedSingleGetFuture.java        |  5 ++++
 .../cache/distributed/near/GridNearGetFuture.java  |  4 ++++
 .../persistence/DistributedMetaStorageImpl.java    | 17 ++++++++++----
 6 files changed, 44 insertions(+), 19 deletions(-)

diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheOffheapEvictionManager.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheOffheapEvictionManager.java
index 6813fec..9da4753 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheOffheapEvictionManager.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheOffheapEvictionManager.java
@@ -39,6 +39,8 @@ public class CacheOffheapEvictionManager extends 
GridCacheManagerAdapter impleme
         if (e.detached())
             return;
 
+        cctx.shared().database().checkpointReadLock();
+
         try {
             boolean evicted = 
e.evictInternal(GridCacheVersionManager.EVICT_VER, null, false)
                 || e.markObsoleteIfEmpty(null);
@@ -49,6 +51,9 @@ public class CacheOffheapEvictionManager extends 
GridCacheManagerAdapter impleme
         catch (IgniteCheckedException ex) {
             U.error(log, "Failed to evict entry from cache: " + e, ex);
         }
+        finally {
+            cctx.shared().database().checkpointReadUnlock();
+        }
     }
 
     /** {@inheritDoc} */
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMapEntry.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMapEntry.java
index 5969666..1ad7eec 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMapEntry.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMapEntry.java
@@ -17,6 +17,10 @@
 
 package org.apache.ignite.internal.processors.cache;
 
+import javax.cache.Cache;
+import javax.cache.expiry.ExpiryPolicy;
+import javax.cache.processor.EntryProcessor;
+import javax.cache.processor.EntryProcessorResult;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -27,10 +31,6 @@ import java.util.UUID;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.concurrent.locks.ReadWriteLock;
 import java.util.concurrent.locks.ReentrantLock;
-import javax.cache.Cache;
-import javax.cache.expiry.ExpiryPolicy;
-import javax.cache.processor.EntryProcessor;
-import javax.cache.processor.EntryProcessorResult;
 import org.apache.ignite.IgniteCache;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.IgniteException;
@@ -538,6 +538,8 @@ public abstract class GridCacheMapEntry extends 
GridMetadataAwareAdapter impleme
         boolean deferred = false;
         GridCacheVersion ver0 = null;
 
+        cctx.shared().database().checkpointReadLock();
+
         lockEntry();
 
         try {
@@ -572,6 +574,8 @@ public abstract class GridCacheMapEntry extends 
GridMetadataAwareAdapter impleme
         }
         finally {
             unlockEntry();
+
+            cctx.shared().database().checkpointReadUnlock();
         }
 
         if (obsolete) {
@@ -4085,17 +4089,10 @@ public abstract class GridCacheMapEntry extends 
GridMetadataAwareAdapter impleme
         if (log.isTraceEnabled())
             log.trace("onExpired clear [key=" + key + ", entry=" + 
System.identityHashCode(this) + ']');
 
-        cctx.shared().database().checkpointReadLock();
-
-        try {
-            if (cctx.mvccEnabled())
-                cctx.offheap().mvccRemoveAll(this);
-            else
-                removeValue();
-        }
-        finally {
-            cctx.shared().database().checkpointReadUnlock();
-        }
+        if (cctx.mvccEnabled())
+            cctx.offheap().mvccRemoveAll(this);
+        else
+            removeValue();
 
         if (cctx.events().isRecordable(EVT_CACHE_OBJECT_EXPIRED)) {
             cctx.events().addEvent(partition(),
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridPartitionedGetFuture.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridPartitionedGetFuture.java
index 6ce1863..d1706e1 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridPartitionedGetFuture.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridPartitionedGetFuture.java
@@ -445,6 +445,8 @@ public class GridPartitionedGetFuture<K, V> extends 
CacheDistributedGetFutureAda
         boolean evt = !skipVals;
 
         while (true) {
+            cctx.shared().database().checkpointReadLock();
+
             try {
                 boolean skipEntry = readNoEntry;
 
@@ -572,6 +574,9 @@ public class GridPartitionedGetFuture<K, V> extends 
CacheDistributedGetFutureAda
 
                 return true;
             }
+            finally {
+                cctx.shared().database().checkpointReadUnlock();
+            }
         }
     }
 
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridPartitionedSingleGetFuture.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridPartitionedSingleGetFuture.java
index a82f5b5..08abf5e 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridPartitionedSingleGetFuture.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridPartitionedSingleGetFuture.java
@@ -434,6 +434,8 @@ public class GridPartitionedSingleGetFuture extends 
GridCacheFutureAdapter<Objec
         boolean evt = !skipVals;
 
         while (true) {
+            cctx.shared().database().checkpointReadLock();
+
             try {
                 CacheObject v = null;
                 GridCacheVersion ver = null;
@@ -560,6 +562,9 @@ public class GridPartitionedSingleGetFuture extends 
GridCacheFutureAdapter<Objec
 
                 return true;
             }
+            finally {
+                cctx.shared().database().checkpointReadUnlock();
+            }
         }
     }
 
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearGetFuture.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearGetFuture.java
index b082726..d4513b7 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearGetFuture.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearGetFuture.java
@@ -483,6 +483,8 @@ public final class GridNearGetFuture<K, V> extends 
CacheDistributedGetFutureAdap
         assert dht.context().affinityNode() : this;
 
         while (true) {
+            cctx.shared().database().checkpointReadLock();
+
             GridCacheEntryEx dhtEntry = null;
 
             try {
@@ -558,6 +560,8 @@ public final class GridNearGetFuture<K, V> extends 
CacheDistributedGetFutureAdap
                 return false;
             }
             finally {
+                cctx.shared().database().checkpointReadUnlock();
+
                 if (dhtEntry != null)
                     // Near cache is enabled, so near entry will be enlisted 
in the transaction.
                     // Always touch DHT entry in this case.
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/metastorage/persistence/DistributedMetaStorageImpl.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/metastorage/persistence/DistributedMetaStorageImpl.java
index 242c65c..038d830 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/metastorage/persistence/DistributedMetaStorageImpl.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/metastorage/persistence/DistributedMetaStorageImpl.java
@@ -273,6 +273,8 @@ public class DistributedMetaStorageImpl extends 
GridProcessorAdapter
         }
         finally {
             lock.writeLock().unlock();
+
+            cancelUpdateFutures();
         }
     }
 
@@ -874,16 +876,23 @@ public class DistributedMetaStorageImpl extends 
GridProcessorAdapter
 
             ver = INITIAL_VERSION;
 
-            for (GridFutureAdapter<Boolean> fut : updateFuts.values())
-                fut.onDone(new IgniteCheckedException("Client was disconnected 
during the operation."));
-
-            updateFuts.clear();
+            cancelUpdateFutures();
         }
         finally {
             lock.writeLock().unlock();
         }
     }
 
+    /**
+     * Cancel all waiting futures and clear the map.
+     */
+    private void cancelUpdateFutures() {
+        for (GridFutureAdapter<Boolean> fut : updateFuts.values())
+            fut.onDone(new IgniteCheckedException("Client was disconnected 
during the operation."));
+
+        updateFuts.clear();
+    }
+
     /** {@inheritDoc} */
     @Override public IgniteInternalFuture<?> onReconnected(boolean 
clusterRestarted) {
         assert isClient;

Reply via email to