You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by no...@apache.org on 2020/09/18 02:13:47 UTC
[lucene-solr] branch master updated: SOLR-14875: Make
SolrEventListeners load from packages (#1887)
This is an automated email from the ASF dual-hosted git repository.
noble pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/lucene-solr.git
The following commit(s) were added to refs/heads/master by this push:
new ee0a374 SOLR-14875: Make SolrEventListeners load from packages (#1887)
ee0a374 is described below
commit ee0a374bb8389282341e49cda195d5630c81e8e5
Author: Noble Paul <no...@users.noreply.github.com>
AuthorDate: Fri Sep 18 12:07:29 2020 +1000
SOLR-14875: Make SolrEventListeners load from packages (#1887)
---
solr/CHANGES.txt | 2 +
.../apache/solr/core/DelegatingEventListener.java | 55 ++++++++++++++++++++++
.../src/java/org/apache/solr/core/PluginBag.java | 7 ++-
.../src/java/org/apache/solr/core/SolrCore.java | 47 ++++++++++++++++--
.../org/apache/solr/handler/StreamHandler.java | 2 +-
.../org/apache/solr/pkg/PackagePluginHolder.java | 18 +++----
.../java/org/apache/solr/update/UpdateHandler.java | 6 +--
7 files changed, 117 insertions(+), 20 deletions(-)
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index afdc6cf..97c2ad2 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -150,6 +150,8 @@ New Features
* SOLR-13751: Add BooleanSimilarityFactory class. (Andy Webb via Christine Poerschke)
+* SOLR-14875: Make SolrEventListeners load from packages (noble)
+
Improvements
---------------------
diff --git a/solr/core/src/java/org/apache/solr/core/DelegatingEventListener.java b/solr/core/src/java/org/apache/solr/core/DelegatingEventListener.java
new file mode 100644
index 0000000..eafd52a
--- /dev/null
+++ b/solr/core/src/java/org/apache/solr/core/DelegatingEventListener.java
@@ -0,0 +1,55 @@
+/*
+ * 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.core;
+
+import org.apache.solr.common.util.NamedList;
+import org.apache.solr.pkg.PackagePluginHolder;
+import org.apache.solr.search.SolrIndexSearcher;
+
+/**
+ * A {@link SolrEventListener} wrapper that loads class from a package
+ * and reload if it's modified
+ */
+public class DelegatingEventListener implements SolrEventListener {
+
+ private final PackagePluginHolder<SolrEventListener> holder;
+
+ public DelegatingEventListener(PackagePluginHolder<SolrEventListener> holder) {
+ this.holder = holder;
+ }
+
+
+ @Override
+ public void postCommit() {
+ holder.getInstance().ifPresent(SolrEventListener::postCommit);
+ }
+
+ @Override
+ public void postSoftCommit() {
+ holder.getInstance().ifPresent(SolrEventListener::postSoftCommit);
+ }
+
+ @Override
+ public void newSearcher(SolrIndexSearcher newSearcher, SolrIndexSearcher currentSearcher) {
+ holder.getInstance().ifPresent(it -> it.newSearcher(newSearcher, currentSearcher));
+ }
+
+ @Override
+ public void init(@SuppressWarnings({"rawtypes"})NamedList args) {
+
+ }
+}
diff --git a/solr/core/src/java/org/apache/solr/core/PluginBag.java b/solr/core/src/java/org/apache/solr/core/PluginBag.java
index e868ada..1708005 100644
--- a/solr/core/src/java/org/apache/solr/core/PluginBag.java
+++ b/solr/core/src/java/org/apache/solr/core/PluginBag.java
@@ -24,6 +24,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Supplier;
@@ -342,7 +343,7 @@ public class PluginBag<T> implements AutoCloseable {
* subclasses may choose to lazily load the plugin
*/
public static class PluginHolder<T> implements Supplier<T>, AutoCloseable {
- protected T inst;
+ protected volatile T inst;
protected final PluginInfo pluginInfo;
boolean registerAPI = false;
@@ -359,6 +360,10 @@ public class PluginBag<T> implements AutoCloseable {
this.pluginInfo = info;
}
+ public Optional<T> getInstance() {
+ return Optional.ofNullable(inst);
+ }
+
public T get() {
return inst;
}
diff --git a/solr/core/src/java/org/apache/solr/core/SolrCore.java b/solr/core/src/java/org/apache/solr/core/SolrCore.java
index f3e0408..955635a 100644
--- a/solr/core/src/java/org/apache/solr/core/SolrCore.java
+++ b/solr/core/src/java/org/apache/solr/core/SolrCore.java
@@ -57,6 +57,7 @@ import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;
+import java.util.function.Consumer;
import com.codahale.metrics.Counter;
import com.codahale.metrics.Timer;
@@ -111,7 +112,9 @@ import org.apache.solr.logging.MDCLoggingContext;
import org.apache.solr.metrics.SolrCoreMetricManager;
import org.apache.solr.metrics.SolrMetricProducer;
import org.apache.solr.metrics.SolrMetricsContext;
-import org.apache.solr.pkg.*;
+import org.apache.solr.pkg.PackageListeners;
+import org.apache.solr.pkg.PackageLoader;
+import org.apache.solr.pkg.PackagePluginHolder;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.request.SolrRequestHandler;
import org.apache.solr.response.BinaryResponseWriter;
@@ -278,6 +281,8 @@ public final class SolrCore implements SolrInfoBean, Closeable {
private ExecutorService coreAsyncTaskExecutor = ExecutorUtil.newMDCAwareCachedThreadPool("Core Async Task");
+ public final SolrCore.Provider coreProvider;
+
/**
* The SolrResourceLoader used to load all resources for this core.
*
@@ -632,22 +637,29 @@ public final class SolrCore implements SolrInfoBean, Closeable {
private void initListeners() {
- final Class<SolrEventListener> clazz = SolrEventListener.class;
- final String label = "Event Listener";
for (PluginInfo info : solrConfig.getPluginInfos(SolrEventListener.class.getName())) {
final String event = info.attributes.get("event");
if ("firstSearcher".equals(event)) {
- SolrEventListener obj = createInitInstance(info, clazz, label, null);
+ SolrEventListener obj = createEventListener(info);
firstSearcherListeners.add(obj);
log.debug("[{}] Added SolrEventListener for firstSearcher: [{}]", logid, obj);
} else if ("newSearcher".equals(event)) {
- SolrEventListener obj = createInitInstance(info, clazz, label, null);
+ SolrEventListener obj = createEventListener(info);
newSearcherListeners.add(obj);
log.debug("[{}] Added SolrEventListener for newSearcher: [{}]", logid, obj);
}
}
}
+ public SolrEventListener createEventListener(PluginInfo info) {
+ final String label = "Event Listener";
+ if(info.pkgName == null) {
+ return createInitInstance(info, SolrEventListener.class, label, null);
+ } else {
+ return new DelegatingEventListener(new PackagePluginHolder<>(info, this, SolrConfig.classVsSolrPluginInfo.get(SolrEventListener.class.getName())));
+ }
+ }
+
final List<SolrEventListener> firstSearcherListeners = new ArrayList<>();
final List<SolrEventListener> newSearcherListeners = new ArrayList<>();
@@ -939,6 +951,7 @@ public final class SolrCore implements SolrInfoBean, Closeable {
this.configSet = configSet;
this.coreDescriptor = Objects.requireNonNull(coreDescriptor, "coreDescriptor cannot be null");
setName(coreDescriptor.getName());
+ coreProvider = new Provider(coreContainer, getName(), uniqueId);
this.solrConfig = configSet.getSolrConfig();
this.resourceLoader = configSet.getSolrConfig().getResourceLoader();
@@ -3245,4 +3258,28 @@ public final class SolrCore implements SolrInfoBean, Closeable {
public void runAsync(Runnable r) {
coreAsyncTaskExecutor.submit(r);
}
+
+ /**Provides the core instance if the core instance is still alive.
+ * This helps to not hold on to a live {@link SolrCore} instance
+ * even after it's unloaded
+ *
+ */
+ public static class Provider {
+ private final CoreContainer coreContainer;
+ private final String coreName;
+ private final UUID coreId;
+
+ public Provider(CoreContainer coreContainer, String coreName, UUID coreId) {
+ this.coreContainer = coreContainer;
+ this.coreName = coreName;
+ this.coreId = coreId;
+ }
+
+ public void withCore(Consumer<SolrCore> r) {
+ try(SolrCore core = coreContainer.getCore(coreName, coreId)) {
+ if(core == null) return;
+ r.accept(core);
+ }
+ }
+ }
}
diff --git a/solr/core/src/java/org/apache/solr/handler/StreamHandler.java b/solr/core/src/java/org/apache/solr/handler/StreamHandler.java
index 0877c54..5b9cb27 100644
--- a/solr/core/src/java/org/apache/solr/handler/StreamHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/StreamHandler.java
@@ -158,7 +158,7 @@ public class StreamHandler extends RequestHandlerBase implements SolrCoreAware,
}
@Override
- protected Object initNewInstance(PackageLoader.Package.Version newest) {
+ protected Object initNewInstance(PackageLoader.Package.Version newest, SolrCore core) {
return clazz = newest.getLoader().findClass(pluginInfo.className, Expressible.class);
}
diff --git a/solr/core/src/java/org/apache/solr/pkg/PackagePluginHolder.java b/solr/core/src/java/org/apache/solr/pkg/PackagePluginHolder.java
index 0c6fd80..3a2bf4d 100644
--- a/solr/core/src/java/org/apache/solr/pkg/PackagePluginHolder.java
+++ b/solr/core/src/java/org/apache/solr/pkg/PackagePluginHolder.java
@@ -37,7 +37,7 @@ public class PackagePluginHolder<T> extends PluginBag.PluginHolder<T> {
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
public static final String LATEST = "$LATEST";
- private final SolrCore core;
+ private final SolrCore.Provider coreProvider;
private final SolrConfig.SolrPluginInfo pluginMeta;
private PackageLoader.Package.Version pkgVersion;
private PluginInfo info;
@@ -45,11 +45,11 @@ public class PackagePluginHolder<T> extends PluginBag.PluginHolder<T> {
public PackagePluginHolder(PluginInfo info, SolrCore core, SolrConfig.SolrPluginInfo pluginMeta) {
super(info);
- this.core = core;
+ this.coreProvider = core.coreProvider;
this.pluginMeta = pluginMeta;
this.info = info;
- reload(core.getCoreContainer().getPackageLoader().getPackage(info.pkgName));
+ reload(core.getCoreContainer().getPackageLoader().getPackage(info.pkgName), core);
core.getPackageListeners().addListener(new PackageListeners.Listener() {
@Override
public String packageName() {
@@ -63,7 +63,7 @@ public class PackagePluginHolder<T> extends PluginBag.PluginHolder<T> {
@Override
public void changed(PackageLoader.Package pkg, Ctx ctx) {
- reload(pkg);
+ coreProvider.withCore(c -> reload(pkg, c));
}
@@ -83,7 +83,7 @@ public class PackagePluginHolder<T> extends PluginBag.PluginHolder<T> {
}
}
- private synchronized void reload(PackageLoader.Package pkg) {
+ private synchronized void reload(PackageLoader.Package pkg, SolrCore core) {
String lessThan = core.getSolrConfig().maxPackageVersion(info.pkgName);
PackageLoader.Package.Version newest = pkg.getLatest(lessThan);
if (newest == null) {
@@ -111,17 +111,17 @@ public class PackagePluginHolder<T> extends PluginBag.PluginHolder<T> {
pluginInfo.type, pluginInfo.name, pkg.name(), newest.getVersion());
}
- initNewInstance(newest);
+ initNewInstance(newest, core);
pkgVersion = newest;
}
@SuppressWarnings({"unchecked"})
- protected Object initNewInstance(PackageLoader.Package.Version newest) {
+ protected Object initNewInstance(PackageLoader.Package.Version newest, SolrCore core) {
Object instance = SolrCore.createInstance(pluginInfo.className,
pluginMeta.clazz, pluginMeta.getCleanTag(), core, newest.getLoader());
PluginBag.initInstance(instance, pluginInfo);
- handleAwareCallbacks(newest.getLoader(), instance);
+ handleAwareCallbacks(newest.getLoader(), instance, core);
T old = inst;
inst = (T) instance;
if (old instanceof AutoCloseable) {
@@ -135,7 +135,7 @@ public class PackagePluginHolder<T> extends PluginBag.PluginHolder<T> {
return inst;
}
- private void handleAwareCallbacks(SolrResourceLoader loader, Object instance) {
+ private void handleAwareCallbacks(SolrResourceLoader loader, Object instance, SolrCore core) {
if (instance instanceof SolrCoreAware) {
SolrCoreAware coreAware = (SolrCoreAware) instance;
if (!core.getResourceLoader().addToCoreAware(coreAware)) {
diff --git a/solr/core/src/java/org/apache/solr/update/UpdateHandler.java b/solr/core/src/java/org/apache/solr/update/UpdateHandler.java
index 37397f7..14b78af 100644
--- a/solr/core/src/java/org/apache/solr/update/UpdateHandler.java
+++ b/solr/core/src/java/org/apache/solr/update/UpdateHandler.java
@@ -57,16 +57,14 @@ public abstract class UpdateHandler implements SolrInfoBean {
protected SolrMetricsContext solrMetricsContext;
private void parseEventListeners() {
- final Class<SolrEventListener> clazz = SolrEventListener.class;
- final String label = "Event Listener";
for (PluginInfo info : core.getSolrConfig().getPluginInfos(SolrEventListener.class.getName())) {
String event = info.attributes.get("event");
if ("postCommit".equals(event)) {
- SolrEventListener obj = core.createInitInstance(info,clazz,label,null);
+ SolrEventListener obj = core.createEventListener(info);
commitCallbacks.add(obj);
log.info("added SolrEventListener for postCommit: {}", obj);
} else if ("postOptimize".equals(event)) {
- SolrEventListener obj = core.createInitInstance(info,clazz,label,null);
+ SolrEventListener obj = core.createEventListener(info);
optimizeCallbacks.add(obj);
log.info("added SolrEventListener for postOptimize: {}", obj);
}