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();
}
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);
}
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;
}
}
}
});
}
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);
}
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);
}
Aggregations