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

vpyatkov 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 57593d5201 IGNITE-20599 Implement 'NOT_TOMBSTONE' operation in the 
meta storage dsl. (#2722)
57593d5201 is described below

commit 57593d5201c895e0db6e59b11345b1baed9425c1
Author: Mirza Aliev <[email protected]>
AuthorDate: Sun Oct 22 16:32:39 2023 +0400

    IGNITE-20599 Implement 'NOT_TOMBSTONE' operation in the meta storage dsl. 
(#2722)
---
 .../distributionzones/DistributionZoneManager.java |   5 +-
 .../internal/metastorage/dsl/ConditionType.java    |   5 +-
 .../internal/metastorage/dsl/Conditions.java       |  13 +++
 .../metastorage/dsl/ConditionTypeTest.java         |   2 +
 .../metastorage/server/TombstoneCondition.java     |  37 ++++++-
 .../server/raft/MetaStorageWriteHandler.java       |   5 +-
 .../server/BasicOperationsKeyValueStorageTest.java | 109 ++++++++++++++++++++-
 .../metastorage/server/TombstoneConditionTest.java |  16 ++-
 ...niteDistributionZoneManagerNodeRestartTest.java |   1 +
 9 files changed, 183 insertions(+), 10 deletions(-)

diff --git 
a/modules/distribution-zones/src/main/java/org/apache/ignite/internal/distributionzones/DistributionZoneManager.java
 
b/modules/distribution-zones/src/main/java/org/apache/ignite/internal/distributionzones/DistributionZoneManager.java
index ae1e59ef3b..0e8bd9c4f2 100644
--- 
a/modules/distribution-zones/src/main/java/org/apache/ignite/internal/distributionzones/DistributionZoneManager.java
+++ 
b/modules/distribution-zones/src/main/java/org/apache/ignite/internal/distributionzones/DistributionZoneManager.java
@@ -421,8 +421,9 @@ public class DistributionZoneManager implements 
IgniteComponent {
 
             Set<Node> dataNodes = 
logicalTopology.stream().map(NodeWithAttributes::node).collect(toSet());
 
-            return initDataNodesAndTriggerKeysInMetaStorage(zoneId, 
causalityToken, dataNodes)
-                    .thenRun(() -> 
causalityDataNodesEngine.onCreateOrRestoreZoneState(causalityToken, zone));
+            
causalityDataNodesEngine.onCreateOrRestoreZoneState(causalityToken, zone);
+
+            return initDataNodesAndTriggerKeysInMetaStorage(zoneId, 
causalityToken, dataNodes);
         } else {
             // Restart case, when topologyAugmentationMap has already been 
saved during a cluster work.
             ConcurrentSkipListMap<Long, Augmentation> topologyAugmentationMap 
= fromBytes(topologyAugmentationMapFromVault.value());
diff --git 
a/modules/metastorage-api/src/main/java/org/apache/ignite/internal/metastorage/dsl/ConditionType.java
 
b/modules/metastorage-api/src/main/java/org/apache/ignite/internal/metastorage/dsl/ConditionType.java
index 7acc732c25..d2bfd900cc 100644
--- 
a/modules/metastorage-api/src/main/java/org/apache/ignite/internal/metastorage/dsl/ConditionType.java
+++ 
b/modules/metastorage-api/src/main/java/org/apache/ignite/internal/metastorage/dsl/ConditionType.java
@@ -64,5 +64,8 @@ public enum ConditionType {
     KEY_NOT_EXISTS,
 
     /** Tombstone condition type for a key. */
-    TOMBSTONE
+    TOMBSTONE,
+
+    /** Not-tombstone condition type for a key. */
+    NOT_TOMBSTONE
 }
diff --git 
a/modules/metastorage-api/src/main/java/org/apache/ignite/internal/metastorage/dsl/Conditions.java
 
b/modules/metastorage-api/src/main/java/org/apache/ignite/internal/metastorage/dsl/Conditions.java
index 8ff4b9f816..89ece8effc 100644
--- 
a/modules/metastorage-api/src/main/java/org/apache/ignite/internal/metastorage/dsl/Conditions.java
+++ 
b/modules/metastorage-api/src/main/java/org/apache/ignite/internal/metastorage/dsl/Conditions.java
@@ -256,6 +256,19 @@ public final class Conditions {
                 .build();
     }
 
+    /**
+     * Produces the condition of type {@link ConditionType#NOT_TOMBSTONE}. 
This condition tests that an entry's value, identified by the
+     * given key, is not a tombstone.
+     *
+     * @return The condition of type {@link ConditionType#NOT_TOMBSTONE}.
+     */
+    public static SimpleCondition notTombstone(ByteArray key) {
+        return MSG_FACTORY.simpleCondition()
+                .key(key.bytes())
+                .conditionType(ConditionType.NOT_TOMBSTONE.ordinal())
+                .build();
+    }
+
     /**
      * Produces the condition of type {@link ConditionType#KEY_EXISTS}. This 
condition tests the existence of an entry identified by the
      * given key.
diff --git 
a/modules/metastorage-api/src/test/java/org/apache/ignite/internal/metastorage/dsl/ConditionTypeTest.java
 
b/modules/metastorage-api/src/test/java/org/apache/ignite/internal/metastorage/dsl/ConditionTypeTest.java
index 1d318a2c92..d7ac47d708 100644
--- 
a/modules/metastorage-api/src/test/java/org/apache/ignite/internal/metastorage/dsl/ConditionTypeTest.java
+++ 
b/modules/metastorage-api/src/test/java/org/apache/ignite/internal/metastorage/dsl/ConditionTypeTest.java
@@ -57,5 +57,7 @@ class ConditionTypeTest {
         assertEquals(13, ConditionType.KEY_NOT_EXISTS.ordinal());
 
         assertEquals(14, ConditionType.TOMBSTONE.ordinal());
+
+        assertEquals(15, ConditionType.NOT_TOMBSTONE.ordinal());
     }
 }
diff --git 
a/modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/server/TombstoneCondition.java
 
b/modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/server/TombstoneCondition.java
index ebf8c1708e..aa7a6dd4cc 100644
--- 
a/modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/server/TombstoneCondition.java
+++ 
b/modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/server/TombstoneCondition.java
@@ -23,18 +23,51 @@ import org.apache.ignite.internal.metastorage.Entry;
  * Condition tests an entry's value is tombstone in meta storage. Entry is 
tombstone if it is not empty and doesn't exists.
  */
 public class TombstoneCondition extends AbstractSimpleCondition {
+    /** Condition type. */
+    private final TombstoneCondition.Type type;
+
     /**
      * Constructs a condition with the given entry key.
      *
+     * @param type Condition type. Can't be {@code null}.
      * @param key Key identifies an entry which the condition will applied to.
      */
-    public TombstoneCondition(byte[] key) {
+    public TombstoneCondition(TombstoneCondition.Type type, byte[] key) {
         super(key);
+
+        this.type = type;
     }
 
     /** {@inheritDoc} */
     @Override
     public boolean test(Entry e) {
-        return e.tombstone();
+        return type.test(e.tombstone());
+    }
+
+    /** Defines tombstone condition types. */
+    public enum Type {
+        /** Tombstone condition type. */
+        TOMBSTONE {
+            @Override
+            public boolean test(boolean res) {
+                return res;
+            }
+        },
+
+        /** Not tombstone condition type. */
+        NOT_TOMBSTONE {
+            @Override
+            public boolean test(boolean res) {
+                return !res;
+            }
+        };
+
+        /**
+         * Interprets comparison result.
+         *
+         * @param res The result of comparison.
+         * @return The interpretation of the comparison result.
+         */
+        public abstract boolean test(boolean res);
     }
 }
diff --git 
a/modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/server/raft/MetaStorageWriteHandler.java
 
b/modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/server/raft/MetaStorageWriteHandler.java
index c28ef2db2c..91feed7beb 100644
--- 
a/modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/server/raft/MetaStorageWriteHandler.java
+++ 
b/modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/server/raft/MetaStorageWriteHandler.java
@@ -227,7 +227,10 @@ public class MetaStorageWriteHandler {
                     return new 
ExistenceCondition(ExistenceCondition.Type.NOT_EXISTS, simpleCondition.key());
 
                 case TOMBSTONE:
-                    return new TombstoneCondition(simpleCondition.key());
+                    return new 
TombstoneCondition(TombstoneCondition.Type.TOMBSTONE, simpleCondition.key());
+
+                case NOT_TOMBSTONE:
+                    return new 
TombstoneCondition(TombstoneCondition.Type.NOT_TOMBSTONE, 
simpleCondition.key());
 
                 default:
                     throw new IllegalArgumentException("Unexpected simple 
condition type " + simpleCondition.type());
diff --git 
a/modules/metastorage/src/test/java/org/apache/ignite/internal/metastorage/server/BasicOperationsKeyValueStorageTest.java
 
b/modules/metastorage/src/test/java/org/apache/ignite/internal/metastorage/server/BasicOperationsKeyValueStorageTest.java
index 61d8f4c2c3..6372ebb13a 100644
--- 
a/modules/metastorage/src/test/java/org/apache/ignite/internal/metastorage/server/BasicOperationsKeyValueStorageTest.java
+++ 
b/modules/metastorage/src/test/java/org/apache/ignite/internal/metastorage/server/BasicOperationsKeyValueStorageTest.java
@@ -1346,7 +1346,7 @@ public abstract class BasicOperationsKeyValueStorageTest 
extends AbstractKeyValu
         assertEquals(2, storage.updateCounter());
 
         boolean branch = invokeOnMs(
-                new TombstoneCondition(key1),
+                new TombstoneCondition(TombstoneCondition.Type.TOMBSTONE, 
key1),
                 List.of(put(new ByteArray(key2), val2)),
                 List.of(put(new ByteArray(key3), val3))
         );
@@ -1398,7 +1398,7 @@ public abstract class BasicOperationsKeyValueStorageTest 
extends AbstractKeyValu
         assertEquals(1, storage.updateCounter());
 
         boolean branch = invokeOnMs(
-                new TombstoneCondition(key1),
+                new TombstoneCondition(TombstoneCondition.Type.TOMBSTONE, 
key1),
                 List.of(put(new ByteArray(key2), val2)),
                 List.of(put(new ByteArray(key3), val3))
         );
@@ -1430,6 +1430,111 @@ public abstract class 
BasicOperationsKeyValueStorageTest extends AbstractKeyValu
         assertTrue(e2.empty());
     }
 
+    @Test
+    public void invokeWithNotTombstoneCondition_successBranch() {
+        byte[] key1 = key(1);
+        byte[] val11 = keyValue(1, 11);
+
+        byte[] key2 = key(2);
+        byte[] val2 = keyValue(2, 2);
+
+        byte[] key3 = key(3);
+        byte[] val3 = keyValue(3, 3);
+
+        assertEquals(0, storage.revision());
+        assertEquals(0, storage.updateCounter());
+
+        putToMs(key1, val11);
+
+        assertEquals(1, storage.revision());
+        assertEquals(1, storage.updateCounter());
+
+        boolean branch = invokeOnMs(
+                new TombstoneCondition(TombstoneCondition.Type.NOT_TOMBSTONE, 
key1),
+                List.of(put(new ByteArray(key2), val2)),
+                List.of(put(new ByteArray(key3), val3))
+        );
+
+        // "Success" branch is applied.
+        assertTrue(branch);
+        assertEquals(2, storage.revision());
+        assertEquals(2, storage.updateCounter());
+
+        Entry e1 = storage.get(key1);
+
+        assertFalse(e1.empty());
+        assertFalse(e1.tombstone());
+        assertEquals(1, e1.revision());
+        assertEquals(1, e1.updateCounter());
+        assertArrayEquals(val11, e1.value());
+
+        Entry e2 = storage.get(key2);
+
+        assertFalse(e2.empty());
+        assertFalse(e2.tombstone());
+        assertEquals(2, e2.revision());
+        assertEquals(2, e2.updateCounter());
+        assertArrayEquals(val2, e2.value());
+
+        // "Failure" branch isn't applied.
+        Entry e3 = storage.get(key3);
+
+        assertTrue(e3.empty());
+    }
+
+    @Test
+    public void invokeWithNotTombstoneCondition_failureBranch() {
+        byte[] key1 = key(1);
+        byte[] val11 = keyValue(1, 11);
+
+        byte[] key2 = key(2);
+        byte[] val2 = keyValue(2, 2);
+
+        byte[] key3 = key(3);
+        byte[] val3 = keyValue(3, 3);
+
+        assertEquals(0, storage.revision());
+        assertEquals(0, storage.updateCounter());
+
+        putToMs(key1, val11);
+        removeFromMs(key1); // Should be tombstone after remove.
+
+        assertEquals(2, storage.revision());
+        assertEquals(2, storage.updateCounter());
+
+        boolean branch = invokeOnMs(
+                new TombstoneCondition(TombstoneCondition.Type.NOT_TOMBSTONE, 
key1),
+                List.of(put(new ByteArray(key2), val2)),
+                List.of(put(new ByteArray(key3), val3))
+        );
+
+        // "Failure" branch is applied.
+        assertFalse(branch);
+        assertEquals(3, storage.revision());
+        assertEquals(3, storage.updateCounter());
+
+        Entry e1 = storage.get(key1);
+
+        assertFalse(e1.empty());
+        assertTrue(e1.tombstone());
+        assertEquals(2, e1.revision());
+        assertEquals(2, e1.updateCounter());
+        assertNull(e1.value());
+
+        Entry e3 = storage.get(key3);
+
+        assertFalse(e3.empty());
+        assertFalse(e3.tombstone());
+        assertEquals(3, e3.revision());
+        assertEquals(3, e3.updateCounter());
+        assertArrayEquals(val3, e3.value());
+
+        // "Success" branch isn't applied.
+        Entry e2 = storage.get(key2);
+
+        assertTrue(e2.empty());
+    }
+
     @Test
     public void invokeWithValueCondition_successBranch() {
         byte[] key1 = key(1);
diff --git 
a/modules/metastorage/src/test/java/org/apache/ignite/internal/metastorage/server/TombstoneConditionTest.java
 
b/modules/metastorage/src/test/java/org/apache/ignite/internal/metastorage/server/TombstoneConditionTest.java
index 35f82b103c..f404c79664 100644
--- 
a/modules/metastorage/src/test/java/org/apache/ignite/internal/metastorage/server/TombstoneConditionTest.java
+++ 
b/modules/metastorage/src/test/java/org/apache/ignite/internal/metastorage/server/TombstoneConditionTest.java
@@ -46,14 +46,26 @@ public class TombstoneConditionTest {
     private static final Entry TOMBSTONE = EntryImpl.tombstone(KEY, 1, 1);
 
     /**
-     * Tests {@link TombstoneCondition} condition for regular, empty and 
tombstone entries.
+     * Tests {@link TombstoneCondition.Type#TOMBSTONE} condition for regular, 
empty and tombstone entries.
      */
     @Test
     public void tombstone() {
-        Condition cond = new TombstoneCondition(KEY);
+        Condition cond = new 
TombstoneCondition(TombstoneCondition.Type.TOMBSTONE, KEY);
 
         assertFalse(cond.test(ENTRY));
         assertFalse(cond.test(EMPTY));
         assertTrue(cond.test(TOMBSTONE));
     }
+
+    /**
+     * Tests {@link TombstoneCondition.Type#NOT_TOMBSTONE} condition for 
regular, empty and tombstone entries.
+     */
+    @Test
+    public void notTombstone() {
+        Condition cond = new 
TombstoneCondition(TombstoneCondition.Type.NOT_TOMBSTONE, KEY);
+
+        assertTrue(cond.test(ENTRY));
+        assertTrue(cond.test(EMPTY));
+        assertFalse(cond.test(TOMBSTONE));
+    }
 }
diff --git 
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/distribution/zones/ItIgniteDistributionZoneManagerNodeRestartTest.java
 
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/distribution/zones/ItIgniteDistributionZoneManagerNodeRestartTest.java
index aadd4367f3..145667b31a 100644
--- 
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/distribution/zones/ItIgniteDistributionZoneManagerNodeRestartTest.java
+++ 
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/distribution/zones/ItIgniteDistributionZoneManagerNodeRestartTest.java
@@ -347,6 +347,7 @@ public class ItIgniteDistributionZoneManagerNodeRestartTest 
extends BaseIgniteRe
     }
 
     @Test
+    @Disabled("https://issues.apache.org/jira/browse/IGNITE-20559";)
     public void testGlobalStateRevisionUpdatedCorrectly() throws Exception {
         PartialNode node = startPartialNode(0);
 

Reply via email to