diff options
author | Jon Bratseth <bratseth@gmail.com> | 2022-04-07 13:58:39 +0200 |
---|---|---|
committer | Jon Bratseth <bratseth@gmail.com> | 2022-04-07 13:58:39 +0200 |
commit | b68f4ba22e523c39e0ca734d7c8627477518c553 (patch) | |
tree | 6968efa48259acb6788c2edfab0858de8c8f4765 /searchlib | |
parent | a6656689f92f2bcd45c07491aada64740669d5c5 (diff) | |
parent | 4c3de59b341522a53e3ebbf8ad40bd2b12aff86e (diff) |
Merge branch 'master' into bratseth/inputs
Diffstat (limited to 'searchlib')
34 files changed, 230 insertions, 119 deletions
diff --git a/searchlib/src/tests/fef/resolver/resolver_test.cpp b/searchlib/src/tests/fef/resolver/resolver_test.cpp index 77aba1664ad..536507f3776 100644 --- a/searchlib/src/tests/fef/resolver/resolver_test.cpp +++ b/searchlib/src/tests/fef/resolver/resolver_test.cpp @@ -86,4 +86,10 @@ TEST_F("require_that_bad_input_is_handled", Fixture) { EXPECT_TRUE(dynamic_cast<RankingExpressionBlueprint *>(spec[1].blueprint.get()) != nullptr); } +TEST("require that features can be described") { + EXPECT_EQUAL(BlueprintResolver::describe_feature("featureName"), vespalib::string("rank feature 'featureName'")); + EXPECT_EQUAL(BlueprintResolver::describe_feature("rankingExpression(foo)"), vespalib::string("function 'foo'")); + EXPECT_EQUAL(BlueprintResolver::describe_feature("rankingExpression(foo@1234.5678)"), vespalib::string("function 'foo'")); +} + TEST_MAIN() { TEST_RUN_ALL(); } diff --git a/searchlib/src/vespa/searchlib/attribute/CMakeLists.txt b/searchlib/src/vespa/searchlib/attribute/CMakeLists.txt index b3aa3bd958b..2e562b4a54f 100644 --- a/searchlib/src/vespa/searchlib/attribute/CMakeLists.txt +++ b/searchlib/src/vespa/searchlib/attribute/CMakeLists.txt @@ -65,6 +65,7 @@ vespa_add_library(searchlib_attribute OBJECT loadednumericvalue.cpp loadedvalue.cpp multi_numeric_enum_search_context.cpp + multi_numeric_flag_search_context.cpp multi_numeric_search_context.cpp multi_string_enum_search_context.cpp multi_string_enum_hint_search_context.cpp diff --git a/searchlib/src/vespa/searchlib/attribute/attributeiterators.h b/searchlib/src/vespa/searchlib/attribute/attributeiterators.h index 8765e52d38a..d12c5a7eadc 100644 --- a/searchlib/src/vespa/searchlib/attribute/attributeiterators.h +++ b/searchlib/src/vespa/searchlib/attribute/attributeiterators.h @@ -333,7 +333,6 @@ template <typename SC> class FlagAttributeIteratorT : public FlagAttributeIterator { private: - using Attribute = typename SC::Attribute; void doSeek(uint32_t docId) override; protected: @@ -366,7 +365,6 @@ private: using FlagAttributeIteratorT<SC>::setDocId; using FlagAttributeIteratorT<SC>::setAtEnd; using FlagAttributeIteratorT<SC>::isAtEnd; - using Attribute = typename SC::Attribute; using Trinary=vespalib::Trinary; void doSeek(uint32_t docId) override; Trinary is_strict() const override { return Trinary::True; } diff --git a/searchlib/src/vespa/searchlib/attribute/attributeiterators.hpp b/searchlib/src/vespa/searchlib/attribute/attributeiterators.hpp index 8cde2862645..16b0c0da143 100644 --- a/searchlib/src/vespa/searchlib/attribute/attributeiterators.hpp +++ b/searchlib/src/vespa/searchlib/attribute/attributeiterators.hpp @@ -307,9 +307,8 @@ void FlagAttributeIteratorStrict<SC>::doSeek(uint32_t docId) { const SC & sc(_concreteSearchCtx); - const Attribute &attr = static_cast<const Attribute &>(sc.attribute()); for (int i = sc._low; (i <= sc._high); ++i) { - const BitVector * bv = attr.getBitVector(i); + const BitVector * bv = sc.get_bit_vector(i); if ((bv != nullptr) && !isAtEnd(docId) && bv->testBit(docId)) { setDocId(docId); return; @@ -318,7 +317,7 @@ FlagAttributeIteratorStrict<SC>::doSeek(uint32_t docId) uint32_t minNextBit(search::endDocId); for (int i = sc._low; (i <= sc._high); ++i) { - const BitVector * bv = attr.getBitVector(i); + const BitVector * bv = sc.get_bit_vector(i); if (bv != nullptr && !isAtEnd(docId)) { uint32_t nextBit = bv->getNextTrueBit(docId); minNextBit = std::min(nextBit, minNextBit); @@ -336,9 +335,8 @@ void FlagAttributeIteratorT<SC>::doSeek(uint32_t docId) { const SC & sc(_concreteSearchCtx); - const Attribute &attr = static_cast<const Attribute &>(sc.attribute()); for (int i = sc._low; (i <= sc._high); ++i) { - const BitVector * bv = attr.getBitVector(i); + const BitVector * bv = sc.get_bit_vector(i); if ((bv != nullptr) && !isAtEnd(docId) && bv->testBit(docId)) { setDocId(docId); return; @@ -351,9 +349,8 @@ void FlagAttributeIteratorT<SC>::or_hits_into(BitVector &result, uint32_t begin_id) { (void) begin_id; const SC & sc(_concreteSearchCtx); - const Attribute &attr = static_cast<const Attribute &>(sc.attribute()); for (int i = sc._low; (i <= sc._high); ++i) { - const BitVector * bv = attr.getBitVector(i); + const BitVector * bv = sc.get_bit_vector(i); if (bv != nullptr) { result.orWith(*bv); } @@ -364,9 +361,8 @@ template <typename SC> void FlagAttributeIteratorT<SC>::and_hits_into(BitVector &result, uint32_t begin_id) { const SC & sc(_concreteSearchCtx); - const Attribute &attr = static_cast<const Attribute &>(sc.attribute()); if (sc._low == sc._high) { - const BitVector * bv = attr.getBitVector(sc._low); + const BitVector * bv = sc.get_bit_vector(sc._low); if (bv != nullptr) { result.andWith(*bv); } else { @@ -383,18 +379,17 @@ template <typename SC> std::unique_ptr<BitVector> FlagAttributeIteratorT<SC>::get_hits(uint32_t begin_id) { const SC & sc(_concreteSearchCtx); - const Attribute &attr = static_cast<const Attribute &>(sc.attribute()); int i = sc._low; BitVector::UP result; for (;!result && i < sc._high; ++i) { - const BitVector * bv = attr.getBitVector(i); + const BitVector * bv = sc.get_bit_vector(i); if (bv != nullptr) { result = BitVector::create(*bv, begin_id, getEndId()); } } for (; i <= sc._high; ++i) { - const BitVector * bv = attr.getBitVector(i); + const BitVector * bv = sc.get_bit_vector(i); if (bv != nullptr) { result->orWith(*bv); } diff --git a/searchlib/src/vespa/searchlib/attribute/flagattribute.cpp b/searchlib/src/vespa/searchlib/attribute/flagattribute.cpp index f6139c28d65..346c238f0cc 100644 --- a/searchlib/src/vespa/searchlib/attribute/flagattribute.cpp +++ b/searchlib/src/vespa/searchlib/attribute/flagattribute.cpp @@ -2,11 +2,8 @@ #include "flagattribute.h" #include "load_utils.hpp" -#include "attributeiterators.h" #include "multinumericattribute.hpp" - -#include <vespa/searchlib/queryeval/emptysearch.h> -#include <vespa/searchlib/common/bitvectoriterator.h> +#include "multi_numeric_flag_search_context.h" #include <vespa/log/log.h> LOG_SETUP(".searchlib.attribute.flag_attribute"); @@ -56,7 +53,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<attribute::MultiNumericFlagSearchContext<typename B::BaseType, typename B::WType>>(std::move(qTerm), *this, this->_mvMapping.make_read_view(this->getCommittedDocIdLimit()), _bitVectors); } template <typename B> @@ -232,38 +229,6 @@ FlagAttributeT<B>::removeOldGenerations(vespalib::GenerationHandler::generation_ _bitVectorHolder.trimHoldLists(firstUsed); } -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), - _zeroHits(false) -{ -} - -template <typename B> -SearchIterator::UP -FlagAttributeT<B>::SearchContext::createIterator(fef::TermFieldMatchData * matchData, bool strict) -{ - if (this->valid()) { - if (this->_low == this->_high) { - const Attribute & attr(static_cast<const Attribute &>(this->attribute())); - const BitVector * bv(attr.getBitVector(this->_low)); - if (bv != nullptr) { - return BitVectorIterator::create(bv, attr.getCommittedDocIdLimit(), *matchData, strict); - } else { - return std::make_unique<queryeval::EmptySearch>(); - } - } else { - SearchIterator::UP flagIterator( - strict - ? new FlagAttributeIteratorStrict<typename FlagAttributeT<B>::SearchContext>(*this, matchData) - : new FlagAttributeIteratorT<typename FlagAttributeT<B>::SearchContext>(*this, matchData)); - return flagIterator; - } - } else { - return std::make_unique<queryeval::EmptySearch>(); - } -} - template class FlagAttributeT<FlagBaseImpl>; } diff --git a/searchlib/src/vespa/searchlib/attribute/flagattribute.h b/searchlib/src/vespa/searchlib/attribute/flagattribute.h index c1ac4e007bf..24bec517eb0 100644 --- a/searchlib/src/vespa/searchlib/attribute/flagattribute.h +++ b/searchlib/src/vespa/searchlib/attribute/flagattribute.h @@ -7,7 +7,6 @@ namespace search { typedef MultiValueNumericAttribute< IntegerAttributeTemplate<int8_t>, multivalue::Value<int8_t> > FlagBaseImpl; -typedef MultiValueNumericAttribute< IntegerAttributeTemplate<int8_t>, multivalue::Value<int8_t> > HugeFlagBaseImpl; template <typename B> class FlagAttributeT : public B { @@ -15,22 +14,6 @@ public: FlagAttributeT(const vespalib::string & baseFileName, const AttributeVector::Config & cfg); private: typedef AttributeVector::DocId DocId; - using BaseSC = attribute::MultiNumericSearchContext<typename B::BaseType, typename B::WType>; - 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); - - std::unique_ptr<queryeval::SearchIterator> - createIterator(fef::TermFieldMatchData * matchData, bool strict) override; - - private: - bool _zeroHits; - - template <class SC> friend class FlagAttributeIteratorT; - template <class SC> friend class FlagAttributeIteratorStrict; - }; bool onLoad(vespalib::Executor *executor) override; bool onLoadEnumerated(ReaderBase &attrReader) override; std::unique_ptr<attribute::SearchContext> @@ -50,20 +33,14 @@ private: void resizeBitVectors(uint32_t neededSize); void removeOldGenerations(vespalib::GenerationHandler::generation_t firstUsed) override; uint32_t getOffset(int8_t value) const { return value + 128; } - BitVector * getBitVector(typename B::BaseType value) const { - return _bitVectors[value + 128]; - } vespalib::GenerationHolder _bitVectorHolder; std::vector<std::shared_ptr<BitVector> > _bitVectorStore; std::vector<BitVector *> _bitVectors; uint32_t _bitVectorSize; - template <class SC> friend class FlagAttributeIteratorT; - template <class SC> friend class FlagAttributeIteratorStrict; }; typedef FlagAttributeT<FlagBaseImpl> FlagAttribute; -typedef FlagAttributeT<HugeFlagBaseImpl> HugeFlagAttribute; } // namespace search 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_flag_search_context.cpp b/searchlib/src/vespa/searchlib/attribute/multi_numeric_flag_search_context.cpp new file mode 100644 index 00000000000..1c187c5dbd6 --- /dev/null +++ b/searchlib/src/vespa/searchlib/attribute/multi_numeric_flag_search_context.cpp @@ -0,0 +1,50 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#include "multi_numeric_flag_search_context.h" +#include "attributeiterators.hpp" +#include "attributevector.h" +#include <vespa/searchcommon/attribute/multivalue.h> +#include <vespa/searchlib/common/bitvectoriterator.h> +#include <vespa/searchlib/queryeval/emptysearch.h> +#include <vespa/searchlib/query/query_term_simple.h> + +namespace search::attribute { + +using queryeval::SearchIterator; + +template <typename T, typename M> +MultiNumericFlagSearchContext<T, M>::MultiNumericFlagSearchContext(std::unique_ptr<QueryTermSimple> qTerm, const AttributeVector& toBeSearched, MultiValueMappingReadView<M> mv_mapping_read_view, vespalib::ConstArrayRef<BitVector *> bit_vectors) + : MultiNumericSearchContext<T, M>(std::move(qTerm), toBeSearched, mv_mapping_read_view), + _bit_vectors(bit_vectors), + _zeroHits(false) +{ +} + +template <typename T, typename M> +std::unique_ptr<SearchIterator> +MultiNumericFlagSearchContext<T, M>::createIterator(fef::TermFieldMatchData* matchData, bool strict) +{ + if (this->valid()) { + if (this->_low == this->_high) { + const AttributeVector & attr = this->attribute(); + const BitVector * bv(get_bit_vector(this->_low)); + if (bv != nullptr) { + return BitVectorIterator::create(bv, attr.getCommittedDocIdLimit(), *matchData, strict); + } else { + return std::make_unique<queryeval::EmptySearch>(); + } + } else { + SearchIterator::UP flagIterator( + strict + ? new FlagAttributeIteratorStrict<MultiNumericFlagSearchContext>(*this, matchData) + : new FlagAttributeIteratorT<MultiNumericFlagSearchContext>(*this, matchData)); + return flagIterator; + } + } else { + return std::make_unique<queryeval::EmptySearch>(); + } +} + +template class MultiNumericFlagSearchContext<int8_t, multivalue::Value<int8_t>>; + +} diff --git a/searchlib/src/vespa/searchlib/attribute/multi_numeric_flag_search_context.h b/searchlib/src/vespa/searchlib/attribute/multi_numeric_flag_search_context.h new file mode 100644 index 00000000000..00f7077b2d0 --- /dev/null +++ b/searchlib/src/vespa/searchlib/attribute/multi_numeric_flag_search_context.h @@ -0,0 +1,39 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#pragma once + +#include "multi_numeric_search_context.h" + +namespace search { +class BitVector; +template <class SC> class FlagAttributeIteratorT; +template <class SC> class FlagAttributeIteratorStrict; +} + +namespace search::attribute { + +/* + * MultiNumericFlagSearchContext handles the creation of search iterators for + * a query term on a multi value numeric flag attribute vector. + */ +template <typename T, typename M> +class MultiNumericFlagSearchContext : public MultiNumericSearchContext<T, M> +{ +public: + MultiNumericFlagSearchContext(std::unique_ptr<QueryTermSimple> qTerm, const AttributeVector& toBeSearched, MultiValueMappingReadView<M> mv_mapping_read_view, vespalib::ConstArrayRef<BitVector *> bit_vectors); + + std::unique_ptr<queryeval::SearchIterator> + createIterator(fef::TermFieldMatchData * matchData, bool strict) override; +private: + vespalib::ConstArrayRef<BitVector *> _bit_vectors; + bool _zeroHits; + const BitVector* get_bit_vector(T value) const { + static_assert(std::is_same_v<T, int8_t>, "Flag attribute search context is only supported for int8_t data type"); + return _bit_vectors[value + 128]; + } + + template <class SC> friend class ::search::FlagAttributeIteratorT; + template <class SC> friend class ::search::FlagAttributeIteratorStrict; +}; + +} 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..b57269d04c6 100644 --- a/searchlib/src/vespa/searchlib/attribute/multi_value_mapping.h +++ b/searchlib/src/vespa/searchlib/attribute/multi_value_mapping.h @@ -3,13 +3,14 @@ #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> namespace search::attribute { /** - * Class for mapping from from document id to an array of values. + * Class for mapping from document id to an array of values. */ template <typename EntryT, typename RefT = vespalib::datastore::EntryRefT<19> > class MultiValueMapping : public MultiValueMappingBase @@ -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 make_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 make_read_view(size_t read_size) const { return ReadView(_indices.make_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..116e069e8b4 --- /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 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..99963094366 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.make_read_view(this->getCommittedDocIdLimit())); } diff --git a/searchlib/src/vespa/searchlib/attribute/multinumericenumattribute.hpp b/searchlib/src/vespa/searchlib/attribute/multinumericenumattribute.hpp index 201bff48be7..c35a2e55ec3 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.make_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..4854728ca37 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.make_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..2d60887c23b 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.make_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..d3cd338cacb 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.make_read_view(doc_id_limit), this->_enumStore); return std::make_unique<SC>(std::move(base_sc), params.useBitVector(), *this); } diff --git a/searchlib/src/vespa/searchlib/expression/documentfieldnode.cpp b/searchlib/src/vespa/searchlib/expression/documentfieldnode.cpp index 91e5a36a7cf..f48be061d15 100644 --- a/searchlib/src/vespa/searchlib/expression/documentfieldnode.cpp +++ b/searchlib/src/vespa/searchlib/expression/documentfieldnode.cpp @@ -26,7 +26,7 @@ DocumentFieldNode::~DocumentFieldNode() = default; DocumentFieldNode::DocumentFieldNode(const DocumentFieldNode & rhs) : DocumentAccessorNode(rhs), - _fieldPath(rhs._fieldPath), + _fieldPath(), _value(rhs._value), _fieldName(rhs._fieldName), _doc(nullptr) @@ -38,7 +38,7 @@ DocumentFieldNode::operator = (const DocumentFieldNode & rhs) { if (this != &rhs) { DocumentAccessorNode::operator=(rhs); - _fieldPath = rhs._fieldPath; + _fieldPath.clear(); _value = rhs._value; _fieldName = rhs._fieldName; _doc = nullptr; @@ -146,7 +146,7 @@ void DocumentFieldNode::onDocType(const DocumentType & docType) _fieldPath.clear(); docType.buildFieldPath(_fieldPath, _fieldName); if (_fieldPath.empty()) { - throw std::runtime_error(make_string("Field %s could not be loacated in documenttype %s", _fieldName.c_str(), docType.getName().c_str())); + throw std::runtime_error(make_string("Field %s could not be located in documenttype %s", _fieldName.c_str(), docType.getName().c_str())); } } diff --git a/searchlib/src/vespa/searchlib/expression/documentfieldnode.h b/searchlib/src/vespa/searchlib/expression/documentfieldnode.h index fd3923bd4a0..e1038f73fa3 100644 --- a/searchlib/src/vespa/searchlib/expression/documentfieldnode.h +++ b/searchlib/src/vespa/searchlib/expression/documentfieldnode.h @@ -32,11 +32,13 @@ public: DECLARE_NBO_SERIALIZE; void visitMembers(vespalib::ObjectVisitor &visitor) const override; DECLARE_EXPRESSIONNODE(DocumentFieldNode); - DocumentFieldNode() : _fieldPath(), _value(), _fieldName(), _doc(NULL) { } - ~DocumentFieldNode(); - DocumentFieldNode(vespalib::stringref name) : _fieldPath(), _value(), _fieldName(name), _doc(NULL) { } + DocumentFieldNode() : _fieldPath(), _value(), _fieldName(), _doc(nullptr) { } + ~DocumentFieldNode() override; + DocumentFieldNode(vespalib::stringref name) : _fieldPath(), _value(), _fieldName(name), _doc(nullptr) { } DocumentFieldNode(const DocumentFieldNode & rhs); DocumentFieldNode & operator = (const DocumentFieldNode & rhs); + DocumentFieldNode(DocumentFieldNode && rhs) noexcept = default; + DocumentFieldNode & operator = (DocumentFieldNode && rhs) noexcept = default; const vespalib::string & getFieldName() const override { return _fieldName; } private: class Handler : public document::fieldvalue::IteratorHandler { diff --git a/searchlib/src/vespa/searchlib/fef/blueprintresolver.cpp b/searchlib/src/vespa/searchlib/fef/blueprintresolver.cpp index 2a12867dd33..731306d1bea 100644 --- a/searchlib/src/vespa/searchlib/fef/blueprintresolver.cpp +++ b/searchlib/src/vespa/searchlib/fef/blueprintresolver.cpp @@ -28,6 +28,10 @@ constexpr int TRACE_SKIP_POS = 10; using Accept = Blueprint::AcceptInput; +vespalib::string describe(const vespalib::string &feature_name) { + return BlueprintResolver::describe_feature(feature_name); +} + bool is_compatible(bool is_object, Accept accept_type) { return ((accept_type == Accept::ANY) || ((accept_type == Accept::OBJECT) == (is_object))); @@ -122,7 +126,7 @@ struct Compiler : public Blueprint::DependencyHandler { should_trace |= (i < TRACE_SKIP_POS); should_trace |= ((end - pos) < (MAX_TRACE_SIZE - TRACE_SKIP_POS)); if (should_trace) { - trace += fmt(" ... needed by rank feature '%s'\n", pos->parser.featureName().c_str()); + trace += fmt(" ... needed by %s\n", describe(pos->parser.featureName()).c_str()); } else if (i == TRACE_SKIP_POS) { trace += fmt(" (skipped %zu entries)\n", (n - MAX_TRACE_SIZE) + 1); } @@ -135,9 +139,9 @@ struct Compiler : public Blueprint::DependencyHandler { failed_set.insert(feature_name); auto trace = make_trace(skip_self); if (trace.empty()) { - LOG(warning, "invalid rank feature '%s': %s", feature_name.c_str(), reason.c_str()); + LOG(warning, "invalid %s: %s", describe(feature_name).c_str(), reason.c_str()); } else { - LOG(warning, "invalid rank feature '%s': %s\n%s", feature_name.c_str(), reason.c_str(), trace.c_str()); + LOG(warning, "invalid %s: %s\n%s", describe(feature_name).c_str(), reason.c_str(), trace.c_str()); } } probe_stack(); @@ -264,6 +268,22 @@ BlueprintResolver::BlueprintResolver(const BlueprintFactory &factory, { } +vespalib::string +BlueprintResolver::describe_feature(const vespalib::string &name) +{ + auto parser = std::make_unique<FeatureNameParser>(name); + if (parser->valid() && + (parser->baseName() == "rankingExpression") && + (parser->parameters().size() == 1) && + parser->output().empty()) + { + auto param = parser->parameters()[0]; + param = param.substr(0, param.find("@")); + return fmt("function '%s'", param.c_str()); + } + return fmt("rank feature '%s'", name.c_str()); +} + void BlueprintResolver::addSeed(vespalib::stringref feature) { diff --git a/searchlib/src/vespa/searchlib/fef/blueprintresolver.h b/searchlib/src/vespa/searchlib/fef/blueprintresolver.h index 80320ae780a..3e3b5879518 100644 --- a/searchlib/src/vespa/searchlib/fef/blueprintresolver.h +++ b/searchlib/src/vespa/searchlib/fef/blueprintresolver.h @@ -100,6 +100,12 @@ public: BlueprintResolver(const BlueprintFactory &factory, const IIndexEnvironment &indexEnv); + // Describe a feature based on its name (intended for log messages) + // + // rankingExpression(foo@hash) -> function 'foo' + // feature -> rank feature 'feature' + static vespalib::string describe_feature(const vespalib::string &name); + /** * Add a feature name to the list of seeds. During compilation, * blueprints for all seeds and dependencies will be instantiated diff --git a/searchlib/src/vespa/searchlib/fef/verify_feature.cpp b/searchlib/src/vespa/searchlib/fef/verify_feature.cpp index d61d7faef0f..85d1daffd01 100644 --- a/searchlib/src/vespa/searchlib/fef/verify_feature.cpp +++ b/searchlib/src/vespa/searchlib/fef/verify_feature.cpp @@ -19,8 +19,8 @@ bool verifyFeature(const BlueprintFactory &factory, resolver.addSeed(featureName); bool result = resolver.compile(); if (!result) { - LOG(error, "rank feature verification failed: %s (%s)", - featureName.c_str(), desc.c_str()); + LOG(error, "verification failed: %s (%s)", + BlueprintResolver::describe_feature(featureName).c_str(), desc.c_str()); } return result; } diff --git a/searchlib/src/vespa/searchlib/tensor/direct_tensor_store.cpp b/searchlib/src/vespa/searchlib/tensor/direct_tensor_store.cpp index 54f95e1c543..3f2a1bb1969 100644 --- a/searchlib/src/vespa/searchlib/tensor/direct_tensor_store.cpp +++ b/searchlib/src/vespa/searchlib/tensor/direct_tensor_store.cpp @@ -21,9 +21,10 @@ void DirectTensorStore::TensorBufferType::cleanHold(void* buffer, size_t offset, ElemCount num_elems, CleanContext clean_ctx) { TensorSP* elem = static_cast<TensorSP*>(buffer) + offset; + const auto& empty = empty_entry(); for (size_t i = 0; i < num_elems; ++i) { clean_ctx.extraBytesCleaned((*elem)->get_memory_usage().allocatedBytes()); - *elem = _emptyEntry; + *elem = empty; ++elem; } } diff --git a/searchlib/src/vespa/searchlib/tensor/direct_tensor_store.h b/searchlib/src/vespa/searchlib/tensor/direct_tensor_store.h index 776920ab930..1f112f1ea28 100644 --- a/searchlib/src/vespa/searchlib/tensor/direct_tensor_store.h +++ b/searchlib/src/vespa/searchlib/tensor/direct_tensor_store.h @@ -24,7 +24,7 @@ private: class TensorBufferType : public vespalib::datastore::BufferType<TensorSP> { private: using ParentType = BufferType<TensorSP>; - using ParentType::_emptyEntry; + using ParentType::empty_entry; using CleanContext = typename ParentType::CleanContext; public: TensorBufferType(); diff --git a/searchlib/src/vespa/searchlib/tensor/streamed_value_store.cpp b/searchlib/src/vespa/searchlib/tensor/streamed_value_store.cpp index 2e6d771a870..a668387e5bd 100644 --- a/searchlib/src/vespa/searchlib/tensor/streamed_value_store.cpp +++ b/searchlib/src/vespa/searchlib/tensor/streamed_value_store.cpp @@ -166,9 +166,10 @@ void StreamedValueStore::TensorBufferType::cleanHold(void* buffer, size_t offset, ElemCount num_elems, CleanContext clean_ctx) { TensorEntry::SP* elem = static_cast<TensorEntry::SP*>(buffer) + offset; + const auto& empty = empty_entry(); for (size_t i = 0; i < num_elems; ++i) { clean_ctx.extraBytesCleaned((*elem)->get_memory_usage().allocatedBytes()); - *elem = _emptyEntry; + *elem = empty; ++elem; } } diff --git a/searchlib/src/vespa/searchlib/tensor/streamed_value_store.h b/searchlib/src/vespa/searchlib/tensor/streamed_value_store.h index 7d83e9f3335..29201dc0e61 100644 --- a/searchlib/src/vespa/searchlib/tensor/streamed_value_store.h +++ b/searchlib/src/vespa/searchlib/tensor/streamed_value_store.h @@ -51,7 +51,7 @@ private: class TensorBufferType : public vespalib::datastore::BufferType<TensorEntry::SP> { private: using ParentType = BufferType<TensorEntry::SP>; - using ParentType::_emptyEntry; + using ParentType::empty_entry; using CleanContext = typename ParentType::CleanContext; public: TensorBufferType() noexcept; |