1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.regionserver;
20
21 import java.io.IOException;
22 import java.lang.management.ManagementFactory;
23 import java.lang.management.MemoryMXBean;
24 import java.util.ArrayList;
25 import java.util.Arrays;
26 import java.util.List;
27 import java.util.concurrent.atomic.AtomicLong;
28 import java.util.concurrent.atomic.AtomicReference;
29
30 import junit.framework.TestCase;
31
32 import org.apache.commons.logging.Log;
33 import org.apache.commons.logging.LogFactory;
34 import org.apache.hadoop.conf.Configuration;
35 import org.apache.hadoop.fs.Path;
36 import org.apache.hadoop.hbase.Cell;
37 import org.apache.hadoop.hbase.CellUtil;
38 import org.apache.hadoop.hbase.HBaseConfiguration;
39 import org.apache.hadoop.hbase.HBaseTestingUtility;
40 import org.apache.hadoop.hbase.HColumnDescriptor;
41 import org.apache.hadoop.hbase.HConstants;
42 import org.apache.hadoop.hbase.HRegionInfo;
43 import org.apache.hadoop.hbase.HTableDescriptor;
44 import org.apache.hadoop.hbase.KeepDeletedCells;
45 import org.apache.hadoop.hbase.KeyValue;
46 import org.apache.hadoop.hbase.KeyValueTestUtil;
47 import org.apache.hadoop.hbase.KeyValueUtil;
48 import org.apache.hadoop.hbase.TableName;
49 import org.apache.hadoop.hbase.client.Scan;
50 import org.apache.hadoop.hbase.exceptions.UnexpectedStateException;
51 import org.apache.hadoop.hbase.testclassification.MediumTests;
52 import org.apache.hadoop.hbase.util.Bytes;
53 import org.apache.hadoop.hbase.util.EnvironmentEdge;
54 import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
55 import org.apache.hadoop.hbase.wal.WALFactory;
56 import org.junit.experimental.categories.Category;
57
58 import com.google.common.base.Joiner;
59 import com.google.common.collect.Iterables;
60 import com.google.common.collect.Lists;
61
62 import static org.mockito.Mockito.mock;
63 import static org.mockito.Mockito.when;
64
65
66 @Category(MediumTests.class)
67 public class TestDefaultMemStore extends TestCase {
68 private static final Log LOG = LogFactory.getLog(TestDefaultMemStore.class);
69 private DefaultMemStore memstore;
70 private static final int ROW_COUNT = 10;
71 private static final int QUALIFIER_COUNT = ROW_COUNT;
72 private static final byte [] FAMILY = Bytes.toBytes("column");
73 private MultiVersionConcurrencyControl mvcc;
74 private AtomicLong startSeqNum = new AtomicLong(0);
75
76 @Override
77 public void setUp() throws Exception {
78 super.setUp();
79 this.mvcc = new MultiVersionConcurrencyControl();
80 this.memstore = new DefaultMemStore();
81 }
82
83 public void testPutSameKey() {
84 byte [] bytes = Bytes.toBytes(getName());
85 KeyValue kv = new KeyValue(bytes, bytes, bytes, bytes);
86 this.memstore.add(kv);
87 byte [] other = Bytes.toBytes("somethingelse");
88 KeyValue samekey = new KeyValue(bytes, bytes, bytes, other);
89 this.memstore.add(samekey);
90 Cell found = this.memstore.activeSection.getCellSkipListSet().first();
91 assertEquals(1, this.memstore.activeSection.getCellSkipListSet().sizeForTests());
92 assertTrue(Bytes.toString(found.getValue()), CellUtil.matchingValue(samekey, found));
93 }
94
95 public void testPutSameCell() {
96 byte[] bytes = Bytes.toBytes(getName());
97 KeyValue kv = new KeyValue(bytes, bytes, bytes, bytes);
98 long sizeChangeForFirstCell = this.memstore.add(kv);
99 long sizeChangeForSecondCell = this.memstore.add(kv);
100
101 assertEquals(DefaultMemStore.heapSizeChange(kv, true), sizeChangeForFirstCell);
102 if (this.memstore.activeSection.getMemStoreLAB() != null) {
103
104 assertEquals(memstore.getCellLength(kv), sizeChangeForSecondCell);
105
106 if (this.memstore.activeSection.getMemStoreLAB() instanceof HeapMemStoreLAB) {
107 assertEquals(2 * memstore.getCellLength(kv),
108 ((HeapMemStoreLAB) this.memstore.activeSection.getMemStoreLAB())
109 .getCurrentChunk().getNextFreeOffset());
110 }
111 } else {
112
113 assertEquals(0, sizeChangeForSecondCell);
114 }
115 }
116
117
118
119
120
121 public void testScanAcrossSnapshot() throws IOException {
122 int rowCount = addRows(this.memstore);
123 List<KeyValueScanner> memstorescanners = this.memstore.getScanners(0);
124 Scan scan = new Scan();
125 List<Cell> result = new ArrayList<Cell>();
126 Configuration conf = HBaseConfiguration.create();
127 ScanInfo scanInfo =
128 new ScanInfo(conf, null, 0, 1, HConstants.LATEST_TIMESTAMP, KeepDeletedCells.FALSE, 0,
129 this.memstore.comparator);
130 ScanType scanType = ScanType.USER_SCAN;
131 StoreScanner s = new StoreScanner(scan, scanInfo, scanType, null, memstorescanners);
132 int count = 0;
133 try {
134 while (s.next(result)) {
135 LOG.info(result);
136 count++;
137
138 assertEquals(rowCount, result.size());
139 result.clear();
140 }
141 } finally {
142 s.close();
143 }
144 assertEquals(rowCount, count);
145 for (KeyValueScanner scanner : memstorescanners) {
146 scanner.close();
147 }
148
149 memstorescanners = this.memstore.getScanners(mvcc.getReadPoint());
150
151 s = new StoreScanner(scan, scanInfo, scanType, null, memstorescanners);
152 count = 0;
153 try {
154 while (s.next(result)) {
155 LOG.info(result);
156
157 assertTrue(CellUtil.matchingRow(result.get(0), Bytes.toBytes(count)));
158 count++;
159
160 assertEquals(rowCount, result.size());
161 if (count == 2) {
162 this.memstore.snapshot();
163 LOG.info("Snapshotted");
164 }
165 result.clear();
166 }
167 } finally {
168 s.close();
169 }
170 assertEquals(rowCount, count);
171 for (KeyValueScanner scanner : memstorescanners) {
172 scanner.close();
173 }
174 memstorescanners = this.memstore.getScanners(mvcc.getReadPoint());
175
176 long ts = System.currentTimeMillis();
177 s = new StoreScanner(scan, scanInfo, scanType, null, memstorescanners);
178 count = 0;
179 int snapshotIndex = 5;
180 try {
181 while (s.next(result)) {
182 LOG.info(result);
183
184 assertTrue(CellUtil.matchingRow(result.get(0), Bytes.toBytes(count)));
185
186 assertEquals("count=" + count + ", result=" + result, rowCount, result.size());
187 count++;
188 if (count == snapshotIndex) {
189 MemStoreSnapshot snapshot = this.memstore.snapshot();
190 this.memstore.clearSnapshot(snapshot.getId());
191
192 addRows(this.memstore, ts);
193 LOG.info("Snapshotted, cleared it and then added values (which wont be seen)");
194 }
195 result.clear();
196 }
197 } finally {
198 s.close();
199 }
200 assertEquals(rowCount, count);
201 }
202
203
204
205
206
207
208 public void testScanAcrossSnapshot2() throws IOException, CloneNotSupportedException {
209
210
211 final byte[] one = Bytes.toBytes(1);
212 final byte[] two = Bytes.toBytes(2);
213 final byte[] f = Bytes.toBytes("f");
214 final byte[] q = Bytes.toBytes("q");
215 final byte[] v = Bytes.toBytes(3);
216
217 final KeyValue kv1 = new KeyValue(one, f, q, v);
218 final KeyValue kv2 = new KeyValue(two, f, q, v);
219
220
221 this.memstore.add(kv1.clone());
222 this.memstore.add(kv2.clone());
223 verifyScanAcrossSnapshot2(kv1, kv2);
224
225
226 this.memstore.snapshot();
227 verifyScanAcrossSnapshot2(kv1, kv2);
228
229
230 this.memstore = new DefaultMemStore();
231 this.memstore.add(kv1.clone());
232 this.memstore.snapshot();
233 this.memstore.add(kv2.clone());
234 verifyScanAcrossSnapshot2(kv1, kv2);
235 }
236
237 private void verifyScanAcrossSnapshot2(KeyValue kv1, KeyValue kv2)
238 throws IOException {
239 List<KeyValueScanner> memstorescanners = this.memstore.getScanners(mvcc.getReadPoint());
240 assertEquals(1, memstorescanners.size());
241 final KeyValueScanner scanner = memstorescanners.get(0);
242 scanner.seek(KeyValueUtil.createFirstOnRow(HConstants.EMPTY_START_ROW));
243 assertEquals(kv1, scanner.next());
244 assertEquals(kv2, scanner.next());
245 assertNull(scanner.next());
246 }
247
248 private void assertScannerResults(KeyValueScanner scanner, KeyValue[] expected)
249 throws IOException {
250 scanner.seek(KeyValueUtil.createFirstOnRow(new byte[]{}));
251 List<Cell> returned = Lists.newArrayList();
252
253 while (true) {
254 Cell next = scanner.next();
255 if (next == null) break;
256 returned.add(next);
257 }
258
259 assertTrue(
260 "Got:\n" + Joiner.on("\n").join(returned) +
261 "\nExpected:\n" + Joiner.on("\n").join(expected),
262 Iterables.elementsEqual(Arrays.asList(expected), returned));
263 assertNull(scanner.peek());
264 }
265
266 public void testMemstoreConcurrentControl() throws IOException {
267 final byte[] row = Bytes.toBytes(1);
268 final byte[] f = Bytes.toBytes("family");
269 final byte[] q1 = Bytes.toBytes("q1");
270 final byte[] q2 = Bytes.toBytes("q2");
271 final byte[] v = Bytes.toBytes("value");
272
273 MultiVersionConcurrencyControl.WriteEntry w =
274 mvcc.begin();
275
276 KeyValue kv1 = new KeyValue(row, f, q1, v);
277 kv1.setSequenceId(w.getWriteNumber());
278 memstore.add(kv1);
279
280 assertTrue(this.memstore.getScanners(mvcc.getReadPoint()) == null);
281
282 mvcc.completeAndWait(w);
283
284 KeyValueScanner s = this.memstore.getScanners(mvcc.getReadPoint()).get(0);
285 assertScannerResults(s, new KeyValue[]{kv1});
286
287 w = mvcc.begin();
288 KeyValue kv2 = new KeyValue(row, f, q2, v);
289 kv2.setSequenceId(w.getWriteNumber());
290 memstore.add(kv2);
291
292 s = this.memstore.getScanners(mvcc.getReadPoint()).get(0);
293 assertScannerResults(s, new KeyValue[]{kv1});
294
295 mvcc.completeAndWait(w);
296
297 s = this.memstore.getScanners(mvcc.getReadPoint()).get(0);
298 assertScannerResults(s, new KeyValue[]{kv1, kv2});
299 }
300
301
302
303
304
305
306
307 public void testMemstoreEditsVisibilityWithSameKey() throws IOException {
308 final byte[] row = Bytes.toBytes(1);
309 final byte[] f = Bytes.toBytes("family");
310 final byte[] q1 = Bytes.toBytes("q1");
311 final byte[] q2 = Bytes.toBytes("q2");
312 final byte[] v1 = Bytes.toBytes("value1");
313 final byte[] v2 = Bytes.toBytes("value2");
314
315
316 MultiVersionConcurrencyControl.WriteEntry w =
317 mvcc.begin();
318
319 KeyValue kv11 = new KeyValue(row, f, q1, v1);
320 kv11.setSequenceId(w.getWriteNumber());
321 memstore.add(kv11);
322
323 KeyValue kv12 = new KeyValue(row, f, q2, v1);
324 kv12.setSequenceId(w.getWriteNumber());
325 memstore.add(kv12);
326 mvcc.completeAndWait(w);
327
328
329 KeyValueScanner s = this.memstore.getScanners(mvcc.getReadPoint()).get(0);
330 assertScannerResults(s, new KeyValue[]{kv11, kv12});
331
332
333 w = mvcc.begin();
334 KeyValue kv21 = new KeyValue(row, f, q1, v2);
335 kv21.setSequenceId(w.getWriteNumber());
336 memstore.add(kv21);
337
338 KeyValue kv22 = new KeyValue(row, f, q2, v2);
339 kv22.setSequenceId(w.getWriteNumber());
340 memstore.add(kv22);
341
342
343 s = this.memstore.getScanners(mvcc.getReadPoint()).get(0);
344 assertScannerResults(s, new KeyValue[]{kv11, kv12});
345
346
347 mvcc.completeAndWait(w);
348
349
350
351
352 s = this.memstore.getScanners(mvcc.getReadPoint()).get(0);
353 assertScannerResults(s, new KeyValue[]{kv21, kv11, kv22, kv12});
354 }
355
356
357
358
359
360
361 public void testMemstoreDeletesVisibilityWithSameKey() throws IOException {
362 final byte[] row = Bytes.toBytes(1);
363 final byte[] f = Bytes.toBytes("family");
364 final byte[] q1 = Bytes.toBytes("q1");
365 final byte[] q2 = Bytes.toBytes("q2");
366 final byte[] v1 = Bytes.toBytes("value1");
367
368 MultiVersionConcurrencyControl.WriteEntry w =
369 mvcc.begin();
370
371 KeyValue kv11 = new KeyValue(row, f, q1, v1);
372 kv11.setSequenceId(w.getWriteNumber());
373 memstore.add(kv11);
374
375 KeyValue kv12 = new KeyValue(row, f, q2, v1);
376 kv12.setSequenceId(w.getWriteNumber());
377 memstore.add(kv12);
378 mvcc.completeAndWait(w);
379
380
381 KeyValueScanner s = this.memstore.getScanners(mvcc.getReadPoint()).get(0);
382 assertScannerResults(s, new KeyValue[]{kv11, kv12});
383
384
385 w = mvcc.begin();
386 KeyValue kvDel = new KeyValue(row, f, q2, kv11.getTimestamp(),
387 KeyValue.Type.DeleteColumn);
388 kvDel.setSequenceId(w.getWriteNumber());
389 memstore.add(kvDel);
390
391
392 s = this.memstore.getScanners(mvcc.getReadPoint()).get(0);
393 assertScannerResults(s, new KeyValue[]{kv11, kv12});
394
395
396 mvcc.completeAndWait(w);
397
398
399 s = this.memstore.getScanners(mvcc.getReadPoint()).get(0);
400 assertScannerResults(s, new KeyValue[]{kv11, kvDel, kv12});
401 }
402
403
404 private static class ReadOwnWritesTester extends Thread {
405 static final int NUM_TRIES = 1000;
406
407 final byte[] row;
408
409 final byte[] f = Bytes.toBytes("family");
410 final byte[] q1 = Bytes.toBytes("q1");
411
412 final MultiVersionConcurrencyControl mvcc;
413 final MemStore memstore;
414 final AtomicLong startSeqNum;
415
416 AtomicReference<Throwable> caughtException;
417
418
419 public ReadOwnWritesTester(int id,
420 MemStore memstore,
421 MultiVersionConcurrencyControl mvcc,
422 AtomicReference<Throwable> caughtException,
423 AtomicLong startSeqNum)
424 {
425 this.mvcc = mvcc;
426 this.memstore = memstore;
427 this.caughtException = caughtException;
428 row = Bytes.toBytes(id);
429 this.startSeqNum = startSeqNum;
430 }
431
432 public void run() {
433 try {
434 internalRun();
435 } catch (Throwable t) {
436 caughtException.compareAndSet(null, t);
437 }
438 }
439
440 private void internalRun() throws IOException {
441 for (long i = 0; i < NUM_TRIES && caughtException.get() == null; i++) {
442 MultiVersionConcurrencyControl.WriteEntry w =
443 mvcc.begin();
444
445
446 byte[] v = Bytes.toBytes(i);
447
448 KeyValue kv = new KeyValue(row, f, q1, i, v);
449 kv.setSequenceId(w.getWriteNumber());
450 memstore.add(kv);
451 mvcc.completeAndWait(w);
452
453
454 KeyValueScanner s = this.memstore.getScanners(mvcc.getReadPoint()).get(0);
455 s.seek(kv);
456
457 Cell ret = s.next();
458 assertNotNull("Didnt find own write at all", ret);
459 assertEquals("Didnt read own writes",
460 kv.getTimestamp(), ret.getTimestamp());
461 }
462 }
463 }
464
465 public void testReadOwnWritesUnderConcurrency() throws Throwable {
466
467 int NUM_THREADS = 8;
468
469 ReadOwnWritesTester threads[] = new ReadOwnWritesTester[NUM_THREADS];
470 AtomicReference<Throwable> caught = new AtomicReference<Throwable>();
471
472 for (int i = 0; i < NUM_THREADS; i++) {
473 threads[i] = new ReadOwnWritesTester(i, memstore, mvcc, caught, this.startSeqNum);
474 threads[i].start();
475 }
476
477 for (int i = 0; i < NUM_THREADS; i++) {
478 threads[i].join();
479 }
480
481 if (caught.get() != null) {
482 throw caught.get();
483 }
484 }
485
486
487
488
489
490 public void testSnapshotting() throws IOException {
491 final int snapshotCount = 5;
492
493 for (int i = 0; i < snapshotCount; i++) {
494 addRows(this.memstore);
495 runSnapshot(this.memstore);
496 assertEquals("History not being cleared", 0,
497 this.memstore.snapshotSection.getCellSkipListSet().sizeForTests());
498 }
499 }
500
501 public void testMultipleVersionsSimple() throws Exception {
502 DefaultMemStore m = new DefaultMemStore(new Configuration(), KeyValue.COMPARATOR);
503 byte [] row = Bytes.toBytes("testRow");
504 byte [] family = Bytes.toBytes("testFamily");
505 byte [] qf = Bytes.toBytes("testQualifier");
506 long [] stamps = {1,2,3};
507 byte [][] values = {Bytes.toBytes("value0"), Bytes.toBytes("value1"),
508 Bytes.toBytes("value2")};
509 KeyValue key0 = new KeyValue(row, family, qf, stamps[0], values[0]);
510 KeyValue key1 = new KeyValue(row, family, qf, stamps[1], values[1]);
511 KeyValue key2 = new KeyValue(row, family, qf, stamps[2], values[2]);
512
513 m.add(key0);
514 m.add(key1);
515 m.add(key2);
516
517 assertTrue("Expected memstore to hold 3 values, actually has " +
518 m.activeSection.getCellSkipListSet().sizeForTests(),
519 m.activeSection.getCellSkipListSet().sizeForTests() == 3);
520 }
521
522
523
524
525
526
527
528
529 public void testGetNextRow() throws Exception {
530 addRows(this.memstore);
531
532 Thread.sleep(1);
533 addRows(this.memstore);
534 Cell closestToEmpty = this.memstore.getNextRow(KeyValue.LOWESTKEY);
535 assertTrue(KeyValue.COMPARATOR.compareRows(closestToEmpty,
536 new KeyValue(Bytes.toBytes(0), System.currentTimeMillis())) == 0);
537 for (int i = 0; i < ROW_COUNT; i++) {
538 Cell nr = this.memstore.getNextRow(new KeyValue(Bytes.toBytes(i),
539 System.currentTimeMillis()));
540 if (i + 1 == ROW_COUNT) {
541 assertEquals(nr, null);
542 } else {
543 assertTrue(KeyValue.COMPARATOR.compareRows(nr,
544 new KeyValue(Bytes.toBytes(i + 1), System.currentTimeMillis())) == 0);
545 }
546 }
547
548 Configuration conf = HBaseConfiguration.create();
549 for (int startRowId = 0; startRowId < ROW_COUNT; startRowId++) {
550 ScanInfo scanInfo = new ScanInfo(conf, FAMILY, 0, 1, Integer.MAX_VALUE,
551 KeepDeletedCells.FALSE, 0, this.memstore.comparator);
552 ScanType scanType = ScanType.USER_SCAN;
553 InternalScanner scanner = new StoreScanner(new Scan(
554 Bytes.toBytes(startRowId)), scanInfo, scanType, null,
555 memstore.getScanners(0));
556 List<Cell> results = new ArrayList<Cell>();
557 for (int i = 0; scanner.next(results); i++) {
558 int rowId = startRowId + i;
559 Cell left = results.get(0);
560 byte[] row1 = Bytes.toBytes(rowId);
561 assertTrue(
562 "Row name",
563 KeyValue.COMPARATOR.compareRows(left.getRowArray(), left.getRowOffset(),
564 (int) left.getRowLength(), row1, 0, row1.length) == 0);
565 assertEquals("Count of columns", QUALIFIER_COUNT, results.size());
566 List<Cell> row = new ArrayList<Cell>();
567 for (Cell kv : results) {
568 row.add(kv);
569 }
570 isExpectedRowWithoutTimestamps(rowId, row);
571
572 results.clear();
573 }
574 }
575 }
576
577 public void testGet_memstoreAndSnapShot() throws IOException {
578 byte [] row = Bytes.toBytes("testrow");
579 byte [] fam = Bytes.toBytes("testfamily");
580 byte [] qf1 = Bytes.toBytes("testqualifier1");
581 byte [] qf2 = Bytes.toBytes("testqualifier2");
582 byte [] qf3 = Bytes.toBytes("testqualifier3");
583 byte [] qf4 = Bytes.toBytes("testqualifier4");
584 byte [] qf5 = Bytes.toBytes("testqualifier5");
585 byte [] val = Bytes.toBytes("testval");
586
587
588 memstore.add(new KeyValue(row, fam ,qf1, val));
589 memstore.add(new KeyValue(row, fam ,qf2, val));
590 memstore.add(new KeyValue(row, fam ,qf3, val));
591
592 memstore.snapshot();
593 assertEquals(3, memstore.snapshotSection.getCellSkipListSet().sizeForTests());
594
595 assertEquals(0, memstore.activeSection.getCellSkipListSet().sizeForTests());
596 memstore.add(new KeyValue(row, fam ,qf4, val));
597 memstore.add(new KeyValue(row, fam ,qf5, val));
598 assertEquals(2, memstore.activeSection.getCellSkipListSet().sizeForTests());
599 }
600
601
602
603
604 public void testGetWithDelete() throws IOException {
605 byte [] row = Bytes.toBytes("testrow");
606 byte [] fam = Bytes.toBytes("testfamily");
607 byte [] qf1 = Bytes.toBytes("testqualifier");
608 byte [] val = Bytes.toBytes("testval");
609
610 long ts1 = System.nanoTime();
611 KeyValue put1 = new KeyValue(row, fam, qf1, ts1, val);
612 long ts2 = ts1 + 1;
613 KeyValue put2 = new KeyValue(row, fam, qf1, ts2, val);
614 long ts3 = ts2 +1;
615 KeyValue put3 = new KeyValue(row, fam, qf1, ts3, val);
616 memstore.add(put1);
617 memstore.add(put2);
618 memstore.add(put3);
619
620 assertEquals(3, memstore.activeSection.getCellSkipListSet().sizeForTests());
621
622 KeyValue del2 = new KeyValue(row, fam, qf1, ts2, KeyValue.Type.Delete, val);
623 memstore.delete(del2);
624
625 List<Cell> expected = new ArrayList<Cell>();
626 expected.add(put3);
627 expected.add(del2);
628 expected.add(put2);
629 expected.add(put1);
630
631 assertEquals(4, memstore.activeSection.getCellSkipListSet().sizeForTests());
632 int i = 0;
633 for(Cell cell : memstore.activeSection.getCellSkipListSet()) {
634 assertEquals(expected.get(i++), cell);
635 }
636 }
637
638 public void testGetWithDeleteColumn() throws IOException {
639 byte [] row = Bytes.toBytes("testrow");
640 byte [] fam = Bytes.toBytes("testfamily");
641 byte [] qf1 = Bytes.toBytes("testqualifier");
642 byte [] val = Bytes.toBytes("testval");
643
644 long ts1 = System.nanoTime();
645 KeyValue put1 = new KeyValue(row, fam, qf1, ts1, val);
646 long ts2 = ts1 + 1;
647 KeyValue put2 = new KeyValue(row, fam, qf1, ts2, val);
648 long ts3 = ts2 +1;
649 KeyValue put3 = new KeyValue(row, fam, qf1, ts3, val);
650 memstore.add(put1);
651 memstore.add(put2);
652 memstore.add(put3);
653
654 assertEquals(3, memstore.activeSection.getCellSkipListSet().sizeForTests());
655
656 KeyValue del2 =
657 new KeyValue(row, fam, qf1, ts2, KeyValue.Type.DeleteColumn, val);
658 memstore.delete(del2);
659
660 List<Cell> expected = new ArrayList<Cell>();
661 expected.add(put3);
662 expected.add(del2);
663 expected.add(put2);
664 expected.add(put1);
665
666 assertEquals(4, memstore.activeSection.getCellSkipListSet().sizeForTests());
667 int i = 0;
668 for (Cell cell: memstore.activeSection.getCellSkipListSet()) {
669 assertEquals(expected.get(i++), cell);
670 }
671 }
672
673 public void testGetWithDeleteFamily() throws IOException {
674 byte [] row = Bytes.toBytes("testrow");
675 byte [] fam = Bytes.toBytes("testfamily");
676 byte [] qf1 = Bytes.toBytes("testqualifier1");
677 byte [] qf2 = Bytes.toBytes("testqualifier2");
678 byte [] qf3 = Bytes.toBytes("testqualifier3");
679 byte [] val = Bytes.toBytes("testval");
680 long ts = System.nanoTime();
681
682 KeyValue put1 = new KeyValue(row, fam, qf1, ts, val);
683 KeyValue put2 = new KeyValue(row, fam, qf2, ts, val);
684 KeyValue put3 = new KeyValue(row, fam, qf3, ts, val);
685 KeyValue put4 = new KeyValue(row, fam, qf3, ts+1, val);
686
687 memstore.add(put1);
688 memstore.add(put2);
689 memstore.add(put3);
690 memstore.add(put4);
691
692 KeyValue del =
693 new KeyValue(row, fam, null, ts, KeyValue.Type.DeleteFamily, val);
694 memstore.delete(del);
695
696 List<Cell> expected = new ArrayList<Cell>();
697 expected.add(del);
698 expected.add(put1);
699 expected.add(put2);
700 expected.add(put4);
701 expected.add(put3);
702
703 assertEquals(5, memstore.activeSection.getCellSkipListSet().sizeForTests());
704 int i = 0;
705 for (Cell cell: memstore.activeSection.getCellSkipListSet()) {
706 assertEquals(expected.get(i++), cell);
707 }
708 }
709
710 public void testKeepDeleteInmemstore() {
711 byte [] row = Bytes.toBytes("testrow");
712 byte [] fam = Bytes.toBytes("testfamily");
713 byte [] qf = Bytes.toBytes("testqualifier");
714 byte [] val = Bytes.toBytes("testval");
715 long ts = System.nanoTime();
716 memstore.add(new KeyValue(row, fam, qf, ts, val));
717 KeyValue delete = new KeyValue(row, fam, qf, ts, KeyValue.Type.Delete, val);
718 memstore.delete(delete);
719 assertEquals(2, memstore.activeSection.getCellSkipListSet().sizeForTests());
720 assertEquals(delete, memstore.activeSection.getCellSkipListSet().first());
721 }
722
723 public void testRetainsDeleteVersion() throws IOException {
724
725 memstore.add(KeyValueTestUtil.create("row1", "fam", "a", 100, "dont-care"));
726
727
728 KeyValue delete = KeyValueTestUtil.create(
729 "row1", "fam", "a", 100, KeyValue.Type.Delete, "dont-care");
730 memstore.delete(delete);
731
732 assertEquals(2, memstore.activeSection.getCellSkipListSet().sizeForTests());
733 assertEquals(delete, memstore.activeSection.getCellSkipListSet().first());
734 }
735 public void testRetainsDeleteColumn() throws IOException {
736
737 memstore.add(KeyValueTestUtil.create("row1", "fam", "a", 100, "dont-care"));
738
739
740 KeyValue delete = KeyValueTestUtil.create("row1", "fam", "a", 100,
741 KeyValue.Type.DeleteColumn, "dont-care");
742 memstore.delete(delete);
743
744 assertEquals(2, memstore.activeSection.getCellSkipListSet().sizeForTests());
745 assertEquals(delete, memstore.activeSection.getCellSkipListSet().first());
746 }
747
748 public void testRetainsDeleteFamily() throws IOException {
749
750 memstore.add(KeyValueTestUtil.create("row1", "fam", "a", 100, "dont-care"));
751
752
753 KeyValue delete = KeyValueTestUtil.create("row1", "fam", "a", 100,
754 KeyValue.Type.DeleteFamily, "dont-care");
755 memstore.delete(delete);
756
757 assertEquals(2, memstore.activeSection.getCellSkipListSet().sizeForTests());
758 assertEquals(delete, memstore.activeSection.getCellSkipListSet().first());
759 }
760
761
762
763
764
765
766
767
768 public void testMultipleTimestamps() throws Exception {
769 long[] timestamps = new long[] {20,10,5,1};
770 Scan scan = new Scan();
771
772 for (long timestamp: timestamps)
773 addRows(memstore,timestamp);
774
775 byte[] fam = Bytes.toBytes("fam");
776 HColumnDescriptor hcd = mock(HColumnDescriptor.class);
777 when(hcd.getName()).thenReturn(fam);
778 Store store = mock(Store.class);
779 when(store.getFamily()).thenReturn(hcd);
780 scan.setColumnFamilyTimeRange(fam, 0, 2);
781 assertTrue(memstore.shouldSeek(scan, store, Long.MIN_VALUE));
782
783 scan.setColumnFamilyTimeRange(fam, 20, 82);
784 assertTrue(memstore.shouldSeek(scan, store, Long.MIN_VALUE));
785
786 scan.setColumnFamilyTimeRange(fam, 10, 20);
787 assertTrue(memstore.shouldSeek(scan, store, Long.MIN_VALUE));
788
789 scan.setColumnFamilyTimeRange(fam, 8, 12);
790 assertTrue(memstore.shouldSeek(scan, store, Long.MIN_VALUE));
791
792 scan.setColumnFamilyTimeRange(fam, 28, 42);
793 assertTrue(!memstore.shouldSeek(scan, store, Long.MIN_VALUE));
794 }
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813 public void testUpsertMSLAB() throws Exception {
814 Configuration conf = HBaseConfiguration.create();
815 conf.setBoolean(DefaultMemStore.USEMSLAB_KEY, true);
816 memstore = new DefaultMemStore(conf, KeyValue.COMPARATOR);
817
818 int ROW_SIZE = 2048;
819 byte[] qualifier = new byte[ROW_SIZE - 4];
820
821 MemoryMXBean bean = ManagementFactory.getMemoryMXBean();
822 for (int i = 0; i < 3; i++) { System.gc(); }
823 long usageBefore = bean.getHeapMemoryUsage().getUsed();
824
825 long size = 0;
826 long ts=0;
827
828 for (int newValue = 0; newValue < 1000; newValue++) {
829 for (int row = newValue; row < newValue + 1000; row++) {
830 byte[] rowBytes = Bytes.toBytes(row);
831 size += memstore.updateColumnValue(rowBytes, FAMILY, qualifier, newValue, ++ts);
832 }
833 }
834 System.out.println("Wrote " + ts + " vals");
835 for (int i = 0; i < 3; i++) { System.gc(); }
836 long usageAfter = bean.getHeapMemoryUsage().getUsed();
837 System.out.println("Memory used: " + (usageAfter - usageBefore)
838 + " (heapsize: " + memstore.heapSize() +
839 " size: " + size + ")");
840 }
841
842
843
844
845 private static byte [] makeQualifier(final int i1, final int i2){
846 return Bytes.toBytes(Integer.toString(i1) + ";" +
847 Integer.toString(i2));
848 }
849
850
851
852
853
854
855 public void testUpsertMemstoreSize() throws Exception {
856 Configuration conf = HBaseConfiguration.create();
857 memstore = new DefaultMemStore(conf, KeyValue.COMPARATOR);
858 long oldSize = memstore.activeSection.getHeapSize().get();
859
860 List<Cell> l = new ArrayList<Cell>();
861 KeyValue kv1 = KeyValueTestUtil.create("r", "f", "q", 100, "v");
862 KeyValue kv2 = KeyValueTestUtil.create("r", "f", "q", 101, "v");
863 KeyValue kv3 = KeyValueTestUtil.create("r", "f", "q", 102, "v");
864
865 kv1.setSequenceId(1); kv2.setSequenceId(1);kv3.setSequenceId(1);
866 l.add(kv1); l.add(kv2); l.add(kv3);
867
868 this.memstore.upsert(l, 2, null);
869 long newSize = this.memstore.activeSection.getHeapSize().get();
870 assert(newSize > oldSize);
871
872 assert(memstore.activeSection.getCellSkipListSet().sizeForTests() == 2);
873
874 KeyValue kv4 = KeyValueTestUtil.create("r", "f", "q", 104, "v");
875 kv4.setSequenceId(1);
876 l.clear(); l.add(kv4);
877 this.memstore.upsert(l, 3, null);
878 assertEquals(newSize, this.memstore.activeSection.getHeapSize().get());
879
880 assert(memstore.activeSection.getCellSkipListSet().sizeForTests() == 2);
881
882 }
883
884
885
886
887
888
889
890
891
892
893
894 public void testUpdateToTimeOfOldestEdit() throws Exception {
895 try {
896 EnvironmentEdgeForMemstoreTest edge = new EnvironmentEdgeForMemstoreTest();
897 EnvironmentEdgeManager.injectEdge(edge);
898 DefaultMemStore memstore = new DefaultMemStore();
899 long t = memstore.timeOfOldestEdit();
900 assertEquals(t, Long.MAX_VALUE);
901
902
903 memstore.add(KeyValueTestUtil.create("r", "f", "q", 100, "v"));
904 t = memstore.timeOfOldestEdit();
905 assertTrue(t == 1234);
906
907
908 t = runSnapshot(memstore);
909
910
911 memstore.delete(KeyValueTestUtil.create("r", "f", "q", 100, "v"));
912 t = memstore.timeOfOldestEdit();
913 assertTrue(t == 1234);
914 t = runSnapshot(memstore);
915
916
917 List<Cell> l = new ArrayList<Cell>();
918 KeyValue kv1 = KeyValueTestUtil.create("r", "f", "q", 100, "v");
919 kv1.setSequenceId(100);
920 l.add(kv1);
921 memstore.upsert(l, 1000, null);
922 t = memstore.timeOfOldestEdit();
923 assertTrue(t == 1234);
924 } finally {
925 EnvironmentEdgeManager.reset();
926 }
927 }
928
929
930
931
932
933
934
935
936 public void testShouldFlush() throws Exception {
937 Configuration conf = new Configuration();
938 conf.setInt(HRegion.MEMSTORE_PERIODIC_FLUSH_INTERVAL, 1000);
939 checkShouldFlush(conf, true);
940
941 conf.setInt(HRegion.MEMSTORE_PERIODIC_FLUSH_INTERVAL, 0);
942 checkShouldFlush(conf, false);
943 }
944
945 private void checkShouldFlush(Configuration conf, boolean expected) throws Exception {
946 try {
947 EnvironmentEdgeForMemstoreTest edge = new EnvironmentEdgeForMemstoreTest();
948 EnvironmentEdgeManager.injectEdge(edge);
949 HBaseTestingUtility hbaseUtility = HBaseTestingUtility.createLocalHTU(conf);
950 HRegion region = hbaseUtility.createTestRegion("foobar", new HColumnDescriptor("foo"));
951
952 List<Store> stores = region.getStores();
953 assertTrue(stores.size() == 1);
954
955 Store s = stores.iterator().next();
956 edge.setCurrentTimeMillis(1234);
957 s.add(KeyValueTestUtil.create("r", "f", "q", 100, "v"));
958 edge.setCurrentTimeMillis(1234 + 100);
959 StringBuffer sb = new StringBuffer();
960 assertTrue(region.shouldFlush(sb) == false);
961 edge.setCurrentTimeMillis(1234 + 10000);
962 assertTrue(region.shouldFlush(sb) == expected);
963 } finally {
964 EnvironmentEdgeManager.reset();
965 }
966 }
967
968 public void testShouldFlushMeta() throws Exception {
969
970
971
972 Configuration conf = new Configuration();
973 conf.setInt(HRegion.MEMSTORE_PERIODIC_FLUSH_INTERVAL, HRegion.SYSTEM_CACHE_FLUSH_INTERVAL * 10);
974 HBaseTestingUtility hbaseUtility = HBaseTestingUtility.createLocalHTU(conf);
975 Path testDir = hbaseUtility.getDataTestDir();
976 EnvironmentEdgeForMemstoreTest edge = new EnvironmentEdgeForMemstoreTest();
977 EnvironmentEdgeManager.injectEdge(edge);
978 edge.setCurrentTimeMillis(1234);
979 WALFactory wFactory = new WALFactory(conf, null, "1234");
980 HRegion meta = HRegion.createHRegion(HRegionInfo.FIRST_META_REGIONINFO, testDir,
981 conf, HTableDescriptor.metaTableDescriptor(conf),
982 wFactory.getMetaWAL(HRegionInfo.FIRST_META_REGIONINFO.
983 getEncodedNameAsBytes()));
984 HRegionInfo hri = new HRegionInfo(TableName.valueOf("testShouldFlushMeta"),
985 Bytes.toBytes("row_0200"), Bytes.toBytes("row_0300"));
986 HTableDescriptor desc = new HTableDescriptor(TableName.valueOf("testShouldFlushMeta"));
987 desc.addFamily(new HColumnDescriptor("foo".getBytes()));
988 HRegion r =
989 HRegion.createHRegion(hri, testDir, conf, desc,
990 wFactory.getWAL(hri.getEncodedNameAsBytes(), hri.getTable().getNamespace()));
991 HRegion.addRegionToMETA(meta, r);
992 edge.setCurrentTimeMillis(1234 + 100);
993 StringBuffer sb = new StringBuffer();
994 assertTrue(meta.shouldFlush(sb) == false);
995 edge.setCurrentTimeMillis(edge.currentTime() + HRegion.SYSTEM_CACHE_FLUSH_INTERVAL + 1);
996 assertTrue(meta.shouldFlush(sb) == true);
997 }
998
999 private class EnvironmentEdgeForMemstoreTest implements EnvironmentEdge {
1000 long t = 1234;
1001 @Override
1002 public long currentTime() {
1003 return t;
1004 }
1005 public void setCurrentTimeMillis(long t) {
1006 this.t = t;
1007 }
1008 }
1009
1010
1011
1012
1013
1014
1015
1016 private int addRows(final MemStore hmc) {
1017 return addRows(hmc, HConstants.LATEST_TIMESTAMP);
1018 }
1019
1020
1021
1022
1023
1024
1025
1026 private int addRows(final MemStore hmc, final long ts) {
1027 for (int i = 0; i < ROW_COUNT; i++) {
1028 long timestamp = ts == HConstants.LATEST_TIMESTAMP?
1029 System.currentTimeMillis(): ts;
1030 for (int ii = 0; ii < QUALIFIER_COUNT; ii++) {
1031 byte [] row = Bytes.toBytes(i);
1032 byte [] qf = makeQualifier(i, ii);
1033 hmc.add(new KeyValue(row, FAMILY, qf, timestamp, qf));
1034 }
1035 }
1036 return ROW_COUNT;
1037 }
1038
1039 private long runSnapshot(final DefaultMemStore hmc) throws UnexpectedStateException {
1040
1041 int oldHistorySize = hmc.snapshotSection.getCellSkipListSet().sizeForTests();
1042 MemStoreSnapshot snapshot = hmc.snapshot();
1043
1044 assertTrue("History size has not increased", oldHistorySize <
1045 hmc.snapshotSection.getCellSkipListSet().sizeForTests());
1046 long t = memstore.timeOfOldestEdit();
1047 assertTrue("Time of oldest edit is not Long.MAX_VALUE", t == Long.MAX_VALUE);
1048 hmc.clearSnapshot(snapshot.getId());
1049 return t;
1050 }
1051
1052 private void isExpectedRowWithoutTimestamps(final int rowIndex,
1053 List<Cell> kvs) {
1054 int i = 0;
1055 for (Cell kv: kvs) {
1056 byte[] expectedColname = makeQualifier(rowIndex, i++);
1057 assertTrue("Column name", CellUtil.matchingQualifier(kv, expectedColname));
1058
1059
1060
1061
1062 assertTrue("Content", CellUtil.matchingValue(kv, expectedColname));
1063 }
1064 }
1065
1066 private static void addRows(int count, final MemStore mem) {
1067 long nanos = System.nanoTime();
1068
1069 for (int i = 0 ; i < count ; i++) {
1070 if (i % 1000 == 0) {
1071
1072 System.out.println(i + " Took for 1k usec: " + (System.nanoTime() - nanos)/1000);
1073 nanos = System.nanoTime();
1074 }
1075 long timestamp = System.currentTimeMillis();
1076
1077 for (int ii = 0; ii < QUALIFIER_COUNT ; ii++) {
1078 byte [] row = Bytes.toBytes(i);
1079 byte [] qf = makeQualifier(i, ii);
1080 mem.add(new KeyValue(row, FAMILY, qf, timestamp, qf));
1081 }
1082 }
1083 }
1084
1085
1086 static void doScan(MemStore ms, int iteration) throws IOException {
1087 long nanos = System.nanoTime();
1088 KeyValueScanner s = ms.getScanners(0).get(0);
1089 s.seek(KeyValueUtil.createFirstOnRow(new byte[]{}));
1090
1091 System.out.println(iteration + " create/seek took: " + (System.nanoTime() - nanos)/1000);
1092 int cnt=0;
1093 while(s.next() != null) ++cnt;
1094
1095 System.out.println(iteration + " took usec: " + (System.nanoTime() - nanos) / 1000 + " for: "
1096 + cnt);
1097
1098 }
1099
1100 public static void main(String [] args) throws IOException {
1101 MemStore ms = new DefaultMemStore();
1102
1103 long n1 = System.nanoTime();
1104 addRows(25000, ms);
1105 System.out.println("Took for insert: " + (System.nanoTime()-n1)/1000);
1106
1107 System.out.println("foo");
1108
1109 for (int i = 0 ; i < 50 ; i++)
1110 doScan(ms, i);
1111 }
1112 }
1113