mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-06-07 17:56:01 +02:00
Fix for 194739, safeguard against corrupt indexes.
This commit is contained in:
parent
05c1dee1bc
commit
22d6ac5a83
13 changed files with 363 additions and 255 deletions
|
@ -53,7 +53,7 @@ public class BTreeTests extends BaseTestCase {
|
||||||
protected void init(int degree) throws Exception {
|
protected void init(int degree) throws Exception {
|
||||||
dbFile = File.createTempFile("pdomtest", "db");
|
dbFile = File.createTempFile("pdomtest", "db");
|
||||||
db = new Database(dbFile, new ChunkCache(), 0, false);
|
db = new Database(dbFile, new ChunkCache(), 0, false);
|
||||||
db.setWritable();
|
db.setExclusiveLock();
|
||||||
rootRecord = Database.DATA_AREA;
|
rootRecord = Database.DATA_AREA;
|
||||||
comparator = new BTMockRecordComparator();
|
comparator = new BTMockRecordComparator();
|
||||||
btree = new BTree(db, rootRecord, degree, comparator);
|
btree = new BTree(db, rootRecord, degree, comparator);
|
||||||
|
|
|
@ -38,7 +38,7 @@ public class DBPropertiesTests extends BaseTestCase {
|
||||||
dbLoc = File.createTempFile("test", "db");
|
dbLoc = File.createTempFile("test", "db");
|
||||||
dbLoc.deleteOnExit();
|
dbLoc.deleteOnExit();
|
||||||
db = new Database(dbLoc, new ChunkCache(), 0, false);
|
db = new Database(dbLoc, new ChunkCache(), 0, false);
|
||||||
db.setWritable();
|
db.setExclusiveLock();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void tearDown() throws Exception {
|
protected void tearDown() throws Exception {
|
||||||
|
@ -46,7 +46,6 @@ public class DBPropertiesTests extends BaseTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testBasic() throws CoreException {
|
public void testBasic() throws CoreException {
|
||||||
db.setWritable();
|
|
||||||
DBProperties properties = new DBProperties(db);
|
DBProperties properties = new DBProperties(db);
|
||||||
Properties expected = System.getProperties();
|
Properties expected = System.getProperties();
|
||||||
for(Iterator i = expected.keySet().iterator(); i.hasNext(); ) {
|
for(Iterator i = expected.keySet().iterator(); i.hasNext(); ) {
|
||||||
|
|
|
@ -37,6 +37,7 @@ public class DBTest extends BaseTestCase {
|
||||||
super.setUp();
|
super.setUp();
|
||||||
db = new Database(getTestDir().append(getName()+System.currentTimeMillis()+".dat").toFile(),
|
db = new Database(getTestDir().append(getName()+System.currentTimeMillis()+".dat").toFile(),
|
||||||
new ChunkCache(), 0, false);
|
new ChunkCache(), 0, false);
|
||||||
|
db.setExclusiveLock();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Test suite() {
|
public static Test suite() {
|
||||||
|
@ -65,7 +66,6 @@ public class DBTest extends BaseTestCase {
|
||||||
final int realsize = 42;
|
final int realsize = 42;
|
||||||
final int blocksize = (realsize / Database.MIN_SIZE + 1) * Database.MIN_SIZE;
|
final int blocksize = (realsize / Database.MIN_SIZE + 1) * Database.MIN_SIZE;
|
||||||
|
|
||||||
db.setWritable();
|
|
||||||
int mem = db.malloc(realsize);
|
int mem = db.malloc(realsize);
|
||||||
assertEquals(-blocksize, db.getInt(mem - Database.INT_SIZE));
|
assertEquals(-blocksize, db.getInt(mem - Database.INT_SIZE));
|
||||||
db.free(mem);
|
db.free(mem);
|
||||||
|
@ -102,7 +102,6 @@ public class DBTest extends BaseTestCase {
|
||||||
final int realsize = 42;
|
final int realsize = 42;
|
||||||
final int blocksize = (realsize / Database.MIN_SIZE + 1) * Database.MIN_SIZE;
|
final int blocksize = (realsize / Database.MIN_SIZE + 1) * Database.MIN_SIZE;
|
||||||
|
|
||||||
db.setWritable();
|
|
||||||
int mem1 = db.malloc(realsize);
|
int mem1 = db.malloc(realsize);
|
||||||
int mem2 = db.malloc(realsize);
|
int mem2 = db.malloc(realsize);
|
||||||
db.free(mem1);
|
db.free(mem1);
|
||||||
|
@ -115,7 +114,6 @@ public class DBTest extends BaseTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testSimpleAllocationLifecycle() throws Exception {
|
public void testSimpleAllocationLifecycle() throws Exception {
|
||||||
db.setWritable();
|
|
||||||
int mem1 = db.malloc(42);
|
int mem1 = db.malloc(42);
|
||||||
db.free(mem1);
|
db.free(mem1);
|
||||||
int mem2 = db.malloc(42);
|
int mem2 = db.malloc(42);
|
||||||
|
@ -152,7 +150,7 @@ public class DBTest extends BaseTestCase {
|
||||||
File f = getTestDir().append("testStrings.dat").toFile();
|
File f = getTestDir().append("testStrings.dat").toFile();
|
||||||
f.delete();
|
f.delete();
|
||||||
final Database db = new Database(f, new ChunkCache(), 0, false);
|
final Database db = new Database(f, new ChunkCache(), 0, false);
|
||||||
db.setWritable();
|
db.setExclusiveLock();
|
||||||
|
|
||||||
String[] names = {
|
String[] names = {
|
||||||
"ARLENE",
|
"ARLENE",
|
||||||
|
@ -270,12 +268,10 @@ public class DBTest extends BaseTestCase {
|
||||||
{
|
{
|
||||||
char[] acs = a.toCharArray();
|
char[] acs = a.toCharArray();
|
||||||
char[] bcs = b.toCharArray();
|
char[] bcs = b.toCharArray();
|
||||||
db.setWritable();
|
|
||||||
IString aiss = db.newString(a);
|
IString aiss = db.newString(a);
|
||||||
IString biss = db.newString(b);
|
IString biss = db.newString(b);
|
||||||
IString aisc = db.newString(acs);
|
IString aisc = db.newString(acs);
|
||||||
IString bisc = db.newString(bcs);
|
IString bisc = db.newString(bcs);
|
||||||
db.setReadOnly(true);
|
|
||||||
|
|
||||||
assertSignEquals(expected, aiss.compare(bcs, caseSensitive));
|
assertSignEquals(expected, aiss.compare(bcs, caseSensitive));
|
||||||
assertSignEquals(expected, aiss.compare(biss, caseSensitive));
|
assertSignEquals(expected, aiss.compare(biss, caseSensitive));
|
||||||
|
|
|
@ -105,7 +105,13 @@ public class GeneratePDOMApplicationTest extends PDOMTestBase {
|
||||||
WritablePDOM wpdom= new WritablePDOM(target, new URIRelativeLocationConverter(baseURI), LanguageManager.getInstance().getPDOMLinkageFactoryMappings());
|
WritablePDOM wpdom= new WritablePDOM(target, new URIRelativeLocationConverter(baseURI), LanguageManager.getInstance().getPDOMLinkageFactoryMappings());
|
||||||
verifyProject1Content(wpdom);
|
verifyProject1Content(wpdom);
|
||||||
|
|
||||||
String fid= wpdom.getProperty(IIndexFragment.PROPERTY_FRAGMENT_ID);
|
String fid;
|
||||||
|
wpdom.acquireReadLock();
|
||||||
|
try {
|
||||||
|
fid = wpdom.getProperty(IIndexFragment.PROPERTY_FRAGMENT_ID);
|
||||||
|
} finally {
|
||||||
|
wpdom.releaseReadLock();
|
||||||
|
}
|
||||||
assertNotNull(fid);
|
assertNotNull(fid);
|
||||||
assertTrue(fid.startsWith("export")); // check for default export id
|
assertTrue(fid.startsWith("export")); // check for default export id
|
||||||
}
|
}
|
||||||
|
@ -120,13 +126,17 @@ public class GeneratePDOMApplicationTest extends PDOMTestBase {
|
||||||
WritablePDOM wpdom= new WritablePDOM(target, new URIRelativeLocationConverter(baseURI), LanguageManager.getInstance().getPDOMLinkageFactoryMappings());
|
WritablePDOM wpdom= new WritablePDOM(target, new URIRelativeLocationConverter(baseURI), LanguageManager.getInstance().getPDOMLinkageFactoryMappings());
|
||||||
verifyProject1Content(wpdom);
|
verifyProject1Content(wpdom);
|
||||||
|
|
||||||
|
wpdom.acquireReadLock();
|
||||||
|
try {
|
||||||
String fid = wpdom.getProperty(IIndexFragment.PROPERTY_FRAGMENT_ID);
|
String fid = wpdom.getProperty(IIndexFragment.PROPERTY_FRAGMENT_ID);
|
||||||
assertNotNull(fid);
|
assertNotNull(fid);
|
||||||
assertEquals(ACME_SDK_ID, fid); // check for custom export id
|
assertEquals(ACME_SDK_ID, fid); // check for custom export id
|
||||||
|
|
||||||
String sdkVer = wpdom.getProperty(SDK_VERSION);
|
String sdkVer = wpdom.getProperty(SDK_VERSION);
|
||||||
assertNotNull(sdkVer);
|
assertNotNull(sdkVer);
|
||||||
assertEquals("4.0.1", sdkVer); // check for custom property value
|
assertEquals("4.0.1", sdkVer); // check for custom property value
|
||||||
|
} finally {
|
||||||
|
wpdom.releaseReadLock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testExternalExportProjectProvider_BadCmdLine1() throws Exception {
|
public void testExternalExportProjectProvider_BadCmdLine1() throws Exception {
|
||||||
|
@ -194,10 +204,14 @@ public class GeneratePDOMApplicationTest extends PDOMTestBase {
|
||||||
WritablePDOM wpdom= new WritablePDOM(target, new URIRelativeLocationConverter(baseURI), LanguageManager.getInstance().getPDOMLinkageFactoryMappings());
|
WritablePDOM wpdom= new WritablePDOM(target, new URIRelativeLocationConverter(baseURI), LanguageManager.getInstance().getPDOMLinkageFactoryMappings());
|
||||||
verifyProject1Content(wpdom);
|
verifyProject1Content(wpdom);
|
||||||
|
|
||||||
|
wpdom.acquireReadLock();
|
||||||
|
try {
|
||||||
String fid = wpdom.getProperty(IIndexFragment.PROPERTY_FRAGMENT_ID);
|
String fid = wpdom.getProperty(IIndexFragment.PROPERTY_FRAGMENT_ID);
|
||||||
assertNotNull(fid);
|
assertNotNull(fid);
|
||||||
assertEquals("hello.world", fid); // check for id passed on command-line
|
assertEquals("hello.world", fid); // check for id passed on command-line
|
||||||
|
} finally {
|
||||||
|
wpdom.releaseReadLock();
|
||||||
|
}
|
||||||
assertTrue(stateCount[0] == 2);
|
assertTrue(stateCount[0] == 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,8 +268,15 @@ public class GeneratePDOMApplicationTest extends PDOMTestBase {
|
||||||
};
|
};
|
||||||
|
|
||||||
WritablePDOM wpdom= new WritablePDOM(target, new URIRelativeLocationConverter(baseURI), LanguageManager.getInstance().getPDOMLinkageFactoryMappings());
|
WritablePDOM wpdom= new WritablePDOM(target, new URIRelativeLocationConverter(baseURI), LanguageManager.getInstance().getPDOMLinkageFactoryMappings());
|
||||||
assertEquals(1, wpdom.findBindings(new char[][] {"foo".toCharArray()}, CLinkage, NPM).length);
|
wpdom.acquireReadLock();
|
||||||
assertEquals(0, wpdom.findBindings(new char[][] {"foo".toCharArray()}, CPPLinkage, NPM).length);
|
try {
|
||||||
|
assertEquals(1, wpdom.findBindings(new char[][] { "foo"
|
||||||
|
.toCharArray() }, CLinkage, NPM).length);
|
||||||
|
assertEquals(0, wpdom.findBindings(new char[][] { "foo"
|
||||||
|
.toCharArray() }, CPPLinkage, NPM).length);
|
||||||
|
} finally {
|
||||||
|
wpdom.releaseReadLock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void verifyProject1Content(WritablePDOM wpdom) throws Exception {
|
public void verifyProject1Content(WritablePDOM wpdom) throws Exception {
|
||||||
|
|
|
@ -45,6 +45,7 @@ import org.eclipse.core.resources.IFile;
|
||||||
import org.eclipse.core.resources.IFolder;
|
import org.eclipse.core.resources.IFolder;
|
||||||
import org.eclipse.core.resources.IProject;
|
import org.eclipse.core.resources.IProject;
|
||||||
import org.eclipse.core.resources.IResource;
|
import org.eclipse.core.resources.IResource;
|
||||||
|
import org.eclipse.core.runtime.CoreException;
|
||||||
import org.eclipse.core.runtime.NullProgressMonitor;
|
import org.eclipse.core.runtime.NullProgressMonitor;
|
||||||
import org.eclipse.core.runtime.Platform;
|
import org.eclipse.core.runtime.Platform;
|
||||||
import org.eclipse.core.runtime.content.IContentType;
|
import org.eclipse.core.runtime.content.IContentType;
|
||||||
|
@ -119,7 +120,7 @@ public class PDOMCPPBugsTest extends BaseTestCase {
|
||||||
String id= pdom.getProperty(IIndexFragment.PROPERTY_FRAGMENT_ID);
|
String id= pdom.getProperty(IIndexFragment.PROPERTY_FRAGMENT_ID);
|
||||||
assertNotNull("Exported pdom ID is null", id);
|
assertNotNull("Exported pdom ID is null", id);
|
||||||
|
|
||||||
String id2= ((PDOM)pdomManager.getPDOM(cproject)).getProperty(IIndexFragment.PROPERTY_FRAGMENT_ID);
|
String id2 = getFragmentID(cproject);
|
||||||
assertNotNull("Project pdom ID is null", id2);
|
assertNotNull("Project pdom ID is null", id2);
|
||||||
assertFalse("Project pdom ID equals export PDOM id", id2.equals(id));
|
assertFalse("Project pdom ID equals export PDOM id", id2.equals(id));
|
||||||
|
|
||||||
|
@ -130,7 +131,7 @@ public class PDOMCPPBugsTest extends BaseTestCase {
|
||||||
assertNotNull("Exported pdom ID is null after project reindex", id3);
|
assertNotNull("Exported pdom ID is null after project reindex", id3);
|
||||||
assertEquals("Exported pdom ID hasChanged during reindex", id, id3);
|
assertEquals("Exported pdom ID hasChanged during reindex", id, id3);
|
||||||
|
|
||||||
String id4= ((PDOM)pdomManager.getPDOM(cproject)).getProperty(IIndexFragment.PROPERTY_FRAGMENT_ID);
|
String id4= getFragmentID(cproject);
|
||||||
assertNotNull("Reindexed project pdom ID is null", id4);
|
assertNotNull("Reindexed project pdom ID is null", id4);
|
||||||
assertFalse("Reindexex project pdom ID equals exported pdom ID", id4.equals(id));
|
assertFalse("Reindexex project pdom ID equals exported pdom ID", id4.equals(id));
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -138,6 +139,20 @@ public class PDOMCPPBugsTest extends BaseTestCase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getFragmentID(final ICProject cproject) throws CoreException, InterruptedException {
|
||||||
|
PDOMManager pdomManager= CCoreInternals.getPDOMManager();
|
||||||
|
final PDOM projectPDOM = (PDOM)pdomManager.getPDOM(cproject);
|
||||||
|
String id2;
|
||||||
|
projectPDOM.acquireReadLock();
|
||||||
|
try {
|
||||||
|
id2= (projectPDOM).getProperty(IIndexFragment.PROPERTY_FRAGMENT_ID);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
projectPDOM.releaseReadLock();
|
||||||
|
}
|
||||||
|
return id2;
|
||||||
|
}
|
||||||
|
|
||||||
public void testInterruptingAcquireReadLock() throws Exception {
|
public void testInterruptingAcquireReadLock() throws Exception {
|
||||||
final PDOM pdom= (PDOM) CCoreInternals.getPDOMManager().getPDOM(cproject);
|
final PDOM pdom= (PDOM) CCoreInternals.getPDOMManager().getPDOM(cproject);
|
||||||
final boolean[] ok= {false};
|
final boolean[] ok= {false};
|
||||||
|
|
|
@ -105,6 +105,8 @@ public class PDOMProviderTests extends PDOMTestBase {
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
IIndex index= CCorePlugin.getIndexManager().getIndex(cproject2);
|
IIndex index= CCorePlugin.getIndexManager().getIndex(cproject2);
|
||||||
|
index.acquireReadLock();
|
||||||
|
try {
|
||||||
IBinding[] bindings= index.findBindings("A".toCharArray(), IndexFilter.ALL, NPM);
|
IBinding[] bindings= index.findBindings("A".toCharArray(), IndexFilter.ALL, NPM);
|
||||||
assertEquals(1, bindings.length);
|
assertEquals(1, bindings.length);
|
||||||
bindings= index.findBindingsForPrefix("A".toCharArray(), false, new IndexFilter() {
|
bindings= index.findBindingsForPrefix("A".toCharArray(), false, new IndexFilter() {
|
||||||
|
@ -114,6 +116,10 @@ public class PDOMProviderTests extends PDOMTestBase {
|
||||||
}, null);
|
}, null);
|
||||||
assertEquals(2, bindings.length);
|
assertEquals(2, bindings.length);
|
||||||
}
|
}
|
||||||
|
finally {
|
||||||
|
index.releaseReadLock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void testCommonSDK() throws Exception {
|
public void testCommonSDK() throws Exception {
|
||||||
|
@ -178,6 +184,8 @@ public class PDOMProviderTests extends PDOMTestBase {
|
||||||
|
|
||||||
{
|
{
|
||||||
IIndex index= CCorePlugin.getIndexManager().getIndex(cproject2);
|
IIndex index= CCorePlugin.getIndexManager().getIndex(cproject2);
|
||||||
|
index.acquireReadLock();
|
||||||
|
try {
|
||||||
IBinding[] bindings= index.findBindings("A".toCharArray(), IndexFilter.ALL, NPM);
|
IBinding[] bindings= index.findBindings("A".toCharArray(), IndexFilter.ALL, NPM);
|
||||||
assertEquals(1, bindings.length);
|
assertEquals(1, bindings.length);
|
||||||
assertEquals(1, index.findDefinitions(bindings[0]).length);
|
assertEquals(1, index.findDefinitions(bindings[0]).length);
|
||||||
|
@ -188,9 +196,15 @@ public class PDOMProviderTests extends PDOMTestBase {
|
||||||
}, null);
|
}, null);
|
||||||
assertEquals(2, bindings.length);
|
assertEquals(2, bindings.length);
|
||||||
}
|
}
|
||||||
|
finally {
|
||||||
|
index.releaseReadLock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
IIndex index= CCorePlugin.getIndexManager().getIndex(cproject3);
|
IIndex index= CCorePlugin.getIndexManager().getIndex(cproject3);
|
||||||
|
index.acquireReadLock();
|
||||||
|
try {
|
||||||
IBinding[] bindings= index.findBindings("A".toCharArray(), IndexFilter.ALL, NPM);
|
IBinding[] bindings= index.findBindings("A".toCharArray(), IndexFilter.ALL, NPM);
|
||||||
assertEquals(1, bindings.length);
|
assertEquals(1, bindings.length);
|
||||||
assertEquals(1, index.findDefinitions(bindings[0]).length);
|
assertEquals(1, index.findDefinitions(bindings[0]).length);
|
||||||
|
@ -201,9 +215,15 @@ public class PDOMProviderTests extends PDOMTestBase {
|
||||||
}, null);
|
}, null);
|
||||||
assertEquals(2, bindings.length);
|
assertEquals(2, bindings.length);
|
||||||
}
|
}
|
||||||
|
finally {
|
||||||
|
index.releaseReadLock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
IIndex index= CCorePlugin.getIndexManager().getIndex(new ICProject[]{cproject2, cproject3});
|
IIndex index= CCorePlugin.getIndexManager().getIndex(new ICProject[]{cproject2, cproject3});
|
||||||
|
index.acquireReadLock();
|
||||||
|
try {
|
||||||
IBinding[] bindings= index.findBindings("A".toCharArray(), IndexFilter.ALL, NPM);
|
IBinding[] bindings= index.findBindings("A".toCharArray(), IndexFilter.ALL, NPM);
|
||||||
assertEquals(1, bindings.length);
|
assertEquals(1, bindings.length);
|
||||||
assertEquals(1, index.findDefinitions(bindings[0]).length);
|
assertEquals(1, index.findDefinitions(bindings[0]).length);
|
||||||
|
@ -213,6 +233,10 @@ public class PDOMProviderTests extends PDOMTestBase {
|
||||||
}
|
}
|
||||||
}, null);
|
}, null);
|
||||||
assertEquals(3, bindings.length);
|
assertEquals(3, bindings.length);
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
index.releaseReadLock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,9 +260,9 @@ public class PDOMProviderTests extends PDOMTestBase {
|
||||||
wpdom.acquireWriteLock();
|
wpdom.acquireWriteLock();
|
||||||
try {
|
try {
|
||||||
wpdom.getDB().setVersion(1);
|
wpdom.getDB().setVersion(1);
|
||||||
|
wpdom.close();
|
||||||
} finally {
|
} finally {
|
||||||
wpdom.releaseWriteLock();
|
wpdom.releaseWriteLock();
|
||||||
wpdom.close();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -93,7 +93,7 @@ public class PDOM extends PlatformObject implements IIndexFragment, IPDOM {
|
||||||
// 14 - added timestamps for files (bug 149571)
|
// 14 - added timestamps for files (bug 149571)
|
||||||
// 15 - fixed offsets for pointer types and qualifier types and PDOMCPPVariable (bug 160540).
|
// 15 - fixed offsets for pointer types and qualifier types and PDOMCPPVariable (bug 160540).
|
||||||
// 16 - have PDOMCPPField store type information, and PDOMCPPNamespaceAlias store what it is aliasing
|
// 16 - have PDOMCPPField store type information, and PDOMCPPNamespaceAlias store what it is aliasing
|
||||||
// 17 - use single linked list for names in file, adds a link to enclosing defintion name.
|
// 17 - use single linked list for names in file, adds a link to enclosing definition name.
|
||||||
// 18 - distinction between c-unions and c-structs.
|
// 18 - distinction between c-unions and c-structs.
|
||||||
// 19 - alter representation of paths in the pdom (162172)
|
// 19 - alter representation of paths in the pdom (162172)
|
||||||
// 20 - add pointer to member types, array types, return types for functions
|
// 20 - add pointer to member types, array types, return types for functions
|
||||||
|
@ -105,13 +105,13 @@ public class PDOM extends PlatformObject implements IIndexFragment, IPDOM {
|
||||||
// 26 - add properties storage
|
// 26 - add properties storage
|
||||||
// 27 - templates: classes, functions, limited nesting support, only template type parameters
|
// 27 - templates: classes, functions, limited nesting support, only template type parameters
|
||||||
// 28 - templates: class instance/specialization base classes
|
// 28 - templates: class instance/specialization base classes
|
||||||
// 29 - includes: fixed modelling of unresolved includes (180159)
|
// 29 - includes: fixed modeling of unresolved includes (180159)
|
||||||
// 30 - templates: method/constructor templates, typedef specializations
|
// 30 - templates: method/constructor templates, typedef specializations
|
||||||
// 31 - macros: added file locations
|
// 31 - macros: added file locations
|
||||||
// 32 - support standalone function types (181936)
|
// 32 - support stand-alone function types (181936)
|
||||||
// 33 - templates: constructor instances
|
// 33 - templates: constructor instances
|
||||||
// 34 - fix for base classes represented by qualified names (183843)
|
// 34 - fix for base classes represented by qualified names (183843)
|
||||||
// 35 - add scanner configuration hashcode (62366)
|
// 35 - add scanner configuration hash-code (62366)
|
||||||
// 36 - changed chunk size back to 4K (184892)
|
// 36 - changed chunk size back to 4K (184892)
|
||||||
|
|
||||||
public static final int LINKAGES = Database.DATA_AREA;
|
public static final int LINKAGES = Database.DATA_AREA;
|
||||||
|
@ -144,13 +144,17 @@ public class PDOM extends PlatformObject implements IIndexFragment, IPDOM {
|
||||||
|
|
||||||
private void loadDatabase(File dbPath, ChunkCache cache) throws CoreException {
|
private void loadDatabase(File dbPath, ChunkCache cache) throws CoreException {
|
||||||
fPath= dbPath;
|
fPath= dbPath;
|
||||||
|
final boolean lockDB= db == null || lockCount != 0;
|
||||||
|
|
||||||
db = new Database(fPath, cache, VERSION, isPermanentlyReadOnly());
|
db = new Database(fPath, cache, VERSION, isPermanentlyReadOnly());
|
||||||
fileIndex= null; // holds on to the database, so clear it.
|
fileIndex= null; // holds on to the database, so clear it.
|
||||||
|
|
||||||
|
db.setLocked(lockDB);
|
||||||
int version= db.getVersion();
|
int version= db.getVersion();
|
||||||
if (version == VERSION) {
|
if (version == VERSION) {
|
||||||
readLinkages();
|
readLinkages();
|
||||||
}
|
}
|
||||||
|
db.setLocked(lockCount != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IIndexLocationConverter getLocationConverter() {
|
public IIndexLocationConverter getLocationConverter() {
|
||||||
|
@ -242,32 +246,24 @@ public class PDOM extends PlatformObject implements IIndexFragment, IPDOM {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void clear() throws CoreException {
|
protected void clear() throws CoreException {
|
||||||
Database db = getDB();
|
assert lockCount < 0; // needs write-lock.
|
||||||
// Clear out the database
|
|
||||||
db.clear(1);
|
|
||||||
|
|
||||||
// Zero out the File Index and Linkages
|
// Clear out the database, everything is set to zero.
|
||||||
clearFileIndex();
|
getDB().clear(VERSION);
|
||||||
|
clearCaches();
|
||||||
db.setVersion(VERSION);
|
|
||||||
db.putInt(PROPERTIES, 0);
|
|
||||||
db.putInt(LINKAGES, 0);
|
|
||||||
fLinkageIDCache.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void reloadFromFile(File file) throws CoreException {
|
void reloadFromFile(File file) throws CoreException {
|
||||||
assert lockCount < 0; // must have write lock.
|
assert lockCount < 0; // must have write lock.
|
||||||
File oldFile= fPath;
|
File oldFile= fPath;
|
||||||
fLinkageIDCache.clear();
|
clearCaches();
|
||||||
try {
|
try {
|
||||||
db.close();
|
db.close();
|
||||||
} catch (CoreException e) {
|
} catch (CoreException e) {
|
||||||
CCorePlugin.log(e);
|
CCorePlugin.log(e);
|
||||||
}
|
}
|
||||||
loadDatabase(file, db.getChunkCache());
|
loadDatabase(file, db.getChunkCache());
|
||||||
if(!isPermanentlyReadOnly()) {
|
db.setExclusiveLock();
|
||||||
db.setWritable();
|
|
||||||
}
|
|
||||||
oldFile.delete();
|
oldFile.delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -538,6 +534,7 @@ public class PDOM extends PlatformObject implements IIndexFragment, IPDOM {
|
||||||
--waitingReaders;
|
--waitingReaders;
|
||||||
}
|
}
|
||||||
++lockCount;
|
++lockCount;
|
||||||
|
db.setLocked(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -550,11 +547,10 @@ public class PDOM extends PlatformObject implements IIndexFragment, IPDOM {
|
||||||
--lockCount;
|
--lockCount;
|
||||||
mutex.notifyAll();
|
mutex.notifyAll();
|
||||||
clearCache= lockCount == 0;
|
clearCache= lockCount == 0;
|
||||||
|
db.setLocked(lockCount != 0);
|
||||||
}
|
}
|
||||||
if (clearCache) {
|
if (clearCache) {
|
||||||
synchronized (fResultCache) {
|
clearResultCache();
|
||||||
fResultCache.clear();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -574,6 +570,7 @@ public class PDOM extends PlatformObject implements IIndexFragment, IPDOM {
|
||||||
* @throws IllegalStateException if this PDOM is not writable
|
* @throws IllegalStateException if this PDOM is not writable
|
||||||
*/
|
*/
|
||||||
public void acquireWriteLock(int giveupReadLocks) throws InterruptedException {
|
public void acquireWriteLock(int giveupReadLocks) throws InterruptedException {
|
||||||
|
assert !isPermanentlyReadOnly();
|
||||||
synchronized (mutex) {
|
synchronized (mutex) {
|
||||||
if (giveupReadLocks > 0) {
|
if (giveupReadLocks > 0) {
|
||||||
// give up on read locks
|
// give up on read locks
|
||||||
|
@ -590,7 +587,7 @@ public class PDOM extends PlatformObject implements IIndexFragment, IPDOM {
|
||||||
while (lockCount > giveupReadLocks || waitingReaders > 0)
|
while (lockCount > giveupReadLocks || waitingReaders > 0)
|
||||||
mutex.wait();
|
mutex.wait();
|
||||||
lockCount= -1;
|
lockCount= -1;
|
||||||
db.setWritable();
|
db.setExclusiveLock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -599,11 +596,9 @@ public class PDOM extends PlatformObject implements IIndexFragment, IPDOM {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void releaseWriteLock(int establishReadLocks, boolean flush) {
|
public void releaseWriteLock(int establishReadLocks, boolean flush) {
|
||||||
synchronized(fResultCache) {
|
clearResultCache();
|
||||||
fResultCache.clear();
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
db.setReadOnly(flush);
|
db.giveUpExclusiveLock(flush);
|
||||||
} catch (CoreException e) {
|
} catch (CoreException e) {
|
||||||
CCorePlugin.log(e);
|
CCorePlugin.log(e);
|
||||||
}
|
}
|
||||||
|
@ -613,6 +608,7 @@ public class PDOM extends PlatformObject implements IIndexFragment, IPDOM {
|
||||||
if (lockCount < 0)
|
if (lockCount < 0)
|
||||||
lockCount= establishReadLocks;
|
lockCount= establishReadLocks;
|
||||||
mutex.notifyAll();
|
mutex.notifyAll();
|
||||||
|
db.setLocked(lockCount != 0);
|
||||||
}
|
}
|
||||||
fireChange();
|
fireChange();
|
||||||
}
|
}
|
||||||
|
@ -756,8 +752,20 @@ public class PDOM extends PlatformObject implements IIndexFragment, IPDOM {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void close() throws CoreException {
|
public void close() throws CoreException {
|
||||||
fLinkageIDCache.clear();
|
|
||||||
db.close();
|
db.close();
|
||||||
|
clearCaches();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void clearCaches() {
|
||||||
|
fileIndex= null;
|
||||||
|
fLinkageIDCache.clear();
|
||||||
|
clearResultCache();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void clearResultCache() {
|
||||||
|
synchronized (fResultCache) {
|
||||||
|
fResultCache.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getCacheHits() {
|
public long getCacheHits() {
|
||||||
|
|
|
@ -61,7 +61,6 @@ import org.eclipse.cdt.internal.core.index.IndexerStateEvent;
|
||||||
import org.eclipse.cdt.internal.core.index.provider.IndexProviderManager;
|
import org.eclipse.cdt.internal.core.index.provider.IndexProviderManager;
|
||||||
import org.eclipse.cdt.internal.core.pdom.PDOM.IListener;
|
import org.eclipse.cdt.internal.core.pdom.PDOM.IListener;
|
||||||
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.Database;
|
|
||||||
import org.eclipse.cdt.internal.core.pdom.dom.PDOMProjectIndexLocationConverter;
|
import org.eclipse.cdt.internal.core.pdom.dom.PDOMProjectIndexLocationConverter;
|
||||||
import org.eclipse.cdt.internal.core.pdom.indexer.DeltaAnalyzer;
|
import org.eclipse.cdt.internal.core.pdom.indexer.DeltaAnalyzer;
|
||||||
import org.eclipse.cdt.internal.core.pdom.indexer.IndexerPreferences;
|
import org.eclipse.cdt.internal.core.pdom.indexer.IndexerPreferences;
|
||||||
|
@ -1082,35 +1081,31 @@ public class PDOMManager implements IWritableIndexManager, IListener {
|
||||||
try {
|
try {
|
||||||
// copy it
|
// copy it
|
||||||
PDOM pdom= (PDOM) getPDOM(cproject);
|
PDOM pdom= (PDOM) getPDOM(cproject);
|
||||||
pdom.acquireWriteLock();
|
pdom.acquireReadLock();
|
||||||
|
String oldID= null;
|
||||||
try {
|
try {
|
||||||
|
oldID= pdom.getProperty(IIndexFragment.PROPERTY_FRAGMENT_ID);
|
||||||
pdom.flush();
|
pdom.flush();
|
||||||
Database db= pdom.getDB();
|
|
||||||
FileChannel from= db.getChannel();
|
|
||||||
FileChannel to = new FileOutputStream(targetLocation).getChannel();
|
FileChannel to = new FileOutputStream(targetLocation).getChannel();
|
||||||
from.transferTo(0, from.size(), to);
|
pdom.getDB().transferTo(to);
|
||||||
to.close();
|
to.close();
|
||||||
} finally {
|
} finally {
|
||||||
pdom.releaseWriteLock();
|
pdom.releaseReadLock();
|
||||||
}
|
}
|
||||||
|
|
||||||
// overwrite internal location representations
|
// overwrite internal location representations
|
||||||
final WritablePDOM newPDOM = new WritablePDOM(targetLocation, pdom.getLocationConverter(), LanguageManager.getInstance().getPDOMLinkageFactoryMappings());
|
final WritablePDOM newPDOM = new WritablePDOM(targetLocation, pdom.getLocationConverter(), LanguageManager.getInstance().getPDOMLinkageFactoryMappings());
|
||||||
try {
|
|
||||||
newPDOM.acquireWriteLock();
|
newPDOM.acquireWriteLock();
|
||||||
try {
|
try {
|
||||||
newPDOM.rewriteLocations(newConverter);
|
newPDOM.rewriteLocations(newConverter);
|
||||||
|
|
||||||
// ensure fragment id has a sensible value, in case callee's do not
|
// ensure fragment id has a sensible value, in case callee's do not
|
||||||
// overwrite their own values
|
// overwrite their own values
|
||||||
String oldId= pdom.getProperty(IIndexFragment.PROPERTY_FRAGMENT_ID);
|
newPDOM.setProperty(IIndexFragment.PROPERTY_FRAGMENT_ID, "exported."+oldID); //$NON-NLS-1$
|
||||||
newPDOM.setProperty(IIndexFragment.PROPERTY_FRAGMENT_ID, "exported."+oldId); //$NON-NLS-1$
|
newPDOM.close();
|
||||||
} finally {
|
} finally {
|
||||||
newPDOM.releaseWriteLock();
|
newPDOM.releaseWriteLock();
|
||||||
}
|
}
|
||||||
} finally {
|
|
||||||
newPDOM.close();
|
|
||||||
}
|
|
||||||
} catch(IOException ioe) {
|
} catch(IOException ioe) {
|
||||||
throw new CoreException(CCorePlugin.createStatus(ioe.getMessage()));
|
throw new CoreException(CCorePlugin.createStatus(ioe.getMessage()));
|
||||||
} catch(InterruptedException ie) {
|
} catch(InterruptedException ie) {
|
||||||
|
|
|
@ -97,12 +97,15 @@ public class TeamPDOMExportOperation implements IWorkspaceRunnable {
|
||||||
|
|
||||||
// create checksums
|
// create checksums
|
||||||
PDOM pdom= new PDOM(tmpPDOM, converter, LanguageManager.getInstance().getPDOMLinkageFactoryMappings());
|
PDOM pdom= new PDOM(tmpPDOM, converter, LanguageManager.getInstance().getPDOMLinkageFactoryMappings());
|
||||||
|
pdom.acquireReadLock();
|
||||||
try {
|
try {
|
||||||
monitor.setTaskName(Messages.Checksums_taskComputeChecksums);
|
monitor.setTaskName(Messages.Checksums_taskComputeChecksums);
|
||||||
createChecksums(fProject, pdom, tmpChecksums, subMonitor(monitor, 94));
|
createChecksums(fProject, pdom, tmpChecksums, subMonitor(monitor, 94));
|
||||||
|
pdom.db.setExclusiveLock(); // The tmpPDOM is all ours.
|
||||||
|
pdom.close();
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
pdom.close();
|
pdom.releaseReadLock();
|
||||||
}
|
}
|
||||||
|
|
||||||
// create archive
|
// create archive
|
||||||
|
@ -111,6 +114,9 @@ public class TeamPDOMExportOperation implements IWorkspaceRunnable {
|
||||||
// store preferences
|
// store preferences
|
||||||
monitor.setTaskName(Messages.TeamPDOMExportOperation_taskExportIndex);
|
monitor.setTaskName(Messages.TeamPDOMExportOperation_taskExportIndex);
|
||||||
IndexerPreferences.setIndexImportLocation(fProject.getProject(), fTargetLocation.toString());
|
IndexerPreferences.setIndexImportLocation(fProject.getProject(), fTargetLocation.toString());
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
if (tmpPDOM != null) {
|
if (tmpPDOM != null) {
|
||||||
|
|
|
@ -39,7 +39,7 @@ final class Chunk {
|
||||||
void read() throws CoreException {
|
void read() throws CoreException {
|
||||||
try {
|
try {
|
||||||
final ByteBuffer buf= ByteBuffer.wrap(fBuffer);
|
final ByteBuffer buf= ByteBuffer.wrap(fBuffer);
|
||||||
fDatabase.getChannel().read(buf, fSequenceNumber*Database.CHUNK_SIZE);
|
fDatabase.getFileChannel().read(buf, fSequenceNumber*Database.CHUNK_SIZE);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new CoreException(new DBStatus(e));
|
throw new CoreException(new DBStatus(e));
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,7 @@ final class Chunk {
|
||||||
void flush() throws CoreException {
|
void flush() throws CoreException {
|
||||||
try {
|
try {
|
||||||
final ByteBuffer buf= ByteBuffer.wrap(fBuffer);
|
final ByteBuffer buf= ByteBuffer.wrap(fBuffer);
|
||||||
fDatabase.getChannel().write(buf, fSequenceNumber*Database.CHUNK_SIZE);
|
fDatabase.getFileChannel().write(buf, fSequenceNumber*Database.CHUNK_SIZE);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new CoreException(new DBStatus(e));
|
throw new CoreException(new DBStatus(e));
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ package org.eclipse.cdt.internal.core.pdom.db;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.RandomAccessFile;
|
import java.io.RandomAccessFile;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.channels.FileChannel;
|
import java.nio.channels.FileChannel;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
@ -61,15 +62,19 @@ public class Database {
|
||||||
|
|
||||||
private final File location;
|
private final File location;
|
||||||
private final RandomAccessFile file;
|
private final RandomAccessFile file;
|
||||||
private boolean fWritable= false;
|
private boolean fExclusiveLock= false; // necessary for any write operation
|
||||||
private boolean fPermanentlyReadOnly;
|
private boolean fLocked; // necessary for any operation.
|
||||||
private Chunk[] chunks;
|
private boolean fIsMarkedIncomplete= false;
|
||||||
|
|
||||||
|
private int fVersion;
|
||||||
|
private final Chunk fHeaderChunk;
|
||||||
|
private Chunk[] fChunks;
|
||||||
|
private ChunkCache fCache;
|
||||||
|
|
||||||
private long malloced;
|
private long malloced;
|
||||||
private long freed;
|
private long freed;
|
||||||
private long cacheHits;
|
private long cacheHits;
|
||||||
private long cacheMisses;
|
private long cacheMisses;
|
||||||
private ChunkCache fCache;
|
|
||||||
|
|
||||||
// public for tests only, you shouldn't need these
|
// public for tests only, you shouldn't need these
|
||||||
public static final int VERSION_OFFSET = 0;
|
public static final int VERSION_OFFSET = 0;
|
||||||
|
@ -86,63 +91,69 @@ public class Database {
|
||||||
/**
|
/**
|
||||||
* Construct a new Database object, creating a backing file if necessary.
|
* Construct a new Database object, creating a backing file if necessary.
|
||||||
* @param location the local file path for the database
|
* @param location the local file path for the database
|
||||||
* @param cache the cache to be used optimisation
|
* @param cache the cache to be used optimization
|
||||||
* @param version the version number to store in the database (only applicable for new databases)
|
* @param version the version number to store in the database (only applicable for new databases)
|
||||||
* @param permanentReadOnly whether this Database object will ever need writing to
|
* @param permanentReadOnly whether this Database object will ever need writing to
|
||||||
* @throws CoreException
|
* @throws CoreException
|
||||||
*/
|
*/
|
||||||
public Database(File location, ChunkCache cache, int version, boolean permanentlyReadOnly) throws CoreException {
|
public Database(File location, ChunkCache cache, int version, boolean openReadOnly) throws CoreException {
|
||||||
try {
|
try {
|
||||||
this.location = location;
|
this.location = location;
|
||||||
this.fPermanentlyReadOnly= permanentlyReadOnly;
|
this.file = new RandomAccessFile(location, openReadOnly ? "r" : "rw"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
this.file = new RandomAccessFile(location, permanentlyReadOnly ? "r" : "rw"); //$NON-NLS-1$ //$NON-NLS-2$
|
|
||||||
this.fCache= cache;
|
this.fCache= cache;
|
||||||
|
|
||||||
// Allocate chunk table, make sure we have at least one
|
int nChunks = Math.max(1, (int) (file.length() / CHUNK_SIZE));
|
||||||
long nChunks = file.length() / CHUNK_SIZE;
|
fHeaderChunk= new Chunk(this, 0);
|
||||||
chunks = new Chunk[(int)nChunks];
|
fHeaderChunk.fLocked= true; // never makes it into the cache, needed to satisfy assertions
|
||||||
|
fChunks = new Chunk[nChunks]; // chunk[0] is unused.
|
||||||
if (nChunks == 0) {
|
if (nChunks == 0) {
|
||||||
if(!permanentlyReadOnly) {
|
fVersion= version;
|
||||||
setWritable();
|
|
||||||
}
|
}
|
||||||
createNewChunk();
|
else {
|
||||||
setVersion(version);
|
fHeaderChunk.read();
|
||||||
setReadOnly(true);
|
fVersion= fHeaderChunk.getInt(0);
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new CoreException(new DBStatus(e));
|
throw new CoreException(new DBStatus(e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public FileChannel getChannel() {
|
FileChannel getFileChannel() {
|
||||||
return file.getChannel();
|
return file.getChannel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void transferTo(FileChannel target) throws IOException {
|
||||||
|
assert fLocked;
|
||||||
|
final FileChannel from= file.getChannel();
|
||||||
|
from.transferTo(0, from.size(), target);
|
||||||
|
}
|
||||||
|
|
||||||
public int getVersion() throws CoreException {
|
public int getVersion() throws CoreException {
|
||||||
return getChunk(0).getInt(0);
|
return fVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setVersion(int version) throws CoreException {
|
public void setVersion(int version) throws CoreException {
|
||||||
getChunk(0).putInt(0, version);
|
assert fExclusiveLock;
|
||||||
|
fHeaderChunk.putInt(0, version);
|
||||||
|
fVersion= version;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Empty the contents of the Database, make it ready to start again
|
* Empty the contents of the Database, make it ready to start again
|
||||||
* @throws CoreException
|
* @throws CoreException
|
||||||
*/
|
*/
|
||||||
public void clear(long timeout) throws CoreException {
|
public void clear(int version) throws CoreException {
|
||||||
int version= getVersion();
|
assert fExclusiveLock;
|
||||||
removeChunksFromCache();
|
removeChunksFromCache();
|
||||||
|
|
||||||
|
fVersion= version;
|
||||||
// clear the first chunk.
|
// clear the first chunk.
|
||||||
Chunk header= getChunk(0);
|
fHeaderChunk.clear(0, CHUNK_SIZE);
|
||||||
header.clear(0, CHUNK_SIZE);
|
// chunks have been removed from the cache, so we may just reset the array of chunks.
|
||||||
setVersion(version);
|
fChunks = new Chunk[] {null};
|
||||||
|
|
||||||
// chunks have been removed from the cache, so we are fine here.
|
|
||||||
chunks = new Chunk[] {header};
|
|
||||||
try {
|
try {
|
||||||
getChannel().truncate(CHUNK_SIZE);
|
fHeaderChunk.flush(); // zero out header chunk
|
||||||
|
file.getChannel().truncate(CHUNK_SIZE); // truncate database
|
||||||
}
|
}
|
||||||
catch (IOException e) {
|
catch (IOException e) {
|
||||||
CCorePlugin.log(e);
|
CCorePlugin.log(e);
|
||||||
|
@ -152,11 +163,11 @@ public class Database {
|
||||||
|
|
||||||
private void removeChunksFromCache() {
|
private void removeChunksFromCache() {
|
||||||
synchronized (fCache) {
|
synchronized (fCache) {
|
||||||
for (int i = 0; i < chunks.length; i++) {
|
for (int i=1; i < fChunks.length; i++) {
|
||||||
Chunk chunk= chunks[i];
|
Chunk chunk= fChunks[i];
|
||||||
if (chunk != null) {
|
if (chunk != null) {
|
||||||
fCache.remove(chunk);
|
fCache.remove(chunk);
|
||||||
chunks[i]= null;
|
fChunks[i]= null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -168,34 +179,22 @@ public class Database {
|
||||||
* @throws CoreException
|
* @throws CoreException
|
||||||
*/
|
*/
|
||||||
public Chunk getChunk(int offset) throws CoreException {
|
public Chunk getChunk(int offset) throws CoreException {
|
||||||
int index = offset / CHUNK_SIZE;
|
if (offset < CHUNK_SIZE) {
|
||||||
|
return fHeaderChunk;
|
||||||
// for performance reasons try to find chunk and mark it without
|
|
||||||
// synchronizing. This means that we might pick up a chunk that
|
|
||||||
// has been paged out, which is fine.
|
|
||||||
// Furthermore the hit-flag may not be seen by the clock-algorithm,
|
|
||||||
// which might lead to the eviction of a chunk. With the next
|
|
||||||
// cache failure we are in sync again, though.
|
|
||||||
Chunk chunk = chunks[index];
|
|
||||||
if (chunk != null && (chunk.fLocked || !fWritable)) {
|
|
||||||
chunk.fCacheHitFlag= true;
|
|
||||||
cacheHits++;
|
|
||||||
return chunk;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// here is the safe code that has to be performed if we cannot
|
|
||||||
// get hold of the chunk.
|
|
||||||
synchronized(fCache) {
|
synchronized(fCache) {
|
||||||
chunk= chunks[index];
|
assert fLocked;
|
||||||
|
final int index = offset / CHUNK_SIZE;
|
||||||
|
Chunk chunk= fChunks[index];
|
||||||
if (chunk == null) {
|
if (chunk == null) {
|
||||||
cacheMisses++;
|
cacheMisses++;
|
||||||
chunk = chunks[index] = new Chunk(this, index);
|
chunk = fChunks[index] = new Chunk(this, index);
|
||||||
chunk.read();
|
chunk.read();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
cacheHits++;
|
cacheHits++;
|
||||||
}
|
}
|
||||||
fCache.add(chunk, fWritable);
|
fCache.add(chunk, fExclusiveLock);
|
||||||
return chunk;
|
return chunk;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -207,6 +206,7 @@ public class Database {
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public int malloc(int size) throws CoreException {
|
public int malloc(int size) throws CoreException {
|
||||||
|
assert fExclusiveLock;
|
||||||
if (size > MAX_SIZE)
|
if (size > MAX_SIZE)
|
||||||
// Too Big
|
// Too Big
|
||||||
throw new CoreException(new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, 0,
|
throw new CoreException(new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, 0,
|
||||||
|
@ -254,31 +254,33 @@ public class Database {
|
||||||
}
|
}
|
||||||
|
|
||||||
private int createNewChunk() throws CoreException {
|
private int createNewChunk() throws CoreException {
|
||||||
// prepare new chunk array
|
assert fExclusiveLock;
|
||||||
final int oldLen= chunks.length;
|
synchronized (fCache) {
|
||||||
|
final int oldLen= fChunks.length;
|
||||||
final Chunk chunk= new Chunk(this, oldLen);
|
final Chunk chunk= new Chunk(this, oldLen);
|
||||||
chunk.fDirty= true;
|
chunk.fDirty= true;
|
||||||
|
|
||||||
Chunk[] newchunks = new Chunk[oldLen+1];
|
Chunk[] newchunks = new Chunk[oldLen+1];
|
||||||
// the content of the chunk array may be modified by the cache, so sync it.
|
System.arraycopy(fChunks, 0, newchunks, 0, oldLen);
|
||||||
synchronized (fCache) {
|
|
||||||
System.arraycopy(chunks, 0, newchunks, 0, oldLen);
|
|
||||||
newchunks[oldLen]= chunk;
|
newchunks[oldLen]= chunk;
|
||||||
chunks= newchunks;
|
fChunks= newchunks;
|
||||||
fCache.add(chunk, true);
|
fCache.add(chunk, true);
|
||||||
}
|
|
||||||
return oldLen * CHUNK_SIZE;
|
return oldLen * CHUNK_SIZE;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private int getFirstBlock(int blocksize) throws CoreException {
|
private int getFirstBlock(int blocksize) throws CoreException {
|
||||||
return getChunk(0).getInt((blocksize / MIN_SIZE) * INT_SIZE);
|
assert fLocked;
|
||||||
|
return fHeaderChunk.getInt((blocksize / MIN_SIZE) * INT_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setFirstBlock(int blocksize, int block) throws CoreException {
|
private void setFirstBlock(int blocksize, int block) throws CoreException {
|
||||||
getChunk(0).putInt((blocksize / MIN_SIZE) * INT_SIZE, block);
|
assert fExclusiveLock;
|
||||||
|
fHeaderChunk.putInt((blocksize / MIN_SIZE) * INT_SIZE, block);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeBlock(Chunk chunk, int blocksize, int block) throws CoreException {
|
private void removeBlock(Chunk chunk, int blocksize, int block) throws CoreException {
|
||||||
|
assert fExclusiveLock;
|
||||||
int prevblock = chunk.getInt(block + PREV_OFFSET);
|
int prevblock = chunk.getInt(block + PREV_OFFSET);
|
||||||
int nextblock = chunk.getInt(block + NEXT_OFFSET);
|
int nextblock = chunk.getInt(block + NEXT_OFFSET);
|
||||||
if (prevblock != 0)
|
if (prevblock != 0)
|
||||||
|
@ -291,6 +293,7 @@ public class Database {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addBlock(Chunk chunk, int blocksize, int block) throws CoreException {
|
private void addBlock(Chunk chunk, int blocksize, int block) throws CoreException {
|
||||||
|
assert fExclusiveLock;
|
||||||
// Mark our size
|
// Mark our size
|
||||||
chunk.putInt(block, blocksize);
|
chunk.putInt(block, blocksize);
|
||||||
|
|
||||||
|
@ -309,6 +312,7 @@ public class Database {
|
||||||
* @param offset
|
* @param offset
|
||||||
*/
|
*/
|
||||||
public void free(int offset) throws CoreException {
|
public void free(int offset) throws CoreException {
|
||||||
|
assert fExclusiveLock;
|
||||||
// TODO - look for opportunities to merge blocks
|
// TODO - look for opportunities to merge blocks
|
||||||
int block = offset - 4;
|
int block = offset - 4;
|
||||||
Chunk chunk = getChunk(block);
|
Chunk chunk = getChunk(block);
|
||||||
|
@ -382,15 +386,14 @@ public class Database {
|
||||||
return new ShortString(this, offset);
|
return new ShortString(this, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getChunkCount() {
|
/**
|
||||||
return chunks.length;
|
* For debugging purposes, only.
|
||||||
}
|
*/
|
||||||
|
|
||||||
public void reportFreeBlocks() throws CoreException {
|
public void reportFreeBlocks() throws CoreException {
|
||||||
System.out.println("Allocated size: " + chunks.length * CHUNK_SIZE); //$NON-NLS-1$
|
System.out.println("Allocated size: " + fChunks.length * CHUNK_SIZE); //$NON-NLS-1$
|
||||||
System.out.println("malloc'ed: " + malloced); //$NON-NLS-1$
|
System.out.println("malloc'ed: " + malloced); //$NON-NLS-1$
|
||||||
System.out.println("free'd: " + freed); //$NON-NLS-1$
|
System.out.println("free'd: " + freed); //$NON-NLS-1$
|
||||||
System.out.println("wasted: " + (chunks.length * CHUNK_SIZE - (malloced - freed))); //$NON-NLS-1$
|
System.out.println("wasted: " + (fChunks.length * CHUNK_SIZE - (malloced - freed))); //$NON-NLS-1$
|
||||||
System.out.println("Free blocks"); //$NON-NLS-1$
|
System.out.println("Free blocks"); //$NON-NLS-1$
|
||||||
for (int bs = MIN_SIZE; bs <= CHUNK_SIZE; bs += MIN_SIZE) {
|
for (int bs = MIN_SIZE; bs <= CHUNK_SIZE; bs += MIN_SIZE) {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
@ -412,11 +415,14 @@ public class Database {
|
||||||
* @throws CoreException
|
* @throws CoreException
|
||||||
*/
|
*/
|
||||||
public void close() throws CoreException {
|
public void close() throws CoreException {
|
||||||
setReadOnly(true);
|
assert fExclusiveLock;
|
||||||
|
flush();
|
||||||
removeChunksFromCache();
|
removeChunksFromCache();
|
||||||
|
|
||||||
// chunks have been removed from the cache, so we are fine
|
// chunks have been removed from the cache, so we are fine
|
||||||
chunks= new Chunk[0];
|
fHeaderChunk.clear(0, CHUNK_SIZE);
|
||||||
|
fHeaderChunk.fDirty= false;
|
||||||
|
fChunks= new Chunk[] {null};
|
||||||
try {
|
try {
|
||||||
file.close();
|
file.close();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
@ -436,7 +442,7 @@ public class Database {
|
||||||
*/
|
*/
|
||||||
void releaseChunk(final Chunk chunk) {
|
void releaseChunk(final Chunk chunk) {
|
||||||
if (!chunk.fLocked) {
|
if (!chunk.fLocked) {
|
||||||
chunks[chunk.fSequenceNumber]= null;
|
fChunks[chunk.fSequenceNumber]= null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -449,65 +455,70 @@ public class Database {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Marks this Database as writable. This is used for avoiding some synchronization on chunk fetching. An
|
* Asserts that database is used by one thread exclusively. This is necessary when doing
|
||||||
* exception is thrown if this Database was constructed as a permanently read only Database.
|
* write operations.
|
||||||
* @see Database#Database(File, ChunkCache, int, boolean)
|
|
||||||
* @throw IllegalStateException if called on a permanently read-only database
|
|
||||||
*/
|
*/
|
||||||
public void setWritable() {
|
public void setExclusiveLock() {
|
||||||
if(fPermanentlyReadOnly)
|
fExclusiveLock= true;
|
||||||
throw new IllegalStateException("A Database created as permanent-read-only may not be changed to writable state"); //$NON-NLS-1$
|
fLocked= true;
|
||||||
fWritable= true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setReadOnly(final boolean flush) throws CoreException {
|
public void setLocked(boolean val) {
|
||||||
if (fWritable) {
|
fLocked= val;
|
||||||
fWritable= false;
|
}
|
||||||
|
|
||||||
|
public void giveUpExclusiveLock(final boolean flush) throws CoreException {
|
||||||
|
if (fExclusiveLock) {
|
||||||
|
try {
|
||||||
ArrayList dirtyChunks= new ArrayList();
|
ArrayList dirtyChunks= new ArrayList();
|
||||||
synchronized (fCache) {
|
synchronized (fCache) {
|
||||||
for (int i= chunks.length-1; i >= 0 ; i--) {
|
for (int i= 1; i < fChunks.length; i++) {
|
||||||
Chunk chunk= chunks[i];
|
Chunk chunk= fChunks[i];
|
||||||
if (chunk != null) {
|
if (chunk != null) {
|
||||||
if (chunk.fCacheIndex < 0) {
|
if (chunk.fCacheIndex < 0) {
|
||||||
chunk.fLocked= false;
|
// locked chunk that has been removed from cache.
|
||||||
chunks[i]= null;
|
|
||||||
if (chunk.fDirty) {
|
if (chunk.fDirty) {
|
||||||
dirtyChunks.add(chunk);
|
dirtyChunks.add(chunk); // keep in fChunks until it is flushed.
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
chunk.fLocked= false;
|
||||||
|
fChunks[i]= null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (chunk.fLocked) {
|
else if (chunk.fLocked) {
|
||||||
if (!chunk.fDirty) {
|
// locked chunk, still in cache.
|
||||||
chunk.fLocked= false;
|
if (chunk.fDirty) {
|
||||||
}
|
if (flush) {
|
||||||
else if (flush) {
|
|
||||||
chunk.fLocked= false;
|
|
||||||
dirtyChunks.add(chunk);
|
dirtyChunks.add(chunk);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (flush && chunk.fDirty) {
|
else {
|
||||||
dirtyChunks.add(chunk);
|
chunk.fLocked= false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assert !chunk.fDirty; // dirty chunks must be locked.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// also handles header chunk
|
||||||
if (!dirtyChunks.isEmpty()) {
|
flushAndUnlockChunks(dirtyChunks, flush);
|
||||||
for (Iterator it = dirtyChunks.iterator(); it.hasNext();) {
|
|
||||||
Chunk chunk = (Chunk) it.next();
|
|
||||||
chunk.flush();
|
|
||||||
}
|
}
|
||||||
|
finally {
|
||||||
|
fExclusiveLock= false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void flush() throws CoreException {
|
public void flush() throws CoreException {
|
||||||
if (fWritable) {
|
assert fLocked;
|
||||||
|
if (fExclusiveLock) {
|
||||||
try {
|
try {
|
||||||
setReadOnly(true);
|
giveUpExclusiveLock(true);
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
setWritable();
|
setExclusiveLock();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -515,17 +526,31 @@ public class Database {
|
||||||
// be careful as other readers may access chunks concurrently
|
// be careful as other readers may access chunks concurrently
|
||||||
ArrayList dirtyChunks= new ArrayList();
|
ArrayList dirtyChunks= new ArrayList();
|
||||||
synchronized (fCache) {
|
synchronized (fCache) {
|
||||||
for (int i= chunks.length-1; i >= 0 ; i--) {
|
for (int i= 1; i < fChunks.length ; i++) {
|
||||||
Chunk chunk= chunks[i];
|
Chunk chunk= fChunks[i];
|
||||||
if (chunk != null && chunk.fDirty) {
|
if (chunk != null && chunk.fDirty) {
|
||||||
dirtyChunks.add(chunk);
|
dirtyChunks.add(chunk);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// also handles header chunk
|
||||||
|
flushAndUnlockChunks(dirtyChunks, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void flushAndUnlockChunks(final ArrayList dirtyChunks, boolean isComplete) throws CoreException {
|
||||||
|
assert !Thread.holdsLock(fCache);
|
||||||
|
synchronized(fHeaderChunk) {
|
||||||
|
if (!fHeaderChunk.fDirty) {
|
||||||
|
if (!(isComplete && fIsMarkedIncomplete)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!dirtyChunks.isEmpty()) {
|
if (!dirtyChunks.isEmpty()) {
|
||||||
|
markFileIncomplete();
|
||||||
for (Iterator it = dirtyChunks.iterator(); it.hasNext();) {
|
for (Iterator it = dirtyChunks.iterator(); it.hasNext();) {
|
||||||
Chunk chunk = (Chunk) it.next();
|
Chunk chunk = (Chunk) it.next();
|
||||||
|
if (chunk.fDirty) {
|
||||||
chunk.flush();
|
chunk.flush();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -536,12 +561,34 @@ public class Database {
|
||||||
Chunk chunk = (Chunk) it.next();
|
Chunk chunk = (Chunk) it.next();
|
||||||
chunk.fLocked= false;
|
chunk.fLocked= false;
|
||||||
if (chunk.fCacheIndex < 0) {
|
if (chunk.fCacheIndex < 0) {
|
||||||
chunks[chunk.fSequenceNumber]= null;
|
fChunks[chunk.fSequenceNumber]= null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isComplete) {
|
||||||
|
if (fHeaderChunk.fDirty || fIsMarkedIncomplete) {
|
||||||
|
fHeaderChunk.putInt(0, fVersion);
|
||||||
|
fHeaderChunk.flush();
|
||||||
|
fIsMarkedIncomplete= false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void markFileIncomplete() throws CoreException {
|
||||||
|
if (!fIsMarkedIncomplete) {
|
||||||
|
fIsMarkedIncomplete= true;
|
||||||
|
try {
|
||||||
|
final ByteBuffer buf= ByteBuffer.wrap(new byte[4]);
|
||||||
|
file.getChannel().write(buf, 0);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new CoreException(new DBStatus(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void resetCacheCounters() {
|
public void resetCacheCounters() {
|
||||||
cacheHits= cacheMisses= 0;
|
cacheHits= cacheMisses= 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance;
|
||||||
import org.eclipse.cdt.core.index.IIndexBinding;
|
import org.eclipse.cdt.core.index.IIndexBinding;
|
||||||
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.IIndexFragmentBindingComparator;
|
||||||
import org.eclipse.cdt.internal.core.pdom.PDOM;
|
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.cdt.internal.core.pdom.db.IString;
|
import org.eclipse.cdt.internal.core.pdom.db.IString;
|
||||||
|
@ -289,11 +290,10 @@ public abstract class PDOMBinding extends PDOMNamedNode implements IIndexFragmen
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public int pdomCompareTo(PDOMBinding other) {
|
public int pdomCompareTo(PDOMBinding other) {
|
||||||
PDOMBinding otherBinding = (PDOMBinding) other;
|
int cmp = comparePDOMBindingQNs(this, other);
|
||||||
int cmp = comparePDOMBindingQNs(this, otherBinding);
|
|
||||||
if(cmp==0) {
|
if(cmp==0) {
|
||||||
int t1 = getNodeType();
|
int t1 = getNodeType();
|
||||||
int t2 = otherBinding.getNodeType();
|
int t2 = other.getNodeType();
|
||||||
return t1 < t2 ? -1 : (t1 > t2 ? 1 : 0);
|
return t1 < t2 ? -1 : (t1 > t2 ? 1 : 0);
|
||||||
}
|
}
|
||||||
return cmp;
|
return cmp;
|
||||||
|
|
|
@ -69,7 +69,6 @@ public class GeneratePDOM implements ISafeRunnable {
|
||||||
try {
|
try {
|
||||||
CCoreInternals.getPDOMManager().exportProjectPDOM(cproject, targetLocation, converter);
|
CCoreInternals.getPDOMManager().exportProjectPDOM(cproject, targetLocation, converter);
|
||||||
WritablePDOM exportedPDOM= new WritablePDOM(targetLocation, converter, LanguageManager.getInstance().getPDOMLinkageFactoryMappings());
|
WritablePDOM exportedPDOM= new WritablePDOM(targetLocation, converter, LanguageManager.getInstance().getPDOMLinkageFactoryMappings());
|
||||||
try {
|
|
||||||
exportedPDOM.acquireWriteLock(0);
|
exportedPDOM.acquireWriteLock(0);
|
||||||
try {
|
try {
|
||||||
Map exportProperties= pm.getExportProperties();
|
Map exportProperties= pm.getExportProperties();
|
||||||
|
@ -79,12 +78,10 @@ public class GeneratePDOM implements ISafeRunnable {
|
||||||
exportedPDOM.setProperty((String) entry.getKey(), (String) entry.getValue());
|
exportedPDOM.setProperty((String) entry.getKey(), (String) entry.getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} finally {
|
exportedPDOM.close();
|
||||||
exportedPDOM.releaseWriteLock(0, true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
exportedPDOM.close();
|
exportedPDOM.releaseWriteLock();
|
||||||
}
|
}
|
||||||
} catch(InterruptedException ie) {
|
} catch(InterruptedException ie) {
|
||||||
String msg= MessageFormat.format(Messages.GeneratePDOM_GenericGenerationFailed, new Object[] {ie.getMessage()});
|
String msg= MessageFormat.format(Messages.GeneratePDOM_GenericGenerationFailed, new Object[] {ie.getMessage()});
|
||||||
|
|
Loading…
Add table
Reference in a new issue