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 */
018package org.apache.hadoop.hbase;
019
020import java.nio.ByteBuffer;
021import org.apache.hadoop.hbase.util.ByteBufferUtils;
022import org.apache.hadoop.hbase.util.Bytes;
023import org.apache.yetus.audience.InterfaceAudience;
024import org.apache.yetus.audience.InterfaceStability;
025
026/**
027 * Tags are part of cells and helps to add metadata about them. Metadata could be ACLs, visibility
028 * labels, etc.
029 * <p>
030 * Each Tag is having a type (one byte) and value part. The max value length for a Tag is 65533.
031 * <p>
032 * See {@link TagType} for reserved tag types.
033 */
034@InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.COPROC)
035@InterfaceStability.Evolving
036public interface Tag {
037
038  public final static int TYPE_LENGTH_SIZE = Bytes.SIZEOF_BYTE;
039  public final static int TAG_LENGTH_SIZE = Bytes.SIZEOF_SHORT;
040  public final static int INFRASTRUCTURE_SIZE = TYPE_LENGTH_SIZE + TAG_LENGTH_SIZE;
041  public static final int MAX_TAG_LENGTH = (2 * Short.MAX_VALUE) + 1 - TAG_LENGTH_SIZE;
042
043  /**
044   * Custom tags if created are suggested to be above this range. So that it does not overlap with
045   * internal tag types
046   */
047  public static final byte CUSTOM_TAG_TYPE_RANGE = (byte) 64;
048
049  /** Returns the tag type */
050  byte getType();
051
052  /** Returns Offset of tag value within the backed buffer */
053  int getValueOffset();
054
055  /** Returns Length of tag value within the backed buffer */
056  int getValueLength();
057
058  /** Return true if the tag is backed by a byte array */
059  boolean hasArray();
060
061  /**
062   * Return an array containing the value bytes if {@link #hasArray()} returns true.
063   * <p>
064   * Use {@link #getValueByteBuffer()} otherwise.
065   */
066  byte[] getValueArray();
067
068  /** Returns The {@link java.nio.ByteBuffer} containing the value bytes. */
069  ByteBuffer getValueByteBuffer();
070
071  /**
072   * Returns tag value in a new byte array. Primarily for use client-side. If server-side, use
073   * {@link Tag#getValueArray()} with appropriate {@link Tag#getValueOffset()} and
074   * {@link Tag#getValueLength()} instead to save on allocations.
075   * @param tag The Tag whose value to be returned
076   * @return tag value in a new byte array.
077   */
078  public static byte[] cloneValue(Tag tag) {
079    int tagLength = tag.getValueLength();
080    byte[] tagArr = new byte[tagLength];
081    if (tag.hasArray()) {
082      Bytes.putBytes(tagArr, 0, tag.getValueArray(), tag.getValueOffset(), tagLength);
083    } else {
084      ByteBufferUtils.copyFromBufferToArray(tagArr, tag.getValueByteBuffer(), tag.getValueOffset(),
085        0, tagLength);
086    }
087    return tagArr;
088  }
089
090  /**
091   * Converts the value bytes of the given tag into a String value
092   * @param tag The Tag
093   * @return value as String
094   */
095  public static String getValueAsString(Tag tag) {
096    if (tag.hasArray()) {
097      return Bytes.toString(tag.getValueArray(), tag.getValueOffset(), tag.getValueLength());
098    }
099    return Bytes.toString(cloneValue(tag));
100  }
101
102  /**
103   * Matches the value part of given tags
104   * @param t1 Tag to match the value
105   * @param t2 Tag to match the value
106   * @return True if values of both tags are same.
107   */
108  public static boolean matchingValue(Tag t1, Tag t2) {
109    if (t1.hasArray() && t2.hasArray()) {
110      return Bytes.equals(t1.getValueArray(), t1.getValueOffset(), t1.getValueLength(),
111        t2.getValueArray(), t2.getValueOffset(), t2.getValueLength());
112    }
113    if (t1.hasArray()) {
114      return ByteBufferUtils.equals(t2.getValueByteBuffer(), t2.getValueOffset(),
115        t2.getValueLength(), t1.getValueArray(), t1.getValueOffset(), t1.getValueLength());
116    }
117    if (t2.hasArray()) {
118      return ByteBufferUtils.equals(t1.getValueByteBuffer(), t1.getValueOffset(),
119        t1.getValueLength(), t2.getValueArray(), t2.getValueOffset(), t2.getValueLength());
120    }
121    return ByteBufferUtils.equals(t1.getValueByteBuffer(), t1.getValueOffset(), t1.getValueLength(),
122      t2.getValueByteBuffer(), t2.getValueOffset(), t2.getValueLength());
123  }
124
125  /**
126   * Copies the tag's value bytes to the given byte array
127   * @param tag    The Tag
128   * @param out    The byte array where to copy the Tag value.
129   * @param offset The offset within 'out' array where to copy the Tag value.
130   */
131  public static void copyValueTo(Tag tag, byte[] out, int offset) {
132    if (tag.hasArray()) {
133      Bytes.putBytes(out, offset, tag.getValueArray(), tag.getValueOffset(), tag.getValueLength());
134    } else {
135      ByteBufferUtils.copyFromBufferToArray(out, tag.getValueByteBuffer(), tag.getValueOffset(),
136        offset, tag.getValueLength());
137    }
138  }
139
140  /**
141   * Converts the value bytes of the given tag into a long value
142   * @param tag The Tag
143   * @return value as long
144   */
145  public static long getValueAsLong(Tag tag) {
146    if (tag.hasArray()) {
147      return Bytes.toLong(tag.getValueArray(), tag.getValueOffset(), tag.getValueLength());
148    }
149    return ByteBufferUtils.toLong(tag.getValueByteBuffer(), tag.getValueOffset());
150  }
151
152  /**
153   * Converts the value bytes of the given tag into a byte value
154   * @param tag The Tag
155   * @return value as byte
156   */
157  public static byte getValueAsByte(Tag tag) {
158    if (tag.hasArray()) {
159      return tag.getValueArray()[tag.getValueOffset()];
160    }
161    return ByteBufferUtils.toByte(tag.getValueByteBuffer(), tag.getValueOffset());
162  }
163}