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);