/**
  * Find the key range for bucket files.
  *
  * @param reader the reader
  * @param options the options for reading with
  * @throws IOException
  */
 private void discoverKeyBounds(Reader reader, Reader.Options options) throws IOException {
   RecordIdentifier[] keyIndex = OrcRecordUpdater.parseKeyIndex(reader);
   long offset = options.getOffset();
   long maxOffset = options.getMaxOffset();
   int firstStripe = 0;
   int stripeCount = 0;
   boolean isTail = true;
   List<StripeInformation> stripes = reader.getStripes();
   for (StripeInformation stripe : stripes) {
     if (offset > stripe.getOffset()) {
       firstStripe += 1;
     } else if (maxOffset > stripe.getOffset()) {
       stripeCount += 1;
     } else {
       isTail = false;
       break;
     }
   }
   if (firstStripe != 0) {
     minKey = keyIndex[firstStripe - 1];
   }
   if (!isTail) {
     maxKey = keyIndex[firstStripe + stripeCount - 1];
   }
 }
 /**
  * Find the key range for original bucket files.
  *
  * @param reader the reader
  * @param bucket the bucket number we are reading
  * @param options the options for reading with
  * @throws IOException
  */
 private void discoverOriginalKeyBounds(Reader reader, int bucket, Reader.Options options)
     throws IOException {
   long rowLength = 0;
   long rowOffset = 0;
   long offset = options.getOffset();
   long maxOffset = options.getMaxOffset();
   boolean isTail = true;
   for (StripeInformation stripe : reader.getStripes()) {
     if (offset > stripe.getOffset()) {
       rowOffset += stripe.getNumberOfRows();
     } else if (maxOffset > stripe.getOffset()) {
       rowLength += stripe.getNumberOfRows();
     } else {
       isTail = false;
       break;
     }
   }
   if (rowOffset > 0) {
     minKey = new RecordIdentifier(0, bucket, rowOffset - 1);
   }
   if (!isTail) {
     maxKey = new RecordIdentifier(0, bucket, rowOffset + rowLength - 1);
   }
 }