Search in sources :

Example 1 with Insert

use of io.pravega.client.tables.Insert 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)

Example 2 with Insert

use of io.pravega.client.tables.Insert 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 3 with Insert

use of io.pravega.client.tables.Insert in project pravega by pravega.

the class KeyValueTableTestBase method testIllegalEntrySizes.

/**
 * Verifies that {@link TableEntry} or {@link TableKey} instances that have invalid key/value lengths are rejected.
 */
@Test
public void testIllegalEntrySizes() {
    val rnd = new Random(0);
    val limitPK = ByteBuffer.wrap(new byte[getPrimaryKeyLength()]);
    val shortPK = ByteBuffer.allocate(getPrimaryKeyLength() - 1);
    val longPK = ByteBuffer.allocate(getPrimaryKeyLength() + 1);
    val limitSK = ByteBuffer.wrap(new byte[getSecondaryKeyLength()]);
    val longSK = ByteBuffer.allocate(getSecondaryKeyLength() + 1);
    val limitValue = ByteBuffer.wrap(new byte[KeyValueTable.MAXIMUM_VALUE_LENGTH]);
    rnd.nextBytes(limitPK.array());
    rnd.nextBytes(limitSK.array());
    rnd.nextBytes(limitValue.array());
    @Cleanup val kvt = createKeyValueTable();
    kvt.update(new Insert(new TableKey(limitPK.duplicate(), limitSK.duplicate()), limitValue.duplicate())).join();
    val resultValue = kvt.get(new TableKey(limitPK.duplicate(), limitSK.duplicate())).join().getValue();
    Assert.assertEquals("Unexpected value returned.", limitValue.duplicate(), resultValue.duplicate());
    // Wrong Key Length
    AssertExtensions.assertSuppliedFutureThrows("Expected a rejection of a PK that is too long.", () -> kvt.update(new Put(new TableKey(longPK.duplicate(), limitSK.duplicate()), limitValue.duplicate())), ex -> ex instanceof IllegalArgumentException);
    AssertExtensions.assertSuppliedFutureThrows("Expected a rejection of a PK that is too long.", () -> kvt.update(new Remove(new TableKey(longPK.duplicate(), limitSK.duplicate()))), ex -> ex instanceof IllegalArgumentException);
    AssertExtensions.assertSuppliedFutureThrows("Expected a rejection of a PK that is too short.", () -> kvt.update(new Put(new TableKey(shortPK.duplicate(), limitSK.duplicate()), limitValue.duplicate())), ex -> ex instanceof IllegalArgumentException);
    AssertExtensions.assertSuppliedFutureThrows("Expected a rejection of a PK that is too short.", () -> kvt.update(new Remove(new TableKey(shortPK.duplicate(), limitSK.duplicate()))), ex -> ex instanceof IllegalArgumentException);
    AssertExtensions.assertSuppliedFutureThrows("Expected a rejection of a SK that is too long.", () -> kvt.update(new Put(new TableKey(limitPK.duplicate(), longSK.duplicate()), limitValue.duplicate())), ex -> ex instanceof IllegalArgumentException);
    AssertExtensions.assertSuppliedFutureThrows("Expected a rejection of a SK that is too long.", () -> kvt.update(new Remove(new TableKey(limitPK.duplicate(), longSK.duplicate()))), ex -> ex instanceof IllegalArgumentException);
    if (getSecondaryKeyLength() > 0) {
        val shortSK = ByteBuffer.allocate(getSecondaryKeyLength() - 1);
        AssertExtensions.assertSuppliedFutureThrows("Expected a rejection of a SK that is too short.", () -> kvt.update(new Put(new TableKey(limitPK.duplicate(), shortSK.duplicate()), limitValue.duplicate())), ex -> ex instanceof IllegalArgumentException);
        AssertExtensions.assertSuppliedFutureThrows("Expected a rejection of a SK that is too short.", () -> kvt.update(new Remove(new TableKey(limitPK.duplicate(), shortSK.duplicate()))), ex -> ex instanceof IllegalArgumentException);
    }
    // Max Value Length exceeded.
    AssertExtensions.assertSuppliedFutureThrows("Expected a rejection of a value that is too long.", () -> kvt.update(new Put(new TableKey(limitPK.duplicate(), limitSK.duplicate()), ByteBuffer.allocate(KeyValueTable.MAXIMUM_VALUE_LENGTH + 1))), ex -> ex instanceof IllegalArgumentException);
}
Also used : lombok.val(lombok.val) Random(java.util.Random) 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 4 with Insert

use of io.pravega.client.tables.Insert 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 5 with Insert

use of io.pravega.client.tables.Insert 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)

Aggregations

Insert (io.pravega.client.tables.Insert)6 TableKey (io.pravega.client.tables.TableKey)6 Cleanup (lombok.Cleanup)6 lombok.val (lombok.val)6 Test (org.junit.Test)6 BadKeyVersionException (io.pravega.client.tables.BadKeyVersionException)5 Put (io.pravega.client.tables.Put)5 Remove (io.pravega.client.tables.Remove)5 Version (io.pravega.client.tables.Version)5 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)5 Random (java.util.Random)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 TableEntry (io.pravega.client.tables.TableEntry)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