Everett
Loading...
Searching...
No Matches
native_sweep.h
Go to the documentation of this file.
1
12#pragma once
13
14#include <everett/cola_index.h>
15#include <algorithm>
16#include <memory>
17#include <optional>
18#include <vector>
19#include <unordered_map>
20
21namespace everett {
22 // Optional initialization instrumentation. Seeding bounds framing headers;
23 // it excludes selector dictionary parsing and reconstructed key bytes.
28}
30 // Runs are oldest first. Equal keys leave the heap in that same order.
31 // Each cursor retains its current decoded key and parsed physical frame.
32 template <class World> struct native_sweep {
33 using policy_type = typename World::policy_type;
34 using native_type = typename World::runtime_family::native_type;
35 struct observation { bit_view value; std::uint64_t retained_bits; };
36 native_sweep() = default;
37 explicit native_sweep(World const & snapshot, bit_view lower = {}, range_positioning_work * work = nullptr) {
38 if (work) *work = {};
39 using P = typename World::policy_type;
40 std::unordered_map<native_type const *, std::uint64_t> starts;
41 auto node = snapshot.runtime().query_root().head();
42 auto context = profile_query_context<P>(lower);
43 std::uint64_t group = 0;
44 bool above = false;
45 while (node) {
46 if (work) ++work->catalogs;
47 auto view = node->view();
49 if (!above && view.virtual_size()) found = view.lower_bound_window(group, context, work ? &work->comparisons : nullptr);
50 starts.emplace(node->native_owner().get(), found.native_ordinal);
51 if (auto side = node->secondary_target()) {
52 if (work) ++work->catalogs;
53 std::uint64_t ordinal = 0;
54 if (auto const & predecessor = found.predecessors[1]) {
55 auto leaf = side->view();
56 auto first = predecessor->target_ordinal;
57 if (first >= leaf.size() || first % P::group_size)
58 throw std::invalid_argument("invalid range secondary route");
59 auto last = first + std::min<std::uint64_t>(P::group_size, leaf.size() - first);
60 ordinal = last;
61 leaf.compare_window(first, last, predecessor->comparison, [&](profile_comparison_item<P> item) {
62 if (item.comparison.order() < 0) return true;
63 ordinal = item.ordinal; return false;
64 }, work ? &work->comparisons : nullptr);
65 }
66 starts.emplace(side.get(), ordinal);
67 }
68 auto main = node->main_target();
69 if (auto const & predecessor = found.predecessors[0]) {
70 if (!main || predecessor->target_ordinal % P::group_size || predecessor->target_ordinal >= main->virtual_size())
71 throw std::invalid_argument("invalid range main route");
72 group = predecessor->target_ordinal / P::group_size;
73 context = predecessor->comparison;
74 } else above = true; // No sampled predecessor: all downstream keys exceed lower.
75 node = std::move(main);
76 }
77 if constexpr (requires { snapshot.runtime().runs(); }) {
78 auto runs = snapshot.runtime().runs();
79 sources_.reserve(runs.size()); heap_.reserve(runs.size());
80 for (auto const & run : runs) {
81 auto native = [&] {
82 if constexpr (requires { run.native_owner(); }) return run.native_owner();
83 else return run->native;
84 }();
85 auto position = starts.find(native.get());
86 if (position == starts.end()) throw std::invalid_argument("native run absent from range cascade");
87 if (work && position->second < native->view().size())
88 work->seeded_headers += position->second % P::codec_block_size + 1;
89 sources_.emplace_back(std::move(native), position->second, lower);
90 if (!sources_.back().cursor.done()) heap_.push_back(sources_.size() - 1);
91 }
92 std::make_heap(heap_.begin(), heap_.end(), later());
93 } else throw std::logic_error("runtime does not expose a native sweep");
94 }
95 bool done() const noexcept { return heap_.empty(); }
96 std::uint64_t consumed() const noexcept { return consumed_; }
97 auto peek() const { return sources_[heap_.front()].cursor.peek(); }
98 std::uint64_t retained_bits() const {
99 auto const & cursor = sources_[heap_.front()].cursor;
100 if constexpr (requires { cursor.retained_bits(); }) return cursor.retained_bits();
101 else return 0; // A custom cursor can conservatively emit the entire key.
102 }
103 void consume() {
104 std::pop_heap(heap_.begin(), heap_.end(), later());
105 auto which = heap_.back(); heap_.pop_back();
106 auto comparison = sources_[which].cursor.advance_comparison();
107 if (comparison && comparison->order >= 0)
108 throw std::invalid_argument("scanned native keys are not unique and sorted");
109 ++consumed_;
110 if (!sources_[which].cursor.done()) {
111 heap_.push_back(which); std::push_heap(heap_.begin(), heap_.end(), later());
112 }
113 }
114 // Queries must be increasing. Values borrow pinned immutable natives.
115 std::optional<observation> replacement(bit_view key) {
116 while (!done() && compare_bits<typename policy_type::architecture>(peek().key.prefix, key) < 0) consume();
117 std::optional<observation> result;
118 while (!done() && compare_bits<typename policy_type::architecture>(peek().key.prefix, key) == 0) {
119 result = observation{peek().value, retained_bits()};
120 consume();
121 }
122 return result;
123 }
124 private:
125 struct source {
126 std::shared_ptr<native_type const> native;
127 decltype(std::declval<native_type const &>().view().cursor()) cursor;
128 source(std::shared_ptr<native_type const> value, std::uint64_t ordinal, bit_view query)
129 : native(std::move(value)), cursor(native->view(), ordinal, query) {}
130 };
131 std::vector<source> sources_;
132 std::vector<std::size_t> heap_;
133 std::uint64_t consumed_ = 0;
134 auto later() const {
135 return [this](std::size_t a, std::size_t b) {
136 auto order = compare_bits<typename policy_type::architecture>(sources_[a].cursor.peek().key.prefix, sources_[b].cursor.peek().key.prefix);
137 return order ? order > 0 : a > b;
138 };
139 }
140 };
141}
Declares dual-target main/secondary fractional indexes for COLA.
std::uint32_t run(simd::neon, std::span< std::byte const >, std::uint32_t) noexcept
Definition native_sweep.h:29
bit_string value(arrow_t< S > const &value)
Definition typed_world.h:99
bit_string key(key_t< S > const &value)
Definition typed_world.h:89
Definition active_engine.h:18
Definition profile.h:56
Definition cola_index.h:94
std::array< std::optional< profile_blob_borrowed_predecessor< P > >, 2 > predecessors
Definition cola_index.h:96
std::uint64_t native_ordinal
Definition cola_index.h:95
Definition profile.h:458
Definition profile.h:452
Definition profile.h:328
Definition native_sweep.h:24
std::uint64_t seeded_headers
Definition native_sweep.h:25
std::uint64_t catalogs
Definition native_sweep.h:25
profile_comparison_work comparisons
Definition native_sweep.h:26
std::uint64_t retained_bits
Definition native_sweep.h:35
bit_view value
Definition native_sweep.h:35
Definition native_sweep.h:125
decltype(std::declval< native_type const & >().view().cursor()) cursor
Definition native_sweep.h:127
std::shared_ptr< native_type const > native
Definition native_sweep.h:126
source(std::shared_ptr< native_type const > value, std::uint64_t ordinal, bit_view query)
Definition native_sweep.h:128
Definition native_sweep.h:32
std::optional< observation > replacement(bit_view key)
Definition native_sweep.h:115
typename World::runtime_family::native_type native_type
Definition native_sweep.h:34
auto peek() const
Definition native_sweep.h:97
std::uint64_t consumed_
Definition native_sweep.h:133
std::uint64_t retained_bits() const
Definition native_sweep.h:98
bool done() const noexcept
Definition native_sweep.h:95
native_sweep(World const &snapshot, bit_view lower={}, range_positioning_work *work=nullptr)
Definition native_sweep.h:37
std::vector< source > sources_
Definition native_sweep.h:131
auto later() const
Definition native_sweep.h:134
std::uint64_t consumed() const noexcept
Definition native_sweep.h:96
std::vector< std::size_t > heap_
Definition native_sweep.h:132
typename World::policy_type policy_type
Definition native_sweep.h:33
void consume()
Definition native_sweep.h:103