001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.regionserver; 019 020import static org.junit.jupiter.api.Assertions.assertEquals; 021import static org.junit.jupiter.api.Assertions.assertFalse; 022import static org.junit.jupiter.api.Assertions.assertNotNull; 023import static org.junit.jupiter.api.Assertions.assertNull; 024import static org.junit.jupiter.api.Assertions.assertTrue; 025 026import java.io.IOException; 027import java.util.ArrayList; 028import java.util.Arrays; 029import java.util.List; 030import java.util.NavigableMap; 031import java.util.Objects; 032import java.util.TreeMap; 033import java.util.concurrent.atomic.AtomicReference; 034import org.apache.hadoop.conf.Configuration; 035import org.apache.hadoop.fs.Path; 036import org.apache.hadoop.hbase.Cell; 037import org.apache.hadoop.hbase.CellComparatorImpl; 038import org.apache.hadoop.hbase.CellUtil; 039import org.apache.hadoop.hbase.ExtendedCell; 040import org.apache.hadoop.hbase.HBaseConfiguration; 041import org.apache.hadoop.hbase.HBaseTestingUtil; 042import org.apache.hadoop.hbase.HConstants; 043import org.apache.hadoop.hbase.KeepDeletedCells; 044import org.apache.hadoop.hbase.KeyValue; 045import org.apache.hadoop.hbase.KeyValueTestUtil; 046import org.apache.hadoop.hbase.KeyValueUtil; 047import org.apache.hadoop.hbase.TableDescriptors; 048import org.apache.hadoop.hbase.TableName; 049import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder; 050import org.apache.hadoop.hbase.client.Put; 051import org.apache.hadoop.hbase.client.RegionInfo; 052import org.apache.hadoop.hbase.client.RegionInfoBuilder; 053import org.apache.hadoop.hbase.client.Scan; 054import org.apache.hadoop.hbase.client.TableDescriptor; 055import org.apache.hadoop.hbase.client.TableDescriptorBuilder; 056import org.apache.hadoop.hbase.exceptions.UnexpectedStateException; 057import org.apache.hadoop.hbase.monitoring.ThreadLocalServerSideScanMetrics; 058import org.apache.hadoop.hbase.testclassification.MediumTests; 059import org.apache.hadoop.hbase.testclassification.RegionServerTests; 060import org.apache.hadoop.hbase.util.Bytes; 061import org.apache.hadoop.hbase.util.EnvironmentEdge; 062import org.apache.hadoop.hbase.util.EnvironmentEdgeManager; 063import org.apache.hadoop.hbase.util.FSTableDescriptors; 064import org.apache.hadoop.hbase.wal.WALFactory; 065import org.junit.jupiter.api.AfterAll; 066import org.junit.jupiter.api.AfterEach; 067import org.junit.jupiter.api.BeforeEach; 068import org.junit.jupiter.api.Tag; 069import org.junit.jupiter.api.Test; 070import org.junit.jupiter.api.TestInfo; 071import org.slf4j.Logger; 072import org.slf4j.LoggerFactory; 073 074import org.apache.hbase.thirdparty.com.google.common.base.Joiner; 075import org.apache.hbase.thirdparty.com.google.common.collect.Iterables; 076import org.apache.hbase.thirdparty.com.google.common.collect.Lists; 077 078/** memstore test case */ 079@Tag(RegionServerTests.TAG) 080@Tag(MediumTests.TAG) 081public class TestDefaultMemStore { 082 083 private static final Logger LOG = LoggerFactory.getLogger(TestDefaultMemStore.class); 084 085 protected AbstractMemStore memstore; 086 protected static final int ROW_COUNT = 10; 087 protected static final int SCAN_ROW_COUNT = 25000; 088 protected static final int QUALIFIER_COUNT = ROW_COUNT; 089 protected static final byte[] FAMILY = Bytes.toBytes("column"); 090 protected MultiVersionConcurrencyControl mvcc; 091 protected ChunkCreator chunkCreator; 092 protected String name; 093 094 @BeforeEach 095 public void setUp(TestInfo testInfo) throws Exception { 096 this.name = getTestName(testInfo); 097 internalSetUp(); 098 createChunkCreator(); 099 createMemStore(); 100 } 101 102 @AfterEach 103 public void tearDown() throws Exception { 104 internalTearDown(); 105 this.memstore.close(); 106 } 107 108 @AfterAll 109 public static void tearDownClass() { 110 ChunkCreator.getInstance().clearChunkIds(); 111 } 112 113 protected String getTestName(TestInfo testInfo) { 114 String methodName = testInfo.getTestMethod().get().getName(); 115 String displayName = testInfo.getDisplayName(); 116 String name = methodName + getParameterizedTestNameSuffix(); 117 if (!displayName.equals(methodName) && !displayName.equals(methodName + "()")) { 118 name += "_" + displayName; 119 } 120 return name.replaceAll("[^A-Za-z0-9_.-]", "_"); 121 } 122 123 protected String getParameterizedTestNameSuffix() { 124 return ""; 125 } 126 127 protected void createChunkCreator() { 128 // no pool 129 this.chunkCreator = ChunkCreator.initialize(MemStoreLAB.CHUNK_SIZE_DEFAULT, false, 0, 0, 0, 130 null, MemStoreLAB.INDEX_CHUNK_SIZE_PERCENTAGE_DEFAULT); 131 } 132 133 protected void createMemStore() throws IOException { 134 this.memstore = new DefaultMemStore(); 135 } 136 137 protected void internalSetUp() throws Exception { 138 this.mvcc = new MultiVersionConcurrencyControl(); 139 } 140 141 protected void internalTearDown() throws Exception { 142 } 143 144 @Test 145 public void testPutSameKey() { 146 byte[] bytes = Bytes.toBytes(this.name); 147 KeyValue kv = new KeyValue(bytes, bytes, bytes, bytes); 148 this.memstore.add(kv, null); 149 byte[] other = Bytes.toBytes("somethingelse"); 150 KeyValue samekey = new KeyValue(bytes, bytes, bytes, other); 151 this.memstore.add(samekey, null); 152 Cell found = this.memstore.getActive().first(); 153 assertEquals(1, this.memstore.getActive().getCellsCount()); 154 assertTrue(CellUtil.matchingValue(samekey, found), Bytes.toString(found.getValueArray())); 155 } 156 157 @Test 158 public void testPutSameCell() { 159 byte[] bytes = Bytes.toBytes(this.name); 160 KeyValue kv = new KeyValue(bytes, bytes, bytes, bytes); 161 MemStoreSizing sizeChangeForFirstCell = new NonThreadSafeMemStoreSizing(); 162 this.memstore.add(kv, sizeChangeForFirstCell); 163 MemStoreSizing sizeChangeForSecondCell = new NonThreadSafeMemStoreSizing(); 164 this.memstore.add(kv, sizeChangeForSecondCell); 165 // make sure memstore size increase won't double-count MSLAB chunk size 166 assertEquals(Segment.getCellLength(kv), sizeChangeForFirstCell.getMemStoreSize().getDataSize()); 167 Segment segment = this.memstore.getActive(); 168 MemStoreLAB msLab = segment.getMemStoreLAB(); 169 if (msLab != null) { 170 // make sure memstore size increased even when writing the same cell, if using MSLAB 171 assertEquals(Segment.getCellLength(kv), 172 sizeChangeForSecondCell.getMemStoreSize().getDataSize()); 173 // make sure chunk size increased even when writing the same cell, if using MSLAB 174 if (msLab instanceof MemStoreLABImpl) { 175 // since we add the chunkID at the 0th offset of the chunk and the 176 // chunkid is an int we need to account for those 4 bytes 177 assertEquals(2 * Segment.getCellLength(kv) + Bytes.SIZEOF_INT, 178 ((MemStoreLABImpl) msLab).getCurrentChunk().getNextFreeOffset()); 179 } 180 } else { 181 // make sure no memstore size change w/o MSLAB 182 assertEquals(0, sizeChangeForSecondCell.getMemStoreSize().getDataSize()); 183 assertEquals(0, sizeChangeForSecondCell.getMemStoreSize().getHeapSize()); 184 } 185 } 186 187 /** 188 * Test memstore snapshot happening while scanning. 189 */ 190 @Test 191 public void testScanAcrossSnapshot() throws IOException { 192 int rowCount = addRows(this.memstore); 193 List<KeyValueScanner> memstorescanners = this.memstore.getScanners(0); 194 Scan scan = new Scan(); 195 List<Cell> result = new ArrayList<>(); 196 Configuration conf = HBaseConfiguration.create(); 197 ScanInfo scanInfo = 198 new ScanInfo(conf, null, 0, 1, HConstants.LATEST_TIMESTAMP, KeepDeletedCells.FALSE, 199 HConstants.DEFAULT_BLOCKSIZE, 0, this.memstore.getComparator(), false); 200 int count = 0; 201 try (StoreScanner s = new StoreScanner(scan, scanInfo, null, memstorescanners)) { 202 while (s.next(result)) { 203 LOG.info(Objects.toString(result)); 204 count++; 205 // Row count is same as column count. 206 assertEquals(rowCount, result.size()); 207 result.clear(); 208 } 209 } 210 assertEquals(rowCount, count); 211 for (KeyValueScanner scanner : memstorescanners) { 212 scanner.close(); 213 } 214 215 memstorescanners = this.memstore.getScanners(mvcc.getReadPoint()); 216 // Now assert can count same number even if a snapshot mid-scan. 217 count = 0; 218 try (StoreScanner s = new StoreScanner(scan, scanInfo, null, memstorescanners)) { 219 while (s.next(result)) { 220 LOG.info(Objects.toString(result)); 221 // Assert the stuff is coming out in right order. 222 assertTrue(CellUtil.matchingRows(result.get(0), Bytes.toBytes(count))); 223 count++; 224 // Row count is same as column count. 225 assertEquals(rowCount, result.size()); 226 if (count == 2) { 227 this.memstore.snapshot(); 228 LOG.info("Snapshotted"); 229 } 230 result.clear(); 231 } 232 } 233 assertEquals(rowCount, count); 234 for (KeyValueScanner scanner : memstorescanners) { 235 scanner.close(); 236 } 237 memstorescanners = this.memstore.getScanners(mvcc.getReadPoint()); 238 // Assert that new values are seen in kvset as we scan. 239 long ts = EnvironmentEdgeManager.currentTime(); 240 count = 0; 241 int snapshotIndex = 5; 242 try (StoreScanner s = new StoreScanner(scan, scanInfo, null, memstorescanners)) { 243 while (s.next(result)) { 244 LOG.info(Objects.toString(result)); 245 // Assert the stuff is coming out in right order. 246 assertTrue(CellUtil.matchingRows(result.get(0), Bytes.toBytes(count))); 247 // Row count is same as column count. 248 assertEquals(rowCount, result.size(), "count=" + count + ", result=" + result); 249 count++; 250 if (count == snapshotIndex) { 251 MemStoreSnapshot snapshot = this.memstore.snapshot(); 252 this.memstore.clearSnapshot(snapshot.getId()); 253 // Added more rows into kvset. But the scanner wont see these rows. 254 addRows(this.memstore, ts); 255 LOG.info("Snapshotted, cleared it and then added values (which wont be seen)"); 256 } 257 result.clear(); 258 } 259 } 260 assertEquals(rowCount, count); 261 } 262 263 /** 264 * A simple test which verifies the 3 possible states when scanning across snapshot. 265 */ 266 @Test 267 public void testScanAcrossSnapshot2() throws IOException, CloneNotSupportedException { 268 // we are going to the scanning across snapshot with two kvs 269 // kv1 should always be returned before kv2 270 final byte[] one = Bytes.toBytes(1); 271 final byte[] two = Bytes.toBytes(2); 272 final byte[] f = Bytes.toBytes("f"); 273 final byte[] q = Bytes.toBytes("q"); 274 final byte[] v = Bytes.toBytes(3); 275 276 final KeyValue kv1 = new KeyValue(one, f, q, v); 277 final KeyValue kv2 = new KeyValue(two, f, q, v); 278 279 // use case 1: both kvs in kvset 280 this.memstore.add(kv1.clone(), null); 281 this.memstore.add(kv2.clone(), null); 282 // snapshot is empty,active segment is not empty, 283 // empty segment is skipped. 284 verifyOneScanAcrossSnapshot2(kv1, kv2); 285 286 // use case 2: both kvs in snapshot 287 // active segment is empty,snapshot is not empty, 288 // empty segment is skipped. 289 this.memstore.snapshot(); 290 // 291 verifyOneScanAcrossSnapshot2(kv1, kv2); 292 293 // use case 3: first in snapshot second in kvset 294 this.memstore = new DefaultMemStore(); 295 this.memstore.add(kv1.clone(), null); 296 this.memstore.snapshot(); 297 this.memstore.add(kv2.clone(), null); 298 verifyScanAcrossSnapshot2(kv1, kv2); 299 } 300 301 protected void verifyScanAcrossSnapshot2(KeyValue kv1, KeyValue kv2) throws IOException { 302 List<KeyValueScanner> memstorescanners = this.memstore.getScanners(mvcc.getReadPoint()); 303 assertEquals(2, memstorescanners.size()); 304 final KeyValueScanner scanner0 = memstorescanners.get(0); 305 final KeyValueScanner scanner1 = memstorescanners.get(1); 306 scanner0.seek(KeyValueUtil.createFirstOnRow(HConstants.EMPTY_START_ROW)); 307 scanner1.seek(KeyValueUtil.createFirstOnRow(HConstants.EMPTY_START_ROW)); 308 Cell n0 = scanner0.next(); 309 Cell n1 = scanner1.next(); 310 assertTrue(kv1.equals(n0) || kv1.equals(n1)); 311 assertTrue(kv2.equals(n0) || kv2.equals(n1) || kv2.equals(scanner0.next()) 312 || kv2.equals(scanner1.next())); 313 assertNull(scanner0.next()); 314 assertNull(scanner1.next()); 315 } 316 317 protected void verifyOneScanAcrossSnapshot2(KeyValue kv1, KeyValue kv2) throws IOException { 318 List<KeyValueScanner> memstorescanners = this.memstore.getScanners(mvcc.getReadPoint()); 319 assertEquals(1, memstorescanners.size()); 320 final KeyValueScanner scanner0 = memstorescanners.get(0); 321 scanner0.seek(KeyValueUtil.createFirstOnRow(HConstants.EMPTY_START_ROW)); 322 Cell n0 = scanner0.next(); 323 Cell n1 = scanner0.next(); 324 assertEquals(kv1, n0); 325 assertEquals(kv2, n1); 326 assertNull(scanner0.next()); 327 } 328 329 protected void assertScannerResults(KeyValueScanner scanner, KeyValue[] expected) 330 throws IOException { 331 scanner.seek(KeyValueUtil.createFirstOnRow(new byte[] {})); 332 List<Cell> returned = Lists.newArrayList(); 333 334 while (true) { 335 Cell next = scanner.next(); 336 if (next == null) break; 337 returned.add(next); 338 } 339 340 assertTrue(Iterables.elementsEqual(Arrays.asList(expected), returned), 341 "Got:\n" + Joiner.on("\n").join(returned) + "\nExpected:\n" + Joiner.on("\n").join(expected)); 342 assertNull(scanner.peek()); 343 } 344 345 @Test 346 public void testMemstoreConcurrentControl() throws IOException { 347 final byte[] row = Bytes.toBytes(1); 348 final byte[] f = Bytes.toBytes("family"); 349 final byte[] q1 = Bytes.toBytes("q1"); 350 final byte[] q2 = Bytes.toBytes("q2"); 351 final byte[] v = Bytes.toBytes("value"); 352 353 MultiVersionConcurrencyControl.WriteEntry w = mvcc.begin(); 354 355 KeyValue kv1 = new KeyValue(row, f, q1, v); 356 kv1.setSequenceId(w.getWriteNumber()); 357 memstore.add(kv1, null); 358 359 KeyValueScanner s = this.memstore.getScanners(mvcc.getReadPoint()).get(0); 360 assertScannerResults(s, new KeyValue[] {}); 361 362 mvcc.completeAndWait(w); 363 364 s = this.memstore.getScanners(mvcc.getReadPoint()).get(0); 365 assertScannerResults(s, new KeyValue[] { kv1 }); 366 367 w = mvcc.begin(); 368 KeyValue kv2 = new KeyValue(row, f, q2, v); 369 kv2.setSequenceId(w.getWriteNumber()); 370 memstore.add(kv2, null); 371 372 s = this.memstore.getScanners(mvcc.getReadPoint()).get(0); 373 assertScannerResults(s, new KeyValue[] { kv1 }); 374 375 mvcc.completeAndWait(w); 376 377 s = this.memstore.getScanners(mvcc.getReadPoint()).get(0); 378 assertScannerResults(s, new KeyValue[] { kv1, kv2 }); 379 } 380 381 private long getBytesReadFromMemstore() throws IOException { 382 final byte[] f = Bytes.toBytes("family"); 383 final byte[] q1 = Bytes.toBytes("q1"); 384 final byte[] v = Bytes.toBytes("value"); 385 int numKvs = 10; 386 387 MultiVersionConcurrencyControl.WriteEntry w = mvcc.begin(); 388 389 KeyValue kv; 390 KeyValue[] kvs = new KeyValue[numKvs]; 391 long totalCellSize = 0; 392 for (int i = 0; i < numKvs; i++) { 393 byte[] row = Bytes.toBytes(i); 394 kv = new KeyValue(row, f, q1, v); 395 kv.setSequenceId(w.getWriteNumber()); 396 memstore.add(kv, null); 397 kvs[i] = kv; 398 totalCellSize += Segment.getCellLength(kv); 399 } 400 mvcc.completeAndWait(w); 401 402 ThreadLocalServerSideScanMetrics.getBytesReadFromMemstoreAndReset(); 403 KeyValueScanner s = this.memstore.getScanners(mvcc.getReadPoint()).get(0); 404 assertScannerResults(s, kvs); 405 return totalCellSize; 406 } 407 408 @Test 409 public void testBytesReadFromMemstore() throws IOException { 410 ThreadLocalServerSideScanMetrics.setScanMetricsEnabled(true); 411 long totalCellSize = getBytesReadFromMemstore(); 412 assertEquals(totalCellSize, 413 ThreadLocalServerSideScanMetrics.getBytesReadFromMemstoreAndReset()); 414 } 415 416 @Test 417 public void testBytesReadFromMemstoreWithScanMetricsDisabled() throws IOException { 418 ThreadLocalServerSideScanMetrics.setScanMetricsEnabled(false); 419 getBytesReadFromMemstore(); 420 assertEquals(0, ThreadLocalServerSideScanMetrics.getBytesReadFromMemstoreAndReset()); 421 } 422 423 /** 424 * Regression test for HBASE-2616, HBASE-2670. When we insert a higher-memstoreTS version of a 425 * cell but with the same timestamp, we still need to provide consistent reads for the same 426 * scanner. 427 */ 428 @Test 429 public void testMemstoreEditsVisibilityWithSameKey() throws IOException { 430 final byte[] row = Bytes.toBytes(1); 431 final byte[] f = Bytes.toBytes("family"); 432 final byte[] q1 = Bytes.toBytes("q1"); 433 final byte[] q2 = Bytes.toBytes("q2"); 434 final byte[] v1 = Bytes.toBytes("value1"); 435 final byte[] v2 = Bytes.toBytes("value2"); 436 437 // INSERT 1: Write both columns val1 438 MultiVersionConcurrencyControl.WriteEntry w = mvcc.begin(); 439 440 KeyValue kv11 = new KeyValue(row, f, q1, v1); 441 kv11.setSequenceId(w.getWriteNumber()); 442 memstore.add(kv11, null); 443 444 KeyValue kv12 = new KeyValue(row, f, q2, v1); 445 kv12.setSequenceId(w.getWriteNumber()); 446 memstore.add(kv12, null); 447 mvcc.completeAndWait(w); 448 449 // BEFORE STARTING INSERT 2, SEE FIRST KVS 450 KeyValueScanner s = this.memstore.getScanners(mvcc.getReadPoint()).get(0); 451 assertScannerResults(s, new KeyValue[] { kv11, kv12 }); 452 453 // START INSERT 2: Write both columns val2 454 w = mvcc.begin(); 455 KeyValue kv21 = new KeyValue(row, f, q1, v2); 456 kv21.setSequenceId(w.getWriteNumber()); 457 memstore.add(kv21, null); 458 459 KeyValue kv22 = new KeyValue(row, f, q2, v2); 460 kv22.setSequenceId(w.getWriteNumber()); 461 memstore.add(kv22, null); 462 463 // BEFORE COMPLETING INSERT 2, SEE FIRST KVS 464 s = this.memstore.getScanners(mvcc.getReadPoint()).get(0); 465 assertScannerResults(s, new KeyValue[] { kv11, kv12 }); 466 467 // COMPLETE INSERT 2 468 mvcc.completeAndWait(w); 469 470 // NOW SHOULD SEE NEW KVS IN ADDITION TO OLD KVS. 471 // See HBASE-1485 for discussion about what we should do with 472 // the duplicate-TS inserts 473 s = this.memstore.getScanners(mvcc.getReadPoint()).get(0); 474 assertScannerResults(s, new KeyValue[] { kv21, kv11, kv22, kv12 }); 475 } 476 477 /** 478 * When we insert a higher-memstoreTS deletion of a cell but with the same timestamp, we still 479 * need to provide consistent reads for the same scanner. 480 */ 481 @Test 482 public void testMemstoreDeletesVisibilityWithSameKey() throws IOException { 483 final byte[] row = Bytes.toBytes(1); 484 final byte[] f = Bytes.toBytes("family"); 485 final byte[] q1 = Bytes.toBytes("q1"); 486 final byte[] q2 = Bytes.toBytes("q2"); 487 final byte[] v1 = Bytes.toBytes("value1"); 488 // INSERT 1: Write both columns val1 489 MultiVersionConcurrencyControl.WriteEntry w = mvcc.begin(); 490 491 KeyValue kv11 = new KeyValue(row, f, q1, v1); 492 kv11.setSequenceId(w.getWriteNumber()); 493 memstore.add(kv11, null); 494 495 KeyValue kv12 = new KeyValue(row, f, q2, v1); 496 kv12.setSequenceId(w.getWriteNumber()); 497 memstore.add(kv12, null); 498 mvcc.completeAndWait(w); 499 500 // BEFORE STARTING INSERT 2, SEE FIRST KVS 501 KeyValueScanner s = this.memstore.getScanners(mvcc.getReadPoint()).get(0); 502 assertScannerResults(s, new KeyValue[] { kv11, kv12 }); 503 504 // START DELETE: Insert delete for one of the columns 505 w = mvcc.begin(); 506 KeyValue kvDel = new KeyValue(row, f, q2, kv11.getTimestamp(), KeyValue.Type.DeleteColumn); 507 kvDel.setSequenceId(w.getWriteNumber()); 508 memstore.add(kvDel, null); 509 510 // BEFORE COMPLETING DELETE, SEE FIRST KVS 511 s = this.memstore.getScanners(mvcc.getReadPoint()).get(0); 512 assertScannerResults(s, new KeyValue[] { kv11, kv12 }); 513 514 // COMPLETE DELETE 515 mvcc.completeAndWait(w); 516 517 // NOW WE SHOULD SEE DELETE 518 s = this.memstore.getScanners(mvcc.getReadPoint()).get(0); 519 assertScannerResults(s, new KeyValue[] { kv11, kvDel, kv12 }); 520 } 521 522 private static class ReadOwnWritesTester extends Thread { 523 static final int NUM_TRIES = 1000; 524 525 final byte[] row; 526 527 final byte[] f = Bytes.toBytes("family"); 528 final byte[] q1 = Bytes.toBytes("q1"); 529 530 final MultiVersionConcurrencyControl mvcc; 531 final MemStore memstore; 532 533 AtomicReference<Throwable> caughtException; 534 535 public ReadOwnWritesTester(int id, MemStore memstore, MultiVersionConcurrencyControl mvcc, 536 AtomicReference<Throwable> caughtException) { 537 this.mvcc = mvcc; 538 this.memstore = memstore; 539 this.caughtException = caughtException; 540 row = Bytes.toBytes(id); 541 } 542 543 @Override 544 public void run() { 545 try { 546 internalRun(); 547 } catch (Throwable t) { 548 caughtException.compareAndSet(null, t); 549 } 550 } 551 552 private void internalRun() throws IOException { 553 for (long i = 0; i < NUM_TRIES && caughtException.get() == null; i++) { 554 MultiVersionConcurrencyControl.WriteEntry w = mvcc.begin(); 555 556 // Insert the sequence value (i) 557 byte[] v = Bytes.toBytes(i); 558 559 KeyValue kv = new KeyValue(row, f, q1, i, v); 560 kv.setSequenceId(w.getWriteNumber()); 561 memstore.add(kv, null); 562 mvcc.completeAndWait(w); 563 564 // Assert that we can read back 565 KeyValueScanner s = this.memstore.getScanners(mvcc.getReadPoint()).get(0); 566 s.seek(kv); 567 568 Cell ret = s.next(); 569 assertNotNull(ret, "Didnt find own write at all"); 570 assertEquals(kv.getTimestamp(), ret.getTimestamp(), "Didnt read own writes"); 571 } 572 } 573 } 574 575 @Test 576 public void testReadOwnWritesUnderConcurrency() throws Throwable { 577 int NUM_THREADS = 8; 578 579 ReadOwnWritesTester threads[] = new ReadOwnWritesTester[NUM_THREADS]; 580 AtomicReference<Throwable> caught = new AtomicReference<>(); 581 582 for (int i = 0; i < NUM_THREADS; i++) { 583 threads[i] = new ReadOwnWritesTester(i, memstore, mvcc, caught); 584 threads[i].start(); 585 } 586 587 for (int i = 0; i < NUM_THREADS; i++) { 588 threads[i].join(); 589 } 590 591 if (caught.get() != null) { 592 throw caught.get(); 593 } 594 } 595 596 /** 597 * Test memstore snapshots 598 */ 599 @Test 600 public void testSnapshotting() throws IOException { 601 final int snapshotCount = 5; 602 // Add some rows, run a snapshot. Do it a few times. 603 for (int i = 0; i < snapshotCount; i++) { 604 addRows(this.memstore); 605 runSnapshot(this.memstore); 606 assertEquals(0, this.memstore.getSnapshot().getCellsCount(), "History not being cleared"); 607 } 608 } 609 610 @Test 611 public void testMultipleVersionsSimple() throws Exception { 612 DefaultMemStore m = new DefaultMemStore(new Configuration(), CellComparatorImpl.COMPARATOR); 613 byte[] row = Bytes.toBytes("testRow"); 614 byte[] family = Bytes.toBytes("testFamily"); 615 byte[] qf = Bytes.toBytes("testQualifier"); 616 long[] stamps = { 1, 2, 3 }; 617 byte[][] values = { Bytes.toBytes("value0"), Bytes.toBytes("value1"), Bytes.toBytes("value2") }; 618 KeyValue key0 = new KeyValue(row, family, qf, stamps[0], values[0]); 619 KeyValue key1 = new KeyValue(row, family, qf, stamps[1], values[1]); 620 KeyValue key2 = new KeyValue(row, family, qf, stamps[2], values[2]); 621 622 m.add(key0, null); 623 m.add(key1, null); 624 m.add(key2, null); 625 626 assertEquals(3, m.getActive().getCellsCount(), 627 "Expected memstore to hold 3 values, actually has " + m.getActive().getCellsCount()); 628 } 629 630 ////////////////////////////////////////////////////////////////////////////// 631 // Get tests 632 ////////////////////////////////////////////////////////////////////////////// 633 634 /** 635 * Test getNextRow from memstore 636 */ 637 @Test 638 public void testGetNextRow() throws Exception { 639 addRows(this.memstore); 640 // Add more versions to make it a little more interesting. 641 Thread.sleep(1); 642 addRows(this.memstore); 643 Cell closestToEmpty = ((DefaultMemStore) this.memstore).getNextRow(KeyValue.LOWESTKEY); 644 assertEquals(0, CellComparatorImpl.COMPARATOR.compareRows(closestToEmpty, 645 new KeyValue(Bytes.toBytes(0), EnvironmentEdgeManager.currentTime()))); 646 for (int i = 0; i < ROW_COUNT; i++) { 647 Cell nr = ((DefaultMemStore) this.memstore) 648 .getNextRow(new KeyValue(Bytes.toBytes(i), EnvironmentEdgeManager.currentTime())); 649 if (i + 1 == ROW_COUNT) { 650 assertNull(nr); 651 } else { 652 assertEquals(0, CellComparatorImpl.COMPARATOR.compareRows(nr, 653 new KeyValue(Bytes.toBytes(i + 1), EnvironmentEdgeManager.currentTime()))); 654 } 655 } 656 // starting from each row, validate results should contain the starting row 657 Configuration conf = HBaseConfiguration.create(); 658 for (int startRowId = 0; startRowId < ROW_COUNT; startRowId++) { 659 ScanInfo scanInfo = 660 new ScanInfo(conf, FAMILY, 0, 1, Integer.MAX_VALUE, KeepDeletedCells.FALSE, 661 HConstants.DEFAULT_BLOCKSIZE, 0, this.memstore.getComparator(), false); 662 try (InternalScanner scanner = 663 new StoreScanner(new Scan().withStartRow(Bytes.toBytes(startRowId)), scanInfo, null, 664 memstore.getScanners(0))) { 665 List<Cell> results = new ArrayList<>(); 666 for (int i = 0; scanner.next(results); i++) { 667 int rowId = startRowId + i; 668 Cell left = results.get(0); 669 byte[] row1 = Bytes.toBytes(rowId); 670 assertEquals(0, CellComparatorImpl.COMPARATOR.compareRows(left, row1, 0, row1.length), 671 "Row name"); 672 assertEquals(QUALIFIER_COUNT, results.size(), "Count of columns"); 673 List<Cell> row = new ArrayList<>(); 674 for (Cell kv : results) { 675 row.add(kv); 676 } 677 isExpectedRowWithoutTimestamps(rowId, row); 678 // Clear out set. Otherwise row results accumulate. 679 results.clear(); 680 } 681 } 682 } 683 } 684 685 @Test 686 public void testGet_memstoreAndSnapShot() throws IOException { 687 byte[] row = Bytes.toBytes("testrow"); 688 byte[] fam = Bytes.toBytes("testfamily"); 689 byte[] qf1 = Bytes.toBytes("testqualifier1"); 690 byte[] qf2 = Bytes.toBytes("testqualifier2"); 691 byte[] qf3 = Bytes.toBytes("testqualifier3"); 692 byte[] qf4 = Bytes.toBytes("testqualifier4"); 693 byte[] qf5 = Bytes.toBytes("testqualifier5"); 694 byte[] val = Bytes.toBytes("testval"); 695 696 // Setting up memstore 697 memstore.add(new KeyValue(row, fam, qf1, val), null); 698 memstore.add(new KeyValue(row, fam, qf2, val), null); 699 memstore.add(new KeyValue(row, fam, qf3, val), null); 700 // Creating a snapshot 701 memstore.snapshot(); 702 assertEquals(3, memstore.getSnapshot().getCellsCount()); 703 // Adding value to "new" memstore 704 assertEquals(0, memstore.getActive().getCellsCount()); 705 memstore.add(new KeyValue(row, fam, qf4, val), null); 706 memstore.add(new KeyValue(row, fam, qf5, val), null); 707 assertEquals(2, memstore.getActive().getCellsCount()); 708 } 709 710 ////////////////////////////////////////////////////////////////////////////// 711 // Delete tests 712 ////////////////////////////////////////////////////////////////////////////// 713 @Test 714 public void testGetWithDelete() throws IOException { 715 byte[] row = Bytes.toBytes("testrow"); 716 byte[] fam = Bytes.toBytes("testfamily"); 717 byte[] qf1 = Bytes.toBytes("testqualifier"); 718 byte[] val = Bytes.toBytes("testval"); 719 720 long ts1 = System.nanoTime(); 721 KeyValue put1 = new KeyValue(row, fam, qf1, ts1, val); 722 long ts2 = ts1 + 1; 723 KeyValue put2 = new KeyValue(row, fam, qf1, ts2, val); 724 long ts3 = ts2 + 1; 725 KeyValue put3 = new KeyValue(row, fam, qf1, ts3, val); 726 memstore.add(put1, null); 727 memstore.add(put2, null); 728 memstore.add(put3, null); 729 730 assertEquals(3, memstore.getActive().getCellsCount()); 731 732 KeyValue del2 = new KeyValue(row, fam, qf1, ts2, KeyValue.Type.Delete, val); 733 memstore.add(del2, null); 734 735 List<Cell> expected = new ArrayList<>(); 736 expected.add(put3); 737 expected.add(del2); 738 expected.add(put2); 739 expected.add(put1); 740 741 assertEquals(4, memstore.getActive().getCellsCount()); 742 int i = 0; 743 for (Cell cell : memstore.getActive().getCellSet()) { 744 assertEquals(expected.get(i++), cell); 745 } 746 } 747 748 @Test 749 public void testGetWithDeleteColumn() throws IOException { 750 byte[] row = Bytes.toBytes("testrow"); 751 byte[] fam = Bytes.toBytes("testfamily"); 752 byte[] qf1 = Bytes.toBytes("testqualifier"); 753 byte[] val = Bytes.toBytes("testval"); 754 755 long ts1 = System.nanoTime(); 756 KeyValue put1 = new KeyValue(row, fam, qf1, ts1, val); 757 long ts2 = ts1 + 1; 758 KeyValue put2 = new KeyValue(row, fam, qf1, ts2, val); 759 long ts3 = ts2 + 1; 760 KeyValue put3 = new KeyValue(row, fam, qf1, ts3, val); 761 memstore.add(put1, null); 762 memstore.add(put2, null); 763 memstore.add(put3, null); 764 765 assertEquals(3, memstore.getActive().getCellsCount()); 766 767 KeyValue del2 = new KeyValue(row, fam, qf1, ts2, KeyValue.Type.DeleteColumn, val); 768 memstore.add(del2, null); 769 770 List<Cell> expected = new ArrayList<>(); 771 expected.add(put3); 772 expected.add(del2); 773 expected.add(put2); 774 expected.add(put1); 775 776 assertEquals(4, memstore.getActive().getCellsCount()); 777 int i = 0; 778 for (Cell cell : memstore.getActive().getCellSet()) { 779 assertEquals(expected.get(i++), cell); 780 } 781 } 782 783 @Test 784 public void testGetWithDeleteFamily() throws IOException { 785 byte[] row = Bytes.toBytes("testrow"); 786 byte[] fam = Bytes.toBytes("testfamily"); 787 byte[] qf1 = Bytes.toBytes("testqualifier1"); 788 byte[] qf2 = Bytes.toBytes("testqualifier2"); 789 byte[] qf3 = Bytes.toBytes("testqualifier3"); 790 byte[] val = Bytes.toBytes("testval"); 791 long ts = System.nanoTime(); 792 793 KeyValue put1 = new KeyValue(row, fam, qf1, ts, val); 794 KeyValue put2 = new KeyValue(row, fam, qf2, ts, val); 795 KeyValue put3 = new KeyValue(row, fam, qf3, ts, val); 796 KeyValue put4 = new KeyValue(row, fam, qf3, ts + 1, val); 797 798 memstore.add(put1, null); 799 memstore.add(put2, null); 800 memstore.add(put3, null); 801 memstore.add(put4, null); 802 803 KeyValue del = new KeyValue(row, fam, null, ts, KeyValue.Type.DeleteFamily, val); 804 memstore.add(del, null); 805 806 List<Cell> expected = new ArrayList<>(); 807 expected.add(del); 808 expected.add(put1); 809 expected.add(put2); 810 expected.add(put4); 811 expected.add(put3); 812 813 assertEquals(5, memstore.getActive().getCellsCount()); 814 int i = 0; 815 for (Cell cell : memstore.getActive().getCellSet()) { 816 assertEquals(expected.get(i++), cell); 817 } 818 } 819 820 @Test 821 public void testKeepDeleteInmemstore() { 822 byte[] row = Bytes.toBytes("testrow"); 823 byte[] fam = Bytes.toBytes("testfamily"); 824 byte[] qf = Bytes.toBytes("testqualifier"); 825 byte[] val = Bytes.toBytes("testval"); 826 long ts = System.nanoTime(); 827 memstore.add(new KeyValue(row, fam, qf, ts, val), null); 828 KeyValue delete = new KeyValue(row, fam, qf, ts, KeyValue.Type.Delete, val); 829 memstore.add(delete, null); 830 assertEquals(2, memstore.getActive().getCellsCount()); 831 assertEquals(delete, memstore.getActive().first()); 832 } 833 834 @Test 835 public void testRetainsDeleteVersion() throws IOException { 836 // add a put to memstore 837 memstore.add(KeyValueTestUtil.create("row1", "fam", "a", 100, "dont-care"), null); 838 839 // now process a specific delete: 840 KeyValue delete = 841 KeyValueTestUtil.create("row1", "fam", "a", 100, KeyValue.Type.Delete, "dont-care"); 842 memstore.add(delete, null); 843 844 assertEquals(2, memstore.getActive().getCellsCount()); 845 assertEquals(delete, memstore.getActive().first()); 846 } 847 848 @Test 849 public void testRetainsDeleteColumn() throws IOException { 850 // add a put to memstore 851 memstore.add(KeyValueTestUtil.create("row1", "fam", "a", 100, "dont-care"), null); 852 853 // now process a specific delete: 854 KeyValue delete = 855 KeyValueTestUtil.create("row1", "fam", "a", 100, KeyValue.Type.DeleteColumn, "dont-care"); 856 memstore.add(delete, null); 857 858 assertEquals(2, memstore.getActive().getCellsCount()); 859 assertEquals(delete, memstore.getActive().first()); 860 } 861 862 @Test 863 public void testRetainsDeleteFamily() throws IOException { 864 // add a put to memstore 865 memstore.add(KeyValueTestUtil.create("row1", "fam", "a", 100, "dont-care"), null); 866 867 // now process a specific delete: 868 KeyValue delete = 869 KeyValueTestUtil.create("row1", "fam", "a", 100, KeyValue.Type.DeleteFamily, "dont-care"); 870 memstore.add(delete, null); 871 872 assertEquals(2, memstore.getActive().getCellsCount()); 873 assertEquals(delete, memstore.getActive().first()); 874 } 875 876 ////////////////////////////////////////////////////////////////////////////// 877 // Helpers 878 ////////////////////////////////////////////////////////////////////////////// 879 protected static byte[] makeQualifier(final int i1, final int i2) { 880 return Bytes.toBytes(i1 + ";" + i2); 881 } 882 883 /** 884 * Add keyvalues with a fixed memstoreTs, and checks that memstore size is decreased as older 885 * keyvalues are deleted from the memstore. 886 */ 887 @Test 888 public void testUpsertMemstoreSize() throws Exception { 889 Configuration conf = HBaseConfiguration.create(); 890 memstore = new DefaultMemStore(conf, CellComparatorImpl.COMPARATOR); 891 MemStoreSize oldSize = memstore.size(); 892 893 List<ExtendedCell> l = new ArrayList<>(); 894 KeyValue kv1 = KeyValueTestUtil.create("r", "f", "q", 100, "v"); 895 KeyValue kv2 = KeyValueTestUtil.create("r", "f", "q", 101, "v"); 896 KeyValue kv3 = KeyValueTestUtil.create("r", "f", "q", 102, "v"); 897 898 kv1.setSequenceId(1); 899 kv2.setSequenceId(1); 900 kv3.setSequenceId(1); 901 l.add(kv1); 902 l.add(kv2); 903 l.add(kv3); 904 905 this.memstore.upsert(l, 2, null);// readpoint is 2 906 MemStoreSize newSize = this.memstore.size(); 907 assert (newSize.getDataSize() > oldSize.getDataSize()); 908 // The kv1 should be removed. 909 assert (memstore.getActive().getCellsCount() == 2); 910 911 KeyValue kv4 = KeyValueTestUtil.create("r", "f", "q", 104, "v"); 912 kv4.setSequenceId(1); 913 l.clear(); 914 l.add(kv4); 915 this.memstore.upsert(l, 3, null); 916 assertEquals(newSize, this.memstore.size()); 917 // The kv2 should be removed. 918 assert (memstore.getActive().getCellsCount() == 2); 919 // this.memstore = null; 920 } 921 922 //////////////////////////////////// 923 // Test for periodic memstore flushes 924 // based on time of oldest edit 925 //////////////////////////////////// 926 927 /** 928 * Tests that the timeOfOldestEdit is updated correctly for the various edit operations in 929 * memstore. 930 */ 931 @Test 932 public void testUpdateToTimeOfOldestEdit() throws Exception { 933 try { 934 EnvironmentEdgeForMemstoreTest edge = new EnvironmentEdgeForMemstoreTest(); 935 EnvironmentEdgeManager.injectEdge(edge); 936 DefaultMemStore memstore = new DefaultMemStore(); 937 long t = memstore.timeOfOldestEdit(); 938 assertEquals(Long.MAX_VALUE, t); 939 940 // test the case that the timeOfOldestEdit is updated after a KV add 941 memstore.add(KeyValueTestUtil.create("r", "f", "q", 100, "v"), null); 942 t = memstore.timeOfOldestEdit(); 943 assertEquals(1234, t); 944 // snapshot() will reset timeOfOldestEdit. The method will also assert the 945 // value is reset to Long.MAX_VALUE 946 t = runSnapshot(memstore); 947 948 // test the case that the timeOfOldestEdit is updated after a KV delete 949 memstore.add(KeyValueTestUtil.create("r", "f", "q", 100, KeyValue.Type.Delete, "v"), null); 950 t = memstore.timeOfOldestEdit(); 951 assertEquals(1234, t); 952 t = runSnapshot(memstore); 953 954 // test the case that the timeOfOldestEdit is updated after a KV upsert 955 List<ExtendedCell> l = new ArrayList<>(); 956 KeyValue kv1 = KeyValueTestUtil.create("r", "f", "q", 100, "v"); 957 kv1.setSequenceId(100); 958 l.add(kv1); 959 memstore.upsert(l, 1000, null); 960 t = memstore.timeOfOldestEdit(); 961 assertEquals(1234, t); 962 } finally { 963 EnvironmentEdgeManager.reset(); 964 } 965 } 966 967 /** 968 * Tests the HRegion.shouldFlush method - adds an edit in the memstore and checks that shouldFlush 969 * returns true, and another where it disables the periodic flush functionality and tests whether 970 * shouldFlush returns false. 971 */ 972 @Test 973 public void testShouldFlush() throws Exception { 974 Configuration conf = new Configuration(); 975 conf.setInt(HRegion.MEMSTORE_PERIODIC_FLUSH_INTERVAL, 1000); 976 checkShouldFlush(conf, true); 977 // test disable flush 978 conf.setInt(HRegion.MEMSTORE_PERIODIC_FLUSH_INTERVAL, 0); 979 checkShouldFlush(conf, false); 980 } 981 982 protected void checkShouldFlush(Configuration conf, boolean expected) throws Exception { 983 try { 984 EnvironmentEdgeForMemstoreTest edge = new EnvironmentEdgeForMemstoreTest(); 985 EnvironmentEdgeManager.injectEdge(edge); 986 HBaseTestingUtil hbaseUtility = new HBaseTestingUtil(conf); 987 String cf = "foo"; 988 HRegion region = 989 hbaseUtility.createTestRegion("foobar", ColumnFamilyDescriptorBuilder.of(cf)); 990 991 edge.setCurrentTimeMillis(1234); 992 Put p = new Put(Bytes.toBytes("r")); 993 p.add(KeyValueTestUtil.create("r", cf, "q", 100, "v")); 994 region.put(p); 995 edge.setCurrentTimeMillis(1234 + 100); 996 StringBuilder sb = new StringBuilder(); 997 assertFalse(region.shouldFlush(sb)); 998 edge.setCurrentTimeMillis(1234 + 10000); 999 assertEquals(expected, region.shouldFlush(sb)); 1000 } finally { 1001 EnvironmentEdgeManager.reset(); 1002 } 1003 } 1004 1005 @Test 1006 public void testShouldFlushMeta() throws Exception { 1007 // write an edit in the META and ensure the shouldFlush (that the periodic memstore 1008 // flusher invokes) returns true after SYSTEM_CACHE_FLUSH_INTERVAL (even though 1009 // the MEMSTORE_PERIODIC_FLUSH_INTERVAL is set to a higher value) 1010 Configuration conf = new Configuration(); 1011 conf.setInt(HRegion.MEMSTORE_PERIODIC_FLUSH_INTERVAL, HRegion.SYSTEM_CACHE_FLUSH_INTERVAL * 10); 1012 HBaseTestingUtil hbaseUtility = new HBaseTestingUtil(conf); 1013 Path testDir = hbaseUtility.getDataTestDir(); 1014 EnvironmentEdgeForMemstoreTest edge = new EnvironmentEdgeForMemstoreTest(); 1015 EnvironmentEdgeManager.injectEdge(edge); 1016 edge.setCurrentTimeMillis(1234); 1017 WALFactory wFactory = new WALFactory(conf, "1234"); 1018 TableDescriptors tds = new FSTableDescriptors(conf); 1019 FSTableDescriptors.tryUpdateMetaTableDescriptor(conf); 1020 HRegion meta = HRegion.createHRegion(RegionInfoBuilder.FIRST_META_REGIONINFO, testDir, conf, 1021 tds.get(TableName.META_TABLE_NAME), wFactory.getWAL(RegionInfoBuilder.FIRST_META_REGIONINFO)); 1022 TableDescriptor desc = TableDescriptorBuilder.newBuilder(TableName.valueOf(name)) 1023 .setColumnFamily(ColumnFamilyDescriptorBuilder.of("foo")).build(); 1024 RegionInfo hri = RegionInfoBuilder.newBuilder(desc.getTableName()) 1025 .setStartKey(Bytes.toBytes("row_0200")).setEndKey(Bytes.toBytes("row_0300")).build(); 1026 HRegion r = HRegion.createHRegion(hri, testDir, conf, desc, wFactory.getWAL(hri)); 1027 addRegionToMETA(meta, r); 1028 edge.setCurrentTimeMillis(1234 + 100); 1029 StringBuilder sb = new StringBuilder(); 1030 assertFalse(meta.shouldFlush(sb)); 1031 edge.setCurrentTimeMillis(edge.currentTime() + HRegion.SYSTEM_CACHE_FLUSH_INTERVAL + 1); 1032 assertTrue(meta.shouldFlush(sb)); 1033 } 1034 1035 /** 1036 * Inserts a new region's meta information into the passed <code>meta</code> region. 1037 * @param meta hbase:meta HRegion to be updated 1038 * @param r HRegion to add to <code>meta</code> 1039 */ 1040 private static void addRegionToMETA(final HRegion meta, final HRegion r) throws IOException { 1041 // The row key is the region name 1042 byte[] row = r.getRegionInfo().getRegionName(); 1043 final long now = EnvironmentEdgeManager.currentTime(); 1044 final List<Cell> cells = new ArrayList<>(2); 1045 cells.add(new KeyValue(row, HConstants.CATALOG_FAMILY, HConstants.REGIONINFO_QUALIFIER, now, 1046 RegionInfo.toByteArray(r.getRegionInfo()))); 1047 // Set into the root table the version of the meta table. 1048 cells.add(new KeyValue(row, HConstants.CATALOG_FAMILY, HConstants.META_VERSION_QUALIFIER, now, 1049 Bytes.toBytes(HConstants.META_VERSION))); 1050 NavigableMap<byte[], List<Cell>> familyMap = new TreeMap<>(Bytes.BYTES_COMPARATOR); 1051 familyMap.put(HConstants.CATALOG_FAMILY, cells); 1052 meta.put(new Put(row, HConstants.LATEST_TIMESTAMP, familyMap)); 1053 } 1054 1055 private class EnvironmentEdgeForMemstoreTest implements EnvironmentEdge { 1056 long t = 1234; 1057 1058 @Override 1059 public long currentTime() { 1060 return t; 1061 } 1062 1063 public void setCurrentTimeMillis(long t) { 1064 this.t = t; 1065 } 1066 } 1067 1068 /** 1069 * Adds {@link #ROW_COUNT} rows and {@link #QUALIFIER_COUNT} 1070 * @param hmc Instance to add rows to. 1071 * @return How many rows we added. 1072 */ 1073 protected int addRows(final AbstractMemStore hmc) { 1074 return addRows(hmc, HConstants.LATEST_TIMESTAMP); 1075 } 1076 1077 /** 1078 * Adds {@link #ROW_COUNT} rows and {@link #QUALIFIER_COUNT} 1079 * @param hmc Instance to add rows to. 1080 * @return How many rows we added. 1081 */ 1082 protected int addRows(final MemStore hmc, final long ts) { 1083 for (int i = 0; i < ROW_COUNT; i++) { 1084 long timestamp = 1085 ts == HConstants.LATEST_TIMESTAMP ? EnvironmentEdgeManager.currentTime() : ts; 1086 for (int ii = 0; ii < QUALIFIER_COUNT; ii++) { 1087 byte[] row = Bytes.toBytes(i); 1088 byte[] qf = makeQualifier(i, ii); 1089 hmc.add(new KeyValue(row, FAMILY, qf, timestamp, qf), null); 1090 } 1091 } 1092 return ROW_COUNT; 1093 } 1094 1095 private long runSnapshot(final AbstractMemStore hmc) throws UnexpectedStateException { 1096 // Save off old state. 1097 int oldHistorySize = hmc.getSnapshot().getCellsCount(); 1098 MemStoreSnapshot snapshot = hmc.snapshot(); 1099 // Make some assertions about what just happened. 1100 assertTrue(oldHistorySize < hmc.getSnapshot().getCellsCount(), 1101 "History size has not increased"); 1102 long t = memstore.timeOfOldestEdit(); 1103 assertEquals(Long.MAX_VALUE, t, "Time of oldest edit is not Long.MAX_VALUE"); 1104 hmc.clearSnapshot(snapshot.getId()); 1105 return t; 1106 } 1107 1108 private void isExpectedRowWithoutTimestamps(final int rowIndex, List<Cell> kvs) { 1109 int i = 0; 1110 for (Cell kv : kvs) { 1111 byte[] expectedColname = makeQualifier(rowIndex, i++); 1112 assertTrue(CellUtil.matchingQualifier(kv, expectedColname), "Column name"); 1113 // Value is column name as bytes. Usually result is 1114 // 100 bytes in size at least. This is the default size 1115 // for BytesWriteable. For comparison, convert bytes to 1116 // String and trim to remove trailing null bytes. 1117 assertTrue(CellUtil.matchingValue(kv, expectedColname), "Content"); 1118 } 1119 } 1120 1121 private static void addRows(int count, final MemStore mem) { 1122 long nanos = System.nanoTime(); 1123 for (int i = 0; i < count; i++) { 1124 if (i % 1000 == 0) { 1125 LOG.info("{} Took for 1k usec: {}", i, (System.nanoTime() - nanos) / 1000); 1126 nanos = System.nanoTime(); 1127 } 1128 1129 long timestamp = System.currentTimeMillis(); 1130 for (int ii = 0; ii < QUALIFIER_COUNT; ii++) { 1131 byte[] row = Bytes.toBytes(i); 1132 byte[] qf = makeQualifier(i, ii); 1133 mem.add(new KeyValue(row, FAMILY, qf, timestamp, qf), null); 1134 } 1135 } 1136 } 1137 1138 private static int doScan(MemStore ms, int iteration) throws IOException { 1139 long nanos = System.nanoTime(); 1140 KeyValueScanner s = ms.getScanners(0).get(0); 1141 s.seek(KeyValueUtil.createFirstOnRow(new byte[] {})); 1142 1143 LOG.info("Iteration {} create/seek took: {}", iteration, (System.nanoTime() - nanos) / 1000); 1144 int cnt = 0; 1145 while (s.next() != null) { 1146 ++cnt; 1147 } 1148 LOG.info("Iteration {} took usec: {} for: {}", iteration, (System.nanoTime() - nanos) / 1000, 1149 cnt); 1150 return cnt; 1151 } 1152 1153 protected void scanMemStore(MemStore ms, int expectedCount) throws IOException { 1154 long n1 = System.nanoTime(); 1155 addRows(SCAN_ROW_COUNT, ms); 1156 LOG.info("Took for insert: {}", (System.nanoTime() - n1) / 1000); 1157 1158 for (int i = 0; i < 50; i++) { 1159 int cnt = doScan(ms, i); 1160 assertEquals(expectedCount, cnt); 1161 } 1162 } 1163 1164 @Test 1165 public void testScan() throws IOException { 1166 scanMemStore(memstore, SCAN_ROW_COUNT * QUALIFIER_COUNT); 1167 } 1168}