You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by ad...@apache.org on 2017/10/18 09:14:38 UTC

svn commit: r1812480 - in /jackrabbit/oak/trunk: oak-benchmarks/src/main/java/org/apache/jackrabbit/oak/benchmark/ oak-benchmarks/src/main/java/org/apache/jackrabbit/oak/scalability/ oak-run-commons/src/main/java/org/apache/jackrabbit/oak/fixture/ oak-...

Author: adulceanu
Date: Wed Oct 18 09:14:38 2017
New Revision: 1812480

URL: http://svn.apache.org/viewvc?rev=1812480&view=rev
Log:
OAK-6615 - Add new segment-tar fixture for attaching a cold-standby to benchmarked primary

Modified:
    jackrabbit/oak/trunk/oak-benchmarks/src/main/java/org/apache/jackrabbit/oak/benchmark/BenchmarkRunner.java
    jackrabbit/oak/trunk/oak-benchmarks/src/main/java/org/apache/jackrabbit/oak/scalability/ScalabilityRunner.java
    jackrabbit/oak/trunk/oak-run-commons/src/main/java/org/apache/jackrabbit/oak/fixture/OakFixture.java
    jackrabbit/oak/trunk/oak-run-commons/src/main/java/org/apache/jackrabbit/oak/fixture/OakRepositoryFixture.java
    jackrabbit/oak/trunk/oak-run-commons/src/main/java/org/apache/jackrabbit/oak/fixture/SegmentTarFixture.java
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ServerCommand.java

Modified: jackrabbit/oak/trunk/oak-benchmarks/src/main/java/org/apache/jackrabbit/oak/benchmark/BenchmarkRunner.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-benchmarks/src/main/java/org/apache/jackrabbit/oak/benchmark/BenchmarkRunner.java?rev=1812480&r1=1812479&r2=1812480&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-benchmarks/src/main/java/org/apache/jackrabbit/oak/benchmark/BenchmarkRunner.java (original)
+++ jackrabbit/oak/trunk/oak-benchmarks/src/main/java/org/apache/jackrabbit/oak/benchmark/BenchmarkRunner.java Wed Oct 18 09:14:38 2017
@@ -166,6 +166,19 @@ public class BenchmarkRunner {
                 .withOptionalArg().ofType(Integer.class).defaultsTo(1000);
         OptionSpec<Integer> vgcMaxAge = parser.accepts("vgcMaxAge", "Continuous DocumentNodeStore VersionGC max age in sec (RDB only)")
                 .withRequiredArg().ofType(Integer.class).defaultsTo(-1);
+        OptionSpec<Integer> coldSyncInterval = parser.accepts("coldSyncInterval", "interval between sync cycles in sec (Segment-Tar-Cold only)")
+                .withRequiredArg().ofType(Integer.class).defaultsTo(5);
+        OptionSpec<Boolean> coldUseDataStore = parser
+                .accepts("useDataStore",
+                        "Whether to use a datastore in the cold standby topology (Segment-Tar-Cold only)")
+                .withOptionalArg().ofType(Boolean.class)
+                .defaultsTo(Boolean.TRUE);
+        OptionSpec<Boolean> coldShareDataStore = parser
+                .accepts("shareDataStore",
+                        "Whether to share the datastore for primary and standby in the cold standby topology (Segment-Tar-Cold only)")
+                .withOptionalArg().ofType(Boolean.class)
+                .defaultsTo(Boolean.FALSE);
+        
         OptionSpec<?> verbose = parser.accepts("verbose", "Enable verbose output");
         OptionSpec<String> nonOption = parser.nonOptions();
         OptionSpec help = parser.acceptsAll(asList("h", "?", "help"), "show help").forHelp();
@@ -201,8 +214,11 @@ public class BenchmarkRunner {
                         cacheSize * MB),
                 OakRepositoryFixture.getSegmentTar(base.value(options), 256, cacheSize,
                         mmap.value(options)),
-                OakRepositoryFixture.getSegmentTarWithBlobStore(base.value(options), 256, cacheSize,
+                OakRepositoryFixture.getSegmentTarWithDataStore(base.value(options), 256, cacheSize,
                         mmap.value(options), fdsCache.value(options)),
+                OakRepositoryFixture.getSegmentTarWithColdStandby(base.value(options), 256, cacheSize,
+                        mmap.value(options), coldUseDataStore.value(options), fdsCache.value(options), 
+                        coldSyncInterval.value(options), coldShareDataStore.value(options)),
                 OakRepositoryFixture.getRDB(rdbjdbcuri.value(options), rdbjdbcuser.value(options),
                         rdbjdbcpasswd.value(options), rdbjdbctableprefix.value(options), 
                         dropDBAfterTest.value(options), cacheSize * MB, vgcMaxAge.value(options)),

Modified: jackrabbit/oak/trunk/oak-benchmarks/src/main/java/org/apache/jackrabbit/oak/scalability/ScalabilityRunner.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-benchmarks/src/main/java/org/apache/jackrabbit/oak/scalability/ScalabilityRunner.java?rev=1812480&r1=1812479&r2=1812480&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-benchmarks/src/main/java/org/apache/jackrabbit/oak/scalability/ScalabilityRunner.java (original)
+++ jackrabbit/oak/trunk/oak-benchmarks/src/main/java/org/apache/jackrabbit/oak/scalability/ScalabilityRunner.java Wed Oct 18 09:14:38 2017
@@ -143,7 +143,7 @@ public class ScalabilityRunner {
                     cacheSize * MB),
                 OakRepositoryFixture.getSegmentTar(
                     base.value(options), 256, cacheSize, mmap.value(options)),
-                OakRepositoryFixture.getSegmentTarWithBlobStore(base.value(options), 256, cacheSize,
+                OakRepositoryFixture.getSegmentTarWithDataStore(base.value(options), 256, cacheSize,
                     mmap.value(options), fdsCache.value(options)),
                 OakRepositoryFixture.getRDB(rdbjdbcuri.value(options), rdbjdbcuser.value(options),
                     rdbjdbcpasswd.value(options), rdbjdbctableprefix.value(options),

Modified: jackrabbit/oak/trunk/oak-run-commons/src/main/java/org/apache/jackrabbit/oak/fixture/OakFixture.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run-commons/src/main/java/org/apache/jackrabbit/oak/fixture/OakFixture.java?rev=1812480&r1=1812479&r2=1812480&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-run-commons/src/main/java/org/apache/jackrabbit/oak/fixture/OakFixture.java (original)
+++ jackrabbit/oak/trunk/oak-run-commons/src/main/java/org/apache/jackrabbit/oak/fixture/OakFixture.java Wed Oct 18 09:14:38 2017
@@ -29,6 +29,7 @@ import com.google.common.base.Predicate;
 import com.google.common.base.Splitter;
 import com.google.common.base.Strings;
 import org.apache.jackrabbit.oak.Oak;
+import org.apache.jackrabbit.oak.fixture.SegmentTarFixture.SegmentTarFixtureBuilder;
 import org.apache.jackrabbit.oak.plugins.document.DocumentMK;
 import org.apache.jackrabbit.oak.plugins.document.DocumentNodeStore;
 import org.apache.jackrabbit.oak.plugins.document.VersionGarbageCollector;
@@ -62,6 +63,7 @@ public abstract class OakFixture {
 
     public static final String OAK_SEGMENT_TAR = "Oak-Segment-Tar";
     public static final String OAK_SEGMENT_TAR_DS = "Oak-Segment-Tar-DS";
+    public static final String OAK_SEGMENT_TAR_COLD = "Oak-Segment-Tar-Cold";
 
     public static final String OAK_COMPOSITE_STORE = "Oak-Composite-Store";
     public static final String OAK_COMPOSITE_MEMORY_STORE = "Oak-Composite-Memory-Store";
@@ -307,16 +309,40 @@ public abstract class OakFixture {
         }
     }
 
-    public static OakFixture getSegmentTar(final String name, final File base,
-        final int maxFileSizeMB, final int cacheSizeMB, final boolean memoryMapping,
-        final boolean useBlobStore) {
-        return getSegmentTar(name, base, maxFileSizeMB, cacheSizeMB, memoryMapping, useBlobStore, 0);
-    }
-
-    public static OakFixture getSegmentTar(final String name, final File base,
-        final int maxFileSizeMB, final int cacheSizeMB, final boolean memoryMapping,
-        final boolean useBlobStore, final int dsCacheInMB) {
-        return new SegmentTarFixture(name, base, maxFileSizeMB, cacheSizeMB, memoryMapping, useBlobStore, dsCacheInMB);
+    public static OakFixture getSegmentTar(final String name, final File base, final int maxFileSizeMB,
+            final int cacheSizeMB, final boolean memoryMapping, final boolean useBlobStore, final int dsCacheInMB,
+            final boolean withColdStandby, final int syncInterval, final boolean shareBlobStore) {
+        
+            SegmentTarFixtureBuilder builder = SegmentTarFixtureBuilder.segmentTarFixtureBuilder(name, base);
+            builder.withMaxFileSize(maxFileSizeMB)
+                   .withSegmentCacheSize(cacheSizeMB)
+                   .withMemoryMapping(memoryMapping)
+                   .withBlobStore(useBlobStore)
+                   .withDSCacheSize(dsCacheInMB);
+            
+            return new SegmentTarFixture(builder, withColdStandby, syncInterval, shareBlobStore);
+        }
+    
+    public static OakFixture getVanillaSegmentTar(final File base, final int maxFileSizeMB,
+            final int cacheSizeMB, final boolean memoryMapping) {
+
+        return getSegmentTar(OakFixture.OAK_SEGMENT_TAR, base, maxFileSizeMB, cacheSizeMB, memoryMapping, false, 0,
+                false, -1, false);
+    }
+
+    public static OakFixture getSegmentTarWithDataStore(final File base,
+        final int maxFileSizeMB, final int cacheSizeMB, final boolean memoryMapping, final int dsCacheInMB) {
+        
+        return getSegmentTar(OakFixture.OAK_SEGMENT_TAR_DS, base, maxFileSizeMB, cacheSizeMB, memoryMapping, true, dsCacheInMB,
+                false, -1, false);
+    }
+    
+    public static OakFixture getSegmentTarWithColdStandby(final File base, final int maxFileSizeMB,
+            final int cacheSizeMB, final boolean memoryMapping, final boolean useBlobStore, final int dsCacheInMB,
+            final int syncInterval, final boolean shareBlobStore) {
+        
+        return getSegmentTar(OakFixture.OAK_SEGMENT_TAR_COLD, base, maxFileSizeMB, cacheSizeMB, memoryMapping, useBlobStore,
+                dsCacheInMB, true, syncInterval, shareBlobStore);
     }
 
     public static OakFixture getCompositeStore(final String name, final File base,

Modified: jackrabbit/oak/trunk/oak-run-commons/src/main/java/org/apache/jackrabbit/oak/fixture/OakRepositoryFixture.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run-commons/src/main/java/org/apache/jackrabbit/oak/fixture/OakRepositoryFixture.java?rev=1812480&r1=1812479&r2=1812480&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-run-commons/src/main/java/org/apache/jackrabbit/oak/fixture/OakRepositoryFixture.java (original)
+++ jackrabbit/oak/trunk/oak-run-commons/src/main/java/org/apache/jackrabbit/oak/fixture/OakRepositoryFixture.java Wed Oct 18 09:14:38 2017
@@ -95,17 +95,21 @@ public class OakRepositoryFixture implem
     }
 
     public static RepositoryFixture getSegmentTar(File base, int maxFileSizeMB, int cacheSizeMB,
-        boolean memoryMapping) {
-        return new OakRepositoryFixture(OakFixture
-            .getSegmentTar(OakFixture.OAK_SEGMENT_TAR, base, maxFileSizeMB, cacheSizeMB,
-                memoryMapping, false));
+            boolean memoryMapping) {
+        return new OakRepositoryFixture(
+                OakFixture.getVanillaSegmentTar(base, maxFileSizeMB, cacheSizeMB, memoryMapping));
     }
 
-    public static RepositoryFixture getSegmentTarWithBlobStore(File base, int maxFileSizeMB,
-        int cacheSizeMB, boolean memoryMapping, int dsCacheInMB) {
-        return new OakRepositoryFixture(OakFixture
-            .getSegmentTar(OakFixture.OAK_SEGMENT_TAR_DS, base, maxFileSizeMB, cacheSizeMB,
-                memoryMapping, true, dsCacheInMB));
+    public static RepositoryFixture getSegmentTarWithDataStore(File base, int maxFileSizeMB, int cacheSizeMB,
+            boolean memoryMapping, int dsCacheInMB) {
+        return new OakRepositoryFixture(
+                OakFixture.getSegmentTarWithDataStore(base, maxFileSizeMB, cacheSizeMB, memoryMapping, dsCacheInMB));
+    }
+    
+    public static RepositoryFixture getSegmentTarWithColdStandby(File base, int maxFileSizeMB, int cacheSizeMB,
+            boolean memoryMapping, boolean useBlobStore, int dsCacheInMB, int syncInterval, boolean shareBlobStore) {
+        return new OakRepositoryFixture(OakFixture.getSegmentTarWithColdStandby(base, maxFileSizeMB, cacheSizeMB,
+                memoryMapping, useBlobStore, dsCacheInMB, syncInterval, shareBlobStore));
     }
 
     public static RepositoryFixture getCompositeStore(File base, int maxFileSizeMB, int cacheSizeMB,

Modified: jackrabbit/oak/trunk/oak-run-commons/src/main/java/org/apache/jackrabbit/oak/fixture/SegmentTarFixture.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run-commons/src/main/java/org/apache/jackrabbit/oak/fixture/SegmentTarFixture.java?rev=1812480&r1=1812479&r2=1812480&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-run-commons/src/main/java/org/apache/jackrabbit/oak/fixture/SegmentTarFixture.java (original)
+++ jackrabbit/oak/trunk/oak-run-commons/src/main/java/org/apache/jackrabbit/oak/fixture/SegmentTarFixture.java Wed Oct 18 09:14:38 2017
@@ -20,93 +20,306 @@ package org.apache.jackrabbit.oak.fixtur
 import static org.apache.jackrabbit.oak.segment.file.FileStoreBuilder.fileStoreBuilder;
 
 import java.io.File;
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
 
+import javax.annotation.Nonnull;
 import org.apache.commons.io.FileUtils;
+import org.apache.jackrabbit.core.data.FileDataStore;
 import org.apache.jackrabbit.oak.Oak;
+import org.apache.jackrabbit.oak.plugins.blob.datastore.DataStoreBlobStore;
+import org.apache.jackrabbit.oak.segment.SegmentId;
 import org.apache.jackrabbit.oak.segment.SegmentNodeStoreBuilders;
+import org.apache.jackrabbit.oak.segment.SegmentNotFoundException;
+import org.apache.jackrabbit.oak.segment.SegmentNotFoundExceptionListener;
 import org.apache.jackrabbit.oak.segment.file.FileStore;
 import org.apache.jackrabbit.oak.segment.file.FileStoreBuilder;
+import org.apache.jackrabbit.oak.segment.file.InvalidFileStoreVersionException;
+import org.apache.jackrabbit.oak.segment.standby.client.StandbyClientSync;
+import org.apache.jackrabbit.oak.segment.standby.server.StandbyServerSync;
 import org.apache.jackrabbit.oak.spi.blob.BlobStore;
 import org.apache.jackrabbit.oak.stats.StatisticsProvider;
 
 class SegmentTarFixture extends OakFixture {
-
-    private FileStore[] stores;
-
-    private BlobStoreFixture[] blobStoreFixtures = new BlobStoreFixture[0];
-
+    /**
+     * Listener instance doing nothing on a {@code SegmentNotFoundException}
+     */
+    SegmentNotFoundExceptionListener IGNORE_SNFE = new SegmentNotFoundExceptionListener() {
+        @Override
+        public void notify(@Nonnull SegmentId id, @Nonnull SegmentNotFoundException snfe) { }
+    };
+    
+    private static final int MB = 1024 * 1024;
+    private static final int DEFAULT_TIMEOUT = 60_000;
+
+    static class SegmentTarFixtureBuilder {
+        private final String name;
+        private final File base;
+        
+        private int maxFileSize;
+        private int segmentCacheSize;
+        private boolean memoryMapping;
+        private boolean useBlobStore;
+        private int dsCacheSize;
+        
+        public static SegmentTarFixtureBuilder segmentTarFixtureBuilder(String name, File directory) {
+            return new SegmentTarFixtureBuilder(name, directory);
+        }
+        
+        private SegmentTarFixtureBuilder(String name, File base) {
+            this.name = name;
+            this.base = base;
+        }
+        
+        public SegmentTarFixtureBuilder withMaxFileSize(int maxFileSize) {
+            this.maxFileSize = maxFileSize;
+            return this;
+        }
+        
+        public SegmentTarFixtureBuilder withSegmentCacheSize(int segmentCacheSize) {
+            this.segmentCacheSize = segmentCacheSize;
+            return this;
+        }
+        
+        public SegmentTarFixtureBuilder withMemoryMapping(boolean memoryMapping) {
+            this.memoryMapping = memoryMapping;
+            return this;
+        }
+        
+        public SegmentTarFixtureBuilder withBlobStore(boolean useBlobStore) {
+            this.useBlobStore = useBlobStore;
+            return this;
+        }
+        
+        public SegmentTarFixtureBuilder withDSCacheSize(int dsCacheSize) {
+            this.dsCacheSize = dsCacheSize;
+            return this;
+        }
+        
+        public SegmentTarFixture build() {
+            return new SegmentTarFixture(this);
+        }
+    }
+    
     private final File base;
-
-    private final int maxFileSizeMB;
-
-    private final int cacheSizeMB;
-
+    private final int maxFileSize;
+    private final int segmentCacheSize;
     private final boolean memoryMapping;
-
     private final boolean useBlobStore;
+    private final int dsCacheSize;
+    
+    private final boolean withColdStandby;
+    private final int syncInterval;
+    private final boolean shareBlobStore;
+    
+    private final File parentPath;
 
-    private final int dsCacheSizeInMB;
-
-    public SegmentTarFixture(String name, File base, int maxFileSizeMB, int cacheSizeMB,
-        boolean memoryMapping, boolean useBlobStore, int dsCacheSizeInMB) {
-        super(name);
-        this.base = base;
-        this.maxFileSizeMB = maxFileSizeMB;
-        this.cacheSizeMB = cacheSizeMB;
-        this.memoryMapping = memoryMapping;
-        this.useBlobStore = useBlobStore;
-        this.dsCacheSizeInMB = dsCacheSizeInMB;
+    private FileStore[] stores;
+    private BlobStoreFixture[] blobStoreFixtures; 
+    
+    private StandbyServerSync[] serverSyncs;
+    private StandbyClientSync[] clientSyncs;
+    private ScheduledExecutorService[] executors;
+    
+    public SegmentTarFixture(SegmentTarFixtureBuilder builder) {
+        this(builder, false, -1, false);
+    }
+    
+    public SegmentTarFixture(SegmentTarFixtureBuilder builder, boolean withColdStandby, int syncInterval) {
+        this(builder, withColdStandby, syncInterval, false);
+    }
+    
+    public SegmentTarFixture(SegmentTarFixtureBuilder builder, boolean withColdStandby, int syncInterval, boolean shareBlobStore) {
+        super(builder.name);
+        this.base = builder.base;
+        this.parentPath = new File(base, unique);
+        
+        this.maxFileSize = builder.maxFileSize;
+        this.segmentCacheSize = builder.segmentCacheSize;
+        this.memoryMapping = builder.memoryMapping;
+        this.useBlobStore = builder.useBlobStore;
+        this.dsCacheSize = builder.dsCacheSize;
+        
+        this.withColdStandby = withColdStandby;
+        this.syncInterval = syncInterval;
+        this.shareBlobStore = shareBlobStore;
     }
 
     @Override
     public Oak getOak(int clusterId) throws Exception {
-        FileStore fs = fileStoreBuilder(base)
-                .withMaxFileSize(maxFileSizeMB)
-                .withSegmentCacheSize(cacheSizeMB)
-                .withMemoryMapping(memoryMapping)
-                .build();
+        FileStoreBuilder fileStoreBuilder = fileStoreBuilder(parentPath)
+                .withMaxFileSize(maxFileSize)
+                .withSegmentCacheSize(segmentCacheSize)
+                .withMemoryMapping(memoryMapping);
+        
+        
+        if (useBlobStore) {
+            FileDataStore fds = new FileDataStore();
+            fds.setMinRecordLength(4092);
+            fds.init(parentPath.getAbsolutePath());
+            BlobStore blobStore = new DataStoreBlobStore(fds);
+            
+            fileStoreBuilder.withBlobStore(blobStore);
+        }
+        
+        FileStore fs = fileStoreBuilder.build();
         return newOak(SegmentNodeStoreBuilders.builder(fs).build());
     }
 
     @Override
     public Oak[] setUpCluster(int n, StatisticsProvider statsProvider) throws Exception {
+        init(n);
+        
         Oak[] cluster = new Oak[n];
-        stores = new FileStore[cluster.length];
-        if (useBlobStore) {
-            blobStoreFixtures = new BlobStoreFixture[cluster.length];
-        }
-
+        
         for (int i = 0; i < cluster.length; i++) {
             BlobStore blobStore = null;
             if (useBlobStore) {
-                blobStoreFixtures[i] = BlobStoreFixture.create(base, true, dsCacheSizeInMB, statsProvider);
+                blobStoreFixtures[i] = BlobStoreFixture.create(parentPath, true, dsCacheSize, statsProvider);
                 blobStore = blobStoreFixtures[i].setUp();
             }
 
-            FileStoreBuilder builder = fileStoreBuilder(new File(base, unique));
+            FileStoreBuilder builder = fileStoreBuilder(new File(parentPath, "primary-" + i));
             if (blobStore != null) {
                 builder.withBlobStore(blobStore);
             }
+            
             stores[i] = builder
-                    .withMaxFileSize(maxFileSizeMB)
+                    .withMaxFileSize(maxFileSize)
                     .withStatisticsProvider(statsProvider)
-                    .withSegmentCacheSize(cacheSizeMB)
+                    .withSegmentCacheSize(segmentCacheSize)
                     .withMemoryMapping(memoryMapping)
                     .build();
+            
+            if (withColdStandby) {
+                attachStandby(i, n, statsProvider, blobStore);
+            }
+            
             cluster[i] = newOak(SegmentNodeStoreBuilders.builder(stores[i]).build());
         }
         return cluster;
     }
 
+    /**
+     * Attaches a standby instance located at index (n+i) in the cluster to the
+     * primary located at index i
+     * 
+     * @param i
+     *            the primary index
+     * @param n
+     *            the number of primary instances in the cluster
+     * @param statsProvider
+     *            statistics provider for the file/blob store(s)
+     * @param blobStore
+     *            the blob store used by the primary (can be <code>null</code>)
+     * @throws InvalidFileStoreVersionException
+     *             if an incorrect oak-segment-tar version is used
+     * @throws IOException
+     *             if the file store manifest cannot be saved
+     */
+    private void attachStandby(int i, int n, StatisticsProvider statsProvider, BlobStore blobStore)
+            throws InvalidFileStoreVersionException, IOException {
+        FileStoreBuilder builder = fileStoreBuilder(new File(parentPath, "standby-" + i));
+        
+        if (useBlobStore) {
+            if (shareBlobStore) {
+                builder.withBlobStore(blobStore);
+            } else {
+                blobStoreFixtures[n + i] = BlobStoreFixture.create(parentPath, true, dsCacheSize, statsProvider);
+                blobStore = blobStoreFixtures[n + i].setUp();
+            }
+        }
+        
+        stores[n + i] = builder
+                .withMaxFileSize(maxFileSize)
+                .withStatisticsProvider(statsProvider)
+                .withSegmentCacheSize(segmentCacheSize)
+                .withMemoryMapping(memoryMapping)
+                .withSnfeListener(IGNORE_SNFE)
+                .build();
+        
+        int port = 0;
+        try (ServerSocket socket = new ServerSocket(0)) {
+            port = socket.getLocalPort();
+        }
+        
+        serverSyncs[i] = new StandbyServerSync(port, stores[i], 1 * MB);
+        clientSyncs[i] = new StandbyClientSync("127.0.0.1", port, stores[n + i], false, DEFAULT_TIMEOUT, false);
+        
+        serverSyncs[i].start();
+        clientSyncs[i].start();
+        
+        executors[i] = Executors.newScheduledThreadPool(1);
+        executors[i].scheduleAtFixedRate(clientSyncs[i], 0, syncInterval, TimeUnit.SECONDS);
+    }
+
+    /**
+     * Initializes various arrays holding internal references based on the
+     * settings provided (e.g. use data store or not, attach cold standby
+     * instance, etc.)
+     * 
+     * @param n
+     *            number of primary instances in the cluster
+     */
+    private void init(int n) {
+        int fileStoresLength = n;
+        int blobStoresLength = 0;
+        
+        if (withColdStandby) {
+            fileStoresLength = 2 * n;
+            
+            if (useBlobStore) {
+                if (shareBlobStore) {
+                    blobStoresLength = n;
+                } else {
+                    blobStoresLength = 2 * n;
+                }
+            } 
+            
+            serverSyncs = new StandbyServerSync[n];
+            clientSyncs = new StandbyClientSync[n];
+            executors = new ScheduledExecutorService[n];
+        } else {
+            if (useBlobStore) {
+                blobStoresLength = n;
+            }
+        }
+        
+        stores = new FileStore[fileStoresLength];
+        blobStoreFixtures = new BlobStoreFixture[blobStoresLength];
+    }
+
     @Override
     public void tearDownCluster() {
+        if (withColdStandby) {
+            for (StandbyClientSync clientSync : clientSyncs) {
+                clientSync.close();
+            }
+            
+            for (StandbyServerSync serverSync : serverSyncs) {
+                serverSync.close();
+            }
+            
+            for (ExecutorService executor : executors) {
+                executor.shutdownNow();
+            }
+        }
+        
         for (FileStore store : stores) {
             store.close();
         }
-        for (BlobStoreFixture blobStore : blobStoreFixtures) {
-            blobStore.tearDown();
+        
+        if (blobStoreFixtures != null) {
+            for (BlobStoreFixture bsf : blobStoreFixtures) {
+                bsf.tearDown();
+            }
         }
-        FileUtils.deleteQuietly(new File(base, unique));
+        
+        FileUtils.deleteQuietly(parentPath);
     }
 
     public BlobStoreFixture[] getBlobStoreFixtures() {

Modified: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ServerCommand.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ServerCommand.java?rev=1812480&r1=1812479&r2=1812480&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ServerCommand.java (original)
+++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ServerCommand.java Wed Oct 18 09:14:38 2017
@@ -122,7 +122,7 @@ class ServerCommand implements Command {
             if (baseFile == null) {
                 throw new IllegalArgumentException("Required argument base missing.");
             }
-            oakFixture = OakFixture.getSegmentTar(OakFixture.OAK_SEGMENT_TAR, baseFile, 256, cacheSize, mmap.value(options), false);
+            oakFixture = OakFixture.getVanillaSegmentTar(baseFile, 256, cacheSize, mmap.value(options));
         } else if (fix.equals(OakFixture.OAK_RDB)) {
             oakFixture = OakFixture.getRDB(OakFixture.OAK_RDB, rdbjdbcuri.value(options), rdbjdbcuser.value(options),
                     rdbjdbcpasswd.value(options), rdbjdbctableprefix.value(options), false, cacheSize, -1);