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