1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/docs/wiki/Server_Library Fri Aug 12 16:41:06 2022 +0200
1.3 @@ -0,0 +1,245 @@
1.4 += Server Library =
1.5 +
1.6 +Within the filesystem server library, a number of different abstractions and
1.7 +mechanisms are employed to provide access to filesystem objects.
1.8 +
1.9 +<<TableOfContents(2,3)>>
1.10 +
1.11 +This document uses C-style interface syntax since the components operating
1.12 +within the described mechanisms will themselves be described using such
1.13 +syntax.
1.14 +
1.15 +== Accountable ==
1.16 +
1.17 +This interface provides the following operations:
1.18 +
1.19 +{{{
1.20 +void attach();
1.21 +unsigned int detach();
1.22 +}}}
1.23 +
1.24 +Its purpose is to provide reference counting for components, with the `attach`
1.25 +operation incrementing the number of users of a component, and with the
1.26 +`detach` operation decrementing the number of users and returning the
1.27 +resulting number of users. When components no longer have any attached users,
1.28 +they may perform operations to tidy up after themselves and permit their
1.29 +deallocation.
1.30 +
1.31 +== Accessors ==
1.32 +
1.33 +Accessors provide the means of accessing filesystem object data and metadata.
1.34 +Conceptually, files and directories are both exposed by accessors, although
1.35 +the interfaces and mechanisms may differ between these types of objects.
1.36 +
1.37 +=== Directory Accessors ===
1.38 +
1.39 +Currently, directory accessors provide support for traversing directory
1.40 +listings, obtaining the relevant filesystem metadata using the underlying
1.41 +filesystem access library.
1.42 +
1.43 +=== File Accessors ===
1.44 +
1.45 +File content is accessed through an interface with the following operations:
1.46 +
1.47 +{{{
1.48 +void close();
1.49 +void fill(Flexpage *flexpage);
1.50 +void flush(Flexpage *flexpage);
1.51 +offset_t get_size();
1.52 +void set_size(offset_t size);
1.53 +}}}
1.54 +
1.55 +The operations need to be supported with actual filesystem operations. For
1.56 +example, ext2-based filesystems employ a specific abstraction which invokes
1.57 +library functions provided by the `libext2fs` package.
1.58 +
1.59 +== Providers ==
1.60 +
1.61 +Providers encapsulate the essential functionality for accessing filesystem
1.62 +objects. Implementing the `Accountable` interface, they are shared by
1.63 +resources and discarded when no resources are using them.
1.64 +
1.65 +The following operations are supported by providers:
1.66 +
1.67 +{{{
1.68 +ProviderRegistry *registry();
1.69 +long make_resource(offset_t *size, object_flags_t *object_flags, Resource **resource);
1.70 +bool removal_pending();
1.71 +void remove();
1.72 +void remove_pending(bool remove);
1.73 +}}}
1.74 +
1.75 +Providers are associated with filesystem objects in a registry which can be
1.76 +obtained from each provider using the `registry` operation.
1.77 +
1.78 +Providers also support the creation of resources through which each user of a
1.79 +provider exercises its use of that provider. The `make_resource` operation
1.80 +performs the creation and returns size, flags and resource instance details.
1.81 +
1.82 +The removal of providers can be directed using the `remove_pending` and
1.83 +`remove` operations. Where `remove_pending` has been called with a true value
1.84 +as its parameter, the `removal_pending` operation will also return a true
1.85 +value, and upon the provider being discarded, the `remove` operation will be
1.86 +invoked. The `remove` operation performs the appropriate underlying operation
1.87 +to remove the object being provided.
1.88 +
1.89 +Typically, removal of providers is managed by the provider registry when
1.90 +resources are closed and detached from providers.
1.91 +
1.92 +######## A graph showing the removal mechanism
1.93 +
1.94 +{{{#!graphviz
1.95 +#format svg
1.96 +#transform notugly
1.97 +digraph provider_removal {
1.98 + node [fontsize="12.0",fontname="sans-serif",shape=box];
1.99 + edge [fontsize="12.0",fontname="sans-serif"];
1.100 + rankdir=LR;
1.101 +
1.102 + ResourceServer -> Resource [label="close"];
1.103 + Resource -> ProviderRegistry [label="detach"];
1.104 + ProviderRegistry -> Provider [label="remove"];
1.105 +}
1.106 +}}}
1.107 +
1.108 +########
1.109 +
1.110 +== Resources ==
1.111 +
1.112 +Resources are objects accessed by clients that support a basic level of
1.113 +accounting and management.
1.114 +
1.115 +The base interface of a resource is as follows:
1.116 +
1.117 +{{{
1.118 +void activate();
1.119 +void close();
1.120 +}}}
1.121 +
1.122 +Activation of a resource is an optional operation that performs any
1.123 +initialisation before a resource is made available to its user.
1.124 +
1.125 +In practice, other operations are required to make resources useful.
1.126 +
1.127 +In some cases, resources provide the mechanism by which each user of a
1.128 +filesystem object may access that object independently. They would then
1.129 +effectively provide a session in which accesses can occur.
1.130 +
1.131 +=== Directory Resources ===
1.132 +
1.133 +Directory resources primarily expose the contents of directories in the
1.134 +filesystem to a user. They employ directory accessors which concern themselves
1.135 +with the actual filesystem content.
1.136 +
1.137 +[[Components#Directories|Directory components]] are provided using directory
1.138 +resources.
1.139 +
1.140 +<<Anchor(Pager)>>
1.141 +=== Pagers or File Resources ===
1.142 +
1.143 +Pagers are resources that support dataspace access operations, thus allowing
1.144 +the resources to expose filesystem content in mapped memory regions to a
1.145 +particular user of the object providing the content.
1.146 +
1.147 +[[Components#Files|File components]] and [[Components#Pipes|pipe components]]
1.148 +are provided using pagers.
1.149 +
1.150 +=== Filesystem Resources ===
1.151 +
1.152 +Filesystem resources provide the entry point for access to a filesystem by
1.153 +other components or programs. Since filesystems often enforce identity-based
1.154 +access controls, a filesystem resource will typically support the
1.155 +`open_for_user` operation in various forms, with the result of this operation
1.156 +being the instantiation of an `OpenerResource` configured for the indicated
1.157 +user identity.
1.158 +
1.159 +== Registries ==
1.160 +
1.161 +The basic mechanism for obtaining a resource involves a registry, as
1.162 +illustrated by the following diagram.
1.163 +
1.164 +######## A graph showing the use of a registry in obtaining resources
1.165 +
1.166 +{{{#!graphviz
1.167 +#format svg
1.168 +#transform notugly
1.169 +digraph registry {
1.170 + node [fontsize="12.0",fontname="sans-serif",shape=box];
1.171 + edge [fontsize="12.0",fontname="sans-serif"];
1.172 + rankdir=LR;
1.173 +
1.174 + subgraph {
1.175 + node [label="OpenerContextResource"];
1.176 + rank=same;
1.177 +
1.178 + OpenerContextResource1 -> OpenerContextResource2 [dir=none,style=dotted];
1.179 + }
1.180 +
1.181 + subgraph {
1.182 + node [label="OpenerResource"];
1.183 + rank=same;
1.184 +
1.185 + OpenerResource1 -> OpenerResource2 [dir=none,style=dotted];
1.186 + }
1.187 +
1.188 + subgraph {
1.189 + rank=same;
1.190 +
1.191 + ResourceRegistry -> Resource;
1.192 + }
1.193 +
1.194 + subgraph {
1.195 + rank=same;
1.196 +
1.197 + ProviderRegistry -> Provider;
1.198 + }
1.199 +
1.200 + OpenerContextResource1 -> OpenerResource1 [label="open"];
1.201 + OpenerResource1 -> ResourceRegistry [label="get_resource"];
1.202 + ResourceRegistry -> ProviderRegistry [label="get/set"];
1.203 +
1.204 + Provider -> Resource -> OpenerResource2 -> OpenerContextResource2;
1.205 +}
1.206 +}}}
1.207 +
1.208 +########
1.209 +
1.210 +The `ResourceRegistry` coordinates access to filesystem resources and, through
1.211 +synchronisation, prevents conflicting operations from occurring concurrently.
1.212 +For example, a removal operation on a file may not be allowed to occur while
1.213 +an opening operation is in progress.
1.214 +
1.215 +To achieve this, a common lock is employed to serialise access, with any
1.216 +underlying filesystem operations being initiated from the registry while the
1.217 +lock is held. An object providing the `FileOpening` interface for a filesystem
1.218 +provides such operations, and the following interaction pattern is thereby
1.219 +employed:
1.220 +
1.221 +######## A graph showing the registry coordinating filesystem operations
1.222 +
1.223 +{{{#!graphviz
1.224 +#format svg
1.225 +#transform notugly
1.226 +digraph registry_operations {
1.227 + node [fontsize="12.0",fontname="sans-serif",shape=box];
1.228 + edge [fontsize="12.0",fontname="sans-serif"];
1.229 + rankdir=LR;
1.230 +
1.231 + OpenerContextResource -> OpenerResource -> ResourceRegistry -> FileOpening;
1.232 +}
1.233 +}}}
1.234 +
1.235 +########
1.236 +
1.237 +Since the `ResourceRegistry` functionality is generic, it could be specialised
1.238 +for each filesystem or be configured with an appropriate reference to a
1.239 +`FileOpening` object. The `OpenerResource` would then be generic, invoking the
1.240 +registry which would, in turn, invoke the opening object.
1.241 +
1.242 +However, the chosen approach is to permit `OpenerResource` objects to
1.243 +implement the `FileOpening` interface for each filesystem, meaning that the
1.244 +`ResourceRegistry` will end up being called by the opener and then invoking
1.245 +the opener in return. This is slightly more convenient than the alternative
1.246 +since the opener can be configured with a given user identity, and such
1.247 +identity details will ultimately be employed when accessing the underlying
1.248 +filesystem itself.