You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-dev@jackrabbit.apache.org by Chetan Mehrotra <ch...@gmail.com> on 2015/03/19 05:09:08 UTC
Re: svn commit: r1667590 - /jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/VersionGCDeletionTest.java
Interesting way for test case scenario construction Marcel !
Chetan Mehrotra
On Wed, Mar 18, 2015 at 10:38 PM, <mr...@apache.org> wrote:
> Author: mreutegg
> Date: Wed Mar 18 17:08:59 2015
> New Revision: 1667590
>
> URL: http://svn.apache.org/r1667590
> Log:
> OAK-2420: DocumentNodeStore revision GC may lead to NPE
>
> Test to reproduce the problem
>
> Modified:
>
> jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/VersionGCDeletionTest.java
>
> Modified:
> jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/VersionGCDeletionTest.java
> URL:
> http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/VersionGCDeletionTest.java?rev=1667590&r1=1667589&r2=1667590&view=diff
>
> ==============================================================================
> ---
> jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/VersionGCDeletionTest.java
> (original)
> +++
> jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/VersionGCDeletionTest.java
> Wed Mar 18 17:08:59 2015
> @@ -22,20 +22,31 @@ package org.apache.jackrabbit.oak.plugin
> import java.util.Collections;
> import java.util.Comparator;
> import java.util.List;
> +import java.util.concurrent.Callable;
> +import java.util.concurrent.CountDownLatch;
> +import java.util.concurrent.Future;
> +import java.util.concurrent.Semaphore;
> import java.util.concurrent.TimeUnit;
>
> import javax.annotation.Nonnull;
>
> +import org.apache.jackrabbit.oak.api.CommitFailedException;
> +import
> org.apache.jackrabbit.oak.plugins.document.VersionGarbageCollector.VersionGCStats;
> import
> org.apache.jackrabbit.oak.plugins.document.memory.MemoryDocumentStore;
> import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
> import org.apache.jackrabbit.oak.spi.commit.EmptyHook;
> +import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
> import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
> +import org.apache.jackrabbit.oak.spi.state.NodeState;
> import org.apache.jackrabbit.oak.stats.Clock;
> import org.junit.After;
> import org.junit.Before;
> +import org.junit.Ignore;
> import org.junit.Test;
>
> +import static java.util.concurrent.Executors.newSingleThreadExecutor;
> import static java.util.concurrent.TimeUnit.HOURS;
> +import static java.util.concurrent.TimeUnit.MINUTES;
> import static org.junit.Assert.assertEquals;
> import static org.junit.Assert.assertNull;
> import static org.junit.Assert.fail;
> @@ -140,7 +151,7 @@ public class VersionGCDeletionTest {
> VersionGarbageCollector gc = store.getVersionGarbageCollector();
> gc.setOverflowToDiskThreshold(100);
>
> - VersionGarbageCollector.VersionGCStats stats = gc.gc(maxAge * 2,
> HOURS);
> + VersionGCStats stats = gc.gc(maxAge * 2, HOURS);
> assertEquals(noOfDocsToDelete * 2 + 1, stats.deletedDocGCCount);
>
>
> @@ -152,6 +163,88 @@ public class VersionGCDeletionTest {
> }
> }
>
> + // OAK-2420
> + @Ignore
> + @Test
> + public void queryWhileDocsAreRemoved() throws Exception {
> + //Baseline the clock
> + clock.waitUntil(Revision.getCurrentTimestamp());
> +
> + final Thread currentThread = Thread.currentThread();
> + final Semaphore queries = new Semaphore(0);
> + final CountDownLatch ready = new CountDownLatch(1);
> + MemoryDocumentStore ms = new MemoryDocumentStore() {
> + @Override
> + public <T extends Document> T find(Collection<T> collection,
> + String key) {
> + if (Thread.currentThread() != currentThread) {
> + ready.countDown();
> + queries.acquireUninterruptibly();
> + }
> + return super.find(collection, key);
> + }
> + };
> + store = new DocumentMK.Builder().clock(clock)
> + .setDocumentStore(ms).setAsyncDelay(0).getNodeStore();
> +
> + // create nodes
> + NodeBuilder builder = store.getRoot().builder();
> + NodeBuilder node = builder.child("node");
> + for (int i = 0; i < 100; i++) {
> + node.child("c-" + i);
> + }
> + merge(store, builder);
> +
> + clock.waitUntil(clock.getTime() + HOURS.toMillis(1));
> +
> + // remove nodes
> + builder = store.getRoot().builder();
> + node = builder.child("node");
> + for (int i = 0; i < 90; i++) {
> + node.getChildNode("c-" + i).remove();
> + }
> + merge(store, builder);
> +
> + store.runBackgroundOperations();
> +
> + clock.waitUntil(clock.getTime() + HOURS.toMillis(1));
> +
> + // fill caches
> + NodeState n = store.getRoot().getChildNode("node");
> + for (ChildNodeEntry entry : n.getChildNodeEntries()) {
> + entry.getName();
> + }
> +
> + // invalidate the nodeChildren cache only
> + store.invalidateNodeChildrenCache();
> +
> + Future f = newSingleThreadExecutor().submit(new
> Callable<Object>() {
> + @Override
> + public Object call() throws Exception {
> + NodeState n = store.getRoot().getChildNode("node");
> + for (ChildNodeEntry entry : n.getChildNodeEntries()) {
> + entry.getName();
> + }
> + return null;
> + }
> + });
> +
> + // run GC once the reader thread is collecting documents
> + ready.await();
> + VersionGarbageCollector gc = store.getVersionGarbageCollector();
> + VersionGCStats stats = gc.gc(30, MINUTES);
> + assertEquals(90, stats.deletedDocGCCount);
> +
> + queries.release(100);
> +
> + f.get();
> + }
> +
> + private void merge(DocumentNodeStore store, NodeBuilder builder)
> + throws CommitFailedException {
> + store.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
> + }
> +
> private static class TestDocumentStore extends MemoryDocumentStore {
> boolean throwException;
> @Override
>
>
>