diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/filename/NodeFileTree.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/filename/NodeFileTree.java index 76feaf6e9ee31..dbf072610670f 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/filename/NodeFileTree.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/filename/NodeFileTree.java @@ -594,9 +594,16 @@ private File[] cacheStorages(CacheConfiguration ccfg, boolean includeIdxPa boolean idxPathEmpty = !includeIdxPath || F.isEmpty(idxPath); if (F.isEmpty(csp)) { - return idxPathEmpty - ? new File[]{cacheStorage(null, cacheDirName)} - : new File[]{cacheStorage(null, cacheDirName), cacheStorage(idxPath, cacheDirName)}; + File cs = cacheStorage(null, cacheDirName); + + if (idxPathEmpty) + return new File[]{cs}; + + File idxStorage = cacheStorage(idxPath, cacheDirName); + + return idxStorage.equals(cs) + ? new File[]{cs} + : new File[]{cs, idxStorage}; } File[] cs = new File[csp.length + (idxPathEmpty ? 0 : 1)]; @@ -604,8 +611,23 @@ private File[] cacheStorages(CacheConfiguration ccfg, boolean includeIdxPa for (int i = 0; i < csp.length; i++) cs[i] = cacheStorage(csp[i], cacheDirName); - if (!idxPathEmpty) - cs[cs.length - 1] = cacheStorage(idxPath, cacheDirName); + if (!idxPathEmpty) { + File idxStorage = cacheStorage(idxPath, cacheDirName); + + for (int i = 0; i < csp.length; i++) { + // indexPath equals to some storagePath. + // No need to add twice. + if (cs[i].equals(idxStorage)) { + File[] cs2 = new File[csp.length]; + + System.arraycopy(cs, 0, cs2, 0, cs2.length); + + return cs2; + } + } + + cs[cs.length - 1] = idxStorage; + } return cs; } diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/filename/SnapshotRestoreIndexPathTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/filename/SnapshotRestoreIndexPathTest.java new file mode 100644 index 0000000000000..6723d0a939964 --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/filename/SnapshotRestoreIndexPathTest.java @@ -0,0 +1,129 @@ +/* + * 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.util.stream.IntStream; +import org.apache.ignite.IgniteCache; +import org.apache.ignite.IgniteCheckedException; +import org.apache.ignite.cluster.ClusterState; +import org.apache.ignite.configuration.CacheConfiguration; +import org.apache.ignite.configuration.DataStorageConfiguration; +import org.apache.ignite.configuration.IgniteConfiguration; +import org.apache.ignite.internal.IgniteEx; +import org.apache.ignite.internal.util.typedef.internal.U; +import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; +import org.junit.Test; + +import static org.apache.ignite.internal.processors.cache.persistence.filename.AbstractDataRegionRelativeStoragePathTest.consId; + +/** Check snapshot restore when {@link CacheConfiguration#getIndexPath()} equals to some of {@link CacheConfiguration#getStoragePaths()}. */ +public class SnapshotRestoreIndexPathTest extends GridCommonAbstractTest { + /** */ + private boolean defaultStoragePath; + + /** {@inheritDoc} */ + @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception { + IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName); + + DataStorageConfiguration dsCfg = new DataStorageConfiguration() + .setStoragePath(path("path1")) + .setExtraStoragePaths(path("path2"), path("path3"), path("path4")); + + dsCfg.getDefaultDataRegionConfiguration() + .setPersistenceEnabled(true); + + return cfg + .setConsistentId(consId(cfg)) + .setDataStorageConfiguration(dsCfg); + } + + /** {@inheritDoc} */ + @Override protected void beforeTest() throws Exception { + super.beforeTest(); + + U.delete(new File(U.defaultWorkDirectory())); + } + + /** {@inheritDoc} */ + @Override protected void afterTest() throws Exception { + stopAllGrids(); + + U.delete(new File(U.defaultWorkDirectory())); + } + + /** */ + @Test + public void testSameIndexAndExtraStorage() throws Exception { + defaultStoragePath = false; + doTest(); + } + + /** */ + @Test + public void testSameIndexAndDefaultStorage() throws Exception { + defaultStoragePath = true; + doTest(); + } + + /** */ + private void doTest() throws Exception { + IgniteEx srv = startGrid(0); + + srv.cluster().state(ClusterState.ACTIVE); + + CacheConfiguration ccfg = new CacheConfiguration<>(DEFAULT_CACHE_NAME); + + if (defaultStoragePath) { + ccfg.setIndexPath(path("path1")); + } + else { + ccfg.setStoragePaths(path("path1"), path("path2"), path("path3"), path("path4")) + .setIndexPath(path("path2")); + } + + IgniteCache c = srv.createCache(ccfg); + + IntStream.range(0, 100).forEach(i -> c.put(i, i)); + + srv.snapshot().createSnapshot("snapshot").get(); + + stopAllGrids(); + + cleanPersistenceDir(true); + U.delete(new File(path("path1"))); + U.delete(new File(path("path2"), "db")); + U.delete(new File(path("path3"), "db")); + U.delete(new File(path("path4"), "db")); + + srv = startGrid(0); + + srv.cluster().state(ClusterState.ACTIVE); + + srv.snapshot().restoreSnapshot("snapshot", null).get(); + + IgniteCache c2 = srv.cache(DEFAULT_CACHE_NAME); + + IntStream.range(0, 100).boxed().forEach(i -> assertEquals(i, c2.get(i))); + } + + /** */ + public String path(String folder) throws IgniteCheckedException { + return new File(new File(U.defaultWorkDirectory()), folder).getAbsolutePath(); + } +} diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgnitePdsTestSuite8.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgnitePdsTestSuite8.java index 29be9f1c383ea..914156bb9af7a 100644 --- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgnitePdsTestSuite8.java +++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgnitePdsTestSuite8.java @@ -51,6 +51,7 @@ import org.apache.ignite.internal.processors.cache.persistence.filename.CacheConfigStoragePathTest; import org.apache.ignite.internal.processors.cache.persistence.filename.CustomCacheStorageConfigurationSelfTest; import org.apache.ignite.internal.processors.cache.persistence.filename.SnapshotCreationNonDefaultStoragePathTest; +import org.apache.ignite.internal.processors.cache.persistence.filename.SnapshotRestoreIndexPathTest; import org.apache.ignite.internal.processors.cache.warmup.LoadAllWarmUpStrategySelfTest; import org.apache.ignite.internal.processors.cache.warmup.WarmUpSelfTest; import org.apache.ignite.testframework.GridTestUtils; @@ -114,6 +115,7 @@ public static List> suite(Collection ignoredTests) { GridTestUtils.addTestIfNeeded(suite, IgnitePdsCheckpointRecoveryTest.class, ignoredTests); GridTestUtils.addTestIfNeeded(suite, CacheConfigStoragePathTest.class, ignoredTests); GridTestUtils.addTestIfNeeded(suite, SnapshotCreationNonDefaultStoragePathTest.class, ignoredTests); + GridTestUtils.addTestIfNeeded(suite, SnapshotRestoreIndexPathTest.class, ignoredTests); GridTestUtils.addTestIfNeeded(suite, CustomCacheStorageConfigurationSelfTest.class, ignoredTests); return suite;