SOLR: Use absolute paths for server paths. (#1546)

CoreContainer's paths and SolrCore instanceDir are now absolute; mandated. This avoids bugs when the current working directory of the server is abnormal (perhaps running in tests or some IDE configs).
This commit is contained in:
David Smiley 2020-06-02 22:36:52 -04:00 committed by GitHub
parent 549c42d44e
commit a06f57c7e1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 35 additions and 32 deletions

View File

@ -405,7 +405,7 @@ public abstract class CachingDirectoryFactory extends DirectoryFactory {
// override global config // override global config
if (args.get(SolrXmlConfig.SOLR_DATA_HOME) != null) { if (args.get(SolrXmlConfig.SOLR_DATA_HOME) != null) {
dataHomePath = Paths.get((String) args.get(SolrXmlConfig.SOLR_DATA_HOME)); dataHomePath = Paths.get((String) args.get(SolrXmlConfig.SOLR_DATA_HOME)).toAbsolutePath().normalize();
} }
if (dataHomePath != null) { if (dataHomePath != null) {
log.info("{} = {}", SolrXmlConfig.SOLR_DATA_HOME, dataHomePath); log.info("{} = {}", SolrXmlConfig.SOLR_DATA_HOME, dataHomePath);

View File

@ -1769,6 +1769,7 @@ public class CoreContainer {
return solrCores.getCoreDescriptor(coreName); return solrCores.getCoreDescriptor(coreName);
} }
/** Where cores are created (absolute). */
public Path getCoreRootDirectory() { public Path getCoreRootDirectory() {
return cfg.getCoreRootDirectory(); return cfg.getCoreRootDirectory();
} }
@ -1927,6 +1928,7 @@ public class CoreContainer {
return solrCores.getUnloadedCoreDescriptor(cname); return solrCores.getUnloadedCoreDescriptor(cname);
} }
/** The primary path of a Solr server's config, cores, and misc things. Absolute. */
//TODO return Path //TODO return Path
public String getSolrHome() { public String getSolrHome() {
return solrHome.toString(); return solrHome.toString();

View File

@ -182,7 +182,7 @@ public class CoreDescriptor {
*/ */
public CoreDescriptor(String name, Path instanceDir, Map<String, String> coreProps, public CoreDescriptor(String name, Path instanceDir, Map<String, String> coreProps,
Properties containerProperties, ZkController zkController) { Properties containerProperties, ZkController zkController) {
this.instanceDir = instanceDir; this.instanceDir = instanceDir.toAbsolutePath();
originalCoreProperties.setProperty(CORE_NAME, name); originalCoreProperties.setProperty(CORE_NAME, name);
@ -290,9 +290,7 @@ public class CoreDescriptor {
return defaultProperties.get(CORE_DATADIR).equals(coreProperties.getProperty(CORE_DATADIR)); return defaultProperties.get(CORE_DATADIR).equals(coreProperties.getProperty(CORE_DATADIR));
} }
/** /** The core instance directory (absolute). */
* @return the core instance directory
*/
public Path getInstanceDir() { public Path getInstanceDir() {
return instanceDir; return instanceDir;
} }

View File

@ -62,7 +62,7 @@ public class CorePropertiesLocator implements CoresLocator {
@Override @Override
public void create(CoreContainer cc, CoreDescriptor... coreDescriptors) { public void create(CoreContainer cc, CoreDescriptor... coreDescriptors) {
for (CoreDescriptor cd : coreDescriptors) { for (CoreDescriptor cd : coreDescriptors) {
Path propertiesFile = this.rootDirectory.resolve(cd.getInstanceDir()).resolve(PROPERTIES_FILENAME); Path propertiesFile = cd.getInstanceDir().resolve(PROPERTIES_FILENAME);
if (Files.exists(propertiesFile)) if (Files.exists(propertiesFile))
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
"Could not create a new core in " + cd.getInstanceDir() "Could not create a new core in " + cd.getInstanceDir()
@ -78,7 +78,7 @@ public class CorePropertiesLocator implements CoresLocator {
@Override @Override
public void persist(CoreContainer cc, CoreDescriptor... coreDescriptors) { public void persist(CoreContainer cc, CoreDescriptor... coreDescriptors) {
for (CoreDescriptor cd : coreDescriptors) { for (CoreDescriptor cd : coreDescriptors) {
Path propFile = this.rootDirectory.resolve(cd.getInstanceDir()).resolve(PROPERTIES_FILENAME); Path propFile = cd.getInstanceDir().resolve(PROPERTIES_FILENAME);
writePropertiesFile(cd, propFile); writePropertiesFile(cd, propFile);
} }
} }
@ -105,7 +105,7 @@ public class CorePropertiesLocator implements CoresLocator {
} }
for (CoreDescriptor cd : coreDescriptors) { for (CoreDescriptor cd : coreDescriptors) {
if (cd == null) continue; if (cd == null) continue;
Path propfile = this.rootDirectory.resolve(cd.getInstanceDir()).resolve(PROPERTIES_FILENAME); Path propfile = cd.getInstanceDir().resolve(PROPERTIES_FILENAME);
try { try {
Files.deleteIfExists(propfile); Files.deleteIfExists(propfile);
} catch (IOException e) { } catch (IOException e) {

View File

@ -23,9 +23,8 @@ import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodHandles;
import java.nio.file.NoSuchFileException; import java.nio.file.NoSuchFileException;
import java.util.Arrays;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@ -55,7 +54,7 @@ public abstract class DirectoryFactory implements NamedListInitializedPlugin,
protected static final String INDEX_W_TIMESTAMP_REGEX = "index\\.[0-9]{17}"; // see SnapShooter.DATE_FMT protected static final String INDEX_W_TIMESTAMP_REGEX = "index\\.[0-9]{17}"; // see SnapShooter.DATE_FMT
// May be set by sub classes as data root, in which case getDataHome will use it as base // May be set by sub classes as data root, in which case getDataHome will use it as base. Absolute.
protected Path dataHomePath; protected Path dataHomePath;
// hint about what the directory contains - default is index directory // hint about what the directory contains - default is index directory
@ -331,16 +330,16 @@ public abstract class DirectoryFactory implements NamedListInitializedPlugin,
* @return a String with absolute path to data direcotry * @return a String with absolute path to data direcotry
*/ */
public String getDataHome(CoreDescriptor cd) throws IOException { public String getDataHome(CoreDescriptor cd) throws IOException {
String dataDir; Path dataDir;
if (dataHomePath != null) { if (dataHomePath != null) {
String instanceDirLastPath = cd.getInstanceDir().getName(cd.getInstanceDir().getNameCount()-1).toString(); Path instanceDirLastPath = cd.getInstanceDir().getName(cd.getInstanceDir().getNameCount()-1);
dataDir = Paths.get(coreContainer.getSolrHome()).resolve(dataHomePath) dataDir = dataHomePath.resolve(instanceDirLastPath).resolve(cd.getDataDir());
.resolve(instanceDirLastPath).resolve(cd.getDataDir()).toAbsolutePath().toString();
} else { } else {
// by default, we go off the instance directory // by default, we go off the instance directory
dataDir = cd.getInstanceDir().resolve(cd.getDataDir()).toAbsolutePath().toString(); dataDir = cd.getInstanceDir().resolve(cd.getDataDir());
} }
return dataDir; assert dataDir.isAbsolute();
return dataDir.toString();
} }
public void cleanupOldIndexDirectories(final String dataDirPath, final String currentIndexDirPath, boolean afterCoreReload) { public void cleanupOldIndexDirectories(final String dataDirPath, final String currentIndexDirPath, boolean afterCoreReload) {
@ -398,7 +397,7 @@ public abstract class DirectoryFactory implements NamedListInitializedPlugin,
public void initCoreContainer(CoreContainer cc) { public void initCoreContainer(CoreContainer cc) {
this.coreContainer = cc; this.coreContainer = cc;
if (cc != null && cc.getConfig() != null) { if (cc != null && cc.getConfig() != null) {
this.dataHomePath = cc.getConfig().getSolrDataHome(); this.dataHomePath = cc.getConfig().getSolrDataHome(); // absolute
} }
} }

View File

@ -29,6 +29,7 @@ import org.apache.solr.update.UpdateShardHandlerConfig;
public class NodeConfig { public class NodeConfig {
// all Path fields here are absolute and normalized.
private final String nodeName; private final String nodeName;
@ -95,6 +96,7 @@ public class NodeConfig {
Properties solrProperties, PluginInfo[] backupRepositoryPlugins, Properties solrProperties, PluginInfo[] backupRepositoryPlugins,
MetricsConfig metricsConfig, PluginInfo transientCacheConfig, PluginInfo tracerConfig, MetricsConfig metricsConfig, PluginInfo transientCacheConfig, PluginInfo tracerConfig,
boolean fromZookeeper) { boolean fromZookeeper) {
// all Path params here are absolute and normalized.
this.nodeName = nodeName; this.nodeName = nodeName;
this.coreRootDirectory = coreRootDirectory; this.coreRootDirectory = coreRootDirectory;
this.solrDataHome = solrDataHome; this.solrDataHome = solrDataHome;
@ -134,10 +136,12 @@ public class NodeConfig {
return nodeName; return nodeName;
} }
/** Absolute. */
public Path getCoreRootDirectory() { public Path getCoreRootDirectory() {
return coreRootDirectory; return coreRootDirectory;
} }
/** Absolute. */
public Path getSolrDataHome() { public Path getSolrDataHome() {
return solrDataHome; return solrDataHome;
} }
@ -208,6 +212,7 @@ public class NodeConfig {
return managementPath; return managementPath;
} }
/** Absolute. */
public Path getConfigSetBaseDirectory() { public Path getConfigSetBaseDirectory() {
return configSetBaseDirectory; return configSetBaseDirectory;
} }
@ -259,7 +264,7 @@ public class NodeConfig {
} }
public static class NodeConfigBuilder { public static class NodeConfigBuilder {
// all Path fields here are absolute and normalized.
private SolrResourceLoader loader; private SolrResourceLoader loader;
private Path coreRootDirectory; private Path coreRootDirectory;
private Path solrDataHome; private Path solrDataHome;
@ -314,26 +319,23 @@ public class NodeConfig {
public NodeConfigBuilder(String nodeName, Path solrHome) { public NodeConfigBuilder(String nodeName, Path solrHome) {
this.nodeName = nodeName; this.nodeName = nodeName;
this.solrHome = solrHome; this.solrHome = solrHome.toAbsolutePath();
this.coreRootDirectory = solrHome; this.coreRootDirectory = solrHome;
// always init from sysprop because <solrDataHome> config element may be missing // always init from sysprop because <solrDataHome> config element may be missing
String dataHomeProperty = System.getProperty(SolrXmlConfig.SOLR_DATA_HOME); setSolrDataHome(System.getProperty(SolrXmlConfig.SOLR_DATA_HOME));
if (dataHomeProperty != null && !dataHomeProperty.isEmpty()) { setConfigSetBaseDirectory("configsets");
solrDataHome = solrHome.resolve(dataHomeProperty);
}
this.configSetBaseDirectory = solrHome.resolve("configsets");
this.metricsConfig = new MetricsConfig.MetricsConfigBuilder().build(); this.metricsConfig = new MetricsConfig.MetricsConfigBuilder().build();
} }
public NodeConfigBuilder setCoreRootDirectory(String coreRootDirectory) { public NodeConfigBuilder setCoreRootDirectory(String coreRootDirectory) {
this.coreRootDirectory = solrHome.resolve(coreRootDirectory); this.coreRootDirectory = solrHome.resolve(coreRootDirectory).normalize();
return this; return this;
} }
public NodeConfigBuilder setSolrDataHome(String solrDataHomeString) { public NodeConfigBuilder setSolrDataHome(String solrDataHomeString) {
// keep it null unless explicitly set to non-empty value // keep it null unless explicitly set to non-empty value
if (solrDataHomeString != null && !solrDataHomeString.isEmpty()) { if (solrDataHomeString != null && !solrDataHomeString.isEmpty()) {
this.solrDataHome = solrHome.resolve(solrDataHomeString); this.solrDataHome = solrHome.resolve(solrDataHomeString).normalize();
} }
return this; return this;
} }

View File

@ -327,7 +327,7 @@ public final class SolrCore implements SolrInfoBean, Closeable {
return schema; return schema;
} }
/** The core's instance directory. */ /** The core's instance directory (absolute). */
public Path getInstancePath() { public Path getInstancePath() {
return getCoreDescriptor().getInstanceDir(); return getCoreDescriptor().getInstanceDir();
} }
@ -1358,7 +1358,7 @@ public final class SolrCore implements SolrInfoBean, Closeable {
private String initUpdateLogDir(CoreDescriptor coreDescriptor) { private String initUpdateLogDir(CoreDescriptor coreDescriptor) {
String updateLogDir = coreDescriptor.getUlogDir(); String updateLogDir = coreDescriptor.getUlogDir();
if (updateLogDir == null) { if (updateLogDir == null) {
updateLogDir = coreDescriptor.getInstanceDir().resolve(dataDir).normalize().toAbsolutePath().toString(); updateLogDir = coreDescriptor.getInstanceDir().resolve(dataDir).toString();
} }
return updateLogDir; return updateLogDir;
} }
@ -3001,7 +3001,7 @@ public final class SolrCore implements SolrInfoBean, Closeable {
public static void deleteUnloadedCore(CoreDescriptor cd, boolean deleteDataDir, boolean deleteInstanceDir) { public static void deleteUnloadedCore(CoreDescriptor cd, boolean deleteDataDir, boolean deleteInstanceDir) {
if (deleteDataDir) { if (deleteDataDir) {
File dataDir = new File(cd.getInstanceDir().resolve(cd.getDataDir()).toAbsolutePath().toString()); File dataDir = cd.getInstanceDir().resolve(cd.getDataDir()).toFile();
try { try {
FileUtils.deleteDirectory(dataDir); FileUtils.deleteDirectory(dataDir);
} catch (IOException e) { } catch (IOException e) {

View File

@ -77,7 +77,7 @@ enum CoreAdminOperation implements CoreAdminOp {
String coreName = params.required().get(CoreAdminParams.NAME); String coreName = params.required().get(CoreAdminParams.NAME);
Map<String, String> coreParams = buildCoreParams(params); Map<String, String> coreParams = buildCoreParams(params);
CoreContainer coreContainer = it.handler.coreContainer; CoreContainer coreContainer = it.handler.coreContainer;
Path instancePath = coreContainer.getCoreRootDirectory().resolve(coreName); Path instancePath;
// TODO: Should we nuke setting odd instance paths? They break core discovery, generally // TODO: Should we nuke setting odd instance paths? They break core discovery, generally
String instanceDir = it.req.getParams().get(CoreAdminParams.INSTANCE_DIR); String instanceDir = it.req.getParams().get(CoreAdminParams.INSTANCE_DIR);
@ -86,6 +86,8 @@ enum CoreAdminOperation implements CoreAdminOp {
if (instanceDir != null) { if (instanceDir != null) {
instanceDir = PropertiesUtil.substituteProperty(instanceDir, coreContainer.getContainerProperties()); instanceDir = PropertiesUtil.substituteProperty(instanceDir, coreContainer.getContainerProperties());
instancePath = coreContainer.getCoreRootDirectory().resolve(instanceDir).normalize(); instancePath = coreContainer.getCoreRootDirectory().resolve(instanceDir).normalize();
} else {
instancePath = coreContainer.getCoreRootDirectory().resolve(coreName);
} }
boolean newCollection = params.getBool(CoreAdminParams.NEW_COLLECTION, false); boolean newCollection = params.getBool(CoreAdminParams.NEW_COLLECTION, false);

View File

@ -397,7 +397,7 @@ public class TestCoreDiscovery extends SolrTestCaseJ4 {
assertNull(cc.getCore("core0")); assertNull(cc.getCore("core0"));
SolrCore core3 = cc.create("core3", ImmutableMap.of("configSet", "minimal")); SolrCore core3 = cc.create("core3", ImmutableMap.of("configSet", "minimal"));
assertThat(core3.getCoreDescriptor().getInstanceDir().toAbsolutePath().toString(), containsString("relative")); assertThat(core3.getCoreDescriptor().getInstanceDir().toString(), containsString("relative"));
} finally { } finally {
cc.shutdown(); cc.shutdown();