Author: mreutegg
Date: Fri Aug 19 07:30:16 2016
New Revision: 1756876
URL: http://svn.apache.org/viewvc?rev=1756876&view=rev
Log:
OAK-4682: ConcurrentModificationException in JournalEntry.TreeNode
Commit fix and enable test
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/JournalEntry.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/JournalEntryTest.java
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java?rev=1756876&r1=1756875&r2=1756876&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java
Fri Aug 19 07:30:16 2016
@@ -435,7 +435,6 @@ public final class DocumentNodeStore
} else {
readOnlyMode = false;
}
- this.changes = Collection.JOURNAL.newDocument(s);
this.executor = builder.getExecutor();
this.clock = builder.getClock();
@@ -459,6 +458,7 @@ public final class DocumentNodeStore
}
this.store = s;
+ this.changes = newJournalEntry();
this.clusterId = cid;
this.branches = new UnmergedBranches();
this.asyncDelay = builder.getAsyncDelay();
@@ -2015,7 +2015,7 @@ public final class DocumentNodeStore
public void acquiring(Revision mostRecent) {
if (store.create(JOURNAL,
singletonList(changes.asUpdateOp(mostRecent)))) {
// success: start with a new document
- changes = JOURNAL.newDocument(getDocumentStore());
+ changes = newJournalEntry();
} else {
// fail: log and keep the changes
LOG.error("Failed to write to journal, accumulating
changes for future write (~" + changes.getMemory()
@@ -2027,6 +2027,10 @@ public final class DocumentNodeStore
//-----------------------------< internal
>---------------------------------
+ private JournalEntry newJournalEntry() {
+ return new JournalEntry(store, true);
+ }
+
/**
* Performs an initial read of the _lastRevs on the root document and sets
* the root state.
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/JournalEntry.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/JournalEntry.java?rev=1756876&r1=1756875&r2=1756876&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/JournalEntry.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/JournalEntry.java
Fri Aug 19 07:30:16 2016
@@ -79,8 +79,15 @@ public final class JournalEntry extends
private volatile TreeNode changes = null;
+ private boolean concurrent;
+
JournalEntry(DocumentStore store) {
+ this(store, false);
+ }
+
+ JournalEntry(DocumentStore store, boolean concurrent) {
this.store = store;
+ this.concurrent = concurrent;
}
static StringSort newSorter() {
@@ -390,7 +397,7 @@ public final class JournalEntry extends
@Nonnull
private TreeNode getChanges() {
if (changes == null) {
- TreeNode node = new TreeNode();
+ TreeNode node = new TreeNode(concurrent);
String c = (String) get(CHANGES);
if (c != null) {
node.parse(new JsopTokenizer(c));
@@ -406,17 +413,23 @@ public final class JournalEntry extends
private Map<String, TreeNode> children = NO_CHILDREN;
+ private final MapFactory mapFactory;
private final TreeNode parent;
private final String name;
TreeNode() {
- this(null, "");
+ this(false);
+ }
+
+ TreeNode(boolean concurrent) {
+ this(concurrent ? MapFactory.CONCURRENT : MapFactory.DEFAULT,
null, "");
}
- TreeNode(TreeNode parent, String name) {
+ TreeNode(MapFactory mapFactory, TreeNode parent, String name) {
checkArgument(!name.contains("/"),
"name must not contain '/': {}", name);
+ this.mapFactory = mapFactory;
this.parent = parent;
this.name = name;
}
@@ -517,11 +530,11 @@ public final class JournalEntry extends
@Nonnull
private TreeNode getOrCreate(String name) {
if (children == NO_CHILDREN) {
- children = Maps.newHashMap();
+ children = mapFactory.newMap();
}
TreeNode c = children.get(name);
if (c == null) {
- c = new TreeNode(this, name);
+ c = new TreeNode(mapFactory, this, name);
children.put(name, c);
}
return c;
@@ -533,4 +546,22 @@ public final class JournalEntry extends
void node(TreeNode node, String path) throws IOException;
}
+ private interface MapFactory {
+
+ MapFactory DEFAULT = new MapFactory() {
+ @Override
+ public Map<String, TreeNode> newMap() {
+ return Maps.newHashMap();
+ }
+ };
+
+ MapFactory CONCURRENT = new MapFactory() {
+ @Override
+ public Map<String, TreeNode> newMap() {
+ return Maps.newConcurrentMap();
+ }
+ };
+
+ Map<String, TreeNode> newMap();
+ }
}
Modified:
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/JournalEntryTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/JournalEntryTest.java?rev=1756876&r1=1756875&r2=1756876&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/JournalEntryTest.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/JournalEntryTest.java
Fri Aug 19 07:30:16 2016
@@ -31,7 +31,6 @@ import org.apache.jackrabbit.oak.commons
import org.apache.jackrabbit.oak.commons.json.JsopTokenizer;
import org.apache.jackrabbit.oak.commons.sort.StringSort;
import org.apache.jackrabbit.oak.plugins.document.memory.MemoryDocumentStore;
-import org.junit.Ignore;
import org.junit.Test;
import static org.apache.jackrabbit.oak.plugins.document.Collection.JOURNAL;
@@ -219,7 +218,6 @@ public class JournalEntryTest {
}
// OAK-4682
- @Ignore
@Test
public void concurrentModification() throws Exception {
DocumentNodeStore store = new DocumentMK.Builder().getNodeStore();