diff options
author | Geir Storli <geirstorli@yahoo.no> | 2018-05-31 14:50:12 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-05-31 14:50:12 +0200 |
commit | 721180812680b7a5dd8bae87e1a114ff8ef5ed98 (patch) | |
tree | a40ffd1ee5d233763edf3f69adc6201e72d42641 | |
parent | ac9c5c9f7656c55a8d2a014a4e1dc02c1b2caf5f (diff) | |
parent | 28ff792377209e754e730dfac77c9d95767b44a2 (diff) |
Merge pull request #6021 from vespa-engine/balder/compute-updatescope-inline-rebased
Balder/compute updatescope inline rebased
12 files changed, 154 insertions, 168 deletions
diff --git a/searchcore/src/tests/proton/attribute/attribute_test.cpp b/searchcore/src/tests/proton/attribute/attribute_test.cpp index f7777ece4ac..98a76023c47 100644 --- a/searchcore/src/tests/proton/attribute/attribute_test.cpp +++ b/searchcore/src/tests/proton/attribute/attribute_test.cpp @@ -1,6 +1,4 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -#include <vespa/log/log.h> -LOG_SETUP("attribute_test"); #include <vespa/config-attributes.h> #include <vespa/document/fieldvalue/document.h> @@ -15,6 +13,7 @@ LOG_SETUP("attribute_test"); #include <vespa/searchcommon/attribute/attributecontent.h> #include <vespa/searchcore/proton/attribute/attribute_collection_spec_factory.h> #include <vespa/searchcore/proton/attribute/attribute_writer.h> +#include <vespa/searchcore/proton/attribute/ifieldupdatecallback.h> #include <vespa/searchcore/proton/attribute/attributemanager.h> #include <vespa/searchcore/proton/attribute/filter_attribute_manager.h> #include <vespa/searchcore/proton/attribute/imported_attributes_repo.h> @@ -44,6 +43,9 @@ LOG_SETUP("attribute_test"); #include <vespa/vespalib/testkit/testapp.h> #include <vespa/searchcommon/attribute/iattributevector.h> +#include <vespa/log/log.h> +LOG_SETUP("attribute_test"); + namespace vespa { namespace config { namespace search {}}} using namespace config; @@ -156,8 +158,8 @@ struct Fixture _aw->put(serialNum, doc, lid, immediateCommit, emptyCallback); } void update(SerialNum serialNum, const DocumentUpdate &upd, - DocumentIdT lid, bool immediateCommit) { - _aw->update(serialNum, upd, lid, immediateCommit, emptyCallback); + DocumentIdT lid, bool immediateCommit, IFieldUpdateCallback & onUpdate) { + _aw->update(serialNum, upd, lid, immediateCommit, emptyCallback, onUpdate); } void update(SerialNum serialNum, const Document &doc, DocumentIdT lid, bool immediateCommit) { @@ -448,8 +450,9 @@ TEST_F("require that attribute writer handles update", Fixture) upd.addUpdate(FieldUpdate(upd.getType().getField("a2")) .addUpdate(ArithmeticValueUpdate(ArithmeticValueUpdate::Add, 10))); + DummyFieldUpdateCallback onUpdate; bool immediateCommit = true; - f.update(2, upd, 1, immediateCommit); + f.update(2, upd, 1, immediateCommit, onUpdate); attribute::IntegerContent ibuf; ibuf.fill(*a1, 1); @@ -459,9 +462,9 @@ TEST_F("require that attribute writer handles update", Fixture) EXPECT_EQUAL(1u, ibuf.size()); EXPECT_EQUAL(30u, ibuf[0]); - f.update(2, upd, 1, immediateCommit); // same sync token as previous + f.update(2, upd, 1, immediateCommit, onUpdate); // same sync token as previous try { - f.update(1, upd, 1, immediateCommit); // lower sync token than previous + f.update(1, upd, 1, immediateCommit, onUpdate); // lower sync token than previous EXPECT_TRUE(true); // update is ignored } catch (vespalib::IllegalStateException & e) { LOG(info, "Got expected exception: '%s'", e.getMessage().c_str()); @@ -494,7 +497,8 @@ TEST_F("require that attribute writer handles predicate update", Fixture) EXPECT_EQUAL(1u, index.getZeroConstraintDocs().size()); EXPECT_FALSE(index.getIntervalIndex().lookup(PredicateHash::hash64("foo=bar")).valid()); bool immediateCommit = true; - f.update(2, upd, 1, immediateCommit); + DummyFieldUpdateCallback onUpdate; + f.update(2, upd, 1, immediateCommit, onUpdate); EXPECT_EQUAL(0u, index.getZeroConstraintDocs().size()); EXPECT_TRUE(index.getIntervalIndex().lookup(PredicateHash::hash64("foo=bar")).valid()); } @@ -681,7 +685,8 @@ TEST_F("require that attribute writer handles tensor assign update", Fixture) upd.addUpdate(FieldUpdate(upd.getType().getField("a1")) .addUpdate(AssignValueUpdate(new_value))); bool immediateCommit = true; - f.update(2, upd, 1, immediateCommit); + DummyFieldUpdateCallback onUpdate; + f.update(2, upd, 1, immediateCommit, onUpdate); EXPECT_EQUAL(2u, a1->getNumDocs()); EXPECT_TRUE(tensorAttribute != nullptr); tensor2 = tensorAttribute->getTensor(1); @@ -795,6 +800,7 @@ struct StructFixtureBase : public Fixture _type.addField(_valueField); _structFieldType.addField(_valueField); } + ~StructFixtureBase(); std::unique_ptr<StructFieldValue> makeStruct() @@ -817,6 +823,7 @@ struct StructFixtureBase : public Fixture } }; +StructFixtureBase::~StructFixtureBase() = default; struct StructArrayFixture : public StructFixtureBase { @@ -832,6 +839,7 @@ struct StructArrayFixture : public StructFixtureBase addAttribute({"array.value", AVConfig(AVBasicType::INT32, AVCollectionType::ARRAY)}, createSerialNum); _type.addField(_structArrayField); } + ~StructArrayFixture(); std::unique_ptr<Document> makeDoc(int32_t value, const std::vector<int32_t> &arrayValues) @@ -858,6 +866,8 @@ struct StructArrayFixture : public StructFixtureBase } }; +StructArrayFixture::~StructArrayFixture() = default; + TEST_F("require that update with doc argument only updates compound attributes", StructArrayFixture) { auto doc = f.makeDoc(10, {11, 12}); diff --git a/searchcore/src/tests/proton/documentdb/feedview/feedview_test.cpp b/searchcore/src/tests/proton/documentdb/feedview/feedview_test.cpp index 6b27141a315..5d040024e63 100644 --- a/searchcore/src/tests/proton/documentdb/feedview/feedview_test.cpp +++ b/searchcore/src/tests/proton/documentdb/feedview/feedview_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/searchcore/proton/attribute/i_attribute_writer.h> +#include <vespa/searchcore/proton/attribute/ifieldupdatecallback.h> #include <vespa/searchcore/proton/test/bucketfactory.h> #include <vespa/searchcore/proton/common/commit_time_tracker.h> #include <vespa/searchcore/proton/common/feedtoken.h> @@ -316,21 +317,23 @@ struct MyAttributeWriter : public IAttributeWriter std::set<vespalib::string> _attrs; proton::IAttributeManager::SP _mgr; MyTracer &_tracer; + MyAttributeWriter(MyTracer &tracer); ~MyAttributeWriter(); - virtual std::vector<AttributeVector *> + + std::vector<AttributeVector *> getWritableAttributes() const override { return std::vector<AttributeVector *>(); } - virtual AttributeVector *getWritableAttribute(const vespalib::string &attrName) const override { + AttributeVector *getWritableAttribute(const vespalib::string &attrName) const override { if (_attrs.count(attrName) == 0) { return nullptr; } AttrMap::const_iterator itr = _attrMap.find(attrName); return ((itr == _attrMap.end()) ? nullptr : itr->second.get()); } - virtual void put(SerialNum serialNum, const document::Document &doc, DocumentIdT lid, - bool immediateCommit, OnWriteDoneType) override { + void put(SerialNum serialNum, const document::Document &doc, DocumentIdT lid, + bool immediateCommit, OnWriteDoneType) override { _putSerial = serialNum; _putDocId = doc.getId(); _putLid = lid; @@ -339,8 +342,8 @@ struct MyAttributeWriter : public IAttributeWriter ++_commitCount; } } - virtual void remove(SerialNum serialNum, DocumentIdT lid, - bool immediateCommit, OnWriteDoneType) override { + void remove(SerialNum serialNum, DocumentIdT lid, + bool immediateCommit, OnWriteDoneType) override { _removeSerial = serialNum; _removeLid = lid; _tracer.traceRemove(attributeAdapterTypeName, serialNum, lid, immediateCommit); @@ -348,45 +351,45 @@ struct MyAttributeWriter : public IAttributeWriter ++_commitCount; } } - virtual void remove(const LidVector & lidsToRemove, SerialNum serialNum, - bool immediateCommit, OnWriteDoneType) override { + void remove(const LidVector & lidsToRemove, SerialNum serialNum, + bool immediateCommit, OnWriteDoneType) override { for (uint32_t lid : lidsToRemove) { LOG(info, "MyAttributeAdapter::remove(): serialNum(%" PRIu64 "), docId(%u)", serialNum, lid); _removes.push_back(lid); _tracer.traceRemove(attributeAdapterTypeName, serialNum, lid, immediateCommit); } } - virtual void update(SerialNum serialNum, const document::DocumentUpdate &upd, - DocumentIdT lid, bool, OnWriteDoneType) override { + void update(SerialNum serialNum, const document::DocumentUpdate &upd, + DocumentIdT lid, bool, OnWriteDoneType, IFieldUpdateCallback & onUpdate) override { _updateSerial = serialNum; _updateDocId = upd.getId(); _updateLid = lid; + for (const auto & fieldUpdate : upd.getUpdates()) { + search::AttributeVector * attr = getWritableAttribute(fieldUpdate.getField().getName()); + onUpdate.onUpdateField(fieldUpdate.getField().getName(), attr); + } } - virtual void update(SerialNum serialNum, const document::Document &doc, DocumentIdT lid, - bool immediateCommit, OnWriteDoneType) override { + void update(SerialNum serialNum, const document::Document &doc, DocumentIdT lid, + bool immediateCommit, OnWriteDoneType) override { (void) serialNum; (void) doc; (void) lid; (void) immediateCommit; } - virtual void heartBeat(SerialNum) override { ++_heartBeatCount; } - virtual void compactLidSpace(uint32_t wantedLidLimit, SerialNum serialNum) override { - (void) serialNum; + void heartBeat(SerialNum) override { ++_heartBeatCount; } + void compactLidSpace(uint32_t wantedLidLimit, SerialNum ) override { _wantedLidLimit = wantedLidLimit; } - virtual const proton::IAttributeManager::SP &getAttributeManager() const override { + const proton::IAttributeManager::SP &getAttributeManager() const override { return _mgr; } void forceCommit(SerialNum serialNum, OnWriteDoneType) override { - (void) serialNum; ++_commitCount; + ++_commitCount; _tracer.traceCommit(attributeAdapterTypeName, serialNum); } - virtual void onReplayDone(uint32_t docIdLimit) override - { - (void) docIdLimit; - } - virtual bool getHasCompoundAttribute() const override { return false; } + void onReplayDone(uint32_t ) override { } + bool getHasCompoundAttribute() const override { return false; } }; MyAttributeWriter::MyAttributeWriter(MyTracer &tracer) @@ -404,7 +407,7 @@ MyAttributeWriter::MyAttributeWriter(MyTracer &tracer) cfg3.setTensorType(ValueType::from_spec("tensor(x[10])")); _attrMap["a3"] = search::AttributeFactory::createAttribute("test3", cfg3); } -MyAttributeWriter::~MyAttributeWriter() {} +MyAttributeWriter::~MyAttributeWriter() = default; struct MyTransport : public feedtoken::ITransport { @@ -428,7 +431,7 @@ struct MyResultHandler : public IGenericResultHandler { vespalib::Gate _gate; MyResultHandler() : _gate() {} - virtual void handle(const storage::spi::Result &) override { + void handle(const storage::spi::Result &) override { _gate.countDown(); } void await() { _gate.await(); } @@ -454,7 +457,7 @@ SchemaContext::SchemaContext() : _schema->addSummaryField(Schema::SummaryField("s1", DataType::STRING, CollectionType::SINGLE)); _builder.reset(new DocBuilder(*_schema)); } -SchemaContext::~SchemaContext() {} +SchemaContext::~SchemaContext() = default; struct DocumentContext diff --git a/searchcore/src/vespa/searchcore/proton/attribute/attribute_writer.cpp b/searchcore/src/vespa/searchcore/proton/attribute/attribute_writer.cpp index f2ab6e1f287..4d38288e9aa 100644 --- a/searchcore/src/vespa/searchcore/proton/attribute/attribute_writer.cpp +++ b/searchcore/src/vespa/searchcore/proton/attribute/attribute_writer.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 "attribute_writer.h" +#include "ifieldupdatecallback.h" #include "attributemanager.h" #include "document_field_extractor.h" #include <vespa/document/base/exceptions.h> @@ -500,17 +501,15 @@ AttributeWriter::remove(const LidVector &lidsToRemove, SerialNum serialNum, void AttributeWriter::update(SerialNum serialNum, const DocumentUpdate &upd, DocumentIdT lid, - bool immediateCommit, OnWriteDoneType onWriteDone) + bool immediateCommit, OnWriteDoneType onWriteDone, IFieldUpdateCallback & onUpdate) { LOG(debug, "Inspecting update for document %d.", lid); for (const auto &fupd : upd.getUpdates()) { - LOG(debug, "Retrieving guard for attribute vector '%s'.", - fupd.getField().getName().c_str()); - AttributeVector *attrp = - _mgr->getWritableAttribute(fupd.getField().getName()); + LOG(debug, "Retrieving guard for attribute vector '%s'.", fupd.getField().getName().c_str()); + AttributeVector *attrp = _mgr->getWritableAttribute(fupd.getField().getName()); + onUpdate.onUpdateField(fupd.getField().getName(), attrp); if (attrp == nullptr) { - LOG(spam, "Failed to find attribute vector %s", - fupd.getField().getName().c_str()); + LOG(spam, "Failed to find attribute vector %s", fupd.getField().getName().c_str()); continue; } AttributeVector &attr = *attrp; @@ -519,8 +518,7 @@ AttributeWriter::update(SerialNum serialNum, const DocumentUpdate &upd, Document if (attr.getStatus().getLastSyncToken() >= serialNum) continue; - LOG(debug, "About to apply update for docId %u in attribute vector '%s'.", - lid, attr.getName().c_str()); + LOG(debug, "About to apply update for docId %u in attribute vector '%s'.", lid, attr.getName().c_str()); // NOTE: The lifetime of the field update will be ensured by keeping the document update alive // in a operation done context object. diff --git a/searchcore/src/vespa/searchcore/proton/attribute/attribute_writer.h b/searchcore/src/vespa/searchcore/proton/attribute/attribute_writer.h index 1820eeb4690..295f873567a 100644 --- a/searchcore/src/vespa/searchcore/proton/attribute/attribute_writer.h +++ b/searchcore/src/vespa/searchcore/proton/attribute/attribute_writer.h @@ -82,7 +82,7 @@ public: void remove(const LidVector &lidVector, SerialNum serialNum, bool immediateCommit, OnWriteDoneType onWriteDone) override; void update(SerialNum serialNum, const DocumentUpdate &upd, DocumentIdT lid, - bool immediateCommit, OnWriteDoneType onWriteDone) override; + bool immediateCommit, OnWriteDoneType onWriteDone, IFieldUpdateCallback & onUpdate) override; void update(SerialNum serialNum, const Document &doc, DocumentIdT lid, bool immediateCommit, OnWriteDoneType onWriteDone) override; void heartBeat(SerialNum serialNum) override; @@ -92,8 +92,8 @@ public: } void forceCommit(SerialNum serialNum, OnWriteDoneType onWriteDone) override; - virtual void onReplayDone(uint32_t docIdLimit) override; - virtual bool getHasCompoundAttribute() const override; + void onReplayDone(uint32_t docIdLimit) override; + bool getHasCompoundAttribute() const override; }; } // namespace proton diff --git a/searchcore/src/vespa/searchcore/proton/attribute/i_attribute_writer.h b/searchcore/src/vespa/searchcore/proton/attribute/i_attribute_writer.h index 34d827a6d84..7a557b17964 100644 --- a/searchcore/src/vespa/searchcore/proton/attribute/i_attribute_writer.h +++ b/searchcore/src/vespa/searchcore/proton/attribute/i_attribute_writer.h @@ -1,18 +1,20 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. #pragma once -#include <vespa/document/fieldvalue/document.h> -#include <vespa/document/update/documentupdate.h> +#include "i_attribute_manager.h" +#include <vespa/searchcore/proton/feedoperation/lidvectorcontext.h> #include <vespa/searchlib/attribute/attributeguard.h> #include <vespa/searchlib/query/base.h> #include <vespa/searchlib/common/serialnum.h> -#include <vespa/searchcore/proton/attribute/i_attribute_manager.h> -#include <vespa/searchcore/proton/feedoperation/lidvectorcontext.h> +#include <vespa/document/fieldvalue/document.h> +#include <vespa/document/update/documentupdate.h> namespace search { class IDestructorCallback; } namespace proton { +class IFieldUpdateCallback; + /** * Interface for an attribute writer that handles writes in form of put, update and remove * to an underlying set of attribute vectors. @@ -31,10 +33,8 @@ public: virtual ~IAttributeWriter() {} - virtual std::vector<search::AttributeVector *> - getWritableAttributes() const = 0; - virtual search::AttributeVector * - getWritableAttribute(const vespalib::string &attrName) const = 0; + virtual std::vector<search::AttributeVector *> getWritableAttributes() const = 0; + virtual search::AttributeVector *getWritableAttribute(const vespalib::string &attrName) const = 0; virtual void put(SerialNum serialNum, const Document &doc, DocumentIdT lid, bool immediateCommit, OnWriteDoneType onWriteDone) = 0; virtual void remove(SerialNum serialNum, DocumentIdT lid, bool immediateCommit, @@ -46,7 +46,7 @@ public: * The OnWriteDoneType instance should ensure the lifetime of the given DocumentUpdate instance. */ virtual void update(SerialNum serialNum, const DocumentUpdate &upd, DocumentIdT lid, - bool immediateCommit, OnWriteDoneType onWriteDone) = 0; + bool immediateCommit, OnWriteDoneType onWriteDone, IFieldUpdateCallback & onUpdate) = 0; /* * Update the underlying compound attributes based on updated document. */ diff --git a/searchcore/src/vespa/searchcore/proton/attribute/ifieldupdatecallback.h b/searchcore/src/vespa/searchcore/proton/attribute/ifieldupdatecallback.h new file mode 100644 index 00000000000..ffb8555cd2c --- /dev/null +++ b/searchcore/src/vespa/searchcore/proton/attribute/ifieldupdatecallback.h @@ -0,0 +1,20 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#pragma once + +#include <vespa/vespalib/stllike/string.h> + +namespace search { class AttributeVector; } + +namespace proton { + +struct IFieldUpdateCallback { + virtual ~IFieldUpdateCallback() { } + virtual void onUpdateField(vespalib::stringref fieldName, const search::AttributeVector * attr) = 0; +}; + +struct DummyFieldUpdateCallback : IFieldUpdateCallback { + void onUpdateField(vespalib::stringref, const search::AttributeVector *) override {} +}; + +} diff --git a/searchcore/src/vespa/searchcore/proton/server/fast_access_feed_view.cpp b/searchcore/src/vespa/searchcore/proton/server/fast_access_feed_view.cpp index 7de2dd74400..78733b14aaa 100644 --- a/searchcore/src/vespa/searchcore/proton/server/fast_access_feed_view.cpp +++ b/searchcore/src/vespa/searchcore/proton/server/fast_access_feed_view.cpp @@ -13,23 +13,6 @@ using search::index::Schema; namespace proton { -FastAccessFeedView::UpdateScope -FastAccessFeedView::getUpdateScope(const DocumentUpdate &upd) -{ - UpdateScope updateScope; - for (const auto &update : upd.getUpdates()) { - const vespalib::string &fieldName = update.getField().getName(); - if (!fastPartialUpdateAttribute(fieldName)) { - updateScope._nonAttributeFields = true; - break; - } - } - if (!upd.getFieldPathUpdates().empty()) { - updateScope._nonAttributeFields = true; - } - return updateScope; -} - /** * NOTE: For both put, update and remove we only need to pass the 'onWriteDone' * instance when we are going to commit as part of handling the operation. @@ -47,9 +30,9 @@ FastAccessFeedView::putAttributes(SerialNum serialNum, search::DocumentIdT lid, void FastAccessFeedView::updateAttributes(SerialNum serialNum, search::DocumentIdT lid, const DocumentUpdate &upd, - bool immediateCommit, OnOperationDoneType onWriteDone) + bool immediateCommit, OnOperationDoneType onWriteDone, IFieldUpdateCallback & onUpdate) { - _attributeWriter->update(serialNum, upd, lid, immediateCommit, onWriteDone); + _attributeWriter->update(serialNum, upd, lid, immediateCommit, onWriteDone, onUpdate); } void @@ -116,19 +99,4 @@ FastAccessFeedView::sync() _writeService.attributeFieldWriter().sync(); } -bool -FastAccessFeedView::fastPartialUpdateAttribute(const vespalib::string &fieldName) const { - search::AttributeVector *attribute = _attributeWriter->getWritableAttribute(fieldName); - if (attribute == nullptr) { - // Partial update to non-attribute field must update document - return false; - } - search::attribute::BasicType::Type attrType = attribute->getBasicType(); - // Partial update to tensor, predicate or reference attribute - // must update document - return ((attrType != search::attribute::BasicType::Type::PREDICATE) && - (attrType != search::attribute::BasicType::Type::TENSOR) && - (attrType != search::attribute::BasicType::Type::REFERENCE)); -} - } // namespace proton diff --git a/searchcore/src/vespa/searchcore/proton/server/fast_access_feed_view.h b/searchcore/src/vespa/searchcore/proton/server/fast_access_feed_view.h index 217fe5acf4a..3af97b4ecb9 100644 --- a/searchcore/src/vespa/searchcore/proton/server/fast_access_feed_view.h +++ b/searchcore/src/vespa/searchcore/proton/server/fast_access_feed_view.h @@ -39,13 +39,11 @@ private: const IAttributeWriter::SP _attributeWriter; DocIdLimit &_docIdLimit; - UpdateScope getUpdateScope(const document::DocumentUpdate &upd) override; - void putAttributes(SerialNum serialNum, search::DocumentIdT lid, const document::Document &doc, bool immediateCommit, OnPutDoneType onWriteDone) override; void updateAttributes(SerialNum serialNum, search::DocumentIdT lid, const document::DocumentUpdate &upd, - bool immediateCommit, OnOperationDoneType onWriteDone) override; + bool immediateCommit, OnOperationDoneType onWriteDone, IFieldUpdateCallback & onUpdate) override; void updateAttributes(SerialNum serialNum, Lid lid, FutureDoc doc, bool immediateCommit, OnOperationDoneType onWriteDone) override; void removeAttributes(SerialNum serialNum, search::DocumentIdT lid, @@ -74,8 +72,6 @@ public: void handleCompactLidSpace(const CompactLidSpaceOperation &op) override; void sync() override; - - bool fastPartialUpdateAttribute(const vespalib::string &fieldName) const; }; } // namespace proton diff --git a/searchcore/src/vespa/searchcore/proton/server/searchable_feed_view.cpp b/searchcore/src/vespa/searchcore/proton/server/searchable_feed_view.cpp index 88ddd9730df..4cda07eee8b 100644 --- a/searchcore/src/vespa/searchcore/proton/server/searchable_feed_view.cpp +++ b/searchcore/src/vespa/searchcore/proton/server/searchable_feed_view.cpp @@ -118,29 +118,6 @@ SearchableFeedView::performIndexHeartBeat(SerialNum serialNum) _indexWriter->heartBeat(serialNum); } -SearchableFeedView::UpdateScope -SearchableFeedView::getUpdateScope(const DocumentUpdate &upd) -{ - UpdateScope updateScope; - const Schema &schema = *_schema; - for(size_t i(0), m(upd.getUpdates().size()); - !(updateScope._indexedFields && updateScope._nonAttributeFields) && - (i < m); i++) { - const document::FieldUpdate & fu(upd.getUpdates()[i]); - const vespalib::string &name = fu.getField().getName(); - if (schema.isIndexField(name)) { - updateScope._indexedFields = true; - } - if (!fastPartialUpdateAttribute(name)) { - updateScope._nonAttributeFields = true; - } - } - if (!upd.getFieldPathUpdates().empty()) { - updateScope._nonAttributeFields = true; - } - return updateScope; -} - void SearchableFeedView::updateIndexedFields(SerialNum serialNum, search::DocumentIdT lid, FutureDoc futureDoc, bool immediateCommit, OnOperationDoneType onWriteDone) diff --git a/searchcore/src/vespa/searchcore/proton/server/searchable_feed_view.h b/searchcore/src/vespa/searchcore/proton/server/searchable_feed_view.h index 81d81a6cc27..ed3ba6740b1 100644 --- a/searchcore/src/vespa/searchcore/proton/server/searchable_feed_view.h +++ b/searchcore/src/vespa/searchcore/proton/server/searchable_feed_view.h @@ -34,24 +34,19 @@ private: bool hasIndexedFields() const { return _hasIndexedFields; } - void - performIndexPut(SerialNum serialNum, search::DocumentIdT lid, const document::Document &doc, - bool immediateCommit, OnOperationDoneType onWriteDone); + void performIndexPut(SerialNum serialNum, search::DocumentIdT lid, const document::Document &doc, + bool immediateCommit, OnOperationDoneType onWriteDone); - void - performIndexPut(SerialNum serialNum, search::DocumentIdT lid, const document::Document::SP &doc, - bool immediateCommit, OnOperationDoneType onWriteDone); - void - performIndexPut(SerialNum serialNum, search::DocumentIdT lid, FutureDoc doc, - bool immediateCommit, OnOperationDoneType onWriteDone); + void performIndexPut(SerialNum serialNum, search::DocumentIdT lid, const document::Document::SP &doc, + bool immediateCommit, OnOperationDoneType onWriteDone); + void performIndexPut(SerialNum serialNum, search::DocumentIdT lid, FutureDoc doc, + bool immediateCommit, OnOperationDoneType onWriteDone); - void - performIndexRemove(SerialNum serialNum, search::DocumentIdT lid, - bool immediateCommit, OnRemoveDoneType onWriteDone); + void performIndexRemove(SerialNum serialNum, search::DocumentIdT lid, + bool immediateCommit, OnRemoveDoneType onWriteDone); - void - performIndexRemove(SerialNum serialNum, const LidVector &lidsToRemove, - bool immediateCommit, OnWriteDoneType onWriteDone); + void performIndexRemove(SerialNum serialNum, const LidVector &lidsToRemove, + bool immediateCommit, OnWriteDoneType onWriteDone); void performIndexHeartBeat(SerialNum serialNum); @@ -60,23 +55,17 @@ private: void performSync(); void heartBeatIndexedFields(SerialNum serialNum) override; - virtual void - putIndexedFields(SerialNum serialNum, search::DocumentIdT lid, const document::Document::SP &newDoc, - bool immediateCommit, OnOperationDoneType onWriteDone) override; + void putIndexedFields(SerialNum serialNum, search::DocumentIdT lid, const document::Document::SP &newDoc, + bool immediateCommit, OnOperationDoneType onWriteDone) override; - UpdateScope getUpdateScope(const document::DocumentUpdate &upd) override; + void updateIndexedFields(SerialNum serialNum, search::DocumentIdT lid, FutureDoc newDoc, + bool immediateCommit, OnOperationDoneType onWriteDone) override; - virtual void - updateIndexedFields(SerialNum serialNum, search::DocumentIdT lid, FutureDoc newDoc, - bool immediateCommit, OnOperationDoneType onWriteDone) override; + void removeIndexedFields(SerialNum serialNum, search::DocumentIdT lid, + bool immediateCommit, OnRemoveDoneType onWriteDone) override; - virtual void - removeIndexedFields(SerialNum serialNum, search::DocumentIdT lid, - bool immediateCommit, OnRemoveDoneType onWriteDone) override; - - virtual void - removeIndexedFields(SerialNum serialNum, const LidVector &lidsToRemove, - bool immediateCommit, OnWriteDoneType onWriteDone) override; + void removeIndexedFields(SerialNum serialNum, const LidVector &lidsToRemove, + bool immediateCommit, OnWriteDoneType onWriteDone) override; void performIndexForceCommit(SerialNum serialNum, OnForceCommitDoneType onCommitDone); void forceCommit(SerialNum serialNum, OnForceCommitDoneType onCommitDone) override; @@ -85,7 +74,7 @@ public: SearchableFeedView(const StoreOnlyFeedView::Context &storeOnlyCtx, const PersistentParams ¶ms, const FastAccessFeedView::Context &fastUpdateCtx, Context ctx); - virtual ~SearchableFeedView(); + ~SearchableFeedView() override; const IIndexWriter::SP &getIndexWriter() const { return _indexWriter; } void sync() override; }; diff --git a/searchcore/src/vespa/searchcore/proton/server/storeonlyfeedview.cpp b/searchcore/src/vespa/searchcore/proton/server/storeonlyfeedview.cpp index 34902e5c673..a0f6ee98b71 100644 --- a/searchcore/src/vespa/searchcore/proton/server/storeonlyfeedview.cpp +++ b/searchcore/src/vespa/searchcore/proton/server/storeonlyfeedview.cpp @@ -17,6 +17,8 @@ #include <vespa/vespalib/util/exceptions.h> #include <vespa/log/log.h> +#include <vespa/searchcore/proton/attribute/ifieldupdatecallback.h> + LOG_SETUP(".proton.server.storeonlyfeedview"); using document::BucketId; @@ -300,21 +302,15 @@ StoreOnlyFeedView::heartBeatIndexedFields(SerialNum ) {} void StoreOnlyFeedView::heartBeatAttributes(SerialNum ) {} - -StoreOnlyFeedView::UpdateScope -StoreOnlyFeedView::getUpdateScope(const DocumentUpdate &upd) +void +StoreOnlyFeedView::updateAttributes(SerialNum, Lid, const DocumentUpdate & upd, bool, + OnOperationDoneType, IFieldUpdateCallback & onUpdate) { - UpdateScope updateScope; - if (!upd.getUpdates().empty() || !upd.getFieldPathUpdates().empty()) { - updateScope._nonAttributeFields = true; + for (const auto & fieldUpdate : upd.getUpdates()) { + onUpdate.onUpdateField(fieldUpdate.getField().getName(), nullptr); } - return updateScope; } - -void -StoreOnlyFeedView::updateAttributes(SerialNum, Lid, const DocumentUpdate &, bool, OnOperationDoneType) {} - void StoreOnlyFeedView::updateAttributes(SerialNum, Lid, FutureDoc, bool, OnOperationDoneType) { @@ -390,6 +386,34 @@ void StoreOnlyFeedView::heartBeatSummary(SerialNum serialNum) { })); } +StoreOnlyFeedView::UpdateScope::UpdateScope(const search::index::Schema & schema, const DocumentUpdate & upd) + : _schema(&schema), + _indexedFields(false), + _nonAttributeFields(!upd.getFieldPathUpdates().empty()) +{} + +namespace { + +bool isAttributeUpdateable(const search::AttributeVector *attribute) { + search::attribute::BasicType::Type attrType = attribute->getBasicType(); + // Partial update to tensor, predicate or reference attribute + // must update document + return ((attrType != search::attribute::BasicType::Type::PREDICATE) && + (attrType != search::attribute::BasicType::Type::TENSOR) && + (attrType != search::attribute::BasicType::Type::REFERENCE)); +} +} + +void +StoreOnlyFeedView::UpdateScope::onUpdateField(vespalib::stringref fieldName, const search::AttributeVector * attr) { + if (!_nonAttributeFields && (attr == nullptr || !isAttributeUpdateable(attr))) { + _nonAttributeFields = true; + } + if (!_indexedFields && _schema->isIndexField(fieldName)) { + _indexedFields = true; + } +} + void StoreOnlyFeedView::internalUpdate(FeedToken token, const UpdateOperation &updOp) { if ( ! updOp.getUpdate()) { @@ -422,9 +446,9 @@ StoreOnlyFeedView::internalUpdate(FeedToken token, const UpdateOperation &updOp) bool immediateCommit = _commitTimeTracker.needCommit(); auto onWriteDone = createUpdateDoneContext(std::move(token), updOp.getUpdate()); - updateAttributes(serialNum, lid, upd, immediateCommit, onWriteDone); + UpdateScope updateScope(*_schema, upd); + updateAttributes(serialNum, lid, upd, immediateCommit, onWriteDone, updateScope); - UpdateScope updateScope(getUpdateScope(upd)); if (updateScope.hasIndexOrNonAttributeFields()) { PromisedDoc promisedDoc; FutureDoc futureDoc = promisedDoc.get_future().share(); diff --git a/searchcore/src/vespa/searchcore/proton/server/storeonlyfeedview.h b/searchcore/src/vespa/searchcore/proton/server/storeonlyfeedview.h index 1ccce8a4a09..a11512590f3 100644 --- a/searchcore/src/vespa/searchcore/proton/server/storeonlyfeedview.h +++ b/searchcore/src/vespa/searchcore/proton/server/storeonlyfeedview.h @@ -9,6 +9,7 @@ #include "searchcontext.h" #include "pendinglidtracker.h" #include <vespa/searchcore/proton/common/doctypename.h> +#include <vespa/searchcore/proton/attribute/ifieldupdatecallback.h> #include <vespa/searchcore/proton/common/feeddebugger.h> #include <vespa/searchcore/proton/documentmetastore/documentmetastore.h> #include <vespa/searchcore/proton/documentmetastore/documentmetastorecontext.h> @@ -33,6 +34,7 @@ class PutDoneContext; class RemoveDoneContext; class CommitTimeTracker; class IGidToLidChangeHandler; +class IFieldUpdateCallback; namespace documentmetastore { class ILidReuseDelayer; } @@ -120,18 +122,19 @@ public: }; protected: - struct UpdateScope + class UpdateScope : public IFieldUpdateCallback { + private: + const search::index::Schema *_schema; + public: bool _indexedFields; bool _nonAttributeFields; - UpdateScope() - : _indexedFields(false), - _nonAttributeFields(false) - {} + UpdateScope(const search::index::Schema & schema, const DocumentUpdate & upd); bool hasIndexOrNonAttributeFields() const { return _indexedFields || _nonAttributeFields; } + void onUpdateField(vespalib::stringref fieldName, const search::AttributeVector * attr) override; }; private: @@ -200,10 +203,8 @@ private: virtual void putIndexedFields(SerialNum serialNum, Lid lid, const DocumentSP &newDoc, bool immediateCommit, OnOperationDoneType onWriteDone); - virtual UpdateScope getUpdateScope(const DocumentUpdate &upd); - virtual void updateAttributes(SerialNum serialNum, Lid lid, const DocumentUpdate &upd, - bool immediateCommit, OnOperationDoneType onWriteDone); + bool immediateCommit, OnOperationDoneType onWriteDone, IFieldUpdateCallback & onUpdate); virtual void updateAttributes(SerialNum serialNum, Lid lid, FutureDoc doc, bool immediateCommit, OnOperationDoneType onWriteDone); |