Transaction multiGet convert to list-based (#9522)
Summary: Transaction multiGet convert to list-based. RocksDB Java (non-transactional) has multiGetAsList() methods to expose multiGet(). These return a list of results. These methods replaced multiGet() methods returning an array of results, which were deprecated in Rocks 6 and are being removed in Rocks 7. The transactional API still presents multiGet() methods returning arrays, so in Rocks 7 we replace these with multiGetAsList()methods and deprecate the multiGet() methods. This does not require any changes to the supporting JNI/C++ code, only to the wrappers which present the Java API. Pull Request resolved: https://github.com/facebook/rocksdb/pull/9522 Reviewed By: mrambacher Differential Revision: D34114373 Pulled By: jay-zhuang fbshipit-source-id: cb22d6095934d951b6aee4aed3e07923d3c18007
This commit is contained in:
parent
479eb1aad6
commit
eed71dfa82
@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
package org.rocksdb;
|
package org.rocksdb;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -310,7 +312,7 @@ public class Transaction extends RocksObject {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* This function is similar to
|
* This function is similar to
|
||||||
* {@link RocksDB#multiGet(ReadOptions, List, List)} except it will
|
* {@link RocksDB#multiGetAsList} except it will
|
||||||
* also read pending changes in this transaction.
|
* also read pending changes in this transaction.
|
||||||
* Currently, this function will return Status::MergeInProgress if the most
|
* Currently, this function will return Status::MergeInProgress if the most
|
||||||
* recent write to the queried key in this batch is a Merge.
|
* recent write to the queried key in this batch is a Merge.
|
||||||
@ -336,9 +338,10 @@ public class Transaction extends RocksObject {
|
|||||||
* @throws IllegalArgumentException thrown if the size of passed keys is not
|
* @throws IllegalArgumentException thrown if the size of passed keys is not
|
||||||
* equal to the amount of passed column family handles.
|
* equal to the amount of passed column family handles.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public byte[][] multiGet(final ReadOptions readOptions,
|
public byte[][] multiGet(final ReadOptions readOptions,
|
||||||
final List<ColumnFamilyHandle> columnFamilyHandles,
|
final List<ColumnFamilyHandle> columnFamilyHandles, final byte[][] keys)
|
||||||
final byte[][] keys) throws RocksDBException {
|
throws RocksDBException {
|
||||||
assert(isOwningHandle());
|
assert(isOwningHandle());
|
||||||
// Check if key size equals cfList size. If not a exception must be
|
// Check if key size equals cfList size. If not a exception must be
|
||||||
// thrown. If not a Segmentation fault happens.
|
// thrown. If not a Segmentation fault happens.
|
||||||
@ -360,7 +363,57 @@ public class Transaction extends RocksObject {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* This function is similar to
|
* This function is similar to
|
||||||
* {@link RocksDB#multiGet(ReadOptions, List)} except it will
|
* {@link RocksDB#multiGetAsList(ReadOptions, List, List)} except it will
|
||||||
|
* also read pending changes in this transaction.
|
||||||
|
* Currently, this function will return Status::MergeInProgress if the most
|
||||||
|
* recent write to the queried key in this batch is a Merge.
|
||||||
|
*
|
||||||
|
* If {@link ReadOptions#snapshot()} is not set, the current version of the
|
||||||
|
* key will be read. Calling {@link #setSnapshot()} does not affect the
|
||||||
|
* version of the data returned.
|
||||||
|
*
|
||||||
|
* Note that setting {@link ReadOptions#setSnapshot(Snapshot)} will affect
|
||||||
|
* what is read from the DB but will NOT change which keys are read from this
|
||||||
|
* transaction (the keys in this transaction do not yet belong to any snapshot
|
||||||
|
* and will be fetched regardless).
|
||||||
|
*
|
||||||
|
* @param readOptions Read options.
|
||||||
|
* @param columnFamilyHandles {@link java.util.List} containing
|
||||||
|
* {@link org.rocksdb.ColumnFamilyHandle} instances.
|
||||||
|
* @param keys of keys for which values need to be retrieved.
|
||||||
|
*
|
||||||
|
* @return Array of values, one for each key
|
||||||
|
*
|
||||||
|
* @throws RocksDBException thrown if error happens in underlying
|
||||||
|
* native library.
|
||||||
|
* @throws IllegalArgumentException thrown if the size of passed keys is not
|
||||||
|
* equal to the amount of passed column family handles.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public List<byte[]> multiGetAsList(final ReadOptions readOptions,
|
||||||
|
final List<ColumnFamilyHandle> columnFamilyHandles, final List<byte[]> keys)
|
||||||
|
throws RocksDBException {
|
||||||
|
assert (isOwningHandle());
|
||||||
|
// Check if key size equals cfList size. If not a exception must be
|
||||||
|
// thrown. If not a Segmentation fault happens.
|
||||||
|
if (keys.size() != columnFamilyHandles.size()) {
|
||||||
|
throw new IllegalArgumentException("For each key there must be a ColumnFamilyHandle.");
|
||||||
|
}
|
||||||
|
if (keys.size() == 0) {
|
||||||
|
return new ArrayList<>(0);
|
||||||
|
}
|
||||||
|
final byte[][] keysArray = keys.toArray(new byte[keys.size()][]);
|
||||||
|
final long[] cfHandles = new long[columnFamilyHandles.size()];
|
||||||
|
for (int i = 0; i < columnFamilyHandles.size(); i++) {
|
||||||
|
cfHandles[i] = columnFamilyHandles.get(i).nativeHandle_;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Arrays.asList(multiGet(nativeHandle_, readOptions.nativeHandle_, keysArray, cfHandles));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function is similar to
|
||||||
|
* {@link RocksDB#multiGetAsList} except it will
|
||||||
* also read pending changes in this transaction.
|
* also read pending changes in this transaction.
|
||||||
* Currently, this function will return Status::MergeInProgress if the most
|
* Currently, this function will return Status::MergeInProgress if the most
|
||||||
* recent write to the queried key in this batch is a Merge.
|
* recent write to the queried key in this batch is a Merge.
|
||||||
@ -383,8 +436,9 @@ public class Transaction extends RocksObject {
|
|||||||
* @throws RocksDBException thrown if error happens in underlying
|
* @throws RocksDBException thrown if error happens in underlying
|
||||||
* native library.
|
* native library.
|
||||||
*/
|
*/
|
||||||
public byte[][] multiGet(final ReadOptions readOptions,
|
@Deprecated
|
||||||
final byte[][] keys) throws RocksDBException {
|
public byte[][] multiGet(final ReadOptions readOptions, final byte[][] keys)
|
||||||
|
throws RocksDBException {
|
||||||
assert(isOwningHandle());
|
assert(isOwningHandle());
|
||||||
if(keys.length == 0) {
|
if(keys.length == 0) {
|
||||||
return new byte[0][0];
|
return new byte[0][0];
|
||||||
@ -394,6 +448,41 @@ public class Transaction extends RocksObject {
|
|||||||
keys);
|
keys);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function is similar to
|
||||||
|
* {@link RocksDB#multiGetAsList} except it will
|
||||||
|
* also read pending changes in this transaction.
|
||||||
|
* Currently, this function will return Status::MergeInProgress if the most
|
||||||
|
* recent write to the queried key in this batch is a Merge.
|
||||||
|
*
|
||||||
|
* If {@link ReadOptions#snapshot()} is not set, the current version of the
|
||||||
|
* key will be read. Calling {@link #setSnapshot()} does not affect the
|
||||||
|
* version of the data returned.
|
||||||
|
*
|
||||||
|
* Note that setting {@link ReadOptions#setSnapshot(Snapshot)} will affect
|
||||||
|
* what is read from the DB but will NOT change which keys are read from this
|
||||||
|
* transaction (the keys in this transaction do not yet belong to any snapshot
|
||||||
|
* and will be fetched regardless).
|
||||||
|
*
|
||||||
|
* @param readOptions Read options.=
|
||||||
|
* {@link org.rocksdb.ColumnFamilyHandle} instances.
|
||||||
|
* @param keys of keys for which values need to be retrieved.
|
||||||
|
*
|
||||||
|
* @return Array of values, one for each key
|
||||||
|
*
|
||||||
|
* @throws RocksDBException thrown if error happens in underlying
|
||||||
|
* native library.
|
||||||
|
*/
|
||||||
|
public List<byte[]> multiGetAsList(final ReadOptions readOptions, final List<byte[]> keys)
|
||||||
|
throws RocksDBException {
|
||||||
|
if (keys.size() == 0) {
|
||||||
|
return new ArrayList<>(0);
|
||||||
|
}
|
||||||
|
final byte[][] keysArray = keys.toArray(new byte[keys.size()][]);
|
||||||
|
|
||||||
|
return Arrays.asList(multiGet(nativeHandle_, readOptions.nativeHandle_, keysArray));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read this key and ensure that this transaction will only
|
* Read this key and ensure that this transaction will only
|
||||||
* be able to be committed if this key is not written outside this
|
* be able to be committed if this key is not written outside this
|
||||||
@ -541,9 +630,10 @@ public class Transaction extends RocksObject {
|
|||||||
* @throws RocksDBException thrown if error happens in underlying
|
* @throws RocksDBException thrown if error happens in underlying
|
||||||
* native library.
|
* native library.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public byte[][] multiGetForUpdate(final ReadOptions readOptions,
|
public byte[][] multiGetForUpdate(final ReadOptions readOptions,
|
||||||
final List<ColumnFamilyHandle> columnFamilyHandles,
|
final List<ColumnFamilyHandle> columnFamilyHandles, final byte[][] keys)
|
||||||
final byte[][] keys) throws RocksDBException {
|
throws RocksDBException {
|
||||||
assert(isOwningHandle());
|
assert(isOwningHandle());
|
||||||
// Check if key size equals cfList size. If not a exception must be
|
// Check if key size equals cfList size. If not a exception must be
|
||||||
// thrown. If not a Segmentation fault happens.
|
// thrown. If not a Segmentation fault happens.
|
||||||
@ -562,6 +652,43 @@ public class Transaction extends RocksObject {
|
|||||||
keys, cfHandles);
|
keys, cfHandles);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A multi-key version of
|
||||||
|
* {@link #getForUpdate(ReadOptions, ColumnFamilyHandle, byte[], boolean)}.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param readOptions Read options.
|
||||||
|
* @param columnFamilyHandles {@link org.rocksdb.ColumnFamilyHandle}
|
||||||
|
* instances
|
||||||
|
* @param keys the keys to retrieve the values for.
|
||||||
|
*
|
||||||
|
* @return Array of values, one for each key
|
||||||
|
*
|
||||||
|
* @throws RocksDBException thrown if error happens in underlying
|
||||||
|
* native library.
|
||||||
|
*/
|
||||||
|
public List<byte[]> multiGetForUpdateAsList(final ReadOptions readOptions,
|
||||||
|
final List<ColumnFamilyHandle> columnFamilyHandles, final List<byte[]> keys)
|
||||||
|
throws RocksDBException {
|
||||||
|
assert (isOwningHandle());
|
||||||
|
// Check if key size equals cfList size. If not a exception must be
|
||||||
|
// thrown. If not a Segmentation fault happens.
|
||||||
|
if (keys.size() != columnFamilyHandles.size()) {
|
||||||
|
throw new IllegalArgumentException("For each key there must be a ColumnFamilyHandle.");
|
||||||
|
}
|
||||||
|
if (keys.size() == 0) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
final byte[][] keysArray = keys.toArray(new byte[keys.size()][]);
|
||||||
|
|
||||||
|
final long[] cfHandles = new long[columnFamilyHandles.size()];
|
||||||
|
for (int i = 0; i < columnFamilyHandles.size(); i++) {
|
||||||
|
cfHandles[i] = columnFamilyHandles.get(i).nativeHandle_;
|
||||||
|
}
|
||||||
|
return Arrays.asList(
|
||||||
|
multiGetForUpdate(nativeHandle_, readOptions.nativeHandle_, keysArray, cfHandles));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A multi-key version of {@link #getForUpdate(ReadOptions, byte[], boolean)}.
|
* A multi-key version of {@link #getForUpdate(ReadOptions, byte[], boolean)}.
|
||||||
*
|
*
|
||||||
@ -574,8 +701,9 @@ public class Transaction extends RocksObject {
|
|||||||
* @throws RocksDBException thrown if error happens in underlying
|
* @throws RocksDBException thrown if error happens in underlying
|
||||||
* native library.
|
* native library.
|
||||||
*/
|
*/
|
||||||
public byte[][] multiGetForUpdate(final ReadOptions readOptions,
|
@Deprecated
|
||||||
final byte[][] keys) throws RocksDBException {
|
public byte[][] multiGetForUpdate(final ReadOptions readOptions, final byte[][] keys)
|
||||||
|
throws RocksDBException {
|
||||||
assert(isOwningHandle());
|
assert(isOwningHandle());
|
||||||
if(keys.length == 0) {
|
if(keys.length == 0) {
|
||||||
return new byte[0][0];
|
return new byte[0][0];
|
||||||
@ -585,6 +713,30 @@ public class Transaction extends RocksObject {
|
|||||||
readOptions.nativeHandle_, keys);
|
readOptions.nativeHandle_, keys);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A multi-key version of {@link #getForUpdate(ReadOptions, byte[], boolean)}.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param readOptions Read options.
|
||||||
|
* @param keys the keys to retrieve the values for.
|
||||||
|
*
|
||||||
|
* @return List of values, one for each key
|
||||||
|
*
|
||||||
|
* @throws RocksDBException thrown if error happens in underlying
|
||||||
|
* native library.
|
||||||
|
*/
|
||||||
|
public List<byte[]> multiGetForUpdateAsList(
|
||||||
|
final ReadOptions readOptions, final List<byte[]> keys) throws RocksDBException {
|
||||||
|
assert (isOwningHandle());
|
||||||
|
if (keys.size() == 0) {
|
||||||
|
return new ArrayList<>(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
final byte[][] keysArray = keys.toArray(new byte[keys.size()][]);
|
||||||
|
|
||||||
|
return Arrays.asList(multiGetForUpdate(nativeHandle_, readOptions.nativeHandle_, keysArray));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an iterator that will iterate on all keys in the default
|
* Returns an iterator that will iterate on all keys in the default
|
||||||
* column family including both keys in the DB and uncommitted keys in this
|
* column family including both keys in the DB and uncommitted keys in this
|
||||||
|
@ -206,12 +206,8 @@ public abstract class AbstractTransactionTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void multiGetPut_cf() throws RocksDBException {
|
public void multiGetPut_cf() throws RocksDBException {
|
||||||
final byte keys[][] = new byte[][] {
|
final byte[][] keys = new byte[][] {"key1".getBytes(UTF_8), "key2".getBytes(UTF_8)};
|
||||||
"key1".getBytes(UTF_8),
|
final byte[][] values = new byte[][] {"value1".getBytes(UTF_8), "value2".getBytes(UTF_8)};
|
||||||
"key2".getBytes(UTF_8)};
|
|
||||||
final byte values[][] = new byte[][] {
|
|
||||||
"value1".getBytes(UTF_8),
|
|
||||||
"value2".getBytes(UTF_8)};
|
|
||||||
|
|
||||||
try(final DBContainer dbContainer = startDb();
|
try(final DBContainer dbContainer = startDb();
|
||||||
final ReadOptions readOptions = new ReadOptions();
|
final ReadOptions readOptions = new ReadOptions();
|
||||||
@ -227,14 +223,31 @@ public abstract class AbstractTransactionTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void multiGetPutAsList_cf() throws RocksDBException {
|
||||||
|
final byte[][] keys = new byte[][] {"key1".getBytes(UTF_8), "key2".getBytes(UTF_8)};
|
||||||
|
final byte[][] values = new byte[][] {"value1".getBytes(UTF_8), "value2".getBytes(UTF_8)};
|
||||||
|
|
||||||
|
try (final DBContainer dbContainer = startDb();
|
||||||
|
final ReadOptions readOptions = new ReadOptions();
|
||||||
|
final Transaction txn = dbContainer.beginTransaction()) {
|
||||||
|
final ColumnFamilyHandle testCf = dbContainer.getTestColumnFamily();
|
||||||
|
final List<ColumnFamilyHandle> cfList = Arrays.asList(testCf, testCf);
|
||||||
|
|
||||||
|
assertThat(txn.multiGetAsList(readOptions, cfList, Arrays.asList(keys)))
|
||||||
|
.containsExactly(null, null);
|
||||||
|
|
||||||
|
txn.put(testCf, keys[0], values[0]);
|
||||||
|
txn.put(testCf, keys[1], values[1]);
|
||||||
|
assertThat(txn.multiGetAsList(readOptions, cfList, Arrays.asList(keys)))
|
||||||
|
.containsExactly(values);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void multiGetPut() throws RocksDBException {
|
public void multiGetPut() throws RocksDBException {
|
||||||
final byte keys[][] = new byte[][] {
|
final byte[][] keys = new byte[][] {"key1".getBytes(UTF_8), "key2".getBytes(UTF_8)};
|
||||||
"key1".getBytes(UTF_8),
|
final byte[][] values = new byte[][] {"value1".getBytes(UTF_8), "value2".getBytes(UTF_8)};
|
||||||
"key2".getBytes(UTF_8)};
|
|
||||||
final byte values[][] = new byte[][] {
|
|
||||||
"value1".getBytes(UTF_8),
|
|
||||||
"value2".getBytes(UTF_8)};
|
|
||||||
|
|
||||||
try(final DBContainer dbContainer = startDb();
|
try(final DBContainer dbContainer = startDb();
|
||||||
final ReadOptions readOptions = new ReadOptions();
|
final ReadOptions readOptions = new ReadOptions();
|
||||||
@ -248,6 +261,22 @@ public abstract class AbstractTransactionTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void multiGetPutAsList() throws RocksDBException {
|
||||||
|
final byte[][] keys = new byte[][] {"key1".getBytes(UTF_8), "key2".getBytes(UTF_8)};
|
||||||
|
final byte[][] values = new byte[][] {"value1".getBytes(UTF_8), "value2".getBytes(UTF_8)};
|
||||||
|
|
||||||
|
try (final DBContainer dbContainer = startDb();
|
||||||
|
final ReadOptions readOptions = new ReadOptions();
|
||||||
|
final Transaction txn = dbContainer.beginTransaction()) {
|
||||||
|
assertThat(txn.multiGetAsList(readOptions, Arrays.asList(keys))).containsExactly(null, null);
|
||||||
|
|
||||||
|
txn.put(keys[0], values[0]);
|
||||||
|
txn.put(keys[1], values[1]);
|
||||||
|
assertThat(txn.multiGetAsList(readOptions, Arrays.asList(keys))).containsExactly(values);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getForUpdate_cf() throws RocksDBException {
|
public void getForUpdate_cf() throws RocksDBException {
|
||||||
final byte k1[] = "key1".getBytes(UTF_8);
|
final byte k1[] = "key1".getBytes(UTF_8);
|
||||||
@ -495,6 +524,7 @@ public abstract class AbstractTransactionTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
@Test
|
@Test
|
||||||
public void multiGetPutUntracked_cf() throws RocksDBException {
|
public void multiGetPutUntracked_cf() throws RocksDBException {
|
||||||
final byte keys[][] = new byte[][] {
|
final byte keys[][] = new byte[][] {
|
||||||
@ -518,14 +548,32 @@ public abstract class AbstractTransactionTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void multiGetPutUntrackedAsList_cf() throws RocksDBException {
|
||||||
|
final byte[][] keys = new byte[][] {"key1".getBytes(UTF_8), "key2".getBytes(UTF_8)};
|
||||||
|
final byte[][] values = new byte[][] {"value1".getBytes(UTF_8), "value2".getBytes(UTF_8)};
|
||||||
|
|
||||||
|
try (final DBContainer dbContainer = startDb();
|
||||||
|
final ReadOptions readOptions = new ReadOptions();
|
||||||
|
final Transaction txn = dbContainer.beginTransaction()) {
|
||||||
|
final ColumnFamilyHandle testCf = dbContainer.getTestColumnFamily();
|
||||||
|
|
||||||
|
final List<ColumnFamilyHandle> cfList = Arrays.asList(testCf, testCf);
|
||||||
|
|
||||||
|
assertThat(txn.multiGetAsList(readOptions, cfList, Arrays.asList(keys)))
|
||||||
|
.containsExactly(null, null);
|
||||||
|
txn.putUntracked(testCf, keys[0], values[0]);
|
||||||
|
txn.putUntracked(testCf, keys[1], values[1]);
|
||||||
|
assertThat(txn.multiGetAsList(readOptions, cfList, Arrays.asList(keys)))
|
||||||
|
.containsExactly(values);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
@Test
|
@Test
|
||||||
public void multiGetPutUntracked() throws RocksDBException {
|
public void multiGetPutUntracked() throws RocksDBException {
|
||||||
final byte keys[][] = new byte[][] {
|
final byte[][] keys = new byte[][] {"key1".getBytes(UTF_8), "key2".getBytes(UTF_8)};
|
||||||
"key1".getBytes(UTF_8),
|
final byte[][] values = new byte[][] {"value1".getBytes(UTF_8), "value2".getBytes(UTF_8)};
|
||||||
"key2".getBytes(UTF_8)};
|
|
||||||
final byte values[][] = new byte[][] {
|
|
||||||
"value1".getBytes(UTF_8),
|
|
||||||
"value2".getBytes(UTF_8)};
|
|
||||||
|
|
||||||
try(final DBContainer dbContainer = startDb();
|
try(final DBContainer dbContainer = startDb();
|
||||||
final ReadOptions readOptions = new ReadOptions();
|
final ReadOptions readOptions = new ReadOptions();
|
||||||
@ -538,6 +586,21 @@ public abstract class AbstractTransactionTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void multiGetPutAsListUntracked() throws RocksDBException {
|
||||||
|
final byte[][] keys = new byte[][] {"key1".getBytes(UTF_8), "key2".getBytes(UTF_8)};
|
||||||
|
final byte[][] values = new byte[][] {"value1".getBytes(UTF_8), "value2".getBytes(UTF_8)};
|
||||||
|
|
||||||
|
try (final DBContainer dbContainer = startDb();
|
||||||
|
final ReadOptions readOptions = new ReadOptions();
|
||||||
|
final Transaction txn = dbContainer.beginTransaction()) {
|
||||||
|
assertThat(txn.multiGetAsList(readOptions, Arrays.asList(keys))).containsExactly(null, null);
|
||||||
|
txn.putUntracked(keys[0], values[0]);
|
||||||
|
txn.putUntracked(keys[1], values[1]);
|
||||||
|
assertThat(txn.multiGetAsList(readOptions, Arrays.asList(keys))).containsExactly(values);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void mergeUntracked_cf() throws RocksDBException {
|
public void mergeUntracked_cf() throws RocksDBException {
|
||||||
final byte[] k1 = "key1".getBytes(UTF_8);
|
final byte[] k1 = "key1".getBytes(UTF_8);
|
||||||
|
@ -19,9 +19,9 @@ public class OptimisticTransactionTest extends AbstractTransactionTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getForUpdate_cf_conflict() throws RocksDBException {
|
public void getForUpdate_cf_conflict() throws RocksDBException {
|
||||||
final byte k1[] = "key1".getBytes(UTF_8);
|
final byte[] k1 = "key1".getBytes(UTF_8);
|
||||||
final byte v1[] = "value1".getBytes(UTF_8);
|
final byte[] v1 = "value1".getBytes(UTF_8);
|
||||||
final byte v12[] = "value12".getBytes(UTF_8);
|
final byte[] v12 = "value12".getBytes(UTF_8);
|
||||||
try(final DBContainer dbContainer = startDb();
|
try(final DBContainer dbContainer = startDb();
|
||||||
final ReadOptions readOptions = new ReadOptions()) {
|
final ReadOptions readOptions = new ReadOptions()) {
|
||||||
final ColumnFamilyHandle testCf = dbContainer.getTestColumnFamily();
|
final ColumnFamilyHandle testCf = dbContainer.getTestColumnFamily();
|
||||||
@ -57,9 +57,9 @@ public class OptimisticTransactionTest extends AbstractTransactionTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getForUpdate_conflict() throws RocksDBException {
|
public void getForUpdate_conflict() throws RocksDBException {
|
||||||
final byte k1[] = "key1".getBytes(UTF_8);
|
final byte[] k1 = "key1".getBytes(UTF_8);
|
||||||
final byte v1[] = "value1".getBytes(UTF_8);
|
final byte[] v1 = "value1".getBytes(UTF_8);
|
||||||
final byte v12[] = "value12".getBytes(UTF_8);
|
final byte[] v12 = "value12".getBytes(UTF_8);
|
||||||
try(final DBContainer dbContainer = startDb();
|
try(final DBContainer dbContainer = startDb();
|
||||||
final ReadOptions readOptions = new ReadOptions()) {
|
final ReadOptions readOptions = new ReadOptions()) {
|
||||||
|
|
||||||
@ -92,14 +92,11 @@ public class OptimisticTransactionTest extends AbstractTransactionTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
@Test
|
@Test
|
||||||
public void multiGetForUpdate_cf_conflict() throws RocksDBException {
|
public void multiGetForUpdate_cf_conflict() throws RocksDBException {
|
||||||
final byte keys[][] = new byte[][] {
|
final byte[][] keys = new byte[][] {"key1".getBytes(UTF_8), "key2".getBytes(UTF_8)};
|
||||||
"key1".getBytes(UTF_8),
|
final byte[][] values = new byte[][] {"value1".getBytes(UTF_8), "value2".getBytes(UTF_8)};
|
||||||
"key2".getBytes(UTF_8)};
|
|
||||||
final byte values[][] = new byte[][] {
|
|
||||||
"value1".getBytes(UTF_8),
|
|
||||||
"value2".getBytes(UTF_8)};
|
|
||||||
final byte[] otherValue = "otherValue".getBytes(UTF_8);
|
final byte[] otherValue = "otherValue".getBytes(UTF_8);
|
||||||
|
|
||||||
try(final DBContainer dbContainer = startDb();
|
try(final DBContainer dbContainer = startDb();
|
||||||
@ -139,14 +136,54 @@ public class OptimisticTransactionTest extends AbstractTransactionTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void multiGetAsListForUpdate_cf_conflict() throws RocksDBException {
|
||||||
|
final byte[][] keys = new byte[][] {"key1".getBytes(UTF_8), "key2".getBytes(UTF_8)};
|
||||||
|
final byte[][] values = new byte[][] {"value1".getBytes(UTF_8), "value2".getBytes(UTF_8)};
|
||||||
|
final byte[] otherValue = "otherValue".getBytes(UTF_8);
|
||||||
|
|
||||||
|
try (final DBContainer dbContainer = startDb();
|
||||||
|
final ReadOptions readOptions = new ReadOptions()) {
|
||||||
|
final ColumnFamilyHandle testCf = dbContainer.getTestColumnFamily();
|
||||||
|
final List<ColumnFamilyHandle> cfList = Arrays.asList(testCf, testCf);
|
||||||
|
|
||||||
|
try (final Transaction txn = dbContainer.beginTransaction()) {
|
||||||
|
txn.put(testCf, keys[0], values[0]);
|
||||||
|
txn.put(testCf, keys[1], values[1]);
|
||||||
|
assertThat(txn.multiGetAsList(readOptions, cfList, Arrays.asList(keys)))
|
||||||
|
.containsExactly(values);
|
||||||
|
txn.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
try (final Transaction txn2 = dbContainer.beginTransaction()) {
|
||||||
|
try (final Transaction txn3 = dbContainer.beginTransaction()) {
|
||||||
|
assertThat(txn3.multiGetForUpdateAsList(readOptions, cfList, Arrays.asList(keys)))
|
||||||
|
.containsExactly(values);
|
||||||
|
|
||||||
|
// NOTE: txn2 updates k1, during txn3
|
||||||
|
txn2.put(testCf, keys[0], otherValue);
|
||||||
|
assertThat(txn2.get(testCf, readOptions, keys[0])).isEqualTo(otherValue);
|
||||||
|
txn2.commit();
|
||||||
|
|
||||||
|
try {
|
||||||
|
txn3.commit(); // should cause an exception!
|
||||||
|
} catch (final RocksDBException e) {
|
||||||
|
assertThat(e.getStatus().getCode()).isSameAs(Status.Code.Busy);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fail("Expected an exception for put after getForUpdate from conflicting"
|
||||||
|
+ "transactions");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
@Test
|
@Test
|
||||||
public void multiGetForUpdate_conflict() throws RocksDBException {
|
public void multiGetForUpdate_conflict() throws RocksDBException {
|
||||||
final byte keys[][] = new byte[][] {
|
final byte[][] keys = new byte[][] {"key1".getBytes(UTF_8), "key2".getBytes(UTF_8)};
|
||||||
"key1".getBytes(UTF_8),
|
final byte[][] values = new byte[][] {"value1".getBytes(UTF_8), "value2".getBytes(UTF_8)};
|
||||||
"key2".getBytes(UTF_8)};
|
|
||||||
final byte values[][] = new byte[][] {
|
|
||||||
"value1".getBytes(UTF_8),
|
|
||||||
"value2".getBytes(UTF_8)};
|
|
||||||
final byte[] otherValue = "otherValue".getBytes(UTF_8);
|
final byte[] otherValue = "otherValue".getBytes(UTF_8);
|
||||||
|
|
||||||
try(final DBContainer dbContainer = startDb();
|
try(final DBContainer dbContainer = startDb();
|
||||||
@ -183,11 +220,50 @@ public class OptimisticTransactionTest extends AbstractTransactionTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void multiGetasListForUpdate_conflict() throws RocksDBException {
|
||||||
|
final byte[][] keys = new byte[][] {"key1".getBytes(UTF_8), "key2".getBytes(UTF_8)};
|
||||||
|
final byte[][] values = new byte[][] {"value1".getBytes(UTF_8), "value2".getBytes(UTF_8)};
|
||||||
|
final byte[] otherValue = "otherValue".getBytes(UTF_8);
|
||||||
|
|
||||||
|
try (final DBContainer dbContainer = startDb();
|
||||||
|
final ReadOptions readOptions = new ReadOptions()) {
|
||||||
|
try (final Transaction txn = dbContainer.beginTransaction()) {
|
||||||
|
txn.put(keys[0], values[0]);
|
||||||
|
txn.put(keys[1], values[1]);
|
||||||
|
assertThat(txn.multiGetAsList(readOptions, Arrays.asList(keys))).containsExactly(values);
|
||||||
|
txn.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
try (final Transaction txn2 = dbContainer.beginTransaction()) {
|
||||||
|
try (final Transaction txn3 = dbContainer.beginTransaction()) {
|
||||||
|
assertThat(txn3.multiGetForUpdateAsList(readOptions, Arrays.asList(keys)))
|
||||||
|
.containsExactly(values);
|
||||||
|
|
||||||
|
// NOTE: txn2 updates k1, during txn3
|
||||||
|
txn2.put(keys[0], otherValue);
|
||||||
|
assertThat(txn2.get(readOptions, keys[0])).isEqualTo(otherValue);
|
||||||
|
txn2.commit();
|
||||||
|
|
||||||
|
try {
|
||||||
|
txn3.commit(); // should cause an exception!
|
||||||
|
} catch (final RocksDBException e) {
|
||||||
|
assertThat(e.getStatus().getCode()).isSameAs(Status.Code.Busy);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fail("Expected an exception for put after getForUpdate from conflicting"
|
||||||
|
+ "transactions");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void undoGetForUpdate_cf_conflict() throws RocksDBException {
|
public void undoGetForUpdate_cf_conflict() throws RocksDBException {
|
||||||
final byte k1[] = "key1".getBytes(UTF_8);
|
final byte[] k1 = "key1".getBytes(UTF_8);
|
||||||
final byte v1[] = "value1".getBytes(UTF_8);
|
final byte[] v1 = "value1".getBytes(UTF_8);
|
||||||
final byte v12[] = "value12".getBytes(UTF_8);
|
final byte[] v12 = "value12".getBytes(UTF_8);
|
||||||
try(final DBContainer dbContainer = startDb();
|
try(final DBContainer dbContainer = startDb();
|
||||||
final ReadOptions readOptions = new ReadOptions()) {
|
final ReadOptions readOptions = new ReadOptions()) {
|
||||||
final ColumnFamilyHandle testCf = dbContainer.getTestColumnFamily();
|
final ColumnFamilyHandle testCf = dbContainer.getTestColumnFamily();
|
||||||
@ -220,9 +296,9 @@ public class OptimisticTransactionTest extends AbstractTransactionTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void undoGetForUpdate_conflict() throws RocksDBException {
|
public void undoGetForUpdate_conflict() throws RocksDBException {
|
||||||
final byte k1[] = "key1".getBytes(UTF_8);
|
final byte[] k1 = "key1".getBytes(UTF_8);
|
||||||
final byte v1[] = "value1".getBytes(UTF_8);
|
final byte[] v1 = "value1".getBytes(UTF_8);
|
||||||
final byte v12[] = "value12".getBytes(UTF_8);
|
final byte[] v12 = "value12".getBytes(UTF_8);
|
||||||
try(final DBContainer dbContainer = startDb();
|
try(final DBContainer dbContainer = startDb();
|
||||||
final ReadOptions readOptions = new ReadOptions()) {
|
final ReadOptions readOptions = new ReadOptions()) {
|
||||||
|
|
||||||
@ -261,12 +337,10 @@ public class OptimisticTransactionTest extends AbstractTransactionTest {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
txn.setName(name);
|
txn.setName(name);
|
||||||
|
fail("Optimistic transactions cannot be named.");
|
||||||
} catch(final RocksDBException e) {
|
} catch(final RocksDBException e) {
|
||||||
assertThat(e.getStatus().getCode() == Status.Code.InvalidArgument);
|
assertThat(e.getStatus().getCode()).isEqualTo(Status.Code.InvalidArgument);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fail("Optimistic transactions cannot be named.");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,9 +19,9 @@ public class TransactionTest extends AbstractTransactionTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getForUpdate_cf_conflict() throws RocksDBException {
|
public void getForUpdate_cf_conflict() throws RocksDBException {
|
||||||
final byte k1[] = "key1".getBytes(UTF_8);
|
final byte[] k1 = "key1".getBytes(UTF_8);
|
||||||
final byte v1[] = "value1".getBytes(UTF_8);
|
final byte[] v1 = "value1".getBytes(UTF_8);
|
||||||
final byte v12[] = "value12".getBytes(UTF_8);
|
final byte[] v12 = "value12".getBytes(UTF_8);
|
||||||
try(final DBContainer dbContainer = startDb();
|
try(final DBContainer dbContainer = startDb();
|
||||||
final ReadOptions readOptions = new ReadOptions()) {
|
final ReadOptions readOptions = new ReadOptions()) {
|
||||||
final ColumnFamilyHandle testCf = dbContainer.getTestColumnFamily();
|
final ColumnFamilyHandle testCf = dbContainer.getTestColumnFamily();
|
||||||
@ -53,9 +53,9 @@ public class TransactionTest extends AbstractTransactionTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getForUpdate_conflict() throws RocksDBException {
|
public void getForUpdate_conflict() throws RocksDBException {
|
||||||
final byte k1[] = "key1".getBytes(UTF_8);
|
final byte[] k1 = "key1".getBytes(UTF_8);
|
||||||
final byte v1[] = "value1".getBytes(UTF_8);
|
final byte[] v1 = "value1".getBytes(UTF_8);
|
||||||
final byte v12[] = "value12".getBytes(UTF_8);
|
final byte[] v12 = "value12".getBytes(UTF_8);
|
||||||
try(final DBContainer dbContainer = startDb();
|
try(final DBContainer dbContainer = startDb();
|
||||||
final ReadOptions readOptions = new ReadOptions()) {
|
final ReadOptions readOptions = new ReadOptions()) {
|
||||||
|
|
||||||
@ -86,12 +86,8 @@ public class TransactionTest extends AbstractTransactionTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void multiGetForUpdate_cf_conflict() throws RocksDBException {
|
public void multiGetForUpdate_cf_conflict() throws RocksDBException {
|
||||||
final byte keys[][] = new byte[][] {
|
final byte[][] keys = new byte[][] {"key1".getBytes(UTF_8), "key2".getBytes(UTF_8)};
|
||||||
"key1".getBytes(UTF_8),
|
final byte[][] values = new byte[][] {"value1".getBytes(UTF_8), "value2".getBytes(UTF_8)};
|
||||||
"key2".getBytes(UTF_8)};
|
|
||||||
final byte values[][] = new byte[][] {
|
|
||||||
"value1".getBytes(UTF_8),
|
|
||||||
"value2".getBytes(UTF_8)};
|
|
||||||
final byte[] otherValue = "otherValue".getBytes(UTF_8);
|
final byte[] otherValue = "otherValue".getBytes(UTF_8);
|
||||||
|
|
||||||
try(final DBContainer dbContainer = startDb();
|
try(final DBContainer dbContainer = startDb();
|
||||||
@ -126,14 +122,49 @@ public class TransactionTest extends AbstractTransactionTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void multiGetAsListForUpdate_cf_conflict() throws RocksDBException {
|
||||||
|
final byte[][] keys = new byte[][] {"key1".getBytes(UTF_8), "key2".getBytes(UTF_8)};
|
||||||
|
final byte[][] values = new byte[][] {"value1".getBytes(UTF_8), "value2".getBytes(UTF_8)};
|
||||||
|
final byte[] otherValue = "otherValue".getBytes(UTF_8);
|
||||||
|
|
||||||
|
try (final DBContainer dbContainer = startDb();
|
||||||
|
final ReadOptions readOptions = new ReadOptions()) {
|
||||||
|
final ColumnFamilyHandle testCf = dbContainer.getTestColumnFamily();
|
||||||
|
final List<ColumnFamilyHandle> cfList = Arrays.asList(testCf, testCf);
|
||||||
|
|
||||||
|
try (final Transaction txn = dbContainer.beginTransaction()) {
|
||||||
|
txn.put(testCf, keys[0], values[0]);
|
||||||
|
txn.put(testCf, keys[1], values[1]);
|
||||||
|
assertThat(txn.multiGetAsList(readOptions, cfList, Arrays.asList(keys)))
|
||||||
|
.containsExactly(values);
|
||||||
|
txn.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
try (final Transaction txn2 = dbContainer.beginTransaction()) {
|
||||||
|
try (final Transaction txn3 = dbContainer.beginTransaction()) {
|
||||||
|
assertThat(txn3.multiGetForUpdateAsList(readOptions, cfList, Arrays.asList(keys)))
|
||||||
|
.containsExactly(values);
|
||||||
|
|
||||||
|
// NOTE: txn2 updates k1, during txn3
|
||||||
|
try {
|
||||||
|
txn2.put(testCf, keys[0], otherValue); // should cause an exception!
|
||||||
|
} catch (final RocksDBException e) {
|
||||||
|
assertThat(e.getStatus().getCode()).isSameAs(Status.Code.TimedOut);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fail("Expected an exception for put after getForUpdate from conflicting"
|
||||||
|
+ "transactions");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void multiGetForUpdate_conflict() throws RocksDBException {
|
public void multiGetForUpdate_conflict() throws RocksDBException {
|
||||||
final byte keys[][] = new byte[][] {
|
final byte[][] keys = new byte[][] {"key1".getBytes(UTF_8), "key2".getBytes(UTF_8)};
|
||||||
"key1".getBytes(UTF_8),
|
final byte[][] values = new byte[][] {"value1".getBytes(UTF_8), "value2".getBytes(UTF_8)};
|
||||||
"key2".getBytes(UTF_8)};
|
|
||||||
final byte values[][] = new byte[][] {
|
|
||||||
"value1".getBytes(UTF_8),
|
|
||||||
"value2".getBytes(UTF_8)};
|
|
||||||
final byte[] otherValue = "otherValue".getBytes(UTF_8);
|
final byte[] otherValue = "otherValue".getBytes(UTF_8);
|
||||||
|
|
||||||
try(final DBContainer dbContainer = startDb();
|
try(final DBContainer dbContainer = startDb();
|
||||||
@ -150,6 +181,41 @@ public class TransactionTest extends AbstractTransactionTest {
|
|||||||
assertThat(txn3.multiGetForUpdate(readOptions, keys))
|
assertThat(txn3.multiGetForUpdate(readOptions, keys))
|
||||||
.isEqualTo(values);
|
.isEqualTo(values);
|
||||||
|
|
||||||
|
// NOTE: txn2 updates k1, during txn3
|
||||||
|
try {
|
||||||
|
txn2.put(keys[0], otherValue); // should cause an exception!
|
||||||
|
} catch (final RocksDBException e) {
|
||||||
|
assertThat(e.getStatus().getCode()).isSameAs(Status.Code.TimedOut);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fail("Expected an exception for put after getForUpdate from conflicting"
|
||||||
|
+ "transactions");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void multiGetAsListForUpdate_conflict() throws RocksDBException {
|
||||||
|
final byte[][] keys = new byte[][] {"key1".getBytes(UTF_8), "key2".getBytes(UTF_8)};
|
||||||
|
final byte[][] values = new byte[][] {"value1".getBytes(UTF_8), "value2".getBytes(UTF_8)};
|
||||||
|
final byte[] otherValue = "otherValue".getBytes(UTF_8);
|
||||||
|
|
||||||
|
try (final DBContainer dbContainer = startDb();
|
||||||
|
final ReadOptions readOptions = new ReadOptions()) {
|
||||||
|
try (final Transaction txn = dbContainer.beginTransaction()) {
|
||||||
|
txn.put(keys[0], values[0]);
|
||||||
|
txn.put(keys[1], values[1]);
|
||||||
|
assertThat(txn.multiGetAsList(readOptions, Arrays.asList(keys))).containsExactly(values);
|
||||||
|
txn.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
try (final Transaction txn2 = dbContainer.beginTransaction()) {
|
||||||
|
try (final Transaction txn3 = dbContainer.beginTransaction()) {
|
||||||
|
assertThat(txn3.multiGetForUpdateAsList(readOptions, Arrays.asList(keys)))
|
||||||
|
.containsExactly(values);
|
||||||
|
|
||||||
// NOTE: txn2 updates k1, during txn3
|
// NOTE: txn2 updates k1, during txn3
|
||||||
try {
|
try {
|
||||||
txn2.put(keys[0], otherValue); // should cause an exception!
|
txn2.put(keys[0], otherValue); // should cause an exception!
|
||||||
|
Loading…
Reference in New Issue
Block a user