Search in sources :

Example 6 with DefaultNodeStateDiff

use of org.apache.jackrabbit.oak.spi.state.DefaultNodeStateDiff in project jackrabbit-oak by apache.

the class DocumentNodeStoreTest method diffMany.

// 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);
    final List<Long> startValues = Lists.newArrayList();
    MemoryDocumentStore ds = new MemoryDocumentStore() {

        @Nonnull
        @Override
        public <T extends Document> List<T> query(Collection<T> collection, String fromKey, String toKey, String indexedProperty, long startValue, int limit) {
            if (indexedProperty != null) {
                startValues.add(startValue);
            }
            return super.query(collection, fromKey, toKey, indexedProperty, startValue, limit);
        }
    };
    DocumentNodeStore ns = builderProvider.newBuilder().clock(clock).setDocumentStore(ds).setAsyncDelay(0).getNodeStore();
    NodeBuilder builder = ns.getRoot().builder();
    NodeBuilder test = builder.child("test");
    for (int i = 0; i < DocumentMK.MANY_CHILDREN_THRESHOLD * 2; i++) {
        test.child("node-" + i);
    }
    merge(ns, builder);
    // 'wait one hour'
    clock.waitUntil(clock.getTime() + TimeUnit.HOURS.toMillis(1));
    // perform a change and use the resulting root as before state
    builder = ns.getRoot().builder();
    builder.child("foo");
    DocumentNodeState before = asDocumentNodeState(merge(ns, builder));
    NodeState beforeTest = before.getChildNode("test");
    // perform another change to span the diff across multiple revisions
    // this will prevent diff calls served from the local cache
    builder = ns.getRoot().builder();
    builder.child("bar");
    merge(ns, builder);
    // add a child node
    builder = ns.getRoot().builder();
    builder.child("test").child("bar");
    NodeState after = merge(ns, builder);
    NodeState afterTest = after.getChildNode("test");
    startValues.clear();
    // make sure diff is not served from node children cache entries
    ns.invalidateNodeChildrenCache();
    afterTest.compareAgainstBaseState(beforeTest, new DefaultNodeStateDiff());
    assertEquals(1, startValues.size());
    Revision localHead = before.getRootRevision().getRevision(ns.getClusterId());
    assertNotNull(localHead);
    long beforeModified = getModifiedInSecs(localHead.getTimestamp());
    // 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");
}
Also used : NodeState(org.apache.jackrabbit.oak.spi.state.NodeState) MemoryDocumentStore(org.apache.jackrabbit.oak.plugins.document.memory.MemoryDocumentStore) Clock(org.apache.jackrabbit.oak.stats.Clock) NodeBuilder(org.apache.jackrabbit.oak.spi.state.NodeBuilder) TRANSIENT(org.apache.jackrabbit.oak.plugins.document.DocumentStoreException.Type.TRANSIENT) CONSTRAINT(org.apache.jackrabbit.oak.api.CommitFailedException.CONSTRAINT) DefaultNodeStateDiff(org.apache.jackrabbit.oak.spi.state.DefaultNodeStateDiff) AtomicLong(java.util.concurrent.atomic.AtomicLong) Test(org.junit.Test)

Example 7 with DefaultNodeStateDiff

use of org.apache.jackrabbit.oak.spi.state.DefaultNodeStateDiff in project jackrabbit-oak by apache.

the class DocumentNodeStoreTest method longRunningTx.

// OAK-5602
@Test
public void longRunningTx() throws Exception {
    Clock clock = new Clock.Virtual();
    clock.waitUntil(System.currentTimeMillis());
    Revision.setClock(clock);
    MemoryDocumentStore docStore = new MemoryDocumentStore();
    DocumentNodeStore ns = builderProvider.newBuilder().setDocumentStore(docStore).setUpdateLimit(100).setJournalGCMaxAge(TimeUnit.HOURS.toMillis(6)).setBundlingDisabled(true).setAsyncDelay(0).clock(clock).getNodeStore();
    NodeBuilder builder = ns.getRoot().builder();
    builder.child("test");
    merge(ns, builder);
    builder = ns.getRoot().builder();
    NodeBuilder test = builder.child("test");
    String firstChildId = Utils.getIdFromPath("/test/child-0");
    for (int i = 0; ; i++) {
        NodeBuilder child = test.child("child-" + i);
        for (int j = 0; j < 10; j++) {
            child.setProperty("p-" + j, "value");
        }
        if (docStore.find(NODES, firstChildId) != null) {
            // branch was created
            break;
        }
    }
    // simulate a long running commit taking 2 hours
    clock.waitUntil(clock.getTime() + TimeUnit.HOURS.toMillis(2));
    // some other commit that moves the head revision forward
    NodeBuilder builder2 = ns.getRoot().builder();
    builder2.child("foo");
    merge(ns, builder2);
    NodeState before = ns.getRoot().getChildNode("test");
    // merge the long running tx
    merge(ns, builder);
    // five hours later the branch commit can be collected by the journal GC
    clock.waitUntil(clock.getTime() + TimeUnit.HOURS.toMillis(5));
    // journal gc cleans up entries older than 6 hours
    ns.getJournalGarbageCollector().gc();
    // now the node state diff mechanism must not use the journal
    // because the required journal entry with the branch commit
    // is incomplete. the journal entry for the merge commit is still
    // present, but the referenced branch commit has been GCed.
    NodeState after = ns.getRoot().getChildNode("test");
    after.compareAgainstBaseState(before, new DefaultNodeStateDiff());
}
Also used : NodeState(org.apache.jackrabbit.oak.spi.state.NodeState) MemoryDocumentStore(org.apache.jackrabbit.oak.plugins.document.memory.MemoryDocumentStore) DefaultNodeStateDiff(org.apache.jackrabbit.oak.spi.state.DefaultNodeStateDiff) Clock(org.apache.jackrabbit.oak.stats.Clock) NodeBuilder(org.apache.jackrabbit.oak.spi.state.NodeBuilder) Test(org.junit.Test)

Example 8 with DefaultNodeStateDiff

use of org.apache.jackrabbit.oak.spi.state.DefaultNodeStateDiff in project jackrabbit-oak by apache.

the class DocumentNodeStoreTest method diffWithBrokenJournal.

// OAK-6495
@Test
public void diffWithBrokenJournal() throws Exception {
    Clock clock = new Clock.Virtual();
    clock.waitUntil(System.currentTimeMillis());
    Revision.setClock(clock);
    MemoryDocumentStore docStore = new MemoryDocumentStore();
    DocumentNodeStore ns = builderProvider.newBuilder().setDocumentStore(docStore).setUpdateLimit(100).setJournalGCMaxAge(TimeUnit.HOURS.toMillis(6)).setBundlingDisabled(true).setAsyncDelay(0).clock(clock).getNodeStore();
    NodeBuilder builder = ns.getRoot().builder();
    builder.child("test");
    merge(ns, builder);
    NodeState before = ns.getRoot().getChildNode("test");
    builder = ns.getRoot().builder();
    NodeBuilder test = builder.child("test");
    String firstChildId = Utils.getIdFromPath("/test/child-0");
    for (int i = 0; ; i++) {
        NodeBuilder child = test.child("child-" + i);
        for (int j = 0; j < 10; j++) {
            child.setProperty("p-" + j, "value");
        }
        if (docStore.find(NODES, firstChildId) != null) {
            // branch was created
            break;
        }
    }
    merge(ns, builder);
    ns.runBackgroundOperations();
    Revision head = ns.getHeadRevision().getRevision(ns.getClusterId());
    assertNotNull(head);
    JournalEntry entry = ns.getDocumentStore().find(JOURNAL, JournalEntry.asId(head));
    assertNotNull(entry);
    // must reference at least one branch commit
    assertThat(Iterables.size(entry.getBranchCommits()), greaterThan(0));
    // now remove them
    for (JournalEntry bc : entry.getBranchCommits()) {
        docStore.remove(JOURNAL, bc.getId());
    }
    // compare must still succeed even when branch commits
    // are missing in the journal
    NodeState after = ns.getRoot().getChildNode("test");
    after.compareAgainstBaseState(before, new DefaultNodeStateDiff());
}
Also used : NodeState(org.apache.jackrabbit.oak.spi.state.NodeState) MemoryDocumentStore(org.apache.jackrabbit.oak.plugins.document.memory.MemoryDocumentStore) DefaultNodeStateDiff(org.apache.jackrabbit.oak.spi.state.DefaultNodeStateDiff) Clock(org.apache.jackrabbit.oak.stats.Clock) NodeBuilder(org.apache.jackrabbit.oak.spi.state.NodeBuilder) Test(org.junit.Test)

Example 9 with DefaultNodeStateDiff

use of org.apache.jackrabbit.oak.spi.state.DefaultNodeStateDiff in project jackrabbit-oak by apache.

the class JournalDiffLoaderTest method useJournal.

// OAK-5228
@Test
public void useJournal() throws Exception {
    final AtomicInteger journalQueryCounter = new AtomicInteger();
    DocumentStore ds = new MemoryDocumentStore() {

        @Nonnull
        @Override
        public <T extends Document> List<T> query(Collection<T> collection, String fromKey, String toKey, int limit) {
            if (collection == Collection.JOURNAL) {
                journalQueryCounter.incrementAndGet();
            }
            return super.query(collection, fromKey, toKey, limit);
        }
    };
    DocumentNodeStore ns1 = builderProvider.newBuilder().setClusterId(1).clock(clock).setLeaseCheck(false).setDocumentStore(ds).setAsyncDelay(0).getNodeStore();
    DocumentNodeStore ns2 = builderProvider.newBuilder().setClusterId(2).clock(clock).setLeaseCheck(false).setDocumentStore(ds).setAsyncDelay(0).getNodeStore();
    NodeBuilder b1 = ns1.getRoot().builder();
    NodeBuilder foo = b1.child("foo");
    for (int i = 0; i < DocumentMK.MANY_CHILDREN_THRESHOLD + 1; i++) {
        foo.child("n" + i);
    }
    merge(ns1, b1);
    ns1.runBackgroundOperations();
    ns2.runBackgroundOperations();
    clock.waitUntil(clock.getTime() + TimeUnit.MINUTES.toMillis(10));
    NodeBuilder b2 = ns2.getRoot().builder();
    b2.child("foo").child("bar");
    merge(ns2, b2);
    ns2.runBackgroundOperations();
    ns1.runBackgroundOperations();
    // collect journal entry created for /foo/nX
    new JournalGarbageCollector(ns1, TimeUnit.MINUTES.toMillis(5)).gc();
    // the next modification updates the root revision
    // for clusterId 1 past the removed journal entry
    b1 = ns1.getRoot().builder();
    b1.child("qux");
    merge(ns1, b1);
    ns1.runBackgroundOperations();
    ns2.runBackgroundOperations();
    // remember before state
    DocumentNodeState fooBefore = (DocumentNodeState) ns1.getRoot().getChildNode("foo");
    b2 = ns2.getRoot().builder();
    b2.child("foo").child("baz");
    merge(ns2, b2);
    ns2.runBackgroundOperations();
    ns1.runBackgroundOperations();
    b1 = ns1.getRoot().builder();
    b1.child("foo").child("bar").remove();
    merge(ns1, b1);
    ns1.runBackgroundOperations();
    ns2.runBackgroundOperations();
    DocumentNodeState fooAfter = (DocumentNodeState) ns1.getRoot().getChildNode("foo");
    journalQueryCounter.set(0);
    final Set<String> changes = Sets.newHashSet();
    fooAfter.compareAgainstBaseState(fooBefore, new DefaultNodeStateDiff() {

        @Override
        public boolean childNodeChanged(String name, NodeState before, NodeState after) {
            changes.add(name);
            return true;
        }

        @Override
        public boolean childNodeAdded(String name, NodeState after) {
            changes.add(name);
            return true;
        }

        @Override
        public boolean childNodeDeleted(String name, NodeState before) {
            changes.add(name);
            return true;
        }
    });
    assertThat(changes, containsInAnyOrder("bar", "baz"));
    assertTrue("must use JournalDiffLoader", journalQueryCounter.get() > 0);
}
Also used : NodeState(org.apache.jackrabbit.oak.spi.state.NodeState) MemoryDocumentStore(org.apache.jackrabbit.oak.plugins.document.memory.MemoryDocumentStore) NodeBuilder(org.apache.jackrabbit.oak.spi.state.NodeBuilder) MemoryDocumentStore(org.apache.jackrabbit.oak.plugins.document.memory.MemoryDocumentStore) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) DefaultNodeStateDiff(org.apache.jackrabbit.oak.spi.state.DefaultNodeStateDiff) Test(org.junit.Test)

Example 10 with DefaultNodeStateDiff

use of org.apache.jackrabbit.oak.spi.state.DefaultNodeStateDiff in project jackrabbit-oak by apache.

the class CompositeCompareTest method nodesOutsideTheMountsAreIgnored.

@Test
public void nodesOutsideTheMountsAreIgnored() throws CommitFailedException {
    MountInfoProvider mip = Mounts.newBuilder().mount("libs", "/libs").build();
    NodeStore globalStore = new MemoryNodeStore();
    NodeStore libsStore = new MemoryNodeStore();
    List<MountedNodeStore> mounts = Lists.newArrayList();
    mounts.add(new MountedNodeStore(mip.getMountByName("libs"), libsStore));
    CompositeNodeStore compositeNodeStore = new CompositeNodeStore(mip, globalStore, mounts);
    NodeState empty = compositeNodeStore.getRoot();
    NodeBuilder builder = globalStore.getRoot().builder();
    builder.child("global-child-1");
    builder.child("global-child-2");
    globalStore.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
    NodeBuilder libsBuilder = libsStore.getRoot().builder();
    libsBuilder.child("libs");
    libsBuilder.child("libs-child-1");
    libsBuilder.child("libs-child-2");
    libsStore.merge(libsBuilder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
    NodeState modified = compositeNodeStore.getRoot();
    final Set<String> addedChildren = newHashSet();
    modified.compareAgainstBaseState(empty, new DefaultNodeStateDiff() {

        @Override
        public boolean childNodeAdded(String name, NodeState after) {
            addedChildren.add(name);
            return true;
        }
    });
    assertEquals(ImmutableSet.of("global-child-1", "global-child-2", "libs"), addedChildren);
}
Also used : NodeStore(org.apache.jackrabbit.oak.spi.state.NodeStore) MemoryNodeStore(org.apache.jackrabbit.oak.plugins.memory.MemoryNodeStore) NodeState(org.apache.jackrabbit.oak.spi.state.NodeState) MemoryNodeStore(org.apache.jackrabbit.oak.plugins.memory.MemoryNodeStore) DefaultNodeStateDiff(org.apache.jackrabbit.oak.spi.state.DefaultNodeStateDiff) MountInfoProvider(org.apache.jackrabbit.oak.spi.mount.MountInfoProvider) NodeBuilder(org.apache.jackrabbit.oak.spi.state.NodeBuilder) Test(org.junit.Test)

Aggregations

DefaultNodeStateDiff (org.apache.jackrabbit.oak.spi.state.DefaultNodeStateDiff)12 NodeState (org.apache.jackrabbit.oak.spi.state.NodeState)12 NodeBuilder (org.apache.jackrabbit.oak.spi.state.NodeBuilder)10 Test (org.junit.Test)10 MemoryDocumentStore (org.apache.jackrabbit.oak.plugins.document.memory.MemoryDocumentStore)5 PropertyState (org.apache.jackrabbit.oak.api.PropertyState)3 MemoryNodeStore (org.apache.jackrabbit.oak.plugins.memory.MemoryNodeStore)3 MountInfoProvider (org.apache.jackrabbit.oak.spi.mount.MountInfoProvider)3 NodeStore (org.apache.jackrabbit.oak.spi.state.NodeStore)3 Clock (org.apache.jackrabbit.oak.stats.Clock)3 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)2 CONSTRAINT (org.apache.jackrabbit.oak.api.CommitFailedException.CONSTRAINT)2 TRANSIENT (org.apache.jackrabbit.oak.plugins.document.DocumentStoreException.Type.TRANSIENT)2 AtomicLong (java.util.concurrent.atomic.AtomicLong)1 DocumentNodeState (org.apache.jackrabbit.oak.plugins.document.DocumentNodeState)1 MapEntry.newMapEntry (org.apache.jackrabbit.oak.segment.MapEntry.newMapEntry)1 Mounts (org.apache.jackrabbit.oak.spi.mount.Mounts)1 AbstractNodeState (org.apache.jackrabbit.oak.spi.state.AbstractNodeState)1 ChildNodeEntry (org.apache.jackrabbit.oak.spi.state.ChildNodeEntry)1