use of org.apache.bookkeeper.common.concurrent.FutureEventListener in project bookkeeper by apache.
the class ReadUtils method getLogRecordNotLessThanTxIdFromEntries.
/**
* Find the log record whose transaction id is not less than provided <code>transactionId</code> from
* entries between <code>startEntryId</code> and <code>endEntryId</code>.
*
* @param logName
* name of the log
* @param segment
* log segment
* @param transactionId
* provided transaction id to search
* @param executorService
* executor service
* @param reader
* log segment random access reader
* @param entriesToSearch
* list of entries to search
* @param nWays
* how many entries to search in parallel
* @param prevFoundRecord
* the log record found in previous search
* @param promise
* promise to satisfy the result
*/
private static void getLogRecordNotLessThanTxIdFromEntries(final String logName, final LogSegmentMetadata segment, final long transactionId, final ExecutorService executorService, final LogSegmentRandomAccessEntryReader reader, final List<Long> entriesToSearch, final int nWays, final Optional<LogRecordWithDLSN> prevFoundRecord, final CompletableFuture<Optional<LogRecordWithDLSN>> promise) {
final List<CompletableFuture<LogRecordWithDLSN>> searchResults = Lists.newArrayListWithExpectedSize(entriesToSearch.size());
for (Long entryId : entriesToSearch) {
LogRecordSelector selector = new FirstTxIdNotLessThanSelector(transactionId);
CompletableFuture<LogRecordWithDLSN> searchResult = asyncReadRecordFromEntries(logName, reader, segment, executorService, new SingleEntryScanContext(entryId), selector);
searchResults.add(searchResult);
}
FutureEventListener<List<LogRecordWithDLSN>> processSearchResultsListener = new FutureEventListener<List<LogRecordWithDLSN>>() {
@Override
public void onSuccess(List<LogRecordWithDLSN> resultList) {
processSearchResults(logName, segment, transactionId, executorService, reader, resultList, nWays, prevFoundRecord, promise);
}
@Override
public void onFailure(Throwable cause) {
promise.completeExceptionally(cause);
}
};
FutureUtils.collect(searchResults).whenCompleteAsync(processSearchResultsListener, executorService);
}
use of org.apache.bookkeeper.common.concurrent.FutureEventListener in project bookkeeper by apache.
the class LedgerAllocatorPool method tryObtain.
@Override
public CompletableFuture<LedgerHandle> tryObtain(final Transaction<Object> txn, final Transaction.OpListener<LedgerHandle> listener) {
final SimpleLedgerAllocator allocator;
synchronized (this) {
if (allocatingList.isEmpty()) {
return FutureUtils.exception(new IOException("No ledger allocator available under " + poolPath + "."));
} else {
allocator = allocatingList.removeFirst();
}
}
final CompletableFuture<LedgerHandle> tryObtainPromise = new CompletableFuture<LedgerHandle>();
final FutureEventListener<LedgerHandle> tryObtainListener = new FutureEventListener<LedgerHandle>() {
@Override
public void onSuccess(LedgerHandle lh) {
synchronized (LedgerAllocatorPool.this) {
obtainMap.put(lh, allocator);
reverseObtainMap.put(allocator, lh);
tryObtainPromise.complete(lh);
}
}
@Override
public void onFailure(Throwable cause) {
try {
rescueAllocator(allocator);
} catch (IOException ioe) {
logger.info("Failed to rescue allocator {}", allocator.allocatePath, ioe);
}
tryObtainPromise.completeExceptionally(cause);
}
};
allocator.tryObtain(txn, new Transaction.OpListener<LedgerHandle>() {
@Override
public void onCommit(LedgerHandle lh) {
confirmObtain(allocator);
listener.onCommit(lh);
}
@Override
public void onAbort(Throwable t) {
abortObtain(allocator);
listener.onAbort(t);
}
}).whenComplete(tryObtainListener);
return tryObtainPromise;
}
use of org.apache.bookkeeper.common.concurrent.FutureEventListener in project bookkeeper by apache.
the class SimpleLedgerAllocator method cleanupAndClose.
private void cleanupAndClose(final CompletableFuture<Void> closePromise) {
LOG.info("Closing ledger allocator on {}.", allocatePath);
final ZKTransaction txn = new ZKTransaction(zkc);
// try obtain ledger handle
tryObtain(txn, new OpListener<LedgerHandle>() {
@Override
public void onCommit(LedgerHandle r) {
// no-op
complete();
}
@Override
public void onAbort(Throwable t) {
// no-op
complete();
}
private void complete() {
closePromise.complete(null);
LOG.info("Closed ledger allocator on {}.", allocatePath);
}
}).whenComplete(new FutureEventListener<LedgerHandle>() {
@Override
public void onSuccess(LedgerHandle lh) {
// try obtain succeed
// if we could obtain the ledger handle, we have the responsibility to close it
deleteLedger(lh.getId());
// wait for deletion to be completed
List<CompletableFuture<Void>> outstandingDeletions;
synchronized (ledgerDeletions) {
outstandingDeletions = Lists.newArrayList(ledgerDeletions);
}
FutureUtils.collect(outstandingDeletions).whenComplete(new FutureEventListener<List<Void>>() {
@Override
public void onSuccess(List<Void> values) {
txn.execute();
}
@Override
public void onFailure(Throwable cause) {
LOG.debug("Fail to obtain the allocated ledger handle when closing the allocator : ", cause);
closePromise.complete(null);
}
});
}
@Override
public void onFailure(Throwable cause) {
LOG.debug("Fail to obtain the allocated ledger handle when closing the allocator : ", cause);
closePromise.complete(null);
}
});
}
use of org.apache.bookkeeper.common.concurrent.FutureEventListener in project bookkeeper by apache.
the class ZKAccessControlManager method fetchAccessControlEntries.
private void fetchAccessControlEntries(final CompletableFuture<Void> promise) {
try {
zkc.get().getChildren(zkRootPath, this, new AsyncCallback.Children2Callback() {
@Override
public void processResult(int rc, String path, Object ctx, List<String> children, Stat stat) {
if (KeeperException.Code.OK.intValue() != rc) {
promise.completeExceptionally(KeeperException.create(KeeperException.Code.get(rc)));
return;
}
Set<String> streamsReceived = new HashSet<String>();
streamsReceived.addAll(children);
Set<String> streamsCached = streamEntries.keySet();
Set<String> streamsRemoved = Sets.difference(streamsCached, streamsReceived).immutableCopy();
for (String s : streamsRemoved) {
ZKAccessControl accessControl = streamEntries.remove(s);
if (null != accessControl) {
logger.info("Removed Access Control Entry for stream {} : {}", s, accessControl.getAccessControlEntry());
}
}
if (streamsReceived.isEmpty()) {
promise.complete(null);
return;
}
final AtomicInteger numPendings = new AtomicInteger(streamsReceived.size());
final AtomicInteger numFailures = new AtomicInteger(0);
for (String s : streamsReceived) {
final String streamName = s;
ZKAccessControl.read(zkc, zkRootPath + "/" + streamName, null).whenComplete(new FutureEventListener<ZKAccessControl>() {
@Override
public void onSuccess(ZKAccessControl accessControl) {
streamEntries.put(streamName, accessControl);
logger.info("Added overrided access control for stream {} : {}", streamName, accessControl.getAccessControlEntry());
complete();
}
@Override
public void onFailure(Throwable cause) {
if (cause instanceof KeeperException.NoNodeException) {
streamEntries.remove(streamName);
} else if (cause instanceof ZKAccessControl.CorruptedAccessControlException) {
logger.warn("Access control is corrupted for stream {} @ {},skipped it ...", new Object[] { streamName, zkRootPath, cause });
streamEntries.remove(streamName);
} else {
if (1 == numFailures.incrementAndGet()) {
promise.completeExceptionally(cause);
}
}
complete();
}
private void complete() {
if (0 == numPendings.decrementAndGet() && numFailures.get() == 0) {
promise.complete(null);
}
}
});
}
}
}, null);
} catch (ZooKeeperClient.ZooKeeperConnectionException e) {
promise.completeExceptionally(e);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
promise.completeExceptionally(e);
}
}
use of org.apache.bookkeeper.common.concurrent.FutureEventListener in project bookkeeper by apache.
the class TestDistributedLock method testAsyncAcquireBasics.
@Test(timeout = 60000)
public void testAsyncAcquireBasics() throws Exception {
TestLockFactory locks = new TestLockFactory(runtime.getMethodName(), zkc, lockStateExecutor);
int count = 3;
ArrayList<CompletableFuture<ZKDistributedLock>> results = new ArrayList<CompletableFuture<ZKDistributedLock>>(count);
ZKDistributedLock[] lockArray = new ZKDistributedLock[count];
final CountDownLatch[] latches = new CountDownLatch[count];
// the future.
for (int i = 0; i < count; i++) {
latches[i] = new CountDownLatch(1);
lockArray[i] = locks.createLock(i, zkc);
final int index = i;
results.add(lockArray[i].asyncAcquire().whenComplete(new FutureEventListener<ZKDistributedLock>() {
@Override
public void onSuccess(ZKDistributedLock lock) {
latches[index].countDown();
}
@Override
public void onFailure(Throwable cause) {
fail("unexpected failure " + cause);
}
}));
}
// acquired).
for (int i = 0; i < count; i++) {
latches[i].await();
assertLatchesSet(latches, i + 1);
Utils.ioResult(results.get(i));
Utils.ioResult(lockArray[i].asyncClose());
}
}
Aggregations