Index: oak-core/src/main/java/org/apache/jackrabbit/oak/api/jmx/IndexStatsMBean.java =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/api/jmx/IndexStatsMBean.java (revision 1614595) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/api/jmx/IndexStatsMBean.java (working copy) @@ -47,4 +47,25 @@ */ String getStatus(); + /** + * Pauses the background indexing process. Future changes are not indexed + * until the {@link #resume()} method is called. + * + * The pause call will take effect on the next run cycle and will affect all + * indexes marked as 'async'. + */ + void pause(); + + /** + * Resumes the indexing process. All changes from the previous indexed state + * will be indexed. + */ + void resume(); + + /** + * + * @return the current status of the pause flag + */ + boolean isPaused(); + } Index: oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/AsyncIndexUpdate.java =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/AsyncIndexUpdate.java (revision 1614595) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/AsyncIndexUpdate.java (working copy) @@ -189,6 +189,9 @@ @Override public synchronized void run() { + if (indexStats.isPaused()) { + return; + } log.debug("Running background index task {}", name); NodeState root = store.getRoot(); @@ -365,12 +368,14 @@ return indexStats.getStatus() == STATUS_DONE; } - private static final class AsyncIndexStats implements IndexStatsMBean { + public static final class AsyncIndexStats implements IndexStatsMBean { private String start = ""; private String done = ""; private String status = STATUS_INIT; + private boolean isPaused; + public void start(String now) { status = STATUS_RUNNING; start = now; @@ -398,6 +403,22 @@ return status; } + public void pause() { + log.debug("Pausing the async indexer"); + this.isPaused = true; + } + + @Override + public void resume() { + log.debug("Resuming the async indexer"); + this.isPaused = false; + } + + @Override + public boolean isPaused() { + return this.isPaused; + } + @Override public String toString() { return "AsyncIndexStats [start=" + start + ", done=" + done Index: oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/AsyncIndexUpdateTest.java =================================================================== --- oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/AsyncIndexUpdateTest.java (revision 1614595) +++ oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/AsyncIndexUpdateTest.java (working copy) @@ -215,6 +215,41 @@ find(lookupChild, "foo", "abc")); } + @Test + public void testAsyncPause() throws Exception { + NodeStore store = new MemoryNodeStore(); + 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"); + + // merge it back in + store.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY); + + AsyncIndexUpdate async = new AsyncIndexUpdate("async", store, provider); + async.getIndexStats().pause(); + async.run(); + assertFalse(store.getRoot().getChildNode(INDEX_DEFINITIONS_NAME) + .getChildNode("rootIndex") + .hasChildNode(INDEX_CONTENT_NODE_NAME)); + + async.getIndexStats().resume(); + async.run(); + NodeState root = store.getRoot(); + + // first check that the index content nodes exist + checkPathExists(root, INDEX_DEFINITIONS_NAME, "rootIndex", + INDEX_CONTENT_NODE_NAME); + assertFalse(root.getChildNode(INDEX_DEFINITIONS_NAME).hasChildNode( + ":conflict")); + + PropertyIndexLookup lookup = new PropertyIndexLookup(root); + assertEquals(ImmutableSet.of("testRoot"), find(lookup, "foo", "abc")); + } + // OAK-1749 @Test public void branchBaseOnCheckpoint() throws Exception {