Skip to content

Commit d80ba4c

Browse files
committed
fix(foundationdb): add compatibility with other bindings
*Motivation* Previous commits were not compatible with other bindings, so everything has been manually checked with the `Go` binding. Before reimplement `delete` and `move`, I will include the `binding-checker` to validate that everything is working properly.
1 parent 4c55038 commit d80ba4c

File tree

3 files changed

+76
-417
lines changed

3 files changed

+76
-417
lines changed

foundationdb/src/directory/mod.rs

Lines changed: 66 additions & 164 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use crate::directory::node::Node;
1919
use crate::future::FdbSlice;
2020
use crate::tuple::hca::HighContentionAllocator;
2121
use crate::tuple::Subspace;
22-
use crate::{FdbError, FdbResult, Transaction};
22+
use crate::{FdbResult, Transaction};
2323
use byteorder::{LittleEndian, WriteBytesExt};
2424

2525
// TODO: useful?
@@ -29,7 +29,7 @@ const MINOR_VERSION: u32 = 0;
2929
const PATCH_VERSION: u32 = 0;
3030
const DEFAULT_NODE_PREFIX: &[u8] = b"\xFE";
3131
const DEFAULT_HCA_PREFIX: &[u8] = b"hca";
32-
const DEFAULT_SUB_DIRS: u8 = 0;
32+
const DEFAULT_SUB_DIRS: i64 = 0;
3333

3434
/// An implementation of FoundationDB's directory that is compatible with other bindings.
3535
///
@@ -205,11 +205,9 @@ impl DirectoryLayer {
205205
trx: &Transaction,
206206
path: Vec<String>,
207207
) -> Result<bool, DirectoryError> {
208-
let nodes = self.find_nodes(trx, path.to_owned()).await?;
209-
match nodes.last() {
210-
None => Ok(false),
211-
Some(node) => Ok(node.content_subspace.is_some()),
212-
}
208+
self.find_node(trx, path.to_owned(), false)
209+
.await
210+
.map(|_| true)
213211
}
214212

215213
/// `move_to` the directory from old_path to new_path(both relative to this
@@ -219,87 +217,21 @@ impl DirectoryLayer {
219217
/// parent directory of newPath does not exist.
220218
pub async fn move_to(
221219
&self,
222-
trx: &Transaction,
223-
old_path: Vec<String>,
224-
new_path: Vec<String>,
220+
_trx: &Transaction,
221+
_old_path: Vec<String>,
222+
_new_path: Vec<String>,
225223
) -> Result<Subspace, DirectoryError> {
226-
self.check_version(trx, false).await?;
227-
228-
if old_path.is_empty() || new_path.is_empty() {
229-
return Err(DirectoryError::NoPathProvided);
230-
}
231-
232-
if new_path.starts_with(old_path.as_slice()) {
233-
return Err(DirectoryError::BadDestinationDirectory);
234-
}
235-
236-
let mut old_nodes = self.find_nodes(&trx, old_path.to_owned()).await?;
237-
let last_node_from_old_path = match old_nodes.last_mut() {
238-
None => return Err(DirectoryError::PathDoesNotExists),
239-
Some(node) => node,
240-
};
241-
242-
let content_subspace = last_node_from_old_path
243-
.content_subspace
244-
.as_ref()
245-
.ok_or(DirectoryError::PathDoesNotExists)?;
246-
247-
let mut new_nodes = self.find_nodes(&trx, new_path.to_owned()).await?;
248-
249-
// assert that parent of the new node exists
250-
if new_nodes.len() >= 2 {
251-
match new_nodes.get(new_nodes.len() - 2) {
252-
None => {}
253-
Some(parent_node) => match parent_node.content_subspace {
254-
None => return Err(DirectoryError::ParentDirDoesNotExists),
255-
Some(_) => {}
256-
},
257-
}
258-
}
259-
260-
let last_node_from_new_path = match new_nodes.last_mut() {
261-
None => return Err(DirectoryError::PathDoesNotExists),
262-
Some(node) => {
263-
if node.content_subspace.is_some() {
264-
return Err(DirectoryError::DirAlreadyExists);
265-
}
266-
node
267-
}
268-
};
269-
270-
last_node_from_new_path
271-
.persist_content_subspace(&trx, content_subspace.to_owned())
272-
.await?;
273-
274-
last_node_from_old_path
275-
.delete_content_from_node_subspace(&trx)
276-
.await?;
277-
278-
Ok(content_subspace.to_owned())
224+
unimplemented!()
279225
}
280226

281227
/// `remove` the subdirectory of this Directory located at `path` and all of its subdirectories,
282228
/// as well as all of their contents.
283229
pub async fn remove(
284230
&self,
285-
trx: &Transaction,
286-
path: Vec<String>,
231+
_trx: &Transaction,
232+
_path: Vec<String>,
287233
) -> Result<bool, DirectoryError> {
288-
self.check_version(trx, false).await?;
289-
if path.is_empty() {
290-
return Err(DirectoryError::NoPathProvided);
291-
}
292-
293-
let nodes = self.find_nodes(&trx, path.to_owned()).await?;
294-
295-
match nodes.last() {
296-
None => Ok(false),
297-
Some(node) => {
298-
node.delete_content_from_node_subspace(&trx).await?;
299-
node.delete_content_from_content_subspace(&trx).await?;
300-
Ok(true)
301-
}
302-
}
234+
unimplemented!()
303235
}
304236

305237
/// `list` returns the names of the immediate subdirectories of the default root directory as a slice of strings.
@@ -309,12 +241,8 @@ impl DirectoryLayer {
309241
trx: &Transaction,
310242
path: Vec<String>,
311243
) -> Result<Vec<String>, DirectoryError> {
312-
let nodes = self.find_nodes(trx, path.to_owned()).await?;
313-
314-
match nodes.last() {
315-
None => Err(DirectoryError::PathDoesNotExists),
316-
Some(node) => node.list(&trx).await,
317-
}
244+
let node = self.find_node(trx, path.to_owned(), false).await?;
245+
node.list(&trx).await
318246
}
319247

320248
/// `create_or_open_internal` is the function used to open and/or create a directory.
@@ -340,64 +268,20 @@ impl DirectoryLayer {
340268
return Err(DirectoryError::NoPathProvided);
341269
}
342270

343-
let mut nodes = self.find_nodes(trx, path.to_owned()).await?;
344-
345-
let last_node = nodes.last().expect("could not contain 0 nodes");
346-
347-
// if the node_subspace of the last element exists, then we do not need to create anything
348-
// and we can return it directly
349-
if last_node.content_subspace.is_some() {
350-
let node = nodes.last().expect("could not contain 0 node");
351-
352-
if !allow_open {
353-
return Err(DirectoryError::DirAlreadyExists);
354-
}
355-
356-
if !self.layer.is_empty() {
357-
node.check_layer(self.layer.to_owned())?;
358-
}
359-
360-
return Ok(node.content_subspace.clone().unwrap());
361-
}
362-
363-
// at least one node does not exists, we need to create them
364-
if !allow_create {
365-
return Err(DirectoryError::PathDoesNotExists);
366-
}
367-
368-
let (last, parent_nodes) = nodes.split_last_mut().expect("already checked");
369-
370-
// let's create parents first.
371-
let mut parent_subspace = self.content_subspace.clone();
372-
for parent_node in parent_nodes {
373-
match &parent_node.content_subspace {
374-
None => {
375-
// creating subspace
376-
let allocator = self.allocator.allocate(trx).await?;
377-
parent_subspace = parent_node
378-
.create_and_write_content_subspace(&trx, allocator, &parent_subspace)
379-
.await?;
271+
match self.find_node(&trx, path.to_owned(), allow_create).await {
272+
Ok(node) => {
273+
// node exists, checking layer
274+
if !allow_open {
275+
return Err(DirectoryError::DirAlreadyExists);
380276
}
381-
Some(subspace) => {
382-
parent_subspace = subspace.clone();
277+
278+
if !self.layer.is_empty() {
279+
node.check_layer(self.layer.to_owned())?;
383280
}
384-
}
385-
}
386281

387-
// parents are created, let's create the final node
388-
match prefix {
389-
None => {
390-
let allocator = self.allocator.allocate(trx).await?;
391-
parent_subspace = last
392-
.create_and_write_content_subspace(&trx, allocator, &parent_subspace)
393-
.await?;
394-
Ok(parent_subspace)
395-
}
396-
Some(prefix) => {
397-
last.persist_prefix_as_content_subspace(&trx, prefix.to_owned())
398-
.await?;
399-
Ok(Subspace::from_bytes(prefix.as_ref()))
282+
Ok(node.content_subspace.clone().unwrap())
400283
}
284+
Err(err) => Err(err),
401285
}
402286
}
403287

@@ -454,56 +338,74 @@ impl DirectoryLayer {
454338
value.write_u32::<LittleEndian>(MINOR_VERSION).unwrap();
455339
value.write_u32::<LittleEndian>(PATCH_VERSION).unwrap();
456340
let version_subspace: &[u8] = b"version";
457-
let directory_version_key = self.node_subspace.subspace(&version_subspace);
341+
let directory_version_key = self.get_root_node_subspace().subspace(&version_subspace);
458342
trx.set(directory_version_key.bytes(), &value);
459343

460344
Ok(())
461345
}
462346

463-
/// walk is crawling the node_subspace and searching for the nodes.
464-
/// It returns a Vec of `Node`, each node represents an element of the paths provided.
465-
///
466-
/// If all paths are already existing, then the last node will have the content_subspace set.
467-
async fn find_nodes(
347+
async fn find_node(
468348
&self,
469349
trx: &Transaction,
470350
path: Vec<String>,
471-
) -> Result<Vec<Node>, FdbError> {
472-
let mut nodes = vec![];
473-
474-
let mut subspace = self.node_subspace.to_owned();
475-
351+
allow_creation: bool,
352+
) -> Result<Node, DirectoryError> {
353+
let mut node = Node {
354+
layer: None,
355+
path: vec![],
356+
node_subspace: self.get_root_node_subspace(),
357+
content_subspace: None,
358+
};
476359
let mut node_path = vec![];
477360

478361
for path_name in path {
479362
node_path.push(path_name.to_owned());
480-
subspace = subspace.subspace::<(&[u8], String)>(&(
481-
vec![DEFAULT_SUB_DIRS].as_slice(),
482-
path_name.to_owned(),
483-
));
363+
let key = node
364+
.node_subspace
365+
.subspace(&(DEFAULT_SUB_DIRS, path_name.to_owned()));
366+
367+
let (prefix, new_node) = match trx.get(key.bytes(), false).await {
368+
Ok(value) => match value {
369+
None => {
370+
if !allow_creation {
371+
return Err(DirectoryError::PathDoesNotExists);
372+
}
373+
// creating the subspace for this not-existing node
374+
let allocator = self.allocator.allocate(trx).await?;
375+
let subspace = self.content_subspace.subspace(&allocator);
376+
(subspace.bytes().to_vec(), true)
377+
}
378+
Some(fdb_slice) => ((&*fdb_slice).to_vec(), false),
379+
},
380+
Err(err) => return Err(DirectoryError::FdbError(err)),
381+
};
484382

485-
let mut node = Node {
383+
node = Node {
486384
path: node_path.clone(),
487385
layer: None,
488-
node_subspace: subspace.to_owned(),
489-
content_subspace: None,
386+
node_subspace: self.node_subspace.subspace(&prefix.as_slice()),
387+
content_subspace: Some(Subspace::from_bytes(&prefix.as_slice())),
490388
};
491389

492390
node.retrieve_layer(&trx).await?;
493391

494-
if let Some(fdb_slice) = trx.get(node.node_subspace.bytes(), false).await? {
495-
node.content_subspace = Some(Subspace::from_bytes(&*fdb_slice));
392+
if new_node {
393+
trx.set(key.bytes(), prefix.as_slice());
496394
}
497-
498-
nodes.push(node);
499395
}
500396

501-
Ok(nodes)
397+
Ok(node)
398+
}
399+
400+
fn get_root_node_subspace(&self) -> Subspace {
401+
return self
402+
.node_subspace
403+
.subspace::<&[u8]>(&self.node_subspace.bytes());
502404
}
503405

504406
async fn get_version_value(&self, trx: &Transaction) -> FdbResult<Option<FdbSlice>> {
505407
let version_subspace: &[u8] = b"version";
506-
let version_key = self.node_subspace.subspace(&version_subspace);
408+
let version_key = self.get_root_node_subspace().subspace(&version_subspace);
507409
trx.get(version_key.bytes(), false).await
508410
}
509411
}

0 commit comments

Comments
 (0)