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.PrivateCellUtil;
024import org.apache.hadoop.hbase.KeepDeletedCells;
025import org.apache.yetus.audience.InterfaceAudience;
026import org.apache.hadoop.hbase.client.Scan;
027import org.apache.hadoop.hbase.regionserver.ScanInfo;
028
029/**
030 * Query matcher for normal user scan.
031 */
032@InterfaceAudience.Private
033public abstract class NormalUserScanQueryMatcher extends UserScanQueryMatcher {
034
035  /** Keeps track of deletes */
036  private final DeleteTracker deletes;
037
038  /** True if we are doing a 'Get' Scan. Every Get is actually a one-row Scan. */
039  private final boolean get;
040
041  /** whether time range queries can see rows "behind" a delete */
042  protected final boolean seePastDeleteMarkers;
043
044  protected NormalUserScanQueryMatcher(Scan scan, ScanInfo scanInfo, ColumnTracker columns,
045      boolean hasNullColumn, DeleteTracker deletes, long oldestUnexpiredTS, long now) {
046    super(scan, scanInfo, columns, hasNullColumn, oldestUnexpiredTS, now);
047    this.deletes = deletes;
048    this.get = scan.isGetScan();
049    this.seePastDeleteMarkers = scanInfo.getKeepDeletedCells() != KeepDeletedCells.FALSE;
050  }
051
052  @Override
053  public void beforeShipped() throws IOException {
054    super.beforeShipped();
055    deletes.beforeShipped();
056  }
057
058  @Override
059  public MatchCode match(Cell cell) throws IOException {
060    if (filter != null && filter.filterAllRemaining()) {
061      return MatchCode.DONE_SCAN;
062    }
063    MatchCode returnCode = preCheck(cell);
064    if (returnCode != null) {
065      return returnCode;
066    }
067    long timestamp = cell.getTimestamp();
068    byte typeByte = cell.getTypeByte();
069    if (PrivateCellUtil.isDelete(typeByte)) {
070      boolean includeDeleteMarker = seePastDeleteMarkers ? tr.withinTimeRange(timestamp)
071          : tr.withinOrAfterTimeRange(timestamp);
072      if (includeDeleteMarker) {
073        this.deletes.add(cell);
074      }
075      return MatchCode.SKIP;
076    }
077    returnCode = checkDeleted(deletes, cell);
078    if (returnCode != null) {
079      return returnCode;
080    }
081    return matchColumn(cell, timestamp, typeByte);
082  }
083
084  @Override
085  protected void reset() {
086    deletes.reset();
087  }
088
089  @Override
090  protected boolean isGet() {
091    return get;
092  }
093
094  public static NormalUserScanQueryMatcher create(Scan scan, ScanInfo scanInfo,
095      ColumnTracker columns, DeleteTracker deletes, boolean hasNullColumn, long oldestUnexpiredTS,
096      long now) throws IOException {
097    if (scan.isReversed()) {
098      if (scan.includeStopRow()) {
099        return new NormalUserScanQueryMatcher(scan, scanInfo, columns, hasNullColumn, deletes,
100            oldestUnexpiredTS, now) {
101
102          @Override
103          protected boolean moreRowsMayExistsAfter(int cmpToStopRow) {
104            return cmpToStopRow >= 0;
105          }
106        };
107      } else {
108        return new NormalUserScanQueryMatcher(scan, scanInfo, columns, hasNullColumn, deletes,
109            oldestUnexpiredTS, now) {
110
111          @Override
112          protected boolean moreRowsMayExistsAfter(int cmpToStopRow) {
113            return cmpToStopRow > 0;
114          }
115        };
116      }
117    } else {
118      if (scan.includeStopRow()) {
119        return new NormalUserScanQueryMatcher(scan, scanInfo, columns, hasNullColumn, deletes,
120            oldestUnexpiredTS, now) {
121
122          @Override
123          protected boolean moreRowsMayExistsAfter(int cmpToStopRow) {
124            return cmpToStopRow <= 0;
125          }
126        };
127      } else {
128        return new NormalUserScanQueryMatcher(scan, scanInfo, columns, hasNullColumn, deletes,
129            oldestUnexpiredTS, now) {
130
131          @Override
132          protected boolean moreRowsMayExistsAfter(int cmpToStopRow) {
133            return cmpToStopRow < 0;
134          }
135        };
136      }
137    }
138  }
139}