001/**
002 *
003 * Licensed to the Apache Software Foundation (ASF) under one
004 * or more contributor license agreements.  See the NOTICE file
005 * distributed with this work for additional information
006 * regarding copyright ownership.  The ASF licenses this file
007 * to you under the Apache License, Version 2.0 (the
008 * "License"); you may not use this file except in compliance
009 * with the License.  You may obtain a copy of the License at
010 *
011 *     http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing, software
014 * distributed under the License is distributed on an "AS IS" BASIS,
015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016 * See the License for the specific language governing permissions and
017 * limitations under the License.
018 */
019package org.apache.hadoop.hbase.regionserver;
020
021import java.io.IOException;
022import java.util.List;
023import java.util.NavigableSet;
024
025import org.apache.hadoop.hbase.Cell;
026import org.apache.hadoop.hbase.client.Scan;
027import org.apache.hadoop.hbase.mob.MobUtils;
028import org.apache.yetus.audience.InterfaceAudience;
029
030/**
031 * ReversedMobStoreScanner extends from ReversedStoreScanner, and is used to support
032 * reversed scanning in both the memstore and the MOB store.
033 *
034 */
035@InterfaceAudience.Private
036public class ReversedMobStoreScanner extends ReversedStoreScanner {
037
038  private boolean cacheMobBlocks = false;
039  private boolean rawMobScan = false;
040  private boolean readEmptyValueOnMobCellMiss = false;
041  protected final HMobStore mobStore;
042
043  ReversedMobStoreScanner(HStore store, ScanInfo scanInfo, Scan scan, NavigableSet<byte[]> columns,
044      long readPt) throws IOException {
045    super(store, scanInfo, scan, columns, readPt);
046    cacheMobBlocks = MobUtils.isCacheMobBlocks(scan);
047    rawMobScan = MobUtils.isRawMobScan(scan);
048    readEmptyValueOnMobCellMiss = MobUtils.isReadEmptyValueOnMobCellMiss(scan);
049    if (!(store instanceof HMobStore)) {
050      throw new IllegalArgumentException("The store " + store + " is not a HMobStore");
051    }
052    mobStore = (HMobStore) store;
053  }
054
055  /**
056   * Firstly reads the cells from the HBase. If the cell is a reference cell (which has the
057   * reference tag), the scanner need seek this cell from the mob file, and use the cell found
058   * from the mob file as the result.
059   */
060  @Override
061  public boolean next(List<Cell> outResult, ScannerContext ctx) throws IOException {
062    boolean result = super.next(outResult, ctx);
063    if (!rawMobScan) {
064      // retrieve the mob data
065      if (outResult.isEmpty()) {
066        return result;
067      }
068      long mobKVCount = 0;
069      long mobKVSize = 0;
070      for (int i = 0; i < outResult.size(); i++) {
071        Cell cell = outResult.get(i);
072        if (MobUtils.isMobReferenceCell(cell)) {
073          Cell mobCell = mobStore
074            .resolve(cell, cacheMobBlocks, readPt, readEmptyValueOnMobCellMiss);
075          mobKVCount++;
076          mobKVSize += mobCell.getValueLength();
077          outResult.set(i, mobCell);
078        }
079      }
080      mobStore.updateMobScanCellsCount(mobKVCount);
081      mobStore.updateMobScanCellsSize(mobKVSize);
082    }
083    return result;
084  }
085}