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 * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -8,15 +8,15 @@
* Contributors: * Contributors:
* IBM - Initial API and implementation * IBM - Initial API and implementation
* Markus Schorn (Wind River Systems) * Markus Schorn (Wind River Systems)
* Sergey Prigogin (Google)
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.core.dom.ast; package org.eclipse.cdt.core.dom.ast;
import org.eclipse.cdt.core.index.IIndexFile; import org.eclipse.cdt.core.index.IIndexFile;
import org.eclipse.cdt.core.parser.ISignificantMacros; 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. * @noextend This interface is not intended to be extended by clients.
* @noimplement This interface is not intended to be implemented 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(); 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> * Returns a hash-code for the contents of the file included, or <code>0</code>
* if the content has not been parsed. * if the content has not been parsed.
* @since 5.4 * @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 * 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 * @since 5.2
*/ */
public abstract class FileContent { 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()} * Returns the location of this file content as it will appear in {@link IASTFileLocation#getFileName()}
*/ */
public abstract String getFileLocation(); 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. * Returns a 64-bit hash value of the file contents.
*/ */
@ -47,7 +73,7 @@ public abstract class FileContent {
public static FileContent create(String filePath, char[] contents) { public static FileContent create(String filePath, char[] contents) {
return new InternalFileContent(filePath, new CharArray(contents)); return new InternalFileContent(filePath, new CharArray(contents));
} }
/** /**
* Creates a file content object for a translation-unit, which may be a working copy. * Creates a file content object for a translation-unit, which may be a working copy.
*/ */

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.internal.core.resources.PathCanonicalizationStrategy;
import org.eclipse.cdt.utils.UNCPathConverter; import org.eclipse.cdt.utils.UNCPathConverter;
import org.eclipse.core.filesystem.EFS; import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileInfo;
import org.eclipse.core.filesystem.IFileStore; import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResource;
@ -152,28 +153,30 @@ public class InternalParserUtil extends ParserFactory {
String path= file.getLocationURI().getPath(); String path= file.getLocationURI().getPath();
path= normalizePath(path, file); path= normalizePath(path, file);
InputStream in; InputStream input;
try { try {
in= file.getContents(true); IFileStore store = EFS.getStore(file.getLocationURI());
if (!(in instanceof FileInputStream)) { 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 * In general, non-local file-systems will not use FileInputStream.
* cached copy of the file and open an input stream to that. * Instead make a cached copy of the file and open an input stream to that.
*/ */
IFileStore store = EFS.getStore(file.getLocationURI());
File fileCache = store.toLocalFile(EFS.CACHE, null); File fileCache = store.toLocalFile(EFS.CACHE, null);
try { try {
in = new FileInputStream(fileCache); input = new FileInputStream(fileCache);
} catch (FileNotFoundException e) { } catch (FileNotFoundException e) {
CCorePlugin.log(e); CCorePlugin.log(e);
return null; return null;
} }
} }
try { try {
return createFileContent(path, file.getCharset(), in); return createFileContent(path, file.getCharset(), input,
fileInfo.getLastModified(), fileInfo.getLength());
} finally { } finally {
try { try {
in.close(); input.close();
} catch (IOException e) { } catch (IOException e) {
} }
} }
@ -215,6 +218,8 @@ public class InternalParserUtil extends ParserFactory {
} }
} }
if (includeFile != null && includeFile.isFile()) { if (includeFile != null && includeFile.isFile()) {
long timestamp = includeFile.lastModified();
long fileSize = includeFile.length();
FileInputStream in; FileInputStream in;
try { try {
in = new FileInputStream(includeFile); in = new FileInputStream(includeFile);
@ -223,7 +228,7 @@ public class InternalParserUtil extends ParserFactory {
return null; return null;
} }
try { try {
return createFileContent(path, encoding, in); return createFileContent(path, encoding, in, timestamp, fileSize);
} finally { } finally {
try { try {
in.close(); in.close();
@ -234,13 +239,14 @@ public class InternalParserUtil extends ParserFactory {
return null; 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 { try {
AbstractCharArray chars= FileCharArray.create(path, charset, in); AbstractCharArray chars= FileCharArray.create(path, charset, in);
if (chars == null) if (chars == null)
return null; return null;
return new InternalFileContent(path, chars); return new InternalFileContent(path, chars, fileTimestamp, fileSize);
} catch (IOException e) { } catch (IOException e) {
CCorePlugin.log(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 * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -7,6 +7,7 @@
* *
* Contributors: * Contributors:
* Markus Schorn - initial API and implementation * Markus Schorn - initial API and implementation
* Sergey Prigogin (Google)
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.parser.scanner; package org.eclipse.cdt.internal.core.parser.scanner;
@ -294,7 +295,10 @@ class ASTInclusionStatement extends ASTPreprocessorNode implements IASTPreproces
private boolean fCreatesAST; private boolean fCreatesAST;
private ISignificantMacros fSignificantMacros; private ISignificantMacros fSignificantMacros;
private ISignificantMacros[] fLoadedVersions = NO_VERSIONS; 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, public ASTInclusionStatement(IASTTranslationUnit parent,
int startNumber, int nameStartNumber, int nameEndNumber, int endNumber, int startNumber, int nameStartNumber, int nameEndNumber, int endNumber,
@ -388,17 +392,56 @@ class ASTInclusionStatement extends ASTPreprocessorNode implements IASTPreproces
} }
@Override @Override
public long getContentsHash() { public long getIncludedFileTimestamp() {
if (fNominationDelegate != null) { if (fNominationDelegate != null) {
return 0; 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; assert fNominationDelegate == null;
fCreatesAST= true; 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 @Override

View file

@ -53,6 +53,11 @@ public abstract class AbstractCharArray {
*/ */
public abstract void arraycopy(int offset, char[] destination, int destinationPos, int length); 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. * 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 * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -1487,7 +1487,10 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
detectIncludeGuard(path, source, fctx); detectIncludeGuard(path, source, fctx);
fCurrentContext= fctx; fCurrentContext= fctx;
stmt= ctx.getInclusionStatement(); 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()) { if (!fCurrentContext.isPragmaOnce()) {
// Track the loaded version count, even in a non-pragma-once context. // Track the loaded version count, even in a non-pragma-once context.
loadedVerisons= fFileContentProvider.getLoadedVersions(path); loadedVerisons= fFileContentProvider.getLoadedVersions(path);

View file

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

View file

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

View file

@ -6,8 +6,8 @@
* http://www.eclipse.org/legal/epl-v10.html * http://www.eclipse.org/legal/epl-v10.html
* *
* Contributors: * Contributors:
* Markus Schorn - initial API and implementation * Markus Schorn - initial API and implementation
* Sergey Prigogin (Google) * Sergey Prigogin (Google)
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.parser.scanner; package org.eclipse.cdt.internal.core.parser.scanner;
@ -55,9 +55,11 @@ public class InternalFileContent extends FileContent {
private final String fFileLocation; private final String fFileLocation;
private final List<FileVersion> fNonPragmaOnceFiles; private final List<FileVersion> fNonPragmaOnceFiles;
private boolean fHeuristic; private boolean fHeuristic;
private boolean fIsSource= false; private boolean fIsSource;
private List<IIndexFile> fFiles; private List<IIndexFile> fFiles;
private IncludeSearchPathElement fFoundOnPath; private IncludeSearchPathElement fFoundOnPath;
private final long fTimestamp;
private final long fFileSize;
/** /**
* For skipping include files. * For skipping include files.
@ -76,13 +78,16 @@ public class InternalFileContent extends FileContent {
fUsingDirectives= null; fUsingDirectives= null;
fSource= null; fSource= null;
fNonPragmaOnceFiles= null; fNonPragmaOnceFiles= null;
fTimestamp= NULL_TIMESTAMP;
fFileSize = NULL_FILE_SIZE;
} }
/** /**
* For reading include files from disk. * For reading include files from disk.
* @throws IllegalArgumentException in case the codeReader or its location is <code>null</code>. * @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) { if (content == null) {
throw new IllegalArgumentException(); throw new IllegalArgumentException();
} }
@ -95,6 +100,29 @@ public class InternalFileContent extends FileContent {
if (fFileLocation == null) { if (fFileLocation == null) {
throw new IllegalArgumentException(); 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 * @param files
* @throws IllegalArgumentException in case the fileLocation or the macroDefinitions are <code>null</code>. * @throws IllegalArgumentException in case the fileLocation or the macroDefinitions are <code>null</code>.
*/ */
public InternalFileContent(String fileLocation, List<IIndexMacro> macroDefinitions, List<ICPPUsingDirective> usingDirectives, public InternalFileContent(String fileLocation, List<IIndexMacro> macroDefinitions,
List<IIndexFile> files, List<FileVersion> nonPragmaOnceVersions) { List<ICPPUsingDirective> usingDirectives, List<IIndexFile> files,
List<FileVersion> nonPragmaOnceVersions) {
fKind= InclusionKind.FOUND_IN_INDEX; fKind= InclusionKind.FOUND_IN_INDEX;
fFileLocation= fileLocation; fFileLocation= fileLocation;
fSource= null; fSource= null;
@ -113,6 +142,8 @@ public class InternalFileContent extends FileContent {
fMacroDefinitions= macroDefinitions; fMacroDefinitions= macroDefinitions;
fFiles= files; fFiles= files;
fNonPragmaOnceFiles= nonPragmaOnceVersions; fNonPragmaOnceFiles= nonPragmaOnceVersions;
fTimestamp= NULL_TIMESTAMP;
fFileSize = NULL_FILE_SIZE;
} }
/** /**
@ -130,14 +161,26 @@ public class InternalFileContent extends FileContent {
return fFileLocation; return fFileLocation;
} }
/** @Override
* Returns a 64-bit hash value of the file contents. public long getTimestamp() {
*/ return fTimestamp;
}
@Override
public long getFileSize() {
return fFileSize;
}
@Override @Override
public long getContentsHash() { public long getContentsHash() {
return fSource != null ? fSource.getContentsHash() : 0; return fSource != null ? fSource.getContentsHash() : 0;
} }
@Override
public boolean hasError() {
return fSource != null && fSource.hasError();
}
/** /**
* Valid with {@link InclusionKind#USE_SOURCE}. * Valid with {@link InclusionKind#USE_SOURCE}.
* @return the codeReader or <code>null</code> if kind is different to {@link InclusionKind#USE_SOURCE}. * @return the codeReader or <code>null</code> if kind is different to {@link InclusionKind#USE_SOURCE}.
@ -200,7 +243,7 @@ public class InternalFileContent extends FileContent {
public void setFoundOnPath(IncludeSearchPathElement isp) { public void setFoundOnPath(IncludeSearchPathElement isp) {
fFoundOnPath= isp; fFoundOnPath= isp;
} }
/** /**
* This method is slow. Use only for debugging. * This method is slow. Use only for debugging.
*/ */

View file

@ -725,7 +725,7 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
@Override @Override
protected void reportFileWrittenToIndex(FileInAST file, IIndexFragmentFile ifile) throws CoreException { protected void reportFileWrittenToIndex(FileInAST file, IIndexFragmentFile ifile) throws CoreException {
final FileContentKey fck = file.fFileContentKey; final FileContentKey fck = file.fileContentKey;
final IIndexFileLocation location = fck.getLocation(); final IIndexFileLocation location = fck.getLocation();
boolean wasCounted= false; boolean wasCounted= false;
UpdateKind kind= UpdateKind.OTHER_HEADER; UpdateKind kind= UpdateKind.OTHER_HEADER;
@ -748,7 +748,7 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
} }
} }
fIndexContentCache.remove(ifile); fIndexContentCache.remove(ifile);
fIndexFilesCache.remove(file.fFileContentKey.getLocation()); fIndexFilesCache.remove(file.fileContentKey.getLocation());
LocationTask task= fOneLinkageTasks.remove(location); LocationTask task= fOneLinkageTasks.remove(location);
if (task != null && task != locTask) { 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, private DependsOnOutdatedFileException parseFile(Object tu, AbstractLanguage lang,
FileContext ctx, IProgressMonitor pm) throws CoreException, InterruptedException { IIndexFileLocation ifl, IScannerInfo scanInfo, FileContext ctx, IProgressMonitor pm)
throws CoreException, InterruptedException {
IPath path= getLabel(ifl); IPath path= getLabel(ifl);
Throwable th= null; Throwable th= null;
try { try {
@ -995,7 +996,7 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
IASTTranslationUnit ast= createAST(lang, codeReader, scanInfo, isSource, fASTOptions, ctx, pm); IASTTranslationUnit ast= createAST(lang, codeReader, scanInfo, isSource, fASTOptions, ctx, pm);
fStatistics.fParsingTime += System.currentTimeMillis() - start; fStatistics.fParsingTime += System.currentTimeMillis() - start;
if (ast != null) { if (ast != null) {
writeToIndex(lang.getLinkageID(), ast, codeReader.getContentsHash(), ctx, pm); writeToIndex(lang.getLinkageID(), ast, codeReader, ctx, pm);
} }
} catch (CoreException e) { } catch (CoreException e) {
th= e; th= e;
@ -1133,7 +1134,7 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
throw new IllegalArgumentException("Invalid file content provider"); //$NON-NLS-1$ 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 { FileContext ctx, IProgressMonitor pm) throws CoreException, InterruptedException {
HashSet<FileContentKey> enteredFiles= new HashSet<FileContentKey>(); HashSet<FileContentKey> enteredFiles= new HashSet<FileContentKey>();
ArrayList<FileInAST> orderedFileKeys= new ArrayList<FileInAST>(); ArrayList<FileInAST> orderedFileKeys= new ArrayList<FileInAST>();
@ -1149,11 +1150,11 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
IIndexFragmentFile newFile= selectIndexFile(linkageID, topIfl, ast.getSignificantMacros()); IIndexFragmentFile newFile= selectIndexFile(linkageID, topIfl, ast.getSignificantMacros());
if (ctx != null) { if (ctx != null) {
orderedFileKeys.add(new FileInAST(null, topKey, fileContentsHash)); orderedFileKeys.add(new FileInAST(topKey, codeReader));
// File can be reused // File can be reused
ctx.fNewFile= newFile; ctx.fNewFile= newFile;
} else if (newFile == null) { } 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()]); FileInAST[] fileKeys= orderedFileKeys.toArray(new FileInAST[orderedFileKeys.size()]);
@ -1184,7 +1185,7 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
collectOrderedFileKeys(linkageID, element, enteredFiles, orderedFileKeys); collectOrderedFileKeys(linkageID, element, enteredFiles, orderedFileKeys);
} }
if (isFirstEntry && selectIndexFile(linkageID, ifl, include.getSignificantMacros()) == null) { 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); LinkageTask map = findRequestMap(linkageID);
if (map != null) { if (map != null) {
for (FileInAST fileKey : fileKeys) { for (FileInAST fileKey : fileKeys) {
LocationTask locTask = map.find(fileKey.fFileContentKey.getLocation()); LocationTask locTask = map.find(fileKey.fileContentKey.getLocation());
if (locTask != null) { if (locTask != null) {
if (locTask.fCountedUnknownVersion) { if (locTask.fCountedUnknownVersion) {
locTask.fCountedUnknownVersion= false; 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. * 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. * 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. * 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. * @param ifl The Location of the file.
* @return {@code true} if the file should be indexed unconditionally. * @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 * 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 * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * 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.IIndexFile;
import org.eclipse.cdt.core.index.IIndexFileLocation; import org.eclipse.cdt.core.index.IIndexFileLocation;
import org.eclipse.cdt.core.index.IIndexInclude; 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.IProblem;
import org.eclipse.cdt.core.parser.ISignificantMacros; import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.internal.core.dom.parser.ASTInternal; 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; import org.eclipse.osgi.util.NLS;
/** /**
* Abstract class to write information from AST * Abstract class to write information from AST.
* @since 4.0 * @since 4.0
*/ */
abstract public class PDOMWriter { 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) { public static class FileInAST {
fIncludeStatement= includeStmt; final IASTPreprocessorIncludeStatement includeStatement;
fFileContentKey= key; final FileContentKey fileContentKey;
fContentsHash= contentsHash; 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 @Override
public String toString() { public String toString() {
return fFileContentKey.toString(); return fileContentKey.toString();
} }
} }
@ -198,7 +215,7 @@ abstract public class PDOMWriter {
Data data= new Data(ast, selectedFiles, index); Data data= new Data(ast, selectedFiles, index);
for (FileInAST file : selectedFiles) { 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) { if (taskUpdater != null) {
Set<IIndexFileLocation> locations= new HashSet<IIndexFileLocation>(); Set<IIndexFileLocation> locations= new HashSet<IIndexFileLocation>();
for (FileInAST file : selectedFiles) { for (FileInAST file : selectedFiles) {
locations.add(file.fFileContentKey.getLocation()); locations.add(file.fileContentKey.getLocation());
} }
taskUpdater.updateTasks(ast.getComments(), locations.toArray(new IIndexFileLocation[locations.size()])); taskUpdater.updateTasks(ast.getComments(), locations.toArray(new IIndexFileLocation[locations.size()]));
} }
@ -223,7 +240,7 @@ abstract public class PDOMWriter {
List<IStatus> stati = data.fStati; List<IStatus> stati = data.fStati;
String path= null; String path= null;
if (selectedFiles.length > 0) { if (selectedFiles.length > 0) {
path= selectedFiles[selectedFiles.length - 1].fFileContentKey.getLocation().getURI().getPath(); path= selectedFiles[selectedFiles.length - 1].fileContentKey.getLocation().getURI().getPath();
} else { } else {
path= ast.getFilePath().toString(); path= ast.getFilePath().toString();
} }
@ -252,13 +269,13 @@ abstract public class PDOMWriter {
final FileInAST fileInAST= data.fSelectedFiles[i]; final FileInAST fileInAST= data.fSelectedFiles[i];
if (fileInAST != null) { if (fileInAST != null) {
if (fShowActivity) { 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; Throwable th= null;
YieldableIndexLock lock = new YieldableIndexLock(data.fIndex, flushIndex); YieldableIndexLock lock = new YieldableIndexLock(data.fIndex, flushIndex);
lock.acquire(); lock.acquire();
try { try {
final boolean isReplacement= ctx != null && fileInAST.fIncludeStatement == null; final boolean isReplacement= ctx != null && fileInAST.includeStatement == null;
IIndexFragmentFile ifile= null; IIndexFragmentFile ifile= null;
if (!isReplacement || newFile == null) { if (!isReplacement || newFile == null) {
ifile= storeFileInIndex(data, fileInAST, linkageID, lock); ifile= storeFileInIndex(data, fileInAST, linkageID, lock);
@ -294,7 +311,7 @@ abstract public class PDOMWriter {
} }
if (th != null) { if (th != null) {
data.fStati.add(createStatus(NLS.bind(Messages.PDOMWriter_errorWhileParsing, 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(); fStatistics.fAddToIndexTime += lock.getCumulativeLockTime();
} }
@ -307,7 +324,7 @@ abstract public class PDOMWriter {
if (pm.isCanceled()) { if (pm.isCanceled()) {
return; return;
} }
Symbols symbols= data.fSymbolMap.get(file.fIncludeStatement); Symbols symbols= data.fSymbolMap.get(file.includeStatement);
final ArrayList<IASTName[]> names= symbols.fNames; final ArrayList<IASTName[]> names= symbols.fNames;
boolean reported= false; boolean reported= false;
@ -351,7 +368,7 @@ abstract public class PDOMWriter {
if (th != null) { if (th != null) {
if (!reported) { if (!reported) {
data.fStati.add(CCorePlugin.createStatus(NLS.bind(Messages.PDOMWriter_errorResolvingName, 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; reported= true;
j.remove(); j.remove();
@ -516,8 +533,8 @@ abstract public class PDOMWriter {
// contents of the old file from the temporary one, then delete the temporary file. // 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, // 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. // if another thread is waiting for a read lock.
final FileContentKey fileKey = astFile.fFileContentKey; final FileContentKey fileKey = astFile.fileContentKey;
final IASTPreprocessorIncludeStatement owner= astFile.fIncludeStatement; final IASTPreprocessorIncludeStatement owner= astFile.includeStatement;
IIndexFileLocation location = fileKey.getLocation(); IIndexFileLocation location = fileKey.getLocation();
ISignificantMacros significantMacros = fileKey.getSignificantMacros(); ISignificantMacros significantMacros = fileKey.getSignificantMacros();
@ -559,9 +576,9 @@ abstract public class PDOMWriter {
IncludeInformation[] includeInfoArray= includeInfos.toArray(new IncludeInformation[includeInfos.size()]); IncludeInformation[] includeInfoArray= includeInfos.toArray(new IncludeInformation[includeInfos.size()]);
index.setFileContent(file, linkageID, includeInfoArray, macros, names, fResolver, lock); index.setFileContent(file, linkageID, includeInfoArray, macros, names, fResolver, lock);
} }
file.setTimestamp(fResolver.getLastModified(location)); file.setTimestamp(astFile.hasError ? 0 : astFile.timestamp);
file.setSizeAndEncodingHashcode(computeFileSizeAndEncodingHashcode(location)); file.setSizeAndEncodingHashcode(computeFileSizeAndEncodingHashcode(astFile.fileSize, location));
file.setContentsHash(astFile.fContentsHash); file.setContentsHash(astFile.contentsHash);
file = index.commitUncommittedFile(); file = index.commitUncommittedFile();
} finally { } finally {
index.clearUncommittedFile(); index.clearUncommittedFile();
@ -570,7 +587,11 @@ abstract public class PDOMWriter {
} }
protected int computeFileSizeAndEncodingHashcode(IIndexFileLocation location) { 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) private boolean isContextFor(IIndexFragmentFile oldFile, IASTPreprocessorIncludeStatement stmt)

View file

@ -320,7 +320,7 @@ public class ProjectIndexerInputAdapter extends IndexerInputAdapter {
ITranslationUnit tu= (ITranslationUnit) tuo; ITranslationUnit tu= (ITranslationUnit) tuo;
if (tu.getLocation() == null) if (tu.getLocation() == null)
return null; return null;
final FileContent reader= FileContent.create(tu); final FileContent reader= FileContent.create(tu);
if (reader != null) { if (reader != null) {
IIndexFileLocation ifl= IndexLocationFactory.getIFL(tu); IIndexFileLocation ifl= IndexLocationFactory.getIFL(tu);