001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019package org.apache.hadoop.hbase;
020
021import static org.apache.hadoop.hbase.KeyValue.COLUMN_FAMILY_DELIMITER;
022import static org.apache.hadoop.hbase.KeyValue.COLUMN_FAMILY_DELIM_ARRAY;
023import static org.apache.hadoop.hbase.KeyValue.getDelimiter;
024import static org.apache.hadoop.hbase.Tag.TAG_LENGTH_SIZE;
025
026import java.io.DataOutput;
027import java.io.DataOutputStream;
028import java.io.IOException;
029import java.nio.ByteBuffer;
030import java.util.ArrayList;
031import java.util.Arrays;
032import java.util.Iterator;
033import java.util.List;
034import java.util.Map.Entry;
035import java.util.NavigableMap;
036import java.util.Optional;
037import java.util.function.Function;
038import org.apache.hadoop.hbase.KeyValue.Type;
039import org.apache.hadoop.hbase.io.HeapSize;
040import org.apache.hadoop.hbase.util.ByteBufferUtils;
041import org.apache.hadoop.hbase.util.ByteRange;
042import org.apache.hadoop.hbase.util.Bytes;
043import org.apache.yetus.audience.InterfaceAudience;
044import org.apache.yetus.audience.InterfaceAudience.Private;
045
046import org.apache.hbase.thirdparty.com.google.common.annotations.VisibleForTesting;
047
048/**
049 * Utility methods helpful for slinging {@link Cell} instances. Some methods below are for internal
050 * use only and are marked InterfaceAudience.Private at the method level. Note that all such methods
051 * have been marked deprecated in HBase-2.0 which will be subsequently removed in HBase-3.0
052 */
053@InterfaceAudience.Public
054public final class CellUtil {
055
056  /**
057   * Private constructor to keep this class from being instantiated.
058   */
059  private CellUtil() {
060  }
061
062  /******************* ByteRange *******************************/
063
064  /**
065   * @deprecated As of HBase-2.0. Will be removed in HBase-3.0.
066   */
067  @Deprecated
068  public static ByteRange fillRowRange(Cell cell, ByteRange range) {
069    return range.set(cell.getRowArray(), cell.getRowOffset(), cell.getRowLength());
070  }
071
072  /**
073   * @deprecated As of HBase-2.0. Will be removed in HBase-3.0.
074   */
075  @Deprecated
076  public static ByteRange fillFamilyRange(Cell cell, ByteRange range) {
077    return range.set(cell.getFamilyArray(), cell.getFamilyOffset(), cell.getFamilyLength());
078  }
079
080  /**
081   * @deprecated As of HBase-2.0. Will be removed in HBase-3.0.
082   */
083  @Deprecated
084  public static ByteRange fillQualifierRange(Cell cell, ByteRange range) {
085    return range.set(cell.getQualifierArray(), cell.getQualifierOffset(),
086      cell.getQualifierLength());
087  }
088
089  /**
090   * @deprecated As of HBase-2.0. Will be removed in HBase-3.0.
091   */
092  @Deprecated
093  public static ByteRange fillValueRange(Cell cell, ByteRange range) {
094    return range.set(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength());
095  }
096
097  /**
098   * @deprecated As of HBase-2.0. Will be removed in HBase-3.0.
099   */
100  @Deprecated
101  public static ByteRange fillTagRange(Cell cell, ByteRange range) {
102    return range.set(cell.getTagsArray(), cell.getTagsOffset(), cell.getTagsLength());
103  }
104
105  /***************** get individual arrays for tests ************/
106
107  public static byte[] cloneRow(Cell cell) {
108    byte[] output = new byte[cell.getRowLength()];
109    copyRowTo(cell, output, 0);
110    return output;
111  }
112
113  public static byte[] cloneFamily(Cell cell) {
114    byte[] output = new byte[cell.getFamilyLength()];
115    copyFamilyTo(cell, output, 0);
116    return output;
117  }
118
119  public static byte[] cloneQualifier(Cell cell) {
120    byte[] output = new byte[cell.getQualifierLength()];
121    copyQualifierTo(cell, output, 0);
122    return output;
123  }
124
125  public static byte[] cloneValue(Cell cell) {
126    byte[] output = new byte[cell.getValueLength()];
127    copyValueTo(cell, output, 0);
128    return output;
129  }
130
131  /**
132   * @deprecated As of HBase-2.0. Will be removed in HBase-3.0.
133   *             Use {@link RawCell#cloneTags()}
134   */
135  @Deprecated
136  public static byte[] cloneTags(Cell cell) {
137    byte[] output = new byte[cell.getTagsLength()];
138    PrivateCellUtil.copyTagsTo(cell, output, 0);
139    return output;
140  }
141
142  /**
143   * Returns tag value in a new byte array. If server-side, use {@link Tag#getValueArray()} with
144   * appropriate {@link Tag#getValueOffset()} and {@link Tag#getValueLength()} instead to save on
145   * allocations.
146   * @param cell
147   * @return tag value in a new byte array.
148   * @deprecated As of HBase-2.0. Will be removed in HBase-3.0
149   */
150  @Deprecated
151  public static byte[] getTagArray(Cell cell) {
152    byte[] output = new byte[cell.getTagsLength()];
153    PrivateCellUtil.copyTagsTo(cell, output, 0);
154    return output;
155  }
156
157  /**
158   * Makes a column in family:qualifier form from separate byte arrays.
159   * <p>
160   * Not recommended for usage as this is old-style API.
161   * @param family
162   * @param qualifier
163   * @return family:qualifier
164   */
165  public static byte[] makeColumn(byte[] family, byte[] qualifier) {
166    return Bytes.add(family, COLUMN_FAMILY_DELIM_ARRAY, qualifier);
167  }
168
169  /**
170   * Splits a column in {@code family:qualifier} form into separate byte arrays. An empty qualifier
171   * (ie, {@code fam:}) is parsed as <code>{ fam, EMPTY_BYTE_ARRAY }</code> while no delimiter (ie,
172   * {@code fam}) is parsed as an array of one element, <code>{ fam }</code>.
173   * <p>
174   * Don't forget, HBase DOES support empty qualifiers. (see HBASE-9549)
175   * </p>
176   * <p>
177   * Not recommend to be used as this is old-style API.
178   * </p>
179   * @param c The column.
180   * @return The parsed column.
181   */
182  public static byte[][] parseColumn(byte[] c) {
183    final int index = getDelimiter(c, 0, c.length, COLUMN_FAMILY_DELIMITER);
184    if (index == -1) {
185      // If no delimiter, return array of size 1
186      return new byte[][] { c };
187    } else if (index == c.length - 1) {
188      // family with empty qualifier, return array size 2
189      byte[] family = new byte[c.length - 1];
190      System.arraycopy(c, 0, family, 0, family.length);
191      return new byte[][] { family, HConstants.EMPTY_BYTE_ARRAY };
192    }
193    // Family and column, return array size 2
194    final byte[][] result = new byte[2][];
195    result[0] = new byte[index];
196    System.arraycopy(c, 0, result[0], 0, index);
197    final int len = c.length - (index + 1);
198    result[1] = new byte[len];
199    System.arraycopy(c, index + 1 /* Skip delimiter */, result[1], 0, len);
200    return result;
201  }
202
203  /******************** copyTo **********************************/
204
205  /**
206   * Copies the row to the given byte[]
207   * @param cell the cell whose row has to be copied
208   * @param destination the destination byte[] to which the row has to be copied
209   * @param destinationOffset the offset in the destination byte[]
210   * @return the offset of the byte[] after the copy has happened
211   */
212  public static int copyRowTo(Cell cell, byte[] destination, int destinationOffset) {
213    short rowLen = cell.getRowLength();
214    if (cell instanceof ByteBufferExtendedCell) {
215      ByteBufferUtils.copyFromBufferToArray(destination,
216          ((ByteBufferExtendedCell) cell).getRowByteBuffer(),
217          ((ByteBufferExtendedCell) cell).getRowPosition(), destinationOffset, rowLen);
218    } else {
219      System.arraycopy(cell.getRowArray(), cell.getRowOffset(), destination, destinationOffset,
220        rowLen);
221    }
222    return destinationOffset + rowLen;
223  }
224
225  /**
226   * Copies the row to the given bytebuffer
227   * @param cell cell the cell whose row has to be copied
228   * @param destination the destination bytebuffer to which the row has to be copied
229   * @param destinationOffset the offset in the destination byte[]
230   * @return the offset of the bytebuffer after the copy has happened
231   */
232  public static int copyRowTo(Cell cell, ByteBuffer destination, int destinationOffset) {
233    short rowLen = cell.getRowLength();
234    if (cell instanceof ByteBufferExtendedCell) {
235      ByteBufferUtils.copyFromBufferToBuffer(((ByteBufferExtendedCell) cell).getRowByteBuffer(),
236        destination, ((ByteBufferExtendedCell) cell).getRowPosition(), destinationOffset, rowLen);
237    } else {
238      ByteBufferUtils.copyFromArrayToBuffer(destination, destinationOffset, cell.getRowArray(),
239        cell.getRowOffset(), rowLen);
240    }
241    return destinationOffset + rowLen;
242  }
243
244  /**
245   * Copies the row to a new byte[]
246   * @param cell the cell from which row has to copied
247   * @return the byte[] containing the row
248   */
249  public static byte[] copyRow(Cell cell) {
250    if (cell instanceof ByteBufferExtendedCell) {
251      return ByteBufferUtils.copyOfRange(((ByteBufferExtendedCell) cell).getRowByteBuffer(),
252        ((ByteBufferExtendedCell) cell).getRowPosition(),
253        ((ByteBufferExtendedCell) cell).getRowPosition() + cell.getRowLength());
254    } else {
255      return Arrays.copyOfRange(cell.getRowArray(), cell.getRowOffset(),
256        cell.getRowOffset() + cell.getRowLength());
257    }
258  }
259
260  /**
261   * Copies the family to the given byte[]
262   * @param cell the cell whose family has to be copied
263   * @param destination the destination byte[] to which the family has to be copied
264   * @param destinationOffset the offset in the destination byte[]
265   * @return the offset of the byte[] after the copy has happened
266   */
267  public static int copyFamilyTo(Cell cell, byte[] destination, int destinationOffset) {
268    byte fLen = cell.getFamilyLength();
269    if (cell instanceof ByteBufferExtendedCell) {
270      ByteBufferUtils.copyFromBufferToArray(destination,
271          ((ByteBufferExtendedCell) cell).getFamilyByteBuffer(),
272          ((ByteBufferExtendedCell) cell).getFamilyPosition(), destinationOffset, fLen);
273    } else {
274      System.arraycopy(cell.getFamilyArray(), cell.getFamilyOffset(), destination,
275        destinationOffset, fLen);
276    }
277    return destinationOffset + fLen;
278  }
279
280  /**
281   * Copies the family to the given bytebuffer
282   * @param cell the cell whose family has to be copied
283   * @param destination the destination bytebuffer to which the family has to be copied
284   * @param destinationOffset the offset in the destination bytebuffer
285   * @return the offset of the bytebuffer after the copy has happened
286   */
287  public static int copyFamilyTo(Cell cell, ByteBuffer destination, int destinationOffset) {
288    byte fLen = cell.getFamilyLength();
289    if (cell instanceof ByteBufferExtendedCell) {
290      ByteBufferUtils.copyFromBufferToBuffer(((ByteBufferExtendedCell) cell).getFamilyByteBuffer(),
291        destination, ((ByteBufferExtendedCell) cell).getFamilyPosition(), destinationOffset, fLen);
292    } else {
293      ByteBufferUtils.copyFromArrayToBuffer(destination, destinationOffset, cell.getFamilyArray(),
294        cell.getFamilyOffset(), fLen);
295    }
296    return destinationOffset + fLen;
297  }
298
299  /**
300   * Copies the qualifier to the given byte[]
301   * @param cell the cell whose qualifier has to be copied
302   * @param destination the destination byte[] to which the qualifier has to be copied
303   * @param destinationOffset the offset in the destination byte[]
304   * @return the offset of the byte[] after the copy has happened
305   */
306  public static int copyQualifierTo(Cell cell, byte[] destination, int destinationOffset) {
307    int qlen = cell.getQualifierLength();
308    if (cell instanceof ByteBufferExtendedCell) {
309      ByteBufferUtils.copyFromBufferToArray(destination,
310        ((ByteBufferExtendedCell) cell).getQualifierByteBuffer(),
311        ((ByteBufferExtendedCell) cell).getQualifierPosition(), destinationOffset, qlen);
312    } else {
313      System.arraycopy(cell.getQualifierArray(), cell.getQualifierOffset(), destination,
314        destinationOffset, qlen);
315    }
316    return destinationOffset + qlen;
317  }
318
319  /**
320   * Copies the qualifier to the given bytebuffer
321   * @param cell the cell whose qualifier has to be copied
322   * @param destination the destination bytebuffer to which the qualifier has to be copied
323   * @param destinationOffset the offset in the destination bytebuffer
324   * @return the offset of the bytebuffer after the copy has happened
325   */
326  public static int copyQualifierTo(Cell cell, ByteBuffer destination, int destinationOffset) {
327    int qlen = cell.getQualifierLength();
328    if (cell instanceof ByteBufferExtendedCell) {
329      ByteBufferUtils.copyFromBufferToBuffer(
330          ((ByteBufferExtendedCell) cell).getQualifierByteBuffer(),
331          destination, ((ByteBufferExtendedCell) cell).getQualifierPosition(),
332          destinationOffset, qlen);
333    } else {
334      ByteBufferUtils.copyFromArrayToBuffer(destination, destinationOffset,
335        cell.getQualifierArray(), cell.getQualifierOffset(), qlen);
336    }
337    return destinationOffset + qlen;
338  }
339
340  /**
341   * Copies the value to the given byte[]
342   * @param cell the cell whose value has to be copied
343   * @param destination the destination byte[] to which the value has to be copied
344   * @param destinationOffset the offset in the destination byte[]
345   * @return the offset of the byte[] after the copy has happened
346   */
347  public static int copyValueTo(Cell cell, byte[] destination, int destinationOffset) {
348    int vlen = cell.getValueLength();
349    if (cell instanceof ByteBufferExtendedCell) {
350      ByteBufferUtils.copyFromBufferToArray(destination,
351          ((ByteBufferExtendedCell) cell).getValueByteBuffer(),
352          ((ByteBufferExtendedCell) cell).getValuePosition(), destinationOffset, vlen);
353    } else {
354      System.arraycopy(cell.getValueArray(), cell.getValueOffset(), destination, destinationOffset,
355        vlen);
356    }
357    return destinationOffset + vlen;
358  }
359
360  /**
361   * Copies the value to the given bytebuffer
362   * @param cell the cell whose value has to be copied
363   * @param destination the destination bytebuffer to which the value has to be copied
364   * @param destinationOffset the offset in the destination bytebuffer
365   * @return the offset of the bytebuffer after the copy has happened
366   */
367  public static int copyValueTo(Cell cell, ByteBuffer destination, int destinationOffset) {
368    int vlen = cell.getValueLength();
369    if (cell instanceof ByteBufferExtendedCell) {
370      ByteBufferUtils.copyFromBufferToBuffer(((ByteBufferExtendedCell) cell).getValueByteBuffer(),
371        destination, ((ByteBufferExtendedCell) cell).getValuePosition(), destinationOffset, vlen);
372    } else {
373      ByteBufferUtils.copyFromArrayToBuffer(destination, destinationOffset, cell.getValueArray(),
374        cell.getValueOffset(), vlen);
375    }
376    return destinationOffset + vlen;
377  }
378
379  /**
380   * Copies the tags info into the tag portion of the cell
381   * @param cell
382   * @param destination
383   * @param destinationOffset
384   * @return position after tags
385   * @deprecated As of HBase-2.0. Will be removed in HBase-3.0.
386   */
387  @Deprecated
388  public static int copyTagTo(Cell cell, byte[] destination, int destinationOffset) {
389    int tlen = cell.getTagsLength();
390    if (cell instanceof ByteBufferExtendedCell) {
391      ByteBufferUtils
392        .copyFromBufferToArray(destination, ((ByteBufferExtendedCell) cell).getTagsByteBuffer(),
393          ((ByteBufferExtendedCell) cell).getTagsPosition(), destinationOffset, tlen);
394    } else {
395      System
396        .arraycopy(cell.getTagsArray(), cell.getTagsOffset(), destination, destinationOffset, tlen);
397    }
398    return destinationOffset + tlen;
399  }
400
401  /**
402   * Copies the tags info into the tag portion of the cell
403   * @param cell
404   * @param destination
405   * @param destinationOffset
406   * @return position after tags
407   * @deprecated As of HBase-2.0. Will be removed in 3.0.
408   */
409  @Deprecated
410  public static int copyTagTo(Cell cell, ByteBuffer destination, int destinationOffset) {
411    int tlen = cell.getTagsLength();
412    if (cell instanceof ByteBufferExtendedCell) {
413      ByteBufferUtils.copyFromBufferToBuffer(((ByteBufferExtendedCell) cell).getTagsByteBuffer(),
414        destination, ((ByteBufferExtendedCell) cell).getTagsPosition(), destinationOffset, tlen);
415    } else {
416      ByteBufferUtils.copyFromArrayToBuffer(destination, destinationOffset, cell.getTagsArray(),
417        cell.getTagsOffset(), tlen);
418    }
419    return destinationOffset + tlen;
420  }
421
422  /********************* misc *************************************/
423
424  @Private
425  /**
426   * @deprecated As of HBase-2.0. Will be removed in HBase-3.0.
427   */
428  @Deprecated
429  public static byte getRowByte(Cell cell, int index) {
430    if (cell instanceof ByteBufferExtendedCell) {
431      return ((ByteBufferExtendedCell) cell).getRowByteBuffer()
432          .get(((ByteBufferExtendedCell) cell).getRowPosition() + index);
433    }
434    return cell.getRowArray()[cell.getRowOffset() + index];
435  }
436
437  /**
438   * @deprecated As of HBase-2.0. Will be removed in 3.0.
439   */
440  @Deprecated
441  public static ByteBuffer getValueBufferShallowCopy(Cell cell) {
442    ByteBuffer buffer =
443        ByteBuffer.wrap(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength());
444    return buffer;
445  }
446
447  /**
448   * @param cell
449   * @return cell's qualifier wrapped into a ByteBuffer.
450   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0.
451   */
452  @Deprecated
453  public static ByteBuffer getQualifierBufferShallowCopy(Cell cell) {
454    // No usage of this in code.
455    ByteBuffer buffer = ByteBuffer.wrap(cell.getQualifierArray(), cell.getQualifierOffset(),
456      cell.getQualifierLength());
457    return buffer;
458  }
459
460  /**
461   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0. Use {@link CellBuilder}
462   *             instead
463   */
464  @Deprecated
465  public static Cell createCell(final byte[] row, final byte[] family, final byte[] qualifier,
466      final long timestamp, final byte type, final byte[] value) {
467    return ExtendedCellBuilderFactory.create(CellBuilderType.DEEP_COPY)
468            .setRow(row)
469            .setFamily(family)
470            .setQualifier(qualifier)
471            .setTimestamp(timestamp)
472            .setType(type)
473            .setValue(value)
474            .build();
475  }
476
477  /**
478   * Creates a cell with deep copy of all passed bytes.
479   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0. Use {@link CellBuilder}
480   *             instead
481   */
482  @Deprecated
483  public static Cell createCell(final byte[] rowArray, final int rowOffset, final int rowLength,
484      final byte[] familyArray, final int familyOffset, final int familyLength,
485      final byte[] qualifierArray, final int qualifierOffset, final int qualifierLength) {
486    // See createCell(final byte [] row, final byte [] value) for why we default Maximum type.
487    return ExtendedCellBuilderFactory.create(CellBuilderType.DEEP_COPY)
488            .setRow(rowArray, rowOffset, rowLength)
489            .setFamily(familyArray, familyOffset, familyLength)
490            .setQualifier(qualifierArray, qualifierOffset, qualifierLength)
491            .setTimestamp(HConstants.LATEST_TIMESTAMP)
492            .setType(KeyValue.Type.Maximum.getCode())
493            .setValue(HConstants.EMPTY_BYTE_ARRAY, 0, HConstants.EMPTY_BYTE_ARRAY.length)
494            .build();
495  }
496
497  /**
498   * Marked as audience Private as of 1.2.0.
499   * Creating a Cell with a memstoreTS/mvcc is an internal
500   * implementation detail not for public use.
501   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0. Use
502   *             {@link ExtendedCellBuilder} instead
503   */
504  @InterfaceAudience.Private
505  @Deprecated
506  public static Cell createCell(final byte[] row, final byte[] family, final byte[] qualifier,
507      final long timestamp, final byte type, final byte[] value, final long memstoreTS) {
508    return createCell(row, family, qualifier, timestamp, type, value, null, memstoreTS);
509  }
510
511  /**
512   * Marked as audience Private as of 1.2.0.
513   * Creating a Cell with tags and a memstoreTS/mvcc is an
514   * internal implementation detail not for public use.
515   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0. Use
516   *             {@link ExtendedCellBuilder} instead
517   */
518  @InterfaceAudience.Private
519  @Deprecated
520  public static Cell createCell(final byte[] row, final byte[] family, final byte[] qualifier,
521      final long timestamp, final byte type, final byte[] value, byte[] tags,
522      final long memstoreTS) {
523    return ExtendedCellBuilderFactory.create(CellBuilderType.DEEP_COPY)
524            .setRow(row)
525            .setFamily(family)
526            .setQualifier(qualifier)
527            .setTimestamp(timestamp)
528            .setType(type)
529            .setValue(value)
530            .setTags(tags)
531            .setSequenceId(memstoreTS)
532            .build();
533  }
534
535  /**
536   * Marked as audience Private as of 1.2.0.
537   * Creating a Cell with tags is an internal implementation detail not for public use.
538   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0. Use
539   *             {@link ExtendedCellBuilder} instead
540   */
541  @InterfaceAudience.Private
542  @Deprecated
543  public static Cell createCell(final byte[] row, final byte[] family, final byte[] qualifier,
544      final long timestamp, Type type, final byte[] value, byte[] tags) {
545    return createCell(row, family, qualifier, timestamp, type.getCode(), value, tags, 0);
546  }
547
548  /**
549   * Create a Cell with specific row. Other fields defaulted.
550   * @param row
551   * @return Cell with passed row but all other fields are arbitrary
552   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0. Use {@link CellBuilder}
553   *             instead
554   */
555  @Deprecated
556  public static Cell createCell(final byte[] row) {
557    return createCell(row, HConstants.EMPTY_BYTE_ARRAY);
558  }
559
560  /**
561   * Create a Cell with specific row and value. Other fields are defaulted.
562   * @param row
563   * @param value
564   * @return Cell with passed row and value but all other fields are arbitrary
565   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0. Use {@link CellBuilder}
566   *             instead
567   */
568  @Deprecated
569  public static Cell createCell(final byte[] row, final byte[] value) {
570    // An empty family + empty qualifier + Type.Minimum is used as flag to indicate last on row.
571    // See the CellComparator and KeyValue comparator. Search for compareWithoutRow.
572    // Lets not make a last-on-row key as default but at same time, if you are making a key
573    // without specifying type, etc., flag it as weird by setting type to be Maximum.
574    return createCell(row, HConstants.EMPTY_BYTE_ARRAY, HConstants.EMPTY_BYTE_ARRAY,
575      HConstants.LATEST_TIMESTAMP, KeyValue.Type.Maximum.getCode(), value);
576  }
577
578  /**
579   * Create a Cell with specific row. Other fields defaulted.
580   * @param row
581   * @param family
582   * @param qualifier
583   * @return Cell with passed row but all other fields are arbitrary
584   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0. Use {@link CellBuilder}
585   *             instead
586   */
587  @Deprecated
588  public static Cell createCell(final byte[] row, final byte[] family, final byte[] qualifier) {
589    // See above in createCell(final byte [] row, final byte [] value) why we set type to Maximum.
590    return createCell(row, family, qualifier, HConstants.LATEST_TIMESTAMP,
591      KeyValue.Type.Maximum.getCode(), HConstants.EMPTY_BYTE_ARRAY);
592  }
593
594  /**
595   * Note : Now only CPs can create cell with tags using the CP environment
596   * @return A new cell which is having the extra tags also added to it.
597   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0.
598   *
599   */
600  @Deprecated
601  public static Cell createCell(Cell cell, List<Tag> tags) {
602    return PrivateCellUtil.createCell(cell, tags);
603  }
604
605  /**
606   * Now only CPs can create cell with tags using the CP environment
607   * @return A new cell which is having the extra tags also added to it.
608   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0.
609   */
610  @Deprecated
611  public static Cell createCell(Cell cell, byte[] tags) {
612    return PrivateCellUtil.createCell(cell, tags);
613  }
614
615  /**
616   * Now only CPs can create cell with tags using the CP environment
617   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0.
618   */
619  @Deprecated
620  public static Cell createCell(Cell cell, byte[] value, byte[] tags) {
621    return PrivateCellUtil.createCell(cell, value, tags);
622  }
623
624  /**
625   * @param cellScannerables
626   * @return CellScanner interface over <code>cellIterables</code>
627   */
628  public static CellScanner
629      createCellScanner(final List<? extends CellScannable> cellScannerables) {
630    return new CellScanner() {
631      private final Iterator<? extends CellScannable> iterator = cellScannerables.iterator();
632      private CellScanner cellScanner = null;
633
634      @Override
635      public Cell current() {
636        return this.cellScanner != null ? this.cellScanner.current() : null;
637      }
638
639      @Override
640      public boolean advance() throws IOException {
641        while (true) {
642          if (this.cellScanner == null) {
643            if (!this.iterator.hasNext()) return false;
644            this.cellScanner = this.iterator.next().cellScanner();
645          }
646          if (this.cellScanner.advance()) return true;
647          this.cellScanner = null;
648        }
649      }
650    };
651  }
652
653  /**
654   * @param cellIterable
655   * @return CellScanner interface over <code>cellIterable</code>
656   */
657  public static CellScanner createCellScanner(final Iterable<Cell> cellIterable) {
658    if (cellIterable == null) return null;
659    return createCellScanner(cellIterable.iterator());
660  }
661
662  /**
663   * @param cells
664   * @return CellScanner interface over <code>cellIterable</code> or null if <code>cells</code> is
665   *         null
666   */
667  public static CellScanner createCellScanner(final Iterator<Cell> cells) {
668    if (cells == null) return null;
669    return new CellScanner() {
670      private final Iterator<Cell> iterator = cells;
671      private Cell current = null;
672
673      @Override
674      public Cell current() {
675        return this.current;
676      }
677
678      @Override
679      public boolean advance() {
680        boolean hasNext = this.iterator.hasNext();
681        this.current = hasNext ? this.iterator.next() : null;
682        return hasNext;
683      }
684    };
685  }
686
687  /**
688   * @param cellArray
689   * @return CellScanner interface over <code>cellArray</code>
690   */
691  public static CellScanner createCellScanner(final Cell[] cellArray) {
692    return new CellScanner() {
693      private final Cell[] cells = cellArray;
694      private int index = -1;
695
696      @Override
697      public Cell current() {
698        if (cells == null) return null;
699        return (index < 0) ? null : this.cells[index];
700      }
701
702      @Override
703      public boolean advance() {
704        if (cells == null) return false;
705        return ++index < this.cells.length;
706      }
707    };
708  }
709
710  /**
711   * Flatten the map of cells out under the CellScanner
712   * @param map Map of Cell Lists; for example, the map of families to Cells that is used inside
713   *          Put, etc., keeping Cells organized by family.
714   * @return CellScanner interface over <code>cellIterable</code>
715   */
716  public static CellScanner createCellScanner(final NavigableMap<byte[], List<Cell>> map) {
717    return new CellScanner() {
718      private final Iterator<Entry<byte[], List<Cell>>> entries = map.entrySet().iterator();
719      private Iterator<Cell> currentIterator = null;
720      private Cell currentCell;
721
722      @Override
723      public Cell current() {
724        return this.currentCell;
725      }
726
727      @Override
728      public boolean advance() {
729        while (true) {
730          if (this.currentIterator == null) {
731            if (!this.entries.hasNext()) return false;
732            this.currentIterator = this.entries.next().getValue().iterator();
733          }
734          if (this.currentIterator.hasNext()) {
735            this.currentCell = this.currentIterator.next();
736            return true;
737          }
738          this.currentCell = null;
739          this.currentIterator = null;
740        }
741      }
742    };
743  }
744
745  /**
746   * @param left
747   * @param right
748   * @return True if the rows in <code>left</code> and <code>right</code> Cells match
749   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0. Instead use
750   *             {@link #matchingRows(Cell, Cell)}
751   */
752  @Deprecated
753  public static boolean matchingRow(final Cell left, final Cell right) {
754    return matchingRows(left, right);
755  }
756
757  /**
758   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0. Instead use
759   *   {@link #matchingRows(Cell, byte[])}
760   */
761  @Deprecated
762  public static boolean matchingRow(final Cell left, final byte[] buf) {
763    return matchingRows(left, buf);
764  }
765
766  public static boolean matchingRows(final Cell left, final byte[] buf) {
767    if (buf == null) {
768      return left.getRowLength() == 0;
769    }
770    return PrivateCellUtil.matchingRows(left, buf, 0, buf.length);
771  }
772
773  /**
774   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0. Instead use
775   *             {@link #matchingRows(Cell, Cell)}
776   * @return true if the row is matching
777   */
778  @Deprecated
779  public static boolean matchingRow(final Cell left, final byte[] buf, final int offset,
780      final int length) {
781    if (left instanceof ByteBufferExtendedCell) {
782      return ByteBufferUtils.equals(((ByteBufferExtendedCell) left).getRowByteBuffer(),
783        ((ByteBufferExtendedCell) left).getRowPosition(), left.getRowLength(), buf, offset, length);
784    }
785    return Bytes.equals(left.getRowArray(), left.getRowOffset(), left.getRowLength(), buf, offset,
786      length);
787  }
788
789  public static boolean matchingFamily(final Cell left, final Cell right) {
790    byte lfamlength = left.getFamilyLength();
791    byte rfamlength = right.getFamilyLength();
792    return matchingFamily(left, lfamlength, right, rfamlength);
793  }
794
795  public static boolean matchingFamily(final Cell left, final byte lfamlength, final Cell right,
796      final byte rfamlength) {
797    if (left instanceof ByteBufferExtendedCell && right instanceof ByteBufferExtendedCell) {
798      return ByteBufferUtils.equals(((ByteBufferExtendedCell) left).getFamilyByteBuffer(),
799        ((ByteBufferExtendedCell) left).getFamilyPosition(), lfamlength,
800        ((ByteBufferExtendedCell) right).getFamilyByteBuffer(),
801        ((ByteBufferExtendedCell) right).getFamilyPosition(), rfamlength);
802    }
803    if (left instanceof ByteBufferExtendedCell) {
804      return ByteBufferUtils.equals(((ByteBufferExtendedCell) left).getFamilyByteBuffer(),
805        ((ByteBufferExtendedCell) left).getFamilyPosition(), lfamlength, right.getFamilyArray(),
806        right.getFamilyOffset(), rfamlength);
807    }
808    if (right instanceof ByteBufferExtendedCell) {
809      return ByteBufferUtils.equals(((ByteBufferExtendedCell) right).getFamilyByteBuffer(),
810        ((ByteBufferExtendedCell) right).getFamilyPosition(), rfamlength, left.getFamilyArray(),
811        left.getFamilyOffset(), lfamlength);
812    }
813    return Bytes.equals(left.getFamilyArray(), left.getFamilyOffset(), lfamlength,
814      right.getFamilyArray(), right.getFamilyOffset(), rfamlength);
815  }
816
817  public static boolean matchingFamily(final Cell left, final byte[] buf) {
818    if (buf == null) {
819      return left.getFamilyLength() == 0;
820    }
821    return PrivateCellUtil.matchingFamily(left, buf, 0, buf.length);
822  }
823
824  /**
825   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0.
826   */
827  @Deprecated
828  public static boolean matchingFamily(final Cell left, final byte[] buf, final int offset,
829    final int length) {
830    if (left instanceof ByteBufferExtendedCell) {
831      return ByteBufferUtils.equals(((ByteBufferExtendedCell) left).getFamilyByteBuffer(),
832        ((ByteBufferExtendedCell) left).getFamilyPosition(), left.getFamilyLength(), buf, offset,
833        length);
834    }
835    return Bytes
836      .equals(left.getFamilyArray(), left.getFamilyOffset(), left.getFamilyLength(), buf, offset,
837        length);
838  }
839
840  public static boolean matchingQualifier(final Cell left, final Cell right) {
841    int lqlength = left.getQualifierLength();
842    int rqlength = right.getQualifierLength();
843    return matchingQualifier(left, lqlength, right, rqlength);
844  }
845
846  private static boolean matchingQualifier(final Cell left, final int lqlength, final Cell right,
847      final int rqlength) {
848    if (left instanceof ByteBufferExtendedCell && right instanceof ByteBufferExtendedCell) {
849      return ByteBufferUtils.equals(((ByteBufferExtendedCell) left).getQualifierByteBuffer(),
850        ((ByteBufferExtendedCell) left).getQualifierPosition(), lqlength,
851        ((ByteBufferExtendedCell) right).getQualifierByteBuffer(),
852        ((ByteBufferExtendedCell) right).getQualifierPosition(), rqlength);
853    }
854    if (left instanceof ByteBufferExtendedCell) {
855      return ByteBufferUtils.equals(((ByteBufferExtendedCell) left).getQualifierByteBuffer(),
856        ((ByteBufferExtendedCell) left).getQualifierPosition(), lqlength, right.getQualifierArray(),
857        right.getQualifierOffset(), rqlength);
858    }
859    if (right instanceof ByteBufferExtendedCell) {
860      return ByteBufferUtils.equals(((ByteBufferExtendedCell) right).getQualifierByteBuffer(),
861        ((ByteBufferExtendedCell) right).getQualifierPosition(), rqlength, left.getQualifierArray(),
862        left.getQualifierOffset(), lqlength);
863    }
864    return Bytes.equals(left.getQualifierArray(), left.getQualifierOffset(), lqlength,
865      right.getQualifierArray(), right.getQualifierOffset(), rqlength);
866  }
867
868  /**
869   * Finds if the qualifier part of the cell and the KV serialized byte[] are equal
870   * @param left
871   * @param buf the serialized keyvalue format byte[]
872   * @return true if the qualifier matches, false otherwise
873   */
874  public static boolean matchingQualifier(final Cell left, final byte[] buf) {
875    if (buf == null) {
876      return left.getQualifierLength() == 0;
877    }
878    return PrivateCellUtil.matchingQualifier(left, buf, 0, buf.length);
879  }
880
881  /**
882   * Finds if the qualifier part of the cell and the KV serialized byte[] are equal
883   * @param left
884   * @param buf the serialized keyvalue format byte[]
885   * @param offset the offset of the qualifier in the byte[]
886   * @param length the length of the qualifier in the byte[]
887   * @return true if the qualifier matches, false otherwise
888   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0.
889   */
890  @Deprecated
891  public static boolean matchingQualifier(final Cell left, final byte[] buf, final int offset,
892    final int length) {
893    if (buf == null) {
894      return left.getQualifierLength() == 0;
895    }
896    if (left instanceof ByteBufferExtendedCell) {
897      return ByteBufferUtils.equals(((ByteBufferExtendedCell) left).getQualifierByteBuffer(),
898        ((ByteBufferExtendedCell) left).getQualifierPosition(), left.getQualifierLength(), buf,
899        offset, length);
900    }
901    return Bytes
902      .equals(left.getQualifierArray(), left.getQualifierOffset(), left.getQualifierLength(), buf,
903        offset, length);
904  }
905
906  public static boolean matchingColumn(final Cell left, final byte[] fam, final byte[] qual) {
907    return matchingFamily(left, fam) && matchingQualifier(left, qual);
908  }
909
910  /**
911   * @return True if matching column family and the qualifier starts with <code>qual</code>
912   */
913  public static boolean matchingColumnFamilyAndQualifierPrefix(final Cell left, final byte[] fam,
914      final byte[] qual) {
915    return matchingFamily(left, fam) && PrivateCellUtil.qualifierStartsWith(left, qual);
916  }
917
918  /**
919   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0.
920   */
921  @Deprecated
922  public static boolean matchingColumn(final Cell left, final byte[] fam, final int foffset,
923      final int flength, final byte[] qual, final int qoffset, final int qlength) {
924    if (!PrivateCellUtil.matchingFamily(left, fam, foffset, flength)) return false;
925    return PrivateCellUtil.matchingQualifier(left, qual, qoffset, qlength);
926  }
927
928  public static boolean matchingColumn(final Cell left, final Cell right) {
929    if (!matchingFamily(left, right)) return false;
930    return matchingQualifier(left, right);
931  }
932
933  private static boolean matchingColumn(final Cell left, final byte lFamLen, final int lQualLength,
934      final Cell right, final byte rFamLen, final int rQualLength) {
935    if (!matchingFamily(left, lFamLen, right, rFamLen)) {
936      return false;
937    }
938    return matchingQualifier(left, lQualLength, right, rQualLength);
939  }
940
941  public static boolean matchingValue(final Cell left, final Cell right) {
942    return PrivateCellUtil.matchingValue(left, right, left.getValueLength(),
943      right.getValueLength());
944  }
945
946  public static boolean matchingValue(final Cell left, final byte[] buf) {
947    if (left instanceof ByteBufferExtendedCell) {
948      return ByteBufferUtils.compareTo(((ByteBufferExtendedCell) left).getValueByteBuffer(),
949        ((ByteBufferExtendedCell) left).getValuePosition(), left.getValueLength(), buf, 0,
950        buf.length) == 0;
951    }
952    return Bytes.equals(left.getValueArray(), left.getValueOffset(), left.getValueLength(), buf, 0,
953      buf.length);
954  }
955
956  /**
957   * @return True if a delete type, a {@link KeyValue.Type#Delete} or a {KeyValue.Type#DeleteFamily}
958   *         or a {@link KeyValue.Type#DeleteColumn} KeyValue type.
959   */
960  @SuppressWarnings("deprecation")
961  public static boolean isDelete(final Cell cell) {
962    return PrivateCellUtil.isDelete(cell.getTypeByte());
963  }
964
965  /**
966   * @return True if a delete type, a {@link KeyValue.Type#Delete} or a {KeyValue.Type#DeleteFamily}
967   *         or a {@link KeyValue.Type#DeleteColumn} KeyValue type.
968   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0.
969   */
970  @Deprecated
971  public static boolean isDelete(final byte type) {
972    return Type.Delete.getCode() <= type && type <= Type.DeleteFamily.getCode();
973  }
974
975  /**
976   * @return True if this cell is a {@link KeyValue.Type#Delete} type.
977   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0.
978   */
979  @Deprecated
980  public static boolean isDeleteType(Cell cell) {
981    return cell.getTypeByte() == Type.Delete.getCode();
982  }
983
984  /**
985   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0.
986   */
987  @Deprecated
988  public static boolean isDeleteFamily(final Cell cell) {
989    return cell.getTypeByte() == Type.DeleteFamily.getCode();
990  }
991
992  /**
993   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0.
994   */
995  @Deprecated
996  public static boolean isDeleteFamilyVersion(final Cell cell) {
997    return cell.getTypeByte() == Type.DeleteFamilyVersion.getCode();
998  }
999
1000  /**
1001   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0.
1002   */
1003  @Deprecated
1004  public static boolean isDeleteColumns(final Cell cell) {
1005    return cell.getTypeByte() == Type.DeleteColumn.getCode();
1006  }
1007
1008  /**
1009   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0.
1010   */
1011  @Deprecated
1012  public static boolean isDeleteColumnVersion(final Cell cell) {
1013    return cell.getTypeByte() == Type.Delete.getCode();
1014  }
1015
1016  /**
1017   * @return True if this cell is a delete family or column type.
1018   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0.
1019   */
1020  @Deprecated
1021  public static boolean isDeleteColumnOrFamily(Cell cell) {
1022    int t = cell.getTypeByte();
1023    return t == Type.DeleteColumn.getCode() || t == Type.DeleteFamily.getCode();
1024  }
1025
1026  /**
1027   * @return True if this cell is a Put.
1028   */
1029  @SuppressWarnings("deprecation")
1030  public static boolean isPut(Cell cell) {
1031    return cell.getTypeByte() == Type.Put.getCode();
1032  }
1033
1034  /**
1035   * Estimate based on keyvalue's serialization format in the RPC layer. Note that there is an extra
1036   * SIZEOF_INT added to the size here that indicates the actual length of the cell for cases where
1037   * cell's are serialized in a contiguous format (For eg in RPCs).
1038   * @param cell
1039   * @return Estimate of the <code>cell</code> size in bytes plus an extra SIZEOF_INT indicating the
1040   *         actual cell length.
1041   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0.
1042   */
1043  @Deprecated
1044  public static int estimatedSerializedSizeOf(final Cell cell) {
1045    if (cell instanceof ExtendedCell) {
1046      return ((ExtendedCell) cell).getSerializedSize(true) + Bytes.SIZEOF_INT;
1047    }
1048
1049    return getSumOfCellElementLengths(cell) +
1050    // Use the KeyValue's infrastructure size presuming that another implementation would have
1051    // same basic cost.
1052        KeyValue.ROW_LENGTH_SIZE + KeyValue.FAMILY_LENGTH_SIZE +
1053        // Serialization is probably preceded by a length (it is in the KeyValueCodec at least).
1054        Bytes.SIZEOF_INT;
1055  }
1056
1057  /**
1058   * @param cell
1059   * @return Sum of the lengths of all the elements in a Cell; does not count in any infrastructure
1060   */
1061  private static int getSumOfCellElementLengths(final Cell cell) {
1062    return getSumOfCellKeyElementLengths(cell) + cell.getValueLength() + cell.getTagsLength();
1063  }
1064
1065  /**
1066   * @param cell
1067   * @return Sum of all elements that make up a key; does not include infrastructure, tags or
1068   *         values.
1069   */
1070  private static int getSumOfCellKeyElementLengths(final Cell cell) {
1071    return cell.getRowLength() + cell.getFamilyLength() + cell.getQualifierLength()
1072        + KeyValue.TIMESTAMP_TYPE_SIZE;
1073  }
1074
1075  /**
1076   * Calculates the serialized key size. We always serialize in the KeyValue's serialization format.
1077   * @param cell the cell for which the key size has to be calculated.
1078   * @return the key size
1079   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0.
1080   */
1081  @Deprecated
1082  public static int estimatedSerializedSizeOfKey(final Cell cell) {
1083    if (cell instanceof KeyValue) return ((KeyValue) cell).getKeyLength();
1084    return cell.getRowLength() + cell.getFamilyLength() + cell.getQualifierLength()
1085        + KeyValue.KEY_INFRASTRUCTURE_SIZE;
1086  }
1087
1088  /**
1089   * This is an estimate of the heap space occupied by a cell. When the cell is of type
1090   * {@link HeapSize} we call {@link HeapSize#heapSize()} so cell can give a correct value. In other
1091   * cases we just consider the bytes occupied by the cell components ie. row, CF, qualifier,
1092   * timestamp, type, value and tags.
1093   * @param cell
1094   * @return estimate of the heap space
1095   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0.
1096   *             Use {@link RawCell#getTags()}
1097   */
1098  @Deprecated
1099  public static long estimatedHeapSizeOf(final Cell cell) {
1100    return cell.heapSize();
1101  }
1102
1103  /********************* tags *************************************/
1104  /**
1105   * Util method to iterate through the tags
1106   * @param tags
1107   * @param offset
1108   * @param length
1109   * @return iterator for the tags
1110   * @deprecated As of 2.0.0 and will be removed in 3.0.0 Instead use
1111   *             {@link PrivateCellUtil#tagsIterator(Cell)}
1112   */
1113  @Deprecated
1114  public static Iterator<Tag> tagsIterator(final byte[] tags, final int offset, final int length) {
1115    return new Iterator<Tag>() {
1116      private int pos = offset;
1117      private int endOffset = offset + length - 1;
1118
1119      @Override
1120      public boolean hasNext() {
1121        return this.pos < endOffset;
1122      }
1123
1124      @Override
1125      public Tag next() {
1126        if (hasNext()) {
1127          int curTagLen = Bytes.readAsInt(tags, this.pos, Tag.TAG_LENGTH_SIZE);
1128          Tag tag = new ArrayBackedTag(tags, pos, curTagLen + TAG_LENGTH_SIZE);
1129          this.pos += Bytes.SIZEOF_SHORT + curTagLen;
1130          return tag;
1131        }
1132        return null;
1133      }
1134
1135      @Override
1136      public void remove() {
1137        throw new UnsupportedOperationException();
1138      }
1139    };
1140  }
1141
1142  /**
1143   * @param cell The Cell
1144   * @return Tags in the given Cell as a List
1145   * @deprecated As of 2.0.0 and will be removed in 3.0.0
1146   */
1147  @Deprecated
1148  public static List<Tag> getTags(Cell cell) {
1149    List<Tag> tags = new ArrayList<>();
1150    Iterator<Tag> tagsItr = PrivateCellUtil.tagsIterator(cell);
1151    while (tagsItr.hasNext()) {
1152      tags.add(tagsItr.next());
1153    }
1154    return tags;
1155  }
1156
1157  /**
1158   * Retrieve Cell's first tag, matching the passed in type
1159   * @param cell The Cell
1160   * @param type Type of the Tag to retrieve
1161   * @return null if there is no tag of the passed in tag type
1162   * @deprecated As of 2.0.0 and will be removed in HBase-3.0.0
1163   *             Use {@link RawCell#getTag(byte)}
1164   */
1165  @Deprecated
1166  public static Tag getTag(Cell cell, byte type) {
1167    Optional<Tag> tag = PrivateCellUtil.getTag(cell, type);
1168    if (tag.isPresent()) {
1169      return tag.get();
1170    } else {
1171      return null;
1172    }
1173  }
1174
1175  /**
1176   * Returns true if the first range start1...end1 overlaps with the second range start2...end2,
1177   * assuming the byte arrays represent row keys
1178   * @deprecated As of 2.0.0 and will be removed in 3.0.0
1179   */
1180  @Deprecated
1181  public static boolean overlappingKeys(final byte[] start1, final byte[] end1, final byte[] start2,
1182      final byte[] end2) {
1183    return (end2.length == 0 || start1.length == 0 || Bytes.compareTo(start1, end2) < 0)
1184        && (end1.length == 0 || start2.length == 0 || Bytes.compareTo(start2, end1) < 0);
1185  }
1186
1187  /**
1188   * Sets the given seqId to the cell. Marked as audience Private as of 1.2.0. Setting a Cell
1189   * sequenceid is an internal implementation detail not for general public use.
1190   * @param cell
1191   * @param seqId
1192   * @throws IOException when the passed cell is not of type {@link ExtendedCell}
1193   * @deprecated As of HBase-2.0. Will be removed in HBase-3.0
1194   */
1195  @Deprecated
1196  public static void setSequenceId(Cell cell, long seqId) throws IOException {
1197    PrivateCellUtil.setSequenceId(cell, seqId);
1198  }
1199
1200  /**
1201   * Sets the given timestamp to the cell.
1202   * @param cell
1203   * @param ts
1204   * @throws IOException when the passed cell is not of type {@link ExtendedCell}
1205   * @deprecated As of HBase-2.0. Will be a LimitedPrivate API in HBase-3.0.
1206   */
1207  @Deprecated
1208  public static void setTimestamp(Cell cell, long ts) throws IOException {
1209    PrivateCellUtil.setTimestamp(cell, ts);
1210  }
1211
1212  /**
1213   * Sets the given timestamp to the cell.
1214   * @param cell
1215   * @param ts buffer containing the timestamp value
1216   * @param tsOffset offset to the new timestamp
1217   * @throws IOException when the passed cell is not of type {@link ExtendedCell}
1218   * @deprecated As of HBase-2.0. Will be a LimitedPrivate API in HBase-3.0.
1219   */
1220  @Deprecated
1221  public static void setTimestamp(Cell cell, byte[] ts, int tsOffset) throws IOException {
1222    PrivateCellUtil.setTimestamp(cell, Bytes.toLong(ts, tsOffset));
1223  }
1224
1225  /**
1226   * Sets the given timestamp to the cell iff current timestamp is
1227   * {@link HConstants#LATEST_TIMESTAMP}.
1228   * @param cell
1229   * @param ts
1230   * @return True if cell timestamp is modified.
1231   * @throws IOException when the passed cell is not of type {@link ExtendedCell}
1232   * @deprecated As of HBase-2.0. Will be removed in HBase-3.0
1233   */
1234  @Deprecated
1235  public static boolean updateLatestStamp(Cell cell, long ts) throws IOException {
1236    return PrivateCellUtil.updateLatestStamp(cell, ts);
1237  }
1238
1239  /**
1240   * Sets the given timestamp to the cell iff current timestamp is
1241   * {@link HConstants#LATEST_TIMESTAMP}.
1242   * @param cell
1243   * @param ts buffer containing the timestamp value
1244   * @param tsOffset offset to the new timestamp
1245   * @return True if cell timestamp is modified.
1246   * @throws IOException when the passed cell is not of type {@link ExtendedCell}
1247   * @deprecated As of HBase-2.0. Will be removed in HBase-3.0
1248   */
1249  @Deprecated
1250  public static boolean updateLatestStamp(Cell cell, byte[] ts, int tsOffset) throws IOException {
1251    return PrivateCellUtil.updateLatestStamp(cell, Bytes.toLong(ts, tsOffset));
1252  }
1253
1254  /**
1255   * Writes the Cell's key part as it would have serialized in a KeyValue. The format is &lt;2 bytes
1256   * rk len&gt;&lt;rk&gt;&lt;1 byte cf len&gt;&lt;cf&gt;&lt;qualifier&gt;&lt;8 bytes
1257   * timestamp&gt;&lt;1 byte type&gt;
1258   * @param cell
1259   * @param out
1260   * @deprecated As of HBase-2.0. Will be removed in HBase-3.0
1261   * @throws IOException
1262   */
1263  @Deprecated
1264  public static void writeFlatKey(Cell cell, DataOutputStream out) throws IOException {
1265    short rowLen = cell.getRowLength();
1266    byte fLen = cell.getFamilyLength();
1267    int qLen = cell.getQualifierLength();
1268    // Using just one if/else loop instead of every time checking before writing every
1269    // component of cell
1270    if (cell instanceof ByteBufferExtendedCell) {
1271      out.writeShort(rowLen);
1272      ByteBufferUtils
1273        .copyBufferToStream((DataOutput) out, ((ByteBufferExtendedCell) cell).getRowByteBuffer(),
1274          ((ByteBufferExtendedCell) cell).getRowPosition(), rowLen);
1275      out.writeByte(fLen);
1276      ByteBufferUtils
1277        .copyBufferToStream((DataOutput) out, ((ByteBufferExtendedCell) cell).getFamilyByteBuffer(),
1278          ((ByteBufferExtendedCell) cell).getFamilyPosition(), fLen);
1279      ByteBufferUtils.copyBufferToStream((DataOutput) out,
1280        ((ByteBufferExtendedCell) cell).getQualifierByteBuffer(),
1281        ((ByteBufferExtendedCell) cell).getQualifierPosition(), qLen);
1282    } else {
1283      out.writeShort(rowLen);
1284      out.write(cell.getRowArray(), cell.getRowOffset(), rowLen);
1285      out.writeByte(fLen);
1286      out.write(cell.getFamilyArray(), cell.getFamilyOffset(), fLen);
1287      out.write(cell.getQualifierArray(), cell.getQualifierOffset(), qLen);
1288    }
1289    out.writeLong(cell.getTimestamp());
1290    out.writeByte(cell.getTypeByte());
1291  }
1292
1293  /**
1294   * Writes the row from the given cell to the output stream excluding the common prefix
1295   * @param out The dataoutputstream to which the data has to be written
1296   * @param cell The cell whose contents has to be written
1297   * @param rlength the row length
1298   * @throws IOException
1299   * @deprecated As of 2.0. Will be removed in hbase-3.0
1300   */
1301  @Deprecated
1302  public static void writeRowSkippingBytes(DataOutputStream out, Cell cell, short rlength,
1303    int commonPrefix) throws IOException {
1304    if (cell instanceof ByteBufferExtendedCell) {
1305      ByteBufferUtils
1306        .copyBufferToStream((DataOutput) out, ((ByteBufferExtendedCell) cell).getRowByteBuffer(),
1307          ((ByteBufferExtendedCell) cell).getRowPosition() + commonPrefix, rlength - commonPrefix);
1308    } else {
1309      out.write(cell.getRowArray(), cell.getRowOffset() + commonPrefix, rlength - commonPrefix);
1310    }
1311  }
1312
1313  /**
1314   * @param cell
1315   * @return The Key portion of the passed <code>cell</code> as a String.
1316   */
1317  public static String getCellKeyAsString(Cell cell) {
1318    return getCellKeyAsString(cell,
1319      c -> Bytes.toStringBinary(c.getRowArray(), c.getRowOffset(), c.getRowLength()));
1320  }
1321
1322  /**
1323   * @param cell the cell to convert
1324   * @param rowConverter used to convert the row of the cell to a string
1325   * @return The Key portion of the passed <code>cell</code> as a String.
1326   */
1327  public static String getCellKeyAsString(Cell cell, Function<Cell, String> rowConverter) {
1328    StringBuilder sb = new StringBuilder(rowConverter.apply(cell));
1329    sb.append('/');
1330    sb.append(cell.getFamilyLength() == 0 ? "" :
1331      Bytes.toStringBinary(cell.getFamilyArray(), cell.getFamilyOffset(), cell.getFamilyLength()));
1332    // KeyValue only added ':' if family is non-null. Do same.
1333    if (cell.getFamilyLength() > 0) sb.append(':');
1334    sb.append(cell.getQualifierLength() == 0 ? "" :
1335      Bytes.toStringBinary(cell.getQualifierArray(), cell.getQualifierOffset(),
1336        cell.getQualifierLength()));
1337    sb.append('/');
1338    sb.append(KeyValue.humanReadableTimestamp(cell.getTimestamp()));
1339    sb.append('/');
1340    sb.append(Type.codeToType(cell.getTypeByte()));
1341    if (!(cell instanceof KeyValue.KeyOnlyKeyValue)) {
1342      sb.append("/vlen=");
1343      sb.append(cell.getValueLength());
1344    }
1345    sb.append("/seqid=");
1346    sb.append(cell.getSequenceId());
1347    return sb.toString();
1348  }
1349
1350  /**
1351   * This method exists just to encapsulate how we serialize keys. To be replaced by a factory that
1352   * we query to figure what the Cell implementation is and then, what serialization engine to use
1353   * and further, how to serialize the key for inclusion in hfile index. TODO.
1354   * @param cell
1355   * @return The key portion of the Cell serialized in the old-school KeyValue way or null if passed
1356   *         a null <code>cell</code>
1357   * @deprecated As of HBase-2.0. Will be removed in HBase-3.0
1358   */
1359  @Deprecated
1360  public static byte[] getCellKeySerializedAsKeyValueKey(final Cell cell) {
1361    if (cell == null) return null;
1362    byte[] b = new byte[KeyValueUtil.keyLength(cell)];
1363    KeyValueUtil.appendKeyTo(cell, b, 0);
1364    return b;
1365  }
1366
1367  /**
1368   * Write rowkey excluding the common part.
1369   * @param cell
1370   * @param rLen
1371   * @param commonPrefix
1372   * @param out
1373   * @throws IOException
1374   * @deprecated As of HBase-2.0. Will be removed in HBase-3.0
1375   */
1376  @Deprecated
1377  public static void writeRowKeyExcludingCommon(Cell cell, short rLen, int commonPrefix,
1378      DataOutputStream out) throws IOException {
1379    if (commonPrefix == 0) {
1380      out.writeShort(rLen);
1381    } else if (commonPrefix == 1) {
1382      out.writeByte((byte) rLen);
1383      commonPrefix--;
1384    } else {
1385      commonPrefix -= KeyValue.ROW_LENGTH_SIZE;
1386    }
1387    if (rLen > commonPrefix) {
1388      PrivateCellUtil.writeRowSkippingBytes(out, cell, rLen, commonPrefix);
1389    }
1390  }
1391
1392  /**
1393   * Find length of common prefix in keys of the cells, considering key as byte[] if serialized in
1394   * {@link KeyValue}. The key format is &lt;2 bytes rk len&gt;&lt;rk&gt;&lt;1 byte cf
1395   * len&gt;&lt;cf&gt;&lt;qualifier&gt;&lt;8 bytes timestamp&gt;&lt;1 byte type&gt;
1396   * @param c1 the cell
1397   * @param c2 the cell
1398   * @param bypassFamilyCheck when true assume the family bytes same in both cells. Pass it as true
1399   *          when dealing with Cells in same CF so as to avoid some checks
1400   * @param withTsType when true check timestamp and type bytes also.
1401   * @return length of common prefix
1402   * @deprecated As of HBase-2.0. Will be removed in HBase-3.0
1403   */
1404  @Deprecated
1405  public static int findCommonPrefixInFlatKey(Cell c1, Cell c2, boolean bypassFamilyCheck,
1406    boolean withTsType) {
1407    // Compare the 2 bytes in RK length part
1408    short rLen1 = c1.getRowLength();
1409    short rLen2 = c2.getRowLength();
1410    int commonPrefix = KeyValue.ROW_LENGTH_SIZE;
1411    if (rLen1 != rLen2) {
1412      // early out when the RK length itself is not matching
1413      return ByteBufferUtils
1414        .findCommonPrefix(Bytes.toBytes(rLen1), 0, KeyValue.ROW_LENGTH_SIZE, Bytes.toBytes(rLen2),
1415          0, KeyValue.ROW_LENGTH_SIZE);
1416    }
1417    // Compare the RKs
1418    int rkCommonPrefix = 0;
1419    if (c1 instanceof ByteBufferExtendedCell && c2 instanceof ByteBufferExtendedCell) {
1420      rkCommonPrefix = ByteBufferUtils
1421        .findCommonPrefix(((ByteBufferExtendedCell) c1).getRowByteBuffer(),
1422          ((ByteBufferExtendedCell) c1).getRowPosition(), rLen1,
1423          ((ByteBufferExtendedCell) c2).getRowByteBuffer(),
1424          ((ByteBufferExtendedCell) c2).getRowPosition(), rLen2);
1425    } else {
1426      // There cannot be a case where one cell is BBCell and other is KeyValue. This flow comes
1427      // either
1428      // in flush or compactions. In flushes both cells are KV and in case of compaction it will be
1429      // either
1430      // KV or BBCell
1431      rkCommonPrefix = ByteBufferUtils
1432        .findCommonPrefix(c1.getRowArray(), c1.getRowOffset(), rLen1, c2.getRowArray(),
1433          c2.getRowOffset(), rLen2);
1434    }
1435    commonPrefix += rkCommonPrefix;
1436    if (rkCommonPrefix != rLen1) {
1437      // Early out when RK is not fully matching.
1438      return commonPrefix;
1439    }
1440    // Compare 1 byte CF length part
1441    byte fLen1 = c1.getFamilyLength();
1442    if (bypassFamilyCheck) {
1443      // This flag will be true when caller is sure that the family will be same for both the cells
1444      // Just make commonPrefix to increment by the family part
1445      commonPrefix += KeyValue.FAMILY_LENGTH_SIZE + fLen1;
1446    } else {
1447      byte fLen2 = c2.getFamilyLength();
1448      if (fLen1 != fLen2) {
1449        // early out when the CF length itself is not matching
1450        return commonPrefix;
1451      }
1452      // CF lengths are same so there is one more byte common in key part
1453      commonPrefix += KeyValue.FAMILY_LENGTH_SIZE;
1454      // Compare the CF names
1455      int fCommonPrefix;
1456      if (c1 instanceof ByteBufferExtendedCell && c2 instanceof ByteBufferExtendedCell) {
1457        fCommonPrefix = ByteBufferUtils
1458          .findCommonPrefix(((ByteBufferExtendedCell) c1).getFamilyByteBuffer(),
1459            ((ByteBufferExtendedCell) c1).getFamilyPosition(), fLen1,
1460            ((ByteBufferExtendedCell) c2).getFamilyByteBuffer(),
1461            ((ByteBufferExtendedCell) c2).getFamilyPosition(), fLen2);
1462      } else {
1463        fCommonPrefix = ByteBufferUtils
1464          .findCommonPrefix(c1.getFamilyArray(), c1.getFamilyOffset(), fLen1, c2.getFamilyArray(),
1465            c2.getFamilyOffset(), fLen2);
1466      }
1467      commonPrefix += fCommonPrefix;
1468      if (fCommonPrefix != fLen1) {
1469        return commonPrefix;
1470      }
1471    }
1472    // Compare the Qualifiers
1473    int qLen1 = c1.getQualifierLength();
1474    int qLen2 = c2.getQualifierLength();
1475    int qCommon;
1476    if (c1 instanceof ByteBufferExtendedCell && c2 instanceof ByteBufferExtendedCell) {
1477      qCommon = ByteBufferUtils
1478        .findCommonPrefix(((ByteBufferExtendedCell) c1).getQualifierByteBuffer(),
1479          ((ByteBufferExtendedCell) c1).getQualifierPosition(), qLen1,
1480          ((ByteBufferExtendedCell) c2).getQualifierByteBuffer(),
1481          ((ByteBufferExtendedCell) c2).getQualifierPosition(), qLen2);
1482    } else {
1483      qCommon = ByteBufferUtils
1484        .findCommonPrefix(c1.getQualifierArray(), c1.getQualifierOffset(), qLen1,
1485          c2.getQualifierArray(), c2.getQualifierOffset(), qLen2);
1486    }
1487    commonPrefix += qCommon;
1488    if (!withTsType || Math.max(qLen1, qLen2) != qCommon) {
1489      return commonPrefix;
1490    }
1491    // Compare the timestamp parts
1492    int tsCommonPrefix = ByteBufferUtils
1493      .findCommonPrefix(Bytes.toBytes(c1.getTimestamp()), 0, KeyValue.TIMESTAMP_SIZE,
1494        Bytes.toBytes(c2.getTimestamp()), 0, KeyValue.TIMESTAMP_SIZE);
1495    commonPrefix += tsCommonPrefix;
1496    if (tsCommonPrefix != KeyValue.TIMESTAMP_SIZE) {
1497      return commonPrefix;
1498    }
1499    // Compare the type
1500    if (c1.getTypeByte() == c2.getTypeByte()) {
1501      commonPrefix += KeyValue.TYPE_SIZE;
1502    }
1503    return commonPrefix;
1504  }
1505
1506  /** Returns a string representation of the cell */
1507  public static String toString(Cell cell, boolean verbose) {
1508    if (cell == null) {
1509      return "";
1510    }
1511    StringBuilder builder = new StringBuilder();
1512    String keyStr = getCellKeyAsString(cell);
1513
1514    String tag = null;
1515    String value = null;
1516    if (verbose) {
1517      // TODO: pretty print tags as well
1518      if (cell.getTagsLength() > 0) {
1519        tag = Bytes.toStringBinary(cell.getTagsArray(), cell.getTagsOffset(), cell.getTagsLength());
1520      }
1521      if (!(cell instanceof KeyValue.KeyOnlyKeyValue)) {
1522        value = Bytes.toStringBinary(cell.getValueArray(), cell.getValueOffset(),
1523          cell.getValueLength());
1524      }
1525    }
1526
1527    builder.append(keyStr);
1528    if (tag != null && !tag.isEmpty()) {
1529      builder.append("/").append(tag);
1530    }
1531    if (value != null) {
1532      builder.append("/").append(value);
1533    }
1534
1535    return builder.toString();
1536  }
1537
1538  /***************** special cases ****************************/
1539
1540  /**
1541   * special case for Cell.equals
1542   * @deprecated As of HBase-2.0. Will be removed in HBase-3.0
1543   */
1544  @Deprecated
1545  public static boolean equalsIgnoreMvccVersion(Cell a, Cell b) {
1546    // row
1547    boolean res = matchingRows(a, b);
1548    if (!res) return res;
1549
1550    // family
1551    res = matchingColumn(a, b);
1552    if (!res) return res;
1553
1554    // timestamp: later sorts first
1555    if (!matchingTimestamp(a, b)) return false;
1556
1557    // type
1558    int c = (0xff & b.getTypeByte()) - (0xff & a.getTypeByte());
1559    if (c != 0) return false;
1560    else return true;
1561  }
1562
1563  /**************** equals ****************************/
1564
1565  public static boolean equals(Cell a, Cell b) {
1566    return matchingRows(a, b) && matchingFamily(a, b) && matchingQualifier(a, b)
1567        && matchingTimestamp(a, b) && PrivateCellUtil.matchingType(a, b);
1568  }
1569
1570  public static boolean matchingTimestamp(Cell a, Cell b) {
1571    return CellComparator.getInstance().compareTimestamps(a.getTimestamp(), b.getTimestamp()) == 0;
1572  }
1573
1574  /**
1575   * @deprecated As of HBase-2.0. Will be removed in HBase-3.0
1576   */
1577  @Deprecated
1578  public static boolean matchingType(Cell a, Cell b) {
1579    return a.getTypeByte() == b.getTypeByte();
1580  }
1581
1582  /**
1583   * Compares the row of two keyvalues for equality
1584   * @param left
1585   * @param right
1586   * @return True if rows match.
1587   */
1588  public static boolean matchingRows(final Cell left, final Cell right) {
1589    short lrowlength = left.getRowLength();
1590    short rrowlength = right.getRowLength();
1591    return matchingRows(left, lrowlength, right, rrowlength);
1592  }
1593
1594  public static boolean matchingRows(final Cell left, final short lrowlength, final Cell right,
1595      final short rrowlength) {
1596    if (lrowlength != rrowlength) return false;
1597    if (left instanceof ByteBufferExtendedCell && right instanceof ByteBufferExtendedCell) {
1598      return ByteBufferUtils.equals(((ByteBufferExtendedCell) left).getRowByteBuffer(),
1599          ((ByteBufferExtendedCell) left).getRowPosition(), lrowlength,
1600          ((ByteBufferExtendedCell) right).getRowByteBuffer(),
1601          ((ByteBufferExtendedCell) right).getRowPosition(), rrowlength);
1602    }
1603    if (left instanceof ByteBufferExtendedCell) {
1604      return ByteBufferUtils.equals(((ByteBufferExtendedCell) left).getRowByteBuffer(),
1605          ((ByteBufferExtendedCell) left).getRowPosition(), lrowlength, right.getRowArray(),
1606          right.getRowOffset(), rrowlength);
1607    }
1608    if (right instanceof ByteBufferExtendedCell) {
1609      return ByteBufferUtils.equals(((ByteBufferExtendedCell) right).getRowByteBuffer(),
1610          ((ByteBufferExtendedCell) right).getRowPosition(), rrowlength, left.getRowArray(),
1611          left.getRowOffset(), lrowlength);
1612    }
1613    return Bytes.equals(left.getRowArray(), left.getRowOffset(), lrowlength, right.getRowArray(),
1614        right.getRowOffset(), rrowlength);
1615  }
1616
1617  /**
1618   * Compares the row and column of two keyvalues for equality
1619   * @param left
1620   * @param right
1621   * @return True if same row and column.
1622   */
1623  public static boolean matchingRowColumn(final Cell left, final Cell right) {
1624    short lrowlength = left.getRowLength();
1625    short rrowlength = right.getRowLength();
1626    // match length
1627    if (lrowlength != rrowlength) {
1628      return false;
1629    }
1630
1631    byte lfamlength = left.getFamilyLength();
1632    byte rfamlength = right.getFamilyLength();
1633    if (lfamlength != rfamlength) {
1634      return false;
1635    }
1636
1637    int lqlength = left.getQualifierLength();
1638    int rqlength = right.getQualifierLength();
1639    if (lqlength != rqlength) {
1640      return false;
1641    }
1642
1643    if (!matchingRows(left, lrowlength, right, rrowlength)) {
1644      return false;
1645    }
1646    return matchingColumn(left, lfamlength, lqlength, right, rfamlength, rqlength);
1647  }
1648
1649  public static boolean matchingRowColumnBytes(final Cell left, final Cell right) {
1650    int lrowlength = left.getRowLength();
1651    int rrowlength = right.getRowLength();
1652    int lfamlength = left.getFamilyLength();
1653    int rfamlength = right.getFamilyLength();
1654    int lqlength = left.getQualifierLength();
1655    int rqlength = right.getQualifierLength();
1656
1657    // match length
1658    if ((lrowlength != rrowlength) || (lfamlength != rfamlength) || (lqlength != rqlength)) {
1659      return false;
1660    }
1661
1662    // match row
1663    if (!Bytes.equals(left.getRowArray(), left.getRowOffset(), lrowlength, right.getRowArray(),
1664        right.getRowOffset(), rrowlength)) {
1665      return false;
1666    }
1667    //match family
1668    if (!Bytes.equals(left.getFamilyArray(), left.getFamilyOffset(), lfamlength,
1669        right.getFamilyArray(), right.getFamilyOffset(), rfamlength)) {
1670      return false;
1671    }
1672    //match qualifier
1673    return Bytes.equals(left.getQualifierArray(), left.getQualifierOffset(),
1674        lqlength, right.getQualifierArray(), right.getQualifierOffset(),
1675        rqlength);
1676  }
1677
1678  /**
1679   * Compares the cell's qualifier with the given byte[]
1680   * @param left the cell for which the qualifier has to be compared
1681   * @param right the byte[] having the qualifier
1682   * @param rOffset the offset of the qualifier
1683   * @param rLength the length of the qualifier
1684   * @return greater than 0 if left cell's qualifier is bigger than byte[], lesser than 0 if left
1685   *         cell's qualifier is lesser than byte[] and 0 otherwise
1686   */
1687  public final static int compareQualifiers(Cell left, byte[] right, int rOffset, int rLength) {
1688    if (left instanceof ByteBufferExtendedCell) {
1689      return ByteBufferUtils.compareTo(((ByteBufferExtendedCell) left).getQualifierByteBuffer(),
1690          ((ByteBufferExtendedCell) left).getQualifierPosition(),
1691          left.getQualifierLength(), right, rOffset, rLength);
1692    }
1693    return Bytes.compareTo(left.getQualifierArray(), left.getQualifierOffset(),
1694      left.getQualifierLength(), right, rOffset, rLength);
1695  }
1696
1697  /**
1698   * Used when a cell needs to be compared with a key byte[] such as cases of finding the index from
1699   * the index block, bloom keys from the bloom blocks This byte[] is expected to be serialized in
1700   * the KeyValue serialization format If the KeyValue (Cell's) serialization format changes this
1701   * method cannot be used.
1702   * @param comparator the cell comparator
1703   * @param left the cell to be compared
1704   * @param key the serialized key part of a KeyValue
1705   * @param offset the offset in the key byte[]
1706   * @param length the length of the key byte[]
1707   * @return an int greater than 0 if left is greater than right lesser than 0 if left is lesser
1708   *         than right equal to 0 if left is equal to right
1709   * @deprecated As of HBase-2.0. Will be removed in HBase-3.0
1710   */
1711  @VisibleForTesting
1712  @Deprecated
1713  public static final int compare(CellComparator comparator, Cell left, byte[] key, int offset,
1714      int length) {
1715    // row
1716    short rrowlength = Bytes.toShort(key, offset);
1717    int c = comparator.compareRows(left, key, offset + Bytes.SIZEOF_SHORT, rrowlength);
1718    if (c != 0) return c;
1719
1720    // Compare the rest of the two KVs without making any assumptions about
1721    // the common prefix. This function will not compare rows anyway, so we
1722    // don't need to tell it that the common prefix includes the row.
1723    return PrivateCellUtil.compareWithoutRow(comparator, left, key, offset, length, rrowlength);
1724  }
1725
1726  /**
1727   * Compares the cell's family with the given byte[]
1728   * @param left the cell for which the family has to be compared
1729   * @param right the byte[] having the family
1730   * @param roffset the offset of the family
1731   * @param rlength the length of the family
1732   * @return greater than 0 if left cell's family is bigger than byte[], lesser than 0 if left
1733   *         cell's family is lesser than byte[] and 0 otherwise
1734   */
1735  public final static int compareFamilies(Cell left, byte[] right, int roffset, int rlength) {
1736    if (left instanceof ByteBufferExtendedCell) {
1737      return ByteBufferUtils.compareTo(((ByteBufferExtendedCell) left).getFamilyByteBuffer(),
1738        ((ByteBufferExtendedCell) left).getFamilyPosition(), left.getFamilyLength(), right, roffset,
1739        rlength);
1740    }
1741    return Bytes.compareTo(left.getFamilyArray(), left.getFamilyOffset(), left.getFamilyLength(),
1742      right, roffset, rlength);
1743  }
1744
1745  /**
1746   * Compares the cell's column (family and qualifier) with the given byte[]
1747   * @param left the cell for which the column has to be compared
1748   * @param right the byte[] having the column
1749   * @param rfoffset the offset of the family
1750   * @param rflength the length of the family
1751   * @param rqoffset the offset of the qualifier
1752   * @param rqlength the length of the qualifier
1753   * @return greater than 0 if left cell's column is bigger than byte[], lesser than 0 if left
1754   *         cell's column is lesser than byte[] and 0 otherwise
1755   */
1756  public final static int compareColumns(Cell left, byte[] right, int rfoffset, int rflength,
1757      int rqoffset, int rqlength) {
1758    int diff = compareFamilies(left, right, rfoffset, rflength);
1759    if (diff != 0) return diff;
1760    return compareQualifiers(left, right, rqoffset, rqlength);
1761  }
1762}