diff options
author | Arne Juul <arnej@yahoo-inc.com> | 2018-06-20 09:48:02 +0200 |
---|---|---|
committer | Arne Juul <arnej@yahoo-inc.com> | 2018-06-20 09:48:02 +0200 |
commit | 44fc1380b66867958f89c47ac8752926b3787a4d (patch) | |
tree | ea324d387b055c3ccf0921f9f973c95b16bad2e2 /searchcore | |
parent | 016e584f0ad5a071e13d75eb8ad5ddb46b8c54f5 (diff) | |
parent | 79e7562d34a20ed28621a9ec0dc296eda0881428 (diff) |
Merge branch 'master' into arnej/use-log-abort
Diffstat (limited to 'searchcore')
57 files changed, 482 insertions, 321 deletions
diff --git a/searchcore/src/apps/vespa-transactionlog-inspect/vespa-transactionlog-inspect.cpp b/searchcore/src/apps/vespa-transactionlog-inspect/vespa-transactionlog-inspect.cpp index 17f1faffbba..8ffe4807427 100644 --- a/searchcore/src/apps/vespa-transactionlog-inspect/vespa-transactionlog-inspect.cpp +++ b/searchcore/src/apps/vespa-transactionlog-inspect/vespa-transactionlog-inspect.cpp @@ -1,8 +1,7 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -#include <vespa/config/helper/configgetter.h> - #include <vespa/searchcore/proton/server/replaypacketdispatcher.h> +#include <vespa/searchcore/proton/feedoperation/operations.h> #include <vespa/searchlib/common/fileheadercontext.h> #include <vespa/searchlib/transactionlog/translogclient.h> #include <vespa/searchlib/transactionlog/translogserver.h> diff --git a/searchcore/src/tests/proton/attribute/attribute_aspect_delayer/attribute_aspect_delayer_test.cpp b/searchcore/src/tests/proton/attribute/attribute_aspect_delayer/attribute_aspect_delayer_test.cpp index b700bf45820..716db497424 100644 --- a/searchcore/src/tests/proton/attribute/attribute_aspect_delayer/attribute_aspect_delayer_test.cpp +++ b/searchcore/src/tests/proton/attribute/attribute_aspect_delayer/attribute_aspect_delayer_test.cpp @@ -40,15 +40,24 @@ namespace proton namespace { -AttributesConfig::Attribute make_sv_cfg(AttributesConfig::Attribute::Datatype dataType) +AttributesConfig::Attribute make_sv_cfg(const vespalib::string &name, AttributesConfig::Attribute::Datatype dataType) { AttributesConfig::Attribute attr; - attr.name = "a"; + attr.name = name; attr.datatype = dataType; attr.collectiontype = AttributesConfig::Attribute::Collectiontype::SINGLE; return attr; } +AttributesConfig::Attribute make_sv_cfg(AttributesConfig::Attribute::Datatype dataType) +{ + return make_sv_cfg("a", dataType); +} + +AttributesConfig::Attribute make_int32_sv_cfg(const vespalib::string &name) { + return make_sv_cfg(name, AttributesConfig::Attribute::Datatype::INT32); +} + AttributesConfig::Attribute make_int32_sv_cfg() { return make_sv_cfg(AttributesConfig::Attribute::Datatype::INT32); } @@ -108,6 +117,14 @@ SummarymapConfig::Override make_geopos_override(const vespalib::string &name) return override; } +SummarymapConfig::Override make_attribute_combiner_override(const vespalib::string &name) +{ + SummarymapConfig::Override override; + override.field = name; + override.command = "attributecombiner"; + return override; +} + SummarymapConfig smCfg(std::vector<SummarymapConfig::Override> overrides) { SummarymapConfigBuilder result; @@ -310,6 +327,29 @@ TEST_F("require that fast access flag change is not delayed, true->false edge, s TEST_DO(f.assertSummarymapConfig({make_attribute_override("a")})); } +TEST_F("require that adding attribute aspect to struct field is not delayed if field type is changed", Fixture) +{ + f.setup(attrCfg({}), smCfg({}), attrCfg({make_int32_sv_cfg("array.a")}), smCfg({make_attribute_combiner_override("array")})); + TEST_DO(f.assertAttributeConfig({make_int32_sv_cfg("array.a")})); + TEST_DO(f.assertSummarymapConfig({make_attribute_combiner_override("array")})); +} + +TEST_F("require that adding attribute aspect to struct field is delayed if field type is unchanged", Fixture) +{ + f.addFields({"array.a"}); + f.setup(attrCfg({}), smCfg({}), attrCfg({make_int32_sv_cfg("array.a")}), smCfg({make_attribute_combiner_override("array")})); + TEST_DO(f.assertAttributeConfig({})); + TEST_DO(f.assertSummarymapConfig({})); +} + +TEST_F("require that removing attribute aspect from struct field is not delayed", Fixture) +{ + f.addFields({"array.a"}); + f.setup(attrCfg({make_int32_sv_cfg("array.a")}), smCfg({make_attribute_combiner_override("array")}), attrCfg({}), smCfg({})); + TEST_DO(f.assertAttributeConfig({})); + TEST_DO(f.assertSummarymapConfig({})); +} + } TEST_MAIN() 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 9bf4d43fff7..ce09a9a3742 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 @@ -1,7 +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_manager_test"); - #include <vespa/config-attributes.h> #include <vespa/fastos/file.h> #include <vespa/searchcommon/attribute/attributecontent.h> @@ -42,6 +39,9 @@ LOG_SETUP("attribute_manager_test"); #include <vespa/vespalib/testkit/testapp.h> #include <vespa/vespalib/util/threadstackexecutor.h> +#include <vespa/log/log.h> +LOG_SETUP("attribute_manager_test"); + namespace vespa { namespace config { namespace search {}}} using std::string; @@ -84,7 +84,7 @@ class MyAttributeFunctor : public proton::IAttributeFunctor std::vector<vespalib::string> _names; public: - virtual void + void operator()(const search::AttributeVector &attributeVector) override { _names.push_back(attributeVector.getName()); } @@ -166,13 +166,12 @@ BaseFixture::BaseFixture() _hwInfo() { } -BaseFixture::~BaseFixture() {} +BaseFixture::~BaseFixture() = default; struct AttributeManagerFixture { proton::AttributeManager::SP _msp; proton::AttributeManager &_m; - AttributeWriter _aw; ImportedAttributesRepoBuilder _builder; AttributeManagerFixture(BaseFixture &bf); ~AttributeManagerFixture(); @@ -191,10 +190,9 @@ AttributeManagerFixture::AttributeManagerFixture(BaseFixture &bf) : _msp(std::make_shared<proton::AttributeManager>(test_dir, "test.subdb", TuneFileAttributes(), bf._fileHeaderContext, bf._attributeFieldWriter, bf._hwInfo)), _m(*_msp), - _aw(_msp), _builder() {} -AttributeManagerFixture::~AttributeManagerFixture() {} +AttributeManagerFixture::~AttributeManagerFixture() = default; struct Fixture : public BaseFixture, public AttributeManagerFixture { @@ -318,16 +316,21 @@ TEST_F("require that attributes are flushed and loaded", BaseFixture) fillAttribute(a1, 1, 2, 200); EXPECT_EQUAL(4u, a1->getNumDocs()); AttributeVector::SP a2 = amf.addAttribute("a2"); // loaded - EXPECT_EQUAL(5u, a2->getNumDocs()); - EXPECT_EQUAL(4u, a1->getNumDocs()); - amf._aw.onReplayDone(5u); - EXPECT_EQUAL(5u, a2->getNumDocs()); - EXPECT_EQUAL(5u, a1->getNumDocs()); - fillAttribute(a2, 1, 4, 200); - EXPECT_EQUAL(6u, a2->getNumDocs()); + { + AttributeWriter aw(amf._msp); + + EXPECT_EQUAL(5u, a2->getNumDocs()); + EXPECT_EQUAL(4u, a1->getNumDocs()); + aw.onReplayDone(5u); + EXPECT_EQUAL(5u, a2->getNumDocs()); + EXPECT_EQUAL(5u, a1->getNumDocs()); + fillAttribute(a2, 1, 4, 200); + EXPECT_EQUAL(6u, a2->getNumDocs()); + } AttributeVector::SP a3 = amf.addAttribute("a3"); // not-loaded + AttributeWriter aw(amf._msp); EXPECT_EQUAL(1u, a3->getNumDocs()); - amf._aw.onReplayDone(6); + aw.onReplayDone(6); EXPECT_EQUAL(6u, a3->getNumDocs()); fillAttribute(a3, 1, 7, 6, 200); EXPECT_EQUAL(7u, a3->getNumDocs()); @@ -352,10 +355,11 @@ TEST_F("require that attributes are flushed and loaded", BaseFixture) EXPECT_EQUAL(6u, a1->getNumDocs()); EXPECT_EQUAL(6u, a2->getNumDocs()); AttributeVector::SP a3 = amf.addAttribute("a3"); // loaded + AttributeWriter aw(amf._msp); EXPECT_EQUAL(6u, a1->getNumDocs()); EXPECT_EQUAL(6u, a2->getNumDocs()); EXPECT_EQUAL(7u, a3->getNumDocs()); - amf._aw.onReplayDone(7); + aw.onReplayDone(7); EXPECT_EQUAL(7u, a1->getNumDocs()); EXPECT_EQUAL(7u, a2->getNumDocs()); EXPECT_EQUAL(7u, a3->getNumDocs()); @@ -559,6 +563,7 @@ TEST_F("require that lid space can be compacted", Fixture) AttributeVector::SP a2 = f.addAttribute("a2"); AttributeVector::SP ex(new Int32Attribute("ex")); f._m.addExtraAttribute(ex); + AttributeWriter aw(f._msp); const int64_t attrValue = 33; fillAttribute(a1, 20, attrValue, 100); fillAttribute(a2, 20, attrValue, 100); @@ -571,7 +576,7 @@ TEST_F("require that lid space can be compacted", Fixture) EXPECT_EQUAL(21u, a2->getCommittedDocIdLimit()); EXPECT_EQUAL(20u, ex->getCommittedDocIdLimit()); - f._aw.compactLidSpace(10, 101); + aw.compactLidSpace(10, 101); EXPECT_EQUAL(21u, a1->getNumDocs()); EXPECT_EQUAL(21u, a2->getNumDocs()); @@ -587,6 +592,7 @@ TEST_F("require that lid space compaction op can be ignored", Fixture) AttributeVector::SP a2 = f.addAttribute("a2"); AttributeVector::SP ex(new Int32Attribute("ex")); f._m.addExtraAttribute(ex); + AttributeWriter aw(f._msp); const int64_t attrValue = 33; fillAttribute(a1, 20, attrValue, 200); fillAttribute(a2, 20, attrValue, 100); @@ -599,7 +605,7 @@ TEST_F("require that lid space compaction op can be ignored", Fixture) EXPECT_EQUAL(21u, a2->getCommittedDocIdLimit()); EXPECT_EQUAL(20u, ex->getCommittedDocIdLimit()); - f._aw.compactLidSpace(10, 101); + aw.compactLidSpace(10, 101); EXPECT_EQUAL(21u, a1->getNumDocs()); EXPECT_EQUAL(21u, a2->getNumDocs()); diff --git a/searchcore/src/tests/proton/attribute/attribute_test.cpp b/searchcore/src/tests/proton/attribute/attribute_test.cpp index 5954932bbaf..346f94180b5 100644 --- a/searchcore/src/tests/proton/attribute/attribute_test.cpp +++ b/searchcore/src/tests/proton/attribute/attribute_test.cpp @@ -445,7 +445,7 @@ TEST_F("require that attribute writer handles update", Fixture) schema.addAttributeField(Schema::AttributeField("a2", schema::DataType::INT32, CollectionType::SINGLE)); DocBuilder idb(schema); const document::DocumentType &dt(idb.getDocumentType()); - DocumentUpdate upd(dt, DocumentId("doc::1")); + DocumentUpdate upd(*idb.getDocumentTypeRepo(), dt, DocumentId("doc::1")); upd.addUpdate(FieldUpdate(upd.getType().getField("a1")) .addUpdate(ArithmeticValueUpdate(ArithmeticValueUpdate::Add, 5))); upd.addUpdate(FieldUpdate(upd.getType().getField("a2")) @@ -489,7 +489,7 @@ TEST_F("require that attribute writer handles predicate update", Fixture) EXPECT_EQUAL(2u, a1->getNumDocs()); const document::DocumentType &dt(idb.getDocumentType()); - DocumentUpdate upd(dt, DocumentId("doc::1")); + DocumentUpdate upd(*idb.getDocumentTypeRepo(), dt, DocumentId("doc::1")); PredicateFieldValue new_value(builder.feature("foo").value("bar").build()); upd.addUpdate(FieldUpdate(upd.getType().getField("a1")) .addUpdate(AssignValueUpdate(new_value))); @@ -678,7 +678,7 @@ TEST_F("require that attribute writer handles tensor assign update", Fixture) EXPECT_TRUE(tensor->equals(*tensor2)); const document::DocumentType &dt(builder.getDocumentType()); - DocumentUpdate upd(dt, DocumentId("doc::1")); + DocumentUpdate upd(*builder.getDocumentTypeRepo(), dt, DocumentId("doc::1")); auto new_tensor = createTensor({ {{{"x", "8"}, {"y", "9"}}, 11} }, {"x", "y"}); TensorFieldValue new_value; diff --git a/searchcore/src/tests/proton/attribute/attributeflush_test.cpp b/searchcore/src/tests/proton/attribute/attributeflush_test.cpp index d73cd805af1..8a5f58bd7e0 100644 --- a/searchcore/src/tests/proton/attribute/attributeflush_test.cpp +++ b/searchcore/src/tests/proton/attribute/attributeflush_test.cpp @@ -256,13 +256,12 @@ BaseFixture::BaseFixture(const HwInfo &hwInfo) _attributeFieldWriter(), _hwInfo(hwInfo) {} -BaseFixture::~BaseFixture() {} +BaseFixture::~BaseFixture() = default; struct AttributeManagerFixture { AttributeManager::SP _msp; AttributeManager &_m; - AttributeWriter _aw; AttributeManagerFixture(BaseFixture &bf); ~AttributeManagerFixture(); AttributeVector::SP addAttribute(const vespalib::string &name) { @@ -278,10 +277,9 @@ struct AttributeManagerFixture AttributeManagerFixture::AttributeManagerFixture(BaseFixture &bf) : _msp(std::make_shared<AttributeManager>(test_dir, "test.subdb", TuneFileAttributes(), bf._fileHeaderContext, bf._attributeFieldWriter, bf._hwInfo)), - _m(*_msp), - _aw(_msp) + _m(*_msp) {} -AttributeManagerFixture::~AttributeManagerFixture() {} +AttributeManagerFixture::~AttributeManagerFixture() = default; struct Fixture : public BaseFixture, public AttributeManagerFixture { @@ -530,6 +528,7 @@ Test::requireThatShrinkWorks() Fixture f; AttributeManager &am = f._m; AttributeVector::SP av = f.addAttribute("a10"); + AttributeWriter aw(f._msp); av->addDocs(1000 - av->getNumDocs()); av->commit(50, 50); @@ -546,13 +545,13 @@ Test::requireThatShrinkWorks() EXPECT_FALSE(av->canShrinkLidSpace()); EXPECT_EQUAL(1000u, av->getNumDocs()); EXPECT_EQUAL(100u, av->getCommittedDocIdLimit()); - f._aw.heartBeat(51); + aw.heartBeat(51); EXPECT_TRUE(av->wantShrinkLidSpace()); EXPECT_FALSE(av->canShrinkLidSpace()); EXPECT_EQUAL(ft->getApproxMemoryGain().getBefore(), ft->getApproxMemoryGain().getAfter()); g.reset(); - f._aw.heartBeat(52); + aw.heartBeat(52); EXPECT_TRUE(av->wantShrinkLidSpace()); EXPECT_TRUE(av->canShrinkLidSpace()); EXPECT_TRUE(ft->getApproxMemoryGain().getBefore() > diff --git a/searchcore/src/tests/proton/attribute/exclusive_attribute_read_accessor/exclusive_attribute_read_accessor_test.cpp b/searchcore/src/tests/proton/attribute/exclusive_attribute_read_accessor/exclusive_attribute_read_accessor_test.cpp index 6d69d9b225b..c5ae0f97875 100644 --- a/searchcore/src/tests/proton/attribute/exclusive_attribute_read_accessor/exclusive_attribute_read_accessor_test.cpp +++ b/searchcore/src/tests/proton/attribute/exclusive_attribute_read_accessor/exclusive_attribute_read_accessor_test.cpp @@ -37,7 +37,7 @@ TEST_F("require that attribute write thread is blocked while guard is held", Fix { ReadGuard::UP guard = f.accessor.takeGuard(); Gate gate; - f.writer.execute("myattr", [&gate]() { gate.countDown(); }); + f.writer.execute(f.writer.getExecutorId(f.attribute->getNamePrefix()), [&gate]() { gate.countDown(); }); bool reachedZero = gate.await(100); EXPECT_FALSE(reachedZero); EXPECT_EQUAL(1u, gate.getCount()); diff --git a/searchcore/src/tests/proton/common/document_type_inspector/document_type_inspector_test.cpp b/searchcore/src/tests/proton/common/document_type_inspector/document_type_inspector_test.cpp index 2dbff7d40dd..167865b5c68 100644 --- a/searchcore/src/tests/proton/common/document_type_inspector/document_type_inspector_test.cpp +++ b/searchcore/src/tests/proton/common/document_type_inspector/document_type_inspector_test.cpp @@ -1,78 +1,131 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. #include <vespa/searchcore/proton/common/document_type_inspector.h> #include <vespa/vespalib/testkit/testapp.h> -#include <vespa/document/repo/configbuilder.h> -#include <vespa/document/repo/documenttyperepo.h> +#include <vespa/document/base/field.h> +#include <vespa/document/datatype/datatypes.h> using namespace document; using namespace proton; -using document::config_builder::DocumenttypesConfigBuilderHelper; -using document::config_builder::Struct; -const int32_t doc_type_id = 787121340; -const vespalib::string type_name = "test"; -const vespalib::string header_name = type_name + ".header"; -const vespalib::string body_name = type_name + ".body"; - -std::unique_ptr<const DocumentTypeRepo> -makeOldDocTypeRepo() +template <class Type> +void +addFields(Type &type, bool fieldF3IsString, bool hasFieldF4, bool hasFieldF5) { - DocumenttypesConfigBuilderHelper builder; - builder.document(doc_type_id, type_name, - Struct(header_name), Struct(body_name). - addField("f1", DataType::T_STRING). - addField("f2", DataType::T_STRING). - addField("f3", DataType::T_STRING). - addField("f4", DataType::T_STRING)); - return std::unique_ptr<const DocumentTypeRepo>(new DocumentTypeRepo(builder.config())); + type.addField(Field("f1", 1, *DataType::STRING, true)); + type.addField(Field("f2", 2, *DataType::STRING, true)); + type.addField(Field("f3", 3, fieldF3IsString ? *DataType::STRING : *DataType::INT, true)); + if (hasFieldF4) { + type.addField(Field("f4", 4, *DataType::STRING, true)); + } + if (hasFieldF5) { + type.addField(Field("f5", 5, *DataType::STRING, true)); + } } -std::unique_ptr<const DocumentTypeRepo> -makeNewDocTypeRepo() +struct DocumentTypeFixture +{ + DocumentType _documentType; + StructDataType _structFieldType; + ArrayDataType _structArrayFieldType; + MapDataType _structMapFieldType; + MapDataType _mapFieldType; + + DocumentTypeFixture(bool fieldF3IsString, bool hasFieldF4, bool hasFieldF5, bool hasStruct, bool mapKeyIsByte); + ~DocumentTypeFixture(); +}; + +DocumentTypeFixture::DocumentTypeFixture(bool fieldF3IsString, bool hasFieldF4, bool hasFieldF5, bool hasStruct, bool mapKeyIsByte) + : _documentType("test"), + _structFieldType("struct"), + _structArrayFieldType(_structFieldType), + _structMapFieldType(mapKeyIsByte ? *DataType::BYTE : *DataType::STRING, _structFieldType), + _mapFieldType(mapKeyIsByte ? *DataType::BYTE : *DataType::STRING, *DataType::STRING) { - DocumenttypesConfigBuilderHelper builder; - builder.document(doc_type_id, type_name, - Struct(header_name), Struct(body_name). - addField("f1", DataType::T_STRING). - addField("f2", DataType::T_STRING). - addField("f3", DataType::T_INT). - addField("f5", DataType::T_STRING)); - return std::unique_ptr<const DocumentTypeRepo>(new DocumentTypeRepo(builder.config())); + addFields(_documentType, fieldF3IsString, hasFieldF4, hasFieldF5); + if (hasStruct) { + addFields(_structFieldType, fieldF3IsString, hasFieldF4, hasFieldF5); + _documentType.addField(Field("sarray", 11, _structArrayFieldType, true)); + _documentType.addField(Field("smap", 12, _structMapFieldType, true)); + _documentType.addField(Field("map", 13, _mapFieldType, true)); + } } +DocumentTypeFixture::~DocumentTypeFixture() = default; + struct Fixture { - std::unique_ptr<const DocumentTypeRepo> _oldRepo; - std::unique_ptr<const DocumentTypeRepo> _newRepo; + DocumentTypeFixture _oldDocType; + DocumentTypeFixture _newDocType; DocumentTypeInspector _inspector; - Fixture() - : _oldRepo(makeOldDocTypeRepo()), - _newRepo(makeNewDocTypeRepo()), - _inspector(*_oldRepo->getDocumentType("test"), *_newRepo->getDocumentType("test")) + Fixture(bool hasStruct = true, bool mapKeyIsByte = false) + : _oldDocType(true, true, false, hasStruct, mapKeyIsByte), + _newDocType(false, false, true, true, false), + _inspector(_oldDocType._documentType, _newDocType._documentType) { } }; TEST_F("require that unchanged fields are known", Fixture) { - EXPECT_TRUE(f._inspector.hasUnchangedField("f1")); - EXPECT_TRUE(f._inspector.hasUnchangedField("f2")); + const IDocumentTypeInspector &inspector = f._inspector; + EXPECT_TRUE(inspector.hasUnchangedField("f1")); + EXPECT_TRUE(inspector.hasUnchangedField("f2")); + EXPECT_TRUE(inspector.hasUnchangedField("sarray.f1")); + EXPECT_TRUE(inspector.hasUnchangedField("sarray.f2")); + EXPECT_TRUE(inspector.hasUnchangedField("smap.key")); + EXPECT_TRUE(inspector.hasUnchangedField("smap.value.f1")); + EXPECT_TRUE(inspector.hasUnchangedField("smap.value.f2")); + EXPECT_TRUE(inspector.hasUnchangedField("map.key")); + EXPECT_TRUE(inspector.hasUnchangedField("map.value")); } TEST_F("require that changed fields are detected", Fixture) { - EXPECT_FALSE(f._inspector.hasUnchangedField("f3")); + const IDocumentTypeInspector &inspector = f._inspector; + EXPECT_FALSE(inspector.hasUnchangedField("f3")); + EXPECT_FALSE(inspector.hasUnchangedField("sarray.f3")); + EXPECT_FALSE(inspector.hasUnchangedField("smap.value.f3")); } TEST_F("require that partially missing fields are detected", Fixture) { - EXPECT_FALSE(f._inspector.hasUnchangedField("f4")); - EXPECT_FALSE(f._inspector.hasUnchangedField("f5")); + const IDocumentTypeInspector &inspector = f._inspector; + EXPECT_FALSE(inspector.hasUnchangedField("f4")); + EXPECT_FALSE(inspector.hasUnchangedField("f5")); + EXPECT_FALSE(inspector.hasUnchangedField("sarray.f4")); + EXPECT_FALSE(inspector.hasUnchangedField("sarray.f5")); + EXPECT_FALSE(inspector.hasUnchangedField("smap.value.f4")); + EXPECT_FALSE(inspector.hasUnchangedField("smap.value.f5")); } TEST_F("require that non-existing fields are NOT known", Fixture) { - EXPECT_FALSE(f._inspector.hasUnchangedField("not")); + const IDocumentTypeInspector &inspector = f._inspector; + EXPECT_FALSE(inspector.hasUnchangedField("not")); + EXPECT_FALSE(inspector.hasUnchangedField("sarray.not")); + EXPECT_FALSE(inspector.hasUnchangedField("smap.not")); +} + +TEST_F("require that map key type change is detected", Fixture(true, true)) +{ + const IDocumentTypeInspector &inspector = f._inspector; + EXPECT_FALSE(inspector.hasUnchangedField("smap.key")); + EXPECT_FALSE(inspector.hasUnchangedField("smap.value.f1")); + EXPECT_FALSE(inspector.hasUnchangedField("smap.value.f2")); + EXPECT_FALSE(inspector.hasUnchangedField("map.key")); + EXPECT_FALSE(inspector.hasUnchangedField("map.value")); +} + +TEST_F("require that struct addition is detected", Fixture(false, false)) +{ + const IDocumentTypeInspector &inspector = f._inspector; + EXPECT_FALSE(inspector.hasUnchangedField("sarray.f1")); + EXPECT_FALSE(inspector.hasUnchangedField("sarray.f2")); + EXPECT_FALSE(inspector.hasUnchangedField("smap.key")); + EXPECT_FALSE(inspector.hasUnchangedField("smap.value.f1")); + EXPECT_FALSE(inspector.hasUnchangedField("smap.value.f2")); + EXPECT_FALSE(inspector.hasUnchangedField("map.key")); + EXPECT_FALSE(inspector.hasUnchangedField("map.value")); } TEST_MAIN() diff --git a/searchcore/src/tests/proton/docsummary/docsummary.cpp b/searchcore/src/tests/proton/docsummary/docsummary.cpp index 79d38e2dc56..1c901097812 100644 --- a/searchcore/src/tests/proton/docsummary/docsummary.cpp +++ b/searchcore/src/tests/proton/docsummary/docsummary.cpp @@ -829,20 +829,16 @@ Test::requireThatAttributesAreUsed() "bi:[]}", *rep, 1, false)); TEST_DO(assertTensor(Tensor::UP(), "bj", *rep, 1, rclass)); - proton::IAttributeManager::SP attributeManager = - dc._ddb->getReadySubDB()->getAttributeManager(); - search::ISequencedTaskExecutor &attributeFieldWriter = - attributeManager->getAttributeFieldWriter(); - search::AttributeVector *bjAttr = - attributeManager->getWritableAttribute("bj"); - search::tensor::TensorAttribute *bjTensorAttr = - dynamic_cast<search::tensor::TensorAttribute *>(bjAttr); - - attributeFieldWriter. - execute("bj", - [&]() { bjTensorAttr->setTensor(3, - *createTensor({ {{{"x", "a"},{"y", "b"}}, 4} }, { "x"})); - bjTensorAttr->commit(); }); + proton::IAttributeManager::SP attributeManager = dc._ddb->getReadySubDB()->getAttributeManager(); + search::ISequencedTaskExecutor &attributeFieldWriter = attributeManager->getAttributeFieldWriter(); + search::AttributeVector *bjAttr = attributeManager->getWritableAttribute("bj"); + auto bjTensorAttr = dynamic_cast<search::tensor::TensorAttribute *>(bjAttr); + + attributeFieldWriter.execute(attributeFieldWriter.getExecutorId(bjAttr->getNamePrefix()), + [&]() { + bjTensorAttr->setTensor(3, *createTensor({ {{{"x", "a"},{"y", "b"}}, 4} }, { "x"})); + bjTensorAttr->commit(); + }); attributeFieldWriter.sync(); DocsumReply::UP rep2 = dc._ddb->getDocsums(req); @@ -961,8 +957,7 @@ Test::requireThatUrisAreUsed() Document::UP exp = bc._bld.startDocument("doc::0"). startIndexField("urisingle"). startSubField("all"). - addUrlTokenizedString( - "http://www.example.com:81/fluke?ab=2#4"). + addUrlTokenizedString("http://www.example.com:81/fluke?ab=2#4"). endSubField(). startSubField("scheme"). addUrlTokenizedString("http"). @@ -986,8 +981,7 @@ Test::requireThatUrisAreUsed() startIndexField("uriarray"). startElement(1). startSubField("all"). - addUrlTokenizedString( - "http://www.example.com:82/fluke?ab=2#8"). + addUrlTokenizedString("http://www.example.com:82/fluke?ab=2#8"). endSubField(). startSubField("scheme"). addUrlTokenizedString("http"). @@ -1010,8 +1004,7 @@ Test::requireThatUrisAreUsed() endElement(). startElement(1). startSubField("all"). - addUrlTokenizedString( - "http://www.flickr.com:82/fluke?ab=2#9"). + addUrlTokenizedString("http://www.flickr.com:82/fluke?ab=2#9"). endSubField(). startSubField("scheme"). addUrlTokenizedString("http"). @@ -1036,8 +1029,7 @@ Test::requireThatUrisAreUsed() startIndexField("uriwset"). startElement(4). startSubField("all"). - addUrlTokenizedString( - "http://www.example.com:83/fluke?ab=2#12"). + addUrlTokenizedString("http://www.example.com:83/fluke?ab=2#12"). endSubField(). startSubField("scheme"). addUrlTokenizedString("http"). @@ -1060,8 +1052,7 @@ Test::requireThatUrisAreUsed() endElement(). startElement(7). startSubField("all"). - addUrlTokenizedString( - "http://www.flickr.com:85/fluke?ab=2#13"). + addUrlTokenizedString("http://www.flickr.com:85/fluke?ab=2#13"). endSubField(). startSubField("scheme"). addUrlTokenizedString("http"). diff --git a/searchcore/src/tests/proton/docsummary/summaryfieldconverter_test.cpp b/searchcore/src/tests/proton/docsummary/summaryfieldconverter_test.cpp index 7f8ce99beb9..73d071be96f 100644 --- a/searchcore/src/tests/proton/docsummary/summaryfieldconverter_test.cpp +++ b/searchcore/src/tests/proton/docsummary/summaryfieldconverter_test.cpp @@ -33,7 +33,7 @@ #include <vespa/document/fieldvalue/referencefieldvalue.h> #include <vespa/document/predicate/predicate.h> #include <vespa/document/repo/configbuilder.h> -#include <vespa/document/repo/documenttyperepo.h> +#include <vespa/document/repo/fixedtyperepo.h> #include <vespa/searchsummary/docsummary/summaryfieldconverter.h> #include <vespa/searchsummary/docsummary/linguisticsannotation.h> #include <vespa/searchsummary/docsummary/searchdatatype.h> diff --git a/searchcore/src/tests/proton/documentdb/combiningfeedview/combiningfeedview_test.cpp b/searchcore/src/tests/proton/documentdb/combiningfeedview/combiningfeedview_test.cpp index f06bb124eb8..958be6a4686 100644 --- a/searchcore/src/tests/proton/documentdb/combiningfeedview/combiningfeedview_test.cpp +++ b/searchcore/src/tests/proton/documentdb/combiningfeedview/combiningfeedview_test.cpp @@ -1,15 +1,16 @@ // 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("combiningfeedview_test"); #include <vespa/document/test/make_bucket_space.h> -#include <vespa/searchcore/proton/feedoperation/moveoperation.h> +#include <vespa/searchcore/proton/feedoperation/operations.h> #include <vespa/searchcore/proton/server/combiningfeedview.h> #include <vespa/searchcore/proton/test/test.h> #include <vespa/searchlib/common/idestructorcallback.h> #include <vespa/document/update/documentupdate.h> #include <vespa/vespalib/testkit/testapp.h> +#include <vespa/log/log.h> +LOG_SETUP("combiningfeedview_test"); + using document::DocumentTypeRepo; using document::DocumentUpdate; using document::test::makeBucketSpace; @@ -22,8 +23,8 @@ typedef std::vector<IFeedView::SP> FeedViewVector; struct MyStreamHandler : public NewConfigOperation::IStreamHandler { - virtual void serializeConfig(SerialNum, vespalib::nbostream &) override {} - virtual void deserializeConfig(SerialNum, vespalib::nbostream &) override {} + void serializeConfig(SerialNum, vespalib::nbostream &) override {} + void deserializeConfig(SerialNum, vespalib::nbostream &) override {} }; diff --git a/searchcore/src/tests/proton/documentdb/document_subdbs/document_subdbs_test.cpp b/searchcore/src/tests/proton/documentdb/document_subdbs/document_subdbs_test.cpp index bab6aff821f..760f7457d33 100644 --- a/searchcore/src/tests/proton/documentdb/document_subdbs/document_subdbs_test.cpp +++ b/searchcore/src/tests/proton/documentdb/document_subdbs/document_subdbs_test.cpp @@ -14,6 +14,7 @@ #include <vespa/searchcore/proton/reference/i_document_db_reference_resolver.h> #include <vespa/searchcore/proton/reprocessing/i_reprocessing_task.h> #include <vespa/searchcore/proton/reprocessing/reprocessingrunner.h> +#include <vespa/searchcore/proton/feedoperation/operations.h> #include <vespa/searchcore/proton/server/bootstrapconfig.h> #include <vespa/searchcore/proton/server/document_subdb_explorer.h> #include <vespa/searchcore/proton/server/emptysearchview.h> diff --git a/searchcore/src/tests/proton/documentdb/feedhandler/feedhandler_test.cpp b/searchcore/src/tests/proton/documentdb/feedhandler/feedhandler_test.cpp index e774728b41e..a1bce7174bf 100644 --- a/searchcore/src/tests/proton/documentdb/feedhandler/feedhandler_test.cpp +++ b/searchcore/src/tests/proton/documentdb/feedhandler/feedhandler_test.cpp @@ -316,7 +316,7 @@ struct UpdateContext { DocumentUpdate::SP update; BucketId bucketId; UpdateContext(const vespalib::string &docId, DocBuilder &builder) : - update(new DocumentUpdate(builder.getDocumentType(), DocumentId(docId))), + update(new DocumentUpdate(*builder.getDocumentTypeRepo(), builder.getDocumentType(), DocumentId(docId))), bucketId(BucketFactory::getBucketId(update->getId())) { } diff --git a/searchcore/src/tests/proton/documentdb/feedview/feedview_test.cpp b/searchcore/src/tests/proton/documentdb/feedview/feedview_test.cpp index a9fa79f513c..d21e5abe30b 100644 --- a/searchcore/src/tests/proton/documentdb/feedview/feedview_test.cpp +++ b/searchcore/src/tests/proton/documentdb/feedview/feedview_test.cpp @@ -11,6 +11,7 @@ #include <vespa/searchcore/proton/server/isummaryadapter.h> #include <vespa/searchcore/proton/server/matchview.h> #include <vespa/searchcore/proton/server/searchable_feed_view.h> +#include <vespa/searchcore/proton/feedoperation/operations.h> #include <vespa/searchcore/proton/test/document_meta_store_context_observer.h> #include <vespa/searchcore/proton/test/dummy_document_store.h> #include <vespa/searchcore/proton/test/dummy_summary_manager.h> @@ -478,11 +479,11 @@ struct DocumentContext DocumentContext::DocumentContext(const vespalib::string &docId, uint64_t timestamp, DocBuilder &builder) : doc(builder.startDocument(docId).startSummaryField("s1").addStr(docId).endField().endDocument().release()), - upd(new DocumentUpdate(builder.getDocumentType(), doc->getId())), + upd(new DocumentUpdate(*builder.getDocumentTypeRepo(), builder.getDocumentType(), doc->getId())), bid(BucketFactory::getNumBucketBits(), doc->getId().getGlobalId().convertToBucketId().getRawId()), ts(timestamp) {} -DocumentContext::~DocumentContext() {} +DocumentContext::~DocumentContext() = default; struct FeedTokenContext { diff --git a/searchcore/src/tests/proton/documentdb/storeonlyfeedview/storeonlyfeedview_test.cpp b/searchcore/src/tests/proton/documentdb/storeonlyfeedview/storeonlyfeedview_test.cpp index e8247a52199..d07c29ead69 100644 --- a/searchcore/src/tests/proton/documentdb/storeonlyfeedview/storeonlyfeedview_test.cpp +++ b/searchcore/src/tests/proton/documentdb/storeonlyfeedview/storeonlyfeedview_test.cpp @@ -9,6 +9,8 @@ #include <vespa/searchcore/proton/server/putdonecontext.h> #include <vespa/searchcore/proton/server/removedonecontext.h> #include <vespa/searchcore/proton/server/storeonlyfeedview.h> +#include <vespa/searchcore/proton/feedoperation/moveoperation.h> +#include <vespa/searchcore/proton/feedoperation/pruneremoveddocumentsoperation.h> #include <vespa/searchcore/proton/reference/dummy_gid_to_lid_change_handler.h> #include <vespa/searchcore/proton/test/mock_summary_adapter.h> #include <vespa/searchcore/proton/test/thread_utils.h> diff --git a/searchcore/src/tests/proton/feedoperation/feedoperation_test.cpp b/searchcore/src/tests/proton/feedoperation/feedoperation_test.cpp index 9a9d896f2b9..e87e9209a17 100644 --- a/searchcore/src/tests/proton/feedoperation/feedoperation_test.cpp +++ b/searchcore/src/tests/proton/feedoperation/feedoperation_test.cpp @@ -122,7 +122,7 @@ public: } auto makeUpdate() { - auto upd(std::make_shared<DocumentUpdate>(_docType, docId)); + auto upd(std::make_shared<DocumentUpdate>(*_repo, _docType, docId)); upd->addUpdate(FieldUpdate(upd->getType().getField("string")). addUpdate(AssignValueUpdate(StringFieldValue("newval")))); return upd; @@ -136,6 +136,7 @@ public: TEST("require that toString() on derived classes are meaningful") { + DocumentTypeRepo repo; BucketId bucket_id1(42); BucketId bucket_id2(43); BucketId bucket_id3(44); @@ -146,7 +147,7 @@ TEST("require that toString() on derived classes are meaningful") MyStreamHandler stream_handler; DocumentIdT doc_id_limit = 15; DocumentId doc_id("doc:foo:bar"); - DocumentUpdate::SP update(new DocumentUpdate(*DataType::DOCUMENT, doc_id)); + DocumentUpdate::SP update(new DocumentUpdate(repo, *DataType::DOCUMENT, doc_id)); EXPECT_EQUAL("DeleteBucket(BucketId(0x0000000000000000), serialNum=0)", DeleteBucketOperation().toString()); diff --git a/searchcore/src/tests/proton/persistenceengine/persistenceengine_test.cpp b/searchcore/src/tests/proton/persistenceengine/persistenceengine_test.cpp index 73580416e65..7f065d0cc15 100644 --- a/searchcore/src/tests/proton/persistenceengine/persistenceengine_test.cpp +++ b/searchcore/src/tests/proton/persistenceengine/persistenceengine_test.cpp @@ -67,7 +67,9 @@ createDoc(const DocumentType &docType, const DocumentId &docId) document::DocumentUpdate::SP createUpd(const DocumentType& docType, const DocumentId &docId) { - return document::DocumentUpdate::SP(new document::DocumentUpdate(docType, docId)); + static std::vector<std::unique_ptr<document::DocumentTypeRepo>> repoList; + repoList.emplace_back(std::make_unique<document::DocumentTypeRepo>(docType)); + return std::make_shared<document::DocumentUpdate>(*repoList.back(), docType, docId); } storage::spi::ClusterState diff --git a/searchcore/src/tests/proton/reprocessing/attribute_reprocessing_initializer/attribute_reprocessing_initializer_test.cpp b/searchcore/src/tests/proton/reprocessing/attribute_reprocessing_initializer/attribute_reprocessing_initializer_test.cpp index 93c192b57e8..7be774f7291 100644 --- a/searchcore/src/tests/proton/reprocessing/attribute_reprocessing_initializer/attribute_reprocessing_initializer_test.cpp +++ b/searchcore/src/tests/proton/reprocessing/attribute_reprocessing_initializer/attribute_reprocessing_initializer_test.cpp @@ -306,6 +306,18 @@ TEST("require that added attribute aspect with flushed attribute after interrupt EXPECT_TRUE(f.assertAttributes({})); } +TEST_F("require that removed attribute aspect from struct field does not require document field populate", Fixture) +{ + f.addOldConfig({"array.a"}, {"array.a"}).addNewConfig({"array.a"}, {}).init(); + EXPECT_TRUE(f.assertFields({})); +} + +TEST_F("require that added attribute aspect to struct field requires attribute populate", Fixture) +{ + f.addOldConfig({"array.a"}, {}).addNewConfig({"array.a"}, {"array.a"}).init(); + EXPECT_TRUE(f.assertAttributes({"array.a"})); +} + TEST_MAIN() { TEST_RUN_ALL(); diff --git a/searchcore/src/tests/proton/server/feedstates_test.cpp b/searchcore/src/tests/proton/server/feedstates_test.cpp index dfa461e2b57..f206ffc9b17 100644 --- a/searchcore/src/tests/proton/server/feedstates_test.cpp +++ b/searchcore/src/tests/proton/server/feedstates_test.cpp @@ -1,8 +1,6 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. // Unit tests for feedstates. -#include <vespa/log/log.h> -LOG_SETUP("feedstates_test"); #include <vespa/document/base/documentid.h> #include <vespa/document/base/testdocrepo.h> @@ -11,6 +9,7 @@ LOG_SETUP("feedstates_test"); #include <vespa/searchcore/proton/server/feedstates.h> #include <vespa/searchcore/proton/server/ireplayconfig.h> #include <vespa/searchcore/proton/server/memoryconfigstore.h> +#include <vespa/searchcore/proton/feedoperation/removeoperation.h> #include <vespa/searchcore/proton/test/dummy_feed_view.h> #include <vespa/searchlib/common/serialnum.h> #include <vespa/vespalib/objects/nbostream.h> @@ -18,6 +17,9 @@ LOG_SETUP("feedstates_test"); #include <vespa/vespalib/util/buffer.h> #include <vespa/searchcore/proton/bucketdb/bucketdbhandler.h> +#include <vespa/log/log.h> +LOG_SETUP("feedstates_test"); + using document::BucketId; using document::DocumentId; using document::DocumentTypeRepo; @@ -83,7 +85,7 @@ Fixture::Fixture() state("doctypename", feed_view_ptr, _bucketDBHandler, replay_config, config_store) { } -Fixture::~Fixture() {} +Fixture::~Fixture() = default; struct RemoveOperationContext @@ -107,7 +109,7 @@ RemoveOperationContext::RemoveOperationContext(search::SerialNum serial) packet.reset(new Packet()); packet->add(Packet::Entry(serial, FeedOperation::REMOVE, buf)); } -RemoveOperationContext::~RemoveOperationContext() {} +RemoveOperationContext::~RemoveOperationContext() = default; TEST_F("require that active FeedView can change during replay", Fixture) { RemoveOperationContext opCtx(10); diff --git a/searchcore/src/vespa/searchcore/config/proton.def b/searchcore/src/vespa/searchcore/config/proton.def index e66466aa1cb..7578066d93a 100644 --- a/searchcore/src/vespa/searchcore/config/proton.def +++ b/searchcore/src/vespa/searchcore/config/proton.def @@ -467,7 +467,7 @@ hwinfo.cpu.cores int default = 0 restart ## max(ceil(hwinfo.cpu.cores * feeding.concurrency), summary.log.numthreads) ## The number of threads in each of pools 2-4 is calculated as: ## max(ceil((hwinfo.cpu.cores * feeding.concurrency)/3), indexing.threads) -feeding.concurrency double default = 0.5 restart +feeding.concurrency double default = 0.2 restart ## Adjustment to resource limit when determining if maintenance jobs can run. ## diff --git a/searchcore/src/vespa/searchcore/proton/attribute/attribute_aspect_delayer.cpp b/searchcore/src/vespa/searchcore/proton/attribute/attribute_aspect_delayer.cpp index 9807faa5021..cf803ec0368 100644 --- a/searchcore/src/vespa/searchcore/proton/attribute/attribute_aspect_delayer.cpp +++ b/searchcore/src/vespa/searchcore/proton/attribute/attribute_aspect_delayer.cpp @@ -29,11 +29,15 @@ bool fastPartialUpdateAttribute(const search::attribute::Config &cfg) { (basicType != BasicType::Type::REFERENCE)); } +bool isStructFieldAttribute(const vespalib::string &name) { + return name.find('.') != vespalib::string::npos; +} + bool willTriggerReprocessOnAttributeAspectRemoval(const search::attribute::Config &cfg, const IIndexschemaInspector &indexschemaInspector, const vespalib::string &name) { - return fastPartialUpdateAttribute(cfg) && !indexschemaInspector.isStringIndex(name); + return fastPartialUpdateAttribute(cfg) && !indexschemaInspector.isStringIndex(name) && !isStructFieldAttribute(name); } @@ -73,6 +77,7 @@ handleNewAttributes(const AttributesConfig &oldAttributesConfig, SummarymapConfigBuilder &summarymapConfig) { vespalib::hash_set<vespalib::string> delayed; + vespalib::hash_set<vespalib::string> delayedStruct; AttributesConfigHash oldAttrs(oldAttributesConfig.attribute); for (const auto &newAttr : newAttributesConfig.attribute) { search::attribute::Config newCfg = ConfigConverter::convert(newAttr); @@ -102,6 +107,10 @@ handleNewAttributes(const AttributesConfig &oldAttributesConfig, } else { // Delay addition of attribute aspect delayed.insert(newAttr.name); + auto pos = newAttr.name.find('.'); + if (pos != vespalib::string::npos) { + delayedStruct.insert(newAttr.name.substr(0, pos)); + } } } } @@ -111,6 +120,11 @@ handleNewAttributes(const AttributesConfig &oldAttributesConfig, if (itr == delayed.end()) { summarymapConfig.override.emplace_back(override); } + } else if (override.command == "attributecombiner") { + auto itr = delayedStruct.find(override.field); + if (itr == delayedStruct.end()) { + summarymapConfig.override.emplace_back(override); + } } else { summarymapConfig.override.emplace_back(override); } diff --git a/searchcore/src/vespa/searchcore/proton/attribute/attribute_writer.cpp b/searchcore/src/vespa/searchcore/proton/attribute/attribute_writer.cpp index 0a0ecbda21c..506f4b5164c 100644 --- a/searchcore/src/vespa/searchcore/proton/attribute/attribute_writer.cpp +++ b/searchcore/src/vespa/searchcore/proton/attribute/attribute_writer.cpp @@ -7,16 +7,16 @@ LOG_SETUP(".proton.attribute.attribute_writer"); #include "ifieldupdatecallback.h" #include "attributemanager.h" #include "document_field_extractor.h" -#include <vespa/document/base/exceptions.h> -#include <vespa/document/datatype/documenttype.h> -#include <vespa/document/fieldvalue/document.h> #include <vespa/searchcore/proton/attribute/imported_attributes_repo.h> #include <vespa/searchcore/proton/common/attrupdate.h> #include <vespa/searchlib/attribute/attributevector.hpp> #include <vespa/searchlib/attribute/imported_attribute_vector.h> #include <vespa/searchlib/common/isequencedtaskexecutor.h> #include <vespa/searchlib/common/idestructorcallback.h> - +#include <vespa/document/base/exceptions.h> +#include <vespa/document/datatype/documenttype.h> +#include <vespa/document/fieldvalue/document.h> +#include <vespa/vespalib/stllike/hash_map.hpp> using namespace document; using namespace search; @@ -47,6 +47,8 @@ AttributeWriter::WriteField::buildFieldPath(const DocumentType &docType) docType.buildFieldPath(fp, name); } catch (document::FieldNotFoundException & e) { fp = FieldPath(); + } catch (vespalib::IllegalArgumentException &e) { + fp = FieldPath(); } _fieldPath = std::move(fp); } @@ -230,7 +232,7 @@ public: FieldContext::FieldContext(ISequencedTaskExecutor &writer, AttributeVector *attr) : _name(attr->getName()), - _executorId(writer.getExecutorId(_name)), + _executorId(writer.getExecutorId(attr->getNamePrefix())), _attr(attr) { } @@ -412,7 +414,7 @@ AttributeWriter::setupWriteContexts() { std::vector<FieldContext> fieldContexts; assert(_writeContexts.empty()); - for (auto attr : _writableAttributes) { + for (auto attr : getWritableAttributes()) { fieldContexts.emplace_back(_attributeFieldWriter, attr); } std::sort(fieldContexts.begin(), fieldContexts.end()); @@ -469,14 +471,23 @@ AttributeWriter::internalRemove(SerialNum serialNum, DocumentIdT lid, bool immed AttributeWriter::AttributeWriter(const proton::IAttributeManager::SP &mgr) : _mgr(mgr), _attributeFieldWriter(mgr->getAttributeFieldWriter()), - _writableAttributes(mgr->getWritableAttributes()), _writeContexts(), _dataType(nullptr), - _hasStructFieldAttribute(false) + _hasStructFieldAttribute(false), + _attrMap() { setupWriteContexts(); + setupAttriuteMapping(); } +void AttributeWriter::setupAttriuteMapping() { + for (auto attr : getWritableAttributes()) { + vespalib::stringref name = attr->getName(); + _attrMap[name] = AttrWithId(attr, _attributeFieldWriter.getExecutorId(attr->getNamePrefix())); + } +} + + AttributeWriter::~AttributeWriter() { _attributeFieldWriter.sync(); @@ -545,7 +556,8 @@ AttributeWriter::update(SerialNum serialNum, const DocumentUpdate &upd, Document 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()); + auto found = _attrMap.find(fupd.getField().getName()); + AttributeVector * attrp = (found != _attrMap.end()) ? found->second.first : nullptr; onUpdate.onUpdateField(fupd.getField().getName(), attrp); if (attrp == nullptr) { LOG(spam, "Failed to find attribute vector %s", fupd.getField().getName().c_str()); @@ -555,7 +567,7 @@ AttributeWriter::update(SerialNum serialNum, const DocumentUpdate &upd, Document // document and attribute. if (attrp->getStatus().getLastSyncToken() >= serialNum) continue; - args[_attributeFieldWriter.getExecutorId(attrp->getName()).getId()]->_updates.emplace_back(attrp, &fupd); + args[found->second.second.getId()]->_updates.emplace_back(attrp, &fupd); LOG(debug, "About to apply update for docId %u in attribute vector '%s'.", lid, attrp->getName().c_str()); } // NOTE: The lifetime of the field update will be ensured by keeping the document update alive @@ -572,11 +584,10 @@ AttributeWriter::update(SerialNum serialNum, const DocumentUpdate &upd, Document void AttributeWriter::heartBeat(SerialNum serialNum) { - for (auto attrp : _writableAttributes) { - auto &attr = *attrp; - _attributeFieldWriter.execute(attr.getName(), - [serialNum, &attr]() - { applyHeartBeat(serialNum, attr); }); + for (auto entry : _attrMap) { + _attributeFieldWriter.execute(entry.second.second, + [serialNum, attr=entry.second.first]() + { applyHeartBeat(serialNum, *attr); }); } } @@ -601,11 +612,10 @@ AttributeWriter::forceCommit(SerialNum serialNum, OnWriteDoneType onWriteDone) void AttributeWriter::onReplayDone(uint32_t docIdLimit) { - for (auto attrp : _writableAttributes) { - auto &attr = *attrp; - _attributeFieldWriter.execute(attr.getName(), - [docIdLimit, &attr]() - { applyReplayDone(docIdLimit, attr); }); + for (auto entry : _attrMap) { + _attributeFieldWriter.execute(entry.second.second, + [docIdLimit, attr = entry.second.first]() + { applyReplayDone(docIdLimit, *attr); }); } _attributeFieldWriter.sync(); } @@ -614,12 +624,11 @@ AttributeWriter::onReplayDone(uint32_t docIdLimit) void AttributeWriter::compactLidSpace(uint32_t wantedLidLimit, SerialNum serialNum) { - for (auto attrp : _writableAttributes) { - auto &attr = *attrp; + for (auto entry : _attrMap) { _attributeFieldWriter. - execute(attr.getName(), - [wantedLidLimit, serialNum, &attr]() - { applyCompactLidSpace(wantedLidLimit, serialNum, attr); }); + execute(entry.second.second, + [wantedLidLimit, serialNum, attr=entry.second.first]() + { applyCompactLidSpace(wantedLidLimit, serialNum, *attr); }); } _attributeFieldWriter.sync(); } diff --git a/searchcore/src/vespa/searchcore/proton/attribute/attribute_writer.h b/searchcore/src/vespa/searchcore/proton/attribute/attribute_writer.h index f89089ed335..4ea7f3fda6c 100644 --- a/searchcore/src/vespa/searchcore/proton/attribute/attribute_writer.h +++ b/searchcore/src/vespa/searchcore/proton/attribute/attribute_writer.h @@ -6,6 +6,7 @@ #include <vespa/searchcore/proton/common/commit_time_tracker.h> #include <vespa/document/base/fieldpath.h> #include <vespa/searchlib/common/isequencedtaskexecutor.h> +#include <vespa/vespalib/stllike/hash_map.h> namespace document { class DocumentType; } @@ -25,7 +26,6 @@ private: typedef document::FieldValue FieldValue; const IAttributeManager::SP _mgr; search::ISequencedTaskExecutor &_attributeFieldWriter; - const std::vector<search::AttributeVector *> &_writableAttributes; using ExecutorId = search::ISequencedTaskExecutor::ExecutorId; public: class WriteField @@ -58,11 +58,15 @@ public: bool hasStructFieldAttribute() const { return _hasStructFieldAttribute; } }; private: + using AttrWithId = std::pair<search::AttributeVector *, ExecutorId>; + using AttrMap = vespalib::hash_map<vespalib::string, AttrWithId>; std::vector<WriteContext> _writeContexts; const DataType *_dataType; bool _hasStructFieldAttribute; + AttrMap _attrMap; void setupWriteContexts(); + void setupAttriuteMapping(); void buildFieldPaths(const DocumentType &docType, const DataType *dataType); void internalPut(SerialNum serialNum, const Document &doc, DocumentIdT lid, bool immediateCommit, bool allAttributes, OnWriteDoneType onWriteDone); @@ -73,13 +77,13 @@ public: AttributeWriter(const proton::IAttributeManager::SP &mgr); ~AttributeWriter(); + /* Only for in tests that add attributes after AttributeWriter construction. */ + /** * Implements IAttributeWriter. */ - std::vector<search::AttributeVector *> - getWritableAttributes() const override; - search::AttributeVector * - getWritableAttribute(const vespalib::string &name) const override; + std::vector<search::AttributeVector *> getWritableAttributes() const override; + search::AttributeVector *getWritableAttribute(const vespalib::string &name) const override; void put(SerialNum serialNum, const Document &doc, DocumentIdT lid, bool immediateCommit, OnWriteDoneType onWriteDone) override; void remove(SerialNum serialNum, DocumentIdT lid, diff --git a/searchcore/src/vespa/searchcore/proton/attribute/attributemanager.cpp b/searchcore/src/vespa/searchcore/proton/attribute/attributemanager.cpp index ef818f7b407..5faf89aa149 100644 --- a/searchcore/src/vespa/searchcore/proton/attribute/attributemanager.cpp +++ b/searchcore/src/vespa/searchcore/proton/attribute/attributemanager.cpp @@ -78,8 +78,8 @@ std::shared_ptr<ShrinkLidSpaceFlushTarget> allocShrinker(const AttributeVector:: using Type = IFlushTarget::Type; using Component = IFlushTarget::Component; + auto shrinkwrap = std::make_shared<ThreadedCompactableLidSpace>(attr, attributeFieldWriter, attributeFieldWriter.getExecutorId(attr->getNamePrefix())); const vespalib::string &name = attr->getName(); - auto shrinkwrap = std::make_shared<ThreadedCompactableLidSpace>(attr, attributeFieldWriter, attributeFieldWriter.getExecutorId(name)); auto dir = diskLayout.createAttributeDir(name); search::SerialNum shrinkSerialNum = estimateShrinkSerialNum(*attr); return std::make_shared<ShrinkLidSpaceFlushTarget>("attribute.shrink." + name, Type::GC, Component::ATTRIBUTE, shrinkSerialNum, dir->getLastFlushTime(), shrinkwrap); @@ -569,16 +569,15 @@ AttributeManager::getWritableAttributes() const void -AttributeManager::asyncForEachAttribute(std::shared_ptr<IAttributeFunctor> - func) const +AttributeManager::asyncForEachAttribute(std::shared_ptr<IAttributeFunctor> func) const { for (const auto &attr : _attributes) { if (attr.second.isExtra()) { continue; } AttributeVector::SP attrsp = attr.second.getAttribute(); - _attributeFieldWriter. - execute(attr.first, [attrsp, func]() { (*func)(*attrsp); }); + _attributeFieldWriter.execute(_attributeFieldWriter.getExecutorId(attrsp->getNamePrefix()), + [attrsp, func]() { (*func)(*attrsp); }); } } diff --git a/searchcore/src/vespa/searchcore/proton/attribute/exclusive_attribute_read_accessor.cpp b/searchcore/src/vespa/searchcore/proton/attribute/exclusive_attribute_read_accessor.cpp index d9a0ff3d8dd..d1d5b1c9af7 100644 --- a/searchcore/src/vespa/searchcore/proton/attribute/exclusive_attribute_read_accessor.cpp +++ b/searchcore/src/vespa/searchcore/proton/attribute/exclusive_attribute_read_accessor.cpp @@ -37,8 +37,7 @@ ExclusiveAttributeReadAccessor(const AttributeVector::SP &attribute, namespace { void -attributeWriteBlockingTask(GateSP entranceGate, - GateSP exitGate) +attributeWriteBlockingTask(GateSP entranceGate, GateSP exitGate) { entranceGate->countDown(); exitGate->await(); @@ -51,9 +50,8 @@ ExclusiveAttributeReadAccessor::takeGuard() { GateSP entranceGate = std::make_shared<Gate>(); GateSP exitGate = std::make_shared<Gate>(); - _attributeFieldWriter.execute(_attribute->getName(), - [entranceGate, exitGate]() - { attributeWriteBlockingTask(entranceGate, exitGate); }); + _attributeFieldWriter.execute(_attributeFieldWriter.getExecutorId(_attribute->getNamePrefix()), + [entranceGate, exitGate]() { attributeWriteBlockingTask(entranceGate, exitGate); }); entranceGate->await(); return std::make_unique<Guard>(*_attribute, exitGate); } 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 d3a74bb9a98..8474efb15c9 100644 --- a/searchcore/src/vespa/searchcore/proton/attribute/filter_attribute_manager.cpp +++ b/searchcore/src/vespa/searchcore/proton/attribute/filter_attribute_manager.cpp @@ -197,9 +197,8 @@ FilterAttributeManager::asyncForEachAttribute(std::shared_ptr<IAttributeFunctor> search::AttributeVector::SP attrsp = guard.getSP(); // Name must be extracted in document db master thread or attribute // writer thread - vespalib::string attributeName = attrsp->getName(); - attributeFieldWriter. - execute(attributeName, [attrsp, func]() { (*func)(*attrsp); }); + attributeFieldWriter.execute(attributeFieldWriter.getExecutorId(attrsp->getNamePrefix()), + [attrsp, func]() { (*func)(*attrsp); }); } } diff --git a/searchcore/src/vespa/searchcore/proton/attribute/flushableattribute.cpp b/searchcore/src/vespa/searchcore/proton/attribute/flushableattribute.cpp index a658b11263a..7716fc5ee61 100644 --- a/searchcore/src/vespa/searchcore/proton/attribute/flushableattribute.cpp +++ b/searchcore/src/vespa/searchcore/proton/attribute/flushableattribute.cpp @@ -243,10 +243,8 @@ FlushableAttribute::initFlush(SerialNum currentSerial) // Called by document db executor std::promise<IFlushTarget::Task::UP> promise; std::future<IFlushTarget::Task::UP> future = promise.get_future(); - _attributeFieldWriter.execute(_attr->getName(), - [&]() { promise.set_value( - internalInitFlush(currentSerial)); - }); + _attributeFieldWriter.execute(_attributeFieldWriter.getExecutorId(_attr->getNamePrefix()), + [&]() { promise.set_value(internalInitFlush(currentSerial)); }); return future.get(); } @@ -257,5 +255,4 @@ FlushableAttribute::getApproxBytesToWriteToDisk() const return _attr->getEstimatedSaveByteSize(); } - } // namespace proton diff --git a/searchcore/src/vespa/searchcore/proton/common/document_type_inspector.cpp b/searchcore/src/vespa/searchcore/proton/common/document_type_inspector.cpp index 6cff162ae08..e19fa5351c2 100644 --- a/searchcore/src/vespa/searchcore/proton/common/document_type_inspector.cpp +++ b/searchcore/src/vespa/searchcore/proton/common/document_type_inspector.cpp @@ -1,6 +1,11 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. #include "document_type_inspector.h" +#include <vespa/document/base/exceptions.h> +#include <vespa/document/base/fieldpath.h> + +using document::FieldPath; +using document::FieldPathEntry; namespace proton { @@ -14,12 +19,28 @@ DocumentTypeInspector::DocumentTypeInspector(const document::DocumentType &oldDo bool DocumentTypeInspector::hasUnchangedField(const vespalib::string &name) const { - if (!_oldDocType.hasField(name) || !_newDocType.hasField(name)) { + FieldPath oldPath; + FieldPath newPath; + try { + _oldDocType.buildFieldPath(oldPath, name); + _newDocType.buildFieldPath(newPath, name); + } catch (document::FieldNotFoundException &e) { + return false; + } catch (vespalib::IllegalArgumentException &e) { return false; } - const document::Field &oldField = _oldDocType.getField(name); - const document::Field &newField = _newDocType.getField(name); - return oldField == newField; + if (oldPath.size() != newPath.size()) { + return false; + } + for (uint32_t i = 0; i < oldPath.size(); ++i) { + const auto &oldEntry = oldPath[i]; + const auto &newEntry = newPath[i]; + if (oldEntry.getType() != newEntry.getType() || + oldEntry.getDataType() != newEntry.getDataType()) { + return false; + } + } + return true; } } // namespace proton diff --git a/searchcore/src/vespa/searchcore/proton/feedoperation/compact_lid_space_operation.cpp b/searchcore/src/vespa/searchcore/proton/feedoperation/compact_lid_space_operation.cpp index cd906891b92..c2a3439388a 100644 --- a/searchcore/src/vespa/searchcore/proton/feedoperation/compact_lid_space_operation.cpp +++ b/searchcore/src/vespa/searchcore/proton/feedoperation/compact_lid_space_operation.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 "compact_lid_space_operation.h" +#include <vespa/vespalib/objects/nbostream.h> #include <vespa/vespalib/util/stringfmt.h> namespace proton { @@ -27,8 +28,7 @@ CompactLidSpaceOperation::serialize(vespalib::nbostream& os) const } void -CompactLidSpaceOperation::deserialize(vespalib::nbostream& is, - const document::DocumentTypeRepo&) +CompactLidSpaceOperation::deserialize(vespalib::nbostream& is, const document::DocumentTypeRepo&) { is >> _subDbId; is >> _lidLimit; diff --git a/searchcore/src/vespa/searchcore/proton/feedoperation/feedoperation.h b/searchcore/src/vespa/searchcore/proton/feedoperation/feedoperation.h index 8a00c739126..77b95547bd0 100644 --- a/searchcore/src/vespa/searchcore/proton/feedoperation/feedoperation.h +++ b/searchcore/src/vespa/searchcore/proton/feedoperation/feedoperation.h @@ -2,10 +2,10 @@ #pragma once #include <vespa/searchlib/common/serialnum.h> -#include <vespa/vespalib/objects/nbostream.h> +#include <vespa/vespalib/stllike/string.h> namespace document { class DocumentTypeRepo; } - +namespace vespalib { class nbostream; } namespace proton { class FeedOperation diff --git a/searchcore/src/vespa/searchcore/proton/feedoperation/lidvectorcontext.cpp b/searchcore/src/vespa/searchcore/proton/feedoperation/lidvectorcontext.cpp index 71a701bdb40..67e4d1b4287 100644 --- a/searchcore/src/vespa/searchcore/proton/feedoperation/lidvectorcontext.cpp +++ b/searchcore/src/vespa/searchcore/proton/feedoperation/lidvectorcontext.cpp @@ -2,6 +2,7 @@ #include "lidvectorcontext.h" #include <vespa/searchlib/common/bitvector.h> +#include <vespa/vespalib/objects/nbostream.h> #include <vespa/log/log.h> LOG_SETUP(".proton.feedoperation.lidvectorcontext"); diff --git a/searchcore/src/vespa/searchcore/proton/feedoperation/lidvectorcontext.h b/searchcore/src/vespa/searchcore/proton/feedoperation/lidvectorcontext.h index b432bbcf20a..b307e50da0a 100644 --- a/searchcore/src/vespa/searchcore/proton/feedoperation/lidvectorcontext.h +++ b/searchcore/src/vespa/searchcore/proton/feedoperation/lidvectorcontext.h @@ -2,9 +2,10 @@ #pragma once #include <vespa/searchlib/query/base.h> -#include <vespa/vespalib/objects/nbostream.h> #include <vector> +namespace vespalib { class nbostream; } + namespace proton { class LidVectorContext @@ -29,5 +30,4 @@ public: size_t getNumLids() const { return _result.size(); } }; -} // namespace proton - +} diff --git a/searchcore/src/vespa/searchcore/proton/feedoperation/newconfigoperation.h b/searchcore/src/vespa/searchcore/proton/feedoperation/newconfigoperation.h index b7b041135d4..144aa534bf7 100644 --- a/searchcore/src/vespa/searchcore/proton/feedoperation/newconfigoperation.h +++ b/searchcore/src/vespa/searchcore/proton/feedoperation/newconfigoperation.h @@ -2,30 +2,29 @@ #pragma once #include "feedoperation.h" -#include <vespa/vespalib/objects/nbostream.h> namespace proton { + namespace feedoperation { + struct IStreamHandler { + virtual ~IStreamHandler() {} + virtual void serializeConfig(search::SerialNum serialNum, vespalib::nbostream &os) = 0; + virtual void deserializeConfig(search::SerialNum serialNum, vespalib::nbostream &is) = 0; + }; + } + class NewConfigOperation : public FeedOperation { public: - struct IStreamHandler { - virtual ~IStreamHandler() {} - virtual void serializeConfig(SerialNum serialNum, - vespalib::nbostream &os) = 0; - virtual void deserializeConfig(SerialNum serialNum, - vespalib::nbostream &is) = 0; - }; + using IStreamHandler = feedoperation::IStreamHandler; private: IStreamHandler &_streamHandler; public: - NewConfigOperation(SerialNum serialNum, - IStreamHandler &streamHandler); - virtual ~NewConfigOperation() {} - virtual void serialize(vespalib::nbostream &os) const override; - virtual void deserialize(vespalib::nbostream &is, - const document::DocumentTypeRepo &repo) override; - virtual vespalib::string toString() const override; + NewConfigOperation(SerialNum serialNum, IStreamHandler &streamHandler); + ~NewConfigOperation() override {} + void serialize(vespalib::nbostream &os) const override; + void deserialize(vespalib::nbostream &is, const document::DocumentTypeRepo &repo) override; + vespalib::string toString() const override; }; } // namespace proton diff --git a/searchcore/src/vespa/searchcore/proton/feedoperation/pruneremoveddocumentsoperation.cpp b/searchcore/src/vespa/searchcore/proton/feedoperation/pruneremoveddocumentsoperation.cpp index eea693e4680..69f754cd594 100644 --- a/searchcore/src/vespa/searchcore/proton/feedoperation/pruneremoveddocumentsoperation.cpp +++ b/searchcore/src/vespa/searchcore/proton/feedoperation/pruneremoveddocumentsoperation.cpp @@ -2,6 +2,7 @@ #include "pruneremoveddocumentsoperation.h" #include <vespa/vespalib/util/stringfmt.h> +#include <vespa/vespalib/objects/nbostream.h> #include <cassert> #include <vespa/log/log.h> @@ -22,8 +23,7 @@ PruneRemovedDocumentsOperation::PruneRemovedDocumentsOperation() PruneRemovedDocumentsOperation:: -PruneRemovedDocumentsOperation(DocumentIdT docIdLimit, - uint32_t subDbId) +PruneRemovedDocumentsOperation(DocumentIdT docIdLimit, uint32_t subDbId) : RemoveDocumentsOperation(FeedOperation::PRUNE_REMOVED_DOCUMENTS), _subDbId(subDbId) { @@ -44,8 +44,7 @@ PruneRemovedDocumentsOperation::serialize(vespalib::nbostream &os) const void -PruneRemovedDocumentsOperation::deserialize(vespalib::nbostream &is, - const DocumentTypeRepo &) +PruneRemovedDocumentsOperation::deserialize(vespalib::nbostream &is, const DocumentTypeRepo &) { is >> _subDbId; deserializeLidsToRemove(is); diff --git a/searchcore/src/vespa/searchcore/proton/feedoperation/removedocumentsoperation.cpp b/searchcore/src/vespa/searchcore/proton/feedoperation/removedocumentsoperation.cpp index 6aa479611d1..ef482a19ca3 100644 --- a/searchcore/src/vespa/searchcore/proton/feedoperation/removedocumentsoperation.cpp +++ b/searchcore/src/vespa/searchcore/proton/feedoperation/removedocumentsoperation.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 "removedocumentsoperation.h" +#include <vespa/vespalib/objects/nbostream.h> namespace proton { @@ -16,11 +17,9 @@ RemoveDocumentsOperation::serializeLidsToRemove(vespalib::nbostream &os) const { uint32_t mapSize = _lidsToRemoveMap.size(); os << mapSize; - for (LidsToRemoveMap::const_iterator - it = _lidsToRemoveMap.begin(), ite = _lidsToRemoveMap.end(); - it != ite; ++it) { - os << it->first; - it->second->serialize(os); + for (const auto & entry : _lidsToRemoveMap) { + os << entry.first; + entry.second->serialize(os); } } diff --git a/searchcore/src/vespa/searchcore/proton/feedoperation/spoolerreplayoperation.cpp b/searchcore/src/vespa/searchcore/proton/feedoperation/spoolerreplayoperation.cpp index f3ef73f4d90..16ddedc4745 100644 --- a/searchcore/src/vespa/searchcore/proton/feedoperation/spoolerreplayoperation.cpp +++ b/searchcore/src/vespa/searchcore/proton/feedoperation/spoolerreplayoperation.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 "spoolerreplayoperation.h" +#include <vespa/vespalib/objects/nbostream.h> #include <vespa/vespalib/util/stringfmt.h> using vespalib::make_string; @@ -14,10 +15,7 @@ SpoolerReplayOperation::SpoolerReplayOperation(Type type) { } - -SpoolerReplayOperation::SpoolerReplayOperation(Type type, - SerialNum serialNum, - SerialNum spoolerSerialNum) +SpoolerReplayOperation::SpoolerReplayOperation(Type type, SerialNum serialNum, SerialNum spoolerSerialNum) : FeedOperation(type), _spoolerSerialNum(spoolerSerialNum) { @@ -39,11 +37,8 @@ SpoolerReplayOperation::deserialize(vespalib::nbostream &is) } vespalib::string SpoolerReplayOperation::toString() const { - return make_string( - "SpoolerReplay%s(spoolerSerialNum=%" PRIu64 - ", serialNum=%" PRIu64 ")", - getType() == SPOOLER_REPLAY_START ? "Start" : "Complete", - _spoolerSerialNum, getSerialNum()); + return make_string("SpoolerReplay%s(spoolerSerialNum=%" PRIu64", serialNum=%" PRIu64 ")", + getType() == SPOOLER_REPLAY_START ? "Start" : "Complete", _spoolerSerialNum, getSerialNum()); } @@ -53,8 +48,7 @@ SpoolerReplayStartOperation::SpoolerReplayStartOperation() } -SpoolerReplayStartOperation::SpoolerReplayStartOperation(SerialNum serialNum, - SerialNum spoolerSerialNum) +SpoolerReplayStartOperation::SpoolerReplayStartOperation(SerialNum serialNum, SerialNum spoolerSerialNum) : SpoolerReplayOperation(FeedOperation::SPOOLER_REPLAY_START, serialNum, spoolerSerialNum) @@ -70,12 +64,8 @@ SpoolerReplayCompleteOperation::SpoolerReplayCompleteOperation() SpoolerReplayCompleteOperation::SpoolerReplayCompleteOperation(SerialNum serialNum, SerialNum spoolerSerialNum) - : SpoolerReplayOperation(FeedOperation::SPOOLER_REPLAY_COMPLETE, - serialNum, - spoolerSerialNum) + : SpoolerReplayOperation(FeedOperation::SPOOLER_REPLAY_COMPLETE, serialNum, spoolerSerialNum) { } - - } // namespace proton diff --git a/searchcore/src/vespa/searchcore/proton/feedoperation/spoolerreplayoperation.h b/searchcore/src/vespa/searchcore/proton/feedoperation/spoolerreplayoperation.h index 028d01dec20..028ad1c6bfa 100644 --- a/searchcore/src/vespa/searchcore/proton/feedoperation/spoolerreplayoperation.h +++ b/searchcore/src/vespa/searchcore/proton/feedoperation/spoolerreplayoperation.h @@ -11,15 +11,12 @@ private: SerialNum _spoolerSerialNum; protected: SpoolerReplayOperation(Type type); - SpoolerReplayOperation(Type type, - SerialNum serialNum, - SerialNum spoolerSerialNum); + SpoolerReplayOperation(Type type, SerialNum serialNum, SerialNum spoolerSerialNum); public: - virtual ~SpoolerReplayOperation() {} + ~SpoolerReplayOperation() override {} SerialNum getSpoolerSerialNum() const { return _spoolerSerialNum; } - virtual void serialize(vespalib::nbostream &os) const override; - virtual void deserialize(vespalib::nbostream &is, - const document::DocumentTypeRepo &) override { + void serialize(vespalib::nbostream &os) const override; + void deserialize(vespalib::nbostream &is, const document::DocumentTypeRepo &) override { deserialize(is); } void deserialize(vespalib::nbostream &is); @@ -38,8 +35,7 @@ public: * @param serialNum the current serial number of the transaction log. * @param spoolerSerialNum the serial number of the first entry of the spooler log replay. */ - SpoolerReplayStartOperation(SerialNum serialNum, - SerialNum spoolerSerialNum); + SpoolerReplayStartOperation(SerialNum serialNum, SerialNum spoolerSerialNum); }; @@ -54,8 +50,7 @@ public: * @param serialNum the current serial number of the transaction log. * @param spoolerSerialNum the serial number of the last entry of the spooler log replay. */ - SpoolerReplayCompleteOperation(SerialNum serialNum, - SerialNum spoolerSerialNum); + SpoolerReplayCompleteOperation(SerialNum serialNum, SerialNum spoolerSerialNum); }; } // namespace proton diff --git a/searchcore/src/vespa/searchcore/proton/feedoperation/updateoperation.cpp b/searchcore/src/vespa/searchcore/proton/feedoperation/updateoperation.cpp index d31f1faec77..dc83848152c 100644 --- a/searchcore/src/vespa/searchcore/proton/feedoperation/updateoperation.cpp +++ b/searchcore/src/vespa/searchcore/proton/feedoperation/updateoperation.cpp @@ -51,12 +51,11 @@ UpdateOperation::serializeUpdate(vespalib::nbostream &os) const } void -UpdateOperation::deserializeUpdate(vespalib::nbostream &is, const document::DocumentTypeRepo &repo) +UpdateOperation::deserializeUpdate(vespalib::nbostream && is, const document::DocumentTypeRepo &repo) { - document::ByteBuffer buf(is.peek(), is.size()); - DocumentUpdate::UP update = (getType() == UPDATE_42) ? DocumentUpdate::create42(repo, buf) : DocumentUpdate::createHEAD(repo, buf); - is.adjustReadPos(buf.getPos()); - _upd = std::move(update); + _upd = (getType() == UPDATE_42) + ? DocumentUpdate::create42(repo, is) + : DocumentUpdate::createHEAD(repo, std::move(is)); } void @@ -73,7 +72,7 @@ UpdateOperation::deserialize(vespalib::nbostream &is, const DocumentTypeRepo &re { DocumentOperation::deserialize(is, repo); try { - deserializeUpdate(is, repo); + deserializeUpdate(std::move(is), repo); } catch (document::DocumentTypeNotFoundException &e) { LOG(warning, "Failed deserialize update operation using unknown document type '%s'", e.getDocumentTypeName().c_str()); @@ -83,18 +82,19 @@ UpdateOperation::deserialize(vespalib::nbostream &is, const DocumentTypeRepo &re } void -UpdateOperation::deserializeUpdate(const DocumentTypeRepo &repo) +UpdateOperation::verifyUpdate(const DocumentTypeRepo &repo) { vespalib::nbostream stream; serializeUpdate(stream); - deserializeUpdate(stream, repo); + deserializeUpdate(std::move(stream), repo); + _upd->eagerDeserialize(); // Will trigger exceptions if incompatible } -vespalib::string UpdateOperation::toString() const { +vespalib::string +UpdateOperation::toString() const { return make_string("%s(%s, %s)", ((getType() == FeedOperation::UPDATE_42) ? "Update42" : "Update"), - _upd.get() ? - _upd->getId().getScheme().toString().c_str() : "NULL", + _upd.get() ? _upd->getId().getScheme().toString().c_str() : "NULL", docArgsToString().c_str()); } diff --git a/searchcore/src/vespa/searchcore/proton/feedoperation/updateoperation.h b/searchcore/src/vespa/searchcore/proton/feedoperation/updateoperation.h index 99dcbfbce6c..83e87fea096 100644 --- a/searchcore/src/vespa/searchcore/proton/feedoperation/updateoperation.h +++ b/searchcore/src/vespa/searchcore/proton/feedoperation/updateoperation.h @@ -19,7 +19,7 @@ private: const storage::spi::Timestamp ×tamp, const DocumentUpdateSP &upd); void serializeUpdate(vespalib::nbostream &os) const; - void deserializeUpdate(vespalib::nbostream &is, const document::DocumentTypeRepo &repo); + void deserializeUpdate(vespalib::nbostream && is, const document::DocumentTypeRepo &repo); public: UpdateOperation(); UpdateOperation(Type type); @@ -30,7 +30,7 @@ public: const DocumentUpdateSP &getUpdate() const { return _upd; } void serialize(vespalib::nbostream &os) const override; void deserialize(vespalib::nbostream &is, const document::DocumentTypeRepo &repo) override; - void deserializeUpdate(const document::DocumentTypeRepo &repo); + void verifyUpdate(const document::DocumentTypeRepo &repo); vespalib::string toString() const override; }; diff --git a/searchcore/src/vespa/searchcore/proton/feedoperation/wipehistoryoperation.cpp b/searchcore/src/vespa/searchcore/proton/feedoperation/wipehistoryoperation.cpp index d7f38a0cc52..c5e6acd80ed 100644 --- a/searchcore/src/vespa/searchcore/proton/feedoperation/wipehistoryoperation.cpp +++ b/searchcore/src/vespa/searchcore/proton/feedoperation/wipehistoryoperation.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 "wipehistoryoperation.h" +#include <vespa/vespalib/objects/nbostream.h> #include <vespa/vespalib/util/stringfmt.h> using vespalib::make_string; @@ -9,29 +10,29 @@ namespace proton { WipeHistoryOperation::WipeHistoryOperation() : FeedOperation(FeedOperation::WIPE_HISTORY), - _wipeTimeLimit(0) { + _wipeTimeLimit(0) +{ } WipeHistoryOperation::WipeHistoryOperation(SerialNum serialNum, fastos::TimeStamp wipeTimeLimit) : FeedOperation(FeedOperation::WIPE_HISTORY), - _wipeTimeLimit(wipeTimeLimit) { + _wipeTimeLimit(wipeTimeLimit) +{ setSerialNum(serialNum); } void WipeHistoryOperation::serialize(vespalib::nbostream &str) const { str << _wipeTimeLimit; } -void WipeHistoryOperation::deserialize(vespalib::nbostream &str, - const document::DocumentTypeRepo &) { +void WipeHistoryOperation::deserialize(vespalib::nbostream &str, const document::DocumentTypeRepo &) { fastos::TimeStamp::TimeT t; str >> t; _wipeTimeLimit = t; } vespalib::string WipeHistoryOperation::toString() const { - return make_string("WipeHistory(wipeTimeLimit=%" PRIu64 - ", serialNum=%" PRIu64 ")", + return make_string("WipeHistory(wipeTimeLimit=%" PRIu64 ", serialNum=%" PRIu64 ")", _wipeTimeLimit.ns(), getSerialNum()); } diff --git a/searchcore/src/vespa/searchcore/proton/feedoperation/wipehistoryoperation.h b/searchcore/src/vespa/searchcore/proton/feedoperation/wipehistoryoperation.h index 80b551dbd92..0cf7256bf27 100644 --- a/searchcore/src/vespa/searchcore/proton/feedoperation/wipehistoryoperation.h +++ b/searchcore/src/vespa/searchcore/proton/feedoperation/wipehistoryoperation.h @@ -12,14 +12,13 @@ class WipeHistoryOperation : public FeedOperation { public: WipeHistoryOperation(); WipeHistoryOperation(SerialNum serialNum, fastos::TimeStamp wipeTimeLimit); - virtual ~WipeHistoryOperation() {} + ~WipeHistoryOperation() override {} fastos::TimeStamp getWipeTimeLimit() const { return _wipeTimeLimit; } - virtual void serialize(vespalib::nbostream &str) const override; - virtual void deserialize(vespalib::nbostream &str, - const document::DocumentTypeRepo &) override; - virtual vespalib::string toString() const override; + void serialize(vespalib::nbostream &str) const override; + void deserialize(vespalib::nbostream &str, const document::DocumentTypeRepo &) override; + vespalib::string toString() const override; }; } // namespace proton diff --git a/searchcore/src/vespa/searchcore/proton/persistenceengine/persistenceengine.cpp b/searchcore/src/vespa/searchcore/proton/persistenceengine/persistenceengine.cpp index bab3494ca5c..6475efdaabb 100644 --- a/searchcore/src/vespa/searchcore/proton/persistenceengine/persistenceengine.cpp +++ b/searchcore/src/vespa/searchcore/proton/persistenceengine/persistenceengine.cpp @@ -6,7 +6,9 @@ #include <vespa/metrics/loadmetric.h> #include <vespa/vespalib/stllike/hash_set.h> #include <vespa/document/fieldvalue/document.h> +#include <vespa/document/datatype/documenttype.h> #include <vespa/document/update/documentupdate.h> +#include <vespa/document/base/exceptions.h> #include <vespa/log/log.h> @@ -25,6 +27,7 @@ using storage::spi::Result; using vespalib::IllegalStateException; using vespalib::Sequence; using vespalib::make_string; +using std::make_unique; using namespace std::chrono_literals; @@ -377,6 +380,18 @@ PersistenceEngine::update(const Bucket& b, Timestamp t, const DocumentUpdate::SP upd->getId().toString().c_str(), state.message().c_str())); } } + try { + upd->eagerDeserialize(); + } catch (document::FieldNotFoundException & e) { + return UpdateResult(Result::TRANSIENT_ERROR, + make_string("Update operation rejected for document '%s' of type '%s': 'Field not found'", + upd->getId().toString().c_str(), upd->getType().getName().c_str())); + } catch (document::DocumentTypeNotFoundException & e) { + return UpdateResult(Result::TRANSIENT_ERROR, + make_string("Update operation rejected for document '%s' of type '%s'.", + upd->getId().toString().c_str(), e.getDocumentTypeName().c_str())); + + } std::shared_lock<std::shared_timed_mutex> rguard(_rwMutex); DocTypeName docType(upd->getType()); LOG(spam, "update(%s, %" PRIu64 ", (\"%s\", \"%s\"), createIfNonExistent='%s')", diff --git a/searchcore/src/vespa/searchcore/proton/persistenceengine/persistenceengine.h b/searchcore/src/vespa/searchcore/proton/persistenceengine/persistenceengine.h index f2ab35e0ccf..a6c696d08fb 100644 --- a/searchcore/src/vespa/searchcore/proton/persistenceengine/persistenceengine.h +++ b/searchcore/src/vespa/searchcore/proton/persistenceengine/persistenceengine.h @@ -87,37 +87,36 @@ public: PersistenceEngine(IPersistenceEngineOwner &owner, const IResourceWriteFilter &writeFilter, ssize_t defaultSerializedSize, bool ignoreMaxBytes); - ~PersistenceEngine(); + ~PersistenceEngine() override; IPersistenceHandler::SP putHandler(document::BucketSpace bucketSpace, const DocTypeName &docType, const IPersistenceHandler::SP &handler); IPersistenceHandler::SP removeHandler(document::BucketSpace bucketSpace, const DocTypeName &docType); // Implements PersistenceProvider - virtual Result initialize() override; - virtual PartitionStateListResult getPartitionStates() const override; - virtual BucketIdListResult listBuckets(BucketSpace bucketSpace, PartitionId) const override; - virtual Result setClusterState(BucketSpace bucketSpace, const ClusterState& calc) override; - virtual Result setActiveState(const Bucket& bucket, BucketInfo::ActiveState newState) override; - virtual BucketInfoResult getBucketInfo(const Bucket&) const override; - virtual Result put(const Bucket&, Timestamp, const std::shared_ptr<document::Document>&, Context&) override; - virtual RemoveResult remove(const Bucket&, Timestamp, const document::DocumentId&, Context&) override; - virtual UpdateResult update(const Bucket&, Timestamp, - const std::shared_ptr<document::DocumentUpdate>&, Context&) override; - virtual GetResult get(const Bucket&, const document::FieldSet&, - const document::DocumentId&, Context&) const override; - virtual CreateIteratorResult createIterator(const Bucket&, const document::FieldSet&, const Selection&, - IncludedVersions, Context&) override; - virtual IterateResult iterate(IteratorId, uint64_t maxByteSize, Context&) const override; - virtual Result destroyIterator(IteratorId, Context&) override; - - virtual Result createBucket(const Bucket &bucketId, Context &) override ; - virtual Result deleteBucket(const Bucket&, Context&) override; - virtual BucketIdListResult getModifiedBuckets(BucketSpace bucketSpace) const override; - virtual Result split(const Bucket& source, const Bucket& target1, const Bucket& target2, Context&) override; - virtual Result join(const Bucket& source1, const Bucket& source2, const Bucket& target, Context&) override; - - virtual Result maintain(const Bucket&, MaintenanceLevel) override; + Result initialize() override; + PartitionStateListResult getPartitionStates() const override; + BucketIdListResult listBuckets(BucketSpace bucketSpace, PartitionId) const override; + Result setClusterState(BucketSpace bucketSpace, const ClusterState& calc) override; + Result setActiveState(const Bucket& bucket, BucketInfo::ActiveState newState) override; + BucketInfoResult getBucketInfo(const Bucket&) const override; + Result put(const Bucket&, Timestamp, const std::shared_ptr<document::Document>&, Context&) override; + RemoveResult remove(const Bucket&, Timestamp, const document::DocumentId&, Context&) override; + UpdateResult update(const Bucket&, Timestamp, + const std::shared_ptr<document::DocumentUpdate>&, Context&) override; + GetResult get(const Bucket&, const document::FieldSet&, const document::DocumentId&, Context&) const override; + CreateIteratorResult createIterator(const Bucket&, const document::FieldSet&, const Selection&, + IncludedVersions, Context&) override; + IterateResult iterate(IteratorId, uint64_t maxByteSize, Context&) const override; + Result destroyIterator(IteratorId, Context&) override; + + Result createBucket(const Bucket &bucketId, Context &) override ; + Result deleteBucket(const Bucket&, Context&) override; + BucketIdListResult getModifiedBuckets(BucketSpace bucketSpace) const override; + Result split(const Bucket& source, const Bucket& target1, const Bucket& target2, Context&) override; + Result join(const Bucket& source1, const Bucket& source2, const Bucket& target, Context&) override; + + Result maintain(const Bucket&, MaintenanceLevel) override; void destroyIterators(); void propagateSavedClusterState(BucketSpace bucketSpace, IPersistenceHandler &handler); diff --git a/searchcore/src/vespa/searchcore/proton/reference/gid_to_lid_change_listener.cpp b/searchcore/src/vespa/searchcore/proton/reference/gid_to_lid_change_listener.cpp index da03adb3fe4..46096fead05 100644 --- a/searchcore/src/vespa/searchcore/proton/reference/gid_to_lid_change_listener.cpp +++ b/searchcore/src/vespa/searchcore/proton/reference/gid_to_lid_change_listener.cpp @@ -12,7 +12,7 @@ GidToLidChangeListener::GidToLidChangeListener(search::ISequencedTaskExecutor &a const vespalib::string &name, const vespalib::string &docTypeName) : _attributeFieldWriter(attributeFieldWriter), - _executorId(_attributeFieldWriter.getExecutorId(attr->getName())), + _executorId(_attributeFieldWriter.getExecutorId(attr->getNamePrefix())), _attr(std::move(attr)), _refCount(refCount), _name(name), diff --git a/searchcore/src/vespa/searchcore/proton/reprocessing/attribute_reprocessing_initializer.cpp b/searchcore/src/vespa/searchcore/proton/reprocessing/attribute_reprocessing_initializer.cpp index 711f8ebdcaf..1df812b0c61 100644 --- a/searchcore/src/vespa/searchcore/proton/reprocessing/attribute_reprocessing_initializer.cpp +++ b/searchcore/src/vespa/searchcore/proton/reprocessing/attribute_reprocessing_initializer.cpp @@ -38,6 +38,9 @@ bool fastPartialUpdateAttribute(BasicType::Type attrType) { (attrType != BasicType::Type::REFERENCE)); } +bool isStructFieldAttribute(const vespalib::string &name) { + return name.find('.') != vespalib::string::npos; +} FilterAttributeManager::AttributeSet getAttributeSetToPopulate(const ARIConfig &newCfg, @@ -100,7 +103,8 @@ getFieldsToPopulate(const ARIConfig &newCfg, // keep the original in order to preserve annotations. bool wasStringIndexField = oldIndexschemaInspector.isStringIndex(name); bool populateField = !inNewAttrMgr && unchangedField && !wasStringIndexField && - fastPartialUpdateAttribute(attrType.type()); + fastPartialUpdateAttribute(attrType.type()) && + !isStructFieldAttribute(name); LOG(debug, "getFieldsToPopulate(): name='%s', inNewAttrMgr=%s, unchangedField=%s, " "wasStringIndexField=%s, dataType=%s, populate=%s", name.c_str(), toStr(inNewAttrMgr), toStr(unchangedField), diff --git a/searchcore/src/vespa/searchcore/proton/server/combiningfeedview.cpp b/searchcore/src/vespa/searchcore/proton/server/combiningfeedview.cpp index 87735dfef5d..6a000973165 100644 --- a/searchcore/src/vespa/searchcore/proton/server/combiningfeedview.cpp +++ b/searchcore/src/vespa/searchcore/proton/server/combiningfeedview.cpp @@ -3,7 +3,7 @@ #include "combiningfeedview.h" #include <vespa/document/fieldvalue/document.h> #include <vespa/searchcore/proton/documentmetastore/i_document_meta_store.h> -#include <vespa/searchcore/proton/feedoperation/moveoperation.h> +#include <vespa/searchcore/proton/feedoperation/operations.h> #include <vespa/searchlib/common/idestructorcallback.h> #include <vespa/log/log.h> @@ -13,17 +13,15 @@ using document::DocumentTypeRepo; using document::DocumentId; using search::IDestructorCallback; -namespace proton -{ +namespace proton { -namespace -{ +namespace { std::shared_ptr<const DocumentTypeRepo> getRepo(const std::vector<IFeedView::SP> &views) { for (const auto &view : views) { - if (view.get() == NULL) + if (view.get() == nullptr) continue; return view->getDocumentTypeRepo(); } diff --git a/searchcore/src/vespa/searchcore/proton/server/combiningfeedview.h b/searchcore/src/vespa/searchcore/proton/server/combiningfeedview.h index 6644f21a3b7..3546fdbea71 100644 --- a/searchcore/src/vespa/searchcore/proton/server/combiningfeedview.h +++ b/searchcore/src/vespa/searchcore/proton/server/combiningfeedview.h @@ -3,21 +3,14 @@ #pragma once #include "ifeedview.h" -#include <vespa/searchcore/proton/common/feedtoken.h> -#include <vespa/searchcore/proton/feedoperation/deletebucketoperation.h> -#include <vespa/searchcore/proton/feedoperation/joinbucketsoperation.h> -#include <vespa/searchcore/proton/feedoperation/pruneremoveddocumentsoperation.h> -#include <vespa/searchcore/proton/feedoperation/putoperation.h> -#include <vespa/searchcore/proton/feedoperation/removeoperation.h> -#include <vespa/searchcore/proton/feedoperation/splitbucketoperation.h> -#include <vespa/searchcore/proton/feedoperation/updateoperation.h> -#include <vespa/searchcore/proton/feedoperation/createbucketoperation.h> -#include <vespa/searchlib/common/serialnum.h> #include "replaypacketdispatcher.h" #include "ibucketstatecalculator.h" +#include <vespa/searchcore/proton/common/feedtoken.h> +#include <vespa/searchlib/common/serialnum.h> namespace proton { +class DocumentOperation; class CombiningFeedView : public IFeedView { diff --git a/searchcore/src/vespa/searchcore/proton/server/documentdb.cpp b/searchcore/src/vespa/searchcore/proton/server/documentdb.cpp index 61ce0e6dc6f..ad7a2d57c89 100644 --- a/searchcore/src/vespa/searchcore/proton/server/documentdb.cpp +++ b/searchcore/src/vespa/searchcore/proton/server/documentdb.cpp @@ -17,6 +17,7 @@ #include <vespa/searchcore/proton/attribute/imported_attributes_repo.h> #include <vespa/searchcore/proton/common/eventlogger.h> #include <vespa/searchcore/proton/common/statusreport.h> +#include <vespa/searchcore/proton/feedoperation/noopoperation.h> #include <vespa/searchcore/proton/index/index_writer.h> #include <vespa/searchcore/proton/initializer/task_runner.h> #include <vespa/searchcore/proton/metrics/attribute_metrics_collection.h> 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 6364e772f94..1c2406b2acf 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 @@ -5,6 +5,7 @@ #include "operationdonecontext.h" #include "removedonecontext.h" #include "putdonecontext.h" +#include <vespa/searchcore/proton/feedoperation/operations.h> #include <vespa/searchlib/common/isequencedtaskexecutor.h> using document::Document; @@ -71,7 +72,7 @@ FastAccessFeedView::FastAccessFeedView(const StoreOnlyFeedView::Context &storeOn _docIdLimit(ctx._docIdLimit) {} -FastAccessFeedView::~FastAccessFeedView() {} +FastAccessFeedView::~FastAccessFeedView() = default; void FastAccessFeedView::handleCompactLidSpace(const CompactLidSpaceOperation &op) diff --git a/searchcore/src/vespa/searchcore/proton/server/feedhandler.cpp b/searchcore/src/vespa/searchcore/proton/server/feedhandler.cpp index 66e721f9222..97cc25e635f 100644 --- a/searchcore/src/vespa/searchcore/proton/server/feedhandler.cpp +++ b/searchcore/src/vespa/searchcore/proton/server/feedhandler.cpp @@ -14,6 +14,7 @@ #include <vespa/searchcore/proton/bucketdb/ibucketdbhandler.h> #include <vespa/searchcore/proton/persistenceengine/i_resource_write_filter.h> #include <vespa/searchcore/proton/persistenceengine/transport_latch.h> +#include <vespa/searchcore/proton/feedoperation/operations.h> #include <vespa/searchcore/proton/common/eventlogger.h> #include <vespa/searchcorespi/index/ithreadingservice.h> #include <vespa/searchlib/common/gatecallback.h> @@ -522,7 +523,7 @@ FeedHandler::considerUpdateOperationForRejection(FeedToken &token, UpdateOperati */ if (_documentType != &update.getType()) { try { - op.deserializeUpdate(*_repo); + op.verifyUpdate(*_repo); } catch (document::FieldNotFoundException &e) { if (token) { auto message = make_string("Update operation rejected for document '%s' of type '%s': 'Field not found'", diff --git a/searchcore/src/vespa/searchcore/proton/server/feedstate.h b/searchcore/src/vespa/searchcore/proton/server/feedstate.h index 472f5cb224f..fa0a1702499 100644 --- a/searchcore/src/vespa/searchcore/proton/server/feedstate.h +++ b/searchcore/src/vespa/searchcore/proton/server/feedstate.h @@ -25,6 +25,7 @@ private: Type _type; protected: + using FeedOperationUP = std::unique_ptr<FeedOperation>; void throwExceptionInReceive(const vespalib::string &docType, uint64_t serialRangeFrom, uint64_t serialRangeTo, size_t packetSize); void throwExceptionInHandleOperation(const vespalib::string &docType, const FeedOperation &op); @@ -38,7 +39,7 @@ public: Type getType() const { return _type; } vespalib::string getName() const; - virtual void handleOperation(FeedToken token, std::unique_ptr<FeedOperation> op) = 0; + virtual void handleOperation(FeedToken token, FeedOperationUP op) = 0; virtual void receive(const PacketWrapper::SP &wrap, vespalib::Executor &executor) = 0; }; diff --git a/searchcore/src/vespa/searchcore/proton/server/feedstates.cpp b/searchcore/src/vespa/searchcore/proton/server/feedstates.cpp index f0866347f59..ae323bc93df 100644 --- a/searchcore/src/vespa/searchcore/proton/server/feedstates.cpp +++ b/searchcore/src/vespa/searchcore/proton/server/feedstates.cpp @@ -6,6 +6,7 @@ #include "ireplayconfig.h" #include "replaypacketdispatcher.h" #include <vespa/searchcore/proton/bucketdb/ibucketdbhandler.h> +#include <vespa/searchcore/proton/feedoperation/operations.h> #include <vespa/searchcore/proton/common/eventlogger.h> #include <vespa/searchlib/common/idestructorcallback.h> #include <vespa/vespalib/util/closuretask.h> diff --git a/searchcore/src/vespa/searchcore/proton/server/feedstates.h b/searchcore/src/vespa/searchcore/proton/server/feedstates.h index 963a78d0d6b..a9224669d87 100644 --- a/searchcore/src/vespa/searchcore/proton/server/feedstates.h +++ b/searchcore/src/vespa/searchcore/proton/server/feedstates.h @@ -28,16 +28,13 @@ public: { } - virtual void handleOperation(FeedToken, FeedOperation::UP op) override { + void handleOperation(FeedToken, FeedOperationUP op) override { throwExceptionInHandleOperation(_doc_type_name, *op); } - virtual void - receive(const PacketWrapper::SP &wrap, vespalib::Executor &) override { - throwExceptionInReceive(_doc_type_name.c_str(), - wrap->packet.range().from(), - wrap->packet.range().to(), - wrap->packet.size()); + void receive(const PacketWrapper::SP &wrap, vespalib::Executor &) override { + throwExceptionInReceive(_doc_type_name.c_str(), wrap->packet.range().from(), + wrap->packet.range().to(), wrap->packet.size()); } }; @@ -57,12 +54,11 @@ public: IReplayConfig &replay_config, FeedConfigStore &config_store); - virtual void handleOperation(FeedToken, FeedOperation::UP op) override { + void handleOperation(FeedToken, FeedOperationUP op) override { throwExceptionInHandleOperation(_doc_type_name, *op); } - virtual void receive(const PacketWrapper::SP &wrap, - vespalib::Executor &executor) override; + void receive(const PacketWrapper::SP &wrap, vespalib::Executor &executor) override; }; @@ -79,15 +75,13 @@ public: _handler(handler) { } - void handleOperation(FeedToken token, FeedOperation::UP op) override { + void handleOperation(FeedToken token, FeedOperationUP op) override { _handler.performOperation(std::move(token), std::move(op)); } void receive(const PacketWrapper::SP &wrap, vespalib::Executor &) override { - throwExceptionInReceive(_handler.getDocTypeName().c_str(), - wrap->packet.range().from(), - wrap->packet.range().to(), - wrap->packet.size()); + throwExceptionInReceive(_handler.getDocTypeName().c_str(), wrap->packet.range().from(), + wrap->packet.range().to(), wrap->packet.size()); } }; } // namespace proton diff --git a/searchcore/src/vespa/searchcore/proton/server/ireplaypackethandler.h b/searchcore/src/vespa/searchcore/proton/server/ireplaypackethandler.h index 210ece3a36a..e93821e2a36 100644 --- a/searchcore/src/vespa/searchcore/proton/server/ireplaypackethandler.h +++ b/searchcore/src/vespa/searchcore/proton/server/ireplaypackethandler.h @@ -2,10 +2,28 @@ #pragma once -#include <vespa/searchcore/proton/feedoperation/operations.h> +namespace document { class DocumentTypeRepo; } namespace proton { +class PutOperation; +class RemoveOperation; +class UpdateOperation; +class NoopOperation; +class NewConfigOperation; +class WipeHistoryOperation; +class DeleteBucketOperation; +class SplitBucketOperation; +class JoinBucketsOperation; +class PruneRemovedDocumentsOperation; +class SpoolerReplayStartOperation; +class SpoolerReplayCompleteOperation; +class MoveOperation; +class CreateBucketOperation; +class CompactLidSpaceOperation; + +namespace feedoperation { class IStreamHandler; } + /** * Interface used to handle the various feed operations during * replay of the transaction log. @@ -29,7 +47,7 @@ struct IReplayPacketHandler virtual void replay(const CreateBucketOperation &op) = 0; virtual void replay(const CompactLidSpaceOperation &op) = 0; - virtual NewConfigOperation::IStreamHandler &getNewConfigStreamHandler() = 0; + virtual feedoperation::IStreamHandler &getNewConfigStreamHandler() = 0; virtual const document::DocumentTypeRepo &getDeserializeRepo() = 0; }; diff --git a/searchcore/src/vespa/searchcore/proton/server/replaypacketdispatcher.cpp b/searchcore/src/vespa/searchcore/proton/server/replaypacketdispatcher.cpp index cdb42906fc2..42451f08315 100644 --- a/searchcore/src/vespa/searchcore/proton/server/replaypacketdispatcher.cpp +++ b/searchcore/src/vespa/searchcore/proton/server/replaypacketdispatcher.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 "replaypacketdispatcher.h" +#include <vespa/searchcore/proton/feedoperation/operations.h> #include <vespa/vespalib/util/exceptions.h> #include <vespa/document/util/serializableexceptions.h> diff --git a/searchcore/src/vespa/searchcore/proton/server/replaypacketdispatcher.h b/searchcore/src/vespa/searchcore/proton/server/replaypacketdispatcher.h index fc6f99471d8..771a79ddad9 100644 --- a/searchcore/src/vespa/searchcore/proton/server/replaypacketdispatcher.h +++ b/searchcore/src/vespa/searchcore/proton/server/replaypacketdispatcher.h @@ -7,6 +7,7 @@ namespace proton { +class FeedOperation; /** * Utility class that deserializes packet entries into feed operations * during replay from the transaction log and dispatches the feed operations @@ -22,14 +23,11 @@ private: void replay(OperationType &op, vespalib::nbostream &is, const Packet::Entry &entry); protected: - virtual void - store(const FeedOperation &op); + virtual void store(const FeedOperation &op); public: ReplayPacketDispatcher(IReplayPacketHandler &handler); - - virtual - ~ReplayPacketDispatcher(); + virtual ~ReplayPacketDispatcher(); void replayEntry(const Packet::Entry &entry); }; diff --git a/searchcore/src/vespa/searchcore/proton/server/storeonlyfeedview.cpp b/searchcore/src/vespa/searchcore/proton/server/storeonlyfeedview.cpp index 29615b0daf9..22ff1b90de4 100644 --- a/searchcore/src/vespa/searchcore/proton/server/storeonlyfeedview.cpp +++ b/searchcore/src/vespa/searchcore/proton/server/storeonlyfeedview.cpp @@ -13,6 +13,7 @@ #include <vespa/searchcore/proton/documentmetastore/ilidreusedelayer.h> #include <vespa/searchcore/proton/reference/i_gid_to_lid_change_handler.h> #include <vespa/searchcore/proton/attribute/ifieldupdatecallback.h> +#include <vespa/searchcore/proton/feedoperation/operations.h> #include <vespa/searchlib/common/isequencedtaskexecutor.h> #include <vespa/document/datatype/documenttype.h> diff --git a/searchcore/src/vespa/searchcore/proton/server/storeonlyfeedview.h b/searchcore/src/vespa/searchcore/proton/server/storeonlyfeedview.h index 825e14b4368..37f67399f4d 100644 --- a/searchcore/src/vespa/searchcore/proton/server/storeonlyfeedview.h +++ b/searchcore/src/vespa/searchcore/proton/server/storeonlyfeedview.h @@ -13,7 +13,7 @@ #include <vespa/searchcore/proton/common/feeddebugger.h> #include <vespa/searchcore/proton/documentmetastore/documentmetastore.h> #include <vespa/searchcore/proton/documentmetastore/documentmetastorecontext.h> -#include <vespa/searchcore/proton/feedoperation/feedoperation.h> +#include <vespa/searchcore/proton/feedoperation/lidvectorcontext.h> #include <vespa/searchcore/proton/persistenceengine/resulthandler.h> #include <vespa/searchcore/proton/reference/pending_notify_remove_done.h> #include <vespa/searchcorespi/index/ithreadingservice.h> @@ -23,7 +23,6 @@ namespace search { class IDestructorCallback; } -namespace document { class GLobalId; } namespace proton { @@ -35,6 +34,8 @@ class RemoveDoneContext; class CommitTimeTracker; class IGidToLidChangeHandler; class IFieldUpdateCallback; +class RemoveDocumentsOperation; +class DocumentOperation; namespace documentmetastore { class ILidReuseDelayer; } |