1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-01 14:15:23 +02:00

fix for 164019 by Jason Montojo

This commit is contained in:
Chris Recoskie 2006-11-30 15:46:09 +00:00
parent cb6c40b03b
commit da9aa45994
3 changed files with 88 additions and 8 deletions

View file

@ -8,6 +8,7 @@
* Contributors:
* QNX - Initial API and implementation
* Markus Schorn (Wind River Systems)
* IBM Corporation
*******************************************************************************/
package org.eclipse.cdt.internal.core.pdom;
@ -174,7 +175,7 @@ public class PDOM extends PlatformObject implements IIndexFragment, IPDOM {
protected void clear() throws CoreException {
Database db = getDB();
// Clear out the database
db.clear();
db.clear(0);
// Zero out the File Index and Linkages
db.putInt(FILE_INDEX, 0);

View file

@ -8,13 +8,17 @@
* Contributors:
* QNX - Initial API and implementation
* Markus Schorn (Wind River Systems)
* IBM Corporation
*******************************************************************************/
package org.eclipse.cdt.internal.core.pdom.db;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel.MapMode;
import java.util.Set;
import org.eclipse.core.runtime.CoreException;
@ -101,8 +105,21 @@ public class Chunk {
buffer.put(new byte[length]);
}
void free() {
db.toc[index] = null;
/**
* Allow this Chunk to be reclaimed. Objects allocated by thus Chunk
* may be registered with a ReferenceQueue to allow for notification
* on deallocation. References registered with the queue are added to
* the Set references.
*
* @param queue ReferenceQueue to register allocated objects with, or
* null if notification is not required.
* @param references Populated with references which were registered
* with the queue.
*/
void reclaim(ReferenceQueue queue, Set references) {
if (queue != null) {
references.add(new WeakReference(buffer, queue));
}
buffer = null;
}
}

View file

@ -9,12 +9,16 @@
* 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;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.lang.ref.ReferenceQueue;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.core.runtime.CoreException;
@ -106,16 +110,74 @@ public class Database {
* Empty the contents of the Database, make it ready to start again
* @throws CoreException
*/
public void clear() throws CoreException {
public void clear(long timeout) throws CoreException {
// 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);
if (!truncate(timeout)) {
// Truncation timed out so the database size couldn't be changed.
// The best we can do is mark all chunks as unallocated blocks.
// Since the block list grows at the head, add all non-header
// chunks backwards to ensure list of blocks is ordered first
// to last.
for (int block = (toc.length - 1) * CHUNK_SIZE; block > 0; block -= CHUNK_SIZE) {
addBlock(getChunk(block), CHUNK_SIZE, block);
}
}
malloced = freed = 0;
}
/**
* Truncate the database as small as possible to reclaim disk space.
* This method returns false if truncation does not succeed within the
* given timeout period (in milliseconds). A timeout of 0 will cause
* this method to block until the database is successfully truncated.
*
* @param timeout maximum amount of milliseconds to wait before giving up;
* 0 means wait indefinitely.
* @return true if truncation succeeds; false if the operation times out.
* @throws CoreException if an IO error occurs during truncation
*/
private boolean truncate(long timeout) throws CoreException {
// Queue all the chunks to be reclaimed.
ReferenceQueue queue = new ReferenceQueue();
Set references = new HashSet();
for (int i = 0; i < toc.length; i++) {
if (toc[i] != null) {
toc[i].reclaim(queue, references);
toc[i] = null;
}
}
System.gc();
try {
// Wait for each chunk to be reclaimed.
int totalReclaimed = references.size();
while (totalReclaimed > 0) {
queue.remove(timeout);
totalReclaimed--;
}
// Truncate everything but the header chunk.
try {
file.getChannel().truncate(CHUNK_SIZE);
} catch (IOException e) {
throw new CoreException(new DBStatus(e));
}
// Reinitialize header chunk.
toc = new Chunk[] { new Chunk(file, 0) };
return true;
}
catch (InterruptedException e) {
// Truncation took longer than we wanted, so we'll
// reinitialize the header chunk and leave the file
// size alone.
toc[0] = new Chunk(file, 0);
return false;
}
}
/**
* Return the Chunk that contains the given offset.
*