cursor.close();
cursor = null;
txnDel.commit();
}
JUnitThread tester1 =
new JUnitThread(config.testName + "1") {
public void testBody()
throws Throwable {
Cursor cursor = null;
Cursor c = null;
try {
Transaction txn1 =
env.beginTransaction(null, null);
cursor = db.openCursor(txn1, CursorConfig.DEFAULT);
OperationStatus status =
cursor.getSearchBoth
(new DatabaseEntry(DUPKEY.getBytes()),
new DatabaseEntry
(config.thread1EntryToLock.getBytes()),
LockMode.RMW);
assertEquals(OperationStatus.SUCCESS, status);
cursor.close();
cursor = null;
sequence++; // 0 -> 1
while (sequence < 2) {
Thread.yield();
}
/*
* Since we can't increment sequence when tester2
* blocks on the getNext call, all we can do is
* bump sequence right before the getNext, and then
* wait a little in this thread for tester2 to
* block.
*/
try {
Thread.sleep(250);
} catch (InterruptedException IE) {
}
if (config.doInsert) {
status = db.put
(txn1,
new DatabaseEntry(DUPKEY.getBytes()),
new DatabaseEntry
(config.thread1OpArg.getBytes()));
} else {
c = db.openCursor(txn1, CursorConfig.DEFAULT);
assertEquals(OperationStatus.SUCCESS,
c.getSearchBoth
(new DatabaseEntry
(DUPKEY.getBytes()),
new DatabaseEntry
(config.thread1OpArg.getBytes()),
LockMode.DEFAULT));
assertEquals(OperationStatus.SUCCESS,
c.delete());
c.close();
c = null;
}
assertEquals(OperationStatus.SUCCESS, status);
sequence++; // 2 -> 3
try {
Thread.sleep(1000);
} catch (InterruptedException IE) {
}
if (config.doCommit) {
txn1.commit();
} else {
txn1.abort();
}
} catch (DatabaseException DBE) {
if (cursor != null) {
cursor.close();
}
if (c != null) {
c.close();
}
DBE.printStackTrace();
fail("caught DatabaseException " + DBE);
}
}
};
JUnitThread tester2 =
new JUnitThread("testPhantomInsert2") {
public void testBody()
throws Throwable {
Cursor cursor = null;
try {
Transaction txn2 =
env.beginTransaction(null, null);
txn2.setLockTimeout(LOCK_TIMEOUT);
cursor = db.openCursor(txn2, CursorConfig.DEFAULT);
while (sequence < 1) {
Thread.yield();
}
OperationStatus status =
cursor.getSearchBoth
(new DatabaseEntry(DUPKEY.getBytes()),
new DatabaseEntry
(config.thread2Start.getBytes()),
LockMode.DEFAULT);
assertEquals(OperationStatus.SUCCESS, status);
sequence++; // 1 -> 2
DatabaseEntry nextKey = new DatabaseEntry();
DatabaseEntry nextData = new DatabaseEntry();
try {
/*
* This will block until tester1 above commits.
*/
if (config.doGetNext) {
status =
cursor.getNextDup(nextKey, nextData,
LockMode.DEFAULT);
} else {
status =
cursor.getPrevDup(nextKey, nextData,
LockMode.DEFAULT);
}
} catch (DatabaseException DBE) {
System.out.println("t2 caught " + DBE);
}
assertEquals(3, sequence);
byte[] data = nextData.getData();
assertEquals(config.expectedResult,
new String(data));
cursor.close();
cursor = null;
txn2.commit();
} catch (DatabaseException DBE) {
if (cursor != null) {
cursor.close();
}
DBE.printStackTrace();
fail("caught DatabaseException " + DBE);
}
}
};
tester1.start();
tester2.start();
tester1.finishTest();
tester2.finishTest();
} finally {
if (cursor != null) {
cursor.close();
}
db.close();