From a004081b913c1bcf50184ee76df00bf889965d98 Mon Sep 17 00:00:00 2001
From: James Moger <james.moger@gitblit.com>
Date: Wed, 21 Mar 2012 18:04:34 -0400
Subject: [PATCH] Documentation

---
 src/com/gitblit/LuceneExecutor.java |  119 ++++++++++++++++++++++++++++-------------------------------
 1 files changed, 56 insertions(+), 63 deletions(-)

diff --git a/src/com/gitblit/LuceneExecutor.java b/src/com/gitblit/LuceneExecutor.java
index 489d308..65e1b2b 100644
--- a/src/com/gitblit/LuceneExecutor.java
+++ b/src/com/gitblit/LuceneExecutor.java
@@ -148,26 +148,12 @@
 	}
 
 	/**
-	 * Indicates if the Lucene executor can index repositories.
-	 * 
-	 * @return true if the Lucene executor is ready to index repositories
-	 */
-	public boolean isReady() {
-		return storedSettings.getBoolean(Keys.lucene.enable, false);
-	}
-
-	/**
-	 * Run is executed by the gitblit executor service at whatever frequency
-	 * is specified in the settings.  Because this is called by an executor
-	 * service, calls will queue - i.e. there can never be concurrent execution
-	 * of repository index updates.
+	 * Run is executed by the Gitblit executor service.  Because this is called 
+	 * by an executor service, calls will queue - i.e. there can never be
+	 * concurrent execution of repository index updates.
 	 */
 	@Override
 	public void run() {
-		if (!isReady()) {
-			return;
-		}
-
 		for (String repositoryName: GitBlit.self().getRepositoryList()) {
 			RepositoryModel model = GitBlit.self().getRepositoryModel(repositoryName);
 			if (model.hasCommits && !ArrayUtils.isEmpty(model.indexedBranches)) {
@@ -228,7 +214,16 @@
 	 * 
 	 * @param repositoryName
 	 */
-	public void close(String repositoryName) {
+	public synchronized void close(String repositoryName) {
+		try {
+			IndexSearcher searcher = searchers.remove(repositoryName);
+			if (searcher != null) {
+				searcher.getIndexReader().close();
+			}
+		} catch (Exception e) {
+			logger.error("Failed to close index searcher for " + repositoryName, e);
+		}
+		
 		try {
 			IndexWriter writer = writers.remove(repositoryName);
 			if (writer != null) {
@@ -236,23 +231,14 @@
 			}
 		} catch (Exception e) {
 			logger.error("Failed to close index writer for " + repositoryName, e);
-		}
-
-		try {
-			IndexSearcher searcher = searchers.remove(repositoryName);
-			if (searcher != null) {
-				searcher.close();
-			}
-		} catch (Exception e) {
-			logger.error("Failed to close index searcher for " + repositoryName, e);
-		}
+		}		
 	}
 
 	/**
 	 * Close all Lucene indexers.
 	 * 
 	 */
-	public void close() {
+	public synchronized void close() {
 		// close all writers
 		for (String writer : writers.keySet()) {
 			try {
@@ -266,7 +252,7 @@
 		// close all searchers
 		for (String searcher : searchers.keySet()) {
 			try {
-				searchers.get(searcher).close();
+				searchers.get(searcher).getIndexReader().close();
 			} catch (Throwable t) {
 				logger.error("Failed to close Lucene searcher for " + searcher, t);
 			}
@@ -283,18 +269,9 @@
 	 */
 	public boolean deleteIndex(String repositoryName) {
 		try {
-			// remove the repository index writer from the cache and close it
-			IndexWriter writer = writers.remove(repositoryName);
-			if (writer != null) {
-				writer.close();
-				writer = null;
-			}
-			// remove the repository index searcher from the cache and close it
-			IndexSearcher searcher = searchers.remove(repositoryName);
-			if (searcher != null) {
-				searcher.close();
-				searcher = null;
-			}
+			// close any open writer/searcher
+			close(repositoryName);
+
 			// delete the index folder
 			File repositoryFolder = new File(repositoriesFolder, repositoryName);
 			File luceneIndex = new File(repositoryFolder, LUCENE_DIR);
@@ -420,7 +397,7 @@
 	 * @return IndexResult
 	 */
 	public IndexResult reindex(RepositoryModel model, Repository repository) {
-		IndexResult result = new IndexResult();
+		IndexResult result = new IndexResult();		
 		if (!deleteIndex(model.name)) {
 			return result;
 		}
@@ -615,8 +592,8 @@
 			// commit all changes and reset the searcher
 			config.setInt(CONF_INDEX, null, CONF_VERSION, INDEX_VERSION);
 			config.save();
-			resetIndexSearcher(model.name);
 			writer.commit();
+			resetIndexSearcher(model.name);
 			result.success();
 		} catch (Exception e) {
 			logger.error("Exception while reindexing " + model.name, e);
@@ -645,7 +622,7 @@
 			IndexWriter writer = getIndexWriter(repositoryName);
 			for (PathChangeModel path : changedPaths) {
 				// delete the indexed blob
-				deleteBlob(repositoryName, branch, path.path);
+				deleteBlob(repositoryName, branch, path.name);
 
 				// re-index the blob
 				if (!ChangeType.DELETE.equals(path.changeType)) {
@@ -678,8 +655,17 @@
 				}
 			}
 			writer.commit();
-
-			Document doc = createDocument(commit, null);
+			
+			// get any annotated commit tags
+			List<String> commitTags = new ArrayList<String>();
+			for (RefModel ref : JGitUtils.getTags(repository, true, -1)) {
+				if (ref.isAnnotatedTag() && ref.getReferencedObjectId().equals(commit.getId())) {
+					commitTags.add(ref.displayName);
+				}
+			}
+			
+			// create and write the Lucene document
+			Document doc = createDocument(commit, commitTags);
 			doc.add(new Field(FIELD_BRANCH, branch, Store.YES, Index.ANALYZED));
 			result.commitCount++;
 			result.success = index(repositoryName, doc);
@@ -931,8 +917,8 @@
 		try {			
 			IndexWriter writer = getIndexWriter(repositoryName);
 			writer.addDocument(doc);
-			resetIndexSearcher(repositoryName);
 			writer.commit();
+			resetIndexSearcher(repositoryName);
 			return true;
 		} catch (Exception e) {
 			logger.error(MessageFormat.format("Exception while incrementally updating {0} Lucene index", repositoryName), e);
@@ -940,8 +926,10 @@
 		return false;
 	}
 
-	private SearchResult createSearchResult(Document doc, float score) throws ParseException {
+	private SearchResult createSearchResult(Document doc, float score, int hitId, int totalHits) throws ParseException {
 		SearchResult result = new SearchResult();
+		result.hitId = hitId;
+		result.totalHits = totalHits;
 		result.score = score;
 		result.date = DateTools.stringToDate(doc.get(FIELD_DATE));
 		result.summary = doc.get(FIELD_SUMMARY);		
@@ -964,7 +952,7 @@
 	private synchronized void resetIndexSearcher(String repository) throws IOException {
 		IndexSearcher searcher = searchers.remove(repository);
 		if (searcher != null) {
-			searcher.close();
+			searcher.getIndexReader().close();
 		}
 	}
 
@@ -1017,19 +1005,21 @@
 	 * 
 	 * @param text
 	 *            if the text is null or empty, null is returned
-	 * @param maximumHits
-	 *            the maximum number of hits to collect
+	 * @param page
+	 *            the page number to retrieve. page is 1-indexed.
+	 * @param pageSize
+	 *            the number of elements to return for this page
 	 * @param repositories
 	 *            a list of repositories to search. if no repositories are
 	 *            specified null is returned.
 	 * @return a list of SearchResults in order from highest to the lowest score
 	 * 
 	 */
-	public List<SearchResult> search(String text, int maximumHits, List<String> repositories) {
+	public List<SearchResult> search(String text, int page, int pageSize, List<String> repositories) {
 		if (ArrayUtils.isEmpty(repositories)) {
 			return null;
 		}
-		return search(text, maximumHits, repositories.toArray(new String[0]));
+		return search(text, page, pageSize, repositories.toArray(new String[0]));
 	}
 	
 	/**
@@ -1037,15 +1027,17 @@
 	 * 
 	 * @param text
 	 *            if the text is null or empty, null is returned
-	 * @param maximumHits
-	 *            the maximum number of hits to collect
+	 * @param page
+	 *            the page number to retrieve. page is 1-indexed.
+	 * @param pageSize
+	 *            the number of elements to return for this page
 	 * @param repositories
 	 *            a list of repositories to search. if no repositories are
 	 *            specified null is returned.
 	 * @return a list of SearchResults in order from highest to the lowest score
 	 * 
-	 */	
-	public List<SearchResult> search(String text, int maximumHits, String... repositories) {
+	 */
+	public List<SearchResult> search(String text, int page, int pageSize, String... repositories) {
 		if (StringUtils.isEmpty(text)) {
 			return null;
 		}
@@ -1082,14 +1074,15 @@
 				searcher = new IndexSearcher(reader);
 			}
 			Query rewrittenQuery = searcher.rewrite(query);
-			TopScoreDocCollector collector = TopScoreDocCollector.create(maximumHits, true);
+			TopScoreDocCollector collector = TopScoreDocCollector.create(5000, true);
 			searcher.search(rewrittenQuery, collector);
-			ScoreDoc[] hits = collector.topDocs().scoreDocs;
+			int offset = Math.max(0, (page - 1) * pageSize);
+			ScoreDoc[] hits = collector.topDocs(offset, pageSize).scoreDocs;
+			int totalHits = collector.getTotalHits();
 			for (int i = 0; i < hits.length; i++) {
 				int docId = hits[i].doc;
 				Document doc = searcher.doc(docId);
-				// TODO identify the source index for the doc, then eliminate FIELD_REPOSITORY				
-				SearchResult result = createSearchResult(doc, hits[i].score);
+				SearchResult result = createSearchResult(doc, hits[i].score, offset + i + 1, totalHits);
 				if (repositories.length == 1) {
 					// single repository search
 					result.repository = repositories[0];
@@ -1140,7 +1133,7 @@
 		Highlighter highlighter = new Highlighter(formatter, scorer);		
 		highlighter.setTextFragmenter(fragmenter);
 		
-		String [] fragments = highlighter.getBestFragments(analyzer, "content", content, 5);
+		String [] fragments = highlighter.getBestFragments(analyzer, "content", content, 3);
 		if (ArrayUtils.isEmpty(fragments)) {
 			if (SearchObjectType.blob  == result.type) {
 				return "";

--
Gitblit v1.9.1