aboutsummaryrefslogtreecommitdiffstats
path: root/searchlib
diff options
context:
space:
mode:
authorHenning Baldersheim <balder@yahoo-inc.com>2019-05-30 14:10:05 +0000
committerHenning Baldersheim <balder@yahoo-inc.com>2019-05-30 14:10:05 +0000
commit029ecfd2df7de90d90ba1d6f01ed6db6cbeef54f (patch)
tree3a3bea4dd7d16d292e7b3a20c197c3e943fbe131 /searchlib
parent45ac7deaaf21b64139ece3968f5e945a18c647e0 (diff)
attribute and query vector are 2 completely different dimensions.
That must be reflected in the ObjectStore too.
Diffstat (limited to 'searchlib')
-rw-r--r--searchlib/src/tests/features/imported_dot_product/imported_dot_product_test.cpp8
-rw-r--r--searchlib/src/vespa/searchlib/features/dotproductfeature.cpp84
-rw-r--r--searchlib/src/vespa/searchlib/features/dotproductfeature.h7
-rw-r--r--searchlib/src/vespa/searchlib/fef/objectstore.h10
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: