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 b520ad3bc3 IGNITE-20561 Change condition for
DistributionZonesUtil#triggerKeyConditionForZonesChanges to solve inconsistency
issues (#2743)
b520ad3bc3 is described below
commit b520ad3bc337b8ca051ae88764d6ae084f6dcc09
Author: Mirza Aliev <[email protected]>
AuthorDate: Wed Oct 25 14:36:06 2023 +0400
IGNITE-20561 Change condition for
DistributionZonesUtil#triggerKeyConditionForZonesChanges to solve inconsistency
issues (#2743)
---
.../distributionzones/DistributionZoneManager.java | 25 ++++----
.../distributionzones/DistributionZonesUtil.java | 61 ++++++++++--------
...ibutionZoneManagerConfigurationChangesTest.java | 22 -------
...butionZoneManagerLogicalTopologyEventsTest.java | 10 ++-
.../DistributionZonesTestUtil.java | 23 -------
...niteDistributionZoneManagerNodeRestartTest.java | 74 ++++++++++++++++++++++
6 files changed, 123 insertions(+), 92 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 0e8bd9c4f2..982c7d7f09 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
@@ -29,12 +29,13 @@ import static
org.apache.ignite.internal.catalog.commands.CatalogUtils.INFINITE_
import static
org.apache.ignite.internal.catalog.events.CatalogEvent.ZONE_ALTER;
import static
org.apache.ignite.internal.catalog.events.CatalogEvent.ZONE_CREATE;
import static org.apache.ignite.internal.catalog.events.CatalogEvent.ZONE_DROP;
+import static
org.apache.ignite.internal.distributionzones.DistributionZonesUtil.conditionForZoneCreation;
+import static
org.apache.ignite.internal.distributionzones.DistributionZonesUtil.conditionForZoneRemoval;
import static
org.apache.ignite.internal.distributionzones.DistributionZonesUtil.createZoneManagerExecutor;
-import static
org.apache.ignite.internal.distributionzones.DistributionZonesUtil.deleteDataNodesAndUpdateTriggerKeys;
+import static
org.apache.ignite.internal.distributionzones.DistributionZonesUtil.deleteDataNodesAndTriggerKeys;
import static
org.apache.ignite.internal.distributionzones.DistributionZonesUtil.extractChangeTriggerRevision;
import static
org.apache.ignite.internal.distributionzones.DistributionZonesUtil.extractDataNodes;
import static
org.apache.ignite.internal.distributionzones.DistributionZonesUtil.toDataNodesMap;
-import static
org.apache.ignite.internal.distributionzones.DistributionZonesUtil.triggerKeyConditionForZonesChanges;
import static
org.apache.ignite.internal.distributionzones.DistributionZonesUtil.triggerScaleUpScaleDownKeysCondition;
import static
org.apache.ignite.internal.distributionzones.DistributionZonesUtil.updateDataNodesAndScaleDownTriggerKey;
import static
org.apache.ignite.internal.distributionzones.DistributionZonesUtil.updateDataNodesAndScaleUpTriggerKey;
@@ -106,6 +107,7 @@ import org.apache.ignite.internal.metastorage.WatchListener;
import org.apache.ignite.internal.metastorage.dsl.CompoundCondition;
import org.apache.ignite.internal.metastorage.dsl.Condition;
import org.apache.ignite.internal.metastorage.dsl.Iif;
+import org.apache.ignite.internal.metastorage.dsl.SimpleCondition;
import org.apache.ignite.internal.metastorage.dsl.StatementResult;
import org.apache.ignite.internal.metastorage.dsl.Update;
import org.apache.ignite.internal.thread.NamedThreadFactory;
@@ -509,8 +511,8 @@ public class DistributionZoneManager implements
IgniteComponent {
/**
* Method initialise data nodes value for the specified zone, also sets
{@code revision} to the
- * {@link DistributionZonesUtil#zoneScaleUpChangeTriggerKey(int)}, {@link
DistributionZonesUtil#zoneScaleDownChangeTriggerKey(int)} and
- * {@link DistributionZonesUtil#zonesChangeTriggerKey(int)} if it passes
the condition. It is called on the first creation of a zone.
+ * {@link DistributionZonesUtil#zoneScaleUpChangeTriggerKey(int)} and
{@link DistributionZonesUtil#zoneScaleDownChangeTriggerKey(int)}
+ * if it passes the condition. It is called on the first creation of a
zone.
*
* @param zoneId Unique id of a zone
* @param revision Revision of an event that has triggered this method.
@@ -527,9 +529,8 @@ public class DistributionZoneManager implements
IgniteComponent {
}
try {
- // Update data nodes for a zone only if the revision of the event
is newer than value in that trigger key,
- // so we do not react on a stale events
- CompoundCondition triggerKeyCondition =
triggerKeyConditionForZonesChanges(revision, zoneId);
+ // Update data nodes for a zone only if the corresponding data
nodes keys weren't initialised in ms yet.
+ CompoundCondition triggerKeyCondition =
conditionForZoneCreation(zoneId);
Update dataNodesAndTriggerKeyUpd =
updateDataNodesAndTriggerKeys(zoneId, revision,
toBytes(toDataNodesMap(dataNodes)));
@@ -578,9 +579,9 @@ public class DistributionZoneManager implements
IgniteComponent {
}
try {
- CompoundCondition triggerKeyCondition =
triggerKeyConditionForZonesChanges(revision, zoneId);
+ SimpleCondition triggerKeyCondition =
conditionForZoneRemoval(zoneId);
- Update removeKeysUpd = deleteDataNodesAndUpdateTriggerKeys(zoneId,
revision);
+ Update removeKeysUpd = deleteDataNodesAndTriggerKeys(zoneId,
revision);
Iif iif = iif(triggerKeyCondition, removeKeysUpd,
ops().yield(false));
@@ -887,8 +888,7 @@ public class DistributionZoneManager implements
IgniteComponent {
/**
* Method updates data nodes value for the specified zone after scale up
timer timeout, sets {@code revision} to the
- * {@link DistributionZonesUtil#zoneScaleUpChangeTriggerKey(int)} and
- * {@link DistributionZonesUtil#zonesChangeTriggerKey(int)} if it passes
the condition.
+ * {@link DistributionZonesUtil#zoneScaleUpChangeTriggerKey(int)} if it
passes the condition.
*
* @param zoneId Unique id of a zone
* @param revision Revision of an event that has triggered this method.
@@ -998,8 +998,7 @@ public class DistributionZoneManager implements
IgniteComponent {
/**
* Method updates data nodes value for the specified zone after scale down
timer timeout, sets {@code revision} to the
- * {@link DistributionZonesUtil#zoneScaleDownChangeTriggerKey(int)} and
- * {@link DistributionZonesUtil#zonesChangeTriggerKey(int)} if it passes
the condition.
+ * {@link DistributionZonesUtil#zoneScaleDownChangeTriggerKey(int)} if it
passes the condition.
*
* @param zoneId Unique id of a zone
* @param revision Revision of an event that has triggered this method.
diff --git
a/modules/distribution-zones/src/main/java/org/apache/ignite/internal/distributionzones/DistributionZonesUtil.java
b/modules/distribution-zones/src/main/java/org/apache/ignite/internal/distributionzones/DistributionZonesUtil.java
index 1ea89d2085..5d050674cf 100644
---
a/modules/distribution-zones/src/main/java/org/apache/ignite/internal/distributionzones/DistributionZonesUtil.java
+++
b/modules/distribution-zones/src/main/java/org/apache/ignite/internal/distributionzones/DistributionZonesUtil.java
@@ -22,8 +22,9 @@ import static java.util.stream.Collectors.toMap;
import static java.util.stream.Collectors.toSet;
import static
org.apache.ignite.internal.catalog.commands.CatalogUtils.DEFAULT_FILTER;
import static org.apache.ignite.internal.metastorage.dsl.Conditions.and;
+import static org.apache.ignite.internal.metastorage.dsl.Conditions.exists;
import static org.apache.ignite.internal.metastorage.dsl.Conditions.notExists;
-import static org.apache.ignite.internal.metastorage.dsl.Conditions.or;
+import static
org.apache.ignite.internal.metastorage.dsl.Conditions.notTombstone;
import static org.apache.ignite.internal.metastorage.dsl.Conditions.value;
import static org.apache.ignite.internal.metastorage.dsl.Operations.ops;
import static org.apache.ignite.internal.metastorage.dsl.Operations.put;
@@ -98,9 +99,6 @@ public class DistributionZonesUtil {
/** Key prefix for zones' logical topology version. */
private static final String DISTRIBUTION_ZONES_LOGICAL_TOPOLOGY_VERSION =
DISTRIBUTION_ZONES_LOGICAL_TOPOLOGY_PREFIX + "version";
- /** Key prefix, needed for processing the event about zone's update was
triggered only once. */
- private static final String DISTRIBUTION_ZONES_CHANGE_TRIGGER_KEY_PREFIX =
"distributionZones.change.trigger.";
-
/** Key prefix that represents {@link ZoneState#topologyAugmentationMap()}
in the Vault.*/
private static final String
DISTRIBUTION_ZONES_TOPOLOGY_AUGMENTATION_VAULT_PREFIX =
"vault.distributionZones.topologyAugmentation.";
@@ -187,14 +185,6 @@ public class DistributionZonesUtil {
return
Integer.parseInt(strKey.substring(DISTRIBUTION_ZONE_DATA_NODES_VALUE_PREFIX.length()));
}
- /**
- * The key needed for processing an event about zone's creation and
deletion.
- * With this key we can be sure that event was triggered only once.
- */
- public static ByteArray zonesChangeTriggerKey(int zoneId) {
- return new ByteArray(DISTRIBUTION_ZONES_CHANGE_TRIGGER_KEY_PREFIX +
zoneId);
- }
-
/**
* The key needed for processing an event about zone's data node
propagation on scale up.
* With this key we can be sure that event was triggered only once.
@@ -271,19 +261,29 @@ public class DistributionZonesUtil {
}
/**
- * Condition for updating {@link
DistributionZonesUtil#zoneScaleUpChangeTriggerKey(int)} key.
- * Update only if the revision of the event is newer than value in that
trigger key.
+ * Condition for creating all data nodes' related keys in Meta Storage.
Condition passes only when
+ * {@link DistributionZonesUtil#zoneDataNodesKey(int)} not exists and not
a tombstone in the Meta Storage.
*
- * @param revision Event revision.
+ * @param zoneId Distribution zone id
* @return Update condition.
*/
- static CompoundCondition triggerKeyConditionForZonesChanges(long revision,
int zoneId) {
- return or(
- notExists(zonesChangeTriggerKey(zoneId)),
-
value(zonesChangeTriggerKey(zoneId)).lt(ByteUtils.longToBytes(revision))
+ static CompoundCondition conditionForZoneCreation(int zoneId) {
+ return and(
+ notExists(zoneDataNodesKey(zoneId)),
+ notTombstone(zoneDataNodesKey(zoneId))
);
}
+ /**
+ * Condition for removing all data nodes' related keys in Meta Storage.
+ *
+ * @param zoneId Distribution zone id
+ * @return Update condition.
+ */
+ static SimpleCondition conditionForZoneRemoval(int zoneId) {
+ return exists(zoneDataNodesKey(zoneId));
+ }
+
/**
* Condition for updating {@link
DistributionZonesUtil#zoneScaleUpChangeTriggerKey(int)} key.
* Update only if the revision of the event is newer than value in that
trigger key.
@@ -328,6 +328,14 @@ public class DistributionZonesUtil {
).yield(true);
}
+ /**
+ * Updates data nodes value for a zone and set {@code revision} to {@link
DistributionZonesUtil#zoneScaleDownChangeTriggerKey(int)}.
+ *
+ * @param zoneId Distribution zone id
+ * @param revision Revision of the event.
+ * @param nodes Data nodes.
+ * @return Update command for the meta storage.
+ */
static Update updateDataNodesAndScaleDownTriggerKey(int zoneId, long
revision, byte[] nodes) {
return ops(
put(zoneDataNodesKey(zoneId), nodes),
@@ -337,8 +345,8 @@ public class DistributionZonesUtil {
/**
- * Updates data nodes value for a zone and set {@code revision} to {@link
DistributionZonesUtil#zoneScaleUpChangeTriggerKey(int)},
- * {@link DistributionZonesUtil#zoneScaleDownChangeTriggerKey(int)} and
{@link DistributionZonesUtil#zonesChangeTriggerKey(int)}.
+ * Updates data nodes value for a zone and set {@code revision} to {@link
DistributionZonesUtil#zoneScaleUpChangeTriggerKey(int)} and
+ * {@link DistributionZonesUtil#zoneScaleDownChangeTriggerKey(int)}.
*
* @param zoneId Distribution zone id
* @param revision Revision of the event.
@@ -349,26 +357,23 @@ public class DistributionZonesUtil {
return ops(
put(zoneDataNodesKey(zoneId), nodes),
put(zoneScaleUpChangeTriggerKey(zoneId),
ByteUtils.longToBytes(revision)),
- put(zoneScaleDownChangeTriggerKey(zoneId),
ByteUtils.longToBytes(revision)),
- put(zonesChangeTriggerKey(zoneId),
ByteUtils.longToBytes(revision))
+ put(zoneScaleDownChangeTriggerKey(zoneId),
ByteUtils.longToBytes(revision))
).yield(true);
}
/**
* Deletes data nodes, {@link
DistributionZonesUtil#zoneScaleUpChangeTriggerKey(int)},
- * {@link DistributionZonesUtil#zoneScaleDownChangeTriggerKey(int)} values
for a zone. Also sets {@code revision} to
- * {@link DistributionZonesUtil#zonesChangeTriggerKey(int)}.
+ * {@link DistributionZonesUtil#zoneScaleDownChangeTriggerKey(int)} values
for a zone.
*
* @param zoneId Distribution zone id
* @param revision Revision of the event.
* @return Update command for the meta storage.
*/
- static Update deleteDataNodesAndUpdateTriggerKeys(int zoneId, long
revision) {
+ static Update deleteDataNodesAndTriggerKeys(int zoneId, long revision) {
return ops(
remove(zoneDataNodesKey(zoneId)),
remove(zoneScaleUpChangeTriggerKey(zoneId)),
- remove(zoneScaleDownChangeTriggerKey(zoneId)),
- put(zonesChangeTriggerKey(zoneId),
ByteUtils.longToBytes(revision))
+ remove(zoneScaleDownChangeTriggerKey(zoneId))
).yield(true);
}
diff --git
a/modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/DistributionZoneManagerConfigurationChangesTest.java
b/modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/DistributionZoneManagerConfigurationChangesTest.java
index ac1b42e369..ca5509592e 100644
---
a/modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/DistributionZoneManagerConfigurationChangesTest.java
+++
b/modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/DistributionZoneManagerConfigurationChangesTest.java
@@ -22,9 +22,7 @@ import static
java.util.concurrent.CompletableFuture.completedFuture;
import static java.util.stream.Collectors.toSet;
import static
org.apache.ignite.internal.distributionzones.DistributionZonesTestUtil.assertDataNodesForZoneWithAttributes;
import static
org.apache.ignite.internal.distributionzones.DistributionZonesTestUtil.assertZoneScaleUpChangeTriggerKey;
-import static
org.apache.ignite.internal.distributionzones.DistributionZonesTestUtil.assertZonesChangeTriggerKey;
import static
org.apache.ignite.internal.distributionzones.DistributionZonesUtil.zoneDataNodesKey;
-import static
org.apache.ignite.internal.distributionzones.DistributionZonesUtil.zonesChangeTriggerKey;
import static
org.apache.ignite.internal.distributionzones.DistributionZonesUtil.zonesGlobalStateRevision;
import static
org.apache.ignite.internal.distributionzones.DistributionZonesUtil.zonesLogicalTopologyVault;
import static
org.apache.ignite.internal.distributionzones.DistributionZonesUtil.zonesLogicalTopologyVersionKey;
@@ -53,7 +51,6 @@ import
org.apache.ignite.internal.cluster.management.topology.api.LogicalTopolog
import
org.apache.ignite.internal.cluster.management.topology.api.LogicalTopologySnapshot;
import org.apache.ignite.internal.hlc.HybridClock;
import org.apache.ignite.internal.hlc.HybridClockImpl;
-import org.apache.ignite.internal.hlc.HybridTimestamp;
import
org.apache.ignite.internal.metastorage.impl.StandaloneMetaStorageManager;
import
org.apache.ignite.internal.metastorage.server.SimpleInMemoryKeyValueStorage;
import org.apache.ignite.internal.testframework.IgniteAbstractTest;
@@ -160,8 +157,6 @@ public class
DistributionZoneManagerConfigurationChangesTest extends IgniteAbstr
assertDataNodesForZoneWithAttributes(zoneId,
nodes.stream().map(NodeWithAttributes::node).collect(toSet()), keyValueStorage);
assertZoneScaleUpChangeTriggerKey(2L, zoneId, keyValueStorage);
-
- assertZonesChangeTriggerKey(2, zoneId, keyValueStorage);
}
@Test
@@ -188,23 +183,6 @@ public class
DistributionZoneManagerConfigurationChangesTest extends IgniteAbstr
assertZoneScaleUpChangeTriggerKey(2L, zoneId, keyValueStorage);
assertZoneScaleUpChangeTriggerKey(4L, zoneId2, keyValueStorage);
- assertZonesChangeTriggerKey(2L, zoneId, keyValueStorage);
- assertZonesChangeTriggerKey(4L, zoneId2, keyValueStorage);
- }
-
- @Test
- void testZoneDeleteDoNotRemoveMetaStorageKey() throws Exception {
- createZone(ZONE_NAME);
-
- int zoneId = getZoneId(ZONE_NAME);
-
- assertDataNodesForZoneWithAttributes(zoneId,
nodes.stream().map(NodeWithAttributes::node).collect(toSet()), keyValueStorage);
-
- keyValueStorage.put(zonesChangeTriggerKey(zoneId).bytes(),
longToBytes(100), HybridTimestamp.MIN_VALUE);
-
- dropZone(ZONE_NAME);
-
- assertDataNodesForZoneWithAttributes(zoneId,
nodes.stream().map(NodeWithAttributes::node).collect(toSet()), keyValueStorage);
}
private void createZone(String zoneName) {
diff --git
a/modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/DistributionZoneManagerLogicalTopologyEventsTest.java
b/modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/DistributionZoneManagerLogicalTopologyEventsTest.java
index 9f58aca736..122acad907 100644
---
a/modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/DistributionZoneManagerLogicalTopologyEventsTest.java
+++
b/modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/DistributionZoneManagerLogicalTopologyEventsTest.java
@@ -23,9 +23,9 @@ import static
org.apache.ignite.internal.distributionzones.DistributionZonesTest
import static
org.apache.ignite.internal.distributionzones.DistributionZonesTestUtil.assertLogicalTopology;
import static
org.apache.ignite.internal.distributionzones.DistributionZonesTestUtil.assertLogicalTopologyVersion;
import static
org.apache.ignite.internal.distributionzones.DistributionZonesTestUtil.mockVaultZonesLogicalTopologyKey;
-import static
org.apache.ignite.internal.distributionzones.DistributionZonesUtil.zonesChangeTriggerKey;
+import static
org.apache.ignite.internal.distributionzones.DistributionZonesUtil.zoneDataNodesKey;
import static
org.apache.ignite.internal.distributionzones.DistributionZonesUtil.zonesLogicalTopologyVersionKey;
-import static org.apache.ignite.internal.util.ByteUtils.longToBytes;
+import static org.apache.ignite.internal.util.ByteUtils.toBytes;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.Collections;
@@ -208,11 +208,9 @@ public class
DistributionZoneManagerLogicalTopologyEventsTest extends BaseDistri
//TODO: IGNITE-19955 Check if this test is needed.
@Test
void testStaleVaultRevisionOnZoneManagerStart() throws Exception {
- long revision = 100;
-
int defaultZoneId = getZoneId(DEFAULT_ZONE_NAME);
- keyValueStorage.put(zonesChangeTriggerKey(defaultZoneId).bytes(),
longToBytes(revision), HybridTimestamp.MIN_VALUE);
+ keyValueStorage.put(zoneDataNodesKey(defaultZoneId).bytes(),
toBytes(Collections.emptyMap()), HybridTimestamp.MIN_VALUE);
Set<LogicalNode> nodes = Set.of(
new LogicalNode(new ClusterNodeImpl("node1", "node1",
NetworkAddress.from("127.0.0.1:127")), Collections.emptyMap()),
@@ -223,6 +221,6 @@ public class
DistributionZoneManagerLogicalTopologyEventsTest extends BaseDistri
startDistributionZoneManager();
- assertDataNodesForZone(defaultZoneId, null, keyValueStorage);
+ assertDataNodesForZone(defaultZoneId, Collections.emptySet(),
keyValueStorage);
}
}
diff --git
a/modules/distribution-zones/src/testFixtures/java/org/apache/ignite/internal/distributionzones/DistributionZonesTestUtil.java
b/modules/distribution-zones/src/testFixtures/java/org/apache/ignite/internal/distributionzones/DistributionZonesTestUtil.java
index e766b7d6fa..e70a2da287 100644
---
a/modules/distribution-zones/src/testFixtures/java/org/apache/ignite/internal/distributionzones/DistributionZonesTestUtil.java
+++
b/modules/distribution-zones/src/testFixtures/java/org/apache/ignite/internal/distributionzones/DistributionZonesTestUtil.java
@@ -23,7 +23,6 @@ import static
org.apache.ignite.internal.distributionzones.DistributionZonesUtil
import static
org.apache.ignite.internal.distributionzones.DistributionZonesUtil.zoneDataNodesKey;
import static
org.apache.ignite.internal.distributionzones.DistributionZonesUtil.zoneScaleDownChangeTriggerKey;
import static
org.apache.ignite.internal.distributionzones.DistributionZonesUtil.zoneScaleUpChangeTriggerKey;
-import static
org.apache.ignite.internal.distributionzones.DistributionZonesUtil.zonesChangeTriggerKey;
import static
org.apache.ignite.internal.distributionzones.DistributionZonesUtil.zonesGlobalStateRevision;
import static
org.apache.ignite.internal.distributionzones.DistributionZonesUtil.zonesLogicalTopologyKey;
import static
org.apache.ignite.internal.distributionzones.DistributionZonesUtil.zonesLogicalTopologyVault;
@@ -277,28 +276,6 @@ public class DistributionZonesTestUtil {
);
}
- /**
- * Asserts {@link DistributionZonesUtil#zonesChangeTriggerKey(int)}
revision.
- *
- * @param revision Revision.
- * @param zoneId Zone id.
- * @param keyValueStorage Key-value storage.
- * @throws InterruptedException If thread was interrupted.
- */
- public static void assertZonesChangeTriggerKey(
- long revision,
- int zoneId,
- KeyValueStorage keyValueStorage
- ) throws InterruptedException {
- assertValueInStorage(
- keyValueStorage,
- zonesChangeTriggerKey(zoneId).bytes(),
- ByteUtils::bytesToLong,
- revision,
- 1000
- );
- }
-
/**
* Asserts {@link DistributionZonesUtil#zonesLogicalTopologyKey()} value.
*
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 c63edadf05..8534e955d7 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
@@ -25,19 +25,25 @@ import static
org.apache.ignite.internal.catalog.commands.CatalogUtils.IMMEDIATE
import static
org.apache.ignite.internal.catalog.commands.CatalogUtils.INFINITE_TIMER_VALUE;
import static
org.apache.ignite.internal.distributionzones.DistributionZonesTestUtil.assertDataNodesFromManager;
import static
org.apache.ignite.internal.distributionzones.DistributionZonesTestUtil.assertValueInStorage;
+import static
org.apache.ignite.internal.distributionzones.DistributionZonesUtil.dataNodes;
+import static
org.apache.ignite.internal.distributionzones.DistributionZonesUtil.toDataNodesMap;
import static
org.apache.ignite.internal.distributionzones.DistributionZonesUtil.zoneDataNodesKey;
import static
org.apache.ignite.internal.distributionzones.DistributionZonesUtil.zoneScaleUpChangeTriggerKey;
import static
org.apache.ignite.internal.distributionzones.DistributionZonesUtil.zonesGlobalStateRevision;
import static
org.apache.ignite.internal.testframework.IgniteTestUtils.testNodeName;
import static
org.apache.ignite.internal.testframework.IgniteTestUtils.waitForCondition;
+import static
org.apache.ignite.internal.testframework.matchers.CompletableFutureMatcher.willBe;
import static org.apache.ignite.internal.util.ByteUtils.bytesToLong;
import static org.apache.ignite.internal.util.ByteUtils.fromBytes;
+import static org.apache.ignite.internal.util.ByteUtils.toBytes;
import static org.apache.ignite.internal.util.IgniteUtils.startsWith;
import static
org.apache.ignite.utils.ClusterServiceTestUtils.defaultSerializationRegistry;
+import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.argThat;
+import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
@@ -47,8 +53,10 @@ import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;
@@ -80,7 +88,9 @@ import
org.apache.ignite.internal.distributionzones.DistributionZonesUtil;
import org.apache.ignite.internal.distributionzones.Node;
import org.apache.ignite.internal.distributionzones.NodeWithAttributes;
import org.apache.ignite.internal.hlc.HybridClockImpl;
+import org.apache.ignite.internal.lang.ByteArray;
import org.apache.ignite.internal.manager.IgniteComponent;
+import org.apache.ignite.internal.metastorage.Entry;
import org.apache.ignite.internal.metastorage.MetaStorageManager;
import
org.apache.ignite.internal.metastorage.impl.StandaloneMetaStorageManager;
import org.apache.ignite.internal.metastorage.server.If;
@@ -346,6 +356,70 @@ public class
ItIgniteDistributionZoneManagerNodeRestartTest extends BaseIgniteRe
assertEquals(logicalTopology,
distributionZoneManager.logicalTopology());
}
+ @Test
+ public void testCreationZoneWhenDataNodesAreDeletedIsNotSuccessful()
throws Exception {
+ PartialNode node = startPartialNode(0);
+
+ node.logicalTopology().putNode(A);
+ node.logicalTopology().putNode(B);
+
+ node.logicalTopology().putNode(C);
+
+ Set<NodeWithAttributes> logicalTopology = Stream.of(A, B, C)
+ .map(n -> new NodeWithAttributes(n.name(), n.id(),
n.attributes()))
+ .collect(toSet());
+
+ DistributionZoneManager distributionZoneManager =
getDistributionZoneManager(node);
+ DistributionZoneManager finalDistributionZoneManager =
distributionZoneManager;
+
+ assertTrue(waitForCondition(() ->
logicalTopology.equals(finalDistributionZoneManager.logicalTopology()),
TIMEOUT_MILLIS));
+
+ int zoneId = getZoneId(node, DEFAULT_ZONE_NAME);
+
+ assertValueInStorage(
+ metastore,
+ zoneDataNodesKey(zoneId),
+ (v) ->
dataNodes(fromBytes(v)).stream().map(Node::nodeName).collect(toSet()),
+ Set.of(A.name(), B.name(), C.name()),
+ TIMEOUT_MILLIS
+ );
+
+ metastore = findComponent(node.startedComponents(),
MetaStorageManager.class);
+
+ byte[][] dataNodeKey = new byte[1][1];
+
+ // In this mock we catch invocation of
DistributionZoneManager.initDataNodesAndTriggerKeysInMetaStorage, where
condition is based
+ // on presence of data node key in ms. After that we make this data
node as a tombstone, so when logic of creation of a zone is
+ // run, there won't be any initialisation of data nodes keys. We try
to imitate concurrent removal of a zone.
+ doAnswer(invocation -> {
+ ByteArray dataNodeKeyForZone = new ByteArray(dataNodeKey[0]);
+
+ // Here we remove data nodes value for newly created zone, so it
is tombstone
+ metastore.put(dataNodeKeyForZone,
toBytes(toDataNodesMap(emptySet()))).get();
+
+ metastore.remove(dataNodeKeyForZone).get();
+
+ return invocation.callRealMethod();
+ }).when(metastore).invoke(argThat(iif -> {
+ If iif1 = MetaStorageWriteHandler.toIf(iif);
+
+ byte[][] keysFromIf = iif1.cond().keys();
+
+ Optional<byte[]> dataNodeKeyOptional = Arrays.stream(keysFromIf)
+ .filter(op -> startsWith(op, zoneDataNodesKey().bytes()))
+ .findFirst();
+
+ dataNodeKeyOptional.ifPresent(bytes -> dataNodeKey[0] = bytes);
+
+ return dataNodeKeyOptional.isPresent();
+ }));
+
+ createZone(node, "zone1", INFINITE_TIMER_VALUE, INFINITE_TIMER_VALUE);
+
+ // Assert that after creation of a zone, data nodes are still
tombstone, but not the logical topology, as for default zone.
+ assertThat(metastore.get(new
ByteArray(dataNodeKey[0])).thenApply(Entry::tombstone), willBe(true));
+ }
+
@Test
@Disabled("https://issues.apache.org/jira/browse/IGNITE-20559")
public void testGlobalStateRevisionUpdatedCorrectly() throws Exception {