diff options
author | anand76 <anand1976@users.noreply.github.com> | 2024-02-16 09:21:06 -0800 |
---|---|---|
committer | Facebook GitHub Bot <facebook-github-bot@users.noreply.github.com> | 2024-02-16 09:21:06 -0800 |
commit | d2272761473082463f1f1328776ad96dc3170db1 (patch) | |
tree | 100365f2cfb8c553e4d3a6406b4f40bd03a462fe /db | |
parent | 956f1dfde3e3af13b2188173ac658feca279d773 (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.cc | 57 | ||||
-rw-r--r-- | db/db_impl/compacted_db_impl.cc | 92 | ||||
-rw-r--r-- | db/db_impl/compacted_db_impl.h | 21 | ||||
-rw-r--r-- | db/db_impl/db_impl.cc | 308 | ||||
-rw-r--r-- | db/db_impl/db_impl.h | 26 | ||||
-rw-r--r-- | db/db_test.cc | 18 | ||||
-rw-r--r-- | db/db_with_timestamp_basic_test.cc | 6 |
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 ? ×tamps[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 = ×tamp_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 +} |