diff options
author | Henning Baldersheim <balder@yahoo-inc.com> | 2019-05-30 14:10:05 +0000 |
---|---|---|
committer | Henning Baldersheim <balder@yahoo-inc.com> | 2019-05-30 14:10:05 +0000 |
commit | 029ecfd2df7de90d90ba1d6f01ed6db6cbeef54f (patch) | |
tree | 3a3bea4dd7d16d292e7b3a20c197c3e943fbe131 /searchlib | |
parent | 45ac7deaaf21b64139ece3968f5e945a18c647e0 (diff) |
attribute and query vector are 2 completely different dimensions.
That must be reflected in the ObjectStore too.
Diffstat (limited to 'searchlib')
4 files changed, 65 insertions, 44 deletions
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 a8352acc952..bbd6d8e61b3 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 @@ -48,7 +48,7 @@ struct FixtureBase : ImportedAttributeFixture { feature.getQueryEnv().getProperties().add("dotProduct.vector", vector); if (pre_parsed) { - feature.getQueryEnv().getObjectStore().add("dotProduct.vector", std::make_unique<DotProductBlueprint::SharedState>(nullptr, std::move(pre_parsed))); + feature.getQueryEnv().getObjectStore().add("dotProduct.vector.vector", std::move(pre_parsed)); } auto readGuard = imported_attr->makeReadGuard(false); const IAttributeVector *attr = readGuard->attribute(); @@ -143,11 +143,9 @@ struct ArrayFixture : FixtureBase { auto& obj_store = feature.getQueryEnv().getObjectStore(); bp.prepareSharedState(feature.getQueryEnv(), obj_store); // Resulting name is very implementation defined. But at least the tests will break if it changes. - const auto* anything = obj_store.get("dotProduct.fancyvector"); + const auto* anything = obj_store.get("dotProduct.vector.fancyvector"); ASSERT_TRUE(anything != nullptr); - const auto* state = dynamic_cast<const DotProductBlueprint::SharedState*>(anything); - ASSERT_TRUE(state != nullptr); - const auto* as_object = dynamic_cast<const ExpectedType*>(state->_arguments.get()); + const auto* as_object = dynamic_cast<const ExpectedType*>(anything); ASSERT_TRUE(as_object != nullptr); verify(expected, *as_object); } diff --git a/searchlib/src/vespa/searchlib/features/dotproductfeature.cpp b/searchlib/src/vespa/searchlib/features/dotproductfeature.cpp index 97216ef5437..642870e94f8 100644 --- a/searchlib/src/vespa/searchlib/features/dotproductfeature.cpp +++ b/searchlib/src/vespa/searchlib/features/dotproductfeature.cpp @@ -775,21 +775,22 @@ attemptParseArrayQueryVector(const IAttributeVector & attribute, const Property } vespalib::string -make_key(const vespalib::string & base, const vespalib::string & queryVector) { +make_queryvector_key(const vespalib::string & base, const vespalib::string & subKey) { vespalib::string key(base); - key.append('.'); - key.append(queryVector); + key.append(".vector."); + key.append(subKey); return key; } -} // anon ns - -DotProductBlueprint::SharedState::SharedState(const IAttributeVector * attribute, fef::Anything::UP arguments) - : _attribute(attribute), - _arguments(std::move(arguments)) -{} +vespalib::string +make_attribute_key(const vespalib::string & base, const vespalib::string & subKey) { + vespalib::string key(base); + key.append(".attribute."); + key.append(subKey); + return key; +} -DotProductBlueprint::SharedState::~SharedState() = default; +} // anon ns const IAttributeVector * DotProductBlueprint::upgradeIfNecessary(const IAttributeVector * attribute, const IQueryEnvironment & env) const { @@ -802,16 +803,15 @@ DotProductBlueprint::upgradeIfNecessary(const IAttributeVector * attribute, cons return attribute; } -void -DotProductBlueprint::prepareSharedState(const IQueryEnvironment & env, IObjectStore & store) const -{ - const IAttributeVector * attribute = env.getAttributeContext().getAttribute(getAttribute(env)); - if (attribute == nullptr) return; +namespace { - attribute = upgradeIfNecessary(attribute, env); +fef::Anything::UP +createQueryVector(const IQueryEnvironment & env, const IAttributeVector * attribute, + const vespalib::string & baseName, const vespalib::string & queryVector) +{ fef::Anything::UP arguments; if (attribute->getCollectionType() == attribute::CollectionType::ARRAY) { - Property tensorBlob = env.getProperties().lookup(getBaseName(), _queryVector, "tensor"); + Property tensorBlob = env.getProperties().lookup(baseName, queryVector, "tensor"); if (attribute->isFloatingPointType() && tensorBlob.found() && !tensorBlob.get().empty()) { const Property::Value & blob = tensorBlob.get(); vespalib::nbostream stream(blob.data(), blob.size()); @@ -821,13 +821,13 @@ DotProductBlueprint::prepareSharedState(const IQueryEnvironment & env, IObjectSt arguments = std::make_unique<ArrayParam<double>>(stream); } } else { - Property prop = env.getProperties().lookup(getBaseName(), _queryVector); + Property prop = env.getProperties().lookup(baseName, queryVector); if (prop.found() && !prop.get().empty()) { arguments = attemptParseArrayQueryVector(*attribute, prop); } } } else if (attribute->getCollectionType() == attribute::CollectionType::WSET) { - Property prop = env.getProperties().lookup(getBaseName(), _queryVector); + Property prop = env.getProperties().lookup(baseName, queryVector); if (prop.found() && !prop.get().empty()) { if (attribute->isStringType() && attribute->hasEnum()) { dotproduct::wset::EnumVector vector(attribute); @@ -844,30 +844,50 @@ DotProductBlueprint::prepareSharedState(const IQueryEnvironment & env, IObjectSt // TODO actually use the parsed output for wset operations! } } - store.add(make_key(getBaseName(), _queryVector), std::make_unique<SharedState>(attribute, std::move(arguments))); + return arguments; } -FeatureExecutor & -DotProductBlueprint::createExecutor(const IQueryEnvironment & env, vespalib::Stash &stash) const +} + +void +DotProductBlueprint::prepareSharedState(const IQueryEnvironment & env, IObjectStore & store) const { - const IAttributeVector * attribute = nullptr; - const SharedState * sharedState = nullptr; - const fef::Anything * argument = env.getObjectStore().get(make_key(getBaseName(), _queryVector)); - if (argument != nullptr) { - sharedState = static_cast<const SharedState *>(argument); - attribute = sharedState->_attribute; + const IAttributeVector * attribute = env.getAttributeContext().getAttribute(getAttribute(env)); + if (attribute == nullptr) return; + + vespalib::string queryVectorKey = make_queryvector_key(getBaseName(), _queryVector); + const fef::Anything * queryVector = env.getObjectStore().get(queryVectorKey); + if (queryVector == nullptr) { + fef::Anything::UP arguments = createQueryVector(env, attribute, getBaseName(), _queryVector); + if (arguments) { + store.add(queryVectorKey, std::move(arguments)); + } } - if (attribute == nullptr) { - attribute = env.getAttributeContext().getAttribute(getAttribute(env)); + + attribute = upgradeIfNecessary(attribute, env); + + vespalib::string attributeKey = make_attribute_key(getBaseName(), _defaultAttribute); + if (store.get(attributeKey) == nullptr) { + store.add(attributeKey, std::make_unique<fef::AnyWrapper<const IAttributeVector *>>(attribute)); } +} + +FeatureExecutor & +DotProductBlueprint::createExecutor(const IQueryEnvironment & env, vespalib::Stash &stash) const +{ + const fef::Anything * attributeArg = env.getObjectStore().get(make_attribute_key(getBaseName(), _defaultAttribute)); + const IAttributeVector * attribute = (attributeArg != nullptr) + ? static_cast<const fef::AnyWrapper<const IAttributeVector *> *>(attributeArg)->getValue() + : env.getAttributeContext().getAttribute(getAttribute(env)); if (attribute == nullptr) { LOG(warning, "The attribute vector '%s' was not found in the attribute manager, returning executor with default value.", getAttribute(env).c_str()); return stash.create<SingleZeroValueExecutor>(); } attribute = upgradeIfNecessary(attribute, env); - if ((sharedState != nullptr) && sharedState->_arguments) { - return createFromObject(attribute, *sharedState->_arguments, stash); + const fef::Anything * queryVectorArg = env.getObjectStore().get(make_queryvector_key(getBaseName(), _queryVector)); + if (queryVectorArg != nullptr) { + return createFromObject(attribute, *queryVectorArg, stash); } else { Property prop = env.getProperties().lookup(getBaseName(), _queryVector); if (prop.found() && !prop.get().empty()) { diff --git a/searchlib/src/vespa/searchlib/features/dotproductfeature.h b/searchlib/src/vespa/searchlib/features/dotproductfeature.h index 77a78b131b0..94c72233c4b 100644 --- a/searchlib/src/vespa/searchlib/features/dotproductfeature.h +++ b/searchlib/src/vespa/searchlib/features/dotproductfeature.h @@ -308,13 +308,6 @@ private: const IAttributeVector * upgradeIfNecessary(const IAttributeVector * attribute, const fef::IQueryEnvironment & env) const; public: - class SharedState : public fef::Anything { - public: - SharedState(const IAttributeVector * attribute, fef::Anything::UP arguments); - ~SharedState() override; - const IAttributeVector * _attribute; - fef::Anything::UP _arguments; - }; DotProductBlueprint(); ~DotProductBlueprint() override; void visitDumpFeatures(const fef::IIndexEnvironment & env, fef::IDumpFeatureVisitor & visitor) const override; diff --git a/searchlib/src/vespa/searchlib/fef/objectstore.h b/searchlib/src/vespa/searchlib/fef/objectstore.h index a62ca66486c..49176afa3c9 100644 --- a/searchlib/src/vespa/searchlib/fef/objectstore.h +++ b/searchlib/src/vespa/searchlib/fef/objectstore.h @@ -12,6 +12,16 @@ public: virtual ~Anything() { } }; +template<typename T> +class AnyWrapper : public Anything +{ +public: + AnyWrapper(T value) : _value(value) { } + const T & getValue() const { return _value; } +private: + T _value; +}; + class IObjectStore { public: |