22 template <
class P,
class Ids,
class Ops,
class Family>
struct graph_sealer {
29 using mapped_type = std::remove_const_t<typename mapped_pointer::element_type>;
42 std::span<native_pointer const> natives) {
43 constexpr std::size_t limit = 16;
44 std::vector<pair_type> unbound;
45 std::unordered_set<node_type const *> seen;
46 std::unordered_set<native_type const *> paired;
47 auto visit = [&](
auto && self,
pair_type const & pair) ->
void {
48 if (!pair || !seen.insert(pair.get()).second ||
50 if (!pair->built())
return;
51 paired.insert(pair->native_owner().get());
52 self(self, pair->main_target());
53 unbound.push_back(pair);
55 for (
auto const & pair : roots) visit(visit, pair);
57 std::vector<ready_unit> units;
59 std::unordered_set<native_type const *> selected;
60 for (
auto const & pair : unbound) {
61 if (units.size() == limit)
break;
64 if ((pair->main_target() && !
main) || (pair->secondary_target() && !
secondary))
continue;
65 auto const & owner = pair->native_owner();
68 if (!
native && (!
batch_owned(owner) || !selected.insert(owner.get()).second))
continue;
73 auto & unit = units.back();
77 for (
auto const &
native : natives) {
78 if (units.size() == limit)
break;
82 !selected.insert(
native.get()).second ||
87 if (units.size() < 2)
return 0;
89 std::vector<ready_unit *> claimed;
90 claimed.reserve(units.size());
91 for (
auto & unit : units) {
92 if (unit.pair_claim) {
93 if (!unit.pair_claim->try_lock())
continue;
94 if (unit.pair_claim->value()) { unit.pair_claim->release();
continue; }
96 if (unit.native_claim) {
97 if (!unit.native_claim->try_lock()) {
98 if (unit.pair_claim) unit.pair_claim->release();
101 if (unit.native_claim->value()) {
102 unit.native_claim->release();
103 if (unit.pair_claim) unit.pair_claim->release();
107 claimed.push_back(&unit);
109 if (claimed.size() < 2)
return 0;
111 std::vector<catalog_object_reservation> outputs;
112 std::vector<blob_identity> inputs;
113 outputs.reserve(claimed.size() * 2);
114 for (
auto * unit : claimed) {
116 unit->native_id = unit->native->receipt.object;
118 unit->native_id =
ids_();
122 unit->index_id =
ids_();
125 if (unit->main) inputs.push_back(unit->main->identity);
127 std::sort(inputs.begin(), inputs.end(), [](
auto const & a,
auto const & b) {
128 return a.native.hex() < b.native.hex() || (a.native == b.native && a.index.hex() < b.index.hex());
130 inputs.erase(std::unique(inputs.begin(), inputs.end()), inputs.end());
131 auto attempt =
reserve(outputs, inputs);
132 for (
auto * unit : claimed)
finish_ready(*unit, attempt);
133 return claimed.size();
137 if (!
native)
throw std::invalid_argument(
"null runtime native owner");
139 return produce_native(native);
148 if (!pair)
throw std::invalid_argument(
"null runtime pair owner");
150 if (!pair->built()) throw std::invalid_argument(
"mapped pair has no binding in this catalog");
153 auto main = pair->main_target() ? ensure_pair(pair->main_target()) : nullptr;
154 auto secondary = pair->secondary_target() ? ensure_native(pair->secondary_target()) : nullptr;
155 auto const & owner = pair->native_owner();
156 if (!owner) throw std::invalid_argument(
"null runtime native owner");
157 std::optional<pair_seal> fused;
158 std::shared_ptr<typename mapped_type::index_type const> fused_index;
159 auto native = owner->bindings_.get_or_create(catalog_.identity(), catalog_.root(), [&] {
160 if constexpr (requires { owner->sealed(); })
161 if (owner->sealed()) return produce_native(owner);
162 if (!owner->owned()) return produce_native(owner);
163 blob_identity id{ids_(), ids_()};
164 std::array outputs{catalog_object_reservation{id.native, file_kind::native_blob},
165 catalog_object_reservation{id.index, file_kind::fractional_index}};
166 std::array<blob_identity, 1> input{main ? main->identity : id};
167 auto attempt = reserve(outputs, std::span<blob_identity const>(input.data(), main ? 1 : 0));
168 auto native_receipt = encode_native(owner).seal(catalog_.root(), id.native, attempt);
169 auto encoded = encode_cola_sections(*pair->built(), id.native,
170 main ? std::optional<blob_identity>(main->identity) : std::nullopt,
171 secondary ? std::optional<object_id>(secondary->receipt.object) : std::nullopt);
172 auto index_receipt = encoded.seal(catalog_.root(), id.index, attempt);
173 auto [mapped_native, index] = catalog_.template seal_native_pair<mapped_type>(
174 operation(), id, native_receipt, index_receipt);
175 auto binding = std::make_shared<native_binding_type const>(
176 native_seal{catalog_.identity(), std::move(native_receipt)}, std::move(mapped_native));
177 fused.emplace(pair_seal{catalog_.identity(), id, std::move(index_receipt)});
178 fused_index = std::move(index);
183 auto mapped = mapped_type::bind(fused->identity,
native->mapped, std::move(fused_index),
186 return std::make_shared<pair_binding_type const>(std::move(*fused), std::move(mapped));
189 std::array<blob_identity, 1> input{
main ?
main->identity :
id};
191 std::span<blob_identity const>(input.data(),
main ? 1 : 0));
193 main ? std::optional<blob_identity>(
main->identity) : std::nullopt,
195 auto receipt = encoded.seal(
catalog_.
root(),
id.index, attempt);
197 auto mapped = mapped_type::bind(
id,
native->mapped, std::move(index),
200 return std::make_shared<pair_binding_type const>(
211 auto result =
native->bindings_.get_or_create(catalog_.identity(), catalog_.root(), [&] {
212 return std::make_shared<native_binding_type const>(native_seal{
213 catalog_.identity(), catalog_.sealed_receipt(id, file_kind::native_blob)},
native->mapped());
215 if (result->receipt.object !=
id)
throw std::invalid_argument(
"native owner has another catalog identity");
218 auto result = pair->bindings_.get_or_create(catalog_.identity(), catalog_.root(), [&] {
219 return std::make_shared<pair_binding_type const>(pair_seal{
220 catalog_.identity(), id, catalog_.sealed_receipt(id.index, file_kind::fractional_index)}, pair->mapped());
222 if (result->identity !=
id)
throw std::invalid_argument(
"pair owner has another catalog identity");
225 auto value =
native->bindings_.find(catalog_.identity(), catalog_.root());
226 if (!value)
throw std::logic_error(
"runtime native has not been sealed");
227 return value->receipt.object;
230 auto value = pair->bindings_.find(catalog_.identity(), catalog_.root());
231 if (!value)
throw std::logic_error(
"runtime pair has not been sealed");
232 return value->identity;
236 auto binding =
native->bindings_.find(catalog_.identity(), catalog_.root());
237 if (!binding)
throw std::logic_error(
"runtime native has not been sealed");
241 return native->mapped_owners_.get_or_create(catalog_.identity(), catalog_.root(), [&] {
242 auto result = native_type::from_mapped(binding->mapped);
243 result->bindings_.get_or_create(catalog_.identity(), catalog_.root(), [&] { return binding; });
248 auto binding = pair->bindings_.find(catalog_.identity(), catalog_.root());
249 if (!binding)
throw std::logic_error(
"runtime pair has not been sealed");
250 if (pair->canonical_mapped() && pair->mapped() == binding->mapped)
return pair;
251 return pair->mapped_owners_.get_or_create(catalog_.identity(), catalog_.root(), [&] {
252 auto result = node_type::from_mapped_parts(binding->mapped, mapped_native(pair->native_owner()),
253 pair->main_target() ? mapped_pair(pair->main_target()) : nullptr,
254 pair->secondary_target() ? mapped_native(pair->secondary_target()) : nullptr);
255 result->bindings_.get_or_create(catalog_.identity(), catalog_.root(), [&] { return binding; });
266 std::shared_ptr<pair_binding_type const>
main;
272 std::shared_ptr<native_binding_type const> s = {}, std::shared_ptr<native_binding_type const> value = {})
273 : pair(std::move(p)), owner(std::move(n)),
main(std::move(m)),
secondary(std::move(s)),
native(std::move(value)) {}
276 if constexpr (
requires {
native->sealed(); })
if (
native->sealed())
return false;
277 return bool(
native->owned());
280 std::optional<object_seal_receipt> native_receipt;
281 if (!unit.
native) native_receipt.emplace(encode_native(unit.
owner).seal(catalog_.root(), *unit.
native_id, attempt));
283 catalog_.record_sealed(operation(), *native_receipt);
284 auto mapped = std::make_shared<mapped_native_type const>(mapped_native_type::open(native_receipt->path));
285 auto binding = std::make_shared<native_binding_type const>(
286 native_seal{catalog_.identity(), std::move(*native_receipt)}, std::move(mapped));
292 unit.
main ? std::optional<blob_identity>(unit.
main->identity) : std::nullopt,
293 unit.
secondary ? std::optional<object_id>(unit.
secondary->receipt.object) : std::nullopt);
294 auto receipt = encoded.seal(catalog_.root(),
id.index, attempt);
295 std::shared_ptr<typename mapped_type::index_type const> index;
296 if (native_receipt) {
297 auto [
mapped_native, prepared_index] = catalog_.template seal_native_pair<mapped_type>(
298 operation(),
id, *native_receipt, receipt);
299 unit.
native = std::make_shared<native_binding_type const>(
302 index = std::move(prepared_index);
303 }
else index = catalog_.template seal_pair<mapped_type>(operation(),
id, receipt);
304 auto mapped = mapped_type::bind(
id, unit.
native->mapped, std::move(index),
306 unit.
secondary ? std::optional<object_id>(unit.
secondary->receipt.object) : std::nullopt);
307 auto binding = std::make_shared<pair_binding_type const>(
315 auto id = ids_().hex();
316 if (last_operation_) *last_operation_ = id;
320 if constexpr (
requires {
typename Family::storage_type; })
321 return Family::storage_type::encode_native(*
native->owned());
325 if constexpr (
requires {
native->sealed(); }) {
326 if (
auto sealed =
native->sealed()) {
327 if (sealed->catalog != catalog_.
identity())
328 throw std::invalid_argument(
"native seal belongs to another catalog");
329 catalog_.
verify_sealed(sealed->receipt, file_kind::native_blob);
330 return std::make_shared<native_binding_type const>(*sealed,
native->mapped());
333 if (!
native->owned())
throw std::invalid_argument(
"mapped native has no binding in this catalog");
335 auto attempt = reserve(
id, file_kind::native_blob);
336 auto receipt = encode_native(
native).seal(catalog_.
root(),
id, attempt);
338 auto mapped = std::make_shared<mapped_native_type const>(mapped_native_type::open(receipt.path));
339 return std::make_shared<native_binding_type const>(
343 std::array<catalog_object_reservation, 1> outputs{{{id, kind}}};
344 return reserve(outputs, inputs);
347 std::span<blob_identity const> inputs = {}) {
349 auto owner = ids_().hex();
350 catalog_.
reserve(operation(), attempt, owner, inputs, outputs);
Definition runtime_checkpoint.h:23
encoded_cola_sections< P > encode_cola_sections(cola_index< P, Native, Main > const &source, object_id const &native_id, std::optional< blob_identity > main_id={}, std::optional< object_id > secondary_id={})
Definition cola_sections.h:256
encoded_sections< P > encode_native_sections(profile_array< P, stream_role::native > const &native)
Definition sections.h:405
file_kind
Definition object_path.h:25
Selects runtime checkpoint codecs and encodes binary admission intervals.
Describes completed native and index objects retained by runtime owners.
Stores retained roots, timeline generations and exact file graphs in optional SQLite metadata.
Definition catalog_bindings.h:41
Definition sections.h:442
Definition runtime_seal.h:30
Definition runtime_seal.h:19
Definition object_writer.h:39
Definition object_path.h:38
Definition runtime_seal.h:36
Definition runtime_seal.h:24
blob_identity identity
Definition runtime_seal.h:26
Definition runtime_graph_sealer.h:263
std::shared_ptr< native_binding_type const > native
Definition runtime_graph_sealer.h:267
std::optional< object_id > native_id
Definition runtime_graph_sealer.h:270
std::optional< pair_producer > pair_claim
Definition runtime_graph_sealer.h:268
std::optional< object_id > index_id
Definition runtime_graph_sealer.h:270
native_pointer owner
Definition runtime_graph_sealer.h:265
std::optional< native_producer > native_claim
Definition runtime_graph_sealer.h:269
std::shared_ptr< pair_binding_type const > main
Definition runtime_graph_sealer.h:266
std::shared_ptr< native_binding_type const > secondary
Definition runtime_graph_sealer.h:267
pair_type pair
Definition runtime_graph_sealer.h:264
ready_unit(pair_type p, native_pointer n, std::shared_ptr< pair_binding_type const > m={}, std::shared_ptr< native_binding_type const > s={}, std::shared_ptr< native_binding_type const > value={})
Definition runtime_graph_sealer.h:271
Definition runtime_graph_sealer.h:22
typename node_type::pair_type pair_type
Definition runtime_graph_sealer.h:26
static bool batch_owned(native_pointer const &native)
Definition runtime_graph_sealer.h:275
std::string * last_operation_
Definition runtime_graph_sealer.h:313
catalog_type & catalog_
Definition runtime_graph_sealer.h:311
typename Family::native_type native_type
Definition runtime_graph_sealer.h:25
object_attempt_id reserve(std::span< catalog_object_reservation const > outputs, std::span< blob_identity const > inputs={})
Definition runtime_graph_sealer.h:346
graph_sealer(catalog_type &catalog, Ids &ids, std::string *last_operation=nullptr)
Definition runtime_graph_sealer.h:34
void finish_ready(ready_unit &unit, object_attempt_id const &attempt)
Definition runtime_graph_sealer.h:279
typename node_type::native_pointer native_pointer
Definition runtime_graph_sealer.h:27
native_pointer mapped_native(native_pointer const &native)
Definition runtime_graph_sealer.h:235
std::shared_ptr< native_binding_type const > produce_native(native_pointer const &native)
Definition runtime_graph_sealer.h:324
decltype(std::declval< node_type const & >().mapped()) mapped_pointer
Definition runtime_graph_sealer.h:28
pair_type mapped_pair(pair_type const &pair)
Definition runtime_graph_sealer.h:247
std::string operation()
Definition runtime_graph_sealer.h:314
Ids & ids_
Definition runtime_graph_sealer.h:312
typename catalog_bindings< pair_binding_type >::producer pair_producer
Definition runtime_graph_sealer.h:262
typename catalog_bindings< native_binding_type >::producer native_producer
Definition runtime_graph_sealer.h:261
void bind_pair(pair_type const &pair, blob_identity const &id)
Definition runtime_graph_sealer.h:217
object_attempt_id reserve(object_id const &id, file_kind kind, std::span< blob_identity const > inputs={})
Definition runtime_graph_sealer.h:342
typename mapped_type::native_type mapped_native_type
Definition runtime_graph_sealer.h:30
std::shared_ptr< pair_binding_type const > ensure_pair(pair_type const &pair)
Definition runtime_graph_sealer.h:147
blob_identity pair_id(pair_type const &pair) const
Definition runtime_graph_sealer.h:229
auto encode_native(native_pointer const &native)
Definition runtime_graph_sealer.h:319
void bind_native(native_pointer const &native, object_id const &id)
Definition runtime_graph_sealer.h:210
std::size_t prepare_ready(std::span< pair_type const > roots, std::span< native_pointer const > natives)
Definition runtime_graph_sealer.h:41
typename Family::node_type node_type
Definition runtime_graph_sealer.h:24
object_id native_id(native_pointer const &native) const
Definition runtime_graph_sealer.h:224
std::remove_const_t< typename mapped_pointer::element_type > mapped_type
Definition runtime_graph_sealer.h:29
std::shared_ptr< native_binding_type const > ensure_native(native_pointer const &native)
Definition runtime_graph_sealer.h:136
Definition sqlite_catalog.h:351
void verify_sealed(object_seal_receipt const &receipt, file_kind expected) const
Definition sqlite_catalog.h:482
std::filesystem::path const & root() const &noexcept
Definition sqlite_catalog.h:396
void record_sealed(std::string_view op, object_seal_receipt const &receipt)
Definition sqlite_catalog.h:552
object_id const & identity() const &
Definition sqlite_catalog.h:398
void reserve(std::string_view op, object_attempt_id const &attempt, std::string_view owner, std::span< blob_identity const > inputs, std::span< catalog_object_reservation const > outputs)
Definition sqlite_catalog.h:518