You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@solr.apache.org by ds...@apache.org on 2023/01/22 17:13:09 UTC
[solr] branch branch_9x updated: SOLR-16591: Deprecate transient Cores. Simplify SolrCores. (#1243)
This is an automated email from the ASF dual-hosted git repository.
dsmiley pushed a commit to branch branch_9x
in repository https://gitbox.apache.org/repos/asf/solr.git
The following commit(s) were added to refs/heads/branch_9x by this push:
new be27d4573a9 SOLR-16591: Deprecate transient Cores. Simplify SolrCores. (#1243)
be27d4573a9 is described below
commit be27d4573a9a134231dc90568afa9201e041f73a
Author: David Smiley <ds...@salesforce.com>
AuthorDate: Sat Jan 21 18:52:51 2023 -0500
SOLR-16591: Deprecate transient Cores. Simplify SolrCores. (#1243)
The "Transient Cores" feature is now deprecated.
In solr.xml "<transientCoreCacheFactory>" no longer works; it wasn't documented either.
Some internals were changed as well to simplify the standard case of having no transient cores.
---
solr/CHANGES.txt | 4 +
.../java/org/apache/solr/core/CoreContainer.java | 31 +--
.../src/java/org/apache/solr/core/NodeConfig.java | 29 +--
.../src/java/org/apache/solr/core/SolrCores.java | 257 +++++++--------------
.../java/org/apache/solr/core/SolrXmlConfig.java | 3 +-
.../apache/solr/core/TransientSolrCoreCache.java | 18 +-
.../solr/core/TransientSolrCoreCacheDefault.java | 48 +---
.../solr/core/TransientSolrCoreCacheFactory.java | 101 --------
.../core/TransientSolrCoreCacheFactoryDefault.java | 31 ---
.../org/apache/solr/core/TransientSolrCores.java | 173 ++++++++++++++
.../solr/handler/admin/CoreAdminOperation.java | 2 +-
.../src/test-files/solr/solr-transientCores.xml | 20 ++
solr/core/src/test-files/solr/solr.xml | 5 -
.../test/org/apache/solr/core/TestLazyCores.java | 6 +-
.../src/test/org/apache/solr/core/TestSolrXml.java | 19 +-
.../solr/metrics/SolrMetricsIntegrationTest.java | 4 +-
.../pages/configuring-solr-xml.adoc | 3 +-
.../pages/major-changes-in-solr-9.adoc | 1 +
.../src/java/org/apache/solr/SolrTestCaseJ4.java | 2 +-
19 files changed, 329 insertions(+), 428 deletions(-)
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index 1c1e56f64b5..d5e7bcdbf1b 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -209,6 +209,10 @@ Other Changes
* SOLR-16544: Improve documentation on how to contribute to Solr (Justin Sweeney)
+* SOLR-16591: The "Transient Cores" feature is now deprecated. In solr.xml "<transientCoreCacheFactory>"
+ no longer works; it wasn't documented either. Some internals were changed as well to simplify
+ the standard case of having no transient cores. (David Smiley)
+
* SOLR-16626: Upgrade to Netty 4.1.87.Final (Kevin Risden)
* SOLR-16627: Upgrade google-cloud-bom to 0.184.0, re2j to 1.6, and grpc to 1.51.0 (Kevin Risden)
diff --git a/solr/core/src/java/org/apache/solr/core/CoreContainer.java b/solr/core/src/java/org/apache/solr/core/CoreContainer.java
index a32b552fe99..666536abc72 100644
--- a/solr/core/src/java/org/apache/solr/core/CoreContainer.java
+++ b/solr/core/src/java/org/apache/solr/core/CoreContainer.java
@@ -175,7 +175,7 @@ public class CoreContainer {
ExecutorUtil.addThreadLocalProvider(SolrRequestInfo.getInheritableThreadLocalProvider());
}
- final SolrCores solrCores = new SolrCores(this);
+ final SolrCores solrCores;
public static class CoreLoadFailure {
@@ -391,6 +391,7 @@ public class CoreContainer {
this.cfg = requireNonNull(config);
this.loader = config.getSolrResourceLoader();
this.solrHome = config.getSolrHome();
+ this.solrCores = SolrCores.newSolrCores(this);
this.nodeKeyPair = new SolrNodeKeyPair(cfg.getCloudConfig());
containerHandlers.put(PublicKeyHandler.PATH, new PublicKeyHandler(nodeKeyPair));
if (null != this.cfg.getBooleanQueryMaxClauseCount()) {
@@ -637,6 +638,7 @@ public class CoreContainer {
*/
protected CoreContainer(Object testConstructor) {
solrHome = null;
+ solrCores = null;
nodeKeyPair = null;
loader = null;
coresLocator = null;
@@ -767,8 +769,6 @@ public class CoreContainer {
solrClientCache = new SolrClientCache(updateShardHandler.getDefaultHttpClient());
- solrCores.load(loader);
-
StartupLoggingUtils.checkRequestLogging();
hostName = cfg.getNodeName();
@@ -1784,11 +1784,16 @@ public class CoreContainer {
}
/**
- * Gets the permanent (non-transient) cores that are currently loaded.
+ * Gets all loaded cores, consistent with {@link #getLoadedCoreNames()}. Caller doesn't need to
+ * close.
+ *
+ * <p>NOTE: rather dangerous API because each core is not reserved (could in theory be closed).
+ * Prefer {@link #getLoadedCoreNames()} and then call {@link #getCore(String)} then close it.
*
* @return An unsorted list. This list is a new copy, it can be modified by the caller (e.g. it
- * can be sorted).
+ * can be sorted). Don't need to close them.
*/
+ @Deprecated
public List<SolrCore> getCores() {
return solrCores.getCores();
}
@@ -2296,17 +2301,6 @@ public class CoreContainer {
return solrCores.isLoaded(name);
}
- /**
- * Gets a solr core descriptor for a core that is not loaded. Note that if the caller calls this
- * on a loaded core, the unloaded descriptor will be returned.
- *
- * @param cname - name of the unloaded core descriptor to load. NOTE:
- * @return a coreDescriptor. May return null
- */
- public CoreDescriptor getUnloadedCoreDescriptor(String cname) {
- return solrCores.getUnloadedCoreDescriptor(cname);
- }
-
/** The primary path of a Solr server's config, cores, and misc things. Absolute. */
// TODO return Path
public String getSolrHome() {
@@ -2391,11 +2385,6 @@ public class CoreContainer {
}
}
- // Occasionally we need to access the transient cache handler in places other than coreContainer.
- public TransientSolrCoreCache getTransientCache() {
- return solrCores.getTransientCacheHandler();
- }
-
/**
* @param solrCore the core against which we check if there has been a tragic exception
* @return whether this Solr core has tragic exception
diff --git a/solr/core/src/java/org/apache/solr/core/NodeConfig.java b/solr/core/src/java/org/apache/solr/core/NodeConfig.java
index ad9f9844ee1..c6763cf2205 100644
--- a/solr/core/src/java/org/apache/solr/core/NodeConfig.java
+++ b/solr/core/src/java/org/apache/solr/core/NodeConfig.java
@@ -92,9 +92,7 @@ public class NodeConfig {
private final int replayUpdatesThreads;
- @Deprecated
- // This should be part of the transientCacheConfig, remove in 7.0
- private final int transientCacheSize;
+ @Deprecated private final int transientCacheSize;
private final boolean useSchemaCache;
@@ -104,8 +102,6 @@ public class NodeConfig {
private final MetricsConfig metricsConfig;
- private final PluginInfo transientCacheConfig;
-
private final PluginInfo tracerConfig;
// Track if this config was loaded from zookeeper so that we can skip validating the zookeeper
@@ -141,7 +137,6 @@ public class NodeConfig {
Properties solrProperties,
PluginInfo[] backupRepositoryPlugins,
MetricsConfig metricsConfig,
- PluginInfo transientCacheConfig,
PluginInfo tracerConfig,
boolean fromZookeeper,
String defaultZkHost,
@@ -176,7 +171,6 @@ public class NodeConfig {
this.solrProperties = solrProperties;
this.backupRepositoryPlugins = backupRepositoryPlugins;
this.metricsConfig = metricsConfig;
- this.transientCacheConfig = transientCacheConfig;
this.tracerConfig = tracerConfig;
this.fromZookeeper = fromZookeeper;
this.defaultZkHost = defaultZkHost;
@@ -378,10 +372,6 @@ public class NodeConfig {
return metricsConfig;
}
- public PluginInfo getTransientCachePluginInfo() {
- return transientCacheConfig;
- }
-
public PluginInfo getTracerConfiguratorPluginInfo() {
return tracerConfig;
}
@@ -556,17 +546,12 @@ public class NodeConfig {
private CloudConfig cloudConfig;
private int coreLoadThreads = DEFAULT_CORE_LOAD_THREADS;
private int replayUpdatesThreads = Runtime.getRuntime().availableProcessors();
-
- @Deprecated
- // Remove in 7.0 and put it all in the transientCache element in solrconfig.xml
- private int transientCacheSize = DEFAULT_TRANSIENT_CACHE_SIZE;
-
+ @Deprecated private int transientCacheSize = -1;
private boolean useSchemaCache = false;
private String managementPath;
private Properties solrProperties = new Properties();
private PluginInfo[] backupRepositoryPlugins;
private MetricsConfig metricsConfig;
- private PluginInfo transientCacheConfig;
private PluginInfo tracerConfig;
private boolean fromZookeeper = false;
private String defaultZkHost;
@@ -580,8 +565,6 @@ public class NodeConfig {
// No:of core load threads in cloud mode is set to a default of 8
public static final int DEFAULT_CORE_LOAD_THREADS_IN_CLOUD = 8;
- public static final int DEFAULT_TRANSIENT_CACHE_SIZE = Integer.MAX_VALUE;
-
private static final String DEFAULT_ADMINHANDLERCLASS =
"org.apache.solr.handler.admin.CoreAdminHandler";
private static final String DEFAULT_INFOHANDLERCLASS =
@@ -705,7 +688,7 @@ public class NodeConfig {
return this;
}
- // Remove in Solr 7.0
+ // Remove in Solr 10.0
@Deprecated
public NodeConfigBuilder setTransientCacheSize(int transientCacheSize) {
this.transientCacheSize = transientCacheSize;
@@ -737,11 +720,6 @@ public class NodeConfig {
return this;
}
- public NodeConfigBuilder setSolrCoreCacheFactoryConfig(PluginInfo transientCacheConfig) {
- this.transientCacheConfig = transientCacheConfig;
- return this;
- }
-
public NodeConfigBuilder setTracerConfig(PluginInfo tracerConfig) {
this.tracerConfig = tracerConfig;
return this;
@@ -816,7 +794,6 @@ public class NodeConfig {
solrProperties,
backupRepositoryPlugins,
metricsConfig,
- transientCacheConfig,
tracerConfig,
fromZookeeper,
defaultZkHost,
diff --git a/solr/core/src/java/org/apache/solr/core/SolrCores.java b/solr/core/src/java/org/apache/solr/core/SolrCores.java
index bc868568889..0f6616a4586 100644
--- a/solr/core/src/java/org/apache/solr/core/SolrCores.java
+++ b/solr/core/src/java/org/apache/solr/core/SolrCores.java
@@ -36,10 +36,14 @@ import org.apache.solr.logging.MDCLoggingContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-class SolrCores {
+/** AKA CoreManager: Holds/manages {@link SolrCore}s within {@link CoreContainer}. */
+public class SolrCores {
+
+ private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+ // for locking around manipulating any of the core maps.
+ protected final Object modifyLock = new Object();
- private static final Object modifyLock =
- new Object(); // for locking around manipulating any of the core maps.
private final Map<String, SolrCore> cores = new LinkedHashMap<>(); // For "permanent" cores
// These descriptors, once loaded, will _not_ be unloaded, i.e. they are not "transient".
@@ -47,49 +51,40 @@ class SolrCores {
private final CoreContainer container;
- private Set<String> currentlyLoadingCores =
+ private final Set<String> currentlyLoadingCores =
Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>());
- private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
-
// This map will hold objects that are being currently operated on. The core (value) may be null
// in the case of initial load. The rule is, never to any operation on a core that is currently
// being operated upon.
- private static final Set<String> pendingCoreOps = new HashSet<>();
+ private final Set<String> pendingCoreOps = new HashSet<>();
// Due to the fact that closes happen potentially whenever anything is _added_ to the transient
// core list, we need to essentially queue them up to be handled via pendingCoreOps.
- private static final List<SolrCore> pendingCloses = new ArrayList<>();
-
- private TransientSolrCoreCacheFactory transientSolrCoreCacheFactory;
+ private final List<SolrCore> pendingCloses = new ArrayList<>();
+
+ public static SolrCores newSolrCores(CoreContainer coreContainer) {
+ final int transientCacheSize = coreContainer.getConfig().getTransientCacheSize();
+ if (transientCacheSize > 0) {
+ return new TransientSolrCores(coreContainer, transientCacheSize);
+ } else {
+ return new SolrCores(coreContainer);
+ }
+ }
SolrCores(CoreContainer container) {
this.container = container;
}
- protected void addCoreDescriptor(CoreDescriptor p) {
+ public void addCoreDescriptor(CoreDescriptor p) {
synchronized (modifyLock) {
- if (p.isTransient()) {
- getTransientCacheHandler().addTransientDescriptor(p.getName(), p);
- } else {
- residentDescriptors.put(p.getName(), p);
- }
- }
- }
-
- protected void removeCoreDescriptor(CoreDescriptor p) {
- synchronized (modifyLock) {
- if (p.isTransient()) {
- getTransientCacheHandler().removeTransientDescriptor(p.getName());
- } else {
- residentDescriptors.remove(p.getName());
- }
+ residentDescriptors.put(p.getName(), p);
}
}
- public void load(SolrResourceLoader loader) {
+ public void removeCoreDescriptor(CoreDescriptor p) {
synchronized (modifyLock) {
- transientSolrCoreCacheFactory = TransientSolrCoreCacheFactory.newInstance(loader, container);
+ residentDescriptors.remove(p.getName());
}
}
@@ -97,39 +92,36 @@ class SolrCores {
// down, so we need to make a temporary copy of the names and shut them down outside the lock.
protected void close() {
waitForLoadingCoresToFinish(30 * 1000);
- Collection<SolrCore> coreList = new ArrayList<>();
-
- // Release transient core cache.
- synchronized (modifyLock) {
- if (transientSolrCoreCacheFactory != null) {
- getTransientCacheHandler().close();
- }
- }
// It might be possible for one of the cores to move from one list to another while we're
// closing them. So loop through the lists until they're all empty. In particular, the core
// could have moved from the transient list to the pendingCloses list.
- do {
- coreList.clear();
+ while (true) {
+ Collection<SolrCore> coreList = new ArrayList<>();
+
synchronized (modifyLock) {
- // make a copy of the cores then clear the map so the core isn't handed out to a request
- // again
- coreList.addAll(cores.values());
- cores.clear();
- if (transientSolrCoreCacheFactory != null) {
- coreList.addAll(getTransientCacheHandler().prepareForShutdown());
+ // remove all loaded cores; add to our working list.
+ for (String name : getLoadedCoreNames()) {
+ final var core = remove(name);
+ if (core != null) { // maybe in pendingCloses due to transient core eviction
+ coreList.add(core);
+ }
}
coreList.addAll(pendingCloses);
pendingCloses.clear();
}
+ if (coreList.isEmpty()) {
+ break;
+ }
+
ExecutorService coreCloseExecutor =
ExecutorUtil.newMDCAwareFixedThreadPool(
Integer.MAX_VALUE, new SolrNamedThreadFactory("coreCloseExecutor"));
try {
for (SolrCore core : coreList) {
- coreCloseExecutor.submit(
+ coreCloseExecutor.execute(
() -> {
MDCLoggingContext.setCore(core);
try {
@@ -142,27 +134,20 @@ class SolrCores {
} finally {
MDCLoggingContext.clear();
}
- return core;
});
}
} finally {
ExecutorUtil.shutdownAndAwaitTermination(coreCloseExecutor);
}
-
- } while (coreList.size() > 0);
+ }
}
// Returns the old core if there was a core of the same name.
// WARNING! This should be the _only_ place you put anything into the list of transient cores!
- protected SolrCore putCore(CoreDescriptor cd, SolrCore core) {
+ public SolrCore putCore(CoreDescriptor cd, SolrCore core) {
synchronized (modifyLock) {
addCoreDescriptor(cd); // cd must always be registered if we register a core
-
- if (cd.isTransient()) {
- return getTransientCacheHandler().addCore(cd.getName(), core);
- } else {
- return cores.put(cd.getName(), core);
- }
+ return cores.put(cd.getName(), core);
}
}
@@ -175,16 +160,16 @@ class SolrCores {
* <p>Note: This is one of the places where SolrCloud is incompatible with Transient Cores.
* This call is used in cancelRecoveries, transient cores don't participate.
*/
- List<SolrCore> getCores() {
-
+ @Deprecated
+ public List<SolrCore> getCores() {
synchronized (modifyLock) {
return new ArrayList<>(cores.values());
}
}
/**
- * Gets the cores that are currently loaded, i.e. cores that have 1> loadOnStartup=true and are
- * either not-transient or, if transient, have been loaded and have not been aged out 2>
+ * Gets the cores that are currently loaded, i.e. cores that have 1: loadOnStartup=true and are
+ * either not-transient or, if transient, have been loaded and have not been aged out 2:
* loadOnStartup=false and have been loaded but either non-transient or have not been aged out.
*
* <p>Put another way, this will not return any names of cores that are lazily loaded but have not
@@ -193,9 +178,9 @@ class SolrCores {
* @return An unsorted list. This list is a new copy, it can be modified by the caller (e.g. it
* can be sorted).
*/
- List<String> getLoadedCoreNames() {
+ public List<String> getLoadedCoreNames() {
synchronized (modifyLock) {
- return distinctSetsUnion(cores.keySet(), getTransientCacheHandler().getLoadedCoreNames());
+ return new ArrayList<>(cores.keySet());
}
}
@@ -209,56 +194,30 @@ class SolrCores {
*/
public List<String> getAllCoreNames() {
synchronized (modifyLock) {
- return distinctSetsUnion(
- residentDescriptors.keySet(), getTransientCacheHandler().getAllCoreNames());
+ return new ArrayList<>(residentDescriptors.keySet());
}
}
- /**
- * Makes the union of two distinct sets.
- *
- * @return An unsorted list. This list is a new copy, it can be modified by the caller (e.g. it
- * can be sorted).
- */
- private static <T> List<T> distinctSetsUnion(Set<T> set1, Set<T> set2) {
- assert areSetsDistinct(set1, set2);
- List<T> union = new ArrayList<>(set1.size() + set2.size());
- union.addAll(set1);
- union.addAll(set2);
- return union;
- }
-
- /** Indicates whether two sets are distinct (intersection is empty). */
- private static <T> boolean areSetsDistinct(Set<T> set1, Set<T> set2) {
- return set1.stream().noneMatch(set2::contains);
- }
-
/**
* Gets the number of currently loaded permanent (non transient) cores. Faster equivalent for
* {@link #getCores()}.size().
*/
- int getNumLoadedPermanentCores() {
+ public int getNumLoadedPermanentCores() {
synchronized (modifyLock) {
return cores.size();
}
}
/** Gets the number of currently loaded transient cores. */
- int getNumLoadedTransientCores() {
- synchronized (modifyLock) {
- return getTransientCacheHandler().getLoadedCoreNames().size();
- }
+ public int getNumLoadedTransientCores() {
+ // TODO; this metric ought to simply not exist here
+ return 0;
}
/** Gets the number of unloaded cores, including permanent and transient cores. */
- int getNumUnloadedCores() {
+ public int getNumUnloadedCores() {
synchronized (modifyLock) {
- assert areSetsDistinct(
- residentDescriptors.keySet(), getTransientCacheHandler().getAllCoreNames());
- return getTransientCacheHandler().getAllCoreNames().size()
- - getTransientCacheHandler().getLoadedCoreNames().size()
- + residentDescriptors.size()
- - cores.size();
+ return residentDescriptors.size() - cores.size();
}
}
@@ -268,17 +227,15 @@ class SolrCores {
*/
public int getNumAllCores() {
synchronized (modifyLock) {
- assert areSetsDistinct(
- residentDescriptors.keySet(), getTransientCacheHandler().getAllCoreNames());
- return residentDescriptors.size() + getTransientCacheHandler().getAllCoreNames().size();
+ return residentDescriptors.size();
}
}
- protected void swap(String n0, String n1) {
-
+ public void swap(String n0, String n1) {
synchronized (modifyLock) {
SolrCore c0 = cores.get(n0);
SolrCore c1 = cores.get(n1);
+ // TODO DWS: honestly this doesn't appear to work properly unless the core is loaded
if (c0 == null) { // Might be an unloaded transient core
c0 = container.getCore(n0);
if (c0 == null) {
@@ -309,31 +266,21 @@ class SolrCores {
}
}
- protected SolrCore remove(String name) {
-
+ public SolrCore remove(String name) {
synchronized (modifyLock) {
- SolrCore ret = cores.remove(name);
- // It could have been a newly-created core. It could have been a transient core. The
- // newly-created cores in particular should be checked. It could have been a dynamic core.
- if (ret == null) {
- ret = getTransientCacheHandler().removeCore(name);
- }
- return ret;
+ return cores.remove(name);
}
}
- SolrCore getCoreFromAnyList(String name, boolean incRefCount) {
+ public SolrCore getCoreFromAnyList(String name, boolean incRefCount) {
return getCoreFromAnyList(name, incRefCount, null);
}
/* If you don't increment the reference count, someone could close the core before you use it. */
- SolrCore getCoreFromAnyList(String name, boolean incRefCount, UUID coreId) {
+ public SolrCore getCoreFromAnyList(String name, boolean incRefCount, UUID coreId) {
synchronized (modifyLock) {
- SolrCore core = cores.get(name);
+ SolrCore core = getLoadedCoreWithoutIncrement(name);
- if (core == null) {
- core = getTransientCacheHandler().getCore(name);
- }
if (core != null && coreId != null && !coreId.equals(core.uniqueId)) return null;
if (core != null && incRefCount) {
@@ -344,57 +291,47 @@ class SolrCores {
}
}
+ /** (internal) Return a core that is already loaded, if it is. NOT incremented! */
+ protected SolrCore getLoadedCoreWithoutIncrement(String name) {
+ synchronized (modifyLock) {
+ return cores.get(name);
+ }
+ }
+
// See SOLR-5366 for why the UNLOAD command needs to know whether a core is actually loaded or
// not, it might have to close the core. However, there's a race condition. If the core happens to
// be in the pending "to close" queue, we should NOT close it in unload core.
- protected boolean isLoadedNotPendingClose(String name) {
- // Just all be synchronized
+ public boolean isLoadedNotPendingClose(String name) {
synchronized (modifyLock) {
- if (cores.containsKey(name)) {
- return true;
+ if (!isLoaded(name)) {
+ return false;
}
- if (getTransientCacheHandler().containsCore(name)) {
- // Check pending
- for (SolrCore core : pendingCloses) {
- if (core.getName().equals(name)) {
- return false;
- }
+ // Check pending
+ for (SolrCore core : pendingCloses) {
+ if (core.getName().equals(name)) {
+ return false;
}
-
- return true;
}
- }
- return false;
- }
- protected boolean isLoaded(String name) {
- synchronized (modifyLock) {
- return cores.containsKey(name) || getTransientCacheHandler().containsCore(name);
+ return true;
}
}
- protected CoreDescriptor getUnloadedCoreDescriptor(String cname) {
+ public boolean isLoaded(String name) {
synchronized (modifyLock) {
- CoreDescriptor desc = residentDescriptors.get(cname);
- if (desc == null) {
- desc = getTransientCacheHandler().getTransientDescriptor(cname);
- if (desc == null) {
- return null;
- }
- }
- return new CoreDescriptor(cname, desc);
+ return cores.containsKey(name);
}
}
/** The core is currently loading, unloading, or reloading. */
- boolean hasPendingCoreOps(String name) {
+ protected boolean hasPendingCoreOps(String name) {
synchronized (modifyLock) {
return pendingCoreOps.contains(name);
}
}
// Wait here until any pending operations (load, unload or reload) are completed on this core.
- protected SolrCore waitAddPendingCoreOps(String name) {
+ public SolrCore waitAddPendingCoreOps(String name) {
// Keep multiple threads from operating on a core at one time.
synchronized (modifyLock) {
@@ -433,7 +370,7 @@ class SolrCores {
// We should always be removing the first thing in the list with our name! The idea here is to NOT
// do anything on any core while some other operation is working on that core.
- protected void removeFromPendingOps(String name) {
+ public void removeFromPendingOps(String name) {
synchronized (modifyLock) {
if (!pendingCoreOps.remove(name)) {
log.warn("Tried to remove core {} from pendingCoreOps and it wasn't there. ", name);
@@ -442,7 +379,7 @@ class SolrCores {
}
}
- protected Object getModifyLock() {
+ public Object getModifyLock() {
return modifyLock;
}
@@ -450,7 +387,7 @@ class SolrCores {
// opened or closed by another thread. So within this lock we'll walk along the list of pending
// closes until we find something NOT in the list of threads currently being loaded or reloaded.
// The "usual" case will probably return the very first one anyway.
- protected SolrCore getCoreToClose() {
+ public SolrCore getCoreToClose() {
synchronized (modifyLock) {
for (SolrCore core : pendingCloses) {
if (!pendingCoreOps.contains(core.getName())) {
@@ -472,11 +409,7 @@ class SolrCores {
*/
public CoreDescriptor getCoreDescriptor(String coreName) {
synchronized (modifyLock) {
- CoreDescriptor coreDescriptor = residentDescriptors.get(coreName);
- if (coreDescriptor != null) {
- return coreDescriptor;
- }
- return getTransientCacheHandler().getTransientDescriptor(coreName);
+ return residentDescriptors.get(coreName);
}
}
@@ -488,13 +421,7 @@ class SolrCores {
*/
public List<CoreDescriptor> getCoreDescriptors() {
synchronized (modifyLock) {
- Collection<CoreDescriptor> transientCoreDescriptors =
- getTransientCacheHandler().getTransientDescriptors();
- List<CoreDescriptor> coreDescriptors =
- new ArrayList<>(residentDescriptors.size() + transientCoreDescriptors.size());
- coreDescriptors.addAll(residentDescriptors.values());
- coreDescriptors.addAll(transientCoreDescriptors);
- return coreDescriptors;
+ return new ArrayList<>(residentDescriptors.values());
}
}
@@ -560,18 +487,4 @@ class SolrCores {
modifyLock.notifyAll(); // Wakes up closer thread too
}
}
-
- /**
- * @return the cache holding the transient cores; never null.
- */
- public TransientSolrCoreCache getTransientCacheHandler() {
- synchronized (modifyLock) {
- if (transientSolrCoreCacheFactory == null) {
- throw new SolrException(
- SolrException.ErrorCode.SERVER_ERROR,
- getClass().getName() + " not loaded; call load() before using it");
- }
- return transientSolrCoreCacheFactory.getTransientSolrCoreCache();
- }
- }
}
diff --git a/solr/core/src/java/org/apache/solr/core/SolrXmlConfig.java b/solr/core/src/java/org/apache/solr/core/SolrXmlConfig.java
index 647c9c71019..77c7adb67e0 100644
--- a/solr/core/src/java/org/apache/solr/core/SolrXmlConfig.java
+++ b/solr/core/src/java/org/apache/solr/core/SolrXmlConfig.java
@@ -168,8 +168,6 @@ public class SolrXmlConfig {
configBuilder.setSolrResourceLoader(loader);
configBuilder.setUpdateShardHandlerConfig(updateConfig);
configBuilder.setShardHandlerFactoryConfig(getPluginInfo(root.get("shardHandlerFactory")));
- configBuilder.setSolrCoreCacheFactoryConfig(
- getPluginInfo(root.get("transientCoreCacheFactory")));
configBuilder.setTracerConfig(getPluginInfo(root.get("tracerConfig")));
configBuilder.setLogWatcherConfig(loadLogWatcherConfig(root.get("logging")));
configBuilder.setSolrProperties(loadProperties(root, substituteProperties));
@@ -380,6 +378,7 @@ public class SolrXmlConfig {
builder.setReplayUpdatesThreads(it.intVal(-1));
break;
case "transientCacheSize":
+ log.warn("solr.xml transientCacheSize -- transient cores is deprecated");
builder.setTransientCacheSize(it.intVal(-1));
break;
case "allowUrls":
diff --git a/solr/core/src/java/org/apache/solr/core/TransientSolrCoreCache.java b/solr/core/src/java/org/apache/solr/core/TransientSolrCoreCache.java
index 85d941c44af..e0119635eda 100644
--- a/solr/core/src/java/org/apache/solr/core/TransientSolrCoreCache.java
+++ b/solr/core/src/java/org/apache/solr/core/TransientSolrCoreCache.java
@@ -25,19 +25,13 @@ import java.util.Set;
* control of transient caches (i.e. any core defined with transient=true) should override this
* class.
*
- * <p>Register your plugin in solr.xml similarly to:
- *
- * <p><transientCoreCacheFactory name="transientCoreCacheFactory"
- * class="TransientSolrCoreCacheFactoryDefault"> <int
- * name="transientCacheSize">4</int> </transientCoreCacheFactory>
- *
* <p>WARNING: There is quite a bit of higher-level locking done by the CoreContainer to avoid
* various race conditions etc. You should _only_ manipulate them within the method calls designed
* to change them. E.g. only add to the transient core descriptors in addTransientDescriptor etc.
*
* <p>Trust the higher-level code (mainly SolrCores and CoreContainer) to call the appropriate
* operations when necessary and to coordinate shutting down cores, manipulating the internal
- * structures and the like..
+ * structures and the like.
*
* <p>The only real action you should _initiate_ is to close a core for whatever reason, and do that
* by calling notifyCoreCloseListener(coreToClose); The observer will call back to removeCore(name)
@@ -60,11 +54,9 @@ import java.util.Set;
* <p>In particular, DO NOT reach into the transientCores structure from a method called to
* manipulate core descriptors or vice-versa.
*/
+@Deprecated(since = "9.2")
public abstract class TransientSolrCoreCache {
- /** Gets the core container that encloses this cache. */
- public abstract CoreContainer getContainer();
-
/** Adds the newly-opened core to the list of open cores. */
public abstract SolrCore addCore(String name, SolrCore core);
@@ -86,12 +78,6 @@ public abstract class TransientSolrCoreCache {
/** Returns whether the cache contains the named core. */
public abstract boolean containsCore(String name);
- /**
- * This method will be called when the container is to be shut down. It returns all transient solr
- * cores and clear any internal structures that hold them.
- */
- public abstract Collection<SolrCore> prepareForShutdown();
-
// These methods allow the implementation to maintain control over the core descriptors.
/**
diff --git a/solr/core/src/java/org/apache/solr/core/TransientSolrCoreCacheDefault.java b/solr/core/src/java/org/apache/solr/core/TransientSolrCoreCacheDefault.java
index 9754074bb79..2c5ee34e9e7 100644
--- a/solr/core/src/java/org/apache/solr/core/TransientSolrCoreCacheDefault.java
+++ b/solr/core/src/java/org/apache/solr/core/TransientSolrCoreCacheDefault.java
@@ -20,14 +20,11 @@ package org.apache.solr.core;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import java.lang.invoke.MethodHandles;
-import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
-import java.util.List;
import java.util.Map;
import java.util.Set;
-import org.apache.solr.common.util.NamedList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -35,11 +32,15 @@ import org.slf4j.LoggerFactory;
* Cache of the most frequently accessed transient cores. Keeps track of all the registered
* transient cores descriptors, including the cores in the cache as well as all the others.
*/
+@Deprecated(since = "9.2")
public class TransientSolrCoreCacheDefault extends TransientSolrCoreCache {
+ // TODO move into TransientSolrCores; remove TransientSolrCoreCache base/abstraction.
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+ public static final int DEFAULT_TRANSIENT_CACHE_SIZE = Integer.MAX_VALUE;
+ public static final String TRANSIENT_CACHE_SIZE = "transientCacheSize";
- protected final CoreContainer coreContainer;
+ private final TransientSolrCores solrCores;
/**
* "Lazily loaded" cores cache with limited size. When the max size is reached, the least accessed
@@ -53,12 +54,8 @@ public class TransientSolrCoreCacheDefault extends TransientSolrCoreCache {
*/
protected final Map<String, CoreDescriptor> transientDescriptors;
- /**
- * @param coreContainer The enclosing {@link CoreContainer}.
- */
- public TransientSolrCoreCacheDefault(CoreContainer coreContainer) {
- this.coreContainer = coreContainer;
- int cacheMaxSize = getConfiguredCacheMaxSize(coreContainer);
+ public TransientSolrCoreCacheDefault(TransientSolrCores solrCores, int cacheMaxSize) {
+ this.solrCores = solrCores;
// Now don't allow ridiculous allocations here, if the size is > 1,000, we'll just deal with
// adding cores as they're opened. This blows up with the marker value of -1.
@@ -89,7 +86,6 @@ public class TransientSolrCoreCacheDefault extends TransientSolrCoreCache {
}
private void onEvict(SolrCore core) {
- final SolrCores solrCores = coreContainer.solrCores;
assert Thread.holdsLock(solrCores.getModifyLock());
// note: the cache's maximum size isn't strictly enforced; it can grow some if we un-evict
if (solrCores.hasPendingCoreOps(core.getName())) {
@@ -119,38 +115,10 @@ public class TransientSolrCoreCacheDefault extends TransientSolrCoreCache {
}
}
- private int getConfiguredCacheMaxSize(CoreContainer container) {
- int configuredCacheMaxSize = NodeConfig.NodeConfigBuilder.DEFAULT_TRANSIENT_CACHE_SIZE;
- NodeConfig cfg = container.getNodeConfig();
- if (cfg.getTransientCachePluginInfo() == null) {
- // Still handle just having transientCacheSize defined in the body of solr.xml
- // not in a transient handler clause.
- configuredCacheMaxSize = cfg.getTransientCacheSize();
- } else {
- NamedList<?> args = cfg.getTransientCachePluginInfo().initArgs;
- Object obj = args.get("transientCacheSize");
- if (obj != null) {
- configuredCacheMaxSize = (int) obj;
- }
- }
- if (configuredCacheMaxSize < 0) { // Trap old flag
- configuredCacheMaxSize = Integer.MAX_VALUE;
- }
- return configuredCacheMaxSize;
- }
-
@Override
- public Collection<SolrCore> prepareForShutdown() {
- // Return a copy of the values.
- List<SolrCore> ret = new ArrayList<>(transientCores.asMap().values());
+ public void close() {
transientCores.invalidateAll();
transientCores.cleanUp();
- return ret;
- }
-
- @Override
- public CoreContainer getContainer() {
- return coreContainer;
}
@Override
diff --git a/solr/core/src/java/org/apache/solr/core/TransientSolrCoreCacheFactory.java b/solr/core/src/java/org/apache/solr/core/TransientSolrCoreCacheFactory.java
deleted file mode 100644
index e3ce7ee7411..00000000000
--- a/solr/core/src/java/org/apache/solr/core/TransientSolrCoreCacheFactory.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.core;
-
-import com.google.common.collect.ImmutableMap;
-import java.lang.invoke.MethodHandles;
-import java.util.Collections;
-import org.apache.solr.common.SolrException;
-import org.apache.solr.util.plugin.PluginInfoInitialized;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * An interface that allows custom transient caches to be maintained with different implementations
- */
-public abstract class TransientSolrCoreCacheFactory {
- private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
-
- private volatile CoreContainer coreContainer = null;
-
- /**
- * @return the cache holding the transient cores; never null.
- */
- public abstract TransientSolrCoreCache getTransientSolrCoreCache();
- /**
- * Create a new TransientSolrCoreCacheFactory instance
- *
- * @param loader a SolrResourceLoader used to find the TransientSolrCacheFactory classes
- * @param coreContainer CoreContainer that encloses all the Solr cores.
- * @return a new, initialized TransientSolrCoreCache instance
- */
- public static TransientSolrCoreCacheFactory newInstance(
- SolrResourceLoader loader, CoreContainer coreContainer) {
- PluginInfo info = coreContainer.getConfig().getTransientCachePluginInfo();
- if (info == null) { // definition not in our solr.xml file, use default
- info = DEFAULT_TRANSIENT_SOLR_CACHE_INFO;
- }
-
- try {
- // According to the docs, this returns a TransientSolrCoreCacheFactory with the default c'tor
- TransientSolrCoreCacheFactory tccf =
- loader
- .findClass(info.className, TransientSolrCoreCacheFactory.class)
- .getConstructor()
- .newInstance();
-
- // OK, now we call its init method.
- if (PluginInfoInitialized.class.isAssignableFrom(tccf.getClass()))
- PluginInfoInitialized.class.cast(tccf).init(info);
- tccf.setCoreContainer(coreContainer);
- return tccf;
- } catch (Exception e) {
- // Many things could cause this, bad solrconfig, mis-typed class name, whatever.
- // Throw an exception to stop loading here; never return null.
- throw new SolrException(
- SolrException.ErrorCode.SERVER_ERROR,
- "Error instantiating "
- + TransientSolrCoreCacheFactory.class.getName()
- + " class ["
- + info.className
- + "]",
- e);
- }
- }
-
- public static final PluginInfo DEFAULT_TRANSIENT_SOLR_CACHE_INFO =
- new PluginInfo(
- "transientSolrCoreCacheFactory",
- ImmutableMap.of(
- "class",
- TransientSolrCoreCacheFactoryDefault.class.getName(),
- "name",
- TransientSolrCoreCacheFactory.class.getName()),
- null,
- Collections.<PluginInfo>emptyList());
-
- // Need this because the plugin framework doesn't require a PluginINfo in the init method, don't
- // see a way to pass additional parameters and we need this when we create the transient core
- // cache, it's _really_ important.
- public void setCoreContainer(CoreContainer coreContainer) {
- this.coreContainer = coreContainer;
- }
-
- public CoreContainer getCoreContainer() {
- return coreContainer;
- }
-}
diff --git a/solr/core/src/java/org/apache/solr/core/TransientSolrCoreCacheFactoryDefault.java b/solr/core/src/java/org/apache/solr/core/TransientSolrCoreCacheFactoryDefault.java
deleted file mode 100644
index 0d564836fef..00000000000
--- a/solr/core/src/java/org/apache/solr/core/TransientSolrCoreCacheFactoryDefault.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.core;
-
-public class TransientSolrCoreCacheFactoryDefault extends TransientSolrCoreCacheFactory {
-
- volatile TransientSolrCoreCache transientSolrCoreCache = null;
-
- @Override
- public TransientSolrCoreCache getTransientSolrCoreCache() {
- if (transientSolrCoreCache == null) {
- transientSolrCoreCache = new TransientSolrCoreCacheDefault(getCoreContainer());
- }
-
- return transientSolrCoreCache;
- }
-}
diff --git a/solr/core/src/java/org/apache/solr/core/TransientSolrCores.java b/solr/core/src/java/org/apache/solr/core/TransientSolrCores.java
new file mode 100644
index 00000000000..2b50b2d81e3
--- /dev/null
+++ b/solr/core/src/java/org/apache/solr/core/TransientSolrCores.java
@@ -0,0 +1,173 @@
+/*
+ * 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 java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+
+/** A {@link SolrCores} that supports {@link CoreDescriptor#isTransient()}. */
+@Deprecated(since = "9.2")
+public class TransientSolrCores extends SolrCores {
+
+ protected final TransientSolrCoreCache transientSolrCoreCache;
+
+ public TransientSolrCores(CoreContainer container, int cacheSize) {
+ super(container);
+ transientSolrCoreCache = new TransientSolrCoreCacheDefault(this, cacheSize);
+ }
+
+ @Override
+ protected void close() {
+ super.close();
+ transientSolrCoreCache.close();
+ }
+
+ @Override
+ public void addCoreDescriptor(CoreDescriptor p) {
+ if (p.isTransient()) {
+ synchronized (modifyLock) {
+ transientSolrCoreCache.addTransientDescriptor(p.getName(), p);
+ }
+ } else {
+ super.addCoreDescriptor(p);
+ }
+ }
+
+ @Override
+ public void removeCoreDescriptor(CoreDescriptor p) {
+ if (p.isTransient()) {
+ synchronized (modifyLock) {
+ transientSolrCoreCache.removeTransientDescriptor(p.getName());
+ }
+ } else {
+ super.removeCoreDescriptor(p);
+ }
+ }
+
+ @Override
+ // Returns the old core if there was a core of the same name.
+ // WARNING! This should be the _only_ place you put anything into the list of transient cores!
+ public SolrCore putCore(CoreDescriptor cd, SolrCore core) {
+ if (cd.isTransient()) {
+ synchronized (modifyLock) {
+ addCoreDescriptor(cd); // cd must always be registered if we register a core
+ return transientSolrCoreCache.addCore(cd.getName(), core);
+ }
+ } else {
+ return super.putCore(cd, core);
+ }
+ }
+
+ @Override
+ public List<String> getLoadedCoreNames() {
+ synchronized (modifyLock) {
+ List<String> coreNames = super.getLoadedCoreNames(); // mutable
+ coreNames.addAll(transientSolrCoreCache.getLoadedCoreNames());
+ assert isSet(coreNames);
+ return coreNames;
+ }
+ }
+
+ @Override
+ public List<String> getAllCoreNames() {
+ synchronized (modifyLock) {
+ List<String> coreNames = super.getAllCoreNames(); // mutable
+ coreNames.addAll(transientSolrCoreCache.getAllCoreNames());
+ assert isSet(coreNames);
+ return coreNames;
+ }
+ }
+
+ private static boolean isSet(Collection<?> collection) {
+ return collection.size() == new HashSet<>(collection).size();
+ }
+
+ @Override
+ public int getNumLoadedTransientCores() {
+ synchronized (modifyLock) {
+ return transientSolrCoreCache.getLoadedCoreNames().size();
+ }
+ }
+
+ @Override
+ public int getNumUnloadedCores() {
+ synchronized (modifyLock) {
+ return super.getNumUnloadedCores()
+ + transientSolrCoreCache.getAllCoreNames().size()
+ - transientSolrCoreCache.getLoadedCoreNames().size();
+ }
+ }
+
+ @Override
+ public int getNumAllCores() {
+ synchronized (modifyLock) {
+ return super.getNumAllCores() + transientSolrCoreCache.getAllCoreNames().size();
+ }
+ }
+
+ @Override
+ public SolrCore remove(String name) {
+ synchronized (modifyLock) {
+ SolrCore ret = super.remove(name);
+ // It could have been a newly-created core. It could have been a transient core. The
+ // newly-created cores in particular should be checked. It could have been a dynamic core.
+ if (ret == null) {
+ ret = transientSolrCoreCache.removeCore(name);
+ }
+ return ret;
+ }
+ }
+
+ @Override
+ protected SolrCore getLoadedCoreWithoutIncrement(String name) {
+ synchronized (modifyLock) {
+ final var core = super.getLoadedCoreWithoutIncrement(name);
+ return core != null ? core : transientSolrCoreCache.getCore(name);
+ }
+ }
+
+ @Override
+ public boolean isLoaded(String name) {
+ synchronized (modifyLock) {
+ return super.isLoaded(name) || transientSolrCoreCache.containsCore(name);
+ }
+ }
+
+ @Override
+ public CoreDescriptor getCoreDescriptor(String coreName) {
+ synchronized (modifyLock) {
+ CoreDescriptor coreDescriptor = super.getCoreDescriptor(coreName);
+ if (coreDescriptor != null) {
+ return coreDescriptor;
+ }
+ return transientSolrCoreCache.getTransientDescriptor(coreName);
+ }
+ }
+
+ @Override
+ public List<CoreDescriptor> getCoreDescriptors() {
+ synchronized (modifyLock) {
+ List<CoreDescriptor> coreDescriptors = new ArrayList<>(getNumAllCores());
+ coreDescriptors.addAll(super.getCoreDescriptors());
+ coreDescriptors.addAll(transientSolrCoreCache.getTransientDescriptors());
+ return coreDescriptors;
+ }
+ }
+}
diff --git a/solr/core/src/java/org/apache/solr/handler/admin/CoreAdminOperation.java b/solr/core/src/java/org/apache/solr/handler/admin/CoreAdminOperation.java
index e2a4643d77e..096476e2efa 100644
--- a/solr/core/src/java/org/apache/solr/handler/admin/CoreAdminOperation.java
+++ b/solr/core/src/java/org/apache/solr/handler/admin/CoreAdminOperation.java
@@ -340,7 +340,7 @@ public enum CoreAdminOperation implements CoreAdminOp {
} else {
if (!cores.isLoaded(cname)) { // Lazily-loaded core, fill in what we can.
// It would be a real mistake to load the cores just to get the status
- CoreDescriptor desc = cores.getUnloadedCoreDescriptor(cname);
+ CoreDescriptor desc = cores.getCoreDescriptor(cname);
if (desc != null) {
info.add(NAME, desc.getName());
info.add("instanceDir", desc.getInstanceDir());
diff --git a/solr/core/src/test-files/solr/solr-transientCores.xml b/solr/core/src/test-files/solr/solr-transientCores.xml
new file mode 100644
index 00000000000..4ab0f389938
--- /dev/null
+++ b/solr/core/src/test-files/solr/solr-transientCores.xml
@@ -0,0 +1,20 @@
+<!--
+ ~ 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.
+ -->
+
+<solr>
+ <int name="transientCacheSize">4</int>
+</solr>
\ No newline at end of file
diff --git a/solr/core/src/test-files/solr/solr.xml b/solr/core/src/test-files/solr/solr.xml
index 735388f638c..439c8defdba 100644
--- a/solr/core/src/test-files/solr/solr.xml
+++ b/solr/core/src/test-files/solr/solr.xml
@@ -35,11 +35,6 @@
<int name="connTimeout">${connTimeout:15000}</int>
</shardHandlerFactory>
- <transientCoreCacheFactory name="transientCoreCacheFactory" class="TransientSolrCoreCacheFactoryDefault">
- <int name="transientCacheSize">4</int>
- </transientCoreCacheFactory>
-
-
<solrcloud>
<str name="host">127.0.0.1</str>
<int name="hostPort">${hostPort:8983}</int>
diff --git a/solr/core/src/test/org/apache/solr/core/TestLazyCores.java b/solr/core/src/test/org/apache/solr/core/TestLazyCores.java
index b9bce3df267..a94d806279f 100644
--- a/solr/core/src/test/org/apache/solr/core/TestLazyCores.java
+++ b/solr/core/src/test/org/apache/solr/core/TestLazyCores.java
@@ -53,7 +53,7 @@ import org.junit.Test;
public class TestLazyCores extends SolrTestCaseJ4 {
- /** Transient core cache max size defined in the test solr.xml */
+ /** Transient core cache max size defined in the test solr-transientCores.xml */
private static final int TRANSIENT_CORE_CACHE_MAX_SIZE = 4;
private File solrHomeDirectory;
@@ -97,7 +97,7 @@ public class TestLazyCores extends SolrTestCaseJ4 {
private CoreContainer init() throws Exception {
solrHomeDirectory = createTempDir().toFile();
- copyXmlToHome(solrHomeDirectory.getAbsoluteFile(), "solr.xml");
+ copyXmlToHome(solrHomeDirectory.getAbsoluteFile(), "solr-transientCores.xml");
for (int idx = 1; idx < 10; ++idx) {
copyMinConf(new File(solrHomeDirectory, "collection" + idx));
}
@@ -108,7 +108,7 @@ public class TestLazyCores extends SolrTestCaseJ4 {
private CoreContainer initEmpty() throws IOException {
solrHomeDirectory = createTempDir().toFile();
- copyXmlToHome(solrHomeDirectory.getAbsoluteFile(), "solr.xml");
+ copyXmlToHome(solrHomeDirectory.getAbsoluteFile(), "solr-transientCores.xml");
NodeConfig cfg = NodeConfig.loadNodeConfig(solrHomeDirectory.toPath(), null);
return createCoreContainer(
cfg,
diff --git a/solr/core/src/test/org/apache/solr/core/TestSolrXml.java b/solr/core/src/test/org/apache/solr/core/TestSolrXml.java
index 7379cc906bb..9cdc5b1a253 100644
--- a/solr/core/src/test/org/apache/solr/core/TestSolrXml.java
+++ b/solr/core/src/test/org/apache/solr/core/TestSolrXml.java
@@ -172,20 +172,29 @@ public class TestSolrXml extends SolrTestCaseJ4 {
public void testIntAsLongBad() {
String bad = "" + TestUtil.nextLong(random(), Integer.MAX_VALUE, Long.MAX_VALUE);
- String solrXml = "<solr><long name=\"transientCacheSize\">" + bad + "</long></solr>";
-
+ String solrXml =
+ "<solr><updateshardhandler>"
+ + "<long name=\"maxUpdateConnections\">"
+ + bad
+ + "</long>"
+ + "</updateshardhandler></solr>";
SolrException thrown =
assertThrows(SolrException.class, () -> SolrXmlConfig.fromString(solrHome, solrXml));
assertEquals(
- "Error parsing 'transientCacheSize', value '" + bad + "' cannot be parsed",
+ "Error parsing 'maxUpdateConnections', value '" + bad + "' cannot be parsed as int",
thrown.getMessage());
}
public void testIntAsLongOk() {
int ok = random().nextInt();
- String solrXml = "<solr><long name=\"transientCacheSize\">" + ok + "</long></solr>";
+ String solrXml =
+ "<solr><updateshardhandler>"
+ + "<long name=\"maxUpdateConnections\">"
+ + ok
+ + "</long>"
+ + "</updateshardhandler></solr>";
NodeConfig cfg = SolrXmlConfig.fromString(solrHome, solrXml);
- assertEquals(ok, cfg.getTransientCacheSize());
+ assertEquals(ok, cfg.getUpdateShardHandlerConfig().getMaxUpdateConnections());
}
public void testMultiCloudSectionError() {
diff --git a/solr/core/src/test/org/apache/solr/metrics/SolrMetricsIntegrationTest.java b/solr/core/src/test/org/apache/solr/metrics/SolrMetricsIntegrationTest.java
index 1010697676c..25cc82c0bb2 100644
--- a/solr/core/src/test/org/apache/solr/metrics/SolrMetricsIntegrationTest.java
+++ b/solr/core/src/test/org/apache/solr/metrics/SolrMetricsIntegrationTest.java
@@ -146,11 +146,9 @@ public class SolrMetricsIntegrationTest extends SolrTestCaseJ4 {
Gauge<?> gauge = (Gauge<?>) coreMetricManager.getRegistry().getMetrics().get("CORE.indexDir");
assertNotNull(gauge.getValue());
- h.getCore().close();
+ deleteCore(); // closes TestHarness which closes CoreContainer which closes SolrCore
assertEquals(metricManager.nullString(), gauge.getValue());
- deleteCore();
-
for (String reporterName : RENAMED_REPORTERS) {
SolrMetricReporter reporter = reporters.get(reporterName + "@" + tag);
MockMetricReporter mockReporter = (MockMetricReporter) reporter;
diff --git a/solr/solr-ref-guide/modules/configuration-guide/pages/configuring-solr-xml.adoc b/solr/solr-ref-guide/modules/configuration-guide/pages/configuring-solr-xml.adoc
index d75e89322b7..1a6fd121f11 100644
--- a/solr/solr-ref-guide/modules/configuration-guide/pages/configuring-solr-xml.adoc
+++ b/solr/solr-ref-guide/modules/configuration-guide/pages/configuring-solr-xml.adoc
@@ -267,7 +267,8 @@ If you use this feature, make sure that no core-specific property is used in you
|Optional |Default: none
|===
+
-Defines how many cores with `transient=true` that can be loaded before swapping the least recently used core for a new core.
+*Deprecated as of 9.2.*
+Defines how many Solr cores with `transient=true` that can be loaded before unloading an unused core for one that is needed.
`configSetBaseDir`::
+
diff --git a/solr/solr-ref-guide/modules/upgrade-notes/pages/major-changes-in-solr-9.adoc b/solr/solr-ref-guide/modules/upgrade-notes/pages/major-changes-in-solr-9.adoc
index bc2bbc7326a..faaf0991443 100644
--- a/solr/solr-ref-guide/modules/upgrade-notes/pages/major-changes-in-solr-9.adoc
+++ b/solr/solr-ref-guide/modules/upgrade-notes/pages/major-changes-in-solr-9.adoc
@@ -69,6 +69,7 @@ Due to changes in Lucene 9, that isn't possible any more.
* Solr no longer duplicates certain Jetty "server" library dependencies between `server/lib` and `WEB-INF/lib` (jetty-util, jetty-io, etc.).
This is an improvement to the binary release artifact, but Jetty does not allow web-apps (Solr) to share these libraries by default.
The `server/contexts/solr-jetty-context.xml` now explicitly removes these restrictions, allowing Solr to share these "server" jars which now live in `server/lib/ext`.
+* The "Transient Cores" feature is now deprecated.
=== Tracing
* A new `opentelemetry` module is added, with support for OTEL tracing in `OTLP` format using gRPC.
diff --git a/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java b/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java
index 6ae2eb76a2e..fe81cb7e5af 100644
--- a/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java
+++ b/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java
@@ -931,7 +931,7 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
// If the test case set up Zk, it should still have it as available,
// otherwise the core close will just be unnecessarily delayed.
CoreContainer cc = h.getCoreContainer();
- if (!cc.getCores().isEmpty() && cc.isZooKeeperAware()) {
+ if (cc.getNumAllCores() > 0 && cc.isZooKeeperAware()) {
try {
cc.getZkController().getZkClient().exists("/", false);
} catch (KeeperException e) {