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.AtomicInteger;
31 import java.util.concurrent.atomic.AtomicLong;
32
33 import org.apache.commons.logging.Log;
34 import org.apache.commons.logging.LogFactory;
35 import org.apache.hadoop.hbase.classification.InterfaceAudience;
36 import org.apache.hadoop.conf.Configuration;
37 import org.apache.hadoop.hbase.Cell;
38 import org.apache.hadoop.hbase.CellUtil;
39 import org.apache.hadoop.hbase.HBaseConfiguration;
40 import org.apache.hadoop.hbase.HConstants;
41 import org.apache.hadoop.hbase.KeyValue;
42 import org.apache.hadoop.hbase.KeyValueUtil;
43 import org.apache.hadoop.hbase.client.Scan;
44 import org.apache.hadoop.hbase.exceptions.UnexpectedStateException;
45 import org.apache.hadoop.hbase.io.TimeRange;
46 import org.apache.hadoop.hbase.util.ByteRange;
47 import org.apache.hadoop.hbase.util.Bytes;
48 import org.apache.hadoop.hbase.util.ClassSize;
49 import org.apache.hadoop.hbase.util.CollectionBackedScanner;
50 import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
51 import org.apache.hadoop.hbase.util.ReflectionUtils;
52 import org.apache.htrace.Trace;
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70 @InterfaceAudience.Private
71 public class DefaultMemStore implements MemStore {
72 private static final Log LOG = LogFactory.getLog(DefaultMemStore.class);
73 static final String USEMSLAB_KEY = "hbase.hregion.memstore.mslab.enabled";
74 private static final boolean USEMSLAB_DEFAULT = true;
75 private static final String MSLAB_CLASS_NAME = "hbase.regionserver.mslab.class";
76
77 private Configuration conf;
78
79 final KeyValue.KVComparator comparator;
80
81
82 private volatile long timeOfOldestEdit = Long.MAX_VALUE;
83
84 private volatile long snapshotId;
85 private volatile boolean tagsPresent;
86
87 volatile Section activeSection;
88 volatile Section snapshotSection;
89
90
91
92
93 public DefaultMemStore() {
94 this(HBaseConfiguration.create(), KeyValue.COMPARATOR);
95 }
96
97
98
99
100
101 public DefaultMemStore(final Configuration conf,
102 final KeyValue.KVComparator c) {
103 this.conf = conf;
104 this.comparator = c;
105 this.activeSection = Section.newActiveSection(comparator, conf);
106 this.snapshotSection = Section.newSnapshotSection(comparator);
107 }
108
109
110
111
112
113 @Override
114 public MemStoreSnapshot snapshot() {
115
116
117 if (!snapshotSection.getCellSkipListSet().isEmpty()) {
118 LOG.warn("Snapshot called again without clearing previous. " +
119 "Doing nothing. Another ongoing flush or did we fail last attempt?");
120 } else {
121 this.snapshotId = EnvironmentEdgeManager.currentTime();
122 if (!activeSection.getCellSkipListSet().isEmpty()) {
123 snapshotSection = activeSection;
124 activeSection = Section.newActiveSection(comparator, conf);
125 snapshotSection.getHeapSize().addAndGet(-DEEP_OVERHEAD);
126 timeOfOldestEdit = Long.MAX_VALUE;
127 }
128 }
129 MemStoreSnapshot memStoreSnapshot = new MemStoreSnapshot(this.snapshotId,
130 snapshotSection.getCellsCount().get(), snapshotSection.getHeapSize().get(),
131 snapshotSection.getTimeRangeTracker(),
132 new CollectionBackedScanner(snapshotSection.getCellSkipListSet(), this.comparator),
133 this.tagsPresent);
134 this.tagsPresent = false;
135 return memStoreSnapshot;
136 }
137
138
139
140
141
142
143
144 @Override
145 public void clearSnapshot(long id) throws UnexpectedStateException {
146 if (this.snapshotId == -1) return;
147 if (this.snapshotId != id) {
148 throw new UnexpectedStateException("Current snapshot id is " + this.snapshotId + ",passed "
149 + id);
150 }
151
152 MemStoreLAB tmpAllocator = snapshotSection.getMemStoreLAB();
153 snapshotSection = Section.newSnapshotSection(comparator);
154 if (tmpAllocator != null) {
155 tmpAllocator.close();
156 }
157 this.snapshotId = -1;
158 }
159
160 @Override
161 public long getFlushableSize() {
162 long snapshotSize = snapshotSection.getHeapSize().get();
163 return snapshotSize > 0 ? snapshotSize : keySize();
164 }
165
166 @Override
167 public long getSnapshotSize() {
168 return snapshotSection.getHeapSize().get();
169 }
170
171
172
173
174
175
176 @Override
177 public long add(Cell cell) {
178 Cell toAdd = maybeCloneWithAllocator(cell);
179 boolean mslabUsed = (toAdd != cell);
180 return internalAdd(toAdd, mslabUsed);
181 }
182
183 @Override
184 public long add(Iterable<Cell> cells) {
185 long size = 0;
186 for (Cell cell : cells) {
187 size += add(cell);
188 }
189 return size;
190 }
191
192 @Override
193 public long timeOfOldestEdit() {
194 return timeOfOldestEdit;
195 }
196
197 private boolean addToCellSet(Cell e) {
198 boolean b = this.activeSection.getCellSkipListSet().add(e);
199
200
201
202
203 if(e.getTagsLength() > 0) {
204 tagsPresent = true;
205 }
206 setOldestEditTimeToNow();
207 return b;
208 }
209
210 private boolean removeFromCellSet(Cell e) {
211 boolean b = this.activeSection.getCellSkipListSet().remove(e);
212 setOldestEditTimeToNow();
213 return b;
214 }
215
216 void setOldestEditTimeToNow() {
217 if (timeOfOldestEdit == Long.MAX_VALUE) {
218 timeOfOldestEdit = EnvironmentEdgeManager.currentTime();
219 }
220 }
221
222
223
224
225
226
227
228
229
230
231 private long internalAdd(final Cell toAdd, boolean mslabUsed) {
232 boolean notPresent = addToCellSet(toAdd);
233 long s = heapSizeChange(toAdd, notPresent);
234 if (notPresent) {
235 activeSection.getCellsCount().incrementAndGet();
236 }
237
238
239
240 if (!notPresent && mslabUsed) {
241 s += getCellLength(toAdd);
242 }
243 activeSection.getTimeRangeTracker().includeTimestamp(toAdd);
244 activeSection.getHeapSize().addAndGet(s);
245 return s;
246 }
247
248
249
250
251 int getCellLength(Cell cell) {
252 return KeyValueUtil.length(cell);
253 }
254
255 private Cell maybeCloneWithAllocator(Cell cell) {
256 if (activeSection.getMemStoreLAB() == null) {
257 return cell;
258 }
259
260 int len = getCellLength(cell);
261 ByteRange alloc = activeSection.getMemStoreLAB().allocateBytes(len);
262 if (alloc == null) {
263
264
265 return cell;
266 }
267 assert alloc.getBytes() != null;
268 KeyValueUtil.appendToByteArray(cell, alloc.getBytes(), alloc.getOffset());
269 KeyValue newKv = new KeyValue(alloc.getBytes(), alloc.getOffset(), len);
270 newKv.setSequenceId(cell.getSequenceId());
271 return newKv;
272 }
273
274
275
276
277
278
279
280
281
282 @Override
283 public void rollback(Cell cell) {
284
285
286
287
288
289 Cell found = snapshotSection.getCellSkipListSet().get(cell);
290 if (found != null && found.getSequenceId() == cell.getSequenceId()) {
291 snapshotSection.getCellSkipListSet().remove(cell);
292 long sz = heapSizeChange(cell, true);
293 snapshotSection.getHeapSize().addAndGet(-sz);
294 snapshotSection.getCellsCount().decrementAndGet();
295 }
296
297
298 found = activeSection.getCellSkipListSet().get(cell);
299 if (found != null && found.getSequenceId() == cell.getSequenceId()) {
300 removeFromCellSet(found);
301 long sz = heapSizeChange(found, true);
302 activeSection.getHeapSize().addAndGet(-sz);
303 activeSection.getCellsCount().decrementAndGet();
304 }
305 }
306
307
308
309
310
311
312 @Override
313 public long delete(Cell deleteCell) {
314 Cell toAdd = maybeCloneWithAllocator(deleteCell);
315 boolean mslabUsed = (toAdd != deleteCell);
316 return internalAdd(toAdd, mslabUsed);
317 }
318
319
320
321
322
323
324 Cell getNextRow(final Cell cell) {
325 return getLowest(getNextRow(cell, activeSection.getCellSkipListSet()),
326 getNextRow(cell, snapshotSection.getCellSkipListSet()));
327 }
328
329
330
331
332
333
334 private Cell getLowest(final Cell a, final Cell b) {
335 if (a == null) {
336 return b;
337 }
338 if (b == null) {
339 return a;
340 }
341 return comparator.compareRows(a, b) <= 0? a: b;
342 }
343
344
345
346
347
348
349
350 private Cell getNextRow(final Cell key,
351 final NavigableSet<Cell> set) {
352 Cell result = null;
353 SortedSet<Cell> tail = key == null? set: set.tailSet(key);
354
355 for (Cell cell: tail) {
356 if (comparator.compareRows(cell, key) <= 0)
357 continue;
358
359
360 result = cell;
361 break;
362 }
363 return result;
364 }
365
366
367
368
369 @Override
370 public void getRowKeyAtOrBefore(final GetClosestRowBeforeTracker state) {
371 getRowKeyAtOrBefore(activeSection.getCellSkipListSet(), state);
372 getRowKeyAtOrBefore(snapshotSection.getCellSkipListSet(), state);
373 }
374
375
376
377
378
379 private void getRowKeyAtOrBefore(final NavigableSet<Cell> set,
380 final GetClosestRowBeforeTracker state) {
381 if (set.isEmpty()) {
382 return;
383 }
384 if (!walkForwardInSingleRow(set, state.getTargetKey(), state)) {
385
386 getRowKeyBefore(set, state);
387 }
388 }
389
390
391
392
393
394
395
396
397
398
399
400 private boolean walkForwardInSingleRow(final SortedSet<Cell> set,
401 final Cell firstOnRow, final GetClosestRowBeforeTracker state) {
402 boolean foundCandidate = false;
403 SortedSet<Cell> tail = set.tailSet(firstOnRow);
404 if (tail.isEmpty()) return foundCandidate;
405 for (Iterator<Cell> i = tail.iterator(); i.hasNext();) {
406 Cell kv = i.next();
407
408 if (state.isTooFar(kv, firstOnRow)) break;
409 if (state.isExpired(kv)) {
410 i.remove();
411 continue;
412 }
413
414 if (state.handle(kv)) {
415 foundCandidate = true;
416 break;
417 }
418 }
419 return foundCandidate;
420 }
421
422
423
424
425
426
427
428 private void getRowKeyBefore(NavigableSet<Cell> set,
429 final GetClosestRowBeforeTracker state) {
430 Cell firstOnRow = state.getTargetKey();
431 for (Member p = memberOfPreviousRow(set, state, firstOnRow);
432 p != null; p = memberOfPreviousRow(p.set, state, firstOnRow)) {
433
434 if (!state.isTargetTable(p.cell)) break;
435
436 if (!state.isBetterCandidate(p.cell)) break;
437
438 firstOnRow = new KeyValue(p.cell.getRowArray(), p.cell.getRowOffset(), p.cell.getRowLength(),
439 HConstants.LATEST_TIMESTAMP);
440
441 if (walkForwardInSingleRow(p.set, firstOnRow, state)) break;
442 }
443 }
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462 @Override
463 public long updateColumnValue(byte[] row,
464 byte[] family,
465 byte[] qualifier,
466 long newValue,
467 long now) {
468 Cell firstCell = KeyValueUtil.createFirstOnRow(row, family, qualifier);
469
470 SortedSet<Cell> snSs = snapshotSection.getCellSkipListSet().tailSet(firstCell);
471 if (!snSs.isEmpty()) {
472 Cell snc = snSs.first();
473
474 if (CellUtil.matchingRow(snc, firstCell) && CellUtil.matchingQualifier(snc, firstCell)) {
475 if (snc.getTimestamp() == now) {
476
477 now += 1;
478 }
479 }
480 }
481
482
483
484
485
486
487
488 SortedSet<Cell> ss = activeSection.getCellSkipListSet().tailSet(firstCell);
489 for (Cell cell : ss) {
490
491 if (!CellUtil.matchingColumn(cell, family, qualifier)
492 || !CellUtil.matchingRow(cell, firstCell)) {
493 break;
494 }
495
496
497 if (cell.getTypeByte() == KeyValue.Type.Put.getCode() &&
498 cell.getTimestamp() > now && CellUtil.matchingQualifier(firstCell, cell)) {
499 now = cell.getTimestamp();
500 }
501 }
502
503
504
505 List<Cell> cells = new ArrayList<Cell>(1);
506 cells.add(new KeyValue(row, family, qualifier, now, Bytes.toBytes(newValue)));
507 return upsert(cells, 1L, null);
508 }
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529 @Override
530 public long upsert(Iterable<Cell> cells, long readpoint, List<Cell> removedCells) {
531 long size = 0;
532 for (Cell cell : cells) {
533 size += upsert(cell, readpoint, removedCells);
534 }
535 return size;
536 }
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552 private long upsert(Cell cell, long readpoint, List<Cell> removedCells) {
553
554
555
556
557
558
559 long addedSize = internalAdd(cell, false);
560
561
562
563 Cell firstCell = KeyValueUtil.createFirstOnRow(
564 cell.getRowArray(), cell.getRowOffset(), cell.getRowLength(),
565 cell.getFamilyArray(), cell.getFamilyOffset(), cell.getFamilyLength(),
566 cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength());
567 SortedSet<Cell> ss = activeSection.getCellSkipListSet().tailSet(firstCell);
568 Iterator<Cell> it = ss.iterator();
569
570 int versionsVisible = 0;
571 while ( it.hasNext() ) {
572 Cell cur = it.next();
573
574 if (cell == cur) {
575
576 continue;
577 }
578
579 if (CellUtil.matchingRow(cell, cur) && CellUtil.matchingQualifier(cell, cur)) {
580
581 if (cur.getTypeByte() == KeyValue.Type.Put.getCode() &&
582 cur.getSequenceId() <= readpoint) {
583 if (versionsVisible >= 1) {
584
585
586
587
588 long delta = heapSizeChange(cur, true);
589 addedSize -= delta;
590 activeSection.getHeapSize().addAndGet(-delta);
591 activeSection.getCellsCount().decrementAndGet();
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 ClassSize.ATOMIC_INTEGER);
1041
1042
1043
1044
1045
1046
1047
1048
1049 static long heapSizeChange(final Cell cell, final boolean notpresent) {
1050 return notpresent ? ClassSize.align(ClassSize.CONCURRENT_SKIPLISTMAP_ENTRY
1051 + CellUtil.estimatedHeapSizeOf(cell)) : 0;
1052 }
1053
1054 private long keySize() {
1055 return heapSize() - DEEP_OVERHEAD;
1056 }
1057
1058
1059
1060
1061
1062 @Override
1063 public long heapSize() {
1064 return activeSection.getHeapSize().get();
1065 }
1066
1067 @Override
1068 public long size() {
1069 return heapSize();
1070 }
1071
1072
1073
1074
1075
1076
1077
1078
1079 public static void main(String [] args) {
1080 RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
1081 LOG.info("vmName=" + runtime.getVmName() + ", vmVendor=" +
1082 runtime.getVmVendor() + ", vmVersion=" + runtime.getVmVersion());
1083 LOG.info("vmInputArguments=" + runtime.getInputArguments());
1084 DefaultMemStore memstore1 = new DefaultMemStore();
1085
1086 long size = 0;
1087 final int count = 10000;
1088 byte [] fam = Bytes.toBytes("col");
1089 byte [] qf = Bytes.toBytes("umn");
1090 byte [] empty = new byte[0];
1091 for (int i = 0; i < count; i++) {
1092
1093 size += memstore1.add(new KeyValue(Bytes.toBytes(i), fam, qf, i, empty));
1094 }
1095 LOG.info("memstore1 estimated size=" + size);
1096 for (int i = 0; i < count; i++) {
1097 size += memstore1.add(new KeyValue(Bytes.toBytes(i), fam, qf, i, empty));
1098 }
1099 LOG.info("memstore1 estimated size (2nd loading of same data)=" + size);
1100
1101 DefaultMemStore memstore2 = new DefaultMemStore();
1102 for (int i = 0; i < count; i++) {
1103 size += memstore2.add(new KeyValue(Bytes.toBytes(i), fam, qf, i, new byte[i]));
1104 }
1105 LOG.info("memstore2 estimated size=" + size);
1106 final int seconds = 30;
1107 LOG.info("Waiting " + seconds + " seconds while heap dump is taken");
1108 for (int i = 0; i < seconds; i++) {
1109
1110 }
1111 LOG.info("Exiting.");
1112 }
1113
1114
1115
1116
1117 @InterfaceAudience.Private
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 AtomicInteger cellCount;
1132 private final MemStoreLAB allocator;
1133
1134 static Section newSnapshotSection(final KeyValue.KVComparator c) {
1135 return new Section(c, null, 0);
1136 }
1137
1138 static Section newActiveSection(final KeyValue.KVComparator c,
1139 final Configuration conf) {
1140 return new Section(c, conf, DEEP_OVERHEAD);
1141 }
1142
1143 private Section(final KeyValue.KVComparator c,
1144 final Configuration conf, long initHeapSize) {
1145 this.cellSet = new CellSkipListSet(c);
1146 this.heapSize = new AtomicLong(initHeapSize);
1147 this.cellCount = new AtomicInteger(0);
1148 if (conf != null && conf.getBoolean(USEMSLAB_KEY, USEMSLAB_DEFAULT)) {
1149 String className = conf.get(MSLAB_CLASS_NAME, HeapMemStoreLAB.class.getName());
1150 this.allocator = ReflectionUtils.instantiateWithCustomCtor(className,
1151 new Class[]{Configuration.class}, new Object[]{conf});
1152 } else {
1153 this.allocator = null;
1154 }
1155 }
1156
1157 CellSkipListSet getCellSkipListSet() {
1158 return cellSet;
1159 }
1160
1161 TimeRangeTracker getTimeRangeTracker() {
1162 return tracker;
1163 }
1164
1165 AtomicLong getHeapSize() {
1166 return heapSize;
1167 }
1168
1169 AtomicInteger getCellsCount() {
1170 return cellCount;
1171 }
1172
1173 MemStoreLAB getMemStoreLAB() {
1174 return allocator;
1175 }
1176 }
1177 }