Search in sources :

Example 1 with FirstTxIdNotLessThanSelector

use of com.twitter.distributedlog.selector.FirstTxIdNotLessThanSelector in project distributedlog by twitter.

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 handleCache
 *          handle cache
 * @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 LedgerDescriptor ld, final LogSegmentMetadata segment, final long transactionId, final ExecutorService executorService, final LedgerHandleCache handleCache, final List<Long> entriesToSearch, final int nWays, final Optional<LogRecordWithDLSN> prevFoundRecord, final Promise<Optional<LogRecordWithDLSN>> promise) {
    final List<Future<LogRecordWithDLSN>> searchResults = Lists.newArrayListWithExpectedSize(entriesToSearch.size());
    for (Long entryId : entriesToSearch) {
        LogRecordSelector selector = new FirstTxIdNotLessThanSelector(transactionId);
        Future<LogRecordWithDLSN> searchResult = asyncReadRecordFromEntries(logName, ld, handleCache, 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, ld, segment, transactionId, executorService, handleCache, resultList, nWays, prevFoundRecord, promise);
        }

        @Override
        public void onFailure(Throwable cause) {
            promise.setException(cause);
        }
    };
    Future.collect(searchResults).addEventListener(FutureEventListenerRunnable.of(processSearchResultsListener, executorService));
}
Also used : AtomicLong(java.util.concurrent.atomic.AtomicLong) Future(com.twitter.util.Future) LogRecordSelector(com.twitter.distributedlog.selector.LogRecordSelector) List(java.util.List) FutureEventListener(com.twitter.util.FutureEventListener) FirstTxIdNotLessThanSelector(com.twitter.distributedlog.selector.FirstTxIdNotLessThanSelector)

Example 2 with FirstTxIdNotLessThanSelector

use of com.twitter.distributedlog.selector.FirstTxIdNotLessThanSelector in project distributedlog by twitter.

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 handleCache
 *          ledger handle cache
 * @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 Future<Optional<LogRecordWithDLSN>> getLogRecordNotLessThanTxId(final String logName, final LogSegmentMetadata segment, final long transactionId, final ExecutorService executorService, final LedgerHandleCache handleCache, 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 Future.value(noneRecord);
        }
    }
    final Promise<Optional<LogRecordWithDLSN>> promise = new Promise<Optional<LogRecordWithDLSN>>();
    final FutureEventListener<LedgerDescriptor> openLedgerListener = new FutureEventListener<LedgerDescriptor>() {

        @Override
        public void onSuccess(final LedgerDescriptor ld) {
            promise.ensure(new AbstractFunction0<BoxedUnit>() {

                @Override
                public BoxedUnit apply() {
                    handleCache.asyncCloseLedger(ld);
                    return BoxedUnit.UNIT;
                }
            });
            long lastEntryId;
            try {
                lastEntryId = handleCache.getLastAddConfirmed(ld);
            } catch (BKException e) {
                promise.setException(e);
                return;
            }
            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.setValue(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, ld, handleCache, segment, executorService, new SingleEntryScanContext(0L), selector).addEventListener(new FutureEventListener<LogRecordWithDLSN>() {

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

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

        @Override
        public void onFailure(final Throwable cause) {
            String errMsg = "Error opening log segment [" + segment + "] for find record from " + logName;
            promise.setException(new IOException(errMsg, BKException.create(FutureUtils.bkResultCode(cause))));
        }
    };
    handleCache.asyncOpenLedger(segment, false).addEventListener(FutureEventListenerRunnable.of(openLedgerListener, executorService));
    return promise;
}
Also used : Optional(com.google.common.base.Optional) IOException(java.io.IOException) FirstTxIdNotLessThanSelector(com.twitter.distributedlog.selector.FirstTxIdNotLessThanSelector) Promise(com.twitter.util.Promise) FutureEventListener(com.twitter.util.FutureEventListener) BKException(org.apache.bookkeeper.client.BKException) BoxedUnit(scala.runtime.BoxedUnit)

Aggregations

FirstTxIdNotLessThanSelector (com.twitter.distributedlog.selector.FirstTxIdNotLessThanSelector)2 FutureEventListener (com.twitter.util.FutureEventListener)2 Optional (com.google.common.base.Optional)1 LogRecordSelector (com.twitter.distributedlog.selector.LogRecordSelector)1 Future (com.twitter.util.Future)1 Promise (com.twitter.util.Promise)1 IOException (java.io.IOException)1 List (java.util.List)1 AtomicLong (java.util.concurrent.atomic.AtomicLong)1 BKException (org.apache.bookkeeper.client.BKException)1 BoxedUnit (scala.runtime.BoxedUnit)1