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 ju...@apache.org on 2013/12/04 14:31:41 UTC

svn commit: r1547796 - in /jackrabbit/oak/trunk/oak-core/src: main/java/org/apache/jackrabbit/oak/plugins/backup/FileStoreBackup.java test/java/org/apache/jackrabbit/oak/plugins/backup/FileStoreBackupTest.java

Author: jukka
Date: Wed Dec  4 13:31:41 2013
New Revision: 1547796

URL: http://svn.apache.org/r1547796
Log:
OAK-1159: Backup and restore

Add a test for the super-root comparison case
Fix the comparison to always use the root (and not super-root) state
Address the todo for optimizing the incremental backup

Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/backup/FileStoreBackup.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/backup/FileStoreBackupTest.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/backup/FileStoreBackup.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/backup/FileStoreBackup.java?rev=1547796&r1=1547795&r2=1547796&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/backup/FileStoreBackup.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/backup/FileStoreBackup.java Wed Dec  4 13:31:41 2013
@@ -39,7 +39,7 @@ public class FileStoreBackup {
 
     private static final long DEFAULT_LIFETIME = TimeUnit.HOURS.toMillis(1);
 
-    static int CACHE_SIZE = 256;
+    static int MAX_FILE_SIZE = 256;
 
     public static void backup(NodeStore store, File destination)
             throws IOException {
@@ -49,32 +49,44 @@ public class FileStoreBackup {
         String checkpoint = store.checkpoint(DEFAULT_LIFETIME);
         NodeState current = store.retrieve(checkpoint);
         if (current == null) {
-            log.debug("Unable to retrieve checkpoint {}", checkpoint);
-            return;
+            // unable to retrieve the checkpoint; use root state instead
+            current = store.getRoot();
         }
 
         // 2. init filestore
-        destination.mkdirs();
-        FileStore backup = null;
+        FileStore backup = new FileStore(destination, MAX_FILE_SIZE, false);
         try {
-            backup = new FileStore(destination, current, CACHE_SIZE,
-                    CACHE_SIZE, false);
+            Journal journal = backup.getJournal("root");
 
-            // TODO optimize incremental backup
-            Journal root = backup.getJournal("root");
-            SegmentNodeState state = new SegmentNodeState(backup.getWriter()
-                    .getDummySegment(), root.getHead());
+            SegmentNodeState state = new SegmentNodeState(
+                    backup.getWriter().getDummySegment(), journal.getHead());
             SegmentNodeBuilder builder = state.builder();
-            current.compareAgainstBaseState(state,
-                    new ApplyDiff(builder.child("root")));
-            root.setHead(state.getRecordId(), builder.getNodeState()
-                    .getRecordId());
 
-        } finally {
-            if (backup != null) {
-                backup.close();
+            String beforeCheckpoint = state.getString("checkpoint");
+            if (beforeCheckpoint == null) {
+                // 3.1 no stored checkpoint, so do the initial full backup
+                builder.setChildNode("root", current);
+            } else {
+                // 3.2 try to retrieve the previously backed up checkpoint
+                NodeState before = store.retrieve(beforeCheckpoint);
+                if (before != null) {
+                    // the previous checkpoint is no longer available,
+                    // so use the backed up state as the basis of the
+                    // incremental backup diff
+                    before = state.getChildNode("root");
+                }
+                current.compareAgainstBaseState(
+                        before, new ApplyDiff(builder.child("root")));
             }
-            log.debug("Backup done in {} ms.", System.currentTimeMillis() - s);
+            builder.setProperty("checkpoint", checkpoint);
+
+            // 4. commit the backup
+            journal.setHead(
+                    state.getRecordId(), builder.getNodeState().getRecordId());
+        } finally {
+            backup.close();
         }
+
+        log.debug("Backup done in {} ms.", System.currentTimeMillis() - s);
     }
 }

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/backup/FileStoreBackupTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/backup/FileStoreBackupTest.java?rev=1547796&r1=1547795&r2=1547796&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/backup/FileStoreBackupTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/backup/FileStoreBackupTest.java Wed Dec  4 13:31:41 2013
@@ -19,7 +19,6 @@
 package org.apache.jackrabbit.oak.plugins.backup;
 
 import static org.apache.commons.io.FileUtils.deleteQuietly;
-import static org.apache.jackrabbit.oak.plugins.backup.FileStoreBackup.CACHE_SIZE;
 import static org.junit.Assert.assertEquals;
 
 import java.io.File;
@@ -59,7 +58,9 @@ public class FileStoreBackupTest {
 
     @Test
     public void testBackup() throws Exception {
-        NodeStore store = newSegmentNodeStore(src);
+        FileStore source = new FileStore(src, 256, false);
+
+        NodeStore store = new SegmentNodeStore(source);
         init(store);
 
         // initial content
@@ -70,19 +71,23 @@ public class FileStoreBackupTest {
         addTestContent(store);
         FileStoreBackup.backup(store, destination);
         compare(store, destination);
+
+        source.close();
     }
 
     private static void addTestContent(NodeStore store)
             throws CommitFailedException {
         NodeBuilder builder = store.getRoot().builder();
         builder.child("test-backup");
+        builder.child("root"); // make sure we don't backup the super-root
         store.merge(builder, EmptyHook.INSTANCE, null);
     }
 
     private static void compare(NodeStore store, File destination)
             throws IOException {
-        NodeStore backup = newSegmentNodeStore(destination);
-        assertEquals(store.getRoot(), backup.getRoot());
+        FileStore backup = new FileStore(destination, 256, false);
+        assertEquals(store.getRoot(), new SegmentNodeStore(backup).getRoot());
+        backup.close();
     }
 
     private static void init(NodeStore store) {
@@ -90,9 +95,4 @@ public class FileStoreBackupTest {
                 .with(new InitialContent()).createContentRepository();
     }
 
-    private static SegmentNodeStore newSegmentNodeStore(File file)
-            throws IOException {
-        return new SegmentNodeStore(new FileStore(file, CACHE_SIZE, CACHE_SIZE,
-                true));
-    }
 }