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;