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);
       }