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 2017/07/05 19:43:15 UTC
[1/5] lucene-solr:jira/solr-10996: SOLR-10996 Reduce confusion - use
EventProcessor instead of TriggerListener.
Repository: lucene-solr
Updated Branches:
refs/heads/jira/solr-10996 [created] b52e11480
SOLR-10996 Reduce confusion - use EventProcessor instead of TriggerListener.
Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/9e93a786
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/9e93a786
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/9e93a786
Branch: refs/heads/jira/solr-10996
Commit: 9e93a786939e8fb5cf361141c5017fe1e0a955bf
Parents: 8e0247e
Author: Andrzej Bialecki <ab...@apache.org>
Authored: Mon Jul 3 15:41:21 2017 +0200
Committer: Andrzej Bialecki <ab...@apache.org>
Committed: Mon Jul 3 15:41:21 2017 +0200
----------------------------------------------------------------------
.../solr/cloud/autoscaling/AutoScaling.java | 29 +++++++++++++++-----
.../cloud/autoscaling/NodeAddedTrigger.java | 20 +++++++-------
.../solr/cloud/autoscaling/NodeLostTrigger.java | 20 +++++++-------
.../cloud/autoscaling/ScheduledTriggers.java | 4 +--
.../cloud/autoscaling/NodeAddedTriggerTest.java | 16 +++++------
.../cloud/autoscaling/NodeLostTriggerTest.java | 16 +++++------
6 files changed, 60 insertions(+), 45 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/9e93a786/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 cd65090..c1d676d 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
@@ -48,6 +48,21 @@ public class AutoScaling {
AFTER_ACTION
}
+ /**
+ * Implementation of this class is used for processing events generated by a trigger.
+ */
+ public interface EventProcessor {
+
+ /**
+ * This method is executed for events produced by {@link Trigger#run()}.
+ *
+ * @param event a subclass of {@link TriggerEvent}
+ * @return true if the processor was ready to perform actions on the event, false
+ * otherwise. If false was returned then callers should assume the event was discarded.
+ */
+ boolean process(TriggerEvent event);
+ }
+
public interface TriggerListener {
/**
* This method is executed when a trigger is ready to fire.
@@ -69,8 +84,8 @@ public class AutoScaling {
/**
* Interface for a Solr trigger. Each trigger implements Runnable and Closeable interface. A trigger
* is scheduled using a {@link java.util.concurrent.ScheduledExecutorService} so it is executed as
- * per a configured schedule to check whether the trigger is ready to fire. The {@link Trigger#setListener(TriggerListener)}
- * method should be used to set a callback listener which is fired by implementation of this class whenever
+ * per a configured schedule to check whether the trigger is ready to fire. The {@link Trigger#setProcessor(EventProcessor)}
+ * method should be used to set a processor which is used by implementation of this class whenever
* ready.
* <p>
* As per the guarantees made by the {@link java.util.concurrent.ScheduledExecutorService} a trigger
@@ -79,7 +94,7 @@ public class AutoScaling {
* which can be get/set by a different thread than the one executing the trigger. Therefore, implementations
* should use appropriate synchronization around the listener.
* <p>
- * When a trigger is ready to fire, it calls the {@link TriggerListener#triggerFired(TriggerEvent)} event
+ * When a trigger is ready to fire, it calls the {@link EventProcessor#process(TriggerEvent)} event
* with the proper trigger event object. If that method returns false then it should be interpreted to mean
* that Solr is not ready to process this trigger event and therefore we should retain the state and fire
* at the next invocation of the run() method.
@@ -107,11 +122,11 @@ public class AutoScaling {
/** Actions to execute when event is fired. */
List<TriggerAction> getActions();
- /** Set event listener to call when event is fired. */
- void setListener(TriggerListener listener);
+ /** Set event processor to call when event is fired. */
+ void setProcessor(EventProcessor processor);
- /** Get event listener. */
- TriggerListener getListener();
+ /** Get event processor. */
+ EventProcessor getProcessor();
/** Return true when this trigger is closed and cannot be used. */
boolean isClosed();
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/9e93a786/solr/core/src/java/org/apache/solr/cloud/autoscaling/NodeAddedTrigger.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/autoscaling/NodeAddedTrigger.java b/solr/core/src/java/org/apache/solr/cloud/autoscaling/NodeAddedTrigger.java
index 4162ef2..c51e586 100644
--- a/solr/core/src/java/org/apache/solr/cloud/autoscaling/NodeAddedTrigger.java
+++ b/solr/core/src/java/org/apache/solr/cloud/autoscaling/NodeAddedTrigger.java
@@ -52,7 +52,7 @@ public class NodeAddedTrigger extends TriggerBase {
private final Map<String, Object> properties;
private final CoreContainer container;
private final List<TriggerAction> actions;
- private final AtomicReference<AutoScaling.TriggerListener> listenerRef;
+ private final AtomicReference<AutoScaling.EventProcessor> processorRef;
private final boolean enabled;
private final int waitForSecond;
private final AutoScaling.EventType eventType;
@@ -71,7 +71,7 @@ public class NodeAddedTrigger extends TriggerBase {
this.properties = properties;
this.container = container;
this.timeSource = TimeSource.CURRENT_TIME;
- this.listenerRef = new AtomicReference<>();
+ this.processorRef = new AtomicReference<>();
List<Map<String, String>> o = (List<Map<String, String>>) properties.get("actions");
if (o != null && !o.isEmpty()) {
actions = new ArrayList<>(3);
@@ -119,13 +119,13 @@ public class NodeAddedTrigger extends TriggerBase {
}
@Override
- public void setListener(AutoScaling.TriggerListener listener) {
- listenerRef.set(listener);
+ public void setProcessor(AutoScaling.EventProcessor processor) {
+ processorRef.set(processor);
}
@Override
- public AutoScaling.TriggerListener getListener() {
- return listenerRef.get();
+ public AutoScaling.EventProcessor getProcessor() {
+ return processorRef.get();
}
@Override
@@ -254,10 +254,10 @@ public class NodeAddedTrigger extends TriggerBase {
long now = timeSource.getTime();
if (TimeUnit.SECONDS.convert(now - timeAdded, TimeUnit.NANOSECONDS) >= getWaitForSecond()) {
// fire!
- AutoScaling.TriggerListener listener = listenerRef.get();
- if (listener != null) {
- log.debug("NodeAddedTrigger {} firing registered listener for node: {} added at time {} , now: {}", name, nodeName, timeAdded, now);
- if (listener.triggerFired(new NodeAddedEvent(getEventType(), getName(), timeAdded, nodeName))) {
+ AutoScaling.EventProcessor processor = processorRef.get();
+ if (processor != null) {
+ log.debug("NodeAddedTrigger {} firing registered processor for node: {} added at time {} , now: {}", name, nodeName, timeAdded, now);
+ if (processor.process(new NodeAddedEvent(getEventType(), getName(), timeAdded, nodeName))) {
// remove from tracking set only if the fire was accepted
it.remove();
removeNodeAddedMarker(nodeName);
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/9e93a786/solr/core/src/java/org/apache/solr/cloud/autoscaling/NodeLostTrigger.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/autoscaling/NodeLostTrigger.java b/solr/core/src/java/org/apache/solr/cloud/autoscaling/NodeLostTrigger.java
index 9db388d..d762897 100644
--- a/solr/core/src/java/org/apache/solr/cloud/autoscaling/NodeLostTrigger.java
+++ b/solr/core/src/java/org/apache/solr/cloud/autoscaling/NodeLostTrigger.java
@@ -52,7 +52,7 @@ public class NodeLostTrigger extends TriggerBase {
private final Map<String, Object> properties;
private final CoreContainer container;
private final List<TriggerAction> actions;
- private final AtomicReference<AutoScaling.TriggerListener> listenerRef;
+ private final AtomicReference<AutoScaling.EventProcessor> processorRef;
private final boolean enabled;
private final int waitForSecond;
private final AutoScaling.EventType eventType;
@@ -71,7 +71,7 @@ public class NodeLostTrigger extends TriggerBase {
this.properties = properties;
this.container = container;
this.timeSource = TimeSource.CURRENT_TIME;
- this.listenerRef = new AtomicReference<>();
+ this.processorRef = new AtomicReference<>();
List<Map<String, String>> o = (List<Map<String, String>>) properties.get("actions");
if (o != null && !o.isEmpty()) {
actions = new ArrayList<>(3);
@@ -117,13 +117,13 @@ public class NodeLostTrigger extends TriggerBase {
}
@Override
- public void setListener(AutoScaling.TriggerListener listener) {
- listenerRef.set(listener);
+ public void setProcessor(AutoScaling.EventProcessor processor) {
+ processorRef.set(processor);
}
@Override
- public AutoScaling.TriggerListener getListener() {
- return listenerRef.get();
+ public AutoScaling.EventProcessor getProcessor() {
+ return processorRef.get();
}
@Override
@@ -250,10 +250,10 @@ public class NodeLostTrigger extends TriggerBase {
Long timeRemoved = entry.getValue();
if (TimeUnit.SECONDS.convert(timeSource.getTime() - timeRemoved, TimeUnit.NANOSECONDS) >= getWaitForSecond()) {
// fire!
- AutoScaling.TriggerListener listener = listenerRef.get();
- if (listener != null) {
- log.debug("NodeLostTrigger firing registered listener");
- if (listener.triggerFired(new NodeLostEvent(getEventType(), getName(), timeRemoved, nodeName))) {
+ AutoScaling.EventProcessor processor = processorRef.get();
+ if (processor != null) {
+ log.debug("NodeLostTrigger firing registered processor");
+ if (processor.process(new NodeLostEvent(getEventType(), getName(), timeRemoved, nodeName))) {
it.remove();
removeNodeLostMarker(nodeName);
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/9e93a786/solr/core/src/java/org/apache/solr/cloud/autoscaling/ScheduledTriggers.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/autoscaling/ScheduledTriggers.java b/solr/core/src/java/org/apache/solr/cloud/autoscaling/ScheduledTriggers.java
index a15b2d1..8c18da2 100644
--- a/solr/core/src/java/org/apache/solr/cloud/autoscaling/ScheduledTriggers.java
+++ b/solr/core/src/java/org/apache/solr/cloud/autoscaling/ScheduledTriggers.java
@@ -127,7 +127,7 @@ public class ScheduledTriggers implements Closeable {
scheduledTrigger.setReplay(false);
scheduledTriggers.replace(newTrigger.getName(), scheduledTrigger);
}
- newTrigger.setListener(event -> {
+ newTrigger.setProcessor(event -> {
ScheduledTrigger scheduledSource = scheduledTriggers.get(event.getSource());
if (scheduledSource == null) {
log.warn("Ignoring autoscaling event " + event + " because the source trigger: " + event.getSource() + " doesn't exist.");
@@ -303,7 +303,7 @@ public class ScheduledTriggers implements Closeable {
while ((event = queue.peekEvent()) != null) {
// override REPLAYING=true
event.getProperties().put(TriggerEvent.REPLAYING, true);
- if (! trigger.getListener().triggerFired(event)) {
+ if (! trigger.getProcessor().process(event)) {
log.error("Failed to re-play event, discarding: " + event);
}
queue.pollEvent(); // always remove it from queue
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/9e93a786/solr/core/src/test/org/apache/solr/cloud/autoscaling/NodeAddedTriggerTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/autoscaling/NodeAddedTriggerTest.java b/solr/core/src/test/org/apache/solr/cloud/autoscaling/NodeAddedTriggerTest.java
index 1a43bd3..50f7e3d 100644
--- a/solr/core/src/test/org/apache/solr/cloud/autoscaling/NodeAddedTriggerTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/autoscaling/NodeAddedTriggerTest.java
@@ -73,13 +73,13 @@ public class NodeAddedTriggerTest extends SolrCloudTestCase {
Map<String, Object> props = createTriggerProps(waitForSeconds);
try (NodeAddedTrigger trigger = new NodeAddedTrigger("node_added_trigger", props, container)) {
- trigger.setListener(noFirstRunListener);
+ trigger.setProcessor(noFirstRunListener);
trigger.run();
JettySolrRunner newNode = cluster.startJettySolrRunner();
AtomicBoolean fired = new AtomicBoolean(false);
AtomicReference<TriggerEvent> eventRef = new AtomicReference<>();
- trigger.setListener(event -> {
+ trigger.setProcessor(event -> {
if (fired.compareAndSet(false, true)) {
eventRef.set(event);
long currentTimeNanos = timeSource.getTime();
@@ -112,12 +112,12 @@ public class NodeAddedTriggerTest extends SolrCloudTestCase {
try (NodeAddedTrigger trigger = new NodeAddedTrigger("node_added_trigger", props, container)) {
final long waitTime = 2;
props.put("waitFor", waitTime);
- trigger.setListener(noFirstRunListener);
+ trigger.setProcessor(noFirstRunListener);
trigger.run();
JettySolrRunner newNode = cluster.startJettySolrRunner();
AtomicBoolean fired = new AtomicBoolean(false);
- trigger.setListener(event -> {
+ trigger.setProcessor(event -> {
if (fired.compareAndSet(false, true)) {
long currentTimeNanos = timeSource.getTime();
long eventTimeNanos = event.getEventTime();
@@ -196,14 +196,14 @@ public class NodeAddedTriggerTest extends SolrCloudTestCase {
CoreContainer container = cluster.getJettySolrRunners().get(0).getCoreContainer();
Map<String, Object> props = createTriggerProps(0);
try (NodeAddedTrigger trigger = new NodeAddedTrigger("node_added_trigger", props, container)) {
- trigger.setListener(noFirstRunListener);
+ trigger.setProcessor(noFirstRunListener);
trigger.run(); // starts tracking live nodes
JettySolrRunner newNode = cluster.startJettySolrRunner();
AtomicInteger callCount = new AtomicInteger(0);
AtomicBoolean fired = new AtomicBoolean(false);
- trigger.setListener(event -> {
+ trigger.setProcessor(event -> {
if (callCount.incrementAndGet() < 2) {
return false;
} else {
@@ -232,7 +232,7 @@ public class NodeAddedTriggerTest extends SolrCloudTestCase {
// add a new node but update the trigger before the waitFor period expires
// and assert that the new trigger still fires
NodeAddedTrigger trigger = new NodeAddedTrigger("node_added_trigger", props, container);
- trigger.setListener(noFirstRunListener);
+ trigger.setProcessor(noFirstRunListener);
trigger.run();
JettySolrRunner newNode = cluster.startJettySolrRunner();
@@ -251,7 +251,7 @@ public class NodeAddedTriggerTest extends SolrCloudTestCase {
try (NodeAddedTrigger newTrigger = new NodeAddedTrigger("node_added_trigger", props, container)) {
AtomicBoolean fired = new AtomicBoolean(false);
AtomicReference<TriggerEvent> eventRef = new AtomicReference<>();
- newTrigger.setListener(event -> {
+ newTrigger.setProcessor(event -> {
if (fired.compareAndSet(false, true)) {
eventRef.set(event);
long currentTimeNanos = timeSource.getTime();
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/9e93a786/solr/core/src/test/org/apache/solr/cloud/autoscaling/NodeLostTriggerTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/autoscaling/NodeLostTriggerTest.java b/solr/core/src/test/org/apache/solr/cloud/autoscaling/NodeLostTriggerTest.java
index 82e1326..bb3339c 100644
--- a/solr/core/src/test/org/apache/solr/cloud/autoscaling/NodeLostTriggerTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/autoscaling/NodeLostTriggerTest.java
@@ -74,14 +74,14 @@ public class NodeLostTriggerTest extends SolrCloudTestCase {
Map<String, Object> props = createTriggerProps(waitForSeconds);
try (NodeLostTrigger trigger = new NodeLostTrigger("node_lost_trigger", props, container)) {
- trigger.setListener(noFirstRunListener);
+ trigger.setProcessor(noFirstRunListener);
trigger.run();
String lostNodeName = cluster.getJettySolrRunner(1).getNodeName();
cluster.stopJettySolrRunner(1);
AtomicBoolean fired = new AtomicBoolean(false);
AtomicReference<TriggerEvent> eventRef = new AtomicReference<>();
- trigger.setListener(event -> {
+ trigger.setProcessor(event -> {
if (fired.compareAndSet(false, true)) {
eventRef.set(event);
long currentTimeNanos = timeSource.getTime();
@@ -115,13 +115,13 @@ public class NodeLostTriggerTest extends SolrCloudTestCase {
try (NodeLostTrigger trigger = new NodeLostTrigger("node_lost_trigger", props, container)) {
final long waitTime = 2;
props.put("waitFor", waitTime);
- trigger.setListener(noFirstRunListener);
+ trigger.setProcessor(noFirstRunListener);
trigger.run();
JettySolrRunner lostNode = cluster.getJettySolrRunner(1);
lostNode.stop();
AtomicBoolean fired = new AtomicBoolean(false);
- trigger.setListener(event -> {
+ trigger.setProcessor(event -> {
if (fired.compareAndSet(false, true)) {
long currentTimeNanos = timeSource.getTime();
long eventTimeNanos = event.getEventTime();
@@ -210,7 +210,7 @@ public class NodeLostTriggerTest extends SolrCloudTestCase {
CoreContainer container = cluster.getJettySolrRunners().get(0).getCoreContainer();
Map<String, Object> props = createTriggerProps(0);
try (NodeLostTrigger trigger = new NodeLostTrigger("node_added_trigger", props, container)) {
- trigger.setListener(noFirstRunListener);
+ trigger.setProcessor(noFirstRunListener);
JettySolrRunner newNode = cluster.startJettySolrRunner();
cluster.waitForAllNodes(5);
@@ -230,7 +230,7 @@ public class NodeLostTriggerTest extends SolrCloudTestCase {
AtomicInteger callCount = new AtomicInteger(0);
AtomicBoolean fired = new AtomicBoolean(false);
- trigger.setListener(event -> {
+ trigger.setProcessor(event -> {
if (callCount.incrementAndGet() < 2) {
return false;
} else {
@@ -263,7 +263,7 @@ public class NodeLostTriggerTest extends SolrCloudTestCase {
// and assert that the new trigger still fires
NodeLostTrigger trigger = new NodeLostTrigger("node_lost_trigger", props, container);
- trigger.setListener(noFirstRunListener);
+ trigger.setProcessor(noFirstRunListener);
trigger.run();
// stop the newly created node
@@ -291,7 +291,7 @@ public class NodeLostTriggerTest extends SolrCloudTestCase {
try (NodeLostTrigger newTrigger = new NodeLostTrigger("node_lost_trigger", props, container)) {
AtomicBoolean fired = new AtomicBoolean(false);
AtomicReference<TriggerEvent> eventRef = new AtomicReference<>();
- newTrigger.setListener(event -> {
+ newTrigger.setProcessor(event -> {
if (fired.compareAndSet(false, true)) {
eventRef.set(event);
long currentTimeNanos = timeSource.getTime();
[2/5] lucene-solr:jira/solr-10996: WIP.
Posted by ab...@apache.org.
WIP.
Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/6a35a889
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/6a35a889
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/6a35a889
Branch: refs/heads/jira/solr-10996
Commit: 6a35a8896e9cdc065c7e2dd3c07f009243c981c1
Parents: 9e93a78
Author: Andrzej Bialecki <ab...@apache.org>
Authored: Tue Jul 4 10:01:49 2017 +0200
Committer: Andrzej Bialecki <ab...@apache.org>
Committed: Tue Jul 4 10:01:49 2017 +0200
----------------------------------------------------------------------
.../solr/cloud/autoscaling/AutoScaling.java | 22 ++---
.../cloud/autoscaling/AutoScalingConfig.java | 89 +++++++++++++++-----
.../cloud/autoscaling/HttpTriggerListener.java | 38 +++++++++
.../cloud/autoscaling/LogTriggerListener.java | 42 +++++++++
.../autoscaling/AutoScalingHandlerTest.java | 6 +-
.../cloud/autoscaling/NodeAddedTriggerTest.java | 10 +--
.../cloud/autoscaling/NodeLostTriggerTest.java | 10 +--
7 files changed, 172 insertions(+), 45 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/6a35a889/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 c1d676d..5f80f80 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
@@ -64,21 +64,17 @@ public class AutoScaling {
}
public interface TriggerListener {
+
+ void init(CoreContainer coreContainer);
+
/**
- * This method is executed when a trigger is ready to fire.
- *
- * @param event a subclass of {@link TriggerEvent}
- * @return true if the listener was ready to perform actions on the event, false
- * otherwise. If false was returned then callers should assume the event was discarded.
+ * This method is called when either a particular <code>stage</code> or
+ * <code>actionName</code> is reached during event processing.
+ * @param stage {@link TriggerStage} that this listener was registered for, or null
+ * @param actionName {@link TriggerAction} name that this listener was registered for, or null
+ * @param event current event being processed
*/
- boolean triggerFired(TriggerEvent event);
- }
-
- public static class HttpCallbackListener implements TriggerListener {
- @Override
- public boolean triggerFired(TriggerEvent event) {
- return true;
- }
+ void onEvent(TriggerStage stage, String actionName, TriggerEvent event);
}
/**
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/6a35a889/solr/core/src/java/org/apache/solr/cloud/autoscaling/AutoScalingConfig.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/autoscaling/AutoScalingConfig.java b/solr/core/src/java/org/apache/solr/cloud/autoscaling/AutoScalingConfig.java
index 5714ac9..753f6e9 100644
--- a/solr/core/src/java/org/apache/solr/cloud/autoscaling/AutoScalingConfig.java
+++ b/solr/core/src/java/org/apache/solr/cloud/autoscaling/AutoScalingConfig.java
@@ -16,6 +16,8 @@
*/
package org.apache.solr.cloud.autoscaling;
+import java.lang.invoke.MethodHandles;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@@ -25,12 +27,15 @@ import java.util.Map;
import org.apache.solr.client.solrj.cloud.autoscaling.Policy;
import org.apache.solr.common.params.AutoScalingParams;
import org.apache.solr.common.util.Utils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Simple bean representation of <code>autoscaling.json</code>, which parses data
* lazily.
*/
public class AutoScalingConfig {
+ private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
private final Map<String, Object> jsonMap;
@@ -42,15 +47,26 @@ public class AutoScalingConfig {
* Bean representation of {@link org.apache.solr.cloud.autoscaling.AutoScaling.TriggerListener} config.
*/
public static class ListenerConfig {
- public String trigger;
- public List<String> stages;
- public String listenerClass;
- public List<Map<String, String>> beforeActions;
- public List<Map<String, String>> afterActions;
+ public final String trigger;
+ public final List<AutoScaling.TriggerStage> stages;
+ public final String listenerClass;
+ public final List<Map<String, String>> beforeActions;
+ public final List<Map<String, String>> afterActions;
+ public final Map<String, Object> properties = new HashMap<>();
public ListenerConfig(Map<String, Object> properties) {
+ this.properties.putAll(properties);
trigger = (String)properties.get(AutoScalingParams.TRIGGER);
- stages = (List<String>)properties.getOrDefault(AutoScalingParams.STAGE, Collections.emptyList());
+ List<String> stageNames = (List<String>)properties.getOrDefault(AutoScalingParams.STAGE, Collections.emptyList());
+ stages = new ArrayList<>(stageNames.size());
+ for (String name : stageNames) {
+ try {
+ AutoScaling.TriggerStage stage = AutoScaling.TriggerStage.valueOf(name.toUpperCase(Locale.ROOT));
+ stages.add(stage);
+ } catch (Exception e) {
+ LOG.warn("Invalid stage name '" + name + "' in listener config, skipping: " + properties);
+ }
+ }
listenerClass = (String)properties.get(AutoScalingParams.CLASS);
beforeActions = (List<Map<String, String>>)properties.getOrDefault(AutoScalingParams.BEFORE_ACTION, Collections.emptyList());
afterActions = (List<Map<String, String>>)properties.getOrDefault(AutoScalingParams.AFTER_ACTION, Collections.emptyList());
@@ -80,6 +96,13 @@ public class AutoScalingConfig {
}
/**
+ * Return the original JSON map representation that was used for building this config.
+ */
+ public Map<String, Object> getJsonMap() {
+ return jsonMap;
+ }
+
+ /**
* Get {@link Policy} configuration.
*/
public Policy getPolicy() {
@@ -108,6 +131,26 @@ public class AutoScalingConfig {
}
/**
+ * Check whether triggers for specific event type exist.
+ * @param types list of event types
+ * @return true if there's at least one trigger matching at least one event type,
+ * false otherwise,
+ */
+ public boolean hasTriggerForEvents(AutoScaling.EventType... types) {
+ if (types == null || types.length == 0) {
+ return false;
+ }
+ for (TriggerConfig config : getTriggerConfigs().values()) {
+ for (AutoScaling.EventType type : types) {
+ if (config.eventType.equals(type)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
* Get listener configurations.
*/
public Map<String, ListenerConfig> getListenerConfigs() {
@@ -126,22 +169,30 @@ public class AutoScalingConfig {
}
/**
- * Check whether triggers for specific event type exist.
- * @param types list of event types
- * @return true if there's at least one trigger matching at least one event type,
- * false otherwise,
+ * Get listeners for a specific trigger name.
+ * @param triggerName name of the trigger
+ * @return a map where keys are the stages and values are the list of listener configs that apply to a
+ * particular triggerName and stage.
*/
- public boolean hasTriggerForEvents(AutoScaling.EventType... types) {
- if (types == null || types.length == 0) {
- return false;
- }
- for (TriggerConfig config : getTriggerConfigs().values()) {
- for (AutoScaling.EventType type : types) {
- if (config.eventType.equals(type)) {
- return true;
+ public Map<AutoScaling.TriggerStage, List<ListenerConfig>> getListenerConfigsForTrigger(String triggerName) {
+ Map<String, ListenerConfig> configs = getListenerConfigs();
+ if (configs.isEmpty()) {
+ return Collections.emptyMap();
+ } else {
+ Map<AutoScaling.TriggerStage, List<ListenerConfig>> res = new HashMap<>();
+ for (ListenerConfig cfg : configs.values()) {
+ if (triggerName.equals(cfg.trigger)) {
+ for (AutoScaling.TriggerStage stage : cfg.stages) {
+ List<ListenerConfig> cfgsPerStage = res.get(stage);
+ if (cfgsPerStage == null) {
+ cfgsPerStage = new ArrayList<>();
+ res.put(stage, cfgsPerStage);
+ }
+ cfgsPerStage.add(cfg);
+ }
}
}
+ return res;
}
- return false;
}
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/6a35a889/solr/core/src/java/org/apache/solr/cloud/autoscaling/HttpTriggerListener.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/autoscaling/HttpTriggerListener.java b/solr/core/src/java/org/apache/solr/cloud/autoscaling/HttpTriggerListener.java
new file mode 100644
index 0000000..57a9c31
--- /dev/null
+++ b/solr/core/src/java/org/apache/solr/cloud/autoscaling/HttpTriggerListener.java
@@ -0,0 +1,38 @@
+/*
+ * 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 org.apache.http.client.HttpClient;
+import org.apache.solr.core.CoreContainer;
+
+/**
+ * Simple HTTP callback that sends trigger events as JSON.
+ */
+public class HttpTriggerListener implements AutoScaling.TriggerListener {
+
+ private HttpClient httpClient;
+
+ @Override
+ public void init(CoreContainer coreContainer) {
+ httpClient = coreContainer.getUpdateShardHandler().getHttpClient();
+ }
+
+ @Override
+ public void onEvent(AutoScaling.TriggerStage stage, String actionName, TriggerEvent event) {
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/6a35a889/solr/core/src/java/org/apache/solr/cloud/autoscaling/LogTriggerListener.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/autoscaling/LogTriggerListener.java b/solr/core/src/java/org/apache/solr/cloud/autoscaling/LogTriggerListener.java
new file mode 100644
index 0000000..a4d4fdd
--- /dev/null
+++ b/solr/core/src/java/org/apache/solr/cloud/autoscaling/LogTriggerListener.java
@@ -0,0 +1,42 @@
+/*
+ * 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 org.apache.solr.core.CoreContainer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Implementation of {@link org.apache.solr.cloud.autoscaling.AutoScaling.TriggerListener} that reports
+ * events to a log.
+ */
+public class LogTriggerListener implements AutoScaling.TriggerListener {
+ private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+ @Override
+ public void init(CoreContainer coreContainer) {
+
+ }
+
+ @Override
+ public void onEvent(AutoScaling.TriggerStage stage, String actionName, TriggerEvent event) {
+ LOG.info("stage={}, actionName={}, event={}", stage, actionName, event);
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/6a35a889/solr/core/src/test/org/apache/solr/cloud/autoscaling/AutoScalingHandlerTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/autoscaling/AutoScalingHandlerTest.java b/solr/core/src/test/org/apache/solr/cloud/autoscaling/AutoScalingHandlerTest.java
index 06c2920..be7fb0c 100644
--- a/solr/core/src/test/org/apache/solr/cloud/autoscaling/AutoScalingHandlerTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/autoscaling/AutoScalingHandlerTest.java
@@ -356,7 +356,7 @@ public class AutoScalingHandlerTest extends SolrCloudTestCase {
"'trigger' : 'node_lost_trigger'," +
"'stage' : ['STARTED','ABORTED','SUCCEEDED']," +
"'beforeAction' : 'execute_plan'," +
- "'class' : 'org.apache.solr.cloud.autoscaling.AutoScaling$HttpCallbackListener'," +
+ "'class' : 'org.apache.solr.cloud.autoscaling.AutoScaling$HttpTriggerListener'," +
"'url' : 'http://xyz.com/on_node_lost?node={$LOST_NODE_NAME}'" +
"}" +
"}";
@@ -371,7 +371,7 @@ public class AutoScalingHandlerTest extends SolrCloudTestCase {
assertTrue(listeners.containsKey("xyz"));
Map<String, Object> xyzListener = (Map<String, Object>) listeners.get("xyz");
assertEquals(5, xyzListener.size());
- assertEquals("org.apache.solr.cloud.autoscaling.AutoScaling$HttpCallbackListener", xyzListener.get("class").toString());
+ assertEquals("org.apache.solr.cloud.autoscaling.AutoScaling$HttpTriggerListener", xyzListener.get("class").toString());
String removeTriggerCommand = "{" +
"'remove-trigger' : {" +
@@ -422,7 +422,7 @@ public class AutoScalingHandlerTest extends SolrCloudTestCase {
"'trigger' : 'node_lost_trigger'," +
"'stage' : ['STARTED','ABORTED','SUCCEEDED']," +
"'beforeAction' : 'execute_plan'," +
- "'class' : 'org.apache.solr.cloud.autoscaling.AutoScaling$HttpCallbackListener'," +
+ "'class' : 'org.apache.solr.cloud.autoscaling.AutoScaling$HttpTriggerListener'," +
"'url' : 'http://xyz.com/on_node_lost?node={$LOST_NODE_NAME}'" +
"}" +
"}";
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/6a35a889/solr/core/src/test/org/apache/solr/cloud/autoscaling/NodeAddedTriggerTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/autoscaling/NodeAddedTriggerTest.java b/solr/core/src/test/org/apache/solr/cloud/autoscaling/NodeAddedTriggerTest.java
index 50f7e3d..a2beed4 100644
--- a/solr/core/src/test/org/apache/solr/cloud/autoscaling/NodeAddedTriggerTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/autoscaling/NodeAddedTriggerTest.java
@@ -43,7 +43,7 @@ public class NodeAddedTriggerTest extends SolrCloudTestCase {
private static AtomicBoolean actionInitCalled = new AtomicBoolean(false);
private static AtomicBoolean actionCloseCalled = new AtomicBoolean(false);
- private AutoScaling.TriggerListener noFirstRunListener = event -> {
+ private AutoScaling.EventProcessor noFirstRunProcessor = event -> {
fail("Did not expect the listener to fire on first run!");
return true;
};
@@ -73,7 +73,7 @@ public class NodeAddedTriggerTest extends SolrCloudTestCase {
Map<String, Object> props = createTriggerProps(waitForSeconds);
try (NodeAddedTrigger trigger = new NodeAddedTrigger("node_added_trigger", props, container)) {
- trigger.setProcessor(noFirstRunListener);
+ trigger.setProcessor(noFirstRunProcessor);
trigger.run();
JettySolrRunner newNode = cluster.startJettySolrRunner();
@@ -112,7 +112,7 @@ public class NodeAddedTriggerTest extends SolrCloudTestCase {
try (NodeAddedTrigger trigger = new NodeAddedTrigger("node_added_trigger", props, container)) {
final long waitTime = 2;
props.put("waitFor", waitTime);
- trigger.setProcessor(noFirstRunListener);
+ trigger.setProcessor(noFirstRunProcessor);
trigger.run();
JettySolrRunner newNode = cluster.startJettySolrRunner();
@@ -196,7 +196,7 @@ public class NodeAddedTriggerTest extends SolrCloudTestCase {
CoreContainer container = cluster.getJettySolrRunners().get(0).getCoreContainer();
Map<String, Object> props = createTriggerProps(0);
try (NodeAddedTrigger trigger = new NodeAddedTrigger("node_added_trigger", props, container)) {
- trigger.setProcessor(noFirstRunListener);
+ trigger.setProcessor(noFirstRunProcessor);
trigger.run(); // starts tracking live nodes
JettySolrRunner newNode = cluster.startJettySolrRunner();
@@ -232,7 +232,7 @@ public class NodeAddedTriggerTest extends SolrCloudTestCase {
// add a new node but update the trigger before the waitFor period expires
// and assert that the new trigger still fires
NodeAddedTrigger trigger = new NodeAddedTrigger("node_added_trigger", props, container);
- trigger.setProcessor(noFirstRunListener);
+ trigger.setProcessor(noFirstRunProcessor);
trigger.run();
JettySolrRunner newNode = cluster.startJettySolrRunner();
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/6a35a889/solr/core/src/test/org/apache/solr/cloud/autoscaling/NodeLostTriggerTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/autoscaling/NodeLostTriggerTest.java b/solr/core/src/test/org/apache/solr/cloud/autoscaling/NodeLostTriggerTest.java
index bb3339c..2492ce2 100644
--- a/solr/core/src/test/org/apache/solr/cloud/autoscaling/NodeLostTriggerTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/autoscaling/NodeLostTriggerTest.java
@@ -43,7 +43,7 @@ public class NodeLostTriggerTest extends SolrCloudTestCase {
private static AtomicBoolean actionInitCalled = new AtomicBoolean(false);
private static AtomicBoolean actionCloseCalled = new AtomicBoolean(false);
- private AutoScaling.TriggerListener noFirstRunListener = event -> {
+ private AutoScaling.EventProcessor noFirstRunProcessor = event -> {
fail("Did not expect the listener to fire on first run!");
return true;
};
@@ -74,7 +74,7 @@ public class NodeLostTriggerTest extends SolrCloudTestCase {
Map<String, Object> props = createTriggerProps(waitForSeconds);
try (NodeLostTrigger trigger = new NodeLostTrigger("node_lost_trigger", props, container)) {
- trigger.setProcessor(noFirstRunListener);
+ trigger.setProcessor(noFirstRunProcessor);
trigger.run();
String lostNodeName = cluster.getJettySolrRunner(1).getNodeName();
cluster.stopJettySolrRunner(1);
@@ -115,7 +115,7 @@ public class NodeLostTriggerTest extends SolrCloudTestCase {
try (NodeLostTrigger trigger = new NodeLostTrigger("node_lost_trigger", props, container)) {
final long waitTime = 2;
props.put("waitFor", waitTime);
- trigger.setProcessor(noFirstRunListener);
+ trigger.setProcessor(noFirstRunProcessor);
trigger.run();
JettySolrRunner lostNode = cluster.getJettySolrRunner(1);
@@ -210,7 +210,7 @@ public class NodeLostTriggerTest extends SolrCloudTestCase {
CoreContainer container = cluster.getJettySolrRunners().get(0).getCoreContainer();
Map<String, Object> props = createTriggerProps(0);
try (NodeLostTrigger trigger = new NodeLostTrigger("node_added_trigger", props, container)) {
- trigger.setProcessor(noFirstRunListener);
+ trigger.setProcessor(noFirstRunProcessor);
JettySolrRunner newNode = cluster.startJettySolrRunner();
cluster.waitForAllNodes(5);
@@ -263,7 +263,7 @@ public class NodeLostTriggerTest extends SolrCloudTestCase {
// and assert that the new trigger still fires
NodeLostTrigger trigger = new NodeLostTrigger("node_lost_trigger", props, container);
- trigger.setProcessor(noFirstRunListener);
+ trigger.setProcessor(noFirstRunProcessor);
trigger.run();
// stop the newly created node
[3/5] lucene-solr:jira/solr-10996: SOLR-10996: Implement
TriggerListener hooks and initializations.
Posted by ab...@apache.org.
SOLR-10996: Implement TriggerListener hooks and initializations.
Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/f17f3e6a
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/f17f3e6a
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/f17f3e6a
Branch: refs/heads/jira/solr-10996
Commit: f17f3e6a2b1da75ca95ee282fa0e1fb5b8d933e1
Parents: 6a35a88
Author: Andrzej Bialecki <ab...@apache.org>
Authored: Wed Jul 5 14:35:46 2017 +0200
Committer: Andrzej Bialecki <ab...@apache.org>
Committed: Wed Jul 5 14:35:46 2017 +0200
----------------------------------------------------------------------
.../solr/cloud/autoscaling/AutoScaling.java | 19 ++-
.../cloud/autoscaling/AutoScalingConfig.java | 57 +++-----
.../cloud/autoscaling/AutoScalingHandler.java | 2 +-
.../cloud/autoscaling/HttpTriggerListener.java | 18 ++-
.../cloud/autoscaling/LogTriggerListener.java | 19 ++-
.../autoscaling/OverseerTriggerThread.java | 24 ++--
.../cloud/autoscaling/ScheduledTriggers.java | 136 ++++++++++++++++++-
.../autoscaling/AutoScalingHandlerTest.java | 4 +-
8 files changed, 212 insertions(+), 67 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f17f3e6a/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 5f80f80..c1a1169 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
@@ -38,7 +38,7 @@ public class AutoScaling {
INDEXRATE
}
- public enum TriggerStage {
+ public enum EventProcessorStage {
WAITING,
STARTED,
ABORTED,
@@ -49,7 +49,7 @@ public class AutoScaling {
}
/**
- * Implementation of this class is used for processing events generated by a trigger.
+ * Implementation of this interface is used for processing events generated by a trigger.
*/
public interface EventProcessor {
@@ -63,18 +63,25 @@ public class AutoScaling {
boolean process(TriggerEvent event);
}
- public interface TriggerListener {
+ /**
+ * Implementations of this interface are notified of stages in event processing that they were
+ * registered for. Note: instances may be closed and re-created on each auto-scaling config update.
+ */
+ public interface TriggerListener extends Closeable {
+
+ void init(CoreContainer coreContainer, AutoScalingConfig.TriggerListenerConfig config);
- void init(CoreContainer coreContainer);
+ AutoScalingConfig.TriggerListenerConfig getTriggerListenerConfig();
/**
* This method is called when either a particular <code>stage</code> or
* <code>actionName</code> is reached during event processing.
- * @param stage {@link TriggerStage} that this listener was registered for, or null
+ * @param stage {@link EventProcessorStage} that this listener was registered for, or null
* @param actionName {@link TriggerAction} name that this listener was registered for, or null
* @param event current event being processed
+ * @param message optional message
*/
- void onEvent(TriggerStage stage, String actionName, TriggerEvent event);
+ void onEvent(EventProcessorStage stage, String actionName, TriggerEvent event, String message);
}
/**
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f17f3e6a/solr/core/src/java/org/apache/solr/cloud/autoscaling/AutoScalingConfig.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/autoscaling/AutoScalingConfig.java b/solr/core/src/java/org/apache/solr/cloud/autoscaling/AutoScalingConfig.java
index 753f6e9..f2c251c 100644
--- a/solr/core/src/java/org/apache/solr/cloud/autoscaling/AutoScalingConfig.java
+++ b/solr/core/src/java/org/apache/solr/cloud/autoscaling/AutoScalingConfig.java
@@ -20,9 +20,11 @@ import java.lang.invoke.MethodHandles;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
+import java.util.Set;
import org.apache.solr.client.solrj.cloud.autoscaling.Policy;
import org.apache.solr.common.params.AutoScalingParams;
@@ -41,35 +43,35 @@ public class AutoScalingConfig {
private Policy policy;
private Map<String, TriggerConfig> triggers;
- private Map<String, ListenerConfig> listeners;
+ private Map<String, TriggerListenerConfig> listeners;
/**
* Bean representation of {@link org.apache.solr.cloud.autoscaling.AutoScaling.TriggerListener} config.
*/
- public static class ListenerConfig {
+ public static class TriggerListenerConfig {
public final String trigger;
- public final List<AutoScaling.TriggerStage> stages;
+ public final Set<AutoScaling.EventProcessorStage> stages;
public final String listenerClass;
- public final List<Map<String, String>> beforeActions;
- public final List<Map<String, String>> afterActions;
+ public final Set<String> beforeActions;
+ public final Set<String> afterActions;
public final Map<String, Object> properties = new HashMap<>();
- public ListenerConfig(Map<String, Object> properties) {
+ public TriggerListenerConfig(Map<String, Object> properties) {
this.properties.putAll(properties);
trigger = (String)properties.get(AutoScalingParams.TRIGGER);
List<String> stageNames = (List<String>)properties.getOrDefault(AutoScalingParams.STAGE, Collections.emptyList());
- stages = new ArrayList<>(stageNames.size());
+ stages = new HashSet<>(stageNames.size());
for (String name : stageNames) {
try {
- AutoScaling.TriggerStage stage = AutoScaling.TriggerStage.valueOf(name.toUpperCase(Locale.ROOT));
+ AutoScaling.EventProcessorStage stage = AutoScaling.EventProcessorStage.valueOf(name.toUpperCase(Locale.ROOT));
stages.add(stage);
} catch (Exception e) {
LOG.warn("Invalid stage name '" + name + "' in listener config, skipping: " + properties);
}
}
listenerClass = (String)properties.get(AutoScalingParams.CLASS);
- beforeActions = (List<Map<String, String>>)properties.getOrDefault(AutoScalingParams.BEFORE_ACTION, Collections.emptyList());
- afterActions = (List<Map<String, String>>)properties.getOrDefault(AutoScalingParams.AFTER_ACTION, Collections.emptyList());
+ beforeActions = new HashSet<>((List<String>)properties.getOrDefault(AutoScalingParams.BEFORE_ACTION, Collections.emptyList()));
+ afterActions = new HashSet<>((List<String>)properties.getOrDefault(AutoScalingParams.AFTER_ACTION, Collections.emptyList()));
}
}
@@ -87,6 +89,10 @@ public class AutoScalingConfig {
}
}
+ public AutoScalingConfig(byte[] utf8) {
+ this(utf8 != null && utf8.length > 0 ? (Map<String, Object>)Utils.fromJSON(utf8) : Collections.emptyMap());
+ }
+
/**
* Construct from a JSON map representation.
* @param jsonMap
@@ -153,7 +159,7 @@ public class AutoScalingConfig {
/**
* Get listener configurations.
*/
- public Map<String, ListenerConfig> getListenerConfigs() {
+ public Map<String, TriggerListenerConfig> getTriggerListenerConfigs() {
if (listeners == null) {
Map<String, Object> map = (Map<String, Object>)jsonMap.get("listeners");
if (map == null) {
@@ -161,38 +167,11 @@ public class AutoScalingConfig {
} else {
listeners = new HashMap<>(map.size());
for (Map.Entry<String, Object> entry : map.entrySet()) {
- listeners.put(entry.getKey(), new ListenerConfig((Map<String, Object>)entry.getValue()));
+ listeners.put(entry.getKey(), new TriggerListenerConfig((Map<String, Object>)entry.getValue()));
}
}
}
return listeners;
}
- /**
- * Get listeners for a specific trigger name.
- * @param triggerName name of the trigger
- * @return a map where keys are the stages and values are the list of listener configs that apply to a
- * particular triggerName and stage.
- */
- public Map<AutoScaling.TriggerStage, List<ListenerConfig>> getListenerConfigsForTrigger(String triggerName) {
- Map<String, ListenerConfig> configs = getListenerConfigs();
- if (configs.isEmpty()) {
- return Collections.emptyMap();
- } else {
- Map<AutoScaling.TriggerStage, List<ListenerConfig>> res = new HashMap<>();
- for (ListenerConfig cfg : configs.values()) {
- if (triggerName.equals(cfg.trigger)) {
- for (AutoScaling.TriggerStage stage : cfg.stages) {
- List<ListenerConfig> cfgsPerStage = res.get(stage);
- if (cfgsPerStage == null) {
- cfgsPerStage = new ArrayList<>();
- res.put(stage, cfgsPerStage);
- }
- cfgsPerStage.add(cfg);
- }
- }
- }
- return res;
- }
- }
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f17f3e6a/solr/core/src/java/org/apache/solr/cloud/autoscaling/AutoScalingHandler.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/autoscaling/AutoScalingHandler.java b/solr/core/src/java/org/apache/solr/cloud/autoscaling/AutoScalingHandler.java
index ed29542..5f877b8 100644
--- a/solr/core/src/java/org/apache/solr/cloud/autoscaling/AutoScalingHandler.java
+++ b/solr/core/src/java/org/apache/solr/cloud/autoscaling/AutoScalingHandler.java
@@ -379,7 +379,7 @@ public class AutoScalingHandler extends RequestHandlerBase implements Permission
for (String stage : stageNames) {
try {
- AutoScaling.TriggerStage.valueOf(stage);
+ AutoScaling.EventProcessorStage.valueOf(stage);
} catch (IllegalArgumentException e) {
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Invalid stage name: " + stage);
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f17f3e6a/solr/core/src/java/org/apache/solr/cloud/autoscaling/HttpTriggerListener.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/autoscaling/HttpTriggerListener.java b/solr/core/src/java/org/apache/solr/cloud/autoscaling/HttpTriggerListener.java
index 57a9c31..84cccf0 100644
--- a/solr/core/src/java/org/apache/solr/cloud/autoscaling/HttpTriggerListener.java
+++ b/solr/core/src/java/org/apache/solr/cloud/autoscaling/HttpTriggerListener.java
@@ -16,6 +16,8 @@
*/
package org.apache.solr.cloud.autoscaling;
+import java.io.IOException;
+
import org.apache.http.client.HttpClient;
import org.apache.solr.core.CoreContainer;
@@ -25,14 +27,26 @@ import org.apache.solr.core.CoreContainer;
public class HttpTriggerListener implements AutoScaling.TriggerListener {
private HttpClient httpClient;
+ private AutoScalingConfig.TriggerListenerConfig config;
@Override
- public void init(CoreContainer coreContainer) {
+ public void init(CoreContainer coreContainer, AutoScalingConfig.TriggerListenerConfig config) {
+ this.config = config;
httpClient = coreContainer.getUpdateShardHandler().getHttpClient();
}
@Override
- public void onEvent(AutoScaling.TriggerStage stage, String actionName, TriggerEvent event) {
+ public void onEvent(AutoScaling.EventProcessorStage stage, String actionName, TriggerEvent event, String message) {
+
+ }
+
+ @Override
+ public AutoScalingConfig.TriggerListenerConfig getTriggerListenerConfig() {
+ return config;
+ }
+
+ @Override
+ public void close() throws IOException {
}
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f17f3e6a/solr/core/src/java/org/apache/solr/cloud/autoscaling/LogTriggerListener.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/autoscaling/LogTriggerListener.java b/solr/core/src/java/org/apache/solr/cloud/autoscaling/LogTriggerListener.java
index a4d4fdd..2246b73 100644
--- a/solr/core/src/java/org/apache/solr/cloud/autoscaling/LogTriggerListener.java
+++ b/solr/core/src/java/org/apache/solr/cloud/autoscaling/LogTriggerListener.java
@@ -17,6 +17,7 @@
package org.apache.solr.cloud.autoscaling;
+import java.io.IOException;
import java.lang.invoke.MethodHandles;
import org.apache.solr.core.CoreContainer;
@@ -30,13 +31,25 @@ import org.slf4j.LoggerFactory;
public class LogTriggerListener implements AutoScaling.TriggerListener {
private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+ private AutoScalingConfig.TriggerListenerConfig config;
+
@Override
- public void init(CoreContainer coreContainer) {
+ public void init(CoreContainer coreContainer, AutoScalingConfig.TriggerListenerConfig config) {
+ this.config = config;
+ }
+ @Override
+ public AutoScalingConfig.TriggerListenerConfig getTriggerListenerConfig() {
+ return config;
}
@Override
- public void onEvent(AutoScaling.TriggerStage stage, String actionName, TriggerEvent event) {
- LOG.info("stage={}, actionName={}, event={}", stage, actionName, event);
+ public void onEvent(AutoScaling.EventProcessorStage stage, String actionName, TriggerEvent event, String message) {
+ LOG.info("stage={}, actionName={}, event={}, messsage={}", stage, actionName, event, message);
+ }
+
+ @Override
+ public void close() throws IOException {
+
}
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f17f3e6a/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 d7fc47e..3666e1b 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
@@ -37,6 +37,7 @@ import org.apache.solr.common.cloud.ZkStateReader;
import org.apache.solr.common.cloud.ZooKeeperException;
import org.apache.solr.common.params.AutoScalingParams;
import org.apache.solr.common.util.IOUtils;
+import org.apache.solr.common.util.Utils;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
@@ -75,6 +76,8 @@ public class OverseerTriggerThread implements Runnable, Closeable {
private boolean isClosed = false;
+ private AutoScalingConfig autoScalingConfig;
+
public OverseerTriggerThread(ZkController zkController) {
this.zkController = zkController;
zkStateReader = zkController.getZkStateReader();
@@ -163,6 +166,9 @@ public class OverseerTriggerThread implements Runnable, Closeable {
break;
}
+ // update the current config
+ scheduledTriggers.setAutoScalingConfig(autoScalingConfig);
+
Set<String> managedTriggerNames = scheduledTriggers.getScheduledTriggerNames();
// remove the triggers which are no longer active
for (String managedTriggerName : managedTriggerNames) {
@@ -265,8 +271,9 @@ public class OverseerTriggerThread implements Runnable, Closeable {
// protect against reordered watcher fires by ensuring that we only move forward
return;
}
+ autoScalingConfig = new AutoScalingConfig(data);
znodeVersion = stat.getVersion();
- Map<String, AutoScaling.Trigger> triggerMap = loadTriggers(triggerFactory, data);
+ Map<String, AutoScaling.Trigger> triggerMap = loadTriggers(triggerFactory, autoScalingConfig);
// remove all active triggers that have been removed from ZK
Set<String> trackingKeySet = activeTriggers.keySet();
@@ -288,22 +295,19 @@ public class OverseerTriggerThread implements Runnable, Closeable {
}
}
- private static Map<String, AutoScaling.Trigger> loadTriggers(AutoScaling.TriggerFactory triggerFactory, byte[] data) {
- ZkNodeProps loaded = ZkNodeProps.load(data);
- Map<String, Object> triggers = (Map<String, Object>) loaded.get("triggers");
-
+ private static Map<String, AutoScaling.Trigger> loadTriggers(AutoScaling.TriggerFactory triggerFactory, AutoScalingConfig autoScalingConfig) {
+ Map<String, AutoScalingConfig.TriggerConfig> triggers = autoScalingConfig.getTriggerConfigs();
if (triggers == null) {
return Collections.emptyMap();
}
Map<String, AutoScaling.Trigger> triggerMap = new HashMap<>(triggers.size());
- for (Map.Entry<String, Object> entry : triggers.entrySet()) {
- Map<String, Object> props = (Map<String, Object>) entry.getValue();
- String event = (String) props.get(AutoScalingParams.EVENT);
- AutoScaling.EventType eventType = AutoScaling.EventType.valueOf(event.toUpperCase(Locale.ROOT));
+ for (Map.Entry<String, AutoScalingConfig.TriggerConfig> entry : triggers.entrySet()) {
+ AutoScalingConfig.TriggerConfig cfg = entry.getValue();
+ AutoScaling.EventType eventType = cfg.eventType;
String triggerName = entry.getKey();
- triggerMap.put(triggerName, triggerFactory.create(eventType, triggerName, props));
+ triggerMap.put(triggerName, triggerFactory.create(eventType, triggerName, cfg.properties));
}
return triggerMap;
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f17f3e6a/solr/core/src/java/org/apache/solr/cloud/autoscaling/ScheduledTriggers.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/autoscaling/ScheduledTriggers.java b/solr/core/src/java/org/apache/solr/cloud/autoscaling/ScheduledTriggers.java
index 8c18da2..1be62a4 100644
--- a/solr/core/src/java/org/apache/solr/cloud/autoscaling/ScheduledTriggers.java
+++ b/solr/core/src/java/org/apache/solr/cloud/autoscaling/ScheduledTriggers.java
@@ -34,6 +34,7 @@ import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.locks.ReentrantLock;
import org.apache.lucene.store.AlreadyClosedException;
import org.apache.solr.cloud.ActionThrottle;
@@ -85,6 +86,10 @@ public class ScheduledTriggers implements Closeable {
private final CoreContainer coreContainer;
+ private final TriggerListeners listeners;
+
+ private AutoScalingConfig autoScalingConfig;
+
public ScheduledTriggers(ZkController zkController) {
// todo make the core pool size configurable
// it is important to use more than one because a time taking trigger can starve other scheduled triggers
@@ -98,9 +103,20 @@ public class ScheduledTriggers implements Closeable {
actionExecutor = ExecutorUtil.newMDCAwareSingleThreadExecutor(new DefaultSolrThreadFactory("AutoscalingActionExecutor"));
// todo make the wait time configurable
actionThrottle = new ActionThrottle("action", DEFAULT_MIN_MS_BETWEEN_ACTIONS);
- this.coreContainer = zkController.getCoreContainer();
- this.zkClient = zkController.getZkClient();
+ coreContainer = zkController.getCoreContainer();
+ zkClient = zkController.getZkClient();
queueStats = new Overseer.Stats();
+ listeners = new TriggerListeners();
+ }
+
+ /**
+ * Set the current autoscaling config. This is invoked by {@link OverseerTriggerThread} when autoscaling.json is updated,
+ * and it re-initializes trigger listeners.
+ * @param autoScalingConfig current autoscaling.json
+ */
+ public void setAutoScalingConfig(AutoScalingConfig autoScalingConfig) {
+ this.autoScalingConfig = autoScalingConfig;
+ listeners.setAutoScalingConfig(autoScalingConfig);
}
/**
@@ -128,15 +144,20 @@ public class ScheduledTriggers implements Closeable {
scheduledTriggers.replace(newTrigger.getName(), scheduledTrigger);
}
newTrigger.setProcessor(event -> {
+ listeners.fireListeners(event.getSource(), AutoScaling.EventProcessorStage.STARTED, null, event, null);
ScheduledTrigger scheduledSource = scheduledTriggers.get(event.getSource());
if (scheduledSource == null) {
- log.warn("Ignoring autoscaling event " + event + " because the source trigger: " + event.getSource() + " doesn't exist.");
+ String msg = String.format("Ignoring autoscaling event {} because the source trigger: {} doesn't exist.", event.toString(), event.getSource());
+ listeners.fireListeners(event.getSource(), AutoScaling.EventProcessorStage.FAILED, null, event, msg);
+ log.warn(msg);
return false;
}
boolean replaying = event.getProperty(TriggerEvent.REPLAYING) != null ? (Boolean)event.getProperty(TriggerEvent.REPLAYING) : false;
AutoScaling.Trigger source = scheduledSource.trigger;
if (source.isClosed()) {
- log.warn("Ignoring autoscaling event " + event + " because the source trigger: " + source + " has already been closed");
+ String msg = String.format("Ignoring autoscaling event {} because the source trigger: {} has already been closed", event.toString(), source);
+ listeners.fireListeners(event.getSource(), AutoScaling.EventProcessorStage.ABORTED, null, event, msg);
+ log.warn(msg);
// we do not want to lose this event just because the trigger was closed, perhaps a replacement will need it
return false;
}
@@ -158,17 +179,21 @@ public class ScheduledTriggers implements Closeable {
actionThrottle.markAttemptingAction();
ActionContext actionContext = new ActionContext(coreContainer, newTrigger, new HashMap<>());
for (TriggerAction action : actions) {
+ listeners.fireListeners(event.getSource(), AutoScaling.EventProcessorStage.BEFORE_ACTION, action.getName(), event, null);
try {
action.process(event, actionContext);
} catch (Exception e) {
+ listeners.fireListeners(event.getSource(), AutoScaling.EventProcessorStage.FAILED, action.getName(), event, null);
log.error("Error executing action: " + action.getName() + " for trigger event: " + event, e);
throw e;
}
+ listeners.fireListeners(event.getSource(), AutoScaling.EventProcessorStage.AFTER_ACTION, action.getName(), event, null);
}
if (enqueued) {
TriggerEvent ev = scheduledTrigger.dequeue();
assert ev.getId().equals(event.getId());
}
+ listeners.fireListeners(event.getSource(), AutoScaling.EventProcessorStage.SUCCEEDED, null, event, null);
} finally {
hasPendingActions.set(false);
}
@@ -181,10 +206,12 @@ public class ScheduledTriggers implements Closeable {
+ " is broken! Expected event=" + event + " but got " + ev);
}
}
+ listeners.fireListeners(event.getSource(), AutoScaling.EventProcessorStage.SUCCEEDED, null, event, null);
hasPendingActions.set(false);
}
return true;
} else {
+ listeners.fireListeners(event.getSource(), AutoScaling.EventProcessorStage.WAITING, null, event, null);
// there is an action in the queue and we don't want to enqueue another until it is complete
return false;
}
@@ -252,6 +279,7 @@ public class ScheduledTriggers implements Closeable {
// guarantee about cluster state
scheduledThreadPoolExecutor.shutdownNow();
actionExecutor.shutdownNow();
+ listeners.close();
}
private class ScheduledTrigger implements Runnable, Closeable {
@@ -339,4 +367,104 @@ public class ScheduledTriggers implements Closeable {
IOUtils.closeQuietly(trigger);
}
}
+
+ private class TriggerListeners {
+ Map<String, Map<AutoScaling.EventProcessorStage, List<AutoScaling.TriggerListener>>> listenerPerStage = new HashMap<>();
+ List<AutoScaling.TriggerListener> listeners = new ArrayList<>();
+ ReentrantLock updateLock = new ReentrantLock();
+
+ void setAutoScalingConfig(AutoScalingConfig autoScalingConfig) {
+ updateLock.lock();
+ try {
+ // close previous instances
+ close();
+ // instantiate only those for existing triggers
+ Set<String> triggerNames = autoScalingConfig.getTriggerConfigs().keySet();
+ Map<String, AutoScalingConfig.TriggerListenerConfig> configs = autoScalingConfig.getTriggerListenerConfigs();
+ for (Map.Entry<String, AutoScalingConfig.TriggerListenerConfig> entry : configs.entrySet()) {
+ AutoScalingConfig.TriggerListenerConfig config = entry.getValue();
+ if (!triggerNames.contains(config.trigger)) {
+ log.debug("-- skipping listener for non-existent trigger: {}", config);
+ continue;
+ }
+ String clazz = config.listenerClass;
+ AutoScaling.TriggerListener listener = null;
+ try {
+ listener = coreContainer.getResourceLoader().newInstance(clazz, AutoScaling.TriggerListener.class);
+ } catch (Exception e) {
+ log.warn("Invalid TriggerListener class name '" + clazz + "', skipping...", e);
+ }
+ if (listener == null) {
+ continue;
+ }
+ listener.init(coreContainer, config);
+ listeners.add(listener);
+ // add per stage
+ Map<AutoScaling.EventProcessorStage, List<AutoScaling.TriggerListener>> perStage = listenerPerStage.get(config.trigger);
+ if (perStage == null) {
+ perStage = new HashMap<>();
+ listenerPerStage.put(config.trigger, perStage);
+ }
+ for (AutoScaling.EventProcessorStage stage : config.stages) {
+ List<AutoScaling.TriggerListener> lst = perStage.get(stage);
+ if (lst == null) {
+ lst = new ArrayList<>(3);
+ perStage.put(stage, lst);
+ }
+ lst.add(listener);
+ }
+ }
+ } finally {
+ updateLock.unlock();
+ }
+ }
+
+ void close() {
+ updateLock.lock();
+ try {
+ listenerPerStage.clear();
+ for (AutoScaling.TriggerListener listener : listeners) {
+ IOUtils.closeQuietly(listener);
+ }
+ } finally {
+ updateLock.unlock();
+ }
+ }
+
+ List<AutoScaling.TriggerListener> getTriggerListeners(String trigger, AutoScaling.EventProcessorStage stage) {
+ Map<AutoScaling.EventProcessorStage, List<AutoScaling.TriggerListener>> perStage = listenerPerStage.get(trigger);
+ if (perStage == null) {
+ return Collections.emptyList();
+ }
+ List<AutoScaling.TriggerListener> lst = perStage.get(stage);
+ if (lst == null) {
+ return Collections.emptyList();
+ } else {
+ return Collections.unmodifiableList(lst);
+ }
+ }
+
+ void fireListeners(String trigger, AutoScaling.EventProcessorStage stage, String actionName, TriggerEvent event, String message) {
+ updateLock.lock();
+ try {
+ for (AutoScaling.TriggerListener listener : getTriggerListeners(trigger, stage)) {
+ if (actionName != null) {
+ AutoScalingConfig.TriggerListenerConfig config = listener.getTriggerListenerConfig();
+ if (stage == AutoScaling.EventProcessorStage.BEFORE_ACTION) {
+ if (!config.beforeActions.contains(actionName)) {
+ continue;
+ }
+ } else if (stage == AutoScaling.EventProcessorStage.AFTER_ACTION) {
+ if (!config.afterActions.contains(actionName)) {
+ continue;
+ }
+ }
+ }
+ listener.onEvent(stage, actionName, event, message);
+ }
+ } finally {
+ updateLock.unlock();
+ }
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f17f3e6a/solr/core/src/test/org/apache/solr/cloud/autoscaling/AutoScalingHandlerTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/autoscaling/AutoScalingHandlerTest.java b/solr/core/src/test/org/apache/solr/cloud/autoscaling/AutoScalingHandlerTest.java
index be7fb0c..59170fa 100644
--- a/solr/core/src/test/org/apache/solr/cloud/autoscaling/AutoScalingHandlerTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/autoscaling/AutoScalingHandlerTest.java
@@ -356,7 +356,7 @@ public class AutoScalingHandlerTest extends SolrCloudTestCase {
"'trigger' : 'node_lost_trigger'," +
"'stage' : ['STARTED','ABORTED','SUCCEEDED']," +
"'beforeAction' : 'execute_plan'," +
- "'class' : 'org.apache.solr.cloud.autoscaling.AutoScaling$HttpTriggerListener'," +
+ "'class' : 'org.apache.solr.cloud.autoscaling.HttpTriggerListener'," +
"'url' : 'http://xyz.com/on_node_lost?node={$LOST_NODE_NAME}'" +
"}" +
"}";
@@ -371,7 +371,7 @@ public class AutoScalingHandlerTest extends SolrCloudTestCase {
assertTrue(listeners.containsKey("xyz"));
Map<String, Object> xyzListener = (Map<String, Object>) listeners.get("xyz");
assertEquals(5, xyzListener.size());
- assertEquals("org.apache.solr.cloud.autoscaling.AutoScaling$HttpTriggerListener", xyzListener.get("class").toString());
+ assertEquals("org.apache.solr.cloud.autoscaling.HttpTriggerListener", xyzListener.get("class").toString());
String removeTriggerCommand = "{" +
"'remove-trigger' : {" +
[4/5] lucene-solr:jira/solr-10996: Merge branch 'feature/autoscaling'
into jira/solr-10996
Posted by ab...@apache.org.
Merge branch 'feature/autoscaling' into jira/solr-10996
Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/b0eed4ce
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/b0eed4ce
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/b0eed4ce
Branch: refs/heads/jira/solr-10996
Commit: b0eed4ce3572331b02568965399a29ff688bb224
Parents: f17f3e6 fd66cb3
Author: Andrzej Bialecki <ab...@apache.org>
Authored: Wed Jul 5 15:52:50 2017 +0200
Committer: Andrzej Bialecki <ab...@apache.org>
Committed: Wed Jul 5 15:52:50 2017 +0200
----------------------------------------------------------------------
README.md | 103 +
README.txt | 13 -
.../lucene/classification/classification.iml | 1 -
dev-tools/scripts/smokeTestRelease.py | 12 +-
lucene/CHANGES.txt | 12 +
.../analysis/custom/TestCustomAnalyzer.java | 8 +-
.../lucene50/Lucene50SegmentInfoFormat.java | 90 -
.../apache/lucene/codecs/lucene50/package.html | 25 -
.../codecs/lucene53/Lucene53NormsFormat.java | 91 -
.../codecs/lucene53/Lucene53NormsProducer.java | 236 --
.../lucene/codecs/lucene53/package-info.java | 23 -
.../lucene54/Lucene54DocValuesConsumer.java | 797 -----
.../lucene54/Lucene54DocValuesFormat.java | 186 -
.../lucene54/Lucene54DocValuesProducer.java | 1803 ----------
.../lucene/codecs/lucene54/package-info.java | 403 ---
.../lucene/codecs/lucene60/Lucene60Codec.java | 177 -
.../apache/lucene/codecs/lucene60/package.html | 25 -
.../lucene/codecs/lucene62/Lucene62Codec.java | 176 -
.../apache/lucene/codecs/lucene62/package.html | 25 -
.../apache/lucene/index/FixBrokenOffsets.java | 138 -
.../java/org/apache/lucene/index/package.html | 27 -
.../services/org.apache.lucene.codecs.Codec | 2 -
.../org.apache.lucene.codecs.DocValuesFormat | 1 -
.../lucene50/Lucene50RWSegmentInfoFormat.java | 125 -
.../lucene50/TestLucene50SegmentInfoFormat.java | 50 -
.../codecs/lucene53/Lucene53NormsConsumer.java | 159 -
.../codecs/lucene53/Lucene53RWNormsFormat.java | 31 -
.../lucene53/TestLucene53NormsFormat.java | 44 -
.../lucene54/TestLucene54DocValuesFormat.java | 640 ----
.../lucene/codecs/lucene60/Lucene60RWCodec.java | 38 -
.../lucene/codecs/lucene62/Lucene62RWCodec.java | 44 -
.../lucene62/Lucene62RWSegmentInfoFormat.java | 193 --
.../lucene62/TestLucene62SegmentInfoFormat.java | 48 -
.../index/TestBackwardsCompatibility.java | 64 +-
.../lucene/index/TestFixBrokenOffsets.java | 112 -
.../lucene/index/TestIndexWriterOnOldIndex.java | 7 +-
.../lucene/index/TestManyPointsInOldIndex.java | 1 +
.../org/apache/lucene/index/dvupdates.6.0.0.zip | Bin 3420 -> 0 bytes
.../org/apache/lucene/index/empty.6.0.0.zip | Bin 225 -> 0 bytes
.../org/apache/lucene/index/index.6.0.0-cfs.zip | Bin 15807 -> 0 bytes
.../apache/lucene/index/index.6.0.0-nocfs.zip | Bin 15806 -> 0 bytes
.../org/apache/lucene/index/index.6.0.1-cfs.zip | Bin 15820 -> 0 bytes
.../apache/lucene/index/index.6.0.1-nocfs.zip | Bin 15823 -> 0 bytes
.../org/apache/lucene/index/index.6.1.0-cfs.zip | Bin 15803 -> 0 bytes
.../apache/lucene/index/index.6.1.0-nocfs.zip | Bin 15829 -> 0 bytes
.../org/apache/lucene/index/index.6.2.0-cfs.zip | Bin 15880 -> 0 bytes
.../apache/lucene/index/index.6.2.0-nocfs.zip | Bin 15867 -> 0 bytes
.../org/apache/lucene/index/index.6.2.1-cfs.zip | Bin 15851 -> 0 bytes
.../apache/lucene/index/index.6.2.1-nocfs.zip | Bin 15845 -> 0 bytes
.../org/apache/lucene/index/index.6.3.0-cfs.zip | Bin 15869 -> 0 bytes
.../apache/lucene/index/index.6.3.0-nocfs.zip | Bin 15876 -> 0 bytes
.../org/apache/lucene/index/index.6.4.0-cfs.zip | Bin 15829 -> 0 bytes
.../apache/lucene/index/index.6.4.0-nocfs.zip | Bin 15831 -> 0 bytes
.../org/apache/lucene/index/index.6.4.1-cfs.zip | Bin 15848 -> 0 bytes
.../apache/lucene/index/index.6.4.1-nocfs.zip | Bin 15838 -> 0 bytes
.../org/apache/lucene/index/index.6.4.2-cfs.zip | Bin 15856 -> 0 bytes
.../apache/lucene/index/index.6.4.2-nocfs.zip | Bin 15886 -> 0 bytes
.../org/apache/lucene/index/index.6.5.0-cfs.zip | Bin 15832 -> 0 bytes
.../apache/lucene/index/index.6.5.0-nocfs.zip | Bin 15836 -> 0 bytes
.../org/apache/lucene/index/index.6.5.1-cfs.zip | Bin 15842 -> 0 bytes
.../apache/lucene/index/index.6.5.1-nocfs.zip | Bin 15827 -> 0 bytes
.../org/apache/lucene/index/index.6.6.0-cfs.zip | Bin 15875 -> 0 bytes
.../apache/lucene/index/index.6.6.0-nocfs.zip | Bin 15883 -> 0 bytes
.../lucene/index/index.630.brokenoffsets.zip | Bin 3203 -> 0 bytes
.../lucene/index/index.single-empty-doc.630.zip | Bin 1363 -> 0 bytes
.../org/apache/lucene/index/manypointsindex.zip | Bin 3739 -> 0 bytes
.../org/apache/lucene/index/maxposindex.zip | Bin 1702 -> 0 bytes
.../org/apache/lucene/index/moreterms.6.0.0.zip | Bin 157215 -> 0 bytes
.../org/apache/lucene/index/sorted.6.2.0.zip | Bin 157007 -> 0 bytes
.../org/apache/lucene/index/sorted.6.2.1.zip | Bin 100974 -> 0 bytes
.../org/apache/lucene/index/sorted.6.3.0.zip | Bin 71090 -> 0 bytes
.../lucene/index/unsupported.6.0.0-cfs.zip | Bin 0 -> 15807 bytes
.../lucene/index/unsupported.6.0.0-nocfs.zip | Bin 0 -> 15806 bytes
.../lucene/index/unsupported.6.0.1-cfs.zip | Bin 0 -> 15820 bytes
.../lucene/index/unsupported.6.0.1-nocfs.zip | Bin 0 -> 15823 bytes
.../lucene/index/unsupported.6.1.0-cfs.zip | Bin 0 -> 15803 bytes
.../lucene/index/unsupported.6.1.0-nocfs.zip | Bin 0 -> 15829 bytes
.../lucene/index/unsupported.6.2.0-cfs.zip | Bin 0 -> 15880 bytes
.../lucene/index/unsupported.6.2.0-nocfs.zip | Bin 0 -> 15867 bytes
.../lucene/index/unsupported.6.2.1-cfs.zip | Bin 0 -> 15851 bytes
.../lucene/index/unsupported.6.2.1-nocfs.zip | Bin 0 -> 15845 bytes
.../lucene/index/unsupported.6.3.0-cfs.zip | Bin 0 -> 15869 bytes
.../lucene/index/unsupported.6.3.0-nocfs.zip | Bin 0 -> 15876 bytes
.../lucene/index/unsupported.6.4.0-cfs.zip | Bin 0 -> 15829 bytes
.../lucene/index/unsupported.6.4.0-nocfs.zip | Bin 0 -> 15831 bytes
.../lucene/index/unsupported.6.4.1-cfs.zip | Bin 0 -> 15848 bytes
.../lucene/index/unsupported.6.4.1-nocfs.zip | Bin 0 -> 15838 bytes
.../lucene/index/unsupported.6.4.2-cfs.zip | Bin 0 -> 15856 bytes
.../lucene/index/unsupported.6.4.2-nocfs.zip | Bin 0 -> 15886 bytes
.../lucene/index/unsupported.6.5.0-cfs.zip | Bin 0 -> 15832 bytes
.../lucene/index/unsupported.6.5.0-nocfs.zip | Bin 0 -> 15836 bytes
.../lucene/index/unsupported.6.5.1-cfs.zip | Bin 0 -> 15842 bytes
.../lucene/index/unsupported.6.5.1-nocfs.zip | Bin 0 -> 15827 bytes
.../lucene/index/unsupported.6.6.0-cfs.zip | Bin 0 -> 15875 bytes
.../lucene/index/unsupported.6.6.0-nocfs.zip | Bin 0 -> 15883 bytes
lucene/classification/build.xml | 6 +-
.../classification/KNearestFuzzyClassifier.java | 29 +-
.../classification/utils/NearestFuzzyQuery.java | 333 ++
.../KNearestFuzzyClassifierTest.java | 2 +-
.../lucene/document/NumericDocValuesField.java | 6 +-
.../document/SortedNumericDocValuesField.java | 6 +-
.../lucene/index/BufferedUpdatesStream.java | 3 +
.../org/apache/lucene/index/CheckIndex.java | 47 +-
.../apache/lucene/index/DocumentsWriter.java | 20 +-
.../lucene/index/DocumentsWriterFlushQueue.java | 4 +
.../lucene/index/FrozenBufferedUpdates.java | 25 +-
.../index/IndexFormatTooOldException.java | 2 +-
.../org/apache/lucene/index/IndexWriter.java | 13 +-
.../apache/lucene/index/ReadersAndUpdates.java | 8 +-
.../org/apache/lucene/index/SegmentInfos.java | 2 +-
.../search/similarities/BM25Similarity.java | 38 +-
.../search/similarities/SimilarityBase.java | 25 +-
.../search/similarities/TFIDFSimilarity.java | 25 +-
.../java/org/apache/lucene/util/Version.java | 101 +-
.../lucene/index/TestIndexManyDocuments.java | 71 +
.../apache/lucene/index/TestSegmentInfos.java | 14 +-
.../lucene/search/TestDocValuesQueries.java | 24 +-
.../search/TestIndexOrDocValuesQuery.java | 4 +-
.../search/similarities/TestBM25Similarity.java | 42 -
.../similarities/TestClassicSimilarity.java | 59 +-
.../search/similarities/TestSimilarityBase.java | 39 -
.../org/apache/lucene/util/TestVersion.java | 71 +-
.../lucene/search/join/BlockJoinSelector.java | 328 +-
.../lucene/search/join/ToParentDocValues.java | 296 ++
.../search/join/TestBlockJoinSelector.java | 76 +-
.../apache/lucene/index/memory/MemoryIndex.java | 6 +-
.../lucene/index/memory/TestMemoryIndex.java | 40 +
.../lucene/document/LatLonDocValuesField.java | 4 +-
.../search/TestLatLonDocValuesQueries.java | 4 +-
.../java/org/apache/lucene/util/TestUtil.java | 4 +-
lucene/version.properties | 2 +-
solr/CHANGES.txt | 117 +
solr/bin/solr | 12 +-
solr/bin/solr.cmd | 4 +-
solr/common-build.xml | 5 +-
.../collection1/conf/solrconfig-icucollate.xml | 2 +-
.../apache/solr/analytics/AnalyticsDriver.java | 82 +
.../solr/analytics/AnalyticsExpression.java | 64 +
.../analytics/AnalyticsGroupingManager.java | 239 ++
.../solr/analytics/AnalyticsRequestManager.java | 279 ++
.../solr/analytics/AnalyticsRequestParser.java | 549 +++
.../solr/analytics/ExpressionFactory.java | 821 +++++
.../analytics/accumulator/BasicAccumulator.java | 173 -
.../accumulator/FacetingAccumulator.java | 730 ----
.../analytics/accumulator/ValueAccumulator.java | 40 -
.../facet/FacetValueAccumulator.java | 35 -
.../facet/FieldFacetAccumulator.java | 153 -
.../facet/QueryFacetAccumulator.java | 72 -
.../facet/RangeFacetAccumulator.java | 49 -
.../accumulator/facet/package-info.java | 24 -
.../analytics/accumulator/package-info.java | 23 -
.../analytics/expression/BaseExpression.java | 88 -
.../expression/DualDelegateExpression.java | 99 -
.../solr/analytics/expression/Expression.java | 39 -
.../analytics/expression/ExpressionFactory.java | 175 -
.../expression/MultiDelegateExpression.java | 131 -
.../expression/SingleDelegateExpression.java | 88 -
.../solr/analytics/expression/package-info.java | 23 -
.../analytics/facet/AbstractSolrQueryFacet.java | 104 +
.../solr/analytics/facet/AnalyticsFacet.java | 166 +
.../apache/solr/analytics/facet/PivotFacet.java | 114 +
.../apache/solr/analytics/facet/PivotNode.java | 263 ++
.../apache/solr/analytics/facet/QueryFacet.java | 64 +
.../apache/solr/analytics/facet/RangeFacet.java | 119 +
.../solr/analytics/facet/SortableFacet.java | 178 +
.../solr/analytics/facet/StreamingFacet.java | 32 +
.../apache/solr/analytics/facet/ValueFacet.java | 60 +
.../facet/compare/ConstantComparator.java | 30 +
.../facet/compare/DelegatingComparator.java | 62 +
.../facet/compare/ExpressionComparator.java | 46 +
.../facet/compare/FacetResultsComparator.java | 52 +
.../facet/compare/FacetValueComparator.java | 37 +
.../analytics/facet/compare/package-info.java | 23 +
.../solr/analytics/facet/package-info.java | 23 +
.../function/ExpressionCalculator.java | 71 +
.../MergingReductionCollectionManager.java | 46 +
.../function/ReductionCollectionManager.java | 320 ++
.../analytics/function/ReductionFunction.java | 37 +
.../function/field/AnalyticsField.java | 69 +
.../analytics/function/field/BooleanField.java | 111 +
.../function/field/BooleanMultiField.java | 101 +
.../analytics/function/field/DateField.java | 108 +
.../function/field/DateMultiField.java | 47 +
.../function/field/DateMultiPointField.java | 47 +
.../analytics/function/field/DoubleField.java | 97 +
.../function/field/DoubleMultiField.java | 85 +
.../function/field/DoubleMultiPointField.java | 81 +
.../analytics/function/field/FloatField.java | 108 +
.../function/field/FloatMultiField.java | 91 +
.../function/field/FloatMultiPointField.java | 87 +
.../solr/analytics/function/field/IntField.java | 129 +
.../analytics/function/field/IntMultiField.java | 100 +
.../function/field/IntMultiPointField.java | 96 +
.../analytics/function/field/LongField.java | 107 +
.../function/field/LongMultiField.java | 89 +
.../function/field/LongMultiPointField.java | 86 +
.../analytics/function/field/StringField.java | 85 +
.../function/field/StringMultiField.java | 66 +
.../analytics/function/field/package-info.java | 23 +
.../function/mapping/AbsoluteValueFunction.java | 54 +
.../analytics/function/mapping/AddFunction.java | 68 +
.../function/mapping/BottomFunction.java | 163 +
.../function/mapping/CompareFunction.java | 614 ++++
.../function/mapping/ConcatFunction.java | 78 +
.../function/mapping/DateMathFunction.java | 156 +
.../function/mapping/DateParseFunction.java | 210 ++
.../function/mapping/DivideFunction.java | 51 +
.../function/mapping/FillMissingFunction.java | 842 +++++
.../function/mapping/FilterFunction.java | 722 ++++
.../analytics/function/mapping/IfFunction.java | 892 +++++
.../function/mapping/JoinFunction.java | 57 +
.../function/mapping/LambdaFunction.java | 3220 ++++++++++++++++++
.../analytics/function/mapping/LogFunction.java | 51 +
.../function/mapping/LogicFunction.java | 90 +
.../function/mapping/MultFunction.java | 68 +
.../function/mapping/NegateFunction.java | 58 +
.../mapping/NumericConvertFunction.java | 256 ++
.../function/mapping/PowerFunction.java | 51 +
.../function/mapping/RemoveFunction.java | 796 +++++
.../function/mapping/ReplaceFunction.java | 914 +++++
.../function/mapping/StringCastFunction.java | 42 +
.../function/mapping/SubtractFunction.java | 51 +
.../analytics/function/mapping/TopFunction.java | 163 +
.../function/mapping/package-info.java | 23 +
.../solr/analytics/function/package-info.java | 23 +
.../function/reduction/CountFunction.java | 87 +
.../function/reduction/DocCountFunction.java | 87 +
.../function/reduction/MaxFunction.java | 298 ++
.../function/reduction/MedianFunction.java | 200 ++
.../function/reduction/MinFunction.java | 298 ++
.../function/reduction/MissingFunction.java | 76 +
.../function/reduction/OrdinalFunction.java | 386 +++
.../function/reduction/PercentileFunction.java | 337 ++
.../function/reduction/SumFunction.java | 92 +
.../function/reduction/UniqueFunction.java | 101 +
.../function/reduction/data/CountCollector.java | 188 +
.../function/reduction/data/MaxCollector.java | 476 +++
.../function/reduction/data/MinCollector.java | 476 +++
.../function/reduction/data/ReductionData.java | 24 +
.../reduction/data/ReductionDataCollector.java | 183 +
.../reduction/data/SortedListCollector.java | 363 ++
.../function/reduction/data/SumCollector.java | 124 +
.../reduction/data/UniqueCollector.java | 241 ++
.../function/reduction/data/package-info.java | 24 +
.../function/reduction/package-info.java | 23 +
.../org/apache/solr/analytics/package-info.java | 23 +
.../request/AbstractFieldFacetRequest.java | 42 -
.../request/AnalyticsContentHandler.java | 314 --
.../analytics/request/AnalyticsRequest.java | 114 -
.../request/AnalyticsRequestFactory.java | 308 --
.../solr/analytics/request/AnalyticsStats.java | 138 -
.../analytics/request/ExpressionRequest.java | 72 -
.../solr/analytics/request/FacetRequest.java | 26 -
.../analytics/request/FieldFacetRequest.java | 172 -
.../analytics/request/QueryFacetRequest.java | 74 -
.../analytics/request/RangeFacetRequest.java | 129 -
.../solr/analytics/request/package-info.java | 24 -
.../AbstractDelegatingStatsCollector.java | 74 -
.../statistics/MedianStatsCollector.java | 76 -
.../statistics/MinMaxStatsCollector.java | 114 -
.../statistics/NumericStatsCollector.java | 68 -
.../statistics/PercentileStatsCollector.java | 80 -
.../analytics/statistics/StatsCollector.java | 69 -
.../StatsCollectorSupplierFactory.java | 646 ----
.../statistics/UniqueStatsCollector.java | 53 -
.../solr/analytics/statistics/package-info.java | 24 -
.../stream/AnalyticsShardRequestManager.java | 245 ++
.../stream/AnalyticsShardResponseParser.java | 89 +
.../solr/analytics/stream/package-info.java | 23 +
.../reservation/BooleanArrayReservation.java | 44 +
.../reservation/BooleanCheckedReservation.java | 42 +
.../stream/reservation/BooleanReservation.java | 42 +
.../reservation/DoubleArrayReservation.java | 44 +
.../reservation/DoubleCheckedReservation.java | 43 +
.../stream/reservation/DoubleReservation.java | 42 +
.../reservation/FloatArrayReservation.java | 44 +
.../reservation/FloatCheckedReservation.java | 43 +
.../stream/reservation/FloatReservation.java | 42 +
.../stream/reservation/IntArrayReservation.java | 42 +
.../reservation/IntCheckedReservation.java | 43 +
.../stream/reservation/IntReservation.java | 42 +
.../reservation/LongArrayReservation.java | 45 +
.../reservation/LongCheckedReservation.java | 43 +
.../stream/reservation/LongReservation.java | 42 +
.../ReductionCheckedDataReservation.java | 35 +
.../ReductionDataArrayReservation.java | 36 +
.../reservation/ReductionDataReservation.java | 53 +
.../reservation/StringArrayReservation.java | 45 +
.../reservation/StringCheckedReservation.java | 44 +
.../stream/reservation/StringReservation.java | 43 +
.../stream/reservation/package-info.java | 24 +
.../read/BooleanCheckedDataReader.java | 33 +
.../read/BooleanDataArrayReader.java | 36 +
.../reservation/read/BooleanDataReader.java | 33 +
.../read/DoubleCheckedDataReader.java | 32 +
.../reservation/read/DoubleDataArrayReader.java | 35 +
.../reservation/read/DoubleDataReader.java | 32 +
.../read/FloatCheckedDataReader.java | 33 +
.../reservation/read/FloatDataArrayReader.java | 36 +
.../reservation/read/FloatDataReader.java | 33 +
.../reservation/read/IntCheckedDataReader.java | 32 +
.../reservation/read/IntDataArrayReader.java | 34 +
.../stream/reservation/read/IntDataReader.java | 32 +
.../reservation/read/LongCheckedDataReader.java | 32 +
.../reservation/read/LongDataArrayReader.java | 35 +
.../stream/reservation/read/LongDataReader.java | 32 +
.../read/ReductionCheckedDataReader.java | 54 +
.../read/ReductionDataArrayReader.java | 54 +
.../reservation/read/ReductionDataReader.java | 40 +
.../read/StringCheckedDataReader.java | 32 +
.../reservation/read/StringDataArrayReader.java | 35 +
.../reservation/read/StringDataReader.java | 34 +
.../stream/reservation/read/package-info.java | 24 +
.../write/BooleanCheckedDataWriter.java | 33 +
.../write/BooleanDataArrayWriter.java | 36 +
.../reservation/write/BooleanDataWriter.java | 33 +
.../write/DoubleCheckedDataWriter.java | 34 +
.../write/DoubleDataArrayWriter.java | 36 +
.../reservation/write/DoubleDataWriter.java | 33 +
.../write/FloatCheckedDataWriter.java | 35 +
.../reservation/write/FloatDataArrayWriter.java | 37 +
.../reservation/write/FloatDataWriter.java | 34 +
.../reservation/write/IntCheckedDataWriter.java | 34 +
.../reservation/write/IntDataArrayWriter.java | 35 +
.../stream/reservation/write/IntDataWriter.java | 33 +
.../write/LongCheckedDataWriter.java | 34 +
.../reservation/write/LongDataArrayWriter.java | 36 +
.../reservation/write/LongDataWriter.java | 33 +
.../write/ReductionCheckedDataWriter.java | 60 +
.../write/ReductionDataArrayWriter.java | 53 +
.../reservation/write/ReductionDataWriter.java | 40 +
.../write/StringCheckedDataWriter.java | 34 +
.../write/StringDataArrayWriter.java | 36 +
.../reservation/write/StringDataWriter.java | 37 +
.../stream/reservation/write/package-info.java | 24 +
.../solr/analytics/util/AnalyticsParams.java | 114 -
.../solr/analytics/util/AnalyticsParsers.java | 171 -
.../util/AnalyticsResponseHeadings.java | 36 +
.../analytics/util/FacetRangeGenerator.java | 356 ++
.../solr/analytics/util/MedianCalculator.java | 4 +
.../solr/analytics/util/OldAnalyticsParams.java | 177 +
.../util/OldAnalyticsRequestConverter.java | 177 +
.../solr/analytics/util/OrdinalCalculator.java | 173 +
.../analytics/util/PercentileCalculator.java | 176 -
.../analytics/util/RangeEndpointCalculator.java | 354 --
.../util/function/BooleanConsumer.java | 59 +
.../analytics/util/function/FloatConsumer.java | 59 +
.../analytics/util/function/FloatSupplier.java | 41 +
.../analytics/util/function/package-info.java | 23 +
.../solr/analytics/util/package-info.java | 3 +-
.../AbsoluteValueDoubleFunction.java | 60 -
.../util/valuesource/AddDoubleFunction.java | 49 -
.../util/valuesource/ConstDateSource.java | 112 -
.../util/valuesource/ConstDoubleSource.java | 104 -
.../util/valuesource/ConstStringSource.java | 50 -
.../util/valuesource/DateFieldSource.java | 131 -
.../util/valuesource/DateMathFunction.java | 71 -
.../util/valuesource/DivDoubleFunction.java | 48 -
.../util/valuesource/DualDoubleFunction.java | 94 -
.../util/valuesource/FilterFieldSource.java | 154 -
.../util/valuesource/LogDoubleFunction.java | 43 -
.../util/valuesource/MultiDateFunction.java | 133 -
.../util/valuesource/MultiDoubleFunction.java | 119 -
.../valuesource/MultiplyDoubleFunction.java | 49 -
.../util/valuesource/NegateDoubleFunction.java | 55 -
.../util/valuesource/PowDoubleFunction.java | 48 -
.../util/valuesource/ReverseStringFunction.java | 45 -
.../util/valuesource/SingleDoubleFunction.java | 79 -
.../util/valuesource/SingleStringFunction.java | 117 -
.../util/valuesource/package-info.java | 24 -
.../solr/analytics/value/AnalyticsValue.java | 55 +
.../analytics/value/AnalyticsValueStream.java | 133 +
.../solr/analytics/value/BooleanValue.java | 85 +
.../analytics/value/BooleanValueStream.java | 55 +
.../solr/analytics/value/ComparableValue.java | 32 +
.../apache/solr/analytics/value/DateValue.java | 102 +
.../solr/analytics/value/DateValueStream.java | 62 +
.../solr/analytics/value/DoubleValue.java | 86 +
.../solr/analytics/value/DoubleValueStream.java | 54 +
.../apache/solr/analytics/value/FloatValue.java | 97 +
.../solr/analytics/value/FloatValueStream.java | 60 +
.../apache/solr/analytics/value/IntValue.java | 121 +
.../solr/analytics/value/IntValueStream.java | 71 +
.../apache/solr/analytics/value/LongValue.java | 97 +
.../solr/analytics/value/LongValueStream.java | 60 +
.../solr/analytics/value/StringValue.java | 71 +
.../solr/analytics/value/StringValueStream.java | 49 +
.../value/constant/ConstantBooleanValue.java | 91 +
.../value/constant/ConstantDateValue.java | 103 +
.../value/constant/ConstantDoubleValue.java | 90 +
.../value/constant/ConstantFloatValue.java | 99 +
.../value/constant/ConstantIntValue.java | 118 +
.../value/constant/ConstantLongValue.java | 100 +
.../value/constant/ConstantStringValue.java | 79 +
.../analytics/value/constant/ConstantValue.java | 128 +
.../analytics/value/constant/package-info.java | 23 +
.../solr/analytics/value/package-info.java | 23 +
.../apache/solr/handler/AnalyticsHandler.java | 147 +
.../handler/component/AnalyticsComponent.java | 119 +-
.../java/org/apache/solr/handler/package.html | 28 +
.../response/AnalyticsShardResponseWriter.java | 91 +
.../java/org/apache/solr/response/package.html | 28 +
.../analytics/requestFiles/expressions.txt | 70 -
.../analytics/requestFiles/fieldFacetExtras.txt | 66 -
.../analytics/requestFiles/fieldFacets.txt | 132 -
.../analytics/requestFiles/functions.txt | 62 -
.../analytics/requestFiles/noFacets.txt | 74 -
.../analytics/requestFiles/queryFacets.txt | 45 -
.../analytics/requestFiles/rangeFacets.txt | 170 -
.../analytics/requestXMLFiles/expressions.xml | 285 --
.../requestXMLFiles/fieldFacetExtras.xml | 101 -
.../analytics/requestXMLFiles/fieldFacets.xml | 496 ---
.../analytics/requestXMLFiles/functions.xml | 246 --
.../analytics/requestXMLFiles/noFacets.xml | 310 --
.../analytics/requestXMLFiles/queryFacets.xml | 94 -
.../analytics/requestXMLFiles/rangeFacets.xml | 319 --
.../test-files/solr/analytics/expressions.txt | 65 +
.../test-files/solr/analytics/facetSorting.txt | 4 +
.../solr/analytics/fieldFacetExtras.txt | 66 +
.../test-files/solr/analytics/fieldFacets.txt | 132 +
.../src/test-files/solr/analytics/functions.txt | 57 +
.../src/test-files/solr/analytics/noFacets.txt | 74 +
.../test-files/solr/analytics/queryFacets.txt | 27 +
.../test-files/solr/analytics/rangeFacets.txt | 161 +
.../solr/collection1/conf/schema-analytics.xml | 7 +-
.../collection1/conf/solrconfig-analytics.xml | 42 +
.../solr/collection1/conf/solrconfig-basic.xml | 40 -
.../configsets/cloud-analytics/conf/schema.xml | 63 +
.../cloud-analytics/conf/solrconfig.xml | 59 +
.../AbstractAnalyticsStatsCloudTest.java | 187 +
.../analytics/AbstractAnalyticsStatsTest.java | 14 +-
.../apache/solr/analytics/NoFacetCloudTest.java | 557 +++
.../org/apache/solr/analytics/NoFacetTest.java | 46 +-
.../analytics/expression/ExpressionTest.java | 70 +-
.../solr/analytics/expression/FunctionTest.java | 221 ++
.../facet/AbstractAnalyticsFacetCloudTest.java | 284 ++
.../facet/AbstractAnalyticsFacetTest.java | 37 +-
.../solr/analytics/facet/FacetSortingTest.java | 53 +
.../analytics/facet/FieldFacetCloudTest.java | 1214 +++++++
.../facet/FieldFacetExtrasCloudTest.java | 253 ++
.../analytics/facet/FieldFacetExtrasTest.java | 6 +-
.../solr/analytics/facet/FieldFacetTest.java | 63 +-
.../analytics/facet/QueryFacetCloudTest.java | 159 +
.../solr/analytics/facet/QueryFacetTest.java | 10 +-
.../analytics/facet/RangeFacetCloudTest.java | 588 ++++
.../solr/analytics/facet/RangeFacetTest.java | 43 +-
.../util/valuesource/FunctionTest.java | 233 --
.../solr/collection1/conf/solrconfig.xml | 20 +-
.../clustering/ClusteringComponentTest.java | 2 +-
.../collection1/conf/dataimport-solrconfig.xml | 40 +-
.../conf/contentstream-solrconfig.xml | 42 +-
.../conf/dataimport-nodatasource-solrconfig.xml | 42 +-
.../collection1/conf/dataimport-solrconfig.xml | 42 +-
.../TestSolrEntityProcessorEndToEnd.java | 4 +-
.../solr/collection1/conf/solrconfig.xml | 37 +-
.../extraction/TestXLSXResponseWriter.java | 2 +-
.../conf/solrconfig-languageidentifier.xml | 4 +-
.../uima/solr/collection1/conf/solrconfig.xml | 25 +-
.../uima/uima-tokenizers-solrconfig.xml | 15 +-
.../client/solrj/embedded/JettySolrRunner.java | 7 +
.../org/apache/solr/cloud/AddReplicaCmd.java | 2 +-
.../src/java/org/apache/solr/cloud/Assign.java | 1 -
.../org/apache/solr/cloud/DeleteNodeCmd.java | 43 +-
.../org/apache/solr/cloud/DeleteReplicaCmd.java | 2 +-
.../cloud/LeaderInitiatedRecoveryThread.java | 7 +-
.../org/apache/solr/cloud/MoveReplicaCmd.java | 42 +-
.../OverseerAutoReplicaFailoverThread.java | 7 +-
.../cloud/OverseerCollectionMessageHandler.java | 30 +-
.../org/apache/solr/cloud/RecoveryStrategy.java | 32 +-
.../org/apache/solr/cloud/ReplaceNodeCmd.java | 43 +-
.../org/apache/solr/cloud/SyncStrategy.java | 8 +-
.../org/apache/solr/cloud/ZkController.java | 7 +-
.../cloud/autoscaling/ExecutePlanAction.java | 58 +-
.../org/apache/solr/core/CoreContainer.java | 56 +-
.../java/org/apache/solr/core/SolrConfig.java | 3 +-
.../src/java/org/apache/solr/core/SolrCore.java | 2 +-
.../java/org/apache/solr/core/SolrCores.java | 91 +-
.../apache/solr/core/SolrResourceLoader.java | 1 -
.../apache/solr/handler/CdcrRequestHandler.java | 12 +-
.../solr/handler/CdcrUpdateLogSynchronizer.java | 7 +-
.../org/apache/solr/handler/IndexFetcher.java | 28 +-
.../solr/handler/MoreLikeThisHandler.java | 2 +-
.../apache/solr/handler/RequestHandlerBase.java | 1 -
.../solr/handler/StandardRequestHandler.java | 19 +-
.../solr/handler/admin/CollectionsHandler.java | 7 +-
.../component/HttpShardHandlerFactory.java | 4 +-
.../solr/handler/component/ResponseBuilder.java | 3 +
.../metrics/FilteringSolrMetricReporter.java | 59 +
.../metrics/reporters/SolrGangliaReporter.java | 34 +-
.../metrics/reporters/SolrGraphiteReporter.java | 34 +-
.../solr/metrics/reporters/SolrJmxReporter.java | 51 +-
.../metrics/reporters/SolrSlf4jReporter.java | 34 +-
.../reporters/solr/SolrShardReporter.java | 26 +-
.../java/org/apache/solr/schema/EnumField.java | 2 +-
.../solr/schema/FieldTypePluginLoader.java | 6 +-
.../org/apache/solr/schema/IndexSchema.java | 4 +-
.../apache/solr/schema/IndexSchemaFactory.java | 9 +-
.../solr/schema/LatLonPointSpatialField.java | 6 +-
.../apache/solr/schema/NumericFieldType.java | 4 +-
.../org/apache/solr/search/SolrCoreParser.java | 2 +-
.../similarities/SchemaSimilarityFactory.java | 4 +-
.../org/apache/solr/servlet/BaseSolrFilter.java | 3 +
.../apache/solr/servlet/BaseSolrServlet.java | 3 +
.../org/apache/solr/servlet/HttpSolrCall.java | 13 +-
.../org/apache/solr/util/Java9InitHack.java | 78 +
.../org/apache/solr/util/SolrPluginUtils.java | 12 +-
.../org/apache/solr/util/TestInjection.java | 2 +-
.../resources/SystemCollectionSolrConfig.xml | 2 +-
.../collection1/conf/bad-error-solrconfig.xml | 2 +-
.../collection1/conf/bad-mpf-solrconfig.xml | 2 +-
.../conf/bad-schema-dup-fieldType.xml | 4 +-
.../collection1/conf/schema-binaryfield.xml | 36 -
.../collection1/conf/schema-copyfield-test.xml | 34 +-
.../collection1/conf/schema-customfield.xml | 29 +-
.../conf/schema-distributed-missing-sort.xml | 28 +-
.../solr/collection1/conf/schema-docValues.xml | 10 +-
.../conf/schema-docValuesFaceting.xml | 10 +-
.../collection1/conf/schema-docValuesJoin.xml | 10 +-
.../conf/schema-docValuesMissing.xml | 10 +-
.../collection1/conf/schema-docValuesMulti.xml | 10 +-
.../conf/schema-field-sort-values.xml | 4 +-
.../conf/schema-non-stored-docvalues.xml | 47 +-
.../conf/schema-not-required-unique-key.xml | 1 -
.../collection1/conf/schema-replication1.xml | 1 -
.../collection1/conf/schema-replication2.xml | 1 -
.../collection1/conf/schema-required-fields.xml | 34 +-
.../solr/collection1/conf/schema-reversed.xml | 5 +-
.../collection1/conf/schema-sortingresponse.xml | 22 +-
.../collection1/conf/schema-tokenizer-test.xml | 21 +-
.../solr/collection1/conf/schema-version-dv.xml | 5 +-
.../collection1/conf/schema-version-indexed.xml | 5 +-
.../solr/collection1/conf/schema15.xml | 22 +-
...dd-schema-fields-update-processor-chains.xml | 2 +-
.../conf/solrconfig-altdirectory.xml | 2 +-
.../conf/solrconfig-analytics-query.xml | 227 +-
.../solr/collection1/conf/solrconfig-basic.xml | 2 +-
.../conf/solrconfig-blockjoinfacetcomponent.xml | 11 +-
.../conf/solrconfig-cache-enable-disable.xml | 4 +-
.../solr/collection1/conf/solrconfig-cdcr.xml | 2 +-
.../conf/solrconfig-cdcrupdatelog.xml | 2 +-
.../conf/solrconfig-classification.xml | 2 +-
.../conf/solrconfig-collapseqparser.xml | 125 +-
.../conf/solrconfig-components-name.xml | 4 +-
.../solrconfig-configurerecoverystrategy.xml | 2 +-
.../conf/solrconfig-customrecoverystrategy.xml | 2 +-
.../conf/solrconfig-delaying-component.xml | 2 +-
.../collection1/conf/solrconfig-delpolicy1.xml | 2 +-
.../collection1/conf/solrconfig-delpolicy2.xml | 2 +-
...lrconfig-distrib-update-processor-chains.xml | 3 +-
.../conf/solrconfig-doctransformers.xml | 4 +-
.../collection1/conf/solrconfig-elevate.xml | 2 +-
.../solrconfig-externalversionconstraint.xml | 2 +-
.../conf/solrconfig-functionquery.xml | 4 +-
.../solr/collection1/conf/solrconfig-hash.xml | 4 +-
.../collection1/conf/solrconfig-headers.xml | 2 +-
.../collection1/conf/solrconfig-highlight.xml | 2 +-
.../conf/solrconfig-implicitproperties.xml | 2 +-
.../conf/solrconfig-infixsuggesters.xml | 2 +-
.../conf/solrconfig-logmergepolicyfactory.xml | 2 +-
.../conf/solrconfig-managed-schema-test.xml | 2 +-
.../conf/solrconfig-managed-schema.xml | 4 +-
.../conf/solrconfig-master-throttled.xml | 8 +-
.../solr/collection1/conf/solrconfig-master.xml | 8 +-
.../conf/solrconfig-master1-keepOneBackup.xml | 4 +-
.../collection1/conf/solrconfig-master1.xml | 8 +-
.../collection1/conf/solrconfig-master2.xml | 8 +-
.../collection1/conf/solrconfig-master3.xml | 8 +-
.../conf/solrconfig-mergepolicy-defaults.xml | 2 +-
.../conf/solrconfig-mergepolicy-legacy.xml | 2 +-
.../solrconfig-mergepolicyfactory-nocfs.xml | 2 +-
.../collection1/conf/solrconfig-nocache.xml | 8 +-
.../conf/solrconfig-nomergepolicyfactory.xml | 2 +-
.../collection1/conf/solrconfig-noopregen.xml | 2 +-
.../collection1/conf/solrconfig-paramset.xml | 2 +-
...lrconfig-parsing-update-processor-chains.xml | 2 +-
.../conf/solrconfig-phrasesuggest.xml | 2 +-
.../conf/solrconfig-plugcollector.xml | 28 +-
.../conf/solrconfig-postingshighlight.xml | 2 +-
.../conf/solrconfig-query-parser-init.xml | 2 +-
.../conf/solrconfig-querysender-noquery.xml | 2 +-
.../collection1/conf/solrconfig-querysender.xml | 8 +-
.../collection1/conf/solrconfig-repeater.xml | 8 +-
.../collection1/conf/solrconfig-reqHandler.incl | 2 +-
.../conf/solrconfig-response-log-component.xml | 16 +-
.../collection1/conf/solrconfig-schemaless.xml | 2 +-
.../conf/solrconfig-script-updateprocessor.xml | 2 +-
.../conf/solrconfig-searcher-listeners1.xml | 2 +-
.../solr/collection1/conf/solrconfig-slave.xml | 8 +-
.../solr/collection1/conf/solrconfig-slave1.xml | 8 +-
.../conf/solrconfig-solcoreproperties.xml | 2 +-
.../solrconfig-sortingmergepolicyfactory.xml | 4 +-
.../conf/solrconfig-sortingresponse.xml | 2 +-
.../collection1/conf/solrconfig-spatial.xml | 2 +-
.../conf/solrconfig-spellcheckcomponent.xml | 12 +-
.../conf/solrconfig-spellchecker.xml | 2 +-
.../solr/collection1/conf/solrconfig-sql.xml | 4 +-
...-suggestercomponent-context-filter-query.xml | 2 +-
.../conf/solrconfig-suggestercomponent.xml | 2 +-
.../collection1/conf/solrconfig-test-misc.xml | 4 +-
.../conf/solrconfig-testxmlparser.xml | 2 +-
.../solrconfig-tieredmergepolicyfactory.xml | 2 +-
.../solr/collection1/conf/solrconfig-tlog.xml | 5 +-
...nfig-uninvertdocvaluesmergepolicyfactory.xml | 2 +-
.../conf/solrconfig-update-processor-chains.xml | 2 +-
...lrconfig-warmer-randommergepolicyfactory.xml | 2 +-
.../solr/collection1/conf/solrconfig.xml | 35 +-
.../conf/solrconfig_SimpleTextCodec.xml | 2 +-
.../solr/collection1/conf/solrconfig_codec.xml | 2 +-
.../solr/collection1/conf/solrconfig_codec2.xml | 2 +-
.../solr/collection1/conf/solrconfig_perf.xml | 5 +-
.../solr/configsets/_default/conf/currency.xml | 67 +
.../solr/configsets/_default/conf/elevate.xml | 42 +
.../_default/conf/lang/contractions_ca.txt | 8 +
.../_default/conf/lang/contractions_fr.txt | 15 +
.../_default/conf/lang/contractions_ga.txt | 5 +
.../_default/conf/lang/contractions_it.txt | 23 +
.../_default/conf/lang/hyphenations_ga.txt | 5 +
.../_default/conf/lang/stemdict_nl.txt | 6 +
.../_default/conf/lang/stoptags_ja.txt | 420 +++
.../_default/conf/lang/stopwords_ar.txt | 125 +
.../_default/conf/lang/stopwords_bg.txt | 193 ++
.../_default/conf/lang/stopwords_ca.txt | 220 ++
.../_default/conf/lang/stopwords_cz.txt | 172 +
.../_default/conf/lang/stopwords_da.txt | 110 +
.../_default/conf/lang/stopwords_de.txt | 294 ++
.../_default/conf/lang/stopwords_el.txt | 78 +
.../_default/conf/lang/stopwords_en.txt | 54 +
.../_default/conf/lang/stopwords_es.txt | 356 ++
.../_default/conf/lang/stopwords_eu.txt | 99 +
.../_default/conf/lang/stopwords_fa.txt | 313 ++
.../_default/conf/lang/stopwords_fi.txt | 97 +
.../_default/conf/lang/stopwords_fr.txt | 186 +
.../_default/conf/lang/stopwords_ga.txt | 110 +
.../_default/conf/lang/stopwords_gl.txt | 161 +
.../_default/conf/lang/stopwords_hi.txt | 235 ++
.../_default/conf/lang/stopwords_hu.txt | 211 ++
.../_default/conf/lang/stopwords_hy.txt | 46 +
.../_default/conf/lang/stopwords_id.txt | 359 ++
.../_default/conf/lang/stopwords_it.txt | 303 ++
.../_default/conf/lang/stopwords_ja.txt | 127 +
.../_default/conf/lang/stopwords_lv.txt | 172 +
.../_default/conf/lang/stopwords_nl.txt | 119 +
.../_default/conf/lang/stopwords_no.txt | 194 ++
.../_default/conf/lang/stopwords_pt.txt | 253 ++
.../_default/conf/lang/stopwords_ro.txt | 233 ++
.../_default/conf/lang/stopwords_ru.txt | 243 ++
.../_default/conf/lang/stopwords_sv.txt | 133 +
.../_default/conf/lang/stopwords_th.txt | 119 +
.../_default/conf/lang/stopwords_tr.txt | 212 ++
.../_default/conf/lang/userdict_ja.txt | 29 +
.../configsets/_default/conf/managed-schema | 1076 ++++++
.../solr/configsets/_default/conf/params.json | 20 +
.../solr/configsets/_default/conf/protwords.txt | 21 +
.../solr/configsets/_default/conf/schema.xml | 37 -
.../configsets/_default/conf/solrconfig.xml | 1355 +++++++-
.../solr/configsets/_default/conf/stopwords.txt | 14 +
.../solr/configsets/_default/conf/synonyms.txt | 29 +
.../bad-mergepolicy/conf/solrconfig.xml | 2 +-
.../cdcr-source-disabled/conf/schema.xml | 2 +-
.../solr/configsets/cdcr-source/conf/schema.xml | 2 +-
.../configsets/cdcr-source/conf/solrconfig.xml | 3 +-
.../solr/configsets/cdcr-target/conf/schema.xml | 2 +-
.../configsets/cdcr-target/conf/solrconfig.xml | 3 +-
.../exitable-directory/conf/solrconfig.xml | 2 +-
.../test-files/solr/crazy-path-to-config.xml | 10 +-
solr/core/src/test-files/solr/solr.xml | 1 +
.../org/apache/solr/BasicFunctionalityTest.java | 6 +-
.../org/apache/solr/ConvertedLegacyTest.java | 46 +-
.../apache/solr/DisMaxRequestHandlerTest.java | 8 +-
.../test/org/apache/solr/EchoParamsTest.java | 4 +-
.../src/test/org/apache/solr/SampleTest.java | 2 +-
.../test/org/apache/solr/SolrInfoBeanTest.java | 4 +-
.../org/apache/solr/TestDistributedSearch.java | 6 +-
.../org/apache/solr/TestRandomDVFaceting.java | 28 +-
.../client/solrj/impl/ConnectionReuseTest.java | 4 +-
.../solr/cloud/BaseCdcrDistributedZkTest.java | 3 +-
.../solr/cloud/BasicDistributedZkTest.java | 51 +-
.../test/org/apache/solr/cloud/BasicZkTest.java | 2 +-
.../cloud/ChaosMonkeyNothingIsSafeTest.java | 19 +-
...MonkeyNothingIsSafeWithPullReplicasTest.java | 20 +-
.../solr/cloud/CollectionsAPISolrJTest.java | 27 +-
.../org/apache/solr/cloud/DeleteNodeTest.java | 61 +-
.../cloud/FullSolrCloudDistribCmdsTest.java | 3 +-
.../FullThrottleStoppableIndexingThread.java | 4 +-
.../apache/solr/cloud/HttpPartitionTest.java | 4 +-
.../apache/solr/cloud/MigrateRouteKeyTest.java | 8 +-
.../apache/solr/cloud/MoveReplicaHDFSTest.java | 69 +
.../org/apache/solr/cloud/MoveReplicaTest.java | 83 +-
.../org/apache/solr/cloud/ShardSplitTest.java | 10 +-
.../org/apache/solr/cloud/SyncSliceTest.java | 5 +-
.../apache/solr/cloud/TestCloudRecovery.java | 8 -
.../apache/solr/cloud/TestConfigSetsAPI.java | 49 +
.../org/apache/solr/cloud/TestPrepRecovery.java | 109 +
.../cloud/TestRandomRequestDistribution.java | 12 +-
.../cloud/TestRequestStatusCollectionAPI.java | 3 +-
.../TestSolrCloudWithDelegationTokens.java | 3 -
.../solr/cloud/UnloadDistributedZkTest.java | 41 +-
.../org/apache/solr/cloud/ZkControllerTest.java | 19 +-
.../autoscaling/AutoScalingHandlerTest.java | 36 +-
.../autoscaling/ComputePlanActionTest.java | 41 +-
.../autoscaling/ExecutePlanActionTest.java | 183 +
.../autoscaling/TriggerIntegrationTest.java | 50 +-
.../apache/solr/cloud/hdfs/StressHdfsTest.java | 3 +-
.../solr/core/AlternateDirectoryTest.java | 2 +-
.../apache/solr/core/DirectoryFactoryTest.java | 15 +-
.../solr/core/OpenCloseCoreStressTest.java | 8 +-
.../apache/solr/core/RequestHandlersTest.java | 8 +-
.../test/org/apache/solr/core/SolrCoreTest.java | 2 +-
.../test/org/apache/solr/core/TestConfig.java | 4 +-
.../org/apache/solr/core/TestCoreDiscovery.java | 3 +-
.../org/apache/solr/core/TestLazyCores.java | 44 +-
.../solr/core/TestQuerySenderListener.java | 2 +-
.../solr/core/TestQuerySenderNoQuery.java | 2 +-
.../apache/solr/core/TestXIncludeConfig.java | 2 +-
.../solr/handler/MoreLikeThisHandlerTest.java | 1 -
.../apache/solr/handler/SearchHandlerTest.java | 80 +
.../handler/StandardRequestHandlerTest.java | 88 -
.../solr/handler/TestReplicationHandler.java | 4 +-
.../handler/TestReplicationHandlerBackup.java | 4 +-
.../apache/solr/handler/TestRestoreCore.java | 4 +-
.../solr/handler/V2ApiIntegrationTest.java | 9 +-
.../handler/admin/CoreAdminHandlerTest.java | 36 +-
.../DistributedSpellCheckComponentTest.java | 10 +-
.../handler/component/FacetPivotSmallTest.java | 1 -
.../component/ResponseLogComponentTest.java | 12 +-
.../component/SpellCheckComponentTest.java | 10 +-
.../handler/component/StatsComponentTest.java | 1 -
.../handler/component/SuggestComponentTest.java | 2 +-
.../component/TermVectorComponentTest.java | 2 +-
.../highlight/FastVectorHighlighterTest.java | 2 +-
.../solr/highlight/HighlighterConfigTest.java | 2 +-
.../apache/solr/highlight/HighlighterTest.java | 84 +-
.../metrics/SolrMetricsIntegrationTest.java | 2 +-
.../metrics/reporters/SolrJmxReporterTest.java | 18 +-
.../apache/solr/request/SimpleFacetsTest.java | 4 +-
.../solr/request/TestIntervalFaceting.java | 2 +-
.../apache/solr/schema/DocValuesMultiTest.java | 10 +-
.../search/TestComplexPhraseQParserPlugin.java | 8 +-
.../search/join/BlockJoinFacetDistribTest.java | 2 +-
.../search/join/BlockJoinFacetRandomTest.java | 2 +-
.../search/join/BlockJoinFacetSimpleTest.java | 2 +-
.../TestNonDefinedSimilarityFactory.java | 10 -
.../hadoop/TestDelegationWithHadoopAuth.java | 1 -
.../spelling/DirectSolrSpellCheckerTest.java | 2 +-
.../solr/spelling/SpellCheckCollatorTest.java | 43 +-
.../SpellCheckCollatorWithCollapseTest.java | 2 +-
.../spelling/WordBreakSolrSpellCheckerTest.java | 16 +-
.../example-DIH/solr/atom/conf/solrconfig.xml | 2 +-
.../example-DIH/solr/db/conf/solrconfig.xml | 26 +-
.../example-DIH/solr/mail/conf/solrconfig.xml | 26 +-
.../example-DIH/solr/solr/conf/solrconfig.xml | 26 +-
.../example-DIH/solr/tika/conf/solrconfig.xml | 2 +-
solr/example/files/conf/solrconfig.xml | 26 +-
.../configsets/_default/conf/solrconfig.xml | 25 +-
.../conf/solrconfig.xml | 25 +-
.../src/cross-data-center-replication-cdcr.adoc | 6 +-
.../src/distributed-requests.adoc | 4 +-
.../src/the-dismax-query-parser.adoc | 16 +-
.../src/uploading-data-with-index-handlers.adoc | 2 +-
.../solr/client/solrj/impl/CloudSolrClient.java | 67 +-
.../solrj/impl/ConcurrentUpdateSolrClient.java | 36 +
.../solr/client/solrj/impl/HttpSolrClient.java | 40 +-
.../client/solrj/impl/LBHttpSolrClient.java | 60 +-
.../solr/common/params/MoreLikeThisParams.java | 3 +-
.../solr/collection1/conf/solrconfig-slave1.xml | 8 +-
.../solr/collection1/conf/solrconfig-sql.xml | 4 +-
.../solrj/solr/collection1/conf/solrconfig.xml | 4 +-
.../solr/configsets/ml/conf/solrconfig.xml | 4 +-
.../solr/configsets/shared/conf/solrconfig.xml | 8 +-
.../configsets/streaming/conf/solrconfig.xml | 6 +-
.../solr/multicore/core0/conf/solrconfig.xml | 8 +-
.../solr/multicore/core1/conf/solrconfig.xml | 8 +-
.../client/solrj/SolrExampleBinaryTest.java | 3 +-
.../solr/client/solrj/SolrExampleXMLTest.java | 3 +-
.../solr/client/solrj/SolrExceptionTest.java | 3 +-
.../client/solrj/SolrSchemalessExampleTest.java | 3 +-
.../solr/client/solrj/TestLBHttpSolrClient.java | 4 +-
.../embedded/SolrExampleStreamingTest.java | 2 +-
.../solrj/impl/BasicHttpSolrClientTest.java | 3 +-
.../client/solrj/impl/CloudSolrClientTest.java | 6 +-
.../solrj/impl/HttpSolrClientConPoolTest.java | 3 +-
.../java/org/apache/solr/SolrJettyTestBase.java | 3 +-
.../java/org/apache/solr/SolrTestCaseJ4.java | 148 +-
.../cloud/AbstractFullDistribZkTestBase.java | 31 +-
784 files changed, 42728 insertions(+), 18623 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b0eed4ce/solr/core/src/test/org/apache/solr/cloud/autoscaling/AutoScalingHandlerTest.java
----------------------------------------------------------------------
[5/5] lucene-solr:jira/solr-10996: SOLR-10996 Some refactoring to use
base classes, plus unit tests.
Posted by ab...@apache.org.
SOLR-10996 Some refactoring to use base classes, plus unit tests.
Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/b52e1148
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/b52e1148
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/b52e1148
Branch: refs/heads/jira/solr-10996
Commit: b52e114806531b96e0fc1df5fe5e57056056349c
Parents: b0eed4c
Author: Andrzej Bialecki <ab...@apache.org>
Authored: Wed Jul 5 21:42:12 2017 +0200
Committer: Andrzej Bialecki <ab...@apache.org>
Committed: Wed Jul 5 21:42:12 2017 +0200
----------------------------------------------------------------------
.../solr/cloud/autoscaling/AutoScaling.java | 21 --
.../cloud/autoscaling/AutoScalingConfig.java | 44 +++-
.../cloud/autoscaling/AutoScalingHandler.java | 2 +-
.../cloud/autoscaling/ComputePlanAction.java | 19 +-
.../cloud/autoscaling/ExecutePlanAction.java | 20 +-
.../cloud/autoscaling/HttpTriggerListener.java | 17 +-
.../solr/cloud/autoscaling/LogPlanAction.java | 20 +-
.../cloud/autoscaling/LogTriggerListener.java | 21 +-
.../cloud/autoscaling/ScheduledTriggers.java | 51 ++--
.../cloud/autoscaling/TriggerActionBase.java | 47 ++++
.../solr/cloud/autoscaling/TriggerListener.java | 42 ++++
.../cloud/autoscaling/TriggerListenerBase.java | 46 ++++
.../autoscaling/TriggerIntegrationTest.java | 246 ++++++++++++++++---
13 files changed, 420 insertions(+), 176 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b52e1148/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 c1a1169..fa7311c 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
@@ -64,27 +64,6 @@ public class AutoScaling {
}
/**
- * Implementations of this interface are notified of stages in event processing that they were
- * registered for. Note: instances may be closed and re-created on each auto-scaling config update.
- */
- public interface TriggerListener extends Closeable {
-
- void init(CoreContainer coreContainer, AutoScalingConfig.TriggerListenerConfig config);
-
- AutoScalingConfig.TriggerListenerConfig getTriggerListenerConfig();
-
- /**
- * This method is called when either a particular <code>stage</code> or
- * <code>actionName</code> is reached during event processing.
- * @param stage {@link EventProcessorStage} that this listener was registered for, or null
- * @param actionName {@link TriggerAction} name that this listener was registered for, or null
- * @param event current event being processed
- * @param message optional message
- */
- void onEvent(EventProcessorStage stage, String actionName, TriggerEvent event, String message);
- }
-
- /**
* Interface for a Solr trigger. Each trigger implements Runnable and Closeable interface. A trigger
* is scheduled using a {@link java.util.concurrent.ScheduledExecutorService} so it is executed as
* per a configured schedule to check whether the trigger is ready to fire. The {@link Trigger#setProcessor(EventProcessor)}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b52e1148/solr/core/src/java/org/apache/solr/cloud/autoscaling/AutoScalingConfig.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/autoscaling/AutoScalingConfig.java b/solr/core/src/java/org/apache/solr/cloud/autoscaling/AutoScalingConfig.java
index f2c251c..056091d 100644
--- a/solr/core/src/java/org/apache/solr/cloud/autoscaling/AutoScalingConfig.java
+++ b/solr/core/src/java/org/apache/solr/cloud/autoscaling/AutoScalingConfig.java
@@ -17,7 +17,6 @@
package org.apache.solr.cloud.autoscaling;
import java.lang.invoke.MethodHandles;
-import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -46,9 +45,10 @@ public class AutoScalingConfig {
private Map<String, TriggerListenerConfig> listeners;
/**
- * Bean representation of {@link org.apache.solr.cloud.autoscaling.AutoScaling.TriggerListener} config.
+ * Bean representation of {@link TriggerListener} config.
*/
public static class TriggerListenerConfig {
+ public final String name;
public final String trigger;
public final Set<AutoScaling.EventProcessorStage> stages;
public final String listenerClass;
@@ -56,22 +56,23 @@ public class AutoScalingConfig {
public final Set<String> afterActions;
public final Map<String, Object> properties = new HashMap<>();
- public TriggerListenerConfig(Map<String, Object> properties) {
+ public TriggerListenerConfig(String name, Map<String, Object> properties) {
+ this.name = name;
this.properties.putAll(properties);
trigger = (String)properties.get(AutoScalingParams.TRIGGER);
- List<String> stageNames = (List<String>)properties.getOrDefault(AutoScalingParams.STAGE, Collections.emptyList());
+ List<String> stageNames = getList(AutoScalingParams.STAGE, properties);
stages = new HashSet<>(stageNames.size());
- for (String name : stageNames) {
+ for (String stageName : stageNames) {
try {
- AutoScaling.EventProcessorStage stage = AutoScaling.EventProcessorStage.valueOf(name.toUpperCase(Locale.ROOT));
+ AutoScaling.EventProcessorStage stage = AutoScaling.EventProcessorStage.valueOf(stageName.toUpperCase(Locale.ROOT));
stages.add(stage);
} catch (Exception e) {
LOG.warn("Invalid stage name '" + name + "' in listener config, skipping: " + properties);
}
}
listenerClass = (String)properties.get(AutoScalingParams.CLASS);
- beforeActions = new HashSet<>((List<String>)properties.getOrDefault(AutoScalingParams.BEFORE_ACTION, Collections.emptyList()));
- afterActions = new HashSet<>((List<String>)properties.getOrDefault(AutoScalingParams.AFTER_ACTION, Collections.emptyList()));
+ beforeActions = new HashSet<>(getList(AutoScalingParams.BEFORE_ACTION, properties));
+ afterActions = new HashSet<>(getList(AutoScalingParams.AFTER_ACTION, properties));
}
}
@@ -79,10 +80,12 @@ public class AutoScalingConfig {
* Bean representation of {@link org.apache.solr.cloud.autoscaling.AutoScaling.Trigger} config.
*/
public static class TriggerConfig {
+ public final String name;
public final AutoScaling.EventType eventType;
public final Map<String, Object> properties = new HashMap<>();
- public TriggerConfig(Map<String, Object> properties) {
+ public TriggerConfig(String name, Map<String, Object> properties) {
+ this.name = name;
String event = (String) properties.get(AutoScalingParams.EVENT);
this.eventType = AutoScaling.EventType.valueOf(event.toUpperCase(Locale.ROOT));
this.properties.putAll(properties);
@@ -129,7 +132,7 @@ public class AutoScalingConfig {
} else {
triggers = new HashMap<>(trigMap.size());
for (Map.Entry<String, Object> entry : trigMap.entrySet()) {
- triggers.put(entry.getKey(), new TriggerConfig((Map<String, Object>)entry.getValue()));
+ triggers.put(entry.getKey(), new TriggerConfig(entry.getKey(), (Map<String, Object>)entry.getValue()));
}
}
}
@@ -167,11 +170,30 @@ public class AutoScalingConfig {
} else {
listeners = new HashMap<>(map.size());
for (Map.Entry<String, Object> entry : map.entrySet()) {
- listeners.put(entry.getKey(), new TriggerListenerConfig((Map<String, Object>)entry.getValue()));
+ listeners.put(entry.getKey(), new TriggerListenerConfig(entry.getKey(), (Map<String, Object>)entry.getValue()));
}
}
}
return listeners;
}
+ private static List<String> getList(String key, Map<String, Object> properties) {
+ return getList(key, properties, null);
+ }
+
+ private static List<String> getList(String key, Map<String, Object> properties, List<String> defaultList) {
+ if (defaultList == null) {
+ defaultList = Collections.emptyList();
+ }
+ Object o = properties.get(key);
+ if (o == null) {
+ return defaultList;
+ }
+ if (o instanceof List) {
+ return (List)o;
+ } else {
+ return Collections.singletonList(String.valueOf(o));
+ }
+ }
+
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b52e1148/solr/core/src/java/org/apache/solr/cloud/autoscaling/AutoScalingHandler.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/autoscaling/AutoScalingHandler.java b/solr/core/src/java/org/apache/solr/cloud/autoscaling/AutoScalingHandler.java
index 5f877b8..e730088 100644
--- a/solr/core/src/java/org/apache/solr/cloud/autoscaling/AutoScalingHandler.java
+++ b/solr/core/src/java/org/apache/solr/cloud/autoscaling/AutoScalingHandler.java
@@ -391,7 +391,7 @@ public class AutoScalingHandler extends RequestHandlerBase implements Permission
// validate that we can load the listener class
// todo nocommit -- what about MemClassLoader?
try {
- container.getResourceLoader().findClass(listenerClass, AutoScaling.TriggerListener.class);
+ container.getResourceLoader().findClass(listenerClass, TriggerListener.class);
} catch (Exception e) {
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Listener not found: " + listenerClass, e);
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b52e1148/solr/core/src/java/org/apache/solr/cloud/autoscaling/ComputePlanAction.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/autoscaling/ComputePlanAction.java b/solr/core/src/java/org/apache/solr/cloud/autoscaling/ComputePlanAction.java
index cb876a5..5cb8f1c 100644
--- a/solr/core/src/java/org/apache/solr/cloud/autoscaling/ComputePlanAction.java
+++ b/solr/core/src/java/org/apache/solr/cloud/autoscaling/ComputePlanAction.java
@@ -42,26 +42,9 @@ import org.slf4j.LoggerFactory;
* The cluster operations computed here are put into the {@link ActionContext}'s properties
* with the key name "operations". The value is a List of SolrRequest objects.
*/
-public class ComputePlanAction implements TriggerAction {
+public class ComputePlanAction extends TriggerActionBase {
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
- private Map<String, String> initArgs;
-
- @Override
- public void close() throws IOException {
-
- }
-
- @Override
- public void init(Map<String, String> args) {
- this.initArgs = args;
- }
-
- @Override
- public String getName() {
- return initArgs.get("name");
- }
-
@Override
public void process(TriggerEvent event, ActionContext context) {
log.debug("-- processing event: {} with context properties: {}", event, context.getProperties());
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b52e1148/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 86e24f4..2cd9824 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
@@ -21,7 +21,6 @@ import java.io.IOException;
import java.lang.invoke.MethodHandles;
import java.util.ArrayList;
import java.util.List;
-import java.util.Map;
import org.apache.solr.client.solrj.SolrRequest;
import org.apache.solr.client.solrj.SolrResponse;
@@ -38,26 +37,9 @@ import org.slf4j.LoggerFactory;
* This class is responsible for executing cluster operations read from the {@link ActionContext}'s properties
* with the key name "operations"
*/
-public class ExecutePlanAction implements TriggerAction {
+public class ExecutePlanAction extends TriggerActionBase {
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
- private Map<String, String> initArgs;
-
- @Override
- public void close() throws IOException {
-
- }
-
- @Override
- public void init(Map<String, String> args) {
- this.initArgs = args;
- }
-
- @Override
- public String getName() {
- return initArgs.get("name");
- }
-
@Override
public void process(TriggerEvent event, ActionContext context) {
log.debug("-- processing event: {} with context properties: {}", event, context.getProperties());
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b52e1148/solr/core/src/java/org/apache/solr/cloud/autoscaling/HttpTriggerListener.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/autoscaling/HttpTriggerListener.java b/solr/core/src/java/org/apache/solr/cloud/autoscaling/HttpTriggerListener.java
index 84cccf0..4253bf6 100644
--- a/solr/core/src/java/org/apache/solr/cloud/autoscaling/HttpTriggerListener.java
+++ b/solr/core/src/java/org/apache/solr/cloud/autoscaling/HttpTriggerListener.java
@@ -16,22 +16,19 @@
*/
package org.apache.solr.cloud.autoscaling;
-import java.io.IOException;
-
import org.apache.http.client.HttpClient;
import org.apache.solr.core.CoreContainer;
/**
* Simple HTTP callback that sends trigger events as JSON.
*/
-public class HttpTriggerListener implements AutoScaling.TriggerListener {
+public class HttpTriggerListener extends TriggerListenerBase {
private HttpClient httpClient;
- private AutoScalingConfig.TriggerListenerConfig config;
@Override
public void init(CoreContainer coreContainer, AutoScalingConfig.TriggerListenerConfig config) {
- this.config = config;
+ super.init(coreContainer, config);
httpClient = coreContainer.getUpdateShardHandler().getHttpClient();
}
@@ -39,14 +36,4 @@ public class HttpTriggerListener implements AutoScaling.TriggerListener {
public void onEvent(AutoScaling.EventProcessorStage stage, String actionName, TriggerEvent event, String message) {
}
-
- @Override
- public AutoScalingConfig.TriggerListenerConfig getTriggerListenerConfig() {
- return config;
- }
-
- @Override
- public void close() throws IOException {
-
- }
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b52e1148/solr/core/src/java/org/apache/solr/cloud/autoscaling/LogPlanAction.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/autoscaling/LogPlanAction.java b/solr/core/src/java/org/apache/solr/cloud/autoscaling/LogPlanAction.java
index 7b2de80..45107c1 100644
--- a/solr/core/src/java/org/apache/solr/cloud/autoscaling/LogPlanAction.java
+++ b/solr/core/src/java/org/apache/solr/cloud/autoscaling/LogPlanAction.java
@@ -17,28 +17,10 @@
package org.apache.solr.cloud.autoscaling;
-import java.io.IOException;
-import java.util.Map;
-
/**
* todo nocommit
*/
-public class LogPlanAction implements TriggerAction {
- @Override
- public void close() throws IOException {
-
- }
-
- @Override
- public void init(Map<String, String> args) {
-
- }
-
- @Override
- public String getName() {
- return null;
- }
-
+public class LogPlanAction extends TriggerActionBase {
@Override
public void process(TriggerEvent event, ActionContext actionContext) {
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b52e1148/solr/core/src/java/org/apache/solr/cloud/autoscaling/LogTriggerListener.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/autoscaling/LogTriggerListener.java b/solr/core/src/java/org/apache/solr/cloud/autoscaling/LogTriggerListener.java
index 2246b73..bf00114 100644
--- a/solr/core/src/java/org/apache/solr/cloud/autoscaling/LogTriggerListener.java
+++ b/solr/core/src/java/org/apache/solr/cloud/autoscaling/LogTriggerListener.java
@@ -25,31 +25,14 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
- * Implementation of {@link org.apache.solr.cloud.autoscaling.AutoScaling.TriggerListener} that reports
+ * Implementation of {@link TriggerListener} that reports
* events to a log.
*/
-public class LogTriggerListener implements AutoScaling.TriggerListener {
+public class LogTriggerListener extends TriggerListenerBase {
private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
- private AutoScalingConfig.TriggerListenerConfig config;
-
- @Override
- public void init(CoreContainer coreContainer, AutoScalingConfig.TriggerListenerConfig config) {
- this.config = config;
- }
-
- @Override
- public AutoScalingConfig.TriggerListenerConfig getTriggerListenerConfig() {
- return config;
- }
-
@Override
public void onEvent(AutoScaling.EventProcessorStage stage, String actionName, TriggerEvent event, String message) {
LOG.info("stage={}, actionName={}, event={}, messsage={}", stage, actionName, event, message);
}
-
- @Override
- public void close() throws IOException {
-
- }
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b52e1148/solr/core/src/java/org/apache/solr/cloud/autoscaling/ScheduledTriggers.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/autoscaling/ScheduledTriggers.java b/solr/core/src/java/org/apache/solr/cloud/autoscaling/ScheduledTriggers.java
index 1be62a4..d5d29de 100644
--- a/solr/core/src/java/org/apache/solr/cloud/autoscaling/ScheduledTriggers.java
+++ b/solr/core/src/java/org/apache/solr/cloud/autoscaling/ScheduledTriggers.java
@@ -369,8 +369,8 @@ public class ScheduledTriggers implements Closeable {
}
private class TriggerListeners {
- Map<String, Map<AutoScaling.EventProcessorStage, List<AutoScaling.TriggerListener>>> listenerPerStage = new HashMap<>();
- List<AutoScaling.TriggerListener> listeners = new ArrayList<>();
+ Map<String, Map<AutoScaling.EventProcessorStage, List<TriggerListener>>> listenerPerStage = new HashMap<>();
+ List<TriggerListener> listeners = new ArrayList<>();
ReentrantLock updateLock = new ReentrantLock();
void setAutoScalingConfig(AutoScalingConfig autoScalingConfig) {
@@ -388,9 +388,9 @@ public class ScheduledTriggers implements Closeable {
continue;
}
String clazz = config.listenerClass;
- AutoScaling.TriggerListener listener = null;
+ TriggerListener listener = null;
try {
- listener = coreContainer.getResourceLoader().newInstance(clazz, AutoScaling.TriggerListener.class);
+ listener = coreContainer.getResourceLoader().newInstance(clazz, TriggerListener.class);
} catch (Exception e) {
log.warn("Invalid TriggerListener class name '" + clazz + "', skipping...", e);
}
@@ -400,18 +400,15 @@ public class ScheduledTriggers implements Closeable {
listener.init(coreContainer, config);
listeners.add(listener);
// add per stage
- Map<AutoScaling.EventProcessorStage, List<AutoScaling.TriggerListener>> perStage = listenerPerStage.get(config.trigger);
- if (perStage == null) {
- perStage = new HashMap<>();
- listenerPerStage.put(config.trigger, perStage);
- }
for (AutoScaling.EventProcessorStage stage : config.stages) {
- List<AutoScaling.TriggerListener> lst = perStage.get(stage);
- if (lst == null) {
- lst = new ArrayList<>(3);
- perStage.put(stage, lst);
- }
- lst.add(listener);
+ addPerStage(config.trigger, stage, listener);
+ }
+ // add also for beforeAction / afterAction TriggerStage
+ if (!config.beforeActions.isEmpty()) {
+ addPerStage(config.trigger, AutoScaling.EventProcessorStage.BEFORE_ACTION, listener);
+ }
+ if (!config.afterActions.isEmpty()) {
+ addPerStage(config.trigger, AutoScaling.EventProcessorStage.AFTER_ACTION, listener);
}
}
} finally {
@@ -419,11 +416,25 @@ public class ScheduledTriggers implements Closeable {
}
}
+ private void addPerStage(String triggerName, AutoScaling.EventProcessorStage stage, TriggerListener listener) {
+ Map<AutoScaling.EventProcessorStage, List<TriggerListener>> perStage = listenerPerStage.get(triggerName);
+ if (perStage == null) {
+ perStage = new HashMap<>();
+ listenerPerStage.put(triggerName, perStage);
+ }
+ List<TriggerListener> lst = perStage.get(stage);
+ if (lst == null) {
+ lst = new ArrayList<>(3);
+ perStage.put(stage, lst);
+ }
+ lst.add(listener);
+ }
+
void close() {
updateLock.lock();
try {
listenerPerStage.clear();
- for (AutoScaling.TriggerListener listener : listeners) {
+ for (TriggerListener listener : listeners) {
IOUtils.closeQuietly(listener);
}
} finally {
@@ -431,12 +442,12 @@ public class ScheduledTriggers implements Closeable {
}
}
- List<AutoScaling.TriggerListener> getTriggerListeners(String trigger, AutoScaling.EventProcessorStage stage) {
- Map<AutoScaling.EventProcessorStage, List<AutoScaling.TriggerListener>> perStage = listenerPerStage.get(trigger);
+ List<TriggerListener> getTriggerListeners(String trigger, AutoScaling.EventProcessorStage stage) {
+ Map<AutoScaling.EventProcessorStage, List<TriggerListener>> perStage = listenerPerStage.get(trigger);
if (perStage == null) {
return Collections.emptyList();
}
- List<AutoScaling.TriggerListener> lst = perStage.get(stage);
+ List<TriggerListener> lst = perStage.get(stage);
if (lst == null) {
return Collections.emptyList();
} else {
@@ -447,7 +458,7 @@ public class ScheduledTriggers implements Closeable {
void fireListeners(String trigger, AutoScaling.EventProcessorStage stage, String actionName, TriggerEvent event, String message) {
updateLock.lock();
try {
- for (AutoScaling.TriggerListener listener : getTriggerListeners(trigger, stage)) {
+ for (TriggerListener listener : getTriggerListeners(trigger, stage)) {
if (actionName != null) {
AutoScalingConfig.TriggerListenerConfig config = listener.getTriggerListenerConfig();
if (stage == AutoScaling.EventProcessorStage.BEFORE_ACTION) {
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b52e1148/solr/core/src/java/org/apache/solr/cloud/autoscaling/TriggerActionBase.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/autoscaling/TriggerActionBase.java b/solr/core/src/java/org/apache/solr/cloud/autoscaling/TriggerActionBase.java
new file mode 100644
index 0000000..75c4a87
--- /dev/null
+++ b/solr/core/src/java/org/apache/solr/cloud/autoscaling/TriggerActionBase.java
@@ -0,0 +1,47 @@
+/*
+ * 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.io.IOException;
+import java.util.Map;
+
+/**
+ * Base class for {@link TriggerAction} implementations.
+ */
+public abstract class TriggerActionBase implements TriggerAction {
+
+ protected Map<String, String> initArgs;
+
+ @Override
+ public String getName() {
+ if (initArgs != null) {
+ return initArgs.get("name");
+ } else {
+ return getClass().getSimpleName();
+ }
+ }
+
+ @Override
+ public void close() throws IOException {
+
+ }
+
+ @Override
+ public void init(Map<String, String> args) {
+ this.initArgs = args;
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b52e1148/solr/core/src/java/org/apache/solr/cloud/autoscaling/TriggerListener.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/autoscaling/TriggerListener.java b/solr/core/src/java/org/apache/solr/cloud/autoscaling/TriggerListener.java
new file mode 100644
index 0000000..0cd5735
--- /dev/null
+++ b/solr/core/src/java/org/apache/solr/cloud/autoscaling/TriggerListener.java
@@ -0,0 +1,42 @@
+/*
+ * 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.io.Closeable;
+
+import org.apache.solr.core.CoreContainer;
+
+/**
+ * Implementations of this interface are notified of stages in event processing that they were
+ * registered for. Note: instances may be closed and re-created on each auto-scaling config update.
+ */
+public interface TriggerListener extends Closeable {
+
+ void init(CoreContainer coreContainer, AutoScalingConfig.TriggerListenerConfig config);
+
+ AutoScalingConfig.TriggerListenerConfig getTriggerListenerConfig();
+
+ /**
+ * This method is called when either a particular <code>stage</code> or
+ * <code>actionName</code> is reached during event processing.
+ * @param stage {@link AutoScaling.EventProcessorStage} that this listener was registered for, or null
+ * @param actionName {@link TriggerAction} name that this listener was registered for, or null
+ * @param event current event being processed
+ * @param message optional message
+ */
+ void onEvent(AutoScaling.EventProcessorStage stage, String actionName, TriggerEvent event, String message);
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b52e1148/solr/core/src/java/org/apache/solr/cloud/autoscaling/TriggerListenerBase.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/autoscaling/TriggerListenerBase.java b/solr/core/src/java/org/apache/solr/cloud/autoscaling/TriggerListenerBase.java
new file mode 100644
index 0000000..2887cec
--- /dev/null
+++ b/solr/core/src/java/org/apache/solr/cloud/autoscaling/TriggerListenerBase.java
@@ -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.solr.cloud.autoscaling;
+
+import java.io.IOException;
+
+import org.apache.solr.core.CoreContainer;
+
+/**
+ * Base class for implementations of {@link TriggerListener}.
+ */
+public abstract class TriggerListenerBase implements TriggerListener {
+
+ protected AutoScalingConfig.TriggerListenerConfig config;
+ protected CoreContainer coreContainer;
+
+ @Override
+ public void init(CoreContainer coreContainer, AutoScalingConfig.TriggerListenerConfig config) {
+ this.coreContainer = coreContainer;
+ this.config = config;
+ }
+
+ @Override
+ public AutoScalingConfig.TriggerListenerConfig getTriggerListenerConfig() {
+ return config;
+ }
+
+ @Override
+ public void close() throws IOException {
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b52e1148/solr/core/src/test/org/apache/solr/cloud/autoscaling/TriggerIntegrationTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/autoscaling/TriggerIntegrationTest.java b/solr/core/src/test/org/apache/solr/cloud/autoscaling/TriggerIntegrationTest.java
index 0ceb875..4f44afb 100644
--- a/solr/core/src/test/org/apache/solr/cloud/autoscaling/TriggerIntegrationTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/autoscaling/TriggerIntegrationTest.java
@@ -19,6 +19,8 @@ package org.apache.solr.cloud.autoscaling;
import java.io.IOException;
import java.lang.invoke.MethodHandles;
+import java.util.ArrayList;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -42,6 +44,7 @@ import org.apache.solr.common.cloud.ZkNodeProps;
import org.apache.solr.common.cloud.ZkStateReader;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.Utils;
+import org.apache.solr.core.CoreContainer;
import org.apache.solr.util.LogLevel;
import org.apache.solr.util.TimeOut;
import org.apache.solr.util.TimeSource;
@@ -566,18 +569,13 @@ public class TriggerIntegrationTest extends SolrCloudTestCase {
newNode.getNodeName(), nodeAddedEvent.getProperty(TriggerEvent.NODE_NAME));
}
- public static class TestTriggerAction implements TriggerAction {
+ public static class TestTriggerAction extends TriggerActionBase {
public TestTriggerAction() {
actionConstructorCalled.countDown();
}
@Override
- public String getName() {
- return "TestTriggerAction";
- }
-
- @Override
public void process(TriggerEvent event, ActionContext actionContext) {
try {
if (triggerFired.compareAndSet(false, true)) {
@@ -596,29 +594,20 @@ public class TriggerIntegrationTest extends SolrCloudTestCase {
}
@Override
- public void close() throws IOException {
-
- }
-
- @Override
public void init(Map<String, String> args) {
log.info("TestTriggerAction init");
actionInitCalled.countDown();
+ super.init(args);
}
}
- public static class TestEventQueueAction implements TriggerAction {
+ public static class TestEventQueueAction extends TriggerActionBase {
public TestEventQueueAction() {
log.info("TestEventQueueAction instantiated");
}
@Override
- public String getName() {
- return this.getClass().getSimpleName();
- }
-
- @Override
public void process(TriggerEvent event, ActionContext actionContext) {
log.info("-- event: " + event);
events.add(event);
@@ -634,14 +623,10 @@ public class TriggerIntegrationTest extends SolrCloudTestCase {
}
@Override
- public void close() throws IOException {
-
- }
-
- @Override
public void init(Map<String, String> args) {
log.debug("TestTriggerAction init");
actionInitCalled.countDown();
+ super.init(args);
}
}
@@ -790,18 +775,13 @@ public class TriggerIntegrationTest extends SolrCloudTestCase {
return listener;
}
- public static class TestEventMarkerAction implements TriggerAction {
+ public static class TestEventMarkerAction extends TriggerActionBase {
public TestEventMarkerAction() {
actionConstructorCalled.countDown();
}
@Override
- public String getName() {
- return "TestEventMarkerAction";
- }
-
- @Override
public void process(TriggerEvent event, ActionContext actionContext) {
boolean locked = lock.tryLock();
if (!locked) {
@@ -820,14 +800,10 @@ public class TriggerIntegrationTest extends SolrCloudTestCase {
}
@Override
- public void close() throws IOException {
-
- }
-
- @Override
public void init(Map<String, String> args) {
log.info("TestEventMarkerAction init");
actionInitCalled.countDown();
+ super.init(args);
}
}
@@ -952,4 +928,208 @@ public class TriggerIntegrationTest extends SolrCloudTestCase {
assertEquals(overseerLeader, ev.getProperty(TriggerEvent.NODE_NAME));
assertEquals(AutoScaling.EventType.NODELOST, ev.getEventType());
}
+
+ private static class TestEvent {
+ final AutoScalingConfig.TriggerListenerConfig config;
+ final AutoScaling.EventProcessorStage stage;
+ final String actionName;
+ final TriggerEvent event;
+ final String message;
+
+ TestEvent(AutoScalingConfig.TriggerListenerConfig config, AutoScaling.EventProcessorStage stage, String actionName, TriggerEvent event, String message) {
+ this.config = config;
+ this.stage = stage;
+ this.actionName = actionName;
+ this.event = event;
+ this.message = message;
+ }
+
+ @Override
+ public String toString() {
+ return "TestEvent{" +
+ "config=" + config +
+ ", stage=" + stage +
+ ", actionName='" + actionName + '\'' +
+ ", event=" + event +
+ ", message='" + message + '\'' +
+ '}';
+ }
+ }
+
+ static Map<String, List<TestEvent>> listenerEvents = new HashMap<>();
+ static CountDownLatch listenerCreated = new CountDownLatch(1);
+ static boolean failDummyAction = false;
+
+ public static class TestTriggerListener extends TriggerListenerBase {
+ @Override
+ public void init(CoreContainer coreContainer, AutoScalingConfig.TriggerListenerConfig config) {
+ super.init(coreContainer, config);
+ listenerCreated.countDown();
+ }
+
+ @Override
+ public synchronized void onEvent(AutoScaling.EventProcessorStage stage, String actionName, TriggerEvent event, String message) {
+ List<TestEvent> lst = listenerEvents.get(config.name);
+ if (lst == null) {
+ lst = new ArrayList<>();
+ listenerEvents.put(config.name, lst);
+ }
+ lst.add(new TestEvent(config, stage, actionName, event, message));
+ }
+ }
+
+ public static class TestDummyAction extends TriggerActionBase {
+
+ @Override
+ public void process(TriggerEvent event, ActionContext context) {
+ if (failDummyAction) {
+ throw new RuntimeException("failure");
+ }
+
+ }
+ }
+
+ @Test
+ public void testListeners() throws Exception {
+ CloudSolrClient solrClient = cluster.getSolrClient();
+ String setTriggerCommand = "{" +
+ "'set-trigger' : {" +
+ "'name' : 'node_added_trigger'," +
+ "'event' : 'nodeAdded'," +
+ "'waitFor' : '" + waitForSeconds + "s'," +
+ "'enabled' : true," +
+ "'actions' : [" +
+ "{'name':'test','class':'" + TestTriggerAction.class.getName() + "'}," +
+ "{'name':'test1','class':'" + TestDummyAction.class.getName() + "'}," +
+ "]" +
+ "}}";
+ SolrRequest req = createAutoScalingRequest(SolrRequest.METHOD.POST, setTriggerCommand);
+ NamedList<Object> response = solrClient.request(req);
+ assertEquals(response.get("result").toString(), "success");
+
+ if (!actionInitCalled.await(3, TimeUnit.SECONDS)) {
+ fail("The TriggerAction should have been created by now");
+ }
+
+ String setListenerCommand = "{" +
+ "'set-listener' : " +
+ "{" +
+ "'name' : 'foo'," +
+ "'trigger' : 'node_added_trigger'," +
+ "'stage' : ['WAITING', 'STARTED','ABORTED','SUCCEEDED', 'FAILED']," +
+ "'beforeAction' : 'test'," +
+ "'afterAction' : ['test', 'test1']," +
+ "'class' : '" + TestTriggerListener.class.getName() + "'" +
+ "}" +
+ "}";
+ req = createAutoScalingRequest(SolrRequest.METHOD.POST, setListenerCommand);
+ response = solrClient.request(req);
+ assertEquals(response.get("result").toString(), "success");
+
+ String setListenerCommand1 = "{" +
+ "'set-listener' : " +
+ "{" +
+ "'name' : 'bar'," +
+ "'trigger' : 'node_added_trigger'," +
+ "'stage' : ['WAITING','FAILED','SUCCEEDED']," +
+ "'beforeAction' : ['test', 'test1']," +
+ "'afterAction' : 'test'," +
+ "'class' : '" + TestTriggerListener.class.getName() + "'" +
+ "}" +
+ "}";
+ req = createAutoScalingRequest(SolrRequest.METHOD.POST, setListenerCommand1);
+ response = solrClient.request(req);
+ assertEquals(response.get("result").toString(), "success");
+
+ listenerEvents.clear();
+ failDummyAction = false;
+
+ JettySolrRunner newNode = cluster.startJettySolrRunner();
+ boolean await = triggerFiredLatch.await(20, TimeUnit.SECONDS);
+ assertTrue("The trigger did not fire at all", await);
+ assertTrue(triggerFired.get());
+
+ assertEquals("both listeners should have fired", 2, listenerEvents.size());
+
+ Thread.sleep(2000);
+
+ // check foo events
+ List<TestEvent> testEvents = listenerEvents.get("foo");
+ assertNotNull("foo events: " + testEvents, testEvents);
+ assertEquals("foo events: " + testEvents, 5, testEvents.size());
+
+ assertEquals(AutoScaling.EventProcessorStage.STARTED, testEvents.get(0).stage);
+
+ assertEquals(AutoScaling.EventProcessorStage.BEFORE_ACTION, testEvents.get(1).stage);
+ assertEquals("test", testEvents.get(1).actionName);
+
+ assertEquals(AutoScaling.EventProcessorStage.AFTER_ACTION, testEvents.get(2).stage);
+ assertEquals("test", testEvents.get(2).actionName);
+
+ assertEquals(AutoScaling.EventProcessorStage.AFTER_ACTION, testEvents.get(3).stage);
+ assertEquals("test1", testEvents.get(3).actionName);
+
+ assertEquals(AutoScaling.EventProcessorStage.SUCCEEDED, testEvents.get(4).stage);
+
+ // check bar events
+ testEvents = listenerEvents.get("bar");
+ assertNotNull("bar events", testEvents);
+ assertEquals("bar events", 4, testEvents.size());
+
+ assertEquals(AutoScaling.EventProcessorStage.BEFORE_ACTION, testEvents.get(0).stage);
+ assertEquals("test", testEvents.get(0).actionName);
+
+ assertEquals(AutoScaling.EventProcessorStage.AFTER_ACTION, testEvents.get(1).stage);
+ assertEquals("test", testEvents.get(1).actionName);
+
+ assertEquals(AutoScaling.EventProcessorStage.BEFORE_ACTION, testEvents.get(2).stage);
+ assertEquals("test1", testEvents.get(2).actionName);
+
+ assertEquals(AutoScaling.EventProcessorStage.SUCCEEDED, testEvents.get(3).stage);
+
+ // reset
+ triggerFired.set(false);
+ triggerFiredLatch = new CountDownLatch(1);
+ listenerEvents.clear();
+ failDummyAction = true;
+
+ newNode = cluster.startJettySolrRunner();
+ await = triggerFiredLatch.await(20, TimeUnit.SECONDS);
+ assertTrue("The trigger did not fire at all", await);
+
+ Thread.sleep(2000);
+
+ // check foo events
+ testEvents = listenerEvents.get("foo");
+ assertNotNull("foo events: " + testEvents, testEvents);
+ assertEquals("foo events: " + testEvents, 4, testEvents.size());
+
+ assertEquals(AutoScaling.EventProcessorStage.STARTED, testEvents.get(0).stage);
+
+ assertEquals(AutoScaling.EventProcessorStage.BEFORE_ACTION, testEvents.get(1).stage);
+ assertEquals("test", testEvents.get(1).actionName);
+
+ assertEquals(AutoScaling.EventProcessorStage.AFTER_ACTION, testEvents.get(2).stage);
+ assertEquals("test", testEvents.get(2).actionName);
+
+ assertEquals(AutoScaling.EventProcessorStage.FAILED, testEvents.get(3).stage);
+ assertEquals("test1", testEvents.get(3).actionName);
+
+ // check bar events
+ testEvents = listenerEvents.get("bar");
+ assertNotNull("bar events", testEvents);
+ assertEquals("bar events", 4, testEvents.size());
+
+ assertEquals(AutoScaling.EventProcessorStage.BEFORE_ACTION, testEvents.get(0).stage);
+ assertEquals("test", testEvents.get(0).actionName);
+
+ assertEquals(AutoScaling.EventProcessorStage.AFTER_ACTION, testEvents.get(1).stage);
+ assertEquals("test", testEvents.get(1).actionName);
+
+ assertEquals(AutoScaling.EventProcessorStage.BEFORE_ACTION, testEvents.get(2).stage);
+ assertEquals("test1", testEvents.get(2).actionName);
+
+ assertEquals(AutoScaling.EventProcessorStage.FAILED, testEvents.get(3).stage);
+ assertEquals("test1", testEvents.get(3).actionName);
+ }
}