in solr/core/src/java/org/apache/solr/core/CoreContainer.java [799:1217]
private void loadInternal() {
if (log.isDebugEnabled()) {
log.debug("Loading cores into CoreContainer [instanceDir={}]", getSolrHome());
}
logging = LogWatcher.newRegisteredLogWatcher(cfg.getLogWatcherConfig(), loader);
ClusterPluginsSource pluginsSource =
ClusterPluginsSource.loadClusterPluginsSource(this, loader);
containerPluginsRegistry =
new ContainerPluginsRegistry(this, containerHandlers.getApiBag(), pluginsSource);
ClusterEventProducerFactory clusterEventProducerFactory = new ClusterEventProducerFactory(this);
clusterEventProducer = clusterEventProducerFactory;
placementPluginFactory =
new DelegatingPlacementPluginFactory(
PlacementPluginFactoryLoader.getDefaultPlacementPluginFactory());
containerPluginsRegistry.registerListener(clusterSingletons.getPluginRegistryListener());
containerPluginsRegistry.registerListener(
clusterEventProducerFactory.getPluginRegistryListener());
metricManager = new SolrMetricManager(loader, cfg.getMetricsConfig());
String registryName = SolrMetricManager.getRegistryName(SolrInfoBean.Group.node);
solrMetricsContext = new SolrMetricsContext(metricManager, registryName, metricTag);
tracer = TracerConfigurator.loadTracer(loader, cfg.getTracerConfiguratorPluginInfo());
coreContainerWorkExecutor =
MetricUtils.instrumentedExecutorService(
coreContainerWorkExecutor,
null,
metricManager.registry(SolrMetricManager.getRegistryName(SolrInfoBean.Group.node)),
SolrMetricManager.mkName(
"coreContainerWorkExecutor",
SolrInfoBean.Category.CONTAINER.toString(),
"threadPool"));
shardHandlerFactory =
ShardHandlerFactory.newInstance(cfg.getShardHandlerFactoryPluginInfo(), loader);
if (shardHandlerFactory instanceof SolrMetricProducer metricProducer) {
metricProducer.initializeMetrics(solrMetricsContext, "httpShardHandler");
}
updateShardHandler = new UpdateShardHandler(cfg.getUpdateShardHandlerConfig());
solrClientProvider =
new HttpSolrClientProvider(cfg.getUpdateShardHandlerConfig(), solrMetricsContext);
updateShardHandler.initializeMetrics(solrMetricsContext, "updateShardHandler");
solrClientCache = new SolrClientCache(solrClientProvider.getSolrClient());
Map<String, CacheConfig> cachesConfig = cfg.getCachesConfig();
if (cachesConfig.isEmpty()) {
this.caches = Collections.emptyMap();
} else {
Map<String, SolrCache<?, ?>> m = CollectionUtil.newHashMap(cachesConfig.size());
for (Map.Entry<String, CacheConfig> e : cachesConfig.entrySet()) {
SolrCache<?, ?> c = e.getValue().newInstance();
String cacheName = e.getKey();
c.initializeMetrics(solrMetricsContext, "nodeLevelCache/" + cacheName);
m.put(cacheName, c);
}
this.caches = Collections.unmodifiableMap(m);
}
StartupLoggingUtils.checkRequestLogging();
hostName = cfg.getNodeName();
zkSys.initZooKeeper(this, cfg.getCloudConfig());
if (isZooKeeperAware()) {
solrClientCache.setDefaultZKHost(getZkController().getZkServerAddress());
// initialize ZkClient metrics
zkSys.getZkMetricsProducer().initializeMetrics(solrMetricsContext, "zkClient");
pkiAuthenticationSecurityBuilder =
new PKIAuthenticationPlugin(
this,
zkSys.getZkController().getNodeName(),
(PublicKeyHandler) containerHandlers.get(PublicKeyHandler.PATH));
pkiAuthenticationSecurityBuilder.initializeMetrics(solrMetricsContext, "/authentication/pki");
fileStore = new DistribFileStore(this);
registerV2ApiIfEnabled(ClusterFileStore.class);
packageLoader = new SolrPackageLoader(this);
registerV2ApiIfEnabled(packageLoader.getPackageAPI().editAPI);
registerV2ApiIfEnabled(packageLoader.getPackageAPI().readAPI);
registerV2ApiIfEnabled(ZookeeperRead.class);
}
MDCLoggingContext.setNode(this);
securityConfHandler =
isZooKeeperAware() ? new SecurityConfHandlerZk(this) : new SecurityConfHandlerLocal(this);
reloadSecurityProperties();
warnUsersOfInsecureSettings();
this.backupRepoFactory = new BackupRepositoryFactory(cfg.getBackupRepositoryPlugins());
coreConfigService = ConfigSetService.createConfigSetService(this);
createHandler(ZK_PATH, ZookeeperInfoHandler.class.getName(), ZookeeperInfoHandler.class);
createHandler(
ZK_STATUS_PATH, ZookeeperStatusHandler.class.getName(), ZookeeperStatusHandler.class);
// CoreContainer is initialized enough at this stage so we can set
// distributedCollectionCommandRunner (the construction of
// DistributedCollectionConfigSetCommandRunner uses Zookeeper so can't be done from the
// CoreContainer constructor because there Zookeeper is not yet ready). Given this is used in
// the CollectionsHandler created next line, this is the latest point where
// distributedCollectionCommandRunner can be initialized without refactoring this method...
// TODO: manage to completely build CoreContainer in the constructor and not in the load()
// method... Requires some test refactoring.
this.distributedCollectionCommandRunner =
isZooKeeperAware() && cfg.getCloudConfig().getDistributedCollectionConfigSetExecution()
? Optional.of(new DistributedCollectionConfigSetCommandRunner(this))
: Optional.empty();
collectionsHandler =
createHandler(
COLLECTIONS_HANDLER_PATH, cfg.getCollectionsHandlerClass(), CollectionsHandler.class);
configSetsHandler =
createHandler(
CONFIGSETS_HANDLER_PATH, cfg.getConfigSetsHandlerClass(), ConfigSetsHandler.class);
ClusterAPI clusterAPI = new ClusterAPI(collectionsHandler, configSetsHandler);
registerV2ApiIfEnabled(clusterAPI);
registerV2ApiIfEnabled(clusterAPI.commands);
if (isZooKeeperAware()) {
registerV2ApiIfEnabled(new SchemaDesignerAPI(this));
} // else Schema Designer not available in standalone (non-cloud) mode
/*
* HealthCheckHandler needs to be initialized before InfoHandler, since the later one will call CoreContainer.getHealthCheckHandler().
* We don't register the handler here because it'll be registered inside InfoHandler
*/
healthCheckHandler =
loader.newInstance(
cfg.getHealthCheckHandlerClass(),
HealthCheckHandler.class,
null,
new Class<?>[] {CoreContainer.class},
new Object[] {this});
infoHandler = createHandler(INFO_HANDLER_PATH, cfg.getInfoHandlerClass(), InfoHandler.class);
coreAdminHandler =
createHandler(CORES_HANDLER_PATH, cfg.getCoreAdminHandlerClass(), CoreAdminHandler.class);
Map<String, CoreAdminOp> coreAdminHandlerActions =
cfg.getCoreAdminHandlerActions().entrySet().stream()
.collect(
Collectors.toMap(
item -> item.getKey(),
item -> loader.newInstance(item.getValue(), CoreAdminOp.class)));
// Register custom actions for CoreAdminHandler
coreAdminHandler.registerCustomActions(coreAdminHandlerActions);
metricsHandler = new MetricsHandler(this);
containerHandlers.put(METRICS_PATH, metricsHandler);
metricsHandler.initializeMetrics(solrMetricsContext, METRICS_PATH);
containerHandlers.put(AUTHZ_PATH, securityConfHandler);
securityConfHandler.initializeMetrics(solrMetricsContext, AUTHZ_PATH);
containerHandlers.put(AUTHC_PATH, securityConfHandler);
PluginInfo[] metricReporters = cfg.getMetricsConfig().getMetricReporters();
metricManager.loadReporters(metricReporters, loader, this, null, null, SolrInfoBean.Group.node);
metricManager.loadReporters(metricReporters, loader, this, null, null, SolrInfoBean.Group.jvm);
metricManager.loadReporters(
metricReporters, loader, this, null, null, SolrInfoBean.Group.jetty);
containerProperties.putAll(cfg.getSolrProperties());
// initialize gauges for reporting the number of cores and disk total/free
solrMetricsContext.gauge(
solrCores::getNumLoadedPermanentCores,
true,
"loaded",
SolrInfoBean.Category.CONTAINER.toString(),
"cores");
solrMetricsContext.gauge(
solrCores::getNumLoadedTransientCores,
true,
"lazy",
SolrInfoBean.Category.CONTAINER.toString(),
"cores");
solrMetricsContext.gauge(
solrCores::getNumUnloadedCores,
true,
"unloaded",
SolrInfoBean.Category.CONTAINER.toString(),
"cores");
Path dataHome =
cfg.getSolrDataHome() != null ? cfg.getSolrDataHome() : cfg.getCoreRootDirectory();
solrMetricsContext.gauge(
() -> dataHome.toFile().getTotalSpace(),
true,
"totalSpace",
SolrInfoBean.Category.CONTAINER.toString(),
"fs");
solrMetricsContext.gauge(
() -> dataHome.toFile().getUsableSpace(),
true,
"usableSpace",
SolrInfoBean.Category.CONTAINER.toString(),
"fs");
solrMetricsContext.gauge(
dataHome::toString, true, "path", SolrInfoBean.Category.CONTAINER.toString(), "fs");
solrMetricsContext.gauge(
() -> cfg.getCoreRootDirectory().toFile().getTotalSpace(),
true,
"totalSpace",
SolrInfoBean.Category.CONTAINER.toString(),
"fs",
"coreRoot");
solrMetricsContext.gauge(
() -> cfg.getCoreRootDirectory().toFile().getUsableSpace(),
true,
"usableSpace",
SolrInfoBean.Category.CONTAINER.toString(),
"fs",
"coreRoot");
solrMetricsContext.gauge(
() -> cfg.getCoreRootDirectory().toString(),
true,
"path",
SolrInfoBean.Category.CONTAINER.toString(),
"fs",
"coreRoot");
// add version information
solrMetricsContext.gauge(
() -> this.getClass().getPackage().getSpecificationVersion(),
true,
"specification",
SolrInfoBean.Category.CONTAINER.toString(),
"version");
solrMetricsContext.gauge(
() -> this.getClass().getPackage().getImplementationVersion(),
true,
"implementation",
SolrInfoBean.Category.CONTAINER.toString(),
"version");
SolrFieldCacheBean fieldCacheBean = new SolrFieldCacheBean();
fieldCacheBean.initializeMetrics(solrMetricsContext, null);
if (isZooKeeperAware()) {
metricManager.loadClusterReporters(metricReporters, this);
}
// setup executor to load cores in parallel
ExecutorService coreLoadExecutor =
MetricUtils.instrumentedExecutorService(
ExecutorUtil.newMDCAwareFixedThreadPool(
cfg.getCoreLoadThreadCount(isZooKeeperAware()),
new SolrNamedThreadFactory("coreLoadExecutor")),
null,
metricManager.registry(SolrMetricManager.getRegistryName(SolrInfoBean.Group.node)),
SolrMetricManager.mkName(
"coreLoadExecutor", SolrInfoBean.Category.CONTAINER.toString(), "threadPool"));
coreSorter =
loader.newInstance(
cfg.getCoreSorterClass(),
CoreSorter.class,
null,
new Class<?>[] {CoreContainer.class},
new Object[] {this});
try {
List<CoreDescriptor> cds = coresLocator.discover(this);
cds = coreSorter.sort(cds);
checkForDuplicateCoreNames(cds);
status |= CORE_DISCOVERY_COMPLETE;
for (final CoreDescriptor cd : cds) {
if (cd.isTransient() || !cd.isLoadOnStartup()) {
solrCores.addCoreDescriptor(cd);
} else if (asyncSolrCoreLoad) {
solrCores.markCoreAsLoading(cd);
}
if (cd.isLoadOnStartup()) {
coreLoadExecutor.execute(
() -> {
SolrCore core;
boolean pendingCoreOpAdded = false;
try {
if (zkSys.getZkController() != null) {
zkSys.getZkController().throwErrorIfReplicaReplaced(cd);
}
MDCLoggingContext.setCoreDescriptor(this, cd);
solrCores.waitAddPendingCoreOps(cd.getName());
pendingCoreOpAdded = true;
core = createFromDescriptor(cd, false, false);
} catch (Exception e) {
log.error("SolrCore failed to load on startup", e);
MDCLoggingContext.clear();
return;
} finally {
if (pendingCoreOpAdded) {
solrCores.removeFromPendingOps(cd.getName());
}
if (asyncSolrCoreLoad) {
solrCores.markCoreAsNotLoading(cd);
}
}
try {
zkSys.registerInZk(core, true, false);
} catch (RuntimeException e) {
log.error("Error registering SolrCore", e);
} finally {
MDCLoggingContext.clear();
}
});
}
}
// Start the background thread
backgroundCloser = new CloserThread(this, solrCores, cfg);
backgroundCloser.start();
} finally {
if (asyncSolrCoreLoad) {
coreContainerWorkExecutor.execute(
() -> ExecutorUtil.shutdownAndAwaitTerminationForever(coreLoadExecutor));
} else {
ExecutorUtil.shutdownAndAwaitTerminationForever(coreLoadExecutor);
}
}
if (isZooKeeperAware()) {
containerPluginsRegistry.refresh();
getZkController().zkStateReader.registerClusterPropertiesListener(containerPluginsRegistry);
registerV2ApiIfEnabled(pluginsSource.getReadApi());
registerV2ApiIfEnabled(pluginsSource.getEditApi());
// initialize the placement plugin factory wrapper
// with the plugin configuration from the registry
PlacementPluginFactoryLoader.load(placementPluginFactory, containerPluginsRegistry);
// create target ClusterEventProducer (possibly from plugins)
clusterEventProducer = clusterEventProducerFactory.create(containerPluginsRegistry);
// init ClusterSingleton-s
// register the handlers that are also ClusterSingleton
containerHandlers
.keySet()
.forEach(
handlerName -> {
SolrRequestHandler handler = containerHandlers.get(handlerName);
if (handler instanceof ClusterSingleton singleton) {
clusterSingletons.getSingletons().put(singleton.getName(), singleton);
}
});
}
if (V2ApiUtils.isEnabled()) {
final CoreContainer thisCCRef = this;
// Init the Jersey app once all CC endpoints have been registered
containerHandlers
.getJerseyEndpoints()
.register(
new AbstractBinder() {
@Override
protected void configure() {
bindFactory(new InjectionFactories.SingletonFactory<>(thisCCRef))
.to(CoreContainer.class)
.in(Singleton.class);
}
})
.register(
new AbstractBinder() {
@Override
protected void configure() {
bindFactory(new InjectionFactories.SingletonFactory<>(nodeKeyPair))
.to(SolrNodeKeyPair.class)
.in(Singleton.class);
}
})
.register(
new AbstractBinder() {
@Override
protected void configure() {
bindFactory(new InjectionFactories.SingletonFactory<>(fileStore))
.to(DistribFileStore.class)
.in(Singleton.class);
}
})
.register(
new AbstractBinder() {
@Override
protected void configure() {
bindFactory(
new InjectionFactories.SingletonFactory<>(
coreAdminHandler.getCoreAdminAsyncTracker()))
.to(CoreAdminHandler.CoreAdminAsyncTracker.class)
.in(Singleton.class);
}
});
jerseyAppHandler = new ApplicationHandler(containerHandlers.getJerseyEndpoints());
}
// Do Node setup logic after all handlers have been registered.
if (isZooKeeperAware()) {
clusterSingletons.setReady();
if (NodeRoles.MODE_PREFERRED.equals(nodeRoles.getRoleMode(NodeRoles.Role.OVERSEER))) {
try {
log.info("This node has been started as a preferred overseer");
zkSys.getZkController().setPreferredOverseer();
} catch (KeeperException | InterruptedException e) {
throw new SolrException(ErrorCode.SERVER_ERROR, e);
}
}
if (!distributedCollectionCommandRunner.isPresent()) {
zkSys.getZkController().checkOverseerDesignate();
}
}
// This is a bit redundant but these are two distinct concepts for all they're accomplished at
// the same time.
status |= LOAD_COMPLETE | INITIAL_CORE_LOAD_COMPLETE;
}