/**
   * 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();
    }
  }