Source:
public void testInterleavedRequests() throws Exception { File journalDir = tempDir.newFolder(); Bookie.checkDirectoryStructure(Bookie.getCurrentDirectory(journalDir)); ServerConfiguration conf = TestBKConfiguration.newServerConfiguration(); conf.setJournalDirName(journalDir.getPath()) .setZkServers(null); LedgerDirsManager ledgerDirsManager = mock(LedgerDirsManager.class); Journal journal = new Journal(journalDir, conf, ledgerDirsManager); journal.start(); final int numEntries = 100; CountDownLatch latchAckBeforeSynch = new CountDownLatch(numEntries); CountDownLatch latchAckAfterSynch = new CountDownLatch(numEntries); AtomicInteger forceWriteCalls = new AtomicInteger(); replace(method(JournalChannel.class, "forceWrite")).with(new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { log.info("{} called with arguments ", method.getName(), Arrays.toString(args)); forceWriteCalls.incrementAndGet(); try { method.invoke(proxy, args); } catch (InvocationTargetException err) { throw err.getCause(); } return null; } }); while (forceWriteCalls.get() == 0) { Thread.sleep(100); } long ledgerIdAckBeforeSync = 1; long ledgerIdAckAfterSync = 2; for (long entryId = 0; entryId < numEntries; entryId++) { journal.logAddEntry(ledgerIdAckBeforeSync, entryId, DATA, true, new WriteCallback() { @Override public void writeComplete(int rc, long ledgerId, long entryId, BookieSocketAddress addr, Object ctx) { latchAckBeforeSynch.countDown(); } }, null); journal.logAddEntry(ledgerIdAckAfterSync, entryId, DATA, false, new WriteCallback() { @Override public void writeComplete(int rc, long ledgerId, long entryId, BookieSocketAddress addr, Object ctx) { latchAckAfterSynch.countDown(); } }, null); } assertTrue(latchAckBeforeSynch.await(20, TimeUnit.SECONDS)); assertTrue(latchAckAfterSynch.await(20, TimeUnit.SECONDS)); journal.shutdown(); }

Target:
public void testInterleavedRequests() throws Exception { File journalDir = tempDir.newFolder(); Bookie.checkDirectoryStructure(Bookie.getCurrentDirectory(journalDir)); ServerConfiguration conf = TestBKConfiguration.newServerConfiguration(); conf.setJournalDirName(journalDir.getPath()) .setZkServers(null); JournalChannel jc = spy(new JournalChannel(journalDir, 1)); whenNew(JournalChannel.class).withAnyArguments().thenReturn(jc); LedgerDirsManager ledgerDirsManager = mock(LedgerDirsManager.class); Journal journal = new Journal(journalDir, conf, ledgerDirsManager); journal.start(); final int numEntries = 100; CountDownLatch latchAckBeforeSynch = new CountDownLatch(numEntries); CountDownLatch latchAckAfterSynch = new CountDownLatch(numEntries); long ledgerIdAckBeforeSync = 1; long ledgerIdAckAfterSync = 2; for (long entryId = 0; entryId < numEntries; entryId++) { journal.logAddEntry(ledgerIdAckBeforeSync, entryId, DATA, true, new WriteCallback() { @Override public void writeComplete(int rc, long ledgerId, long entryId, BookieSocketAddress addr, Object ctx) { latchAckBeforeSynch.countDown(); } }, null); journal.logAddEntry(ledgerIdAckAfterSync, entryId, DATA, false, new WriteCallback() { @Override public void writeComplete(int rc, long ledgerId, long entryId, BookieSocketAddress addr, Object ctx) { latchAckAfterSynch.countDown(); } }, null); } assertTrue(latchAckBeforeSynch.await(20, TimeUnit.SECONDS)); assertTrue(latchAckAfterSynch.await(20, TimeUnit.SECONDS)); verify(jc, times(0)).forceWrite(true); verify(jc, atLeast(1)).forceWrite(false); journal.shutdown(); }