use of org.cojen.tupl.Transaction in project Tupl by cojen.
the class UpgradableRowUpdater method toNext.
@Override
protected LockResult toNext(Cursor c) throws IOException {
Transaction txn = c.link();
LockMode original = txn.lockMode();
txn.lockMode(LockMode.UPGRADABLE_READ);
try {
return super.toNext(c);
} finally {
txn.lockMode(original);
}
}
use of org.cojen.tupl.Transaction in project Tupl by cojen.
the class MergeCursor method link.
@Override
public Transaction link(Transaction txn) {
Transaction old = mTxn;
mTxn = txn;
return old;
}
use of org.cojen.tupl.Transaction in project Tupl by cojen.
the class MergeCursor method store.
@Override
public void store(byte[] value) throws IOException {
byte[] key = mKey;
ViewUtils.positionCheck(key);
Transaction txn = mTxn;
if (txn == null) {
txn = mView.newTransaction(null);
try {
store(txn, key, value);
txn.commit();
} finally {
txn.reset();
}
} else if (txn.lockMode() != LockMode.UNSAFE) {
txn.enter();
try {
store(txn, key, value);
txn.commit();
} finally {
txn.exit();
}
} else {
store(txn, key, value);
}
}
use of org.cojen.tupl.Transaction in project Tupl by cojen.
the class DatabaseReplicatorTest method prepareTransfer.
private void prepareTransfer(boolean prepareCommit) throws Exception {
// Prepared transaction should be transferred to replica and finish.
var dbQueue = new LinkedBlockingQueue<Database>();
var txnQueue = new LinkedBlockingQueue<Transaction>();
Supplier<PrepareHandler> supplier = () -> new PrepareHandler() {
private Database mDb;
@Override
public void init(Database db) {
mDb = db;
}
@Override
public void prepare(Transaction txn, byte[] message) throws IOException {
dbQueue.add(mDb);
txnQueue.add(txn);
}
@Override
public void prepareCommit(Transaction txn, byte[] message) throws IOException {
prepare(txn, message);
}
};
Database[] dbs = startGroup(2, Role.NORMAL, supplier);
Database leaderDb = dbs[0];
Database replicaDb = dbs[1];
Index leaderIx = leaderDb.openIndex("test");
// Wait for replica to catch up.
fence(leaderDb, replicaDb);
Index replicaIx = replicaDb.openIndex("test");
Transaction txn1 = leaderDb.newTransaction();
PrepareHandler handler = leaderDb.prepareWriter("TestHandler");
byte[] k1 = "k1".getBytes();
byte[] v1 = "v1".getBytes();
leaderIx.store(txn1, k1, v1);
if (prepareCommit) {
handler.prepareCommit(txn1, null);
fastAssertArrayEquals(v1, leaderIx.load(null, k1));
} else {
handler.prepare(txn1, null);
try {
leaderIx.load(null, k1);
fail();
} catch (LockTimeoutException e) {
}
}
leaderDb.failover();
// Replica is now the leader and should have the transaction.
assertEquals(replicaDb, dbQueue.take());
Transaction txn2 = txnQueue.take();
assertNotEquals(txn1, txn2);
assertEquals(txn1.id(), txn2.id());
fastAssertArrayEquals(v1, replicaIx.load(txn2, k1));
byte[] k2 = "k2".getBytes();
byte[] v2 = "v2".getBytes();
replicaIx.store(txn2, k2, v2);
if (prepareCommit) {
fastAssertArrayEquals(v1, replicaIx.load(null, k1));
} else {
try {
replicaIx.load(null, k1);
fail();
} catch (LockTimeoutException e) {
}
}
txn2.commit();
// Wait for old leader to catch up. This will fail at first because the old leader
// transaction is stuck.
boolean pass = true;
try {
fence(replicaDb, leaderDb, true);
pass = false;
} catch (AssertionError e) {
}
assertTrue(pass);
try {
txn1.commit();
fail();
} catch (UnmodifiableReplicaException e) {
// This will unstick the transaction.
}
fence(replicaDb, leaderDb);
// Verify that the old leader observes the committed changes.
fastAssertArrayEquals(v1, leaderIx.load(null, k1));
fastAssertArrayEquals(v2, leaderIx.load(null, k2));
}
use of org.cojen.tupl.Transaction in project Tupl by cojen.
the class DatabaseReplicatorTest method largeWrite.
@Test
public void largeWrite() throws Exception {
Database[] dbs = startGroup(1);
Database db = dbs[0];
Index ix = db.openIndex("test");
var value = new byte[100_000];
// illegal redo op
Arrays.fill(value, 0, value.length, (byte) 0x7f);
byte[] key = "hello".getBytes();
Transaction txn = db.newTransaction();
Cursor c = ix.newCursor(txn);
c.find(key);
// This used to hang due to a bug. The commit index was too high, and so it wouldn't be
// confirmed.
c.commit(value);
db.checkpoint();
db = closeAndReopen(0);
ix = db.openIndex("test");
fastAssertArrayEquals(value, ix.load(null, key));
db.close();
}
Aggregations