Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
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.hadoop.hbase.regionserver;
 
 import java.util.List;
 
KeyValueScanner adaptor over the Reader. It also provides hooks into bloom filter things.
 
 public class StoreFileScanner implements KeyValueScanner {
   static final Log LOG = LogFactory.getLog(HStore.class);
 
   // the reader it comes from:
   private final StoreFile.Reader reader;
   private final HFileScanner hfs;
   private KeyValue cur = null;
 
   private boolean realSeekDone;
   private boolean delayedReseek;
   private KeyValue delayedSeekKV;
 
   private boolean enforceMVCC = false;
   private boolean hasMVCCInfo = false;
   // A flag represents whether could stop skipping KeyValues for MVCC
   // if have encountered the next row. Only used for reversed scan
   private boolean stopSkippingKVsIfNextRow = false;
 
   private static AtomicLong seekCount;
 
   private ScanQueryMatcher matcher;
   
   private long readPt;

  
Implements a KeyValueScanner on top of the specified org.apache.hadoop.hbase.io.hfile.HFileScanner

Parameters:
hfs HFile scanner
 
   public StoreFileScanner(StoreFile.Reader readerHFileScanner hfsboolean useMVCC,
       boolean hasMVCClong readPt) {
     this. = readPt;
     this. = reader;
     this. = hfs;
     this. = useMVCC;
     this. = hasMVCC;
   }

  
Return an array of scanners corresponding to the given set of store files.
 
       Collection<StoreFilefiles,
       boolean cacheBlocks,
       boolean usePreadlong readPtthrows IOException {
     return getScannersForStoreFiles(filescacheBlocks,
                                    usePreadfalsereadPt);
   }

  
Return an array of scanners corresponding to the given set of store files.
 
       Collection<StoreFilefilesboolean cacheBlocksboolean usePread,
       boolean isCompactionlong readPtthrows IOException {
     return getScannersForStoreFiles(filescacheBlocksusePreadisCompaction,
         nullreadPt);
  }

  
Return an array of scanners corresponding to the given set of store files, And set the ScanQueryMatcher for each store file scanner for further optimization
      Collection<StoreFilefilesboolean cacheBlocksboolean usePread,
      boolean isCompactionScanQueryMatcher matcherlong readPtthrows IOException {
    List<StoreFileScannerscanners = new ArrayList<StoreFileScanner>(
        files.size());
    for (StoreFile file : files) {
      StoreFile.Reader r = file.createReader();
      StoreFileScanner scanner = r.getStoreFileScanner(cacheBlocksusePread,
          isCompactionreadPt);
      scanner.setScanQueryMatcher(matcher);
      scanners.add(scanner);
    }
    return scanners;
  }
  public String toString() {
    return "StoreFileScanner[" + .toString() + ", cur=" +  + "]";
  }
  public KeyValue peek() {
    return ;
  }
  public KeyValue next() throws IOException {
    KeyValue retKey = ;
    try {
      // only seek if we aren't at the end. cur == null implies 'end'.
      if ( != null) {
        .next();
         = .getKeyValue();
        if ()
          skipKVsNewerThanReadpoint();
      }
    } catch(IOException e) {
      throw new IOException("Could not iterate " + thise);
    }
    return retKey;
  }
  public boolean seek(KeyValue keythrows IOException {
    if ( != null.incrementAndGet();
    try {
      try {
        if(!seekAtOrAfter(key)) {
          close();
          return false;
        }
         = .getKeyValue();
        return ! ? true : skipKVsNewerThanReadpoint();
      } finally {
         = true;
      }
    } catch (IOException ioe) {
      throw new IOException("Could not seek " + this + " to key " + keyioe);
    }
  }
  public boolean reseek(KeyValue keythrows IOException {
    if ( != null.incrementAndGet();
    try {
      try {
        if (!reseekAtOrAfter(key)) {
          close();
          return false;
        }
         = .getKeyValue();
        return ! ? true : skipKVsNewerThanReadpoint();
      } finally {
         = true;
      }
    } catch (IOException ioe) {
      throw new IOException("Could not reseek " + this + " to key " + key,
          ioe);
    }
  }
  protected boolean skipKVsNewerThanReadpoint() throws IOException {
    // We want to ignore all key-values that are newer than our current
    // readPoint
    KeyValue startKV = ;
    while(
        &&  != null
        && (.getMvccVersion() > )) {
      .next();
       = .getKeyValue();
      if (this.
          && getComparator().compareRows(.getBuffer(), .getRowOffset(),
              .getRowLength(), startKV.getBuffer(), startKV.getRowOffset(),
              startKV.getRowLength()) > 0) {
        return false;
      }
    }
    if ( == null) {
      close();
      return false;
    }
    // For the optimisation in HBASE-4346, we set the KV's memstoreTS to
    // 0, if it is older than all the scanners' read points. It is possible
    // that a newer KV's memstoreTS was reset to 0. But, there is an
    // older KV which was not reset to 0 (because it was
    // not old enough during flush). Make sure that we set it correctly now,
    // so that the comparision order does not change.
    if (.getMvccVersion() <= ) {
      .setMvccVersion(0);
    }
    return true;
  }
  public void close() {
    // Nothing to close on HFileScanner?
     = null;
  }

  

Parameters:
s
k
Returns:
false if not found or if k is after the end.
Throws:
java.io.IOException
  public static boolean seekAtOrAfter(HFileScanner sKeyValue k)
  throws IOException {
    int result = s.seekTo(k.getBuffer(), k.getKeyOffset(), k.getKeyLength());
    if(result < 0) {
      if (result == .) {
        // using faked key
        return true;
      }
      // Passed KV is smaller than first KV in file, work from start of file
      return s.seekTo();
    } else if(result > 0) {
      // Passed KV is larger than current KV in file, if there is a next
      // it is the "after", if not then this scanner is done.
      return s.next();
    }
    // Seeked to the exact key
    return true;
  }
  static boolean reseekAtOrAfter(HFileScanner sKeyValue k)
  throws IOException {
    //This function is similar to seekAtOrAfter function
    int result = s.reseekTo(k.getBuffer(), k.getKeyOffset(), k.getKeyLength());
    if (result <= 0) {
      if (result == .) {
        // using faked key
        return true;
      }
      // If up to now scanner is not seeked yet, this means passed KV is smaller
      // than first KV in file, and it is the first time we seek on this file.
      // So we also need to work from the start of file.
      if (!s.isSeeked()) {
        return  s.seekTo();
      }
      return true;
    }
    // passed KV is larger than current KV in file, if there is a next
    // it is after, if not then this scanner is done.
    return s.next();
  }
  public long getSequenceID() {
    return .getSequenceID();
  }

  
Pretend we have done a seek but don't do it yet, if possible. The hope is that we find requested columns in more recent files and won't have to seek in older files. Creates a fake key/value with the given row/column and the highest (most recent) possible timestamp we might get from this file. When users of such "lazy scanner" need to know the next KV precisely (e.g. when this scanner is at the top of the heap), they run enforceSeek().

Note that this function does guarantee that the current KV of this scanner will be advanced to at least the given KV. Because of this, it does have to do a real seek in cases when the seek timestamp is older than the highest timestamp of the file, e.g. when we are trying to seek to the next row/column and use OLDEST_TIMESTAMP in the seek key.

  public boolean requestSeek(KeyValue kvboolean forwardboolean useBloom)
      throws IOException {
    if (kv.getFamilyLength() == 0) {
      useBloom = false;
    }
    boolean haveToSeek = true;
    if (useBloom) {
      // check ROWCOL Bloom filter first.
      if (.getBloomFilterType() == .) {
        haveToSeek = .passesGeneralBloomFilter(kv.getBuffer(),
            kv.getRowOffset(), kv.getRowLength(), kv.getBuffer(),
            kv.getQualifierOffset(), kv.getQualifierLength());
      } else if (this. != null && !.hasNullColumnInQuery() &&
          (kv.isDeleteFamily() || kv.isDeleteFamilyVersion())) {
        // if there is no such delete family kv in the store file,
        // then no need to seek.
        haveToSeek = .passesDeleteFamilyBloomFilter(kv.getBuffer(),
            kv.getRowOffset(), kv.getRowLength());
      }
    }
     = forward;
     = kv;
    if (haveToSeek) {
      // This row/column might be in this store file (or we did not use the
      // Bloom filter), so we still need to seek.
       = false;
      long maxTimestampInFile = .getMaxTimestamp();
      long seekTimestamp = kv.getTimestamp();
      if (seekTimestamp > maxTimestampInFile) {
        // Create a fake key that is not greater than the real next key.
        // (Lower timestamps correspond to higher KVs.)
        // To understand this better, consider that we are asked to seek to
        // a higher timestamp than the max timestamp in this file. We know that
        // the next point when we have to consider this file again is when we
        // pass the max timestamp of this file (with the same row/column).
         = kv.createFirstOnRowColTS(maxTimestampInFile);
      } else {
        // This will be the case e.g. when we need to seek to the next
        // row/column, and we don't know exactly what they are, so we set the
        // seek key's timestamp to OLDEST_TIMESTAMP to skip the rest of this
        // row/column.
        enforceSeek();
      }
      return  != null;
    }
    // Multi-column Bloom filter optimization.
    // Create a fake key/value, so that this scanner only bubbles up to the top
    // of the KeyValueHeap in StoreScanner after we scanned this row/column in
    // all other store files. The query matcher will then just skip this fake
    // key/value and the store scanner will progress to the next column. This
    // is obviously not a "real real" seek, but unlike the fake KV earlier in
    // this method, we want this to be propagated to ScanQueryMatcher.
     = kv.createLastOnRowCol();
     = true;
    return true;
  }
    return ;
  }
    return .getComparator();
  }
  public boolean realSeekDone() {
    return ;
  }
  public void enforceSeek() throws IOException {
    if ()
      return;
    if () {
      reseek();
    } else {
      seek();
    }
  }
  public void setScanQueryMatcher(ScanQueryMatcher matcher) {
    this. = matcher;
  }
  public boolean isFileScanner() {
    return true;
  }
  // Test methods
  static final long getSeekCount() {
    return .get();
  }
  static final void instrument() {
     = new AtomicLong();
  }
  public boolean shouldUseScanner(Scan scanSortedSet<byte[]> columnslong oldestUnexpiredTS) {
    return .passesTimerangeFilter(scanoldestUnexpiredTS)
        && .passesKeyRangeFilter(scan) && .passesBloomFilter(scancolumns);
  }
  public boolean seekToPreviousRow(KeyValue keythrows IOException {
    try {
      try {
        KeyValue seekKey = KeyValue.createFirstOnRow(key.getRow());
        if ( != null.incrementAndGet();
        if (!.seekBefore(seekKey.getBuffer(), seekKey.getKeyOffset(),
            seekKey.getKeyLength())) {
          close();
          return false;
        }
        KeyValue firstKeyOfPreviousRow = KeyValue.createFirstOnRow(
            .getKeyValue().getRow());
        if ( != null.incrementAndGet();
        if (!seekAtOrAfter(firstKeyOfPreviousRow)) {
          close();
          return false;
        }
         = .getKeyValue();
        this. = true;
        boolean resultOfSkipKVs;
        try {
          resultOfSkipKVs = skipKVsNewerThanReadpoint();
        } finally {
          this. = false;
        }
        if (!resultOfSkipKVs
            || getComparator().compareRows(.getBuffer(), .getRowOffset(),
                .getRowLength(), firstKeyOfPreviousRow.getBuffer(),
                firstKeyOfPreviousRow.getRowOffset(),
                firstKeyOfPreviousRow.getRowLength()) > 0) {
          return seekToPreviousRow(firstKeyOfPreviousRow);
        }
        return true;
      } finally {
         = true;
      }
    } catch (IOException ioe) {
      throw new IOException("Could not seekToPreviousRow " + this + " to key "
          + keyioe);
    }
  }
  public boolean seekToLastRow() throws IOException {
    byte[] lastRow = .getLastRowKey();
    if (lastRow == null) {
      return false;
    }
    KeyValue seekKey = KeyValue.createFirstOnRow(lastRow);
    if (seek(seekKey)) {
      return true;
    } else {
      return seekToPreviousRow(seekKey);
    }
  }
  public boolean backwardSeek(KeyValue keythrows IOException {
    seek(key);
    if ( == null
            .getRowLength(), key.getRowArray(), key.getRowOffset(),
            key.getRowLength()) > 0) {
      return seekToPreviousRow(key);
    }
    return true;
  }
New to GrepCode? Check out our FAQ X