1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase;
20
21 import java.io.IOException;
22 import java.nio.ByteBuffer;
23 import java.util.Iterator;
24 import java.util.List;
25 import java.util.Map.Entry;
26 import java.util.NavigableMap;
27
28 import org.apache.hadoop.classification.InterfaceAudience;
29 import org.apache.hadoop.classification.InterfaceStability;
30 import org.apache.hadoop.hbase.KeyValue.Type;
31 import org.apache.hadoop.hbase.util.ByteRange;
32 import org.apache.hadoop.hbase.util.Bytes;
33
34
35
36
37 @InterfaceAudience.Public
38 @InterfaceStability.Evolving
39 public final class CellUtil {
40
41
42
43 public static ByteRange fillRowRange(Cell cell, ByteRange range) {
44 return range.set(cell.getRowArray(), cell.getRowOffset(), cell.getRowLength());
45 }
46
47 public static ByteRange fillFamilyRange(Cell cell, ByteRange range) {
48 return range.set(cell.getFamilyArray(), cell.getFamilyOffset(), cell.getFamilyLength());
49 }
50
51 public static ByteRange fillQualifierRange(Cell cell, ByteRange range) {
52 return range.set(cell.getQualifierArray(), cell.getQualifierOffset(),
53 cell.getQualifierLength());
54 }
55
56 public static ByteRange fillTagRange(Cell cell, ByteRange range) {
57 return range.set(cell.getTagsArray(), cell.getTagsOffset(), cell.getTagsLengthUnsigned());
58 }
59
60
61
62 public static byte[] cloneRow(Cell cell){
63 byte[] output = new byte[cell.getRowLength()];
64 copyRowTo(cell, output, 0);
65 return output;
66 }
67
68 public static byte[] cloneFamily(Cell cell){
69 byte[] output = new byte[cell.getFamilyLength()];
70 copyFamilyTo(cell, output, 0);
71 return output;
72 }
73
74 public static byte[] cloneQualifier(Cell cell){
75 byte[] output = new byte[cell.getQualifierLength()];
76 copyQualifierTo(cell, output, 0);
77 return output;
78 }
79
80 public static byte[] cloneValue(Cell cell){
81 byte[] output = new byte[cell.getValueLength()];
82 copyValueTo(cell, output, 0);
83 return output;
84 }
85
86
87
88
89
90
91
92
93 public static byte[] getTagArray(Cell cell){
94 byte[] output = new byte[cell.getTagsLengthUnsigned()];
95 copyTagTo(cell, output, 0);
96 return output;
97 }
98
99
100
101
102 public static int copyRowTo(Cell cell, byte[] destination, int destinationOffset) {
103 System.arraycopy(cell.getRowArray(), cell.getRowOffset(), destination, destinationOffset,
104 cell.getRowLength());
105 return destinationOffset + cell.getRowLength();
106 }
107
108 public static int copyFamilyTo(Cell cell, byte[] destination, int destinationOffset) {
109 System.arraycopy(cell.getFamilyArray(), cell.getFamilyOffset(), destination, destinationOffset,
110 cell.getFamilyLength());
111 return destinationOffset + cell.getFamilyLength();
112 }
113
114 public static int copyQualifierTo(Cell cell, byte[] destination, int destinationOffset) {
115 System.arraycopy(cell.getQualifierArray(), cell.getQualifierOffset(), destination,
116 destinationOffset, cell.getQualifierLength());
117 return destinationOffset + cell.getQualifierLength();
118 }
119
120 public static int copyValueTo(Cell cell, byte[] destination, int destinationOffset) {
121 System.arraycopy(cell.getValueArray(), cell.getValueOffset(), destination, destinationOffset,
122 cell.getValueLength());
123 return destinationOffset + cell.getValueLength();
124 }
125
126
127
128
129
130
131
132
133 public static int copyTagTo(Cell cell, byte[] destination, int destinationOffset) {
134 System.arraycopy(cell.getTagsArray(), cell.getTagsOffset(), destination, destinationOffset,
135 cell.getTagsLengthUnsigned());
136 return destinationOffset + cell.getTagsLengthUnsigned();
137 }
138
139
140
141 public static byte getRowByte(Cell cell, int index) {
142 return cell.getRowArray()[cell.getRowOffset() + index];
143 }
144
145 public static ByteBuffer getValueBufferShallowCopy(Cell cell) {
146 ByteBuffer buffer = ByteBuffer.wrap(cell.getValueArray(), cell.getValueOffset(),
147 cell.getValueLength());
148 return buffer;
149 }
150
151 public static ByteBuffer getQualifierBufferShallowCopy(Cell cell) {
152 ByteBuffer buffer = ByteBuffer.wrap(cell.getQualifierArray(), cell.getQualifierOffset(),
153 cell.getQualifierLength());
154 return buffer;
155 }
156
157 public static Cell createCell(final byte [] row, final byte [] family, final byte [] qualifier,
158 final long timestamp, final byte type, final byte [] value) {
159
160
161
162 return new KeyValue(row, family, qualifier, timestamp,
163 KeyValue.Type.codeToType(type), value);
164 }
165
166 public static Cell createCell(final byte[] row, final byte[] family, final byte[] qualifier,
167 final long timestamp, final byte type, final byte[] value, final long memstoreTS) {
168 KeyValue keyValue = new KeyValue(row, family, qualifier, timestamp,
169 KeyValue.Type.codeToType(type), value);
170 keyValue.setMvccVersion(memstoreTS);
171 return keyValue;
172 }
173
174 public static Cell createCell(final byte[] row, final byte[] family, final byte[] qualifier,
175 final long timestamp, final byte type, final byte[] value, byte[] tags, final long memstoreTS) {
176 KeyValue keyValue = new KeyValue(row, family, qualifier, timestamp,
177 KeyValue.Type.codeToType(type), value, tags);
178 keyValue.setMvccVersion(memstoreTS);
179 return keyValue;
180 }
181
182 public static Cell createCell(final byte[] row, final byte[] family, final byte[] qualifier,
183 final long timestamp, Type type, final byte[] value, byte[] tags) {
184 KeyValue keyValue = new KeyValue(row, family, qualifier, timestamp, type, value, tags);
185 return keyValue;
186 }
187
188
189
190
191
192 public static CellScanner createCellScanner(final List<? extends CellScannable> cellScannerables) {
193 return new CellScanner() {
194 private final Iterator<? extends CellScannable> iterator = cellScannerables.iterator();
195 private CellScanner cellScanner = null;
196
197 @Override
198 public Cell current() {
199 return this.cellScanner != null? this.cellScanner.current(): null;
200 }
201
202 @Override
203 public boolean advance() throws IOException {
204 if (this.cellScanner == null) {
205 if (!this.iterator.hasNext()) return false;
206 this.cellScanner = this.iterator.next().cellScanner();
207 }
208 if (this.cellScanner.advance()) return true;
209 this.cellScanner = null;
210 return advance();
211 }
212 };
213 }
214
215
216
217
218
219 public static CellScanner createCellScanner(final Iterable<Cell> cellIterable) {
220 if (cellIterable == null) return null;
221 return createCellScanner(cellIterable.iterator());
222 }
223
224
225
226
227
228
229 public static CellScanner createCellScanner(final Iterator<Cell> cells) {
230 if (cells == null) return null;
231 return new CellScanner() {
232 private final Iterator<Cell> iterator = cells;
233 private Cell current = null;
234
235 @Override
236 public Cell current() {
237 return this.current;
238 }
239
240 @Override
241 public boolean advance() {
242 boolean hasNext = this.iterator.hasNext();
243 this.current = hasNext? this.iterator.next(): null;
244 return hasNext;
245 }
246 };
247 }
248
249
250
251
252
253 public static CellScanner createCellScanner(final Cell[] cellArray) {
254 return new CellScanner() {
255 private final Cell [] cells = cellArray;
256 private int index = -1;
257
258 @Override
259 public Cell current() {
260 if (cells == null) return null;
261 return (index < 0)? null: this.cells[index];
262 }
263
264 @Override
265 public boolean advance() {
266 if (cells == null) return false;
267 return ++index < this.cells.length;
268 }
269 };
270 }
271
272
273
274
275
276
277
278 public static CellScanner createCellScanner(final NavigableMap<byte [],
279 List<Cell>> map) {
280 return new CellScanner() {
281 private final Iterator<Entry<byte[], List<Cell>>> entries =
282 map.entrySet().iterator();
283 private Iterator<Cell> currentIterator = null;
284 private Cell currentCell;
285
286 @Override
287 public Cell current() {
288 return this.currentCell;
289 }
290
291 @Override
292 public boolean advance() {
293 if (this.currentIterator == null) {
294 if (!this.entries.hasNext()) return false;
295 this.currentIterator = this.entries.next().getValue().iterator();
296 }
297 if (this.currentIterator.hasNext()) {
298 this.currentCell = this.currentIterator.next();
299 return true;
300 }
301 this.currentCell = null;
302 this.currentIterator = null;
303 return advance();
304 }
305 };
306 }
307
308
309
310
311
312
313 public static boolean matchingRow(final Cell left, final Cell right) {
314 return Bytes.equals(left.getRowArray(), left.getRowOffset(), left.getRowLength(),
315 right.getRowArray(), right.getRowOffset(), right.getRowLength());
316 }
317
318 public static boolean matchingRow(final Cell left, final byte[] buf) {
319 return Bytes.equals(left.getRowArray(), left.getRowOffset(), left.getRowLength(),
320 buf, 0, buf.length);
321 }
322
323 public static boolean matchingFamily(final Cell left, final Cell right) {
324 return Bytes.equals(left.getFamilyArray(), left.getFamilyOffset(), left.getFamilyLength(),
325 right.getFamilyArray(), right.getFamilyOffset(), right.getFamilyLength());
326 }
327
328 public static boolean matchingFamily(final Cell left, final byte[] buf) {
329 return Bytes.equals(left.getFamilyArray(), left.getFamilyOffset(), left.getFamilyLength(),
330 buf, 0, buf.length);
331 }
332
333 public static boolean matchingQualifier(final Cell left, final Cell right) {
334 return Bytes.equals(left.getQualifierArray(), left.getQualifierOffset(), left.getQualifierLength(),
335 right.getQualifierArray(), right.getQualifierOffset(), right.getQualifierLength());
336 }
337
338 public static boolean matchingQualifier(final Cell left, final byte[] buf) {
339 return Bytes.equals(left.getQualifierArray(), left.getQualifierOffset(), left.getQualifierLength(),
340 buf, 0, buf.length);
341 }
342
343 public static boolean matchingColumn(final Cell left, final byte[] fam, final byte[] qual) {
344 if (!matchingFamily(left, fam))
345 return false;
346 return matchingQualifier(left, qual);
347 }
348
349 public static boolean matchingColumn(final Cell left, final Cell right) {
350 if (!matchingFamily(left, right))
351 return false;
352 return matchingQualifier(left, right);
353 }
354
355 public static boolean matchingValue(final Cell left, final Cell right) {
356 return Bytes.equals(left.getValueArray(), left.getValueOffset(), left.getValueLength(),
357 right.getValueArray(), right.getValueOffset(), right.getValueLength());
358 }
359
360 public static boolean matchingValue(final Cell left, final byte[] buf) {
361 return Bytes.equals(left.getValueArray(), left.getValueOffset(), left.getValueLength(),
362 buf, 0, buf.length);
363 }
364
365
366
367
368
369 public static boolean isDelete(final Cell cell) {
370 return KeyValue.isDelete(cell.getTypeByte());
371 }
372
373 public static boolean isDeleteFamily(final Cell cell) {
374 return cell.getTypeByte() == Type.DeleteFamily.getCode();
375 }
376
377
378
379
380
381 public static int estimatedSizeOf(final Cell cell) {
382
383 if (cell instanceof KeyValue) {
384 return ((KeyValue)cell).getLength() + Bytes.SIZEOF_INT;
385 }
386
387
388 return cell.getRowLength() + cell.getFamilyLength() +
389 cell.getQualifierLength() +
390 cell.getValueLength() +
391
392
393 KeyValue.KEY_INFRASTRUCTURE_SIZE +
394
395 Bytes.SIZEOF_INT;
396 }
397
398
399
400
401
402
403
404
405
406
407
408 public static Iterator<Tag> tagsIterator(final byte[] tags, final int offset, final int length) {
409 return new Iterator<Tag>() {
410 private int pos = offset;
411 private int endOffset = offset + length - 1;
412
413 @Override
414 public boolean hasNext() {
415 return this.pos < endOffset;
416 }
417
418 @Override
419 public Tag next() {
420 if (hasNext()) {
421 int curTagLen = Bytes.readAsInt(tags, this.pos, Tag.TAG_LENGTH_SIZE);
422 Tag tag = new Tag(tags, pos, curTagLen + Tag.TAG_LENGTH_SIZE);
423 this.pos += Bytes.SIZEOF_SHORT + curTagLen;
424 return tag;
425 }
426 return null;
427 }
428
429 @Override
430 public void remove() {
431 throw new UnsupportedOperationException();
432 }
433 };
434 }
435
436 public static boolean isDeleteColumns(final Cell cell) {
437 return cell.getTypeByte() == Type.DeleteColumn.getCode();
438 }
439
440 public static boolean isDeleteColumnVersion(final Cell cell) {
441 return cell.getTypeByte() == Type.Delete.getCode();
442 }
443
444
445
446
447
448 public static boolean overlappingKeys(final byte[] start1, final byte[] end1,
449 final byte[] start2, final byte[] end2) {
450 return (end2.length == 0 || start1.length == 0 || Bytes.compareTo(start1,
451 end2) < 0)
452 && (end1.length == 0 || start2.length == 0 || Bytes.compareTo(start2,
453 end1) < 0);
454 }
455 }