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