Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarkus Schorn2007-06-21 12:44:40 +0000
committerMarkus Schorn2007-06-21 12:44:40 +0000
commit3bad87738f130cb216f5b01fab5dfdc60be52880 (patch)
tree9fdbf8a3bd01f2aac55a6a62c197ed32f014f020
parenta86a73a2e2d8e9bfcc27f7b417ab469b3d218949 (diff)
downloadorg.eclipse.cdt-3bad87738f130cb216f5b01fab5dfdc60be52880.tar.gz
org.eclipse.cdt-3bad87738f130cb216f5b01fab5dfdc60be52880.tar.xz
org.eclipse.cdt-3bad87738f130cb216f5b01fab5dfdc60be52880.zip
Fix for 193505, Unprotected read-operations can corrupt the index.
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/Chunk.java110
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/Database.java26
-rw-r--r--core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/indexview/IndexView.java21
3 files changed, 104 insertions, 53 deletions
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/Chunk.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/Chunk.java
index ef28bed112c..def665109b6 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/Chunk.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/Chunk.java
@@ -21,7 +21,7 @@ import org.eclipse.core.runtime.CoreException;
* Caches the content of a piece of the database.
*/
final class Chunk {
- final private ByteBuffer fBuffer;
+ final private byte[] fBuffer= new byte[Database.CHUNK_SIZE];
final Database fDatabase;
final int fSequenceNumber;
@@ -33,14 +33,13 @@ final class Chunk {
Chunk(Database db, int sequenceNumber) {
fDatabase= db;
- fBuffer= ByteBuffer.allocate(Database.CHUNK_SIZE);
fSequenceNumber= sequenceNumber;
}
void read() throws CoreException {
try {
- fBuffer.position(0);
- fDatabase.getChannel().read(fBuffer, fSequenceNumber*Database.CHUNK_SIZE);
+ final ByteBuffer buf= ByteBuffer.wrap(fBuffer);
+ fDatabase.getChannel().read(buf, fSequenceNumber*Database.CHUNK_SIZE);
} catch (IOException e) {
throw new CoreException(new DBStatus(e));
}
@@ -48,87 +47,120 @@ final class Chunk {
void flush() throws CoreException {
try {
- fBuffer.position(0);
- fDatabase.getChannel().write(fBuffer, fSequenceNumber*Database.CHUNK_SIZE);
+ final ByteBuffer buf= ByteBuffer.wrap(fBuffer);
+ fDatabase.getChannel().write(buf, fSequenceNumber*Database.CHUNK_SIZE);
} catch (IOException e) {
throw new CoreException(new DBStatus(e));
}
fDirty= false;
}
- public void putByte(int offset, byte value) {
+ public void putByte(final int offset, final byte value) {
assert fLocked;
fDirty= true;
- fBuffer.put(offset % Database.CHUNK_SIZE, value);
+ fBuffer[offset % Database.CHUNK_SIZE]= value;
}
- public byte getByte(int offset) {
- return fBuffer.get(offset % Database.CHUNK_SIZE);
+ public byte getByte(final int offset) {
+ return fBuffer[offset % Database.CHUNK_SIZE];
}
- public byte[] getBytes(int offset, int length) {
- byte[] bytes = new byte[length];
- fBuffer.position(offset % Database.CHUNK_SIZE);
- fBuffer.get(bytes, 0, length);
+ public byte[] getBytes(final int offset, final int length) {
+ final byte[] bytes = new byte[length];
+ System.arraycopy(fBuffer, offset % Database.CHUNK_SIZE, bytes, 0, length);
return bytes;
}
- public void putBytes(int offset, byte[] bytes) {
+ public void putBytes(final int offset, final byte[] bytes) {
assert fLocked;
fDirty= true;
- fBuffer.position(offset % Database.CHUNK_SIZE);
- fBuffer.put(bytes, 0, bytes.length);
+ System.arraycopy(bytes, 0, fBuffer, offset % Database.CHUNK_SIZE, bytes.length);
}
- public void putInt(int offset, int value) {
+ public void putInt(final int offset, final int value) {
assert fLocked;
fDirty= true;
- fBuffer.putInt(offset % Database.CHUNK_SIZE, value);
+ int idx= offset % Database.CHUNK_SIZE;
+ fBuffer[idx]= (byte)(value >> 24);
+ fBuffer[++idx]= (byte)(value >> 16);
+ fBuffer[++idx]= (byte)(value >> 8);
+ fBuffer[++idx]= (byte)(value);
}
- public int getInt(int offset) {
- return fBuffer.getInt(offset % Database.CHUNK_SIZE);
+ public int getInt(final int offset) {
+ int idx= offset % Database.CHUNK_SIZE;
+ return ((fBuffer[idx] & 0xff) << 24) |
+ ((fBuffer[++idx] & 0xff) << 16) |
+ ((fBuffer[++idx] & 0xff) << 8) |
+ ((fBuffer[++idx] & 0xff) << 0);
}
- public void putShort(int offset, short value) {
+ public void putShort(final int offset, final short value) {
assert fLocked;
fDirty= true;
- fBuffer.putShort(offset % Database.CHUNK_SIZE, value);
+ int idx= offset % Database.CHUNK_SIZE;
+ fBuffer[idx]= (byte)(value >> 8);
+ fBuffer[++idx]= (byte)(value);
}
- public short getShort(int offset) {
- return fBuffer.getShort(offset % Database.CHUNK_SIZE);
+ public short getShort(final int offset) {
+ int idx= offset % Database.CHUNK_SIZE;
+ return (short) (((fBuffer[idx] << 8) | (fBuffer[++idx] & 0xff)));
}
- public long getLong(int offset) {
- return fBuffer.getLong(offset % Database.CHUNK_SIZE);
+ public long getLong(final int offset) {
+ int idx= offset % Database.CHUNK_SIZE;
+ return ((((long)fBuffer[idx] & 0xff) << 56) |
+ (((long)fBuffer[++idx] & 0xff) << 48) |
+ (((long)fBuffer[++idx] & 0xff) << 40) |
+ (((long)fBuffer[++idx] & 0xff) << 32) |
+ (((long)fBuffer[++idx] & 0xff) << 24) |
+ (((long)fBuffer[++idx] & 0xff) << 16) |
+ (((long)fBuffer[++idx] & 0xff) << 8) |
+ (((long)fBuffer[++idx] & 0xff) << 0));
}
- public void putLong(int offset, long value) {
+ public void putLong(final int offset, final long value) {
assert fLocked;
fDirty= true;
- fBuffer.putLong(offset % Database.CHUNK_SIZE, value);
+ int idx= offset % Database.CHUNK_SIZE;
+
+ fBuffer[idx]= (byte)(value >> 56);
+ fBuffer[++idx]= (byte)(value >> 48);
+ fBuffer[++idx]= (byte)(value >> 40);
+ fBuffer[++idx]= (byte)(value >> 32);
+ fBuffer[++idx]= (byte)(value >> 24);
+ fBuffer[++idx]= (byte)(value >> 16);
+ fBuffer[++idx]= (byte)(value >> 8);
+ fBuffer[++idx]= (byte)(value);
}
- public void putChar(int offset, char value) {
+ public void putChar(final int offset, final char value) {
assert fLocked;
fDirty= true;
- fBuffer.putChar(offset % Database.CHUNK_SIZE, value);
+ int idx= offset % Database.CHUNK_SIZE;
+ fBuffer[idx]= (byte)(value >> 8);
+ fBuffer[++idx]= (byte)(value);
}
- public char getChar(int offset) {
- return fBuffer.getChar(offset % Database.CHUNK_SIZE);
+ public char getChar(final int offset) {
+ int idx= offset % Database.CHUNK_SIZE;
+ return (char) (((fBuffer[idx] << 8) | (fBuffer[++idx] & 0xff)));
}
- public void getCharArray(int offset, char[] result) {
- fBuffer.position(offset % Database.CHUNK_SIZE);
- fBuffer.asCharBuffer().get(result);
+ public void getCharArray(final int offset, final char[] result) {
+ final ByteBuffer buf= ByteBuffer.wrap(fBuffer);
+ buf.position(offset % Database.CHUNK_SIZE);
+ buf.asCharBuffer().get(result);
}
- void clear(int offset, int length) {
+ void clear(final int offset, final int length) {
assert fLocked;
fDirty= true;
- fBuffer.position(offset % Database.CHUNK_SIZE);
- fBuffer.put(new byte[length]);
+ int idx= (offset % Database.CHUNK_SIZE);
+ final int end= idx + length;
+ for (; idx < end; idx++) {
+ fBuffer[idx]= 0;
+ }
}
}
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 859332df2e3..5a11f93cc27 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
@@ -138,6 +138,8 @@ public class Database {
Chunk header= getChunk(0);
header.clear(0, CHUNK_SIZE);
setVersion(version);
+
+ // chunks have been removed from the cache, so we are fine here.
chunks = new Chunk[] {header};
try {
getChannel().truncate(CHUNK_SIZE);
@@ -252,16 +254,20 @@ public class Database {
}
private int createNewChunk() throws CoreException {
- Chunk[] oldtoc = chunks;
- int n = oldtoc.length;
- int offset = n * CHUNK_SIZE;
- chunks = new Chunk[n + 1];
- System.arraycopy(oldtoc, 0, chunks, 0, n);
- final Chunk chunk= new Chunk(this, n);
+ // prepare new chunk array
+ final int oldLen= chunks.length;
+ final Chunk chunk= new Chunk(this, oldLen);
chunk.fDirty= true;
- chunks[n]= chunk;
- fCache.add(chunk, true);
- return offset;
+
+ Chunk[] newchunks = new Chunk[oldLen+1];
+ // the content of the chunk array may be modified by the cache, so sync it.
+ synchronized (fCache) {
+ System.arraycopy(chunks, 0, newchunks, 0, oldLen);
+ newchunks[oldLen]= chunk;
+ chunks= newchunks;
+ fCache.add(chunk, true);
+ }
+ return oldLen * CHUNK_SIZE;
}
private int getFirstBlock(int blocksize) throws CoreException {
@@ -408,6 +414,8 @@ public class Database {
public void close() throws CoreException {
setReadOnly(true);
removeChunksFromCache();
+
+ // chunks have been removed from the cache, so we are fine
chunks= new Chunk[0];
try {
file.close();
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/indexview/IndexView.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/indexview/IndexView.java
index cdd3fd3b417..02ee5484a3b 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/indexview/IndexView.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/indexview/IndexView.java
@@ -77,6 +77,7 @@ public class IndexView extends ViewPart implements PDOM.IListener, IElementChang
private IndexAction findReferencesAction;
Filter filter = new Filter();
public boolean isLinking = false;
+ private volatile boolean fUpdateRequested= false;
public void toggleExternalDefs() {
if (!filter.showExternalDefs) {
@@ -406,13 +407,23 @@ public class IndexView extends ViewPart implements PDOM.IListener, IElementChang
}
public void handleChange(PDOM pdom) {
- viewer.getControl().getDisplay().asyncExec(new Runnable() {
- public void run() {
- viewer.refresh();
- }
- });
+ requestUpdate();
}
+ private void requestUpdate() {
+ if (!fUpdateRequested) {
+ fUpdateRequested= true;
+ viewer.getControl().getDisplay().asyncExec(new Runnable() {
+ public void run() {
+ fUpdateRequested= false;
+ if (!viewer.getControl().isDisposed()) {
+ viewer.refresh();
+ }
+ }
+ });
+ }
+ }
+
public void elementChanged(ElementChangedEvent event) {
// Only respond to post change events
if (event.getType() != ElementChangedEvent.POST_CHANGE)

Back to the top