ReadUtils { static List<Long> getEntriesToSearch( long transactionId, LogRecordWithDLSN firstRecord, LogRecordWithDLSN lastRecord, int nWays) { long txnDiff = lastRecord.getTransactionId() - firstRecord.getTransactionId(); if (txnDiff > 0) { if (lastRecord.getTransactionId() == transactionId) { List<Long> entries = getEntriesToSearch( firstRecord.getDlsn().getEntryId() + 1, lastRecord.getDlsn().getEntryId() - 2, Math.max(MIN_SEARCH_BATCH_SIZE, nWays - 1)); entries.add(lastRecord.getDlsn().getEntryId() - 1); return entries; } else { return getEntriesToSearch( firstRecord.getDlsn().getEntryId() + 1, lastRecord.getDlsn().getEntryId() - 1, nWays); } } else { return Lists.newArrayList(); } }  static Future<LogRecordWithDLSN> asyncReadLastRecord(
            final String streamName,
            final LogSegmentMetadata l,
            final boolean fence,
            final boolean includeControl,
            final boolean includeEndOfStream,
            final int scanStartBatchSize,
            final int scanMaxBatchSize,
            final AtomicInteger numRecordsScanned,
            final ExecutorService executorService,
            final LedgerHandleCache handleCache); static Future<LogRecordWithDLSN> asyncReadFirstUserRecord(
            final String streamName,
            final LogSegmentMetadata l,
            final int scanStartBatchSize,
            final int scanMaxBatchSize,
            final AtomicInteger numRecordsScanned,
            final ExecutorService executorService,
            final LedgerHandleCache handleCache,
            final DLSN dlsn); static Future<Optional<LogRecordWithDLSN>> getLogRecordNotLessThanTxId(
            final String logName,
            final LogSegmentMetadata segment,
            final long transactionId,
            final ExecutorService executorService,
            final LedgerHandleCache handleCache,
            final int nWays);  }
@Test(timeout = 60000) public void testGetEntriesToSearch() throws Exception { assertTrue(ReadUtils.getEntriesToSearch(2L, 1L, 10).isEmpty()); assertEquals(Lists.newArrayList(1L), ReadUtils.getEntriesToSearch(1L, 1L, 10)); assertEquals(Lists.newArrayList(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L), ReadUtils.getEntriesToSearch(1L, 10L, 10)); assertEquals(Lists.newArrayList(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L), ReadUtils.getEntriesToSearch(1L, 9L, 10)); assertEquals(Lists.newArrayList(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L), ReadUtils.getEntriesToSearch(1L, 8L, 10)); assertEquals(Lists.newArrayList(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 11L), ReadUtils.getEntriesToSearch(1L, 11L, 10)); assertEquals(Lists.newArrayList(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 12L), ReadUtils.getEntriesToSearch(1L, 12L, 10)); }
@Test(timeout = 60000) public void testGetEntriesToSearchByTxnId() throws Exception { LogRecordWithDLSN firstRecord = DLMTestUtil.getLogRecordWithDLSNInstance(new DLSN(1L, 0L, 0L), 999L); LogRecordWithDLSN secondRecord = DLMTestUtil.getLogRecordWithDLSNInstance(new DLSN(1L, 10L, 0L), 99L); LogRecordWithDLSN thirdRecord = DLMTestUtil.getLogRecordWithDLSNInstance(new DLSN(1L, 100L, 0L), 1099L); assertTrue(ReadUtils.getEntriesToSearch(888L, firstRecord, secondRecord, 10).isEmpty()); assertTrue(ReadUtils.getEntriesToSearch(888L, firstRecord, firstRecord, 10).isEmpty()); assertEquals(2, ReadUtils.getEntriesToSearch(888L, firstRecord, thirdRecord, 2).size()); assertEquals(3, ReadUtils.getEntriesToSearch(1099L, firstRecord, thirdRecord, 2).size()); LogRecordWithDLSN record1 = DLMTestUtil.getLogRecordWithDLSNInstance(new DLSN(1L, 0L, 0L), 88L); LogRecordWithDLSN record2 = DLMTestUtil.getLogRecordWithDLSNInstance(new DLSN(1L, 12L, 0L), 888L); LogRecordWithDLSN record3 = DLMTestUtil.getLogRecordWithDLSNInstance(new DLSN(1L, 12L, 0L), 999L); assertEquals(Lists.newArrayList(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 10L, 11L), ReadUtils.getEntriesToSearch(888L, record1, record2, 10)); assertEquals(Lists.newArrayList(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 11L), ReadUtils.getEntriesToSearch(888L, record1, record3, 10)); }