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

Yielding of index write lock. Bug 287907.

This commit is contained in:
Sergey Prigogin 2010-01-23 22:42:24 +00:00
parent c3c9c83823
commit 1bb19098d3
19 changed files with 587 additions and 79 deletions

View file

@ -8,6 +8,7 @@
* Contributors: * Contributors:
* Andrew Ferguson (Symbian) - initial API and implementation * Andrew Ferguson (Symbian) - initial API and implementation
* Markus Schorn (Wind River Systems) * Markus Schorn (Wind River Systems)
* Sergey Prigogin (Google)
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.index.tests; package org.eclipse.cdt.internal.index.tests;
@ -123,6 +124,11 @@ public class EmptyIndexFragment implements IIndexFragment {
} }
public void releaseReadLock() {} public void releaseReadLock() {}
public boolean hasWaitingReaders() {
return false;
}
public void resetCacheCounters() {} public void resetCacheCounters() {}
public IIndexFragmentFileSet createFileSet() { public IIndexFragmentFileSet createFileSet() {

View file

@ -9,6 +9,7 @@
* Markus Schorn - initial API and implementation * Markus Schorn - initial API and implementation
* Andrew Ferguson (Symbian) * Andrew Ferguson (Symbian)
* Bryan Wilkinson (QNX) * Bryan Wilkinson (QNX)
* Sergey Prigogin (Google)
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.core.index; package org.eclipse.cdt.core.index;
@ -91,6 +92,12 @@ public interface IIndex {
*/ */
public void releaseReadLock(); public void releaseReadLock();
/**
* @return <code>true</code> 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 * 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 * be used to figure out whether information read from the index is

View file

@ -10,6 +10,7 @@
* Bryan Wilkinson (QNX) * Bryan Wilkinson (QNX)
* Andrew Ferguson (Symbian) * Andrew Ferguson (Symbian)
* Anton Leherbauer (Wind River Systems) * Anton Leherbauer (Wind River Systems)
* Sergey Prigogin (Google)
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.index; package org.eclipse.cdt.internal.core.index;
@ -355,6 +356,15 @@ public class CIndex implements IIndex {
return fReadLock; return fReadLock;
} }
public boolean hasWaitingReaders() {
for (int i= 0; i < fFragments.length; i++) {
if (fFragments[i].hasWaitingReaders()) {
return true;
}
}
return false;
}
public long getLastWriteAccess() { public long getLastWriteAccess() {
long result= 0; long result= 0;
for (int i = 0; i < fFragments.length; i++) { for (int i = 0; i < fFragments.length; i++) {

View file

@ -9,6 +9,7 @@
* Markus Schorn - initial API and implementation * Markus Schorn - initial API and implementation
* Bryan Wilkinson (QNX) * Bryan Wilkinson (QNX)
* Andrew Ferguson (Symbian) * Andrew Ferguson (Symbian)
* Sergey Prigogin (Google)
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.index; package org.eclipse.cdt.internal.core.index;
@ -85,6 +86,10 @@ final public class EmptyCIndex implements IIndex {
public void releaseReadLock() { public void releaseReadLock() {
} }
public boolean hasWaitingReaders() {
return false;
}
public long getLastWriteAccess() { public long getLastWriteAccess() {
return 0; return 0;
} }

View file

@ -9,6 +9,7 @@
* Markus Schorn - initial API and implementation * Markus Schorn - initial API and implementation
* Bryan Wilkinson (QNX) * Bryan Wilkinson (QNX)
* Andrew Ferguson (Symbian) * Andrew Ferguson (Symbian)
* Sergey Prigogin (Google)
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.index; package org.eclipse.cdt.internal.core.index;
@ -190,6 +191,11 @@ public interface IIndexFragment {
*/ */
void releaseReadLock(); void releaseReadLock();
/**
* @return <code>true</code> if there are threads waiting for read locks.
*/
public boolean hasWaitingReaders();
/** /**
* Returns the timestamp of the last modification to the index. * Returns the timestamp of the last modification to the index.
*/ */

View file

@ -8,6 +8,7 @@
* Contributors: * Contributors:
* Markus Schorn - initial API and implementation * Markus Schorn - initial API and implementation
* Andrew Ferguson (Symbian) * Andrew Ferguson (Symbian)
* Sergey Prigogin (Google)
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.index; 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.IIndexFile;
import org.eclipse.cdt.core.index.IIndexFileLocation; import org.eclipse.cdt.core.index.IIndexFileLocation;
import org.eclipse.cdt.internal.core.pdom.ASTFilePathResolver; import org.eclipse.cdt.internal.core.pdom.ASTFilePathResolver;
import org.eclipse.cdt.internal.core.pdom.YieldableIndexLock;
import org.eclipse.core.runtime.CoreException; 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. * 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. * Adds content to the given file.
@ -73,7 +96,7 @@ public interface IWritableIndex extends IIndex {
void setFileContent(IIndexFragmentFile sourceFile, void setFileContent(IIndexFragmentFile sourceFile,
int linkageID, IncludeInformation[] includes, int linkageID, IncludeInformation[] includes,
IASTPreprocessorStatement[] macros, IASTName[][] names, IASTPreprocessorStatement[] macros, IASTName[][] names,
ASTFilePathResolver resolver) throws CoreException; ASTFilePathResolver resolver, YieldableIndexLock lock) throws CoreException, InterruptedException;
/** /**
* Clears the entire index. * Clears the entire index.

View file

@ -8,7 +8,8 @@
* Contributors: * Contributors:
* Markus Schorn - initial API and implementation * Markus Schorn - initial API and implementation
* Andrew Ferguson (Symbian) * Andrew Ferguson (Symbian)
*******************************************************************************/ * Sergey Prigogin (Google)
******************************************************************************/
package org.eclipse.cdt.internal.core.index; 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.core.index.IIndexFileLocation;
import org.eclipse.cdt.internal.core.index.IWritableIndex.IncludeInformation; import org.eclipse.cdt.internal.core.index.IWritableIndex.IncludeInformation;
import org.eclipse.cdt.internal.core.pdom.ASTFilePathResolver; import org.eclipse.cdt.internal.core.pdom.ASTFilePathResolver;
import org.eclipse.cdt.internal.core.pdom.YieldableIndexLock;
import org.eclipse.core.runtime.CoreException; 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. * 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 * @param fileLocation an IIndexFileLocation representing the location of the file.
* @return the existing IIndexFragmentFile for this location, or a newly created one * @return the existing IIndexFragmentFile for this location, or a newly created one.
* @throws CoreException * @throws CoreException
*/ */
IIndexFragmentFile addFile(int linkageID, IIndexFileLocation fileLocation) 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, IIndexFragmentFile addUncommittedFile(int linkageID, IIndexFileLocation fileLocation) throws CoreException;
IncludeInformation[] includes,
IASTPreprocessorStatement[] macros, IASTName[][] names, ASTFilePathResolver resolver) 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. * Acquires a write lock, while giving up a certain amount of read locks.

View file

@ -8,6 +8,7 @@
* Contributors: * Contributors:
* Markus Schorn - initial API and implementation * Markus Schorn - initial API and implementation
* Andrew Ferguson (Symbian) * Andrew Ferguson (Symbian)
* Sergey Prigogin (Google)
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.index; 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.IIndexFile;
import org.eclipse.cdt.core.index.IIndexFileLocation; import org.eclipse.cdt.core.index.IIndexFileLocation;
import org.eclipse.cdt.internal.core.pdom.ASTFilePathResolver; import org.eclipse.cdt.internal.core.pdom.ASTFilePathResolver;
import org.eclipse.cdt.internal.core.pdom.YieldableIndexLock;
import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.CoreException;
public class WritableCIndex extends CIndex implements IWritableIndex { public class WritableCIndex extends CIndex implements IWritableIndex {
@ -50,17 +52,29 @@ public class WritableCIndex extends CIndex implements IWritableIndex {
return fWritableFragment.getFiles(location); return fWritableFragment.getFiles(location);
} }
public IIndexFragmentFile addFile(int linkageID, IIndexFileLocation fileLocation) throws CoreException { public IIndexFragmentFile addFile(int linkageID, IIndexFileLocation location) throws CoreException {
return fWritableFragment.addFile(linkageID, fileLocation); 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) { private boolean isWritableFragment(IIndexFragment frag) {
return frag == fWritableFragment; return frag == fWritableFragment;
} }
public void setFileContent(IIndexFragmentFile file, int linkageID, public void setFileContent(IIndexFragmentFile file, int linkageID, IncludeInformation[] includes,
IncludeInformation[] includes, IASTPreprocessorStatement[] macros, IASTName[][] names, ASTFilePathResolver resolver,
IASTPreprocessorStatement[] macros, IASTName[][] names, ASTFilePathResolver resolver) throws CoreException { YieldableIndexLock lock) throws CoreException, InterruptedException {
IIndexFragment indexFragment = file.getIndexFragment(); IIndexFragment indexFragment = file.getIndexFragment();
if (!isWritableFragment(indexFragment)) { if (!isWritableFragment(indexFragment)) {
assert false : "Attempt to update file of read-only fragment"; //$NON-NLS-1$ 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); ii.fTargetFile= addFile(linkageID, ii.fLocation);
} }
} }
((IWritableIndexFragment) indexFragment).addFileContent(file, includes, macros, names, resolver); ((IWritableIndexFragment) indexFragment).addFileContent(file, includes, macros, names, resolver, lock);
} }
} }

View file

@ -11,6 +11,7 @@
* IBM Corporation * IBM Corporation
* Andrew Ferguson (Symbian) * Andrew Ferguson (Symbian)
* Anton Leherbauer (Wind River Systems) * Anton Leherbauer (Wind River Systems)
* Sergey Prigogin (Google)
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.pdom; package org.eclipse.cdt.internal.core.pdom;
@ -96,6 +97,7 @@ import org.eclipse.core.runtime.Status;
public class PDOM extends PlatformObject implements IPDOM { public class PDOM extends PlatformObject implements IPDOM {
private static final int BLOCKED_WRITE_LOCK_OUTPUT_INTERVAL = 30000; 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_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. 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); PDOMLinkage pdomLinkage= fLinkageIDCache.get(linkageID);
if (pdomLinkage == null) { if (pdomLinkage == null) {
final String linkageName= Linkage.getLinkageName(linkageID); final String linkageName= Linkage.getLinkageName(linkageID);
@ -766,6 +768,7 @@ public class PDOM extends PlatformObject implements IPDOM {
private long timeWriteLockAcquired; private long timeWriteLockAcquired;
public void acquireReadLock() throws InterruptedException { public void acquireReadLock() throws InterruptedException {
long t = sDEBUG_LOCKS ? System.nanoTime() : 0;
synchronized (mutex) { synchronized (mutex) {
++waitingReaders; ++waitingReaders;
try { try {
@ -778,12 +781,15 @@ public class PDOM extends PlatformObject implements IPDOM {
db.setLocked(true); db.setLocked(true);
if (sDEBUG_LOCKS) { 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); incReadLock(fLockDebugging);
} }
} }
} }
public void releaseReadLock() { public void releaseReadLock() {
boolean clearCache= false; boolean clearCache= false;
synchronized (mutex) { synchronized (mutex) {
@ -884,6 +890,12 @@ public class PDOM extends PlatformObject implements IPDOM {
fireChange(event); fireChange(event);
} }
public boolean hasWaitingReaders() {
synchronized (mutex) {
return waitingReaders > 0;
}
}
public long getLastWriteAccess() { public long getLastWriteAccess() {
return lastWriteAccess; return lastWriteAccess;
} }
@ -957,45 +969,67 @@ public class PDOM extends PlatformObject implements IPDOM {
PDOMName name; PDOMName name;
if ((options & FIND_DECLARATIONS) != 0) { if ((options & FIND_DECLARATIONS) != 0) {
for (name= pdomBinding.getFirstDeclaration(); name != null; name= name.getNextInBinding()) { for (name= pdomBinding.getFirstDeclaration(); name != null; name= name.getNextInBinding()) {
if (isCommitted(name)) {
names.add(name); names.add(name);
} }
} }
}
if ((options & FIND_DEFINITIONS) != 0) { if ((options & FIND_DEFINITIONS) != 0) {
for (name = pdomBinding.getFirstDefinition(); name != null; name= name.getNextInBinding()) { for (name = pdomBinding.getFirstDefinition(); name != null; name= name.getNextInBinding()) {
if (isCommitted(name)) {
names.add(name); names.add(name);
} }
} }
}
if ((options & FIND_REFERENCES) != 0) { if ((options & FIND_REFERENCES) != 0) {
for (name = pdomBinding.getFirstReference(); name != null; name= name.getNextInBinding()) { for (name = pdomBinding.getFirstReference(); name != null; name= name.getNextInBinding()) {
if (isCommitted(name)) {
names.add(name); names.add(name);
} }
} }
} }
}
private void findNamesForMyBinding(PDOMMacroContainer container, int options, ArrayList<IIndexFragmentName> names) private void findNamesForMyBinding(PDOMMacroContainer container, int options, ArrayList<IIndexFragmentName> names)
throws CoreException { throws CoreException {
if ((options & FIND_DEFINITIONS) != 0) { if ((options & FIND_DEFINITIONS) != 0) {
for (PDOMMacro macro= container.getFirstDefinition(); macro != null; macro= macro.getNextInContainer()) { for (PDOMMacro macro= container.getFirstDefinition(); macro != null; macro= macro.getNextInContainer()) {
final IIndexFragmentName name = macro.getDefinition(); final IIndexFragmentName name = macro.getDefinition();
if (name != null) { if (name != null && isCommitted(macro)) {
names.add(name); names.add(name);
} }
} }
} }
if ((options & FIND_REFERENCES) != 0) { if ((options & FIND_REFERENCES) != 0) {
for (PDOMMacroReferenceName name = container.getFirstReference(); name != null; name= name.getNextInContainer()) { for (PDOMMacroReferenceName name = container.getFirstReference(); name != null; name= name.getNextInContainer()) {
if (isCommitted(name)) {
names.add(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 { public IIndexFragmentInclude[] findIncludedBy(IIndexFragmentFile file) throws CoreException {
PDOMFile pdomFile= adaptFile(file); PDOMFile pdomFile= adaptFile(file);
if (pdomFile != null) { if (pdomFile != null) {
List<PDOMInclude> result = new ArrayList<PDOMInclude>(); List<PDOMInclude> result = new ArrayList<PDOMInclude>();
for (PDOMInclude i= pdomFile.getFirstIncludedBy(); i != null; i= i.getNextInIncludedBy()) { for (PDOMInclude i= pdomFile.getFirstIncludedBy(); i != null; i= i.getNextInIncludedBy()) {
if (i.getIncludedBy().getTimestamp() > 0) {
result.add(i); result.add(i);
} }
}
return result.toArray(new PDOMInclude[result.size()]); return result.toArray(new PDOMInclude[result.size()]);
} }
return new PDOMInclude[0]; return new PDOMInclude[0];
@ -1198,6 +1232,10 @@ public class PDOM extends PlatformObject implements IPDOM {
return new StringBuilder(name.length + 2).append((char) (record >> 16)).append((char) record).append(name).toString(); 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 { private PDOMBinding[] getCrossLanguageBindings(IBinding binding) throws CoreException {
switch(binding.getLinkage().getLinkageID()) { switch(binding.getLinkage().getLinkageID()) {
case ILinkage.C_LINKAGE_ID: case ILinkage.C_LINKAGE_ID:

View file

@ -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.pdom; 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() { public synchronized void resetCacheCounters() {
if (fDelegate != null) if (fDelegate != null)
fDelegate.resetCacheCounters(); fDelegate.resetCacheCounters();

View file

@ -8,6 +8,7 @@
* Contributors: * Contributors:
* Markus Schorn - initial API and implementation * Markus Schorn - initial API and implementation
* IBM Corporation * IBM Corporation
* Sergey Prigogin (Google)
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.pdom; 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.ICPPTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier;
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.parser.IProblem; import org.eclipse.cdt.core.parser.IProblem;
import org.eclipse.cdt.internal.core.dom.parser.ASTInternal; import org.eclipse.cdt.internal.core.dom.parser.ASTInternal;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding;
@ -68,6 +70,9 @@ import org.eclipse.osgi.util.NLS;
* @since 4.0 * @since 4.0
*/ */
abstract public class PDOMWriter { 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_ALL_REFERENCES= -1;
public static int SKIP_TYPE_REFERENCES= 1; public static int SKIP_TYPE_REFERENCES= 1;
public static int SKIP_MACRO_REFERENCES= 2; public static int SKIP_MACRO_REFERENCES= 2;
@ -200,11 +205,11 @@ abstract public class PDOMWriter {
if (fShowActivity) { if (fShowActivity) {
trace("Indexer: adding " + ifl.getURI()); //$NON-NLS-1$ trace("Indexer: adding " + ifl.getURI()); //$NON-NLS-1$
} }
index.acquireWriteLock(readlockCount);
long start= System.currentTimeMillis();
Throwable th= null; Throwable th= null;
YieldableIndexLock lock = new YieldableIndexLock(index, readlockCount, flushIndex);
lock.acquire();
try { try {
storeFileInIndex(index, ifl, symbolMap, linkageID, configHash, contextIncludes); storeFileInIndex(index, ifl, symbolMap, linkageID, configHash, contextIncludes, lock);
} catch (RuntimeException e) { } catch (RuntimeException e) {
th= e; th= e;
} catch (PDOMNotImplementedError e) { } catch (PDOMNotImplementedError e) {
@ -214,7 +219,7 @@ abstract public class PDOMWriter {
} catch (AssertionError e) { } catch (AssertionError e) {
th= e; th= e;
} finally { } finally {
index.releaseWriteLock(readlockCount, flushIndex); lock.release();
} }
if (th != null) { if (th != null) {
stati.add(createStatus(NLS.bind(Messages.PDOMWriter_errorWhileParsing, stati.add(createStatus(NLS.bind(Messages.PDOMWriter_errorWhileParsing,
@ -223,7 +228,7 @@ abstract public class PDOMWriter {
if (i < ifls.length - 1) { if (i < ifls.length - 1) {
updateFileCount(0, 0, 1); // update header count updateFileCount(0, 0, 1); // update header count
} }
fStatistics.fAddToIndexTime += System.currentTimeMillis() - start; fStatistics.fAddToIndexTime += lock.getCumulativeLockTime();
} }
} }
} }
@ -448,16 +453,38 @@ abstract public class PDOMWriter {
private IIndexFragmentFile storeFileInIndex(IWritableIndex index, IIndexFileLocation location, private IIndexFragmentFile storeFileInIndex(IWritableIndex index, IIndexFileLocation location,
Map<IIndexFileLocation, Symbols> symbolMap, int linkageID, int configHash, Map<IIndexFileLocation, Symbols> symbolMap, int linkageID, int configHash,
Set<IASTPreprocessorIncludeStatement> contextIncludes) throws CoreException { Set<IASTPreprocessorIncludeStatement> contextIncludes, YieldableIndexLock lock)
throws CoreException, InterruptedException {
Set<IIndexFileLocation> clearedContexts= Collections.emptySet(); Set<IIndexFileLocation> clearedContexts= Collections.emptySet();
IIndexFragmentFile file= index.getWritableFile(linkageID, location); 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<IIndexFileLocation>();
for (IIndexInclude include : includedBy) {
clearedContexts.add(include.getIncludedByLocation());
}
}
}
file= index.addUncommittedFile(linkageID, location);
} else {
file= index.getWritableFile(linkageID, location);
if (file != null) { if (file != null) {
clearedContexts= new HashSet<IIndexFileLocation>(); clearedContexts= new HashSet<IIndexFileLocation>();
index.clearFile(file, clearedContexts); index.clearFile(file, clearedContexts);
} else { } else {
file= index.addFile(linkageID, location); file= index.addFile(linkageID, location);
} }
file.setTimestamp(fResolver.getLastModified(location)); file.setTimestamp(timestamp);
}
try {
file.setScannerConfigurationHashcode(configHash); file.setScannerConfigurationHashcode(configHash);
Symbols lists= symbolMap.get(location); Symbols lists= symbolMap.get(location);
if (lists != null) { if (lists != null) {
@ -481,7 +508,15 @@ abstract public class PDOMWriter {
(contextIncludes.contains(include) || clearedContexts.contains(info.fLocation)); (contextIncludes.contains(include) || clearedContexts.contains(info.fLocation));
} }
} }
index.setFileContent(file, linkageID, includeInfos, macros, names, fResolver); index.setFileContent(file, linkageID, includeInfos, macros, names, fResolver,
SEMI_TRANSACTIONAL_UPDATES && ALLOW_LOCK_YIELDING ? lock : null);
}
if (SEMI_TRANSACTIONAL_UPDATES) {
file.setTimestamp(timestamp);
file = index.commitUncommittedFile();
}
} finally {
index.clearUncommittedFile();
} }
return file; return file;
} }

View file

@ -8,6 +8,7 @@
* Contributors: * Contributors:
* Markus Schorn - initial API and implementation * Markus Schorn - initial API and implementation
* Andrew Ferguson (Symbian) * Andrew Ferguson (Symbian)
* Sergey Prigogin (Google)
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.pdom; 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.IIndexFragmentFile;
import org.eclipse.cdt.internal.core.index.IWritableIndexFragment; import org.eclipse.cdt.internal.core.index.IWritableIndexFragment;
import org.eclipse.cdt.internal.core.index.IWritableIndex.IncludeInformation; 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.ChunkCache;
import org.eclipse.cdt.internal.core.pdom.db.DBProperties; 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.db.IBTreeVisitor;
import org.eclipse.cdt.internal.core.pdom.dom.IPDOMLinkageFactory; 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.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; import org.eclipse.core.runtime.CoreException;
public class WritablePDOM extends PDOM implements IWritableIndexFragment { public class WritablePDOM extends PDOM implements IWritableIndexFragment {
private boolean fClearedBecauseOfVersionMismatch= false; private boolean fClearedBecauseOfVersionMismatch= false;
private boolean fCreatedFromScratch= false; private boolean fCreatedFromScratch= false;
private ASTFilePathResolver fPathResolver; private ASTFilePathResolver fPathResolver;
private PDOMFile fileBeingUpdated;
private PDOMFile uncommittedFile;
private IIndexFileLocation uncommittedLocation;
public WritablePDOM(File dbPath, IIndexLocationConverter locationConverter, public WritablePDOM(File dbPath, IIndexLocationConverter locationConverter,
Map<String, IPDOMLinkageFactory> linkageFactoryMappings) throws CoreException { Map<String, IPDOMLinkageFactory> linkageFactoryMappings) throws CoreException {
@ -53,11 +63,57 @@ public class WritablePDOM extends PDOM implements IWritableIndexFragment {
@Override @Override
public IIndexFragmentFile addFile(int linkageID, IIndexFileLocation location) throws CoreException { public IIndexFragmentFile addFile(int linkageID, IIndexFileLocation location) throws CoreException {
if (uncommittedLocation != null && uncommittedLocation.equals(location)) {
return uncommittedFile;
}
return super.addFile(linkageID, location); 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, 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; assert sourceFile.getIndexFragment() == this;
PDOMFile pdomFile = (PDOMFile) sourceFile; PDOMFile pdomFile = (PDOMFile) sourceFile;
@ -66,15 +122,17 @@ public class WritablePDOM extends PDOM implements IWritableIndexFragment {
final ASTFilePathResolver origResolver= fPathResolver; final ASTFilePathResolver origResolver= fPathResolver;
fPathResolver= pathResolver; fPathResolver= pathResolver;
try { try {
pdomFile.addNames(names); pdomFile.addNames(names, lock);
} finally { } finally {
fPathResolver= origResolver; fPathResolver= origResolver;
} }
final IIndexFileLocation location = pdomFile.getLocation(); final IIndexFileLocation location = pdomFile.getLocation();
if (location != null) {
fEvent.fClearedFiles.remove(location); fEvent.fClearedFiles.remove(location);
fEvent.fFilesWritten.add(location); fEvent.fFilesWritten.add(location);
} }
}
public void clearFile(IIndexFragmentFile file, Collection<IIndexFileLocation> contextsRemoved) public void clearFile(IIndexFragmentFile file, Collection<IIndexFileLocation> contextsRemoved)
throws CoreException { throws CoreException {
@ -171,11 +229,47 @@ public class WritablePDOM extends PDOM implements IWritableIndexFragment {
public PDOMFile getFileForASTPath(int linkageID, String astPath) throws CoreException { public PDOMFile getFileForASTPath(int linkageID, String astPath) throws CoreException {
if (fPathResolver != null && astPath != null) { 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; 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) /* (non-Javadoc)
* @see org.eclipse.cdt.internal.core.index.IWritableIndexFragment#getDatabaseSizeBytes() * @see org.eclipse.cdt.internal.core.index.IWritableIndexFragment#getDatabaseSizeBytes()
*/ */

View file

@ -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;
}
}

View file

@ -9,6 +9,7 @@
* QNX - Initial API and implementation * QNX - Initial API and implementation
* Markus Schorn (Wind River Systems) * Markus Schorn (Wind River Systems)
* Andrew Ferguson (Symbian) * Andrew Ferguson (Symbian)
* Sergey Prigogin (Google)
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.pdom.dom; 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.IMacroBinding;
import org.eclipse.cdt.core.dom.ast.IParameter; import org.eclipse.cdt.core.dom.ast.IParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDirective; 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.IIndexFileLocation;
import org.eclipse.cdt.core.index.IIndexInclude; import org.eclipse.cdt.core.index.IIndexInclude;
import org.eclipse.cdt.core.index.IIndexLocationConverter; 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.IndexFileLocation;
import org.eclipse.cdt.internal.core.index.IWritableIndex.IncludeInformation; import org.eclipse.cdt.internal.core.index.IWritableIndex.IncludeInformation;
import org.eclipse.cdt.internal.core.pdom.PDOM; 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.BTree;
import org.eclipse.cdt.internal.core.pdom.db.Database; import org.eclipse.cdt.internal.core.pdom.db.Database;
import org.eclipse.cdt.internal.core.pdom.db.IBTreeComparator; import org.eclipse.cdt.internal.core.pdom.db.IBTreeComparator;
@ -115,6 +118,10 @@ public class PDOMFile implements IIndexFragmentFile {
return record; return record;
} }
public PDOM getPDOM() {
return fLinkage.getPDOM();
}
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (obj == this) if (obj == this)
@ -132,9 +139,112 @@ public class PDOMFile implements IIndexFragmentFile {
} }
/** /**
* Directly changes this record's internal location string. The format * Transfers names, macros and includes from another file to this one and deletes the other file.
* of this string is unspecified in general and is determined by the * @param sourceFile the file to transfer the local bindings from.
* associated IIndexLocationConverter * @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<PDOMMacroReferenceName> mrefs= new ArrayList<PDOMMacroReferenceName>();
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<PDOMName> names= new ArrayList<PDOMName>();
PDOMName name = getFirstName();
for (; name != null; name= name.getNextInFile()) {
names.add(name);
linkage.onDeleteName(name);
}
for (Iterator<PDOMName> 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 * @param internalLocation
* @throws CoreException * @throws CoreException
*/ */
@ -256,7 +366,7 @@ public class PDOMFile implements IIndexFragmentFile {
return fLinkage; return fLinkage;
} }
public void addNames(IASTName[][] names) throws CoreException { public void addNames(IASTName[][] names, YieldableIndexLock lock) throws CoreException, InterruptedException {
assert getFirstName() == null; assert getFirstName() == null;
assert getFirstMacroReference() == null; assert getFirstMacroReference() == null;
final PDOMLinkage linkage= getLinkage(); final PDOMLinkage linkage= getLinkage();
@ -265,6 +375,9 @@ public class PDOMFile implements IIndexFragmentFile {
PDOMMacroReferenceName lastMacroName= null; PDOMMacroReferenceName lastMacroName= null;
for (IASTName[] name : names) { for (IASTName[] name : names) {
if (name[0] != null) { if (name[0] != null) {
if (lock != null) {
lock.yield();
}
PDOMName caller= nameCache.get(name[1]); PDOMName caller= nameCache.get(name[1]);
IIndexFragmentName fname= createPDOMName(linkage, name[0], caller); IIndexFragmentName fname= createPDOMName(linkage, name[0], caller);
if (fname instanceof PDOMName) { if (fname instanceof PDOMName) {
@ -340,7 +453,7 @@ public class PDOMFile implements IIndexFragmentFile {
include.delete(); include.delete();
include = nextInclude; include = nextInclude;
} }
setFirstInclude(include); setFirstInclude(null);
// Delete all the macros in this file // Delete all the macros in this file
PDOMLinkage linkage= getLinkage(); PDOMLinkage linkage= getLinkage();
@ -381,6 +494,15 @@ public class PDOMFile implements IIndexFragmentFile {
setTimestamp(-1); 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 { public void addIncludesTo(IncludeInformation[] includeInfos) throws CoreException {
assert getFirstInclude() == null; assert getFirstInclude() == null;

View file

@ -141,6 +141,11 @@ public class PDOMInclude implements IIndexFragmentInclude {
return rec != 0 ? new PDOMFile(linkage, rec) : null; 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. * 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; 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; long rec = includedBy != null ? includedBy.getRecord() : 0;
linkage.getDB().putRecPtr(record + INCLUDED_BY, rec); linkage.getDB().putRecPtr(record + INCLUDED_BY, rec);
} }

View file

@ -9,6 +9,7 @@
* QNX - Initial API and implementation * QNX - Initial API and implementation
* Markus Schorn (Wind River Systems) * Markus Schorn (Wind River Systems)
* Andrew Ferguson (Symbian) * Andrew Ferguson (Symbian)
* Sergey Prigogin (Google)
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.pdom.dom; package org.eclipse.cdt.internal.core.pdom.dom;
@ -269,6 +270,14 @@ public class PDOMMacro implements IIndexMacro, IPDOMBinding, IASTFileLocation {
return filerec != 0 ? new PDOMFile(fLinkage, filerec) : null; 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() { public int getEndingLineNumber() {
return 0; return 0;
} }

View file

@ -8,6 +8,7 @@
* Contributors: * Contributors:
* QNX - Initial API and implementation * QNX - Initial API and implementation
* Markus Schorn (Wind River Systems) * Markus Schorn (Wind River Systems)
* Sergey Prigogin (Google)
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.pdom.dom; 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.IIndexFragment;
import org.eclipse.cdt.internal.core.index.IIndexFragmentBinding; import org.eclipse.cdt.internal.core.index.IIndexFragmentBinding;
import org.eclipse.cdt.internal.core.index.IIndexFragmentName; 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.cdt.internal.core.pdom.db.Database;
import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IPath;
@ -67,6 +69,10 @@ public final class PDOMMacroReferenceName implements IIndexFragmentName, IASTFil
return record; return record;
} }
public PDOM getPDOM() {
return linkage.getPDOM();
}
private long getRecField(int offset) throws CoreException { private long getRecField(int offset) throws CoreException {
return linkage.getDB().getRecPtr(record + offset); return linkage.getDB().getRecPtr(record + offset);
} }
@ -111,6 +117,14 @@ public final class PDOMMacroReferenceName implements IIndexFragmentName, IASTFil
return filerec != 0 ? new PDOMFile(linkage, filerec) : null; 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 { PDOMMacroReferenceName getNextInFile() throws CoreException {
return getNameField(FILE_NEXT_OFFSET); return getNameField(FILE_NEXT_OFFSET);
} }

View file

@ -8,6 +8,7 @@
* Contributors: * Contributors:
* QNX - Initial API and implementation * QNX - Initial API and implementation
* Markus Schorn (Wind River Systems) * Markus Schorn (Wind River Systems)
* Sergey Prigogin (Google)
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.pdom.dom; 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.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.internal.core.index.IIndexFragment; import org.eclipse.cdt.internal.core.index.IIndexFragment;
import org.eclipse.cdt.internal.core.index.IIndexFragmentName; 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.cdt.internal.core.pdom.db.Database;
import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IPath;
@ -121,6 +123,10 @@ public final class PDOMName implements IIndexFragmentName, IASTFileLocation {
linkage.getDB().putRecPtr(record + offset, fieldrec); linkage.getDB().putRecPtr(record + offset, fieldrec);
} }
public PDOM getPDOM() {
return linkage.getPDOM();
}
public PDOMBinding getBinding() throws CoreException { public PDOMBinding getBinding() throws CoreException {
long bindingrec = getRecField(BINDING_REC_OFFSET); long bindingrec = getRecField(BINDING_REC_OFFSET);
return linkage.getBinding(bindingrec); return linkage.getBinding(bindingrec);
@ -162,6 +168,14 @@ public final class PDOMName implements IIndexFragmentName, IASTFileLocation {
return filerec != 0 ? new PDOMFile(linkage, filerec) : null; 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 { public IIndexName getEnclosingDefinition() throws CoreException {
long namerec = getEnclosingDefinitionRecord(); long namerec = getEnclosingDefinitionRecord();
return namerec != 0 ? new PDOMName(linkage, namerec) : null; return namerec != 0 ? new PDOMName(linkage, namerec) : null;

View file

@ -299,7 +299,7 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants {
if (fromName.isDefinition()) { if (fromName.isDefinition()) {
return true; return true;
} }
return !pdomBinding.hasDefinition(); return !getPDOM().hasLastingDefinition(pdomBinding);
} }
return false; return false;
} }
@ -444,8 +444,8 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants {
if (!(method instanceof IProblemBinding)) { if (!(method instanceof IProblemBinding)) {
PDOMBinding pdomBinding= adaptBinding(method); PDOMBinding pdomBinding= adaptBinding(method);
if (pdomBinding == null) { if (pdomBinding == null) {
createBinding(type, method, fileLocalRec); pdomBinding = createBinding(type, method, fileLocalRec);
} else if (!pdomBinding.hasDefinition()) { } else if (!getPDOM().hasLastingDefinition(pdomBinding)) {
pdomBinding.update(this, method); pdomBinding.update(this, method);
} }
} }