Author: epbernard
Date: 2008-05-22 14:21:01 -0400 (Thu, 22 May 2008)
New Revision: 14687
Modified:
search/trunk/src/java/org/hibernate/search/backend/QueueingProcessor.java
search/trunk/src/java/org/hibernate/search/backend/Worker.java
search/trunk/src/java/org/hibernate/search/backend/impl/BatchedQueueingProcessor.java
search/trunk/src/java/org/hibernate/search/backend/impl/TransactionalWorker.java
search/trunk/src/java/org/hibernate/search/engine/SearchFactoryImplementor.java
search/trunk/src/java/org/hibernate/search/event/FullTextIndexEventListener.java
search/trunk/src/java/org/hibernate/search/impl/SearchFactoryImpl.java
search/trunk/src/java/org/hibernate/search/store/DirectoryProvider.java
search/trunk/src/java/org/hibernate/search/store/FSDirectoryProvider.java
search/trunk/src/java/org/hibernate/search/store/FSMasterDirectoryProvider.java
search/trunk/src/java/org/hibernate/search/store/FSSlaveDirectoryProvider.java
search/trunk/src/java/org/hibernate/search/store/RAMDirectoryProvider.java
search/trunk/src/test/org/hibernate/search/test/FSDirectoryTest.java
search/trunk/src/test/org/hibernate/search/test/HANTestCase.java
search/trunk/src/test/org/hibernate/search/test/directoryProvider/FSSlaveAndMasterDPTest.java
search/trunk/src/test/org/hibernate/search/test/worker/WorkerTestCase.java
Log:
HSEARCH-199 close resources on SF.close() had to change the DirectoryProvider API and the
worker / QueueingProcess APIs
Modified: search/trunk/src/java/org/hibernate/search/backend/QueueingProcessor.java
===================================================================
--- search/trunk/src/java/org/hibernate/search/backend/QueueingProcessor.java 2008-05-22
15:43:24 UTC (rev 14686)
+++ search/trunk/src/java/org/hibernate/search/backend/QueueingProcessor.java 2008-05-22
18:21:01 UTC (rev 14687)
@@ -36,4 +36,10 @@
* Rollback works
*/
void cancelWorks(WorkQueue workQueue);
+
+ /**
+ * clean resources
+ * This method should log errors rather than raise an exception
+ */
+ void close();
}
Modified: search/trunk/src/java/org/hibernate/search/backend/Worker.java
===================================================================
--- search/trunk/src/java/org/hibernate/search/backend/Worker.java 2008-05-22 15:43:24 UTC
(rev 14686)
+++ search/trunk/src/java/org/hibernate/search/backend/Worker.java 2008-05-22 18:21:01 UTC
(rev 14687)
@@ -16,4 +16,10 @@
void performWork(Work work, EventSource session);
void initialize(Properties props, SearchFactoryImplementor searchFactoryImplementor);
+
+ /**
+ * clean resources
+ * This method can return exceptions
+ */
+ void close();
}
Modified:
search/trunk/src/java/org/hibernate/search/backend/impl/BatchedQueueingProcessor.java
===================================================================
---
search/trunk/src/java/org/hibernate/search/backend/impl/BatchedQueueingProcessor.java 2008-05-22
15:43:24 UTC (rev 14686)
+++
search/trunk/src/java/org/hibernate/search/backend/impl/BatchedQueueingProcessor.java 2008-05-22
18:21:01 UTC (rev 14687)
@@ -25,6 +25,8 @@
import org.hibernate.search.backend.impl.lucene.LuceneBackendQueueProcessorFactory;
import org.hibernate.search.engine.DocumentBuilder;
import org.hibernate.search.engine.SearchFactoryImplementor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Batch work until #performWorks is called.
@@ -33,6 +35,9 @@
* @author Emmanuel Bernard
*/
public class BatchedQueueingProcessor implements QueueingProcessor {
+
+ private static final Logger log = LoggerFactory.getLogger(
BatchedQueueingProcessor.class );
+
private boolean sync;
private int batchSize;
private ExecutorService executorService;
@@ -157,14 +162,16 @@
workQueue.clear();
}
- @Override
- public void finalize() throws Throwable {
- super.finalize();
+ public void close() {
//gracefully stop
- //TODO move to the SF close lifecycle
if ( executorService != null && !executorService.isShutdown() ) {
executorService.shutdown();
- executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS );
+ try {
+ executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS );
+ }
+ catch (InterruptedException e) {
+ log.error("Unable to property shut down asynchronous indexing work", e);
+ }
}
}
Modified:
search/trunk/src/java/org/hibernate/search/backend/impl/TransactionalWorker.java
===================================================================
---
search/trunk/src/java/org/hibernate/search/backend/impl/TransactionalWorker.java 2008-05-22
15:43:24 UTC (rev 14686)
+++
search/trunk/src/java/org/hibernate/search/backend/impl/TransactionalWorker.java 2008-05-22
18:21:01 UTC (rev 14687)
@@ -49,4 +49,9 @@
public void initialize(Properties props, SearchFactoryImplementor searchFactory) {
this.queueingProcessor = new BatchedQueueingProcessor( searchFactory, props );
}
+
+ public void close() {
+ queueingProcessor.close();
+ }
+
}
Modified: search/trunk/src/java/org/hibernate/search/engine/SearchFactoryImplementor.java
===================================================================
---
search/trunk/src/java/org/hibernate/search/engine/SearchFactoryImplementor.java 2008-05-22
15:43:24 UTC (rev 14686)
+++
search/trunk/src/java/org/hibernate/search/engine/SearchFactoryImplementor.java 2008-05-22
18:21:01 UTC (rev 14687)
@@ -42,4 +42,6 @@
void addIndexingParmeters(DirectoryProvider<?> provider, LuceneIndexingParameters
indexingParams);
public String getIndexingStrategy();
+
+ public void close();
}
Modified:
search/trunk/src/java/org/hibernate/search/event/FullTextIndexEventListener.java
===================================================================
---
search/trunk/src/java/org/hibernate/search/event/FullTextIndexEventListener.java 2008-05-22
15:43:24 UTC (rev 14686)
+++
search/trunk/src/java/org/hibernate/search/event/FullTextIndexEventListener.java 2008-05-22
18:21:01 UTC (rev 14687)
@@ -12,6 +12,7 @@
import org.hibernate.event.PostInsertEventListener;
import org.hibernate.event.PostUpdateEvent;
import org.hibernate.event.PostUpdateEventListener;
+import org.hibernate.event.Destructible;
import org.hibernate.search.backend.WorkType;
import org.hibernate.search.backend.Work;
import org.hibernate.search.engine.DocumentBuilder;
@@ -31,7 +32,7 @@
//TODO work on sharing the same indexWriters and readers across a single post
operation...
//TODO implement and use a LockableDirectoryProvider that wraps a DP to handle the lock
inside the LDP
public class FullTextIndexEventListener implements PostDeleteEventListener,
PostInsertEventListener,
- PostUpdateEventListener, Initializable {
+ PostUpdateEventListener, Initializable, Destructible {
@SuppressWarnings( { "WeakerAccess" } )
protected boolean used;
@@ -87,4 +88,8 @@
Work work = new Work(entity, id, workType);
searchFactoryImplementor.getWorker().performWork( work, event.getSession() );
}
+
+ public void cleanup() {
+ searchFactoryImplementor.close();
+ }
}
Modified: search/trunk/src/java/org/hibernate/search/impl/SearchFactoryImpl.java
===================================================================
--- search/trunk/src/java/org/hibernate/search/impl/SearchFactoryImpl.java 2008-05-22
15:43:24 UTC (rev 14686)
+++ search/trunk/src/java/org/hibernate/search/impl/SearchFactoryImpl.java 2008-05-22
18:21:01 UTC (rev 14687)
@@ -44,6 +44,8 @@
import org.hibernate.search.store.DirectoryProviderFactory;
import org.hibernate.search.store.optimization.OptimizerStrategy;
import org.apache.lucene.analysis.Analyzer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* @author Emmanuel Bernard
@@ -56,6 +58,8 @@
Version.touch();
}
+ private final Logger log = LoggerFactory.getLogger( SearchFactoryImpl.class );
+
private Map<Class, DocumentBuilder<Object>> documentBuilders = new
HashMap<Class, DocumentBuilder<Object>>();
//keep track of the index modifiers per DirectoryProvider since multiple entity can use
the same directory provider
private Map<DirectoryProvider, ReentrantLock> lockableDirectoryProviders =
@@ -68,6 +72,7 @@
private Map<String, FilterDef> filterDefinitions = new HashMap<String,
FilterDef>();
private FilterCachingStrategy filterCachingStrategy;
private Map<String, Analyzer> analyzers;
+ private boolean stopped = false;
/**
* Each directory provider (index) can have its own performance settings.
@@ -113,6 +118,27 @@
return indexingStrategy;
}
+ public void close() {
+ if (!stopped) {
+ stopped = true;
+ try {
+ worker.close();
+ }
+ catch (Exception e) {
+ log.error( "Worker raises an exception on close()", e );
+ }
+ //TODO move to DirectoryProviderFactory for cleaner
+ for (DirectoryProvider dp : lockableDirectoryProviders.keySet() ) {
+ try {
+ dp.stop();
+ }
+ catch (Exception e) {
+ log.error( "DirectoryProvider raises an exception on stop() ", e );
+ }
+ }
+ }
+ }
+
private void bindFilterDefs(XClass mappedXClass) {
FullTextFilterDef defAnn = mappedXClass.getAnnotation( FullTextFilterDef.class );
if ( defAnn != null ) {
Modified: search/trunk/src/java/org/hibernate/search/store/DirectoryProvider.java
===================================================================
--- search/trunk/src/java/org/hibernate/search/store/DirectoryProvider.java 2008-05-22
15:43:24 UTC (rev 14686)
+++ search/trunk/src/java/org/hibernate/search/store/DirectoryProvider.java 2008-05-22
18:21:01 UTC (rev 14687)
@@ -30,11 +30,17 @@
* Executed after initialize, this method set up the heavy process of starting up the
DirectoryProvider
* IO processing as well as backgroup processing are expected to be set up here
*
- * TODO stop() method, for now use finalize()
*/
void start();
/**
+ * Executed when the search factory is closed. This method should stop any background
process as well as
+ * releasing any resource.
+ * This method should avoid raising exceptions and log potential errors instead
+ */
+ void stop();
+
+ /**
* Returns an initialized Lucene Directory. This method call <b>must</b> be
threadsafe
*/
TDirectory getDirectory();
Modified: search/trunk/src/java/org/hibernate/search/store/FSDirectoryProvider.java
===================================================================
--- search/trunk/src/java/org/hibernate/search/store/FSDirectoryProvider.java 2008-05-22
15:43:24 UTC (rev 14686)
+++ search/trunk/src/java/org/hibernate/search/store/FSDirectoryProvider.java 2008-05-22
18:21:01 UTC (rev 14687)
@@ -9,6 +9,8 @@
import org.hibernate.search.Environment;
import org.hibernate.search.SearchException;
import org.hibernate.search.engine.SearchFactoryImplementor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Use a Lucene FSDirectory
@@ -20,6 +22,8 @@
* @author Sanne Grinovero
*/
public class FSDirectoryProvider implements DirectoryProvider<FSDirectory> {
+
+ private final Logger log = LoggerFactory.getLogger( FSDirectoryProvider.class );
private FSDirectory directory;
private String indexName;
@@ -42,6 +46,15 @@
//all the process is done in initialize
}
+ public void stop() {
+ try {
+ directory.close();
+ }
+ catch (Exception e) {
+ log.error( "Unable to property close Lucene directory {}" +
directory.getFile(), e );
+ }
+ }
+
public FSDirectory getDirectory() {
return directory;
}
Modified: search/trunk/src/java/org/hibernate/search/store/FSMasterDirectoryProvider.java
===================================================================
---
search/trunk/src/java/org/hibernate/search/store/FSMasterDirectoryProvider.java 2008-05-22
15:43:24 UTC (rev 14686)
+++
search/trunk/src/java/org/hibernate/search/store/FSMasterDirectoryProvider.java 2008-05-22
18:21:01 UTC (rev 14687)
@@ -117,6 +117,18 @@
return 37 * hash + indexName.hashCode();
}
+
+
+ public void stop() {
+ timer.cancel();
+ try {
+ directory.close();
+ }
+ catch (Exception e) {
+ log.error( "Unable to property close Lucene directory {}" +
directory.getFile(), e );
+ }
+ }
+
class TriggerTask extends TimerTask {
private final ExecutorService executor;
@@ -194,10 +206,4 @@
log.trace( "Copy for {} took {} ms", indexName, (System.currentTimeMillis()
- start) );
}
}
-
- public void finalize() throws Throwable {
- super.finalize();
- timer.cancel();
- //TODO find a better cycle from Hibernate core
- }
}
Modified: search/trunk/src/java/org/hibernate/search/store/FSSlaveDirectoryProvider.java
===================================================================
---
search/trunk/src/java/org/hibernate/search/store/FSSlaveDirectoryProvider.java 2008-05-22
15:43:24 UTC (rev 14686)
+++
search/trunk/src/java/org/hibernate/search/store/FSSlaveDirectoryProvider.java 2008-05-22
18:21:01 UTC (rev 14687)
@@ -226,9 +226,19 @@
}
}
- public void finalize() throws Throwable {
- super.finalize();
+ public void stop() {
timer.cancel();
- //TODO find a better cycle from Hibernate core
+ try {
+ directory1.close();
+ }
+ catch (Exception e) {
+ log.error( "Unable to property close Lucene directory {}" +
directory1.getFile(), e );
+ }
+ try {
+ directory2.close();
+ }
+ catch (Exception e) {
+ log.error( "Unable to property close Lucene directory {}" +
directory2.getFile(), e );
+ }
}
}
Modified: search/trunk/src/java/org/hibernate/search/store/RAMDirectoryProvider.java
===================================================================
--- search/trunk/src/java/org/hibernate/search/store/RAMDirectoryProvider.java 2008-05-22
15:43:24 UTC (rev 14686)
+++ search/trunk/src/java/org/hibernate/search/store/RAMDirectoryProvider.java 2008-05-22
18:21:01 UTC (rev 14687)
@@ -41,6 +41,8 @@
return directory;
}
+ public void stop() {}
+
@Override
public boolean equals(Object obj) {
// this code is actually broken since the value change after initialize call
Modified: search/trunk/src/test/org/hibernate/search/test/FSDirectoryTest.java
===================================================================
--- search/trunk/src/test/org/hibernate/search/test/FSDirectoryTest.java 2008-05-22
15:43:24 UTC (rev 14686)
+++ search/trunk/src/test/org/hibernate/search/test/FSDirectoryTest.java 2008-05-22
18:21:01 UTC (rev 14687)
@@ -190,6 +190,7 @@
}
s.getTransaction().commit();
s.close();
+ getSessions().close(); //run the searchfactory.close() operations
}
public void testSearchOnDeletedIndex() throws Exception {
Modified: search/trunk/src/test/org/hibernate/search/test/HANTestCase.java
===================================================================
--- search/trunk/src/test/org/hibernate/search/test/HANTestCase.java 2008-05-22 15:43:24
UTC (rev 14686)
+++ search/trunk/src/test/org/hibernate/search/test/HANTestCase.java 2008-05-22 18:21:01
UTC (rev 14687)
@@ -61,7 +61,7 @@
}
protected void setUp() throws Exception {
- if ( getSessions() == null || lastTestClass != getClass() ) {
+ if ( getSessions() == null || getSessions().isClosed() || lastTestClass != getClass() )
{
buildSessionFactory( getMappings(), getAnnotatedPackages(), getXmlFiles() );
lastTestClass = getClass();
}
Modified:
search/trunk/src/test/org/hibernate/search/test/directoryProvider/FSSlaveAndMasterDPTest.java
===================================================================
---
search/trunk/src/test/org/hibernate/search/test/directoryProvider/FSSlaveAndMasterDPTest.java 2008-05-22
15:43:24 UTC (rev 14686)
+++
search/trunk/src/test/org/hibernate/search/test/directoryProvider/FSSlaveAndMasterDPTest.java 2008-05-22
18:21:01 UTC (rev 14687)
@@ -8,6 +8,7 @@
import org.apache.lucene.analysis.StopAnalyzer;
import org.apache.lucene.queryParser.QueryParser;
import org.hibernate.Session;
+import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.event.PostDeleteEventListener;
import org.hibernate.event.PostInsertEventListener;
@@ -87,6 +88,10 @@
assertEquals("Third copy did not work out", 1, result.size() );
fts2.close();
+ //run the searchfactory.close() operations
+ for ( SessionFactory sf : getSessionFactories() ) {
+ sf.close();
+ }
}
@@ -102,7 +107,7 @@
File slave = new File(root, "slave");
slave.mkdir();
-
+
super.setUp();
}
Modified: search/trunk/src/test/org/hibernate/search/test/worker/WorkerTestCase.java
===================================================================
--- search/trunk/src/test/org/hibernate/search/test/worker/WorkerTestCase.java 2008-05-22
15:43:24 UTC (rev 14686)
+++ search/trunk/src/test/org/hibernate/search/test/worker/WorkerTestCase.java 2008-05-22
18:21:01 UTC (rev 14687)
@@ -77,6 +77,7 @@
while ( work.count < iteration - 1 ) {
Thread.sleep( 20 );
}
+ getSessions().close();
System.out.println( iteration + " iterations (8 tx per iteration) in " +
nThreads + " threads: " + ( System
.currentTimeMillis() - start ) );
}