Index: oak-run/src/main/java/org/apache/jackrabbit/oak/run/Main.java =================================================================== --- oak-run/src/main/java/org/apache/jackrabbit/oak/run/Main.java (revision 1726966) +++ oak-run/src/main/java/org/apache/jackrabbit/oak/run/Main.java (working copy) @@ -332,6 +332,7 @@ final OptionSpec port = parser.accepts("port", "master port").withRequiredArg().ofType(Integer.class).defaultsTo(defaultPort); final OptionSpec interval = parser.accepts("interval", "interval between successive executions").withRequiredArg().ofType(Integer.class); final OptionSpec secure = parser.accepts("secure", "use secure connections").withRequiredArg().ofType(Boolean.class); + final OptionSpec forceFlag = parser.accepts("force", "Ignore non matching segment version"); final OptionSpec help = parser.acceptsAll(asList("h", "?", "help"), "show help").forHelp(); final OptionSpec nonOption = parser.nonOptions(Mode.STANDBY + " "); @@ -348,6 +349,8 @@ System.exit(1); } + checkFileStoreVersionOrFail(new File(nonOptions.get(0)), options.has(forceFlag)); + FileStore store = null; StandbyClient failoverClient = null; try { @@ -382,6 +385,7 @@ final OptionSpec port = parser.accepts("port", "port to listen").withRequiredArg().ofType(Integer.class).defaultsTo(defaultPort); final OptionSpec secure = parser.accepts("secure", "use secure connections").withRequiredArg().ofType(Boolean.class); final OptionSpec admissible = parser.accepts("admissible", "list of admissible slave host names or ip ranges").withRequiredArg().ofType(String.class); + final OptionSpec forceFlag = parser.accepts("force", "Ignore non matching segment version"); final OptionSpec help = parser.acceptsAll(asList("h", "?", "help"), "show help").forHelp(); final OptionSpec nonOption = parser.nonOptions(Mode.PRIMARY + " "); @@ -398,6 +402,7 @@ System.exit(1); } + checkFileStoreVersionOrFail(new File(nonOptions.get(0)), options.has(forceFlag)); List admissibleSlaves = options.has(admissible) ? options.valuesOf(admissible) : Collections.EMPTY_LIST; @@ -622,6 +627,45 @@ .create(); } + private static FileStore openReadOnlyFileStore(File directory) throws IOException { + return newFileStore(directory) + .withCacheSize(256) + .withMemoryMapping(TAR_STORAGE_MEMORY_MAPPED) + .withReadOnly(true) + .create(); + } + + private static void checkFileStoreVersionOrFail(File directory, boolean force) throws IOException { + if (!directory.exists()) { + return; + } + + if (!directory.isDirectory()) { + return; + } + + FileStore store = null; + + try { + store = openReadOnlyFileStore(directory); + + SegmentVersion segmentVersion = getSegmentVersion(store); + + if (segmentVersion != LATEST_VERSION) { + if (force) { + System.out.printf("Segment version mismatch. Found %s, expected %s. Upgrading the file store to segment version %s.\n", segmentVersion, LATEST_VERSION, LATEST_VERSION); + } else { + failWith(String.format("Segment version mismatch. Found %s, expected %s. Aborting.", segmentVersion, LATEST_VERSION)); + } + } + } finally { + if (store != null) { + store.close(); + } + } + + } + private static void checkpoints(String[] args) throws IOException { if (args.length == 0) { System.out Index: oak-segment/src/main/java/org/apache/jackrabbit/oak/plugins/segment/file/FileStore.java =================================================================== --- oak-segment/src/main/java/org/apache/jackrabbit/oak/plugins/segment/file/FileStore.java (revision 1726966) +++ oak-segment/src/main/java/org/apache/jackrabbit/oak/plugins/segment/file/FileStore.java (working copy) @@ -233,6 +233,7 @@ private boolean memoryMapping; private final LoggingGCMonitor gcMonitor = new LoggingGCMonitor(); private StatisticsProvider statsProvider = StatisticsProvider.NOOP; + private boolean readOnly = false; private Builder(File directory) { this.directory = directory; @@ -325,6 +326,12 @@ return this; } + @Nonnull + public Builder withReadOnly(boolean readOnly) { + this.readOnly = readOnly; + return this; + } + /** /** @@ -346,8 +353,7 @@ */ @Nonnull public FileStore create() throws IOException { - return new FileStore( - blobStore, directory, root, maxFileSize, cacheSize, memoryMapping, gcMonitor, statsProvider, false); + return new FileStore(blobStore, directory, root, maxFileSize, cacheSize, memoryMapping, gcMonitor, statsProvider, readOnly); } }