Skip to content

Commit 97e9d18

Browse files
garrensmithPierreZ
authored andcommitted
initial basic work
1 parent 250b8fd commit 97e9d18

File tree

4 files changed

+322
-4
lines changed

4 files changed

+322
-4
lines changed
Lines changed: 200 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,209 @@
11
use crate::Transaction;
2+
use crate::tuple::{Subspace, pack_into, pack};
3+
use crate::tuple::hca::HighContentionAllocator;
24

3-
pub struct Directory;
5+
use super::*;
6+
use std::result;
7+
use crate::DirectoryError::Version;
8+
use crate::directory::directory_subspace::{DirectorySubspaceResult, DirectorySubspace};
49

5-
// use crate::transactions::{Transaction};
10+
const LAYER_VERSION: (u8, u8, u8) = (1, 0, 0);
11+
const MAJOR_VERSION: u32 = 1;
12+
const MINOR_VERSION: u32 = 0;
13+
const PATCH_VERSION: u32 = 0;
14+
const DEFAULT_NODE_PREFIX:&[u8] = b"\xFE";
15+
16+
const SUBDIRS:u8 = 0;
17+
18+
#[derive(PartialEq)]
19+
enum PermissionLevel {
20+
Read,
21+
Write
22+
}
23+
24+
pub type DirectoryResult = result::Result<Directory, DirectoryError>;
25+
26+
pub struct Directory {
27+
node_prefix: Subspace,
28+
content_prefix: Subspace,
29+
30+
allow_manual_prefixes: bool,
31+
32+
allocator: HighContentionAllocator,
33+
root_node: Subspace,
34+
35+
path: Vec<String>,
36+
layer: Vec<u8>,
37+
}
638

739
impl Directory {
840

9-
pub fn create_or_open(trx: Transaction, path: Option<&str>, layer: Option<&[u8]> ) -> bool {
10-
false
41+
pub fn root() -> Directory {
42+
Directory {
43+
node_prefix: DEFAULT_NODE_PREFIX.into(),
44+
content_prefix: Subspace::from_bytes(b""),
45+
46+
allow_manual_prefixes: false,
47+
48+
allocator: HighContentionAllocator::new(Subspace::from_bytes(b"hca")),
49+
root_node: DEFAULT_NODE_PREFIX.into(),
50+
51+
path: Vec::new(),
52+
layer: Vec::new()
53+
}
54+
}
55+
56+
pub fn contents_of_node(&self, node: Subspace, path: &[String], layer: &[u8]) -> DirectorySubspaceResult {
57+
58+
59+
Ok(DirectorySubspace)
60+
}
61+
62+
// pub fn new(parent_node: Directory, path: &[String], layer: &[u8]) -> Directory {
63+
// Directory {
64+
//
65+
// allow_manual_prefixes: true,
66+
//
67+
// allocator: HighContentionAllocator::new(Subspace::from_bytes(b"hca")),
68+
//
69+
// root_node: parent_node.node_prefix.clone(),
70+
// path: path.to_vec(),
71+
// layer: layer.to_vec(),
72+
//
73+
// }
74+
//
75+
// }
76+
77+
pub async fn create_or_open(&self, trx: Transaction, path: &[&str], layer: &[u8], prefix: &[u8], allow_create: bool, allow_open: bool) -> DirectoryResult {
78+
self.check_version(&trx, PermissionLevel::Read).await?;
79+
80+
if prefix.len() > 0 && !self.allow_manual_prefixes {
81+
if self.path.len() == 0 {
82+
return Err(DirectoryError::Message("cannot specify a prefix unless manual prefixes are enabled".to_string()))
83+
}
84+
85+
return Err(DirectoryError::Message("cannot specify a prefix in a partition".to_string()))
86+
}
87+
88+
if path.len() == 0 {
89+
return Err(DirectoryError::CannotOpenRoot)
90+
}
91+
92+
// FIND
93+
94+
if !allow_create {
95+
return Err(DirectoryError::NotExist)
96+
}
97+
98+
// self.initialize_directory(&trx);
99+
100+
if prefix.len() == 0 {
101+
// let new_subspace = self.allocator.allocate(&trx).await?;
102+
// TODO: maybe check range and prefix free but I think the allocate does that already
103+
} else {
104+
let is_prefix_free = self.is_prefix_free(&trx, prefix).await?;
105+
}
106+
//
107+
// if layer != self.get_layer() && layer != &[] {
108+
// return Err(DirectoryError::LayerMismatch);
109+
// }
110+
111+
Ok(Directory::root())
112+
}
113+
114+
// pub async fn find(&self, trx: Transaction, path: &[&str]) -> DirectoryResult {
115+
//
116+
// }
117+
118+
// pub async fn initialize_directory(&self, trx: &Transaction) {
119+
// let version = [MAJOR_VERSION, MINOR_VERSION, PATCH_VERSION].to_le_bytes();
120+
// let version_subspace: &[u8] = b"version";
121+
// let version_key = self.root_node.subspace(&version_subspace);
122+
//
123+
// trx.set(version_key.bytes(), version).await;
124+
// }
125+
126+
async fn is_prefix_free(&self, trx: &Transaction, prefix: &[u8]) -> Result<bool, DirectoryError> {
127+
128+
if prefix.len() == 0 {
129+
return Ok(false);
130+
}
131+
132+
Ok(true)
133+
}
134+
135+
136+
async fn check_version(&self, trx: &Transaction, perm_level: PermissionLevel ) -> Result<(), DirectoryError> {
137+
let version_subspace: &[u8] = b"version";
138+
let version_key = self.root_node.subspace(&version_subspace);
139+
let version_opt = trx.get(version_key.bytes(), false).await?;
140+
141+
match version_opt {
142+
None => {
143+
if perm_level == PermissionLevel::Write {
144+
//init
145+
return Err(Version("fix soon".to_string()));
146+
}
147+
148+
Ok(())
149+
}
150+
Some(versions) => {
151+
if versions.len() < 12 {
152+
return Err(Version("incorrect version length".to_string()));
153+
}
154+
let mut arr = [0u8; 4];
155+
arr.copy_from_slice(&versions[0..4]);
156+
let major: u32 = u32::from_be_bytes(arr);
157+
158+
arr.copy_from_slice(&versions[4..8]);
159+
let minor: u32 = u32::from_be_bytes(arr);
160+
161+
arr.copy_from_slice(&versions[8..12]);
162+
let patch: u32 = u32::from_be_bytes(arr);
163+
164+
if major > MAJOR_VERSION {
165+
let msg = format!("cannot load directory with version {}.{}.{} using directory layer {}.{}.{}", major, minor, patch, MAJOR_VERSION, MINOR_VERSION, PATCH_VERSION);
166+
return Err(Version(msg))
167+
}
168+
169+
if minor > MINOR_VERSION && perm_level == PermissionLevel::Write {
170+
let msg = format!("directory with version {}.{}.{} is read-only when opened using directory layer {}.{}.{}", major, minor, patch, MAJOR_VERSION, MINOR_VERSION, PATCH_VERSION);
171+
return Err(Version(msg))
172+
}
173+
174+
Ok(())
175+
}
176+
}
11177
}
12178

179+
// pub async fn find(&self, trx: &Transaction, path: &[&str]) -> DirectoryResult {
180+
// let mut node = Directory::root();
181+
//
182+
// for path_name in path {
183+
// let mut node_layer_id = vec!(SUBDIRS);
184+
// pack_into(&path_name, &mut node_layer_id);
185+
// let new_node = node.node_prefix.subspace(&node_layer_id);
186+
//
187+
// match trx.get(new_node.bytes(), false).await {
188+
// Err(_) => {
189+
// return Ok(node);
190+
// }
191+
// Result(node_name) => {
192+
// let ss = node.node_with_prefix(key);
193+
// node.node_prefix = ss;
194+
// node.path.push(path_name.to_string())
195+
// }
196+
// }
197+
// }
198+
//
199+
//
200+
// Ok(node)
201+
// }
202+
203+
204+
205+
pub fn get_layer(&self) -> &[u8] {
206+
self.layer.as_slice()
207+
}
13208
}
209+
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
use crate::tuple::Subspace;
2+
use crate::{Directory, DirectoryError};
3+
use std::result;
4+
5+
pub type DirectorySubspaceResult = result::Result<DirectorySubspace, DirectoryError>;
6+
7+
pub struct DirectorySubspace {
8+
subspace: Subspace,
9+
dl: Directory,
10+
path: Vec<String>,
11+
layer: Vec<u8>
12+
}
13+
14+
// TODO: impl { .. }

foundationdb/src/directory/mod.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,48 @@
11
pub mod directory;
2+
pub mod node;
3+
pub mod directory_subspace;
24

35
pub use directory::*;
6+
use std::io;
7+
use std::fmt::{self, Display};
8+
use crate::error;
9+
10+
11+
#[derive(Debug)]
12+
pub enum DirectoryError {
13+
CannotOpenRoot,
14+
LayerMismatch,
15+
NotExist,
16+
Message(String),
17+
Version(String),
18+
IoError(io::Error),
19+
FdbError(error::FdbError)
20+
}
21+
22+
impl From<io::Error> for DirectoryError {
23+
fn from(err: io::Error) -> Self {
24+
DirectoryError::IoError(err)
25+
}
26+
}
27+
28+
impl From<error::FdbError> for DirectoryError {
29+
fn from(err: error::FdbError) -> Self {
30+
DirectoryError::FdbError(err)
31+
}
32+
}
33+
34+
impl Display for DirectoryError {
35+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
36+
match self {
37+
DirectoryError::CannotOpenRoot => write!(f, "Cannot open root directory"),
38+
DirectoryError::LayerMismatch => write!(f, "Layer mismatch"),
39+
DirectoryError::NotExist => write!(f, "Directory does not exist"),
40+
DirectoryError::Version(s) => s.fmt(f),
41+
DirectoryError::Message(s) => s.fmt(f),
42+
DirectoryError::IoError(err) => err.fmt(f),
43+
DirectoryError::FdbError(err) => err.fmt(f),
44+
}
45+
}
46+
}
447

548

foundationdb/src/directory/node.rs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
use crate::tuple::{Subspace};
2+
use crate::future::FdbSlice;
3+
use crate::{Transaction, Directory, DirectoryResult};
4+
use crate::directory::directory_subspace::DirectorySubspaceResult;
5+
6+
7+
pub struct Node {
8+
subspace: Subspace,
9+
path: Vec<String>,
10+
target_path: Vec<String>,
11+
_layer: Option<Vec<u8>>
12+
}
13+
14+
impl Node {
15+
16+
pub fn exists(&self) -> bool {
17+
// if self.subspace == None {
18+
// return false;
19+
// }
20+
21+
true
22+
}
23+
24+
pub async fn prefetchMetadata(&self, trx: &Transaction) -> &Node {
25+
if self.exists() {
26+
self.layer(trx).await;
27+
}
28+
29+
return self;
30+
}
31+
32+
pub async fn layer(&mut self, trx: &Transaction) -> &[u8] {
33+
if self._layer == None {
34+
let key = self.subspace.subspace(&b"layer".to_vec());
35+
self._layer = match trx.get(key.bytes(), false).await {
36+
Ok(None) => Some(Vec::new()),
37+
Err(_) => Some(Vec::new()),
38+
Ok(Some(fv)) => Some(fv.to_vec())
39+
}
40+
}
41+
42+
return self._layer.unwrap().as_slice()
43+
}
44+
45+
pub async fn is_in_partition(&mut self, trx: Transaction, include_empty_subpath: bool) -> bool {
46+
if !self.exists() {
47+
return false
48+
}
49+
50+
self.layer(&trx).await == b"partition" &&
51+
(include_empty_subpath || self.target_path.len() > self.path.len())
52+
}
53+
54+
pub fn get_partition_subpath(&self) -> &[String] {
55+
self.target_path[..self.path.len()].clone()
56+
}
57+
58+
pub async fn get_contents(self, directory: Directory, trx: &Transaction ) -> DirectorySubspaceResult {
59+
directory.contents_of_node(self.subspace, &self.path, &self.layer(trx).await)
60+
}
61+
}
62+
63+
64+
65+

0 commit comments

Comments
 (0)