diff options
author | Henning Baldersheim <balder@yahoo-inc.com> | 2018-06-18 11:58:45 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-06-18 11:58:45 +0200 |
commit | 6e5bb3cda59f55f94ff7660a8ecd32e53221521e (patch) | |
tree | 1218621a6095c14d520be8fa8f9f3c644574b750 | |
parent | db7d99e291683c5a2b3f9d651f978199a8cf0f76 (diff) | |
parent | 041733a98ab70297a8ca256572efe0d803f9220c (diff) |
Merge pull request #6219 from vespa-engine/balder/use-single-precomputed-hashmap
Precompute and store attribute and executor id together in a single h…
15 files changed, 133 insertions, 112 deletions
diff --git a/searchcommon/src/vespa/searchcommon/attribute/iattributevector.h b/searchcommon/src/vespa/searchcommon/attribute/iattributevector.h index c7993503107..c432606f7f0 100644 --- a/searchcommon/src/vespa/searchcommon/attribute/iattributevector.h +++ b/searchcommon/src/vespa/searchcommon/attribute/iattributevector.h @@ -71,6 +71,11 @@ public: **/ virtual const vespalib::string & getName() const = 0; + vespalib::stringref getNamePrefix() const { + vespalib::stringref name = getName(); + return name.substr(0, name.find('.')); + } + /** * Returns the number of documents stored in this attribute vector. * 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/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/docsummary/docsummary.cpp b/searchcore/src/tests/proton/docsummary/docsummary.cpp index 7eae1c9d12d..b2bf768052b 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/vespa/searchcore/proton/attribute/attribute_writer.cpp b/searchcore/src/vespa/searchcore/proton/attribute/attribute_writer.cpp index bc49b300a1a..944882b1e98 100644 --- a/searchcore/src/vespa/searchcore/proton/attribute/attribute_writer.cpp +++ b/searchcore/src/vespa/searchcore/proton/attribute/attribute_writer.cpp @@ -4,16 +4,16 @@ #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> #include <vespa/log/log.h> LOG_SETUP(".proton.server.attributeadapter"); @@ -232,7 +232,7 @@ public: FieldContext::FieldContext(ISequencedTaskExecutor &writer, AttributeVector *attr) : _name(attr->getName()), - _executorId(writer.getExecutorId(_name)), + _executorId(writer.getExecutorId(attr->getNamePrefix())), _attr(attr) { } @@ -414,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()); @@ -471,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(); @@ -547,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()); @@ -557,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 @@ -574,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); }); } } @@ -603,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(); } @@ -616,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/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/searchlib/src/tests/attribute/attribute_test.cpp b/searchlib/src/tests/attribute/attribute_test.cpp index 9134711773c..b0aec782c64 100644 --- a/searchlib/src/tests/attribute/attribute_test.cpp +++ b/searchlib/src/tests/attribute/attribute_test.cpp @@ -32,8 +32,7 @@ using search::index::DummyFileHeaderContext; using search::attribute::BasicType; using search::attribute::IAttributeVector; -namespace -{ +namespace { vespalib::string empty; vespalib::string tmpDir("tmp"); @@ -2315,6 +2314,23 @@ AttributeTest::testPendingCompaction() populateSimple(iv, 1, 2); // should not trigger new compaction } +void testNamePrefix() { + Config cfg(BasicType::INT32, CollectionType::SINGLE); + AttributeVector::SP vFlat = createAttribute("sfsint32_pc", cfg); + AttributeVector::SP vS1 = createAttribute("sfsint32_pc.abc", cfg); + AttributeVector::SP vS2 = createAttribute("sfsint32_pc.xyz", cfg); + AttributeVector::SP vSS1 = createAttribute("sfsint32_pc.xyz.abc", cfg); + EXPECT_EQUAL("sfsint32_pc", vFlat->getName()); + EXPECT_EQUAL("sfsint32_pc", vFlat->getNamePrefix()); + EXPECT_EQUAL("sfsint32_pc.abc", vS1->getName()); + EXPECT_EQUAL("sfsint32_pc", vS1->getNamePrefix()); + EXPECT_EQUAL("sfsint32_pc.xyz", vS2->getName()); + EXPECT_EQUAL("sfsint32_pc", vS2->getNamePrefix()); + EXPECT_EQUAL("sfsint32_pc.xyz.abc", vSS1->getName()); + EXPECT_EQUAL("sfsint32_pc", vSS1->getNamePrefix()); + +} + void deleteDataDirs() { @@ -2361,6 +2377,7 @@ int AttributeTest::Main() TEST_DO(requireThatAddressSpaceUsageIsReported()); testReaderDuringLastUpdate(); TEST_DO(testPendingCompaction()); + TEST_DO(testNamePrefix()); deleteDataDirs(); TEST_DONE(); diff --git a/searchlib/src/tests/common/sequencedtaskexecutor/sequencedtaskexecutor_test.cpp b/searchlib/src/tests/common/sequencedtaskexecutor/sequencedtaskexecutor_test.cpp index 805a6d3b962..f8ab03d7710 100644 --- a/searchlib/src/tests/common/sequencedtaskexecutor/sequencedtaskexecutor_test.cpp +++ b/searchlib/src/tests/common/sequencedtaskexecutor/sequencedtaskexecutor_test.cpp @@ -122,8 +122,8 @@ TEST_F("require that task with same string component id are serialized", Fixture std::shared_ptr<TestObj> tv(std::make_shared<TestObj>()); EXPECT_EQUAL(0, tv->_val); auto test2 = [=]() { tv->modify(14, 42); }; - f._threads.execute("0", [=]() { usleep(2000); tv->modify(0, 14); }); - f._threads.execute("0", test2); + f._threads.execute(f._threads.getExecutorId("0"), [=]() { usleep(2000); tv->modify(0, 14); }); + f._threads.execute(f._threads.getExecutorId("0"), test2); tv->wait(2); EXPECT_EQUAL(0, tv->_fail); EXPECT_EQUAL(42, tv->_val); @@ -132,8 +132,7 @@ TEST_F("require that task with same string component id are serialized", Fixture EXPECT_EQUAL(42, tv->_val); } -namespace -{ +namespace { int detectSerializeFailure(Fixture &f, vespalib::stringref altComponentId, int tryLimit) { @@ -141,8 +140,8 @@ int detectSerializeFailure(Fixture &f, vespalib::stringref altComponentId, int t for (tryCnt = 0; tryCnt < tryLimit; ++tryCnt) { std::shared_ptr<TestObj> tv(std::make_shared<TestObj>()); EXPECT_EQUAL(0, tv->_val); - f._threads.execute("0", [=]() { usleep(2000); tv->modify(0, 14); }); - f._threads.execute(altComponentId, [=]() { tv->modify(14, 42); }); + f._threads.execute(f._threads.getExecutorId("0"), [=]() { usleep(2000); tv->modify(0, 14); }); + f._threads.execute(f._threads.getExecutorId(altComponentId), [=]() { tv->modify(14, 42); }); tv->wait(2); if (tv->_fail != 1) { continue; diff --git a/searchlib/src/vespa/searchlib/common/isequencedtaskexecutor.h b/searchlib/src/vespa/searchlib/common/isequencedtaskexecutor.h index 05347e790fb..a8b2a722c01 100644 --- a/searchlib/src/vespa/searchlib/common/isequencedtaskexecutor.h +++ b/searchlib/src/vespa/searchlib/common/isequencedtaskexecutor.h @@ -89,14 +89,14 @@ public: * call sync before tearing down pointed to/referenced data. * All tasks must be scheduled from same thread. * - * @param componentId component id - * @param function function to be wrapped in a task and later executed + * @param id executor id + * @param function function to be wrapped in a task and later executed */ template <class FunctionType> - void execute(vespalib::stringref componentId, FunctionType &&function) { - ExecutorId id = getExecutorId(componentId); + void execute(ExecutorId id, FunctionType &&function) { executeTask(id, vespalib::makeLambdaTask(std::forward<FunctionType>(function))); } + }; } // namespace search |