paul@233 | 1 | = Mechanisms = |
paul@233 | 2 | |
paul@233 | 3 | Within the filesystem server library, a number of different abstractions and |
paul@233 | 4 | mechanisms are employed to provide access to filesystem objects. |
paul@233 | 5 | |
paul@233 | 6 | <<TableOfContents(2,3)>> |
paul@233 | 7 | |
paul@233 | 8 | The abstractions or components used in the library are organised as follows. |
paul@233 | 9 | |
paul@233 | 10 | ######## A graph showing the relationships between library components |
paul@233 | 11 | |
paul@233 | 12 | {{{#!graphviz |
paul@233 | 13 | #format svg |
paul@233 | 14 | #transform notugly |
paul@233 | 15 | digraph components { |
paul@233 | 16 | node [fontsize="12.0",fontname="sans-serif",shape=box]; |
paul@233 | 17 | edge [fontsize="12.0",fontname="sans-serif"]; |
paul@233 | 18 | rankdir=LR; |
paul@233 | 19 | |
paul@233 | 20 | subgraph { |
paul@233 | 21 | rank=same; |
paul@233 | 22 | |
paul@233 | 23 | Resource -> DirectoryResource -> FilePager |
paul@233 | 24 | [dir=none,style=dotted]; |
paul@233 | 25 | } |
paul@233 | 26 | |
paul@233 | 27 | subgraph { |
paul@233 | 28 | rank=same; |
paul@233 | 29 | |
paul@233 | 30 | Provider -> DirectoryProvider -> FileProvider |
paul@233 | 31 | [dir=none,style=dotted]; |
paul@233 | 32 | } |
paul@233 | 33 | |
paul@233 | 34 | subgraph { |
paul@233 | 35 | rank=same; |
paul@233 | 36 | |
paul@233 | 37 | Accessor -> Ext2FileAccessor |
paul@233 | 38 | [dir=none,style=dotted]; |
paul@233 | 39 | } |
paul@233 | 40 | |
paul@233 | 41 | subgraph { |
paul@233 | 42 | rank=same; |
paul@233 | 43 | |
paul@233 | 44 | DirectoryAccessor -> Ext2DirectoryAccessor |
paul@233 | 45 | [dir=none,style=dotted]; |
paul@233 | 46 | } |
paul@233 | 47 | |
paul@233 | 48 | subgraph { |
paul@233 | 49 | node [shape=ellipse]; |
paul@233 | 50 | rank=same; |
paul@233 | 51 | |
paul@233 | 52 | Directory [label="dir"]; |
paul@233 | 53 | File [label="dir/file"]; |
paul@233 | 54 | } |
paul@233 | 55 | |
paul@233 | 56 | DirectoryResource -> DirectoryProvider -> Ext2DirectoryAccessor -> Directory; |
paul@233 | 57 | FilePager -> FileProvider -> Ext2FileAccessor -> File; |
paul@233 | 58 | } |
paul@233 | 59 | }}} |
paul@233 | 60 | |
paul@233 | 61 | ######## |
paul@233 | 62 | |
paul@233 | 63 | == Accountable == |
paul@233 | 64 | |
paul@233 | 65 | This interface provides the following operations: |
paul@233 | 66 | |
paul@233 | 67 | {{{ |
paul@233 | 68 | attach() |
paul@233 | 69 | detach(out unsigned int count) |
paul@233 | 70 | }}} |
paul@233 | 71 | |
paul@233 | 72 | Its purpose is to provide reference counting for components, with the `attach` |
paul@233 | 73 | operation incrementing the number of users of a component, and with the |
paul@233 | 74 | `detach` operation decrementing the number of users. When components no longer |
paul@233 | 75 | have any attached users, they may perform operations to tidy up after |
paul@233 | 76 | themselves and permit their deallocation. |
paul@233 | 77 | |
paul@233 | 78 | == Accessors == |
paul@233 | 79 | |
paul@233 | 80 | Accessors provide the means of accessing filesystem object data and metadata. |
paul@233 | 81 | Conceptually, files and directories are both exposed by accessors, although |
paul@233 | 82 | the interfaces and mechanisms may differ between these types of objects. |
paul@233 | 83 | |
paul@233 | 84 | === Directory Accessors === |
paul@233 | 85 | |
paul@233 | 86 | Currently, directory accessors provide support for traversing directory |
paul@233 | 87 | listings, obtaining the relevant filesystem metadata using the underlying |
paul@233 | 88 | filesystem access library. |
paul@233 | 89 | |
paul@233 | 90 | === File Accessors === |
paul@233 | 91 | |
paul@233 | 92 | File content is accessed through an interface with the following operations: |
paul@233 | 93 | |
paul@233 | 94 | {{{ |
paul@233 | 95 | close() |
paul@233 | 96 | fill(inout Flexpage flexpage) |
paul@233 | 97 | flush(inout Flexpage flexpage) |
paul@233 | 98 | get_size(out offset_t size) |
paul@233 | 99 | set_size(in offset_t size) |
paul@233 | 100 | }}} |
paul@233 | 101 | |
paul@233 | 102 | The operations need to be supported with actual filesystem operations. For |
paul@233 | 103 | example, ext2-based filesystems employ a specific abstraction which invokes |
paul@233 | 104 | library functions provided by the `libext2fs` package. |
paul@233 | 105 | |
paul@233 | 106 | == Providers == |
paul@233 | 107 | |
paul@233 | 108 | Providers encapsulate the essential functionality for accessing filesystem |
paul@233 | 109 | objects. Implementing the `Accountable` interface, they are shared by |
paul@233 | 110 | resources and discarded when no resources are using them. |
paul@233 | 111 | |
paul@233 | 112 | The following operations are supported by providers: |
paul@233 | 113 | |
paul@233 | 114 | {{{ |
paul@233 | 115 | registry(out ProviderRegistry *registry) |
paul@233 | 116 | make_resource(out offset_t size, out object_flags_t object_flags, out Resource *resource) |
paul@233 | 117 | }}} |
paul@233 | 118 | |
paul@233 | 119 | Providers are associated with filesystem objects in a registry which can be |
paul@233 | 120 | obtained from each provider. |
paul@233 | 121 | |
paul@233 | 122 | Providers also support the creation of resources through which each user of a |
paul@233 | 123 | provider exercises its use of that provider. |
paul@233 | 124 | |
paul@233 | 125 | == Resources == |
paul@233 | 126 | |
paul@233 | 127 | Resources allow each user of a filesystem object to access that object |
paul@233 | 128 | independently. They effectively provide a session in which accesses may occur. |
paul@233 | 129 | |
paul@233 | 130 | The base interface of a resource is as follows: |
paul@233 | 131 | |
paul@233 | 132 | {{{ |
paul@233 | 133 | activate() |
paul@233 | 134 | close() |
paul@233 | 135 | }}} |
paul@233 | 136 | |
paul@233 | 137 | Activation of a resource is an optional operation that performs any |
paul@233 | 138 | initialisation before a resource is made available to its user. |
paul@233 | 139 | |
paul@233 | 140 | In practice, other operations are required to make resources useful. |
paul@233 | 141 | |
paul@233 | 142 | === Directory Resources === |
paul@233 | 143 | |
paul@233 | 144 | Directory resources primarily expose the contents of directories in the |
paul@233 | 145 | filesystem. They employ directory accessors which concern themselves with the |
paul@233 | 146 | actual filesystem content. |
paul@233 | 147 | |
paul@233 | 148 | [[Components#Directories|Directory components]] are provided using directory |
paul@233 | 149 | resources. |
paul@233 | 150 | |
paul@233 | 151 | === Pagers === |
paul@233 | 152 | |
paul@233 | 153 | Pagers are resources that support dataspace access operations, thus allowing |
paul@233 | 154 | the resources to expose filesystem content in mapped memory regions. |
paul@233 | 155 | |
paul@233 | 156 | [[Components#Files|File components]] and [[Components#Pipes|pipe components]] |
paul@233 | 157 | are provided using pagers. |
paul@233 | 158 | |
paul@233 | 159 | == Registries == |
paul@233 | 160 | |
paul@233 | 161 | The basic mechanism for obtaining a resource involves a registry, as |
paul@233 | 162 | illustrated by the following diagram. |
paul@233 | 163 | |
paul@233 | 164 | ######## A graph showing the use of a registry in obtaining resources |
paul@233 | 165 | |
paul@233 | 166 | {{{#!graphviz |
paul@233 | 167 | #format svg |
paul@233 | 168 | #transform notugly |
paul@233 | 169 | digraph registry { |
paul@233 | 170 | node [fontsize="12.0",fontname="sans-serif",shape=box]; |
paul@233 | 171 | edge [fontsize="12.0",fontname="sans-serif"]; |
paul@233 | 172 | rankdir=LR; |
paul@233 | 173 | |
paul@233 | 174 | subgraph { |
paul@233 | 175 | node [label="OpenerContextResource"]; |
paul@233 | 176 | rank=same; |
paul@233 | 177 | |
paul@233 | 178 | OpenerContextResource1 -> OpenerContextResource2 [dir=none,style=dotted]; |
paul@233 | 179 | } |
paul@233 | 180 | |
paul@233 | 181 | subgraph { |
paul@233 | 182 | node [label="OpenerResource"]; |
paul@233 | 183 | rank=same; |
paul@233 | 184 | |
paul@233 | 185 | OpenerResource1 -> OpenerResource2 [dir=none,style=dotted]; |
paul@233 | 186 | } |
paul@233 | 187 | |
paul@233 | 188 | subgraph { |
paul@233 | 189 | rank=same; |
paul@233 | 190 | |
paul@233 | 191 | ResourceRegistry -> Resource; |
paul@233 | 192 | } |
paul@233 | 193 | |
paul@233 | 194 | subgraph { |
paul@233 | 195 | rank=same; |
paul@233 | 196 | |
paul@233 | 197 | ProviderRegistry -> Provider; |
paul@233 | 198 | } |
paul@233 | 199 | |
paul@233 | 200 | OpenerContextResource1 -> OpenerResource1 [label="open"]; |
paul@233 | 201 | OpenerResource1 -> ResourceRegistry [label="get_resource"]; |
paul@233 | 202 | ResourceRegistry -> ProviderRegistry [label="get/set"]; |
paul@233 | 203 | |
paul@233 | 204 | Provider -> Resource -> OpenerResource2 -> OpenerContextResource2; |
paul@233 | 205 | } |
paul@233 | 206 | }}} |
paul@233 | 207 | |
paul@233 | 208 | ######## |