diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/EmptyIndexFragment.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/EmptyIndexFragment.java index eb1aec237a2..526777f16cc 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/EmptyIndexFragment.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/EmptyIndexFragment.java @@ -8,6 +8,7 @@ * Contributors: * Andrew Ferguson (Symbian) - initial API and implementation * Markus Schorn (Wind River Systems) + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.internal.index.tests; @@ -123,6 +124,11 @@ public class EmptyIndexFragment implements IIndexFragment { } public void releaseReadLock() {} + + public boolean hasWaitingReaders() { + return false; + } + public void resetCacheCounters() {} public IIndexFragmentFileSet createFileSet() { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndex.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndex.java index 03047bd8f8e..6fe8024593c 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndex.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndex.java @@ -9,6 +9,7 @@ * Markus Schorn - initial API and implementation * Andrew Ferguson (Symbian) * Bryan Wilkinson (QNX) + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.core.index; @@ -91,6 +92,12 @@ public interface IIndex { */ public void releaseReadLock(); + /** + * @return true if there are threads waiting for read locks. + * @since 5.2 + */ + public boolean hasWaitingReaders(); + /** * Returns a timestamp of when the index was last written to. This can * be used to figure out whether information read from the index is diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/CIndex.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/CIndex.java index c3c0844d523..0df4c0555df 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/CIndex.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/CIndex.java @@ -10,6 +10,7 @@ * Bryan Wilkinson (QNX) * Andrew Ferguson (Symbian) * Anton Leherbauer (Wind River Systems) + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.internal.core.index; @@ -355,6 +356,15 @@ public class CIndex implements IIndex { return fReadLock; } + public boolean hasWaitingReaders() { + for (int i= 0; i < fFragments.length; i++) { + if (fFragments[i].hasWaitingReaders()) { + return true; + } + } + return false; + } + public long getLastWriteAccess() { long result= 0; for (int i = 0; i < fFragments.length; i++) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/EmptyCIndex.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/EmptyCIndex.java index 5d9ffa85dbf..3197f68f2a5 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/EmptyCIndex.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/EmptyCIndex.java @@ -9,6 +9,7 @@ * Markus Schorn - initial API and implementation * Bryan Wilkinson (QNX) * Andrew Ferguson (Symbian) + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.internal.core.index; @@ -85,6 +86,10 @@ final public class EmptyCIndex implements IIndex { public void releaseReadLock() { } + public boolean hasWaitingReaders() { + return false; + } + public long getLastWriteAccess() { return 0; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragment.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragment.java index 50d35af6e28..ff5755f07f9 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragment.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragment.java @@ -9,6 +9,7 @@ * Markus Schorn - initial API and implementation * Bryan Wilkinson (QNX) * Andrew Ferguson (Symbian) + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.internal.core.index; @@ -190,6 +191,11 @@ public interface IIndexFragment { */ void releaseReadLock(); + /** + * @return true if there are threads waiting for read locks. + */ + public boolean hasWaitingReaders(); + /** * Returns the timestamp of the last modification to the index. */ diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IWritableIndex.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IWritableIndex.java index 21169115848..b125d44838e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IWritableIndex.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IWritableIndex.java @@ -8,6 +8,7 @@ * Contributors: * Markus Schorn - initial API and implementation * Andrew Ferguson (Symbian) + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.internal.core.index; @@ -21,6 +22,7 @@ import org.eclipse.cdt.core.index.IIndex; import org.eclipse.cdt.core.index.IIndexFile; import org.eclipse.cdt.core.index.IIndexFileLocation; import org.eclipse.cdt.internal.core.pdom.ASTFilePathResolver; +import org.eclipse.cdt.internal.core.pdom.YieldableIndexLock; import org.eclipse.core.runtime.CoreException; /** @@ -65,7 +67,28 @@ public interface IWritableIndex extends IIndex { /** * Creates a file object for the given location or returns an existing one. */ - IIndexFragmentFile addFile(int linkageID, IIndexFileLocation fileLocation) throws CoreException; + IIndexFragmentFile addFile(int linkageID, IIndexFileLocation location) throws CoreException; + + /** + * Creates a uncommitted file object for the given location. + */ + IIndexFragmentFile addUncommittedFile(int linkageID, IIndexFileLocation location) throws CoreException; + + /** + * Makes an uncommitted file that was created earlier by calling + * {@link #addUncommittedFile(int, IIndexFileLocation)} method visible in the index. + * + * @return The file that was updated. + * @throws CoreException + */ + IIndexFragmentFile commitUncommittedFile() throws CoreException; + + /** + * Removes an uncommitted file if there is one. Used to recover from a failed index update. + * + * @throws CoreException + */ + void clearUncommittedFile() throws CoreException; /** * Adds content to the given file. @@ -73,7 +96,7 @@ public interface IWritableIndex extends IIndex { void setFileContent(IIndexFragmentFile sourceFile, int linkageID, IncludeInformation[] includes, IASTPreprocessorStatement[] macros, IASTName[][] names, - ASTFilePathResolver resolver) throws CoreException; + ASTFilePathResolver resolver, YieldableIndexLock lock) throws CoreException, InterruptedException; /** * Clears the entire index. diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IWritableIndexFragment.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IWritableIndexFragment.java index 137d950c63a..aec945d2c91 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IWritableIndexFragment.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IWritableIndexFragment.java @@ -8,7 +8,8 @@ * Contributors: * Markus Schorn - initial API and implementation * Andrew Ferguson (Symbian) - *******************************************************************************/ + * Sergey Prigogin (Google) +******************************************************************************/ package org.eclipse.cdt.internal.core.index; @@ -19,6 +20,7 @@ import org.eclipse.cdt.core.dom.ast.IASTPreprocessorStatement; import org.eclipse.cdt.core.index.IIndexFileLocation; import org.eclipse.cdt.internal.core.index.IWritableIndex.IncludeInformation; import org.eclipse.cdt.internal.core.pdom.ASTFilePathResolver; +import org.eclipse.cdt.internal.core.pdom.YieldableIndexLock; import org.eclipse.core.runtime.CoreException; /** @@ -41,18 +43,43 @@ public interface IWritableIndexFragment extends IIndexFragment { /** * Creates a file object for the given location and linkage or returns an existing one. - * @param fileLocation an IIndexFileLocation representing the location of the file - * @return the existing IIndexFragmentFile for this location, or a newly created one + * @param fileLocation an IIndexFileLocation representing the location of the file. + * @return the existing IIndexFragmentFile for this location, or a newly created one. * @throws CoreException */ IIndexFragmentFile addFile(int linkageID, IIndexFileLocation fileLocation) throws CoreException; /** - * Adds an include to the given file. + * Creates a file object for the given location and linkage. The created file object is not added to + * the file index. + * @param fileLocation an IIndexFileLocation representing the location of the file. + * @return a newly created IIndexFragmentFile. + * @throws CoreException */ - void addFileContent(IIndexFragmentFile sourceFile, - IncludeInformation[] includes, - IASTPreprocessorStatement[] macros, IASTName[][] names, ASTFilePathResolver resolver) throws CoreException; + IIndexFragmentFile addUncommittedFile(int linkageID, IIndexFileLocation fileLocation) throws CoreException; + + /** + * Makes an uncommitted file that was created earlier by calling + * {@link #addUncommittedFile(int, IIndexFileLocation)} method visible in the index. + * + * @return The file that was updated. + * @throws CoreException + */ + IIndexFragmentFile commitUncommittedFile() throws CoreException; + + /** + * Removes an uncommitted file if there is one. Used to recover from a failed index update. + * + * @throws CoreException + */ + void clearUncommittedFile() throws CoreException; + + /** + * Adds includes, macros and names to the given file. + */ + void addFileContent(IIndexFragmentFile sourceFile, IncludeInformation[] includes, + IASTPreprocessorStatement[] macros, IASTName[][] names, ASTFilePathResolver resolver, + YieldableIndexLock lock) throws CoreException, InterruptedException; /** * Acquires a write lock, while giving up a certain amount of read locks. diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/WritableCIndex.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/WritableCIndex.java index 1cca94dbdd6..ad7d877db3f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/WritableCIndex.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/WritableCIndex.java @@ -8,6 +8,7 @@ * Contributors: * Markus Schorn - initial API and implementation * Andrew Ferguson (Symbian) + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.internal.core.index; @@ -19,6 +20,7 @@ import org.eclipse.cdt.core.dom.ast.IASTPreprocessorStatement; import org.eclipse.cdt.core.index.IIndexFile; import org.eclipse.cdt.core.index.IIndexFileLocation; import org.eclipse.cdt.internal.core.pdom.ASTFilePathResolver; +import org.eclipse.cdt.internal.core.pdom.YieldableIndexLock; import org.eclipse.core.runtime.CoreException; public class WritableCIndex extends CIndex implements IWritableIndex { @@ -50,17 +52,29 @@ public class WritableCIndex extends CIndex implements IWritableIndex { return fWritableFragment.getFiles(location); } - public IIndexFragmentFile addFile(int linkageID, IIndexFileLocation fileLocation) throws CoreException { - return fWritableFragment.addFile(linkageID, fileLocation); + public IIndexFragmentFile addFile(int linkageID, IIndexFileLocation location) throws CoreException { + return fWritableFragment.addFile(linkageID, location); + } + + public IIndexFragmentFile addUncommittedFile(int linkageID, IIndexFileLocation location) throws CoreException { + return fWritableFragment.addUncommittedFile(linkageID, location); + } + + public IIndexFragmentFile commitUncommittedFile() throws CoreException { + return fWritableFragment.commitUncommittedFile(); + } + + public void clearUncommittedFile() throws CoreException { + fWritableFragment.clearUncommittedFile(); } private boolean isWritableFragment(IIndexFragment frag) { return frag == fWritableFragment; } - public void setFileContent(IIndexFragmentFile file, int linkageID, - IncludeInformation[] includes, - IASTPreprocessorStatement[] macros, IASTName[][] names, ASTFilePathResolver resolver) throws CoreException { + public void setFileContent(IIndexFragmentFile file, int linkageID, IncludeInformation[] includes, + IASTPreprocessorStatement[] macros, IASTName[][] names, ASTFilePathResolver resolver, + YieldableIndexLock lock) throws CoreException, InterruptedException { IIndexFragment indexFragment = file.getIndexFragment(); if (!isWritableFragment(indexFragment)) { assert false : "Attempt to update file of read-only fragment"; //$NON-NLS-1$ @@ -70,7 +84,7 @@ public class WritableCIndex extends CIndex implements IWritableIndex { ii.fTargetFile= addFile(linkageID, ii.fLocation); } } - ((IWritableIndexFragment) indexFragment).addFileContent(file, includes, macros, names, resolver); + ((IWritableIndexFragment) indexFragment).addFileContent(file, includes, macros, names, resolver, lock); } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java index e7ca8c7fc85..56652441d7a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java @@ -6,11 +6,12 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * Doug Schaefer (QNX) - Initial API and implementation - * Markus Schorn (Wind River Systems) - * IBM Corporation - * Andrew Ferguson (Symbian) - * Anton Leherbauer (Wind River Systems) + * Doug Schaefer (QNX) - Initial API and implementation + * Markus Schorn (Wind River Systems) + * IBM Corporation + * Andrew Ferguson (Symbian) + * Anton Leherbauer (Wind River Systems) + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.internal.core.pdom; @@ -96,6 +97,7 @@ import org.eclipse.core.runtime.Status; public class PDOM extends PlatformObject implements IPDOM { private static final int BLOCKED_WRITE_LOCK_OUTPUT_INTERVAL = 30000; private static final int LONG_WRITE_LOCK_REPORT_THRESHOLD = 1000; + private static final int LONG_READ_LOCK_WAIT_REPORT_THRESHOLD = 1000; static boolean sDEBUG_LOCKS= false; // initialized in the PDOMManager, because IBM needs PDOM independent of runtime plugin. /** @@ -341,7 +343,7 @@ public class PDOM extends PlatformObject implements IPDOM { } } - private PDOMLinkage createLinkage(int linkageID) throws CoreException { + protected PDOMLinkage createLinkage(int linkageID) throws CoreException { PDOMLinkage pdomLinkage= fLinkageIDCache.get(linkageID); if (pdomLinkage == null) { final String linkageName= Linkage.getLinkageName(linkageID); @@ -766,6 +768,7 @@ public class PDOM extends PlatformObject implements IPDOM { private long timeWriteLockAcquired; public void acquireReadLock() throws InterruptedException { + long t = sDEBUG_LOCKS ? System.nanoTime() : 0; synchronized (mutex) { ++waitingReaders; try { @@ -776,14 +779,17 @@ public class PDOM extends PlatformObject implements IPDOM { } ++lockCount; db.setLocked(true); - + if (sDEBUG_LOCKS) { + t = (System.nanoTime() - t) / 1000000; + if (t >= LONG_READ_LOCK_WAIT_REPORT_THRESHOLD) { + System.out.println("Acquired index read lock after " + t + " ms wait."); //$NON-NLS-1$//$NON-NLS-2$ + } incReadLock(fLockDebugging); } } } - public void releaseReadLock() { boolean clearCache= false; synchronized (mutex) { @@ -884,6 +890,12 @@ public class PDOM extends PlatformObject implements IPDOM { fireChange(event); } + public boolean hasWaitingReaders() { + synchronized (mutex) { + return waitingReaders > 0; + } + } + public long getLastWriteAccess() { return lastWriteAccess; } @@ -957,17 +969,23 @@ public class PDOM extends PlatformObject implements IPDOM { PDOMName name; if ((options & FIND_DECLARATIONS) != 0) { for (name= pdomBinding.getFirstDeclaration(); name != null; name= name.getNextInBinding()) { - names.add(name); + if (isCommitted(name)) { + names.add(name); + } } } if ((options & FIND_DEFINITIONS) != 0) { for (name = pdomBinding.getFirstDefinition(); name != null; name= name.getNextInBinding()) { - names.add(name); + if (isCommitted(name)) { + names.add(name); + } } } if ((options & FIND_REFERENCES) != 0) { for (name = pdomBinding.getFirstReference(); name != null; name= name.getNextInBinding()) { - names.add(name); + if (isCommitted(name)) { + names.add(name); + } } } } @@ -977,24 +995,40 @@ public class PDOM extends PlatformObject implements IPDOM { if ((options & FIND_DEFINITIONS) != 0) { for (PDOMMacro macro= container.getFirstDefinition(); macro != null; macro= macro.getNextInContainer()) { final IIndexFragmentName name = macro.getDefinition(); - if (name != null) { + if (name != null && isCommitted(macro)) { names.add(name); } } } if ((options & FIND_REFERENCES) != 0) { for (PDOMMacroReferenceName name = container.getFirstReference(); name != null; name= name.getNextInContainer()) { - names.add(name); + if (isCommitted(name)) { + names.add(name); + } } } } + protected boolean isCommitted(PDOMName name) throws CoreException { + return true; + } + + protected boolean isCommitted(PDOMMacro name) throws CoreException { + return true; + } + + protected boolean isCommitted(PDOMMacroReferenceName name) throws CoreException { + return true; + } + public IIndexFragmentInclude[] findIncludedBy(IIndexFragmentFile file) throws CoreException { PDOMFile pdomFile= adaptFile(file); if (pdomFile != null) { List result = new ArrayList(); for (PDOMInclude i= pdomFile.getFirstIncludedBy(); i != null; i= i.getNextInIncludedBy()) { - result.add(i); + if (i.getIncludedBy().getTimestamp() > 0) { + result.add(i); + } } return result.toArray(new PDOMInclude[result.size()]); } @@ -1197,6 +1231,10 @@ public class PDOM extends PlatformObject implements IPDOM { public String createKeyForCache(long record, char[] name) { return new StringBuilder(name.length + 2).append((char) (record >> 16)).append((char) record).append(name).toString(); } + + public boolean hasLastingDefinition(PDOMBinding binding) throws CoreException { + return binding.hasDefinition(); + } private PDOMBinding[] getCrossLanguageBindings(IBinding binding) throws CoreException { switch(binding.getLinkage().getLinkageID()) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMProxy.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMProxy.java index e1cabeb4403..e61693ef1bc 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMProxy.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMProxy.java @@ -7,6 +7,7 @@ * * Contributors: * Markus Schorn - initial API and implementation + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.internal.core.pdom; @@ -187,6 +188,10 @@ public class PDOMProxy implements IPDOM { } } + public boolean hasWaitingReaders() { + return fDelegate != null && fDelegate.hasWaitingReaders(); + } + public synchronized void resetCacheCounters() { if (fDelegate != null) fDelegate.resetCacheCounters(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMWriter.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMWriter.java index 24f3e024944..e5abcf63fb6 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMWriter.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMWriter.java @@ -8,6 +8,7 @@ * Contributors: * Markus Schorn - initial API and implementation * IBM Corporation + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.internal.core.pdom; @@ -46,6 +47,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceAlias; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier; import org.eclipse.cdt.core.index.IIndexFileLocation; +import org.eclipse.cdt.core.index.IIndexInclude; import org.eclipse.cdt.core.parser.IProblem; import org.eclipse.cdt.internal.core.dom.parser.ASTInternal; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding; @@ -68,6 +70,9 @@ import org.eclipse.osgi.util.NLS; * @since 4.0 */ abstract public class PDOMWriter { + // TODO(sprigogin): Remove SEMI_TRANSACTIONAL_UPDATES and ALLOW_LOCK_YIELDING constants and simplify the code. + public static boolean SEMI_TRANSACTIONAL_UPDATES = true; + public static boolean ALLOW_LOCK_YIELDING = true; public static int SKIP_ALL_REFERENCES= -1; public static int SKIP_TYPE_REFERENCES= 1; public static int SKIP_MACRO_REFERENCES= 2; @@ -200,11 +205,11 @@ abstract public class PDOMWriter { if (fShowActivity) { trace("Indexer: adding " + ifl.getURI()); //$NON-NLS-1$ } - index.acquireWriteLock(readlockCount); - long start= System.currentTimeMillis(); Throwable th= null; + YieldableIndexLock lock = new YieldableIndexLock(index, readlockCount, flushIndex); + lock.acquire(); try { - storeFileInIndex(index, ifl, symbolMap, linkageID, configHash, contextIncludes); + storeFileInIndex(index, ifl, symbolMap, linkageID, configHash, contextIncludes, lock); } catch (RuntimeException e) { th= e; } catch (PDOMNotImplementedError e) { @@ -214,7 +219,7 @@ abstract public class PDOMWriter { } catch (AssertionError e) { th= e; } finally { - index.releaseWriteLock(readlockCount, flushIndex); + lock.release(); } if (th != null) { stati.add(createStatus(NLS.bind(Messages.PDOMWriter_errorWhileParsing, @@ -223,7 +228,7 @@ abstract public class PDOMWriter { if (i < ifls.length - 1) { updateFileCount(0, 0, 1); // update header count } - fStatistics.fAddToIndexTime += System.currentTimeMillis() - start; + fStatistics.fAddToIndexTime += lock.getCumulativeLockTime(); } } } @@ -448,40 +453,70 @@ abstract public class PDOMWriter { private IIndexFragmentFile storeFileInIndex(IWritableIndex index, IIndexFileLocation location, Map symbolMap, int linkageID, int configHash, - Set contextIncludes) throws CoreException { + Set contextIncludes, YieldableIndexLock lock) + throws CoreException, InterruptedException { Set clearedContexts= Collections.emptySet(); - IIndexFragmentFile file= index.getWritableFile(linkageID, location); - if (file != null) { - clearedContexts= new HashSet(); - index.clearFile(file, clearedContexts); + IIndexFragmentFile file; + long timestamp = fResolver.getLastModified(location); + if (SEMI_TRANSACTIONAL_UPDATES) { + // In fine grained locking mode we create a temporary PDOMFile with zero timestamp, + // add names to it, then replace contents of the old file from the temporary one, then + // delete the temporary file. The write lock on the index is periodically yielded while + // adding names to the temporary file, if the process takes long time. + IIndexFragmentFile oldFile = index.getWritableFile(linkageID, location); + if (oldFile != null) { + IIndexInclude[] includedBy = index.findIncludedBy(oldFile); + if (includedBy.length > 0) { + clearedContexts= new HashSet(); + for (IIndexInclude include : includedBy) { + clearedContexts.add(include.getIncludedByLocation()); + } + } + } + file= index.addUncommittedFile(linkageID, location); } else { - file= index.addFile(linkageID, location); + file= index.getWritableFile(linkageID, location); + if (file != null) { + clearedContexts= new HashSet(); + index.clearFile(file, clearedContexts); + } else { + file= index.addFile(linkageID, location); + } + file.setTimestamp(timestamp); } - file.setTimestamp(fResolver.getLastModified(location)); - file.setScannerConfigurationHashcode(configHash); - Symbols lists= symbolMap.get(location); - if (lists != null) { - IASTPreprocessorStatement[] macros= lists.fMacros.toArray(new IASTPreprocessorStatement[lists.fMacros.size()]); - IASTName[][] names= lists.fNames.toArray(new IASTName[lists.fNames.size()][]); - for (IASTName[] name2 : names) { - final IASTName name= name2[0]; - if (name != null) { - ASTInternal.setFullyResolved(name.getBinding(), true); + try { + file.setScannerConfigurationHashcode(configHash); + Symbols lists= symbolMap.get(location); + if (lists != null) { + IASTPreprocessorStatement[] macros= lists.fMacros.toArray(new IASTPreprocessorStatement[lists.fMacros.size()]); + IASTName[][] names= lists.fNames.toArray(new IASTName[lists.fNames.size()][]); + for (IASTName[] name2 : names) { + final IASTName name= name2[0]; + if (name != null) { + ASTInternal.setFullyResolved(name.getBinding(), true); + } } - } - - IncludeInformation[] includeInfos= new IncludeInformation[lists.fIncludes.size()]; - for (int i= 0; i < lists.fIncludes.size(); i++) { - final IASTPreprocessorIncludeStatement include = lists.fIncludes.get(i); - final IncludeInformation info= includeInfos[i]= new IncludeInformation(); - info.fStatement= include; - if (include.isResolved()) { - info.fLocation= fResolver.resolveASTPath(include.getPath()); - info.fIsContext= include.isActive() && - (contextIncludes.contains(include) || clearedContexts.contains(info.fLocation)); + + IncludeInformation[] includeInfos= new IncludeInformation[lists.fIncludes.size()]; + for (int i= 0; i < lists.fIncludes.size(); i++) { + final IASTPreprocessorIncludeStatement include = lists.fIncludes.get(i); + final IncludeInformation info= includeInfos[i]= new IncludeInformation(); + info.fStatement= include; + if (include.isResolved()) { + info.fLocation= fResolver.resolveASTPath(include.getPath()); + info.fIsContext= include.isActive() && + (contextIncludes.contains(include) || clearedContexts.contains(info.fLocation)); + } } + index.setFileContent(file, linkageID, includeInfos, macros, names, fResolver, + SEMI_TRANSACTIONAL_UPDATES && ALLOW_LOCK_YIELDING ? lock : null); } - index.setFileContent(file, linkageID, includeInfos, macros, names, fResolver); + if (SEMI_TRANSACTIONAL_UPDATES) { + file.setTimestamp(timestamp); + file = index.commitUncommittedFile(); + } + } finally { + index.clearUncommittedFile(); } return file; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/WritablePDOM.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/WritablePDOM.java index 9d8fc7199e8..216bfa9cf79 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/WritablePDOM.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/WritablePDOM.java @@ -8,6 +8,7 @@ * Contributors: * Markus Schorn - initial API and implementation * Andrew Ferguson (Symbian) + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.internal.core.pdom; @@ -25,17 +26,26 @@ import org.eclipse.cdt.internal.core.index.IIndexFragment; import org.eclipse.cdt.internal.core.index.IIndexFragmentFile; import org.eclipse.cdt.internal.core.index.IWritableIndexFragment; import org.eclipse.cdt.internal.core.index.IWritableIndex.IncludeInformation; +import org.eclipse.cdt.internal.core.pdom.db.BTree; import org.eclipse.cdt.internal.core.pdom.db.ChunkCache; import org.eclipse.cdt.internal.core.pdom.db.DBProperties; import org.eclipse.cdt.internal.core.pdom.db.IBTreeVisitor; import org.eclipse.cdt.internal.core.pdom.dom.IPDOMLinkageFactory; +import org.eclipse.cdt.internal.core.pdom.dom.PDOMBinding; import org.eclipse.cdt.internal.core.pdom.dom.PDOMFile; +import org.eclipse.cdt.internal.core.pdom.dom.PDOMLinkage; +import org.eclipse.cdt.internal.core.pdom.dom.PDOMMacro; +import org.eclipse.cdt.internal.core.pdom.dom.PDOMMacroReferenceName; +import org.eclipse.cdt.internal.core.pdom.dom.PDOMName; import org.eclipse.core.runtime.CoreException; public class WritablePDOM extends PDOM implements IWritableIndexFragment { private boolean fClearedBecauseOfVersionMismatch= false; private boolean fCreatedFromScratch= false; private ASTFilePathResolver fPathResolver; + private PDOMFile fileBeingUpdated; + private PDOMFile uncommittedFile; + private IIndexFileLocation uncommittedLocation; public WritablePDOM(File dbPath, IIndexLocationConverter locationConverter, Map linkageFactoryMappings) throws CoreException { @@ -53,11 +63,57 @@ public class WritablePDOM extends PDOM implements IWritableIndexFragment { @Override public IIndexFragmentFile addFile(int linkageID, IIndexFileLocation location) throws CoreException { + if (uncommittedLocation != null && uncommittedLocation.equals(location)) { + return uncommittedFile; + } return super.addFile(linkageID, location); } + public IIndexFragmentFile addUncommittedFile(int linkageID, IIndexFileLocation location) throws CoreException { + uncommittedLocation = location; + fileBeingUpdated = getFile(linkageID, uncommittedLocation); + PDOMLinkage linkage= createLinkage(linkageID); + uncommittedFile = new PDOMFile(linkage, location, linkageID); + return uncommittedFile; + } + + public IIndexFragmentFile commitUncommittedFile() throws CoreException { + if (uncommittedFile == null) + return null; + IIndexFragmentFile file; + if (fileBeingUpdated == null) { + // New file. + BTree fileIndex = getFileIndex(); + fileIndex.insert(uncommittedFile.getRecord()); + file = uncommittedFile; + } else { + // Existing file. + fileBeingUpdated.replaceContentsFrom(uncommittedFile); + file = fileBeingUpdated; + fileBeingUpdated = null; + } + fEvent.fFilesWritten.add(uncommittedLocation); + uncommittedFile = null; + uncommittedLocation = null; + return file; + } + + public void clearUncommittedFile() throws CoreException { + if (uncommittedFile != null) { + try { + uncommittedFile.clear(null); + uncommittedFile.delete(); + } finally { + uncommittedFile = null; + uncommittedLocation = null; + fileBeingUpdated = null; + } + } + } + public void addFileContent(IIndexFragmentFile sourceFile, IncludeInformation[] includes, - IASTPreprocessorStatement[] macros, IASTName[][] names, ASTFilePathResolver pathResolver) throws CoreException { + IASTPreprocessorStatement[] macros, IASTName[][] names, ASTFilePathResolver pathResolver, + YieldableIndexLock lock) throws CoreException, InterruptedException { assert sourceFile.getIndexFragment() == this; PDOMFile pdomFile = (PDOMFile) sourceFile; @@ -66,14 +122,16 @@ public class WritablePDOM extends PDOM implements IWritableIndexFragment { final ASTFilePathResolver origResolver= fPathResolver; fPathResolver= pathResolver; try { - pdomFile.addNames(names); + pdomFile.addNames(names, lock); } finally { fPathResolver= origResolver; } final IIndexFileLocation location = pdomFile.getLocation(); - fEvent.fClearedFiles.remove(location); - fEvent.fFilesWritten.add(location); + if (location != null) { + fEvent.fClearedFiles.remove(location); + fEvent.fFilesWritten.add(location); + } } public void clearFile(IIndexFragmentFile file, Collection contextsRemoved) @@ -171,11 +229,47 @@ public class WritablePDOM extends PDOM implements IWritableIndexFragment { public PDOMFile getFileForASTPath(int linkageID, String astPath) throws CoreException { if (fPathResolver != null && astPath != null) { - return getFile(linkageID, fPathResolver.resolveASTPath(astPath)); + IIndexFileLocation location = fPathResolver.resolveASTPath(astPath); + if (location.equals(uncommittedLocation)) + return fileBeingUpdated != null ? fileBeingUpdated : uncommittedFile; + return getFile(linkageID, location); } return null; } + @Override + public boolean hasLastingDefinition(PDOMBinding binding) throws CoreException { + if (fileBeingUpdated == null) { + return binding.hasDefinition(); + } + // Definitions in fileBeingUpdated will soon go away, so look for a definition elsewhere. + for (PDOMName name = binding.getFirstDefinition(); name != null; name = name.getNextInBinding()) { + if (!fileBeingUpdated.getPDOM().equals(name.getPDOM()) || + fileBeingUpdated.getRecord() != name.getFileRecord()) { + return true; + } + } + return false; + } + + @Override + protected boolean isCommitted(PDOMName name) throws CoreException { + return uncommittedFile == null || !uncommittedFile.getPDOM().equals(name.getPDOM()) || + uncommittedFile.getRecord() != name.getFileRecord(); + } + + @Override + protected boolean isCommitted(PDOMMacro name) throws CoreException { + return uncommittedFile == null || !uncommittedFile.getPDOM().equals(name.getPDOM()) || + uncommittedFile.getRecord() != name.getFileRecord(); + } + + @Override + protected boolean isCommitted(PDOMMacroReferenceName name) throws CoreException { + return uncommittedFile == null || !uncommittedFile.getPDOM().equals(name.getPDOM()) || + uncommittedFile.getRecord() != name.getFileRecord(); + } + /* (non-Javadoc) * @see org.eclipse.cdt.internal.core.index.IWritableIndexFragment#getDatabaseSizeBytes() */ diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/YieldableIndexLock.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/YieldableIndexLock.java new file mode 100644 index 00000000000..8e110800675 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/YieldableIndexLock.java @@ -0,0 +1,74 @@ +/******************************************************************************* + * Copyright (c) 2010 Google, Inc and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Sergey Prigogin (Google) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.pdom; + +import org.eclipse.cdt.internal.core.index.IWritableIndex; + +/** + * Write lock on the index that can be yielded temporarily to unblock threads that need + * read access to the index. + * @since 5.2 + */ +public class YieldableIndexLock { + private final IWritableIndex index; + private final int readlockCount; + private final boolean flushIndex; + private long lastLockTime; + private long cumulativeLockTime; + + public YieldableIndexLock(IWritableIndex index, int readlockCount, boolean flushIndex) { + this.index = index; + this.readlockCount = readlockCount; + this.flushIndex = flushIndex; + } + + /** + * Acquires the lock. + * + * @throws InterruptedException + */ + public void acquire() throws InterruptedException { + index.acquireWriteLock(readlockCount); + lastLockTime = System.currentTimeMillis(); + } + + /** + * Releases the lock. + */ + public void release() { + if (lastLockTime != 0) { + index.releaseWriteLock(readlockCount, flushIndex); + cumulativeLockTime += System.currentTimeMillis() - lastLockTime; + lastLockTime = 0; + } + } + + /** + * Yields the lock temporarily if it was held for YIELD_INTERVAL or more, and somebody is waiting + * for a read lock. + * @throws InterruptedException + */ + public void yield() throws InterruptedException { + if (index.hasWaitingReaders()) { + index.releaseWriteLock(readlockCount, false); + cumulativeLockTime += System.currentTimeMillis() - lastLockTime; + lastLockTime = 0; + acquire(); + } + } + + /** + * @return Total time the lock was held in milliseconds. + */ + public long getCumulativeLockTime() { + return cumulativeLockTime; + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMFile.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMFile.java index fa688906957..ad1fce180b3 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMFile.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMFile.java @@ -9,6 +9,7 @@ * QNX - Initial API and implementation * Markus Schorn (Wind River Systems) * Andrew Ferguson (Symbian) + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.internal.core.pdom.dom; @@ -30,6 +31,7 @@ import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IMacroBinding; import org.eclipse.cdt.core.dom.ast.IParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDirective; +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.index.IIndexLocationConverter; @@ -42,6 +44,7 @@ import org.eclipse.cdt.internal.core.index.IWritableIndexFragment; import org.eclipse.cdt.internal.core.index.IndexFileLocation; import org.eclipse.cdt.internal.core.index.IWritableIndex.IncludeInformation; import org.eclipse.cdt.internal.core.pdom.PDOM; +import org.eclipse.cdt.internal.core.pdom.YieldableIndexLock; import org.eclipse.cdt.internal.core.pdom.db.BTree; import org.eclipse.cdt.internal.core.pdom.db.Database; import org.eclipse.cdt.internal.core.pdom.db.IBTreeComparator; @@ -115,6 +118,10 @@ public class PDOMFile implements IIndexFragmentFile { return record; } + public PDOM getPDOM() { + return fLinkage.getPDOM(); + } + @Override public boolean equals(Object obj) { if (obj == this) @@ -128,13 +135,116 @@ public class PDOMFile implements IIndexFragmentFile { @Override public final int hashCode() { - return System.identityHashCode(fLinkage.getPDOM()) + (int)(41*record); + return System.identityHashCode(fLinkage.getPDOM()) + (int) (41 * record); } /** - * Directly changes this record's internal location string. The format - * of this string is unspecified in general and is determined by the - * associated IIndexLocationConverter + * Transfers names, macros and includes from another file to this one and deletes the other file. + * @param sourceFile the file to transfer the local bindings from. + * @throws CoreException + */ + public void replaceContentsFrom(PDOMFile sourceFile) throws CoreException { + ICPPUsingDirective[] directives= getUsingDirectives(); + for (ICPPUsingDirective ud : directives) { + if (ud instanceof IPDOMNode) { + ((IPDOMNode) ud).delete(null); + } + } + setFirstUsingDirectiveRec(sourceFile.getLastUsingDirectiveRec()); + + // Replace the includes + PDOMInclude include = getFirstInclude(); + while (include != null) { + PDOMInclude nextInclude = include.getNextInIncludes(); + IIndexFile includedBy = include.getIncludedBy(); + if (this.equals(includedBy)) { + include.delete(); + } + include = nextInclude; + } + include = sourceFile.getFirstInclude(); + setFirstInclude(include); + while (include != null) { + IIndexFile includedBy = include.getIncludedBy(); + if (sourceFile.equals(includedBy)) { + include.setIncludedBy(this); + if (sourceFile.equals(include.getIncludes())) { + include.setIncludes(this); + } + } + include = include.getNextInIncludes(); + } + + // Replace all the macros in this file. + PDOMLinkage linkage= getLinkage(); + PDOMMacro macro = getFirstMacro(); + while (macro != null) { + PDOMMacro nextMacro = macro.getNextMacro(); + macro.delete(linkage); + macro = nextMacro; + } + macro = sourceFile.getFirstMacro(); + setFirstMacro(macro); + for (; macro != null; macro = macro.getNextMacro()) { + macro.setFile(this); + } + + // Replace all macro references + ArrayList mrefs= new ArrayList(); + PDOMMacroReferenceName mref = getFirstMacroReference(); + while (mref != null) { + mrefs.add(mref); + mref= mref.getNextInFile(); + } + for (PDOMMacroReferenceName m : mrefs) { + m.delete(); + } + mref = sourceFile.getFirstMacroReference(); + setFirstMacroReference(mref); + for (; mref != null; mref = mref.getNextInFile()) { + mref.setFile(this); + } + + // Replace all the names in this file + ArrayList names= new ArrayList(); + PDOMName name = getFirstName(); + for (; name != null; name= name.getNextInFile()) { + names.add(name); + linkage.onDeleteName(name); + } + for (Iterator iterator = names.iterator(); iterator.hasNext();) { + name = iterator.next(); + name.delete(); + } + name = sourceFile.getFirstName(); + setFirstName(name); + for (; name != null; name= name.getNextInFile()) { + name.setFile(this); + } + + setTimestamp(sourceFile.getTimestamp()); + setScannerConfigurationHashcode(sourceFile.getScannerConfigurationHashcode()); + + sourceFile.delete(); + } + + /** + * This method should not be called on PDOMFile objects that are referenced by the file index. + * @param location a new location + * @throws CoreException + */ + public void setLocation(IIndexFileLocation location) throws CoreException { + String locationString = fLinkage.getPDOM().getLocationConverter().toInternalFormat(location); + if (locationString == null) + throw new CoreException(CCorePlugin.createStatus(Messages.getString("PDOMFile.toInternalProblem") + //$NON-NLS-1$ + location.getURI())); + setInternalLocation(locationString); + } + + /** + * Directly changes this record's internal location string. The format of this string is unspecified + * in general and is determined by the associated IIndexLocationConverter. + * This method should not be called on PDOMFile objects that are referenced by the file index. * @param internalLocation * @throws CoreException */ @@ -256,7 +366,7 @@ public class PDOMFile implements IIndexFragmentFile { return fLinkage; } - public void addNames(IASTName[][] names) throws CoreException { + public void addNames(IASTName[][] names, YieldableIndexLock lock) throws CoreException, InterruptedException { assert getFirstName() == null; assert getFirstMacroReference() == null; final PDOMLinkage linkage= getLinkage(); @@ -265,6 +375,9 @@ public class PDOMFile implements IIndexFragmentFile { PDOMMacroReferenceName lastMacroName= null; for (IASTName[] name : names) { if (name[0] != null) { + if (lock != null) { + lock.yield(); + } PDOMName caller= nameCache.get(name[1]); IIndexFragmentName fname= createPDOMName(linkage, name[0], caller); if (fname instanceof PDOMName) { @@ -340,7 +453,7 @@ public class PDOMFile implements IIndexFragmentFile { include.delete(); include = nextInclude; } - setFirstInclude(include); + setFirstInclude(null); // Delete all the macros in this file PDOMLinkage linkage= getLinkage(); @@ -381,6 +494,15 @@ public class PDOMFile implements IIndexFragmentFile { setTimestamp(-1); } + /** + * Deletes this file from PDOM. Only uncommitted files can be safely deleted. + * + * @throws CoreException + */ + public void delete() throws CoreException { + fLinkage.getDB().free(record); + } + public void addIncludesTo(IncludeInformation[] includeInfos) throws CoreException { assert getFirstInclude() == null; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMInclude.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMInclude.java index 8ec79306035..28b45654ab8 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMInclude.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMInclude.java @@ -141,6 +141,11 @@ public class PDOMInclude implements IIndexFragmentInclude { return rec != 0 ? new PDOMFile(linkage, rec) : null; } + void setIncludes(PDOMFile includedFile) throws CoreException { + long rec = includedFile != null ? includedFile.getRecord() : 0; + linkage.getDB().putRecPtr(record + INCLUDED_FILE, rec); + } + /** * Checks if the name is the same as the end part of the path of the included file. */ @@ -166,7 +171,7 @@ public class PDOMInclude implements IIndexFragmentInclude { return rec != 0 ? new PDOMFile(linkage, rec) : null; } - private void setIncludedBy(PDOMFile includedBy) throws CoreException { + void setIncludedBy(PDOMFile includedBy) throws CoreException { long rec = includedBy != null ? includedBy.getRecord() : 0; linkage.getDB().putRecPtr(record + INCLUDED_BY, rec); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMMacro.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMMacro.java index a41393de695..a0399058e37 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMMacro.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMMacro.java @@ -9,6 +9,7 @@ * QNX - Initial API and implementation * Markus Schorn (Wind River Systems) * Andrew Ferguson (Symbian) + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.internal.core.pdom.dom; @@ -116,7 +117,7 @@ public class PDOMMacro implements IIndexMacro, IPDOMBinding, IASTFileLocation { public PDOM getPDOM() { return fLinkage.getPDOM(); } - + public long getRecord() { return fRecord; } @@ -269,6 +270,14 @@ public class PDOMMacro implements IIndexMacro, IPDOMBinding, IASTFileLocation { return filerec != 0 ? new PDOMFile(fLinkage, filerec) : null; } + public long getFileRecord() throws CoreException { + return fLinkage.getDB().getRecPtr(fRecord + FILE); + } + + void setFile(PDOMFile file) throws CoreException { + fLinkage.getDB().putRecPtr(fRecord + FILE, file != null ? file.getRecord() : 0); + } + public int getEndingLineNumber() { return 0; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMMacroReferenceName.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMMacroReferenceName.java index 60f4b027f68..ccd4fa9c5d6 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMMacroReferenceName.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMMacroReferenceName.java @@ -8,6 +8,7 @@ * Contributors: * QNX - Initial API and implementation * Markus Schorn (Wind River Systems) + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.internal.core.pdom.dom; @@ -21,6 +22,7 @@ import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.internal.core.index.IIndexFragment; import org.eclipse.cdt.internal.core.index.IIndexFragmentBinding; import org.eclipse.cdt.internal.core.index.IIndexFragmentName; +import org.eclipse.cdt.internal.core.pdom.PDOM; import org.eclipse.cdt.internal.core.pdom.db.Database; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; @@ -67,6 +69,10 @@ public final class PDOMMacroReferenceName implements IIndexFragmentName, IASTFil return record; } + public PDOM getPDOM() { + return linkage.getPDOM(); + } + private long getRecField(int offset) throws CoreException { return linkage.getDB().getRecPtr(record + offset); } @@ -110,7 +116,15 @@ public final class PDOMMacroReferenceName implements IIndexFragmentName, IASTFil long filerec = linkage.getDB().getRecPtr(record + FILE_REC_OFFSET); return filerec != 0 ? new PDOMFile(linkage, filerec) : null; } - + + public long getFileRecord() throws CoreException { + return linkage.getDB().getRecPtr(record + FILE_REC_OFFSET); + } + + void setFile(PDOMFile file) throws CoreException { + linkage.getDB().putRecPtr(record + FILE_REC_OFFSET, file != null ? file.getRecord() : 0); + } + PDOMMacroReferenceName getNextInFile() throws CoreException { return getNameField(FILE_NEXT_OFFSET); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMName.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMName.java index 5d2a4518274..7bce580de92 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMName.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMName.java @@ -8,6 +8,7 @@ * Contributors: * QNX - Initial API and implementation * Markus Schorn (Wind River Systems) + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.internal.core.pdom.dom; @@ -22,6 +23,7 @@ import org.eclipse.cdt.core.index.IndexLocationFactory; import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.internal.core.index.IIndexFragment; import org.eclipse.cdt.internal.core.index.IIndexFragmentName; +import org.eclipse.cdt.internal.core.pdom.PDOM; import org.eclipse.cdt.internal.core.pdom.db.Database; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; @@ -121,6 +123,10 @@ public final class PDOMName implements IIndexFragmentName, IASTFileLocation { linkage.getDB().putRecPtr(record + offset, fieldrec); } + public PDOM getPDOM() { + return linkage.getPDOM(); + } + public PDOMBinding getBinding() throws CoreException { long bindingrec = getRecField(BINDING_REC_OFFSET); return linkage.getBinding(bindingrec); @@ -162,6 +168,14 @@ public final class PDOMName implements IIndexFragmentName, IASTFileLocation { return filerec != 0 ? new PDOMFile(linkage, filerec) : null; } + public long getFileRecord() throws CoreException { + return linkage.getDB().getRecPtr(record + FILE_REC_OFFSET); + } + + void setFile(PDOMFile file) throws CoreException { + linkage.getDB().putRecPtr(record + FILE_REC_OFFSET, file != null ? file.getRecord() : 0); + } + public IIndexName getEnclosingDefinition() throws CoreException { long namerec = getEnclosingDefinitionRecord(); return namerec != 0 ? new PDOMName(linkage, namerec) : null; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java index 43a932f73e1..15795a7516f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java @@ -299,7 +299,7 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { if (fromName.isDefinition()) { return true; } - return !pdomBinding.hasDefinition(); + return !getPDOM().hasLastingDefinition(pdomBinding); } return false; } @@ -444,8 +444,8 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { if (!(method instanceof IProblemBinding)) { PDOMBinding pdomBinding= adaptBinding(method); if (pdomBinding == null) { - createBinding(type, method, fileLocalRec); - } else if (!pdomBinding.hasDefinition()) { + pdomBinding = createBinding(type, method, fileLocalRec); + } else if (!getPDOM().hasLastingDefinition(pdomBinding)) { pdomBinding.update(this, method); } }