Author: mreutegg Date: Thu Jul 17 08:36:43 2014 New Revision: 1611285 URL: http://svn.apache.org/r1611285 Log: OAK-1972: Async property index update may fail on DocumentMK with more than 100 index changes
Merged 1611041 and 1611277 from tunk Modified: jackrabbit/oak/branches/1.0/ (props changed) jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/NodeDocument.java jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreTest.java Propchange: jackrabbit/oak/branches/1.0/ ------------------------------------------------------------------------------ Merged /jackrabbit/oak/trunk:r1611041,1611277 Modified: jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/NodeDocument.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/NodeDocument.java?rev=1611285&r1=1611284&r2=1611285&view=diff ============================================================================== --- jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/NodeDocument.java (original) +++ jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/NodeDocument.java Thu Jul 17 08:36:43 2014 @@ -734,6 +734,22 @@ public final class NodeDocument extends // first check local map, which contains most recent values Value value = getLatestValue(nodeStore, getLocalMap(key), min, readRevision, validRevisions); + + // check if there may be more recent values in a previous document + if (value != null && !getPreviousRanges().isEmpty()) { + Revision newest = getLocalMap(key).firstKey(); + if (!value.revision.equals(newest)) { + // not reading the most recent value, we may need to + // consider previous documents as well + Revision newestPrev = getPreviousRanges().firstKey(); + if (isRevisionNewer(nodeStore, newestPrev, value.revision)) { + // a previous document has more recent changes + // than value.revision + value = null; + } + } + } + if (value == null && !getPreviousRanges().isEmpty()) { // check complete revision history value = getLatestValue(nodeStore, getValueMap(key), Modified: jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreTest.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreTest.java?rev=1611285&r1=1611284&r2=1611285&view=diff ============================================================================== --- jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreTest.java (original) +++ jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreTest.java Thu Jul 17 08:36:43 2014 @@ -60,6 +60,7 @@ import static org.apache.jackrabbit.oak. import static org.apache.jackrabbit.oak.plugins.document.Collection.NODES; import static org.apache.jackrabbit.oak.plugins.document.NodeDocument.MODIFIED_IN_SECS; import static org.apache.jackrabbit.oak.plugins.document.NodeDocument.MODIFIED_IN_SECS_RESOLUTION; +import static org.apache.jackrabbit.oak.plugins.document.NodeDocument.NUM_REVS_THRESHOLD; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; @@ -484,6 +485,47 @@ public class DocumentNodeStoreTest { maxLimit.get() <= DocumentNodeState.INITIAL_FETCH_SIZE + 1); } + // OAK-1972 + @Test + public void readFromPreviousDoc() throws CommitFailedException { + DocumentStore docStore = new MemoryDocumentStore(); + DocumentNodeStore ns = new DocumentMK.Builder() + .setDocumentStore(docStore).getNodeStore(); + NodeBuilder builder = ns.getRoot().builder(); + builder.child("test").setProperty("prop", "initial"); + ns.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY); + ns.dispose(); + + ns = new DocumentMK.Builder().setClusterId(2).setAsyncDelay(0) + .setDocumentStore(docStore).getNodeStore(); + builder = ns.getRoot().builder(); + builder.child("test").setProperty("prop", "value"); + ns.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY); + + Revision rev = ns.getHeadRevision(); + NodeDocument doc = docStore.find(Collection.NODES, Utils.getIdFromPath("/test")); + assertNotNull(doc); + DocumentNodeState state = doc.getNodeAtRevision(ns, rev, null); + assertNotNull(state); + assertTrue(state.hasProperty("prop")); + assertEquals("value", state.getProperty("prop").getValue(Type.STRING)); + + for (int i = 0; i < NUM_REVS_THRESHOLD; i++) { + builder = ns.getRoot().builder(); + builder.child("test").setProperty("prop", "v-" + i); + ns.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY); + } + ns.runBackgroundOperations(); + + // must still return the same value as before the split + doc = docStore.find(Collection.NODES, Utils.getIdFromPath("/test")); + assertNotNull(doc); + state = doc.getNodeAtRevision(ns, rev, null); + assertNotNull(state); + assertTrue(state.hasProperty("prop")); + assertEquals("value", state.getProperty("prop").getValue(Type.STRING)); + } + private static class TestHook extends EditorHook { TestHook(final String prefix) {