[hibernate-commits] Hibernate SVN: r14300 - in search/trunk/src: java/org/hibernate/search/backend and 4 other directories.
hibernate-commits at lists.jboss.org
hibernate-commits at lists.jboss.org
Wed Jan 30 17:47:58 EST 2008
Author: epbernard
Date: 2008-01-30 17:47:58 -0500 (Wed, 30 Jan 2008)
New Revision: 14300
Added:
search/trunk/src/java/org/hibernate/search/event/FullTextIndexCollectionEventListener.java
search/trunk/src/java/org/hibernate/search/lucene/
Modified:
search/trunk/src/java/org/hibernate/search/backend/WorkType.java
search/trunk/src/java/org/hibernate/search/backend/impl/BatchedQueueingProcessor.java
search/trunk/src/java/org/hibernate/search/engine/DocumentBuilder.java
search/trunk/src/java/org/hibernate/search/event/FullTextIndexEventListener.java
search/trunk/src/test/org/hibernate/search/test/embedded/EmbeddedTest.java
Log:
HSEARCH-56 use Hibernate collection events to index on collection change
Modified: search/trunk/src/java/org/hibernate/search/backend/WorkType.java
===================================================================
--- search/trunk/src/java/org/hibernate/search/backend/WorkType.java 2008-01-30 17:54:10 UTC (rev 14299)
+++ search/trunk/src/java/org/hibernate/search/backend/WorkType.java 2008-01-30 22:47:58 UTC (rev 14300)
@@ -13,6 +13,7 @@
ADD,
UPDATE,
DELETE,
+ COLLECTION,
/**
* Used to remove a specific instance
* of a class from an index.
Modified: search/trunk/src/java/org/hibernate/search/backend/impl/BatchedQueueingProcessor.java
===================================================================
--- search/trunk/src/java/org/hibernate/search/backend/impl/BatchedQueueingProcessor.java 2008-01-30 17:54:10 UTC (rev 14299)
+++ search/trunk/src/java/org/hibernate/search/backend/impl/BatchedQueueingProcessor.java 2008-01-30 22:47:58 UTC (rev 14300)
@@ -98,6 +98,7 @@
public void add(Work work, WorkQueue workQueue) {
//don't check for builder it's done in prepareWork
+ //FIXME WorkType.COLLECTION does not play well with batchSize
workQueue.add( work );
if ( batchSize > 0 && workQueue.size() >= batchSize ) {
WorkQueue subQueue = workQueue.splitQueue();
@@ -111,17 +112,33 @@
List<Work> queue = workQueue.getQueue();
int initialSize = queue.size();
List<LuceneWork> luceneQueue = new ArrayList<LuceneWork>( initialSize ); //TODO load factor for containedIn
+ /**
+ * Collection work type are process second, so if the owner entity has already been processed for whatever reason
+ * the work will be ignored.
+ * However if the owner entity has not been processed, an "UPDATE" work is executed
+ *
+ * Processing collection works last is mandatory to avoid reindexing a object to be deleted
+ */
+ processWorkByLayer( queue, initialSize, luceneQueue, Layer.FIRST );
+ processWorkByLayer( queue, initialSize, luceneQueue, Layer.SECOND );
+ workQueue.setSealedQueue( luceneQueue );
+ }
+
+ private void processWorkByLayer(List<Work> queue, int initialSize, List<LuceneWork> luceneQueue, Layer layer) {
for ( int i = 0 ; i < initialSize ; i++ ) {
Work work = queue.get( i );
- queue.set( i, null ); // help GC and avoid 2 loaded queues in memory
- Class entityClass = work.getEntityClass() != null ?
- work.getEntityClass() :
- Hibernate.getClass( work.getEntity() );
- DocumentBuilder<Object> builder = searchFactoryImplementor.getDocumentBuilders().get( entityClass );
- if ( builder == null ) return; //or exception?
- builder.addWorkToQueue(entityClass, work.getEntity(), work.getId(), work.getType(), luceneQueue, searchFactoryImplementor );
+ if ( work != null) {
+ if ( layer.isRightLayer( work.getType() ) ) {
+ queue.set( i, null ); // help GC and avoid 2 loaded queues in memory
+ Class entityClass = work.getEntityClass() != null ?
+ work.getEntityClass() :
+ Hibernate.getClass( work.getEntity() );
+ DocumentBuilder<Object> builder = searchFactoryImplementor.getDocumentBuilders().get( entityClass );
+ if ( builder == null ) continue; //or exception?
+ builder.addWorkToQueue(entityClass, work.getEntity(), work.getId(), work.getType(), luceneQueue, searchFactoryImplementor );
+ }
+ }
}
- workQueue.setSealedQueue( luceneQueue );
}
//TODO implements parallel batchWorkers (one per Directory)
@@ -151,4 +168,15 @@
}
}
+ private static enum Layer {
+ FIRST,
+ SECOND;
+
+ public boolean isRightLayer(WorkType type) {
+ if (this == FIRST && type != WorkType.COLLECTION) return true;
+ if (this == SECOND && type == WorkType.COLLECTION) return true;
+ return false;
+ }
+ }
+
}
Modified: search/trunk/src/java/org/hibernate/search/engine/DocumentBuilder.java
===================================================================
--- search/trunk/src/java/org/hibernate/search/engine/DocumentBuilder.java 2008-01-30 17:54:10 UTC (rev 14299)
+++ search/trunk/src/java/org/hibernate/search/engine/DocumentBuilder.java 2008-01-30 22:47:58 UTC (rev 14300)
@@ -392,7 +392,7 @@
//TODO could we use T instead of EntityClass?
public void addWorkToQueue(Class entityClass, T entity, Serializable id, WorkType workType, List<LuceneWork> queue, SearchFactoryImplementor searchFactoryImplementor) {
- //TODO with the caller loop we are in a n^2: optimize it using a HashMap for work recognition
+ //TODO with the caller loop we are in a n^2: optimize it using a HashMap for work recognition
for (LuceneWork luceneWork : queue) {
//any work on the same entity should be ignored
if ( luceneWork.getEntityClass() == entityClass
@@ -418,7 +418,7 @@
else if ( workType == WorkType.PURGE_ALL ) {
queue.add( new PurgeAllLuceneWork( entityClass ) );
}
- else if ( workType == WorkType.UPDATE ) {
+ else if ( workType == WorkType.UPDATE || workType == WorkType.COLLECTION ) {
Document doc = getDocument( entity, id );
/**
* even with Lucene 2.1, use of indexWriter to update is not an option
Added: search/trunk/src/java/org/hibernate/search/event/FullTextIndexCollectionEventListener.java
===================================================================
--- search/trunk/src/java/org/hibernate/search/event/FullTextIndexCollectionEventListener.java (rev 0)
+++ search/trunk/src/java/org/hibernate/search/event/FullTextIndexCollectionEventListener.java 2008-01-30 22:47:58 UTC (rev 14300)
@@ -0,0 +1,49 @@
+//$
+package org.hibernate.search.event;
+
+import java.io.Serializable;
+
+import org.hibernate.event.PostCollectionRecreateEventListener;
+import org.hibernate.event.PostCollectionRemoveEventListener;
+import org.hibernate.event.PostCollectionUpdateEventListener;
+import org.hibernate.event.PostCollectionRecreateEvent;
+import org.hibernate.event.PostCollectionRemoveEvent;
+import org.hibernate.event.PostCollectionUpdateEvent;
+import org.hibernate.event.AbstractEvent;
+import org.hibernate.search.backend.WorkType;
+
+/**
+ * Support collection event listening (starts from hibernate core 3.2.6)
+ * FIXME deprecate as soon as we target Core 3.3 and merge back into the superclass
+ *
+ * @author Emmanuel Bernard
+ */
+public class FullTextIndexCollectionEventListener extends FullTextIndexEventListener
+ implements PostCollectionRecreateEventListener,
+ PostCollectionRemoveEventListener,
+ PostCollectionUpdateEventListener {
+ public void onPostRecreateCollection(PostCollectionRecreateEvent event) {
+ Object entity = event.getAffectedOwner();
+ if ( used && searchFactoryImplementor.getDocumentBuilders().containsKey( entity.getClass() ) ) {
+ processWork( entity, getId( entity, event ), WorkType.COLLECTION, event );
+ }
+ }
+
+ private Serializable getId(Object entity, AbstractEvent event) {
+ return event.getSession().getPersistenceContext().getEntry( entity ).getId();
+ }
+
+ public void onPostRemoveCollection(PostCollectionRemoveEvent event) {
+ Object entity = event.getAffectedOwner();
+ if ( used && searchFactoryImplementor.getDocumentBuilders().containsKey( entity.getClass() ) ) {
+ processWork( entity, getId( entity, event ), WorkType.COLLECTION, event );
+ }
+ }
+
+ public void onPostUpdateCollection(PostCollectionUpdateEvent event) {
+ Object entity = event.getAffectedOwner();
+ if ( used && searchFactoryImplementor.getDocumentBuilders().containsKey( entity.getClass() ) ) {
+ processWork( entity, getId( entity, event ), WorkType.COLLECTION, event );
+ }
+ }
+}
Modified: search/trunk/src/java/org/hibernate/search/event/FullTextIndexEventListener.java
===================================================================
--- search/trunk/src/java/org/hibernate/search/event/FullTextIndexEventListener.java 2008-01-30 17:54:10 UTC (rev 14299)
+++ search/trunk/src/java/org/hibernate/search/event/FullTextIndexEventListener.java 2008-01-30 22:47:58 UTC (rev 14300)
@@ -35,11 +35,9 @@
public class FullTextIndexEventListener implements PostDeleteEventListener, PostInsertEventListener,
PostUpdateEventListener, Initializable {
- private static final Log log = LogFactory.getLog( FullTextIndexEventListener.class );
- private boolean used;
+ protected boolean used;
+ protected SearchFactoryImplementor searchFactoryImplementor;
- private SearchFactoryImplementor searchFactoryImplementor;
-
public void initialize(Configuration cfg) {
searchFactoryImplementor = SearchFactoryImpl.getSearchFactory( cfg );
String indexingStrategy = cfg.getProperties().getProperty( Environment.INDEXING_STRATEGY, "event" );
@@ -88,7 +86,7 @@
}
}
- private void processWork(Object entity, Serializable id, WorkType workType, AbstractEvent event) {
+ protected void processWork(Object entity, Serializable id, WorkType workType, AbstractEvent event) {
Work work = new Work(entity, id, workType);
searchFactoryImplementor.getWorker().performWork( work, event.getSession() );
}
Modified: search/trunk/src/test/org/hibernate/search/test/embedded/EmbeddedTest.java
===================================================================
--- search/trunk/src/test/org/hibernate/search/test/embedded/EmbeddedTest.java 2008-01-30 17:54:10 UTC (rev 14299)
+++ search/trunk/src/test/org/hibernate/search/test/embedded/EmbeddedTest.java 2008-01-30 22:47:58 UTC (rev 14300)
@@ -11,8 +11,14 @@
import org.apache.lucene.search.TermQuery;
import org.hibernate.Session;
import org.hibernate.Transaction;
+import org.hibernate.event.PostCollectionRecreateEventListener;
+import org.hibernate.event.PostInsertEventListener;
+import org.hibernate.event.PostUpdateEventListener;
+import org.hibernate.event.PostCollectionUpdateEventListener;
+import org.hibernate.event.PostCollectionRemoveEventListener;
import org.hibernate.search.FullTextSession;
import org.hibernate.search.Search;
+import org.hibernate.search.event.FullTextIndexCollectionEventListener;
import org.hibernate.search.test.SearchTestCase;
/**
@@ -231,6 +237,14 @@
}
+ protected void configure(org.hibernate.cfg.Configuration cfg) {
+ super.configure( cfg );
+ FullTextIndexCollectionEventListener del = new FullTextIndexCollectionEventListener();
+ cfg.getEventListeners().setPostCollectionRecreateEventListeners( new PostCollectionRecreateEventListener[]{del} );
+ cfg.getEventListeners().setPostCollectionUpdateEventListeners( new PostCollectionUpdateEventListener[]{del} );
+ cfg.getEventListeners().setPostCollectionRemoveEventListeners( new PostCollectionRemoveEventListener[]{del} );
+ }
+
protected Class[] getMappings() {
return new Class[] {
Tower.class,
More information about the hibernate-commits
mailing list