1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-04 23:55:26 +02:00

192437: apply fix

This commit is contained in:
Andrew Ferguson 2007-06-13 16:39:58 +00:00
parent 4f3484f3e7
commit 3fdfd1e46b
7 changed files with 81 additions and 12 deletions
core
org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests
org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom

View file

@ -52,7 +52,7 @@ public class BTreeTests extends BaseTestCase {
// and invoke it multiple times per Junit test
protected void init(int degree) throws Exception {
dbFile = File.createTempFile("pdomtest", "db");
db = new Database(dbFile, new ChunkCache(), 0);
db = new Database(dbFile, new ChunkCache(), 0, false);
db.setWritable();
rootRecord = Database.DATA_AREA;
comparator = new BTMockRecordComparator();

View file

@ -37,7 +37,7 @@ public class DBPropertiesTests extends BaseTestCase {
protected void setUp() throws Exception {
dbLoc = File.createTempFile("test", "db");
dbLoc.deleteOnExit();
db = new Database(dbLoc, new ChunkCache(), 0);
db = new Database(dbLoc, new ChunkCache(), 0, false);
db.setWritable();
}

View file

@ -13,6 +13,7 @@
package org.eclipse.cdt.internal.pdom.tests;
import java.io.File;
import java.io.IOException;
import java.util.Random;
import junit.framework.Test;
@ -35,7 +36,7 @@ public class DBTest extends BaseTestCase {
protected void setUp() throws Exception {
super.setUp();
db = new Database(getTestDir().append(getName()+System.currentTimeMillis()+".dat").toFile(),
new ChunkCache(), 0);
new ChunkCache(), 0, false);
}
public static Test suite() {
@ -73,6 +74,30 @@ public class DBTest extends BaseTestCase {
assertEquals(mem - Database.INT_SIZE + blocksize, db.getInt(((Database.CHUNK_SIZE - blocksize) / Database.MIN_SIZE) * Database.INT_SIZE));
}
public void testBug192437() throws IOException {
File tmp= File.createTempFile("readOnlyEmpty", ".db");
try {
tmp.setReadOnly();
/* check opening a readonly file for rw access fails */
try {
new Database(tmp, ChunkCache.getSharedInstance(), 0, false);
fail("A readonly file should not be openable with write-access");
} catch(CoreException ioe) {
// we expect to get a failure here
}
/* check opening a readonly file for read access does not fail */
try {
new Database(tmp, ChunkCache.getSharedInstance(), 0, true);
} catch(CoreException ce) {
fail("A readonly file should be readable by a permanently readonly database "+ce);
}
} finally {
tmp.delete(); // this may be pointless on some platforms
}
}
public void testFreeBlockLinking() throws Exception {
final int realsize = 42;
final int blocksize = (realsize / Database.MIN_SIZE + 1) * Database.MIN_SIZE;
@ -126,7 +151,7 @@ public class DBTest extends BaseTestCase {
// Tests inserting and retrieving strings
File f = getTestDir().append("testStrings.dat").toFile();
f.delete();
final Database db = new Database(f, new ChunkCache(), 0);
final Database db = new Database(f, new ChunkCache(), 0, false);
db.setWritable();
String[] names = {

View file

@ -165,7 +165,7 @@ public class PDOMCPPBugsTest extends BaseTestCase {
}
public void testInterruptingAcquireWriteLock() throws Exception {
final PDOM pdom= (PDOM) CCoreInternals.getPDOMManager().getPDOM(cproject);
final WritablePDOM pdom= (WritablePDOM) CCoreInternals.getPDOMManager().getPDOM(cproject);
final boolean[] ok= {false};
pdom.acquireReadLock();
try {

View file

@ -134,10 +134,17 @@ public class PDOM extends PlatformObject implements IIndexFragment, IPDOM {
loadDatabase(dbPath, cache);
this.locationConverter = locationConverter;
}
/**
* Returns whether this PDOM can never be written to. Writable subclasses should return false.
*/
protected boolean isPermanentlyReadOnly() {
return true;
}
private void loadDatabase(File dbPath, ChunkCache cache) throws CoreException {
fPath= dbPath;
db = new Database(fPath, cache, VERSION);
db = new Database(fPath, cache, VERSION, isPermanentlyReadOnly());
fileIndex= null; // holds on to the database, so clear it.
int version= db.getVersion();
@ -258,7 +265,9 @@ public class PDOM extends PlatformObject implements IIndexFragment, IPDOM {
CCorePlugin.log(e);
}
loadDatabase(file, db.getChunkCache());
db.setWritable();
if(!isPermanentlyReadOnly()) {
db.setWritable();
}
oldFile.delete();
}
@ -549,10 +558,21 @@ public class PDOM extends PlatformObject implements IIndexFragment, IPDOM {
}
}
/**
* Acquire a write lock on this PDOM. Blocks until any existing read/write locks are released.
* @throws InterruptedException
* @throws IllegalStateException if this PDOM is not writable
*/
public void acquireWriteLock() throws InterruptedException {
acquireWriteLock(0);
}
/**
* Acquire a write lock on this PDOM, giving up the specified number of read locks first. Blocks
* until any existing read/write locks are released.
* @throws InterruptedException
* @throws IllegalStateException if this PDOM is not writable
*/
public void acquireWriteLock(int giveupReadLocks) throws InterruptedException {
synchronized (mutex) {
if (giveupReadLocks > 0) {

View file

@ -154,4 +154,8 @@ public class WritablePDOM extends PDOM implements IWritableIndexFragment {
void setCreatedFromScratch(boolean createdFromScratch) {
fCreatedFromScratch = createdFromScratch;
}
protected final boolean isPermanentlyReadOnly() {
return false;
}
}

View file

@ -62,6 +62,7 @@ public class Database {
private final File location;
private final RandomAccessFile file;
private boolean fWritable= false;
private boolean fPermanentlyReadOnly;
private Chunk[] chunks;
private long malloced;
@ -81,18 +82,29 @@ public class Database {
public static final int DATA_AREA = CHUNK_SIZE / MIN_SIZE * INT_SIZE + INT_SIZE;
public static final int MAX_SIZE = CHUNK_SIZE - 4; // Room for overhead
public Database(File location, ChunkCache cache, int version) throws CoreException {
/**
* Construct a new Database object, creating a backing file if necessary.
* @param location the local file path for the database
* @param cache the cache to be used optimisation
* @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
* @throws CoreException
*/
public Database(File location, ChunkCache cache, int version, boolean permanentlyReadOnly) throws CoreException {
try {
this.location = location;
this.file = new RandomAccessFile(location, "rw"); //$NON-NLS-1$
fCache= cache;
this.fPermanentlyReadOnly= permanentlyReadOnly;
this.file = new RandomAccessFile(location, permanentlyReadOnly ? "r" : "rw"); //$NON-NLS-1$ //$NON-NLS-2$
this.fCache= cache;
// Allocate chunk table, make sure we have at least one
long nChunks = file.length() / CHUNK_SIZE;
chunks = new Chunk[(int)nChunks];
if (nChunks == 0) {
setWritable();
if(!permanentlyReadOnly) {
setWritable();
}
createNewChunk();
setVersion(version);
setReadOnly(true);
@ -428,7 +440,15 @@ public class Database {
return fCache;
}
/**
* Marks this Database as writable. This is used for avoiding some synchronization on chunk fetching. An
* exception is thrown if this Database was constructed as a permanently read only Database.
* @see Database#Database(File, ChunkCache, int, boolean)
* @throw IllegalStateException if called on a permanently read-only database
*/
public void setWritable() {
if(fPermanentlyReadOnly)
throw new IllegalStateException("A Database created as permanent-read-only may not be changed to writable state"); //$NON-NLS-1$
fWritable= true;
}