diff options
author | Tor Egge <Tor.Egge@yahooinc.com> | 2022-04-06 14:37:32 +0200 |
---|---|---|
committer | Tor Egge <Tor.Egge@yahooinc.com> | 2022-04-06 14:37:32 +0200 |
commit | bd880deb08ddca54e5fce63763e86af59bfbce88 (patch) | |
tree | f1f873cdcc2730ab7b34a45918b544b51ddffee0 | |
parent | 3c4cddd0b08666e497996e7f5b499e5a86fc68eb (diff) |
Add MultiValueMappingReadView, used by readers to get limited read access
to a MultiValueMapping.
21 files changed, 95 insertions, 35 deletions
diff --git a/searchlib/src/vespa/searchlib/attribute/flagattribute.cpp b/searchlib/src/vespa/searchlib/attribute/flagattribute.cpp index f6139c28d65..bd77ce0044d 100644 --- a/searchlib/src/vespa/searchlib/attribute/flagattribute.cpp +++ b/searchlib/src/vespa/searchlib/attribute/flagattribute.cpp @@ -56,7 +56,7 @@ template <typename B> std::unique_ptr<attribute::SearchContext> FlagAttributeT<B>::getSearch(QueryTermSimple::UP qTerm, const attribute::SearchContextParams &) const { - return std::make_unique<SearchContext>(std::move(qTerm), *this, this->_mvMapping); + return std::make_unique<SearchContext>(std::move(qTerm), *this, this->_mvMapping.get_read_view(this->getCommittedDocIdLimit())); } template <typename B> @@ -233,8 +233,8 @@ FlagAttributeT<B>::removeOldGenerations(vespalib::GenerationHandler::generation_ } template <typename B> -FlagAttributeT<B>::SearchContext::SearchContext(QueryTermSimple::UP qTerm, const FlagAttributeT<B> & toBeSearched, const MvMapping& mv_mapping) - : BaseSC(std::move(qTerm), toBeSearched, mv_mapping), +FlagAttributeT<B>::SearchContext::SearchContext(QueryTermSimple::UP qTerm, const FlagAttributeT<B> & toBeSearched, MvMappingReadView mv_mapping_read_view) + : BaseSC(std::move(qTerm), toBeSearched, mv_mapping_read_view), _zeroHits(false) { } diff --git a/searchlib/src/vespa/searchlib/attribute/flagattribute.h b/searchlib/src/vespa/searchlib/attribute/flagattribute.h index c1ac4e007bf..46fcf1592a9 100644 --- a/searchlib/src/vespa/searchlib/attribute/flagattribute.h +++ b/searchlib/src/vespa/searchlib/attribute/flagattribute.h @@ -19,8 +19,8 @@ private: class SearchContext : public BaseSC { public: typedef FlagAttributeT<B> Attribute; - using MvMapping = attribute::MultiValueMapping<typename B::WType>; - SearchContext(std::unique_ptr<QueryTermSimple> qTerm, const FlagAttributeT<B> & toBeSearched, const MvMapping& mv_mapping); + using MvMappingReadView = attribute::MultiValueMappingReadView<typename B::WType>; + SearchContext(std::unique_ptr<QueryTermSimple> qTerm, const FlagAttributeT<B> & toBeSearched, MvMappingReadView mv_mapping_read_view); std::unique_ptr<queryeval::SearchIterator> createIterator(fef::TermFieldMatchData * matchData, bool strict) override; diff --git a/searchlib/src/vespa/searchlib/attribute/multi_enum_search_context.h b/searchlib/src/vespa/searchlib/attribute/multi_enum_search_context.h index 44e7fe9491f..b88a10652a7 100644 --- a/searchlib/src/vespa/searchlib/attribute/multi_enum_search_context.h +++ b/searchlib/src/vespa/searchlib/attribute/multi_enum_search_context.h @@ -4,7 +4,7 @@ #include "numeric_search_context.h" #include "enumstore.h" -#include "multi_value_mapping.h" +#include "multi_value_mapping_read_view.h" namespace search::attribute { @@ -18,8 +18,8 @@ class MultiEnumSearchContext : public BaseSC { protected: using DocId = ISearchContext::DocId; - const MultiValueMapping<M>& _mv_mapping; - const EnumStoreT<T>& _enum_store; + MultiValueMappingReadView<M> _mv_mapping_read_view; + const EnumStoreT<T>& _enum_store; int32_t onFind(DocId docId, int32_t elemId, int32_t & weight) const override { return find(docId, elemId, weight); @@ -29,11 +29,11 @@ protected: return find(docId, elemId); } - MultiEnumSearchContext(typename BaseSC::MatcherType&& matcher, const AttributeVector& toBeSearched, const MultiValueMapping<M>& mv_mapping, const EnumStoreT<T>& enum_store); + MultiEnumSearchContext(typename BaseSC::MatcherType&& matcher, const AttributeVector& toBeSearched, MultiValueMappingReadView<M> mv_mapping_read_view, const EnumStoreT<T>& enum_store); public: int32_t find(DocId doc, int32_t elemId, int32_t & weight) const { - auto indices(_mv_mapping.get(doc)); + auto indices(_mv_mapping_read_view.get(doc)); for (uint32_t i(elemId); i < indices.size(); i++) { T v = _enum_store.get_value(indices[i].value_ref().load_acquire()); if (this->match(v)) { @@ -46,7 +46,7 @@ public: } int32_t find(DocId doc, int32_t elemId) const { - auto indices(_mv_mapping.get(doc)); + auto indices(_mv_mapping_read_view.get(doc)); for (uint32_t i(elemId); i < indices.size(); i++) { T v = _enum_store.get_value(indices[i].value_ref().load_acquire()); if (this->match(v)) { diff --git a/searchlib/src/vespa/searchlib/attribute/multi_enum_search_context.hpp b/searchlib/src/vespa/searchlib/attribute/multi_enum_search_context.hpp index cc1640a08b9..e7901199e50 100644 --- a/searchlib/src/vespa/searchlib/attribute/multi_enum_search_context.hpp +++ b/searchlib/src/vespa/searchlib/attribute/multi_enum_search_context.hpp @@ -9,9 +9,9 @@ namespace search::attribute { template <typename T, typename BaseSC, typename M> -MultiEnumSearchContext<T, BaseSC, M>::MultiEnumSearchContext(typename BaseSC::MatcherType&& matcher, const AttributeVector& toBeSearched, const MultiValueMapping<M>& mv_mapping, const EnumStoreT<T>& enum_store) +MultiEnumSearchContext<T, BaseSC, M>::MultiEnumSearchContext(typename BaseSC::MatcherType&& matcher, const AttributeVector& toBeSearched, MultiValueMappingReadView<M> mv_mapping_read_view, const EnumStoreT<T>& enum_store) : BaseSC(toBeSearched, std::move(matcher)), - _mv_mapping(mv_mapping), + _mv_mapping_read_view(mv_mapping_read_view), _enum_store(enum_store) { } diff --git a/searchlib/src/vespa/searchlib/attribute/multi_numeric_enum_search_context.h b/searchlib/src/vespa/searchlib/attribute/multi_numeric_enum_search_context.h index b70ce2459ee..fe05afc606f 100644 --- a/searchlib/src/vespa/searchlib/attribute/multi_numeric_enum_search_context.h +++ b/searchlib/src/vespa/searchlib/attribute/multi_numeric_enum_search_context.h @@ -16,7 +16,7 @@ template <typename T, typename M> class MultiNumericEnumSearchContext : public MultiEnumSearchContext<T, NumericSearchContext<NumericRangeMatcher<T>>, M> { public: - MultiNumericEnumSearchContext(std::unique_ptr<QueryTermSimple> qTerm, const AttributeVector& toBeSearched, const MultiValueMapping<M>& mv_mapping, const EnumStoreT<T>& enum_store); + MultiNumericEnumSearchContext(std::unique_ptr<QueryTermSimple> qTerm, const AttributeVector& toBeSearched, MultiValueMappingReadView<M> mv_mapping_read_view, const EnumStoreT<T>& enum_store); }; } diff --git a/searchlib/src/vespa/searchlib/attribute/multi_numeric_enum_search_context.hpp b/searchlib/src/vespa/searchlib/attribute/multi_numeric_enum_search_context.hpp index 9780aa7a507..f4f2c2407fc 100644 --- a/searchlib/src/vespa/searchlib/attribute/multi_numeric_enum_search_context.hpp +++ b/searchlib/src/vespa/searchlib/attribute/multi_numeric_enum_search_context.hpp @@ -8,8 +8,8 @@ namespace search::attribute { template <typename T, typename M> -MultiNumericEnumSearchContext<T, M>::MultiNumericEnumSearchContext(std::unique_ptr<QueryTermSimple> qTerm, const AttributeVector& toBeSearched, const MultiValueMapping<M>& mv_mapping, const EnumStoreT<T>& enum_store) - : MultiEnumSearchContext<T, NumericSearchContext<NumericRangeMatcher<T>>, M>(NumericRangeMatcher<T>(*qTerm), toBeSearched, mv_mapping, enum_store) +MultiNumericEnumSearchContext<T, M>::MultiNumericEnumSearchContext(std::unique_ptr<QueryTermSimple> qTerm, const AttributeVector& toBeSearched, MultiValueMappingReadView<M> mv_mapping_read_view, const EnumStoreT<T>& enum_store) + : MultiEnumSearchContext<T, NumericSearchContext<NumericRangeMatcher<T>>, M>(NumericRangeMatcher<T>(*qTerm), toBeSearched, mv_mapping_read_view, enum_store) { } diff --git a/searchlib/src/vespa/searchlib/attribute/multi_numeric_search_context.h b/searchlib/src/vespa/searchlib/attribute/multi_numeric_search_context.h index 7d43e195d00..3649b542e87 100644 --- a/searchlib/src/vespa/searchlib/attribute/multi_numeric_search_context.h +++ b/searchlib/src/vespa/searchlib/attribute/multi_numeric_search_context.h @@ -3,7 +3,7 @@ #pragma once #include "numeric_search_context.h" -#include "multi_value_mapping.h" +#include "multi_value_mapping_read_view.h" #include "numeric_range_matcher.h" namespace search::attribute { @@ -17,7 +17,7 @@ class MultiNumericSearchContext : public NumericSearchContext<NumericRangeMatche { private: using DocId = ISearchContext::DocId; - const MultiValueMapping<M>& _mv_mapping; + MultiValueMappingReadView<M> _mv_mapping_read_view; int32_t onFind(DocId docId, int32_t elemId, int32_t& weight) const override final { return find(docId, elemId, weight); @@ -28,9 +28,9 @@ private: } public: - MultiNumericSearchContext(std::unique_ptr<QueryTermSimple> qTerm, const AttributeVector& toBeSearched, const MultiValueMapping<M>& mv_mapping); + MultiNumericSearchContext(std::unique_ptr<QueryTermSimple> qTerm, const AttributeVector& toBeSearched, MultiValueMappingReadView<M> mv_mapping_read_view); int32_t find(DocId doc, int32_t elemId, int32_t & weight) const { - auto values(_mv_mapping.get(doc)); + auto values(_mv_mapping_read_view.get(doc)); for (uint32_t i(elemId); i < values.size(); i++) { if (this->match(values[i].value())) { weight = values[i].weight(); @@ -42,7 +42,7 @@ public: } int32_t find(DocId doc, int32_t elemId) const { - auto values(_mv_mapping.get(doc)); + auto values(_mv_mapping_read_view.get(doc)); for (uint32_t i(elemId); i < values.size(); i++) { if (this->match(values[i].value())) { return i; diff --git a/searchlib/src/vespa/searchlib/attribute/multi_numeric_search_context.hpp b/searchlib/src/vespa/searchlib/attribute/multi_numeric_search_context.hpp index 8398c921ec6..15b851215f8 100644 --- a/searchlib/src/vespa/searchlib/attribute/multi_numeric_search_context.hpp +++ b/searchlib/src/vespa/searchlib/attribute/multi_numeric_search_context.hpp @@ -10,9 +10,9 @@ namespace search::attribute { template <typename T, typename M> -MultiNumericSearchContext<T, M>::MultiNumericSearchContext(std::unique_ptr<QueryTermSimple> qTerm, const AttributeVector& toBeSearched, const MultiValueMapping<M>& mv_mapping) +MultiNumericSearchContext<T, M>::MultiNumericSearchContext(std::unique_ptr<QueryTermSimple> qTerm, const AttributeVector& toBeSearched, MultiValueMappingReadView<M> mv_mapping_read_view) : NumericSearchContext<NumericRangeMatcher<T>>(toBeSearched, *qTerm, false), - _mv_mapping(mv_mapping) + _mv_mapping_read_view(mv_mapping_read_view) { } diff --git a/searchlib/src/vespa/searchlib/attribute/multi_string_enum_hint_search_context.h b/searchlib/src/vespa/searchlib/attribute/multi_string_enum_hint_search_context.h index 92650851116..3ae342be61b 100644 --- a/searchlib/src/vespa/searchlib/attribute/multi_string_enum_hint_search_context.h +++ b/searchlib/src/vespa/searchlib/attribute/multi_string_enum_hint_search_context.h @@ -17,7 +17,7 @@ class MultiStringEnumHintSearchContext : public MultiStringEnumSearchContext<M>, public EnumHintSearchContext { public: - MultiStringEnumHintSearchContext(std::unique_ptr<QueryTermSimple> qTerm, bool cased, const AttributeVector& toBeSearched, const MultiValueMapping<M>& mv_mapping, const EnumStoreT<const char*>& enum_store, uint32_t doc_id_limit, uint64_t num_values); + MultiStringEnumHintSearchContext(std::unique_ptr<QueryTermSimple> qTerm, bool cased, const AttributeVector& toBeSearched, MultiValueMappingReadView<M> mv_mapping_read_view, const EnumStoreT<const char*>& enum_store, uint32_t doc_id_limit, uint64_t num_values); ~MultiStringEnumHintSearchContext() override; }; diff --git a/searchlib/src/vespa/searchlib/attribute/multi_string_enum_hint_search_context.hpp b/searchlib/src/vespa/searchlib/attribute/multi_string_enum_hint_search_context.hpp index a6b0f3f5eb9..fc1f72c940f 100644 --- a/searchlib/src/vespa/searchlib/attribute/multi_string_enum_hint_search_context.hpp +++ b/searchlib/src/vespa/searchlib/attribute/multi_string_enum_hint_search_context.hpp @@ -6,8 +6,8 @@ namespace search::attribute { template <typename M> -MultiStringEnumHintSearchContext<M>::MultiStringEnumHintSearchContext(std::unique_ptr<QueryTermSimple> qTerm, bool cased, const AttributeVector& toBeSearched, const MultiValueMapping<M>& mv_mapping, const EnumStoreT<const char*>& enum_store, uint32_t doc_id_limit, uint64_t num_values) - : MultiStringEnumSearchContext<M>(std::move(qTerm), cased, toBeSearched, mv_mapping, enum_store), +MultiStringEnumHintSearchContext<M>::MultiStringEnumHintSearchContext(std::unique_ptr<QueryTermSimple> qTerm, bool cased, const AttributeVector& toBeSearched, MultiValueMappingReadView<M> mv_mapping_read_view, const EnumStoreT<const char*>& enum_store, uint32_t doc_id_limit, uint64_t num_values) + : MultiStringEnumSearchContext<M>(std::move(qTerm), cased, toBeSearched, mv_mapping_read_view, enum_store), EnumHintSearchContext(enum_store.get_dictionary(), doc_id_limit, num_values) { diff --git a/searchlib/src/vespa/searchlib/attribute/multi_string_enum_search_context.h b/searchlib/src/vespa/searchlib/attribute/multi_string_enum_search_context.h index a4f05a5c9cc..1787ea0086d 100644 --- a/searchlib/src/vespa/searchlib/attribute/multi_string_enum_search_context.h +++ b/searchlib/src/vespa/searchlib/attribute/multi_string_enum_search_context.h @@ -15,7 +15,7 @@ template <typename M> class MultiStringEnumSearchContext : public MultiEnumSearchContext<const char*, StringSearchContext, M> { public: - MultiStringEnumSearchContext(std::unique_ptr<QueryTermSimple> qTerm, bool cased, const AttributeVector& toBeSearched, const MultiValueMapping<M>& mv_mapping, const EnumStoreT<const char*>& enum_store); + MultiStringEnumSearchContext(std::unique_ptr<QueryTermSimple> qTerm, bool cased, const AttributeVector& toBeSearched, MultiValueMappingReadView<M> mv_mapping_read_view, const EnumStoreT<const char*>& enum_store); }; } diff --git a/searchlib/src/vespa/searchlib/attribute/multi_string_enum_search_context.hpp b/searchlib/src/vespa/searchlib/attribute/multi_string_enum_search_context.hpp index 02a740b06dc..1d74db04373 100644 --- a/searchlib/src/vespa/searchlib/attribute/multi_string_enum_search_context.hpp +++ b/searchlib/src/vespa/searchlib/attribute/multi_string_enum_search_context.hpp @@ -9,8 +9,8 @@ namespace search::attribute { template <typename M> -MultiStringEnumSearchContext<M>::MultiStringEnumSearchContext(std::unique_ptr<QueryTermSimple> qTerm, bool cased, const AttributeVector& toBeSearched, const MultiValueMapping<M>& mv_mapping, const EnumStoreT<const char*>& enum_store) - : MultiEnumSearchContext<const char*, StringSearchContext, M>(StringMatcher(std::move(qTerm), cased), toBeSearched, mv_mapping, enum_store) +MultiStringEnumSearchContext<M>::MultiStringEnumSearchContext(std::unique_ptr<QueryTermSimple> qTerm, bool cased, const AttributeVector& toBeSearched, MultiValueMappingReadView<M> mv_mapping_read_view, const EnumStoreT<const char*>& enum_store) + : MultiEnumSearchContext<const char*, StringSearchContext, M>(StringMatcher(std::move(qTerm), cased), toBeSearched, mv_mapping_read_view, enum_store) { } diff --git a/searchlib/src/vespa/searchlib/attribute/multi_value_mapping.h b/searchlib/src/vespa/searchlib/attribute/multi_value_mapping.h index 382f5b02642..16184fbe5fb 100644 --- a/searchlib/src/vespa/searchlib/attribute/multi_value_mapping.h +++ b/searchlib/src/vespa/searchlib/attribute/multi_value_mapping.h @@ -3,6 +3,7 @@ #pragma once #include "multi_value_mapping_base.h" +#include "multi_value_mapping_read_view.h" #include <vespa/vespalib/datastore/array_store.h> #include <vespa/vespalib/util/address_space.h> @@ -17,6 +18,7 @@ class MultiValueMapping : public MultiValueMappingBase public: using MultiValueType = EntryT; using RefType = RefT; + using ReadView = MultiValueMappingReadView<EntryT, RefT>; private: using ArrayRef = vespalib::ArrayRef<EntryT>; using ArrayStore = vespalib::datastore::ArrayStore<EntryT, RefT>; @@ -39,6 +41,12 @@ public: // compacting enum store (replacing old enum index with updated enum index) ArrayRef get_writable(uint32_t docId) { return _store.get_writable(_indices[docId].load_relaxed()); } + /* + * Readers holding a generation guard can call get_read_view() to + * get a read view to the multi value mapping. Array bound (read_size) must + * be specified by reader, cf. committed docid limit in attribute vectors. + */ + ReadView get_read_view(size_t read_size) const { return ReadView(_indices.get_read_view(read_size), &_store); } // Pass on hold list management to underlying store void transferHoldLists(generation_t generation) { _store.transferHoldLists(generation); } void trimHoldLists(generation_t firstUsed) { _store.trimHoldLists(firstUsed); } diff --git a/searchlib/src/vespa/searchlib/attribute/multi_value_mapping_read_view.h b/searchlib/src/vespa/searchlib/attribute/multi_value_mapping_read_view.h new file mode 100644 index 00000000000..502cc353ab9 --- /dev/null +++ b/searchlib/src/vespa/searchlib/attribute/multi_value_mapping_read_view.h @@ -0,0 +1,38 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#pragma once + +#include <vespa/vespalib/datastore/atomic_entry_ref.h> +#include <vespa/vespalib/datastore/array_store.h> +#include <vespa/vespalib/util/address_space.h> + +namespace search::attribute { + +/** + * Class for mapping from from document id to an array of values as reader. + */ +template <typename EntryT, typename RefT = vespalib::datastore::EntryRefT<19> > +class MultiValueMappingReadView +{ + using AtomicEntryRef = vespalib::datastore::AtomicEntryRef; + using Indices = vespalib::ConstArrayRef<AtomicEntryRef>; + using ArrayStore = vespalib::datastore::ArrayStore<EntryT, RefT>; + + Indices _indices; + const ArrayStore* _store; +public: + constexpr MultiValueMappingReadView() + : _indices(), + _store(nullptr) + { + } + MultiValueMappingReadView(Indices indices, const ArrayStore* store) + : _indices(indices), + _store(store) + { + } + vespalib::ConstArrayRef<EntryT> get(uint32_t doc_id) const { return _store->get(_indices[doc_id].load_acquire()); } + bool valid() const noexcept { return _store != nullptr; } +}; + +} diff --git a/searchlib/src/vespa/searchlib/attribute/multinumericattribute.hpp b/searchlib/src/vespa/searchlib/attribute/multinumericattribute.hpp index 57a7c6a3b14..d31f3ddd450 100644 --- a/searchlib/src/vespa/searchlib/attribute/multinumericattribute.hpp +++ b/searchlib/src/vespa/searchlib/attribute/multinumericattribute.hpp @@ -171,7 +171,7 @@ MultiValueNumericAttribute<B, M>::getSearch(QueryTermSimple::UP qTerm, const attribute::SearchContextParams & params) const { (void) params; - return std::make_unique<attribute::MultiNumericSearchContext<T, M>>(std::move(qTerm), *this, this->_mvMapping); + return std::make_unique<attribute::MultiNumericSearchContext<T, M>>(std::move(qTerm), *this, this->_mvMapping.get_read_view(this->getCommittedDocIdLimit())); } diff --git a/searchlib/src/vespa/searchlib/attribute/multinumericenumattribute.hpp b/searchlib/src/vespa/searchlib/attribute/multinumericenumattribute.hpp index 201bff48be7..052322fd0e2 100644 --- a/searchlib/src/vespa/searchlib/attribute/multinumericenumattribute.hpp +++ b/searchlib/src/vespa/searchlib/attribute/multinumericenumattribute.hpp @@ -121,7 +121,8 @@ MultiValueNumericEnumAttribute<B, M>::getSearch(QueryTermSimple::UP qTerm, const attribute::SearchContextParams & params) const { (void) params; - return std::make_unique<attribute::MultiNumericEnumSearchContext<T, M>>(std::move(qTerm), *this, this->_mvMapping, this->_enumStore); + auto doc_id_limit = this->getCommittedDocIdLimit(); + return std::make_unique<attribute::MultiNumericEnumSearchContext<T, M>>(std::move(qTerm), *this, this->_mvMapping.get_read_view(doc_id_limit), this->_enumStore); } } // namespace search diff --git a/searchlib/src/vespa/searchlib/attribute/multinumericpostattribute.hpp b/searchlib/src/vespa/searchlib/attribute/multinumericpostattribute.hpp index 688bcaf1825..97912614551 100644 --- a/searchlib/src/vespa/searchlib/attribute/multinumericpostattribute.hpp +++ b/searchlib/src/vespa/searchlib/attribute/multinumericpostattribute.hpp @@ -78,7 +78,8 @@ MultiValueNumericPostingAttribute<B, M>::getSearch(QueryTermSimpleUP qTerm, { using BaseSC = attribute::MultiNumericEnumSearchContext<typename B::BaseClass::BaseType, M>; using SC = attribute::NumericPostingSearchContext<BaseSC, SelfType, int32_t>; - BaseSC base_sc(std::move(qTerm), *this, this->_mvMapping, this->_enumStore); + auto doc_id_limit = this->getCommittedDocIdLimit(); + BaseSC base_sc(std::move(qTerm), *this, this->_mvMapping.get_read_view(doc_id_limit), this->_enumStore); return std::make_unique<SC>(std::move(base_sc), params, *this); } diff --git a/searchlib/src/vespa/searchlib/attribute/multistringattribute.hpp b/searchlib/src/vespa/searchlib/attribute/multistringattribute.hpp index 212a71dad74..e83d6baa9ab 100644 --- a/searchlib/src/vespa/searchlib/attribute/multistringattribute.hpp +++ b/searchlib/src/vespa/searchlib/attribute/multistringattribute.hpp @@ -43,7 +43,8 @@ MultiValueStringAttributeT<B, M>::getSearch(QueryTermSimpleUP qTerm, const attribute::SearchContextParams &) const { bool cased = this->get_match_is_cased(); - return std::make_unique<attribute::MultiStringEnumHintSearchContext<M>>(std::move(qTerm), cased, *this, this->_mvMapping, this->_enumStore, this->getCommittedDocIdLimit(), this->getStatus().getNumValues()); + auto doc_id_limit = this->getCommittedDocIdLimit(); + return std::make_unique<attribute::MultiStringEnumHintSearchContext<M>>(std::move(qTerm), cased, *this, this->_mvMapping.get_read_view(doc_id_limit), this->_enumStore, doc_id_limit, this->getStatus().getNumValues()); } } // namespace search diff --git a/searchlib/src/vespa/searchlib/attribute/multistringpostattribute.hpp b/searchlib/src/vespa/searchlib/attribute/multistringpostattribute.hpp index 2c2ac48979d..132f57e9c95 100644 --- a/searchlib/src/vespa/searchlib/attribute/multistringpostattribute.hpp +++ b/searchlib/src/vespa/searchlib/attribute/multistringpostattribute.hpp @@ -93,7 +93,8 @@ MultiValueStringPostingAttributeT<B, T>::getSearch(QueryTermSimpleUP qTerm, using BaseSC = attribute::MultiStringEnumSearchContext<T>; using SC = attribute::StringPostingSearchContext<BaseSC, SelfType, int32_t>; bool cased = this->get_match_is_cased(); - BaseSC base_sc(std::move(qTerm), cased, *this, this->_mvMapping, this->_enumStore); + auto doc_id_limit = this->getCommittedDocIdLimit(); + BaseSC base_sc(std::move(qTerm), cased, *this, this->_mvMapping.get_read_view(doc_id_limit), this->_enumStore); return std::make_unique<SC>(std::move(base_sc), params.useBitVector(), *this); } diff --git a/vespalib/src/vespa/vespalib/util/arrayref.h b/vespalib/src/vespa/vespalib/util/arrayref.h index db3b39f400d..bc1fc540a6c 100644 --- a/vespalib/src/vespa/vespalib/util/arrayref.h +++ b/vespalib/src/vespa/vespalib/util/arrayref.h @@ -42,7 +42,7 @@ public: ConstArrayRef(const SmallVector<T, N> &v) noexcept : _v(&v[0]), _sz(v.size()) { } ConstArrayRef(const ArrayRef<T> & v) noexcept : _v(&v[0]), _sz(v.size()) { } ConstArrayRef(const Array<T> &v) noexcept : _v(&v[0]), _sz(v.size()) { } - ConstArrayRef() noexcept : _v(nullptr), _sz(0) {} + constexpr ConstArrayRef() noexcept : _v(nullptr), _sz(0) {} const T & operator [] (size_t i) const { return _v[i]; } size_t size() const { return _sz; } bool empty() const { return _sz == 0; } diff --git a/vespalib/src/vespa/vespalib/util/rcuvector.h b/vespalib/src/vespa/vespalib/util/rcuvector.h index 09957d14aaf..e3e17d8edf0 100644 --- a/vespalib/src/vespa/vespalib/util/rcuvector.h +++ b/vespalib/src/vespa/vespalib/util/rcuvector.h @@ -4,6 +4,7 @@ #include "alloc.h" #include "array.h" +#include "arrayref.h" #include "generationholder.h" #include "growstrategy.h" #include "memoryusage.h" @@ -148,6 +149,15 @@ public: const T& get_elem_ref(size_t i) const noexcept { return _data[i]; } // Called from writer only + /* + * Readers holding a generation guard can call get_read_view() to + * get a read view to the rcu vector. Array bound (read_size) must + * be specified by reader, cf. committed docid limit in attribute vectors. + */ + ConstArrayRef<T> get_read_view(size_t read_size) const noexcept { + return ConstArrayRef<T>(&acquire_elem_ref(0), read_size); + } + void reset(); void shrink(size_t newSize) __attribute__((noinline)); void replaceVector(ArrayType replacement); |