Search in sources :

Example 1 with AttributeIndex

use of io.pravega.segmentstore.server.AttributeIndex in project pravega by pravega.

the class AttributeIndexTests method checkIndex.

private void checkIndex(AttributeIndex index, Map<AttributeId, Long> expectedValues) {
    val actual = index.get(expectedValues.keySet(), TIMEOUT).join();
    val expected = expectedValues.entrySet().stream().filter(e -> e.getValue() != Attributes.NULL_ATTRIBUTE_VALUE).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
    AssertExtensions.assertMapEquals("Unexpected attributes in index.", expected, actual);
}
Also used : lombok.val(lombok.val) Arrays(java.util.Arrays) StreamSegmentInformation(io.pravega.segmentstore.contracts.StreamSegmentInformation) StreamSegmentNotExistsException(io.pravega.segmentstore.contracts.StreamSegmentNotExistsException) SneakyThrows(lombok.SneakyThrows) AssertExtensions(io.pravega.test.common.AssertExtensions) BiFunction(java.util.function.BiFunction) Cleanup(lombok.Cleanup) SegmentProperties(io.pravega.segmentstore.contracts.SegmentProperties) StreamSegmentSealedException(io.pravega.segmentstore.contracts.StreamSegmentSealedException) SegmentHandle(io.pravega.segmentstore.storage.SegmentHandle) ByteArrayInputStream(java.io.ByteArrayInputStream) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) BufferView(io.pravega.common.util.BufferView) Duration(java.time.Duration) Map(java.util.Map) CachePolicy(io.pravega.segmentstore.server.CachePolicy) TestCacheManager(io.pravega.segmentstore.server.TestCacheManager) Attributes(io.pravega.segmentstore.contracts.Attributes) Collection(java.util.Collection) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) InMemoryStorage(io.pravega.segmentstore.storage.mocks.InMemoryStorage) CompletionException(java.util.concurrent.CompletionException) Collectors(java.util.stream.Collectors) ByteArraySegment(io.pravega.common.util.ByteArraySegment) ThreadPooledTestSuite(io.pravega.test.common.ThreadPooledTestSuite) SyncStorage(io.pravega.segmentstore.storage.SyncStorage) DirectMemoryCache(io.pravega.segmentstore.storage.cache.DirectMemoryCache) TestUtils(io.pravega.test.common.TestUtils) Futures(io.pravega.common.concurrent.Futures) IntStream(java.util.stream.IntStream) MetadataBuilder(io.pravega.segmentstore.server.MetadataBuilder) StreamSegmentException(io.pravega.segmentstore.contracts.StreamSegmentException) AsyncStorageWrapper(io.pravega.segmentstore.storage.AsyncStorageWrapper) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) HashMap(java.util.HashMap) CompletableFuture(java.util.concurrent.CompletableFuture) Function(java.util.function.Function) Supplier(java.util.function.Supplier) UpdateableContainerMetadata(io.pravega.segmentstore.server.UpdateableContainerMetadata) BiConsumer(java.util.function.BiConsumer) CacheFullException(io.pravega.segmentstore.storage.cache.CacheFullException) StreamHelpers(io.pravega.common.io.StreamHelpers) ReusableLatch(io.pravega.common.util.ReusableLatch) StreamSegmentTruncatedException(io.pravega.segmentstore.contracts.StreamSegmentTruncatedException) NameUtils(io.pravega.shared.NameUtils) AttributeIndex(io.pravega.segmentstore.server.AttributeIndex) RollingStorage(io.pravega.segmentstore.storage.rolling.RollingStorage) Executor(java.util.concurrent.Executor) AttributeId(io.pravega.segmentstore.contracts.AttributeId) IntentionalException(io.pravega.test.common.IntentionalException) lombok.val(lombok.val) Test(org.junit.Test) TimeUnit(java.util.concurrent.TimeUnit) Consumer(java.util.function.Consumer) AtomicLong(java.util.concurrent.atomic.AtomicLong) AbstractMap(java.util.AbstractMap) Preconditions(com.google.common.base.Preconditions) DataCorruptionException(io.pravega.segmentstore.server.DataCorruptionException) Assert(org.junit.Assert) Collections(java.util.Collections) InputStream(java.io.InputStream) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap) AbstractMap(java.util.AbstractMap)

Example 2 with AttributeIndex

use of io.pravega.segmentstore.server.AttributeIndex in project pravega by pravega.

the class ContainerAttributeIndexImpl method forSegment.

// endregion
// region ContainerAttributeIndex Implementation
@Override
public CompletableFuture<AttributeIndex> forSegment(long streamSegmentId, Duration timeout) {
    Exceptions.checkNotClosed(this.closed.get(), this);
    SegmentMetadata sm = this.containerMetadata.getStreamSegmentMetadata(streamSegmentId);
    if (sm.isDeleted()) {
        return Futures.failedFuture(new StreamSegmentNotExistsException(sm.getName()));
    }
    // Figure out if we already have this AttributeIndex cached. If not, we need to initialize it.
    CompletableFuture<AttributeIndex> result;
    AtomicReference<SegmentAttributeBTreeIndex> toInitialize = new AtomicReference<>();
    synchronized (this.attributeIndices) {
        result = this.attributeIndices.computeIfAbsent(streamSegmentId, id -> {
            toInitialize.set(new SegmentAttributeBTreeIndex(sm, this.storage, this.cacheManager.getCacheStorage(), this.config, this.executor));
            return new CompletableFuture<>();
        });
    }
    if (toInitialize.get() == null) {
        // its initialization is done).
        return result;
    } else {
        try {
            // Need to initialize the AttributeIndex and complete the future that we just registered.
            // If this fails, we must fail the Future that we previously registered and unregister any pointers to
            // this index.
            toInitialize.get().initialize(timeout).thenRun(() -> this.cacheManager.register(toInitialize.get())).whenComplete((r, ex) -> {
                if (ex == null) {
                    result.complete(toInitialize.get());
                } else {
                    indexInitializationFailed(streamSegmentId, result, ex);
                }
            });
        } catch (Throwable ex) {
            if (!Exceptions.mustRethrow(ex)) {
                indexInitializationFailed(streamSegmentId, result, ex);
            }
            throw ex;
        }
    }
    return result;
}
Also used : SegmentMetadata(io.pravega.segmentstore.server.SegmentMetadata) Storage(io.pravega.segmentstore.storage.Storage) AttributeIndex(io.pravega.segmentstore.server.AttributeIndex) StreamSegmentNotExistsException(io.pravega.segmentstore.contracts.StreamSegmentNotExistsException) Collection(java.util.Collection) Exceptions(io.pravega.common.Exceptions) ContainerMetadata(io.pravega.segmentstore.server.ContainerMetadata) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) HashMap(java.util.HashMap) CompletableFuture(java.util.concurrent.CompletableFuture) GuardedBy(javax.annotation.concurrent.GuardedBy) AtomicReference(java.util.concurrent.atomic.AtomicReference) ArrayList(java.util.ArrayList) SegmentMetadata(io.pravega.segmentstore.server.SegmentMetadata) Slf4j(lombok.extern.slf4j.Slf4j) Duration(java.time.Duration) ScheduledExecutorService(java.util.concurrent.ScheduledExecutorService) Preconditions(com.google.common.base.Preconditions) Futures(io.pravega.common.concurrent.Futures) CacheManager(io.pravega.segmentstore.server.CacheManager) AttributeIndex(io.pravega.segmentstore.server.AttributeIndex) AtomicReference(java.util.concurrent.atomic.AtomicReference) StreamSegmentNotExistsException(io.pravega.segmentstore.contracts.StreamSegmentNotExistsException)

Example 3 with AttributeIndex

use of io.pravega.segmentstore.server.AttributeIndex in project pravega by pravega.

the class AttributeIndexTests method testRecoveryAfterIncompleteUpdateWithRootPointer.

/**
 * Tests the ability of the Attribute Index to recover correctly after a partial update has been written to Storage.
 * This simulates how it should be used by a caller: after every update, the {@link Attributes#ATTRIBUTE_SEGMENT_ROOT_POINTER}
 * attribute of the segment should be set to the return value from {@link AttributeIndex#update} in order to perform
 * a correct recovery.
 */
@Test
public void testRecoveryAfterIncompleteUpdateWithRootPointer() {
    final int attributeCount = 1000;
    val attributes = IntStream.range(0, attributeCount).mapToObj(i -> AttributeId.uuid(i, i)).collect(Collectors.toList());
    @Cleanup val context = new TestContext(DEFAULT_CONFIG);
    // Root pointers are read from Segment's Metadata if Storage does not support atomic writes. This test validates
    // that case: a partial write with the help of metadata-stored Root Pointers (if the Root Pointers were not stored
    // in the metadata, then the recovery would fail).
    context.storage.supportsAtomicWrites = false;
    populateSegments(context);
    // 1. Populate and verify first index.
    val idx = context.index.forSegment(SEGMENT_ID, TIMEOUT).join();
    val expectedValues = new HashMap<AttributeId, Long>();
    val updateBatch = new HashMap<AttributeId, Long>();
    AtomicLong nextValue = new AtomicLong(0);
    for (AttributeId attributeId : attributes) {
        long value = nextValue.getAndIncrement();
        expectedValues.put(attributeId, value);
        updateBatch.put(attributeId, value);
    }
    // Perform the update and remember the root pointer.
    long rootPointer = idx.update(updateBatch, TIMEOUT).join();
    context.containerMetadata.getStreamSegmentMetadata(SEGMENT_ID).updateAttributes(Collections.singletonMap(Attributes.ATTRIBUTE_SEGMENT_ROOT_POINTER, rootPointer));
    // 2. Write some garbage data at the end of the segment. This simulates a partial (incomplete update) that did not
    // fully write the BTree pages to the end of the segment.
    String attributeSegmentName = NameUtils.getAttributeSegmentName(SEGMENT_NAME);
    byte[] partialUpdate = new byte[1234];
    context.storage.openWrite(attributeSegmentName).thenCompose(handle -> context.storage.write(handle, context.storage.getStreamSegmentInfo(attributeSegmentName, TIMEOUT).join().getLength(), new ByteArrayInputStream(partialUpdate), partialUpdate.length, TIMEOUT)).join();
    // 3. Reload index and verify it still has the correct values. This also forces a cache cleanup so we read data
    // directly from Storage.
    context.index.cleanup(null);
    val storageRead = new AtomicBoolean();
    context.storage.readInterceptor = (name, offset, length, storage) -> CompletableFuture.runAsync(() -> storageRead.set(true));
    val idx2 = context.index.forSegment(SEGMENT_ID, TIMEOUT).join();
    checkIndex(idx2, expectedValues);
    Assert.assertTrue("Expecting storage reads after reload.", storageRead.get());
    // 4. Remove all values (and thus force an update - validates conditional updates still work in this case).
    idx2.update(toDelete(expectedValues.keySet()), TIMEOUT).join();
    expectedValues.replaceAll((key, v) -> Attributes.NULL_ATTRIBUTE_VALUE);
    checkIndex(idx2, expectedValues);
}
Also used : lombok.val(lombok.val) Arrays(java.util.Arrays) StreamSegmentInformation(io.pravega.segmentstore.contracts.StreamSegmentInformation) StreamSegmentNotExistsException(io.pravega.segmentstore.contracts.StreamSegmentNotExistsException) SneakyThrows(lombok.SneakyThrows) AssertExtensions(io.pravega.test.common.AssertExtensions) BiFunction(java.util.function.BiFunction) Cleanup(lombok.Cleanup) SegmentProperties(io.pravega.segmentstore.contracts.SegmentProperties) StreamSegmentSealedException(io.pravega.segmentstore.contracts.StreamSegmentSealedException) SegmentHandle(io.pravega.segmentstore.storage.SegmentHandle) ByteArrayInputStream(java.io.ByteArrayInputStream) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) BufferView(io.pravega.common.util.BufferView) Duration(java.time.Duration) Map(java.util.Map) CachePolicy(io.pravega.segmentstore.server.CachePolicy) TestCacheManager(io.pravega.segmentstore.server.TestCacheManager) Attributes(io.pravega.segmentstore.contracts.Attributes) Collection(java.util.Collection) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) InMemoryStorage(io.pravega.segmentstore.storage.mocks.InMemoryStorage) CompletionException(java.util.concurrent.CompletionException) Collectors(java.util.stream.Collectors) ByteArraySegment(io.pravega.common.util.ByteArraySegment) ThreadPooledTestSuite(io.pravega.test.common.ThreadPooledTestSuite) SyncStorage(io.pravega.segmentstore.storage.SyncStorage) DirectMemoryCache(io.pravega.segmentstore.storage.cache.DirectMemoryCache) TestUtils(io.pravega.test.common.TestUtils) Futures(io.pravega.common.concurrent.Futures) IntStream(java.util.stream.IntStream) MetadataBuilder(io.pravega.segmentstore.server.MetadataBuilder) StreamSegmentException(io.pravega.segmentstore.contracts.StreamSegmentException) AsyncStorageWrapper(io.pravega.segmentstore.storage.AsyncStorageWrapper) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) HashMap(java.util.HashMap) CompletableFuture(java.util.concurrent.CompletableFuture) Function(java.util.function.Function) Supplier(java.util.function.Supplier) UpdateableContainerMetadata(io.pravega.segmentstore.server.UpdateableContainerMetadata) BiConsumer(java.util.function.BiConsumer) CacheFullException(io.pravega.segmentstore.storage.cache.CacheFullException) StreamHelpers(io.pravega.common.io.StreamHelpers) ReusableLatch(io.pravega.common.util.ReusableLatch) StreamSegmentTruncatedException(io.pravega.segmentstore.contracts.StreamSegmentTruncatedException) NameUtils(io.pravega.shared.NameUtils) AttributeIndex(io.pravega.segmentstore.server.AttributeIndex) RollingStorage(io.pravega.segmentstore.storage.rolling.RollingStorage) Executor(java.util.concurrent.Executor) AttributeId(io.pravega.segmentstore.contracts.AttributeId) IntentionalException(io.pravega.test.common.IntentionalException) lombok.val(lombok.val) Test(org.junit.Test) TimeUnit(java.util.concurrent.TimeUnit) Consumer(java.util.function.Consumer) AtomicLong(java.util.concurrent.atomic.AtomicLong) AbstractMap(java.util.AbstractMap) Preconditions(com.google.common.base.Preconditions) DataCorruptionException(io.pravega.segmentstore.server.DataCorruptionException) Assert(org.junit.Assert) Collections(java.util.Collections) InputStream(java.io.InputStream) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap) AttributeId(io.pravega.segmentstore.contracts.AttributeId) Cleanup(lombok.Cleanup) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) AtomicLong(java.util.concurrent.atomic.AtomicLong) ByteArrayInputStream(java.io.ByteArrayInputStream) Test(org.junit.Test)

Aggregations

Preconditions (com.google.common.base.Preconditions)3 Futures (io.pravega.common.concurrent.Futures)3 StreamSegmentNotExistsException (io.pravega.segmentstore.contracts.StreamSegmentNotExistsException)3 AttributeIndex (io.pravega.segmentstore.server.AttributeIndex)3 Duration (java.time.Duration)3 Collection (java.util.Collection)3 HashMap (java.util.HashMap)3 StreamHelpers (io.pravega.common.io.StreamHelpers)2 BufferView (io.pravega.common.util.BufferView)2 ByteArraySegment (io.pravega.common.util.ByteArraySegment)2 ReusableLatch (io.pravega.common.util.ReusableLatch)2 AttributeId (io.pravega.segmentstore.contracts.AttributeId)2 Attributes (io.pravega.segmentstore.contracts.Attributes)2 SegmentProperties (io.pravega.segmentstore.contracts.SegmentProperties)2 StreamSegmentException (io.pravega.segmentstore.contracts.StreamSegmentException)2 StreamSegmentInformation (io.pravega.segmentstore.contracts.StreamSegmentInformation)2 StreamSegmentSealedException (io.pravega.segmentstore.contracts.StreamSegmentSealedException)2 StreamSegmentTruncatedException (io.pravega.segmentstore.contracts.StreamSegmentTruncatedException)2 CachePolicy (io.pravega.segmentstore.server.CachePolicy)2 DataCorruptionException (io.pravega.segmentstore.server.DataCorruptionException)2