1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/docs/wiki/Components Sat Aug 28 00:28:17 2021 +0200
1.3 @@ -0,0 +1,227 @@
1.4 += Components =
1.5 +
1.6 +Access to files is provided by a number of programs acting as components. For
1.7 +convenience, the component-level operations are wrapped up in a
1.8 +[[ClientLibrary|client library]] that aims to provide simpler, more familiar
1.9 +mechanisms for opening, reading, writing, and closing files, together with
1.10 +various other operations.
1.11 +
1.12 +<<TableOfContents(2,3)>>
1.13 +
1.14 +Components are accessed via interfaces defined using the interface description
1.15 +language supported by the ``idl4re`` tool. Interface operations in this
1.16 +document are described using excerpts from the appropriate interface
1.17 +descriptions.
1.18 +
1.19 +######## A graph showing the interactions between components
1.20 +
1.21 +{{{#!graphviz
1.22 +#format svg
1.23 +#transform notugly
1.24 +digraph components {
1.25 + node [fontsize="12.0",fontname="sans-serif",shape=box];
1.26 + edge [fontsize="12.0",fontname="sans-serif"];
1.27 + rankdir=LR;
1.28 +
1.29 + subgraph {
1.30 + node [label="Client",style=solid,color="#000000",fontcolor="#000000"];
1.31 + rank=min;
1.32 +
1.33 + Client1; Client3; Client5;
1.34 +
1.35 + subgraph {
1.36 + node [label="Client",color="#999999",fontcolor="#999999"];
1.37 + Client2; Client4; Client6;
1.38 + }
1.39 + }
1.40 +
1.41 + subgraph {
1.42 + rank=same;
1.43 + Filesystem;
1.44 +
1.45 + subgraph {
1.46 + node [label="Opener\n(user)"];
1.47 + Opener1; Opener2;
1.48 + }
1.49 +
1.50 + subgraph {
1.51 + node [label="OpenerContext"];
1.52 + OpenerContext1; OpenerContext2;
1.53 + }
1.54 +
1.55 + MappedFile;
1.56 + }
1.57 +
1.58 + Client1 -> Client2 -> Client3 -> Client4 -> Client5 -> Client6 [arrowhead=none,style=invisible];
1.59 + Opener1 -> Opener2 [arrowhead=none,style=invisible];
1.60 + OpenerContext1 -> OpenerContext2 [arrowhead=none,style=invisible];
1.61 +
1.62 + Client1 -> Filesystem [label="open_for_user(user)"];
1.63 + Filesystem -> Opener1;
1.64 + Opener1 -> Client2 [style=dashed];
1.65 +
1.66 + Client3 -> Opener2 [label="context()"];
1.67 + Opener2 -> OpenerContext1;
1.68 + OpenerContext1 -> Client4 [style=dashed];
1.69 +
1.70 + Client5 -> OpenerContext2 [label="open(flags, ...)"];
1.71 + OpenerContext2 -> MappedFile;
1.72 + MappedFile -> Client6 [style=dashed];
1.73 +}
1.74 +}}}
1.75 +
1.76 +########
1.77 +
1.78 +== Filesystems ==
1.79 +
1.80 +Filesystems implement the `Filesystem` interface which provides the
1.81 +`open_for_user` operation:
1.82 +
1.83 +{{{
1.84 +open_for_user(in user_t user, out cap opener)
1.85 +}}}
1.86 +
1.87 +The operation yields a file opener appropriate for the given [[Users|user]]
1.88 +credentials.
1.89 +
1.90 +== File Openers ==
1.91 +
1.92 +File openers implement the `Opener` interface which provides the `context`
1.93 +operation:
1.94 +
1.95 +{{{
1.96 +context(out cap context)
1.97 +}}}
1.98 +
1.99 +Each client program, task or thread obtains its own context because it will
1.100 +need its own dedicated channel for communication with the filesystem.
1.101 +
1.102 +== Opener Contexts ==
1.103 +
1.104 +An opener context acts as a dataspace, meaning that it can be attached to a
1.105 +task using a region manager and provide a buffer via a region of mapped memory
1.106 +that the task can write to. In the case of a context, the task will write a
1.107 +filesystem path indicating the file to be opened.
1.108 +
1.109 +Each context allows a client program to request access to individual files via
1.110 +operations provided by the `OpenerContext` interface, of which the most
1.111 +pertinent is the `open` operation:
1.112 +
1.113 +{{{
1.114 +open(in flags_t flags, out offset_t size, out cap file,
1.115 + out object_flags_t object_flags)
1.116 +}}}
1.117 +
1.118 +Using the path information written to the context's memory region, the `open`
1.119 +operation will obtain a reference to a file-like object whose characteristics
1.120 +are described by the accompanying `object_flags`, these helping the client to
1.121 +distinguish between files that support arbitrary memory mapping operations and
1.122 +pipes that mandate sequential region-by-region access.
1.123 +
1.124 +Alongside regular files, directories may also be opened. Reading from them
1.125 +yields a listing of directory entries.
1.126 +
1.127 +== Files ==
1.128 +
1.129 +Files themselves act as dataspaces, meaning that they can be attached to a
1.130 +task using a region manager and provide their content via a region of mapped
1.131 +memory. Files implement the `MappedFile` interface.
1.132 +
1.133 +Control over the region of the file provided via mapped memory occurs
1.134 +using the `mmap` operation:
1.135 +
1.136 +{{{
1.137 +mmap(in offset_t position, in offset_t length,
1.138 + out offset_t start_pos, out offset_t end_pos,
1.139 + out offset_t size)
1.140 +}}}
1.141 +
1.142 +Files also implement the more general `File` interface that provides the
1.143 +`resize` operation:
1.144 +
1.145 +{{{
1.146 +resize(inout offset_t size)
1.147 +}}}
1.148 +
1.149 +This allows the portion of the memory region dedicated to the file's contents
1.150 +to be extended.
1.151 +
1.152 +== Directories ==
1.153 +
1.154 +Directories are also meant to be accessed like files, meaning that it should
1.155 +be possible to attach them to a task using a region manager and access the
1.156 +provided content, this being a listing of directory entries, via the mapped
1.157 +region.
1.158 +
1.159 +However, unlike files which may support arbitrary mapping of their contents,
1.160 +the provided content may be supplied by a pipe endpoint, thereby not
1.161 +supporting precisely the same navigation mechanisms as those supported by
1.162 +files.
1.163 +
1.164 +'''Note''' that directories may well be redefined to support multiple
1.165 +operations, one of which supporting the file-like access described above.
1.166 +
1.167 +== Pipe Openers ==
1.168 +
1.169 +Distinct from filesystems but potentially used by them, pipe openers provide a
1.170 +means of obtaining pipes, which are channels that support unidirectional
1.171 +communication via shared memory.
1.172 +
1.173 +Pipe openers implement the `PipeOpener` interface and support the following
1.174 +operation:
1.175 +
1.176 +{{{
1.177 +pipe(in offset_t size, out cap reader, out cap writer)
1.178 +}}}
1.179 +
1.180 +The size is indicated to request pipe regions long enough for the needs of the
1.181 +communicating parties, with both reader and writer endpoint capabilities being
1.182 +returned. Such capabilities may be propagated to the eventual parties, these
1.183 +typically being separate tasks.
1.184 +
1.185 +== Pipes ==
1.186 +
1.187 +Although not generally obtained from filesystems, pipes may be involved in
1.188 +providing content from some filesystem objects such as directories. However,
1.189 +they are also obtained directly from an appropriate pipe server providing pipe
1.190 +opening facilities.
1.191 +
1.192 +Pipes expose single regions of shared memory to their endpoints, with the
1.193 +writing endpoint populating one region while the reading endpoint accesses the
1.194 +other. The reading endpoint may advance to the region being written, and this
1.195 +will free up a new region for the writer when it has filled its region. When
1.196 +the writer itself advances, it permits the reader to consume all data in the
1.197 +fully populated region. Naturally, the reader may not advance ahead of the
1.198 +writer.
1.199 +
1.200 +Pipes implement the `Pipe` interface and a number of operations to support
1.201 +this interaction mechanism.
1.202 +
1.203 +The details of an endpoint's current region can be queried using the following
1.204 +operation:
1.205 +
1.206 +{{{
1.207 +current_region(out offset_t populated_size, out offset_t size)
1.208 +}}}
1.209 +
1.210 +This provides details of the populated size (or amount of written data) in a
1.211 +region along with the size of the region.
1.212 +
1.213 +Navigation to the next available region of the pipe is performed using the
1.214 +following operation:
1.215 +
1.216 +{{{
1.217 +next_region(inout offset_t populated_size, out offset_t size)
1.218 +}}}
1.219 +
1.220 +Here, the populated size may be specified by the writer so that the reader may
1.221 +query the current region's properties using the appropriate operation.
1.222 +
1.223 +The status of the pipe can be queried using the `closed` operation:
1.224 +
1.225 +{{{
1.226 +closed(out int closed)
1.227 +}}}
1.228 +
1.229 +This indicates through a boolean-equivalent parameter whether one or both
1.230 +endpoints have been closed.