blob: 622cf4c8a10f7455c2c68ca2c009c842f47a2c17 [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 org.apache.commons.io.FileUtils;
import org.apache.lucene.util.IOUtils;
import org.apache.solr.SolrTestCaseJ4;
import org.apache.solr.common.SolrException;
import org.junit.After;
import org.xml.sax.SAXParseException;
import java.io.File;
import java.util.Collection;
import java.util.Map;
import java.util.regex.Pattern;
public class CoreContainerCoreInitFailuresTest extends SolrTestCaseJ4 {
File solrHome = null;
CoreContainer cc = null;
private void init(final String dirSuffix) {
// would be nice to do this in an @Before method,
// but junit doesn't let @Before methods have test names
solrHome = new File(TEMP_DIR, this.getClass().getName() + "_" + dirSuffix);
assertTrue("Failed to mkdirs solrhome [" + solrHome + "]", solrHome.mkdirs());
}
@After
public void cleanUp() throws Exception {
if (cc != null) {
cc.shutdown();
cc = null;
}
if (null != solrHome) {
if (solrHome.exists()) {
FileUtils.deleteDirectory(solrHome);
}
solrHome = null;
}
}
public void testFlowWithEmpty() throws Exception {
// reused state
Map<String,Exception> failures = null;
Collection<String> cores = null;
Exception fail = null;
init("empty_flow");
// solr.xml
File solrXml = new File(solrHome, "solr.xml");
FileUtils.write(solrXml, EMPTY_SOLR_XML, IOUtils.CHARSET_UTF_8.toString());
// ----
// init the CoreContainer
cc = new CoreContainer(solrHome.getAbsolutePath());
cc.load();
// check that we have the cores we expect
cores = cc.getCoreNames();
assertNotNull("core names is null", cores);
assertEquals("wrong number of cores", 0, cores.size());
// check that we have the failures we expect
failures = cc.getCoreInitFailures();
assertNotNull("core failures is a null map", failures);
assertEquals("wrong number of core failures", 0, failures.size());
// -----
// try to add a collection with a path that doesn't exist
final CoreDescriptor bogus = new CoreDescriptor(cc, "bogus", "bogus_path");
try {
ignoreException(Pattern.quote("bogus_path"));
cc.create(bogus);
fail("bogus inst dir failed to trigger exception from create");
} catch (SolrException e) {
assertTrue("init exception doesn't mention bogus dir: " + e.getCause().getCause().getMessage(),
0 < e.getCause().getCause().getMessage().indexOf("bogus_path"));
}
// check that we have the cores we expect
cores = cc.getCoreNames();
assertNotNull("core names is null", cores);
assertEquals("wrong number of cores", 0, cores.size());
// check that we have the failures we expect
failures = cc.getCoreInitFailures();
assertNotNull("core failures is a null map", failures);
assertEquals("wrong number of core failures", 1, failures.size());
fail = failures.get("bogus");
assertNotNull("null failure for test core", fail);
assertTrue("init failure doesn't mention problem: " + fail.getCause().getMessage(),
0 < fail.getCause().getMessage().indexOf("bogus_path"));
// check that we get null accessing a non-existent core
assertNull(cc.getCore("does_not_exist"));
// check that we get a 500 accessing the core with an init failure
try {
SolrCore c = cc.getCore("bogus");
fail("Failed to get Exception on accessing core with init failure");
} catch (SolrException ex) {
assertEquals(500, ex.code());
// double wrapped
String cause = ex.getCause().getCause().getMessage();
assertTrue("getCore() ex cause doesn't mention init fail: " + cause,
0 < cause.indexOf("bogus_path"));
}
// let the test end here, with some recorded failures, and let cleanUp()
// verify that there is no problem shuting down CoreContainer with known
// SolrCore failures
}
public void testFlowBadFromStart() throws Exception {
// reused state
Map<String,Exception> failures = null;
Collection<String> cores = null;
Exception fail = null;
init("bad_flow");
// start with two collections: one valid, and one broken
File solrXml = new File(solrHome, "solr.xml");
FileUtils.write(solrXml, BAD_SOLR_XML, IOUtils.CHARSET_UTF_8.toString());
// our "ok" collection
FileUtils.copyFile(getFile("solr/collection1/conf/solrconfig-defaults.xml"),
FileUtils.getFile(solrHome, "col_ok", "conf", "solrconfig.xml"));
FileUtils.copyFile(getFile("solr/collection1/conf/schema-minimal.xml"),
FileUtils.getFile(solrHome, "col_ok", "conf", "schema.xml"));
// our "bad" collection
ignoreException(Pattern.quote("DummyMergePolicy"));
FileUtils.copyFile(getFile("solr/collection1/conf/bad-mp-solrconfig.xml"),
FileUtils.getFile(solrHome, "col_bad", "conf", "solrconfig.xml"));
FileUtils.copyFile(getFile("solr/collection1/conf/schema-minimal.xml"),
FileUtils.getFile(solrHome, "col_bad", "conf", "schema.xml"));
// -----
// init the CoreContainer with the mix of ok/bad cores
cc = new CoreContainer(solrHome.getAbsolutePath());
cc.load();
// check that we have the cores we expect
cores = cc.getCoreNames();
assertNotNull("core names is null", cores);
assertEquals("wrong number of cores", 1, cores.size());
assertTrue("col_ok not found", cores.contains("col_ok"));
// check that we have the failures we expect
failures = cc.getCoreInitFailures();
assertNotNull("core failures is a null map", failures);
assertEquals("wrong number of core failures", 1, failures.size());
fail = failures.get("col_bad");
assertNotNull("null failure for test core", fail);
assertTrue("init failure doesn't mention problem: " + fail.getMessage(),
0 < fail.getMessage().indexOf("DummyMergePolicy"));
// check that we get null accessing a non-existent core
assertNull(cc.getCore("does_not_exist"));
// check that we get a 500 accessing the core with an init failure
try {
SolrCore c = cc.getCore("col_bad");
fail("Failed to get Exception on accessing core with init failure");
} catch (SolrException ex) {
assertEquals(500, ex.code());
// double wrapped
String cause = ex.getCause().getCause().getMessage();
assertTrue("getCore() ex cause doesn't mention init fail: " + cause,
0 < cause.indexOf("DummyMergePolicy"));
}
// -----
// "fix" the bad collection
FileUtils.copyFile(getFile("solr/collection1/conf/solrconfig-defaults.xml"),
FileUtils.getFile(solrHome, "col_bad", "conf", "solrconfig.xml"));
final CoreDescriptor fixed = new CoreDescriptor(cc, "col_bad", "col_bad");
cc.register("col_bad", cc.create(fixed), false);
// check that we have the cores we expect
cores = cc.getCoreNames();
assertNotNull("core names is null", cores);
assertEquals("wrong number of cores", 2, cores.size());
assertTrue("col_ok not found", cores.contains("col_ok"));
assertTrue("col_bad not found", cores.contains("col_bad"));
// check that we have the failures we expect
failures = cc.getCoreInitFailures();
assertNotNull("core failures is a null map", failures);
assertEquals("wrong number of core failures", 0, failures.size());
// -----
// try to add a collection with a path that doesn't exist
final CoreDescriptor bogus = new CoreDescriptor(cc, "bogus", "bogus_path");
try {
ignoreException(Pattern.quote("bogus_path"));
cc.create(bogus);
fail("bogus inst dir failed to trigger exception from create");
} catch (SolrException e) {
assertTrue("init exception doesn't mention bogus dir: " + e.getCause().getCause().getMessage(),
0 < e.getCause().getCause().getMessage().indexOf("bogus_path"));
}
// check that we have the cores we expect
cores = cc.getCoreNames();
assertNotNull("core names is null", cores);
assertEquals("wrong number of cores", 2, cores.size());
assertTrue("col_ok not found", cores.contains("col_ok"));
assertTrue("col_bad not found", cores.contains("col_bad"));
// check that we have the failures we expect
failures = cc.getCoreInitFailures();
assertNotNull("core failures is a null map", failures);
assertEquals("wrong number of core failures", 1, failures.size());
fail = failures.get("bogus");
assertNotNull("null failure for test core", fail);
assertTrue("init failure doesn't mention problem: " + fail.getCause().getMessage(),
0 < fail.getCause().getMessage().indexOf("bogus_path"));
// check that we get null accessing a non-existent core
assertNull(cc.getCore("does_not_exist"));
// check that we get a 500 accessing the core with an init failure
try {
SolrCore c = cc.getCore("bogus");
fail("Failed to get Exception on accessing core with init failure");
} catch (SolrException ex) {
assertEquals(500, ex.code());
// double wrapped
String cause = ex.getCause().getCause().getMessage();
assertTrue("getCore() ex cause doesn't mention init fail: " + cause,
0 < cause.indexOf("bogus_path"));
}
// -----
// register bogus as an alias for col_ok and confirm failure goes away
cc.register("bogus", cc.getCore("col_ok"), false);
// check that we have the cores we expect
cores = cc.getCoreNames();
assertNotNull("core names is null", cores);
assertEquals("wrong number of cores", 3, cores.size());
assertTrue("col_ok not found", cores.contains("col_ok"));
assertTrue("col_bad not found", cores.contains("col_bad"));
assertTrue("bogus not found", cores.contains("bogus"));
// check that we have the failures we expect
failures = cc.getCoreInitFailures();
assertNotNull("core failures is a null map", failures);
assertEquals("wrong number of core failures", 0, failures.size());
// -----
// break col_bad's config and try to RELOAD to add failure
final long col_bad_old_start = getCoreStartTime(cc, "col_bad");
FileUtils.write
(FileUtils.getFile(solrHome, "col_bad", "conf", "solrconfig.xml"),
"This is giberish, not valid XML <",
IOUtils.CHARSET_UTF_8.toString());
try {
ignoreException(Pattern.quote("SAX"));
cc.reload("col_bad");
fail("corrupt solrconfig.xml failed to trigger exception from reload");
} catch (SolrException e) {
assertTrue("We're supposed to have a wrapped SAXParserException here, but we don't",
e.getCause().getCause() instanceof SAXParseException);
SAXParseException se = (SAXParseException)e.getCause().getCause();
assertTrue("reload exception doesn't refer to slrconfig.xml " + se.getSystemId(),
0 < se.getSystemId().indexOf("solrconfig.xml"));
}
assertEquals("Failed core reload should not have changed start time",
col_bad_old_start, getCoreStartTime(cc, "col_bad"));
// check that we have the cores we expect
cores = cc.getCoreNames();
assertNotNull("core names is null", cores);
assertEquals("wrong number of cores", 3, cores.size());
assertTrue("col_ok not found", cores.contains("col_ok"));
assertTrue("col_bad not found", cores.contains("col_bad"));
assertTrue("bogus not found", cores.contains("bogus"));
// check that we have the failures we expect
failures = cc.getCoreInitFailures();
assertNotNull("core failures is a null map", failures);
assertEquals("wrong number of core failures", 1, failures.size());
fail = failures.get("col_bad");
assertNotNull("null failure for test core", fail);
assertTrue("init failure isn't SAXParseException",
fail.getCause() instanceof SAXParseException);
assertTrue("init failure doesn't mention problem: " + fail.toString(),
0 < ((SAXParseException)fail.getCause()).getSystemId().indexOf("solrconfig.xml"));
// ----
// fix col_bad's config (again) and RELOAD to fix failure
FileUtils.copyFile(getFile("solr/collection1/conf/solrconfig-defaults.xml"),
FileUtils.getFile(solrHome, "col_bad", "conf", "solrconfig.xml"));
cc.reload("col_bad");
assertTrue("Core reload should have changed start time",
col_bad_old_start < getCoreStartTime(cc, "col_bad"));
// check that we have the cores we expect
cores = cc.getCoreNames();
assertNotNull("core names is null", cores);
assertEquals("wrong number of cores", 3, cores.size());
assertTrue("col_ok not found", cores.contains("col_ok"));
assertTrue("col_bad not found", cores.contains("col_bad"));
assertTrue("bogus not found", cores.contains("bogus"));
// check that we have the failures we expect
failures = cc.getCoreInitFailures();
assertNotNull("core failures is a null map", failures);
assertEquals("wrong number of core failures", 0, failures.size());
}
private final long getCoreStartTime(final CoreContainer cc,
final String name) {
SolrCore tmp = cc.getCore(name);
try {
return tmp.getStartTime();
} finally {
tmp.close();
}
}
private static final String EMPTY_SOLR_XML ="<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" +
"<solr persistent=\"false\">\n" +
" <cores adminPath=\"/admin/cores\">\n" +
" </cores>\n" +
"</solr>";
private static final String BAD_SOLR_XML =
"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" +
"<solr persistent=\"false\">\n" +
" <cores adminPath=\"/admin/cores\">\n" +
" <core name=\"col_ok\" instanceDir=\"col_ok\" />\n" +
" <core name=\"col_bad\" instanceDir=\"col_bad\" />\n" +
" </cores>\n" +
"</solr>";
}