Search in sources :

Example 1 with Database

use of org.cojen.tupl.Database in project Tupl by cojen.

the class Compact method main.

/**
 * @param args a base file path for the database, a compaction target, and an optional
 * cache size
 */
public static void main(String[] args) throws Exception {
    var config = new DatabaseConfig().createFilePath(false).baseFilePath(args[0]).eventListener(EventListener.printTo(System.out).ignore(EventType.Category.CHECKPOINT)).checkpointSizeThreshold(0);
    double target = Double.parseDouble(args[1]);
    if (args.length > 2) {
        config.minCacheSize(Long.parseLong(args[2]));
    }
    Database db = Database.open(config);
    System.out.println("Before: " + db.stats());
    db.compactFile(null, target);
    System.out.println("After: " + db.stats());
}
Also used : Database(org.cojen.tupl.Database) DatabaseConfig(org.cojen.tupl.DatabaseConfig)

Example 2 with Database

use of org.cojen.tupl.Database 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));
}
Also used : Index(org.cojen.tupl.Index) LinkedBlockingQueue(java.util.concurrent.LinkedBlockingQueue) UnmodifiableReplicaException(org.cojen.tupl.UnmodifiableReplicaException) Transaction(org.cojen.tupl.Transaction) PrepareHandler(org.cojen.tupl.ext.PrepareHandler) Database(org.cojen.tupl.Database) LockTimeoutException(org.cojen.tupl.LockTimeoutException)

Example 3 with Database

use of org.cojen.tupl.Database 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();
}
Also used : Transaction(org.cojen.tupl.Transaction) Database(org.cojen.tupl.Database) Index(org.cojen.tupl.Index) Cursor(org.cojen.tupl.Cursor)

Example 4 with Database

use of org.cojen.tupl.Database in project Tupl by cojen.

the class DatabaseReplicatorTest method prepareBlank.

private void prepareBlank(boolean prepareCommit) throws Exception {
    // Test against a prepared transaction that has no changes. It should still ensure that
    // the transaction is created properly on the replica.
    var dbQueue = new LinkedBlockingQueue<Database>();
    var txnQueue = new LinkedBlockingQueue<Transaction>();
    var msgQueue = new LinkedBlockingQueue<byte[]>();
    var pcQueue = new LinkedBlockingQueue<Boolean>();
    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 {
            doPrepare(txn, message, false);
        }

        @Override
        public void prepareCommit(Transaction txn, byte[] message) throws IOException {
            doPrepare(txn, message, true);
        }

        private void doPrepare(Transaction txn, byte[] message, boolean commit) throws IOException {
            dbQueue.add(mDb);
            txnQueue.add(txn);
            msgQueue.add(message);
            pcQueue.add(commit);
        }
    };
    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");
    if (prepareCommit) {
        handler.prepareCommit(txn1, "message".getBytes());
    } else {
        handler.prepare(txn1, "message".getBytes());
    }
    leaderDb.failover();
    // Must capture the id before it gets replaced.
    long txnId = txn1.id();
    try {
        txn1.commit();
        fail();
    } catch (UnmodifiableReplicaException e) {
    // This will unstick the transaction.
    }
    // Replica is now the leader and should have the transaction.
    assertEquals(replicaDb, dbQueue.take());
    Transaction txn2 = txnQueue.take();
    assertNotEquals(txn1, txn2);
    assertEquals(txnId, txn2.id());
    fastAssertArrayEquals("message".getBytes(), msgQueue.take());
    assertEquals(prepareCommit, pcQueue.take());
    byte[] k1 = "k1".getBytes();
    byte[] v1 = "v1".getBytes();
    replicaIx.store(txn2, k1, v1);
    txn2.commit();
    fence(replicaDb, leaderDb);
    // Verify that the old leader observes the committed changes.
    fastAssertArrayEquals(v1, leaderIx.load(null, k1));
}
Also used : UnmodifiableReplicaException(org.cojen.tupl.UnmodifiableReplicaException) Transaction(org.cojen.tupl.Transaction) PrepareHandler(org.cojen.tupl.ext.PrepareHandler) Database(org.cojen.tupl.Database) Index(org.cojen.tupl.Index) LinkedBlockingQueue(java.util.concurrent.LinkedBlockingQueue)

Example 5 with Database

use of org.cojen.tupl.Database in project Tupl by cojen.

the class DatabaseReplicatorTest method basicTest.

private void basicTest(int memberCount) throws Exception {
    Database[] dbs = startGroup(memberCount);
    Index ix0 = dbs[0].openIndex("test");
    for (int t = 0; t < 10; t++) {
        byte[] key = ("hello-" + t).getBytes();
        byte[] value = ("world-" + t).getBytes();
        ix0.store(null, key, value);
        fastAssertArrayEquals(value, ix0.load(null, key));
        for (int i = 0; i < dbs.length; i++) {
            for (int q = 100; --q >= 0; ) {
                byte[] actual = null;
                try {
                    Index ix = dbs[i].openIndex("test");
                    actual = ix.load(null, key);
                    fastAssertArrayEquals(value, actual);
                    break;
                } catch (UnmodifiableReplicaException e) {
                    // Index doesn't exist yet due to replication delay.
                    if (q == 0) {
                        throw e;
                    }
                } catch (AssertionError e) {
                    // Value doesn't exist yet due to replication delay.
                    if (q == 0 || actual != null) {
                        throw e;
                    }
                }
                TestUtils.sleep(100);
            }
        }
    }
}
Also used : UnmodifiableReplicaException(org.cojen.tupl.UnmodifiableReplicaException) Database(org.cojen.tupl.Database) Index(org.cojen.tupl.Index)

Aggregations

Database (org.cojen.tupl.Database)15 Index (org.cojen.tupl.Index)10 UnmodifiableReplicaException (org.cojen.tupl.UnmodifiableReplicaException)8 Transaction (org.cojen.tupl.Transaction)6 DatabaseConfig (org.cojen.tupl.DatabaseConfig)5 PrepareHandler (org.cojen.tupl.ext.PrepareHandler)4 LinkedBlockingQueue (java.util.concurrent.LinkedBlockingQueue)3 Cursor (org.cojen.tupl.Cursor)3 LockTimeoutException (org.cojen.tupl.LockTimeoutException)2 File (java.io.File)1 IOException (java.io.IOException)1 BigDecimal (java.math.BigDecimal)1 Random (java.util.Random)1 LinkedTransferQueue (java.util.concurrent.LinkedTransferQueue)1 ThreadLocalRandom (java.util.concurrent.ThreadLocalRandom)1 DatabaseStats (org.cojen.tupl.diag.DatabaseStats)1 EventListener (org.cojen.tupl.diag.EventListener)1