Search in sources :

Example 11 with UnexpectedException

use of com.twitter.distributedlog.exceptions.UnexpectedException in project distributedlog by twitter.

the class BKLogWriteHandler method doCompleteAndCloseLogSegment.

protected void doCompleteAndCloseLogSegment(final String inprogressZnodeName, long logSegmentSeqNo, long ledgerId, long firstTxId, long lastTxId, int recordCount, long lastEntryId, long lastSlotId, final Promise<LogSegmentMetadata> promise) {
    try {
        lock.checkOwnershipAndReacquire();
    } catch (IOException ioe) {
        FutureUtils.setException(promise, ioe);
        return;
    }
    LOG.debug("Completing and Closing Log Segment {} {}", firstTxId, lastTxId);
    final String inprogressZnodePath = inprogressZNode(inprogressZnodeName);
    LogSegmentMetadata inprogressLogSegment = readLogSegmentFromCache(inprogressZnodeName);
    // validate log segment
    if (inprogressLogSegment.getLedgerId() != ledgerId) {
        FutureUtils.setException(promise, new IOException("Active ledger has different ID to inprogress. " + inprogressLogSegment.getLedgerId() + " found, " + ledgerId + " expected"));
        return;
    }
    // validate the transaction id
    if (inprogressLogSegment.getFirstTxId() != firstTxId) {
        FutureUtils.setException(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.setException(promise, new UnexpectedException("Didn't find matched inprogress log segments when completing inprogress " + inprogressLogSegment));
                return;
            }
            long leastInprogressLSSN = inprogressLSSNs.getFirst();
            // it should also be same as the least inprogress log segment sequence number tracked in {@link inprogressLSSNs}
            if ((inprogressLogSegment.getLogSegmentSequenceNumber() != logSegmentSeqNo) || (leastInprogressLSSN != logSegmentSeqNo)) {
                FutureUtils.setException(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, inprogressZnodePath });
    } else {
        LOG.warn("Unexpected max ledger sequence number {} found while completing log segment {} for {}", new Object[] { maxLogSegmentSequenceNo.getSequenceNumber(), logSegmentSeqNo, getFullyQualifiedName() });
        if (validateLogSegmentSequenceNumber) {
            FutureUtils.setException(promise, new DLIllegalStateException("Unexpected max log segment sequence number " + maxLogSegmentSequenceNo.getSequenceNumber() + " for " + getFullyQualifiedName() + ", expected " + (logSegmentSeqNo - 1)));
            return;
        }
    }
    // Prepare the completion
    final String nameForCompletedLedger = completedLedgerZNodeName(firstTxId, lastTxId, logSegmentSeqNo);
    final String pathForCompletedLedger = completedLedgerZNode(firstTxId, lastTxId, logSegmentSeqNo);
    long startSequenceId;
    try {
        startSequenceId = computeStartSequenceId(inprogressLogSegment);
    } catch (IOException ioe) {
        FutureUtils.setException(promise, ioe);
        return;
    }
    // write completed ledger znode
    final LogSegmentMetadata completedLogSegment = inprogressLogSegment.completeLogSegment(pathForCompletedLedger, lastTxId, recordCount, lastEntryId, lastSlotId, startSequenceId);
    setLastLedgerRollingTimeMillis(completedLogSegment.getCompletionTime());
    // prepare the transaction
    ZKTransaction txn = new ZKTransaction(zooKeeperClient);
    // create completed log segment
    writeLogSegment(txn, zooKeeperClient.getDefaultACL(), nameForCompletedLedger, completedLogSegment, pathForCompletedLedger);
    // delete inprogress log segment
    deleteLogSegment(txn, inprogressZnodeName, inprogressZnodePath);
    // 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().addEventListener(FutureEventListenerRunnable.of(new FutureEventListener<Void>() {

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

        @Override
        public void onFailure(Throwable cause) {
            FutureUtils.setException(promise, cause);
        }
    }, scheduler));
}
Also used : UnexpectedException(com.twitter.distributedlog.exceptions.UnexpectedException) DLIllegalStateException(com.twitter.distributedlog.exceptions.DLIllegalStateException) FutureEventListener(com.twitter.util.FutureEventListener) IOException(java.io.IOException) ZKTransaction(com.twitter.distributedlog.zk.ZKTransaction)

Example 12 with UnexpectedException

use of com.twitter.distributedlog.exceptions.UnexpectedException in project distributedlog by twitter.

the class FederatedZKLogMetadataStore method fetchLogLocation.

private Future<Optional<URI>> fetchLogLocation(final String logName) {
    final Promise<Optional<URI>> fetchPromise = new Promise<Optional<URI>>();
    Set<URI> uris = subNamespaces.keySet();
    List<Future<Optional<URI>>> fetchFutures = Lists.newArrayListWithExpectedSize(uris.size());
    for (URI uri : uris) {
        fetchFutures.add(fetchLogLocation(uri, logName));
    }
    Future.collect(fetchFutures).addEventListener(new FutureEventListener<List<Optional<URI>>>() {

        @Override
        public void onSuccess(List<Optional<URI>> fetchResults) {
            Optional<URI> result = Optional.absent();
            for (Optional<URI> fetchResult : fetchResults) {
                if (result.isPresent()) {
                    if (fetchResult.isPresent()) {
                        logger.error("Log {} is found in multiple sub namespaces : {} & {}.", new Object[] { logName, result.get(), fetchResult.get() });
                        duplicatedLogName.compareAndSet(null, logName);
                        duplicatedLogFound.set(true);
                        fetchPromise.setException(new UnexpectedException("Log " + logName + " is found in multiple sub namespaces : " + result.get() + " & " + fetchResult.get()));
                        return;
                    }
                } else {
                    result = fetchResult;
                }
            }
            fetchPromise.setValue(result);
        }

        @Override
        public void onFailure(Throwable cause) {
            fetchPromise.setException(cause);
        }
    });
    return fetchPromise;
}
Also used : UnexpectedException(com.twitter.distributedlog.exceptions.UnexpectedException) Optional(com.google.common.base.Optional) URI(java.net.URI) Promise(com.twitter.util.Promise) Future(com.twitter.util.Future) List(java.util.List)

Example 13 with UnexpectedException

use of com.twitter.distributedlog.exceptions.UnexpectedException in project distributedlog by twitter.

the class FederatedZKLogMetadataStore method createSubNamespace.

Future<URI> createSubNamespace() {
    final Promise<URI> promise = new Promise<URI>();
    final String nsPath = namespace.getPath() + "/" + ZNODE_SUB_NAMESPACES + "/" + SUB_NAMESPACE_PREFIX;
    try {
        zkc.get().create(nsPath, new byte[0], zkc.getDefaultACL(), CreateMode.PERSISTENT_SEQUENTIAL, new AsyncCallback.StringCallback() {

            @Override
            public void processResult(int rc, String path, Object ctx, String name) {
                if (Code.OK.intValue() == rc) {
                    try {
                        URI newUri = getSubNamespaceURI(getNamespaceFromZkPath(name));
                        logger.info("Created sub namespace {}", newUri);
                        promise.setValue(newUri);
                    } catch (UnexpectedException ue) {
                        promise.setException(ue);
                    } catch (URISyntaxException e) {
                        promise.setException(new UnexpectedException("Invalid namespace " + name + " is created."));
                    }
                } else {
                    promise.setException(KeeperException.create(Code.get(rc)));
                }
            }
        }, null);
    } catch (ZooKeeperClient.ZooKeeperConnectionException e) {
        promise.setException(e);
    } catch (InterruptedException e) {
        promise.setException(e);
    }
    return promise;
}
Also used : UnexpectedException(com.twitter.distributedlog.exceptions.UnexpectedException) AsyncCallback(org.apache.zookeeper.AsyncCallback) URISyntaxException(java.net.URISyntaxException) URI(java.net.URI) Promise(com.twitter.util.Promise) ZooKeeperClient(com.twitter.distributedlog.ZooKeeperClient)

Example 14 with UnexpectedException

use of com.twitter.distributedlog.exceptions.UnexpectedException in project distributedlog by twitter.

the class FederatedZKLogMetadataStore method findSubNamespaceToCreateLog.

private void findSubNamespaceToCreateLog(final String logName, final Set<URI> uris, final Promise<URI> createPromise) {
    final List<URI> uriList = Lists.newArrayListWithExpectedSize(uris.size());
    List<Future<Set<String>>> futureList = Lists.newArrayListWithExpectedSize(uris.size());
    for (URI uri : uris) {
        SubNamespace subNs = subNamespaces.get(uri);
        if (null == subNs) {
            createPromise.setException(new UnexpectedException("No sub namespace " + uri + " found"));
            return;
        }
        futureList.add(subNs.getLogs());
        uriList.add(uri);
    }
    Future.collect(futureList).addEventListener(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().addEventListener(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.setException(cause);
                }
            });
        }

        @Override
        public void onFailure(Throwable cause) {
            createPromise.setException(cause);
        }
    });
}
Also used : UnexpectedException(com.twitter.distributedlog.exceptions.UnexpectedException) Set(java.util.Set) URI(java.net.URI) Future(com.twitter.util.Future) List(java.util.List) FutureEventListener(com.twitter.util.FutureEventListener)

Aggregations

UnexpectedException (com.twitter.distributedlog.exceptions.UnexpectedException)14 URI (java.net.URI)5 Promise (com.twitter.util.Promise)4 FutureEventListener (com.twitter.util.FutureEventListener)3 List (java.util.List)3 Stopwatch (com.google.common.base.Stopwatch)2 Future (com.twitter.util.Future)2 IOException (java.io.IOException)2 Set (java.util.Set)2 Pair (org.apache.commons.lang3.tuple.Pair)2 AsyncCallback (org.apache.zookeeper.AsyncCallback)2 Test (org.junit.Test)2 BoxedUnit (scala.runtime.BoxedUnit)2 Optional (com.google.common.base.Optional)1 DistributedLogConfiguration (com.twitter.distributedlog.DistributedLogConfiguration)1 LogSegmentMetadata (com.twitter.distributedlog.LogSegmentMetadata)1 ZooKeeperClient (com.twitter.distributedlog.ZooKeeperClient)1 DLIllegalStateException (com.twitter.distributedlog.exceptions.DLIllegalStateException)1 DLInterruptedException (com.twitter.distributedlog.exceptions.DLInterruptedException)1 StreamUnavailableException (com.twitter.distributedlog.exceptions.StreamUnavailableException)1