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.util.ArrayList;
23 import java.util.List;
24 import java.util.NavigableSet;
25
26 import org.apache.hadoop.hbase.HConstants;
27 import org.apache.hadoop.hbase.util.Bytes;
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48 public class ExplicitColumnTracker implements ColumnTracker {
49
50 private final int maxVersions;
51 private final List<ColumnCount> columns;
52 private final List<ColumnCount> columnsToReuse;
53 private int index;
54 private ColumnCount column;
55
56
57 private long latestTSOfCurrentColumn;
58
59
60
61
62
63
64 public ExplicitColumnTracker(NavigableSet<byte[]> columns, int maxVersions) {
65 this.maxVersions = maxVersions;
66 this.columns = new ArrayList<ColumnCount>(columns.size());
67 this.columnsToReuse = new ArrayList<ColumnCount>(columns.size());
68 for(byte [] column : columns) {
69 this.columnsToReuse.add(new ColumnCount(column,maxVersions));
70 }
71 reset();
72 }
73
74
75
76
77 public boolean done() {
78 return this.columns.size() == 0;
79 }
80
81 public ColumnCount getColumnHint() {
82 return this.column;
83 }
84
85
86
87
88
89
90
91
92
93
94 public ScanQueryMatcher.MatchCode checkColumn(byte [] bytes, int offset,
95 int length, long timestamp) {
96 do {
97
98 if(this.columns.size() == 0) {
99 return ScanQueryMatcher.MatchCode.SEEK_NEXT_ROW;
100 }
101
102
103 if(this.column == null) {
104 return ScanQueryMatcher.MatchCode.SEEK_NEXT_ROW;
105 }
106
107
108 int ret = Bytes.compareTo(column.getBuffer(), column.getOffset(),
109 column.getLength(), bytes, offset, length);
110
111
112
113 if(ret == 0) {
114
115 if (sameAsPreviousTS(timestamp)) {
116
117 return ScanQueryMatcher.MatchCode.SKIP;
118 }
119 if(this.column.decrement() == 0) {
120
121 this.columns.remove(this.index);
122 resetTS();
123 if(this.columns.size() == this.index) {
124
125 this.column = null;
126 } else {
127 this.column = this.columns.get(this.index);
128 }
129 } else {
130 setTS(timestamp);
131 }
132 return ScanQueryMatcher.MatchCode.INCLUDE;
133 }
134
135 resetTS();
136
137 if (ret > 0) {
138
139 return ScanQueryMatcher.MatchCode.SEEK_NEXT_COL;
140 }
141
142
143
144 if(ret <= -1) {
145 if(++this.index >= this.columns.size()) {
146
147 return ScanQueryMatcher.MatchCode.SEEK_NEXT_ROW;
148 }
149
150 this.column = this.columns.get(this.index);
151 }
152 } while(true);
153 }
154
155
156
157
158 public void update() {
159 if(this.columns.size() != 0) {
160 this.index = 0;
161 this.column = this.columns.get(this.index);
162 } else {
163 this.index = -1;
164 this.column = null;
165 }
166 }
167
168
169 public void reset() {
170 buildColumnList();
171 this.index = 0;
172 this.column = this.columns.get(this.index);
173 resetTS();
174 }
175
176 private void resetTS() {
177 latestTSOfCurrentColumn = HConstants.LATEST_TIMESTAMP;
178 }
179
180 private void setTS(long timestamp) {
181 latestTSOfCurrentColumn = timestamp;
182 }
183
184 private boolean sameAsPreviousTS(long timestamp) {
185 return timestamp == latestTSOfCurrentColumn;
186 }
187
188 private void buildColumnList() {
189 this.columns.clear();
190 this.columns.addAll(this.columnsToReuse);
191 for(ColumnCount col : this.columns) {
192 col.setCount(this.maxVersions);
193 }
194 }
195
196
197
198
199
200
201
202
203
204
205 public void doneWithColumn(byte [] bytes, int offset, int length) {
206 while (this.column != null) {
207 int compare = Bytes.compareTo(column.getBuffer(), column.getOffset(),
208 column.getLength(), bytes, offset, length);
209 resetTS();
210 if (compare == 0) {
211 this.columns.remove(this.index);
212 if (this.columns.size() == this.index) {
213
214 this.column = null;
215 } else {
216 this.column = this.columns.get(this.index);
217 }
218 return;
219 } else if ( compare <= -1) {
220 if(++this.index != this.columns.size()) {
221 this.column = this.columns.get(this.index);
222 } else {
223 this.column = null;
224 }
225 } else {
226 return;
227 }
228 }
229 }
230
231 }