You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by se...@apache.org on 2020/12/11 14:57:00 UTC

[ignite] branch master updated: IGNITE-12892 WAL archive size configuration made more clear - Fixes #8550.

This is an automated email from the ASF dual-hosted git repository.

sergeychugunov pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git


The following commit(s) were added to refs/heads/master by this push:
     new 1f108fb  IGNITE-12892 WAL archive size configuration made more clear - Fixes #8550.
1f108fb is described below

commit 1f108fb163ba58fdf3cda8697d5e3202adabfe28
Author: Semyon Danilov <sa...@yandex.ru>
AuthorDate: Fri Dec 11 17:51:50 2020 +0300

    IGNITE-12892 WAL archive size configuration made more clear - Fixes #8550.
    
    Signed-off-by: Sergey Chugunov <se...@gmail.com>
---
 .../configuration/DataStorageConfiguration.java    |  14 ++-
 .../IgniteCacheDatabaseSharedManager.java          |   9 +-
 .../persistence/checkpoint/CheckpointHistory.java  | 121 +++++++++++++--------
 .../persistence/wal/FileWriteAheadLogManager.java  |   4 +-
 .../apache/ignite/internal/util/IgniteUtils.java   |   3 +-
 .../db/IgnitePdsReserveWalSegmentsTest.java        |   2 +-
 .../db/IgnitePdsStartWIthEmptyArchive.java         |   2 +-
 .../db/wal/WalDeletionArchiveAbstractTest.java     |  39 +------
 8 files changed, 101 insertions(+), 93 deletions(-)

diff --git a/modules/core/src/main/java/org/apache/ignite/configuration/DataStorageConfiguration.java b/modules/core/src/main/java/org/apache/ignite/configuration/DataStorageConfiguration.java
index 2a1927b..2fe4824 100644
--- a/modules/core/src/main/java/org/apache/ignite/configuration/DataStorageConfiguration.java
+++ b/modules/core/src/main/java/org/apache/ignite/configuration/DataStorageConfiguration.java
@@ -72,6 +72,9 @@ public class DataStorageConfiguration implements Serializable {
     /** */
     private static final long serialVersionUID = 0L;
 
+    /** Value used for making WAL archive size unlimited */
+    public static final long UNLIMITED_WAL_ARCHIVE = -1;
+
     /** Default data region start size (256 MB). */
     public static final long DFLT_DATA_REGION_INITIAL_SIZE = 256L * 1024 * 1024;
 
@@ -594,21 +597,26 @@ public class DataStorageConfiguration implements Serializable {
     /**
      * Gets a max allowed size(in bytes) of WAL archives.
      *
-     * @return max size(in bytes) of WAL archive directory(always greater than 0).
+     * @return max size(in bytes) of WAL archive directory(greater than 0, or {@link #UNLIMITED_WAL_ARCHIVE} if
+     * WAL archive size is unlimited).
      */
     public long getMaxWalArchiveSize() {
-        return maxWalArchiveSize <= 0 ? DFLT_WAL_ARCHIVE_MAX_SIZE : maxWalArchiveSize;
+        return maxWalArchiveSize;
     }
 
     /**
      * Sets a max allowed size(in bytes) of WAL archives.
      *
-     * If value is not positive, {@link #DFLT_WAL_ARCHIVE_MAX_SIZE} will be used.
+     * If value is not positive or {@link #UNLIMITED_WAL_ARCHIVE}, {@link #DFLT_WAL_ARCHIVE_MAX_SIZE} will be used.
      *
      * @param walArchiveMaxSize max size(in bytes) of WAL archive directory.
      * @return {@code this} for chaining.
      */
     public DataStorageConfiguration setMaxWalArchiveSize(long walArchiveMaxSize) {
+        if (walArchiveMaxSize != UNLIMITED_WAL_ARCHIVE)
+            A.ensure(walArchiveMaxSize > 0, "Max WAL archive size can be only greater than 0 " +
+                "or must be equal to " + UNLIMITED_WAL_ARCHIVE + " (to be unlimited)");
+
         this.maxWalArchiveSize = walArchiveMaxSize;
 
         return this;
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 346b842..821d3a3 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
@@ -627,15 +627,18 @@ public class IgniteCacheDatabaseSharedManager extends GridCacheSharedManagerAdap
             LT.warn(log, "DataRegionConfiguration.maxWalArchiveSize instead DataRegionConfiguration.walHistorySize " +
             "would be used for removing old archive wal files");
         else if (memCfg.getMaxWalArchiveSize() == DFLT_WAL_ARCHIVE_MAX_SIZE)
-            LT.warn(log, "walHistorySize was deprecated. maxWalArchiveSize should be used instead");
+            LT.warn(log, "walHistorySize was deprecated and does not have any effect anymore. " +
+                "maxWalArchiveSize should be used instead");
         else
             throw new IgniteCheckedException("Should be used only one of wal history size or max wal archive size." +
                 "(use DataRegionConfiguration.maxWalArchiveSize because DataRegionConfiguration.walHistorySize was deprecated)"
             );
 
-        if (memCfg.getMaxWalArchiveSize() < memCfg.getWalSegmentSize())
+        if (memCfg.getMaxWalArchiveSize() != DataStorageConfiguration.UNLIMITED_WAL_ARCHIVE
+            && memCfg.getMaxWalArchiveSize() < memCfg.getWalSegmentSize())
             throw new IgniteCheckedException(
-                "DataRegionConfiguration.maxWalArchiveSize should be greater than DataRegionConfiguration.walSegmentSize"
+                "DataRegionConfiguration.maxWalArchiveSize should be greater than DataRegionConfiguration.walSegmentSize " +
+                    "or must be equal to " + DataStorageConfiguration.UNLIMITED_WAL_ARCHIVE + "."
             );
     }
 
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/checkpoint/CheckpointHistory.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/checkpoint/CheckpointHistory.java
index ed28d95..869f0da 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/checkpoint/CheckpointHistory.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/checkpoint/CheckpointHistory.java
@@ -68,8 +68,8 @@ public class CheckpointHistory {
     /** The maximal number of checkpoints hold in memory. */
     private final int maxCpHistMemSize;
 
-    /** If WalHistorySize was setted by user will use old way for removing checkpoints. */
-    private final boolean isWalHistorySizeParameterEnabled;
+    /** Should WAL be truncated */
+    private final boolean isWalTruncationEnabled;
 
     /** Map stores the earliest checkpoint for each partition from particular group. */
     private final Map<GroupPartitionId, CheckpointEntry> earliestCp = new ConcurrentHashMap<>();
@@ -80,9 +80,6 @@ public class CheckpointHistory {
     /** Checking that checkpoint is applicable or not for given cache group. */
     private final IgniteThrowableBiPredicate</*Checkpoint timestamp*/Long, /*Group id*/Integer> checkpointInapplicable;
 
-    /** It is available or not to truncate WAL on checkpoint finish. */
-    private final boolean truncateWalOnCpFinish;
-
     /** It is available or not to reserve checkpoint(deletion protection). */
     private final boolean reservationDisabled;
 
@@ -103,15 +100,9 @@ public class CheckpointHistory {
         this.wal = wal;
         this.checkpointInapplicable = inapplicable;
 
-        maxCpHistMemSize = Math.min(dsCfg.getWalHistorySize(),
-            IgniteSystemProperties.getInteger(IGNITE_PDS_MAX_CHECKPOINT_MEMORY_HISTORY_SIZE,
-                DFLT_PDS_MAX_CHECKPOINT_MEMORY_HISTORY_SIZE));
-
-        isWalHistorySizeParameterEnabled = dsCfg.isWalHistorySizeParameterUsed();
+        isWalTruncationEnabled = dsCfg.getMaxWalArchiveSize() != DataStorageConfiguration.UNLIMITED_WAL_ARCHIVE;
 
-        truncateWalOnCpFinish = dsCfg.isWalHistorySizeParameterUsed()
-            ? dsCfg.getWalHistorySize() != Integer.MAX_VALUE
-            : dsCfg.getMaxWalArchiveSize() != Long.MAX_VALUE;
+        maxCpHistMemSize = IgniteSystemProperties.getInteger(IGNITE_PDS_MAX_CHECKPOINT_MEMORY_HISTORY_SIZE, DFLT_PDS_MAX_CHECKPOINT_MEMORY_HISTORY_SIZE);
 
         reservationDisabled = dsCfg.getWalMode() == WALMode.NONE;
     }
@@ -317,7 +308,7 @@ public class CheckpointHistory {
      * @return {@code true} if there is space for next checkpoint.
      */
     public boolean hasSpace() {
-        return histMap.size() + 1 <= maxCpHistMemSize;
+        return isWalTruncationEnabled || histMap.size() + 1 <= maxCpHistMemSize;
     }
 
     /**
@@ -334,31 +325,70 @@ public class CheckpointHistory {
             if (highBound.compareTo(cpPnt) <= 0)
                 break;
 
-            if (wal.reserved(cpEntry.checkpointMark())) {
-                U.warn(log, "Could not clear historyMap due to WAL reservation on cp: " + cpEntry +
-                    ", history map size is " + histMap.size());
-
+            if (!removeCheckpoint(cpEntry))
                 break;
-            }
 
-            synchronized (earliestCp) {
-                CheckpointEntry deletedCpEntry = histMap.remove(cpEntry.timestamp());
+            removed.add(cpEntry);
+        }
 
-                CheckpointEntry oldestCpInHistory = firstCheckpoint();
+        return removed;
+    }
 
-                for (Map.Entry<GroupPartitionId, CheckpointEntry> grpPartPerCp : earliestCp.entrySet()) {
-                    if (grpPartPerCp.getValue() == deletedCpEntry)
-                        grpPartPerCp.setValue(oldestCpInHistory);
-                }
-            }
+    /**
+     * Removes checkpoints from history.
+     *
+     * @return List of checkpoint entries removed from history.
+     */
+    public List<CheckpointEntry> removeCheckpoints(int countToRemove) {
+        if (countToRemove == 0)
+            return Collections.emptyList();
 
-            removed.add(cpEntry);
+        List<CheckpointEntry> removed = new ArrayList<>();
+
+        for (Iterator<Map.Entry<Long, CheckpointEntry>> iterator = histMap.entrySet().iterator();
+             iterator.hasNext() && removed.size() < countToRemove; ) {
+            Map.Entry<Long, CheckpointEntry> entry = iterator.next();
+
+            CheckpointEntry checkpoint = entry.getValue();
+
+            if (!removeCheckpoint(checkpoint))
+                break;
+
+            removed.add(checkpoint);
         }
 
         return removed;
     }
 
     /**
+     * Remove checkpoint from history
+     *
+     * @param checkpoint Checkpoint to be removed
+     * @return Whether checkpoint was removed from history
+     */
+    private boolean removeCheckpoint(CheckpointEntry checkpoint) {
+        if (wal.reserved(checkpoint.checkpointMark())) {
+            U.warn(log, "Could not clear historyMap due to WAL reservation on cp: " + checkpoint +
+                ", history map size is " + histMap.size());
+
+            return false;
+        }
+
+        synchronized (earliestCp) {
+            CheckpointEntry deletedCpEntry = histMap.remove(checkpoint.timestamp());
+
+            CheckpointEntry oldestCpInHistory = firstCheckpoint();
+
+            for (Map.Entry<GroupPartitionId, CheckpointEntry> grpPartPerCp : earliestCp.entrySet()) {
+                if (grpPartPerCp.getValue() == deletedCpEntry)
+                    grpPartPerCp.setValue(oldestCpInHistory);
+            }
+        }
+
+        return true;
+    }
+
+    /**
      * Logs and clears checkpoint history after checkpoint finish.
      *
      * @return List of checkpoints removed from history.
@@ -366,21 +396,20 @@ public class CheckpointHistory {
     public List<CheckpointEntry> onCheckpointFinished(Checkpoint chp) {
         chp.walSegsCoveredRange(calculateWalSegmentsCovered());
 
-        WALPointer checkpointMarkUntilDel = isWalHistorySizeParameterEnabled //check for compatibility mode.
-            ? checkpointMarkUntilDeleteByMemorySize()
-            : newerPointer(checkpointMarkUntilDeleteByMemorySize(), checkpointMarkUntilDeleteByArchiveSize());
+        int removeCount = isWalTruncationEnabled
+            ? checkpointCountUntilDeleteByArchiveSize()
+            : (histMap.size() - maxCpHistMemSize);
 
-        if (checkpointMarkUntilDel == null)
+        if (removeCount <= 0)
             return Collections.emptyList();
 
-        List<CheckpointEntry> deletedCheckpoints = onWalTruncated(checkpointMarkUntilDel);
+        List<CheckpointEntry> deletedCheckpoints = removeCheckpoints(removeCount);
 
-        int deleted = 0;
+        if (isWalTruncationEnabled) {
+            int deleted = wal.truncate(firstCheckpointPointer());
 
-        if (truncateWalOnCpFinish)
-            deleted += wal.truncate(firstCheckpointPointer());
-
-        chp.walFilesDeleted(deleted);
+            chp.walFilesDeleted(deleted);
+        }
 
         return deletedCheckpoints;
     }
@@ -420,28 +449,32 @@ public class CheckpointHistory {
     }
 
     /**
-     * Calculate mark until delete by maximum allowed archive size.
+     * Calculate count of checkpoints to delete by maximum allowed archive size.
      *
-     * @return Checkpoint mark until which checkpoints can be deleted(not including this pointer).
+     * @return Checkpoint count to be deleted.
      */
-    @Nullable private WALPointer checkpointMarkUntilDeleteByArchiveSize() {
+    private int checkpointCountUntilDeleteByArchiveSize() {
         long absFileIdxToDel = wal.maxArchivedSegmentToDelete();
 
         if (absFileIdxToDel < 0)
-            return null;
+            return 0;
 
         long fileUntilDel = absFileIdxToDel + 1;
 
         long checkpointFileIdx = absFileIdx(lastCheckpoint());
 
+        int countToRemove = 0;
+
         for (CheckpointEntry cpEntry : histMap.values()) {
             long currFileIdx = absFileIdx(cpEntry);
 
             if (checkpointFileIdx <= currFileIdx || fileUntilDel <= currFileIdx)
-                return cpEntry.checkpointMark();
+                return countToRemove;
+
+            countToRemove++;
         }
 
-        return lastCheckpoint().checkpointMark();
+        return histMap.size() - 1;
     }
 
     /**
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 7a24fa9..de27753 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
@@ -1649,8 +1649,8 @@ public class FileWriteAheadLogManager extends GridCacheSharedManagerAdapter impl
 
     /** {@inheritDoc} */
     @Override public long maxArchivedSegmentToDelete() {
-        //When maxWalArchiveSize==MAX_VALUE deleting files is not permit.
-        if (dsCfg.getMaxWalArchiveSize() == Long.MAX_VALUE)
+        //When maxWalArchiveSize==-1 deleting files is not permitted.
+        if (dsCfg.getMaxWalArchiveSize() == DataStorageConfiguration.UNLIMITED_WAL_ARCHIVE)
             return -1;
 
         FileDescriptor[] archivedFiles = walArchiveFiles();
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java
index 2dc9910..3cf5c38 100755
--- a/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java
@@ -10797,7 +10797,8 @@ public abstract class IgniteUtils {
      * @return User-set max WAL archive size of triple size of the maximum checkpoint buffer.
      */
     public static long adjustedWalHistorySize(DataStorageConfiguration dsCfg, @Nullable IgniteLogger log) {
-        if (dsCfg.getMaxWalArchiveSize() != DataStorageConfiguration.DFLT_WAL_ARCHIVE_MAX_SIZE)
+        if (dsCfg.getMaxWalArchiveSize() != DataStorageConfiguration.UNLIMITED_WAL_ARCHIVE &&
+            dsCfg.getMaxWalArchiveSize() != DataStorageConfiguration.DFLT_WAL_ARCHIVE_MAX_SIZE)
             return dsCfg.getMaxWalArchiveSize();
 
         // Find out the maximum checkpoint buffer size.
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/IgnitePdsReserveWalSegmentsTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/IgnitePdsReserveWalSegmentsTest.java
index e7c212f..c18f062 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/IgnitePdsReserveWalSegmentsTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/IgnitePdsReserveWalSegmentsTest.java
@@ -67,7 +67,7 @@ public class IgnitePdsReserveWalSegmentsTest extends GridCommonAbstractTest {
                 new DataStorageConfiguration()
                     .setCheckpointFrequency(Long.MAX_VALUE)
                     .setWalMode(WALMode.LOG_ONLY)
-                    .setMaxWalArchiveSize(Long.MAX_VALUE)
+                    .setMaxWalArchiveSize(DataStorageConfiguration.UNLIMITED_WAL_ARCHIVE)
                     .setWalSegmentSize(1024 * 1024)
                     .setWalSegments(10)
                     .setDefaultDataRegionConfiguration(
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/IgnitePdsStartWIthEmptyArchive.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/IgnitePdsStartWIthEmptyArchive.java
index 78e6cae..e55e036 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/IgnitePdsStartWIthEmptyArchive.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/IgnitePdsStartWIthEmptyArchive.java
@@ -68,7 +68,7 @@ public class IgnitePdsStartWIthEmptyArchive extends GridCommonAbstractTest {
         cfg.setDataStorageConfiguration(
             new DataStorageConfiguration()
                 // Checkpoint should not remove any WAL archive files.
-                .setMaxWalArchiveSize(Long.MAX_VALUE)
+                .setMaxWalArchiveSize(DataStorageConfiguration.UNLIMITED_WAL_ARCHIVE)
                 .setDefaultDataRegionConfiguration(
                     new DataRegionConfiguration()
                         .setPersistenceEnabled(true)
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/WalDeletionArchiveAbstractTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/WalDeletionArchiveAbstractTest.java
index 044c173..9f3eaaf 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/WalDeletionArchiveAbstractTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/WalDeletionArchiveAbstractTest.java
@@ -17,7 +17,6 @@
 
 package org.apache.ignite.internal.processors.cache.persistence.db.wal;
 
-import java.io.File;
 import java.util.function.Consumer;
 import java.util.stream.Stream;
 import org.apache.ignite.Ignite;
@@ -196,42 +195,6 @@ public abstract class WalDeletionArchiveAbstractTest extends GridCommonAbstractT
     }
 
     /**
-     * Test for check deprecated removing checkpoint by deprecated walHistorySize parameter
-     *
-     * @deprecated Test old removing process depends on WalHistorySize.
-     */
-    @Test
-    public void testCheckpointHistoryRemovingByWalHistorySize() throws Exception {
-        //given: configured grid with wal history size = 10
-        int walHistorySize = 10;
-
-        Ignite ignite = startGrid(dbCfg -> {
-            dbCfg.setWalHistorySize(walHistorySize);
-        });
-
-        GridCacheDatabaseSharedManager dbMgr = gridDatabase(ignite);
-
-        IgniteCache<Integer, Integer> cache = ignite.getOrCreateCache(cacheConfiguration());
-
-        //when: put to cache and do checkpoint
-        int testNumberOfCheckpoint = walHistorySize * 2;
-
-        for (int i = 0; i < testNumberOfCheckpoint; i++) {
-            cache.put(i, i);
-            //and: wait for checkpoint finished
-            forceCheckpoint();
-        }
-
-        //then: number of checkpoints less or equal than walHistorySize
-        CheckpointHistory hist = dbMgr.checkpointHistory();
-        assertTrue(hist.checkpoints().size() == walHistorySize);
-
-        File[] cpFiles = dbMgr.checkpointDirectory().listFiles();
-
-        assertTrue(cpFiles.length <= (walHistorySize * 2 + 1));// starts & ends + node_start
-    }
-
-    /**
      * Correct delete checkpoint history from memory depends on IGNITE_PDS_MAX_CHECKPOINT_MEMORY_HISTORY_SIZE. WAL files
      * doesn't delete because deleting was disabled.
      */
@@ -240,7 +203,7 @@ public abstract class WalDeletionArchiveAbstractTest extends GridCommonAbstractT
     public void testCorrectDeletedCheckpointHistoryButKeepWalFiles() throws Exception {
         //given: configured grid with disabled WAL removing.
         Ignite ignite = startGrid(dbCfg -> {
-            dbCfg.setMaxWalArchiveSize(Long.MAX_VALUE);
+            dbCfg.setMaxWalArchiveSize(DataStorageConfiguration.UNLIMITED_WAL_ARCHIVE);
         });
 
         GridCacheDatabaseSharedManager dbMgr = gridDatabase(ignite);