001/**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase.regionserver.querymatcher;
019
020import java.io.IOException;
021
022import org.apache.hadoop.hbase.Cell;
023import org.apache.hadoop.hbase.CellUtil;
024import org.apache.hadoop.hbase.PrivateCellUtil;
025import org.apache.hadoop.hbase.KeepDeletedCells;
026import org.apache.yetus.audience.InterfaceAudience;
027import org.apache.hadoop.hbase.client.Scan;
028import org.apache.hadoop.hbase.regionserver.ScanInfo;
029
030/**
031 * Query matcher for normal user scan.
032 */
033@InterfaceAudience.Private
034public abstract class NormalUserScanQueryMatcher extends UserScanQueryMatcher {
035
036  /** Keeps track of deletes */
037  private final DeleteTracker deletes;
038
039  /** True if we are doing a 'Get' Scan. Every Get is actually a one-row Scan. */
040  private final boolean get;
041
042  /** whether time range queries can see rows "behind" a delete */
043  protected final boolean seePastDeleteMarkers;
044
045  protected NormalUserScanQueryMatcher(Scan scan, ScanInfo scanInfo, ColumnTracker columns,
046      boolean hasNullColumn, DeleteTracker deletes, long oldestUnexpiredTS, long now) {
047    super(scan, scanInfo, columns, hasNullColumn, oldestUnexpiredTS, now);
048    this.deletes = deletes;
049    this.get = scan.isGetScan();
050    this.seePastDeleteMarkers = scanInfo.getKeepDeletedCells() != KeepDeletedCells.FALSE;
051  }
052
053  @Override
054  public void beforeShipped() throws IOException {
055    super.beforeShipped();
056    deletes.beforeShipped();
057  }
058
059  @Override
060  public MatchCode match(Cell cell) throws IOException {
061    if (filter != null && filter.filterAllRemaining()) {
062      return MatchCode.DONE_SCAN;
063    }
064    MatchCode returnCode = preCheck(cell);
065    if (returnCode != null) {
066      return returnCode;
067    }
068    long timestamp = cell.getTimestamp();
069    byte typeByte = cell.getTypeByte();
070    if (PrivateCellUtil.isDelete(typeByte)) {
071      boolean includeDeleteMarker = seePastDeleteMarkers ? tr.withinTimeRange(timestamp)
072          : tr.withinOrAfterTimeRange(timestamp);
073      if (includeDeleteMarker) {
074        this.deletes.add(cell);
075      }
076      return MatchCode.SKIP;
077    }
078    returnCode = checkDeleted(deletes, cell);
079    if (returnCode != null) {
080      return returnCode;
081    }
082    return matchColumn(cell, timestamp, typeByte);
083  }
084
085  @Override
086  protected void reset() {
087    deletes.reset();
088  }
089
090  @Override
091  protected boolean isGet() {
092    return get;
093  }
094
095  public static NormalUserScanQueryMatcher create(Scan scan, ScanInfo scanInfo,
096      ColumnTracker columns, DeleteTracker deletes, boolean hasNullColumn, long oldestUnexpiredTS,
097      long now) throws IOException {
098    if (scan.isReversed()) {
099      if (scan.includeStopRow()) {
100        return new NormalUserScanQueryMatcher(scan, scanInfo, columns, hasNullColumn, deletes,
101            oldestUnexpiredTS, now) {
102
103          @Override
104          protected boolean moreRowsMayExistsAfter(int cmpToStopRow) {
105            return cmpToStopRow >= 0;
106          }
107        };
108      } else {
109        return new NormalUserScanQueryMatcher(scan, scanInfo, columns, hasNullColumn, deletes,
110            oldestUnexpiredTS, now) {
111
112          @Override
113          protected boolean moreRowsMayExistsAfter(int cmpToStopRow) {
114            return cmpToStopRow > 0;
115          }
116        };
117      }
118    } else {
119      if (scan.includeStopRow()) {
120        return new NormalUserScanQueryMatcher(scan, scanInfo, columns, hasNullColumn, deletes,
121            oldestUnexpiredTS, now) {
122
123          @Override
124          protected boolean moreRowsMayExistsAfter(int cmpToStopRow) {
125            return cmpToStopRow <= 0;
126          }
127        };
128      } else {
129        return new NormalUserScanQueryMatcher(scan, scanInfo, columns, hasNullColumn, deletes,
130            oldestUnexpiredTS, now) {
131
132          @Override
133          protected boolean moreRowsMayExistsAfter(int cmpToStopRow) {
134            return cmpToStopRow < 0;
135          }
136        };
137      }
138    }
139  }
140}