Search in sources :

Example 16 with VersionGCStats

use of org.apache.jackrabbit.oak.plugins.document.VersionGarbageCollector.VersionGCStats in project jackrabbit-oak by apache.

the class VersionGCDeletionTest method gcForPreviousDocs.

@Test
public void gcForPreviousDocs() throws Exception {
    DocumentStore ts = new MemoryDocumentStore();
    store = new DocumentMK.Builder().clock(clock).setDocumentStore(ts).setAsyncDelay(0).getNodeStore();
    NodeBuilder b1;
    NodeBuilder xb;
    // Create/remove "/x/split" sufficient times to split it
    boolean create = true;
    for (int i = 0; create || i < NodeDocument.NUM_REVS_THRESHOLD; i++) {
        b1 = store.getRoot().builder();
        xb = b1.child("x").child("split");
        if (!create) {
            xb.remove();
        }
        store.merge(b1, EmptyHook.INSTANCE, CommitInfo.EMPTY);
        create = !create;
    }
    store.runBackgroundOperations();
    // Count split docs
    NodeDocument doc = ts.find(Collection.NODES, "2:/x/split");
    int splitDocCount = Iterators.size(doc.getAllPreviousDocs());
    // hours
    long maxAge = 1;
    long delta = TimeUnit.MINUTES.toMillis(10);
    // Remove "/x"
    NodeBuilder b2 = store.getRoot().builder();
    b2.child("x").remove();
    store.merge(b2, EmptyHook.INSTANCE, CommitInfo.EMPTY);
    store.runBackgroundOperations();
    // Pass some time and run GC
    clock.waitUntil(clock.getTime() + HOURS.toMillis(maxAge * 2) + delta);
    VersionGarbageCollector gc = store.getVersionGarbageCollector();
    VersionGCStats stats = gc.gc(maxAge * 2, HOURS);
    // Asset GC stats
    assertEquals(2, stats.deletedDocGCCount);
    assertEquals(splitDocCount, stats.splitDocGCCount);
    // check if the deleted docs are really gone after GC
    assertNull(ts.find(Collection.NODES, "1:/x"));
    assertNull(ts.find(Collection.NODES, "2:/x/split"));
}
Also used : MemoryDocumentStore(org.apache.jackrabbit.oak.plugins.document.memory.MemoryDocumentStore) MemoryDocumentStore(org.apache.jackrabbit.oak.plugins.document.memory.MemoryDocumentStore) VersionGCStats(org.apache.jackrabbit.oak.plugins.document.VersionGarbageCollector.VersionGCStats) NodeBuilder(org.apache.jackrabbit.oak.spi.state.NodeBuilder) Test(org.junit.Test)

Example 17 with VersionGCStats

use of org.apache.jackrabbit.oak.plugins.document.VersionGarbageCollector.VersionGCStats in project jackrabbit-oak by apache.

the class VersionGCDeletionTest method queryWhileDocsAreRemoved.

// OAK-2420
@Test
public void queryWhileDocsAreRemoved() throws Exception {
    final Thread currentThread = Thread.currentThread();
    final Semaphore queries = new Semaphore(0);
    final CountDownLatch ready = new CountDownLatch(1);
    MemoryDocumentStore ms = new MemoryDocumentStore() {

        @Nonnull
        @Override
        public <T extends Document> List<T> query(Collection<T> collection, String fromKey, String toKey, int limit) {
            if (collection == Collection.NODES && Thread.currentThread() != currentThread) {
                ready.countDown();
                queries.acquireUninterruptibly();
            }
            return super.query(collection, fromKey, toKey, limit);
        }
    };
    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 < 200; 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));
    List<String> expected = Lists.newArrayList();
    // fill caches
    NodeState n = store.getRoot().getChildNode("node");
    for (ChildNodeEntry entry : n.getChildNodeEntries()) {
        expected.add(entry.getName());
    }
    assertEquals(110, expected.size());
    // invalidate the nodeChildren cache only
    store.invalidateNodeChildrenCache();
    Future<List<String>> f = newSingleThreadExecutor().submit(new Callable<List<String>>() {

        @Override
        public List<String> call() throws Exception {
            List<String> names = Lists.newArrayList();
            NodeState n = store.getRoot().getChildNode("node");
            for (ChildNodeEntry entry : n.getChildNodeEntries()) {
                names.add(entry.getName());
            }
            return names;
        }
    });
    // 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);
    assertEquals(90, stats.deletedLeafDocGCCount);
    queries.release(2);
    List<String> names = f.get();
    assertEquals(expected, names);
}
Also used : NodeState(org.apache.jackrabbit.oak.spi.state.NodeState) MemoryDocumentStore(org.apache.jackrabbit.oak.plugins.document.memory.MemoryDocumentStore) VersionGCStats(org.apache.jackrabbit.oak.plugins.document.VersionGarbageCollector.VersionGCStats) ChildNodeEntry(org.apache.jackrabbit.oak.spi.state.ChildNodeEntry) Semaphore(java.util.concurrent.Semaphore) CountDownLatch(java.util.concurrent.CountDownLatch) NodeBuilder(org.apache.jackrabbit.oak.spi.state.NodeBuilder) CommitFailedException(org.apache.jackrabbit.oak.api.CommitFailedException) List(java.util.List) Test(org.junit.Test)

Example 18 with VersionGCStats

use of org.apache.jackrabbit.oak.plugins.document.VersionGarbageCollector.VersionGCStats in project jackrabbit-oak by apache.

the class VersionGarbageCollectorIT method malformedId.

// OAK-4819
@Test
public void malformedId() throws Exception {
    // hrs
    long maxAge = 1;
    long delta = TimeUnit.MINUTES.toMillis(10);
    NodeBuilder builder = store.getRoot().builder();
    builder.child("foo");
    store.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
    // remove again
    builder = store.getRoot().builder();
    builder.child("foo").remove();
    store.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
    store.runBackgroundOperations();
    // add a document with a malformed id
    String id = "42";
    UpdateOp op = new UpdateOp(id, true);
    NodeDocument.setDeletedOnce(op);
    NodeDocument.setModified(op, store.newRevision());
    store.getDocumentStore().create(NODES, Lists.newArrayList(op));
    clock.waitUntil(clock.getTime() + HOURS.toMillis(maxAge) + delta);
    // gc must not fail
    VersionGCStats stats = gc.gc(maxAge, HOURS);
    assertEquals(1, stats.deletedDocGCCount);
    assertEquals(1, stats.deletedLeafDocGCCount);
}
Also used : VersionGCStats(org.apache.jackrabbit.oak.plugins.document.VersionGarbageCollector.VersionGCStats) NodeBuilder(org.apache.jackrabbit.oak.spi.state.NodeBuilder) Test(org.junit.Test)

Example 19 with VersionGCStats

use of org.apache.jackrabbit.oak.plugins.document.VersionGarbageCollector.VersionGCStats in project jackrabbit-oak by apache.

the class VersionGarbageCollectorIT method gcWithConcurrentModification.

// OAK-2778
@Test
public void gcWithConcurrentModification() throws Exception {
    Revision.setClock(clock);
    DocumentStore ds = store.getDocumentStore();
    // create test content
    createTestNode("foo");
    createTestNode("bar");
    // remove again
    NodeBuilder builder = store.getRoot().builder();
    builder.getChildNode("foo").remove();
    builder.getChildNode("bar").remove();
    merge(store, builder);
    // wait one hour
    clock.waitUntil(clock.getTime() + HOURS.toMillis(1));
    final BlockingQueue<NodeDocument> docs = Queues.newSynchronousQueue();
    VersionGCSupport gcSupport = new VersionGCSupport(store.getDocumentStore()) {

        @Override
        public Iterable<NodeDocument> getPossiblyDeletedDocs(long fromModified, long toModified) {
            return filter(super.getPossiblyDeletedDocs(fromModified, toModified), new Predicate<NodeDocument>() {

                @Override
                public boolean apply(NodeDocument input) {
                    try {
                        docs.put(input);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    return true;
                }
            });
        }
    };
    final VersionGarbageCollector gc = new VersionGarbageCollector(store, gcSupport);
    // start GC -> will try to remove /foo and /bar
    Future<VersionGCStats> f = execService.submit(new Callable<VersionGCStats>() {

        @Override
        public VersionGCStats call() throws Exception {
            return gc.gc(30, MINUTES);
        }
    });
    NodeDocument doc = docs.take();
    String name = PathUtils.getName(doc.getPath());
    // recreate node, which hasn't been removed yet
    name = name.equals("foo") ? "bar" : "foo";
    builder = store.getRoot().builder();
    builder.child(name);
    merge(store, builder);
    // loop over child node entries -> will populate nodeChildrenCache
    for (ChildNodeEntry cne : store.getRoot().getChildNodeEntries()) {
        cne.getName();
    }
    // invalidate cached DocumentNodeState
    DocumentNodeState state = (DocumentNodeState) store.getRoot().getChildNode(name);
    store.invalidateNodeCache(state.getPath(), store.getRoot().getLastRevision());
    while (!f.isDone()) {
        docs.poll();
    }
    // read children again after GC finished
    List<String> names = Lists.newArrayList();
    for (ChildNodeEntry cne : store.getRoot().getChildNodeEntries()) {
        names.add(cne.getName());
    }
    assertEquals(1, names.size());
    doc = ds.find(NODES, Utils.getIdFromPath("/" + names.get(0)));
    assertNotNull(doc);
    assertEquals(0, Iterators.size(doc.getAllPreviousDocs()));
    VersionGCStats stats = f.get();
    assertEquals(1, stats.deletedDocGCCount);
    assertEquals(2, stats.splitDocGCCount);
    assertEquals(0, stats.deletedLeafDocGCCount);
}
Also used : VersionGCStats(org.apache.jackrabbit.oak.plugins.document.VersionGarbageCollector.VersionGCStats) ChildNodeEntry(org.apache.jackrabbit.oak.spi.state.ChildNodeEntry) NodeBuilder(org.apache.jackrabbit.oak.spi.state.NodeBuilder) CommitFailedException(org.apache.jackrabbit.oak.api.CommitFailedException) IOException(java.io.IOException) Test(org.junit.Test)

Example 20 with VersionGCStats

use of org.apache.jackrabbit.oak.plugins.document.VersionGarbageCollector.VersionGCStats in project jackrabbit-oak by apache.

the class VersionGarbageCollectorIT method gcWithOldSweepRev.

@Test
public void gcWithOldSweepRev() throws Exception {
    // hrs
    long maxAge = 1;
    long delta = TimeUnit.MINUTES.toMillis(10);
    NodeBuilder builder = store.getRoot().builder();
    builder.child("foo").child("bar");
    merge(store, builder);
    String value = "";
    for (int i = 0; i < NUM_REVS_THRESHOLD; i++) {
        builder = store.getRoot().builder();
        value = "v" + i;
        builder.child("foo").setProperty("prop", value);
        merge(store, builder);
    }
    // trigger split of /foo
    store.runBackgroundUpdateOperations();
    // now /foo must have previous docs
    NodeDocument doc = getDoc("/foo");
    List<NodeDocument> prevDocs = ImmutableList.copyOf(doc.getAllPreviousDocs());
    assertEquals(1, prevDocs.size());
    assertEquals(SplitDocType.DEFAULT_NO_BRANCH, prevDocs.get(0).getSplitDocType());
    clock.waitUntil(clock.getTime() + HOURS.toMillis(maxAge) + delta);
    // revision gc must not collect previous doc because sweep did not run
    VersionGCStats stats = gc.gc(maxAge, HOURS);
    assertEquals(0, stats.splitDocGCCount);
    // write something to make sure sweep rev is after the split revs
    // otherwise GC won't collect the split doc
    builder = store.getRoot().builder();
    builder.child("qux");
    merge(store, builder);
    // run full background operations with sweep
    clock.waitUntil(clock.getTime() + TimeUnit.SECONDS.toMillis(NodeDocument.MODIFIED_IN_SECS_RESOLUTION * 2));
    store.runBackgroundOperations();
    // now sweep rev must be updated and revision GC can collect prev doc
    stats = gc.gc(maxAge, HOURS);
    assertEquals(1, stats.splitDocGCCount);
    doc = getDoc("/foo");
    assertNotNull(doc);
    prevDocs = ImmutableList.copyOf(doc.getAllPreviousDocs());
    assertEquals(0, prevDocs.size());
    // check value
    assertEquals(value, store.getRoot().getChildNode("foo").getString("prop"));
}
Also used : VersionGCStats(org.apache.jackrabbit.oak.plugins.document.VersionGarbageCollector.VersionGCStats) NodeBuilder(org.apache.jackrabbit.oak.spi.state.NodeBuilder) Test(org.junit.Test)

Aggregations

VersionGCStats (org.apache.jackrabbit.oak.plugins.document.VersionGarbageCollector.VersionGCStats)29 Test (org.junit.Test)26 NodeBuilder (org.apache.jackrabbit.oak.spi.state.NodeBuilder)20 MemoryDocumentStore (org.apache.jackrabbit.oak.plugins.document.memory.MemoryDocumentStore)4 ChildNodeEntry (org.apache.jackrabbit.oak.spi.state.ChildNodeEntry)3 IOException (java.io.IOException)2 InputStream (java.io.InputStream)2 CommitFailedException (org.apache.jackrabbit.oak.api.CommitFailedException)2 PropertyState (org.apache.jackrabbit.oak.api.PropertyState)2 BinaryPropertyState (org.apache.jackrabbit.oak.plugins.memory.BinaryPropertyState)2 NodeState (org.apache.jackrabbit.oak.spi.state.NodeState)2 AbstractIterator (com.google.common.collect.AbstractIterator)1 Iterator (java.util.Iterator)1 List (java.util.List)1 Map (java.util.Map)1 Random (java.util.Random)1 CountDownLatch (java.util.concurrent.CountDownLatch)1 ExecutionException (java.util.concurrent.ExecutionException)1 Semaphore (java.util.concurrent.Semaphore)1 TimeoutException (java.util.concurrent.TimeoutException)1