17
17
#include < stdint.h>
18
18
#include < string>
19
19
#include < unordered_set>
20
+ #include < utility>
20
21
#include < vector>
21
22
22
23
#include " db/builder.h"
32
33
#include " db/prefix_filter_iterator.h"
33
34
#include " db/table_cache.h"
34
35
#include " db/table_properties_collector.h"
36
+ #include " db/tailing_iter.h"
35
37
#include " db/transaction_log_impl.h"
36
38
#include " db/version_set.h"
37
39
#include " db/write_batch_internal.h"
@@ -264,6 +266,7 @@ DBImpl::DBImpl(const Options& options, const std::string& dbname)
264
266
mem_(new MemTable(internal_comparator_, options_)),
265
267
logfile_number_(0 ),
266
268
super_version_(nullptr ),
269
+ super_version_number_(0 ),
267
270
tmp_batch_(),
268
271
bg_compaction_scheduled_(0 ),
269
272
bg_manual_only_(0 ),
@@ -1413,6 +1416,10 @@ int DBImpl::Level0StopWriteTrigger() {
1413
1416
return options_.level0_stop_writes_trigger ;
1414
1417
}
1415
1418
1419
+ uint64_t DBImpl::CurrentVersionNumber () const {
1420
+ return super_version_number_.load ();
1421
+ }
1422
+
1416
1423
Status DBImpl::Flush (const FlushOptions& options) {
1417
1424
Status status = FlushMemTable (options);
1418
1425
return status;
@@ -2652,11 +2659,14 @@ static void CleanupIteratorState(void* arg1, void* arg2) {
2652
2659
deletion_state.memtables_to_free .push_back (m);
2653
2660
}
2654
2661
}
2655
- state->version ->Unref ();
2662
+ if (state->version ) { // not set for memtable-only iterator
2663
+ state->version ->Unref ();
2664
+ }
2656
2665
// fast path FindObsoleteFiles
2657
2666
state->db ->FindObsoleteFiles (deletion_state, false , true );
2658
2667
state->mu ->Unlock ();
2659
2668
state->db ->PurgeObsoleteFiles (deletion_state);
2669
+
2660
2670
delete state;
2661
2671
}
2662
2672
} // namespace
@@ -2678,18 +2688,20 @@ Iterator* DBImpl::NewInternalIterator(const ReadOptions& options,
2678
2688
for (unsigned int i = 0 ; i < immutables.size (); i++) {
2679
2689
immutables[i]->Ref ();
2680
2690
}
2681
- // Collect iterators for files in L0 - Ln
2682
2691
versions_->current ()->Ref ();
2683
2692
version = versions_->current ();
2684
2693
mutex_.Unlock ();
2685
2694
2686
2695
std::vector<Iterator*> list;
2687
2696
list.push_back (mutable_mem->NewIterator (options));
2688
2697
cleanup->mem .push_back (mutable_mem);
2698
+
2699
+ // Collect all needed child iterators for immutable memtables
2689
2700
for (MemTable* m : immutables) {
2690
2701
list.push_back (m->NewIterator (options));
2691
2702
cleanup->mem .push_back (m);
2692
2703
}
2704
+ // Collect iterators for files in L0 - Ln
2693
2705
version->AddIterators (options, storage_options_, &list);
2694
2706
Iterator* internal_iter =
2695
2707
NewMergingIterator (&internal_comparator_, &list[0 ], list.size ());
@@ -2706,6 +2718,66 @@ Iterator* DBImpl::TEST_NewInternalIterator() {
2706
2718
return NewInternalIterator (ReadOptions (), &ignored);
2707
2719
}
2708
2720
2721
+ std::pair<Iterator*, Iterator*> DBImpl::GetTailingIteratorPair (
2722
+ const ReadOptions& options,
2723
+ uint64_t * superversion_number) {
2724
+
2725
+ MemTable* mutable_mem;
2726
+ std::vector<MemTable*> immutables;
2727
+ Version* version;
2728
+
2729
+ immutables.reserve (options_.max_write_buffer_number );
2730
+
2731
+ // get all child iterators and bump their refcounts under lock
2732
+ mutex_.Lock ();
2733
+ mutable_mem = mem_;
2734
+ mutable_mem->Ref ();
2735
+ imm_.GetMemTables (&immutables);
2736
+ for (size_t i = 0 ; i < immutables.size (); ++i) {
2737
+ immutables[i]->Ref ();
2738
+ }
2739
+ version = versions_->current ();
2740
+ version->Ref ();
2741
+ if (superversion_number != nullptr ) {
2742
+ *superversion_number = CurrentVersionNumber ();
2743
+ }
2744
+ mutex_.Unlock ();
2745
+
2746
+ Iterator* mutable_iter = mutable_mem->NewIterator (options);
2747
+ IterState* mutable_cleanup = new IterState ();
2748
+ mutable_cleanup->mem .push_back (mutable_mem);
2749
+ mutable_cleanup->db = this ;
2750
+ mutable_cleanup->mu = &mutex_;
2751
+ mutable_iter->RegisterCleanup (CleanupIteratorState, mutable_cleanup, nullptr );
2752
+
2753
+ // create a DBIter that only uses memtable content; see NewIterator()
2754
+ mutable_iter = NewDBIterator (&dbname_, env_, options_, user_comparator (),
2755
+ mutable_iter, kMaxSequenceNumber );
2756
+
2757
+ Iterator* immutable_iter;
2758
+ IterState* immutable_cleanup = new IterState ();
2759
+ std::vector<Iterator*> list;
2760
+ for (MemTable* m : immutables) {
2761
+ list.push_back (m->NewIterator (options));
2762
+ immutable_cleanup->mem .push_back (m);
2763
+ }
2764
+ version->AddIterators (options, storage_options_, &list);
2765
+ immutable_cleanup->version = version;
2766
+ immutable_cleanup->db = this ;
2767
+ immutable_cleanup->mu = &mutex_;
2768
+
2769
+ immutable_iter =
2770
+ NewMergingIterator (&internal_comparator_, &list[0 ], list.size ());
2771
+ immutable_iter->RegisterCleanup (CleanupIteratorState, immutable_cleanup,
2772
+ nullptr );
2773
+
2774
+ // create a DBIter that only uses memtable content; see NewIterator()
2775
+ immutable_iter = NewDBIterator (&dbname_, env_, options_, user_comparator (),
2776
+ immutable_iter, kMaxSequenceNumber );
2777
+
2778
+ return std::make_pair (mutable_iter, immutable_iter);
2779
+ }
2780
+
2709
2781
int64_t DBImpl::TEST_MaxNextLevelOverlappingBytes () {
2710
2782
MutexLock l (&mutex_);
2711
2783
return versions_->current ()->MaxNextLevelOverlappingBytes ();
@@ -2748,6 +2820,7 @@ DBImpl::SuperVersion* DBImpl::InstallSuperVersion(
2748
2820
new_superversion->Init (mem_, imm_, versions_->current ());
2749
2821
SuperVersion* old_superversion = super_version_;
2750
2822
super_version_ = new_superversion;
2823
+ ++super_version_number_;
2751
2824
if (old_superversion != nullptr && old_superversion->Unref ()) {
2752
2825
old_superversion->Cleanup ();
2753
2826
return old_superversion; // will let caller delete outside of mutex
@@ -2930,13 +3003,21 @@ bool DBImpl::KeyMayExist(const ReadOptions& options,
2930
3003
}
2931
3004
2932
3005
Iterator* DBImpl::NewIterator (const ReadOptions& options) {
2933
- SequenceNumber latest_snapshot;
2934
- Iterator* iter = NewInternalIterator (options, &latest_snapshot);
2935
- iter = NewDBIterator (
2936
- &dbname_, env_, options_, user_comparator (), iter,
2937
- (options.snapshot != nullptr
2938
- ? reinterpret_cast <const SnapshotImpl*>(options.snapshot )->number_
2939
- : latest_snapshot));
3006
+ Iterator* iter;
3007
+
3008
+ if (options.tailing ) {
3009
+ iter = new TailingIterator (this , options, user_comparator ());
3010
+ } else {
3011
+ SequenceNumber latest_snapshot;
3012
+ iter = NewInternalIterator (options, &latest_snapshot);
3013
+
3014
+ iter = NewDBIterator (
3015
+ &dbname_, env_, options_, user_comparator (), iter,
3016
+ (options.snapshot != nullptr
3017
+ ? reinterpret_cast <const SnapshotImpl*>(options.snapshot )->number_
3018
+ : latest_snapshot));
3019
+ }
3020
+
2940
3021
if (options.prefix ) {
2941
3022
// use extra wrapper to exclude any keys from the results which
2942
3023
// don't begin with the prefix
0 commit comments