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 * Scanner scans both the memstore and the MOB Store. Coalesce KeyValue stream into
032 * {@code List<KeyValue>} for a single row.
033 */
034@InterfaceAudience.Private
035public class MobStoreScanner extends StoreScanner {
036
037  private boolean cacheMobBlocks = false;
038  private boolean rawMobScan = false;
039  private boolean readEmptyValueOnMobCellMiss = false;
040  private final HMobStore mobStore;
041
042  public MobStoreScanner(HStore store, ScanInfo scanInfo, Scan scan,
043      final NavigableSet<byte[]> columns, long readPt) throws IOException {
044    super(store, scanInfo, scan, columns, readPt);
045    cacheMobBlocks = MobUtils.isCacheMobBlocks(scan);
046    rawMobScan = MobUtils.isRawMobScan(scan);
047    readEmptyValueOnMobCellMiss = MobUtils.isReadEmptyValueOnMobCellMiss(scan);
048    if (!(store instanceof HMobStore)) {
049      throw new IllegalArgumentException("The store " + store + " is not a HMobStore");
050    }
051    mobStore = (HMobStore) store;
052  }
053
054  /**
055   * Firstly reads the cells from the HBase. If the cell are a reference cell (which has the
056   * reference tag), the scanner need seek this cell from the mob file, and use the cell found
057   * from the mob file as the result.
058   */
059  @Override
060  public boolean next(List<Cell> outResult, ScannerContext ctx) throws IOException {
061    boolean result = super.next(outResult, ctx);
062    if (!rawMobScan) {
063      // retrieve the mob data
064      if (outResult.isEmpty()) {
065        return result;
066      }
067      long mobKVCount = 0;
068      long mobKVSize = 0;
069      for (int i = 0; i < outResult.size(); i++) {
070        Cell cell = outResult.get(i);
071        if (MobUtils.isMobReferenceCell(cell)) {
072          Cell mobCell = mobStore
073            .resolve(cell, cacheMobBlocks, readPt, readEmptyValueOnMobCellMiss);
074          mobKVCount++;
075          mobKVSize += mobCell.getValueLength();
076          outResult.set(i, mobCell);
077        }
078      }
079      mobStore.updateMobScanCellsCount(mobKVCount);
080      mobStore.updateMobScanCellsSize(mobKVSize);
081    }
082    return result;
083  }
084}