diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/DBTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/DBTest.java index 8ce32b281e7..cb7f52904ee 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/DBTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/DBTest.java @@ -284,6 +284,16 @@ public class DBTest extends BaseTestCase { assertSignEquals(expected, -biss.compare(aisc, caseSensitive)); assertSignEquals(expected, -biss.compare(a, caseSensitive)); assertSignEquals(expected, -biss.comparePrefix(acs, caseSensitive)); + + if (!caseSensitive && expected != 0) { + assertSignEquals(expected, aiss.compareCompatibleWithIgnoreCase(bcs)); + assertSignEquals(expected, aiss.compareCompatibleWithIgnoreCase(biss)); + assertSignEquals(expected, aiss.compareCompatibleWithIgnoreCase(bisc)); + + assertSignEquals(expected, -biss.compareCompatibleWithIgnoreCase(acs)); + assertSignEquals(expected, -biss.compareCompatibleWithIgnoreCase(aiss)); + assertSignEquals(expected, -biss.compareCompatibleWithIgnoreCase(aisc)); + } } private void assertSignEquals(int a, int b) { diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/GeneratePDOMApplicationTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/GeneratePDOMApplicationTest.java index 3295b3e92c9..87974999174 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/GeneratePDOMApplicationTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/GeneratePDOMApplicationTest.java @@ -6,7 +6,8 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * Andrew Ferguson (Symbian) - Initial implementation + * Andrew Ferguson (Symbian) - Initial implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.pdom.tests; @@ -103,6 +104,7 @@ public class GeneratePDOMApplicationTest extends PDOMTestBase { }); assertTrue(target.exists()); WritablePDOM wpdom= new WritablePDOM(target, new URIRelativeLocationConverter(baseURI), LanguageManager.getInstance().getPDOMLinkageFactoryMappings()); + assertEquals(36, wpdom.getDB().getVersion()); // faked version, remove for CDT 4.1 verifyProject1Content(wpdom); String fid; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/provider/PDOMCache.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/provider/PDOMCache.java index ad8507202c6..382a7a0821b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/provider/PDOMCache.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/provider/PDOMCache.java @@ -6,7 +6,8 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * Andrew Ferguson (Symbian) - Initial implementation + * Andrew Ferguson (Symbian) - Initial implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.index.provider; @@ -74,7 +75,7 @@ class PDOMCache { result.acquireReadLock(); try { - if(result.versionMismatch()) { + if(!result.isSupportedVersion()) { versionMismatch.add(file); String msg= MessageFormat.format(Messages.PDOMCache_VersionTooOld, new Object[] {file}); CCorePlugin.log(msg); 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 4507ff123bb..47fe62dd09c 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,11 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * QNX - Initial API and implementation - * Markus Schorn (Wind River Systems) - * IBM Corporation - * Andrew Ferguson (Symbian) - * Anton Leherbauer (Wind River Systems) + * QNX - Initial API and implementation + * Markus Schorn (Wind River Systems) + * IBM Corporation + * Andrew Ferguson (Symbian) + * Anton Leherbauer (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.pdom; @@ -73,7 +73,9 @@ import org.eclipse.core.runtime.Status; public class PDOM extends PlatformObject implements IIndexFragment, IPDOM { protected Database db; - public static final int VERSION = 36; + public static final int CURRENT_VERSION = 37; + public static final int MIN_SUPPORTED_VERSION= 36; + public static final int MIN_VERSION_TO_WRITE_NESTED_BINDINGS_INDEX= 37; // to be removed in 4.1 // 0 - the beginning of it all // 1 - first change to kick off upgrades // 2 - added file inclusions @@ -111,17 +113,24 @@ public class PDOM extends PlatformObject implements IIndexFragment, IPDOM { // 34 - fix for base classes represented by qualified names (183843) // 35 - add scanner configuration hash-code (62366) // 36 - changed chunk size back to 4K (184892) + // 37 - added index for nested bindings (189811), compatible with version 36. public static final int LINKAGES = Database.DATA_AREA; public static final int FILE_INDEX = Database.DATA_AREA + 4; public static final int PROPERTIES = Database.DATA_AREA + 8; - + public static final int HAS_NESTED_BINDING_BTREES= Database.DATA_AREA + 12; + public static final int END= Database.DATA_AREA + 13; + static { + assert END <= Database.CHUNK_SIZE; + } + // Local caches private BTree fileIndex; private Map fLinkageIDCache = new HashMap(); private File fPath; private IIndexLocationConverter locationConverter; private Map fPDOMLinkageFactoryCache; + private boolean fHasBTreeForNestedBindings; public PDOM(File dbPath, IIndexLocationConverter locationConverter, Map linkageFactoryMappings) throws CoreException { this(dbPath, locationConverter, ChunkCache.getSharedInstance(), linkageFactoryMappings); @@ -144,13 +153,22 @@ public class PDOM extends PlatformObject implements IIndexFragment, IPDOM { fPath= dbPath; final boolean lockDB= db == null || lockCount != 0; - db = new Database(fPath, cache, VERSION, isPermanentlyReadOnly()); + db = new Database(fPath, cache, CURRENT_VERSION, isPermanentlyReadOnly()); fileIndex= null; // holds on to the database, so clear it. db.setLocked(lockDB); int version= db.getVersion(); - if (version == VERSION) { + if (version >= MIN_SUPPORTED_VERSION) { readLinkages(); + fHasBTreeForNestedBindings= db.getByte(HAS_NESTED_BINDING_BTREES) == 1; + + // new PDOM with version ready to write nested bindings index + if (version >= MIN_VERSION_TO_WRITE_NESTED_BINDINGS_INDEX) { + if (!fHasBTreeForNestedBindings && !isPermanentlyReadOnly()) { + fHasBTreeForNestedBindings= true; + db.putByte(HAS_NESTED_BINDING_BTREES, (byte) 1); + } + } } db.setLocked(lockCount != 0); } @@ -159,11 +177,12 @@ public class PDOM extends PlatformObject implements IIndexFragment, IPDOM { return locationConverter; } - public boolean versionMismatch() throws CoreException { - if (db.getVersion() != VERSION) { - return true; - } else - return false; + public boolean isCurrentVersion() throws CoreException { + return db.getVersion() == CURRENT_VERSION; + } + + public boolean isSupportedVersion() throws CoreException { + return db.getVersion() >= MIN_SUPPORTED_VERSION; } public void accept(IPDOMVisitor visitor) throws CoreException { @@ -247,7 +266,9 @@ public class PDOM extends PlatformObject implements IIndexFragment, IPDOM { assert lockCount < 0; // needs write-lock. // Clear out the database, everything is set to zero. - getDB().clear(VERSION); + db.clear(CURRENT_VERSION); + db.putByte(HAS_NESTED_BINDING_BTREES, (byte) 1); + fHasBTreeForNestedBindings= true; clearCaches(); } @@ -713,26 +734,22 @@ public class PDOM extends PlatformObject implements IIndexFragment, IPDOM { PDOMLinkage linkage= (PDOMLinkage) iter.next(); if (filter.acceptLinkage(linkage)) { IBinding[] bindings; - if(filescope) { - BindingCollector visitor = new BindingCollector(linkage, prefix, filter, true, false); - visitor.setMonitor(monitor); - try { - linkage.accept(visitor); + BindingCollector visitor = new BindingCollector(linkage, prefix, filter, true, false); + visitor.setMonitor(monitor); + try { + linkage.accept(visitor); + if (!filescope) { + if (fHasBTreeForNestedBindings) { + linkage.getNestedBindingsIndex().accept(visitor); + } + else { + linkage.accept(new ApplyVisitor(linkage, visitor)); + } } - catch (OperationCanceledException e) { - } - bindings= visitor.getBindings(); - } else { - BindingCollector visitor = new BindingCollector(linkage, prefix, filter, true, false); - visitor.setMonitor(monitor); - try { - linkage.accept(visitor); - linkage.accept(new ApplyVisitor(linkage, visitor)); - } - catch (OperationCanceledException e) { - } - bindings= visitor.getBindings(); } + catch (OperationCanceledException e) { + } + bindings= visitor.getBindings(); for (int j = 0; j < bindings.length; j++) { result.add(bindings[j]); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMIndexerJob.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMIndexerJob.java index 086d08329d6..00d4e5bfb6d 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMIndexerJob.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMIndexerJob.java @@ -46,6 +46,7 @@ public class PDOMIndexerJob extends Job { } protected IStatus run(IProgressMonitor monitor) { + final long start= System.currentTimeMillis(); fMonitor = monitor; String taskName = CCorePlugin.getResourceString("pdom.indexer.task"); //$NON-NLS-1$ monitor.beginTask(taskName, TOTAL_MONITOR_WORK); @@ -97,6 +98,16 @@ public class PDOMIndexerJob extends Job { } } while (currentTask != null); + + // work-around for https://bugs.eclipse.org/bugs/show_bug.cgi?id=197258 + long rest= 100-(System.currentTimeMillis()-start); + if (rest > 0) { + try { + Thread.sleep(rest); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } return Status.OK_STATUS; } catch (RuntimeException e) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMManager.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMManager.java index 9613e9381b3..f89ce2babe5 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMManager.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMManager.java @@ -327,7 +327,7 @@ public class PDOMManager implements IWritableIndexManager, IListener { } WritablePDOM pdom= new WritablePDOM(dbFile, new PDOMProjectIndexLocationConverter(rproject), LanguageManager.getInstance().getPDOMLinkageFactoryMappings()); - if (pdom.versionMismatch() || fromScratch) { + if (!pdom.isSupportedVersion() || fromScratch) { try { pdom.acquireWriteLock(); } catch (InterruptedException e) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/TeamPDOMImportOperation.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/TeamPDOMImportOperation.java index fa03036f143..75a7614a9ae 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/TeamPDOMImportOperation.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/TeamPDOMImportOperation.java @@ -203,7 +203,7 @@ public class TeamPDOMImportOperation implements IWorkspaceRunnable { WritablePDOM pdom= (WritablePDOM) obj; pdom.acquireReadLock(); try { - if (pdom.versionMismatch()) { + if (!pdom.isSupportedVersion()) { throw new CoreException(CCorePlugin.createStatus( NLS.bind(Messages.PDOMImportTask_errorInvalidPDOMVersion, fProject.getElementName()))); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/BTree.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/BTree.java index cb35bb7f6af..6cdb683423d 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/BTree.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/BTree.java @@ -1,14 +1,14 @@ /******************************************************************************* - * Copyright (c) 2005, 2006 QNX Software Systems and others. + * Copyright (c) 2005, 2007 QNX Software Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * QNX - Initial API and implementation - * Andrew Ferguson (Symbian) - Provide B-tree deletion routine - * Markus Schorn (Wind River Systems) + * QNX - Initial API and implementation + * Andrew Ferguson (Symbian) - Provide B-tree deletion routine + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.pdom.db; @@ -47,7 +47,7 @@ public class BTree { } /** - * Contructor. + * Constructor. * * @param db the database containing the btree * @param root offset into database of the pointer to the root node @@ -160,24 +160,34 @@ public class BTree { } } - // search to find the insert point - int i; - for (i = 0; i < MAX_RECORDS; ++i) { - int record1 = getRecord(chunk, node, i); - if (record1 == 0) { - // past the end - break; - } else { - int compare = cmp.compare(record1, record); - if (compare == 0) - // found it, no insert, just return the record - return record; - else if (compare > 0) - // past it - break; - } + // binary search to find the insert point + int lower= 0; + int upper= MAX_RECORDS-1; + while (lower < upper && getRecord(chunk, node, upper-1) == 0) { + upper--; } + while (lower < upper) { + int middle= (lower+upper)/2; + int checkRec= getRecord(chunk, node, middle); + if (checkRec == 0) { + upper= middle; + } + else { + int compare= cmp.compare(checkRec, record); + if (compare > 0) { + upper= middle; + } + else if (compare < 0) { + lower= middle+1; + } + else { + // found it, no insert, just return the record + return record; + } + } + } + final int i= lower; int child = getChild(chunk, node, i); if (child != 0) { // visit the children @@ -472,7 +482,7 @@ public class BTree { * @param src the node to read from * @param srcPos the initial index to read from (inclusive) * @param dst the node to write to - * @param dstPos the intial index to write to (inclusive) + * @param dstPos the initial index to write to (inclusive) * @param length the number of (key,(predecessor)child) nodes to write */ private void nodeContentCopy(BTNode src, int srcPos, BTNode dst, int dstPos, int length) { @@ -538,14 +548,38 @@ public class BTree { try { Chunk chunk = db.getChunk(node); - - int i= 0; + + // binary search to find first record greater or equal + int lower= 0; + int upper= MAX_RECORDS-1; + while (lower < upper && getRecord(chunk, node, upper-1) == 0) { + upper--; + } + while (lower < upper) { + int middle= (lower+upper)/2; + int checkRec= getRecord(chunk, node, middle); + if (checkRec == 0) { + upper= middle; + } + else { + int compare= visitor.compare(checkRec); + if (compare >= 0) { + upper= middle; + } + else { + lower= middle+1; + } + } + } + + // start with first record greater or equal, reuse comparison results. + int i= lower; for (; i < MAX_RECORDS; ++i) { int record = getRecord(chunk, node, i); if (record == 0) break; - int compare = visitor.compare(record); + int compare= visitor.compare(record); if (compare > 0) { // start point is to the left return accept(getChild(chunk, node, i), visitor); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/Database.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/Database.java index 6135b4e1bc1..687b10c7235 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/Database.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/Database.java @@ -6,10 +6,10 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * QNX - Initial API and implementation - * Symbian - Add some non-javadoc implementation notes - * Markus Schorn (Wind River Systems) - * IBM Corporation + * QNX - Initial API and implementation + * Symbian - Add some non-javadoc implementation notes + * Markus Schorn (Wind River Systems) + * IBM Corporation *******************************************************************************/ package org.eclipse.cdt.internal.core.pdom.db; @@ -111,7 +111,7 @@ public class Database { } else { fHeaderChunk.read(); - fVersion= fHeaderChunk.getInt(0); + fVersion= fHeaderChunk.getInt(VERSION_OFFSET); fChunks = new Chunk[nChunksOnDisk]; // chunk[0] is unused. } } catch (IOException e) { @@ -139,7 +139,7 @@ public class Database { public void setVersion(int version) throws CoreException { assert fExclusiveLock; - fHeaderChunk.putInt(0, version); + fHeaderChunk.putInt(VERSION_OFFSET, version); fVersion= version; } @@ -574,7 +574,7 @@ public class Database { if (isComplete) { if (fHeaderChunk.fDirty || fIsMarkedIncomplete) { - fHeaderChunk.putInt(0, fVersion); + fHeaderChunk.putInt(VERSION_OFFSET, fVersion); fHeaderChunk.flush(); fIsMarkedIncomplete= false; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/IString.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/IString.java index c7e485616f8..c4b5b070b5a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/IString.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/IString.java @@ -6,8 +6,9 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * QNX - Initial API and implementation - * Andrew Ferguson (Symbian) + * QNX - Initial API and implementation + * Andrew Ferguson (Symbian) + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.pdom.db; @@ -30,7 +31,7 @@ public interface IString { // strcmp equivalents /** * Compare this IString record and the specified IString record - * @param chars + * @param string * @param caseSensitive whether to compare in a case-sensitive way * @return