7
7
// copied, modified, or distributed except according to those terms.
8
8
9
9
use crate :: directory:: node;
10
+ use crate :: directory:: node:: Node ;
10
11
use crate :: future:: FdbSlice ;
11
12
use crate :: tuple:: hca:: HighContentionAllocator ;
12
13
use crate :: tuple:: { pack_into, Subspace } ;
@@ -59,20 +60,30 @@ impl Default for DirectoryLayer {
59
60
}
60
61
61
62
impl DirectoryLayer {
62
- fn get_path ( & self ) -> Vec < String > {
63
- self . path . to_owned ( )
63
+ pub async fn create_or_open (
64
+ & self ,
65
+ txn : & Transaction ,
66
+ paths : Vec < String > ,
67
+ ) -> Result < Subspace , DirectoryError > {
68
+ self . create_or_open_internal ( txn, paths, vec ! [ ] , vec ! [ ] , true , true )
69
+ . await
64
70
}
65
71
66
- fn get_layer ( & self ) -> Vec < u8 > {
67
- self . layer . to_owned ( )
72
+ pub async fn create (
73
+ & self ,
74
+ txn : & Transaction ,
75
+ paths : Vec < String > ,
76
+ ) -> Result < Subspace , DirectoryError > {
77
+ self . create_or_open_internal ( txn, paths, vec ! [ ] , vec ! [ ] , true , false )
78
+ . await
68
79
}
69
80
70
- pub async fn create_or_open (
81
+ pub async fn open (
71
82
& self ,
72
83
txn : & Transaction ,
73
84
paths : Vec < String > ,
74
85
) -> Result < Subspace , DirectoryError > {
75
- self . create_or_open_internal ( txn, paths, vec ! [ ] , vec ! [ ] , true , true )
86
+ self . create_or_open_internal ( txn, paths, vec ! [ ] , vec ! [ ] , false , true )
76
87
. await
77
88
}
78
89
@@ -103,11 +114,15 @@ impl DirectoryLayer {
103
114
return Err ( DirectoryError :: NoPathProvided ) ;
104
115
}
105
116
106
- let mut node = self . find ( trx, paths. to_owned ( ) ) . await ?;
107
- node. prefetch_metadata ( trx) . await ?;
117
+ let nodes = self . find_nodes ( trx, paths. to_owned ( ) ) . await ?;
118
+
119
+ let last_node = nodes. last ( ) . expect ( "could not contain 0 nodes" ) ;
120
+
121
+ // if the node_subspace of the last element exists, then we do not need to create anything
122
+ // and we can return it directly
123
+ if last_node. content_subspace . is_some ( ) {
124
+ let node = nodes. last ( ) . expect ( "could not contain 0 node" ) ;
108
125
109
- // subspace already exists
110
- if node. content_subspace . is_some ( ) {
111
126
if !allow_open {
112
127
return Err ( DirectoryError :: DirAlreadyExists ) ;
113
128
}
@@ -116,34 +131,21 @@ impl DirectoryLayer {
116
131
node. check_layer ( layer) ?;
117
132
}
118
133
119
- return Ok ( node. content_subspace . unwrap ( ) . to_owned ( ) ) ;
134
+ return Ok ( node. content_subspace . clone ( ) . unwrap ( ) ) ;
120
135
}
121
136
122
- // subspace does not exists
137
+ // at least one node does not exists, we need to create them
123
138
if !allow_create {
124
139
return Err ( DirectoryError :: DirNotExists ) ;
125
140
}
126
141
127
- if prefix. len ( ) > 0 {
128
- unimplemented ! ( "no prefix allowed yet" )
129
- }
142
+ let mut subspace = self . content_subspace . clone ( ) ;
130
143
131
- if paths. len ( ) != 1 {
132
- unimplemented ! ( "paths too long for now" )
144
+ for mut node in nodes {
145
+ let allocator = self . allocator . allocate ( trx) . await ?;
146
+ subspace = node. create_subspace ( & trx, allocator, & subspace) . await ?;
133
147
}
134
-
135
- let allocator = self . allocator . allocate ( trx) . await ?;
136
- let new_subspace = self . content_subspace . subspace ( & allocator) ;
137
-
138
- // store node in the node_subspace
139
- let mut new_node_key = vec ! [ DEFAULT_SUB_DIRS ] ;
140
- pack_into ( paths. get ( 0 ) . unwrap ( ) , & mut new_node_key) ;
141
- trx. set (
142
- self . node_subspace . subspace ( & new_node_key) . bytes ( ) ,
143
- new_subspace. bytes ( ) ,
144
- ) ;
145
-
146
- Ok ( new_subspace)
148
+ Ok ( subspace)
147
149
}
148
150
149
151
async fn check_version (
@@ -195,42 +197,46 @@ impl DirectoryLayer {
195
197
value. write_u32 :: < LittleEndian > ( MINOR_VERSION ) . unwrap ( ) ;
196
198
value. write_u32 :: < LittleEndian > ( PATCH_VERSION ) . unwrap ( ) ;
197
199
let version_subspace: & [ u8 ] = b"version" ;
198
- let version_key = self . node_subspace . subspace ( & version_subspace) ;
199
-
200
- trx. set ( version_key. bytes ( ) , & value) ;
200
+ let directory_version_key = self . node_subspace . subspace ( & version_subspace) ;
201
+ trx. set ( directory_version_key. bytes ( ) , & value) ;
201
202
202
203
Ok ( ( ) )
203
204
}
204
205
205
- async fn find ( & self , trx : & Transaction , path : Vec < String > ) -> Result < node:: Node , FdbError > {
206
- let mut node = node:: Node {
207
- subspace : self . node_subspace . to_owned ( ) ,
208
- path : path. to_owned ( ) ,
209
- target_path : vec ! [ ] ,
210
- layer : None ,
211
- content_subspace : None ,
212
- already_fetched_metadata : false ,
213
- } ;
214
- for path_name in path. to_owned ( ) {
206
+ /// walk is crawling the node_subspace and searching for the nodes
207
+ /// Result will hold a Vec with at least two nodes: root node and as many nodes as paths
208
+ async fn find_nodes (
209
+ & self ,
210
+ trx : & Transaction ,
211
+ paths : Vec < String > ,
212
+ ) -> Result < Vec < node:: Node > , FdbError > {
213
+ let mut nodes = vec ! [ ] ;
214
+
215
+ let mut subspace = self . node_subspace . to_owned ( ) ;
216
+
217
+ for path_name in paths {
215
218
let mut next_node_key = vec ! [ DEFAULT_SUB_DIRS ] ;
216
219
pack_into ( & path_name, & mut next_node_key) ;
217
- let next_node_subspace = node . subspace . subspace ( & next_node_key) ;
220
+ subspace = subspace. subspace ( & next_node_key) ;
218
221
219
- match trx. get ( next_node_subspace. bytes ( ) , false ) . await ? {
220
- None => {
221
- if !path. ends_with ( & [ path_name] ) {
222
- unimplemented ! ( "node not found" )
223
- }
224
- }
222
+ let mut node = Node {
223
+ layer : None ,
224
+ node_subspace : subspace. to_owned ( ) ,
225
+ content_subspace : None ,
226
+ } ;
227
+
228
+ node. retrieve_layer ( & trx) . await ?;
229
+
230
+ match trx. get ( node. node_subspace . bytes ( ) , false ) . await ? {
225
231
Some ( fdb_slice) => {
226
- node. subspace = next_node_subspace;
227
232
node. content_subspace = Some ( Subspace :: from_bytes ( & * fdb_slice) ) ;
228
- node. path . push ( path_name. to_owned ( ) ) ;
229
233
}
234
+ _ => { } // noop in case of a none existing node
230
235
}
236
+ nodes. push ( node) ;
231
237
}
232
238
233
- Ok ( node )
239
+ Ok ( nodes )
234
240
}
235
241
236
242
async fn get_version_value ( & self , trx : & Transaction ) -> FdbResult < Option < FdbSlice > > {
0 commit comments