Search in sources :

Example 1 with FirstTxIdNotLessThanSelector

use of org.apache.distributedlog.selector.FirstTxIdNotLessThanSelector in project bookkeeper by apache.

the class ReadUtils method getLogRecordNotLessThanTxIdFromEntries.

/**
 * Find the log record whose transaction id is not less than provided <code>transactionId</code> from
 * entries between <code>startEntryId</code> and <code>endEntryId</code>.
 *
 * @param logName
 *          name of the log
 * @param segment
 *          log segment
 * @param transactionId
 *          provided transaction id to search
 * @param executorService
 *          executor service
 * @param reader
 *          log segment random access reader
 * @param entriesToSearch
 *          list of entries to search
 * @param nWays
 *          how many entries to search in parallel
 * @param prevFoundRecord
 *          the log record found in previous search
 * @param promise
 *          promise to satisfy the result
 */
private static void getLogRecordNotLessThanTxIdFromEntries(final String logName, final LogSegmentMetadata segment, final long transactionId, final ExecutorService executorService, final LogSegmentRandomAccessEntryReader reader, final List<Long> entriesToSearch, final int nWays, final Optional<LogRecordWithDLSN> prevFoundRecord, final CompletableFuture<Optional<LogRecordWithDLSN>> promise) {
    final List<CompletableFuture<LogRecordWithDLSN>> searchResults = Lists.newArrayListWithExpectedSize(entriesToSearch.size());
    for (Long entryId : entriesToSearch) {
        LogRecordSelector selector = new FirstTxIdNotLessThanSelector(transactionId);
        CompletableFuture<LogRecordWithDLSN> searchResult = asyncReadRecordFromEntries(logName, reader, segment, executorService, new SingleEntryScanContext(entryId), selector);
        searchResults.add(searchResult);
    }
    FutureEventListener<List<LogRecordWithDLSN>> processSearchResultsListener = new FutureEventListener<List<LogRecordWithDLSN>>() {

        @Override
        public void onSuccess(List<LogRecordWithDLSN> resultList) {
            processSearchResults(logName, segment, transactionId, executorService, reader, resultList, nWays, prevFoundRecord, promise);
        }

        @Override
        public void onFailure(Throwable cause) {
            promise.completeExceptionally(cause);
        }
    };
    FutureUtils.collect(searchResults).whenCompleteAsync(processSearchResultsListener, executorService);
}
Also used : CompletableFuture(java.util.concurrent.CompletableFuture) AtomicLong(java.util.concurrent.atomic.AtomicLong) LogRecordSelector(org.apache.distributedlog.selector.LogRecordSelector) List(java.util.List) FutureEventListener(org.apache.bookkeeper.common.concurrent.FutureEventListener) FirstTxIdNotLessThanSelector(org.apache.distributedlog.selector.FirstTxIdNotLessThanSelector)

Example 2 with FirstTxIdNotLessThanSelector

use of org.apache.distributedlog.selector.FirstTxIdNotLessThanSelector in project bookkeeper by apache.

the class ReadUtils method getLogRecordNotLessThanTxId.

// 
// Search Functions
// 
/**
 * Get the log record whose transaction id is not less than provided <code>transactionId</code>.
 *
 * <p>
 * It uses a binary-search like algorithm to find the log record whose transaction id is not less than
 * provided <code>transactionId</code> within a log <code>segment</code>. You could think of a log segment
 * in terms of a sequence of records whose transaction ids are non-decreasing.
 *
 * - The sequence of records within a log segment is divided into N pieces.
 * - Find the piece of records that contains a record whose transaction id is not less than provided
 *   <code>transactionId</code>.
 *
 * N could be chosen based on trading off concurrency and latency.
 * </p>
 *
 * @param logName
 *          name of the log
 * @param segment
 *          metadata of the log segment
 * @param transactionId
 *          transaction id
 * @param executorService
 *          executor service used for processing entries
 * @param entryStore
 *          log segment entry store
 * @param nWays
 *          how many number of entries to search in parallel
 * @return found log record. none if all transaction ids are less than provided <code>transactionId</code>.
 */
public static CompletableFuture<Optional<LogRecordWithDLSN>> getLogRecordNotLessThanTxId(final String logName, final LogSegmentMetadata segment, final long transactionId, final ExecutorService executorService, final LogSegmentEntryStore entryStore, final int nWays) {
    if (!segment.isInProgress()) {
        if (segment.getLastTxId() < transactionId) {
            // all log records whose transaction id is less than provided transactionId
            // then return none
            Optional<LogRecordWithDLSN> noneRecord = Optional.absent();
            return FutureUtils.value(noneRecord);
        }
    }
    final CompletableFuture<Optional<LogRecordWithDLSN>> promise = new CompletableFuture<Optional<LogRecordWithDLSN>>();
    final FutureEventListener<LogSegmentRandomAccessEntryReader> openReaderListener = new FutureEventListener<LogSegmentRandomAccessEntryReader>() {

        @Override
        public void onSuccess(final LogSegmentRandomAccessEntryReader reader) {
            promise.whenComplete((value, cause) -> reader.asyncClose());
            long lastEntryId = reader.getLastAddConfirmed();
            if (lastEntryId < 0) {
                // it means that the log segment is created but not written yet or an empty log segment.
                // it is equivalent to 'all log records whose transaction id is less than provided transactionId'
                Optional<LogRecordWithDLSN> nonRecord = Optional.absent();
                promise.complete(nonRecord);
                return;
            }
            // all log records whose transaction id is not less than provided transactionId
            if (segment.getFirstTxId() >= transactionId) {
                final FirstTxIdNotLessThanSelector selector = new FirstTxIdNotLessThanSelector(transactionId);
                asyncReadRecordFromEntries(logName, reader, segment, executorService, new SingleEntryScanContext(0L), selector).whenComplete(new FutureEventListener<LogRecordWithDLSN>() {

                    @Override
                    public void onSuccess(LogRecordWithDLSN value) {
                        promise.complete(Optional.of(selector.result()));
                    }

                    @Override
                    public void onFailure(Throwable cause) {
                        promise.completeExceptionally(cause);
                    }
                });
                return;
            }
            getLogRecordNotLessThanTxIdFromEntries(logName, segment, transactionId, executorService, reader, Lists.newArrayList(0L, lastEntryId), nWays, Optional.<LogRecordWithDLSN>absent(), promise);
        }

        @Override
        public void onFailure(final Throwable cause) {
            promise.completeExceptionally(cause);
        }
    };
    entryStore.openRandomAccessReader(segment, false).whenCompleteAsync(openReaderListener, executorService);
    return promise;
}
Also used : Optional(com.google.common.base.Optional) LogSegmentRandomAccessEntryReader(org.apache.distributedlog.logsegment.LogSegmentRandomAccessEntryReader) FirstTxIdNotLessThanSelector(org.apache.distributedlog.selector.FirstTxIdNotLessThanSelector) CompletableFuture(java.util.concurrent.CompletableFuture) FutureEventListener(org.apache.bookkeeper.common.concurrent.FutureEventListener)

Aggregations

CompletableFuture (java.util.concurrent.CompletableFuture)2 FutureEventListener (org.apache.bookkeeper.common.concurrent.FutureEventListener)2 FirstTxIdNotLessThanSelector (org.apache.distributedlog.selector.FirstTxIdNotLessThanSelector)2 Optional (com.google.common.base.Optional)1 List (java.util.List)1 AtomicLong (java.util.concurrent.atomic.AtomicLong)1 LogSegmentRandomAccessEntryReader (org.apache.distributedlog.logsegment.LogSegmentRandomAccessEntryReader)1 LogRecordSelector (org.apache.distributedlog.selector.LogRecordSelector)1