aboutsummaryrefslogblamecommitdiffstats
path: root/Runtime/NtContext.h
blob: 4e28f9f37acaf76969cdf16df62bd786a873831f (plain) (tree)





















































































































































































                                                                                                                                                                              
#pragma once
#include <cstdint>
#include <set>
#include <vector>
#include <string>

#ifdef NT_EXPORTS
#define NT_API __declspec(dllexport)
#else
#define NT_API __declspec(dllimport)
#endif

enum OBJECT_TYPE {
    MULTIGROUP,
    RELATION,
    TUPLE,
    ATTRIBUTE,
    TRANSACTION
};

enum METHOD {
    OPEN,
    CLOSE,
    PARSE, // To plug a secondary namespace
    SECURITY
};

enum AUTH_CLAIM {
    READ,
    WRITE
};

enum AUTH_METHOD {
    CERTIFICATE,
    PLAIN_TEXT
};

namespace nt
{
    class NT_API ObjectManager
    {
    public:
        class IObject {
            virtual ~IObject() {}
        };
        class Multigroup : IObject {};
        class Relation : IObject {};
        class Tuple : IObject {};
        class Transaction : IObject {};
        struct object_type {
            OBJECT_TYPE label;
            // If the object is not durable. E.g.: TRANSACTION
            bool disposable;
            std::set<METHOD> methods;
        };
        struct registry_head {
            uint32_t reference_count;
            uint32_t handle_count;
            struct object_type* type;
            std::vector<std::string> path;
            //security_descriptor to be added later, maybe also a set of labels
        };
        struct registry {
            struct registry_head* head;
            IObject object;
            // TODO: Treat as a list for now, but ideally it's a tree
            struct registry* next;
        };
        struct registry** registry;
        // Looks into this registry and attempts to retrieve the entry
        struct registry* Find(const std::vector<std::string> object_path){}
    };

    class NT_API PermissionsManager
    {
    public:
        // For validating connections at login
        std::set<AUTH_CLAIM> Firewall(AUTH_METHOD method) {}
        // For validating permission to an object
        const bool Access(const std::vector<std::string> object_path, const void* connection_context) {
            // Checks the security descriptor on the head of the object we find in the ObjectManager::registry
            // Then additionally check other metadata yet to be defined in the connection_context,
            // like user group, policy, etc.
            // Yet to decide if this should be summoned at every attempt to get ahold of an object,
            // that might produce significant overhead. How can we solve this?
        }
    };

    class NT_API NamespaceReferenceManager
    {
    };
    
    class NT_API CursorManager
    {
    };
    
    class NT_API IdentityManager
    {
    public:
        // Looks into the methods of the object type and asserts if it can be opened
        const bool CanOpen(struct ObjectManager::registry* object) {}
    };

    class NT_API LifecycleManager
    {
    public:
        // If object is not being monitored already, monitors 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.
        // Think of other use cases later.
        void Monitor(struct ObjectManager::registry* object) {}
        // Serializes contention for the change of a mutable reference.
        // This can be used in, for example, the HEAD of a branch to serialize the access.
        // If the object does not causes contention, like a relation (since they are immutable, just like multigroups, all snapshots)
        // then just approve, as they do not cause any contention. Transactions also do not cause any, 
        // the only things that do are mutable reference states in shared sessions,
        // for example: the HEAD of a branch, namespace collisions (creating two branches with the same name, or two multigroups with the same name from the same state, etc),
        // multi-branch atomic commits (which I wish to not have as it damages isolation), 
        // garbage collection of old state (as in, we want to delete an old-enough history to save up space), etc.
        const bool Contention(struct ObjectManager::registry* object){}
        // The inverse of `Monitor`, stops monitoring.
        // Maybe garbage collect here also if the counters goes to zero.
        void Unmonitor(struct ObjectManager::registry* object) {}
    };

    class NT_API HandlerManager
    {
    public:
        // This is supposed to represent an authorized access to a certain object in the registry
        // This increases the handle count in the object manager
        // We should consider adding on the object manager a vector of all the handles that refer to an object
        struct handle {};
        void DeallocateHandle(struct handle* handle) {}
        struct handle Open(std::vector<std::string> object_path, void* connection_context) {
            struct ObjectManager::registry* retrieved_object = ObjectManager::Find((const std::vector<std::string>)object_path);
            if (PermissionsManager::Access(retrieved_object, (const void*)connection_context)
                && IdentityManager::CanOpen(retrieved_object)
                && LifecycleManager::Contention(retrieved_object)) {
                // Starts monitoring this guy
                LifecycleManager::Monitor(retrieved_object);
                return {}; // Return a successful handle
            }
            else {
                // Return something more algebraic instead of null or an int
                return {};
            };
        }
        bool Close(struct handle *handle) {
            // Somehow grab the object pointer and connection (maybe drop it...) from the handle
            struct 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 (PermissionsManager::Access(object, connection_context)
                && IdentityManager::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)
                ) {
                // Stops monitoring this guy
                LifecycleManager::Unmonitor(object);
                DeallocateHandle(handle);
                return true; // Return a successful handle
            }
            else {
                // Return something more algebraic instead of null or an int.
                // It's kinda bad to not even report what went wrong.
                return false;
            };
        }
    };

    class NT_API WAM
    {
    };

    class NT_API NT
    {
    public:
        bool IsRunning() const;
        void SimulateEntryCall() {};
    };
}