Search in sources :

Example 16 with DurableDataLog

use of io.pravega.segmentstore.storage.DurableDataLog in project pravega by pravega.

the class StreamSegmentContainerTests method testStartOffline.

/**
 * Tests the ability of the StreamSegmentContainer to start in Offline mode (due to an offline DurableLog) and eventually
 * become online when the DurableLog becomes too.
 */
@Test
public void testStartOffline() throws Exception {
    @Cleanup val context = createContext();
    AtomicReference<DurableDataLog> dataLog = new AtomicReference<>();
    @Cleanup val dataLogFactory = new TestDurableDataLogFactory(context.dataLogFactory, dataLog::set);
    AtomicReference<OperationLog> durableLog = new AtomicReference<>();
    val durableLogFactory = new WatchableOperationLogFactory(new DurableLogFactory(DEFAULT_DURABLE_LOG_CONFIG, dataLogFactory, executorService()), durableLog::set);
    val containerFactory = new StreamSegmentContainerFactory(DEFAULT_CONFIG, durableLogFactory, context.readIndexFactory, context.attributeIndexFactory, context.writerFactory, context.storageFactory, context.getDefaultExtensions(), executorService());
    // Write some data
    ArrayList<String> segmentNames = new ArrayList<>();
    HashMap<String, Long> lengths = new HashMap<>();
    HashMap<String, ByteArrayOutputStream> segmentContents = new HashMap<>();
    try (val container = containerFactory.createStreamSegmentContainer(CONTAINER_ID)) {
        container.startAsync().awaitRunning();
        val creationFutures = new ArrayList<CompletableFuture<Void>>();
        for (int i = 0; i < SEGMENT_COUNT; i++) {
            String segmentName = getSegmentName(i);
            segmentNames.add(segmentName);
            creationFutures.add(container.createStreamSegment(segmentName, getSegmentType(segmentName), null, TIMEOUT));
        }
        // Wait for the segments to be created first.
        Futures.allOf(creationFutures).join();
        val opFutures = new ArrayList<CompletableFuture<Long>>();
        for (int i = 0; i < APPENDS_PER_SEGMENT / 2; i++) {
            for (String segmentName : segmentNames) {
                RefCountByteArraySegment appendData = getAppendData(segmentName, i);
                opFutures.add(container.append(segmentName, appendData, null, TIMEOUT));
                lengths.put(segmentName, lengths.getOrDefault(segmentName, 0L) + appendData.getLength());
                recordAppend(segmentName, appendData, segmentContents, null);
            }
        }
        Futures.allOf(opFutures).join();
        // Disable the DurableDataLog.
        dataLog.get().disable();
    }
    // Start in "Offline" mode, verify operations cannot execute and then shut down - make sure we can shut down an offline container.
    try (val container = containerFactory.createStreamSegmentContainer(CONTAINER_ID)) {
        container.startAsync().awaitRunning();
        Assert.assertTrue("Expecting Segment Container to be offline.", container.isOffline());
        AssertExtensions.assertSuppliedFutureThrows("append() worked in offline mode.", () -> container.append("foo", new ByteArraySegment(new byte[1]), null, TIMEOUT), ex -> ex instanceof ContainerOfflineException);
        AssertExtensions.assertSuppliedFutureThrows("getStreamSegmentInfo() worked in offline mode.", () -> container.getStreamSegmentInfo("foo", TIMEOUT), ex -> ex instanceof ContainerOfflineException);
        AssertExtensions.assertSuppliedFutureThrows("read() worked in offline mode.", () -> container.read("foo", 0, 1, TIMEOUT), ex -> ex instanceof ContainerOfflineException);
        container.stopAsync().awaitTerminated();
    }
    // Start in "Offline" mode and verify we can resume a normal startup.
    try (val container = containerFactory.createStreamSegmentContainer(CONTAINER_ID)) {
        container.startAsync().awaitRunning();
        Assert.assertTrue("Expecting Segment Container to be offline.", container.isOffline());
        dataLog.get().enable();
        // Wait for the DurableLog to become online.
        durableLog.get().awaitOnline().get(DEFAULT_DURABLE_LOG_CONFIG.getStartRetryDelay().toMillis() * 100, TimeUnit.MILLISECONDS);
        // Verify we can execute regular operations now.
        ArrayList<CompletableFuture<Void>> opFutures = new ArrayList<>();
        for (int i = 0; i < APPENDS_PER_SEGMENT / 2; i++) {
            for (String segmentName : segmentNames) {
                RefCountByteArraySegment appendData = getAppendData(segmentName, i);
                opFutures.add(Futures.toVoid(container.append(segmentName, appendData, null, TIMEOUT)));
                lengths.put(segmentName, lengths.getOrDefault(segmentName, 0L) + appendData.getLength());
                recordAppend(segmentName, appendData, segmentContents, null);
            }
        }
        Futures.allOf(opFutures).join();
        // Verify all operations arrived in Storage.
        ArrayList<CompletableFuture<Void>> segmentsCompletion = new ArrayList<>();
        for (String segmentName : segmentNames) {
            SegmentProperties sp = container.getStreamSegmentInfo(segmentName, TIMEOUT).join();
            segmentsCompletion.add(waitForSegmentInStorage(sp, context));
        }
        Futures.allOf(segmentsCompletion).join();
        container.stopAsync().awaitTerminated();
    }
}
Also used : ByteArraySegment(io.pravega.common.util.ByteArraySegment) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap) ContainerOfflineException(io.pravega.segmentstore.server.ContainerOfflineException) ArrayList(java.util.ArrayList) OperationLog(io.pravega.segmentstore.server.OperationLog) Cleanup(lombok.Cleanup) DurableLogFactory(io.pravega.segmentstore.server.logs.DurableLogFactory) CompletableFuture(java.util.concurrent.CompletableFuture) lombok.val(lombok.val) DurableDataLog(io.pravega.segmentstore.storage.DurableDataLog) AtomicReference(java.util.concurrent.atomic.AtomicReference) ByteArrayOutputStream(java.io.ByteArrayOutputStream) AtomicLong(java.util.concurrent.atomic.AtomicLong) TestDurableDataLogFactory(io.pravega.segmentstore.server.TestDurableDataLogFactory) SegmentProperties(io.pravega.segmentstore.contracts.SegmentProperties) Test(org.junit.Test)

Aggregations

DurableDataLog (io.pravega.segmentstore.storage.DurableDataLog)16 Cleanup (lombok.Cleanup)10 lombok.val (lombok.val)10 Test (org.junit.Test)10 ArrayList (java.util.ArrayList)7 CompletableFuture (java.util.concurrent.CompletableFuture)7 ObjectClosedException (io.pravega.common.ObjectClosedException)6 DurableDataLogException (io.pravega.segmentstore.storage.DurableDataLogException)6 IOException (java.io.IOException)6 ByteArraySegment (io.pravega.common.util.ByteArraySegment)5 Operation (io.pravega.segmentstore.server.logs.operations.Operation)5 LogAddress (io.pravega.segmentstore.storage.LogAddress)5 Duration (java.time.Duration)5 HashMap (java.util.HashMap)5 SegmentProperties (io.pravega.segmentstore.contracts.SegmentProperties)4 StreamSegmentAppendOperation (io.pravega.segmentstore.server.logs.operations.StreamSegmentAppendOperation)4 ReadIndexConfig (io.pravega.segmentstore.server.reading.ReadIndexConfig)4 BookKeeperLogFactory (io.pravega.segmentstore.storage.impl.bookkeeper.BookKeeperLogFactory)4 List (java.util.List)4 CancellationException (java.util.concurrent.CancellationException)4