From 3a2fab1d46f6bd2c48ee443018d4ad69649bcaa6 Mon Sep 17 00:00:00 2001 From: Ryan Emerson Date: Thu, 28 Jan 2021 13:56:13 +0000 Subject: [PATCH] ISPN-12667 GlobalState incompatibility between 11.x and 12.x --- .../ch/impl/ReplicatedConsistentHash.java | 6 +- ...GlobalStateBackwardsCompatibilityTest.java | 88 +++++++++++++++++++ 2 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 core/src/test/java/org/infinispan/globalstate/GlobalStateBackwardsCompatibilityTest.java diff --git a/core/src/main/java/org/infinispan/distribution/ch/impl/ReplicatedConsistentHash.java b/core/src/main/java/org/infinispan/distribution/ch/impl/ReplicatedConsistentHash.java index 183afc17a65e..6ca54716f46f 100644 --- a/core/src/main/java/org/infinispan/distribution/ch/impl/ReplicatedConsistentHash.java +++ b/core/src/main/java/org/infinispan/distribution/ch/impl/ReplicatedConsistentHash.java @@ -125,7 +125,11 @@ public ReplicatedConsistentHash union(ReplicatedConsistentHash ch2) { private static List
parseMembers(ScopedPersistentState state, String numMembersPropertyName, String memberPropertyFormat) { - int numMembers = Integer.parseInt(state.getProperty(numMembersPropertyName)); + String property = state.getProperty(numMembersPropertyName); + if (property == null) { + return Collections.emptyList(); + } + int numMembers = Integer.parseInt(property); List
members = new ArrayList<>(numMembers); for (int i = 0; i < numMembers; i++) { PersistentUUID uuid = PersistentUUID.fromString(state.getProperty(String.format(memberPropertyFormat, i))); diff --git a/core/src/test/java/org/infinispan/globalstate/GlobalStateBackwardsCompatibilityTest.java b/core/src/test/java/org/infinispan/globalstate/GlobalStateBackwardsCompatibilityTest.java new file mode 100644 index 000000000000..b42651e23546 --- /dev/null +++ b/core/src/test/java/org/infinispan/globalstate/GlobalStateBackwardsCompatibilityTest.java @@ -0,0 +1,88 @@ +package org.infinispan.globalstate; + +import static org.infinispan.commons.test.CommonsTestingUtil.tmpDirectory; + +import java.io.File; +import java.io.FileOutputStream; +import java.util.Properties; +import java.util.concurrent.TimeUnit; +import java.util.stream.IntStream; + +import org.infinispan.commons.util.Util; +import org.infinispan.configuration.cache.CacheMode; +import org.infinispan.configuration.cache.ConfigurationBuilder; +import org.infinispan.configuration.global.GlobalConfigurationBuilder; +import org.infinispan.manager.EmbeddedCacheManager; +import org.infinispan.test.MultipleCacheManagersTest; +import org.infinispan.topology.PersistentUUID; +import org.testng.annotations.AfterClass; +import org.testng.annotations.Test; + +/** + * ISPN-12667 A test to ensure that global state properties from previous Infinispan majors are compatible. + * + * @author Ryan Emerson + * @since 12.0 + */ +@Test(groups = "functional", testName = "globalstate.GlobalStateBackwardsCompatibilityTest") +public class GlobalStateBackwardsCompatibilityTest extends MultipleCacheManagersTest { + private static final String CACHE_NAME = "testCache"; + private static final String MEMBER_0 = PersistentUUID.randomUUID().toString(); + private static final String MEMBER_1 = PersistentUUID.randomUUID().toString(); + + @Override + protected void createCacheManagers() throws Throwable { + createCacheManagerWithGlobalState(MEMBER_0, tmpDirectory(this.getClass().getSimpleName(), "0")); + createCacheManagerWithGlobalState(MEMBER_1, tmpDirectory(this.getClass().getSimpleName(), "1")); + waitForClusterToForm(CACHE_NAME); + } + + @AfterClass(alwaysRun = true) + @Override + protected void destroy() { + super.destroy(); + Util.recursiveFileRemove(tmpDirectory(this.getClass().getSimpleName())); + } + + private void createCacheManagerWithGlobalState(String uuid, String stateDirectory) throws Exception { + new File(stateDirectory).mkdirs(); + createCacheState(stateDirectory); + + Properties globalState = new Properties(); + globalState.put("@version", "11.0.9.Final"); + globalState.put("version-major", "11"); + globalState.put("@timestamp", "2021-01-28T10\\:53\\:56.289272Z"); + globalState.put("uuid", uuid); + globalState.store(new FileOutputStream(new File(stateDirectory, "___global.state")), null); + + GlobalConfigurationBuilder global = GlobalConfigurationBuilder.defaultClusteredBuilder(); + global.globalState().enable().persistentLocation(stateDirectory); + + ConfigurationBuilder config = new ConfigurationBuilder(); + config.clustering().cacheMode(CacheMode.REPL_SYNC).stateTransfer().timeout(1, TimeUnit.SECONDS) + .persistence().addSingleFileStore().location(stateDirectory); + EmbeddedCacheManager manager = addClusterEnabledCacheManager(global, null); + manager.defineConfiguration(CACHE_NAME, config.build()); + } + + private void createCacheState(String stateDirectory) throws Exception { + Properties cacheState = new Properties(); + cacheState.put("@version", "11.0.9.Final"); + cacheState.put("@timestamp", "2021-01-28T10\\:53\\:56.289272Z"); + cacheState.put("version-major", "11"); + cacheState.put("consistentHash", "org.infinispan.distribution.ch.impl.ReplicatedConsistentHash"); + cacheState.put("members", "2"); + cacheState.put("member.0", MEMBER_0); + cacheState.put("member.1", MEMBER_1); + cacheState.put("capacityFactors", "2"); + cacheState.put("capacityFactor.0", "1.0"); + cacheState.put("capacityFactor.1", "1.0"); + cacheState.put("primaryOwners", "256"); + IntStream.range(0, 256).forEach(i -> cacheState.put("primaryOwners." + i, Integer.toString(i % 2))); + cacheState.store(new FileOutputStream(new File(stateDirectory, CACHE_NAME + ".state")), null); + } + + @Test + public void compatibilityTest() { + } +}