All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.hadoop.hbase.CellUtil Maven / Gradle / Ivy

There is a newer version: 3.0.0-beta-1
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.hadoop.hbase;

import static org.apache.hadoop.hbase.KeyValue.COLUMN_FAMILY_DELIMITER;
import static org.apache.hadoop.hbase.KeyValue.COLUMN_FAMILY_DELIM_ARRAY;
import static org.apache.hadoop.hbase.KeyValue.getDelimiter;
import static org.apache.hadoop.hbase.Tag.TAG_LENGTH_SIZE;

import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import java.util.NavigableMap;
import java.util.Optional;
import java.util.function.Function;
import org.apache.hadoop.hbase.io.HeapSize;
import org.apache.hadoop.hbase.util.ByteBufferUtils;
import org.apache.hadoop.hbase.util.ByteRange;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.yetus.audience.InterfaceAudience;
import org.apache.yetus.audience.InterfaceAudience.Private;

/**
 * Utility methods helpful for slinging {@link Cell} instances. Some methods below are for internal
 * use only and are marked InterfaceAudience.Private at the method level. Note that all such methods
 * have been marked deprecated in HBase-2.0 which will be subsequently removed in HBase-3.0
 */
@InterfaceAudience.Public
public final class CellUtil {

  /**
   * Private constructor to keep this class from being instantiated.
   */
  private CellUtil() {
  }

  /******************* ByteRange *******************************/

  /**
   * @deprecated As of HBase-2.0. Will be removed in HBase-3.0.
   */
  @Deprecated
  public static ByteRange fillRowRange(Cell cell, ByteRange range) {
    return range.set(cell.getRowArray(), cell.getRowOffset(), cell.getRowLength());
  }

  /**
   * @deprecated As of HBase-2.0. Will be removed in HBase-3.0.
   */
  @Deprecated
  public static ByteRange fillFamilyRange(Cell cell, ByteRange range) {
    return range.set(cell.getFamilyArray(), cell.getFamilyOffset(), cell.getFamilyLength());
  }

  /**
   * @deprecated As of HBase-2.0. Will be removed in HBase-3.0.
   */
  @Deprecated
  public static ByteRange fillQualifierRange(Cell cell, ByteRange range) {
    return range.set(cell.getQualifierArray(), cell.getQualifierOffset(),
      cell.getQualifierLength());
  }

  /**
   * @deprecated As of HBase-2.0. Will be removed in HBase-3.0.
   */
  @Deprecated
  public static ByteRange fillValueRange(Cell cell, ByteRange range) {
    return range.set(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength());
  }

  /**
   * @deprecated As of HBase-2.0. Will be removed in HBase-3.0.
   */
  @Deprecated
  public static ByteRange fillTagRange(Cell cell, ByteRange range) {
    return range.set(cell.getTagsArray(), cell.getTagsOffset(), cell.getTagsLength());
  }

  /***************** get individual arrays for tests ************/

  public static byte[] cloneRow(Cell cell) {
    byte[] output = new byte[cell.getRowLength()];
    copyRowTo(cell, output, 0);
    return output;
  }

  public static byte[] cloneFamily(Cell cell) {
    byte[] output = new byte[cell.getFamilyLength()];
    copyFamilyTo(cell, output, 0);
    return output;
  }

  public static byte[] cloneQualifier(Cell cell) {
    byte[] output = new byte[cell.getQualifierLength()];
    copyQualifierTo(cell, output, 0);
    return output;
  }

  public static byte[] cloneValue(Cell cell) {
    byte[] output = new byte[cell.getValueLength()];
    copyValueTo(cell, output, 0);
    return output;
  }

  /**
   * @deprecated As of HBase-2.0. Will be removed in HBase-3.0. Use {@link RawCell#cloneTags()}
   */
  @Deprecated
  public static byte[] cloneTags(Cell cell) {
    byte[] output = new byte[cell.getTagsLength()];
    PrivateCellUtil.copyTagsTo(cell, output, 0);
    return output;
  }

  /**
   * Returns tag value in a new byte array. If server-side, use {@link Tag#getValueArray()} with
   * appropriate {@link Tag#getValueOffset()} and {@link Tag#getValueLength()} instead to save on
   * allocations.
   * @return tag value in a new byte array.
   * @deprecated As of HBase-2.0. Will be removed in HBase-3.0
   */
  @Deprecated
  public static byte[] getTagArray(Cell cell) {
    byte[] output = new byte[cell.getTagsLength()];
    PrivateCellUtil.copyTagsTo(cell, output, 0);
    return output;
  }

  /**
   * Makes a column in family:qualifier form from separate byte arrays.
   * 

* Not recommended for usage as this is old-style API. * @return family:qualifier */ public static byte[] makeColumn(byte[] family, byte[] qualifier) { return Bytes.add(family, COLUMN_FAMILY_DELIM_ARRAY, qualifier); } /** * Splits a column in {@code family:qualifier} form into separate byte arrays. An empty qualifier * (ie, {@code fam:}) is parsed as { fam, EMPTY_BYTE_ARRAY } while no delimiter (ie, * {@code fam}) is parsed as an array of one element, { fam }. *

* Don't forget, HBase DOES support empty qualifiers. (see HBASE-9549) *

*

* Not recommend to be used as this is old-style API. *

* @param c The column. * @return The parsed column. */ public static byte[][] parseColumn(byte[] c) { final int index = getDelimiter(c, 0, c.length, COLUMN_FAMILY_DELIMITER); if (index == -1) { // If no delimiter, return array of size 1 return new byte[][] { c }; } else if (index == c.length - 1) { // family with empty qualifier, return array size 2 byte[] family = new byte[c.length - 1]; System.arraycopy(c, 0, family, 0, family.length); return new byte[][] { family, HConstants.EMPTY_BYTE_ARRAY }; } // Family and column, return array size 2 final byte[][] result = new byte[2][]; result[0] = new byte[index]; System.arraycopy(c, 0, result[0], 0, index); final int len = c.length - (index + 1); result[1] = new byte[len]; System.arraycopy(c, index + 1 /* Skip delimiter */, result[1], 0, len); return result; } /******************** copyTo **********************************/ /** * Copies the row to the given byte[] * @param cell the cell whose row has to be copied * @param destination the destination byte[] to which the row has to be copied * @param destinationOffset the offset in the destination byte[] * @return the offset of the byte[] after the copy has happened */ public static int copyRowTo(Cell cell, byte[] destination, int destinationOffset) { short rowLen = cell.getRowLength(); if (cell instanceof ByteBufferExtendedCell) { ByteBufferUtils.copyFromBufferToArray(destination, ((ByteBufferExtendedCell) cell).getRowByteBuffer(), ((ByteBufferExtendedCell) cell).getRowPosition(), destinationOffset, rowLen); } else { System.arraycopy(cell.getRowArray(), cell.getRowOffset(), destination, destinationOffset, rowLen); } return destinationOffset + rowLen; } /** * Copies the row to the given bytebuffer * @param cell cell the cell whose row has to be copied * @param destination the destination bytebuffer to which the row has to be copied * @param destinationOffset the offset in the destination byte[] * @return the offset of the bytebuffer after the copy has happened */ public static int copyRowTo(Cell cell, ByteBuffer destination, int destinationOffset) { short rowLen = cell.getRowLength(); if (cell instanceof ByteBufferExtendedCell) { ByteBufferUtils.copyFromBufferToBuffer(((ByteBufferExtendedCell) cell).getRowByteBuffer(), destination, ((ByteBufferExtendedCell) cell).getRowPosition(), destinationOffset, rowLen); } else { ByteBufferUtils.copyFromArrayToBuffer(destination, destinationOffset, cell.getRowArray(), cell.getRowOffset(), rowLen); } return destinationOffset + rowLen; } /** * Copies the row to a new byte[] * @param cell the cell from which row has to copied * @return the byte[] containing the row */ public static byte[] copyRow(Cell cell) { if (cell instanceof ByteBufferExtendedCell) { return ByteBufferUtils.copyOfRange(((ByteBufferExtendedCell) cell).getRowByteBuffer(), ((ByteBufferExtendedCell) cell).getRowPosition(), ((ByteBufferExtendedCell) cell).getRowPosition() + cell.getRowLength()); } else { return Arrays.copyOfRange(cell.getRowArray(), cell.getRowOffset(), cell.getRowOffset() + cell.getRowLength()); } } /** * Copies the family to the given byte[] * @param cell the cell whose family has to be copied * @param destination the destination byte[] to which the family has to be copied * @param destinationOffset the offset in the destination byte[] * @return the offset of the byte[] after the copy has happened */ public static int copyFamilyTo(Cell cell, byte[] destination, int destinationOffset) { byte fLen = cell.getFamilyLength(); if (cell instanceof ByteBufferExtendedCell) { ByteBufferUtils.copyFromBufferToArray(destination, ((ByteBufferExtendedCell) cell).getFamilyByteBuffer(), ((ByteBufferExtendedCell) cell).getFamilyPosition(), destinationOffset, fLen); } else { System.arraycopy(cell.getFamilyArray(), cell.getFamilyOffset(), destination, destinationOffset, fLen); } return destinationOffset + fLen; } /** * Copies the family to the given bytebuffer * @param cell the cell whose family has to be copied * @param destination the destination bytebuffer to which the family has to be copied * @param destinationOffset the offset in the destination bytebuffer * @return the offset of the bytebuffer after the copy has happened */ public static int copyFamilyTo(Cell cell, ByteBuffer destination, int destinationOffset) { byte fLen = cell.getFamilyLength(); if (cell instanceof ByteBufferExtendedCell) { ByteBufferUtils.copyFromBufferToBuffer(((ByteBufferExtendedCell) cell).getFamilyByteBuffer(), destination, ((ByteBufferExtendedCell) cell).getFamilyPosition(), destinationOffset, fLen); } else { ByteBufferUtils.copyFromArrayToBuffer(destination, destinationOffset, cell.getFamilyArray(), cell.getFamilyOffset(), fLen); } return destinationOffset + fLen; } /** * Copies the qualifier to the given byte[] * @param cell the cell whose qualifier has to be copied * @param destination the destination byte[] to which the qualifier has to be copied * @param destinationOffset the offset in the destination byte[] * @return the offset of the byte[] after the copy has happened */ public static int copyQualifierTo(Cell cell, byte[] destination, int destinationOffset) { int qlen = cell.getQualifierLength(); if (cell instanceof ByteBufferExtendedCell) { ByteBufferUtils.copyFromBufferToArray(destination, ((ByteBufferExtendedCell) cell).getQualifierByteBuffer(), ((ByteBufferExtendedCell) cell).getQualifierPosition(), destinationOffset, qlen); } else { System.arraycopy(cell.getQualifierArray(), cell.getQualifierOffset(), destination, destinationOffset, qlen); } return destinationOffset + qlen; } /** * Copies the qualifier to the given bytebuffer * @param cell the cell whose qualifier has to be copied * @param destination the destination bytebuffer to which the qualifier has to be copied * @param destinationOffset the offset in the destination bytebuffer * @return the offset of the bytebuffer after the copy has happened */ public static int copyQualifierTo(Cell cell, ByteBuffer destination, int destinationOffset) { int qlen = cell.getQualifierLength(); if (cell instanceof ByteBufferExtendedCell) { ByteBufferUtils.copyFromBufferToBuffer( ((ByteBufferExtendedCell) cell).getQualifierByteBuffer(), destination, ((ByteBufferExtendedCell) cell).getQualifierPosition(), destinationOffset, qlen); } else { ByteBufferUtils.copyFromArrayToBuffer(destination, destinationOffset, cell.getQualifierArray(), cell.getQualifierOffset(), qlen); } return destinationOffset + qlen; } /** * Copies the value to the given byte[] * @param cell the cell whose value has to be copied * @param destination the destination byte[] to which the value has to be copied * @param destinationOffset the offset in the destination byte[] * @return the offset of the byte[] after the copy has happened */ public static int copyValueTo(Cell cell, byte[] destination, int destinationOffset) { int vlen = cell.getValueLength(); if (cell instanceof ByteBufferExtendedCell) { ByteBufferUtils.copyFromBufferToArray(destination, ((ByteBufferExtendedCell) cell).getValueByteBuffer(), ((ByteBufferExtendedCell) cell).getValuePosition(), destinationOffset, vlen); } else { System.arraycopy(cell.getValueArray(), cell.getValueOffset(), destination, destinationOffset, vlen); } return destinationOffset + vlen; } /** * Copies the value to the given bytebuffer * @param cell the cell whose value has to be copied * @param destination the destination bytebuffer to which the value has to be copied * @param destinationOffset the offset in the destination bytebuffer * @return the offset of the bytebuffer after the copy has happened */ public static int copyValueTo(Cell cell, ByteBuffer destination, int destinationOffset) { int vlen = cell.getValueLength(); if (cell instanceof ByteBufferExtendedCell) { ByteBufferUtils.copyFromBufferToBuffer(((ByteBufferExtendedCell) cell).getValueByteBuffer(), destination, ((ByteBufferExtendedCell) cell).getValuePosition(), destinationOffset, vlen); } else { ByteBufferUtils.copyFromArrayToBuffer(destination, destinationOffset, cell.getValueArray(), cell.getValueOffset(), vlen); } return destinationOffset + vlen; } /** * Copies the tags info into the tag portion of the cell * @return position after tags * @deprecated As of HBase-2.0. Will be removed in HBase-3.0. */ @Deprecated public static int copyTagTo(Cell cell, byte[] destination, int destinationOffset) { int tlen = cell.getTagsLength(); if (cell instanceof ByteBufferExtendedCell) { ByteBufferUtils.copyFromBufferToArray(destination, ((ByteBufferExtendedCell) cell).getTagsByteBuffer(), ((ByteBufferExtendedCell) cell).getTagsPosition(), destinationOffset, tlen); } else { System.arraycopy(cell.getTagsArray(), cell.getTagsOffset(), destination, destinationOffset, tlen); } return destinationOffset + tlen; } /** * Copies the tags info into the tag portion of the cell * @return position after tags * @deprecated As of HBase-2.0. Will be removed in 3.0. */ @Deprecated public static int copyTagTo(Cell cell, ByteBuffer destination, int destinationOffset) { int tlen = cell.getTagsLength(); if (cell instanceof ByteBufferExtendedCell) { ByteBufferUtils.copyFromBufferToBuffer(((ByteBufferExtendedCell) cell).getTagsByteBuffer(), destination, ((ByteBufferExtendedCell) cell).getTagsPosition(), destinationOffset, tlen); } else { ByteBufferUtils.copyFromArrayToBuffer(destination, destinationOffset, cell.getTagsArray(), cell.getTagsOffset(), tlen); } return destinationOffset + tlen; } /********************* misc *************************************/ @Private /** * @deprecated As of HBase-2.0. Will be removed in HBase-3.0. */ @Deprecated public static byte getRowByte(Cell cell, int index) { if (cell instanceof ByteBufferExtendedCell) { return ((ByteBufferExtendedCell) cell).getRowByteBuffer() .get(((ByteBufferExtendedCell) cell).getRowPosition() + index); } return cell.getRowArray()[cell.getRowOffset() + index]; } /** * @deprecated As of HBase-2.0. Will be removed in 3.0. */ @Deprecated public static ByteBuffer getValueBufferShallowCopy(Cell cell) { ByteBuffer buffer = ByteBuffer.wrap(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength()); return buffer; } /** * Return cell's qualifier wrapped into a ByteBuffer. * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0. */ @Deprecated public static ByteBuffer getQualifierBufferShallowCopy(Cell cell) { // No usage of this in code. ByteBuffer buffer = ByteBuffer.wrap(cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength()); return buffer; } /** * Create a cell * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0. Use {@link CellBuilder} * instead */ @Deprecated public static Cell createCell(final byte[] row, final byte[] family, final byte[] qualifier, final long timestamp, final byte type, final byte[] value) { return ExtendedCellBuilderFactory.create(CellBuilderType.DEEP_COPY).setRow(row) .setFamily(family).setQualifier(qualifier).setTimestamp(timestamp).setType(type) .setValue(value).build(); } /** * Creates a cell with deep copy of all passed bytes. * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0. Use {@link CellBuilder} * instead */ @Deprecated public static Cell createCell(final byte[] rowArray, final int rowOffset, final int rowLength, final byte[] familyArray, final int familyOffset, final int familyLength, final byte[] qualifierArray, final int qualifierOffset, final int qualifierLength) { // See createCell(final byte [] row, final byte [] value) for why we default Maximum type. return ExtendedCellBuilderFactory.create(CellBuilderType.DEEP_COPY) .setRow(rowArray, rowOffset, rowLength).setFamily(familyArray, familyOffset, familyLength) .setQualifier(qualifierArray, qualifierOffset, qualifierLength) .setTimestamp(HConstants.LATEST_TIMESTAMP).setType(KeyValue.Type.Maximum.getCode()) .setValue(HConstants.EMPTY_BYTE_ARRAY, 0, HConstants.EMPTY_BYTE_ARRAY.length).build(); } /** * Marked as audience Private as of 1.2.0. Creating a Cell with a memstoreTS/mvcc is an internal * implementation detail not for public use. * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0. Use * {@link ExtendedCellBuilder} instead */ @InterfaceAudience.Private @Deprecated public static Cell createCell(final byte[] row, final byte[] family, final byte[] qualifier, final long timestamp, final byte type, final byte[] value, final long memstoreTS) { return createCell(row, family, qualifier, timestamp, type, value, null, memstoreTS); } /** * Marked as audience Private as of 1.2.0. Creating a Cell with tags and a memstoreTS/mvcc is an * internal implementation detail not for public use. * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0. Use * {@link ExtendedCellBuilder} instead */ @InterfaceAudience.Private @Deprecated public static Cell createCell(final byte[] row, final byte[] family, final byte[] qualifier, final long timestamp, final byte type, final byte[] value, byte[] tags, final long memstoreTS) { return ExtendedCellBuilderFactory.create(CellBuilderType.DEEP_COPY).setRow(row) .setFamily(family).setQualifier(qualifier).setTimestamp(timestamp).setType(type) .setValue(value).setTags(tags).setSequenceId(memstoreTS).build(); } /** * Marked as audience Private as of 1.2.0. Creating a Cell with tags is an internal implementation * detail not for public use. * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0. Use * {@link ExtendedCellBuilder} instead */ @InterfaceAudience.Private @Deprecated public static Cell createCell(final byte[] row, final byte[] family, final byte[] qualifier, final long timestamp, KeyValue.Type type, final byte[] value, byte[] tags) { return createCell(row, family, qualifier, timestamp, type.getCode(), value, tags, 0); } /** * Create a Cell with specific row. Other fields defaulted. * @return Cell with passed row but all other fields are arbitrary * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0. Use {@link CellBuilder} * instead */ @Deprecated public static Cell createCell(final byte[] row) { return createCell(row, HConstants.EMPTY_BYTE_ARRAY); } /** * Create a Cell with specific row and value. Other fields are defaulted. * @return Cell with passed row and value but all other fields are arbitrary * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0. Use {@link CellBuilder} * instead */ @Deprecated public static Cell createCell(final byte[] row, final byte[] value) { // An empty family + empty qualifier + Type.Minimum is used as flag to indicate last on row. // See the CellComparator and KeyValue comparator. Search for compareWithoutRow. // Lets not make a last-on-row key as default but at same time, if you are making a key // without specifying type, etc., flag it as weird by setting type to be Maximum. return createCell(row, HConstants.EMPTY_BYTE_ARRAY, HConstants.EMPTY_BYTE_ARRAY, HConstants.LATEST_TIMESTAMP, KeyValue.Type.Maximum.getCode(), value); } /** * Create a Cell with specific row. Other fields defaulted. * @return Cell with passed row but all other fields are arbitrary * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0. Use {@link CellBuilder} * instead */ @Deprecated public static Cell createCell(final byte[] row, final byte[] family, final byte[] qualifier) { // See above in createCell(final byte [] row, final byte [] value) why we set type to Maximum. return createCell(row, family, qualifier, HConstants.LATEST_TIMESTAMP, KeyValue.Type.Maximum.getCode(), HConstants.EMPTY_BYTE_ARRAY); } /** * Note : Now only CPs can create cell with tags using the CP environment Within CP, use * {@link RawCell#createCell(Cell, List)} method instead * @return A new cell which is having the extra tags also added to it. * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0. */ @Deprecated public static Cell createCell(Cell cell, List tags) { return PrivateCellUtil.createCell(cell, tags); } /** * Now only CPs can create cell with tags using the CP environment Within CP, use * {@link RawCell#createCell(Cell, List)} method instead * @return A new cell which is having the extra tags also added to it. * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0. */ @Deprecated public static Cell createCell(Cell cell, byte[] tags) { return PrivateCellUtil.createCell(cell, tags); } /** * Now only CPs can create cell with tags using the CP environment Within CP, use * {@link RawCell#createCell(Cell, List)} method instead * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0. */ @Deprecated public static Cell createCell(Cell cell, byte[] value, byte[] tags) { return PrivateCellUtil.createCell(cell, value, tags); } /** Returns CellScanner interface over cellIterables */ public static CellScanner createCellScanner(final List cellScannerables) { return new CellScanner() { private final Iterator iterator = cellScannerables.iterator(); private CellScanner cellScanner = null; @Override public Cell current() { return this.cellScanner != null ? this.cellScanner.current() : null; } @Override public boolean advance() throws IOException { while (true) { if (this.cellScanner == null) { if (!this.iterator.hasNext()) return false; this.cellScanner = this.iterator.next().cellScanner(); } if (this.cellScanner.advance()) return true; this.cellScanner = null; } } }; } /** Returns CellScanner interface over cellIterable */ public static CellScanner createCellScanner(final Iterable cellIterable) { if (cellIterable == null) return null; return createCellScanner(cellIterable.iterator()); } /** * Returns CellScanner interface over cellIterable or null if cells is * null */ public static CellScanner createCellScanner(final Iterator cells) { if (cells == null) return null; return new CellScanner() { private final Iterator iterator = cells; private Cell current = null; @Override public Cell current() { return this.current; } @Override public boolean advance() { boolean hasNext = this.iterator.hasNext(); this.current = hasNext ? this.iterator.next() : null; return hasNext; } }; } /** Returns CellScanner interface over cellArray */ public static CellScanner createCellScanner(final Cell[] cellArray) { return new CellScanner() { private final Cell[] cells = cellArray; private int index = -1; @Override public Cell current() { if (cells == null) return null; return (index < 0) ? null : this.cells[index]; } @Override public boolean advance() { if (cells == null) return false; return ++index < this.cells.length; } }; } /** * Flatten the map of cells out under the CellScanner * @param map Map of Cell Lists; for example, the map of families to Cells that is used inside * Put, etc., keeping Cells organized by family. * @return CellScanner interface over cellIterable */ public static CellScanner createCellScanner(final NavigableMap> map) { return new CellScanner() { private final Iterator>> entries = map.entrySet().iterator(); private Iterator currentIterator = null; private Cell currentCell; @Override public Cell current() { return this.currentCell; } @Override public boolean advance() { while (true) { if (this.currentIterator == null) { if (!this.entries.hasNext()) return false; this.currentIterator = this.entries.next().getValue().iterator(); } if (this.currentIterator.hasNext()) { this.currentCell = this.currentIterator.next(); return true; } this.currentCell = null; this.currentIterator = null; } } }; } /** * Return true if the rows in left and right Cells match * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0. Instead use * {@link #matchingRows(Cell, Cell)} */ @Deprecated public static boolean matchingRow(final Cell left, final Cell right) { return matchingRows(left, right); } /** * Return true if the row is matching * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0. Instead use * {@link #matchingRows(Cell, byte[])} */ @Deprecated public static boolean matchingRow(final Cell left, final byte[] buf) { return matchingRows(left, buf); } public static boolean matchingRows(final Cell left, final byte[] buf) { if (buf == null) { return left.getRowLength() == 0; } return PrivateCellUtil.matchingRows(left, buf, 0, buf.length); } /** * Return true if the row is matching * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0. Instead use * {@link #matchingRows(Cell, Cell)} */ @Deprecated public static boolean matchingRow(final Cell left, final byte[] buf, final int offset, final int length) { if (left instanceof ByteBufferExtendedCell) { return ByteBufferUtils.equals(((ByteBufferExtendedCell) left).getRowByteBuffer(), ((ByteBufferExtendedCell) left).getRowPosition(), left.getRowLength(), buf, offset, length); } return Bytes.equals(left.getRowArray(), left.getRowOffset(), left.getRowLength(), buf, offset, length); } public static boolean matchingFamily(final Cell left, final Cell right) { byte lfamlength = left.getFamilyLength(); byte rfamlength = right.getFamilyLength(); return matchingFamily(left, lfamlength, right, rfamlength); } public static boolean matchingFamily(final Cell left, final byte lfamlength, final Cell right, final byte rfamlength) { if (left instanceof ByteBufferExtendedCell && right instanceof ByteBufferExtendedCell) { return ByteBufferUtils.equals(((ByteBufferExtendedCell) left).getFamilyByteBuffer(), ((ByteBufferExtendedCell) left).getFamilyPosition(), lfamlength, ((ByteBufferExtendedCell) right).getFamilyByteBuffer(), ((ByteBufferExtendedCell) right).getFamilyPosition(), rfamlength); } if (left instanceof ByteBufferExtendedCell) { return ByteBufferUtils.equals(((ByteBufferExtendedCell) left).getFamilyByteBuffer(), ((ByteBufferExtendedCell) left).getFamilyPosition(), lfamlength, right.getFamilyArray(), right.getFamilyOffset(), rfamlength); } if (right instanceof ByteBufferExtendedCell) { return ByteBufferUtils.equals(((ByteBufferExtendedCell) right).getFamilyByteBuffer(), ((ByteBufferExtendedCell) right).getFamilyPosition(), rfamlength, left.getFamilyArray(), left.getFamilyOffset(), lfamlength); } return Bytes.equals(left.getFamilyArray(), left.getFamilyOffset(), lfamlength, right.getFamilyArray(), right.getFamilyOffset(), rfamlength); } public static boolean matchingFamily(final Cell left, final byte[] buf) { if (buf == null) { return left.getFamilyLength() == 0; } return PrivateCellUtil.matchingFamily(left, buf, 0, buf.length); } /** * Return true if the family is matching * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0. */ @Deprecated public static boolean matchingFamily(final Cell left, final byte[] buf, final int offset, final int length) { if (left instanceof ByteBufferExtendedCell) { return ByteBufferUtils.equals(((ByteBufferExtendedCell) left).getFamilyByteBuffer(), ((ByteBufferExtendedCell) left).getFamilyPosition(), left.getFamilyLength(), buf, offset, length); } return Bytes.equals(left.getFamilyArray(), left.getFamilyOffset(), left.getFamilyLength(), buf, offset, length); } public static boolean matchingQualifier(final Cell left, final Cell right) { int lqlength = left.getQualifierLength(); int rqlength = right.getQualifierLength(); return matchingQualifier(left, lqlength, right, rqlength); } private static boolean matchingQualifier(final Cell left, final int lqlength, final Cell right, final int rqlength) { if (left instanceof ByteBufferExtendedCell && right instanceof ByteBufferExtendedCell) { return ByteBufferUtils.equals(((ByteBufferExtendedCell) left).getQualifierByteBuffer(), ((ByteBufferExtendedCell) left).getQualifierPosition(), lqlength, ((ByteBufferExtendedCell) right).getQualifierByteBuffer(), ((ByteBufferExtendedCell) right).getQualifierPosition(), rqlength); } if (left instanceof ByteBufferExtendedCell) { return ByteBufferUtils.equals(((ByteBufferExtendedCell) left).getQualifierByteBuffer(), ((ByteBufferExtendedCell) left).getQualifierPosition(), lqlength, right.getQualifierArray(), right.getQualifierOffset(), rqlength); } if (right instanceof ByteBufferExtendedCell) { return ByteBufferUtils.equals(((ByteBufferExtendedCell) right).getQualifierByteBuffer(), ((ByteBufferExtendedCell) right).getQualifierPosition(), rqlength, left.getQualifierArray(), left.getQualifierOffset(), lqlength); } return Bytes.equals(left.getQualifierArray(), left.getQualifierOffset(), lqlength, right.getQualifierArray(), right.getQualifierOffset(), rqlength); } /** * Finds if the qualifier part of the cell and the KV serialized byte[] are equal. * @return true if the qualifier matches, false otherwise */ public static boolean matchingQualifier(final Cell left, final byte[] buf) { if (buf == null) { return left.getQualifierLength() == 0; } return PrivateCellUtil.matchingQualifier(left, buf, 0, buf.length); } /** * Finds if the qualifier part of the cell and the KV serialized byte[] are equal * @param buf the serialized keyvalue format byte[] * @param offset the offset of the qualifier in the byte[] * @param length the length of the qualifier in the byte[] * @return true if the qualifier matches, false otherwise * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0. */ @Deprecated public static boolean matchingQualifier(final Cell left, final byte[] buf, final int offset, final int length) { if (buf == null) { return left.getQualifierLength() == 0; } if (left instanceof ByteBufferExtendedCell) { return ByteBufferUtils.equals(((ByteBufferExtendedCell) left).getQualifierByteBuffer(), ((ByteBufferExtendedCell) left).getQualifierPosition(), left.getQualifierLength(), buf, offset, length); } return Bytes.equals(left.getQualifierArray(), left.getQualifierOffset(), left.getQualifierLength(), buf, offset, length); } public static boolean matchingColumn(final Cell left, final byte[] fam, final byte[] qual) { return matchingFamily(left, fam) && matchingQualifier(left, qual); } /** Returns True if matching column family and the qualifier starts with qual */ public static boolean matchingColumnFamilyAndQualifierPrefix(final Cell left, final byte[] fam, final byte[] qual) { return matchingFamily(left, fam) && PrivateCellUtil.qualifierStartsWith(left, qual); } /** * Return true if the column is matching * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0. */ @Deprecated public static boolean matchingColumn(final Cell left, final byte[] fam, final int foffset, final int flength, final byte[] qual, final int qoffset, final int qlength) { if (!PrivateCellUtil.matchingFamily(left, fam, foffset, flength)) return false; return PrivateCellUtil.matchingQualifier(left, qual, qoffset, qlength); } public static boolean matchingColumn(final Cell left, final Cell right) { if (!matchingFamily(left, right)) return false; return matchingQualifier(left, right); } private static boolean matchingColumn(final Cell left, final byte lFamLen, final int lQualLength, final Cell right, final byte rFamLen, final int rQualLength) { if (!matchingFamily(left, lFamLen, right, rFamLen)) { return false; } return matchingQualifier(left, lQualLength, right, rQualLength); } public static boolean matchingValue(final Cell left, final Cell right) { return PrivateCellUtil.matchingValue(left, right, left.getValueLength(), right.getValueLength()); } public static boolean matchingValue(final Cell left, final byte[] buf) { if (left instanceof ByteBufferExtendedCell) { return ByteBufferUtils.compareTo(((ByteBufferExtendedCell) left).getValueByteBuffer(), ((ByteBufferExtendedCell) left).getValuePosition(), left.getValueLength(), buf, 0, buf.length) == 0; } return Bytes.equals(left.getValueArray(), left.getValueOffset(), left.getValueLength(), buf, 0, buf.length); } public static boolean matchingTags(final Cell left, final Cell right) { return PrivateCellUtil.matchingTags(left, right, left.getTagsLength(), right.getTagsLength()); } /** * Return true if a delete type, a {@link KeyValue.Type#Delete} or a {KeyValue.Type#DeleteFamily} * or a {@link KeyValue.Type#DeleteColumn} KeyValue type. */ @SuppressWarnings("deprecation") public static boolean isDelete(final Cell cell) { return PrivateCellUtil.isDelete(cell.getTypeByte()); } /** * Return true if a delete type, a {@link KeyValue.Type#Delete} or a {KeyValue.Type#DeleteFamily} * or a {@link KeyValue.Type#DeleteColumn} KeyValue type. * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0. */ @Deprecated public static boolean isDelete(final byte type) { return KeyValue.Type.Delete.getCode() <= type && type <= KeyValue.Type.DeleteFamily.getCode(); } /** * Return true if this cell is a {@link KeyValue.Type#Delete} type. * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0. */ @Deprecated public static boolean isDeleteType(Cell cell) { return cell.getTypeByte() == KeyValue.Type.Delete.getCode(); } /** * Check whether the given cell is a delete family * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0. */ @Deprecated public static boolean isDeleteFamily(final Cell cell) { return cell.getTypeByte() == KeyValue.Type.DeleteFamily.getCode(); } /** * Check whether the given cell is a delete family version * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0. */ @Deprecated public static boolean isDeleteFamilyVersion(final Cell cell) { return cell.getTypeByte() == KeyValue.Type.DeleteFamilyVersion.getCode(); } /** * Check whether the given cell is a delete columns * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0. */ @Deprecated public static boolean isDeleteColumns(final Cell cell) { return cell.getTypeByte() == KeyValue.Type.DeleteColumn.getCode(); } /** * Check whether the given cell is a delete column version * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0. */ @Deprecated public static boolean isDeleteColumnVersion(final Cell cell) { return cell.getTypeByte() == KeyValue.Type.Delete.getCode(); } /** * Return true if this cell is a delete family or column type. * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0. */ @Deprecated public static boolean isDeleteColumnOrFamily(Cell cell) { int t = cell.getTypeByte(); return t == KeyValue.Type.DeleteColumn.getCode() || t == KeyValue.Type.DeleteFamily.getCode(); } /** Returns True if this cell is a Put. */ @SuppressWarnings("deprecation") public static boolean isPut(Cell cell) { return cell.getTypeByte() == KeyValue.Type.Put.getCode(); } /** * Estimate based on keyvalue's serialization format in the RPC layer. Note that there is an extra * SIZEOF_INT added to the size here that indicates the actual length of the cell for cases where * cell's are serialized in a contiguous format (For eg in RPCs). * @return Estimate of the cell size in bytes plus an extra SIZEOF_INT indicating the * actual cell length. * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0. */ @Deprecated public static int estimatedSerializedSizeOf(final Cell cell) { if (cell instanceof ExtendedCell) { return ((ExtendedCell) cell).getSerializedSize(true) + Bytes.SIZEOF_INT; } return getSumOfCellElementLengths(cell) + // Use the KeyValue's infrastructure size presuming that another implementation would have // same basic cost. KeyValue.ROW_LENGTH_SIZE + KeyValue.FAMILY_LENGTH_SIZE + // Serialization is probably preceded by a length (it is in the KeyValueCodec at least). Bytes.SIZEOF_INT; } /** * Return sum of the lengths of all the elements in a Cell; does not count in any infrastructure */ private static int getSumOfCellElementLengths(final Cell cell) { return getSumOfCellKeyElementLengths(cell) + cell.getValueLength() + cell.getTagsLength(); } /** * Return sum of all elements that make up a key; does not include infrastructure, tags or values. */ private static int getSumOfCellKeyElementLengths(final Cell cell) { return cell.getRowLength() + cell.getFamilyLength() + cell.getQualifierLength() + KeyValue.TIMESTAMP_TYPE_SIZE; } /** * Calculates the serialized key size. We always serialize in the KeyValue's serialization format. * @param cell the cell for which the key size has to be calculated. * @return the key size * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0. */ @Deprecated public static int estimatedSerializedSizeOfKey(final Cell cell) { if (cell instanceof KeyValue) return ((KeyValue) cell).getKeyLength(); return cell.getRowLength() + cell.getFamilyLength() + cell.getQualifierLength() + KeyValue.KEY_INFRASTRUCTURE_SIZE; } /** * This is an estimate of the heap space occupied by a cell. When the cell is of type * {@link HeapSize} we call {@link HeapSize#heapSize()} so cell can give a correct value. In other * cases we just consider the bytes occupied by the cell components ie. row, CF, qualifier, * timestamp, type, value and tags. * @return estimate of the heap space * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0. Use * {@link RawCell#getTags()} */ @Deprecated public static long estimatedHeapSizeOf(final Cell cell) { return cell.heapSize(); } /********************* tags *************************************/ /** * Util method to iterate through the tags * @return iterator for the tags * @deprecated As of 2.0.0 and will be removed in 3.0.0 Instead use * {@link PrivateCellUtil#tagsIterator(Cell)} */ @Deprecated public static Iterator tagsIterator(final byte[] tags, final int offset, final int length) { return new Iterator() { private int pos = offset; private int endOffset = offset + length - 1; @Override public boolean hasNext() { return this.pos < endOffset; } @Override public Tag next() { if (hasNext()) { int curTagLen = Bytes.readAsInt(tags, this.pos, Tag.TAG_LENGTH_SIZE); Tag tag = new ArrayBackedTag(tags, pos, curTagLen + TAG_LENGTH_SIZE); this.pos += Bytes.SIZEOF_SHORT + curTagLen; return tag; } return null; } @Override public void remove() { throw new UnsupportedOperationException(); } }; } /** * Return tags in the given Cell as a List * @deprecated As of 2.0.0 and will be removed in 3.0.0 */ @Deprecated public static List getTags(Cell cell) { List tags = new ArrayList<>(); Iterator tagsItr = PrivateCellUtil.tagsIterator(cell); while (tagsItr.hasNext()) { tags.add(tagsItr.next()); } return tags; } /** * Retrieve Cell's first tag, matching the passed in type * @param cell The Cell * @param type Type of the Tag to retrieve * @return null if there is no tag of the passed in tag type * @deprecated As of 2.0.0 and will be removed in HBase-3.0.0 Use {@link RawCell#getTag(byte)} */ @Deprecated public static Tag getTag(Cell cell, byte type) { Optional tag = PrivateCellUtil.getTag(cell, type); if (tag.isPresent()) { return tag.get(); } else { return null; } } /** * Returns true if the first range start1...end1 overlaps with the second range start2...end2, * assuming the byte arrays represent row keys * @deprecated As of 2.0.0 and will be removed in 3.0.0 */ @Deprecated public static boolean overlappingKeys(final byte[] start1, final byte[] end1, final byte[] start2, final byte[] end2) { return (end2.length == 0 || start1.length == 0 || Bytes.compareTo(start1, end2) < 0) && (end1.length == 0 || start2.length == 0 || Bytes.compareTo(start2, end1) < 0); } /** * Sets the given seqId to the cell. Marked as audience Private as of 1.2.0. Setting a Cell * sequenceid is an internal implementation detail not for general public use. * @throws IOException when the passed cell is not of type {@link ExtendedCell} * @deprecated As of HBase-2.0. Will be removed in HBase-3.0 */ @Deprecated public static void setSequenceId(Cell cell, long seqId) throws IOException { PrivateCellUtil.setSequenceId(cell, seqId); } /** * Sets the given timestamp to the cell. Note that this method is a LimitedPrivate API and may * change between minor releases. * @throws IOException when the passed cell is not of type {@link ExtendedCell} * @deprecated As of HBase-2.0. Will be a LimitedPrivate API in HBase-3.0. */ @Deprecated public static void setTimestamp(Cell cell, long ts) throws IOException { PrivateCellUtil.setTimestamp(cell, ts); } /** * Sets the given timestamp to the cell. Note that this method is a LimitedPrivate API and may * change between minor releases. * @throws IOException when the passed cell is not of type {@link ExtendedCell} * @deprecated As of HBase-2.0. Will be a LimitedPrivate API in HBase-3.0. */ @Deprecated public static void setTimestamp(Cell cell, byte[] ts, int tsOffset) throws IOException { PrivateCellUtil.setTimestamp(cell, Bytes.toLong(ts, tsOffset)); } /** * Sets the given timestamp to the cell iff current timestamp is * {@link HConstants#LATEST_TIMESTAMP}. * @return True if cell timestamp is modified. * @throws IOException when the passed cell is not of type {@link ExtendedCell} * @deprecated As of HBase-2.0. Will be removed in HBase-3.0 */ @Deprecated public static boolean updateLatestStamp(Cell cell, long ts) throws IOException { return PrivateCellUtil.updateLatestStamp(cell, ts); } /** * Sets the given timestamp to the cell iff current timestamp is * {@link HConstants#LATEST_TIMESTAMP}. * @param ts buffer containing the timestamp value * @param tsOffset offset to the new timestamp * @return True if cell timestamp is modified. * @throws IOException when the passed cell is not of type {@link ExtendedCell} * @deprecated As of HBase-2.0. Will be removed in HBase-3.0 */ @Deprecated public static boolean updateLatestStamp(Cell cell, byte[] ts, int tsOffset) throws IOException { return PrivateCellUtil.updateLatestStamp(cell, Bytes.toLong(ts, tsOffset)); } /** * Writes the Cell's key part as it would have serialized in a KeyValue. The format is <2 bytes * rk len><rk><1 byte cf len><cf><qualifier><8 bytes * timestamp><1 byte type> * @deprecated As of HBase-2.0. Will be removed in HBase-3.0 */ @Deprecated public static void writeFlatKey(Cell cell, DataOutputStream out) throws IOException { short rowLen = cell.getRowLength(); byte fLen = cell.getFamilyLength(); int qLen = cell.getQualifierLength(); // Using just one if/else loop instead of every time checking before writing every // component of cell if (cell instanceof ByteBufferExtendedCell) { out.writeShort(rowLen); ByteBufferUtils.copyBufferToStream((DataOutput) out, ((ByteBufferExtendedCell) cell).getRowByteBuffer(), ((ByteBufferExtendedCell) cell).getRowPosition(), rowLen); out.writeByte(fLen); ByteBufferUtils.copyBufferToStream((DataOutput) out, ((ByteBufferExtendedCell) cell).getFamilyByteBuffer(), ((ByteBufferExtendedCell) cell).getFamilyPosition(), fLen); ByteBufferUtils.copyBufferToStream((DataOutput) out, ((ByteBufferExtendedCell) cell).getQualifierByteBuffer(), ((ByteBufferExtendedCell) cell).getQualifierPosition(), qLen); } else { out.writeShort(rowLen); out.write(cell.getRowArray(), cell.getRowOffset(), rowLen); out.writeByte(fLen); out.write(cell.getFamilyArray(), cell.getFamilyOffset(), fLen); out.write(cell.getQualifierArray(), cell.getQualifierOffset(), qLen); } out.writeLong(cell.getTimestamp()); out.writeByte(cell.getTypeByte()); } /** * Writes the row from the given cell to the output stream excluding the common prefix * @param out The dataoutputstream to which the data has to be written * @param cell The cell whose contents has to be written * @param rlength the row length * @deprecated As of 2.0. Will be removed in hbase-3.0 */ @Deprecated public static void writeRowSkippingBytes(DataOutputStream out, Cell cell, short rlength, int commonPrefix) throws IOException { if (cell instanceof ByteBufferExtendedCell) { ByteBufferUtils.copyBufferToStream((DataOutput) out, ((ByteBufferExtendedCell) cell).getRowByteBuffer(), ((ByteBufferExtendedCell) cell).getRowPosition() + commonPrefix, rlength - commonPrefix); } else { out.write(cell.getRowArray(), cell.getRowOffset() + commonPrefix, rlength - commonPrefix); } } /** * Return the key portion of the passed cell as a String. */ public static String getCellKeyAsString(Cell cell) { return getCellKeyAsString(cell, c -> Bytes.toStringBinary(c.getRowArray(), c.getRowOffset(), c.getRowLength())); } /** * Return the Key portion of the passed cell as a String. * @param cell the cell to convert * @param rowConverter used to convert the row of the cell to a string * @return The Key portion of the passed cell as a String. */ public static String getCellKeyAsString(Cell cell, Function rowConverter) { StringBuilder sb = new StringBuilder(rowConverter.apply(cell)); sb.append('/'); sb.append(cell.getFamilyLength() == 0 ? "" : Bytes.toStringBinary(cell.getFamilyArray(), cell.getFamilyOffset(), cell.getFamilyLength())); // KeyValue only added ':' if family is non-null. Do same. if (cell.getFamilyLength() > 0) sb.append(':'); sb.append(cell.getQualifierLength() == 0 ? "" : Bytes.toStringBinary(cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength())); sb.append('/'); sb.append(KeyValue.humanReadableTimestamp(cell.getTimestamp())); sb.append('/'); sb.append(KeyValue.Type.codeToType(cell.getTypeByte())); if (!(cell instanceof KeyValue.KeyOnlyKeyValue)) { sb.append("/vlen="); sb.append(cell.getValueLength()); } sb.append("/seqid="); sb.append(cell.getSequenceId()); return sb.toString(); } /** * This method exists just to encapsulate how we serialize keys. To be replaced by a factory that * we query to figure what the Cell implementation is and then, what serialization engine to use * and further, how to serialize the key for inclusion in hfile index. TODO. * @return The key portion of the Cell serialized in the old-school KeyValue way or null if passed * a null cell * @deprecated As of HBase-2.0. Will be removed in HBase-3.0 */ @Deprecated public static byte[] getCellKeySerializedAsKeyValueKey(final Cell cell) { if (cell == null) return null; byte[] b = new byte[KeyValueUtil.keyLength(cell)]; KeyValueUtil.appendKeyTo(cell, b, 0); return b; } /** * Write rowkey excluding the common part. * @deprecated As of HBase-2.0. Will be removed in HBase-3.0 */ @Deprecated public static void writeRowKeyExcludingCommon(Cell cell, short rLen, int commonPrefix, DataOutputStream out) throws IOException { if (commonPrefix == 0) { out.writeShort(rLen); } else if (commonPrefix == 1) { out.writeByte((byte) rLen); commonPrefix--; } else { commonPrefix -= KeyValue.ROW_LENGTH_SIZE; } if (rLen > commonPrefix) { PrivateCellUtil.writeRowSkippingBytes(out, cell, rLen, commonPrefix); } } /** * Find length of common prefix in keys of the cells, considering key as byte[] if serialized in * {@link KeyValue}. The key format is <2 bytes rk len><rk><1 byte cf * len><cf><qualifier><8 bytes timestamp><1 byte type> * @param c1 the cell * @param c2 the cell * @param bypassFamilyCheck when true assume the family bytes same in both cells. Pass it as true * when dealing with Cells in same CF so as to avoid some checks * @param withTsType when true check timestamp and type bytes also. * @return length of common prefix * @deprecated As of HBase-2.0. Will be removed in HBase-3.0 */ @Deprecated public static int findCommonPrefixInFlatKey(Cell c1, Cell c2, boolean bypassFamilyCheck, boolean withTsType) { // Compare the 2 bytes in RK length part short rLen1 = c1.getRowLength(); short rLen2 = c2.getRowLength(); int commonPrefix = KeyValue.ROW_LENGTH_SIZE; if (rLen1 != rLen2) { // early out when the RK length itself is not matching return ByteBufferUtils.findCommonPrefix(Bytes.toBytes(rLen1), 0, KeyValue.ROW_LENGTH_SIZE, Bytes.toBytes(rLen2), 0, KeyValue.ROW_LENGTH_SIZE); } // Compare the RKs int rkCommonPrefix = 0; if (c1 instanceof ByteBufferExtendedCell && c2 instanceof ByteBufferExtendedCell) { rkCommonPrefix = ByteBufferUtils.findCommonPrefix(((ByteBufferExtendedCell) c1).getRowByteBuffer(), ((ByteBufferExtendedCell) c1).getRowPosition(), rLen1, ((ByteBufferExtendedCell) c2).getRowByteBuffer(), ((ByteBufferExtendedCell) c2).getRowPosition(), rLen2); } else { // There cannot be a case where one cell is BBCell and other is KeyValue. This flow comes // either // in flush or compactions. In flushes both cells are KV and in case of compaction it will be // either // KV or BBCell rkCommonPrefix = ByteBufferUtils.findCommonPrefix(c1.getRowArray(), c1.getRowOffset(), rLen1, c2.getRowArray(), c2.getRowOffset(), rLen2); } commonPrefix += rkCommonPrefix; if (rkCommonPrefix != rLen1) { // Early out when RK is not fully matching. return commonPrefix; } // Compare 1 byte CF length part byte fLen1 = c1.getFamilyLength(); if (bypassFamilyCheck) { // This flag will be true when caller is sure that the family will be same for both the cells // Just make commonPrefix to increment by the family part commonPrefix += KeyValue.FAMILY_LENGTH_SIZE + fLen1; } else { byte fLen2 = c2.getFamilyLength(); if (fLen1 != fLen2) { // early out when the CF length itself is not matching return commonPrefix; } // CF lengths are same so there is one more byte common in key part commonPrefix += KeyValue.FAMILY_LENGTH_SIZE; // Compare the CF names int fCommonPrefix; if (c1 instanceof ByteBufferExtendedCell && c2 instanceof ByteBufferExtendedCell) { fCommonPrefix = ByteBufferUtils.findCommonPrefix(((ByteBufferExtendedCell) c1).getFamilyByteBuffer(), ((ByteBufferExtendedCell) c1).getFamilyPosition(), fLen1, ((ByteBufferExtendedCell) c2).getFamilyByteBuffer(), ((ByteBufferExtendedCell) c2).getFamilyPosition(), fLen2); } else { fCommonPrefix = ByteBufferUtils.findCommonPrefix(c1.getFamilyArray(), c1.getFamilyOffset(), fLen1, c2.getFamilyArray(), c2.getFamilyOffset(), fLen2); } commonPrefix += fCommonPrefix; if (fCommonPrefix != fLen1) { return commonPrefix; } } // Compare the Qualifiers int qLen1 = c1.getQualifierLength(); int qLen2 = c2.getQualifierLength(); int qCommon; if (c1 instanceof ByteBufferExtendedCell && c2 instanceof ByteBufferExtendedCell) { qCommon = ByteBufferUtils.findCommonPrefix(((ByteBufferExtendedCell) c1).getQualifierByteBuffer(), ((ByteBufferExtendedCell) c1).getQualifierPosition(), qLen1, ((ByteBufferExtendedCell) c2).getQualifierByteBuffer(), ((ByteBufferExtendedCell) c2).getQualifierPosition(), qLen2); } else { qCommon = ByteBufferUtils.findCommonPrefix(c1.getQualifierArray(), c1.getQualifierOffset(), qLen1, c2.getQualifierArray(), c2.getQualifierOffset(), qLen2); } commonPrefix += qCommon; if (!withTsType || Math.max(qLen1, qLen2) != qCommon) { return commonPrefix; } // Compare the timestamp parts int tsCommonPrefix = ByteBufferUtils.findCommonPrefix(Bytes.toBytes(c1.getTimestamp()), 0, KeyValue.TIMESTAMP_SIZE, Bytes.toBytes(c2.getTimestamp()), 0, KeyValue.TIMESTAMP_SIZE); commonPrefix += tsCommonPrefix; if (tsCommonPrefix != KeyValue.TIMESTAMP_SIZE) { return commonPrefix; } // Compare the type if (c1.getTypeByte() == c2.getTypeByte()) { commonPrefix += KeyValue.TYPE_SIZE; } return commonPrefix; } /** Returns a string representation of the cell */ public static String toString(Cell cell, boolean verbose) { if (cell == null) { return ""; } StringBuilder builder = new StringBuilder(); String keyStr = getCellKeyAsString(cell); String tag = null; String value = null; if (verbose) { // TODO: pretty print tags as well if (cell.getTagsLength() > 0) { tag = Bytes.toStringBinary(cell.getTagsArray(), cell.getTagsOffset(), cell.getTagsLength()); } if (!(cell instanceof KeyValue.KeyOnlyKeyValue)) { value = Bytes.toStringBinary(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength()); } } builder.append(keyStr); if (tag != null && !tag.isEmpty()) { builder.append("/").append(tag); } if (value != null) { builder.append("/").append(value); } return builder.toString(); } /***************** special cases ****************************/ /** * special case for Cell.equals * @deprecated As of HBase-2.0. Will be removed in HBase-3.0 */ @Deprecated public static boolean equalsIgnoreMvccVersion(Cell a, Cell b) { // row boolean res = matchingRows(a, b); if (!res) return res; // family res = matchingColumn(a, b); if (!res) return res; // timestamp: later sorts first if (!matchingTimestamp(a, b)) return false; // type int c = (0xff & b.getTypeByte()) - (0xff & a.getTypeByte()); if (c != 0) return false; else return true; } /**************** equals ****************************/ public static boolean equals(Cell a, Cell b) { return matchingRows(a, b) && matchingFamily(a, b) && matchingQualifier(a, b) && matchingTimestamp(a, b) && PrivateCellUtil.matchingType(a, b); } public static boolean matchingTimestamp(Cell a, Cell b) { return CellComparator.getInstance().compareTimestamps(a.getTimestamp(), b.getTimestamp()) == 0; } /** * Check whether the type of these two cells are the same * @deprecated As of HBase-2.0. Will be removed in HBase-3.0 */ @Deprecated public static boolean matchingType(Cell a, Cell b) { return a.getTypeByte() == b.getTypeByte(); } /** Compares the row of two keyvalues for equality */ public static boolean matchingRows(final Cell left, final Cell right) { short lrowlength = left.getRowLength(); short rrowlength = right.getRowLength(); return matchingRows(left, lrowlength, right, rrowlength); } /** Compares the row of two keyvalues for equality */ public static boolean matchingRows(final Cell left, final short lrowlength, final Cell right, final short rrowlength) { if (lrowlength != rrowlength) return false; if (left instanceof ByteBufferExtendedCell && right instanceof ByteBufferExtendedCell) { return ByteBufferUtils.equals(((ByteBufferExtendedCell) left).getRowByteBuffer(), ((ByteBufferExtendedCell) left).getRowPosition(), lrowlength, ((ByteBufferExtendedCell) right).getRowByteBuffer(), ((ByteBufferExtendedCell) right).getRowPosition(), rrowlength); } if (left instanceof ByteBufferExtendedCell) { return ByteBufferUtils.equals(((ByteBufferExtendedCell) left).getRowByteBuffer(), ((ByteBufferExtendedCell) left).getRowPosition(), lrowlength, right.getRowArray(), right.getRowOffset(), rrowlength); } if (right instanceof ByteBufferExtendedCell) { return ByteBufferUtils.equals(((ByteBufferExtendedCell) right).getRowByteBuffer(), ((ByteBufferExtendedCell) right).getRowPosition(), rrowlength, left.getRowArray(), left.getRowOffset(), lrowlength); } return Bytes.equals(left.getRowArray(), left.getRowOffset(), lrowlength, right.getRowArray(), right.getRowOffset(), rrowlength); } /** Compares the row and column of two keyvalues for equality */ public static boolean matchingRowColumn(final Cell left, final Cell right) { short lrowlength = left.getRowLength(); short rrowlength = right.getRowLength(); // match length if (lrowlength != rrowlength) { return false; } byte lfamlength = left.getFamilyLength(); byte rfamlength = right.getFamilyLength(); if (lfamlength != rfamlength) { return false; } int lqlength = left.getQualifierLength(); int rqlength = right.getQualifierLength(); if (lqlength != rqlength) { return false; } if (!matchingRows(left, lrowlength, right, rrowlength)) { return false; } return matchingColumn(left, lfamlength, lqlength, right, rfamlength, rqlength); } /** Compares the row and column of two keyvalues for equality */ public static boolean matchingRowColumnBytes(final Cell left, final Cell right) { int lrowlength = left.getRowLength(); int rrowlength = right.getRowLength(); int lfamlength = left.getFamilyLength(); int rfamlength = right.getFamilyLength(); int lqlength = left.getQualifierLength(); int rqlength = right.getQualifierLength(); // match length if ((lrowlength != rrowlength) || (lfamlength != rfamlength) || (lqlength != rqlength)) { return false; } // match row if ( !Bytes.equals(left.getRowArray(), left.getRowOffset(), lrowlength, right.getRowArray(), right.getRowOffset(), rrowlength) ) { return false; } // match family if ( !Bytes.equals(left.getFamilyArray(), left.getFamilyOffset(), lfamlength, right.getFamilyArray(), right.getFamilyOffset(), rfamlength) ) { return false; } // match qualifier return Bytes.equals(left.getQualifierArray(), left.getQualifierOffset(), lqlength, right.getQualifierArray(), right.getQualifierOffset(), rqlength); } /** * Compares the cell's qualifier with the given byte[] * @param left the cell for which the qualifier has to be compared * @param right the byte[] having the qualifier * @param rOffset the offset of the qualifier * @param rLength the length of the qualifier * @return greater than 0 if left cell's qualifier is bigger than byte[], lesser than 0 if left * cell's qualifier is lesser than byte[] and 0 otherwise */ public final static int compareQualifiers(Cell left, byte[] right, int rOffset, int rLength) { if (left instanceof ByteBufferExtendedCell) { return ByteBufferUtils.compareTo(((ByteBufferExtendedCell) left).getQualifierByteBuffer(), ((ByteBufferExtendedCell) left).getQualifierPosition(), left.getQualifierLength(), right, rOffset, rLength); } return Bytes.compareTo(left.getQualifierArray(), left.getQualifierOffset(), left.getQualifierLength(), right, rOffset, rLength); } /** * Used when a cell needs to be compared with a key byte[] such as cases of finding the index from * the index block, bloom keys from the bloom blocks This byte[] is expected to be serialized in * the KeyValue serialization format If the KeyValue (Cell's) serialization format changes this * method cannot be used. * @param comparator the cell comparator * @param left the cell to be compared * @param key the serialized key part of a KeyValue * @param offset the offset in the key byte[] * @param length the length of the key byte[] * @return an int greater than 0 if left is greater than right lesser than 0 if left is lesser * than right equal to 0 if left is equal to right * @deprecated As of HBase-2.0. Will be removed in HBase-3.0 */ @InterfaceAudience.Private @Deprecated public static final int compare(CellComparator comparator, Cell left, byte[] key, int offset, int length) { // row short rrowlength = Bytes.toShort(key, offset); int c = comparator.compareRows(left, key, offset + Bytes.SIZEOF_SHORT, rrowlength); if (c != 0) return c; // Compare the rest of the two KVs without making any assumptions about // the common prefix. This function will not compare rows anyway, so we // don't need to tell it that the common prefix includes the row. return PrivateCellUtil.compareWithoutRow(comparator, left, key, offset, length, rrowlength); } /** * Compares the cell's family with the given byte[] * @param left the cell for which the family has to be compared * @param right the byte[] having the family * @param roffset the offset of the family * @param rlength the length of the family * @return greater than 0 if left cell's family is bigger than byte[], lesser than 0 if left * cell's family is lesser than byte[] and 0 otherwise */ public final static int compareFamilies(Cell left, byte[] right, int roffset, int rlength) { if (left instanceof ByteBufferExtendedCell) { return ByteBufferUtils.compareTo(((ByteBufferExtendedCell) left).getFamilyByteBuffer(), ((ByteBufferExtendedCell) left).getFamilyPosition(), left.getFamilyLength(), right, roffset, rlength); } return Bytes.compareTo(left.getFamilyArray(), left.getFamilyOffset(), left.getFamilyLength(), right, roffset, rlength); } /** * Compares the cell's column (family and qualifier) with the given byte[] * @param left the cell for which the column has to be compared * @param right the byte[] having the column * @param rfoffset the offset of the family * @param rflength the length of the family * @param rqoffset the offset of the qualifier * @param rqlength the length of the qualifier * @return greater than 0 if left cell's column is bigger than byte[], lesser than 0 if left * cell's column is lesser than byte[] and 0 otherwise */ public final static int compareColumns(Cell left, byte[] right, int rfoffset, int rflength, int rqoffset, int rqlength) { int diff = compareFamilies(left, right, rfoffset, rflength); if (diff != 0) return diff; return compareQualifiers(left, right, rqoffset, rqlength); } public static void cloneIfNecessary(ArrayList cells) { if (cells == null || cells.isEmpty()) { return; } for (int i = 0; i < cells.size(); i++) { Cell cell = cells.get(i); cells.set(i, cloneIfNecessary(cell)); } } public static Cell cloneIfNecessary(Cell cell) { return (cell instanceof ByteBufferExtendedCell ? KeyValueUtil.copyToNewKeyValue(cell) : cell); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy