use of io.pravega.client.tables.Version in project pravega by pravega.
the class KeyValueTableTestBase method testSingleKeyUnconditionalRemovals.
/**
* Tests the ability to perform single-key updates and removals (conditional and unconditional). These methods are exercised:
* - {@link KeyValueTable#update} with {@link Put} instances and with {@link Remove} instances.
* - {@link KeyValueTable#get} and {@link KeyValueTable#getAll}
*/
@Test
public void testSingleKeyUnconditionalRemovals() {
val versions = new Versions();
@Cleanup val kvt = createKeyValueTable();
// Put (unconditional update).
val iteration = new AtomicInteger(0);
forEveryKey((pk, sk) -> {
val value = getValue(pk, sk, iteration.get());
Version kv = kvt.update(new Put(new TableKey(pk, sk), value)).join();
versions.add(getUniqueKeyId(pk, sk), kv);
});
// Remove (both conditional and unconditional)
iteration.incrementAndGet();
forEveryKey((pk, sk) -> {
val keyId = getUniqueKeyId(pk, sk);
val existingVersion = versions.get(keyId);
// Verify that conditions are checked both for segment names and their versions.
val pkValue = Math.abs(PK_SERIALIZER.deserialize(pk));
boolean conditional = pkValue % 2 == 0;
if (conditional) {
// First check that a bad version will be checked.
Version badVersion = alterVersion(existingVersion, pkValue % 4 == 0, pkValue % 4 != 0);
AssertExtensions.assertSuppliedFutureThrows("update(Remove) did not throw for bad version.", () -> kvt.update(new Remove(new TableKey(pk, sk), badVersion)), ex -> ex instanceof BadKeyVersionException);
// Remove it.
kvt.update(new Remove(new TableKey(pk, sk), existingVersion)).join();
} else {
kvt.update(new Remove(new TableKey(pk, sk))).join();
}
versions.remove(keyId);
});
Assert.assertTrue("Expected all keys to have been removed.", versions.isEmpty());
checkValues(iteration.get(), versions, kvt);
// Re-insert (conditionally).
iteration.incrementAndGet();
forEveryKey((pk, sk) -> {
val value = getValue(pk, sk, iteration.get());
// First one should work.
Version kv = kvt.update(new Insert(new TableKey(pk, sk), value)).join();
versions.add(getUniqueKeyId(pk, sk), kv);
});
checkValues(iteration.get(), versions, kvt);
}
use of io.pravega.client.tables.Version in project pravega by pravega.
the class KeyValueTableTestBase method testMultiKeyOperations.
/**
* Tests the ability to perform multi-key updates, replacements and removals. These methods should be exercised:
* - {@link KeyValueTable#update(Iterable)} with {@link Insert} and {@link Put} instances.
* - {@link KeyValueTable#update(Iterable)} with {@link Remove}.
* - {@link KeyValueTable#getAll}
*/
@Test
public void testMultiKeyOperations() {
val versions = new Versions();
@Cleanup val kvt = createKeyValueTable();
// Conditional Insert.
val iteration = new AtomicInteger(0);
forEveryPrimaryKey((pk, secondaryKeys) -> {
List<TableModification> inserts = secondaryKeys.stream().map(sk -> new Insert(new TableKey(pk, sk), getValue(pk, sk, iteration.get()))).collect(Collectors.toList());
val keyVersions = kvt.update(inserts).join();
val hint = getUniqueKeyId(pk);
Assert.assertEquals("Unexpected result size" + hint, inserts.size(), keyVersions.size());
for (int i = 0; i < inserts.size(); i++) {
versions.add(getUniqueKeyId(pk, inserts.get(i).getKey().getSecondaryKey()), keyVersions.get(i));
}
});
checkValues(iteration.get(), versions, kvt);
// Unconditional update.
iteration.incrementAndGet();
forEveryPrimaryKey((pk, secondaryKeys) -> {
List<TableModification> puts = secondaryKeys.stream().map(sk -> new Put(new TableKey(pk, sk), getValue(pk, sk, iteration.get()))).collect(Collectors.toList());
val keyVersions = kvt.update(puts).join();
val hint = getUniqueKeyId(pk);
Assert.assertEquals("Unexpected result size" + hint, puts.size(), keyVersions.size());
for (int i = 0; i < puts.size(); i++) {
versions.add(getUniqueKeyId(pk, puts.get(i).getKey().getSecondaryKey()), keyVersions.get(i));
}
});
checkValues(iteration.get(), versions, kvt);
// Conditional replace.
iteration.incrementAndGet();
forEveryPrimaryKey((pk, secondaryKeys) -> {
// Failed update (bad version).
val pkValue = Math.abs(PK_SERIALIZER.deserialize(pk));
List<TableModification> badPuts = secondaryKeys.stream().map(sk -> new Put(new TableKey(pk, sk), getValue(pk, sk, iteration.get()), alterVersion(versions.get(getUniqueKeyId(pk, sk)), pkValue % 2 == 0, pkValue % 2 == 1))).collect(Collectors.toList());
AssertExtensions.assertSuppliedFutureThrows("update(Put) did not throw for bad version.", () -> kvt.update(badPuts), ex -> ex instanceof BadKeyVersionException);
// Correct update.
List<TableModification> puts = secondaryKeys.stream().map(sk -> new Put(new TableKey(pk, sk), getValue(pk, sk, iteration.get()), versions.get(getUniqueKeyId(pk, sk)))).collect(Collectors.toList());
val keyVersions = kvt.update(puts).join();
val hint = getUniqueKeyId(pk);
Assert.assertEquals("Unexpected result size" + hint, puts.size(), keyVersions.size());
for (int i = 0; i < puts.size(); i++) {
versions.add(getUniqueKeyId(pk, puts.get(i).getKey().getSecondaryKey()), keyVersions.get(i));
}
});
checkValues(iteration.get(), versions, kvt);
// Conditional removal.
iteration.incrementAndGet();
forEveryPrimaryKey((pk, secondaryKeys) -> {
val hint = getUniqueKeyId(pk);
// Failed update (bad version).
val pkValue = Math.abs(PK_SERIALIZER.deserialize(pk));
List<TableModification> badRemovals = secondaryKeys.stream().map(sk -> new Remove(new TableKey(pk, sk), alterVersion(versions.get(getUniqueKeyId(pk, sk)), pkValue % 2 == 0, pkValue % 2 == 1))).collect(Collectors.toList());
AssertExtensions.assertSuppliedFutureThrows("update(Remove) did not throw for bad version." + hint, () -> kvt.update(badRemovals), ex -> ex instanceof BadKeyVersionException);
// Correct update.
List<TableModification> removals = secondaryKeys.stream().map(sk -> new Remove(new TableKey(pk, sk), versions.get(getUniqueKeyId(pk, sk)))).collect(Collectors.toList());
kvt.update(removals).join();
for (val sk : secondaryKeys) {
versions.remove(getUniqueKeyId(pk, sk));
}
});
Assert.assertTrue("Expected all keys to have been removed.", versions.isEmpty());
checkValues(iteration.get(), versions, kvt);
// Reinsert (conditionally)
iteration.incrementAndGet();
forEveryPrimaryKey((pk, secondaryKeys) -> {
val hint = getUniqueKeyId(pk);
List<TableModification> entries = secondaryKeys.stream().map(sk -> new Insert(new TableKey(pk, sk), getValue(pk, sk, iteration.get()))).collect(Collectors.toList());
val keyVersions = kvt.update(entries).join();
Assert.assertEquals("Unexpected result size" + hint, entries.size(), keyVersions.size());
for (int i = 0; i < entries.size(); i++) {
versions.add(getUniqueKeyId(pk, entries.get(i).getKey().getSecondaryKey()), keyVersions.get(i));
}
});
checkValues(iteration.get(), versions, kvt);
}
use of io.pravega.client.tables.Version in project pravega by pravega.
the class KeyValueTableTestBase method testSingleKeyConditionalInserts.
/**
* Tests the ability to perform single-key conditional insertions. These methods are exercised:
* - {@link KeyValueTable#update} with {@link Insert} instances.
* - {@link KeyValueTable#get} and {@link KeyValueTable#getAll}.
*/
@Test
public void testSingleKeyConditionalInserts() {
val versions = new Versions();
@Cleanup val kvt = createKeyValueTable();
// Put (conditional insert)
val iteration = new AtomicInteger(0);
forEveryKey((pk, sk) -> {
val value = getValue(pk, sk, iteration.get());
// First one should work.
val insert = new Insert(new TableKey(pk, sk), value);
Version kv = kvt.update(insert).join();
versions.add(getUniqueKeyId(pk, sk), kv);
// Second one should throw.
AssertExtensions.assertSuppliedFutureThrows("insert() did not throw for already existing key.", () -> kvt.update(insert), ex -> ex instanceof BadKeyVersionException);
});
checkValues(iteration.get(), versions, kvt);
}
use of io.pravega.client.tables.Version in project pravega by pravega.
the class KeyValueTableTestBase method checkValues.
private void checkValues(int iteration, Map<ByteBuffer, Version> keyVersions, KeyValueTable kvt) {
// Using single get.
for (val k : keyVersions.entrySet()) {
val expectedValue = k.getValue() == null ? null : new TableEntry(new TableKey(k.getKey()), k.getValue(), getValue(k.getKey(), iteration));
val actualEntry = kvt.get(new TableKey(k.getKey())).join();
Assert.assertTrue(areEqual(expectedValue, actualEntry));
boolean exists = kvt.exists(new TableKey(k.getKey())).join();
Assert.assertEquals(expectedValue != null, exists);
}
// Using multi-get.
val requestKeys = new ArrayList<>(keyVersions.entrySet());
val entries = kvt.getAll(requestKeys.stream().map(k -> new TableKey(k.getKey())).collect(Collectors.toList())).join();
Assert.assertEquals(keyVersions.size(), entries.size());
for (int i = 0; i < requestKeys.size(); i++) {
val k = requestKeys.get(i);
val expectedValue = k.getValue() == null ? null : new TableEntry(new TableKey(k.getKey()), k.getValue(), getValue(k.getKey(), iteration));
val actualEntry = entries.get(i);
Assert.assertTrue(areEqual(expectedValue, actualEntry));
}
}
use of io.pravega.client.tables.Version in project pravega by pravega.
the class KeyValueTableTestBase method testNoSecondaryKeys.
/**
* Tests functionality without secondary keys. Only single-key operations are tested because we cannot do multi-key
* operations using different primary keys.
* @throws Exception If an error occurred.
*/
@Test
public void testNoSecondaryKeys() throws Exception {
val entryCount = getPrimaryKeyCount();
val config = KeyValueTableConfiguration.builder().partitionCount(DEFAULT_SEGMENT_COUNT).primaryKeyLength(16).secondaryKeyLength(// No Secondary Keys.
0).build();
val rnd = new Random(0);
@Cleanup val kvt = createKeyValueTable(new KeyValueTableInfo("Scope", "KVTNoSecondaryKeys"), config);
List<ByteBuffer> keys = IntStream.range(0, entryCount).mapToObj(i -> {
val keyData = new byte[config.getPrimaryKeyLength()];
rnd.nextBytes(keyData);
return ByteBuffer.wrap(keyData).asReadOnlyBuffer();
}).collect(Collectors.toList());
// Insertions.
val iteration = new AtomicInteger(0);
val versions = new HashMap<ByteBuffer, Version>();
for (ByteBuffer k : keys) {
Version v = kvt.update(new Insert(new TableKey(k), getValue(k, iteration.get()))).get(TIMEOUT.toMillis(), TimeUnit.MILLISECONDS);
versions.put(k, v);
AssertExtensions.assertSuppliedFutureThrows("Conditional insert did not fail for existing key.", () -> kvt.update(new Insert(new TableKey(k), getValue(k, iteration.get()))), ex -> ex instanceof BadKeyVersionException);
}
checkValues(iteration.get(), versions, kvt);
// Updates.
iteration.incrementAndGet();
for (ByteBuffer k : keys) {
Version v = versions.get(k);
long pkValue = Math.abs(PK_SERIALIZER.deserialize(k));
Put p = pkValue % 2 == 0 ? new Put(new TableKey(k), getValue(k, iteration.get()), v) : new Put(new TableKey(k), getValue(k, iteration.get()));
v = kvt.update(p).get(TIMEOUT.toMillis(), TimeUnit.MILLISECONDS);
versions.put(k, v);
}
checkValues(iteration.get(), versions, kvt);
// Removals.
iteration.incrementAndGet();
for (ByteBuffer k : keys) {
Version v = versions.get(k);
long pkValue = Math.abs(PK_SERIALIZER.deserialize(k));
Remove r = pkValue % 2 == 0 ? new Remove(new TableKey(k), v) : new Remove(new TableKey(k));
kvt.update(r).get(TIMEOUT.toMillis(), TimeUnit.MILLISECONDS);
versions.put(k, null);
}
checkValues(iteration.get(), versions, kvt);
}
Aggregations