use of org.apache.distributedlog.lock.ZKDistributedLock in project bookkeeper by apache.
the class TestBKLogSegmentWriter method testCloseShouldFailIfLedgerFenced.
/**
* Close the writer when ledger is fenced: it should release the lock, fail on flushing data and throw exception.
*
* @throws Exception
*/
@Test(timeout = 60000)
public void testCloseShouldFailIfLedgerFenced() throws Exception {
DistributedLogConfiguration confLocal = newLocalConf();
confLocal.setImmediateFlushEnabled(false);
confLocal.setOutputBufferSize(Integer.MAX_VALUE);
confLocal.setPeriodicFlushFrequencyMilliSeconds(0);
ZKDistributedLock lock = createLock("/test/lock-" + runtime.getMethodName(), zkc, true);
BKLogSegmentWriter writer = createLogSegmentWriter(confLocal, 0L, -1L, lock);
// Use another lock to wait for writer releasing lock
ZKDistributedLock lock0 = createLock("/test/lock-" + runtime.getMethodName(), zkc0, false);
CompletableFuture<ZKDistributedLock> lockFuture0 = lock0.asyncAcquire();
// add 10 records
int numRecords = 10;
List<CompletableFuture<DLSN>> futureList = new ArrayList<CompletableFuture<DLSN>>(numRecords);
for (int i = 0; i < numRecords; i++) {
futureList.add(writer.asyncWrite(DLMTestUtil.getLogRecordInstance(i)));
}
assertEquals("Last tx id should be " + (numRecords - 1), numRecords - 1, writer.getLastTxId());
assertEquals("Last acked tx id should be -1", -1L, writer.getLastTxIdAcknowledged());
assertEquals("Last DLSN should be " + DLSN.InvalidDLSN, DLSN.InvalidDLSN, writer.getLastDLSN());
assertEquals("Position should be " + numRecords, 10, writer.getPositionWithinLogSegment());
// fence the ledger
fenceLedger(getLedgerHandle(writer));
// close the writer: it should release the lock, fail on flushing data and throw exception
try {
closeWriterAndLock(writer, lock);
fail("Close a log segment writer when ledger is fenced should throw exception");
} catch (BKTransmitException bkte) {
assertEquals("Inconsistent rc is thrown", BKException.Code.LedgerFencedException, bkte.getBKResultCode());
}
Utils.ioResult(lockFuture0);
lock0.checkOwnership();
assertEquals("Last tx id should still be " + (numRecords - 1), numRecords - 1, writer.getLastTxId());
assertEquals("Last acked tx id should still be " + (numRecords - 1), -1L, writer.getLastTxIdAcknowledged());
assertEquals("Last DLSN should still be " + DLSN.InvalidDLSN, DLSN.InvalidDLSN, writer.getLastDLSN());
assertEquals("Position should still be " + numRecords, 10, writer.getPositionWithinLogSegment());
for (int i = 0; i < numRecords; i++) {
try {
Utils.ioResult(futureList.get(i));
fail("Should be aborted record " + i + " with transmit exception");
} catch (BKTransmitException bkte) {
assertEquals("Record " + i + " should be aborted", BKException.Code.LedgerFencedException, bkte.getBKResultCode());
}
}
// check no entries were written
LedgerHandle lh = getLedgerHandle(writer);
LedgerHandle readLh = openLedgerNoRecovery(lh);
assertTrue("Ledger " + lh.getId() + " should be closed", readLh.isClosed());
assertEquals("There should be no entries in ledger " + lh.getId(), LedgerHandle.INVALID_ENTRY_ID, readLh.getLastAddConfirmed());
}
use of org.apache.distributedlog.lock.ZKDistributedLock in project bookkeeper by apache.
the class TestBKLogSegmentWriter method testCloseShouldNotFlushIfInErrorState.
/**
* Close a log segment writer that is already in error state, should not flush buffered data.
*
* @throws Exception
*/
void testCloseShouldNotFlushIfInErrorState(int rcToFailComplete) throws Exception {
DistributedLogConfiguration confLocal = newLocalConf();
confLocal.setImmediateFlushEnabled(false);
confLocal.setOutputBufferSize(Integer.MAX_VALUE);
confLocal.setPeriodicFlushFrequencyMilliSeconds(0);
ZKDistributedLock lock = createLock("/test/lock-" + runtime.getMethodName(), zkc, true);
BKLogSegmentWriter writer = createLogSegmentWriter(confLocal, 0L, -1L, lock);
// Use another lock to wait for writer releasing lock
ZKDistributedLock lock0 = createLock("/test/lock-" + runtime.getMethodName(), zkc0, false);
CompletableFuture<ZKDistributedLock> lockFuture0 = lock0.asyncAcquire();
// add 10 records
int numRecords = 10;
List<CompletableFuture<DLSN>> futureList = new ArrayList<CompletableFuture<DLSN>>(numRecords);
for (int i = 0; i < numRecords; i++) {
futureList.add(writer.asyncWrite(DLMTestUtil.getLogRecordInstance(i)));
}
assertEquals("Last tx id should be " + (numRecords - 1), numRecords - 1, writer.getLastTxId());
assertEquals("Last acked tx id should be -1", -1L, writer.getLastTxIdAcknowledged());
assertEquals("Last DLSN should be " + DLSN.InvalidDLSN, DLSN.InvalidDLSN, writer.getLastDLSN());
assertEquals("Position should be " + numRecords, 10, writer.getPositionWithinLogSegment());
writer.setTransmitResult(rcToFailComplete);
// close the writer should release lock but not flush data
try {
closeWriterAndLock(writer, lock);
fail("Close a log segment writer in error state should throw exception");
} catch (BKTransmitException bkte) {
assertEquals("Inconsistent rc is thrown", rcToFailComplete, bkte.getBKResultCode());
}
Utils.ioResult(lockFuture0);
lock0.checkOwnership();
assertEquals("Last tx id should still be " + (numRecords - 1), numRecords - 1, writer.getLastTxId());
assertEquals("Last acked tx id should still be " + (numRecords - 1), -1L, writer.getLastTxIdAcknowledged());
assertEquals("Last DLSN should still be " + DLSN.InvalidDLSN, DLSN.InvalidDLSN, writer.getLastDLSN());
assertEquals("Position should still be " + numRecords, 10, writer.getPositionWithinLogSegment());
for (int i = 0; i < numRecords; i++) {
try {
Utils.ioResult(futureList.get(i));
fail("Should be aborted record " + i + " with transmit exception");
} catch (WriteCancelledException wce) {
assertTrue("Record " + i + " should be aborted because of ledger fenced", wce.getCause() instanceof BKTransmitException);
BKTransmitException bkte = (BKTransmitException) wce.getCause();
assertEquals("Record " + i + " should be aborted", rcToFailComplete, bkte.getBKResultCode());
}
}
// check no entries were written
LedgerHandle lh = getLedgerHandle(writer);
LedgerHandle readLh = openLedgerNoRecovery(lh);
assertFalse("Ledger " + lh.getId() + " should not be closed", readLh.isClosed());
assertEquals("There should be no entries in ledger " + lh.getId(), LedgerHandle.INVALID_ENTRY_ID, readLh.getLastAddConfirmed());
}
use of org.apache.distributedlog.lock.ZKDistributedLock in project bookkeeper by apache.
the class TestBKLogSegmentWriter method testNondurableWriteAfterEndOfStream.
/**
* Non durable write should fail if writer is marked as end of stream.
*
* @throws Exception
*/
@Test(timeout = 60000)
public void testNondurableWriteAfterEndOfStream() throws Exception {
DistributedLogConfiguration confLocal = newLocalConf();
confLocal.setImmediateFlushEnabled(false);
confLocal.setOutputBufferSize(Integer.MAX_VALUE);
confLocal.setPeriodicFlushFrequencyMilliSeconds(0);
confLocal.setDurableWriteEnabled(false);
ZKDistributedLock lock = createLock("/test/lock-" + runtime.getMethodName(), zkc, true);
BKLogSegmentWriter writer = createLogSegmentWriter(confLocal, 0L, -1L, lock);
Utils.ioResult(writer.markEndOfStream());
try {
Utils.ioResult(writer.asyncWrite(DLMTestUtil.getLogRecordInstance(1)));
fail("Should fail the write if the writer is marked as end of stream");
} catch (EndOfStreamException we) {
// expected
}
closeWriterAndLock(writer, lock);
}
use of org.apache.distributedlog.lock.ZKDistributedLock in project bookkeeper by apache.
the class TestBKLogSegmentWriter method testCloseShouldFlush.
/**
* Close a segment log writer should flush buffered data.
*
* @throws Exception
*/
@Test(timeout = 60000)
public void testCloseShouldFlush() throws Exception {
DistributedLogConfiguration confLocal = newLocalConf();
confLocal.setImmediateFlushEnabled(false);
confLocal.setOutputBufferSize(Integer.MAX_VALUE);
confLocal.setPeriodicFlushFrequencyMilliSeconds(0);
ZKDistributedLock lock = createLock("/test/lock-" + runtime.getMethodName(), zkc, true);
BKLogSegmentWriter writer = createLogSegmentWriter(confLocal, 0L, -1L, lock);
// Use another lock to wait for writer releasing lock
ZKDistributedLock lock0 = createLock("/test/lock-" + runtime.getMethodName(), zkc0, false);
CompletableFuture<ZKDistributedLock> lockFuture0 = lock0.asyncAcquire();
// add 10 records
int numRecords = 10;
List<CompletableFuture<DLSN>> futureList = new ArrayList<CompletableFuture<DLSN>>(numRecords);
for (int i = 0; i < numRecords; i++) {
futureList.add(writer.asyncWrite(DLMTestUtil.getLogRecordInstance(i)));
}
assertEquals("Last tx id should be " + (numRecords - 1), numRecords - 1, writer.getLastTxId());
assertEquals("Last acked tx id should be -1", -1L, writer.getLastTxIdAcknowledged());
assertEquals("Last DLSN should be " + DLSN.InvalidDLSN, DLSN.InvalidDLSN, writer.getLastDLSN());
assertEquals("Position should be " + numRecords, 10, writer.getPositionWithinLogSegment());
// close the writer should flush buffered data and release lock
closeWriterAndLock(writer, lock);
Utils.ioResult(lockFuture0);
lock0.checkOwnership();
assertEquals("Last tx id should still be " + (numRecords - 1), numRecords - 1, writer.getLastTxId());
assertEquals("Last acked tx id should become " + (numRecords - 1), numRecords - 1, writer.getLastTxIdAcknowledged());
assertEquals("Position should still be " + numRecords, 10, writer.getPositionWithinLogSegment());
List<DLSN> dlsns = Utils.ioResult(FutureUtils.collect(futureList));
assertEquals("All records should be written", numRecords, dlsns.size());
for (int i = 0; i < numRecords; i++) {
DLSN dlsn = dlsns.get(i);
assertEquals("Incorrent ledger sequence number", 0L, dlsn.getLogSegmentSequenceNo());
assertEquals("Incorrent entry id", 0L, dlsn.getEntryId());
assertEquals("Inconsistent slot id", i, dlsn.getSlotId());
}
assertEquals("Last DLSN should be " + dlsns.get(dlsns.size() - 1), dlsns.get(dlsns.size() - 1), writer.getLastDLSN());
LedgerHandle lh = getLedgerHandle(writer);
LedgerHandle readLh = openLedgerNoRecovery(lh);
assertTrue("Ledger " + lh.getId() + " should be closed", readLh.isClosed());
assertEquals("There should be two entries in ledger " + lh.getId(), 1L, readLh.getLastAddConfirmed());
}
use of org.apache.distributedlog.lock.ZKDistributedLock in project bookkeeper by apache.
the class TestBKLogSegmentWriter method createLock.
private ZKDistributedLock createLock(String path, ZooKeeperClient zkClient, boolean acquireLock) throws Exception {
try {
Utils.ioResult(Utils.zkAsyncCreateFullPathOptimistic(zkClient, path, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT));
} catch (ZKException zke) {
// node already exists
}
SessionLockFactory lockFactory = new ZKSessionLockFactory(zkClient, "test-lock", lockStateExecutor, 0, Long.MAX_VALUE, conf.getZKSessionTimeoutMilliseconds(), NullStatsLogger.INSTANCE);
ZKDistributedLock lock = new ZKDistributedLock(lockStateExecutor, lockFactory, path, Long.MAX_VALUE, NullStatsLogger.INSTANCE);
if (acquireLock) {
return Utils.ioResult(lock.asyncAcquire());
} else {
return lock;
}
}
Aggregations