Changing the models that the SearchReindexingListener listens to. NIHVIVO-2076

This commit is contained in:
bdc34 2011-02-09 16:08:42 +00:00
parent 61812f7a1e
commit 1341d23a25
10 changed files with 327 additions and 323 deletions

View file

@ -5,6 +5,7 @@ package edu.cornell.mannlib.vitro.webapp.dao.jena;
import javax.servlet.ServletContext; import javax.servlet.ServletContext;
import com.hp.hpl.jena.ontology.OntModel; import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.rdf.model.ModelChangedListener;
public class ModelContext { public class ModelContext {
@ -75,4 +76,26 @@ public class ModelContext {
ctx.setAttribute(INFERENCE_ONT_MODEL, ontModel); ctx.setAttribute(INFERENCE_ONT_MODEL, ontModel);
} }
/**
* Register a listener to the models needed to get changes to:
* class membership
* inferred class membership
* class group membership,
* object properties,
* data properties,
* inferred object properties,
* rdfs:label annotations
* This listener does not need:
* other annotations
* change to TBox
*/
public static void registerListenerForChanges(ServletContext ctx, ModelChangedListener ml){
ModelContext.getJenaOntModel(ctx).register(ml);
ModelContext.getBaseOntModel(ctx).register(ml);
ModelContext.getInferenceOntModel(ctx).register(ml);
ModelContext.getUnionOntModelSelector(ctx).getABoxModel().register(ml);
ModelContext.getBaseOntModelSelector(ctx).getABoxModel().register(ml);
ModelContext.getInferenceOntModelSelector(ctx).getABoxModel().register(ml);
}
} }

View file

@ -2,9 +2,7 @@
package edu.cornell.mannlib.vitro.webapp.dao.jena; package edu.cornell.mannlib.vitro.webapp.dao.jena;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
@ -34,16 +32,32 @@ public class SearchReindexingListener implements ModelChangedListener {
private synchronized void addChange(Statement stmt){ private synchronized void addChange(Statement stmt){
if( stmt == null ) return; if( stmt == null ) return;
if( log.isDebugEnabled() ){
String sub="unknown";
String pred = "unknown";
String obj ="unknown";
if( stmt.getSubject().isURIResource() ){
sub = stmt.getSubject().getURI();
}
if( stmt.getPredicate() != null ){
pred = stmt.getPredicate().getURI();
}
if( stmt.getObject().isURIResource() ){
obj = ((Resource) (stmt.getPredicate().as(Resource.class))).getURI();
}else{
obj = stmt.getObject().toString();
}
log.debug("changed statement: sub='" + sub + "' pred='" + pred +"' obj='" + obj + "'");
}
if( stmt.getSubject().isURIResource() ){ if( stmt.getSubject().isURIResource() ){
//changedUris.add( stmt.getSubject().getURI());
indexBuilder.addToChangedUris(stmt.getSubject().getURI()); indexBuilder.addToChangedUris(stmt.getSubject().getURI());
log.debug("subject: " + stmt.getSubject().getURI()); log.debug("subject: " + stmt.getSubject().getURI());
} }
if( stmt.getObject().isURIResource() ){ if( stmt.getObject().isURIResource() ){
//changedUris.add( ((Resource) stmt.getObject().as(Resource.class)).getURI() );
indexBuilder.addToChangedUris(((Resource) stmt.getObject()).getURI()); indexBuilder.addToChangedUris(((Resource) stmt.getObject()).getURI());
log.debug("object: " + ((Resource) stmt.getObject().as(Resource.class)).getURI());
} }
} }

View file

@ -70,12 +70,14 @@ public class VClassGroupCache{
} }
VClassGroupCacheChangeListener bccl = new VClassGroupCacheChangeListener(this); VClassGroupCacheChangeListener bccl = new VClassGroupCacheChangeListener(this);
ModelContext.getJenaOntModel(context).register(bccl); ModelContext.registerListenerForChanges(context, bccl);
ModelContext.getBaseOntModel(context).register(bccl); //
ModelContext.getInferenceOntModel(context).register(bccl); // ModelContext.getJenaOntModel(context).register(bccl);
ModelContext.getUnionOntModelSelector(context).getABoxModel().register(bccl); // ModelContext.getBaseOntModel(context).register(bccl);
ModelContext.getBaseOntModelSelector(context).getABoxModel().register(bccl); // ModelContext.getInferenceOntModel(context).register(bccl);
ModelContext.getInferenceOntModelSelector(context).getABoxModel().register(bccl); // ModelContext.getUnionOntModelSelector(context).getABoxModel().register(bccl);
// ModelContext.getBaseOntModelSelector(context).getABoxModel().register(bccl);
// ModelContext.getInferenceOntModelSelector(context).getABoxModel().register(bccl);
_rebuildQueue.add(REBUILD_EVERY_PORTAL); _rebuildQueue.add(REBUILD_EVERY_PORTAL);
_cacheRebuildThread = new RebuildGroupCacheThread(this); _cacheRebuildThread = new RebuildGroupCacheThread(this);

View file

@ -26,38 +26,31 @@ import edu.cornell.mannlib.vitro.webapp.search.beans.ProhibitedFromSearch;
/** /**
* The IndexBuilder is used to rebuild or update a search index. * The IndexBuilder is used to rebuild or update a search index.
* There should only be one IndexBuilder in a vitro web application.
* It uses an implementation of a back-end through an object that * It uses an implementation of a back-end through an object that
* implements IndexerIface. An example of a back-end is LuceneIndexer. * implements IndexerIface. An example of a back-end is LuceneIndexer.
* *
* See the class SearchReindexingListener for an example of how a model change * See the class SearchReindexingListener for an example of how a model change
* listener can use an IndexBuilder to keep the full text index in sncy with * listener can use an IndexBuilder to keep the full text index in sncy with
* updates to a model. * updates to a model. It calls IndexBuilder.addToChangedUris().
* *
* There should be an IndexBuilder in the servlet context, try:
*
IndexBuilder builder = (IndexBuilder)getServletContext().getAttribute(IndexBuilder.class.getName());
if( request.getParameter("update") != null )
builder.doUpdateIndex();
* @author bdc34 * @author bdc34
* *
*/ */
public class IndexBuilder { public class IndexBuilder extends Thread {
private List<ObjectSourceIface> sourceList = new LinkedList<ObjectSourceIface>(); private List<ObjectSourceIface> sourceList = new LinkedList<ObjectSourceIface>();
private IndexerIface indexer = null; private IndexerIface indexer = null;
private ServletContext context = null; private ServletContext context = null;
private long lastRun = 0; /* changedUris should only be accessed from synchronized blocks */
private HashSet<String> changedUris = null; private HashSet<String> changedUris = null;
private List<Individual> updatedInds = null; private List<Individual> updatedInds = null;
private List<Individual> deletedInds = null; private List<Individual> deletedInds = null;
private IndexBuilderThread indexingThread = null;
//shared with IndexBuilderThread
private boolean reindexRequested = false; private boolean reindexRequested = false;
protected boolean stopRequested = false;
protected long reindexInterval = 1000 * 60 /* msec */ ;
public static final boolean UPDATE_DOCS = false; public static final boolean UPDATE_DOCS = false;
public static final boolean NEW_DOCS = true; public static final boolean NEW_DOCS = true;
@ -67,13 +60,18 @@ public class IndexBuilder {
public IndexBuilder(ServletContext context, public IndexBuilder(ServletContext context,
IndexerIface indexer, IndexerIface indexer,
List /*ObjectSourceIface*/ sources){ List /*ObjectSourceIface*/ sources){
super("IndexBuilder");
this.indexer = indexer; this.indexer = indexer;
this.sourceList = sources; this.sourceList = sources;
this.context = context; this.context = context;
this.changedUris = new HashSet<String>(); this.changedUris = new HashSet<String>();
this.indexingThread = new IndexBuilderThread(this); this.start();
this.indexingThread.start(); }
protected IndexBuilder(){
//for testing only
this( null, null, Collections.emptyList());
} }
public void addObjectSource(ObjectSourceIface osi) { public void addObjectSource(ObjectSourceIface osi) {
@ -89,24 +87,20 @@ public class IndexBuilder {
return sourceList; return sourceList;
} }
public void doIndexRebuild() throws IndexingException { public synchronized void doIndexRebuild() throws IndexingException {
//set up full index rebuild //set flag for full index rebuild
setReindexRequested( true ); this.reindexRequested = true;
//wake up indexing thread //wake up
synchronized (this.indexingThread) { this.notifyAll();
this.indexingThread.notifyAll();
}
} }
/** /**
* This will re-index Individuals that changed because of modtime or because they * This will re-index Individuals that changed because of modtime or because they
* were added with addChangedUris(). * were added with addChangedUris().
*/ */
public void doUpdateIndex() { public synchronized void doUpdateIndex() {
//wake up thread //wake up thread and it will attempt to index anything in changedUris
synchronized (this.indexingThread) { this.notifyAll();
this.indexingThread.notifyAll();
}
} }
public synchronized void addToChangedUris(String uri){ public synchronized void addToChangedUris(String uri){
@ -125,79 +119,47 @@ public class IndexBuilder {
return isReindexRequested() || ! changedUris.isEmpty() ; return isReindexRequested() || ! changedUris.isEmpty() ;
} }
public void killIndexingThread() { public synchronized void stopIndexingThread() {
this.indexingThread.kill(); stopRequested = true;
this.notifyAll();
} }
@Override
public void run() {
while(! stopRequested ){
try{
if( !stopRequested && isReindexRequested() ){
log.debug("full re-index requested");
indexRebuild();
}else if( !stopRequested && isThereWorkToDo() ){
Thread.sleep(250); //wait a bit to let a bit more work to come into the queue
log.debug("work found for IndexBuilder, starting update");
updatedIndex();
}else if( !stopRequested && ! isThereWorkToDo() ){
log.debug("there is no indexing working to do, waiting for work");
synchronized (this) { this.wait(reindexInterval); }
}
} catch (InterruptedException e) {
log.debug("woken up",e);
}catch(Throwable e){
log.error(e,e);
}
}
log.info("Stopping IndexBuilder thread");
}
/* ******************** non-public methods ************************* */ /* ******************** non-public methods ************************* */
private synchronized void setReindexRequested(boolean reindexRequested) {
this.reindexRequested = reindexRequested;
}
private synchronized Collection<String> getAndEmptyChangedUris(){ private synchronized Collection<String> getAndEmptyChangedUris(){
Collection<String> out = changedUris; Collection<String> out = changedUris;
changedUris = new HashSet<String>(); changedUris = new HashSet<String>();
return out; return out;
} }
protected void indexRebuild() throws IndexingException {
log.info("Rebuild of search index is starting.");
Iterator<ObjectSourceIface> sources = sourceList.iterator();
List listOfIterators = new LinkedList();
while(sources.hasNext()){
Object obj = sources.next();
if( obj != null && obj instanceof ObjectSourceIface )
listOfIterators.add((((ObjectSourceIface) obj)
.getAllOfThisTypeIterator()));
else
log.warn("\tskipping object of class "
+ obj.getClass().getName() + "\n"
+ "\tIt doesn not implement ObjectSourceIface.\n");
}
//clear out changed uris since we are doing a full index rebuild
getAndEmptyChangedUris();
if( listOfIterators.size() == 0){ log.warn("Warning: no ObjectSources found.");}
setReindexRequested(false);
doBuild( listOfIterators, Collections.EMPTY_LIST, true, NEW_DOCS );
log.info("Rebuild of search index is complete.");
}
protected void updatedIndex() throws IndexingException{
log.debug("Starting updateIndex()");
long since = indexer.getModified() - 60000;
Iterator<ObjectSourceIface> sources = sourceList.iterator();
List<Iterator<Individual>> listOfIterators =
new LinkedList<Iterator<Individual>>();
while (sources.hasNext()) {
Object obj = sources.next();
if (obj != null && obj instanceof ObjectSourceIface)
listOfIterators.add((((ObjectSourceIface) obj)
.getUpdatedSinceIterator(since)));
else
log.warn("\tskipping object of class "
+ obj.getClass().getName() + "\n"
+ "\tIt doesn not implement " + "ObjectSourceIface.\n");
}
buildAddAndDeleteLists( getAndEmptyChangedUris());
listOfIterators.add( (new IndexBuilder.BuilderObjectSource(updatedInds)).getUpdatedSinceIterator(0) );
doBuild( listOfIterators, deletedInds, false, UPDATE_DOCS );
log.debug("Ending updateIndex()");
}
/** /**
* Sets updatedUris and deletedUris. * Sets updatedUris and deletedUris lists.
* @param changedUris
*/ */
private void buildAddAndDeleteLists( Collection<String> uris){ private void makeAddAndDeleteLists( Collection<String> uris){
/* clear updateInds and deletedUris. This is the only method that should set these. */ /* clear updateInds and deletedUris. This is the only method that should set these. */
this.updatedInds = new ArrayList<Individual>(); this.updatedInds = new ArrayList<Individual>();
this.deletedInds = new ArrayList<Individual>(); this.deletedInds = new ArrayList<Individual>();
@ -218,43 +180,58 @@ public class IndexBuilder {
this.updatedInds = addDepResourceClasses(updatedInds); this.updatedInds = addDepResourceClasses(updatedInds);
} }
protected void indexRebuild() throws IndexingException {
log.info("Rebuild of search index is starting.");
Iterator<ObjectSourceIface> sources = sourceList.iterator();
List listOfIterators = new LinkedList();
while (sources.hasNext()) {
Object obj = sources.next();
if (obj != null && obj instanceof ObjectSourceIface)
listOfIterators.add((((ObjectSourceIface) obj)
.getAllOfThisTypeIterator()));
else
log.warn("\tskipping object of class "
+ obj.getClass().getName() + "\n"
+ "\tIt doesn not implement ObjectSourceIface.\n");
}
private List<Individual> addDepResourceClasses(List<Individual> inds) { // clear out changed uris since we are doing a full index rebuild
WebappDaoFactory wdf = (WebappDaoFactory)context.getAttribute("webappDaoFactory"); getAndEmptyChangedUris();
VClassDao vClassDao = wdf.getVClassDao();
Iterator<Individual> it = inds.iterator(); if (listOfIterators.size() == 0)
VClass depResVClass = new VClass(VitroVocabulary.DEPENDENT_RESORUCE); log.warn("Warning: no ObjectSources found.");
while(it.hasNext()){
Individual ind = it.next(); doBuild(listOfIterators, Collections.EMPTY_LIST );
List<VClass> classes = ind.getVClasses(); if( log != null ) //log might be null if system is shutting down.
boolean isDepResource = false; log.info("Rebuild of search index is complete.");
for( VClass clazz : classes){ }
if( !isDepResource && VitroVocabulary.DEPENDENT_RESORUCE.equals( clazz.getURI() ) ){
isDepResource = true; protected void updatedIndex() throws IndexingException{
break; log.debug("Starting updateIndex()");
} long since = indexer.getModified() - 60000;
}
if( ! isDepResource ){ Iterator<ObjectSourceIface> sources = sourceList.iterator();
for( VClass clazz : classes){ List<Iterator<Individual>> listOfIterators =
List<String> superClassUris = vClassDao.getAllSuperClassURIs(clazz.getURI()); new LinkedList<Iterator<Individual>>();
for( String uri : superClassUris){
if( VitroVocabulary.DEPENDENT_RESORUCE.equals( uri ) ){ while (sources.hasNext()) {
isDepResource = true; Object obj = sources.next();
break; if (obj != null && obj instanceof ObjectSourceIface)
} listOfIterators.add((((ObjectSourceIface) obj)
} .getUpdatedSinceIterator(since)));
if( isDepResource ) else
break; log.warn("\tskipping object of class "
} + obj.getClass().getName() + "\n"
} + "\tIt doesn not implement " + "ObjectSourceIface.\n");
if( isDepResource){ }
classes.add(depResVClass);
ind.setVClasses(classes, true); makeAddAndDeleteLists( getAndEmptyChangedUris());
} listOfIterators.add( (new IndexBuilder.BuilderObjectSource(updatedInds)).getUpdatedSinceIterator(0) );
}
return inds; doBuild( listOfIterators, deletedInds );
} log.debug("Ending updateIndex()");
}
/** /**
* For each sourceIterator, get all of the objects and attempt to * For each sourceIterator, get all of the objects and attempt to
@ -270,17 +247,22 @@ public class IndexBuilder {
* to false, and a check is made before adding, it will work fine; but * to false, and a check is made before adding, it will work fine; but
* checking if an object is on the index is slow. * checking if an object is on the index is slow.
*/ */
private void doBuild(List sourceIterators, Collection<Individual> deletes, boolean forceNewIndex, boolean newDocs ){ private void doBuild(List<Iterator<Individual>> sourceIterators, Collection<Individual> deletes ){
boolean aborted = false;
boolean newDocs = reindexRequested;
boolean forceNewIndex = reindexRequested;
try { try {
if( forceNewIndex ) if( reindexRequested )
indexer.prepareForRebuild(); indexer.prepareForRebuild();
indexer.startIndexing(); indexer.startIndexing();
reindexRequested = false;
if( ! forceNewIndex ){ if( ! forceNewIndex ){
for(Individual deleteMe : deletes ){ for(Individual deleteMe : deletes ){
indexer.removeFromIndex(deleteMe); indexer.removeFromIndex(deleteMe);
} }
} }
//get an iterator for all of the sources of indexable objects //get an iterator for all of the sources of indexable objects
@ -289,35 +271,50 @@ public class IndexBuilder {
while (sourceIters.hasNext()) { while (sourceIters.hasNext()) {
obj = sourceIters.next(); obj = sourceIters.next();
if (obj == null || !(obj instanceof Iterator)) { if (obj == null || !(obj instanceof Iterator)) {
log.warn("\tskipping object of class " log.warn("skipping object of class " + obj.getClass().getName()
+ obj.getClass().getName() + "\n" + "It doesn not implement Iterator.");
+ "\tIt doesn not implement "
+ "Iterator.\n");
continue; continue;
} }
indexForSource((Iterator)obj, newDocs); indexForSource((Iterator)obj, newDocs);
} }
} catch (IndexingException ex) { } catch (AbortIndexing abort){
log.error(ex,ex); if( log != null)
log.debug("aborting the indexing because thread stop was requested");
aborted = true;
} catch (Exception e) { } catch (Exception e) {
log.error(e,e); log.error(e,e);
} finally { }
if( aborted && forceNewIndex ){
indexer.abortIndexingAndCleanUp();
}else{
indexer.endIndexing(); indexer.endIndexing();
} }
} }
/** /**
* Use the back end indexer to index each object that the Iterator returns. * Use the back end indexer to index each object that the Iterator returns.
* @param items * @throws AbortIndexing
* @return
*/ */
private void indexForSource(Iterator<Individual> individuals , boolean newDocs){ private void indexForSource(Iterator<Individual> individuals , boolean newDocs) throws AbortIndexing{
if( individuals == null ) return;
long starttime = System.currentTimeMillis(); long starttime = System.currentTimeMillis();
long count = 0; long count = 0;
while(individuals.hasNext()){ while(individuals.hasNext()){
indexItem(individuals.next(), newDocs); if( stopRequested )
throw new AbortIndexing();
Individual ind = null;
try{
ind = individuals.next();
indexer.index(ind, newDocs);
}catch(Throwable ex){
if( stopRequested || log == null){//log might be null if system is shutting down.
throw new AbortIndexing();
}
String uri = ind!=null?ind.getURI():"null";
log.warn("Error indexing individual " + uri + " " + ex.getMessage());
}
count++; count++;
if( log.isDebugEnabled() ){ if( log.isDebugEnabled() ){
if( (count % 100 ) == 0 && count > 0 ){ if( (count % 100 ) == 0 && count > 0 ){
@ -330,55 +327,74 @@ public class IndexBuilder {
log.info( log.info(
"individuals indexed: " + count + " in " + (System.currentTimeMillis() - starttime) + " msec" + "individuals indexed: " + count + " in " + (System.currentTimeMillis() - starttime) + " msec" +
(count!=0?(" time per individual = " + (System.currentTimeMillis() - starttime)/ count + " msec"):"") (count!=0?(" time per individual = " + (System.currentTimeMillis() - starttime)/ count + " msec"):"")
); );
} }
/** /**
* Use the backend indexer to index a single item. * For a list of individuals, this builds a list of dependent resources and returns it.
* @param item
* @return
*/ */
private void indexItem( Individual ind, boolean newDoc){ private List<Individual> addDepResourceClasses(List<Individual> inds) {
try{ WebappDaoFactory wdf = (WebappDaoFactory)context.getAttribute("webappDaoFactory");
if( ind != null ){ VClassDao vClassDao = wdf.getVClassDao();
indexer.index(ind, newDoc); Iterator<Individual> it = inds.iterator();
} VClass depResVClass = new VClass(VitroVocabulary.DEPENDENT_RESORUCE);
}catch(Throwable ex){ while(it.hasNext()){
log.warn("IndexBuilder.indexItem() Error indexing " Individual ind = it.next();
+ ind + "\n" +ex); List<VClass> classes = ind.getVClasses();
boolean isDepResource = false;
for( VClass clazz : classes){
if( !isDepResource && VitroVocabulary.DEPENDENT_RESORUCE.equals( clazz.getURI() ) ){
isDepResource = true;
break;
}
}
if( ! isDepResource ){
for( VClass clazz : classes){
List<String> superClassUris = vClassDao.getAllSuperClassURIs(clazz.getURI());
for( String uri : superClassUris){
if( VitroVocabulary.DEPENDENT_RESORUCE.equals( uri ) ){
isDepResource = true;
break;
}
}
if( isDepResource )
break;
}
}
if( isDepResource){
classes.add(depResVClass);
ind.setVClasses(classes, true);
}
} }
return ; return inds;
} }
/* maybe ObjectSourceIface should be replaced with just an iterator. */
private class BuilderObjectSource implements ObjectSourceIface { private class BuilderObjectSource implements ObjectSourceIface {
private final List<Individual> individuals; private final List<Individual> individuals;
public BuilderObjectSource( List<Individual> individuals){ public BuilderObjectSource( List<Individual> individuals){
this.individuals=individuals; this.individuals=individuals;
} }
public Iterator getAllOfThisTypeIterator() {
return new Iterator(){
final Iterator it = individuals.iterator();
public Iterator getAllOfThisTypeIterator() { public boolean hasNext() {
return new Iterator(){ return it.hasNext();
final Iterator it = individuals.iterator(); }
public boolean hasNext() { public Object next() {
return it.hasNext(); return it.next();
} }
public Object next() { public void remove() { /* not implemented */}
return it.next(); };
} }
public Iterator getUpdatedSinceIterator(long msSinceEpoc) {
public void remove() { /* not implemented */} return getAllOfThisTypeIterator();
}; }
}
public Iterator getUpdatedSinceIterator(long msSinceEpoc) {
return getAllOfThisTypeIterator();
}
} }
private class AbortIndexing extends Exception { }
} }

View file

@ -1,72 +0,0 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.search.indexing;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Thread that executes the methods in IndexBuilder.
*
* @author bdc34
*
*/
public class IndexBuilderThread extends Thread{
private IndexBuilder indexBuilder;
protected boolean stopRequested = false;
protected long reindexInterval = 1000 * 60 /* msec */ ;
private static final Log log = LogFactory.getLog(IndexBuilderThread.class.getName());
public IndexBuilderThread(IndexBuilder ib){
super("IndexBuilderThread");
if( ib == null )
log.error("IndexBuilderThread needs an IndexBuilder, search is not configured.");
this.indexBuilder = ib;
}
@Override
public void run() {
while(true){
if( stopRequested ){
log.info("Stopping IndexBuilderThread ");
return;
}
if( indexBuilder == null )
log.warn("IndexBuilderThread needs a IndexBuilder, search may not be configured.");
try{
if( indexBuilder != null && indexBuilder.isReindexRequested() ){
log.debug("full re-index requested");
indexBuilder.indexRebuild();
}else{
if( indexBuilder != null && indexBuilder.isThereWorkToDo() ){
Thread.sleep(250); //wait a bit to let a bit more work to come into the queue
log.debug("work found for IndexBuilder, starting update");
indexBuilder.updatedIndex();
}
}
}catch (Throwable e) {
log.error(e,e);
}
if( indexBuilder != null && ! indexBuilder.isThereWorkToDo() ){
log.debug("there is no indexing working to do, going to sleep");
try {
synchronized (this) {
this.wait(reindexInterval);
}
} catch (InterruptedException e) {
log.debug(" woken up",e);
}
}
}
}
public synchronized void kill(){
log.debug("Attempting to kill IndexBuilderThread ");
stopRequested = true;
this.notifyAll();
}
}

View file

@ -54,4 +54,10 @@ public interface IndexerIface {
public void endIndexing(); public void endIndexing();
public long getModified(); public long getModified();
/**
* Ends the indexing and removes any temporary files.
* This may be called instead of endIndexing()
*/
public void abortIndexingAndCleanUp();
} }

View file

@ -456,4 +456,21 @@ public class LuceneIndexer implements IndexerIface {
//if it is clear it out but don't rebuild. //if it is clear it out but don't rebuild.
return false; return false;
} }
@Override
public synchronized void abortIndexingAndCleanUp() {
if( ! indexing )
log.error("abortIndexingAndCleanUp() should only be called if LuceneIndexer is indexing.");
else if( ! fullRebuild )
log.error("abortIndexingAndCleanUp() should only be called if LuceneIndexer to end an aborted full index rebuild");
else{
closeWriter();
File offLineDir = new File(currentOffLineDir);
boolean deleted = deleteDir(offLineDir);
//log might be null if system is shutting down.
if( ! deleted ){
System.out.println("Could not clean up temp indexing dir " + currentOffLineDir);
}
}
}
} }

View file

@ -134,17 +134,12 @@ public class LuceneSetup implements javax.servlet.ServletContextListener {
// set up listeners so search index builder is notified of changes to model // set up listeners so search index builder is notified of changes to model
ServletContext ctx = sce.getServletContext(); ServletContext ctx = sce.getServletContext();
SearchReindexingListener srl = new SearchReindexingListener(builder); SearchReindexingListener srl = new SearchReindexingListener(builder);
ModelContext.getBaseOntModel(ctx).getBaseModel().register(srl); ModelContext.registerListenerForChanges(ctx, srl);
ModelContext.getJenaOntModel(ctx).getBaseModel().register(srl);
ModelContext.getInferenceOntModel(ctx).register(srl);
ModelContext.getUnionOntModelSelector(ctx).getABoxModel()
.getBaseModel().register(srl);
if( (Boolean)sce.getServletContext().getAttribute(INDEX_REBUILD_REQUESTED_AT_STARTUP) instanceof Boolean && if( (Boolean)sce.getServletContext().getAttribute(INDEX_REBUILD_REQUESTED_AT_STARTUP) instanceof Boolean &&
(Boolean)sce.getServletContext().getAttribute(INDEX_REBUILD_REQUESTED_AT_STARTUP) ){ (Boolean)sce.getServletContext().getAttribute(INDEX_REBUILD_REQUESTED_AT_STARTUP) ){
log.info("Rebuild of lucene index required before startup."); log.info("Rebuild of lucene index required before startup.");
builder.doIndexRebuild(); builder.doIndexRebuild();
Thread.currentThread().sleep(500);
int n = 0; int n = 0;
while( builder.isReindexRequested() || builder.isIndexing() ){ while( builder.isReindexRequested() || builder.isIndexing() ){
n++; n++;
@ -169,7 +164,7 @@ public class LuceneSetup implements javax.servlet.ServletContextListener {
log.debug("**** Running " + this.getClass().getName() + ".contextDestroyed()"); log.debug("**** Running " + this.getClass().getName() + ".contextDestroyed()");
IndexBuilder builder = (IndexBuilder) sce.getServletContext().getAttribute(IndexBuilder.class.getName()); IndexBuilder builder = (IndexBuilder) sce.getServletContext().getAttribute(IndexBuilder.class.getName());
if( builder != null){ if( builder != null){
builder.killIndexingThread(); builder.stopIndexingThread();
} }
} }

View file

@ -25,8 +25,8 @@ import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
import edu.cornell.mannlib.vitro.webapp.dao.filtering.WebappDaoFactoryFiltering; import edu.cornell.mannlib.vitro.webapp.dao.filtering.WebappDaoFactoryFiltering;
import edu.cornell.mannlib.vitro.webapp.dao.filtering.filters.VitroFilterUtils; import edu.cornell.mannlib.vitro.webapp.dao.filtering.filters.VitroFilterUtils;
import edu.cornell.mannlib.vitro.webapp.dao.filtering.filters.VitroFilters; import edu.cornell.mannlib.vitro.webapp.dao.filtering.filters.VitroFilters;
import edu.cornell.mannlib.vitro.webapp.dao.jena.ModelContext;
import edu.cornell.mannlib.vitro.webapp.dao.jena.SearchReindexingListener; import edu.cornell.mannlib.vitro.webapp.dao.jena.SearchReindexingListener;
import edu.cornell.mannlib.vitro.webapp.search.beans.Searcher;
import edu.cornell.mannlib.vitro.webapp.search.indexing.IndexBuilder; import edu.cornell.mannlib.vitro.webapp.search.indexing.IndexBuilder;
/** /**
@ -108,8 +108,7 @@ public class LuceneSetupCJK implements javax.servlet.ServletContextListener {
OntModel baseOntModel = (OntModel)sce.getServletContext().getAttribute("baseOntModel"); OntModel baseOntModel = (OntModel)sce.getServletContext().getAttribute("baseOntModel");
OntModel jenaOntModel = (OntModel)sce.getServletContext().getAttribute("jenaOntModel"); OntModel jenaOntModel = (OntModel)sce.getServletContext().getAttribute("jenaOntModel");
SearchReindexingListener srl = new SearchReindexingListener( builder ); SearchReindexingListener srl = new SearchReindexingListener( builder );
baseOntModel.getBaseModel().register(srl); ModelContext.registerListenerForChanges(sce.getServletContext(), srl);
jenaOntModel.getBaseModel().register(srl);
}catch(Exception ex){ }catch(Exception ex){
log.error("Could not setup lucene full text search." , ex); log.error("Could not setup lucene full text search." , ex);
@ -125,7 +124,7 @@ public class LuceneSetupCJK implements javax.servlet.ServletContextListener {
log.info("**** Running "+this.getClass().getName()+".contextDestroyed()"); log.info("**** Running "+this.getClass().getName()+".contextDestroyed()");
IndexBuilder builder = (IndexBuilder)sce.getServletContext().getAttribute(IndexBuilder.class.getName()); IndexBuilder builder = (IndexBuilder)sce.getServletContext().getAttribute(IndexBuilder.class.getName());
builder.killIndexingThread(); builder.stopIndexingThread();
} }
/** /**

View file

@ -14,20 +14,24 @@ public class IndexBuilderThreadTest extends AbstractTestClass {
@Test @Test
public void testStoppingTheThread(){ public void testStoppingTheThread(){
setLoggerLevel(IndexBuilderThread.class, Level.OFF); setLoggerLevel(IndexBuilder.class, Level.OFF);
IndexBuilderThread ibt = new IndexBuilderThread(null);
ibt.start(); IndexBuilder ib = new IndexBuilder();
Assert.assertNotSame(Thread.State.NEW, ib.getState() );
Assert.assertNotSame(Thread.State.TERMINATED, ib.getState() );
try { try {
Thread.sleep(100); Thread.sleep(100);
} catch (InterruptedException e) { } catch (InterruptedException e) {
Assert.fail(e.getMessage()); Assert.fail(e.getMessage());
} }
ibt.kill(); ib.stopIndexingThread();
try { try {
Thread.sleep(100); Thread.sleep(100);
} catch (InterruptedException e) { } catch (InterruptedException e) {
Assert.fail(e.getMessage()); Assert.fail(e.getMessage());
} }
Assert.assertFalse(ibt.isAlive()); Assert.assertFalse(ib.isAlive());
Assert.assertSame(Thread.State.TERMINATED, ib.getState() );
} }
} }