Author: jukka
Date: Mon Jul 15 14:40:18 2013
New Revision: 1503273
URL: http://svn.apache.org/r1503273
Log:
OAK-786: Fall back to pessimism
Instead of extending the journal API, we can simply put extra metadata in the
content tree, at a "super-root" above the one visible to clients.
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/EmptyNodeState.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStore.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStoreBranch.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/file/FileJournal.java
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
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/memory/MemoryStore.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/mongo/MongoJournal.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/mongo/MongoStore.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/AbstractNodeState.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/NodeState.java
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/EmptyNodeState.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/EmptyNodeState.java?rev=1503273&r1=1503272&r2=1503273&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/EmptyNodeState.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/EmptyNodeState.java
Mon Jul 15 14:40:18 2013
@@ -70,6 +70,16 @@ public final class EmptyNodeState implem
return false;
}
+ @Override
+ public long getLong(String name) {
+ return 0;
+ }
+
+ @Override
+ public String getString(String name) {
+ return null;
+ }
+
@Override @CheckForNull
public String getName(@Nonnull String name) {
return null;
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStore.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStore.java?rev=1503273&r1=1503272&r2=1503273&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStore.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStore.java
Mon Jul 15 14:40:18 2013
@@ -34,6 +34,8 @@ import org.apache.jackrabbit.oak.spi.sta
public class SegmentNodeStore extends AbstractNodeStore {
+ static final String ROOT = "root";
+
private final SegmentStore store;
private final Journal journal;
@@ -42,36 +44,41 @@ public class SegmentNodeStore extends Ab
private final Observer observer;
- private SegmentNodeState root;
+ private SegmentNodeState head;
public SegmentNodeStore(SegmentStore store, String journal) {
this.store = store;
this.journal = store.getJournal(journal);
this.reader = new SegmentReader(store);
this.observer = EmptyObserver.INSTANCE;
- this.root = new SegmentNodeState(store, this.journal.getHead());
+ this.head = new SegmentNodeState(store, this.journal.getHead());
}
public SegmentNodeStore(SegmentStore store) {
this(store, "root");
}
+ synchronized SegmentNodeState getHead() {
+ NodeState before = head.getChildNode(ROOT);
+ head = new SegmentNodeState(store, journal.getHead());
+ NodeState after = head.getChildNode(ROOT);
+ observer.contentChanged(before, after);
+ return head;
+ }
+
boolean setHead(SegmentNodeState base, SegmentNodeState head) {
return journal.setHead(base.getRecordId(), head.getRecordId());
}
@Override @Nonnull
- public synchronized SegmentNodeState getRoot() {
- NodeState before = root;
- root = new SegmentNodeState(store, journal.getHead());
- observer.contentChanged(before, root);
- return root;
+ public synchronized NodeState getRoot() {
+ return getHead().getChildNode(ROOT);
}
@Override @Nonnull
public NodeStoreBranch branch() {
return new SegmentNodeStoreBranch(
- this, new SegmentWriter(store), getRoot());
+ this, new SegmentWriter(store), getHead());
}
@Override
@@ -86,14 +93,14 @@ public class SegmentNodeStore extends Ab
public synchronized String checkpoint(long lifetime) {
checkArgument(lifetime > 0);
// TODO: Guard the checkpoint from garbage collection
- return getRoot().getRecordId().toString();
+ return getHead().getRecordId().toString();
}
@Override @CheckForNull
public synchronized NodeState retrieve(@Nonnull String checkpoint) {
// TODO: Verify validity of the checkpoint
RecordId id = RecordId.fromString(checkNotNull(checkpoint));
- return new SegmentNodeState(store, id);
+ return new SegmentNodeState(store, id).getChildNode(ROOT);
}
}
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStoreBranch.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStoreBranch.java?rev=1503273&r1=1503272&r2=1503273&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStoreBranch.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStoreBranch.java
Mon Jul 15 14:40:18 2013
@@ -16,6 +16,8 @@
*/
package org.apache.jackrabbit.oak.plugins.segment;
+import static org.apache.jackrabbit.oak.plugins.segment.SegmentNodeStore.ROOT;
+
import java.util.Random;
import javax.annotation.Nonnull;
@@ -51,27 +53,30 @@ class SegmentNodeStoreBranch extends Abs
@Override @Nonnull
public NodeState getBase() {
- return base;
+ return base.getChildNode(ROOT);
}
@Override @Nonnull
public synchronized NodeState getHead() {
- return head;
+ return head.getChildNode(ROOT);
}
@Override
public synchronized void setRoot(NodeState newRoot) {
- head = writer.writeNode(newRoot);
+ NodeBuilder builder = head.builder();
+ builder.setChildNode(ROOT, newRoot);
+ head = writer.writeNode(builder.getNodeState());
writer.flush();
}
@Override
public synchronized void rebase() {
- SegmentNodeState newBase = store.getRoot();
+ SegmentNodeState newBase = store.getHead();
if (!base.getRecordId().equals(newBase.getRecordId())) {
NodeBuilder builder = newBase.builder();
- head.compareAgainstBaseState(
- base, new ConflictAnnotatingRebaseDiff(builder));
+ head.getChildNode(ROOT).compareAgainstBaseState(
+ base.getChildNode(ROOT),
+ new ConflictAnnotatingRebaseDiff(builder.child(ROOT)));
base = newBase;
head = writer.writeNode(builder.getNodeState());
writer.flush();
@@ -81,19 +86,23 @@ class SegmentNodeStoreBranch extends Abs
@Override @Nonnull
public synchronized NodeState merge(CommitHook hook)
throws CommitFailedException {
+ int backoff = 1;
SegmentNodeState originalBase = base;
SegmentNodeState originalHead = head;
- long backoff = 1;
while (base != head) {
// apply commit hooks on the rebased changes
- SegmentNodeState root = writer.writeNode(
- hook.processCommit(base, head));
+ NodeBuilder builder = head.builder();
+ builder.removeProperty("token");
+ builder.removeProperty("timeout");
+ builder.setChildNode(ROOT, hook.processCommit(
+ base.getChildNode(ROOT), head.getChildNode(ROOT)));
+ SegmentNodeState newHead =
writer.writeNode(builder.getNodeState());
writer.flush();
// use optimistic locking to update the journal
- if (store.setHead(base, root)) {
- base = root;
- head = root;
+ if (store.setHead(base, newHead)) {
+ base = newHead;
+ head = newHead;
} else {
// someone else was faster, so restore state and retry later
base = originalBase;
@@ -105,6 +114,7 @@ class SegmentNodeStoreBranch extends Abs
Thread.sleep(backoff, RANDOM.nextInt(1000000));
backoff *= 2;
} catch (InterruptedException e) {
+ // TODO: correct interrupt handling?
throw new CommitFailedException(
"Segment", 1, "Commit was interrupted", e);
}
@@ -118,7 +128,6 @@ class SegmentNodeStoreBranch extends Abs
rebase();
}
}
-
return getHead();
}
Modified:
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=1503273&r1=1503272&r2=1503273&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/file/FileJournal.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/file/FileJournal.java
Mon Jul 15 14:40:18 2013
@@ -24,8 +24,8 @@ class FileJournal extends MemoryJournal
private final FileStore store;
- FileJournal(FileStore store, NodeState root) {
- super(store, root);
+ FileJournal(FileStore store, NodeState head) {
+ super(store, head);
this.store = store;
}
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=1503273&r1=1503272&r2=1503273&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
Mon Jul 15 14:40:18 2013
@@ -40,6 +40,7 @@ import org.apache.jackrabbit.oak.plugins
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.spi.state.NodeBuilder;
import org.apache.jackrabbit.oak.spi.state.NodeState;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -95,7 +96,9 @@ public class FileStore implements Segmen
}
if (!journals.containsKey("root")) {
- journals.put("root", new FileJournal(this, root));
+ NodeBuilder builder = EMPTY_NODE.builder();
+ builder.setChildNode("root", root);
+ journals.put("root", new FileJournal(this,
builder.getNodeState()));
}
}
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=1503273&r1=1503272&r2=1503273&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
Mon Jul 15 14:40:18 2013
@@ -37,12 +37,12 @@ public class MemoryJournal implements Jo
private RecordId head;
- public MemoryJournal(SegmentStore store, NodeState root) {
+ public MemoryJournal(SegmentStore store, NodeState head) {
this.store = checkNotNull(store);
this.parent = null;
SegmentWriter writer = new SegmentWriter(store);
- RecordId id = writer.writeNode(root).getRecordId();
+ RecordId id = writer.writeNode(head).getRecordId();
writer.flush();
this.base = id;
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/memory/MemoryStore.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/memory/MemoryStore.java?rev=1503273&r1=1503272&r2=1503273&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/memory/MemoryStore.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/memory/MemoryStore.java
Mon Jul 15 14:40:18 2013
@@ -29,6 +29,7 @@ import org.apache.jackrabbit.oak.plugins
import org.apache.jackrabbit.oak.plugins.segment.Segment;
import org.apache.jackrabbit.oak.plugins.segment.SegmentStore;
import org.apache.jackrabbit.oak.plugins.segment.Template;
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
import org.apache.jackrabbit.oak.spi.state.NodeState;
import com.google.common.collect.Maps;
@@ -41,7 +42,9 @@ public class MemoryStore implements Segm
Maps.newConcurrentMap();
public MemoryStore(NodeState root) {
- journals.put("root", new MemoryJournal(this, root));
+ NodeBuilder builder = EMPTY_NODE.builder();
+ builder.setChildNode("root", root);
+ journals.put("root", new MemoryJournal(this, builder.getNodeState()));
}
public MemoryStore() {
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/mongo/MongoJournal.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/mongo/MongoJournal.java?rev=1503273&r1=1503272&r2=1503273&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/mongo/MongoJournal.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/mongo/MongoJournal.java
Mon Jul 15 14:40:18 2013
@@ -61,7 +61,7 @@ class MongoJournal implements Journal {
MongoJournal(
SegmentStore store, DBCollection journals,
- WriteConcern concern, NodeState root) {
+ WriteConcern concern, NodeState head) {
this.store = checkNotNull(store);
this.journals = checkNotNull(journals);
this.concern = checkNotNull(concern);
@@ -71,11 +71,11 @@ class MongoJournal implements Journal {
state = journals.findOne(id, null, primaryPreferred());
if (state == null) {
SegmentWriter writer = new SegmentWriter(store);
- RecordId head = writer.writeNode(root).getRecordId();
+ RecordId headId = writer.writeNode(head).getRecordId();
writer.flush();
state = new BasicDBObject(of(
"_id", "root",
- "head", head.toString()));
+ "head", headId.toString()));
try {
journals.insert(state, concern);
} catch (MongoException.DuplicateKey e) {
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/mongo/MongoStore.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/mongo/MongoStore.java?rev=1503273&r1=1503272&r2=1503273&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/mongo/MongoStore.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/mongo/MongoStore.java
Mon Jul 15 14:40:18 2013
@@ -36,6 +36,7 @@ import org.apache.jackrabbit.oak.plugins
import org.apache.jackrabbit.oak.plugins.segment.SegmentCache;
import org.apache.jackrabbit.oak.plugins.segment.SegmentStore;
import org.apache.jackrabbit.oak.plugins.segment.Template;
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
@@ -62,8 +63,11 @@ public class MongoStore implements Segme
this.db = checkNotNull(db);
this.segments = db.getCollection("segments");
this.cache = cache;
+ NodeBuilder builder = EMPTY_NODE.builder();
+ builder.child("root");
journals.put("root", new MongoJournal(
- this, db.getCollection("journals"), concern, EMPTY_NODE));
+ this, db.getCollection("journals"),
+ concern, builder.getNodeState()));
}
public MongoStore(DB db, long cacheSize) {
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/AbstractNodeState.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/AbstractNodeState.java?rev=1503273&r1=1503272&r2=1503273&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/AbstractNodeState.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/AbstractNodeState.java
Mon Jul 15 14:40:18 2013
@@ -18,8 +18,10 @@ package org.apache.jackrabbit.oak.spi.st
import static java.util.Collections.emptyList;
import static org.apache.jackrabbit.oak.api.Type.BOOLEAN;
+import static org.apache.jackrabbit.oak.api.Type.LONG;
import static org.apache.jackrabbit.oak.api.Type.NAME;
import static org.apache.jackrabbit.oak.api.Type.NAMES;
+import static org.apache.jackrabbit.oak.api.Type.STRING;
import java.util.HashSet;
import java.util.Iterator;
@@ -61,6 +63,26 @@ public abstract class AbstractNodeState
&& property.getValue(BOOLEAN);
}
+ @Override
+ public long getLong(String name) {
+ PropertyState property = getProperty(name);
+ if (property != null && property.getType() == LONG) {
+ return property.getValue(LONG);
+ } else {
+ return 0;
+ }
+ }
+
+ @Override
+ public String getString(String name) {
+ PropertyState property = getProperty(name);
+ if (property != null && property.getType() == STRING) {
+ return property.getValue(STRING);
+ } else {
+ return null;
+ }
+ }
+
@Override @CheckForNull
public String getName(@Nonnull String name) {
PropertyState property = getProperty(name);
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/NodeState.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/NodeState.java?rev=1503273&r1=1503272&r2=1503273&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/NodeState.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/NodeState.java
Mon Jul 15 14:40:18 2013
@@ -172,6 +172,41 @@ public interface NodeState {
boolean getBoolean(@Nonnull String name);
/**
+ * Returns the long value of the named property. The implementation
+ * is equivalent to the following code, but may be optimized.
+ * <pre>
+ * PropertyState property = state.getProperty(name);
+ * if (property != null && property.getType() == Type.LONG) {
+ * return property.getValue(Type.LONG);
+ * } else {
+ * return 0;
+ * }
+ * </pre>
+ *
+ * @param name property name
+ * @return long value of the named property, or zero
+ */
+ long getLong(String name);
+
+
+ /**
+ * Returns the string value of the named property. The implementation
+ * is equivalent to the following code, but may be optimized.
+ * <pre>
+ * PropertyState property = state.getProperty(name);
+ * if (property != null && property.getType() == Type.STRING) {
+ * return property.getValue(Type.STRING);
+ * } else {
+ * return null;
+ * }
+ * </pre>
+ *
+ * @param name property name
+ * @return string value of the named property, or {@code null}
+ */
+ String getString(String name);
+
+ /**
* Returns the name value of the named property. The implementation
* is equivalent to the following code, but may be optimized.
* <pre>