Skip to content

Commit be40732

Browse files
committed
chore(foundationdb): improve documentation and errors's handling
1 parent 6948175 commit be40732

File tree

4 files changed

+101
-54
lines changed

4 files changed

+101
-54
lines changed

foundationdb/src/directory/error.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,22 @@ pub enum DirectoryError {
2020
NoPathProvided,
2121
/// tried to create an already existing path.
2222
DirAlreadyExists,
23-
/// missing path.
24-
DirNotExists,
23+
/// missing directory.
24+
PathDoesNotExists,
25+
/// Directory does not exists
26+
MissingDirectory,
2527
/// Parent does not exists
2628
ParentDirDoesNotExists,
2729
/// the layer is incompatible.
2830
IncompatibleLayer,
2931
/// the destination directory cannot be a subdirectory of the source directory.
3032
BadDestinationDirectory,
31-
Message(String),
3233
/// Bad directory version.
3334
Version(String),
35+
/// cannot specify a prefix unless manual prefixes are enabled
36+
PrefixNotAllowed,
37+
/// cannot specify a prefix in a partition.
38+
CannotPrefixInPartition,
3439
IoError(io::Error),
3540
FdbError(error::FdbError),
3641
HcaError(HcaError),

foundationdb/src/directory/mod.rs

Lines changed: 79 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use crate::tuple::Subspace;
2222
use crate::{FdbError, FdbResult, Transaction};
2323
use byteorder::{LittleEndian, WriteBytesExt};
2424

25+
// TODO: useful?
2526
const _LAYER_VERSION: (u8, u8, u8) = (1, 0, 0);
2627
const MAJOR_VERSION: u32 = 1;
2728
const MINOR_VERSION: u32 = 0;
@@ -73,19 +74,58 @@ const DEFAULT_SUB_DIRS: u8 = 0;
7374
/// futures::executor::block_on(async_main()).expect("failed to run");
7475
/// drop(network);
7576
/// ```
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+
///
76114
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()`.
78117
pub node_subspace: Subspace,
79118
/// the subspace used to actually store the data.
119+
/// Default is `Subspace::from_bytes(b"\xFE")`
80120
pub content_subspace: Subspace,
81121

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.
83124
pub allocator: HighContentionAllocator,
84125

85126
pub allow_manual_prefixes: bool,
86127

87128
pub path: Vec<String>,
88-
89129
/// This is set at node creation time and never mutated by the directory layer.
90130
/// If a layer is provided when opening nodes it checks to see that the layer matches nodes that are read.
91131
/// When there's a mismatch an error is thrown.
@@ -104,62 +144,62 @@ impl Default for DirectoryLayer {
104144
Subspace::from_bytes(DEFAULT_NODE_PREFIX).subspace(&DEFAULT_HCA_PREFIX),
105145
),
106146
allow_manual_prefixes: false,
107-
path: vec![],
108147
layer: vec![],
148+
path: vec![],
109149
}
110150
}
111151
}
112152

113153
impl DirectoryLayer {
114-
/// CreateOrOpen opens the directory specified by path (relative to this
154+
/// `CreateOrOpen` opens the directory specified by path (relative to this
115155
/// Directory), and returns the directory and its contents as a
116156
/// Subspace. If the directory does not exist, it is created
117157
/// (creating parent directories if necessary).
118158
pub async fn create_or_open(
119159
&self,
120160
txn: &Transaction,
121-
paths: Vec<String>,
161+
path: Vec<String>,
122162
) -> 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)
124164
.await
125165
}
126166

127-
/// Create creates a directory specified by path (relative to this
167+
/// `Create` creates a directory specified by path (relative to this
128168
/// Directory), and returns the directory and its contents as a
129169
/// 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)
132172
.await
133173
.err()
134174
}
135175

136-
/// Open opens the directory specified by path (relative to this Directory),
176+
/// `Open` opens the directory specified by path (relative to this Directory),
137177
/// and returns the directory and its contents as a Subspace (or Err(DirNotExists)
138178
/// error if the directory does not exist, or ErrParentDirDoesNotExist if one of the parent
139179
/// directories in the path does not exist).
140180
pub async fn open(
141181
&self,
142182
txn: &Transaction,
143-
paths: Vec<String>,
183+
path: Vec<String>,
144184
) -> 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)
146186
.await
147187
}
148188

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.
150190
pub async fn exists(
151191
&self,
152192
trx: &Transaction,
153-
paths: Vec<String>,
193+
path: Vec<String>,
154194
) -> 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?;
156196
match nodes.last() {
157197
None => Ok(false),
158198
Some(node) => Ok(node.content_subspace.is_some()),
159199
}
160200
}
161201

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
163203
/// Directory), and returns the directory (at its new location) and its
164204
/// contents as a Subspace. Move will return an error if a directory
165205
/// does not exist at oldPath, a directory already exists at newPath, or the
@@ -169,7 +209,7 @@ impl DirectoryLayer {
169209
trx: &Transaction,
170210
old_path: Vec<String>,
171211
new_path: Vec<String>,
172-
) -> Result<bool, DirectoryError> {
212+
) -> Result<Subspace, DirectoryError> {
173213
self.check_version(trx, false).await?;
174214

175215
if old_path.is_empty() || new_path.is_empty() {
@@ -182,14 +222,14 @@ impl DirectoryLayer {
182222

183223
let mut old_nodes = self.find_nodes(&trx, old_path.to_owned()).await?;
184224
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),
186226
Some(node) => node,
187227
};
188228

189229
let content_subspace = last_node_from_old_path
190230
.content_subspace
191231
.as_ref()
192-
.ok_or(DirectoryError::DirNotExists)?;
232+
.ok_or(DirectoryError::PathDoesNotExists)?;
193233

194234
let mut new_nodes = self.find_nodes(&trx, new_path.to_owned()).await?;
195235

@@ -205,7 +245,7 @@ impl DirectoryLayer {
205245
}
206246

207247
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),
209249
Some(node) => {
210250
if node.content_subspace.is_some() {
211251
return Err(DirectoryError::DirAlreadyExists);
@@ -222,7 +262,7 @@ impl DirectoryLayer {
222262
.delete_content_from_node_subspace(&trx)
223263
.await?;
224264

225-
Ok(true)
265+
Ok(content_subspace.to_owned())
226266
}
227267

228268
/// `Remove` the subdirectory of this Directory located at `path` and all of its subdirectories,
@@ -242,33 +282,33 @@ impl DirectoryLayer {
242282
match nodes.last() {
243283
None => Ok(false),
244284
Some(node) => {
245-
println!("found a node to delete: {:?}", node);
246285
node.delete_content_from_node_subspace(&trx).await?;
247286
node.delete_content_from_content_subspace(&trx).await?;
248287
Ok(true)
249288
}
250289
}
251290
}
252291

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.
254293
/// Each string is the name of the last component of a subdirectory's path.
255294
pub async fn list(
256295
&self,
257296
trx: &Transaction,
258-
paths: Vec<String>,
297+
path: Vec<String>,
259298
) -> 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?;
261300

262301
match nodes.last() {
263-
None => Err(DirectoryError::DirNotExists),
302+
None => Err(DirectoryError::PathDoesNotExists),
264303
Some(node) => node.list(&trx).await,
265304
}
266305
}
267306

307+
/// `create_or_open_internal` is the function used to open and/or create a directory.
268308
async fn create_or_open_internal(
269309
&self,
270310
trx: &Transaction,
271-
paths: Vec<String>,
311+
path: Vec<String>,
272312
prefix: Vec<u8>,
273313
allow_create: bool,
274314
allow_open: bool,
@@ -277,21 +317,17 @@ impl DirectoryLayer {
277317

278318
if !prefix.is_empty() && !self.allow_manual_prefixes {
279319
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);
283321
}
284322

285-
return Err(DirectoryError::Message(
286-
"cannot specify a prefix in a partition".to_string(),
287-
));
323+
return Err(DirectoryError::CannotPrefixInPartition);
288324
}
289325

290-
if paths.is_empty() {
326+
if path.is_empty() {
291327
return Err(DirectoryError::NoPathProvided);
292328
}
293329

294-
let nodes = self.find_nodes(trx, paths.to_owned()).await?;
330+
let nodes = self.find_nodes(trx, path.to_owned()).await?;
295331

296332
let last_node = nodes.last().expect("could not contain 0 nodes");
297333

@@ -313,7 +349,7 @@ impl DirectoryLayer {
313349

314350
// at least one node does not exists, we need to create them
315351
if !allow_create {
316-
return Err(DirectoryError::DirNotExists);
352+
return Err(DirectoryError::PathDoesNotExists);
317353
}
318354

319355
let mut parent_subspace = self.content_subspace.clone();
@@ -333,7 +369,7 @@ impl DirectoryLayer {
333369
Ok(parent_subspace)
334370
}
335371

336-
/// checks the version of the directory within FDB
372+
/// `check_version` is checking the Directory's version in FDB.
337373
async fn check_version(
338374
&self,
339375
trx: &Transaction,
@@ -345,7 +381,7 @@ impl DirectoryLayer {
345381
if allow_creation {
346382
self.initialize_directory(trx).await
347383
} else {
348-
Err(DirectoryError::DirNotExists)
384+
Err(DirectoryError::MissingDirectory)
349385
}
350386
}
351387
Some(versions) => {
@@ -379,6 +415,7 @@ impl DirectoryLayer {
379415
}
380416
}
381417

418+
/// `initialize_directory` is initializing the directory
382419
async fn initialize_directory(&self, trx: &Transaction) -> Result<(), DirectoryError> {
383420
let mut value = vec![];
384421
value.write_u32::<LittleEndian>(MAJOR_VERSION).unwrap();
@@ -398,23 +435,23 @@ impl DirectoryLayer {
398435
async fn find_nodes(
399436
&self,
400437
trx: &Transaction,
401-
paths: Vec<String>,
438+
path: Vec<String>,
402439
) -> Result<Vec<Node>, FdbError> {
403440
let mut nodes = vec![];
404441

405442
let mut subspace = self.node_subspace.to_owned();
406443

407444
let mut node_path = vec![];
408445

409-
for path_name in paths {
446+
for path_name in path {
410447
node_path.push(path_name.to_owned());
411448
subspace = subspace.subspace::<(&[u8], String)>(&(
412449
vec![DEFAULT_SUB_DIRS].as_slice(),
413450
path_name.to_owned(),
414451
));
415452

416453
let mut node = Node {
417-
paths: node_path.clone(),
454+
path: node_path.clone(),
418455
layer: None,
419456
node_subspace: subspace.to_owned(),
420457
content_subspace: None,
@@ -423,7 +460,6 @@ impl DirectoryLayer {
423460
node.retrieve_layer(&trx).await?;
424461

425462
if let Some(fdb_slice) = trx.get(node.node_subspace.bytes(), false).await? {
426-
println!("found something in {:?}", node.node_subspace.to_owned());
427463
node.content_subspace = Some(Subspace::from_bytes(&*fdb_slice));
428464
}
429465

foundationdb/src/directory/node.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,26 @@ use crate::tuple::Subspace;
1111
use crate::{FdbError, RangeOption, Transaction};
1212

1313
/// Node are used to represent the paths generated by a Directory.
14-
/// They are stored in the `Directory.`
14+
/// They are stored in the `Directory.node_subspace``.
1515
#[derive(Debug)]
1616
pub(crate) struct Node {
17+
/// The layer is checked during opening, if it does not match the layer
18+
/// stored, an Error is thrown. It can be used as some ownership's feature
19+
/// on a path.
1720
pub(crate) layer: Option<Vec<u8>>,
1821

19-
pub(crate) paths: Vec<String>,
22+
/// the current path of a node.
23+
pub(crate) path: Vec<String>,
2024

25+
/// the node_space of this node,
2126
pub(crate) node_subspace: Subspace,
27+
/// the content_subspace of this node.
2228
pub(crate) content_subspace: Option<Subspace>,
2329
}
2430

2531
impl Node {
32+
/// `check_layer` is checking the layer, throwing `IncompatibleLayer` when
33+
/// the provided layer does not match the one provided.
2634
pub(crate) fn check_layer(&self, layer: Vec<u8>) -> Result<(), DirectoryError> {
2735
match &self.layer {
2836
None => Err(DirectoryError::IncompatibleLayer),
@@ -72,10 +80,10 @@ impl Node {
7280
&self.node_subspace.to_owned()
7381
);
7482
trx.clear(&self.node_subspace.bytes());
75-
//trx.clear_subspace_range(&self.node_subspace.to_owned());
7683
Ok(())
7784
}
7885

86+
/// delete subspace from the content_subspace
7987
pub(crate) async fn delete_content_from_content_subspace(
8088
&self,
8189
trx: &Transaction,

0 commit comments

Comments
 (0)