diff --git a/Cargo.lock b/Cargo.lock index c52b23e9..aa95ca26 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -323,6 +323,7 @@ dependencies = [ "thiserror", "tokio", "tracing", + "tracing-error", "transform-stream", "url", "uuid", @@ -1018,11 +1019,15 @@ checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" name = "rustfs" version = "0.1.0" dependencies = [ + "async-trait", "clap", "ecstore", "hyper-util", "s3s", + "time", "tokio", + "tokio-util", + "tracing", "tracing-subscriber", ] @@ -1362,6 +1367,16 @@ dependencies = [ "valuable", ] +[[package]] +name = "tracing-error" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d686ec1c0f384b1277f097b2f279a2ecc11afe8c133c1aabf036a27cb4cd206e" +dependencies = [ + "tracing", + "tracing-subscriber", +] + [[package]] name = "tracing-log" version = "0.2.0" diff --git a/ecstore/Cargo.toml b/ecstore/Cargo.toml index d849326b..1a5153a9 100644 --- a/ecstore/Cargo.toml +++ b/ecstore/Cargo.toml @@ -25,3 +25,4 @@ netif = "0.1.6" async-trait = "0.1.80" s3s = "0.10.0" tracing.workspace = true +tracing-error = "0.2.0" diff --git a/ecstore/src/error.rs b/ecstore/src/error.rs index 9a38f7e5..698a164c 100644 --- a/ecstore/src/error.rs +++ b/ecstore/src/error.rs @@ -1 +1,74 @@ +// use s3s::S3Error; +// use s3s::S3ErrorCode; + +use std::panic::Location; + +use tracing::error; + pub type StdError = Box; + +#[derive(Debug)] +pub struct Error { + source: StdError, +} + +pub type Result = std::result::Result; + +impl Error { + #[must_use] + #[track_caller] + pub fn new(source: StdError) -> Self { + log(&*source); + Self { source } + } + + #[must_use] + #[track_caller] + pub fn from_string(s: impl Into) -> Self { + Self::new(s.into().into()) + } +} + +impl From for Error +where + E: std::error::Error + Send + Sync + 'static, +{ + #[track_caller] + fn from(source: E) -> Self { + Self::new(Box::new(source)) + } +} + +// impl From for S3Error { +// fn from(e: Error) -> Self { +// S3Error::with_source(S3ErrorCode::InternalError, e.source) +// } +// } + +#[inline] +#[track_caller] +pub(crate) fn log(source: &dyn std::error::Error) { + if cfg!(feature = "binary") { + let location = Location::caller(); + let span_trace = tracing_error::SpanTrace::capture(); + + error!( + target: "s3s_fs_internal_error", + %location, + error=%source, + "span trace:\n{span_trace}" + ); + } +} + +macro_rules! try_ { + ($result:expr) => { + match $result { + Ok(val) => val, + Err(err) => { + $crate::error::log(&err); + return Err(::s3s::S3Error::internal_error(err)); + } + } + }; +} diff --git a/ecstore/src/lib.rs b/ecstore/src/lib.rs index 4bcbcb3c..2321c314 100644 --- a/ecstore/src/lib.rs +++ b/ecstore/src/lib.rs @@ -2,7 +2,7 @@ mod disks_layout; mod ellipses; mod endpoint; mod erasure; -mod error; +pub mod error; pub mod s3; pub mod store; mod stream; diff --git a/ecstore/src/store.rs b/ecstore/src/store.rs index f73cd245..9bc3ee2b 100644 --- a/ecstore/src/store.rs +++ b/ecstore/src/store.rs @@ -1,19 +1,25 @@ +use uuid::Uuid; + use super::endpoint::Endpoint; -use crate::endpoint::EndpointServerPools; +use super::error::Result; use std::fmt::Debug; #[derive(Debug)] pub struct ECStore { pub id: uuid::Uuid, - pub disks: Vec>, + // pub disks: Vec>, pub pools: Vec, pub peer: Vec, } impl ECStore { - pub fn new(endpoints: EndpointServerPools) { - unimplemented!() + pub fn new(endpoints: Vec) -> Result { + Ok(ECStore { + id: Uuid::nil(), + pools: Vec::new(), + peer: Vec::new(), + }) } } diff --git a/rustfs/Cargo.toml b/rustfs/Cargo.toml index 662d180d..cee3b6c4 100644 --- a/rustfs/Cargo.toml +++ b/rustfs/Cargo.toml @@ -11,21 +11,20 @@ rust-version.workspace = true [[bin]] name = "rustfs" -required-features = ["binary"] +# required-features = ["binary"] -[features] -binary = ["tokio/full", "dep:clap", "dep:tracing-subscriber", "dep:hyper-util"] +# [features] +# binary = ["tokio/full", "dep:clap", "dep:tracing-subscriber", "dep:hyper-util"] [dependencies] ecstore = { path = "../ecstore" } -# time = { workspace = true, features = ["parsing", "formatting"] } -# s3s = "0.10.0" -hyper-util = { version = "0.1.5", optional = true, features = ["server-auto", "server-graceful", "http1", "http2", "tokio"] } -tokio.workspace = true -clap = { version = "4.5.7", optional = true, features = ["derive"] } -# tracing.workspace = true -# tokio-util.workspace = true -tracing-subscriber = { version = "0.3.18", optional = true, features = ["env-filter", "time"] } +time = { workspace = true, features = ["parsing", "formatting"] } s3s = "0.10.0" -# async-trait = "0.1.80" +hyper-util = { version = "0.1.5", features = ["server-auto", "server-graceful", "http1", "http2", "tokio"] } +tokio.workspace = true +clap = { version = "4.5.7", features = ["derive"] } +tracing.workspace = true +tokio-util.workspace = true +tracing-subscriber = { version = "0.3.18", features = ["env-filter", "time"] } +async-trait = "0.1.80" diff --git a/rustfs/src/main.rs b/rustfs/src/main.rs index 108da2e2..e49b09d6 100644 --- a/rustfs/src/main.rs +++ b/rustfs/src/main.rs @@ -1,8 +1,5 @@ -#![forbid(unsafe_code)] -#![deny(clippy::all, clippy::pedantic)] - -use s3s_fs::FileSystem; -use s3s_fs::Result; +use ecstore::error::Result; +use ecstore::store::ECStore; use s3s::auth::SimpleAuth; use s3s::service::S3ServiceBuilder; @@ -26,23 +23,30 @@ struct Opt { host: String, /// Port number to listen on. - #[arg(long, default_value = "8014")] // The original design was finished on 2020-08-14. + #[arg(long, default_value = "9010")] port: u16, /// Access key used for authentication. - #[arg(long)] + #[arg(long, default_value = "AKEXAMPLERUSTFS")] access_key: Option, /// Secret key used for authentication. - #[arg(long)] + #[arg(long, default_value = "SKEXAMPLERUSTFS")] secret_key: Option, /// Domain name used for virtual-hosted-style requests. #[arg(long)] domain_name: Option, - /// Root directory of stored data. - root: PathBuf, + #[arg( + required = true, + help = r#"DIR points to a directory on a filesystem. When you want to combine +multiple drives into a single large system, pass one directory per +filesystem separated by space. You may also use a '...' convention +to abbreviate the directory arguments. Remote directories in a +distributed setup are encoded as HTTP(s) URIs."# + )] + volumes: Vec, } fn setup_tracing() { @@ -89,11 +93,11 @@ fn main() -> Result { #[tokio::main] async fn run(opt: Opt) -> Result { // Setup S3 provider - let fs = FileSystem::new(opt.root)?; + let sto = ECStore::new(opt.volumes)?; // Setup S3 service let service = { - let mut b = S3ServiceBuilder::new(fs); + let mut b = S3ServiceBuilder::new(sto); // Enable authentication if let (Some(ak), Some(sk)) = (opt.access_key, opt.secret_key) { diff --git a/scripts/run.sh b/scripts/run.sh new file mode 100755 index 00000000..37864993 --- /dev/null +++ b/scripts/run.sh @@ -0,0 +1,18 @@ +#!/bin/bash +DATA_DIR="/tmp" + +if [ -n "$1" ]; then + DATA_DIR="$1" +fi + +if [ -z "$RUST_LOG" ]; then + export RUST_LOG="rustfs=debug" +fi + +cargo run \ + -- --access-key AKEXAMPLERUSTFS \ + -- --secret-key SKEXAMPLERUSTFS \ + -- --host localhost \ + -- --port 9010 \ + -- --domain-name localhost:9010 \ + "$DATA_DIR"