use of com.twitter.util.Promise in project distributedlog by twitter.
the class BKDistributedLogManager method asyncClose.
/**
* Close the distributed log manager, freeing any resources it may hold.
*/
@Override
public Future<Void> asyncClose() {
Promise<Void> closeFuture;
BKLogReadHandler readHandlerToClose;
synchronized (this) {
if (null != closePromise) {
return closePromise;
}
closeFuture = closePromise = new Promise<Void>();
readHandlerToClose = readHandlerForListener;
}
// NOTE: the resources {scheduler, writerBKC, readerBKC} are mostly from namespace instance.
// so they are not blocking call except tests.
AsyncCloseable resourcesCloseable = new AsyncCloseable() {
@Override
public Future<Void> asyncClose() {
int schedTimeout = conf.getSchedulerShutdownTimeoutMs();
// Clean up executor state.
if (ownExecutor) {
SchedulerUtils.shutdownScheduler(scheduler, schedTimeout, TimeUnit.MILLISECONDS);
LOG.info("Stopped BKDL executor service for {}.", name);
if (scheduler != readAheadScheduler) {
SchedulerUtils.shutdownScheduler(readAheadScheduler, schedTimeout, TimeUnit.MILLISECONDS);
LOG.info("Stopped BKDL ReadAhead Executor Service for {}.", name);
}
SchedulerUtils.shutdownScheduler(getLockStateExecutor(false), schedTimeout, TimeUnit.MILLISECONDS);
LOG.info("Stopped BKDL Lock State Executor for {}.", name);
}
if (ownWriterBKC) {
writerBKC.close();
}
if (ownReaderBKC) {
readerBKC.close();
}
return Future.Void();
}
};
Future<Void> closeResult = Utils.closeSequence(null, true, readHandlerToClose, pendingReaders, resourcesCloseable, new AsyncCloseable() {
@Override
public Future<Void> asyncClose() {
return BKDistributedLogManager.super.asyncClose();
}
});
closeResult.proxyTo(closeFuture);
return closeFuture;
}
use of com.twitter.util.Promise in project distributedlog by twitter.
the class BKLogWriteHandler method deleteLogSegment.
private Future<LogSegmentMetadata> deleteLogSegment(final LogSegmentMetadata ledgerMetadata) {
LOG.info("Deleting ledger {} for {}", ledgerMetadata, getFullyQualifiedName());
final Promise<LogSegmentMetadata> promise = new Promise<LogSegmentMetadata>();
final Stopwatch stopwatch = Stopwatch.createStarted();
promise.addEventListener(new FutureEventListener<LogSegmentMetadata>() {
@Override
public void onSuccess(LogSegmentMetadata segment) {
deleteOpStats.registerSuccessfulEvent(stopwatch.stop().elapsed(TimeUnit.MICROSECONDS));
}
@Override
public void onFailure(Throwable cause) {
deleteOpStats.registerFailedEvent(stopwatch.stop().elapsed(TimeUnit.MICROSECONDS));
}
});
try {
bookKeeperClient.get().asyncDeleteLedger(ledgerMetadata.getLedgerId(), new AsyncCallback.DeleteCallback() {
@Override
public void deleteComplete(int rc, Object ctx) {
if (BKException.Code.NoSuchLedgerExistsException == rc) {
LOG.warn("No ledger {} found to delete for {} : {}.", new Object[] { ledgerMetadata.getLedgerId(), getFullyQualifiedName(), ledgerMetadata });
} else if (BKException.Code.OK != rc) {
BKException bke = BKException.create(rc);
LOG.error("Couldn't delete ledger {} from bookkeeper for {} : ", new Object[] { ledgerMetadata.getLedgerId(), getFullyQualifiedName(), bke });
promise.setException(bke);
return;
}
// after the ledger is deleted, we delete the metadata znode
scheduler.submit(new Runnable() {
@Override
public void run() {
deleteLogSegmentMetadata(ledgerMetadata, promise);
}
});
}
}, null);
} catch (IOException e) {
promise.setException(BKException.create(BKException.Code.BookieHandleNotAvailableException));
}
return promise;
}
use of com.twitter.util.Promise in project distributedlog by twitter.
the class BookKeeperClient method deleteLedger.
public Future<Void> deleteLedger(long lid, final boolean ignoreNonExistentLedger) {
BookKeeper bk;
try {
bk = get();
} catch (IOException ioe) {
return Future.exception(ioe);
}
final Promise<Void> promise = new Promise<Void>();
bk.asyncDeleteLedger(lid, new AsyncCallback.DeleteCallback() {
@Override
public void deleteComplete(int rc, Object ctx) {
if (BKException.Code.OK == rc) {
promise.updateIfEmpty(new Return<Void>(null));
} else if (BKException.Code.NoSuchLedgerExistsException == rc) {
if (ignoreNonExistentLedger) {
promise.updateIfEmpty(new Return<Void>(null));
} else {
promise.updateIfEmpty(new Throw<Void>(BKException.create(rc)));
}
} else {
promise.updateIfEmpty(new Throw<Void>(BKException.create(rc)));
}
}
}, null);
return promise;
}
use of com.twitter.util.Promise in project distributedlog by twitter.
the class ZKLogMetadataStore method getLogs.
@Override
public Future<Iterator<String>> getLogs() {
final Promise<Iterator<String>> promise = new Promise<Iterator<String>>();
final String nsRootPath = namespace.getPath();
try {
final ZooKeeper zk = zkc.get();
zk.sync(nsRootPath, new AsyncCallback.VoidCallback() {
@Override
public void processResult(int syncRc, String syncPath, Object ctx) {
if (KeeperException.Code.OK.intValue() == syncRc) {
zk.getChildren(nsRootPath, false, new AsyncCallback.Children2Callback() {
@Override
public void processResult(int rc, String path, Object ctx, List<String> children, Stat stat) {
if (KeeperException.Code.OK.intValue() == rc) {
List<String> results = Lists.newArrayListWithExpectedSize(children.size());
for (String child : children) {
if (!isReservedStreamName(child)) {
results.add(child);
}
}
promise.setValue(results.iterator());
} else if (KeeperException.Code.NONODE.intValue() == rc) {
List<String> streams = Lists.newLinkedList();
promise.setValue(streams.iterator());
} else {
promise.setException(new ZKException("Error reading namespace " + nsRootPath, KeeperException.Code.get(rc)));
}
}
}, null);
} else if (KeeperException.Code.NONODE.intValue() == syncRc) {
List<String> streams = Lists.newLinkedList();
promise.setValue(streams.iterator());
} else {
promise.setException(new ZKException("Error reading namespace " + nsRootPath, KeeperException.Code.get(syncRc)));
}
}
}, null);
zkc.get();
} catch (ZooKeeperClient.ZooKeeperConnectionException e) {
promise.setException(e);
} catch (InterruptedException e) {
promise.setException(e);
}
return promise;
}
use of com.twitter.util.Promise in project distributedlog by twitter.
the class TestAsyncReaderWriter method testWriteRecordSet.
@Test(timeout = 60000)
public void testWriteRecordSet() throws Exception {
String name = runtime.getMethodName();
DistributedLogConfiguration confLocal = new DistributedLogConfiguration();
confLocal.addConfiguration(testConf);
confLocal.setOutputBufferSize(0);
confLocal.setImmediateFlushEnabled(false);
confLocal.setPeriodicFlushFrequencyMilliSeconds(0);
URI uri = createDLMURI("/" + name);
ensureURICreated(uri);
DistributedLogManager dlm = createNewDLM(confLocal, name);
BKAsyncLogWriter writer = (BKAsyncLogWriter) dlm.startAsyncLogSegmentNonPartitioned();
List<Future<DLSN>> writeFutures = Lists.newArrayList();
for (int i = 0; i < 5; i++) {
LogRecord record = DLMTestUtil.getLogRecordInstance(1L + i);
writeFutures.add(writer.write(record));
}
List<Future<DLSN>> recordSetFutures = Lists.newArrayList();
// write another 5 records
final LogRecordSet.Writer recordSetWriter = LogRecordSet.newWriter(4096, CompressionCodec.Type.LZ4);
for (int i = 0; i < 5; i++) {
LogRecord record = DLMTestUtil.getLogRecordInstance(6L + i);
Promise<DLSN> writePromise = new Promise<DLSN>();
recordSetWriter.writeRecord(ByteBuffer.wrap(record.getPayload()), writePromise);
recordSetFutures.add(writePromise);
}
final ByteBuffer recordSetBuffer = recordSetWriter.getBuffer();
byte[] data = new byte[recordSetBuffer.remaining()];
recordSetBuffer.get(data);
LogRecord setRecord = new LogRecord(6L, data);
setRecord.setRecordSet();
Future<DLSN> writeRecordSetFuture = writer.write(setRecord);
writeRecordSetFuture.addEventListener(new FutureEventListener<DLSN>() {
@Override
public void onSuccess(DLSN dlsn) {
recordSetWriter.completeTransmit(dlsn.getLogSegmentSequenceNo(), dlsn.getEntryId(), dlsn.getSlotId());
}
@Override
public void onFailure(Throwable cause) {
recordSetWriter.abortTransmit(cause);
}
});
writeFutures.add(writeRecordSetFuture);
FutureUtils.result(writeRecordSetFuture);
// write last 5 records
for (int i = 0; i < 5; i++) {
LogRecord record = DLMTestUtil.getLogRecordInstance(11L + i);
Future<DLSN> writeFuture = writer.write(record);
writeFutures.add(writeFuture);
// make sure get log record count returns the right count
if (i == 0) {
FutureUtils.result(writeFuture);
assertEquals(10, dlm.getLogRecordCount());
}
}
List<DLSN> writeResults = FutureUtils.result(Future.collect(writeFutures));
for (int i = 0; i < 5; i++) {
Assert.assertEquals(new DLSN(1L, i, 0L), writeResults.get(i));
}
Assert.assertEquals(new DLSN(1L, 5L, 0L), writeResults.get(5));
for (int i = 0; i < 5; i++) {
Assert.assertEquals(new DLSN(1L, 6L + i, 0L), writeResults.get(6 + i));
}
List<DLSN> recordSetWriteResults = Await.result(Future.collect(recordSetFutures));
for (int i = 0; i < 5; i++) {
Assert.assertEquals(new DLSN(1L, 5L, i), recordSetWriteResults.get(i));
}
FutureUtils.result(writer.flushAndCommit());
DistributedLogConfiguration readConf1 = new DistributedLogConfiguration();
readConf1.addConfiguration(confLocal);
readConf1.setDeserializeRecordSetOnReads(true);
DistributedLogManager readDLM1 = createNewDLM(readConf1, name);
AsyncLogReader reader1 = readDLM1.getAsyncLogReader(DLSN.InitialDLSN);
for (int i = 0; i < 15; i++) {
LogRecordWithDLSN record = FutureUtils.result(reader1.readNext());
if (i < 5) {
assertEquals(new DLSN(1L, i, 0L), record.getDlsn());
assertEquals(1L + i, record.getTransactionId());
} else if (i >= 10) {
assertEquals(new DLSN(1L, 6L + i - 10, 0L), record.getDlsn());
assertEquals(11L + i - 10, record.getTransactionId());
} else {
assertEquals(new DLSN(1L, 5L, i - 5), record.getDlsn());
assertEquals(6L, record.getTransactionId());
}
assertEquals(i + 1, record.getPositionWithinLogSegment());
assertArrayEquals(DLMTestUtil.generatePayload(i + 1), record.getPayload());
}
DistributedLogConfiguration readConf2 = new DistributedLogConfiguration();
readConf2.addConfiguration(confLocal);
readConf2.setDeserializeRecordSetOnReads(false);
DistributedLogManager readDLM2 = createNewDLM(readConf2, name);
AsyncLogReader reader2 = readDLM2.getAsyncLogReader(DLSN.InitialDLSN);
for (int i = 0; i < 11; i++) {
LogRecordWithDLSN record = FutureUtils.result(reader2.readNext());
LOG.info("Read record {}", record);
if (i < 5) {
assertEquals(new DLSN(1L, i, 0L), record.getDlsn());
assertEquals(1L + i, record.getTransactionId());
assertEquals(i + 1, record.getPositionWithinLogSegment());
assertArrayEquals(DLMTestUtil.generatePayload(i + 1), record.getPayload());
} else if (i >= 6L) {
assertEquals(new DLSN(1L, 6L + i - 6, 0L), record.getDlsn());
assertEquals(11L + i - 6, record.getTransactionId());
assertEquals(11 + i - 6, record.getPositionWithinLogSegment());
assertArrayEquals(DLMTestUtil.generatePayload(11L + i - 6), record.getPayload());
} else {
assertEquals(new DLSN(1L, 5L, 0), record.getDlsn());
assertEquals(6L, record.getTransactionId());
assertEquals(6, record.getPositionWithinLogSegment());
assertTrue(record.isRecordSet());
assertEquals(5, LogRecordSet.numRecords(record));
}
}
}
Aggregations