From 06aa676b5c1560354479df27e387a1d4c3d3e9e5 Mon Sep 17 00:00:00 2001 From: Tor Egge Date: Tue, 15 Aug 2017 19:18:28 +0000 Subject: Factor out ReferenceMappings from ReferenceAttribute. --- .../reference_attribute_test.cpp | 5 +- .../src/vespa/searchlib/attribute/CMakeLists.txt | 1 + .../src/vespa/searchlib/attribute/reference.h | 42 +++++++++++ .../searchlib/attribute/reference_attribute.cpp | 60 ++++------------ .../searchlib/attribute/reference_attribute.h | 52 ++------------ .../attribute/reference_attribute_saver.h | 2 +- .../searchlib/attribute/reference_mappings.cpp | 82 ++++++++++++++++++++++ .../vespa/searchlib/attribute/reference_mappings.h | 74 +++++++++++++++++++ 8 files changed, 222 insertions(+), 96 deletions(-) create mode 100644 searchlib/src/vespa/searchlib/attribute/reference.h create mode 100644 searchlib/src/vespa/searchlib/attribute/reference_mappings.cpp create mode 100644 searchlib/src/vespa/searchlib/attribute/reference_mappings.h (limited to 'searchlib') diff --git a/searchlib/src/tests/attribute/reference_attribute/reference_attribute_test.cpp b/searchlib/src/tests/attribute/reference_attribute/reference_attribute_test.cpp index a638309576a..7e2e8904170 100644 --- a/searchlib/src/tests/attribute/reference_attribute/reference_attribute_test.cpp +++ b/searchlib/src/tests/attribute/reference_attribute/reference_attribute_test.cpp @@ -15,6 +15,7 @@ LOG_SETUP("reference_attribute_test"); using search::MemoryUsage; using vespalib::ArrayRef; using generation_t = vespalib::GenerationHandler::generation_t; +using search::attribute::Reference; using search::attribute::ReferenceAttribute; using search::attribute::Config; using search::attribute::BasicType; @@ -99,7 +100,7 @@ struct Fixture } const GlobalId *get(uint32_t doc) { - const ReferenceAttribute::Reference *ref = _attr->getReference(doc); + const Reference *ref = _attr->getReference(doc); if (ref != nullptr) { return &ref->gid(); } else { @@ -107,7 +108,7 @@ struct Fixture } } - const ReferenceAttribute::Reference *getRef(uint32_t doc) { + const Reference *getRef(uint32_t doc) { return _attr->getReference(doc); } diff --git a/searchlib/src/vespa/searchlib/attribute/CMakeLists.txt b/searchlib/src/vespa/searchlib/attribute/CMakeLists.txt index 9308ae015b5..6838119ccd9 100644 --- a/searchlib/src/vespa/searchlib/attribute/CMakeLists.txt +++ b/searchlib/src/vespa/searchlib/attribute/CMakeLists.txt @@ -79,6 +79,7 @@ vespa_add_library(searchlib_attribute OBJECT readerbase.cpp reference_attribute.cpp reference_attribute_saver.cpp + reference_mappings.cpp singleenumattribute.cpp singleenumattributesaver.cpp singlenumericattribute.cpp diff --git a/searchlib/src/vespa/searchlib/attribute/reference.h b/searchlib/src/vespa/searchlib/attribute/reference.h new file mode 100644 index 00000000000..db8c94b4a11 --- /dev/null +++ b/searchlib/src/vespa/searchlib/attribute/reference.h @@ -0,0 +1,42 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#pragma once + +#include +#include + +namespace search::attribute { + +/* + * Class representing a single reference in a reference attribute. + */ +class Reference { + using EntryRef = search::datastore::EntryRef; + using GlobalId = document::GlobalId; + GlobalId _gid; + mutable uint32_t _lid; // referenced lid + mutable EntryRef _revMapIdx; // map from gid to lids referencing gid +public: + Reference() + : _gid(), + _lid(0u), + _revMapIdx() + { + } + Reference(const GlobalId &gid_) + : _gid(gid_), + _lid(0u), + _revMapIdx() + { + } + bool operator<(const Reference &rhs) const { + return _gid < rhs._gid; + } + const GlobalId &gid() const { return _gid; } + uint32_t lid() const { return _lid; } + EntryRef revMapIdx() const { return _revMapIdx; } + void setLid(uint32_t referencedLid) const { _lid = referencedLid; } + void setRevMapIdx(EntryRef newRevMapIdx) const { _revMapIdx = newRevMapIdx; } +}; + +} diff --git a/searchlib/src/vespa/searchlib/attribute/reference_attribute.cpp b/searchlib/src/vespa/searchlib/attribute/reference_attribute.cpp index 2798127e981..ee911c9a8cc 100644 --- a/searchlib/src/vespa/searchlib/attribute/reference_attribute.cpp +++ b/searchlib/src/vespa/searchlib/attribute/reference_attribute.cpp @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include @@ -37,8 +36,7 @@ ReferenceAttribute::ReferenceAttribute(const vespalib::stringref baseFileName, _indices(getGenerationHolder()), _cachedUniqueStoreMemoryUsage(), _gidToLidMapperFactory(), - _reverseMappingIndices(getGenerationHolder()), - _reverseMapping() + _referenceMappings(getGenerationHolder()) { setEnum(true); enableEnumeratedSave(true); @@ -46,16 +44,13 @@ ReferenceAttribute::ReferenceAttribute(const vespalib::stringref baseFileName, ReferenceAttribute::~ReferenceAttribute() { - _reverseMapping.clearBuilder(); + _referenceMappings.clearBuilder(); incGeneration(); // Force freeze const auto &store = _store; const auto saver = _store.getSaver(); saver.foreach_key([&store,this](EntryRef ref) { const Reference &entry = store.get(ref); - EntryRef revMapIdx = entry.revMapIdx(); - if (revMapIdx.valid()) { - _reverseMapping.clear(revMapIdx); - } + _referenceMappings.clearMapping(entry); }); incGeneration(); // Force freeze } @@ -82,47 +77,25 @@ ReferenceAttribute::addDoc(DocId &doc) return true; } -void -ReferenceAttribute::syncReverseMappingIndices(const Reference &entry) -{ - uint32_t referencedLid = entry.lid(); - if (referencedLid != 0u) { - _reverseMappingIndices.ensure_size(referencedLid + 1); - _reverseMappingIndices[referencedLid] = entry.revMapIdx(); - } -} - void ReferenceAttribute::removeReverseMapping(EntryRef oldRef, uint32_t lid) { const auto &entry = _store.get(oldRef); - EntryRef revMapIdx = entry.revMapIdx(); - _reverseMapping.apply(revMapIdx, nullptr, nullptr, &lid, &lid + 1); - std::atomic_thread_fence(std::memory_order_release); - entry.setRevMapIdx(revMapIdx); - syncReverseMappingIndices(entry); + _referenceMappings.removeReverseMapping(entry, lid); } void ReferenceAttribute::addReverseMapping(EntryRef newRef, uint32_t lid) { const auto &entry = _store.get(newRef); - EntryRef revMapIdx = entry.revMapIdx(); - ReverseMapping::KeyDataType add(lid, btree::BTreeNoLeafData()); - _reverseMapping.apply(revMapIdx, &add, &add + 1, nullptr, nullptr); - std::atomic_thread_fence(std::memory_order_release); - entry.setRevMapIdx(revMapIdx); - syncReverseMappingIndices(entry); + _referenceMappings.addReverseMapping(entry, lid); } void ReferenceAttribute::buildReverseMapping(EntryRef newRef, const std::vector &adds) { const auto &entry = _store.get(newRef); - EntryRef revMapIdx = entry.revMapIdx(); - assert(!revMapIdx.valid()); - _reverseMapping.apply(revMapIdx, &adds[0], &adds[adds.size()], nullptr, nullptr); - entry.setRevMapIdx(revMapIdx); + _referenceMappings.buildReverseMapping(entry, adds); } void @@ -174,7 +147,7 @@ ReferenceAttribute::clearDoc(DocId doc) void ReferenceAttribute::removeOldGenerations(generation_t firstUsed) { - _reverseMapping.trimHoldLists(firstUsed); + _referenceMappings.trimHoldLists(firstUsed); _store.trimHoldLists(firstUsed); getGenerationHolder().trimHoldLists(firstUsed); } @@ -182,9 +155,9 @@ ReferenceAttribute::removeOldGenerations(generation_t firstUsed) void ReferenceAttribute::onGenerationChange(generation_t generation) { - _reverseMapping.freeze(); + _referenceMappings.freeze(); _store.freeze(); - _reverseMapping.transferHoldLists(generation - 1); + _referenceMappings.transferHoldLists(generation - 1); _store.transferHoldLists(generation - 1); getGenerationHolder().transferHoldLists(generation - 1); } @@ -287,7 +260,7 @@ ReferenceAttribute::update(DocId doc, const GlobalId &gid) } } -const ReferenceAttribute::Reference * +const Reference * ReferenceAttribute::getReference(DocId doc) { assert(doc < _indices.size()); @@ -360,14 +333,7 @@ ReferenceAttribute::notifyGidToLidChange(const GlobalId &gid, DocId referencedLi EntryRef ref = _store.find(gid); if (ref.valid()) { const auto &entry = _store.get(ref); - uint32_t oldReferencedLid = entry.lid(); - if (oldReferencedLid != referencedLid) { - if (oldReferencedLid != 0u && oldReferencedLid < _reverseMappingIndices.size()) { - _reverseMappingIndices[oldReferencedLid] = EntryRef(); - } - entry.setLid(referencedLid); - } - syncReverseMappingIndices(entry); + _referenceMappings.notifyGidToLidChange(entry, referencedLid); commit(); } } @@ -383,7 +349,7 @@ ReferenceAttribute::populateReferencedLids() saver.foreach_key([&store,&mapper,this](EntryRef ref) { const Reference &entry = store.get(ref); entry.setLid(mapper.mapGidToLid(entry.gid())); - syncReverseMappingIndices(entry); }); + _referenceMappings.syncReverseMappingIndices(entry); }); } commit(); } @@ -419,7 +385,7 @@ IMPLEMENT_IDENTIFIABLE_ABSTRACT(ReferenceAttribute, AttributeVector); namespace datastore { -using Reference = attribute::ReferenceAttribute::Reference; +using Reference = attribute::Reference; template class UniqueStore>; template class UniqueStoreBuilder>; diff --git a/searchlib/src/vespa/searchlib/attribute/reference_attribute.h b/searchlib/src/vespa/searchlib/attribute/reference_attribute.h index 5647acfd163..a751213dc9a 100644 --- a/searchlib/src/vespa/searchlib/attribute/reference_attribute.h +++ b/searchlib/src/vespa/searchlib/attribute/reference_attribute.h @@ -3,10 +3,10 @@ #pragma once #include "not_implemented_attribute.h" -#include +#include "reference_mappings.h" +#include "reference.h" #include #include -#include "postingstore.h" namespace search { @@ -28,32 +28,6 @@ class ReferenceAttribute : public NotImplementedAttribute public: using EntryRef = search::datastore::EntryRef; using GlobalId = document::GlobalId; - class Reference { - GlobalId _gid; - mutable uint32_t _lid; // referenced lid - mutable EntryRef _revMapIdx; // map from gid to lids referencing gid - public: - Reference() - : _gid(), - _lid(0u), - _revMapIdx() - { - } - Reference(const GlobalId &gid_) - : _gid(gid_), - _lid(0u), - _revMapIdx() - { - } - bool operator<(const Reference &rhs) const { - return _gid < rhs._gid; - } - const GlobalId &gid() const { return _gid; } - uint32_t lid() const { return _lid; } - EntryRef revMapIdx() const { return _revMapIdx; } - void setLid(uint32_t referencedLid) const { _lid = referencedLid; } - void setRevMapIdx(EntryRef newRevMapIdx) const { _revMapIdx = newRevMapIdx; } - }; using ReferenceStore = datastore::UniqueStore; using ReferenceStoreIndices = RcuVectorBase; using IndicesCopyVector = vespalib::Array; @@ -68,12 +42,7 @@ private: ReferenceStoreIndices _indices; MemoryUsage _cachedUniqueStoreMemoryUsage; std::shared_ptr _gidToLidMapperFactory; - // Vector containing references to trees of lids referencing given - // referenced lid. - ReverseMappingIndices _reverseMappingIndices; - // Store of B-Trees, used to map from gid or referenced lid to - // referencing lids. - ReverseMapping _reverseMapping; + ReferenceMappings _referenceMappings; virtual void onAddDocs(DocId docIdLimit) override; virtual void removeOldGenerations(generation_t firstUsed) override; @@ -87,7 +56,6 @@ private: bool considerCompact(const CompactionStrategy &compactionStrategy); void compactWorst(); IndicesCopyVector getIndicesCopy(uint32_t size) const; - void syncReverseMappingIndices(const Reference &entry); void removeReverseMapping(EntryRef oldRef, uint32_t lid); void addReverseMapping(EntryRef newRef, uint32_t lid); void buildReverseMapping(EntryRef newRef, const std::vector &adds); @@ -113,18 +81,10 @@ public: template void - foreach_lid(uint32_t referencedLid, FunctionType &&func) const; -}; - -template -void -ReferenceAttribute::foreach_lid(uint32_t referencedLid, FunctionType &&func) const -{ - if (referencedLid < _reverseMappingIndices.size()) { - EntryRef revMapIdx = _reverseMappingIndices[referencedLid]; - _reverseMapping.foreach_frozen_key(revMapIdx, func); + foreach_lid(uint32_t referencedLid, FunctionType &&func) const { + _referenceMappings.foreach_lid(referencedLid, std::forward(func)); } -} +}; } } diff --git a/searchlib/src/vespa/searchlib/attribute/reference_attribute_saver.h b/searchlib/src/vespa/searchlib/attribute/reference_attribute_saver.h index d1ee5e0339a..7d85c60c3e6 100644 --- a/searchlib/src/vespa/searchlib/attribute/reference_attribute_saver.h +++ b/searchlib/src/vespa/searchlib/attribute/reference_attribute_saver.h @@ -8,6 +8,7 @@ #include #include #include "reference_attribute.h" +#include "reference.h" namespace search { namespace attribute { @@ -31,7 +32,6 @@ private: using GlobalId = document::GlobalId; using IndicesCopyVector = ReferenceAttribute::IndicesCopyVector; using Store = ReferenceAttribute::ReferenceStore; - using Reference = ReferenceAttribute::Reference; using Saver = Store::Saver; IndicesCopyVector _indices; const Store &_store; diff --git a/searchlib/src/vespa/searchlib/attribute/reference_mappings.cpp b/searchlib/src/vespa/searchlib/attribute/reference_mappings.cpp new file mode 100644 index 00000000000..67f02c50d88 --- /dev/null +++ b/searchlib/src/vespa/searchlib/attribute/reference_mappings.cpp @@ -0,0 +1,82 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#include "reference_mappings.h" +#include "reference.h" +#include +#include + +namespace search::attribute { + +ReferenceMappings::ReferenceMappings(GenerationHolder &genHolder) + : _reverseMappingIndices(genHolder), + _reverseMapping() +{ +} + +ReferenceMappings::~ReferenceMappings() +{ +} + +void +ReferenceMappings::clearMapping(const Reference &entry) +{ + EntryRef revMapIdx = entry.revMapIdx(); + if (revMapIdx.valid()) { + _reverseMapping.clear(revMapIdx); + } +} + +void +ReferenceMappings::syncReverseMappingIndices(const Reference &entry) +{ + uint32_t referencedLid = entry.lid(); + if (referencedLid != 0u) { + _reverseMappingIndices.ensure_size(referencedLid + 1); + _reverseMappingIndices[referencedLid] = entry.revMapIdx(); + } +} + +void +ReferenceMappings::removeReverseMapping(const Reference &entry, uint32_t lid) +{ + EntryRef revMapIdx = entry.revMapIdx(); + _reverseMapping.apply(revMapIdx, nullptr, nullptr, &lid, &lid + 1); + std::atomic_thread_fence(std::memory_order_release); + entry.setRevMapIdx(revMapIdx); + syncReverseMappingIndices(entry); +} + +void +ReferenceMappings::addReverseMapping(const Reference &entry, uint32_t lid) +{ + EntryRef revMapIdx = entry.revMapIdx(); + ReverseMapping::KeyDataType add(lid, btree::BTreeNoLeafData()); + _reverseMapping.apply(revMapIdx, &add, &add + 1, nullptr, nullptr); + std::atomic_thread_fence(std::memory_order_release); + entry.setRevMapIdx(revMapIdx); + syncReverseMappingIndices(entry); +} + +void +ReferenceMappings::buildReverseMapping(const Reference &entry, const std::vector &adds) +{ + EntryRef revMapIdx = entry.revMapIdx(); + assert(!revMapIdx.valid()); + _reverseMapping.apply(revMapIdx, &adds[0], &adds[adds.size()], nullptr, nullptr); + entry.setRevMapIdx(revMapIdx); +} + +void +ReferenceMappings::notifyGidToLidChange(const Reference &entry, uint32_t referencedLid) +{ + uint32_t oldReferencedLid = entry.lid(); + if (oldReferencedLid != referencedLid) { + if (oldReferencedLid != 0u && oldReferencedLid < _reverseMappingIndices.size()) { + _reverseMappingIndices[oldReferencedLid] = EntryRef(); + } + entry.setLid(referencedLid); + } + syncReverseMappingIndices(entry); +} + +} diff --git a/searchlib/src/vespa/searchlib/attribute/reference_mappings.h b/searchlib/src/vespa/searchlib/attribute/reference_mappings.h new file mode 100644 index 00000000000..129ccbbea25 --- /dev/null +++ b/searchlib/src/vespa/searchlib/attribute/reference_mappings.h @@ -0,0 +1,74 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#pragma once + +#include +#include + +namespace search::attribute { + +class Reference; + +/* + * Class representing mappings in a reference attribute. + */ +class ReferenceMappings +{ + using GenerationHolder = vespalib::GenerationHolder; + using EntryRef = search::datastore::EntryRef; + using ReverseMappingIndices = RcuVectorBase; + using ReverseMapping = btree::BTreeStore, + btree::BTreeDefaultTraits, + btree::NoAggrCalc>; + using generation_t = vespalib::GenerationHandler::generation_t; + + // Vector containing references to trees of lids referencing given + // referenced lid. + ReverseMappingIndices _reverseMappingIndices; + // Store of B-Trees, used to map from gid or referenced lid to + // referencing lids. + ReverseMapping _reverseMapping; + + +public: + ReferenceMappings(GenerationHolder &genHolder); + + ~ReferenceMappings(); + + // Cleanup helpers, to free resources + void clearBuilder() { _reverseMapping.clearBuilder(); } + void clearMapping(const Reference &entry); + + // Hold list management & freezing + void trimHoldLists(generation_t usedGen) { _reverseMapping.trimHoldLists(usedGen); } + void freeze() { _reverseMapping.freeze(); } + void transferHoldLists(generation_t generation) { _reverseMapping.transferHoldLists(generation); } + + // Handle mapping changes + void notifyGidToLidChange(const Reference &entry, uint32_t referencedLid); + void syncReverseMappingIndices(const Reference &entry); + void removeReverseMapping(const Reference &entry, uint32_t lid); + void addReverseMapping(const Reference &entry, uint32_t lid); + + // Setup mapping after load + void buildReverseMapping(const Reference &entry, const std::vector &adds); + + // Reader API, reader must hold generation guard + template + void + foreach_lid(uint32_t referencedLid, FunctionType &&func) const; +}; + +template +void +ReferenceMappings::foreach_lid(uint32_t referencedLid, FunctionType &&func) const +{ + if (referencedLid < _reverseMappingIndices.size()) { + EntryRef revMapIdx = _reverseMappingIndices[referencedLid]; + _reverseMapping.foreach_frozen_key(revMapIdx, std::forward(func)); + } +} + +} -- cgit v1.2.3