aboutsummaryrefslogtreecommitdiffstats
path: root/Runtime/NtContext.h
blob: 4e28f9f37acaf76969cdf16df62bd786a873831f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
#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() {};
    };
}