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