package com.venky.swf.plugins.lucene.index.background; import java.io.IOException; import java.util.List; import org.apache.lucene.document.Document; import org.apache.lucene.index.IndexReader; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.Query; import org.apache.lucene.search.ScoreDoc; import org.apache.lucene.search.Sort; import org.apache.lucene.search.SortField; import org.apache.lucene.search.TopDocs; import org.apache.lucene.store.Directory; import com.venky.cache.Cache; import com.venky.core.util.Bucket; import com.venky.swf.plugins.background.core.TaskManager; import com.venky.swf.plugins.lucene.index.background.IndexTask.Operation; import com.venky.swf.plugins.lucene.index.common.CompleteSearchCollector; import com.venky.swf.plugins.lucene.index.common.DatabaseDirectory; import com.venky.swf.plugins.lucene.index.common.ResultCollector; import com.venky.swf.sql.Select; public class IndexManager { private static IndexManager _instance = new IndexManager(); public static IndexManager instance() { return _instance; } private IndexManager() { } private Cache<String, Directory> directoryCache = new Cache<String, Directory>() { /** * */ private static final long serialVersionUID = -7199535528835102853L; @Override protected Directory getValue(String k) { try { return new DatabaseDirectory(k); } catch (IOException e) { throw new RuntimeException(e); } } }; public Directory getDirectory(String name){ return directoryCache.get(name); } private IndexTask createIndexTask(String tableName,List<Document> documents, Operation operation){ IndexTask task = new IndexTask(); task.setDirectory(tableName); task.setDocuments(documents); task.setOperation(operation); return task; } public void addDocuments(String tableName, List<Document> documents){ TaskManager.instance().executeDelayed(createIndexTask(tableName, documents, Operation.ADD)); } public void updateDocuments(String tableName, List<Document> documents) { TaskManager.instance().executeDelayed(createIndexTask(tableName, documents, Operation.MODIFY)); } public void removeDocuments(String tableName, List<Document> documents) { TaskManager.instance().executeDelayed(createIndexTask(tableName, documents, Operation.DELETE)); } private Cache<String, IndexSearcher> indexSearcherCache = new Cache<String, IndexSearcher>() { /** * */ private static final long serialVersionUID = -7984161420681471139L; @Override protected IndexSearcher getValue(String k) { try { return new IndexSearcher( IndexReader.open(directoryCache.get(k))); } catch (IOException e) { throw new RuntimeException(e); } } }; private Cache<IndexSearcher, Bucket> searcherReferenceCount = new Cache<IndexSearcher, Bucket>() { /** * */ private static final long serialVersionUID = -3704220332108717190L; @Override protected Bucket getValue(IndexSearcher k) { return new Bucket(); } }; private void incRef(IndexSearcher searcher) { Bucket bucket = searcherReferenceCount.get(searcher); bucket.increment(); } private void decRef(String tableName,IndexSearcher searcher) { Bucket bucket = searcherReferenceCount.get(searcher); bucket.decrement(); if (bucket.intValue() <= 0) { IndexSearcher currentSearcher = indexSearcherCache.get(tableName); if (currentSearcher != searcher){ try { searcher.getIndexReader().close(); searcher.close(); }catch (IOException ex){ throw new RuntimeException(ex); } } } } private IndexSearcher getIndexSearcher(String tableName) { try { IndexSearcher searcher = null; synchronized (indexSearcherCache) { searcher = indexSearcherCache.get(tableName); IndexReader newReader = IndexReader.openIfChanged(searcher.getIndexReader()); if (newReader != null) { searcher = new IndexSearcher(newReader); indexSearcherCache.put(tableName, searcher); } } return searcher; } catch (IOException ex) { throw new RuntimeException(ex); } } public void fire(String tableName, Query q, int numHits, ResultCollector callback) { IndexSearcher searcher = null; try { searcher = getIndexSearcher(tableName); incRef(searcher); if (numHits == Select.MAX_RECORDS_ALL_RECORDS){ CompleteSearchCollector collector = new CompleteSearchCollector(); searcher.search(q, collector); for (int docId : collector.getDocIds()){ Document d = searcher.doc(docId); callback.found(d); } }else { TopDocs tDocs = searcher.search(q,numHits,new Sort(new SortField("ID", SortField.INT ,true))); /* TopScoreDocCollector collector = TopScoreDocCollector.create(numHits, true); searcher.search(q, collector); tDocs = collector.topDocs(); */ ScoreDoc[] hits = tDocs.scoreDocs; for (int i = 0; i < hits.length; ++i) { int docId = hits[i].doc; Document d = searcher.doc(docId); callback.found(d); } } } catch (Exception ex) { throw new RuntimeException(ex); }finally { if (searcher != null){ decRef(tableName, searcher); } } } }