Search in sources :

Example 1 with Version

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);
}
Also used : lombok.val(lombok.val) BadKeyVersionException(io.pravega.client.tables.BadKeyVersionException) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Version(io.pravega.client.tables.Version) TableKey(io.pravega.client.tables.TableKey) Remove(io.pravega.client.tables.Remove) Insert(io.pravega.client.tables.Insert) Cleanup(lombok.Cleanup) Put(io.pravega.client.tables.Put) Test(org.junit.Test)

Example 2 with Version

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);
}
Also used : lombok.val(lombok.val) Insert(io.pravega.client.tables.Insert) IntStream(java.util.stream.IntStream) Put(io.pravega.client.tables.Put) Getter(lombok.Getter) AssertExtensions(io.pravega.test.common.AssertExtensions) Cleanup(lombok.Cleanup) HashMap(java.util.HashMap) Random(java.util.Random) KeyValueTableConfiguration(io.pravega.client.tables.KeyValueTableConfiguration) BitConverter(io.pravega.common.util.BitConverter) Function(java.util.function.Function) ByteBuffer(java.nio.ByteBuffer) ArrayList(java.util.ArrayList) AccessLevel(lombok.AccessLevel) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) KeyValueTableInfo(io.pravega.client.admin.KeyValueTableInfo) Duration(java.time.Duration) Map(java.util.Map) BiConsumer(java.util.function.BiConsumer) Timeout(org.junit.rules.Timeout) Nullable(javax.annotation.Nullable) Before(org.junit.Before) Serializer(io.pravega.client.stream.Serializer) LeakDetectorTestSuite(io.pravega.test.common.LeakDetectorTestSuite) TableEntry(io.pravega.client.tables.TableEntry) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) lombok.val(lombok.val) Test(org.junit.Test) Collectors(java.util.stream.Collectors) Version(io.pravega.client.tables.Version) TimeUnit(java.util.concurrent.TimeUnit) TableModification(io.pravega.client.tables.TableModification) List(java.util.List) Rule(org.junit.Rule) KeyValueTable(io.pravega.client.tables.KeyValueTable) TableKey(io.pravega.client.tables.TableKey) Assert(org.junit.Assert) BadKeyVersionException(io.pravega.client.tables.BadKeyVersionException) Remove(io.pravega.client.tables.Remove) BadKeyVersionException(io.pravega.client.tables.BadKeyVersionException) TableModification(io.pravega.client.tables.TableModification) TableKey(io.pravega.client.tables.TableKey) Remove(io.pravega.client.tables.Remove) Insert(io.pravega.client.tables.Insert) Cleanup(lombok.Cleanup) Put(io.pravega.client.tables.Put) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Test(org.junit.Test)

Example 3 with Version

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);
}
Also used : lombok.val(lombok.val) BadKeyVersionException(io.pravega.client.tables.BadKeyVersionException) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Version(io.pravega.client.tables.Version) TableKey(io.pravega.client.tables.TableKey) Insert(io.pravega.client.tables.Insert) Cleanup(lombok.Cleanup) Test(org.junit.Test)

Example 4 with Version

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));
    }
}
Also used : lombok.val(lombok.val) TableEntry(io.pravega.client.tables.TableEntry) Insert(io.pravega.client.tables.Insert) IntStream(java.util.stream.IntStream) Put(io.pravega.client.tables.Put) Getter(lombok.Getter) AssertExtensions(io.pravega.test.common.AssertExtensions) Cleanup(lombok.Cleanup) HashMap(java.util.HashMap) Random(java.util.Random) KeyValueTableConfiguration(io.pravega.client.tables.KeyValueTableConfiguration) BitConverter(io.pravega.common.util.BitConverter) Function(java.util.function.Function) ByteBuffer(java.nio.ByteBuffer) ArrayList(java.util.ArrayList) AccessLevel(lombok.AccessLevel) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) KeyValueTableInfo(io.pravega.client.admin.KeyValueTableInfo) Duration(java.time.Duration) Map(java.util.Map) BiConsumer(java.util.function.BiConsumer) Timeout(org.junit.rules.Timeout) Nullable(javax.annotation.Nullable) Before(org.junit.Before) Serializer(io.pravega.client.stream.Serializer) LeakDetectorTestSuite(io.pravega.test.common.LeakDetectorTestSuite) TableEntry(io.pravega.client.tables.TableEntry) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) lombok.val(lombok.val) Test(org.junit.Test) Collectors(java.util.stream.Collectors) Version(io.pravega.client.tables.Version) TimeUnit(java.util.concurrent.TimeUnit) TableModification(io.pravega.client.tables.TableModification) List(java.util.List) Rule(org.junit.Rule) KeyValueTable(io.pravega.client.tables.KeyValueTable) TableKey(io.pravega.client.tables.TableKey) Assert(org.junit.Assert) BadKeyVersionException(io.pravega.client.tables.BadKeyVersionException) Remove(io.pravega.client.tables.Remove) ArrayList(java.util.ArrayList) TableKey(io.pravega.client.tables.TableKey)

Example 5 with Version

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);
}
Also used : lombok.val(lombok.val) Insert(io.pravega.client.tables.Insert) IntStream(java.util.stream.IntStream) Put(io.pravega.client.tables.Put) Getter(lombok.Getter) AssertExtensions(io.pravega.test.common.AssertExtensions) Cleanup(lombok.Cleanup) HashMap(java.util.HashMap) Random(java.util.Random) KeyValueTableConfiguration(io.pravega.client.tables.KeyValueTableConfiguration) BitConverter(io.pravega.common.util.BitConverter) Function(java.util.function.Function) ByteBuffer(java.nio.ByteBuffer) ArrayList(java.util.ArrayList) AccessLevel(lombok.AccessLevel) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) KeyValueTableInfo(io.pravega.client.admin.KeyValueTableInfo) Duration(java.time.Duration) Map(java.util.Map) BiConsumer(java.util.function.BiConsumer) Timeout(org.junit.rules.Timeout) Nullable(javax.annotation.Nullable) Before(org.junit.Before) Serializer(io.pravega.client.stream.Serializer) LeakDetectorTestSuite(io.pravega.test.common.LeakDetectorTestSuite) TableEntry(io.pravega.client.tables.TableEntry) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) lombok.val(lombok.val) Test(org.junit.Test) Collectors(java.util.stream.Collectors) Version(io.pravega.client.tables.Version) TimeUnit(java.util.concurrent.TimeUnit) TableModification(io.pravega.client.tables.TableModification) List(java.util.List) Rule(org.junit.Rule) KeyValueTable(io.pravega.client.tables.KeyValueTable) TableKey(io.pravega.client.tables.TableKey) Assert(org.junit.Assert) BadKeyVersionException(io.pravega.client.tables.BadKeyVersionException) Remove(io.pravega.client.tables.Remove) BadKeyVersionException(io.pravega.client.tables.BadKeyVersionException) HashMap(java.util.HashMap) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) TableKey(io.pravega.client.tables.TableKey) Remove(io.pravega.client.tables.Remove) Insert(io.pravega.client.tables.Insert) Cleanup(lombok.Cleanup) ByteBuffer(java.nio.ByteBuffer) KeyValueTableInfo(io.pravega.client.admin.KeyValueTableInfo) Put(io.pravega.client.tables.Put) Random(java.util.Random) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Version(io.pravega.client.tables.Version) Test(org.junit.Test)

Aggregations

Version (io.pravega.client.tables.Version)8 TableKey (io.pravega.client.tables.TableKey)7 Test (org.junit.Test)7 BadKeyVersionException (io.pravega.client.tables.BadKeyVersionException)6 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)6 Cleanup (lombok.Cleanup)6 lombok.val (lombok.val)6 Insert (io.pravega.client.tables.Insert)5 Put (io.pravega.client.tables.Put)5 Remove (io.pravega.client.tables.Remove)4 TableEntry (io.pravega.client.tables.TableEntry)4 ByteBuffer (java.nio.ByteBuffer)4 KeyValueTableInfo (io.pravega.client.admin.KeyValueTableInfo)3 Serializer (io.pravega.client.stream.Serializer)3 KeyValueTable (io.pravega.client.tables.KeyValueTable)3 KeyValueTableConfiguration (io.pravega.client.tables.KeyValueTableConfiguration)3 TableModification (io.pravega.client.tables.TableModification)3 BitConverter (io.pravega.common.util.BitConverter)3 AssertExtensions (io.pravega.test.common.AssertExtensions)3 LeakDetectorTestSuite (io.pravega.test.common.LeakDetectorTestSuite)3