diff options
author | Tor Egge <Tor.Egge@online.no> | 2024-02-15 13:21:11 +0100 |
---|---|---|
committer | Tor Egge <Tor.Egge@online.no> | 2024-02-15 13:21:11 +0100 |
commit | fe310e5cdfe5e51abddda0a8ed6ef100ae11ccfb (patch) | |
tree | 602cef16199c5c63eedc36cdde3829188fa57185 | |
parent | fe7cfe2a7c6c549acedd217f73fa4fc6340c81eb (diff) |
Prepare SimpleIndexSaver for index flush thread.
3 files changed, 51 insertions, 14 deletions
diff --git a/searchlib/src/vespa/searchlib/predicate/simple_index.hpp b/searchlib/src/vespa/searchlib/predicate/simple_index.hpp index 5c5afedfe90..5d2380b523d 100644 --- a/searchlib/src/vespa/searchlib/predicate/simple_index.hpp +++ b/searchlib/src/vespa/searchlib/predicate/simple_index.hpp @@ -108,18 +108,18 @@ SimpleIndex<Posting, Key, DocId>::deserialize(vespalib::DataBuffer &buffer, Post template <typename Posting, typename Key, typename DocId> void SimpleIndex<Posting, Key, DocId>::addPosting(Key key, DocId doc_id, const Posting &posting) { - auto iter = _dictionary.find(key); + auto iter = _dictionary.lowerBound(key); vespalib::datastore::EntryRef ref; - if (iter.valid()) { + if (iter.valid() && key == iter.getKey()) { ref = iter.getData(); insertIntoPosting(ref, key, doc_id, posting); if (ref != iter.getData()) { - std::atomic_thread_fence(std::memory_order_release); + _dictionary.thaw(iter); iter.writeData(ref); } } else { insertIntoPosting(ref, key, doc_id, posting); - _dictionary.insert(key, ref); + _dictionary.insert(iter, key, ref); } } @@ -147,9 +147,9 @@ SimpleIndex<Posting, Key, DocId>::removeFromPostingList(Key key, DocId doc_id) { _btree_posting_lists.remove(ref, doc_id); removeFromVectorPostingList(ref, key, doc_id); if (!ref.valid()) { // last posting was removed - _dictionary.remove(key); + _dictionary.remove(dict_it); } else if (ref != original_ref) { // ref changed. update dictionary. - std::atomic_thread_fence(std::memory_order_release); + _dictionary.thaw(dict_it); dict_it.writeData(ref); } return std::make_pair(posting, true); @@ -304,7 +304,7 @@ template <typename Posting, typename Key, typename DocId> std::unique_ptr<ISaver> SimpleIndex<Posting, Key, DocId>::make_saver(std::unique_ptr<PostingSaver<Posting>> subsaver) const { - return std::make_unique<SimpleIndexSaver<Posting, Key, DocId>>(_dictionary, _btree_posting_lists, std::move(subsaver)); + return std::make_unique<SimpleIndexSaver<Posting, Key, DocId>>(_dictionary.getFrozenView(), _btree_posting_lists, std::move(subsaver)); } } diff --git a/searchlib/src/vespa/searchlib/predicate/simple_index_saver.h b/searchlib/src/vespa/searchlib/predicate/simple_index_saver.h index eefaf7c79f4..53357187d54 100644 --- a/searchlib/src/vespa/searchlib/predicate/simple_index_saver.h +++ b/searchlib/src/vespa/searchlib/predicate/simple_index_saver.h @@ -4,6 +4,7 @@ #include "i_saver.h" #include "simple_index.h" +#include <vespa/vespalib/stllike/allocator.h> namespace search::predicate { @@ -15,15 +16,20 @@ template <typename Posting, typename Key = uint64_t, typename DocId = uint32_t> class SimpleIndexSaver : public ISaver { + using EntryRef = vespalib::datastore::EntryRef; using Source = SimpleIndex<Posting,Key,DocId>; - using Dictionary = Source::Dictionary; + using Dictionary = Source::Dictionary::FrozenView; + using FrozenRoots = std::vector<EntryRef, vespalib::allocator_large<EntryRef>>; using BTreeStore = Source::BTreeStore; - const Dictionary& _dictionary; + const Dictionary _dictionary; + FrozenRoots _frozen_roots; const BTreeStore& _btree_posting_lists; std::unique_ptr<PostingSaver<Posting>> _subsaver; + + void make_frozen_roots(); public: - SimpleIndexSaver(const Dictionary& dictionary, const BTreeStore& btree_posting_lists, std::unique_ptr<PostingSaver<Posting>> _subsaver); + SimpleIndexSaver(Dictionary dictionary, const BTreeStore& btree_posting_lists, std::unique_ptr<PostingSaver<Posting>> _subsaver); ~SimpleIndexSaver() override; void save(BufferWriter& writer) const override; }; diff --git a/searchlib/src/vespa/searchlib/predicate/simple_index_saver.hpp b/searchlib/src/vespa/searchlib/predicate/simple_index_saver.hpp index a3db21ca6cb..327d5440346 100644 --- a/searchlib/src/vespa/searchlib/predicate/simple_index_saver.hpp +++ b/searchlib/src/vespa/searchlib/predicate/simple_index_saver.hpp @@ -6,11 +6,13 @@ namespace search::predicate { template <typename Posting, typename Key, typename DocId> -SimpleIndexSaver<Posting, Key, DocId>::SimpleIndexSaver(const Dictionary& dictionary, const BTreeStore& btree_posting_lists, std::unique_ptr<PostingSaver<Posting>> subsaver) - : _dictionary(dictionary), +SimpleIndexSaver<Posting, Key, DocId>::SimpleIndexSaver(Dictionary dictionary, const BTreeStore& btree_posting_lists, std::unique_ptr<PostingSaver<Posting>> subsaver) + : _dictionary(std::move(dictionary)), + _frozen_roots(), _btree_posting_lists(btree_posting_lists), _subsaver(std::move(subsaver)) { + make_frozen_roots(); } template <typename Posting, typename Key, typename DocId> @@ -23,9 +25,16 @@ SimpleIndexSaver<Posting, Key, DocId>::save(BufferWriter& writer) const assert(sizeof(Key) <= sizeof(uint64_t)); assert(sizeof(DocId) <= sizeof(uint32_t)); nbo_write<uint32_t>(writer, _dictionary.size()); - for (auto it = _dictionary.begin(); it.valid(); ++it) { + auto& allocator = _btree_posting_lists.getAllocator(); + auto frozen_roots_it = _frozen_roots.begin(); + using PostingIterator = BTreeStore::ConstIterator; + for (auto it = _dictionary.begin(); it.valid(); ++it, ++frozen_roots_it) { vespalib::datastore::EntryRef ref = it.getData(); - auto posting_it = _btree_posting_lists.begin(ref); + /* + * Use copy of frozen root if valid, otherwise use ref from + * frozen dictionary. + */ + auto posting_it = frozen_roots_it->valid() ? PostingIterator(*frozen_roots_it, allocator) : _btree_posting_lists.begin(ref); nbo_write<uint32_t>(writer, posting_it.size()); // 0 if !valid() if (!posting_it.valid()) continue; @@ -35,6 +44,28 @@ SimpleIndexSaver<Posting, Key, DocId>::save(BufferWriter& writer) const _subsaver->save(posting_it.getData(), writer); } } + assert(frozen_roots_it == _frozen_roots.end()); +} + +template <typename Posting, typename Key, typename DocId> +void +SimpleIndexSaver<Posting, Key, DocId>::make_frozen_roots() +{ + /* + * Compensate for lacking snapshot property in + * vespalib::btree::BTreeStore. Traverse frozen dictionary in writer + * thread and make a copy of frozen btree roots. + */ + _frozen_roots.reserve(_dictionary.size()); + for (auto it = _dictionary.begin(); it.valid(); ++it) { + auto ref = it.getData(); + if (ref.valid() && _btree_posting_lists.isBTree(ref)) { + _frozen_roots.emplace_back(_btree_posting_lists.getTreeEntry(ref)->getFrozenRootRelaxed()); + assert(_frozen_roots.back().valid()); + } else { + _frozen_roots.emplace_back(); + } + } } } |