use of com.twitter.util.Promise in project distributedlog by twitter.
the class BKLogHandler method asyncGetLedgerListWithRetries.
protected Future<List<LogSegmentMetadata>> asyncGetLedgerListWithRetries(Comparator<LogSegmentMetadata> comparator, LogSegmentFilter segmentFilter, Watcher watcher) {
final Promise<List<LogSegmentMetadata>> promise = new Promise<List<LogSegmentMetadata>>();
asyncGetLedgerListWithRetries(comparator, segmentFilter, watcher, new GenericCallback<List<LogSegmentMetadata>>() {
@Override
public void operationComplete(int rc, List<LogSegmentMetadata> segments) {
if (KeeperException.Code.OK.intValue() == rc) {
promise.setValue(segments);
} else if (KeeperException.Code.NONODE.intValue() == rc) {
promise.setException(new LogNotFoundException("Log " + getFullyQualifiedName() + " not found"));
} else {
String errMsg = "ZK Exception " + rc + " reading ledger list for " + getFullyQualifiedName();
promise.setException(new ZKException(errMsg, KeeperException.Code.get(rc)));
}
}
});
return promise;
}
use of com.twitter.util.Promise in project distributedlog by twitter.
the class BKLogHandler method asyncForceGetLedgerList.
protected Future<List<LogSegmentMetadata>> asyncForceGetLedgerList(final Comparator<LogSegmentMetadata> comparator, final LogSegmentFilter segmentFilter, final boolean throwOnEmpty) {
final Promise<List<LogSegmentMetadata>> promise = new Promise<List<LogSegmentMetadata>>();
final Stopwatch stopwatch = Stopwatch.createStarted();
asyncGetLedgerListWithRetries(comparator, segmentFilter, null).addEventListener(new FutureEventListener<List<LogSegmentMetadata>>() {
@Override
public void onSuccess(List<LogSegmentMetadata> ledgers) {
forceGetListStat.registerSuccessfulEvent(stopwatch.stop().elapsed(TimeUnit.MICROSECONDS));
if (ledgers.isEmpty() && throwOnEmpty) {
promise.setException(new LogEmptyException("Log " + getFullyQualifiedName() + " is empty"));
} else {
promise.setValue(ledgers);
}
}
@Override
public void onFailure(Throwable cause) {
forceGetListStat.registerFailedEvent(stopwatch.stop().elapsed(TimeUnit.MICROSECONDS));
promise.setException(cause);
}
});
return promise;
}
use of com.twitter.util.Promise in project distributedlog by twitter.
the class BookKeeperClient method createLedger.
// Util functions
public Future<LedgerHandle> createLedger(int ensembleSize, int writeQuorumSize, int ackQuorumSize) {
BookKeeper bk;
try {
bk = get();
} catch (IOException ioe) {
return Future.exception(ioe);
}
final Promise<LedgerHandle> promise = new Promise<LedgerHandle>();
bk.asyncCreateLedger(ensembleSize, writeQuorumSize, ackQuorumSize, BookKeeper.DigestType.CRC32, passwd, new AsyncCallback.CreateCallback() {
@Override
public void createComplete(int rc, LedgerHandle lh, Object ctx) {
if (BKException.Code.OK == rc) {
promise.updateIfEmpty(new Return<LedgerHandle>(lh));
} else {
promise.updateIfEmpty(new Throw<LedgerHandle>(BKException.create(rc)));
}
}
}, null);
return promise;
}
use of com.twitter.util.Promise in project distributedlog by twitter.
the class LedgerHandleCache method asyncOpenLedger.
/**
* Open the log segment.
*
* @param metadata
* the log segment metadata
* @param fence
* whether to fence the log segment during open
* @return a future presenting the open result.
*/
public Future<LedgerDescriptor> asyncOpenLedger(LogSegmentMetadata metadata, boolean fence) {
final Stopwatch stopwatch = Stopwatch.createStarted();
final OpStatsLogger openStatsLogger = fence ? openStats : openNoRecoveryStats;
final Promise<LedgerDescriptor> promise = new Promise<LedgerDescriptor>();
final LedgerDescriptor ledgerDesc = new LedgerDescriptor(metadata.getLedgerId(), metadata.getLogSegmentSequenceNumber(), fence);
RefCountedLedgerHandle refhandle = handlesMap.get(ledgerDesc);
if (null == refhandle) {
asyncOpenLedger(ledgerDesc, new AsyncCallback.OpenCallback() {
@Override
public void openComplete(int rc, LedgerHandle lh, Object ctx) {
if (BKException.Code.OK != rc) {
promise.setException(BKException.create(rc));
return;
}
RefCountedLedgerHandle newRefHandle = new RefCountedLedgerHandle(lh);
RefCountedLedgerHandle oldRefHandle = handlesMap.putIfAbsent(ledgerDesc, newRefHandle);
if (null != oldRefHandle) {
oldRefHandle.addRef();
if (newRefHandle.removeRef()) {
newRefHandle.handle.asyncClose(new AsyncCallback.CloseCallback() {
@Override
public void closeComplete(int i, LedgerHandle ledgerHandle, Object o) {
// No action necessary
}
}, null);
}
}
promise.setValue(ledgerDesc);
}
}, null);
} else {
refhandle.addRef();
promise.setValue(ledgerDesc);
}
return promise.addEventListener(new FutureEventListener<LedgerDescriptor>() {
@Override
public void onSuccess(LedgerDescriptor value) {
openStatsLogger.registerSuccessfulEvent(stopwatch.elapsed(TimeUnit.MICROSECONDS));
}
@Override
public void onFailure(Throwable cause) {
openStatsLogger.registerFailedEvent(stopwatch.elapsed(TimeUnit.MICROSECONDS));
}
});
}
use of com.twitter.util.Promise in project distributedlog by twitter.
the class ReadUtils method getLogRecordNotLessThanTxId.
//
// Search Functions
//
/**
* Get the log record whose transaction id is not less than provided <code>transactionId</code>.
*
* <p>
* It uses a binary-search like algorithm to find the log record whose transaction id is not less than
* provided <code>transactionId</code> within a log <code>segment</code>. You could think of a log segment
* in terms of a sequence of records whose transaction ids are non-decreasing.
*
* - The sequence of records within a log segment is divided into N pieces.
* - Find the piece of records that contains a record whose transaction id is not less than provided
* <code>transactionId</code>.
*
* N could be chosen based on trading off concurrency and latency.
* </p>
*
* @param logName
* name of the log
* @param segment
* metadata of the log segment
* @param transactionId
* transaction id
* @param executorService
* executor service used for processing entries
* @param handleCache
* ledger handle cache
* @param nWays
* how many number of entries to search in parallel
* @return found log record. none if all transaction ids are less than provided <code>transactionId</code>.
*/
public static Future<Optional<LogRecordWithDLSN>> getLogRecordNotLessThanTxId(final String logName, final LogSegmentMetadata segment, final long transactionId, final ExecutorService executorService, final LedgerHandleCache handleCache, final int nWays) {
if (!segment.isInProgress()) {
if (segment.getLastTxId() < transactionId) {
// all log records whose transaction id is less than provided transactionId
// then return none
Optional<LogRecordWithDLSN> noneRecord = Optional.absent();
return Future.value(noneRecord);
}
}
final Promise<Optional<LogRecordWithDLSN>> promise = new Promise<Optional<LogRecordWithDLSN>>();
final FutureEventListener<LedgerDescriptor> openLedgerListener = new FutureEventListener<LedgerDescriptor>() {
@Override
public void onSuccess(final LedgerDescriptor ld) {
promise.ensure(new AbstractFunction0<BoxedUnit>() {
@Override
public BoxedUnit apply() {
handleCache.asyncCloseLedger(ld);
return BoxedUnit.UNIT;
}
});
long lastEntryId;
try {
lastEntryId = handleCache.getLastAddConfirmed(ld);
} catch (BKException e) {
promise.setException(e);
return;
}
if (lastEntryId < 0) {
// it means that the log segment is created but not written yet or an empty log segment.
// it is equivalent to 'all log records whose transaction id is less than provided transactionId'
Optional<LogRecordWithDLSN> nonRecord = Optional.absent();
promise.setValue(nonRecord);
return;
}
// all log records whose transaction id is not less than provided transactionId
if (segment.getFirstTxId() >= transactionId) {
final FirstTxIdNotLessThanSelector selector = new FirstTxIdNotLessThanSelector(transactionId);
asyncReadRecordFromEntries(logName, ld, handleCache, segment, executorService, new SingleEntryScanContext(0L), selector).addEventListener(new FutureEventListener<LogRecordWithDLSN>() {
@Override
public void onSuccess(LogRecordWithDLSN value) {
promise.setValue(Optional.of(selector.result()));
}
@Override
public void onFailure(Throwable cause) {
promise.setException(cause);
}
});
return;
}
getLogRecordNotLessThanTxIdFromEntries(logName, ld, segment, transactionId, executorService, handleCache, Lists.newArrayList(0L, lastEntryId), nWays, Optional.<LogRecordWithDLSN>absent(), promise);
}
@Override
public void onFailure(final Throwable cause) {
String errMsg = "Error opening log segment [" + segment + "] for find record from " + logName;
promise.setException(new IOException(errMsg, BKException.create(FutureUtils.bkResultCode(cause))));
}
};
handleCache.asyncOpenLedger(segment, false).addEventListener(FutureEventListenerRunnable.of(openLedgerListener, executorService));
return promise;
}
Aggregations