// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. #pragma once #include "attribute_read_guard.h" #include "attributeguard.h" #include #include #include #include #include namespace search::attribute { class BitVectorSearchCache; class ImportedAttributeVector; class ReferenceAttribute; /* * Short lived attribute vector that does not store values on its own. * * Read guards are held on * - target attribute, to ensure that reads are safe. * - target document meta store, to avoid target lids being reused. * - reference attribute, to ensure that access to lid mapping is safe. * * Extra information for direct lid to target lid mapping with * boundary check is setup during construction. */ class ImportedAttributeVectorReadGuard : public IAttributeVector, public AttributeReadGuard, public IMultiValueAttribute { public: using MetaStoreReadGuard = search::IDocumentMetaStoreContext::IReadGuard; ImportedAttributeVectorReadGuard(std::shared_ptr targetMetaStoreReadGuard, const ImportedAttributeVector &imported_attribute, bool stableEnumGuard); ~ImportedAttributeVectorReadGuard() override; const vespalib::string &getName() const override; uint32_t getNumDocs() const override; uint32_t getValueCount(uint32_t doc) const override; uint32_t getMaxValueCount() const override; largeint_t getInt(DocId doc) const override; double getFloat(DocId doc) const override; vespalib::ConstArrayRef get_raw(DocId doc) const override; EnumHandle getEnum(DocId doc) const override; uint32_t get(DocId docId, largeint_t *buffer, uint32_t sz) const override; uint32_t get(DocId docId, double *buffer, uint32_t sz) const override; uint32_t get(DocId docId, const char **buffer, uint32_t sz) const override; uint32_t get(DocId docId, EnumHandle *buffer, uint32_t sz) const override; uint32_t get(DocId docId, WeightedInt *buffer, uint32_t sz) const override; uint32_t get(DocId docId, WeightedFloat *buffer, uint32_t sz) const override; uint32_t get(DocId docId, WeightedString *buffer, uint32_t sz) const override; uint32_t get(DocId docId, WeightedConstChar *buffer, uint32_t sz) const override; uint32_t get(DocId docId, WeightedEnum *buffer, uint32_t sz) const override; bool findEnum(const char * value, EnumHandle & e) const override; std::vector findFoldedEnums(const char *value) const override; const char * getStringFromEnum(EnumHandle e) const override; std::unique_ptr createSearchContext(std::unique_ptr term, const SearchContextParams ¶ms) const override; const IDocidPostingStore* as_docid_posting_store() const override; const IDocidWithWeightPostingStore *as_docid_with_weight_posting_store() const override; const tensor::ITensorAttribute *asTensorAttribute() const override; const attribute::IMultiValueAttribute* as_multi_value_attribute() const override; BasicType::Type getBasicType() const override; size_t getFixedWidth() const override; CollectionType::Type getCollectionType() const override; bool hasEnum() const override; bool getIsFilter() const override; bool getIsFastSearch() const override; uint32_t getCommittedDocIdLimit() const override; bool isImported() const override; bool isUndefined(DocId doc) const override; template const IMultiValueReadView* make_read_view_helper(MultiValueTag tag, vespalib::Stash& stash) const; const IArrayReadView* make_read_view(ArrayTag tag, vespalib::Stash& stash) const override; const IArrayReadView* make_read_view(ArrayTag tag, vespalib::Stash& stash) const override; const IArrayReadView* make_read_view(ArrayTag tag, vespalib::Stash& stash) const override; const IArrayReadView* make_read_view(ArrayTag tag, vespalib::Stash& stash) const override; const IArrayReadView* make_read_view(ArrayTag tag, vespalib::Stash& stash) const override; const IArrayReadView* make_read_view(ArrayTag tag, vespalib::Stash& stash) const override; const IArrayReadView* make_read_view(ArrayTag tag, vespalib::Stash& stash) const override; const IWeightedSetReadView* make_read_view(WeightedSetTag tag, vespalib::Stash& stash) const override; const IWeightedSetReadView* make_read_view(WeightedSetTag tag, vespalib::Stash& stash) const override; const IWeightedSetReadView* make_read_view(WeightedSetTag tag, vespalib::Stash& stash) const override; const IWeightedSetReadView* make_read_view(WeightedSetTag tag, vespalib::Stash& stash) const override; const IWeightedSetReadView* make_read_view(WeightedSetTag tag, vespalib::Stash& stash) const override; const IWeightedSetReadView* make_read_view(WeightedSetTag tag, vespalib::Stash& stash) const override; const IWeightedSetReadView* make_read_view(WeightedSetTag tag, vespalib::Stash& stash) const override; const IArrayEnumReadView* make_read_view(ArrayEnumTag tag, vespalib::Stash& stash) const override; const IWeightedSetEnumReadView* make_read_view(WeightedSetEnumTag tag, vespalib::Stash& stash) const override; private: using AtomicTargetLid = vespalib::datastore::AtomicValueWrapper; using TargetLids = vespalib::ConstArrayRef; std::shared_ptr _target_document_meta_store_read_guard; const ImportedAttributeVector &_imported_attribute; TargetLids _targetLids; uint32_t _target_docid_limit; vespalib::GenerationHandler::Guard _reference_attribute_guard; std::unique_ptr _target_attribute_guard; const ReferenceAttribute &_reference_attribute; protected: const IAttributeVector &_target_attribute; uint32_t getTargetLid(uint32_t lid) const { // Check range to avoid reading memory beyond end of mapping array uint32_t target_lid = lid < _targetLids.size() ? _targetLids[lid].load_acquire() : 0u; // Check target range return target_lid < _target_docid_limit ? target_lid : 0u; } long onSerializeForAscendingSort(DocId doc, void * serTo, long available, const common::BlobConverter * bc) const override; long onSerializeForDescendingSort(DocId doc, void * serTo, long available, const common::BlobConverter * bc) const override; }; }