1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.apache.hadoop.hbase.regionserver;
22
23 import java.io.IOException;
24
25 import org.apache.hadoop.hbase.HConstants;
26 import org.apache.hadoop.hbase.KeyValue;
27 import org.apache.hadoop.hbase.regionserver.ScanQueryMatcher.MatchCode;
28 import org.apache.hadoop.hbase.util.Bytes;
29
30
31
32
33 public class ScanWildcardColumnTracker implements ColumnTracker {
34 private byte [] columnBuffer = null;
35 private int columnOffset = 0;
36 private int columnLength = 0;
37 private int currentCount = 0;
38 private int maxVersions;
39 private int minVersions;
40
41
42 private long latestTSOfCurrentColumn;
43 private byte latestTypeOfCurrentColumn;
44
45 private long oldestStamp;
46
47
48
49
50
51
52
53
54 public ScanWildcardColumnTracker(int minVersion, int maxVersion,
55 long oldestUnexpiredTS) {
56 this.maxVersions = maxVersion;
57 this.minVersions = minVersion;
58 this.oldestStamp = oldestUnexpiredTS;
59 }
60
61
62
63
64
65 @Override
66 public MatchCode checkColumn(byte[] bytes, int offset, int length, byte type)
67 throws IOException {
68 return MatchCode.INCLUDE;
69 }
70
71
72
73
74
75
76 @Override
77 public MatchCode checkVersions(byte[] bytes, int offset, int length, long timestamp, byte type,
78 boolean ignoreCount) throws IOException {
79
80 if (columnBuffer == null) {
81
82 resetBuffer(bytes, offset, length);
83 if (ignoreCount) return ScanQueryMatcher.MatchCode.INCLUDE;
84
85 return checkVersion(type, timestamp);
86 }
87 int cmp = Bytes.compareTo(bytes, offset, length,
88 columnBuffer, columnOffset, columnLength);
89 if (cmp == 0) {
90 if (ignoreCount) return ScanQueryMatcher.MatchCode.INCLUDE;
91
92
93 if (sameAsPreviousTSAndType(timestamp, type)) {
94 return ScanQueryMatcher.MatchCode.SKIP;
95 }
96 return checkVersion(type, timestamp);
97 }
98
99 resetTSAndType();
100
101
102 if (cmp > 0) {
103
104 resetBuffer(bytes, offset, length);
105 if (ignoreCount) return ScanQueryMatcher.MatchCode.INCLUDE;
106 return checkVersion(type, timestamp);
107 }
108
109
110
111
112
113 throw new IOException(
114 "ScanWildcardColumnTracker.checkColumn ran into a column actually " +
115 "smaller than the previous column: " +
116 Bytes.toStringBinary(bytes, offset, length));
117 }
118
119 private void resetBuffer(byte[] bytes, int offset, int length) {
120 columnBuffer = bytes;
121 columnOffset = offset;
122 columnLength = length;
123 currentCount = 0;
124 }
125
126
127
128
129
130
131
132
133
134
135 private MatchCode checkVersion(byte type, long timestamp) {
136 if (!KeyValue.isDelete(type)) {
137 currentCount++;
138 }
139 if (currentCount > maxVersions) {
140 return ScanQueryMatcher.MatchCode.SEEK_NEXT_COL;
141 }
142
143 if (currentCount <= minVersions || !isExpired(timestamp)) {
144 setTSAndType(timestamp, type);
145 return ScanQueryMatcher.MatchCode.INCLUDE;
146 } else {
147 return MatchCode.SEEK_NEXT_COL;
148 }
149
150 }
151
152 @Override
153 public void reset() {
154 columnBuffer = null;
155 resetTSAndType();
156 }
157
158 private void resetTSAndType() {
159 latestTSOfCurrentColumn = HConstants.LATEST_TIMESTAMP;
160 latestTypeOfCurrentColumn = 0;
161 }
162
163 private void setTSAndType(long timestamp, byte type) {
164 latestTSOfCurrentColumn = timestamp;
165 latestTypeOfCurrentColumn = type;
166 }
167
168 private boolean sameAsPreviousTSAndType(long timestamp, byte type) {
169 return timestamp == latestTSOfCurrentColumn && type == latestTypeOfCurrentColumn;
170 }
171
172 private boolean isExpired(long timestamp) {
173 return timestamp < oldestStamp;
174 }
175
176
177
178
179
180
181
182
183 public ColumnCount getColumnHint() {
184 return null;
185 }
186
187
188
189
190
191
192 @Override
193 public boolean done() {
194 return false;
195 }
196
197 public MatchCode getNextRowOrNextColumn(byte[] bytes, int offset,
198 int qualLength) {
199 return MatchCode.SEEK_NEXT_COL;
200 }
201
202 public boolean isDone(long timestamp) {
203 return minVersions <= 0 && isExpired(timestamp);
204 }
205 }