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/05/16 15:38:12 UTC

svn commit: r1483356 - in /jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment: file/FileJournal.java file/FileStore.java memory/MemoryJournal.java

Author: jukka
Date: Thu May 16 13:38:11 2013
New Revision: 1483356

URL: http://svn.apache.org/r1483356
Log:
OAK-788: File backend for the SegmentMK

Make the TarMK survive a restart

Added:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/file/FileJournal.java   (with props)
Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/file/FileStore.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/memory/MemoryJournal.java

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/file/FileJournal.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/file/FileJournal.java?rev=1483356&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/file/FileJournal.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/file/FileJournal.java Thu May 16 13:38:11 2013
@@ -0,0 +1,52 @@
+/*
+ * 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.plugins.segment.file;
+
+import org.apache.jackrabbit.oak.plugins.segment.RecordId;
+import org.apache.jackrabbit.oak.plugins.segment.memory.MemoryJournal;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+
+class FileJournal extends MemoryJournal {
+
+    private final FileStore store;
+
+    FileJournal(FileStore store, NodeState root) {
+        super(store, root);
+        this.store = store;
+    }
+
+    FileJournal(FileStore store, String parent) {
+        super(store, parent);
+        this.store = store;
+    }
+
+    @Override
+    public synchronized boolean setHead(RecordId base, RecordId head) {
+        if (super.setHead(base, head)) {
+            store.writeJournals();
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    public synchronized void merge() {
+        super.merge();
+        store.writeJournals();
+    }
+}
\ No newline at end of file

Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/file/FileJournal.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/file/FileStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/file/FileStore.java?rev=1483356&r1=1483355&r2=1483356&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/file/FileStore.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/file/FileStore.java Thu May 16 13:38:11 2013
@@ -37,16 +37,20 @@ import java.util.concurrent.ConcurrentMa
 import org.apache.jackrabbit.oak.plugins.segment.Journal;
 import org.apache.jackrabbit.oak.plugins.segment.RecordId;
 import org.apache.jackrabbit.oak.plugins.segment.Segment;
+import org.apache.jackrabbit.oak.plugins.segment.SegmentNodeState;
 import org.apache.jackrabbit.oak.plugins.segment.SegmentStore;
 import org.apache.jackrabbit.oak.plugins.segment.Template;
-import org.apache.jackrabbit.oak.plugins.segment.memory.MemoryJournal;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
 
 import com.google.common.collect.Maps;
 
 public class FileStore implements SegmentStore {
 
-    private static final long MAGIC_BYTES = 0x4f616b0a527845ddL;
+    private static final long SEGMENT_MAGIC = 0x4f616b0a527845ddL;
+
+    private static final long JOURNAL_MAGIC = 0xdf36544212c0cb24L;
+
+    private static final String JOURNALS_UUID = new UUID(0, 0).toString();
 
     private static final long FILE_SIZE = 256 * 1024 * 1024;
 
@@ -71,7 +75,9 @@ public class FileStore implements Segmen
             this.index++;
         }
 
-        journals.put("root", new MemoryJournal(this, root));
+        if (!journals.containsKey("root")) {
+            journals.put("root", new FileJournal(this, root));
+        }
     }
 
     public FileStore(File directory) throws IOException {
@@ -107,7 +113,7 @@ public class FileStore implements Segmen
             while (ro.remaining() >= 4 * 0x200) {
                 // skip tar header and get the magic bytes; TODO: verify?
                 long magic = ro.getLong(ro.position() + 0x200);
-                if (magic == MAGIC_BYTES) {
+                if (magic == SEGMENT_MAGIC) {
                     ro.position(ro.position() + 0x200 + 8);
 
                     int length = ro.getInt();
@@ -133,6 +139,23 @@ public class FileStore implements Segmen
 
                     // advance to next entry in the file
                     ro.position((ro.position() + length + 0x1ff) & ~0x1ff);
+                } else if (magic == JOURNAL_MAGIC) {
+                    ro.position(ro.position() + 0x200 + 8);
+
+                    int count = ro.getInt();
+                    for (int i = 0; i < count; i++) {
+                        byte[] n = new byte[ro.getInt()];
+                        ro.get(n);
+                        SegmentNodeState h = new SegmentNodeState(this, new RecordId(
+                                new UUID(ro.getLong(), ro.getLong()),
+                                ro.getInt()));
+                        journals.put(
+                                new String(n, UTF_8),
+                                new FileJournal(this, h));
+                    }
+
+                    // advance to next entry in the file
+                    ro.position((ro.position() + 0x1ff) & ~0x1ff);
                 } else {
                     // still space for more segments: position the write
                     // buffer at this point and return false to stop looking
@@ -151,7 +174,7 @@ public class FileStore implements Segmen
     public synchronized Journal getJournal(final String name) {
         Journal journal = journals.get(name);
         if (journal == null) {
-            journal = new MemoryJournal(this, "root");
+            journal = new FileJournal(this, "root");
             journals.put(name, journal);
         }
         return journal;
@@ -174,26 +197,11 @@ public class FileStore implements Segmen
             Map<String, RecordId> strings, Map<Template, RecordId> templates) {
         int size = 8 + 4 + 4 + 16 + 16 * referencedSegmentIds.size() + length;
 
-        if (0x200 + ((size + 0x1ff) & ~0x1ff) + 2 * 0x200 > rw.remaining()) {
-            rw.force();
-            String name = String.format(FILE_NAME_FORMAT, ++index);
-            File file = new File(directory, name);
-            try {
-                RandomAccessFile f = new RandomAccessFile(file, "rw");
-                try {
-                    rw = f.getChannel().map(READ_WRITE, 0, FILE_SIZE);
-                    ro = rw.asReadOnlyBuffer();
-                } finally {
-                    f.close();
-                }
-            } catch (IOException e) {
-                throw new RuntimeException("Unable to create a new segment", e);
-            }
-        }
+        prepare(size);
 
         rw.put(createTarHeader(segmentId.toString(), size));
 
-        rw.putLong(MAGIC_BYTES);
+        rw.putLong(SEGMENT_MAGIC);
         rw.putInt(length);
         rw.putInt(referencedSegmentIds.size());
         rw.putLong(segmentId.getMostSignificantBits());
@@ -225,6 +233,49 @@ public class FileStore implements Segmen
         }
     }
 
+    synchronized void writeJournals() {
+        int size = 8 + 4;
+        for (String name : journals.keySet()) {
+            size += 4 + name.getBytes(UTF_8).length + 16 + 4;
+        }
+
+        prepare(size);
+
+        rw.put(createTarHeader(JOURNALS_UUID, size));
+
+        rw.putLong(JOURNAL_MAGIC);
+        rw.putInt(journals.size());
+        for (Map.Entry<String, Journal> entry : journals.entrySet()) {
+            byte[] name = entry.getKey().getBytes(UTF_8);
+            rw.putInt(name.length);
+            rw.put(name);
+            RecordId head = entry.getValue().getHead();
+            rw.putLong(head.getSegmentId().getMostSignificantBits());
+            rw.putLong(head.getSegmentId().getLeastSignificantBits());
+            rw.putInt(head.getOffset());
+        }
+        rw.position((rw.position() + 0x1ff) & ~0x1ff);
+    }
+
+    private void prepare(int size) {
+        if (0x200 + ((size + 0x1ff) & ~0x1ff) + 2 * 0x200 > rw.remaining()) {
+            rw.force();
+            String name = String.format(FILE_NAME_FORMAT, ++index);
+            File file = new File(directory, name);
+            try {
+                RandomAccessFile f = new RandomAccessFile(file, "rw");
+                try {
+                    rw = f.getChannel().map(READ_WRITE, 0, FILE_SIZE);
+                    ro = rw.asReadOnlyBuffer();
+                } finally {
+                    f.close();
+                }
+            } catch (IOException e) {
+                throw new RuntimeException("Unable to create a new segment", e);
+            }
+        }
+    }
+
     private static byte[] createTarHeader(String name, int length) {
         byte[] header = new byte[] {
                 // File name

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/memory/MemoryJournal.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/memory/MemoryJournal.java?rev=1483356&r1=1483355&r2=1483356&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/memory/MemoryJournal.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/memory/MemoryJournal.java Thu May 16 13:38:11 2013
@@ -27,7 +27,7 @@ import org.apache.jackrabbit.oak.plugins
 import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
 
-public final class MemoryJournal implements Journal {
+public class MemoryJournal implements Journal {
 
     private final SegmentStore store;