1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.hadoop.hbase.regionserver;
21
22 import java.lang.management.ManagementFactory;
23 import java.lang.management.RuntimeMXBean;
24 import java.util.ArrayList;
25 import java.util.Collections;
26 import java.util.Iterator;
27 import java.util.List;
28 import java.util.NavigableSet;
29 import java.util.SortedSet;
30 import java.util.concurrent.atomic.AtomicLong;
31
32 import org.apache.commons.logging.Log;
33 import org.apache.commons.logging.LogFactory;
34 import org.apache.hadoop.hbase.classification.InterfaceAudience;
35 import org.apache.hadoop.conf.Configuration;
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.HConstants;
40 import org.apache.hadoop.hbase.KeyValue;
41 import org.apache.hadoop.hbase.KeyValueUtil;
42 import org.apache.hadoop.hbase.client.Scan;
43 import org.apache.hadoop.hbase.exceptions.UnexpectedStateException;
44 import org.apache.hadoop.hbase.io.TimeRange;
45 import org.apache.hadoop.hbase.util.ByteRange;
46 import org.apache.hadoop.hbase.util.Bytes;
47 import org.apache.hadoop.hbase.util.ClassSize;
48 import org.apache.hadoop.hbase.util.CollectionBackedScanner;
49 import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
50 import org.apache.hadoop.hbase.util.ReflectionUtils;
51 import org.apache.htrace.Trace;
52
53 import com.google.common.annotations.VisibleForTesting;
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71 @InterfaceAudience.Private
72 public class DefaultMemStore implements MemStore {
73 private static final Log LOG = LogFactory.getLog(DefaultMemStore.class);
74 @VisibleForTesting
75 static final String USEMSLAB_KEY = "hbase.hregion.memstore.mslab.enabled";
76 private static final boolean USEMSLAB_DEFAULT = true;
77 private static final String MSLAB_CLASS_NAME = "hbase.regionserver.mslab.class";
78
79 private Configuration conf;
80
81 @VisibleForTesting
82 final KeyValue.KVComparator comparator;
83
84
85 private volatile long timeOfOldestEdit = Long.MAX_VALUE;
86
87 private volatile long snapshotId;
88 private volatile boolean tagsPresent;
89
90 @VisibleForTesting
91 volatile Section activeSection;
92 @VisibleForTesting
93 volatile Section snapshotSection;
94
95
96
97
98 public DefaultMemStore() {
99 this(HBaseConfiguration.create(), KeyValue.COMPARATOR);
100 }
101
102
103
104
105
106 public DefaultMemStore(final Configuration conf,
107 final KeyValue.KVComparator c) {
108 this.conf = conf;
109 this.comparator = c;
110 this.activeSection = Section.newActiveSection(comparator, conf);
111 this.snapshotSection = Section.newSnapshotSection(comparator);
112 }
113
114
115
116
117
118 @Override
119 public MemStoreSnapshot snapshot() {
120
121
122 if (!snapshotSection.getCellSkipListSet().isEmpty()) {
123 LOG.warn("Snapshot called again without clearing previous. " +
124 "Doing nothing. Another ongoing flush or did we fail last attempt?");
125 } else {
126 this.snapshotId = EnvironmentEdgeManager.currentTime();
127 if (!activeSection.getCellSkipListSet().isEmpty()) {
128 snapshotSection = activeSection;
129 activeSection = Section.newActiveSection(comparator, conf);
130 snapshotSection.getHeapSize().addAndGet(-DEEP_OVERHEAD);
131 timeOfOldestEdit = Long.MAX_VALUE;
132 }
133 }
134 MemStoreSnapshot memStoreSnapshot = new MemStoreSnapshot(this.snapshotId,
135 snapshotSection.getCellSkipListSet().size(), snapshotSection.getHeapSize().get(),
136 snapshotSection.getTimeRangeTracker(),
137 new CollectionBackedScanner(snapshotSection.getCellSkipListSet(), this.comparator),
138 this.tagsPresent);
139 this.tagsPresent = false;
140 return memStoreSnapshot;
141 }
142
143
144
145
146
147
148
149 @Override
150 public void clearSnapshot(long id) throws UnexpectedStateException {
151 if (this.snapshotId == -1) return;
152 if (this.snapshotId != id) {
153 throw new UnexpectedStateException("Current snapshot id is " + this.snapshotId + ",passed "
154 + id);
155 }
156
157 MemStoreLAB tmpAllocator = snapshotSection.getMemStoreLAB();
158 snapshotSection = Section.newSnapshotSection(comparator);
159 if (tmpAllocator != null) {
160 tmpAllocator.close();
161 }
162 this.snapshotId = -1;
163 }
164
165 @Override
166 public long getFlushableSize() {
167 long snapshotSize = snapshotSection.getHeapSize().get();
168 return snapshotSize > 0 ? snapshotSize : keySize();
169 }
170
171 @Override
172 public long getSnapshotSize() {
173 return snapshotSection.getHeapSize().get();
174 }
175
176
177
178
179
180
181 @Override
182 public long add(Cell cell) {
183 Cell toAdd = maybeCloneWithAllocator(cell);
184 boolean mslabUsed = (toAdd != cell);
185 return internalAdd(toAdd, mslabUsed);
186 }
187
188 @Override
189 public long add(Iterable<Cell> cells) {
190 long size = 0;
191 for (Cell cell : cells) {
192 size += add(cell);
193 }
194 return size;
195 }
196
197 @Override
198 public long timeOfOldestEdit() {
199 return timeOfOldestEdit;
200 }
201
202 private boolean addToCellSet(Cell e) {
203 boolean b = this.activeSection.getCellSkipListSet().add(e);
204
205
206
207
208 if(e.getTagsLength() > 0) {
209 tagsPresent = true;
210 }
211 setOldestEditTimeToNow();
212 return b;
213 }
214
215 private boolean removeFromCellSet(Cell e) {
216 boolean b = this.activeSection.getCellSkipListSet().remove(e);
217 setOldestEditTimeToNow();
218 return b;
219 }
220
221 void setOldestEditTimeToNow() {
222 if (timeOfOldestEdit == Long.MAX_VALUE) {
223 timeOfOldestEdit = EnvironmentEdgeManager.currentTime();
224 }
225 }
226
227
228
229
230
231
232
233
234
235
236 private long internalAdd(final Cell toAdd, boolean mslabUsed) {
237 boolean notPresent = addToCellSet(toAdd);
238 long s = heapSizeChange(toAdd, notPresent);
239
240
241
242 if (!notPresent && mslabUsed) {
243 s += getCellLength(toAdd);
244 }
245 activeSection.getTimeRangeTracker().includeTimestamp(toAdd);
246 activeSection.getHeapSize().addAndGet(s);
247 return s;
248 }
249
250
251
252
253 @VisibleForTesting
254 int getCellLength(Cell cell) {
255 return KeyValueUtil.length(cell);
256 }
257
258 private Cell maybeCloneWithAllocator(Cell cell) {
259 if (activeSection.getMemStoreLAB() == null) {
260 return cell;
261 }
262
263 int len = getCellLength(cell);
264 ByteRange alloc = activeSection.getMemStoreLAB().allocateBytes(len);
265 if (alloc == null) {
266
267
268 return cell;
269 }
270 assert alloc.getBytes() != null;
271 KeyValueUtil.appendToByteArray(cell, alloc.getBytes(), alloc.getOffset());
272 KeyValue newKv = new KeyValue(alloc.getBytes(), alloc.getOffset(), len);
273 newKv.setSequenceId(cell.getSequenceId());
274 return newKv;
275 }
276
277
278
279
280
281
282
283
284
285 @Override
286 public void rollback(Cell cell) {
287
288
289
290
291
292 Cell found = snapshotSection.getCellSkipListSet().get(cell);
293 if (found != null && found.getSequenceId() == cell.getSequenceId()) {
294 snapshotSection.getCellSkipListSet().remove(cell);
295 long sz = heapSizeChange(cell, true);
296 snapshotSection.getHeapSize().addAndGet(-sz);
297 }
298
299
300 found = activeSection.getCellSkipListSet().get(cell);
301 if (found != null && found.getSequenceId() == cell.getSequenceId()) {
302 removeFromCellSet(found);
303 long sz = heapSizeChange(found, true);
304 activeSection.getHeapSize().addAndGet(-sz);
305 }
306 }
307
308
309
310
311
312
313 @Override
314 public long delete(Cell deleteCell) {
315 Cell toAdd = maybeCloneWithAllocator(deleteCell);
316 boolean mslabUsed = (toAdd != deleteCell);
317 return internalAdd(toAdd, mslabUsed);
318 }
319
320
321
322
323
324
325 Cell getNextRow(final Cell cell) {
326 return getLowest(getNextRow(cell, activeSection.getCellSkipListSet()),
327 getNextRow(cell, snapshotSection.getCellSkipListSet()));
328 }
329
330
331
332
333
334
335 private Cell getLowest(final Cell a, final Cell b) {
336 if (a == null) {
337 return b;
338 }
339 if (b == null) {
340 return a;
341 }
342 return comparator.compareRows(a, b) <= 0? a: b;
343 }
344
345
346
347
348
349
350
351 private Cell getNextRow(final Cell key,
352 final NavigableSet<Cell> set) {
353 Cell result = null;
354 SortedSet<Cell> tail = key == null? set: set.tailSet(key);
355
356 for (Cell cell: tail) {
357 if (comparator.compareRows(cell, key) <= 0)
358 continue;
359
360
361 result = cell;
362 break;
363 }
364 return result;
365 }
366
367
368
369
370 @Override
371 public void getRowKeyAtOrBefore(final GetClosestRowBeforeTracker state) {
372 getRowKeyAtOrBefore(activeSection.getCellSkipListSet(), state);
373 getRowKeyAtOrBefore(snapshotSection.getCellSkipListSet(), state);
374 }
375
376
377
378
379
380 private void getRowKeyAtOrBefore(final NavigableSet<Cell> set,
381 final GetClosestRowBeforeTracker state) {
382 if (set.isEmpty()) {
383 return;
384 }
385 if (!walkForwardInSingleRow(set, state.getTargetKey(), state)) {
386
387 getRowKeyBefore(set, state);
388 }
389 }
390
391
392
393
394
395
396
397
398
399
400
401 private boolean walkForwardInSingleRow(final SortedSet<Cell> set,
402 final Cell firstOnRow, final GetClosestRowBeforeTracker state) {
403 boolean foundCandidate = false;
404 SortedSet<Cell> tail = set.tailSet(firstOnRow);
405 if (tail.isEmpty()) return foundCandidate;
406 for (Iterator<Cell> i = tail.iterator(); i.hasNext();) {
407 Cell kv = i.next();
408
409 if (state.isTooFar(kv, firstOnRow)) break;
410 if (state.isExpired(kv)) {
411 i.remove();
412 continue;
413 }
414
415 if (state.handle(kv)) {
416 foundCandidate = true;
417 break;
418 }
419 }
420 return foundCandidate;
421 }
422
423
424
425
426
427
428
429 private void getRowKeyBefore(NavigableSet<Cell> set,
430 final GetClosestRowBeforeTracker state) {
431 Cell firstOnRow = state.getTargetKey();
432 for (Member p = memberOfPreviousRow(set, state, firstOnRow);
433 p != null; p = memberOfPreviousRow(p.set, state, firstOnRow)) {
434
435 if (!state.isTargetTable(p.cell)) break;
436
437 if (!state.isBetterCandidate(p.cell)) break;
438
439 firstOnRow = new KeyValue(p.cell.getRowArray(), p.cell.getRowOffset(), p.cell.getRowLength(),
440 HConstants.LATEST_TIMESTAMP);
441
442 if (walkForwardInSingleRow(p.set, firstOnRow, state)) break;
443 }
444 }
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463 @Override
464 public long updateColumnValue(byte[] row,
465 byte[] family,
466 byte[] qualifier,
467 long newValue,
468 long now) {
469 Cell firstCell = KeyValueUtil.createFirstOnRow(row, family, qualifier);
470
471 SortedSet<Cell> snSs = snapshotSection.getCellSkipListSet().tailSet(firstCell);
472 if (!snSs.isEmpty()) {
473 Cell snc = snSs.first();
474
475 if (CellUtil.matchingRow(snc, firstCell) && CellUtil.matchingQualifier(snc, firstCell)) {
476 if (snc.getTimestamp() == now) {
477
478 now += 1;
479 }
480 }
481 }
482
483
484
485
486
487
488
489 SortedSet<Cell> ss = activeSection.getCellSkipListSet().tailSet(firstCell);
490 for (Cell cell : ss) {
491
492 if (!CellUtil.matchingColumn(cell, family, qualifier)
493 || !CellUtil.matchingRow(cell, firstCell)) {
494 break;
495 }
496
497
498 if (cell.getTypeByte() == KeyValue.Type.Put.getCode() &&
499 cell.getTimestamp() > now && CellUtil.matchingQualifier(firstCell, cell)) {
500 now = cell.getTimestamp();
501 }
502 }
503
504
505
506 List<Cell> cells = new ArrayList<Cell>(1);
507 cells.add(new KeyValue(row, family, qualifier, now, Bytes.toBytes(newValue)));
508 return upsert(cells, 1L, null);
509 }
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530 @Override
531 public long upsert(Iterable<Cell> cells, long readpoint, List<Cell> removedCells) {
532 long size = 0;
533 for (Cell cell : cells) {
534 size += upsert(cell, readpoint, removedCells);
535 }
536 return size;
537 }
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553 private long upsert(Cell cell, long readpoint, List<Cell> removedCells) {
554
555
556
557
558
559
560 long addedSize = internalAdd(cell, false);
561
562
563
564 Cell firstCell = KeyValueUtil.createFirstOnRow(
565 cell.getRowArray(), cell.getRowOffset(), cell.getRowLength(),
566 cell.getFamilyArray(), cell.getFamilyOffset(), cell.getFamilyLength(),
567 cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength());
568 SortedSet<Cell> ss = activeSection.getCellSkipListSet().tailSet(firstCell);
569 Iterator<Cell> it = ss.iterator();
570
571 int versionsVisible = 0;
572 while ( it.hasNext() ) {
573 Cell cur = it.next();
574
575 if (cell == cur) {
576
577 continue;
578 }
579
580 if (CellUtil.matchingRow(cell, cur) && CellUtil.matchingQualifier(cell, cur)) {
581
582 if (cur.getTypeByte() == KeyValue.Type.Put.getCode() &&
583 cur.getSequenceId() <= readpoint) {
584 if (versionsVisible >= 1) {
585
586
587
588
589 long delta = heapSizeChange(cur, true);
590 addedSize -= delta;
591 activeSection.getHeapSize().addAndGet(-delta);
592 if (removedCells != null) {
593 removedCells.add(cur);
594 }
595 it.remove();
596 setOldestEditTimeToNow();
597 } else {
598 versionsVisible++;
599 }
600 }
601 } else {
602
603 break;
604 }
605 }
606 return addedSize;
607 }
608
609
610
611
612
613 private static class Member {
614 final Cell cell;
615 final NavigableSet<Cell> set;
616 Member(final NavigableSet<Cell> s, final Cell kv) {
617 this.cell = kv;
618 this.set = s;
619 }
620 }
621
622
623
624
625
626
627
628
629
630 private Member memberOfPreviousRow(NavigableSet<Cell> set,
631 final GetClosestRowBeforeTracker state, final Cell firstOnRow) {
632 NavigableSet<Cell> head = set.headSet(firstOnRow, false);
633 if (head.isEmpty()) return null;
634 for (Iterator<Cell> i = head.descendingIterator(); i.hasNext();) {
635 Cell found = i.next();
636 if (state.isExpired(found)) {
637 i.remove();
638 continue;
639 }
640 return new Member(head, found);
641 }
642 return null;
643 }
644
645
646
647
648 @Override
649 public List<KeyValueScanner> getScanners(long readPt) {
650 MemStoreScanner scanner =
651 new MemStoreScanner(activeSection, snapshotSection, readPt, comparator);
652 scanner.seek(CellUtil.createCell(HConstants.EMPTY_START_ROW));
653 if (scanner.peek() == null) {
654 scanner.close();
655 return null;
656 }
657 return Collections.<KeyValueScanner> singletonList(scanner);
658 }
659
660
661
662
663
664
665
666
667 public boolean shouldSeek(Scan scan, Store store, long oldestUnexpiredTS) {
668 return shouldSeek(activeSection.getTimeRangeTracker(),
669 snapshotSection.getTimeRangeTracker(), scan, store, oldestUnexpiredTS);
670 }
671
672
673
674
675
676
677
678
679
680
681 private static boolean shouldSeek(TimeRangeTracker activeTimeRangeTracker,
682 TimeRangeTracker snapshotTimeRangeTracker, Scan scan, Store store, long oldestUnexpiredTS) {
683 byte[] cf = store.getFamily().getName();
684 TimeRange timeRange = scan.getColumnFamilyTimeRange().get(cf);
685 if (timeRange == null) {
686 timeRange = scan.getTimeRange();
687 }
688 return (activeTimeRangeTracker.includesTimeRange(timeRange) ||
689 snapshotTimeRangeTracker.includesTimeRange(timeRange)) &&
690 (Math.max(activeTimeRangeTracker.getMax(), snapshotTimeRangeTracker.getMax()) >= oldestUnexpiredTS);
691 }
692
693
694
695
696
697
698
699 protected static class MemStoreScanner extends NonLazyKeyValueScanner {
700
701 private Cell cellSetNextRow = null;
702 private Cell snapshotNextRow = null;
703
704
705 private Cell cellSetItRow = null;
706 private Cell snapshotItRow = null;
707
708
709 private Iterator<Cell> cellSetIt;
710 private Iterator<Cell> snapshotIt;
711
712
713 private final Section activeAtCreation;
714 private final Section snapshotAtCreation;
715
716
717 private Cell theNext;
718
719
720
721 private boolean stopSkippingCellsIfNextRow = false;
722
723 private Cell stopSkippingKVsRow;
724
725 private final long readPoint;
726 private final KeyValue.KVComparator comparator;
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748 MemStoreScanner(Section activeSection, Section snapshotSection, long readPoint, final KeyValue.KVComparator c) {
749 this.readPoint = readPoint;
750 this.comparator = c;
751 activeAtCreation = activeSection;
752 snapshotAtCreation = snapshotSection;
753 if (activeAtCreation.getMemStoreLAB() != null) {
754 activeAtCreation.getMemStoreLAB().incScannerCount();
755 }
756 if (snapshotAtCreation.getMemStoreLAB() != null) {
757 snapshotAtCreation.getMemStoreLAB().incScannerCount();
758 }
759 if (Trace.isTracing() && Trace.currentSpan() != null) {
760 Trace.currentSpan().addTimelineAnnotation("Creating MemStoreScanner");
761 }
762 }
763
764
765
766
767
768
769 private Cell getNext(Iterator<Cell> it) {
770 Cell v = null;
771 try {
772 while (it.hasNext()) {
773 v = it.next();
774 if (v.getSequenceId() <= this.readPoint) {
775 return v;
776 }
777 if (stopSkippingCellsIfNextRow && stopSkippingKVsRow != null
778 && comparator.compareRows(v, stopSkippingKVsRow) > 0) {
779 return null;
780 }
781 }
782
783 return null;
784 } finally {
785 if (v != null) {
786
787 if (it == snapshotIt) {
788 snapshotItRow = v;
789 } else {
790 cellSetItRow = v;
791 }
792 }
793 }
794 }
795
796
797
798
799
800
801
802
803 @Override
804 public synchronized boolean seek(Cell key) {
805 if (key == null) {
806 close();
807 return false;
808 }
809
810
811 cellSetIt = activeAtCreation.getCellSkipListSet().tailSet(key).iterator();
812 snapshotIt = snapshotAtCreation.getCellSkipListSet().tailSet(key).iterator();
813 cellSetItRow = null;
814 snapshotItRow = null;
815
816 return seekInSubLists(key);
817 }
818
819
820
821
822
823 private synchronized boolean seekInSubLists(Cell key){
824 cellSetNextRow = getNext(cellSetIt);
825 snapshotNextRow = getNext(snapshotIt);
826
827
828 theNext = getLowest(cellSetNextRow, snapshotNextRow);
829
830
831 return (theNext != null);
832 }
833
834
835
836
837
838
839
840 @Override
841 public synchronized boolean reseek(Cell key) {
842
843
844
845
846
847
848
849
850
851
852
853
854 cellSetIt = activeAtCreation.getCellSkipListSet().tailSet(getHighest(key, cellSetItRow)).iterator();
855 snapshotIt = snapshotAtCreation.getCellSkipListSet().tailSet(getHighest(key, snapshotItRow)).iterator();
856
857 return seekInSubLists(key);
858 }
859
860
861 @Override
862 public synchronized Cell peek() {
863
864 return theNext;
865 }
866
867 @Override
868 public synchronized Cell next() {
869 if (theNext == null) {
870 return null;
871 }
872
873 final Cell ret = theNext;
874
875
876 if (theNext == cellSetNextRow) {
877 cellSetNextRow = getNext(cellSetIt);
878 } else {
879 snapshotNextRow = getNext(snapshotIt);
880 }
881
882
883 theNext = getLowest(cellSetNextRow, snapshotNextRow);
884
885
886
887
888 return ret;
889 }
890
891
892
893
894
895
896 private Cell getLowest(Cell first, Cell second) {
897 if (first == null && second == null) {
898 return null;
899 }
900 if (first != null && second != null) {
901 int compare = comparator.compare(first, second);
902 return (compare <= 0 ? first : second);
903 }
904 return (first != null ? first : second);
905 }
906
907
908
909
910
911
912 private Cell getHighest(Cell first, Cell second) {
913 if (first == null && second == null) {
914 return null;
915 }
916 if (first != null && second != null) {
917 int compare = comparator.compare(first, second);
918 return (compare > 0 ? first : second);
919 }
920 return (first != null ? first : second);
921 }
922
923 @Override
924 public synchronized void close() {
925 this.cellSetNextRow = null;
926 this.snapshotNextRow = null;
927
928 this.cellSetIt = null;
929 this.snapshotIt = null;
930
931 if (activeAtCreation != null && activeAtCreation.getMemStoreLAB() != null) {
932 activeAtCreation.getMemStoreLAB().decScannerCount();
933 }
934 if (snapshotAtCreation != null && snapshotAtCreation.getMemStoreLAB() != null) {
935 snapshotAtCreation.getMemStoreLAB().decScannerCount();
936 }
937
938 this.cellSetItRow = null;
939 this.snapshotItRow = null;
940 }
941
942
943
944
945
946
947 @Override
948 public long getScannerOrder() {
949 return Long.MAX_VALUE;
950 }
951
952 @Override
953 public boolean shouldUseScanner(Scan scan, Store store, long oldestUnexpiredTS) {
954 return shouldSeek(activeAtCreation.getTimeRangeTracker(),
955 snapshotAtCreation.getTimeRangeTracker(), scan, store, oldestUnexpiredTS);
956 }
957
958
959
960
961
962
963 @Override
964 public synchronized boolean backwardSeek(Cell key) {
965 seek(key);
966 if (peek() == null || comparator.compareRows(peek(), key) > 0) {
967 return seekToPreviousRow(key);
968 }
969 return true;
970 }
971
972
973
974
975
976
977 @Override
978 public synchronized boolean seekToPreviousRow(Cell originalKey) {
979 boolean keepSeeking = false;
980 Cell key = originalKey;
981 do {
982 Cell firstKeyOnRow = KeyValueUtil.createFirstOnRow(key.getRowArray(), key.getRowOffset(),
983 key.getRowLength());
984 SortedSet<Cell> cellHead = activeAtCreation.getCellSkipListSet().headSet(firstKeyOnRow);
985 Cell cellSetBeforeRow = cellHead.isEmpty() ? null : cellHead.last();
986 SortedSet<Cell> snapshotHead = snapshotAtCreation.getCellSkipListSet()
987 .headSet(firstKeyOnRow);
988 Cell snapshotBeforeRow = snapshotHead.isEmpty() ? null : snapshotHead
989 .last();
990 Cell lastCellBeforeRow = getHighest(cellSetBeforeRow, snapshotBeforeRow);
991 if (lastCellBeforeRow == null) {
992 theNext = null;
993 return false;
994 }
995 Cell firstKeyOnPreviousRow = KeyValueUtil.createFirstOnRow(lastCellBeforeRow.getRowArray(),
996 lastCellBeforeRow.getRowOffset(), lastCellBeforeRow.getRowLength());
997 this.stopSkippingCellsIfNextRow = true;
998 this.stopSkippingKVsRow = firstKeyOnPreviousRow;
999 seek(firstKeyOnPreviousRow);
1000 this.stopSkippingCellsIfNextRow = false;
1001 if (peek() == null
1002 || comparator.compareRows(peek(), firstKeyOnPreviousRow) > 0) {
1003 keepSeeking = true;
1004 key = firstKeyOnPreviousRow;
1005 continue;
1006 } else {
1007 keepSeeking = false;
1008 }
1009 } while (keepSeeking);
1010 return true;
1011 }
1012
1013 @Override
1014 public synchronized boolean seekToLastRow() {
1015 Cell first = activeAtCreation.getCellSkipListSet().isEmpty() ? null
1016 : activeAtCreation.getCellSkipListSet().last();
1017 Cell second = snapshotAtCreation.getCellSkipListSet().isEmpty() ? null
1018 : snapshotAtCreation.getCellSkipListSet().last();
1019 Cell higherCell = getHighest(first, second);
1020 if (higherCell == null) {
1021 return false;
1022 }
1023 Cell firstCellOnLastRow = KeyValueUtil.createFirstOnRow(higherCell.getRowArray(),
1024 higherCell.getRowOffset(), higherCell.getRowLength());
1025 if (seek(firstCellOnLastRow)) {
1026 return true;
1027 } else {
1028 return seekToPreviousRow(higherCell);
1029 }
1030
1031 }
1032 }
1033
1034 public final static long FIXED_OVERHEAD = ClassSize.align(ClassSize.OBJECT
1035 + (4 * ClassSize.REFERENCE) + (2 * Bytes.SIZEOF_LONG) + Bytes.SIZEOF_BOOLEAN);
1036
1037 public final static long DEEP_OVERHEAD = ClassSize.align(FIXED_OVERHEAD +
1038 (2 * ClassSize.ATOMIC_LONG) + (2 * ClassSize.TIMERANGE_TRACKER) +
1039 (2 * ClassSize.CELL_SKIPLIST_SET) + (2 * ClassSize.CONCURRENT_SKIPLISTMAP));
1040
1041
1042
1043
1044
1045
1046
1047
1048 static long heapSizeChange(final Cell cell, final boolean notpresent) {
1049 return notpresent ? ClassSize.align(ClassSize.CONCURRENT_SKIPLISTMAP_ENTRY
1050 + CellUtil.estimatedHeapSizeOf(cell)) : 0;
1051 }
1052
1053 private long keySize() {
1054 return heapSize() - DEEP_OVERHEAD;
1055 }
1056
1057
1058
1059
1060
1061 @Override
1062 public long heapSize() {
1063 return activeSection.getHeapSize().get();
1064 }
1065
1066 @Override
1067 public long size() {
1068 return heapSize();
1069 }
1070
1071
1072
1073
1074
1075
1076
1077
1078 public static void main(String [] args) {
1079 RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
1080 LOG.info("vmName=" + runtime.getVmName() + ", vmVendor=" +
1081 runtime.getVmVendor() + ", vmVersion=" + runtime.getVmVersion());
1082 LOG.info("vmInputArguments=" + runtime.getInputArguments());
1083 DefaultMemStore memstore1 = new DefaultMemStore();
1084
1085 long size = 0;
1086 final int count = 10000;
1087 byte [] fam = Bytes.toBytes("col");
1088 byte [] qf = Bytes.toBytes("umn");
1089 byte [] empty = new byte[0];
1090 for (int i = 0; i < count; i++) {
1091
1092 size += memstore1.add(new KeyValue(Bytes.toBytes(i), fam, qf, i, empty));
1093 }
1094 LOG.info("memstore1 estimated size=" + size);
1095 for (int i = 0; i < count; i++) {
1096 size += memstore1.add(new KeyValue(Bytes.toBytes(i), fam, qf, i, empty));
1097 }
1098 LOG.info("memstore1 estimated size (2nd loading of same data)=" + size);
1099
1100 DefaultMemStore memstore2 = new DefaultMemStore();
1101 for (int i = 0; i < count; i++) {
1102 size += memstore2.add(new KeyValue(Bytes.toBytes(i), fam, qf, i, new byte[i]));
1103 }
1104 LOG.info("memstore2 estimated size=" + size);
1105 final int seconds = 30;
1106 LOG.info("Waiting " + seconds + " seconds while heap dump is taken");
1107 for (int i = 0; i < seconds; i++) {
1108
1109 }
1110 LOG.info("Exiting.");
1111 }
1112
1113
1114
1115
1116 @InterfaceAudience.Private
1117 @VisibleForTesting
1118 static class Section {
1119
1120
1121
1122
1123
1124
1125 private final CellSkipListSet cellSet;
1126 private final TimeRangeTracker tracker = new TimeRangeTracker();
1127
1128
1129
1130 private final AtomicLong heapSize;
1131 private final MemStoreLAB allocator;
1132
1133 static Section newSnapshotSection(final KeyValue.KVComparator c) {
1134 return new Section(c, null, 0);
1135 }
1136
1137 static Section newActiveSection(final KeyValue.KVComparator c,
1138 final Configuration conf) {
1139 return new Section(c, conf, DEEP_OVERHEAD);
1140 }
1141
1142 private Section(final KeyValue.KVComparator c,
1143 final Configuration conf, long initHeapSize) {
1144 this.cellSet = new CellSkipListSet(c);
1145 this.heapSize = new AtomicLong(initHeapSize);
1146 if (conf != null && conf.getBoolean(USEMSLAB_KEY, USEMSLAB_DEFAULT)) {
1147 String className = conf.get(MSLAB_CLASS_NAME, HeapMemStoreLAB.class.getName());
1148 this.allocator = ReflectionUtils.instantiateWithCustomCtor(className,
1149 new Class[]{Configuration.class}, new Object[]{conf});
1150 } else {
1151 this.allocator = null;
1152 }
1153 }
1154
1155 CellSkipListSet getCellSkipListSet() {
1156 return cellSet;
1157 }
1158
1159 TimeRangeTracker getTimeRangeTracker() {
1160 return tracker;
1161 }
1162
1163 AtomicLong getHeapSize() {
1164 return heapSize;
1165 }
1166
1167 MemStoreLAB getMemStoreLAB() {
1168 return allocator;
1169 }
1170
1171 }
1172 }