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 ba...@apache.org on 2016/09/27 13:34:26 UTC
svn commit: r1762477 - in /jackrabbit/oak/branches/1.4: ./
oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/
oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/
Author: baedke
Date: Tue Sep 27 13:34:26 2016
New Revision: 1762477
URL: http://svn.apache.org/viewvc?rev=1762477&view=rev
Log:
OAK-4528: diff calculation in DocumentNodeStore should try to re-use journal info on diff cache miss
Added:
jackrabbit/oak/branches/1.4/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/JournalDiffLoader.java
- copied unchanged from r1752596, jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/JournalDiffLoader.java
jackrabbit/oak/branches/1.4/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/JsopNodeStateDiffer.java
- copied unchanged from r1752596, jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/JsopNodeStateDiffer.java
jackrabbit/oak/branches/1.4/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/JournalDiffLoaderTest.java
- copied unchanged from r1752596, jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/JournalDiffLoaderTest.java
Modified:
jackrabbit/oak/branches/1.4/ (props changed)
jackrabbit/oak/branches/1.4/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java
jackrabbit/oak/branches/1.4/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/JournalEntry.java
jackrabbit/oak/branches/1.4/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/JournalGarbageCollector.java
jackrabbit/oak/branches/1.4/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/UnmergedBranches.java
jackrabbit/oak/branches/1.4/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreTest.java
jackrabbit/oak/branches/1.4/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/JournalEntryTest.java
jackrabbit/oak/branches/1.4/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/JournalGCTest.java
jackrabbit/oak/branches/1.4/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/SimpleTest.java
Propchange: jackrabbit/oak/branches/1.4/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Tue Sep 27 13:34:26 2016
@@ -1,3 +1,3 @@
/jackrabbit/oak/branches/1.0:1665962
-/jackrabbit/oak/trunk:1733615,1733875,1733913,1733929,1734230,1734254,1734279,1734941,1735052,1735081,1735141,1735267,1735405,1735484,1735549,1735564,1735588,1735622,1735638,1735919,1735983,1736176,1737309-1737310,1737334,1737349,1737998,1738004,1738136,1738138,1738207,1738234,1738252,1738775,1738795,1738833,1738950,1738957,1738963,1739712,1739760,1739867,1739894,1739959-1739960,1740114,1740116,1740250,1740333,1740360,1740625-1740626,1740774,1740837,1740971,1741016,1741032,1741339,1741343,1742077,1742117,1742363,1742520,1742888,1742916,1743097,1743172,1743343,1743674,1744265,1744292,1744589,1744670,1744672,1744959,1745038,1745127,1745197,1745336,1745368,1746086,1746117,1746342,1746345,1746408,1746696,1746981,1747198,1747200,1747341-1747342,1747380,1747387,1747406,1747492,1747512,1747654,1748505,1748553,1748722,1748870,1749275,1749350,1749424,1749443,1749464,1749475,1749645,1749662,1749815,1749872,1749875,1749899,1750052,1750076-1750077,1750287,1750457,1750462,1750465,1750495,1750626
,1750809,1750886,1751410,1751445-1751446,1751478,1751755,1751871,1752198,1752202,1752259,1752273-1752274,1752283,1752292,1752438,1752447-1752448,1752508,1752616,1752659,1752672,1753262,1753331-1753332,1753355,1753444,1754117,1754239,1755157,1756520,1756580,1757119,1757166,1759433,1760340,1760373,1760387,1760661-1760662,1761412,1761444,1761571,1761762,1761787
+/jackrabbit/oak/trunk:1733615,1733875,1733913,1733929,1734230,1734254,1734279,1734941,1735052,1735081,1735141,1735267,1735405,1735484,1735549,1735564,1735588,1735622,1735638,1735919,1735983,1736176,1737309-1737310,1737334,1737349,1737998,1738004,1738136,1738138,1738207,1738234,1738252,1738775,1738795,1738833,1738950,1738957,1738963,1739712,1739760,1739867,1739894,1739959-1739960,1740114,1740116,1740250,1740333,1740360,1740625-1740626,1740774,1740837,1740971,1741016,1741032,1741339,1741343,1742077,1742117,1742363,1742520,1742888,1742916,1743097,1743172,1743343,1743674,1744265,1744292,1744589,1744670,1744672,1744959,1745038,1745127,1745197,1745336,1745368,1746086,1746117,1746342,1746345,1746408,1746696,1746981,1747198,1747200,1747341-1747342,1747380,1747387,1747406,1747492,1747512,1747654,1748505,1748553,1748722,1748870,1749275,1749350,1749424,1749443,1749464,1749475,1749645,1749662,1749815,1749872,1749875,1749899,1750052,1750076-1750077,1750287,1750457,1750462,1750465,1750495,1750626
,1750809,1750886,1751410,1751445-1751446,1751478,1751755,1751871,1752198,1752202,1752259,1752273-1752274,1752283,1752292,1752438,1752447-1752448,1752508,1752596,1752616,1752659,1752672,1753262,1753331-1753332,1753355,1753444,1754117,1754239,1755157,1756520,1756580,1757119,1757166,1759433,1760340,1760373,1760387,1760661-1760662,1761412,1761444,1761571,1761762,1761787
/jackrabbit/trunk:1345480
Modified: jackrabbit/oak/branches/1.4/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.4/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java?rev=1762477&r1=1762476&r2=1762477&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.4/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java (original)
+++ jackrabbit/oak/branches/1.4/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java Tue Sep 27 13:34:26 2016
@@ -147,6 +147,12 @@ public final class DocumentNodeStore
Boolean.parseBoolean(System.getProperty("oak.fairBackgroundOperationLock", "true"));
/**
+ * Feature flag to disable the journal diff mechanism. See OAK-4528.
+ */
+ private boolean disableJournalDiff =
+ Boolean.getBoolean("oak.disableJournalDiff");
+
+ /**
* The document store (might be used by multiple node stores).
*/
protected final DocumentStore store;
@@ -1454,22 +1460,22 @@ public final class DocumentNodeStore
*/
@Override
public boolean compare(@Nonnull final AbstractDocumentNodeState node,
- @Nonnull final AbstractDocumentNodeState base,
- @Nonnull NodeStateDiff diff) {
+ @Nonnull final AbstractDocumentNodeState base,
+ @Nonnull NodeStateDiff diff) {
if (!AbstractNodeState.comparePropertiesAgainstBaseState(node, base, diff)) {
return false;
}
if (node.hasNoChildren() && base.hasNoChildren()) {
return true;
}
- return dispatch(diffCache.getChanges(base.getRootRevision(),
+ return new JsopNodeStateDiffer(diffCache.getChanges(base.getRootRevision(),
node.getRootRevision(), node.getPath(),
new DiffCache.Loader() {
@Override
public String call() {
return diffImpl(base, node);
}
- }), node, base, diff);
+ })).withoutPropertyChanges().compare(node, base, diff);
}
/**
@@ -2165,47 +2171,6 @@ public final class DocumentNodeStore
}
}
- private boolean dispatch(@Nonnull final String jsonDiff,
- @Nonnull final AbstractDocumentNodeState node,
- @Nonnull final AbstractDocumentNodeState base,
- @Nonnull final NodeStateDiff diff) {
- return DiffCache.parseJsopDiff(jsonDiff, new DiffCache.Diff() {
- @Override
- public boolean childNodeAdded(String name) {
- return diff.childNodeAdded(name,
- node.getChildNode(name));
- }
-
- @Override
- public boolean childNodeChanged(String name) {
- boolean continueComparison = true;
- NodeState baseChild = base.getChildNode(name);
- NodeState nodeChild = node.getChildNode(name);
- if (baseChild.exists()) {
- if (nodeChild.exists()) {
- continueComparison = diff.childNodeChanged(name,
- baseChild, nodeChild);
- } else {
- continueComparison = diff.childNodeDeleted(name,
- baseChild);
- }
- } else {
- if (nodeChild.exists()) {
- continueComparison = diff.childNodeAdded(name,
- nodeChild);
- }
- }
- return continueComparison;
- }
-
- @Override
- public boolean childNodeDeleted(String name) {
- return diff.childNodeDeleted(name,
- base.getChildNode(name));
- }
- });
- }
-
/**
* Search for presence of child node as denoted by path in the children cache of parent
*
@@ -2248,44 +2213,54 @@ public final class DocumentNodeStore
private String diffImpl(AbstractDocumentNodeState from, AbstractDocumentNodeState to)
throws DocumentStoreException {
- JsopWriter w = new JsopStream();
- // TODO this does not work well for large child node lists
- // use a document store index instead
int max = MANY_CHILDREN_THRESHOLD;
final boolean debug = LOG.isDebugEnabled();
final long start = debug ? now() : 0;
+ long getChildrenDoneIn = start;
- DocumentNodeState.Children fromChildren, toChildren;
- fromChildren = getChildren(from, null, max);
- toChildren = getChildren(to, null, max);
-
- final long getChildrenDoneIn = debug ? now() : 0;
-
+ String diff;
String diffAlgo;
RevisionVector fromRev = from.getLastRevision();
RevisionVector toRev = to.getLastRevision();
- if (!fromChildren.hasMore && !toChildren.hasMore) {
- diffAlgo = "diffFewChildren";
- diffFewChildren(w, from.getPath(), fromChildren,
- fromRev, toChildren, toRev);
+ long minTimestamp = Utils.getMinTimestampForDiff(
+ fromRev, toRev, getMinExternalRevisions());
+
+ // use journal if possible
+ Revision tailRev = journalGarbageCollector.getTailRevision();
+ if (!disableJournalDiff
+ && tailRev.getTimestamp() < minTimestamp) {
+ diffAlgo = "diffJournalChildren";
+ diff = new JournalDiffLoader(from, to, this).call();
} else {
- if (FAST_DIFF) {
- diffAlgo = "diffManyChildren";
- fromRev = from.getRootRevision();
- toRev = to.getRootRevision();
- diffManyChildren(w, from.getPath(), fromRev, toRev);
- } else {
- diffAlgo = "diffAllChildren";
- max = Integer.MAX_VALUE;
- fromChildren = getChildren(from, null, max);
- toChildren = getChildren(to, null, max);
+ DocumentNodeState.Children fromChildren, toChildren;
+ fromChildren = getChildren(from, null, max);
+ toChildren = getChildren(to, null, max);
+ getChildrenDoneIn = debug ? now() : 0;
+
+ JsopWriter w = new JsopStream();
+ if (!fromChildren.hasMore && !toChildren.hasMore) {
+ diffAlgo = "diffFewChildren";
diffFewChildren(w, from.getPath(), fromChildren,
fromRev, toChildren, toRev);
+ } else {
+ if (FAST_DIFF) {
+ diffAlgo = "diffManyChildren";
+ fromRev = from.getRootRevision();
+ toRev = to.getRootRevision();
+ diffManyChildren(w, from.getPath(), fromRev, toRev);
+ } else {
+ diffAlgo = "diffAllChildren";
+ max = Integer.MAX_VALUE;
+ fromChildren = getChildren(from, null, max);
+ toChildren = getChildren(to, null, max);
+ diffFewChildren(w, from.getPath(), fromChildren,
+ fromRev, toChildren, toRev);
+ }
}
+ diff = w.toString();
}
- String diff = w.toString();
if (debug) {
long end = now();
LOG.debug("Diff performed via '{}' at [{}] between revisions [{}] => [{}] took {} ms ({} ms), diff '{}', external '{}",
Modified: jackrabbit/oak/branches/1.4/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/JournalEntry.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.4/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/JournalEntry.java?rev=1762477&r1=1762476&r2=1762477&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.4/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/JournalEntry.java (original)
+++ jackrabbit/oak/branches/1.4/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/JournalEntry.java Tue Sep 27 13:34:26 2016
@@ -175,7 +175,9 @@ public final class JournalEntry extends
/**
* Reads all external changes between the two given revisions (with the same
* clusterId) from the journal and appends the paths therein to the provided
- * sorter.
+ * sorter. If there is no exact match of a journal entry for the given
+ * {@code to} revision, this method will fill external changes from the
+ * next higher journal entry that contains the revision.
*
* @param sorter the StringSort to which all externally changed paths
* between the provided revisions will be added
@@ -191,6 +193,10 @@ public final class JournalEntry extends
throws IOException {
checkArgument(checkNotNull(from).getClusterId() == checkNotNull(to).getClusterId());
+ if (from.compareRevisionTime(to) >= 0) {
+ return;
+ }
+
// to is inclusive, but DocumentStore.query() toKey is exclusive
final String inclusiveToId = asId(to);
to = new Revision(to.getTimestamp(), to.getCounter() + 1,
@@ -203,6 +209,8 @@ public final class JournalEntry extends
// limit, then loop and do subsequent queries
final String toId = asId(to);
String fromId = asId(from);
+ int numEntries = 0;
+ JournalEntry lastEntry = null;
while (true) {
if (fromId.equals(inclusiveToId)) {
// avoid query if from and to are off by just 1 counter (which
@@ -212,6 +220,10 @@ public final class JournalEntry extends
break;
}
List<JournalEntry> partialResult = store.query(JOURNAL, fromId, toId, READ_CHUNK_SIZE);
+ numEntries += partialResult.size();
+ if (!partialResult.isEmpty()) {
+ lastEntry = partialResult.get(partialResult.size() - 1);
+ }
for (JournalEntry d : partialResult) {
d.addTo(sorter);
@@ -224,6 +236,16 @@ public final class JournalEntry extends
// include the from which we'd otherwise double-process)
fromId = partialResult.get(partialResult.size() - 1).getId();
}
+ // check if last processed journal entry covers toId, otherwise
+ // read next document. also read next journal entry when none
+ // were read so far
+ if (numEntries == 0
+ || (lastEntry != null && !lastEntry.getId().equals(inclusiveToId))) {
+ String maxId = asId(new Revision(Long.MAX_VALUE, 0, to.getClusterId()));
+ for (JournalEntry d : store.query(JOURNAL, inclusiveToId, maxId, 1)) {
+ d.addTo(sorter);
+ }
+ }
}
long getRevisionTimestamp() {
Modified: jackrabbit/oak/branches/1.4/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/JournalGarbageCollector.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.4/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/JournalGarbageCollector.java?rev=1762477&r1=1762476&r2=1762477&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.4/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/JournalGarbageCollector.java (original)
+++ jackrabbit/oak/branches/1.4/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/JournalGarbageCollector.java Tue Sep 27 13:34:26 2016
@@ -22,11 +22,14 @@ import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
+import org.apache.jackrabbit.oak.plugins.document.util.Utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Stopwatch;
+import static org.apache.jackrabbit.oak.plugins.document.Collection.SETTINGS;
+
/**
* The JournalGarbageCollector can clean up JournalEntries that are older than a
* particular age.
@@ -38,12 +41,27 @@ import com.google.common.base.Stopwatch;
*/
public class JournalGarbageCollector {
+ private static final Logger log = LoggerFactory.getLogger(JournalGarbageCollector.class);
+
+ /**
+ * ID of the journalGC document in the settings collection.
+ */
+ private static final String JOURNAL_GC_ID = "journalGC";
+
+ /**
+ * Key name of the entry that contains the timestamp of the journal tail.
+ */
+ private static final String TAIL_TIMESTAMP = "tailTimestamp";
+
private final DocumentNodeStore ns;
- private static final Logger log = LoggerFactory.getLogger(JournalGarbageCollector.class);
+ private volatile long lastTailTimestampRefresh = Long.MIN_VALUE;
+
+ private Revision tailRevision;
public JournalGarbageCollector(DocumentNodeStore nodeStore) {
this.ns = nodeStore;
+ this.tailRevision = new Revision(0, 0, ns.getClusterId());
}
/**
@@ -89,6 +107,10 @@ public class JournalGarbageCollector {
// will compete at deletion, which is not optimal
// due to performance, but does not harm.
+ // update the tail timestamp in the journalGC document
+ // of the settings collection
+ updateTailTimestamp(gcOlderThan);
+
// 1. get the list of cluster node ids
final List<ClusterNodeInfoDocument> clusterNodeInfos = ClusterNodeInfoDocument.all(ds);
int numDeleted = 0;
@@ -139,6 +161,36 @@ public class JournalGarbageCollector {
return numDeleted;
}
+ private void updateTailTimestamp(long gcOlderThan) {
+ UpdateOp op = new UpdateOp(JOURNAL_GC_ID, true);
+ op.max(TAIL_TIMESTAMP, gcOlderThan);
+ ns.getDocumentStore().createOrUpdate(SETTINGS, op);
+ }
+
+ public Revision getTailRevision() {
+ refreshTailRevisionIfNecessary();
+ return tailRevision;
+ }
+
+ private void refreshTailRevisionIfNecessary() {
+ // refresh once a minute
+ long now = ns.getClock().getTime();
+ if (lastTailTimestampRefresh + TimeUnit.MINUTES.toMillis(1) > now) {
+ return;
+ }
+ lastTailTimestampRefresh = now;
+
+ Document doc = ns.getDocumentStore().find(SETTINGS, JOURNAL_GC_ID);
+ if (doc == null) {
+ // no gc yet
+ return;
+ }
+ Long ts = Utils.asLong((Number) doc.get(TAIL_TIMESTAMP));
+ if (ts != null) {
+ tailRevision = Utils.max(tailRevision, new Revision(ts, 0, ns.getClusterId()));
+ }
+ }
+
private List<String> asKeys(List<JournalEntry> deletionBatch) {
final List<String> keys = new ArrayList<String>(deletionBatch.size());
for (JournalEntry e : deletionBatch) {
Modified: jackrabbit/oak/branches/1.4/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/UnmergedBranches.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.4/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/UnmergedBranches.java?rev=1762477&r1=1762476&r2=1762477&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.4/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/UnmergedBranches.java (original)
+++ jackrabbit/oak/branches/1.4/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/UnmergedBranches.java Tue Sep 27 13:34:26 2016
@@ -138,6 +138,26 @@ class UnmergedBranches {
}
/**
+ * Returns {@code true} if the given revision is the base of an unmerged
+ * branch.
+ *
+ * @param r the base revision of a branch.
+ * @return {@code true} if such a branch exists, {@code false} otherwise.
+ */
+ boolean isBranchBase(@Nonnull RevisionVector r) {
+ if (!r.isBranch()) {
+ return false;
+ }
+ RevisionVector base = r.asTrunkRevision();
+ for (Branch b : branches) {
+ if (b.getBase().equals(base)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
* Returns the branch commit with the given revision or {@code null} if
* it doesn't exists.
*
Modified: jackrabbit/oak/branches/1.4/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.4/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreTest.java?rev=1762477&r1=1762476&r2=1762477&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.4/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreTest.java (original)
+++ jackrabbit/oak/branches/1.4/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreTest.java Tue Sep 27 13:34:26 2016
@@ -2173,6 +2173,10 @@ public class DocumentNodeStoreTest {
// OAK-1970
@Test
public void diffMany() throws Exception {
+ // make sure diffMany is used and not the new
+ // journal diff introduced with OAK-4528
+ System.setProperty("oak.disableJournalDiff", "true");
+
Clock clock = new Clock.Virtual();
clock.waitUntil(System.currentTimeMillis());
Revision.setClock(clock);
@@ -2233,6 +2237,8 @@ public class DocumentNodeStoreTest {
// startValue must be based on the revision of the before state
// and not when '/test' was last modified
assertEquals(beforeModified, (long) startValues.get(0));
+
+ System.clearProperty("oak.disableJournalDiff");
}
// OAK-2620
Modified: jackrabbit/oak/branches/1.4/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/JournalEntryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.4/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/JournalEntryTest.java?rev=1762477&r1=1762476&r2=1762477&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.4/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/JournalEntryTest.java (original)
+++ jackrabbit/oak/branches/1.4/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/JournalEntryTest.java Tue Sep 27 13:34:26 2016
@@ -136,6 +136,76 @@ public class JournalEntryTest {
}
@Test
+ public void fillExternalChanges2() throws Exception {
+ Revision r1 = new Revision(1, 0, 1);
+ Revision r2 = new Revision(2, 0, 1);
+ Revision r3 = new Revision(3, 0, 1);
+ Revision r4 = new Revision(4, 0, 1);
+ DocumentStore store = new MemoryDocumentStore();
+ JournalEntry entry = JOURNAL.newDocument(store);
+ entry.modified("/");
+ entry.modified("/foo");
+ UpdateOp op = entry.asUpdateOp(r2);
+ assertTrue(store.create(JOURNAL, Collections.singletonList(op)));
+
+ entry = JOURNAL.newDocument(store);
+ entry.modified("/");
+ entry.modified("/bar");
+ op = entry.asUpdateOp(r4);
+ assertTrue(store.create(JOURNAL, Collections.singletonList(op)));
+
+ StringSort sort = JournalEntry.newSorter();
+ JournalEntry.fillExternalChanges(sort, r1, r1, store);
+ assertEquals(0, sort.getSize());
+ sort.close();
+
+ sort = JournalEntry.newSorter();
+ JournalEntry.fillExternalChanges(sort, r1, r2, store);
+ assertEquals(Sets.newHashSet("/", "/foo"), Sets.newHashSet(sort));
+ sort.close();
+
+ sort = JournalEntry.newSorter();
+ JournalEntry.fillExternalChanges(sort, r1, r3, store);
+ assertEquals(Sets.newHashSet("/", "/foo", "/bar"), Sets.newHashSet(sort));
+ sort.close();
+
+ sort = JournalEntry.newSorter();
+ JournalEntry.fillExternalChanges(sort, r1, r4, store);
+ assertEquals(Sets.newHashSet("/", "/foo", "/bar"), Sets.newHashSet(sort));
+ sort.close();
+
+ sort = JournalEntry.newSorter();
+ JournalEntry.fillExternalChanges(sort, r2, r2, store);
+ assertEquals(0, sort.getSize());
+ sort.close();
+
+ sort = JournalEntry.newSorter();
+ JournalEntry.fillExternalChanges(sort, r2, r3, store);
+ assertEquals(Sets.newHashSet("/", "/bar"), Sets.newHashSet(sort));
+ sort.close();
+
+ sort = JournalEntry.newSorter();
+ JournalEntry.fillExternalChanges(sort, r2, r4, store);
+ assertEquals(Sets.newHashSet("/", "/bar"), Sets.newHashSet(sort));
+ sort.close();
+
+ sort = JournalEntry.newSorter();
+ JournalEntry.fillExternalChanges(sort, r3, r3, store);
+ assertEquals(0, sort.getSize());
+ sort.close();
+
+ sort = JournalEntry.newSorter();
+ JournalEntry.fillExternalChanges(sort, r3, r4, store);
+ assertEquals(Sets.newHashSet("/", "/bar"), Sets.newHashSet(sort));
+ sort.close();
+
+ sort = JournalEntry.newSorter();
+ JournalEntry.fillExternalChanges(sort, r4, r4, store);
+ assertEquals(0, sort.getSize());
+ sort.close();
+ }
+
+ @Test
public void getRevisionTimestamp() throws Exception {
DocumentStore store = new MemoryDocumentStore();
JournalEntry entry = JOURNAL.newDocument(store);
Modified: jackrabbit/oak/branches/1.4/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/JournalGCTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.4/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/JournalGCTest.java?rev=1762477&r1=1762476&r2=1762477&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.4/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/JournalGCTest.java (original)
+++ jackrabbit/oak/branches/1.4/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/JournalGCTest.java Tue Sep 27 13:34:26 2016
@@ -28,6 +28,7 @@ import org.junit.Rule;
import org.junit.Test;
import static org.apache.jackrabbit.oak.plugins.document.Collection.JOURNAL;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
@@ -74,4 +75,41 @@ public class JournalGCTest {
entry = ns.getDocumentStore().find(JOURNAL, JournalEntry.asId(head));
assertNull(entry);
}
+
+ @Test
+ public void getTailRevision() throws Exception {
+ Clock c = new Clock.Virtual();
+ c.waitUntil(System.currentTimeMillis());
+ DocumentNodeStore ns = builderProvider.newBuilder()
+ .clock(c).setAsyncDelay(0).getNodeStore();
+
+ JournalGarbageCollector jgc = ns.getJournalGarbageCollector();
+ assertEquals(new Revision(0, 0, ns.getClusterId()), jgc.getTailRevision());
+
+ NodeBuilder builder = ns.getRoot().builder();
+ builder.child("foo");
+ ns.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+ ns.runBackgroundOperations();
+
+ assertEquals(0, jgc.gc(1, 10, TimeUnit.HOURS));
+
+ // current time, but without the increment done by getTime()
+ long now = c.getTime() - 1;
+ Revision tail = new Revision(now - TimeUnit.HOURS.toMillis(1), 0, ns.getClusterId());
+
+ c.waitUntil(c.getTime() + TimeUnit.MINUTES.toMillis(1));
+ assertEquals(tail, jgc.getTailRevision());
+
+ c.waitUntil(c.getTime() + TimeUnit.HOURS.toMillis(1));
+
+ // must collect all journal entries. the first created when
+ // DocumentNodeStore was initialized and the second created
+ // by the background update
+ assertEquals(2, jgc.gc(1, 10, TimeUnit.HOURS));
+
+ // current time, but without the increment done by getTime()
+ now = c.getTime() - 1;
+ tail = new Revision(now - TimeUnit.HOURS.toMillis(1), 0, ns.getClusterId());
+ assertEquals(tail, jgc.getTailRevision());
+ }
}
Modified: jackrabbit/oak/branches/1.4/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/SimpleTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.4/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/SimpleTest.java?rev=1762477&r1=1762476&r2=1762477&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.4/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/SimpleTest.java (original)
+++ jackrabbit/oak/branches/1.4/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/SimpleTest.java Tue Sep 27 13:34:26 2016
@@ -16,10 +16,13 @@
*/
package org.apache.jackrabbit.oak.plugins.document;
+import static org.hamcrest.CoreMatchers.anyOf;
+import static org.hamcrest.CoreMatchers.equalTo;
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;
import static org.junit.Assert.fail;
@@ -162,7 +165,7 @@ public class SimpleTest {
String diff23 = mk.diff(rev2, rev3, "/", 0).trim();
assertEquals("+\"/t3\":{}", diff23);
String diff13 = mk.diff(rev1, rev3, "/", 0).trim();
- assertEquals("+\"/t2\":{}+\"/t3\":{}", diff13);
+ assertThat(diff13, anyOf(equalTo("+\"/t2\":{}+\"/t3\":{}"), equalTo("+\"/t3\":{}+\"/t2\":{}")));
String diff34 = mk.diff(rev3, rev4, "/", 0).trim();
assertEquals("^\"/t3\":{}", diff34);
}