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