1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.hadoop.hbase.regionserver.querymatcher;
19
20 import java.io.IOException;
21 import java.util.NavigableSet;
22
23 import org.apache.hadoop.hbase.Cell;
24 import org.apache.hadoop.hbase.KeyValueUtil;
25 import org.apache.hadoop.hbase.classification.InterfaceAudience;
26 import org.apache.hadoop.hbase.client.Scan;
27 import org.apache.hadoop.hbase.filter.Filter;
28 import org.apache.hadoop.hbase.filter.Filter.ReturnCode;
29 import org.apache.hadoop.hbase.io.TimeRange;
30 import org.apache.hadoop.hbase.regionserver.RegionCoprocessorHost;
31 import org.apache.hadoop.hbase.regionserver.ScanInfo;
32
33
34
35
36
37
38
39
40
41
42
43 @InterfaceAudience.Private
44 public abstract class UserScanQueryMatcher extends ScanQueryMatcher {
45
46 protected final boolean hasNullColumn;
47
48 protected final Filter filter;
49
50 protected final byte[] stopRow;
51
52 protected final TimeRange tr;
53
54 private static Cell createStartKey(Scan scan, ScanInfo scanInfo) {
55 if (scan.includeStartRow()) {
56 return createStartKeyFromRow(scan.getStartRow(), scanInfo);
57 } else {
58 return KeyValueUtil.createLastOnRow(scan.getStartRow());
59 }
60 }
61
62 protected UserScanQueryMatcher(Scan scan, ScanInfo scanInfo, ColumnTracker columns,
63 boolean hasNullColumn, long oldestUnexpiredTS, long now) {
64 super(createStartKey(scan, scanInfo), scanInfo, columns, oldestUnexpiredTS, now);
65 this.hasNullColumn = hasNullColumn;
66 this.filter = scan.getFilter();
67 this.stopRow = scan.getStopRow();
68 TimeRange timeRange = scan.getColumnFamilyTimeRange().get(scanInfo.getFamily());
69 if (timeRange == null) {
70 this.tr = scan.getTimeRange();
71 } else {
72 this.tr = timeRange;
73 }
74 }
75
76 @Override
77 public boolean hasNullColumnInQuery() {
78 return hasNullColumn;
79 }
80
81 @Override
82 public boolean isUserScan() {
83 return true;
84 }
85
86 @Override
87 public Filter getFilter() {
88 return filter;
89 }
90
91 @Override
92 public Cell getNextKeyHint(Cell cell) throws IOException {
93 if (filter == null) {
94 return null;
95 } else {
96 return filter.getNextCellHint(cell);
97 }
98 }
99
100 protected final MatchCode matchColumn(Cell cell, long timestamp, byte typeByte)
101 throws IOException {
102 int tsCmp = tr.compare(timestamp);
103 if (tsCmp > 0) {
104 return MatchCode.SKIP;
105 }
106 int qualifierOffset = cell.getQualifierOffset();
107 int qualifierLength = cell.getQualifierLength();
108 if (tsCmp < 0) {
109 return columns.getNextRowOrNextColumn(cell.getQualifierArray(), qualifierOffset,
110 qualifierLength);
111 }
112
113 MatchCode colChecker = columns.checkColumn(cell.getQualifierArray(), qualifierOffset,
114 qualifierLength, typeByte);
115 if (colChecker != MatchCode.INCLUDE) {
116 return colChecker;
117 }
118 ReturnCode filterResponse = ReturnCode.SKIP;
119
120 if (filter != null) {
121
122 filterResponse = filter.filterKeyValue(cell);
123 switch (filterResponse) {
124 case SKIP:
125 return MatchCode.SKIP;
126 case NEXT_COL:
127 return columns.getNextRowOrNextColumn(cell.getQualifierArray(), qualifierOffset,
128 qualifierLength);
129 case NEXT_ROW:
130 return MatchCode.SEEK_NEXT_ROW;
131 case SEEK_NEXT_USING_HINT:
132 return MatchCode.SEEK_NEXT_USING_HINT;
133 default:
134
135 break;
136 }
137 }
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157 colChecker = columns.checkVersions(cell.getQualifierArray(), qualifierOffset, qualifierLength,
158 timestamp, typeByte, false);
159 return (filterResponse == ReturnCode.INCLUDE_AND_NEXT_COL && colChecker == MatchCode.INCLUDE)
160 ? MatchCode.INCLUDE_AND_SEEK_NEXT_COL : colChecker;
161 }
162
163 protected abstract boolean isGet();
164
165 protected abstract boolean moreRowsMayExistsAfter(int cmpToStopRow);
166
167 @Override
168 public boolean moreRowsMayExistAfter(Cell cell) {
169
170
171
172 if (isGet()) {
173 return false;
174 }
175
176
177
178 if (this.stopRow == null || this.stopRow.length == 0) {
179 return true;
180 }
181 return moreRowsMayExistsAfter(rowComparator.compareRows(cell, stopRow, 0, stopRow.length));
182 }
183
184 public static UserScanQueryMatcher create(Scan scan, ScanInfo scanInfo,
185 NavigableSet<byte[]> columns, long oldestUnexpiredTS, long now,
186 RegionCoprocessorHost regionCoprocessorHost) throws IOException {
187 int maxVersions = scan.isRaw() ? scan.getMaxVersions()
188 : Math.min(scan.getMaxVersions(), scanInfo.getMaxVersions());
189 boolean hasNullColumn;
190 ColumnTracker columnTracker;
191 if (columns == null || columns.size() == 0) {
192
193 hasNullColumn = true;
194
195 columnTracker = new ScanWildcardColumnTracker(scanInfo.getMinVersions(), maxVersions,
196 oldestUnexpiredTS);
197 } else {
198
199
200
201 hasNullColumn = columns.first().length == 0;
202 columnTracker = new ExplicitColumnTracker(columns, scanInfo.getMinVersions(), maxVersions,
203 oldestUnexpiredTS);
204 }
205 if (scan.isRaw()) {
206 return RawScanQueryMatcher.create(scan, scanInfo, columnTracker, hasNullColumn,
207 oldestUnexpiredTS, now);
208 } else {
209 return NormalUserScanQueryMatcher.create(scan, scanInfo, columnTracker, hasNullColumn,
210 oldestUnexpiredTS, now, regionCoprocessorHost);
211 }
212 }
213 }