ivankelly commented on a change in pull request #1225: Issue #570: getting rid of unnecessary synchronization in InterleavedLedgerStorage URL: https://github.com/apache/bookkeeper/pull/1225#discussion_r172126626
########## File path: bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/EntryLogTest.java ########## @@ -391,4 +400,137 @@ public void testGetEntryLogsSet() throws Exception { assertEquals(Sets.newHashSet(0L, 1L, 2L, 3L), logger.getEntryLogsSet()); } + + class LedgerStorageWriteTask implements Callable<Boolean> { + long ledgerId; + int entryId; + LedgerStorage ledgerStorage; + + LedgerStorageWriteTask(long ledgerId, int entryId, LedgerStorage ledgerStorage) { + this.ledgerId = ledgerId; + this.entryId = entryId; + this.ledgerStorage = ledgerStorage; + } + + @Override + public Boolean call() { + try { + ledgerStorage.addEntry(generateEntry(ledgerId, entryId)); + } catch (IOException e) { + LOG.error("Got Exception for AddEntry call. LedgerId: " + ledgerId + " entryId: " + entryId, e); + return false; + } + return true; + } + } + + class LedgerStorageReadTask implements Callable<Boolean> { + long ledgerId; + int entryId; + LedgerStorage ledgerStorage; + + LedgerStorageReadTask(long ledgerId, int entryId, LedgerStorage ledgerStorage) { + this.ledgerId = ledgerId; + this.entryId = entryId; + this.ledgerStorage = ledgerStorage; + } + + @Override + public Boolean call() { + try { + String expectedValue = generateDataString(ledgerId, entryId); + ByteBuf byteBuf = ledgerStorage.getEntry(ledgerId, entryId); + long actualLedgerId = byteBuf.readLong(); + long actualEntryId = byteBuf.readLong(); + byte[] data = new byte[byteBuf.readableBytes()]; + byteBuf.readBytes(data); + if (ledgerId != actualLedgerId) { + LOG.error("For ledgerId: {} entryId: {} readRequest, actual ledgerId: {}", ledgerId, entryId, + actualLedgerId); + return false; + } + if (entryId != actualEntryId) { + LOG.error("For ledgerId: {} entryId: {} readRequest, actual entryId: {}", ledgerId, entryId, + actualEntryId); + return false; + } + if (!expectedValue.equals(new String(data))) { + LOG.error("For ledgerId: {} entryId: {} readRequest, actual Data: {}", ledgerId, entryId, + new String(data)); + return false; + } + } catch (IOException e) { + LOG.error("Got Exception for GetEntry call. LedgerId: " + ledgerId + " entryId: " + entryId, e); + return false; + } + return true; + } + } + + /** + * test concurrent write operations and then concurrent read + * operations using InterleavedLedgerStorage. + */ + @Test + public void testConcurrentWriteAndReadCallsOfInterleavedLedgerStorage() throws Exception { + File ledgerDir = createTempDir("bkTest", ".dir"); + ServerConfiguration conf = TestBKConfiguration.newServerConfiguration(); + conf.setJournalDirName(ledgerDir.toString()); + conf.setLedgerDirNames(new String[] { ledgerDir.getAbsolutePath()}); + conf.setLedgerStorageClass(InterleavedLedgerStorage.class.getName()); + Bookie bookie = new Bookie(conf); Review comment: I've seen this pattern a few times where we construct a whole bookie, and everything that goes with it, just to get the ledger dirs manager or ledger storage. It makes our tests super heavy, and hard to inject mocked behaviour. This is part of the reason we have Thread.sleep all over the place in the test. Anyhow, I won't block for this, but it's something we should be aware of and try to avoid in future. If you're concerned about long argument lists, we can create utility methods to hide the complexity. ---------------------------------------------------------------- This is an automated message from the Apache Git Service. To respond to the message, please log on GitHub and use the URL above to go to the specific comment. For queries about this service, please contact Infrastructure at: us...@infra.apache.org With regards, Apache Git Services