summaryrefslogtreecommitdiff
path: root/db
diff options
context:
space:
mode:
authoranand76 <anand1976@users.noreply.github.com>2024-02-16 09:21:06 -0800
committerFacebook GitHub Bot <facebook-github-bot@users.noreply.github.com>2024-02-16 09:21:06 -0800
commitd2272761473082463f1f1328776ad96dc3170db1 (patch)
tree100365f2cfb8c553e4d3a6406b4f40bd03a462fe /db
parent956f1dfde3e3af13b2188173ac658feca279d773 (diff)
Deprecate some variants of Get and MultiGet (#12327)
Summary: A lot of variants of Get and MultiGet have been added to `include/rocksdb/db.h` over the years. Try to consolidate them by marking variants that don't return timestamps as deprecated. The underlying DB implementation will check and return Status::NotSupported() if it doesn't support returning timestamps and the caller asks for it. Pull Request resolved: https://github.com/facebook/rocksdb/pull/12327 Reviewed By: pdillinger Differential Revision: D53828151 Pulled By: anand1976 fbshipit-source-id: e0b5ca42d32daa2739d5f439a729815a2d4ff050
Diffstat (limited to 'db')
-rw-r--r--db/db_basic_test.cc57
-rw-r--r--db/db_impl/compacted_db_impl.cc92
-rw-r--r--db/db_impl/compacted_db_impl.h21
-rw-r--r--db/db_impl/db_impl.cc308
-rw-r--r--db/db_impl/db_impl.h26
-rw-r--r--db/db_test.cc18
-rw-r--r--db/db_with_timestamp_basic_test.cc6
7 files changed, 87 insertions, 441 deletions
diff --git a/db/db_basic_test.cc b/db/db_basic_test.cc
index f20706333..9c2af8358 100644
--- a/db/db_basic_test.cc
+++ b/db/db_basic_test.cc
@@ -4504,68 +4504,35 @@ TEST_P(DBBasicTestMultiGetDeadline, MultiGetDeadlineExceeded) {
SetTimeElapseOnlySleepOnReopen(&options);
ReopenWithColumnFamilies(GetCFNames(), options);
- // Test the non-batched version of MultiGet with multiple column
- // families
+ // Test batched MultiGet with an IO delay in the first data block read.
+ // Both keys in the first CF should succeed as they're in the same data
+ // block and would form one batch, and we check for deadline between
+ // batches.
std::vector<std::string> key_str;
size_t i;
- for (i = 0; i < 5; ++i) {
+ for (i = 0; i < 10; ++i) {
key_str.emplace_back(Key(static_cast<int>(i)));
}
std::vector<ColumnFamilyHandle*> cfs(key_str.size());
- ;
std::vector<Slice> keys(key_str.size());
- std::vector<std::string> values(key_str.size());
+ std::vector<PinnableSlice> pin_values(keys.size());
+
for (i = 0; i < key_str.size(); ++i) {
- cfs[i] = handles_[i];
+ // 2 keys per CF
+ cfs[i] = handles_[i / 2];
keys[i] = Slice(key_str[i].data(), key_str[i].size());
}
-
ReadOptions ro;
ro.deadline = std::chrono::microseconds{env->NowMicros() + 10000};
ro.async_io = GetParam();
// Delay the first IO
fs->SetDelayTrigger(ro.deadline, ro.io_timeout, 0);
- std::vector<Status> statuses = dbfull()->MultiGet(ro, cfs, keys, &values);
- // The first key is successful because we check after the lookup, but
- // subsequent keys fail due to deadline exceeded
- CheckStatus(statuses, 1);
-
- // Clear the cache
- cache->SetCapacity(0);
- cache->SetCapacity(1048576);
- // Test non-batched Multiget with multiple column families and
- // introducing an IO delay in one of the middle CFs
- key_str.clear();
- for (i = 0; i < 10; ++i) {
- key_str.emplace_back(Key(static_cast<int>(i)));
- }
- cfs.resize(key_str.size());
- keys.resize(key_str.size());
- values.resize(key_str.size());
- for (i = 0; i < key_str.size(); ++i) {
- // 2 keys per CF
- cfs[i] = handles_[i / 2];
- keys[i] = Slice(key_str[i].data(), key_str[i].size());
- }
- ro.deadline = std::chrono::microseconds{env->NowMicros() + 10000};
- fs->SetDelayTrigger(ro.deadline, ro.io_timeout, 1);
- statuses = dbfull()->MultiGet(ro, cfs, keys, &values);
- CheckStatus(statuses, 3);
-
- // Test batched MultiGet with an IO delay in the first data block read.
- // Both keys in the first CF should succeed as they're in the same data
- // block and would form one batch, and we check for deadline between
- // batches.
- std::vector<PinnableSlice> pin_values(keys.size());
- cache->SetCapacity(0);
- cache->SetCapacity(1048576);
- statuses.clear();
- statuses.resize(keys.size());
- ro.deadline = std::chrono::microseconds{env->NowMicros() + 10000};
- fs->SetDelayTrigger(ro.deadline, ro.io_timeout, 0);
+ std::vector<Status> statuses(key_str.size());
dbfull()->MultiGet(ro, keys.size(), cfs.data(), keys.data(),
pin_values.data(), statuses.data());
+ // The first key is successful because we check after the lookup, but
+ // subsequent keys fail due to deadline exceeded
CheckStatus(statuses, 2);
// Similar to the previous one, but an IO delay in the third CF data block
diff --git a/db/db_impl/compacted_db_impl.cc b/db/db_impl/compacted_db_impl.cc
index 6c714e1d9..d1c2db17b 100644
--- a/db/db_impl/compacted_db_impl.cc
+++ b/db/db_impl/compacted_db_impl.cc
@@ -33,12 +33,6 @@ size_t CompactedDBImpl::FindFile(const Slice& key) {
files_.files);
}
-Status CompactedDBImpl::Get(const ReadOptions& options, ColumnFamilyHandle*,
- const Slice& key, PinnableSlice* value) {
- return Get(options, /*column_family*/ nullptr, key, value,
- /*timestamp*/ nullptr);
-}
-
Status CompactedDBImpl::Get(const ReadOptions& _read_options,
ColumnFamilyHandle*, const Slice& key,
PinnableSlice* value, std::string* timestamp) {
@@ -108,62 +102,59 @@ Status CompactedDBImpl::Get(const ReadOptions& _read_options,
return Status::NotFound();
}
-std::vector<Status> CompactedDBImpl::MultiGet(
- const ReadOptions& options, const std::vector<ColumnFamilyHandle*>&,
- const std::vector<Slice>& keys, std::vector<std::string>* values) {
- return MultiGet(options, keys, values, /*timestamps*/ nullptr);
-}
-
-std::vector<Status> CompactedDBImpl::MultiGet(
- const ReadOptions& _read_options, const std::vector<ColumnFamilyHandle*>&,
- const std::vector<Slice>& keys, std::vector<std::string>* values,
- std::vector<std::string>* timestamps) {
+void CompactedDBImpl::MultiGet(const ReadOptions& _read_options,
+ size_t num_keys,
+ ColumnFamilyHandle** /*column_families*/,
+ const Slice* keys, PinnableSlice* values,
+ std::string* timestamps, Status* statuses,
+ const bool /*sorted_input*/) {
assert(user_comparator_);
- size_t num_keys = keys.size();
+ Status s;
if (_read_options.io_activity != Env::IOActivity::kUnknown &&
_read_options.io_activity != Env::IOActivity::kMultiGet) {
- Status s = Status::InvalidArgument(
+ s = Status::InvalidArgument(
"Can only call MultiGet with `ReadOptions::io_activity` is "
"`Env::IOActivity::kUnknown` or `Env::IOActivity::kMultiGet`");
- return std::vector<Status>(num_keys, s);
}
ReadOptions read_options(_read_options);
- if (read_options.io_activity == Env::IOActivity::kUnknown) {
- read_options.io_activity = Env::IOActivity::kMultiGet;
- }
-
- if (read_options.timestamp) {
- Status s =
- FailIfTsMismatchCf(DefaultColumnFamily(), *(read_options.timestamp));
- if (!s.ok()) {
- return std::vector<Status>(num_keys, s);
+ if (s.ok()) {
+ if (read_options.io_activity == Env::IOActivity::kUnknown) {
+ read_options.io_activity = Env::IOActivity::kMultiGet;
}
- if (read_options.timestamp->size() > 0) {
- s = FailIfReadCollapsedHistory(cfd_, cfd_->GetSuperVersion(),
- *(read_options.timestamp));
- if (!s.ok()) {
- return std::vector<Status>(num_keys, s);
+
+ if (read_options.timestamp) {
+ s = FailIfTsMismatchCf(DefaultColumnFamily(), *(read_options.timestamp));
+ if (s.ok()) {
+ if (read_options.timestamp->size() > 0) {
+ s = FailIfReadCollapsedHistory(cfd_, cfd_->GetSuperVersion(),
+ *(read_options.timestamp));
+ }
}
+ } else {
+ s = FailIfCfHasTs(DefaultColumnFamily());
}
- } else {
- Status s = FailIfCfHasTs(DefaultColumnFamily());
- if (!s.ok()) {
- return std::vector<Status>(num_keys, s);
+ }
+
+ if (!s.ok()) {
+ for (size_t i = 0; i < num_keys; ++i) {
+ statuses[i] = s;
}
+ return;
}
// Clear the timestamps for returning results so that we can distinguish
// between tombstone or key that has never been written
if (timestamps) {
- for (auto& ts : *timestamps) {
- ts.clear();
+ for (size_t i = 0; i < num_keys; ++i) {
+ timestamps[i].clear();
}
}
GetWithTimestampReadCallback read_cb(kMaxSequenceNumber);
autovector<TableReader*, 16> reader_list;
- for (const auto& key : keys) {
+ for (size_t i = 0; i < num_keys; ++i) {
+ const Slice& key = keys[i];
LookupKey lkey(key, kMaxSequenceNumber, read_options.timestamp);
const FdWithKeyRange& f = files_.files[FindFile(lkey.user_key())];
if (user_comparator_->CompareWithoutTimestamp(
@@ -177,30 +168,26 @@ std::vector<Status> CompactedDBImpl::MultiGet(
reader_list.push_back(f.fd.table_reader);
}
}
- std::vector<Status> statuses(num_keys, Status::NotFound());
- values->resize(num_keys);
- if (timestamps) {
- timestamps->resize(num_keys);
+ for (size_t i = 0; i < num_keys; ++i) {
+ statuses[i] = Status::NotFound();
}
int idx = 0;
for (auto* r : reader_list) {
if (r != nullptr) {
- PinnableSlice pinnable_val;
- std::string& value = (*values)[idx];
+ PinnableSlice& pinnable_val = values[idx];
LookupKey lkey(keys[idx], kMaxSequenceNumber, read_options.timestamp);
- std::string* timestamp = timestamps ? &(*timestamps)[idx] : nullptr;
+ std::string* timestamp = timestamps ? &timestamps[idx] : nullptr;
GetContext get_context(
user_comparator_, nullptr, nullptr, nullptr, GetContext::kNotFound,
lkey.user_key(), &pinnable_val, /*columns=*/nullptr,
user_comparator_->timestamp_size() > 0 ? timestamp : nullptr, nullptr,
nullptr, true, nullptr, nullptr, nullptr, nullptr, &read_cb);
- Status s =
+ Status status =
r->Get(read_options, lkey.internal_key(), &get_context, nullptr);
- assert(static_cast<size_t>(idx) < statuses.size());
- if (!s.ok() && !s.IsNotFound()) {
- statuses[idx] = s;
+ assert(static_cast<size_t>(idx) < num_keys);
+ if (!status.ok() && !status.IsNotFound()) {
+ statuses[idx] = status;
} else {
- value.assign(pinnable_val.data(), pinnable_val.size());
if (get_context.State() == GetContext::kFound) {
statuses[idx] = Status::OK();
}
@@ -208,7 +195,6 @@ std::vector<Status> CompactedDBImpl::MultiGet(
}
++idx;
}
- return statuses;
}
Status CompactedDBImpl::Init(const Options& options) {
diff --git a/db/db_impl/compacted_db_impl.h b/db/db_impl/compacted_db_impl.h
index 17d8c9bfc..03853a5dd 100644
--- a/db/db_impl/compacted_db_impl.h
+++ b/db/db_impl/compacted_db_impl.h
@@ -27,26 +27,17 @@ class CompactedDBImpl : public DBImpl {
// Implementations of the DB interface
using DB::Get;
Status Get(const ReadOptions& options, ColumnFamilyHandle* column_family,
- const Slice& key, PinnableSlice* value) override;
-
- Status Get(const ReadOptions& _read_options,
- ColumnFamilyHandle* column_family, const Slice& key,
- PinnableSlice* value, std::string* timestamp) override;
+ const Slice& key, PinnableSlice* value,
+ std::string* timestamp) override;
using DB::MultiGet;
// Note that CompactedDBImpl::MultiGet is not the optimized version of
// MultiGet to use.
// TODO: optimize CompactedDBImpl::MultiGet, see DBImpl::MultiGet for details.
- std::vector<Status> MultiGet(const ReadOptions& options,
- const std::vector<ColumnFamilyHandle*>&,
- const std::vector<Slice>& keys,
- std::vector<std::string>* values) override;
-
- std::vector<Status> MultiGet(const ReadOptions& _read_options,
- const std::vector<ColumnFamilyHandle*>&,
- const std::vector<Slice>& keys,
- std::vector<std::string>* values,
- std::vector<std::string>* timestamps) override;
+ void MultiGet(const ReadOptions& options, size_t num_keys,
+ ColumnFamilyHandle** column_families, const Slice* keys,
+ PinnableSlice* values, std::string* timestamps,
+ Status* statuses, const bool sorted_input) override;
using DBImpl::Put;
Status Put(const WriteOptions& /*options*/,
diff --git a/db/db_impl/db_impl.cc b/db/db_impl/db_impl.cc
index 7c71bb752..b0465815e 100644
--- a/db/db_impl/db_impl.cc
+++ b/db/db_impl/db_impl.cc
@@ -2020,12 +2020,6 @@ ColumnFamilyHandle* DBImpl::PersistentStatsColumnFamily() const {
return persist_stats_cf_handle_;
}
-Status DBImpl::Get(const ReadOptions& read_options,
- ColumnFamilyHandle* column_family, const Slice& key,
- PinnableSlice* value) {
- return Get(read_options, column_family, key, value, /*timestamp=*/nullptr);
-}
-
Status DBImpl::GetImpl(const ReadOptions& read_options,
ColumnFamilyHandle* column_family, const Slice& key,
PinnableSlice* value) {
@@ -2497,250 +2491,6 @@ Status DBImpl::GetImpl(const ReadOptions& read_options, const Slice& key,
return s;
}
-std::vector<Status> DBImpl::MultiGet(
- const ReadOptions& read_options,
- const std::vector<ColumnFamilyHandle*>& column_family,
- const std::vector<Slice>& keys, std::vector<std::string>* values) {
- return MultiGet(read_options, column_family, keys, values,
- /*timestamps=*/nullptr);
-}
-
-std::vector<Status> DBImpl::MultiGet(
- const ReadOptions& _read_options,
- const std::vector<ColumnFamilyHandle*>& column_family,
- const std::vector<Slice>& keys, std::vector<std::string>* values,
- std::vector<std::string>* timestamps) {
- PERF_CPU_TIMER_GUARD(get_cpu_nanos, immutable_db_options_.clock);
- StopWatch sw(immutable_db_options_.clock, stats_, DB_MULTIGET);
- PERF_TIMER_GUARD(get_snapshot_time);
-
- size_t num_keys = keys.size();
- assert(column_family.size() == num_keys);
- std::vector<Status> stat_list(num_keys);
-
- if (_read_options.io_activity != Env::IOActivity::kUnknown &&
- _read_options.io_activity != Env::IOActivity::kMultiGet) {
- Status s = Status::InvalidArgument(
- "Can only call MultiGet with `ReadOptions::io_activity` is "
- "`Env::IOActivity::kUnknown` or `Env::IOActivity::kMultiGet`");
-
- for (size_t i = 0; i < num_keys; ++i) {
- stat_list[i] = s;
- }
- return stat_list;
- }
-
- ReadOptions read_options(_read_options);
- if (read_options.io_activity == Env::IOActivity::kUnknown) {
- read_options.io_activity = Env::IOActivity::kMultiGet;
- }
-
- bool should_fail = false;
- for (size_t i = 0; i < num_keys; ++i) {
- assert(column_family[i]);
- if (read_options.timestamp) {
- stat_list[i] =
- FailIfTsMismatchCf(column_family[i], *(read_options.timestamp));
- if (!stat_list[i].ok()) {
- should_fail = true;
- }
- } else {
- stat_list[i] = FailIfCfHasTs(column_family[i]);
- if (!stat_list[i].ok()) {
- should_fail = true;
- }
- }
- }
-
- if (should_fail) {
- for (auto& s : stat_list) {
- if (s.ok()) {
- s = Status::Incomplete(
- "DB not queried due to invalid argument(s) in the same MultiGet");
- }
- }
- return stat_list;
- }
-
- if (tracer_) {
- // TODO: This mutex should be removed later, to improve performance when
- // tracing is enabled.
- InstrumentedMutexLock lock(&trace_mutex_);
- if (tracer_) {
- // TODO: maybe handle the tracing status?
- tracer_->MultiGet(column_family, keys).PermitUncheckedError();
- }
- }
-
- UnorderedMap<uint32_t, MultiGetColumnFamilyData> multiget_cf_data(
- column_family.size());
- for (auto cf : column_family) {
- auto cfh = static_cast_with_check<ColumnFamilyHandleImpl>(cf);
- auto cfd = cfh->cfd();
- if (multiget_cf_data.find(cfd->GetID()) == multiget_cf_data.end()) {
- multiget_cf_data.emplace(cfd->GetID(),
- MultiGetColumnFamilyData(cfh, nullptr));
- }
- }
-
- std::function<MultiGetColumnFamilyData*(
- UnorderedMap<uint32_t, MultiGetColumnFamilyData>::iterator&)>
- iter_deref_lambda =
- [](UnorderedMap<uint32_t, MultiGetColumnFamilyData>::iterator&
- cf_iter) { return &cf_iter->second; };
-
- SequenceNumber consistent_seqnum;
- bool sv_from_thread_local;
- Status status =
- MultiCFSnapshot<UnorderedMap<uint32_t, MultiGetColumnFamilyData>>(
- read_options, nullptr, iter_deref_lambda, &multiget_cf_data,
- &consistent_seqnum, &sv_from_thread_local);
-
- if (!status.ok()) {
- for (auto& s : stat_list) {
- if (s.ok()) {
- s = status;
- }
- }
- return stat_list;
- }
-
- TEST_SYNC_POINT("DBImpl::MultiGet:AfterGetSeqNum1");
- TEST_SYNC_POINT("DBImpl::MultiGet:AfterGetSeqNum2");
-
- // Contain a list of merge operations if merge occurs.
- MergeContext merge_context;
-
- // Note: this always resizes the values array
- values->resize(num_keys);
- if (timestamps) {
- timestamps->resize(num_keys);
- }
-
- // Keep track of bytes that we read for statistics-recording later
- uint64_t bytes_read = 0;
- PERF_TIMER_STOP(get_snapshot_time);
-
- // For each of the given keys, apply the entire "get" process as follows:
- // First look in the memtable, then in the immutable memtable (if any).
- // s is both in/out. When in, s could either be OK or MergeInProgress.
- // merge_operands will contain the sequence of merges in the latter case.
- size_t num_found = 0;
- size_t keys_read;
- uint64_t curr_value_size = 0;
-
- GetWithTimestampReadCallback timestamp_read_callback(0);
- ReadCallback* read_callback = nullptr;
- if (read_options.timestamp && read_options.timestamp->size() > 0) {
- timestamp_read_callback.Refresh(consistent_seqnum);
- read_callback = &timestamp_read_callback;
- }
-
- for (keys_read = 0; keys_read < num_keys; ++keys_read) {
- merge_context.Clear();
- Status& s = stat_list[keys_read];
- std::string* value = &(*values)[keys_read];
- std::string* timestamp = timestamps ? &(*timestamps)[keys_read] : nullptr;
-
- LookupKey lkey(keys[keys_read], consistent_seqnum, read_options.timestamp);
- auto cfh = static_cast_with_check<ColumnFamilyHandleImpl>(
- column_family[keys_read]);
- SequenceNumber max_covering_tombstone_seq = 0;
- auto mgd_iter = multiget_cf_data.find(cfh->cfd()->GetID());
- assert(mgd_iter != multiget_cf_data.end());
- auto mgd = mgd_iter->second;
- auto super_version = mgd.super_version;
- bool skip_memtable =
- (read_options.read_tier == kPersistedTier &&
- has_unpersisted_data_.load(std::memory_order_relaxed));
- bool done = false;
- if (!skip_memtable) {
- if (super_version->mem->Get(
- lkey, value, /*columns=*/nullptr, timestamp, &s, &merge_context,
- &max_covering_tombstone_seq, read_options,
- false /* immutable_memtable */, read_callback)) {
- done = true;
- RecordTick(stats_, MEMTABLE_HIT);
- } else if (super_version->imm->Get(lkey, value, /*columns=*/nullptr,
- timestamp, &s, &merge_context,
- &max_covering_tombstone_seq,
- read_options, read_callback)) {
- done = true;
- RecordTick(stats_, MEMTABLE_HIT);
- }
- }
- if (!done) {
- PinnableSlice pinnable_val;
- PERF_TIMER_GUARD(get_from_output_files_time);
- PinnedIteratorsManager pinned_iters_mgr;
- super_version->current->Get(read_options, lkey, &pinnable_val,
- /*columns=*/nullptr, timestamp, &s,
- &merge_context, &max_covering_tombstone_seq,
- &pinned_iters_mgr, /*value_found=*/nullptr,
- /*key_exists=*/nullptr,
- /*seq=*/nullptr, read_callback);
- value->assign(pinnable_val.data(), pinnable_val.size());
- RecordTick(stats_, MEMTABLE_MISS);
- }
-
- if (s.ok()) {
- const auto& merge_threshold = read_options.merge_operand_count_threshold;
- if (merge_threshold.has_value() &&
- merge_context.GetNumOperands() > merge_threshold.value()) {
- s = Status::OkMergeOperandThresholdExceeded();
- }
-
- bytes_read += value->size();
- num_found++;
-
- curr_value_size += value->size();
- if (curr_value_size > read_options.value_size_soft_limit) {
- while (++keys_read < num_keys) {
- stat_list[keys_read] = Status::Aborted();
- }
- break;
- }
- }
- if (read_options.deadline.count() &&
- immutable_db_options_.clock->NowMicros() >
- static_cast<uint64_t>(read_options.deadline.count())) {
- break;
- }
- }
-
- if (keys_read < num_keys) {
- // The only reason to break out of the loop is when the deadline is
- // exceeded
- assert(immutable_db_options_.clock->NowMicros() >
- static_cast<uint64_t>(read_options.deadline.count()));
- for (++keys_read; keys_read < num_keys; ++keys_read) {
- stat_list[keys_read] = Status::TimedOut();
- }
- }
-
- // Post processing (decrement reference counts and record statistics)
- PERF_TIMER_GUARD(get_post_process_time);
-
- for (auto mgd_iter : multiget_cf_data) {
- auto mgd = mgd_iter.second;
- if (sv_from_thread_local) {
- ReturnAndCleanupSuperVersion(mgd.cfd, mgd.super_version);
- } else {
- TEST_SYNC_POINT("DBImpl::MultiGet::BeforeLastTryUnRefSV");
- CleanupSuperVersion(mgd.super_version);
- }
- }
- RecordTick(stats_, NUMBER_MULTIGET_CALLS);
- RecordTick(stats_, NUMBER_MULTIGET_KEYS_READ, num_keys);
- RecordTick(stats_, NUMBER_MULTIGET_KEYS_FOUND, num_found);
- RecordTick(stats_, NUMBER_MULTIGET_BYTES_READ, bytes_read);
- RecordInHistogram(stats_, BYTES_PER_MULTIGET, bytes_read);
- PERF_COUNTER_ADD(multiget_read_bytes, bytes_read);
- PERF_TIMER_STOP(get_post_process_time);
-
- return stat_list;
-}
-
template <class T>
Status DBImpl::MultiCFSnapshot(
const ReadOptions& read_options, ReadCallback* callback,
@@ -2889,7 +2639,8 @@ Status DBImpl::MultiCFSnapshot(
}
}
- // Keep track of bytes that we read for statistics-recording later
+ TEST_SYNC_POINT("DBImpl::MultiCFSnapshot:AfterGetSeqNum1");
+ TEST_SYNC_POINT("DBImpl::MultiCFSnapshot:AfterGetSeqNum2");
PERF_TIMER_STOP(get_snapshot_time);
*sv_from_thread_local = !last_try;
if (!s.ok()) {
@@ -2898,14 +2649,6 @@ Status DBImpl::MultiCFSnapshot(
return s;
}
-void DBImpl::MultiGet(const ReadOptions& read_options, const size_t num_keys,
- ColumnFamilyHandle** column_families, const Slice* keys,
- PinnableSlice* values, Status* statuses,
- const bool sorted_input) {
- MultiGet(read_options, num_keys, column_families, keys, values,
- /* timestamps */ nullptr, statuses, sorted_input);
-}
-
void DBImpl::MultiGet(const ReadOptions& _read_options, const size_t num_keys,
ColumnFamilyHandle** column_families, const Slice* keys,
PinnableSlice* values, std::string* timestamps,
@@ -3122,38 +2865,23 @@ void DBImpl::PrepareMultiGetKeys(
CompareKeyContext());
}
-void DBImpl::MultiGet(const ReadOptions& read_options,
- ColumnFamilyHandle* column_family, const size_t num_keys,
- const Slice* keys, PinnableSlice* values,
- Status* statuses, const bool sorted_input) {
- MultiGet(read_options, column_family, num_keys, keys, values,
- /* timestamps */ nullptr, statuses, sorted_input);
-}
-
-void DBImpl::MultiGet(const ReadOptions& _read_options,
- ColumnFamilyHandle* column_family, const size_t num_keys,
- const Slice* keys, PinnableSlice* values,
- std::string* timestamps, Status* statuses,
- const bool sorted_input) {
- if (_read_options.io_activity != Env::IOActivity::kUnknown &&
- _read_options.io_activity != Env::IOActivity::kMultiGet) {
- Status s = Status::InvalidArgument(
- "Can only call MultiGet with `ReadOptions::io_activity` is "
- "`Env::IOActivity::kUnknown` or `Env::IOActivity::kMultiGet`");
- for (size_t i = 0; i < num_keys; ++i) {
- if (statuses[i].ok()) {
- statuses[i] = s;
- }
- }
- return;
- }
-
- ReadOptions read_options(_read_options);
- if (read_options.io_activity == Env::IOActivity::kUnknown) {
- read_options.io_activity = Env::IOActivity::kMultiGet;
+void DB::MultiGet(const ReadOptions& options, ColumnFamilyHandle* column_family,
+ const size_t num_keys, const Slice* keys,
+ PinnableSlice* values, std::string* timestamps,
+ Status* statuses, const bool sorted_input) {
+ // Use std::array, if possible, to avoid memory allocation overhead
+ if (num_keys > MultiGetContext::MAX_BATCH_SIZE) {
+ std::vector<ColumnFamilyHandle*> column_families(num_keys, column_family);
+ MultiGet(options, num_keys, column_families.data(), keys, values,
+ timestamps, statuses, sorted_input);
+ } else {
+ std::array<ColumnFamilyHandle*, MultiGetContext::MAX_BATCH_SIZE>
+ column_families;
+ std::fill(column_families.begin(), column_families.begin() + num_keys,
+ column_family);
+ MultiGet(options, num_keys, column_families.data(), keys, values,
+ timestamps, statuses, sorted_input);
}
- MultiGetCommon(read_options, column_family, num_keys, keys, values,
- /* columns */ nullptr, timestamps, statuses, sorted_input);
}
void DBImpl::MultiGetCommon(const ReadOptions& read_options,
diff --git a/db/db_impl/db_impl.h b/db/db_impl/db_impl.h
index 1601129cd..eb0f6e043 100644
--- a/db/db_impl/db_impl.h
+++ b/db/db_impl/db_impl.h
@@ -232,8 +232,6 @@ class DBImpl : public DB {
Status Write(const WriteOptions& options, WriteBatch* updates) override;
using DB::Get;
- Status Get(const ReadOptions& options, ColumnFamilyHandle* column_family,
- const Slice& key, PinnableSlice* value) override;
Status Get(const ReadOptions& _read_options,
ColumnFamilyHandle* column_family, const Slice& key,
PinnableSlice* value, std::string* timestamp) override;
@@ -261,17 +259,6 @@ class DBImpl : public DB {
}
using DB::MultiGet;
- std::vector<Status> MultiGet(
- const ReadOptions& options,
- const std::vector<ColumnFamilyHandle*>& column_family,
- const std::vector<Slice>& keys,
- std::vector<std::string>* values) override;
- std::vector<Status> MultiGet(
- const ReadOptions& _read_options,
- const std::vector<ColumnFamilyHandle*>& column_family,
- const std::vector<Slice>& keys, std::vector<std::string>* values,
- std::vector<std::string>* timestamps) override;
-
// This MultiGet is a batched version, which may be faster than calling Get
// multiple times, especially if the keys have some spatial locality that
// enables them to be queried in the same SST files/set of files. The larger
@@ -279,19 +266,6 @@ class DBImpl : public DB {
// The values and statuses parameters are arrays with number of elements
// equal to keys.size(). This allows the storage for those to be alloacted
// by the caller on the stack for small batches
- void MultiGet(const ReadOptions& options, ColumnFamilyHandle* column_family,
- const size_t num_keys, const Slice* keys, PinnableSlice* values,
- Status* statuses, const bool sorted_input = false) override;
- void MultiGet(const ReadOptions& _read_options,
- ColumnFamilyHandle* column_family, const size_t num_keys,
- const Slice* keys, PinnableSlice* values,
- std::string* timestamps, Status* statuses,
- const bool sorted_input = false) override;
-
- void MultiGet(const ReadOptions& options, const size_t num_keys,
- ColumnFamilyHandle** column_families, const Slice* keys,
- PinnableSlice* values, Status* statuses,
- const bool sorted_input = false) override;
void MultiGet(const ReadOptions& _read_options, const size_t num_keys,
ColumnFamilyHandle** column_families, const Slice* keys,
PinnableSlice* values, std::string* timestamps,
diff --git a/db/db_test.cc b/db/db_test.cc
index b1054b6c8..7f9eda724 100644
--- a/db/db_test.cc
+++ b/db/db_test.cc
@@ -3098,7 +3098,8 @@ class ModelDB : public DB {
}
using DB::Get;
Status Get(const ReadOptions& /*options*/, ColumnFamilyHandle* /*cf*/,
- const Slice& key, PinnableSlice* /*value*/) override {
+ const Slice& key, PinnableSlice* /*value*/,
+ std::string* /*timestamp*/) override {
return Status::NotSupported(key);
}
@@ -3112,14 +3113,13 @@ class ModelDB : public DB {
}
using DB::MultiGet;
- std::vector<Status> MultiGet(
- const ReadOptions& /*options*/,
- const std::vector<ColumnFamilyHandle*>& /*column_family*/,
- const std::vector<Slice>& keys,
- std::vector<std::string>* /*values*/) override {
- std::vector<Status> s(keys.size(),
- Status::NotSupported("Not implemented."));
- return s;
+ void MultiGet(const ReadOptions& /*options*/, const size_t num_keys,
+ ColumnFamilyHandle** /*column_families*/, const Slice* /*keys*/,
+ PinnableSlice* /*values*/, std::string* /*timestamps*/,
+ Status* statuses, const bool /*sorted_input*/) override {
+ for (size_t i = 0; i < num_keys; ++i) {
+ statuses[i] = Status::NotSupported("Not implemented.");
+ }
}
using DB::IngestExternalFile;
diff --git a/db/db_with_timestamp_basic_test.cc b/db/db_with_timestamp_basic_test.cc
index c7dbae20c..2d5b08832 100644
--- a/db/db_with_timestamp_basic_test.cc
+++ b/db/db_with_timestamp_basic_test.cc
@@ -2610,10 +2610,10 @@ TEST_F(DataVisibilityTest, MultiGetWithoutSnapshot) {
SyncPoint::GetInstance()->DisableProcessing();
SyncPoint::GetInstance()->LoadDependency({
- {"DBImpl::MultiGet:AfterGetSeqNum1",
+ {"DBImpl::MultiCFSnapshot:AfterGetSeqNum1",
"DataVisibilityTest::MultiGetWithoutSnapshot:BeforePut"},
{"DataVisibilityTest::MultiGetWithoutSnapshot:AfterPut",
- "DBImpl::MultiGet:AfterGetSeqNum2"},
+ "DBImpl::MultiCFSnapshot:AfterGetSeqNum2"},
});
SyncPoint::GetInstance()->EnableProcessing();
port::Thread writer_thread([this]() {
@@ -4737,4 +4737,4 @@ int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
RegisterCustomObjects(argc, argv);
return RUN_ALL_TESTS();
-} \ No newline at end of file
+}