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