summaryrefslogtreecommitdiffstats
path: root/src/rocksdb/java/samples
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/rocksdb/java/samples/src/main/java/OptimisticTransactionSample.java184
-rw-r--r--src/rocksdb/java/samples/src/main/java/RocksDBColumnFamilySample.java78
-rw-r--r--src/rocksdb/java/samples/src/main/java/RocksDBSample.java296
-rw-r--r--src/rocksdb/java/samples/src/main/java/TransactionSample.java183
4 files changed, 741 insertions, 0 deletions
diff --git a/src/rocksdb/java/samples/src/main/java/OptimisticTransactionSample.java b/src/rocksdb/java/samples/src/main/java/OptimisticTransactionSample.java
new file mode 100644
index 000000000..7e7a22e94
--- /dev/null
+++ b/src/rocksdb/java/samples/src/main/java/OptimisticTransactionSample.java
@@ -0,0 +1,184 @@
+// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
+// This source code is licensed under both the GPLv2 (found in the
+// COPYING file in the root directory) and Apache 2.0 License
+// (found in the LICENSE.Apache file in the root directory).
+
+import org.rocksdb.*;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+/**
+ * Demonstrates using Transactions on an OptimisticTransactionDB with
+ * varying isolation guarantees
+ */
+public class OptimisticTransactionSample {
+ private static final String dbPath = "/tmp/rocksdb_optimistic_transaction_example";
+
+ public static final void main(final String args[]) throws RocksDBException {
+
+ try(final Options options = new Options()
+ .setCreateIfMissing(true);
+ final OptimisticTransactionDB txnDb =
+ OptimisticTransactionDB.open(options, dbPath)) {
+
+ try (final WriteOptions writeOptions = new WriteOptions();
+ final ReadOptions readOptions = new ReadOptions()) {
+
+ ////////////////////////////////////////////////////////
+ //
+ // Simple OptimisticTransaction Example ("Read Committed")
+ //
+ ////////////////////////////////////////////////////////
+ readCommitted(txnDb, writeOptions, readOptions);
+
+
+ ////////////////////////////////////////////////////////
+ //
+ // "Repeatable Read" (Snapshot Isolation) Example
+ // -- Using a single Snapshot
+ //
+ ////////////////////////////////////////////////////////
+ repeatableRead(txnDb, writeOptions, readOptions);
+
+
+ ////////////////////////////////////////////////////////
+ //
+ // "Read Committed" (Monotonic Atomic Views) Example
+ // --Using multiple Snapshots
+ //
+ ////////////////////////////////////////////////////////
+ readCommitted_monotonicAtomicViews(txnDb, writeOptions, readOptions);
+ }
+ }
+ }
+
+ /**
+ * Demonstrates "Read Committed" isolation
+ */
+ private static void readCommitted(final OptimisticTransactionDB txnDb,
+ final WriteOptions writeOptions, final ReadOptions readOptions)
+ throws RocksDBException {
+ final byte key1[] = "abc".getBytes(UTF_8);
+ final byte value1[] = "def".getBytes(UTF_8);
+
+ final byte key2[] = "xyz".getBytes(UTF_8);
+ final byte value2[] = "zzz".getBytes(UTF_8);
+
+ // Start a transaction
+ try(final Transaction txn = txnDb.beginTransaction(writeOptions)) {
+ // Read a key in this transaction
+ byte[] value = txn.get(readOptions, key1);
+ assert(value == null);
+
+ // Write a key in this transaction
+ txn.put(key1, value1);
+
+ // Read a key OUTSIDE this transaction. Does not affect txn.
+ value = txnDb.get(readOptions, key1);
+ assert(value == null);
+
+ // Write a key OUTSIDE of this transaction.
+ // Does not affect txn since this is an unrelated key.
+ // If we wrote key 'abc' here, the transaction would fail to commit.
+ txnDb.put(writeOptions, key2, value2);
+
+ // Commit transaction
+ txn.commit();
+ }
+ }
+
+ /**
+ * Demonstrates "Repeatable Read" (Snapshot Isolation) isolation
+ */
+ private static void repeatableRead(final OptimisticTransactionDB txnDb,
+ final WriteOptions writeOptions, final ReadOptions readOptions)
+ throws RocksDBException {
+
+ final byte key1[] = "ghi".getBytes(UTF_8);
+ final byte value1[] = "jkl".getBytes(UTF_8);
+
+ // Set a snapshot at start of transaction by setting setSnapshot(true)
+ try(final OptimisticTransactionOptions txnOptions =
+ new OptimisticTransactionOptions().setSetSnapshot(true);
+ final Transaction txn =
+ txnDb.beginTransaction(writeOptions, txnOptions)) {
+
+ final Snapshot snapshot = txn.getSnapshot();
+
+ // Write a key OUTSIDE of transaction
+ txnDb.put(writeOptions, key1, value1);
+
+ // Read a key using the snapshot.
+ readOptions.setSnapshot(snapshot);
+ final byte[] value = txn.getForUpdate(readOptions, key1, true);
+ assert (value == null);
+
+ try {
+ // Attempt to commit transaction
+ txn.commit();
+ throw new IllegalStateException();
+ } catch(final RocksDBException e) {
+ // Transaction could not commit since the write outside of the txn
+ // conflicted with the read!
+ assert(e.getStatus().getCode() == Status.Code.Busy);
+ }
+
+ txn.rollback();
+ } finally {
+ // Clear snapshot from read options since it is no longer valid
+ readOptions.setSnapshot(null);
+ }
+ }
+
+ /**
+ * Demonstrates "Read Committed" (Monotonic Atomic Views) isolation
+ *
+ * In this example, we set the snapshot multiple times. This is probably
+ * only necessary if you have very strict isolation requirements to
+ * implement.
+ */
+ private static void readCommitted_monotonicAtomicViews(
+ final OptimisticTransactionDB txnDb, final WriteOptions writeOptions,
+ final ReadOptions readOptions) throws RocksDBException {
+
+ final byte keyX[] = "x".getBytes(UTF_8);
+ final byte valueX[] = "x".getBytes(UTF_8);
+
+ final byte keyY[] = "y".getBytes(UTF_8);
+ final byte valueY[] = "y".getBytes(UTF_8);
+
+ try (final OptimisticTransactionOptions txnOptions =
+ new OptimisticTransactionOptions().setSetSnapshot(true);
+ final Transaction txn =
+ txnDb.beginTransaction(writeOptions, txnOptions)) {
+
+ // Do some reads and writes to key "x"
+ Snapshot snapshot = txnDb.getSnapshot();
+ readOptions.setSnapshot(snapshot);
+ byte[] value = txn.get(readOptions, keyX);
+ txn.put(valueX, valueX);
+
+ // Do a write outside of the transaction to key "y"
+ txnDb.put(writeOptions, keyY, valueY);
+
+ // Set a new snapshot in the transaction
+ txn.setSnapshot();
+ snapshot = txnDb.getSnapshot();
+ readOptions.setSnapshot(snapshot);
+
+ // Do some reads and writes to key "y"
+ // Since the snapshot was advanced, the write done outside of the
+ // transaction does not conflict.
+ value = txn.getForUpdate(readOptions, keyY, true);
+ txn.put(keyY, valueY);
+
+ // Commit. Since the snapshot was advanced, the write done outside of the
+ // transaction does not prevent this transaction from Committing.
+ txn.commit();
+
+ } finally {
+ // Clear snapshot from read options since it is no longer valid
+ readOptions.setSnapshot(null);
+ }
+ }
+}
diff --git a/src/rocksdb/java/samples/src/main/java/RocksDBColumnFamilySample.java b/src/rocksdb/java/samples/src/main/java/RocksDBColumnFamilySample.java
new file mode 100644
index 000000000..72f5731a1
--- /dev/null
+++ b/src/rocksdb/java/samples/src/main/java/RocksDBColumnFamilySample.java
@@ -0,0 +1,78 @@
+// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
+// This source code is licensed under both the GPLv2 (found in the
+// COPYING file in the root directory) and Apache 2.0 License
+// (found in the LICENSE.Apache file in the root directory).
+
+import org.rocksdb.*;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class RocksDBColumnFamilySample {
+ static {
+ RocksDB.loadLibrary();
+ }
+
+ public static void main(final String[] args) throws RocksDBException {
+ if (args.length < 1) {
+ System.out.println(
+ "usage: RocksDBColumnFamilySample db_path");
+ System.exit(-1);
+ }
+
+ final String db_path = args[0];
+
+ System.out.println("RocksDBColumnFamilySample");
+ try(final Options options = new Options().setCreateIfMissing(true);
+ final RocksDB db = RocksDB.open(options, db_path)) {
+
+ assert(db != null);
+
+ // create column family
+ try(final ColumnFamilyHandle columnFamilyHandle = db.createColumnFamily(
+ new ColumnFamilyDescriptor("new_cf".getBytes(),
+ new ColumnFamilyOptions()))) {
+ assert (columnFamilyHandle != null);
+ }
+ }
+
+ // open DB with two column families
+ final List<ColumnFamilyDescriptor> columnFamilyDescriptors =
+ new ArrayList<>();
+ // have to open default column family
+ columnFamilyDescriptors.add(new ColumnFamilyDescriptor(
+ RocksDB.DEFAULT_COLUMN_FAMILY, new ColumnFamilyOptions()));
+ // open the new one, too
+ columnFamilyDescriptors.add(new ColumnFamilyDescriptor(
+ "new_cf".getBytes(), new ColumnFamilyOptions()));
+ final List<ColumnFamilyHandle> columnFamilyHandles = new ArrayList<>();
+ try(final DBOptions options = new DBOptions();
+ final RocksDB db = RocksDB.open(options, db_path,
+ columnFamilyDescriptors, columnFamilyHandles)) {
+ assert(db != null);
+
+ try {
+ // put and get from non-default column family
+ db.put(
+ columnFamilyHandles.get(1), new WriteOptions(), "key".getBytes(), "value".getBytes());
+
+ // atomic write
+ try (final WriteBatch wb = new WriteBatch()) {
+ wb.put(columnFamilyHandles.get(0), "key2".getBytes(),
+ "value2".getBytes());
+ wb.put(columnFamilyHandles.get(1), "key3".getBytes(),
+ "value3".getBytes());
+ wb.delete(columnFamilyHandles.get(1), "key".getBytes());
+ db.write(new WriteOptions(), wb);
+ }
+
+ // drop column family
+ db.dropColumnFamily(columnFamilyHandles.get(1));
+ } finally {
+ for (final ColumnFamilyHandle handle : columnFamilyHandles) {
+ handle.close();
+ }
+ }
+ }
+ }
+}
diff --git a/src/rocksdb/java/samples/src/main/java/RocksDBSample.java b/src/rocksdb/java/samples/src/main/java/RocksDBSample.java
new file mode 100644
index 000000000..ea650b141
--- /dev/null
+++ b/src/rocksdb/java/samples/src/main/java/RocksDBSample.java
@@ -0,0 +1,296 @@
+// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
+// This source code is licensed under both the GPLv2 (found in the
+// COPYING file in the root directory) and Apache 2.0 License
+// (found in the LICENSE.Apache file in the root directory).
+
+import java.lang.IllegalArgumentException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.ArrayList;
+
+import org.rocksdb.*;
+import org.rocksdb.util.SizeUnit;
+
+public class RocksDBSample {
+ static {
+ RocksDB.loadLibrary();
+ }
+
+ public static void main(final String[] args) {
+ if (args.length < 1) {
+ System.out.println("usage: RocksDBSample db_path");
+ System.exit(-1);
+ }
+
+ final String db_path = args[0];
+ final String db_path_not_found = db_path + "_not_found";
+
+ System.out.println("RocksDBSample");
+ try (final Options options = new Options();
+ final Filter bloomFilter = new BloomFilter(10);
+ final ReadOptions readOptions = new ReadOptions()
+ .setFillCache(false);
+ final Statistics stats = new Statistics();
+ final RateLimiter rateLimiter = new RateLimiter(10000000,10000, 10)) {
+
+ try (final RocksDB db = RocksDB.open(options, db_path_not_found)) {
+ assert (false);
+ } catch (final RocksDBException e) {
+ System.out.format("Caught the expected exception -- %s\n", e);
+ }
+
+ try {
+ options.setCreateIfMissing(true)
+ .setStatistics(stats)
+ .setWriteBufferSize(8 * SizeUnit.KB)
+ .setMaxWriteBufferNumber(3)
+ .setMaxBackgroundJobs(10)
+ .setCompressionType(CompressionType.ZLIB_COMPRESSION)
+ .setCompactionStyle(CompactionStyle.UNIVERSAL);
+ } catch (final IllegalArgumentException e) {
+ assert (false);
+ }
+
+ assert (options.createIfMissing() == true);
+ assert (options.writeBufferSize() == 8 * SizeUnit.KB);
+ assert (options.maxWriteBufferNumber() == 3);
+ assert (options.maxBackgroundJobs() == 10);
+ assert (options.compressionType() == CompressionType.ZLIB_COMPRESSION);
+ assert (options.compactionStyle() == CompactionStyle.UNIVERSAL);
+
+ assert (options.memTableFactoryName().equals("SkipListFactory"));
+ options.setMemTableConfig(
+ new HashSkipListMemTableConfig()
+ .setHeight(4)
+ .setBranchingFactor(4)
+ .setBucketCount(2000000));
+ assert (options.memTableFactoryName().equals("HashSkipListRepFactory"));
+
+ options.setMemTableConfig(
+ new HashLinkedListMemTableConfig()
+ .setBucketCount(100000));
+ assert (options.memTableFactoryName().equals("HashLinkedListRepFactory"));
+
+ options.setMemTableConfig(
+ new VectorMemTableConfig().setReservedSize(10000));
+ assert (options.memTableFactoryName().equals("VectorRepFactory"));
+
+ options.setMemTableConfig(new SkipListMemTableConfig());
+ assert (options.memTableFactoryName().equals("SkipListFactory"));
+
+ options.setTableFormatConfig(new PlainTableConfig());
+ // Plain-Table requires mmap read
+ options.setAllowMmapReads(true);
+ assert (options.tableFactoryName().equals("PlainTable"));
+
+ options.setRateLimiter(rateLimiter);
+
+ final BlockBasedTableConfig table_options = new BlockBasedTableConfig();
+ Cache cache = new LRUCache(64 * 1024, 6);
+ table_options.setBlockCache(cache)
+ .setFilterPolicy(bloomFilter)
+ .setBlockSizeDeviation(5)
+ .setBlockRestartInterval(10)
+ .setCacheIndexAndFilterBlocks(true)
+ .setBlockCacheCompressed(new LRUCache(64 * 1000, 10));
+
+ assert (table_options.blockSizeDeviation() == 5);
+ assert (table_options.blockRestartInterval() == 10);
+ assert (table_options.cacheIndexAndFilterBlocks() == true);
+
+ options.setTableFormatConfig(table_options);
+ assert (options.tableFactoryName().equals("BlockBasedTable"));
+
+ try (final RocksDB db = RocksDB.open(options, db_path)) {
+ db.put("hello".getBytes(), "world".getBytes());
+
+ final byte[] value = db.get("hello".getBytes());
+ assert ("world".equals(new String(value)));
+
+ final String str = db.getProperty("rocksdb.stats");
+ assert (str != null && !str.equals(""));
+ } catch (final RocksDBException e) {
+ System.out.format("[ERROR] caught the unexpected exception -- %s\n", e);
+ assert (false);
+ }
+
+ try (final RocksDB db = RocksDB.open(options, db_path)) {
+ db.put("hello".getBytes(), "world".getBytes());
+ byte[] value = db.get("hello".getBytes());
+ System.out.format("Get('hello') = %s\n",
+ new String(value));
+
+ for (int i = 1; i <= 9; ++i) {
+ for (int j = 1; j <= 9; ++j) {
+ db.put(String.format("%dx%d", i, j).getBytes(),
+ String.format("%d", i * j).getBytes());
+ }
+ }
+
+ for (int i = 1; i <= 9; ++i) {
+ for (int j = 1; j <= 9; ++j) {
+ System.out.format("%s ", new String(db.get(
+ String.format("%dx%d", i, j).getBytes())));
+ }
+ System.out.println("");
+ }
+
+ // write batch test
+ try (final WriteOptions writeOpt = new WriteOptions()) {
+ for (int i = 10; i <= 19; ++i) {
+ try (final WriteBatch batch = new WriteBatch()) {
+ for (int j = 10; j <= 19; ++j) {
+ batch.put(String.format("%dx%d", i, j).getBytes(),
+ String.format("%d", i * j).getBytes());
+ }
+ db.write(writeOpt, batch);
+ }
+ }
+ }
+ for (int i = 10; i <= 19; ++i) {
+ for (int j = 10; j <= 19; ++j) {
+ assert (new String(
+ db.get(String.format("%dx%d", i, j).getBytes())).equals(
+ String.format("%d", i * j)));
+ System.out.format("%s ", new String(db.get(
+ String.format("%dx%d", i, j).getBytes())));
+ }
+ System.out.println("");
+ }
+
+ value = db.get("1x1".getBytes());
+ assert (value != null);
+ value = db.get("world".getBytes());
+ assert (value == null);
+ value = db.get(readOptions, "world".getBytes());
+ assert (value == null);
+
+ final byte[] testKey = "asdf".getBytes();
+ final byte[] testValue =
+ "asdfghjkl;'?><MNBVCXZQWERTYUIOP{+_)(*&^%$#@".getBytes();
+ db.put(testKey, testValue);
+ byte[] testResult = db.get(testKey);
+ assert (testResult != null);
+ assert (Arrays.equals(testValue, testResult));
+ assert (new String(testValue).equals(new String(testResult)));
+ testResult = db.get(readOptions, testKey);
+ assert (testResult != null);
+ assert (Arrays.equals(testValue, testResult));
+ assert (new String(testValue).equals(new String(testResult)));
+
+ final byte[] insufficientArray = new byte[10];
+ final byte[] enoughArray = new byte[50];
+ int len;
+ len = db.get(testKey, insufficientArray);
+ assert (len > insufficientArray.length);
+ len = db.get("asdfjkl;".getBytes(), enoughArray);
+ assert (len == RocksDB.NOT_FOUND);
+ len = db.get(testKey, enoughArray);
+ assert (len == testValue.length);
+
+ len = db.get(readOptions, testKey, insufficientArray);
+ assert (len > insufficientArray.length);
+ len = db.get(readOptions, "asdfjkl;".getBytes(), enoughArray);
+ assert (len == RocksDB.NOT_FOUND);
+ len = db.get(readOptions, testKey, enoughArray);
+ assert (len == testValue.length);
+
+ db.delete(testKey);
+ len = db.get(testKey, enoughArray);
+ assert (len == RocksDB.NOT_FOUND);
+
+ // repeat the test with WriteOptions
+ try (final WriteOptions writeOpts = new WriteOptions()) {
+ writeOpts.setSync(true);
+ writeOpts.setDisableWAL(false);
+ db.put(writeOpts, testKey, testValue);
+ len = db.get(testKey, enoughArray);
+ assert (len == testValue.length);
+ assert (new String(testValue).equals(
+ new String(enoughArray, 0, len)));
+ }
+
+ try {
+ for (final TickerType statsType : TickerType.values()) {
+ if (statsType != TickerType.TICKER_ENUM_MAX) {
+ stats.getTickerCount(statsType);
+ }
+ }
+ System.out.println("getTickerCount() passed.");
+ } catch (final Exception e) {
+ System.out.println("Failed in call to getTickerCount()");
+ assert (false); //Should never reach here.
+ }
+
+ try {
+ for (final HistogramType histogramType : HistogramType.values()) {
+ if (histogramType != HistogramType.HISTOGRAM_ENUM_MAX) {
+ HistogramData data = stats.getHistogramData(histogramType);
+ }
+ }
+ System.out.println("getHistogramData() passed.");
+ } catch (final Exception e) {
+ System.out.println("Failed in call to getHistogramData()");
+ assert (false); //Should never reach here.
+ }
+
+ try (final RocksIterator iterator = db.newIterator()) {
+
+ boolean seekToFirstPassed = false;
+ for (iterator.seekToFirst(); iterator.isValid(); iterator.next()) {
+ iterator.status();
+ assert (iterator.key() != null);
+ assert (iterator.value() != null);
+ seekToFirstPassed = true;
+ }
+ if (seekToFirstPassed) {
+ System.out.println("iterator seekToFirst tests passed.");
+ }
+
+ boolean seekToLastPassed = false;
+ for (iterator.seekToLast(); iterator.isValid(); iterator.prev()) {
+ iterator.status();
+ assert (iterator.key() != null);
+ assert (iterator.value() != null);
+ seekToLastPassed = true;
+ }
+
+ if (seekToLastPassed) {
+ System.out.println("iterator seekToLastPassed tests passed.");
+ }
+
+ iterator.seekToFirst();
+ iterator.seek(iterator.key());
+ assert (iterator.key() != null);
+ assert (iterator.value() != null);
+
+ System.out.println("iterator seek test passed.");
+
+ }
+ System.out.println("iterator tests passed.");
+
+ final List<byte[]> keys = new ArrayList<>();
+ try (final RocksIterator iterator = db.newIterator()) {
+ for (iterator.seekToLast(); iterator.isValid(); iterator.prev()) {
+ keys.add(iterator.key());
+ }
+ }
+
+ List<byte[]> values = db.multiGetAsList(keys);
+ assert (values.size() == keys.size());
+ for (final byte[] value1 : values) {
+ assert (value1 != null);
+ }
+
+ values = db.multiGetAsList(new ReadOptions(), keys);
+ assert (values.size() == keys.size());
+ for (final byte[] value1 : values) {
+ assert (value1 != null);
+ }
+ } catch (final RocksDBException e) {
+ System.err.println(e);
+ }
+ }
+ }
+}
diff --git a/src/rocksdb/java/samples/src/main/java/TransactionSample.java b/src/rocksdb/java/samples/src/main/java/TransactionSample.java
new file mode 100644
index 000000000..b88a68f12
--- /dev/null
+++ b/src/rocksdb/java/samples/src/main/java/TransactionSample.java
@@ -0,0 +1,183 @@
+// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
+// This source code is licensed under both the GPLv2 (found in the
+// COPYING file in the root directory) and Apache 2.0 License
+// (found in the LICENSE.Apache file in the root directory).
+
+import org.rocksdb.*;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+/**
+ * Demonstrates using Transactions on a TransactionDB with
+ * varying isolation guarantees
+ */
+public class TransactionSample {
+ private static final String dbPath = "/tmp/rocksdb_transaction_example";
+
+ public static final void main(final String args[]) throws RocksDBException {
+
+ try(final Options options = new Options()
+ .setCreateIfMissing(true);
+ final TransactionDBOptions txnDbOptions = new TransactionDBOptions();
+ final TransactionDB txnDb =
+ TransactionDB.open(options, txnDbOptions, dbPath)) {
+
+ try (final WriteOptions writeOptions = new WriteOptions();
+ final ReadOptions readOptions = new ReadOptions()) {
+
+ ////////////////////////////////////////////////////////
+ //
+ // Simple Transaction Example ("Read Committed")
+ //
+ ////////////////////////////////////////////////////////
+ readCommitted(txnDb, writeOptions, readOptions);
+
+
+ ////////////////////////////////////////////////////////
+ //
+ // "Repeatable Read" (Snapshot Isolation) Example
+ // -- Using a single Snapshot
+ //
+ ////////////////////////////////////////////////////////
+ repeatableRead(txnDb, writeOptions, readOptions);
+
+
+ ////////////////////////////////////////////////////////
+ //
+ // "Read Committed" (Monotonic Atomic Views) Example
+ // --Using multiple Snapshots
+ //
+ ////////////////////////////////////////////////////////
+ readCommitted_monotonicAtomicViews(txnDb, writeOptions, readOptions);
+ }
+ }
+ }
+
+ /**
+ * Demonstrates "Read Committed" isolation
+ */
+ private static void readCommitted(final TransactionDB txnDb,
+ final WriteOptions writeOptions, final ReadOptions readOptions)
+ throws RocksDBException {
+ final byte key1[] = "abc".getBytes(UTF_8);
+ final byte value1[] = "def".getBytes(UTF_8);
+
+ final byte key2[] = "xyz".getBytes(UTF_8);
+ final byte value2[] = "zzz".getBytes(UTF_8);
+
+ // Start a transaction
+ try(final Transaction txn = txnDb.beginTransaction(writeOptions)) {
+ // Read a key in this transaction
+ byte[] value = txn.get(readOptions, key1);
+ assert(value == null);
+
+ // Write a key in this transaction
+ txn.put(key1, value1);
+
+ // Read a key OUTSIDE this transaction. Does not affect txn.
+ value = txnDb.get(readOptions, key1);
+ assert(value == null);
+
+ // Write a key OUTSIDE of this transaction.
+ // Does not affect txn since this is an unrelated key.
+ // If we wrote key 'abc' here, the transaction would fail to commit.
+ txnDb.put(writeOptions, key2, value2);
+
+ // Commit transaction
+ txn.commit();
+ }
+ }
+
+ /**
+ * Demonstrates "Repeatable Read" (Snapshot Isolation) isolation
+ */
+ private static void repeatableRead(final TransactionDB txnDb,
+ final WriteOptions writeOptions, final ReadOptions readOptions)
+ throws RocksDBException {
+
+ final byte key1[] = "ghi".getBytes(UTF_8);
+ final byte value1[] = "jkl".getBytes(UTF_8);
+
+ // Set a snapshot at start of transaction by setting setSnapshot(true)
+ try(final TransactionOptions txnOptions = new TransactionOptions()
+ .setSetSnapshot(true);
+ final Transaction txn =
+ txnDb.beginTransaction(writeOptions, txnOptions)) {
+
+ final Snapshot snapshot = txn.getSnapshot();
+
+ // Write a key OUTSIDE of transaction
+ txnDb.put(writeOptions, key1, value1);
+
+ // Attempt to read a key using the snapshot. This will fail since
+ // the previous write outside this txn conflicts with this read.
+ readOptions.setSnapshot(snapshot);
+
+ try {
+ final byte[] value = txn.getForUpdate(readOptions, key1, true);
+ throw new IllegalStateException();
+ } catch(final RocksDBException e) {
+ assert(e.getStatus().getCode() == Status.Code.Busy);
+ }
+
+ txn.rollback();
+ } finally {
+ // Clear snapshot from read options since it is no longer valid
+ readOptions.setSnapshot(null);
+ }
+ }
+
+ /**
+ * Demonstrates "Read Committed" (Monotonic Atomic Views) isolation
+ *
+ * In this example, we set the snapshot multiple times. This is probably
+ * only necessary if you have very strict isolation requirements to
+ * implement.
+ */
+ private static void readCommitted_monotonicAtomicViews(
+ final TransactionDB txnDb, final WriteOptions writeOptions,
+ final ReadOptions readOptions) throws RocksDBException {
+
+ final byte keyX[] = "x".getBytes(UTF_8);
+ final byte valueX[] = "x".getBytes(UTF_8);
+
+ final byte keyY[] = "y".getBytes(UTF_8);
+ final byte valueY[] = "y".getBytes(UTF_8);
+
+ try (final TransactionOptions txnOptions = new TransactionOptions()
+ .setSetSnapshot(true);
+ final Transaction txn =
+ txnDb.beginTransaction(writeOptions, txnOptions)) {
+
+ // Do some reads and writes to key "x"
+ Snapshot snapshot = txnDb.getSnapshot();
+ readOptions.setSnapshot(snapshot);
+ byte[] value = txn.get(readOptions, keyX);
+ txn.put(valueX, valueX);
+
+ // Do a write outside of the transaction to key "y"
+ txnDb.put(writeOptions, keyY, valueY);
+
+ // Set a new snapshot in the transaction
+ txn.setSnapshot();
+ txn.setSavePoint();
+ snapshot = txnDb.getSnapshot();
+ readOptions.setSnapshot(snapshot);
+
+ // Do some reads and writes to key "y"
+ // Since the snapshot was advanced, the write done outside of the
+ // transaction does not conflict.
+ value = txn.getForUpdate(readOptions, keyY, true);
+ txn.put(keyY, valueY);
+
+ // Decide we want to revert the last write from this transaction.
+ txn.rollbackToSavePoint();
+
+ // Commit.
+ txn.commit();
+ } finally {
+ // Clear snapshot from read options since it is no longer valid
+ readOptions.setSnapshot(null);
+ }
+ }
+}