/** * Test correct detection and resolution of a write-write conflict. An index is registered with an * {@link IConflictResolver} and the journal is committed. Two transactions (tx1, tx2) are then * started. Both transactions write a value under the same key. tx1 prepares and commits. tx2 * attempts to prepare, and the test verifies that the conflict resolver is invoked, that it may * resolve the conflict causing validation to succeed and that the value determined by conflict * resolution is made persistent when tx2 commits. */ public void test_writeWriteConflict_conflictIsResolved() { final Journal journal = new Journal(getProperties()); try { final String name = "abc"; final byte[] k1 = new byte[] {1}; final byte[] v1a = new byte[] {1}; final byte[] v1b = new byte[] {2}; final byte[] v1c = new byte[] {3}; { /* * register an index with a conflict resolver and commit the * journal. */ final IndexMetadata metadata = new IndexMetadata(name, UUID.randomUUID()); metadata.setIsolatable(true); metadata.setConflictResolver(new SingleValueConflictResolver(k1, v1c)); journal.registerIndex(name, BTree.create(journal, metadata)); journal.commit(); } /* * Create two transactions. */ final long tx1 = journal.newTx(ITx.UNISOLATED); final long tx2 = journal.newTx(ITx.UNISOLATED); /* * Write a value under the same key on the same index in both * transactions. */ journal.getIndex(name, tx1).insert(k1, v1a); journal.getIndex(name, tx2).insert(k1, v1b); journal.commit(tx1); /* * verify that the value from tx1 is found under the key on the * unisolated index. */ assertEquals(v1a, (byte[]) journal.getIndex(name).lookup(k1)); journal.commit(tx2); /* * verify that the resolved value is found under the key on the * unisolated index. */ assertEquals(v1c, (byte[]) journal.getIndex(name).lookup(k1)); } finally { journal.destroy(); } }
/** * Test correct detection of a write-write conflict. An index is registered and the journal is * committed. Two transactions (tx1, tx2) are then started. Both transactions write a value under * the same key. tx1 prepares and commits. tx2 attempts to prepare, and the test verifies that a * {@link ValidationError} is reported. */ public void test_writeWriteConflict_correctDetection() { final Journal journal = new Journal(getProperties()); try { String name = "abc"; final byte[] k1 = new byte[] {1}; final byte[] v1a = new byte[] {1}; final byte[] v1b = new byte[] {2}; { /* * register an index and commit the journal. */ IndexMetadata metadata = new IndexMetadata(name, UUID.randomUUID()); metadata.setIsolatable(true); // Note: No conflict resolver. journal.registerIndex(name, BTree.create(journal, metadata)); journal.commit(); } /* * Create two transactions. */ final long tx1 = journal.newTx(ITx.UNISOLATED); final long tx2 = journal.newTx(ITx.UNISOLATED); /* * Write a value under the same key on the same index in both * transactions. */ journal.getIndex(name, tx1).insert(k1, v1a); journal.getIndex(name, tx2).insert(k1, v1b); journal.commit(tx1); /* * verify that the value from tx1 is found under the key on the * unisolated index. */ assertEquals(v1a, (byte[]) journal.getIndex(name).lookup(k1)); // final ITx tmp = journal.getTx(tx2); try { journal.commit(tx2); fail("Expecting: " + ValidationError.class); } catch (ValidationError ex) { if (log.isInfoEnabled()) log.info("Ignoring expected exception: " + ex); // assertTrue(tmp.isAborted()); } } finally { journal.destroy(); } }