Review Board 1.7.22


HBASE-5625 Avoid byte buffer allocations when reading a value from a Result object

Review Request #4607 - Created April 2, 2012 and updated

Tudor Scurtu
trunk
HBASE-5625
Reviewers
hbase
hbase-git
When calling Result.getValue(), an extra dummy KeyValue and its associated underlying byte array are allocated, as well as a persistent buffer that will contain the returned value.

These can be avoided by reusing a static array for the dummy object and by passing a ByteBuffer object as a value destination buffer to the read method.
Added value check to TestResult#testBasic and TestResult.testMultiVersion.
src/main/java/org/apache/hadoop/hbase/KeyValue.java
Diff Revision 1 Diff Revision 4
[20] 25 lines
[+20]
26
import java.nio.ByteBuffer;
26
import java.nio.ByteBuffer;
27
import java.util.Comparator;
27
import java.util.Comparator;
28
import java.util.HashMap;
28
import java.util.HashMap;
29
import java.util.Map;
29
import java.util.Map;
30

    
   
30

   
31
import com.google.common.primitives.Longs;

   
32
import org.apache.commons.logging.Log;
31
import org.apache.commons.logging.Log;
33
import org.apache.commons.logging.LogFactory;
32
import org.apache.commons.logging.LogFactory;
34
import org.apache.hadoop.classification.InterfaceAudience;
33
import org.apache.hadoop.classification.InterfaceAudience;
35
import org.apache.hadoop.classification.InterfaceStability;
34
import org.apache.hadoop.classification.InterfaceStability;
36
import org.apache.hadoop.hbase.io.HeapSize;
35
import org.apache.hadoop.hbase.io.HeapSize;
37
import org.apache.hadoop.hbase.io.hfile.HFile;
36
import org.apache.hadoop.hbase.io.hfile.HFile;
38
import org.apache.hadoop.hbase.util.Bytes;
37
import org.apache.hadoop.hbase.util.Bytes;
39
import org.apache.hadoop.hbase.util.ClassSize;
38
import org.apache.hadoop.hbase.util.ClassSize;
40
import org.apache.hadoop.io.RawComparator;
39
import org.apache.hadoop.io.RawComparator;
41
import org.apache.hadoop.io.Writable;
40
import org.apache.hadoop.io.Writable;
42

    
   
41

   

    
   
42
import com.google.common.primitives.Longs;

    
   
43

   
43
/**
44
/**
44
 * An HBase Key/Value.  This is the fundamental HBase Type.
45
 * An HBase Key/Value.  This is the fundamental HBase Type.
45
 *
46
 *
46
 * <p>If being used client-side, the primary methods to access individual fields
47
 * <p>If being used client-side, the primary methods to access individual fields
47
 * are {@link #getRow()}, {@link #getFamily()}, {@link #getQualifier()},
48
 * are {@link #getRow()}, {@link #getFamily()}, {@link #getQualifier()},
[+20] [20] 117 lines
[+20] [+] public static KeyComparator getRowComparator(byte [] tableName) {
165

    
   
166

   
166
  // Size of the length ints in a KeyValue datastructure.
167
  // Size of the length ints in a KeyValue datastructure.
167
  public static final int KEYVALUE_INFRASTRUCTURE_SIZE = ROW_OFFSET;
168
  public static final int KEYVALUE_INFRASTRUCTURE_SIZE = ROW_OFFSET;
168

    
   
169

   
169
  /**
170
  /**

    
   
171
   * Computes the number of bytes that a <code>KeyValue</code> instance with the provided

    
   
172
   * characteristics would take up for its underlying data structure.

    
   
173
   *

    
   
174
   * @param rlength row length

    
   
175
   * @param flength family length

    
   
176
   * @param qlength qualifier length

    
   
177
   * @param vlength value length

    
   
178
   *

    
   
179
   * @return the <code>KeyValue</code> data structure length

    
   
180
   */

    
   
181
  public static long getKeyValueDataStructureSize(int rlength,

    
   
182
      int flength, int qlength, int vlength) {

    
   
183
    return KeyValue.KEYVALUE_INFRASTRUCTURE_SIZE +

    
   
184
            getKeyDataStructureSize(rlength, flength, qlength) + vlength;

    
   
185
  }

    
   
186

   

    
   
187
  /**

    
   
188
   * Computes the number of bytes that a <code>KeyValue</code> instance with the provided

    
   
189
   * characteristics would take up in its underlying data structure for the key.

    
   
190
   *

    
   
191
   * @param rlength row length

    
   
192
   * @param flength family length

    
   
193
   * @param qlength qualifier length

    
   
194
   *

    
   
195
   * @return the key data structure length

    
   
196
   */

    
   
197
  public static long getKeyDataStructureSize(int rlength, int flength, int qlength) {

    
   
198
    return KeyValue.KEY_INFRASTRUCTURE_SIZE + rlength + flength + qlength;

    
   
199
  }

    
   
200

   

    
   
201
  /**
170
   * Key type.
202
   * Key type.
171
   * Has space for other key types to be added later.  Cannot rely on
203
   * Has space for other key types to be added later.  Cannot rely on
172
   * enum ordinals . They change if item is removed or moved.  Do our own codes.
204
   * enum ordinals . They change if item is removed or moved.  Do our own codes.
173
   */
205
   */
174
  public static enum Type {
206
  public static enum Type {
[+20] [20] 301 lines
[+20] [+] static byte[] createEmptyByteArray(final int rlength, int flength,
476
    // Qualifier length
508
    // Qualifier length
477
    if (qlength > Integer.MAX_VALUE - rlength - flength) {
509
    if (qlength > Integer.MAX_VALUE - rlength - flength) {
478
      throw new IllegalArgumentException("Qualifier > " + Integer.MAX_VALUE);
510
      throw new IllegalArgumentException("Qualifier > " + Integer.MAX_VALUE);
479
    }
511
    }
480
    // Key length
512
    // Key length
481
    long longkeylength = KEY_INFRASTRUCTURE_SIZE + rlength + flength + qlength;
513
    long longkeylength = getKeyDataStructureSize(rlength, flength, qlength);
482
    if (longkeylength > Integer.MAX_VALUE) {
514
    if (longkeylength > Integer.MAX_VALUE) {
483
      throw new IllegalArgumentException("keylength " + longkeylength + " > " +
515
      throw new IllegalArgumentException("keylength " + longkeylength + " > " +
484
        Integer.MAX_VALUE);
516
        Integer.MAX_VALUE);
485
    }
517
    }
486
    int keylength = (int)longkeylength;
518
    int keylength = (int)longkeylength;
487
    // Value length
519
    // Value length
488
    if (vlength > HConstants.MAXIMUM_VALUE_LENGTH) { // FindBugs INT_VACUOUS_COMPARISON
520
    if (vlength > HConstants.MAXIMUM_VALUE_LENGTH) { // FindBugs INT_VACUOUS_COMPARISON
489
      throw new IllegalArgumentException("Valuer > " +
521
      throw new IllegalArgumentException("Valuer > " +
490
          HConstants.MAXIMUM_VALUE_LENGTH);
522
          HConstants.MAXIMUM_VALUE_LENGTH);
491
    }
523
    }
492

    
   
524

   
493
    // Allocate right-sized byte array.
525
    // Allocate right-sized byte array.
494
    byte [] bytes = new byte[KEYVALUE_INFRASTRUCTURE_SIZE + keylength + vlength];
526
    byte [] bytes =

    
   
527
        new byte[(int) getKeyValueDataStructureSize(rlength, flength, qlength, vlength)];
495
    // Write the correct size markers
528
    // Write the correct size markers
496
    int pos = 0;
529
    int pos = 0;
497
    pos = Bytes.putInt(bytes, pos, keylength);
530
    pos = Bytes.putInt(bytes, pos, keylength);
498
    pos = Bytes.putInt(bytes, pos, vlength);
531
    pos = Bytes.putInt(bytes, pos, vlength);
499
    pos = Bytes.putShort(bytes, pos, (short)(rlength & 0x0000ffff));
532
    pos = Bytes.putShort(bytes, pos, (short)(rlength & 0x0000ffff));
[+20] [20] 4 lines
[+20] static byte[] createEmptyByteArray(final int rlength, int flength,
504
    pos = Bytes.putByte(bytes, pos, type.getCode());
537
    pos = Bytes.putByte(bytes, pos, type.getCode());
505
    return bytes;
538
    return bytes;
506
  }
539
  }
507

    
   
540

   
508
  /**
541
  /**

    
   
542
   * Constructs KeyValue structure filled with specified values. Uses the provided buffer as its

    
   
543
   * backing data buffer.

    
   
544
   * <p>

    
   
545
   * Column is split into two fields, family and qualifier.

    
   
546
   *

    
   
547
   * @param buffer the bytes buffer to use

    
   
548
   * @param row row key

    
   
549
   * @param roffset row offset

    
   
550
   * @param rlength row length

    
   
551
   * @param family family name

    
   
552
   * @param foffset family offset

    
   
553
   * @param flength family length

    
   
554
   * @param qualifier column qualifier

    
   
555
   * @param qoffset qualifier offset

    
   
556
   * @param qlength qualifier length

    
   
557
   * @param timestamp version timestamp

    
   
558
   * @param type key type

    
   
559
   * @param value column value

    
   
560
   * @param voffset value offset

    
   
561
   * @param vlength value length

    
   
562
   * @throws IllegalArgumentException an illegal value was passed or there is insufficient space

    
   
563
   * remaining in the buffer

    
   
564
   */

    
   
565
  public KeyValue(byte [] buffer,

    
   
566
      final byte [] row, final int roffset, final int rlength,

    
   
567
      final byte [] family, final int foffset, final int flength,

    
   
568
      final byte [] qualifier, final int qoffset, final int qlength,

    
   
569
      final long timestamp, final Type type,

    
   
570
      final byte [] value, final int voffset, final int vlength) {

    
   
571

   

    
   
572
    this(buffer, 0,

    
   
573
        row, roffset, rlength,

    
   
574
        family, foffset, flength,

    
   
575
        qualifier, qoffset, qlength,

    
   
576
        timestamp, type,

    
   
577
        value, voffset, vlength);

    
   
578
  }

    
   
579

   

    
   
580
  /**
509
   * Constructs KeyValue structure filled with specified values. Uses the provided buffer as the
581
   * Constructs KeyValue structure filled with specified values. Uses the provided buffer as the
510
   * data buffer.
582
   * data buffer.
511
   * <p>
583
   * <p>
512
   * Column is split into two fields, family and qualifier.
584
   * Column is split into two fields, family and qualifier.
513
   *
585
   *
514
   * @param buffer the bytes buffer to use
586
   * @param buffer the bytes buffer to use

    
   
587
   * @param boffset buffer offset
515
   * @param row row key
588
   * @param row row key
516
   * @param roffset row offset
589
   * @param roffset row offset
517
   * @param rlength row length
590
   * @param rlength row length
518
   * @param family family name
591
   * @param family family name
519
   * @param foffset family offset
592
   * @param foffset family offset
[+20] [20] 4 lines
[+20] static byte[] createEmptyByteArray(final int rlength, int flength,
524
   * @param timestamp version timestamp
597
   * @param timestamp version timestamp
525
   * @param type key type
598
   * @param type key type
526
   * @param value column value
599
   * @param value column value
527
   * @param voffset value offset
600
   * @param voffset value offset
528
   * @param vlength value length
601
   * @param vlength value length
529
   * @throws IllegalArgumentException
602
   * @throws IllegalArgumentException an illegal value was passed or there is insufficient space

    
   
603
   * remaining in the buffer
530
   */
604
   */
531
  public KeyValue(byte [] buffer,
605
  public KeyValue(byte [] buffer, final int boffset,
532
                  final byte [] row, final int roffset, final int rlength,
606
      final byte [] row, final int roffset, final int rlength,
533
                  final byte [] family, final int foffset, final int flength,
607
      final byte [] family, final int foffset, final int flength,
534
                  final byte [] qualifier, final int qoffset, final int qlength,
608
      final byte [] qualifier, final int qoffset, final int qlength,
535
                  final long timestamp, final Type type,
609
      final long timestamp, final Type type,
536
                  final byte [] value, final int voffset, final int vlength) {
610
      final byte [] value, final int voffset, final int vlength) {
537

    
   
611

   
538
    this.bytes  = buffer;
612
    this.bytes  = buffer;
539
    this.length = writeByteArray(buffer, row, roffset, rlength,
613
    this.length = writeByteArray(buffer, boffset,

    
   
614
        row, roffset, rlength,
540
                                 family, foffset, flength, qualifier, qoffset, qlength,
615
        family, foffset, flength, qualifier, qoffset, qlength,
541
                                 timestamp, type, value, voffset, vlength);
616
        timestamp, type, value, voffset, vlength);
542
    this.offset = 0;
617
    this.offset = boffset;
543
  }
618
  }
544

    
   
619

   
545
  /**
620
  /**
546
   * Checks the parameters passed to a constructor.
621
   * Checks the parameters passed to a constructor.
547
   *
622
   *
[+20] [20] 29 lines
[+20] [+] private static void checkParameters(final byte [] row, final int rlength,
577
    qlength = qualifier == null ? 0 : qlength;
652
    qlength = qualifier == null ? 0 : qlength;
578
    if (qlength > Integer.MAX_VALUE - rlength - flength) {
653
    if (qlength > Integer.MAX_VALUE - rlength - flength) {
579
      throw new IllegalArgumentException("Qualifier > " + Integer.MAX_VALUE);
654
      throw new IllegalArgumentException("Qualifier > " + Integer.MAX_VALUE);
580
    }
655
    }
581
    // Key length
656
    // Key length
582
    long longKeyLength = KEY_INFRASTRUCTURE_SIZE + rlength + flength + qlength;
657
    long longKeyLength = getKeyDataStructureSize(rlength, flength, qlength);
583
    if (longKeyLength > Integer.MAX_VALUE) {
658
    if (longKeyLength > Integer.MAX_VALUE) {
584
      throw new IllegalArgumentException("keylength " + longKeyLength + " > " + Integer.MAX_VALUE);
659
      throw new IllegalArgumentException("keylength " + longKeyLength + " > " +

    
   
660
          Integer.MAX_VALUE);
585
    }
661
    }
586
    // Value length
662
    // Value length
587
    vlength = value == null? 0 : vlength;
663
    vlength = value == null? 0 : vlength;
588
    if (vlength > HConstants.MAXIMUM_VALUE_LENGTH) { // FindBugs INT_VACUOUS_COMPARISON
664
    if (vlength > HConstants.MAXIMUM_VALUE_LENGTH) { // FindBugs INT_VACUOUS_COMPARISON
589
      throw new IllegalArgumentException("Value > " + HConstants.MAXIMUM_VALUE_LENGTH);
665
      throw new IllegalArgumentException("Value length " + vlength + " > " +

    
   
666
          HConstants.MAXIMUM_VALUE_LENGTH);
590
    }
667
    }
591
  }
668
  }
592

    
   
669

   
593
  /**
670
  /**
594
   * Write KeyValue format into the provided byte array.
671
   * Write KeyValue format into the provided byte array.
595
   *
672
   *
596
   * @param buffer the bytes buffer to use
673
   * @param buffer the bytes buffer to use

    
   
674
   * @param boffset buffer offset
597
   * @param row row key
675
   * @param row row key
598
   * @param roffset row offset
676
   * @param roffset row offset
599
   * @param rlength row length
677
   * @param rlength row length
600
   * @param family family name
678
   * @param family family name
601
   * @param foffset family offset
679
   * @param foffset family offset
[+20] [20] 6 lines
[+20] private static void checkParameters(final byte [] row, final int rlength,
608
   * @param value column value
686
   * @param value column value
609
   * @param voffset value offset
687
   * @param voffset value offset
610
   * @param vlength value length
688
   * @param vlength value length
611
   *
689
   *
612
   * @return The number of useful bytes in the buffer.
690
   * @return The number of useful bytes in the buffer.

    
   
691
   *

    
   
692
   * @throws IllegalArgumentException an illegal value was passed or there is insufficient space

    
   
693
   * remaining in the buffer
613
   */
694
   */
614
  static int writeByteArray(byte [] buffer,
695
  static int writeByteArray(byte [] buffer, final int boffset,
615
                            final byte [] row, final int roffset, final int rlength,
696
      final byte [] row, final int roffset, final int rlength,
616
                            final byte [] family, final int foffset, int flength,
697
      final byte [] family, final int foffset, int flength,
617
                            final byte [] qualifier, final int qoffset, int qlength,
698
      final byte [] qualifier, final int qoffset, int qlength,
618
                            final long timestamp, final Type type,
699
      final long timestamp, final Type type,
619
                            final byte [] value, final int voffset, int vlength) {
700
      final byte [] value, final int voffset, int vlength) {
620

    
   
701

   
621
    checkParameters(row, rlength, family, flength, qualifier, qlength, value, vlength);
702
    checkParameters(row, rlength, family, flength, qualifier, qlength, value, vlength);
622

    
   
703

   
623
    int keyLength = KEY_INFRASTRUCTURE_SIZE + rlength + flength + qlength;
704
    int keyLength = (int) getKeyDataStructureSize(rlength, flength, qlength);
624
    int keyValueLength = KEYVALUE_INFRASTRUCTURE_SIZE + keyLength + vlength;
705
    int keyValueLength = (int) getKeyValueDataStructureSize(rlength, flength, qlength, vlength);
625
    if (keyValueLength > buffer.length) {
706
    if (keyValueLength > buffer.length - boffset) {
626
      throw new IllegalArgumentException("Buffer size " + buffer.length + " < " + keyValueLength);
707
      throw new IllegalArgumentException("Buffer size " + (buffer.length - boffset) + " < " +

    
   
708
          keyValueLength);
627
    }
709
    }
628

    
   
710

   
629
    // Write key, value and key row length.
711
    // Write key, value and key row length.
630
    int pos = 0;
712
    int pos = boffset;
631
    pos = Bytes.putInt(buffer, pos, keyLength);
713
    pos = Bytes.putInt(buffer, pos, keyLength);
632
    pos = Bytes.putInt(buffer, pos, vlength);
714
    pos = Bytes.putInt(buffer, pos, vlength);
633
    pos = Bytes.putShort(buffer, pos, (short)(rlength & 0x0000ffff));
715
    pos = Bytes.putShort(buffer, pos, (short)(rlength & 0x0000ffff));
634
    pos = Bytes.putBytes(buffer, pos, row, roffset, rlength);
716
    pos = Bytes.putBytes(buffer, pos, row, roffset, rlength);
635
    pos = Bytes.putByte(buffer, pos, (byte) (flength & 0x0000ff));
717
    pos = Bytes.putByte(buffer, pos, (byte) (flength & 0x0000ff));
[+20] [20] 38 lines
[+20] static int writeByteArray(byte [] buffer, [+] static int writeByteArray(byte [] buffer, final int boffset,
674
      final byte [] value, final int voffset, int vlength) {
756
      final byte [] value, final int voffset, int vlength) {
675

    
   
757

   
676
    checkParameters(row, rlength, family, flength, qualifier, qlength, value, vlength);
758
    checkParameters(row, rlength, family, flength, qualifier, qlength, value, vlength);
677

    
   
759

   
678
    // Allocate right-sized byte array.
760
    // Allocate right-sized byte array.
679
    int keyLength = KEY_INFRASTRUCTURE_SIZE + rlength + flength + qlength;
761
    int keyLength = (int) getKeyDataStructureSize(rlength, flength, qlength);
680
    byte [] bytes = new byte[KEYVALUE_INFRASTRUCTURE_SIZE + keyLength + vlength];
762
    byte [] bytes =

    
   
763
        new byte[(int) getKeyValueDataStructureSize(rlength, flength, qlength, vlength)];
681
    // Write key, value and key row length.
764
    // Write key, value and key row length.
682
    int pos = 0;
765
    int pos = 0;
683
    pos = Bytes.putInt(bytes, pos, keyLength);
766
    pos = Bytes.putInt(bytes, pos, keyLength);
684
    pos = Bytes.putInt(bytes, pos, vlength);
767
    pos = Bytes.putInt(bytes, pos, vlength);
685
    pos = Bytes.putShort(bytes, pos, (short)(rlength & 0x0000ffff));
768
    pos = Bytes.putShort(bytes, pos, (short)(rlength & 0x0000ffff));
[+20] [20] 342 lines
[+20] [+] public int getQualifierLength() {
1028

    
   
1111

   
1029
  /**
1112
  /**
1030
   * @return Qualifier length
1113
   * @return Qualifier length
1031
   */
1114
   */
1032
  public int getQualifierLength(int rlength, int flength) {
1115
  public int getQualifierLength(int rlength, int flength) {
1033
    return getKeyLength() -
1116
    return getKeyLength() - (int) getKeyDataStructureSize(rlength, flength, 0);
1034
      (KEY_INFRASTRUCTURE_SIZE + rlength + flength);

   
1035
  }
1117
  }
1036

    
   
1118

   
1037
  /**
1119
  /**
1038
   * @return Column (family + qualifier) length
1120
   * @return Column (family + qualifier) length
1039
   */
1121
   */
[+20] [20] 83 lines
[+20] [+] public boolean updateLatestStamp(final byte [] now) {
1123
    System.arraycopy(getBuffer(), o, result, 0, l);
1205
    System.arraycopy(getBuffer(), o, result, 0, l);
1124
    return result;
1206
    return result;
1125
  }
1207
  }
1126

    
   
1208

   
1127
  /**
1209
  /**

    
   
1210
   * Returns the value wrapped in a new <code>ByteBuffer</code>.

    
   
1211
   *

    
   
1212
   * @return the value

    
   
1213
   */

    
   
1214
  public ByteBuffer getValueAsByteBuffer() {

    
   
1215
    return ByteBuffer.wrap(getBuffer(), getValueOffset(), getValueLength());

    
   
1216
  }

    
   
1217

   

    
   
1218
  /**
1128
   * Loads this object's value into the provided <code>ByteBuffer</code>.
1219
   * Loads this object's value into the provided <code>ByteBuffer</code>.
1129
   * <p>
1220
   * <p>
1130
   * Does not clear or flip the buffer.
1221
   * Does not clear or flip the buffer.
1131
   *
1222
   *
1132
   * @param dst the buffer where to write the value
1223
   * @param dst the buffer where to write the value
1133
   *
1224
   *
1134
   * @throws BufferOverflowException there is insufficient space remaining in the buffer
1225
   * @throws BufferOverflowException if there is insufficient space remaining in the buffer
1135
   */
1226
   */
1136
  public void loadValue(ByteBuffer dst)
1227
  public void loadValue(ByteBuffer dst) throws BufferOverflowException {
1137
          throws BufferOverflowException {

   
1138
    dst.put(getBuffer(), getValueOffset(), getValueLength());
1228
    dst.put(getBuffer(), getValueOffset(), getValueLength());
1139
  }
1229
  }
1140

    
   
1230

   
1141
  /**
1231
  /**
1142
   * Primarily for use client-side.  Returns the row of this KeyValue in a new
1232
   * Primarily for use client-side.  Returns the row of this KeyValue in a new
[+20] [20] 264 lines
[+20] [+] public boolean matchingColumnNoDelimiter(final byte [] column) {
1407
   * @param family column family
1497
   * @param family column family
1408
   * @param qualifier column qualifier
1498
   * @param qualifier column qualifier
1409
   * @return True if column matches
1499
   * @return True if column matches
1410
   */
1500
   */
1411
  public boolean matchingColumn(final byte[] family, final byte[] qualifier) {
1501
  public boolean matchingColumn(final byte[] family, final byte[] qualifier) {
1412
    int rl = getRowLength();
1502
    return matchingColumn(family, 0, family == null ? 0 : family.length,
1413
    int o = getFamilyOffset(rl);
1503
        qualifier, 0, qualifier == null ? 0 : qualifier.length);
1414
    int fl = getFamilyLength(o);

   
1415
    int ql = getQualifierLength(rl,fl);

   
1416
    if (!Bytes.equals(family, 0, family.length, this.bytes, o, fl)) {

   
1417
      return false;

   
1418
    }

   
1419
    if (qualifier == null || qualifier.length == 0) {

   
1420
      if (ql == 0) {

   
1421
        return true;

   
1422
      }

   
1423
      return false;

   
1424
    }

   
1425
    return Bytes.equals(qualifier, 0, qualifier.length,

   
1426
        this.bytes, o + fl, ql);

   
1427
  }
1504
  }
1428

    
   
1505

   
1429
  /**
1506
  /**
1430
   * Checks if column matches.
1507
   * Checks if column matches.
1431
   *
1508
   *
[+20] [20] 4 lines
[+20] public boolean matchingColumnNoDelimiter(final byte [] column) {
1436
   * @param qoffset qualifier offset
1513
   * @param qoffset qualifier offset
1437
   * @param qlength qualifier length
1514
   * @param qlength qualifier length
1438
   *
1515
   *
1439
   * @return True if column matches
1516
   * @return True if column matches
1440
   */
1517
   */
1441
  public boolean matchingColumn(final byte [] family,    final int foffset, final int flength,
1518
  public boolean matchingColumn(final byte [] family, final int foffset, final int flength,
1442
                                final byte [] qualifier, final int qoffset, final int qlength) {
1519
      final byte [] qualifier, final int qoffset, final int qlength) {
1443
    int rl = getRowLength();
1520
    int rl = getRowLength();
1444
    int o  = getFamilyOffset(rl);
1521
    int o = getFamilyOffset(rl);
1445
    int fl = getFamilyLength(o);
1522
    int fl = getFamilyLength(o);
1446
    int ql = getQualifierLength(rl,fl);

   
1447

    
   

   
1448
    if (!Bytes.equals(family, foffset, flength, this.bytes, o, fl)) {
1523
    if (!Bytes.equals(family, foffset, flength, this.bytes, o, fl)) {
1449
      return false;
1524
      return false;
1450
    }
1525
    }

    
   
1526

   

    
   
1527
    int ql = getQualifierLength(rl, fl);
1451
    if (qualifier == null || qlength == 0) {
1528
    if (qualifier == null || qlength == 0) {
1452
      return (ql == 0);
1529
      return (ql == 0);
1453
    }
1530
    }
1454
    return Bytes.equals(qualifier, qoffset, qlength, this.bytes, o + fl, ql);
1531
    return Bytes.equals(qualifier, qoffset, qlength, this.bytes, o + fl, ql);
1455
  }
1532
  }
[+20] [20] 521 lines
[+20] [+] public static KeyValue createFirstOnRow(final byte [] row,
1977
    return new KeyValue(row, roffset, rlength, family,
2054
    return new KeyValue(row, roffset, rlength, family,
1978
        foffset, flength, qualifier, qoffset, qlength,
2055
        foffset, flength, qualifier, qoffset, qlength,
1979
        HConstants.LATEST_TIMESTAMP, Type.Maximum, null, 0, 0);
2056
        HConstants.LATEST_TIMESTAMP, Type.Maximum, null, 0, 0);
1980
  }
2057
  }
1981

    
   
2058

   
1982

    
   

   
1983
  /**
2059
  /**
1984
   * Create a KeyValue for the specified row, family and qualifier that would be
2060
   * Create a KeyValue for the specified row, family and qualifier that would be
1985
   * smaller than all other possible KeyValues that have the same row,
2061
   * smaller than all other possible KeyValues that have the same row,
1986
   * family, qualifier.
2062
   * family, qualifier.
1987
   * Used for seeking.
2063
   * Used for seeking.
[+20] [20] 10 lines
[+20] public static KeyValue createFirstOnRow(final byte [] row,
1998
   */
2074
   */
1999
  public static KeyValue createFirstOnRow(byte [] buffer, final byte [] row,
2075
  public static KeyValue createFirstOnRow(byte [] buffer, final byte [] row,
2000
                                          final byte [] family, final byte [] qualifier)
2076
      final byte [] family, final byte [] qualifier)
2001
          throws IllegalArgumentException {
2077
          throws IllegalArgumentException {
2002

    
   
2078

   
2003
    return createFirstOnRow(buffer, row, family, 0, family.length, qualifier, 0, qualifier.length);
2079
    return createFirstOnRow(buffer, 0, row, 0, row.length,

    
   
2080
        family, 0, family.length,

    
   
2081
        qualifier, 0, qualifier.length);
2004
  }
2082
  }
2005

    
   
2083

   
2006
  /**
2084
  /**
2007
   * Create a KeyValue for the specified row, family and qualifier that would be
2085
   * Create a KeyValue for the specified row, family and qualifier that would be
2008
   * smaller than all other possible KeyValues that have the same row,
2086
   * smaller than all other possible KeyValues that have the same row,
2009
   * family, qualifier.
2087
   * family, qualifier.
2010
   * Used for seeking.
2088
   * Used for seeking.
2011
   *
2089
   *
2012
   * @param buffer the buffer to use for the new <code>KeyValue</code> object
2090
   * @param buffer the buffer to use for the new <code>KeyValue</code> object

    
   
2091
   * @param boffset buffer offset
2013
   * @param row the value key
2092
   * @param row the value key

    
   
2093
   * @param roffset row offset

    
   
2094
   * @param rlength row length
2014
   * @param family family name
2095
   * @param family family name
2015
   * @param foffset family offset
2096
   * @param foffset family offset
2016
   * @param flength family length
2097
   * @param flength family length
2017
   * @param qualifier column qualifier
2098
   * @param qualifier column qualifier
2018
   * @param qoffset qualifier offset
2099
   * @param qoffset qualifier offset
2019
   * @param qlength qualifier length
2100
   * @param qlength qualifier length
2020
   *
2101
   *
2021
   * @return First possible key on passed Row, Family, Qualifier.
2102
   * @return First possible key on passed Row, Family, Qualifier.
2022
   *
2103
   *
2023
   * @throws IllegalArgumentException The resulting <code>KeyValue</code> object would be larger
2104
   * @throws IllegalArgumentException The resulting <code>KeyValue</code> object would be larger
2024
   * than the provided buffer or than <code>Integer.MAX_VALUE</code>
2105
   * than the provided buffer or than <code>Integer.MAX_VALUE</code>
2025
   */
2106
   */
2026
  public static KeyValue createFirstOnRow(byte [] buffer, final byte [] row,
2107
  public static KeyValue createFirstOnRow(byte [] buffer, final int boffset,
2027
      final byte [] family,    final int foffset, final int flength,
2108
      final byte [] row, final int roffset, final int rlength,

    
   
2109
      final byte [] family, final int foffset, final int flength,
2028
      final byte [] qualifier, final int qoffset, final int qlength)
2110
      final byte [] qualifier, final int qoffset, final int qlength)
2029
          throws IllegalArgumentException {
2111
          throws IllegalArgumentException {
2030

    
   
2112

   
2031
    long lLength = KeyValue.KEY_INFRASTRUCTURE_SIZE +
2113
    long lLength = getKeyValueDataStructureSize(rlength, flength, qlength, 0);
2032
                   row.length + flength + qlength +

   
2033
                   KeyValue.KEYVALUE_INFRASTRUCTURE_SIZE;

   
2034

    
   
2114

   
2035
    if (lLength > Integer.MAX_VALUE) {
2115
    if (lLength > Integer.MAX_VALUE) {
2036
      throw new IllegalArgumentException("KeyValue length " + lLength + " > " + Integer.MAX_VALUE);
2116
      throw new IllegalArgumentException("KeyValue length " + lLength + " > " + Integer.MAX_VALUE);
2037
    }
2117
    }
2038
    int iLength = (int) lLength;
2118
    int iLength = (int) lLength;
2039
    if (buffer.length < iLength) {
2119
    if (buffer.length - boffset < iLength) {
2040
      throw new IllegalArgumentException("Buffer size " + buffer.length + " < " + iLength);
2120
      throw new IllegalArgumentException("Buffer size " + (buffer.length - boffset) + " < " +

    
   
2121
          iLength);
2041
    }
2122
    }
2042
    return new KeyValue(buffer,
2123
    return new KeyValue(buffer, boffset,
2043
                        row, 0, row.length,
2124
        row, roffset, rlength,
2044
                        family, foffset, flength,
2125
        family, foffset, flength,
2045
                        qualifier, qoffset, qlength,
2126
        qualifier, qoffset, qlength,
2046
                        HConstants.LATEST_TIMESTAMP, KeyValue.Type.Maximum,
2127
        HConstants.LATEST_TIMESTAMP, KeyValue.Type.Maximum,
2047
                        null, 0, 0);
2128
        null, 0, 0);
2048
  }
2129
  }
[+20] [20] 412 lines
[+20] [+] public long heapSize() {
2461

    
   
2542

   
2462
  // this overload assumes that the length bytes have already been read,
2543
  // this overload assumes that the length bytes have already been read,
2463
  // and it expects the length of the KeyValue to be explicitly passed
2544
  // and it expects the length of the KeyValue to be explicitly passed
2464
  // to it.
2545
  // to it.
2465
  public void readFields(int length, final DataInput in) throws IOException {
2546
  public void readFields(int length, final DataInput in) throws IOException {

    
   
2547
    this.rowCache = null;
2466
    this.length = length;
2548
    this.length = length;
2467
    this.offset = 0;
2549
    this.offset = 0;
2468
    this.bytes = new byte[this.length];
2550
    this.bytes = new byte[this.length];
2469
    in.readFully(this.bytes, 0, this.length);
2551
    in.readFully(this.bytes, 0, this.length);
2470
  }
2552
  }
[+20] [20] 12 lines
src/main/java/org/apache/hadoop/hbase/client/Result.java
Diff Revision 1 Diff Revision 4
 
src/test/java/org/apache/hadoop/hbase/TestKeyValue.java
Diff Revision 1 Diff Revision 4
 
src/test/java/org/apache/hadoop/hbase/client/TestResult.java
Diff Revision 1 Diff Revision 4
 
  1. src/main/java/org/apache/hadoop/hbase/KeyValue.java: Loading...
  2. src/main/java/org/apache/hadoop/hbase/client/Result.java: Loading...
  3. src/test/java/org/apache/hadoop/hbase/TestKeyValue.java: Loading...
  4. src/test/java/org/apache/hadoop/hbase/client/TestResult.java: Loading...