Register a vertex, and address it (L4 graph)¶
The first thing a node does. A path_t parses its string once into
the canonical PATH-TLV payload — the packed segment records — and the vertex map is keyed on
those bytes, never on the string
(reference 02 §Dispatch keyed on canonical PATH TLV bytes).
register_vertex returns a vertex_handle_t, and find takes the key, which is the same
lookup the dispatcher runs.
What to notice¶
The key is the identity, the string is a courtesy. The example prints the byte length of
/sensor/temp’s key and resolves the handle throughg.find(temp.key()). Two spellings that name one vertex must canonicalize to byte-identical PATH payload bytes.Two registration doors, one fallible.
register_vertextakes a known-good literal and hard-aborts on a collision, because a collision on a compile-site literal is a source bug (ADR-0056).try_register_vertexis the runtime-path form and reportsPATH_IN_USEinstead.Registering
/sensor/tempdoes not register/sensor. The intermediate is an unregistered structural placeholder — the addressing scaffolding created it on the way to a deeper registration, andfinddoes not answer for one (CONTEXT.md §Structural vertex). That is distinct from a structural vertex, which is registered and merely carries no application datum.There is no null handle. “No such vertex” is
std::optional<vertex_handle_t>’s empty state, not an invalid handle.
Source¶
1/*
2 * SPDX-License-Identifier: Apache-2.0
3 * SPDX-FileCopyrightText: Copyright 2026 avatarsd LLC
4 */
5
6/**
7 * @file
8 * @brief ONE CONCEPT — register a vertex, and address it by its canonical PATH bytes.
9 *
10 * A `path_t` parses its string ONCE into the canonical PATH-TLV payload (packed segment
11 * records); the vertex map is keyed on those bytes, never on the string
12 * (`docs/reference/02-graph-model.md` §Dispatch keyed on canonical PATH TLV bytes). Two
13 * further first-contact facts fall out and are checked here: re-registering a live path is
14 * `PATH_IN_USE`, and registering `/sensor/temp` does NOT register `/sensor` — the
15 * intermediate is an unregistered structural placeholder (`CONTEXT.md` §Structural vertex).
16 *
17 * Runs under ctest as `example_graph_register`; returns non-zero on any failed check.
18 */
19
20#include <cstdio>
21
22#include "libtracer/tracer.hpp"
23
24namespace {
25
26using tr::graph::path_t;
27using tr::graph::role_t;
28using tr::graph::status_t;
29using tr::graph::vertex_handle_t;
30
31/** @brief Report expectation @p what and record a failure on @p ok. */
32void check(bool& ok, bool cond, const char* what) {
33 std::printf(" [%s] %s\n", cond ? "ok" : "FAIL", what);
34 ok = ok && cond;
35}
36
37} // namespace
38
39int main() {
40 tr::graph::graph_t g;
41 bool ok = true;
42
43 const path_t temp("/sensor/temp");
44 const vertex_handle_t vh = g.register_vertex(temp, role_t::STORED_VALUE);
45 std::printf("registered /sensor/temp — key is %zu packed bytes\n", temp.key().size());
46
47 // find() takes the KEY, not the string: the same lookup the dispatcher runs.
48 const auto found = g.find(temp.key());
49 check(ok, found && *found == vh, "find(key) resolves to the registered handle");
50
51 // register_vertex(literal) hard-aborts on a collision (ADR-0056: a source bug); the
52 // fallible form is for a genuine runtime path, and reports the collision.
53 const auto dup = g.try_register_vertex(path_t("/sensor/temp"), role_t::STORED_VALUE);
54 check(ok, !dup && dup.error() == status_t::PATH_IN_USE,
55 "re-registering a live path is PATH_IN_USE");
56
57 check(ok, !g.find(path_t("/sensor").key()),
58 "the intermediate /sensor stays an unregistered placeholder");
59 check(ok, !g.find(path_t("/sensor/humidity").key()), "an unknown path resolves to nothing");
60 return ok ? 0 : 1;
61}
See also: graph module · path module · graph model reference · addressing reference.