mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-23 17:05:26 +02:00
Bug 145415 - Made sure we deleted all the info associated with the macro, not just the macro. Also found latent bugs like BTree records not allocating enough memory for themselves (hidden by the block size), and goofy behavior when the PDOM was cleared which I'm sure lead to the truncated chunks not getting reused in certain situations.
This commit is contained in:
parent
21f564232c
commit
2372381692
9 changed files with 81 additions and 27 deletions
|
@ -165,9 +165,14 @@ public class PDOM extends PlatformObject
|
|||
|
||||
public void clear() throws CoreException {
|
||||
Database db = getDB();
|
||||
// Clear out the database
|
||||
db.clear();
|
||||
db.setVersion(VERSION);
|
||||
|
||||
// Zero out the File Index and Linkages
|
||||
db.putInt(FILE_INDEX, 0);
|
||||
fileIndex = null;
|
||||
|
||||
db.putInt(LINKAGES, 0);
|
||||
linkageCache.clear();
|
||||
}
|
||||
|
||||
|
|
|
@ -173,7 +173,7 @@ public class BTree {
|
|||
}
|
||||
|
||||
private int allocateNode() throws CoreException {
|
||||
return db.malloc((2 * NUM_RECORDS - 1) * Database.INT_SIZE);
|
||||
return db.malloc((2 * NUM_RECORDS + 1) * Database.INT_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -27,6 +27,9 @@ public class Database {
|
|||
private final RandomAccessFile file;
|
||||
Chunk[] toc;
|
||||
|
||||
private long malloced;
|
||||
private long freed;
|
||||
|
||||
// public for tests only, you shouldn't need these
|
||||
public static final int VERSION_OFFSET = 0;
|
||||
public static final int CHUNK_SIZE = 1024 * 16;
|
||||
|
@ -46,31 +49,18 @@ public class Database {
|
|||
// Allocate chunk table, make sure we have at least one
|
||||
long nChunks = file.length() / CHUNK_SIZE;
|
||||
if (nChunks == 0) {
|
||||
create();
|
||||
file.seek(0);
|
||||
file.write(new byte[CHUNK_SIZE]); // the header chunk
|
||||
++nChunks;
|
||||
}
|
||||
|
||||
toc = new Chunk[(int)nChunks];
|
||||
init();
|
||||
toc[0] = new Chunk(file, 0);
|
||||
} catch (IOException e) {
|
||||
throw new CoreException(new DBStatus(e));
|
||||
}
|
||||
}
|
||||
|
||||
private void create() throws CoreException {
|
||||
try {
|
||||
file.seek(0);
|
||||
file.write(new byte[CHUNK_SIZE]); // the header chunk
|
||||
} catch (IOException e) {
|
||||
throw new CoreException(new DBStatus(e));
|
||||
}
|
||||
}
|
||||
|
||||
private void init() throws CoreException {
|
||||
// Load in the magic chunk zero
|
||||
toc[0] = new Chunk(file, 0);
|
||||
}
|
||||
|
||||
public int getVersion() {
|
||||
return toc[0].getInt(0);
|
||||
}
|
||||
|
@ -84,11 +74,13 @@ public class Database {
|
|||
* @throws CoreException
|
||||
*/
|
||||
public void clear() throws CoreException {
|
||||
int version = toc[0].getInt(0);
|
||||
create();
|
||||
toc = new Chunk[1];
|
||||
init();
|
||||
setVersion(version);
|
||||
// Clear out the memory headers
|
||||
toc[0].clear(4, DATA_AREA - 4);
|
||||
// Add the remainder of the chunks backwards
|
||||
for (int block = (toc.length - 1) * CHUNK_SIZE; block > 0; block -= CHUNK_SIZE) {
|
||||
addBlock(getChunk(block), CHUNK_SIZE, block);
|
||||
}
|
||||
malloced = freed = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -153,8 +145,12 @@ public class Database {
|
|||
|
||||
// Make our size negative to show in use
|
||||
chunk.putInt(freeblock, - matchsize);
|
||||
|
||||
return freeblock + INT_SIZE;
|
||||
|
||||
// Clear out the block, lots of people are expecting this
|
||||
chunk.clear(freeblock + 4, size);
|
||||
|
||||
malloced += matchsize;
|
||||
return freeblock + 4;
|
||||
}
|
||||
|
||||
private int createChunk() throws CoreException {
|
||||
|
@ -219,8 +215,8 @@ public class Database {
|
|||
if (blocksize < 0)
|
||||
// already freed
|
||||
throw new CoreException(new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, 0, "Already Freed", new Exception()));
|
||||
chunk.clear(offset, blocksize - 4);
|
||||
addBlock(chunk, blocksize, block);
|
||||
freed += blocksize;
|
||||
}
|
||||
|
||||
public void putByte(int offset, byte value) throws CoreException {
|
||||
|
@ -279,4 +275,21 @@ public class Database {
|
|||
return toc.length;
|
||||
}
|
||||
|
||||
public void reportFreeBlocks() throws CoreException {
|
||||
System.out.println("Allocated size: " + toc.length * CHUNK_SIZE);
|
||||
System.out.println("malloc'ed: " + malloced);
|
||||
System.out.println("free'd: " + freed);
|
||||
System.out.println("wasted: " + (toc.length * CHUNK_SIZE - (malloced - freed)));
|
||||
System.out.println("Free blocks");
|
||||
for (int bs = MIN_SIZE; bs <= CHUNK_SIZE; bs += MIN_SIZE) {
|
||||
int count = 0;
|
||||
int block = getFirstBlock(bs);
|
||||
while (block != 0) {
|
||||
++count;
|
||||
block = getInt(block + NEXT_OFFSET);
|
||||
}
|
||||
if (count != 0)
|
||||
System.out.println("Block size: " + bs + "=" + count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,4 +32,5 @@ public interface IString {
|
|||
public char[] getChars() throws CoreException;
|
||||
public String getString() throws CoreException;
|
||||
|
||||
public void delete() throws CoreException;
|
||||
}
|
||||
|
|
|
@ -103,6 +103,23 @@ public class LongString implements IString {
|
|||
return record1;
|
||||
}
|
||||
|
||||
public void delete() throws CoreException {
|
||||
int length = db.getInt(record1 + LENGTH) - NUM_CHARS1;
|
||||
int nextRecord = db.getInt(record1 + NEXT1);
|
||||
db.free(record1);
|
||||
|
||||
// Middle records
|
||||
while (length > NUM_CHARSN) {
|
||||
length -= NUM_CHARSN;
|
||||
int nextnext = db.getInt(nextRecord + NEXTN);
|
||||
db.free(nextRecord);
|
||||
nextRecord = nextnext;
|
||||
}
|
||||
|
||||
// Last record
|
||||
db.free(nextRecord);
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
throw new PDOMNotImplementedError();
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ public class ShortString implements IString {
|
|||
this.record = db.malloc(CHARS + string.length() * 2);
|
||||
|
||||
Chunk chunk = db.getChunk(record);
|
||||
chunk.putInt(record + LENGTH, (char)string.length());
|
||||
chunk.putInt(record + LENGTH, string.length());
|
||||
int n = string.length();
|
||||
int p = record + CHARS;
|
||||
for (int i = 0; i < n; ++i) {
|
||||
|
@ -66,6 +66,10 @@ public class ShortString implements IString {
|
|||
return record;
|
||||
}
|
||||
|
||||
public void delete() throws CoreException {
|
||||
db.free(record);
|
||||
}
|
||||
|
||||
public char[] getChars() throws CoreException {
|
||||
Chunk chunk = db.getChunk(record);
|
||||
int length = chunk.getInt(record + LENGTH);
|
||||
|
|
|
@ -77,6 +77,11 @@ public class PDOMMacro {
|
|||
}
|
||||
|
||||
public void delete() throws CoreException {
|
||||
getName().delete();
|
||||
getExpansion().delete();
|
||||
PDOMMacroParameter param = getFirstParameter();
|
||||
if (param != null)
|
||||
param.delete();
|
||||
pdom.getDB().free(record);
|
||||
}
|
||||
|
||||
|
|
|
@ -49,6 +49,14 @@ public class PDOMMacroParameter {
|
|||
return record;
|
||||
}
|
||||
|
||||
public void delete() throws CoreException {
|
||||
PDOMMacroParameter next = getNextParameter();
|
||||
if (next != null)
|
||||
next.delete();
|
||||
getName().delete();
|
||||
pdom.getDB().free(record);
|
||||
}
|
||||
|
||||
public void setNextParameter(PDOMMacroParameter next) throws CoreException {
|
||||
int rec = next != null ? next.getRecord() : 0;
|
||||
pdom.getDB().putInt(record + NEXT, rec);
|
||||
|
|
|
@ -63,6 +63,7 @@ public class CountNodeAction extends IndexAction {
|
|||
|
||||
ICProject project = (ICProject)objs[i];
|
||||
final PDOM pdom = (PDOM)CCorePlugin.getPDOMManager().getPDOM(project);
|
||||
//pdom.getDB().reportFreeBlocks();
|
||||
|
||||
pdom.getFileIndex().accept(new IBTreeVisitor() {
|
||||
public int compare(int record) throws CoreException {
|
||||
|
|
Loading…
Add table
Reference in a new issue