From 2e0d07d89bf416d3b39c7b292e2d92d46bc66e47 Mon Sep 17 00:00:00 2001 From: Markus Schorn Date: Thu, 14 Feb 2008 08:39:37 +0000 Subject: [PATCH] Participants for indexer-setup, bug 218286. --- .../eclipse/cdt/core/index/IIndexManager.java | 13 +- .../core/index/IndexerSetupParticipant.java | 43 +++++++ .../pdom/CProjectDescriptionListener.java | 23 +++- .../cdt/internal/core/pdom/PDOMManager.java | 118 +++++++++++++----- 4 files changed, 163 insertions(+), 34 deletions(-) create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IndexerSetupParticipant.java diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndexManager.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndexManager.java index 3e2531e8d3e..6cce732b04c 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndexManager.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndexManager.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2007 Wind River Systems, Inc. and others. + * Copyright (c) 2006, 2008 Wind River Systems, Inc. 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 @@ -11,6 +11,7 @@ package org.eclipse.cdt.core.index; +import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.dom.IPDOMManager; import org.eclipse.cdt.core.model.ICElement; import org.eclipse.cdt.core.model.ICProject; @@ -196,4 +197,14 @@ public interface IIndexManager extends IPDOMManager { * @since 4.0 */ public void export(ICProject project, String location, int options, IProgressMonitor monitor) throws CoreException; + + /** + * Adds a participant for the indexer-setup + */ + public void addIndexerSetupParticipant(IndexerSetupParticipant participant); + + /** + * Removes a participant for the indexer-setup + */ + public void removeIndexerSetupParticipant(IndexerSetupParticipant participant); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IndexerSetupParticipant.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IndexerSetupParticipant.java new file mode 100644 index 00000000000..4979d85d225 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IndexerSetupParticipant.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2008 Wind River Systems, Inc. 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.core.index; + +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.internal.core.CCoreInternals; + +/** + * Abstract base class for indexer setup participants. A participant can delay the + * setup of the indexer when a project is added to the workspace. + */ +public abstract class IndexerSetupParticipant { + + /** + * The method will be called before an indexer is set up for a project. If you + * return true the setup will be postponed. You need to call + * {@link #notifyIndexerSetup(ICProject)} as soon as this participant no longer + * needs to block the indexer setup. + *

+ * This method may be called multiple times for the same project. + * @param project the project for which the indexer is supposed to be initialized. + * @return whether or not to proceed with the indexer setup. + */ + public abstract boolean postponeIndexerSetup(ICProject project); + + /** + * Informs the index manager that this participant no longer needs to postpone the + * indexer setup for the given project. Depending on the state of other participants + * this may trigger the indexer setup. + * @param project the project for which the setup no longer needs to be postponed + */ + public void notifyIndexerSetup(ICProject project) { + CCoreInternals.getPDOMManager().notifyIndexerSetup(this, project); + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/CProjectDescriptionListener.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/CProjectDescriptionListener.java index 70163de9ee7..d3894ef7e58 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/CProjectDescriptionListener.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/CProjectDescriptionListener.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2008 Wind River Systems, Inc. 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 @@ -11,20 +11,34 @@ package org.eclipse.cdt.internal.core.pdom; +import org.eclipse.cdt.core.index.IndexerSetupParticipant; import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.cdt.core.model.ICProject; import org.eclipse.cdt.core.settings.model.CProjectDescriptionEvent; import org.eclipse.cdt.core.settings.model.ICConfigurationDescription; import org.eclipse.cdt.core.settings.model.ICProjectDescription; import org.eclipse.cdt.core.settings.model.ICProjectDescriptionListener; +import org.eclipse.cdt.internal.core.settings.model.CProjectDescriptionManager; import org.eclipse.core.resources.IProject; public class CProjectDescriptionListener implements ICProjectDescriptionListener { private PDOMManager fIndexManager; + private IndexerSetupParticipant fIndexerSetupParticipant; public CProjectDescriptionListener(PDOMManager manager) { fIndexManager= manager; + fIndexerSetupParticipant= createIndexerSetupParticipant(); + manager.addIndexerSetupParticipant(fIndexerSetupParticipant); + } + + private IndexerSetupParticipant createIndexerSetupParticipant() { + return new IndexerSetupParticipant() { + @Override + public boolean postponeIndexerSetup(ICProject project) { + return !isProjectCreationComplete(project.getProject()); + } + }; } public void handleEvent(CProjectDescriptionEvent event) { @@ -34,7 +48,7 @@ public class CProjectDescriptionListener implements ICProjectDescriptionListener if (completedProjectCreation(old, act)) { ICProject project= getProject(event); if (project != null) { - fIndexManager.addProject(project); + fIndexerSetupParticipant.notifyIndexerSetup(project); } } else if (old != null && changedDefaultSettingConfiguration(old, act)) { @@ -69,6 +83,11 @@ public class CProjectDescriptionListener implements ICProjectDescriptionListener return null; } + protected boolean isProjectCreationComplete(IProject project) { + ICProjectDescription desc= CProjectDescriptionManager.getInstance().getProjectDescription(project.getProject(), false); + return !(desc == null || desc.isCdtProjectCreating()); + } + private boolean completedProjectCreation(ICProjectDescription old, ICProjectDescription act) { return (old == null || old.isCdtProjectCreating()) && !act.isCdtProjectCreating(); } 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 f845cc0a6ad..bfae97e6ede 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 @@ -40,6 +40,7 @@ import org.eclipse.cdt.core.index.IIndexChangeListener; import org.eclipse.cdt.core.index.IIndexLocationConverter; import org.eclipse.cdt.core.index.IIndexManager; import org.eclipse.cdt.core.index.IIndexerStateListener; +import org.eclipse.cdt.core.index.IndexerSetupParticipant; import org.eclipse.cdt.core.model.CModelException; import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.cdt.core.model.ICContainer; @@ -50,7 +51,6 @@ import org.eclipse.cdt.core.model.ILanguageMappingChangeListener; import org.eclipse.cdt.core.model.ITranslationUnit; import org.eclipse.cdt.core.model.LanguageManager; import org.eclipse.cdt.core.settings.model.CProjectDescriptionEvent; -import org.eclipse.cdt.core.settings.model.ICProjectDescription; import org.eclipse.cdt.core.settings.model.ICProjectDescriptionListener; import org.eclipse.cdt.internal.core.CCoreInternals; import org.eclipse.cdt.internal.core.index.IIndexFragment; @@ -70,7 +70,6 @@ import org.eclipse.cdt.internal.core.pdom.indexer.PDOMRebuildTask; import org.eclipse.cdt.internal.core.pdom.indexer.PDOMUpdateTask; import org.eclipse.cdt.internal.core.pdom.indexer.ProjectIndexerInputAdapter; import org.eclipse.cdt.internal.core.pdom.indexer.TriggerNotificationTask; -import org.eclipse.cdt.internal.core.settings.model.CProjectDescriptionManager; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; @@ -166,7 +165,7 @@ public class PDOMManager implements IWritableIndexManager, IListener { private CModelListener fCModelListener= new CModelListener(this); private ILanguageMappingChangeListener fLanguageChangeListener = new LanguageMappingChangeListener(this); - private ICProjectDescriptionListener fProjectDescriptionListener= new CProjectDescriptionListener(this); + private final ICProjectDescriptionListener fProjectDescriptionListener; private IndexFactory fIndexFactory= new IndexFactory(this); private IndexProviderManager fIndexProviderManager = new IndexProviderManager(); @@ -178,13 +177,21 @@ public class PDOMManager implements IWritableIndexManager, IListener { */ private HashMap fUpdatePolicies= new HashMap(); private HashMap fPrefListeners= new HashMap(); + private ArrayList fSetupParticipants= new ArrayList(); + private HashSet fPostponedProjects= new HashSet(); + public PDOMManager() { + fProjectDescriptionListener= new CProjectDescriptionListener(this); + } + public Job startup() { Job postStartupJob= new Job(CCorePlugin.getResourceString("CCorePlugin.startupJob")) { //$NON-NLS-1$ + @Override protected IStatus run(IProgressMonitor monitor) { postStartup(); return Status.OK_STATUS; } + @Override public boolean belongsTo(Object family) { return family == PDOMManager.this; } @@ -660,9 +667,10 @@ public class PDOMManager implements IWritableIndexManager, IListener { void addProject(final ICProject cproject) { final IProject project = cproject.getProject(); Job addProject= new Job(Messages.PDOMManager_StartJob_name) { + @Override protected IStatus run(IProgressMonitor monitor) { monitor.beginTask("", 100); //$NON-NLS-1$ - if (project.isOpen() && isFullyCreated(project)) { + if (project.isOpen() && !postponeSetup(cproject)) { syncronizeProjectSettings(project, new SubProgressMonitor(monitor, 1)); if (getIndexer(cproject) == null) { createIndexer(cproject, new SubProgressMonitor(monitor, 99)); @@ -681,6 +689,7 @@ public class PDOMManager implements IWritableIndexManager, IListener { monitor.done(); } + @Override public boolean belongsTo(Object family) { return family == PDOMManager.this; } @@ -703,14 +712,6 @@ public class PDOMManager implements IWritableIndexManager, IListener { addProject.schedule(); } - private boolean isFullyCreated(IProject project) { - ICProjectDescription desc= CProjectDescriptionManager.getInstance().getProjectDescription(project, false); - if (desc != null && !desc.isCdtProjectCreating()) { - return true; - } - return false; - } - private void registerPreferenceListener(ICProject project) { IProject prj= project.getProject(); PCL pcl= fPrefListeners.get(prj); @@ -797,7 +798,8 @@ public class PDOMManager implements IWritableIndexManager, IListener { if (pdom instanceof WritablePDOM) { final WritablePDOM finalpdom= (WritablePDOM) pdom; Job job= new Job(Messages.PDOMManager_ClosePDOMJob) { - protected IStatus run(IProgressMonitor monitor) { + @Override + protected IStatus run(IProgressMonitor monitor) { try { finalpdom.acquireWriteLock(); try { @@ -866,24 +868,35 @@ public class PDOMManager implements IWritableIndexManager, IListener { } } - public void reindex(ICProject project) { - assert !Thread.holdsLock(fProjectToPDOM); - IPDOMIndexer indexer= null; - synchronized (fUpdatePolicies) { - indexer= getIndexer(project); - } - // don't attempt to hold lock on indexerMutex while cancelling - if (indexer != null) { - cancelIndexerJobs(indexer); - } - - synchronized(fUpdatePolicies) { - indexer= getIndexer(project); - if (indexer != null) { - createPolicy(project).clearTUs(); - enqueue(new PDOMRebuildTask(indexer)); + public void reindex(final ICProject project) { + Job job= new Job(Messages.PDOMManager_notifyJob_label) { + @Override + protected IStatus run(IProgressMonitor monitor) { + IPDOMIndexer indexer= null; + synchronized (fUpdatePolicies) { + indexer= getIndexer(project); + } + // don't attempt to hold lock on indexerMutex while cancelling + if (indexer != null) { + cancelIndexerJobs(indexer); + } + + synchronized(fUpdatePolicies) { + indexer= getIndexer(project); + if (indexer != null) { + createPolicy(project).clearTUs(); + enqueue(new PDOMRebuildTask(indexer)); + } + } + return Status.OK_STATUS; } - } + @Override + public boolean belongsTo(Object family) { + return family == PDOMManager.this; + } + }; + job.setSystem(true); + job.schedule(); } public void addIndexChangeListener(IIndexChangeListener listener) { @@ -913,7 +926,8 @@ public class PDOMManager implements IWritableIndexManager, IListener { return; } Job notify= new Job(Messages.PDOMManager_notifyJob_label) { - protected IStatus run(IProgressMonitor monitor) { + @Override + protected IStatus run(IProgressMonitor monitor) { fIndexerStateEvent.setState(state); Object[] listeners= fStateListeners.getListeners(); monitor.beginTask(Messages.PDOMManager_notifyTask_message, listeners.length); @@ -950,6 +964,7 @@ public class PDOMManager implements IWritableIndexManager, IListener { if (project != null) { final ICProject finalProject= project; Job notify= new Job(Messages.PDOMManager_notifyJob_label) { + @Override protected IStatus run(IProgressMonitor monitor) { fIndexChangeEvent.setAffectedProject(finalProject); Object[] listeners= fChangeListeners.getListeners(); @@ -980,6 +995,7 @@ public class PDOMManager implements IWritableIndexManager, IListener { Thread th= null; if (waitMaxMillis != FOREVER) { th= new Thread() { + @Override public void run() { try { Thread.sleep(waitMaxMillis); @@ -1278,4 +1294,44 @@ public class PDOMManager implements IWritableIndexManager, IListener { } } } + + protected boolean postponeSetup(ICProject cproject) { + synchronized(fSetupParticipants) { + for (IndexerSetupParticipant sp : fSetupParticipants) { + if (sp.postponeIndexerSetup(cproject)) { + fPostponedProjects.add(cproject); + return true; + } + } + fPostponedProjects.remove(cproject); + return false; + } + } + + /** + * @param indexerSetupParticipant + * @param project + */ + public void notifyIndexerSetup(IndexerSetupParticipant participant, ICProject project) { + synchronized(fSetupParticipants) { + if (fPostponedProjects.contains(project)) { + addProject(project); + } + } + } + + public void addIndexerSetupParticipant(IndexerSetupParticipant participant) { + synchronized (fSetupParticipants) { + fSetupParticipants.add(participant); + } + } + + public void removeIndexerSetupParticipant(IndexerSetupParticipant participant) { + synchronized (fSetupParticipants) { + fSetupParticipants.remove(participant); + for (ICProject project : fPostponedProjects) { + addProject(project); + } + } + } }