Search in sources :

Example 21 with Clock

use of org.apache.jackrabbit.oak.stats.Clock in project jackrabbit-oak by apache.

the class SuggestionIntervalTest method createRepository.

@Override
protected ContentRepository createRepository() {
    LuceneIndexProvider provider = new LuceneIndexProvider();
    ContentRepository repository = new Oak().with(new InitialContent()).with(new OpenSecurityProvider()).with((QueryIndexProvider) provider).with((Observer) provider).with(new LuceneIndexEditorProvider()).createContentRepository();
    clock = new Clock.Virtual();
    try {
        clock.waitUntil(System.currentTimeMillis());
    } catch (Exception e) {
    //eat exception if clock couldn't wait... that was just courteous anyway!
    }
    LuceneIndexEditorContext.setClock(clock);
    return repository;
}
Also used : InitialContent(org.apache.jackrabbit.oak.InitialContent) ContentRepository(org.apache.jackrabbit.oak.api.ContentRepository) Oak(org.apache.jackrabbit.oak.Oak) OpenSecurityProvider(org.apache.jackrabbit.oak.spi.security.OpenSecurityProvider) Clock(org.apache.jackrabbit.oak.stats.Clock) QueryIndexProvider(org.apache.jackrabbit.oak.spi.query.QueryIndexProvider)

Example 22 with Clock

use of org.apache.jackrabbit.oak.stats.Clock in project jackrabbit-oak by apache.

the class LastRevRecoveryAgent method recoverCandidates.

/**
     * Retrieves possible candidates which have been modified after the given
     * {@code startTime} and recovers the missing updates.
     *
     * @param nodeInfo the info of the cluster node to recover.
     * @param startTime the start time
     * @param waitUntil wait at most until this time for an ongoing recovery
     *                  done by another cluster node.
     * @param info a string with additional information how recovery is run.
     * @return the number of restored nodes or {@code -1} if recovery is still
     *      ongoing by another process even when {@code waitUntil} time was
     *      reached.
     */
private int recoverCandidates(final ClusterNodeInfoDocument nodeInfo, final long startTime, final long waitUntil, final String info) {
    ClusterNodeInfoDocument infoDoc = nodeInfo;
    int clusterId = infoDoc.getClusterId();
    for (; ; ) {
        if (missingLastRevUtil.acquireRecoveryLock(clusterId, nodeStore.getClusterId())) {
            break;
        }
        Clock clock = nodeStore.getClock();
        long remaining = waitUntil - clock.getTime();
        if (remaining < 0) {
            // no need to wait for lock release, waitUntil already reached
            return -1;
        }
        log.info("Last revision recovery already being performed by " + "cluster node {}. Waiting at most until {} for recovery " + "to finish ({} seconds remaining).", infoDoc.getRecoveryBy(), Utils.timestampToString(waitUntil), remaining / 1000);
        // check once every five seconds
        long time = Math.min(waitUntil, clock.getTime() + 5000);
        try {
            clock.waitUntil(time);
        } catch (InterruptedException e) {
            Thread.interrupted();
            String msg = "Interrupted while waiting for _lastRev recovery to finish.";
            throw new DocumentStoreException(msg, e);
        }
        infoDoc = missingLastRevUtil.getClusterNodeInfo(clusterId);
        if (!missingLastRevUtil.isRecoveryNeeded(infoDoc)) {
            // meanwhile another process finished recovery
            return 0;
        }
    }
    // if we get here, the recovery lock was acquired successfully
    boolean success = false;
    try {
        log.info("Recovering candidates modified after: [{}] for clusterId [{}] [{}]", Utils.timestampToString(startTime), clusterId, info);
        Iterable<NodeDocument> suspects = missingLastRevUtil.getCandidates(startTime);
        try {
            log.info("Performing Last Revision Recovery for clusterNodeId {}", clusterId);
            int num = recover(suspects, clusterId);
            success = true;
            return num;
        } finally {
            Utils.closeIfCloseable(suspects);
        }
    } finally {
        missingLastRevUtil.releaseRecoveryLock(clusterId, success);
        nodeStore.signalClusterStateChange();
    }
}
Also used : Clock(org.apache.jackrabbit.oak.stats.Clock)

Example 23 with Clock

use of org.apache.jackrabbit.oak.stats.Clock in project jackrabbit-oak by apache.

the class DocumentNodeStoreTest method conflictDetectionWithClockDifference.

// OAK-2929
@Test
public void conflictDetectionWithClockDifference() throws Exception {
    MemoryDocumentStore store = new MemoryDocumentStore();
    long now = System.currentTimeMillis();
    Clock c1 = new Clock.Virtual();
    c1.waitUntil(now);
    Revision.setClock(c1);
    DocumentNodeStore ns1 = builderProvider.newBuilder().clock(c1).setDocumentStore(store).setAsyncDelay(0).setClusterId(1).getNodeStore();
    NodeBuilder b1 = ns1.getRoot().builder();
    b1.child("node");
    merge(ns1, b1);
    // make /node visible
    ns1.runBackgroundOperations();
    Revision.resetClockToDefault();
    Clock c2 = new Clock.Virtual();
    // c2 is five seconds ahead
    c2.waitUntil(now + 5000);
    Revision.setClock(c2);
    DocumentNodeStore ns2 = builderProvider.newBuilder().clock(c2).setDocumentStore(store).setAsyncDelay(0).setClusterId(2).getNodeStore();
    // ns2 sees /node
    assertTrue(ns2.getRoot().hasChildNode("node"));
    // add a child /node/foo
    NodeBuilder b2 = ns2.getRoot().builder();
    b2.child("node").child("foo");
    merge(ns2, b2);
    // make /node/foo visible
    ns2.runBackgroundOperations();
    Revision.resetClockToDefault();
    Revision.setClock(c1);
    ns1.runBackgroundOperations();
    b1 = ns1.getRoot().builder();
    // ns1 sees /node/foo as well
    assertTrue(b1.getChildNode("node").hasChildNode("foo"));
    // remove both /node and /node/foo
    b1.child("node").remove();
    merge(ns1, b1);
    Revision.resetClockToDefault();
    Revision.setClock(c2);
    b2 = ns2.getRoot().builder();
    b2.child("node").child("bar");
    try {
        merge(ns2, b2);
        // must not be able to add another child node
        fail("must fail with CommitFailedException");
    } catch (CommitFailedException e) {
    // expected
    }
}
Also used : MemoryDocumentStore(org.apache.jackrabbit.oak.plugins.document.memory.MemoryDocumentStore) Clock(org.apache.jackrabbit.oak.stats.Clock) NodeBuilder(org.apache.jackrabbit.oak.spi.state.NodeBuilder) CommitFailedException(org.apache.jackrabbit.oak.api.CommitFailedException) Test(org.junit.Test)

Example 24 with Clock

use of org.apache.jackrabbit.oak.stats.Clock in project jackrabbit-oak by apache.

the class DocumentNodeStoreBranchesTest method commitHookChangesOnBranchWithInterference.

@Test
public void commitHookChangesOnBranchWithInterference() throws Exception {
    Clock c = new Clock.Virtual();
    c.waitUntil(System.currentTimeMillis());
    Revision.setClock(c);
    ClusterNodeInfo.setClock(c);
    // enough nodes that diffManyChildren() is called
    final int NUM_NODES = DocumentMK.MANY_CHILDREN_THRESHOLD * 2;
    LOG.info("create new dns");
    Builder nsBuilder = builderProvider.newBuilder();
    nsBuilder.setAsyncDelay(0).clock(c);
    final DocumentNodeStore ns = nsBuilder.getNodeStore();
    // 0) initialization
    {
        LOG.info("initialization");
        NodeBuilder initBuilder = ns.getRoot().builder();
        for (int i = 0; i < NUM_NODES; i++) {
            initBuilder.child("child" + i);
        }
        ns.merge(initBuilder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
    }
    // 1) do more than UPDATE_LIMIT changes
    LOG.info("starting doing many changes to force a branch commit");
    NodeBuilder rootBuilder = ns.getRoot().builder();
    int totalUpdates = 5 * DocumentMK.UPDATE_LIMIT;
    int updateShare = totalUpdates / NUM_NODES;
    for (int i = 0; i < NUM_NODES; i++) {
        NodeBuilder childBuilder = rootBuilder.child("child" + i);
        childBuilder.child("grandChild" + i);
        childBuilder.setProperty("p1", "originalValue");
        for (int j = 0; j < updateShare; j++) {
            childBuilder.setProperty("someProperty" + j, "sameValue");
        }
    }
    // 2) wait 6 sec
    LOG.info("after purge was triggered above, 'waiting' 6sec");
    c.waitUntil(c.getTime() + 6000);
    // 3) now in another 'session', do another merge - to change the head
    LOG.info("in another session, do some unrelated changes to change the head");
    NodeBuilder parallelBuilder = ns.getRoot().builder();
    parallelBuilder.child("unrelated").setProperty("anyProp", "anywhere");
    ns.merge(parallelBuilder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
    // 4) now merge the first session - this should now fail
    LOG.info("now merge the original builder - this should cause not all children to be visited");
    ns.merge(rootBuilder, CompositeHook.compose(Arrays.<CommitHook>asList(new TestHook("p"), new TestHook("q"))), CommitInfo.EMPTY);
    DocumentNodeState root = ns.getRoot();
    for (int i = 0; i < NUM_NODES; i++) {
        NodeState child = root.getChildNode("child" + i);
        assertTrue(child.exists());
        assertEquals("test", child.getProperty("p1").getValue(Type.STRING));
    }
}
Also used : NodeState(org.apache.jackrabbit.oak.spi.state.NodeState) Builder(org.apache.jackrabbit.oak.plugins.document.DocumentMK.Builder) NodeBuilder(org.apache.jackrabbit.oak.spi.state.NodeBuilder) CommitHook(org.apache.jackrabbit.oak.spi.commit.CommitHook) Clock(org.apache.jackrabbit.oak.stats.Clock) NodeBuilder(org.apache.jackrabbit.oak.spi.state.NodeBuilder) Test(org.junit.Test)

Example 25 with Clock

use of org.apache.jackrabbit.oak.stats.Clock in project jackrabbit-oak by apache.

the class DocumentNodeStoreTest method concurrentChildOperations.

// OAK-3646
@Test
public void concurrentChildOperations() throws Exception {
    Clock clock = new Clock.Virtual();
    clock.waitUntil(System.currentTimeMillis());
    Revision.setClock(clock);
    MemoryDocumentStore store = new MemoryDocumentStore();
    DocumentNodeStore ns1 = builderProvider.newBuilder().setAsyncDelay(0).clock(clock).setDocumentStore(store).setClusterId(1).getNodeStore();
    DocumentNodeStore ns2 = builderProvider.newBuilder().setAsyncDelay(0).clock(clock).setDocumentStore(store).setClusterId(2).getNodeStore();
    // create some children under /foo/bar
    NodeBuilder b1 = ns1.getRoot().builder();
    NodeBuilder node = b1.child("foo").child("bar");
    node.child("child-0");
    node.child("child-1");
    node.child("child-2");
    merge(ns1, b1);
    // make changes visible on both cluster nodes
    ns1.runBackgroundOperations();
    ns2.runBackgroundOperations();
    // remove child-0 on cluster node 1
    b1 = ns1.getRoot().builder();
    b1.child("foo").child("bar").getChildNode("child-0").remove();
    merge(ns1, b1);
    // push _lastRev updates to DocumentStore
    ns1.runBackgroundOperations();
    // remove child-1 on cluster node 2
    NodeBuilder b2 = ns2.getRoot().builder();
    b2.child("foo").child("bar").getChildNode("child-1").remove();
    merge(ns2, b2);
    // on cluster node 2, remove of child-0 is not yet visible
    DocumentNodeState bar = asDocumentNodeState(ns2.getRoot().getChildNode("foo").getChildNode("bar"));
    List<ChildNodeEntry> children = Lists.newArrayList(bar.getChildNodeEntries());
    assertEquals(2, Iterables.size(children));
    RevisionVector invalidate = bar.getLastRevision();
    assertNotNull(invalidate);
    // this will make changes from cluster node 1 visible
    ns2.runBackgroundOperations();
    // wait two hours
    clock.waitUntil(clock.getTime() + TimeUnit.HOURS.toMillis(2));
    // collect everything older than one hour
    // this will remove child-0 and child-1 doc
    ns1.getVersionGarbageCollector().gc(1, TimeUnit.HOURS);
    // forget cache entry for deleted node
    ns2.invalidateNodeCache("/foo/bar/child-0", invalidate);
    children = Lists.newArrayList(ns2.getRoot().getChildNode("foo").getChildNode("bar").getChildNodeEntries());
    assertEquals(1, Iterables.size(children));
}
Also used : MemoryDocumentStore(org.apache.jackrabbit.oak.plugins.document.memory.MemoryDocumentStore) ChildNodeEntry(org.apache.jackrabbit.oak.spi.state.ChildNodeEntry) Clock(org.apache.jackrabbit.oak.stats.Clock) NodeBuilder(org.apache.jackrabbit.oak.spi.state.NodeBuilder) Test(org.junit.Test)

Aggregations

Clock (org.apache.jackrabbit.oak.stats.Clock)39 Test (org.junit.Test)24 MemoryDocumentStore (org.apache.jackrabbit.oak.plugins.document.memory.MemoryDocumentStore)21 NodeBuilder (org.apache.jackrabbit.oak.spi.state.NodeBuilder)19 Before (org.junit.Before)8 ChildNodeEntry (org.apache.jackrabbit.oak.spi.state.ChildNodeEntry)3 NodeState (org.apache.jackrabbit.oak.spi.state.NodeState)3 AtomicLong (java.util.concurrent.atomic.AtomicLong)2 MemoryNodeStore (org.apache.jackrabbit.oak.plugins.memory.MemoryNodeStore)2 BlobStore (org.apache.jackrabbit.oak.spi.blob.BlobStore)2 ByteArrayInputStream (java.io.ByteArrayInputStream)1 File (java.io.File)1 IOException (java.io.IOException)1 Calendar (java.util.Calendar)1 Map (java.util.Map)1 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)1 InitialContent (org.apache.jackrabbit.oak.InitialContent)1 Oak (org.apache.jackrabbit.oak.Oak)1 CommitFailedException (org.apache.jackrabbit.oak.api.CommitFailedException)1 CONSTRAINT (org.apache.jackrabbit.oak.api.CommitFailedException.CONSTRAINT)1