diff options
author | Geir Storli <geirst@oath.com> | 2018-04-19 10:40:03 +0000 |
---|---|---|
committer | Geir Storli <geirst@oath.com> | 2018-04-19 10:42:21 +0000 |
commit | 6a26d4ed5021be4ed75727167fbf194ec3faba12 (patch) | |
tree | 5567b626e4371e1a626aa77eb0d02c215675d3c8 | |
parent | 1e0a2f24d4159edf46b5b457f07b33121d7e5bbf (diff) |
Add ReadableAttributeVector interface used to create a short-lived read guard over an attribute vector.
Let AttributeVector and ImportedAttributeVector implement this interface.
19 files changed, 139 insertions, 29 deletions
diff --git a/searchcore/src/vespa/searchcore/proton/attribute/imported_attributes_context.cpp b/searchcore/src/vespa/searchcore/proton/attribute/imported_attributes_context.cpp index 7a9d877621c..8e4714d6fa2 100644 --- a/searchcore/src/vespa/searchcore/proton/attribute/imported_attributes_context.cpp +++ b/searchcore/src/vespa/searchcore/proton/attribute/imported_attributes_context.cpp @@ -2,6 +2,7 @@ #include "imported_attributes_context.h" #include "imported_attributes_repo.h" +#include <vespa/searchlib/attribute/attribute_read_guard.h> #include <vespa/searchlib/attribute/attributeguard.h> #include <vespa/searchlib/attribute/imported_attribute_vector.h> #include <vespa/vespalib/stllike/hash_map.hpp> @@ -20,12 +21,12 @@ ImportedAttributesContext::getOrCacheAttribute(const vespalib::string &name, { auto itr = attributes.find(name); if (itr != attributes.end()) { - return itr->second.get(); + return itr->second->attribute(); } ImportedAttributeVector::SP result = _repo.get(name); if (result.get() != nullptr) { auto insRes = attributes.emplace(name, result->makeReadGuard(stableEnumGuard)); - return insRes.first->second.get(); + return insRes.first->second->attribute(); } else { return nullptr; } diff --git a/searchcore/src/vespa/searchcore/proton/attribute/imported_attributes_context.h b/searchcore/src/vespa/searchcore/proton/attribute/imported_attributes_context.h index a0d785d8cc7..90f95ce6447 100644 --- a/searchcore/src/vespa/searchcore/proton/attribute/imported_attributes_context.h +++ b/searchcore/src/vespa/searchcore/proton/attribute/imported_attributes_context.h @@ -10,6 +10,7 @@ namespace search { class AttributeGuard; namespace attribute { +class AttributeReadGuard; class IAttributeVector; class ImportedAttributeVector; }} @@ -26,10 +27,11 @@ class ImportedAttributesRepo; class ImportedAttributesContext : public search::attribute::IAttributeContext { private: using AttributeGuard = search::AttributeGuard; + using AttributeReadGuard = search::attribute::AttributeReadGuard; using IAttributeVector = search::attribute::IAttributeVector; using ImportedAttributeVector = search::attribute::ImportedAttributeVector; - using AttributeCache = std::unordered_map<vespalib::string, std::unique_ptr<IAttributeVector>, vespalib::hash<vespalib::string>>; + using AttributeCache = std::unordered_map<vespalib::string, std::unique_ptr<AttributeReadGuard>, vespalib::hash<vespalib::string>>; using LockGuard = std::lock_guard<std::mutex>; const ImportedAttributesRepo &_repo; diff --git a/searchlib/src/tests/attribute/imported_attribute_vector/imported_attribute_vector_test.cpp b/searchlib/src/tests/attribute/imported_attribute_vector/imported_attribute_vector_test.cpp index 285c49c9133..90b63138fde 100644 --- a/searchlib/src/tests/attribute/imported_attribute_vector/imported_attribute_vector_test.cpp +++ b/searchlib/src/tests/attribute/imported_attribute_vector/imported_attribute_vector_test.cpp @@ -33,7 +33,7 @@ TEST_F("Accessors return expected attributes", Fixture) { TEST_F("getName() is equal to name given during construction", Fixture) { auto attr = f.create_attribute_vector_from_members("coolvector"); EXPECT_EQUAL("coolvector", attr->getName()); - EXPECT_EQUAL("coolvector", attr->makeReadGuard(false)->getName()); + EXPECT_EQUAL("coolvector", attr->makeReadGuard(false)->attribute()->getName()); } TEST_F("getNumDocs() returns number of documents in reference attribute vector", Fixture) { diff --git a/searchlib/src/tests/attribute/imported_search_context/imported_search_context_test.cpp b/searchlib/src/tests/attribute/imported_search_context/imported_search_context_test.cpp index 2f302e50470..53ad20c3b03 100644 --- a/searchlib/src/tests/attribute/imported_search_context/imported_search_context_test.cpp +++ b/searchlib/src/tests/attribute/imported_search_context/imported_search_context_test.cpp @@ -1,6 +1,7 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. #include <vespa/searchcommon/attribute/search_context_params.h> +#include <vespa/searchlib/attribute/attribute_read_guard.h> #include <vespa/searchlib/attribute/imported_search_context.h> #include <vespa/searchlib/fef/termfieldmatchdata.h> #include <vespa/searchlib/queryeval/simpleresult.h> diff --git a/searchlib/src/tests/features/imported_dot_product/imported_dot_product_test.cpp b/searchlib/src/tests/features/imported_dot_product/imported_dot_product_test.cpp index 13225836bd1..42ce9725f91 100644 --- a/searchlib/src/tests/features/imported_dot_product/imported_dot_product_test.cpp +++ b/searchlib/src/tests/features/imported_dot_product/imported_dot_product_test.cpp @@ -1,5 +1,6 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +#include <vespa/searchlib/attribute/attribute_read_guard.h> #include <vespa/searchlib/features/dotproductfeature.h> #include <vespa/searchlib/test/imported_attribute_fixture.h> #include <vespa/searchlib/fef/test/ftlib.h> @@ -45,10 +46,11 @@ struct FixtureBase : ImportedAttributeFixture { if (pre_parsed) { feature.getQueryEnv().getObjectStore().add("dotProduct.vector.object", std::move(pre_parsed)); } - std::shared_ptr<IAttributeVector> readable_imported_attr = imported_attr->makeReadGuard(false); - feature.getIndexEnv().getAttributeMap().add(readable_imported_attr); + auto readGuard = imported_attr->makeReadGuard(false); + const IAttributeVector *attr = readGuard->attribute(); + feature.getIndexEnv().getAttributeMap().add(std::move(readGuard)); schema::CollectionType collection_type( - (readable_imported_attr->getCollectionType() == attribute::CollectionType::ARRAY) + (attr->getCollectionType() == attribute::CollectionType::ARRAY) ? schema::CollectionType::ARRAY : schema::CollectionType::WEIGHTEDSET); feature.getIndexEnv().getBuilder().addField( FieldType::ATTRIBUTE, collection_type, imported_attr->getName()); diff --git a/searchlib/src/vespa/searchlib/attribute/CMakeLists.txt b/searchlib/src/vespa/searchlib/attribute/CMakeLists.txt index cc6736e21c5..794e0b2bdf6 100644 --- a/searchlib/src/vespa/searchlib/attribute/CMakeLists.txt +++ b/searchlib/src/vespa/searchlib/attribute/CMakeLists.txt @@ -5,6 +5,7 @@ vespa_add_library(searchlib_attribute OBJECT attribute.cpp attribute_blueprint_factory.cpp attribute_header.cpp + attribute_read_guard.cpp attribute_weighted_set_blueprint.cpp attributecontext.cpp attributefactory.cpp diff --git a/searchlib/src/vespa/searchlib/attribute/attribute_read_guard.cpp b/searchlib/src/vespa/searchlib/attribute/attribute_read_guard.cpp new file mode 100644 index 00000000000..9f88d37aa6b --- /dev/null +++ b/searchlib/src/vespa/searchlib/attribute/attribute_read_guard.cpp @@ -0,0 +1,16 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#include "attribute_read_guard.h" + +namespace search::attribute { + +AttributeReadGuard::AttributeReadGuard(const IAttributeVector *attr) + : _attr(attr) +{ +} + +AttributeReadGuard::~AttributeReadGuard() +{ +} + +} diff --git a/searchlib/src/vespa/searchlib/attribute/attribute_read_guard.h b/searchlib/src/vespa/searchlib/attribute/attribute_read_guard.h new file mode 100644 index 00000000000..aeccb6c8828 --- /dev/null +++ b/searchlib/src/vespa/searchlib/attribute/attribute_read_guard.h @@ -0,0 +1,33 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#pragma once + +namespace search::attribute { + +class IAttributeVector; + +/** + * Short-lived guard for getting read access to an attribute vector. + * + * Sub-classes must ensure that the appropriate guard(s) + * are held during the lifetime of this object. + */ +class AttributeReadGuard { +private: + const IAttributeVector *_attr; + +protected: + AttributeReadGuard(const IAttributeVector *attr); + +public: + AttributeReadGuard(const AttributeReadGuard &) = delete; + AttributeReadGuard &operator=(const AttributeReadGuard &) = delete; + AttributeReadGuard(AttributeReadGuard &&) = delete; + AttributeReadGuard &operator=(AttributeReadGuard &&) = delete; + virtual ~AttributeReadGuard(); + const IAttributeVector *operator->() const { return _attr; } + const IAttributeVector &operator*() const { return *_attr; } + const IAttributeVector *attribute() const { return _attr; } +}; + +} diff --git a/searchlib/src/vespa/searchlib/attribute/attributevector.cpp b/searchlib/src/vespa/searchlib/attribute/attributevector.cpp index 8b3af9bddd3..b3a25207e00 100644 --- a/searchlib/src/vespa/searchlib/attribute/attributevector.cpp +++ b/searchlib/src/vespa/searchlib/attribute/attributevector.cpp @@ -1,5 +1,6 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +#include "attribute_read_guard.h" #include "attributefilesavetarget.h" #include "attributeiterators.hpp" #include "attributesaver.h" @@ -884,6 +885,14 @@ AttributeVector::getEstimatedShrinkLidSpaceGain() const return canFree; } +std::unique_ptr<attribute::AttributeReadGuard> +AttributeVector::makeReadGuard(bool stableEnumGuard) const +{ + (void) stableEnumGuard; + // TODO: implement + return std::unique_ptr<attribute::AttributeReadGuard>(); +} + MemoryUsage AttributeVector::getChangeVectorMemoryUsage() const { diff --git a/searchlib/src/vespa/searchlib/attribute/attributevector.h b/searchlib/src/vespa/searchlib/attribute/attributevector.h index bdb5e5c02db..efec7d4edb3 100644 --- a/searchlib/src/vespa/searchlib/attribute/attributevector.h +++ b/searchlib/src/vespa/searchlib/attribute/attributevector.h @@ -4,6 +4,7 @@ #include "address_space_usage.h" #include "changevector.h" +#include "readable_attribute_vector.h" #include <vespa/fastlib/text/normwordfolder.h> #include <vespa/searchcommon/attribute/config.h> #include <vespa/searchcommon/attribute/i_search_context.h> @@ -110,7 +111,8 @@ public: class AttributeVector : public vespalib::Identifiable, public attribute::IAttributeVector, - public common::ICompactableLidSpace + public common::ICompactableLidSpace, + public attribute::ReadableAttributeVector { protected: using Config = search::attribute::Config; @@ -664,6 +666,8 @@ public: virtual void onShrinkLidSpace(); virtual size_t getEstimatedShrinkLidSpaceGain() const override; + virtual std::unique_ptr<attribute::AttributeReadGuard> makeReadGuard(bool stableEnumGuard) const override; + void setInterlock(const std::shared_ptr<attribute::Interlock> &interlock); const std::shared_ptr<attribute::Interlock> &getInterlock() const { diff --git a/searchlib/src/vespa/searchlib/attribute/imported_attribute_vector.cpp b/searchlib/src/vespa/searchlib/attribute/imported_attribute_vector.cpp index dd089446065..62244b2c3d6 100644 --- a/searchlib/src/vespa/searchlib/attribute/imported_attribute_vector.cpp +++ b/searchlib/src/vespa/searchlib/attribute/imported_attribute_vector.cpp @@ -38,7 +38,7 @@ ImportedAttributeVector::ImportedAttributeVector(vespalib::stringref name, ImportedAttributeVector::~ImportedAttributeVector() { } -std::unique_ptr<IAttributeVector> +std::unique_ptr<AttributeReadGuard> ImportedAttributeVector::makeReadGuard(bool stableEnumGuard) const { return std::make_unique<ImportedAttributeVectorReadGuard>(*this, stableEnumGuard); diff --git a/searchlib/src/vespa/searchlib/attribute/imported_attribute_vector.h b/searchlib/src/vespa/searchlib/attribute/imported_attribute_vector.h index 731b0bbbd19..fa5470d2449 100644 --- a/searchlib/src/vespa/searchlib/attribute/imported_attribute_vector.h +++ b/searchlib/src/vespa/searchlib/attribute/imported_attribute_vector.h @@ -2,6 +2,7 @@ #pragma once +#include "readable_attribute_vector.h" #include "reference_attribute.h" #include <vespa/vespalib/stllike/string.h> #include <memory> @@ -26,7 +27,7 @@ class BitVectorSearchCache; * Any accessor on the imported attribute for a local LID yields the same result as * if the same accessor were invoked with the target LID on the target attribute vector. */ -class ImportedAttributeVector { +class ImportedAttributeVector : public ReadableAttributeVector { public: using SP = std::shared_ptr<ImportedAttributeVector>; ImportedAttributeVector(vespalib::stringref name, @@ -58,10 +59,7 @@ public: return _name; } - /* - * Create an imported attribute with a snapshot of lid to lid mapping. - */ - virtual std::unique_ptr<IAttributeVector> makeReadGuard(bool stableEnumGuard) const; + virtual std::unique_ptr<AttributeReadGuard> makeReadGuard(bool stableEnumGuard) const override; protected: vespalib::string _name; diff --git a/searchlib/src/vespa/searchlib/attribute/imported_attribute_vector_read_guard.cpp b/searchlib/src/vespa/searchlib/attribute/imported_attribute_vector_read_guard.cpp index da5287b6068..da404d6f904 100644 --- a/searchlib/src/vespa/searchlib/attribute/imported_attribute_vector_read_guard.cpp +++ b/searchlib/src/vespa/searchlib/attribute/imported_attribute_vector_read_guard.cpp @@ -12,7 +12,8 @@ namespace attribute { ImportedAttributeVectorReadGuard::ImportedAttributeVectorReadGuard( const ImportedAttributeVector &imported_attribute, bool stableEnumGuard) - : _imported_attribute(imported_attribute), + : AttributeReadGuard(this), + _imported_attribute(imported_attribute), _referencedLids(), _reference_attribute_guard(imported_attribute.getReferenceAttribute()), _target_attribute_guard(stableEnumGuard ? std::shared_ptr<AttributeVector>() : imported_attribute.getTargetAttribute()), diff --git a/searchlib/src/vespa/searchlib/attribute/imported_attribute_vector_read_guard.h b/searchlib/src/vespa/searchlib/attribute/imported_attribute_vector_read_guard.h index ad0d55cf29e..96f46fa684c 100644 --- a/searchlib/src/vespa/searchlib/attribute/imported_attribute_vector_read_guard.h +++ b/searchlib/src/vespa/searchlib/attribute/imported_attribute_vector_read_guard.h @@ -2,8 +2,9 @@ #pragma once -#include "imported_attribute_vector.h" +#include "attribute_read_guard.h" #include "attributeguard.h" +#include "imported_attribute_vector.h" #include <vespa/searchcommon/attribute/iattributevector.h> namespace search { class IGidToLidMapper; } @@ -18,7 +19,8 @@ class BitVectorSearchCache; * Extra information for direct lid to referenced lid mapping with * boundary check is setup during construction. */ -class ImportedAttributeVectorReadGuard : public IAttributeVector +class ImportedAttributeVectorReadGuard : public IAttributeVector, + public AttributeReadGuard { private: using ReferencedLids = vespalib::ConstArrayRef<uint32_t>; diff --git a/searchlib/src/vespa/searchlib/attribute/readable_attribute_vector.h b/searchlib/src/vespa/searchlib/attribute/readable_attribute_vector.h new file mode 100644 index 00000000000..03058362cb1 --- /dev/null +++ b/searchlib/src/vespa/searchlib/attribute/readable_attribute_vector.h @@ -0,0 +1,20 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#pragma once + +#include <memory> + +namespace search::attribute { + +class AttributeReadGuard; + +/** + * Interface for an attribute vector used to create a short-lived read guard over that attribute. + */ +class ReadableAttributeVector { +public: + virtual ~ReadableAttributeVector() {} + virtual std::unique_ptr<AttributeReadGuard> makeReadGuard(bool stableEnumGuard) const = 0; +}; + +} diff --git a/searchlib/src/vespa/searchlib/fef/test/attribute_map.h b/searchlib/src/vespa/searchlib/fef/test/attribute_map.h index 8fddc0e1c41..aadca263722 100644 --- a/searchlib/src/vespa/searchlib/fef/test/attribute_map.h +++ b/searchlib/src/vespa/searchlib/fef/test/attribute_map.h @@ -2,14 +2,13 @@ #include "mock_attribute_context.h" #include <vespa/searchcommon/attribute/iattributecontext.h> +#include <vespa/searchlib/attribute/attribute_read_guard.h> #include <memory> #include <map> #pragma once -namespace search { -namespace fef { -namespace test { +namespace search::fef::test { /** * Simple mapping from attribute name to IAttributeVector which can be used for tests @@ -21,6 +20,7 @@ namespace test { */ class AttributeMap { std::map<vespalib::string, std::shared_ptr<attribute::IAttributeVector>> _attributes; + std::map<vespalib::string, std::unique_ptr<attribute::AttributeReadGuard>> _guards; public: using IAttributeVector = attribute::IAttributeVector; @@ -28,15 +28,29 @@ public: _attributes.emplace(attr->getName(), std::move(attr)); } + void add(std::unique_ptr<attribute::AttributeReadGuard> guard) { + _guards.emplace(guard->attribute()->getName(), std::move(guard)); + } + const IAttributeVector * getAttribute(const vespalib::string & name) const { - auto iter = _attributes.find(name); - return (iter != _attributes.end() ? iter->second.get() : nullptr); + auto attrItr = _attributes.find(name); + if (attrItr != _attributes.end()) { + return attrItr->second.get(); + } + auto guardItr = _guards.find(name); + if (guardItr != _guards.end()) { + return guardItr->second->attribute(); + } + return nullptr; } void getAttributeList(std::vector<const IAttributeVector *> & list) const { for (const auto& attr : _attributes) { list.emplace_back(attr.second.get()); } + for (const auto &guard : _guards) { + list.emplace_back(guard.second->attribute()); + } } attribute::IAttributeContext::UP createContext() const { @@ -44,6 +58,4 @@ public: } }; -} // test -} // fef -} // search +} diff --git a/searchlib/src/vespa/searchlib/tensor/imported_tensor_attribute_vector.cpp b/searchlib/src/vespa/searchlib/tensor/imported_tensor_attribute_vector.cpp index aeaa153ef1c..90c9c9b7f33 100644 --- a/searchlib/src/vespa/searchlib/tensor/imported_tensor_attribute_vector.cpp +++ b/searchlib/src/vespa/searchlib/tensor/imported_tensor_attribute_vector.cpp @@ -38,7 +38,7 @@ ImportedTensorAttributeVector::~ImportedTensorAttributeVector() { } -std::unique_ptr<attribute::IAttributeVector> +std::unique_ptr<attribute::AttributeReadGuard> ImportedTensorAttributeVector::makeReadGuard(bool stableEnumGuard) const { return std::make_unique<ImportedTensorAttributeVectorReadGuard>(*this, stableEnumGuard); diff --git a/searchlib/src/vespa/searchlib/tensor/imported_tensor_attribute_vector.h b/searchlib/src/vespa/searchlib/tensor/imported_tensor_attribute_vector.h index c94b0469e93..93155a2defc 100644 --- a/searchlib/src/vespa/searchlib/tensor/imported_tensor_attribute_vector.h +++ b/searchlib/src/vespa/searchlib/tensor/imported_tensor_attribute_vector.h @@ -29,7 +29,7 @@ public: std::shared_ptr<BitVectorSearchCache> search_cache); ~ImportedTensorAttributeVector(); - virtual std::unique_ptr<attribute::IAttributeVector> makeReadGuard(bool stableEnumGuard) const override; + virtual std::unique_ptr<attribute::AttributeReadGuard> makeReadGuard(bool stableEnumGuard) const override; virtual std::unique_ptr<Tensor> getTensor(uint32_t docId) const override; virtual std::unique_ptr<Tensor> getEmptyTensor() const override; virtual void getTensor(uint32_t docId, vespalib::tensor::MutableDenseTensorView &tensor) const override; diff --git a/searchlib/src/vespa/searchlib/test/imported_attribute_fixture.h b/searchlib/src/vespa/searchlib/test/imported_attribute_fixture.h index 6245e0304fb..339060bbfc3 100644 --- a/searchlib/src/vespa/searchlib/test/imported_attribute_fixture.h +++ b/searchlib/src/vespa/searchlib/test/imported_attribute_fixture.h @@ -5,6 +5,7 @@ #include "mock_gid_to_lid_mapping.h" #include <vespa/document/base/documentid.h> #include <vespa/document/base/globalid.h> +#include <vespa/searchlib/attribute/attribute_read_guard.h> #include <vespa/searchlib/attribute/attributefactory.h> #include <vespa/searchlib/attribute/attributeguard.h> #include <vespa/searchlib/attribute/floatbase.h> @@ -137,6 +138,13 @@ std::unique_ptr<QueryTermSimple> word_term(vespalib::stringref term) { return std::make_unique<QueryTermSimple>(term, QueryTerm::WORD); } +struct ReadGuardWrapper { + std::unique_ptr<AttributeReadGuard> guard; + ReadGuardWrapper(std::unique_ptr<AttributeReadGuard> guard_) : guard(std::move(guard_)) {} + const IAttributeVector *operator->() const { return guard->operator->(); } + const IAttributeVector &operator*() const { return guard->operator*(); } +}; + struct ImportedAttributeFixture { bool use_search_cache; std::shared_ptr<AttributeVector> target_attr; @@ -149,8 +157,8 @@ struct ImportedAttributeFixture { virtual ~ImportedAttributeFixture(); - std::unique_ptr<IAttributeVector> get_imported_attr() const { - return imported_attr->makeReadGuard(false); + ReadGuardWrapper get_imported_attr() const { + return ReadGuardWrapper(imported_attr->makeReadGuard(false)); } void map_reference(DocId from_lid, GlobalId via_gid, DocId to_lid) { |