You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by sd...@apache.org on 2022/10/05 16:37:32 UTC
[ignite] branch master updated: IGNITE-17436 Fix CacheGroupReencryptionTest#testReencryptionOnUnstableTopology fails if checkpoint is skipped on node stop (#10289)
This is an automated email from the ASF dual-hosted git repository.
sdanilov pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git
The following commit(s) were added to refs/heads/master by this push:
new 72aa5848bb8 IGNITE-17436 Fix CacheGroupReencryptionTest#testReencryptionOnUnstableTopology fails if checkpoint is skipped on node stop (#10289)
72aa5848bb8 is described below
commit 72aa5848bb8462bf3118ad548e584461688af818
Author: Semyon Danilov <sa...@yandex.ru>
AuthorDate: Wed Oct 5 19:37:23 2022 +0300
IGNITE-17436 Fix CacheGroupReencryptionTest#testReencryptionOnUnstableTopology fails if checkpoint is skipped on node stop (#10289)
---
.../encryption/CacheGroupReencryptionTest.java | 89 +++++++++++++++++++++-
1 file changed, 88 insertions(+), 1 deletion(-)
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/encryption/CacheGroupReencryptionTest.java b/modules/core/src/test/java/org/apache/ignite/internal/encryption/CacheGroupReencryptionTest.java
index e97ed90ef35..f809a1c317b 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/encryption/CacheGroupReencryptionTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/encryption/CacheGroupReencryptionTest.java
@@ -45,6 +45,8 @@ import org.apache.ignite.internal.IgniteEx;
import org.apache.ignite.internal.IgniteFutureCancelledCheckedException;
import org.apache.ignite.internal.IgniteInternalFuture;
import org.apache.ignite.internal.IgniteInterruptedCheckedException;
+import org.apache.ignite.internal.managers.encryption.ReencryptStateUtils;
+import org.apache.ignite.internal.processors.cache.CacheGroupContext;
import org.apache.ignite.internal.processors.cache.CacheGroupMetricsImpl;
import org.apache.ignite.internal.processors.cache.persistence.file.FileIO;
import org.apache.ignite.internal.processors.cache.persistence.file.FileIODecorator;
@@ -57,11 +59,15 @@ import org.apache.ignite.internal.util.typedef.internal.CU;
import org.apache.ignite.spi.metric.BooleanMetric;
import org.apache.ignite.spi.metric.LongMetric;
import org.apache.ignite.testframework.GridTestUtils;
+import org.apache.ignite.testframework.junits.WithSystemProperty;
+import org.jetbrains.annotations.Nullable;
import org.junit.Test;
import static org.apache.ignite.configuration.EncryptionConfiguration.DFLT_REENCRYPTION_RATE_MBPS;
import static org.apache.ignite.configuration.WALMode.LOG_ONLY;
import static org.apache.ignite.internal.managers.encryption.GridEncryptionManager.INITIAL_KEY_ID;
+import static org.apache.ignite.internal.pagemem.PageIdAllocator.INDEX_PARTITION;
+import static org.apache.ignite.internal.processors.cache.persistence.GridCacheDatabaseSharedManager.IGNITE_PDS_SKIP_CHECKPOINT_ON_NODE_STOP;
import static org.apache.ignite.internal.processors.metric.impl.MetricUtils.metricName;
import static org.apache.ignite.testframework.GridTestUtils.assertThrowsAnyCause;
import static org.apache.ignite.testframework.GridTestUtils.waitForCondition;
@@ -581,6 +587,7 @@ public class CacheGroupReencryptionTest extends AbstractEncryptionTest {
* @throws Exception If failed.
*/
@Test
+ @WithSystemProperty(key = IGNITE_PDS_SKIP_CHECKPOINT_ON_NODE_STOP, value = "true")
public void testReencryptionOnUnstableTopology() throws Exception {
backups = 1;
pageScanRate = 2;
@@ -615,7 +622,24 @@ public class CacheGroupReencryptionTest extends AbstractEncryptionTest {
stopGrid(gridName);
- startGrid(gridName);
+ IgniteEx restarted = startGrid(gridName);
+
+ // Find last reencrypted page's index of currently reencrypted partition.
+ ReencryptionStatus firstNotReencrypted = findFirstNotReencrypted(restarted, cacheGroups);
+
+ if (firstNotReencrypted != null) {
+ int grpId = firstNotReencrypted.grpId;
+ int partId = firstNotReencrypted.partId;
+ int idx = firstNotReencrypted.pageIdx;
+
+ // Wait until reencryption status changes.
+ boolean updated = waitForCondition(() ->
+ reencryptionPageIndex(restarted, grpId, partId) > idx, TimeUnit.SECONDS.toMillis(10));
+
+ // If reencryption page index changed, make a checkpoint, so that status of reencryption is saved.
+ if (updated)
+ forceCheckpoint(restarted);
+ }
}
stopAllGrids();
@@ -921,4 +945,67 @@ public class CacheGroupReencryptionTest extends AbstractEncryptionTest {
return Objects.hash(name, id);
}
}
+
+ /** Reencryption status of the partition. */
+ private static class ReencryptionStatus {
+ /** Cache group id. */
+ final int grpId;
+
+ /** Partition id. */
+ final int partId;
+
+ /** Reencrypted page index. */
+ final int pageIdx;
+
+ /** Constructor. */
+ private ReencryptionStatus(int grpId, int partId, int pageIdx) {
+ this.grpId = grpId;
+ this.partId = partId;
+ this.pageIdx = pageIdx;
+ }
+ }
+
+ /**
+ * Finds first not reencrypted partition and returns tuple with cache group id, partition id and reencrypted page index.
+ */
+ @Nullable private static ReencryptionStatus findFirstNotReencrypted(IgniteEx node, Iterable<String> cacheGrps) {
+ for (String cacheGrp : cacheGrps) {
+ int grpId = CU.cacheId(cacheGrp);
+
+ CacheGroupContext grp = node.context().cache().cacheGroup(grpId);
+
+ if (grp == null || !grp.affinityNode())
+ continue;
+
+ for (int p = 0; p < grp.affinity().partitions(); p++) {
+ int pageIdx = reencryptionPageIndex(node, grpId, p);
+
+ if (pageIdx != Integer.MAX_VALUE)
+ return new ReencryptionStatus(grpId, p, pageIdx);
+ }
+
+ int pageIdx = reencryptionPageIndex(node, grpId, INDEX_PARTITION);
+
+ if (pageIdx != Integer.MAX_VALUE)
+ return new ReencryptionStatus(grpId, INDEX_PARTITION, pageIdx);
+ }
+
+ return null;
+ }
+
+ /** Gets reencryption page index of partition. */
+ private static int reencryptionPageIndex(IgniteEx node, int grpId, int partId) {
+ long state = node.context().encryption().getEncryptionState(grpId, partId);
+
+ int pageIdx = ReencryptStateUtils.pageIndex(state);
+
+ if (ReencryptStateUtils.pageCount(state) == pageIdx) {
+ // In case if reencryption finished, page count will be zero along with page index,
+ // making pageIndex lesser than previously obtained. Return MAX_VALUE so that it will always be higher than
+ // previously obtained value.
+ return Integer.MAX_VALUE;
+ }
+
+ return pageIdx;
+ }
}