Search in sources :

Example 31 with CommitInfo

use of org.apache.jackrabbit.oak.spi.commit.CommitInfo in project jackrabbit-oak by apache.

the class AsyncIndexUpdateTest method checkpointLostEventualConsistent.

@Test
public void checkpointLostEventualConsistent() throws Exception {
    MemoryNodeStore store = new MemoryNodeStore();
    final List<NodeState> rootStates = Lists.newArrayList();
    store.addObserver(new Observer() {

        @Override
        public void contentChanged(@Nonnull NodeState root, @Nullable CommitInfo info) {
            rootStates.add(root);
        }
    });
    IndexEditorProvider provider = new PropertyIndexEditorProvider();
    NodeBuilder builder = store.getRoot().builder();
    createIndexDefinition(builder.child(INDEX_DEFINITIONS_NAME), "rootIndex", true, false, ImmutableSet.of("foo"), null).setProperty(ASYNC_PROPERTY_NAME, "async");
    builder.child("testRoot").setProperty("foo", "abc");
    store.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
    AsyncIndexUpdate pre = new AsyncIndexUpdate("async", store, provider);
    pre.run();
    //Create another commit so that we have two checkpoints
    builder = store.getRoot().builder();
    builder.child("testRoot2").setProperty("foo", "abc");
    store.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
    pre.run();
    pre.close();
    //Look for the nodestate just before the final merge in AsyncIndexUpdate
    //i.e. where older checkpoint was still referred and which has been "released"
    //post last run
    Collections.reverse(rootStates);
    final AtomicReference<NodeState> oldRootState = new AtomicReference<NodeState>();
    for (NodeState ns : rootStates) {
        NodeState async = ns.getChildNode(ASYNC);
        String checkpointName = async.getString("async");
        if (store.retrieve(checkpointName) == null && async.getProperty(AsyncIndexUpdate.leasify("async")) == null) {
            oldRootState.set(ns);
            break;
        }
    }
    assertNotNull(oldRootState.get());
    final AtomicBoolean intiLeaseCalled = new AtomicBoolean(false);
    //Here for the call to read existing NodeState we would return the old
    //"stale" state where we have a stale checkpoint
    store = new MemoryNodeStore(store.getRoot()) {

        @Override
        public NodeState getRoot() {
            //Keep returning stale view untill initlease is not invoked
            if (!intiLeaseCalled.get()) {
                return oldRootState.get();
            }
            return super.getRoot();
        }
    };
    final AsyncIndexUpdate async = new AsyncIndexUpdate("async", store, provider) {

        @Override
        protected AsyncUpdateCallback newAsyncUpdateCallback(NodeStore store, String name, long leaseTimeOut, String beforeCheckpoint, AsyncIndexStats indexStats, AtomicBoolean stopFlag) {
            return new AsyncUpdateCallback(store, name, leaseTimeOut, beforeCheckpoint, indexStats, stopFlag) {

                @Override
                protected void initLease() throws CommitFailedException {
                    intiLeaseCalled.set(true);
                    super.initLease();
                }
            };
        }
    };
    async.run();
    //This run should fail
    assertTrue(async.getIndexStats().isFailing());
    async.close();
}
Also used : NodeState(org.apache.jackrabbit.oak.spi.state.NodeState) PropertyIndexEditorProvider(org.apache.jackrabbit.oak.plugins.index.property.PropertyIndexEditorProvider) AtomicReference(java.util.concurrent.atomic.AtomicReference) CoreMatchers.containsString(org.hamcrest.CoreMatchers.containsString) NodeBuilder(org.apache.jackrabbit.oak.spi.state.NodeBuilder) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) ProxyNodeStore(org.apache.jackrabbit.oak.spi.state.ProxyNodeStore) NodeStore(org.apache.jackrabbit.oak.spi.state.NodeStore) MemoryNodeStore(org.apache.jackrabbit.oak.plugins.memory.MemoryNodeStore) MemoryNodeStore(org.apache.jackrabbit.oak.plugins.memory.MemoryNodeStore) AsyncIndexStats(org.apache.jackrabbit.oak.plugins.index.AsyncIndexUpdate.AsyncIndexStats) Observer(org.apache.jackrabbit.oak.spi.commit.Observer) PropertyIndexEditorProvider(org.apache.jackrabbit.oak.plugins.index.property.PropertyIndexEditorProvider) CommitInfo(org.apache.jackrabbit.oak.spi.commit.CommitInfo) Test(org.junit.Test)

Example 32 with CommitInfo

use of org.apache.jackrabbit.oak.spi.commit.CommitInfo in project jackrabbit-oak by apache.

the class AsyncIndexUpdateTest method failOnConflict.

// OAK-1784
@Test
public void failOnConflict() throws Exception {
    final Map<Thread, Semaphore> locks = Maps.newIdentityHashMap();
    NodeStore store = new MemoryNodeStore() {

        @Nonnull
        @Override
        public NodeState merge(@Nonnull NodeBuilder builder, @Nonnull CommitHook commitHook, @Nonnull CommitInfo info) throws CommitFailedException {
            Semaphore s = locks.get(Thread.currentThread());
            if (s != null) {
                s.acquireUninterruptibly();
            }
            return super.merge(builder, commitHook, info);
        }
    };
    IndexEditorProvider provider = new PropertyIndexEditorProvider();
    NodeBuilder builder = store.getRoot().builder();
    createIndexDefinition(builder.child(INDEX_DEFINITIONS_NAME), "foo", false, ImmutableSet.of("foo"), null, TYPE, Collections.singletonMap(ASYNC_PROPERTY_NAME, "async"));
    builder.child("test").setProperty("foo", "a");
    store.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
    final AsyncIndexUpdate async = new AsyncIndexUpdate("async", store, provider);
    async.run();
    builder = store.getRoot().builder();
    builder.child("test").setProperty("foo", "b");
    store.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
    Thread t = new Thread(new Runnable() {

        @Override
        public void run() {
            async.run();
        }
    });
    Semaphore s = new Semaphore(0);
    locks.put(t, s);
    t.start();
    // make some unrelated changes to trigger indexing
    builder = store.getRoot().builder();
    builder.setChildNode("dummy").setProperty("foo", "bar");
    store.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
    while (!s.hasQueuedThreads()) {
        Thread.yield();
    }
    // introduce a conflict
    builder = store.getRoot().builder();
    builder.getChildNode(INDEX_DEFINITIONS_NAME).getChildNode("foo").getChildNode(":index").child("a").remove();
    store.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
    s.release(100);
    t.join();
    builder = store.getRoot().builder();
    assertNoConflictMarker(builder);
}
Also used : Nonnull(javax.annotation.Nonnull) CommitHook(org.apache.jackrabbit.oak.spi.commit.CommitHook) PropertyIndexEditorProvider(org.apache.jackrabbit.oak.plugins.index.property.PropertyIndexEditorProvider) Semaphore(java.util.concurrent.Semaphore) NodeBuilder(org.apache.jackrabbit.oak.spi.state.NodeBuilder) ProxyNodeStore(org.apache.jackrabbit.oak.spi.state.ProxyNodeStore) NodeStore(org.apache.jackrabbit.oak.spi.state.NodeStore) MemoryNodeStore(org.apache.jackrabbit.oak.plugins.memory.MemoryNodeStore) MemoryNodeStore(org.apache.jackrabbit.oak.plugins.memory.MemoryNodeStore) PropertyIndexEditorProvider(org.apache.jackrabbit.oak.plugins.index.property.PropertyIndexEditorProvider) CommitInfo(org.apache.jackrabbit.oak.spi.commit.CommitInfo) Test(org.junit.Test)

Example 33 with CommitInfo

use of org.apache.jackrabbit.oak.spi.commit.CommitInfo in project jackrabbit-oak by apache.

the class ChangeProcessor method createObserver.

private FilteringObserver createObserver(final WhiteboardExecutor executor) {
    FilteringDispatcher fd = new FilteringDispatcher(this);
    BackgroundObserver bo = new BackgroundObserver(fd, executor, queueLength) {

        private volatile long delay;

        private volatile boolean blocking;

        private long lastQueueFullWarnTimestamp = -1;

        @Override
        protected void added(int newQueueSize) {
            queueSizeChanged(newQueueSize);
        }

        @Override
        protected void removed(int newQueueSize, long created) {
            queueSizeChanged(newQueueSize);
        }

        private void queueSizeChanged(int newQueueSize) {
            maxQueueLengthRecorder.recordValue(newQueueSize);
            tracker.recordQueueLength(newQueueSize);
            if (newQueueSize >= queueLength) {
                if (commitRateLimiter != null) {
                    if (!blocking) {
                        logQueueFullWarning("Revision queue is full. Further commits will be blocked.");
                    }
                    commitRateLimiter.blockCommits();
                } else if (!blocking) {
                    logQueueFullWarning("Revision queue is full. Further revisions will be compacted.");
                }
                blocking = true;
            } else {
                double fillRatio = (double) newQueueSize / queueLength;
                if (fillRatio > DELAY_THRESHOLD) {
                    if (commitRateLimiter != null) {
                        if (delay == 0) {
                            LOG.warn("Revision queue is becoming full. Further commits will be delayed.");
                        }
                        // Linear backoff proportional to the number of items exceeding
                        // DELAY_THRESHOLD. Offset by 1 to trigger the log message in the
                        // else branch once the queue falls below DELAY_THRESHOLD again.
                        int newDelay = 1 + (int) ((fillRatio - DELAY_THRESHOLD) / (1 - DELAY_THRESHOLD) * MAX_DELAY);
                        if (newDelay > delay) {
                            delay = newDelay;
                            commitRateLimiter.setDelay(delay);
                        }
                    }
                } else {
                    if (commitRateLimiter != null) {
                        if (delay > 0) {
                            LOG.debug("Revision queue becoming empty. Unblocking commits");
                            commitRateLimiter.setDelay(0);
                            delay = 0;
                        }
                        if (blocking) {
                            LOG.debug("Revision queue becoming empty. Stop delaying commits.");
                            commitRateLimiter.unblockCommits();
                            blocking = false;
                        }
                    } else {
                        blocking = false;
                    }
                }
            }
        }

        private void logQueueFullWarning(String message) {
            long currTime = clock.getTime();
            if (lastQueueFullWarnTimestamp + QUEUE_FULL_WARN_INTERVAL < currTime) {
                LOG.warn("{} Suppressing further such cases for {} minutes.", message, TimeUnit.MILLISECONDS.toMinutes(QUEUE_FULL_WARN_INTERVAL));
                lastQueueFullWarnTimestamp = currTime;
            } else {
                LOG.debug(message);
            }
        }

        @Override
        public String toString() {
            return "Prefiltering BackgroundObserver for " + ChangeProcessor.this;
        }
    };
    return new FilteringObserver(bo, new Filter() {

        @Override
        public boolean excludes(NodeState root, CommitInfo info) {
            final FilterResult filterResult = evalPrefilter(root, info, getChangeSet(info));
            switch(filterResult) {
                case PREFILTERING_SKIPPED:
                    {
                        prefilterSkipCount++;
                        return false;
                    }
                case EXCLUDE:
                    {
                        prefilterExcludeCount++;
                        return true;
                    }
                case INCLUDE:
                    {
                        prefilterIncludeCount++;
                        return false;
                    }
                default:
                    {
                        LOG.info("isExcluded: unknown/unsupported filter result: " + filterResult);
                        prefilterSkipCount++;
                        return false;
                    }
            }
        }
    });
}
Also used : BackgroundObserver(org.apache.jackrabbit.oak.spi.commit.BackgroundObserver) NodeState(org.apache.jackrabbit.oak.spi.state.NodeState) FilteringDispatcher(org.apache.jackrabbit.oak.plugins.observation.FilteringDispatcher) EventFilter(org.apache.jackrabbit.oak.plugins.observation.filter.EventFilter) ChangeSetFilter(org.apache.jackrabbit.oak.plugins.observation.filter.ChangeSetFilter) Filter(org.apache.jackrabbit.oak.plugins.observation.Filter) FilteringObserver(org.apache.jackrabbit.oak.plugins.observation.FilteringObserver) CommitInfo(org.apache.jackrabbit.oak.spi.commit.CommitInfo)

Example 34 with CommitInfo

use of org.apache.jackrabbit.oak.spi.commit.CommitInfo in project jackrabbit-oak by apache.

the class NodeStoreTest method afterCommitHook.

@Test
public void afterCommitHook() throws CommitFailedException, InterruptedException {
    assumeTrue(store instanceof Observable);
    final AtomicReference<NodeState> observedRoot = new AtomicReference<NodeState>(null);
    final CountDownLatch latch = new CountDownLatch(2);
    ((Observable) store).addObserver(new Observer() {

        @Override
        public void contentChanged(@Nonnull NodeState root, @Nonnull CommitInfo info) {
            if (root.getChildNode("test").hasChildNode("newNode")) {
                observedRoot.set(checkNotNull(root));
                latch.countDown();
            }
        }
    });
    NodeState root = store.getRoot();
    NodeBuilder rootBuilder = root.builder();
    NodeBuilder testBuilder = rootBuilder.child("test");
    NodeBuilder newNodeBuilder = testBuilder.child("newNode");
    newNodeBuilder.setProperty("n", 42);
    testBuilder.getChildNode("a").remove();
    store.merge(rootBuilder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
    // triggers the observer
    NodeState newRoot = store.getRoot();
    latch.await(2, TimeUnit.SECONDS);
    NodeState after = observedRoot.get();
    assertNotNull(after);
    assertTrue(after.getChildNode("test").getChildNode("newNode").exists());
    assertFalse(after.getChildNode("test").getChildNode("a").exists());
    assertEquals(42, (long) after.getChildNode("test").getChildNode("newNode").getProperty("n").getValue(LONG));
    assertEquals(newRoot, after);
}
Also used : Observer(org.apache.jackrabbit.oak.spi.commit.Observer) AtomicReference(java.util.concurrent.atomic.AtomicReference) CommitInfo(org.apache.jackrabbit.oak.spi.commit.CommitInfo) CountDownLatch(java.util.concurrent.CountDownLatch) Observable(org.apache.jackrabbit.oak.spi.commit.Observable) Test(org.junit.Test) OakBaseTest(org.apache.jackrabbit.oak.OakBaseTest)

Example 35 with CommitInfo

use of org.apache.jackrabbit.oak.spi.commit.CommitInfo in project jackrabbit-oak by apache.

the class LuceneIndexEditorContext method getUpdatedTime.

private String getUpdatedTime(Calendar currentTime) {
    CommitInfo info = getIndexingContext().getCommitInfo();
    String checkpointTime = (String) info.getInfo().get(IndexConstants.CHECKPOINT_CREATION_TIME);
    if (checkpointTime != null) {
        return checkpointTime;
    }
    return ISO8601.format(currentTime);
}
Also used : CommitInfo(org.apache.jackrabbit.oak.spi.commit.CommitInfo)

Aggregations

CommitInfo (org.apache.jackrabbit.oak.spi.commit.CommitInfo)39 Test (org.junit.Test)29 NodeBuilder (org.apache.jackrabbit.oak.spi.state.NodeBuilder)23 NodeState (org.apache.jackrabbit.oak.spi.state.NodeState)16 CommitFailedException (org.apache.jackrabbit.oak.api.CommitFailedException)11 CommitHook (org.apache.jackrabbit.oak.spi.commit.CommitHook)9 Nonnull (javax.annotation.Nonnull)7 Observer (org.apache.jackrabbit.oak.spi.commit.Observer)7 SimpleCommitContext (org.apache.jackrabbit.oak.core.SimpleCommitContext)6 CommitContext (org.apache.jackrabbit.oak.spi.commit.CommitContext)6 OakBaseTest (org.apache.jackrabbit.oak.OakBaseTest)4 EditorHook (org.apache.jackrabbit.oak.spi.commit.EditorHook)4 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)3 AtomicReference (java.util.concurrent.atomic.AtomicReference)3 PropertyIndexEditorProvider (org.apache.jackrabbit.oak.plugins.index.property.PropertyIndexEditorProvider)3 MemoryNodeStore (org.apache.jackrabbit.oak.plugins.memory.MemoryNodeStore)3 ChangeSet (org.apache.jackrabbit.oak.plugins.observation.ChangeSet)3 EditorProvider (org.apache.jackrabbit.oak.spi.commit.EditorProvider)3 Observable (org.apache.jackrabbit.oak.spi.commit.Observable)3 NodeStore (org.apache.jackrabbit.oak.spi.state.NodeStore)3