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 reset() {
145 columnBuffer = null;
146 resetTSAndType();
147 }
148
149 private void resetTSAndType() {
150 latestTSOfCurrentColumn = HConstants.LATEST_TIMESTAMP;
151 latestTypeOfCurrentColumn = 0;
152 }
153
154 private void setTSAndType(long timestamp, byte type) {
155 latestTSOfCurrentColumn = timestamp;
156 latestTypeOfCurrentColumn = type;
157 }
158
159 private boolean sameAsPreviousTSAndType(long timestamp, byte type) {
160 return timestamp == latestTSOfCurrentColumn && type == latestTypeOfCurrentColumn;
161 }
162
163 private boolean isExpired(long timestamp) {
164 return timestamp < oldestStamp;
165 }
166
167
168
169
170
171
172
173
174 public ColumnCount getColumnHint() {
175 return null;
176 }
177
178
179
180
181
182
183 @Override
184 public boolean done() {
185 return false;
186 }
187
188 public MatchCode getNextRowOrNextColumn(byte[] bytes, int offset,
189 int qualLength) {
190 return MatchCode.SEEK_NEXT_COL;
191 }
192
193 public boolean isDone(long timestamp) {
194 return minVersions <= 0 && isExpired(timestamp);
195 }
196 }