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);
}
});
}
}
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;
}
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;
}
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;
}
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);
}
Aggregations