@@ -1083,6 +1083,11 @@ Status DBImpl::RecoverLogFile(uint64_t log_number, SequenceNumber* max_sequence,
1083
1083
// Since we already recovered log_number, we want all logs
1084
1084
// with numbers `<= log_number` (includes this one) to be ignored
1085
1085
edit.SetLogNumber (log_number + 1 );
1086
+ // we must mark the next log number as used, even though it's
1087
+ // not actually used. that is because VersionSet assumes
1088
+ // VersionSet::next_file_number_ always to be strictly greater than any log
1089
+ // number
1090
+ versions_->MarkFileNumberUsed (log_number + 1 );
1086
1091
status = versions_->LogAndApply (&edit, &mutex_);
1087
1092
}
1088
1093
@@ -2676,70 +2681,53 @@ Status DBImpl::DoCompactionWork(CompactionState* compact,
2676
2681
2677
2682
namespace {
2678
2683
struct IterState {
2684
+ IterState (DBImpl* db, port::Mutex* mu, DBImpl::SuperVersion* super_version)
2685
+ : db(db), mu(mu), super_version(super_version) {}
2686
+
2687
+ DBImpl* db;
2679
2688
port::Mutex* mu;
2680
- Version* version = nullptr ;
2681
- MemTable* mem = nullptr ;
2682
- MemTableListVersion* imm = nullptr ;
2683
- DBImpl *db;
2689
+ DBImpl::SuperVersion* super_version;
2684
2690
};
2685
2691
2686
2692
static void CleanupIteratorState (void * arg1, void * arg2) {
2687
2693
IterState* state = reinterpret_cast <IterState*>(arg1);
2688
- DBImpl::DeletionState deletion_state;
2689
- state->mu ->Lock ();
2690
- if (state->mem ) { // not set for immutable iterator
2691
- MemTable* m = state->mem ->Unref ();
2692
- if (m != nullptr ) {
2693
- deletion_state.memtables_to_free .push_back (m);
2694
- }
2695
- }
2696
- if (state->version ) { // not set for memtable-only iterator
2697
- state->version ->Unref ();
2698
- }
2699
- if (state->imm ) { // not set for memtable-only iterator
2700
- state->imm ->Unref (&deletion_state.memtables_to_free );
2694
+ DBImpl::DeletionState deletion_state (state->db ->GetOptions ().
2695
+ max_write_buffer_number);
2696
+
2697
+ bool need_cleanup = state->super_version ->Unref ();
2698
+ if (need_cleanup) {
2699
+ state->mu ->Lock ();
2700
+ state->super_version ->Cleanup ();
2701
+ state->db ->FindObsoleteFiles (deletion_state, false , true );
2702
+ state->mu ->Unlock ();
2703
+
2704
+ delete state->super_version ;
2705
+ state->db ->PurgeObsoleteFiles (deletion_state);
2701
2706
}
2702
- // fast path FindObsoleteFiles
2703
- state->db ->FindObsoleteFiles (deletion_state, false , true );
2704
- state->mu ->Unlock ();
2705
- state->db ->PurgeObsoleteFiles (deletion_state);
2706
2707
2707
2708
delete state;
2708
2709
}
2709
2710
} // namespace
2710
2711
2711
2712
Iterator* DBImpl::NewInternalIterator (const ReadOptions& options,
2712
2713
SequenceNumber* latest_snapshot) {
2713
- IterState* cleanup = new IterState;
2714
- MemTable* mutable_mem;
2715
- MemTableListVersion* immutable_mems;
2716
- Version* version;
2717
-
2718
- // Collect together all needed child iterators for mem
2719
2714
mutex_.Lock ();
2720
2715
*latest_snapshot = versions_->LastSequence ();
2721
- mem_->Ref ();
2722
- mutable_mem = mem_;
2723
- // Collect together all needed child iterators for imm_
2724
- immutable_mems = imm_.current ();
2725
- immutable_mems->Ref ();
2726
- versions_->current ()->Ref ();
2727
- version = versions_->current ();
2716
+ SuperVersion* super_version = super_version_->Ref ();
2728
2717
mutex_.Unlock ();
2729
2718
2730
2719
std::vector<Iterator*> iterator_list;
2731
- iterator_list.push_back (mutable_mem->NewIterator (options));
2732
- cleanup->mem = mutable_mem;
2733
- cleanup->imm = immutable_mems;
2720
+ // Collect iterator for mutable mem
2721
+ iterator_list.push_back (super_version->mem ->NewIterator (options));
2734
2722
// Collect all needed child iterators for immutable memtables
2735
- immutable_mems ->AddIterators (options, &iterator_list);
2723
+ super_version-> imm ->AddIterators (options, &iterator_list);
2736
2724
// Collect iterators for files in L0 - Ln
2737
- version->AddIterators (options, storage_options_, &iterator_list);
2725
+ super_version->current ->AddIterators (options, storage_options_,
2726
+ &iterator_list);
2738
2727
Iterator* internal_iter = NewMergingIterator (
2739
2728
env_, &internal_comparator_, &iterator_list[0 ], iterator_list.size ());
2740
- cleanup->version = version;
2741
- cleanup->mu = &mutex_;
2742
- cleanup->db = this ;
2729
+
2730
+ IterState* cleanup = new IterState (this , &mutex_, super_version);
2743
2731
internal_iter->RegisterCleanup (CleanupIteratorState, cleanup, nullptr );
2744
2732
2745
2733
return internal_iter;
@@ -2754,53 +2742,36 @@ std::pair<Iterator*, Iterator*> DBImpl::GetTailingIteratorPair(
2754
2742
const ReadOptions& options,
2755
2743
uint64_t * superversion_number) {
2756
2744
2757
- MemTable* mutable_mem;
2758
- MemTableListVersion* immutable_mems;
2759
- Version* version;
2760
-
2761
- // get all child iterators and bump their refcounts under lock
2762
2745
mutex_.Lock ();
2763
- mutable_mem = mem_;
2764
- mutable_mem->Ref ();
2765
- immutable_mems = imm_.current ();
2766
- immutable_mems->Ref ();
2767
- version = versions_->current ();
2768
- version->Ref ();
2746
+ SuperVersion* super_version = super_version_->Ref ();
2769
2747
if (superversion_number != nullptr ) {
2770
2748
*superversion_number = CurrentVersionNumber ();
2771
2749
}
2772
2750
mutex_.Unlock ();
2773
2751
2774
- Iterator* mutable_iter = mutable_mem->NewIterator (options);
2775
- IterState* mutable_cleanup = new IterState ();
2776
- mutable_cleanup->mem = mutable_mem;
2777
- mutable_cleanup->db = this ;
2778
- mutable_cleanup->mu = &mutex_;
2779
- mutable_iter->RegisterCleanup (CleanupIteratorState, mutable_cleanup, nullptr );
2780
-
2752
+ Iterator* mutable_iter = super_version->mem ->NewIterator (options);
2781
2753
// create a DBIter that only uses memtable content; see NewIterator()
2782
2754
mutable_iter = NewDBIterator (&dbname_, env_, options_, user_comparator (),
2783
2755
mutable_iter, kMaxSequenceNumber );
2784
2756
2785
- Iterator* immutable_iter;
2786
- IterState* immutable_cleanup = new IterState ();
2787
2757
std::vector<Iterator*> list;
2788
- immutable_mems->AddIterators (options, &list);
2789
- immutable_cleanup->imm = immutable_mems;
2790
- version->AddIterators (options, storage_options_, &list);
2791
- immutable_cleanup->version = version;
2792
- immutable_cleanup->db = this ;
2793
- immutable_cleanup->mu = &mutex_;
2794
-
2795
- immutable_iter =
2796
- NewMergingIterator (env_, &internal_comparator_, &list[0 ], list.size ());
2797
- immutable_iter->RegisterCleanup (CleanupIteratorState, immutable_cleanup,
2798
- nullptr );
2758
+ super_version->imm ->AddIterators (options, &list);
2759
+ super_version->current ->AddIterators (options, storage_options_, &list);
2760
+ Iterator* immutable_iter =
2761
+ NewMergingIterator (env_, &internal_comparator_, &list[0 ], list.size ());
2799
2762
2800
2763
// create a DBIter that only uses memtable content; see NewIterator()
2801
2764
immutable_iter = NewDBIterator (&dbname_, env_, options_, user_comparator (),
2802
2765
immutable_iter, kMaxSequenceNumber );
2803
2766
2767
+ // register cleanups
2768
+ mutable_iter->RegisterCleanup (CleanupIteratorState,
2769
+ new IterState (this , &mutex_, super_version), nullptr );
2770
+
2771
+ // bump the ref one more time since it will be Unref'ed twice
2772
+ immutable_iter->RegisterCleanup (CleanupIteratorState,
2773
+ new IterState (this , &mutex_, super_version->Ref ()), nullptr );
2774
+
2804
2775
return std::make_pair (mutable_iter, immutable_iter);
2805
2776
}
2806
2777
@@ -2946,7 +2917,6 @@ std::vector<Status> DBImpl::MultiGet(const ReadOptions& options,
2946
2917
StartPerfTimer (&snapshot_timer);
2947
2918
2948
2919
SequenceNumber snapshot;
2949
- autovector<MemTable*> to_delete;
2950
2920
2951
2921
mutex_.Lock ();
2952
2922
if (options.snapshot != nullptr ) {
@@ -2955,16 +2925,9 @@ std::vector<Status> DBImpl::MultiGet(const ReadOptions& options,
2955
2925
snapshot = versions_->LastSequence ();
2956
2926
}
2957
2927
2958
- MemTable* mem = mem_;
2959
- MemTableListVersion* imm = imm_.current ();
2960
- Version* current = versions_->current ();
2961
- mem->Ref ();
2962
- imm->Ref ();
2963
- current->Ref ();
2964
-
2965
- // Unlock while reading from files and memtables
2966
-
2928
+ SuperVersion* get_version = super_version_->Ref ();
2967
2929
mutex_.Unlock ();
2930
+
2968
2931
bool have_stat_update = false ;
2969
2932
Version::GetStats stats;
2970
2933
@@ -2990,12 +2953,14 @@ std::vector<Status> DBImpl::MultiGet(const ReadOptions& options,
2990
2953
std::string* value = &(*values)[i];
2991
2954
2992
2955
LookupKey lkey (keys[i], snapshot);
2993
- if (mem->Get (lkey, value, &s, merge_context, options_)) {
2956
+ if (get_version-> mem ->Get (lkey, value, &s, merge_context, options_)) {
2994
2957
// Done
2995
- } else if (imm->Get (lkey, value, &s, merge_context, options_)) {
2958
+ } else if (get_version->imm ->Get (lkey, value, &s, merge_context,
2959
+ options_)) {
2996
2960
// Done
2997
2961
} else {
2998
- current->Get (options, lkey, value, &s, &merge_context, &stats, options_);
2962
+ get_version->current ->Get (options, lkey, value, &s, &merge_context,
2963
+ &stats, options_);
2999
2964
have_stat_update = true ;
3000
2965
}
3001
2966
@@ -3007,19 +2972,28 @@ std::vector<Status> DBImpl::MultiGet(const ReadOptions& options,
3007
2972
// Post processing (decrement reference counts and record statistics)
3008
2973
StopWatchNano post_process_timer (env_, false );
3009
2974
StartPerfTimer (&post_process_timer);
3010
- mutex_.Lock ();
3011
- if (!options_.disable_seek_compaction &&
3012
- have_stat_update && current->UpdateStats (stats)) {
3013
- MaybeScheduleFlushOrCompaction ();
2975
+ bool delete_get_version = false ;
2976
+ if (!options_.disable_seek_compaction && have_stat_update) {
2977
+ mutex_.Lock ();
2978
+ if (get_version->current ->UpdateStats (stats)) {
2979
+ MaybeScheduleFlushOrCompaction ();
2980
+ }
2981
+ if (get_version->Unref ()) {
2982
+ get_version->Cleanup ();
2983
+ delete_get_version = true ;
2984
+ }
2985
+ mutex_.Unlock ();
2986
+ } else {
2987
+ if (get_version->Unref ()) {
2988
+ mutex_.Lock ();
2989
+ get_version->Cleanup ();
2990
+ mutex_.Unlock ();
2991
+ delete_get_version = true ;
2992
+ }
2993
+ }
2994
+ if (delete_get_version) {
2995
+ delete get_version;
3014
2996
}
3015
- MemTable* m = mem->Unref ();
3016
- imm->Unref (&to_delete);
3017
- current->Unref ();
3018
- mutex_.Unlock ();
3019
-
3020
- // free up all obsolete memtables outside the mutex
3021
- delete m;
3022
- for (MemTable* v: to_delete) delete v;
3023
2997
3024
2998
RecordTick (options_.statistics .get (), NUMBER_MULTIGET_CALLS);
3025
2999
RecordTick (options_.statistics .get (), NUMBER_MULTIGET_KEYS_READ, numKeys);
0 commit comments