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 through g.find(temp.key()). Two spellings that name one vertex must canonicalize to byte-identical PATH payload bytes.

  • Two registration doors, one fallible. register_vertex takes 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_vertex is the runtime-path form and reports PATH_IN_USE instead.

  • Registering /sensor/temp does not register /sensor. The intermediate is an unregistered structural placeholder — the addressing scaffolding created it on the way to a deeper registration, and find does 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.