Search in sources :

Example 81 with MVStore

use of org.h2.mvstore.MVStore 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 82 with MVStore

use of org.h2.mvstore.MVStore 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 83 with MVStore

use of org.h2.mvstore.MVStore 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 84 with MVStore

use of org.h2.mvstore.MVStore 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 85 with MVStore

use of org.h2.mvstore.MVStore 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

MVStore (org.h2.mvstore.MVStore)123 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)69 Random (java.util.Random)23 Task (org.h2.util.Task)20 TransactionStore (org.h2.mvstore.db.TransactionStore)19 Transaction (org.h2.mvstore.db.TransactionStore.Transaction)17 MVRTreeMap (org.h2.mvstore.rtree.MVRTreeMap)8 SpatialKey (org.h2.mvstore.rtree.SpatialKey)8 IOException (java.io.IOException)6 Connection (java.sql.Connection)5 Statement (java.sql.Statement)5 FileStore (org.h2.mvstore.FileStore)5 StreamStore (org.h2.mvstore.StreamStore)5 ArrayList (java.util.ArrayList)4 TreeMap (java.util.TreeMap)4 Store (org.h2.mvstore.db.MVTableEngine.Store)4 ByteArrayInputStream (java.io.ByteArrayInputStream)3 FileOutputStream (java.io.FileOutputStream)3 OutputStream (java.io.OutputStream)3 PreparedStatement (java.sql.PreparedStatement)3