aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--include/CursorManager.h24
-rw-r--r--include/HandlerManager.h18
-rw-r--r--include/IStorageBackend.h10
-rw-r--r--include/IdentityManager.h10
-rw-r--r--include/InMemoryBackend.h12
-rw-r--r--include/LifecycleManager.h14
-rw-r--r--include/Merkle.h259
-rw-r--r--include/MultigroupCodec.h23
-rw-r--r--include/NT.h12
-rw-r--r--include/NamespaceReferenceManager.h17
-rw-r--r--include/ObjectManager.h38
-rw-r--r--include/PermissionsManager.h23
-rw-r--r--include/RNT_C_API.h82
-rw-r--r--include/Runtime.h10
-rw-r--r--include/SqliteBackend.h12
-rw-r--r--include/TupleCodec.h5
-rw-r--r--include/Types.h21
-rw-r--r--include/VM.h49
18 files changed, 313 insertions, 326 deletions
diff --git a/include/CursorManager.h b/include/CursorManager.h
index 2743516..a4c82d7 100644
--- a/include/CursorManager.h
+++ b/include/CursorManager.h
@@ -16,8 +16,7 @@
* @brief Declares paging and cursor orchestration for query execution.
*/
-namespace nt
-{
+namespace nt {
/**
* @class CursorManager
* @brief Orchestrates paginated data retrieval from a storage backend.
@@ -34,9 +33,8 @@ namespace nt
* Merkle::Page(backend, merkle_root, fetch_offset, PAGE_SIZE) to retrieve
* the next page of tuple hashes without loading sibling subtrees.
*/
- class CursorManager
- {
- public:
+ class CursorManager {
+ public:
static constexpr std::size_t PAGE_SIZE = 1;
/**
@@ -49,8 +47,7 @@ namespace nt
* resolved snapshot for the handle's relation and Pins it for the
* cursor's lifetime, releasing the pin in Close.
*/
- explicit CursorManager(IStorageBackend& backend,
- LifecycleManager* lifecycles = nullptr,
+ explicit CursorManager(IStorageBackend& backend, LifecycleManager* lifecycles = nullptr,
ObjectManager* objects = nullptr);
/**
@@ -88,7 +85,7 @@ namespace nt
std::vector<std::string> args;
std::vector<Tuple> page;
std::size_t page_position = 0;
- std::size_t fetch_offset = 0; // next Merkle::Page() call starts here
+ std::size_t fetch_offset = 0; // next Merkle::Page() call starts here
bool exhausted = false;
/**
* True for EPHEMERAL_RELATION cursors; selects the generator-driven
@@ -124,8 +121,7 @@ namespace nt
* @param merkle_root Hex hash of the relation's Merkle root at open
* time. Ignored for EPHEMERAL_RELATION handles.
*/
- cursor* Open(HandlerManager::handle* handle,
- const std::string& merkle_root = "");
+ cursor* Open(HandlerManager::handle* handle, const std::string& merkle_root = "");
/**
* @brief Pulls the next tuple from the cursor.
@@ -141,10 +137,10 @@ namespace nt
*/
void Close(cursor* cursor);
- private:
- IStorageBackend& backend_;
+ private:
+ IStorageBackend& backend_;
LifecycleManager* lifecycles_ = nullptr;
- ObjectManager* objects_ = nullptr;
+ ObjectManager* objects_ = nullptr;
/**
* Fetches a page of hashes via Merkle::Page, resolves each from the
@@ -154,4 +150,4 @@ namespace nt
*/
void LoadPage(cursor* c);
};
-}
+} // namespace nt
diff --git a/include/HandlerManager.h b/include/HandlerManager.h
index a9ce09d..b2beb5f 100644
--- a/include/HandlerManager.h
+++ b/include/HandlerManager.h
@@ -13,17 +13,15 @@
* @brief Declares handle allocation and release for authorized object access.
*/
-namespace nt
-{
+namespace nt {
class IdentityManager;
class LifecycleManager;
class NamespaceReferenceManager;
class PermissionsManager;
/** @brief Opens and closes authorized handles to registry objects. */
- class HandlerManager
- {
- public:
+ class HandlerManager {
+ public:
/**
* @brief Constructs a HandlerManager with shared runtime dependencies.
*
@@ -31,10 +29,8 @@ namespace nt
* counters, permission policy) persists across calls rather than being
* rebuilt per open/close.
*/
- HandlerManager(ObjectManager& objects,
- PermissionsManager& permissions,
- IdentityManager& identities,
- LifecycleManager& lifecycles,
+ HandlerManager(ObjectManager& objects, PermissionsManager& permissions,
+ IdentityManager& identities, LifecycleManager& lifecycles,
NamespaceReferenceManager& references);
/**
@@ -90,11 +86,11 @@ namespace nt
*/
bool Close(struct handle* handle);
- private:
+ private:
ObjectManager& objects_;
PermissionsManager& permissions_;
IdentityManager& identities_;
LifecycleManager& lifecycles_;
NamespaceReferenceManager& references_;
};
-}
+} // namespace nt
diff --git a/include/IStorageBackend.h b/include/IStorageBackend.h
index e408c95..a7cc782 100644
--- a/include/IStorageBackend.h
+++ b/include/IStorageBackend.h
@@ -15,8 +15,7 @@
* Merkle class, not by this interface. Only Put and Get are required.
*/
-namespace nt
-{
+namespace nt {
/**
* @interface IStorageBackend
* @brief Contract between CursorManager / Merkle and a physical storage engine.
@@ -29,9 +28,8 @@ namespace nt
* maintains insertion-order-independent relation membership on top of these
* two primitives.
*/
- class IStorageBackend
- {
- public:
+ class IStorageBackend {
+ public:
virtual ~IStorageBackend() = default;
/**
@@ -48,4 +46,4 @@ namespace nt
*/
virtual std::optional<std::vector<uint8_t>> Get(const std::string& hash) = 0;
};
-}
+} // namespace nt
diff --git a/include/IdentityManager.h b/include/IdentityManager.h
index 6b487a9..1dd75da 100644
--- a/include/IdentityManager.h
+++ b/include/IdentityManager.h
@@ -8,8 +8,7 @@
* @brief Declares object capability checks.
*/
-namespace nt
-{
+namespace nt {
/**
* @brief Checks whether an object supports identity-level operations.
*
@@ -21,9 +20,8 @@ namespace nt
* so that error logs identify the type without dereferencing the pointer.
* See docs/reactos-ob-comparison.md §2.
*/
- class IdentityManager
- {
- public:
+ class IdentityManager {
+ public:
/**
* @brief Returns true when the object's type supports being opened.
*
@@ -46,4 +44,4 @@ namespace nt
*/
const bool CanClose(ObjectManager::registry* object);
};
-}
+} // namespace nt
diff --git a/include/InMemoryBackend.h b/include/InMemoryBackend.h
index 1a7d3a7..b66d355 100644
--- a/include/InMemoryBackend.h
+++ b/include/InMemoryBackend.h
@@ -19,15 +19,13 @@
* Relation membership is tracked by the Merkle class, not this backend.
*/
-namespace nt
-{
- class InMemoryBackend : public IStorageBackend
- {
- public:
+namespace nt {
+ class InMemoryBackend : public IStorageBackend {
+ public:
std::string Put(std::vector<uint8_t> value) override;
std::optional<std::vector<uint8_t>> Get(const std::string& hash) override;
- private:
+ private:
std::unordered_map<std::string, std::vector<uint8_t>> kv_;
};
-}
+} // namespace nt
diff --git a/include/LifecycleManager.h b/include/LifecycleManager.h
index e053cd2..c1e63d8 100644
--- a/include/LifecycleManager.h
+++ b/include/LifecycleManager.h
@@ -9,8 +9,7 @@
* @brief Declares monitoring, pinning, cleanup, and contention operations.
*/
-namespace nt
-{
+namespace nt {
/**
* @brief Manages runtime lifecycle concerns for registry objects.
*
@@ -23,9 +22,8 @@ namespace nt
* Monitor / Unmonitor manage `handle_count`. Pin / Unpin manage
* `reference_count`. See docs/reactos-ob-comparison.md §1.
*/
- class LifecycleManager
- {
- public:
+ class LifecycleManager {
+ public:
/**
* @brief Constructs a LifecycleManager bound to a registry and store.
*
@@ -120,7 +118,7 @@ namespace nt
*/
const bool Contention(ObjectManager::registry* object);
- private:
+ private:
/**
* @brief Joint-counters check + type-specific cascade + Unregister.
*
@@ -158,7 +156,7 @@ namespace nt
*/
void CascadeBranchTree(ObjectManager::registry* branch_tree);
- ObjectManager& objects_;
+ ObjectManager& objects_;
IStorageBackend& storage_;
};
-}
+} // namespace nt
diff --git a/include/Merkle.h b/include/Merkle.h
index ba8018a..6256ddc 100644
--- a/include/Merkle.h
+++ b/include/Merkle.h
@@ -58,143 +58,128 @@
namespace nt {
-/** @brief 32-byte hash, the universal payload type for all merkle levels. */
-using Hash32 = std::array<uint8_t, 32>;
-
-/** @brief Decode a 64-character lowercase-hex SHA256 string into raw bytes.
- * Throws std::invalid_argument when the string is not exactly 64 hex chars. */
-Hash32 hex_to_bin(const std::string& hex);
-
-/** @brief Encode raw 32 bytes back into a 64-character lowercase-hex string. */
-std::string bin_to_hex(const Hash32& bin);
-
-template<typename Key>
-class Merkle {
-public:
- static constexpr size_t B = 64;
-
- /**
- * @brief Insert or overwrite a `(key, payload)` mapping.
- * @param store KV backend for node serialisation.
- * @param root_hex Current root hash (empty string = empty tree).
- * @param key Routing/identity key.
- * @param payload Hash this key maps to (child root one level down, or
- * the key itself at the relation level).
- * @return New root hash. Equal to root_hex when an insertion of an
- * identical (key, payload) pair would be a no-op.
- */
- static std::string Insert(IStorageBackend& store,
- const std::string& root_hex,
- const Key& key,
- const Hash32& payload);
-
- /**
- * @brief Remove a key from the tree.
- * @return New root hash. Empty string when the tree becomes empty.
- * Equal to root_hex when the key is absent.
- */
- static std::string Remove(IStorageBackend& store,
- const std::string& root_hex,
- const Key& key);
-
- /**
- * @brief Look up the payload for a key.
- * @return The payload when present, std::nullopt when absent.
- */
- static std::optional<Hash32> Get(IStorageBackend& store,
- const std::string& root_hex,
- const Key& key);
-
- /** @brief One (key, payload) pair returned by Page(). */
- struct Entry {
- Key key;
- Hash32 payload;
+ /** @brief 32-byte hash, the universal payload type for all merkle levels. */
+ using Hash32 = std::array<uint8_t, 32>;
+
+ /** @brief Decode a 64-character lowercase-hex SHA256 string into raw bytes.
+ * Throws std::invalid_argument when the string is not exactly 64 hex chars. */
+ Hash32 hex_to_bin(const std::string& hex);
+
+ /** @brief Encode raw 32 bytes back into a 64-character lowercase-hex string. */
+ std::string bin_to_hex(const Hash32& bin);
+
+ template <typename Key> class Merkle {
+ public:
+ static constexpr size_t B = 64;
+
+ /**
+ * @brief Insert or overwrite a `(key, payload)` mapping.
+ * @param store KV backend for node serialisation.
+ * @param root_hex Current root hash (empty string = empty tree).
+ * @param key Routing/identity key.
+ * @param payload Hash this key maps to (child root one level down, or
+ * the key itself at the relation level).
+ * @return New root hash. Equal to root_hex when an insertion of an
+ * identical (key, payload) pair would be a no-op.
+ */
+ static std::string Insert(IStorageBackend& store, const std::string& root_hex,
+ const Key& key, const Hash32& payload);
+
+ /**
+ * @brief Remove a key from the tree.
+ * @return New root hash. Empty string when the tree becomes empty.
+ * Equal to root_hex when the key is absent.
+ */
+ static std::string Remove(IStorageBackend& store, const std::string& root_hex,
+ const Key& key);
+
+ /**
+ * @brief Look up the payload for a key.
+ * @return The payload when present, std::nullopt when absent.
+ */
+ static std::optional<Hash32> Get(IStorageBackend& store, const std::string& root_hex,
+ const Key& key);
+
+ /** @brief One (key, payload) pair returned by Page(). */
+ struct Entry {
+ Key key;
+ Hash32 payload;
+ };
+
+ /**
+ * @brief Page through entries in key-sorted order.
+ *
+ * Descends to the leaf at logical position @p offset using cumulative
+ * leaf_counts stored in internal nodes, then walks forward collecting at
+ * most @p limit entries. Only the nodes on the active path are loaded;
+ * sibling subtrees are never touched.
+ */
+ static std::vector<Entry> Page(IStorageBackend& store, const std::string& root_hex,
+ size_t offset, size_t limit);
+
+ private:
+ struct LeafEntry {
+ Key key;
+ Hash32 payload;
+ };
+
+ struct LeafNode {
+ std::vector<LeafEntry> entries;
+ };
+
+ struct ChildEntry {
+ uint64_t leaf_count;
+ Key min_key;
+ Hash32 child_hash;
+ };
+
+ struct InternalNode {
+ std::vector<ChildEntry> entries;
+ };
+
+ // Wire format
+ static std::vector<uint8_t> encode_leaf(const LeafNode& n);
+ static std::vector<uint8_t> encode_internal(const InternalNode& n);
+ static LeafNode decode_leaf(const std::vector<uint8_t>& bytes);
+ static InternalNode decode_internal(const std::vector<uint8_t>& bytes);
+ static bool is_leaf_bytes(const std::vector<uint8_t>& bytes);
+
+ // Storage helpers
+ static std::vector<uint8_t> load_node(IStorageBackend& store, const std::string& hash_hex);
+ static std::string store_leaf(IStorageBackend& store, const LeafNode& n);
+ static std::string store_internal(IStorageBackend& store, const InternalNode& n);
+
+ /** @brief Returns the smallest key in the subtree rooted at @p node_hex. */
+ static Key subtree_min_key(IStorageBackend& store, const std::string& node_hex);
+
+ /** @brief Routes a key to the rightmost child whose min_key ≤ target. */
+ static size_t route(const InternalNode& node, const Key& target);
+
+ struct InsertResult {
+ std::string new_hash;
+ uint64_t leaf_count = 0;
+ bool did_split = false;
+ uint64_t split_leaf_count = 0;
+ Key split_min_key{};
+ std::string split_hash;
+ };
+
+ static InsertResult insert_into(IStorageBackend& store, const std::string& node_hex,
+ const Key& key, const Hash32& payload);
+
+ struct RemoveResult {
+ std::string new_hash;
+ uint64_t leaf_count = 0;
+ };
+
+ static RemoveResult remove_from(IStorageBackend& store, const std::string& node_hex,
+ const Key& key);
+
+ static void page_from(IStorageBackend& store, const std::string& node_hex, size_t& offset,
+ size_t limit, std::vector<Entry>& out);
+
+ static std::optional<Hash32> get_from(IStorageBackend& store, const std::string& node_hex,
+ const Key& key);
};
- /**
- * @brief Page through entries in key-sorted order.
- *
- * Descends to the leaf at logical position @p offset using cumulative
- * leaf_counts stored in internal nodes, then walks forward collecting at
- * most @p limit entries. Only the nodes on the active path are loaded;
- * sibling subtrees are never touched.
- */
- static std::vector<Entry> Page(IStorageBackend& store,
- const std::string& root_hex,
- size_t offset,
- size_t limit);
-
-private:
- struct LeafEntry {
- Key key;
- Hash32 payload;
- };
-
- struct LeafNode {
- std::vector<LeafEntry> entries;
- };
-
- struct ChildEntry {
- uint64_t leaf_count;
- Key min_key;
- Hash32 child_hash;
- };
-
- struct InternalNode {
- std::vector<ChildEntry> entries;
- };
-
- // Wire format
- static std::vector<uint8_t> encode_leaf(const LeafNode& n);
- static std::vector<uint8_t> encode_internal(const InternalNode& n);
- static LeafNode decode_leaf(const std::vector<uint8_t>& bytes);
- static InternalNode decode_internal(const std::vector<uint8_t>& bytes);
- static bool is_leaf_bytes(const std::vector<uint8_t>& bytes);
-
- // Storage helpers
- static std::vector<uint8_t> load_node(IStorageBackend& store,
- const std::string& hash_hex);
- static std::string store_leaf(IStorageBackend& store, const LeafNode& n);
- static std::string store_internal(IStorageBackend& store, const InternalNode& n);
-
- /** @brief Returns the smallest key in the subtree rooted at @p node_hex. */
- static Key subtree_min_key(IStorageBackend& store, const std::string& node_hex);
-
- /** @brief Routes a key to the rightmost child whose min_key ≤ target. */
- static size_t route(const InternalNode& node, const Key& target);
-
- struct InsertResult {
- std::string new_hash;
- uint64_t leaf_count = 0;
- bool did_split = false;
- uint64_t split_leaf_count = 0;
- Key split_min_key{};
- std::string split_hash;
- };
-
- static InsertResult insert_into(IStorageBackend& store,
- const std::string& node_hex,
- const Key& key,
- const Hash32& payload);
-
- struct RemoveResult {
- std::string new_hash;
- uint64_t leaf_count = 0;
- };
-
- static RemoveResult remove_from(IStorageBackend& store,
- const std::string& node_hex,
- const Key& key);
-
- static void page_from(IStorageBackend& store,
- const std::string& node_hex,
- size_t& offset,
- size_t limit,
- std::vector<Entry>& out);
-
- static std::optional<Hash32> get_from(IStorageBackend& store,
- const std::string& node_hex,
- const Key& key);
-};
-
} // namespace nt
diff --git a/include/MultigroupCodec.h b/include/MultigroupCodec.h
index 50f7bb8..9d003ea 100644
--- a/include/MultigroupCodec.h
+++ b/include/MultigroupCodec.h
@@ -29,8 +29,7 @@
* payloads to `Merkle<std::string>`.
*/
-namespace nt::MultigroupCodec
-{
+namespace nt::MultigroupCodec {
/** @brief One entry in a multigroup snapshot: (relation_name, root_hex). */
using RelationEntry = std::pair<std::string, std::string>;
@@ -45,8 +44,7 @@ namespace nt::MultigroupCodec
* @param relations Entries to load. Duplicates collapse to the last value.
* @return Root node hash (empty string when `relations` is empty).
*/
- std::string Build(IStorageBackend& store,
- const std::vector<RelationEntry>& relations);
+ std::string Build(IStorageBackend& store, const std::vector<RelationEntry>& relations);
/**
* @brief Enumerate all (name, root_hex) pairs at a multigroup root.
@@ -54,8 +52,7 @@ namespace nt::MultigroupCodec
* Pages the entire tree (offset 0, no limit). Returned entries are in
* key-sorted order. Empty input root yields an empty list.
*/
- std::vector<RelationEntry> List(IStorageBackend& store,
- const std::string& root_hex);
+ std::vector<RelationEntry> List(IStorageBackend& store, const std::string& root_hex);
/**
* @brief Insert or overwrite one (relation_name → root_hex) entry.
@@ -65,25 +62,21 @@ namespace nt::MultigroupCodec
* mutations. Pass an empty `root_hex` for the prior-state argument to
* start from an empty tree.
*/
- std::string InsertOne(IStorageBackend& store,
- const std::string& root_hex,
- const std::string& relation_name,
- const std::string& relation_root_hex);
+ std::string InsertOne(IStorageBackend& store, const std::string& root_hex,
+ const std::string& relation_name, const std::string& relation_root_hex);
/**
* @brief Remove one relation entry from the multigroup tree.
*
* Returns the new root hash; empty when the tree becomes empty.
*/
- std::string RemoveOne(IStorageBackend& store,
- const std::string& root_hex,
+ std::string RemoveOne(IStorageBackend& store, const std::string& root_hex,
const std::string& relation_name);
/**
* @brief Look up one relation's root hex by name.
* @return Hex root, or empty string when the name is absent.
*/
- std::string Lookup(IStorageBackend& store,
- const std::string& root_hex,
+ std::string Lookup(IStorageBackend& store, const std::string& root_hex,
const std::string& relation_name);
-}
+} // namespace nt::MultigroupCodec
diff --git a/include/NT.h b/include/NT.h
index 0fc5514..041c517 100644
--- a/include/NT.h
+++ b/include/NT.h
@@ -5,13 +5,13 @@
* @brief Includes for the Relational NT public API.
*/
-#include "Types.h"
-#include "ObjectManager.h"
-#include "PermissionsManager.h"
-#include "NamespaceReferenceManager.h"
#include "CursorManager.h"
+#include "HandlerManager.h"
#include "IdentityManager.h"
#include "LifecycleManager.h"
-#include "HandlerManager.h"
-#include "VM.h"
+#include "NamespaceReferenceManager.h"
+#include "ObjectManager.h"
+#include "PermissionsManager.h"
#include "Runtime.h"
+#include "Types.h"
+#include "VM.h"
diff --git a/include/NamespaceReferenceManager.h b/include/NamespaceReferenceManager.h
index 3264271..d09f4d4 100644
--- a/include/NamespaceReferenceManager.h
+++ b/include/NamespaceReferenceManager.h
@@ -12,8 +12,7 @@
* @brief Declares logical reference mapping and namespace isolation.
*/
-namespace nt
-{
+namespace nt {
/**
* @class NamespaceReferenceManager
* @brief Handles the logical mapping and isolation of human-readable references.
@@ -67,9 +66,8 @@ namespace nt
* @todo Define the batch-update API with all-or-nothing contention semantics.
* See docs/reactos-ob-comparison.md §8.
*/
- class NamespaceReferenceManager
- {
- public:
+ class NamespaceReferenceManager {
+ public:
/**
* @brief Constructs a NamespaceReferenceManager bound to a registry.
* @param objects Registry used to look up reference objects (branches,
@@ -78,8 +76,7 @@ namespace nt
* nodes when resolving `/system/branches/<n>/<mg>/...`
* paths through to their snapshot.
*/
- NamespaceReferenceManager(ObjectManager& objects,
- IStorageBackend& storage);
+ NamespaceReferenceManager(ObjectManager& objects, IStorageBackend& storage);
/**
* @brief Rewrites a logical path through reference reparse rules.
@@ -103,8 +100,8 @@ namespace nt
*/
std::vector<std::string> Resolve(std::vector<std::string> path) const;
- private:
- ObjectManager& objects_;
+ private:
+ ObjectManager& objects_;
IStorageBackend& storage_;
};
-}
+} // namespace nt
diff --git a/include/ObjectManager.h b/include/ObjectManager.h
index 1391508..9ea49e6 100644
--- a/include/ObjectManager.h
+++ b/include/ObjectManager.h
@@ -16,8 +16,7 @@
* @brief Declares the registry responsible for runtime-managed database objects.
*/
-namespace nt
-{
+namespace nt {
/**
* @brief Owns the registry used to locate and reference database objects.
*
@@ -25,12 +24,11 @@ namespace nt
* the metadata needed to reason about object type, path, references, and
* handles while the concrete storage model is still being designed.
*/
- class ObjectManager
- {
- public:
+ class ObjectManager {
+ public:
/** @brief Base type for objects stored in the registry. */
class IObject {
- public:
+ public:
virtual ~IObject() = default;
};
@@ -52,7 +50,7 @@ namespace nt
* pins it, no pinned cursor still references it).
*/
class Multigroup : public IObject {
- public:
+ public:
std::string merkle_root;
};
/**
@@ -63,7 +61,7 @@ namespace nt
* Updated atomically by rnt_link_tuple / rnt_unlink_tuple / rnt_clear_relation.
*/
class Relation : public IObject {
- public:
+ public:
std::string merkle_root;
};
/**
@@ -96,8 +94,8 @@ namespace nt
* path this remains a documentation-only contract.
*/
class EphemeralRelation : public IObject {
- public:
- std::string merkle_root;
+ public:
+ std::string merkle_root;
std::vector<std::string> dependencies;
};
/** @brief Abstract registry object representing a transaction. */
@@ -125,7 +123,7 @@ namespace nt
* the walk hot.
*/
class Session : public IObject {
- public:
+ public:
void* connection_context = nullptr;
std::map<std::string, std::string> branch_overrides;
};
@@ -147,7 +145,7 @@ namespace nt
* Multigroups and operate on those.
*/
class Branch : public IObject {
- public:
+ public:
std::string name;
std::string target_hash;
};
@@ -165,7 +163,7 @@ namespace nt
* each multigroup it references before unregistering the entry.
*/
class BranchTree : public IObject {
- public:
+ public:
std::string merkle_root;
};
@@ -224,8 +222,7 @@ namespace nt
* maps `offset` to the appropriate pair via a bijective enumeration scheme
* (e.g. Cantor pairing); callers must bound such scans with a TAKE node.
*/
- struct ephemeral_object_type : object_type
- {
+ struct ephemeral_object_type : object_type {
enum class Cardinality { Finite, ConstrainedFinite, AlephZero, Continuum };
/**
@@ -235,12 +232,10 @@ namespace nt
* @param limit Maximum number of tuples to return.
*/
using Generator = std::function<std::vector<Tuple>(
- const std::vector<std::string>& args,
- std::size_t offset,
- std::size_t limit)>;
+ const std::vector<std::string>& args, std::size_t offset, std::size_t limit)>;
Cardinality cardinality;
- Generator generator;
+ Generator generator;
};
/**
@@ -313,8 +308,7 @@ namespace nt
* @param object Object payload. Ownership is transferred to the registry.
* @param type Object type descriptor. Ownership is transferred to the registry.
*/
- void Register(std::vector<std::string> path,
- std::unique_ptr<IObject> object,
+ void Register(std::vector<std::string> path, std::unique_ptr<IObject> object,
std::unique_ptr<object_type> type);
/**
@@ -338,4 +332,4 @@ namespace nt
*/
bool Unregister(const std::vector<std::string>& object_path);
};
-}
+} // namespace nt
diff --git a/include/PermissionsManager.h b/include/PermissionsManager.h
index 3af75f6..af72154 100644
--- a/include/PermissionsManager.h
+++ b/include/PermissionsManager.h
@@ -11,8 +11,7 @@
* @brief Declares authentication and object-access checks.
*/
-namespace nt
-{
+namespace nt {
/**
* @class Capability-based permission manager
* @brief Evaluates connection claims and object permissions.
@@ -37,9 +36,8 @@ namespace nt
* rather than re-evaluating the descriptor on every call.
* See docs/reactos-ob-comparison.md §4.
*/
- class PermissionsManager
- {
- public:
+ class PermissionsManager {
+ public:
/**
* @brief Validates a connection during login.
* @param method Authentication method used by the connection.
@@ -62,7 +60,7 @@ namespace nt
* 3 other stored relations, while you can access the ephemeral relation,
* you cannot directly access the other 3 relations. You need explicit
* permission to create a handle on the others.
- *
+ *
* Here's an example tree:
* /system
* /multigroups
@@ -70,22 +68,21 @@ namespace nt
* /relations
* /user {type : stored}
* /order {type : stored}
- * /user_and_order {type : ephemeral; deps = [/system/multigroups/coffee_shop/relations/users, /system/multigroups/coffee_shop/relations/orders]}
- * /users
- * /peter
- * /permissions
+ * /user_and_order {type : ephemeral; deps =
+ * [/system/multigroups/coffee_shop/relations/users,
+ * /system/multigroups/coffee_shop/relations/orders]} /users /peter /permissions
* /multigroups/coffee_shop/relations/user_and_order {descriptor : [read]}
* /paul
* /permissions
* /multigroups/coffee_shop/relations/user {descriptor : [write, read]}
- *
+ *
* Meaning that `peter` has access to read the `user_and_order` ephemeral
* relation, but cannot open a handle on `user` and `order`.
- *
+ *
* @param object Object being accessed.
* @param connection_context Connection metadata for the caller.
* @return True when access is allowed.
*/
const bool Access(const ObjectManager::registry* object, const void* connection_context);
};
-}
+} // namespace nt
diff --git a/include/RNT_C_API.h b/include/RNT_C_API.h
index 707c04a..1a59785 100644
--- a/include/RNT_C_API.h
+++ b/include/RNT_C_API.h
@@ -36,6 +36,7 @@
#include <stdint.h>
#include "Api.h"
+#include "VM.h"
#ifdef __cplusplus
extern "C" {
@@ -133,8 +134,7 @@ NT_API int rnt_session_close(const char* session_hash);
* @param target_hash Snapshot hash to bind, or "" to clear.
* @return 0 on success, negative on error.
*/
-NT_API int rnt_session_set_branch(const char* session_hash,
- const char* branch_name,
+NT_API int rnt_session_set_branch(const char* session_hash, const char* branch_name,
const char* target_hash);
/* ------------------------------------------------------------------ */
@@ -292,9 +292,7 @@ NT_API int rnt_list_snapshot_relations(const char* snapshot_hash, char** out);
* Release with rnt_free_string(). NULL on error.
* @return 0 on success, negative on error.
*/
-NT_API int rnt_link_tuple(const char* relation_path,
- const char* kv_attrs,
- char** hash_out);
+NT_API int rnt_link_tuple(const char* relation_path, const char* kv_attrs, char** hash_out);
/**
* @brief Removes a tuple from the relation's Merkle tree and tuple store.
@@ -377,40 +375,78 @@ NT_API int rnt_cursor_close(rnt_cursor_t cursor);
/* VM plan builder */
/* ------------------------------------------------------------------ */
-/** Opaque plan node tree, built incrementally via rnt_plan_* calls. */
+/** Opaque plan node tree, built via rnt_plan_assemble calls. */
typedef void* rnt_plan_t;
/**
- * @brief Creates a SCAN plan node that reads all tuples from a stored relation.
+ * SCAN context: reads all tuples from a stored relation.
*
- * Opens a RELATION handle and cursor internally. Both are transferred to the
- * plan and released when the resulting VM cursor is closed.
- *
- * @param relation_path Absolute slash-separated path to the relation, e.g.
+ * @param relation_path Absolute slash-separated path, e.g.
* "/system/branches/main/multigroups/warehouse/relations/public:users".
- * @return Plan node, or NULL when the relation does not exist or cannot be opened.
*/
-NT_API rnt_plan_t rnt_plan_scan(const char* relation_path);
+typedef struct {
+ const char* relation_path;
+} PlanArgsScan;
/**
- * @brief Creates a nested-loop JOIN plan node.
+ * JOIN context: nested-loop join of two child plans.
*
- * Takes ownership of both @p left and @p right. On success the caller must not
- * free either child; they are released when the returned plan is freed or
- * executed. On failure (NULL return) both children are freed.
+ * Takes ownership of both children. They are released when the assembled plan
+ * is freed or executed; on failure both are freed.
+ */
+typedef struct {
+ rnt_plan_t left;
+ rnt_plan_t right;
+} PlanArgsJoin;
+
+/**
+ * TAKE context: passes at most @p limit tuples from @p source, then stops.
*
- * @return Plan node, or NULL on error.
+ * Takes ownership of @p source; on failure @p source is freed.
+ */
+typedef struct {
+ rnt_plan_t source;
+ size_t limit;
+} PlanArgsTake;
+
+/**
+ * PROJECT context: keeps only the named attributes of @p source.
+ *
+ * @p attrs is a NULL-terminated array of attribute names to retain, e.g.
+ * <tt>{ "name", "profession", NULL }</tt>. Takes ownership of @p source; on
+ * failure @p source is freed.
+ */
+typedef struct {
+ rnt_plan_t source;
+ const char** attrs;
+} PlanArgsProject;
+
+/**
+ * A single plan-construction request. @p operation selects which context member
+ * is read; the others are ignored. The members are laid out side by side rather
+ * than overlapped in a union so the struct maps cleanly onto OCaml ctypes, which
+ * has no union support. Only the member matching @p operation need be populated.
*/
-NT_API rnt_plan_t rnt_plan_join(rnt_plan_t left, rnt_plan_t right);
+typedef struct {
+ nt::Operation operation;
+ PlanArgsScan scan;
+ PlanArgsJoin join;
+ PlanArgsTake take;
+ PlanArgsProject project;
+} PlanAction;
/**
- * @brief Creates a TAKE plan node that limits output to at most @p limit tuples.
+ * @brief Builds one plan node from @p action and returns the resulting subtree.
*
- * Takes ownership of @p source. On failure @p source is freed.
+ * Sole entry point for plan construction. Validates runtime state once, then
+ * dispatches on @p 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.
*
- * @return Plan node, or NULL on error.
+ * @return Plan node, or NULL when the runtime is uninitialised or construction
+ * fails (e.g. relation does not exist).
*/
-NT_API rnt_plan_t rnt_plan_take(rnt_plan_t source, size_t limit);
+NT_API rnt_plan_t rnt_plan_assemble(PlanAction action);
/**
* @brief Releases a plan that was built but not yet executed.
diff --git a/include/Runtime.h b/include/Runtime.h
index 4abe8c7..0fb41a5 100644
--- a/include/Runtime.h
+++ b/include/Runtime.h
@@ -7,12 +7,10 @@
* @brief Declares the top-level Relational NT runtime facade.
*/
-namespace nt
-{
+namespace nt {
/** @brief Top-level runtime object used by applications and the console entry point. */
- class NT
- {
- public:
+ class NT {
+ public:
/**
* @brief Reports whether the runtime is active.
* @return True when the runtime is running.
@@ -22,4 +20,4 @@ namespace nt
/** @brief Simulates an external entry call into the runtime. */
void SimulateEntryCall();
};
-}
+} // namespace nt
diff --git a/include/SqliteBackend.h b/include/SqliteBackend.h
index e4cdf56..037d8e6 100644
--- a/include/SqliteBackend.h
+++ b/include/SqliteBackend.h
@@ -21,11 +21,9 @@
* via Merkle::Page which reads only the KV store.
*/
-namespace nt
-{
- class SqliteBackend : public IStorageBackend
- {
- public:
+namespace nt {
+ class SqliteBackend : public IStorageBackend {
+ public:
/**
* @brief Opens (or creates) a SQLite database at @p path.
* @param path File path, or ":memory:" for an in-process database.
@@ -37,7 +35,7 @@ namespace nt
std::string Put(std::vector<uint8_t> value) override;
std::optional<std::vector<uint8_t>> Get(const std::string& hash) override;
- private:
+ private:
sqlite3* db_ = nullptr;
};
-}
+} // namespace nt
diff --git a/include/TupleCodec.h b/include/TupleCodec.h
index 18294d4..6c74c1e 100644
--- a/include/TupleCodec.h
+++ b/include/TupleCodec.h
@@ -23,8 +23,7 @@
* [uint32_le name_len][name bytes][uint32_le value_len][value bytes] ...
*/
-namespace nt::TupleCodec
-{
+namespace nt::TupleCodec {
/**
* @brief Computes the SHA256 hex digest of the serialized tuple.
*
@@ -49,4 +48,4 @@ namespace nt::TupleCodec
* @return Reconstructed attribute list in serialization order.
*/
std::vector<Attribute> Deserialize(const std::vector<uint8_t>& bytes);
-}
+} // namespace nt::TupleCodec
diff --git a/include/Types.h b/include/Types.h
index edf4297..6956e09 100644
--- a/include/Types.h
+++ b/include/Types.h
@@ -118,8 +118,7 @@ enum AUTH_METHOD {
PLAIN_TEXT
};
-namespace nt
-{
+namespace nt {
/** @brief A single named value in a tuple, produced by the cursor layer. */
struct Attribute {
std::string name;
@@ -133,9 +132,9 @@ namespace nt
* one attribute at a time. Returns nullptr when all attributes are exhausted.
*/
class Tuple {
- public:
- explicit Tuple(std::vector<Attribute> attributes)
- : attributes_(std::move(attributes)) {}
+ public:
+ explicit Tuple(std::vector<Attribute> attributes) : attributes_(std::move(attributes)) {
+ }
/** @brief Returns the next attribute, or nullptr when exhausted. */
const Attribute* Next() {
@@ -144,13 +143,17 @@ namespace nt
return nullptr;
}
- void Reset() { position_ = 0; }
+ void Reset() {
+ position_ = 0;
+ }
/** @brief Direct read-only access to all attributes without affecting position. */
- const std::vector<Attribute>& attrs() const { return attributes_; }
+ const std::vector<Attribute>& attrs() const {
+ return attributes_;
+ }
- private:
+ private:
std::vector<Attribute> attributes_;
size_t position_ = 0;
};
-}
+} // namespace nt
diff --git a/include/VM.h b/include/VM.h
index 3bfe521..3d97779 100644
--- a/include/VM.h
+++ b/include/VM.h
@@ -14,8 +14,7 @@
* @brief Declares the logic execution boundary for relational and higher-order workloads.
*/
-namespace nt
-{
+namespace nt {
/**
* @class VM
* @brief Hosts the first-order logic (FOL) and second-order logic (SOL) cores.
@@ -64,15 +63,25 @@ namespace nt
* (for EPHEMERAL_RELATION cursors) or ignored (for stored RELATION cursors,
* which need no per-probe parameterization).
*/
- struct PathArg
- {
+ struct PathArg {
enum class Kind { Var, Const };
- Kind kind;
+ Kind kind;
std::string name; /**< Attribute name to look up (Var), or literal value (Const). */
- static PathArg Var(std::string attr) { return { Kind::Var, std::move(attr) }; }
- static PathArg Const(std::string val) { return { Kind::Const, std::move(val) }; }
+ static PathArg Var(std::string attr) {
+ return {Kind::Var, std::move(attr)};
+ }
+ static PathArg Const(std::string val) {
+ return {Kind::Const, std::move(val)};
+ }
+ };
+
+ enum Operation {
+ FOL_OPERATION_SCAN = 1,
+ FOL_OPERATION_JOIN,
+ FOL_OPERATION_TAKE,
+ FOL_OPERATION_PROJECT
};
/**
@@ -91,12 +100,9 @@ namespace nt
* this to bound scans over AlephZero ephemeral relations.
* - PROJECT: filters each input tuple to the named attributes in project_attrs.
*/
- struct PlanNode
- {
- enum class Op { SCAN, JOIN, TAKE, PROJECT };
-
- Op op;
- PlanNode* left = nullptr;
+ struct PlanNode {
+ Operation op;
+ PlanNode* left = nullptr;
PlanNode* right = nullptr;
/**
@@ -134,13 +140,12 @@ namespace nt
* successful join. Callers must consume the returned pointer before
* calling Next() again — same contract as a cursor page pointer.
*/
- Tuple* join_left = nullptr;
+ Tuple* join_left = nullptr;
std::optional<Tuple> join_buffer;
};
- class VM
- {
- public:
+ class VM {
+ public:
// TODO: CursorManager should be injected as a shared runtime instance,
// matching the pattern flagged for HandlerManager and LifecycleManager.
//
@@ -167,21 +172,19 @@ namespace nt
*/
Tuple* Next(PlanNode* node);
- private:
+ private:
CursorManager& cursors_;
/**
* Resolves a scan_args template against an outer tuple, producing the
* concrete args vector to write into the inner cursor before probing.
*/
- static std::vector<std::string> ResolveArgs(const std::vector<PathArg>& tmpl,
- Tuple* from);
+ static std::vector<std::string> ResolveArgs(const std::vector<PathArg>& tmpl, Tuple* from);
/** Resets the inner cursor state and writes resolved args into it. */
- static void ResetInner(CursorManager::cursor* c,
- std::vector<std::string> args);
+ static void ResetInner(CursorManager::cursor* c, std::vector<std::string> args);
/** Merges left and right tuple attributes into node->join_buffer. */
static Tuple* MergeInto(PlanNode* node, Tuple* left, Tuple* right);
};
-}
+} // namespace nt