From 77e3dfc0168bed883d4e2703e0d38dff7ef43e00 Mon Sep 17 00:00:00 2001 From: Shalin Shekhar Mangar Date: Wed, 22 Jun 2011 11:18:43 +0000 Subject: [PATCH] SOLR-2610 -- Add an option to delete index through CoreAdmin UNLOAD action git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1138405 13f79535-47bb-0310-9956-ffa450edef68 --- solr/CHANGES.txt | 8 +++ .../solr/common/params/CoreAdminParams.java | 3 ++ .../java/org/apache/solr/core/CloseHook.java | 53 ++++++++++++------- .../java/org/apache/solr/core/SolrCore.java | 12 ++++- .../solr/handler/ReplicationHandler.java | 6 ++- .../solr/handler/admin/CoreAdminHandler.java | 29 +++++++--- .../solrj/request/CoreAdminRequest.java | 34 ++++++++++-- .../solrj/MultiCoreExampleTestBase.java | 12 +++++ .../org/apache/solr/core/SolrCoreTest.java | 6 ++- 9 files changed, 128 insertions(+), 35 deletions(-) diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt index bd84a35e3f2..80f1cefd86f 100644 --- a/solr/CHANGES.txt +++ b/solr/CHANGES.txt @@ -251,6 +251,12 @@ Documentation ================== 3.3.0 ================== +Upgrading from Solr 3.2.0 +---------------------- +The SolrCore's CloseHook API has been changed in a backward-incompatible way. +Any custom components which use the SolrCore.addCloseHook method will need to +be modified accordingly. + New Features ---------------------- @@ -276,6 +282,8 @@ New Features * SOLR-1331 -- Added a srcCore parameter to CoreAdminHandler's mergeindexes action to merge one or more cores' indexes to a target core (shalin) +* SOLR-2610 -- Add an option to delete index through CoreAdmin UNLOAD action (shalin) + Optimizations ---------------------- diff --git a/solr/src/common/org/apache/solr/common/params/CoreAdminParams.java b/solr/src/common/org/apache/solr/common/params/CoreAdminParams.java index 0691264e240..1e8e7022571 100644 --- a/solr/src/common/org/apache/solr/common/params/CoreAdminParams.java +++ b/solr/src/common/org/apache/solr/common/params/CoreAdminParams.java @@ -69,6 +69,9 @@ public interface CoreAdminParams /** The shard id in solr cloud */ public final static String SHARD = "shard"; + /** If you unload a core, delete the index too */ + public final static String DELETE_INDEX = "deleteIndex"; + public enum CoreAdminAction { STATUS, LOAD, diff --git a/solr/src/java/org/apache/solr/core/CloseHook.java b/solr/src/java/org/apache/solr/core/CloseHook.java index 46939cdc87b..18850142de5 100644 --- a/solr/src/java/org/apache/solr/core/CloseHook.java +++ b/solr/src/java/org/apache/solr/core/CloseHook.java @@ -18,27 +18,40 @@ package org.apache.solr.core; /** - * Interface to request notification when the core is closed. - *

+ * Used to request notification when the core is closed. + *

* Call {@link org.apache.solr.core.SolrCore#addCloseHook(org.apache.solr.core.CloseHook)} during the {@link org.apache.solr.util.plugin.SolrCoreAware#inform(SolrCore)} method to * add a close hook to your object. *

- * The close hook can be useful for releasing objects related to the request handler (for instance, if you have a JDBC DataSource or something like that) - * - * - */ + * The close hook can be useful for releasing objects related to the request handler (for instance, if you have a JDBC DataSource or something like that) + */ - public interface CloseHook { - - /** - * Method called when the given SolrCore object is closing / shutting down. - *
- * Important: Keep the method implementation as short as possible. If it were to use any heavy i/o , network connections - - * it might be a better idea to launch in a separate Thread so as to not to block the process of - * shutting down a given SolrCore instance. - * - * - * @param core SolrCore object that is shutting down / closing - */ - void close( SolrCore core ); - } +public abstract class CloseHook { + + /** + * Method called when the given SolrCore object is closing / shutting down but before the update handler and + * searcher(s) are actually closed + *
+ * Important: Keep the method implementation as short as possible. If it were to use any heavy i/o , network connections - + * it might be a better idea to launch in a separate Thread so as to not to block the process of + * shutting down a given SolrCore instance. + * + * @param core SolrCore object that is shutting down / closing + */ + public abstract void preClose(SolrCore core); + + /** + * Method called when the given SolrCore object has been shut down and update handlers and searchers are closed + *
+ * Use this method for post-close clean up operations e.g. deleting the index from disk. + *
+ * The core's passed to the method is already closed and therefore, it's update handler or searcher should *NOT* be used + * + * Important: Keep the method implementation as short as possible. If it were to use any heavy i/o , network connections - + * it might be a better idea to launch in a separate Thread so as to not to block the process of + * shutting down a given SolrCore instance. + * + * @param core + */ + public abstract void postClose(SolrCore core); +} diff --git a/solr/src/java/org/apache/solr/core/SolrCore.java b/solr/src/java/org/apache/solr/core/SolrCore.java index 1afc3be2269..23f66ed8fb3 100644 --- a/solr/src/java/org/apache/solr/core/SolrCore.java +++ b/solr/src/java/org/apache/solr/core/SolrCore.java @@ -654,7 +654,7 @@ public final class SolrCore implements SolrInfoMBean { if( closeHooks != null ) { for( CloseHook hook : closeHooks ) { try { - hook.close( this ); + hook.preClose( this ); } catch (Throwable e) { SolrException.log(log, e); } @@ -693,7 +693,15 @@ public final class SolrCore implements SolrInfoMBean { SolrException.log(log,e); } - + if( closeHooks != null ) { + for( CloseHook hook : closeHooks ) { + try { + hook.postClose( this ); + } catch (Throwable e) { + SolrException.log(log, e); + } + } + } } /** Current core usage count. */ diff --git a/solr/src/java/org/apache/solr/handler/ReplicationHandler.java b/solr/src/java/org/apache/solr/handler/ReplicationHandler.java index 8fcc7e54fe4..0f593bbc9d8 100644 --- a/solr/src/java/org/apache/solr/handler/ReplicationHandler.java +++ b/solr/src/java/org/apache/solr/handler/ReplicationHandler.java @@ -889,11 +889,15 @@ public class ReplicationHandler extends RequestHandlerBase implements SolrCoreAw */ private void registerCloseHook() { core.addCloseHook(new CloseHook() { - public void close(SolrCore core) { + @Override + public void preClose(SolrCore core) { if (snapPuller != null) { snapPuller.destroy(); } } + + @Override + public void postClose(SolrCore core) {} }); } diff --git a/solr/src/java/org/apache/solr/handler/admin/CoreAdminHandler.java b/solr/src/java/org/apache/solr/handler/admin/CoreAdminHandler.java index f004c0ce888..be9e46ccd8d 100644 --- a/solr/src/java/org/apache/solr/handler/admin/CoreAdminHandler.java +++ b/solr/src/java/org/apache/solr/handler/admin/CoreAdminHandler.java @@ -18,7 +18,6 @@ package org.apache.solr.handler.admin; import org.apache.lucene.index.IndexReader; -import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.util.IOUtils; import org.apache.solr.cloud.CloudDescriptor; import org.apache.solr.common.SolrException; @@ -28,10 +27,7 @@ import org.apache.solr.common.params.SolrParams; import org.apache.solr.common.params.UpdateParams; import org.apache.solr.common.util.NamedList; import org.apache.solr.common.util.SimpleOrderedMap; -import org.apache.solr.core.CoreContainer; -import org.apache.solr.core.CoreDescriptor; -import org.apache.solr.core.SolrCore; -import org.apache.solr.core.DirectoryFactory; +import org.apache.solr.core.*; import org.apache.solr.handler.RequestHandlerBase; import org.apache.solr.request.SolrQueryRequest; import org.apache.solr.request.LocalSolrQueryRequest; @@ -41,19 +37,19 @@ import org.apache.solr.util.RefCounted; import org.apache.solr.update.MergeIndexesCommand; import org.apache.solr.update.processor.UpdateRequestProcessor; import org.apache.solr.update.processor.UpdateRequestProcessorChain; -import org.apache.lucene.store.Directory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.File; import java.io.IOException; -import java.util.ArrayList; import java.util.Date; -import java.util.List; /** * * @since solr 1.3 */ public class CoreAdminHandler extends RequestHandlerBase { + protected static Logger log = LoggerFactory.getLogger(CoreAdminHandler.class); protected final CoreContainer coreContainer; public CoreAdminHandler() { @@ -397,6 +393,23 @@ public class CoreAdminHandler extends RequestHandlerBase { 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(); diff --git a/solr/src/solrj/org/apache/solr/client/solrj/request/CoreAdminRequest.java b/solr/src/solrj/org/apache/solr/client/solrj/request/CoreAdminRequest.java index 05b4e37f0f1..e3ddd42736a 100644 --- a/solr/src/solrj/org/apache/solr/client/solrj/request/CoreAdminRequest.java +++ b/solr/src/solrj/org/apache/solr/client/solrj/request/CoreAdminRequest.java @@ -163,6 +163,30 @@ public class CoreAdminRequest extends SolrRequest } } + public static class Unload extends CoreAdminRequest { + protected boolean deleteIndex; + + public Unload(boolean deleteIndex) { + action = CoreAdminAction.UNLOAD; + this.deleteIndex = deleteIndex; + } + + public boolean isDeleteIndex() { + return deleteIndex; + } + + public void setDeleteIndex(boolean deleteIndex) { + this.deleteIndex = deleteIndex; + } + + @Override + public SolrParams getParams() { + ModifiableSolrParams params = (ModifiableSolrParams) super.getParams(); + params.set(CoreAdminParams.DELETE_INDEX, deleteIndex); + return params; + } + } + public CoreAdminRequest() { super( METHOD.GET, "/admin/cores" ); @@ -244,11 +268,15 @@ public class CoreAdminRequest extends SolrRequest public static CoreAdminResponse unloadCore( String name, SolrServer server ) throws SolrServerException, IOException { - CoreAdminRequest req = new CoreAdminRequest(); + return unloadCore(name, false, server); + } + + public static CoreAdminResponse unloadCore( String name, boolean deleteIndex, SolrServer server ) throws SolrServerException, IOException + { + Unload req = new Unload(deleteIndex); req.setCoreName( name ); - req.setAction( CoreAdminAction.UNLOAD ); return req.process( server ); - } + } public static CoreAdminResponse renameCore(String coreName, String newName, SolrServer server ) throws SolrServerException, IOException { diff --git a/solr/src/test/org/apache/solr/client/solrj/MultiCoreExampleTestBase.java b/solr/src/test/org/apache/solr/client/solrj/MultiCoreExampleTestBase.java index a25676a6d47..c74ffd4c20b 100644 --- a/solr/src/test/org/apache/solr/client/solrj/MultiCoreExampleTestBase.java +++ b/solr/src/test/org/apache/solr/client/solrj/MultiCoreExampleTestBase.java @@ -23,11 +23,15 @@ import org.apache.solr.client.solrj.request.UpdateRequest; import org.apache.solr.client.solrj.request.UpdateRequest.ACTION; import org.apache.solr.client.solrj.response.CoreAdminResponse; import org.apache.solr.common.SolrInputDocument; +import org.apache.solr.common.util.NamedList; import org.apache.solr.core.CoreContainer; import org.apache.solr.core.SolrCore; +import org.apache.solr.request.SolrRequestInfo; import org.apache.solr.util.ExternalPaths; import org.junit.Test; +import java.io.File; + /** * @@ -161,5 +165,13 @@ public abstract class MultiCoreExampleTestBase extends SolrExampleTestBase } catch( Exception ex ) {} assertEquals( 1, getSolrCore("corefoo").query( new SolrQuery( "id:BBB" ) ).getResults().size() ); + + NamedList response = getSolrCore("corefoo").query(new SolrQuery().setQueryType("/admin/system")).getResponse(); + NamedList coreInfo = (NamedList) response.get("core"); + String indexDir = (String) ((NamedList) coreInfo.get("directory")).get("index"); + // test delete index on core + CoreAdminRequest.unloadCore("corefoo", true, coreadmin); + File dir = new File(indexDir); + assertFalse("Index directory exists after core unload with deleteIndex=true", dir.exists()); } } diff --git a/solr/src/test/org/apache/solr/core/SolrCoreTest.java b/solr/src/test/org/apache/solr/core/SolrCoreTest.java index b979ede29f1..3731dc65b02 100755 --- a/solr/src/test/org/apache/solr/core/SolrCoreTest.java +++ b/solr/src/test/org/apache/solr/core/SolrCoreTest.java @@ -207,9 +207,13 @@ class ClosingRequestHandler extends EmptyRequestHandler implements SolrCoreAware public void inform(SolrCore core) { core.addCloseHook( new CloseHook() { - public void close(SolrCore core) { + @Override + public void preClose(SolrCore core) { closed = true; } + + @Override + public void postClose(SolrCore core) {} }); } }