Search in sources :

Example 26 with TransactionMap

use of org.h2.mvstore.db.TransactionStore.TransactionMap in project h2database by h2database.

the class TestTransactionStore method testCompareWithPostgreSQL.

private void testCompareWithPostgreSQL() throws Exception {
    ArrayList<Statement> statements = New.arrayList();
    ArrayList<Transaction> transactions = New.arrayList();
    ArrayList<TransactionMap<Integer, String>> maps = New.arrayList();
    int connectionCount = 3, opCount = 1000, rowCount = 10;
    try {
        Class.forName("org.postgresql.Driver");
        for (int i = 0; i < connectionCount; i++) {
            Connection conn = DriverManager.getConnection("jdbc:postgresql:test?loggerLevel=OFF", "sa", "sa");
            statements.add(conn.createStatement());
        }
    } catch (Exception e) {
        // database not installed - ok
        return;
    }
    statements.get(0).execute("drop table if exists test cascade");
    statements.get(0).execute("create table test(id int primary key, name varchar(255))");
    MVStore s = MVStore.open(null);
    TransactionStore ts = new TransactionStore(s);
    ts.init();
    for (int i = 0; i < connectionCount; i++) {
        Statement stat = statements.get(i);
        // 100 ms to avoid blocking (the test is single threaded)
        stat.execute("set statement_timeout to 100");
        Connection c = stat.getConnection();
        c.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
        c.setAutoCommit(false);
        Transaction transaction = ts.begin();
        transactions.add(transaction);
        TransactionMap<Integer, String> map;
        map = transaction.openMap("test");
        maps.add(map);
    }
    StringBuilder buff = new StringBuilder();
    Random r = new Random(1);
    try {
        for (int i = 0; i < opCount; i++) {
            int connIndex = r.nextInt(connectionCount);
            Statement stat = statements.get(connIndex);
            Transaction transaction = transactions.get(connIndex);
            TransactionMap<Integer, String> map = maps.get(connIndex);
            if (transaction == null) {
                transaction = ts.begin();
                map = transaction.openMap("test");
                transactions.set(connIndex, transaction);
                maps.set(connIndex, map);
                // read all data, to get a snapshot
                ResultSet rs = stat.executeQuery("select * from test order by id");
                buff.append(i).append(": [" + connIndex + "]=");
                int size = 0;
                while (rs.next()) {
                    buff.append(' ');
                    int k = rs.getInt(1);
                    String v = rs.getString(2);
                    buff.append(k).append(':').append(v);
                    assertEquals(v, map.get(k));
                    size++;
                }
                buff.append('\n');
                if (size != map.sizeAsLong()) {
                    assertEquals(size, map.sizeAsLong());
                }
            }
            int x = r.nextInt(rowCount);
            int y = r.nextInt(rowCount);
            buff.append(i).append(": [" + connIndex + "]: ");
            ResultSet rs = null;
            switch(r.nextInt(7)) {
                case 0:
                    buff.append("commit");
                    stat.getConnection().commit();
                    transaction.commit();
                    transactions.set(connIndex, null);
                    break;
                case 1:
                    buff.append("rollback");
                    stat.getConnection().rollback();
                    transaction.rollback();
                    transactions.set(connIndex, null);
                    break;
                case 2:
                    // insert or update
                    String old = map.get(x);
                    if (old == null) {
                        buff.append("insert " + x + "=" + y);
                        if (map.tryPut(x, "" + y)) {
                            stat.execute("insert into test values(" + x + ", '" + y + "')");
                        } else {
                            buff.append(" -> row was locked");
                        // the statement would time out in PostgreSQL
                        // TODO test sometimes if timeout occurs
                        }
                    } else {
                        buff.append("update " + x + "=" + y + " (old:" + old + ")");
                        if (map.tryPut(x, "" + y)) {
                            int c = stat.executeUpdate("update test set name = '" + y + "' where id = " + x);
                            assertEquals(1, c);
                        } else {
                            buff.append(" -> row was locked");
                        // the statement would time out in PostgreSQL
                        // TODO test sometimes if timeout occurs
                        }
                    }
                    break;
                case 3:
                    buff.append("delete " + x);
                    try {
                        int c = stat.executeUpdate("delete from test where id = " + x);
                        if (c == 1) {
                            map.remove(x);
                        } else {
                            assertNull(map.get(x));
                        }
                    } catch (SQLException e) {
                        assertNotNull(map.get(x));
                        assertFalse(map.tryRemove(x));
                        // PostgreSQL needs to rollback
                        buff.append(" -> rollback");
                        stat.getConnection().rollback();
                        transaction.rollback();
                        transactions.set(connIndex, null);
                    }
                    break;
                case 4:
                case 5:
                case 6:
                    rs = stat.executeQuery("select * from test where id = " + x);
                    String expected = rs.next() ? rs.getString(2) : null;
                    buff.append("select " + x + "=" + expected);
                    assertEquals("i:" + i, expected, map.get(x));
                    break;
            }
            buff.append('\n');
        }
    } catch (Exception e) {
        e.printStackTrace();
        fail(buff.toString());
    }
    for (Statement stat : statements) {
        stat.getConnection().close();
    }
    ts.close();
    s.close();
}
Also used : SQLException(java.sql.SQLException) Statement(java.sql.Statement) Connection(java.sql.Connection) SQLException(java.sql.SQLException) MVStore(org.h2.mvstore.MVStore) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) TransactionStore(org.h2.mvstore.db.TransactionStore) Transaction(org.h2.mvstore.db.TransactionStore.Transaction) Random(java.util.Random) ResultSet(java.sql.ResultSet) TransactionMap(org.h2.mvstore.db.TransactionStore.TransactionMap)

Example 27 with TransactionMap

use of org.h2.mvstore.db.TransactionStore.TransactionMap in project h2database by h2database.

the class TestTransactionStore method testTwoPhaseCommit.

private void testTwoPhaseCommit() {
    String fileName = getBaseDir() + "/testTwoPhaseCommit.h3";
    FileUtils.delete(fileName);
    MVStore s;
    TransactionStore ts;
    Transaction tx;
    Transaction txOld;
    TransactionMap<String, String> m;
    List<Transaction> list;
    s = MVStore.open(fileName);
    ts = new TransactionStore(s);
    ts.init();
    tx = ts.begin();
    assertEquals(null, tx.getName());
    tx.setName("first transaction");
    assertEquals("first transaction", tx.getName());
    assertEquals(1, tx.getId());
    assertEquals(Transaction.STATUS_OPEN, tx.getStatus());
    m = tx.openMap("test");
    m.put("1", "Hello");
    list = ts.getOpenTransactions();
    assertEquals(1, list.size());
    txOld = list.get(0);
    assertTrue(tx.getId() == txOld.getId());
    assertEquals("first transaction", txOld.getName());
    s.commit();
    ts.close();
    s.close();
    s = MVStore.open(fileName);
    ts = new TransactionStore(s);
    ts.init();
    tx = ts.begin();
    assertEquals(2, tx.getId());
    m = tx.openMap("test");
    assertEquals(null, m.get("1"));
    m.put("2", "Hello");
    list = ts.getOpenTransactions();
    assertEquals(2, list.size());
    txOld = list.get(0);
    assertEquals(1, txOld.getId());
    assertEquals(Transaction.STATUS_OPEN, txOld.getStatus());
    assertEquals("first transaction", txOld.getName());
    txOld.prepare();
    assertEquals(Transaction.STATUS_PREPARED, txOld.getStatus());
    txOld = list.get(1);
    txOld.commit();
    s.commit();
    s.close();
    s = MVStore.open(fileName);
    ts = new TransactionStore(s);
    ts.init();
    tx = ts.begin();
    m = tx.openMap("test");
    m.put("3", "Test");
    assertEquals(2, tx.getId());
    list = ts.getOpenTransactions();
    assertEquals(2, list.size());
    txOld = list.get(1);
    assertEquals(2, txOld.getId());
    assertEquals(Transaction.STATUS_OPEN, txOld.getStatus());
    assertEquals(null, txOld.getName());
    txOld.rollback();
    txOld = list.get(0);
    assertEquals(1, txOld.getId());
    assertEquals(Transaction.STATUS_PREPARED, txOld.getStatus());
    assertEquals("first transaction", txOld.getName());
    txOld.commit();
    assertEquals("Hello", m.get("1"));
    s.close();
    FileUtils.delete(fileName);
}
Also used : MVStore(org.h2.mvstore.MVStore) TransactionStore(org.h2.mvstore.db.TransactionStore) Transaction(org.h2.mvstore.db.TransactionStore.Transaction)

Example 28 with TransactionMap

use of org.h2.mvstore.db.TransactionStore.TransactionMap in project h2database by h2database.

the class TestTransactionStore method testKeyIterator.

private void testKeyIterator() {
    MVStore s = MVStore.open(null);
    TransactionStore ts = new TransactionStore(s);
    ts.init();
    Transaction tx, tx2;
    TransactionMap<String, String> m, m2;
    Iterator<String> it, it2;
    tx = ts.begin();
    m = tx.openMap("test");
    m.put("1", "Hello");
    m.put("2", "World");
    m.put("3", ".");
    tx.commit();
    tx2 = ts.begin();
    m2 = tx2.openMap("test");
    m2.remove("2");
    m2.put("3", "!");
    m2.put("4", "?");
    tx = ts.begin();
    m = tx.openMap("test");
    it = m.keyIterator(null);
    assertTrue(it.hasNext());
    assertEquals("1", it.next());
    assertTrue(it.hasNext());
    assertEquals("2", it.next());
    assertTrue(it.hasNext());
    assertEquals("3", it.next());
    assertFalse(it.hasNext());
    it2 = m2.keyIterator(null);
    assertTrue(it2.hasNext());
    assertEquals("1", it2.next());
    assertTrue(it2.hasNext());
    assertEquals("3", it2.next());
    assertTrue(it2.hasNext());
    assertEquals("4", it2.next());
    assertFalse(it2.hasNext());
    s.close();
}
Also used : MVStore(org.h2.mvstore.MVStore) TransactionStore(org.h2.mvstore.db.TransactionStore) Transaction(org.h2.mvstore.db.TransactionStore.Transaction)

Example 29 with TransactionMap

use of org.h2.mvstore.db.TransactionStore.TransactionMap in project h2database by h2database.

the class TestTransactionStore method testSavepoint.

private void testSavepoint() {
    MVStore s = MVStore.open(null);
    TransactionStore ts = new TransactionStore(s);
    ts.init();
    Transaction tx;
    TransactionMap<String, String> m;
    tx = ts.begin();
    m = tx.openMap("test");
    m.put("1", "Hello");
    m.put("2", "World");
    m.put("1", "Hallo");
    m.remove("2");
    m.put("3", "!");
    long logId = tx.setSavepoint();
    m.put("1", "Hi");
    m.put("2", ".");
    m.remove("3");
    tx.rollbackToSavepoint(logId);
    assertEquals("Hallo", m.get("1"));
    assertNull(m.get("2"));
    assertEquals("!", m.get("3"));
    tx.rollback();
    tx = ts.begin();
    m = tx.openMap("test");
    assertNull(m.get("1"));
    assertNull(m.get("2"));
    assertNull(m.get("3"));
    ts.close();
    s.close();
}
Also used : MVStore(org.h2.mvstore.MVStore) TransactionStore(org.h2.mvstore.db.TransactionStore) Transaction(org.h2.mvstore.db.TransactionStore.Transaction)

Example 30 with TransactionMap

use of org.h2.mvstore.db.TransactionStore.TransactionMap in project h2database by h2database.

the class TestTransactionStore method testStoreMultiThreadedReads.

private static void testStoreMultiThreadedReads() throws Exception {
    MVStore s = MVStore.open(null);
    final TransactionStore ts = new TransactionStore(s);
    ts.init();
    Transaction t = ts.begin();
    TransactionMap<Integer, Integer> mapA = t.openMap("a");
    mapA.put(1, 0);
    t.commit();
    Task task = new Task() {

        @Override
        public void call() throws Exception {
            for (int i = 0; !stop; i++) {
                Transaction tx = ts.begin();
                TransactionMap<Integer, Integer> mapA = tx.openMap("a");
                while (!mapA.tryPut(1, i)) {
                // repeat
                }
                tx.commit();
                // map B transaction
                // the other thread will get a map A uncommitted value,
                // but by the time it tries to walk back to the committed
                // value, the undoLog has changed
                tx = ts.begin();
                TransactionMap<Integer, Integer> mapB = tx.openMap("b");
                // put a new value to the map; this will cause a map B
                // undoLog entry to be created with a null pre-image value
                mapB.tryPut(i, -i);
                // this is where the real race condition occurs:
                // some other thread might get the B log entry
                // for this transaction rather than the uncommitted A log
                // entry it is expecting
                tx.commit();
            }
        }
    };
    task.execute();
    try {
        for (int i = 0; i < 10000; i++) {
            Transaction tx = ts.begin();
            mapA = tx.openMap("a");
            if (mapA.get(1) == null) {
                throw new AssertionError("key not found");
            }
            tx.commit();
        }
    } finally {
        task.get();
    }
    ts.close();
}
Also used : MVStore(org.h2.mvstore.MVStore) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) TransactionStore(org.h2.mvstore.db.TransactionStore) Task(org.h2.util.Task) Transaction(org.h2.mvstore.db.TransactionStore.Transaction)

Aggregations

Transaction (org.h2.mvstore.db.TransactionStore.Transaction)19 MVStore (org.h2.mvstore.MVStore)17 TransactionStore (org.h2.mvstore.db.TransactionStore)17 Value (org.h2.value.Value)15 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)8 ValueArray (org.h2.value.ValueArray)6 Random (java.util.Random)5 VersionedValue (org.h2.mvstore.db.TransactionStore.VersionedValue)4 SpatialKey (org.h2.mvstore.rtree.SpatialKey)4 Task (org.h2.util.Task)4 ValueLong (org.h2.value.ValueLong)2 Connection (java.sql.Connection)1 ResultSet (java.sql.ResultSet)1 SQLException (java.sql.SQLException)1 Statement (java.sql.Statement)1 Entry (java.util.Map.Entry)1 MetaRecord (org.h2.engine.MetaRecord)1 Session (org.h2.engine.Session)1 DbException (org.h2.message.DbException)1 Change (org.h2.mvstore.db.TransactionStore.Change)1