1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.hadoop.hbase.regionserver;
21
22 import java.util.NavigableSet;
23
24 import org.apache.hadoop.hbase.HConstants;
25 import org.apache.hadoop.hbase.KeyValue;
26 import org.apache.hadoop.hbase.regionserver.ScanQueryMatcher.MatchCode;
27 import org.apache.hadoop.hbase.util.Bytes;
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 public class ExplicitColumnTracker implements ColumnTracker {
53
54 private final int maxVersions;
55 private final int minVersions;
56
57
58
59
60
61
62 private final ColumnCount[] columns;
63 private int index;
64 private ColumnCount column;
65
66
67 private long latestTSOfCurrentColumn;
68 private long oldestStamp;
69
70
71
72
73
74
75
76
77
78
79 public ExplicitColumnTracker(NavigableSet<byte[]> columns, int minVersions,
80 int maxVersions, long oldestUnexpiredTS) {
81 this.maxVersions = maxVersions;
82 this.minVersions = minVersions;
83 this.oldestStamp = oldestUnexpiredTS;
84 this.columns = new ColumnCount[columns.size()];
85 int i=0;
86 for(byte [] column : columns) {
87 this.columns[i++] = new ColumnCount(column);
88 }
89 reset();
90 }
91
92
93
94
95 public boolean done() {
96 return this.index >= columns.length;
97 }
98
99 public ColumnCount getColumnHint() {
100 return this.column;
101 }
102
103
104
105
106 @Override
107 public ScanQueryMatcher.MatchCode checkColumn(byte [] bytes, int offset,
108 int length, byte type) {
109
110
111 assert !KeyValue.isDelete(type);
112 do {
113
114 if(done()) {
115 return ScanQueryMatcher.MatchCode.SEEK_NEXT_ROW;
116 }
117
118
119 if(this.column == null) {
120 return ScanQueryMatcher.MatchCode.SEEK_NEXT_ROW;
121 }
122
123
124 int ret = Bytes.compareTo(column.getBuffer(), column.getOffset(),
125 column.getLength(), bytes, offset, length);
126
127
128
129 if(ret == 0) {
130 return ScanQueryMatcher.MatchCode.INCLUDE;
131 }
132
133 resetTS();
134
135 if (ret > 0) {
136
137
138 return ScanQueryMatcher.MatchCode.SEEK_NEXT_COL;
139 }
140
141
142
143
144
145 if (ret <= -1) {
146 ++this.index;
147 if (done()) {
148
149 return ScanQueryMatcher.MatchCode.SEEK_NEXT_ROW;
150 }
151
152 this.column = this.columns[this.index];
153 }
154 } while(true);
155 }
156
157 @Override
158 public ScanQueryMatcher.MatchCode checkVersions(byte[] bytes, int offset, int length,
159 long timestamp, byte type, boolean ignoreCount) {
160 assert !KeyValue.isDelete(type);
161 if (ignoreCount) return ScanQueryMatcher.MatchCode.INCLUDE;
162
163 if (sameAsPreviousTS(timestamp)) {
164
165 return ScanQueryMatcher.MatchCode.SKIP;
166 }
167 int count = this.column.increment();
168 if (count >= maxVersions || (count >= minVersions && isExpired(timestamp))) {
169
170 ++this.index;
171 resetTS();
172 if (done()) {
173
174 this.column = null;
175 return ScanQueryMatcher.MatchCode.INCLUDE_AND_SEEK_NEXT_ROW;
176 }
177
178
179 this.column = this.columns[this.index];
180 return ScanQueryMatcher.MatchCode.INCLUDE_AND_SEEK_NEXT_COL;
181 }
182 setTS(timestamp);
183 return ScanQueryMatcher.MatchCode.INCLUDE;
184 }
185
186
187 public void reset() {
188 this.index = 0;
189 this.column = this.columns[this.index];
190 for(ColumnCount col : this.columns) {
191 col.setCount(0);
192 }
193 resetTS();
194 }
195
196 private void resetTS() {
197 latestTSOfCurrentColumn = HConstants.LATEST_TIMESTAMP;
198 }
199
200 private void setTS(long timestamp) {
201 latestTSOfCurrentColumn = timestamp;
202 }
203
204 private boolean sameAsPreviousTS(long timestamp) {
205 return timestamp == latestTSOfCurrentColumn;
206 }
207
208 private boolean isExpired(long timestamp) {
209 return timestamp < oldestStamp;
210 }
211
212
213
214
215
216
217
218
219
220
221 public void doneWithColumn(byte [] bytes, int offset, int length) {
222 while (this.column != null) {
223 int compare = Bytes.compareTo(column.getBuffer(), column.getOffset(),
224 column.getLength(), bytes, offset, length);
225 resetTS();
226 if (compare <= 0) {
227 ++this.index;
228 if (done()) {
229
230 this.column = null;
231 } else {
232 this.column = this.columns[this.index];
233 }
234 if (compare <= -1)
235 continue;
236 }
237 return;
238 }
239 }
240
241 public MatchCode getNextRowOrNextColumn(byte[] bytes, int offset,
242 int qualLength) {
243 doneWithColumn(bytes, offset,qualLength);
244
245 if (getColumnHint() == null) {
246 return MatchCode.SEEK_NEXT_ROW;
247 } else {
248 return MatchCode.SEEK_NEXT_COL;
249 }
250 }
251
252 public boolean isDone(long timestamp) {
253 return minVersions <= 0 && isExpired(timestamp);
254 }
255 }