content: /*
   *
   * Licensed to the Apache Software Foundation (ASF) under one
   * or more contributor license agreements.  See the NOTICE file
   * distributed with this work for additional information
   * regarding copyright ownership.  The ASF licenses this file
   * to you under the Apache License, Version 2.0 (the
   * "License"); you may not use this file except in compliance
   * with the License.  You may obtain a copy of the License at
   *
   *   http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing,
   * software distributed under the License is distributed on an
   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   * KIND, either express or implied.  See the License for the
   * specific language governing permissions and limitations
   * under the License.
   *
   */
  package org.apache.bookkeeper.client.api;
  
  import java.util.concurrent.CompletableFuture;
  import org.apache.bookkeeper.common.annotation.InterfaceAudience.Public;
  import org.apache.bookkeeper.common.annotation.InterfaceStability.Unstable;
  import org.apache.bookkeeper.common.concurrent.FutureUtils;
  
  /**
   * Provide read access to a ledger.
   *
   * @since 4.6
   */
  @Public
  @Unstable
  public interface ReadHandle extends Handle {
  
      /**
       * Read a sequence of entries asynchronously.
       *
       * @param firstEntry
       *          id of first entry of sequence
       * @param lastEntry
       *          id of last entry of sequence, inclusive
       * @return an handle to the result of the operation
       */
      CompletableFuture<LedgerEntries> readAsync(long firstEntry, long lastEntry);
  
      /**
       * Read a sequence of entries asynchronously.
       *
       * @param startEntry
       *          start entry id
       * @param maxCount
       *          the total entries count.
       * @param maxSize
       *          the total entries size.
       * @return an handle to the result of the operation
       */
      default CompletableFuture<LedgerEntries> batchReadAsync(long startEntry, int maxCount, long maxSize) {
          CompletableFuture<LedgerEntries> future = new CompletableFuture<>();
          future.completeExceptionally(new UnsupportedOperationException());
          return future;
      }
  
      /**
       * Read a sequence of entries synchronously.
       *
       * @param firstEntry
       *          id of first entry of sequence
       * @param lastEntry
       *          id of last entry of sequence, inclusive
       * @return the result of the operation
       */
      default LedgerEntries read(long firstEntry, long lastEntry) throws BKException, InterruptedException {
          return FutureUtils.<LedgerEntries, BKException>result(readAsync(firstEntry, lastEntry),
                                                                BKException.HANDLER);
      }
  
      /**
       *
       * @param startEntry
       *          start entry id
       * @param maxCount
       *          the total entries count.
       * @param maxSize
       *          the total entries size.
       * @return the result of the operation
       */
      default LedgerEntries batchRead(long startEntry, int maxCount, long maxSize)
              throws BKException, InterruptedException {
          return FutureUtils.result(batchReadAsync(startEntry, maxCount, maxSize), BKException.HANDLER);
      }
  
      /**
       * Read a sequence of entries asynchronously, allowing to read after the LastAddConfirmed range.
       * <br>This is the same of
       * {@link #read(long, long) }
       * but it lets the client read without checking the local value of LastAddConfirmed, so that it is possible to
       * read entries for which the writer has not received the acknowledge yet. <br>
       * For entries which are within the range 0..LastAddConfirmed BookKeeper guarantees that the writer has successfully
       * received the acknowledge.<br>
       * For entries outside that range it is possible that the writer never received the acknowledge
       * and so there is the risk that the reader is seeing entries before the writer and this could
       * result in a consistency issue in some cases.<br>
       * With this method you can even read entries before the LastAddConfirmed and entries after it with one call,
       * the expected consistency will be as described above for each subrange of ids.
       *
       * @param firstEntry
       *          id of first entry of sequence
       * @param lastEntry
       *          id of last entry of sequence, inclusive
       * @return an handle to the result of the operation
       *
       * @see #readAsync(long, long)
       * @see #readLastAddConfirmedAsync()
       */
      CompletableFuture<LedgerEntries> readUnconfirmedAsync(long firstEntry, long lastEntry);
  
      /**
       * Read a sequence of entries synchronously.
       *
       * @param firstEntry
       *          id of first entry of sequence
       * @param lastEntry
       *          id of last entry of sequence, inclusive
       * @return an handle to the result of the operation
       *
       * @see #readUnconfirmedAsync(long, long)
       */
      default LedgerEntries readUnconfirmed(long firstEntry, long lastEntry)
              throws BKException, InterruptedException {
          return FutureUtils.<LedgerEntries, BKException>result(readUnconfirmedAsync(firstEntry, lastEntry),
                                                                BKException.HANDLER);
      }
  
      /**
       * Obtains asynchronously the last confirmed write from a quorum of bookies. This
       * call obtains the last add confirmed each bookie has received for this ledger
       * and returns the maximum. If the ledger has been closed, the value returned by this
       * call may not correspond to the id of the last entry of the ledger, since it reads
       * the hint of bookies. Consequently, in the case the ledger has been closed, it may
       * return a different value than getLastAddConfirmed, which returns the local value
       * of the ledger handle.
       *
       * @return an handle to the result of the operation
       * @see #getLastAddConfirmed()
       */
      CompletableFuture<Long> readLastAddConfirmedAsync();
  
      /**
       * Obtains asynchronously the last confirmed write from a quorum of bookies.
       *
       * @return the result of the operation
       * @see #readLastAddConfirmedAsync()
       */
      default long readLastAddConfirmed() throws BKException, InterruptedException {
          return FutureUtils.<Long, BKException>result(readLastAddConfirmedAsync(),
                                                       BKException.HANDLER);
      }
  
  
      /**
       * Obtains asynchronously the last confirmed write from a quorum of bookies
       * but it doesn't wait all the responses from the quorum. It would callback
       * immediately if it received a LAC which is larger than current LAC.
       *
       * @return an handle to the result of the operation
       */
      CompletableFuture<Long> tryReadLastAddConfirmedAsync();
  
      /**
       * Obtains asynchronously the last confirmed write from a quorum of bookies
       * but it doesn't wait all the responses from the quorum.
       *
       * @return the result of the operation
       * @see #tryReadLastAddConfirmedAsync()
       */
      default long tryReadLastAddConfirmed() throws BKException, InterruptedException {
          return FutureUtils.<Long, BKException>result(tryReadLastAddConfirmedAsync(),
                                                       BKException.HANDLER);
      }
  
      /**
       * Get the last confirmed entry id on this ledger. It reads the local state of the ledger handle,
       * which is different from the {@link #readLastAddConfirmed()} call.
       *
       * <p>In the case the ledger is not closed and the client is a reader, it is necessary to
       * call {@link #readLastAddConfirmed()} to obtain a fresh value of last add confirmed entry id.
       *
       * @see #readLastAddConfirmed()
       *
       * @return the local value for LastAddConfirmed or -1L if no entry has been confirmed.
       */
      long getLastAddConfirmed();
  
      /**
       * Returns the length of the data written in this ledger so much, in bytes.
       *
       * @return the length of the data written in this ledger, in bytes.
       */
      long getLength();
  
      /**
       * Returns whether the ledger is sealed or not.
       *
       * <p>A ledger is sealed when either the client explicitly closes it ({@link WriteHandle#close()} or
       * {@link WriteAdvHandle#close()}) or another client explicitly open and recovery it
       * {@link OpenBuilder#withRecovery(boolean)}.
       *
       * <p>This method only checks the metadata cached locally. The metadata can be not update-to-date because
       * the metadata notification is delayed.
       *
       * @return true if the ledger is sealed, otherwise false.
       */
      boolean isClosed();
  
      /**
       * Asynchronous read specific entry and the latest last add confirmed.
       * If the next entryId is less than known last add confirmed, the call will read next entry directly.
       * If the next entryId is ahead of known last add confirmed, the call will issue a long poll read
       * to wait for the next entry <i>entryId</i>.
       *
       * @param entryId
       *          next entry id to read
       * @param timeOutInMillis
       *          timeout period to wait for the entry id to be available (for long poll only)
       *          if timeout for get the entry, it will return null entry.
       * @param parallel
       *          whether to issue the long poll reads in parallel
       * @return an handle to the result of the operation
       */
      CompletableFuture<LastConfirmedAndEntry> readLastAddConfirmedAndEntryAsync(long entryId,
                                                                                 long timeOutInMillis,
                                                                                 boolean parallel);
  
      /**
       * Asynchronous read specific entry and the latest last add confirmed.
       *
       * @param entryId
       *          next entry id to read
       * @param timeOutInMillis
       *          timeout period to wait for the entry id to be available (for long poll only)
       *          if timeout for get the entry, it will return null entry.
       * @param parallel
       *          whether to issue the long poll reads in parallel
       * @return the result of the operation
       * @see #readLastAddConfirmedAndEntry(long, long, boolean)
       */
      default LastConfirmedAndEntry readLastAddConfirmedAndEntry(long entryId,
                                                                 long timeOutInMillis,
                                                                 boolean parallel)
              throws BKException, InterruptedException {
          return FutureUtils.<LastConfirmedAndEntry, BKException>result(
                  readLastAddConfirmedAndEntryAsync(entryId, timeOutInMillis, parallel),
                  BKException.HANDLER);
      }
  
  }
  