Search in sources :

Example 1 with UnexpectedException

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

the class BKLogHandler method readLogSegmentsFromStore.

protected void readLogSegmentsFromStore(final Versioned<List<String>> logSegmentNames, final Comparator<LogSegmentMetadata> comparator, final LogSegmentFilter segmentFilter, final CompletableFuture<Versioned<List<LogSegmentMetadata>>> readResult) {
    Set<String> segmentsReceived = new HashSet<String>();
    segmentsReceived.addAll(segmentFilter.filter(logSegmentNames.getValue()));
    Set<String> segmentsAdded;
    final Set<String> removedSegments = Collections.synchronizedSet(new HashSet<String>());
    final Map<String, LogSegmentMetadata> addedSegments = Collections.synchronizedMap(new HashMap<String, LogSegmentMetadata>());
    Pair<Set<String>, Set<String>> segmentChanges = logSegmentCache.diff(segmentsReceived);
    segmentsAdded = segmentChanges.getLeft();
    removedSegments.addAll(segmentChanges.getRight());
    if (segmentsAdded.isEmpty()) {
        if (LOG.isTraceEnabled()) {
            LOG.trace("No segments added for {}.", getFullyQualifiedName());
        }
        // update the cache before #getCachedLogSegments to return
        updateLogSegmentCache(removedSegments, addedSegments);
        List<LogSegmentMetadata> segmentList;
        try {
            segmentList = getCachedLogSegments(comparator);
        } catch (UnexpectedException e) {
            readResult.completeExceptionally(e);
            return;
        }
        readResult.complete(new Versioned<List<LogSegmentMetadata>>(segmentList, logSegmentNames.getVersion()));
        return;
    }
    final AtomicInteger numChildren = new AtomicInteger(segmentsAdded.size());
    final AtomicInteger numFailures = new AtomicInteger(0);
    for (final String segment : segmentsAdded) {
        String logSegmentPath = logMetadata.getLogSegmentPath(segment);
        LogSegmentMetadata cachedSegment = metadataCache.get(logSegmentPath);
        if (null != cachedSegment) {
            addedSegments.put(segment, cachedSegment);
            completeReadLogSegmentsFromStore(removedSegments, addedSegments, comparator, readResult, logSegmentNames.getVersion(), numChildren, numFailures);
            continue;
        }
        metadataStore.getLogSegment(logSegmentPath).whenComplete(new FutureEventListener<LogSegmentMetadata>() {

            @Override
            public void onSuccess(LogSegmentMetadata result) {
                addedSegments.put(segment, result);
                complete();
            }

            @Override
            public void onFailure(Throwable cause) {
                // 2. In progress segment has been completed => inprogress ZNode does not exist
                if (cause instanceof LogSegmentNotFoundException) {
                    removedSegments.add(segment);
                    complete();
                } else {
                    // fail fast
                    if (1 == numFailures.incrementAndGet()) {
                        readResult.completeExceptionally(cause);
                        return;
                    }
                }
            }

            private void complete() {
                completeReadLogSegmentsFromStore(removedSegments, addedSegments, comparator, readResult, logSegmentNames.getVersion(), numChildren, numFailures);
            }
        });
    }
}
Also used : UnexpectedException(org.apache.distributedlog.exceptions.UnexpectedException) HashSet(java.util.HashSet) Set(java.util.Set) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) List(java.util.List) LogSegmentNotFoundException(org.apache.distributedlog.exceptions.LogSegmentNotFoundException) HashSet(java.util.HashSet)

Example 2 with UnexpectedException

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

the class ZKDistributedLock method asyncAcquire.

/**
 * Asynchronously acquire the lock. Technically the try phase of this operation--which adds us to the waiter
 * list--is executed synchronously, but the lock wait itself doesn't block.
 */
@Override
public synchronized CompletableFuture<ZKDistributedLock> asyncAcquire() {
    if (null != lockAcquireFuture) {
        return FutureUtils.exception(new UnexpectedException("Someone is already acquiring/acquired lock " + lockPath));
    }
    final CompletableFuture<ZKDistributedLock> promise = FutureUtils.createFuture();
    promise.whenComplete((zkDistributedLock, throwable) -> {
        if (null == throwable || !(throwable instanceof CancellationException)) {
            return;
        }
        lockStateExecutor.executeOrdered(lockPath, () -> asyncClose());
    });
    final Stopwatch stopwatch = Stopwatch.createStarted();
    promise.whenComplete(new FutureEventListener<ZKDistributedLock>() {

        @Override
        public void onSuccess(ZKDistributedLock lock) {
            acquireStats.registerSuccessfulEvent(stopwatch.stop().elapsed(TimeUnit.MICROSECONDS), TimeUnit.MICROSECONDS);
        }

        @Override
        public void onFailure(Throwable cause) {
            acquireStats.registerFailedEvent(stopwatch.stop().elapsed(TimeUnit.MICROSECONDS), TimeUnit.MICROSECONDS);
            // release the lock if fail to acquire
            asyncClose();
        }
    });
    this.lockAcquireFuture = promise;
    lockStateExecutor.executeOrdered(lockPath, () -> doAsyncAcquireWithSemaphore(promise, lockTimeout));
    return promise;
}
Also used : UnexpectedException(org.apache.distributedlog.exceptions.UnexpectedException) CancellationException(java.util.concurrent.CancellationException) Stopwatch(com.google.common.base.Stopwatch)

Example 3 with UnexpectedException

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

the class FederatedZKLogMetadataStore method createSubNamespace.

CompletableFuture<URI> createSubNamespace() {
    final CompletableFuture<URI> promise = new CompletableFuture<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.complete(newUri);
                    } catch (UnexpectedException ue) {
                        promise.completeExceptionally(ue);
                    } catch (URISyntaxException e) {
                        promise.completeExceptionally(new UnexpectedException("Invalid namespace " + name + " is created."));
                    }
                } else {
                    promise.completeExceptionally(KeeperException.create(Code.get(rc)));
                }
            }
        }, null);
    } catch (ZooKeeperClient.ZooKeeperConnectionException e) {
        promise.completeExceptionally(e);
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
        promise.completeExceptionally(e);
    }
    return promise;
}
Also used : UnexpectedException(org.apache.distributedlog.exceptions.UnexpectedException) AsyncCallback(org.apache.zookeeper.AsyncCallback) URISyntaxException(java.net.URISyntaxException) URI(java.net.URI) CompletableFuture(java.util.concurrent.CompletableFuture) ZooKeeperClient(org.apache.distributedlog.ZooKeeperClient)

Example 4 with UnexpectedException

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

the class FederatedZKLogMetadataStore method fetchLogLocation.

private CompletableFuture<Optional<URI>> fetchLogLocation(final String logName) {
    final CompletableFuture<Optional<URI>> fetchPromise = new CompletableFuture<Optional<URI>>();
    Set<URI> uris = subNamespaces.keySet();
    List<CompletableFuture<Optional<URI>>> fetchFutures = Lists.newArrayListWithExpectedSize(uris.size());
    for (URI uri : uris) {
        fetchFutures.add(fetchLogLocation(uri, logName));
    }
    FutureUtils.collect(fetchFutures).whenComplete(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.completeExceptionally(new UnexpectedException("Log " + logName + " is found in multiple sub namespaces : " + result.get() + " & " + fetchResult.get()));
                        return;
                    }
                } else {
                    result = fetchResult;
                }
            }
            fetchPromise.complete(result);
        }

        @Override
        public void onFailure(Throwable cause) {
            fetchPromise.completeExceptionally(cause);
        }
    });
    return fetchPromise;
}
Also used : UnexpectedException(org.apache.distributedlog.exceptions.UnexpectedException) Optional(com.google.common.base.Optional) URI(java.net.URI) CompletableFuture(java.util.concurrent.CompletableFuture) List(java.util.List)

Example 5 with UnexpectedException

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

the class ZKSessionLock method processLockWaiters.

/**
 * Check Lock Owner Phase 2 : check all lock waiters to get current owner and wait for ownership if necessary.
 *
 * @param lockWatcher
 *          lock watcher.
 * @param wait
 *          whether to wait for ownership.
 * @param getChildrenRc
 *          result of getting all lock waiters
 * @param children
 *          current lock waiters.
 * @param promise
 *          promise to satisfy with current lock owner.
 */
private void processLockWaiters(final LockWatcher lockWatcher, final boolean wait, final int getChildrenRc, final List<String> children, final CompletableFuture<String> promise) {
    executeLockAction(lockWatcher.epoch, new LockAction() {

        @Override
        public void execute() {
            if (!lockState.inState(State.PREPARED)) {
                // e.g. lock closed or session expired after prepared
                promise.completeExceptionally(new LockStateChangedException(lockPath, lockId, State.PREPARED, lockState.getState()));
                return;
            }
            if (KeeperException.Code.OK.intValue() != getChildrenRc) {
                promise.completeExceptionally(KeeperException.create(KeeperException.Code.get(getChildrenRc)));
                return;
            }
            if (children.isEmpty()) {
                LOG.error("Error, member list is empty for lock {}.", lockPath);
                promise.completeExceptionally(new UnexpectedException("Empty member list for lock " + lockPath));
                return;
            }
            // sort the children
            Collections.sort(children, MEMBER_COMPARATOR);
            final String cid = currentId;
            final int memberIndex = children.indexOf(cid);
            if (LOG.isDebugEnabled()) {
                LOG.debug("{} is the number {} member in the list.", cid, memberIndex);
            }
            // If we hold the lock
            if (memberIndex == 0) {
                LOG.info("{} acquired the lock {}.", cid, lockPath);
                claimOwnership(lockWatcher.epoch);
                promise.complete(cid);
            } else if (memberIndex > 0) {
                // we are in the member list but we didn't hold the lock
                // get ownership of current owner
                asyncParseClientID(zk, lockPath, children.get(0)).whenComplete(new FutureEventListener<Pair<String, Long>>() {

                    @Override
                    public void onSuccess(Pair<String, Long> currentOwner) {
                        watchLockOwner(lockWatcher, wait, cid, children.get(memberIndex - 1), children.get(0), currentOwner, promise);
                    }

                    @Override
                    public void onFailure(final Throwable cause) {
                        // ensure promise is satisfied in lock thread
                        executeLockAction(lockWatcher.epoch, new LockAction() {

                            @Override
                            public void execute() {
                                promise.completeExceptionally(cause);
                            }

                            @Override
                            public String getActionName() {
                                return "handleFailureOnParseClientID(lockPath=" + lockPath + ")";
                            }
                        }, promise);
                    }
                });
            } else {
                LOG.error("Member {} doesn't exist in the members list {} for lock {}.", new Object[] { cid, children, lockPath });
                promise.completeExceptionally(new UnexpectedException("Member " + cid + " doesn't exist in member list " + children + " for lock " + lockPath));
            }
        }

        @Override
        public String getActionName() {
            return "processLockWaiters(rc=" + getChildrenRc + ", waiters=" + children + ")";
        }
    }, promise);
}
Also used : UnexpectedException(org.apache.distributedlog.exceptions.UnexpectedException) Pair(org.apache.commons.lang3.tuple.Pair)

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