Compare commits
7 commits
Author | SHA1 | Date | |
---|---|---|---|
ad9180ae29 | |||
eb0b3bd473 | |||
23cf71a483 | |||
e5e23364be | |||
a70ef456e4 | |||
12fd12fd6a | |||
a0de940b8a |
16 changed files with 564 additions and 342 deletions
25
Cargo.lock
generated
25
Cargo.lock
generated
|
@ -879,6 +879,7 @@ dependencies = [
|
||||||
"form_urlencoded",
|
"form_urlencoded",
|
||||||
"futures",
|
"futures",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
|
"garage_block",
|
||||||
"garage_model 0.7.0",
|
"garage_model 0.7.0",
|
||||||
"garage_table 0.7.0",
|
"garage_table 0.7.0",
|
||||||
"garage_util 0.7.0",
|
"garage_util 0.7.0",
|
||||||
|
@ -906,6 +907,29 @@ dependencies = [
|
||||||
"url",
|
"url",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "garage_block"
|
||||||
|
version = "0.7.0"
|
||||||
|
dependencies = [
|
||||||
|
"async-trait",
|
||||||
|
"bytes 1.1.0",
|
||||||
|
"futures",
|
||||||
|
"futures-util",
|
||||||
|
"garage_rpc 0.7.0",
|
||||||
|
"garage_table 0.7.0",
|
||||||
|
"garage_util 0.7.0",
|
||||||
|
"hex",
|
||||||
|
"opentelemetry",
|
||||||
|
"rand 0.8.5",
|
||||||
|
"rmp-serde 0.15.5",
|
||||||
|
"serde",
|
||||||
|
"serde_bytes",
|
||||||
|
"sled",
|
||||||
|
"tokio",
|
||||||
|
"tracing",
|
||||||
|
"zstd",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "garage_model"
|
name = "garage_model"
|
||||||
version = "0.5.1"
|
version = "0.5.1"
|
||||||
|
@ -940,6 +964,7 @@ dependencies = [
|
||||||
"err-derive 0.3.1",
|
"err-derive 0.3.1",
|
||||||
"futures",
|
"futures",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
|
"garage_block",
|
||||||
"garage_model 0.5.1",
|
"garage_model 0.5.1",
|
||||||
"garage_rpc 0.7.0",
|
"garage_rpc 0.7.0",
|
||||||
"garage_table 0.7.0",
|
"garage_table 0.7.0",
|
||||||
|
|
174
Cargo.nix
174
Cargo.nix
|
@ -9,6 +9,7 @@ args@{
|
||||||
"garage_admin/default"
|
"garage_admin/default"
|
||||||
"garage_table/default"
|
"garage_table/default"
|
||||||
"garage_model/default"
|
"garage_model/default"
|
||||||
|
"garage_block/default"
|
||||||
"garage_api/default"
|
"garage_api/default"
|
||||||
"garage_web/default"
|
"garage_web/default"
|
||||||
"garage/default"
|
"garage/default"
|
||||||
|
@ -49,6 +50,7 @@ in
|
||||||
garage_admin = rustPackages.unknown.garage_admin."0.7.0";
|
garage_admin = rustPackages.unknown.garage_admin."0.7.0";
|
||||||
garage_table = rustPackages.unknown.garage_table."0.7.0";
|
garage_table = rustPackages.unknown.garage_table."0.7.0";
|
||||||
garage_model = rustPackages.unknown.garage_model."0.7.0";
|
garage_model = rustPackages.unknown.garage_model."0.7.0";
|
||||||
|
garage_block = rustPackages.unknown.garage_block."0.7.0";
|
||||||
garage_api = rustPackages.unknown.garage_api."0.7.0";
|
garage_api = rustPackages.unknown.garage_api."0.7.0";
|
||||||
garage_web = rustPackages.unknown.garage_web."0.7.0";
|
garage_web = rustPackages.unknown.garage_web."0.7.0";
|
||||||
garage = rustPackages.unknown.garage."0.7.0";
|
garage = rustPackages.unknown.garage."0.7.0";
|
||||||
|
@ -612,7 +614,7 @@ in
|
||||||
registry = "registry+https://github.com/rust-lang/crates.io-index";
|
registry = "registry+https://github.com/rust-lang/crates.io-index";
|
||||||
src = fetchCratesIo { inherit name version; sha256 = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469"; };
|
src = fetchCratesIo { inherit name version; sha256 = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469"; };
|
||||||
dependencies = {
|
dependencies = {
|
||||||
${ if hostPlatform.config == "aarch64-apple-darwin" || hostPlatform.parsed.cpu.name == "aarch64" && hostPlatform.parsed.kernel.name == "linux" then "libc" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".libc."0.2.119" { inherit profileName; };
|
${ if hostPlatform.parsed.cpu.name == "aarch64" && hostPlatform.parsed.kernel.name == "linux" || hostPlatform.config == "aarch64-apple-darwin" then "libc" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".libc."0.2.119" { inherit profileName; };
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1128,7 +1130,7 @@ in
|
||||||
[ "async-await" ]
|
[ "async-await" ]
|
||||||
[ "async-await-macro" ]
|
[ "async-await-macro" ]
|
||||||
[ "channel" ]
|
[ "channel" ]
|
||||||
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "default")
|
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "default")
|
||||||
[ "futures-channel" ]
|
[ "futures-channel" ]
|
||||||
[ "futures-io" ]
|
[ "futures-io" ]
|
||||||
[ "futures-macro" ]
|
[ "futures-macro" ]
|
||||||
|
@ -1237,6 +1239,7 @@ in
|
||||||
form_urlencoded = rustPackages."registry+https://github.com/rust-lang/crates.io-index".form_urlencoded."1.0.1" { inherit profileName; };
|
form_urlencoded = rustPackages."registry+https://github.com/rust-lang/crates.io-index".form_urlencoded."1.0.1" { inherit profileName; };
|
||||||
futures = rustPackages."registry+https://github.com/rust-lang/crates.io-index".futures."0.3.21" { inherit profileName; };
|
futures = rustPackages."registry+https://github.com/rust-lang/crates.io-index".futures."0.3.21" { inherit profileName; };
|
||||||
futures_util = rustPackages."registry+https://github.com/rust-lang/crates.io-index".futures-util."0.3.21" { inherit profileName; };
|
futures_util = rustPackages."registry+https://github.com/rust-lang/crates.io-index".futures-util."0.3.21" { inherit profileName; };
|
||||||
|
garage_block = rustPackages."unknown".garage_block."0.7.0" { inherit profileName; };
|
||||||
garage_model = rustPackages."unknown".garage_model."0.7.0" { inherit profileName; };
|
garage_model = rustPackages."unknown".garage_model."0.7.0" { inherit profileName; };
|
||||||
garage_table = rustPackages."unknown".garage_table."0.7.0" { inherit profileName; };
|
garage_table = rustPackages."unknown".garage_table."0.7.0" { inherit profileName; };
|
||||||
garage_util = rustPackages."unknown".garage_util."0.7.0" { inherit profileName; };
|
garage_util = rustPackages."unknown".garage_util."0.7.0" { inherit profileName; };
|
||||||
|
@ -1265,6 +1268,32 @@ in
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
"unknown".garage_block."0.7.0" = overridableMkRustCrate (profileName: rec {
|
||||||
|
name = "garage_block";
|
||||||
|
version = "0.7.0";
|
||||||
|
registry = "unknown";
|
||||||
|
src = fetchCrateLocal (workspaceSrc + "/src/block");
|
||||||
|
dependencies = {
|
||||||
|
async_trait = buildRustPackages."registry+https://github.com/rust-lang/crates.io-index".async-trait."0.1.52" { profileName = "__noProfile"; };
|
||||||
|
bytes = rustPackages."registry+https://github.com/rust-lang/crates.io-index".bytes."1.1.0" { inherit profileName; };
|
||||||
|
futures = rustPackages."registry+https://github.com/rust-lang/crates.io-index".futures."0.3.21" { inherit profileName; };
|
||||||
|
futures_util = rustPackages."registry+https://github.com/rust-lang/crates.io-index".futures-util."0.3.21" { inherit profileName; };
|
||||||
|
garage_rpc = rustPackages."unknown".garage_rpc."0.7.0" { inherit profileName; };
|
||||||
|
garage_table = rustPackages."unknown".garage_table."0.7.0" { inherit profileName; };
|
||||||
|
garage_util = rustPackages."unknown".garage_util."0.7.0" { inherit profileName; };
|
||||||
|
hex = rustPackages."registry+https://github.com/rust-lang/crates.io-index".hex."0.4.3" { inherit profileName; };
|
||||||
|
opentelemetry = rustPackages."registry+https://github.com/rust-lang/crates.io-index".opentelemetry."0.17.0" { inherit profileName; };
|
||||||
|
rand = rustPackages."registry+https://github.com/rust-lang/crates.io-index".rand."0.8.5" { inherit profileName; };
|
||||||
|
rmp_serde = rustPackages."registry+https://github.com/rust-lang/crates.io-index".rmp-serde."0.15.5" { inherit profileName; };
|
||||||
|
serde = rustPackages."registry+https://github.com/rust-lang/crates.io-index".serde."1.0.136" { inherit profileName; };
|
||||||
|
serde_bytes = rustPackages."registry+https://github.com/rust-lang/crates.io-index".serde_bytes."0.11.5" { inherit profileName; };
|
||||||
|
sled = rustPackages."registry+https://github.com/rust-lang/crates.io-index".sled."0.34.7" { inherit profileName; };
|
||||||
|
tokio = rustPackages."registry+https://github.com/rust-lang/crates.io-index".tokio."1.17.0" { inherit profileName; };
|
||||||
|
tracing = rustPackages."registry+https://github.com/rust-lang/crates.io-index".tracing."0.1.32" { inherit profileName; };
|
||||||
|
zstd = rustPackages."registry+https://github.com/rust-lang/crates.io-index".zstd."0.9.2+zstd.1.5.1" { inherit profileName; };
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
"registry+https://github.com/rust-lang/crates.io-index".garage_model."0.5.1" = overridableMkRustCrate (profileName: rec {
|
"registry+https://github.com/rust-lang/crates.io-index".garage_model."0.5.1" = overridableMkRustCrate (profileName: rec {
|
||||||
name = "garage_model";
|
name = "garage_model";
|
||||||
version = "0.5.1";
|
version = "0.5.1";
|
||||||
|
@ -1302,6 +1331,7 @@ in
|
||||||
err_derive = buildRustPackages."registry+https://github.com/rust-lang/crates.io-index".err-derive."0.3.1" { profileName = "__noProfile"; };
|
err_derive = buildRustPackages."registry+https://github.com/rust-lang/crates.io-index".err-derive."0.3.1" { profileName = "__noProfile"; };
|
||||||
futures = rustPackages."registry+https://github.com/rust-lang/crates.io-index".futures."0.3.21" { inherit profileName; };
|
futures = rustPackages."registry+https://github.com/rust-lang/crates.io-index".futures."0.3.21" { inherit profileName; };
|
||||||
futures_util = rustPackages."registry+https://github.com/rust-lang/crates.io-index".futures-util."0.3.21" { inherit profileName; };
|
futures_util = rustPackages."registry+https://github.com/rust-lang/crates.io-index".futures-util."0.3.21" { inherit profileName; };
|
||||||
|
garage_block = rustPackages."unknown".garage_block."0.7.0" { inherit profileName; };
|
||||||
garage_model_050 = rustPackages."registry+https://github.com/rust-lang/crates.io-index".garage_model."0.5.1" { inherit profileName; };
|
garage_model_050 = rustPackages."registry+https://github.com/rust-lang/crates.io-index".garage_model."0.5.1" { inherit profileName; };
|
||||||
garage_rpc = rustPackages."unknown".garage_rpc."0.7.0" { inherit profileName; };
|
garage_rpc = rustPackages."unknown".garage_rpc."0.7.0" { inherit profileName; };
|
||||||
garage_table = rustPackages."unknown".garage_table."0.7.0" { inherit profileName; };
|
garage_table = rustPackages."unknown".garage_table."0.7.0" { inherit profileName; };
|
||||||
|
@ -1738,12 +1768,12 @@ in
|
||||||
features = builtins.concatLists [
|
features = builtins.concatLists [
|
||||||
[ "client" ]
|
[ "client" ]
|
||||||
[ "default" ]
|
[ "default" ]
|
||||||
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "full")
|
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "full")
|
||||||
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "h2")
|
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "h2")
|
||||||
[ "http1" ]
|
[ "http1" ]
|
||||||
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "http2")
|
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "http2")
|
||||||
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "runtime")
|
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "runtime")
|
||||||
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "server")
|
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "server")
|
||||||
[ "socket2" ]
|
[ "socket2" ]
|
||||||
[ "stream" ]
|
[ "stream" ]
|
||||||
[ "tcp" ]
|
[ "tcp" ]
|
||||||
|
@ -1753,7 +1783,7 @@ in
|
||||||
futures_channel = rustPackages."registry+https://github.com/rust-lang/crates.io-index".futures-channel."0.3.21" { inherit profileName; };
|
futures_channel = rustPackages."registry+https://github.com/rust-lang/crates.io-index".futures-channel."0.3.21" { inherit profileName; };
|
||||||
futures_core = rustPackages."registry+https://github.com/rust-lang/crates.io-index".futures-core."0.3.21" { inherit profileName; };
|
futures_core = rustPackages."registry+https://github.com/rust-lang/crates.io-index".futures-core."0.3.21" { inherit profileName; };
|
||||||
futures_util = rustPackages."registry+https://github.com/rust-lang/crates.io-index".futures-util."0.3.21" { inherit profileName; };
|
futures_util = rustPackages."registry+https://github.com/rust-lang/crates.io-index".futures-util."0.3.21" { inherit profileName; };
|
||||||
${ if rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web" then "h2" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".h2."0.3.12" { inherit profileName; };
|
${ if rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web" then "h2" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".h2."0.3.12" { inherit profileName; };
|
||||||
http = rustPackages."registry+https://github.com/rust-lang/crates.io-index".http."0.2.6" { inherit profileName; };
|
http = rustPackages."registry+https://github.com/rust-lang/crates.io-index".http."0.2.6" { inherit profileName; };
|
||||||
http_body = rustPackages."registry+https://github.com/rust-lang/crates.io-index".http-body."0.4.4" { inherit profileName; };
|
http_body = rustPackages."registry+https://github.com/rust-lang/crates.io-index".http-body."0.4.4" { inherit profileName; };
|
||||||
httparse = rustPackages."registry+https://github.com/rust-lang/crates.io-index".httparse."1.6.0" { inherit profileName; };
|
httparse = rustPackages."registry+https://github.com/rust-lang/crates.io-index".httparse."1.6.0" { inherit profileName; };
|
||||||
|
@ -1845,7 +1875,7 @@ in
|
||||||
registry = "registry+https://github.com/rust-lang/crates.io-index";
|
registry = "registry+https://github.com/rust-lang/crates.io-index";
|
||||||
src = fetchCratesIo { inherit name version; sha256 = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223"; };
|
src = fetchCratesIo { inherit name version; sha256 = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223"; };
|
||||||
features = builtins.concatLists [
|
features = builtins.concatLists [
|
||||||
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "std")
|
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "std")
|
||||||
];
|
];
|
||||||
dependencies = {
|
dependencies = {
|
||||||
hashbrown = rustPackages."registry+https://github.com/rust-lang/crates.io-index".hashbrown."0.11.2" { inherit profileName; };
|
hashbrown = rustPackages."registry+https://github.com/rust-lang/crates.io-index".hashbrown."0.11.2" { inherit profileName; };
|
||||||
|
@ -2424,10 +2454,10 @@ in
|
||||||
src = fetchCratesIo { inherit name version; sha256 = "22c545a13b0c47b47e8052b35c4884dbe33c9ea62607371b0f4f1b0490cafd38"; };
|
src = fetchCratesIo { inherit name version; sha256 = "22c545a13b0c47b47e8052b35c4884dbe33c9ea62607371b0f4f1b0490cafd38"; };
|
||||||
features = builtins.concatLists [
|
features = builtins.concatLists [
|
||||||
[ "default" ]
|
[ "default" ]
|
||||||
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "opentelemetry")
|
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "opentelemetry")
|
||||||
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "opentelemetry-contrib")
|
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "opentelemetry-contrib")
|
||||||
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "rand")
|
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "rand")
|
||||||
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "telemetry")
|
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "telemetry")
|
||||||
];
|
];
|
||||||
dependencies = {
|
dependencies = {
|
||||||
arc_swap = rustPackages."registry+https://github.com/rust-lang/crates.io-index".arc-swap."1.5.0" { inherit profileName; };
|
arc_swap = rustPackages."registry+https://github.com/rust-lang/crates.io-index".arc-swap."1.5.0" { inherit profileName; };
|
||||||
|
@ -2440,9 +2470,9 @@ in
|
||||||
kuska_handshake = rustPackages."registry+https://github.com/rust-lang/crates.io-index".kuska-handshake."0.2.0" { inherit profileName; };
|
kuska_handshake = rustPackages."registry+https://github.com/rust-lang/crates.io-index".kuska-handshake."0.2.0" { inherit profileName; };
|
||||||
sodiumoxide = rustPackages."registry+https://github.com/rust-lang/crates.io-index".kuska-sodiumoxide."0.2.5-0" { inherit profileName; };
|
sodiumoxide = rustPackages."registry+https://github.com/rust-lang/crates.io-index".kuska-sodiumoxide."0.2.5-0" { inherit profileName; };
|
||||||
log = rustPackages."registry+https://github.com/rust-lang/crates.io-index".log."0.4.14" { inherit profileName; };
|
log = rustPackages."registry+https://github.com/rust-lang/crates.io-index".log."0.4.14" { inherit profileName; };
|
||||||
${ if rootFeatures' ? "garage" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web" then "opentelemetry" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".opentelemetry."0.17.0" { inherit profileName; };
|
${ if rootFeatures' ? "garage" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web" then "opentelemetry" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".opentelemetry."0.17.0" { inherit profileName; };
|
||||||
${ if rootFeatures' ? "garage" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web" then "opentelemetry_contrib" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".opentelemetry-contrib."0.9.0" { inherit profileName; };
|
${ if rootFeatures' ? "garage" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web" then "opentelemetry_contrib" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".opentelemetry-contrib."0.9.0" { inherit profileName; };
|
||||||
${ if rootFeatures' ? "garage" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web" then "rand" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".rand."0.5.6" { inherit profileName; };
|
${ if rootFeatures' ? "garage" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web" then "rand" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".rand."0.5.6" { inherit profileName; };
|
||||||
rmp_serde = rustPackages."registry+https://github.com/rust-lang/crates.io-index".rmp-serde."0.14.4" { inherit profileName; };
|
rmp_serde = rustPackages."registry+https://github.com/rust-lang/crates.io-index".rmp-serde."0.14.4" { inherit profileName; };
|
||||||
serde = rustPackages."registry+https://github.com/rust-lang/crates.io-index".serde."1.0.136" { inherit profileName; };
|
serde = rustPackages."registry+https://github.com/rust-lang/crates.io-index".serde."1.0.136" { inherit profileName; };
|
||||||
tokio = rustPackages."registry+https://github.com/rust-lang/crates.io-index".tokio."1.17.0" { inherit profileName; };
|
tokio = rustPackages."registry+https://github.com/rust-lang/crates.io-index".tokio."1.17.0" { inherit profileName; };
|
||||||
|
@ -2562,7 +2592,7 @@ in
|
||||||
registry = "registry+https://github.com/rust-lang/crates.io-index";
|
registry = "registry+https://github.com/rust-lang/crates.io-index";
|
||||||
src = fetchCratesIo { inherit name version; sha256 = "0c7ae222234c30df141154f159066c5093ff73b63204dcda7121eb082fc56a95"; };
|
src = fetchCratesIo { inherit name version; sha256 = "0c7ae222234c30df141154f159066c5093ff73b63204dcda7121eb082fc56a95"; };
|
||||||
features = builtins.concatLists [
|
features = builtins.concatLists [
|
||||||
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "vendored")
|
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "vendored")
|
||||||
];
|
];
|
||||||
dependencies = {
|
dependencies = {
|
||||||
bitflags = rustPackages."registry+https://github.com/rust-lang/crates.io-index".bitflags."1.3.2" { inherit profileName; };
|
bitflags = rustPackages."registry+https://github.com/rust-lang/crates.io-index".bitflags."1.3.2" { inherit profileName; };
|
||||||
|
@ -2600,8 +2630,8 @@ in
|
||||||
registry = "registry+https://github.com/rust-lang/crates.io-index";
|
registry = "registry+https://github.com/rust-lang/crates.io-index";
|
||||||
src = fetchCratesIo { inherit name version; sha256 = "7e46109c383602735fa0a2e48dd2b7c892b048e1bf69e5c3b1d804b7d9c203cb"; };
|
src = fetchCratesIo { inherit name version; sha256 = "7e46109c383602735fa0a2e48dd2b7c892b048e1bf69e5c3b1d804b7d9c203cb"; };
|
||||||
features = builtins.concatLists [
|
features = builtins.concatLists [
|
||||||
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "openssl-src")
|
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "openssl-src")
|
||||||
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "vendored")
|
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "vendored")
|
||||||
];
|
];
|
||||||
dependencies = {
|
dependencies = {
|
||||||
libc = rustPackages."registry+https://github.com/rust-lang/crates.io-index".libc."0.2.119" { inherit profileName; };
|
libc = rustPackages."registry+https://github.com/rust-lang/crates.io-index".libc."0.2.119" { inherit profileName; };
|
||||||
|
@ -2609,7 +2639,7 @@ in
|
||||||
buildDependencies = {
|
buildDependencies = {
|
||||||
autocfg = buildRustPackages."registry+https://github.com/rust-lang/crates.io-index".autocfg."1.1.0" { profileName = "__noProfile"; };
|
autocfg = buildRustPackages."registry+https://github.com/rust-lang/crates.io-index".autocfg."1.1.0" { profileName = "__noProfile"; };
|
||||||
cc = buildRustPackages."registry+https://github.com/rust-lang/crates.io-index".cc."1.0.73" { profileName = "__noProfile"; };
|
cc = buildRustPackages."registry+https://github.com/rust-lang/crates.io-index".cc."1.0.73" { profileName = "__noProfile"; };
|
||||||
${ if rootFeatures' ? "garage" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web" then "openssl_src" else null } = buildRustPackages."registry+https://github.com/rust-lang/crates.io-index".openssl-src."111.17.0+1.1.1m" { profileName = "__noProfile"; };
|
${ if rootFeatures' ? "garage" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web" then "openssl_src" else null } = buildRustPackages."registry+https://github.com/rust-lang/crates.io-index".openssl-src."111.17.0+1.1.1m" { profileName = "__noProfile"; };
|
||||||
pkg_config = buildRustPackages."registry+https://github.com/rust-lang/crates.io-index".pkg-config."0.3.24" { profileName = "__noProfile"; };
|
pkg_config = buildRustPackages."registry+https://github.com/rust-lang/crates.io-index".pkg-config."0.3.24" { profileName = "__noProfile"; };
|
||||||
${ if hostPlatform.parsed.abi.name == "msvc" then "vcpkg" else null } = buildRustPackages."registry+https://github.com/rust-lang/crates.io-index".vcpkg."0.2.15" { profileName = "__noProfile"; };
|
${ if hostPlatform.parsed.abi.name == "msvc" then "vcpkg" else null } = buildRustPackages."registry+https://github.com/rust-lang/crates.io-index".vcpkg."0.2.15" { profileName = "__noProfile"; };
|
||||||
};
|
};
|
||||||
|
@ -2623,23 +2653,23 @@ in
|
||||||
features = builtins.concatLists [
|
features = builtins.concatLists [
|
||||||
[ "async-trait" ]
|
[ "async-trait" ]
|
||||||
[ "crossbeam-channel" ]
|
[ "crossbeam-channel" ]
|
||||||
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "dashmap")
|
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "dashmap")
|
||||||
[ "default" ]
|
[ "default" ]
|
||||||
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "fnv")
|
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "fnv")
|
||||||
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "metrics")
|
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "metrics")
|
||||||
[ "percent-encoding" ]
|
[ "percent-encoding" ]
|
||||||
[ "pin-project" ]
|
[ "pin-project" ]
|
||||||
[ "rand" ]
|
[ "rand" ]
|
||||||
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "rt-tokio")
|
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "rt-tokio")
|
||||||
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "tokio")
|
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "tokio")
|
||||||
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "tokio-stream")
|
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "tokio-stream")
|
||||||
[ "trace" ]
|
[ "trace" ]
|
||||||
];
|
];
|
||||||
dependencies = {
|
dependencies = {
|
||||||
async_trait = buildRustPackages."registry+https://github.com/rust-lang/crates.io-index".async-trait."0.1.52" { profileName = "__noProfile"; };
|
async_trait = buildRustPackages."registry+https://github.com/rust-lang/crates.io-index".async-trait."0.1.52" { profileName = "__noProfile"; };
|
||||||
crossbeam_channel = rustPackages."registry+https://github.com/rust-lang/crates.io-index".crossbeam-channel."0.5.2" { inherit profileName; };
|
crossbeam_channel = rustPackages."registry+https://github.com/rust-lang/crates.io-index".crossbeam-channel."0.5.2" { inherit profileName; };
|
||||||
${ if rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web" then "dashmap" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".dashmap."4.0.2" { inherit profileName; };
|
${ if rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web" then "dashmap" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".dashmap."4.0.2" { inherit profileName; };
|
||||||
${ if rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web" then "fnv" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".fnv."1.0.7" { inherit profileName; };
|
${ if rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web" then "fnv" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".fnv."1.0.7" { inherit profileName; };
|
||||||
futures_channel = rustPackages."registry+https://github.com/rust-lang/crates.io-index".futures-channel."0.3.21" { inherit profileName; };
|
futures_channel = rustPackages."registry+https://github.com/rust-lang/crates.io-index".futures-channel."0.3.21" { inherit profileName; };
|
||||||
futures_executor = rustPackages."registry+https://github.com/rust-lang/crates.io-index".futures-executor."0.3.21" { inherit profileName; };
|
futures_executor = rustPackages."registry+https://github.com/rust-lang/crates.io-index".futures-executor."0.3.21" { inherit profileName; };
|
||||||
futures_util = rustPackages."registry+https://github.com/rust-lang/crates.io-index".futures-util."0.3.21" { inherit profileName; };
|
futures_util = rustPackages."registry+https://github.com/rust-lang/crates.io-index".futures-util."0.3.21" { inherit profileName; };
|
||||||
|
@ -2649,8 +2679,8 @@ in
|
||||||
pin_project = rustPackages."registry+https://github.com/rust-lang/crates.io-index".pin-project."1.0.10" { inherit profileName; };
|
pin_project = rustPackages."registry+https://github.com/rust-lang/crates.io-index".pin-project."1.0.10" { inherit profileName; };
|
||||||
rand = rustPackages."registry+https://github.com/rust-lang/crates.io-index".rand."0.8.5" { inherit profileName; };
|
rand = rustPackages."registry+https://github.com/rust-lang/crates.io-index".rand."0.8.5" { inherit profileName; };
|
||||||
thiserror = rustPackages."registry+https://github.com/rust-lang/crates.io-index".thiserror."1.0.30" { inherit profileName; };
|
thiserror = rustPackages."registry+https://github.com/rust-lang/crates.io-index".thiserror."1.0.30" { inherit profileName; };
|
||||||
${ if rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web" then "tokio" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".tokio."1.17.0" { inherit profileName; };
|
${ if rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web" then "tokio" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".tokio."1.17.0" { inherit profileName; };
|
||||||
${ if rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web" then "tokio_stream" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".tokio-stream."0.1.8" { inherit profileName; };
|
${ if rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web" then "tokio_stream" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".tokio-stream."0.1.8" { inherit profileName; };
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -3216,7 +3246,7 @@ in
|
||||||
[ "getrandom" ]
|
[ "getrandom" ]
|
||||||
[ "libc" ]
|
[ "libc" ]
|
||||||
[ "rand_chacha" ]
|
[ "rand_chacha" ]
|
||||||
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "small_rng")
|
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "small_rng")
|
||||||
[ "std" ]
|
[ "std" ]
|
||||||
[ "std_rng" ]
|
[ "std_rng" ]
|
||||||
];
|
];
|
||||||
|
@ -3308,27 +3338,27 @@ in
|
||||||
registry = "registry+https://github.com/rust-lang/crates.io-index";
|
registry = "registry+https://github.com/rust-lang/crates.io-index";
|
||||||
src = fetchCratesIo { inherit name version; sha256 = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286"; };
|
src = fetchCratesIo { inherit name version; sha256 = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286"; };
|
||||||
features = builtins.concatLists [
|
features = builtins.concatLists [
|
||||||
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "aho-corasick")
|
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "aho-corasick")
|
||||||
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "default")
|
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "default")
|
||||||
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "memchr")
|
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "memchr")
|
||||||
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "perf")
|
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "perf")
|
||||||
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "perf-cache")
|
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "perf-cache")
|
||||||
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "perf-dfa")
|
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "perf-dfa")
|
||||||
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "perf-inline")
|
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "perf-inline")
|
||||||
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "perf-literal")
|
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "perf-literal")
|
||||||
[ "std" ]
|
[ "std" ]
|
||||||
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "unicode")
|
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "unicode")
|
||||||
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "unicode-age")
|
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "unicode-age")
|
||||||
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "unicode-bool")
|
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "unicode-bool")
|
||||||
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "unicode-case")
|
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "unicode-case")
|
||||||
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "unicode-gencat")
|
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "unicode-gencat")
|
||||||
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "unicode-perl")
|
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "unicode-perl")
|
||||||
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "unicode-script")
|
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "unicode-script")
|
||||||
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "unicode-segment")
|
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "unicode-segment")
|
||||||
];
|
];
|
||||||
dependencies = {
|
dependencies = {
|
||||||
${ if rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web" then "aho_corasick" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".aho-corasick."0.7.18" { inherit profileName; };
|
${ if rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web" then "aho_corasick" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".aho-corasick."0.7.18" { inherit profileName; };
|
||||||
${ if rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web" then "memchr" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".memchr."2.4.1" { inherit profileName; };
|
${ if rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web" then "memchr" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".memchr."2.4.1" { inherit profileName; };
|
||||||
regex_syntax = rustPackages."registry+https://github.com/rust-lang/crates.io-index".regex-syntax."0.6.25" { inherit profileName; };
|
regex_syntax = rustPackages."registry+https://github.com/rust-lang/crates.io-index".regex-syntax."0.6.25" { inherit profileName; };
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
@ -3851,7 +3881,7 @@ in
|
||||||
];
|
];
|
||||||
dependencies = {
|
dependencies = {
|
||||||
bitflags = rustPackages."registry+https://github.com/rust-lang/crates.io-index".bitflags."1.3.2" { inherit profileName; };
|
bitflags = rustPackages."registry+https://github.com/rust-lang/crates.io-index".bitflags."1.3.2" { inherit profileName; };
|
||||||
${ if hostPlatform.parsed.kernel.name == "android" || hostPlatform.parsed.kernel.name == "linux" then "libc" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".libc."0.2.119" { inherit profileName; };
|
${ if hostPlatform.parsed.kernel.name == "linux" || hostPlatform.parsed.kernel.name == "android" then "libc" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".libc."0.2.119" { inherit profileName; };
|
||||||
${ if !(hostPlatform.parsed.kernel.name == "linux" || hostPlatform.parsed.kernel.name == "android") then "parking_lot" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".parking_lot."0.11.2" { inherit profileName; };
|
${ if !(hostPlatform.parsed.kernel.name == "linux" || hostPlatform.parsed.kernel.name == "android") then "parking_lot" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".parking_lot."0.11.2" { inherit profileName; };
|
||||||
${ if !(hostPlatform.parsed.kernel.name == "linux" || hostPlatform.parsed.kernel.name == "android") then "parking_lot_core" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".parking_lot_core."0.8.5" { inherit profileName; };
|
${ if !(hostPlatform.parsed.kernel.name == "linux" || hostPlatform.parsed.kernel.name == "android") then "parking_lot_core" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".parking_lot_core."0.8.5" { inherit profileName; };
|
||||||
static_init_macro = buildRustPackages."registry+https://github.com/rust-lang/crates.io-index".static_init_macro."1.0.2" { profileName = "__noProfile"; };
|
static_init_macro = buildRustPackages."registry+https://github.com/rust-lang/crates.io-index".static_init_macro."1.0.2" { profileName = "__noProfile"; };
|
||||||
|
@ -4077,8 +4107,8 @@ in
|
||||||
[ "bytes" ]
|
[ "bytes" ]
|
||||||
[ "default" ]
|
[ "default" ]
|
||||||
[ "fs" ]
|
[ "fs" ]
|
||||||
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "full")
|
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "full")
|
||||||
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "io-std")
|
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "io-std")
|
||||||
[ "io-util" ]
|
[ "io-util" ]
|
||||||
[ "libc" ]
|
[ "libc" ]
|
||||||
[ "macros" ]
|
[ "macros" ]
|
||||||
|
@ -4087,8 +4117,8 @@ in
|
||||||
[ "net" ]
|
[ "net" ]
|
||||||
[ "num_cpus" ]
|
[ "num_cpus" ]
|
||||||
[ "once_cell" ]
|
[ "once_cell" ]
|
||||||
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "parking_lot")
|
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "parking_lot")
|
||||||
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "process")
|
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "process")
|
||||||
[ "rt" ]
|
[ "rt" ]
|
||||||
[ "rt-multi-thread" ]
|
[ "rt-multi-thread" ]
|
||||||
[ "signal" ]
|
[ "signal" ]
|
||||||
|
@ -4106,7 +4136,7 @@ in
|
||||||
mio = rustPackages."registry+https://github.com/rust-lang/crates.io-index".mio."0.8.1" { inherit profileName; };
|
mio = rustPackages."registry+https://github.com/rust-lang/crates.io-index".mio."0.8.1" { inherit profileName; };
|
||||||
num_cpus = rustPackages."registry+https://github.com/rust-lang/crates.io-index".num_cpus."1.13.1" { inherit profileName; };
|
num_cpus = rustPackages."registry+https://github.com/rust-lang/crates.io-index".num_cpus."1.13.1" { inherit profileName; };
|
||||||
once_cell = rustPackages."registry+https://github.com/rust-lang/crates.io-index".once_cell."1.10.0" { inherit profileName; };
|
once_cell = rustPackages."registry+https://github.com/rust-lang/crates.io-index".once_cell."1.10.0" { inherit profileName; };
|
||||||
${ if rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web" then "parking_lot" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".parking_lot."0.12.0" { inherit profileName; };
|
${ if rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web" then "parking_lot" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".parking_lot."0.12.0" { inherit profileName; };
|
||||||
pin_project_lite = rustPackages."registry+https://github.com/rust-lang/crates.io-index".pin-project-lite."0.2.8" { inherit profileName; };
|
pin_project_lite = rustPackages."registry+https://github.com/rust-lang/crates.io-index".pin-project-lite."0.2.8" { inherit profileName; };
|
||||||
${ if hostPlatform.isUnix then "signal_hook_registry" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".signal-hook-registry."1.4.0" { inherit profileName; };
|
${ if hostPlatform.isUnix then "signal_hook_registry" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".signal-hook-registry."1.4.0" { inherit profileName; };
|
||||||
socket2 = rustPackages."registry+https://github.com/rust-lang/crates.io-index".socket2."0.4.4" { inherit profileName; };
|
socket2 = rustPackages."registry+https://github.com/rust-lang/crates.io-index".socket2."0.4.4" { inherit profileName; };
|
||||||
|
@ -4168,7 +4198,7 @@ in
|
||||||
src = fetchCratesIo { inherit name version; sha256 = "50145484efff8818b5ccd256697f36863f587da82cf8b409c53adf1e840798e3"; };
|
src = fetchCratesIo { inherit name version; sha256 = "50145484efff8818b5ccd256697f36863f587da82cf8b409c53adf1e840798e3"; };
|
||||||
features = builtins.concatLists [
|
features = builtins.concatLists [
|
||||||
[ "default" ]
|
[ "default" ]
|
||||||
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "net")
|
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "net")
|
||||||
[ "time" ]
|
[ "time" ]
|
||||||
];
|
];
|
||||||
dependencies = {
|
dependencies = {
|
||||||
|
@ -4304,24 +4334,24 @@ in
|
||||||
src = fetchCratesIo { inherit name version; sha256 = "9a89fd63ad6adf737582df5db40d286574513c69a11dac5214dc3b5603d6713e"; };
|
src = fetchCratesIo { inherit name version; sha256 = "9a89fd63ad6adf737582df5db40d286574513c69a11dac5214dc3b5603d6713e"; };
|
||||||
features = builtins.concatLists [
|
features = builtins.concatLists [
|
||||||
[ "__common" ]
|
[ "__common" ]
|
||||||
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "balance")
|
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "balance")
|
||||||
[ "buffer" ]
|
[ "buffer" ]
|
||||||
[ "default" ]
|
[ "default" ]
|
||||||
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "discover")
|
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "discover")
|
||||||
[ "futures-core" ]
|
[ "futures-core" ]
|
||||||
[ "futures-util" ]
|
[ "futures-util" ]
|
||||||
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "indexmap")
|
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "indexmap")
|
||||||
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "limit")
|
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "limit")
|
||||||
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "load")
|
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "load")
|
||||||
[ "log" ]
|
[ "log" ]
|
||||||
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "make")
|
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "make")
|
||||||
[ "pin-project" ]
|
[ "pin-project" ]
|
||||||
[ "pin-project-lite" ]
|
[ "pin-project-lite" ]
|
||||||
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "rand")
|
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "rand")
|
||||||
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "ready-cache")
|
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "ready-cache")
|
||||||
(lib.optional (rootFeatures' ? "garage") "retry")
|
(lib.optional (rootFeatures' ? "garage") "retry")
|
||||||
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "slab")
|
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "slab")
|
||||||
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "timeout")
|
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "timeout")
|
||||||
[ "tokio" ]
|
[ "tokio" ]
|
||||||
[ "tokio-util" ]
|
[ "tokio-util" ]
|
||||||
[ "tracing" ]
|
[ "tracing" ]
|
||||||
|
@ -4330,11 +4360,11 @@ in
|
||||||
dependencies = {
|
dependencies = {
|
||||||
futures_core = rustPackages."registry+https://github.com/rust-lang/crates.io-index".futures-core."0.3.21" { inherit profileName; };
|
futures_core = rustPackages."registry+https://github.com/rust-lang/crates.io-index".futures-core."0.3.21" { inherit profileName; };
|
||||||
futures_util = rustPackages."registry+https://github.com/rust-lang/crates.io-index".futures-util."0.3.21" { inherit profileName; };
|
futures_util = rustPackages."registry+https://github.com/rust-lang/crates.io-index".futures-util."0.3.21" { inherit profileName; };
|
||||||
${ if rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web" then "indexmap" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".indexmap."1.8.0" { inherit profileName; };
|
${ if rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web" then "indexmap" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".indexmap."1.8.0" { inherit profileName; };
|
||||||
pin_project = rustPackages."registry+https://github.com/rust-lang/crates.io-index".pin-project."1.0.10" { inherit profileName; };
|
pin_project = rustPackages."registry+https://github.com/rust-lang/crates.io-index".pin-project."1.0.10" { inherit profileName; };
|
||||||
pin_project_lite = rustPackages."registry+https://github.com/rust-lang/crates.io-index".pin-project-lite."0.2.8" { inherit profileName; };
|
pin_project_lite = rustPackages."registry+https://github.com/rust-lang/crates.io-index".pin-project-lite."0.2.8" { inherit profileName; };
|
||||||
${ if rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web" then "rand" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".rand."0.8.5" { inherit profileName; };
|
${ if rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web" then "rand" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".rand."0.8.5" { inherit profileName; };
|
||||||
${ if rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web" then "slab" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".slab."0.4.5" { inherit profileName; };
|
${ if rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web" then "slab" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".slab."0.4.5" { inherit profileName; };
|
||||||
tokio = rustPackages."registry+https://github.com/rust-lang/crates.io-index".tokio."1.17.0" { inherit profileName; };
|
tokio = rustPackages."registry+https://github.com/rust-lang/crates.io-index".tokio."1.17.0" { inherit profileName; };
|
||||||
tokio_util = rustPackages."registry+https://github.com/rust-lang/crates.io-index".tokio-util."0.7.0" { inherit profileName; };
|
tokio_util = rustPackages."registry+https://github.com/rust-lang/crates.io-index".tokio-util."0.7.0" { inherit profileName; };
|
||||||
tower_layer = rustPackages."registry+https://github.com/rust-lang/crates.io-index".tower-layer."0.3.1" { inherit profileName; };
|
tower_layer = rustPackages."registry+https://github.com/rust-lang/crates.io-index".tower-layer."0.3.1" { inherit profileName; };
|
||||||
|
@ -4761,7 +4791,7 @@ in
|
||||||
[ "std" ]
|
[ "std" ]
|
||||||
[ "synchapi" ]
|
[ "synchapi" ]
|
||||||
[ "sysinfoapi" ]
|
[ "sysinfoapi" ]
|
||||||
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "threadpoollegacyapiset")
|
(lib.optional (rootFeatures' ? "garage" || rootFeatures' ? "garage_admin" || rootFeatures' ? "garage_api" || rootFeatures' ? "garage_block" || rootFeatures' ? "garage_model" || rootFeatures' ? "garage_rpc" || rootFeatures' ? "garage_table" || rootFeatures' ? "garage_web") "threadpoollegacyapiset")
|
||||||
[ "timezoneapi" ]
|
[ "timezoneapi" ]
|
||||||
[ "winbase" ]
|
[ "winbase" ]
|
||||||
[ "wincon" ]
|
[ "wincon" ]
|
||||||
|
@ -4821,9 +4851,9 @@ in
|
||||||
[ "default" ]
|
[ "default" ]
|
||||||
];
|
];
|
||||||
dependencies = {
|
dependencies = {
|
||||||
${ if hostPlatform.config == "aarch64-pc-windows-msvc" || hostPlatform.config == "aarch64-uwp-windows-msvc" then "windows_aarch64_msvc" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".windows_aarch64_msvc."0.32.0" { inherit profileName; };
|
${ if hostPlatform.config == "aarch64-uwp-windows-msvc" || hostPlatform.config == "aarch64-pc-windows-msvc" then "windows_aarch64_msvc" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".windows_aarch64_msvc."0.32.0" { inherit profileName; };
|
||||||
${ if hostPlatform.config == "i686-uwp-windows-gnu" || hostPlatform.config == "i686-pc-windows-gnu" then "windows_i686_gnu" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".windows_i686_gnu."0.32.0" { inherit profileName; };
|
${ if hostPlatform.config == "i686-uwp-windows-gnu" || hostPlatform.config == "i686-pc-windows-gnu" then "windows_i686_gnu" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".windows_i686_gnu."0.32.0" { inherit profileName; };
|
||||||
${ if hostPlatform.config == "i686-pc-windows-msvc" || hostPlatform.config == "i686-uwp-windows-msvc" then "windows_i686_msvc" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".windows_i686_msvc."0.32.0" { inherit profileName; };
|
${ if hostPlatform.config == "i686-uwp-windows-msvc" || hostPlatform.config == "i686-pc-windows-msvc" then "windows_i686_msvc" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".windows_i686_msvc."0.32.0" { inherit profileName; };
|
||||||
${ if hostPlatform.config == "x86_64-pc-windows-gnu" || hostPlatform.config == "x86_64-uwp-windows-gnu" then "windows_x86_64_gnu" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".windows_x86_64_gnu."0.32.0" { inherit profileName; };
|
${ if hostPlatform.config == "x86_64-pc-windows-gnu" || hostPlatform.config == "x86_64-uwp-windows-gnu" then "windows_x86_64_gnu" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".windows_x86_64_gnu."0.32.0" { inherit profileName; };
|
||||||
${ if hostPlatform.config == "x86_64-uwp-windows-msvc" || hostPlatform.config == "x86_64-pc-windows-msvc" then "windows_x86_64_msvc" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".windows_x86_64_msvc."0.32.0" { inherit profileName; };
|
${ if hostPlatform.config == "x86_64-uwp-windows-msvc" || hostPlatform.config == "x86_64-pc-windows-msvc" then "windows_x86_64_msvc" else null } = rustPackages."registry+https://github.com/rust-lang/crates.io-index".windows_x86_64_msvc."0.32.0" { inherit profileName; };
|
||||||
};
|
};
|
||||||
|
|
|
@ -16,6 +16,7 @@ path = "lib.rs"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
garage_model = { version = "0.7.0", path = "../model" }
|
garage_model = { version = "0.7.0", path = "../model" }
|
||||||
garage_table = { version = "0.7.0", path = "../table" }
|
garage_table = { version = "0.7.0", path = "../table" }
|
||||||
|
garage_block = { version = "0.7.0", path = "../block" }
|
||||||
garage_util = { version = "0.7.0", path = "../util" }
|
garage_util = { version = "0.7.0", path = "../util" }
|
||||||
|
|
||||||
base64 = "0.13"
|
base64 = "0.13"
|
||||||
|
|
|
@ -14,7 +14,7 @@ use garage_util::data::*;
|
||||||
use garage_util::error::Error as GarageError;
|
use garage_util::error::Error as GarageError;
|
||||||
use garage_util::time::*;
|
use garage_util::time::*;
|
||||||
|
|
||||||
use garage_model::block::INLINE_THRESHOLD;
|
use garage_block::manager::INLINE_THRESHOLD;
|
||||||
use garage_model::block_ref_table::*;
|
use garage_model::block_ref_table::*;
|
||||||
use garage_model::garage::Garage;
|
use garage_model::garage::Garage;
|
||||||
use garage_model::key_table::Key;
|
use garage_model::key_table::Key;
|
||||||
|
|
38
src/block/Cargo.toml
Normal file
38
src/block/Cargo.toml
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
[package]
|
||||||
|
name = "garage_block"
|
||||||
|
version = "0.7.0"
|
||||||
|
authors = ["Alex Auvolat <alex@adnab.me>"]
|
||||||
|
edition = "2018"
|
||||||
|
license = "AGPL-3.0"
|
||||||
|
description = "Block manager for the Garage object store"
|
||||||
|
repository = "https://git.deuxfleurs.fr/Deuxfleurs/garage"
|
||||||
|
readme = "../../README.md"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
path = "lib.rs"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
garage_rpc = { version = "0.7.0", path = "../rpc" }
|
||||||
|
garage_util = { version = "0.7.0", path = "../util" }
|
||||||
|
garage_table = { version = "0.7.0", path = "../table" }
|
||||||
|
|
||||||
|
opentelemetry = "0.17"
|
||||||
|
|
||||||
|
async-trait = "0.1.7"
|
||||||
|
bytes = "1.0"
|
||||||
|
hex = "0.4"
|
||||||
|
tracing = "0.1.30"
|
||||||
|
rand = "0.8"
|
||||||
|
zstd = { version = "0.9", default-features = false }
|
||||||
|
|
||||||
|
sled = "0.34"
|
||||||
|
|
||||||
|
rmp-serde = "0.15"
|
||||||
|
serde = { version = "1.0", default-features = false, features = ["derive", "rc"] }
|
||||||
|
serde_bytes = "0.11"
|
||||||
|
|
||||||
|
futures = "0.3"
|
||||||
|
futures-util = "0.3"
|
||||||
|
tokio = { version = "1.0", default-features = false, features = ["rt", "rt-multi-thread", "io-util", "net", "time", "macros", "sync", "signal", "fs"] }
|
81
src/block/block.rs
Normal file
81
src/block/block.rs
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use zstd::stream::{decode_all as zstd_decode, Encoder};
|
||||||
|
|
||||||
|
use garage_util::data::*;
|
||||||
|
use garage_util::error::*;
|
||||||
|
|
||||||
|
/// A possibly compressed block of data
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub enum DataBlock {
|
||||||
|
/// Uncompressed data
|
||||||
|
Plain(#[serde(with = "serde_bytes")] Vec<u8>),
|
||||||
|
/// Data compressed with zstd
|
||||||
|
Compressed(#[serde(with = "serde_bytes")] Vec<u8>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DataBlock {
|
||||||
|
/// Query whether this block is compressed
|
||||||
|
pub fn is_compressed(&self) -> bool {
|
||||||
|
matches!(self, DataBlock::Compressed(_))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the inner, possibly compressed buffer. You should probably use [`DataBlock::verify_get`]
|
||||||
|
/// instead
|
||||||
|
pub fn inner_buffer(&self) -> &[u8] {
|
||||||
|
use DataBlock::*;
|
||||||
|
let (Plain(ref res) | Compressed(ref res)) = self;
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the buffer, possibly decompressing it, and verify it's integrity.
|
||||||
|
/// For Plain block, data is compared to hash, for Compressed block, zstd checksumming system
|
||||||
|
/// is used instead.
|
||||||
|
pub fn verify_get(self, hash: Hash) -> Result<Vec<u8>, Error> {
|
||||||
|
match self {
|
||||||
|
DataBlock::Plain(data) => {
|
||||||
|
if blake2sum(&data) == hash {
|
||||||
|
Ok(data)
|
||||||
|
} else {
|
||||||
|
Err(Error::CorruptData(hash))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DataBlock::Compressed(data) => {
|
||||||
|
zstd_decode(&data[..]).map_err(|_| Error::CorruptData(hash))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Verify data integrity. Allocate less than [`DataBlock::verify_get`] and don't consume self, but
|
||||||
|
/// does not return the buffer content.
|
||||||
|
pub fn verify(&self, hash: Hash) -> Result<(), Error> {
|
||||||
|
match self {
|
||||||
|
DataBlock::Plain(data) => {
|
||||||
|
if blake2sum(data) == hash {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(Error::CorruptData(hash))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DataBlock::Compressed(data) => zstd::stream::copy_decode(&data[..], std::io::sink())
|
||||||
|
.map_err(|_| Error::CorruptData(hash)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_buffer(data: Vec<u8>, level: Option<i32>) -> DataBlock {
|
||||||
|
if let Some(level) = level {
|
||||||
|
if let Ok(data) = zstd_encode(&data[..], level) {
|
||||||
|
return DataBlock::Compressed(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DataBlock::Plain(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn zstd_encode<R: std::io::Read>(mut source: R, level: i32) -> std::io::Result<Vec<u8>> {
|
||||||
|
let mut result = Vec::<u8>::new();
|
||||||
|
let mut encoder = Encoder::new(&mut result, level)?;
|
||||||
|
encoder.include_checksum(true)?;
|
||||||
|
std::io::copy(&mut source, &mut encoder)?;
|
||||||
|
encoder.finish()?;
|
||||||
|
Ok(result)
|
||||||
|
}
|
8
src/block/lib.rs
Normal file
8
src/block/lib.rs
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#[macro_use]
|
||||||
|
extern crate tracing;
|
||||||
|
|
||||||
|
pub mod manager;
|
||||||
|
|
||||||
|
mod block;
|
||||||
|
mod metrics;
|
||||||
|
mod rc;
|
|
@ -3,10 +3,8 @@ use std::path::{Path, PathBuf};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use arc_swap::ArcSwapOption;
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use zstd::stream::{decode_all as zstd_decode, Encoder};
|
|
||||||
|
|
||||||
use futures::future::*;
|
use futures::future::*;
|
||||||
use futures::select;
|
use futures::select;
|
||||||
|
@ -31,15 +29,13 @@ use garage_rpc::*;
|
||||||
|
|
||||||
use garage_table::replication::{TableReplication, TableShardedReplication};
|
use garage_table::replication::{TableReplication, TableShardedReplication};
|
||||||
|
|
||||||
use crate::block_metrics::*;
|
use crate::block::*;
|
||||||
use crate::block_ref_table::*;
|
use crate::metrics::*;
|
||||||
use crate::garage::Garage;
|
use crate::rc::*;
|
||||||
|
|
||||||
/// Size under which data will be stored inlined in database instead of as files
|
/// Size under which data will be stored inlined in database instead of as files
|
||||||
pub const INLINE_THRESHOLD: usize = 3072;
|
pub const INLINE_THRESHOLD: usize = 3072;
|
||||||
|
|
||||||
pub const BACKGROUND_TRANQUILITY: u32 = 2;
|
|
||||||
|
|
||||||
// Timeout for RPCs that read and write blocks to remote nodes
|
// Timeout for RPCs that read and write blocks to remote nodes
|
||||||
const BLOCK_RW_TIMEOUT: Duration = Duration::from_secs(30);
|
const BLOCK_RW_TIMEOUT: Duration = Duration::from_secs(30);
|
||||||
// Timeout for RPCs that ask other nodes whether they need a copy
|
// Timeout for RPCs that ask other nodes whether they need a copy
|
||||||
|
@ -54,7 +50,7 @@ const RESYNC_RETRY_DELAY: Duration = Duration::from_secs(60);
|
||||||
// The delay between the moment when the reference counter
|
// The delay between the moment when the reference counter
|
||||||
// drops to zero, and the moment where we allow ourselves
|
// drops to zero, and the moment where we allow ourselves
|
||||||
// to delete the block locally.
|
// to delete the block locally.
|
||||||
const BLOCK_GC_DELAY: Duration = Duration::from_secs(600);
|
pub(crate) const BLOCK_GC_DELAY: Duration = Duration::from_secs(600);
|
||||||
|
|
||||||
/// RPC messages used to share blocks of data between nodes
|
/// RPC messages used to share blocks of data between nodes
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
@ -74,73 +70,6 @@ pub enum BlockRpc {
|
||||||
NeedBlockReply(bool),
|
NeedBlockReply(bool),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A possibly compressed block of data
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
|
||||||
pub enum DataBlock {
|
|
||||||
/// Uncompressed data
|
|
||||||
Plain(#[serde(with = "serde_bytes")] Vec<u8>),
|
|
||||||
/// Data compressed with zstd
|
|
||||||
Compressed(#[serde(with = "serde_bytes")] Vec<u8>),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DataBlock {
|
|
||||||
/// Query whether this block is compressed
|
|
||||||
pub fn is_compressed(&self) -> bool {
|
|
||||||
matches!(self, DataBlock::Compressed(_))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the inner, possibly compressed buffer. You should probably use [`DataBlock::verify_get`]
|
|
||||||
/// instead
|
|
||||||
pub fn inner_buffer(&self) -> &[u8] {
|
|
||||||
use DataBlock::*;
|
|
||||||
let (Plain(ref res) | Compressed(ref res)) = self;
|
|
||||||
res
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the buffer, possibly decompressing it, and verify it's integrity.
|
|
||||||
/// For Plain block, data is compared to hash, for Compressed block, zstd checksumming system
|
|
||||||
/// is used instead.
|
|
||||||
pub fn verify_get(self, hash: Hash) -> Result<Vec<u8>, Error> {
|
|
||||||
match self {
|
|
||||||
DataBlock::Plain(data) => {
|
|
||||||
if blake2sum(&data) == hash {
|
|
||||||
Ok(data)
|
|
||||||
} else {
|
|
||||||
Err(Error::CorruptData(hash))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DataBlock::Compressed(data) => {
|
|
||||||
zstd_decode(&data[..]).map_err(|_| Error::CorruptData(hash))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Verify data integrity. Allocate less than [`DataBlock::verify_get`] and don't consume self, but
|
|
||||||
/// does not return the buffer content.
|
|
||||||
pub fn verify(&self, hash: Hash) -> Result<(), Error> {
|
|
||||||
match self {
|
|
||||||
DataBlock::Plain(data) => {
|
|
||||||
if blake2sum(data) == hash {
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(Error::CorruptData(hash))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DataBlock::Compressed(data) => zstd::stream::copy_decode(&data[..], std::io::sink())
|
|
||||||
.map_err(|_| Error::CorruptData(hash)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn from_buffer(data: Vec<u8>, level: Option<i32>) -> DataBlock {
|
|
||||||
if let Some(level) = level {
|
|
||||||
if let Ok(data) = zstd_encode(&data[..], level) {
|
|
||||||
return DataBlock::Compressed(data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DataBlock::Plain(data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Rpc for BlockRpc {
|
impl Rpc for BlockRpc {
|
||||||
type Response = Result<BlockRpc, Error>;
|
type Response = Result<BlockRpc, Error>;
|
||||||
}
|
}
|
||||||
|
@ -152,9 +81,12 @@ pub struct BlockManager {
|
||||||
/// Directory in which block are stored
|
/// Directory in which block are stored
|
||||||
pub data_dir: PathBuf,
|
pub data_dir: PathBuf,
|
||||||
|
|
||||||
|
compression_level: Option<i32>,
|
||||||
|
background_tranquility: u32,
|
||||||
|
|
||||||
mutation_lock: Mutex<BlockManagerLocked>,
|
mutation_lock: Mutex<BlockManagerLocked>,
|
||||||
|
|
||||||
rc: sled::Tree,
|
rc: BlockRc,
|
||||||
|
|
||||||
resync_queue: SledCountedTree,
|
resync_queue: SledCountedTree,
|
||||||
resync_notify: Notify,
|
resync_notify: Notify,
|
||||||
|
@ -162,7 +94,6 @@ pub struct BlockManager {
|
||||||
|
|
||||||
system: Arc<System>,
|
system: Arc<System>,
|
||||||
endpoint: Arc<Endpoint<BlockRpc, Self>>,
|
endpoint: Arc<Endpoint<BlockRpc, Self>>,
|
||||||
pub(crate) garage: ArcSwapOption<Garage>,
|
|
||||||
|
|
||||||
metrics: BlockManagerMetrics,
|
metrics: BlockManagerMetrics,
|
||||||
}
|
}
|
||||||
|
@ -176,12 +107,15 @@ impl BlockManager {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
db: &sled::Db,
|
db: &sled::Db,
|
||||||
data_dir: PathBuf,
|
data_dir: PathBuf,
|
||||||
|
compression_level: Option<i32>,
|
||||||
|
background_tranquility: u32,
|
||||||
replication: TableShardedReplication,
|
replication: TableShardedReplication,
|
||||||
system: Arc<System>,
|
system: Arc<System>,
|
||||||
) -> Arc<Self> {
|
) -> Arc<Self> {
|
||||||
let rc = db
|
let rc = db
|
||||||
.open_tree("block_local_rc")
|
.open_tree("block_local_rc")
|
||||||
.expect("Unable to open block_local_rc tree");
|
.expect("Unable to open block_local_rc tree");
|
||||||
|
let rc = BlockRc::new(rc);
|
||||||
|
|
||||||
let resync_queue = db
|
let resync_queue = db
|
||||||
.open_tree("block_local_resync_queue")
|
.open_tree("block_local_resync_queue")
|
||||||
|
@ -204,6 +138,8 @@ impl BlockManager {
|
||||||
let block_manager = Arc::new(Self {
|
let block_manager = Arc::new(Self {
|
||||||
replication,
|
replication,
|
||||||
data_dir,
|
data_dir,
|
||||||
|
compression_level,
|
||||||
|
background_tranquility,
|
||||||
mutation_lock: Mutex::new(manager_locked),
|
mutation_lock: Mutex::new(manager_locked),
|
||||||
rc,
|
rc,
|
||||||
resync_queue,
|
resync_queue,
|
||||||
|
@ -211,11 +147,12 @@ impl BlockManager {
|
||||||
resync_errors,
|
resync_errors,
|
||||||
system,
|
system,
|
||||||
endpoint,
|
endpoint,
|
||||||
garage: ArcSwapOption::from(None),
|
|
||||||
metrics,
|
metrics,
|
||||||
});
|
});
|
||||||
block_manager.endpoint.set_handler(block_manager.clone());
|
block_manager.endpoint.set_handler(block_manager.clone());
|
||||||
|
|
||||||
|
block_manager.clone().spawn_background_worker();
|
||||||
|
|
||||||
block_manager
|
block_manager
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -257,14 +194,7 @@ impl BlockManager {
|
||||||
/// Send block to nodes that should have it
|
/// Send block to nodes that should have it
|
||||||
pub async fn rpc_put_block(&self, hash: Hash, data: Vec<u8>) -> Result<(), Error> {
|
pub async fn rpc_put_block(&self, hash: Hash, data: Vec<u8>) -> Result<(), Error> {
|
||||||
let who = self.replication.write_nodes(&hash);
|
let who = self.replication.write_nodes(&hash);
|
||||||
let compression_level = self
|
let data = DataBlock::from_buffer(data, self.compression_level);
|
||||||
.garage
|
|
||||||
.load()
|
|
||||||
.as_ref()
|
|
||||||
.unwrap()
|
|
||||||
.config
|
|
||||||
.compression_level;
|
|
||||||
let data = DataBlock::from_buffer(data, compression_level);
|
|
||||||
self.system
|
self.system
|
||||||
.rpc
|
.rpc
|
||||||
.try_call_many(
|
.try_call_many(
|
||||||
|
@ -286,18 +216,10 @@ impl BlockManager {
|
||||||
/// to fix any mismatch between the two.
|
/// to fix any mismatch between the two.
|
||||||
pub async fn repair_data_store(&self, must_exit: &watch::Receiver<bool>) -> Result<(), Error> {
|
pub async fn repair_data_store(&self, must_exit: &watch::Receiver<bool>) -> Result<(), Error> {
|
||||||
// 1. Repair blocks from RC table.
|
// 1. Repair blocks from RC table.
|
||||||
let garage = self.garage.load_full().unwrap();
|
for (i, entry) in self.rc.rc.iter().enumerate() {
|
||||||
let mut last_hash = None;
|
let (hash, _) = entry?;
|
||||||
for (i, entry) in garage.block_ref_table.data.store.iter().enumerate() {
|
let hash = Hash::try_from(&hash[..]).unwrap();
|
||||||
let (_k, v_bytes) = entry?;
|
self.put_to_resync(&hash, Duration::from_secs(0))?;
|
||||||
let block_ref = rmp_serde::decode::from_read_ref::<_, BlockRef>(v_bytes.as_ref())?;
|
|
||||||
if Some(&block_ref.block) == last_hash.as_ref() {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if !block_ref.deleted.get() {
|
|
||||||
last_hash = Some(block_ref.block);
|
|
||||||
self.put_to_resync(&block_ref.block, Duration::from_secs(0))?;
|
|
||||||
}
|
|
||||||
if i & 0xFF == 0 && *must_exit.borrow() {
|
if i & 0xFF == 0 && *must_exit.borrow() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
@ -309,7 +231,10 @@ impl BlockManager {
|
||||||
// so that we can offload them if necessary and then delete them locally.
|
// so that we can offload them if necessary and then delete them locally.
|
||||||
self.for_each_file(
|
self.for_each_file(
|
||||||
(),
|
(),
|
||||||
move |_, hash| async move { self.put_to_resync(&hash, Duration::from_secs(0)) },
|
move |_, hash| async move {
|
||||||
|
self.put_to_resync(&hash, Duration::from_secs(0))
|
||||||
|
.map_err(Into::into)
|
||||||
|
},
|
||||||
must_exit,
|
must_exit,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
|
@ -342,7 +267,7 @@ impl BlockManager {
|
||||||
|
|
||||||
/// Get number of items in the refcount table
|
/// Get number of items in the refcount table
|
||||||
pub fn rc_len(&self) -> usize {
|
pub fn rc_len(&self) -> usize {
|
||||||
self.rc.len()
|
self.rc.rc.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
//// ----- Managing the reference counter ----
|
//// ----- Managing the reference counter ----
|
||||||
|
@ -350,11 +275,7 @@ impl BlockManager {
|
||||||
/// Increment the number of time a block is used, putting it to resynchronization if it is
|
/// Increment the number of time a block is used, putting it to resynchronization if it is
|
||||||
/// required, but not known
|
/// required, but not known
|
||||||
pub fn block_incref(&self, hash: &Hash) -> Result<(), Error> {
|
pub fn block_incref(&self, hash: &Hash) -> Result<(), Error> {
|
||||||
let old_rc = self
|
if self.rc.block_incref(hash)? {
|
||||||
.rc
|
|
||||||
.fetch_and_update(&hash, |old| RcEntry::parse_opt(old).increment().serialize())?;
|
|
||||||
let old_rc = RcEntry::parse_opt(old_rc);
|
|
||||||
if old_rc.is_zero() {
|
|
||||||
// When the reference counter is incremented, there is
|
// When the reference counter is incremented, there is
|
||||||
// normally a node that is responsible for sending us the
|
// normally a node that is responsible for sending us the
|
||||||
// data of the block. However that operation may fail,
|
// data of the block. However that operation may fail,
|
||||||
|
@ -368,35 +289,17 @@ impl BlockManager {
|
||||||
|
|
||||||
/// Decrement the number of time a block is used
|
/// Decrement the number of time a block is used
|
||||||
pub fn block_decref(&self, hash: &Hash) -> Result<(), Error> {
|
pub fn block_decref(&self, hash: &Hash) -> Result<(), Error> {
|
||||||
let new_rc = self
|
if self.rc.block_decref(hash)? {
|
||||||
.rc
|
// When the RC is decremented, it might drop to zero,
|
||||||
.update_and_fetch(&hash, |old| RcEntry::parse_opt(old).decrement().serialize())?;
|
// indicating that we don't need the block.
|
||||||
let new_rc = RcEntry::parse_opt(new_rc);
|
// There is a delay before we garbage collect it;
|
||||||
if let RcEntry::Deletable { .. } = new_rc {
|
// make sure that it is handled in the resync loop
|
||||||
|
// after that delay has passed.
|
||||||
self.put_to_resync(hash, BLOCK_GC_DELAY + Duration::from_secs(10))?;
|
self.put_to_resync(hash, BLOCK_GC_DELAY + Duration::from_secs(10))?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read a block's reference count
|
|
||||||
fn get_block_rc(&self, hash: &Hash) -> Result<RcEntry, Error> {
|
|
||||||
Ok(RcEntry::parse_opt(self.rc.get(hash.as_ref())?))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Delete an entry in the RC table if it is deletable and the
|
|
||||||
/// deletion time has passed
|
|
||||||
fn clear_deleted_block_rc(&self, hash: &Hash) -> Result<(), Error> {
|
|
||||||
let now = now_msec();
|
|
||||||
self.rc.update_and_fetch(&hash, |rcval| {
|
|
||||||
let updated = match RcEntry::parse_opt(rcval) {
|
|
||||||
RcEntry::Deletable { at_time } if now > at_time => RcEntry::Absent,
|
|
||||||
v => v,
|
|
||||||
};
|
|
||||||
updated.serialize()
|
|
||||||
})?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---- Reading and writing blocks locally ----
|
// ---- Reading and writing blocks locally ----
|
||||||
|
|
||||||
/// Write a block to disk
|
/// Write a block to disk
|
||||||
|
@ -510,7 +413,78 @@ impl BlockManager {
|
||||||
|
|
||||||
// ---- Resync loop ----
|
// ---- Resync loop ----
|
||||||
|
|
||||||
pub fn spawn_background_worker(self: Arc<Self>) {
|
// This part manages a queue of blocks that need to be
|
||||||
|
// "resynchronized", i.e. that need to have a check that
|
||||||
|
// they are at present if we need them, or that they are
|
||||||
|
// deleted once the garbage collection delay has passed.
|
||||||
|
//
|
||||||
|
// Here are some explanations on how the resync queue works.
|
||||||
|
// There are two Sled trees that are used to have information
|
||||||
|
// about the status of blocks that need to be resynchronized:
|
||||||
|
//
|
||||||
|
// - resync_queue: a tree that is ordered first by a timestamp
|
||||||
|
// (in milliseconds since Unix epoch) that is the time at which
|
||||||
|
// the resync must be done, and second by block hash.
|
||||||
|
// The key in this tree is just:
|
||||||
|
// concat(timestamp (8 bytes), hash (32 bytes))
|
||||||
|
// The value is the same 32-byte hash.
|
||||||
|
//
|
||||||
|
// - resync_errors: a tree that indicates for each block
|
||||||
|
// if the last resync resulted in an error, and if so,
|
||||||
|
// the following two informations (see the ErrorCounter struct):
|
||||||
|
// - how many consecutive resync errors for this block?
|
||||||
|
// - when was the last try?
|
||||||
|
// These two informations are used to implement an
|
||||||
|
// exponential backoff retry strategy.
|
||||||
|
// The key in this tree is the 32-byte hash of the block,
|
||||||
|
// and the value is the encoded ErrorCounter value.
|
||||||
|
//
|
||||||
|
// We need to have these two trees, because the resync queue
|
||||||
|
// is not just a queue of items to process, but a set of items
|
||||||
|
// that are waiting a specific delay until we can process them
|
||||||
|
// (the delay being necessary both internally for the exponential
|
||||||
|
// backoff strategy, and exposed as a parameter when adding items
|
||||||
|
// to the queue, e.g. to wait until the GC delay has passed).
|
||||||
|
// This is why we need one tree ordered by time, and one
|
||||||
|
// ordered by identifier of item to be processed (block hash).
|
||||||
|
//
|
||||||
|
// When the worker wants to process an item it takes from
|
||||||
|
// resync_queue, it checks in resync_errors that if there is an
|
||||||
|
// exponential back-off delay to await, it has passed before we
|
||||||
|
// process the item. If not, the item in the queue is skipped
|
||||||
|
// (but added back for later processing after the time of the
|
||||||
|
// delay).
|
||||||
|
//
|
||||||
|
// An alternative that would have seemed natural is to
|
||||||
|
// only add items to resync_queue with a processing time that is
|
||||||
|
// after the delay, but there are several issues with this:
|
||||||
|
// - This requires to synchronize updates to resync_queue and
|
||||||
|
// resync_errors (with the current model, there is only one thread,
|
||||||
|
// the worker thread, that accesses resync_errors,
|
||||||
|
// so no need to synchronize) by putting them both in a lock.
|
||||||
|
// This would mean that block_incref might need to take a lock
|
||||||
|
// before doing its thing, meaning it has much more chances of
|
||||||
|
// not completing successfully if something bad happens to Garage.
|
||||||
|
// Currently Garage is not able to recover from block_incref that
|
||||||
|
// doesn't complete successfully, because it is necessary to ensure
|
||||||
|
// the consistency between the state of the block manager and
|
||||||
|
// information in the BlockRef table.
|
||||||
|
// - If a resync fails, we put that block in the resync_errors table,
|
||||||
|
// and also add it back to resync_queue to be processed after
|
||||||
|
// the exponential back-off delay,
|
||||||
|
// but maybe the block is already scheduled to be resynced again
|
||||||
|
// at another time that is before the exponential back-off delay,
|
||||||
|
// and we have no way to check that easily. This means that
|
||||||
|
// in all cases, we need to check the resync_errors table
|
||||||
|
// in the resync loop at the time when a block is popped from
|
||||||
|
// the resync_queue.
|
||||||
|
// Overall, the current design is therefore simpler and more robust
|
||||||
|
// because it tolerates inconsistencies between the resync_queue
|
||||||
|
// and resync_errors table (items being scheduled in resync_queue
|
||||||
|
// for times that are earlier than the exponential back-off delay
|
||||||
|
// is a natural condition that is handled properly).
|
||||||
|
|
||||||
|
fn spawn_background_worker(self: Arc<Self>) {
|
||||||
// Launch a background workers for background resync loop processing
|
// Launch a background workers for background resync loop processing
|
||||||
let background = self.system.background.clone();
|
let background = self.system.background.clone();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
|
@ -521,12 +495,12 @@ impl BlockManager {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn put_to_resync(&self, hash: &Hash, delay: Duration) -> Result<(), Error> {
|
fn put_to_resync(&self, hash: &Hash, delay: Duration) -> Result<(), sled::Error> {
|
||||||
let when = now_msec() + delay.as_millis() as u64;
|
let when = now_msec() + delay.as_millis() as u64;
|
||||||
self.put_to_resync_at(hash, when)
|
self.put_to_resync_at(hash, when)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn put_to_resync_at(&self, hash: &Hash, when: u64) -> Result<(), Error> {
|
fn put_to_resync_at(&self, hash: &Hash, when: u64) -> Result<(), sled::Error> {
|
||||||
trace!("Put resync_queue: {} {:?}", when, hash);
|
trace!("Put resync_queue: {} {:?}", when, hash);
|
||||||
let mut key = u64::to_be_bytes(when).to_vec();
|
let mut key = u64::to_be_bytes(when).to_vec();
|
||||||
key.extend(hash.as_ref());
|
key.extend(hash.as_ref());
|
||||||
|
@ -541,7 +515,7 @@ impl BlockManager {
|
||||||
while !*must_exit.borrow() {
|
while !*must_exit.borrow() {
|
||||||
match self.resync_iter(&mut must_exit).await {
|
match self.resync_iter(&mut must_exit).await {
|
||||||
Ok(true) => {
|
Ok(true) => {
|
||||||
tranquilizer.tranquilize(BACKGROUND_TRANQUILITY).await;
|
tranquilizer.tranquilize(self.background_tranquility).await;
|
||||||
}
|
}
|
||||||
Ok(false) => {
|
Ok(false) => {
|
||||||
tranquilizer.reset();
|
tranquilizer.reset();
|
||||||
|
@ -561,7 +535,14 @@ impl BlockManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn resync_iter(&self, must_exit: &mut watch::Receiver<bool>) -> Result<bool, Error> {
|
// The result of resync_iter is:
|
||||||
|
// - Ok(true) -> a block was processed (successfully or not)
|
||||||
|
// - Ok(false) -> no block was processed, but we are ready for the next iteration
|
||||||
|
// - Err(_) -> a Sled error occurred when reading/writing from resync_queue/resync_errors
|
||||||
|
async fn resync_iter(
|
||||||
|
&self,
|
||||||
|
must_exit: &mut watch::Receiver<bool>,
|
||||||
|
) -> Result<bool, sled::Error> {
|
||||||
if let Some(first_pair_res) = self.resync_queue.iter().next() {
|
if let Some(first_pair_res) = self.resync_queue.iter().next() {
|
||||||
let (time_bytes, hash_bytes) = first_pair_res?;
|
let (time_bytes, hash_bytes) = first_pair_res?;
|
||||||
|
|
||||||
|
@ -580,6 +561,8 @@ impl BlockManager {
|
||||||
self.put_to_resync_at(&hash, ec.next_try())?;
|
self.put_to_resync_at(&hash, ec.next_try())?;
|
||||||
// ec.next_try() > now >= time_msec, so this remove
|
// ec.next_try() > now >= time_msec, so this remove
|
||||||
// is not removing the one we added just above
|
// is not removing the one we added just above
|
||||||
|
// (we want to do the remove after the insert to ensure
|
||||||
|
// that the item is not lost if we crash in-between)
|
||||||
self.resync_queue.remove(time_bytes)?;
|
self.resync_queue.remove(time_bytes)?;
|
||||||
return Ok(false);
|
return Ok(false);
|
||||||
}
|
}
|
||||||
|
@ -639,7 +622,15 @@ impl BlockManager {
|
||||||
Ok(false)
|
Ok(false)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// Here we wait either for a notification that an item has been
|
||||||
|
// added to the queue, or for a constant delay of 10 secs to expire.
|
||||||
|
// The delay avoids a race condition where the notification happens
|
||||||
|
// between the time we checked the queue and the first poll
|
||||||
|
// to resync_notify.notified(): if that happens, we'll just loop
|
||||||
|
// back 10 seconds later, which is fine.
|
||||||
|
let delay = tokio::time::sleep(Duration::from_secs(10));
|
||||||
select! {
|
select! {
|
||||||
|
_ = delay.fuse() => {},
|
||||||
_ = self.resync_notify.notified().fuse() => {},
|
_ = self.resync_notify.notified().fuse() => {},
|
||||||
_ = must_exit.changed().fuse() => {},
|
_ = must_exit.changed().fuse() => {},
|
||||||
}
|
}
|
||||||
|
@ -740,7 +731,7 @@ impl BlockManager {
|
||||||
.delete_if_unneeded(hash, self)
|
.delete_if_unneeded(hash, self)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
self.clear_deleted_block_rc(hash)?;
|
self.rc.clear_deleted_block_rc(hash)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if needed.is_nonzero() && !exists {
|
if needed.is_nonzero() && !exists {
|
||||||
|
@ -854,7 +845,7 @@ impl BlockManagerLocked {
|
||||||
mgr: &BlockManager,
|
mgr: &BlockManager,
|
||||||
) -> Result<BlockStatus, Error> {
|
) -> Result<BlockStatus, Error> {
|
||||||
let exists = mgr.is_block_compressed(hash).await.is_ok();
|
let exists = mgr.is_block_compressed(hash).await.is_ok();
|
||||||
let needed = mgr.get_block_rc(hash)?;
|
let needed = mgr.rc.get_block_rc(hash)?;
|
||||||
|
|
||||||
Ok(BlockStatus { exists, needed })
|
Ok(BlockStatus { exists, needed })
|
||||||
}
|
}
|
||||||
|
@ -950,107 +941,6 @@ impl BlockManagerLocked {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Describes the state of the reference counter for a block
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
|
||||||
enum RcEntry {
|
|
||||||
/// Present: the block has `count` references, with `count` > 0.
|
|
||||||
///
|
|
||||||
/// This is stored as u64::to_be_bytes(count)
|
|
||||||
Present { count: u64 },
|
|
||||||
|
|
||||||
/// Deletable: the block has zero references, and can be deleted
|
|
||||||
/// once time (returned by now_msec) is larger than at_time
|
|
||||||
/// (in millis since Unix epoch)
|
|
||||||
///
|
|
||||||
/// This is stored as [0u8; 8] followed by u64::to_be_bytes(at_time),
|
|
||||||
/// (this allows for the data format to be backwards compatible with
|
|
||||||
/// previous Garage versions that didn't have this intermediate state)
|
|
||||||
Deletable { at_time: u64 },
|
|
||||||
|
|
||||||
/// Absent: the block has zero references, and can be deleted
|
|
||||||
/// immediately
|
|
||||||
Absent,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RcEntry {
|
|
||||||
fn parse(bytes: &[u8]) -> Self {
|
|
||||||
if bytes.len() == 8 {
|
|
||||||
RcEntry::Present {
|
|
||||||
count: u64::from_be_bytes(bytes.try_into().unwrap()),
|
|
||||||
}
|
|
||||||
} else if bytes.len() == 16 {
|
|
||||||
RcEntry::Deletable {
|
|
||||||
at_time: u64::from_be_bytes(bytes[8..16].try_into().unwrap()),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
panic!("Invalid RC entry: {:?}, database is corrupted. This is an error Garage is currently unable to recover from. Sorry, and also please report a bug.",
|
|
||||||
bytes
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_opt<V: AsRef<[u8]>>(bytes: Option<V>) -> Self {
|
|
||||||
bytes
|
|
||||||
.map(|b| Self::parse(b.as_ref()))
|
|
||||||
.unwrap_or(Self::Absent)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize(self) -> Option<Vec<u8>> {
|
|
||||||
match self {
|
|
||||||
RcEntry::Present { count } => Some(u64::to_be_bytes(count).to_vec()),
|
|
||||||
RcEntry::Deletable { at_time } => {
|
|
||||||
Some([u64::to_be_bytes(0), u64::to_be_bytes(at_time)].concat())
|
|
||||||
}
|
|
||||||
RcEntry::Absent => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn increment(self) -> Self {
|
|
||||||
let old_count = match self {
|
|
||||||
RcEntry::Present { count } => count,
|
|
||||||
_ => 0,
|
|
||||||
};
|
|
||||||
RcEntry::Present {
|
|
||||||
count: old_count + 1,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn decrement(self) -> Self {
|
|
||||||
match self {
|
|
||||||
RcEntry::Present { count } => {
|
|
||||||
if count > 1 {
|
|
||||||
RcEntry::Present { count: count - 1 }
|
|
||||||
} else {
|
|
||||||
RcEntry::Deletable {
|
|
||||||
at_time: now_msec() + BLOCK_GC_DELAY.as_millis() as u64,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
del => del,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_zero(&self) -> bool {
|
|
||||||
matches!(self, RcEntry::Deletable { .. } | RcEntry::Absent)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_nonzero(&self) -> bool {
|
|
||||||
!self.is_zero()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_deletable(&self) -> bool {
|
|
||||||
match self {
|
|
||||||
RcEntry::Present { .. } => false,
|
|
||||||
RcEntry::Deletable { at_time } => now_msec() > *at_time,
|
|
||||||
RcEntry::Absent => true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_needed(&self) -> bool {
|
|
||||||
!self.is_deletable()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Counts the number of errors when resyncing a block,
|
/// Counts the number of errors when resyncing a block,
|
||||||
/// and the time of the last try.
|
/// and the time of the last try.
|
||||||
/// Used to implement exponential backoff.
|
/// Used to implement exponential backoff.
|
||||||
|
@ -1096,12 +986,3 @@ impl ErrorCounter {
|
||||||
self.last_try + self.delay_msec()
|
self.last_try + self.delay_msec()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn zstd_encode<R: std::io::Read>(mut source: R, level: i32) -> std::io::Result<Vec<u8>> {
|
|
||||||
let mut result = Vec::<u8>::new();
|
|
||||||
let mut encoder = Encoder::new(&mut result, level)?;
|
|
||||||
encoder.include_checksum(true)?;
|
|
||||||
std::io::copy(&mut source, &mut encoder)?;
|
|
||||||
encoder.finish()?;
|
|
||||||
Ok(result)
|
|
||||||
}
|
|
157
src/block/rc.rs
Normal file
157
src/block/rc.rs
Normal file
|
@ -0,0 +1,157 @@
|
||||||
|
use std::convert::TryInto;
|
||||||
|
|
||||||
|
use garage_util::data::*;
|
||||||
|
use garage_util::error::*;
|
||||||
|
use garage_util::time::*;
|
||||||
|
|
||||||
|
use crate::manager::BLOCK_GC_DELAY;
|
||||||
|
|
||||||
|
pub struct BlockRc {
|
||||||
|
pub(crate) rc: sled::Tree,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BlockRc {
|
||||||
|
pub(crate) fn new(rc: sled::Tree) -> Self {
|
||||||
|
Self { rc }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Increment the reference counter associated to a hash.
|
||||||
|
/// Returns true if the RC goes from zero to nonzero.
|
||||||
|
pub(crate) fn block_incref(&self, hash: &Hash) -> Result<bool, Error> {
|
||||||
|
let old_rc = self
|
||||||
|
.rc
|
||||||
|
.fetch_and_update(&hash, |old| RcEntry::parse_opt(old).increment().serialize())?;
|
||||||
|
let old_rc = RcEntry::parse_opt(old_rc);
|
||||||
|
Ok(old_rc.is_zero())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Decrement the reference counter associated to a hash.
|
||||||
|
/// Returns true if the RC is now zero.
|
||||||
|
pub(crate) fn block_decref(&self, hash: &Hash) -> Result<bool, Error> {
|
||||||
|
let new_rc = self
|
||||||
|
.rc
|
||||||
|
.update_and_fetch(&hash, |old| RcEntry::parse_opt(old).decrement().serialize())?;
|
||||||
|
let new_rc = RcEntry::parse_opt(new_rc);
|
||||||
|
Ok(matches!(new_rc, RcEntry::Deletable { .. }))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read a block's reference count
|
||||||
|
pub(crate) fn get_block_rc(&self, hash: &Hash) -> Result<RcEntry, Error> {
|
||||||
|
Ok(RcEntry::parse_opt(self.rc.get(hash.as_ref())?))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Delete an entry in the RC table if it is deletable and the
|
||||||
|
/// deletion time has passed
|
||||||
|
pub(crate) fn clear_deleted_block_rc(&self, hash: &Hash) -> Result<(), Error> {
|
||||||
|
let now = now_msec();
|
||||||
|
self.rc.update_and_fetch(&hash, |rcval| {
|
||||||
|
let updated = match RcEntry::parse_opt(rcval) {
|
||||||
|
RcEntry::Deletable { at_time } if now > at_time => RcEntry::Absent,
|
||||||
|
v => v,
|
||||||
|
};
|
||||||
|
updated.serialize()
|
||||||
|
})?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Describes the state of the reference counter for a block
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub(crate) enum RcEntry {
|
||||||
|
/// Present: the block has `count` references, with `count` > 0.
|
||||||
|
///
|
||||||
|
/// This is stored as u64::to_be_bytes(count)
|
||||||
|
Present { count: u64 },
|
||||||
|
|
||||||
|
/// Deletable: the block has zero references, and can be deleted
|
||||||
|
/// once time (returned by now_msec) is larger than at_time
|
||||||
|
/// (in millis since Unix epoch)
|
||||||
|
///
|
||||||
|
/// This is stored as [0u8; 8] followed by u64::to_be_bytes(at_time),
|
||||||
|
/// (this allows for the data format to be backwards compatible with
|
||||||
|
/// previous Garage versions that didn't have this intermediate state)
|
||||||
|
Deletable { at_time: u64 },
|
||||||
|
|
||||||
|
/// Absent: the block has zero references, and can be deleted
|
||||||
|
/// immediately
|
||||||
|
Absent,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RcEntry {
|
||||||
|
fn parse(bytes: &[u8]) -> Self {
|
||||||
|
if bytes.len() == 8 {
|
||||||
|
RcEntry::Present {
|
||||||
|
count: u64::from_be_bytes(bytes.try_into().unwrap()),
|
||||||
|
}
|
||||||
|
} else if bytes.len() == 16 {
|
||||||
|
RcEntry::Deletable {
|
||||||
|
at_time: u64::from_be_bytes(bytes[8..16].try_into().unwrap()),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
panic!("Invalid RC entry: {:?}, database is corrupted. This is an error Garage is currently unable to recover from. Sorry, and also please report a bug.",
|
||||||
|
bytes
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_opt<V: AsRef<[u8]>>(bytes: Option<V>) -> Self {
|
||||||
|
bytes
|
||||||
|
.map(|b| Self::parse(b.as_ref()))
|
||||||
|
.unwrap_or(Self::Absent)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize(self) -> Option<Vec<u8>> {
|
||||||
|
match self {
|
||||||
|
RcEntry::Present { count } => Some(u64::to_be_bytes(count).to_vec()),
|
||||||
|
RcEntry::Deletable { at_time } => {
|
||||||
|
Some([u64::to_be_bytes(0), u64::to_be_bytes(at_time)].concat())
|
||||||
|
}
|
||||||
|
RcEntry::Absent => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn increment(self) -> Self {
|
||||||
|
let old_count = match self {
|
||||||
|
RcEntry::Present { count } => count,
|
||||||
|
_ => 0,
|
||||||
|
};
|
||||||
|
RcEntry::Present {
|
||||||
|
count: old_count + 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decrement(self) -> Self {
|
||||||
|
match self {
|
||||||
|
RcEntry::Present { count } => {
|
||||||
|
if count > 1 {
|
||||||
|
RcEntry::Present { count: count - 1 }
|
||||||
|
} else {
|
||||||
|
RcEntry::Deletable {
|
||||||
|
at_time: now_msec() + BLOCK_GC_DELAY.as_millis() as u64,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
del => del,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn is_zero(&self) -> bool {
|
||||||
|
matches!(self, RcEntry::Deletable { .. } | RcEntry::Absent)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn is_nonzero(&self) -> bool {
|
||||||
|
!self.is_zero()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn is_deletable(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
RcEntry::Present { .. } => false,
|
||||||
|
RcEntry::Deletable { at_time } => now_msec() > *at_time,
|
||||||
|
RcEntry::Absent => true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn is_needed(&self) -> bool {
|
||||||
|
!self.is_deletable()
|
||||||
|
}
|
||||||
|
}
|
|
@ -98,8 +98,7 @@ pub async fn run_server(config_file: PathBuf) -> Result<(), Error> {
|
||||||
// Await for netapp RPC system to end
|
// Await for netapp RPC system to end
|
||||||
run_system.await?;
|
run_system.await?;
|
||||||
|
|
||||||
// Break last reference cycles so that stuff can terminate properly
|
// Drop all references so that stuff can terminate properly
|
||||||
garage.break_reference_cycles();
|
|
||||||
drop(garage);
|
drop(garage);
|
||||||
|
|
||||||
// Await for all background tasks to end
|
// Await for all background tasks to end
|
||||||
|
|
|
@ -16,6 +16,7 @@ path = "lib.rs"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
garage_rpc = { version = "0.7.0", path = "../rpc" }
|
garage_rpc = { version = "0.7.0", path = "../rpc" }
|
||||||
garage_table = { version = "0.7.0", path = "../table" }
|
garage_table = { version = "0.7.0", path = "../table" }
|
||||||
|
garage_block = { version = "0.7.0", path = "../block" }
|
||||||
garage_util = { version = "0.7.0", path = "../util" }
|
garage_util = { version = "0.7.0", path = "../util" }
|
||||||
garage_model_050 = { package = "garage_model", version = "0.5.1" }
|
garage_model_050 = { package = "garage_model", version = "0.5.1" }
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ use garage_util::data::*;
|
||||||
use garage_table::crdt::Crdt;
|
use garage_table::crdt::Crdt;
|
||||||
use garage_table::*;
|
use garage_table::*;
|
||||||
|
|
||||||
use crate::block::*;
|
use garage_block::manager::*;
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Debug, Serialize, Deserialize)]
|
#[derive(PartialEq, Clone, Debug, Serialize, Deserialize)]
|
||||||
pub struct BlockRef {
|
pub struct BlockRef {
|
||||||
|
@ -52,7 +52,8 @@ impl TableSchema for BlockRefTable {
|
||||||
type Filter = DeletedFilter;
|
type Filter = DeletedFilter;
|
||||||
|
|
||||||
fn updated(&self, old: Option<Self::E>, new: Option<Self::E>) {
|
fn updated(&self, old: Option<Self::E>, new: Option<Self::E>) {
|
||||||
let block = &old.as_ref().or_else(|| new.as_ref()).unwrap().block;
|
#[allow(clippy::or_fun_call)]
|
||||||
|
let block = &old.as_ref().or(new.as_ref()).unwrap().block;
|
||||||
let was_before = old.as_ref().map(|x| !x.deleted.get()).unwrap_or(false);
|
let was_before = old.as_ref().map(|x| !x.deleted.get()).unwrap_or(false);
|
||||||
let is_after = new.as_ref().map(|x| !x.deleted.get()).unwrap_or(false);
|
let is_after = new.as_ref().map(|x| !x.deleted.get()).unwrap_or(false);
|
||||||
if is_after && !was_before {
|
if is_after && !was_before {
|
||||||
|
|
|
@ -7,12 +7,12 @@ use garage_util::config::*;
|
||||||
|
|
||||||
use garage_rpc::system::System;
|
use garage_rpc::system::System;
|
||||||
|
|
||||||
|
use garage_block::manager::*;
|
||||||
use garage_table::replication::ReplicationMode;
|
use garage_table::replication::ReplicationMode;
|
||||||
use garage_table::replication::TableFullReplication;
|
use garage_table::replication::TableFullReplication;
|
||||||
use garage_table::replication::TableShardedReplication;
|
use garage_table::replication::TableShardedReplication;
|
||||||
use garage_table::*;
|
use garage_table::*;
|
||||||
|
|
||||||
use crate::block::*;
|
|
||||||
use crate::block_ref_table::*;
|
use crate::block_ref_table::*;
|
||||||
use crate::bucket_alias_table::*;
|
use crate::bucket_alias_table::*;
|
||||||
use crate::bucket_table::*;
|
use crate::bucket_table::*;
|
||||||
|
@ -86,8 +86,14 @@ impl Garage {
|
||||||
};
|
};
|
||||||
|
|
||||||
info!("Initialize block manager...");
|
info!("Initialize block manager...");
|
||||||
let block_manager =
|
let block_manager = BlockManager::new(
|
||||||
BlockManager::new(&db, config.data_dir.clone(), data_rep_param, system.clone());
|
&db,
|
||||||
|
config.data_dir.clone(),
|
||||||
|
config.compression_level,
|
||||||
|
config.block_manager_background_tranquility,
|
||||||
|
data_rep_param,
|
||||||
|
system.clone(),
|
||||||
|
);
|
||||||
|
|
||||||
info!("Initialize block_ref_table...");
|
info!("Initialize block_ref_table...");
|
||||||
let block_ref_table = Table::new(
|
let block_ref_table = Table::new(
|
||||||
|
@ -136,7 +142,8 @@ impl Garage {
|
||||||
let key_table = Table::new(KeyTable, control_rep_param, system.clone(), &db);
|
let key_table = Table::new(KeyTable, control_rep_param, system.clone(), &db);
|
||||||
|
|
||||||
info!("Initialize Garage...");
|
info!("Initialize Garage...");
|
||||||
let garage = Arc::new(Self {
|
|
||||||
|
Arc::new(Self {
|
||||||
config,
|
config,
|
||||||
db,
|
db,
|
||||||
background,
|
background,
|
||||||
|
@ -148,18 +155,7 @@ impl Garage {
|
||||||
object_table,
|
object_table,
|
||||||
version_table,
|
version_table,
|
||||||
block_ref_table,
|
block_ref_table,
|
||||||
});
|
})
|
||||||
|
|
||||||
info!("Start block manager background thread...");
|
|
||||||
garage.block_manager.garage.swap(Some(garage.clone()));
|
|
||||||
garage.block_manager.clone().spawn_background_worker();
|
|
||||||
|
|
||||||
garage
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Use this for shutdown
|
|
||||||
pub fn break_reference_cycles(&self) {
|
|
||||||
self.block_manager.garage.swap(None);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bucket_helper(&self) -> helper::bucket::BucketHelper {
|
pub fn bucket_helper(&self) -> helper::bucket::BucketHelper {
|
||||||
|
|
|
@ -10,9 +10,6 @@ pub mod key_table;
|
||||||
pub mod object_table;
|
pub mod object_table;
|
||||||
pub mod version_table;
|
pub mod version_table;
|
||||||
|
|
||||||
pub mod block;
|
|
||||||
mod block_metrics;
|
|
||||||
|
|
||||||
pub mod garage;
|
pub mod garage;
|
||||||
pub mod helper;
|
pub mod helper;
|
||||||
pub mod migrate;
|
pub mod migrate;
|
||||||
|
|
|
@ -23,6 +23,10 @@ pub struct Config {
|
||||||
#[serde(default = "default_block_size")]
|
#[serde(default = "default_block_size")]
|
||||||
pub block_size: usize,
|
pub block_size: usize,
|
||||||
|
|
||||||
|
/// Size of data blocks to save to disk
|
||||||
|
#[serde(default = "default_block_manager_background_tranquility")]
|
||||||
|
pub block_manager_background_tranquility: u32,
|
||||||
|
|
||||||
/// Replication mode. Supported values:
|
/// Replication mode. Supported values:
|
||||||
/// - none, 1 -> no replication
|
/// - none, 1 -> no replication
|
||||||
/// - 2 -> 2-way replication
|
/// - 2 -> 2-way replication
|
||||||
|
@ -118,6 +122,9 @@ fn default_sled_flush_every_ms() -> u64 {
|
||||||
fn default_block_size() -> usize {
|
fn default_block_size() -> usize {
|
||||||
1048576
|
1048576
|
||||||
}
|
}
|
||||||
|
fn default_block_manager_background_tranquility() -> u32 {
|
||||||
|
2
|
||||||
|
}
|
||||||
|
|
||||||
/// Read and parse configuration
|
/// Read and parse configuration
|
||||||
pub fn read_config(config_file: PathBuf) -> Result<Config, Error> {
|
pub fn read_config(config_file: PathBuf) -> Result<Config, Error> {
|
||||||
|
|
Loading…
Reference in a new issue