summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Oberhuber2013-01-14 15:04:29 (EST)
committerSergey Prigogin2013-01-14 15:09:49 (EST)
commit446545ab16adc8a01ca6d9915e79cd05d944431f (patch)
tree0c17970149a258c47bc134534648200cf96a08d7
parent0c5bb6307e58e0cc42ecb3797f99c99ec7d065d2 (diff)
downloadorg.eclipse.cdt-446545ab16adc8a01ca6d9915e79cd05d944431f.zip
org.eclipse.cdt-446545ab16adc8a01ca6d9915e79cd05d944431f.tar.gz
org.eclipse.cdt-446545ab16adc8a01ca6d9915e79cd05d944431f.tar.bz2
Bug 397652 - Exporting a PDOM fails due to wrong index-in-sync check
Fixes an incorrect workaround from bug 229989 comment 6: It is perfectly valid for one location to map to multiple index files. Also adds better error reporting for out-of-sync files, and adds API to allow exporting a PDOM without any index-in-sync check. Change-Id: I63a7d36a2de465f9994cc9b9698688e3ad6850ee
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMManager.java93
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/export/GeneratePDOM.java106
2 files changed, 125 insertions, 74 deletions
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 0728d56..b111d0e 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
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2005, 2012 QNX Software Systems and others.
+ * Copyright (c) 2005, 2013 QNX Software Systems 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
@@ -13,6 +13,7 @@
* Tim Kelly (Nokia)
* Anna Dushistova (MontaVista)
* Marc-Andre Laperle
+ * Martin Oberhuber (Wind River) - [397652] fix up-to-date check for PDOM
*******************************************************************************/
package org.eclipse.cdt.internal.core.pdom;
@@ -23,6 +24,7 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayDeque;
import java.util.ArrayList;
+import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@@ -93,6 +95,7 @@ import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.ISafeRunnable;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.ListenerList;
+import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Path;
@@ -109,6 +112,7 @@ import org.eclipse.core.runtime.preferences.IPreferencesService;
import org.eclipse.core.runtime.preferences.InstanceScope;
import com.ibm.icu.text.MessageFormat;
+import com.ibm.icu.text.SimpleDateFormat;
/**
* Manages PDOM updates and events associated with them. Provides methods for index access.
@@ -1529,11 +1533,25 @@ public class PDOMManager implements IWritableIndexManager, IListener {
* @throws CoreException
*/
public boolean isProjectContentSynced(ICProject cproject) throws CoreException {
+ IStatus s = getProjectContentSyncState(cproject);
+ return s == null;
+ }
+
+ /**
+ * Checks whether the index is in sync with the file system.
+ * @param cproject the project to check
+ * @return <code>null</code> when the content in the project fragment of the specified project's index
+ * is complete (contains all sources) and up to date; or an @link{IStatus} indicating the first
+ * occurrence of an index file found not up-to-date, along with its include trail.
+ * @throws CoreException in case of a file access or other internal error
+ */
+ public IStatus getProjectContentSyncState(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
+ return null; // No check is performed in this case
Set<ITranslationUnit> sources= new HashSet<ITranslationUnit>();
cproject.accept(new TranslationUnitCollector(sources, null, new NullProgressMonitor()));
+ IStatus syncStatus = null;
try {
IIndex index= getIndex(cproject);
@@ -1543,8 +1561,9 @@ public class PDOMManager implements IWritableIndexManager, IListener {
IResource resource= tu.getResource();
if (resource instanceof IFile && isSubjectToIndexing(tu.getLanguage())) {
IIndexFileLocation location= IndexLocationFactory.getWorkspaceIFL((IFile) resource);
- if (!areSynchronized(new HashSet<IIndexFileLocation>(), index, resource, location)) {
- return false;
+ syncStatus = areSynchronized(new HashSet<IIndexFileLocation>(), index, resource, location);
+ if (syncStatus != null) {
+ return syncStatus;
}
}
}
@@ -1555,11 +1574,11 @@ public class PDOMManager implements IWritableIndexManager, IListener {
CCorePlugin.log(e);
}
- return true;
+ return null;
}
private boolean isSubjectToIndexing(ILanguage language) {
- final int linkageID=language.getLinkageID();
+ final int linkageID = language.getLinkageID();
for (int id : IDS_FOR_LINKAGES_TO_INDEX) {
if (linkageID == id)
return true;
@@ -1568,45 +1587,57 @@ public class PDOMManager implements IWritableIndexManager, IListener {
}
/**
- * Recursively checks that the specified file, and its include are up-to-date.
+ * Recursively checks that the specified file, and its includes are up-to-date.
* @param trail a set of previously checked include file locations
* @param index the index to check against
* @param resource the resource to check from the workspace
* @param location the location to check from the index
- * @return whether the specified file, and its includes are up-to-date.
+ * @return <code>null</code> when whether the specified file, and its includes are up-to-date,
+ * or a MultiStatus indicating the file found to be not in sync along with it include trail.
* @throws CoreException
*/
- private static boolean areSynchronized(Set<IIndexFileLocation> trail, IIndex index, IResource resource, IIndexFileLocation location) throws CoreException {
+ private static MultiStatus areSynchronized(Set<IIndexFileLocation> 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)
- if (file.length < 1 || file.length > 2)
- return false;
-
- if (resource.getLocalTimeStamp() != file[0].getTimestamp())
- return false;
-
- // if it is up-to-date, the includes have not changed and may
- // be read from the index.
- IIndexInclude[] includes= index.findIncludes(file[0]);
- for (IIndexInclude inc : includes) {
- IIndexFileLocation newLocation= inc.getIncludesLocation();
- if (newLocation != null) {
- String path= newLocation.getFullPath();
- if (path != null) {
- IResource newResource= ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(path));
- if (!areSynchronized(trail, index, newResource, newLocation)) {
- return false;
+ IIndexFile[] files= index.getFiles(location);
+
+ if (files.length <= 0)
+ return new MultiStatus(CCorePlugin.PLUGIN_ID, IStatus.OK, "No index file found for: " + location, null); //$NON-NLS-1$
+
+ for (IIndexFile file : files) {
+ long diff = resource.getLocalTimeStamp() - file.getTimestamp();
+ if (diff != 0) {
+ return new MultiStatus(CCorePlugin.PLUGIN_ID, IStatus.OK,
+ "Index timestamp for '" //$NON-NLS-1$
+ + file.getLocation().getFullPath()
+ + "' is " + diff + " msec older than " //$NON-NLS-1$ //$NON-NLS-2$
+ + location
+ + "(" + SimpleDateFormat.getDateTimeInstance().format(new Date(resource.getLocalTimeStamp())) //$NON-NLS-1$
+ + ")", null); //$NON-NLS-1$
+ }
+
+ // If it is up-to-date, the includes have not changed and may be read from the index.
+ IIndexInclude[] includes= index.findIncludes(file);
+ for (IIndexInclude inc : includes) {
+ IIndexFileLocation newLocation= inc.getIncludesLocation();
+ if (newLocation != null) {
+ String path= newLocation.getFullPath();
+ if (path != null) {
+ IResource newResource= ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(path));
+ MultiStatus m = areSynchronized(trail, index, newResource, newLocation);
+ if (m != null) {
+ m.add(new Status(IStatus.INFO, CCorePlugin.PLUGIN_ID,
+ "Included by " + file.getLocation().getFullPath())); //$NON-NLS-1$
+ return m;
+ }
}
}
}
}
}
-
- return true;
+ return null;
}
public boolean isFileIndexedUnconditionally(IIndexFileLocation ifl) {
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/export/GeneratePDOM.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/export/GeneratePDOM.java
index fbd6182..6312b59 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/export/GeneratePDOM.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/export/GeneratePDOM.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2009 Symbian Software Systems and others.
+ * Copyright (c) 2007, 2013 Symbian Software Systems 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
@@ -8,11 +8,11 @@
* Contributors:
* Andrew Ferguson (Symbian) - Initial implementation
* Markus Schorn (Wind River Systems)
+ * Martin Oberhuber (Wind River) - [397652] fix up-to-date check for PDOM
*******************************************************************************/
package org.eclipse.cdt.internal.core.pdom.export;
import java.io.File;
-import com.ibm.icu.text.MessageFormat;
import java.util.Map;
import org.eclipse.cdt.core.CCorePlugin;
@@ -26,9 +26,12 @@ import org.eclipse.cdt.internal.core.pdom.WritablePDOM;
import org.eclipse.cdt.internal.core.pdom.indexer.IndexerPreferences;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
+import com.ibm.icu.text.MessageFormat;
+
/**
* An ISafeRunnable which
* <ul>
@@ -43,14 +46,28 @@ public class GeneratePDOM {
protected File targetLocation;
protected String indexerID;
protected boolean deleteOnExit;
-
- public GeneratePDOM(IExportProjectProvider pm, String[] applicationArguments, File targetLocation, String indexerID) {
+ protected boolean checkIndexStatus;
+
+ /**
+ * Runnable to export a PDOM.
+ * @param checkIndexStatus <code>true</code> to check index completeness before exporting, or
+ * <code>false</code> to export the index without checking anything
+ * @since 5.5
+ */
+ public GeneratePDOM(IExportProjectProvider pm, String[] applicationArguments, File targetLocation,
+ String indexerID, boolean checkIndexStatus) {
this.pm= pm;
this.applicationArguments= applicationArguments;
this.targetLocation= targetLocation;
this.indexerID= indexerID;
+ this.checkIndexStatus= checkIndexStatus;
}
-
+
+ public GeneratePDOM(IExportProjectProvider pm, String[] applicationArguments, File targetLocation,
+ String indexerID) {
+ this(pm, applicationArguments, targetLocation, indexerID, true);
+ }
+
/**
* When set, the project created by the associated {@link IExportProjectProvider} will
* be deleted after {@link #run()} completes. By default this is not set.
@@ -66,74 +83,77 @@ public class GeneratePDOM {
* @throws CoreException if an internal or invalid configuration error occurs
*/
public final IStatus run() throws CoreException {
- boolean isContentSynced= false;
-
- // create the project
+ // Create the project
pm.setApplicationArguments(applicationArguments);
final ICProject cproject = pm.createProject();
- if(cproject==null) {
+ if (cproject == null) {
fail(MessageFormat.format(Messages.GeneratePDOM_ProjectProviderReturnedNullCProject,
- new Object [] {pm.getClass().getName()}));
- return null; // cannot be reached, inform the compiler
+ new Object[] { pm.getClass().getName() }));
+ return null; // Cannot be reached, inform the compiler
}
IIndexLocationConverter converter= pm.getLocationConverter(cproject);
- if(converter==null) {
+ if (converter == null) {
fail(MessageFormat.format(Messages.GeneratePDOM_NullLocationConverter,
- new Object [] {pm.getClass().getName()}));
+ new Object[] { pm.getClass().getName() }));
}
- // index the project
+ // Index the project
IndexerPreferences.set(cproject.getProject(), IndexerPreferences.KEY_INDEXER_ID, indexerID);
try {
- final IIndexManager im = CCorePlugin.getIndexManager();
+ final IIndexManager manager = CCorePlugin.getIndexManager();
for (int i = 0; i < 20; i++) {
- if(CCoreInternals.getPDOMManager().isProjectRegistered(cproject)) {
- im.joinIndexer(Integer.MAX_VALUE, new NullProgressMonitor());
- if (!im.isIndexerSetupPostponed(cproject)) {
+ if (CCoreInternals.getPDOMManager().isProjectRegistered(cproject)) {
+ manager.joinIndexer(Integer.MAX_VALUE, new NullProgressMonitor());
+ if (!manager.isIndexerSetupPostponed(cproject)) {
break;
}
}
Thread.sleep(200);
}
- // check status
- isContentSynced= CCoreInternals.getPDOMManager().isProjectContentSynced(cproject);
-
- if(isContentSynced) {
- // export a .pdom file
- CCoreInternals.getPDOMManager().exportProjectPDOM(cproject, targetLocation, converter);
+ if (checkIndexStatus) {
+ // Check status
+ IStatus syncStatus = CCoreInternals.getPDOMManager().getProjectContentSyncState(cproject);
+ if (syncStatus != null) {
+ // Add message and error severity
+ IStatus myStatus = new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, Messages.GeneratePDOM_Incomplete);
+ MultiStatus m = new MultiStatus(CCorePlugin.PLUGIN_ID, 1, new IStatus[] {myStatus, syncStatus},
+ Messages.GeneratePDOM_Incomplete, null);
+ // Log the status right away since legacy clients did not return any status details
+ CCorePlugin.log(m);
+ return m;
+ }
+ }
+ // Export a .pdom file
+ CCoreInternals.getPDOMManager().exportProjectPDOM(cproject, targetLocation, converter);
- // write properties to exported PDOM
- WritablePDOM exportedPDOM= new WritablePDOM(targetLocation, converter, LanguageManager.getInstance().getPDOMLinkageFactoryMappings());
- exportedPDOM.acquireWriteLock(0);
- try {
- Map<String,String> exportProperties= pm.getExportProperties();
- if(exportProperties!=null) {
- for(Map.Entry<String,String> entry : exportProperties.entrySet()) {
- exportedPDOM.setProperty(entry.getKey(), entry.getValue());
- }
+ // Write properties to exported PDOM
+ WritablePDOM exportedPDOM= new WritablePDOM(targetLocation, converter,
+ LanguageManager.getInstance().getPDOMLinkageFactoryMappings());
+ exportedPDOM.acquireWriteLock(0);
+ try {
+ Map<String, String> exportProperties= pm.getExportProperties();
+ if (exportProperties != null) {
+ for(Map.Entry<String, String> entry : exportProperties.entrySet()) {
+ exportedPDOM.setProperty(entry.getKey(), entry.getValue());
}
- exportedPDOM.close();
- }
- finally {
- exportedPDOM.releaseWriteLock();
}
+ exportedPDOM.close();
+ } finally {
+ exportedPDOM.releaseWriteLock();
}
-
- } catch(InterruptedException ie) {
+ } catch (InterruptedException ie) {
String msg= MessageFormat.format(Messages.GeneratePDOM_GenericGenerationFailed, new Object[] {ie.getMessage()});
throw new CoreException(CCorePlugin.createStatus(msg, ie));
} finally {
- if(deleteOnExit) {
+ if (deleteOnExit) {
cproject.getProject().delete(true, new NullProgressMonitor());
}
}
- return isContentSynced ?
- new Status(IStatus.OK, CCorePlugin.PLUGIN_ID, Messages.GeneratePDOM_Success)
- : new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, Messages.GeneratePDOM_Incomplete);
+ return new Status(IStatus.OK, CCorePlugin.PLUGIN_ID, Messages.GeneratePDOM_Success);
}
private void fail(String message) throws CoreException {