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
66
67 @Override
68 public MatchCode checkColumn(byte[] bytes, int offset, int length,
69 long timestamp, byte type, boolean ignoreCount) throws IOException {
70
71 if (columnBuffer == null) {
72
73 resetBuffer(bytes, offset, length);
74 if (ignoreCount) return ScanQueryMatcher.MatchCode.INCLUDE;
75
76 return checkVersion(type, timestamp);
77 }
78 int cmp = Bytes.compareTo(bytes, offset, length,
79 columnBuffer, columnOffset, columnLength);
80 if (cmp == 0) {
81 if (ignoreCount) return ScanQueryMatcher.MatchCode.INCLUDE;
82
83
84 if (sameAsPreviousTSAndType(timestamp, type)) {
85 return ScanQueryMatcher.MatchCode.SKIP;
86 }
87 return checkVersion(type, timestamp);
88 }
89
90 resetTSAndType();
91
92
93 if (cmp > 0) {
94
95 resetBuffer(bytes, offset, length);
96 if (ignoreCount) return ScanQueryMatcher.MatchCode.INCLUDE;
97 return checkVersion(type, timestamp);
98 }
99
100
101
102
103
104 throw new IOException(
105 "ScanWildcardColumnTracker.checkColumn ran into a column actually " +
106 "smaller than the previous column: " +
107 Bytes.toStringBinary(bytes, offset, length));
108 }
109
110 private void resetBuffer(byte[] bytes, int offset, int length) {
111 columnBuffer = bytes;
112 columnOffset = offset;
113 columnLength = length;
114 currentCount = 0;
115 }
116
117
118
119
120
121
122
123
124
125
126 private MatchCode checkVersion(byte type, long timestamp) {
127 if (!KeyValue.isDelete(type)) {
128 currentCount++;
129 }
130 if (currentCount > maxVersions) {
131 return ScanQueryMatcher.MatchCode.SEEK_NEXT_COL;
132 }
133
134 if (currentCount <= minVersions || !isExpired(timestamp)) {
135 setTSAndType(timestamp, type);
136 return ScanQueryMatcher.MatchCode.INCLUDE;
137 } else {
138 return MatchCode.SEEK_NEXT_COL;
139 }
140
141 }
142
143 @Override
144 public void update() {
145
146 throw new UnsupportedOperationException(
147 "ScanWildcardColumnTracker.update should never be called!");
148 }
149
150 @Override
151 public void reset() {
152 columnBuffer = null;
153 resetTSAndType();
154 }
155
156 private void resetTSAndType() {
157 latestTSOfCurrentColumn = HConstants.LATEST_TIMESTAMP;
158 latestTypeOfCurrentColumn = 0;
159 }
160
161 private void setTSAndType(long timestamp, byte type) {
162 latestTSOfCurrentColumn = timestamp;
163 latestTypeOfCurrentColumn = type;
164 }
165
166 private boolean sameAsPreviousTSAndType(long timestamp, byte type) {
167 return timestamp == latestTSOfCurrentColumn && type == latestTypeOfCurrentColumn;
168 }
169
170 private boolean isExpired(long timestamp) {
171 return timestamp < oldestStamp;
172 }
173
174
175
176
177
178
179
180
181 public ColumnCount getColumnHint() {
182 return null;
183 }
184
185
186
187
188
189
190 @Override
191 public boolean done() {
192 return false;
193 }
194
195 public MatchCode getNextRowOrNextColumn(byte[] bytes, int offset,
196 int qualLength) {
197 return MatchCode.SEEK_NEXT_COL;
198 }
199
200 public boolean isDone(long timestamp) {
201 return minVersions <= 0 && isExpired(timestamp);
202 }
203 }