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