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 mr...@apache.org on 2015/07/01 14:35:24 UTC
svn commit: r1688633 - in /jackrabbit/oak/branches/1.2: ./
oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/
oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/
Author: mreutegg
Date: Wed Jul 1 12:35:23 2015
New Revision: 1688633
URL: http://svn.apache.org/r1688633
Log:
OAK-2850: Flag states from revision of an external change
Merged revision 1678211 from trunk
Modified:
jackrabbit/oak/branches/1.2/ (props changed)
jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeState.java
jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java
jackrabbit/oak/branches/1.2/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/ClusterTest.java
Propchange: jackrabbit/oak/branches/1.2/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Wed Jul 1 12:35:23 2015
@@ -1,3 +1,3 @@
/jackrabbit/oak/branches/1.0:1665962
-/jackrabbit/oak/trunk:1672350,1672468,1672537,1672603,1672642,1672644,1672834-1672835,1673351,1673410,1673414-1673415,1673436,1673644,1673662-1673664,1673669,1673695,1673738,1673787,1673791,1674046,1674065,1674075,1674107,1674228,1674780,1674880,1675054-1675055,1675319,1675332,1675354,1675357,1675382,1675555,1675566,1675593,1676198,1676237,1676407,1676458,1676539,1676670,1676693,1676703,1676725,1677579,1677581,1677609,1677611,1677774,1677788,1677797,1677804,1677806,1677939,1677991,1678173,1678323,1678758,1678938,1678954,1679144,1679165,1679191,1679232,1679235,1679503,1679958,1679961,1680182,1680222,1680232,1680236,1680461,1680633,1680643,1680747,1680805-1680806,1680903,1681282,1681767,1681918,1682218,1682235,1682437,1682494,1682555,1682855,1682904,1683059,1683089,1683213,1683249,1683259,1683278,1683323,1683687,1683700,1684174-1684175,1684186,1684376,1684442,1684561,1684570,1684601,1684618,1684868,1685023,1685370,1685552,1685589,1685840,1685999,1686097,1686162,1686229,1686234,1686253
,1686414,1686780,1686854,1686857,1686971,1687053-1687055,1687198,1687220,1687239-1687240,1687301,1687441,1687553,1688089-1688090,1688172,1688349,1688421,1688436,1688453,1688616,1688622
+/jackrabbit/oak/trunk:1672350,1672468,1672537,1672603,1672642,1672644,1672834-1672835,1673351,1673410,1673414-1673415,1673436,1673644,1673662-1673664,1673669,1673695,1673738,1673787,1673791,1674046,1674065,1674075,1674107,1674228,1674780,1674880,1675054-1675055,1675319,1675332,1675354,1675357,1675382,1675555,1675566,1675593,1676198,1676237,1676407,1676458,1676539,1676670,1676693,1676703,1676725,1677579,1677581,1677609,1677611,1677774,1677788,1677797,1677804,1677806,1677939,1677991,1678173,1678211,1678323,1678758,1678938,1678954,1679144,1679165,1679191,1679232,1679235,1679503,1679958,1679961,1680182,1680222,1680232,1680236,1680461,1680633,1680643,1680747,1680805-1680806,1680903,1681282,1681767,1681918,1682218,1682235,1682437,1682494,1682555,1682855,1682904,1683059,1683089,1683213,1683249,1683259,1683278,1683323,1683687,1683700,1684174-1684175,1684186,1684376,1684442,1684561,1684570,1684601,1684618,1684868,1685023,1685370,1685552,1685589,1685840,1685999,1686097,1686162,1686229,1686234
,1686253,1686414,1686780,1686854,1686857,1686971,1687053-1687055,1687198,1687220,1687239-1687240,1687301,1687441,1687553,1688089-1688090,1688172,1688349,1688421,1688436,1688453,1688616,1688622
/jackrabbit/trunk:1345480
Modified: jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeState.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeState.java?rev=1688633&r1=1688632&r2=1688633&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeState.java (original)
+++ jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeState.java Wed Jul 1 12:35:23 2015
@@ -83,6 +83,7 @@ public class DocumentNodeState extends A
final Revision rev;
Revision lastRevision;
final Revision rootRevision;
+ final boolean fromExternalChange;
final Map<String, PropertyState> properties;
final boolean hasChildren;
@@ -97,7 +98,7 @@ public class DocumentNodeState extends A
DocumentNodeState(@Nonnull DocumentNodeStore store, @Nonnull String path,
@Nonnull Revision rev, boolean hasChildren) {
this(store, path, rev, new HashMap<String, PropertyState>(),
- hasChildren, null, null);
+ hasChildren, null, null, false);
}
private DocumentNodeState(@Nonnull DocumentNodeStore store,
@@ -106,12 +107,14 @@ public class DocumentNodeState extends A
@Nonnull Map<String, PropertyState> properties,
boolean hasChildren,
@Nullable Revision lastRevision,
- @Nullable Revision rootRevision) {
+ @Nullable Revision rootRevision,
+ boolean fromExternalChange) {
this.store = checkNotNull(store);
this.path = checkNotNull(path);
this.rev = checkNotNull(rev);
this.lastRevision = lastRevision;
this.rootRevision = rootRevision != null ? rootRevision : rev;
+ this.fromExternalChange = fromExternalChange;
this.hasChildren = hasChildren;
this.properties = checkNotNull(properties);
}
@@ -120,20 +123,43 @@ public class DocumentNodeState extends A
* Creates a copy of this {@code DocumentNodeState} with the
* {@link #rootRevision} set to the given {@code root} revision. This method
* returns {@code this} instance if the given {@code root} revision is
- * the same as the one in this instance.
+ * the same as the one in this instance and the {@link #fromExternalChange}
+ * flags are equal.
*
* @param root the root revision for the copy of this node state.
- * @return a copy of this node state with the given root revision.
+ * @param externalChange if the {@link #fromExternalChange} flag must be
+ * set on the returned node state.
+ * @return a copy of this node state with the given root revision and
+ * external change flag.
*/
- DocumentNodeState withRootRevision(@Nonnull Revision root) {
- if (rootRevision.equals(root)) {
+ private DocumentNodeState withRootRevision(@Nonnull Revision root,
+ boolean externalChange) {
+ if (rootRevision.equals(root) && fromExternalChange == externalChange) {
return this;
} else {
return new DocumentNodeState(store, path, rev, properties,
- hasChildren, lastRevision, root);
+ hasChildren, lastRevision, root, externalChange);
}
}
+ /**
+ * @return a copy of this {@code DocumentNodeState} with the
+ * {@link #fromExternalChange} flag set to {@code true}.
+ */
+ @Nonnull
+ DocumentNodeState fromExternalChange() {
+ return new DocumentNodeState(store, path, rev, properties, hasChildren,
+ lastRevision, rootRevision, true);
+ }
+
+ /**
+ * @return {@code true} if this node state was created as a result of an
+ * external change; {@code false} otherwise.
+ */
+ boolean isFromExternalChange() {
+ return fromExternalChange;
+ }
+
@Nonnull
Revision getRevision() {
return rev;
@@ -228,7 +254,7 @@ public class DocumentNodeState extends A
checkValidName(name);
return EmptyNodeState.MISSING_NODE;
} else {
- return child.withRootRevision(rootRevision);
+ return child.withRootRevision(rootRevision, fromExternalChange);
}
}
@@ -486,7 +512,7 @@ public class DocumentNodeState extends A
@Nonnull
@Override
public NodeState getNodeState() {
- return input.withRootRevision(rootRevision);
+ return input.withRootRevision(rootRevision, fromExternalChange);
}
};
}
Modified: jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java?rev=1688633&r1=1688632&r2=1688633&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java (original)
+++ jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java Wed Jul 1 12:35:23 2015
@@ -1782,7 +1782,7 @@ public final class DocumentNodeStore
// the new head revision is after other revisions
setHeadRevision(newRevision());
if (dispatchChange) {
- dispatcher.contentChanged(getRoot(), null);
+ dispatcher.contentChanged(getRoot().fromExternalChange(), null);
}
} finally {
backgroundOperationLock.writeLock().unlock();
Modified: jackrabbit/oak/branches/1.2/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/ClusterTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.2/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/ClusterTest.java?rev=1688633&r1=1688632&r2=1688633&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.2/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/ClusterTest.java (original)
+++ jackrabbit/oak/branches/1.2/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/ClusterTest.java Wed Jul 1 12:35:23 2015
@@ -25,18 +25,31 @@ import static org.junit.Assert.assertTru
import static org.junit.Assert.fail;
import java.util.HashSet;
+import java.util.List;
import java.util.Set;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.mongodb.DB;
+
import org.apache.jackrabbit.mk.api.MicroKernelException;
+import org.apache.jackrabbit.oak.api.CommitFailedException;
import org.apache.jackrabbit.oak.commons.PathUtils;
import org.apache.jackrabbit.oak.plugins.document.memory.MemoryDocumentStore;
import org.apache.jackrabbit.oak.spi.blob.BlobStore;
import org.apache.jackrabbit.oak.spi.blob.MemoryBlobStore;
+import org.apache.jackrabbit.oak.spi.commit.CommitHook;
+import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
+import org.apache.jackrabbit.oak.spi.commit.EmptyHook;
+import org.apache.jackrabbit.oak.spi.commit.Observer;
import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
import org.apache.jackrabbit.oak.spi.state.DefaultNodeStateDiff;
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.jackrabbit.oak.spi.state.NodeStore;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.junit.After;
@@ -51,24 +64,15 @@ public class ClusterTest {
private static final boolean MONGO_DB = false;
// private static final boolean MONGO_DB = true;
+ private List<DocumentMK> mks = Lists.newArrayList();
private MemoryDocumentStore ds;
private MemoryBlobStore bs;
@Test
public void threeNodes() throws Exception {
- MemoryDocumentStore ds = new MemoryDocumentStore();
- MemoryBlobStore bs = new MemoryBlobStore();
- DocumentMK.Builder builder;
-
- builder = new DocumentMK.Builder();
- builder.setDocumentStore(ds).setBlobStore(bs).setAsyncDelay(0);
- DocumentMK mk1 = builder.setClusterId(1).open();
- builder = new DocumentMK.Builder();
- builder.setDocumentStore(ds).setBlobStore(bs).setAsyncDelay(0);
- DocumentMK mk2 = builder.setClusterId(2).open();
- builder = new DocumentMK.Builder();
- builder.setDocumentStore(ds).setBlobStore(bs).setAsyncDelay(0);
- DocumentMK mk3 = builder.setClusterId(3).open();
+ DocumentMK mk1 = createMK(1, 0);
+ DocumentMK mk2 = createMK(2, 0);
+ DocumentMK mk3 = createMK(3, 0);
mk1.commit("/", "+\"test\":{}", null, null);
mk2.commit("/", "+\"a\":{}", null, null);
@@ -115,10 +119,6 @@ public class ClusterTest {
assertEquals(1L, obj.get("x"));
assertEquals(2L, obj.get("y"));
assertEquals(0L, obj.get(":childNodeCount"));
-
- mk1.dispose();
- mk2.dispose();
- mk3.dispose();
}
@Test
@@ -162,12 +162,6 @@ public class ClusterTest {
DocumentMK mk5 = createMK(5, 0, ds, bs);
mk5.commit("/", "-\"a\"", null, null);
mk5.commit("/", "+\"a\": {}", null, null);
-
- mk1.dispose();
- mk2.dispose();
- mk3.dispose();
- mk4.dispose();
- mk5.dispose();
}
@Test
@@ -176,8 +170,6 @@ public class ClusterTest {
DocumentMK mk2 = createMK(0);
assertEquals(1, mk1.getClusterInfo().getId());
assertEquals(2, mk2.getClusterInfo().getId());
- mk1.dispose();
- mk2.dispose();
}
@Test
@@ -192,13 +184,11 @@ public class ClusterTest {
// mk1.merge only becomes visible to mk2 after async delay
// therefore dispose mk1 now to make sure it flushes
// unsaved last revisions
- mk1.dispose();
+ disposeMK(mk1);
DocumentMK mk2 = createMK(2);
String nodes = mk2.getNodes("/", null, 0, 0, 100, null);
assertEquals("{\"branchVisible\":{},\"regular\":{},\":childNodeCount\":2}", nodes);
-
- mk2.dispose();
}
/**
@@ -244,10 +234,6 @@ public class ClusterTest {
assertEquals(1, diff.added.size());
assertEquals(Sets.newHashSet("/mk3"), diff.added);
assertEquals(new HashSet<String>(), diff.deleted);
-
- mk1.dispose();
- mk2.dispose();
- mk3.dispose();
}
@Test
@@ -309,9 +295,6 @@ public class ClusterTest {
String n1 = mk1.getNodes("/", mk1.getHeadRevision(), 0, 0, 10, null);
String n2 = mk2.getNodes("/", mk2.getHeadRevision(), 0, 0, 10, null);
assertEquals(n1, n2);
-
- mk1.dispose();
- mk2.dispose();
}
@Test
@@ -347,9 +330,6 @@ public class ClusterTest {
// so now it should be available
m2h = mk2.getNodes("/", mk2.getHeadRevision(), 0, 0, 5, null);
assertEquals("{\"test\":{},\":childNodeCount\":1}", m2h);
-
- mk1.dispose();
- mk2.dispose();
}
@Test
@@ -368,20 +348,68 @@ public class ClusterTest {
// expected
}
mk2.commit("/", "+\"a\": {}", null, null);
+ }
- mk1.dispose();
- mk2.dispose();
+ @Test
+ public void fromExternalChange() throws Exception {
+ final List<DocumentNodeState> rootStates1 = Lists.newArrayList();
+ DocumentNodeStore ns1 = createMK(1, 0).getNodeStore();
+ ns1.addObserver(new Observer() {
+ @Override
+ public void contentChanged(@Nonnull NodeState root,
+ @Nullable CommitInfo info) {
+ rootStates1.add((DocumentNodeState) root);
+ }
+ });
+ final List<DocumentNodeState> rootStates2 = Lists.newArrayList();
+ DocumentNodeStore ns2 = createMK(2, 0).getNodeStore();
+ ns2.addObserver(new Observer() {
+ @Override
+ public void contentChanged(@Nonnull NodeState root,
+ @Nullable CommitInfo info) {
+ rootStates2.add((DocumentNodeState) root);
+ }
+ });
+ rootStates1.clear();
+ rootStates2.clear();
+
+ NodeBuilder builder = ns1.getRoot().builder();
+ builder.child("foo");
+ merge(ns1, builder);
+
+ assertEquals(1, rootStates1.size());
+ assertEquals(0, rootStates2.size());
+ assertFalse(rootStates1.get(0).isFromExternalChange());
+
+ ns1.runBackgroundOperations();
+ ns2.runBackgroundOperations();
+
+ assertEquals(1, rootStates1.size());
+ assertEquals(1, rootStates2.size());
+ assertTrue(rootStates2.get(0).isFromExternalChange());
+ NodeState foo = rootStates2.get(0).getChildNode("foo");
+ assertTrue(foo instanceof DocumentNodeState);
+ assertTrue(((DocumentNodeState) foo).isFromExternalChange());
}
@Before
@After
public void clear() {
+ for (DocumentMK mk : mks) {
+ mk.dispose();
+ }
+ mks.clear();
if (MONGO_DB) {
DB db = MongoUtils.getConnection().getDB();
MongoUtils.dropCollections(db);
}
}
+ private static NodeState merge(NodeStore store, NodeBuilder builder)
+ throws CommitFailedException {
+ return store.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+ }
+
private DocumentMK createMK(int clusterId) {
return createMK(clusterId, 10);
}
@@ -389,8 +417,8 @@ public class ClusterTest {
private DocumentMK createMK(int clusterId, int asyncDelay) {
if (MONGO_DB) {
DB db = MongoUtils.getConnection().getDB();
- return new DocumentMK.Builder().setMongoDB(db)
- .setClusterId(clusterId).setAsyncDelay(asyncDelay).open();
+ return register(new DocumentMK.Builder().setMongoDB(db)
+ .setClusterId(clusterId).setAsyncDelay(asyncDelay).open());
} else {
if (ds == null) {
ds = new MemoryDocumentStore();
@@ -404,8 +432,23 @@ public class ClusterTest {
private DocumentMK createMK(int clusterId, int asyncDelay,
DocumentStore ds, BlobStore bs) {
- return new DocumentMK.Builder().setDocumentStore(ds).setBlobStore(bs)
- .setClusterId(clusterId).setAsyncDelay(asyncDelay).open();
+ return register(new DocumentMK.Builder().setDocumentStore(ds)
+ .setBlobStore(bs).setClusterId(clusterId)
+ .setAsyncDelay(asyncDelay).open());
+ }
+
+ private DocumentMK register(DocumentMK mk) {
+ mks.add(mk);
+ return mk;
+ }
+
+ private void disposeMK(DocumentMK mk) {
+ mk.dispose();
+ for (int i = 0; i < mks.size(); i++) {
+ if (mks.get(i) == mk) {
+ mks.remove(i);
+ }
+ }
}
private void traverse(NodeState node, String path) {