mirror of
https://git.deuxfleurs.fr/Deuxfleurs/garage.git
synced 2026-05-15 05:36:53 -04:00
Compare commits
9 commits
1686a/tran
...
main-v1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b6b18427a5 | ||
|
|
9987166b2b | ||
|
|
b72b090a09 | ||
|
|
8551aefed4 | ||
|
|
47bf5d9fb0 | ||
|
|
5df37dae5e | ||
|
|
44af0bdab3 | ||
|
|
a7d6620e18 | ||
|
|
8eb12755e4 |
22 changed files with 1024 additions and 824 deletions
1692
Cargo.lock
generated
1692
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
36
Cargo.toml
36
Cargo.toml
|
|
@ -24,18 +24,18 @@ default-members = ["src/garage"]
|
||||||
|
|
||||||
# Internal Garage crates
|
# Internal Garage crates
|
||||||
format_table = { version = "0.1.1", path = "src/format-table" }
|
format_table = { version = "0.1.1", path = "src/format-table" }
|
||||||
garage_api_common = { version = "1.3.0", path = "src/api/common" }
|
garage_api_common = { version = "1.3.1", path = "src/api/common" }
|
||||||
garage_api_admin = { version = "1.3.0", path = "src/api/admin" }
|
garage_api_admin = { version = "1.3.1", path = "src/api/admin" }
|
||||||
garage_api_s3 = { version = "1.3.0", path = "src/api/s3" }
|
garage_api_s3 = { version = "1.3.1", path = "src/api/s3" }
|
||||||
garage_api_k2v = { version = "1.3.0", path = "src/api/k2v" }
|
garage_api_k2v = { version = "1.3.1", path = "src/api/k2v" }
|
||||||
garage_block = { version = "1.3.0", path = "src/block" }
|
garage_block = { version = "1.3.1", path = "src/block" }
|
||||||
garage_db = { version = "1.3.0", path = "src/db", default-features = false }
|
garage_db = { version = "1.3.1", path = "src/db", default-features = false }
|
||||||
garage_model = { version = "1.3.0", path = "src/model", default-features = false }
|
garage_model = { version = "1.3.1", path = "src/model", default-features = false }
|
||||||
garage_net = { version = "1.3.0", path = "src/net" }
|
garage_net = { version = "1.3.1", path = "src/net" }
|
||||||
garage_rpc = { version = "1.3.0", path = "src/rpc" }
|
garage_rpc = { version = "1.3.1", path = "src/rpc" }
|
||||||
garage_table = { version = "1.3.0", path = "src/table" }
|
garage_table = { version = "1.3.1", path = "src/table" }
|
||||||
garage_util = { version = "1.3.0", path = "src/util" }
|
garage_util = { version = "1.3.1", path = "src/util" }
|
||||||
garage_web = { version = "1.3.0", path = "src/web" }
|
garage_web = { version = "1.3.1", path = "src/web" }
|
||||||
k2v-client = { version = "0.0.4", path = "src/k2v-client" }
|
k2v-client = { version = "0.0.4", path = "src/k2v-client" }
|
||||||
|
|
||||||
# External crates from crates.io
|
# External crates from crates.io
|
||||||
|
|
@ -146,12 +146,8 @@ aws-smithy-runtime = { version = "1.8", default-features = false, features = ["t
|
||||||
aws-sdk-config = { version = "1.62", default-features = false }
|
aws-sdk-config = { version = "1.62", default-features = false }
|
||||||
aws-sdk-s3 = { version = "1.79", default-features = false, features = ["rt-tokio"] }
|
aws-sdk-s3 = { version = "1.79", default-features = false, features = ["rt-tokio"] }
|
||||||
|
|
||||||
[profile.dev]
|
|
||||||
#lto = "thin" # disabled for now, adds 2-4 min to each CI build
|
|
||||||
lto = "off"
|
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
lto = true
|
lto = "thin"
|
||||||
codegen-units = 1
|
codegen-units = 16
|
||||||
opt-level = "s"
|
opt-level = 3
|
||||||
strip = true
|
strip = "debuginfo"
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@ apiVersion: v2
|
||||||
name: garage
|
name: garage
|
||||||
description: S3-compatible object store for small self-hosted geo-distributed deployments
|
description: S3-compatible object store for small self-hosted geo-distributed deployments
|
||||||
type: application
|
type: application
|
||||||
version: 0.7.2
|
version: 0.7.3
|
||||||
appVersion: "v1.3.0"
|
appVersion: "v1.3.1"
|
||||||
home: https://garagehq.deuxfleurs.fr/
|
home: https://garagehq.deuxfleurs.fr/
|
||||||
icon: https://garagehq.deuxfleurs.fr/images/garage-logo.svg
|
icon: https://garagehq.deuxfleurs.fr/images/garage-logo.svg
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# garage
|
# garage
|
||||||
|
|
||||||
  
|
  
|
||||||
|
|
||||||
S3-compatible object store for small self-hosted geo-distributed deployments
|
S3-compatible object store for small self-hosted geo-distributed deployments
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "garage_api_admin"
|
name = "garage_api_admin"
|
||||||
version = "1.3.0"
|
version = "1.3.1"
|
||||||
authors = ["Alex Auvolat <alex@adnab.me>"]
|
authors = ["Alex Auvolat <alex@adnab.me>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
license = "AGPL-3.0"
|
license = "AGPL-3.0"
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "garage_api_common"
|
name = "garage_api_common"
|
||||||
version = "1.3.0"
|
version = "1.3.1"
|
||||||
authors = ["Alex Auvolat <alex@adnab.me>"]
|
authors = ["Alex Auvolat <alex@adnab.me>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
license = "AGPL-3.0"
|
license = "AGPL-3.0"
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "garage_api_k2v"
|
name = "garage_api_k2v"
|
||||||
version = "1.3.0"
|
version = "1.3.1"
|
||||||
authors = ["Alex Auvolat <alex@adnab.me>"]
|
authors = ["Alex Auvolat <alex@adnab.me>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
license = "AGPL-3.0"
|
license = "AGPL-3.0"
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "garage_api_s3"
|
name = "garage_api_s3"
|
||||||
version = "1.3.0"
|
version = "1.3.1"
|
||||||
authors = ["Alex Auvolat <alex@adnab.me>"]
|
authors = ["Alex Auvolat <alex@adnab.me>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
license = "AGPL-3.0"
|
license = "AGPL-3.0"
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,9 @@ pub async fn handle_put_cors(
|
||||||
pub struct CorsConfiguration {
|
pub struct CorsConfiguration {
|
||||||
#[serde(serialize_with = "xmlns_tag", skip_deserializing)]
|
#[serde(serialize_with = "xmlns_tag", skip_deserializing)]
|
||||||
pub xmlns: (),
|
pub xmlns: (),
|
||||||
#[serde(rename = "CORSRule")]
|
// "default" is required to be able to parse an empty list of rules,
|
||||||
|
// cf https://docs.rs/quick-xml/latest/quick_xml/de/#sequences-xsall-and-xssequence-xml-schema-types
|
||||||
|
#[serde(rename = "CORSRule", default)]
|
||||||
pub cors_rules: Vec<CorsRule>,
|
pub cors_rules: Vec<CorsRule>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -270,4 +272,26 @@ mod tests {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_deserialize_norules() -> Result<(), Error> {
|
||||||
|
let message = r#"<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/" />"#;
|
||||||
|
let conf: CorsConfiguration = from_str(message).unwrap();
|
||||||
|
let ref_value = CorsConfiguration {
|
||||||
|
xmlns: (),
|
||||||
|
cors_rules: vec![],
|
||||||
|
};
|
||||||
|
assert_eq! {
|
||||||
|
ref_value,
|
||||||
|
conf
|
||||||
|
};
|
||||||
|
|
||||||
|
let message2 = to_xml_with_header(&ref_value)?;
|
||||||
|
|
||||||
|
let cleanup = |c: &str| c.replace(char::is_whitespace, "");
|
||||||
|
assert_eq!(cleanup(message), cleanup(&message2));
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -141,10 +141,26 @@ pub async fn handle_post_object(
|
||||||
|
|
||||||
let mut conditions = decoded_policy.into_conditions()?;
|
let mut conditions = decoded_policy.into_conditions()?;
|
||||||
|
|
||||||
|
// If there are conditions on the bucket name, check these against the actual bucket_name rather
|
||||||
|
// than the one in params, which is allowed to be absent.
|
||||||
|
if let Some(conds) = conditions.params.remove("bucket") {
|
||||||
|
for cond in conds {
|
||||||
|
let ok = match cond {
|
||||||
|
Operation::Equal(s) => s.as_str() == bucket_name,
|
||||||
|
Operation::StartsWith(s) => bucket_name.starts_with(&s),
|
||||||
|
};
|
||||||
|
if !ok {
|
||||||
|
return Err(Error::bad_request(
|
||||||
|
"Key 'bucket' has value not allowed in policy",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (param_key, value) in params.iter() {
|
for (param_key, value) in params.iter() {
|
||||||
let param_key = param_key.as_str();
|
let param_key = param_key.as_str();
|
||||||
match param_key {
|
match param_key {
|
||||||
"policy" | "x-amz-signature" => (), // this is always accepted, as it's required to validate other fields
|
"policy" | "x-amz-signature" | "bucket" => (), // this is always accepted, as it's required to validate other fields
|
||||||
"content-type" => {
|
"content-type" => {
|
||||||
let conds = conditions.params.remove("content-type").ok_or_else(|| {
|
let conds = conditions.params.remove("content-type").ok_or_else(|| {
|
||||||
Error::bad_request(format!("Key '{}' is not allowed in policy", param_key))
|
Error::bad_request(format!("Key '{}' is not allowed in policy", param_key))
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "garage_block"
|
name = "garage_block"
|
||||||
version = "1.3.0"
|
version = "1.3.1"
|
||||||
authors = ["Alex Auvolat <alex@adnab.me>"]
|
authors = ["Alex Auvolat <alex@adnab.me>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
license = "AGPL-3.0"
|
license = "AGPL-3.0"
|
||||||
|
|
|
||||||
|
|
@ -783,6 +783,7 @@ impl BlockManagerLocked {
|
||||||
|
|
||||||
let mut f = fs::File::create(&path_tmp).await?;
|
let mut f = fs::File::create(&path_tmp).await?;
|
||||||
f.write_all(data).await?;
|
f.write_all(data).await?;
|
||||||
|
f.flush().await?;
|
||||||
mgr.metrics.bytes_written.add(data.len() as u64);
|
mgr.metrics.bytes_written.add(data.len() as u64);
|
||||||
|
|
||||||
if mgr.data_fsync {
|
if mgr.data_fsync {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "garage_db"
|
name = "garage_db"
|
||||||
version = "1.3.0"
|
version = "1.3.1"
|
||||||
authors = ["Alex Auvolat <alex@adnab.me>"]
|
authors = ["Alex Auvolat <alex@adnab.me>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
license = "AGPL-3.0"
|
license = "AGPL-3.0"
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "garage"
|
name = "garage"
|
||||||
version = "1.3.0"
|
version = "1.3.1"
|
||||||
authors = ["Alex Auvolat <alex@adnab.me>"]
|
authors = ["Alex Auvolat <alex@adnab.me>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
license = "AGPL-3.0"
|
license = "AGPL-3.0"
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "garage_model"
|
name = "garage_model"
|
||||||
version = "1.3.0"
|
version = "1.3.1"
|
||||||
authors = ["Alex Auvolat <alex@adnab.me>"]
|
authors = ["Alex Auvolat <alex@adnab.me>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
license = "AGPL-3.0"
|
license = "AGPL-3.0"
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "garage_net"
|
name = "garage_net"
|
||||||
version = "1.3.0"
|
version = "1.3.1"
|
||||||
authors = ["Alex Auvolat <alex@adnab.me>"]
|
authors = ["Alex Auvolat <alex@adnab.me>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
license = "AGPL-3.0"
|
license = "AGPL-3.0"
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "garage_rpc"
|
name = "garage_rpc"
|
||||||
version = "1.3.0"
|
version = "1.3.1"
|
||||||
authors = ["Alex Auvolat <alex@adnab.me>"]
|
authors = ["Alex Auvolat <alex@adnab.me>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
license = "AGPL-3.0"
|
license = "AGPL-3.0"
|
||||||
|
|
|
||||||
|
|
@ -507,7 +507,7 @@ impl LayoutVersion {
|
||||||
g.compute_maximal_flow()?;
|
g.compute_maximal_flow()?;
|
||||||
if g.get_flow_value()? < (NB_PARTITIONS * self.replication_factor) as i64 {
|
if g.get_flow_value()? < (NB_PARTITIONS * self.replication_factor) as i64 {
|
||||||
return Err(Error::Message(
|
return Err(Error::Message(
|
||||||
"The storage capacity of he cluster is to small. It is \
|
"The storage capacity of the cluster is too small. It is \
|
||||||
impossible to store partitions of size 1."
|
impossible to store partitions of size 1."
|
||||||
.into(),
|
.into(),
|
||||||
));
|
));
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "garage_table"
|
name = "garage_table"
|
||||||
version = "1.3.0"
|
version = "1.3.1"
|
||||||
authors = ["Alex Auvolat <alex@adnab.me>"]
|
authors = ["Alex Auvolat <alex@adnab.me>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
license = "AGPL-3.0"
|
license = "AGPL-3.0"
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "garage_util"
|
name = "garage_util"
|
||||||
version = "1.3.0"
|
version = "1.3.1"
|
||||||
authors = ["Alex Auvolat <alex@adnab.me>"]
|
authors = ["Alex Auvolat <alex@adnab.me>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
license = "AGPL-3.0"
|
license = "AGPL-3.0"
|
||||||
|
|
|
||||||
|
|
@ -115,6 +115,7 @@ impl WorkerProcessor {
|
||||||
trace!("{} (TID {}): {:?}", worker.worker.name(), worker.task_id, worker.state);
|
trace!("{} (TID {}): {:?}", worker.worker.name(), worker.task_id, worker.state);
|
||||||
|
|
||||||
// Save worker info
|
// Save worker info
|
||||||
|
{
|
||||||
let mut wi = self.worker_info.lock().unwrap();
|
let mut wi = self.worker_info.lock().unwrap();
|
||||||
match wi.get_mut(&worker.task_id) {
|
match wi.get_mut(&worker.task_id) {
|
||||||
Some(i) => {
|
Some(i) => {
|
||||||
|
|
@ -137,10 +138,16 @@ impl WorkerProcessor {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if worker.state == WorkerState::Done {
|
if worker.state == WorkerState::Done {
|
||||||
info!("Worker {} (TID {}) exited", worker.worker.name(), worker.task_id);
|
info!("Worker {} (TID {}) exited", worker.worker.name(), worker.task_id);
|
||||||
} else {
|
} else {
|
||||||
|
// Yield to the Tokio scheduler between consecutive Busy steps so
|
||||||
|
// that a worker which never suspends on its own cannot starve other tasks.
|
||||||
|
if worker.state == WorkerState::Busy {
|
||||||
|
tokio::task::yield_now().await;
|
||||||
|
}
|
||||||
workers.push(async move {
|
workers.push(async move {
|
||||||
worker.step().await;
|
worker.step().await;
|
||||||
worker
|
worker
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "garage_web"
|
name = "garage_web"
|
||||||
version = "1.3.0"
|
version = "1.3.1"
|
||||||
authors = ["Alex Auvolat <alex@adnab.me>", "Quentin Dufour <quentin@dufour.io>"]
|
authors = ["Alex Auvolat <alex@adnab.me>", "Quentin Dufour <quentin@dufour.io>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
license = "AGPL-3.0"
|
license = "AGPL-3.0"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue