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.ExtendedCell; 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(ExtendedCell 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 ExtendedCell getNextKeyHint(ExtendedCell 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(ExtendedCell 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}