diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMManager.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMManager.java index 6a90fe119aa..88867c6a356 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMManager.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMManager.java @@ -149,12 +149,12 @@ public class PDOMManager implements IWritableIndexManager, IListener { private final PDOMIndexerJob fIndexerJob; private IPDOMIndexerTask fCurrentTask; private int fSourceCount, fHeaderCount, fTickCount; - + private final ArrayDeque fChangeEvents= new ArrayDeque(); private final Job fNotificationJob; - private final AtomicMultiSet fFilesIndexedUnconditionlly= new AtomicMultiSet(); - + private final AtomicMultiSet fFilesIndexedUnconditionlly= new AtomicMultiSet(); + /** * Stores mapping from pdom to project, used to serialize creation of new pdoms. */ @@ -162,7 +162,7 @@ public class PDOMManager implements IWritableIndexManager, IListener { private Map fFileToProject= new HashMap(); private ListenerList fChangeListeners= new ListenerList(); private ListenerList fStateListeners= new ListenerList(); - + private IndexChangeEvent fIndexChangeEvent= new IndexChangeEvent(); private IndexerStateEvent fIndexerStateEvent= new IndexerStateEvent(); @@ -172,17 +172,17 @@ public class PDOMManager implements IWritableIndexManager, IListener { private final ICProjectDescriptionListener fProjectDescriptionListener; private final JobChangeListener fJobChangeListener; private final IPreferenceChangeListener fPreferenceChangeListener; - + private IndexFactory fIndexFactory= new IndexFactory(this); private IndexProviderManager fIndexProviderManager = new IndexProviderManager(); - + /** - * Serializes creation of new indexer, when acquiring the lock you are + * Serializes creation of new indexer, when acquiring the lock you are * not allowed to hold a lock on fPDOMs. */ private Map fUpdatePolicies= new HashMap(); private Set fClosingProjects= new HashSet(); - + private Map fPrefListeners= new HashMap(); private List fSetupParticipants= new ArrayList(); private Set fPostponedProjects= new HashSet(); @@ -190,7 +190,7 @@ public class PDOMManager implements IWritableIndexManager, IListener { private boolean fInShutDown; boolean fTraceIndexerSetup; - + public PDOMManager() { PDOM.sDEBUG_LOCKS= "true".equals(Platform.getDebugOption(CCorePlugin.PLUGIN_ID + "/debug/index/locks")); //$NON-NLS-1$//$NON-NLS-2$ addIndexerSetupParticipant(new WaitForRefreshJobs()); @@ -206,7 +206,7 @@ public class PDOMManager implements IWritableIndexManager, IListener { fIndexerJob= new PDOMIndexerJob(this); fNotificationJob= createNotifyJob(); } - + public Job startup() { fInShutDown= false; Job postStartupJob= new Job(CCorePlugin.getResourceString("CCorePlugin.startupJob")) { //$NON-NLS-1$ @@ -221,10 +221,10 @@ public class PDOMManager implements IWritableIndexManager, IListener { } }; postStartupJob.setSystem(true); - return postStartupJob; + return postStartupJob; } - /** + /** * Called from a job after plugin start. */ protected void postStartup() { @@ -236,7 +236,7 @@ public class PDOMManager implements IWritableIndexManager, IListener { adjustCacheSize(); updatePathCanonicalizationStrategy(); fIndexProviderManager.startup(); - + fTraceIndexerSetup= String.valueOf(true).equals(Platform.getDebugOption(TRACE_INDEXER_SETUP)); final CoreModel model = CoreModel.getDefault(); ResourcesPlugin.getWorkspace().addResourceChangeListener(fCModelListener, IResourceChangeEvent.POST_BUILD); @@ -270,7 +270,7 @@ public class PDOMManager implements IWritableIndexManager, IListener { fTaskQueue.clear(); jobToCancel= fIndexerJob; } - + if (jobToCancel != null) { assert !Thread.holdsLock(fTaskQueue); jobToCancel.cancelJobs(null, false); @@ -292,7 +292,7 @@ public class PDOMManager implements IWritableIndexManager, IListener { reindexAll(); } } - + protected void adjustCacheSize() { IPreferencesService prefs = Platform.getPreferencesService(); int cachePct= prefs.getInt(CCorePlugin.PLUGIN_ID, CCorePreferenceConstants.INDEX_DB_CACHE_SIZE_PCT, 10, null); @@ -315,7 +315,7 @@ public class PDOMManager implements IWritableIndexManager, IListener { } /** - * Returns the pdom for the project. + * Returns the pdom for the project. * @throws CoreException */ public IPDOM getPDOM(ICProject project) throws CoreException { @@ -329,9 +329,9 @@ public class PDOMManager implements IWritableIndexManager, IListener { return pdom; } } - + /** - * Returns the pdom for the project. The call to the method may cause + * Returns the pdom for the project. The call to the method may cause * opening the database. In case there is a version mismatch the data * base is cleared, in case it does not exist it is created. In any * case a pdom ready to use is returned. @@ -392,7 +392,7 @@ public class PDOMManager implements IWritableIndexManager, IListener { } pdom.setASTFilePathResolver(new ProjectIndexerInputAdapter(project, false)); pdom.addListener(this); - + fFileToProject.put(dbFile, project); fProjectToPDOM.put(rproject, pdom); if (pdomProxy instanceof PDOMProxy) { @@ -440,7 +440,7 @@ public class PDOMManager implements IWritableIndexManager, IListener { public void setDefaultIndexerId(String indexerId) { IndexerPreferences.setDefaultIndexerId(indexerId); } - + @Override public String getIndexerId(ICProject project) { IProject prj= project != null ? project.getProject() : null; @@ -453,7 +453,7 @@ public class PDOMManager implements IWritableIndexManager, IListener { IndexerPreferences.set(prj, IndexerPreferences.KEY_INDEXER_ID, indexerId); CCoreInternals.savePreferences(prj, IndexerPreferences.getScope(prj) == IndexerPreferences.SCOPE_PROJECT_SHARED); } - + protected void onPreferenceChange(ICProject cproject, PreferenceChangeEvent event) { if (IndexerPreferences.KEY_UPDATE_POLICY.equals(event.getKey())) { changeUpdatePolicy(cproject); @@ -484,17 +484,17 @@ public class PDOMManager implements IWritableIndexManager, IListener { private void changeIndexer(ICProject cproject) throws CoreException { assert !Thread.holdsLock(fProjectToPDOM); - + // if there is no indexer, don't touch the preferences. IPDOMIndexer oldIndexer= getIndexer(cproject); if (oldIndexer == null) { return; } - + IProject prj= cproject.getProject(); String newid= IndexerPreferences.get(prj, IndexerPreferences.KEY_INDEXER_ID, IPDOMManager.ID_NO_INDEXER); Properties props= IndexerPreferences.getProperties(prj); - + synchronized (fUpdatePolicies) { if (fClosingProjects.contains(prj.getName())) { return; @@ -519,7 +519,7 @@ public class PDOMManager implements IWritableIndexManager, IListener { enqueue(new PDOMRebuildTask(indexer)); } } - + if (oldIndexer != null) { stopIndexer(oldIndexer); } @@ -546,24 +546,24 @@ public class PDOMManager implements IWritableIndexManager, IListener { void createIndexer(ICProject project, IProgressMonitor pm) throws InterruptedException { final IProject prj= project.getProject(); final String name = prj.getName(); - if (fTraceIndexerSetup) + if (fTraceIndexerSetup) System.out.println("Indexer: Creation for project " + name); //$NON-NLS-1$ - + assert !Thread.holdsLock(fProjectToPDOM); try { synchronized (fUpdatePolicies) { if (fClosingProjects.contains(name)) { - if (fTraceIndexerSetup) + if (fTraceIndexerSetup) System.out.println("Indexer: Aborting setup (1) for closing project " + name + " [1]"); //$NON-NLS-1$ //$NON-NLS-2$ return; } - + WritablePDOM pdom= getOrCreatePDOM(project); Properties props= IndexerPreferences.getProperties(prj); IPDOMIndexer indexer= newIndexer(getIndexerId(project), props); IndexUpdatePolicy policy= createPolicy(project); - boolean rebuild= + boolean rebuild= pdom.isClearedBecauseOfVersionMismatch() || pdom.isCreatedFromScratch() || policy.isInitialRebuildRequested(); @@ -591,7 +591,7 @@ public class PDOMManager implements IWritableIndexManager, IListener { pdom.releaseReadLock(); } if (resume) { - if (fTraceIndexerSetup) + if (fTraceIndexerSetup) System.out.println("Indexer: Resuming for project " + name); //$NON-NLS-1$ enqueue(new PDOMUpdateTask(indexer, @@ -608,7 +608,7 @@ public class PDOMManager implements IWritableIndexManager, IListener { synchronized (fUpdatePolicies) { if (fClosingProjects.contains(name)) { - if (fTraceIndexerSetup) + if (fTraceIndexerSetup) System.out.println("Indexer: Aborting setup for closing project " + name + " [2]"); //$NON-NLS-1$ //$NON-NLS-2$ return; } @@ -623,13 +623,13 @@ public class PDOMManager implements IWritableIndexManager, IListener { if (policy.isAutomatic() || policy.isInitialRebuildRequested()) { policy.clearInitialFlags(); if (operation.wasSuccessful()) { - if (fTraceIndexerSetup) - System.out.println("Indexer: Imported shared index for project " + name); //$NON-NLS-1$ + if (fTraceIndexerSetup) + System.out.println("Indexer: Imported shared index for project " + name); //$NON-NLS-1$ task= new PDOMUpdateTask(indexer, IIndexManager.UPDATE_CHECK_TIMESTAMPS | IIndexManager.UPDATE_CHECK_CONTENTS_HASH); } else { - if (fTraceIndexerSetup) - System.out.println("Indexer: Rebuiding for project " + name); //$NON-NLS-1$ + if (fTraceIndexerSetup) + System.out.println("Indexer: Rebuiding for project " + name); //$NON-NLS-1$ task= new PDOMRebuildTask(indexer); } enqueue(task); @@ -642,7 +642,7 @@ public class PDOMManager implements IWritableIndexManager, IListener { } } } - + private IPDOMIndexer newIndexer(String indexerId, Properties props) throws CoreException { IPDOMIndexer indexer = null; // Look up in extension point @@ -656,14 +656,14 @@ public class PDOMManager implements IWritableIndexManager, IListener { indexer.setProperties(props); } catch (CoreException e) { CCorePlugin.log(e); - } + } break; } } } // Unknown index, default to the null one - if (indexer == null) + if (indexer == null) indexer = new PDOMNullIndexer(); return indexer; @@ -683,7 +683,7 @@ public class PDOMManager implements IWritableIndexManager, IListener { fIndexerJob.schedule(); } } - + IPDOMIndexerTask getNextTask() { IPDOMIndexerTask result= null; synchronized (fTaskQueue) { @@ -703,7 +703,7 @@ public class PDOMManager implements IWritableIndexManager, IListener { } return result; } - + void cancelledIndexerJob(boolean byManager) { synchronized (fTaskQueue) { fCurrentTask= null; @@ -715,7 +715,7 @@ public class PDOMManager implements IWritableIndexManager, IListener { } } } - + @Override public boolean isIndexerIdle() { return Job.getJobManager().find(this).length == 0; @@ -725,19 +725,19 @@ public class PDOMManager implements IWritableIndexManager, IListener { final String name = cproject.getProject().getName(); if (fTraceIndexerSetup) { System.out.println("Indexer: Adding new project " + name); //$NON-NLS-1$ - } - + } + synchronized (fUpdatePolicies) { fClosingProjects.remove(name); } - + setupProject(cproject); } void setupProject(final ICProject cproject) { if (fInShutDown) return; - + synchronized (fProjectQueue) { fProjectQueue.add(cproject); } @@ -776,7 +776,7 @@ public class PDOMManager implements IWritableIndexManager, IListener { if (indexer != null && indexer.getID().equals(IPDOMManager.ID_NO_INDEXER)) { return; } - + if (added.length > 0 || changed.length > 0 || removed.length > 0) { synchronized (fUpdatePolicies) { IndexUpdatePolicy policy= createPolicy(project); @@ -807,7 +807,7 @@ public class PDOMManager implements IWritableIndexManager, IListener { } public void preDeleteProject(ICProject cproject) { - preRemoveProject(cproject, true); + preRemoveProject(cproject, true); } public void preCloseProject(ICProject cproject) { @@ -820,8 +820,8 @@ public class PDOMManager implements IWritableIndexManager, IListener { final IProject rproject= cproject.getProject(); final String name = rproject.getName(); - if (fTraceIndexerSetup) - System.out.println("Indexer: Removing project " + name + "; delete=" + delete); //$NON-NLS-1$ //$NON-NLS-2$ + if (fTraceIndexerSetup) + System.out.println("Indexer: Removing project " + name + "; delete=" + delete); //$NON-NLS-1$ //$NON-NLS-2$ IPDOMIndexer indexer; synchronized (fUpdatePolicies) { @@ -868,12 +868,12 @@ public class PDOMManager implements IWritableIndexManager, IListener { job.setSystem(true); job.schedule(); } - + synchronized (fUpdatePolicies) { fUpdatePolicies.remove(cproject); } } - + void removeProject(ICProject cproject, ICElementDelta delta) { synchronized (fProjectToPDOM) { IProject rproject= cproject.getProject(); @@ -893,7 +893,7 @@ public class PDOMManager implements IWritableIndexManager, IListener { policy.clearTUs(); policy.setIndexer(null); } - } + } } cancelIndexerJobs(indexer); } @@ -909,13 +909,13 @@ public class PDOMManager implements IWritableIndexManager, IListener { } jobToCancel= fIndexerJob; } - + if (jobToCancel != null) { assert !Thread.holdsLock(fTaskQueue); jobToCancel.cancelJobs(indexer, true); } - } - + } + private void reindexAll() { ICProject[] cProjects; try { @@ -930,7 +930,7 @@ public class PDOMManager implements IWritableIndexManager, IListener { @Override public void reindex(final ICProject project) { - Job job= new Job(Messages.PDOMManager_notifyJob_label) { + Job job= new Job(Messages.PDOMManager_notifyJob_label) { @Override protected IStatus run(IProgressMonitor monitor) { IPDOMIndexer indexer= null; @@ -971,7 +971,7 @@ public class PDOMManager implements IWritableIndexManager, IListener { public void removeIndexChangeListener(IIndexChangeListener listener) { fChangeListeners.remove(listener); } - + @Override public void addIndexerStateListener(IIndexerStateListener listener) { fStateListeners.add(listener); @@ -1001,7 +1001,7 @@ public class PDOMManager implements IWritableIndexManager, IListener { notify.setSystem(true); return notify; } - + private void scheduleNotification(Runnable notify) { if (fInShutDown) return; @@ -1052,12 +1052,12 @@ public class PDOMManager implements IWritableIndexManager, IListener { if (fChangeListeners.isEmpty()) { return; } - + ICProject project; synchronized (fProjectToPDOM) { project = fFileToProject.get(pdom.getPath()); - } - + } + if (project != null) { final ICProject finalProject= project; Runnable notify= new Runnable() { @@ -1088,6 +1088,10 @@ public class PDOMManager implements IWritableIndexManager, IListener { @Override public boolean joinIndexer(final int waitMaxMillis, final IProgressMonitor monitor) { assert monitor != null; + long startMillis = System.currentTimeMillis(); + + // Unfortunately, IJobManager.join() doesn't take a timeout. So, we create a watchdog thread to + // interrupt the call if the indexer job doesn't complete in the alloted time Thread th= null; if (waitMaxMillis != FOREVER) { final Thread callingThread= Thread.currentThread(); @@ -1112,17 +1116,30 @@ public class PDOMManager implements IWritableIndexManager, IListener { } catch (OperationCanceledException e) { } catch (InterruptedException e) { } - return Job.getJobManager().find(this).length == 0; + + // When the indexer job is interrupted, the join() above will throw an exception and that can + // happen slightly before the JobManager updates its job collection. Wait for it. + while (Job.getJobManager().find(this).length != 0) { + if (System.currentTimeMillis() - startMillis > waitMaxMillis) { + return false; + } + try { + Thread.sleep(50); + } catch (InterruptedException e) { + } + } + return true; } finally { + // Make sure we don't leave the watchdog thread running if (th != null) { th.interrupt(); } } } - + int getMonitorMessage(PDOMIndexerJob job, int currentTicks, int base) { assert !Thread.holdsLock(fTaskQueue); - + int sourceCount, sourceEstimate, headerCount, tickCount, tickEstimate; String detail= null; synchronized (fTaskQueue) { @@ -1149,14 +1166,14 @@ public class PDOMManager implements IWritableIndexManager, IListener { detail= PDOMIndexerJob.sMonitorDetail; } } - - String msg= MessageFormat.format(Messages.PDOMManager_indexMonitorDetail, new Object[] { - new Integer(sourceCount), new Integer(sourceEstimate), - new Integer(headerCount)}); + + String msg= MessageFormat.format(Messages.PDOMManager_indexMonitorDetail, new Object[] { + new Integer(sourceCount), new Integer(sourceEstimate), + new Integer(headerCount)}); if (detail != null) { msg += ": " + detail; //$NON-NLS-1$ } - + job.subTask(msg); if (tickCount > 0 && tickCount <= tickEstimate) { int newTick= tickCount*base/tickEstimate; @@ -1192,7 +1209,7 @@ public class PDOMManager implements IWritableIndexManager, IListener { public IIndex getIndex(ICProject[] projects, int options) throws CoreException { return fIndexFactory.getIndex(projects, options); } - + /** * Exports the project PDOM to the specified location, rewriting locations with * the specified location converter. @@ -1228,7 +1245,7 @@ public class PDOMManager implements IWritableIndexManager, IListener { } // Overwrite internal location representations. - final WritablePDOM newPDOM = new WritablePDOM(targetLocation, pdom.getLocationConverter(), getLinkageFactories()); + final WritablePDOM newPDOM = new WritablePDOM(targetLocation, pdom.getLocationConverter(), getLinkageFactories()); newPDOM.acquireWriteLock(); try { newPDOM.rewriteLocations(newConverter); @@ -1248,7 +1265,7 @@ public class PDOMManager implements IWritableIndexManager, IListener { } /** - * Resets the pdom for the project with the provided stream. + * Resets the pdom for the project with the provided stream. * @throws CoreException * @throws OperationCanceledException in case the thread was interrupted * @since 4.0 @@ -1267,11 +1284,11 @@ public class PDOMManager implements IWritableIndexManager, IListener { } if (version > PDOM.getMaxSupportedVersion()) { final IStatus status = new Status(IStatus.WARNING, CCorePlugin.PLUGIN_ID, 0, CCorePlugin.getResourceString("PDOMManager.unsupportedHigherVersion"), null); //$NON-NLS-1$ - throw new CoreException(status); + throw new CoreException(status); } if ( !PDOM.isSupportedVersion( version ) ) { final IStatus status = new Status(IStatus.WARNING, CCorePlugin.PLUGIN_ID, 0, CCorePlugin.getResourceString("PDOMManager.unsupportedVersion"), null); //$NON-NLS-1$ - throw new CoreException(status); + throw new CoreException(status); } byte[] buffer= new byte[2048]; int read; @@ -1281,7 +1298,7 @@ public class PDOMManager implements IWritableIndexManager, IListener { } finally { out.close(); } - + WritablePDOM pdom= (WritablePDOM) getPDOM(project); try { pdom.acquireWriteLock(); @@ -1296,7 +1313,7 @@ public class PDOMManager implements IWritableIndexManager, IListener { pdom.releaseWriteLock(); } } - + @Override public void export(ICProject project, String location, int options, IProgressMonitor monitor) throws CoreException { TeamPDOMExportOperation operation= new TeamPDOMExportOperation(project); @@ -1304,7 +1321,7 @@ public class PDOMManager implements IWritableIndexManager, IListener { operation.setOptions(options); operation.run(monitor); } - + /** * Write metadata appropriate for a project pdom * @param pdom the pdom to write to @@ -1335,7 +1352,7 @@ public class PDOMManager implements IWritableIndexManager, IListener { for (Map.Entry> entry : projectsToElements.entrySet()) { ICProject project = entry.getKey(); List filesAndFolders = entry.getValue(); - + update(project, filesAndFolders, options); } } @@ -1362,14 +1379,14 @@ public class PDOMManager implements IWritableIndexManager, IListener { } else if (contains(element, other)) { set.set(j, element); continue allElements; - } + } } set.add(element); } } return result; } - + private boolean contains(final ICElement a, ICElement b) { if (a.equals(b)) { return true; @@ -1467,7 +1484,7 @@ public class PDOMManager implements IWritableIndexManager, IListener { if (fPostponedProjects.contains(project)) { setupProject(project); } - } + } } @Override @@ -1486,7 +1503,7 @@ public class PDOMManager implements IWritableIndexManager, IListener { } } } - + /** * @param project * @return whether the specified project has been registered. If a project has @@ -1496,7 +1513,7 @@ public class PDOMManager implements IWritableIndexManager, IListener { public boolean isProjectRegistered(ICProject project) { return getIndexer(project) != null; } - + /** * @param cproject the project to check * @return whether the content in the project fragment of the specified project's index @@ -1506,7 +1523,7 @@ public class PDOMManager implements IWritableIndexManager, IListener { public boolean isProjectContentSynced(ICProject cproject) throws CoreException { if (!"true".equals(IndexerPreferences.get(cproject.getProject(), IndexerPreferences.KEY_INDEX_ALL_FILES, null))) //$NON-NLS-1$ return true; // no check performed in this case - + Set sources= new HashSet(); cproject.accept(new TranslationUnitCollector(sources, null, new NullProgressMonitor())); @@ -1532,7 +1549,7 @@ public class PDOMManager implements IWritableIndexManager, IListener { return true; } - + private boolean isSubjectToIndexing(ILanguage language) { final int linkageID=language.getLinkageID(); for (int id : IDS_FOR_LINKAGES_TO_INDEX) { @@ -1554,7 +1571,7 @@ public class PDOMManager implements IWritableIndexManager, IListener { private static boolean areSynchronized(Set trail, IIndex index, IResource resource, IIndexFileLocation location) throws CoreException { if (!trail.contains(location)) { trail.add(location); - + IIndexFile[] file= index.getFiles(location); // pre-includes may be listed twice (191989) @@ -1580,7 +1597,7 @@ public class PDOMManager implements IWritableIndexManager, IListener { } } } - + return true; }