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