use of org.apache.jackrabbit.oak.spi.commit.CommitHook in project jackrabbit-oak by apache.
the class VersionHook method processCommit.
@Nonnull
@Override
public NodeState processCommit(NodeState before, NodeState after, CommitInfo info) throws CommitFailedException {
Set<String> existingVersionables = newHashSet();
List<EditorProvider> providers = newArrayList();
providers.add(new VersionEditorProvider());
providers.add(new VersionableCollector.Provider(existingVersionables));
providers.add(new OrphanedVersionCleaner.Provider(existingVersionables));
return compose(transform(providers, new Function<EditorProvider, CommitHook>() {
@Nullable
@Override
public CommitHook apply(@Nullable EditorProvider input) {
return new EditorHook(input);
}
})).processCommit(before, after, info);
}
use of org.apache.jackrabbit.oak.spi.commit.CommitHook 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));
}
}
use of org.apache.jackrabbit.oak.spi.commit.CommitHook in project jackrabbit-oak by apache.
the class DocumentNodeStoreStatsCollectorIT method failedMerge.
@Test
public void failedMerge() throws Exception {
CommitHook failingHook = new CommitHook() {
@Override
public NodeState processCommit(NodeState before, NodeState after, CommitInfo info) throws CommitFailedException {
throw new CommitFailedException(CommitFailedException.MERGE, 0, "");
}
};
NodeBuilder nb1 = nodeStore.getRoot().builder();
nb1.child("a");
try {
nodeStore.merge(nb1, failingHook, CommitInfo.EMPTY);
fail();
} catch (CommitFailedException ignore) {
}
verify(statsCollector).failedMerge(anyInt(), anyLong(), eq(false), eq(false));
//Should be called once more with exclusive lock
verify(statsCollector).failedMerge(anyInt(), anyLong(), eq(false), eq(true));
}
use of org.apache.jackrabbit.oak.spi.commit.CommitHook in project jackrabbit-oak by apache.
the class DocumentNodeStoreTest method nonBlockingReset.
// OAK-2620
@Test
public void nonBlockingReset() throws Exception {
final List<String> failure = Lists.newArrayList();
final AtomicReference<ReentrantReadWriteLock> mergeLock = new AtomicReference<ReentrantReadWriteLock>();
MemoryDocumentStore store = new MemoryDocumentStore() {
@Override
public <T extends Document> T findAndUpdate(Collection<T> collection, UpdateOp update) {
for (Map.Entry<Key, Operation> entry : update.getChanges().entrySet()) {
if (entry.getKey().getName().equals(NodeDocument.COLLISIONS)) {
ReentrantReadWriteLock rwLock = mergeLock.get();
if (rwLock.getReadHoldCount() > 0 || rwLock.getWriteHoldCount() > 0) {
failure.add("Branch reset still holds merge lock");
break;
}
}
}
return super.findAndUpdate(collection, update);
}
};
DocumentNodeStore ds = builderProvider.newBuilder().setDocumentStore(store).setAsyncDelay(0).getNodeStore();
// do not retry merges
ds.setMaxBackOffMillis(0);
DocumentNodeState root = ds.getRoot();
final DocumentNodeStoreBranch b = ds.createBranch(root);
// branch state is now Unmodified
assertTrue(b.getMergeLock() instanceof ReentrantReadWriteLock);
mergeLock.set((ReentrantReadWriteLock) b.getMergeLock());
NodeBuilder builder = root.builder();
builder.child("foo");
b.setRoot(builder.getNodeState());
// branch state is now InMemory
builder.child("bar");
b.setRoot(builder.getNodeState());
try {
b.merge(new CommitHook() {
@Nonnull
@Override
public NodeState processCommit(NodeState before, NodeState after, CommitInfo info) throws CommitFailedException {
NodeBuilder foo = after.builder().child("foo");
for (int i = 0; i <= DocumentMK.UPDATE_LIMIT; i++) {
foo.setProperty("prop", i);
}
throw new CommitFailedException("Fail", 0, "");
}
}, CommitInfo.EMPTY);
} catch (CommitFailedException e) {
// expected
}
for (String s : failure) {
fail(s);
}
}
use of org.apache.jackrabbit.oak.spi.commit.CommitHook 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);
}
Aggregations