1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

Obtain timestamp and file size _before_ reading the file contents to

protect the index from getting stale.
This commit is contained in:
Sergey Prigogin 2012-05-02 20:35:52 -07:00
parent d9caf9f42b
commit 3c572e9afb
13 changed files with 272 additions and 88 deletions

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2004, 2009 IBM Corporation and others.
* Copyright (c) 2004, 2012 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
@ -8,15 +8,15 @@
* Contributors:
* IBM - Initial API and implementation
* Markus Schorn (Wind River Systems)
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.core.dom.ast;
import org.eclipse.cdt.core.index.IIndexFile;
import org.eclipse.cdt.core.parser.ISignificantMacros;
/**
* This interface represent a preprocessor #include statement.
* This interface represents a preprocessor #include statement.
*
* @noextend This interface is not intended to be extended by clients.
* @noimplement This interface is not intended to be implemented by clients.
@ -76,12 +76,30 @@ public interface IASTPreprocessorIncludeStatement extends IASTPreprocessorStatem
*/
public ISignificantMacros[] getLoadedVersions();
/**
* Returns the modification time of the included file, or -1 if the file was not read.
* @since 5.4
*/
public long getIncludedFileTimestamp();
/**
* Returns the size of the included file, or -1 if the file was not read.
* @since 5.4
*/
public long getIncludedFileSize();
/**
* Returns a hash-code for the contents of the file included, or <code>0</code>
* if the content has not been parsed.
* @since 5.4
*/
public long getContentsHash();
public long getIncludedFileContentsHash();
/**
* Returns <code>true</code> if I/O errors were encountered while reading the included file.
* @since 5.4
*/
public boolean isErrorInIncludedFile();
/**
* Returns true, if an attempt will be or has been made to create AST for the target

View file

@ -29,11 +29,37 @@ import org.eclipse.core.runtime.IPath;
* @since 5.2
*/
public abstract class FileContent {
/** @since 5.4 */
public static final long NULL_TIMESTAMP = -1;
/** @since 5.4 */
public static final long NULL_FILE_SIZE = -1;
/**
* Returns the location of this file content as it will appear in {@link IASTFileLocation#getFileName()}
*/
public abstract String getFileLocation();
/**
* Returns the modification time of the file containing the content or NULL_TIMESTAMP if
* the content does not originate from a file. A zero value may be returned if there was
* an I/O error.
* @since 5.4
*/
public abstract long getTimestamp();
/**
* Returns the size of the file, or NULL_FILE_SIZE if the content does not originate from
* a file. A zero value may be returned if there was an I/O error.
* @since 5.4
*/
public abstract long getFileSize();
/**
* Returns {@code true} if there were I/O errors while retrieving contents of this file.
* @since 5.4
*/
public abstract boolean hasError();
/**
* Returns a 64-bit hash value of the file contents.
*/

View file

@ -27,6 +27,7 @@ import org.eclipse.cdt.internal.core.parser.scanner.InternalFileContent;
import org.eclipse.cdt.internal.core.resources.PathCanonicalizationStrategy;
import org.eclipse.cdt.utils.UNCPathConverter;
import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileInfo;
import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
@ -152,28 +153,30 @@ public class InternalParserUtil extends ParserFactory {
String path= file.getLocationURI().getPath();
path= normalizePath(path, file);
InputStream in;
InputStream input;
try {
in= file.getContents(true);
if (!(in instanceof FileInputStream)) {
/*
* In general, non-local file-systems will not use FileInputStream. Instead make a
* cached copy of the file and open an input stream to that.
*/
IFileStore store = EFS.getStore(file.getLocationURI());
IFileInfo fileInfo = store.fetchInfo();
input= file.getContents(true);
if (!(input instanceof FileInputStream)) {
/*
* In general, non-local file-systems will not use FileInputStream.
* Instead make a cached copy of the file and open an input stream to that.
*/
File fileCache = store.toLocalFile(EFS.CACHE, null);
try {
in = new FileInputStream(fileCache);
input = new FileInputStream(fileCache);
} catch (FileNotFoundException e) {
CCorePlugin.log(e);
return null;
}
}
try {
return createFileContent(path, file.getCharset(), in);
return createFileContent(path, file.getCharset(), input,
fileInfo.getLastModified(), fileInfo.getLength());
} finally {
try {
in.close();
input.close();
} catch (IOException e) {
}
}
@ -215,6 +218,8 @@ public class InternalParserUtil extends ParserFactory {
}
}
if (includeFile != null && includeFile.isFile()) {
long timestamp = includeFile.lastModified();
long fileSize = includeFile.length();
FileInputStream in;
try {
in = new FileInputStream(includeFile);
@ -223,7 +228,7 @@ public class InternalParserUtil extends ParserFactory {
return null;
}
try {
return createFileContent(path, encoding, in);
return createFileContent(path, encoding, in, timestamp, fileSize);
} finally {
try {
in.close();
@ -234,13 +239,14 @@ public class InternalParserUtil extends ParserFactory {
return null;
}
private static InternalFileContent createFileContent(String path, String charset, InputStream in) {
private static InternalFileContent createFileContent(String path, String charset, InputStream in,
long fileTimestamp, long fileSize) {
try {
AbstractCharArray chars= FileCharArray.create(path, charset, in);
if (chars == null)
return null;
return new InternalFileContent(path, chars);
return new InternalFileContent(path, chars, fileTimestamp, fileSize);
} catch (IOException e) {
CCorePlugin.log(e);
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2007, 2011 Wind River Systems, Inc. and others.
* Copyright (c) 2007, 2012 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
@ -7,6 +7,7 @@
*
* Contributors:
* Markus Schorn - initial API and implementation
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.core.parser.scanner;
@ -294,7 +295,10 @@ class ASTInclusionStatement extends ASTPreprocessorNode implements IASTPreproces
private boolean fCreatesAST;
private ISignificantMacros fSignificantMacros;
private ISignificantMacros[] fLoadedVersions = NO_VERSIONS;
private long fContentsHash;
private long fIncludedFileContentsHash;
private long fIncludedFileTimestamp = -1;
private long fIncludedFileSize;
private boolean fErrorInIncludedFile;
public ASTInclusionStatement(IASTTranslationUnit parent,
int startNumber, int nameStartNumber, int nameEndNumber, int endNumber,
@ -388,17 +392,56 @@ class ASTInclusionStatement extends ASTPreprocessorNode implements IASTPreproces
}
@Override
public long getContentsHash() {
public long getIncludedFileTimestamp() {
if (fNominationDelegate != null) {
return 0;
}
return fContentsHash;
return fIncludedFileTimestamp;
}
public void setContentsHash(long hash) {
public void setIncludedFileTimestamp(long timestamp) {
assert fNominationDelegate == null;
fIncludedFileTimestamp= timestamp;
}
@Override
public long getIncludedFileSize() {
if (fNominationDelegate != null) {
return 0;
}
return fIncludedFileSize;
}
public void setIncludedFileSize(long size) {
assert fNominationDelegate == null;
fIncludedFileSize= size;
}
@Override
public long getIncludedFileContentsHash() {
if (fNominationDelegate != null) {
return 0;
}
return fIncludedFileContentsHash;
}
public void setIncludedFileContentsHash(long hash) {
assert fNominationDelegate == null;
fCreatesAST= true;
fContentsHash= hash;
fIncludedFileContentsHash= hash;
}
@Override
public boolean isErrorInIncludedFile() {
if (fNominationDelegate != null) {
return false;
}
return fErrorInIncludedFile;
}
public void setErrorInIncludedFile(boolean error) {
assert fNominationDelegate == null;
fErrorInIncludedFile= error;
}
@Override

View file

@ -53,6 +53,11 @@ public abstract class AbstractCharArray {
*/
public abstract void arraycopy(int offset, char[] destination, int destinationPos, int length);
/**
* Returns {@code true} if there were I/O errors while retrieving contents of this array.
*/
public abstract boolean hasError();
/**
* This method is slow. Use only for debugging.
*/

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2004, 2011 IBM Corporation and others.
* Copyright (c) 2004, 2012 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
@ -1487,7 +1487,10 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
detectIncludeGuard(path, source, fctx);
fCurrentContext= fctx;
stmt= ctx.getInclusionStatement();
stmt.setContentsHash(source.getContentsHash());
stmt.setIncludedFileTimestamp(fi.getTimestamp());
stmt.setIncludedFileSize(fi.getFileSize());
stmt.setIncludedFileContentsHash(source.getContentsHash());
stmt.setErrorInIncludedFile(source.hasError());
if (!fCurrentContext.isPragmaOnce()) {
// Track the loaded version count, even in a non-pragma-once context.
loadedVerisons= fFileContentProvider.getLoadedVersions(path);

View file

@ -55,6 +55,11 @@ public final class CharArray extends AbstractCharArray {
return offset < fArray.length;
}
@Override
public boolean hasError() {
return false;
}
@Override
public long getContentsHash() {
if (hash64 == 0 && fArray.length != 0) {

View file

@ -30,7 +30,8 @@ import org.eclipse.cdt.core.CCorePlugin;
public class FileCharArray extends LazyCharArray {
private static final String UTF8_CHARSET_NAME = "UTF-8"; //$NON-NLS-1$
public static AbstractCharArray create(String fileName, String charSet, InputStream in) throws IOException {
public static AbstractCharArray create(String fileName, String charSet, InputStream in)
throws IOException {
// No support for non-local files.
if (!(in instanceof FileInputStream)) {
return null;
@ -48,7 +49,8 @@ public class FileCharArray extends LazyCharArray {
return new FileCharArray(fileName, charSet);
}
private static AbstractCharArray decodeSmallFile(FileChannel channel, int lsize, String charSet) throws IOException {
private static AbstractCharArray decodeSmallFile(FileChannel channel, int lsize, String charSet)
throws IOException {
ByteBuffer byteBuffer = ByteBuffer.allocate(lsize);
channel.read(byteBuffer);
byteBuffer.flip();
@ -80,8 +82,9 @@ public class FileCharArray extends LazyCharArray {
return buf;
}
private String fFileName;
private String fCharSet;
private final String fFileName;
private final String fCharSet;
private boolean fHasError;
private FileChannel fChannel;
private long fNextFileOffset;
private int fNextCharOffset;
@ -97,8 +100,9 @@ public class FileCharArray extends LazyCharArray {
FileInputStream fis;
try {
fis = new FileInputStream(fFileName);
} catch (FileNotFoundException e1) {
} catch (FileNotFoundException e) {
// File has been deleted in the meantime
fHasError = true;
return null;
}
fChannel= fis.getChannel();
@ -121,7 +125,8 @@ public class FileCharArray extends LazyCharArray {
try {
assert fChannel != null;
final Charset charset = Charset.forName(fCharSet);
final CharsetDecoder decoder = charset.newDecoder().onMalformedInput(CodingErrorAction.REPLACE)
final CharsetDecoder decoder = charset.newDecoder()
.onMalformedInput(CodingErrorAction.REPLACE)
.onUnmappableCharacter(CodingErrorAction.REPLACE);
int needBytes = 3 + (int) (CHUNK_SIZE * (double) decoder.averageCharsPerByte()); // avoid rounding errors.
@ -141,7 +146,7 @@ public class FileCharArray extends LazyCharArray {
skipUTF8ByteOrderMark(in, fCharSet);
}
result = decoder.decode(in, dest, eof);
fileOffset+= in.position();
fileOffset += in.position();
} while (result == CoderResult.UNDERFLOW && !eof);
dest.flip();
@ -154,14 +159,14 @@ public class FileCharArray extends LazyCharArray {
}
final char[] chars = extractChars(dest);
Chunk chunk = newChunk(fNextFileOffset, fileOffset, fNextCharOffset, chars);
fNextFileOffset= fileOffset;
fNextCharOffset+= chars.length;
fNextFileOffset = fileOffset;
fNextCharOffset += chars.length;
return chunk;
} catch (Exception e) {
// The file cannot be read
CCorePlugin.log(e);
fReachedEOF= true;
fHasError = true;
fReachedEOF = true;
return null;
}
}
@ -173,6 +178,7 @@ public class FileCharArray extends LazyCharArray {
fis = new FileInputStream(fFileName);
} catch (FileNotFoundException e1) {
// File has been deleted in the meantime
fHasError = true;
return;
}
try {
@ -180,6 +186,7 @@ public class FileCharArray extends LazyCharArray {
decode(channel, chunk.fSourceOffset, chunk.fSourceEndOffset, CharBuffer.wrap(dest));
} catch (IOException e) {
// File cannot be read
fHasError = true;
} finally {
try {
fis.close();
@ -188,7 +195,8 @@ public class FileCharArray extends LazyCharArray {
}
}
private void decode(FileChannel channel, long fileOffset, long fileEndOffset, CharBuffer dest) throws IOException {
private void decode(FileChannel channel, long fileOffset, long fileEndOffset, CharBuffer dest)
throws IOException {
final Charset charset = Charset.forName(fCharSet);
final CharsetDecoder decoder = charset.newDecoder()
.onMalformedInput(CodingErrorAction.REPLACE)
@ -205,4 +213,9 @@ public class FileCharArray extends LazyCharArray {
}
decoder.decode(in, dest, true);
}
@Override
public boolean hasError() {
return fHasError;
}
}

View file

@ -55,9 +55,11 @@ public class InternalFileContent extends FileContent {
private final String fFileLocation;
private final List<FileVersion> fNonPragmaOnceFiles;
private boolean fHeuristic;
private boolean fIsSource= false;
private boolean fIsSource;
private List<IIndexFile> fFiles;
private IncludeSearchPathElement fFoundOnPath;
private final long fTimestamp;
private final long fFileSize;
/**
* For skipping include files.
@ -76,13 +78,16 @@ public class InternalFileContent extends FileContent {
fUsingDirectives= null;
fSource= null;
fNonPragmaOnceFiles= null;
fTimestamp= NULL_TIMESTAMP;
fFileSize = NULL_FILE_SIZE;
}
/**
* For reading include files from disk.
* @throws IllegalArgumentException in case the codeReader or its location is <code>null</code>.
*/
public InternalFileContent(String filePath, AbstractCharArray content) throws IllegalArgumentException {
public InternalFileContent(String filePath, AbstractCharArray content, long timestamp,
long fileSize) throws IllegalArgumentException {
if (content == null) {
throw new IllegalArgumentException();
}
@ -95,6 +100,29 @@ public class InternalFileContent extends FileContent {
if (fFileLocation == null) {
throw new IllegalArgumentException();
}
fTimestamp= timestamp;
fFileSize = fileSize;
}
/**
* For reading in-memory buffers.
* @throws IllegalArgumentException in case the codeReader or its location is <code>null</code>.
*/
public InternalFileContent(String filePath, CharArray content) throws IllegalArgumentException {
if (content == null) {
throw new IllegalArgumentException();
}
fKind= InclusionKind.USE_SOURCE;
fFileLocation= filePath;
fSource= content;
fMacroDefinitions= null;
fUsingDirectives= null;
fNonPragmaOnceFiles= null;
if (fFileLocation == null) {
throw new IllegalArgumentException();
}
fTimestamp= NULL_TIMESTAMP;
fFileSize = NULL_FILE_SIZE;
}
/**
@ -104,8 +132,9 @@ public class InternalFileContent extends FileContent {
* @param files
* @throws IllegalArgumentException in case the fileLocation or the macroDefinitions are <code>null</code>.
*/
public InternalFileContent(String fileLocation, List<IIndexMacro> macroDefinitions, List<ICPPUsingDirective> usingDirectives,
List<IIndexFile> files, List<FileVersion> nonPragmaOnceVersions) {
public InternalFileContent(String fileLocation, List<IIndexMacro> macroDefinitions,
List<ICPPUsingDirective> usingDirectives, List<IIndexFile> files,
List<FileVersion> nonPragmaOnceVersions) {
fKind= InclusionKind.FOUND_IN_INDEX;
fFileLocation= fileLocation;
fSource= null;
@ -113,6 +142,8 @@ public class InternalFileContent extends FileContent {
fMacroDefinitions= macroDefinitions;
fFiles= files;
fNonPragmaOnceFiles= nonPragmaOnceVersions;
fTimestamp= NULL_TIMESTAMP;
fFileSize = NULL_FILE_SIZE;
}
/**
@ -130,14 +161,26 @@ public class InternalFileContent extends FileContent {
return fFileLocation;
}
/**
* Returns a 64-bit hash value of the file contents.
*/
@Override
public long getTimestamp() {
return fTimestamp;
}
@Override
public long getFileSize() {
return fFileSize;
}
@Override
public long getContentsHash() {
return fSource != null ? fSource.getContentsHash() : 0;
}
@Override
public boolean hasError() {
return fSource != null && fSource.hasError();
}
/**
* Valid with {@link InclusionKind#USE_SOURCE}.
* @return the codeReader or <code>null</code> if kind is different to {@link InclusionKind#USE_SOURCE}.

View file

@ -725,7 +725,7 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
@Override
protected void reportFileWrittenToIndex(FileInAST file, IIndexFragmentFile ifile) throws CoreException {
final FileContentKey fck = file.fFileContentKey;
final FileContentKey fck = file.fileContentKey;
final IIndexFileLocation location = fck.getLocation();
boolean wasCounted= false;
UpdateKind kind= UpdateKind.OTHER_HEADER;
@ -748,7 +748,7 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
}
}
fIndexContentCache.remove(ifile);
fIndexFilesCache.remove(file.fFileContentKey.getLocation());
fIndexFilesCache.remove(file.fileContentKey.getLocation());
LocationTask task= fOneLinkageTasks.remove(location);
if (task != null && task != locTask) {
@ -978,8 +978,9 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
}
private DependsOnOutdatedFileException parseFile(Object tu, AbstractLanguage lang, IIndexFileLocation ifl, IScannerInfo scanInfo,
FileContext ctx, IProgressMonitor pm) throws CoreException, InterruptedException {
private DependsOnOutdatedFileException parseFile(Object tu, AbstractLanguage lang,
IIndexFileLocation ifl, IScannerInfo scanInfo, FileContext ctx, IProgressMonitor pm)
throws CoreException, InterruptedException {
IPath path= getLabel(ifl);
Throwable th= null;
try {
@ -995,7 +996,7 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
IASTTranslationUnit ast= createAST(lang, codeReader, scanInfo, isSource, fASTOptions, ctx, pm);
fStatistics.fParsingTime += System.currentTimeMillis() - start;
if (ast != null) {
writeToIndex(lang.getLinkageID(), ast, codeReader.getContentsHash(), ctx, pm);
writeToIndex(lang.getLinkageID(), ast, codeReader, ctx, pm);
}
} catch (CoreException e) {
th= e;
@ -1133,7 +1134,7 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
throw new IllegalArgumentException("Invalid file content provider"); //$NON-NLS-1$
}
private void writeToIndex(final int linkageID, IASTTranslationUnit ast, long fileContentsHash,
private void writeToIndex(final int linkageID, IASTTranslationUnit ast, FileContent codeReader,
FileContext ctx, IProgressMonitor pm) throws CoreException, InterruptedException {
HashSet<FileContentKey> enteredFiles= new HashSet<FileContentKey>();
ArrayList<FileInAST> orderedFileKeys= new ArrayList<FileInAST>();
@ -1149,11 +1150,11 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
IIndexFragmentFile newFile= selectIndexFile(linkageID, topIfl, ast.getSignificantMacros());
if (ctx != null) {
orderedFileKeys.add(new FileInAST(null, topKey, fileContentsHash));
orderedFileKeys.add(new FileInAST(topKey, codeReader));
// File can be reused
ctx.fNewFile= newFile;
} else if (newFile == null) {
orderedFileKeys.add(new FileInAST(null, topKey, fileContentsHash));
orderedFileKeys.add(new FileInAST(topKey, codeReader));
}
FileInAST[] fileKeys= orderedFileKeys.toArray(new FileInAST[orderedFileKeys.size()]);
@ -1184,7 +1185,7 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
collectOrderedFileKeys(linkageID, element, enteredFiles, orderedFileKeys);
}
if (isFirstEntry && selectIndexFile(linkageID, ifl, include.getSignificantMacros()) == null) {
orderedFileKeys.add(new FileInAST(include, fileKey, include.getContentsHash()));
orderedFileKeys.add(new FileInAST(include, fileKey));
}
}
}
@ -1193,7 +1194,7 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
LinkageTask map = findRequestMap(linkageID);
if (map != null) {
for (FileInAST fileKey : fileKeys) {
LocationTask locTask = map.find(fileKey.fFileContentKey.getLocation());
LocationTask locTask = map.find(fileKey.fileContentKey.getLocation());
if (locTask != null) {
if (locTask.fCountedUnknownVersion) {
locTask.fCountedUnknownVersion= false;

View file

@ -37,12 +37,12 @@ public abstract class IndexerInputAdapter extends ASTFilePathResolver {
/**
* Returns the size of the file in bytes, or 0 if the file does not exist.
*/
public abstract long getFileSize(IIndexFileLocation ifl);
public abstract long getFileSize(IIndexFileLocation location);
/**
* Returns the encoding for the file.
*/
public abstract String getEncoding(IIndexFileLocation ifl);
public abstract String getEncoding(IIndexFileLocation location);
/**
* Create an index location for the given input file.
@ -70,7 +70,7 @@ public abstract class IndexerInputAdapter extends ASTFilePathResolver {
* @param ifl The Location of the file.
* @return {@code true} if the file should be indexed unconditionally.
*/
public abstract boolean isIndexedUnconditionally(IIndexFileLocation ifl);
public abstract boolean isIndexedUnconditionally(IIndexFileLocation location);
/**
* Tests whether the file in the index is allowed to be part of an SDK. If not

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2007, 2011 Wind River Systems, Inc. and others.
* Copyright (c) 2007, 2012 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
@ -48,6 +48,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
import org.eclipse.cdt.core.index.IIndexFile;
import org.eclipse.cdt.core.index.IIndexFileLocation;
import org.eclipse.cdt.core.index.IIndexInclude;
import org.eclipse.cdt.core.parser.FileContent;
import org.eclipse.cdt.core.parser.IProblem;
import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.internal.core.dom.parser.ASTInternal;
@ -67,24 +68,40 @@ import org.eclipse.core.runtime.Status;
import org.eclipse.osgi.util.NLS;
/**
* Abstract class to write information from AST
* Abstract class to write information from AST.
* @since 4.0
*/
abstract public class PDOMWriter {
public static class FileInAST {
final IASTPreprocessorIncludeStatement fIncludeStatement;
final FileContentKey fFileContentKey;
final long fContentsHash;
public FileInAST(IASTPreprocessorIncludeStatement includeStmt, FileContentKey key, long contentsHash) {
fIncludeStatement= includeStmt;
fFileContentKey= key;
fContentsHash= contentsHash;
public static class FileInAST {
final IASTPreprocessorIncludeStatement includeStatement;
final FileContentKey fileContentKey;
final long timestamp;
final long fileSize;
final long contentsHash;
final boolean hasError;
public FileInAST(IASTPreprocessorIncludeStatement includeStmt, FileContentKey key) {
includeStatement= includeStmt;
fileContentKey= key;
timestamp= includeStmt.getIncludedFileTimestamp();
fileSize = includeStmt.getIncludedFileSize();
contentsHash= includeStmt.getIncludedFileContentsHash();
hasError= includeStmt.isErrorInIncludedFile();
}
public FileInAST(FileContentKey key, FileContent codeReader) {
includeStatement= null;
fileContentKey= key;
timestamp= codeReader.getTimestamp();
fileSize= codeReader.getFileSize();
contentsHash= codeReader.getContentsHash();
hasError= codeReader.hasError();
}
@Override
public String toString() {
return fFileContentKey.toString();
return fileContentKey.toString();
}
}
@ -198,7 +215,7 @@ abstract public class PDOMWriter {
Data data= new Data(ast, selectedFiles, index);
for (FileInAST file : selectedFiles) {
data.fSymbolMap.put(file.fIncludeStatement, new Symbols());
data.fSymbolMap.put(file.includeStatement, new Symbols());
}
@ -215,7 +232,7 @@ abstract public class PDOMWriter {
if (taskUpdater != null) {
Set<IIndexFileLocation> locations= new HashSet<IIndexFileLocation>();
for (FileInAST file : selectedFiles) {
locations.add(file.fFileContentKey.getLocation());
locations.add(file.fileContentKey.getLocation());
}
taskUpdater.updateTasks(ast.getComments(), locations.toArray(new IIndexFileLocation[locations.size()]));
}
@ -223,7 +240,7 @@ abstract public class PDOMWriter {
List<IStatus> stati = data.fStati;
String path= null;
if (selectedFiles.length > 0) {
path= selectedFiles[selectedFiles.length - 1].fFileContentKey.getLocation().getURI().getPath();
path= selectedFiles[selectedFiles.length - 1].fileContentKey.getLocation().getURI().getPath();
} else {
path= ast.getFilePath().toString();
}
@ -252,13 +269,13 @@ abstract public class PDOMWriter {
final FileInAST fileInAST= data.fSelectedFiles[i];
if (fileInAST != null) {
if (fShowActivity) {
trace("Indexer: adding " + fileInAST.fFileContentKey.getLocation().getURI()); //$NON-NLS-1$
trace("Indexer: adding " + fileInAST.fileContentKey.getLocation().getURI()); //$NON-NLS-1$
}
Throwable th= null;
YieldableIndexLock lock = new YieldableIndexLock(data.fIndex, flushIndex);
lock.acquire();
try {
final boolean isReplacement= ctx != null && fileInAST.fIncludeStatement == null;
final boolean isReplacement= ctx != null && fileInAST.includeStatement == null;
IIndexFragmentFile ifile= null;
if (!isReplacement || newFile == null) {
ifile= storeFileInIndex(data, fileInAST, linkageID, lock);
@ -294,7 +311,7 @@ abstract public class PDOMWriter {
}
if (th != null) {
data.fStati.add(createStatus(NLS.bind(Messages.PDOMWriter_errorWhileParsing,
fileInAST.fFileContentKey.getLocation().getURI().getPath()), th));
fileInAST.fileContentKey.getLocation().getURI().getPath()), th));
}
fStatistics.fAddToIndexTime += lock.getCumulativeLockTime();
}
@ -307,7 +324,7 @@ abstract public class PDOMWriter {
if (pm.isCanceled()) {
return;
}
Symbols symbols= data.fSymbolMap.get(file.fIncludeStatement);
Symbols symbols= data.fSymbolMap.get(file.includeStatement);
final ArrayList<IASTName[]> names= symbols.fNames;
boolean reported= false;
@ -351,7 +368,7 @@ abstract public class PDOMWriter {
if (th != null) {
if (!reported) {
data.fStati.add(CCorePlugin.createStatus(NLS.bind(Messages.PDOMWriter_errorResolvingName,
name.toString(), file.fFileContentKey.getLocation().getURI().getPath()), th));
name.toString(), file.fileContentKey.getLocation().getURI().getPath()), th));
}
reported= true;
j.remove();
@ -516,8 +533,8 @@ abstract public class PDOMWriter {
// contents of the old file from the temporary one, then delete the temporary file.
// The write lock on the index can be yielded between adding names to the temporary file,
// if another thread is waiting for a read lock.
final FileContentKey fileKey = astFile.fFileContentKey;
final IASTPreprocessorIncludeStatement owner= astFile.fIncludeStatement;
final FileContentKey fileKey = astFile.fileContentKey;
final IASTPreprocessorIncludeStatement owner= astFile.includeStatement;
IIndexFileLocation location = fileKey.getLocation();
ISignificantMacros significantMacros = fileKey.getSignificantMacros();
@ -559,9 +576,9 @@ abstract public class PDOMWriter {
IncludeInformation[] includeInfoArray= includeInfos.toArray(new IncludeInformation[includeInfos.size()]);
index.setFileContent(file, linkageID, includeInfoArray, macros, names, fResolver, lock);
}
file.setTimestamp(fResolver.getLastModified(location));
file.setSizeAndEncodingHashcode(computeFileSizeAndEncodingHashcode(location));
file.setContentsHash(astFile.fContentsHash);
file.setTimestamp(astFile.hasError ? 0 : astFile.timestamp);
file.setSizeAndEncodingHashcode(computeFileSizeAndEncodingHashcode(astFile.fileSize, location));
file.setContentsHash(astFile.contentsHash);
file = index.commitUncommittedFile();
} finally {
index.clearUncommittedFile();
@ -570,7 +587,11 @@ abstract public class PDOMWriter {
}
protected int computeFileSizeAndEncodingHashcode(IIndexFileLocation location) {
return ((int) fResolver.getFileSize(location)) + 31 * fResolver.getEncoding(location).hashCode();
return computeFileSizeAndEncodingHashcode((int) fResolver.getFileSize(location), location);
}
private int computeFileSizeAndEncodingHashcode(long size, IIndexFileLocation location) {
return (int) size + 31 * fResolver.getEncoding(location).hashCode();
}
private boolean isContextFor(IIndexFragmentFile oldFile, IASTPreprocessorIncludeStatement stmt)