001/** 002 * Copyright The Apache Software Foundation 003 * 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, software 015 * distributed under the License is distributed on an "AS IS" BASIS, 016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 017 * See the License for the specific language governing permissions and 018 * limitations under the License. 019 */ 020package org.apache.hadoop.hbase; 021 022import static org.apache.hadoop.hbase.util.Bytes.len; 023 024import java.io.DataInput; 025import java.io.DataOutput; 026import java.io.IOException; 027import java.io.OutputStream; 028import java.nio.ByteBuffer; 029import java.util.ArrayList; 030import java.util.Arrays; 031import java.util.HashMap; 032import java.util.Iterator; 033import java.util.List; 034import java.util.Map; 035import org.apache.hadoop.hbase.util.ByteBufferUtils; 036import org.apache.hadoop.hbase.util.Bytes; 037import org.apache.hadoop.hbase.util.ClassSize; 038import org.apache.hadoop.io.RawComparator; 039import org.apache.yetus.audience.InterfaceAudience; 040import org.slf4j.Logger; 041import org.slf4j.LoggerFactory; 042 043import org.apache.hbase.thirdparty.com.google.common.annotations.VisibleForTesting; 044 045/** 046 * An HBase Key/Value. This is the fundamental HBase Type. 047 * <p> 048 * HBase applications and users should use the Cell interface and avoid directly using KeyValue and 049 * member functions not defined in Cell. 050 * <p> 051 * If being used client-side, the primary methods to access individual fields are 052 * {@link #getRowArray()}, {@link #getFamilyArray()}, {@link #getQualifierArray()}, 053 * {@link #getTimestamp()}, and {@link #getValueArray()}. These methods allocate new byte arrays 054 * and return copies. Avoid their use server-side. 055 * <p> 056 * Instances of this class are immutable. They do not implement Comparable but Comparators are 057 * provided. Comparators change with context, whether user table or a catalog table comparison. Its 058 * critical you use the appropriate comparator. There are Comparators for normal HFiles, Meta's 059 * Hfiles, and bloom filter keys. 060 * <p> 061 * KeyValue wraps a byte array and takes offsets and lengths into passed array at where to start 062 * interpreting the content as KeyValue. The KeyValue format inside a byte array is: 063 * <code><keylength> <valuelength> <key> <value></code> Key is further 064 * decomposed as: <code><rowlength> <row> <columnfamilylength> 065 * <columnfamily> <columnqualifier> 066 * <timestamp> <keytype></code> The <code>rowlength</code> maximum is 067 * <code>Short.MAX_SIZE</code>, column family length maximum is <code>Byte.MAX_SIZE</code>, and 068 * column qualifier + key length must be < <code>Integer.MAX_SIZE</code>. The column does not 069 * contain the family/qualifier delimiter, {@link #COLUMN_FAMILY_DELIMITER}<br> 070 * KeyValue can optionally contain Tags. When it contains tags, it is added in the byte array after 071 * the value part. The format for this part is: <code><tagslength><tagsbytes></code>. 072 * <code>tagslength</code> maximum is <code>Short.MAX_SIZE</code>. The <code>tagsbytes</code> 073 * contain one or more tags where as each tag is of the form 074 * <code><taglength><tagtype><tagbytes></code>. <code>tagtype</code> is one byte 075 * and <code>taglength</code> maximum is <code>Short.MAX_SIZE</code> and it includes 1 byte type 076 * length and actual tag bytes length. 077 */ 078@InterfaceAudience.Private 079public class KeyValue implements ExtendedCell, Cloneable { 080 private static final ArrayList<Tag> EMPTY_ARRAY_LIST = new ArrayList<>(); 081 082 private static final Logger LOG = LoggerFactory.getLogger(KeyValue.class); 083 084 public static final int FIXED_OVERHEAD = ClassSize.OBJECT + // the KeyValue object itself 085 ClassSize.REFERENCE + // pointer to "bytes" 086 2 * Bytes.SIZEOF_INT + // offset, length 087 Bytes.SIZEOF_LONG;// memstoreTS 088 089 /** 090 * Colon character in UTF-8 091 */ 092 public static final char COLUMN_FAMILY_DELIMITER = ':'; 093 094 public static final byte[] COLUMN_FAMILY_DELIM_ARRAY = 095 new byte[]{COLUMN_FAMILY_DELIMITER}; 096 097 /** 098 * Comparator for plain key/values; i.e. non-catalog table key/values. Works on Key portion 099 * of KeyValue only. 100 * @deprecated Use {@link CellComparator#getInstance()} instead. Deprecated for hbase 2.0, remove for hbase 3.0. 101 */ 102 @Deprecated 103 public static final KVComparator COMPARATOR = new KVComparator(); 104 /** 105 * A {@link KVComparator} for <code>hbase:meta</code> catalog table 106 * {@link KeyValue}s. 107 * @deprecated Use {@link CellComparatorImpl#META_COMPARATOR} instead. Deprecated for hbase 2.0, remove for hbase 3.0. 108 */ 109 @Deprecated 110 public static final KVComparator META_COMPARATOR = new MetaComparator(); 111 112 /** Size of the key length field in bytes*/ 113 public static final int KEY_LENGTH_SIZE = Bytes.SIZEOF_INT; 114 115 /** Size of the key type field in bytes */ 116 public static final int TYPE_SIZE = Bytes.SIZEOF_BYTE; 117 118 /** Size of the row length field in bytes */ 119 public static final int ROW_LENGTH_SIZE = Bytes.SIZEOF_SHORT; 120 121 /** Size of the family length field in bytes */ 122 public static final int FAMILY_LENGTH_SIZE = Bytes.SIZEOF_BYTE; 123 124 /** Size of the timestamp field in bytes */ 125 public static final int TIMESTAMP_SIZE = Bytes.SIZEOF_LONG; 126 127 // Size of the timestamp and type byte on end of a key -- a long + a byte. 128 public static final int TIMESTAMP_TYPE_SIZE = TIMESTAMP_SIZE + TYPE_SIZE; 129 130 // Size of the length shorts and bytes in key. 131 public static final int KEY_INFRASTRUCTURE_SIZE = ROW_LENGTH_SIZE 132 + FAMILY_LENGTH_SIZE + TIMESTAMP_TYPE_SIZE; 133 134 // How far into the key the row starts at. First thing to read is the short 135 // that says how long the row is. 136 public static final int ROW_OFFSET = 137 Bytes.SIZEOF_INT /*keylength*/ + 138 Bytes.SIZEOF_INT /*valuelength*/; 139 140 public static final int ROW_KEY_OFFSET = ROW_OFFSET + ROW_LENGTH_SIZE; 141 142 // Size of the length ints in a KeyValue datastructure. 143 public static final int KEYVALUE_INFRASTRUCTURE_SIZE = ROW_OFFSET; 144 145 /** Size of the tags length field in bytes */ 146 public static final int TAGS_LENGTH_SIZE = Bytes.SIZEOF_SHORT; 147 148 public static final int KEYVALUE_WITH_TAGS_INFRASTRUCTURE_SIZE = ROW_OFFSET + TAGS_LENGTH_SIZE; 149 150 /** 151 * Computes the number of bytes that a <code>KeyValue</code> instance with the provided 152 * characteristics would take up for its underlying data structure. 153 * 154 * @param rlength row length 155 * @param flength family length 156 * @param qlength qualifier length 157 * @param vlength value length 158 * 159 * @return the <code>KeyValue</code> data structure length 160 */ 161 public static long getKeyValueDataStructureSize(int rlength, 162 int flength, int qlength, int vlength) { 163 return KeyValue.KEYVALUE_INFRASTRUCTURE_SIZE 164 + getKeyDataStructureSize(rlength, flength, qlength) + vlength; 165 } 166 167 /** 168 * Computes the number of bytes that a <code>KeyValue</code> instance with the provided 169 * characteristics would take up for its underlying data structure. 170 * 171 * @param rlength row length 172 * @param flength family length 173 * @param qlength qualifier length 174 * @param vlength value length 175 * @param tagsLength total length of the tags 176 * 177 * @return the <code>KeyValue</code> data structure length 178 */ 179 public static long getKeyValueDataStructureSize(int rlength, int flength, int qlength, 180 int vlength, int tagsLength) { 181 if (tagsLength == 0) { 182 return getKeyValueDataStructureSize(rlength, flength, qlength, vlength); 183 } 184 return KeyValue.KEYVALUE_WITH_TAGS_INFRASTRUCTURE_SIZE 185 + getKeyDataStructureSize(rlength, flength, qlength) + vlength + tagsLength; 186 } 187 188 /** 189 * Computes the number of bytes that a <code>KeyValue</code> instance with the provided 190 * characteristics would take up for its underlying data structure. 191 * 192 * @param klength key length 193 * @param vlength value length 194 * @param tagsLength total length of the tags 195 * 196 * @return the <code>KeyValue</code> data structure length 197 */ 198 public static long getKeyValueDataStructureSize(int klength, int vlength, int tagsLength) { 199 if (tagsLength == 0) { 200 return (long) KeyValue.KEYVALUE_INFRASTRUCTURE_SIZE + klength + vlength; 201 } 202 return (long) KeyValue.KEYVALUE_WITH_TAGS_INFRASTRUCTURE_SIZE + klength + vlength + tagsLength; 203 } 204 205 /** 206 * Computes the number of bytes that a <code>KeyValue</code> instance with the provided 207 * characteristics would take up in its underlying data structure for the key. 208 * 209 * @param rlength row length 210 * @param flength family length 211 * @param qlength qualifier length 212 * 213 * @return the key data structure length 214 */ 215 public static long getKeyDataStructureSize(int rlength, int flength, int qlength) { 216 return (long) KeyValue.KEY_INFRASTRUCTURE_SIZE + rlength + flength + qlength; 217 } 218 219 /** 220 * Key type. 221 * Has space for other key types to be added later. Cannot rely on 222 * enum ordinals . They change if item is removed or moved. Do our own codes. 223 */ 224 public static enum Type { 225 Minimum((byte)0), 226 Put((byte)4), 227 228 Delete((byte)8), 229 DeleteFamilyVersion((byte)10), 230 DeleteColumn((byte)12), 231 DeleteFamily((byte)14), 232 233 // Maximum is used when searching; you look from maximum on down. 234 Maximum((byte)255); 235 236 private final byte code; 237 238 Type(final byte c) { 239 this.code = c; 240 } 241 242 public byte getCode() { 243 return this.code; 244 } 245 246 private static Type[] codeArray = new Type[256]; 247 248 static { 249 for (Type t : Type.values()) { 250 codeArray[t.code & 0xff] = t; 251 } 252 } 253 254 /** 255 * Cannot rely on enum ordinals . They change if item is removed or moved. 256 * Do our own codes. 257 * @param b 258 * @return Type associated with passed code. 259 */ 260 public static Type codeToType(final byte b) { 261 Type t = codeArray[b & 0xff]; 262 if (t != null) { 263 return t; 264 } 265 throw new RuntimeException("Unknown code " + b); 266 } 267 } 268 269 /** 270 * Lowest possible key. 271 * Makes a Key with highest possible Timestamp, empty row and column. No 272 * key can be equal or lower than this one in memstore or in store file. 273 */ 274 public static final KeyValue LOWESTKEY = 275 new KeyValue(HConstants.EMPTY_BYTE_ARRAY, HConstants.LATEST_TIMESTAMP); 276 277 //// 278 // KeyValue core instance fields. 279 protected byte [] bytes = null; // an immutable byte array that contains the KV 280 protected int offset = 0; // offset into bytes buffer KV starts at 281 protected int length = 0; // length of the KV starting from offset. 282 283 /** Here be dragons **/ 284 285 /** 286 * used to achieve atomic operations in the memstore. 287 */ 288 @Override 289 public long getSequenceId() { 290 return seqId; 291 } 292 293 @Override 294 public void setSequenceId(long seqId) { 295 this.seqId = seqId; 296 } 297 298 // multi-version concurrency control version. default value is 0, aka do not care. 299 private long seqId = 0; 300 301 /** Dragon time over, return to normal business */ 302 303 304 /** Writable Constructor -- DO NOT USE */ 305 public KeyValue() {} 306 307 /** 308 * Creates a KeyValue from the start of the specified byte array. 309 * Presumes <code>bytes</code> content is formatted as a KeyValue blob. 310 * @param bytes byte array 311 */ 312 public KeyValue(final byte [] bytes) { 313 this(bytes, 0); 314 } 315 316 /** 317 * Creates a KeyValue from the specified byte array and offset. 318 * Presumes <code>bytes</code> content starting at <code>offset</code> is 319 * formatted as a KeyValue blob. 320 * @param bytes byte array 321 * @param offset offset to start of KeyValue 322 */ 323 public KeyValue(final byte [] bytes, final int offset) { 324 this(bytes, offset, getLength(bytes, offset)); 325 } 326 327 /** 328 * Creates a KeyValue from the specified byte array, starting at offset, and 329 * for length <code>length</code>. 330 * @param bytes byte array 331 * @param offset offset to start of the KeyValue 332 * @param length length of the KeyValue 333 */ 334 public KeyValue(final byte [] bytes, final int offset, final int length) { 335 this.bytes = bytes; 336 this.offset = offset; 337 this.length = length; 338 } 339 340 /** 341 * Creates a KeyValue from the specified byte array, starting at offset, and 342 * for length <code>length</code>. 343 * 344 * @param bytes byte array 345 * @param offset offset to start of the KeyValue 346 * @param length length of the KeyValue 347 * @param ts 348 */ 349 public KeyValue(final byte[] bytes, final int offset, final int length, long ts) { 350 this(bytes, offset, length, null, 0, 0, null, 0, 0, ts, Type.Maximum, null, 0, 0, null); 351 } 352 353 /** Constructors that build a new backing byte array from fields */ 354 355 /** 356 * Constructs KeyValue structure filled with null value. 357 * Sets type to {@link KeyValue.Type#Maximum} 358 * @param row - row key (arbitrary byte array) 359 * @param timestamp 360 */ 361 public KeyValue(final byte [] row, final long timestamp) { 362 this(row, null, null, timestamp, Type.Maximum, null); 363 } 364 365 /** 366 * Constructs KeyValue structure filled with null value. 367 * @param row - row key (arbitrary byte array) 368 * @param timestamp 369 */ 370 public KeyValue(final byte [] row, final long timestamp, Type type) { 371 this(row, null, null, timestamp, type, null); 372 } 373 374 /** 375 * Constructs KeyValue structure filled with null value. 376 * Sets type to {@link KeyValue.Type#Maximum} 377 * @param row - row key (arbitrary byte array) 378 * @param family family name 379 * @param qualifier column qualifier 380 */ 381 public KeyValue(final byte [] row, final byte [] family, 382 final byte [] qualifier) { 383 this(row, family, qualifier, HConstants.LATEST_TIMESTAMP, Type.Maximum); 384 } 385 386 /** 387 * Constructs KeyValue structure as a put filled with specified values and 388 * LATEST_TIMESTAMP. 389 * @param row - row key (arbitrary byte array) 390 * @param family family name 391 * @param qualifier column qualifier 392 */ 393 public KeyValue(final byte [] row, final byte [] family, 394 final byte [] qualifier, final byte [] value) { 395 this(row, family, qualifier, HConstants.LATEST_TIMESTAMP, Type.Put, value); 396 } 397 398 /** 399 * Constructs KeyValue structure filled with specified values. 400 * @param row row key 401 * @param family family name 402 * @param qualifier column qualifier 403 * @param timestamp version timestamp 404 * @param type key type 405 * @throws IllegalArgumentException 406 */ 407 public KeyValue(final byte[] row, final byte[] family, 408 final byte[] qualifier, final long timestamp, Type type) { 409 this(row, family, qualifier, timestamp, type, 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 * @throws IllegalArgumentException 420 */ 421 public KeyValue(final byte[] row, final byte[] family, 422 final byte[] qualifier, final long timestamp, final byte[] value) { 423 this(row, family, qualifier, timestamp, Type.Put, value); 424 } 425 426 /** 427 * Constructs KeyValue structure filled with specified values. 428 * @param row row key 429 * @param family family name 430 * @param qualifier column qualifier 431 * @param timestamp version timestamp 432 * @param value column value 433 * @param tags tags 434 * @throws IllegalArgumentException 435 */ 436 public KeyValue(final byte[] row, final byte[] family, 437 final byte[] qualifier, final long timestamp, final byte[] value, 438 final Tag[] tags) { 439 this(row, family, qualifier, timestamp, value, tags != null ? Arrays.asList(tags) : null); 440 } 441 442 /** 443 * Constructs KeyValue structure filled with specified values. 444 * @param row row key 445 * @param family family name 446 * @param qualifier column qualifier 447 * @param timestamp version timestamp 448 * @param value column value 449 * @param tags tags non-empty list of tags or null 450 * @throws IllegalArgumentException 451 */ 452 public KeyValue(final byte[] row, final byte[] family, 453 final byte[] qualifier, final long timestamp, final byte[] value, 454 final List<Tag> tags) { 455 this(row, 0, row==null ? 0 : row.length, 456 family, 0, family==null ? 0 : family.length, 457 qualifier, 0, qualifier==null ? 0 : qualifier.length, 458 timestamp, Type.Put, 459 value, 0, value==null ? 0 : value.length, tags); 460 } 461 462 /** 463 * Constructs KeyValue structure filled with specified values. 464 * @param row row key 465 * @param family family name 466 * @param qualifier column qualifier 467 * @param timestamp version timestamp 468 * @param type key type 469 * @param value column value 470 * @throws IllegalArgumentException 471 */ 472 public KeyValue(final byte[] row, final byte[] family, 473 final byte[] qualifier, final long timestamp, Type type, 474 final byte[] value) { 475 this(row, 0, len(row), family, 0, len(family), qualifier, 0, len(qualifier), 476 timestamp, type, value, 0, len(value)); 477 } 478 479 /** 480 * Constructs KeyValue structure filled with specified values. 481 * <p> 482 * Column is split into two fields, family and qualifier. 483 * @param row row key 484 * @param family family name 485 * @param qualifier column qualifier 486 * @param timestamp version timestamp 487 * @param type key type 488 * @param value column value 489 * @throws IllegalArgumentException 490 */ 491 public KeyValue(final byte[] row, final byte[] family, 492 final byte[] qualifier, final long timestamp, Type type, 493 final byte[] value, final List<Tag> tags) { 494 this(row, family, qualifier, 0, qualifier==null ? 0 : qualifier.length, 495 timestamp, type, value, 0, value==null ? 0 : value.length, tags); 496 } 497 498 /** 499 * Constructs KeyValue structure filled with specified values. 500 * @param row row key 501 * @param family family name 502 * @param qualifier column qualifier 503 * @param timestamp version timestamp 504 * @param type key type 505 * @param value column value 506 * @throws IllegalArgumentException 507 */ 508 public KeyValue(final byte[] row, final byte[] family, 509 final byte[] qualifier, final long timestamp, Type type, 510 final byte[] value, final byte[] tags) { 511 this(row, family, qualifier, 0, qualifier==null ? 0 : qualifier.length, 512 timestamp, type, value, 0, value==null ? 0 : value.length, tags); 513 } 514 515 /** 516 * Constructs KeyValue structure filled with specified values. 517 * @param row row key 518 * @param family family name 519 * @param qualifier column qualifier 520 * @param qoffset qualifier offset 521 * @param qlength qualifier length 522 * @param timestamp version timestamp 523 * @param type key type 524 * @param value column value 525 * @param voffset value offset 526 * @param vlength value length 527 * @throws IllegalArgumentException 528 */ 529 public KeyValue(byte [] row, byte [] family, 530 byte [] qualifier, int qoffset, int qlength, long timestamp, Type type, 531 byte [] value, int voffset, int vlength, List<Tag> tags) { 532 this(row, 0, row==null ? 0 : row.length, 533 family, 0, family==null ? 0 : family.length, 534 qualifier, qoffset, qlength, timestamp, type, 535 value, voffset, vlength, tags); 536 } 537 538 /** 539 * @param row 540 * @param family 541 * @param qualifier 542 * @param qoffset 543 * @param qlength 544 * @param timestamp 545 * @param type 546 * @param value 547 * @param voffset 548 * @param vlength 549 * @param tags 550 */ 551 public KeyValue(byte [] row, byte [] family, 552 byte [] qualifier, int qoffset, int qlength, long timestamp, Type type, 553 byte [] value, int voffset, int vlength, byte[] tags) { 554 this(row, 0, row==null ? 0 : row.length, 555 family, 0, family==null ? 0 : family.length, 556 qualifier, qoffset, qlength, timestamp, type, 557 value, voffset, vlength, tags, 0, tags==null ? 0 : tags.length); 558 } 559 560 /** 561 * Constructs KeyValue structure filled with specified values. 562 * <p> 563 * Column is split into two fields, family and qualifier. 564 * @param row row key 565 * @throws IllegalArgumentException 566 */ 567 public KeyValue(final byte [] row, final int roffset, final int rlength, 568 final byte [] family, final int foffset, final int flength, 569 final byte [] qualifier, final int qoffset, final int qlength, 570 final long timestamp, final Type type, 571 final byte [] value, final int voffset, final int vlength) { 572 this(row, roffset, rlength, family, foffset, flength, qualifier, qoffset, 573 qlength, timestamp, type, value, voffset, vlength, null); 574 } 575 576 /** 577 * Constructs KeyValue structure filled with specified values. Uses the provided buffer as the 578 * data buffer. 579 * <p> 580 * Column is split into two fields, family and qualifier. 581 * 582 * @param buffer the bytes buffer to use 583 * @param boffset buffer offset 584 * @param row row key 585 * @param roffset row offset 586 * @param rlength row length 587 * @param family family name 588 * @param foffset family offset 589 * @param flength family length 590 * @param qualifier column qualifier 591 * @param qoffset qualifier offset 592 * @param qlength qualifier length 593 * @param timestamp version timestamp 594 * @param type key type 595 * @param value column value 596 * @param voffset value offset 597 * @param vlength value length 598 * @param tags non-empty list of tags or null 599 * @throws IllegalArgumentException an illegal value was passed or there is insufficient space 600 * remaining in the buffer 601 */ 602 public KeyValue(byte [] buffer, final int boffset, 603 final byte [] row, final int roffset, final int rlength, 604 final byte [] family, final int foffset, final int flength, 605 final byte [] qualifier, final int qoffset, final int qlength, 606 final long timestamp, final Type type, 607 final byte [] value, final int voffset, final int vlength, 608 final Tag[] tags) { 609 this.bytes = buffer; 610 this.length = writeByteArray(buffer, boffset, 611 row, roffset, rlength, 612 family, foffset, flength, qualifier, qoffset, qlength, 613 timestamp, type, value, voffset, vlength, tags); 614 this.offset = boffset; 615 } 616 617 /** 618 * Constructs KeyValue structure filled with specified values. 619 * <p> 620 * Column is split into two fields, family and qualifier. 621 * @param row row key 622 * @param roffset row offset 623 * @param rlength row length 624 * @param family family name 625 * @param foffset family offset 626 * @param flength family length 627 * @param qualifier column qualifier 628 * @param qoffset qualifier offset 629 * @param qlength qualifier length 630 * @param timestamp version timestamp 631 * @param type key type 632 * @param value column value 633 * @param voffset value offset 634 * @param vlength value length 635 * @param tags tags 636 * @throws IllegalArgumentException 637 */ 638 public KeyValue(final byte [] row, final int roffset, final int rlength, 639 final byte [] family, final int foffset, final int flength, 640 final byte [] qualifier, final int qoffset, final int qlength, 641 final long timestamp, final Type type, 642 final byte [] value, final int voffset, final int vlength, 643 final List<Tag> tags) { 644 this.bytes = createByteArray(row, roffset, rlength, 645 family, foffset, flength, qualifier, qoffset, qlength, 646 timestamp, type, value, voffset, vlength, tags); 647 this.length = bytes.length; 648 this.offset = 0; 649 } 650 651 /** 652 * @param row 653 * @param roffset 654 * @param rlength 655 * @param family 656 * @param foffset 657 * @param flength 658 * @param qualifier 659 * @param qoffset 660 * @param qlength 661 * @param timestamp 662 * @param type 663 * @param value 664 * @param voffset 665 * @param vlength 666 * @param tags 667 */ 668 public KeyValue(final byte [] row, final int roffset, final int rlength, 669 final byte [] family, final int foffset, final int flength, 670 final byte [] qualifier, final int qoffset, final int qlength, 671 final long timestamp, final Type type, 672 final byte [] value, final int voffset, final int vlength, 673 final byte[] tags, final int tagsOffset, final int tagsLength) { 674 this.bytes = createByteArray(row, roffset, rlength, 675 family, foffset, flength, qualifier, qoffset, qlength, 676 timestamp, type, value, voffset, vlength, tags, tagsOffset, tagsLength); 677 this.length = bytes.length; 678 this.offset = 0; 679 } 680 681 /** 682 * Constructs an empty KeyValue structure, with specified sizes. 683 * This can be used to partially fill up KeyValues. 684 * <p> 685 * Column is split into two fields, family and qualifier. 686 * @param rlength row length 687 * @param flength family length 688 * @param qlength qualifier length 689 * @param timestamp version timestamp 690 * @param type key type 691 * @param vlength value length 692 * @throws IllegalArgumentException 693 */ 694 public KeyValue(final int rlength, 695 final int flength, 696 final int qlength, 697 final long timestamp, final Type type, 698 final int vlength) { 699 this(rlength, flength, qlength, timestamp, type, vlength, 0); 700 } 701 702 /** 703 * Constructs an empty KeyValue structure, with specified sizes. 704 * This can be used to partially fill up KeyValues. 705 * <p> 706 * Column is split into two fields, family and qualifier. 707 * @param rlength row length 708 * @param flength family length 709 * @param qlength qualifier length 710 * @param timestamp version timestamp 711 * @param type key type 712 * @param vlength value length 713 * @param tagsLength 714 * @throws IllegalArgumentException 715 */ 716 public KeyValue(final int rlength, 717 final int flength, 718 final int qlength, 719 final long timestamp, final Type type, 720 final int vlength, final int tagsLength) { 721 this.bytes = createEmptyByteArray(rlength, flength, qlength, timestamp, type, vlength, 722 tagsLength); 723 this.length = bytes.length; 724 this.offset = 0; 725 } 726 727 728 public KeyValue(byte[] row, int roffset, int rlength, 729 byte[] family, int foffset, int flength, 730 ByteBuffer qualifier, long ts, Type type, ByteBuffer value, List<Tag> tags) { 731 this.bytes = createByteArray(row, roffset, rlength, family, foffset, flength, 732 qualifier, 0, qualifier == null ? 0 : qualifier.remaining(), ts, type, 733 value, 0, value == null ? 0 : value.remaining(), tags); 734 this.length = bytes.length; 735 this.offset = 0; 736 } 737 738 public KeyValue(Cell c) { 739 this(c.getRowArray(), c.getRowOffset(), c.getRowLength(), 740 c.getFamilyArray(), c.getFamilyOffset(), c.getFamilyLength(), 741 c.getQualifierArray(), c.getQualifierOffset(), c.getQualifierLength(), 742 c.getTimestamp(), Type.codeToType(c.getTypeByte()), c.getValueArray(), c.getValueOffset(), 743 c.getValueLength(), c.getTagsArray(), c.getTagsOffset(), c.getTagsLength()); 744 this.seqId = c.getSequenceId(); 745 } 746 747 /** 748 * Create an empty byte[] representing a KeyValue 749 * All lengths are preset and can be filled in later. 750 * @param rlength 751 * @param flength 752 * @param qlength 753 * @param timestamp 754 * @param type 755 * @param vlength 756 * @return The newly created byte array. 757 */ 758 private static byte[] createEmptyByteArray(final int rlength, int flength, 759 int qlength, final long timestamp, final Type type, int vlength, int tagsLength) { 760 if (rlength > Short.MAX_VALUE) { 761 throw new IllegalArgumentException("Row > " + Short.MAX_VALUE); 762 } 763 if (flength > Byte.MAX_VALUE) { 764 throw new IllegalArgumentException("Family > " + Byte.MAX_VALUE); 765 } 766 // Qualifier length 767 if (qlength > Integer.MAX_VALUE - rlength - flength) { 768 throw new IllegalArgumentException("Qualifier > " + Integer.MAX_VALUE); 769 } 770 RawCell.checkForTagsLength(tagsLength); 771 // Key length 772 long longkeylength = getKeyDataStructureSize(rlength, flength, qlength); 773 if (longkeylength > Integer.MAX_VALUE) { 774 throw new IllegalArgumentException("keylength " + longkeylength + " > " + 775 Integer.MAX_VALUE); 776 } 777 int keylength = (int)longkeylength; 778 // Value length 779 if (vlength > HConstants.MAXIMUM_VALUE_LENGTH) { // FindBugs INT_VACUOUS_COMPARISON 780 throw new IllegalArgumentException("Valuer > " + 781 HConstants.MAXIMUM_VALUE_LENGTH); 782 } 783 784 // Allocate right-sized byte array. 785 byte[] bytes= new byte[(int) getKeyValueDataStructureSize(rlength, flength, qlength, vlength, 786 tagsLength)]; 787 // Write the correct size markers 788 int pos = 0; 789 pos = Bytes.putInt(bytes, pos, keylength); 790 pos = Bytes.putInt(bytes, pos, vlength); 791 pos = Bytes.putShort(bytes, pos, (short)(rlength & 0x0000ffff)); 792 pos += rlength; 793 pos = Bytes.putByte(bytes, pos, (byte)(flength & 0x0000ff)); 794 pos += flength + qlength; 795 pos = Bytes.putLong(bytes, pos, timestamp); 796 pos = Bytes.putByte(bytes, pos, type.getCode()); 797 pos += vlength; 798 if (tagsLength > 0) { 799 pos = Bytes.putAsShort(bytes, pos, tagsLength); 800 } 801 return bytes; 802 } 803 804 /** 805 * Checks the parameters passed to a constructor. 806 * 807 * @param row row key 808 * @param rlength row length 809 * @param family family name 810 * @param flength family length 811 * @param qlength qualifier length 812 * @param vlength value length 813 * 814 * @throws IllegalArgumentException an illegal value was passed 815 */ 816 static void checkParameters(final byte [] row, final int rlength, 817 final byte [] family, int flength, int qlength, int vlength) 818 throws IllegalArgumentException { 819 if (rlength > Short.MAX_VALUE) { 820 throw new IllegalArgumentException("Row > " + Short.MAX_VALUE); 821 } 822 if (row == null) { 823 throw new IllegalArgumentException("Row is null"); 824 } 825 // Family length 826 flength = family == null ? 0 : flength; 827 if (flength > Byte.MAX_VALUE) { 828 throw new IllegalArgumentException("Family > " + Byte.MAX_VALUE); 829 } 830 // Qualifier length 831 if (qlength > Integer.MAX_VALUE - rlength - flength) { 832 throw new IllegalArgumentException("Qualifier > " + Integer.MAX_VALUE); 833 } 834 // Key length 835 long longKeyLength = getKeyDataStructureSize(rlength, flength, qlength); 836 if (longKeyLength > Integer.MAX_VALUE) { 837 throw new IllegalArgumentException("keylength " + longKeyLength + " > " + 838 Integer.MAX_VALUE); 839 } 840 // Value length 841 if (vlength > HConstants.MAXIMUM_VALUE_LENGTH) { // FindBugs INT_VACUOUS_COMPARISON 842 throw new IllegalArgumentException("Value length " + vlength + " > " + 843 HConstants.MAXIMUM_VALUE_LENGTH); 844 } 845 } 846 847 /** 848 * Write KeyValue format into the provided byte array. 849 * 850 * @param buffer the bytes buffer to use 851 * @param boffset buffer offset 852 * @param row row key 853 * @param roffset row offset 854 * @param rlength row length 855 * @param family family name 856 * @param foffset family offset 857 * @param flength family length 858 * @param qualifier column qualifier 859 * @param qoffset qualifier offset 860 * @param qlength qualifier length 861 * @param timestamp version timestamp 862 * @param type key type 863 * @param value column value 864 * @param voffset value offset 865 * @param vlength value length 866 * 867 * @return The number of useful bytes in the buffer. 868 * 869 * @throws IllegalArgumentException an illegal value was passed or there is insufficient space 870 * remaining in the buffer 871 */ 872 public static int writeByteArray(byte [] buffer, final int boffset, 873 final byte [] row, final int roffset, final int rlength, 874 final byte [] family, final int foffset, int flength, 875 final byte [] qualifier, final int qoffset, int qlength, 876 final long timestamp, final Type type, 877 final byte [] value, final int voffset, int vlength, Tag[] tags) { 878 879 checkParameters(row, rlength, family, flength, qlength, vlength); 880 881 // Calculate length of tags area 882 int tagsLength = 0; 883 if (tags != null && tags.length > 0) { 884 for (Tag t: tags) { 885 tagsLength += t.getValueLength() + Tag.INFRASTRUCTURE_SIZE; 886 } 887 } 888 RawCell.checkForTagsLength(tagsLength); 889 int keyLength = (int) getKeyDataStructureSize(rlength, flength, qlength); 890 int keyValueLength = (int) getKeyValueDataStructureSize(rlength, flength, qlength, vlength, 891 tagsLength); 892 if (keyValueLength > buffer.length - boffset) { 893 throw new IllegalArgumentException("Buffer size " + (buffer.length - boffset) + " < " + 894 keyValueLength); 895 } 896 897 // Write key, value and key row length. 898 int pos = boffset; 899 pos = Bytes.putInt(buffer, pos, keyLength); 900 pos = Bytes.putInt(buffer, pos, vlength); 901 pos = Bytes.putShort(buffer, pos, (short)(rlength & 0x0000ffff)); 902 pos = Bytes.putBytes(buffer, pos, row, roffset, rlength); 903 pos = Bytes.putByte(buffer, pos, (byte) (flength & 0x0000ff)); 904 if (flength != 0) { 905 pos = Bytes.putBytes(buffer, pos, family, foffset, flength); 906 } 907 if (qlength != 0) { 908 pos = Bytes.putBytes(buffer, pos, qualifier, qoffset, qlength); 909 } 910 pos = Bytes.putLong(buffer, pos, timestamp); 911 pos = Bytes.putByte(buffer, pos, type.getCode()); 912 if (value != null && value.length > 0) { 913 pos = Bytes.putBytes(buffer, pos, value, voffset, vlength); 914 } 915 // Write the number of tags. If it is 0 then it means there are no tags. 916 if (tagsLength > 0) { 917 pos = Bytes.putAsShort(buffer, pos, tagsLength); 918 for (Tag t : tags) { 919 int tlen = t.getValueLength(); 920 pos = Bytes.putAsShort(buffer, pos, tlen + Tag.TYPE_LENGTH_SIZE); 921 pos = Bytes.putByte(buffer, pos, t.getType()); 922 Tag.copyValueTo(t, buffer, pos); 923 pos += tlen; 924 } 925 } 926 return keyValueLength; 927 } 928 929 /** 930 * Write KeyValue format into a byte array. 931 * @param row row key 932 * @param roffset row offset 933 * @param rlength row length 934 * @param family family name 935 * @param foffset family offset 936 * @param flength family length 937 * @param qualifier column qualifier 938 * @param qoffset qualifier offset 939 * @param qlength qualifier length 940 * @param timestamp version timestamp 941 * @param type key type 942 * @param value column value 943 * @param voffset value offset 944 * @param vlength value length 945 * @return The newly created byte array. 946 */ 947 private static byte [] createByteArray(final byte [] row, final int roffset, 948 final int rlength, final byte [] family, final int foffset, int flength, 949 final byte [] qualifier, final int qoffset, int qlength, 950 final long timestamp, final Type type, 951 final byte [] value, final int voffset, 952 int vlength, byte[] tags, int tagsOffset, int tagsLength) { 953 954 checkParameters(row, rlength, family, flength, qlength, vlength); 955 RawCell.checkForTagsLength(tagsLength); 956 // Allocate right-sized byte array. 957 int keyLength = (int) getKeyDataStructureSize(rlength, flength, qlength); 958 byte[] bytes = new byte[(int) getKeyValueDataStructureSize(rlength, flength, qlength, vlength, 959 tagsLength)]; 960 // Write key, value and key row length. 961 int pos = 0; 962 pos = Bytes.putInt(bytes, pos, keyLength); 963 pos = Bytes.putInt(bytes, pos, vlength); 964 pos = Bytes.putShort(bytes, pos, (short)(rlength & 0x0000ffff)); 965 pos = Bytes.putBytes(bytes, pos, row, roffset, rlength); 966 pos = Bytes.putByte(bytes, pos, (byte)(flength & 0x0000ff)); 967 if(flength != 0) { 968 pos = Bytes.putBytes(bytes, pos, family, foffset, flength); 969 } 970 if(qlength != 0) { 971 pos = Bytes.putBytes(bytes, pos, qualifier, qoffset, qlength); 972 } 973 pos = Bytes.putLong(bytes, pos, timestamp); 974 pos = Bytes.putByte(bytes, pos, type.getCode()); 975 if (value != null && value.length > 0) { 976 pos = Bytes.putBytes(bytes, pos, value, voffset, vlength); 977 } 978 // Add the tags after the value part 979 if (tagsLength > 0) { 980 pos = Bytes.putAsShort(bytes, pos, tagsLength); 981 pos = Bytes.putBytes(bytes, pos, tags, tagsOffset, tagsLength); 982 } 983 return bytes; 984 } 985 986 /** 987 * @param qualifier can be a ByteBuffer or a byte[], or null. 988 * @param value can be a ByteBuffer or a byte[], or null. 989 */ 990 private static byte [] createByteArray(final byte [] row, final int roffset, 991 final int rlength, final byte [] family, final int foffset, int flength, 992 final Object qualifier, final int qoffset, int qlength, 993 final long timestamp, final Type type, 994 final Object value, final int voffset, int vlength, List<Tag> tags) { 995 996 checkParameters(row, rlength, family, flength, qlength, vlength); 997 998 // Calculate length of tags area 999 int tagsLength = 0; 1000 if (tags != null && !tags.isEmpty()) { 1001 for (Tag t : tags) { 1002 tagsLength += t.getValueLength() + Tag.INFRASTRUCTURE_SIZE; 1003 } 1004 } 1005 RawCell.checkForTagsLength(tagsLength); 1006 // Allocate right-sized byte array. 1007 int keyLength = (int) getKeyDataStructureSize(rlength, flength, qlength); 1008 byte[] bytes = new byte[(int) getKeyValueDataStructureSize(rlength, flength, qlength, vlength, 1009 tagsLength)]; 1010 1011 // Write key, value and key row length. 1012 int pos = 0; 1013 pos = Bytes.putInt(bytes, pos, keyLength); 1014 1015 pos = Bytes.putInt(bytes, pos, vlength); 1016 pos = Bytes.putShort(bytes, pos, (short)(rlength & 0x0000ffff)); 1017 pos = Bytes.putBytes(bytes, pos, row, roffset, rlength); 1018 pos = Bytes.putByte(bytes, pos, (byte)(flength & 0x0000ff)); 1019 if(flength != 0) { 1020 pos = Bytes.putBytes(bytes, pos, family, foffset, flength); 1021 } 1022 if (qlength > 0) { 1023 if (qualifier instanceof ByteBuffer) { 1024 pos = Bytes.putByteBuffer(bytes, pos, (ByteBuffer) qualifier); 1025 } else { 1026 pos = Bytes.putBytes(bytes, pos, (byte[]) qualifier, qoffset, qlength); 1027 } 1028 } 1029 pos = Bytes.putLong(bytes, pos, timestamp); 1030 pos = Bytes.putByte(bytes, pos, type.getCode()); 1031 if (vlength > 0) { 1032 if (value instanceof ByteBuffer) { 1033 pos = Bytes.putByteBuffer(bytes, pos, (ByteBuffer) value); 1034 } else { 1035 pos = Bytes.putBytes(bytes, pos, (byte[]) value, voffset, vlength); 1036 } 1037 } 1038 // Add the tags after the value part 1039 if (tagsLength > 0) { 1040 pos = Bytes.putAsShort(bytes, pos, tagsLength); 1041 for (Tag t : tags) { 1042 int tlen = t.getValueLength(); 1043 pos = Bytes.putAsShort(bytes, pos, tlen + Tag.TYPE_LENGTH_SIZE); 1044 pos = Bytes.putByte(bytes, pos, t.getType()); 1045 Tag.copyValueTo(t, bytes, pos); 1046 pos += tlen; 1047 } 1048 } 1049 return bytes; 1050 } 1051 1052 /** 1053 * Needed doing 'contains' on List. Only compares the key portion, not the value. 1054 */ 1055 @Override 1056 public boolean equals(Object other) { 1057 if (!(other instanceof Cell)) { 1058 return false; 1059 } 1060 return CellUtil.equals(this, (Cell)other); 1061 } 1062 1063 /** 1064 * In line with {@link #equals(Object)}, only uses the key portion, not the value. 1065 */ 1066 @Override 1067 public int hashCode() { 1068 return calculateHashForKey(this); 1069 } 1070 1071 private int calculateHashForKey(Cell cell) { 1072 // pre-calculate the 3 hashes made of byte ranges 1073 int rowHash = Bytes.hashCode(cell.getRowArray(), cell.getRowOffset(), cell.getRowLength()); 1074 int familyHash = Bytes.hashCode(cell.getFamilyArray(), cell.getFamilyOffset(), 1075 cell.getFamilyLength()); 1076 int qualifierHash = Bytes.hashCode(cell.getQualifierArray(), cell.getQualifierOffset(), 1077 cell.getQualifierLength()); 1078 1079 // combine the 6 sub-hashes 1080 int hash = 31 * rowHash + familyHash; 1081 hash = 31 * hash + qualifierHash; 1082 hash = 31 * hash + (int) cell.getTimestamp(); 1083 hash = 31 * hash + cell.getTypeByte(); 1084 return hash; 1085 } 1086 1087 //--------------------------------------------------------------------------- 1088 // 1089 // KeyValue cloning 1090 // 1091 //--------------------------------------------------------------------------- 1092 1093 /** 1094 * Clones a KeyValue. This creates a copy, re-allocating the buffer. 1095 * @return Fully copied clone of this KeyValue 1096 * @throws CloneNotSupportedException 1097 */ 1098 @Override 1099 public KeyValue clone() throws CloneNotSupportedException { 1100 super.clone(); 1101 byte [] b = new byte[this.length]; 1102 System.arraycopy(this.bytes, this.offset, b, 0, this.length); 1103 KeyValue ret = new KeyValue(b, 0, b.length); 1104 // Important to clone the memstoreTS as well - otherwise memstore's 1105 // update-in-place methods (eg increment) will end up creating 1106 // new entries 1107 ret.setSequenceId(seqId); 1108 return ret; 1109 } 1110 1111 /** 1112 * Creates a shallow copy of this KeyValue, reusing the data byte buffer. 1113 * http://en.wikipedia.org/wiki/Object_copy 1114 * @return Shallow copy of this KeyValue 1115 */ 1116 public KeyValue shallowCopy() { 1117 KeyValue shallowCopy = new KeyValue(this.bytes, this.offset, this.length); 1118 shallowCopy.setSequenceId(this.seqId); 1119 return shallowCopy; 1120 } 1121 1122 //--------------------------------------------------------------------------- 1123 // 1124 // String representation 1125 // 1126 //--------------------------------------------------------------------------- 1127 1128 @Override 1129 public String toString() { 1130 if (this.bytes == null || this.bytes.length == 0) { 1131 return "empty"; 1132 } 1133 return keyToString(this.bytes, this.offset + ROW_OFFSET, getKeyLength()) + "/vlen=" 1134 + getValueLength() + "/seqid=" + seqId; 1135 } 1136 1137 /** 1138 * @param k Key portion of a KeyValue. 1139 * @return Key as a String, empty string if k is null. 1140 */ 1141 public static String keyToString(final byte [] k) { 1142 if (k == null) { 1143 return ""; 1144 } 1145 return keyToString(k, 0, k.length); 1146 } 1147 1148 /** 1149 * Produces a string map for this key/value pair. Useful for programmatic use 1150 * and manipulation of the data stored in an WALKey, for example, printing 1151 * as JSON. Values are left out due to their tendency to be large. If needed, 1152 * they can be added manually. 1153 * 1154 * @return the Map<String,?> containing data from this key 1155 */ 1156 public Map<String, Object> toStringMap() { 1157 Map<String, Object> stringMap = new HashMap<>(); 1158 stringMap.put("row", Bytes.toStringBinary(getRowArray(), getRowOffset(), getRowLength())); 1159 stringMap.put("family", 1160 Bytes.toStringBinary(getFamilyArray(), getFamilyOffset(), getFamilyLength())); 1161 stringMap.put("qualifier", 1162 Bytes.toStringBinary(getQualifierArray(), getQualifierOffset(), getQualifierLength())); 1163 stringMap.put("timestamp", getTimestamp()); 1164 stringMap.put("vlen", getValueLength()); 1165 Iterator<Tag> tags = getTags(); 1166 if (tags != null) { 1167 List<String> tagsString = new ArrayList<String>(); 1168 while (tags.hasNext()) { 1169 tagsString.add(tags.next().toString()); 1170 } 1171 stringMap.put("tag", tagsString); 1172 } 1173 return stringMap; 1174 } 1175 1176 /** 1177 * Use for logging. 1178 * @param b Key portion of a KeyValue. 1179 * @param o Offset to start of key 1180 * @param l Length of key. 1181 * @return Key as a String. 1182 */ 1183 public static String keyToString(final byte [] b, final int o, final int l) { 1184 if (b == null) return ""; 1185 int rowlength = Bytes.toShort(b, o); 1186 String row = Bytes.toStringBinary(b, o + Bytes.SIZEOF_SHORT, rowlength); 1187 int columnoffset = o + Bytes.SIZEOF_SHORT + 1 + rowlength; 1188 int familylength = b[columnoffset - 1]; 1189 int columnlength = l - ((columnoffset - o) + TIMESTAMP_TYPE_SIZE); 1190 String family = familylength == 0? "": 1191 Bytes.toStringBinary(b, columnoffset, familylength); 1192 String qualifier = columnlength == 0? "": 1193 Bytes.toStringBinary(b, columnoffset + familylength, 1194 columnlength - familylength); 1195 long timestamp = Bytes.toLong(b, o + (l - TIMESTAMP_TYPE_SIZE)); 1196 String timestampStr = humanReadableTimestamp(timestamp); 1197 byte type = b[o + l - 1]; 1198 return row + "/" + family + 1199 (family != null && family.length() > 0? ":" :"") + 1200 qualifier + "/" + timestampStr + "/" + Type.codeToType(type); 1201 } 1202 1203 public static String humanReadableTimestamp(final long timestamp) { 1204 if (timestamp == HConstants.LATEST_TIMESTAMP) { 1205 return "LATEST_TIMESTAMP"; 1206 } 1207 if (timestamp == HConstants.OLDEST_TIMESTAMP) { 1208 return "OLDEST_TIMESTAMP"; 1209 } 1210 return String.valueOf(timestamp); 1211 } 1212 1213 //--------------------------------------------------------------------------- 1214 // 1215 // Public Member Accessors 1216 // 1217 //--------------------------------------------------------------------------- 1218 1219 /** 1220 * To be used only in tests where the Cells are clearly assumed to be of type KeyValue 1221 * and that we need access to the backing array to do some test case related assertions. 1222 * @return The byte array backing this KeyValue. 1223 */ 1224 @VisibleForTesting 1225 public byte [] getBuffer() { 1226 return this.bytes; 1227 } 1228 1229 /** 1230 * @return Offset into {@link #getBuffer()} at which this KeyValue starts. 1231 */ 1232 public int getOffset() { 1233 return this.offset; 1234 } 1235 1236 /** 1237 * @return Length of bytes this KeyValue occupies in {@link #getBuffer()}. 1238 */ 1239 public int getLength() { 1240 return length; 1241 } 1242 1243 //--------------------------------------------------------------------------- 1244 // 1245 // Length and Offset Calculators 1246 // 1247 //--------------------------------------------------------------------------- 1248 1249 /** 1250 * Determines the total length of the KeyValue stored in the specified 1251 * byte array and offset. Includes all headers. 1252 * @param bytes byte array 1253 * @param offset offset to start of the KeyValue 1254 * @return length of entire KeyValue, in bytes 1255 */ 1256 private static int getLength(byte [] bytes, int offset) { 1257 int klength = ROW_OFFSET + Bytes.toInt(bytes, offset); 1258 int vlength = Bytes.toInt(bytes, offset + Bytes.SIZEOF_INT); 1259 return klength + vlength; 1260 } 1261 1262 /** 1263 * @return Key offset in backing buffer.. 1264 */ 1265 public int getKeyOffset() { 1266 return this.offset + ROW_OFFSET; 1267 } 1268 1269 public String getKeyString() { 1270 return Bytes.toStringBinary(getBuffer(), getKeyOffset(), getKeyLength()); 1271 } 1272 1273 /** 1274 * @return Length of key portion. 1275 */ 1276 public int getKeyLength() { 1277 return Bytes.toInt(this.bytes, this.offset); 1278 } 1279 1280 /** 1281 * @return the backing array of the entire KeyValue (all KeyValue fields are in a single array) 1282 */ 1283 @Override 1284 public byte[] getValueArray() { 1285 return bytes; 1286 } 1287 1288 /** 1289 * @return the value offset 1290 */ 1291 @Override 1292 public int getValueOffset() { 1293 int voffset = getKeyOffset() + getKeyLength(); 1294 return voffset; 1295 } 1296 1297 /** 1298 * @return Value length 1299 */ 1300 @Override 1301 public int getValueLength() { 1302 int vlength = Bytes.toInt(this.bytes, this.offset + Bytes.SIZEOF_INT); 1303 return vlength; 1304 } 1305 1306 /** 1307 * @return the backing array of the entire KeyValue (all KeyValue fields are in a single array) 1308 */ 1309 @Override 1310 public byte[] getRowArray() { 1311 return bytes; 1312 } 1313 1314 /** 1315 * @return Row offset 1316 */ 1317 @Override 1318 public int getRowOffset() { 1319 return this.offset + ROW_KEY_OFFSET; 1320 } 1321 1322 /** 1323 * @return Row length 1324 */ 1325 @Override 1326 public short getRowLength() { 1327 return Bytes.toShort(this.bytes, getKeyOffset()); 1328 } 1329 1330 /** 1331 * @return the backing array of the entire KeyValue (all KeyValue fields are in a single array) 1332 */ 1333 @Override 1334 public byte[] getFamilyArray() { 1335 return bytes; 1336 } 1337 1338 /** 1339 * @return Family offset 1340 */ 1341 @Override 1342 public int getFamilyOffset() { 1343 return getFamilyOffset(getRowLength()); 1344 } 1345 1346 /** 1347 * @return Family offset 1348 */ 1349 private int getFamilyOffset(int rlength) { 1350 return this.offset + ROW_KEY_OFFSET + rlength + Bytes.SIZEOF_BYTE; 1351 } 1352 1353 /** 1354 * @return Family length 1355 */ 1356 @Override 1357 public byte getFamilyLength() { 1358 return getFamilyLength(getFamilyOffset()); 1359 } 1360 1361 /** 1362 * @return Family length 1363 */ 1364 public byte getFamilyLength(int foffset) { 1365 return this.bytes[foffset-1]; 1366 } 1367 1368 /** 1369 * @return the backing array of the entire KeyValue (all KeyValue fields are in a single array) 1370 */ 1371 @Override 1372 public byte[] getQualifierArray() { 1373 return bytes; 1374 } 1375 1376 /** 1377 * @return Qualifier offset 1378 */ 1379 @Override 1380 public int getQualifierOffset() { 1381 return getQualifierOffset(getFamilyOffset()); 1382 } 1383 1384 /** 1385 * @return Qualifier offset 1386 */ 1387 private int getQualifierOffset(int foffset) { 1388 return foffset + getFamilyLength(foffset); 1389 } 1390 1391 /** 1392 * @return Qualifier length 1393 */ 1394 @Override 1395 public int getQualifierLength() { 1396 return getQualifierLength(getRowLength(),getFamilyLength()); 1397 } 1398 1399 /** 1400 * @return Qualifier length 1401 */ 1402 private int getQualifierLength(int rlength, int flength) { 1403 return getKeyLength() - (int) getKeyDataStructureSize(rlength, flength, 0); 1404 } 1405 1406 /** 1407 * @return Timestamp offset 1408 */ 1409 public int getTimestampOffset() { 1410 return getTimestampOffset(getKeyLength()); 1411 } 1412 1413 /** 1414 * @param keylength Pass if you have it to save on a int creation. 1415 * @return Timestamp offset 1416 */ 1417 private int getTimestampOffset(final int keylength) { 1418 return getKeyOffset() + keylength - TIMESTAMP_TYPE_SIZE; 1419 } 1420 1421 /** 1422 * @return True if this KeyValue has a LATEST_TIMESTAMP timestamp. 1423 */ 1424 public boolean isLatestTimestamp() { 1425 return Bytes.equals(getBuffer(), getTimestampOffset(), Bytes.SIZEOF_LONG, 1426 HConstants.LATEST_TIMESTAMP_BYTES, 0, Bytes.SIZEOF_LONG); 1427 } 1428 1429 /** 1430 * @param now Time to set into <code>this</code> IFF timestamp == 1431 * {@link HConstants#LATEST_TIMESTAMP} (else, its a noop). 1432 * @return True is we modified this. 1433 */ 1434 public boolean updateLatestStamp(final byte [] now) { 1435 if (this.isLatestTimestamp()) { 1436 int tsOffset = getTimestampOffset(); 1437 System.arraycopy(now, 0, this.bytes, tsOffset, Bytes.SIZEOF_LONG); 1438 // clear cache or else getTimestamp() possibly returns an old value 1439 return true; 1440 } 1441 return false; 1442 } 1443 1444 @Override 1445 public void setTimestamp(long ts) { 1446 Bytes.putBytes(this.bytes, this.getTimestampOffset(), Bytes.toBytes(ts), 0, Bytes.SIZEOF_LONG); 1447 } 1448 1449 @Override 1450 public void setTimestamp(byte[] ts) { 1451 Bytes.putBytes(this.bytes, this.getTimestampOffset(), ts, 0, Bytes.SIZEOF_LONG); 1452 } 1453 1454 //--------------------------------------------------------------------------- 1455 // 1456 // Methods that return copies of fields 1457 // 1458 //--------------------------------------------------------------------------- 1459 1460 /** 1461 * Do not use unless you have to. Used internally for compacting and testing. Use 1462 * {@link #getRowArray()}, {@link #getFamilyArray()}, {@link #getQualifierArray()}, and 1463 * {@link #getValueArray()} if accessing a KeyValue client-side. 1464 * @return Copy of the key portion only. 1465 */ 1466 public byte [] getKey() { 1467 int keylength = getKeyLength(); 1468 byte [] key = new byte[keylength]; 1469 System.arraycopy(getBuffer(), getKeyOffset(), key, 0, keylength); 1470 return key; 1471 } 1472 1473 /** 1474 * 1475 * @return Timestamp 1476 */ 1477 @Override 1478 public long getTimestamp() { 1479 return getTimestamp(getKeyLength()); 1480 } 1481 1482 /** 1483 * @param keylength Pass if you have it to save on a int creation. 1484 * @return Timestamp 1485 */ 1486 long getTimestamp(final int keylength) { 1487 int tsOffset = getTimestampOffset(keylength); 1488 return Bytes.toLong(this.bytes, tsOffset); 1489 } 1490 1491 /** 1492 * @return KeyValue.TYPE byte representation 1493 */ 1494 @Override 1495 public byte getTypeByte() { 1496 return this.bytes[this.offset + getKeyLength() - 1 + ROW_OFFSET]; 1497 } 1498 1499 /** 1500 * This returns the offset where the tag actually starts. 1501 */ 1502 @Override 1503 public int getTagsOffset() { 1504 int tagsLen = getTagsLength(); 1505 if (tagsLen == 0) { 1506 return this.offset + this.length; 1507 } 1508 return this.offset + this.length - tagsLen; 1509 } 1510 1511 /** 1512 * This returns the total length of the tag bytes 1513 */ 1514 @Override 1515 public int getTagsLength() { 1516 int tagsLen = this.length - (getKeyLength() + getValueLength() + KEYVALUE_INFRASTRUCTURE_SIZE); 1517 if (tagsLen > 0) { 1518 // There are some Tag bytes in the byte[]. So reduce 2 bytes which is added to denote the tags 1519 // length 1520 tagsLen -= TAGS_LENGTH_SIZE; 1521 } 1522 return tagsLen; 1523 } 1524 1525 /** 1526 * @return the backing array of the entire KeyValue (all KeyValue fields are in a single array) 1527 */ 1528 @Override 1529 public byte[] getTagsArray() { 1530 return bytes; 1531 } 1532 1533 /** 1534 * Creates a new KeyValue that only contains the key portion (the value is 1535 * set to be null). 1536 * 1537 * TODO only used by KeyOnlyFilter -- move there. 1538 * @param lenAsVal replace value with the actual value length (false=empty) 1539 */ 1540 public KeyValue createKeyOnly(boolean lenAsVal) { 1541 // KV format: <keylen:4><valuelen:4><key:keylen><value:valuelen> 1542 // Rebuild as: <keylen:4><0:4><key:keylen> 1543 int dataLen = lenAsVal? Bytes.SIZEOF_INT : 0; 1544 byte [] newBuffer = new byte[getKeyLength() + ROW_OFFSET + dataLen]; 1545 System.arraycopy(this.bytes, this.offset, newBuffer, 0, 1546 Math.min(newBuffer.length,this.length)); 1547 Bytes.putInt(newBuffer, Bytes.SIZEOF_INT, dataLen); 1548 if (lenAsVal) { 1549 Bytes.putInt(newBuffer, newBuffer.length - dataLen, this.getValueLength()); 1550 } 1551 return new KeyValue(newBuffer); 1552 } 1553 1554 /** 1555 * @param b 1556 * @param delimiter 1557 * @return Index of delimiter having started from start of <code>b</code> 1558 * moving rightward. 1559 */ 1560 public static int getDelimiter(final byte [] b, int offset, final int length, 1561 final int delimiter) { 1562 if (b == null) { 1563 throw new IllegalArgumentException("Passed buffer is null"); 1564 } 1565 int result = -1; 1566 for (int i = offset; i < length + offset; i++) { 1567 if (b[i] == delimiter) { 1568 result = i; 1569 break; 1570 } 1571 } 1572 return result; 1573 } 1574 1575 /** 1576 * Find index of passed delimiter walking from end of buffer backwards. 1577 * @param b 1578 * @param delimiter 1579 * @return Index of delimiter 1580 */ 1581 public static int getDelimiterInReverse(final byte [] b, final int offset, 1582 final int length, final int delimiter) { 1583 if (b == null) { 1584 throw new IllegalArgumentException("Passed buffer is null"); 1585 } 1586 int result = -1; 1587 for (int i = (offset + length) - 1; i >= offset; i--) { 1588 if (b[i] == delimiter) { 1589 result = i; 1590 break; 1591 } 1592 } 1593 return result; 1594 } 1595 1596 /** 1597 * A {@link KVComparator} for <code>hbase:meta</code> catalog table 1598 * {@link KeyValue}s. 1599 * @deprecated : {@link CellComparatorImpl#META_COMPARATOR} to be used. Deprecated for hbase 2.0, remove for hbase 3.0. 1600 */ 1601 @Deprecated 1602 public static class MetaComparator extends KVComparator { 1603 /** 1604 * Compare key portion of a {@link KeyValue} for keys in <code>hbase:meta</code> 1605 * table. 1606 */ 1607 @Override 1608 public int compare(final Cell left, final Cell right) { 1609 return PrivateCellUtil.compareKeyIgnoresMvcc(CellComparatorImpl.META_COMPARATOR, left, right); 1610 } 1611 1612 @Override 1613 public int compareOnlyKeyPortion(Cell left, Cell right) { 1614 return compare(left, right); 1615 } 1616 1617 @Override 1618 public int compareRows(byte [] left, int loffset, int llength, 1619 byte [] right, int roffset, int rlength) { 1620 int leftDelimiter = getDelimiter(left, loffset, llength, 1621 HConstants.DELIMITER); 1622 int rightDelimiter = getDelimiter(right, roffset, rlength, 1623 HConstants.DELIMITER); 1624 // Compare up to the delimiter 1625 int lpart = (leftDelimiter < 0 ? llength :leftDelimiter - loffset); 1626 int rpart = (rightDelimiter < 0 ? rlength :rightDelimiter - roffset); 1627 int result = Bytes.compareTo(left, loffset, lpart, right, roffset, rpart); 1628 if (result != 0) { 1629 return result; 1630 } else { 1631 if (leftDelimiter < 0 && rightDelimiter >= 0) { 1632 return -1; 1633 } else if (rightDelimiter < 0 && leftDelimiter >= 0) { 1634 return 1; 1635 } else if (leftDelimiter < 0 && rightDelimiter < 0) { 1636 return 0; 1637 } 1638 } 1639 // Compare middle bit of the row. 1640 // Move past delimiter 1641 leftDelimiter++; 1642 rightDelimiter++; 1643 int leftFarDelimiter = getDelimiterInReverse(left, leftDelimiter, 1644 llength - (leftDelimiter - loffset), HConstants.DELIMITER); 1645 int rightFarDelimiter = getDelimiterInReverse(right, 1646 rightDelimiter, rlength - (rightDelimiter - roffset), 1647 HConstants.DELIMITER); 1648 // Now compare middlesection of row. 1649 lpart = (leftFarDelimiter < 0 ? llength + loffset: leftFarDelimiter) - leftDelimiter; 1650 rpart = (rightFarDelimiter < 0 ? rlength + roffset: rightFarDelimiter)- rightDelimiter; 1651 result = super.compareRows(left, leftDelimiter, lpart, right, rightDelimiter, rpart); 1652 if (result != 0) { 1653 return result; 1654 } else { 1655 if (leftDelimiter < 0 && rightDelimiter >= 0) { 1656 return -1; 1657 } else if (rightDelimiter < 0 && leftDelimiter >= 0) { 1658 return 1; 1659 } else if (leftDelimiter < 0 && rightDelimiter < 0) { 1660 return 0; 1661 } 1662 } 1663 // Compare last part of row, the rowid. 1664 leftFarDelimiter++; 1665 rightFarDelimiter++; 1666 result = Bytes.compareTo(left, leftFarDelimiter, llength - (leftFarDelimiter - loffset), 1667 right, rightFarDelimiter, rlength - (rightFarDelimiter - roffset)); 1668 return result; 1669 } 1670 1671 /** 1672 * Don't do any fancy Block Index splitting tricks. 1673 */ 1674 @Override 1675 public byte[] getShortMidpointKey(final byte[] leftKey, final byte[] rightKey) { 1676 return Arrays.copyOf(rightKey, rightKey.length); 1677 } 1678 1679 /** 1680 * The HFileV2 file format's trailer contains this class name. We reinterpret this and 1681 * instantiate the appropriate comparator. 1682 * TODO: With V3 consider removing this. 1683 * @return legacy class name for FileFileTrailer#comparatorClassName 1684 */ 1685 @Override 1686 public String getLegacyKeyComparatorName() { 1687 return "org.apache.hadoop.hbase.KeyValue$MetaKeyComparator"; 1688 } 1689 1690 @Override 1691 protected Object clone() throws CloneNotSupportedException { 1692 return new MetaComparator(); 1693 } 1694 1695 /** 1696 * Override the row key comparison to parse and compare the meta row key parts. 1697 */ 1698 @Override 1699 protected int compareRowKey(final Cell l, final Cell r) { 1700 byte[] left = l.getRowArray(); 1701 int loffset = l.getRowOffset(); 1702 int llength = l.getRowLength(); 1703 byte[] right = r.getRowArray(); 1704 int roffset = r.getRowOffset(); 1705 int rlength = r.getRowLength(); 1706 return compareRows(left, loffset, llength, right, roffset, rlength); 1707 } 1708 } 1709 1710 /** 1711 * Compare KeyValues. When we compare KeyValues, we only compare the Key 1712 * portion. This means two KeyValues with same Key but different Values are 1713 * considered the same as far as this Comparator is concerned. 1714 * @deprecated : Use {@link CellComparatorImpl}. Deprecated for hbase 2.0, remove for hbase 3.0. 1715 */ 1716 @Deprecated 1717 public static class KVComparator implements RawComparator<Cell>, SamePrefixComparator<byte[]> { 1718 1719 /** 1720 * The HFileV2 file format's trailer contains this class name. We reinterpret this and 1721 * instantiate the appropriate comparator. 1722 * TODO: With V3 consider removing this. 1723 * @return legacy class name for FileFileTrailer#comparatorClassName 1724 */ 1725 public String getLegacyKeyComparatorName() { 1726 return "org.apache.hadoop.hbase.KeyValue$KeyComparator"; 1727 } 1728 1729 @Override // RawComparator 1730 public int compare(byte[] l, int loff, int llen, byte[] r, int roff, int rlen) { 1731 return compareFlatKey(l,loff,llen, r,roff,rlen); 1732 } 1733 1734 1735 /** 1736 * Compares the only the user specified portion of a Key. This is overridden by MetaComparator. 1737 * @param left 1738 * @param right 1739 * @return 0 if equal, <0 if left smaller, >0 if right smaller 1740 */ 1741 protected int compareRowKey(final Cell left, final Cell right) { 1742 return CellComparatorImpl.COMPARATOR.compareRows(left, right); 1743 } 1744 1745 /** 1746 * Compares left to right assuming that left,loffset,llength and right,roffset,rlength are 1747 * full KVs laid out in a flat byte[]s. 1748 * @param left 1749 * @param loffset 1750 * @param llength 1751 * @param right 1752 * @param roffset 1753 * @param rlength 1754 * @return 0 if equal, <0 if left smaller, >0 if right smaller 1755 */ 1756 public int compareFlatKey(byte[] left, int loffset, int llength, 1757 byte[] right, int roffset, int rlength) { 1758 // Compare row 1759 short lrowlength = Bytes.toShort(left, loffset); 1760 short rrowlength = Bytes.toShort(right, roffset); 1761 int compare = compareRows(left, loffset + Bytes.SIZEOF_SHORT, 1762 lrowlength, right, roffset + Bytes.SIZEOF_SHORT, rrowlength); 1763 if (compare != 0) { 1764 return compare; 1765 } 1766 1767 // Compare the rest of the two KVs without making any assumptions about 1768 // the common prefix. This function will not compare rows anyway, so we 1769 // don't need to tell it that the common prefix includes the row. 1770 return compareWithoutRow(0, left, loffset, llength, right, roffset, 1771 rlength, rrowlength); 1772 } 1773 1774 public int compareFlatKey(byte[] left, byte[] right) { 1775 return compareFlatKey(left, 0, left.length, right, 0, right.length); 1776 } 1777 1778 // compare a key against row/fam/qual/ts/type 1779 public int compareKey(Cell cell, 1780 byte[] row, int roff, int rlen, 1781 byte[] fam, int foff, int flen, 1782 byte[] col, int coff, int clen, 1783 long ts, byte type) { 1784 1785 int compare = compareRows( 1786 cell.getRowArray(), cell.getRowOffset(), cell.getRowLength(), 1787 row, roff, rlen); 1788 if (compare != 0) { 1789 return compare; 1790 } 1791 // If the column is not specified, the "minimum" key type appears the 1792 // latest in the sorted order, regardless of the timestamp. This is used 1793 // for specifying the last key/value in a given row, because there is no 1794 // "lexicographically last column" (it would be infinitely long). The 1795 // "maximum" key type does not need this behavior. 1796 if (cell.getFamilyLength() + cell.getQualifierLength() == 0 1797 && cell.getTypeByte() == Type.Minimum.getCode()) { 1798 // left is "bigger", i.e. it appears later in the sorted order 1799 return 1; 1800 } 1801 if (flen+clen == 0 && type == Type.Minimum.getCode()) { 1802 return -1; 1803 } 1804 1805 compare = compareFamilies( 1806 cell.getFamilyArray(), cell.getFamilyOffset(), cell.getFamilyLength(), 1807 fam, foff, flen); 1808 if (compare != 0) { 1809 return compare; 1810 } 1811 compare = compareColumns( 1812 cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength(), 1813 col, coff, clen); 1814 if (compare != 0) { 1815 return compare; 1816 } 1817 // Next compare timestamps. 1818 compare = compareTimestamps(cell.getTimestamp(), ts); 1819 if (compare != 0) { 1820 return compare; 1821 } 1822 1823 // Compare types. Let the delete types sort ahead of puts; i.e. types 1824 // of higher numbers sort before those of lesser numbers. Maximum (255) 1825 // appears ahead of everything, and minimum (0) appears after 1826 // everything. 1827 return (0xff & type) - (0xff & cell.getTypeByte()); 1828 } 1829 1830 public int compareOnlyKeyPortion(Cell left, Cell right) { 1831 return PrivateCellUtil.compareKeyIgnoresMvcc(CellComparatorImpl.COMPARATOR, left, right); 1832 } 1833 1834 /** 1835 * Compares the Key of a cell -- with fields being more significant in this order: 1836 * rowkey, colfam/qual, timestamp, type, mvcc 1837 */ 1838 @Override 1839 public int compare(final Cell left, final Cell right) { 1840 int compare = CellComparatorImpl.COMPARATOR.compare(left, right); 1841 return compare; 1842 } 1843 1844 public int compareTimestamps(final Cell left, final Cell right) { 1845 return CellComparatorImpl.COMPARATOR.compareTimestamps(left, right); 1846 } 1847 1848 /** 1849 * @param left 1850 * @param right 1851 * @return Result comparing rows. 1852 */ 1853 public int compareRows(final Cell left, final Cell right) { 1854 return compareRows(left.getRowArray(),left.getRowOffset(), left.getRowLength(), 1855 right.getRowArray(), right.getRowOffset(), right.getRowLength()); 1856 } 1857 1858 /** 1859 * Get the b[],o,l for left and right rowkey portions and compare. 1860 * @param left 1861 * @param loffset 1862 * @param llength 1863 * @param right 1864 * @param roffset 1865 * @param rlength 1866 * @return 0 if equal, <0 if left smaller, >0 if right smaller 1867 */ 1868 public int compareRows(byte [] left, int loffset, int llength, 1869 byte [] right, int roffset, int rlength) { 1870 return Bytes.compareTo(left, loffset, llength, right, roffset, rlength); 1871 } 1872 1873 int compareColumns(final Cell left, final short lrowlength, final Cell right, 1874 final short rrowlength) { 1875 return CellComparatorImpl.COMPARATOR.compareColumns(left, right); 1876 } 1877 1878 protected int compareColumns( 1879 byte [] left, int loffset, int llength, final int lfamilylength, 1880 byte [] right, int roffset, int rlength, final int rfamilylength) { 1881 // Compare family portion first. 1882 int diff = Bytes.compareTo(left, loffset, lfamilylength, 1883 right, roffset, rfamilylength); 1884 if (diff != 0) { 1885 return diff; 1886 } 1887 // Compare qualifier portion 1888 return Bytes.compareTo(left, loffset + lfamilylength, 1889 llength - lfamilylength, 1890 right, roffset + rfamilylength, rlength - rfamilylength); 1891 } 1892 1893 static int compareTimestamps(final long ltimestamp, final long rtimestamp) { 1894 // The below older timestamps sorting ahead of newer timestamps looks 1895 // wrong but it is intentional. This way, newer timestamps are first 1896 // found when we iterate over a memstore and newer versions are the 1897 // first we trip over when reading from a store file. 1898 if (ltimestamp < rtimestamp) { 1899 return 1; 1900 } else if (ltimestamp > rtimestamp) { 1901 return -1; 1902 } 1903 return 0; 1904 } 1905 1906 /** 1907 * Overridden 1908 * @param commonPrefix 1909 * @param left 1910 * @param loffset 1911 * @param llength 1912 * @param right 1913 * @param roffset 1914 * @param rlength 1915 * @return 0 if equal, <0 if left smaller, >0 if right smaller 1916 */ 1917 @Override // SamePrefixComparator 1918 public int compareIgnoringPrefix(int commonPrefix, byte[] left, 1919 int loffset, int llength, byte[] right, int roffset, int rlength) { 1920 // Compare row 1921 short lrowlength = Bytes.toShort(left, loffset); 1922 short rrowlength; 1923 1924 int comparisonResult = 0; 1925 if (commonPrefix < ROW_LENGTH_SIZE) { 1926 // almost nothing in common 1927 rrowlength = Bytes.toShort(right, roffset); 1928 comparisonResult = compareRows(left, loffset + ROW_LENGTH_SIZE, 1929 lrowlength, right, roffset + ROW_LENGTH_SIZE, rrowlength); 1930 } else { // the row length is the same 1931 rrowlength = lrowlength; 1932 if (commonPrefix < ROW_LENGTH_SIZE + rrowlength) { 1933 // The rows are not the same. Exclude the common prefix and compare 1934 // the rest of the two rows. 1935 int common = commonPrefix - ROW_LENGTH_SIZE; 1936 comparisonResult = compareRows( 1937 left, loffset + common + ROW_LENGTH_SIZE, lrowlength - common, 1938 right, roffset + common + ROW_LENGTH_SIZE, rrowlength - common); 1939 } 1940 } 1941 if (comparisonResult != 0) { 1942 return comparisonResult; 1943 } 1944 1945 assert lrowlength == rrowlength; 1946 return compareWithoutRow(commonPrefix, left, loffset, llength, right, 1947 roffset, rlength, lrowlength); 1948 } 1949 1950 /** 1951 * Compare columnFamily, qualifier, timestamp, and key type (everything 1952 * except the row). This method is used both in the normal comparator and 1953 * the "same-prefix" comparator. Note that we are assuming that row portions 1954 * of both KVs have already been parsed and found identical, and we don't 1955 * validate that assumption here. 1956 * @param commonPrefix 1957 * the length of the common prefix of the two key-values being 1958 * compared, including row length and row 1959 */ 1960 private int compareWithoutRow(int commonPrefix, byte[] left, int loffset, 1961 int llength, byte[] right, int roffset, int rlength, short rowlength) { 1962 /*** 1963 * KeyValue Format and commonLength: 1964 * |_keyLen_|_valLen_|_rowLen_|_rowKey_|_famiLen_|_fami_|_Quali_|.... 1965 * ------------------|-------commonLength--------|-------------- 1966 */ 1967 int commonLength = ROW_LENGTH_SIZE + FAMILY_LENGTH_SIZE + rowlength; 1968 1969 // commonLength + TIMESTAMP_TYPE_SIZE 1970 int commonLengthWithTSAndType = TIMESTAMP_TYPE_SIZE + commonLength; 1971 // ColumnFamily + Qualifier length. 1972 int lcolumnlength = llength - commonLengthWithTSAndType; 1973 int rcolumnlength = rlength - commonLengthWithTSAndType; 1974 1975 byte ltype = left[loffset + (llength - 1)]; 1976 byte rtype = right[roffset + (rlength - 1)]; 1977 1978 // If the column is not specified, the "minimum" key type appears the 1979 // latest in the sorted order, regardless of the timestamp. This is used 1980 // for specifying the last key/value in a given row, because there is no 1981 // "lexicographically last column" (it would be infinitely long). The 1982 // "maximum" key type does not need this behavior. 1983 if (lcolumnlength == 0 && ltype == Type.Minimum.getCode()) { 1984 // left is "bigger", i.e. it appears later in the sorted order 1985 return 1; 1986 } 1987 if (rcolumnlength == 0 && rtype == Type.Minimum.getCode()) { 1988 return -1; 1989 } 1990 1991 int lfamilyoffset = commonLength + loffset; 1992 int rfamilyoffset = commonLength + roffset; 1993 1994 // Column family length. 1995 int lfamilylength = left[lfamilyoffset - 1]; 1996 int rfamilylength = right[rfamilyoffset - 1]; 1997 // If left family size is not equal to right family size, we need not 1998 // compare the qualifiers. 1999 boolean sameFamilySize = (lfamilylength == rfamilylength); 2000 int common = 0; 2001 if (commonPrefix > 0) { 2002 common = Math.max(0, commonPrefix - commonLength); 2003 if (!sameFamilySize) { 2004 // Common should not be larger than Math.min(lfamilylength, 2005 // rfamilylength). 2006 common = Math.min(common, Math.min(lfamilylength, rfamilylength)); 2007 } else { 2008 common = Math.min(common, Math.min(lcolumnlength, rcolumnlength)); 2009 } 2010 } 2011 if (!sameFamilySize) { 2012 // comparing column family is enough. 2013 return Bytes.compareTo(left, lfamilyoffset + common, lfamilylength 2014 - common, right, rfamilyoffset + common, rfamilylength - common); 2015 } 2016 // Compare family & qualifier together. 2017 final int comparison = Bytes.compareTo(left, lfamilyoffset + common, 2018 lcolumnlength - common, right, rfamilyoffset + common, 2019 rcolumnlength - common); 2020 if (comparison != 0) { 2021 return comparison; 2022 } 2023 2024 //// 2025 // Next compare timestamps. 2026 long ltimestamp = Bytes.toLong(left, 2027 loffset + (llength - TIMESTAMP_TYPE_SIZE)); 2028 long rtimestamp = Bytes.toLong(right, 2029 roffset + (rlength - TIMESTAMP_TYPE_SIZE)); 2030 int compare = compareTimestamps(ltimestamp, rtimestamp); 2031 if (compare != 0) { 2032 return compare; 2033 } 2034 2035 // Compare types. Let the delete types sort ahead of puts; i.e. types 2036 // of higher numbers sort before those of lesser numbers. Maximum (255) 2037 // appears ahead of everything, and minimum (0) appears after 2038 // everything. 2039 return (0xff & rtype) - (0xff & ltype); 2040 } 2041 2042 protected int compareFamilies(final byte[] left, final int loffset, final int lfamilylength, 2043 final byte[] right, final int roffset, final int rfamilylength) { 2044 int diff = Bytes.compareTo(left, loffset, lfamilylength, right, roffset, rfamilylength); 2045 return diff; 2046 } 2047 2048 protected int compareColumns(final byte[] left, final int loffset, final int lquallength, 2049 final byte[] right, final int roffset, final int rquallength) { 2050 int diff = Bytes.compareTo(left, loffset, lquallength, right, roffset, rquallength); 2051 return diff; 2052 } 2053 /** 2054 * Compares the row and column of two keyvalues for equality 2055 * @param left 2056 * @param right 2057 * @return True if same row and column. 2058 */ 2059 public boolean matchingRowColumn(final Cell left, 2060 final Cell right) { 2061 short lrowlength = left.getRowLength(); 2062 short rrowlength = right.getRowLength(); 2063 2064 // TsOffset = end of column data. just comparing Row+CF length of each 2065 if ((left.getRowLength() + left.getFamilyLength() + left.getQualifierLength()) != (right 2066 .getRowLength() + right.getFamilyLength() + right.getQualifierLength())) { 2067 return false; 2068 } 2069 2070 if (!matchingRows(left, lrowlength, right, rrowlength)) { 2071 return false; 2072 } 2073 2074 int lfoffset = left.getFamilyOffset(); 2075 int rfoffset = right.getFamilyOffset(); 2076 int lclength = left.getQualifierLength(); 2077 int rclength = right.getQualifierLength(); 2078 int lfamilylength = left.getFamilyLength(); 2079 int rfamilylength = right.getFamilyLength(); 2080 int diff = compareFamilies(left.getFamilyArray(), lfoffset, lfamilylength, 2081 right.getFamilyArray(), rfoffset, rfamilylength); 2082 if (diff != 0) { 2083 return false; 2084 } else { 2085 diff = compareColumns(left.getQualifierArray(), left.getQualifierOffset(), lclength, 2086 right.getQualifierArray(), right.getQualifierOffset(), rclength); 2087 return diff == 0; 2088 } 2089 } 2090 2091 /** 2092 * Compares the row of two keyvalues for equality 2093 * @param left 2094 * @param right 2095 * @return True if rows match. 2096 */ 2097 public boolean matchingRows(final Cell left, final Cell right) { 2098 short lrowlength = left.getRowLength(); 2099 short rrowlength = right.getRowLength(); 2100 return matchingRows(left, lrowlength, right, rrowlength); 2101 } 2102 2103 /** 2104 * @param left 2105 * @param lrowlength 2106 * @param right 2107 * @param rrowlength 2108 * @return True if rows match. 2109 */ 2110 private boolean matchingRows(final Cell left, final short lrowlength, 2111 final Cell right, final short rrowlength) { 2112 return lrowlength == rrowlength && 2113 matchingRows(left.getRowArray(), left.getRowOffset(), lrowlength, 2114 right.getRowArray(), right.getRowOffset(), rrowlength); 2115 } 2116 2117 /** 2118 * Compare rows. Just calls Bytes.equals, but it's good to have this encapsulated. 2119 * @param left Left row array. 2120 * @param loffset Left row offset. 2121 * @param llength Left row length. 2122 * @param right Right row array. 2123 * @param roffset Right row offset. 2124 * @param rlength Right row length. 2125 * @return Whether rows are the same row. 2126 */ 2127 public boolean matchingRows(final byte [] left, final int loffset, final int llength, 2128 final byte [] right, final int roffset, final int rlength) { 2129 return Bytes.equals(left, loffset, llength, right, roffset, rlength); 2130 } 2131 2132 public byte[] calcIndexKey(byte[] lastKeyOfPreviousBlock, byte[] firstKeyInBlock) { 2133 byte[] fakeKey = getShortMidpointKey(lastKeyOfPreviousBlock, firstKeyInBlock); 2134 if (compareFlatKey(fakeKey, firstKeyInBlock) > 0) { 2135 LOG.error("Unexpected getShortMidpointKey result, fakeKey:" 2136 + Bytes.toStringBinary(fakeKey) + ", firstKeyInBlock:" 2137 + Bytes.toStringBinary(firstKeyInBlock)); 2138 return firstKeyInBlock; 2139 } 2140 if (lastKeyOfPreviousBlock != null && compareFlatKey(lastKeyOfPreviousBlock, fakeKey) >= 0) { 2141 LOG.error("Unexpected getShortMidpointKey result, lastKeyOfPreviousBlock:" + 2142 Bytes.toStringBinary(lastKeyOfPreviousBlock) + ", fakeKey:" + 2143 Bytes.toStringBinary(fakeKey)); 2144 return firstKeyInBlock; 2145 } 2146 return fakeKey; 2147 } 2148 2149 /** 2150 * This is a HFile block index key optimization. 2151 * @param leftKey 2152 * @param rightKey 2153 * @return 0 if equal, <0 if left smaller, >0 if right smaller 2154 * @deprecated Since 0.99.2; 2155 */ 2156 @Deprecated 2157 public byte[] getShortMidpointKey(final byte[] leftKey, final byte[] rightKey) { 2158 if (rightKey == null) { 2159 throw new IllegalArgumentException("rightKey can not be null"); 2160 } 2161 if (leftKey == null) { 2162 return Arrays.copyOf(rightKey, rightKey.length); 2163 } 2164 if (compareFlatKey(leftKey, rightKey) >= 0) { 2165 throw new IllegalArgumentException("Unexpected input, leftKey:" + Bytes.toString(leftKey) 2166 + ", rightKey:" + Bytes.toString(rightKey)); 2167 } 2168 2169 short leftRowLength = Bytes.toShort(leftKey, 0); 2170 short rightRowLength = Bytes.toShort(rightKey, 0); 2171 int leftCommonLength = ROW_LENGTH_SIZE + FAMILY_LENGTH_SIZE + leftRowLength; 2172 int rightCommonLength = ROW_LENGTH_SIZE + FAMILY_LENGTH_SIZE + rightRowLength; 2173 int leftCommonLengthWithTSAndType = TIMESTAMP_TYPE_SIZE + leftCommonLength; 2174 int rightCommonLengthWithTSAndType = TIMESTAMP_TYPE_SIZE + rightCommonLength; 2175 int leftColumnLength = leftKey.length - leftCommonLengthWithTSAndType; 2176 int rightColumnLength = rightKey.length - rightCommonLengthWithTSAndType; 2177 // rows are equal 2178 if (leftRowLength == rightRowLength && compareRows(leftKey, ROW_LENGTH_SIZE, leftRowLength, 2179 rightKey, ROW_LENGTH_SIZE, rightRowLength) == 0) { 2180 // Compare family & qualifier together. 2181 int comparison = Bytes.compareTo(leftKey, leftCommonLength, leftColumnLength, rightKey, 2182 rightCommonLength, rightColumnLength); 2183 // same with "row + family + qualifier", return rightKey directly 2184 if (comparison == 0) { 2185 return Arrays.copyOf(rightKey, rightKey.length); 2186 } 2187 // "family + qualifier" are different, generate a faked key per rightKey 2188 byte[] newKey = Arrays.copyOf(rightKey, rightKey.length); 2189 Bytes.putLong(newKey, rightKey.length - TIMESTAMP_TYPE_SIZE, HConstants.LATEST_TIMESTAMP); 2190 Bytes.putByte(newKey, rightKey.length - TYPE_SIZE, Type.Maximum.getCode()); 2191 return newKey; 2192 } 2193 // rows are different 2194 short minLength = leftRowLength < rightRowLength ? leftRowLength : rightRowLength; 2195 short diffIdx = 0; 2196 while (diffIdx < minLength 2197 && leftKey[ROW_LENGTH_SIZE + diffIdx] == rightKey[ROW_LENGTH_SIZE + diffIdx]) { 2198 diffIdx++; 2199 } 2200 byte[] newRowKey = null; 2201 if (diffIdx >= minLength) { 2202 // leftKey's row is prefix of rightKey's. 2203 newRowKey = new byte[diffIdx + 1]; 2204 System.arraycopy(rightKey, ROW_LENGTH_SIZE, newRowKey, 0, diffIdx + 1); 2205 } else { 2206 int diffByte = leftKey[ROW_LENGTH_SIZE + diffIdx]; 2207 if ((0xff & diffByte) < 0xff && (diffByte + 1) < 2208 (rightKey[ROW_LENGTH_SIZE + diffIdx] & 0xff)) { 2209 newRowKey = new byte[diffIdx + 1]; 2210 System.arraycopy(leftKey, ROW_LENGTH_SIZE, newRowKey, 0, diffIdx); 2211 newRowKey[diffIdx] = (byte) (diffByte + 1); 2212 } else { 2213 newRowKey = new byte[diffIdx + 1]; 2214 System.arraycopy(rightKey, ROW_LENGTH_SIZE, newRowKey, 0, diffIdx + 1); 2215 } 2216 } 2217 return new KeyValue(newRowKey, null, null, HConstants.LATEST_TIMESTAMP, 2218 Type.Maximum).getKey(); 2219 } 2220 2221 @Override 2222 protected Object clone() throws CloneNotSupportedException { 2223 super.clone(); 2224 return new KVComparator(); 2225 } 2226 2227 } 2228 2229 /** 2230 * @param in Where to read bytes from. Creates a byte array to hold the KeyValue 2231 * backing bytes copied from the steam. 2232 * @return KeyValue created by deserializing from <code>in</code> OR if we find a length 2233 * of zero, we will return null which can be useful marking a stream as done. 2234 * @throws IOException 2235 */ 2236 public static KeyValue create(final DataInput in) throws IOException { 2237 return create(in.readInt(), in); 2238 } 2239 2240 /** 2241 * Create a KeyValue reading <code>length</code> from <code>in</code> 2242 * @param length 2243 * @param in 2244 * @return Created KeyValue OR if we find a length of zero, we will return null which 2245 * can be useful marking a stream as done. 2246 * @throws IOException 2247 */ 2248 public static KeyValue create(int length, final DataInput in) throws IOException { 2249 2250 if (length <= 0) { 2251 if (length == 0) return null; 2252 throw new IOException("Failed read " + length + " bytes, stream corrupt?"); 2253 } 2254 2255 // This is how the old Writables.readFrom used to deserialize. Didn't even vint. 2256 byte [] bytes = new byte[length]; 2257 in.readFully(bytes); 2258 return new KeyValue(bytes, 0, length); 2259 } 2260 2261 /** 2262 * Write out a KeyValue in the manner in which we used to when KeyValue was a Writable. 2263 * @param kv 2264 * @param out 2265 * @return Length written on stream 2266 * @throws IOException 2267 * @see #create(DataInput) for the inverse function 2268 */ 2269 public static long write(final KeyValue kv, final DataOutput out) throws IOException { 2270 // This is how the old Writables write used to serialize KVs. Need to figure way to make it 2271 // work for all implementations. 2272 int length = kv.getLength(); 2273 out.writeInt(length); 2274 out.write(kv.getBuffer(), kv.getOffset(), length); 2275 return (long) length + Bytes.SIZEOF_INT; 2276 } 2277 2278 /** 2279 * Write out a KeyValue in the manner in which we used to when KeyValue was a Writable but do 2280 * not require a {@link DataOutput}, just take plain {@link OutputStream} 2281 * Named <code>oswrite</code> so does not clash with {@link #write(KeyValue, DataOutput)} 2282 * @param kv 2283 * @param out 2284 * @param withTags 2285 * @return Length written on stream 2286 * @throws IOException 2287 * @see #create(DataInput) for the inverse function 2288 * @see #write(KeyValue, DataOutput) 2289 * @see KeyValueUtil#oswrite(Cell, OutputStream, boolean) 2290 * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0. 2291 * Instead use {@link #write(OutputStream, boolean)} 2292 */ 2293 @Deprecated 2294 public static long oswrite(final KeyValue kv, final OutputStream out, final boolean withTags) 2295 throws IOException { 2296 ByteBufferUtils.putInt(out, kv.getSerializedSize(withTags)); 2297 return (long) kv.write(out, withTags) + Bytes.SIZEOF_INT; 2298 } 2299 2300 @Override 2301 public int write(OutputStream out, boolean withTags) throws IOException { 2302 int len = getSerializedSize(withTags); 2303 out.write(this.bytes, this.offset, len); 2304 return len; 2305 } 2306 2307 @Override 2308 public int getSerializedSize(boolean withTags) { 2309 if (withTags) { 2310 return this.length; 2311 } 2312 return this.getKeyLength() + this.getValueLength() + KEYVALUE_INFRASTRUCTURE_SIZE; 2313 } 2314 2315 @Override 2316 public void write(ByteBuffer buf, int offset) { 2317 ByteBufferUtils.copyFromArrayToBuffer(buf, offset, this.bytes, this.offset, this.length); 2318 } 2319 2320 /** 2321 * Avoids redundant comparisons for better performance. 2322 * 2323 * TODO get rid of this wart 2324 */ 2325 public interface SamePrefixComparator<T> { 2326 /** 2327 * Compare two keys assuming that the first n bytes are the same. 2328 * @param commonPrefix How many bytes are the same. 2329 */ 2330 int compareIgnoringPrefix(int commonPrefix, byte[] left, int loffset, int llength, 2331 byte[] right, int roffset, int rlength 2332 ); 2333 } 2334 2335 /** 2336 * HeapSize implementation 2337 * 2338 * We do not count the bytes in the rowCache because it should be empty for a KeyValue in the 2339 * MemStore. 2340 */ 2341 @Override 2342 public long heapSize() { 2343 /* 2344 * Deep object overhead for this KV consists of two parts. The first part is the KV object 2345 * itself, while the second part is the backing byte[]. We will only count the array overhead 2346 * from the byte[] only if this is the first KV in there. 2347 */ 2348 return ClassSize.align(FIXED_OVERHEAD) + 2349 (offset == 0 2350 ? ClassSize.sizeOfByteArray(length) // count both length and object overhead 2351 : length); // only count the number of bytes 2352 } 2353 2354 /** 2355 * A simple form of KeyValue that creates a keyvalue with only the key part of the byte[] 2356 * Mainly used in places where we need to compare two cells. Avoids copying of bytes 2357 * In places like block index keys, we need to compare the key byte[] with a cell. 2358 * Hence create a Keyvalue(aka Cell) that would help in comparing as two cells 2359 */ 2360 public static class KeyOnlyKeyValue extends KeyValue { 2361 private short rowLen = -1; 2362 public KeyOnlyKeyValue() { 2363 2364 } 2365 public KeyOnlyKeyValue(byte[] b) { 2366 this(b, 0, b.length); 2367 } 2368 2369 public KeyOnlyKeyValue(byte[] b, int offset, int length) { 2370 this.bytes = b; 2371 this.length = length; 2372 this.offset = offset; 2373 this.rowLen = Bytes.toShort(this.bytes, this.offset); 2374 } 2375 2376 public void set(KeyOnlyKeyValue keyOnlyKeyValue) { 2377 this.bytes = keyOnlyKeyValue.bytes; 2378 this.length = keyOnlyKeyValue.length; 2379 this.offset = keyOnlyKeyValue.offset; 2380 this.rowLen = keyOnlyKeyValue.rowLen; 2381 } 2382 2383 public void clear() { 2384 rowLen = -1; 2385 bytes = null; 2386 offset = 0; 2387 length = 0; 2388 } 2389 2390 @Override 2391 public int getKeyOffset() { 2392 return this.offset; 2393 } 2394 2395 /** 2396 * A setter that helps to avoid object creation every time and whenever 2397 * there is a need to create new KeyOnlyKeyValue. 2398 * @param key 2399 * @param offset 2400 * @param length 2401 */ 2402 public void setKey(byte[] key, int offset, int length) { 2403 this.bytes = key; 2404 this.offset = offset; 2405 this.length = length; 2406 this.rowLen = Bytes.toShort(this.bytes, this.offset); 2407 } 2408 2409 @Override 2410 public byte[] getKey() { 2411 int keylength = getKeyLength(); 2412 byte[] key = new byte[keylength]; 2413 System.arraycopy(this.bytes, getKeyOffset(), key, 0, keylength); 2414 return key; 2415 } 2416 2417 @Override 2418 public byte[] getRowArray() { 2419 return bytes; 2420 } 2421 2422 @Override 2423 public int getRowOffset() { 2424 return getKeyOffset() + Bytes.SIZEOF_SHORT; 2425 } 2426 2427 @Override 2428 public byte[] getFamilyArray() { 2429 return bytes; 2430 } 2431 2432 @Override 2433 public byte getFamilyLength() { 2434 return this.bytes[getFamilyOffset() - 1]; 2435 } 2436 2437 @Override 2438 public int getFamilyOffset() { 2439 return this.offset + Bytes.SIZEOF_SHORT + getRowLength() + Bytes.SIZEOF_BYTE; 2440 } 2441 2442 @Override 2443 public byte[] getQualifierArray() { 2444 return bytes; 2445 } 2446 2447 @Override 2448 public int getQualifierLength() { 2449 return getQualifierLength(getRowLength(), getFamilyLength()); 2450 } 2451 2452 @Override 2453 public int getQualifierOffset() { 2454 return getFamilyOffset() + getFamilyLength(); 2455 } 2456 2457 @Override 2458 public int getKeyLength() { 2459 return length; 2460 } 2461 2462 @Override 2463 public short getRowLength() { 2464 return rowLen; 2465 } 2466 2467 @Override 2468 public byte getTypeByte() { 2469 return this.bytes[this.offset + getKeyLength() - 1]; 2470 } 2471 2472 private int getQualifierLength(int rlength, int flength) { 2473 return getKeyLength() - (int) getKeyDataStructureSize(rlength, flength, 0); 2474 } 2475 2476 @Override 2477 public long getTimestamp() { 2478 int tsOffset = getTimestampOffset(); 2479 return Bytes.toLong(this.bytes, tsOffset); 2480 } 2481 2482 @Override 2483 public int getTimestampOffset() { 2484 return getKeyOffset() + getKeyLength() - TIMESTAMP_TYPE_SIZE; 2485 } 2486 2487 @Override 2488 public byte[] getTagsArray() { 2489 return HConstants.EMPTY_BYTE_ARRAY; 2490 } 2491 2492 @Override 2493 public int getTagsOffset() { 2494 return 0; 2495 } 2496 2497 @Override 2498 public byte[] getValueArray() { 2499 throw new IllegalArgumentException("KeyOnlyKeyValue does not work with values."); 2500 } 2501 2502 @Override 2503 public int getValueOffset() { 2504 throw new IllegalArgumentException("KeyOnlyKeyValue does not work with values."); 2505 } 2506 2507 @Override 2508 public int getValueLength() { 2509 throw new IllegalArgumentException("KeyOnlyKeyValue does not work with values."); 2510 } 2511 2512 @Override 2513 public int getTagsLength() { 2514 return 0; 2515 } 2516 2517 @Override 2518 public String toString() { 2519 if (this.bytes == null || this.bytes.length == 0) { 2520 return "empty"; 2521 } 2522 return keyToString(this.bytes, this.offset, getKeyLength()) + "/vlen=0/mvcc=0"; 2523 } 2524 2525 @Override 2526 public int hashCode() { 2527 return super.hashCode(); 2528 } 2529 2530 @Override 2531 public boolean equals(Object other) { 2532 return super.equals(other); 2533 } 2534 2535 @Override 2536 public long heapSize() { 2537 return super.heapSize() + Bytes.SIZEOF_SHORT; 2538 } 2539 2540 @Override 2541 public int write(OutputStream out, boolean withTags) throws IOException { 2542 // This type of Cell is used only to maintain some internal states. We never allow this type 2543 // of Cell to be returned back over the RPC 2544 throw new IllegalStateException("A reader should never return this type of a Cell"); 2545 } 2546 } 2547 2548 @Override 2549 public ExtendedCell deepClone() { 2550 byte[] copy = Bytes.copy(this.bytes, this.offset, this.length); 2551 KeyValue kv = new KeyValue(copy, 0, copy.length); 2552 kv.setSequenceId(this.getSequenceId()); 2553 return kv; 2554 } 2555}