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