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