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.

Diff revision 1

This is not the most recent revision of the diff. The latest diff is revision 4. See what's changed.

1 2 3 4
1 2 3 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/client/TestResult.java: Loading...
src/main/java/org/apache/hadoop/hbase/KeyValue.java
Revision 243d76f New Change
1
/**
1
/**
2
 * Copyright 2009 The Apache Software Foundation
2
 * Copyright 2009 The Apache Software Foundation
3
 *
3
 *
4
 * Licensed to the Apache Software Foundation (ASF) under one
4
 * Licensed to the Apache Software Foundation (ASF) under one
5
 * or more contributor license agreements.  See the NOTICE file
5
 * or more contributor license agreements.  See the NOTICE file
6
 * distributed with this work for additional information
6
 * distributed with this work for additional information
7
 * regarding copyright ownership.  The ASF licenses this file
7
 * regarding copyright ownership.  The ASF licenses this file
8
 * to you under the Apache License, Version 2.0 (the
8
 * to you under the Apache License, Version 2.0 (the
9
 * "License"); you may not use this file except in compliance
9
 * "License"); you may not use this file except in compliance
10
 * with the License.  You may obtain a copy of the License at
10
 * with the License.  You may obtain a copy of the License at
11
 *
11
 *
12
 *     http://www.apache.org/licenses/LICENSE-2.0
12
 *     http://www.apache.org/licenses/LICENSE-2.0
13
 *
13
 *
14
 * Unless required by applicable law or agreed to in writing, software
14
 * Unless required by applicable law or agreed to in writing, software
15
 * distributed under the License is distributed on an "AS IS" BASIS,
15
 * distributed under the License is distributed on an "AS IS" BASIS,
16
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
 * See the License for the specific language governing permissions and
17
 * See the License for the specific language governing permissions and
18
 * limitations under the License.
18
 * limitations under the License.
19
 */
19
 */
20
package org.apache.hadoop.hbase;
20
package org.apache.hadoop.hbase;
21

    
   
21

   
22
import java.io.DataInput;
22
import java.io.DataInput;
23
import java.io.DataOutput;
23
import java.io.DataOutput;
24
import java.io.IOException;
24
import java.io.IOException;

    
   
25
import java.nio.BufferOverflowException;
25
import java.nio.ByteBuffer;
26
import java.nio.ByteBuffer;
26
import java.util.Comparator;
27
import java.util.Comparator;
27
import java.util.HashMap;
28
import java.util.HashMap;
28
import java.util.Map;
29
import java.util.Map;
29

    
   
30

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

    
   
42

   
42
/**
43
/**
43
 * An HBase Key/Value.  This is the fundamental HBase Type.
44
 * An HBase Key/Value.  This is the fundamental HBase Type.
44
 *
45
 *
45
 * <p>If being used client-side, the primary methods to access individual fields
46
 * <p>If being used client-side, the primary methods to access individual fields
46
 * are {@link #getRow()}, {@link #getFamily()}, {@link #getQualifier()},
47
 * are {@link #getRow()}, {@link #getFamily()}, {@link #getQualifier()},
47
 * {@link #getTimestamp()}, and {@link #getValue()}.  These methods allocate new
48
 * {@link #getTimestamp()}, and {@link #getValue()}.  These methods allocate new
48
 * byte arrays and return copies. Avoid their use server-side.
49
 * byte arrays and return copies. Avoid their use server-side.
49
 *
50
 *
50
 * <p>Instances of this class are immutable.  They do not implement Comparable
51
 * <p>Instances of this class are immutable.  They do not implement Comparable
51
 * but Comparators are provided.  Comparators change with context,
52
 * but Comparators are provided.  Comparators change with context,
52
 * whether user table or a catalog table comparison.  Its critical you use the
53
 * whether user table or a catalog table comparison.  Its critical you use the
53
 * appropriate comparator.  There are Comparators for KeyValue instances and
54
 * appropriate comparator.  There are Comparators for KeyValue instances and
54
 * then for just the Key portion of a KeyValue used mostly by {@link HFile}.
55
 * then for just the Key portion of a KeyValue used mostly by {@link HFile}.
55
 *
56
 *
56
 * <p>KeyValue wraps a byte array and takes offsets and lengths into passed
57
 * <p>KeyValue wraps a byte array and takes offsets and lengths into passed
57
 * array at where to start interpreting the content as KeyValue.  The KeyValue
58
 * array at where to start interpreting the content as KeyValue.  The KeyValue
58
 * format inside a byte array is:
59
 * format inside a byte array is:
59
 * <code>&lt;keylength> &lt;valuelength> &lt;key> &lt;value></code>
60
 * <code>&lt;keylength> &lt;valuelength> &lt;key> &lt;value></code>
60
 * Key is further decomposed as:
61
 * Key is further decomposed as:
61
 * <code>&lt;rowlength> &lt;row> &lt;columnfamilylength> &lt;columnfamily> &lt;columnqualifier> &lt;timestamp> &lt;keytype></code>
62
 * <code>&lt;rowlength> &lt;row> &lt;columnfamilylength> &lt;columnfamily> &lt;columnqualifier> &lt;timestamp> &lt;keytype></code>
62
 * The <code>rowlength</code> maximum is <code>Short.MAX_SIZE</code>,
63
 * The <code>rowlength</code> maximum is <code>Short.MAX_SIZE</code>,
63
 * column family length maximum is
64
 * column family length maximum is
64
 * <code>Byte.MAX_SIZE</code>, and column qualifier + key length must
65
 * <code>Byte.MAX_SIZE</code>, and column qualifier + key length must
65
 * be < <code>Integer.MAX_SIZE</code>.
66
 * be < <code>Integer.MAX_SIZE</code>.
66
 * The column does not contain the family/qualifier delimiter, {@link #COLUMN_FAMILY_DELIMITER}
67
 * The column does not contain the family/qualifier delimiter, {@link #COLUMN_FAMILY_DELIMITER}
67
 */
68
 */
68
@InterfaceAudience.Public
69
@InterfaceAudience.Public
69
@InterfaceStability.Evolving
70
@InterfaceStability.Evolving
70
public class KeyValue implements Writable, HeapSize {
71
public class KeyValue implements Writable, HeapSize {
71
  static final Log LOG = LogFactory.getLog(KeyValue.class);
72
  static final Log LOG = LogFactory.getLog(KeyValue.class);
72
  // TODO: Group Key-only comparators and operations into a Key class, just
73
  // TODO: Group Key-only comparators and operations into a Key class, just
73
  // for neatness sake, if can figure what to call it.
74
  // for neatness sake, if can figure what to call it.
74

    
   
75

   
75
  /**
76
  /**
76
   * Colon character in UTF-8
77
   * Colon character in UTF-8
77
   */
78
   */
78
  public static final char COLUMN_FAMILY_DELIMITER = ':';
79
  public static final char COLUMN_FAMILY_DELIMITER = ':';
79

    
   
80

   
80
  public static final byte[] COLUMN_FAMILY_DELIM_ARRAY =
81
  public static final byte[] COLUMN_FAMILY_DELIM_ARRAY =
81
    new byte[]{COLUMN_FAMILY_DELIMITER};
82
    new byte[]{COLUMN_FAMILY_DELIMITER};
82

    
   
83

   
83
  /**
84
  /**
84
   * Comparator for plain key/values; i.e. non-catalog table key/values.
85
   * Comparator for plain key/values; i.e. non-catalog table key/values.
85
   */
86
   */
86
  public static KVComparator COMPARATOR = new KVComparator();
87
  public static KVComparator COMPARATOR = new KVComparator();
87

    
   
88

   
88
  /**
89
  /**
89
   * Comparator for plain key; i.e. non-catalog table key.  Works on Key portion
90
   * Comparator for plain key; i.e. non-catalog table key.  Works on Key portion
90
   * of KeyValue only.
91
   * of KeyValue only.
91
   */
92
   */
92
  public static KeyComparator KEY_COMPARATOR = new KeyComparator();
93
  public static KeyComparator KEY_COMPARATOR = new KeyComparator();
93

    
   
94

   
94
  /**
95
  /**
95
   * A {@link KVComparator} for <code>.META.</code> catalog table
96
   * A {@link KVComparator} for <code>.META.</code> catalog table
96
   * {@link KeyValue}s.
97
   * {@link KeyValue}s.
97
   */
98
   */
98
  public static KVComparator META_COMPARATOR = new MetaComparator();
99
  public static KVComparator META_COMPARATOR = new MetaComparator();
99

    
   
100

   
100
  /**
101
  /**
101
   * A {@link KVComparator} for <code>.META.</code> catalog table
102
   * A {@link KVComparator} for <code>.META.</code> catalog table
102
   * {@link KeyValue} keys.
103
   * {@link KeyValue} keys.
103
   */
104
   */
104
  public static KeyComparator META_KEY_COMPARATOR = new MetaKeyComparator();
105
  public static KeyComparator META_KEY_COMPARATOR = new MetaKeyComparator();
105

    
   
106

   
106
  /**
107
  /**
107
   * A {@link KVComparator} for <code>-ROOT-</code> catalog table
108
   * A {@link KVComparator} for <code>-ROOT-</code> catalog table
108
   * {@link KeyValue}s.
109
   * {@link KeyValue}s.
109
   */
110
   */
110
  public static KVComparator ROOT_COMPARATOR = new RootComparator();
111
  public static KVComparator ROOT_COMPARATOR = new RootComparator();
111

    
   
112

   
112
  /**
113
  /**
113
   * A {@link KVComparator} for <code>-ROOT-</code> catalog table
114
   * A {@link KVComparator} for <code>-ROOT-</code> catalog table
114
   * {@link KeyValue} keys.
115
   * {@link KeyValue} keys.
115
   */
116
   */
116
  public static KeyComparator ROOT_KEY_COMPARATOR = new RootKeyComparator();
117
  public static KeyComparator ROOT_KEY_COMPARATOR = new RootKeyComparator();
117

    
   
118

   
118
  /**
119
  /**
119
   * Get the appropriate row comparator for the specified table.
120
   * Get the appropriate row comparator for the specified table.
120
   *
121
   *
121
   * Hopefully we can get rid of this, I added this here because it's replacing
122
   * Hopefully we can get rid of this, I added this here because it's replacing
122
   * something in HSK.  We should move completely off of that.
123
   * something in HSK.  We should move completely off of that.
123
   *
124
   *
124
   * @param tableName  The table name.
125
   * @param tableName  The table name.
125
   * @return The comparator.
126
   * @return The comparator.
126
   */
127
   */
127
  public static KeyComparator getRowComparator(byte [] tableName) {
128
  public static KeyComparator getRowComparator(byte [] tableName) {
128
    if(Bytes.equals(HTableDescriptor.ROOT_TABLEDESC.getName(),tableName)) {
129
    if(Bytes.equals(HTableDescriptor.ROOT_TABLEDESC.getName(),tableName)) {
129
      return ROOT_COMPARATOR.getRawComparator();
130
      return ROOT_COMPARATOR.getRawComparator();
130
    }
131
    }
131
    if(Bytes.equals(HTableDescriptor.META_TABLEDESC.getName(), tableName)) {
132
    if(Bytes.equals(HTableDescriptor.META_TABLEDESC.getName(), tableName)) {
132
      return META_COMPARATOR.getRawComparator();
133
      return META_COMPARATOR.getRawComparator();
133
    }
134
    }
134
    return COMPARATOR.getRawComparator();
135
    return COMPARATOR.getRawComparator();
135
  }
136
  }
136

    
   
137

   
137
  /** Size of the key length field in bytes*/
138
  /** Size of the key length field in bytes*/
138
  public static final int KEY_LENGTH_SIZE = Bytes.SIZEOF_INT;
139
  public static final int KEY_LENGTH_SIZE = Bytes.SIZEOF_INT;
139

    
   
140

   
140
  /** Size of the key type field in bytes */
141
  /** Size of the key type field in bytes */
141
  public static final int TYPE_SIZE = Bytes.SIZEOF_BYTE;
142
  public static final int TYPE_SIZE = Bytes.SIZEOF_BYTE;
142

    
   
143

   
143
  /** Size of the row length field in bytes */
144
  /** Size of the row length field in bytes */
144
  public static final int ROW_LENGTH_SIZE = Bytes.SIZEOF_SHORT;
145
  public static final int ROW_LENGTH_SIZE = Bytes.SIZEOF_SHORT;
145

    
   
146

   
146
  /** Size of the family length field in bytes */
147
  /** Size of the family length field in bytes */
147
  public static final int FAMILY_LENGTH_SIZE = Bytes.SIZEOF_BYTE;
148
  public static final int FAMILY_LENGTH_SIZE = Bytes.SIZEOF_BYTE;
148

    
   
149

   
149
  /** Size of the timestamp field in bytes */
150
  /** Size of the timestamp field in bytes */
150
  public static final int TIMESTAMP_SIZE = Bytes.SIZEOF_LONG;
151
  public static final int TIMESTAMP_SIZE = Bytes.SIZEOF_LONG;
151

    
   
152

   
152
  // Size of the timestamp and type byte on end of a key -- a long + a byte.
153
  // Size of the timestamp and type byte on end of a key -- a long + a byte.
153
  public static final int TIMESTAMP_TYPE_SIZE = TIMESTAMP_SIZE + TYPE_SIZE;
154
  public static final int TIMESTAMP_TYPE_SIZE = TIMESTAMP_SIZE + TYPE_SIZE;
154

    
   
155

   
155
  // Size of the length shorts and bytes in key.
156
  // Size of the length shorts and bytes in key.
156
  public static final int KEY_INFRASTRUCTURE_SIZE = ROW_LENGTH_SIZE
157
  public static final int KEY_INFRASTRUCTURE_SIZE = ROW_LENGTH_SIZE
157
      + FAMILY_LENGTH_SIZE + TIMESTAMP_TYPE_SIZE;
158
      + FAMILY_LENGTH_SIZE + TIMESTAMP_TYPE_SIZE;
158

    
   
159

   
159
  // How far into the key the row starts at. First thing to read is the short
160
  // How far into the key the row starts at. First thing to read is the short
160
  // that says how long the row is.
161
  // that says how long the row is.
161
  public static final int ROW_OFFSET =
162
  public static final int ROW_OFFSET =
162
    Bytes.SIZEOF_INT /*keylength*/ +
163
    Bytes.SIZEOF_INT /*keylength*/ +
163
    Bytes.SIZEOF_INT /*valuelength*/;
164
    Bytes.SIZEOF_INT /*valuelength*/;
164

    
   
165

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

    
   
168

   
168
  /**
169
  /**
169
   * Key type.
170
   * Key type.
170
   * Has space for other key types to be added later.  Cannot rely on
171
   * Has space for other key types to be added later.  Cannot rely on
171
   * enum ordinals . They change if item is removed or moved.  Do our own codes.
172
   * enum ordinals . They change if item is removed or moved.  Do our own codes.
172
   */
173
   */
173
  public static enum Type {
174
  public static enum Type {
174
    Minimum((byte)0),
175
    Minimum((byte)0),
175
    Put((byte)4),
176
    Put((byte)4),
176

    
   
177

   
177
    Delete((byte)8),
178
    Delete((byte)8),
178
    DeleteColumn((byte)12),
179
    DeleteColumn((byte)12),
179
    DeleteFamily((byte)14),
180
    DeleteFamily((byte)14),
180

    
   
181

   
181
    // Maximum is used when searching; you look from maximum on down.
182
    // Maximum is used when searching; you look from maximum on down.
182
    Maximum((byte)255);
183
    Maximum((byte)255);
183

    
   
184

   
184
    private final byte code;
185
    private final byte code;
185

    
   
186

   
186
    Type(final byte c) {
187
    Type(final byte c) {
187
      this.code = c;
188
      this.code = c;
188
    }
189
    }
189

    
   
190

   
190
    public byte getCode() {
191
    public byte getCode() {
191
      return this.code;
192
      return this.code;
192
    }
193
    }
193

    
   
194

   
194
    /**
195
    /**
195
     * Cannot rely on enum ordinals . They change if item is removed or moved.
196
     * Cannot rely on enum ordinals . They change if item is removed or moved.
196
     * Do our own codes.
197
     * Do our own codes.
197
     * @param b
198
     * @param b
198
     * @return Type associated with passed code.
199
     * @return Type associated with passed code.
199
     */
200
     */
200
    public static Type codeToType(final byte b) {
201
    public static Type codeToType(final byte b) {
201
      for (Type t : Type.values()) {
202
      for (Type t : Type.values()) {
202
        if (t.getCode() == b) {
203
        if (t.getCode() == b) {
203
          return t;
204
          return t;
204
        }
205
        }
205
      }
206
      }
206
      throw new RuntimeException("Unknown code " + b);
207
      throw new RuntimeException("Unknown code " + b);
207
    }
208
    }
208
  }
209
  }
209

    
   
210

   
210
  /**
211
  /**
211
   * Lowest possible key.
212
   * Lowest possible key.
212
   * Makes a Key with highest possible Timestamp, empty row and column.  No
213
   * Makes a Key with highest possible Timestamp, empty row and column.  No
213
   * key can be equal or lower than this one in memstore or in store file.
214
   * key can be equal or lower than this one in memstore or in store file.
214
   */
215
   */
215
  public static final KeyValue LOWESTKEY =
216
  public static final KeyValue LOWESTKEY =
216
    new KeyValue(HConstants.EMPTY_BYTE_ARRAY, HConstants.LATEST_TIMESTAMP);
217
    new KeyValue(HConstants.EMPTY_BYTE_ARRAY, HConstants.LATEST_TIMESTAMP);
217

    
   
218

   
218
  private byte [] bytes = null;
219
  private byte [] bytes = null;
219
  private int offset = 0;
220
  private int offset = 0;
220
  private int length = 0;
221
  private int length = 0;
221

    
   
222

   
222
  // the row cached
223
  // the row cached
223
  private volatile byte [] rowCache = null;
224
  private volatile byte [] rowCache = null;
224

    
   
225

   
225
  /**
226
  /**
226
   * @return True if a delete type, a {@link KeyValue.Type#Delete} or
227
   * @return True if a delete type, a {@link KeyValue.Type#Delete} or
227
   * a {KeyValue.Type#DeleteFamily} or a {@link KeyValue.Type#DeleteColumn}
228
   * a {KeyValue.Type#DeleteFamily} or a {@link KeyValue.Type#DeleteColumn}
228
   * KeyValue type.
229
   * KeyValue type.
229
   */
230
   */
230
  public static boolean isDelete(byte t) {
231
  public static boolean isDelete(byte t) {
231
    return Type.Delete.getCode() <= t && t <= Type.DeleteFamily.getCode();
232
    return Type.Delete.getCode() <= t && t <= Type.DeleteFamily.getCode();
232
  }
233
  }
233

    
   
234

   
234
  /** Here be dragons **/
235
  /** Here be dragons **/
235

    
   
236

   
236
  // used to achieve atomic operations in the memstore.
237
  // used to achieve atomic operations in the memstore.
237
  public long getMemstoreTS() {
238
  public long getMemstoreTS() {
238
    return memstoreTS;
239
    return memstoreTS;
239
  }
240
  }
240

    
   
241

   
241
  public void setMemstoreTS(long memstoreTS) {
242
  public void setMemstoreTS(long memstoreTS) {
242
    this.memstoreTS = memstoreTS;
243
    this.memstoreTS = memstoreTS;
243
  }
244
  }
244

    
   
245

   
245
  // default value is 0, aka DNC
246
  // default value is 0, aka DNC
246
  private long memstoreTS = 0;
247
  private long memstoreTS = 0;
247

    
   
248

   
248
  /** Dragon time over, return to normal business */
249
  /** Dragon time over, return to normal business */
249

    
   
250

   
250

    
   
251

   
251
  /** Writable Constructor -- DO NOT USE */
252
  /** Writable Constructor -- DO NOT USE */
252
  public KeyValue() {}
253
  public KeyValue() {}
253

    
   
254

   
254
  /**
255
  /**
255
   * Creates a KeyValue from the start of the specified byte array.
256
   * Creates a KeyValue from the start of the specified byte array.
256
   * Presumes <code>bytes</code> content is formatted as a KeyValue blob.
257
   * Presumes <code>bytes</code> content is formatted as a KeyValue blob.
257
   * @param bytes byte array
258
   * @param bytes byte array
258
   */
259
   */
259
  public KeyValue(final byte [] bytes) {
260
  public KeyValue(final byte [] bytes) {
260
    this(bytes, 0);
261
    this(bytes, 0);
261
  }
262
  }
262

    
   
263

   
263
  /**
264
  /**
264
   * Creates a KeyValue from the specified byte array and offset.
265
   * Creates a KeyValue from the specified byte array and offset.
265
   * Presumes <code>bytes</code> content starting at <code>offset</code> is
266
   * Presumes <code>bytes</code> content starting at <code>offset</code> is
266
   * formatted as a KeyValue blob.
267
   * formatted as a KeyValue blob.
267
   * @param bytes byte array
268
   * @param bytes byte array
268
   * @param offset offset to start of KeyValue
269
   * @param offset offset to start of KeyValue
269
   */
270
   */
270
  public KeyValue(final byte [] bytes, final int offset) {
271
  public KeyValue(final byte [] bytes, final int offset) {
271
    this(bytes, offset, getLength(bytes, offset));
272
    this(bytes, offset, getLength(bytes, offset));
272
  }
273
  }
273

    
   
274

   
274
  /**
275
  /**
275
   * Creates a KeyValue from the specified byte array, starting at offset, and
276
   * Creates a KeyValue from the specified byte array, starting at offset, and
276
   * for length <code>length</code>.
277
   * for length <code>length</code>.
277
   * @param bytes byte array
278
   * @param bytes byte array
278
   * @param offset offset to start of the KeyValue
279
   * @param offset offset to start of the KeyValue
279
   * @param length length of the KeyValue
280
   * @param length length of the KeyValue
280
   */
281
   */
281
  public KeyValue(final byte [] bytes, final int offset, final int length) {
282
  public KeyValue(final byte [] bytes, final int offset, final int length) {
282
    this.bytes = bytes;
283
    this.bytes = bytes;
283
    this.offset = offset;
284
    this.offset = offset;
284
    this.length = length;
285
    this.length = length;
285
  }
286
  }
286

    
   
287

   
287
  /** Constructors that build a new backing byte array from fields */
288
  /** Constructors that build a new backing byte array from fields */
288

    
   
289

   
289
  /**
290
  /**
290
   * Constructs KeyValue structure filled with null value.
291
   * Constructs KeyValue structure filled with null value.
291
   * Sets type to {@link KeyValue.Type#Maximum}
292
   * Sets type to {@link KeyValue.Type#Maximum}
292
   * @param row - row key (arbitrary byte array)
293
   * @param row - row key (arbitrary byte array)
293
   * @param timestamp
294
   * @param timestamp
294
   */
295
   */
295
  public KeyValue(final byte [] row, final long timestamp) {
296
  public KeyValue(final byte [] row, final long timestamp) {
296
    this(row, timestamp, Type.Maximum);
297
    this(row, timestamp, Type.Maximum);
297
  }
298
  }
298

    
   
299

   
299
  /**
300
  /**
300
   * Constructs KeyValue structure filled with null value.
301
   * Constructs KeyValue structure filled with null value.
301
   * @param row - row key (arbitrary byte array)
302
   * @param row - row key (arbitrary byte array)
302
   * @param timestamp
303
   * @param timestamp
303
   */
304
   */
304
  public KeyValue(final byte [] row, final long timestamp, Type type) {
305
  public KeyValue(final byte [] row, final long timestamp, Type type) {
305
    this(row, null, null, timestamp, type, null);
306
    this(row, null, null, timestamp, type, null);
306
  }
307
  }
307

    
   
308

   
308
  /**
309
  /**
309
   * Constructs KeyValue structure filled with null value.
310
   * Constructs KeyValue structure filled with null value.
310
   * Sets type to {@link KeyValue.Type#Maximum}
311
   * Sets type to {@link KeyValue.Type#Maximum}
311
   * @param row - row key (arbitrary byte array)
312
   * @param row - row key (arbitrary byte array)
312
   * @param family family name
313
   * @param family family name
313
   * @param qualifier column qualifier
314
   * @param qualifier column qualifier
314
   */
315
   */
315
  public KeyValue(final byte [] row, final byte [] family,
316
  public KeyValue(final byte [] row, final byte [] family,
316
      final byte [] qualifier) {
317
      final byte [] qualifier) {
317
    this(row, family, qualifier, HConstants.LATEST_TIMESTAMP, Type.Maximum);
318
    this(row, family, qualifier, HConstants.LATEST_TIMESTAMP, Type.Maximum);
318
  }
319
  }
319

    
   
320

   
320
  /**
321
  /**
321
   * Constructs KeyValue structure filled with null value.
322
   * Constructs KeyValue structure filled with null value.
322
   * @param row - row key (arbitrary byte array)
323
   * @param row - row key (arbitrary byte array)
323
   * @param family family name
324
   * @param family family name
324
   * @param qualifier column qualifier
325
   * @param qualifier column qualifier
325
   */
326
   */
326
  public KeyValue(final byte [] row, final byte [] family,
327
  public KeyValue(final byte [] row, final byte [] family,
327
      final byte [] qualifier, final byte [] value) {
328
      final byte [] qualifier, final byte [] value) {
328
    this(row, family, qualifier, HConstants.LATEST_TIMESTAMP, Type.Put, value);
329
    this(row, family, qualifier, HConstants.LATEST_TIMESTAMP, Type.Put, value);
329
  }
330
  }
330

    
   
331

   
331
  /**
332
  /**
332
   * Constructs KeyValue structure filled with specified values.
333
   * Constructs KeyValue structure filled with specified values.
333
   * @param row row key
334
   * @param row row key
334
   * @param family family name
335
   * @param family family name
335
   * @param qualifier column qualifier
336
   * @param qualifier column qualifier
336
   * @param timestamp version timestamp
337
   * @param timestamp version timestamp
337
   * @param type key type
338
   * @param type key type
338
   * @throws IllegalArgumentException
339
   * @throws IllegalArgumentException
339
   */
340
   */
340
  public KeyValue(final byte[] row, final byte[] family,
341
  public KeyValue(final byte[] row, final byte[] family,
341
      final byte[] qualifier, final long timestamp, Type type) {
342
      final byte[] qualifier, final long timestamp, Type type) {
342
    this(row, family, qualifier, timestamp, type, null);
343
    this(row, family, qualifier, timestamp, type, null);
343
  }
344
  }
344

    
   
345

   
345
  /**
346
  /**
346
   * Constructs KeyValue structure filled with specified values.
347
   * Constructs KeyValue structure filled with specified values.
347
   * @param row row key
348
   * @param row row key
348
   * @param family family name
349
   * @param family family name
349
   * @param qualifier column qualifier
350
   * @param qualifier column qualifier
350
   * @param timestamp version timestamp
351
   * @param timestamp version timestamp
351
   * @param value column value
352
   * @param value column value
352
   * @throws IllegalArgumentException
353
   * @throws IllegalArgumentException
353
   */
354
   */
354
  public KeyValue(final byte[] row, final byte[] family,
355
  public KeyValue(final byte[] row, final byte[] family,
355
      final byte[] qualifier, final long timestamp, final byte[] value) {
356
      final byte[] qualifier, final long timestamp, final byte[] value) {
356
    this(row, family, qualifier, timestamp, Type.Put, value);
357
    this(row, family, qualifier, timestamp, Type.Put, value);
357
  }
358
  }
358

    
   
359

   
359
  /**
360
  /**
360
   * Constructs KeyValue structure filled with specified values.
361
   * Constructs KeyValue structure filled with specified values.
361
   * @param row row key
362
   * @param row row key
362
   * @param family family name
363
   * @param family family name
363
   * @param qualifier column qualifier
364
   * @param qualifier column qualifier
364
   * @param timestamp version timestamp
365
   * @param timestamp version timestamp
365
   * @param type key type
366
   * @param type key type
366
   * @param value column value
367
   * @param value column value
367
   * @throws IllegalArgumentException
368
   * @throws IllegalArgumentException
368
   */
369
   */
369
  public KeyValue(final byte[] row, final byte[] family,
370
  public KeyValue(final byte[] row, final byte[] family,
370
      final byte[] qualifier, final long timestamp, Type type,
371
      final byte[] qualifier, final long timestamp, Type type,
371
      final byte[] value) {
372
      final byte[] value) {
372
    this(row, family, qualifier, 0, qualifier==null ? 0 : qualifier.length,
373
    this(row, family, qualifier, 0, qualifier==null ? 0 : qualifier.length,
373
        timestamp, type, value, 0, value==null ? 0 : value.length);
374
        timestamp, type, value, 0, value==null ? 0 : value.length);
374
  }
375
  }
375

    
   
376

   
376
  /**
377
  /**
377
   * Constructs KeyValue structure filled with specified values.
378
   * Constructs KeyValue structure filled with specified values.
378
   * @param row row key
379
   * @param row row key
379
   * @param family family name
380
   * @param family family name
380
   * @param qualifier column qualifier
381
   * @param qualifier column qualifier
381
   * @param qoffset qualifier offset
382
   * @param qoffset qualifier offset
382
   * @param qlength qualifier length
383
   * @param qlength qualifier length
383
   * @param timestamp version timestamp
384
   * @param timestamp version timestamp
384
   * @param type key type
385
   * @param type key type
385
   * @param value column value
386
   * @param value column value
386
   * @param voffset value offset
387
   * @param voffset value offset
387
   * @param vlength value length
388
   * @param vlength value length
388
   * @throws IllegalArgumentException
389
   * @throws IllegalArgumentException
389
   */
390
   */
390
  public KeyValue(byte [] row, byte [] family,
391
  public KeyValue(byte [] row, byte [] family,
391
      byte [] qualifier, int qoffset, int qlength, long timestamp, Type type,
392
      byte [] qualifier, int qoffset, int qlength, long timestamp, Type type,
392
      byte [] value, int voffset, int vlength) {
393
      byte [] value, int voffset, int vlength) {
393
    this(row, 0, row==null ? 0 : row.length,
394
    this(row, 0, row==null ? 0 : row.length,
394
        family, 0, family==null ? 0 : family.length,
395
        family, 0, family==null ? 0 : family.length,
395
        qualifier, qoffset, qlength, timestamp, type,
396
        qualifier, qoffset, qlength, timestamp, type,
396
        value, voffset, vlength);
397
        value, voffset, vlength);
397
  }
398
  }
398

    
   
399

   
399
  /**
400
  /**
400
   * Constructs KeyValue structure filled with specified values.
401
   * Constructs KeyValue structure filled with specified values.
401
   * <p>
402
   * <p>
402
   * Column is split into two fields, family and qualifier.
403
   * Column is split into two fields, family and qualifier.
403
   * @param row row key
404
   * @param row row key
404
   * @param roffset row offset
405
   * @param roffset row offset
405
   * @param rlength row length
406
   * @param rlength row length
406
   * @param family family name
407
   * @param family family name
407
   * @param foffset family offset
408
   * @param foffset family offset
408
   * @param flength family length
409
   * @param flength family length
409
   * @param qualifier column qualifier
410
   * @param qualifier column qualifier
410
   * @param qoffset qualifier offset
411
   * @param qoffset qualifier offset
411
   * @param qlength qualifier length
412
   * @param qlength qualifier length
412
   * @param timestamp version timestamp
413
   * @param timestamp version timestamp
413
   * @param type key type
414
   * @param type key type
414
   * @param value column value
415
   * @param value column value
415
   * @param voffset value offset
416
   * @param voffset value offset
416
   * @param vlength value length
417
   * @param vlength value length
417
   * @throws IllegalArgumentException
418
   * @throws IllegalArgumentException
418
   */
419
   */
419
  public KeyValue(final byte [] row, final int roffset, final int rlength,
420
  public KeyValue(final byte [] row, final int roffset, final int rlength,
420
      final byte [] family, final int foffset, final int flength,
421
      final byte [] family, final int foffset, final int flength,
421
      final byte [] qualifier, final int qoffset, final int qlength,
422
      final byte [] qualifier, final int qoffset, final int qlength,
422
      final long timestamp, final Type type,
423
      final long timestamp, final Type type,
423
      final byte [] value, final int voffset, final int vlength) {
424
      final byte [] value, final int voffset, final int vlength) {
424
    this.bytes = createByteArray(row, roffset, rlength,
425
    this.bytes = createByteArray(row, roffset, rlength,
425
        family, foffset, flength, qualifier, qoffset, qlength,
426
        family, foffset, flength, qualifier, qoffset, qlength,
426
        timestamp, type, value, voffset, vlength);
427
        timestamp, type, value, voffset, vlength);
427
    this.length = bytes.length;
428
    this.length = bytes.length;
428
    this.offset = 0;
429
    this.offset = 0;
429
  }
430
  }
430

    
   
431

   
431
  /**
432
  /**
432
   * Constructs an empty KeyValue structure, with specified sizes.
433
   * Constructs an empty KeyValue structure, with specified sizes.
433
   * This can be used to partially fill up KeyValues.
434
   * This can be used to partially fill up KeyValues.
434
   * <p>
435
   * <p>
435
   * Column is split into two fields, family and qualifier.
436
   * Column is split into two fields, family and qualifier.
436
   * @param rlength row length
437
   * @param rlength row length
437
   * @param flength family length
438
   * @param flength family length
438
   * @param qlength qualifier length
439
   * @param qlength qualifier length
439
   * @param timestamp version timestamp
440
   * @param timestamp version timestamp
440
   * @param type key type
441
   * @param type key type
441
   * @param vlength value length
442
   * @param vlength value length
442
   * @throws IllegalArgumentException
443
   * @throws IllegalArgumentException
443
   */
444
   */
444
  public KeyValue(final int rlength,
445
  public KeyValue(final int rlength,
445
      final int flength,
446
      final int flength,
446
      final int qlength,
447
      final int qlength,
447
      final long timestamp, final Type type,
448
      final long timestamp, final Type type,
448
      final int vlength) {
449
      final int vlength) {
449
    this.bytes = createEmptyByteArray(rlength,
450
    this.bytes = createEmptyByteArray(rlength,
450
        flength, qlength,
451
        flength, qlength,
451
        timestamp, type, vlength);
452
        timestamp, type, vlength);
452
    this.length = bytes.length;
453
    this.length = bytes.length;
453
    this.offset = 0;
454
    this.offset = 0;
454
  }
455
  }
455

    
   
456

   
456
  /**
457
  /**
457
   * Create an empty byte[] representing a KeyValue
458
   * Create an empty byte[] representing a KeyValue
458
   * All lengths are preset and can be filled in later.
459
   * All lengths are preset and can be filled in later.
459
   * @param rlength
460
   * @param rlength
460
   * @param flength
461
   * @param flength
461
   * @param qlength
462
   * @param qlength
462
   * @param timestamp
463
   * @param timestamp
463
   * @param type
464
   * @param type
464
   * @param vlength
465
   * @param vlength
465
   * @return The newly created byte array.
466
   * @return The newly created byte array.
466
   */
467
   */
467
  static byte[] createEmptyByteArray(final int rlength, int flength,
468
  static byte[] createEmptyByteArray(final int rlength, int flength,
468
      int qlength, final long timestamp, final Type type, int vlength) {
469
      int qlength, final long timestamp, final Type type, int vlength) {
469
    if (rlength > Short.MAX_VALUE) {
470
    if (rlength > Short.MAX_VALUE) {
470
      throw new IllegalArgumentException("Row > " + Short.MAX_VALUE);
471
      throw new IllegalArgumentException("Row > " + Short.MAX_VALUE);
471
    }
472
    }
472
    if (flength > Byte.MAX_VALUE) {
473
    if (flength > Byte.MAX_VALUE) {
473
      throw new IllegalArgumentException("Family > " + Byte.MAX_VALUE);
474
      throw new IllegalArgumentException("Family > " + Byte.MAX_VALUE);
474
    }
475
    }
475
    // Qualifier length
476
    // Qualifier length
476
    if (qlength > Integer.MAX_VALUE - rlength - flength) {
477
    if (qlength > Integer.MAX_VALUE - rlength - flength) {
477
      throw new IllegalArgumentException("Qualifier > " + Integer.MAX_VALUE);
478
      throw new IllegalArgumentException("Qualifier > " + Integer.MAX_VALUE);
478
    }
479
    }
479
    // Key length
480
    // Key length
480
    long longkeylength = KEY_INFRASTRUCTURE_SIZE + rlength + flength + qlength;
481
    long longkeylength = KEY_INFRASTRUCTURE_SIZE + rlength + flength + qlength;
481
    if (longkeylength > Integer.MAX_VALUE) {
482
    if (longkeylength > Integer.MAX_VALUE) {
482
      throw new IllegalArgumentException("keylength " + longkeylength + " > " +
483
      throw new IllegalArgumentException("keylength " + longkeylength + " > " +
483
        Integer.MAX_VALUE);
484
        Integer.MAX_VALUE);
484
    }
485
    }
485
    int keylength = (int)longkeylength;
486
    int keylength = (int)longkeylength;
486
    // Value length
487
    // Value length
487
    if (vlength > HConstants.MAXIMUM_VALUE_LENGTH) { // FindBugs INT_VACUOUS_COMPARISON
488
    if (vlength > HConstants.MAXIMUM_VALUE_LENGTH) { // FindBugs INT_VACUOUS_COMPARISON
488
      throw new IllegalArgumentException("Valuer > " +
489
      throw new IllegalArgumentException("Valuer > " +
489
          HConstants.MAXIMUM_VALUE_LENGTH);
490
          HConstants.MAXIMUM_VALUE_LENGTH);
490
    }
491
    }
491

    
   
492

   
492
    // Allocate right-sized byte array.
493
    // Allocate right-sized byte array.
493
    byte [] bytes = new byte[KEYVALUE_INFRASTRUCTURE_SIZE + keylength + vlength];
494
    byte [] bytes = new byte[KEYVALUE_INFRASTRUCTURE_SIZE + keylength + vlength];
494
    // Write the correct size markers
495
    // Write the correct size markers
495
    int pos = 0;
496
    int pos = 0;
496
    pos = Bytes.putInt(bytes, pos, keylength);
497
    pos = Bytes.putInt(bytes, pos, keylength);
497
    pos = Bytes.putInt(bytes, pos, vlength);
498
    pos = Bytes.putInt(bytes, pos, vlength);
498
    pos = Bytes.putShort(bytes, pos, (short)(rlength & 0x0000ffff));
499
    pos = Bytes.putShort(bytes, pos, (short)(rlength & 0x0000ffff));
499
    pos += rlength;
500
    pos += rlength;
500
    pos = Bytes.putByte(bytes, pos, (byte)(flength & 0x0000ff));
501
    pos = Bytes.putByte(bytes, pos, (byte)(flength & 0x0000ff));
501
    pos += flength + qlength;
502
    pos += flength + qlength;
502
    pos = Bytes.putLong(bytes, pos, timestamp);
503
    pos = Bytes.putLong(bytes, pos, timestamp);
503
    pos = Bytes.putByte(bytes, pos, type.getCode());
504
    pos = Bytes.putByte(bytes, pos, type.getCode());
504
    return bytes;
505
    return bytes;
505
  }
506
  }
506

    
   
507

   
507
  /**
508
  /**
508
   * Write KeyValue format into a byte array.
509
   * Constructs KeyValue structure filled with specified values. Uses the provided buffer as the

    
   
510
   * data buffer.

    
   
511
   * <p>

    
   
512
   * Column is split into two fields, family and qualifier.
509
   *
513
   *

    
   
514
   * @param buffer the bytes buffer to use
510
   * @param row row key
515
   * @param row row key
511
   * @param roffset row offset
516
   * @param roffset row offset
512
   * @param rlength row length
517
   * @param rlength row length
513
   * @param family family name
518
   * @param family family name
514
   * @param foffset family offset
519
   * @param foffset family offset
515
   * @param flength family length
520
   * @param flength family length
516
   * @param qualifier column qualifier
521
   * @param qualifier column qualifier
517
   * @param qoffset qualifier offset
522
   * @param qoffset qualifier offset
518
   * @param qlength qualifier length
523
   * @param qlength qualifier length
519
   * @param timestamp version timestamp
524
   * @param timestamp version timestamp
520
   * @param type key type
525
   * @param type key type
521
   * @param value column value
526
   * @param value column value
522
   * @param voffset value offset
527
   * @param voffset value offset
523
   * @param vlength value length
528
   * @param vlength value length
524
   * @return The newly created byte array.
529
   * @throws IllegalArgumentException
525
   */
530
   */
526
  static byte [] createByteArray(final byte [] row, final int roffset,
531
  public KeyValue(byte [] buffer,
527
      final int rlength, final byte [] family, final int foffset, int flength,
532
                  final byte [] row, final int roffset, final int rlength,
528
      final byte [] qualifier, final int qoffset, int qlength,
533
                  final byte [] family, final int foffset, final int flength,

    
   
534
                  final byte [] qualifier, final int qoffset, final int qlength,
529
      final long timestamp, final Type type,
535
                  final long timestamp, final Type type,
530
      final byte [] value, final int voffset, int vlength) {
536
                  final byte [] value, final int voffset, final int vlength) {

    
   
537

   

    
   
538
    this.bytes  = buffer;

    
   
539
    this.length = writeByteArray(buffer, row, roffset, rlength,

    
   
540
                                 family, foffset, flength, qualifier, qoffset, qlength,

    
   
541
                                 timestamp, type, value, voffset, vlength);

    
   
542
    this.offset = 0;

    
   
543
  }

    
   
544

   

    
   
545
  /**

    
   
546
   * Checks the parameters passed to a constructor.

    
   
547
   *

    
   
548
   * @param row row key

    
   
549
   * @param rlength row length

    
   
550
   * @param family family name

    
   
551
   * @param flength family length

    
   
552
   * @param qualifier column qualifier

    
   
553
   * @param qlength qualifier length

    
   
554
   * @param value column value

    
   
555
   * @param vlength value length

    
   
556
   *

    
   
557
   * @throws IllegalArgumentException an illegal value was passed

    
   
558
   */

    
   
559
  private static void checkParameters(final byte [] row, final int rlength,

    
   
560
                                      final byte [] family, int flength,

    
   
561
                                      final byte [] qualifier, int qlength,

    
   
562
                                      final byte [] value, int vlength)

    
   
563
          throws IllegalArgumentException {

    
   
564

   
531
    if (rlength > Short.MAX_VALUE) {
565
    if (rlength > Short.MAX_VALUE) {
532
      throw new IllegalArgumentException("Row > " + Short.MAX_VALUE);
566
      throw new IllegalArgumentException("Row > " + Short.MAX_VALUE);
533
    }
567
    }
534
    if (row == null) {
568
    if (row == null) {
535
      throw new IllegalArgumentException("Row is null");
569
      throw new IllegalArgumentException("Row is null");
536
    }
570
    }
537
    // Family length
571
    // Family length
538
    flength = family == null ? 0 : flength;
572
    flength = family == null ? 0 : flength;
539
    if (flength > Byte.MAX_VALUE) {
573
    if (flength > Byte.MAX_VALUE) {
540
      throw new IllegalArgumentException("Family > " + Byte.MAX_VALUE);
574
      throw new IllegalArgumentException("Family > " + Byte.MAX_VALUE);
541
    }
575
    }
542
    // Qualifier length
576
    // Qualifier length
543
    qlength = qualifier == null ? 0 : qlength;
577
    qlength = qualifier == null ? 0 : qlength;
544
    if (qlength > Integer.MAX_VALUE - rlength - flength) {
578
    if (qlength > Integer.MAX_VALUE - rlength - flength) {
545
      throw new IllegalArgumentException("Qualifier > " + Integer.MAX_VALUE);
579
      throw new IllegalArgumentException("Qualifier > " + Integer.MAX_VALUE);
546
    }
580
    }
547
    // Key length
581
    // Key length
548
    long longkeylength = KEY_INFRASTRUCTURE_SIZE + rlength + flength + qlength;
582
    long longKeyLength = KEY_INFRASTRUCTURE_SIZE + rlength + flength + qlength;
549
    if (longkeylength > Integer.MAX_VALUE) {
583
    if (longKeyLength > Integer.MAX_VALUE) {
550
      throw new IllegalArgumentException("keylength " + longkeylength + " > " +
584
      throw new IllegalArgumentException("keylength " + longKeyLength + " > " + Integer.MAX_VALUE);
551
        Integer.MAX_VALUE);

   
552
    }
585
    }
553
    int keylength = (int)longkeylength;

   
554
    // Value length
586
    // Value length
555
    vlength = value == null? 0 : vlength;
587
    vlength = value == null? 0 : vlength;
556
    if (vlength > HConstants.MAXIMUM_VALUE_LENGTH) { // FindBugs INT_VACUOUS_COMPARISON
588
    if (vlength > HConstants.MAXIMUM_VALUE_LENGTH) { // FindBugs INT_VACUOUS_COMPARISON
557
      throw new IllegalArgumentException("Valuer > " +
589
      throw new IllegalArgumentException("Value > " + HConstants.MAXIMUM_VALUE_LENGTH);
558
          HConstants.MAXIMUM_VALUE_LENGTH);
590
    }
559
    }
591
  }
560

    
   
592

   

    
   
593
  /**

    
   
594
   * Write KeyValue format into the provided byte array.

    
   
595
   *

    
   
596
   * @param buffer the bytes buffer to use

    
   
597
   * @param row row key

    
   
598
   * @param roffset row offset

    
   
599
   * @param rlength row length

    
   
600
   * @param family family name

    
   
601
   * @param foffset family offset

    
   
602
   * @param flength family length

    
   
603
   * @param qualifier column qualifier

    
   
604
   * @param qoffset qualifier offset

    
   
605
   * @param qlength qualifier length

    
   
606
   * @param timestamp version timestamp

    
   
607
   * @param type key type

    
   
608
   * @param value column value

    
   
609
   * @param voffset value offset

    
   
610
   * @param vlength value length

    
   
611
   *

    
   
612
   * @return The number of useful bytes in the buffer.

    
   
613
   */

    
   
614
  static int writeByteArray(byte [] buffer,

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

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

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

    
   
618
                            final long timestamp, final Type type,

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

    
   
620

   

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

    
   
622

   

    
   
623
    int keyLength = KEY_INFRASTRUCTURE_SIZE + rlength + flength + qlength;

    
   
624
    int keyValueLength = KEYVALUE_INFRASTRUCTURE_SIZE + keyLength + vlength;

    
   
625
    if (keyValueLength > buffer.length) {

    
   
626
      throw new IllegalArgumentException("Buffer size " + buffer.length + " < " + keyValueLength);

    
   
627
    }

    
   
628

   

    
   
629
    // Write key, value and key row length.

    
   
630
    int pos = 0;

    
   
631
    pos = Bytes.putInt(buffer, pos, keyLength);

    
   
632
    pos = Bytes.putInt(buffer, pos, vlength);

    
   
633
    pos = Bytes.putShort(buffer, pos, (short)(rlength & 0x0000ffff));

    
   
634
    pos = Bytes.putBytes(buffer, pos, row, roffset, rlength);

    
   
635
    pos = Bytes.putByte(buffer, pos, (byte) (flength & 0x0000ff));

    
   
636
    if (flength != 0) {

    
   
637
      pos = Bytes.putBytes(buffer, pos, family, foffset, flength);

    
   
638
    }

    
   
639
    if (qlength != 0) {

    
   
640
      pos = Bytes.putBytes(buffer, pos, qualifier, qoffset, qlength);

    
   
641
    }

    
   
642
    pos = Bytes.putLong(buffer, pos, timestamp);

    
   
643
    pos = Bytes.putByte(buffer, pos, type.getCode());

    
   
644
    if (value != null && value.length > 0) {

    
   
645
      pos = Bytes.putBytes(buffer, pos, value, voffset, vlength);

    
   
646
    }

    
   
647

   

    
   
648
    return keyValueLength;

    
   
649
  }

    
   
650

   

    
   
651
  /**

    
   
652
   * Write KeyValue format into a byte array.

    
   
653
   *

    
   
654
   * @param row row key

    
   
655
   * @param roffset row offset

    
   
656
   * @param rlength row length

    
   
657
   * @param family family name

    
   
658
   * @param foffset family offset

    
   
659
   * @param flength family length

    
   
660
   * @param qualifier column qualifier

    
   
661
   * @param qoffset qualifier offset

    
   
662
   * @param qlength qualifier length

    
   
663
   * @param timestamp version timestamp

    
   
664
   * @param type key type

    
   
665
   * @param value column value

    
   
666
   * @param voffset value offset

    
   
667
   * @param vlength value length

    
   
668
   * @return The newly created byte array.

    
   
669
   */

    
   
670
  static byte [] createByteArray(final byte [] row, final int roffset,

    
   
671
      final int rlength, final byte [] family, final int foffset, int flength,

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

    
   
673
      final long timestamp, final Type type,

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

    
   
675

   

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

    
   
677

   
561
    // Allocate right-sized byte array.
678
    // Allocate right-sized byte array.
562
    byte [] bytes = new byte[KEYVALUE_INFRASTRUCTURE_SIZE + keylength + vlength];
679
    int keyLength = KEY_INFRASTRUCTURE_SIZE + rlength + flength + qlength;

    
   
680
    byte [] bytes = new byte[KEYVALUE_INFRASTRUCTURE_SIZE + keyLength + vlength];
563
    // Write key, value and key row length.
681
    // Write key, value and key row length.
564
    int pos = 0;
682
    int pos = 0;
565
    pos = Bytes.putInt(bytes, pos, keylength);
683
    pos = Bytes.putInt(bytes, pos, keyLength);
566
    pos = Bytes.putInt(bytes, pos, vlength);
684
    pos = Bytes.putInt(bytes, pos, vlength);
567
    pos = Bytes.putShort(bytes, pos, (short)(rlength & 0x0000ffff));
685
    pos = Bytes.putShort(bytes, pos, (short)(rlength & 0x0000ffff));
568
    pos = Bytes.putBytes(bytes, pos, row, roffset, rlength);
686
    pos = Bytes.putBytes(bytes, pos, row, roffset, rlength);
569
    pos = Bytes.putByte(bytes, pos, (byte)(flength & 0x0000ff));
687
    pos = Bytes.putByte(bytes, pos, (byte)(flength & 0x0000ff));
570
    if(flength != 0) {
688
    if(flength != 0) {
571
      pos = Bytes.putBytes(bytes, pos, family, foffset, flength);
689
      pos = Bytes.putBytes(bytes, pos, family, foffset, flength);
572
    }
690
    }
573
    if(qlength != 0) {
691
    if(qlength != 0) {
574
      pos = Bytes.putBytes(bytes, pos, qualifier, qoffset, qlength);
692
      pos = Bytes.putBytes(bytes, pos, qualifier, qoffset, qlength);
575
    }
693
    }
576
    pos = Bytes.putLong(bytes, pos, timestamp);
694
    pos = Bytes.putLong(bytes, pos, timestamp);
577
    pos = Bytes.putByte(bytes, pos, type.getCode());
695
    pos = Bytes.putByte(bytes, pos, type.getCode());
578
    if (value != null && value.length > 0) {
696
    if (value != null && value.length > 0) {
579
      pos = Bytes.putBytes(bytes, pos, value, voffset, vlength);
697
      pos = Bytes.putBytes(bytes, pos, value, voffset, vlength);
580
    }
698
    }
581
    return bytes;
699
    return bytes;
582
  }
700
  }
583

    
   
701

   
584
  /**
702
  /**
585
   * Write KeyValue format into a byte array.
703
   * Write KeyValue format into a byte array.
586
   * <p>
704
   * <p>
587
   * Takes column in the form <code>family:qualifier</code>
705
   * Takes column in the form <code>family:qualifier</code>
588
   * @param row - row key (arbitrary byte array)
706
   * @param row - row key (arbitrary byte array)
589
   * @param roffset
707
   * @param roffset
590
   * @param rlength
708
   * @param rlength
591
   * @param column
709
   * @param column
592
   * @param coffset
710
   * @param coffset
593
   * @param clength
711
   * @param clength
594
   * @param timestamp
712
   * @param timestamp
595
   * @param type
713
   * @param type
596
   * @param value
714
   * @param value
597
   * @param voffset
715
   * @param voffset
598
   * @param vlength
716
   * @param vlength
599
   * @return The newly created byte array.
717
   * @return The newly created byte array.
600
   */
718
   */
601
  static byte [] createByteArray(final byte [] row, final int roffset,
719
  static byte [] createByteArray(final byte [] row, final int roffset,
602
        final int rlength,
720
        final int rlength,
603
      final byte [] column, final int coffset, int clength,
721
      final byte [] column, final int coffset, int clength,
604
      final long timestamp, final Type type,
722
      final long timestamp, final Type type,
605
      final byte [] value, final int voffset, int vlength) {
723
      final byte [] value, final int voffset, int vlength) {
606
    // If column is non-null, figure where the delimiter is at.
724
    // If column is non-null, figure where the delimiter is at.
607
    int delimiteroffset = 0;
725
    int delimiteroffset = 0;
608
    if (column != null && column.length > 0) {
726
    if (column != null && column.length > 0) {
609
      delimiteroffset = getFamilyDelimiterIndex(column, coffset, clength);
727
      delimiteroffset = getFamilyDelimiterIndex(column, coffset, clength);
610
      if (delimiteroffset > Byte.MAX_VALUE) {
728
      if (delimiteroffset > Byte.MAX_VALUE) {
611
        throw new IllegalArgumentException("Family > " + Byte.MAX_VALUE);
729
        throw new IllegalArgumentException("Family > " + Byte.MAX_VALUE);
612
      }
730
      }
613
    } else {
731
    } else {
614
      return createByteArray(row,roffset,rlength,null,0,0,null,0,0,timestamp,
732
      return createByteArray(row,roffset,rlength,null,0,0,null,0,0,timestamp,
615
          type,value,voffset,vlength);
733
          type,value,voffset,vlength);
616
    }
734
    }
617
    int flength = delimiteroffset-coffset;
735
    int flength = delimiteroffset-coffset;
618
    int qlength = clength - flength - 1;
736
    int qlength = clength - flength - 1;
619
    return createByteArray(row, roffset, rlength, column, coffset,
737
    return createByteArray(row, roffset, rlength, column, coffset,
620
        flength, column, delimiteroffset+1, qlength, timestamp, type,
738
        flength, column, delimiteroffset+1, qlength, timestamp, type,
621
        value, voffset, vlength);
739
        value, voffset, vlength);
622
  }
740
  }
623

    
   
741

   
624
  // Needed doing 'contains' on List.  Only compares the key portion, not the
742
  // Needed doing 'contains' on List.  Only compares the key portion, not the
625
  // value.
743
  // value.
626
  public boolean equals(Object other) {
744
  public boolean equals(Object other) {
627
    if (!(other instanceof KeyValue)) {
745
    if (!(other instanceof KeyValue)) {
628
      return false;
746
      return false;
629
    }
747
    }
630
    KeyValue kv = (KeyValue)other;
748
    KeyValue kv = (KeyValue)other;
631
    // Comparing bytes should be fine doing equals test.  Shouldn't have to
749
    // Comparing bytes should be fine doing equals test.  Shouldn't have to
632
    // worry about special .META. comparators doing straight equals.
750
    // worry about special .META. comparators doing straight equals.
633
    return Bytes.equals(getBuffer(), getKeyOffset(), getKeyLength(),
751
    return Bytes.equals(getBuffer(), getKeyOffset(), getKeyLength(),
634
      kv.getBuffer(), kv.getKeyOffset(), kv.getKeyLength());
752
      kv.getBuffer(), kv.getKeyOffset(), kv.getKeyLength());
635
  }
753
  }
636

    
   
754

   
637
  public int hashCode() {
755
  public int hashCode() {
638
    byte[] b = getBuffer();
756
    byte[] b = getBuffer();
639
    int start = getOffset(), end = getOffset() + getLength();
757
    int start = getOffset(), end = getOffset() + getLength();
640
    int h = b[start++];
758
    int h = b[start++];
641
    for (int i = start; i < end; i++) {
759
    for (int i = start; i < end; i++) {
642
      h = (h * 13) ^ b[i];
760
      h = (h * 13) ^ b[i];
643
    }
761
    }
644
    return h;
762
    return h;
645
  }
763
  }
646

    
   
764

   
647
  //---------------------------------------------------------------------------
765
  //---------------------------------------------------------------------------
648
  //
766
  //
649
  //  KeyValue cloning
767
  //  KeyValue cloning
650
  //
768
  //
651
  //---------------------------------------------------------------------------
769
  //---------------------------------------------------------------------------
652

    
   
770

   
653
  /**
771
  /**
654
   * Clones a KeyValue.  This creates a copy, re-allocating the buffer.
772
   * Clones a KeyValue.  This creates a copy, re-allocating the buffer.
655
   * @return Fully copied clone of this KeyValue
773
   * @return Fully copied clone of this KeyValue
656
   */
774
   */
657
  public KeyValue clone() {
775
  public KeyValue clone() {
658
    byte [] b = new byte[this.length];
776
    byte [] b = new byte[this.length];
659
    System.arraycopy(this.bytes, this.offset, b, 0, this.length);
777
    System.arraycopy(this.bytes, this.offset, b, 0, this.length);
660
    KeyValue ret = new KeyValue(b, 0, b.length);
778
    KeyValue ret = new KeyValue(b, 0, b.length);
661
    // Important to clone the memstoreTS as well - otherwise memstore's
779
    // Important to clone the memstoreTS as well - otherwise memstore's
662
    // update-in-place methods (eg increment) will end up creating
780
    // update-in-place methods (eg increment) will end up creating
663
    // new entries
781
    // new entries
664
    ret.setMemstoreTS(memstoreTS);
782
    ret.setMemstoreTS(memstoreTS);
665
    return ret;
783
    return ret;
666
  }
784
  }
667

    
   
785

   
668
  /**
786
  /**
669
   * Creates a deep copy of this KeyValue, re-allocating the buffer.
787
   * Creates a deep copy of this KeyValue, re-allocating the buffer.
670
   * Same function as {@link #clone()}.  Added for clarity vs shallowCopy()
788
   * Same function as {@link #clone()}.  Added for clarity vs shallowCopy()
671
   * @return Deep copy of this KeyValue
789
   * @return Deep copy of this KeyValue
672
   */
790
   */
673
  public KeyValue deepCopy() {
791
  public KeyValue deepCopy() {
674
    return clone();
792
    return clone();
675
  }
793
  }
676

    
   
794

   
677
  /**
795
  /**
678
   * Creates a shallow copy of this KeyValue, reusing the data byte buffer.
796
   * Creates a shallow copy of this KeyValue, reusing the data byte buffer.
679
   * http://en.wikipedia.org/wiki/Object_copy
797
   * http://en.wikipedia.org/wiki/Object_copy
680
   * @return Shallow copy of this KeyValue
798
   * @return Shallow copy of this KeyValue
681
   */
799
   */
682
  public KeyValue shallowCopy() {
800
  public KeyValue shallowCopy() {
683
    KeyValue shallowCopy = new KeyValue(this.bytes, this.offset, this.length);
801
    KeyValue shallowCopy = new KeyValue(this.bytes, this.offset, this.length);
684
    shallowCopy.setMemstoreTS(this.memstoreTS);
802
    shallowCopy.setMemstoreTS(this.memstoreTS);
685
    return shallowCopy;
803
    return shallowCopy;
686
  }
804
  }
687

    
   
805

   
688
  //---------------------------------------------------------------------------
806
  //---------------------------------------------------------------------------
689
  //
807
  //
690
  //  String representation
808
  //  String representation
691
  //
809
  //
692
  //---------------------------------------------------------------------------
810
  //---------------------------------------------------------------------------
693

    
   
811

   
694
  public String toString() {
812
  public String toString() {
695
    if (this.bytes == null || this.bytes.length == 0) {
813
    if (this.bytes == null || this.bytes.length == 0) {
696
      return "empty";
814
      return "empty";
697
    }
815
    }
698
    return keyToString(this.bytes, this.offset + ROW_OFFSET, getKeyLength()) +
816
    return keyToString(this.bytes, this.offset + ROW_OFFSET, getKeyLength()) +
699
      "/vlen=" + getValueLength() + "/ts=" + memstoreTS;
817
      "/vlen=" + getValueLength() + "/ts=" + memstoreTS;
700
  }
818
  }
701

    
   
819

   
702
  /**
820
  /**
703
   * @param k Key portion of a KeyValue.
821
   * @param k Key portion of a KeyValue.
704
   * @return Key as a String.
822
   * @return Key as a String.
705
   */
823
   */
706
  public static String keyToString(final byte [] k) {
824
  public static String keyToString(final byte [] k) {
707
    return keyToString(k, 0, k.length);
825
    return keyToString(k, 0, k.length);
708
  }
826
  }
709

    
   
827

   
710
  /**
828
  /**
711
   * Use for logging.
829
   * Use for logging.
712
   * @param b Key portion of a KeyValue.
830
   * @param b Key portion of a KeyValue.
713
   * @param o Offset to start of key
831
   * @param o Offset to start of key
714
   * @param l Length of key.
832
   * @param l Length of key.
715
   * @return Key as a String.
833
   * @return Key as a String.
716
   */
834
   */
717
  /**
835
  /**
718
   * Produces a string map for this key/value pair. Useful for programmatic use
836
   * Produces a string map for this key/value pair. Useful for programmatic use
719
   * and manipulation of the data stored in an HLogKey, for example, printing
837
   * and manipulation of the data stored in an HLogKey, for example, printing
720
   * as JSON. Values are left out due to their tendency to be large. If needed,
838
   * as JSON. Values are left out due to their tendency to be large. If needed,
721
   * they can be added manually.
839
   * they can be added manually.
722
   *
840
   *
723
   * @return the Map<String,?> containing data from this key
841
   * @return the Map<String,?> containing data from this key
724
   */
842
   */
725
  public Map<String, Object> toStringMap() {
843
  public Map<String, Object> toStringMap() {
726
    Map<String, Object> stringMap = new HashMap<String, Object>();
844
    Map<String, Object> stringMap = new HashMap<String, Object>();
727
    stringMap.put("row", Bytes.toStringBinary(getRow()));
845
    stringMap.put("row", Bytes.toStringBinary(getRow()));
728
    stringMap.put("family", Bytes.toStringBinary(getFamily()));
846
    stringMap.put("family", Bytes.toStringBinary(getFamily()));
729
    stringMap.put("qualifier", Bytes.toStringBinary(getQualifier()));
847
    stringMap.put("qualifier", Bytes.toStringBinary(getQualifier()));
730
    stringMap.put("timestamp", getTimestamp());
848
    stringMap.put("timestamp", getTimestamp());
731
    stringMap.put("vlen", getValueLength());
849
    stringMap.put("vlen", getValueLength());
732
    return stringMap;
850
    return stringMap;
733
  }
851
  }
734

    
   
852

   
735
  public static String keyToString(final byte [] b, final int o, final int l) {
853
  public static String keyToString(final byte [] b, final int o, final int l) {
736
    if (b == null) return "";
854
    if (b == null) return "";
737
    int rowlength = Bytes.toShort(b, o);
855
    int rowlength = Bytes.toShort(b, o);
738
    String row = Bytes.toStringBinary(b, o + Bytes.SIZEOF_SHORT, rowlength);
856
    String row = Bytes.toStringBinary(b, o + Bytes.SIZEOF_SHORT, rowlength);
739
    int columnoffset = o + Bytes.SIZEOF_SHORT + 1 + rowlength;
857
    int columnoffset = o + Bytes.SIZEOF_SHORT + 1 + rowlength;
740
    int familylength = b[columnoffset - 1];
858
    int familylength = b[columnoffset - 1];
741
    int columnlength = l - ((columnoffset - o) + TIMESTAMP_TYPE_SIZE);
859
    int columnlength = l - ((columnoffset - o) + TIMESTAMP_TYPE_SIZE);
742
    String family = familylength == 0? "":
860
    String family = familylength == 0? "":
743
      Bytes.toStringBinary(b, columnoffset, familylength);
861
      Bytes.toStringBinary(b, columnoffset, familylength);
744
    String qualifier = columnlength == 0? "":
862
    String qualifier = columnlength == 0? "":
745
      Bytes.toStringBinary(b, columnoffset + familylength,
863
      Bytes.toStringBinary(b, columnoffset + familylength,
746
      columnlength - familylength);
864
      columnlength - familylength);
747
    long timestamp = Bytes.toLong(b, o + (l - TIMESTAMP_TYPE_SIZE));
865
    long timestamp = Bytes.toLong(b, o + (l - TIMESTAMP_TYPE_SIZE));
748
    String timestampStr = humanReadableTimestamp(timestamp);
866
    String timestampStr = humanReadableTimestamp(timestamp);
749
    byte type = b[o + l - 1];
867
    byte type = b[o + l - 1];
750
    return row + "/" + family +
868
    return row + "/" + family +
751
      (family != null && family.length() > 0? ":" :"") +
869
      (family != null && family.length() > 0? ":" :"") +
752
      qualifier + "/" + timestampStr + "/" + Type.codeToType(type);
870
      qualifier + "/" + timestampStr + "/" + Type.codeToType(type);
753
  }
871
  }
754

    
   
872

   
755
  public static String humanReadableTimestamp(final long timestamp) {
873
  public static String humanReadableTimestamp(final long timestamp) {
756
    if (timestamp == HConstants.LATEST_TIMESTAMP) {
874
    if (timestamp == HConstants.LATEST_TIMESTAMP) {
757
      return "LATEST_TIMESTAMP";
875
      return "LATEST_TIMESTAMP";
758
    }
876
    }
759
    if (timestamp == HConstants.OLDEST_TIMESTAMP) {
877
    if (timestamp == HConstants.OLDEST_TIMESTAMP) {
760
      return "OLDEST_TIMESTAMP";
878
      return "OLDEST_TIMESTAMP";
761
    }
879
    }
762
    return String.valueOf(timestamp);
880
    return String.valueOf(timestamp);
763
  }
881
  }
764

    
   
882

   
765
  //---------------------------------------------------------------------------
883
  //---------------------------------------------------------------------------
766
  //
884
  //
767
  //  Public Member Accessors
885
  //  Public Member Accessors
768
  //
886
  //
769
  //---------------------------------------------------------------------------
887
  //---------------------------------------------------------------------------
770

    
   
888

   
771
  /**
889
  /**
772
   * @return The byte array backing this KeyValue.
890
   * @return The byte array backing this KeyValue.
773
   */
891
   */
774
  public byte [] getBuffer() {
892
  public byte [] getBuffer() {
775
    return this.bytes;
893
    return this.bytes;
776
  }
894
  }
777

    
   
895

   
778
  /**
896
  /**
779
   * @return Offset into {@link #getBuffer()} at which this KeyValue starts.
897
   * @return Offset into {@link #getBuffer()} at which this KeyValue starts.
780
   */
898
   */
781
  public int getOffset() {
899
  public int getOffset() {
782
    return this.offset;
900
    return this.offset;
783
  }
901
  }
784

    
   
902

   
785
  /**
903
  /**
786
   * @return Length of bytes this KeyValue occupies in {@link #getBuffer()}.
904
   * @return Length of bytes this KeyValue occupies in {@link #getBuffer()}.
787
   */
905
   */
788
  public int getLength() {
906
  public int getLength() {
789
    return length;
907
    return length;
790
  }
908
  }
791

    
   
909

   
792
  //---------------------------------------------------------------------------
910
  //---------------------------------------------------------------------------
793
  //
911
  //
794
  //  Length and Offset Calculators
912
  //  Length and Offset Calculators
795
  //
913
  //
796
  //---------------------------------------------------------------------------
914
  //---------------------------------------------------------------------------
797

    
   
915

   
798
  /**
916
  /**
799
   * Determines the total length of the KeyValue stored in the specified
917
   * Determines the total length of the KeyValue stored in the specified
800
   * byte array and offset.  Includes all headers.
918
   * byte array and offset.  Includes all headers.
801
   * @param bytes byte array
919
   * @param bytes byte array
802
   * @param offset offset to start of the KeyValue
920
   * @param offset offset to start of the KeyValue
803
   * @return length of entire KeyValue, in bytes
921
   * @return length of entire KeyValue, in bytes
804
   */
922
   */
805
  private static int getLength(byte [] bytes, int offset) {
923
  private static int getLength(byte [] bytes, int offset) {
806
    return ROW_OFFSET +
924
    return ROW_OFFSET +
807
        Bytes.toInt(bytes, offset) +
925
        Bytes.toInt(bytes, offset) +
808
        Bytes.toInt(bytes, offset + Bytes.SIZEOF_INT);
926
        Bytes.toInt(bytes, offset + Bytes.SIZEOF_INT);
809
  }
927
  }
810

    
   
928

   
811
  /**
929
  /**
812
   * @return Key offset in backing buffer..
930
   * @return Key offset in backing buffer..
813
   */
931
   */
814
  public int getKeyOffset() {
932
  public int getKeyOffset() {
815
    return this.offset + ROW_OFFSET;
933
    return this.offset + ROW_OFFSET;
816
  }
934
  }
817

    
   
935

   
818
  public String getKeyString() {
936
  public String getKeyString() {
819
    return Bytes.toStringBinary(getBuffer(), getKeyOffset(), getKeyLength());
937
    return Bytes.toStringBinary(getBuffer(), getKeyOffset(), getKeyLength());
820
  }
938
  }
821

    
   
939

   
822
  /**
940
  /**
823
   * @return Length of key portion.
941
   * @return Length of key portion.
824
   */
942
   */
825
  private int keyLength = 0;
943
  private int keyLength = 0;
826

    
   
944

   
827
  public int getKeyLength() {
945
  public int getKeyLength() {
828
    if (keyLength == 0) {
946
    if (keyLength == 0) {
829
      keyLength = Bytes.toInt(this.bytes, this.offset);
947
      keyLength = Bytes.toInt(this.bytes, this.offset);
830
    }
948
    }
831
    return keyLength;
949
    return keyLength;
832
  }
950
  }
833

    
   
951

   
834
  /**
952
  /**
835
   * @return Value offset
953
   * @return Value offset
836
   */
954
   */
837
  public int getValueOffset() {
955
  public int getValueOffset() {
838
    return getKeyOffset() + getKeyLength();
956
    return getKeyOffset() + getKeyLength();
839
  }
957
  }
840

    
   
958

   
841
  /**
959
  /**
842
   * @return Value length
960
   * @return Value length
843
   */
961
   */
844
  public int getValueLength() {
962
  public int getValueLength() {
845
    return Bytes.toInt(this.bytes, this.offset + Bytes.SIZEOF_INT);
963
    return Bytes.toInt(this.bytes, this.offset + Bytes.SIZEOF_INT);
846
  }
964
  }
847

    
   
965

   
848
  /**
966
  /**
849
   * @return Row offset
967
   * @return Row offset
850
   */
968
   */
851
  public int getRowOffset() {
969
  public int getRowOffset() {
852
    return getKeyOffset() + Bytes.SIZEOF_SHORT;
970
    return getKeyOffset() + Bytes.SIZEOF_SHORT;
853
  }
971
  }
854

    
   
972

   
855
  /**
973
  /**
856
   * @return Row length
974
   * @return Row length
857
   */
975
   */
858
  public short getRowLength() {
976
  public short getRowLength() {
859
    return Bytes.toShort(this.bytes, getKeyOffset());
977
    return Bytes.toShort(this.bytes, getKeyOffset());
860
  }
978
  }
861

    
   
979

   
862
  /**
980
  /**
863
   * @return Family offset
981
   * @return Family offset
864
   */
982
   */
865
  public int getFamilyOffset() {
983
  public int getFamilyOffset() {
866
    return getFamilyOffset(getRowLength());
984
    return getFamilyOffset(getRowLength());
867
  }
985
  }
868

    
   
986

   
869
  /**
987
  /**
870
   * @return Family offset
988
   * @return Family offset
871
   */
989
   */
872
  public int getFamilyOffset(int rlength) {
990
  public int getFamilyOffset(int rlength) {
873
    return this.offset + ROW_OFFSET + Bytes.SIZEOF_SHORT + rlength + Bytes.SIZEOF_BYTE;
991
    return this.offset + ROW_OFFSET + Bytes.SIZEOF_SHORT + rlength + Bytes.SIZEOF_BYTE;
874
  }
992
  }
875

    
   
993

   
876
  /**
994
  /**
877
   * @return Family length
995
   * @return Family length
878
   */
996
   */
879
  public byte getFamilyLength() {
997
  public byte getFamilyLength() {
880
    return getFamilyLength(getFamilyOffset());
998
    return getFamilyLength(getFamilyOffset());
881
  }
999
  }
882

    
   
1000

   
883
  /**
1001
  /**
884
   * @return Family length
1002
   * @return Family length
885
   */
1003
   */
886
  public byte getFamilyLength(int foffset) {
1004
  public byte getFamilyLength(int foffset) {
887
    return this.bytes[foffset-1];
1005
    return this.bytes[foffset-1];
888
  }
1006
  }
889

    
   
1007

   
890
  /**
1008
  /**
891
   * @return Qualifier offset
1009
   * @return Qualifier offset
892
   */
1010
   */
893
  public int getQualifierOffset() {
1011
  public int getQualifierOffset() {
894
    return getQualifierOffset(getFamilyOffset());
1012
    return getQualifierOffset(getFamilyOffset());
895
  }
1013
  }
896

    
   
1014

   
897
  /**
1015
  /**
898
   * @return Qualifier offset
1016
   * @return Qualifier offset
899
   */
1017
   */
900
  public int getQualifierOffset(int foffset) {
1018
  public int getQualifierOffset(int foffset) {
901
    return foffset + getFamilyLength(foffset);
1019
    return foffset + getFamilyLength(foffset);
902
  }
1020
  }
903

    
   
1021

   
904
  /**
1022
  /**
905
   * @return Qualifier length
1023
   * @return Qualifier length
906
   */
1024
   */
907
  public int getQualifierLength() {
1025
  public int getQualifierLength() {
908
    return getQualifierLength(getRowLength(),getFamilyLength());
1026
    return getQualifierLength(getRowLength(),getFamilyLength());
909
  }
1027
  }
910

    
   
1028

   
911
  /**
1029
  /**
912
   * @return Qualifier length
1030
   * @return Qualifier length
913
   */
1031
   */
914
  public int getQualifierLength(int rlength, int flength) {
1032
  public int getQualifierLength(int rlength, int flength) {
915
    return getKeyLength() -
1033
    return getKeyLength() -
916
      (KEY_INFRASTRUCTURE_SIZE + rlength + flength);
1034
      (KEY_INFRASTRUCTURE_SIZE + rlength + flength);
917
  }
1035
  }
918

    
   
1036

   
919
  /**
1037
  /**
920
   * @return Column (family + qualifier) length
1038
   * @return Column (family + qualifier) length
921
   */
1039
   */
922
  public int getTotalColumnLength() {
1040
  public int getTotalColumnLength() {
923
    int rlength = getRowLength();
1041
    int rlength = getRowLength();
924
    int foffset = getFamilyOffset(rlength);
1042
    int foffset = getFamilyOffset(rlength);
925
    return getTotalColumnLength(rlength,foffset);
1043
    return getTotalColumnLength(rlength,foffset);
926
  }
1044
  }
927

    
   
1045

   
928
  /**
1046
  /**
929
   * @return Column (family + qualifier) length
1047
   * @return Column (family + qualifier) length
930
   */
1048
   */
931
  public int getTotalColumnLength(int rlength, int foffset) {
1049
  public int getTotalColumnLength(int rlength, int foffset) {
932
    int flength = getFamilyLength(foffset);
1050
    int flength = getFamilyLength(foffset);
933
    int qlength = getQualifierLength(rlength,flength);
1051
    int qlength = getQualifierLength(rlength,flength);
934
    return flength + qlength;
1052
    return flength + qlength;
935
  }
1053
  }
936

    
   
1054

   
937
  /**
1055
  /**
938
   * @return Timestamp offset
1056
   * @return Timestamp offset
939
   */
1057
   */
940
  public int getTimestampOffset() {
1058
  public int getTimestampOffset() {
941
    return getTimestampOffset(getKeyLength());
1059
    return getTimestampOffset(getKeyLength());
942
  }
1060
  }
943

    
   
1061

   
944
  /**
1062
  /**
945
   * @param keylength Pass if you have it to save on a int creation.
1063
   * @param keylength Pass if you have it to save on a int creation.
946
   * @return Timestamp offset
1064
   * @return Timestamp offset
947
   */
1065
   */
948
  public int getTimestampOffset(final int keylength) {
1066
  public int getTimestampOffset(final int keylength) {
949
    return getKeyOffset() + keylength - TIMESTAMP_TYPE_SIZE;
1067
    return getKeyOffset() + keylength - TIMESTAMP_TYPE_SIZE;
950
  }
1068
  }
951

    
   
1069

   
952
  /**
1070
  /**
953
   * @return True if this KeyValue has a LATEST_TIMESTAMP timestamp.
1071
   * @return True if this KeyValue has a LATEST_TIMESTAMP timestamp.
954
   */
1072
   */
955
  public boolean isLatestTimestamp() {
1073
  public boolean isLatestTimestamp() {
956
    return Bytes.equals(getBuffer(), getTimestampOffset(), Bytes.SIZEOF_LONG,
1074
    return Bytes.equals(getBuffer(), getTimestampOffset(), Bytes.SIZEOF_LONG,
957
      HConstants.LATEST_TIMESTAMP_BYTES, 0, Bytes.SIZEOF_LONG);
1075
      HConstants.LATEST_TIMESTAMP_BYTES, 0, Bytes.SIZEOF_LONG);
958
  }
1076
  }
959

    
   
1077

   
960
  /**
1078
  /**
961
   * @param now Time to set into <code>this</code> IFF timestamp ==
1079
   * @param now Time to set into <code>this</code> IFF timestamp ==
962
   * {@link HConstants#LATEST_TIMESTAMP} (else, its a noop).
1080
   * {@link HConstants#LATEST_TIMESTAMP} (else, its a noop).
963
   * @return True is we modified this.
1081
   * @return True is we modified this.
964
   */
1082
   */
965
  public boolean updateLatestStamp(final byte [] now) {
1083
  public boolean updateLatestStamp(final byte [] now) {
966
    if (this.isLatestTimestamp()) {
1084
    if (this.isLatestTimestamp()) {
967
      int tsOffset = getTimestampOffset();
1085
      int tsOffset = getTimestampOffset();
968
      System.arraycopy(now, 0, this.bytes, tsOffset, Bytes.SIZEOF_LONG);
1086
      System.arraycopy(now, 0, this.bytes, tsOffset, Bytes.SIZEOF_LONG);
969
      return true;
1087
      return true;
970
    }
1088
    }
971
    return false;
1089
    return false;
972
  }
1090
  }
973

    
   
1091

   
974
  //---------------------------------------------------------------------------
1092
  //---------------------------------------------------------------------------
975
  //
1093
  //
976
  //  Methods that return copies of fields
1094
  //  Methods that return copies of fields
977
  //
1095
  //
978
  //---------------------------------------------------------------------------
1096
  //---------------------------------------------------------------------------
979

    
   
1097

   
980
  /**
1098
  /**
981
   * Do not use unless you have to.  Used internally for compacting and testing.
1099
   * Do not use unless you have to.  Used internally for compacting and testing.
982
   *
1100
   *
983
   * Use {@link #getRow()}, {@link #getFamily()}, {@link #getQualifier()}, and
1101
   * Use {@link #getRow()}, {@link #getFamily()}, {@link #getQualifier()}, and
984
   * {@link #getValue()} if accessing a KeyValue client-side.
1102
   * {@link #getValue()} if accessing a KeyValue client-side.
985
   * @return Copy of the key portion only.
1103
   * @return Copy of the key portion only.
986
   */
1104
   */
987
  public byte [] getKey() {
1105
  public byte [] getKey() {
988
    int keylength = getKeyLength();
1106
    int keylength = getKeyLength();
989
    byte [] key = new byte[keylength];
1107
    byte [] key = new byte[keylength];
990
    System.arraycopy(getBuffer(), getKeyOffset(), key, 0, keylength);
1108
    System.arraycopy(getBuffer(), getKeyOffset(), key, 0, keylength);
991
    return key;
1109
    return key;
992
  }
1110
  }
993

    
   
1111

   
994
  /**
1112
  /**
995
   * Returns value in a new byte array.
1113
   * Returns value in a new byte array.
996
   * Primarily for use client-side. If server-side, use
1114
   * Primarily for use client-side. If server-side, use
997
   * {@link #getBuffer()} with appropriate offsets and lengths instead to
1115
   * {@link #getBuffer()} with appropriate offsets and lengths instead to
998
   * save on allocations.
1116
   * save on allocations.
999
   * @return Value in a new byte array.
1117
   * @return Value in a new byte array.
1000
   */
1118
   */
1001
  public byte [] getValue() {
1119
  public byte [] getValue() {
1002
    int o = getValueOffset();
1120
    int o = getValueOffset();
1003
    int l = getValueLength();
1121
    int l = getValueLength();
1004
    byte [] result = new byte[l];
1122
    byte [] result = new byte[l];
1005
    System.arraycopy(getBuffer(), o, result, 0, l);
1123
    System.arraycopy(getBuffer(), o, result, 0, l);
1006
    return result;
1124
    return result;
1007
  }
1125
  }
1008

    
   
1126

   
1009
  /**
1127
  /**

    
   
1128
   * Loads this object's value into the provided <code>ByteBuffer</code>.

    
   
1129
   * <p>

    
   
1130
   * Does not clear or flip the buffer.

    
   
1131
   *

    
   
1132
   * @param dst the buffer where to write the value

    
   
1133
   *

    
   
1134
   * @throws BufferOverflowException there is insufficient space remaining in the buffer

    
   
1135
   */

    
   
1136
  public void loadValue(ByteBuffer dst)

    
   
1137
          throws BufferOverflowException {

    
   
1138
    dst.put(getBuffer(), getValueOffset(), getValueLength());

    
   
1139
  }

    
   
1140

   

    
   
1141
  /**
1010
   * Primarily for use client-side.  Returns the row of this KeyValue in a new
1142
   * Primarily for use client-side.  Returns the row of this KeyValue in a new
1011
   * byte array.<p>
1143
   * byte array.<p>
1012
   *
1144
   *
1013
   * If server-side, use {@link #getBuffer()} with appropriate offsets and
1145
   * If server-side, use {@link #getBuffer()} with appropriate offsets and
1014
   * lengths instead.
1146
   * lengths instead.
1015
   * @return Row in a new byte array.
1147
   * @return Row in a new byte array.
1016
   */
1148
   */
1017
  public byte [] getRow() {
1149
  public byte [] getRow() {
1018
    if (rowCache == null) {
1150
    if (rowCache == null) {
1019
      int o = getRowOffset();
1151
      int o = getRowOffset();
1020
      short l = getRowLength();
1152
      short l = getRowLength();
1021
      // initialize and copy the data into a local variable
1153
      // initialize and copy the data into a local variable
1022
      // in case multiple threads race here.
1154
      // in case multiple threads race here.
1023
      byte local[] = new byte[l];
1155
      byte local[] = new byte[l];
1024
      System.arraycopy(getBuffer(), o, local, 0, l);
1156
      System.arraycopy(getBuffer(), o, local, 0, l);
1025
      rowCache = local; // volatile assign
1157
      rowCache = local; // volatile assign
1026
    }
1158
    }
1027
    return rowCache;
1159
    return rowCache;
1028
  }
1160
  }
1029

    
   
1161

   
1030
  /**
1162
  /**
1031
   *
1163
   *
1032
   * @return Timestamp
1164
   * @return Timestamp
1033
   */
1165
   */
1034
  private long timestampCache = -1;
1166
  private long timestampCache = -1;
1035
  public long getTimestamp() {
1167
  public long getTimestamp() {
1036
    if (timestampCache == -1) {
1168
    if (timestampCache == -1) {
1037
      timestampCache = getTimestamp(getKeyLength());
1169
      timestampCache = getTimestamp(getKeyLength());
1038
    }
1170
    }
1039
    return timestampCache;
1171
    return timestampCache;
1040
  }
1172
  }
1041

    
   
1173

   
1042
  /**
1174
  /**
1043
   * @param keylength Pass if you have it to save on a int creation.
1175
   * @param keylength Pass if you have it to save on a int creation.
1044
   * @return Timestamp
1176
   * @return Timestamp
1045
   */
1177
   */
1046
  long getTimestamp(final int keylength) {
1178
  long getTimestamp(final int keylength) {
1047
    int tsOffset = getTimestampOffset(keylength);
1179
    int tsOffset = getTimestampOffset(keylength);
1048
    return Bytes.toLong(this.bytes, tsOffset);
1180
    return Bytes.toLong(this.bytes, tsOffset);
1049
  }
1181
  }
1050

    
   
1182

   
1051
  /**
1183
  /**
1052
   * @return Type of this KeyValue.
1184
   * @return Type of this KeyValue.
1053
   */
1185
   */
1054
  public byte getType() {
1186
  public byte getType() {
1055
    return getType(getKeyLength());
1187
    return getType(getKeyLength());
1056
  }
1188
  }
1057

    
   
1189

   
1058
  /**
1190
  /**
1059
   * @param keylength Pass if you have it to save on a int creation.
1191
   * @param keylength Pass if you have it to save on a int creation.
1060
   * @return Type of this KeyValue.
1192
   * @return Type of this KeyValue.
1061
   */
1193
   */
1062
  byte getType(final int keylength) {
1194
  byte getType(final int keylength) {
1063
    return this.bytes[this.offset + keylength - 1 + ROW_OFFSET];
1195
    return this.bytes[this.offset + keylength - 1 + ROW_OFFSET];
1064
  }
1196
  }
1065

    
   
1197

   
1066
  /**
1198
  /**
1067
   * @return True if a delete type, a {@link KeyValue.Type#Delete} or
1199
   * @return True if a delete type, a {@link KeyValue.Type#Delete} or
1068
   * a {KeyValue.Type#DeleteFamily} or a {@link KeyValue.Type#DeleteColumn}
1200
   * a {KeyValue.Type#DeleteFamily} or a {@link KeyValue.Type#DeleteColumn}
1069
   * KeyValue type.
1201
   * KeyValue type.
1070
   */
1202
   */
1071
  public boolean isDelete() {
1203
  public boolean isDelete() {
1072
    return KeyValue.isDelete(getType());
1204
    return KeyValue.isDelete(getType());
1073
  }
1205
  }
1074

    
   
1206

   
1075
  /**
1207
  /**
1076
   * @return True if this KV is a {@link KeyValue.Type#Delete} type.
1208
   * @return True if this KV is a {@link KeyValue.Type#Delete} type.
1077
   */
1209
   */
1078
  public boolean isDeleteType() {
1210
  public boolean isDeleteType() {
1079
    // TODO: Fix this method name vis-a-vis isDelete!
1211
    // TODO: Fix this method name vis-a-vis isDelete!
1080
    return getType() == Type.Delete.getCode();
1212
    return getType() == Type.Delete.getCode();
1081
  }
1213
  }
1082

    
   
1214

   
1083
  /**
1215
  /**
1084
   * @return True if this KV is a delete family type.
1216
   * @return True if this KV is a delete family type.
1085
   */
1217
   */
1086
  public boolean isDeleteFamily() {
1218
  public boolean isDeleteFamily() {
1087
    return getType() == Type.DeleteFamily.getCode();
1219
    return getType() == Type.DeleteFamily.getCode();
1088
  }
1220
  }
1089

    
   
1221

   
1090
  /**
1222
  /**
1091
   *
1223
   *
1092
   * @return True if this KV is a delete family or column type.
1224
   * @return True if this KV is a delete family or column type.
1093
   */
1225
   */
1094
  public boolean isDeleteColumnOrFamily() {
1226
  public boolean isDeleteColumnOrFamily() {
1095
    int t = getType();
1227
    int t = getType();
1096
    return t == Type.DeleteColumn.getCode() || t == Type.DeleteFamily.getCode();
1228
    return t == Type.DeleteColumn.getCode() || t == Type.DeleteFamily.getCode();
1097
  }
1229
  }
1098

    
   
1230

   
1099
  /**
1231
  /**
1100
   * Primarily for use client-side.  Returns the family of this KeyValue in a
1232
   * Primarily for use client-side.  Returns the family of this KeyValue in a
1101
   * new byte array.<p>
1233
   * new byte array.<p>
1102
   *
1234
   *
1103
   * If server-side, use {@link #getBuffer()} with appropriate offsets and
1235
   * If server-side, use {@link #getBuffer()} with appropriate offsets and
1104
   * lengths instead.
1236
   * lengths instead.
1105
   * @return Returns family. Makes a copy.
1237
   * @return Returns family. Makes a copy.
1106
   */
1238
   */
1107
  public byte [] getFamily() {
1239
  public byte [] getFamily() {
1108
    int o = getFamilyOffset();
1240
    int o = getFamilyOffset();
1109
    int l = getFamilyLength(o);
1241
    int l = getFamilyLength(o);
1110
    byte [] result = new byte[l];
1242
    byte [] result = new byte[l];
1111
    System.arraycopy(this.bytes, o, result, 0, l);
1243
    System.arraycopy(this.bytes, o, result, 0, l);
1112
    return result;
1244
    return result;
1113
  }
1245
  }
1114

    
   
1246

   
1115
  /**
1247
  /**
1116
   * Primarily for use client-side.  Returns the column qualifier of this
1248
   * Primarily for use client-side.  Returns the column qualifier of this
1117
   * KeyValue in a new byte array.<p>
1249
   * KeyValue in a new byte array.<p>
1118
   *
1250
   *
1119
   * If server-side, use {@link #getBuffer()} with appropriate offsets and
1251
   * If server-side, use {@link #getBuffer()} with appropriate offsets and
1120
   * lengths instead.
1252
   * lengths instead.
1121
   * Use {@link #getBuffer()} with appropriate offsets and lengths instead.
1253
   * Use {@link #getBuffer()} with appropriate offsets and lengths instead.
1122
   * @return Returns qualifier. Makes a copy.
1254
   * @return Returns qualifier. Makes a copy.
1123
   */
1255
   */
1124
  public byte [] getQualifier() {
1256
  public byte [] getQualifier() {
1125
    int o = getQualifierOffset();
1257
    int o = getQualifierOffset();
1126
    int l = getQualifierLength();
1258
    int l = getQualifierLength();
1127
    byte [] result = new byte[l];
1259
    byte [] result = new byte[l];
1128
    System.arraycopy(this.bytes, o, result, 0, l);
1260
    System.arraycopy(this.bytes, o, result, 0, l);
1129
    return result;
1261
    return result;
1130
  }
1262
  }
1131

    
   
1263

   
1132
  //---------------------------------------------------------------------------
1264
  //---------------------------------------------------------------------------
1133
  //
1265
  //
1134
  //  KeyValue splitter
1266
  //  KeyValue splitter
1135
  //
1267
  //
1136
  //---------------------------------------------------------------------------
1268
  //---------------------------------------------------------------------------
1137

    
   
1269

   
1138
  /**
1270
  /**
1139
   * Utility class that splits a KeyValue buffer into separate byte arrays.
1271
   * Utility class that splits a KeyValue buffer into separate byte arrays.
1140
   * <p>
1272
   * <p>
1141
   * Should get rid of this if we can, but is very useful for debugging.
1273
   * Should get rid of this if we can, but is very useful for debugging.
1142
   */
1274
   */
1143
  public static class SplitKeyValue {
1275
  public static class SplitKeyValue {
1144
    private byte [][] split;
1276
    private byte [][] split;
1145
    SplitKeyValue() {
1277
    SplitKeyValue() {
1146
      this.split = new byte[6][];
1278
      this.split = new byte[6][];
1147
    }
1279
    }
1148
    public void setRow(byte [] value) { this.split[0] = value; }
1280
    public void setRow(byte [] value) { this.split[0] = value; }
1149
    public void setFamily(byte [] value) { this.split[1] = value; }
1281
    public void setFamily(byte [] value) { this.split[1] = value; }
1150
    public void setQualifier(byte [] value) { this.split[2] = value; }
1282
    public void setQualifier(byte [] value) { this.split[2] = value; }
1151
    public void setTimestamp(byte [] value) { this.split[3] = value; }
1283
    public void setTimestamp(byte [] value) { this.split[3] = value; }
1152
    public void setType(byte [] value) { this.split[4] = value; }
1284
    public void setType(byte [] value) { this.split[4] = value; }
1153
    public void setValue(byte [] value) { this.split[5] = value; }
1285
    public void setValue(byte [] value) { this.split[5] = value; }
1154
    public byte [] getRow() { return this.split[0]; }
1286
    public byte [] getRow() { return this.split[0]; }
1155
    public byte [] getFamily() { return this.split[1]; }
1287
    public byte [] getFamily() { return this.split[1]; }
1156
    public byte [] getQualifier() { return this.split[2]; }
1288
    public byte [] getQualifier() { return this.split[2]; }
1157
    public byte [] getTimestamp() { return this.split[3]; }
1289
    public byte [] getTimestamp() { return this.split[3]; }
1158
    public byte [] getType() { return this.split[4]; }
1290
    public byte [] getType() { return this.split[4]; }
1159
    public byte [] getValue() { return this.split[5]; }
1291
    public byte [] getValue() { return this.split[5]; }
1160
  }
1292
  }
1161

    
   
1293

   
1162
  public SplitKeyValue split() {
1294
  public SplitKeyValue split() {
1163
    SplitKeyValue split = new SplitKeyValue();
1295
    SplitKeyValue split = new SplitKeyValue();
1164
    int splitOffset = this.offset;
1296
    int splitOffset = this.offset;
1165
    int keyLen = Bytes.toInt(bytes, splitOffset);
1297
    int keyLen = Bytes.toInt(bytes, splitOffset);
1166
    splitOffset += Bytes.SIZEOF_INT;
1298
    splitOffset += Bytes.SIZEOF_INT;
1167
    int valLen = Bytes.toInt(bytes, splitOffset);
1299
    int valLen = Bytes.toInt(bytes, splitOffset);
1168
    splitOffset += Bytes.SIZEOF_INT;
1300
    splitOffset += Bytes.SIZEOF_INT;
1169
    short rowLen = Bytes.toShort(bytes, splitOffset);
1301
    short rowLen = Bytes.toShort(bytes, splitOffset);
1170
    splitOffset += Bytes.SIZEOF_SHORT;
1302
    splitOffset += Bytes.SIZEOF_SHORT;
1171
    byte [] row = new byte[rowLen];
1303
    byte [] row = new byte[rowLen];
1172
    System.arraycopy(bytes, splitOffset, row, 0, rowLen);
1304
    System.arraycopy(bytes, splitOffset, row, 0, rowLen);
1173
    splitOffset += rowLen;
1305
    splitOffset += rowLen;
1174
    split.setRow(row);
1306
    split.setRow(row);
1175
    byte famLen = bytes[splitOffset];
1307
    byte famLen = bytes[splitOffset];
1176
    splitOffset += Bytes.SIZEOF_BYTE;
1308
    splitOffset += Bytes.SIZEOF_BYTE;
1177
    byte [] family = new byte[famLen];
1309
    byte [] family = new byte[famLen];
1178
    System.arraycopy(bytes, splitOffset, family, 0, famLen);
1310
    System.arraycopy(bytes, splitOffset, family, 0, famLen);
1179
    splitOffset += famLen;
1311
    splitOffset += famLen;
1180
    split.setFamily(family);
1312
    split.setFamily(family);
1181
    int colLen = keyLen -
1313
    int colLen = keyLen -
1182
      (rowLen + famLen + Bytes.SIZEOF_SHORT + Bytes.SIZEOF_BYTE +
1314
      (rowLen + famLen + Bytes.SIZEOF_SHORT + Bytes.SIZEOF_BYTE +
1183
      Bytes.SIZEOF_LONG + Bytes.SIZEOF_BYTE);
1315
      Bytes.SIZEOF_LONG + Bytes.SIZEOF_BYTE);
1184
    byte [] qualifier = new byte[colLen];
1316
    byte [] qualifier = new byte[colLen];
1185
    System.arraycopy(bytes, splitOffset, qualifier, 0, colLen);
1317
    System.arraycopy(bytes, splitOffset, qualifier, 0, colLen);
1186
    splitOffset += colLen;
1318
    splitOffset += colLen;
1187
    split.setQualifier(qualifier);
1319
    split.setQualifier(qualifier);
1188
    byte [] timestamp = new byte[Bytes.SIZEOF_LONG];
1320
    byte [] timestamp = new byte[Bytes.SIZEOF_LONG];
1189
    System.arraycopy(bytes, splitOffset, timestamp, 0, Bytes.SIZEOF_LONG);
1321
    System.arraycopy(bytes, splitOffset, timestamp, 0, Bytes.SIZEOF_LONG);
1190
    splitOffset += Bytes.SIZEOF_LONG;
1322
    splitOffset += Bytes.SIZEOF_LONG;
1191
    split.setTimestamp(timestamp);
1323
    split.setTimestamp(timestamp);
1192
    byte [] type = new byte[1];
1324
    byte [] type = new byte[1];
1193
    type[0] = bytes[splitOffset];
1325
    type[0] = bytes[splitOffset];
1194
    splitOffset += Bytes.SIZEOF_BYTE;
1326
    splitOffset += Bytes.SIZEOF_BYTE;
1195
    split.setType(type);
1327
    split.setType(type);
1196
    byte [] value = new byte[valLen];
1328
    byte [] value = new byte[valLen];
1197
    System.arraycopy(bytes, splitOffset, value, 0, valLen);
1329
    System.arraycopy(bytes, splitOffset, value, 0, valLen);
1198
    split.setValue(value);
1330
    split.setValue(value);
1199
    return split;
1331
    return split;
1200
  }
1332
  }
1201

    
   
1333

   
1202
  //---------------------------------------------------------------------------
1334
  //---------------------------------------------------------------------------
1203
  //
1335
  //
1204
  //  Compare specified fields against those contained in this KeyValue
1336
  //  Compare specified fields against those contained in this KeyValue
1205
  //
1337
  //
1206
  //---------------------------------------------------------------------------
1338
  //---------------------------------------------------------------------------
1207

    
   
1339

   
1208
  /**
1340
  /**
1209
   * @param family
1341
   * @param family
1210
   * @return True if matching families.
1342
   * @return True if matching families.
1211
   */
1343
   */
1212
  public boolean matchingFamily(final byte [] family) {
1344
  public boolean matchingFamily(final byte [] family) {
1213
    return matchingFamily(family, 0, family.length);
1345
    return matchingFamily(family, 0, family.length);
1214
  }
1346
  }
1215

    
   
1347

   
1216
  public boolean matchingFamily(final byte[] family, int offset, int length) {
1348
  public boolean matchingFamily(final byte[] family, int offset, int length) {
1217
    if (this.length == 0 || this.bytes.length == 0) {
1349
    if (this.length == 0 || this.bytes.length == 0) {
1218
      return false;
1350
      return false;
1219
    }
1351
    }
1220
    return Bytes.equals(family, offset, length,
1352
    return Bytes.equals(family, offset, length,
1221
        this.bytes, getFamilyOffset(), getFamilyLength());
1353
        this.bytes, getFamilyOffset(), getFamilyLength());
1222
  }
1354
  }
1223

    
   
1355

   
1224
  public boolean matchingFamily(final KeyValue other) {
1356
  public boolean matchingFamily(final KeyValue other) {
1225
    return matchingFamily(other.getBuffer(), other.getFamilyOffset(),
1357
    return matchingFamily(other.getBuffer(), other.getFamilyOffset(),
1226
        other.getFamilyLength());
1358
        other.getFamilyLength());
1227
  }
1359
  }
1228

    
   
1360

   
1229
  /**
1361
  /**
1230
   * @param qualifier
1362
   * @param qualifier
1231
   * @return True if matching qualifiers.
1363
   * @return True if matching qualifiers.
1232
   */
1364
   */
1233
  public boolean matchingQualifier(final byte [] qualifier) {
1365
  public boolean matchingQualifier(final byte [] qualifier) {
1234
    return matchingQualifier(qualifier, 0, qualifier.length);
1366
    return matchingQualifier(qualifier, 0, qualifier.length);
1235
  }
1367
  }
1236

    
   
1368

   
1237
  public boolean matchingQualifier(final byte [] qualifier, int offset, int length) {
1369
  public boolean matchingQualifier(final byte [] qualifier, int offset, int length) {
1238
    return Bytes.equals(qualifier, offset, length,
1370
    return Bytes.equals(qualifier, offset, length,
1239
        this.bytes, getQualifierOffset(), getQualifierLength());
1371
        this.bytes, getQualifierOffset(), getQualifierLength());
1240
  }
1372
  }
1241

    
   
1373

   
1242
  public boolean matchingQualifier(final KeyValue other) {
1374
  public boolean matchingQualifier(final KeyValue other) {
1243
    return matchingQualifier(other.getBuffer(), other.getQualifierOffset(),
1375
    return matchingQualifier(other.getBuffer(), other.getQualifierOffset(),
1244
        other.getQualifierLength());
1376
        other.getQualifierLength());
1245
  }
1377
  }
1246

    
   
1378

   
1247
  public boolean matchingRow(final byte [] row) {
1379
  public boolean matchingRow(final byte [] row) {
1248
    return matchingRow(row, 0, row.length);
1380
    return matchingRow(row, 0, row.length);
1249
  }
1381
  }
1250

    
   
1382

   
1251
  public boolean matchingRow(final byte[] row, int offset, int length) {
1383
  public boolean matchingRow(final byte[] row, int offset, int length) {
1252
    return Bytes.equals(row, offset, length,
1384
    return Bytes.equals(row, offset, length,
1253
        this.bytes, getRowOffset(), getRowLength());
1385
        this.bytes, getRowOffset(), getRowLength());
1254
  }
1386
  }
1255

    
   
1387

   
1256
  public boolean matchingRow(KeyValue other) {
1388
  public boolean matchingRow(KeyValue other) {
1257
    return matchingRow(other.getBuffer(), other.getRowOffset(),
1389
    return matchingRow(other.getBuffer(), other.getRowOffset(),
1258
        other.getRowLength());
1390
        other.getRowLength());
1259
  }
1391
  }
1260

    
   
1392

   
1261
  /**
1393
  /**
1262
   * @param column Column minus its delimiter
1394
   * @param column Column minus its delimiter
1263
   * @return True if column matches.
1395
   * @return True if column matches.
1264
   */
1396
   */
1265
  public boolean matchingColumnNoDelimiter(final byte [] column) {
1397
  public boolean matchingColumnNoDelimiter(final byte [] column) {
1266
    int rl = getRowLength();
1398
    int rl = getRowLength();
1267
    int o = getFamilyOffset(rl);
1399
    int o = getFamilyOffset(rl);
1268
    int fl = getFamilyLength(o);
1400
    int fl = getFamilyLength(o);
1269
    int l = fl + getQualifierLength(rl,fl);
1401
    int l = fl + getQualifierLength(rl,fl);
1270
    return Bytes.equals(column, 0, column.length, this.bytes, o, l);
1402
    return Bytes.equals(column, 0, column.length, this.bytes, o, l);
1271
  }
1403
  }
1272

    
   
1404

   
1273
  /**
1405
  /**
1274
   *
1406
   *
1275
   * @param family column family
1407
   * @param family column family
1276
   * @param qualifier column qualifier
1408
   * @param qualifier column qualifier
1277
   * @return True if column matches
1409
   * @return True if column matches
1278
   */
1410
   */
1279
  public boolean matchingColumn(final byte[] family, final byte[] qualifier) {
1411
  public boolean matchingColumn(final byte[] family, final byte[] qualifier) {
1280
    int rl = getRowLength();
1412
    int rl = getRowLength();
1281
    int o = getFamilyOffset(rl);
1413
    int o = getFamilyOffset(rl);
1282
    int fl = getFamilyLength(o);
1414
    int fl = getFamilyLength(o);
1283
    int ql = getQualifierLength(rl,fl);
1415
    int ql = getQualifierLength(rl,fl);
1284
    if (!Bytes.equals(family, 0, family.length, this.bytes, o, fl)) {
1416
    if (!Bytes.equals(family, 0, family.length, this.bytes, o, fl)) {
1285
      return false;
1417
      return false;
1286
    }
1418
    }
1287
    if (qualifier == null || qualifier.length == 0) {
1419
    if (qualifier == null || qualifier.length == 0) {
1288
      if (ql == 0) {
1420
      if (ql == 0) {
1289
        return true;
1421
        return true;
1290
      }
1422
      }
1291
      return false;
1423
      return false;
1292
    }
1424
    }
1293
    return Bytes.equals(qualifier, 0, qualifier.length,
1425
    return Bytes.equals(qualifier, 0, qualifier.length,
1294
        this.bytes, o + fl, ql);
1426
        this.bytes, o + fl, ql);
1295
  }
1427
  }
1296

    
   
1428

   
1297
  /**
1429
  /**

    
   
1430
   * Checks if column matches.

    
   
1431
   *

    
   
1432
   * @param family family name

    
   
1433
   * @param foffset family offset

    
   
1434
   * @param flength family length

    
   
1435
   * @param qualifier column qualifier

    
   
1436
   * @param qoffset qualifier offset

    
   
1437
   * @param qlength qualifier length

    
   
1438
   *

    
   
1439
   * @return True if column matches

    
   
1440
   */

    
   
1441
  public boolean matchingColumn(final byte [] family,    final int foffset, final int flength,

    
   
1442
                                final byte [] qualifier, final int qoffset, final int qlength) {

    
   
1443
    int rl = getRowLength();

    
   
1444
    int o  = getFamilyOffset(rl);

    
   
1445
    int fl = getFamilyLength(o);

    
   
1446
    int ql = getQualifierLength(rl,fl);

    
   
1447

   

    
   
1448
    if (!Bytes.equals(family, foffset, flength, this.bytes, o, fl)) {

    
   
1449
      return false;

    
   
1450
    }

    
   
1451
    if (qualifier == null || qlength == 0) {

    
   
1452
      return (ql == 0);

    
   
1453
    }

    
   
1454
    return Bytes.equals(qualifier, qoffset, qlength, this.bytes, o + fl, ql);

    
   
1455
  }

    
   
1456

   

    
   
1457
  /**
1298
   * @param left
1458
   * @param left
1299
   * @param loffset
1459
   * @param loffset
1300
   * @param llength
1460
   * @param llength
1301
   * @param lfamilylength Offset of family delimiter in left column.
1461
   * @param lfamilylength Offset of family delimiter in left column.
1302
   * @param right
1462
   * @param right
1303
   * @param roffset
1463
   * @param roffset
1304
   * @param rlength
1464
   * @param rlength
1305
   * @param rfamilylength Offset of family delimiter in right column.
1465
   * @param rfamilylength Offset of family delimiter in right column.
1306
   * @return The result of the comparison.
1466
   * @return The result of the comparison.
1307
   */
1467
   */
1308
  static int compareColumns(final byte [] left, final int loffset,
1468
  static int compareColumns(final byte [] left, final int loffset,
1309
      final int llength, final int lfamilylength,
1469
      final int llength, final int lfamilylength,
1310
      final byte [] right, final int roffset, final int rlength,
1470
      final byte [] right, final int roffset, final int rlength,
1311
      final int rfamilylength) {
1471
      final int rfamilylength) {
1312
    // Compare family portion first.
1472
    // Compare family portion first.
1313
    int diff = Bytes.compareTo(left, loffset, lfamilylength,
1473
    int diff = Bytes.compareTo(left, loffset, lfamilylength,
1314
      right, roffset, rfamilylength);
1474
      right, roffset, rfamilylength);
1315
    if (diff != 0) {
1475
    if (diff != 0) {
1316
      return diff;
1476
      return diff;
1317
    }
1477
    }
1318
    // Compare qualifier portion
1478
    // Compare qualifier portion
1319
    return Bytes.compareTo(left, loffset + lfamilylength,
1479
    return Bytes.compareTo(left, loffset + lfamilylength,
1320
      llength - lfamilylength,
1480
      llength - lfamilylength,
1321
      right, roffset + rfamilylength, rlength - rfamilylength);
1481
      right, roffset + rfamilylength, rlength - rfamilylength);
1322
  }
1482
  }
1323

    
   
1483

   
1324
  /**
1484
  /**
1325
   * @return True if non-null row and column.
1485
   * @return True if non-null row and column.
1326
   */
1486
   */
1327
  public boolean nonNullRowAndColumn() {
1487
  public boolean nonNullRowAndColumn() {
1328
    return getRowLength() > 0 && !isEmptyColumn();
1488
    return getRowLength() > 0 && !isEmptyColumn();
1329
  }
1489
  }
1330

    
   
1490

   
1331
  /**
1491
  /**
1332
   * @return True if column is empty.
1492
   * @return True if column is empty.
1333
   */
1493
   */
1334
  public boolean isEmptyColumn() {
1494
  public boolean isEmptyColumn() {
1335
    return getQualifierLength() == 0;
1495
    return getQualifierLength() == 0;
1336
  }
1496
  }
1337

    
   
1497

   
1338
  /**
1498
  /**
1339
   * Creates a new KeyValue that only contains the key portion (the value is
1499
   * Creates a new KeyValue that only contains the key portion (the value is
1340
   * set to be null).
1500
   * set to be null).
1341
   * @param lenAsVal replace value with the actual value length (false=empty)
1501
   * @param lenAsVal replace value with the actual value length (false=empty)
1342
   */
1502
   */
1343
  public KeyValue createKeyOnly(boolean lenAsVal) {
1503
  public KeyValue createKeyOnly(boolean lenAsVal) {
1344
    // KV format:  <keylen:4><valuelen:4><key:keylen><value:valuelen>
1504
    // KV format:  <keylen:4><valuelen:4><key:keylen><value:valuelen>
1345
    // Rebuild as: <keylen:4><0:4><key:keylen>
1505
    // Rebuild as: <keylen:4><0:4><key:keylen>
1346
    int dataLen = lenAsVal? Bytes.SIZEOF_INT : 0;
1506
    int dataLen = lenAsVal? Bytes.SIZEOF_INT : 0;
1347
    byte [] newBuffer = new byte[getKeyLength() + ROW_OFFSET + dataLen];
1507
    byte [] newBuffer = new byte[getKeyLength() + ROW_OFFSET + dataLen];
1348
    System.arraycopy(this.bytes, this.offset, newBuffer, 0,
1508
    System.arraycopy(this.bytes, this.offset, newBuffer, 0,
1349
        Math.min(newBuffer.length,this.length));
1509
        Math.min(newBuffer.length,this.length));
1350
    Bytes.putInt(newBuffer, Bytes.SIZEOF_INT, dataLen);
1510
    Bytes.putInt(newBuffer, Bytes.SIZEOF_INT, dataLen);
1351
    if (lenAsVal) {
1511
    if (lenAsVal) {
1352
      Bytes.putInt(newBuffer, newBuffer.length - dataLen, this.getValueLength());
1512
      Bytes.putInt(newBuffer, newBuffer.length - dataLen, this.getValueLength());
1353
    }
1513
    }
1354
    return new KeyValue(newBuffer);
1514
    return new KeyValue(newBuffer);
1355
  }
1515
  }
1356

    
   
1516

   
1357
  /**
1517
  /**
1358
   * Splits a column in family:qualifier form into separate byte arrays.
1518
   * Splits a column in family:qualifier form into separate byte arrays.
1359
   * <p>
1519
   * <p>
1360
   * Not recommend to be used as this is old-style API.
1520
   * Not recommend to be used as this is old-style API.
1361
   * @param c  The column.
1521
   * @param c  The column.
1362
   * @return The parsed column.
1522
   * @return The parsed column.
1363
   */
1523
   */
1364
  public static byte [][] parseColumn(byte [] c) {
1524
  public static byte [][] parseColumn(byte [] c) {
1365
    final int index = getDelimiter(c, 0, c.length, COLUMN_FAMILY_DELIMITER);
1525
    final int index = getDelimiter(c, 0, c.length, COLUMN_FAMILY_DELIMITER);
1366
    if (index == -1) {
1526
    if (index == -1) {
1367
      // If no delimiter, return array of size 1
1527
      // If no delimiter, return array of size 1
1368
      return new byte [][] { c };
1528
      return new byte [][] { c };
1369
    } else if(index == c.length - 1) {
1529
    } else if(index == c.length - 1) {
1370
      // Only a family, return array size 1
1530
      // Only a family, return array size 1
1371
      byte [] family = new byte[c.length-1];
1531
      byte [] family = new byte[c.length-1];
1372
      System.arraycopy(c, 0, family, 0, family.length);
1532
      System.arraycopy(c, 0, family, 0, family.length);
1373
      return new byte [][] { family };
1533
      return new byte [][] { family };
1374
    }
1534
    }
1375
    // Family and column, return array size 2
1535
    // Family and column, return array size 2
1376
    final byte [][] result = new byte [2][];
1536
    final byte [][] result = new byte [2][];
1377
    result[0] = new byte [index];
1537
    result[0] = new byte [index];
1378
    System.arraycopy(c, 0, result[0], 0, index);
1538
    System.arraycopy(c, 0, result[0], 0, index);
1379
    final int len = c.length - (index + 1);
1539
    final int len = c.length - (index + 1);
1380
    result[1] = new byte[len];
1540
    result[1] = new byte[len];
1381
    System.arraycopy(c, index + 1 /*Skip delimiter*/, result[1], 0,
1541
    System.arraycopy(c, index + 1 /*Skip delimiter*/, result[1], 0,
1382
      len);
1542
      len);
1383
    return result;
1543
    return result;
1384
  }
1544
  }
1385

    
   
1545

   
1386
  /**
1546
  /**
1387
   * Makes a column in family:qualifier form from separate byte arrays.
1547
   * Makes a column in family:qualifier form from separate byte arrays.
1388
   * <p>
1548
   * <p>
1389
   * Not recommended for usage as this is old-style API.
1549
   * Not recommended for usage as this is old-style API.
1390
   * @param family
1550
   * @param family
1391
   * @param qualifier
1551
   * @param qualifier
1392
   * @return family:qualifier
1552
   * @return family:qualifier
1393
   */
1553
   */
1394
  public static byte [] makeColumn(byte [] family, byte [] qualifier) {
1554
  public static byte [] makeColumn(byte [] family, byte [] qualifier) {
1395
    return Bytes.add(family, COLUMN_FAMILY_DELIM_ARRAY, qualifier);
1555
    return Bytes.add(family, COLUMN_FAMILY_DELIM_ARRAY, qualifier);
1396
  }
1556
  }
1397

    
   
1557

   
1398
  /**
1558
  /**
1399
   * @param b
1559
   * @param b
1400
   * @return Index of the family-qualifier colon delimiter character in passed
1560
   * @return Index of the family-qualifier colon delimiter character in passed
1401
   * buffer.
1561
   * buffer.
1402
   */
1562
   */
1403
  public static int getFamilyDelimiterIndex(final byte [] b, final int offset,
1563
  public static int getFamilyDelimiterIndex(final byte [] b, final int offset,
1404
      final int length) {
1564
      final int length) {
1405
    return getRequiredDelimiter(b, offset, length, COLUMN_FAMILY_DELIMITER);
1565
    return getRequiredDelimiter(b, offset, length, COLUMN_FAMILY_DELIMITER);
1406
  }
1566
  }
1407

    
   
1567

   
1408
  private static int getRequiredDelimiter(final byte [] b,
1568
  private static int getRequiredDelimiter(final byte [] b,
1409
      final int offset, final int length, final int delimiter) {
1569
      final int offset, final int length, final int delimiter) {
1410
    int index = getDelimiter(b, offset, length, delimiter);
1570
    int index = getDelimiter(b, offset, length, delimiter);
1411
    if (index < 0) {
1571
    if (index < 0) {
1412
      throw new IllegalArgumentException("No " + (char)delimiter + " in <" +
1572
      throw new IllegalArgumentException("No " + (char)delimiter + " in <" +
1413
        Bytes.toString(b) + ">" + ", length=" + length + ", offset=" + offset);
1573
        Bytes.toString(b) + ">" + ", length=" + length + ", offset=" + offset);
1414
    }
1574
    }
1415
    return index;
1575
    return index;
1416
  }
1576
  }
1417

    
   
1577

   
1418
  /**
1578
  /**
1419
   * This function is only used in Meta key comparisons so its error message
1579
   * This function is only used in Meta key comparisons so its error message
1420
   * is specific for meta key errors.
1580
   * is specific for meta key errors.
1421
   */
1581
   */
1422
  static int getRequiredDelimiterInReverse(final byte [] b,
1582
  static int getRequiredDelimiterInReverse(final byte [] b,
1423
      final int offset, final int length, final int delimiter) {
1583
      final int offset, final int length, final int delimiter) {
1424
    int index = getDelimiterInReverse(b, offset, length, delimiter);
1584
    int index = getDelimiterInReverse(b, offset, length, delimiter);
1425
    if (index < 0) {
1585
    if (index < 0) {
1426
      throw new IllegalArgumentException(".META. key must have two '" + (char)delimiter + "' "
1586
      throw new IllegalArgumentException(".META. key must have two '" + (char)delimiter + "' "
1427
        + "delimiters and have the following format: '<table>,<key>,<etc>'");
1587
        + "delimiters and have the following format: '<table>,<key>,<etc>'");
1428
    }
1588
    }
1429
    return index;
1589
    return index;
1430
  }
1590
  }
1431

    
   
1591

   
1432
  /**
1592
  /**
1433
   * @param b
1593
   * @param b
1434
   * @param delimiter
1594
   * @param delimiter
1435
   * @return Index of delimiter having started from start of <code>b</code>
1595
   * @return Index of delimiter having started from start of <code>b</code>
1436
   * moving rightward.
1596
   * moving rightward.
1437
   */
1597
   */
1438
  public static int getDelimiter(final byte [] b, int offset, final int length,
1598
  public static int getDelimiter(final byte [] b, int offset, final int length,
1439
      final int delimiter) {
1599
      final int delimiter) {
1440
    if (b == null) {
1600
    if (b == null) {
1441
      throw new IllegalArgumentException("Passed buffer is null");
1601
      throw new IllegalArgumentException("Passed buffer is null");
1442
    }
1602
    }
1443
    int result = -1;
1603
    int result = -1;
1444
    for (int i = offset; i < length + offset; i++) {
1604
    for (int i = offset; i < length + offset; i++) {
1445
      if (b[i] == delimiter) {
1605
      if (b[i] == delimiter) {
1446
        result = i;
1606
        result = i;
1447
        break;
1607
        break;
1448
      }
1608
      }
1449
    }
1609
    }
1450
    return result;
1610
    return result;
1451
  }
1611
  }
1452

    
   
1612

   
1453
  /**
1613
  /**
1454
   * Find index of passed delimiter walking from end of buffer backwards.
1614
   * Find index of passed delimiter walking from end of buffer backwards.
1455
   * @param b
1615
   * @param b
1456
   * @param delimiter
1616
   * @param delimiter
1457
   * @return Index of delimiter
1617
   * @return Index of delimiter
1458
   */
1618
   */
1459
  public static int getDelimiterInReverse(final byte [] b, final int offset,
1619
  public static int getDelimiterInReverse(final byte [] b, final int offset,
1460
      final int length, final int delimiter) {
1620
      final int length, final int delimiter) {
1461
    if (b == null) {
1621
    if (b == null) {
1462
      throw new IllegalArgumentException("Passed buffer is null");
1622
      throw new IllegalArgumentException("Passed buffer is null");
1463
    }
1623
    }
1464
    int result = -1;
1624
    int result = -1;
1465
    for (int i = (offset + length) - 1; i >= offset; i--) {
1625
    for (int i = (offset + length) - 1; i >= offset; i--) {
1466
      if (b[i] == delimiter) {
1626
      if (b[i] == delimiter) {
1467
        result = i;
1627
        result = i;
1468
        break;
1628
        break;
1469
      }
1629
      }
1470
    }
1630
    }
1471
    return result;
1631
    return result;
1472
  }
1632
  }
1473

    
   
1633

   
1474
  /**
1634
  /**
1475
   * A {@link KVComparator} for <code>-ROOT-</code> catalog table
1635
   * A {@link KVComparator} for <code>-ROOT-</code> catalog table
1476
   * {@link KeyValue}s.
1636
   * {@link KeyValue}s.
1477
   */
1637
   */
1478
  public static class RootComparator extends MetaComparator {
1638
  public static class RootComparator extends MetaComparator {
1479
    private final KeyComparator rawcomparator = new RootKeyComparator();
1639
    private final KeyComparator rawcomparator = new RootKeyComparator();
1480

    
   
1640

   
1481
    public KeyComparator getRawComparator() {
1641
    public KeyComparator getRawComparator() {
1482
      return this.rawcomparator;
1642
      return this.rawcomparator;
1483
    }
1643
    }
1484

    
   
1644

   
1485
    @Override
1645
    @Override
1486
    protected Object clone() throws CloneNotSupportedException {
1646
    protected Object clone() throws CloneNotSupportedException {
1487
      return new RootComparator();
1647
      return new RootComparator();
1488
    }
1648
    }
1489
  }
1649
  }
1490

    
   
1650

   
1491
  /**
1651
  /**
1492
   * A {@link KVComparator} for <code>.META.</code> catalog table
1652
   * A {@link KVComparator} for <code>.META.</code> catalog table
1493
   * {@link KeyValue}s.
1653
   * {@link KeyValue}s.
1494
   */
1654
   */
1495
  public static class MetaComparator extends KVComparator {
1655
  public static class MetaComparator extends KVComparator {
1496
    private final KeyComparator rawcomparator = new MetaKeyComparator();
1656
    private final KeyComparator rawcomparator = new MetaKeyComparator();
1497

    
   
1657

   
1498
    public KeyComparator getRawComparator() {
1658
    public KeyComparator getRawComparator() {
1499
      return this.rawcomparator;
1659
      return this.rawcomparator;
1500
    }
1660
    }
1501

    
   
1661

   
1502
    @Override
1662
    @Override
1503
    protected Object clone() throws CloneNotSupportedException {
1663
    protected Object clone() throws CloneNotSupportedException {
1504
      return new MetaComparator();
1664
      return new MetaComparator();
1505
    }
1665
    }
1506
  }
1666
  }
1507

    
   
1667

   
1508
  /**
1668
  /**
1509
   * Compare KeyValues.  When we compare KeyValues, we only compare the Key
1669
   * Compare KeyValues.  When we compare KeyValues, we only compare the Key
1510
   * portion.  This means two KeyValues with same Key but different Values are
1670
   * portion.  This means two KeyValues with same Key but different Values are
1511
   * considered the same as far as this Comparator is concerned.
1671
   * considered the same as far as this Comparator is concerned.
1512
   * Hosts a {@link KeyComparator}.
1672
   * Hosts a {@link KeyComparator}.
1513
   */
1673
   */
1514
  public static class KVComparator implements java.util.Comparator<KeyValue> {
1674
  public static class KVComparator implements java.util.Comparator<KeyValue> {
1515
    private final KeyComparator rawcomparator = new KeyComparator();
1675
    private final KeyComparator rawcomparator = new KeyComparator();
1516

    
   
1676

   
1517
    /**
1677
    /**
1518
     * @return RawComparator that can compare the Key portion of a KeyValue.
1678
     * @return RawComparator that can compare the Key portion of a KeyValue.
1519
     * Used in hfile where indices are the Key portion of a KeyValue.
1679
     * Used in hfile where indices are the Key portion of a KeyValue.
1520
     */
1680
     */
1521
    public KeyComparator getRawComparator() {
1681
    public KeyComparator getRawComparator() {
1522
      return this.rawcomparator;
1682
      return this.rawcomparator;
1523
    }
1683
    }
1524

    
   
1684

   
1525
    public int compare(final KeyValue left, final KeyValue right) {
1685
    public int compare(final KeyValue left, final KeyValue right) {
1526
      int ret = getRawComparator().compare(left.getBuffer(),
1686
      int ret = getRawComparator().compare(left.getBuffer(),
1527
          left.getOffset() + ROW_OFFSET, left.getKeyLength(),
1687
          left.getOffset() + ROW_OFFSET, left.getKeyLength(),
1528
          right.getBuffer(), right.getOffset() + ROW_OFFSET,
1688
          right.getBuffer(), right.getOffset() + ROW_OFFSET,
1529
          right.getKeyLength());
1689
          right.getKeyLength());
1530
      if (ret != 0) return ret;
1690
      if (ret != 0) return ret;
1531
      // Negate this comparison so later edits show up first
1691
      // Negate this comparison so later edits show up first
1532
      return -Longs.compare(left.getMemstoreTS(), right.getMemstoreTS());
1692
      return -Longs.compare(left.getMemstoreTS(), right.getMemstoreTS());
1533
    }
1693
    }
1534

    
   
1694

   
1535
    public int compareTimestamps(final KeyValue left, final KeyValue right) {
1695
    public int compareTimestamps(final KeyValue left, final KeyValue right) {
1536
      return compareTimestamps(left, left.getKeyLength(), right,
1696
      return compareTimestamps(left, left.getKeyLength(), right,
1537
        right.getKeyLength());
1697
        right.getKeyLength());
1538
    }
1698
    }
1539

    
   
1699

   
1540
    int compareTimestamps(final KeyValue left, final int lkeylength,
1700
    int compareTimestamps(final KeyValue left, final int lkeylength,
1541
        final KeyValue right, final int rkeylength) {
1701
        final KeyValue right, final int rkeylength) {
1542
      // Compare timestamps
1702
      // Compare timestamps
1543
      long ltimestamp = left.getTimestamp(lkeylength);
1703
      long ltimestamp = left.getTimestamp(lkeylength);
1544
      long rtimestamp = right.getTimestamp(rkeylength);
1704
      long rtimestamp = right.getTimestamp(rkeylength);
1545
      return getRawComparator().compareTimestamps(ltimestamp, rtimestamp);
1705
      return getRawComparator().compareTimestamps(ltimestamp, rtimestamp);
1546
    }
1706
    }
1547

    
   
1707

   
1548
    /**
1708
    /**
1549
     * @param left
1709
     * @param left
1550
     * @param right
1710
     * @param right
1551
     * @return Result comparing rows.
1711
     * @return Result comparing rows.
1552
     */
1712
     */
1553
    public int compareRows(final KeyValue left, final KeyValue right) {
1713
    public int compareRows(final KeyValue left, final KeyValue right) {
1554
      return compareRows(left, left.getRowLength(), right,
1714
      return compareRows(left, left.getRowLength(), right,
1555
          right.getRowLength());
1715
          right.getRowLength());
1556
    }
1716
    }
1557

    
   
1717

   
1558
    /**
1718
    /**
1559
     * @param left
1719
     * @param left
1560
     * @param lrowlength Length of left row.
1720
     * @param lrowlength Length of left row.
1561
     * @param right
1721
     * @param right
1562
     * @param rrowlength Length of right row.
1722
     * @param rrowlength Length of right row.
1563
     * @return Result comparing rows.
1723
     * @return Result comparing rows.
1564
     */
1724
     */
1565
    public int compareRows(final KeyValue left, final short lrowlength,
1725
    public int compareRows(final KeyValue left, final short lrowlength,
1566
        final KeyValue right, final short rrowlength) {
1726
        final KeyValue right, final short rrowlength) {
1567
      return getRawComparator().compareRows(left.getBuffer(),
1727
      return getRawComparator().compareRows(left.getBuffer(),
1568
          left.getRowOffset(), lrowlength,
1728
          left.getRowOffset(), lrowlength,
1569
        right.getBuffer(), right.getRowOffset(), rrowlength);
1729
        right.getBuffer(), right.getRowOffset(), rrowlength);
1570
    }
1730
    }
1571

    
   
1731

   
1572
    /**
1732
    /**
1573
     * @param left
1733
     * @param left
1574
     * @param row - row key (arbitrary byte array)
1734
     * @param row - row key (arbitrary byte array)
1575
     * @return RawComparator
1735
     * @return RawComparator
1576
     */
1736
     */
1577
    public int compareRows(final KeyValue left, final byte [] row) {
1737
    public int compareRows(final KeyValue left, final byte [] row) {
1578
      return getRawComparator().compareRows(left.getBuffer(),
1738
      return getRawComparator().compareRows(left.getBuffer(),
1579
          left.getRowOffset(), left.getRowLength(), row, 0, row.length);
1739
          left.getRowOffset(), left.getRowLength(), row, 0, row.length);
1580
    }
1740
    }
1581

    
   
1741

   
1582
    public int compareRows(byte [] left, int loffset, int llength,
1742
    public int compareRows(byte [] left, int loffset, int llength,
1583
        byte [] right, int roffset, int rlength) {
1743
        byte [] right, int roffset, int rlength) {
1584
      return getRawComparator().compareRows(left, loffset, llength,
1744
      return getRawComparator().compareRows(left, loffset, llength,
1585
        right, roffset, rlength);
1745
        right, roffset, rlength);
1586
    }
1746
    }
1587

    
   
1747

   
1588
    public int compareColumns(final KeyValue left, final byte [] right,
1748
    public int compareColumns(final KeyValue left, final byte [] right,
1589
        final int roffset, final int rlength, final int rfamilyoffset) {
1749
        final int roffset, final int rlength, final int rfamilyoffset) {
1590
      int offset = left.getFamilyOffset();
1750
      int offset = left.getFamilyOffset();
1591
      int length = left.getFamilyLength() + left.getQualifierLength();
1751
      int length = left.getFamilyLength() + left.getQualifierLength();
1592
      return getRawComparator().compareColumns(left.getBuffer(), offset, length,
1752
      return getRawComparator().compareColumns(left.getBuffer(), offset, length,
1593
        left.getFamilyLength(offset),
1753
        left.getFamilyLength(offset),
1594
        right, roffset, rlength, rfamilyoffset);
1754
        right, roffset, rlength, rfamilyoffset);
1595
    }
1755
    }
1596

    
   
1756

   
1597
    int compareColumns(final KeyValue left, final short lrowlength,
1757
    int compareColumns(final KeyValue left, final short lrowlength,
1598
        final KeyValue right, final short rrowlength) {
1758
        final KeyValue right, final short rrowlength) {
1599
      int lfoffset = left.getFamilyOffset(lrowlength);
1759
      int lfoffset = left.getFamilyOffset(lrowlength);
1600
      int rfoffset = right.getFamilyOffset(rrowlength);
1760
      int rfoffset = right.getFamilyOffset(rrowlength);
1601
      int lclength = left.getTotalColumnLength(lrowlength,lfoffset);
1761
      int lclength = left.getTotalColumnLength(lrowlength,lfoffset);
1602
      int rclength = right.getTotalColumnLength(rrowlength, rfoffset);
1762
      int rclength = right.getTotalColumnLength(rrowlength, rfoffset);
1603
      int lfamilylength = left.getFamilyLength(lfoffset);
1763
      int lfamilylength = left.getFamilyLength(lfoffset);
1604
      int rfamilylength = right.getFamilyLength(rfoffset);
1764
      int rfamilylength = right.getFamilyLength(rfoffset);
1605
      return getRawComparator().compareColumns(left.getBuffer(), lfoffset,
1765
      return getRawComparator().compareColumns(left.getBuffer(), lfoffset,
1606
          lclength, lfamilylength,
1766
          lclength, lfamilylength,
1607
        right.getBuffer(), rfoffset, rclength, rfamilylength);
1767
        right.getBuffer(), rfoffset, rclength, rfamilylength);
1608
    }
1768
    }
1609

    
   
1769

   
1610
    /**
1770
    /**
1611
     * Compares the row and column of two keyvalues for equality
1771
     * Compares the row and column of two keyvalues for equality
1612
     * @param left
1772
     * @param left
1613
     * @param right
1773
     * @param right
1614
     * @return True if same row and column.
1774
     * @return True if same row and column.
1615
     */
1775
     */
1616
    public boolean matchingRowColumn(final KeyValue left,
1776
    public boolean matchingRowColumn(final KeyValue left,
1617
        final KeyValue right) {
1777
        final KeyValue right) {
1618
      short lrowlength = left.getRowLength();
1778
      short lrowlength = left.getRowLength();
1619
      short rrowlength = right.getRowLength();
1779
      short rrowlength = right.getRowLength();
1620
      // TsOffset = end of column data. just comparing Row+CF length of each
1780
      // TsOffset = end of column data. just comparing Row+CF length of each
1621
      return ((left.getTimestampOffset() - left.getOffset()) ==
1781
      return ((left.getTimestampOffset() - left.getOffset()) ==
1622
              (right.getTimestampOffset() - right.getOffset())) &&
1782
              (right.getTimestampOffset() - right.getOffset())) &&
1623
        matchingRows(left, lrowlength, right, rrowlength) &&
1783
        matchingRows(left, lrowlength, right, rrowlength) &&
1624
        compareColumns(left, lrowlength, right, rrowlength) == 0;
1784
        compareColumns(left, lrowlength, right, rrowlength) == 0;
1625
    }
1785
    }
1626

    
   
1786

   
1627
    /**
1787
    /**
1628
     * @param left
1788
     * @param left
1629
     * @param right
1789
     * @param right
1630
     * @return True if rows match.
1790
     * @return True if rows match.
1631
     */
1791
     */
1632
    public boolean matchingRows(final KeyValue left, final byte [] right) {
1792
    public boolean matchingRows(final KeyValue left, final byte [] right) {
1633
      return Bytes.equals(left.getBuffer(), left.getRowOffset(), left.getRowLength(),
1793
      return Bytes.equals(left.getBuffer(), left.getRowOffset(), left.getRowLength(),
1634
          right, 0, right.length);
1794
          right, 0, right.length);
1635
    }
1795
    }
1636

    
   
1796

   
1637
    /**
1797
    /**
1638
     * Compares the row of two keyvalues for equality
1798
     * Compares the row of two keyvalues for equality
1639
     * @param left
1799
     * @param left
1640
     * @param right
1800
     * @param right
1641
     * @return True if rows match.
1801
     * @return True if rows match.
1642
     */
1802
     */
1643
    public boolean matchingRows(final KeyValue left, final KeyValue right) {
1803
    public boolean matchingRows(final KeyValue left, final KeyValue right) {
1644
      short lrowlength = left.getRowLength();
1804
      short lrowlength = left.getRowLength();
1645
      short rrowlength = right.getRowLength();
1805
      short rrowlength = right.getRowLength();
1646
      return matchingRows(left, lrowlength, right, rrowlength);
1806
      return matchingRows(left, lrowlength, right, rrowlength);
1647
    }
1807
    }
1648

    
   
1808

   
1649
    /**
1809
    /**
1650
     * @param left
1810
     * @param left
1651
     * @param lrowlength
1811
     * @param lrowlength
1652
     * @param right
1812
     * @param right
1653
     * @param rrowlength
1813
     * @param rrowlength
1654
     * @return True if rows match.
1814
     * @return True if rows match.
1655
     */
1815
     */
1656
    public boolean matchingRows(final KeyValue left, final short lrowlength,
1816
    public boolean matchingRows(final KeyValue left, final short lrowlength,
1657
        final KeyValue right, final short rrowlength) {
1817
        final KeyValue right, final short rrowlength) {
1658
      return lrowlength == rrowlength &&
1818
      return lrowlength == rrowlength &&
1659
          Bytes.equals(left.getBuffer(), left.getRowOffset(), lrowlength,
1819
          Bytes.equals(left.getBuffer(), left.getRowOffset(), lrowlength,
1660
              right.getBuffer(), right.getRowOffset(), rrowlength);
1820
              right.getBuffer(), right.getRowOffset(), rrowlength);
1661
    }
1821
    }
1662

    
   
1822

   
1663
    public boolean matchingRows(final byte [] left, final int loffset,
1823
    public boolean matchingRows(final byte [] left, final int loffset,
1664
        final int llength,
1824
        final int llength,
1665
        final byte [] right, final int roffset, final int rlength) {
1825
        final byte [] right, final int roffset, final int rlength) {
1666
      return Bytes.equals(left, loffset, llength,
1826
      return Bytes.equals(left, loffset, llength,
1667
          right, roffset, rlength);
1827
          right, roffset, rlength);
1668
    }
1828
    }
1669

    
   
1829

   
1670
    /**
1830
    /**
1671
     * Compares the row and timestamp of two keys
1831
     * Compares the row and timestamp of two keys
1672
     * Was called matchesWithoutColumn in HStoreKey.
1832
     * Was called matchesWithoutColumn in HStoreKey.
1673
     * @param right Key to compare against.
1833
     * @param right Key to compare against.
1674
     * @return True if same row and timestamp is greater than the timestamp in
1834
     * @return True if same row and timestamp is greater than the timestamp in
1675
     * <code>right</code>
1835
     * <code>right</code>
1676
     */
1836
     */
1677
    public boolean matchingRowsGreaterTimestamp(final KeyValue left,
1837
    public boolean matchingRowsGreaterTimestamp(final KeyValue left,
1678
        final KeyValue right) {
1838
        final KeyValue right) {
1679
      short lrowlength = left.getRowLength();
1839
      short lrowlength = left.getRowLength();
1680
      short rrowlength = right.getRowLength();
1840
      short rrowlength = right.getRowLength();
1681
      if (!matchingRows(left, lrowlength, right, rrowlength)) {
1841
      if (!matchingRows(left, lrowlength, right, rrowlength)) {
1682
        return false;
1842
        return false;
1683
      }
1843
      }
1684
      return left.getTimestamp() >= right.getTimestamp();
1844
      return left.getTimestamp() >= right.getTimestamp();
1685
    }
1845
    }
1686

    
   
1846

   
1687
    @Override
1847
    @Override
1688
    protected Object clone() throws CloneNotSupportedException {
1848
    protected Object clone() throws CloneNotSupportedException {
1689
      return new KVComparator();
1849
      return new KVComparator();
1690
    }
1850
    }
1691

    
   
1851

   
1692
    /**
1852
    /**
1693
     * @return Comparator that ignores timestamps; useful counting versions.
1853
     * @return Comparator that ignores timestamps; useful counting versions.
1694
     */
1854
     */
1695
    public KVComparator getComparatorIgnoringTimestamps() {
1855
    public KVComparator getComparatorIgnoringTimestamps() {
1696
      KVComparator c = null;
1856
      KVComparator c = null;
1697
      try {
1857
      try {
1698
        c = (KVComparator)this.clone();
1858
        c = (KVComparator)this.clone();
1699
        c.getRawComparator().ignoreTimestamp = true;
1859
        c.getRawComparator().ignoreTimestamp = true;
1700
      } catch (CloneNotSupportedException e) {
1860
      } catch (CloneNotSupportedException e) {
1701
        LOG.error("Not supported", e);
1861
        LOG.error("Not supported", e);
1702
      }
1862
      }
1703
      return c;
1863
      return c;
1704
    }
1864
    }
1705

    
   
1865

   
1706
    /**
1866
    /**
1707
     * @return Comparator that ignores key type; useful checking deletes
1867
     * @return Comparator that ignores key type; useful checking deletes
1708
     */
1868
     */
1709
    public KVComparator getComparatorIgnoringType() {
1869
    public KVComparator getComparatorIgnoringType() {
1710
      KVComparator c = null;
1870
      KVComparator c = null;
1711
      try {
1871
      try {
1712
        c = (KVComparator)this.clone();
1872
        c = (KVComparator)this.clone();
1713
        c.getRawComparator().ignoreType = true;
1873
        c.getRawComparator().ignoreType = true;
1714
      } catch (CloneNotSupportedException e) {
1874
      } catch (CloneNotSupportedException e) {
1715
        LOG.error("Not supported", e);
1875
        LOG.error("Not supported", e);
1716
      }
1876
      }
1717
      return c;
1877
      return c;
1718
    }
1878
    }
1719
  }
1879
  }
1720

    
   
1880

   
1721
  /**
1881
  /**
1722
   * Creates a KeyValue that is last on the specified row id. That is,
1882
   * Creates a KeyValue that is last on the specified row id. That is,
1723
   * every other possible KeyValue for the given row would compareTo()
1883
   * every other possible KeyValue for the given row would compareTo()
1724
   * less than the result of this call.
1884
   * less than the result of this call.
1725
   * @param row row key
1885
   * @param row row key
1726
   * @return Last possible KeyValue on passed <code>row</code>
1886
   * @return Last possible KeyValue on passed <code>row</code>
1727
   */
1887
   */
1728
  public static KeyValue createLastOnRow(final byte[] row) {
1888
  public static KeyValue createLastOnRow(final byte[] row) {
1729
    return new KeyValue(row, null, null, HConstants.LATEST_TIMESTAMP, Type.Minimum);
1889
    return new KeyValue(row, null, null, HConstants.LATEST_TIMESTAMP, Type.Minimum);
1730
  }
1890
  }
1731

    
   
1891

   
1732
  /**
1892
  /**
1733
   * Create a KeyValue that is smaller than all other possible KeyValues
1893
   * Create a KeyValue that is smaller than all other possible KeyValues
1734
   * for the given row. That is any (valid) KeyValue on 'row' would sort
1894
   * for the given row. That is any (valid) KeyValue on 'row' would sort
1735
   * _after_ the result.
1895
   * _after_ the result.
1736
   *
1896
   *
1737
   * @param row - row key (arbitrary byte array)
1897
   * @param row - row key (arbitrary byte array)
1738
   * @return First possible KeyValue on passed <code>row</code>
1898
   * @return First possible KeyValue on passed <code>row</code>
1739
   */
1899
   */
1740
  public static KeyValue createFirstOnRow(final byte [] row) {
1900
  public static KeyValue createFirstOnRow(final byte [] row) {
1741
    return createFirstOnRow(row, HConstants.LATEST_TIMESTAMP);
1901
    return createFirstOnRow(row, HConstants.LATEST_TIMESTAMP);
1742
  }
1902
  }
1743

    
   
1903

   
1744
  /**
1904
  /**
1745
   * Creates a KeyValue that is smaller than all other KeyValues that
1905
   * Creates a KeyValue that is smaller than all other KeyValues that
1746
   * are older than the passed timestamp.
1906
   * are older than the passed timestamp.
1747
   * @param row - row key (arbitrary byte array)
1907
   * @param row - row key (arbitrary byte array)
1748
   * @param ts - timestamp
1908
   * @param ts - timestamp
1749
   * @return First possible key on passed <code>row</code> and timestamp.
1909
   * @return First possible key on passed <code>row</code> and timestamp.
1750
   */
1910
   */
1751
  public static KeyValue createFirstOnRow(final byte [] row,
1911
  public static KeyValue createFirstOnRow(final byte [] row,
1752
      final long ts) {
1912
      final long ts) {
1753
    return new KeyValue(row, null, null, ts, Type.Maximum);
1913
    return new KeyValue(row, null, null, ts, Type.Maximum);
1754
  }
1914
  }
1755

    
   
1915

   
1756
  /**
1916
  /**
1757
   * Create a KeyValue for the specified row, family and qualifier that would be
1917
   * Create a KeyValue for the specified row, family and qualifier that would be
1758
   * smaller than all other possible KeyValues that have the same row,family,qualifier.
1918
   * smaller than all other possible KeyValues that have the same row,family,qualifier.
1759
   * Used for seeking.
1919
   * Used for seeking.
1760
   * @param row - row key (arbitrary byte array)
1920
   * @param row - row key (arbitrary byte array)
1761
   * @param family - family name
1921
   * @param family - family name
1762
   * @param qualifier - column qualifier
1922
   * @param qualifier - column qualifier
1763
   * @return First possible key on passed <code>row</code>, and column.
1923
   * @return First possible key on passed <code>row</code>, and column.
1764
   */
1924
   */
1765
  public static KeyValue createFirstOnRow(final byte [] row, final byte [] family,
1925
  public static KeyValue createFirstOnRow(final byte [] row, final byte [] family,
1766
      final byte [] qualifier) {
1926
      final byte [] qualifier) {
1767
    return new KeyValue(row, family, qualifier, HConstants.LATEST_TIMESTAMP, Type.Maximum);
1927
    return new KeyValue(row, family, qualifier, HConstants.LATEST_TIMESTAMP, Type.Maximum);
1768
  }
1928
  }
1769

    
   
1929

   
1770
  /**
1930
  /**
1771
   * Create a Delete Family KeyValue for the specified row and family that would
1931
   * Create a Delete Family KeyValue for the specified row and family that would
1772
   * be smaller than all other possible Delete Family KeyValues that have the
1932
   * be smaller than all other possible Delete Family KeyValues that have the
1773
   * same row and family.
1933
   * same row and family.
1774
   * Used for seeking.
1934
   * Used for seeking.
1775
   * @param row - row key (arbitrary byte array)
1935
   * @param row - row key (arbitrary byte array)
1776
   * @param family - family name
1936
   * @param family - family name
1777
   * @return First Delete Family possible key on passed <code>row</code>.
1937
   * @return First Delete Family possible key on passed <code>row</code>.
1778
   */
1938
   */
1779
  public static KeyValue createFirstDeleteFamilyOnRow(final byte [] row,
1939
  public static KeyValue createFirstDeleteFamilyOnRow(final byte [] row,
1780
      final byte [] family) {
1940
      final byte [] family) {
1781
    return new KeyValue(row, family, null, HConstants.LATEST_TIMESTAMP,
1941
    return new KeyValue(row, family, null, HConstants.LATEST_TIMESTAMP,
1782
        Type.DeleteFamily);
1942
        Type.DeleteFamily);
1783
  }
1943
  }
1784

    
   
1944

   
1785
  /**
1945
  /**
1786
   * @param row - row key (arbitrary byte array)
1946
   * @param row - row key (arbitrary byte array)
1787
   * @param f - family name
1947
   * @param f - family name
1788
   * @param q - column qualifier
1948
   * @param q - column qualifier
1789
   * @param ts - timestamp
1949
   * @param ts - timestamp
1790
   * @return First possible key on passed <code>row</code>, column and timestamp
1950
   * @return First possible key on passed <code>row</code>, column and timestamp
1791
   */
1951
   */
1792
  public static KeyValue createFirstOnRow(final byte [] row, final byte [] f,
1952
  public static KeyValue createFirstOnRow(final byte [] row, final byte [] f,
1793
      final byte [] q, final long ts) {
1953
      final byte [] q, final long ts) {
1794
    return new KeyValue(row, f, q, ts, Type.Maximum);
1954
    return new KeyValue(row, f, q, ts, Type.Maximum);
1795
  }
1955
  }
1796

    
   
1956

   
1797
  /**
1957
  /**
1798
   * Create a KeyValue for the specified row, family and qualifier that would be
1958
   * Create a KeyValue for the specified row, family and qualifier that would be
1799
   * smaller than all other possible KeyValues that have the same row,
1959
   * smaller than all other possible KeyValues that have the same row,
1800
   * family, qualifier.
1960
   * family, qualifier.
1801
   * Used for seeking.
1961
   * Used for seeking.
1802
   * @param row row key
1962
   * @param row row key
1803
   * @param roffset row offset
1963
   * @param roffset row offset
1804
   * @param rlength row length
1964
   * @param rlength row length
1805
   * @param family family name
1965
   * @param family family name
1806
   * @param foffset family offset
1966
   * @param foffset family offset
1807
   * @param flength family length
1967
   * @param flength family length
1808
   * @param qualifier column qualifier
1968
   * @param qualifier column qualifier
1809
   * @param qoffset qualifier offset
1969
   * @param qoffset qualifier offset
1810
   * @param qlength qualifier length
1970
   * @param qlength qualifier length
1811
   * @return First possible key on passed Row, Family, Qualifier.
1971
   * @return First possible key on passed Row, Family, Qualifier.
1812
   */
1972
   */
1813
  public static KeyValue createFirstOnRow(final byte [] row,
1973
  public static KeyValue createFirstOnRow(final byte [] row,
1814
      final int roffset, final int rlength, final byte [] family,
1974
      final int roffset, final int rlength, final byte [] family,
1815
      final int foffset, final int flength, final byte [] qualifier,
1975
      final int foffset, final int flength, final byte [] qualifier,
1816
      final int qoffset, final int qlength) {
1976
      final int qoffset, final int qlength) {
1817
    return new KeyValue(row, roffset, rlength, family,
1977
    return new KeyValue(row, roffset, rlength, family,
1818
        foffset, flength, qualifier, qoffset, qlength,
1978
        foffset, flength, qualifier, qoffset, qlength,
1819
        HConstants.LATEST_TIMESTAMP, Type.Maximum, null, 0, 0);
1979
        HConstants.LATEST_TIMESTAMP, Type.Maximum, null, 0, 0);
1820
  }
1980
  }
1821

    
   
1981

   

    
   
1982

   

    
   
1983
  /**

    
   
1984
   * 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,

    
   
1986
   * family, qualifier.

    
   
1987
   * Used for seeking.

    
   
1988
   *

    
   
1989
   * @param buffer the buffer to use for the new <code>KeyValue</code> object

    
   
1990
   * @param row the value key

    
   
1991
   * @param family family name

    
   
1992
   * @param qualifier column qualifier

    
   
1993
   *

    
   
1994
   * @return First possible key on passed Row, Family, Qualifier.

    
   
1995
   *

    
   
1996
   * @throws IllegalArgumentException The resulting <code>KeyValue</code> object would be larger

    
   
1997
   * than the provided buffer or than <code>Integer.MAX_VALUE</code>

    
   
1998
   */

    
   
1999
  public static KeyValue createFirstOnRow(byte [] buffer, final byte [] row,

    
   
2000
                                          final byte [] family, final byte [] qualifier)

    
   
2001
          throws IllegalArgumentException {

    
   
2002

   

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

    
   
2004
  }

    
   
2005

   

    
   
2006
  /**

    
   
2007
   * 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,

    
   
2009
   * family, qualifier.

    
   
2010
   * Used for seeking.

    
   
2011
   *

    
   
2012
   * @param buffer the buffer to use for the new <code>KeyValue</code> object

    
   
2013
   * @param row the value key

    
   
2014
   * @param family family name

    
   
2015
   * @param foffset family offset

    
   
2016
   * @param flength family length

    
   
2017
   * @param qualifier column qualifier

    
   
2018
   * @param qoffset qualifier offset

    
   
2019
   * @param qlength qualifier length

    
   
2020
   *

    
   
2021
   * @return First possible key on passed Row, Family, Qualifier.

    
   
2022
   *

    
   
2023
   * @throws IllegalArgumentException The resulting <code>KeyValue</code> object would be larger

    
   
2024
   * than the provided buffer or than <code>Integer.MAX_VALUE</code>

    
   
2025
   */

    
   
2026
  public static KeyValue createFirstOnRow(byte [] buffer, final byte [] row,

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

    
   
2028
      final byte [] qualifier, final int qoffset, final int qlength)

    
   
2029
          throws IllegalArgumentException {

    
   
2030

   

    
   
2031
    long lLength = KeyValue.KEY_INFRASTRUCTURE_SIZE +

    
   
2032
                   row.length + flength + qlength +

    
   
2033
                   KeyValue.KEYVALUE_INFRASTRUCTURE_SIZE;

    
   
2034

   

    
   
2035
    if (lLength > Integer.MAX_VALUE) {

    
   
2036
      throw new IllegalArgumentException("KeyValue length " + lLength + " > " + Integer.MAX_VALUE);

    
   
2037
    }

    
   
2038
    int iLength = (int) lLength;

    
   
2039
    if (buffer.length < iLength) {

    
   
2040
      throw new IllegalArgumentException("Buffer size " + buffer.length + " < " + iLength);

    
   
2041
    }

    
   
2042
    return new KeyValue(buffer,

    
   
2043
                        row, 0, row.length,

    
   
2044
                        family, foffset, flength,

    
   
2045
                        qualifier, qoffset, qlength,

    
   
2046
                        HConstants.LATEST_TIMESTAMP, KeyValue.Type.Maximum,

    
   
2047
                        null, 0, 0);

    
   
2048
  }

    
   
2049

   
1822
  /**
2050
  /**
1823
   * Create a KeyValue for the specified row, family and qualifier that would be
2051
   * Create a KeyValue for the specified row, family and qualifier that would be
1824
   * larger than or equal to all other possible KeyValues that have the same
2052
   * larger than or equal to all other possible KeyValues that have the same
1825
   * row, family, qualifier.
2053
   * row, family, qualifier.
1826
   * Used for reseeking.
2054
   * Used for reseeking.
1827
   * @param row row key
2055
   * @param row row key
1828
   * @param roffset row offset
2056
   * @param roffset row offset
1829
   * @param rlength row length
2057
   * @param rlength row length
1830
   * @param family family name
2058
   * @param family family name
1831
   * @param foffset family offset
2059
   * @param foffset family offset
1832
   * @param flength family length
2060
   * @param flength family length
1833
   * @param qualifier column qualifier
2061
   * @param qualifier column qualifier
1834
   * @param qoffset qualifier offset
2062
   * @param qoffset qualifier offset
1835
   * @param qlength qualifier length
2063
   * @param qlength qualifier length
1836
   * @return Last possible key on passed row, family, qualifier.
2064
   * @return Last possible key on passed row, family, qualifier.
1837
   */
2065
   */
1838
  public static KeyValue createLastOnRow(final byte [] row,
2066
  public static KeyValue createLastOnRow(final byte [] row,
1839
      final int roffset, final int rlength, final byte [] family,
2067
      final int roffset, final int rlength, final byte [] family,
1840
      final int foffset, final int flength, final byte [] qualifier,
2068
      final int foffset, final int flength, final byte [] qualifier,
1841
      final int qoffset, final int qlength) {
2069
      final int qoffset, final int qlength) {
1842
    return new KeyValue(row, roffset, rlength, family,
2070
    return new KeyValue(row, roffset, rlength, family,
1843
        foffset, flength, qualifier, qoffset, qlength,
2071
        foffset, flength, qualifier, qoffset, qlength,
1844
        HConstants.OLDEST_TIMESTAMP, Type.Minimum, null, 0, 0);
2072
        HConstants.OLDEST_TIMESTAMP, Type.Minimum, null, 0, 0);
1845
  }
2073
  }
1846

    
   
2074

   
1847
  /**
2075
  /**
1848
   * Similar to {@link #createLastOnRow(byte[], int, int, byte[], int, int,
2076
   * Similar to {@link #createLastOnRow(byte[], int, int, byte[], int, int,
1849
   * byte[], int, int)} but creates the last key on the row/column of this KV
2077
   * byte[], int, int)} but creates the last key on the row/column of this KV
1850
   * (the value part of the returned KV is always empty). Used in creating
2078
   * (the value part of the returned KV is always empty). Used in creating
1851
   * "fake keys" for the multi-column Bloom filter optimization to skip the
2079
   * "fake keys" for the multi-column Bloom filter optimization to skip the
1852
   * row/column we already know is not in the file.
2080
   * row/column we already know is not in the file.
1853
   * @return the last key on the row/column of the given key-value pair
2081
   * @return the last key on the row/column of the given key-value pair
1854
   */
2082
   */
1855
  public KeyValue createLastOnRowCol() {
2083
  public KeyValue createLastOnRowCol() {
1856
    return new KeyValue(
2084
    return new KeyValue(
1857
        bytes, getRowOffset(), getRowLength(),
2085
        bytes, getRowOffset(), getRowLength(),
1858
        bytes, getFamilyOffset(), getFamilyLength(),
2086
        bytes, getFamilyOffset(), getFamilyLength(),
1859
        bytes, getQualifierOffset(), getQualifierLength(),
2087
        bytes, getQualifierOffset(), getQualifierLength(),
1860
        HConstants.OLDEST_TIMESTAMP, Type.Minimum, null, 0, 0);
2088
        HConstants.OLDEST_TIMESTAMP, Type.Minimum, null, 0, 0);
1861
  }
2089
  }
1862

    
   
2090

   
1863
  /**
2091
  /**
1864
   * Creates the first KV with the row/family/qualifier of this KV and the
2092
   * Creates the first KV with the row/family/qualifier of this KV and the
1865
   * given timestamp. Uses the "maximum" KV type that guarantees that the new
2093
   * given timestamp. Uses the "maximum" KV type that guarantees that the new
1866
   * KV is the lowest possible for this combination of row, family, qualifier,
2094
   * KV is the lowest possible for this combination of row, family, qualifier,
1867
   * and timestamp. This KV's own timestamp is ignored. While this function
2095
   * and timestamp. This KV's own timestamp is ignored. While this function
1868
   * copies the value from this KV, it is normally used on key-only KVs.
2096
   * copies the value from this KV, it is normally used on key-only KVs.
1869
   */
2097
   */
1870
  public KeyValue createFirstOnRowColTS(long ts) {
2098
  public KeyValue createFirstOnRowColTS(long ts) {
1871
    return new KeyValue(
2099
    return new KeyValue(
1872
        bytes, getRowOffset(), getRowLength(),
2100
        bytes, getRowOffset(), getRowLength(),
1873
        bytes, getFamilyOffset(), getFamilyLength(),
2101
        bytes, getFamilyOffset(), getFamilyLength(),
1874
        bytes, getQualifierOffset(), getQualifierLength(),
2102
        bytes, getQualifierOffset(), getQualifierLength(),
1875
        ts, Type.Maximum, bytes, getValueOffset(), getValueLength());
2103
        ts, Type.Maximum, bytes, getValueOffset(), getValueLength());
1876
  }
2104
  }
1877

    
   
2105

   
1878
  /**
2106
  /**
1879
   * @param b
2107
   * @param b
1880
   * @return A KeyValue made of a byte array that holds the key-only part.
2108
   * @return A KeyValue made of a byte array that holds the key-only part.
1881
   * Needed to convert hfile index members to KeyValues.
2109
   * Needed to convert hfile index members to KeyValues.
1882
   */
2110
   */
1883
  public static KeyValue createKeyValueFromKey(final byte [] b) {
2111
  public static KeyValue createKeyValueFromKey(final byte [] b) {
1884
    return createKeyValueFromKey(b, 0, b.length);
2112
    return createKeyValueFromKey(b, 0, b.length);
1885
  }
2113
  }
1886

    
   
2114

   
1887
  /**
2115
  /**
1888
   * @param bb
2116
   * @param bb
1889
   * @return A KeyValue made of a byte buffer that holds the key-only part.
2117
   * @return A KeyValue made of a byte buffer that holds the key-only part.
1890
   * Needed to convert hfile index members to KeyValues.
2118
   * Needed to convert hfile index members to KeyValues.
1891
   */
2119
   */
1892
  public static KeyValue createKeyValueFromKey(final ByteBuffer bb) {
2120
  public static KeyValue createKeyValueFromKey(final ByteBuffer bb) {
1893
    return createKeyValueFromKey(bb.array(), bb.arrayOffset(), bb.limit());
2121
    return createKeyValueFromKey(bb.array(), bb.arrayOffset(), bb.limit());
1894
  }
2122
  }
1895

    
   
2123

   
1896
  /**
2124
  /**
1897
   * @param b
2125
   * @param b
1898
   * @param o
2126
   * @param o
1899
   * @param l
2127
   * @param l
1900
   * @return A KeyValue made of a byte array that holds the key-only part.
2128
   * @return A KeyValue made of a byte array that holds the key-only part.
1901
   * Needed to convert hfile index members to KeyValues.
2129
   * Needed to convert hfile index members to KeyValues.
1902
   */
2130
   */
1903
  public static KeyValue createKeyValueFromKey(final byte [] b, final int o,
2131
  public static KeyValue createKeyValueFromKey(final byte [] b, final int o,
1904
      final int l) {
2132
      final int l) {
1905
    byte [] newb = new byte[l + ROW_OFFSET];
2133
    byte [] newb = new byte[l + ROW_OFFSET];
1906
    System.arraycopy(b, o, newb, ROW_OFFSET, l);
2134
    System.arraycopy(b, o, newb, ROW_OFFSET, l);
1907
    Bytes.putInt(newb, 0, l);
2135
    Bytes.putInt(newb, 0, l);
1908
    Bytes.putInt(newb, Bytes.SIZEOF_INT, 0);
2136
    Bytes.putInt(newb, Bytes.SIZEOF_INT, 0);
1909
    return new KeyValue(newb);
2137
    return new KeyValue(newb);
1910
  }
2138
  }
1911

    
   
2139

   
1912
  /**
2140
  /**
1913
   * Compare key portion of a {@link KeyValue} for keys in <code>-ROOT-<code>
2141
   * Compare key portion of a {@link KeyValue} for keys in <code>-ROOT-<code>
1914
   * table.
2142
   * table.
1915
   */
2143
   */
1916
  public static class RootKeyComparator extends MetaKeyComparator {
2144
  public static class RootKeyComparator extends MetaKeyComparator {
1917
    public int compareRows(byte [] left, int loffset, int llength,
2145
    public int compareRows(byte [] left, int loffset, int llength,
1918
        byte [] right, int roffset, int rlength) {
2146
        byte [] right, int roffset, int rlength) {
1919
      // Rows look like this: .META.,ROW_FROM_META,RID
2147
      // Rows look like this: .META.,ROW_FROM_META,RID
1920
      //        LOG.info("ROOT " + Bytes.toString(left, loffset, llength) +
2148
      //        LOG.info("ROOT " + Bytes.toString(left, loffset, llength) +
1921
      //          "---" + Bytes.toString(right, roffset, rlength));
2149
      //          "---" + Bytes.toString(right, roffset, rlength));
1922
      final int metalength = 7; // '.META.' length
2150
      final int metalength = 7; // '.META.' length
1923
      int lmetaOffsetPlusDelimiter = loffset + metalength;
2151
      int lmetaOffsetPlusDelimiter = loffset + metalength;
1924
      int leftFarDelimiter = getDelimiterInReverse(left,
2152
      int leftFarDelimiter = getDelimiterInReverse(left,
1925
          lmetaOffsetPlusDelimiter,
2153
          lmetaOffsetPlusDelimiter,
1926
          llength - metalength, HRegionInfo.DELIMITER);
2154
          llength - metalength, HRegionInfo.DELIMITER);
1927
      int rmetaOffsetPlusDelimiter = roffset + metalength;
2155
      int rmetaOffsetPlusDelimiter = roffset + metalength;
1928
      int rightFarDelimiter = getDelimiterInReverse(right,
2156
      int rightFarDelimiter = getDelimiterInReverse(right,
1929
          rmetaOffsetPlusDelimiter, rlength - metalength,
2157
          rmetaOffsetPlusDelimiter, rlength - metalength,
1930
          HRegionInfo.DELIMITER);
2158
          HRegionInfo.DELIMITER);
1931
      if (leftFarDelimiter < 0 && rightFarDelimiter >= 0) {
2159
      if (leftFarDelimiter < 0 && rightFarDelimiter >= 0) {
1932
        // Nothing between .META. and regionid.  Its first key.
2160
        // Nothing between .META. and regionid.  Its first key.
1933
        return -1;
2161
        return -1;
1934
      } else if (rightFarDelimiter < 0 && leftFarDelimiter >= 0) {
2162
      } else if (rightFarDelimiter < 0 && leftFarDelimiter >= 0) {
1935
        return 1;
2163
        return 1;
1936
      } else if (leftFarDelimiter < 0 && rightFarDelimiter < 0) {
2164
      } else if (leftFarDelimiter < 0 && rightFarDelimiter < 0) {
1937
        return 0;
2165
        return 0;
1938
      }
2166
      }
1939
      int result = super.compareRows(left, lmetaOffsetPlusDelimiter,
2167
      int result = super.compareRows(left, lmetaOffsetPlusDelimiter,
1940
          leftFarDelimiter - lmetaOffsetPlusDelimiter,
2168
          leftFarDelimiter - lmetaOffsetPlusDelimiter,
1941
          right, rmetaOffsetPlusDelimiter,
2169
          right, rmetaOffsetPlusDelimiter,
1942
          rightFarDelimiter - rmetaOffsetPlusDelimiter);
2170
          rightFarDelimiter - rmetaOffsetPlusDelimiter);
1943
      if (result != 0) {
2171
      if (result != 0) {
1944
        return result;
2172
        return result;
1945
      }
2173
      }
1946
      // Compare last part of row, the rowid.
2174
      // Compare last part of row, the rowid.
1947
      leftFarDelimiter++;
2175
      leftFarDelimiter++;
1948
      rightFarDelimiter++;
2176
      rightFarDelimiter++;
1949
      result = compareRowid(left, leftFarDelimiter,
2177
      result = compareRowid(left, leftFarDelimiter,
1950
          llength - (leftFarDelimiter - loffset),
2178
          llength - (leftFarDelimiter - loffset),
1951
          right, rightFarDelimiter, rlength - (rightFarDelimiter - roffset));
2179
          right, rightFarDelimiter, rlength - (rightFarDelimiter - roffset));
1952
      return result;
2180
      return result;
1953
    }
2181
    }
1954
  }
2182
  }
1955

    
   
2183

   
1956
  /**
2184
  /**
1957
   * Comparator that compares row component only of a KeyValue.
2185
   * Comparator that compares row component only of a KeyValue.
1958
   */
2186
   */
1959
  public static class RowComparator implements Comparator<KeyValue> {
2187
  public static class RowComparator implements Comparator<KeyValue> {
1960
    final KVComparator comparator;
2188
    final KVComparator comparator;
1961

    
   
2189

   
1962
    public RowComparator(final KVComparator c) {
2190
    public RowComparator(final KVComparator c) {
1963
      this.comparator = c;
2191
      this.comparator = c;
1964
    }
2192
    }
1965

    
   
2193

   
1966
    public int compare(KeyValue left, KeyValue right) {
2194
    public int compare(KeyValue left, KeyValue right) {
1967
      return comparator.compareRows(left, right);
2195
      return comparator.compareRows(left, right);
1968
    }
2196
    }
1969
  }
2197
  }
1970

    
   
2198

   
1971
  /**
2199
  /**
1972
   * Compare key portion of a {@link KeyValue} for keys in <code>.META.</code>
2200
   * Compare key portion of a {@link KeyValue} for keys in <code>.META.</code>
1973
   * table.
2201
   * table.
1974
   */
2202
   */
1975
  public static class MetaKeyComparator extends KeyComparator {
2203
  public static class MetaKeyComparator extends KeyComparator {
1976
    public int compareRows(byte [] left, int loffset, int llength,
2204
    public int compareRows(byte [] left, int loffset, int llength,
1977
        byte [] right, int roffset, int rlength) {
2205
        byte [] right, int roffset, int rlength) {
1978
      //        LOG.info("META " + Bytes.toString(left, loffset, llength) +
2206
      //        LOG.info("META " + Bytes.toString(left, loffset, llength) +
1979
      //          "---" + Bytes.toString(right, roffset, rlength));
2207
      //          "---" + Bytes.toString(right, roffset, rlength));
1980
      int leftDelimiter = getDelimiter(left, loffset, llength,
2208
      int leftDelimiter = getDelimiter(left, loffset, llength,
1981
          HRegionInfo.DELIMITER);
2209
          HRegionInfo.DELIMITER);
1982
      int rightDelimiter = getDelimiter(right, roffset, rlength,
2210
      int rightDelimiter = getDelimiter(right, roffset, rlength,
1983
          HRegionInfo.DELIMITER);
2211
          HRegionInfo.DELIMITER);
1984
      if (leftDelimiter < 0 && rightDelimiter >= 0) {
2212
      if (leftDelimiter < 0 && rightDelimiter >= 0) {
1985
        // Nothing between .META. and regionid.  Its first key.
2213
        // Nothing between .META. and regionid.  Its first key.
1986
        return -1;
2214
        return -1;
1987
      } else if (rightDelimiter < 0 && leftDelimiter >= 0) {
2215
      } else if (rightDelimiter < 0 && leftDelimiter >= 0) {
1988
        return 1;
2216
        return 1;
1989
      } else if (leftDelimiter < 0 && rightDelimiter < 0) {
2217
      } else if (leftDelimiter < 0 && rightDelimiter < 0) {
1990
        return 0;
2218
        return 0;
1991
      }
2219
      }
1992
      // Compare up to the delimiter
2220
      // Compare up to the delimiter
1993
      int result = Bytes.compareTo(left, loffset, leftDelimiter - loffset,
2221
      int result = Bytes.compareTo(left, loffset, leftDelimiter - loffset,
1994
          right, roffset, rightDelimiter - roffset);
2222
          right, roffset, rightDelimiter - roffset);
1995
      if (result != 0) {
2223
      if (result != 0) {
1996
        return result;
2224
        return result;
1997
      }
2225
      }
1998
      // Compare middle bit of the row.
2226
      // Compare middle bit of the row.
1999
      // Move past delimiter
2227
      // Move past delimiter
2000
      leftDelimiter++;
2228
      leftDelimiter++;
2001
      rightDelimiter++;
2229
      rightDelimiter++;
2002
      int leftFarDelimiter = getRequiredDelimiterInReverse(left, leftDelimiter,
2230
      int leftFarDelimiter = getRequiredDelimiterInReverse(left, leftDelimiter,
2003
          llength - (leftDelimiter - loffset), HRegionInfo.DELIMITER);
2231
          llength - (leftDelimiter - loffset), HRegionInfo.DELIMITER);
2004
      int rightFarDelimiter = getRequiredDelimiterInReverse(right,
2232
      int rightFarDelimiter = getRequiredDelimiterInReverse(right,
2005
          rightDelimiter, rlength - (rightDelimiter - roffset),
2233
          rightDelimiter, rlength - (rightDelimiter - roffset),
2006
          HRegionInfo.DELIMITER);
2234
          HRegionInfo.DELIMITER);
2007
      // Now compare middlesection of row.
2235
      // Now compare middlesection of row.
2008
      result = super.compareRows(left, leftDelimiter,
2236
      result = super.compareRows(left, leftDelimiter,
2009
          leftFarDelimiter - leftDelimiter, right, rightDelimiter,
2237
          leftFarDelimiter - leftDelimiter, right, rightDelimiter,
2010
          rightFarDelimiter - rightDelimiter);
2238
          rightFarDelimiter - rightDelimiter);
2011
      if (result != 0) {
2239
      if (result != 0) {
2012
        return result;
2240
        return result;
2013
      }
2241
      }
2014
      // Compare last part of row, the rowid.
2242
      // Compare last part of row, the rowid.
2015
      leftFarDelimiter++;
2243
      leftFarDelimiter++;
2016
      rightFarDelimiter++;
2244
      rightFarDelimiter++;
2017
      result = compareRowid(left, leftFarDelimiter,
2245
      result = compareRowid(left, leftFarDelimiter,
2018
          llength - (leftFarDelimiter - loffset),
2246
          llength - (leftFarDelimiter - loffset),
2019
          right, rightFarDelimiter, rlength - (rightFarDelimiter - roffset));
2247
          right, rightFarDelimiter, rlength - (rightFarDelimiter - roffset));
2020
      return result;
2248
      return result;
2021
    }
2249
    }
2022

    
   
2250

   
2023
    protected int compareRowid(byte[] left, int loffset, int llength,
2251
    protected int compareRowid(byte[] left, int loffset, int llength,
2024
        byte[] right, int roffset, int rlength) {
2252
        byte[] right, int roffset, int rlength) {
2025
      return Bytes.compareTo(left, loffset, llength, right, roffset, rlength);
2253
      return Bytes.compareTo(left, loffset, llength, right, roffset, rlength);
2026
    }
2254
    }
2027
  }
2255
  }
2028

    
   
2256

   
2029
  /**
2257
  /**
2030
   * Avoids redundant comparisons for better performance.
2258
   * Avoids redundant comparisons for better performance.
2031
   */
2259
   */
2032
  public static interface SamePrefixComparator<T> {
2260
  public static interface SamePrefixComparator<T> {
2033
    /**
2261
    /**
2034
     * Compare two keys assuming that the first n bytes are the same.
2262
     * Compare two keys assuming that the first n bytes are the same.
2035
     * @param commonPrefix How many bytes are the same.
2263
     * @param commonPrefix How many bytes are the same.
2036
     */
2264
     */
2037
    public int compareIgnoringPrefix(int commonPrefix,
2265
    public int compareIgnoringPrefix(int commonPrefix,
2038
        T left, int loffset, int llength,
2266
        T left, int loffset, int llength,
2039
        T right, int roffset, int rlength);
2267
        T right, int roffset, int rlength);
2040
  }
2268
  }
2041

    
   
2269

   
2042
  /**
2270
  /**
2043
   * Compare key portion of a {@link KeyValue}.
2271
   * Compare key portion of a {@link KeyValue}.
2044
   */
2272
   */
2045
  public static class KeyComparator
2273
  public static class KeyComparator
2046
      implements RawComparator<byte []>, SamePrefixComparator<byte[]> {
2274
      implements RawComparator<byte []>, SamePrefixComparator<byte[]> {
2047
    volatile boolean ignoreTimestamp = false;
2275
    volatile boolean ignoreTimestamp = false;
2048
    volatile boolean ignoreType = false;
2276
    volatile boolean ignoreType = false;
2049

    
   
2277

   
2050
    public int compare(byte[] left, int loffset, int llength, byte[] right,
2278
    public int compare(byte[] left, int loffset, int llength, byte[] right,
2051
        int roffset, int rlength) {
2279
        int roffset, int rlength) {
2052
      // Compare row
2280
      // Compare row
2053
      short lrowlength = Bytes.toShort(left, loffset);
2281
      short lrowlength = Bytes.toShort(left, loffset);
2054
      short rrowlength = Bytes.toShort(right, roffset);
2282
      short rrowlength = Bytes.toShort(right, roffset);
2055
      int compare = compareRows(left, loffset + Bytes.SIZEOF_SHORT,
2283
      int compare = compareRows(left, loffset + Bytes.SIZEOF_SHORT,
2056
          lrowlength, right, roffset + Bytes.SIZEOF_SHORT, rrowlength);
2284
          lrowlength, right, roffset + Bytes.SIZEOF_SHORT, rrowlength);
2057
      if (compare != 0) {
2285
      if (compare != 0) {
2058
        return compare;
2286
        return compare;
2059
      }
2287
      }
2060

    
   
2288

   
2061
      // Compare the rest of the two KVs without making any assumptions about
2289
      // Compare the rest of the two KVs without making any assumptions about
2062
      // the common prefix. This function will not compare rows anyway, so we
2290
      // the common prefix. This function will not compare rows anyway, so we
2063
      // don't need to tell it that the common prefix includes the row.
2291
      // don't need to tell it that the common prefix includes the row.
2064
      return compareWithoutRow(0, left, loffset, llength, right, roffset,
2292
      return compareWithoutRow(0, left, loffset, llength, right, roffset,
2065
          rlength, rrowlength);
2293
          rlength, rrowlength);
2066
    }
2294
    }
2067

    
   
2295

   
2068
    /**
2296
    /**
2069
     * Compare the two key-values, ignoring the prefix of the given length
2297
     * Compare the two key-values, ignoring the prefix of the given length
2070
     * that is known to be the same between the two.
2298
     * that is known to be the same between the two.
2071
     * @param commonPrefix the prefix length to ignore
2299
     * @param commonPrefix the prefix length to ignore
2072
     */
2300
     */
2073
    @Override
2301
    @Override
2074
    public int compareIgnoringPrefix(int commonPrefix, byte[] left,
2302
    public int compareIgnoringPrefix(int commonPrefix, byte[] left,
2075
        int loffset, int llength, byte[] right, int roffset, int rlength) {
2303
        int loffset, int llength, byte[] right, int roffset, int rlength) {
2076
      // Compare row
2304
      // Compare row
2077
      short lrowlength = Bytes.toShort(left, loffset);
2305
      short lrowlength = Bytes.toShort(left, loffset);
2078
      short rrowlength;
2306
      short rrowlength;
2079

    
   
2307

   
2080
      int comparisonResult = 0;
2308
      int comparisonResult = 0;
2081
      if (commonPrefix < ROW_LENGTH_SIZE) {
2309
      if (commonPrefix < ROW_LENGTH_SIZE) {
2082
        // almost nothing in common
2310
        // almost nothing in common
2083
        rrowlength = Bytes.toShort(right, roffset);
2311
        rrowlength = Bytes.toShort(right, roffset);
2084
        comparisonResult = compareRows(left, loffset + ROW_LENGTH_SIZE,
2312
        comparisonResult = compareRows(left, loffset + ROW_LENGTH_SIZE,
2085
            lrowlength, right, roffset + ROW_LENGTH_SIZE, rrowlength);
2313
            lrowlength, right, roffset + ROW_LENGTH_SIZE, rrowlength);
2086
      } else { // the row length is the same
2314
      } else { // the row length is the same
2087
        rrowlength = lrowlength;
2315
        rrowlength = lrowlength;
2088
        if (commonPrefix < ROW_LENGTH_SIZE + rrowlength) {
2316
        if (commonPrefix < ROW_LENGTH_SIZE + rrowlength) {
2089
          // The rows are not the same. Exclude the common prefix and compare
2317
          // The rows are not the same. Exclude the common prefix and compare
2090
          // the rest of the two rows.
2318
          // the rest of the two rows.
2091
          int common = commonPrefix - ROW_LENGTH_SIZE;
2319
          int common = commonPrefix - ROW_LENGTH_SIZE;
2092
          comparisonResult = compareRows(
2320
          comparisonResult = compareRows(
2093
              left, loffset + common + ROW_LENGTH_SIZE, lrowlength - common,
2321
              left, loffset + common + ROW_LENGTH_SIZE, lrowlength - common,
2094
              right, roffset + common + ROW_LENGTH_SIZE, rrowlength - common);
2322
              right, roffset + common + ROW_LENGTH_SIZE, rrowlength - common);
2095
        }
2323
        }
2096
      }
2324
      }
2097
      if (comparisonResult != 0) {
2325
      if (comparisonResult != 0) {
2098
        return comparisonResult;
2326
        return comparisonResult;
2099
      }
2327
      }
2100

    
   
2328

   
2101
      assert lrowlength == rrowlength;
2329
      assert lrowlength == rrowlength;
2102

    
   
2330

   
2103
      return compareWithoutRow(commonPrefix, left, loffset, llength, right,
2331
      return compareWithoutRow(commonPrefix, left, loffset, llength, right,
2104
          roffset, rlength, lrowlength);
2332
          roffset, rlength, lrowlength);
2105
    }
2333
    }
2106

    
   
2334

   
2107
    /**
2335
    /**
2108
     * Compare column, timestamp, and key type (everything except the row).
2336
     * Compare column, timestamp, and key type (everything except the row).
2109
     * This method is used both in the normal comparator and the "same-prefix"
2337
     * This method is used both in the normal comparator and the "same-prefix"
2110
     * comparator. Note that we are assuming that row portions of both KVs have
2338
     * comparator. Note that we are assuming that row portions of both KVs have
2111
     * already been parsed and found identical, and we don't validate that
2339
     * already been parsed and found identical, and we don't validate that
2112
     * assumption here.
2340
     * assumption here.
2113
     * @param commonPrefix the length of the common prefix of the two
2341
     * @param commonPrefix the length of the common prefix of the two
2114
     *          key-values being compared, including row length and row
2342
     *          key-values being compared, including row length and row
2115
     */
2343
     */
2116
    private int compareWithoutRow(int commonPrefix, byte[] left, int loffset,
2344
    private int compareWithoutRow(int commonPrefix, byte[] left, int loffset,
2117
        int llength, byte[] right, int roffset, int rlength, short rowlength) {
2345
        int llength, byte[] right, int roffset, int rlength, short rowlength) {
2118
      // Compare column family. Start comparing past row and family length.
2346
      // Compare column family. Start comparing past row and family length.
2119
      int lcolumnoffset = ROW_LENGTH_SIZE + FAMILY_LENGTH_SIZE +
2347
      int lcolumnoffset = ROW_LENGTH_SIZE + FAMILY_LENGTH_SIZE +
2120
          rowlength + loffset;
2348
          rowlength + loffset;
2121
      int rcolumnoffset = ROW_LENGTH_SIZE + FAMILY_LENGTH_SIZE +
2349
      int rcolumnoffset = ROW_LENGTH_SIZE + FAMILY_LENGTH_SIZE +
2122
          rowlength + roffset;
2350
          rowlength + roffset;
2123
      int lcolumnlength = llength - TIMESTAMP_TYPE_SIZE -
2351
      int lcolumnlength = llength - TIMESTAMP_TYPE_SIZE -
2124
          (lcolumnoffset - loffset);
2352
          (lcolumnoffset - loffset);
2125
      int rcolumnlength = rlength - TIMESTAMP_TYPE_SIZE -
2353
      int rcolumnlength = rlength - TIMESTAMP_TYPE_SIZE -
2126
          (rcolumnoffset - roffset);
2354
          (rcolumnoffset - roffset);
2127

    
   
2355

   
2128
      // If row matches, and no column in the 'left' AND put type is 'minimum',
2356
      // If row matches, and no column in the 'left' AND put type is 'minimum',
2129
      // then return that left is larger than right.
2357
      // then return that left is larger than right.
2130

    
   
2358

   
2131
      // This supports 'last key on a row' - the magic is if there is no column
2359
      // This supports 'last key on a row' - the magic is if there is no column
2132
      // in the left operand, and the left operand has a type of '0' - magical
2360
      // in the left operand, and the left operand has a type of '0' - magical
2133
      // value, then we say the left is bigger.  This will let us seek to the
2361
      // value, then we say the left is bigger.  This will let us seek to the
2134
      // last key in a row.
2362
      // last key in a row.
2135

    
   
2363

   
2136
      byte ltype = left[loffset + (llength - 1)];
2364
      byte ltype = left[loffset + (llength - 1)];
2137
      byte rtype = right[roffset + (rlength - 1)];
2365
      byte rtype = right[roffset + (rlength - 1)];
2138

    
   
2366

   
2139
      // If the column is not specified, the "minimum" key type appears the
2367
      // If the column is not specified, the "minimum" key type appears the
2140
      // latest in the sorted order, regardless of the timestamp. This is used
2368
      // latest in the sorted order, regardless of the timestamp. This is used
2141
      // for specifying the last key/value in a given row, because there is no
2369
      // for specifying the last key/value in a given row, because there is no
2142
      // "lexicographically last column" (it would be infinitely long).  The
2370
      // "lexicographically last column" (it would be infinitely long).  The
2143
      // "maximum" key type does not need this behavior.
2371
      // "maximum" key type does not need this behavior.
2144
      if (lcolumnlength == 0 && ltype == Type.Minimum.getCode()) {
2372
      if (lcolumnlength == 0 && ltype == Type.Minimum.getCode()) {
2145
        // left is "bigger", i.e. it appears later in the sorted order
2373
        // left is "bigger", i.e. it appears later in the sorted order
2146
        return 1;
2374
        return 1;
2147
      }
2375
      }
2148
      if (rcolumnlength == 0 && rtype == Type.Minimum.getCode()) {
2376
      if (rcolumnlength == 0 && rtype == Type.Minimum.getCode()) {
2149
        return -1;
2377
        return -1;
2150
      }
2378
      }
2151

    
   
2379

   
2152
      int common = 0;
2380
      int common = 0;
2153
      if (commonPrefix > 0) {
2381
      if (commonPrefix > 0) {
2154
        common = Math.max(0, commonPrefix -
2382
        common = Math.max(0, commonPrefix -
2155
            rowlength - ROW_LENGTH_SIZE - FAMILY_LENGTH_SIZE);
2383
            rowlength - ROW_LENGTH_SIZE - FAMILY_LENGTH_SIZE);
2156
        common = Math.min(common, Math.min(lcolumnlength, rcolumnlength));
2384
        common = Math.min(common, Math.min(lcolumnlength, rcolumnlength));
2157
      }
2385
      }
2158

    
   
2386

   
2159
      final int comparisonResult = Bytes.compareTo(
2387
      final int comparisonResult = Bytes.compareTo(
2160
          left, lcolumnoffset + common, lcolumnlength - common,
2388
          left, lcolumnoffset + common, lcolumnlength - common,
2161
          right, rcolumnoffset + common, rcolumnlength - common);
2389
          right, rcolumnoffset + common, rcolumnlength - common);
2162
      if (comparisonResult != 0) {
2390
      if (comparisonResult != 0) {
2163
        return comparisonResult;
2391
        return comparisonResult;
2164
      }
2392
      }
2165

    
   
2393

   
2166
      return compareTimestampAndType(left, loffset, llength, right, roffset,
2394
      return compareTimestampAndType(left, loffset, llength, right, roffset,
2167
          rlength, ltype, rtype);
2395
          rlength, ltype, rtype);
2168
    }
2396
    }
2169

    
   
2397

   
2170
    private int compareTimestampAndType(byte[] left, int loffset, int llength,
2398
    private int compareTimestampAndType(byte[] left, int loffset, int llength,
2171
        byte[] right, int roffset, int rlength, byte ltype, byte rtype) {
2399
        byte[] right, int roffset, int rlength, byte ltype, byte rtype) {
2172
      int compare;
2400
      int compare;
2173
      if (!this.ignoreTimestamp) {
2401
      if (!this.ignoreTimestamp) {
2174
        // Get timestamps.
2402
        // Get timestamps.
2175
        long ltimestamp = Bytes.toLong(left,
2403
        long ltimestamp = Bytes.toLong(left,
2176
            loffset + (llength - TIMESTAMP_TYPE_SIZE));
2404
            loffset + (llength - TIMESTAMP_TYPE_SIZE));
2177
        long rtimestamp = Bytes.toLong(right,
2405
        long rtimestamp = Bytes.toLong(right,
2178
            roffset + (rlength - TIMESTAMP_TYPE_SIZE));
2406
            roffset + (rlength - TIMESTAMP_TYPE_SIZE));
2179
        compare = compareTimestamps(ltimestamp, rtimestamp);
2407
        compare = compareTimestamps(ltimestamp, rtimestamp);
2180
        if (compare != 0) {
2408
        if (compare != 0) {
2181
          return compare;
2409
          return compare;
2182
        }
2410
        }
2183
      }
2411
      }
2184

    
   
2412

   
2185
      if (!this.ignoreType) {
2413
      if (!this.ignoreType) {
2186
        // Compare types. Let the delete types sort ahead of puts; i.e. types
2414
        // Compare types. Let the delete types sort ahead of puts; i.e. types
2187
        // of higher numbers sort before those of lesser numbers. Maximum (255)
2415
        // of higher numbers sort before those of lesser numbers. Maximum (255)
2188
        // appears ahead of everything, and minimum (0) appears after
2416
        // appears ahead of everything, and minimum (0) appears after
2189
        // everything.
2417
        // everything.
2190
        return (0xff & rtype) - (0xff & ltype);
2418
        return (0xff & rtype) - (0xff & ltype);
2191
      }
2419
      }
2192
      return 0;
2420
      return 0;
2193
    }
2421
    }
2194

    
   
2422

   
2195
    public int compare(byte[] left, byte[] right) {
2423
    public int compare(byte[] left, byte[] right) {
2196
      return compare(left, 0, left.length, right, 0, right.length);
2424
      return compare(left, 0, left.length, right, 0, right.length);
2197
    }
2425
    }
2198

    
   
2426

   
2199
    public int compareRows(byte [] left, int loffset, int llength,
2427
    public int compareRows(byte [] left, int loffset, int llength,
2200
        byte [] right, int roffset, int rlength) {
2428
        byte [] right, int roffset, int rlength) {
2201
      return Bytes.compareTo(left, loffset, llength, right, roffset, rlength);
2429
      return Bytes.compareTo(left, loffset, llength, right, roffset, rlength);
2202
    }
2430
    }
2203

    
   
2431

   
2204
    protected int compareColumns(
2432
    protected int compareColumns(
2205
        byte [] left, int loffset, int llength, final int lfamilylength,
2433
        byte [] left, int loffset, int llength, final int lfamilylength,
2206
        byte [] right, int roffset, int rlength, final int rfamilylength) {
2434
        byte [] right, int roffset, int rlength, final int rfamilylength) {
2207
      return KeyValue.compareColumns(left, loffset, llength, lfamilylength,
2435
      return KeyValue.compareColumns(left, loffset, llength, lfamilylength,
2208
        right, roffset, rlength, rfamilylength);
2436
        right, roffset, rlength, rfamilylength);
2209
    }
2437
    }
2210

    
   
2438

   
2211
    int compareTimestamps(final long ltimestamp, final long rtimestamp) {
2439
    int compareTimestamps(final long ltimestamp, final long rtimestamp) {
2212
      // The below older timestamps sorting ahead of newer timestamps looks
2440
      // The below older timestamps sorting ahead of newer timestamps looks
2213
      // wrong but it is intentional. This way, newer timestamps are first
2441
      // wrong but it is intentional. This way, newer timestamps are first
2214
      // found when we iterate over a memstore and newer versions are the
2442
      // found when we iterate over a memstore and newer versions are the
2215
      // first we trip over when reading from a store file.
2443
      // first we trip over when reading from a store file.
2216
      if (ltimestamp < rtimestamp) {
2444
      if (ltimestamp < rtimestamp) {
2217
        return 1;
2445
        return 1;
2218
      } else if (ltimestamp > rtimestamp) {
2446
      } else if (ltimestamp > rtimestamp) {
2219
        return -1;
2447
        return -1;
2220
      }
2448
      }
2221
      return 0;
2449
      return 0;
2222
    }
2450
    }
2223
  }
2451
  }
2224

    
   
2452

   
2225
  // HeapSize
2453
  // HeapSize
2226
  public long heapSize() {
2454
  public long heapSize() {
2227
    return ClassSize.align(ClassSize.OBJECT + (2 * ClassSize.REFERENCE) +
2455
    return ClassSize.align(ClassSize.OBJECT + (2 * ClassSize.REFERENCE) +
2228
        ClassSize.align(ClassSize.ARRAY) + ClassSize.align(length) +
2456
        ClassSize.align(ClassSize.ARRAY) + ClassSize.align(length) +
2229
        (3 * Bytes.SIZEOF_INT) +
2457
        (3 * Bytes.SIZEOF_INT) +
2230
        ClassSize.align(ClassSize.ARRAY) +
2458
        ClassSize.align(ClassSize.ARRAY) +
2231
        (2 * Bytes.SIZEOF_LONG));
2459
        (2 * Bytes.SIZEOF_LONG));
2232
  }
2460
  }
2233

    
   
2461

   
2234
  // this overload assumes that the length bytes have already been read,
2462
  // this overload assumes that the length bytes have already been read,
2235
  // and it expects the length of the KeyValue to be explicitly passed
2463
  // and it expects the length of the KeyValue to be explicitly passed
2236
  // to it.
2464
  // to it.
2237
  public void readFields(int length, final DataInput in) throws IOException {
2465
  public void readFields(int length, final DataInput in) throws IOException {
2238
    this.length = length;
2466
    this.length = length;
2239
    this.offset = 0;
2467
    this.offset = 0;
2240
    this.bytes = new byte[this.length];
2468
    this.bytes = new byte[this.length];
2241
    in.readFully(this.bytes, 0, this.length);
2469
    in.readFully(this.bytes, 0, this.length);
2242
  }
2470
  }
2243

    
   
2471

   
2244
  // Writable
2472
  // Writable
2245
  public void readFields(final DataInput in) throws IOException {
2473
  public void readFields(final DataInput in) throws IOException {
2246
    int length = in.readInt();
2474
    int length = in.readInt();
2247
    readFields(length, in);
2475
    readFields(length, in);
2248
  }
2476
  }
2249

    
   
2477

   
2250
  public void write(final DataOutput out) throws IOException {
2478
  public void write(final DataOutput out) throws IOException {
2251
    out.writeInt(this.length);
2479
    out.writeInt(this.length);
2252
    out.write(this.bytes, this.offset, this.length);
2480
    out.write(this.bytes, this.offset, this.length);
2253
  }
2481
  }
2254
}
2482
}
src/main/java/org/apache/hadoop/hbase/client/Result.java
Revision df0b3ef New Change
 
src/test/java/org/apache/hadoop/hbase/client/TestResult.java
Revision f9e29c2 New Change
 
  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/client/TestResult.java: Loading...