reddycharan 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_r171930561
 
 

 ##########
 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);
+        InterleavedLedgerStorage ledgerStorage = ((InterleavedLedgerStorage) 
bookie.ledgerStorage);
+
+        int numOfLedgers = 70;
+        int numEntries = 3000;
+        // Create ledgers
+        for (int i = 0; i < numOfLedgers; i++) {
+            ledgerStorage.setMasterKey(i, "key".getBytes());
+        }
+
+        ExecutorService executor = Executors.newFixedThreadPool(40);
+        List<LedgerStorageWriteTask> writeTasks = new 
ArrayList<LedgerStorageWriteTask>();
+        for (int j = 0; j < numEntries; j++) {
+            for (int i = 0; i < numOfLedgers; i++) {
+                writeTasks.add(new LedgerStorageWriteTask(i, j, 
ledgerStorage));
+            }
+        }
+
+        // invoke all those write tasks all at once concurrently and set 
timeout
+        // 6 seconds for them to complete
+        List<Future<Boolean>> writeTasksFutures = 
executor.invokeAll(writeTasks, 6, TimeUnit.SECONDS);
+        for (int i = 0; i < writeTasks.size(); i++) {
+            Future<Boolean> future = writeTasksFutures.get(i);
+            LedgerStorageWriteTask writeTask = writeTasks.get(i);
+            long ledgerId = writeTask.ledgerId;
+            int entryId = writeTask.entryId;
+            Assert.assertTrue(
+                    "WriteTask should have been completed successfully 
ledgerId: " + ledgerId + " entryId: " + entryId,
+                    future.isDone() && (!future.isCancelled()));
 
 Review comment:
   agreed, checking future.isDone is redundant here. but I would like to check 
"isCancelled" status before calling ".get". It would be helpful to diagnose the 
issue incase of failure (cancelled), if there is assert log statement instead 
of seeing CancellationException in the test results with no real context 
regarding which task has failed because of cancellation.

----------------------------------------------------------------
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

Reply via email to