View Javadoc

1   /**
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  package org.apache.hadoop.hbase;
20  
21  import java.io.IOException;
22  import java.util.Arrays;
23  import java.util.Iterator;
24  import java.util.List;
25  import java.util.Set;
26  import java.util.TreeSet;
27  
28  import junit.framework.TestCase;
29  
30  import org.apache.commons.logging.Log;
31  import org.apache.commons.logging.LogFactory;
32  import org.apache.hadoop.hbase.KeyValue.KVComparator;
33  import org.apache.hadoop.hbase.KeyValue.MetaComparator;
34  import org.apache.hadoop.hbase.KeyValue.Type;
35  import org.apache.hadoop.hbase.util.Bytes;
36  
37  public class TestKeyValue extends TestCase {
38    private final Log LOG = LogFactory.getLog(this.getClass().getName());
39  
40    public void testColumnCompare() throws Exception {
41      final byte [] a = Bytes.toBytes("aaa");
42      byte [] family1 = Bytes.toBytes("abc");
43      byte [] qualifier1 = Bytes.toBytes("def");
44      byte [] family2 = Bytes.toBytes("abcd");
45      byte [] qualifier2 = Bytes.toBytes("ef");
46  
47      KeyValue aaa = new KeyValue(a, family1, qualifier1, 0L, Type.Put, a);
48      assertFalse(aaa.matchingColumn(family2, qualifier2));
49      assertTrue(aaa.matchingColumn(family1, qualifier1));
50      aaa = new KeyValue(a, family2, qualifier2, 0L, Type.Put, a);
51      assertFalse(aaa.matchingColumn(family1, qualifier1));
52      assertTrue(aaa.matchingColumn(family2,qualifier2));
53      byte [] nullQualifier = new byte[0];
54      aaa = new KeyValue(a, family1, nullQualifier, 0L, Type.Put, a);
55      assertTrue(aaa.matchingColumn(family1,null));
56      assertFalse(aaa.matchingColumn(family2,qualifier2));
57    }
58  
59    /**
60     * Test a corner case when the family qualifier is a prefix of the
61     *  column qualifier.
62     */
63    public void testColumnCompare_prefix() throws Exception {
64      final byte [] a = Bytes.toBytes("aaa");
65      byte [] family1 = Bytes.toBytes("abc");
66      byte [] qualifier1 = Bytes.toBytes("def");
67      byte [] family2 = Bytes.toBytes("ab");
68      byte [] qualifier2 = Bytes.toBytes("def");
69  
70      KeyValue aaa = new KeyValue(a, family1, qualifier1, 0L, Type.Put, a);
71      assertFalse(aaa.matchingColumn(family2, qualifier2));
72    }
73  
74    public void testBasics() throws Exception {
75      LOG.info("LOWKEY: " + KeyValue.LOWESTKEY.toString());
76      check(Bytes.toBytes(getName()),
77        Bytes.toBytes(getName()), Bytes.toBytes(getName()), 1,
78        Bytes.toBytes(getName()));
79      // Test empty value and empty column -- both should work. (not empty fam)
80      check(Bytes.toBytes(getName()), Bytes.toBytes(getName()), null, 1, null);
81      check(HConstants.EMPTY_BYTE_ARRAY, Bytes.toBytes(getName()), null, 1, null);
82      // empty qual is equivalent to null qual
83      assertEquals(
84        new KeyValue(Bytes.toBytes("rk"), Bytes.toBytes("fam"), null, 1, (byte[]) null),
85        new KeyValue(Bytes.toBytes("rk"), Bytes.toBytes("fam"),
86          HConstants.EMPTY_BYTE_ARRAY, 1, (byte[]) null));
87    }
88  
89    private void check(final byte [] row, final byte [] family, byte [] qualifier,
90      final long timestamp, final byte [] value) {
91      KeyValue kv = new KeyValue(row, family, qualifier, timestamp, value);
92      assertTrue(Bytes.compareTo(kv.getRow(), row) == 0);
93      assertTrue(kv.matchingColumn(family, qualifier));
94      // Call toString to make sure it works.
95      LOG.info(kv.toString());
96    }
97  
98    public void testPlainCompare() throws Exception {
99      final byte [] a = Bytes.toBytes("aaa");
100     final byte [] b = Bytes.toBytes("bbb");
101     final byte [] fam = Bytes.toBytes("col");
102     final byte [] qf = Bytes.toBytes("umn");
103     KeyValue aaa = new KeyValue(a, fam, qf, a);
104     KeyValue bbb = new KeyValue(b, fam, qf, b);
105     assertTrue(KeyValue.COMPARATOR.compare(aaa, bbb) < 0);
106     assertTrue(KeyValue.COMPARATOR.compare(bbb, aaa) > 0);
107     // Compare breaks if passed same ByteBuffer as both left and right arguments.
108     assertTrue(KeyValue.COMPARATOR.compare(bbb, bbb) == 0);
109     assertTrue(KeyValue.COMPARATOR.compare(aaa, aaa) == 0);
110     // Do compare with different timestamps.
111     aaa = new KeyValue(a, fam, qf, 1, a);
112     bbb = new KeyValue(a, fam, qf, 2, a);
113     assertTrue(KeyValue.COMPARATOR.compare(aaa, bbb) > 0);
114     assertTrue(KeyValue.COMPARATOR.compare(bbb, aaa) < 0);
115     assertTrue(KeyValue.COMPARATOR.compare(aaa, aaa) == 0);
116     // Do compare with different types.  Higher numbered types -- Delete
117     // should sort ahead of lower numbers; i.e. Put
118     aaa = new KeyValue(a, fam, qf, 1, KeyValue.Type.Delete, a);
119     bbb = new KeyValue(a, fam, qf, 1, a);
120     assertTrue(KeyValue.COMPARATOR.compare(aaa, bbb) < 0);
121     assertTrue(KeyValue.COMPARATOR.compare(bbb, aaa) > 0);
122     assertTrue(KeyValue.COMPARATOR.compare(aaa, aaa) == 0);
123   }
124 
125   public void testMoreComparisons() throws Exception {
126     long now = System.currentTimeMillis();
127 
128     // Meta compares
129     KeyValue aaa = new KeyValue(
130         Bytes.toBytes("TestScanMultipleVersions,row_0500,1236020145502"), now);
131     KeyValue bbb = new KeyValue(
132         Bytes.toBytes("TestScanMultipleVersions,,99999999999999"), now);
133     KVComparator c = new KeyValue.MetaComparator();
134     assertTrue(c.compare(bbb, aaa) < 0);
135 
136     KeyValue aaaa = new KeyValue(Bytes.toBytes("TestScanMultipleVersions,,1236023996656"),
137         Bytes.toBytes("info"), Bytes.toBytes("regioninfo"), 1236024396271L,
138         (byte[])null);
139     assertTrue(c.compare(aaaa, bbb) < 0);
140 
141     KeyValue x = new KeyValue(Bytes.toBytes("TestScanMultipleVersions,row_0500,1236034574162"),
142         Bytes.toBytes("info"), Bytes.toBytes(""), 9223372036854775807L,
143         (byte[])null);
144     KeyValue y = new KeyValue(Bytes.toBytes("TestScanMultipleVersions,row_0500,1236034574162"),
145         Bytes.toBytes("info"), Bytes.toBytes("regioninfo"), 1236034574912L,
146         (byte[])null);
147     assertTrue(c.compare(x, y) < 0);
148     comparisons(new KeyValue.MetaComparator());
149     comparisons(new KeyValue.KVComparator());
150     metacomparisons(new KeyValue.MetaComparator());
151   }
152 
153   public void testMetaComparatorTableKeysWithCommaOk() {
154     MetaComparator c = new KeyValue.MetaComparator();
155     long now = System.currentTimeMillis();
156     // meta keys values are not quite right.  A users can enter illegal values
157     // from shell when scanning meta.
158     KeyValue a = new KeyValue(Bytes.toBytes("table,key,with,commas1,1234"), now);
159     KeyValue b = new KeyValue(Bytes.toBytes("table,key,with,commas2,0123"), now);
160     assertTrue(c.compare(a, b) < 0);
161   }
162 
163   /**
164    * Tests cases where rows keys have characters below the ','.
165    * See HBASE-832
166    * @throws IOException
167    */
168   public void testKeyValueBorderCases() throws IOException {
169     // % sorts before , so if we don't do special comparator, rowB would
170     // come before rowA.
171     KeyValue rowA = new KeyValue(Bytes.toBytes("testtable,www.hbase.org/,1234"),
172       Bytes.toBytes("fam"), Bytes.toBytes(""), Long.MAX_VALUE, (byte[])null);
173     KeyValue rowB = new KeyValue(Bytes.toBytes("testtable,www.hbase.org/%20,99999"),
174         Bytes.toBytes("fam"), Bytes.toBytes(""), Long.MAX_VALUE, (byte[])null);
175     assertTrue(KeyValue.META_COMPARATOR.compare(rowA, rowB) < 0);
176 
177     rowA = new KeyValue(Bytes.toBytes("testtable,,1234"), Bytes.toBytes("fam"),
178         Bytes.toBytes(""), Long.MAX_VALUE, (byte[])null);
179     rowB = new KeyValue(Bytes.toBytes("testtable,$www.hbase.org/,99999"),
180         Bytes.toBytes("fam"), Bytes.toBytes(""), Long.MAX_VALUE, (byte[])null);
181     assertTrue(KeyValue.META_COMPARATOR.compare(rowA, rowB) < 0);
182 
183   }
184 
185   private void metacomparisons(final KeyValue.MetaComparator c) {
186     long now = System.currentTimeMillis();
187     assertTrue(c.compare(new KeyValue(
188         Bytes.toBytes(TableName.META_TABLE_NAME.getNameAsString()+",a,,0,1"), now),
189       new KeyValue(
190           Bytes.toBytes(TableName.META_TABLE_NAME.getNameAsString()+",a,,0,1"), now)) == 0);
191     KeyValue a = new KeyValue(
192         Bytes.toBytes(TableName.META_TABLE_NAME.getNameAsString()+",a,,0,1"), now);
193     KeyValue b = new KeyValue(
194         Bytes.toBytes(TableName.META_TABLE_NAME.getNameAsString()+",a,,0,2"), now);
195     assertTrue(c.compare(a, b) < 0);
196     assertTrue(c.compare(new KeyValue(
197         Bytes.toBytes(TableName.META_TABLE_NAME.getNameAsString()+",a,,0,2"), now),
198       new KeyValue(
199           Bytes.toBytes(TableName.META_TABLE_NAME.getNameAsString()+",a,,0,1"), now)) > 0);
200   }
201 
202   private void comparisons(final KeyValue.KVComparator c) {
203     long now = System.currentTimeMillis();
204     assertTrue(c.compare(new KeyValue(
205         Bytes.toBytes(TableName.META_TABLE_NAME.getNameAsString()+",,1"), now),
206       new KeyValue(
207           Bytes.toBytes(TableName.META_TABLE_NAME.getNameAsString()+",,1"), now)) == 0);
208     assertTrue(c.compare(new KeyValue(
209         Bytes.toBytes(TableName.META_TABLE_NAME.getNameAsString()+",,1"), now),
210       new KeyValue(
211           Bytes.toBytes(TableName.META_TABLE_NAME.getNameAsString()+",,2"), now)) < 0);
212     assertTrue(c.compare(new KeyValue(
213         Bytes.toBytes(TableName.META_TABLE_NAME.getNameAsString()+",,2"), now),
214       new KeyValue(
215           Bytes.toBytes(TableName.META_TABLE_NAME.getNameAsString()+",,1"), now)) > 0);
216   }
217 
218   public void testBinaryKeys() throws Exception {
219     Set<KeyValue> set = new TreeSet<KeyValue>(KeyValue.COMPARATOR);
220     final byte [] fam = Bytes.toBytes("col");
221     final byte [] qf = Bytes.toBytes("umn");
222     final byte [] nb = new byte[0];
223     KeyValue [] keys = {new KeyValue(Bytes.toBytes("aaaaa,\u0000\u0000,2"), fam, qf, 2, nb),
224       new KeyValue(Bytes.toBytes("aaaaa,\u0001,3"), fam, qf, 3, nb),
225       new KeyValue(Bytes.toBytes("aaaaa,,1"), fam, qf, 1, nb),
226       new KeyValue(Bytes.toBytes("aaaaa,\u1000,5"), fam, qf, 5, nb),
227       new KeyValue(Bytes.toBytes("aaaaa,a,4"), fam, qf, 4, nb),
228       new KeyValue(Bytes.toBytes("a,a,0"), fam, qf, 0, nb),
229     };
230     // Add to set with bad comparator
231     for (int i = 0; i < keys.length; i++) {
232       set.add(keys[i]);
233     }
234     // This will output the keys incorrectly.
235     boolean assertion = false;
236     int count = 0;
237     try {
238       for (KeyValue k: set) {
239         assertTrue(count++ == k.getTimestamp());
240       }
241     } catch (junit.framework.AssertionFailedError e) {
242       // Expected
243       assertion = true;
244     }
245     assertTrue(assertion);
246     // Make set with good comparator
247     set = new TreeSet<KeyValue>(new KeyValue.MetaComparator());
248     for (int i = 0; i < keys.length; i++) {
249       set.add(keys[i]);
250     }
251     count = 0;
252     for (KeyValue k: set) {
253       assertTrue(count++ == k.getTimestamp());
254     }
255   }
256 
257   public void testStackedUpKeyValue() {
258     // Test multiple KeyValues in a single blob.
259 
260     // TODO actually write this test!
261 
262   }
263 
264   private final byte[] rowA = Bytes.toBytes("rowA");
265   private final byte[] rowB = Bytes.toBytes("rowB");
266 
267   private final byte[] family = Bytes.toBytes("family");
268   private final byte[] qualA = Bytes.toBytes("qfA");
269   private final byte[] qualB = Bytes.toBytes("qfB");
270 
271   private void assertKVLess(KeyValue.KVComparator c,
272                             KeyValue less,
273                             KeyValue greater) {
274     int cmp = c.compare(less,greater);
275     assertTrue(cmp < 0);
276     cmp = c.compare(greater,less);
277     assertTrue(cmp > 0);
278   }
279 
280   private void assertKVLessWithoutRow(KeyValue.KVComparator c, int common, KeyValue less,
281       KeyValue greater) {
282     int cmp = c.compareIgnoringPrefix(common, less.getBuffer(), less.getOffset()
283         + KeyValue.ROW_OFFSET, less.getKeyLength(), greater.getBuffer(),
284         greater.getOffset() + KeyValue.ROW_OFFSET, greater.getKeyLength());
285     assertTrue(cmp < 0);
286     cmp = c.compareIgnoringPrefix(common, greater.getBuffer(), greater.getOffset()
287         + KeyValue.ROW_OFFSET, greater.getKeyLength(), less.getBuffer(),
288         less.getOffset() + KeyValue.ROW_OFFSET, less.getKeyLength());
289     assertTrue(cmp > 0);
290   }
291 
292   public void testCompareWithoutRow() {
293     final KeyValue.KVComparator c = KeyValue.COMPARATOR;
294     byte[] row = Bytes.toBytes("row");
295 
296     byte[] fa = Bytes.toBytes("fa");
297     byte[] fami = Bytes.toBytes("fami");
298     byte[] fami1 = Bytes.toBytes("fami1");
299 
300     byte[] qual0 = Bytes.toBytes("");
301     byte[] qual1 = Bytes.toBytes("qf1");
302     byte[] qual2 = Bytes.toBytes("qf2");
303     long ts = 1;
304 
305     // 'fa:'
306     KeyValue kv_0 = new KeyValue(row, fa, qual0, ts, Type.Put);
307     // 'fami:'
308     KeyValue kv0_0 = new KeyValue(row, fami, qual0, ts, Type.Put);
309     // 'fami:qf1'
310     KeyValue kv0_1 = new KeyValue(row, fami, qual1, ts, Type.Put);
311     // 'fami:qf2'
312     KeyValue kv0_2 = new KeyValue(row, fami, qual2, ts, Type.Put);
313     // 'fami1:'
314     KeyValue kv1_0 = new KeyValue(row, fami1, qual0, ts, Type.Put);
315 
316     // 'fami:qf1' < 'fami:qf2'
317     assertKVLessWithoutRow(c, 0, kv0_1, kv0_2);
318     // 'fami:qf1' < 'fami1:'
319     assertKVLessWithoutRow(c, 0, kv0_1, kv1_0);
320 
321     // Test comparison by skipping the same prefix bytes.
322     /***
323      * KeyValue Format and commonLength:
324      * |_keyLen_|_valLen_|_rowLen_|_rowKey_|_famiLen_|_fami_|_Quali_|....
325      * ------------------|-------commonLength--------|--------------
326      */
327     int commonLength = KeyValue.ROW_LENGTH_SIZE + KeyValue.FAMILY_LENGTH_SIZE
328         + row.length;
329     // 'fa:' < 'fami:'. They have commonPrefix + 2 same prefix bytes.
330     assertKVLessWithoutRow(c, commonLength + 2, kv_0, kv0_0);
331     // 'fami:' < 'fami:qf1'. They have commonPrefix + 4 same prefix bytes.
332     assertKVLessWithoutRow(c, commonLength + 4, kv0_0, kv0_1);
333     // 'fami:qf1' < 'fami1:'. They have commonPrefix + 4 same prefix bytes.
334     assertKVLessWithoutRow(c, commonLength + 4, kv0_1, kv1_0);
335     // 'fami:qf1' < 'fami:qf2'. They have commonPrefix + 6 same prefix bytes.
336     assertKVLessWithoutRow(c, commonLength + 6, kv0_1, kv0_2);
337   }
338 
339   public void testFirstLastOnRow() {
340     final KVComparator c = KeyValue.COMPARATOR;
341     long ts = 1;
342     byte[] bufferA = new byte[128];
343     int offsetA = 0;
344     byte[] bufferB = new byte[128];
345     int offsetB = 7;
346 
347     // These are listed in sort order (ie: every one should be less
348     // than the one on the next line).
349     final KeyValue firstOnRowA = KeyValue.createFirstOnRow(rowA);
350     final KeyValue firstOnRowABufferFamQual = KeyValue.createFirstOnRow(bufferA, offsetA,
351         rowA, 0, rowA.length, family, 0, family.length, qualA, 0, qualA.length);
352     final KeyValue kvA_1 = new KeyValue(rowA, null, null, ts, Type.Put);
353     final KeyValue kvA_2 = new KeyValue(rowA, family, qualA, ts, Type.Put);
354 
355     final KeyValue lastOnRowA = KeyValue.createLastOnRow(rowA);
356     final KeyValue firstOnRowB = KeyValue.createFirstOnRow(rowB);
357     final KeyValue firstOnRowBBufferFam = KeyValue.createFirstOnRow(bufferB, offsetB,
358         rowB, 0, rowB.length, family, 0, family.length, null, 0, 0);
359     final KeyValue kvB = new KeyValue(rowB, family, qualA, ts, Type.Put);
360 
361     assertKVLess(c, firstOnRowA, firstOnRowB);
362     assertKVLess(c, firstOnRowA, firstOnRowBBufferFam);
363     assertKVLess(c, firstOnRowABufferFamQual, firstOnRowB);
364     assertKVLess(c, firstOnRowA, kvA_1);
365     assertKVLess(c, firstOnRowA, kvA_2);
366     assertKVLess(c, firstOnRowABufferFamQual, kvA_2);
367     assertKVLess(c, kvA_1, kvA_2);
368     assertKVLess(c, kvA_2, firstOnRowB);
369     assertKVLess(c, kvA_1, firstOnRowB);
370     assertKVLess(c, kvA_2, firstOnRowBBufferFam);
371     assertKVLess(c, kvA_1, firstOnRowBBufferFam);
372 
373     assertKVLess(c, lastOnRowA, firstOnRowB);
374     assertKVLess(c, lastOnRowA, firstOnRowBBufferFam);
375     assertKVLess(c, firstOnRowB, kvB);
376     assertKVLess(c, firstOnRowBBufferFam, kvB);
377     assertKVLess(c, lastOnRowA, kvB);
378 
379     assertKVLess(c, kvA_2, lastOnRowA);
380     assertKVLess(c, kvA_1, lastOnRowA);
381     assertKVLess(c, firstOnRowA, lastOnRowA);
382     assertKVLess(c, firstOnRowABufferFamQual, lastOnRowA);
383   }
384 
385   public void testCreateKeyOnly() throws Exception {
386     long ts = 1;
387     byte [] value = Bytes.toBytes("a real value");
388     byte [] evalue = new byte[0]; // empty value
389 
390     for (byte[] val : new byte[][]{value, evalue}) {
391       for (boolean useLen : new boolean[]{false,true}) {
392         KeyValue kv1 = new KeyValue(rowA, family, qualA, ts, val);
393         KeyValue kv1ko = kv1.createKeyOnly(useLen);
394         // keys are still the same
395         assertTrue(kv1.equals(kv1ko));
396         // but values are not
397         assertTrue(kv1ko.getValue().length == (useLen?Bytes.SIZEOF_INT:0));
398         if (useLen) {
399           assertEquals(kv1.getValueLength(), Bytes.toInt(kv1ko.getValue()));
400         }
401       }
402     }
403   }
404 
405   public void testCreateKeyValueFromKey() {
406     KeyValue kv = new KeyValue(Bytes.toBytes("myRow"), Bytes.toBytes("myCF"),
407         Bytes.toBytes("myQualifier"), 12345L, Bytes.toBytes("myValue"));
408     int initialPadding = 10;
409     int endingPadding = 20;
410     int keyLen = kv.getKeyLength();
411     byte[] tmpArr = new byte[initialPadding + endingPadding + keyLen];
412     System.arraycopy(kv.getBuffer(), kv.getKeyOffset(), tmpArr,
413         initialPadding, keyLen);
414     KeyValue kvFromKey = KeyValue.createKeyValueFromKey(tmpArr, initialPadding,
415         keyLen);
416     assertEquals(keyLen, kvFromKey.getKeyLength());
417     assertEquals(KeyValue.ROW_OFFSET + keyLen, kvFromKey.getBuffer().length);
418     System.err.println("kv=" + kv);
419     System.err.println("kvFromKey=" + kvFromKey);
420     assertEquals(kvFromKey.toString(),
421         kv.toString().replaceAll("=[0-9]+", "=0"));
422   }
423 
424   /**
425    * Tests that getTimestamp() does always return the proper timestamp, even after updating it.
426    * See HBASE-6265.
427    */
428   public void testGetTimestamp() {
429     KeyValue kv = new KeyValue(Bytes.toBytes("myRow"), Bytes.toBytes("myCF"),
430       Bytes.toBytes("myQualifier"), HConstants.LATEST_TIMESTAMP,
431       Bytes.toBytes("myValue"));
432     long time1 = kv.getTimestamp();
433     kv.updateLatestStamp(Bytes.toBytes(12345L));
434     long time2 = kv.getTimestamp();
435     assertEquals(HConstants.LATEST_TIMESTAMP, time1);
436     assertEquals(12345L, time2);
437   }
438 
439   /**
440    * See HBASE-7845
441    */
442   public void testGetShortMidpointKey() {
443     final KVComparator keyComparator = KeyValue.COMPARATOR;
444     //verify that faked shorter rowkey could be generated
445     long ts = 5;
446     KeyValue kv1 = new KeyValue(Bytes.toBytes("the quick brown fox"), family, qualA, ts, Type.Put);
447     KeyValue kv2 = new KeyValue(Bytes.toBytes("the who test text"), family, qualA, ts, Type.Put);
448     byte[] newKey = keyComparator.getShortMidpointKey(kv1.getKey(), kv2.getKey());
449     assertTrue(keyComparator.compareFlatKey(kv1.getKey(), newKey) < 0);
450     assertTrue(keyComparator.compareFlatKey(newKey, kv2.getKey()) < 0);
451     short newRowLength = Bytes.toShort(newKey, 0);
452     byte[] expectedArray = Bytes.toBytes("the r");
453     Bytes.equals(newKey, KeyValue.ROW_LENGTH_SIZE, newRowLength, expectedArray, 0,
454       expectedArray.length);
455 
456     //verify: same with "row + family + qualifier", return rightKey directly
457     kv1 = new KeyValue(Bytes.toBytes("ilovehbase"), family, qualA, 5, Type.Put);
458     kv2 = new KeyValue(Bytes.toBytes("ilovehbase"), family, qualA, 0, Type.Put);
459     assertTrue(keyComparator.compareFlatKey(kv1.getKey(), kv2.getKey()) < 0);
460     newKey = keyComparator.getShortMidpointKey(kv1.getKey(), kv2.getKey());
461     assertTrue(keyComparator.compareFlatKey(kv1.getKey(), newKey) < 0);
462     assertTrue(keyComparator.compareFlatKey(newKey, kv2.getKey()) == 0);
463     kv1 = new KeyValue(Bytes.toBytes("ilovehbase"), family, qualA, -5, Type.Put);
464     kv2 = new KeyValue(Bytes.toBytes("ilovehbase"), family, qualA, -10, Type.Put);
465     assertTrue(keyComparator.compareFlatKey(kv1.getKey(), kv2.getKey()) < 0);
466     newKey = keyComparator.getShortMidpointKey(kv1.getKey(), kv2.getKey());
467     assertTrue(keyComparator.compareFlatKey(kv1.getKey(), newKey) < 0);
468     assertTrue(keyComparator.compareFlatKey(newKey, kv2.getKey()) == 0);
469 
470     // verify: same with row, different with qualifier
471     kv1 = new KeyValue(Bytes.toBytes("ilovehbase"), family, qualA, 5, Type.Put);
472     kv2 = new KeyValue(Bytes.toBytes("ilovehbase"), family, qualB, 5, Type.Put);
473     assertTrue(keyComparator.compareFlatKey(kv1.getKey(), kv2.getKey()) < 0);
474     newKey = keyComparator.getShortMidpointKey(kv1.getKey(), kv2.getKey());
475     assertTrue(keyComparator.compareFlatKey(kv1.getKey(), newKey) < 0);
476     assertTrue(keyComparator.compareFlatKey(newKey, kv2.getKey()) < 0);
477     KeyValue newKeyValue = KeyValue.createKeyValueFromKey(newKey);
478     assertTrue(Arrays.equals(newKeyValue.getFamily(),family));
479     assertTrue(Arrays.equals(newKeyValue.getQualifier(),qualB));
480     assertTrue(newKeyValue.getTimestamp() == HConstants.LATEST_TIMESTAMP);
481     assertTrue(newKeyValue.getTypeByte() == Type.Maximum.getCode());
482 
483     //verify metaKeyComparator's getShortMidpointKey output
484     final KVComparator metaKeyComparator = KeyValue.META_COMPARATOR;
485     kv1 = new KeyValue(Bytes.toBytes("ilovehbase123"), family, qualA, 5, Type.Put);
486     kv2 = new KeyValue(Bytes.toBytes("ilovehbase234"), family, qualA, 0, Type.Put);
487     newKey = metaKeyComparator.getShortMidpointKey(kv1.getKey(), kv2.getKey());
488     assertTrue(metaKeyComparator.compareFlatKey(kv1.getKey(), newKey) < 0);
489     assertTrue(metaKeyComparator.compareFlatKey(newKey, kv2.getKey()) == 0);
490 
491     //verify common fix scenario
492     kv1 = new KeyValue(Bytes.toBytes("ilovehbase"), family, qualA, ts, Type.Put);
493     kv2 = new KeyValue(Bytes.toBytes("ilovehbaseandhdfs"), family, qualA, ts, Type.Put);
494     assertTrue(keyComparator.compareFlatKey(kv1.getKey(), kv2.getKey()) < 0);
495     newKey = keyComparator.getShortMidpointKey(kv1.getKey(), kv2.getKey());
496     assertTrue(keyComparator.compareFlatKey(kv1.getKey(), newKey) < 0);
497     assertTrue(keyComparator.compareFlatKey(newKey, kv2.getKey()) < 0);
498     newRowLength = Bytes.toShort(newKey, 0);
499     expectedArray = Bytes.toBytes("ilovehbasea");
500     Bytes.equals(newKey, KeyValue.ROW_LENGTH_SIZE, newRowLength, expectedArray, 0,
501       expectedArray.length);
502     //verify only 1 offset scenario
503     kv1 = new KeyValue(Bytes.toBytes("100abcdefg"), family, qualA, ts, Type.Put);
504     kv2 = new KeyValue(Bytes.toBytes("101abcdefg"), family, qualA, ts, Type.Put);
505     assertTrue(keyComparator.compareFlatKey(kv1.getKey(), kv2.getKey()) < 0);
506     newKey = keyComparator.getShortMidpointKey(kv1.getKey(), kv2.getKey());
507     assertTrue(keyComparator.compareFlatKey(kv1.getKey(), newKey) < 0);
508     assertTrue(keyComparator.compareFlatKey(newKey, kv2.getKey()) < 0);
509     newRowLength = Bytes.toShort(newKey, 0);
510     expectedArray = Bytes.toBytes("101");
511     Bytes.equals(newKey, KeyValue.ROW_LENGTH_SIZE, newRowLength, expectedArray, 0,
512       expectedArray.length);
513   }
514 
515   public void testKVsWithTags() {
516     byte[] row = Bytes.toBytes("myRow");
517     byte[] cf = Bytes.toBytes("myCF");
518     byte[] q = Bytes.toBytes("myQualifier");
519     byte[] value = Bytes.toBytes("myValue");
520     byte[] metaValue1 = Bytes.toBytes("metaValue1");
521     byte[] metaValue2 = Bytes.toBytes("metaValue2");
522     KeyValue kv = new KeyValue(row, cf, q, HConstants.LATEST_TIMESTAMP, value, new Tag[] {
523         new Tag((byte) 1, metaValue1), new Tag((byte) 2, metaValue2) });
524     assertTrue(kv.getTagsLengthUnsigned() > 0);
525     assertTrue(Bytes.equals(kv.getRow(), row));
526     assertTrue(Bytes.equals(kv.getFamily(), cf));
527     assertTrue(Bytes.equals(kv.getQualifier(), q));
528     assertTrue(Bytes.equals(kv.getValue(), value));
529     List<Tag> tags = kv.getTags();
530     assertNotNull(tags);
531     assertEquals(2, tags.size());
532     boolean meta1Ok = false, meta2Ok = false;
533     for (Tag tag : tags) {
534       if (tag.getType() == (byte) 1) {
535         if (Bytes.equals(tag.getValue(), metaValue1)) {
536           meta1Ok = true;
537         }
538       } else {
539         if (Bytes.equals(tag.getValue(), metaValue2)) {
540           meta2Ok = true;
541         }
542       }
543     }
544     assertTrue(meta1Ok);
545     assertTrue(meta2Ok);
546     Iterator<Tag> tagItr = CellUtil.tagsIterator(kv.getTagsArray(), kv.getTagsOffset(),
547         kv.getTagsLengthUnsigned());
548     //Iterator<Tag> tagItr = kv.tagsIterator();
549     assertTrue(tagItr.hasNext());
550     Tag next = tagItr.next();
551     assertEquals(10, next.getTagLength());
552     assertEquals((byte) 1, next.getType());
553     Bytes.equals(next.getValue(), metaValue1);
554     assertTrue(tagItr.hasNext());
555     next = tagItr.next();
556     assertEquals(10, next.getTagLength());
557     assertEquals((byte) 2, next.getType());
558     Bytes.equals(next.getValue(), metaValue2);
559     assertFalse(tagItr.hasNext());
560 
561     tagItr = CellUtil.tagsIterator(kv.getTagsArray(), kv.getTagsOffset(),
562         kv.getTagsLengthUnsigned());
563     assertTrue(tagItr.hasNext());
564     next = tagItr.next();
565     assertEquals(10, next.getTagLength());
566     assertEquals((byte) 1, next.getType());
567     Bytes.equals(next.getValue(), metaValue1);
568     assertTrue(tagItr.hasNext());
569     next = tagItr.next();
570     assertEquals(10, next.getTagLength());
571     assertEquals((byte) 2, next.getType());
572     Bytes.equals(next.getValue(), metaValue2);
573     assertFalse(tagItr.hasNext());
574   }
575   
576   public void testMetaKeyComparator() {
577     MetaComparator c = new KeyValue.MetaComparator();
578     long now = System.currentTimeMillis();
579 
580     KeyValue a = new KeyValue(Bytes.toBytes("table1"), now);
581     KeyValue b = new KeyValue(Bytes.toBytes("table2"), now);
582     assertTrue(c.compare(a, b) < 0);
583     
584     a = new KeyValue(Bytes.toBytes("table1,111"), now);
585     b = new KeyValue(Bytes.toBytes("table2"), now);
586     assertTrue(c.compare(a, b) < 0);
587     
588     a = new KeyValue(Bytes.toBytes("table1"), now);
589     b = new KeyValue(Bytes.toBytes("table2,111"), now);
590     assertTrue(c.compare(a, b) < 0);
591     
592     a = new KeyValue(Bytes.toBytes("table,111"), now);
593     b = new KeyValue(Bytes.toBytes("table,2222"), now);
594     assertTrue(c.compare(a, b) < 0);
595     
596     a = new KeyValue(Bytes.toBytes("table,111,aaaa"), now);
597     b = new KeyValue(Bytes.toBytes("table,2222"), now);
598     assertTrue(c.compare(a, b) < 0);
599     
600     a = new KeyValue(Bytes.toBytes("table,111"), now);
601     b = new KeyValue(Bytes.toBytes("table,2222.bbb"), now);
602     assertTrue(c.compare(a, b) < 0);
603 
604     a = new KeyValue(Bytes.toBytes("table,,aaaa"), now);
605     b = new KeyValue(Bytes.toBytes("table,111,bbb"), now);
606     assertTrue(c.compare(a, b) < 0);
607     
608     a = new KeyValue(Bytes.toBytes("table,111,aaaa"), now);
609     b = new KeyValue(Bytes.toBytes("table,111,bbb"), now);
610     assertTrue(c.compare(a, b) < 0);
611 
612     a = new KeyValue(Bytes.toBytes("table,111,xxxx"), now);
613     b = new KeyValue(Bytes.toBytes("table,111,222,bbb"), now);
614     assertTrue(c.compare(a, b) < 0);
615     
616     a = new KeyValue(Bytes.toBytes("table,111,11,xxx"), now);
617     b = new KeyValue(Bytes.toBytes("table,111,222,bbb"), now);
618     assertTrue(c.compare(a, b) < 0);
619   }
620 }