diff --git oak-segment-tar/pom.xml oak-segment-tar/pom.xml
index 9aea358..3004740 100644
--- oak-segment-tar/pom.xml
+++ oak-segment-tar/pom.xml
@@ -51,7 +51,7 @@
maven-bundle-plugin
-
+ org.apache.jackrabbit.oak.backup; version=0.0.1
commons-math3,
netty-*
diff --git oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/backup/FileStoreBackup.java oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/backup/FileStoreBackup.java
index e5803f0..91ad5bb 100644
--- oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/backup/FileStoreBackup.java
+++ oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/backup/FileStoreBackup.java
@@ -16,108 +16,19 @@
* specific language governing permissions and limitations
* under the License.
*/
-
package org.apache.jackrabbit.oak.backup;
-import static org.apache.jackrabbit.oak.segment.file.FileStoreBuilder.fileStoreBuilder;
-
import java.io.File;
import java.io.IOException;
-import javax.annotation.Nonnull;
-
-import com.google.common.base.Stopwatch;
-import com.google.common.base.Suppliers;
-import org.apache.jackrabbit.oak.segment.Compactor;
import org.apache.jackrabbit.oak.segment.Revisions;
-import org.apache.jackrabbit.oak.segment.SegmentBufferWriter;
-import org.apache.jackrabbit.oak.segment.SegmentNodeState;
import org.apache.jackrabbit.oak.segment.SegmentReader;
-import org.apache.jackrabbit.oak.segment.SegmentWriter;
-import org.apache.jackrabbit.oak.segment.WriterCacheManager;
-import org.apache.jackrabbit.oak.segment.compaction.SegmentGCOptions;
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.file.tooling.BasicReadOnlyBlobStore;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class FileStoreBackup {
-
- private static final Logger log = LoggerFactory
- .getLogger(FileStoreBackup.class);
-
- public static boolean USE_FAKE_BLOBSTORE = Boolean
- .getBoolean("oak.backup.UseFakeBlobStore");
-
- public static void backup(@Nonnull SegmentReader reader,
- @Nonnull Revisions revisions,
- @Nonnull File destination)
- throws IOException, InvalidFileStoreVersionException {
- Stopwatch watch = Stopwatch.createStarted();
- SegmentGCOptions gcOptions = SegmentGCOptions.defaultGCOptions()
- .setOffline();
-
- FileStoreBuilder builder = fileStoreBuilder(destination)
- .withDefaultMemoryMapping();
- if (USE_FAKE_BLOBSTORE) {
- builder.withBlobStore(new BasicReadOnlyBlobStore());
- }
- builder.withGCOptions(gcOptions);
- FileStore backup = builder.build();
- SegmentNodeState current = reader.readHeadState(revisions);
- try {
- int gen = 0;
- gen = current.getRecordId().getSegmentId().getGcGeneration();
- SegmentBufferWriter bufferWriter = new SegmentBufferWriter(
- backup,
- backup.getTracker(),
- backup.getReader(),
- "b",
- gen
- );
- SegmentWriter writer = new SegmentWriter(
- backup,
- backup.getReader(),
- backup.getBlobStore(),
- new WriterCacheManager.Default(),
- bufferWriter,
- backup.getBinaryReferenceConsumer()
- );
- Compactor compactor = new Compactor(backup.getReader(), writer,
- backup.getBlobStore(), Suppliers.ofInstance(false),
- gcOptions);
- compactor.setContentEqualityCheck(true);
- SegmentNodeState head = backup.getHead();
- SegmentNodeState after = compactor.compact(head, current, head);
- if (after != null) {
- backup.getRevisions().setHead(head.getRecordId(),
- after.getRecordId());
- }
- } finally {
- backup.close();
- backup = null;
- }
-
- FileStoreBuilder builder2 = fileStoreBuilder(destination)
- .withDefaultMemoryMapping();
- builder2.withGCOptions(gcOptions);
- backup = builder2.build();
- try {
- cleanup(backup);
- } finally {
- backup.close();
- }
- watch.stop();
- log.info("Backup finished in {}.", watch);
- }
- static boolean cleanup(FileStore f) throws IOException {
- boolean ok = true;
- for (File file : f.cleanup()) {
- ok = ok && file.delete();
- }
- return true;
- }
+public interface FileStoreBackup {
+ void backup(SegmentReader reader, Revisions revisions, File destination)
+ throws IOException, InvalidFileStoreVersionException;
+
+ boolean cleanup(FileStore f) throws IOException;
}
diff --git oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/backup/FileStoreBackupRestore.java oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/backup/FileStoreBackupRestore.java
deleted file mode 100644
index 4f4dc54..0000000
--- oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/backup/FileStoreBackupRestore.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * 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.jackrabbit.oak.backup;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static java.lang.System.nanoTime;
-import static org.apache.jackrabbit.oak.management.ManagementOperation.Status.formatTime;
-import static org.apache.jackrabbit.oak.management.ManagementOperation.done;
-import static org.apache.jackrabbit.oak.management.ManagementOperation.newManagementOperation;
-
-import java.io.File;
-import java.util.concurrent.Callable;
-import java.util.concurrent.Executor;
-
-import javax.annotation.Nonnull;
-import javax.management.openmbean.CompositeData;
-
-import org.apache.jackrabbit.oak.api.jmx.FileStoreBackupRestoreMBean;
-import org.apache.jackrabbit.oak.management.ManagementOperation;
-import org.apache.jackrabbit.oak.segment.Revisions;
-import org.apache.jackrabbit.oak.segment.SegmentNodeStore;
-import org.apache.jackrabbit.oak.segment.SegmentReader;
-
-/**
- * Default implementation of {@link FileStoreBackupRestoreMBean} based on a file.
- */
-public class FileStoreBackupRestore implements FileStoreBackupRestoreMBean {
-
- public static final String BACKUP_OP_NAME = "Backup";
- public static final String RESTORE_OP_NAME = "Restore";
-
- private final SegmentNodeStore store;
- private final Revisions revisions;
- private final SegmentReader reader;
- private final File file;
- private final Executor executor;
-
- private ManagementOperation backupOp = done(BACKUP_OP_NAME, "");
- private ManagementOperation restoreOp = done(RESTORE_OP_NAME, "");
-
- /**
- * @param store store to back up from or restore to
- * @param file file to back up to or restore from
- * @param executor executor for running the back up or restore operation
- */
- public FileStoreBackupRestore(
- @Nonnull SegmentNodeStore store,
- @Nonnull Revisions revisions,
- @Nonnull SegmentReader reader,
- @Nonnull File file,
- @Nonnull Executor executor) {
- this.store = checkNotNull(store);
- this.revisions = checkNotNull(revisions);
- this.reader = checkNotNull(reader);
- this.file = checkNotNull(file);
- this.executor = checkNotNull(executor);
- }
-
- @Override
- public synchronized CompositeData startBackup() {
- if (backupOp.isDone()) {
- backupOp = newManagementOperation("Backup", new Callable() {
- @Override
- public String call() throws Exception {
- long t0 = nanoTime();
- FileStoreBackup.backup(reader, revisions, file);
- return "Backup completed in " + formatTime(nanoTime() - t0);
- }
- });
- executor.execute(backupOp);
- }
- return getBackupStatus();
- }
-
- @Override
- public synchronized CompositeData getBackupStatus() {
- return backupOp.getStatus().toCompositeData();
- }
-
- @Override
- public synchronized CompositeData startRestore() {
- if (restoreOp.isDone()) {
- restoreOp = newManagementOperation("Restore", new Callable() {
- @Override
- public String call() throws Exception {
- long t0 = nanoTime();
- FileStoreRestore.restore(file);
- return "Restore completed in " + formatTime(nanoTime() - t0);
- }
- });
- executor.execute(restoreOp);
- }
- return getRestoreStatus();
- }
-
- @Override
- public synchronized CompositeData getRestoreStatus() {
- return restoreOp.getStatus().toCompositeData();
- }
-
- @Override
- public String checkpoint(long lifetime) {
- return store.checkpoint(lifetime);
- }
-
-}
diff --git oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/backup/FileStoreRestore.java oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/backup/FileStoreRestore.java
index 49c5d99..be29c1e 100644
--- oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/backup/FileStoreRestore.java
+++ oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/backup/FileStoreRestore.java
@@ -16,96 +16,14 @@
* specific language governing permissions and limitations
* under the License.
*/
-
package org.apache.jackrabbit.oak.backup;
-import static org.apache.jackrabbit.oak.segment.compaction.SegmentGCOptions.defaultGCOptions;
-import static org.apache.jackrabbit.oak.segment.file.FileStoreBuilder.fileStoreBuilder;
-
import java.io.File;
import java.io.IOException;
-import com.google.common.base.Stopwatch;
-import com.google.common.base.Suppliers;
-import org.apache.jackrabbit.oak.segment.Compactor;
-import org.apache.jackrabbit.oak.segment.SegmentBufferWriter;
-import org.apache.jackrabbit.oak.segment.SegmentNodeState;
-import org.apache.jackrabbit.oak.segment.SegmentWriter;
-import org.apache.jackrabbit.oak.segment.WriterCacheManager;
-import org.apache.jackrabbit.oak.segment.compaction.SegmentGCOptions;
-import org.apache.jackrabbit.oak.segment.file.FileStore;
import org.apache.jackrabbit.oak.segment.file.InvalidFileStoreVersionException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class FileStoreRestore {
-
- private static final Logger log = LoggerFactory
- .getLogger(FileStoreRestore.class);
-
- static int MAX_FILE_SIZE = 256;
-
- private static final String JOURNAL_FILE_NAME = "journal.log";
-
- public static void restore(File source, File destination)
- throws IOException, InvalidFileStoreVersionException {
- if (!validFileStore(source)) {
- throw new IOException("Folder " + source
- + " is not a valid FileStore directory");
- }
-
- FileStore restore = fileStoreBuilder(source).buildReadOnly();
- Stopwatch watch = Stopwatch.createStarted();
-
- FileStore store = fileStoreBuilder(destination).build();
- SegmentNodeState current = store.getHead();
- try {
- SegmentNodeState head = restore.getHead();
- int gen = head.getRecordId().getSegmentId().getGcGeneration();
- SegmentBufferWriter bufferWriter = new SegmentBufferWriter(
- store,
- store.getTracker(),
- store.getReader(),
- "r",
- gen
- );
- SegmentWriter writer = new SegmentWriter(
- store,
- store.getReader(),
- store.getBlobStore(),
- new WriterCacheManager.Default(),
- bufferWriter,
- store.getBinaryReferenceConsumer()
- );
- SegmentGCOptions gcOptions = defaultGCOptions().setOffline();
- Compactor compactor = new Compactor(store.getReader(), writer,
- store.getBlobStore(), Suppliers.ofInstance(false),
- gcOptions);
- compactor.setContentEqualityCheck(true);
- SegmentNodeState after = compactor.compact(current, head, current);
- store.getRevisions().setHead(current.getRecordId(),
- after.getRecordId());
- } finally {
- restore.close();
- store.close();
- }
- watch.stop();
- log.info("Restore finished in {}.", watch);
- }
-
- public static void restore(File source) {
- log.warn("Restore not available as an online operation.");
- }
- private static boolean validFileStore(File source) {
- if (source == null || !source.isDirectory()) {
- return false;
- }
- for (String f : source.list()) {
- if (JOURNAL_FILE_NAME.equals(f)) {
- return true;
- }
- }
- return false;
- }
+public interface FileStoreRestore {
+ void restore(File source, File destination) throws IOException, InvalidFileStoreVersionException;
+ void restore(File source);
}
diff --git oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/backup/impl/FileStoreBackupImpl.java oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/backup/impl/FileStoreBackupImpl.java
new file mode 100644
index 0000000..da785dc
--- /dev/null
+++ oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/backup/impl/FileStoreBackupImpl.java
@@ -0,0 +1,127 @@
+/*
+ * 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.jackrabbit.oak.backup.impl;
+
+import static org.apache.jackrabbit.oak.segment.file.FileStoreBuilder.fileStoreBuilder;
+
+import java.io.File;
+import java.io.IOException;
+
+import javax.annotation.Nonnull;
+
+import com.google.common.base.Stopwatch;
+import com.google.common.base.Suppliers;
+
+import org.apache.jackrabbit.oak.backup.FileStoreBackup;
+import org.apache.jackrabbit.oak.segment.Compactor;
+import org.apache.jackrabbit.oak.segment.Revisions;
+import org.apache.jackrabbit.oak.segment.SegmentBufferWriter;
+import org.apache.jackrabbit.oak.segment.SegmentNodeState;
+import org.apache.jackrabbit.oak.segment.SegmentReader;
+import org.apache.jackrabbit.oak.segment.SegmentWriter;
+import org.apache.jackrabbit.oak.segment.WriterCacheManager;
+import org.apache.jackrabbit.oak.segment.compaction.SegmentGCOptions;
+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.file.tooling.BasicReadOnlyBlobStore;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class FileStoreBackupImpl implements FileStoreBackup {
+
+ private static final Logger log = LoggerFactory
+ .getLogger(FileStoreBackupImpl.class);
+
+ public static boolean USE_FAKE_BLOBSTORE = Boolean
+ .getBoolean("oak.backup.UseFakeBlobStore");
+
+ @Override
+ public void backup(@Nonnull SegmentReader reader,
+ @Nonnull Revisions revisions,
+ @Nonnull File destination)
+ throws IOException, InvalidFileStoreVersionException {
+ Stopwatch watch = Stopwatch.createStarted();
+ SegmentGCOptions gcOptions = SegmentGCOptions.defaultGCOptions()
+ .setOffline();
+
+ FileStoreBuilder builder = fileStoreBuilder(destination)
+ .withDefaultMemoryMapping();
+ if (USE_FAKE_BLOBSTORE) {
+ builder.withBlobStore(new BasicReadOnlyBlobStore());
+ }
+ builder.withGCOptions(gcOptions);
+ FileStore backup = builder.build();
+ SegmentNodeState current = reader.readHeadState(revisions);
+ try {
+ int gen = 0;
+ gen = current.getRecordId().getSegmentId().getGcGeneration();
+ SegmentBufferWriter bufferWriter = new SegmentBufferWriter(
+ backup,
+ backup.getTracker(),
+ backup.getReader(),
+ "b",
+ gen
+ );
+ SegmentWriter writer = new SegmentWriter(
+ backup,
+ backup.getReader(),
+ backup.getBlobStore(),
+ new WriterCacheManager.Default(),
+ bufferWriter,
+ backup.getBinaryReferenceConsumer()
+ );
+ Compactor compactor = new Compactor(backup.getReader(), writer,
+ backup.getBlobStore(), Suppliers.ofInstance(false),
+ gcOptions);
+ compactor.setContentEqualityCheck(true);
+ SegmentNodeState head = backup.getHead();
+ SegmentNodeState after = compactor.compact(head, current, head);
+ if (after != null) {
+ backup.getRevisions().setHead(head.getRecordId(),
+ after.getRecordId());
+ }
+ } finally {
+ backup.close();
+ backup = null;
+ }
+
+ FileStoreBuilder builder2 = fileStoreBuilder(destination)
+ .withDefaultMemoryMapping();
+ builder2.withGCOptions(gcOptions);
+ backup = builder2.build();
+ try {
+ cleanup(backup);
+ } finally {
+ backup.close();
+ }
+ watch.stop();
+ log.info("Backup finished in {}.", watch);
+ }
+
+ @Override
+ public boolean cleanup(FileStore f) throws IOException {
+ boolean ok = true;
+ for (File file : f.cleanup()) {
+ ok = ok && file.delete();
+ }
+ return true;
+ }
+}
diff --git oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/backup/impl/FileStoreBackupRestoreImpl.java oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/backup/impl/FileStoreBackupRestoreImpl.java
new file mode 100644
index 0000000..7055c5a
--- /dev/null
+++ oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/backup/impl/FileStoreBackupRestoreImpl.java
@@ -0,0 +1,131 @@
+/*
+ * 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.jackrabbit.oak.backup.impl;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static java.lang.System.nanoTime;
+import static org.apache.jackrabbit.oak.management.ManagementOperation.done;
+import static org.apache.jackrabbit.oak.management.ManagementOperation.newManagementOperation;
+import static org.apache.jackrabbit.oak.management.ManagementOperation.Status.formatTime;
+
+import java.io.File;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Executor;
+
+import javax.annotation.Nonnull;
+import javax.management.openmbean.CompositeData;
+
+import org.apache.jackrabbit.oak.api.jmx.FileStoreBackupRestoreMBean;
+import org.apache.jackrabbit.oak.backup.FileStoreBackup;
+import org.apache.jackrabbit.oak.backup.FileStoreRestore;
+import org.apache.jackrabbit.oak.management.ManagementOperation;
+import org.apache.jackrabbit.oak.segment.Revisions;
+import org.apache.jackrabbit.oak.segment.SegmentNodeStore;
+import org.apache.jackrabbit.oak.segment.SegmentReader;
+
+/**
+ * Default implementation of {@link FileStoreBackupRestoreMBean} based on a file.
+ */
+public class FileStoreBackupRestoreImpl implements FileStoreBackupRestoreMBean {
+
+ public static final String BACKUP_OP_NAME = "Backup";
+ public static final String RESTORE_OP_NAME = "Restore";
+
+ private final SegmentNodeStore store;
+ private final Revisions revisions;
+ private final SegmentReader reader;
+ private final File file;
+ private final Executor executor;
+
+ private ManagementOperation backupOp = done(BACKUP_OP_NAME, "");
+ private ManagementOperation restoreOp = done(RESTORE_OP_NAME, "");
+
+ private final FileStoreBackup fileStoreBackup;
+ private final FileStoreRestore fileStoreRestore;
+
+ /**
+ * @param store store to back up from or restore to
+ * @param file file to back up to or restore from
+ * @param executor executor for running the back up or restore operation
+ */
+ public FileStoreBackupRestoreImpl(
+ @Nonnull SegmentNodeStore store,
+ @Nonnull Revisions revisions,
+ @Nonnull SegmentReader reader,
+ @Nonnull File file,
+ @Nonnull Executor executor) {
+ this.store = checkNotNull(store);
+ this.revisions = checkNotNull(revisions);
+ this.reader = checkNotNull(reader);
+ this.file = checkNotNull(file);
+ this.executor = checkNotNull(executor);
+
+ this.fileStoreBackup = new FileStoreBackupImpl();
+ this.fileStoreRestore = new FileStoreRestoreImpl();
+ }
+
+ @Override
+ public synchronized CompositeData startBackup() {
+ if (backupOp.isDone()) {
+ backupOp = newManagementOperation("Backup", new Callable() {
+ @Override
+ public String call() throws Exception {
+ long t0 = nanoTime();
+ fileStoreBackup.backup(reader, revisions, file);
+ return "Backup completed in " + formatTime(nanoTime() - t0);
+ }
+ });
+ executor.execute(backupOp);
+ }
+ return getBackupStatus();
+ }
+
+ @Override
+ public synchronized CompositeData getBackupStatus() {
+ return backupOp.getStatus().toCompositeData();
+ }
+
+ @Override
+ public synchronized CompositeData startRestore() {
+ if (restoreOp.isDone()) {
+ restoreOp = newManagementOperation("Restore", new Callable() {
+ @Override
+ public String call() throws Exception {
+ long t0 = nanoTime();
+ fileStoreRestore.restore(file);
+ return "Restore completed in " + formatTime(nanoTime() - t0);
+ }
+ });
+ executor.execute(restoreOp);
+ }
+ return getRestoreStatus();
+ }
+
+ @Override
+ public synchronized CompositeData getRestoreStatus() {
+ return restoreOp.getStatus().toCompositeData();
+ }
+
+ @Override
+ public String checkpoint(long lifetime) {
+ return store.checkpoint(lifetime);
+ }
+
+}
diff --git oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/backup/impl/FileStoreRestoreImpl.java oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/backup/impl/FileStoreRestoreImpl.java
new file mode 100644
index 0000000..e107541
--- /dev/null
+++ oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/backup/impl/FileStoreRestoreImpl.java
@@ -0,0 +1,115 @@
+/*
+ * 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.jackrabbit.oak.backup.impl;
+
+import static org.apache.jackrabbit.oak.segment.compaction.SegmentGCOptions.defaultGCOptions;
+import static org.apache.jackrabbit.oak.segment.file.FileStoreBuilder.fileStoreBuilder;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.apache.jackrabbit.oak.backup.FileStoreRestore;
+import org.apache.jackrabbit.oak.segment.Compactor;
+import org.apache.jackrabbit.oak.segment.SegmentBufferWriter;
+import org.apache.jackrabbit.oak.segment.SegmentNodeState;
+import org.apache.jackrabbit.oak.segment.SegmentWriter;
+import org.apache.jackrabbit.oak.segment.WriterCacheManager;
+import org.apache.jackrabbit.oak.segment.compaction.SegmentGCOptions;
+import org.apache.jackrabbit.oak.segment.file.FileStore;
+import org.apache.jackrabbit.oak.segment.file.InvalidFileStoreVersionException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Stopwatch;
+import com.google.common.base.Suppliers;
+
+public class FileStoreRestoreImpl implements FileStoreRestore {
+
+ private static final Logger log = LoggerFactory
+ .getLogger(FileStoreRestoreImpl.class);
+
+ static int MAX_FILE_SIZE = 256;
+
+ private static final String JOURNAL_FILE_NAME = "journal.log";
+
+ @Override
+ public void restore(File source, File destination)
+ throws IOException, InvalidFileStoreVersionException {
+ if (!validFileStore(source)) {
+ throw new IOException("Folder " + source
+ + " is not a valid FileStore directory");
+ }
+
+ FileStore restore = fileStoreBuilder(source).buildReadOnly();
+ Stopwatch watch = Stopwatch.createStarted();
+
+ FileStore store = fileStoreBuilder(destination).build();
+ SegmentNodeState current = store.getHead();
+ try {
+ SegmentNodeState head = restore.getHead();
+ int gen = head.getRecordId().getSegmentId().getGcGeneration();
+ SegmentBufferWriter bufferWriter = new SegmentBufferWriter(
+ store,
+ store.getTracker(),
+ store.getReader(),
+ "r",
+ gen
+ );
+ SegmentWriter writer = new SegmentWriter(
+ store,
+ store.getReader(),
+ store.getBlobStore(),
+ new WriterCacheManager.Default(),
+ bufferWriter,
+ store.getBinaryReferenceConsumer()
+ );
+ SegmentGCOptions gcOptions = defaultGCOptions().setOffline();
+ Compactor compactor = new Compactor(store.getReader(), writer,
+ store.getBlobStore(), Suppliers.ofInstance(false),
+ gcOptions);
+ compactor.setContentEqualityCheck(true);
+ SegmentNodeState after = compactor.compact(current, head, current);
+ store.getRevisions().setHead(current.getRecordId(),
+ after.getRecordId());
+ } finally {
+ restore.close();
+ store.close();
+ }
+ watch.stop();
+ log.info("Restore finished in {}.", watch);
+ }
+
+ @Override
+ public void restore(File source) {
+ log.warn("Restore not available as an online operation.");
+ }
+
+ private boolean validFileStore(File source) {
+ if (source == null || !source.isDirectory()) {
+ return false;
+ }
+ for (String f : source.list()) {
+ if (JOURNAL_FILE_NAME.equals(f)) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/Backup.java oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/Backup.java
index 351e288..8fc897a 100644
--- oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/Backup.java
+++ oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/Backup.java
@@ -25,6 +25,7 @@ import java.io.File;
import java.io.IOException;
import org.apache.jackrabbit.oak.backup.FileStoreBackup;
+import org.apache.jackrabbit.oak.backup.impl.FileStoreBackupImpl;
import org.apache.jackrabbit.oak.segment.file.FileStore;
import org.apache.jackrabbit.oak.segment.file.InvalidFileStoreVersionException;
@@ -51,10 +52,13 @@ public class Backup implements Runnable {
private File target;
- private boolean fakeBlobStore = FileStoreBackup.USE_FAKE_BLOBSTORE;
+ private boolean fakeBlobStore = FileStoreBackupImpl.USE_FAKE_BLOBSTORE;
+
+ private final FileStoreBackup fileStoreBackup;
private Builder() {
// Prevent external instantiation.
+ this.fileStoreBackup = new FileStoreBackupImpl();
}
/**
@@ -94,7 +98,7 @@ public class Backup implements Runnable {
this.fakeBlobStore = fakeBlobStore;
return this;
}
-
+
/**
* Create an executable version of the {@link Backup} command.
*
@@ -109,21 +113,21 @@ public class Backup implements Runnable {
}
private final File source;
-
private final File target;
-
private final boolean fakeBlobStore;
+ private final FileStoreBackup fileStoreBackup;
private Backup(Builder builder) {
this.source = builder.source;
this.target = builder.target;
this.fakeBlobStore = builder.fakeBlobStore;
+ this.fileStoreBackup = builder.fileStoreBackup;
}
@Override
public void run() {
try (FileStore fs = newFileStore()) {
- FileStoreBackup.backup(fs.getReader(), fs.getRevisions(), target);
+ fileStoreBackup.backup(fs.getReader(), fs.getRevisions(), target);
} catch (Exception e) {
e.printStackTrace();
}
diff --git oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/Restore.java oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/Restore.java
index 56d41a8..24e30f5 100644
--- oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/Restore.java
+++ oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/Restore.java
@@ -22,6 +22,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.io.File;
import org.apache.jackrabbit.oak.backup.FileStoreRestore;
+import org.apache.jackrabbit.oak.backup.impl.FileStoreRestoreImpl;
/**
* Restore a backup of a segment store into an existing segment store.
@@ -43,11 +44,12 @@ public class Restore implements Runnable {
public static class Builder {
private File source;
-
private File target;
+ private final FileStoreRestore fileStoreRestore;
private Builder() {
// Prevent external instantiation.
+ this.fileStoreRestore = new FileStoreRestoreImpl();
}
/**
@@ -86,18 +88,19 @@ public class Restore implements Runnable {
}
private final File source;
-
private final File target;
+ private final FileStoreRestore fileStoreRestore;
private Restore(Builder builder) {
this.source = builder.source;
this.target = builder.target;
+ this.fileStoreRestore = builder.fileStoreRestore;
}
@Override
public void run() {
try {
- FileStoreRestore.restore(source, target);
+ fileStoreRestore.restore(source, target);
} catch (Exception e) {
e.printStackTrace();
}
diff --git oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/backup/FileStoreBackupTest.java oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/backup/FileStoreBackupTest.java
index a0b302c..64f3c79 100644
--- oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/backup/FileStoreBackupTest.java
+++ oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/backup/FileStoreBackupTest.java
@@ -30,6 +30,8 @@ import java.util.Random;
import org.apache.jackrabbit.oak.Oak;
import org.apache.jackrabbit.oak.api.Blob;
import org.apache.jackrabbit.oak.api.CommitFailedException;
+import org.apache.jackrabbit.oak.backup.impl.FileStoreBackupImpl;
+import org.apache.jackrabbit.oak.backup.impl.FileStoreRestoreImpl;
import org.apache.jackrabbit.oak.plugins.nodetype.write.InitialContent;
import org.apache.jackrabbit.oak.segment.SegmentNodeStore;
import org.apache.jackrabbit.oak.segment.SegmentNodeStoreBuilders;
@@ -64,20 +66,23 @@ public class FileStoreBackupTest {
FileStore source = newFileStore(src);
SegmentNodeStore store = SegmentNodeStoreBuilders.builder(source)
.build();
+
+ FileStoreBackup fsb = new FileStoreBackupImpl();
+
try {
init(store);
source.flush();
- FileStoreBackup.backup(source.getReader(), source.getRevisions(), destination);
+ fsb.backup(source.getReader(), source.getRevisions(), destination);
compare(source, destination);
addTestContent(store);
source.flush();
- FileStoreBackup.backup(source.getReader(), source.getRevisions(), destination);
+ fsb.backup(source.getReader(), source.getRevisions(), destination);
compare(source, destination);
source.compact();
- FileStoreBackup.cleanup(source);
- FileStoreBackup.backup(source.getReader(), source.getRevisions(), destination);
+ fsb.cleanup(source);
+ fsb.backup(source.getReader(), source.getRevisions(), destination);
compare(source, destination);
} finally {
source.close();
@@ -89,12 +94,15 @@ public class FileStoreBackupTest {
FileStore source = newFileStore(src);
SegmentNodeStore store = SegmentNodeStoreBuilders.builder(source)
.build();
+ FileStoreBackup fsb = new FileStoreBackupImpl();
+ FileStoreRestore fsr = new FileStoreRestoreImpl();
+
init(store);
source.flush();
- FileStoreBackup.backup(source.getReader(), source.getRevisions(), destination);
+ fsb.backup(source.getReader(), source.getRevisions(), destination);
source.close();
- FileStoreRestore.restore(destination, src);
+ fsr.restore(destination, src);
source = newFileStore(src);
compare(source, destination);
source.close();