Repository: ignite Updated Branches: refs/heads/ignite-2.5 df34d192d -> 247ab2e3d
IGNITE-7896 FilePageStore truncate now actually remove redundant partition page file. Signed-off-by: Andrey Gura <ag...@apache.org> (cherry picked from commit d154eec) Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/4a722bbc Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/4a722bbc Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/4a722bbc Branch: refs/heads/ignite-2.5 Commit: 4a722bbc57cf997b58a88778f32180353378d87c Parents: df34d19 Author: Ivan Daschinskiy <ivanda...@gmail.com> Authored: Thu May 10 20:00:12 2018 +0300 Committer: Andrey Gura <ag...@apache.org> Committed: Thu May 17 21:07:41 2018 +0300 ---------------------------------------------------------------------- .../cache/persistence/file/FilePageStore.java | 23 +-- .../IgnitePdsPartitionFilesTruncateTest.java | 153 +++++++++++++++++++ .../ignite/testsuites/IgnitePdsTestSuite2.java | 3 + 3 files changed, 170 insertions(+), 9 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/4a722bbc/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FilePageStore.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FilePageStore.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FilePageStore.java index fa02f5d..05f9421 100755 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FilePageStore.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FilePageStore.java @@ -260,26 +260,31 @@ public class FilePageStore implements PageStore { public void truncate(int tag) throws PersistentStorageIOException { lock.writeLock().lock(); + long pages = this.pages(); + try { if (!inited) return; this.tag = tag; - fileIO.clear(); - - long newAlloc = initFile(); - - long delta = newAlloc - allocated.getAndSet(newAlloc); - - assert delta % pageSize == 0; - - allocatedTracker.updateTotalAllocatedPages(delta / pageSize); + try { + fileIO.close(); + } + finally { + cfgFile.delete(); + } } catch (IOException e) { throw new PersistentStorageIOException(e); } finally { + inited = false; + + allocated.set(0); + + allocatedTracker.updateTotalAllocatedPages(-1L * pages); + lock.writeLock().unlock(); } } http://git-wip-us.apache.org/repos/asf/ignite/blob/4a722bbc/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/IgnitePdsPartitionFilesTruncateTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/IgnitePdsPartitionFilesTruncateTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/IgnitePdsPartitionFilesTruncateTest.java new file mode 100644 index 0000000..78c2453 --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/IgnitePdsPartitionFilesTruncateTest.java @@ -0,0 +1,153 @@ +/* + * 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; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.apache.ignite.Ignite; +import org.apache.ignite.IgniteDataStreamer; +import org.apache.ignite.cache.affinity.rendezvous.RendezvousAffinityFunction; +import org.apache.ignite.configuration.CacheConfiguration; +import org.apache.ignite.configuration.DataRegionConfiguration; +import org.apache.ignite.configuration.DataStorageConfiguration; +import org.apache.ignite.configuration.IgniteConfiguration; +import org.apache.ignite.configuration.WALMode; +import org.apache.ignite.internal.util.typedef.internal.U; +import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; + +/** + * Checks that evicted partitions doesn't leave files in PDS. + */ +public class IgnitePdsPartitionFilesTruncateTest extends GridCommonAbstractTest { + /** {@inheritDoc} */ + @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception { + IgniteConfiguration cfg = super.getConfiguration(gridName); + + cfg.setConsistentId(gridName) + .setDataStorageConfiguration(new DataStorageConfiguration() + .setPageSize(1024) + .setWalMode(WALMode.LOG_ONLY) + .setDefaultDataRegionConfiguration( + new DataRegionConfiguration() + .setPersistenceEnabled(true))) + .setCacheConfiguration(new CacheConfiguration(DEFAULT_CACHE_NAME) + .setBackups(1) + .setAffinity(new RendezvousAffinityFunction(false, 32))); + + return cfg; + } + + /** {@inheritDoc} */ + @Override protected void beforeTest() throws Exception { + stopAllGrids(); + + cleanPersistenceDir(); + } + + /** {@inheritDoc} */ + @Override protected void afterTest() throws Exception { + stopAllGrids(); + + cleanPersistenceDir(); + } + + /** + * @throws Exception If failed. + */ + public void testTruncatingPartitionFilesOnEviction() throws Exception { + Ignite ignite0 = startGrids(3); + + ignite0.cluster().active(true); + + try (IgniteDataStreamer<Integer,String> streamer = ignite0.dataStreamer(DEFAULT_CACHE_NAME)) { + for (int i = 0; i < 1_000; i++) + streamer.addData(i, "Value " + i); + } + + assertEquals(1, ignite0.cacheNames().size()); + + awaitPartitionMapExchange(true, true, null); + + checkPartFiles(0); + checkPartFiles(1); + checkPartFiles(2); + + stopGrid(2); + + ignite0.cluster().setBaselineTopology(ignite0.cluster().topologyVersion()); + + awaitPartitionMapExchange(true, true, null); + + checkPartFiles(0); + checkPartFiles(1); + + startGrid(2); + + ignite0.cluster().setBaselineTopology(ignite0.cluster().topologyVersion()); + + awaitPartitionMapExchange(true, true, null); + + checkPartFiles(0); + checkPartFiles(1); + checkPartFiles(2); + } + + /** + * @param idx Node index. + */ + private void checkPartFiles(int idx) throws Exception { + Ignite ignite = grid(idx); + + int[] parts = ignite.affinity(DEFAULT_CACHE_NAME).allPartitions(ignite.cluster().localNode()); + + Path dirPath = Paths.get(U.defaultWorkDirectory(), "db", + U.maskForFileName(ignite.configuration().getIgniteInstanceName()), "cache-" + DEFAULT_CACHE_NAME); + + info("Path: " + dirPath.toString()); + + assertTrue(Files.exists(dirPath)); + + for (Path f : Files.newDirectoryStream(dirPath)) { + if (f.getFileName().toString().startsWith("part-")) + assertTrue("Node_" + idx +" should contains only partitions " + Arrays.toString(parts) + + ", but the file is redundant: " + f.getFileName(), anyMatch(parts, f)); + } + } + + /** */ + private boolean anyMatch(int[] parts, Path f) { + Pattern ptrn = Pattern.compile("part-(\\d+).bin"); + Matcher matcher = ptrn.matcher(f.getFileName().toString()); + + if (!matcher.find()) + throw new IllegalArgumentException("File is not a partition:" + f.getFileName()); + + int part = Integer.parseInt(matcher.group(1)); + + for (int p: parts) { + if (p == part) + return true; + } + + return false; + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/4a722bbc/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 6d953cd..43de84e 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 @@ -25,6 +25,7 @@ import org.apache.ignite.internal.processors.cache.persistence.IgnitePdsContinuo import org.apache.ignite.internal.processors.cache.persistence.IgnitePdsCorruptedStoreTest; import org.apache.ignite.internal.processors.cache.persistence.IgnitePdsExchangeDuringCheckpointTest; import org.apache.ignite.internal.processors.cache.persistence.IgnitePdsPageSizesTest; +import org.apache.ignite.internal.processors.cache.persistence.IgnitePdsPartitionFilesTruncateTest; import org.apache.ignite.internal.processors.cache.persistence.IgnitePdsRecoveryAfterFileCorruptionTest; import org.apache.ignite.internal.processors.cache.persistence.IgnitePersistentStoreDataStructuresTest; import org.apache.ignite.internal.processors.cache.persistence.LocalWalModeChangeDuringRebalancingSelfTest; @@ -100,6 +101,8 @@ public class IgnitePdsTestSuite2 extends TestSuite { public static void addRealPageStoreTests(TestSuite suite) { suite.addTestSuite(IgnitePdsPageSizesTest.class); + suite.addTestSuite(IgnitePdsPartitionFilesTruncateTest.class); + // Metrics test. suite.addTestSuite(IgniteDataStorageMetricsSelfTest.class);