package org.apache.solr.core; /* * 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. */ import org.apache.commons.codec.Charsets; import org.apache.commons.io.FileUtils; import org.apache.solr.SolrTestCaseJ4; import org.apache.solr.common.SolrException; import org.apache.solr.common.params.CoreAdminParams; import org.apache.solr.common.util.NamedList; import org.apache.solr.handler.admin.CoreAdminHandler; import org.apache.solr.request.LocalSolrQueryRequest; import org.apache.solr.request.SolrQueryRequest; import org.apache.solr.response.SolrQueryResponse; import org.apache.solr.search.SolrIndexSearcher; import org.apache.solr.update.AddUpdateCommand; import org.apache.solr.update.CommitUpdateCommand; import org.apache.solr.update.UpdateHandler; import org.apache.solr.util.RefCounted; import org.apache.solr.util.TestHarness; import org.junit.After; import org.junit.BeforeClass; import org.junit.Test; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Pattern; public class TestLazyCores extends SolrTestCaseJ4 { @BeforeClass public static void beforeClass() throws Exception { initCore("solrconfig-minimal.xml", "schema-tiny.xml"); } private final File solrHomeDirectory = new File(TEMP_DIR, TestLazyCores.getSimpleClassName()); private CoreContainer init() throws Exception { if (solrHomeDirectory.exists()) { FileUtils.deleteDirectory(solrHomeDirectory); } assertTrue("Failed to mkdirs workDir", solrHomeDirectory.mkdirs()); for (int idx = 1; idx < 10; ++idx) { copyMinConf(new File(solrHomeDirectory, "collection" + idx)); } SolrResourceLoader loader = new SolrResourceLoader(solrHomeDirectory.getAbsolutePath()); File solrXml = new File(solrHomeDirectory, "solr.xml"); FileUtils.write(solrXml, LOTS_SOLR_XML, Charsets.UTF_8.toString()); ConfigSolrXmlOld config = (ConfigSolrXmlOld) ConfigSolr.fromFile(loader, solrXml); CoresLocator locator = new SolrXMLCoresLocator.NonPersistingLocator(LOTS_SOLR_XML, config); final CoreContainer cores = new CoreContainer(loader, config, locator); cores.load(); return cores; } @After public void after() throws Exception { if (solrHomeDirectory.exists()) { FileUtils.deleteDirectory(solrHomeDirectory); } } @Test public void testLazyLoad() throws Exception { CoreContainer cc = init(); try { // NOTE: This checks the initial state for loading, no need to do this elsewhere. checkInCores(cc, "collection1", "collectionLazy2", "collectionLazy5"); checkNotInCores(cc, "collectionLazy3", "collectionLazy4", "collectionLazy6", "collectionLazy7", "collectionLazy8", "collectionLazy9"); SolrCore core1 = cc.getCore("collection1"); assertFalse("core1 should not be transient", core1.getCoreDescriptor().isTransient()); assertTrue("core1 should be loadable", core1.getCoreDescriptor().isLoadOnStartup()); assertNotNull(core1.getSolrConfig()); SolrCore core2 = cc.getCore("collectionLazy2"); assertTrue("core2 should be transient", core2.getCoreDescriptor().isTransient()); assertTrue("core2 should be loadable", core2.getCoreDescriptor().isLoadOnStartup()); SolrCore core3 = cc.getCore("collectionLazy3"); assertTrue("core3 should be transient", core3.getCoreDescriptor().isTransient()); assertFalse("core3 should not be loadable", core3.getCoreDescriptor().isLoadOnStartup()); SolrCore core4 = cc.getCore("collectionLazy4"); assertFalse("core4 should not be transient", core4.getCoreDescriptor().isTransient()); assertFalse("core4 should not be loadable", core4.getCoreDescriptor().isLoadOnStartup()); SolrCore core5 = cc.getCore("collectionLazy5"); assertFalse("core5 should not be transient", core5.getCoreDescriptor().isTransient()); assertTrue("core5 should be loadable", core5.getCoreDescriptor().isLoadOnStartup()); core1.close(); core2.close(); core3.close(); core4.close(); core5.close(); } finally { cc.shutdown(); } } // This is a little weak. I'm not sure how to test that lazy core2 is loaded automagically. The getCore // will, of course, load it. private void checkSearch(SolrCore core) throws IOException { addLazy(core, "id", "0"); addLazy(core, "id", "1", "v_t", "Hello Dude"); addLazy(core, "id", "2", "v_t", "Hello Yonik"); addLazy(core, "id", "3", "v_s", "{!literal}"); addLazy(core, "id", "4", "v_s", "other stuff"); addLazy(core, "id", "5", "v_f", "3.14159"); addLazy(core, "id", "6", "v_f", "8983"); SolrQueryRequest req = makeReq(core); CommitUpdateCommand cmtCmd = new CommitUpdateCommand(req, false); core.getUpdateHandler().commit(cmtCmd); // Just get a couple of searches to work! assertQ("test prefix query", makeReq(core, "q", "{!prefix f=v_t}hel", "wt", "xml") , "//result[@numFound='2']" ); assertQ("test raw query", makeReq(core, "q", "{!raw f=v_t}hello", "wt", "xml") , "//result[@numFound='2']" ); // no analysis is done, so these should match nothing assertQ("test raw query", makeReq(core, "q", "{!raw f=v_t}Hello", "wt", "xml") , "//result[@numFound='0']" ); assertQ("test raw query", makeReq(core, "q", "{!raw f=v_f}1.5", "wt", "xml") , "//result[@numFound='0']" ); } @Test public void testLazySearch() throws Exception { CoreContainer cc = init(); try { // Make sure Lazy4 isn't loaded. Should be loaded on the get checkNotInCores(cc, "collectionLazy4"); SolrCore core4 = cc.getCore("collectionLazy4"); checkSearch(core4); // Now just insure that the normal searching on "collection1" finds _0_ on the same query that found _2_ above. // Use of makeReq above and req below is tricky, very tricky. assertQ("test raw query", req("q", "{!raw f=v_t}hello", "wt", "xml") , "//result[@numFound='0']" ); checkInCores(cc, "collectionLazy4"); core4.close(); } finally { cc.shutdown(); } } @Test public void testCachingLimit() throws Exception { CoreContainer cc = init(); try { // First check that all the cores that should be loaded at startup actually are. checkInCores(cc, "collection1", "collectionLazy2", "collectionLazy5"); checkNotInCores(cc, "collectionLazy3", "collectionLazy4", "collectionLazy6", "collectionLazy7", "collectionLazy8", "collectionLazy9"); // By putting these in non-alpha order, we're also checking that we're not just seeing an artifact. SolrCore core1 = cc.getCore("collection1"); SolrCore core3 = cc.getCore("collectionLazy3"); SolrCore core4 = cc.getCore("collectionLazy4"); SolrCore core2 = cc.getCore("collectionLazy2"); SolrCore core5 = cc.getCore("collectionLazy5"); checkInCores(cc, "collection1", "collectionLazy2", "collectionLazy3", "collectionLazy4", "collectionLazy5"); checkNotInCores(cc, "collectionLazy6", "collectionLazy7", "collectionLazy8", "collectionLazy9"); // map should be full up, add one more and verify SolrCore core6 = cc.getCore("collectionLazy6"); checkInCores(cc, "collection1", "collectionLazy2", "collectionLazy3", "collectionLazy4", "collectionLazy5", "collectionLazy6"); checkNotInCores(cc, "collectionLazy7", "collectionLazy8", "collectionLazy9"); SolrCore core7 = cc.getCore("collectionLazy7"); checkInCores(cc, "collection1", "collectionLazy2", "collectionLazy3", "collectionLazy4", "collectionLazy5", "collectionLazy6", "collectionLazy7"); checkNotInCores(cc, "collectionLazy8", "collectionLazy9"); SolrCore core8 = cc.getCore("collectionLazy8"); checkInCores(cc, "collection1", "collectionLazy2", "collectionLazy4", "collectionLazy5", "collectionLazy6", "collectionLazy7", "collectionLazy8"); checkNotInCores(cc, "collectionLazy3", "collectionLazy9"); SolrCore core9 = cc.getCore("collectionLazy9"); checkInCores(cc, "collection1", "collectionLazy4", "collectionLazy5", "collectionLazy6", "collectionLazy7", "collectionLazy8", "collectionLazy9"); checkNotInCores(cc, "collectionLazy2", "collectionLazy3"); // Note decrementing the count when the core is removed from the lazyCores list is appropriate, since the // refcount is 1 when constructed. anyone _else_ who's opened up one has to close it. core1.close(); core2.close(); core3.close(); core4.close(); core5.close(); core6.close(); core7.close(); core8.close(); core9.close(); } finally { cc.shutdown(); } } // Test case for SOLR-4300 @Test public void testRace() throws Exception { final List<SolrCore> theCores = new ArrayList<>(); final CoreContainer cc = init(); try { Thread[] threads = new Thread[15]; for (int idx = 0; idx < threads.length; idx++) { threads[idx] = new Thread() { @Override public void run() { SolrCore core = cc.getCore("collectionLazy3"); synchronized (theCores) { theCores.add(core); } } }; threads[idx].start(); } for (Thread thread : threads) { thread.join(); } for (int idx = 0; idx < theCores.size() - 1; ++idx) { assertEquals("Cores should be the same!", theCores.get(idx), theCores.get(idx + 1)); } for (SolrCore core : theCores) { core.close(); } } finally { cc.shutdown(); } } private void tryCreateFail(CoreAdminHandler admin, String name, String dataDir, String... errs) throws Exception { try { SolrQueryResponse resp = new SolrQueryResponse(); SolrQueryRequest request = req(CoreAdminParams.ACTION, CoreAdminParams.CoreAdminAction.CREATE.toString(), CoreAdminParams.DATA_DIR, dataDir, CoreAdminParams.NAME, name, "schema", "schema.xml", "config", "solrconfig.xml"); admin.handleRequestBody(request, resp); fail("Should have thrown an error"); } catch (SolrException se) { //SolrException cause = (SolrException)se.getCause(); assertEquals("Exception code should be 500", 500, se.code()); for (String err : errs) { assertTrue("Should have seen an exception containing the an error", se.getMessage().contains(err)); } } } @Test public void testCreateSame() throws Exception { final CoreContainer cc = init(); try { // First, try all 4 combinations of load on startup and transient final CoreAdminHandler admin = new CoreAdminHandler(cc); SolrCore lc2 = cc.getCore("collectionLazy2"); SolrCore lc4 = cc.getCore("collectionLazy4"); SolrCore lc5 = cc.getCore("collectionLazy5"); SolrCore lc6 = cc.getCore("collectionLazy6"); copyMinConf(new File(solrHomeDirectory, "t2")); copyMinConf(new File(solrHomeDirectory, "t4")); copyMinConf(new File(solrHomeDirectory, "t5")); copyMinConf(new File(solrHomeDirectory, "t6")); // Should also fail with the same name tryCreateFail(admin, "collectionLazy2", "t12", "Core with name", "collectionLazy2", "already exists"); tryCreateFail(admin, "collectionLazy4", "t14", "Core with name", "collectionLazy4", "already exists"); tryCreateFail(admin, "collectionLazy5", "t15", "Core with name", "collectionLazy5", "already exists"); tryCreateFail(admin, "collectionLazy6", "t16", "Core with name", "collectionLazy6", "already exists"); lc2.close(); lc4.close(); lc5.close(); lc6.close(); } finally { cc.shutdown(); } } private void createViaAdmin(CoreContainer cc, String name, String instanceDir, boolean isTransient, boolean loadOnStartup) throws Exception { final CoreAdminHandler admin = new CoreAdminHandler(cc); SolrQueryResponse resp = new SolrQueryResponse(); admin.handleRequestBody (req(CoreAdminParams.ACTION, CoreAdminParams.CoreAdminAction.CREATE.toString(), CoreAdminParams.INSTANCE_DIR, instanceDir, CoreAdminParams.NAME, name, CoreAdminParams.TRANSIENT, Boolean.toString(isTransient), CoreAdminParams.LOAD_ON_STARTUP, Boolean.toString(loadOnStartup)), resp); } private void unloadViaAdmin(CoreContainer cc, String name) throws Exception { final CoreAdminHandler admin = new CoreAdminHandler(cc); SolrQueryResponse resp = new SolrQueryResponse(); admin.handleRequestBody (req(CoreAdminParams.ACTION, CoreAdminParams.CoreAdminAction.UNLOAD.toString(), CoreAdminParams.CORE, name), resp); } // Make sure that creating a transient core from the admin handler correctly respects the transient limits etc. @Test public void testCreateTransientFromAdmin() throws Exception { final CoreContainer cc = init(); try { copyMinConf(new File(solrHomeDirectory, "core1")); copyMinConf(new File(solrHomeDirectory, "core2")); copyMinConf(new File(solrHomeDirectory, "core3")); copyMinConf(new File(solrHomeDirectory, "core4")); copyMinConf(new File(solrHomeDirectory, "core5")); createViaAdmin(cc, "core1", "./core1", true, true); createViaAdmin(cc, "core2", "./core2", true, false); createViaAdmin(cc, "core3", "./core3", true, true); createViaAdmin(cc, "core4", "./core4", true, false); createViaAdmin(cc, "core5", "./core5", true, false); SolrCore c1 = cc.getCore("core1"); SolrCore c2 = cc.getCore("core2"); SolrCore c3 = cc.getCore("core3"); SolrCore c4 = cc.getCore("core4"); SolrCore c5 = cc.getCore("core5"); checkNotInCores(cc, "core1", "collectionLazy2", "collectionLazy3", "collectionLazy4", "collectionLazy6" , "collectionLazy7", "collectionLazy8", "collectionLazy9"); checkInCores(cc, "collection1", "collectionLazy5", "core2", "core3", "core4", "core5"); // While we're at it, a test for SOLR-5366, unloading transient core that's been unloaded b/c it's // transient generates a "too many closes" errorl unloadViaAdmin(cc, "core1"); unloadViaAdmin(cc, "core2"); unloadViaAdmin(cc, "core3"); unloadViaAdmin(cc, "core4"); unloadViaAdmin(cc, "core5"); c1.close(); c2.close(); c3.close(); c4.close(); c5.close(); } finally { cc.shutdown(); } } //Make sure persisting not-loaded lazy cores is done. See SOLR-4347 @Test public void testPersistence() throws Exception { final CoreContainer cc = init(); try { copyMinConf(new File(solrHomeDirectory, "core1")); copyMinConf(new File(solrHomeDirectory, "core2")); copyMinConf(new File(solrHomeDirectory, "core3")); copyMinConf(new File(solrHomeDirectory, "core4")); final CoreDescriptor cd1 = buildCoreDescriptor(cc, "core1", "./core1") .isTransient(true).loadOnStartup(true).build(); final CoreDescriptor cd2 = buildCoreDescriptor(cc, "core2", "./core2") .isTransient(true).loadOnStartup(false).build(); final CoreDescriptor cd3 = buildCoreDescriptor(cc, "core3", "./core3") .isTransient(false).loadOnStartup(true).build(); final CoreDescriptor cd4 = buildCoreDescriptor(cc, "core4", "./core4") .isTransient(false).loadOnStartup(false).build(); SolrCore core1 = cc.create(cd1); SolrCore core2 = cc.create(cd2); SolrCore core3 = cc.create(cd3); SolrCore core4 = cc.create(cd4); SolrXMLCoresLocator.NonPersistingLocator locator = (SolrXMLCoresLocator.NonPersistingLocator) cc.getCoresLocator(); TestHarness.validateXPath(locator.xml, "/solr/cores/core[@name='collection1']", "/solr/cores/core[@name='collectionLazy2']", "/solr/cores/core[@name='collectionLazy3']", "/solr/cores/core[@name='collectionLazy4']", "/solr/cores/core[@name='collectionLazy5']", "/solr/cores/core[@name='collectionLazy6']", "/solr/cores/core[@name='collectionLazy7']", "/solr/cores/core[@name='collectionLazy8']", "/solr/cores/core[@name='collectionLazy9']", "/solr/cores/core[@name='core1']", "/solr/cores/core[@name='core2']", "/solr/cores/core[@name='core3']", "/solr/cores/core[@name='core4']", "13=count(/solr/cores/core)"); removeOne(cc, "collectionLazy2"); removeOne(cc, "collectionLazy3"); removeOne(cc, "collectionLazy4"); removeOne(cc, "collectionLazy5"); removeOne(cc, "collectionLazy6"); removeOne(cc, "collectionLazy7"); removeOne(cc, "core1"); removeOne(cc, "core2"); removeOne(cc, "core3"); removeOne(cc, "core4"); // now test that unloading a core means the core is not persisted TestHarness.validateXPath(locator.xml, "3=count(/solr/cores/core)"); } finally { cc.shutdown(); } } // Test that transient cores // 1> produce errors as appropriate when the config or schema files are foo'd // 2> "self heal". That is, if the problem is corrected can the core be reloaded and used? // 3> that OK cores can be searched even when some cores failed to load. @Test public void testBadConfigsGenerateErrors() throws Exception { final CoreContainer cc = initGoodAndBad(Arrays.asList("core1", "core2"), Arrays.asList("badSchema1", "badSchema2"), Arrays.asList("badConfig1", "badConfig2")); try { // first, did the two good cores load successfully? checkInCores(cc, "core1", "core2"); // Did the bad cores fail to load? checkNotInCores(cc, "badSchema1", "badSchema2", "badConfig1", "badConfig2"); // Can we still search the "good" cores even though there were core init failures? SolrCore core1 = cc.getCore("core1"); checkSearch(core1); // Did we get the expected message for each of the cores that failed to load? Make sure we don't run afoul of // the dreaded slash/backslash difference on Windows and *nix machines. testMessage(cc.getCoreInitFailures(), "TestLazyCores" + File.separator + "badConfig1" + File.separator + "solrconfig.xml"); testMessage(cc.getCoreInitFailures(), "TestLazyCores" + File.separator + "badConfig2" + File.separator + "solrconfig.xml"); testMessage(cc.getCoreInitFailures(), "TestLazyCores" + File.separator + "badSchema1" + File.separator + "schema.xml"); testMessage(cc.getCoreInitFailures(), "TestLazyCores" + File.separator + "badSchema2" + File.separator + "schema.xml"); // Status should report that there are failure messages for the bad cores and none for the good cores. checkStatus(cc, true, "core1"); checkStatus(cc, true, "core2"); checkStatus(cc, false, "badSchema1"); checkStatus(cc, false, "badSchema2"); checkStatus(cc, false, "badConfig1"); checkStatus(cc, false, "badConfig2"); // Copy good config and schema files in and see if you can then load them (they are transient after all) copyGoodConf("badConfig1", "solrconfig-minimal.xml", "solrconfig.xml"); copyGoodConf("badConfig2", "solrconfig-minimal.xml", "solrconfig.xml"); copyGoodConf("badSchema1", "schema-tiny.xml", "schema.xml"); copyGoodConf("badSchema2", "schema-tiny.xml", "schema.xml"); // This should force a reload of the cores. SolrCore bc1 = cc.getCore("badConfig1"); SolrCore bc2 = cc.getCore("badConfig2"); SolrCore bs1 = cc.getCore("badSchema1"); SolrCore bs2 = cc.getCore("badSchema2"); // all the cores should be found in the list now. checkInCores(cc, "core1", "core2", "badSchema1", "badSchema2", "badConfig1", "badConfig2"); // Did we clear out the errors by putting good files in place? And the cores that never were bad should be OK too. checkStatus(cc, true, "core1"); checkStatus(cc, true, "core2"); checkStatus(cc, true, "badSchema1"); checkStatus(cc, true, "badSchema2"); checkStatus(cc, true, "badConfig1"); checkStatus(cc, true, "badConfig2"); // Are the formerly bad cores now searchable? Testing one of each should do. checkSearch(core1); checkSearch(bc1); checkSearch(bs1); core1.close(); bc1.close(); bc2.close(); bs1.close(); bs2.close(); } finally { cc.shutdown(); } } // See fi the message you expect is in the list of failures private void testMessage(Map<String, Exception> failures, String lookFor) { for (Exception e : failures.values()) { if (e.getMessage().indexOf(lookFor) != -1) return; } fail("Should have found message containing these tokens " + lookFor + " in the failure messages"); } // Just localizes writing a configuration rather than repeating it for good and bad files. private void writeCustomConfig(String coreName, String config, String schema, String rand_snip) throws IOException { File coreRoot = new File(solrHomeDirectory, coreName); File subHome = new File(coreRoot, "conf"); if (!coreRoot.exists()) { assertTrue("Failed to make subdirectory ", coreRoot.mkdirs()); } // Write the file for core discovery FileUtils.writeStringToFile(new File(coreRoot, "core.properties"), "name=" + coreName + System.getProperty("line.separator") + "transient=true" + System.getProperty("line.separator") + "loadOnStartup=true", Charsets.UTF_8.toString()); FileUtils.writeStringToFile(new File(subHome, "solrconfig.snippet.randomindexconfig.xml"), rand_snip, Charsets.UTF_8.toString()); FileUtils.writeStringToFile(new File(subHome, "solrconfig.xml"), config, Charsets.UTF_8.toString()); FileUtils.writeStringToFile(new File(subHome, "schema.xml"), schema, Charsets.UTF_8.toString()); } // Write out the cores' config files, both bad schema files, bad config files as well as some good cores. private CoreContainer initGoodAndBad(List<String> goodCores, List<String> badSchemaCores, List<String> badConfigCores) throws Exception { // Don't pollute the log with exception traces when they're expected. ignoreException(Pattern.quote("SAXParseException")); if (solrHomeDirectory.exists()) { FileUtils.deleteDirectory(solrHomeDirectory); } assertTrue("Failed to mkdirs workDir", solrHomeDirectory.mkdirs()); // Create the cores that should be fine. for (String coreName : goodCores) { File coreRoot = new File(solrHomeDirectory, coreName); copyMinConf(coreRoot, "name=" + coreName); } // Collect the files that we'll write to the config directories. String top = SolrTestCaseJ4.TEST_HOME() + "/collection1/conf"; String min_schema = FileUtils.readFileToString(new File(top, "schema-tiny.xml"), Charsets.UTF_8.toString()); String min_config = FileUtils.readFileToString(new File(top, "solrconfig-minimal.xml"), Charsets.UTF_8.toString()); String rand_snip = FileUtils.readFileToString(new File(top, "solrconfig.snippet.randomindexconfig.xml"), Charsets.UTF_8.toString()); // Now purposely mess up the config files, introducing stupid syntax errors. String bad_config = min_config.replace("<requestHandler", "<reqsthalr"); String bad_schema = min_schema.replace("<field", "<filed"); // Create the cores with bad configs for (String coreName : badConfigCores) { writeCustomConfig(coreName, bad_config, min_schema, rand_snip); } // Create the cores with bad schemas. for (String coreName : badSchemaCores) { writeCustomConfig(coreName, min_config, bad_schema, rand_snip); } // Write the solr.xml file. Cute how minimal it can be now.... File solrXml = new File(solrHomeDirectory, "solr.xml"); FileUtils.write(solrXml, "<solr/>", Charsets.UTF_8.toString()); SolrResourceLoader loader = new SolrResourceLoader(solrHomeDirectory.getAbsolutePath()); ConfigSolrXml config = (ConfigSolrXml) ConfigSolr.fromFile(loader, solrXml); CoresLocator locator = new CorePropertiesLocator(solrHomeDirectory.getAbsolutePath()); // OK this should succeed, but at the end we should have recorded a series of errors. final CoreContainer cores = new CoreContainer(loader, config, locator); cores.load(); return cores; } // We want to see that the core "heals itself" if an un-corrupted file is written to the directory. private void copyGoodConf(String coreName, String srcName, String dstName) throws IOException { File coreRoot = new File(solrHomeDirectory, coreName); File subHome = new File(coreRoot, "conf"); String top = SolrTestCaseJ4.TEST_HOME() + "/collection1/conf"; FileUtils.copyFile(new File(top, srcName), new File(subHome, dstName)); } // If ok==true, we shouldn't be seeing any failure cases. // if ok==false, the core being examined should have a failure in the list. private void checkStatus(CoreContainer cc, Boolean ok, String core) throws Exception { SolrQueryResponse resp = new SolrQueryResponse(); final CoreAdminHandler admin = new CoreAdminHandler(cc); admin.handleRequestBody (req(CoreAdminParams.ACTION, CoreAdminParams.CoreAdminAction.STATUS.toString(), CoreAdminParams.CORE, core), resp); Map<String, Exception> failures = (Map<String, Exception>) resp.getValues().get("initFailures"); if (ok) { if (failures.size() != 0) { fail("Should have cleared the error, but there are failues " + failures.toString()); } } else { if (failures.size() == 0) { fail("Should have had errors here but the status return has no failures!"); } } } private void removeOne(CoreContainer cc, String coreName) { SolrCore tmp = cc.remove(coreName); if (tmp != null) tmp.close(); } public static void checkNotInCores(CoreContainer cc, String... nameCheck) { Collection<String> names = cc.getCoreNames(); for (String name : nameCheck) { assertFalse("core " + name + " was found in the list of cores", names.contains(name)); } } public static void checkInCores(CoreContainer cc, String... nameCheck) { Collection<String> names = cc.getCoreNames(); for (String name : nameCheck) { assertTrue("core " + name + " was not found in the list of cores", names.contains(name)); } } private void addLazy(SolrCore core, String... fieldValues) throws IOException { UpdateHandler updater = core.getUpdateHandler(); AddUpdateCommand cmd = new AddUpdateCommand(makeReq(core)); cmd.solrDoc = sdoc((Object[])fieldValues); updater.addDoc(cmd); } private LocalSolrQueryRequest makeReq(SolrCore core, String... q) { if (q.length == 1) { return new LocalSolrQueryRequest(core, q[0], null, 0, 20, new HashMap<String, String>()); } if (q.length % 2 != 0) { throw new RuntimeException("The length of the string array (query arguments) needs to be even"); } NamedList.NamedListEntry[] entries = new NamedList.NamedListEntry[q.length / 2]; for (int i = 0; i < q.length; i += 2) { entries[i / 2] = new NamedList.NamedListEntry<>(q[i], q[i + 1]); } return new LocalSolrQueryRequest(core, new NamedList<>(entries)); } private final static String LOTS_SOLR_XML = " <solr persistent=\"false\"> " + "<cores adminPath=\"/admin/cores\" defaultCoreName=\"collectionLazy2\" transientCacheSize=\"4\"> " + "<core name=\"collection1\" instanceDir=\"collection1\" /> " + "<core name=\"collectionLazy2\" instanceDir=\"collection2\" transient=\"true\" loadOnStartup=\"true\" /> " + "<core name=\"collectionLazy3\" instanceDir=\"collection3\" transient=\"on\" loadOnStartup=\"false\" /> " + "<core name=\"collectionLazy4\" instanceDir=\"collection4\" transient=\"false\" loadOnStartup=\"false\" /> " + "<core name=\"collectionLazy5\" instanceDir=\"collection5\" transient=\"false\" loadOnStartup=\"true\" /> " + "<core name=\"collectionLazy6\" instanceDir=\"collection6\" transient=\"true\" loadOnStartup=\"false\" /> " + "<core name=\"collectionLazy7\" instanceDir=\"collection7\" transient=\"true\" loadOnStartup=\"false\" /> " + "<core name=\"collectionLazy8\" instanceDir=\"collection8\" transient=\"true\" loadOnStartup=\"false\" /> " + "<core name=\"collectionLazy9\" instanceDir=\"collection9\" transient=\"true\" loadOnStartup=\"false\" /> " + "</cores> " + "</solr>"; }