aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorMarcos Magueta <maguetamarcos@gmail.com>2026-05-10 02:27:08 -0300
committerMarcos Magueta <maguetamarcos@gmail.com>2026-05-10 02:27:08 -0300
commit7ffd4d99bbb8e358c6694c27c7ff859967872ece (patch)
tree8af04f4032651de7e49d1cac01e6f20b2315b6cb /include
parent5ee324f03f8a7e6f09dad7b8580a2d32172694f8 (diff)
downloadRNT-7ffd4d99bbb8e358c6694c27c7ff859967872ece.tar.gz
RNT-7ffd4d99bbb8e358c6694c27c7ff859967872ece.zip
comparison to nt ob
Diffstat (limited to '')
-rw-r--r--include/HandlerManager.h26
-rw-r--r--include/IdentityManager.h24
-rw-r--r--include/LifecycleManager.h93
-rw-r--r--include/NamespaceReferenceManager.h54
-rw-r--r--include/ObjectManager.h77
-rw-r--r--include/PermissionsManager.h16
6 files changed, 237 insertions, 53 deletions
diff --git a/include/HandlerManager.h b/include/HandlerManager.h
index 4f63f17..f3d504e 100644
--- a/include/HandlerManager.h
+++ b/include/HandlerManager.h
@@ -2,7 +2,9 @@
#include "Api.h"
#include "ObjectManager.h"
+#include "Types.h"
+#include <set>
#include <string>
#include <vector>
@@ -36,15 +38,33 @@ namespace nt
/**
* @brief Represents authorized access to an object in the registry.
*
- * This increases the handle count in the object manager. We should
- * consider adding a vector to the object manager with all handles that
- * refer to an object.
+ * The access mask is evaluated once during Open and cached here for the
+ * lifetime of the handle. Subsequent operations check `granted_access`
+ * rather than re-evaluating the security descriptor on every call. This
+ * resolves the performance question in PermissionsManager about when to
+ * check permissions.
+ *
+ * Because storage is append-only, a WRITE claim does not mean mutating an
+ * existing tuple in-place. It means the session is authorized to commit a
+ * new snapshot version of the relation. Two sessions holding WRITE handles
+ * on the same relation always produce independent snapshots — there is no
+ * data-level conflict.
+ *
+ * @todo Populate `granted_access` inside HandlerManager::Open from
+ * PermissionsManager::Firewall / Access. See docs/reactos-ob-comparison.md §4.
*/
struct handle {
/** Object referenced by this handle. */
ObjectManager::registry* object = nullptr;
/** Connection metadata associated with the authorized access. */
void* connection_context = nullptr;
+ /**
+ * Access claims granted to this handle at open time.
+ * Cached here so that per-operation checks read from the handle
+ * rather than re-evaluating the security descriptor.
+ * @todo Populate in HandlerManager::Open.
+ */
+ std::set<AUTH_CLAIM> granted_access;
};
/**
diff --git a/include/IdentityManager.h b/include/IdentityManager.h
index 0e2d08f..5c8dd14 100644
--- a/include/IdentityManager.h
+++ b/include/IdentityManager.h
@@ -10,19 +10,37 @@
namespace nt
{
- /** @brief Checks whether an object supports identity-level operations. */
+ /**
+ * @brief Checks whether an object supports identity-level operations.
+ *
+ * @todo Migrate to type callbacks. Once `object_type` holds `OpenProcedure`
+ * and `CloseProcedure` function pointers, CanOpen / CanClose become
+ * thin dispatchers that invoke the corresponding procedure — or this
+ * manager is absorbed into HandlerManager directly. The function pointer
+ * should be accompanied by a `const char* name` label on `object_type`
+ * so that error logs identify the type without dereferencing the pointer.
+ * See docs/reactos-ob-comparison.md §2.
+ */
class NT_API IdentityManager
{
public:
/**
- * @brief Looks into the methods of the object type and asserts if it can be opened.
+ * @brief Returns true when the object's type supports being opened.
+ *
+ * Currently checks that the object is non-null (stub). Should invoke
+ * `object_type::OpenProcedure` once callbacks are defined.
+ *
* @param object Object to inspect.
* @return True when the object can be opened.
*/
const bool CanOpen(ObjectManager::registry* object);
/**
- * @brief Checks whether an object can be closed.
+ * @brief Returns true when the object's type supports being closed.
+ *
+ * Currently checks that the object is non-null (stub). Should invoke
+ * `object_type::CloseProcedure` once callbacks are defined.
+ *
* @param object Object to inspect.
* @return True when the object can be closed.
*/
diff --git a/include/LifecycleManager.h b/include/LifecycleManager.h
index 914ce0a..8126820 100644
--- a/include/LifecycleManager.h
+++ b/include/LifecycleManager.h
@@ -10,53 +10,92 @@
namespace nt
{
- /** @brief Manages runtime lifecycle concerns for registry objects. */
+ /**
+ * @brief Manages runtime lifecycle concerns for registry objects.
+ *
+ * Object lifetime is governed by two independent counters in registry_head:
+ * `handle_count` (sessions holding an open handle) and `reference_count`
+ * (structural dependencies such as cursors pinned to a snapshot or views
+ * referencing base relations). An object is eligible for GC only when both
+ * reach zero.
+ *
+ * Monitor / Unmonitor manage `handle_count`. Pin / Unpin manage
+ * `reference_count`. See docs/reactos-ob-comparison.md §1.
+ */
class NT_API LifecycleManager
{
public:
/**
* @brief Starts monitoring an object's lifecycle.
*
- * If the object is not being monitored already, monitor the lifecycle
- * by updating the handle count. Maybe also look at the reference count
- * and kill some categories of disposable objects no longer referenced
- * by other objects, like transactions.
- *
- * One use case is preventing compaction/pruning of history while
- * cursors depend on old database snapshots, for example. Think of
- * other use cases later.
+ * Increments `handle_count` on the object's registry_head. Should be
+ * called after all authorization checks pass inside HandlerManager::Open.
*
* @param object Object to monitor.
*/
void Monitor(ObjectManager::registry* object);
/**
- * @brief Serializes contention for changes to mutable references.
+ * @brief Stops monitoring an object.
*
- * This can be used for the HEAD of a branch to serialize access. If the
- * object does not cause contention, such as a relation, then this can
- * approve the operation because relations and multigroups are immutable
- * snapshots. Transactions also do not cause contention.
+ * Decrements `handle_count`. When both `handle_count` and
+ * `reference_count` reach zero, the object becomes eligible for GC.
*
- * The objects that do cause contention are mutable reference states in
- * shared sessions. Examples include the HEAD of a branch, namespace
- * collisions, multi-branch atomic commits (which may damage isolation),
- * and garbage collection of old state when old-enough history is removed
- * to save space.
+ * @todo Gate GC on both counters reaching zero, not just handle_count.
+ * For deferred compaction, enqueue onto a background GC list rather
+ * than freeing inline. See docs/reactos-ob-comparison.md §1 and §7.
*
- * @param object Object to check for contention.
- * @return True when the operation may proceed.
+ * @param object Object to stop monitoring.
*/
- const bool Contention(ObjectManager::registry* object);
+ void Unmonitor(ObjectManager::registry* object);
/**
- * @brief Stops monitoring an object.
+ * @brief Increments the structural dependency count on an object.
*
- * The inverse of Monitor. Maybe garbage collect here also if the
- * counters go to zero.
+ * Call when one object takes a dependency on another — for example when
+ * a cursor pins an immutable snapshot version, or when a view is
+ * registered against its base relations. Prevents GC of the target object
+ * while the dependency is live.
*
- * @param object Object to stop monitoring.
+ * @todo Implement. See docs/reactos-ob-comparison.md §1.
+ *
+ * @param object Object being depended upon.
*/
- void Unmonitor(ObjectManager::registry* object);
+ void Pin(ObjectManager::registry* object);
+
+ /**
+ * @brief Decrements the structural dependency count on an object.
+ *
+ * The inverse of Pin. When both `reference_count` and `handle_count`
+ * reach zero the object becomes eligible for GC.
+ *
+ * @todo Implement. See docs/reactos-ob-comparison.md §1.
+ *
+ * @param object Object whose dependency is being released.
+ */
+ void Unpin(ObjectManager::registry* object);
+
+ /**
+ * @brief Serializes contention for changes to mutable reference states.
+ *
+ * Immutable objects — relation snapshots, multigroup snapshots,
+ * transactions — never raise contention. Two sessions opening the same
+ * immutable snapshot simultaneously is always safe; they will produce
+ * independent results without conflict.
+ *
+ * Contention applies only to mutable reference states: the HEAD of a
+ * branch and namespace entries targeted by atomic multi-reference updates.
+ * These are the sole mutable pointers in the system. When a session holds
+ * a write handle on a HEAD, a second write opener must block or fail.
+ *
+ * @todo Implement: read `object_type::exclusive`. Return false immediately
+ * for non-exclusive objects. For exclusive objects, return false
+ * (contention detected) when `handle_count > 0` for a write-mode
+ * opener. See docs/reactos-ob-comparison.md §6.
+ *
+ * @param object Object to check for contention.
+ * @return True when the operation may proceed.
+ */
+ const bool Contention(ObjectManager::registry* object);
};
}
diff --git a/include/NamespaceReferenceManager.h b/include/NamespaceReferenceManager.h
index 59068f7..0bf00bc 100644
--- a/include/NamespaceReferenceManager.h
+++ b/include/NamespaceReferenceManager.h
@@ -13,20 +13,50 @@ namespace nt
* @class NamespaceReferenceManager
* @brief Handles the logical mapping and isolation of human-readable references.
*
- * Design notes:
- * - Namespace isolation: allow private branch shadowing, such as
- * /user_a/refs/branch/abc. To preserve lookup clarity, protocol-level
- * syntax must explicitly define scope and prevent non-deterministic
- * shadowing during resolution.
+ * This manager is the reparse layer of the namespace. Its design mirrors the
+ * ReactOS ParseProcedure / STATUS_REPARSE mechanism: a namespace entry whose
+ * type carries a ParseProcedure can redirect name resolution to a different
+ * path, allowing branch references and views to appear as first-class objects
+ * in the namespace without exposing their physical storage paths directly.
*
- * - Multi-reference atomic updates: ensure updates to multiple references,
- * such as pushing to master and audit_log simultaneously, are
- * all-or-nothing. If any contention check fails, the whole batch is
- * aborted to prevent partial commits and preserve audit consistency.
+ * **Branch references.**
+ * A path such as `/refs/branch/main` is a namespace entry backed by a
+ * reference object. Its ParseProcedure rewrites the path to the physical
+ * snapshot path (e.g. `/snapshots/abc123`). The caller's handle lands on the
+ * snapshot. To advance the HEAD, the caller must explicitly open the reference
+ * object itself with WRITE access, which is the sole contention point for that
+ * branch.
*
- * Audit needs global access, which means it should be dissociated from a
- * branch scope. Since branches are the only contention points for
- * references, it makes sense to model audit as an independent branch too.
+ * **View resolution.**
+ * A view is an ephemeral RELATION whose ParseProcedure reparses to its base
+ * relations internally on behalf of the runtime. The caller's handle and access
+ * mask remain bound to the view. The base relations are accessed only via the
+ * view's own type callbacks; the caller never receives a handle on them and
+ * does not need explicit permission on them. Capability security is enforced at
+ * the view boundary, not the base relation boundary.
+ *
+ * **Atomic multi-reference updates.**
+ * Updating multiple references simultaneously (e.g. advancing both `main` and
+ * `audit_log`) must be all-or-nothing. The implementation should acquire
+ * exclusive locks on all target namespace entries before modifying any. If
+ * LifecycleManager::Contention fails on any entry, all locks are released and
+ * the batch is aborted. This preserves audit consistency.
+ *
+ * **Cycle guard.**
+ * View definitions may reference other views, and branch aliases may chain.
+ * Name resolution must track reparse depth and return an error after a bounded
+ * number of iterations to prevent infinite cycles.
+ *
+ * **Audit branch.**
+ * Audit requires global access dissociated from any data branch. It should be
+ * modelled as an independent branch; its HEAD is the only contention point for
+ * audit-affecting operations.
+ *
+ * @todo Implement `Resolve(path)` with a reparse loop and cycle depth guard.
+ * @todo Define the reference object type with `object_type::exclusive = true`
+ * and a ParseProcedure that rewrites the resolution path.
+ * @todo Define the batch-update API with all-or-nothing contention semantics.
+ * See docs/reactos-ob-comparison.md §8.
*/
class NT_API NamespaceReferenceManager
{
diff --git a/include/ObjectManager.h b/include/ObjectManager.h
index aab3a6f..4b537f7 100644
--- a/include/ObjectManager.h
+++ b/include/ObjectManager.h
@@ -39,21 +39,75 @@ namespace nt
/** @brief Abstract registry object representing a transaction. */
class Transaction : public IObject {};
- /** @brief Describes the behavior and capabilities of an object category. */
+ /**
+ * @brief Describes the behavior and capabilities of an object category.
+ *
+ * @todo Replace `methods` with typed callback fields: `OpenProcedure`,
+ * `CloseProcedure`, `DeleteProcedure`, and `ParseProcedure`.
+ * Store a `const char* name` label alongside each callback so that
+ * logs and assertions can identify which type fired without having
+ * to dereference a pointer. `IdentityManager::CanOpen` / `CanClose`
+ * then become thin dispatchers that invoke the corresponding
+ * procedure, or are absorbed into `HandlerManager` directly.
+ * See docs/reactos-ob-comparison.md §2.
+ *
+ * @todo Add an `exclusive` flag for mutable reference objects (branch
+ * HEADs, namespace entries). Non-exclusive objects — immutable
+ * snapshots, transactions — must skip contention checks entirely.
+ * See docs/reactos-ob-comparison.md §6.
+ */
struct object_type {
/** Object category label. */
OBJECT_TYPE label;
/** True when the object is not durable. For example: TRANSACTION. */
bool disposable;
- /** Methods supported by this object type. */
+ /**
+ * Methods supported by this object type.
+ * @todo Replace with typed callback function pointers. See class-level todo.
+ */
std::set<METHOD> methods;
+ /**
+ * When true, only one write-mode handle may be open at a time.
+ * Applies to mutable reference states such as branch HEADs.
+ * Immutable snapshot objects must leave this false.
+ * @todo Wire into LifecycleManager::Contention.
+ */
+ bool exclusive = false;
};
- /** @brief Shared metadata stored at the head of a registry entry. */
+ /**
+ * @brief Shared metadata stored at the head of a registry entry.
+ *
+ * Two independent reference counters govern object lifetime.
+ * An object is eligible for garbage collection only when both reach zero:
+ *
+ * - `handle_count` — open sessions holding a cursor or handle on this object.
+ * Managed exclusively by LifecycleManager::Monitor / Unmonitor.
+ * - `reference_count` — structural dependencies such as a view referencing its
+ * base relations, or a cursor pinned to an immutable snapshot version.
+ * Managed by LifecycleManager::Pin / Unpin (not yet implemented).
+ *
+ * All snapshot versions are immutable. An insertion or deletion produces a new
+ * snapshot rather than mutating an existing one. A snapshot's `reference_count`
+ * is non-zero while any cursor is pinned to it and drops to zero only when all
+ * such cursors are released.
+ *
+ * @todo Implement `reference_count` tracking. Add LifecycleManager::Pin /
+ * Unpin. Update LifecycleManager::Unmonitor to gate GC on both counters
+ * reaching zero. See docs/reactos-ob-comparison.md §1.
+ *
+ * @todo Define and attach a security_descriptor. When added, store it as a
+ * pointer into a shared, content-addressed SD cache rather than inline.
+ * Permissions are strictly capability-based and must never be inherited
+ * from a parent namespace entry. See docs/reactos-ob-comparison.md §5.
+ */
struct registry_head {
- // TODO: Increment reference_count when one registry object depends on another
- // (e.g. an ephemeral view that references base relations). Decrement when the
- // dependency is removed. Used to block cleanup of objects still referenced by others.
+ /**
+ * Structural dependency count. Non-zero while another registry object
+ * references this one (e.g. a view depending on a base relation, or a
+ * cursor pinned to a snapshot version).
+ * @todo Implement via LifecycleManager::Pin / Unpin.
+ */
uint32_t reference_count = 0;
/** Number of open handles. Maintained by LifecycleManager::Monitor/Unmonitor. */
uint32_t handle_count = 0;
@@ -61,7 +115,6 @@ namespace nt
std::unique_ptr<object_type> type;
/** Logical object path inside the namespace. */
std::vector<std::string> path;
- /** security_descriptor to be added later, maybe also a set of labels */
};
/** @brief Node in the object registry. */
@@ -70,7 +123,15 @@ namespace nt
std::unique_ptr<registry_head> head;
/** Abstract object payload. Owned by this entry. */
std::unique_ptr<IObject> object;
- /** TODO: Treat as a list for now, but ideally it is a tree. */
+ /**
+ * Next entry in the registry. Currently a flat linked list.
+ * @todo Replace with a trie whose nodes are per-path-segment hash maps.
+ * Each directory level holds a hash map from segment string to
+ * child registry*. Find() and Register() walk the trie
+ * component-by-component instead of scanning a flat list.
+ * Consider pulling a well-tested radix-tree via vcpkg rather than
+ * implementing from scratch. See docs/reactos-ob-comparison.md §3.
+ */
std::unique_ptr<registry> next;
};
diff --git a/include/PermissionsManager.h b/include/PermissionsManager.h
index 65c00e5..2db1784 100644
--- a/include/PermissionsManager.h
+++ b/include/PermissionsManager.h
@@ -20,6 +20,22 @@ namespace nt
* Permission checks are intentionally separated from lookup. The object
* manager can retrieve a candidate object, while this manager decides
* whether the caller is allowed to use it.
+ *
+ * Permissions are strictly capability-based and must be explicitly granted.
+ * There is no implicit flow of access rights from a parent namespace entry to
+ * its children (no SD inheritance). A caller who holds READ on a multigroup
+ * does not thereby hold READ on its constituent relations — that is a separate,
+ * explicit capability.
+ *
+ * @todo Define a security_descriptor structure. Store instances in a shared,
+ * content-addressed cache (keyed by descriptor content, not by namespace
+ * ancestry) so that identical ACLs are not duplicated across relations.
+ * See docs/reactos-ob-comparison.md §5 and §7.
+ *
+ * @todo Cache the result of Access() in HandlerManager::handle::granted_access
+ * at open time. Per-operation checks should then read from the handle
+ * rather than re-evaluating the descriptor on every call.
+ * See docs/reactos-ob-comparison.md §4.
*/
class NT_API PermissionsManager
{