Skip to content

Commit 84f8185

Browse files
committed
Merge branch 'master' into performance
Conflicts: HISTORY.md db/db_impl.cc db/memtable.cc
2 parents d43ebd8 + 183ba01 commit 84f8185

18 files changed

+158
-142
lines changed

HISTORY.md

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
# Rocksdb Change Log
22

3-
## 2.8.0 (01/28/2014)
3+
## Unreleased
44

55
### Public API changes
66

77
* Removed arena.h from public header files.
8+
* By default, checksums are verified on every read from database
9+
10+
>>>>>>> master
811
912
## 2.7.0 (01/28/2014)
1013

db/compaction_picker.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -551,7 +551,7 @@ Compaction* UniversalCompactionPicker::PickCompaction(Version* version) {
551551
return nullptr;
552552
}
553553
Version::FileSummaryStorage tmp;
554-
Log(options_->info_log, "Universal: candidate files(%lu): %s\n",
554+
Log(options_->info_log, "Universal: candidate files(%zu): %s\n",
555555
version->files_[level].size(),
556556
version->LevelFileSummary(&tmp, 0));
557557

db/corruption_test.cc

+6-1
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,12 @@ class CorruptionTest {
9595
int bad_values = 0;
9696
int correct = 0;
9797
std::string value_space;
98-
Iterator* iter = db_->NewIterator(ReadOptions());
98+
// Do not verify checksums. If we verify checksums then the
99+
// db itself will raise errors because data is corrupted.
100+
// Instead, we want the reads to be successful and this test
101+
// will detect whether the appropriate corruptions have
102+
// occured.
103+
Iterator* iter = db_->NewIterator(ReadOptions(false, true));
99104
for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
100105
uint64_t key;
101106
Slice in(iter->key());

db/db_bench.cc

+15-2
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ DEFINE_string(benchmarks,
100100
"Must be used with merge_operator\n"
101101
"\treadrandommergerandom -- perform N random read-or-merge "
102102
"operations. Must be used with merge_operator\n"
103+
"\tnewiterator -- repeated iterator creation\n"
103104
"\tseekrandom -- N random seeks\n"
104105
"\tcrc32c -- repeated crc32c of 4K of data\n"
105106
"\tacquireload -- load N*1000 times\n"
@@ -1094,6 +1095,8 @@ class Benchmark {
10941095
method = &Benchmark::ReadRandom;
10951096
} else if (name == Slice("readmissing")) {
10961097
method = &Benchmark::ReadMissing;
1098+
} else if (name == Slice("newiterator")) {
1099+
method = &Benchmark::IteratorCreation;
10971100
} else if (name == Slice("seekrandom")) {
10981101
method = &Benchmark::SeekRandom;
10991102
} else if (name == Slice("readhot")) {
@@ -1532,14 +1535,14 @@ class Benchmark {
15321535
++count;
15331536
char* tab = std::find(linep, linep + bufferLen, columnSeparator);
15341537
if (tab == linep + bufferLen) {
1535-
fprintf(stderr, "[Error] No Key delimiter TAB at line %ld\n", count);
1538+
fprintf(stderr, "[Error] No Key delimiter TAB at line %zu\n", count);
15361539
continue;
15371540
}
15381541
Slice key(linep, tab - linep);
15391542
tab++;
15401543
char* endLine = std::find(tab, linep + bufferLen, lineSeparator);
15411544
if (endLine == linep + bufferLen) {
1542-
fprintf(stderr, "[Error] No ENTER at end of line # %ld\n", count);
1545+
fprintf(stderr, "[Error] No ENTER at end of line # %zu\n", count);
15431546
continue;
15441547
}
15451548
Slice value(tab, endLine - tab);
@@ -1883,6 +1886,16 @@ class Benchmark {
18831886
thread->stats.AddMessage(msg);
18841887
}
18851888

1889+
void IteratorCreation(ThreadState* thread) {
1890+
Duration duration(FLAGS_duration, reads_);
1891+
ReadOptions options(FLAGS_verify_checksum, true);
1892+
while (!duration.Done(1)) {
1893+
Iterator* iter = db_->NewIterator(options);
1894+
delete iter;
1895+
thread->stats.FinishedSingleOp(db_);
1896+
}
1897+
}
1898+
18861899
void SeekRandom(ThreadState* thread) {
18871900
Duration duration(FLAGS_duration, reads_);
18881901
ReadOptions options(FLAGS_verify_checksum, true);

db/db_impl.cc

+72-98
Original file line numberDiff line numberDiff line change
@@ -1083,6 +1083,11 @@ Status DBImpl::RecoverLogFile(uint64_t log_number, SequenceNumber* max_sequence,
10831083
// Since we already recovered log_number, we want all logs
10841084
// with numbers `<= log_number` (includes this one) to be ignored
10851085
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);
10861091
status = versions_->LogAndApply(&edit, &mutex_);
10871092
}
10881093

@@ -2676,70 +2681,53 @@ Status DBImpl::DoCompactionWork(CompactionState* compact,
26762681

26772682
namespace {
26782683
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;
26792688
port::Mutex* mu;
2680-
Version* version = nullptr;
2681-
MemTable* mem = nullptr;
2682-
MemTableListVersion* imm = nullptr;
2683-
DBImpl *db;
2689+
DBImpl::SuperVersion* super_version;
26842690
};
26852691

26862692
static void CleanupIteratorState(void* arg1, void* arg2) {
26872693
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);
27012706
}
2702-
// fast path FindObsoleteFiles
2703-
state->db->FindObsoleteFiles(deletion_state, false, true);
2704-
state->mu->Unlock();
2705-
state->db->PurgeObsoleteFiles(deletion_state);
27062707

27072708
delete state;
27082709
}
27092710
} // namespace
27102711

27112712
Iterator* DBImpl::NewInternalIterator(const ReadOptions& options,
27122713
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
27192714
mutex_.Lock();
27202715
*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();
27282717
mutex_.Unlock();
27292718

27302719
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));
27342722
// Collect all needed child iterators for immutable memtables
2735-
immutable_mems->AddIterators(options, &iterator_list);
2723+
super_version->imm->AddIterators(options, &iterator_list);
27362724
// 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);
27382727
Iterator* internal_iter = NewMergingIterator(
27392728
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);
27432731
internal_iter->RegisterCleanup(CleanupIteratorState, cleanup, nullptr);
27442732

27452733
return internal_iter;
@@ -2754,53 +2742,36 @@ std::pair<Iterator*, Iterator*> DBImpl::GetTailingIteratorPair(
27542742
const ReadOptions& options,
27552743
uint64_t* superversion_number) {
27562744

2757-
MemTable* mutable_mem;
2758-
MemTableListVersion* immutable_mems;
2759-
Version* version;
2760-
2761-
// get all child iterators and bump their refcounts under lock
27622745
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();
27692747
if (superversion_number != nullptr) {
27702748
*superversion_number = CurrentVersionNumber();
27712749
}
27722750
mutex_.Unlock();
27732751

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);
27812753
// create a DBIter that only uses memtable content; see NewIterator()
27822754
mutable_iter = NewDBIterator(&dbname_, env_, options_, user_comparator(),
27832755
mutable_iter, kMaxSequenceNumber);
27842756

2785-
Iterator* immutable_iter;
2786-
IterState* immutable_cleanup = new IterState();
27872757
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());
27992762

28002763
// create a DBIter that only uses memtable content; see NewIterator()
28012764
immutable_iter = NewDBIterator(&dbname_, env_, options_, user_comparator(),
28022765
immutable_iter, kMaxSequenceNumber);
28032766

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+
28042775
return std::make_pair(mutable_iter, immutable_iter);
28052776
}
28062777

@@ -2946,7 +2917,6 @@ std::vector<Status> DBImpl::MultiGet(const ReadOptions& options,
29462917
StartPerfTimer(&snapshot_timer);
29472918

29482919
SequenceNumber snapshot;
2949-
autovector<MemTable*> to_delete;
29502920

29512921
mutex_.Lock();
29522922
if (options.snapshot != nullptr) {
@@ -2955,16 +2925,9 @@ std::vector<Status> DBImpl::MultiGet(const ReadOptions& options,
29552925
snapshot = versions_->LastSequence();
29562926
}
29572927

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();
29672929
mutex_.Unlock();
2930+
29682931
bool have_stat_update = false;
29692932
Version::GetStats stats;
29702933

@@ -2990,12 +2953,14 @@ std::vector<Status> DBImpl::MultiGet(const ReadOptions& options,
29902953
std::string* value = &(*values)[i];
29912954

29922955
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_)) {
29942957
// 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_)) {
29962960
// Done
29972961
} 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_);
29992964
have_stat_update = true;
30002965
}
30012966

@@ -3007,19 +2972,28 @@ std::vector<Status> DBImpl::MultiGet(const ReadOptions& options,
30072972
// Post processing (decrement reference counts and record statistics)
30082973
StopWatchNano post_process_timer(env_, false);
30092974
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;
30142996
}
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;
30232997

30242998
RecordTick(options_.statistics.get(), NUMBER_MULTIGET_CALLS);
30252999
RecordTick(options_.statistics.get(), NUMBER_MULTIGET_KEYS_READ, numKeys);

db/db_impl.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -249,8 +249,8 @@ class DBImpl : public DB {
249249
return internal_comparator_.user_comparator();
250250
}
251251

252-
MemTable* GetMemTable() {
253-
return mem_;
252+
SuperVersion* GetSuperVersion() {
253+
return super_version_;
254254
}
255255

256256
Iterator* NewInternalIterator(const ReadOptions&,

db/db_impl_readonly.cc

+7-4
Original file line numberDiff line numberDiff line change
@@ -56,15 +56,15 @@ Status DBImplReadOnly::Get(const ReadOptions& options,
5656
const Slice& key,
5757
std::string* value) {
5858
Status s;
59-
MemTable* mem = GetMemTable();
60-
Version* current = versions_->current();
6159
SequenceNumber snapshot = versions_->LastSequence();
60+
SuperVersion* super_version = GetSuperVersion();
6261
MergeContext merge_context;
6362
LookupKey lkey(key, snapshot);
64-
if (mem->Get(lkey, value, &s, merge_context, options_)) {
63+
if (super_version->mem->Get(lkey, value, &s, merge_context, options_)) {
6564
} else {
6665
Version::GetStats stats;
67-
current->Get(options, lkey, value, &s, &merge_context, &stats, options_);
66+
super_version->current->Get(options, lkey, value, &s, &merge_context,
67+
&stats, options_);
6868
}
6969
return s;
7070
}
@@ -87,6 +87,9 @@ Status DB::OpenForReadOnly(const Options& options, const std::string& dbname,
8787
DBImplReadOnly* impl = new DBImplReadOnly(options, dbname);
8888
impl->mutex_.Lock();
8989
Status s = impl->Recover(true /* read only */, error_if_log_file_exist);
90+
if (s.ok()) {
91+
delete impl->InstallSuperVersion(new DBImpl::SuperVersion());
92+
}
9093
impl->mutex_.Unlock();
9194
if (s.ok()) {
9295
*dbptr = impl;

0 commit comments

Comments
 (0)