@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(); } }
@Test public void testRefCount() throws Exception { SolrCore core = h.getCore(); assertTrue("Refcount != 1", core.getOpenCount() == 1); final CoreContainer cores = h.getCoreContainer(); SolrCore c1 = cores.getCore(SolrTestCaseJ4.DEFAULT_TEST_CORENAME); assertTrue("Refcount != 2", core.getOpenCount() == 2); ClosingRequestHandler handler1 = new ClosingRequestHandler(); handler1.inform(core); String path = "/this/is A path /that won't be registered!"; SolrRequestHandler old = core.registerRequestHandler(path, handler1); assertNull(old); // should not be anything... assertEquals(core.getRequestHandlers().get(path), handler1); SolrCore c2 = cores.getCore(SolrTestCaseJ4.DEFAULT_TEST_CORENAME); c1.close(); assertTrue("Refcount < 1", core.getOpenCount() >= 1); assertTrue("Handler is closed", handler1.closed == false); c1 = cores.getCore(SolrTestCaseJ4.DEFAULT_TEST_CORENAME); assertTrue("Refcount < 2", core.getOpenCount() >= 2); assertTrue("Handler is closed", handler1.closed == false); c2.close(); assertTrue("Refcount < 1", core.getOpenCount() >= 1); assertTrue("Handler is closed", handler1.closed == false); c1.close(); cores.shutdown(); assertTrue("Refcount != 0", core.getOpenCount() == 0); assertTrue("Handler not closed", core.isClosed() && handler1.closed == true); }
// 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(); } }
protected SolrCore registerCore(String name, SolrCore core, boolean registerInZk) { if (core == null) { throw new RuntimeException("Can not register a null core."); } // We can register a core when creating them via the admin UI, so we need to ensure that the // dynamic descriptors // are up to date CoreDescriptor cd = core.getCoreDescriptor(); if ((cd.isTransient() || !cd.isLoadOnStartup()) && solrCores.getDynamicDescriptor(name) == null) { // Store it away for later use. includes non-transient but not // loaded at startup cores. solrCores.putDynamicDescriptor(name, cd); } SolrCore old; if (isShutDown) { core.close(); throw new IllegalStateException("This CoreContainer has been closed"); } if (cd.isTransient()) { old = solrCores.putTransientCore(cfg, name, core, loader); } else { old = solrCores.putCore(name, core); } /* * set both the name of the descriptor and the name of the * core, since the descriptors name is used for persisting. */ core.setName(name); coreInitFailures.remove(name); if (old == null || old == core) { log.info("registering core: " + name); if (registerInZk) { zkSys.registerInZk(core, false); } return null; } else { log.info("replacing core: " + name); old.close(); if (registerInZk) { zkSys.registerInZk(core, false); } return old; } }
@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(); } }
/** * Handle "UNLOAD" Action * * @param req * @param rsp * @return true if a modification has resulted that requires persistance of the CoreContainer * configuration. */ protected boolean handleUnloadAction(SolrQueryRequest req, SolrQueryResponse rsp) throws SolrException { SolrParams params = req.getParams(); String cname = params.get(CoreAdminParams.CORE); SolrCore core = coreContainer.remove(cname); if (core == null) { throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, "No such core exists '" + cname + "'"); } if (params.getBool(CoreAdminParams.DELETE_INDEX, false)) { core.addCloseHook( new CloseHook() { @Override public void preClose(SolrCore core) {} @Override public void postClose(SolrCore core) { File dataDir = new File(core.getIndexDir()); for (File file : dataDir.listFiles()) { if (!file.delete()) { log.error(file.getAbsolutePath() + " could not be deleted on core unload"); } } if (!dataDir.delete()) log.error(dataDir.getAbsolutePath() + " could not be deleted on core unload"); } }); } core.close(); return coreContainer.isPersistent(); }
@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(); } }
private final long getCoreStartTime(final CoreContainer cc, final String name) { SolrCore tmp = cc.getCore(name); try { return tmp.getStartTime(); } finally { tmp.close(); } }
@Test public void testClose() throws Exception { final CoreContainer cores = h.getCoreContainer(); SolrCore core = cores.getCore(SolrTestCaseJ4.DEFAULT_TEST_CORENAME); ClosingRequestHandler handler1 = new ClosingRequestHandler(); handler1.inform(core); String path = "/this/is A path /that won't be registered 2!!!!!!!!!!!"; SolrRequestHandler old = core.registerRequestHandler(path, handler1); assertNull(old); // should not be anything... assertEquals(core.getRequestHandlers().get(path), handler1); core.close(); cores.shutdown(); assertTrue("Handler not closed", handler1.closed == true); }
/** * Handle "RENAME" Action * * @param req * @param rsp * @return true if a modification has resulted that requires persistance of the CoreContainer * configuration. * @throws SolrException */ protected boolean handleRenameAction(SolrQueryRequest req, SolrQueryResponse rsp) throws SolrException { SolrParams params = req.getParams(); String name = params.get(CoreAdminParams.OTHER); String cname = params.get(CoreAdminParams.CORE); boolean doPersist = false; if (cname.equals(name)) return doPersist; SolrCore core = coreContainer.getCore(cname); if (core != null) { doPersist = coreContainer.isPersistent(); coreContainer.register(name, core, false); coreContainer.remove(cname); core.close(); } return doPersist; }
protected NamedList<Object> getCoreStatus(CoreContainer cores, String cname) throws IOException { NamedList<Object> info = new SimpleOrderedMap<Object>(); SolrCore core = cores.getCore(cname); if (core != null) { try { info.add("name", core.getName()); info.add("instanceDir", normalizePath(core.getResourceLoader().getInstanceDir())); info.add("dataDir", normalizePath(core.getDataDir())); info.add("startTime", new Date(core.getStartTime())); info.add("uptime", System.currentTimeMillis() - core.getStartTime()); RefCounted<SolrIndexSearcher> searcher = core.getSearcher(); try { info.add("index", LukeRequestHandler.getIndexInfo(searcher.get().getReader(), false)); } finally { searcher.decref(); } } finally { core.close(); } } return info; }
@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(); } }
// It's important that this be the _only_ thread removing things from pendingDynamicCloses! // This is single-threaded, but I tried a multi-threaded approach and didn't see any performance // gains, so // there's no good justification for the complexity. I suspect that the locking on things like // DefaultSolrCoreState // essentially create a single-threaded process anyway. @Override public void run() { while (!container.isShutDown()) { synchronized (solrCores.getModifyLock()) { // need this so we can wait and be awoken. try { solrCores.getModifyLock().wait(); } catch (InterruptedException e) { // Well, if we've been told to stop, we will. Otherwise, continue on and check to see if // there are // any cores to close. } } for (SolrCore removeMe = solrCores.getCoreToClose(); removeMe != null && !container.isShutDown(); removeMe = solrCores.getCoreToClose()) { try { removeMe.close(); } finally { solrCores.removeFromPendingOps(removeMe.getName()); } } } }
private void removeOne(CoreContainer cc, String coreName) { SolrCore tmp = cc.remove(coreName); if (tmp != null) tmp.close(); }
@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(); } }
protected boolean handleMergeAction(SolrQueryRequest req, SolrQueryResponse rsp) throws IOException { SolrParams params = req.getParams(); String cname = params.required().get(CoreAdminParams.CORE); SolrCore core = coreContainer.getCore(cname); SolrCore[] sourceCores = null; RefCounted<SolrIndexSearcher>[] searchers = null; // stores readers created from indexDir param values IndexReader[] readersToBeClosed = null; if (core != null) { try { String[] dirNames = params.getParams(CoreAdminParams.INDEX_DIR); if (dirNames == null || dirNames.length == 0) { String[] sources = params.getParams("srcCore"); if (sources == null || sources.length == 0) throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, "At least one indexDir or srcCore must be specified"); sourceCores = new SolrCore[sources.length]; for (int i = 0; i < sources.length; i++) { String source = sources[i]; SolrCore srcCore = coreContainer.getCore(source); if (srcCore == null) throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, "Core: " + source + " does not exist"); sourceCores[i] = srcCore; } } else { readersToBeClosed = new IndexReader[dirNames.length]; DirectoryFactory dirFactory = core.getDirectoryFactory(); for (int i = 0; i < dirNames.length; i++) { readersToBeClosed[i] = IndexReader.open(dirFactory.open(dirNames[i]), true); } } IndexReader[] readers = null; if (readersToBeClosed != null) { readers = readersToBeClosed; } else { readers = new IndexReader[sourceCores.length]; searchers = new RefCounted[sourceCores.length]; for (int i = 0; i < sourceCores.length; i++) { SolrCore solrCore = sourceCores[i]; // record the searchers so that we can decref searchers[i] = solrCore.getSearcher(); readers[i] = searchers[i].get().getIndexReader(); } } UpdateRequestProcessorChain processorChain = core.getUpdateProcessingChain(params.get(UpdateParams.UPDATE_CHAIN)); SolrQueryRequest wrappedReq = new LocalSolrQueryRequest(core, req.getParams()); UpdateRequestProcessor processor = processorChain.createProcessor(wrappedReq, rsp); processor.processMergeIndexes(new MergeIndexesCommand(readers)); } finally { if (searchers != null) { for (RefCounted<SolrIndexSearcher> searcher : searchers) { if (searcher != null) searcher.decref(); } } if (sourceCores != null) { for (SolrCore solrCore : sourceCores) { if (solrCore != null) solrCore.close(); } } if (readersToBeClosed != null) IOUtils.closeWhileHandlingException(readersToBeClosed); core.close(); } } return coreContainer.isPersistent(); }
// 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(); } }