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

sdanilov pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git


The following commit(s) were added to refs/heads/main by this push:
     new dcaa4da3ae IGNITE-19362 Fix deadlock while restarting with existing 
raft snapshot and scheduled index rebuild (#1983)
dcaa4da3ae is described below

commit dcaa4da3ae31578fe49efcab3a0bbde2142ba0d7
Author: Semyon Danilov <[email protected]>
AuthorDate: Wed Apr 26 12:02:08 2023 +0400

    IGNITE-19362 Fix deadlock while restarting with existing raft snapshot and 
scheduled index rebuild (#1983)
---
 .../storage/snapshot/SnapshotExecutorImpl.java     |  8 +++-
 .../runner/app/ItIgniteNodeRestartTest.java        | 49 ++++++++++++++++++++++
 2 files changed, 56 insertions(+), 1 deletion(-)

diff --git 
a/modules/raft/src/main/java/org/apache/ignite/raft/jraft/storage/snapshot/SnapshotExecutorImpl.java
 
b/modules/raft/src/main/java/org/apache/ignite/raft/jraft/storage/snapshot/SnapshotExecutorImpl.java
index 30d966add3..f005b3199a 100644
--- 
a/modules/raft/src/main/java/org/apache/ignite/raft/jraft/storage/snapshot/SnapshotExecutorImpl.java
+++ 
b/modules/raft/src/main/java/org/apache/ignite/raft/jraft/storage/snapshot/SnapshotExecutorImpl.java
@@ -250,7 +250,13 @@ public class SnapshotExecutorImpl implements 
SnapshotExecutor {
         final FirstSnapshotLoadDone done = new FirstSnapshotLoadDone(reader);
         Requires.requireTrue(this.fsmCaller.onSnapshotLoad(done));
         try {
-            done.waitForRun();
+            // TODO: IGNITE-19363 We want to avoid deadlock for now, but this 
is an ad-hoc decision.
+            // We don't wait for the partition's snapshot load closure to 
finish here.
+            if (!node.getNodeId().getGroupId().contains("part")) {
+                done.waitForRun();
+            } else {
+                done.status = Status.OK();
+            }
         }
         catch (final InterruptedException e) {
             LOG.warn("Wait for FirstSnapshotLoadDone run is interrupted.");
diff --git 
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ItIgniteNodeRestartTest.java
 
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ItIgniteNodeRestartTest.java
index 1fcc58cb61..c4eef0882a 100644
--- 
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ItIgniteNodeRestartTest.java
+++ 
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ItIgniteNodeRestartTest.java
@@ -107,6 +107,7 @@ import org.apache.ignite.internal.table.TableImpl;
 import org.apache.ignite.internal.table.distributed.TableManager;
 import org.apache.ignite.internal.table.distributed.TableMessageGroup;
 import 
org.apache.ignite.internal.table.distributed.raft.snapshot.outgoing.OutgoingSnapshotsManager;
+import org.apache.ignite.internal.table.distributed.storage.InternalTableImpl;
 import org.apache.ignite.internal.testframework.IgniteAbstractTest;
 import org.apache.ignite.internal.testframework.TestIgnitionManager;
 import org.apache.ignite.internal.testframework.WithSystemProperty;
@@ -878,6 +879,54 @@ public class ItIgniteNodeRestartTest extends 
IgniteAbstractTest {
         checkTableWithData(ignite, TABLE_NAME);
     }
 
+    /**
+     * Restarts the node which stores some data.
+     */
+    @Test
+    public void nodeWithDataAndIndexRebuildTest() throws InterruptedException {
+        IgniteImpl ignite = startNode(0);
+
+        int partitions = 20;
+
+        createTableWithData(List.of(ignite), TABLE_NAME, 1, partitions);
+
+        TableImpl table = (TableImpl) ignite.tables().table(TABLE_NAME);
+
+        InternalTableImpl internalTable = (InternalTableImpl) 
table.internalTable();
+
+        CompletableFuture[] flushFuts = new CompletableFuture[partitions];
+
+        for (int i = 0; i < partitions; i++) {
+            // Flush data on disk, so that we will have a snapshot to read on 
restart.
+            flushFuts[i] = internalTable.storage().getMvPartition(i).flush();
+        }
+
+        assertThat(CompletableFuture.allOf(flushFuts), 
willCompleteSuccessfully());
+
+        // Add more data, so that on restart there will be a index rebuilding 
operation.
+        try (Session session = ignite.sql().createSession()) {
+            for (int i = 0; i < 100; i++) {
+                session.execute(null, "INSERT INTO " + TABLE_NAME + "(id, 
name) VALUES (?, ?)",
+                        i + 500, VALUE_PRODUCER.apply(i + 500));
+            }
+        }
+
+        stopNode(0);
+
+        ignite = startNode(0);
+
+        checkTableWithData(ignite, TABLE_NAME);
+
+        table = (TableImpl) ignite.tables().table(TABLE_NAME);
+
+        // Check data that was added after flush.
+        for (int i = 0; i < 100; i++) {
+            Tuple row = table.keyValueView().get(null, 
Tuple.create().set("id", i + 500));
+
+            assertEquals(VALUE_PRODUCER.apply(i + 500), 
row.stringValue("name"));
+        }
+    }
+
     /**
      * Starts two nodes and checks that the data are storing through restarts. 
Nodes restart in the same order when they started at first.
      */

Reply via email to