private void loadInternal()

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