SOLR-14151: Bug fixes (#1815)

This commit is contained in:
Noble Paul 2020-09-08 09:58:42 +10:00 committed by GitHub
parent e2003029e3
commit 95ab98c920
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 92 additions and 32 deletions

View File

@ -26,6 +26,7 @@ import java.nio.file.Path;
import org.apache.solr.common.SolrException.ErrorCode; import org.apache.solr.common.SolrException.ErrorCode;
import org.apache.solr.common.cloud.ZkConfigManager; import org.apache.solr.common.cloud.ZkConfigManager;
import org.apache.solr.common.cloud.ZooKeeperException; import org.apache.solr.common.cloud.ZooKeeperException;
import org.apache.solr.core.CoreContainer;
import org.apache.solr.core.SolrResourceLoader; import org.apache.solr.core.SolrResourceLoader;
import org.apache.solr.core.SolrResourceNotFoundException; import org.apache.solr.core.SolrResourceNotFoundException;
import org.apache.solr.schema.ZkIndexSchemaReader; import org.apache.solr.schema.ZkIndexSchemaReader;
@ -157,4 +158,9 @@ public class ZkSolrResourceLoader extends SolrResourceLoader {
} }
public ZkIndexSchemaReader getZkIndexSchemaReader() { return zkIndexSchemaReader; } public ZkIndexSchemaReader getZkIndexSchemaReader() { return zkIndexSchemaReader; }
@Override
public CoreContainer getCoreContainer() {
return zkController.getCoreContainer();
}
} }

View File

@ -81,8 +81,7 @@ public abstract class ConfigSetService {
) ? false: true; ) ? false: true;
SolrConfig solrConfig = createSolrConfig(dcore, coreLoader, trusted); SolrConfig solrConfig = createSolrConfig(dcore, coreLoader, trusted);
IndexSchema indexSchema = createIndexSchema(dcore, solrConfig, false); return new ConfigSet(configSetName(dcore), solrConfig, force -> createIndexSchema(dcore, solrConfig, force), properties, trusted);
return new ConfigSet(configSetName(dcore), solrConfig, force -> indexSchema, properties, trusted);
} catch (Exception e) { } catch (Exception e) {
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
"Could not load conf for core " + dcore.getName() + "Could not load conf for core " + dcore.getName() +

View File

@ -1582,6 +1582,13 @@ public class CoreContainer {
public void reload(String name) { public void reload(String name) {
reload(name, null); reload(name, null);
} }
public void reload(String name, UUID coreId, boolean async) {
if(async) {
runAsync(() -> reload(name, coreId));
} else {
reload(name, coreId);
}
}
/** /**
* Recreates a SolrCore. * Recreates a SolrCore.
* While the new core is loading, requests will continue to be dispatched to * While the new core is loading, requests will continue to be dispatched to
@ -1596,13 +1603,8 @@ public class CoreContainer {
throw new AlreadyClosedException(); throw new AlreadyClosedException();
} }
SolrCore newCore = null; SolrCore newCore = null;
SolrCore core = solrCores.getCoreFromAnyList(name, false); SolrCore core = solrCores.getCoreFromAnyList(name, false, coreId);
if (core != null) { if (core != null) {
if(coreId != null && core.uniqueId != coreId) {
//trying to reload an already unloaded core
return;
}
// The underlying core properties files may have changed, we don't really know. So we have a (perhaps) stale // The underlying core properties files may have changed, we don't really know. So we have a (perhaps) stale
// CoreDescriptor and we need to reload it from the disk files // CoreDescriptor and we need to reload it from the disk files
CoreDescriptor cd = reloadCoreDescriptor(core.getCoreDescriptor()); CoreDescriptor cd = reloadCoreDescriptor(core.getCoreDescriptor());
@ -1832,6 +1834,9 @@ public class CoreContainer {
return cfg.getCoreRootDirectory(); return cfg.getCoreRootDirectory();
} }
public SolrCore getCore(String name) {
return getCore(name, null);
}
/** /**
* Gets a core by name and increase its refcount. * Gets a core by name and increase its refcount.
* *
@ -1840,10 +1845,10 @@ public class CoreContainer {
* @throws SolrCoreInitializationException if a SolrCore with this name failed to be initialized * @throws SolrCoreInitializationException if a SolrCore with this name failed to be initialized
* @see SolrCore#close() * @see SolrCore#close()
*/ */
public SolrCore getCore(String name) { public SolrCore getCore(String name, UUID id) {
// Do this in two phases since we don't want to lock access to the cores over a load. // Do this in two phases since we don't want to lock access to the cores over a load.
SolrCore core = solrCores.getCoreFromAnyList(name, true); SolrCore core = solrCores.getCoreFromAnyList(name, true, id);
// If a core is loaded, we're done just return it. // If a core is loaded, we're done just return it.
if (core != null) { if (core != null) {

View File

@ -225,8 +225,8 @@ public final class SolrCore implements SolrInfoBean, Closeable {
private final RecoveryStrategy.Builder recoveryStrategyBuilder; private final RecoveryStrategy.Builder recoveryStrategyBuilder;
private IndexReaderFactory indexReaderFactory; private IndexReaderFactory indexReaderFactory;
private final Codec codec; private final Codec codec;
private final ConfigSet configSet;
//singleton listener for all packages used in schema //singleton listener for all packages used in schema
private final PackageListeningClassLoader schemaPluginsLoader;
private final CircuitBreakerManager circuitBreakerManager; private final CircuitBreakerManager circuitBreakerManager;
@ -273,9 +273,6 @@ public final class SolrCore implements SolrInfoBean, Closeable {
public PackageListeners getPackageListeners() { public PackageListeners getPackageListeners() {
return packageListeners; return packageListeners;
} }
public PackageListeningClassLoader getSchemaPluginsLoader() {
return schemaPluginsLoader;
}
static int boolean_query_max_clause_count = Integer.MIN_VALUE; static int boolean_query_max_clause_count = Integer.MIN_VALUE;
@ -939,15 +936,12 @@ public final class SolrCore implements SolrInfoBean, Closeable {
final CountDownLatch latch = new CountDownLatch(1); final CountDownLatch latch = new CountDownLatch(1);
try { try {
this.coreContainer = coreContainer; this.coreContainer = coreContainer;
this.configSet = configSet;
this.coreDescriptor = Objects.requireNonNull(coreDescriptor, "coreDescriptor cannot be null"); this.coreDescriptor = Objects.requireNonNull(coreDescriptor, "coreDescriptor cannot be null");
setName(coreDescriptor.getName()); setName(coreDescriptor.getName());
this.solrConfig = configSet.getSolrConfig(); this.solrConfig = configSet.getSolrConfig();
this.resourceLoader = configSet.getSolrConfig().getResourceLoader(); this.resourceLoader = configSet.getSolrConfig().getResourceLoader();
schemaPluginsLoader = new PackageListeningClassLoader(coreContainer, resourceLoader,
solrConfig::maxPackageVersion,
() -> setLatestSchema(configSet.getIndexSchema()));
this.packageListeners.addListener(schemaPluginsLoader);
IndexSchema schema = configSet.getIndexSchema(); IndexSchema schema = configSet.getIndexSchema();
this.configSetProperties = configSet.getProperties(); this.configSetProperties = configSet.getProperties();
@ -2768,7 +2762,10 @@ public final class SolrCore implements SolrInfoBean, Closeable {
}; };
} }
public void fetchLatestSchema() {
IndexSchema schema = configSet.getIndexSchema(true);
setLatestSchema(schema);
}
public interface RawWriter { public interface RawWriter {
default String getContentType() { default String getContentType() {
return BinaryResponseParser.BINARY_CONTENT_TYPE; return BinaryResponseParser.BINARY_CONTENT_TYPE;
@ -3076,7 +3073,7 @@ public final class SolrCore implements SolrInfoBean, Closeable {
SolrZkClient zkClient = cc.getZkController().getZkClient(); SolrZkClient zkClient = cc.getZkController().getZkClient();
int solrConfigversion, overlayVersion, managedSchemaVersion = 0; int solrConfigversion, overlayVersion, managedSchemaVersion = 0;
SolrConfig cfg = null; SolrConfig cfg = null;
try (SolrCore solrCore = cc.solrCores.getCoreFromAnyList(coreName, true)) { try (SolrCore solrCore = cc.solrCores.getCoreFromAnyList(coreName, true, coreId)) {
if (solrCore == null || solrCore.isClosed() || solrCore.getCoreContainer().isShutDown()) return; if (solrCore == null || solrCore.isClosed() || solrCore.getCoreContainer().isShutDown()) return;
cfg = solrCore.getSolrConfig(); cfg = solrCore.getSolrConfig();
solrConfigversion = solrCore.getSolrConfig().getOverlay().getZnodeVersion(); solrConfigversion = solrCore.getSolrConfig().getOverlay().getZnodeVersion();
@ -3097,7 +3094,7 @@ public final class SolrCore implements SolrInfoBean, Closeable {
if (configHandler.getReloadLock().tryLock()) { if (configHandler.getReloadLock().tryLock()) {
try { try {
cc.reload(coreName, coreId); cc.reload(coreName, coreId, false);
} catch (SolrCoreState.CoreIsClosedException e) { } catch (SolrCoreState.CoreIsClosedException e) {
/*no problem this core is already closed*/ /*no problem this core is already closed*/
} finally { } finally {
@ -3110,7 +3107,7 @@ public final class SolrCore implements SolrInfoBean, Closeable {
return; return;
} }
//some files in conf directory may have other than managedschema, overlay, params //some files in conf directory may have other than managedschema, overlay, params
try (SolrCore solrCore = cc.solrCores.getCoreFromAnyList(coreName, true)) { try (SolrCore solrCore = cc.solrCores.getCoreFromAnyList(coreName, true, coreId)) {
if (solrCore == null || solrCore.isClosed() || cc.isShutDown()) return; if (solrCore == null || solrCore.isClosed() || cc.isShutDown()) return;
for (Runnable listener : solrCore.confListeners) { for (Runnable listener : solrCore.confListeners) {
try { try {

View File

@ -34,6 +34,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.TreeSet; import java.util.TreeSet;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -282,15 +283,19 @@ class SolrCores {
return ret; return ret;
} }
} }
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. */ /* If you don't increment the reference count, someone could close the core before you use it. */
SolrCore getCoreFromAnyList(String name, boolean incRefCount) { SolrCore getCoreFromAnyList(String name, boolean incRefCount, UUID coreId) {
synchronized (modifyLock) { synchronized (modifyLock) {
SolrCore core = cores.get(name); SolrCore core = cores.get(name);
if (core == null && getTransientCacheHandler() != null) { if (core == null && getTransientCacheHandler() != null) {
core = getTransientCacheHandler().getCore(name); core = getTransientCacheHandler().getCore(name);
} }
if(core != null && coreId != null && coreId != core.uniqueId) return null;
if (core != null && incRefCount) { if (core != null && incRefCount) {
core.open(); core.open();

View File

@ -46,6 +46,7 @@ import org.apache.solr.common.SolrException;
import org.apache.solr.common.cloud.SolrClassLoader; import org.apache.solr.common.cloud.SolrClassLoader;
import org.apache.solr.handler.component.SearchComponent; import org.apache.solr.handler.component.SearchComponent;
import org.apache.solr.handler.component.ShardHandlerFactory; import org.apache.solr.handler.component.ShardHandlerFactory;
import org.apache.solr.pkg.PackageListeningClassLoader;
import org.apache.solr.request.SolrRequestHandler; import org.apache.solr.request.SolrRequestHandler;
import org.apache.solr.response.QueryResponseWriter; import org.apache.solr.response.QueryResponseWriter;
import org.apache.solr.rest.RestManager; import org.apache.solr.rest.RestManager;
@ -61,7 +62,7 @@ import org.slf4j.LoggerFactory;
/** /**
* @since solr 1.3 * @since solr 1.3
*/ */
public class SolrResourceLoader implements ResourceLoader, Closeable, SolrClassLoader { public class SolrResourceLoader implements ResourceLoader, Closeable, SolrClassLoader, SolrCoreAware {
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
private static final String base = "org.apache.solr"; private static final String base = "org.apache.solr";
@ -76,6 +77,30 @@ public class SolrResourceLoader implements ResourceLoader, Closeable, SolrClassL
private String name = ""; private String name = "";
protected URLClassLoader classLoader; protected URLClassLoader classLoader;
private final Path instanceDir; private final Path instanceDir;
private String coreName;
private UUID coreId;
private SolrConfig config;
private CoreContainer coreContainer;
private PackageListeningClassLoader schemaLoader ;
private PackageListeningClassLoader createSchemaLoader() {
CoreContainer cc = getCoreContainer();
if (cc == null) {
//corecontainer not available . can't load from packages
return null;
}
return new PackageListeningClassLoader(cc, this, pkg -> {
if (getSolrConfig() == null) return null;
return getSolrConfig().maxPackageVersion(pkg);
}, () -> {
if(getCoreContainer() == null || config == null || coreName == null || coreId==null) return;
try (SolrCore c = getCoreContainer().getCore(coreName, coreId)) {
if (c != null) {
c.fetchLatestSchema();
}
}
});
}
@ -101,6 +126,13 @@ public class SolrResourceLoader implements ResourceLoader, Closeable, SolrClassL
return managedResourceRegistry; return managedResourceRegistry;
} }
public SolrClassLoader getSchemaLoader() {
if (schemaLoader == null) {
schemaLoader = createSchemaLoader();
}
return schemaLoader;
}
public SolrResourceLoader() { public SolrResourceLoader() {
this(SolrPaths.locateSolrHome(), null); this(SolrPaths.locateSolrHome(), null);
} }
@ -607,6 +639,12 @@ public class SolrResourceLoader implements ResourceLoader, Closeable, SolrClassL
* Tell all {@link SolrCoreAware} instances about the SolrCore * Tell all {@link SolrCoreAware} instances about the SolrCore
*/ */
public void inform(SolrCore core) { public void inform(SolrCore core) {
this.coreName = core.getName();
this.config = core.getSolrConfig();
this.coreId = core.uniqueId;
this.coreContainer = core.getCoreContainer();
if(getSchemaLoader() != null) core.getPackageListeners().addListener(schemaLoader);
// make a copy to avoid potential deadlock of a callback calling newInstance and trying to // make a copy to avoid potential deadlock of a callback calling newInstance and trying to
// add something to waitingForCore. // add something to waitingForCore.
SolrCoreAware[] arr; SolrCoreAware[] arr;
@ -745,6 +783,14 @@ public class SolrResourceLoader implements ResourceLoader, Closeable, SolrClassL
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, builder.toString()); throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, builder.toString());
} }
public CoreContainer getCoreContainer(){
return coreContainer;
}
public SolrConfig getSolrConfig() {
return config;
}
@Override @Override
public void close() throws IOException { public void close() throws IOException {
IOUtils.close(classLoader); IOUtils.close(classLoader);

View File

@ -909,7 +909,7 @@ public class IndexFetcher {
final CountDownLatch latch = new CountDownLatch(1); final CountDownLatch latch = new CountDownLatch(1);
new Thread(() -> { new Thread(() -> {
try { try {
solrCore.getCoreContainer().reload(solrCore.getName()); solrCore.getCoreContainer().reload(solrCore.getName(), solrCore.uniqueId);
} catch (Exception e) { } catch (Exception e) {
log.error("Could not reload core ", e); log.error("Could not reload core ", e);
} finally { } finally {

View File

@ -26,6 +26,7 @@ import org.apache.solr.api.ApiBag;
import org.apache.solr.cloud.ZkSolrResourceLoader; import org.apache.solr.cloud.ZkSolrResourceLoader;
import org.apache.solr.common.MapWriter; import org.apache.solr.common.MapWriter;
import org.apache.solr.common.SolrException; import org.apache.solr.common.SolrException;
import org.apache.solr.common.cloud.SolrClassLoader;
import org.apache.solr.common.params.MapSolrParams; import org.apache.solr.common.params.MapSolrParams;
import org.apache.solr.common.params.SolrParams; import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.NamedList; import org.apache.solr.common.util.NamedList;
@ -34,6 +35,7 @@ import org.apache.solr.common.util.StrUtils;
import org.apache.solr.common.util.Utils; import org.apache.solr.common.util.Utils;
import org.apache.solr.core.PluginInfo; import org.apache.solr.core.PluginInfo;
import org.apache.solr.core.SolrCore; import org.apache.solr.core.SolrCore;
import org.apache.solr.pkg.PackageListeningClassLoader;
import org.apache.solr.request.SolrQueryRequest; import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.request.SolrRequestHandler; import org.apache.solr.request.SolrRequestHandler;
import org.apache.solr.response.SolrQueryResponse; import org.apache.solr.response.SolrQueryResponse;
@ -225,7 +227,9 @@ public class SchemaHandler extends RequestHandlerBase implements SolrCoreAware,
String klas = (String) v; String klas = (String) v;
PluginInfo.ClassName parsedClassName = new PluginInfo.ClassName(klas); PluginInfo.ClassName parsedClassName = new PluginInfo.ClassName(klas);
if (parsedClassName.pkg != null) { if (parsedClassName.pkg != null) {
MapWriter mw = req.getCore().getSchemaPluginsLoader().getPackageVersion(parsedClassName); SolrClassLoader solrClassLoader = req.getCore().getLatestSchema().getSolrClassLoader();
MapWriter mw = solrClassLoader instanceof PackageListeningClassLoader ?
((PackageListeningClassLoader) solrClassLoader).getPackageVersion(parsedClassName) : null;
if (mw != null) nl.add("_packageinfo_", mw); if (mw != null) nl.add("_packageinfo_", mw);
} }
} }

View File

@ -547,7 +547,7 @@ public class SolrConfigHandler extends RequestHandlerBase implements SolrCoreAwa
latestVersion, 30); latestVersion, 30);
} else { } else {
SolrResourceLoader.persistConfLocally(loader, ConfigOverlay.RESOURCE_NAME, overlay.toByteArray()); SolrResourceLoader.persistConfLocally(loader, ConfigOverlay.RESOURCE_NAME, overlay.toByteArray());
req.getCore().getCoreContainer().reload(req.getCore().getName(), req.getCore().uniqueId); req.getCore().getCoreContainer().reload(req.getCore().getName(), req.getCore().uniqueId, false);
log.info("Executed config commands successfully and persisted to File System {}", ops); log.info("Executed config commands successfully and persisted to File System {}", ops);
} }

View File

@ -190,7 +190,7 @@ public class IndexSchema {
protected IndexSchema(Version luceneVersion, SolrResourceLoader loader, Properties substitutableProperties) { protected IndexSchema(Version luceneVersion, SolrResourceLoader loader, Properties substitutableProperties) {
this.luceneVersion = Objects.requireNonNull(luceneVersion); this.luceneVersion = Objects.requireNonNull(luceneVersion);
this.loader = loader; this.loader = loader;
this.solrClassLoader = loader;//loader.getCore() == null? loader: loader.getCore().getSchemaPluginsLoader(); this.solrClassLoader = loader.getSchemaLoader() == null ? loader : loader.getSchemaLoader();
this.substitutableProperties = substitutableProperties; this.substitutableProperties = substitutableProperties;
} }

View File

@ -132,7 +132,7 @@ public class SchemaManager {
latestVersion = ZkController.persistConfigResourceToZooKeeper latestVersion = ZkController.persistConfigResourceToZooKeeper
(zkLoader, managedIndexSchema.getSchemaZkVersion(), managedIndexSchema.getResourceName(), (zkLoader, managedIndexSchema.getSchemaZkVersion(), managedIndexSchema.getResourceName(),
sw.toString().getBytes(StandardCharsets.UTF_8), true); sw.toString().getBytes(StandardCharsets.UTF_8), true);
req.getCore().getCoreContainer().reload(req.getCore().getName(), req.getCore().uniqueId); req.getCore().getCoreContainer().reload(req.getCore().getName(), req.getCore().uniqueId, false);
break; break;
} catch (ZkController.ResourceModifiedInZkException e) { } catch (ZkController.ResourceModifiedInZkException e) {
log.info("Schema was modified by another node. Retrying.."); log.info("Schema was modified by another node. Retrying..");
@ -142,7 +142,7 @@ public class SchemaManager {
//only for non cloud stuff //only for non cloud stuff
managedIndexSchema.persistManagedSchema(false); managedIndexSchema.persistManagedSchema(false);
core.setLatestSchema(managedIndexSchema); core.setLatestSchema(managedIndexSchema);
core.getCoreContainer().reload(core.getName(), core.uniqueId); core.getCoreContainer().reload(core.getName(), core.uniqueId, false);
} catch (SolrException e) { } catch (SolrException e) {
log.warn(errorMsg); log.warn(errorMsg);
errors = singletonList(errorMsg + e.getMessage()); errors = singletonList(errorMsg + e.getMessage());

View File

@ -63,7 +63,6 @@ import org.apache.solr.util.plugin.SolrCoreAware;
import org.apache.zookeeper.data.Stat; import org.apache.zookeeper.data.Stat;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
import static org.apache.solr.common.cloud.ZkStateReader.SOLR_PKGS_PATH; import static org.apache.solr.common.cloud.ZkStateReader.SOLR_PKGS_PATH;
@ -640,7 +639,6 @@ public class TestPackages extends SolrCloudTestCase {
} }
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
@Ignore("SOLR-14750")
public void testSchemaPlugins() throws Exception { public void testSchemaPlugins() throws Exception {
String COLLECTION_NAME = "testSchemaLoadingColl"; String COLLECTION_NAME = "testSchemaLoadingColl";
System.setProperty("managed.schema.mutable", "true"); System.setProperty("managed.schema.mutable", "true");