1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.codec.prefixtree;
20
21 import java.nio.ByteBuffer;
22
23 import org.apache.hadoop.hbase.Cell;
24 import org.apache.hadoop.hbase.CellUtil;
25 import org.apache.hadoop.hbase.KeyValue;
26 import org.apache.hadoop.hbase.KeyValue.KVComparator;
27 import org.apache.hadoop.hbase.KeyValue.Type;
28 import org.apache.hadoop.hbase.KeyValueUtil;
29 import org.apache.hadoop.hbase.SettableSequenceId;
30 import org.apache.hadoop.hbase.classification.InterfaceAudience;
31 import org.apache.hadoop.hbase.codec.prefixtree.decode.DecoderFactory;
32 import org.apache.hadoop.hbase.codec.prefixtree.decode.PrefixTreeArraySearcher;
33 import org.apache.hadoop.hbase.codec.prefixtree.scanner.CellScannerPosition;
34 import org.apache.hadoop.hbase.io.HeapSize;
35 import org.apache.hadoop.hbase.io.encoding.DataBlockEncoder.EncodedSeeker;
36 import org.apache.hadoop.hbase.util.Bytes;
37 import org.apache.hadoop.hbase.util.ClassSize;
38
39
40
41
42
43
44
45
46
47 @InterfaceAudience.Private
48 public class PrefixTreeSeeker implements EncodedSeeker {
49
50 protected ByteBuffer block;
51 protected boolean includeMvccVersion;
52 protected PrefixTreeArraySearcher ptSearcher;
53
54 public PrefixTreeSeeker(boolean includeMvccVersion) {
55 this.includeMvccVersion = includeMvccVersion;
56 }
57
58 @Override
59 public void setCurrentBuffer(ByteBuffer fullBlockBuffer) {
60 block = fullBlockBuffer;
61 ptSearcher = DecoderFactory.checkOut(block, includeMvccVersion);
62 rewind();
63 }
64
65
66
67
68
69
70
71 public void releaseCurrentSearcher(){
72 DecoderFactory.checkIn(ptSearcher);
73 }
74
75
76 @Override
77 public ByteBuffer getKeyDeepCopy() {
78 return KeyValueUtil.copyKeyToNewByteBuffer(ptSearcher.current());
79 }
80
81
82 @Override
83 public ByteBuffer getValueShallowCopy() {
84 return CellUtil.getValueBufferShallowCopy(ptSearcher.current());
85 }
86
87
88
89
90 @Override
91 public Cell getKeyValue() {
92 Cell cell = ptSearcher.current();
93 if (cell == null) {
94 return null;
95 }
96 return new ClonedPrefixTreeCell(cell.getRowArray(), cell.getRowOffset(), cell.getRowLength(),
97 cell.getFamilyArray(), cell.getFamilyOffset(), cell.getFamilyLength(),
98 cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength(),
99 cell.getValueArray(), cell.getValueOffset(), cell.getValueLength(), cell.getTagsArray(),
100 cell.getTagsOffset(), cell.getTagsLength(), cell.getTimestamp(), cell.getTypeByte(),
101 cell.getSequenceId());
102 }
103
104
105
106
107
108
109
110
111
112
113
114 public Cell get() {
115 return ptSearcher.current();
116 }
117
118 @Override
119 public void rewind() {
120 ptSearcher.positionAtFirstCell();
121 }
122
123 @Override
124 public boolean next() {
125 return ptSearcher.advance();
126 }
127
128 public boolean advance() {
129 return ptSearcher.advance();
130 }
131
132
133 private static final boolean USE_POSITION_BEFORE = false;
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152 @Override
153 public int seekToKeyInBlock(byte[] keyOnlyBytes, int offset, int length,
154 boolean forceBeforeOnExactMatch) {
155 if (USE_POSITION_BEFORE) {
156 return seekToOrBeforeUsingPositionAtOrBefore(keyOnlyBytes, offset, length,
157 forceBeforeOnExactMatch);
158 } else {
159 return seekToOrBeforeUsingPositionAtOrAfter(keyOnlyBytes, offset, length,
160 forceBeforeOnExactMatch);
161 }
162 }
163
164
165
166
167
168
169 protected int seekToOrBeforeUsingPositionAtOrBefore(byte[] keyOnlyBytes, int offset, int length,
170 boolean seekBefore){
171
172 KeyValue kv = new KeyValue.KeyOnlyKeyValue(keyOnlyBytes, offset, length);
173
174 return seekToOrBeforeUsingPositionAtOrBefore(kv, seekBefore);
175 }
176
177
178
179
180
181
182 protected int seekToOrBeforeUsingPositionAtOrBefore(Cell kv, boolean seekBefore) {
183
184
185 CellScannerPosition position = ptSearcher.seekForwardToOrBefore(kv);
186
187 if (CellScannerPosition.AT == position) {
188 if (seekBefore) {
189 ptSearcher.previous();
190 return 1;
191 }
192 return 0;
193 }
194
195 return 1;
196 }
197
198 protected int seekToOrBeforeUsingPositionAtOrAfter(byte[] keyOnlyBytes, int offset, int length,
199 boolean seekBefore) {
200
201
202 KeyValue kv = new KeyValue.KeyOnlyKeyValue(keyOnlyBytes, offset, length);
203 return seekToOrBeforeUsingPositionAtOrAfter(kv, seekBefore);
204 }
205
206 protected int seekToOrBeforeUsingPositionAtOrAfter(Cell kv, boolean seekBefore) {
207
208 CellScannerPosition position = ptSearcher.seekForwardToOrAfter(kv);
209
210 if (CellScannerPosition.AT == position) {
211 if (seekBefore) {
212 ptSearcher.previous();
213 return 1;
214 }
215 return 0;
216
217 }
218
219 if (CellScannerPosition.AFTER == position) {
220 if (!ptSearcher.isBeforeFirst()) {
221 ptSearcher.previous();
222 }
223 return 1;
224 }
225
226 if (position == CellScannerPosition.AFTER_LAST) {
227 if (seekBefore) {
228 ptSearcher.previous();
229 }
230 return 1;
231 }
232
233 throw new RuntimeException("unexpected CellScannerPosition:" + position);
234 }
235
236 @Override
237 public int compareKey(KVComparator comparator, byte[] key, int offset, int length) {
238
239 ByteBuffer bb = getKeyDeepCopy();
240 return comparator.compareFlatKey(key, offset, length, bb.array(), bb.arrayOffset(), bb.limit());
241 }
242
243 @Override
244 public int seekToKeyInBlock(Cell key, boolean forceBeforeOnExactMatch) {
245 if (USE_POSITION_BEFORE) {
246 return seekToOrBeforeUsingPositionAtOrBefore(key, forceBeforeOnExactMatch);
247 } else {
248 return seekToOrBeforeUsingPositionAtOrAfter(key, forceBeforeOnExactMatch);
249 }
250 }
251
252 @Override
253 public int compareKey(KVComparator comparator, Cell key) {
254 ByteBuffer bb = getKeyDeepCopy();
255 return comparator.compare(key,
256 new KeyValue.KeyOnlyKeyValue(bb.array(), bb.arrayOffset(), bb.limit()));
257 }
258
259
260
261
262
263 private static class ClonedPrefixTreeCell implements Cell, SettableSequenceId, HeapSize {
264 private static final long FIXED_OVERHEAD = ClassSize.align(ClassSize.OBJECT
265 + (5 * ClassSize.REFERENCE) + (2 * Bytes.SIZEOF_LONG) + (4 * Bytes.SIZEOF_INT)
266 + (Bytes.SIZEOF_SHORT) + (2 * Bytes.SIZEOF_BYTE) + (5 * ClassSize.ARRAY));
267 private byte[] row;
268 private short rowLength;
269 private byte[] fam;
270 private byte famLength;
271 private byte[] qual;
272 private int qualLength;
273 private byte[] val;
274 private int valOffset;
275 private int valLength;
276 private byte[] tag;
277 private int tagsLength;
278 private long ts;
279 private long seqId;
280 private byte type;
281
282 public ClonedPrefixTreeCell(byte[] row, int rowOffset, short rowLength, byte[] fam,
283 int famOffset, byte famLength, byte[] qual, int qualOffset, int qualLength, byte[] val,
284 int valOffset, int valLength, byte[] tag, int tagOffset, int tagLength, long ts, byte type,
285 long seqId) {
286 this.row = new byte[rowLength];
287 System.arraycopy(row, rowOffset, this.row, 0, rowLength);
288 this.rowLength = rowLength;
289 this.fam = new byte[famLength];
290 System.arraycopy(fam, famOffset, this.fam, 0, famLength);
291 this.famLength = famLength;
292 this.qual = new byte[qualLength];
293 System.arraycopy(qual, qualOffset, this.qual, 0, qualLength);
294 this.qualLength = qualLength;
295 this.tag = new byte[tagLength];
296 System.arraycopy(tag, tagOffset, this.tag, 0, tagLength);
297 this.tagsLength = tagLength;
298 this.val = val;
299 this.valLength = valLength;
300 this.valOffset = valOffset;
301 this.ts = ts;
302 this.seqId = seqId;
303 this.type = type;
304 }
305
306 @Override
307 public void setSequenceId(long seqId) {
308 this.seqId = seqId;
309 }
310
311 @Override
312 public byte[] getRowArray() {
313 return this.row;
314 }
315
316 @Override
317 public int getRowOffset() {
318 return 0;
319 }
320
321 @Override
322 public short getRowLength() {
323 return this.rowLength;
324 }
325
326 @Override
327 public byte[] getFamilyArray() {
328 return this.fam;
329 }
330
331 @Override
332 public int getFamilyOffset() {
333 return 0;
334 }
335
336 @Override
337 public byte getFamilyLength() {
338 return this.famLength;
339 }
340
341 @Override
342 public byte[] getQualifierArray() {
343 return this.qual;
344 }
345
346 @Override
347 public int getQualifierOffset() {
348 return 0;
349 }
350
351 @Override
352 public int getQualifierLength() {
353 return this.qualLength;
354 }
355
356 @Override
357 public long getTimestamp() {
358 return ts;
359 }
360
361 @Override
362 public byte getTypeByte() {
363 return type;
364 }
365
366 @Override
367 @Deprecated
368 public long getMvccVersion() {
369 return getSequenceId();
370 }
371
372 @Override
373 public long getSequenceId() {
374 return seqId;
375 }
376
377 @Override
378 public byte[] getValueArray() {
379 return val;
380 }
381
382 @Override
383 public int getValueOffset() {
384 return this.valOffset;
385 }
386
387 @Override
388 public int getValueLength() {
389 return this.valLength;
390 }
391
392 @Override
393 public byte[] getTagsArray() {
394 return this.tag;
395 }
396
397 @Override
398 public int getTagsOffset() {
399 return 0;
400 }
401
402 @Override
403 public int getTagsLength() {
404 return this.tagsLength;
405 }
406
407 @Override
408 @Deprecated
409 public byte[] getValue() {
410 return this.val;
411 }
412
413 @Override
414 @Deprecated
415 public byte[] getFamily() {
416 return this.fam;
417 }
418
419 @Override
420 @Deprecated
421 public byte[] getQualifier() {
422 return this.qual;
423 }
424
425 @Override
426 @Deprecated
427 public byte[] getRow() {
428 return this.row;
429 }
430
431 @Override
432 public String toString() {
433 String row = Bytes.toStringBinary(getRowArray(), getRowOffset(), getRowLength());
434 String family = Bytes.toStringBinary(getFamilyArray(), getFamilyOffset(), getFamilyLength());
435 String qualifier = Bytes.toStringBinary(getQualifierArray(), getQualifierOffset(),
436 getQualifierLength());
437 String timestamp = String.valueOf((getTimestamp()));
438 return row + "/" + family + (family != null && family.length() > 0 ? ":" : "") + qualifier
439 + "/" + timestamp + "/" + Type.codeToType(type);
440 }
441
442 @Override
443 public long heapSize() {
444 return FIXED_OVERHEAD + rowLength + famLength + qualLength + valLength + tagsLength;
445 }
446 }
447 }