@@ -22,6 +22,7 @@ use crate::tuple::Subspace;
22
22
use crate :: { FdbError , FdbResult , Transaction } ;
23
23
use byteorder:: { LittleEndian , WriteBytesExt } ;
24
24
25
+ // TODO: useful?
25
26
const _LAYER_VERSION: ( u8 , u8 , u8 ) = ( 1 , 0 , 0 ) ;
26
27
const MAJOR_VERSION : u32 = 1 ;
27
28
const MINOR_VERSION : u32 = 0 ;
@@ -73,19 +74,58 @@ const DEFAULT_SUB_DIRS: u8 = 0;
73
74
/// futures::executor::block_on(async_main()).expect("failed to run");
74
75
/// drop(network);
75
76
/// ```
77
+ /// ## How it works
78
+ ///
79
+ /// Here's what will be generated when using the Directory to create a path `/app/my-app`:
80
+ ///
81
+ /// ```text
82
+ /// +
83
+ /// |
84
+ /// | version = (1,0,0) # Directory's version
85
+ /// |
86
+ /// | +
87
+ /// | "hca"| # used to allocate numbers like 12 and 42
88
+ /// | +
89
+ /// \xFE |
90
+ /// node's | (0,"app")=12 # id allocated by the hca for "path"
91
+ /// subspace | (0,"app","layer")="" # layer allow an ownership's mecanism
92
+ /// |
93
+ /// |
94
+ /// | (0,"app",0,"my-app","layer")="" # layer allow an ownership's mecanism
95
+ /// | (0,"app",0,"my-app")=42 # id allocated by the hca for "layer"
96
+ /// +
97
+ //
98
+ ///
99
+ /// +
100
+ /// |
101
+ /// |
102
+ /// (12,42) |
103
+ /// content | # data's subspace for path "app","my-app"
104
+ /// subspace |
105
+ /// |
106
+ /// +
107
+ /// ```
108
+ /// In this schema:
109
+ ///
110
+ /// * vertical lines represents `Subspaces`,
111
+ /// * `()` `Tuples`,
112
+ /// * `#` comments.
113
+ ///
76
114
pub struct DirectoryLayer {
77
- /// the subspace used to store nodes.
115
+ /// the subspace used to store the hierarchy of paths. Each path is composed of Nodes.
116
+ /// Default is `Subspace::all()`.
78
117
pub node_subspace : Subspace ,
79
118
/// the subspace used to actually store the data.
119
+ /// Default is `Subspace::from_bytes(b"\xFE")`
80
120
pub content_subspace : Subspace ,
81
121
82
- /// The allocator used to generates i64 paths to shorten keys
122
+ /// The allocator used to generates i64 paths that will reduce keys's length.
123
+ /// Default HAC is using `Subspace::from_bytes(b"hca")` as the subspace.
83
124
pub allocator : HighContentionAllocator ,
84
125
85
126
pub allow_manual_prefixes : bool ,
86
127
87
128
pub path : Vec < String > ,
88
-
89
129
/// This is set at node creation time and never mutated by the directory layer.
90
130
/// If a layer is provided when opening nodes it checks to see that the layer matches nodes that are read.
91
131
/// When there's a mismatch an error is thrown.
@@ -104,62 +144,62 @@ impl Default for DirectoryLayer {
104
144
Subspace :: from_bytes ( DEFAULT_NODE_PREFIX ) . subspace ( & DEFAULT_HCA_PREFIX ) ,
105
145
) ,
106
146
allow_manual_prefixes : false ,
107
- path : vec ! [ ] ,
108
147
layer : vec ! [ ] ,
148
+ path : vec ! [ ] ,
109
149
}
110
150
}
111
151
}
112
152
113
153
impl DirectoryLayer {
114
- /// CreateOrOpen opens the directory specified by path (relative to this
154
+ /// ` CreateOrOpen` opens the directory specified by path (relative to this
115
155
/// Directory), and returns the directory and its contents as a
116
156
/// Subspace. If the directory does not exist, it is created
117
157
/// (creating parent directories if necessary).
118
158
pub async fn create_or_open (
119
159
& self ,
120
160
txn : & Transaction ,
121
- paths : Vec < String > ,
161
+ path : Vec < String > ,
122
162
) -> Result < Subspace , DirectoryError > {
123
- self . create_or_open_internal ( txn, paths , vec ! [ ] , true , true )
163
+ self . create_or_open_internal ( txn, path , vec ! [ ] , true , true )
124
164
. await
125
165
}
126
166
127
- /// Create creates a directory specified by path (relative to this
167
+ /// ` Create` creates a directory specified by path (relative to this
128
168
/// Directory), and returns the directory and its contents as a
129
169
/// Subspace (or ErrDirAlreadyExists if the directory already exists).
130
- pub async fn create ( & self , txn : & Transaction , paths : Vec < String > ) -> Option < DirectoryError > {
131
- self . create_or_open_internal ( txn, paths , vec ! [ ] , true , false )
170
+ pub async fn create ( & self , txn : & Transaction , path : Vec < String > ) -> Option < DirectoryError > {
171
+ self . create_or_open_internal ( txn, path , vec ! [ ] , true , false )
132
172
. await
133
173
. err ( )
134
174
}
135
175
136
- /// Open opens the directory specified by path (relative to this Directory),
176
+ /// ` Open` opens the directory specified by path (relative to this Directory),
137
177
/// and returns the directory and its contents as a Subspace (or Err(DirNotExists)
138
178
/// error if the directory does not exist, or ErrParentDirDoesNotExist if one of the parent
139
179
/// directories in the path does not exist).
140
180
pub async fn open (
141
181
& self ,
142
182
txn : & Transaction ,
143
- paths : Vec < String > ,
183
+ path : Vec < String > ,
144
184
) -> Result < Subspace , DirectoryError > {
145
- self . create_or_open_internal ( txn, paths , vec ! [ ] , false , true )
185
+ self . create_or_open_internal ( txn, path , vec ! [ ] , false , true )
146
186
. await
147
187
}
148
188
149
- /// Exists returns true if the directory at path (relative to the default root directory) exists, and false otherwise.
189
+ /// ` Exists` returns true if the directory at path (relative to the default root directory) exists, and false otherwise.
150
190
pub async fn exists (
151
191
& self ,
152
192
trx : & Transaction ,
153
- paths : Vec < String > ,
193
+ path : Vec < String > ,
154
194
) -> Result < bool , DirectoryError > {
155
- let nodes = self . find_nodes ( trx, paths . to_owned ( ) ) . await ?;
195
+ let nodes = self . find_nodes ( trx, path . to_owned ( ) ) . await ?;
156
196
match nodes. last ( ) {
157
197
None => Ok ( false ) ,
158
198
Some ( node) => Ok ( node. content_subspace . is_some ( ) ) ,
159
199
}
160
200
}
161
201
162
- /// Move moves the directory at oldPath to newPath (both relative to this
202
+ /// ` Move moves` the directory from old_path to new_path (both relative to this
163
203
/// Directory), and returns the directory (at its new location) and its
164
204
/// contents as a Subspace. Move will return an error if a directory
165
205
/// does not exist at oldPath, a directory already exists at newPath, or the
@@ -169,7 +209,7 @@ impl DirectoryLayer {
169
209
trx : & Transaction ,
170
210
old_path : Vec < String > ,
171
211
new_path : Vec < String > ,
172
- ) -> Result < bool , DirectoryError > {
212
+ ) -> Result < Subspace , DirectoryError > {
173
213
self . check_version ( trx, false ) . await ?;
174
214
175
215
if old_path. is_empty ( ) || new_path. is_empty ( ) {
@@ -182,14 +222,14 @@ impl DirectoryLayer {
182
222
183
223
let mut old_nodes = self . find_nodes ( & trx, old_path. to_owned ( ) ) . await ?;
184
224
let last_node_from_old_path = match old_nodes. last_mut ( ) {
185
- None => return Err ( DirectoryError :: Message ( String :: from ( "empty path" ) ) ) ,
225
+ None => return Err ( DirectoryError :: PathDoesNotExists ) ,
186
226
Some ( node) => node,
187
227
} ;
188
228
189
229
let content_subspace = last_node_from_old_path
190
230
. content_subspace
191
231
. as_ref ( )
192
- . ok_or ( DirectoryError :: DirNotExists ) ?;
232
+ . ok_or ( DirectoryError :: PathDoesNotExists ) ?;
193
233
194
234
let mut new_nodes = self . find_nodes ( & trx, new_path. to_owned ( ) ) . await ?;
195
235
@@ -205,7 +245,7 @@ impl DirectoryLayer {
205
245
}
206
246
207
247
let last_node_from_new_path = match new_nodes. last_mut ( ) {
208
- None => return Err ( DirectoryError :: Message ( String :: from ( "empty path" ) ) ) ,
248
+ None => return Err ( DirectoryError :: PathDoesNotExists ) ,
209
249
Some ( node) => {
210
250
if node. content_subspace . is_some ( ) {
211
251
return Err ( DirectoryError :: DirAlreadyExists ) ;
@@ -222,7 +262,7 @@ impl DirectoryLayer {
222
262
. delete_content_from_node_subspace ( & trx)
223
263
. await ?;
224
264
225
- Ok ( true )
265
+ Ok ( content_subspace . to_owned ( ) )
226
266
}
227
267
228
268
/// `Remove` the subdirectory of this Directory located at `path` and all of its subdirectories,
@@ -242,33 +282,33 @@ impl DirectoryLayer {
242
282
match nodes. last ( ) {
243
283
None => Ok ( false ) ,
244
284
Some ( node) => {
245
- println ! ( "found a node to delete: {:?}" , node) ;
246
285
node. delete_content_from_node_subspace ( & trx) . await ?;
247
286
node. delete_content_from_content_subspace ( & trx) . await ?;
248
287
Ok ( true )
249
288
}
250
289
}
251
290
}
252
291
253
- /// List returns the names of the immediate subdirectories of the default root directory as a slice of strings.
292
+ /// ` List` returns the names of the immediate subdirectories of the default root directory as a slice of strings.
254
293
/// Each string is the name of the last component of a subdirectory's path.
255
294
pub async fn list (
256
295
& self ,
257
296
trx : & Transaction ,
258
- paths : Vec < String > ,
297
+ path : Vec < String > ,
259
298
) -> Result < Vec < String > , DirectoryError > {
260
- let nodes = self . find_nodes ( trx, paths . to_owned ( ) ) . await ?;
299
+ let nodes = self . find_nodes ( trx, path . to_owned ( ) ) . await ?;
261
300
262
301
match nodes. last ( ) {
263
- None => Err ( DirectoryError :: DirNotExists ) ,
302
+ None => Err ( DirectoryError :: PathDoesNotExists ) ,
264
303
Some ( node) => node. list ( & trx) . await ,
265
304
}
266
305
}
267
306
307
+ /// `create_or_open_internal` is the function used to open and/or create a directory.
268
308
async fn create_or_open_internal (
269
309
& self ,
270
310
trx : & Transaction ,
271
- paths : Vec < String > ,
311
+ path : Vec < String > ,
272
312
prefix : Vec < u8 > ,
273
313
allow_create : bool ,
274
314
allow_open : bool ,
@@ -277,21 +317,17 @@ impl DirectoryLayer {
277
317
278
318
if !prefix. is_empty ( ) && !self . allow_manual_prefixes {
279
319
if self . path . is_empty ( ) {
280
- return Err ( DirectoryError :: Message (
281
- "cannot specify a prefix unless manual prefixes are enabled" . to_string ( ) ,
282
- ) ) ;
320
+ return Err ( DirectoryError :: PrefixNotAllowed ) ;
283
321
}
284
322
285
- return Err ( DirectoryError :: Message (
286
- "cannot specify a prefix in a partition" . to_string ( ) ,
287
- ) ) ;
323
+ return Err ( DirectoryError :: CannotPrefixInPartition ) ;
288
324
}
289
325
290
- if paths . is_empty ( ) {
326
+ if path . is_empty ( ) {
291
327
return Err ( DirectoryError :: NoPathProvided ) ;
292
328
}
293
329
294
- let nodes = self . find_nodes ( trx, paths . to_owned ( ) ) . await ?;
330
+ let nodes = self . find_nodes ( trx, path . to_owned ( ) ) . await ?;
295
331
296
332
let last_node = nodes. last ( ) . expect ( "could not contain 0 nodes" ) ;
297
333
@@ -313,7 +349,7 @@ impl DirectoryLayer {
313
349
314
350
// at least one node does not exists, we need to create them
315
351
if !allow_create {
316
- return Err ( DirectoryError :: DirNotExists ) ;
352
+ return Err ( DirectoryError :: PathDoesNotExists ) ;
317
353
}
318
354
319
355
let mut parent_subspace = self . content_subspace . clone ( ) ;
@@ -333,7 +369,7 @@ impl DirectoryLayer {
333
369
Ok ( parent_subspace)
334
370
}
335
371
336
- /// checks the version of the directory within FDB
372
+ /// `check_version` is checking the Directory's version in FDB.
337
373
async fn check_version (
338
374
& self ,
339
375
trx : & Transaction ,
@@ -345,7 +381,7 @@ impl DirectoryLayer {
345
381
if allow_creation {
346
382
self . initialize_directory ( trx) . await
347
383
} else {
348
- Err ( DirectoryError :: DirNotExists )
384
+ Err ( DirectoryError :: MissingDirectory )
349
385
}
350
386
}
351
387
Some ( versions) => {
@@ -379,6 +415,7 @@ impl DirectoryLayer {
379
415
}
380
416
}
381
417
418
+ /// `initialize_directory` is initializing the directory
382
419
async fn initialize_directory ( & self , trx : & Transaction ) -> Result < ( ) , DirectoryError > {
383
420
let mut value = vec ! [ ] ;
384
421
value. write_u32 :: < LittleEndian > ( MAJOR_VERSION ) . unwrap ( ) ;
@@ -398,23 +435,23 @@ impl DirectoryLayer {
398
435
async fn find_nodes (
399
436
& self ,
400
437
trx : & Transaction ,
401
- paths : Vec < String > ,
438
+ path : Vec < String > ,
402
439
) -> Result < Vec < Node > , FdbError > {
403
440
let mut nodes = vec ! [ ] ;
404
441
405
442
let mut subspace = self . node_subspace . to_owned ( ) ;
406
443
407
444
let mut node_path = vec ! [ ] ;
408
445
409
- for path_name in paths {
446
+ for path_name in path {
410
447
node_path. push ( path_name. to_owned ( ) ) ;
411
448
subspace = subspace. subspace :: < ( & [ u8 ] , String ) > ( & (
412
449
vec ! [ DEFAULT_SUB_DIRS ] . as_slice ( ) ,
413
450
path_name. to_owned ( ) ,
414
451
) ) ;
415
452
416
453
let mut node = Node {
417
- paths : node_path. clone ( ) ,
454
+ path : node_path. clone ( ) ,
418
455
layer : None ,
419
456
node_subspace : subspace. to_owned ( ) ,
420
457
content_subspace : None ,
@@ -423,7 +460,6 @@ impl DirectoryLayer {
423
460
node. retrieve_layer ( & trx) . await ?;
424
461
425
462
if let Some ( fdb_slice) = trx. get ( node. node_subspace . bytes ( ) , false ) . await ? {
426
- println ! ( "found something in {:?}" , node. node_subspace. to_owned( ) ) ;
427
463
node. content_subspace = Some ( Subspace :: from_bytes ( & * fdb_slice) ) ;
428
464
}
429
465
0 commit comments