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 2021/01/13 12:16:07 UTC
[lucene-solr] branch branch_8x updated: porting changes
This is an automated email from the ASF dual-hosted git repository.
noble pushed a commit to branch branch_8x
in repository https://gitbox.apache.org/repos/asf/lucene-solr.git
The following commit(s) were added to refs/heads/branch_8x by this push:
new 624d4ba porting changes
624d4ba is described below
commit 624d4baa913c69eb9acf340b7cf7f1948b976d73
Author: noblepaul <no...@gmail.com>
AuthorDate: Wed Jan 13 23:13:02 2021 +1100
porting changes
---
solr/CHANGES.txt | 2 +
.../org/apache/solr/core/DirectoryFactory.java | 2 +-
.../src/java/org/apache/solr/core/PluginBag.java | 1 -
.../src/java/org/apache/solr/core/SolrCore.java | 46 +++++++--
.../org/apache/solr/core/SolrResourceLoader.java | 114 ++++++++++++++++-----
.../org/apache/solr/handler/SolrConfigHandler.java | 29 +++---
.../solr/handler/component/SearchHandler.java | 26 ++---
.../java/org/apache/solr/pkg/PackageListeners.java | 15 ++-
.../solr/pkg/PackageListeningClassLoader.java | 73 ++++++++-----
.../org/apache/solr/pkg/PackagePluginHolder.java | 16 ++-
.../java/org/apache/solr/search/CacheConfig.java | 42 ++++++--
.../java/org/apache/solr/update/UpdateHandler.java | 6 +-
.../solr/configsets/conf2/conf/schema.xml | 43 ++++++++
.../solr/configsets/conf2/conf/solrconfig.xml | 68 ++++++++++++
.../src/test/org/apache/solr/pkg/TestPackages.java | 81 +++++++++++++--
15 files changed, 449 insertions(+), 115 deletions(-)
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index e02e5ae..8e3201f 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -86,6 +86,8 @@ Improvements
* SOLR-15040: Improvements to postlogs timestamp handling (Joel Bernstein)
+* SOLR-14155: Load all other SolrCore plugins from packages (noble)
+
Optimizations
---------------------
* SOLR-14975: Optimize CoreContainer.getAllCoreNames, getLoadedCoreNames and getCoreDescriptors. (Bruno Roustant)
diff --git a/solr/core/src/java/org/apache/solr/core/DirectoryFactory.java b/solr/core/src/java/org/apache/solr/core/DirectoryFactory.java
index 5736692..619e7c9 100644
--- a/solr/core/src/java/org/apache/solr/core/DirectoryFactory.java
+++ b/solr/core/src/java/org/apache/solr/core/DirectoryFactory.java
@@ -419,7 +419,7 @@ public abstract class DirectoryFactory implements NamedListInitializedPlugin,
final DirectoryFactory dirFactory;
if (info != null) {
log.debug(info.className);
- dirFactory = config.getResourceLoader().newInstance(info.className, DirectoryFactory.class);
+ dirFactory = config.getResourceLoader().newInstance (info, DirectoryFactory.class, true);
// allow DirectoryFactory instances to access the CoreContainer
dirFactory.initCoreContainer(cc);
dirFactory.init(info.initArgs);
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 d2442a1..b7c07f7 100644
--- a/solr/core/src/java/org/apache/solr/core/PluginBag.java
+++ b/solr/core/src/java/org/apache/solr/core/PluginBag.java
@@ -413,7 +413,6 @@ public class PluginBag<T> implements AutoCloseable {
if (pluginInfo != null) return pluginInfo.className;
return null;
}
-
public PluginInfo getPluginInfo() {
return pluginInfo;
}
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 bde2fd5..7ac37f8 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.MetricRegistry;
@@ -280,6 +281,8 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab
private ExecutorService coreAsyncTaskExecutor = ExecutorUtil.newMDCAwareCachedThreadPool("Core Async Task");
+ public final SolrCore.Provider coreProvider;
+
/**
* The SolrResourceLoader used to load all resources for this core.
*
@@ -745,7 +748,7 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab
IndexReaderFactory indexReaderFactory;
PluginInfo info = solrConfig.getPluginInfo(IndexReaderFactory.class.getName());
if (info != null) {
- indexReaderFactory = resourceLoader.newInstance(info.className, IndexReaderFactory.class);
+ indexReaderFactory = resourceLoader.newInstance(info, IndexReaderFactory.class, true);
indexReaderFactory.init(info.initArgs);
} else {
indexReaderFactory = new StandardIndexReaderFactory();
@@ -941,9 +944,11 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab
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();
+ this.resourceLoader.initCore(this);
IndexSchema schema = configSet.getIndexSchema();
this.configSetProperties = configSet.getProperties();
@@ -1247,7 +1252,7 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab
private void checkVersionFieldExistsInSchema(IndexSchema schema, CoreDescriptor coreDescriptor) {
if (null != coreDescriptor.getCloudDescriptor()) {
- // we are evidently running in cloud mode.
+ // we are evidently running in cloud mode.
//
// In cloud mode, version field is required for correct consistency
// ideally this check would be more fine grained, and individual features
@@ -1411,7 +1416,7 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab
final PluginInfo info = solrConfig.getPluginInfo(CodecFactory.class.getName());
final CodecFactory factory;
if (info != null) {
- factory = resourceLoader.newInstance(info.className, CodecFactory.class);
+ factory = resourceLoader.newInstance( info, CodecFactory.class, true);
factory.init(info.initArgs);
} else {
factory = new CodecFactory() {
@@ -1449,8 +1454,8 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab
final StatsCache cache;
PluginInfo pluginInfo = solrConfig.getPluginInfo(StatsCache.class.getName());
if (pluginInfo != null && pluginInfo.className != null && pluginInfo.className.length() > 0) {
- cache = createInitInstance(pluginInfo, StatsCache.class, null,
- LocalStatsCache.class.getName());
+ cache = resourceLoader.newInstance( pluginInfo, StatsCache.class, true);
+ initPlugin(pluginInfo ,cache);
if (log.isDebugEnabled()) {
log.debug("Using statsCache impl: {}", cache.getClass().getName());
}
@@ -2159,7 +2164,7 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab
newReader = currentReader;
}
- // for now, turn off caches if this is for a realtime reader
+ // for now, turn off caches if this is for a realtime reader
// (caches take a little while to instantiate)
final boolean useCaches = !realtime;
final String newName = realtime ? "realtime" : "main";
@@ -3212,7 +3217,7 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab
public void cleanupOldIndexDirectories(boolean reload) {
final DirectoryFactory myDirFactory = getDirectoryFactory();
final String myDataDir = getDataDir();
- final String myIndexDir = getNewIndexDir(); // ensure the latest replicated index is protected
+ final String myIndexDir = getNewIndexDir(); // ensure the latest replicated index is protected
final String coreName = getName();
if (myDirFactory != null && myDataDir != null && myIndexDir != null) {
Thread cleanupThread = new Thread(() -> {
@@ -3299,4 +3304,31 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab
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 reload() {
+ coreContainer.reload(coreName, 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/core/SolrResourceLoader.java b/solr/core/src/java/org/apache/solr/core/SolrResourceLoader.java
index 17d0132..b58c8d9 100644
--- a/solr/core/src/java/org/apache/solr/core/SolrResourceLoader.java
+++ b/solr/core/src/java/org/apache/solr/core/SolrResourceLoader.java
@@ -31,6 +31,7 @@ import java.nio.file.Path;
import java.nio.file.PathMatcher;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@@ -48,6 +49,7 @@ import org.apache.solr.handler.component.SearchComponent;
import org.apache.solr.handler.component.ShardHandlerFactory;
import org.apache.solr.logging.DeprecationLog;
import org.apache.solr.pkg.PackageListeningClassLoader;
+import org.apache.solr.pkg.PackageLoader;
import org.apache.solr.request.SolrRequestHandler;
import org.apache.solr.response.QueryResponseWriter;
import org.apache.solr.rest.RestManager;
@@ -86,6 +88,7 @@ public class SolrResourceLoader implements ResourceLoader, Closeable, SolrClassL
private CoreContainer coreContainer;
private PackageListeningClassLoader schemaLoader ;
+ private PackageListeningClassLoader coreReloadingClassLoader ;
private final List<SolrCoreAware> waitingForCore = Collections.synchronizedList(new ArrayList<SolrCoreAware>());
private final List<SolrInfoBean> infoMBeans = Collections.synchronizedList(new ArrayList<SolrInfoBean>());
private final List<ResourceLoaderAware> waitingForResources = Collections.synchronizedList(new ArrayList<ResourceLoaderAware>());
@@ -452,7 +455,7 @@ public class SolrResourceLoader implements ResourceLoader, Closeable, SolrClassL
* @throws IOException If there is a low-level I/O error.
*/
public List<String> getLines(String resource,
- String encoding) throws IOException {
+ String encoding) throws IOException {
return getLines(resource, Charset.forName(encoding));
}
@@ -462,7 +465,7 @@ public class SolrResourceLoader implements ResourceLoader, Closeable, SolrClassL
return WordlistLoader.getLines(openResource(resource), charset);
} catch (CharacterCodingException ex) {
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
- "Error loading resource (wrong encoding?): " + resource, ex);
+ "Error loading resource (wrong encoding?): " + resource, ex);
}
}
@@ -556,8 +559,8 @@ public class SolrResourceLoader implements ResourceLoader, Closeable, SolrClassL
//cache the shortname vs FQN if it is loaded by the webapp classloader and it is loaded
// using a shortname
if (clazz.getClassLoader() == SolrResourceLoader.class.getClassLoader() &&
- !cname.equals(clazz.getName()) &&
- (subpackages.length == 0 || subpackages == packages)) {
+ !cname.equals(clazz.getName()) &&
+ (subpackages.length == 0 || subpackages == packages)) {
//store in the cache
classNameCache.put(cname, clazz.getName());
}
@@ -565,7 +568,7 @@ public class SolrResourceLoader implements ResourceLoader, Closeable, SolrClassL
// print warning if class is deprecated
if (clazz.isAnnotationPresent(Deprecated.class)) {
DeprecationLog.log(cname,
- "Solr loaded a deprecated plugin/analysis class [" + cname + "]. Please consult documentation how to replace it accordingly.");
+ "Solr loaded a deprecated plugin/analysis class [" + cname + "]. Please consult documentation how to replace it accordingly.");
}
}
}
@@ -682,6 +685,24 @@ public class SolrResourceLoader implements ResourceLoader, Closeable, SolrClassL
}
}
+ void initCore(SolrCore core) {
+ this.coreName = core.getName();
+ this.config = core.getSolrConfig();
+ this.coreId = core.uniqueId;
+ this.coreContainer = core.getCoreContainer();
+ SolrCore.Provider coreProvider = core.coreProvider;
+
+ this.coreReloadingClassLoader = new PackageListeningClassLoader(core.getCoreContainer(),
+ this, s -> config.maxPackageVersion(s), null){
+ @Override
+ protected void doReloadAction(Ctx ctx) {
+ log.info("Core reloading classloader issued reload for: {}/{} ", coreName, coreId);
+ coreProvider.reload();
+ }
+ };
+ core.getPackageListeners().addListener(coreReloadingClassLoader, true);
+
+ }
/**
* Tell all {@link SolrCoreAware} instances about the SolrCore
@@ -720,7 +741,7 @@ public class SolrResourceLoader implements ResourceLoader, Closeable, SolrClassL
public void inform( ResourceLoader loader ) throws IOException
{
- // make a copy to avoid potential deadlock of a callback adding to the list
+ // make a copy to avoid potential deadlock of a callback adding to the list
ResourceLoaderAware[] arr;
while (waitingForResources.size() > 0) {
@@ -801,30 +822,30 @@ public class SolrResourceLoader implements ResourceLoader, Closeable, SolrClassL
awareCompatibility = new HashMap<>();
awareCompatibility.put(
SolrCoreAware.class, new Class<?>[]{
- // DO NOT ADD THINGS TO THIS LIST -- ESPECIALLY THINGS THAT CAN BE CREATED DYNAMICALLY
- // VIA RUNTIME APIS -- UNTILL CAREFULLY CONSIDERING THE ISSUES MENTIONED IN SOLR-8311
- CodecFactory.class,
- DirectoryFactory.class,
- ManagedIndexSchemaFactory.class,
- QueryResponseWriter.class,
- SearchComponent.class,
- ShardHandlerFactory.class,
- SimilarityFactory.class,
- SolrRequestHandler.class,
- UpdateRequestProcessorFactory.class
- }
+ // DO NOT ADD THINGS TO THIS LIST -- ESPECIALLY THINGS THAT CAN BE CREATED DYNAMICALLY
+ // VIA RUNTIME APIS -- UNTILL CAREFULLY CONSIDERING THE ISSUES MENTIONED IN SOLR-8311
+ CodecFactory.class,
+ DirectoryFactory.class,
+ ManagedIndexSchemaFactory.class,
+ QueryResponseWriter.class,
+ SearchComponent.class,
+ ShardHandlerFactory.class,
+ SimilarityFactory.class,
+ SolrRequestHandler.class,
+ UpdateRequestProcessorFactory.class
+ }
);
awareCompatibility.put(
ResourceLoaderAware.class, new Class<?>[]{
- // DO NOT ADD THINGS TO THIS LIST -- ESPECIALLY THINGS THAT CAN BE CREATED DYNAMICALLY
- // VIA RUNTIME APIS -- UNTILL CAREFULLY CONSIDERING THE ISSUES MENTIONED IN SOLR-8311
- CharFilterFactory.class,
- TokenFilterFactory.class,
- TokenizerFactory.class,
- QParserPlugin.class,
- FieldType.class
- }
+ // DO NOT ADD THINGS TO THIS LIST -- ESPECIALLY THINGS THAT CAN BE CREATED DYNAMICALLY
+ // VIA RUNTIME APIS -- UNTILL CAREFULLY CONSIDERING THE ISSUES MENTIONED IN SOLR-8311
+ CharFilterFactory.class,
+ TokenFilterFactory.class,
+ TokenizerFactory.class,
+ QParserPlugin.class,
+ FieldType.class
+ }
);
}
@@ -878,6 +899,47 @@ public class SolrResourceLoader implements ResourceLoader, Closeable, SolrClassL
public List<SolrInfoBean> getInfoMBeans(){
return Collections.unmodifiableList(infoMBeans);
}
+ /**
+ * Load a class using an appropriate {@link SolrResourceLoader} depending of the package on that class
+ * @param registerCoreReloadListener register a listener for the package and reload the core if the package is changed.
+ * Use this sparingly. This will result in core reloads across all the cores in
+ * all collections using this configset
+ */
+ public <T> Class<? extends T> findClass( PluginInfo info, Class<T> type, boolean registerCoreReloadListener) {
+ if(info.cName.pkg == null) return findClass(info.className, type);
+ return _classLookup(info,
+ (Function<PackageLoader.Package.Version, Class<? extends T>>) ver -> ver.getLoader().findClass(info.cName.className, type), registerCoreReloadListener);
+
+ }
+
+
+ private <T> T _classLookup(PluginInfo info, Function<PackageLoader.Package.Version, T> fun, boolean registerCoreReloadListener ) {
+ PluginInfo.ClassName cName = info.cName;
+ if (registerCoreReloadListener) {
+ if (coreReloadingClassLoader == null) {
+ throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Core not set");
+ }
+ return fun.apply(coreReloadingClassLoader.findPackageVersion(cName, true));
+ } else {
+ return fun.apply(coreReloadingClassLoader.findPackageVersion(cName, false));
+ }
+ }
+
+ /**
+ *Create a n instance of a class using an appropriate {@link SolrResourceLoader} depending on the package of that class
+ * @param registerCoreReloadListener register a listener for the package and reload the core if the package is changed.
+ * Use this sparingly. This will result in core reloads across all the cores in
+ * all collections using this configset
+ */
+ public <T> T newInstance(PluginInfo info, Class<T> type, boolean registerCoreReloadListener) {
+ if(info.cName.pkg == null) {
+ return newInstance(info.cName.className == null?
+ type.getName():
+ info.cName.className ,
+ type);
+ }
+ return _classLookup( info, version -> version.getLoader().newInstance(info.cName.className, type), registerCoreReloadListener);
+ }
private PackageListeningClassLoader createSchemaLoader() {
CoreContainer cc = getCoreContainer();
diff --git a/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java b/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java
index 7f48b63..03579c6 100644
--- a/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java
@@ -48,6 +48,7 @@ import org.apache.solr.client.solrj.impl.HttpSolrClient;
import org.apache.solr.client.solrj.io.stream.expr.Expressible;
import org.apache.solr.cloud.ZkController;
import org.apache.solr.cloud.ZkSolrResourceLoader;
+import org.apache.solr.common.MapSerializable;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.cloud.ClusterState;
import org.apache.solr.common.cloud.DocCollection;
@@ -70,6 +71,7 @@ import org.apache.solr.core.RequestParams;
import org.apache.solr.core.SolrConfig;
import org.apache.solr.core.SolrCore;
import org.apache.solr.core.SolrResourceLoader;
+import org.apache.solr.pkg.PackageAPI;
import org.apache.solr.pkg.PackageListeners;
import org.apache.solr.request.LocalSolrQueryRequest;
import org.apache.solr.request.SolrQueryRequest;
@@ -251,25 +253,28 @@ public class SolrConfigHandler extends RequestHandlerBase implements SolrCoreAwa
String componentName = req.getParams().get("componentName");
if (componentName != null) {
@SuppressWarnings({"rawtypes"})
- Map map = (Map) val.get(parts.get(1));
- if (map != null) {
- Object o = map.get(componentName);
- val.put(parts.get(1), makeMap(componentName, o));
+ Map pluginNameVsPluginInfo = (Map) val.get(parts.get(1));
+ if (pluginNameVsPluginInfo != null) {
+ @SuppressWarnings({"rawtypes"})
+ Object o = pluginNameVsPluginInfo instanceof MapSerializable ?
+ pluginNameVsPluginInfo:
+ pluginNameVsPluginInfo.get(componentName);
+ @SuppressWarnings({"rawtypes"})
+ Map pluginInfo = o instanceof MapSerializable? ((MapSerializable) o).toMap(new LinkedHashMap<>()): (Map) o;
+ val.put(parts.get(1),pluginNameVsPluginInfo instanceof PluginInfo? pluginInfo : makeMap(componentName, pluginInfo));
if (req.getParams().getBool("meta", false)) {
// meta=true is asking for the package info of the plugin
// We go through all the listeners and see if there is one registered for this plugin
List<PackageListeners.Listener> listeners = req.getCore().getPackageListeners().getListeners();
for (PackageListeners.Listener listener :
listeners) {
- PluginInfo info = listener.pluginInfo();
- if(info == null) continue;
- if (info.type.equals(parts.get(1)) && info.name.equals(componentName)) {
- if (o instanceof Map) {
- @SuppressWarnings({"rawtypes"})
- Map m1 = (Map) o;
- m1.put("_packageinfo_", listener.getPackageVersion(info.cName));
+ Map<String, PackageAPI.PkgVersion> infos = listener.packageDetails();
+ if(infos == null || infos.isEmpty()) continue;
+ infos.forEach((s, mapWriter) -> {
+ if(s.equals(pluginInfo.get("class"))) {
+ (pluginInfo).put("_packageinfo_", mapWriter);
}
- }
+ });
}
}
}
diff --git a/solr/core/src/java/org/apache/solr/handler/component/SearchHandler.java b/solr/core/src/java/org/apache/solr/handler/component/SearchHandler.java
index f5c2474..c0c536f 100644
--- a/solr/core/src/java/org/apache/solr/handler/component/SearchHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/component/SearchHandler.java
@@ -16,16 +16,6 @@
*/
package org.apache.solr.handler.component;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.lang.invoke.MethodHandles;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.atomic.AtomicLong;
-
import org.apache.commons.lang3.StringUtils;
import org.apache.lucene.index.ExitableDirectoryReader;
import org.apache.lucene.search.TotalHits;
@@ -44,6 +34,7 @@ import org.apache.solr.core.CoreContainer;
import org.apache.solr.core.PluginInfo;
import org.apache.solr.core.SolrCore;
import org.apache.solr.handler.RequestHandlerBase;
+import org.apache.solr.pkg.PackageAPI;
import org.apache.solr.pkg.PackageListeners;
import org.apache.solr.pkg.PackageLoader;
import org.apache.solr.request.SolrQueryRequest;
@@ -61,10 +52,13 @@ import org.apache.solr.util.plugin.SolrCoreAware;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import static org.apache.solr.common.params.CommonParams.DISTRIB;
-import static org.apache.solr.common.params.CommonParams.FAILURE;
-import static org.apache.solr.common.params.CommonParams.PATH;
-import static org.apache.solr.common.params.CommonParams.STATUS;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.lang.invoke.MethodHandles;
+import java.util.*;
+import java.util.concurrent.atomic.AtomicLong;
+
+import static org.apache.solr.common.params.CommonParams.*;
/**
@@ -162,8 +156,8 @@ public class SearchHandler extends RequestHandlerBase implements SolrCoreAware,
}
@Override
- public PluginInfo pluginInfo() {
- return null;
+ public Map<String , PackageAPI.PkgVersion> packageDetails() {
+ return Collections.emptyMap();
}
@Override
diff --git a/solr/core/src/java/org/apache/solr/pkg/PackageListeners.java b/solr/core/src/java/org/apache/solr/pkg/PackageListeners.java
index 1895b6d..1281d99 100644
--- a/solr/core/src/java/org/apache/solr/pkg/PackageListeners.java
+++ b/solr/core/src/java/org/apache/solr/pkg/PackageListeners.java
@@ -47,6 +47,14 @@ public class PackageListeners {
public synchronized void addListener(Listener listener) {
listeners.add(new SoftReference<>(listener));
+ }
+
+ public synchronized void addListener(Listener listener, boolean addFirst) {
+ if(addFirst) {
+ listeners.add(0, new SoftReference<>(listener));
+ } else {
+ addListener(listener);
+ }
}
@@ -71,7 +79,7 @@ public class PackageListeners {
invokeListeners(pkgInfo, ctx);
}
} finally {
- ctx.runLaterTasks(core::runAsync);
+ ctx.runLaterTasks(r -> core.getCoreContainer().runAsync(r));
MDCLoggingContext.clear();
}
}
@@ -102,7 +110,10 @@ public class PackageListeners {
/**Name of the package or null to listen to all package changes */
String packageName();
- PluginInfo pluginInfo();
+ /** fetch the package versions of class names
+ *
+ */
+ Map<String, PackageAPI.PkgVersion> packageDetails();
/**A callback when the package is updated */
void changed(PackageLoader.Package pkg, Ctx ctx);
diff --git a/solr/core/src/java/org/apache/solr/pkg/PackageListeningClassLoader.java b/solr/core/src/java/org/apache/solr/pkg/PackageListeningClassLoader.java
index c10af0c..0a90162 100644
--- a/solr/core/src/java/org/apache/solr/pkg/PackageListeningClassLoader.java
+++ b/solr/core/src/java/org/apache/solr/pkg/PackageListeningClassLoader.java
@@ -26,9 +26,8 @@ import org.apache.solr.common.cloud.SolrClassLoader;
import org.apache.solr.core.SolrResourceLoader;
import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Objects;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
/**
* A {@link SolrClassLoader} that is designed to listen to a set of packages.
@@ -37,22 +36,29 @@ import java.util.function.Function;
* */
public class PackageListeningClassLoader implements SolrClassLoader , PackageListeners.Listener {
private final CoreContainer coreContainer;
- private final SolrResourceLoader coreResourceLoader;
+ private final SolrClassLoader fallbackClassLoader;
private final Function<String, String> pkgVersionSupplier;
/** package name and the versions that we are tracking
*/
- private Map<String ,PackageAPI.PkgVersion> packageVersions = new HashMap<>(1);
+ private Map<String ,PackageAPI.PkgVersion> packageVersions = new ConcurrentHashMap<>(1);
+ private Map<String, String> classNameVsPackageName = new ConcurrentHashMap<>();
private final Runnable onReload;
+ /**
+ * @param fallbackClassLoader The {@link SolrClassLoader} to use if no package is specified
+ * @param pkgVersionSupplier Get the version configured for a given package
+ * @param onReload The callback function that should be run if a package is updated
+ */
public PackageListeningClassLoader(CoreContainer coreContainer,
- SolrResourceLoader coreResourceLoader,
+ SolrClassLoader fallbackClassLoader,
Function<String, String> pkgVersionSupplier,
Runnable onReload) {
this.coreContainer = coreContainer;
- this.coreResourceLoader = coreResourceLoader;
+ this.fallbackClassLoader = fallbackClassLoader;
this.pkgVersionSupplier = pkgVersionSupplier;
this.onReload = () -> {
- packageVersions = new HashMap<>();
+ packageVersions = new ConcurrentHashMap<>();
+ classNameVsPackageName = new ConcurrentHashMap<>();
onReload.run();
};
}
@@ -61,18 +67,28 @@ public class PackageListeningClassLoader implements SolrClassLoader , PackageLis
@Override
public <T> T newInstance(String cname, Class<T> expectedType, String... subpackages) {
PluginInfo.ClassName cName = new PluginInfo.ClassName(cname);
- if(cName.pkg == null){
- return coreResourceLoader.newInstance(cname, expectedType, subpackages);
+ if(cName.pkg == null) {
+ return fallbackClassLoader.newInstance(cname, expectedType, subpackages);
} else {
- PackageLoader.Package.Version version = findPkgVersion(cName);
- return applyResourceLoaderAware(version, version.getLoader().newInstance(cName.className, expectedType, subpackages));
-
+ PackageLoader.Package.Version version = findPackageVersion(cName, true);
+ T obj = version.getLoader().newInstance(cName.className, expectedType, subpackages);
+ classNameVsPackageName.put(cName.original, cName.pkg);
+ return applyResourceLoaderAware(version, obj);
}
}
- private PackageLoader.Package.Version findPkgVersion(PluginInfo.ClassName cName) {
+
+ /**
+ * This looks up for package and also listens for that package if required
+ * @param cName The class name
+ */
+ public PackageLoader.Package.Version findPackageVersion(PluginInfo.ClassName cName, boolean registerListener) {
PackageLoader.Package.Version theVersion = coreContainer.getPackageLoader().getPackage(cName.pkg).getLatest(pkgVersionSupplier.apply(cName.pkg));
- packageVersions.put(cName.pkg, theVersion.getPkgVersion());
+ if(registerListener) {
+ classNameVsPackageName.put(cName.original, cName.pkg);
+ PackageAPI.PkgVersion pkgVersion = theVersion.getPkgVersion();
+ if(pkgVersion !=null) packageVersions.put(cName.pkg, pkgVersion);
+ }
return theVersion;
}
@@ -101,10 +117,12 @@ public class PackageListeningClassLoader implements SolrClassLoader , PackageLis
public <T> T newInstance(String cname, Class<T> expectedType, String[] subPackages, Class[] params, Object[] args) {
PluginInfo.ClassName cName = new PluginInfo.ClassName(cname);
if (cName.pkg == null) {
- return coreResourceLoader.newInstance(cname, expectedType, subPackages, params, args);
+ return fallbackClassLoader.newInstance(cname, expectedType, subPackages, params, args);
} else {
- PackageLoader.Package.Version version = findPkgVersion(cName);
- return applyResourceLoaderAware(version, version.getLoader().newInstance(cName.className, expectedType, subPackages, params, args));
+ PackageLoader.Package.Version version = findPackageVersion(cName, true);
+ T obj = version.getLoader().newInstance(cName.className, expectedType, subPackages, params, args);
+ classNameVsPackageName.put(cName.original, cName.pkg);
+ return applyResourceLoaderAware(version, obj);
}
}
@@ -112,10 +130,12 @@ public class PackageListeningClassLoader implements SolrClassLoader , PackageLis
public <T> Class<? extends T> findClass(String cname, Class<T> expectedType) {
PluginInfo.ClassName cName = new PluginInfo.ClassName(cname);
if (cName.pkg == null) {
- return coreResourceLoader.findClass(cname, expectedType);
+ return fallbackClassLoader.findClass(cname, expectedType);
} else {
- PackageLoader.Package.Version version = findPkgVersion(cName);
- return version.getLoader().findClass(cName.className, expectedType);
+ PackageLoader.Package.Version version = findPackageVersion(cName, true);
+ Class<? extends T> klas = version.getLoader().findClass(cName.className, expectedType);
+ classNameVsPackageName.put(cName.original, cName.pkg);
+ return klas;
}
}
@@ -126,8 +146,10 @@ public class PackageListeningClassLoader implements SolrClassLoader , PackageLis
}
@Override
- public PluginInfo pluginInfo() {
- return null;
+ public Map<String, PackageAPI.PkgVersion> packageDetails() {
+ Map<String, PackageAPI.PkgVersion> result = new LinkedHashMap<>();
+ classNameVsPackageName.forEach((k, v) -> result.put(k, packageVersions.get(v)));
+ return result;
}
@Override
@@ -146,6 +168,11 @@ public class PackageListeningClassLoader implements SolrClassLoader , PackageLis
//no need to update
return;
}
+ doReloadAction(ctx);
+ }
+
+ protected void doReloadAction(Ctx ctx) {
+ if(onReload == null) return;
ctx.runLater(null, onReload);
}
}
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..978f707 100644
--- a/solr/core/src/java/org/apache/solr/pkg/PackagePluginHolder.java
+++ b/solr/core/src/java/org/apache/solr/pkg/PackagePluginHolder.java
@@ -19,6 +19,8 @@ package org.apache.solr.pkg;
import java.io.IOException;
import java.lang.invoke.MethodHandles;
+import java.util.Collections;
+import java.util.Map;
import org.apache.lucene.analysis.util.ResourceLoaderAware;
import org.apache.solr.common.MapWriter;
@@ -57,8 +59,8 @@ public class PackagePluginHolder<T> extends PluginBag.PluginHolder<T> {
}
@Override
- public PluginInfo pluginInfo() {
- return info;
+ public Map<String, PackageAPI.PkgVersion> packageDetails() {
+ return Collections.singletonMap(info.cName.original, pkgVersion.getPkgVersion());
}
@Override
@@ -75,6 +77,12 @@ public class PackagePluginHolder<T> extends PluginBag.PluginHolder<T> {
});
}
+ public static <T> PluginBag.PluginHolder<T> createHolder(T inst, Class<T> type) {
+ SolrConfig.SolrPluginInfo plugin = SolrConfig.classVsSolrPluginInfo.get(type.getName());
+ PluginInfo info = new PluginInfo(plugin.tag, Collections.singletonMap("class", inst.getClass().getName()));
+ return new PluginBag.PluginHolder<T>(info,inst);
+ }
+
public static <T> PluginBag.PluginHolder<T> createHolder(PluginInfo info, SolrCore core, Class<T> type, String msg) {
if(info.cName.pkg == null) {
return new PluginBag.PluginHolder<T>(info, core.createInitInstance(info, type,msg, null));
@@ -108,7 +116,7 @@ public class PackagePluginHolder<T> extends PluginBag.PluginHolder<T> {
if (log.isInfoEnabled()) {
log.info("loading plugin: {} -> {} using package {}:{}",
- pluginInfo.type, pluginInfo.name, pkg.name(), newest.getVersion());
+ pluginInfo.type, pluginInfo.name, pkg.name(), newest.getVersion());
}
initNewInstance(newest);
@@ -119,7 +127,7 @@ public class PackagePluginHolder<T> extends PluginBag.PluginHolder<T> {
@SuppressWarnings({"unchecked"})
protected Object initNewInstance(PackageLoader.Package.Version newest) {
Object instance = SolrCore.createInstance(pluginInfo.className,
- pluginMeta.clazz, pluginMeta.getCleanTag(), core, newest.getLoader());
+ pluginMeta.clazz, pluginMeta.getCleanTag(), core, newest.getLoader());
PluginBag.initInstance(instance, pluginInfo);
handleAwareCallbacks(newest.getLoader(), instance);
T old = inst;
diff --git a/solr/core/src/java/org/apache/solr/search/CacheConfig.java b/solr/core/src/java/org/apache/solr/search/CacheConfig.java
index b4f4706..9b1c297 100644
--- a/solr/core/src/java/org/apache/solr/search/CacheConfig.java
+++ b/solr/core/src/java/org/apache/solr/search/CacheConfig.java
@@ -23,10 +23,14 @@ import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import java.util.function.Supplier;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.util.StrUtils;
import org.apache.solr.common.MapSerializable;
+
+import org.apache.solr.core.PluginInfo;
+
import org.apache.solr.core.SolrConfig;
import org.apache.solr.core.SolrResourceLoader;
import org.apache.solr.common.util.DOMUtil;
@@ -46,11 +50,17 @@ import static org.apache.solr.common.params.CommonParams.NAME;
*/
public class CacheConfig implements MapSerializable{
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
-
+
private String nodeName;
+
+ /**
+ * When this object is created, the core is not yet available . So, if the class is to be
+ * loaded from a package we should have a corresponding core
+ *
+ */
@SuppressWarnings({"rawtypes"})
- private Class<? extends SolrCache> clazz;
+ private Supplier<Class<? extends SolrCache>> clazz;
private Map<String,String> args;
private CacheRegenerator regenerator;
@@ -64,9 +74,10 @@ public class CacheConfig implements MapSerializable{
@SuppressWarnings({"rawtypes"})
public CacheConfig(Class<? extends SolrCache> clazz, Map<String,String> args, CacheRegenerator regenerator) {
- this.clazz = clazz;
+ this.clazz = () -> clazz;
this.args = args;
this.regenerator = regenerator;
+ this.nodeName = args.get(NAME);
}
public CacheRegenerator getRegenerator() {
@@ -85,7 +96,7 @@ public class CacheConfig implements MapSerializable{
Node node = nodes.item(i);
if ("true".equals(DOMUtil.getAttrOrDefault(node, "enabled", "true"))) {
CacheConfig config = getConfig(solrConfig, node.getNodeName(),
- DOMUtil.toMap(node.getAttributes()), configPath);
+ DOMUtil.toMap(node.getAttributes()), configPath);
result.put(config.args.get(NAME), config);
}
}
@@ -134,19 +145,31 @@ public class CacheConfig implements MapSerializable{
SolrResourceLoader loader = solrConfig.getResourceLoader();
config.cacheImpl = config.args.get("class");
if (config.cacheImpl == null) config.cacheImpl = "solr.CaffeineCache";
+ config.clazz = new Supplier() {
+ @SuppressWarnings("rawtypes")
+ Class<SolrCache> loadedClass;
+
+ @Override
+ @SuppressWarnings("rawtypes")
+ public Class<? extends SolrCache> get() {
+ if (loadedClass != null) return loadedClass;
+ return loadedClass = (Class<SolrCache>) loader.findClass(
+ new PluginInfo("cache", Collections.singletonMap("class", config.cacheImpl)),
+ SolrCache.class, true);
+ }
+ };
config.regenImpl = config.args.get("regenerator");
- config.clazz = loader.findClass(config.cacheImpl, SolrCache.class);
if (config.regenImpl != null) {
config.regenerator = loader.newInstance(config.regenImpl, CacheRegenerator.class);
}
-
+
return config;
}
@SuppressWarnings({"rawtypes"})
public SolrCache newInstance() {
try {
- SolrCache cache = clazz.getConstructor().newInstance();
+ SolrCache cache = clazz.get().getConstructor().newInstance();
persistence[0] = cache.init(args, persistence[0], regenerator);
return cache;
} catch (Exception e) {
@@ -158,11 +181,8 @@ public class CacheConfig implements MapSerializable{
}
@Override
- @SuppressWarnings({"unchecked"})
public Map<String, Object> toMap(Map<String, Object> map) {
- @SuppressWarnings({"rawtypes"})
- Map result = Collections.unmodifiableMap(args);
- return result;
+ return new HashMap<>(args);
}
public String getNodeName() {
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 a2ee786..13cdfbb 100644
--- a/solr/core/src/java/org/apache/solr/update/UpdateHandler.java
+++ b/solr/core/src/java/org/apache/solr/update/UpdateHandler.java
@@ -111,7 +111,7 @@ public abstract class UpdateHandler implements SolrInfoBean {
public UpdateHandler(SolrCore core) {
this(core, null);
}
-
+
public UpdateHandler(SolrCore core, UpdateLog updateLog) {
this.core=core;
idField = core.getLatestSchema().getUniqueKeyField();
@@ -126,8 +126,8 @@ public abstract class UpdateHandler implements SolrInfoBean {
if (dirFactory instanceof HdfsDirectoryFactory) {
ulog = new HdfsUpdateLog(((HdfsDirectoryFactory)dirFactory).getConfDir());
} else {
- String className = ulogPluginInfo.className == null ? UpdateLog.class.getName() : ulogPluginInfo.className;
- ulog = core.getResourceLoader().newInstance(className, UpdateLog.class);
+ ulog = ulogPluginInfo.className == null ? new UpdateLog():
+ core.getResourceLoader().newInstance(ulogPluginInfo, UpdateLog.class, true);
}
if (!core.isReloaded() && !dirFactory.isPersistent()) {
diff --git a/solr/core/src/test-files/solr/configsets/conf2/conf/schema.xml b/solr/core/src/test-files/solr/configsets/conf2/conf/schema.xml
new file mode 100644
index 0000000..85f7ed3
--- /dev/null
+++ b/solr/core/src/test-files/solr/configsets/conf2/conf/schema.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+ 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.
+-->
+<schema name="minimal" version="1.1">
+ <fieldType name="string" class="solr.StrField"/>
+ <fieldType name="int" class="${solr.tests.IntegerFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+ <fieldType name="long" class="${solr.tests.LongFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+ <dynamicField name="*" type="string" indexed="true" stored="true"/>
+ <!-- for versioning -->
+ <field name="_version_" type="long" indexed="true" stored="true"/>
+ <field name="_root_" type="string" indexed="true" stored="true" multiValued="false" required="false"/>
+ <field name="id" type="string" indexed="true" stored="true"/>
+ <dynamicField name="*_s" type="string" indexed="true" stored="true" />
+ <uniqueKey>id</uniqueKey>
+ <query>
+ <filterCache
+ size="0"
+ initialSize="0"
+ autowarmCount="0"/>
+ <queryResultCache
+ size="0"
+ initialSize="0"
+ autowarmCount="0"/>
+ <documentCache
+ size="0"
+ initialSize="0"
+ autowarmCount="0"/>
+ </query>
+</schema>
diff --git a/solr/core/src/test-files/solr/configsets/conf2/conf/solrconfig.xml b/solr/core/src/test-files/solr/configsets/conf2/conf/solrconfig.xml
new file mode 100644
index 0000000..e69d16f
--- /dev/null
+++ b/solr/core/src/test-files/solr/configsets/conf2/conf/solrconfig.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" ?>
+
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!-- Minimal solrconfig.xml with /select, /admin and /update only -->
+
+<config>
+
+ <dataDir>${solr.data.dir:}</dataDir>
+
+ <directoryFactory name="DirectoryFactory"
+ class="${solr.directoryFactory:solr.NRTCachingDirectoryFactory}"/>
+ <schemaFactory class="ClassicIndexSchemaFactory"/>
+
+ <luceneMatchVersion>${tests.luceneMatchVersion:LATEST}</luceneMatchVersion>
+
+ <updateHandler class="solr.DirectUpdateHandler2">
+ <commitWithin>
+ <softCommit>${solr.commitwithin.softcommit:true}</softCommit>
+ </commitWithin>
+ <updateLog class="${solr.ulog:solr.UpdateLog}"></updateLog>
+ </updateHandler>
+
+ <requestHandler name="/select" class="solr.SearchHandler">
+ <lst name="defaults">
+ <str name="echoParams">explicit</str>
+ <str name="indent">true</str>
+ <str name="df">text</str>
+ </lst>
+
+ </requestHandler>
+ <query>
+ <filterCache
+ class = "mypkg:org.apache.solr.search.CaffeineCache"
+ size="512"
+ initialSize="512"
+ autowarmCount="0" />
+
+ <queryResultCache
+ size="512"
+ initialSize="512"
+ autowarmCount="0" />
+
+ <documentCache
+ size="512"
+ initialSize="512"
+ autowarmCount="0" />
+ </query>
+ <indexConfig>
+ <mergeScheduler class="${solr.mscheduler:org.apache.lucene.index.ConcurrentMergeScheduler}"/>
+ </indexConfig>
+</config>
+
diff --git a/solr/core/src/test/org/apache/solr/pkg/TestPackages.java b/solr/core/src/test/org/apache/solr/pkg/TestPackages.java
index 9b30753..dc90769 100644
--- a/solr/core/src/test/org/apache/solr/pkg/TestPackages.java
+++ b/solr/core/src/test/org/apache/solr/pkg/TestPackages.java
@@ -102,6 +102,69 @@ public class TestPackages extends SolrCloudTestCase {
@JsonProperty("class")
public String klass;
}
+
+
+ public void testCoreReloadingPlugin() throws Exception {
+ MiniSolrCloudCluster cluster =
+ configureCluster(4)
+ .withJettyConfig(jetty -> jetty.enableV2(true))
+ .addConfig("conf", configset("conf2"))
+ .configure();
+ try {
+ String FILE1 = "/mypkg/runtimelibs.jar";
+ String COLLECTION_NAME = "testCoreReloadingPluginColl";
+ byte[] derFile = readFile("cryptokeys/pub_key512.der");
+ uploadKey(derFile, PackageStoreAPI.KEYS_DIR+"/pub_key512.der", cluster);
+ postFileAndWait(cluster, "runtimecode/runtimelibs.jar.bin", FILE1,
+ "L3q/qIGs4NaF6JiO0ZkMUFa88j0OmYc+I6O7BOdNuMct/xoZ4h73aZHZGc0+nmI1f/U3bOlMPINlSOM6LK3JpQ==");
+
+ Package.AddVersion add = new Package.AddVersion();
+ add.version = "1.0";
+ add.pkg = "mypkg";
+ add.files = Arrays.asList(new String[]{FILE1});
+ V2Request req = new V2Request.Builder("/cluster/package")
+ .forceV2(true)
+ .withMethod(SolrRequest.METHOD.POST)
+ .withPayload(Collections.singletonMap("add", add))
+ .build();
+
+ req.process(cluster.getSolrClient());
+ TestDistribPackageStore.assertResponseValues(10,
+ () -> new V2Request.Builder("/cluster/package").
+ withMethod(SolrRequest.METHOD.GET)
+ .build().process(cluster.getSolrClient()),
+ Utils.makeMap(
+ ":result:packages:mypkg[0]:version", "1.0",
+ ":result:packages:mypkg[0]:files[0]", FILE1
+ ));
+
+ CollectionAdminRequest
+ .createCollection(COLLECTION_NAME, "conf", 2, 2)
+ .process(cluster.getSolrClient());
+ cluster.waitForActiveCollection(COLLECTION_NAME, 2, 4);
+
+ verifyComponent(cluster.getSolrClient(), COLLECTION_NAME, "query", "filterCache", add.pkg, add.version);
+
+
+ add.version = "2.0";
+ req.process(cluster.getSolrClient());
+ TestDistribPackageStore.assertResponseValues(10,
+ () -> new V2Request.Builder("/cluster/package").
+ withMethod(SolrRequest.METHOD.GET)
+ .build().process(cluster.getSolrClient()),
+ Utils.makeMap(
+ ":result:packages:mypkg[1]:version", "2.0",
+ ":result:packages:mypkg[1]:files[0]", FILE1
+ ));
+ new UpdateRequest().commit(cluster.getSolrClient(), COLLECTION_NAME);
+
+ verifyComponent(cluster.getSolrClient(),
+ COLLECTION_NAME, "query", "filterCache",
+ "mypkg", "2.0" );
+ } finally {
+ cluster.shutdown();
+ }
+ }
@Test
@SuppressWarnings({"unchecked"})
public void testPluginLoading() throws Exception {
@@ -650,10 +713,10 @@ public class TestPackages extends SolrCloudTestCase {
System.setProperty("managed.schema.mutable", "true");
MiniSolrCloudCluster cluster =
- configureCluster(4)
- .withJettyConfig(jetty -> jetty.enableV2(true))
- .addConfig("conf1", configset("schema-package"))
- .configure();
+ configureCluster(4)
+ .withJettyConfig(jetty -> jetty.enableV2(true))
+ .addConfig("conf1", configset("schema-package"))
+ .configure();
try {
String FILE1 = "/schemapkg/schema-plugins.jar";
byte[] derFile = readFile("cryptokeys/pub_key512.der");
@@ -686,14 +749,14 @@ public class TestPackages extends SolrCloudTestCase {
));
CollectionAdminRequest
- .createCollection(COLLECTION_NAME, "conf1", 2, 2)
- .process(cluster.getSolrClient());
+ .createCollection(COLLECTION_NAME, "conf1", 2, 2)
+ .process(cluster.getSolrClient());
cluster.waitForActiveCollection(COLLECTION_NAME, 2, 4);
verifySchemaComponent(cluster.getSolrClient(), COLLECTION_NAME, "/schema/fieldtypes/myNewTextFieldWithAnalyzerClass",
- Utils.makeMap(":fieldType:analyzer:charFilters[0]:_packageinfo_:version" ,"1.0",
- ":fieldType:analyzer:tokenizer:_packageinfo_:version","1.0",
- ":fieldType:_packageinfo_:version","1.0"));
+ Utils.makeMap(":fieldType:analyzer:charFilters[0]:_packageinfo_:version" ,"1.0",
+ ":fieldType:analyzer:tokenizer:_packageinfo_:version","1.0",
+ ":fieldType:_packageinfo_:version","1.0"));
add = new Package.AddVersion();
add.version = "2.0";