001/** 002 * 003 * Licensed to the Apache Software Foundation (ASF) under one 004 * or more contributor license agreements. See the NOTICE file 005 * distributed with this work for additional information 006 * regarding copyright ownership. The ASF licenses this file 007 * to you under the Apache License, Version 2.0 (the 008 * "License"); you may not use this file except in compliance 009 * with the License. You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, software 014 * distributed under the License is distributed on an "AS IS" BASIS, 015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 016 * See the License for the specific language governing permissions and 017 * limitations under the License. 018 */ 019package org.apache.hadoop.hbase; 020 021import java.io.IOException; 022import java.nio.ByteBuffer; 023import java.util.Collections; 024import java.util.Iterator; 025import java.util.Optional; 026import org.apache.hadoop.hbase.util.ByteBufferUtils; 027import org.apache.hadoop.hbase.util.Bytes; 028import org.apache.hadoop.hbase.util.ClassSize; 029import org.apache.yetus.audience.InterfaceAudience; 030 031/** 032 * This is a key only Cell implementation which is identical to {@link KeyValue.KeyOnlyKeyValue} 033 * with respect to key serialization but have its data in the form of Byte buffer 034 * (onheap and offheap). 035 */ 036@InterfaceAudience.Private 037public class ByteBufferKeyOnlyKeyValue extends ByteBufferExtendedCell { 038 public static final int FIXED_OVERHEAD = ClassSize.OBJECT + ClassSize.REFERENCE 039 + (2 * Bytes.SIZEOF_INT) + Bytes.SIZEOF_SHORT; 040 private ByteBuffer buf; 041 private int offset = 0; // offset into buffer where key starts at 042 private int length = 0; // length of this. 043 private short rowLen; 044 045 /** 046 * Used in cases where we want to avoid lot of garbage by allocating new objects with different 047 * keys. Use the emtpy construtor and set the keys using {@link #setKey(ByteBuffer, int, int)} 048 */ 049 public ByteBufferKeyOnlyKeyValue() { 050 } 051 052 public ByteBufferKeyOnlyKeyValue(ByteBuffer buf, int offset, int length) { 053 setKey(buf, offset, length); 054 } 055 056 /** 057 * A setter that helps to avoid object creation every time and whenever 058 * there is a need to create new OffheapKeyOnlyKeyValue. 059 * @param key 060 * @param offset 061 * @param length 062 */ 063 public void setKey(ByteBuffer key, int offset, int length) { 064 this.buf = key; 065 this.offset = offset; 066 this.length = length; 067 this.rowLen = ByteBufferUtils.toShort(this.buf, this.offset); 068 } 069 070 @Override 071 public byte[] getRowArray() { 072 if (this.buf.hasArray()) { 073 return this.buf.array(); 074 } 075 return CellUtil.cloneRow(this); 076 } 077 078 @Override 079 public int getRowOffset() { 080 if (this.buf.hasArray()) { 081 return getRowPosition() + this.buf.arrayOffset(); 082 } 083 return 0; 084 } 085 086 @Override 087 public short getRowLength() { 088 return this.rowLen; 089 } 090 091 @Override 092 public byte[] getFamilyArray() { 093 if (this.buf.hasArray()) { 094 return this.buf.array(); 095 } 096 return CellUtil.cloneFamily(this); 097 } 098 099 @Override 100 public int getFamilyOffset() { 101 if (this.buf.hasArray()) { 102 return getFamilyPosition() + this.buf.arrayOffset(); 103 } 104 return 0; 105 } 106 107 @Override 108 public byte getFamilyLength() { 109 return getFamilyLength(getFamilyLengthPosition()); 110 } 111 112 private byte getFamilyLength(int famLenPos) { 113 return ByteBufferUtils.toByte(this.buf, famLenPos); 114 } 115 116 @Override 117 public byte[] getQualifierArray() { 118 if (this.buf.hasArray()) { 119 return this.buf.array(); 120 } 121 return CellUtil.cloneQualifier(this); 122 } 123 124 @Override 125 public int getQualifierOffset() { 126 if (this.buf.hasArray()) { 127 return getQualifierPosition() + this.buf.arrayOffset(); 128 } 129 return 0; 130 } 131 132 @Override 133 public int getQualifierLength() { 134 return getQualifierLength(getRowLength(), getFamilyLength()); 135 } 136 137 private int getQualifierLength(int rlength, int flength) { 138 return this.length - (int) KeyValue.getKeyDataStructureSize(rlength, flength, 0); 139 } 140 141 @Override 142 public long getTimestamp() { 143 return ByteBufferUtils.toLong(this.buf, getTimestampOffset()); 144 } 145 146 private int getTimestampOffset() { 147 return this.offset + this.length - KeyValue.TIMESTAMP_TYPE_SIZE; 148 } 149 150 @Override 151 public byte getTypeByte() { 152 return ByteBufferUtils.toByte(this.buf, this.offset + this.length - 1); 153 } 154 155 @Override 156 public void setSequenceId(long seqId) throws IOException { 157 throw new IllegalArgumentException("This is a key only Cell"); 158 } 159 160 @Override 161 public void setTimestamp(long ts) throws IOException { 162 throw new IllegalArgumentException("This is a key only Cell"); 163 } 164 165 @Override 166 public void setTimestamp(byte[] ts) throws IOException { 167 throw new IllegalArgumentException("This is a key only Cell"); 168 } 169 170 @Override 171 public long getSequenceId() { 172 return 0; 173 } 174 175 @Override 176 public byte[] getValueArray() { 177 throw new IllegalArgumentException("This is a key only Cell"); 178 } 179 180 @Override 181 public int getValueOffset() { 182 return 0; 183 } 184 185 @Override 186 public int getValueLength() { 187 return 0; 188 } 189 190 @Override 191 public byte[] getTagsArray() { 192 throw new IllegalArgumentException("This is a key only Cell"); 193 } 194 195 @Override 196 public int getTagsOffset() { 197 return 0; 198 } 199 200 @Override 201 public int getTagsLength() { 202 return 0; 203 } 204 205 @Override 206 public ByteBuffer getRowByteBuffer() { 207 return this.buf; 208 } 209 210 @Override 211 public int getRowPosition() { 212 return this.offset + Bytes.SIZEOF_SHORT; 213 } 214 215 @Override 216 public ByteBuffer getFamilyByteBuffer() { 217 return this.buf; 218 } 219 220 @Override 221 public int getFamilyPosition() { 222 return getFamilyLengthPosition() + Bytes.SIZEOF_BYTE; 223 } 224 225 // The position in BB where the family length is added. 226 private int getFamilyLengthPosition() { 227 return this.offset + Bytes.SIZEOF_SHORT + getRowLength(); 228 } 229 230 @Override 231 public ByteBuffer getQualifierByteBuffer() { 232 return this.buf; 233 } 234 235 @Override 236 public int getQualifierPosition() { 237 int famLenPos = getFamilyLengthPosition(); 238 return famLenPos + Bytes.SIZEOF_BYTE + getFamilyLength(famLenPos); 239 } 240 241 @Override 242 public ByteBuffer getValueByteBuffer() { 243 throw new IllegalArgumentException("This is a key only Cell"); 244 } 245 246 @Override 247 public int getValuePosition() { 248 return 0; 249 } 250 251 @Override 252 public ByteBuffer getTagsByteBuffer() { 253 throw new IllegalArgumentException("This is a key only Cell"); 254 } 255 256 @Override 257 public int getTagsPosition() { 258 return 0; 259 } 260 261 @Override 262 public String toString() { 263 return CellUtil.toString(this, false); 264 } 265 266 @Override 267 public Iterator<Tag> getTags() { 268 return Collections.emptyIterator(); 269 } 270 271 @Override 272 public Optional<Tag> getTag(byte type) { 273 return Optional.empty(); 274 } 275 276 @Override 277 public long heapSize() { 278 if (this.buf.hasArray()) { 279 return ClassSize.align(FIXED_OVERHEAD + length); 280 } 281 return ClassSize.align(FIXED_OVERHEAD); 282 } 283}