//  Copyright (c) 2014, Facebook, Inc.  All rights reserved.
//  This source code is licensed under the BSD-style license found in the
//  LICENSE file in the root directory of this source tree. An additional grant
//  of patent rights can be found in the PATENTS file in the same directory.
//
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. See the AUTHORS file for names of contributors.

package org.rocksdb.test;

import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.rocksdb.*;

import static org.assertj.core.api.Assertions.assertThat;


public class WriteBatchWithIndexTest {

  @ClassRule
  public static final RocksMemoryResource rocksMemoryResource =
      new RocksMemoryResource();

  @Rule
  public TemporaryFolder dbFolder = new TemporaryFolder();

  @Test
  public void readYourOwnWrites() throws RocksDBException {
    RocksDB db = null;
    Options options = null;
    try {
      options = new Options();
      // Setup options
      options.setCreateIfMissing(true);
      db = RocksDB.open(options, dbFolder.getRoot().getAbsolutePath());

      final byte[] k1 = "key1".getBytes();
      final byte[] v1 = "value1".getBytes();
      final byte[] k2 = "key2".getBytes();
      final byte[] v2 = "value2".getBytes();

      db.put(k1, v1);
      db.put(k2, v2);

      final WriteBatchWithIndex wbwi = new WriteBatchWithIndex(true);

      RocksIterator base = null;
      RocksIterator it = null;
      try {
        base = db.newIterator();
        it = wbwi.newIteratorWithBase(base);

        it.seek(k1);
        assertThat(it.isValid()).isTrue();
        assertThat(it.key()).isEqualTo(k1);
        assertThat(it.value()).isEqualTo(v1);

        it.seek(k2);
        assertThat(it.isValid()).isTrue();
        assertThat(it.key()).isEqualTo(k2);
        assertThat(it.value()).isEqualTo(v2);

        //put data to the write batch and make sure we can read it.
        final byte[] k3 = "key3".getBytes();
        final byte[] v3 = "value3".getBytes();
        wbwi.put(k3, v3);
        it.seek(k3);
        assertThat(it.isValid()).isTrue();
        assertThat(it.key()).isEqualTo(k3);
        assertThat(it.value()).isEqualTo(v3);

        //update k2 in the write batch and check the value
        final byte[] v2Other = "otherValue2".getBytes();
        wbwi.put(k2, v2Other);
        it.seek(k2);
        assertThat(it.isValid()).isTrue();
        assertThat(it.key()).isEqualTo(k2);
        assertThat(it.value()).isEqualTo(v2Other);

        //remove k1 and make sure we can read back the write
        wbwi.remove(k1);
        it.seek(k1);
        assertThat(it.key()).isNotEqualTo(k1);

        //reinsert k1 and make sure we see the new value
        final byte[] v1Other = "otherValue1".getBytes();
        wbwi.put(k1, v1Other);
        it.seek(k1);
        assertThat(it.isValid()).isTrue();
        assertThat(it.key()).isEqualTo(k1);
        assertThat(it.value()).isEqualTo(v1Other);
      } finally {
        if (it != null) {
          it.dispose();
        }
        if (base != null) {
          base.dispose();
        }
      }

    } finally {
      if (db != null) {
        db.close();
      }
      if (options != null) {
        options.dispose();
      }
    }
  }
}

@@ -669,9 +669,339 @@
 sdb.
-*
+WriteBatchWithIndex;%0Aimport org.rocksdb.DirectSlice;%0Aimport org.rocksdb.Options;%0Aimport org.rocksdb.RocksDB;%0Aimport org.rocksdb.RocksDBException;%0Aimport org.rocksdb.RocksIterator;%0Aimport org.rocksdb.WriteOptions;%0Aimport org.rocksdb.WBWIRocksIterator;%0A%0Aimport java.nio.ByteBuffer;%0Aimport java.util.ArrayDeque;%0Aimport java.util.Deque
 ;%0A%0Ai
@@ -3732,10 +3732,1007 @@
   %7D%0A  %7D%0A
-%7D
+%0A  @Test%0A  public void write_writeBatchWithIndex() throws RocksDBException %7B%0A    RocksDB db = null;%0A    Options options = null;%0A    try %7B%0A      options = new Options();%0A      // Setup options%0A      options.setCreateIfMissing(true);%0A      db = RocksDB.open(options, dbFolder.getRoot().getAbsolutePath());%0A%0A      final byte%5B%5D k1 = %22key1%22.getBytes();%0A      final byte%5B%5D v1 = %22value1%22.getBytes();%0A      final byte%5B%5D k2 = %22key2%22.getBytes();%0A      final byte%5B%5D v2 = %22value2%22.getBytes();%0A%0A      WriteBatchWithIndex wbwi = null;%0A%0A      try %7B%0A        wbwi = new WriteBatchWithIndex();%0A%0A%0A        wbwi.put(k1, v1);%0A        wbwi.put(k2, v2);%0A%0A        db.write(new WriteOptions(), wbwi);%0A      %7D finally %7B%0A        if(wbwi != null) %7B%0A          wbwi.dispose();%0A        %7D%0A      %7D%0A%0A      assertThat(db.get(k1)).isEqualTo(v1);%0A      assertThat(db.get(k2)).isEqualTo(v2);%0A%0A    %7D finally %7B%0A      if (db != null) %7B%0A        db.close();%0A      %7D%0A      if (options != null) %7B%0A        options.dispose();%0A      %7D%0A    %7D%0A  %7D%0A%7D%0A
 %0A

Test for RocksDB#write(WriteBatchWithIndex)