Index: oak-core/src/main/java/org/apache/jackrabbit/oak/Oak.java
===================================================================
--- oak-core/src/main/java/org/apache/jackrabbit/oak/Oak.java (revision 1585541)
+++ oak-core/src/main/java/org/apache/jackrabbit/oak/Oak.java (working copy)
@@ -49,6 +49,7 @@
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.io.Closer;
+
import org.apache.jackrabbit.oak.api.ContentRepository;
import org.apache.jackrabbit.oak.api.ContentSession;
import org.apache.jackrabbit.oak.api.Root;
@@ -62,6 +63,8 @@
import org.apache.jackrabbit.oak.plugins.index.CompositeIndexEditorProvider;
import org.apache.jackrabbit.oak.plugins.index.IndexEditorProvider;
import org.apache.jackrabbit.oak.plugins.index.IndexUpdateProvider;
+import org.apache.jackrabbit.oak.plugins.index.property.jmx.PropertyIndexAsyncReindex;
+import org.apache.jackrabbit.oak.plugins.index.property.jmx.PropertyIndexAsyncReindexMBean;
import org.apache.jackrabbit.oak.plugins.memory.MemoryNodeStore;
import org.apache.jackrabbit.oak.query.QueryEngineSettings;
import org.apache.jackrabbit.oak.spi.commit.CommitHook;
@@ -508,6 +511,12 @@
scheduleWithFixedDelay(whiteboard, task, 5, true);
registerMBean(whiteboard, IndexStatsMBean.class,
task.getIndexStats(), IndexStatsMBean.TYPE, name);
+
+ PropertyIndexAsyncReindex asyncPI = new PropertyIndexAsyncReindex(
+ new AsyncIndexUpdate("async-reindex", store, indexEditors,
+ true), executor);
+ registerMBean(whiteboard, PropertyIndexAsyncReindexMBean.class,
+ asyncPI, PropertyIndexAsyncReindexMBean.TYPE, name);
}
registerMBean(whiteboard, QueryEngineSettingsMBean.class,
Index: oak-core/src/main/java/org/apache/jackrabbit/oak/api/jmx/RepositoryManagementMBean.java
===================================================================
--- oak-core/src/main/java/org/apache/jackrabbit/oak/api/jmx/RepositoryManagementMBean.java (revision 1585541)
+++ oak-core/src/main/java/org/apache/jackrabbit/oak/api/jmx/RepositoryManagementMBean.java (working copy)
@@ -175,4 +175,23 @@
@CheckForNull
String checkpoint(long lifetime);
+ /**
+ * Initiate a reindex operation for the property indexes marked for
+ * reindexing
+ *
+ * @return the status of the operation right after it was initiated
+ */
+ @Nonnull
+ CompositeData startPropertyIndexAsyncReindex();
+
+ /**
+ * Asynchronous Property Index reindexing status
+ *
+ * @return the status of the ongoing operation or if none the terminal
+ * status of the last operation or Status not available if
+ * none.
+ */
+ @Nonnull
+ CompositeData getPropertyIndexAsyncReindexStatus();
+
}
Index: oak-core/src/main/java/org/apache/jackrabbit/oak/management/RepositoryManager.java
===================================================================
--- oak-core/src/main/java/org/apache/jackrabbit/oak/management/RepositoryManager.java (revision 1585541)
+++ oak-core/src/main/java/org/apache/jackrabbit/oak/management/RepositoryManager.java (working copy)
@@ -35,6 +35,7 @@
import org.apache.jackrabbit.oak.api.jmx.RepositoryManagementMBean;
import org.apache.jackrabbit.oak.plugins.backup.FileStoreBackupRestoreMBean;
import org.apache.jackrabbit.oak.plugins.blob.BlobGCMBean;
+import org.apache.jackrabbit.oak.plugins.index.property.jmx.PropertyIndexAsyncReindexMBean;
import org.apache.jackrabbit.oak.spi.state.RevisionGCMBean;
import org.apache.jackrabbit.oak.spi.whiteboard.Tracker;
import org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard;
@@ -181,4 +182,30 @@
: null;
}
+ @Override
+ public CompositeData startPropertyIndexAsyncReindex() {
+ return execute(PropertyIndexAsyncReindexMBean.class,
+ new Function() {
+ @Nonnull
+ @Override
+ public Status apply(PropertyIndexAsyncReindexMBean reindexer) {
+ return fromCompositeData(reindexer
+ .startPropertyIndexAsyncReindex());
+ }
+ }).toCompositeData();
+ }
+
+ @Override
+ public CompositeData getPropertyIndexAsyncReindexStatus() {
+ return execute(PropertyIndexAsyncReindexMBean.class,
+ new Function() {
+ @Nonnull
+ @Override
+ public Status apply(PropertyIndexAsyncReindexMBean reindexer) {
+ return fromCompositeData(reindexer
+ .getPropertyIndexAsyncReindexStatus());
+ }
+ }).toCompositeData();
+ }
+
}
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 1585541)
+++ oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/AsyncIndexUpdate.java (working copy)
@@ -126,7 +126,7 @@
public void indexUpdate() throws CommitFailedException {
if (!dirty) {
dirty = true;
- preAsyncRun(store, name, indexStats);
+ preAsyncRun(store, name);
}
}
@@ -161,6 +161,7 @@
}
AsyncUpdateCallback callback = new AsyncUpdateCallback();
+ preAsyncRunStatsStats(indexStats);
IndexUpdate indexUpdate = new IndexUpdate(provider, name, after,
builder, callback);
@@ -170,7 +171,7 @@
if (callback.dirty) {
async.setProperty(name, checkpoint);
try {
- store.merge(builder, newCommitHook(name, state, indexStats),
+ store.merge(builder, newCommitHook(name, state),
CommitInfo.EMPTY);
} catch (CommitFailedException e) {
if (e != CONCURRENT_UPDATE) {
@@ -180,8 +181,10 @@
if (switchOnSync) {
reindexedDefinitions.addAll(indexUpdate
.getReindexedDefinitions());
+ } else {
+ postAsyncRunStatsStatus(indexStats);
}
- } else if (switchOnSync && !reindexedDefinitions.isEmpty()) {
+ } else if (switchOnSync) {
log.debug("No changes detected after diff, will try to switch to synchronous updates on "
+ reindexedDefinitions);
async.setProperty(name, checkpoint);
@@ -198,9 +201,10 @@
}
try {
- store.merge(builder, newCommitHook(name, state, indexStats),
+ store.merge(builder, newCommitHook(name, state),
CommitInfo.EMPTY);
reindexedDefinitions.clear();
+ postAsyncRunStatsStatus(indexStats);
} catch (CommitFailedException e) {
if (e != CONCURRENT_UPDATE) {
exception = e;
@@ -223,8 +227,7 @@
}
private static CommitHook newCommitHook(final String name,
- final PropertyState state, final AsyncIndexStats indexStats)
- throws CommitFailedException {
+ final PropertyState state) throws CommitFailedException {
return new CommitHook() {
@Override
@Nonnull
@@ -234,7 +237,7 @@
PropertyState stateAfterRebase = before.getChildNode(ASYNC)
.getProperty(name);
if (Objects.equal(state, stateAfterRebase)) {
- return postAsyncRunStatus(after.builder(), indexStats, name)
+ return postAsyncRunNodeStatus(after.builder(), name)
.getNodeState();
} else {
throw CONCURRENT_UPDATE;
@@ -243,10 +246,9 @@
};
}
- private static void preAsyncRun(NodeStore store, String name,
- AsyncIndexStats stats) throws CommitFailedException {
+ private static void preAsyncRun(NodeStore store, String name) throws CommitFailedException {
NodeBuilder builder = store.getRoot().builder();
- preAsyncRunStatus(builder, stats, name);
+ preAsyncRunNodeStatus(builder, name);
store.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
}
@@ -278,20 +280,21 @@
return false;
}
- private static void preAsyncRunStatus(NodeBuilder builder,
- AsyncIndexStats stats, String name) {
+ private static void preAsyncRunNodeStatus(NodeBuilder builder, String name) {
String now = now();
- stats.start(now);
builder.getChildNode(INDEX_DEFINITIONS_NAME)
.setProperty(name + "-status", STATUS_RUNNING)
.setProperty(name + "-start", now, Type.DATE)
.removeProperty(name + "-done");
}
- private static NodeBuilder postAsyncRunStatus(NodeBuilder builder,
- AsyncIndexStats stats, String name) {
+ private static void preAsyncRunStatsStats(AsyncIndexStats stats) {
+ stats.start(now());
+ }
+
+ private static NodeBuilder postAsyncRunNodeStatus(NodeBuilder builder,
+ String name) {
String now = now();
- stats.done(now);
builder.getChildNode(INDEX_DEFINITIONS_NAME)
.setProperty(name + "-status", STATUS_DONE)
.setProperty(name + "-done", now, Type.DATE)
@@ -299,6 +302,10 @@
return builder;
}
+ private static void postAsyncRunStatsStatus(AsyncIndexStats stats) {
+ stats.done(now());
+ }
+
private static String now() {
return ISO8601.format(Calendar.getInstance());
}
@@ -307,6 +314,10 @@
return indexStats;
}
+ public boolean isFinished() {
+ return indexStats.getStatus() == STATUS_DONE;
+ }
+
private static final class AsyncIndexStats implements IndexStatsMBean {
private String start = "";
@@ -339,6 +350,12 @@
public String getStatus() {
return status;
}
+
+ @Override
+ public String toString() {
+ return "AsyncIndexStats [start=" + start + ", done=" + done
+ + ", status=" + status + "]";
+ }
}
}
Index: oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/jmx/PropertyIndexAsyncReindex.java
===================================================================
--- oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/jmx/PropertyIndexAsyncReindex.java (revision 0)
+++ oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/jmx/PropertyIndexAsyncReindex.java (revision 0)
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jackrabbit.oak.plugins.index.property.jmx;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static java.lang.System.nanoTime;
+import static org.apache.jackrabbit.oak.management.ManagementOperation.done;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.Executor;
+
+import javax.annotation.Nonnull;
+import javax.management.openmbean.CompositeData;
+
+import org.apache.jackrabbit.oak.management.ManagementOperation;
+import org.apache.jackrabbit.oak.plugins.index.AsyncIndexUpdate;
+
+public class PropertyIndexAsyncReindex implements
+ PropertyIndexAsyncReindexMBean {
+
+ public static final String OP_NAME = "Property index asynchronous reindex";
+
+ private final AsyncIndexUpdate async;
+ private final Executor executor;
+
+ private ManagementOperation arOp = done(OP_NAME, 0);
+
+ /**
+ * @param gc
+ * Revision garbage collector
+ * @param executor
+ * executor for running the garbage collection task
+ */
+ public PropertyIndexAsyncReindex(@Nonnull AsyncIndexUpdate async,
+ @Nonnull Executor executor) {
+ this.async = checkNotNull(async);
+ this.executor = checkNotNull(executor);
+ }
+
+ @Nonnull
+ @Override
+ public CompositeData startPropertyIndexAsyncReindex() {
+ if (arOp.isDone()) {
+ arOp = new ManagementOperation(OP_NAME, new Callable() {
+ @Override
+ public Long call() throws Exception {
+ long t0 = nanoTime();
+ boolean done = false;
+ while (!done) {
+ async.run();
+ done = async.isFinished();
+ }
+ return nanoTime() - t0;
+ }
+ });
+ executor.execute(arOp);
+ }
+ return getPropertyIndexAsyncReindexStatus();
+ }
+
+ @Nonnull
+ @Override
+ public CompositeData getPropertyIndexAsyncReindexStatus() {
+ return arOp.getStatus().toCompositeData();
+ }
+}
Index: oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/jmx/PropertyIndexAsyncReindexMBean.java
===================================================================
--- oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/jmx/PropertyIndexAsyncReindexMBean.java (revision 0)
+++ oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/jmx/PropertyIndexAsyncReindexMBean.java (revision 0)
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jackrabbit.oak.plugins.index.property.jmx;
+
+import javax.annotation.Nonnull;
+import javax.management.openmbean.CompositeData;
+
+public interface PropertyIndexAsyncReindexMBean {
+
+ String TYPE = "PropertyIndexAsyncReindex";
+
+ /**
+ * Initiate a reindex operation for the property indexes marked for
+ * reindexing
+ *
+ * @return the status of the operation right after it was initiated
+ */
+ @Nonnull
+ CompositeData startPropertyIndexAsyncReindex();
+
+ /**
+ * Asynchronous Property Index reindexing status
+ *
+ * @return the status of the ongoing operation or if none the terminal
+ * status of the last operation or Status not available if
+ * none.
+ */
+ @Nonnull
+ CompositeData getPropertyIndexAsyncReindexStatus();
+
+}
Index: oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/jmx/package-info.java
===================================================================
--- oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/jmx/package-info.java (revision 0)
+++ oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/jmx/package-info.java (revision 0)
@@ -0,0 +1,22 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+@Version("0.21.0")
+@Export(optional = "provide:=true")
+package org.apache.jackrabbit.oak.plugins.index.property.jmx;
+
+import aQute.bnd.annotation.Version;
+import aQute.bnd.annotation.Export;
\ No newline at end of file