Repository: ignite
Updated Branches:
  refs/heads/master 6f9c702cd -> db05c8bb2


IGNITE-10045 Add fail-fast mode to bounded iteration of 
StandaloneWalRecordsIterator - Fixes #5199.

Signed-off-by: Dmitriy Pavlov <dpav...@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/db05c8bb
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/db05c8bb
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/db05c8bb

Branch: refs/heads/master
Commit: db05c8bb244e409603bcae6142e280e55f2c54f1
Parents: 6f9c702
Author: Alexey Stelmak <spiderru5...@gmail.com>
Authored: Thu Nov 1 19:41:38 2018 +0300
Committer: Dmitriy Pavlov <dpav...@apache.org>
Committed: Thu Nov 1 19:41:38 2018 +0300

----------------------------------------------------------------------
 .../wal/reader/IgniteWalIteratorFactory.java    |  16 ++-
 .../reader/StandaloneWalRecordsIterator.java    |  56 ++++++++-
 .../StandaloneWalRecordsIteratorTest.java       | 115 ++++++++++++++++++-
 3 files changed, 181 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/db05c8bb/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/IgniteWalIteratorFactory.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/IgniteWalIteratorFactory.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/IgniteWalIteratorFactory.java
index 4ea1828..f4ebec5 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/IgniteWalIteratorFactory.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/IgniteWalIteratorFactory.java
@@ -181,7 +181,8 @@ public class IgniteWalIteratorFactory {
             iteratorParametersBuilder.lowBound,
             iteratorParametersBuilder.highBound,
             iteratorParametersBuilder.keepBinary,
-            iteratorParametersBuilder.bufferSize
+            iteratorParametersBuilder.bufferSize,
+            iteratorParametersBuilder.strictBoundsCheck
         );
     }
 
@@ -418,6 +419,9 @@ public class IgniteWalIteratorFactory {
         /** */
         private FileWALPointer highBound = DFLT_HIGH_BOUND;
 
+        /** Use strict bounds check for WAL segments. */
+        private boolean strictBoundsCheck;
+
         /**
          * @param filesOrDirs Paths to files or directories.
          * @return IteratorParametersBuilder Self reference.
@@ -535,6 +539,16 @@ public class IgniteWalIteratorFactory {
         }
 
         /**
+         * @param flag Use strict check.
+         * @return IteratorParametersBuilder Self reference.
+         */
+        public IteratorParametersBuilder strictBoundsCheck(boolean flag) {
+            this.strictBoundsCheck = flag;
+
+            return this;
+        }
+
+        /**
          * Copy current state of builder to new instance.
          *
          * @return IteratorParametersBuilder Self reference.

http://git-wip-us.apache.org/repos/asf/ignite/blob/db05c8bb/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/StandaloneWalRecordsIterator.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/StandaloneWalRecordsIterator.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/StandaloneWalRecordsIterator.java
index 25432d3..be5f55a 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/StandaloneWalRecordsIterator.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/StandaloneWalRecordsIterator.java
@@ -22,6 +22,7 @@ import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.stream.Collectors;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.IgniteLogger;
 import org.apache.ignite.internal.GridKernalContext;
@@ -116,7 +117,8 @@ class StandaloneWalRecordsIterator extends 
AbstractWalRecordsIterator {
         FileWALPointer lowBound,
         FileWALPointer highBound,
         boolean keepBinary,
-        int initialReadBufferSize
+        int initialReadBufferSize,
+        boolean strictBoundsCheck
     ) throws IgniteCheckedException {
         super(
             log,
@@ -127,6 +129,9 @@ class StandaloneWalRecordsIterator extends 
AbstractWalRecordsIterator {
             FILE_INPUT_FACTORY
         );
 
+        if (strictBoundsCheck)
+            strictCheck(walFiles, lowBound, highBound);
+
         this.lowBound = lowBound;
         this.highBound = highBound;
 
@@ -140,6 +145,55 @@ class StandaloneWalRecordsIterator extends 
AbstractWalRecordsIterator {
     }
 
     /**
+     * @param walFiles Wal files.
+     * @return printable indexes of segment files.
+     */
+    private static String printIndexes(List<FileDescriptor> walFiles) {
+        return "[" + String.join(",", walFiles.stream().map(f -> 
Long.toString(f.idx())).collect(Collectors.toList())) + "]";
+    }
+
+    /**
+     * @param walFiles Wal files.
+     * @param lowBound Low bound.
+     * @param highBound High bound.
+     *
+     * @throws IgniteCheckedException if failed
+     */
+    private static void strictCheck(List<FileDescriptor> walFiles, 
FileWALPointer lowBound, FileWALPointer highBound) throws 
IgniteCheckedException {
+        int idx = 0;
+
+        if (lowBound.index() > Long.MIN_VALUE) {
+            for (; idx < walFiles.size(); idx++) {
+                FileDescriptor desc = walFiles.get(idx);
+
+                assert desc != null;
+
+                if (desc.idx() == lowBound.index())
+                    break;
+            }
+        }
+
+        if (idx == walFiles.size())
+            throw new IgniteCheckedException("Wal segments not in bounds. 
loBoundIndex=" + lowBound.index() +
+                                                ", indexes=" + 
printIndexes(walFiles));
+
+        long curWalSegmIdx = walFiles.get(idx).idx();
+
+        for (; idx < walFiles.size() && curWalSegmIdx <= highBound.index(); 
idx++, curWalSegmIdx++) {
+            FileDescriptor desc = walFiles.get(idx);
+
+            assert desc != null;
+
+            if (curWalSegmIdx != desc.idx())
+                throw new IgniteCheckedException("Wal segment " + 
curWalSegmIdx + " not found in files " + printIndexes(walFiles));
+        }
+
+        if (highBound.index() < Long.MAX_VALUE && curWalSegmIdx <= 
highBound.index())
+            throw new IgniteCheckedException("Wal segments not in bounds. 
hiBoundIndex=" + highBound.index() +
+                                                ", indexes=" + 
printIndexes(walFiles));
+    }
+
+    /**
      * For directory mode sets oldest file as initial segment, for file by 
file mode, converts all files to descriptors
      * and gets oldest as initial.
      *

http://git-wip-us.apache.org/repos/asf/ignite/blob/db05c8bb/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/StandaloneWalRecordsIteratorTest.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/StandaloneWalRecordsIteratorTest.java
 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/StandaloneWalRecordsIteratorTest.java
index 4d2bdcf..aa24479 100644
--- 
a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/StandaloneWalRecordsIteratorTest.java
+++ 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/StandaloneWalRecordsIteratorTest.java
@@ -21,6 +21,8 @@ import java.io.File;
 import java.io.IOException;
 import java.nio.file.OpenOption;
 import java.nio.file.StandardOpenOption;
+import java.util.List;
+import java.util.Random;
 import java.util.concurrent.atomic.AtomicInteger;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.IgniteCheckedException;
@@ -30,17 +32,23 @@ import org.apache.ignite.configuration.IgniteConfiguration;
 import org.apache.ignite.internal.IgniteEx;
 import org.apache.ignite.internal.pagemem.wal.IgniteWriteAheadLogManager;
 import org.apache.ignite.internal.pagemem.wal.WALIterator;
+import org.apache.ignite.internal.pagemem.wal.WALPointer;
 import org.apache.ignite.internal.pagemem.wal.record.RolloverType;
 import org.apache.ignite.internal.pagemem.wal.record.SnapshotRecord;
+import org.apache.ignite.internal.pagemem.wal.record.WALRecord;
 import 
org.apache.ignite.internal.processors.cache.persistence.IgniteCacheDatabaseSharedManager;
 import org.apache.ignite.internal.processors.cache.persistence.file.FileIO;
 import 
org.apache.ignite.internal.processors.cache.persistence.file.RandomAccessFileIO;
 import 
org.apache.ignite.internal.processors.cache.persistence.file.RandomAccessFileIOFactory;
+import 
org.apache.ignite.internal.processors.cache.persistence.wal.FileDescriptor;
+import 
org.apache.ignite.internal.processors.cache.persistence.wal.FileWALPointer;
 import 
org.apache.ignite.internal.processors.cache.persistence.wal.FileWriteAheadLogManager;
 import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.lang.IgniteBiTuple;
 import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
 import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
 import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
+import org.apache.ignite.testframework.GridTestUtils;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
 
 import static 
org.apache.ignite.internal.processors.cache.persistence.wal.reader.IgniteWalIteratorFactory.IteratorParametersBuilder;
@@ -89,11 +97,9 @@ public class StandaloneWalRecordsIteratorTest extends 
GridCommonAbstractTest {
     }
 
     /**
-     * Check correct closing file descriptors.
      *
-     * @throws Exception if test failed.
      */
-    public void testCorrectClosingFileDescriptors() throws Exception {
+    private String createWalFiles() throws Exception {
         IgniteEx ig = (IgniteEx)startGrid();
 
         String archiveWalDir = getArchiveWalDirPath(ig);
@@ -118,8 +124,18 @@ public class StandaloneWalRecordsIteratorTest extends 
GridCommonAbstractTest {
 
         stopGrid();
 
+        return archiveWalDir;
+    }
+
+    /**
+     * Check correct closing file descriptors.
+     *
+     * @throws Exception if test failed.
+     */
+    public void testCorrectClosingFileDescriptors() throws Exception {
+
         // Iterate by all archived WAL segments.
-        createWalIterator(archiveWalDir).forEach(x -> {
+        createWalIterator(createWalFiles()).forEach(x -> {
         });
 
         assertTrue("At least one WAL file must be opened!", 
CountedFileIO.getCountOpenedWalFiles() > 0);
@@ -128,6 +144,62 @@ public class StandaloneWalRecordsIteratorTest extends 
GridCommonAbstractTest {
     }
 
     /**
+     * Check correct check bounds.
+     *
+     * @throws Exception if test failed.
+     */
+    public void testStrictBounds() throws Exception {
+        String dir = createWalFiles();
+
+        FileWALPointer lowBound = null, highBound = null;
+
+        for (IgniteBiTuple<WALPointer, WALRecord> p : createWalIterator(dir, 
null, null, false)) {
+            if (lowBound == null)
+                lowBound = (FileWALPointer) p.get1();
+
+            highBound = (FileWALPointer) p.get1();
+        }
+
+        assertNotNull(lowBound);
+
+        assertNotNull(highBound);
+
+        createWalIterator(dir, lowBound, highBound, true);
+
+        final FileWALPointer lBound = lowBound;
+        final FileWALPointer hBound = highBound;
+
+        //noinspection ThrowableNotThrown
+        GridTestUtils.assertThrows(log, () -> {
+            createWalIterator(dir, new FileWALPointer(lBound.index() - 1, 0, 
0), hBound, true);
+
+            return 0;
+        } , IgniteCheckedException.class, null);
+
+        //noinspection ThrowableNotThrown
+        GridTestUtils.assertThrows(log, () -> {
+            createWalIterator(dir, lBound, new FileWALPointer(hBound.index() + 
1, 0, 0), true);
+
+            return 0;
+        }, IgniteCheckedException.class, null);
+
+        List<FileDescriptor> walFiles = listWalFiles(dir);
+
+        assertNotNull(walFiles);
+
+        assertTrue(!walFiles.isEmpty());
+
+        assertTrue(walFiles.get(new 
Random().nextInt(walFiles.size())).file().delete());
+
+        //noinspection ThrowableNotThrown
+        GridTestUtils.assertThrows(log, () -> {
+            createWalIterator(dir, lBound, hBound, true);
+
+            return 0;
+        }, IgniteCheckedException.class, null);
+    }
+
+    /**
      * Creates WALIterator associated with files inside walDir.
      *
      * @param walDir - path to WAL directory.
@@ -142,6 +214,41 @@ public class StandaloneWalRecordsIteratorTest extends 
GridCommonAbstractTest {
         return new 
IgniteWalIteratorFactory(log).iterator(params.filesOrDirs(walDir));
     }
 
+
+    /**
+     * @param walDir Wal directory.
+     */
+    private List<FileDescriptor> listWalFiles(String walDir) throws 
IgniteCheckedException {
+        IteratorParametersBuilder params = new IteratorParametersBuilder();
+
+        params.ioFactory(new RandomAccessFileIOFactory());
+
+        return new 
IgniteWalIteratorFactory(log).resolveWalFiles(params.filesOrDirs(walDir));
+    }
+
+    /**
+     * @param walDir Wal directory.
+     * @param lowBound Low bound.
+     * @param highBound High bound.
+     * @param strictCheck Strict check.
+     */
+    private WALIterator createWalIterator(String walDir, FileWALPointer 
lowBound, FileWALPointer highBound, boolean strictCheck)
+                    throws IgniteCheckedException {
+        IteratorParametersBuilder params = new IteratorParametersBuilder();
+
+        params.ioFactory(new RandomAccessFileIOFactory()).
+            filesOrDirs(walDir).
+            strictBoundsCheck(strictCheck);
+
+        if (lowBound != null)
+            params.from(lowBound);
+
+        if (lowBound != null)
+            params.to(highBound);
+
+        return new IgniteWalIteratorFactory(log).iterator(params);
+    }
+
     /**
      * Evaluate path to directory with WAL archive.
      *

Reply via email to