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 static org.apache.hadoop.hbase.HConstants.EMPTY_START_ROW;
021
022import java.io.IOException;
023import org.apache.hadoop.hbase.Cell;
024import org.apache.hadoop.hbase.KeepDeletedCells;
025import org.apache.hadoop.hbase.filter.Filter;
026import org.apache.hadoop.hbase.regionserver.RegionCoprocessorHost;
027import org.apache.hadoop.hbase.regionserver.ScanInfo;
028import org.apache.hadoop.hbase.regionserver.ScanType;
029import org.apache.hadoop.hbase.util.Pair;
030import org.apache.yetus.audience.InterfaceAudience;
031
032/**
033 * Query matcher for compaction.
034 */
035@InterfaceAudience.Private
036public abstract class CompactionScanQueryMatcher extends ScanQueryMatcher {
037
038  /** readPoint over which the KVs are unconditionally included */
039  protected final long maxReadPointToTrackVersions;
040
041  /** Keeps track of deletes */
042  protected final DeleteTracker deletes;
043
044  /** whether to return deleted rows */
045  protected final KeepDeletedCells keepDeletedCells;
046
047  protected CompactionScanQueryMatcher(ScanInfo scanInfo, DeleteTracker deletes,
048    ColumnTracker columnTracker, long readPointToUse, long oldestUnexpiredTS, long now) {
049    super(createStartKeyFromRow(EMPTY_START_ROW, scanInfo), scanInfo, columnTracker,
050      oldestUnexpiredTS, now);
051    this.maxReadPointToTrackVersions = readPointToUse;
052    this.deletes = deletes;
053    this.keepDeletedCells = scanInfo.getKeepDeletedCells();
054  }
055
056  @Override
057  public void beforeShipped() throws IOException {
058    super.beforeShipped();
059    deletes.beforeShipped();
060  }
061
062  @Override
063  public boolean hasNullColumnInQuery() {
064    return true;
065  }
066
067  @Override
068  public boolean isUserScan() {
069    return false;
070  }
071
072  @Override
073  public boolean moreRowsMayExistAfter(Cell cell) {
074    return true;
075  }
076
077  @Override
078  public Filter getFilter() {
079    // no filter when compaction
080    return null;
081  }
082
083  @Override
084  public Cell getNextKeyHint(Cell cell) throws IOException {
085    // no filter, so no key hint.
086    return null;
087  }
088
089  @Override
090  protected void reset() {
091    deletes.reset();
092  }
093
094  protected final void trackDelete(Cell cell) {
095    // If keepDeletedCells is true, then we only remove cells by versions or TTL during
096    // compaction, so we do not need to track delete here.
097    // If keepDeletedCells is TTL and the delete marker is expired, then we can make sure that the
098    // minVerions is larger than 0(otherwise we will just return at preCheck). So here we still
099    // need to track the delete marker to see if it masks some cells.
100    if (
101      keepDeletedCells == KeepDeletedCells.FALSE
102        || (keepDeletedCells == KeepDeletedCells.TTL && cell.getTimestamp() < oldestUnexpiredTS)
103    ) {
104      deletes.add(cell);
105    }
106  }
107
108  public static CompactionScanQueryMatcher create(ScanInfo scanInfo, ScanType scanType,
109    long readPointToUse, long earliestPutTs, long oldestUnexpiredTS, long now,
110    byte[] dropDeletesFromRow, byte[] dropDeletesToRow, RegionCoprocessorHost regionCoprocessorHost)
111    throws IOException {
112    Pair<DeleteTracker, ColumnTracker> trackers =
113      getTrackers(regionCoprocessorHost, null, scanInfo, oldestUnexpiredTS, null);
114    DeleteTracker deleteTracker = trackers.getFirst();
115    ColumnTracker columnTracker = trackers.getSecond();
116    if (dropDeletesFromRow == null) {
117      if (scanType == ScanType.COMPACT_RETAIN_DELETES) {
118        if (scanInfo.isNewVersionBehavior()) {
119          return new IncludeAllCompactionQueryMatcher(scanInfo, deleteTracker, columnTracker,
120            readPointToUse, oldestUnexpiredTS, now);
121        } else {
122          return new MinorCompactionScanQueryMatcher(scanInfo, deleteTracker, columnTracker,
123            readPointToUse, oldestUnexpiredTS, now);
124        }
125      } else {
126        return new MajorCompactionScanQueryMatcher(scanInfo, deleteTracker, columnTracker,
127          readPointToUse, earliestPutTs, oldestUnexpiredTS, now);
128      }
129    } else {
130      return new StripeCompactionScanQueryMatcher(scanInfo, deleteTracker, columnTracker,
131        readPointToUse, earliestPutTs, oldestUnexpiredTS, now, dropDeletesFromRow,
132        dropDeletesToRow);
133    }
134  }
135}