use of org.apache.bookkeeper.proto.BookkeeperInternalCallbacks.GenericCallback in project bookkeeper by apache.
the class LedgerReader method readLacs.
public void readLacs(final LedgerHandle lh, long eid, final GenericCallback<Set<ReadResult<Long>>> callback) {
WriteSet writeSet = lh.distributionSchedule.getWriteSet(eid);
final AtomicInteger numBookies = new AtomicInteger(writeSet.size());
final Set<ReadResult<Long>> readResults = new HashSet<ReadResult<Long>>();
ReadEntryCallback readEntryCallback = (rc, lid, eid1, buffer, ctx) -> {
InetSocketAddress bookieAddress = (InetSocketAddress) ctx;
ReadResult<Long> rr;
if (BKException.Code.OK != rc) {
rr = new ReadResult<Long>(eid1, rc, null, bookieAddress);
} else {
try {
DigestManager.RecoveryData data = lh.macManager.verifyDigestAndReturnLastConfirmed(buffer);
rr = new ReadResult<Long>(eid1, BKException.Code.OK, data.getLastAddConfirmed(), bookieAddress);
} catch (BKException.BKDigestMatchException e) {
rr = new ReadResult<Long>(eid1, BKException.Code.DigestMatchException, null, bookieAddress);
}
}
readResults.add(rr);
if (numBookies.decrementAndGet() == 0) {
callback.operationComplete(BKException.Code.OK, readResults);
}
};
ArrayList<BookieSocketAddress> ensemble = lh.getLedgerMetadata().getEnsemble(eid);
for (int i = 0; i < writeSet.size(); i++) {
int idx = writeSet.get(i);
bookieClient.readEntry(ensemble.get(idx), lh.getId(), eid, readEntryCallback, ensemble.get(idx), BookieProtocol.FLAG_NONE);
}
}
use of org.apache.bookkeeper.proto.BookkeeperInternalCallbacks.GenericCallback in project bookkeeper by apache.
the class BookieLedgerIndexer method getBookieToLedgerIndex.
/**
* Generating bookie vs its ledgers map by reading all the ledgers in each
* bookie and parsing its metadata.
*
* @return bookie2ledgersMap map of bookie vs ledgers
* @throws BKAuditException
* exception while getting bookie-ledgers
*/
public Map<String, Set<Long>> getBookieToLedgerIndex() throws BKAuditException {
// bookie vs ledgers map
final ConcurrentHashMap<String, Set<Long>> bookie2ledgersMap = new ConcurrentHashMap<String, Set<Long>>();
final CountDownLatch ledgerCollectorLatch = new CountDownLatch(1);
Processor<Long> ledgerProcessor = new Processor<Long>() {
@Override
public void process(final Long ledgerId, final AsyncCallback.VoidCallback iterCallback) {
GenericCallback<LedgerMetadata> genericCallback = new GenericCallback<LedgerMetadata>() {
@Override
public void operationComplete(int rc, LedgerMetadata ledgerMetadata) {
if (rc == BKException.Code.OK) {
for (Map.Entry<Long, ArrayList<BookieSocketAddress>> ensemble : ledgerMetadata.getEnsembles().entrySet()) {
for (BookieSocketAddress bookie : ensemble.getValue()) {
putLedger(bookie2ledgersMap, bookie.toString(), ledgerId);
}
}
} else if (rc == BKException.Code.NoSuchLedgerExistsException) {
LOG.info("Ignoring replication of already deleted ledger {}", ledgerId);
rc = BKException.Code.OK;
} else {
LOG.warn("Unable to read the ledger:" + ledgerId + " information");
}
iterCallback.processResult(rc, null, null);
}
};
ledgerManager.readLedgerMetadata(ledgerId, genericCallback);
}
};
// Reading the result after processing all the ledgers
final List<Integer> resultCode = new ArrayList<Integer>(1);
ledgerManager.asyncProcessLedgers(ledgerProcessor, new AsyncCallback.VoidCallback() {
@Override
public void processResult(int rc, String s, Object obj) {
resultCode.add(rc);
ledgerCollectorLatch.countDown();
}
}, null, BKException.Code.OK, BKException.Code.ReadException);
try {
ledgerCollectorLatch.await();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new BKAuditException("Exception while getting the bookie-ledgers", e);
}
if (!resultCode.contains(BKException.Code.OK)) {
throw new BKAuditException("Exception while getting the bookie-ledgers", BKException.create(resultCode.get(0)));
}
return bookie2ledgersMap;
}
use of org.apache.bookkeeper.proto.BookkeeperInternalCallbacks.GenericCallback in project bookkeeper by apache.
the class TestLongZkLedgerIdGenerator method testGenerateLedgerId.
@Test
public void testGenerateLedgerId() throws Exception {
// Create *nThread* threads each generate *nLedgers* ledger id,
// and then check there is no identical ledger id.
final int nThread = 2;
final int nLedgers = 2000;
// Multiply by two. We're going to do half in the old legacy space and half in the new.
final CountDownLatch countDownLatch = new CountDownLatch(nThread * nLedgers * 2);
final AtomicInteger errCount = new AtomicInteger(0);
final ConcurrentLinkedQueue<Long> ledgerIds = new ConcurrentLinkedQueue<Long>();
final GenericCallback<Long> cb = new GenericCallback<Long>() {
@Override
public void operationComplete(int rc, Long result) {
if (Code.OK.intValue() == rc) {
ledgerIds.add(result);
} else {
errCount.incrementAndGet();
}
countDownLatch.countDown();
}
};
long start = System.currentTimeMillis();
for (int i = 0; i < nThread; i++) {
new Thread() {
@Override
public void run() {
for (int j = 0; j < nLedgers; j++) {
ledgerIdGenerator.generateLedgerId(cb);
}
}
}.start();
}
// Go and create the long-id directory in zookeeper. This should cause the id generator to generate ids with the
// new algo once we clear it's stored status.
ZkUtils.createFullPathOptimistic(zk, "/test-zk-ledger-id-generator/idgen-long", new byte[0], Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
ledgerIdGenerator.invalidateLedgerIdGenPathStatus();
for (int i = 0; i < nThread; i++) {
new Thread() {
@Override
public void run() {
for (int j = 0; j < nLedgers; j++) {
ledgerIdGenerator.generateLedgerId(cb);
}
}
}.start();
}
assertTrue("Wait ledger id generation threads to stop timeout : ", countDownLatch.await(120, TimeUnit.SECONDS));
LOG.info("Number of generated ledger id: {}, time used: {}", ledgerIds.size(), System.currentTimeMillis() - start);
assertEquals("Error occur during ledger id generation : ", 0, errCount.get());
Set<Long> ledgers = new HashSet<Long>();
while (!ledgerIds.isEmpty()) {
Long ledger = ledgerIds.poll();
assertNotNull("Generated ledger id is null : ", ledger);
assertFalse("Ledger id [" + ledger + "] conflict : ", ledgers.contains(ledger));
ledgers.add(ledger);
}
}
use of org.apache.bookkeeper.proto.BookkeeperInternalCallbacks.GenericCallback in project bookkeeper by apache.
the class TestPerChannelBookieClient method testDisconnectRace.
/**
* Test that all resources are freed if connections and disconnections
* are interleaved randomly.
*
* {@link https://issues.apache.org/jira/browse/BOOKKEEPER-620}
*/
@Test
public void testDisconnectRace() throws Exception {
final GenericCallback<PerChannelBookieClient> nullop = new GenericCallback<PerChannelBookieClient>() {
@Override
public void operationComplete(int rc, PerChannelBookieClient client) {
// do nothing, we don't care about doing anything with the connection,
// we just want to trigger it connecting.
}
};
final int iterations = 100000;
EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
OrderedExecutor executor = getOrderedSafeExecutor();
BookieSocketAddress addr = getBookie(0);
final PerChannelBookieClient client = new PerChannelBookieClient(executor, eventLoopGroup, addr, authProvider, extRegistry);
final AtomicBoolean shouldFail = new AtomicBoolean(false);
final AtomicBoolean running = new AtomicBoolean(true);
final CountDownLatch disconnectRunning = new CountDownLatch(1);
Thread connectThread = new Thread() {
public void run() {
try {
if (!disconnectRunning.await(10, TimeUnit.SECONDS)) {
LOG.error("Disconnect thread never started");
shouldFail.set(true);
}
} catch (InterruptedException ie) {
LOG.error("Connect thread interrupted", ie);
Thread.currentThread().interrupt();
running.set(false);
}
for (int i = 0; i < iterations && running.get(); i++) {
client.connectIfNeededAndDoOp(nullop);
}
running.set(false);
}
};
Thread disconnectThread = new Thread() {
public void run() {
disconnectRunning.countDown();
while (running.get()) {
client.disconnect();
}
}
};
Thread checkThread = new Thread() {
public void run() {
ConnectionState state;
Channel channel;
while (running.get()) {
synchronized (client) {
state = client.state;
channel = client.channel;
if ((state == ConnectionState.CONNECTED && (channel == null || !channel.isActive())) || (state != ConnectionState.CONNECTED && channel != null && channel.isActive())) {
LOG.error("State({}) and channel({}) inconsistent " + channel, state, channel == null ? null : channel.isActive());
shouldFail.set(true);
running.set(false);
}
}
}
}
};
connectThread.start();
disconnectThread.start();
checkThread.start();
connectThread.join();
disconnectThread.join();
checkThread.join();
assertFalse("Failure in threads, check logs", shouldFail.get());
client.close();
eventLoopGroup.shutdownGracefully();
executor.shutdown();
}
use of org.apache.bookkeeper.proto.BookkeeperInternalCallbacks.GenericCallback in project bookkeeper by apache.
the class TestPerChannelBookieClient method testConnectRace.
/**
* Test race scenario found in {@link https://issues.apache.org/jira/browse/BOOKKEEPER-5}
* where multiple clients try to connect a channel simultaneously. If not synchronised
* correctly, this causes the netty channel to get orphaned.
*/
@Test
public void testConnectRace() throws Exception {
GenericCallback<PerChannelBookieClient> nullop = new GenericCallback<PerChannelBookieClient>() {
@Override
public void operationComplete(int rc, PerChannelBookieClient pcbc) {
// do nothing, we don't care about doing anything with the connection,
// we just want to trigger it connecting.
}
};
EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
OrderedExecutor executor = getOrderedSafeExecutor();
BookieSocketAddress addr = getBookie(0);
for (int i = 0; i < 100; i++) {
PerChannelBookieClient client = new PerChannelBookieClient(executor, eventLoopGroup, addr, authProvider, extRegistry);
for (int j = i; j < 10; j++) {
client.connectIfNeededAndDoOp(nullop);
}
client.close();
}
eventLoopGroup.shutdownGracefully();
executor.shutdown();
}
Aggregations