### Eclipse Workspace Patch 1.0 #P org.eclipse.jdt.core Index: search/org/eclipse/jdt/core/search/SearchParticipant.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchParticipant.java,v retrieving revision 1.27 diff -u -r1.27 SearchParticipant.java --- search/org/eclipse/jdt/core/search/SearchParticipant.java 27 Jun 2008 16:04:08 -0000 1.27 +++ search/org/eclipse/jdt/core/search/SearchParticipant.java 20 Aug 2010 09:13:50 -0000 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2008 IBM Corporation and others. + * Copyright (c) 2000, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -49,6 +49,8 @@ */ public abstract class SearchParticipant { + private IPath lastIndexLocation; + /** * Creates a new search participant. */ @@ -205,6 +207,10 @@ // TODO (frederic) should not have to create index manually, should expose API that recreates index instead manager.ensureIndexExists(indexLocation, containerPath); manager.scheduleDocumentIndexing(document, containerPath, indexLocation, this); + if (!indexLocation.equals(this.lastIndexLocation)) { + manager.updateParticipant(indexLocation, containerPath); + this.lastIndexLocation = indexLocation; + } } /** Index: search/org/eclipse/jdt/internal/core/search/indexing/IndexManager.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IndexManager.java,v retrieving revision 1.166 diff -u -r1.166 IndexManager.java --- search/org/eclipse/jdt/internal/core/search/indexing/IndexManager.java 13 May 2010 00:51:11 -0000 1.166 +++ search/org/eclipse/jdt/internal/core/search/indexing/IndexManager.java 20 Aug 2010 09:13:51 -0000 @@ -53,11 +53,16 @@ // key = indexLocation path, value = index state integer private SimpleLookupTable indexStates = null; private File savedIndexNamesFile = new File(getSavedIndexesDirectory(), "savedIndexNames.txt"); //$NON-NLS-1$ + private File participantIndexNamesFile = new File(getSavedIndexesDirectory(), "participantsIndexNames.txt"); //$NON-NLS-1$ private boolean javaLikeNamesChanged = true; public static final Integer SAVED_STATE = new Integer(0); public static final Integer UPDATING_STATE = new Integer(1); public static final Integer UNKNOWN_STATE = new Integer(2); public static final Integer REBUILDING_STATE = new Integer(3); + + // search participants who register indexes with the index manager + private SimpleLookupTable participantsContainers = null; + private boolean participantUpdated = false; // Debug public static boolean DEBUG = false; @@ -324,6 +329,20 @@ rebuildIndex(indexLocation, containerPath); index = null; } + } else { + if (!getJavaPluginWorkingLocation().isPrefixOf(indexLocation)) { // the index belongs to non-jdt search participant + if (indexLocation.toFile().exists()) { + try { + IPath container = getParticipantsContainer(indexLocation); + if (container != null) { + index = new Index(indexLocation.toOSString(), container.toOSString(), true /*reuse index file*/); + this.indexes.put(indexLocation, index); + } + } catch (IOException e) { + // ignore + } + } + } } } if (index != null) @@ -370,6 +389,12 @@ } return this.indexStates; } +private IPath getParticipantsContainer(IPath indexLocation) { + if (this.participantsContainers == null) { + readParticipantsIndexNamesFile(); + } + return (IPath)this.participantsContainers.get(indexLocation); +} private IPath getJavaPluginWorkingLocation() { if (this.javaPluginLocation != null) return this.javaPluginLocation; @@ -661,6 +686,10 @@ for (int i = 0; i < count; i++) this.indexes.removeKey(locations[i]); removeIndexesState(locations); + if (this.participantsContainers != null && this.participantsContainers.get(path.toOSString()) != null) { + this.participantsContainers.removeKey(path.toOSString()); + writeParticipantsIndexNamesFile(); + } } } /** @@ -802,6 +831,10 @@ monitor.exitRead(); } } + if (this.participantsContainers != null && this.participantUpdated) { + writeParticipantsIndexNamesFile(); + this.participantUpdated = false; + } this.needToSave = !allSaved; } public void scheduleDocumentIndexing(final SearchDocument searchDocument, IPath container, final IPath indexLocation, final SearchParticipant searchParticipant) { @@ -861,6 +894,28 @@ } return null; } +private void readParticipantsIndexNamesFile() { + SimpleLookupTable containers = new SimpleLookupTable(3); + try { + char[] participantIndexNames = org.eclipse.jdt.internal.compiler.util.Util.getFileCharContent(this.participantIndexNamesFile, null); + if (participantIndexNames.length > 0) { + char[][] names = CharOperation.splitOn('\n', participantIndexNames); + if (names.length >= 3) { + // First line is DiskIndex signature (see writeParticipantsIndexNamesFile()) + if (DiskIndex.SIGNATURE.equals(new String(names[0]))) { + for (int i = 1, l = names.length-1 ; i < l ; i+=2) { + containers.put(new Path(new String(names[i])), new Path(new String(names[i+1]))); + } + } + } + } + } catch (IOException ignored) { + if (VERBOSE) + Util.verbose("Failed to read participant index file names"); //$NON-NLS-1$ + } + this.participantsContainers = containers; + return; +} private synchronized void removeIndexesState(IPath[] locations) { getIndexStates(); // ensure the states are initialized int length = locations.length; @@ -907,6 +962,15 @@ } } +public void updateParticipant(IPath indexLocation, IPath containerPath) { + if (this.participantsContainers == null) { + readParticipantsIndexNamesFile(); + } + if (this.participantsContainers.get(indexLocation) == null) { + this.participantsContainers.put(indexLocation, containerPath); + this.participantUpdated = true; + } +} private void writeJavaLikeNamesFile() { BufferedWriter writer = null; String pathName = getJavaPluginWorkingLocation().toOSString(); @@ -941,6 +1005,36 @@ } } } +private void writeParticipantsIndexNamesFile() { + BufferedWriter writer = null; + try { + writer = new BufferedWriter(new FileWriter(this.participantIndexNamesFile)); + writer.write(DiskIndex.SIGNATURE); + writer.write('\n'); + Object[] indexFiles = this.participantsContainers.keyTable; + Object[] containers = this.participantsContainers.valueTable; + for (int i = 0, l = indexFiles.length; i < l; i++) { + IPath indexFile = (IPath)indexFiles[i]; + if (indexFile != null) { + writer.write(indexFile.toOSString()); + writer.write('\n'); + writer.write(((IPath)containers[i]).toOSString()); + writer.write('\n'); + } + } + } catch (IOException ignored) { + if (VERBOSE) + Util.verbose("Failed to write participant index file names", System.err); //$NON-NLS-1$ + } finally { + if (writer != null) { + try { + writer.close(); + } catch (IOException e) { + // ignore + } + } + } +} private void writeSavedIndexNamesFile() { BufferedWriter writer = null; try { #P org.eclipse.jdt.core.tests.model Index: src/org/eclipse/jdt/core/tests/model/SearchParticipantTests.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/SearchParticipantTests.java,v retrieving revision 1.18 diff -u -r1.18 SearchParticipantTests.java --- src/org/eclipse/jdt/core/tests/model/SearchParticipantTests.java 27 Jun 2008 16:02:38 -0000 1.18 +++ src/org/eclipse/jdt/core/tests/model/SearchParticipantTests.java 20 Aug 2010 09:13:56 -0000 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2008 IBM Corporation and others. + * Copyright (c) 2000, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -314,4 +314,85 @@ "X.test X [X]", requestor); } + + /* + * Ensures that a simple search that forwards queries to the default participant works as expected even after restart + * https://bugs.eclipse.org/bugs/show_bug.cgi?id=308402 + */ + public void testSearchAfterRestart() throws CoreException { + createFile( + "/P/X.test", + "public class X {\n" + + "}" + ); + + // index file + TestSearchParticipant participant = new TestSearchParticipant(); + TestSearchDocument document = new TestSearchDocument("/P/X.test", participant); + participant.scheduleDocumentIndexing(document, getIndexLocation()); + waitUntilIndexesReady(); + try { + Thread.sleep(5000); // wait for the indexes to go into the disk + } catch (InterruptedException e) { + // ignore + } + simulateExit(); + simulateRestart(); + waitUntilIndexesReady(); + + // search for declaration of X + SearchPattern pattern = SearchPattern.createPattern("X", IJavaSearchConstants.DECLARATIONS, IJavaSearchConstants.TYPE, SearchPattern.R_EXACT_MATCH); + IJavaSearchScope scope = SearchEngine.createWorkspaceScope(); + SearchRequestor requestor = new TestResultCollector(); + new SearchEngine().search(pattern, new SearchParticipant[] {participant}, scope, requestor, null); + assertSearchResults( + "X.test X [X]", + requestor); + + } + + /* + * Ensures that a simple search that forwards queries to the default participant works as expected even after restart + * https://bugs.eclipse.org/bugs/show_bug.cgi?id=308402 + */ + public void testSearchAfterRemoveAndRestart() throws CoreException { + createFile( + "/P/X.test", + "public class X {\n" + + "}" + ); + + // index file + TestSearchParticipant participant = new TestSearchParticipant(); + TestSearchDocument document = new TestSearchDocument("/P/X.test", participant); + participant.scheduleDocumentIndexing(document, getIndexLocation()); + waitUntilIndexesReady(); + + // search for declaration of X + SearchPattern pattern = SearchPattern.createPattern("X", IJavaSearchConstants.DECLARATIONS, IJavaSearchConstants.TYPE, SearchPattern.R_EXACT_MATCH); + IJavaSearchScope scope = SearchEngine.createWorkspaceScope(); + SearchRequestor requestor = new TestResultCollector(); + new SearchEngine().search(pattern, new SearchParticipant[] {participant}, scope, requestor, null); + + // remove the index + participant.removeIndex(getIndexLocation()); + assertSearchResults( + "X.test X [X]", + requestor); + try { + Thread.sleep(5000); // wait for the indexes to go into the disk + } catch (InterruptedException e) { + // ignore + } + requestor = new TestResultCollector(); + new SearchEngine().search(pattern, new SearchParticipant[] {participant}, scope, requestor, null); + assertSearchResults("", requestor); + + simulateExit(); + simulateRestart(); + waitUntilIndexesReady(); + requestor = new TestResultCollector(); + new SearchEngine().search(pattern, new SearchParticipant[] {participant}, scope, requestor, null); + assertSearchResults("", requestor); + } }