use of org.apache.jackrabbit.oak.spi.state.ChildNodeEntry in project jackrabbit-oak by apache.
the class DocumentNodeStoreTest method concurrentChildOperations2.
// OAK-3646
// similar to previous test but both cluster nodes add a child node
@Test
public void concurrentChildOperations2() throws Exception {
Clock clock = new Clock.Virtual();
clock.waitUntil(System.currentTimeMillis());
Revision.setClock(clock);
MemoryDocumentStore store = new MemoryDocumentStore();
DocumentNodeStore ns1 = builderProvider.newBuilder().setClusterId(1).setAsyncDelay(0).clock(clock).setDocumentStore(store).getNodeStore();
DocumentNodeStore ns2 = builderProvider.newBuilder().setClusterId(2).setAsyncDelay(0).clock(clock).setDocumentStore(store).getNodeStore();
// create initial /foo
NodeBuilder b1 = ns1.getRoot().builder();
b1.child("foo");
merge(ns1, b1);
// make changes visible on both cluster nodes
ns1.runBackgroundOperations();
ns2.runBackgroundOperations();
// add child-1 on cluster node 1
b1 = ns1.getRoot().builder();
b1.child("foo").child("child-1");
merge(ns1, b1);
// push _lastRev updates to DocumentStore
ns1.runBackgroundOperations();
// remove child-2 on cluster node 2
NodeBuilder b2 = ns2.getRoot().builder();
b2.child("foo").child("child-2");
merge(ns2, b2);
// on cluster node 2, add of child-1 is not yet visible
List<ChildNodeEntry> children = Lists.newArrayList(ns2.getRoot().getChildNode("foo").getChildNodeEntries());
assertEquals(1, Iterables.size(children));
// this will make changes from cluster node 1 visible
ns2.runBackgroundOperations();
children = Lists.newArrayList(ns2.getRoot().getChildNode("foo").getChildNodeEntries());
assertEquals(2, Iterables.size(children));
}
use of org.apache.jackrabbit.oak.spi.state.ChildNodeEntry in project jackrabbit-oak by apache.
the class LastRevRecoveryRandomizedIT method compareAndTraverse.
private void compareAndTraverse(NodeState state, final String path, Map<String, NodeState> states) {
NodeState expected = states.remove(path);
if (expected == null) {
fail("unexpected node at " + path + " (seed=" + SEED + ")");
return;
}
comparePropertiesAgainstBaseState(state, expected, new DefaultNodeStateDiff() {
@Override
public boolean propertyAdded(PropertyState after) {
fail("unexpected property: " + path + "/" + after + " (seed=" + SEED + ")");
return super.propertyAdded(after);
}
@Override
public boolean propertyChanged(PropertyState before, PropertyState after) {
assertEquals("property mismatch on node " + path + " (seed=" + SEED + ")", before, after);
return super.propertyChanged(before, after);
}
@Override
public boolean propertyDeleted(PropertyState before) {
fail("missing property: " + path + "/" + before + " (seed=" + SEED + ")");
return super.propertyDeleted(before);
}
});
for (ChildNodeEntry entry : state.getChildNodeEntries()) {
String p = PathUtils.concat(path, entry.getName());
compareAndTraverse(entry.getNodeState(), p, states);
}
}
use of org.apache.jackrabbit.oak.spi.state.ChildNodeEntry 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);
}
use of org.apache.jackrabbit.oak.spi.state.ChildNodeEntry 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);
}
use of org.apache.jackrabbit.oak.spi.state.ChildNodeEntry in project jackrabbit-oak by apache.
the class DelegatingDocumentNodeStateTest method childNodeDecorated.
@Test
public void childNodeDecorated() throws Exception {
setMetaProps(builder);
setMetaProps(builder.child("a"));
setMetaProps(builder.child("b"));
AbstractDocumentNodeState state = DelegatingDocumentNodeState.wrap(builder.getNodeState(), NodeStateDiffer.DEFAULT_DIFFER);
assertTrue(state.getChildNode("a") instanceof AbstractDocumentNodeState);
assertTrue(state.getChildNode("b") instanceof AbstractDocumentNodeState);
assertFalse(state.hasChildNode("c"));
assertFalse(state.getChildNode("c").exists());
assertFalse(state.hasNoChildren());
for (ChildNodeEntry cne : state.getChildNodeEntries()) {
assertTrue(cne.getNodeState() instanceof AbstractDocumentNodeState);
}
assertEquals(2, state.getChildNodeCount(100));
}
Aggregations