use of org.apache.bookkeeper.proto.BookkeeperInternalCallbacks.WriteCallback in project bookkeeper by apache.
the class AuditorPeriodicCheckTest method replaceBookieWithWriteFailingBookie.
private BookieSocketAddress replaceBookieWithWriteFailingBookie(LedgerHandle lh) throws Exception {
int bookieIdx = -1;
Long entryId = LedgerHandleAdapter.getLedgerMetadata(lh).getEnsembles().firstKey();
ArrayList<BookieSocketAddress> curEnsemble = LedgerHandleAdapter.getLedgerMetadata(lh).getEnsembles().get(entryId);
// Identify a bookie in the current ledger ensemble to be replaced
BookieSocketAddress replacedBookie = null;
for (int i = 0; i < numBookies; i++) {
if (curEnsemble.contains(bs.get(i).getLocalAddress())) {
bookieIdx = i;
replacedBookie = bs.get(i).getLocalAddress();
break;
}
}
assertNotEquals("Couldn't find ensemble bookie in bookie list", -1, bookieIdx);
LOG.info("Killing bookie " + bs.get(bookieIdx).getLocalAddress());
ServerConfiguration conf = killBookie(bookieIdx);
Bookie writeFailingBookie = new Bookie(conf) {
@Override
public void addEntry(ByteBuf entry, boolean ackBeforeSync, WriteCallback cb, Object ctx, byte[] masterKey) throws IOException, BookieException {
try {
LOG.info("Failing write to entry ");
// sleep a bit so that writes to other bookies succeed before
// the client hears about the failure on this bookie. If the
// client gets ack-quorum number of acks first, it won't care
// about any failures and won't reform the ensemble.
Thread.sleep(100);
throw new IOException();
} catch (InterruptedException ie) {
// ignore, only interrupted if shutting down,
// and an exception would spam the logs
Thread.currentThread().interrupt();
}
}
};
bsConfs.add(conf);
bs.add(startBookie(conf, writeFailingBookie));
return replacedBookie;
}
use of org.apache.bookkeeper.proto.BookkeeperInternalCallbacks.WriteCallback in project bookkeeper by apache.
the class LedgerRecoveryTest method ledgerRecoveryWithSlowBookie.
private void ledgerRecoveryWithSlowBookie(int ensembleSize, int writeQuorumSize, int ackQuorumSize, int numEntries, int slowBookieIdx) throws Exception {
// Create a ledger
LedgerHandle beforelh = null;
beforelh = bkc.createLedger(ensembleSize, writeQuorumSize, ackQuorumSize, digestType, "".getBytes());
// kill first bookie server to start a fake one to simulate a slow bookie
// and failed to add entry on crash
// until write succeed
BookieSocketAddress host = beforelh.getLedgerMetadata().currentEnsemble.get(slowBookieIdx);
ServerConfiguration conf = killBookie(host);
Bookie fakeBookie = new Bookie(conf) {
@Override
public void addEntry(ByteBuf entry, boolean ackBeforeSync, WriteCallback cb, Object ctx, byte[] masterKey) throws IOException, BookieException {
// drop request to simulate a slow and failed bookie
}
};
bsConfs.add(conf);
bs.add(startBookie(conf, fakeBookie));
// avoid not-enough-bookies case
startNewBookie();
// write would still succeed with 2 bookies ack
String tmp = "BookKeeper is cool!";
for (int i = 0; i < numEntries; i++) {
beforelh.addEntry(tmp.getBytes());
}
conf = killBookie(host);
bsConfs.add(conf);
// the bookie goes normally
bs.add(startBookie(conf));
/*
* Try to open ledger.
*/
LedgerHandle afterlh = bkc.openLedger(beforelh.getId(), digestType, "".getBytes());
/*
* Check if has recovered properly.
*/
assertEquals(numEntries - 1, afterlh.getLastAddConfirmed());
}
use of org.apache.bookkeeper.proto.BookkeeperInternalCallbacks.WriteCallback in project bookkeeper by apache.
the class BookKeeperCloseTest method restartBookieSlow.
private void restartBookieSlow() throws Exception {
ServerConfiguration conf = killBookie(0);
Bookie delayBookie = new Bookie(conf) {
@Override
public void recoveryAddEntry(ByteBuf entry, WriteCallback cb, Object ctx, byte[] masterKey) throws IOException, BookieException {
try {
Thread.sleep(5000);
} catch (InterruptedException ie) {
// ignore, only interrupted if shutting down,
// and an exception would spam the logs
Thread.currentThread().interrupt();
}
super.recoveryAddEntry(entry, cb, ctx, masterKey);
}
@Override
public void addEntry(ByteBuf entry, boolean ackBeforeSync, WriteCallback cb, Object ctx, byte[] masterKey) throws IOException, BookieException {
try {
Thread.sleep(5000);
} catch (InterruptedException ie) {
// ignore, only interrupted if shutting down,
// and an exception would spam the logs
Thread.currentThread().interrupt();
}
super.addEntry(entry, ackBeforeSync, cb, ctx, masterKey);
}
@Override
public ByteBuf readEntry(long ledgerId, long entryId) throws IOException, NoLedgerException {
try {
Thread.sleep(5000);
} catch (InterruptedException ie) {
// ignore, only interrupted if shutting down,
// and an exception would spam the logs
Thread.currentThread().interrupt();
}
return super.readEntry(ledgerId, entryId);
}
};
bsConfs.add(conf);
bs.add(startBookie(conf, delayBookie));
}
use of org.apache.bookkeeper.proto.BookkeeperInternalCallbacks.WriteCallback in project bookkeeper by apache.
the class LedgerCloseTest method startDeadBookie.
// simulate slow adds, then become normal when recover,
// so no ensemble change when recovering ledger on this bookie.
private void startDeadBookie(ServerConfiguration conf, final CountDownLatch latch) throws Exception {
Bookie dBookie = new Bookie(conf) {
@Override
public void addEntry(ByteBuf entry, boolean ackBeforeSync, WriteCallback cb, Object ctx, byte[] masterKey) throws IOException, BookieException {
try {
latch.await();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
// simulate slow adds.
throw new IOException("Dead bookie");
}
};
bsConfs.add(conf);
bs.add(startBookie(conf, dBookie));
}
use of org.apache.bookkeeper.proto.BookkeeperInternalCallbacks.WriteCallback in project bookkeeper by apache.
the class LedgerRecoveryTest method testLedgerRecoveryWithRollingRestart.
/**
* {@link https://issues.apache.org/jira/browse/BOOKKEEPER-355}
* A recovery during a rolling restart shouldn't affect the ability
* to recovery the ledger later.
* We have a ledger on ensemble B1,B2,B3.
* The sequence of events is
* 1. B1 brought down for maintenance
* 2. Ledger recovery started
* 3. B2 answers read last confirmed.
* 4. B1 replaced in ensemble by B4
* 5. Write to B4 fails for some reason
* 6. B1 comes back up.
* 7. B2 goes down for maintenance.
* 8. Ledger recovery starts (ledger is now unavailable)
*/
@Test
public void testLedgerRecoveryWithRollingRestart() throws Exception {
LedgerHandle lhbefore = bkc.createLedger(numBookies, 2, digestType, "".getBytes());
for (int i = 0; i < (numBookies * 3) + 1; i++) {
lhbefore.addEntry("data".getBytes());
}
// Add a dead bookie to the cluster
ServerConfiguration conf = newServerConfiguration();
Bookie deadBookie1 = new Bookie(conf) {
@Override
public void recoveryAddEntry(ByteBuf entry, WriteCallback cb, Object ctx, byte[] masterKey) throws IOException, BookieException {
// drop request to simulate a slow and failed bookie
throw new IOException("Couldn't write for some reason");
}
};
bsConfs.add(conf);
bs.add(startBookie(conf, deadBookie1));
// kill first bookie server
BookieSocketAddress bookie1 = lhbefore.getLedgerMetadata().currentEnsemble.get(0);
ServerConfiguration conf1 = killBookie(bookie1);
// ensemble in the ensemble, and another bookie is available in zk, but not writtable
try {
bkc.openLedger(lhbefore.getId(), digestType, "".getBytes());
fail("Shouldn't be able to open ledger, there should be entries missing");
} catch (BKException.BKLedgerRecoveryException e) {
// expected
}
// restart the first server, kill the second
bsConfs.add(conf1);
bs.add(startBookie(conf1));
BookieSocketAddress bookie2 = lhbefore.getLedgerMetadata().currentEnsemble.get(1);
ServerConfiguration conf2 = killBookie(bookie2);
// using async, because this could trigger an assertion
final AtomicInteger returnCode = new AtomicInteger(0);
final CountDownLatch openLatch = new CountDownLatch(1);
bkc.asyncOpenLedger(lhbefore.getId(), digestType, "".getBytes(), new AsyncCallback.OpenCallback() {
public void openComplete(int rc, LedgerHandle lh, Object ctx) {
returnCode.set(rc);
openLatch.countDown();
if (rc == BKException.Code.OK) {
try {
lh.close();
} catch (Exception e) {
LOG.error("Exception closing ledger handle", e);
}
}
}
}, null);
assertTrue("Open call should have completed", openLatch.await(5, TimeUnit.SECONDS));
assertFalse("Open should not have succeeded", returnCode.get() == BKException.Code.OK);
bsConfs.add(conf2);
bs.add(startBookie(conf2));
LedgerHandle lhafter = bkc.openLedger(lhbefore.getId(), digestType, "".getBytes());
assertEquals("Fenced ledger should have correct lastAddConfirmed", lhbefore.getLastAddConfirmed(), lhafter.getLastAddConfirmed());
}
Aggregations