Relational NT
A relational database kernel shaped around NT-style object management.
Loading...
Searching...
No Matches
RNT_C_API.h File Reference

C-callable surface over the RNT manager pipeline for OCaml ctypes. More...

#include <stddef.h>
#include <stdint.h>
#include "Api.h"
#include "VM.h"

Go to the source code of this file.

Classes

struct  PlanArgsScan
 SCAN context: reads all tuples from a stored relation. More...
struct  PlanArgsJoin
 JOIN context: nested-loop join of two child plans. More...
struct  PlanArgsTake
 TAKE context: passes at most limit tuples from source, then stops. More...
struct  PlanArgsProject
 PROJECT context: keeps only the named attributes of source. More...
struct  PlanArgsMaterialize
 MATERIALIZE context: caches source on its first scan, then replays the cache on later scans without touching source again. More...
struct  PlanArgsRename
 RENAME context: returns source, with the keys of pairs the values of it. More...
struct  PlanArgsUnion
 UNION context. More...
struct  PlanAction
 A single plan-construction request. More...

Typedefs

typedef void * rnt_handle_t
 Opaque handle to a registry object opened through HandlerManager.
typedef void * rnt_cursor_t
 Opaque cursor over a relation, driven by the VM or used directly.
typedef void * rnt_tuple_sink_t
 Opaque sink passed to a generator callback.
typedef int(* rnt_generator_fn) (void *ctx, const char *args, size_t offset, size_t limit, rnt_tuple_sink_t sink)
 Tuple-producing callback backing an ephemeral relation.
typedef void * rnt_plan_t
 Opaque plan node tree, built via rnt_plan_assemble calls.

Functions

NT_API int rnt_init (const char *driver, const char *storage_path)
 Initializes the RNT runtime with the selected storage backend.
NT_API int rnt_firewall (const char *auth_method, char **claims_out)
 Runs PermissionsManager::Firewall for a connection.
NT_API int rnt_session_open (void *connection_context, char **session_hash_out)
 Opens a session and registers it at /system/sessions/<hash>.
NT_API int rnt_session_close (const char *session_hash)
 Closes a session, unregistering it from /system/sessions/<hash>.
NT_API int rnt_session_set_branch (const char *session_hash, const char *branch_name, const char *target_hash)
 Sets a per-session override for a branch.
NT_API int rnt_sink_emit (rnt_tuple_sink_t sink, const char *tuple_kv)
 Emits one tuple from inside a generator callback.
NT_API int rnt_register_ephemeral_relation (const char *session_hash, int named, const char *name, rnt_generator_fn generator, void *generator_ctx, int cardinality, const char *generator_identity, const char *schema_kv, const char *dependencies, char **path_out)
 Registers an ephemeral relation owned by a session.
NT_API int rnt_drop_ephemeral_relation (const char *session_hash, const char *name)
 Drops a named ephemeral relation, releasing its session-ownership pin.
NT_API rnt_handle_t rnt_open_handle (const char *path, const char *claims)
 Opens a handle to the object at the given slash-separated path.
NT_API int rnt_close_handle (rnt_handle_t handle)
 Closes a handle, running HandlerManager::Close and Unmonitor.
NT_API int rnt_branch_target (rnt_handle_t handle, char **target_hash_out)
 Reads the current branch-tree root hash from a BRANCH object.
NT_API int rnt_branch_advance (const char *branch_path, const char *new_hash)
 Atomically advances a branch to point at a new branch-tree root.
NT_API int rnt_register_relation (const char *path)
 Registers a RELATION object at the given path.
NT_API int rnt_register_branch (const char *path, const char *target_hash)
 Registers a BRANCH object at the given path pointing at a branch-tree root.
NT_API int rnt_list_relations (const char *branch_mg_path, char **out)
 Lists all relations of a specific multigroup under a branch.
NT_API int rnt_list_branch_multigroups (const char *branch_path, char **out)
 Lists all multigroups bound to a branch.
NT_API int rnt_list_snapshot_relations (const char *snapshot_hash, char **out)
 Lists all relations stored in a specific snapshot.
NT_API int rnt_link_tuple (const char *relation_path, const char *kv_attrs, char **hash_out)
 Stores a tuple and links it to the relation at the given path.
NT_API int rnt_unlink_tuple (const char *relation_path, const char *tuple_hash)
 Removes a tuple from the relation's Merkle tree and tuple store.
NT_API int rnt_clear_relation (const char *relation_path)
 Resets a relation's Merkle root to the empty-tree state.
NT_API int rnt_relation_root (const char *relation_path, char **root_hash_out)
 Returns the current Merkle root hash for a relation.
NT_API rnt_cursor_t rnt_cursor_open (rnt_handle_t handle)
 Opens a cursor on the relation referenced by handle.
NT_API int rnt_cursor_next (rnt_cursor_t cursor, char **tuple_out)
 Advances the cursor and returns the next tuple as a kv string.
NT_API int rnt_cursor_close (rnt_cursor_t cursor)
 Closes a cursor and releases its resources.
NT_API rnt_plan_t rnt_plan_assemble (PlanAction action)
 Builds one plan node from action and returns the resulting subtree.
NT_API void rnt_plan_free (rnt_plan_t plan)
 Releases a plan that was built but not yet executed.
NT_API rnt_cursor_t rnt_vm_execute_plan (rnt_plan_t plan)
 Executes a plan tree and returns a streaming VM cursor.
NT_API int rnt_vm_cursor_next (rnt_cursor_t vm_cursor, char **tuple_out)
 Advances a VM cursor and returns the next merged tuple as a kv string.
NT_API int rnt_vm_cursor_close (rnt_cursor_t vm_cursor)
 Closes a VM cursor, releases all plan nodes, cursors, and handles.
NT_API void rnt_free_string (char *s)
 Releases a string allocated by the API.
NT_API void rnt_free_bytes (uint8_t *p)
 Releases a byte buffer allocated by the API.

Detailed Description

C-callable surface over the RNT manager pipeline for OCaml ctypes.

All types are opaque void pointers on the C side; the implementation casts them to the appropriate C++ types internally. Callers must never dereference handle or cursor pointers directly.

Memory contract

  • Strings returned via out-parameters (char**) are heap-allocated by the API and must be released with rnt_free_string().
  • Payloads returned via (uint8_t**, size_t*) are heap-allocated and must be released with rnt_free_bytes().
  • Handles and cursors are owned by the caller and must be closed before the program exits.

Error convention

  • Functions returning int use 0 for success and a negative value for error.
  • Functions returning a pointer return NULL on failure.

Thread safety

This API is not thread-safe. The global runtime (g_rt) is a single in-process instance; all callers share the same ObjectManager and storage backend. The expected usage model is a single OCaml thread (or domain) driving the API at a time. If concurrent access is needed in the future, a per-object or per-relation mutex strategy should be introduced.

Todo
Implement AUTH_CLAIM::READ/WRITE enforcement in rnt_open_handle once PermissionsManager::Access is wired to a real policy engine. Currently all handles open with full access regardless of the claims parameter.

Typedef Documentation

◆ rnt_generator_fn

typedef int(* rnt_generator_fn) (void *ctx, const char *args, size_t offset, size_t limit, rnt_tuple_sink_t sink)

Tuple-producing callback backing an ephemeral relation.

Invoked by the cursor layer each time a page of tuples is needed. The callback must emit at most limit tuples starting at logical position offset by calling rnt_sink_emit once per tuple. Calls may re-enter the RNT API (e.g. to execute a VM plan over base relations); the runtime is single-threaded, so no locking is required.

Parameters
ctxOpaque context pointer given at registration time.
argsBound argument values written by a JOIN before probing, newline-separated. Empty string when scanned standalone.
offsetZero-based logical tuple offset (for pagination).
limitMaximum number of tuples to emit.
sinkPass to rnt_sink_emit for each produced tuple.
Returns
0 on success, negative on error (the page is treated as empty).

◆ rnt_tuple_sink_t

typedef void* rnt_tuple_sink_t

Opaque sink passed to a generator callback.

The callback pushes each tuple it produces through rnt_sink_emit; the runtime copies the tuple out immediately, so the string only needs to stay valid for the duration of the rnt_sink_emit call.

Function Documentation

◆ rnt_branch_advance()

NT_API int rnt_branch_advance ( const char * branch_path,
const char * new_hash )

Atomically advances a branch to point at a new branch-tree root.

The new hash must already exist as a content-addressed blob in the KV store — branch-tree roots are produced by mutating calls (rnt_link_tuple, rnt_register_relation, …) and cannot be invented externally. Pass an empty string to reset the branch to unborn.

Write exclusion is structural: BRANCH objects carry exclusive=true in their object_type, so LifecycleManager::Contention prevents a second handle from being opened while a writer holds the branch. AUTH_CLAIM::WRITE is not checked at the C API boundary.

Parameters
branch_pathSlash-separated branch path, e.g. "/system/branches/main".
new_hashBranch-tree root to advance to (64-char lowercase hex), or "" to reset to unborn.
Returns
0 on success, negative when the branch is not found, the type is not BRANCH, or new_hash is non-empty but no matching blob exists in the KV store.

◆ rnt_branch_target()

NT_API int rnt_branch_target ( rnt_handle_t handle,
char ** target_hash_out )

Reads the current branch-tree root hash from a BRANCH object.

Only valid for handles opened on BRANCH objects. The returned string is the merkle_root of the BRANCH_TREE this branch currently points at — a Merkle<std::string> root mapping mg_name → mg_hash. An empty string indicates an unborn branch with no commits yet.

Parameters
handleHandle to a BRANCH object.
target_hash_outSet to a heap-allocated copy of the target hash (possibly empty). Release with rnt_free_string().
Returns
0 on success, negative when the handle is not a BRANCH.

◆ rnt_clear_relation()

NT_API int rnt_clear_relation ( const char * relation_path)

Resets a relation's Merkle root to the empty-tree state.

Sets ObjectManager::Relation::merkle_root to the empty string. Existing tuple bytes remain in the KV store. After this call the relation contains no tuples from the perspective of cursor iteration.

Parameters
relation_pathSlash-separated relation path.
Returns
0 on success, negative when the relation is not found.

◆ rnt_close_handle()

NT_API int rnt_close_handle ( rnt_handle_t handle)

Closes a handle, running HandlerManager::Close and Unmonitor.

Returns
0 on success, negative on error.

◆ rnt_cursor_close()

NT_API int rnt_cursor_close ( rnt_cursor_t cursor)

Closes a cursor and releases its resources.

Returns
0 on success, negative on error.

◆ rnt_cursor_next()

NT_API int rnt_cursor_next ( rnt_cursor_t cursor,
char ** tuple_out )

Advances the cursor and returns the next tuple as a kv string.

The tuple is encoded as a newline-delimited "key=value" string matching the format accepted by rnt_link_tuple: "name=Blathers\nprofession=Museum Curator\n"

Parameters
cursorOpen cursor.
tuple_outSet to a heap-allocated kv string, or NULL when exhausted. Release with rnt_free_string() when non-NULL.
Returns
1 when a tuple was returned, 0 when exhausted, negative on error.

◆ rnt_cursor_open()

NT_API rnt_cursor_t rnt_cursor_open ( rnt_handle_t handle)

Opens a cursor on the relation referenced by handle.

The returned cursor is positioned before the first tuple. Advance it with rnt_cursor_next(). The cursor must be closed with rnt_cursor_close() before closing the handle.

Parameters
handleOpen RELATION handle.
Returns
Cursor pointer, or NULL on error.

◆ rnt_drop_ephemeral_relation()

NT_API int rnt_drop_ephemeral_relation ( const char * session_hash,
const char * name )

Drops a named ephemeral relation, releasing its session-ownership pin.

The entry is collected as soon as no cursor or dependent ephemeral still holds it, cascading the pins it took on its base relations. Scratch entries cannot be dropped by name; they die with their consuming cursor.

Parameters
session_hashOwning session's hash.
nameLeaf name given at registration.
Returns
0 on success, negative when no such named binding exists.

◆ rnt_firewall()

NT_API int rnt_firewall ( const char * auth_method,
char ** claims_out )

Runs PermissionsManager::Firewall for a connection.

Parameters
auth_method"plain_text" or "certificate".
claims_outSet to a heap-allocated, newline-separated claim string. Release with rnt_free_string(). NULL on error.
Returns
0 on success, negative when authentication is rejected.

◆ rnt_free_bytes()

NT_API void rnt_free_bytes ( uint8_t * p)

Releases a byte buffer allocated by the API.

Safe to call with NULL.

◆ rnt_free_string()

NT_API void rnt_free_string ( char * s)

Releases a string allocated by the API.

Safe to call with NULL.

◆ rnt_init()

NT_API int rnt_init ( const char * driver,
const char * storage_path )

Initializes the RNT runtime with the selected storage backend.

Must be called before any other API function. Once the runtime is successfully initialized, subsequent calls are no-ops and return 0. If initialization fails (returns negative), the call may be retried with corrected parameters — the runtime is left in a clean state.

Parameters
driverStorage driver to use: "sqlite" or "memory". "sqlite" persists data to storage_path. "memory" keeps all data in process memory (ignores storage_path); intended for tests.
storage_pathFile path for the SQLite database, or ":memory:" for an ephemeral SQLite store. Ignored when driver is "memory".
Returns
0 on success, negative on error.

◆ rnt_link_tuple()

NT_API int rnt_link_tuple ( const char * relation_path,
const char * kv_attrs,
char ** hash_out )

Stores a tuple and links it to the relation at the given path.

Tuples are encoded as a flat key=value string, one attribute per line: "name=Blathers\nprofession=Museum Curator\n" Attributes are sorted by name before hashing to ensure content-addressing is order-independent.

Parameters
relation_pathSlash-separated relation path.
kv_attrsNewline-delimited "key=value" attribute string.
hash_outSet to the 64-character hex SHA-256 hash of the tuple. Release with rnt_free_string(). NULL on error.
Returns
0 on success, negative on error.

◆ rnt_list_branch_multigroups()

NT_API int rnt_list_branch_multigroups ( const char * branch_path,
char ** out )

Lists all multigroups bound to a branch.

Reads the branch-tree root from /system/branches/<name> and pages each (mg_name, mg_hash) entry. Returns "name\thash\n" lines. Unborn branches yield an empty string.

Parameters
branch_pathSlash-separated branch path, e.g. "/system/branches/main".
outHeap-allocated string; release with rnt_free_string().
Returns
0 on success, negative when the branch is not found.

◆ rnt_list_relations()

NT_API int rnt_list_relations ( const char * branch_mg_path,
char ** out )

Lists all relations of a specific multigroup under a branch.

Returns a newline-delimited string of "name\troot_hash" pairs, one per relation in the named multigroup at the branch's current tree. An unborn branch or an mg absent from the branch tree yields an empty string. The caller must release the string with rnt_free_string().

Parameters
branch_mg_pathSlash-separated path of the form "/system/branches/<name>/multigroups/<mg>".
outSet to a heap-allocated "name\troot\n" string. Release with rnt_free_string(). NULL on error.
Returns
0 on success, negative when the path shape is wrong or the branch is not found.

◆ rnt_list_snapshot_relations()

NT_API int rnt_list_snapshot_relations ( const char * snapshot_hash,
char ** out )

Lists all relations stored in a specific snapshot.

Reads the multigroup codec directly from the snapshot at /system/snapshots/<snapshot_hash> without following any branch HEAD. Use this when the desired snapshot hash is already known (e.g. detached checkout). Returns the same "name\troot_hash\n" format as rnt_list_relations.

Parameters
snapshot_hash64-char hex hash of the snapshot.
outSet to heap-allocated string. Release with rnt_free_string().
Returns
0 on success, negative when the snapshot is not registered.

◆ rnt_open_handle()

NT_API rnt_handle_t rnt_open_handle ( const char * path,
const char * claims )

Opens a handle to the object at the given slash-separated path.

Runs the full HandlerManager::Open pipeline: ObjectManager::Find → PermissionsManager::Access → IdentityManager::CanOpen → LifecycleManager::Contention → LifecycleManager::Monitor.

Parameters
pathSlash-separated logical path, e.g. "/system/branches/main".
claimsClaim string returned by rnt_firewall (may be NULL).
Returns
Handle pointer, or NULL when the path is not found or access is denied.

◆ rnt_plan_assemble()

NT_API rnt_plan_t rnt_plan_assemble ( PlanAction action)

Builds one plan node from action and returns the resulting subtree.

Sole entry point for plan construction. Validates runtime state once, then dispatches on action.op. Child plans for JOIN/TAKE/PROJECT are themselves results of prior rnt_plan_assemble calls; ownership transfers per the per-operator rules documented on each PlanArgs* struct.

Returns
Plan node, or NULL when the runtime is uninitialised or construction fails (e.g. relation does not exist).

◆ rnt_plan_free()

NT_API void rnt_plan_free ( rnt_plan_t plan)

Releases a plan that was built but not yet executed.

Closes any open cursors and handles owned by the plan tree, then frees all nodes. Safe to call with NULL. Do NOT call after rnt_vm_execute_plan — that function takes ownership.

◆ rnt_register_branch()

NT_API int rnt_register_branch ( const char * path,
const char * target_hash )

Registers a BRANCH object at the given path pointing at a branch-tree root.

If a BRANCH already exists at this path, returns 0 without modifying it. When target_hash is non-NULL and non-empty it must already exist as a content-addressed blob in the KV store (produced by an earlier mutation through the same runtime); otherwise the call fails. Pass NULL or "" to register an unborn branch.

Parameters
pathSlash-separated path, e.g. "/system/branches/main".
target_hashBranch-tree root this branch points at (may be NULL or "" for unborn).
Returns
0 on success, negative on error.

◆ rnt_register_ephemeral_relation()

NT_API int rnt_register_ephemeral_relation ( const char * session_hash,
int named,
const char * name,
rnt_generator_fn generator,
void * generator_ctx,
int cardinality,
const char * generator_identity,
const char * schema_kv,
const char * dependencies,
char ** path_out )

Registers an ephemeral relation owned by a session.

An ephemeral relation has no tuple storage of its own: its tuples are produced on demand by generator. The entry lands under the session's namespace — /system/sessions/<hash>/ephemeral/<name> when named is non-zero (a named binding that survives between commands until dropped or session close), or /system/sessions/<hash>/scratch/<composed_root> when zero (an anonymous intermediate collected as soon as its consuming cursor closes). Scan it through the normal pipeline: rnt_open_handle on the registered path, then rnt_cursor_open / rnt_plan_scan.

Registration pins every dependency, so a base relation cannot be collected while this relation is defined atop it; the pins are released when the ephemeral itself is collected. Registration is idempotent for an identical scratch result or a live named binding. See docs/ephemeral-relations.org.

Parameters
session_hashHash returned by rnt_session_open.
namedNon-zero for a named binding, 0 for scratch.
nameLeaf name for named bindings; ignored for scratch.
generatorTuple-producing callback. Must stay callable until the entry is collected.
generator_ctxOpaque pointer passed back to generator.
cardinality0 Finite, 1 ConstrainedFinite, 2 AlephZero, 3 Continuum.
generator_identityStable operator label for the identity hash, e.g. "join:id", "select:age".
schema_kvNewline-separated "name=type" attribute lines.
dependenciesNewline-separated logical paths of the base relations this is defined atop, e.g. "system/snapshots/<h>/relations/<rel>". Every path must resolve or the call fails.
path_outOptional (may be NULL): set to the heap-allocated slash-joined registered path. Release with rnt_free_string().
Returns
0 on success, negative on error.

◆ rnt_register_relation()

NT_API int rnt_register_relation ( const char * path)

Registers a RELATION object at the given path.

Idempotent: if an object already exists at the path, the call succeeds without re-registering.

Parameters
pathSlash-separated path of the form "/system/branches/<branch>/multigroups/<mg>/relations/<rel>".
Returns
0 on success, negative on error.

◆ rnt_relation_root()

NT_API int rnt_relation_root ( const char * relation_path,
char ** root_hash_out )

Returns the current Merkle root hash for a relation.

OCaml calls this after rnt_link_tuple or rnt_unlink_tuple to read the updated root back and store it in the in-memory multigroup (tree_pointer). An empty string is returned for a relation that contains no tuples.

Parameters
relation_pathSlash-separated relation path.
root_hash_outSet to the 64-character hex root hash, or to an empty heap-allocated string for an empty relation. Release with rnt_free_string().
Returns
0 on success, negative when the relation is not found.

◆ rnt_session_close()

NT_API int rnt_session_close ( const char * session_hash)

Closes a session, unregistering it from /system/sessions/<hash>.

After this call the session hash is invalid; subsequent rnt_session_* or resolver lookups against it will fail. Branch overrides held by the session are dropped.

Parameters
session_hashHash returned by rnt_session_open.
Returns
0 on success, negative when the hash does not match an active session.

◆ rnt_session_open()

NT_API int rnt_session_open ( void * connection_context,
char ** session_hash_out )

Opens a session and registers it at /system/sessions/<hash>.

The runtime mints a random 256-bit hex hash for the session; the caller has no influence over the value. The returned string is the opaque identifier required by every other rnt_session_* call.

Parameters
connection_contextCaller-owned pointer carried on the session. The runtime treats it as opaque; ownership of the pointee remains with the caller.
session_hash_outSet to a heap-allocated 64-char hex string. Release with rnt_free_string().
Returns
0 on success, negative on error.

◆ rnt_session_set_branch()

NT_API int rnt_session_set_branch ( const char * session_hash,
const char * branch_name,
const char * target_hash )

Sets a per-session override for a branch.

While the override is in effect, paths resolved through /system/sessions/<hash>/branches/<branch_name>/... point at /system/snapshots/<target_hash>/... regardless of where the global branch HEAD currently sits. Pass an empty string for target_hash to remove the override and resume falling back to the global branch.

Non-empty target hashes must correspond to an existing /system/snapshots/<target_hash> entry; otherwise the call fails.

Parameters
session_hashSession identifier.
branch_nameBranch the override applies to (e.g. "main").
target_hashSnapshot hash to bind, or "" to clear.
Returns
0 on success, negative on error.

◆ rnt_sink_emit()

NT_API int rnt_sink_emit ( rnt_tuple_sink_t sink,
const char * tuple_kv )

Emits one tuple from inside a generator callback.

Parameters
sinkSink received by the callback.
tuple_kvNewline-separated "name=value" attribute lines — the same wire format rnt_link_tuple consumes and rnt_cursor_next returns. Copied before returning.
Returns
0 on success, negative on error.

◆ rnt_unlink_tuple()

NT_API int rnt_unlink_tuple ( const char * relation_path,
const char * tuple_hash )

Removes a tuple from the relation's Merkle tree and tuple store.

Calls Merkle::Remove on the relation's current root and updates ObjectManager::Relation::merkle_root atomically. The tuple bytes remain in the KV store (they may be referenced by older snapshots); only the membership in the current tree is removed.

Parameters
relation_pathSlash-separated relation path.
tuple_hash64-character hex SHA-256 of the tuple to remove.
Returns
0 on success, negative when the relation is not found.

◆ rnt_vm_cursor_close()

NT_API int rnt_vm_cursor_close ( rnt_cursor_t vm_cursor)

Closes a VM cursor, releases all plan nodes, cursors, and handles.

Returns
0 on success, negative on error.

◆ rnt_vm_cursor_next()

NT_API int rnt_vm_cursor_next ( rnt_cursor_t vm_cursor,
char ** tuple_out )

Advances a VM cursor and returns the next merged tuple as a kv string.

Same encoding and return-value semantics as rnt_cursor_next.

Parameters
vm_cursorCursor returned by rnt_vm_execute_plan.
tuple_outSet to a heap-allocated kv string, or NULL when exhausted. Release with rnt_free_string() when non-NULL.
Returns
1 when a tuple was returned, 0 when exhausted, negative on error.

◆ rnt_vm_execute_plan()

NT_API rnt_cursor_t rnt_vm_execute_plan ( rnt_plan_t plan)

Executes a plan tree and returns a streaming VM cursor.

Takes ownership of plan; the caller must not call rnt_plan_free after this. The returned cursor is advanced with rnt_vm_cursor_next() and must be closed with rnt_vm_cursor_close(), which also releases all plan resources.

Returns
VM cursor, or NULL when the plan is NULL.