Search in sources :

Example 1 with IteratorItem

use of io.pravega.segmentstore.contracts.tables.IteratorItem in project pravega by pravega.

the class HashTableSegmentLayout method newIterator.

private <T> CompletableFuture<AsyncIterator<IteratorItem<T>>> newIterator(@NonNull DirectSegmentAccess segment, @NonNull IteratorArgs args, @NonNull GetBucketReader<T> createBucketReader) {
    Preconditions.checkArgument(args.getFrom() == null && args.getTo() == null, "Range Iterators not supported for HashTableSegments.");
    UUID fromHash;
    BufferView serializedState = args.getContinuationToken();
    try {
        fromHash = KeyHasher.getNextHash(serializedState == null ? null : IteratorStateImpl.deserialize(serializedState).getKeyHash());
    } catch (IOException ex) {
        // Bad IteratorState serialization.
        throw new IllegalDataFormatException("Unable to deserialize `serializedState`.", ex);
    }
    if (fromHash == null) {
        // Nothing to iterate on.
        return CompletableFuture.completedFuture(TableIterator.empty());
    }
    // Create a converter that will use a TableBucketReader to fetch all requested items in the iterated Buckets.
    val bucketReader = createBucketReader.apply(segment, this.keyIndex::getBackpointerOffset, this.executor);
    TableIterator.ConvertResult<IteratorItem<T>> converter = bucket -> bucketReader.findAllExisting(bucket.getSegmentOffset(), new TimeoutTimer(args.getFetchTimeout())).thenApply(result -> new IteratorItemImpl<>(new IteratorStateImpl(bucket.getHash()).serialize(), result));
    // Fetch the Tail (Unindexed) Hashes, then create the TableIterator.
    return this.keyIndex.getUnindexedKeyHashes(segment).thenComposeAsync(cacheHashes -> TableIterator.<IteratorItem<T>>builder().segment(segment).cacheHashes(cacheHashes).firstHash(fromHash).executor(executor).resultConverter(converter).fetchTimeout(args.getFetchTimeout()).build(), this.executor);
}
Also used : lombok.val(lombok.val) TableAttributes(io.pravega.segmentstore.contracts.tables.TableAttributes) TableSegmentConfig(io.pravega.segmentstore.contracts.tables.TableSegmentConfig) Getter(lombok.Getter) OperationPriority(io.pravega.segmentstore.server.logs.operations.OperationPriority) SneakyThrows(lombok.SneakyThrows) RequiredArgsConstructor(lombok.RequiredArgsConstructor) HashMap(java.util.HashMap) CompletableFuture(java.util.concurrent.CompletableFuture) RevisionDataInput(io.pravega.common.io.serialization.RevisionDataInput) Function(java.util.function.Function) IteratorArgs(io.pravega.segmentstore.contracts.tables.IteratorArgs) UpdateableSegmentMetadata(io.pravega.segmentstore.server.UpdateableSegmentMetadata) ArrayList(java.util.ArrayList) ArrayView(io.pravega.common.util.ArrayView) SegmentMetadata(io.pravega.segmentstore.server.SegmentMetadata) SegmentType(io.pravega.segmentstore.contracts.SegmentType) IteratorItem(io.pravega.segmentstore.contracts.tables.IteratorItem) Runnables(com.google.common.util.concurrent.Runnables) BufferView(io.pravega.common.util.BufferView) Duration(java.time.Duration) Map(java.util.Map) ScheduledExecutorService(java.util.concurrent.ScheduledExecutorService) RevisionDataOutput(io.pravega.common.io.serialization.RevisionDataOutput) VersionedSerializer(io.pravega.common.io.serialization.VersionedSerializer) IteratorState(io.pravega.segmentstore.contracts.tables.IteratorState) Attributes(io.pravega.segmentstore.contracts.Attributes) TableKey(io.pravega.segmentstore.contracts.tables.TableKey) TimeoutTimer(io.pravega.common.TimeoutTimer) NonNull(lombok.NonNull) Collection(java.util.Collection) AttributeId(io.pravega.segmentstore.contracts.AttributeId) lombok.val(lombok.val) AsyncIterator(io.pravega.common.util.AsyncIterator) IOException(java.io.IOException) UUID(java.util.UUID) Collectors(java.util.stream.Collectors) ObjectBuilder(io.pravega.common.ObjectBuilder) DirectSegmentAccess(io.pravega.segmentstore.server.DirectSegmentAccess) List(java.util.List) TableSegmentInfo(io.pravega.segmentstore.contracts.tables.TableSegmentInfo) Preconditions(com.google.common.base.Preconditions) IllegalDataFormatException(io.pravega.common.util.IllegalDataFormatException) WriterSegmentProcessor(io.pravega.segmentstore.server.WriterSegmentProcessor) TableEntry(io.pravega.segmentstore.contracts.tables.TableEntry) Collections(java.util.Collections) Futures(io.pravega.common.concurrent.Futures) CacheManager(io.pravega.segmentstore.server.CacheManager) IllegalDataFormatException(io.pravega.common.util.IllegalDataFormatException) BufferView(io.pravega.common.util.BufferView) IteratorItem(io.pravega.segmentstore.contracts.tables.IteratorItem) IOException(java.io.IOException) UUID(java.util.UUID) TimeoutTimer(io.pravega.common.TimeoutTimer)

Example 2 with IteratorItem

use of io.pravega.segmentstore.contracts.tables.IteratorItem in project pravega by pravega.

the class TableSegmentLayoutTestBase method collectIteratorItems.

private <T> List<T> collectIteratorItems(AsyncIterator<IteratorItem<T>> iterator) throws Exception {
    val result = new ArrayList<T>();
    val hashes = new HashSet<BufferView>();
    iterator.forEachRemaining(item -> {
        Assert.assertTrue("Duplicate IteratorItem.getState().", hashes.add(item.getState()));
        result.addAll(item.getEntries());
    }, executorService()).get(TIMEOUT.toMillis(), TimeUnit.MILLISECONDS);
    return result;
}
Also used : lombok.val(lombok.val) IntStream(java.util.stream.IntStream) TableAttributes(io.pravega.segmentstore.contracts.tables.TableAttributes) BufferViewComparator(io.pravega.common.util.BufferViewComparator) StreamSegmentNotExistsException(io.pravega.segmentstore.contracts.StreamSegmentNotExistsException) SneakyThrows(lombok.SneakyThrows) AssertExtensions(io.pravega.test.common.AssertExtensions) RequiredArgsConstructor(lombok.RequiredArgsConstructor) Cleanup(lombok.Cleanup) HashMap(java.util.HashMap) AtomicReference(java.util.concurrent.atomic.AtomicReference) Function(java.util.function.Function) BadKeyVersionException(io.pravega.segmentstore.contracts.tables.BadKeyVersionException) IteratorArgs(io.pravega.segmentstore.contracts.tables.IteratorArgs) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) TableSegmentNotEmptyException(io.pravega.segmentstore.contracts.tables.TableSegmentNotEmptyException) IteratorItem(io.pravega.segmentstore.contracts.tables.IteratorItem) BufferView(io.pravega.common.util.BufferView) Duration(java.time.Duration) Map(java.util.Map) TableKey(io.pravega.segmentstore.contracts.tables.TableKey) Collection(java.util.Collection) AttributeId(io.pravega.segmentstore.contracts.AttributeId) lombok.val(lombok.val) AsyncIterator(io.pravega.common.util.AsyncIterator) Test(org.junit.Test) Collectors(java.util.stream.Collectors) Objects(java.util.Objects) TimeUnit(java.util.concurrent.TimeUnit) List(java.util.List) ByteArraySegment(io.pravega.common.util.ByteArraySegment) ThreadPooledTestSuite(io.pravega.test.common.ThreadPooledTestSuite) TestUtils(io.pravega.test.common.TestUtils) Comparator(java.util.Comparator) Assert(org.junit.Assert) TableEntry(io.pravega.segmentstore.contracts.tables.TableEntry) Collections(java.util.Collections) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet)

Example 3 with IteratorItem

use of io.pravega.segmentstore.contracts.tables.IteratorItem in project pravega by pravega.

the class TableServiceTests method check.

private void check(HashMap<BufferView, EntryData> keyInfo, TableStore tableStore) throws Exception {
    val bySegment = keyInfo.entrySet().stream().collect(Collectors.groupingBy(e -> e.getValue().segmentName));
    // Check inexistent keys.
    val searchFutures = new ArrayList<CompletableFuture<List<TableEntry>>>();
    val iteratorFutures = new ArrayList<CompletableFuture<List<TableEntry>>>();
    // Delta Iteration does not support fixed-key-length TableSegments.
    val unsortedIteratorFutures = new ArrayList<CompletableFuture<List<TableEntry>>>();
    val offsetIteratorFutures = new ArrayList<CompletableFuture<List<IteratorItem<TableEntry>>>>();
    val expectedResult = new ArrayList<Map.Entry<BufferView, EntryData>>();
    for (val e : bySegment.entrySet()) {
        String segmentName = e.getKey();
        boolean fixedKeyLength = isFixedKeyLength(segmentName);
        val info = tableStore.getInfo(segmentName, TIMEOUT).get(TIMEOUT.toMillis(), TimeUnit.MILLISECONDS);
        Assert.assertEquals(segmentName, info.getName());
        AssertExtensions.assertGreaterThan("Unexpected length for " + segmentName, 0, info.getLength());
        val expectedKeyLength = isFixedKeyLength(segmentName) ? getFixedKeyLength(segmentName) : 0;
        Assert.assertEquals("Unexpected key length for " + segmentName, expectedKeyLength, info.getKeyLength());
        Assert.assertEquals(fixedKeyLength, info.getType().isFixedKeyLengthTableSegment());
        val keys = new ArrayList<BufferView>();
        for (val se : e.getValue()) {
            keys.add(se.getKey());
            expectedResult.add(se);
        }
        searchFutures.add(tableStore.get(segmentName, keys, TIMEOUT));
        CompletableFuture<List<TableEntry>> entryIteratorFuture = tableStore.entryIterator(segmentName, IteratorArgs.builder().fetchTimeout(TIMEOUT).build()).thenCompose(ei -> {
            val result = new ArrayList<TableEntry>();
            return ei.forEachRemaining(i -> result.addAll(i.getEntries()), executorService()).thenApply(v -> {
                if (fixedKeyLength) {
                    checkSortedOrder(result);
                }
                return result;
            });
        });
        iteratorFutures.add(entryIteratorFuture);
        if (!fixedKeyLength) {
            unsortedIteratorFutures.add(entryIteratorFuture);
            // For simplicity, always start from beginning of TableSegment.
            offsetIteratorFutures.add(tableStore.entryDeltaIterator(segmentName, 0L, TIMEOUT).thenCompose(ei -> {
                val result = new ArrayList<IteratorItem<TableEntry>>();
                return ei.forEachRemaining(result::add, executorService()).thenApply(v -> result);
            }));
        }
    }
    // Check search results.
    val actualResults = Futures.allOfWithResults(searchFutures).get(TIMEOUT.toMillis(), TimeUnit.MILLISECONDS).stream().flatMap(List::stream).collect(Collectors.toList());
    Assert.assertEquals("Unexpected number of search results.", expectedResult.size(), actualResults.size());
    for (int i = 0; i < expectedResult.size(); i++) {
        val expectedKey = expectedResult.get(i).getKey();
        val expectedEntry = expectedResult.get(i).getValue();
        val actual = actualResults.get(i);
        if (expectedEntry.isDeleted()) {
            // Deleted keys will be returned as nulls.
            if (actual != null) {
                val r2 = tableStore.get(expectedEntry.segmentName, Collections.singletonList(expectedKey), TIMEOUT).join();
            }
            Assert.assertNull("Not expecting a value for a deleted Key ", actual);
        } else {
            Assert.assertEquals("Unexpected value for non-deleted Key.", expectedEntry.getValue(), actual.getValue());
            Assert.assertEquals("Unexpected key for non-deleted Key.", expectedKey, actual.getKey().getKey());
            Assert.assertEquals("Unexpected TableKey.Version for non-deleted Key.", expectedEntry.getVersion(), actual.getKey().getVersion());
        }
    }
    // Check iterator results. We sort it (and actualResults) by Version/Offset to ease the comparison.
    val actualIteratorResults = Futures.allOfWithResults(iteratorFutures).get(TIMEOUT.toMillis(), TimeUnit.MILLISECONDS).stream().flatMap(List::stream).sorted(Comparator.comparingLong(e -> e.getKey().getVersion())).collect(Collectors.toList());
    val expectedIteratorResults = actualResults.stream().filter(Objects::nonNull).sorted(Comparator.comparingLong(e -> e.getKey().getVersion())).collect(Collectors.toList());
    // These lists are used to compare non-delta based iteration with delta based iteration.
    val actualUnsortedIteratorResults = Futures.allOfWithResults(unsortedIteratorFutures).get(TIMEOUT.toMillis(), TimeUnit.MILLISECONDS).stream().flatMap(List::stream).sorted(Comparator.comparingLong(e -> e.getKey().getVersion())).collect(Collectors.toList());
    val expectedUnsortedIteratorResults = actualUnsortedIteratorResults.stream().filter(Objects::nonNull).sorted(Comparator.comparingLong(e -> e.getKey().getVersion())).collect(Collectors.toList());
    val actualOffsetIteratorList = Futures.allOfWithResults(offsetIteratorFutures).get(TIMEOUT.toMillis(), TimeUnit.MILLISECONDS).stream().flatMap(List::stream).collect(Collectors.toList());
    val actualOffsetIteratorResults = processDeltaIteratorItems(actualOffsetIteratorList).stream().sorted(Comparator.comparingLong(e -> e.getKey().getVersion())).collect(Collectors.toList());
    AssertExtensions.assertListEquals("Unexpected result from entryIterator().", expectedIteratorResults, actualIteratorResults, TableEntry::equals);
    for (val entry : expectedUnsortedIteratorResults) {
        Assert.assertNotNull("Missing expected TableEntry from deltaEntryIterator()", actualOffsetIteratorResults.contains(entry));
    }
}
Also used : lombok.val(lombok.val) BufferViewComparator(io.pravega.common.util.BufferViewComparator) TableSegmentConfig(io.pravega.segmentstore.contracts.tables.TableSegmentConfig) WriterConfig(io.pravega.segmentstore.server.writer.WriterConfig) TableStore(io.pravega.segmentstore.contracts.tables.TableStore) AssertExtensions(io.pravega.test.common.AssertExtensions) RequiredArgsConstructor(lombok.RequiredArgsConstructor) ServiceConfig(io.pravega.segmentstore.server.store.ServiceConfig) HashMap(java.util.HashMap) Random(java.util.Random) CompletableFuture(java.util.concurrent.CompletableFuture) ServiceBuilderConfig(io.pravega.segmentstore.server.store.ServiceBuilderConfig) AtomicReference(java.util.concurrent.atomic.AtomicReference) IteratorArgs(io.pravega.segmentstore.contracts.tables.IteratorArgs) ArrayList(java.util.ArrayList) SegmentType(io.pravega.segmentstore.contracts.SegmentType) ServiceBuilder(io.pravega.segmentstore.server.store.ServiceBuilder) IteratorItem(io.pravega.segmentstore.contracts.tables.IteratorItem) BufferView(io.pravega.common.util.BufferView) InMemoryStorageFactory(io.pravega.segmentstore.storage.mocks.InMemoryStorageFactory) Duration(java.time.Duration) Map(java.util.Map) After(org.junit.After) ContainerConfig(io.pravega.segmentstore.server.containers.ContainerConfig) ReadIndexConfig(io.pravega.segmentstore.server.reading.ReadIndexConfig) ScheduledExecutorService(java.util.concurrent.ScheduledExecutorService) Timeout(org.junit.rules.Timeout) InMemoryDurableDataLogFactory(io.pravega.segmentstore.storage.mocks.InMemoryDurableDataLogFactory) StreamSegmentStore(io.pravega.segmentstore.contracts.StreamSegmentStore) Before(org.junit.Before) TableKey(io.pravega.segmentstore.contracts.tables.TableKey) DurableLogConfig(io.pravega.segmentstore.server.logs.DurableLogConfig) lombok.val(lombok.val) Test(org.junit.Test) Collectors(java.util.stream.Collectors) Objects(java.util.Objects) TimeUnit(java.util.concurrent.TimeUnit) AtomicLong(java.util.concurrent.atomic.AtomicLong) List(java.util.List) Slf4j(lombok.extern.slf4j.Slf4j) Rule(org.junit.Rule) ByteArraySegment(io.pravega.common.util.ByteArraySegment) ThreadPooledTestSuite(io.pravega.test.common.ThreadPooledTestSuite) Comparator(java.util.Comparator) Assert(org.junit.Assert) TableEntry(io.pravega.segmentstore.contracts.tables.TableEntry) Collections(java.util.Collections) Futures(io.pravega.common.concurrent.Futures) ArrayList(java.util.ArrayList) TableEntry(io.pravega.segmentstore.contracts.tables.TableEntry) BufferView(io.pravega.common.util.BufferView) IteratorItem(io.pravega.segmentstore.contracts.tables.IteratorItem) Objects(java.util.Objects) ArrayList(java.util.ArrayList) List(java.util.List) HashMap(java.util.HashMap) Map(java.util.Map)

Example 4 with IteratorItem

use of io.pravega.segmentstore.contracts.tables.IteratorItem in project pravega by pravega.

the class HashTableSegmentLayout method entryDeltaIterator.

@Override
AsyncIterator<IteratorItem<TableEntry>> entryDeltaIterator(@NonNull DirectSegmentAccess segment, long fromPosition, Duration fetchTimeout) {
    val segmentInfo = segment.getInfo();
    ensureSegmentType(segmentInfo.getName(), segmentInfo.getType());
    Preconditions.checkArgument(fromPosition <= segmentInfo.getLength(), "fromPosition (%s) can not exceed the length (%s) of the TableSegment.", fromPosition, segmentInfo.getLength());
    logRequest("entryDeltaIterator", segment.getSegmentId(), fromPosition);
    long compactionOffset = segmentInfo.getAttributes().getOrDefault(TableAttributes.COMPACTION_OFFSET, 0L);
    // All of the most recent keys will exist beyond the compactionOffset.
    long startOffset = Math.max(fromPosition, compactionOffset);
    // We should clear if the starting position may have been truncated out due to compaction.
    boolean shouldClear = fromPosition < compactionOffset;
    // Maximum length of the TableSegment we want to read until.
    int maxBytesToRead = (int) (segmentInfo.getLength() - startOffset);
    TableEntryDeltaIterator.ConvertResult<IteratorItem<TableEntry>> converter = item -> CompletableFuture.completedFuture(new IteratorItemImpl<TableEntry>(item.getKey().serialize(), Collections.singletonList(item.getValue())));
    return TableEntryDeltaIterator.<IteratorItem<TableEntry>>builder().segment(segment).entrySerializer(serializer).executor(executor).maxBytesToRead(maxBytesToRead).startOffset(startOffset).currentBatchOffset(fromPosition).fetchTimeout(fetchTimeout).resultConverter(converter).shouldClear(shouldClear).build();
}
Also used : lombok.val(lombok.val) TableAttributes(io.pravega.segmentstore.contracts.tables.TableAttributes) TableSegmentConfig(io.pravega.segmentstore.contracts.tables.TableSegmentConfig) Getter(lombok.Getter) OperationPriority(io.pravega.segmentstore.server.logs.operations.OperationPriority) SneakyThrows(lombok.SneakyThrows) RequiredArgsConstructor(lombok.RequiredArgsConstructor) HashMap(java.util.HashMap) CompletableFuture(java.util.concurrent.CompletableFuture) RevisionDataInput(io.pravega.common.io.serialization.RevisionDataInput) Function(java.util.function.Function) IteratorArgs(io.pravega.segmentstore.contracts.tables.IteratorArgs) UpdateableSegmentMetadata(io.pravega.segmentstore.server.UpdateableSegmentMetadata) ArrayList(java.util.ArrayList) ArrayView(io.pravega.common.util.ArrayView) SegmentMetadata(io.pravega.segmentstore.server.SegmentMetadata) SegmentType(io.pravega.segmentstore.contracts.SegmentType) IteratorItem(io.pravega.segmentstore.contracts.tables.IteratorItem) Runnables(com.google.common.util.concurrent.Runnables) BufferView(io.pravega.common.util.BufferView) Duration(java.time.Duration) Map(java.util.Map) ScheduledExecutorService(java.util.concurrent.ScheduledExecutorService) RevisionDataOutput(io.pravega.common.io.serialization.RevisionDataOutput) VersionedSerializer(io.pravega.common.io.serialization.VersionedSerializer) IteratorState(io.pravega.segmentstore.contracts.tables.IteratorState) Attributes(io.pravega.segmentstore.contracts.Attributes) TableKey(io.pravega.segmentstore.contracts.tables.TableKey) TimeoutTimer(io.pravega.common.TimeoutTimer) NonNull(lombok.NonNull) Collection(java.util.Collection) AttributeId(io.pravega.segmentstore.contracts.AttributeId) lombok.val(lombok.val) AsyncIterator(io.pravega.common.util.AsyncIterator) IOException(java.io.IOException) UUID(java.util.UUID) Collectors(java.util.stream.Collectors) ObjectBuilder(io.pravega.common.ObjectBuilder) DirectSegmentAccess(io.pravega.segmentstore.server.DirectSegmentAccess) List(java.util.List) TableSegmentInfo(io.pravega.segmentstore.contracts.tables.TableSegmentInfo) Preconditions(com.google.common.base.Preconditions) IllegalDataFormatException(io.pravega.common.util.IllegalDataFormatException) WriterSegmentProcessor(io.pravega.segmentstore.server.WriterSegmentProcessor) TableEntry(io.pravega.segmentstore.contracts.tables.TableEntry) Collections(java.util.Collections) Futures(io.pravega.common.concurrent.Futures) CacheManager(io.pravega.segmentstore.server.CacheManager) TableEntry(io.pravega.segmentstore.contracts.tables.TableEntry) IteratorItem(io.pravega.segmentstore.contracts.tables.IteratorItem)

Aggregations

BufferView (io.pravega.common.util.BufferView)4 IteratorArgs (io.pravega.segmentstore.contracts.tables.IteratorArgs)4 IteratorItem (io.pravega.segmentstore.contracts.tables.IteratorItem)4 TableEntry (io.pravega.segmentstore.contracts.tables.TableEntry)4 TableKey (io.pravega.segmentstore.contracts.tables.TableKey)4 Duration (java.time.Duration)4 ArrayList (java.util.ArrayList)4 Collections (java.util.Collections)4 HashMap (java.util.HashMap)4 List (java.util.List)4 Map (java.util.Map)4 Collectors (java.util.stream.Collectors)4 RequiredArgsConstructor (lombok.RequiredArgsConstructor)4 lombok.val (lombok.val)4 Futures (io.pravega.common.concurrent.Futures)3 AsyncIterator (io.pravega.common.util.AsyncIterator)3 AttributeId (io.pravega.segmentstore.contracts.AttributeId)3 SegmentType (io.pravega.segmentstore.contracts.SegmentType)3 TableAttributes (io.pravega.segmentstore.contracts.tables.TableAttributes)3 TableSegmentConfig (io.pravega.segmentstore.contracts.tables.TableSegmentConfig)3