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 ch...@apache.org on 2016/12/02 06:23:52 UTC
svn commit: r1772305 - in /jackrabbit/oak/trunk/oak-core/src:
main/java/org/apache/jackrabbit/oak/plugins/document/
main/java/org/apache/jackrabbit/oak/plugins/observation/
test/java/org/apache/jackrabbit/oak/plugins/document/
test/java/org/apache/jack...
Author: chetanm
Date: Fri Dec 2 06:23:52 2016
New Revision: 1772305
URL: http://svn.apache.org/viewvc?rev=1772305&view=rev
Log:
OAK-5101 - Enable prefiltering for external changes
Added:
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/ExternalChangesTest.java (with props)
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/JournalDiffLoader.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/JournalEntry.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/ChangeSetBuilder.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/JournalEntryTest.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/observation/ChangeSetBuilderTest.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=1772305&r1=1772304&r2=1772305&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 Dec 2 06:23:52 2016
@@ -36,6 +36,7 @@ import static org.apache.jackrabbit.oak.
import static org.apache.jackrabbit.oak.plugins.document.UpdateOp.Operation;
import static org.apache.jackrabbit.oak.plugins.document.util.Utils.getIdFromPath;
import static org.apache.jackrabbit.oak.plugins.document.util.Utils.pathToId;
+import static org.apache.jackrabbit.oak.plugins.observation.ChangeCollectorProvider.COMMIT_CONTEXT_OBSERVATION_CHANGESET;
import java.io.Closeable;
import java.io.IOException;
@@ -73,6 +74,7 @@ import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.cache.Cache;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
@@ -82,6 +84,7 @@ import org.apache.jackrabbit.api.stats.T
import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.commons.IOUtils;
import org.apache.jackrabbit.oak.commons.jmx.AnnotatedStandardMBean;
+import org.apache.jackrabbit.oak.core.SimpleCommitContext;
import org.apache.jackrabbit.oak.plugins.blob.BlobStoreBlob;
import org.apache.jackrabbit.oak.plugins.blob.MarkSweepGarbageCollector;
import org.apache.jackrabbit.oak.plugins.blob.ReferencedBlob;
@@ -92,6 +95,8 @@ import org.apache.jackrabbit.oak.plugins
import org.apache.jackrabbit.oak.plugins.document.persistentCache.PersistentCache;
import org.apache.jackrabbit.oak.plugins.document.persistentCache.broadcast.DynamicBroadcastConfig;
import org.apache.jackrabbit.oak.plugins.document.util.ReadOnlyDocumentStoreWrapperFactory;
+import org.apache.jackrabbit.oak.plugins.observation.ChangeSet;
+import org.apache.jackrabbit.oak.plugins.observation.ChangeSetBuilder;
import org.apache.jackrabbit.oak.spi.blob.BlobStore;
import org.apache.jackrabbit.oak.commons.json.JsopStream;
import org.apache.jackrabbit.oak.commons.json.JsopWriter;
@@ -107,6 +112,7 @@ import org.apache.jackrabbit.oak.plugins
import org.apache.jackrabbit.oak.plugins.document.util.Utils;
import org.apache.jackrabbit.oak.spi.blob.GarbageCollectableBlobStore;
import org.apache.jackrabbit.oak.spi.commit.ChangeDispatcher;
+import org.apache.jackrabbit.oak.spi.commit.CommitContext;
import org.apache.jackrabbit.oak.spi.commit.Observable;
import org.apache.jackrabbit.oak.spi.commit.CommitHook;
import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
@@ -217,6 +223,10 @@ public final class DocumentNodeStore
protected int maxBackOffMillis =
Integer.getInteger("oak.maxBackOffMS", asyncDelay * 2);
+ protected int changeSetMaxItems = Integer.getInteger("oak.document.changeSet.maxItems", 50);
+
+ protected int changeSetMaxDepth = Integer.getInteger("oak.document.changeSet.maxDepth", 9);
+
/**
* Whether this instance is disposed.
*/
@@ -586,6 +596,7 @@ public final class DocumentNodeStore
journalCache = builder.getJournalCache();
this.mbean = createMBean();
+ LOG.info("ChangeSetBuilder enabled and size set to maxItems: {}, maxDepth: {}", changeSetMaxItems, changeSetMaxDepth);
LOG.info("Initialized DocumentNodeStore with clusterNodeId: {} ({})", clusterId,
getClusterNodeInfoDisplayString());
@@ -776,6 +787,7 @@ public final class DocumentNodeStore
c.applyToCache(before, false);
// track modified paths
changes.modified(c.getModifiedPaths());
+ changes.addChangeSet(getChangeSet(info));
// update head revision
newHead[0] = before.update(c.getRevision());
setRoot(newHead[0]);
@@ -825,6 +837,22 @@ public final class DocumentNodeStore
return maxBackOffMillis;
}
+ public int getChangeSetMaxItems() {
+ return changeSetMaxItems;
+ }
+
+ public void setChangeSetMaxItems(int changeSetMaxItems) {
+ this.changeSetMaxItems = changeSetMaxItems;
+ }
+
+ public int getChangeSetMaxDepth() {
+ return changeSetMaxDepth;
+ }
+
+ public void setChangeSetMaxDepth(int changeSetMaxDepth) {
+ this.changeSetMaxDepth = changeSetMaxDepth;
+ }
+
void setEnableConcurrentAddRemove(boolean b) {
enableConcurrentAddRemove = b;
}
@@ -1919,6 +1947,7 @@ public final class DocumentNodeStore
Map<Integer, Revision> lastRevMap = doc.getLastRev();
try {
+ ChangeSetBuilder changeSetBuilder = newChangeSetBuilder();
RevisionVector headRevision = getHeadRevision();
Set<Revision> externalChanges = Sets.newHashSet();
for (Map.Entry<Integer, Revision> e : lastRevMap.entrySet()) {
@@ -1942,7 +1971,7 @@ public final class DocumentNodeStore
if (externalSort != null) {
// add changes for this particular clusterId to the externalSort
try {
- fillExternalChanges(externalSort, last, r, store);
+ fillExternalChanges(externalSort, PathUtils.ROOT_PATH, last, r, store, changeSetBuilder);
} catch (IOException e1) {
LOG.error("backgroundRead: Exception while reading external changes from journal: " + e1, e1);
IOUtils.closeQuietly(externalSort);
@@ -1999,7 +2028,9 @@ public final class DocumentNodeStore
stats.populateDiffCache = clock.getTime() - time;
time = clock.getTime();
- dispatcher.contentChanged(getRoot().fromExternalChange(), CommitInfo.EMPTY_EXTERNAL);
+ ChangeSet changeSet = changeSetBuilder.build();
+ LOG.debug("Dispatching external change with ChangeSet {}", changeSet);
+ dispatcher.contentChanged(getRoot().fromExternalChange(), newCommitInfo(changeSet));
} finally {
backgroundOperationLock.writeLock().unlock();
}
@@ -2012,6 +2043,25 @@ public final class DocumentNodeStore
return stats;
}
+ private static CommitInfo newCommitInfo(@Nonnull ChangeSet changeSet) {
+ CommitContext commitContext = new SimpleCommitContext();
+ commitContext.set(COMMIT_CONTEXT_OBSERVATION_CHANGESET, changeSet);
+ Map<String, Object> info = ImmutableMap.<String, Object>of(CommitContext.NAME, commitContext);
+ return new CommitInfo(CommitInfo.OAK_UNKNOWN, CommitInfo.OAK_UNKNOWN, info, true);
+ }
+
+ private static ChangeSet getChangeSet(CommitInfo info) {
+ CommitContext commitContext = (CommitContext) info.getInfo().get(CommitContext.NAME);
+ if (commitContext == null){
+ return null;
+ }
+ return (ChangeSet) commitContext.get(COMMIT_CONTEXT_OBSERVATION_CHANGESET);
+ }
+
+ private ChangeSetBuilder newChangeSetBuilder() {
+ return new ChangeSetBuilder(changeSetMaxItems, changeSetMaxDepth);
+ }
+
private void cleanOrphanedBranches() {
Branch b;
while ((b = branches.pollOrphanedBranch()) != null) {
@@ -2134,7 +2184,7 @@ public final class DocumentNodeStore
}
private JournalEntry newJournalEntry() {
- return new JournalEntry(store, true);
+ return new JournalEntry(store, true, newChangeSetBuilder());
}
/**
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/JournalDiffLoader.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/JournalDiffLoader.java?rev=1772305&r1=1772304&r2=1772305&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/JournalDiffLoader.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/JournalDiffLoader.java Fri Dec 2 06:23:52 2016
@@ -159,7 +159,7 @@ class JournalDiffLoader implements DiffC
// use revision with a timestamp of zero
from = new Revision(0, 0, to.getClusterId());
}
- stats.numJournalEntries += fillExternalChanges(changes, path, from, to, ns.getDocumentStore());
+ stats.numJournalEntries += fillExternalChanges(changes, path, from, to, ns.getDocumentStore(), null);
}
// do we need to include changes from pending local changes?
if (!max.isRevisionNewer(localLastRev)
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=1772305&r1=1772304&r2=1772305&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 Dec 2 06:23:52 2016
@@ -26,6 +26,7 @@ import java.util.Set;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
import com.google.common.collect.AbstractIterator;
import com.google.common.collect.Lists;
@@ -37,6 +38,8 @@ 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.util.Utils;
+import org.apache.jackrabbit.oak.plugins.observation.ChangeSet;
+import org.apache.jackrabbit.oak.plugins.observation.ChangeSetBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -63,6 +66,8 @@ public final class JournalEntry extends
private static final String CHANGES = "_c";
+ private static final String CHANGE_SET = "_cs";
+
private static final String BRANCH_COMMITS = "_bc";
public static final String MODIFIED = "_modified";
@@ -77,17 +82,20 @@ public final class JournalEntry extends
private final DocumentStore store;
+ private final ChangeSetBuilder changeSetBuilder;
+
private volatile TreeNode changes = null;
private boolean concurrent;
JournalEntry(DocumentStore store) {
- this(store, false);
+ this(store, false, null);
}
- JournalEntry(DocumentStore store, boolean concurrent) {
+ JournalEntry(DocumentStore store, boolean concurrent, ChangeSetBuilder changeSetBuilder) {
this.store = store;
this.concurrent = concurrent;
+ this.changeSetBuilder = changeSetBuilder;
}
static StringSort newSorter() {
@@ -207,7 +215,7 @@ public final class JournalEntry extends
@Nonnull Revision to,
@Nonnull DocumentStore store)
throws IOException {
- return fillExternalChanges(sorter, PathUtils.ROOT_PATH, from, to, store);
+ return fillExternalChanges(sorter, PathUtils.ROOT_PATH, from, to, store, null);
}
/**
@@ -225,6 +233,8 @@ public final class JournalEntry extends
* @param from the lower bound of the revision range (exclusive).
* @param to the upper bound of the revision range (inclusive).
* @param store the document store to query.
+ * @param changeSetBuilder a nullable ChangeSetBuilder to collect changes from
+ * the JournalEntry between given revisions *
* @return the number of journal entries read from the store.
* @throws IOException
*/
@@ -232,7 +242,8 @@ public final class JournalEntry extends
@Nonnull String path,
@Nonnull Revision from,
@Nonnull Revision to,
- @Nonnull DocumentStore store)
+ @Nonnull DocumentStore store,
+ @Nullable ChangeSetBuilder changeSetBuilder)
throws IOException {
checkNotNull(path);
checkArgument(checkNotNull(from).getClusterId() == checkNotNull(to).getClusterId());
@@ -271,6 +282,9 @@ public final class JournalEntry extends
for (JournalEntry d : partialResult) {
d.addTo(sorter, path);
+ if (changeSetBuilder != null) {
+ d.addTo(changeSetBuilder);
+ }
}
if (partialResult.size() < READ_CHUNK_SIZE) {
break;
@@ -312,6 +326,34 @@ public final class JournalEntry extends
}
}
+ void addChangeSet(@Nullable ChangeSet changeSet){
+ if (changeSet == null){
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Null changeSet found for caller. ChangeSetBuilder would be set to overflow mode",
+ new Exception());
+ }
+ }
+ changeSetBuilder.add(changeSet);
+ }
+
+ private void addTo(ChangeSetBuilder changeSetBuilder) {
+ String cs = (String) get(CHANGE_SET);
+ ChangeSet set = null;
+
+ if (cs == null && getChanges().keySet().isEmpty()){
+ //Purely a branch commit. So ChangeSet can be empty
+ return;
+ }
+
+ if (cs != null) {
+ set = ChangeSet.fromString(cs);
+ } else {
+ LOG.debug("Null changeSet found for JournalEntry {}. ChangeSetBuilder would be set to overflow mode", getId());
+ }
+
+ changeSetBuilder.add(set);
+ }
+
void branchCommit(@Nonnull Iterable<Revision> revisions) {
String branchCommits = (String) get(BRANCH_COMMITS);
if (branchCommits == null) {
@@ -330,6 +372,12 @@ public final class JournalEntry extends
String id = asId(revision);
UpdateOp op = new UpdateOp(id, true);
op.set(CHANGES, getChanges().serialize());
+
+ //For branch commits builder would be null
+ if (changeSetBuilder != null) {
+ op.set(CHANGE_SET, changeSetBuilder.build().asString());
+ }
+
// OAK-3085 : introduce a timestamp property
// for later being used by OAK-3001
op.set(MODIFIED, revision.getTimestamp());
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/ChangeSetBuilder.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/ChangeSetBuilder.java?rev=1772305&r1=1772304&r2=1772305&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/ChangeSetBuilder.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/ChangeSetBuilder.java Fri Dec 2 06:23:52 2016
@@ -20,6 +20,8 @@ package org.apache.jackrabbit.oak.plugin
import java.util.Set;
+import javax.annotation.Nullable;
+
import com.google.common.collect.Sets;
import org.apache.jackrabbit.oak.commons.PathUtils;
@@ -117,7 +119,16 @@ public class ChangeSetBuilder {
return maxPathDepth;
}
- public ChangeSetBuilder add(ChangeSet cs){
+ public ChangeSetBuilder add(@Nullable ChangeSet cs){
+ if (cs == null){
+ parentPathOverflow = true;
+ parentNodeNameOverflow = true;
+ parentNodeTypeOverflow = true;
+ propertyNameOverflow = true;
+ allNodeTypeOverflow = true;
+ return this;
+ }
+
if (cs.getParentPaths() == null){
parentPathOverflow = true;
} else {
Added: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/ExternalChangesTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/ExternalChangesTest.java?rev=1772305&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/ExternalChangesTest.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/ExternalChangesTest.java Fri Dec 2 06:23:52 2016
@@ -0,0 +1,207 @@
+/*
+ * 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.document;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.annotation.Nonnull;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import org.apache.jackrabbit.oak.core.SimpleCommitContext;
+import org.apache.jackrabbit.oak.plugins.document.memory.MemoryDocumentStore;
+import org.apache.jackrabbit.oak.plugins.observation.ChangeCollectorProvider;
+import org.apache.jackrabbit.oak.plugins.observation.ChangeSet;
+import org.apache.jackrabbit.oak.spi.commit.CommitContext;
+import org.apache.jackrabbit.oak.spi.commit.CommitHook;
+import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
+import org.apache.jackrabbit.oak.spi.commit.EditorHook;
+import org.apache.jackrabbit.oak.spi.commit.EmptyHook;
+import org.apache.jackrabbit.oak.spi.commit.Observer;
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+public class ExternalChangesTest {
+ @Rule
+ public final DocumentMKBuilderProvider builderProvider = new DocumentMKBuilderProvider();
+
+ private DocumentNodeStore ns1;
+ private DocumentNodeStore ns2;
+
+ private CommitInfoCollector c1 = new CommitInfoCollector();
+ private CommitInfoCollector c2 = new CommitInfoCollector();
+
+ @Before
+ public void setUp() {
+ MemoryDocumentStore store = new MemoryDocumentStore();
+ ns1 = newDocumentNodeStore(store, 1);
+ ns2 = newDocumentNodeStore(store, 2);
+
+ ns1.addObserver(c1);
+ ns2.addObserver(c2);
+ }
+
+ @Test
+ public void defaultConfig() throws Exception{
+ assertEquals(50, ns1.getChangeSetMaxItems());
+ assertEquals(9, ns1.getChangeSetMaxDepth());
+ }
+
+ @Test
+ public void changeSetForExternalChanges() throws Exception{
+ NodeBuilder b1 = ns1.getRoot().builder();
+ b1.child("a");
+ b1.setProperty("foo1", "bar");
+ ns1.merge(b1, newCollectingHook(), newCommitInfo());
+
+ NodeBuilder b2 = ns1.getRoot().builder();
+ b2.child("b");
+ b2.setProperty("foo2", "bar");
+ ns1.merge(b2, newCollectingHook(), newCommitInfo());
+
+ ns1.backgroundWrite();
+
+ c2.reset();
+ ns2.backgroundRead();
+
+ CommitInfo ci = c2.getExternalChange();
+ CommitContext cc = (CommitContext) ci.getInfo().get(CommitContext.NAME);
+ assertNotNull(cc);
+ ChangeSet cs = (ChangeSet) cc.get(ChangeCollectorProvider.COMMIT_CONTEXT_OBSERVATION_CHANGESET);
+ assertNotNull(cs);
+ assertFalse(cs.anyOverflow());
+ assertThat(cs.getPropertyNames(), containsInAnyOrder("foo1", "foo2"));
+ }
+
+ @Test
+ public void missingChangeSetResultsInOverflow() throws Exception{
+ NodeBuilder b1 = ns1.getRoot().builder();
+ b1.child("a");
+ b1.setProperty("foo1", "bar");
+ ns1.merge(b1, newCollectingHook(), newCommitInfo());
+
+ NodeBuilder b2 = ns1.getRoot().builder();
+ b2.child("b");
+ b2.setProperty("foo2", "bar");
+ //Commit without ChangeSet
+ ns1.merge(b2, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+
+ ns1.backgroundWrite();
+
+ c2.reset();
+ ns2.backgroundRead();
+
+ CommitInfo ci = c2.getExternalChange();
+ CommitContext cc = (CommitContext) ci.getInfo().get(CommitContext.NAME);
+ assertNotNull(cc);
+ ChangeSet cs = (ChangeSet) cc.get(ChangeCollectorProvider.COMMIT_CONTEXT_OBSERVATION_CHANGESET);
+ assertNotNull(cs);
+
+ //ChangeSet should result in overflow
+ assertTrue(cs.anyOverflow());
+ }
+
+ @Test
+ public void changeSetForBranchCommit() throws Exception{
+ final int NUM_NODES = DocumentRootBuilder.UPDATE_LIMIT / 2;
+ final int NUM_PROPS = 10;
+
+ Set<String> propNames = Sets.newHashSet();
+ NodeBuilder b1 = ns1.getRoot().builder();
+ for (int i = 0; i < NUM_NODES; i++) {
+ NodeBuilder c = b1.child("n" + i);
+ for (int j = 0; j < NUM_PROPS; j++) {
+ c.setProperty("q" + j, "value");
+ c.setProperty("p" + j, "value");
+ propNames.add("q" + j);
+ propNames.add("p" + j);
+ }
+ }
+
+ ns1.merge(b1, newCollectingHook(), newCommitInfo());
+ ns1.backgroundWrite();
+
+ c2.reset();
+ ns2.backgroundRead();
+
+ CommitInfo ci = c2.getExternalChange();
+ CommitContext cc = (CommitContext) ci.getInfo().get(CommitContext.NAME);
+ assertNotNull(cc);
+ ChangeSet cs = (ChangeSet) cc.get(ChangeCollectorProvider.COMMIT_CONTEXT_OBSERVATION_CHANGESET);
+ assertNotNull(cs);
+ assertTrue(cs.getPropertyNames().containsAll(propNames));
+ }
+
+ private CommitHook newCollectingHook(){
+ return new EditorHook(new ChangeCollectorProvider());
+ }
+
+ private CommitInfo newCommitInfo(){
+ Map<String, Object> info = ImmutableMap.<String, Object>of(CommitContext.NAME, new SimpleCommitContext());
+ return new CommitInfo(CommitInfo.OAK_UNKNOWN, CommitInfo.OAK_UNKNOWN, info);
+ }
+
+ private DocumentNodeStore newDocumentNodeStore(DocumentStore store, int clusterId) {
+ return builderProvider.newBuilder()
+ .setAsyncDelay(0)
+ .setDocumentStore(store)
+ .setLeaseCheck(false) // disabled for debugging purposes
+ .setClusterId(clusterId)
+ .getNodeStore();
+ }
+
+ private static class CommitInfoCollector implements Observer {
+ List<CommitInfo> infos = Lists.newArrayList();
+
+ @Override
+ public void contentChanged(@Nonnull NodeState root, @Nonnull CommitInfo info) {
+ infos.add(info);
+ }
+
+ public CommitInfo getExternalChange(){
+ List<CommitInfo> result = Lists.newArrayList();
+ for (CommitInfo info : infos){
+ if (info.isExternal()) {
+ result.add(info);
+ }
+ }
+ assertEquals(1, result.size());
+ return result.get(0);
+ }
+
+ void reset(){
+ infos.clear();
+ }
+ }
+}
Propchange: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/ExternalChangesTest.java
------------------------------------------------------------------------------
svn:eol-style = native
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=1772305&r1=1772304&r2=1772305&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 Dec 2 06:23:52 2016
@@ -248,7 +248,7 @@ public class JournalEntryTest {
assertTrue(store.create(JOURNAL, Collections.singletonList(op)));
StringSort sort = JournalEntry.newSorter();
- JournalEntry.fillExternalChanges(sort, "/foo", r1, r2, store);
+ JournalEntry.fillExternalChanges(sort, "/foo", r1, r2, store, null);
assertEquals(4, sort.getSize());
sort.close();
}
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/observation/ChangeSetBuilderTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/observation/ChangeSetBuilderTest.java?rev=1772305&r1=1772304&r2=1772305&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/observation/ChangeSetBuilderTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/observation/ChangeSetBuilderTest.java Fri Dec 2 06:23:52 2016
@@ -195,6 +195,20 @@ public class ChangeSetBuilderTest {
assertEquals(cb2.getMaxPrefilterPathDepth(), cs.getMaxPrefilterPathDepth());
}
+ @Test
+ public void nullChangeSet() throws Exception{
+ ChangeSetBuilder cb1 = new ChangeSetBuilder(10, 8);
+ add(cb1, "1");
+
+ cb1.add(null);
+ ChangeSet cs = cb1.build();
+ assertNull(cs.getParentNodeTypes());
+ assertNull(cs.getParentNodeNames());
+ assertNull(cs.getParentPaths());
+ assertNull(cs.getAllNodeTypes());
+ assertNull(cs.getPropertyNames());
+ }
+
private static void add(ChangeSetBuilder cb, String suffix){
cb.addNodeType("nt-"+suffix)
.addParentPath("p-"+suffix)