mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-31 21:05:37 +02:00
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
This commit is contained in:
parent
9e6ee807a9
commit
111b6ba185
2 changed files with 124 additions and 73 deletions
|
@ -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);
|
||||
IIndexFile[] files= index.getFiles(location);
|
||||
|
||||
// pre-includes may be listed twice (191989)
|
||||
if (file.length < 1 || file.length > 2)
|
||||
return false;
|
||||
if (files.length <= 0)
|
||||
return new MultiStatus(CCorePlugin.PLUGIN_ID, IStatus.OK, "No index file found for: " + location, null); //$NON-NLS-1$
|
||||
|
||||
if (resource.getLocalTimeStamp() != file[0].getTimestamp())
|
||||
return false;
|
||||
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[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;
|
||||
// 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) {
|
||||
|
|
|
@ -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);
|
||||
|
||||
// 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();
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
} catch(InterruptedException ie) {
|
||||
// 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());
|
||||
}
|
||||
}
|
||||
exportedPDOM.close();
|
||||
} finally {
|
||||
exportedPDOM.releaseWriteLock();
|
||||
}
|
||||
} 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 {
|
||||
|
|
Loading…
Add table
Reference in a new issue