You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by ab...@apache.org on 2018/03/06 17:26:57 UTC
[2/5] lucene-solr:jira/solr-11670-2: Refactoring.
Refactoring.
Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/023d870c
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/023d870c
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/023d870c
Branch: refs/heads/jira/solr-11670-2
Commit: 023d870c6a76739bed28b00857de3aead9c8fc2a
Parents: 1ab5f1c
Author: Andrzej Bialecki <ab...@apache.org>
Authored: Mon Mar 5 13:44:23 2018 +0100
Committer: Andrzej Bialecki <ab...@apache.org>
Committed: Mon Mar 5 13:44:23 2018 +0100
----------------------------------------------------------------------
.../org/apache/solr/cloud/MaintenanceTask.java | 35 ------
.../apache/solr/cloud/MaintenanceThread.java | 104 ------------------
.../java/org/apache/solr/cloud/Overseer.java | 28 -----
.../cloud/api/collections/SplitShardCmd.java | 72 -------------
.../solr/cloud/autoscaling/AutoScaling.java | 15 +++
.../cloud/autoscaling/ExecutePlanAction.java | 3 +-
.../autoscaling/InactiveSliceCleanupAction.java | 106 +++++++++++++++++++
.../autoscaling/OverseerTriggerThread.java | 19 +++-
.../ScheduledMaintenanceTriggerTest.java | 7 ++
9 files changed, 144 insertions(+), 245 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/023d870c/solr/core/src/java/org/apache/solr/cloud/MaintenanceTask.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/MaintenanceTask.java b/solr/core/src/java/org/apache/solr/cloud/MaintenanceTask.java
deleted file mode 100644
index 5525c42..0000000
--- a/solr/core/src/java/org/apache/solr/cloud/MaintenanceTask.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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.solr.cloud;
-
-import java.io.Closeable;
-import java.io.IOException;
-
-/**
- *
- */
-public interface MaintenanceTask extends Runnable, Closeable {
-
- default String getName() {
- return getClass().getSimpleName();
- }
-
- default void close() throws IOException {
-
- }
-}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/023d870c/solr/core/src/java/org/apache/solr/cloud/MaintenanceThread.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/MaintenanceThread.java b/solr/core/src/java/org/apache/solr/cloud/MaintenanceThread.java
deleted file mode 100644
index 216beca..0000000
--- a/solr/core/src/java/org/apache/solr/cloud/MaintenanceThread.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * 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.solr.cloud;
-
-import java.io.IOException;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.ScheduledThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-
-import org.apache.solr.client.solrj.cloud.autoscaling.AlreadyExistsException;
-import org.apache.solr.client.solrj.cloud.autoscaling.SolrCloudManager;
-import org.apache.solr.common.SolrCloseable;
-import org.apache.solr.common.util.IOUtils;
-import org.apache.solr.util.DefaultSolrThreadFactory;
-
-/**
- * Responsible for running periodically some maintenance tasks.
- */
-public class MaintenanceThread implements SolrCloseable {
-
- private class Task {
- MaintenanceTask maintenanceTask;
- ScheduledFuture<?> scheduledFuture;
- }
-
- private final SolrCloudManager cloudManager;
- private final ScheduledThreadPoolExecutor taskExecutor;
- private final Map<String, Task> tasks = new ConcurrentHashMap<>();
-
- private transient boolean isClosed = false;
-
- public MaintenanceThread(SolrCloudManager cloudManager) {
- this.cloudManager = cloudManager;
- this.taskExecutor = (ScheduledThreadPoolExecutor) Executors.newScheduledThreadPool(3, new DefaultSolrThreadFactory("MaintenanceTask"));
- }
-
- public void addTask(MaintenanceTask task, int period, TimeUnit timeUnit, boolean replace) throws AlreadyExistsException {
- if (tasks.containsKey(task.getName())) {
- if (replace) {
- Task oldTask = tasks.get(task.getName());
- IOUtils.closeQuietly(oldTask.maintenanceTask);
- if (oldTask.scheduledFuture != null) {
- oldTask.scheduledFuture.cancel(false);
- }
- } else {
- throw new AlreadyExistsException(task.getName());
- }
- }
- Task t = new Task();
- t.maintenanceTask = task;
- tasks.put(task.getName(), t);
- t.scheduledFuture = taskExecutor.scheduleWithFixedDelay(task, 0,
- cloudManager.getTimeSource().convertDelay(timeUnit, period, TimeUnit.MILLISECONDS),
- TimeUnit.MILLISECONDS);
- }
-
- public void removeTask(String name) {
- Task t = tasks.get(name);
- if (t == null) {
- // ignore
- return;
- }
- IOUtils.closeQuietly(t.maintenanceTask);
- if (t.scheduledFuture != null) {
- t.scheduledFuture.cancel(false);
- }
- }
-
- @Override
- public void close() throws IOException {
- isClosed = true;
- for (Task task : tasks.values()) {
- IOUtils.closeQuietly(task.maintenanceTask);
- if (task.scheduledFuture != null) {
- task.scheduledFuture.cancel(false);
- }
- }
- tasks.clear();
- taskExecutor.shutdown();
- }
-
- @Override
- public boolean isClosed() {
- return isClosed;
- }
-}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/023d870c/solr/core/src/java/org/apache/solr/cloud/Overseer.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/Overseer.java b/solr/core/src/java/org/apache/solr/cloud/Overseer.java
index dd03a99..608fb20 100644
--- a/solr/core/src/java/org/apache/solr/cloud/Overseer.java
+++ b/solr/core/src/java/org/apache/solr/cloud/Overseer.java
@@ -484,8 +484,6 @@ public class Overseer implements SolrCloseable {
private OverseerThread triggerThread;
- private OverseerThread maintenanceThread;
-
private final ZkStateReader reader;
private final ShardHandler shardHandler;
@@ -529,11 +527,6 @@ public class Overseer implements SolrCloseable {
updaterThread = new OverseerThread(tg, new ClusterStateUpdater(reader, id, stats), "OverseerStateUpdate-" + id);
updaterThread.setDaemon(true);
- // create this early so that collection commands may register their tasks
- ThreadGroup maintenanceThreadGroup = new ThreadGroup("Overseer maintenance process");
- MaintenanceThread maintenance = new MaintenanceThread(zkController.getSolrCloudManager());
- maintenanceThread = new OverseerThread(maintenanceThreadGroup, maintenance, "OverseerMaintenanceThread-" + id);
-
ThreadGroup ccTg = new ThreadGroup("Overseer collection creation process.");
OverseerNodePrioritizer overseerPrioritizer = new OverseerNodePrioritizer(reader, adminPath, shardHandler.getShardHandlerFactory());
@@ -549,7 +542,6 @@ public class Overseer implements SolrCloseable {
updaterThread.start();
ccThread.start();
triggerThread.start();
- maintenanceThread.start();
assert ObjectReleaseTracker.track(this);
}
@@ -587,16 +579,6 @@ public class Overseer implements SolrCloseable {
public synchronized OverseerThread getTriggerThread() {
return triggerThread;
}
-
- /**
- * For tests.
- * @lucene.internal
- * @return trigger thread
- */
- public synchronized OverseerThread getMaintenanceThread() {
- return maintenanceThread;
- }
-
public synchronized void close() {
if (closed) return;
@@ -626,10 +608,6 @@ public class Overseer implements SolrCloseable {
IOUtils.closeQuietly(triggerThread);
triggerThread.interrupt();
}
- if (maintenanceThread != null) {
- IOUtils.closeQuietly(maintenanceThread);
- maintenanceThread.interrupt();
- }
if (updaterThread != null) {
try {
updaterThread.join();
@@ -645,15 +623,9 @@ public class Overseer implements SolrCloseable {
triggerThread.join();
} catch (InterruptedException e) {}
}
- if (maintenanceThread != null) {
- try {
- maintenanceThread.join();
- } catch (InterruptedException e) {}
- }
updaterThread = null;
ccThread = null;
triggerThread = null;
- maintenanceThread = null;
}
/**
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/023d870c/solr/core/src/java/org/apache/solr/cloud/api/collections/SplitShardCmd.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/api/collections/SplitShardCmd.java b/solr/core/src/java/org/apache/solr/cloud/api/collections/SplitShardCmd.java
index 3c3ae4f..03e7430 100644
--- a/solr/core/src/java/org/apache/solr/cloud/api/collections/SplitShardCmd.java
+++ b/solr/core/src/java/org/apache/solr/cloud/api/collections/SplitShardCmd.java
@@ -18,7 +18,6 @@
package org.apache.solr.cloud.api.collections;
-import java.io.IOException;
import java.lang.invoke.MethodHandles;
import java.util.ArrayList;
import java.util.Collection;
@@ -27,16 +26,12 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import org.apache.solr.client.solrj.cloud.DistributedQueue;
-import org.apache.solr.client.solrj.cloud.autoscaling.AlreadyExistsException;
import org.apache.solr.client.solrj.cloud.autoscaling.PolicyHelper;
import org.apache.solr.client.solrj.cloud.autoscaling.SolrCloudManager;
import org.apache.solr.client.solrj.request.CoreAdminRequest;
-import org.apache.solr.cloud.MaintenanceTask;
-import org.apache.solr.cloud.MaintenanceThread;
import org.apache.solr.cloud.Overseer;
import org.apache.solr.cloud.overseer.OverseerAction;
import org.apache.solr.common.SolrException;
@@ -74,24 +69,8 @@ public class SplitShardCmd implements OverseerCollectionMessageHandler.Cmd {
private final OverseerCollectionMessageHandler ocmh;
- public static final String CLEANUP_PERIOD_PROP = "split.shard.cleanup.period";
- public static final String CLEANUP_TTL_PROP = "split.shard.cleanup.ttl";
-
- public static final int DEFAULT_CLEANUP_PERIOD_SECONDS = 3600;
- public static final int DEFAULT_CLEANUP_TTL_SECONDS = 3600 * 24 * 2;
-
public SplitShardCmd(OverseerCollectionMessageHandler ocmh) {
this.ocmh = ocmh;
- int cleanupPeriod = ocmh.cloudManager.getClusterStateProvider().getClusterProperty(CLEANUP_PERIOD_PROP, DEFAULT_CLEANUP_PERIOD_SECONDS);
- int cleanupTTL = ocmh.cloudManager.getClusterStateProvider().getClusterProperty(CLEANUP_TTL_PROP, DEFAULT_CLEANUP_TTL_SECONDS);
- InactiveSliceCleanupTask task = new InactiveSliceCleanupTask(ocmh, cleanupTTL);
- try {
- ((MaintenanceThread) ocmh.overseer.getMaintenanceThread().getThread())
- .addTask(task, cleanupPeriod, TimeUnit.SECONDS, false);
- } catch (AlreadyExistsException e) { // should not happen
- log.error("Already registered cleanup task? ", e);
- throw new RuntimeException(e);
- }
}
@Override
@@ -558,55 +537,4 @@ public class SplitShardCmd implements OverseerCollectionMessageHandler.Cmd {
}
return rangesStr;
}
-
- /**
- * This maintenance task checks whether there are shards that have been inactive for a long
- * time (which usually means they are left-overs from shard splitting) and removes them after
- * their cleanupTTL period elapsed.
- */
- public static class InactiveSliceCleanupTask implements MaintenanceTask {
- private OverseerCollectionMessageHandler ocmh;
- private int cleanupTTL;
- private DeleteShardCmd cmd;
-
- public InactiveSliceCleanupTask(OverseerCollectionMessageHandler ocmh, int cleanupTTL) {
- this.ocmh = ocmh;
- this.cleanupTTL = cleanupTTL;
- cmd = (DeleteShardCmd)ocmh.commandMap.get(DELETESHARD);
- }
-
- @Override
- public synchronized void run() {
- try {
- ClusterState state = ocmh.cloudManager.getClusterStateProvider().getClusterState();
- state.forEachCollection(coll -> {
- coll.getSlices().forEach(s -> {
- if (Slice.State.INACTIVE.equals(s.getState())) {
- String tstampStr = s.getStr(ZkStateReader.STATE_TIMESTAMP_PROP);
- if (tstampStr == null || tstampStr.isEmpty()) {
- return;
- }
- long timestamp = Long.parseLong(tstampStr);
- long delta = TimeUnit.NANOSECONDS.toSeconds(ocmh.cloudManager.getTimeSource().getTime() - timestamp);
- if (delta > cleanupTTL) {
- ZkNodeProps props = new ZkNodeProps(ZkStateReader.COLLECTION_PROP, coll.getName(),
- ZkStateReader.SHARD_ID_PROP, s.getName());
- NamedList results = new NamedList();
- try {
- cmd.call(state, props, results);
- if (results.get("failure") != null) {
- throw new Exception("Failed to delete inactive shard: " + results);
- }
- } catch (Exception e) {
- log.warn("Exception deleting inactive shard " + coll.getName() + "/" + s.getName(), e);
- }
- }
- }
- });
- });
- } catch (IOException e) {
- log.warn("Error running inactive shard cleanup task", e);
- }
- }
- }
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/023d870c/solr/core/src/java/org/apache/solr/cloud/autoscaling/AutoScaling.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/autoscaling/AutoScaling.java b/solr/core/src/java/org/apache/solr/cloud/autoscaling/AutoScaling.java
index 3ebfbd0..355fb7d 100644
--- a/solr/core/src/java/org/apache/solr/cloud/autoscaling/AutoScaling.java
+++ b/solr/core/src/java/org/apache/solr/cloud/autoscaling/AutoScaling.java
@@ -183,4 +183,19 @@ public class AutoScaling {
" }";
public static final Map<String, Object> AUTO_ADD_REPLICAS_TRIGGER_PROPS = (Map) Utils.fromJSONString(AUTO_ADD_REPLICAS_TRIGGER_DSL);
+
+ public static final String SCHEDULED_MAINTENANCE_TRIGGER_DSL =
+ " {" +
+ " 'name' : '.scheduled_maintenance'," +
+ " 'event' : 'scheduled'," +
+ " 'enabled' : true," +
+ " 'actions' : [" +
+ " {" +
+ " 'name':'inactive_slice_cleanup'," +
+ " 'class':'solr.InactiveSliceCleanupAction'" +
+ " }" +
+ " ]" +
+ " }";
+
+ public static final Map<String, Object> SCHEDULED_MAINTENANCE_TRIGGER_PROPS = (Map) Utils.fromJSONString(SCHEDULED_MAINTENANCE_TRIGGER_DSL);
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/023d870c/solr/core/src/java/org/apache/solr/cloud/autoscaling/ExecutePlanAction.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/autoscaling/ExecutePlanAction.java b/solr/core/src/java/org/apache/solr/cloud/autoscaling/ExecutePlanAction.java
index bce0806..00fe50a 100644
--- a/solr/core/src/java/org/apache/solr/cloud/autoscaling/ExecutePlanAction.java
+++ b/solr/core/src/java/org/apache/solr/cloud/autoscaling/ExecutePlanAction.java
@@ -67,12 +67,11 @@ public class ExecutePlanAction extends TriggerActionBase {
log.debug("Executing operation: {}", operation.getParams());
try {
SolrResponse response = null;
- int counter = 0;
if (operation instanceof CollectionAdminRequest.AsyncCollectionAdminRequest) {
CollectionAdminRequest.AsyncCollectionAdminRequest req = (CollectionAdminRequest.AsyncCollectionAdminRequest) operation;
// waitForFinalState so that the end effects of operations are visible
req.setWaitForFinalState(true);
- String asyncId = event.getSource() + '/' + event.getId() + '/' + counter;
+ String asyncId = event.getSource() + '/' + event.getId();
String znode = saveAsyncId(cloudManager.getDistribStateManager(), event, asyncId);
log.trace("Saved requestId: {} in znode: {}", asyncId, znode);
// TODO: find a better way of using async calls using dataProvider API !!!
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/023d870c/solr/core/src/java/org/apache/solr/cloud/autoscaling/InactiveSliceCleanupAction.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/autoscaling/InactiveSliceCleanupAction.java b/solr/core/src/java/org/apache/solr/cloud/autoscaling/InactiveSliceCleanupAction.java
new file mode 100644
index 0000000..ed9db68
--- /dev/null
+++ b/solr/core/src/java/org/apache/solr/cloud/autoscaling/InactiveSliceCleanupAction.java
@@ -0,0 +1,106 @@
+/*
+ * 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.solr.cloud.autoscaling;
+
+import java.lang.invoke.MethodHandles;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.solr.client.solrj.SolrRequest;
+import org.apache.solr.client.solrj.SolrResponse;
+import org.apache.solr.client.solrj.cloud.autoscaling.SolrCloudManager;
+import org.apache.solr.client.solrj.request.CollectionAdminRequest;
+import org.apache.solr.common.cloud.ClusterState;
+import org.apache.solr.common.cloud.Slice;
+import org.apache.solr.common.cloud.ZkStateReader;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This maintenance action checks whether there are shards that have been inactive for a long
+ * time (which usually means they are left-overs from shard splitting) and removes them after
+ * their cleanupTTL period elapsed.
+ */
+public class InactiveSliceCleanupAction extends TriggerActionBase {
+ private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+ public static final String TTL_PROP = "ttl";
+
+ public static final int DEFAULT_TTL_SECONDS = 3600 * 24 * 2;
+
+ private int cleanupTTL;
+
+ @Override
+ public void init(Map<String, String> args) {
+ String cleanupStr = args.getOrDefault(TTL_PROP, String.valueOf(DEFAULT_TTL_SECONDS));
+ try {
+ cleanupTTL = Integer.parseInt(cleanupStr);
+ } catch (Exception e) {
+ log.warn("Invalid " + TTL_PROP + " value: '" + cleanupStr + "', using default " + DEFAULT_TTL_SECONDS);
+ cleanupTTL = DEFAULT_TTL_SECONDS;
+ }
+ if (cleanupTTL < 0) {
+ log.warn("Invalid " + TTL_PROP + " value: '" + cleanupStr + "', using default " + DEFAULT_TTL_SECONDS);
+ cleanupTTL = DEFAULT_TTL_SECONDS;
+ }
+ }
+
+ @Override
+ public void process(TriggerEvent event, ActionContext context) throws Exception {
+ SolrCloudManager cloudManager = context.getCloudManager();
+ ClusterState state = cloudManager.getClusterStateProvider().getClusterState();
+ Map<String, List<String>> cleaned = new LinkedHashMap<>();
+ AtomicInteger totalInactive = new AtomicInteger(0);
+ state.forEachCollection(coll ->
+ coll.getSlices().forEach(s -> {
+ if (Slice.State.INACTIVE.equals(s.getState())) {
+ totalInactive.incrementAndGet();
+ String tstampStr = s.getStr(ZkStateReader.STATE_TIMESTAMP_PROP);
+ if (tstampStr == null || tstampStr.isEmpty()) {
+ return;
+ }
+ long timestamp = Long.parseLong(tstampStr);
+ long delta = TimeUnit.NANOSECONDS.toSeconds(cloudManager.getTimeSource().getTime() - timestamp);
+ if (delta > cleanupTTL) {
+ SolrRequest req = CollectionAdminRequest.deleteShard(coll.getName(), s.getName());
+ try {
+ SolrResponse rsp = cloudManager.request(req);
+ if (rsp.getResponse().get("failure") != null) {
+ throw new Exception("Failed to delete inactive shard: " + rsp);
+ }
+ cleaned.computeIfAbsent(coll.getName(), c -> new ArrayList<>()).add(s.getName());
+ } catch (Exception e) {
+ log.warn("Exception deleting inactive shard " + coll.getName() + "/" + s.getName(), e);
+ }
+ }
+ }
+ })
+ );
+ if (totalInactive.get() > 0) {
+ Map<String, Object> results = new LinkedHashMap<>();
+ results.put("totalInactive", totalInactive.get());
+ if (!cleaned.isEmpty()) {
+ results.put("cleaned", cleaned);
+ }
+ context.getProperties().put(getName(), results);
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/023d870c/solr/core/src/java/org/apache/solr/cloud/autoscaling/OverseerTriggerThread.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/autoscaling/OverseerTriggerThread.java b/solr/core/src/java/org/apache/solr/cloud/autoscaling/OverseerTriggerThread.java
index 717e666..d75453a 100644
--- a/solr/core/src/java/org/apache/solr/cloud/autoscaling/OverseerTriggerThread.java
+++ b/solr/core/src/java/org/apache/solr/cloud/autoscaling/OverseerTriggerThread.java
@@ -121,13 +121,15 @@ public class OverseerTriggerThread implements Runnable, SolrCloseable {
int lastZnodeVersion = znodeVersion;
// we automatically add a trigger for auto add replicas if it does not exists already
+ // we also automatically add a scheduled maintenance trigger
while (!isClosed) {
try {
AutoScalingConfig autoScalingConfig = cloudManager.getDistribStateManager().getAutoScalingConfig();
- AutoScalingConfig withAutoAddReplicasTrigger = withAutoAddReplicasTrigger(autoScalingConfig);
- if (withAutoAddReplicasTrigger.equals(autoScalingConfig)) break;
- log.debug("Adding .autoAddReplicas trigger");
- cloudManager.getDistribStateManager().setData(SOLR_AUTOSCALING_CONF_PATH, Utils.toJSON(withAutoAddReplicasTrigger), withAutoAddReplicasTrigger.getZkVersion());
+ AutoScalingConfig updatedConfig = withAutoAddReplicasTrigger(autoScalingConfig);
+ updatedConfig = withScheduledMaintenanceTrigger(updatedConfig);
+ if (updatedConfig.equals(autoScalingConfig)) break;
+ log.debug("Adding .auto_add_replicas and .scheduled_maintenance triggers");
+ cloudManager.getDistribStateManager().setData(SOLR_AUTOSCALING_CONF_PATH, Utils.toJSON(updatedConfig), updatedConfig.getZkVersion());
break;
} catch (BadVersionException bve) {
// somebody else has changed the configuration so we must retry
@@ -338,6 +340,15 @@ public class OverseerTriggerThread implements Runnable, SolrCloseable {
private AutoScalingConfig withAutoAddReplicasTrigger(AutoScalingConfig autoScalingConfig) {
Map<String, Object> triggerProps = AutoScaling.AUTO_ADD_REPLICAS_TRIGGER_PROPS;
+ return withDefaultTrigger(triggerProps, autoScalingConfig);
+ }
+
+ private AutoScalingConfig withScheduledMaintenanceTrigger(AutoScalingConfig autoScalingConfig) {
+ Map<String, Object> triggerProps = AutoScaling.SCHEDULED_MAINTENANCE_TRIGGER_PROPS;
+ return withDefaultTrigger(triggerProps, autoScalingConfig);
+ }
+
+ private AutoScalingConfig withDefaultTrigger(Map<String, Object> triggerProps, AutoScalingConfig autoScalingConfig) {
String triggerName = (String) triggerProps.get("name");
Map<String, AutoScalingConfig.TriggerConfig> configs = autoScalingConfig.getTriggerConfigs();
for (AutoScalingConfig.TriggerConfig cfg : configs.values()) {
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/023d870c/solr/core/src/test/org/apache/solr/cloud/autoscaling/ScheduledMaintenanceTriggerTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/autoscaling/ScheduledMaintenanceTriggerTest.java b/solr/core/src/test/org/apache/solr/cloud/autoscaling/ScheduledMaintenanceTriggerTest.java
new file mode 100644
index 0000000..9b4cece
--- /dev/null
+++ b/solr/core/src/test/org/apache/solr/cloud/autoscaling/ScheduledMaintenanceTriggerTest.java
@@ -0,0 +1,7 @@
+package org.apache.solr.cloud.autoscaling;
+
+/**
+ *
+ */
+public class ScheduledMaintenanceTriggerTest {
+}