Search in sources :

Example 1 with KeyValueTable

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

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

the class KeyValueTableTestBase method checkPrimaryKeyIterator.

private void checkPrimaryKeyIterator(KeyValueTable keyValueTable, Versions versions, int iteration) {
    val itemsAtOnce = getSecondaryKeyCount() / 5;
    forEveryPrimaryKey((pk, secondaryKeys) -> {
        // Get all Table Keys and sort them.
        val allKeys = secondaryKeys.stream().map(sk -> new TableKey(pk, sk)).sorted(KEY_COMPARATOR).collect(Collectors.toList());
        val allEntries = allKeys.stream().map(k -> new TableEntry(k, versions.get(getUniqueKeyId(k.getPrimaryKey(), k.getSecondaryKey())), getValue(k.getPrimaryKey(), k.getSecondaryKey(), iteration))).collect(Collectors.toList());
        // Issue various iterators (range) and verify against expected values.
        for (int startIndex = 0; startIndex < allKeys.size() / 2; startIndex++) {
            val endIndex = allKeys.size() - startIndex;
            val expectedKeys = allKeys.subList(startIndex, endIndex);
            val iterator = keyValueTable.iterator().maxIterationSize(itemsAtOnce).forPrimaryKey(pk, expectedKeys.get(0).getSecondaryKey(), expectedKeys.get(expectedKeys.size() - 1).getSecondaryKey());
            val iteratorKeys = new ArrayList<TableKey>();
            iterator.keys().collectRemaining(ii -> iteratorKeys.addAll(ii.getItems())).join();
            AssertExtensions.assertListEquals("Unexpected keys returned from iterator.keys()", expectedKeys, iteratorKeys, this::areEqual);
            val expectedEntries = allEntries.subList(startIndex, endIndex);
            val iteratorEntries = new ArrayList<TableEntry>();
            iterator.entries().collectRemaining(ii -> iteratorEntries.addAll(ii.getItems())).join();
            AssertExtensions.assertListEquals("Unexpected entries returned from iterator.entries()", expectedEntries, iteratorEntries, (e1, e2) -> areEqual(e1, e2) && e1.getVersion().equals(e2.getVersion()));
        }
    });
}
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) TableEntry(io.pravega.client.tables.TableEntry) ArrayList(java.util.ArrayList) TableKey(io.pravega.client.tables.TableKey)

Example 3 with KeyValueTable

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

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

the class KeyValueTableTestBase method checkValues.

private void checkValues(int iteration, Versions versions, KeyValueTable keyValueTable) {
    // Check individually.
    forEveryKey((pk, sk) -> {
        val keyId = getUniqueKeyId(pk, sk);
        val expectedValue = getValue(pk, sk, iteration);
        val expectedVersion = versions.get(keyId);
        val requestKey = new TableKey(pk, sk);
        val actualEntry = keyValueTable.get(requestKey).join();
        checkValue(requestKey, expectedValue, expectedVersion, actualEntry, keyId);
    });
    // Check using getAll.
    forEveryPrimaryKey((pk, secondaryKeys) -> {
        val expectedVersions = secondaryKeys.stream().map(sk -> versions.get(getUniqueKeyId(pk, sk))).collect(Collectors.toList());
        val expectedValues = secondaryKeys.stream().map(sk -> getValue(pk, sk, iteration)).collect(Collectors.toList());
        val requestKeys = secondaryKeys.stream().map(sk -> new TableKey(pk, sk)).collect(Collectors.toList());
        val result = keyValueTable.getAll(requestKeys).join();
        val hint = getUniqueKeyId(pk);
        Assert.assertEquals("Unexpected result size" + hint, requestKeys.size(), result.size());
        for (int i = 0; i < requestKeys.size(); i++) {
            checkValue(requestKeys.get(i), expectedValues.get(i), expectedVersions.get(i), result.get(i), hint);
        }
    });
}
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) TableKey(io.pravega.client.tables.TableKey)

Example 5 with KeyValueTable

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

the class KeyValueTableTestBase method testLargeEntryBatchRetrieval.

/**
 * Verify that multi-get retrieval from a single segment of keys totalling more than the limit(s) works correctly.
 */
@Test
public void testLargeEntryBatchRetrieval() {
    val keyCount = TableSegment.MAXIMUM_BATCH_KEY_COUNT;
    Function<Integer, byte[]> getValue = keyId -> {
        val result = new byte[Long.BYTES];
        BitConverter.writeInt(result, 0, keyId + 1);
        return result;
    };
    @Cleanup val kvt = createKeyValueTable();
    // Update the entries one-by-one to make sure we do not exceed the max lengths at this step.
    val allKeys = new ArrayList<TableKey>();
    for (int keyId = 0; keyId < keyCount; keyId++) {
        val pk = new byte[getPrimaryKeyLength()];
        val sk = new byte[getSecondaryKeyLength()];
        BitConverter.writeLong(pk, 0, keyId);
        BitConverter.writeInt(sk, 0, keyId);
        val value = getValue.apply(keyId);
        kvt.update(new Put(new TableKey(ByteBuffer.wrap(pk), ByteBuffer.wrap(sk)), ByteBuffer.wrap(value))).join();
        allKeys.add(new TableKey(ByteBuffer.wrap(pk), ByteBuffer.wrap(sk)));
    }
    // Bulk-get all the keys. This should work regardless of the size of the data returned; the KeyValueTable and
    // TableSegment internally should break down the requests and handle this properly.
    val getResult = kvt.getAll(allKeys).join();
    Assert.assertEquals("Unexpected number of keys returned.", allKeys.size(), getResult.size());
    for (int keyId = 0; keyId < allKeys.size(); keyId++) {
        val r = getResult.get(keyId);
        val expectedKey = allKeys.get(keyId);
        Assert.assertTrue("Unexpected key at index " + keyId, areEqual(expectedKey, r.getKey()));
        val expectedValue = getValue.apply(keyId);
        Assert.assertEquals("Unexpected value at index " + keyId, ByteBuffer.wrap(expectedValue), r.getValue());
    }
}
Also used : lombok.val(lombok.val) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) 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) Cleanup(lombok.Cleanup) Put(io.pravega.client.tables.Put) Test(org.junit.Test)

Aggregations

KeyValueTableInfo (io.pravega.client.admin.KeyValueTableInfo)6 Serializer (io.pravega.client.stream.Serializer)6 BadKeyVersionException (io.pravega.client.tables.BadKeyVersionException)6 Insert (io.pravega.client.tables.Insert)6 KeyValueTable (io.pravega.client.tables.KeyValueTable)6 KeyValueTableConfiguration (io.pravega.client.tables.KeyValueTableConfiguration)6 Put (io.pravega.client.tables.Put)6 Remove (io.pravega.client.tables.Remove)6 TableEntry (io.pravega.client.tables.TableEntry)6 TableKey (io.pravega.client.tables.TableKey)6 TableModification (io.pravega.client.tables.TableModification)6 Version (io.pravega.client.tables.Version)6 BitConverter (io.pravega.common.util.BitConverter)6 AssertExtensions (io.pravega.test.common.AssertExtensions)6 LeakDetectorTestSuite (io.pravega.test.common.LeakDetectorTestSuite)6 ByteBuffer (java.nio.ByteBuffer)6 Duration (java.time.Duration)6 ArrayList (java.util.ArrayList)6 HashMap (java.util.HashMap)6 List (java.util.List)6