blob: 65e18d8a2a9f113661ed9bafb1628f04eb806c71 [file] [log] [blame]
/*
* 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.lang.invoke.MethodHandles;
import java.util.*;
import org.apache.solr.common.util.NamedList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TransientSolrCoreCacheDefault extends TransientSolrCoreCache {
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
private int cacheSize = NodeConfig.NodeConfigBuilder.DEFAULT_TRANSIENT_CACHE_SIZE;
protected CoreContainer coreContainer;
protected final Map<String, CoreDescriptor> transientDescriptors = new LinkedHashMap<>();
//WARNING! The _only_ place you put anything into the list of transient cores is with the putTransientCore method!
protected Map<String, SolrCore> transientCores = new LinkedHashMap<>(); // For "lazily loaded" cores
/**
* @param container The enclosing CoreContainer. It allows us to access everything we need.
*/
public TransientSolrCoreCacheDefault(final CoreContainer container) {
this.coreContainer = container;
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.
// deprecate this for 7.0?
this.cacheSize = cfg.getTransientCacheSize();
} else {
@SuppressWarnings({"rawtypes"})
NamedList args = cfg.getTransientCachePluginInfo().initArgs;
Object obj = args.get("transientCacheSize");
if (obj != null) {
this.cacheSize = (int) obj;
}
}
doInit();
}
// This just moves the
private void doInit() {
NodeConfig cfg = coreContainer.getNodeConfig();
if (cfg.getTransientCachePluginInfo() == null) {
// Still handle just having transientCacheSize defined in the body of solr.xml not in a transient handler clause.
this.cacheSize = cfg.getTransientCacheSize();
} else {
@SuppressWarnings({"rawtypes"})
NamedList args = cfg.getTransientCachePluginInfo().initArgs;
Object obj = args.get("transientCacheSize");
if (obj != null) {
this.cacheSize = (int) obj;
}
}
log.info("Allocating transient cache for {} transient cores", cacheSize);
// it's possible for cache
if (cacheSize < 0) { // Trap old flag
cacheSize = Integer.MAX_VALUE;
}
// 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.
transientCores = new LinkedHashMap<String, SolrCore>(Math.min(cacheSize, 1000), 0.75f, true) {
@Override
protected boolean removeEldestEntry(Map.Entry<String, SolrCore> eldest) {
if (size() > cacheSize) {
SolrCore coreToClose = eldest.getValue();
if (log.isInfoEnabled()) {
log.info("Closing transient core [{}]", coreToClose.getName());
}
coreContainer.queueCoreToClose(coreToClose);
return true;
}
return false;
}
};
}
@Override
public Collection<SolrCore> prepareForShutdown() {
// Returna copy of the values
@SuppressWarnings({"unchecked", "rawtypes"})
List<SolrCore> ret = new ArrayList(transientCores.values());
transientCores.clear();
return ret;
}
@Override
public CoreContainer getContainer() { return this.coreContainer; }
@Override
public SolrCore addCore(String name, SolrCore core) {
return transientCores.put(name, core);
}
@Override
public Set<String> getAllCoreNames() {
return Collections.unmodifiableSet(transientDescriptors.keySet());
}
@Override
public Set<String> getLoadedCoreNames() {
return Collections.unmodifiableSet(transientCores.keySet());
}
// Remove a core from the internal structures, presumably it
// being closed. If the core is re-opened, it will be re-added by CoreContainer.
@Override
public SolrCore removeCore(String name) {
return transientCores.remove(name);
}
// Get the core associated with the name. Return null if you don't want this core to be used.
@Override
public SolrCore getCore(String name) {
return transientCores.get(name);
}
@Override
public boolean containsCore(String name) {
return transientCores.containsKey(name);
}
// These methods allow the implementation to maintain control over the core descriptors.
// This method will only be called during core discovery at startup.
@Override
public void addTransientDescriptor(String rawName, CoreDescriptor cd) {
transientDescriptors.put(rawName, cd);
}
// This method is used when opening cores and the like. If you want to change a core's descriptor, override this
// method and return the current core descriptor.
@Override
public CoreDescriptor getTransientDescriptor(String name) {
return transientDescriptors.get(name);
}
@Override
public Collection<CoreDescriptor> getTransientDescriptors() {
return Collections.unmodifiableCollection(transientDescriptors.values());
}
@Override
public CoreDescriptor removeTransientDescriptor(String name) {
return transientDescriptors.remove(name);
}
// For custom implementations to communicate arbitrary information as necessary.
@Override
public int getStatus(String coreName) { return 0; } //no_op for default handler.
@Override
public void setStatus(String coreName, int status) {} //no_op for default handler.
}