You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by ag...@apache.org on 2017/10/04 06:47:02 UTC
[1/2] ignite git commit: IGNITE-6285 Enhance persistent store paths
handling - Fixes #2775.
Repository: ignite
Updated Branches:
refs/heads/master 855fe4b51 -> 62f3c4c52
http://git-wip-us.apache.org/repos/asf/ignite/blob/62f3c4c5/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/filename/IgniteUidAsConsistentIdMigrationTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/filename/IgniteUidAsConsistentIdMigrationTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/filename/IgniteUidAsConsistentIdMigrationTest.java
new file mode 100644
index 0000000..fe7e4df
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/filename/IgniteUidAsConsistentIdMigrationTest.java
@@ -0,0 +1,712 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.cache.persistence.db.filename;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.UUID;
+import java.util.regex.Pattern;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.configuration.MemoryConfiguration;
+import org.apache.ignite.configuration.MemoryPolicyConfiguration;
+import org.apache.ignite.configuration.PersistentStoreConfiguration;
+import org.apache.ignite.internal.processors.cache.persistence.filename.PdsConsistentIdProcessor;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.testframework.GridStringLogger;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.jetbrains.annotations.NotNull;
+
+import static org.apache.ignite.IgniteSystemProperties.IGNITE_CONSISTENT_ID_BY_HOST_WITHOUT_PORT;
+import static org.apache.ignite.IgniteSystemProperties.IGNITE_DATA_STORAGE_FOLDER_BY_CONSISTENT_ID;
+import static org.apache.ignite.internal.processors.cache.persistence.filename.PdsConsistentIdProcessor.parseSubFolderName;
+
+/**
+ * Test for new and old style persistent storage folders generation
+ */
+public class IgniteUidAsConsistentIdMigrationTest extends GridCommonAbstractTest {
+ /** Cache name for test. */
+ public static final String CACHE_NAME = "dummy";
+
+ /** Clear DB folder after each test. May be set to false for local debug */
+ private static final boolean deleteAfter = true;
+
+ /** Clear DB folder before each test. */
+ private static final boolean deleteBefore = true;
+
+ /** Fail test if delete of DB folder was not completed. */
+ private static final boolean failIfDeleteNotCompleted = true;
+
+ /** Configured consistent id. */
+ private String configuredConsistentId;
+
+ /** Logger to accumulate messages, null will cause logger won't be customized */
+ private GridStringLogger strLog;
+
+ /** Clear properties after this test run. Flag protects from failed test */
+ private boolean clearPropsAfterTest = false;
+
+ /** Place storage in temp folder for current test run. */
+ private boolean placeStorageInTemp;
+
+ /** A path to persistent store custom path for current test run. */
+ private File pstStoreCustomPath;
+
+ /** A path to persistent store WAL work custom path. */
+ private File pstWalStoreCustomPath;
+
+ /** A path to persistent store WAL archive custom path. */
+ private File pstWalArchCustomPath;
+
+ /** {@inheritDoc} */
+ @Override protected void beforeTest() throws Exception {
+ stopAllGrids();
+
+ if (deleteBefore)
+ deleteWorkFiles();
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void afterTest() throws Exception {
+ stopAllGrids();
+
+ if (deleteAfter)
+ deleteWorkFiles();
+
+ if (clearPropsAfterTest) {
+ System.clearProperty(IGNITE_DATA_STORAGE_FOLDER_BY_CONSISTENT_ID);
+ System.clearProperty(IGNITE_CONSISTENT_ID_BY_HOST_WITHOUT_PORT);
+ }
+ }
+
+ /**
+ * @throws IgniteCheckedException If failed.
+ */
+ private void deleteWorkFiles() throws IgniteCheckedException {
+ boolean ok = true;
+
+ if (pstStoreCustomPath != null)
+ ok &= deleteRecursively(pstStoreCustomPath);
+ else
+ ok &= deleteRecursively(U.resolveWorkDirectory(U.defaultWorkDirectory(), "db", false));
+
+ if (pstWalArchCustomPath != null)
+ ok &= deleteRecursively(pstWalArchCustomPath);
+
+ if (pstWalStoreCustomPath != null)
+ ok &= deleteRecursively(pstWalStoreCustomPath);
+
+ ok &= deleteRecursively(U.resolveWorkDirectory(U.defaultWorkDirectory(), "binary_meta", false));
+
+ if (failIfDeleteNotCompleted)
+ assertTrue(ok);
+ }
+
+ /** {@inheritDoc} */
+ @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+ final IgniteConfiguration cfg = super.getConfiguration(gridName);
+
+ if (configuredConsistentId != null)
+ cfg.setConsistentId(configuredConsistentId);
+
+ final PersistentStoreConfiguration psCfg = new PersistentStoreConfiguration();
+
+ if (placeStorageInTemp) {
+ final File tempDir = new File(System.getProperty("java.io.tmpdir"));
+
+ pstStoreCustomPath = new File(tempDir, "Store");
+ pstWalStoreCustomPath = new File(tempDir, "WalStore");
+ pstWalArchCustomPath = new File(tempDir, "WalArchive");
+
+ psCfg.setPersistentStorePath(pstStoreCustomPath.getAbsolutePath());
+ psCfg.setWalStorePath(pstWalStoreCustomPath.getAbsolutePath());
+ psCfg.setWalArchivePath(pstWalArchCustomPath.getAbsolutePath());
+ }
+
+ cfg.setPersistentStoreConfiguration(psCfg);
+
+ final MemoryConfiguration memCfg = new MemoryConfiguration();
+ final MemoryPolicyConfiguration memPolCfg = new MemoryPolicyConfiguration();
+
+ memPolCfg.setMaxSize(32 * 1024 * 1024); // we don't need much memory for this test
+ memCfg.setMemoryPolicies(memPolCfg);
+ cfg.setMemoryConfiguration(memCfg);
+
+ if (strLog != null)
+ cfg.setGridLogger(strLog);
+
+ return cfg;
+ }
+
+ /**
+ * Checks start on empty PDS folder, in that case node 0 should start with random UUID.
+ *
+ * @throws Exception if failed.
+ */
+ public void testNewStyleIdIsGenerated() throws Exception {
+ final Ignite ignite = startActivateFillDataGrid(0);
+
+ //test UUID is parsable from consistent ID test
+ UUID.fromString(ignite.cluster().localNode().consistentId().toString());
+ assertPdsDirsDefaultExist(genNewStyleSubfolderName(0, ignite));
+ stopGrid(0);
+ }
+
+ /**
+ * Checks start on empty PDS folder, in that case node 0 should start with random UUID.
+ *
+ * @throws Exception if failed.
+ */
+ public void testNewStyleIdIsGeneratedInCustomStorePath() throws Exception {
+ placeStorageInTemp = true;
+ final Ignite ignite = startActivateFillDataGrid(0);
+
+ //test UUID is parsable from consistent ID test
+ UUID.fromString(ignite.cluster().localNode().consistentId().toString());
+ final String subfolderName = genNewStyleSubfolderName(0, ignite);
+
+ assertDirectoryExist("binary_meta", subfolderName);
+
+ assertDirectoryExist(pstWalArchCustomPath, subfolderName);
+ assertDirectoryExist(pstWalArchCustomPath, subfolderName);
+ assertDirectoryExist(pstStoreCustomPath, subfolderName);
+
+ stopGrid(0);
+ }
+
+ /**
+ * Checks start on empty PDS folder using configured ConsistentId. We should start using this ID in compatible mode.
+ *
+ * @throws Exception if failed.
+ */
+ public void testPreconfiguredConsitentIdIsApplied() throws Exception {
+ this.configuredConsistentId = "someConfiguredConsistentId";
+ Ignite ignite = startActivateFillDataGrid(0);
+
+ assertPdsDirsDefaultExist(configuredConsistentId);
+ stopGrid(0);
+ }
+
+ /**
+ * Checks start on configured ConsistentId with same value as default, this emulate old style folder is already
+ * available. We should restart using this folder.
+ *
+ * @throws Exception if failed
+ */
+ public void testRestartOnExistingOldStyleId() throws Exception {
+ final String expDfltConsistentId = "127.0.0.1:47500";
+
+ this.configuredConsistentId = expDfltConsistentId; //this is for create old node folder
+
+ final Ignite igniteEx = startActivateGrid(0);
+
+ final String expVal = "there is compatible mode with old style folders!";
+
+ igniteEx.getOrCreateCache(CACHE_NAME).put("hi", expVal);
+
+ assertPdsDirsDefaultExist(U.maskForFileName(configuredConsistentId));
+ stopGrid(0);
+
+ this.configuredConsistentId = null; //now set up grid on existing folder
+
+ final Ignite igniteRestart = startActivateGrid(0);
+
+ assertEquals(expDfltConsistentId, igniteRestart.cluster().localNode().consistentId());
+ final IgniteCache<Object, Object> cache = igniteRestart.cache(CACHE_NAME);
+
+ assertNotNull("Expected to have cache [" + CACHE_NAME + "] using [" + expDfltConsistentId + "] as PDS folder", cache);
+ final Object valFromCache = cache.get("hi");
+
+ assertNotNull("Expected to load data from cache using [" + expDfltConsistentId + "] as PDS folder", valFromCache);
+ assertTrue(expVal.equals(valFromCache));
+ stopGrid(0);
+ }
+
+ /**
+ * Start stop grid without activation should cause lock to be released and restarted node should have index 0
+ *
+ * @throws Exception if failed
+ */
+ public void testStartWithoutActivate() throws Exception {
+ //start stop grid without activate
+ startGrid(0);
+ stopGrid(0);
+
+ Ignite igniteRestart = startActivateFillDataGrid(0);
+ assertPdsDirsDefaultExist(genNewStyleSubfolderName(0, igniteRestart));
+ stopGrid(0);
+ }
+
+ /**
+ * Checks start on empty PDS folder, in that case node 0 should start with random UUID
+ *
+ * @throws Exception if failed
+ */
+ public void testRestartOnSameFolderWillCauseSameUuidGeneration() throws Exception {
+ final UUID uuid;
+ {
+ final Ignite ignite = startActivateFillDataGrid(0);
+
+ assertPdsDirsDefaultExist(genNewStyleSubfolderName(0, ignite));
+
+ uuid = (UUID)ignite.cluster().localNode().consistentId();
+ stopGrid(0);
+ }
+
+ {
+ final Ignite igniteRestart = startActivateGrid(0);
+
+ assertTrue("there!".equals(igniteRestart.cache(CACHE_NAME).get("hi")));
+
+ final Object consIdRestart = igniteRestart.cluster().localNode().consistentId();
+
+ assertPdsDirsDefaultExist(genNewStyleSubfolderName(0, igniteRestart));
+ stopGrid(0);
+
+ assertEquals(uuid, consIdRestart);
+ }
+ }
+
+ /**
+ * This test starts node, activates, deactivates node, and then start second node.
+ * Expected behaviour is following: second node will join topology with separate node folder
+ *
+ * @throws Exception if failed
+ */
+ public void testStartNodeAfterDeactivate() throws Exception {
+ final UUID uuid;
+ {
+ final Ignite ignite = startActivateFillDataGrid(0);
+
+ assertPdsDirsDefaultExist(genNewStyleSubfolderName(0, ignite));
+
+ uuid = (UUID)ignite.cluster().localNode().consistentId();
+ ignite.active(false);
+ }
+ {
+ final Ignite igniteRestart = startActivateGrid(1);
+
+ grid(0).active(true);
+ final Object consIdRestart = igniteRestart.cluster().localNode().consistentId();
+
+ assertPdsDirsDefaultExist(genNewStyleSubfolderName(1, igniteRestart));
+
+ stopGrid(1);
+ assertFalse(consIdRestart.equals(uuid));
+ }
+ stopGrid(0);
+ assertNodeIndexesInFolder(0, 1);
+ }
+
+ /**
+ * @param idx Index of the grid to start.
+ * @return Started and activated grid.
+ * @throws Exception If failed.
+ */
+ @NotNull private Ignite startActivateFillDataGrid(int idx) throws Exception {
+ final Ignite ignite = startActivateGrid(idx);
+
+ ignite.getOrCreateCache(CACHE_NAME).put("hi", "there!");
+
+ return ignite;
+ }
+
+ /**
+ * Starts and activates new grid with given index.
+ *
+ * @param idx Index of the grid to start.
+ * @return Started and activated grid.
+ * @throws Exception If anything failed.
+ */
+ @NotNull private Ignite startActivateGrid(int idx) throws Exception {
+ final Ignite ignite = startGrid(idx);
+
+ ignite.active(true);
+
+ return ignite;
+ }
+
+ /**
+ * Generates folder name in new style using constant prefix and UUID
+ *
+ * @param nodeIdx expected node index to check
+ * @param ignite ignite instance
+ * @return name of storage related subfolders
+ */
+ @NotNull private String genNewStyleSubfolderName(final int nodeIdx, final Ignite ignite) {
+ final Object consistentId = ignite.cluster().localNode().consistentId();
+
+ assertTrue("For new style folders consistent ID should be UUID," +
+ " but actual class is " + (consistentId == null ? null : consistentId.getClass()),
+ consistentId instanceof UUID);
+
+ return PdsConsistentIdProcessor.genNewStyleSubfolderName(nodeIdx, (UUID)consistentId);
+ }
+
+ /**
+ * test two nodes started at the same db root folder, second node should get index 1
+ *
+ * @throws Exception if failed
+ */
+ public void testNodeIndexIncremented() throws Exception {
+ final Ignite ignite0 = startGrid(0);
+ final Ignite ignite1 = startGrid(1);
+
+ ignite0.active(true);
+
+ ignite0.getOrCreateCache(CACHE_NAME).put("hi", "there!");
+ ignite1.getOrCreateCache(CACHE_NAME).put("hi1", "there!");
+
+ assertPdsDirsDefaultExist(genNewStyleSubfolderName(0, ignite0));
+ assertPdsDirsDefaultExist(genNewStyleSubfolderName(1, ignite1));
+
+ stopGrid(0);
+ stopGrid(1);
+ assertNodeIndexesInFolder(0, 1);
+ }
+
+ /**
+ * Test verified that new style folder is taken always with lowest index
+ *
+ * @throws Exception if failed
+ */
+ public void testNewStyleAlwaysSmallestNodeIndexIsCreated() throws Exception {
+ final Ignite ignite0 = startGrid(0);
+ final Ignite ignite1 = startGrid(1);
+ final Ignite ignite2 = startGrid(2);
+ final Ignite ignite3 = startGrid(3);
+
+ ignite0.active(true);
+
+ ignite0.getOrCreateCache(CACHE_NAME).put("hi", "there!");
+ ignite3.getOrCreateCache(CACHE_NAME).put("hi1", "there!");
+
+ assertPdsDirsDefaultExist(genNewStyleSubfolderName(0, ignite0));
+ assertPdsDirsDefaultExist(genNewStyleSubfolderName(1, ignite1));
+ assertPdsDirsDefaultExist(genNewStyleSubfolderName(2, ignite2));
+ assertPdsDirsDefaultExist(genNewStyleSubfolderName(3, ignite3));
+
+ assertNodeIndexesInFolder(0, 1, 2, 3);
+ stopAllGrids();
+
+ //this grid should take folder with index 0 as unlocked
+ final Ignite ignite4Restart = startActivateGrid(3);
+ assertPdsDirsDefaultExist(genNewStyleSubfolderName(0, ignite4Restart));
+
+ assertNodeIndexesInFolder(0, 1, 2, 3);
+ stopAllGrids();
+ }
+
+ /**
+ * Test verified that new style folder is taken always with lowest index
+ *
+ * @throws Exception if failed
+ */
+ public void testNewStyleAlwaysSmallestNodeIndexIsCreatedMultithreaded() throws Exception {
+ final Ignite ignite0 = startGridsMultiThreaded(11);
+
+ ignite0.active(true);
+
+ ignite0.getOrCreateCache(CACHE_NAME).put("hi", "there!");
+ ignite0.getOrCreateCache(CACHE_NAME).put("hi1", "there!");
+
+ assertPdsDirsDefaultExist(genNewStyleSubfolderName(0, ignite0));
+
+ assertNodeIndexesInFolder(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+ stopAllGrids();
+
+ //this grid should take folder with index 0 as unlocked
+ final Ignite ignite4Restart = startActivateGrid(4);
+ assertPdsDirsDefaultExist(genNewStyleSubfolderName(0, ignite4Restart));
+ stopAllGrids();
+
+ assertNodeIndexesInFolder(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+ }
+
+ /**
+ * Test start two nodes with predefined conistent ID (emulate old fashion node). Then restart two nodes. Expected
+ * both nodes will get its own old folders
+ *
+ * @throws Exception if failed.
+ */
+ public void testStartTwoOldStyleNodes() throws Exception {
+ final String expDfltConsistentId1 = "127.0.0.1:47500";
+
+ this.configuredConsistentId = expDfltConsistentId1; //this is for create old node folder
+ final Ignite ignite = startGrid(0);
+
+ final String expDfltConsistentId2 = "127.0.0.1:47501";
+
+ this.configuredConsistentId = expDfltConsistentId2; //this is for create old node folder
+ final Ignite ignite2 = startGrid(1);
+
+ ignite.active(true);
+
+ final String expVal = "there is compatible mode with old style folders!";
+
+ ignite2.getOrCreateCache(CACHE_NAME).put("hi", expVal);
+
+ assertPdsDirsDefaultExist(U.maskForFileName(expDfltConsistentId1));
+ assertPdsDirsDefaultExist(U.maskForFileName(expDfltConsistentId2));
+ stopAllGrids();
+
+ this.configuredConsistentId = null; //now set up grid on existing folder
+
+ final Ignite igniteRestart = startGrid(0);
+ final Ignite igniteRestart2 = startGrid(1);
+
+ igniteRestart2.active(true);
+
+ assertEquals(expDfltConsistentId1, igniteRestart.cluster().localNode().consistentId());
+ assertEquals(expDfltConsistentId2, igniteRestart2.cluster().localNode().consistentId());
+
+ final IgniteCache<Object, Object> cache = igniteRestart.cache(CACHE_NAME);
+
+ assertNotNull("Expected to have cache [" + CACHE_NAME + "] using [" + expDfltConsistentId1 + "] as PDS folder", cache);
+ final Object valFromCache = cache.get("hi");
+
+ assertNotNull("Expected to load data from cache using [" + expDfltConsistentId1 + "] as PDS folder", valFromCache);
+ assertTrue(expVal.equals(valFromCache));
+
+ assertNodeIndexesInFolder(); //no new style nodes should be found
+ stopGrid(0);
+ }
+
+ /**
+ * Tests compatible mode enabled by this test to start.
+ * Expected to be 2 folders and no new style folders in this case.
+ *
+ * @throws Exception if failed.
+ */
+ public void testStartOldStyleNodesByCompatibleProperty() throws Exception {
+ clearPropsAfterTest = true;
+ System.setProperty(IGNITE_DATA_STORAGE_FOLDER_BY_CONSISTENT_ID, "true");
+
+ final Ignite ignite1 = startGrid(0);
+ final Ignite ignite2 = startGrid(1);
+
+ ignite1.active(true);
+
+ final String expVal = "there is compatible mode with old style folders!";
+
+ ignite2.getOrCreateCache(CACHE_NAME).put("hi", expVal);
+
+ assertNodeIndexesInFolder(); // expected to have no new style folders
+
+ final Object consistentId1 = ignite1.cluster().localNode().consistentId();
+
+ assertPdsDirsDefaultExist(U.maskForFileName(consistentId1.toString()));
+ final Object consistentId2 = ignite2.cluster().localNode().consistentId();
+
+ assertPdsDirsDefaultExist(U.maskForFileName(consistentId2.toString()));
+ stopAllGrids();
+
+ System.clearProperty(IGNITE_DATA_STORAGE_FOLDER_BY_CONSISTENT_ID);
+ final Ignite igniteRestart = startGrid(0);
+ final Ignite igniteRestart2 = startGrid(1);
+
+ igniteRestart2.active(true);
+
+ assertEquals(consistentId1, igniteRestart.cluster().localNode().consistentId());
+ assertEquals(consistentId2, igniteRestart2.cluster().localNode().consistentId());
+
+ assertNodeIndexesInFolder(); //new style nodes should not be found
+ stopGrid(0);
+ }
+
+ /**
+ * Tests compatible mode enabled by this test to start, also no port is enabled.
+ * Expected to be 1 folder and no new style folders in this case.
+ *
+ * @throws Exception if failed.
+ */
+ public void testStartOldStyleNoPortsNodesByCompatibleProperty() throws Exception {
+ clearPropsAfterTest = true;
+ System.setProperty(IGNITE_DATA_STORAGE_FOLDER_BY_CONSISTENT_ID, "true");
+ System.setProperty(IGNITE_CONSISTENT_ID_BY_HOST_WITHOUT_PORT, "true");
+
+ final Ignite ignite1 = startGrid(0);
+
+ ignite1.active(true);
+
+ final String expVal = "there is compatible mode with old style folders!";
+
+ ignite1.getOrCreateCache(CACHE_NAME).put("hi", expVal);
+
+ assertNodeIndexesInFolder(); // expected to have no new style folders
+
+ final Object consistentId1 = ignite1.cluster().localNode().consistentId();
+
+ assertPdsDirsDefaultExist(U.maskForFileName(consistentId1.toString()));
+ stopAllGrids();
+
+ System.clearProperty(IGNITE_DATA_STORAGE_FOLDER_BY_CONSISTENT_ID);
+
+ final Ignite igniteRestart = startGrid(0);
+
+ igniteRestart.active(true);
+
+ assertEquals(consistentId1, igniteRestart.cluster().localNode().consistentId());
+
+ assertNodeIndexesInFolder(); //new style nodes should not be found
+ stopGrid(0);
+ System.clearProperty(IGNITE_CONSISTENT_ID_BY_HOST_WITHOUT_PORT);
+ }
+
+ /**
+ * Test case If there are no matching folders,
+ * but the directory contains old-style consistent IDs.
+ * Ignite should print out a warning.
+ *
+ * @throws Exception if failed.
+ */
+ public void testOldStyleNodeWithUnexpectedPort() throws Exception {
+ this.configuredConsistentId = "127.0.0.1:49999"; //emulated old-style node with not appropriate consistent ID
+ final Ignite ignite = startActivateFillDataGrid(0);
+ final IgniteCache<Object, Object> second = ignite.getOrCreateCache("second");
+
+ final int entries = 100;
+
+ for (int i = 0; i < entries; i++)
+ second.put((int)(Math.random() * entries), getClass().getName());
+
+ final String prevVerFolder = U.maskForFileName(ignite.cluster().localNode().consistentId().toString());
+ final String path = new File(new File(U.defaultWorkDirectory(), "db"), prevVerFolder).getCanonicalPath();
+
+ assertPdsDirsDefaultExist(prevVerFolder);
+ stopAllGrids();
+
+ this.configuredConsistentId = null;
+ this.strLog = new GridStringLogger();
+ startActivateGrid(0);
+ assertNodeIndexesInFolder(0); //one 0 index folder is created
+
+ final String wholeNodeLog = strLog.toString();
+ stopAllGrids();
+
+ String foundWarning = null;
+ for (String line : wholeNodeLog.split("\n")) {
+ if (line.contains("There is other non-empty storage folder under storage base directory")) {
+ foundWarning = line;
+ break;
+ }
+ }
+
+ if (foundWarning != null)
+ log.info("\nWARNING generated successfully [\n" + foundWarning + "\n]");
+
+ assertTrue("Expected to warn user on existence of old style path",
+ foundWarning != null);
+
+ assertTrue("Expected to warn user on existence of old style path [" + path + "]",
+ foundWarning.contains(path));
+
+ assertTrue("Expected to print some size for [" + path + "]",
+ Pattern.compile(" [0-9]* bytes").matcher(foundWarning).find());
+
+ strLog = null;
+ startActivateGrid(0);
+ assertNodeIndexesInFolder(0); //one 0 index folder is created
+ stopAllGrids();
+ }
+
+ /**
+ * @param indexes expected new style node indexes in folders
+ * @throws IgniteCheckedException if failed
+ */
+ private void assertNodeIndexesInFolder(Integer... indexes) throws IgniteCheckedException {
+ assertEquals(new TreeSet<>(Arrays.asList(indexes)), getAllNodeIndexesInFolder());
+ }
+
+ /**
+ * @return set of all indexes of nodes found in work folder
+ * @throws IgniteCheckedException if failed.
+ */
+ @NotNull private Set<Integer> getAllNodeIndexesInFolder() throws IgniteCheckedException {
+ final File curFolder = new File(U.defaultWorkDirectory(), PdsConsistentIdProcessor.DB_DEFAULT_FOLDER);
+ final Set<Integer> indexes = new TreeSet<>();
+ final File[] files = curFolder.listFiles(PdsConsistentIdProcessor.DB_SUBFOLDERS_NEW_STYLE_FILTER);
+
+ for (File file : files) {
+ final PdsConsistentIdProcessor.FolderCandidate uid = parseSubFolderName(file, log);
+
+ if (uid != null)
+ indexes.add(uid.nodeIndex());
+ }
+
+ return indexes;
+ }
+
+ /**
+ * Checks existence of all storage-related directories
+ *
+ * @param subDirName sub directories name expected
+ * @throws IgniteCheckedException if IO error occur
+ */
+ private void assertPdsDirsDefaultExist(String subDirName) throws IgniteCheckedException {
+ assertDirectoryExist("binary_meta", subDirName);
+ assertDirectoryExist(PersistentStoreConfiguration.DFLT_WAL_STORE_PATH, subDirName);
+ assertDirectoryExist(PersistentStoreConfiguration.DFLT_WAL_ARCHIVE_PATH, subDirName);
+ assertDirectoryExist(PdsConsistentIdProcessor.DB_DEFAULT_FOLDER, subDirName);
+ }
+
+ /**
+ * Checks one folder existence.
+ *
+ * @param subFolderNames sub folders chain array to touch.
+ * @throws IgniteCheckedException if IO error occur.
+ */
+ private void assertDirectoryExist(String... subFolderNames) throws IgniteCheckedException {
+ final File curFolder = new File(U.defaultWorkDirectory());
+
+ assertDirectoryExist(curFolder, subFolderNames);
+ }
+
+
+ /**
+ * Checks one folder existence.
+ *
+ * @param workFolder current work folder.
+ * @param subFolderNames sub folders chain array to touch.
+ * @throws IgniteCheckedException if IO error occur.
+ */
+ private void assertDirectoryExist(final File workFolder, String... subFolderNames) throws IgniteCheckedException {
+ File curFolder = workFolder;
+
+ for (String name : subFolderNames) {
+ curFolder = new File(curFolder, name);
+ }
+
+ final String path;
+
+ try {
+ path = curFolder.getCanonicalPath();
+ }
+ catch (IOException e) {
+ throw new IgniteCheckedException("Failed to convert path: [" + curFolder.getAbsolutePath() + "]", e);
+ }
+ assertTrue("Directory " + Arrays.asList(subFolderNames).toString()
+ + " is expected to exist [" + path + "]", curFolder.exists() && curFolder.isDirectory());
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/62f3c4c5/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/IgniteWalRecoveryTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/IgniteWalRecoveryTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/IgniteWalRecoveryTest.java
index c160f60..bf8cd85 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/IgniteWalRecoveryTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/IgniteWalRecoveryTest.java
@@ -28,6 +28,7 @@ import java.util.Map;
import java.util.Objects;
import java.util.Random;
import java.util.Set;
+import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
@@ -68,6 +69,7 @@ import org.apache.ignite.internal.pagemem.wal.record.WALRecord;
import org.apache.ignite.internal.pagemem.wal.record.delta.PageDeltaRecord;
import org.apache.ignite.internal.processors.cache.GridCacheSharedContext;
import org.apache.ignite.internal.processors.cache.persistence.GridCacheDatabaseSharedManager;
+import org.apache.ignite.internal.processors.cache.persistence.filename.PdsConsistentIdProcessor;
import org.apache.ignite.internal.processors.cache.persistence.pagemem.PageMemoryEx;
import org.apache.ignite.internal.processors.cache.persistence.tree.io.TrackingPageIO;
import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
@@ -575,9 +577,11 @@ public class IgniteWalRecoveryTest extends GridCommonAbstractTest {
for (int i = 0; i < 100; i++)
cache.put(i, new IndexedObject(i));
+ final Object consistentId = ignite.cluster().localNode().consistentId();
+
stopGrid(1);
- final File cacheDir = cacheDir("partitioned", ignite.context().discovery().consistentId().toString());
+ final File cacheDir = cacheDir("partitioned", consistentId.toString());
final boolean renamed = cacheDir.renameTo(new File(cacheDir.getParent(), "cache-partitioned0"));
@@ -605,14 +609,15 @@ public class IgniteWalRecoveryTest extends GridCommonAbstractTest {
* @return Cache dir.
* @throws IgniteCheckedException If fail.
*/
- private File cacheDir(final String cacheName, String consId) throws IgniteCheckedException {
- consId = consId.replaceAll("[\\.:]", "_");
+ private File cacheDir(final String cacheName, final String consId) throws IgniteCheckedException {
+ final String subfolderName
+ = PdsConsistentIdProcessor.genNewStyleSubfolderName(0, UUID.fromString(consId));
final File dbDir = U.resolveWorkDirectory(U.defaultWorkDirectory(), DFLT_STORE_DIR, false);
assert dbDir.exists();
- final File consIdDir = new File(dbDir.getAbsolutePath(), consId);
+ final File consIdDir = new File(dbDir.getAbsolutePath(), subfolderName);
assert consIdDir.exists();
http://git-wip-us.apache.org/repos/asf/ignite/blob/62f3c4c5/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/reader/IgniteWalReaderTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/reader/IgniteWalReaderTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/reader/IgniteWalReaderTest.java
index e2f58bd..b9c60b2 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/reader/IgniteWalReaderTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/reader/IgniteWalReaderTest.java
@@ -30,6 +30,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.UUID;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -64,14 +65,17 @@ import org.apache.ignite.internal.processors.cache.KeyCacheObject;
import org.apache.ignite.internal.processors.cache.persistence.wal.FileWriteAheadLogManager;
import org.apache.ignite.internal.processors.cache.persistence.wal.reader.IgniteWalIteratorFactory;
import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
+import org.apache.ignite.internal.util.typedef.internal.A;
import org.apache.ignite.internal.util.typedef.internal.U;
import org.apache.ignite.lang.IgniteBiTuple;
import org.apache.ignite.lang.IgnitePredicate;
import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
import org.apache.ignite.transactions.Transaction;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import static org.apache.ignite.events.EventType.EVT_WAL_SEGMENT_ARCHIVED;
+import static org.apache.ignite.internal.processors.cache.persistence.filename.PdsConsistentIdProcessor.genNewStyleSubfolderName;
import static org.apache.ignite.internal.processors.cache.persistence.file.FilePageStoreManager.DFLT_STORE_DIR;
/**
@@ -87,9 +91,6 @@ public class IgniteWalReaderTest extends GridCommonAbstractTest {
/** additional cache for testing different combinations of types in WAL */
private static final String CACHE_ADDL_NAME = "cache1";
- /** Fill wal with some data before iterating. Should be true for non local run */
- private static final boolean fillWalBeforeTest = true;
-
/** Delete DB dir before test. */
private static final boolean deleteBefore = true;
@@ -152,7 +153,7 @@ public class IgniteWalReaderTest extends GridCommonAbstractTest {
}
/** {@inheritDoc} */
- @Override protected void beforeTestsStarted() throws Exception {
+ @Override protected void beforeTest() throws Exception {
stopAllGrids();
if (deleteBefore)
@@ -171,8 +172,7 @@ public class IgniteWalReaderTest extends GridCommonAbstractTest {
* @throws IgniteCheckedException If failed.
*/
private void deleteWorkFiles() throws IgniteCheckedException {
- if (fillWalBeforeTest)
- deleteRecursively(U.resolveWorkDirectory(U.defaultWorkDirectory(), DFLT_STORE_DIR, false));
+ deleteRecursively(U.resolveWorkDirectory(U.defaultWorkDirectory(), DFLT_STORE_DIR, false));
}
/**
@@ -181,27 +181,23 @@ public class IgniteWalReaderTest extends GridCommonAbstractTest {
public void testFillWalAndReadRecords() throws Exception {
final int cacheObjectsToWrite = 10000;
- final String consistentId;
- if (fillWalBeforeTest) {
- final Ignite ignite0 = startGrid("node0");
+ final Ignite ignite0 = startGrid("node0");
- ignite0.active(true);
+ ignite0.active(true);
- consistentId = U.maskForFileName(ignite0.cluster().localNode().consistentId().toString());
+ final Serializable consistentId = (Serializable)ignite0.cluster().localNode().consistentId();
+ final String subfolderName = genNewStyleSubfolderName(0, (UUID)consistentId);
- putDummyRecords(ignite0, cacheObjectsToWrite);
+ putDummyRecords(ignite0, cacheObjectsToWrite);
- stopGrid("node0");
- }
- else
- consistentId = "127_0_0_1_47500";
+ stopGrid("node0");
final String workDir = U.defaultWorkDirectory();
final File db = U.resolveWorkDirectory(workDir, DFLT_STORE_DIR, false);
final File wal = new File(db, "wal");
final File walArchive = new File(wal, "archive");
- final MockWalIteratorFactory mockItFactory = new MockWalIteratorFactory(log, PAGE_SIZE, consistentId, WAL_SEGMENTS);
+ final MockWalIteratorFactory mockItFactory = new MockWalIteratorFactory(log, PAGE_SIZE, consistentId, subfolderName, WAL_SEGMENTS);
final WALIterator it = mockItFactory.iterator(wal, walArchive);
final int cntUsingMockIter = iterateAndCount(it, false);
@@ -209,11 +205,11 @@ public class IgniteWalReaderTest extends GridCommonAbstractTest {
assert cntUsingMockIter > 0;
assert cntUsingMockIter > cacheObjectsToWrite;
- final File walArchiveDirWithConsistentId = new File(walArchive, consistentId);
- final File walWorkDirWithConsistentId = new File(wal, consistentId);
+ final File walArchiveDirWithConsistentId = new File(walArchive, subfolderName);
+ final File walWorkDirWithConsistentId = new File(wal, subfolderName);
final File binaryMeta = U.resolveWorkDirectory(workDir, "binary_meta", false);
- final File binaryMetaWithConsId = new File(binaryMeta, consistentId);
+ final File binaryMetaWithConsId = new File(binaryMeta, subfolderName);
final File marshaller = U.resolveWorkDirectory(workDir, "marshaller", false);
final IgniteWalIteratorFactory factory = new IgniteWalIteratorFactory(log, PAGE_SIZE, binaryMetaWithConsId, marshaller);
@@ -304,7 +300,7 @@ public class IgniteWalReaderTest extends GridCommonAbstractTest {
final IgniteEvents evts = ignite.events();
if (!evts.isEnabled(EVT_WAL_SEGMENT_ARCHIVED))
- return; //nothing to test
+ assertTrue("nothing to test", false);
evts.localListen(new IgnitePredicate<Event>() {
@Override public boolean apply(Event e) {
@@ -428,29 +424,23 @@ public class IgniteWalReaderTest extends GridCommonAbstractTest {
final int cntEntries = 1000;
final int txCnt = 100;
- final Map<Object, Object> ctrlMap = new HashMap<>();
- final String consistentId;
- if (fillWalBeforeTest) {
- final Ignite ignite0 = startGrid("node0");
-
- ignite0.active(true);
-
- final IgniteCache<Object, Object> entries = txPutDummyRecords(ignite0, cntEntries, txCnt);
+ final Ignite ignite0 = startGrid("node0");
- for (Cache.Entry<Object, Object> next : entries) {
- ctrlMap.put(next.getKey(), next.getValue());
- }
+ ignite0.active(true);
- consistentId = U.maskForFileName(ignite0.cluster().localNode().consistentId().toString());
+ final IgniteCache<Object, Object> entries = txPutDummyRecords(ignite0, cntEntries, txCnt);
- stopGrid("node0");
+ final Map<Object, Object> ctrlMap = new HashMap<>();
+ for (Cache.Entry<Object, Object> next : entries) {
+ ctrlMap.put(next.getKey(), next.getValue());
}
- else
- consistentId = "127_0_0_1_47500";
+
+ final String subfolderName = genDbSubfolderName(ignite0, 0);
+ stopGrid("node0");
final String workDir = U.defaultWorkDirectory();
final File binaryMeta = U.resolveWorkDirectory(workDir, "binary_meta", false);
- final File binaryMetaWithConsId = new File(binaryMeta, consistentId);
+ final File binaryMetaWithConsId = new File(binaryMeta, subfolderName);
final File marshallerMapping = U.resolveWorkDirectory(workDir, "marshaller", false);
final IgniteWalIteratorFactory factory = new IgniteWalIteratorFactory(log,
@@ -474,17 +464,28 @@ public class IgniteWalReaderTest extends GridCommonAbstractTest {
}
}
};
- scanIterateAndCount(factory, workDir, consistentId, cntEntries, txCnt, objConsumer, null);
+ scanIterateAndCount(factory, workDir, subfolderName, cntEntries, txCnt, objConsumer, null);
assert ctrlMap.isEmpty() : " Control Map is not empty after reading entries " + ctrlMap;
}
/**
+ * Generates DB subfolder name for provided node index (local) and UUID (consistent ID)
+ *
+ * @param ignite ignite instance.
+ * @param nodeIdx node index.
+ * @return folder file name
+ */
+ @NotNull private String genDbSubfolderName(Ignite ignite, int nodeIdx) {
+ return genNewStyleSubfolderName(nodeIdx, (UUID)ignite.cluster().localNode().consistentId());
+ }
+
+ /**
* Scan WAL and WAL archive for logical records and its entries.
*
* @param factory WAL iterator factory.
* @param workDir Ignite work directory.
- * @param consistentId consistent ID.
+ * @param subfolderName DB subfolder name based on consistent ID.
* @param expCntEntries minimum expected entries count to find.
* @param expTxCnt minimum expected transaction count to find.
* @param objConsumer object handler, called for each object found in logical data records.
@@ -494,7 +495,7 @@ public class IgniteWalReaderTest extends GridCommonAbstractTest {
private void scanIterateAndCount(
final IgniteWalIteratorFactory factory,
final String workDir,
- final String consistentId,
+ final String subfolderName,
final int expCntEntries,
final int expTxCnt,
@Nullable final BiConsumer<Object, Object> objConsumer,
@@ -504,11 +505,10 @@ public class IgniteWalReaderTest extends GridCommonAbstractTest {
final File wal = new File(db, "wal");
final File walArchive = new File(wal, "archive");
- final File walArchiveDirWithConsistentId = new File(walArchive, consistentId);
+ final File walArchiveDirWithConsistentId = new File(walArchive, subfolderName);
final File[] files = walArchiveDirWithConsistentId.listFiles(FileWriteAheadLogManager.WAL_SEGMENT_FILE_FILTER);
-
- assert files != null : "Can't iterate over files [" + walArchiveDirWithConsistentId + "] Directory is N/A";
+ A.notNull(files, "Can't iterate over files [" + walArchiveDirWithConsistentId + "] Directory is N/A");
final WALIterator iter = factory.iteratorArchiveFiles(files);
final Map<GridCacheVersion, Integer> cntArch = iterateAndCountDataRecord(iter, objConsumer, dataRecordHnd);
@@ -520,8 +520,8 @@ public class IgniteWalReaderTest extends GridCommonAbstractTest {
log.info("Total tx found loaded using archive directory (file-by-file): " + txCntObservedArch);
- final File walWorkDirWithConsistentId = new File(wal, consistentId);
- final File[] workFiles = walWorkDirWithConsistentId.listFiles(FileWriteAheadLogManager.WAL_SEGMENT_FILE_FILTER);
+ final File walWorkDirWithNodeSubDir = new File(wal, subfolderName);
+ final File[] workFiles = walWorkDirWithNodeSubDir.listFiles(FileWriteAheadLogManager.WAL_SEGMENT_FILE_FILTER);
final WALIterator tuples = factory.iteratorWorkFiles(workFiles);
final Map<GridCacheVersion, Integer> cntWork = iterateAndCountDataRecord(tuples, objConsumer, dataRecordHnd);
@@ -541,71 +541,66 @@ public class IgniteWalReaderTest extends GridCommonAbstractTest {
*/
public void testFillWalWithDifferentTypes() throws Exception {
int cntEntries = 0;
- final String consistentId;
final Map<Object, Object> ctrlMap = new HashMap<>();
final Map<Object, Object> ctrlMapForBinaryObjects = new HashMap<>();
final Collection<String> ctrlStringsToSearch = new HashSet<>();
final Collection<String> ctrlStringsForBinaryObjSearch = new HashSet<>();
- if (fillWalBeforeTest) {
- final Ignite ignite0 = startGrid("node0");
- ignite0.active(true);
-
- final IgniteCache<Object, Object> addlCache = ignite0.getOrCreateCache(CACHE_ADDL_NAME);
- addlCache.put("1", "2");
- addlCache.put(1, 2);
- addlCache.put(1L, 2L);
- addlCache.put(TestEnum.A, "Enum_As_Key");
- addlCache.put("Enum_As_Value", TestEnum.B);
- addlCache.put(TestEnum.C, TestEnum.C);
-
- addlCache.put("Serializable", new TestSerializable(42));
- addlCache.put(new TestSerializable(42), "Serializable_As_Key");
- addlCache.put("Externalizable", new TestExternalizable(42));
- addlCache.put(new TestExternalizable(42), "Externalizable_As_Key");
- addlCache.put(292, new IndexedObject(292));
-
- final String search1 = "SomeUnexpectedStringValueAsKeyToSearch";
- ctrlStringsToSearch.add(search1);
- ctrlStringsForBinaryObjSearch.add(search1);
- addlCache.put(search1, "SearchKey");
-
- String search2 = "SomeTestStringContainerToBePrintedLongLine";
- final TestStringContainerToBePrinted val = new TestStringContainerToBePrinted(search2);
- ctrlStringsToSearch.add(val.toString()); //will validate original toString() was called
- ctrlStringsForBinaryObjSearch.add(search2);
- addlCache.put("SearchValue", val);
-
- String search3 = "SomeTestStringContainerToBePrintedLongLine2";
- final TestStringContainerToBePrinted key = new TestStringContainerToBePrinted(search3);
- ctrlStringsToSearch.add(key.toString()); //will validate original toString() was called
- ctrlStringsForBinaryObjSearch.add(search3); //validate only string itself
- addlCache.put(key, "SearchKey");
-
- cntEntries = addlCache.size();
- for (Cache.Entry<Object, Object> next : addlCache) {
- ctrlMap.put(next.getKey(), next.getValue());
- }
+ final Ignite ignite0 = startGrid("node0");
+ ignite0.active(true);
+
+ final IgniteCache<Object, Object> addlCache = ignite0.getOrCreateCache(CACHE_ADDL_NAME);
+ addlCache.put("1", "2");
+ addlCache.put(1, 2);
+ addlCache.put(1L, 2L);
+ addlCache.put(TestEnum.A, "Enum_As_Key");
+ addlCache.put("Enum_As_Value", TestEnum.B);
+ addlCache.put(TestEnum.C, TestEnum.C);
+
+ addlCache.put("Serializable", new TestSerializable(42));
+ addlCache.put(new TestSerializable(42), "Serializable_As_Key");
+ addlCache.put("Externalizable", new TestExternalizable(42));
+ addlCache.put(new TestExternalizable(42), "Externalizable_As_Key");
+ addlCache.put(292, new IndexedObject(292));
+
+ final String search1 = "SomeUnexpectedStringValueAsKeyToSearch";
+ ctrlStringsToSearch.add(search1);
+ ctrlStringsForBinaryObjSearch.add(search1);
+ addlCache.put(search1, "SearchKey");
+
+ String search2 = "SomeTestStringContainerToBePrintedLongLine";
+ final TestStringContainerToBePrinted val = new TestStringContainerToBePrinted(search2);
+ ctrlStringsToSearch.add(val.toString()); //will validate original toString() was called
+ ctrlStringsForBinaryObjSearch.add(search2);
+ addlCache.put("SearchValue", val);
+
+ String search3 = "SomeTestStringContainerToBePrintedLongLine2";
+ final TestStringContainerToBePrinted key = new TestStringContainerToBePrinted(search3);
+ ctrlStringsToSearch.add(key.toString()); //will validate original toString() was called
+ ctrlStringsForBinaryObjSearch.add(search3); //validate only string itself
+ addlCache.put(key, "SearchKey");
+
+ cntEntries = addlCache.size();
+ for (Cache.Entry<Object, Object> next : addlCache) {
+ ctrlMap.put(next.getKey(), next.getValue());
+ }
for (Cache.Entry<Object, Object> next : addlCache) {
ctrlMapForBinaryObjects.put(next.getKey(), next.getValue());
}
- consistentId = U.maskForFileName(ignite0.cluster().localNode().consistentId().toString());
+ final String subfolderName = genDbSubfolderName(ignite0, 0);
- stopGrid("node0");
- }
- else
- consistentId = "127_0_0_1_47500";
+ stopGrid("node0");
final String workDir = U.defaultWorkDirectory();
final File binaryMeta = U.resolveWorkDirectory(workDir, "binary_meta", false);
- final File binaryMetaWithConsId = new File(binaryMeta, consistentId);
+ final File binaryMetaWithNodeSubfolder = new File(binaryMeta, subfolderName);
final File marshallerMapping = U.resolveWorkDirectory(workDir, "marshaller", false);
final IgniteWalIteratorFactory factory = new IgniteWalIteratorFactory(log, PAGE_SIZE,
- binaryMetaWithConsId,
+ binaryMetaWithNodeSubfolder,
marshallerMapping);
final BiConsumer<Object, Object> objConsumer = new BiConsumer<Object, Object>() {
@Override public void accept(Object key, Object val) {
@@ -634,7 +629,7 @@ public class IgniteWalReaderTest extends GridCommonAbstractTest {
}
}
};
- scanIterateAndCount(factory, workDir, consistentId, cntEntries, 0, objConsumer, toStrChecker);
+ scanIterateAndCount(factory, workDir, subfolderName, cntEntries, 0, objConsumer, toStrChecker);
assert ctrlMap.isEmpty() : " Control Map is not empty after reading entries: " + ctrlMap;
assert ctrlStringsToSearch.isEmpty() : " Control Map for strings in entries is not empty after" +
@@ -642,7 +637,7 @@ public class IgniteWalReaderTest extends GridCommonAbstractTest {
//Validate same WAL log with flag binary objects only
final IgniteWalIteratorFactory keepBinFactory = new IgniteWalIteratorFactory(log, PAGE_SIZE,
- binaryMetaWithConsId,
+ binaryMetaWithNodeSubfolder,
marshallerMapping,
true);
final BiConsumer<Object, Object> binObjConsumer = new BiConsumer<Object, Object>() {
@@ -693,7 +688,7 @@ public class IgniteWalReaderTest extends GridCommonAbstractTest {
}
};
- final Consumer<DataRecord> binObjToStringChecker = new Consumer<DataRecord>() {
+ final Consumer<DataRecord> binObjToStrChecker = new Consumer<DataRecord>() {
@Override public void accept(DataRecord record) {
String strRepresentation = record.toString();
for (Iterator<String> iter = ctrlStringsForBinaryObjSearch.iterator(); iter.hasNext(); ) {
@@ -705,7 +700,7 @@ public class IgniteWalReaderTest extends GridCommonAbstractTest {
}
}
};
- scanIterateAndCount(keepBinFactory, workDir, consistentId, cntEntries, 0, binObjConsumer, binObjToStringChecker);
+ scanIterateAndCount(keepBinFactory, workDir, subfolderName, cntEntries, 0, binObjConsumer, binObjToStrChecker);
assert ctrlMapForBinaryObjects.isEmpty() : " Control Map is not empty after reading entries: " + ctrlMapForBinaryObjects;
assert ctrlStringsForBinaryObjSearch.isEmpty() : " Control Map for strings in entries is not empty after" +
http://git-wip-us.apache.org/repos/asf/ignite/blob/62f3c4c5/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/reader/MockWalIteratorFactory.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/reader/MockWalIteratorFactory.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/reader/MockWalIteratorFactory.java
index 4030e53..05636eb 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/reader/MockWalIteratorFactory.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/reader/MockWalIteratorFactory.java
@@ -18,6 +18,7 @@
package org.apache.ignite.internal.processors.cache.persistence.db.wal.reader;
import java.io.File;
+import java.io.Serializable;
import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.IgniteLogger;
import org.apache.ignite.configuration.IgniteConfiguration;
@@ -29,6 +30,8 @@ import org.apache.ignite.internal.pagemem.wal.WALIterator;
import org.apache.ignite.internal.processors.cache.GridCacheSharedContext;
import org.apache.ignite.internal.processors.cache.persistence.GridCacheDatabaseSharedManager;
import org.apache.ignite.internal.processors.cache.persistence.file.FileIOFactory;
+import org.apache.ignite.internal.processors.cache.persistence.filename.PdsFoldersResolver;
+import org.apache.ignite.internal.processors.cache.persistence.filename.PdsFolderSettings;
import org.apache.ignite.internal.processors.cache.persistence.wal.FileWriteAheadLogManager;
import org.jetbrains.annotations.Nullable;
import org.mockito.Mockito;
@@ -47,25 +50,34 @@ public class MockWalIteratorFactory {
private final int pageSize;
/** Consistent node id. */
- private final String consistentId;
+ private final Serializable consistentId;
+
+ /** DB storage subfolder based node index and consistent node ID. */
+ private String subfolderName;
/** Segments count in work dir. */
private int segments;
+
/**
* Creates factory
* @param log Logger.
* @param pageSize Page size.
* @param consistentId Consistent id.
+ * @param subfolderName
* @param segments Segments.
*/
- public MockWalIteratorFactory(@Nullable IgniteLogger log, int pageSize, String consistentId, int segments) {
+ public MockWalIteratorFactory(@Nullable IgniteLogger log,
+ int pageSize,
+ Serializable consistentId,
+ String subfolderName,
+ int segments) {
this.log = log == null ? Mockito.mock(IgniteLogger.class) : log;
this.pageSize = pageSize;
this.consistentId = consistentId;
+ this.subfolderName = subfolderName;
this.segments = segments;
}
-
/**
* Creates iterator
* @param wal WAL directory without node consistent id
@@ -93,10 +105,13 @@ public class MockWalIteratorFactory {
when(ctx.config()).thenReturn(cfg);
when(ctx.clientNode()).thenReturn(false);
+ when(ctx.pdsFolderResolver()).thenReturn(new PdsFoldersResolver() {
+ @Override public PdsFolderSettings resolveFolders() {
+ return new PdsFolderSettings(new File("."), subfolderName, consistentId, null, false);
+ }
+ });
final GridDiscoveryManager disco = Mockito.mock(GridDiscoveryManager.class);
-
- when(disco.consistentId()).thenReturn(consistentId);
when(ctx.discovery()).thenReturn(disco);
final IgniteWriteAheadLogManager mgr = new FileWriteAheadLogManager(ctx);
http://git-wip-us.apache.org/repos/asf/ignite/blob/62f3c4c5/modules/core/src/test/java/org/apache/ignite/testsuites/IgnitePdsTestSuite2.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgnitePdsTestSuite2.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgnitePdsTestSuite2.java
index 29f7255..d92d848 100644
--- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgnitePdsTestSuite2.java
+++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgnitePdsTestSuite2.java
@@ -29,6 +29,7 @@ import org.apache.ignite.internal.processors.cache.persistence.db.IgnitePdsPageE
import org.apache.ignite.internal.processors.cache.persistence.db.IgnitePdsRebalancingOnNotStableTopologyTest;
import org.apache.ignite.internal.processors.cache.persistence.db.IgnitePdsTransactionsHangTest;
import org.apache.ignite.internal.processors.cache.persistence.db.IgnitePdsWholeClusterRestartTest;
+import org.apache.ignite.internal.processors.cache.persistence.db.filename.IgniteUidAsConsistentIdMigrationTest;
import org.apache.ignite.internal.processors.cache.persistence.db.wal.IgniteWalFlushFailoverTest;
import org.apache.ignite.internal.processors.cache.persistence.db.wal.IgniteWalHistoryReservationsTest;
import org.apache.ignite.internal.processors.cache.persistence.db.wal.IgniteWalSerializerVersionTest;
@@ -78,6 +79,9 @@ public class IgnitePdsTestSuite2 extends TestSuite {
suite.addTestSuite(IgnitePdsExchangeDuringCheckpointTest.class);
+ // new style folders with generated consistent ID test
+ suite.addTestSuite(IgniteUidAsConsistentIdMigrationTest.class);
+
suite.addTestSuite(IgniteWalSerializerVersionTest.class);
return suite;
[2/2] ignite git commit: IGNITE-6285 Enhance persistent store paths
handling - Fixes #2775.
Posted by ag...@apache.org.
IGNITE-6285 Enhance persistent store paths handling - Fixes #2775.
Signed-off-by: Alexey Goncharuk <al...@gmail.com>
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/62f3c4c5
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/62f3c4c5
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/62f3c4c5
Branch: refs/heads/master
Commit: 62f3c4c52f5aad82e51e93b7981e670090cddd4c
Parents: 855fe4b
Author: dpavlov <dp...@gridgain.com>
Authored: Wed Oct 4 09:46:16 2017 +0300
Committer: Alexey Goncharuk <al...@gmail.com>
Committed: Wed Oct 4 09:46:16 2017 +0300
----------------------------------------------------------------------
.../FoldersReuseCompatibilityTest.java | 224 ++++++
...itePersistenceCompatibilityAbstractTest.java | 3 +
.../IgniteCompatibilityBasicTestSuite.java | 3 +
.../apache/ignite/IgniteSystemProperties.java | 7 +
.../ignite/internal/GridKernalContext.java | 6 +
.../ignite/internal/GridKernalContextImpl.java | 17 +-
.../apache/ignite/internal/IgniteKernal.java | 4 +-
.../discovery/GridDiscoveryManager.java | 55 +-
.../cache/binary/BinaryMetadataFileStore.java | 6 +-
.../GridCacheDatabaseSharedManager.java | 91 ++-
.../IgniteCacheDatabaseSharedManager.java | 13 +-
.../persistence/file/FilePageStoreManager.java | 29 +-
.../filename/PdsConsistentIdProcessor.java | 568 +++++++++++++++
.../persistence/filename/PdsFolderSettings.java | 138 ++++
.../filename/PdsFoldersResolver.java | 33 +
.../wal/FileWriteAheadLogManager.java | 20 +-
.../wal/reader/StandaloneGridKernalContext.java | 32 +-
.../spi/discovery/tcp/TcpDiscoverySpi.java | 4 +-
.../tcp/internal/TcpDiscoveryNode.java | 15 +
.../IgniteUidAsConsistentIdMigrationTest.java | 712 +++++++++++++++++++
.../db/wal/IgniteWalRecoveryTest.java | 13 +-
.../db/wal/reader/IgniteWalReaderTest.java | 187 +++--
.../db/wal/reader/MockWalIteratorFactory.java | 25 +-
.../ignite/testsuites/IgnitePdsTestSuite2.java | 4 +
24 files changed, 1995 insertions(+), 214 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/62f3c4c5/modules/compatibility/src/test/java/org/apache/ignite/compatibility/persistence/FoldersReuseCompatibilityTest.java
----------------------------------------------------------------------
diff --git a/modules/compatibility/src/test/java/org/apache/ignite/compatibility/persistence/FoldersReuseCompatibilityTest.java b/modules/compatibility/src/test/java/org/apache/ignite/compatibility/persistence/FoldersReuseCompatibilityTest.java
new file mode 100644
index 0000000..1775013
--- /dev/null
+++ b/modules/compatibility/src/test/java/org/apache/ignite/compatibility/persistence/FoldersReuseCompatibilityTest.java
@@ -0,0 +1,224 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.compatibility.persistence;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Set;
+import java.util.TreeSet;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.configuration.MemoryConfiguration;
+import org.apache.ignite.configuration.MemoryPolicyConfiguration;
+import org.apache.ignite.configuration.PersistentStoreConfiguration;
+import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.internal.processors.cache.GridCacheAbstractFullApiSelfTest;
+import org.apache.ignite.internal.processors.cache.persistence.filename.PdsConsistentIdProcessor;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.lang.IgniteInClosure;
+import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
+import org.jetbrains.annotations.NotNull;
+
+import static org.apache.ignite.internal.processors.cache.persistence.filename.PdsConsistentIdProcessor.parseSubFolderName;
+
+/**
+ * Test for new and old style persistent storage folders generation and compatible startup of current ignite version
+ */
+public class FoldersReuseCompatibilityTest extends IgnitePersistenceCompatibilityAbstractTest {
+ /** Cache name for test. */
+ private static final String CACHE_NAME = "dummy";
+
+ /** Key to store in previous version of ignite */
+ private static final String KEY = "ObjectFromPast";
+
+ /** Value to store in previous version of ignite */
+ private static final String VAL = "ValueFromPast";
+
+ /** {@inheritDoc} */
+ @Override protected void afterTest() throws Exception {
+ // No-op. super.afterTest();
+ stopAllGrids();
+ }
+
+ /** {@inheritDoc} */
+ @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
+ final IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
+
+ configPersistence(cfg);
+
+ return cfg;
+ }
+
+ /**
+ * Test startup of current ignite version using DB storage folder from previous version of Ignite. Expected to start
+ * successfully with existing DB
+ *
+ * @throws Exception if failed.
+ */
+ public void testFoldersReuseCompatibility_2_2() throws Exception {
+ runFoldersReuse("2.2.0");
+ }
+
+ /**
+ * Test startup of current ignite version using DB storage folder from previous version of Ignite. Expected to start
+ * successfully with existing DB
+ *
+ * @throws Exception if failed.
+ */
+ public void testFoldersReuseCompatibility_2_1() throws Exception {
+ runFoldersReuse("2.1.0");
+ }
+
+ /**
+ * Test startup of current ignite version using DB storage folder from previous version of Ignite. Expected to start
+ * successfully with existing DB
+ *
+ * @param ver 3 digit Ignite version to check compatibility with
+ * @throws Exception if failed.
+ */
+ private void runFoldersReuse(String ver) throws Exception {
+ final IgniteEx grid = startGrid(1, ver, new ConfigurationClosure(), new PostStartupClosure());
+
+ grid.close();
+ stopAllGrids();
+
+ IgniteEx ignite = startGrid(0);
+
+ ignite.active(true);
+ ignite.getOrCreateCache("cache2createdForNewGrid").put("Object", "Value");
+ assertEquals(1, ignite.context().discovery().topologyVersion());
+
+ assertPdsDirsDefaultExist(U.maskForFileName(ignite.cluster().node().consistentId().toString()));
+
+ assertEquals(VAL, ignite.cache(CACHE_NAME).get(KEY));
+
+ assertNodeIndexesInFolder();// should not create any new style directories
+
+ stopAllGrids();
+ }
+
+ /** Started node test actions closure. */
+ private static class PostStartupClosure implements IgniteInClosure<Ignite> {
+ /** {@inheritDoc} */
+ @Override public void apply(Ignite ignite) {
+ ignite.active(true);
+ ignite.getOrCreateCache(CACHE_NAME).put(KEY, VAL);
+ }
+ }
+
+ /** Setup compatible node closure. */
+ private static class ConfigurationClosure implements IgniteInClosure<IgniteConfiguration> {
+ /** {@inheritDoc} */
+ @Override public void apply(IgniteConfiguration cfg) {
+ cfg.setLocalHost("127.0.0.1");
+ TcpDiscoverySpi disco = new TcpDiscoverySpi();
+ disco.setIpFinder(GridCacheAbstractFullApiSelfTest.LOCAL_IP_FINDER);
+
+ cfg.setDiscoverySpi(disco);
+
+ configPersistence(cfg);
+ }
+ }
+
+ /**
+ * Setup persistence for compatible and current version node.
+ *
+ * @param cfg ignite config to setup.
+ */
+ private static void configPersistence(IgniteConfiguration cfg) {
+ final PersistentStoreConfiguration psCfg = new PersistentStoreConfiguration();
+
+ cfg.setPersistentStoreConfiguration(psCfg);
+
+ final MemoryConfiguration memCfg = new MemoryConfiguration();
+ final MemoryPolicyConfiguration memPolCfg = new MemoryPolicyConfiguration();
+
+ memPolCfg.setMaxSize(32 * 1024 * 1024); // we don't need much memory for this test
+ memCfg.setMemoryPolicies(memPolCfg);
+ cfg.setMemoryConfiguration(memCfg);
+ }
+
+ /**
+ * @param indexes expected new style node indexes in folders
+ * @throws IgniteCheckedException if failed
+ */
+ private void assertNodeIndexesInFolder(Integer... indexes) throws IgniteCheckedException {
+ assertEquals(new TreeSet<>(Arrays.asList(indexes)), getAllNodeIndexesInFolder());
+ }
+
+ /**
+ * @return set of all indexes of nodes found in work folder
+ * @throws IgniteCheckedException if failed.
+ */
+ @NotNull private Set<Integer> getAllNodeIndexesInFolder() throws IgniteCheckedException {
+ final File curFolder = new File(U.defaultWorkDirectory(), PdsConsistentIdProcessor.DB_DEFAULT_FOLDER);
+ final Set<Integer> indexes = new TreeSet<>();
+ final File[] files = curFolder.listFiles(PdsConsistentIdProcessor.DB_SUBFOLDERS_NEW_STYLE_FILTER);
+
+ for (File file : files) {
+ final PdsConsistentIdProcessor.FolderCandidate uid
+ = parseSubFolderName(file, log);
+
+ if (uid != null)
+ indexes.add(uid.nodeIndex());
+ }
+
+ return indexes;
+ }
+
+ /**
+ * Checks existence of all storage-related directories
+ *
+ * @param subDirName sub directories name expected
+ * @throws IgniteCheckedException if IO error occur
+ */
+ private void assertPdsDirsDefaultExist(String subDirName) throws IgniteCheckedException {
+ assertDirectoryExist("binary_meta", subDirName);
+ assertDirectoryExist(PersistentStoreConfiguration.DFLT_WAL_STORE_PATH, subDirName);
+ assertDirectoryExist(PersistentStoreConfiguration.DFLT_WAL_ARCHIVE_PATH, subDirName);
+ assertDirectoryExist(PdsConsistentIdProcessor.DB_DEFAULT_FOLDER, subDirName);
+ }
+
+ /**
+ * Checks one folder existence
+ *
+ * @param subFolderNames subfolders array to touch
+ * @throws IgniteCheckedException if IO error occur
+ */
+ private void assertDirectoryExist(String... subFolderNames) throws IgniteCheckedException {
+ File curFolder = new File(U.defaultWorkDirectory());
+
+ for (String name : subFolderNames) {
+ curFolder = new File(curFolder, name);
+ }
+
+ final String path;
+ try {
+ path = curFolder.getCanonicalPath();
+ }
+ catch (IOException e) {
+ throw new IgniteCheckedException("Failed to convert path: [" + curFolder.getAbsolutePath() + "]", e);
+ }
+
+ assertTrue("Directory " + Arrays.asList(subFolderNames).toString()
+ + " is expected to exist [" + path + "]", curFolder.exists() && curFolder.isDirectory());
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/62f3c4c5/modules/compatibility/src/test/java/org/apache/ignite/compatibility/persistence/IgnitePersistenceCompatibilityAbstractTest.java
----------------------------------------------------------------------
diff --git a/modules/compatibility/src/test/java/org/apache/ignite/compatibility/persistence/IgnitePersistenceCompatibilityAbstractTest.java b/modules/compatibility/src/test/java/org/apache/ignite/compatibility/persistence/IgnitePersistenceCompatibilityAbstractTest.java
index d76b862..f39b6f6 100644
--- a/modules/compatibility/src/test/java/org/apache/ignite/compatibility/persistence/IgnitePersistenceCompatibilityAbstractTest.java
+++ b/modules/compatibility/src/test/java/org/apache/ignite/compatibility/persistence/IgnitePersistenceCompatibilityAbstractTest.java
@@ -45,6 +45,9 @@ public abstract class IgnitePersistenceCompatibilityAbstractTest extends IgniteC
@Override protected void afterTest() throws Exception {
super.afterTest();
+ //protection if test failed to finish, e.g. by error
+ stopAllGrids();
+
assert deleteDefaultDBWorkDirectory() : "Couldn't delete DB work directory.";
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/62f3c4c5/modules/compatibility/src/test/java/org/apache/ignite/compatibility/testsuites/IgniteCompatibilityBasicTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/compatibility/src/test/java/org/apache/ignite/compatibility/testsuites/IgniteCompatibilityBasicTestSuite.java b/modules/compatibility/src/test/java/org/apache/ignite/compatibility/testsuites/IgniteCompatibilityBasicTestSuite.java
index b54b396..351a0e7 100644
--- a/modules/compatibility/src/test/java/org/apache/ignite/compatibility/testsuites/IgniteCompatibilityBasicTestSuite.java
+++ b/modules/compatibility/src/test/java/org/apache/ignite/compatibility/testsuites/IgniteCompatibilityBasicTestSuite.java
@@ -19,6 +19,7 @@ package org.apache.ignite.compatibility.testsuites;
import junit.framework.TestSuite;
import org.apache.ignite.compatibility.persistence.DummyPersistenceCompatibilityTest;
+import org.apache.ignite.compatibility.persistence.FoldersReuseCompatibilityTest;
/**
* Compatibility tests basic test suite.
@@ -33,6 +34,8 @@ public class IgniteCompatibilityBasicTestSuite {
suite.addTestSuite(DummyPersistenceCompatibilityTest.class);
+ suite.addTestSuite(FoldersReuseCompatibilityTest.class);
+
return suite;
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/62f3c4c5/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java b/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java
index e1e72f7..d7b4de9 100644
--- a/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java
+++ b/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java
@@ -737,6 +737,13 @@ public final class IgniteSystemProperties {
public static final String IGNITE_WAL_SERIALIZER_VERSION = "IGNITE_WAL_SERIALIZER_VERSION";
/**
+ * When set to {@code true}, Data store folders are generated only by consistent id, and no consistent ID will be
+ * set based on existing data store folders. This option also enables compatible folder generation mode as it was
+ * before 2.3.
+ */
+ public static final String IGNITE_DATA_STORAGE_FOLDER_BY_CONSISTENT_ID = "IGNITE_DATA_STORAGE_FOLDER_BY_CONSISTENT_ID";
+
+ /**
* Enforces singleton.
*/
private IgniteSystemProperties() {
http://git-wip-us.apache.org/repos/asf/ignite/blob/62f3c4c5/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContext.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContext.java b/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContext.java
index 99c7cce..210b401 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContext.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContext.java
@@ -34,6 +34,7 @@ import org.apache.ignite.internal.managers.indexing.GridIndexingManager;
import org.apache.ignite.internal.managers.loadbalancer.GridLoadBalancerManager;
import org.apache.ignite.internal.processors.affinity.GridAffinityProcessor;
import org.apache.ignite.internal.processors.cache.GridCacheProcessor;
+import org.apache.ignite.internal.processors.cache.persistence.filename.PdsFoldersResolver;
import org.apache.ignite.internal.processors.cacheobject.IgniteCacheObjectProcessor;
import org.apache.ignite.internal.processors.closure.GridClosureProcessor;
import org.apache.ignite.internal.processors.cluster.ClusterProcessor;
@@ -643,4 +644,9 @@ public interface GridKernalContext extends Iterable<GridComponent> {
* @return Platform processor.
*/
public PlatformProcessor platform();
+
+ /**
+ * @return PDS mode folder name resolver, also generates consistent ID in case new folder naming is used
+ */
+ public PdsFoldersResolver pdsFolderResolver();
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/62f3c4c5/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContextImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContextImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContextImpl.java
index 07e5970..1f0292c 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContextImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContextImpl.java
@@ -49,6 +49,7 @@ import org.apache.ignite.internal.processors.affinity.GridAffinityProcessor;
import org.apache.ignite.internal.processors.cache.CacheConflictResolutionManager;
import org.apache.ignite.internal.processors.cache.GridCacheProcessor;
import org.apache.ignite.internal.processors.cache.binary.CacheObjectBinaryProcessorImpl;
+import org.apache.ignite.internal.processors.cache.persistence.filename.PdsFoldersResolver;
import org.apache.ignite.internal.processors.cacheobject.IgniteCacheObjectProcessor;
import org.apache.ignite.internal.processors.closure.GridClosureProcessor;
import org.apache.ignite.internal.processors.cluster.ClusterProcessor;
@@ -377,6 +378,9 @@ public class GridKernalContextImpl implements GridKernalContext, Externalizable
/** */
private volatile boolean disconnected;
+ /** PDS mode folder name resolver, also generates consistent ID in case new folder naming is used */
+ private PdsFoldersResolver pdsFolderRslvr;
+
/**
* No-arg constructor is required by externalization.
*/
@@ -536,7 +540,7 @@ public class GridKernalContextImpl implements GridKernalContext, Externalizable
else if (comp instanceof GridCacheProcessor)
cacheProc = (GridCacheProcessor)comp;
else if (comp instanceof GridClusterStateProcessor)
- stateProc =(GridClusterStateProcessor)comp;
+ stateProc = (GridClusterStateProcessor)comp;
else if (comp instanceof GridTaskSessionProcessor)
sesProc = (GridTaskSessionProcessor)comp;
else if (comp instanceof GridPortProcessor)
@@ -576,9 +580,11 @@ public class GridKernalContextImpl implements GridKernalContext, Externalizable
else if (comp instanceof PlatformProcessor)
platformProc = (PlatformProcessor)comp;
else if (comp instanceof PoolProcessor)
- poolProc = (PoolProcessor) comp;
+ poolProc = (PoolProcessor)comp;
else if (comp instanceof GridMarshallerMappingProcessor)
mappingProc = (GridMarshallerMappingProcessor)comp;
+ else if (comp instanceof PdsFoldersResolver)
+ pdsFolderRslvr = (PdsFoldersResolver)comp;
else if (!(comp instanceof DiscoveryNodeValidationProcessor
|| comp instanceof PlatformPluginProcessor))
assert (comp instanceof GridPluginComponent) : "Unknown manager class: " + comp.getClass();
@@ -1005,7 +1011,7 @@ public class GridKernalContextImpl implements GridKernalContext, Externalizable
}
/** {@inheritDoc} */
- public Map<String, ? extends ExecutorService> customExecutors() {
+ @Override public Map<String, ? extends ExecutorService> customExecutors() {
return customExecSvcs;
}
@@ -1069,6 +1075,11 @@ public class GridKernalContextImpl implements GridKernalContext, Externalizable
this.disconnected = disconnected;
}
+ /**{@inheritDoc}*/
+ @Override public PdsFoldersResolver pdsFolderResolver() {
+ return pdsFolderRslvr;
+ }
+
/** {@inheritDoc} */
@Override public String toString() {
return S.toString(GridKernalContextImpl.class, this);
http://git-wip-us.apache.org/repos/asf/ignite/blob/62f3c4c5/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java b/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
index f5d736a..759bf64 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
@@ -115,6 +115,7 @@ import org.apache.ignite.internal.processors.cache.IgniteCacheProxy;
import org.apache.ignite.internal.processors.cache.IgniteInternalCache;
import org.apache.ignite.internal.processors.cache.binary.CacheObjectBinaryProcessorImpl;
import org.apache.ignite.internal.processors.cache.persistence.MemoryPolicy;
+import org.apache.ignite.internal.processors.cache.persistence.filename.PdsConsistentIdProcessor;
import org.apache.ignite.internal.processors.cacheobject.IgniteCacheObjectProcessor;
import org.apache.ignite.internal.processors.closure.GridClosureProcessor;
import org.apache.ignite.internal.processors.cluster.ClusterProcessor;
@@ -930,13 +931,14 @@ public class IgniteKernal implements IgniteEx, IgniteMXBean, Externalizable {
// Assign discovery manager to context before other processors start so they
// are able to register custom event listener.
- GridManager discoMgr = new GridDiscoveryManager(ctx);
+ final GridManager discoMgr = new GridDiscoveryManager(ctx);
ctx.add(discoMgr, false);
// Start processors before discovery manager, so they will
// be able to start receiving messages once discovery completes.
try {
+ startProcessor(new PdsConsistentIdProcessor(ctx));
startProcessor(createComponent(DiscoveryNodeValidationProcessor.class, ctx));
startProcessor(new GridAffinityProcessor(ctx));
startProcessor(createComponent(GridSegmentationProcessor.class, ctx));
http://git-wip-us.apache.org/repos/asf/ignite/blob/62f3c4c5/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java
index 527399d..14485d2 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java
@@ -17,6 +17,7 @@
package org.apache.ignite.internal.managers.discovery;
+import java.io.Serializable;
import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
@@ -116,6 +117,7 @@ import org.apache.ignite.spi.discovery.DiscoverySpiListener;
import org.apache.ignite.spi.discovery.DiscoverySpiNodeAuthenticator;
import org.apache.ignite.spi.discovery.DiscoverySpiOrderSupport;
import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
+import org.apache.ignite.spi.discovery.tcp.internal.TcpDiscoveryNode;
import org.apache.ignite.thread.IgniteThread;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -281,12 +283,12 @@ public class GridDiscoveryManager extends GridManagerAdapter<DiscoverySpi> {
/** */
private final CountDownLatch startLatch = new CountDownLatch(1);
- /** */
- private Object consistentId;
-
/** Discovery spi registered flag. */
private boolean registeredDiscoSpi;
+ /** Local node compatibility consistent ID. */
+ private Serializable consistentId;
+
/** @param ctx Context. */
public GridDiscoveryManager(GridKernalContext ctx) {
super(ctx, ctx.config().getDiscoverySpi());
@@ -549,6 +551,13 @@ public class GridDiscoveryManager extends GridManagerAdapter<DiscoverySpi> {
@Override public void onLocalNodeInitialized(ClusterNode locNode) {
for (IgniteInClosure<ClusterNode> lsnr : locNodeInitLsnrs)
lsnr.apply(locNode);
+
+ if (locNode instanceof TcpDiscoveryNode) {
+ final TcpDiscoveryNode node = (TcpDiscoveryNode)locNode;
+
+ if (consistentId != null)
+ node.setConsistentId(consistentId);
+ }
}
@Override public void onDiscovery(
@@ -2017,22 +2026,42 @@ public class GridDiscoveryManager extends GridManagerAdapter<DiscoverySpi> {
/**
* @return Consistent ID.
+ * @deprecated Use PdsConsistentIdProcessor to get actual consistent ID
*/
- public Object consistentId() {
- if (consistentId == null) {
- try {
- inject();
- }
- catch (IgniteCheckedException e) {
- throw new IgniteException("Failed to init consistent ID.", e);
- }
+ @Deprecated
+ public Serializable consistentId() {
+ if (consistentId == null)
+ consistentId = getInjectedDiscoverySpi().consistentId();
+
+ return consistentId;
+ }
- consistentId = getSpi().consistentId();
+ /**
+ * Performs injection of discovery SPI if needed, then provides DiscoverySpi SPI.
+ * Manual injection is required because normal startup of SPI is done after processor started.
+ *
+ * @return Wrapped DiscoverySpi SPI.
+ */
+ private DiscoverySpi getInjectedDiscoverySpi() {
+ try {
+ inject();
+ }
+ catch (IgniteCheckedException e) {
+ throw new IgniteException("Failed to init consistent ID.", e);
}
+ return getSpi();
+ }
- return consistentId;
+ /**
+ * Sets TCP local node consistent ID. This setter is to be called before node init in SPI
+ *
+ * @param consistentId New value of consistent ID to be used in local node initialization
+ */
+ public void consistentId(final Serializable consistentId) {
+ this.consistentId = consistentId;
}
+
/** @return Topology version. */
public long topologyVersion() {
return topSnap.get().topVer.topologyVersion();
http://git-wip-us.apache.org/repos/asf/ignite/blob/62f3c4c5/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/BinaryMetadataFileStore.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/BinaryMetadataFileStore.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/BinaryMetadataFileStore.java
index 2d4114f..420cde5 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/BinaryMetadataFileStore.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/BinaryMetadataFileStore.java
@@ -34,7 +34,7 @@ import org.jetbrains.annotations.Nullable;
* which may lead to segmentation of nodes from cluster.
*/
class BinaryMetadataFileStore {
- /** */
+ /** Link to resolved binary metadata directory. Null for non persistent mode */
private File workDir;
/** */
@@ -68,14 +68,14 @@ class BinaryMetadataFileStore {
if (binaryMetadataFileStoreDir != null)
workDir = binaryMetadataFileStoreDir;
else {
- String consId = U.maskForFileName(ctx.discovery().consistentId().toString());
+ final String subFolder = ctx.pdsFolderResolver().resolveFolders().folderName();
workDir = new File(U.resolveWorkDirectory(
ctx.config().getWorkDirectory(),
"binary_meta",
false
),
- consId);
+ subFolder);
}
U.ensureDirectory(workDir, "directory for serialized binary metadata", log);
http://git-wip-us.apache.org/repos/asf/ignite/blob/62f3c4c5/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheDatabaseSharedManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheDatabaseSharedManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheDatabaseSharedManager.java
index 9f1ccb4..2d89942 100755
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheDatabaseSharedManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheDatabaseSharedManager.java
@@ -62,6 +62,7 @@ import org.apache.ignite.IgniteException;
import org.apache.ignite.IgniteLogger;
import org.apache.ignite.IgniteSystemProperties;
import org.apache.ignite.PersistenceMetrics;
+import org.apache.ignite.cluster.ClusterNode;
import org.apache.ignite.configuration.CheckpointWriteOrder;
import org.apache.ignite.configuration.DataPageEvictionMode;
import org.apache.ignite.configuration.IgniteConfiguration;
@@ -74,6 +75,7 @@ import org.apache.ignite.internal.GridKernalContext;
import org.apache.ignite.internal.IgniteInternalFuture;
import org.apache.ignite.internal.IgniteInterruptedCheckedException;
import org.apache.ignite.internal.NodeStoppingException;
+import org.apache.ignite.internal.managers.discovery.GridDiscoveryManager;
import org.apache.ignite.internal.mem.DirectMemoryProvider;
import org.apache.ignite.internal.pagemem.FullPageId;
import org.apache.ignite.internal.pagemem.PageIdUtils;
@@ -280,8 +282,11 @@ public class GridCacheDatabaseSharedManager extends IgniteCacheDatabaseSharedMan
/** */
private final ConcurrentMap<Integer, IgniteInternalFuture> idxRebuildFuts = new ConcurrentHashMap<>();
- /** Lock holder. */
- private FileLockHolder fileLockHolder;
+ /**
+ * Lock holder for compatible folders mode. Null if lock holder was created at start node. <br>
+ * In this case lock is held on PDS resover manager and it is not required to manage locking here
+ */
+ @Nullable private FileLockHolder fileLockHolder;
/** Lock wait time. */
private final long lockWaitTime;
@@ -367,7 +372,9 @@ public class GridCacheDatabaseSharedManager extends IgniteCacheDatabaseSharedMan
snapshotMgr = cctx.snapshot();
- if (!cctx.kernalContext().clientNode()) {
+ final GridKernalContext kernalCtx = cctx.kernalContext();
+
+ if (!kernalCtx.clientNode()) {
IgnitePageStoreManager store = cctx.pageStore();
assert store instanceof FilePageStoreManager : "Invalid page store manager was created: " + store;
@@ -379,7 +386,11 @@ public class GridCacheDatabaseSharedManager extends IgniteCacheDatabaseSharedMan
if (!U.mkdirs(cpDir))
throw new IgniteCheckedException("Could not create directory for checkpoint metadata: " + cpDir);
- fileLockHolder = new FileLockHolder(storeMgr.workDir().getPath(), cctx.kernalContext(), log);
+ final FileLockHolder preLocked = kernalCtx.pdsFolderResolver()
+ .resolveFolders()
+ .getLockedFileLockHolder();
+ if (preLocked == null)
+ fileLockHolder = new FileLockHolder(storeMgr.workDir().getPath(), kernalCtx, log);
persStoreMetrics.wal(cctx.wal());
}
@@ -488,8 +499,11 @@ public class GridCacheDatabaseSharedManager extends IgniteCacheDatabaseSharedMan
/* Must be here, because after deactivate we can invoke activate and file lock must be already configured */
stopping = false;
- if (!cctx.localNode().isClient())
- fileLockHolder = new FileLockHolder(storeMgr.workDir().getPath(), cctx.kernalContext(), log);
+ if (!cctx.localNode().isClient()) {
+ //we replace lock with new instance (only if we're responsible for locking folders)
+ if (fileLockHolder != null)
+ fileLockHolder = new FileLockHolder(storeMgr.workDir().getPath(), cctx.kernalContext(), log);
+ }
}
/**
@@ -592,20 +606,24 @@ public class GridCacheDatabaseSharedManager extends IgniteCacheDatabaseSharedMan
/** {@inheritDoc} */
@Override public void lock() throws IgniteCheckedException {
- if (log.isDebugEnabled())
- log.debug("Try to capture file lock [nodeId=" +
- cctx.localNodeId() + " path=" + fileLockHolder.lockPath() + "]");
+ if (fileLockHolder != null) {
+ if (log.isDebugEnabled())
+ log.debug("Try to capture file lock [nodeId=" +
+ cctx.localNodeId() + " path=" + fileLockHolder.lockPath() + "]");
- fileLockHolder.tryLock(lockWaitTime);
+ fileLockHolder.tryLock(lockWaitTime);
+ }
}
/** {@inheritDoc} */
@Override public void unLock() {
- if (log.isDebugEnabled())
- log.debug("Release file lock [nodeId=" +
- cctx.localNodeId() + " path=" + fileLockHolder.lockPath() + "]");
+ if (fileLockHolder != null) {
+ if (log.isDebugEnabled())
+ log.debug("Release file lock [nodeId=" +
+ cctx.localNodeId() + " path=" + fileLockHolder.lockPath() + "]");
- fileLockHolder.release();
+ fileLockHolder.release();
+ }
}
/** {@inheritDoc} */
@@ -628,7 +646,8 @@ public class GridCacheDatabaseSharedManager extends IgniteCacheDatabaseSharedMan
if (!cctx.kernalContext().clientNode()) {
unLock();
- fileLockHolder.close();
+ if (fileLockHolder != null)
+ fileLockHolder.close();
}
unRegistrateMetricsMBean();
@@ -875,7 +894,7 @@ public class GridCacheDatabaseSharedManager extends IgniteCacheDatabaseSharedMan
idxRebuildFuts.remove(cacheId, rebuildFut);
log().info("Finished indexes rebuilding for cache: [name=" + cacheCtx.config().getName()
- + ", grpName=" + cacheCtx.config().getGroupName());
+ + ", grpName=" + cacheCtx.config().getGroupName());
}
});
}
@@ -1189,7 +1208,6 @@ public class GridCacheDatabaseSharedManager extends IgniteCacheDatabaseSharedMan
/**
* For debugging only. TODO: remove.
- *
*/
public Map<T2<Integer, Integer>, T2<Long, WALPointer>> reservedForPreloading() {
return reservedForPreloading;
@@ -2310,7 +2328,6 @@ public class GridCacheDatabaseSharedManager extends IgniteCacheDatabaseSharedMan
cpRec.addCacheGroupState(grp.groupId(), state);
}
-
cpPagesTuple = beginAllCheckpoints();
hasPages = hasPageForWrite(cpPagesTuple.get1());
@@ -2400,7 +2417,8 @@ public class GridCacheDatabaseSharedManager extends IgniteCacheDatabaseSharedMan
}
/**
- * @return tuple with collections of FullPageIds obtained from each PageMemory and overall number of dirty pages.
+ * @return tuple with collections of FullPageIds obtained from each PageMemory and overall number of dirty
+ * pages.
*/
private IgniteBiTuple<Collection<GridMultiCollectionWrapper<FullPageId>>, Integer> beginAllCheckpoints() {
Collection<GridMultiCollectionWrapper<FullPageId>> res = new ArrayList(memoryPolicies().size());
@@ -2792,9 +2810,9 @@ public class GridCacheDatabaseSharedManager extends IgniteCacheDatabaseSharedMan
}
/**
- * Checkpoint history. Holds chronological ordered map with {@link GridCacheDatabaseSharedManager.CheckpointEntry CheckpointEntries}.
- * Data is loaded from corresponding checkpoint directory.
- * This directory holds files for checkpoint start and end.
+ * Checkpoint history. Holds chronological ordered map with {@link GridCacheDatabaseSharedManager.CheckpointEntry
+ * CheckpointEntries}. Data is loaded from corresponding checkpoint directory. This directory holds files for
+ * checkpoint start and end.
*/
@SuppressWarnings("PublicInnerClass")
public class CheckpointHistory {
@@ -3117,7 +3135,7 @@ public class GridCacheDatabaseSharedManager extends IgniteCacheDatabaseSharedMan
/**
*
*/
- private static class FileLockHolder {
+ public static class FileLockHolder implements AutoCloseable {
/** Lock file name. */
private static final String lockFileName = "lock";
@@ -3130,8 +3148,8 @@ public class GridCacheDatabaseSharedManager extends IgniteCacheDatabaseSharedMan
/** Lock. */
private FileLock lock;
- /** Id. */
- private GridKernalContext ctx;
+ /** Kernal context to generate Id of locked node in file. */
+ @NotNull private GridKernalContext ctx;
/** Logger. */
private IgniteLogger log;
@@ -3139,7 +3157,7 @@ public class GridCacheDatabaseSharedManager extends IgniteCacheDatabaseSharedMan
/**
* @param path Path.
*/
- private FileLockHolder(String path, GridKernalContext ctx, IgniteLogger log) {
+ public FileLockHolder(String path, @NotNull GridKernalContext ctx, IgniteLogger log) {
try {
file = Paths.get(path, lockFileName).toFile();
@@ -3168,7 +3186,14 @@ public class GridCacheDatabaseSharedManager extends IgniteCacheDatabaseSharedMan
sb.a("[").a(ctx.localNodeId().toString()).a("]");
//write ip addresses
- sb.a(ctx.discovery().localNode().addresses());
+ final GridDiscoveryManager discovery = ctx.discovery();
+
+ if (discovery != null) { //discovery may be not up and running
+ final ClusterNode node = discovery.localNode();
+
+ if (node != null)
+ sb.a(node.addresses());
+ }
//write ports
sb.a("[");
@@ -3264,17 +3289,13 @@ public class GridCacheDatabaseSharedManager extends IgniteCacheDatabaseSharedMan
return content;
}
- /**
- *
- */
- private void release() {
+ /** Releases file lock */
+ public void release() {
U.releaseQuiet(lock);
}
- /**
- *
- */
- private void close() {
+ /** Closes file channel */
+ public void close() {
U.closeQuiet(lockFile);
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/62f3c4c5/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IgniteCacheDatabaseSharedManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IgniteCacheDatabaseSharedManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IgniteCacheDatabaseSharedManager.java
index 6ea6eff..d7682f0 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IgniteCacheDatabaseSharedManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IgniteCacheDatabaseSharedManager.java
@@ -50,6 +50,7 @@ import org.apache.ignite.internal.processors.cache.persistence.evict.NoOpPageEvi
import org.apache.ignite.internal.processors.cache.persistence.evict.PageEvictionTracker;
import org.apache.ignite.internal.processors.cache.persistence.evict.Random2LruPageEvictionTracker;
import org.apache.ignite.internal.processors.cache.persistence.evict.RandomLruPageEvictionTracker;
+import org.apache.ignite.internal.processors.cache.persistence.filename.PdsFolderSettings;
import org.apache.ignite.internal.processors.cache.persistence.freelist.FreeList;
import org.apache.ignite.internal.processors.cache.persistence.freelist.FreeListImpl;
import org.apache.ignite.internal.processors.cache.persistence.tree.reuse.ReuseList;
@@ -939,17 +940,21 @@ public class IgniteCacheDatabaseSharedManager extends GridCacheSharedManagerAdap
*
* @throws IgniteCheckedException If resolving swap directory fails.
*/
- @Nullable protected File buildAllocPath(MemoryPolicyConfiguration plc) throws IgniteCheckedException {
+ @Nullable private File buildAllocPath(MemoryPolicyConfiguration plc) throws IgniteCheckedException {
String path = plc.getSwapFilePath();
if (path == null)
return null;
- String consId = String.valueOf(cctx.discovery().consistentId());
+ final PdsFolderSettings folderSettings = cctx.kernalContext().pdsFolderResolver().resolveFolders();
+ final String folderName;
- consId = consId.replaceAll("[:,\\.]", "_");
+ if(folderSettings.isCompatible())
+ folderName = String.valueOf(folderSettings.consistentId()).replaceAll("[:,\\.]", "_");
+ else
+ folderName = folderSettings.folderName();
- return buildPath(path, consId);
+ return buildPath(path, folderName);
}
/**
http://git-wip-us.apache.org/repos/asf/ignite/blob/62f3c4c5/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FilePageStoreManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FilePageStoreManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FilePageStoreManager.java
index a20bda1..ed82127 100755
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FilePageStoreManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FilePageStoreManager.java
@@ -47,6 +47,7 @@ import org.apache.ignite.internal.processors.cache.CacheGroupContext;
import org.apache.ignite.internal.processors.cache.CacheGroupDescriptor;
import org.apache.ignite.internal.processors.cache.GridCacheSharedManagerAdapter;
import org.apache.ignite.internal.processors.cache.StoredCacheData;
+import org.apache.ignite.internal.processors.cache.persistence.filename.PdsFolderSettings;
import org.apache.ignite.internal.processors.cache.persistence.snapshot.IgniteCacheSnapshotManager;
import org.apache.ignite.internal.util.typedef.internal.U;
import org.apache.ignite.marshaller.Marshaller;
@@ -93,7 +94,7 @@ public class FilePageStoreManager extends GridCacheSharedManagerAdapter implemen
/** */
private PersistentStoreConfiguration pstCfg;
- /** Absolute directory for file page store */
+ /** Absolute directory for file page store. Includes consistent id based folder. */
private File storeWorkDir;
/** */
@@ -117,29 +118,13 @@ public class FilePageStoreManager extends GridCacheSharedManagerAdapter implemen
/** {@inheritDoc} */
@Override public void start0() throws IgniteCheckedException {
- if (cctx.kernalContext().clientNode())
+ final GridKernalContext ctx = cctx.kernalContext();
+ if (ctx.clientNode())
return;
- String consId = U.maskForFileName(cctx.kernalContext().discovery().consistentId().toString());
-
- if (pstCfg.getPersistentStorePath() != null) {
- File workDir0 = new File(pstCfg.getPersistentStorePath());
-
- if (!workDir0.isAbsolute())
- workDir0 = U.resolveWorkDirectory(
- igniteCfg.getWorkDirectory(),
- pstCfg.getPersistentStorePath(),
- false
- );
+ final PdsFolderSettings folderSettings = ctx.pdsFolderResolver().resolveFolders();
- storeWorkDir = new File(workDir0, consId);
- }
- else
- storeWorkDir = new File(U.resolveWorkDirectory(
- igniteCfg.getWorkDirectory(),
- DFLT_STORE_DIR,
- false
- ), consId);
+ storeWorkDir = new File(folderSettings.persistentStoreRootPath(), folderSettings.folderName());
U.ensureDirectory(storeWorkDir, "page store work directory", log);
}
@@ -551,7 +536,7 @@ public class FilePageStoreManager extends GridCacheSharedManagerAdapter implemen
}
/**
- * @return Store work dir.
+ * @return Store work dir. Includes consistent-id based folder
*/
public File workDir() {
return storeWorkDir;
http://git-wip-us.apache.org/repos/asf/ignite/blob/62f3c4c5/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/filename/PdsConsistentIdProcessor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/filename/PdsConsistentIdProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/filename/PdsConsistentIdProcessor.java
new file mode 100644
index 0000000..c73a952
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/filename/PdsConsistentIdProcessor.java
@@ -0,0 +1,568 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.cache.persistence.filename;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.io.IOException;
+import java.io.Serializable;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.UUID;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.IgniteLogger;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.configuration.PersistentStoreConfiguration;
+import org.apache.ignite.internal.GridKernalContext;
+import org.apache.ignite.internal.processors.GridProcessorAdapter;
+import org.apache.ignite.internal.processors.cache.persistence.GridCacheDatabaseSharedManager;
+import org.apache.ignite.internal.util.typedef.internal.A;
+import org.apache.ignite.internal.util.typedef.internal.SB;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import static org.apache.ignite.IgniteSystemProperties.IGNITE_DATA_STORAGE_FOLDER_BY_CONSISTENT_ID;
+import static org.apache.ignite.IgniteSystemProperties.getBoolean;
+
+/**
+ * Component for resolving PDS storage file names, also used for generating consistent ID for case PDS mode is enabled
+ */
+public class PdsConsistentIdProcessor extends GridProcessorAdapter implements PdsFoldersResolver {
+ /** Database subfolders constant prefix. */
+ private static final String DB_FOLDER_PREFIX = "node";
+
+ /** Node index and uid separator in subfolders name. */
+ private static final String NODEIDX_UID_SEPARATOR = "-";
+
+ /** Constant node subfolder prefix and node index pattern (nodeII, where II - node index as decimal integer) */
+ private static final String NODE_PATTERN = DB_FOLDER_PREFIX + "[0-9]*" + NODEIDX_UID_SEPARATOR;
+
+ /** Uuid as string pattern. */
+ private static final String UUID_STR_PATTERN = "[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}";
+
+ /**
+ * Subdir (nodeII-UID, where II - node index as decimal integer, UID - string representation of consistent ID)
+ * pattern.
+ */
+ private static final String SUBDIR_PATTERN = NODE_PATTERN + UUID_STR_PATTERN;
+
+ /** Database subfolders for new style filter. */
+ public static final FileFilter DB_SUBFOLDERS_NEW_STYLE_FILTER = new FileFilter() {
+ @Override public boolean accept(File pathname) {
+ return pathname.isDirectory() && pathname.getName().matches(SUBDIR_PATTERN);
+ }
+ };
+
+ /** Database subfolders for old style filter. */
+ private static final FileFilter DB_SUBFOLDERS_OLD_STYLE_FILTER = new FileFilter() {
+ @Override public boolean accept(File pathname) {
+ return pathname.isDirectory()
+ && !"wal".equals(pathname.getName())
+ && !pathname.getName().matches(SUBDIR_PATTERN);
+ }
+ };
+
+ /** Database default folder. */
+ public static final String DB_DEFAULT_FOLDER = "db";
+
+ /** Config. */
+ private IgniteConfiguration cfg;
+
+ /** Logger. */
+ private IgniteLogger log;
+
+ /** Context. */
+ private GridKernalContext ctx;
+
+ /** Cached folder settings. */
+ private PdsFolderSettings settings;
+
+ /**
+ * Creates folders resolver
+ *
+ * @param ctx Context.
+ */
+ public PdsConsistentIdProcessor(final GridKernalContext ctx) {
+ super(ctx);
+
+ this.cfg = ctx.config();
+ this.log = ctx.log(PdsFoldersResolver.class);
+ this.ctx = ctx;
+ }
+
+ /**
+ * Prepares compatible PDS folder settings. No locking is performed, consistent ID is not overridden.
+ *
+ * @param pstStoreBasePath DB storage base path or null if persistence is not enabled.
+ * @param consistentId compatibility consistent ID
+ * @return PDS folder settings compatible with previous versions.
+ */
+ private PdsFolderSettings compatibleResolve(
+ @Nullable final File pstStoreBasePath,
+ @NotNull final Serializable consistentId) {
+
+ if (cfg.getConsistentId() != null) {
+ // compatible mode from configuration is used fot this case, no locking, no consitent id change
+ return new PdsFolderSettings(pstStoreBasePath, cfg.getConsistentId());
+ }
+
+ return new PdsFolderSettings(pstStoreBasePath, consistentId);
+ }
+
+ /** {@inheritDoc} */
+ @Override public PdsFolderSettings resolveFolders() throws IgniteCheckedException {
+ if (settings == null) {
+ settings = prepareNewSettings();
+
+ if (!settings.isCompatible()) {
+ if (log.isInfoEnabled())
+ log.info("Consistent ID used for local node is [" + settings.consistentId() + "] " +
+ "according to persistence data storage folders");
+
+ ctx.discovery().consistentId(settings.consistentId());
+ }
+ }
+ return settings;
+ }
+
+ /**
+ * Creates new settings when we don't have cached one.
+ *
+ * @return new settings with prelocked directory (if appropriate).
+ * @throws IgniteCheckedException if IO failed.
+ */
+ private PdsFolderSettings prepareNewSettings() throws IgniteCheckedException {
+ final File pstStoreBasePath = resolvePersistentStoreBasePath();
+ //here deprecated method is used to get compatible version of consistentId
+ final Serializable consistentId = ctx.discovery().consistentId();
+
+ if (!cfg.isPersistentStoreEnabled())
+ return compatibleResolve(pstStoreBasePath, consistentId);
+
+ if (getBoolean(IGNITE_DATA_STORAGE_FOLDER_BY_CONSISTENT_ID, false))
+ return compatibleResolve(pstStoreBasePath, consistentId);
+
+ // compatible mode from configuration is used fot this case
+ if (cfg.getConsistentId() != null) {
+ // compatible mode from configuration is used fot this case, no locking, no consistent id change
+ return new PdsFolderSettings(pstStoreBasePath, cfg.getConsistentId());
+ }
+ // The node scans the work directory and checks if there is a folder matching the consistent ID.
+ // If such a folder exists, we start up with this ID (compatibility mode)
+ final String subFolder = U.maskForFileName(consistentId.toString());
+
+ final GridCacheDatabaseSharedManager.FileLockHolder oldStyleFolderLockHolder = tryLock(new File(pstStoreBasePath, subFolder));
+
+ if (oldStyleFolderLockHolder != null)
+ return new PdsFolderSettings(pstStoreBasePath,
+ subFolder,
+ consistentId,
+ oldStyleFolderLockHolder,
+ true);
+
+ final File[] oldStyleFolders = pstStoreBasePath.listFiles(DB_SUBFOLDERS_OLD_STYLE_FILTER);
+
+ if (oldStyleFolders != null && oldStyleFolders.length != 0) {
+ for (File folder : oldStyleFolders) {
+ final String path = getPathDisplayableInfo(folder);
+
+ U.warn(log, "There is other non-empty storage folder under storage base directory [" + path + "]");
+ }
+ }
+
+ for (FolderCandidate next : getNodeIndexSortedCandidates(pstStoreBasePath)) {
+ final GridCacheDatabaseSharedManager.FileLockHolder fileLockHolder = tryLock(next.subFolderFile());
+
+ if (fileLockHolder != null) {
+ if (log.isInfoEnabled())
+ log.info("Successfully locked persistence storage folder [" + next.subFolderFile() + "]");
+
+ return new PdsFolderSettings(pstStoreBasePath,
+ next.subFolderFile().getName(),
+ next.uuid(),
+ fileLockHolder,
+ false);
+ }
+ }
+
+ // was not able to find free slot, allocating new
+ final GridCacheDatabaseSharedManager.FileLockHolder rootDirLock = lockRootDirectory(pstStoreBasePath);
+
+ try {
+ final List<FolderCandidate> sortedCandidates = getNodeIndexSortedCandidates(pstStoreBasePath);
+ final int nodeIdx = sortedCandidates.isEmpty() ? 0 : (sortedCandidates.get(sortedCandidates.size() - 1).nodeIndex() + 1);
+
+ return generateAndLockNewDbStorage(pstStoreBasePath, nodeIdx);
+ }
+ finally {
+ rootDirLock.release();
+ rootDirLock.close();
+ }
+ }
+
+ /**
+ * Calculate overall folder size.
+ *
+ * @param dir directory to scan.
+ * @return total size in bytes.
+ */
+ private static FolderParams folderSize(File dir) {
+ final FolderParams params = new FolderParams();
+
+ visitFolder(dir, params);
+
+ return params;
+ }
+
+ /**
+ * Scans provided directory and its sub dirs, collects found metrics.
+ *
+ * @param dir directory to start scan from.
+ * @param params input/output.
+ */
+ private static void visitFolder(final File dir, final FolderParams params) {
+ for (File file : dir.listFiles()) {
+ if (file.isDirectory())
+ visitFolder(file, params);
+ else {
+ params.size += file.length();
+ params.lastModified = Math.max(params.lastModified, dir.lastModified());
+ }
+ }
+ }
+
+ /**
+ * @param folder folder to scan.
+ * @return folder displayable information.
+ */
+ @NotNull private String getPathDisplayableInfo(final File folder) {
+ final SB res = new SB();
+
+ res.a(getCanonicalPath(folder));
+ res.a(", ");
+ final FolderParams params = folderSize(folder);
+
+ res.a(params.size);
+ res.a(" bytes, modified ");
+ final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("MM/dd/yyyy hh:mm a");
+
+ res.a(simpleDateFormat.format(params.lastModified));
+ res.a(" ");
+
+ return res.toString();
+ }
+
+ /**
+ * Returns the canonical pathname string of this abstract pathname.
+ *
+ * @param file path to convert.
+ * @return canonical pathname or at leas absolute if convert to canonical failed.
+ */
+ @NotNull private String getCanonicalPath(final File file) {
+ try {
+ return file.getCanonicalPath();
+ }
+ catch (IOException ignored) {
+ return file.getAbsolutePath();
+ }
+ }
+
+ /**
+ * Pad start of string with provided character.
+ *
+ * @param str sting to pad.
+ * @param minLength expected length.
+ * @param padChar padding character.
+ * @return padded string.
+ */
+ private static String padStart(String str, int minLength, char padChar) {
+ A.notNull(str, "String should not be empty");
+ if (str.length() >= minLength)
+ return str;
+
+ final SB sb = new SB(minLength);
+
+ for (int i = str.length(); i < minLength; ++i)
+ sb.a(padChar);
+
+ sb.a(str);
+
+ return sb.toString();
+
+ }
+
+ /**
+ * Creates new DB storage folder.
+ *
+ * @param pstStoreBasePath DB root path.
+ * @param nodeIdx next node index to use in folder name.
+ * @return new settings to be used in this node.
+ * @throws IgniteCheckedException if failed.
+ */
+ @NotNull private PdsFolderSettings generateAndLockNewDbStorage(final File pstStoreBasePath,
+ final int nodeIdx) throws IgniteCheckedException {
+
+ final UUID uuid = UUID.randomUUID();
+ final String consIdBasedFolder = genNewStyleSubfolderName(nodeIdx, uuid);
+ final File newRandomFolder = U.resolveWorkDirectory(pstStoreBasePath.getAbsolutePath(), consIdBasedFolder, false); //mkdir here
+ final GridCacheDatabaseSharedManager.FileLockHolder fileLockHolder = tryLock(newRandomFolder);
+
+ if (fileLockHolder != null) {
+ if (log.isInfoEnabled())
+ log.info("Successfully created new persistent storage folder [" + newRandomFolder + "]");
+
+ return new PdsFolderSettings(pstStoreBasePath, consIdBasedFolder, uuid, fileLockHolder, false);
+ }
+ throw new IgniteCheckedException("Unable to lock file generated randomly [" + newRandomFolder + "]");
+ }
+
+ /**
+ * Generates DB subfolder name for provided node index (local) and UUID (consistent ID)
+ *
+ * @param nodeIdx node index.
+ * @param uuid consistent ID.
+ * @return folder file name
+ */
+ @NotNull public static String genNewStyleSubfolderName(final int nodeIdx, final UUID uuid) {
+ final String uuidAsStr = uuid.toString();
+
+ assert uuidAsStr.matches(UUID_STR_PATTERN);
+
+ final String nodeIdxPadded = padStart(Integer.toString(nodeIdx), 2, '0');
+
+ return DB_FOLDER_PREFIX + nodeIdxPadded + NODEIDX_UID_SEPARATOR + uuidAsStr;
+ }
+
+ /**
+ * Acquires lock to root storage directory, used to lock root directory in case creating new files is required.
+ *
+ * @param pstStoreBasePath rood DB dir to lock
+ * @return locked directory, should be released and closed later
+ * @throws IgniteCheckedException if failed
+ */
+ @NotNull private GridCacheDatabaseSharedManager.FileLockHolder lockRootDirectory(File pstStoreBasePath)
+ throws IgniteCheckedException {
+
+ GridCacheDatabaseSharedManager.FileLockHolder rootDirLock;
+ int retry = 0;
+
+ while ((rootDirLock = tryLock(pstStoreBasePath)) == null) {
+ if (retry > 600)
+ throw new IgniteCheckedException("Unable to start under DB storage path [" + pstStoreBasePath + "]" +
+ ". Lock is being held to root directory");
+ retry++;
+ }
+
+ return rootDirLock;
+ }
+
+ /**
+ * @param pstStoreBasePath root storage folder to scan.
+ * @return empty list if there is no files in folder to test. Non null value is returned for folder having
+ * applicable new style files. Collection is sorted ascending according to node ID, 0 node index is coming first.
+ */
+ @Nullable private List<FolderCandidate> getNodeIndexSortedCandidates(File pstStoreBasePath) {
+ final File[] files = pstStoreBasePath.listFiles(DB_SUBFOLDERS_NEW_STYLE_FILTER);
+
+ if (files == null)
+ return Collections.emptyList();
+
+ final List<FolderCandidate> res = new ArrayList<>();
+
+ for (File file : files) {
+ final FolderCandidate candidate = parseFileName(file);
+
+ if (candidate != null)
+ res.add(candidate);
+ }
+ Collections.sort(res, new Comparator<FolderCandidate>() {
+ @Override public int compare(FolderCandidate c1, FolderCandidate c2) {
+ return Integer.compare(c1.nodeIndex(), c2.nodeIndex());
+ }
+ });
+
+ return res;
+ }
+
+ /**
+ * Tries to lock subfolder within storage root folder.
+ *
+ * @param dbStoreDirWithSubdirectory DB store directory, is to be absolute and should include consistent ID based
+ * sub folder.
+ * @return non null holder if lock was successful, null in case lock failed. If directory does not exist method will
+ * always fail to lock.
+ */
+ private GridCacheDatabaseSharedManager.FileLockHolder tryLock(File dbStoreDirWithSubdirectory) {
+ if (!dbStoreDirWithSubdirectory.exists())
+ return null;
+
+ final String path = dbStoreDirWithSubdirectory.getAbsolutePath();
+ final GridCacheDatabaseSharedManager.FileLockHolder fileLockHolder
+ = new GridCacheDatabaseSharedManager.FileLockHolder(path, ctx, log);
+
+ try {
+ fileLockHolder.tryLock(1000);
+
+ return fileLockHolder;
+ }
+ catch (IgniteCheckedException e) {
+ U.closeQuiet(fileLockHolder);
+
+ if (log.isInfoEnabled())
+ log.info("Unable to acquire lock to file [" + path + "], reason: " + e.getMessage());
+
+ return null;
+ }
+ }
+
+ /**
+ * @return DB storage absolute root path resolved as 'db' folder in Ignite work dir (by default) or using persistent
+ * store configuration. Null if persistence is not enabled. Returned folder is created automatically.
+ * @throws IgniteCheckedException if I/O failed.
+ */
+ @Nullable private File resolvePersistentStoreBasePath() throws IgniteCheckedException {
+ final PersistentStoreConfiguration pstCfg = cfg.getPersistentStoreConfiguration();
+
+ if (pstCfg == null)
+ return null;
+
+ final String pstPath = pstCfg.getPersistentStorePath();
+
+ return U.resolveWorkDirectory(
+ cfg.getWorkDirectory(),
+ pstPath != null ? pstPath : DB_DEFAULT_FOLDER,
+ false
+ );
+
+ }
+
+ /**
+ * @param subFolderFile new style folder name to parse
+ * @return Pair of UUID and node index
+ */
+ private FolderCandidate parseFileName(@NotNull final File subFolderFile) {
+ return parseSubFolderName(subFolderFile, log);
+ }
+
+ /**
+ * @param subFolderFile new style file to parse.
+ * @param log Logger.
+ * @return Pair of UUID and node index.
+ */
+ @Nullable public static FolderCandidate parseSubFolderName(
+ @NotNull final File subFolderFile,
+ @NotNull final IgniteLogger log) {
+
+ final String fileName = subFolderFile.getName();
+ final Matcher matcher = Pattern.compile(NODE_PATTERN).matcher(fileName);
+ if (!matcher.find())
+ return null;
+
+ int uidStart = matcher.end();
+
+ try {
+ final String uid = fileName.substring(uidStart);
+ final UUID uuid = UUID.fromString(uid);
+ final String substring = fileName.substring(DB_FOLDER_PREFIX.length(), uidStart - NODEIDX_UID_SEPARATOR.length());
+ final int idx = Integer.parseInt(substring);
+
+ return new FolderCandidate(subFolderFile, idx, uuid);
+ }
+ catch (Exception e) {
+ U.warn(log, "Unable to parse new style file format from [" + subFolderFile.getAbsolutePath() + "]: " + e);
+
+ return null;
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public void stop(boolean cancel) throws IgniteCheckedException {
+ if (settings != null) {
+ final GridCacheDatabaseSharedManager.FileLockHolder fileLockHolder = settings.getLockedFileLockHolder();
+
+ if (fileLockHolder != null) {
+ fileLockHolder.release();
+ fileLockHolder.close();
+ }
+ }
+ super.stop(cancel);
+ }
+
+ /** Path metrics */
+ private static class FolderParams {
+ /** Overall size in bytes. */
+ private long size;
+
+ /** Last modified. */
+ private long lastModified;
+ }
+
+ /**
+ * Represents parsed new style file and encoded parameters in this file name
+ */
+ public static class FolderCandidate {
+ /** Absolute file path pointing to DB subfolder within DB storage root folder. */
+ private final File subFolderFile;
+
+ /** Node index (local, usually 0 if multiple nodes are not started at local PC). */
+ private final int nodeIdx;
+
+ /** Uuid contained in file name, is to be set as consistent ID. */
+ private final UUID uuid;
+
+ /**
+ * @param subFolderFile Absolute file path pointing to DB subfolder.
+ * @param nodeIdx Node index.
+ * @param uuid Uuid.
+ */
+ public FolderCandidate(File subFolderFile, int nodeIdx, UUID uuid) {
+ this.subFolderFile = subFolderFile;
+ this.nodeIdx = nodeIdx;
+ this.uuid = uuid;
+ }
+
+ /**
+ * @return Node index (local, usually 0 if multiple nodes are not started at local PC).
+ */
+ public int nodeIndex() {
+ return nodeIdx;
+ }
+
+ /**
+ * @return Uuid contained in file name, is to be set as consistent ID.
+ */
+ public Serializable uuid() {
+ return uuid;
+ }
+
+ /**
+ * @return Absolute file path pointing to DB subfolder within DB storage root folder.
+ */
+ public File subFolderFile() {
+ return subFolderFile;
+ }
+ }
+}
+
+
http://git-wip-us.apache.org/repos/asf/ignite/blob/62f3c4c5/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/filename/PdsFolderSettings.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/filename/PdsFolderSettings.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/filename/PdsFolderSettings.java
new file mode 100644
index 0000000..20fb5ca
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/filename/PdsFolderSettings.java
@@ -0,0 +1,138 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.cache.persistence.filename;
+
+import java.io.File;
+import java.io.Serializable;
+import org.apache.ignite.internal.processors.cache.persistence.GridCacheDatabaseSharedManager;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Class holds information required for folder generation for ignite persistent store
+ */
+public class PdsFolderSettings {
+ /**
+ * DB storage absolute root path resolved as 'db' folder in Ignite work dir (by default) or using persistent store
+ * configuration. <br>
+ * Note WAL storage may be configured outside this path.<br>
+ * This value may be null if persistence is not enabled.
+ */
+ @Nullable private final File persistentStoreRootPath;
+
+ /** Sub folder name containing consistent ID and optionally node index. */
+ private final String folderName;
+
+ /** Consistent id to be set to local node. */
+ private final Serializable consistentId;
+
+ /**
+ * File lock holder with prelocked db directory. For non compatible mode this holder contains prelocked work
+ * directory. This value is to be used at activate instead of locking. <br> May be null in case preconfigured
+ * consistent ID is used or in case lock holder was already taken by other processor.
+ */
+ @Nullable private final GridCacheDatabaseSharedManager.FileLockHolder fileLockHolder;
+
+ /**
+ * Indicates if compatible mode is enabled, in that case all sub folders are generated from consistent ID without
+ * 'node' and node index prefix. In compatible mode there is no overriding for consistent ID is done.
+ */
+ private final boolean compatible;
+
+ /**
+ * Creates settings in for new PST(DB) folder mode.
+ *
+ * @param persistentStoreRootPath Persistent store root path or null if non PDS mode.
+ * @param folderName Sub folder name containing consistent ID and optionally node index.
+ * @param consistentId Consistent id.
+ * @param fileLockHolder File lock holder with prelocked db directory.
+ * @param compatible Compatible mode flag.
+ */
+ public PdsFolderSettings(@Nullable final File persistentStoreRootPath,
+ final String folderName,
+ final Serializable consistentId,
+ @Nullable final GridCacheDatabaseSharedManager.FileLockHolder fileLockHolder,
+ final boolean compatible) {
+
+ this.consistentId = consistentId;
+ this.folderName = folderName;
+ this.fileLockHolder = fileLockHolder;
+ this.compatible = compatible;
+ this.persistentStoreRootPath = persistentStoreRootPath;
+ }
+
+ /**
+ * Creates settings for compatible mode. Folder name is consistent ID (masked), no node prefix is added.
+ *
+ * @param persistentStoreRootPath root DB path.
+ * @param consistentId node consistent ID.
+ */
+ public PdsFolderSettings(
+ @Nullable final File persistentStoreRootPath,
+ @NotNull final Serializable consistentId) {
+
+ this.consistentId = consistentId;
+ this.compatible = true;
+ this.folderName = U.maskForFileName(consistentId.toString());
+ this.persistentStoreRootPath = persistentStoreRootPath;
+ this.fileLockHolder = null;
+ }
+
+ /**
+ * @return sub folders name based on consistent ID. In compatible mode this is escaped consistent ID, in new mode
+ * this is UUID based folder name.
+ */
+ public String folderName() {
+ return folderName;
+ }
+
+ /**
+ * @return Consistent id to be set to local node.
+ */
+ public Serializable consistentId() {
+ return consistentId;
+ }
+
+ /**
+ * @return flag indicating if compatible mode is enabled for folder generation. In that case all sub folders names are
+ * generated from consistent ID without 'node' and node index prefix. In compatible mode there is no overriding for
+ * consistent ID is done for cluster node. Locking files is independent to compatibility mode.
+ */
+ public boolean isCompatible() {
+ return compatible;
+ }
+
+ /**
+ * Returns already locked file lock holder to lock file in {@link #persistentStoreRootPath}. Unlock and close this
+ * lock is not required.
+ *
+ * @return File lock holder with prelocked db directory.
+ */
+ @Nullable public GridCacheDatabaseSharedManager.FileLockHolder getLockedFileLockHolder() {
+ return fileLockHolder;
+ }
+
+ /**
+ * @return DB storage absolute root path resolved as 'db' folder in Ignite work dir (by default) or using persistent
+ * store configuration. Note WAL storage may be configured outside this path. May return null for non pds mode.
+ */
+ @Nullable public File persistentStoreRootPath() {
+ return persistentStoreRootPath;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/62f3c4c5/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/filename/PdsFoldersResolver.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/filename/PdsFoldersResolver.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/filename/PdsFoldersResolver.java
new file mode 100644
index 0000000..cefaa04
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/filename/PdsFoldersResolver.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.cache.persistence.filename;
+
+import org.apache.ignite.IgniteCheckedException;
+
+/**
+ * Resolves folders for PDS mode, may have side effect as setting random UUID as local node consistent ID.
+ */
+public interface PdsFoldersResolver {
+ /**
+ * Prepares and caches PDS folder settings. Subsequent call to this method will provide same settings.
+ *
+ * @return PDS folder settings, consistentID and prelocked DB file lock.
+ * @throws IgniteCheckedException if failed.
+ */
+ public PdsFolderSettings resolveFolders() throws IgniteCheckedException;
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/62f3c4c5/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/FileWriteAheadLogManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/FileWriteAheadLogManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/FileWriteAheadLogManager.java
index c8715aa..6a75dd2 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/FileWriteAheadLogManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/FileWriteAheadLogManager.java
@@ -64,6 +64,7 @@ import org.apache.ignite.internal.processors.cache.persistence.GridCacheDatabase
import org.apache.ignite.internal.processors.cache.persistence.PersistenceMetricsImpl;
import org.apache.ignite.internal.processors.cache.persistence.file.FileIO;
import org.apache.ignite.internal.processors.cache.persistence.file.FileIOFactory;
+import org.apache.ignite.internal.processors.cache.persistence.filename.PdsFolderSettings;
import org.apache.ignite.internal.processors.cache.persistence.wal.crc.PureJavaCrc32;
import org.apache.ignite.internal.processors.cache.persistence.wal.record.HeaderRecord;
import org.apache.ignite.internal.processors.cache.persistence.wal.serializer.RecordDataV1Serializer;
@@ -162,7 +163,7 @@ public class FileWriteAheadLogManager extends GridCacheSharedManagerAdapter impl
/** WAL archive directory (including consistent ID as subfolder) */
private File walArchiveDir;
- /** Serializer of latest version. */
+ /** Serializer of latest version, used to read header record and for write records */
private RecordSerializer serializer;
/** Serializer latest version to use. */
@@ -258,25 +259,21 @@ public class FileWriteAheadLogManager extends GridCacheSharedManagerAdapter impl
/** {@inheritDoc} */
@Override public void start0() throws IgniteCheckedException {
if (!cctx.kernalContext().clientNode()) {
- String consId = consistentId();
-
- A.notNullOrEmpty(consId, "consistentId");
-
- consId = U.maskForFileName(consId);
+ final PdsFolderSettings resolveFolders = cctx.kernalContext().pdsFolderResolver().resolveFolders();
checkWalConfiguration();
walWorkDir = initDirectory(
psCfg.getWalStorePath(),
PersistentStoreConfiguration.DFLT_WAL_STORE_PATH,
- consId,
+ resolveFolders.folderName(),
"write ahead log work directory"
);
walArchiveDir = initDirectory(
psCfg.getWalArchivePath(),
PersistentStoreConfiguration.DFLT_WAL_ARCHIVE_PATH,
- consId,
+ resolveFolders.folderName(),
"write ahead log archive directory"
);
@@ -317,13 +314,6 @@ public class FileWriteAheadLogManager extends GridCacheSharedManagerAdapter impl
}
}
- /**
- * @return Consistent ID.
- */
- protected String consistentId() {
- return cctx.discovery().consistentId().toString();
- }
-
/** {@inheritDoc} */
@Override protected void stop0(boolean cancel) {
final GridTimeoutProcessor.CancelableTask schedule = backgroundFlushSchedule;
http://git-wip-us.apache.org/repos/asf/ignite/blob/62f3c4c5/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/StandaloneGridKernalContext.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/StandaloneGridKernalContext.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/StandaloneGridKernalContext.java
index 07be8b4..e234766 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/StandaloneGridKernalContext.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/StandaloneGridKernalContext.java
@@ -18,6 +18,7 @@
package org.apache.ignite.internal.processors.cache.persistence.wal.reader;
import java.io.File;
+import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.Iterator;
import java.util.List;
@@ -47,6 +48,8 @@ import org.apache.ignite.internal.managers.loadbalancer.GridLoadBalancerManager;
import org.apache.ignite.internal.processors.affinity.GridAffinityProcessor;
import org.apache.ignite.internal.processors.cache.GridCacheProcessor;
import org.apache.ignite.internal.processors.cache.binary.CacheObjectBinaryProcessorImpl;
+import org.apache.ignite.internal.processors.cache.persistence.filename.PdsFoldersResolver;
+import org.apache.ignite.internal.processors.cache.persistence.filename.PdsFolderSettings;
import org.apache.ignite.internal.processors.cacheobject.IgniteCacheObjectProcessor;
import org.apache.ignite.internal.processors.closure.GridClosureProcessor;
import org.apache.ignite.internal.processors.cluster.ClusterProcessor;
@@ -79,6 +82,7 @@ import org.apache.ignite.internal.processors.timeout.GridTimeoutProcessor;
import org.apache.ignite.internal.suggestions.GridPerformanceSuggestions;
import org.apache.ignite.internal.util.IgniteExceptionRegistry;
import org.apache.ignite.internal.util.StripedExecutor;
+import org.apache.ignite.internal.util.typedef.internal.U;
import org.apache.ignite.marshaller.Marshaller;
import org.apache.ignite.plugin.PluginNotFoundException;
import org.apache.ignite.plugin.PluginProvider;
@@ -106,7 +110,7 @@ public class StandaloneGridKernalContext implements GridKernalContext {
@Nullable private IgniteCacheObjectProcessor cacheObjProcessor;
/** Marshaller context implementation. */
- private MarshallerContextImpl marshallerContext;
+ private MarshallerContextImpl marshallerCtx;
/**
* @param log Logger.
@@ -130,13 +134,13 @@ public class StandaloneGridKernalContext implements GridKernalContext {
throw new IllegalStateException("Must not fail on empty providers list.", e);
}
- this.marshallerContext = new MarshallerContextImpl(null);
+ this.marshallerCtx = new MarshallerContextImpl(null);
this.cfg = prepareIgniteConfiguration();
this.cacheObjProcessor = binaryMetadataFileStoreDir != null ? binaryProcessor(this, binaryMetadataFileStoreDir) : null;
if (marshallerMappingFileStoreDir != null) {
- marshallerContext.setMarshallerMappingFileStoreDir(marshallerMappingFileStoreDir);
- marshallerContext.onMarshallerProcessorStarted(this, null);
+ marshallerCtx.setMarshallerMappingFileStoreDir(marshallerMappingFileStoreDir);
+ marshallerCtx.onMarshallerProcessorStarted(this, null);
}
}
@@ -176,7 +180,7 @@ public class StandaloneGridKernalContext implements GridKernalContext {
PersistentStoreConfiguration pstCfg = new PersistentStoreConfiguration();
cfg.setPersistentStoreConfiguration(pstCfg);
- marshaller.setContext(marshallerContext);
+ marshaller.setContext(marshallerCtx);
return cfg;
}
@@ -392,11 +396,7 @@ public class StandaloneGridKernalContext implements GridKernalContext {
/** {@inheritDoc} */
@Override public GridDiscoveryManager discovery() {
- return new GridDiscoveryManager(StandaloneGridKernalContext.this) {
- @Override public Object consistentId() {
- return ""; // some non null value is required
- }
- };
+ return new GridDiscoveryManager(this);
}
/** {@inheritDoc} */
@@ -579,7 +579,7 @@ public class StandaloneGridKernalContext implements GridKernalContext {
/** {@inheritDoc} */
@Override public MarshallerContextImpl marshallerContext() {
- return marshallerContext;
+ return marshallerCtx;
}
/** {@inheritDoc} */
@@ -598,6 +598,16 @@ public class StandaloneGridKernalContext implements GridKernalContext {
}
/** {@inheritDoc} */
+ @Override public PdsFoldersResolver pdsFolderResolver() {
+ return new PdsFoldersResolver() {
+ /** {@inheritDoc} */
+ @Override public PdsFolderSettings resolveFolders() {
+ return new PdsFolderSettings(new File("."), U.maskForFileName(""));
+ }
+ };
+ }
+
+ /** {@inheritDoc} */
@NotNull @Override public Iterator<GridComponent> iterator() {
return null;
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/62f3c4c5/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoverySpi.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoverySpi.java b/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoverySpi.java
index e6eaa8e..eb8ee30 100644
--- a/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoverySpi.java
+++ b/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoverySpi.java
@@ -966,10 +966,10 @@ public class TcpDiscoverySpi extends IgniteSpiAdapter implements DiscoverySpi {
initAddresses();
- Serializable cfgId = ignite.configuration().getConsistentId();
+ final Serializable cfgId = ignite.configuration().getConsistentId();
if (cfgId == null) {
- List<String> sortedAddrs = new ArrayList<>(addrs.get1());
+ final List<String> sortedAddrs = new ArrayList<>(addrs.get1());
Collections.sort(sortedAddrs);
http://git-wip-us.apache.org/repos/asf/ignite/blob/62f3c4c5/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/internal/TcpDiscoveryNode.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/internal/TcpDiscoveryNode.java b/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/internal/TcpDiscoveryNode.java
index 20fb6c5..38c2a1b 100644
--- a/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/internal/TcpDiscoveryNode.java
+++ b/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/internal/TcpDiscoveryNode.java
@@ -225,6 +225,21 @@ public class TcpDiscoveryNode extends GridMetadataAwareAdapter implements Cluste
return consistentId;
}
+ /**
+ * Sets consistent globally unique node ID which survives node restarts.
+ *
+ * @param consistentId Consistent globally unique node ID.
+ */
+ public void setConsistentId(Serializable consistentId) {
+ this.consistentId = consistentId;
+
+ final Map<String, Object> map = new HashMap<>(attrs);
+
+ map.put(ATTR_NODE_CONSISTENT_ID, consistentId);
+
+ attrs = Collections.unmodifiableMap(map);
+ }
+
/** {@inheritDoc} */
@SuppressWarnings("unchecked")
@Override public <T> T attribute(String name) {