Use KeyMayExist for WriteBatch-Deletes

Summary:
Introduced KeyMayExist checking during writebatch-delete and removed from Outer Delete API because it uses writebatch-delete.
Added code to skip getting Table from disk if not already present in table_cache.
Some renaming of variables.
Introduced KeyMayExistImpl which allows checking since specified sequence number in GetImpl useful to check partially written writebatch.
Changed KeyMayExist to not be pure virtual and provided a default implementation.
Expanded unit-tests in db_test to check appropriately.
Ran db_stress for 1 hour with ./db_stress --max_key=100000 --ops_per_thread=10000000 --delpercent=50 --filter_deletes=1 --statistics=1.

Test Plan: db_stress;make check

Reviewers: dhruba, haobo

Reviewed By: dhruba

CC: leveldb, xjin

Differential Revision: https://reviews.facebook.net/D11745
This commit is contained in:
Mayank Agarwal
2013-07-12 16:56:52 -07:00
parent d364eea1fc
commit bf66c10b13
16 changed files with 155 additions and 58 deletions

View File

@@ -691,7 +691,7 @@ Status DBImpl::RecoverLogFile(uint64_t log_number,
mem = new MemTable(internal_comparator_, NumberLevels());
mem->Ref();
}
status = WriteBatchInternal::InsertInto(&batch, mem);
status = WriteBatchInternal::InsertInto(&batch, mem, &options_);
MaybeIgnoreError(&status);
if (!status.ok()) {
break;
@@ -2078,13 +2078,13 @@ Status DBImpl::Get(const ReadOptions& options,
return GetImpl(options, key, value);
}
// If no_IO is true, then returns Status::NotFound if key is not in memtable,
// If no_io is true, then returns Status::NotFound if key is not in memtable,
// immutable-memtable and bloom-filters can guarantee that key is not in db,
// "value" is garbage string if no_IO is true
// "value" is garbage string if no_io is true
Status DBImpl::GetImpl(const ReadOptions& options,
const Slice& key,
std::string* value,
const bool no_IO) {
const bool no_io) {
Status s;
StopWatch sw(env_, options_.statistics, DB_GET);
@@ -2113,12 +2113,12 @@ Status DBImpl::GetImpl(const ReadOptions& options,
// s is both in/out. When in, s could either be OK or MergeInProgress.
// value will contain the current merge operand in the latter case.
LookupKey lkey(key, snapshot);
if (mem->Get(lkey, value, &s, options_, no_IO)) {
if (mem->Get(lkey, value, &s, options_, no_io)) {
// Done
} else if (imm.Get(lkey, value, &s, options_, no_IO)) {
} else if (imm.Get(lkey, value, &s, options_, no_io)) {
// Done
} else {
current->Get(options, lkey, value, &s, &stats, options_, no_IO);
current->Get(options, lkey, value, &s, &stats, options_, no_io);
have_stat_update = true;
}
mutex_.Lock();
@@ -2209,8 +2209,17 @@ std::vector<Status> DBImpl::MultiGet(const ReadOptions& options,
}
bool DBImpl::KeyMayExist(const Slice& key) {
return KeyMayExistImpl(key, versions_->LastSequence());
}
bool DBImpl::KeyMayExistImpl(const Slice& key,
const SequenceNumber read_from_seq) {
std::string value;
const Status s = GetImpl(ReadOptions(), key, &value, true);
SnapshotImpl read_from_snapshot;
read_from_snapshot.number_ = read_from_seq;
ReadOptions ropts;
ropts.snapshot = &read_from_snapshot;
const Status s = GetImpl(ropts, key, &value, true);
return !s.IsNotFound();
}
@@ -2249,10 +2258,6 @@ Status DBImpl::Merge(const WriteOptions& o, const Slice& key,
}
Status DBImpl::Delete(const WriteOptions& options, const Slice& key) {
if (options_.deletes_check_filter_first && !KeyMayExist(key)) {
RecordTick(options_.statistics, NUMBER_FILTERED_DELETES);
return Status::OK();
}
return DB::Delete(options, key);
}
@@ -2311,7 +2316,8 @@ Status DBImpl::Write(const WriteOptions& options, WriteBatch* my_batch) {
}
}
if (status.ok()) {
status = WriteBatchInternal::InsertInto(updates, mem_);
status = WriteBatchInternal::InsertInto(updates, mem_, &options_, this,
options_.filter_deletes);
if (!status.ok()) {
// Panic for in-memory corruptions
// Note that existing logic was not sound. Any partial failure writing