aboutsummaryrefslogtreecommitdiffstats
path: root/searchcore/src
diff options
context:
space:
mode:
authorTor Brede Vekterli <vekterli@verizonmedia.com>2020-01-29 11:26:48 +0000
committerTor Brede Vekterli <vekterli@verizonmedia.com>2020-01-29 12:22:05 +0000
commitbb74faa5f2e56c930db1ec06ebf912e5b316c087 (patch)
tree42860f1ae5821dea25b900270a5aa1721e4618e7 /searchcore/src
parentb525ae9930ce37017eec664fbc4a0e12258c3db0 (diff)
Add ReadableAttributeVector accessor to IAttributeManager
Provides a unified interface for fetching both regular as well as imported attributes. Exposing `ReadableAttributeVector` instead of raw `AttributeVector` instances enforces that all access is done via appropriate acquired read guards. Refactor document selection processing code to use the new interface in order to prepare for imported field support in selections.
Diffstat (limited to 'searchcore/src')
-rw-r--r--searchcore/src/tests/proton/attribute/attribute_manager/attribute_manager_test.cpp37
-rw-r--r--searchcore/src/tests/proton/attribute/attribute_test.cpp15
-rw-r--r--searchcore/src/vespa/searchcore/proton/attribute/attributemanager.cpp11
-rw-r--r--searchcore/src/vespa/searchcore/proton/attribute/attributemanager.h2
-rw-r--r--searchcore/src/vespa/searchcore/proton/attribute/filter_attribute_manager.cpp9
-rw-r--r--searchcore/src/vespa/searchcore/proton/attribute/filter_attribute_manager.h1
-rw-r--r--searchcore/src/vespa/searchcore/proton/common/attributefieldvaluenode.cpp21
-rw-r--r--searchcore/src/vespa/searchcore/proton/common/attributefieldvaluenode.h7
-rw-r--r--searchcore/src/vespa/searchcore/proton/common/cachedselect.cpp18
-rw-r--r--searchcore/src/vespa/searchcore/proton/common/cachedselect.h4
-rw-r--r--searchcore/src/vespa/searchcore/proton/common/selectcontext.cpp33
-rw-r--r--searchcore/src/vespa/searchcore/proton/common/selectcontext.h4
-rw-r--r--searchcore/src/vespa/searchcore/proton/common/selectpruner.cpp10
-rw-r--r--searchcore/src/vespa/searchcore/proton/test/mock_attribute_manager.h3
14 files changed, 124 insertions, 51 deletions
diff --git a/searchcore/src/tests/proton/attribute/attribute_manager/attribute_manager_test.cpp b/searchcore/src/tests/proton/attribute/attribute_manager/attribute_manager_test.cpp
index c6d49c479c4..44ff8cb925e 100644
--- a/searchcore/src/tests/proton/attribute/attribute_manager/attribute_manager_test.cpp
+++ b/searchcore/src/tests/proton/attribute/attribute_manager/attribute_manager_test.cpp
@@ -215,7 +215,7 @@ struct SequentialAttributeManager
{
mgr.addInitializedAttributes(initializer.getInitializedAttributes());
}
- ~SequentialAttributeManager() {}
+ ~SequentialAttributeManager() = default;
};
struct DummyInitializerTask : public InitializerTask
@@ -262,23 +262,33 @@ ParallelAttributeManager::ParallelAttributeManager(search::SerialNum configSeria
initializer::TaskRunner taskRunner(executor);
taskRunner.runTask(initializer);
}
-ParallelAttributeManager::~ParallelAttributeManager() {}
+ParallelAttributeManager::~ParallelAttributeManager() = default;
TEST_F("require that attributes are added", Fixture)
{
- EXPECT_TRUE(f.addAttribute("a1").get() != NULL);
- EXPECT_TRUE(f.addAttribute("a2").get() != NULL);
+ EXPECT_TRUE(f.addAttribute("a1").get() != nullptr);
+ EXPECT_TRUE(f.addAttribute("a2").get() != nullptr);
EXPECT_EQUAL("a1", (*f._m.getAttribute("a1"))->getName());
EXPECT_EQUAL("a1", (*f._m.getAttributeReadGuard("a1", true))->getName());
EXPECT_EQUAL("a2", (*f._m.getAttribute("a2"))->getName());
EXPECT_EQUAL("a2", (*f._m.getAttributeReadGuard("a2", true))->getName());
EXPECT_TRUE(!f._m.getAttribute("not")->valid());
+
+ auto rv = f._m.readable_attribute_vector("a1");
+ ASSERT_TRUE(rv.get() != nullptr);
+ EXPECT_EQUAL("a1", rv->makeReadGuard(true)->attribute()->getName());
+
+ rv = f._m.readable_attribute_vector("a2");
+ ASSERT_TRUE(rv.get() != nullptr);
+ EXPECT_EQUAL("a2", rv->makeReadGuard(true)->attribute()->getName());
+
+ EXPECT_TRUE(f._m.readable_attribute_vector("not_valid").get() == nullptr);
}
TEST_F("require that predicate attributes are added", Fixture)
{
EXPECT_TRUE(f._m.addAttribute({"p1", AttributeUtils::getPredicateConfig()},
- createSerialNum).get() != NULL);
+ createSerialNum).get() != nullptr);
EXPECT_EQUAL("p1", (*f._m.getAttribute("p1"))->getName());
EXPECT_EQUAL("p1", (*f._m.getAttributeReadGuard("p1", true))->getName());
}
@@ -376,7 +386,7 @@ TEST_F("require that predicate attributes are flushed and loaded", BaseFixture)
AttributeVector::SP a1 = am.addAttribute({"a1", AttributeUtils::getPredicateConfig()}, createSerialNum);
EXPECT_EQUAL(1u, a1->getNumDocs());
- PredicateAttribute &pa = static_cast<PredicateAttribute &>(*a1);
+ auto &pa = static_cast<PredicateAttribute &>(*a1);
PredicateIndex &index = pa.getIndex();
uint32_t doc_id;
a1->addDoc(doc_id);
@@ -396,7 +406,7 @@ TEST_F("require that predicate attributes are flushed and loaded", BaseFixture)
AttributeVector::SP a1 = am.addAttribute({"a1", AttributeUtils::getPredicateConfig()}, createSerialNum); // loaded
EXPECT_EQUAL(2u, a1->getNumDocs());
- PredicateAttribute &pa = static_cast<PredicateAttribute &>(*a1);
+ auto &pa = static_cast<PredicateAttribute &>(*a1);
PredicateIndex &index = pa.getIndex();
uint32_t doc_id;
a1->addDoc(doc_id);
@@ -746,7 +756,7 @@ TEST_F("require that we can acquire exclusive read access to attribute", Fixture
EXPECT_TRUE(noneAccessor.get() == nullptr);
}
-TEST_F("require that imported attributes are exposed via attribute context together vi regular attributes", Fixture)
+TEST_F("require that imported attributes are exposed via attribute context together with regular attributes", Fixture)
{
f.addAttribute("attr");
f.addImportedAttribute("imported");
@@ -767,6 +777,17 @@ TEST_F("require that imported attributes are exposed via attribute context toget
EXPECT_EQUAL("imported", all[1]->getName());
}
+TEST_F("imported attributes are transparently returned from readable_attribute_vector", Fixture)
+{
+ f.addAttribute("attr");
+ f.addImportedAttribute("imported");
+ f.setImportedAttributes();
+ auto av = f._m.readable_attribute_vector("imported");
+ ASSERT_TRUE(av);
+ auto g = av->makeReadGuard(false);
+ EXPECT_EQUAL("imported", g->attribute()->getName());
+}
+
TEST_F("require that attribute vector of wrong type is dropped", BaseFixture)
{
AVConfig generic_tensor(BasicType::TENSOR);
diff --git a/searchcore/src/tests/proton/attribute/attribute_test.cpp b/searchcore/src/tests/proton/attribute/attribute_test.cpp
index 14b72c9d8f8..edb5a07b059 100644
--- a/searchcore/src/tests/proton/attribute/attribute_test.cpp
+++ b/searchcore/src/tests/proton/attribute/attribute_test.cpp
@@ -20,6 +20,7 @@
#include <vespa/searchcore/proton/test/attribute_utils.h>
#include <vespa/searchcorespi/flush/iflushtarget.h>
#include <vespa/searchlib/attribute/attributefactory.h>
+#include <vespa/searchlib/attribute/attribute_read_guard.h>
#include <vespa/searchlib/attribute/bitvector_search_cache.h>
#include <vespa/searchlib/attribute/imported_attribute_vector.h>
#include <vespa/searchlib/attribute/imported_attribute_vector_factory.h>
@@ -588,8 +589,8 @@ struct FilterFixture
TEST_F("require that filter attribute manager can filter attributes", FilterFixture)
{
- EXPECT_TRUE(f._filterMgr.getAttribute("a1").get() == NULL);
- EXPECT_TRUE(f._filterMgr.getAttribute("a2").get() != NULL);
+ EXPECT_TRUE(f._filterMgr.getAttribute("a1").get() == nullptr);
+ EXPECT_TRUE(f._filterMgr.getAttribute("a2").get() != nullptr);
std::vector<AttributeGuard> attrs;
f._filterMgr.getAttributeList(attrs);
EXPECT_EQUAL(1u, attrs.size());
@@ -607,6 +608,16 @@ TEST_F("require that filter attribute manager can return flushed serial number",
EXPECT_EQUAL(100u, f._filterMgr.getFlushedSerialNum("a2"));
}
+TEST_F("readable_attribute_vector filters attributes", FilterFixture)
+{
+ auto av = f._filterMgr.readable_attribute_vector("a2");
+ ASSERT_TRUE(av);
+ EXPECT_EQUAL("a2", av->makeReadGuard(false)->attribute()->getName());
+
+ av = f._filterMgr.readable_attribute_vector("a1");
+ EXPECT_FALSE(av);
+}
+
namespace {
Tensor::UP make_tensor(const TensorSpec &spec) {
diff --git a/searchcore/src/vespa/searchcore/proton/attribute/attributemanager.cpp b/searchcore/src/vespa/searchcore/proton/attribute/attributemanager.cpp
index e39061a8389..02bf4f4d7cc 100644
--- a/searchcore/src/vespa/searchcore/proton/attribute/attributemanager.cpp
+++ b/searchcore/src/vespa/searchcore/proton/attribute/attributemanager.cpp
@@ -11,6 +11,7 @@
#include <vespa/searchcore/proton/flushengine/shrink_lid_space_flush_target.h>
#include <vespa/searchlib/attribute/attributecontext.h>
#include <vespa/searchlib/attribute/attribute_read_guard.h>
+#include <vespa/searchlib/attribute/imported_attribute_vector.h>
#include <vespa/searchcommon/attribute/i_attribute_functor.h>
#include <vespa/searchlib/attribute/interlock.h>
#include <vespa/searchlib/common/isequencedtaskexecutor.h>
@@ -613,4 +614,14 @@ AttributeManager::setImportedAttributes(std::unique_ptr<ImportedAttributesRepo>
_importedAttributes = std::move(attributes);
}
+std::shared_ptr<search::attribute::ReadableAttributeVector>
+AttributeManager::readable_attribute_vector(const string& name) const
+{
+ auto attribute = findAttribute(name);
+ if (attribute || !_importedAttributes) {
+ return attribute;
+ }
+ return _importedAttributes->get(name);
+}
+
} // namespace proton
diff --git a/searchcore/src/vespa/searchcore/proton/attribute/attributemanager.h b/searchcore/src/vespa/searchcore/proton/attribute/attributemanager.h
index cf60a0a41e9..881452c6b3d 100644
--- a/searchcore/src/vespa/searchcore/proton/attribute/attributemanager.h
+++ b/searchcore/src/vespa/searchcore/proton/attribute/attributemanager.h
@@ -178,6 +178,8 @@ public:
void setImportedAttributes(std::unique_ptr<ImportedAttributesRepo> attributes) override;
const ImportedAttributesRepo *getImportedAttributes() const override { return _importedAttributes.get(); }
+
+ std::shared_ptr<search::attribute::ReadableAttributeVector> readable_attribute_vector(const string& name) const override;
};
} // namespace proton
diff --git a/searchcore/src/vespa/searchcore/proton/attribute/filter_attribute_manager.cpp b/searchcore/src/vespa/searchcore/proton/attribute/filter_attribute_manager.cpp
index fd1f95e13ba..aee68457b62 100644
--- a/searchcore/src/vespa/searchcore/proton/attribute/filter_attribute_manager.cpp
+++ b/searchcore/src/vespa/searchcore/proton/attribute/filter_attribute_manager.cpp
@@ -231,4 +231,13 @@ FilterAttributeManager::getImportedAttributes() const
throw vespalib::IllegalArgumentException("Not implemented");
}
+std::shared_ptr<search::attribute::ReadableAttributeVector>
+FilterAttributeManager::readable_attribute_vector(const string& name) const
+{
+ if (acceptAttribute(name)) {
+ return _mgr->readable_attribute_vector(name);
+ }
+ return {};
+}
+
}
diff --git a/searchcore/src/vespa/searchcore/proton/attribute/filter_attribute_manager.h b/searchcore/src/vespa/searchcore/proton/attribute/filter_attribute_manager.h
index 099bb2e84ba..0bd04b8f0a5 100644
--- a/searchcore/src/vespa/searchcore/proton/attribute/filter_attribute_manager.h
+++ b/searchcore/src/vespa/searchcore/proton/attribute/filter_attribute_manager.h
@@ -54,6 +54,7 @@ public:
ExclusiveAttributeReadAccessor::UP getExclusiveReadAccessor(const vespalib::string &name) const override;
void setImportedAttributes(std::unique_ptr<ImportedAttributesRepo> attributes) override;
const ImportedAttributesRepo *getImportedAttributes() const override;
+ std::shared_ptr<search::attribute::ReadableAttributeVector> readable_attribute_vector(const string& name) const override;
void asyncForAttribute(const vespalib::string &name, std::unique_ptr<IAttributeFunctor> func) const override;
};
diff --git a/searchcore/src/vespa/searchcore/proton/common/attributefieldvaluenode.cpp b/searchcore/src/vespa/searchcore/proton/common/attributefieldvaluenode.cpp
index ab3b0588f3f..3a15bb16409 100644
--- a/searchcore/src/vespa/searchcore/proton/common/attributefieldvaluenode.cpp
+++ b/searchcore/src/vespa/searchcore/proton/common/attributefieldvaluenode.cpp
@@ -4,6 +4,7 @@
#include "selectcontext.h"
#include <vespa/searchcommon/attribute/attributecontent.h>
#include <vespa/searchlib/attribute/attributevector.h>
+#include <vespa/searchlib/attribute/attribute_read_guard.h>
#include <vespa/vespalib/util/exceptions.h>
#include <vespa/log/log.h>
@@ -31,14 +32,10 @@ using vespalib::make_string;
AttributeFieldValueNode::
AttributeFieldValueNode(const vespalib::string& doctype,
const vespalib::string& field,
- const std::shared_ptr<search::AttributeVector> &attribute)
+ uint32_t attr_guard_index)
: FieldValueNode(doctype, field),
- _attribute(attribute)
+ _attr_guard_index(attr_guard_index)
{
- const AttributeVector &v(*_attribute);
- // Only handle single value attribute vectors for now
- assert(v.getCollectionType() == CollectionType::SINGLE);
- (void) v;
}
@@ -46,10 +43,10 @@ std::unique_ptr<document::select::Value>
AttributeFieldValueNode::
getValue(const Context &context) const
{
- const SelectContext &sc(static_cast<const SelectContext &>(context));
+ const auto &sc(static_cast<const SelectContext &>(context));
uint32_t docId(sc._docId);
assert(docId != 0u);
- const AttributeVector &v(*_attribute);
+ const auto& v = *sc.read_guard_at_index(_attr_guard_index).attribute();
if (v.isUndefined(docId)) {
return std::make_unique<NullValue>();
}
@@ -86,10 +83,10 @@ getValue(const Context &context) const
case BasicType::PREDICATE:
case BasicType::TENSOR:
case BasicType::REFERENCE:
- throw new IllegalArgumentException(make_string("Attribute '%s' of type '%s' can not be used for selection",
- v.getName().c_str(), v.getInternalBasicType().asString()));
+ throw IllegalArgumentException(make_string("Attribute '%s' of type '%s' can not be used for selection",
+ v.getName().c_str(), BasicType(v.getBasicType()).asString()));
case BasicType::MAX_TYPE:
- throw new IllegalStateException(make_string("Attribute '%s' has illegal type '%d'", v.getName().c_str(), v.getBasicType()));
+ throw IllegalStateException(make_string("Attribute '%s' has illegal type '%d'", v.getName().c_str(), v.getBasicType()));
}
return std::make_unique<NullValue>();;
@@ -106,7 +103,7 @@ AttributeFieldValueNode::traceValue(const Context &context, std::ostream& out) c
document::select::ValueNode::UP
AttributeFieldValueNode::clone() const
{
- return wrapParens(new AttributeFieldValueNode(getDocType(), getFieldName(), _attribute));
+ return wrapParens(new AttributeFieldValueNode(getDocType(), getFieldName(), _attr_guard_index));
}
} // namespace proton
diff --git a/searchcore/src/vespa/searchcore/proton/common/attributefieldvaluenode.h b/searchcore/src/vespa/searchcore/proton/common/attributefieldvaluenode.h
index 9ac6ce0e32b..89d1dac321b 100644
--- a/searchcore/src/vespa/searchcore/proton/common/attributefieldvaluenode.h
+++ b/searchcore/src/vespa/searchcore/proton/common/attributefieldvaluenode.h
@@ -3,18 +3,19 @@
#include <vespa/document/select/valuenodes.h>
-namespace search { class AttributeVector; }
+namespace search { class ReadableAttributeVector; }
namespace proton {
class AttributeFieldValueNode : public document::select::FieldValueNode
{
using Context = document::select::Context;
- std::shared_ptr<search::AttributeVector> _attribute;
+ uint32_t _attr_guard_index;
public:
+ // Precondition: attribute must be of a single-value type.
AttributeFieldValueNode(const vespalib::string& doctype,
const vespalib::string& field,
- const std::shared_ptr<search::AttributeVector> &attribute);
+ uint32_t attr_guard_index);
std::unique_ptr<document::select::Value> getValue(const Context &context) const override;
std::unique_ptr<document::select::Value> traceValue(const Context &context, std::ostream& out) const override;
diff --git a/searchcore/src/vespa/searchcore/proton/common/cachedselect.cpp b/searchcore/src/vespa/searchcore/proton/common/cachedselect.cpp
index d007b030e6b..21f757fba79 100644
--- a/searchcore/src/vespa/searchcore/proton/common/cachedselect.cpp
+++ b/searchcore/src/vespa/searchcore/proton/common/cachedselect.cpp
@@ -7,6 +7,7 @@
#include "selectpruner.h"
#include <vespa/document/select/parser.h>
#include <vespa/searchlib/attribute/attributevector.h>
+#include <vespa/searchlib/attribute/attribute_read_guard.h>
#include <vespa/searchlib/attribute/iattributemanager.h>
namespace proton {
@@ -24,7 +25,7 @@ namespace {
class AttrVisitor : public document::select::CloningVisitor
{
public:
- typedef std::map<vespalib::string, uint32_t> AttrMap;
+ using AttrMap = std::map<vespalib::string, uint32_t>;
AttrMap _amap;
const search::IAttributeManager &_amgr;
@@ -62,7 +63,7 @@ AttrVisitor::AttrVisitor(const search::IAttributeManager &amgr, CachedSelect::At
AttrVisitor::~AttrVisitor() = default;
-bool isSingleValueThatWEHandle(BasicType type) {
+bool isSingleValueThatWeHandle(BasicType type) {
return (type != BasicType::PREDICATE) && (type != BasicType::TENSOR) && (type != BasicType::REFERENCE);
}
@@ -75,17 +76,18 @@ AttrVisitor::visitFieldValueNode(const FieldValueNode &expr)
bool complex = false;
vespalib::string name = SelectUtils::extractFieldName(expr, complex);
- AttributeGuard::UP ag(_amgr.getAttribute(name));
- if (ag->valid()) {
+ auto av = _amgr.readable_attribute_vector(name);
+ if (av) {
if (complex) {
++_complexAttrs;
// Don't try to optimize complex attribute references yet.
_valueNode = expr.clone();
return;
}
- std::shared_ptr<search::AttributeVector> av(ag->getSP());
- if (av->getCollectionType() == CollectionType::SINGLE) {
- if (isSingleValueThatWEHandle(av->getBasicType())) {
+ auto guard = av->makeReadGuard(false);
+ const auto* attr = guard->attribute();
+ if (attr->getCollectionType() == CollectionType::SINGLE) {
+ if (isSingleValueThatWeHandle(attr->getBasicType())) {
++_svAttrs;
auto it(_amap.find(name));
uint32_t idx(invalidIdx());
@@ -99,7 +101,7 @@ AttrVisitor::visitFieldValueNode(const FieldValueNode &expr)
idx = it->second;
}
assert(idx != invalidIdx());
- _valueNode = std::make_unique<AttributeFieldValueNode>(expr.getDocType(), name, av);
+ _valueNode = std::make_unique<AttributeFieldValueNode>(expr.getDocType(), name, idx);
} else {
++_complexAttrs;
// Don't try to optimize predicate/tensor/reference attributes yet.
diff --git a/searchcore/src/vespa/searchcore/proton/common/cachedselect.h b/searchcore/src/vespa/searchcore/proton/common/cachedselect.h
index e9eb452889e..563eed75c32 100644
--- a/searchcore/src/vespa/searchcore/proton/common/cachedselect.h
+++ b/searchcore/src/vespa/searchcore/proton/common/cachedselect.h
@@ -15,6 +15,8 @@ namespace search {
class IAttributeManager;
}
+namespace search::attribute { class ReadableAttributeVector; }
+
namespace proton {
class SelectContext;
@@ -44,7 +46,7 @@ public:
const document::select::Node &selectNode() const;
};
- using AttributeVectors = std::vector<std::shared_ptr<search::AttributeVector>>;
+ using AttributeVectors = std::vector<std::shared_ptr<search::attribute::ReadableAttributeVector>>;
private:
// Single value attributes referenced from selection expression
diff --git a/searchcore/src/vespa/searchcore/proton/common/selectcontext.cpp b/searchcore/src/vespa/searchcore/proton/common/selectcontext.cpp
index 3275fbe06d4..ae6a1f58bdc 100644
--- a/searchcore/src/vespa/searchcore/proton/common/selectcontext.cpp
+++ b/searchcore/src/vespa/searchcore/proton/common/selectcontext.cpp
@@ -3,20 +3,22 @@
#include "selectcontext.h"
#include "cachedselect.h"
#include <vespa/document/select/value.h>
-#include <vespa/searchlib/attribute/attributeguard.h>
+#include <vespa/searchlib/attribute/attribute_read_guard.h>
+#include <vespa/searchlib/attribute/readable_attribute_vector.h>
+#include <cassert>
namespace proton {
using document::select::Value;
using document::select::Context;
-using search::AttributeGuard;
using search::AttributeVector;
+using search::attribute::AttributeReadGuard;
namespace select {
- struct Guards : public std::vector<AttributeGuard> {
- using Parent = std::vector<AttributeGuard>;
- using Parent::Parent;
- };
+struct Guards : public std::vector<std::unique_ptr<AttributeReadGuard>> {
+ using Parent = std::vector<std::unique_ptr<AttributeReadGuard>>;
+ using Parent::Parent;
+};
}
SelectContext::SelectContext(const CachedSelect &cachedSelect)
@@ -26,23 +28,30 @@ SelectContext::SelectContext(const CachedSelect &cachedSelect)
_cachedSelect(cachedSelect)
{ }
-SelectContext::~SelectContext() { }
+SelectContext::~SelectContext() = default;
void
SelectContext::getAttributeGuards()
{
- _guards->resize(_cachedSelect.attributes().size());
- auto j(_cachedSelect.attributes().begin());
- for (std::vector<AttributeGuard>::iterator i(_guards->begin()), ie(_guards->end()); i != ie; ++i, ++j) {
- *i = AttributeGuard(*j);
+ _guards->clear();
+ _guards->reserve(_cachedSelect.attributes().size());
+ for (const auto& attr : _cachedSelect.attributes()) {
+ _guards->emplace_back(attr->makeReadGuard(false));
}
}
-
void
SelectContext::dropAttributeGuards()
{
_guards->clear();
}
+const search::attribute::AttributeReadGuard&
+SelectContext::read_guard_at_index(uint32_t index) const noexcept
+{
+ assert(index < _guards->size());
+ assert((*_guards)[index].get() != nullptr);
+ return *((*_guards)[index]);
+}
+
}
diff --git a/searchcore/src/vespa/searchcore/proton/common/selectcontext.h b/searchcore/src/vespa/searchcore/proton/common/selectcontext.h
index d37c6eb6f14..84e51bc611b 100644
--- a/searchcore/src/vespa/searchcore/proton/common/selectcontext.h
+++ b/searchcore/src/vespa/searchcore/proton/common/selectcontext.h
@@ -3,6 +3,8 @@
#include <vespa/document/select/context.h>
+namespace search::attribute { class AttributeReadGuard; }
+
namespace proton {
class CachedSelect;
@@ -19,6 +21,8 @@ public:
void dropAttributeGuards();
uint32_t _docId;
+
+ const search::attribute::AttributeReadGuard& read_guard_at_index(uint32_t index) const noexcept;
private:
std::unique_ptr<select::Guards> _guards;
const CachedSelect &_cachedSelect;
diff --git a/searchcore/src/vespa/searchcore/proton/common/selectpruner.cpp b/searchcore/src/vespa/searchcore/proton/common/selectpruner.cpp
index 6cad54f134b..4ed404333b5 100644
--- a/searchcore/src/vespa/searchcore/proton/common/selectpruner.cpp
+++ b/searchcore/src/vespa/searchcore/proton/common/selectpruner.cpp
@@ -12,6 +12,7 @@
#include <vespa/document/select/invalidconstant.h>
#include <vespa/document/select/valuenodes.h>
#include <vespa/searchlib/attribute/attributevector.h>
+#include <vespa/searchlib/attribute/attribute_read_guard.h>
#include <vespa/searchlib/attribute/iattributemanager.h>
using document::select::And;
@@ -395,7 +396,6 @@ SelectPruner::visitIdValueNode(const IdValueNode &expr)
CloningVisitor::visitIdValueNode(expr);
}
-
void
SelectPruner::visitFieldValueNode(const FieldValueNode &expr)
{
@@ -440,11 +440,11 @@ SelectPruner::visitFieldValueNode(const FieldValueNode &expr)
bool svAttr = false;
bool attrField = false;
if (_amgr != nullptr) {
- AttributeGuard::UP ag(_amgr->getAttribute(name));
- if (ag->valid()) {
+ auto attr = _amgr->readable_attribute_vector(name);
+ if (attr) {
attrField = true;
- auto av(ag->getSP());
- if (av->getCollectionType() == CollectionType::SINGLE && !complex) {
+ auto ag = attr->makeReadGuard(false);
+ if ((ag->attribute()->getCollectionType() == CollectionType::SINGLE) && !complex) {
svAttr = true;
}
}
diff --git a/searchcore/src/vespa/searchcore/proton/test/mock_attribute_manager.h b/searchcore/src/vespa/searchcore/proton/test/mock_attribute_manager.h
index 87fa2053508..57c86855217 100644
--- a/searchcore/src/vespa/searchcore/proton/test/mock_attribute_manager.h
+++ b/searchcore/src/vespa/searchcore/proton/test/mock_attribute_manager.h
@@ -78,6 +78,9 @@ public:
void asyncForAttribute(const vespalib::string & name, std::unique_ptr<IAttributeFunctor> func) const override {
_mock.asyncForAttribute(name, std::move(func));
}
+ std::shared_ptr<search::attribute::ReadableAttributeVector> readable_attribute_vector(const string& name) const override {
+ return _mock.readable_attribute_vector(name);
+ }
};
}