Search in sources :

Example 6 with UnexpectedException

use of org.apache.distributedlog.exceptions.UnexpectedException in project bookkeeper by apache.

the class BKLogWriteHandler method doCompleteAndCloseLogSegmentAfterLogSegmentListFetched.

private void doCompleteAndCloseLogSegmentAfterLogSegmentListFetched(final String inprogressZnodeName, long logSegmentSeqNo, long logSegmentId, long firstTxId, long lastTxId, int recordCount, long lastEntryId, long lastSlotId, final CompletableFuture<LogSegmentMetadata> promise) {
    try {
        lock.checkOwnershipAndReacquire();
    } catch (IOException ioe) {
        FutureUtils.completeExceptionally(promise, ioe);
        return;
    }
    LOG.debug("Completing and Closing Log Segment {} {}", firstTxId, lastTxId);
    LogSegmentMetadata inprogressLogSegment = readLogSegmentFromCache(inprogressZnodeName);
    // validate log segment
    if (inprogressLogSegment.getLogSegmentId() != logSegmentId) {
        FutureUtils.completeExceptionally(promise, new IOException("Active ledger has different ID to inprogress. " + inprogressLogSegment.getLogSegmentId() + " found, " + logSegmentId + " expected"));
        return;
    }
    // validate the transaction id
    if (inprogressLogSegment.getFirstTxId() != firstTxId) {
        FutureUtils.completeExceptionally(promise, new IOException("Transaction id not as expected, " + inprogressLogSegment.getFirstTxId() + " found, " + firstTxId + " expected"));
        return;
    }
    // validate the log sequence number
    if (validateLogSegmentSequenceNumber) {
        synchronized (inprogressLSSNs) {
            if (inprogressLSSNs.isEmpty()) {
                FutureUtils.completeExceptionally(promise, new UnexpectedException("Didn't find matched inprogress log segments when completing inprogress " + inprogressLogSegment));
                return;
            }
            long leastInprogressLSSN = inprogressLSSNs.getFirst();
            // tracked in {@link inprogressLSSNs}
            if ((inprogressLogSegment.getLogSegmentSequenceNumber() != logSegmentSeqNo) || (leastInprogressLSSN != logSegmentSeqNo)) {
                FutureUtils.completeExceptionally(promise, new UnexpectedException("Didn't find matched inprogress log segments when completing inprogress " + inprogressLogSegment));
                return;
            }
        }
    }
    // store max sequence number.
    long maxSeqNo = Math.max(logSegmentSeqNo, maxLogSegmentSequenceNo.getSequenceNumber());
    if (maxLogSegmentSequenceNo.getSequenceNumber() == logSegmentSeqNo || (maxLogSegmentSequenceNo.getSequenceNumber() == logSegmentSeqNo + 1)) {
        // ignore the case that a new inprogress log segment is pre-allocated
        // before completing current inprogress one
        LOG.info("Try storing max sequence number {} in completing {}.", new Object[] { logSegmentSeqNo, inprogressLogSegment.getZkPath() });
    } else {
        LOG.warn("Unexpected max ledger sequence number {} found while completing log segment {} for {}", new Object[] { maxLogSegmentSequenceNo.getSequenceNumber(), logSegmentSeqNo, getFullyQualifiedName() });
        if (validateLogSegmentSequenceNumber) {
            FutureUtils.completeExceptionally(promise, new DLIllegalStateException("Unexpected max log segment sequence number " + maxLogSegmentSequenceNo.getSequenceNumber() + " for " + getFullyQualifiedName() + ", expected " + (logSegmentSeqNo - 1)));
            return;
        }
    }
    // Prepare the completion
    final String pathForCompletedLedger = completedLedgerZNode(firstTxId, lastTxId, logSegmentSeqNo);
    long startSequenceId;
    try {
        startSequenceId = computeStartSequenceId(inprogressLogSegment);
    } catch (IOException ioe) {
        FutureUtils.completeExceptionally(promise, ioe);
        return;
    }
    // write completed ledger znode
    final LogSegmentMetadata completedLogSegment = inprogressLogSegment.completeLogSegment(pathForCompletedLedger, lastTxId, recordCount, lastEntryId, lastSlotId, startSequenceId);
    setLastLedgerRollingTimeMillis(completedLogSegment.getCompletionTime());
    // prepare the transaction
    Transaction<Object> txn = streamMetadataStore.newTransaction();
    // create completed log segment
    writeLogSegment(txn, completedLogSegment);
    // delete inprogress log segment
    deleteLogSegment(txn, inprogressLogSegment);
    // store max sequence number
    storeMaxSequenceNumber(txn, maxLogSegmentSequenceNo, maxSeqNo, false);
    // update max txn id.
    LOG.debug("Trying storing LastTxId in Finalize Path {} LastTxId {}", pathForCompletedLedger, lastTxId);
    storeMaxTxId(txn, maxTxId, lastTxId);
    txn.execute().whenCompleteAsync(new FutureEventListener<Void>() {

        @Override
        public void onSuccess(Void value) {
            LOG.info("Completed {} to {} for {} : {}", new Object[] { inprogressZnodeName, completedLogSegment.getSegmentName(), getFullyQualifiedName(), completedLogSegment });
            FutureUtils.complete(promise, completedLogSegment);
        }

        @Override
        public void onFailure(Throwable cause) {
            FutureUtils.completeExceptionally(promise, cause);
        }
    }, scheduler);
}
Also used : UnexpectedException(org.apache.distributedlog.exceptions.UnexpectedException) DLIllegalStateException(org.apache.distributedlog.exceptions.DLIllegalStateException) IOException(java.io.IOException)

Example 7 with UnexpectedException

use of org.apache.distributedlog.exceptions.UnexpectedException in project bookkeeper by apache.

the class TestFederatedZKLogMetadataStore method testDuplicatedLogs.

@Test(timeout = 60000)
public void testDuplicatedLogs() throws Exception {
    DistributedLogConfiguration conf = new DistributedLogConfiguration();
    conf.addConfiguration(baseConf);
    String logName = "test-log";
    Utils.ioResult(metadataStore.createLog(logName));
    URI subNs1 = Utils.ioResult(metadataStore.createSubNamespace());
    URI subNs2 = Utils.ioResult(metadataStore.createSubNamespace());
    String duplicatedLogName = "test-duplicated-logs";
    // Create same log in different sub namespaces
    metadataStore.createLogInNamespaceSync(subNs1, duplicatedLogName);
    metadataStore.createLogInNamespaceSync(subNs2, duplicatedLogName);
    try {
        Utils.ioResult(metadataStore.createLog("non-existent-log"));
        fail("should throw exception when duplicated log found");
    } catch (UnexpectedException ue) {
        // should throw unexpected exception
        assertTrue(metadataStore.duplicatedLogFound.get());
    }
    try {
        Utils.ioResult(metadataStore.getLogLocation(logName));
        fail("should throw exception when duplicated log found");
    } catch (UnexpectedException ue) {
        // should throw unexpected exception
        assertTrue(metadataStore.duplicatedLogFound.get());
    }
    try {
        Utils.ioResult(metadataStore.getLogLocation("non-existent-log"));
        fail("should throw exception when duplicated log found");
    } catch (UnexpectedException ue) {
        // should throw unexpected exception
        assertTrue(metadataStore.duplicatedLogFound.get());
    }
    try {
        Utils.ioResult(metadataStore.getLogLocation(duplicatedLogName));
        fail("should throw exception when duplicated log found");
    } catch (UnexpectedException ue) {
        // should throw unexpected exception
        assertTrue(metadataStore.duplicatedLogFound.get());
    }
    try {
        Utils.ioResult(metadataStore.getLogs(""));
        fail("should throw exception when duplicated log found");
    } catch (UnexpectedException ue) {
        // should throw unexpected exception
        assertTrue(metadataStore.duplicatedLogFound.get());
    }
}
Also used : DistributedLogConfiguration(org.apache.distributedlog.DistributedLogConfiguration) UnexpectedException(org.apache.distributedlog.exceptions.UnexpectedException) URI(java.net.URI) Test(org.junit.Test)

Example 8 with UnexpectedException

use of org.apache.distributedlog.exceptions.UnexpectedException in project bookkeeper by apache.

the class TestDistributedLogAdmin method testChangeSequenceNumber.

/**
 * {@link https://issues.apache.org/jira/browse/DL-44}.
 */
@DistributedLogAnnotations.FlakyTest
@Ignore
@Test(timeout = 60000)
@SuppressWarnings("deprecation")
public void testChangeSequenceNumber() throws Exception {
    DistributedLogConfiguration confLocal = new DistributedLogConfiguration();
    confLocal.addConfiguration(conf);
    confLocal.setLogSegmentSequenceNumberValidationEnabled(false);
    confLocal.setLogSegmentCacheEnabled(false);
    DistributedLogConfiguration readConf = new DistributedLogConfiguration();
    readConf.addConfiguration(conf);
    readConf.setLogSegmentCacheEnabled(false);
    readConf.setLogSegmentSequenceNumberValidationEnabled(true);
    URI uri = createDLMURI("/change-sequence-number");
    zooKeeperClient.get().create(uri.getPath(), new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
    Namespace namespace = NamespaceBuilder.newBuilder().conf(confLocal).uri(uri).build();
    Namespace readNamespace = NamespaceBuilder.newBuilder().conf(readConf).uri(uri).build();
    String streamName = "change-sequence-number";
    // create completed log segments
    DistributedLogManager dlm = namespace.openLog(streamName);
    DLMTestUtil.generateCompletedLogSegments(dlm, confLocal, 4, 10);
    DLMTestUtil.injectLogSegmentWithGivenLogSegmentSeqNo(dlm, confLocal, 5, 41, false, 10, true);
    dlm.close();
    // create a reader
    DistributedLogManager readDLM = readNamespace.openLog(streamName);
    AsyncLogReader reader = readDLM.getAsyncLogReader(DLSN.InitialDLSN);
    // read the records
    long expectedTxId = 1L;
    DLSN lastDLSN = DLSN.InitialDLSN;
    for (int i = 0; i < 4 * 10; i++) {
        LogRecordWithDLSN record = Utils.ioResult(reader.readNext());
        assertNotNull(record);
        DLMTestUtil.verifyLogRecord(record);
        assertEquals(expectedTxId, record.getTransactionId());
        expectedTxId++;
        lastDLSN = record.getDlsn();
    }
    LOG.info("Injecting bad log segment '3'");
    dlm = namespace.openLog(streamName);
    DLMTestUtil.injectLogSegmentWithGivenLogSegmentSeqNo(dlm, confLocal, 3L, 5 * 10 + 1, true, 10, false);
    LOG.info("Injected bad log segment '3'");
    // there isn't records should be read
    CompletableFuture<LogRecordWithDLSN> readFuture = reader.readNext();
    try {
        LogRecordWithDLSN record = Utils.ioResult(readFuture);
        fail("Should fail reading next record " + record + " when there is a corrupted log segment");
    } catch (UnexpectedException ue) {
    // expected
    }
    LOG.info("Dryrun fix inprogress segment that has lower sequence number");
    // Dryrun
    DistributedLogAdmin.fixInprogressSegmentWithLowerSequenceNumber(namespace, new DryrunLogSegmentMetadataStoreUpdater(confLocal, getLogSegmentMetadataStore(namespace)), streamName, false, false);
    try {
        reader = readDLM.getAsyncLogReader(lastDLSN);
        Utils.ioResult(reader.readNext());
        fail("Should fail reading next when there is a corrupted log segment");
    } catch (UnexpectedException ue) {
    // expected
    }
    LOG.info("Actual run fix inprogress segment that has lower sequence number");
    // Actual run
    DistributedLogAdmin.fixInprogressSegmentWithLowerSequenceNumber(namespace, LogSegmentMetadataStoreUpdater.createMetadataUpdater(confLocal, getLogSegmentMetadataStore(namespace)), streamName, false, false);
    // be able to read more after fix
    reader = readDLM.getAsyncLogReader(lastDLSN);
    // skip the first record
    Utils.ioResult(reader.readNext());
    readFuture = reader.readNext();
    expectedTxId = 51L;
    LogRecord record = Utils.ioResult(readFuture);
    assertNotNull(record);
    DLMTestUtil.verifyLogRecord(record);
    assertEquals(expectedTxId, record.getTransactionId());
    expectedTxId++;
    for (int i = 1; i < 10; i++) {
        record = Utils.ioResult(reader.readNext());
        assertNotNull(record);
        DLMTestUtil.verifyLogRecord(record);
        assertEquals(expectedTxId, record.getTransactionId());
        expectedTxId++;
    }
    Utils.close(reader);
    readDLM.close();
    dlm.close();
    namespace.close();
    readNamespace.close();
}
Also used : UnexpectedException(org.apache.distributedlog.exceptions.UnexpectedException) LogRecordWithDLSN(org.apache.distributedlog.LogRecordWithDLSN) DLSN(org.apache.distributedlog.DLSN) LogRecordWithDLSN(org.apache.distributedlog.LogRecordWithDLSN) AsyncLogReader(org.apache.distributedlog.api.AsyncLogReader) URI(java.net.URI) Namespace(org.apache.distributedlog.api.namespace.Namespace) DistributedLogConfiguration(org.apache.distributedlog.DistributedLogConfiguration) LogRecord(org.apache.distributedlog.LogRecord) DistributedLogManager(org.apache.distributedlog.api.DistributedLogManager) DryrunLogSegmentMetadataStoreUpdater(org.apache.distributedlog.metadata.DryrunLogSegmentMetadataStoreUpdater) Ignore(org.junit.Ignore) Test(org.junit.Test)

Example 9 with UnexpectedException

use of org.apache.distributedlog.exceptions.UnexpectedException in project bookkeeper by apache.

the class DLOutputStream method write.

private synchronized void write(ByteBuf buf) throws IOException {
    Throwable cause = exceptionUpdater.get(this);
    if (null != cause) {
        if (cause instanceof IOException) {
            throw (IOException) cause;
        } else {
            throw new UnexpectedException("Encountered unknown issue", cause);
        }
    }
    writePos += buf.readableBytes();
    LogRecord record = new LogRecord(writePos, buf);
    writer.write(record).whenComplete(new FutureEventListener<DLSN>() {

        @Override
        public void onSuccess(DLSN value) {
            synchronized (syncPos) {
                syncPos[0] = record.getTransactionId();
            }
        }

        @Override
        public void onFailure(Throwable cause) {
            exceptionUpdater.compareAndSet(DLOutputStream.this, null, cause);
        }
    });
}
Also used : UnexpectedException(org.apache.distributedlog.exceptions.UnexpectedException) DLSN(org.apache.distributedlog.DLSN) LogRecord(org.apache.distributedlog.LogRecord) IOException(java.io.IOException)

Example 10 with UnexpectedException

use of org.apache.distributedlog.exceptions.UnexpectedException in project bookkeeper by apache.

the class FederatedZKLogMetadataStore method findSubNamespaceToCreateLog.

private void findSubNamespaceToCreateLog(final String logName, final Set<URI> uris, final CompletableFuture<URI> createPromise) {
    final List<URI> uriList = Lists.newArrayListWithExpectedSize(uris.size());
    List<CompletableFuture<Set<String>>> futureList = Lists.newArrayListWithExpectedSize(uris.size());
    for (URI uri : uris) {
        SubNamespace subNs = subNamespaces.get(uri);
        if (null == subNs) {
            createPromise.completeExceptionally(new UnexpectedException("No sub namespace " + uri + " found"));
            return;
        }
        futureList.add(subNs.getLogs());
        uriList.add(uri);
    }
    FutureUtils.collect(futureList).whenComplete(new FutureEventListener<List<Set<String>>>() {

        @Override
        public void onSuccess(List<Set<String>> resultList) {
            for (int i = resultList.size() - 1; i >= 0; i--) {
                Set<String> logs = resultList.get(i);
                if (logs.size() < maxLogsPerSubnamespace) {
                    URI uri = uriList.get(i);
                    createLogInNamespace(uri, logName, createPromise);
                    return;
                }
            }
            // All sub namespaces are full
            createSubNamespace().whenComplete(new FutureEventListener<URI>() {

                @Override
                public void onSuccess(URI uri) {
                    // the new namespace will be propagated to the namespace cache by the namespace listener
                    // so we don't need to cache it here. we could go ahead to create the stream under this
                    // namespace, as we are using sequential znode. we are mostly the first guy who create
                    // the log under this namespace.
                    createLogInNamespace(uri, logName, createPromise);
                }

                @Override
                public void onFailure(Throwable cause) {
                    createPromise.completeExceptionally(cause);
                }
            });
        }

        @Override
        public void onFailure(Throwable cause) {
            createPromise.completeExceptionally(cause);
        }
    });
}
Also used : UnexpectedException(org.apache.distributedlog.exceptions.UnexpectedException) Set(java.util.Set) URI(java.net.URI) CompletableFuture(java.util.concurrent.CompletableFuture) List(java.util.List) FutureEventListener(org.apache.bookkeeper.common.concurrent.FutureEventListener)

Aggregations

UnexpectedException (org.apache.distributedlog.exceptions.UnexpectedException)14 URI (java.net.URI)6 List (java.util.List)3 CompletableFuture (java.util.concurrent.CompletableFuture)3 Test (org.junit.Test)3 IOException (java.io.IOException)2 Set (java.util.Set)2 CancellationException (java.util.concurrent.CancellationException)2 DLSN (org.apache.distributedlog.DLSN)2 DistributedLogConfiguration (org.apache.distributedlog.DistributedLogConfiguration)2 LogRecord (org.apache.distributedlog.LogRecord)2 AsyncLogReader (org.apache.distributedlog.api.AsyncLogReader)2 DistributedLogManager (org.apache.distributedlog.api.DistributedLogManager)2 Namespace (org.apache.distributedlog.api.namespace.Namespace)2 Optional (com.google.common.base.Optional)1 Stopwatch (com.google.common.base.Stopwatch)1 URISyntaxException (java.net.URISyntaxException)1 HashSet (java.util.HashSet)1 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)1 Function (java.util.function.Function)1