From c375b1c69665ae7c16ffa3f17264386dfc257d8e Mon Sep 17 00:00:00 2001 From: Marcos Magueta Date: Sat, 9 May 2026 23:03:00 -0300 Subject: FOL VM with cursor mocked storage --- src/CursorManager.cpp | 45 +++++++++++++++++++++++++++++ src/HandlerManager.cpp | 35 +++++++++++----------- src/LifecycleManager.cpp | 4 +++ src/NT.cpp | 75 ++++++++++++++++++++++++++++++++++++++++++++++-- src/ObjectManager.cpp | 26 ++++++++++++++++- src/VM.cpp | 15 ++++++++++ 6 files changed, 181 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/CursorManager.cpp b/src/CursorManager.cpp index 8ae4496..f80ac54 100644 --- a/src/CursorManager.cpp +++ b/src/CursorManager.cpp @@ -1,5 +1,50 @@ #include "CursorManager.h" +#include + namespace nt { + static std::string JoinPath(const std::vector& path) + { + return std::accumulate( + std::next(path.begin()), path.end(), path.front(), + [](std::string a, const std::string& b) { return std::move(a) + "/" + b; }); + } + + CursorManager::cursor* CursorManager::Open(HandlerManager::handle* handle) + { + if (handle == nullptr || handle->object == nullptr) + return nullptr; + + if (handle->object->head->type->label != RELATION) + return nullptr; + + const std::string key = JoinPath(handle->object->head->path); + auto it = mock_store_.find(key); + if (it == mock_store_.end()) + return nullptr; + + auto* c = new cursor(); + c->handle = handle; + for (const auto& row : it->second) + c->tuples.emplace_back(row); + return c; + } + + Tuple* CursorManager::Next(cursor* cursor) + { + if (cursor == nullptr || cursor->position >= cursor->tuples.size()) + return nullptr; + return &cursor->tuples[cursor->position++]; + } + + void CursorManager::Close(cursor* cursor) + { + delete cursor; + } + + void CursorManager::MockInsert(std::vector path, std::vector tuple) + { + mock_store_[JoinPath(path)].push_back(std::move(tuple)); + } } diff --git a/src/HandlerManager.cpp b/src/HandlerManager.cpp index 7d7015d..8149ff2 100644 --- a/src/HandlerManager.cpp +++ b/src/HandlerManager.cpp @@ -11,18 +11,24 @@ namespace nt delete handle; } + HandlerManager::HandlerManager(ObjectManager& objects, + PermissionsManager& permissions, + IdentityManager& identities, + LifecycleManager& lifecycles) + : objects_(objects) + , permissions_(permissions) + , identities_(identities) + , lifecycles_(lifecycles) + {} + struct HandlerManager::handle* HandlerManager::Open(std::vector object_path, void* connection_context) { - ObjectManager objects; - PermissionsManager permissions; - IdentityManager identities; - LifecycleManager lifecycles; - ObjectManager::registry* retrieved_object = objects.Find((const std::vector)object_path); - if (permissions.Access(retrieved_object, (const void*)connection_context) - && identities.CanOpen(retrieved_object) - && lifecycles.Contention(retrieved_object)) { + ObjectManager::registry* retrieved_object = objects_.Find((const std::vector)object_path); + if (permissions_.Access(retrieved_object, (const void*)connection_context) + && identities_.CanOpen(retrieved_object) + && lifecycles_.Contention(retrieved_object)) { // Starts monitoring this guy - lifecycles.Monitor(retrieved_object); + lifecycles_.Monitor(retrieved_object); return new handle{ retrieved_object, connection_context }; // Return a successful handle } else { @@ -36,22 +42,19 @@ namespace nt if (handle == nullptr) { return false; } - PermissionsManager permissions; - IdentityManager identities; - LifecycleManager lifecycles; // Somehow grab the object pointer and connection (maybe drop it...) from the handle ObjectManager::registry* object = handle->object; void* connection_context = handle->connection_context; // Checking for permissions here may be relevant. // What if we have a handle but no permission? Spooky - if (permissions.Access(object, connection_context) - && identities.CanClose(object) + if (permissions_.Access(object, connection_context) + && identities_.CanClose(object) // TODO: I think that in this case we do not need to worry about contention. // But be careful to evaluate this scenario later. - //&& LifecycleManager::Contention(retrieved_object) + //&& lifecycles_.Contention(object) ) { // Stops monitoring this guy - lifecycles.Unmonitor(object); + lifecycles_.Unmonitor(object); DeallocateHandle(handle); return true; // Return a successful handle } diff --git a/src/LifecycleManager.cpp b/src/LifecycleManager.cpp index bcab4b5..a83c9e1 100644 --- a/src/LifecycleManager.cpp +++ b/src/LifecycleManager.cpp @@ -4,6 +4,8 @@ namespace nt { void LifecycleManager::Monitor(ObjectManager::registry* object) { + if (object != nullptr) + ++object->head->handle_count; } const bool LifecycleManager::Contention(ObjectManager::registry* object) @@ -13,5 +15,7 @@ namespace nt void LifecycleManager::Unmonitor(ObjectManager::registry* object) { + if (object != nullptr && object->head->handle_count > 0) + --object->head->handle_count; } } diff --git a/src/NT.cpp b/src/NT.cpp index 4d391a8..66752ef 100644 --- a/src/NT.cpp +++ b/src/NT.cpp @@ -1,6 +1,14 @@ #include "Runtime.h" #ifdef NT_CONSOLE_APP +#include "CursorManager.h" +#include "HandlerManager.h" +#include "IdentityManager.h" +#include "LifecycleManager.h" +#include "ObjectManager.h" +#include "PermissionsManager.h" +#include "VM.h" + #include #endif @@ -21,13 +29,76 @@ int main() { const nt::NT runtime; std::cout << "RNT running: " << (runtime.IsRunning() ? "yes" : "no") << '\n'; - const int exit_code = runtime.IsRunning() ? 0 : 1; + + // --- Mock: register RelationX in the object registry --- + nt::ObjectManager objects; + + auto type = std::make_unique(); + type->label = RELATION; + type->disposable = false; + type->methods = { OPEN, CLOSE }; + + objects.Register({ "RelationX" }, std::make_unique(), std::move(type)); + + // --- Mock: populate the cursor store with three tuples --- + nt::CursorManager cursors; + cursors.MockInsert({ "RelationX" }, { { "name", "Alice" }, { "age", "30" } }); + cursors.MockInsert({ "RelationX" }, { { "name", "Bob" }, { "age", "25" } }); + cursors.MockInsert({ "RelationX" }, { { "name", "Carol" }, { "age", "35" } }); + + // --- Open a handle on RelationX through the full manager pipeline --- + nt::PermissionsManager permissions; + nt::IdentityManager identities; + nt::LifecycleManager lifecycles; + nt::HandlerManager handler(objects, permissions, identities, lifecycles); + + int connection = 1; // dummy connection context + nt::HandlerManager::handle* handle = handler.Open({ "RelationX" }, &connection); + if (handle == nullptr) + { + std::cout << "Failed to open handle for RelationX\n"; + return 1; + } + + // --- Open a cursor on the relation --- + nt::CursorManager::cursor* cursor = cursors.Open(handle); + if (cursor == nullptr) + { + std::cout << "Failed to open cursor for RelationX\n"; + handler.Close(handle); + return 1; + } + + // --- Build a SCAN plan and pull all tuples lazily through the FOL VM --- + nt::PlanNode plan; + plan.op = nt::PlanNode::Op::SCAN; + plan.scan_cursor = cursor; + + nt::VM vm(cursors); + std::cout << "Tuples in RelationX:\n"; + while (nt::Tuple* t = vm.Next(&plan)) + { + std::cout << " "; + const nt::Attribute* attr = t->Next(); + while (attr != nullptr) + { + std::cout << attr->name << "=" << attr->value; + attr = t->Next(); + if (attr != nullptr) + std::cout << ", "; + } + std::cout << '\n'; + } + + // --- Cleanup --- + cursors.Close(cursor); + handler.Close(handle); #ifdef NT_WAIT_ON_EXIT std::cout << "Press Enter to exit..."; std::cin.get(); #endif - return exit_code; + return runtime.IsRunning() ? 0 : 1; } #endif diff --git a/src/ObjectManager.cpp b/src/ObjectManager.cpp index ff85af2..19f862d 100644 --- a/src/ObjectManager.cpp +++ b/src/ObjectManager.cpp @@ -2,8 +2,32 @@ namespace nt { - struct ObjectManager::registry* ObjectManager::Find(const std::vector object_path) + void ObjectManager::Register(std::vector path, + std::unique_ptr object, + std::unique_ptr type) { + auto head = std::make_unique(); + head->reference_count = 0; + head->handle_count = 0; + head->path = std::move(path); + head->type = std::move(type); + + auto entry = std::make_unique(); + entry->head = std::move(head); + entry->object = std::move(object); + entry->next = std::move(entries); + entries = std::move(entry); + } + + ObjectManager::registry* ObjectManager::Find(const std::vector object_path) + { + registry* current = entries.get(); + while (current != nullptr) + { + if (current->head->path == object_path) + return current; + current = current->next.get(); + } return nullptr; } } diff --git a/src/VM.cpp b/src/VM.cpp index 4e69b8e..b5824d0 100644 --- a/src/VM.cpp +++ b/src/VM.cpp @@ -2,4 +2,19 @@ namespace nt { + VM::VM(CursorManager& cursors) : cursors_(cursors) {} + + Tuple* VM::Next(PlanNode* node) + { + if (node == nullptr) + return nullptr; + + switch (node->op) + { + case PlanNode::Op::SCAN: + return cursors_.Next(node->scan_cursor); + } + + return nullptr; + } } -- cgit v1.2.3