1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
//
// Wildland Project
//
// Copyright © 2022 Golem Foundation
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 3 as published by
// the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
pub mod error;
pub mod events;
pub mod fs_stat;
pub mod node_stat;
pub mod stream;
pub mod wl_permissions;
use std::fmt::Display;
use std::sync::{Arc, Mutex};
pub use error::DfsFrontendError;
pub use events::EventReceiver;
pub use fs_stat::FsStat;
pub use node_stat::NodeStat;
pub use stream::*;
pub use wl_permissions::WlPermissions;
use super::unix_timestamp::UnixTimestamp;
use crate::Storage;
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct DirEntry {
/// file or dir name
pub item_name: String,
pub stat: NodeStat,
}
impl DirEntry {
pub fn item_name(&self) -> String {
self.item_name.clone()
}
pub fn stat(&self) -> NodeStat {
self.stat.clone()
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SpaceUsage {
used_space: u64,
total_space: u64,
}
impl SpaceUsage {
pub fn new(used_space: u64, total_space: u64) -> Self {
Self {
used_space,
total_space,
}
}
pub fn get_used_space(&self) -> u64 {
self.used_space
}
pub fn get_total_space(&self) -> u64 {
self.total_space
}
}
impl Display for SpaceUsage {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}/{} bytes",
self.get_used_space(),
self.get_total_space()
)
}
}
/// Interface that DFS exposes towards filesystem-like frontend providers
///
/// DFS methods may return error that are not related with particular operation but rather
/// with wildland system in general. Those errors could be:
///
/// - `PathResolutionError` - happens when path resolving failed, e.g. due to the catlib error.
/// - `StorageNotResponsive` - happens when none of storages that operation involves returns an answer.
/// - `Generic` - unanticipated errors.
#[mockall::automock]
pub trait DfsFrontend: Send + Sync {
/// Returns vector of entries found under the provided path.
/// It may merge entries from multiple containers.
///
/// # Errors:
/// - `NotADirectory` - for paths that don't represent directories
/// - `NoSuchPath` - requested path does not exist
///
fn read_dir(&self, path: String) -> Result<Vec<DirEntry>, DfsFrontendError>;
/// Returns metadata of a node.
///
/// # Errors:
///
/// - `NoSuchPath` - requested path does not exist
fn metadata(&self, path: String) -> Result<NodeStat, DfsFrontendError>;
/// Removes a file
///
/// # Errors:
/// - `NoSuchPath` - requested path does not exist
/// - `NotAFile` - provided path represents a node that is not a file
fn remove_file(&self, path: String) -> Result<(), DfsFrontendError>;
/// Rename a file or directory to a new path, if new path does not exist yet.
/// In contrast to POSIX-like rename operation, it returns error in case of new path existence
/// in all cases, so it is up to a caller whether to remove a node under new path or not.
///
/// # Errors:
/// `NoSuchPath` - source not found
/// `SourceIsParentOfTarget` - new directory would be a subdirectory of itself
/// `MoveBetweenContainers` - `new_path` is in different Container than `old_path`
/// `PathAlreadyExists` - `new_path` already exists
fn rename(&self, old_path: String, new_path: String) -> Result<(), DfsFrontendError>;
/// Changes the permissions of the underlying file.
fn set_permissions(
&self,
path: String,
permissions: WlPermissions,
) -> Result<(), DfsFrontendError>;
/// Not supported yet - it always returns `DfsFrontendError::Generic(_)`
fn set_owner(&self, path: String) -> Result<(), DfsFrontendError>;
/// Creates a new, empty directory at the provided path
///
/// # Errors:
/// `InvalidParent` - a parent of the given path doesn’t exist.
/// `PathAlreadyExists` - path already exists.
fn create_dir(&self, path: String) -> Result<(), DfsFrontendError>;
/// Removes a directory
/// If `is_recursive` is set to true, it will remove all the children of the directory
///
/// # Errors:
/// `NotADirectory` - path does not represent a directory
/// `NoSuchPath` - no such path exists
/// `DirNotEmpty` - directory is not empty
fn remove_dir(&self, path: String, is_recursive: bool) -> Result<(), DfsFrontendError>;
/// Returns information about a mounted filesystem. Path is the pathname of any file within the
/// mounted filesystem.
///
/// # Errors:
/// `NoSuchPath` - no such path exists
fn stat_fs(&self, path: String) -> Result<FsStat, DfsFrontendError>;
// Methods that are not part of the Posix-like FS API
/// Returns receiver that can listen to DFS events.
/// Events may be split between different `EventReceiver`.
fn get_receiver(&self) -> Arc<Mutex<dyn EventReceiver>>;
/// Attempts to mount given Storage. This method's state
/// should not be considered emphemeral.
///
/// This functionality may be used during container mount to ensure
/// storage being healthy, before any FS operations are performed.
fn mount(&self, storage: &Storage) -> Result<(), DfsFrontendError>;
/// Returns (used, total) space in bytes
///
fn get_space_usage(&self, storage: &Storage) -> Result<SpaceUsage, DfsFrontendError>;
/// Checks whether the Storage is accessible
///
fn is_accessible(&self, storage: &Storage) -> Result<bool, DfsFrontendError>;
//
// Non-POSIX-like access to files
//
/// Downloads a file and writes it to the provided output stream
///
fn download(
&self,
path: String,
output: Box<dyn OStream>,
progress_reporter: Box<dyn ProgressReporter>,
abort_flag: &AbortFlag,
) -> Result<(), DfsFrontendError>;
/// Reads a file from the provided input stream and uploads it to the backend
///
fn upload(
&self,
path: String,
input: Box<dyn IStream>,
progress_reporter: Box<dyn ProgressReporter>,
abort_flag: &AbortFlag,
creation_time: Option<UnixTimestamp>,
) -> Result<(), DfsFrontendError>;
/// Finds path of object which matches the uuid
///
fn get_path(&self, identifier: String) -> Result<String, DfsFrontendError>;
}