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