001/** 002 * 003 * Licensed to the Apache Software Foundation (ASF) under one 004 * or more contributor license agreements. See the NOTICE file 005 * distributed with this work for additional information 006 * regarding copyright ownership. The ASF licenses this file 007 * to you under the Apache License, Version 2.0 (the 008 * "License"); you may not use this file except in compliance 009 * with the License. You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, software 014 * distributed under the License is distributed on an "AS IS" BASIS, 015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 016 * See the License for the specific language governing permissions and 017 * limitations under the License. 018 */ 019package org.apache.hadoop.hbase; 020 021import static org.junit.Assert.assertNotEquals; 022 023import java.io.ByteArrayInputStream; 024import java.io.ByteArrayOutputStream; 025import java.io.DataInputStream; 026import java.io.DataOutputStream; 027import java.io.IOException; 028import java.util.Collections; 029import java.util.Iterator; 030import java.util.List; 031import java.util.Set; 032import java.util.TreeSet; 033 034import org.apache.hadoop.hbase.util.ByteBufferUtils; 035import org.apache.hadoop.hbase.util.Bytes; 036import org.slf4j.Logger; 037import org.slf4j.LoggerFactory; 038 039import junit.framework.TestCase; 040 041public class TestKeyValue extends TestCase { 042 private static final Logger LOG = LoggerFactory.getLogger(TestKeyValue.class); 043 044 public void testColumnCompare() throws Exception { 045 final byte [] a = Bytes.toBytes("aaa"); 046 byte [] family1 = Bytes.toBytes("abc"); 047 byte [] qualifier1 = Bytes.toBytes("def"); 048 byte [] family2 = Bytes.toBytes("abcd"); 049 byte [] qualifier2 = Bytes.toBytes("ef"); 050 051 KeyValue aaa = new KeyValue(a, family1, qualifier1, 0L, KeyValue.Type.Put, a); 052 assertFalse(CellUtil.matchingColumn(aaa, family2, qualifier2)); 053 assertTrue(CellUtil.matchingColumn(aaa, family1, qualifier1)); 054 aaa = new KeyValue(a, family2, qualifier2, 0L, KeyValue.Type.Put, a); 055 assertFalse(CellUtil.matchingColumn(aaa, family1, qualifier1)); 056 assertTrue(CellUtil.matchingColumn(aaa, family2,qualifier2)); 057 byte [] nullQualifier = new byte[0]; 058 aaa = new KeyValue(a, family1, nullQualifier, 0L, KeyValue.Type.Put, a); 059 assertTrue(CellUtil.matchingColumn(aaa, family1,null)); 060 assertFalse(CellUtil.matchingColumn(aaa, family2,qualifier2)); 061 } 062 063 /** 064 * Test a corner case when the family qualifier is a prefix of the 065 * column qualifier. 066 */ 067 public void testColumnCompare_prefix() throws Exception { 068 final byte [] a = Bytes.toBytes("aaa"); 069 byte [] family1 = Bytes.toBytes("abc"); 070 byte [] qualifier1 = Bytes.toBytes("def"); 071 byte [] family2 = Bytes.toBytes("ab"); 072 byte [] qualifier2 = Bytes.toBytes("def"); 073 074 KeyValue aaa = new KeyValue(a, family1, qualifier1, 0L, KeyValue.Type.Put, a); 075 assertFalse(CellUtil.matchingColumn(aaa, family2, qualifier2)); 076 } 077 078 public void testBasics() throws Exception { 079 LOG.info("LOWKEY: " + KeyValue.LOWESTKEY.toString()); 080 check(Bytes.toBytes(getName()), 081 Bytes.toBytes(getName()), Bytes.toBytes(getName()), 1, 082 Bytes.toBytes(getName())); 083 // Test empty value and empty column -- both should work. (not empty fam) 084 check(Bytes.toBytes(getName()), Bytes.toBytes(getName()), null, 1, null); 085 check(HConstants.EMPTY_BYTE_ARRAY, Bytes.toBytes(getName()), null, 1, null); 086 // empty qual is equivalent to null qual 087 assertEquals( 088 new KeyValue(Bytes.toBytes("rk"), Bytes.toBytes("fam"), null, 1, (byte[]) null), 089 new KeyValue(Bytes.toBytes("rk"), Bytes.toBytes("fam"), 090 HConstants.EMPTY_BYTE_ARRAY, 1, (byte[]) null)); 091 } 092 093 private void check(final byte [] row, final byte [] family, byte [] qualifier, 094 final long timestamp, final byte [] value) { 095 KeyValue kv = new KeyValue(row, family, qualifier, timestamp, value); 096 assertTrue(Bytes.compareTo(kv.getRowArray(), kv.getRowOffset(), kv.getRowLength(), row, 0, 097 row.length) == 0); 098 assertTrue(CellUtil.matchingColumn(kv, family, qualifier)); 099 // Call toString to make sure it works. 100 LOG.info(kv.toString()); 101 } 102 103 public void testPlainCompare() throws Exception { 104 final byte [] a = Bytes.toBytes("aaa"); 105 final byte [] b = Bytes.toBytes("bbb"); 106 final byte [] fam = Bytes.toBytes("col"); 107 final byte [] qf = Bytes.toBytes("umn"); 108 KeyValue aaa = new KeyValue(a, fam, qf, a); 109 KeyValue bbb = new KeyValue(b, fam, qf, b); 110 assertTrue(CellComparatorImpl.COMPARATOR.compare(aaa, bbb) < 0); 111 assertTrue(CellComparatorImpl.COMPARATOR.compare(bbb, aaa) > 0); 112 // Compare breaks if passed same ByteBuffer as both left and right arguments. 113 assertTrue(CellComparatorImpl.COMPARATOR.compare(bbb, bbb) == 0); 114 assertTrue(CellComparatorImpl.COMPARATOR.compare(aaa, aaa) == 0); 115 // Do compare with different timestamps. 116 aaa = new KeyValue(a, fam, qf, 1, a); 117 bbb = new KeyValue(a, fam, qf, 2, a); 118 assertTrue(CellComparatorImpl.COMPARATOR.compare(aaa, bbb) > 0); 119 assertTrue(CellComparatorImpl.COMPARATOR.compare(bbb, aaa) < 0); 120 assertTrue(CellComparatorImpl.COMPARATOR.compare(aaa, aaa) == 0); 121 // Do compare with different types. Higher numbered types -- Delete 122 // should sort ahead of lower numbers; i.e. Put 123 aaa = new KeyValue(a, fam, qf, 1, KeyValue.Type.Delete, a); 124 bbb = new KeyValue(a, fam, qf, 1, a); 125 assertTrue(CellComparatorImpl.COMPARATOR.compare(aaa, bbb) < 0); 126 assertTrue(CellComparatorImpl.COMPARATOR.compare(bbb, aaa) > 0); 127 assertTrue(CellComparatorImpl.COMPARATOR.compare(aaa, aaa) == 0); 128 } 129 130 public void testMoreComparisons() throws Exception { 131 long now = System.currentTimeMillis(); 132 133 // Meta compares 134 KeyValue aaa = new KeyValue( 135 Bytes.toBytes("TestScanMultipleVersions,row_0500,1236020145502"), now); 136 KeyValue bbb = new KeyValue( 137 Bytes.toBytes("TestScanMultipleVersions,,99999999999999"), now); 138 CellComparator c = CellComparatorImpl.META_COMPARATOR; 139 assertTrue(c.compare(bbb, aaa) < 0); 140 141 KeyValue aaaa = new KeyValue(Bytes.toBytes("TestScanMultipleVersions,,1236023996656"), 142 Bytes.toBytes("info"), Bytes.toBytes("regioninfo"), 1236024396271L, 143 (byte[])null); 144 assertTrue(c.compare(aaaa, bbb) < 0); 145 146 KeyValue x = new KeyValue(Bytes.toBytes("TestScanMultipleVersions,row_0500,1236034574162"), 147 Bytes.toBytes("info"), Bytes.toBytes(""), 9223372036854775807L, 148 (byte[])null); 149 KeyValue y = new KeyValue(Bytes.toBytes("TestScanMultipleVersions,row_0500,1236034574162"), 150 Bytes.toBytes("info"), Bytes.toBytes("regioninfo"), 1236034574912L, 151 (byte[])null); 152 assertTrue(c.compare(x, y) < 0); 153 comparisons(CellComparatorImpl.META_COMPARATOR); 154 comparisons(CellComparatorImpl.COMPARATOR); 155 metacomparisons(CellComparatorImpl.META_COMPARATOR); 156 } 157 158 public void testMetaComparatorTableKeysWithCommaOk() { 159 CellComparator c = CellComparatorImpl.META_COMPARATOR; 160 long now = System.currentTimeMillis(); 161 // meta keys values are not quite right. A users can enter illegal values 162 // from shell when scanning meta. 163 KeyValue a = new KeyValue(Bytes.toBytes("table,key,with,commas1,1234"), now); 164 KeyValue b = new KeyValue(Bytes.toBytes("table,key,with,commas2,0123"), now); 165 assertTrue(c.compare(a, b) < 0); 166 } 167 168 /** 169 * Tests cases where rows keys have characters below the ','. 170 * See HBASE-832 171 * @throws IOException 172 */ 173 public void testKeyValueBorderCases() throws IOException { 174 // % sorts before , so if we don't do special comparator, rowB would 175 // come before rowA. 176 KeyValue rowA = new KeyValue(Bytes.toBytes("testtable,www.hbase.org/,1234"), 177 Bytes.toBytes("fam"), Bytes.toBytes(""), Long.MAX_VALUE, (byte[])null); 178 KeyValue rowB = new KeyValue(Bytes.toBytes("testtable,www.hbase.org/%20,99999"), 179 Bytes.toBytes("fam"), Bytes.toBytes(""), Long.MAX_VALUE, (byte[])null); 180 assertTrue(CellComparatorImpl.META_COMPARATOR.compare(rowA, rowB) < 0); 181 182 rowA = new KeyValue(Bytes.toBytes("testtable,,1234"), Bytes.toBytes("fam"), 183 Bytes.toBytes(""), Long.MAX_VALUE, (byte[])null); 184 rowB = new KeyValue(Bytes.toBytes("testtable,$www.hbase.org/,99999"), 185 Bytes.toBytes("fam"), Bytes.toBytes(""), Long.MAX_VALUE, (byte[])null); 186 assertTrue(CellComparatorImpl.META_COMPARATOR.compare(rowA, rowB) < 0); 187 188 } 189 190 private void metacomparisons(final CellComparatorImpl c) { 191 long now = System.currentTimeMillis(); 192 assertTrue(c.compare(new KeyValue( 193 Bytes.toBytes(TableName.META_TABLE_NAME.getNameAsString()+",a,,0,1"), now), 194 new KeyValue( 195 Bytes.toBytes(TableName.META_TABLE_NAME.getNameAsString()+",a,,0,1"), now)) == 0); 196 KeyValue a = new KeyValue( 197 Bytes.toBytes(TableName.META_TABLE_NAME.getNameAsString()+",a,,0,1"), now); 198 KeyValue b = new KeyValue( 199 Bytes.toBytes(TableName.META_TABLE_NAME.getNameAsString()+",a,,0,2"), now); 200 assertTrue(c.compare(a, b) < 0); 201 assertTrue(c.compare(new KeyValue( 202 Bytes.toBytes(TableName.META_TABLE_NAME.getNameAsString()+",a,,0,2"), now), 203 new KeyValue( 204 Bytes.toBytes(TableName.META_TABLE_NAME.getNameAsString()+",a,,0,1"), now)) > 0); 205 } 206 207 private void comparisons(final CellComparatorImpl c) { 208 long now = System.currentTimeMillis(); 209 assertTrue(c.compare(new KeyValue( 210 Bytes.toBytes(TableName.META_TABLE_NAME.getNameAsString()+",,1"), now), 211 new KeyValue( 212 Bytes.toBytes(TableName.META_TABLE_NAME.getNameAsString()+",,1"), now)) == 0); 213 assertTrue(c.compare(new KeyValue( 214 Bytes.toBytes(TableName.META_TABLE_NAME.getNameAsString()+",,1"), now), 215 new KeyValue( 216 Bytes.toBytes(TableName.META_TABLE_NAME.getNameAsString()+",,2"), now)) < 0); 217 assertTrue(c.compare(new KeyValue( 218 Bytes.toBytes(TableName.META_TABLE_NAME.getNameAsString()+",,2"), now), 219 new KeyValue( 220 Bytes.toBytes(TableName.META_TABLE_NAME.getNameAsString()+",,1"), now)) > 0); 221 } 222 223 public void testBinaryKeys() throws Exception { 224 Set<KeyValue> set = new TreeSet<>(CellComparatorImpl.COMPARATOR); 225 final byte [] fam = Bytes.toBytes("col"); 226 final byte [] qf = Bytes.toBytes("umn"); 227 final byte [] nb = new byte[0]; 228 KeyValue [] keys = {new KeyValue(Bytes.toBytes("aaaaa,\u0000\u0000,2"), fam, qf, 2, nb), 229 new KeyValue(Bytes.toBytes("aaaaa,\u0001,3"), fam, qf, 3, nb), 230 new KeyValue(Bytes.toBytes("aaaaa,,1"), fam, qf, 1, nb), 231 new KeyValue(Bytes.toBytes("aaaaa,\u1000,5"), fam, qf, 5, nb), 232 new KeyValue(Bytes.toBytes("aaaaa,a,4"), fam, qf, 4, nb), 233 new KeyValue(Bytes.toBytes("a,a,0"), fam, qf, 0, nb), 234 }; 235 // Add to set with bad comparator 236 Collections.addAll(set, keys); 237 // This will output the keys incorrectly. 238 boolean assertion = false; 239 int count = 0; 240 try { 241 for (KeyValue k: set) { 242 assertTrue(count++ == k.getTimestamp()); 243 } 244 } catch (junit.framework.AssertionFailedError e) { 245 // Expected 246 assertion = true; 247 } 248 assertTrue(assertion); 249 // Make set with good comparator 250 set = new TreeSet<>(CellComparatorImpl.META_COMPARATOR); 251 Collections.addAll(set, keys); 252 count = 0; 253 for (KeyValue k: set) { 254 assertTrue(count++ == k.getTimestamp()); 255 } 256 } 257 258 public void testStackedUpKeyValue() { 259 // Test multiple KeyValues in a single blob. 260 261 // TODO actually write this test! 262 263 } 264 265 private final byte[] rowA = Bytes.toBytes("rowA"); 266 private final byte[] rowB = Bytes.toBytes("rowB"); 267 268 private final byte[] family = Bytes.toBytes("family"); 269 private final byte[] qualA = Bytes.toBytes("qfA"); 270 private final byte[] qualB = Bytes.toBytes("qfB"); 271 272 private void assertKVLess(CellComparator c, 273 KeyValue less, 274 KeyValue greater) { 275 int cmp = c.compare(less,greater); 276 assertTrue(cmp < 0); 277 cmp = c.compare(greater,less); 278 assertTrue(cmp > 0); 279 } 280 281 private void assertKVLessWithoutRow(CellComparator c, int common, KeyValue less, 282 KeyValue greater) { 283 int cmp = c.compare(less, greater); 284 assertTrue(cmp < 0); 285 cmp = c.compare(greater, less); 286 assertTrue(cmp > 0); 287 } 288 289 public void testCompareWithoutRow() { 290 final CellComparator c = CellComparatorImpl.COMPARATOR; 291 byte[] row = Bytes.toBytes("row"); 292 293 byte[] fa = Bytes.toBytes("fa"); 294 byte[] fami = Bytes.toBytes("fami"); 295 byte[] fami1 = Bytes.toBytes("fami1"); 296 297 byte[] qual0 = Bytes.toBytes(""); 298 byte[] qual1 = Bytes.toBytes("qf1"); 299 byte[] qual2 = Bytes.toBytes("qf2"); 300 long ts = 1; 301 302 // 'fa:' 303 KeyValue kv_0 = new KeyValue(row, fa, qual0, ts, KeyValue.Type.Put); 304 // 'fami:' 305 KeyValue kv0_0 = new KeyValue(row, fami, qual0, ts, KeyValue.Type.Put); 306 // 'fami:qf1' 307 KeyValue kv0_1 = new KeyValue(row, fami, qual1, ts, KeyValue.Type.Put); 308 // 'fami:qf2' 309 KeyValue kv0_2 = new KeyValue(row, fami, qual2, ts, KeyValue.Type.Put); 310 // 'fami1:' 311 KeyValue kv1_0 = new KeyValue(row, fami1, qual0, ts, KeyValue.Type.Put); 312 313 // 'fami:qf1' < 'fami:qf2' 314 assertKVLessWithoutRow(c, 0, kv0_1, kv0_2); 315 // 'fami:qf1' < 'fami1:' 316 assertKVLessWithoutRow(c, 0, kv0_1, kv1_0); 317 318 // Test comparison by skipping the same prefix bytes. 319 /*** 320 * KeyValue Format and commonLength: 321 * |_keyLen_|_valLen_|_rowLen_|_rowKey_|_famiLen_|_fami_|_Quali_|.... 322 * ------------------|-------commonLength--------|-------------- 323 */ 324 int commonLength = KeyValue.ROW_LENGTH_SIZE + KeyValue.FAMILY_LENGTH_SIZE 325 + row.length; 326 // 'fa:' < 'fami:'. They have commonPrefix + 2 same prefix bytes. 327 assertKVLessWithoutRow(c, commonLength + 2, kv_0, kv0_0); 328 // 'fami:' < 'fami:qf1'. They have commonPrefix + 4 same prefix bytes. 329 assertKVLessWithoutRow(c, commonLength + 4, kv0_0, kv0_1); 330 // 'fami:qf1' < 'fami1:'. They have commonPrefix + 4 same prefix bytes. 331 assertKVLessWithoutRow(c, commonLength + 4, kv0_1, kv1_0); 332 // 'fami:qf1' < 'fami:qf2'. They have commonPrefix + 6 same prefix bytes. 333 assertKVLessWithoutRow(c, commonLength + 6, kv0_1, kv0_2); 334 } 335 336 public void testFirstLastOnRow() { 337 final CellComparator c = CellComparatorImpl.COMPARATOR; 338 long ts = 1; 339 byte[] bufferA = new byte[128]; 340 int offsetA = 0; 341 byte[] bufferB = new byte[128]; 342 int offsetB = 7; 343 344 // These are listed in sort order (ie: every one should be less 345 // than the one on the next line). 346 final KeyValue firstOnRowA = KeyValueUtil.createFirstOnRow(rowA); 347 final KeyValue firstOnRowABufferFamQual = KeyValueUtil.createFirstOnRow(bufferA, offsetA, 348 rowA, 0, rowA.length, family, 0, family.length, qualA, 0, qualA.length); 349 final KeyValue kvA_1 = new KeyValue(rowA, null, null, ts, KeyValue.Type.Put); 350 final KeyValue kvA_2 = new KeyValue(rowA, family, qualA, ts, KeyValue.Type.Put); 351 352 final KeyValue lastOnRowA = KeyValueUtil.createLastOnRow(rowA); 353 final KeyValue firstOnRowB = KeyValueUtil.createFirstOnRow(rowB); 354 final KeyValue firstOnRowBBufferFam = KeyValueUtil.createFirstOnRow(bufferB, offsetB, 355 rowB, 0, rowB.length, family, 0, family.length, null, 0, 0); 356 final KeyValue kvB = new KeyValue(rowB, family, qualA, ts, KeyValue.Type.Put); 357 358 assertKVLess(c, firstOnRowA, firstOnRowB); 359 assertKVLess(c, firstOnRowA, firstOnRowBBufferFam); 360 assertKVLess(c, firstOnRowABufferFamQual, firstOnRowB); 361 assertKVLess(c, firstOnRowA, kvA_1); 362 assertKVLess(c, firstOnRowA, kvA_2); 363 assertKVLess(c, firstOnRowABufferFamQual, kvA_2); 364 assertKVLess(c, kvA_1, kvA_2); 365 assertKVLess(c, kvA_2, firstOnRowB); 366 assertKVLess(c, kvA_1, firstOnRowB); 367 assertKVLess(c, kvA_2, firstOnRowBBufferFam); 368 assertKVLess(c, kvA_1, firstOnRowBBufferFam); 369 370 assertKVLess(c, lastOnRowA, firstOnRowB); 371 assertKVLess(c, lastOnRowA, firstOnRowBBufferFam); 372 assertKVLess(c, firstOnRowB, kvB); 373 assertKVLess(c, firstOnRowBBufferFam, kvB); 374 assertKVLess(c, lastOnRowA, kvB); 375 376 assertKVLess(c, kvA_2, lastOnRowA); 377 assertKVLess(c, kvA_1, lastOnRowA); 378 assertKVLess(c, firstOnRowA, lastOnRowA); 379 assertKVLess(c, firstOnRowABufferFamQual, lastOnRowA); 380 } 381 382 public void testCreateKeyOnly() throws Exception { 383 long ts = 1; 384 byte [] value = Bytes.toBytes("a real value"); 385 byte [] evalue = new byte[0]; // empty value 386 387 for (byte[] val : new byte[][]{value, evalue}) { 388 for (boolean useLen : new boolean[]{false,true}) { 389 KeyValue kv1 = new KeyValue(rowA, family, qualA, ts, val); 390 KeyValue kv1ko = kv1.createKeyOnly(useLen); 391 // keys are still the same 392 assertTrue(kv1.equals(kv1ko)); 393 // but values are not 394 assertTrue(kv1ko.getValueLength() == (useLen?Bytes.SIZEOF_INT:0)); 395 if (useLen) { 396 assertEquals(kv1.getValueLength(), 397 Bytes.toInt(kv1ko.getValueArray(), kv1ko.getValueOffset(), kv1ko.getValueLength())); 398 } 399 } 400 } 401 } 402 403 public void testCreateKeyValueFromKey() { 404 KeyValue kv = new KeyValue(Bytes.toBytes("myRow"), Bytes.toBytes("myCF"), 405 Bytes.toBytes("myQualifier"), 12345L, Bytes.toBytes("myValue")); 406 int initialPadding = 10; 407 int endingPadding = 20; 408 int keyLen = kv.getKeyLength(); 409 byte[] tmpArr = new byte[initialPadding + endingPadding + keyLen]; 410 System.arraycopy(kv.getBuffer(), kv.getKeyOffset(), tmpArr, 411 initialPadding, keyLen); 412 KeyValue kvFromKey = KeyValueUtil.createKeyValueFromKey(tmpArr, initialPadding, 413 keyLen); 414 assertEquals(keyLen, kvFromKey.getKeyLength()); 415 assertEquals(KeyValue.ROW_OFFSET + keyLen, kvFromKey.getBuffer().length); 416 System.err.println("kv=" + kv); 417 System.err.println("kvFromKey=" + kvFromKey); 418 assertEquals(kvFromKey.toString(), 419 kv.toString().replaceAll("=[0-9]+", "=0")); 420 } 421 422 /** 423 * Tests that getTimestamp() does always return the proper timestamp, even after updating it. 424 * See HBASE-6265. 425 */ 426 public void testGetTimestamp() { 427 KeyValue kv = new KeyValue(Bytes.toBytes("myRow"), Bytes.toBytes("myCF"), 428 Bytes.toBytes("myQualifier"), HConstants.LATEST_TIMESTAMP, 429 Bytes.toBytes("myValue")); 430 long time1 = kv.getTimestamp(); 431 kv.updateLatestStamp(Bytes.toBytes(12345L)); 432 long time2 = kv.getTimestamp(); 433 assertEquals(HConstants.LATEST_TIMESTAMP, time1); 434 assertEquals(12345L, time2); 435 } 436 437 public void testKVsWithTags() { 438 byte[] row = Bytes.toBytes("myRow"); 439 byte[] cf = Bytes.toBytes("myCF"); 440 byte[] q = Bytes.toBytes("myQualifier"); 441 byte[] value = Bytes.toBytes("myValue"); 442 byte[] metaValue1 = Bytes.toBytes("metaValue1"); 443 byte[] metaValue2 = Bytes.toBytes("metaValue2"); 444 KeyValue kv = new KeyValue(row, cf, q, HConstants.LATEST_TIMESTAMP, value, new Tag[] { 445 new ArrayBackedTag((byte) 1, metaValue1), new ArrayBackedTag((byte) 2, metaValue2) }); 446 assertTrue(kv.getTagsLength() > 0); 447 assertTrue(Bytes.equals(kv.getRowArray(), kv.getRowOffset(), kv.getRowLength(), row, 0, 448 row.length)); 449 assertTrue(Bytes.equals(kv.getFamilyArray(), kv.getFamilyOffset(), kv.getFamilyLength(), cf, 0, 450 cf.length)); 451 assertTrue(Bytes.equals(kv.getQualifierArray(), kv.getQualifierOffset(), 452 kv.getQualifierLength(), q, 0, q.length)); 453 assertTrue(Bytes.equals(kv.getValueArray(), kv.getValueOffset(), kv.getValueLength(), value, 0, 454 value.length)); 455 List<Tag> tags = PrivateCellUtil.getTags(kv); 456 assertNotNull(tags); 457 assertEquals(2, tags.size()); 458 boolean meta1Ok = false, meta2Ok = false; 459 for (Tag tag : tags) { 460 if (tag.getType() == (byte) 1) { 461 if (Bytes.equals(Tag.cloneValue(tag), metaValue1)) { 462 meta1Ok = true; 463 } 464 } else { 465 if (Bytes.equals(Tag.cloneValue(tag), metaValue2)) { 466 meta2Ok = true; 467 } 468 } 469 } 470 assertTrue(meta1Ok); 471 assertTrue(meta2Ok); 472 Iterator<Tag> tagItr = PrivateCellUtil.tagsIterator(kv); 473 //Iterator<Tag> tagItr = kv.tagsIterator(); 474 assertTrue(tagItr.hasNext()); 475 Tag next = tagItr.next(); 476 assertEquals(10, next.getValueLength()); 477 assertEquals((byte) 1, next.getType()); 478 Bytes.equals(Tag.cloneValue(next), metaValue1); 479 assertTrue(tagItr.hasNext()); 480 next = tagItr.next(); 481 assertEquals(10, next.getValueLength()); 482 assertEquals((byte) 2, next.getType()); 483 Bytes.equals(Tag.cloneValue(next), metaValue2); 484 assertFalse(tagItr.hasNext()); 485 486 tagItr = PrivateCellUtil.tagsIterator(kv); 487 assertTrue(tagItr.hasNext()); 488 next = tagItr.next(); 489 assertEquals(10, next.getValueLength()); 490 assertEquals((byte) 1, next.getType()); 491 Bytes.equals(Tag.cloneValue(next), metaValue1); 492 assertTrue(tagItr.hasNext()); 493 next = tagItr.next(); 494 assertEquals(10, next.getValueLength()); 495 assertEquals((byte) 2, next.getType()); 496 Bytes.equals(Tag.cloneValue(next), metaValue2); 497 assertFalse(tagItr.hasNext()); 498 } 499 500 public void testMetaKeyComparator() { 501 CellComparator c = CellComparatorImpl.META_COMPARATOR; 502 long now = System.currentTimeMillis(); 503 504 KeyValue a = new KeyValue(Bytes.toBytes("table1"), now); 505 KeyValue b = new KeyValue(Bytes.toBytes("table2"), now); 506 assertTrue(c.compare(a, b) < 0); 507 508 a = new KeyValue(Bytes.toBytes("table1,111"), now); 509 b = new KeyValue(Bytes.toBytes("table2"), now); 510 assertTrue(c.compare(a, b) < 0); 511 512 a = new KeyValue(Bytes.toBytes("table1"), now); 513 b = new KeyValue(Bytes.toBytes("table2,111"), now); 514 assertTrue(c.compare(a, b) < 0); 515 516 a = new KeyValue(Bytes.toBytes("table,111"), now); 517 b = new KeyValue(Bytes.toBytes("table,2222"), now); 518 assertTrue(c.compare(a, b) < 0); 519 520 a = new KeyValue(Bytes.toBytes("table,111,aaaa"), now); 521 b = new KeyValue(Bytes.toBytes("table,2222"), now); 522 assertTrue(c.compare(a, b) < 0); 523 524 a = new KeyValue(Bytes.toBytes("table,111"), now); 525 b = new KeyValue(Bytes.toBytes("table,2222.bbb"), now); 526 assertTrue(c.compare(a, b) < 0); 527 528 a = new KeyValue(Bytes.toBytes("table,,aaaa"), now); 529 b = new KeyValue(Bytes.toBytes("table,111,bbb"), now); 530 assertTrue(c.compare(a, b) < 0); 531 532 a = new KeyValue(Bytes.toBytes("table,111,aaaa"), now); 533 b = new KeyValue(Bytes.toBytes("table,111,bbb"), now); 534 assertTrue(c.compare(a, b) < 0); 535 536 a = new KeyValue(Bytes.toBytes("table,111,xxxx"), now); 537 b = new KeyValue(Bytes.toBytes("table,111,222,bbb"), now); 538 assertTrue(c.compare(a, b) < 0); 539 540 a = new KeyValue(Bytes.toBytes("table,111,11,xxx"), now); 541 b = new KeyValue(Bytes.toBytes("table,111,222,bbb"), now); 542 assertTrue(c.compare(a, b) < 0); 543 } 544 545 public void testEqualsAndHashCode() throws Exception { 546 KeyValue kvA1 = new KeyValue(Bytes.toBytes("key"), Bytes.toBytes("cf"), 547 Bytes.toBytes("qualA"), Bytes.toBytes("1")); 548 KeyValue kvA2 = new KeyValue(Bytes.toBytes("key"), Bytes.toBytes("cf"), 549 Bytes.toBytes("qualA"), Bytes.toBytes("2")); 550 // We set a different sequence id on kvA2 to demonstrate that the equals and hashCode also 551 // don't take this into account. 552 kvA2.setSequenceId(2); 553 KeyValue kvB = new KeyValue(Bytes.toBytes("key"), Bytes.toBytes("cf"), 554 Bytes.toBytes("qualB"), Bytes.toBytes("1")); 555 556 assertEquals(kvA1, kvA2); 557 assertNotEquals(kvA1, kvB); 558 assertEquals(kvA1.hashCode(), kvA2.hashCode()); 559 assertNotEquals(kvA1.hashCode(), kvB.hashCode()); 560 561 } 562 563 public void testKeyValueSerialization() throws Exception { 564 KeyValue kvA1 = new KeyValue(Bytes.toBytes("key"), Bytes.toBytes("cf"), Bytes.toBytes("qualA"), 565 Bytes.toBytes("1")); 566 KeyValue kvA2 = new KeyValue(Bytes.toBytes("key"), Bytes.toBytes("cf"), Bytes.toBytes("qualA"), 567 Bytes.toBytes("2")); 568 MockKeyValue mkvA1 = new MockKeyValue(kvA1); 569 MockKeyValue mkvA2 = new MockKeyValue(kvA2); 570 ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); 571 DataOutputStream os = new DataOutputStream(byteArrayOutputStream); 572 ByteBufferUtils.putInt(os, KeyValueUtil.getSerializedSize(mkvA1, true)); 573 KeyValueUtil.oswrite(mkvA1, os, true); 574 ByteBufferUtils.putInt(os, KeyValueUtil.getSerializedSize(mkvA2, true)); 575 KeyValueUtil.oswrite(mkvA2, os, true); 576 DataInputStream is = new DataInputStream(new ByteArrayInputStream( 577 byteArrayOutputStream.toByteArray())); 578 KeyValue deSerKV1 = KeyValueUtil.iscreate(is, true); 579 assertTrue(kvA1.equals(deSerKV1)); 580 KeyValue deSerKV2 = KeyValueUtil.iscreate(is, true); 581 assertTrue(kvA2.equals(deSerKV2)); 582 } 583 584 private static class MockKeyValue implements Cell { 585 private final KeyValue kv; 586 587 public MockKeyValue(KeyValue kv) { 588 this.kv = kv; 589 } 590 591 /** 592 * This returns the offset where the tag actually starts. 593 */ 594 @Override 595 public int getTagsOffset() { 596 return this.kv.getTagsOffset(); 597 } 598 599 /** 600 * used to achieve atomic operations in the memstore. 601 */ 602 @Override 603 public long getSequenceId() { 604 return this.kv.getSequenceId(); 605 } 606 607 /** 608 * This returns the total length of the tag bytes 609 */ 610 @Override 611 public int getTagsLength() { 612 return this.kv.getTagsLength(); 613 } 614 615 /** 616 * 617 * @return Timestamp 618 */ 619 @Override 620 public long getTimestamp() { 621 return this.kv.getTimestamp(); 622 } 623 624 /** 625 * @return KeyValue.TYPE byte representation 626 */ 627 @Override 628 public byte getTypeByte() { 629 return this.kv.getTypeByte(); 630 } 631 632 /** 633 * @return the backing array of the entire KeyValue (all KeyValue fields are 634 * in a single array) 635 */ 636 @Override 637 public byte[] getValueArray() { 638 return this.kv.getValueArray(); 639 } 640 641 /** 642 * @return the value offset 643 */ 644 @Override 645 public int getValueOffset() { 646 return this.kv.getValueOffset(); 647 } 648 649 /** 650 * @return Value length 651 */ 652 @Override 653 public int getValueLength() { 654 return this.kv.getValueLength(); 655 } 656 657 /** 658 * @return the backing array of the entire KeyValue (all KeyValue fields are 659 * in a single array) 660 */ 661 @Override 662 public byte[] getRowArray() { 663 return this.kv.getRowArray(); 664 } 665 666 /** 667 * @return Row offset 668 */ 669 @Override 670 public int getRowOffset() { 671 return this.kv.getRowOffset(); 672 } 673 674 /** 675 * @return Row length 676 */ 677 @Override 678 public short getRowLength() { 679 return this.kv.getRowLength(); 680 } 681 682 /** 683 * @return the backing array of the entire KeyValue (all KeyValue fields are 684 * in a single array) 685 */ 686 @Override 687 public byte[] getFamilyArray() { 688 return this.kv.getFamilyArray(); 689 } 690 691 /** 692 * @return Family offset 693 */ 694 @Override 695 public int getFamilyOffset() { 696 return this.kv.getFamilyOffset(); 697 } 698 699 /** 700 * @return Family length 701 */ 702 @Override 703 public byte getFamilyLength() { 704 return this.kv.getFamilyLength(); 705 } 706 707 /** 708 * @return the backing array of the entire KeyValue (all KeyValue fields are 709 * in a single array) 710 */ 711 @Override 712 public byte[] getQualifierArray() { 713 return this.kv.getQualifierArray(); 714 } 715 716 /** 717 * @return Qualifier offset 718 */ 719 @Override 720 public int getQualifierOffset() { 721 return this.kv.getQualifierOffset(); 722 } 723 724 /** 725 * @return Qualifier length 726 */ 727 @Override 728 public int getQualifierLength() { 729 return this.kv.getQualifierLength(); 730 } 731 732 /** 733 * @return the backing array of the entire KeyValue (all KeyValue fields are 734 * in a single array) 735 */ 736 @Override 737 public byte[] getTagsArray() { 738 return this.kv.getTagsArray(); 739 } 740 } 741}