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 static org.apache.hadoop.hbase.util.Bytes.len; 021 022import java.io.DataInput; 023import java.io.DataOutput; 024import java.io.IOException; 025import java.io.OutputStream; 026import java.nio.ByteBuffer; 027import java.util.ArrayList; 028import java.util.Arrays; 029import java.util.HashMap; 030import java.util.Iterator; 031import java.util.List; 032import java.util.Map; 033import org.apache.hadoop.hbase.util.ByteBufferUtils; 034import org.apache.hadoop.hbase.util.Bytes; 035import org.apache.hadoop.hbase.util.ClassSize; 036import org.apache.yetus.audience.InterfaceAudience; 037import org.slf4j.Logger; 038import org.slf4j.LoggerFactory; 039 040/** 041 * An HBase Key/Value. This is the fundamental HBase Type. 042 * <p> 043 * HBase applications and users should use the Cell interface and avoid directly using KeyValue and 044 * member functions not defined in Cell. 045 * <p> 046 * If being used client-side, the primary methods to access individual fields are 047 * {@link #getRowArray()}, {@link #getFamilyArray()}, {@link #getQualifierArray()}, 048 * {@link #getTimestamp()}, and {@link #getValueArray()}. These methods allocate new byte arrays and 049 * return copies. Avoid their use server-side. 050 * <p> 051 * Instances of this class are immutable. They do not implement Comparable but Comparators are 052 * provided. Comparators change with context, whether user table or a catalog table comparison. Its 053 * critical you use the appropriate comparator. There are Comparators for normal HFiles, Meta's 054 * Hfiles, and bloom filter keys. 055 * <p> 056 * KeyValue wraps a byte array and takes offsets and lengths into passed array at where to start 057 * interpreting the content as KeyValue. The KeyValue format inside a byte array is: 058 * <code><keylength> <valuelength> <key> <value></code> Key is further 059 * decomposed as: <code><rowlength> <row> <columnfamilylength> 060 * <columnfamily> <columnqualifier> 061 * <timestamp> <keytype></code> The <code>rowlength</code> maximum is 062 * <code>Short.MAX_SIZE</code>, column family length maximum is <code>Byte.MAX_SIZE</code>, and 063 * column qualifier + key length must be < <code>Integer.MAX_SIZE</code>. The column does not 064 * contain the family/qualifier delimiter, {@link #COLUMN_FAMILY_DELIMITER}<br> 065 * KeyValue can optionally contain Tags. When it contains tags, it is added in the byte array after 066 * the value part. The format for this part is: <code><tagslength><tagsbytes></code>. 067 * <code>tagslength</code> maximum is <code>Short.MAX_SIZE</code>. The <code>tagsbytes</code> 068 * contain one or more tags where as each tag is of the form 069 * <code><taglength><tagtype><tagbytes></code>. <code>tagtype</code> is one byte 070 * and <code>taglength</code> maximum is <code>Short.MAX_SIZE</code> and it includes 1 byte type 071 * length and actual tag bytes length. 072 */ 073@InterfaceAudience.Private 074public class KeyValue implements ExtendedCell, Cloneable { 075 private static final Logger LOG = LoggerFactory.getLogger(KeyValue.class); 076 077 public static final int FIXED_OVERHEAD = ClassSize.OBJECT + // the KeyValue object itself 078 ClassSize.REFERENCE + // pointer to "bytes" 079 2 * Bytes.SIZEOF_INT + // offset, length 080 Bytes.SIZEOF_LONG;// memstoreTS 081 082 /** 083 * Colon character in UTF-8 084 */ 085 public static final char COLUMN_FAMILY_DELIMITER = ':'; 086 087 public static final byte[] COLUMN_FAMILY_DELIM_ARRAY = new byte[] { COLUMN_FAMILY_DELIMITER }; 088 089 /** Size of the key length field in bytes */ 090 public static final int KEY_LENGTH_SIZE = Bytes.SIZEOF_INT; 091 092 /** Size of the key type field in bytes */ 093 public static final int TYPE_SIZE = Bytes.SIZEOF_BYTE; 094 095 /** Size of the row length field in bytes */ 096 public static final int ROW_LENGTH_SIZE = Bytes.SIZEOF_SHORT; 097 098 /** Size of the family length field in bytes */ 099 public static final int FAMILY_LENGTH_SIZE = Bytes.SIZEOF_BYTE; 100 101 /** Size of the timestamp field in bytes */ 102 public static final int TIMESTAMP_SIZE = Bytes.SIZEOF_LONG; 103 104 // Size of the timestamp and type byte on end of a key -- a long + a byte. 105 public static final int TIMESTAMP_TYPE_SIZE = TIMESTAMP_SIZE + TYPE_SIZE; 106 107 // Size of the length shorts and bytes in key. 108 public static final int KEY_INFRASTRUCTURE_SIZE = 109 ROW_LENGTH_SIZE + FAMILY_LENGTH_SIZE + TIMESTAMP_TYPE_SIZE; 110 111 // How far into the key the row starts at. First thing to read is the short 112 // that says how long the row is. 113 public static final int ROW_OFFSET = 114 Bytes.SIZEOF_INT /* keylength */ + Bytes.SIZEOF_INT /* valuelength */; 115 116 public static final int ROW_KEY_OFFSET = ROW_OFFSET + ROW_LENGTH_SIZE; 117 118 // Size of the length ints in a KeyValue datastructure. 119 public static final int KEYVALUE_INFRASTRUCTURE_SIZE = ROW_OFFSET; 120 121 /** Size of the tags length field in bytes */ 122 public static final int TAGS_LENGTH_SIZE = Bytes.SIZEOF_SHORT; 123 124 public static final int KEYVALUE_WITH_TAGS_INFRASTRUCTURE_SIZE = ROW_OFFSET + TAGS_LENGTH_SIZE; 125 126 /** 127 * Computes the number of bytes that a <code>KeyValue</code> instance with the provided 128 * characteristics would take up for its underlying data structure. 129 * @param rlength row length 130 * @param flength family length 131 * @param qlength qualifier length 132 * @param vlength value length 133 * @return the <code>KeyValue</code> data structure length 134 */ 135 public static long getKeyValueDataStructureSize(int rlength, int flength, int qlength, 136 int vlength) { 137 return KeyValue.KEYVALUE_INFRASTRUCTURE_SIZE 138 + getKeyDataStructureSize(rlength, flength, qlength) + vlength; 139 } 140 141 /** 142 * Computes the number of bytes that a <code>KeyValue</code> instance with the provided 143 * characteristics would take up for its underlying data structure. 144 * @param rlength row length 145 * @param flength family length 146 * @param qlength qualifier length 147 * @param vlength value length 148 * @param tagsLength total length of the tags 149 * @return the <code>KeyValue</code> data structure length 150 */ 151 public static long getKeyValueDataStructureSize(int rlength, int flength, int qlength, 152 int vlength, int tagsLength) { 153 if (tagsLength == 0) { 154 return getKeyValueDataStructureSize(rlength, flength, qlength, vlength); 155 } 156 return KeyValue.KEYVALUE_WITH_TAGS_INFRASTRUCTURE_SIZE 157 + getKeyDataStructureSize(rlength, flength, qlength) + vlength + tagsLength; 158 } 159 160 /** 161 * Computes the number of bytes that a <code>KeyValue</code> instance with the provided 162 * characteristics would take up for its underlying data structure. 163 * @param klength key length 164 * @param vlength value length 165 * @param tagsLength total length of the tags 166 * @return the <code>KeyValue</code> data structure length 167 */ 168 public static long getKeyValueDataStructureSize(int klength, int vlength, int tagsLength) { 169 if (tagsLength == 0) { 170 return (long) KeyValue.KEYVALUE_INFRASTRUCTURE_SIZE + klength + vlength; 171 } 172 return (long) KeyValue.KEYVALUE_WITH_TAGS_INFRASTRUCTURE_SIZE + klength + vlength + tagsLength; 173 } 174 175 /** 176 * Computes the number of bytes that a <code>KeyValue</code> instance with the provided 177 * characteristics would take up in its underlying data structure for the key. 178 * @param rlength row length 179 * @param flength family length 180 * @param qlength qualifier length 181 * @return the key data structure length 182 */ 183 public static long getKeyDataStructureSize(int rlength, int flength, int qlength) { 184 return (long) KeyValue.KEY_INFRASTRUCTURE_SIZE + rlength + flength + qlength; 185 } 186 187 /** 188 * Key type. Has space for other key types to be added later. Cannot rely on enum ordinals . They 189 * change if item is removed or moved. Do our own codes. 190 */ 191 public static enum Type { 192 Minimum((byte) 0), 193 Put((byte) 4), 194 195 Delete((byte) 8), 196 DeleteFamilyVersion((byte) 10), 197 DeleteColumn((byte) 12), 198 DeleteFamily((byte) 14), 199 200 // Maximum is used when searching; you look from maximum on down. 201 Maximum((byte) 255); 202 203 private final byte code; 204 205 Type(final byte c) { 206 this.code = c; 207 } 208 209 public byte getCode() { 210 return this.code; 211 } 212 213 private static Type[] codeArray = new Type[256]; 214 215 static { 216 for (Type t : Type.values()) { 217 codeArray[t.code & 0xff] = t; 218 } 219 } 220 221 /** 222 * True to indicate that the byte b is a valid type. 223 * @param b byte to check 224 * @return true or false 225 */ 226 static boolean isValidType(byte b) { 227 return codeArray[b & 0xff] != null; 228 } 229 230 /** 231 * Cannot rely on enum ordinals . They change if item is removed or moved. Do our own codes. 232 * @param b the kv serialized byte[] to process 233 * @return Type associated with passed code. 234 */ 235 public static Type codeToType(final byte b) { 236 Type t = codeArray[b & 0xff]; 237 if (t != null) { 238 return t; 239 } 240 throw new RuntimeException("Unknown code " + b); 241 } 242 } 243 244 /** 245 * Lowest possible key. Makes a Key with highest possible Timestamp, empty row and column. No key 246 * can be equal or lower than this one in memstore or in store file. 247 */ 248 public static final KeyValue LOWESTKEY = 249 new KeyValue(HConstants.EMPTY_BYTE_ARRAY, HConstants.LATEST_TIMESTAMP); 250 251 //// 252 // KeyValue core instance fields. 253 protected byte[] bytes = null; // an immutable byte array that contains the KV 254 protected int offset = 0; // offset into bytes buffer KV starts at 255 protected int length = 0; // length of the KV starting from offset. 256 257 /** Here be dragons **/ 258 259 /** 260 * used to achieve atomic operations in the memstore. 261 */ 262 @Override 263 public long getSequenceId() { 264 return seqId; 265 } 266 267 @Override 268 public void setSequenceId(long seqId) { 269 this.seqId = seqId; 270 } 271 272 // multi-version concurrency control version. default value is 0, aka do not care. 273 private long seqId = 0; 274 275 /** Dragon time over, return to normal business */ 276 277 /** Writable Constructor -- DO NOT USE */ 278 public KeyValue() { 279 } 280 281 /** 282 * Creates a KeyValue from the start of the specified byte array. Presumes <code>bytes</code> 283 * content is formatted as a KeyValue blob. 284 * @param bytes byte array 285 */ 286 public KeyValue(final byte[] bytes) { 287 this(bytes, 0); 288 } 289 290 /** 291 * Creates a KeyValue from the specified byte array and offset. Presumes <code>bytes</code> 292 * content starting at <code>offset</code> is formatted as a KeyValue blob. 293 * @param bytes byte array 294 * @param offset offset to start of KeyValue 295 */ 296 public KeyValue(final byte[] bytes, final int offset) { 297 this(bytes, offset, getLength(bytes, offset)); 298 } 299 300 /** 301 * Creates a KeyValue from the specified byte array, starting at offset, and for length 302 * <code>length</code>. 303 * @param bytes byte array 304 * @param offset offset to start of the KeyValue 305 * @param length length of the KeyValue 306 */ 307 public KeyValue(final byte[] bytes, final int offset, final int length) { 308 KeyValueUtil.checkKeyValueBytes(bytes, offset, length, true); 309 this.bytes = bytes; 310 this.offset = offset; 311 this.length = length; 312 } 313 314 /** 315 * Creates a KeyValue from the specified byte array, starting at offset, and for length 316 * <code>length</code>. 317 * @param bytes byte array 318 * @param offset offset to start of the KeyValue 319 * @param length length of the KeyValue 320 * @param ts timestamp 321 */ 322 public KeyValue(final byte[] bytes, final int offset, final int length, long ts) { 323 this(bytes, offset, length, null, 0, 0, null, 0, 0, ts, Type.Maximum, null, 0, 0, null); 324 } 325 326 /** Constructors that build a new backing byte array from fields */ 327 328 /** 329 * Constructs KeyValue structure filled with null value. Sets type to 330 * {@link KeyValue.Type#Maximum} 331 * @param row - row key (arbitrary byte array) 332 * @param timestamp version timestamp 333 */ 334 public KeyValue(final byte[] row, final long timestamp) { 335 this(row, null, null, timestamp, Type.Maximum, null); 336 } 337 338 /** 339 * Constructs KeyValue structure filled with null value. 340 * @param row - row key (arbitrary byte array) 341 * @param timestamp version timestamp 342 */ 343 public KeyValue(final byte[] row, final long timestamp, Type type) { 344 this(row, null, null, timestamp, type, null); 345 } 346 347 /** 348 * Constructs KeyValue structure filled with null value. Sets type to 349 * {@link KeyValue.Type#Maximum} 350 * @param row - row key (arbitrary byte array) 351 * @param family family name 352 * @param qualifier column qualifier 353 */ 354 public KeyValue(final byte[] row, final byte[] family, final byte[] qualifier) { 355 this(row, family, qualifier, HConstants.LATEST_TIMESTAMP, Type.Maximum); 356 } 357 358 /** 359 * Constructs KeyValue structure as a put filled with specified values and LATEST_TIMESTAMP. 360 * @param row - row key (arbitrary byte array) 361 * @param family family name 362 * @param qualifier column qualifier 363 */ 364 public KeyValue(final byte[] row, final byte[] family, final byte[] qualifier, 365 final byte[] value) { 366 this(row, family, qualifier, HConstants.LATEST_TIMESTAMP, Type.Put, value); 367 } 368 369 /** 370 * Constructs KeyValue structure filled with specified values. 371 * @param row row key 372 * @param family family name 373 * @param qualifier column qualifier 374 * @param timestamp version timestamp 375 * @param type key type 376 * @throws IllegalArgumentException an illegal value was passed 377 */ 378 public KeyValue(final byte[] row, final byte[] family, final byte[] qualifier, 379 final long timestamp, Type type) { 380 this(row, family, qualifier, timestamp, type, null); 381 } 382 383 /** 384 * Constructs KeyValue structure filled with specified values. 385 * @param row row key 386 * @param family family name 387 * @param qualifier column qualifier 388 * @param timestamp version timestamp 389 * @param value column value 390 * @throws IllegalArgumentException an illegal value was passed 391 */ 392 public KeyValue(final byte[] row, final byte[] family, final byte[] qualifier, 393 final long timestamp, final byte[] value) { 394 this(row, family, qualifier, timestamp, Type.Put, value); 395 } 396 397 /** 398 * Constructs KeyValue structure filled with specified values. 399 * @param row row key 400 * @param family family name 401 * @param qualifier column qualifier 402 * @param timestamp version timestamp 403 * @param value column value 404 * @param tags tags 405 * @throws IllegalArgumentException an illegal value was passed 406 */ 407 public KeyValue(final byte[] row, final byte[] family, final byte[] qualifier, 408 final long timestamp, final byte[] value, final Tag[] tags) { 409 this(row, family, qualifier, timestamp, value, tags != null ? Arrays.asList(tags) : null); 410 } 411 412 /** 413 * Constructs KeyValue structure filled with specified values. 414 * @param row row key 415 * @param family family name 416 * @param qualifier column qualifier 417 * @param timestamp version timestamp 418 * @param value column value 419 * @param tags tags non-empty list of tags or null 420 * @throws IllegalArgumentException an illegal value was passed 421 */ 422 public KeyValue(final byte[] row, final byte[] family, final byte[] qualifier, 423 final long timestamp, final byte[] value, final List<Tag> tags) { 424 this(row, 0, row == null ? 0 : row.length, family, 0, family == null ? 0 : family.length, 425 qualifier, 0, qualifier == null ? 0 : qualifier.length, timestamp, Type.Put, value, 0, 426 value == null ? 0 : value.length, tags); 427 } 428 429 /** 430 * Constructs KeyValue structure filled with specified values. 431 * @param row row key 432 * @param family family name 433 * @param qualifier column qualifier 434 * @param timestamp version timestamp 435 * @param type key type 436 * @param value column value 437 * @throws IllegalArgumentException an illegal value was passed 438 */ 439 public KeyValue(final byte[] row, final byte[] family, final byte[] qualifier, 440 final long timestamp, Type type, final byte[] value) { 441 this(row, 0, len(row), family, 0, len(family), qualifier, 0, len(qualifier), timestamp, type, 442 value, 0, len(value)); 443 } 444 445 /** 446 * Constructs KeyValue structure filled with specified values. 447 * <p> 448 * Column is split into two fields, family and qualifier. 449 * @param row row key 450 * @param family family name 451 * @param qualifier column qualifier 452 * @param timestamp version timestamp 453 * @param type key type 454 * @param value column value 455 * @throws IllegalArgumentException an illegal value was passed 456 */ 457 public KeyValue(final byte[] row, final byte[] family, final byte[] qualifier, 458 final long timestamp, Type type, final byte[] value, final List<Tag> tags) { 459 this(row, family, qualifier, 0, qualifier == null ? 0 : qualifier.length, timestamp, type, 460 value, 0, value == null ? 0 : value.length, tags); 461 } 462 463 /** 464 * Constructs KeyValue structure filled with specified values. 465 * @param row row key 466 * @param family family name 467 * @param qualifier column qualifier 468 * @param timestamp version timestamp 469 * @param type key type 470 * @param value column value 471 * @throws IllegalArgumentException an illegal value was passed 472 */ 473 public KeyValue(final byte[] row, final byte[] family, final byte[] qualifier, 474 final long timestamp, Type type, final byte[] value, final byte[] tags) { 475 this(row, family, qualifier, 0, qualifier == null ? 0 : qualifier.length, timestamp, type, 476 value, 0, value == null ? 0 : value.length, tags); 477 } 478 479 /** 480 * Constructs KeyValue structure filled with specified values. 481 * @param row row key 482 * @param family family name 483 * @param qualifier column qualifier 484 * @param qoffset qualifier offset 485 * @param qlength qualifier length 486 * @param timestamp version timestamp 487 * @param type key type 488 * @param value column value 489 * @param voffset value offset 490 * @param vlength value length 491 * @throws IllegalArgumentException an illegal value was passed 492 */ 493 public KeyValue(byte[] row, byte[] family, byte[] qualifier, int qoffset, int qlength, 494 long timestamp, Type type, byte[] value, int voffset, int vlength, List<Tag> tags) { 495 this(row, 0, row == null ? 0 : row.length, family, 0, family == null ? 0 : family.length, 496 qualifier, qoffset, qlength, timestamp, type, value, voffset, vlength, tags); 497 } 498 499 /** 500 * @param row row key 501 * @param family family name 502 * @param qualifier qualifier name 503 * @param qoffset qualifier offset 504 * @param qlength qualifier length 505 * @param timestamp version timestamp 506 * @param type key type 507 * @param value column value 508 * @param voffset value offset 509 * @param vlength value length 510 * @param tags tags 511 */ 512 public KeyValue(byte[] row, byte[] family, byte[] qualifier, int qoffset, int qlength, 513 long timestamp, Type type, byte[] value, int voffset, int vlength, byte[] tags) { 514 this(row, 0, row == null ? 0 : row.length, family, 0, family == null ? 0 : family.length, 515 qualifier, qoffset, qlength, timestamp, type, value, voffset, vlength, tags, 0, 516 tags == null ? 0 : tags.length); 517 } 518 519 /** 520 * Constructs KeyValue structure filled with specified values. 521 * <p> 522 * Column is split into two fields, family and qualifier. 523 * @param row row key 524 * @throws IllegalArgumentException an illegal value was passed 525 */ 526 public KeyValue(final byte[] row, final int roffset, final int rlength, final byte[] family, 527 final int foffset, final int flength, final byte[] qualifier, final int qoffset, 528 final int qlength, final long timestamp, final Type type, final byte[] value, final int voffset, 529 final int vlength) { 530 this(row, roffset, rlength, family, foffset, flength, qualifier, qoffset, qlength, timestamp, 531 type, value, voffset, vlength, null); 532 } 533 534 /** 535 * Constructs KeyValue structure filled with specified values. Uses the provided buffer as the 536 * data buffer. 537 * <p> 538 * Column is split into two fields, family and qualifier. 539 * @param buffer the bytes buffer to use 540 * @param boffset buffer offset 541 * @param row row key 542 * @param roffset row offset 543 * @param rlength row length 544 * @param family family name 545 * @param foffset family offset 546 * @param flength family length 547 * @param qualifier column qualifier 548 * @param qoffset qualifier offset 549 * @param qlength qualifier length 550 * @param timestamp version timestamp 551 * @param type key type 552 * @param value column value 553 * @param voffset value offset 554 * @param vlength value length 555 * @param tags non-empty list of tags or null 556 * @throws IllegalArgumentException an illegal value was passed or there is insufficient space 557 * remaining in the buffer 558 */ 559 public KeyValue(byte[] buffer, final int boffset, final byte[] row, final int roffset, 560 final int rlength, final byte[] family, final int foffset, final int flength, 561 final byte[] qualifier, final int qoffset, final int qlength, final long timestamp, 562 final Type type, final byte[] value, final int voffset, final int vlength, final Tag[] tags) { 563 this.bytes = buffer; 564 this.length = writeByteArray(buffer, boffset, row, roffset, rlength, family, foffset, flength, 565 qualifier, qoffset, qlength, timestamp, type, value, voffset, vlength, tags); 566 this.offset = boffset; 567 } 568 569 /** 570 * Constructs KeyValue structure filled with specified values. 571 * <p> 572 * Column is split into two fields, family and qualifier. 573 * @param row row key 574 * @param roffset row offset 575 * @param rlength row length 576 * @param family family name 577 * @param foffset family offset 578 * @param flength family length 579 * @param qualifier column qualifier 580 * @param qoffset qualifier offset 581 * @param qlength qualifier length 582 * @param timestamp version timestamp 583 * @param type key type 584 * @param value column value 585 * @param voffset value offset 586 * @param vlength value length 587 * @param tags tags 588 * @throws IllegalArgumentException an illegal value was passed 589 */ 590 public KeyValue(final byte[] row, final int roffset, final int rlength, final byte[] family, 591 final int foffset, final int flength, final byte[] qualifier, final int qoffset, 592 final int qlength, final long timestamp, final Type type, final byte[] value, final int voffset, 593 final int vlength, final List<Tag> tags) { 594 this.bytes = createByteArray(row, roffset, rlength, family, foffset, flength, qualifier, 595 qoffset, qlength, timestamp, type, value, voffset, vlength, tags); 596 this.length = bytes.length; 597 this.offset = 0; 598 } 599 600 /** 601 * @param row row key 602 * @param roffset row offset 603 * @param rlength row length 604 * @param family family name 605 * @param foffset fammily offset 606 * @param flength family length 607 * @param qualifier column qualifier 608 * @param qoffset qualifier offset 609 * @param qlength qualifier length 610 * @param timestamp version timestamp 611 * @param type key type 612 * @param value column value 613 * @param voffset value offset 614 * @param vlength value length 615 * @param tags input tags 616 */ 617 public KeyValue(final byte[] row, final int roffset, final int rlength, final byte[] family, 618 final int foffset, final int flength, final byte[] qualifier, final int qoffset, 619 final int qlength, final long timestamp, final Type type, final byte[] value, final int voffset, 620 final int vlength, final byte[] tags, final int tagsOffset, final int tagsLength) { 621 this.bytes = createByteArray(row, roffset, rlength, family, foffset, flength, qualifier, 622 qoffset, qlength, timestamp, type, value, voffset, vlength, tags, tagsOffset, tagsLength); 623 this.length = bytes.length; 624 this.offset = 0; 625 } 626 627 /** 628 * Constructs an empty KeyValue structure, with specified sizes. This can be used to partially 629 * fill up KeyValues. 630 * <p> 631 * Column is split into two fields, family and qualifier. 632 * @param rlength row length 633 * @param flength family length 634 * @param qlength qualifier length 635 * @param timestamp version timestamp 636 * @param type key type 637 * @param vlength value length 638 * @throws IllegalArgumentException an illegal value was passed 639 */ 640 public KeyValue(final int rlength, final int flength, final int qlength, final long timestamp, 641 final Type type, final int vlength) { 642 this(rlength, flength, qlength, timestamp, type, vlength, 0); 643 } 644 645 /** 646 * Constructs an empty KeyValue structure, with specified sizes. This can be used to partially 647 * fill up KeyValues. 648 * <p> 649 * Column is split into two fields, family and qualifier. 650 * @param rlength row length 651 * @param flength family length 652 * @param qlength qualifier length 653 * @param timestamp version timestamp 654 * @param type key type 655 * @param vlength value length 656 * @param tagsLength length of the tags 657 * @throws IllegalArgumentException an illegal value was passed 658 */ 659 public KeyValue(final int rlength, final int flength, final int qlength, final long timestamp, 660 final Type type, final int vlength, final int tagsLength) { 661 this.bytes = 662 createEmptyByteArray(rlength, flength, qlength, timestamp, type, vlength, tagsLength); 663 this.length = bytes.length; 664 this.offset = 0; 665 } 666 667 public KeyValue(byte[] row, int roffset, int rlength, byte[] family, int foffset, int flength, 668 ByteBuffer qualifier, long ts, Type type, ByteBuffer value, List<Tag> tags) { 669 this.bytes = createByteArray(row, roffset, rlength, family, foffset, flength, qualifier, 0, 670 qualifier == null ? 0 : qualifier.remaining(), ts, type, value, 0, 671 value == null ? 0 : value.remaining(), tags); 672 this.length = bytes.length; 673 this.offset = 0; 674 } 675 676 public KeyValue(ExtendedCell c) { 677 this(c.getRowArray(), c.getRowOffset(), c.getRowLength(), c.getFamilyArray(), 678 c.getFamilyOffset(), c.getFamilyLength(), c.getQualifierArray(), c.getQualifierOffset(), 679 c.getQualifierLength(), c.getTimestamp(), Type.codeToType(c.getTypeByte()), c.getValueArray(), 680 c.getValueOffset(), c.getValueLength(), c.getTagsArray(), c.getTagsOffset(), 681 c.getTagsLength()); 682 this.seqId = c.getSequenceId(); 683 } 684 685 /** 686 * Create an empty byte[] representing a KeyValue All lengths are preset and can be filled in 687 * later. 688 * @param rlength row length 689 * @param flength family length 690 * @param qlength qualifier length 691 * @param timestamp version timestamp 692 * @param type key type 693 * @param vlength value length 694 * @return The newly created byte array. 695 */ 696 private static byte[] createEmptyByteArray(final int rlength, int flength, int qlength, 697 final long timestamp, final Type type, int vlength, int tagsLength) { 698 if (rlength > Short.MAX_VALUE) { 699 throw new IllegalArgumentException("Row > " + Short.MAX_VALUE); 700 } 701 if (flength > Byte.MAX_VALUE) { 702 throw new IllegalArgumentException("Family > " + Byte.MAX_VALUE); 703 } 704 // Qualifier length 705 if (qlength > Integer.MAX_VALUE - rlength - flength) { 706 throw new IllegalArgumentException("Qualifier > " + Integer.MAX_VALUE); 707 } 708 RawCell.checkForTagsLength(tagsLength); 709 // Key length 710 long longkeylength = getKeyDataStructureSize(rlength, flength, qlength); 711 if (longkeylength > Integer.MAX_VALUE) { 712 throw new IllegalArgumentException("keylength " + longkeylength + " > " + Integer.MAX_VALUE); 713 } 714 int keylength = (int) longkeylength; 715 // Value length 716 if (vlength > HConstants.MAXIMUM_VALUE_LENGTH) { // FindBugs INT_VACUOUS_COMPARISON 717 throw new IllegalArgumentException("Valuer > " + HConstants.MAXIMUM_VALUE_LENGTH); 718 } 719 720 // Allocate right-sized byte array. 721 byte[] bytes = 722 new byte[(int) getKeyValueDataStructureSize(rlength, flength, qlength, vlength, tagsLength)]; 723 // Write the correct size markers 724 int pos = 0; 725 pos = Bytes.putInt(bytes, pos, keylength); 726 pos = Bytes.putInt(bytes, pos, vlength); 727 pos = Bytes.putShort(bytes, pos, (short) (rlength & 0x0000ffff)); 728 pos += rlength; 729 pos = Bytes.putByte(bytes, pos, (byte) (flength & 0x0000ff)); 730 pos += flength + qlength; 731 pos = Bytes.putLong(bytes, pos, timestamp); 732 pos = Bytes.putByte(bytes, pos, type.getCode()); 733 pos += vlength; 734 if (tagsLength > 0) { 735 pos = Bytes.putAsShort(bytes, pos, tagsLength); 736 } 737 return bytes; 738 } 739 740 /** 741 * Checks the parameters passed to a constructor. 742 * @param row row key 743 * @param rlength row length 744 * @param family family name 745 * @param flength family length 746 * @param qlength qualifier length 747 * @param vlength value length 748 * @throws IllegalArgumentException an illegal value was passed 749 */ 750 static void checkParameters(final byte[] row, final int rlength, final byte[] family, int flength, 751 int qlength, int vlength) throws IllegalArgumentException { 752 if (rlength > Short.MAX_VALUE) { 753 throw new IllegalArgumentException("Row > " + Short.MAX_VALUE); 754 } 755 if (row == null) { 756 throw new IllegalArgumentException("Row is null"); 757 } 758 // Family length 759 flength = family == null ? 0 : flength; 760 if (flength > Byte.MAX_VALUE) { 761 throw new IllegalArgumentException("Family > " + Byte.MAX_VALUE); 762 } 763 // Qualifier length 764 if (qlength > Integer.MAX_VALUE - rlength - flength) { 765 throw new IllegalArgumentException("Qualifier > " + Integer.MAX_VALUE); 766 } 767 // Key length 768 long longKeyLength = getKeyDataStructureSize(rlength, flength, qlength); 769 if (longKeyLength > Integer.MAX_VALUE) { 770 throw new IllegalArgumentException("keylength " + longKeyLength + " > " + Integer.MAX_VALUE); 771 } 772 // Value length 773 if (vlength > HConstants.MAXIMUM_VALUE_LENGTH) { // FindBugs INT_VACUOUS_COMPARISON 774 throw new IllegalArgumentException( 775 "Value length " + vlength + " > " + HConstants.MAXIMUM_VALUE_LENGTH); 776 } 777 } 778 779 /** 780 * Write KeyValue format into the provided byte array. 781 * @param buffer the bytes buffer to use 782 * @param boffset buffer offset 783 * @param row row key 784 * @param roffset row offset 785 * @param rlength row length 786 * @param family family name 787 * @param foffset family offset 788 * @param flength family length 789 * @param qualifier column qualifier 790 * @param qoffset qualifier offset 791 * @param qlength qualifier length 792 * @param timestamp version timestamp 793 * @param type key type 794 * @param value column value 795 * @param voffset value offset 796 * @param vlength value length 797 * @return The number of useful bytes in the buffer. 798 * @throws IllegalArgumentException an illegal value was passed or there is insufficient space 799 * remaining in the buffer 800 */ 801 public static int writeByteArray(byte[] buffer, final int boffset, final byte[] row, 802 final int roffset, final int rlength, final byte[] family, final int foffset, int flength, 803 final byte[] qualifier, final int qoffset, int qlength, final long timestamp, final Type type, 804 final byte[] value, final int voffset, int vlength, Tag[] tags) { 805 806 checkParameters(row, rlength, family, flength, qlength, vlength); 807 808 // Calculate length of tags area 809 int tagsLength = 0; 810 if (tags != null && tags.length > 0) { 811 for (Tag t : tags) { 812 tagsLength += t.getValueLength() + Tag.INFRASTRUCTURE_SIZE; 813 } 814 } 815 RawCell.checkForTagsLength(tagsLength); 816 int keyLength = (int) getKeyDataStructureSize(rlength, flength, qlength); 817 int keyValueLength = 818 (int) getKeyValueDataStructureSize(rlength, flength, qlength, vlength, tagsLength); 819 if (keyValueLength > buffer.length - boffset) { 820 throw new IllegalArgumentException( 821 "Buffer size " + (buffer.length - boffset) + " < " + keyValueLength); 822 } 823 824 // Write key, value and key row length. 825 int pos = boffset; 826 pos = Bytes.putInt(buffer, pos, keyLength); 827 pos = Bytes.putInt(buffer, pos, vlength); 828 pos = Bytes.putShort(buffer, pos, (short) (rlength & 0x0000ffff)); 829 pos = Bytes.putBytes(buffer, pos, row, roffset, rlength); 830 pos = Bytes.putByte(buffer, pos, (byte) (flength & 0x0000ff)); 831 if (flength != 0) { 832 pos = Bytes.putBytes(buffer, pos, family, foffset, flength); 833 } 834 if (qlength != 0) { 835 pos = Bytes.putBytes(buffer, pos, qualifier, qoffset, qlength); 836 } 837 pos = Bytes.putLong(buffer, pos, timestamp); 838 pos = Bytes.putByte(buffer, pos, type.getCode()); 839 if (value != null && value.length > 0) { 840 pos = Bytes.putBytes(buffer, pos, value, voffset, vlength); 841 } 842 // Write the number of tags. If it is 0 then it means there are no tags. 843 if (tagsLength > 0) { 844 pos = Bytes.putAsShort(buffer, pos, tagsLength); 845 for (Tag t : tags) { 846 int tlen = t.getValueLength(); 847 pos = Bytes.putAsShort(buffer, pos, tlen + Tag.TYPE_LENGTH_SIZE); 848 pos = Bytes.putByte(buffer, pos, t.getType()); 849 Tag.copyValueTo(t, buffer, pos); 850 pos += tlen; 851 } 852 } 853 return keyValueLength; 854 } 855 856 /** 857 * Write KeyValue format into a byte array. 858 * @param row row key 859 * @param roffset row offset 860 * @param rlength row length 861 * @param family family name 862 * @param foffset family offset 863 * @param flength family length 864 * @param qualifier column qualifier 865 * @param qoffset qualifier offset 866 * @param qlength qualifier length 867 * @param timestamp version timestamp 868 * @param type key type 869 * @param value column value 870 * @param voffset value offset 871 * @param vlength value length 872 * @return The newly created byte array. 873 */ 874 private static byte[] createByteArray(final byte[] row, final int roffset, final int rlength, 875 final byte[] family, final int foffset, int flength, final byte[] qualifier, final int qoffset, 876 int qlength, final long timestamp, final Type type, final byte[] value, final int voffset, 877 int vlength, byte[] tags, int tagsOffset, int tagsLength) { 878 879 checkParameters(row, rlength, family, flength, qlength, vlength); 880 RawCell.checkForTagsLength(tagsLength); 881 // Allocate right-sized byte array. 882 int keyLength = (int) getKeyDataStructureSize(rlength, flength, qlength); 883 byte[] bytes = 884 new byte[(int) getKeyValueDataStructureSize(rlength, flength, qlength, vlength, tagsLength)]; 885 // Write key, value and key row length. 886 int pos = 0; 887 pos = Bytes.putInt(bytes, pos, keyLength); 888 pos = Bytes.putInt(bytes, pos, vlength); 889 pos = Bytes.putShort(bytes, pos, (short) (rlength & 0x0000ffff)); 890 pos = Bytes.putBytes(bytes, pos, row, roffset, rlength); 891 pos = Bytes.putByte(bytes, pos, (byte) (flength & 0x0000ff)); 892 if (flength != 0) { 893 pos = Bytes.putBytes(bytes, pos, family, foffset, flength); 894 } 895 if (qlength != 0) { 896 pos = Bytes.putBytes(bytes, pos, qualifier, qoffset, qlength); 897 } 898 pos = Bytes.putLong(bytes, pos, timestamp); 899 pos = Bytes.putByte(bytes, pos, type.getCode()); 900 if (value != null && value.length > 0) { 901 pos = Bytes.putBytes(bytes, pos, value, voffset, vlength); 902 } 903 // Add the tags after the value part 904 if (tagsLength > 0) { 905 pos = Bytes.putAsShort(bytes, pos, tagsLength); 906 pos = Bytes.putBytes(bytes, pos, tags, tagsOffset, tagsLength); 907 } 908 return bytes; 909 } 910 911 /** 912 * @param qualifier can be a ByteBuffer or a byte[], or null. 913 * @param value can be a ByteBuffer or a byte[], or null. 914 */ 915 private static byte[] createByteArray(final byte[] row, final int roffset, final int rlength, 916 final byte[] family, final int foffset, int flength, final Object qualifier, final int qoffset, 917 int qlength, final long timestamp, final Type type, final Object value, final int voffset, 918 int vlength, List<Tag> tags) { 919 920 checkParameters(row, rlength, family, flength, qlength, vlength); 921 922 // Calculate length of tags area 923 int tagsLength = 0; 924 if (tags != null && !tags.isEmpty()) { 925 for (Tag t : tags) { 926 tagsLength += t.getValueLength() + Tag.INFRASTRUCTURE_SIZE; 927 } 928 } 929 RawCell.checkForTagsLength(tagsLength); 930 // Allocate right-sized byte array. 931 int keyLength = (int) getKeyDataStructureSize(rlength, flength, qlength); 932 byte[] bytes = 933 new byte[(int) getKeyValueDataStructureSize(rlength, flength, qlength, vlength, tagsLength)]; 934 935 // Write key, value and key row length. 936 int pos = 0; 937 pos = Bytes.putInt(bytes, pos, keyLength); 938 939 pos = Bytes.putInt(bytes, pos, vlength); 940 pos = Bytes.putShort(bytes, pos, (short) (rlength & 0x0000ffff)); 941 pos = Bytes.putBytes(bytes, pos, row, roffset, rlength); 942 pos = Bytes.putByte(bytes, pos, (byte) (flength & 0x0000ff)); 943 if (flength != 0) { 944 pos = Bytes.putBytes(bytes, pos, family, foffset, flength); 945 } 946 if (qlength > 0) { 947 if (qualifier instanceof ByteBuffer) { 948 pos = Bytes.putByteBuffer(bytes, pos, (ByteBuffer) qualifier); 949 } else { 950 pos = Bytes.putBytes(bytes, pos, (byte[]) qualifier, qoffset, qlength); 951 } 952 } 953 pos = Bytes.putLong(bytes, pos, timestamp); 954 pos = Bytes.putByte(bytes, pos, type.getCode()); 955 if (vlength > 0) { 956 if (value instanceof ByteBuffer) { 957 pos = Bytes.putByteBuffer(bytes, pos, (ByteBuffer) value); 958 } else { 959 pos = Bytes.putBytes(bytes, pos, (byte[]) value, voffset, vlength); 960 } 961 } 962 // Add the tags after the value part 963 if (tagsLength > 0) { 964 pos = Bytes.putAsShort(bytes, pos, tagsLength); 965 for (Tag t : tags) { 966 int tlen = t.getValueLength(); 967 pos = Bytes.putAsShort(bytes, pos, tlen + Tag.TYPE_LENGTH_SIZE); 968 pos = Bytes.putByte(bytes, pos, t.getType()); 969 Tag.copyValueTo(t, bytes, pos); 970 pos += tlen; 971 } 972 } 973 return bytes; 974 } 975 976 /** 977 * Needed doing 'contains' on List. Only compares the key portion, not the value. 978 */ 979 @Override 980 public boolean equals(Object other) { 981 if (!(other instanceof ExtendedCell)) { 982 return false; 983 } 984 return PrivateCellUtil.equals(this, (ExtendedCell) other); 985 } 986 987 /** 988 * In line with {@link #equals(Object)}, only uses the key portion, not the value. 989 */ 990 @Override 991 public int hashCode() { 992 return calculateHashForKey(this); 993 } 994 995 private int calculateHashForKey(ExtendedCell cell) { 996 // pre-calculate the 3 hashes made of byte ranges 997 int rowHash = Bytes.hashCode(cell.getRowArray(), cell.getRowOffset(), cell.getRowLength()); 998 int familyHash = 999 Bytes.hashCode(cell.getFamilyArray(), cell.getFamilyOffset(), cell.getFamilyLength()); 1000 int qualifierHash = Bytes.hashCode(cell.getQualifierArray(), cell.getQualifierOffset(), 1001 cell.getQualifierLength()); 1002 1003 // combine the 6 sub-hashes 1004 int hash = 31 * rowHash + familyHash; 1005 hash = 31 * hash + qualifierHash; 1006 hash = 31 * hash + (int) cell.getTimestamp(); 1007 hash = 31 * hash + cell.getTypeByte(); 1008 return hash; 1009 } 1010 1011 // --------------------------------------------------------------------------- 1012 // 1013 // KeyValue cloning 1014 // 1015 // --------------------------------------------------------------------------- 1016 1017 /** 1018 * Clones a KeyValue. This creates a copy, re-allocating the buffer. 1019 * @return Fully copied clone of this KeyValue 1020 * @throws CloneNotSupportedException if cloning of keyValue is not supported 1021 */ 1022 @Override 1023 public KeyValue clone() throws CloneNotSupportedException { 1024 KeyValue ret = (KeyValue) super.clone(); 1025 ret.bytes = Arrays.copyOf(this.bytes, this.bytes.length); 1026 ret.offset = 0; 1027 ret.length = ret.bytes.length; 1028 // Important to clone the memstoreTS as well - otherwise memstore's 1029 // update-in-place methods (eg increment) will end up creating 1030 // new entries 1031 ret.setSequenceId(seqId); 1032 return ret; 1033 } 1034 1035 /** 1036 * Creates a shallow copy of this KeyValue, reusing the data byte buffer. 1037 * http://en.wikipedia.org/wiki/Object_copy 1038 * @return Shallow copy of this KeyValue 1039 */ 1040 public KeyValue shallowCopy() { 1041 KeyValue shallowCopy = new KeyValue(this.bytes, this.offset, this.length); 1042 shallowCopy.setSequenceId(this.seqId); 1043 return shallowCopy; 1044 } 1045 1046 // --------------------------------------------------------------------------- 1047 // 1048 // String representation 1049 // 1050 // --------------------------------------------------------------------------- 1051 1052 @Override 1053 public String toString() { 1054 if (this.bytes == null || this.bytes.length == 0) { 1055 return "empty"; 1056 } 1057 return keyToString(this.bytes, this.offset + ROW_OFFSET, getKeyLength()) + "/vlen=" 1058 + getValueLength() + "/seqid=" + seqId; 1059 } 1060 1061 /** Return key as a String, empty string if k is null. */ 1062 public static String keyToString(final byte[] k) { 1063 if (k == null) { 1064 return ""; 1065 } 1066 return keyToString(k, 0, k.length); 1067 } 1068 1069 /** 1070 * Produces a string map for this key/value pair. Useful for programmatic use and manipulation of 1071 * the data stored in an WALKey, for example, printing as JSON. Values are left out due to their 1072 * tendency to be large. If needed, they can be added manually. 1073 * @return the Map<String,?> containing data from this key 1074 */ 1075 public Map<String, Object> toStringMap() { 1076 Map<String, Object> stringMap = new HashMap<>(); 1077 stringMap.put("row", Bytes.toStringBinary(getRowArray(), getRowOffset(), getRowLength())); 1078 stringMap.put("family", 1079 Bytes.toStringBinary(getFamilyArray(), getFamilyOffset(), getFamilyLength())); 1080 stringMap.put("qualifier", 1081 Bytes.toStringBinary(getQualifierArray(), getQualifierOffset(), getQualifierLength())); 1082 stringMap.put("timestamp", getTimestamp()); 1083 stringMap.put("vlen", getValueLength()); 1084 Iterator<Tag> tags = getTags(); 1085 if (tags != null) { 1086 List<String> tagsString = new ArrayList<String>(); 1087 while (tags.hasNext()) { 1088 tagsString.add(tags.next().toString()); 1089 } 1090 stringMap.put("tag", tagsString); 1091 } 1092 return stringMap; 1093 } 1094 1095 /** 1096 * Use for logging. 1097 * @param b Key portion of a KeyValue. 1098 * @param o Offset to start of key 1099 * @param l Length of key. 1100 * @return Key as a String. 1101 */ 1102 public static String keyToString(final byte[] b, final int o, final int l) { 1103 if (b == null) { 1104 return ""; 1105 } 1106 int rowlength = Bytes.toShort(b, o); 1107 String row = Bytes.toStringBinary(b, o + Bytes.SIZEOF_SHORT, rowlength); 1108 int columnoffset = o + Bytes.SIZEOF_SHORT + 1 + rowlength; 1109 int familylength = b[columnoffset - 1]; 1110 int columnlength = l - ((columnoffset - o) + TIMESTAMP_TYPE_SIZE); 1111 String family = familylength == 0 ? "" : Bytes.toStringBinary(b, columnoffset, familylength); 1112 String qualifier = columnlength == 0 1113 ? "" 1114 : Bytes.toStringBinary(b, columnoffset + familylength, columnlength - familylength); 1115 long timestamp = Bytes.toLong(b, o + (l - TIMESTAMP_TYPE_SIZE)); 1116 String timestampStr = humanReadableTimestamp(timestamp); 1117 byte type = b[o + l - 1]; 1118 return row + "/" + family + (family != null && family.length() > 0 ? ":" : "") + qualifier + "/" 1119 + timestampStr + "/" + Type.codeToType(type); 1120 } 1121 1122 public static String humanReadableTimestamp(final long timestamp) { 1123 if (timestamp == HConstants.LATEST_TIMESTAMP) { 1124 return "LATEST_TIMESTAMP"; 1125 } 1126 if (timestamp == PrivateConstants.OLDEST_TIMESTAMP) { 1127 return "OLDEST_TIMESTAMP"; 1128 } 1129 return String.valueOf(timestamp); 1130 } 1131 1132 // --------------------------------------------------------------------------- 1133 // 1134 // Public Member Accessors 1135 // 1136 // --------------------------------------------------------------------------- 1137 1138 /** 1139 * To be used only in tests where the Cells are clearly assumed to be of type KeyValue and that we 1140 * need access to the backing array to do some test case related assertions. 1141 * @return The byte array backing this KeyValue. 1142 */ 1143 public byte[] getBuffer() { 1144 return this.bytes; 1145 } 1146 1147 /** Returns Offset into {@link #getBuffer()} at which this KeyValue starts. */ 1148 public int getOffset() { 1149 return this.offset; 1150 } 1151 1152 /** Returns Length of bytes this KeyValue occupies in {@link #getBuffer()}. */ 1153 public int getLength() { 1154 return length; 1155 } 1156 1157 // --------------------------------------------------------------------------- 1158 // 1159 // Length and Offset Calculators 1160 // 1161 // --------------------------------------------------------------------------- 1162 1163 /** 1164 * Determines the total length of the KeyValue stored in the specified byte array and offset. 1165 * Includes all headers. 1166 * @param bytes byte array 1167 * @param offset offset to start of the KeyValue 1168 * @return length of entire KeyValue, in bytes 1169 */ 1170 private static int getLength(byte[] bytes, int offset) { 1171 int klength = ROW_OFFSET + Bytes.toInt(bytes, offset); 1172 int vlength = Bytes.toInt(bytes, offset + Bytes.SIZEOF_INT); 1173 return klength + vlength; 1174 } 1175 1176 /** Returns Key offset in backing buffer.. */ 1177 public int getKeyOffset() { 1178 return this.offset + ROW_OFFSET; 1179 } 1180 1181 public String getKeyString() { 1182 return Bytes.toStringBinary(getBuffer(), getKeyOffset(), getKeyLength()); 1183 } 1184 1185 /** Returns Length of key portion. */ 1186 public int getKeyLength() { 1187 return Bytes.toInt(this.bytes, this.offset); 1188 } 1189 1190 /** 1191 * Returns the backing array of the entire KeyValue (all KeyValue fields are in a single array) 1192 */ 1193 @Override 1194 public byte[] getValueArray() { 1195 return bytes; 1196 } 1197 1198 /** Returns the value offset */ 1199 @Override 1200 public int getValueOffset() { 1201 int voffset = getKeyOffset() + getKeyLength(); 1202 return voffset; 1203 } 1204 1205 /** Returns Value length */ 1206 @Override 1207 public int getValueLength() { 1208 int vlength = Bytes.toInt(this.bytes, this.offset + Bytes.SIZEOF_INT); 1209 return vlength; 1210 } 1211 1212 /** 1213 * Returns the backing array of the entire KeyValue (all KeyValue fields are in a single array) 1214 */ 1215 @Override 1216 public byte[] getRowArray() { 1217 return bytes; 1218 } 1219 1220 /** Returns Row offset */ 1221 @Override 1222 public int getRowOffset() { 1223 return this.offset + ROW_KEY_OFFSET; 1224 } 1225 1226 /** Returns Row length */ 1227 @Override 1228 public short getRowLength() { 1229 return Bytes.toShort(this.bytes, getKeyOffset()); 1230 } 1231 1232 /** 1233 * Returns the backing array of the entire KeyValue (all KeyValue fields are in a single array) 1234 */ 1235 @Override 1236 public byte[] getFamilyArray() { 1237 return bytes; 1238 } 1239 1240 /** Returns Family offset */ 1241 @Override 1242 public int getFamilyOffset() { 1243 return getFamilyOffset(getFamilyLengthPosition(getRowLength())); 1244 } 1245 1246 /** Returns Family offset */ 1247 int getFamilyOffset(int familyLenPosition) { 1248 return familyLenPosition + Bytes.SIZEOF_BYTE; 1249 } 1250 1251 /** Returns Family length */ 1252 @Override 1253 public byte getFamilyLength() { 1254 return getFamilyLength(getFamilyLengthPosition(getRowLength())); 1255 } 1256 1257 /** Returns Family length */ 1258 public byte getFamilyLength(int famLenPos) { 1259 return this.bytes[famLenPos]; 1260 } 1261 1262 int getFamilyLengthPosition(int rowLength) { 1263 return this.offset + KeyValue.ROW_KEY_OFFSET + rowLength; 1264 } 1265 1266 /** 1267 * Returns the backing array of the entire KeyValue (all KeyValue fields are in a single array) 1268 */ 1269 @Override 1270 public byte[] getQualifierArray() { 1271 return bytes; 1272 } 1273 1274 /** Returns Qualifier offset */ 1275 @Override 1276 public int getQualifierOffset() { 1277 return getQualifierOffset(getFamilyOffset()); 1278 } 1279 1280 /** Returns Qualifier offset */ 1281 private int getQualifierOffset(int foffset) { 1282 return getQualifierOffset(foffset, getFamilyLength()); 1283 } 1284 1285 /** Returns Qualifier offset */ 1286 int getQualifierOffset(int foffset, int flength) { 1287 return foffset + flength; 1288 } 1289 1290 /** Returns Qualifier length */ 1291 @Override 1292 public int getQualifierLength() { 1293 return getQualifierLength(getRowLength(), getFamilyLength()); 1294 } 1295 1296 /** Returns Qualifier length */ 1297 private int getQualifierLength(int rlength, int flength) { 1298 return getQualifierLength(getKeyLength(), rlength, flength); 1299 } 1300 1301 /** Returns Qualifier length */ 1302 int getQualifierLength(int keyLength, int rlength, int flength) { 1303 return keyLength - (int) getKeyDataStructureSize(rlength, flength, 0); 1304 } 1305 1306 /** Returns Timestamp offset */ 1307 public int getTimestampOffset() { 1308 return getTimestampOffset(getKeyLength()); 1309 } 1310 1311 /** Return the timestamp offset */ 1312 private int getTimestampOffset(final int keylength) { 1313 return getKeyOffset() + keylength - TIMESTAMP_TYPE_SIZE; 1314 } 1315 1316 /** Returns True if this KeyValue has a LATEST_TIMESTAMP timestamp. */ 1317 public boolean isLatestTimestamp() { 1318 return Bytes.equals(getBuffer(), getTimestampOffset(), Bytes.SIZEOF_LONG, 1319 HConstants.LATEST_TIMESTAMP_BYTES, 0, Bytes.SIZEOF_LONG); 1320 } 1321 1322 /** 1323 * Update the timestamp. 1324 * @param now Time to set into <code>this</code> IFF timestamp == 1325 * {@link HConstants#LATEST_TIMESTAMP} (else, its a noop). 1326 * @return True is we modified this. 1327 */ 1328 public boolean updateLatestStamp(final byte[] now) { 1329 if (this.isLatestTimestamp()) { 1330 int tsOffset = getTimestampOffset(); 1331 System.arraycopy(now, 0, this.bytes, tsOffset, Bytes.SIZEOF_LONG); 1332 // clear cache or else getTimestamp() possibly returns an old value 1333 return true; 1334 } 1335 return false; 1336 } 1337 1338 @Override 1339 public void setTimestamp(long ts) { 1340 Bytes.putBytes(this.bytes, this.getTimestampOffset(), Bytes.toBytes(ts), 0, Bytes.SIZEOF_LONG); 1341 } 1342 1343 @Override 1344 public void setTimestamp(byte[] ts) { 1345 Bytes.putBytes(this.bytes, this.getTimestampOffset(), ts, 0, Bytes.SIZEOF_LONG); 1346 } 1347 1348 // --------------------------------------------------------------------------- 1349 // 1350 // Methods that return copies of fields 1351 // 1352 // --------------------------------------------------------------------------- 1353 1354 /** 1355 * Do not use unless you have to. Used internally for compacting and testing. Use 1356 * {@link #getRowArray()}, {@link #getFamilyArray()}, {@link #getQualifierArray()}, and 1357 * {@link #getValueArray()} if accessing a KeyValue client-side. 1358 * @return Copy of the key portion only. 1359 */ 1360 public byte[] getKey() { 1361 int keylength = getKeyLength(); 1362 byte[] key = new byte[keylength]; 1363 System.arraycopy(getBuffer(), getKeyOffset(), key, 0, keylength); 1364 return key; 1365 } 1366 1367 /** Return the timestamp. */ 1368 @Override 1369 public long getTimestamp() { 1370 return getTimestamp(getKeyLength()); 1371 } 1372 1373 /** Return the timestamp. */ 1374 long getTimestamp(final int keylength) { 1375 int tsOffset = getTimestampOffset(keylength); 1376 return Bytes.toLong(this.bytes, tsOffset); 1377 } 1378 1379 /** Returns KeyValue.TYPE byte representation */ 1380 @Override 1381 public byte getTypeByte() { 1382 return getTypeByte(getKeyLength()); 1383 } 1384 1385 /** Return the KeyValue.TYPE byte representation */ 1386 byte getTypeByte(int keyLength) { 1387 return this.bytes[this.offset + keyLength - 1 + ROW_OFFSET]; 1388 } 1389 1390 /** Return the offset where the tag data starts. */ 1391 @Override 1392 public int getTagsOffset() { 1393 int tagsLen = getTagsLength(); 1394 if (tagsLen == 0) { 1395 return this.offset + this.length; 1396 } 1397 return this.offset + this.length - tagsLen; 1398 } 1399 1400 /** Return the total length of the tag bytes */ 1401 @Override 1402 public int getTagsLength() { 1403 int tagsLen = this.length - (getKeyLength() + getValueLength() + KEYVALUE_INFRASTRUCTURE_SIZE); 1404 if (tagsLen > 0) { 1405 // There are some Tag bytes in the byte[]. So reduce 2 bytes which is added to denote the tags 1406 // length 1407 tagsLen -= TAGS_LENGTH_SIZE; 1408 } 1409 return tagsLen; 1410 } 1411 1412 /** 1413 * Returns the backing array of the entire KeyValue (all KeyValue fields are in a single array) 1414 */ 1415 @Override 1416 public byte[] getTagsArray() { 1417 return bytes; 1418 } 1419 1420 /** 1421 * Creates a new KeyValue that only contains the key portion (the value is set to be null). TODO 1422 * only used by KeyOnlyFilter -- move there. 1423 * @param lenAsVal replace value with the actual value length (false=empty) 1424 */ 1425 public KeyValue createKeyOnly(boolean lenAsVal) { 1426 // KV format: <keylen:4><valuelen:4><key:keylen><value:valuelen> 1427 // Rebuild as: <keylen:4><0:4><key:keylen> 1428 int dataLen = lenAsVal ? Bytes.SIZEOF_INT : 0; 1429 byte[] newBuffer = new byte[getKeyLength() + ROW_OFFSET + dataLen]; 1430 System.arraycopy(this.bytes, this.offset, newBuffer, 0, 1431 Math.min(newBuffer.length, this.length)); 1432 Bytes.putInt(newBuffer, Bytes.SIZEOF_INT, dataLen); 1433 if (lenAsVal) { 1434 Bytes.putInt(newBuffer, newBuffer.length - dataLen, this.getValueLength()); 1435 } 1436 return new KeyValue(newBuffer); 1437 } 1438 1439 /** 1440 * Find index of passed delimiter walking from start of buffer forwards. 1441 * @param b the kv serialized byte[] to process 1442 * @param delimiter input delimeter to fetch index from start 1443 * @return Index of delimiter having started from start of <code>b</code> moving rightward. 1444 */ 1445 public static int getDelimiter(final byte[] b, int offset, final int length, 1446 final int delimiter) { 1447 if (b == null) { 1448 throw new IllegalArgumentException("Passed buffer is null"); 1449 } 1450 int result = -1; 1451 for (int i = offset; i < length + offset; i++) { 1452 if (b[i] == delimiter) { 1453 result = i; 1454 break; 1455 } 1456 } 1457 return result; 1458 } 1459 1460 /** 1461 * Find index of passed delimiter walking from end of buffer backwards. 1462 * @param b the kv serialized byte[] to process 1463 * @param offset the offset in the byte[] 1464 * @param length the length in the byte[] 1465 * @param delimiter input delimeter to fetch index from end 1466 * @return Index of delimiter 1467 */ 1468 public static int getDelimiterInReverse(final byte[] b, final int offset, final int length, 1469 final int delimiter) { 1470 if (b == null) { 1471 throw new IllegalArgumentException("Passed buffer is null"); 1472 } 1473 int result = -1; 1474 for (int i = (offset + length) - 1; i >= offset; i--) { 1475 if (b[i] == delimiter) { 1476 result = i; 1477 break; 1478 } 1479 } 1480 return result; 1481 } 1482 1483 /** 1484 * Create a KeyValue reading from <code>in</code> 1485 * @param in Where to read bytes from. Creates a byte array to hold the KeyValue backing bytes 1486 * copied from the steam. 1487 * @return KeyValue created by deserializing from <code>in</code> OR if we find a length of zero, 1488 * we will return null which can be useful marking a stream as done. 1489 * @throws IOException if any IO error happen 1490 */ 1491 public static KeyValue create(final DataInput in) throws IOException { 1492 return create(in.readInt(), in); 1493 } 1494 1495 /** 1496 * Create a KeyValue reading <code>length</code> from <code>in</code> 1497 * @param length length of the Key 1498 * @param in Input to read from 1499 * @return Created KeyValue OR if we find a length of zero, we will return null which can be 1500 * useful marking a stream as done. 1501 * @throws IOException if any IO error happen 1502 */ 1503 public static KeyValue create(int length, final DataInput in) throws IOException { 1504 1505 if (length <= 0) { 1506 if (length == 0) { 1507 return null; 1508 } 1509 throw new IOException("Failed read " + length + " bytes, stream corrupt?"); 1510 } 1511 1512 // This is how the old Writables.readFrom used to deserialize. Didn't even vint. 1513 byte[] bytes = new byte[length]; 1514 in.readFully(bytes); 1515 return new KeyValue(bytes, 0, length); 1516 } 1517 1518 /** 1519 * Write out a KeyValue in the manner in which we used to when KeyValue was a Writable. 1520 * @param kv the KeyValue on which write is being requested 1521 * @param out OutputStream to write keyValue to 1522 * @return Length written on stream 1523 * @throws IOException if any IO error happen 1524 * @see #create(DataInput) for the inverse function 1525 */ 1526 public static long write(final KeyValue kv, final DataOutput out) throws IOException { 1527 // This is how the old Writables write used to serialize KVs. Need to figure way to make it 1528 // work for all implementations. 1529 int length = kv.getLength(); 1530 out.writeInt(length); 1531 out.write(kv.getBuffer(), kv.getOffset(), length); 1532 return (long) length + Bytes.SIZEOF_INT; 1533 } 1534 1535 @Override 1536 public int write(OutputStream out, boolean withTags) throws IOException { 1537 int len = getSerializedSize(withTags); 1538 out.write(this.bytes, this.offset, len); 1539 return len; 1540 } 1541 1542 @Override 1543 public int getSerializedSize(boolean withTags) { 1544 if (withTags) { 1545 return this.length; 1546 } 1547 return this.getKeyLength() + this.getValueLength() + KEYVALUE_INFRASTRUCTURE_SIZE; 1548 } 1549 1550 @Override 1551 public int getSerializedSize() { 1552 return this.length; 1553 } 1554 1555 @Override 1556 public void write(ByteBuffer buf, int offset) { 1557 ByteBufferUtils.copyFromArrayToBuffer(buf, offset, this.bytes, this.offset, this.length); 1558 } 1559 1560 /** 1561 * Avoids redundant comparisons for better performance. TODO get rid of this wart 1562 */ 1563 public interface SamePrefixComparator<T> { 1564 /** 1565 * Compare two keys assuming that the first n bytes are the same. 1566 * @param commonPrefix How many bytes are the same. 1567 */ 1568 int compareIgnoringPrefix(int commonPrefix, byte[] left, int loffset, int llength, byte[] right, 1569 int roffset, int rlength); 1570 } 1571 1572 /** 1573 * HeapSize implementation 1574 * <p/> 1575 * We do not count the bytes in the rowCache because it should be empty for a KeyValue in the 1576 * MemStore. 1577 */ 1578 @Override 1579 public long heapSize() { 1580 // Deep object overhead for this KV consists of two parts. The first part is the KV object 1581 // itself, while the second part is the backing byte[]. We will only count the array overhead 1582 // from the byte[] only if this is the first KV in there. 1583 int fixed = ClassSize.align(FIXED_OVERHEAD); 1584 if (offset == 0) { 1585 // count both length and object overhead 1586 return fixed + ClassSize.sizeOfByteArray(length); 1587 } else { 1588 // only count the number of bytes 1589 return (long) fixed + length; 1590 } 1591 } 1592 1593 /** 1594 * A simple form of KeyValue that creates a keyvalue with only the key part of the byte[] Mainly 1595 * used in places where we need to compare two cells. Avoids copying of bytes In places like block 1596 * index keys, we need to compare the key byte[] with a cell. Hence create a Keyvalue(aka Cell) 1597 * that would help in comparing as two cells 1598 */ 1599 public static class KeyOnlyKeyValue extends KeyValue { 1600 private short rowLen = -1; 1601 1602 public KeyOnlyKeyValue() { 1603 1604 } 1605 1606 public KeyOnlyKeyValue(byte[] b) { 1607 this(b, 0, b.length); 1608 } 1609 1610 public KeyOnlyKeyValue(byte[] b, int offset, int length) { 1611 this.bytes = b; 1612 this.length = length; 1613 this.offset = offset; 1614 this.rowLen = Bytes.toShort(this.bytes, this.offset); 1615 } 1616 1617 public void set(KeyOnlyKeyValue keyOnlyKeyValue) { 1618 this.bytes = keyOnlyKeyValue.bytes; 1619 this.length = keyOnlyKeyValue.length; 1620 this.offset = keyOnlyKeyValue.offset; 1621 this.rowLen = keyOnlyKeyValue.rowLen; 1622 } 1623 1624 public void clear() { 1625 rowLen = -1; 1626 bytes = null; 1627 offset = 0; 1628 length = 0; 1629 } 1630 1631 @Override 1632 public int getKeyOffset() { 1633 return this.offset; 1634 } 1635 1636 /** 1637 * A setter that helps to avoid object creation every time and whenever there is a need to 1638 * create new KeyOnlyKeyValue. 1639 * @param key Key to set 1640 * @param offset Offset of the Key 1641 * @param length length of the Key 1642 */ 1643 public void setKey(byte[] key, int offset, int length) { 1644 this.bytes = key; 1645 this.offset = offset; 1646 this.length = length; 1647 this.rowLen = Bytes.toShort(this.bytes, this.offset); 1648 } 1649 1650 @Override 1651 public byte[] getKey() { 1652 int keylength = getKeyLength(); 1653 byte[] key = new byte[keylength]; 1654 System.arraycopy(this.bytes, getKeyOffset(), key, 0, keylength); 1655 return key; 1656 } 1657 1658 @Override 1659 public byte[] getRowArray() { 1660 return bytes; 1661 } 1662 1663 @Override 1664 public int getRowOffset() { 1665 return getKeyOffset() + Bytes.SIZEOF_SHORT; 1666 } 1667 1668 @Override 1669 public byte[] getFamilyArray() { 1670 return bytes; 1671 } 1672 1673 @Override 1674 public byte getFamilyLength() { 1675 return this.bytes[getFamilyOffset() - 1]; 1676 } 1677 1678 @Override 1679 int getFamilyLengthPosition(int rowLength) { 1680 return this.offset + Bytes.SIZEOF_SHORT + rowLength; 1681 } 1682 1683 @Override 1684 public int getFamilyOffset() { 1685 return this.offset + Bytes.SIZEOF_SHORT + getRowLength() + Bytes.SIZEOF_BYTE; 1686 } 1687 1688 @Override 1689 public byte[] getQualifierArray() { 1690 return bytes; 1691 } 1692 1693 @Override 1694 public int getQualifierLength() { 1695 return getQualifierLength(getRowLength(), getFamilyLength()); 1696 } 1697 1698 @Override 1699 public int getQualifierOffset() { 1700 return getFamilyOffset() + getFamilyLength(); 1701 } 1702 1703 @Override 1704 public int getKeyLength() { 1705 return length; 1706 } 1707 1708 @Override 1709 public short getRowLength() { 1710 return rowLen; 1711 } 1712 1713 @Override 1714 public byte getTypeByte() { 1715 return getTypeByte(getKeyLength()); 1716 } 1717 1718 @Override 1719 byte getTypeByte(int keyLength) { 1720 return this.bytes[this.offset + keyLength - 1]; 1721 } 1722 1723 private int getQualifierLength(int rlength, int flength) { 1724 return getKeyLength() - (int) getKeyDataStructureSize(rlength, flength, 0); 1725 } 1726 1727 @Override 1728 public long getTimestamp() { 1729 int tsOffset = getTimestampOffset(); 1730 return Bytes.toLong(this.bytes, tsOffset); 1731 } 1732 1733 @Override 1734 public int getTimestampOffset() { 1735 return getKeyOffset() + getKeyLength() - TIMESTAMP_TYPE_SIZE; 1736 } 1737 1738 @Override 1739 public byte[] getTagsArray() { 1740 return HConstants.EMPTY_BYTE_ARRAY; 1741 } 1742 1743 @Override 1744 public int getTagsOffset() { 1745 return 0; 1746 } 1747 1748 @Override 1749 public byte[] getValueArray() { 1750 throw new IllegalArgumentException("KeyOnlyKeyValue does not work with values."); 1751 } 1752 1753 @Override 1754 public int getValueOffset() { 1755 throw new IllegalArgumentException("KeyOnlyKeyValue does not work with values."); 1756 } 1757 1758 @Override 1759 public int getValueLength() { 1760 throw new IllegalArgumentException("KeyOnlyKeyValue does not work with values."); 1761 } 1762 1763 @Override 1764 public int getTagsLength() { 1765 return 0; 1766 } 1767 1768 @Override 1769 public String toString() { 1770 if (this.bytes == null || this.bytes.length == 0) { 1771 return "empty"; 1772 } 1773 return keyToString(this.bytes, this.offset, getKeyLength()) + "/vlen=0/mvcc=0"; 1774 } 1775 1776 @Override 1777 public int hashCode() { 1778 return super.hashCode(); 1779 } 1780 1781 @Override 1782 public boolean equals(Object other) { 1783 return super.equals(other); 1784 } 1785 1786 @Override 1787 public long heapSize() { 1788 return super.heapSize() + Bytes.SIZEOF_SHORT; 1789 } 1790 1791 @Override 1792 public int write(OutputStream out, boolean withTags) throws IOException { 1793 // This type of Cell is used only to maintain some internal states. We never allow this type 1794 // of Cell to be returned back over the RPC 1795 throw new IllegalStateException("A reader should never return this type of a Cell"); 1796 } 1797 } 1798 1799 @Override 1800 public ExtendedCell deepClone() { 1801 byte[] copy = Bytes.copy(this.bytes, this.offset, this.length); 1802 KeyValue kv = new KeyValue(copy, 0, copy.length); 1803 kv.setSequenceId(this.getSequenceId()); 1804 return kv; 1805 } 1806}