mirror of
https://github.com/rustfs/rustfs.git
synced 2026-09-06 12:09:12 +00:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c130d00d4b | |||
| e49d9cdea2 | |||
| f5778d8b97 | |||
| 9da42a899a | |||
| 3d46ed312a | |||
| 3496277e7c |
Generated
+34
-34
@@ -2527,18 +2527,18 @@ checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-channel"
|
name = "crossbeam-channel"
|
||||||
version = "0.5.16"
|
version = "0.5.17"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d85363c37faeca707aef026efa9f3b34d077bce547e48f770770625c6013679e"
|
checksum = "98b0cc327b5bc766e7fda9c9260cc0fa81b43a8e240440422dff70788e3f9ef1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-deque"
|
name = "crossbeam-deque"
|
||||||
version = "0.8.7"
|
version = "0.8.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5181e0de7b61eb03a81e347d6dd8797bae9da5146707b51077e2d71a54ec0ceb"
|
checksum = "622f3fc73690be383c7214310406f28a90e6edeadc3cea882f9d71e495b9711a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crossbeam-epoch",
|
"crossbeam-epoch",
|
||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
@@ -2546,27 +2546,27 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-epoch"
|
name = "crossbeam-epoch"
|
||||||
version = "0.9.20"
|
version = "0.9.21"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f"
|
checksum = "dc74980687109a3b14c72fd458107bf0baa1da1a1a805e178d15501ba9b86d9d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-queue"
|
name = "crossbeam-queue"
|
||||||
version = "0.3.13"
|
version = "0.3.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "803d13fb3b09d88be9f4dbc29062c66b19bf7170867ceb746d2a8689bf6c7a26"
|
checksum = "03e8bd762f7479489c70ed6c768ddca99d7296857de437a68dcb2a94365b3fae"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-utils"
|
name = "crossbeam-utils"
|
||||||
version = "0.8.22"
|
version = "0.8.23"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17"
|
checksum = "a31eee39dddec8330830986fcd7625edb5a24ec90ea038215273bbc3adb08ac6"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crunchy"
|
name = "crunchy"
|
||||||
@@ -3673,9 +3673,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "der"
|
name = "der"
|
||||||
version = "0.8.1"
|
version = "0.8.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a69dedd701da44b0536442edf09c81a64b0ab97a7a4a5e3d1971f00027cbc63d"
|
checksum = "a878c850e9e421b20262e9b41f9c860e4785fa07541c266b62ff9d1ef998a80a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"const-oid 0.10.2",
|
"const-oid 0.10.2",
|
||||||
"pem-rfc7468 1.0.0",
|
"pem-rfc7468 1.0.0",
|
||||||
@@ -3946,7 +3946,7 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
"option-ext",
|
"option-ext",
|
||||||
"redox_users 0.5.2",
|
"redox_users 0.5.2",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -4090,7 +4090,7 @@ version = "0.17.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c0681a4fc24c767085329728d8dfba959af91228aa4610cca4f8ce317ba46ae0"
|
checksum = "c0681a4fc24c767085329728d8dfba959af91228aa4610cca4f8ce317ba46ae0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"der 0.8.1",
|
"der 0.8.2",
|
||||||
"digest 0.11.3",
|
"digest 0.11.3",
|
||||||
"elliptic-curve 0.14.1",
|
"elliptic-curve 0.14.1",
|
||||||
"rfc6979 0.6.0",
|
"rfc6979 0.6.0",
|
||||||
@@ -4295,7 +4295,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -5693,7 +5693,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "20fd6de4ccfcc187e38bc21cfa543cb5a302cb86a8b114eb7f0bf0dc9f8ac00f"
|
checksum = "20fd6de4ccfcc187e38bc21cfa543cb5a302cb86a8b114eb7f0bf0dc9f8ac00f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"io-lifetimes 3.0.1",
|
"io-lifetimes 3.0.1",
|
||||||
"windows-sys 0.60.2",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -5734,9 +5734,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ipnet"
|
name = "ipnet"
|
||||||
version = "2.12.1"
|
version = "2.12.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6a756c3fac73139e83f14c2d742155dd2b78d3ee56597b419a0579b7bdd6dd78"
|
checksum = "791930b43c0d5973160d90a8f3894509f2b273430f5c5c73b668636d0287c5c0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
@@ -5758,7 +5758,7 @@ checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"hermit-abi",
|
"hermit-abi",
|
||||||
"libc",
|
"libc",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -6955,7 +6955,7 @@ version = "0.50.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"
|
checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -7933,7 +7933,7 @@ version = "0.8.0-rc.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "986d2e952779af96ea048f160fd9194e1751b4faea78bcf3ceb456efe008088e"
|
checksum = "986d2e952779af96ea048f160fd9194e1751b4faea78bcf3ceb456efe008088e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"der 0.8.1",
|
"der 0.8.2",
|
||||||
"spki 0.8.0",
|
"spki 0.8.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -7976,7 +7976,7 @@ dependencies = [
|
|||||||
"aes 0.9.3",
|
"aes 0.9.3",
|
||||||
"aes-gcm",
|
"aes-gcm",
|
||||||
"cbc 0.2.1",
|
"cbc 0.2.1",
|
||||||
"der 0.8.1",
|
"der 0.8.2",
|
||||||
"pbkdf2 0.13.0",
|
"pbkdf2 0.13.0",
|
||||||
"rand_core 0.10.1",
|
"rand_core 0.10.1",
|
||||||
"scrypt 0.12.0",
|
"scrypt 0.12.0",
|
||||||
@@ -8000,7 +8000,7 @@ version = "0.11.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "451913da69c775a56034ea8d9003d27ee8948e12443eae7c038ba100a4f21cb7"
|
checksum = "451913da69c775a56034ea8d9003d27ee8948e12443eae7c038ba100a4f21cb7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"der 0.8.1",
|
"der 0.8.2",
|
||||||
"pkcs5 0.8.1",
|
"pkcs5 0.8.1",
|
||||||
"rand_core 0.10.1",
|
"rand_core 0.10.1",
|
||||||
"spki 0.8.0",
|
"spki 0.8.0",
|
||||||
@@ -8706,7 +8706,7 @@ dependencies = [
|
|||||||
"once_cell",
|
"once_cell",
|
||||||
"socket2",
|
"socket2",
|
||||||
"tracing",
|
"tracing",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -8942,9 +8942,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redis"
|
name = "redis"
|
||||||
version = "1.6.0"
|
version = "1.7.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e37a4ca5c6ca42aa3e6df2fd32b987a65d32a4c2159a6f3fe0fd1df306a2658f"
|
checksum = "2acbc41a996f7652b2ddd9dfd98cc4ff602cfd742ae35382f07f608405ab50ed"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arc-swap",
|
"arc-swap",
|
||||||
"arcstr",
|
"arcstr",
|
||||||
@@ -9326,7 +9326,7 @@ dependencies = [
|
|||||||
"curve25519-dalek 5.0.0",
|
"curve25519-dalek 5.0.0",
|
||||||
"data-encoding",
|
"data-encoding",
|
||||||
"delegate",
|
"delegate",
|
||||||
"der 0.8.1",
|
"der 0.8.2",
|
||||||
"digest 0.11.3",
|
"digest 0.11.3",
|
||||||
"ecdsa 0.17.0",
|
"ecdsa 0.17.0",
|
||||||
"ed25519-dalek 3.0.0",
|
"ed25519-dalek 3.0.0",
|
||||||
@@ -11066,7 +11066,7 @@ dependencies = [
|
|||||||
"errno",
|
"errno",
|
||||||
"libc",
|
"libc",
|
||||||
"linux-raw-sys",
|
"linux-raw-sys",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -11149,7 +11149,7 @@ dependencies = [
|
|||||||
"security-framework",
|
"security-framework",
|
||||||
"security-framework-sys",
|
"security-framework-sys",
|
||||||
"webpki-root-certs",
|
"webpki-root-certs",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -11420,7 +11420,7 @@ checksum = "d56d437c2f19203ce5f7122e507831de96f3d2d4d3be5af44a0b0a09d8a80e4d"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"base16ct 1.0.0",
|
"base16ct 1.0.0",
|
||||||
"ctutils",
|
"ctutils",
|
||||||
"der 0.8.1",
|
"der 0.8.2",
|
||||||
"hybrid-array",
|
"hybrid-array",
|
||||||
"subtle",
|
"subtle",
|
||||||
"zeroize",
|
"zeroize",
|
||||||
@@ -11994,7 +11994,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "1d9efca8738c78ee9484207732f728b1ef517bbb1833d6fc0879ca898a522f6f"
|
checksum = "1d9efca8738c78ee9484207732f728b1ef517bbb1833d6fc0879ca898a522f6f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64ct",
|
"base64ct",
|
||||||
"der 0.8.1",
|
"der 0.8.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -12406,10 +12406,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd"
|
checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"fastrand",
|
"fastrand",
|
||||||
"getrandom 0.4.3",
|
"getrandom 0.3.4",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"rustix",
|
"rustix",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -13528,7 +13528,7 @@ version = "0.1.11"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
|
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
+5
-5
@@ -256,10 +256,10 @@ clap = { version = "4.6.6" }
|
|||||||
const-str = { version = "1.1.0" }
|
const-str = { version = "1.1.0" }
|
||||||
convert_case = "0.12.0"
|
convert_case = "0.12.0"
|
||||||
criterion = { version = "0.8" }
|
criterion = { version = "0.8" }
|
||||||
crossbeam-queue = "0.3.13"
|
crossbeam-queue = "0.3.14"
|
||||||
crossbeam-channel = "0.5.16"
|
crossbeam-channel = "0.5.17"
|
||||||
crossbeam-deque = "0.8.7"
|
crossbeam-deque = "0.8.8"
|
||||||
crossbeam-utils = "0.8.22"
|
crossbeam-utils = "0.8.23"
|
||||||
datafusion = { default-features = false, version = "55.0.0" }
|
datafusion = { default-features = false, version = "55.0.0" }
|
||||||
derive_builder = "0.20.2"
|
derive_builder = "0.20.2"
|
||||||
enumset = "1.1.14"
|
enumset = "1.1.14"
|
||||||
@@ -306,7 +306,7 @@ rustfs-erasure-codec = { version = "8.0.2" }
|
|||||||
reed-solomon-simd = "3.1.0"
|
reed-solomon-simd = "3.1.0"
|
||||||
regex = { version = "1.13.1" }
|
regex = { version = "1.13.1" }
|
||||||
rumqttc = { package = "rumqttc-next", version = "0.34.0" }
|
rumqttc = { package = "rumqttc-next", version = "0.34.0" }
|
||||||
redis = { version = "1.6.0" }
|
redis = { version = "1.7.0" }
|
||||||
rustify = { version = "0.7", default-features = false }
|
rustify = { version = "0.7", default-features = false }
|
||||||
rustix = { version = "1.1.4" }
|
rustix = { version = "1.1.4" }
|
||||||
rust-embed = { version = "8.12.0" }
|
rust-embed = { version = "8.12.0" }
|
||||||
|
|||||||
@@ -293,7 +293,7 @@ pub mod cache {
|
|||||||
pub mod capacity {
|
pub mod capacity {
|
||||||
pub use crate::core::pools::{
|
pub use crate::core::pools::{
|
||||||
DecommissionUnresolvedEntry, PoolDecommissionInfo, PoolStatus, get_total_usable_capacity, get_total_usable_capacity_free,
|
DecommissionUnresolvedEntry, PoolDecommissionInfo, PoolStatus, get_total_usable_capacity, get_total_usable_capacity_free,
|
||||||
is_pool_activation_fleet_proof_error, path2_bucket_object, path2_bucket_object_with_base_path,
|
path2_bucket_object, path2_bucket_object_with_base_path,
|
||||||
};
|
};
|
||||||
pub use crate::store::utils::is_reserved_or_invalid_bucket;
|
pub use crate::store::utils::is_reserved_or_invalid_bucket;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3385,7 +3385,7 @@ pub(crate) async fn acquire_pool_activation_fleet_proof(
|
|||||||
.ok_or_else(|| Error::other(POOL_ACTIVATION_FLEET_PROOF_REQUIRED))
|
.ok_or_else(|| Error::other(POOL_ACTIVATION_FLEET_PROOF_REQUIRED))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_pool_activation_fleet_proof_error(err: &Error) -> bool {
|
pub(crate) fn is_pool_activation_fleet_proof_error(err: &Error) -> bool {
|
||||||
// Save-stage helpers add context by formatting the original error, so the
|
// Save-stage helpers add context by formatting the original error, so the
|
||||||
// marker may be nested in the display string. Restrict matching to the
|
// marker may be nested in the display string. Restrict matching to the
|
||||||
// `Error::other` I/O shape used by this activation path.
|
// `Error::other` I/O shape used by this activation path.
|
||||||
|
|||||||
@@ -16291,7 +16291,23 @@ mod transition_upload_integrity_tests {
|
|||||||
let bucket = format!("transition-real-bitrot-{}", position.label());
|
let bucket = format!("transition-real-bitrot-{}", position.label());
|
||||||
let object = format!("{}-corrupt.bin", position.label());
|
let object = format!("{}-corrupt.bin", position.label());
|
||||||
let payload = vec![0x41; 2 * 1024 * 1024];
|
let payload = vec![0x41; 2 * 1024 * 1024];
|
||||||
let original = write_source(&set_disks, &disk_stores, &bucket, &object, &payload).await;
|
// Corruption edits physical shards, so every healthy rename must finish first.
|
||||||
|
for disk in &disk_stores {
|
||||||
|
disk.make_volume(&bucket).await.expect("bucket volume should be created");
|
||||||
|
}
|
||||||
|
let mut reader = PutObjReader::from_vec(payload.to_vec());
|
||||||
|
let original = set_disks
|
||||||
|
.put_object(
|
||||||
|
&bucket,
|
||||||
|
&object,
|
||||||
|
&mut reader,
|
||||||
|
&ObjectOptions {
|
||||||
|
write_completion: WriteCompletion::TailDrained,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.expect("source object should be written");
|
||||||
let source = set_disks
|
let source = set_disks
|
||||||
.get_object_fileinfo(
|
.get_object_fileinfo(
|
||||||
&bucket,
|
&bucket,
|
||||||
|
|||||||
@@ -1730,6 +1730,7 @@ where
|
|||||||
};
|
};
|
||||||
let baseline_publication_epoch = baseline_publication_guard.epoch();
|
let baseline_publication_epoch = baseline_publication_guard.epoch();
|
||||||
let usage_persist_baseline_result = read_data_usage_persist_baseline(storeapi.clone()).await;
|
let usage_persist_baseline_result = read_data_usage_persist_baseline(storeapi.clone()).await;
|
||||||
|
let observed_usage_candidate_result = read_config(storeapi.clone(), DATA_USAGE_OBSERVED_OBJ_NAME_PATH.as_str()).await;
|
||||||
drop(baseline_publication_guard);
|
drop(baseline_publication_guard);
|
||||||
let usage_persist_baseline = match usage_persist_baseline_result {
|
let usage_persist_baseline = match usage_persist_baseline_result {
|
||||||
Ok(baseline) => baseline,
|
Ok(baseline) => baseline,
|
||||||
@@ -1750,6 +1751,24 @@ where
|
|||||||
return ScannerCycleOutcome::Failed;
|
return ScannerCycleOutcome::Failed;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
let observed_usage_candidate = match observed_usage_candidate_result {
|
||||||
|
Ok(candidate) => Some(Bytes::from(candidate)),
|
||||||
|
Err(EcstoreError::ConfigNotFound) => None,
|
||||||
|
Err(err) => {
|
||||||
|
debug!(
|
||||||
|
target: "rustfs::scanner",
|
||||||
|
event = EVENT_SCANNER_PERSIST_STATE,
|
||||||
|
component = LOG_COMPONENT_SCANNER,
|
||||||
|
subsystem = LOG_SUBSYSTEM_RUNTIME,
|
||||||
|
cycle = cycle_info.current,
|
||||||
|
path = %DATA_USAGE_OBSERVED_OBJ_NAME_PATH.as_str(),
|
||||||
|
state = "observed_candidate_load_failed",
|
||||||
|
error = %err,
|
||||||
|
"Scanner skipped an unavailable observed usage candidate for scoped refresh"
|
||||||
|
);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
};
|
||||||
let (sender, receiver) = mpsc::channel::<DataUsageInfo>(1);
|
let (sender, receiver) = mpsc::channel::<DataUsageInfo>(1);
|
||||||
|
|
||||||
let done_cycle = Metrics::time(Metric::ScanCycle);
|
let done_cycle = Metrics::time(Metric::ScanCycle);
|
||||||
@@ -1764,6 +1783,7 @@ where
|
|||||||
scan_mode,
|
scan_mode,
|
||||||
scan_scope: crate::scanner_io::ScannerBucketScanScope::default(),
|
scan_scope: crate::scanner_io::ScannerBucketScanScope::default(),
|
||||||
persisted_usage_baseline: usage_persist_baseline.data.clone(),
|
persisted_usage_baseline: usage_persist_baseline.data.clone(),
|
||||||
|
observed_usage_candidate,
|
||||||
requires_full_scan: scheduling.requires_full_scan,
|
requires_full_scan: scheduling.requires_full_scan,
|
||||||
service_cohort: scheduling.service_cohort,
|
service_cohort: scheduling.service_cohort,
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ use metrics::counter;
|
|||||||
use rand::seq::SliceRandom as _;
|
use rand::seq::SliceRandom as _;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
use rustfs_config::{ENV_SCANNER_MAX_CONCURRENT_DISK_SCANS, ENV_SCANNER_MAX_CONCURRENT_SET_SCANS};
|
use rustfs_config::{ENV_SCANNER_MAX_CONCURRENT_DISK_SCANS, ENV_SCANNER_MAX_CONCURRENT_SET_SCANS};
|
||||||
use rustfs_data_usage::{BucketTargetUsageInfo, BucketUsageInfo};
|
use rustfs_data_usage::{BucketTargetUsageInfo, BucketUsageInfo, observed_data_usage_is_newer};
|
||||||
use rustfs_filemeta::FileMeta;
|
use rustfs_filemeta::FileMeta;
|
||||||
use rustfs_heal_contracts::heal_channel::HealScanMode;
|
use rustfs_heal_contracts::heal_channel::HealScanMode;
|
||||||
use rustfs_lock::{LockError, NamespaceLockGuard};
|
use rustfs_lock::{LockError, NamespaceLockGuard};
|
||||||
@@ -128,7 +128,8 @@ impl ScannerBucketScanScope {
|
|||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub(super) struct ScannerCacheBaselineProof<'a> {
|
pub(super) struct ScannerCacheBaselineProof<'a> {
|
||||||
pub(super) data: Option<&'a Bytes>,
|
pub(super) authoritative_data: Option<&'a Bytes>,
|
||||||
|
pub(super) observed_candidate_data: Option<&'a Bytes>,
|
||||||
pub(super) expected_sources: &'a HashSet<DataUsageCacheSource>,
|
pub(super) expected_sources: &'a HashSet<DataUsageCacheSource>,
|
||||||
pub(super) leader_epoch: u64,
|
pub(super) leader_epoch: u64,
|
||||||
pub(super) want_cycle: u64,
|
pub(super) want_cycle: u64,
|
||||||
@@ -171,21 +172,23 @@ fn verified_remote_dirty_usage_buckets(
|
|||||||
(received_peers.len() == expected_peers.len()).then_some(dirty_buckets)
|
(received_peers.len() == expected_peers.len()).then_some(dirty_buckets)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn complete_scanner_cache_baseline_plan_digest(proof: ScannerCacheBaselineProof<'_>) -> Option<DataUsageScanPlanDigest> {
|
fn complete_scanner_cache_snapshot_plan_digest(
|
||||||
let data = proof.data?;
|
snapshot: &DataUsageInfo,
|
||||||
let baseline = serde_json::from_slice::<DataUsageInfo>(data).ok()?;
|
proof: ScannerCacheBaselineProof<'_>,
|
||||||
if !baseline.is_complete_bucket_usage_snapshot()
|
expected_converged: bool,
|
||||||
|| baseline.usage_snapshot_partial
|
) -> Option<DataUsageScanPlanDigest> {
|
||||||
|| baseline.usage_snapshot_converged != Some(true)
|
if !snapshot.is_complete_bucket_usage_snapshot()
|
||||||
|| baseline.scanner_epoch != Some(proof.leader_epoch)
|
|| snapshot.usage_snapshot_partial
|
||||||
|| baseline.usage_snapshot_set_states.len() != proof.expected_sources.len()
|
|| snapshot.usage_snapshot_converged != Some(expected_converged)
|
||||||
|
|| snapshot.scanner_epoch != Some(proof.leader_epoch)
|
||||||
|
|| snapshot.usage_snapshot_set_states.len() != proof.expected_sources.len()
|
||||||
{
|
{
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Completed maintenance also covers ordinary usage. Keep its exact stored
|
// Completed maintenance also covers ordinary usage. Keep its exact stored
|
||||||
// proof for cache reuse, and reject mixtures of different set work proofs.
|
// proof for cache reuse, and reject mixtures of different set work proofs.
|
||||||
let baseline_plan_digest = DataUsageScanPlanDigest(baseline.usage_snapshot_set_states.first()?.scan_plan_digest?);
|
let baseline_plan_digest = DataUsageScanPlanDigest(snapshot.usage_snapshot_set_states.first()?.scan_plan_digest?);
|
||||||
if ![
|
if ![
|
||||||
proof.scan_plan_digest,
|
proof.scan_plan_digest,
|
||||||
scanner_bucket_work_digest(proof.scan_plan_digest, HealScanMode::Normal, true),
|
scanner_bucket_work_digest(proof.scan_plan_digest, HealScanMode::Normal, true),
|
||||||
@@ -195,8 +198,8 @@ fn complete_scanner_cache_baseline_plan_digest(proof: ScannerCacheBaselineProof<
|
|||||||
{
|
{
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let mut states = HashSet::with_capacity(baseline.usage_snapshot_set_states.len());
|
let mut states = HashSet::with_capacity(snapshot.usage_snapshot_set_states.len());
|
||||||
for state in &baseline.usage_snapshot_set_states {
|
for state in &snapshot.usage_snapshot_set_states {
|
||||||
let source = DataUsageCacheSource::new(usize::try_from(state.pool_index).ok()?, usize::try_from(state.set_index).ok()?);
|
let source = DataUsageCacheSource::new(usize::try_from(state.pool_index).ok()?, usize::try_from(state.set_index).ok()?);
|
||||||
if !proof.expected_sources.contains(&source)
|
if !proof.expected_sources.contains(&source)
|
||||||
|| !states.insert(source)
|
|| !states.insert(source)
|
||||||
@@ -213,6 +216,30 @@ fn complete_scanner_cache_baseline_plan_digest(proof: ScannerCacheBaselineProof<
|
|||||||
(states == *proof.expected_sources).then_some(baseline_plan_digest)
|
(states == *proof.expected_sources).then_some(baseline_plan_digest)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn complete_scanner_cache_baseline_plan_digest(proof: ScannerCacheBaselineProof<'_>) -> Option<DataUsageScanPlanDigest> {
|
||||||
|
let authoritative = serde_json::from_slice::<DataUsageInfo>(proof.authoritative_data?).ok()?;
|
||||||
|
if complete_scanner_cache_snapshot_plan_digest(&authoritative, proof, true).is_some() {
|
||||||
|
return Some(proof.scan_plan_digest);
|
||||||
|
}
|
||||||
|
|
||||||
|
// A complete but superseded observation may reuse its per-set cache only
|
||||||
|
// when it was explicitly tied to the durable authoritative baseline. It
|
||||||
|
// remains observational: this proof grants bucket-scope reuse only and
|
||||||
|
// never changes authoritative usage publication or dirty acknowledgement.
|
||||||
|
let authoritative_has_identity = (crate::scanner::data_usage_info_has_persisted_baseline_identity(&authoritative)
|
||||||
|
&& authoritative.usage_snapshot_converged != Some(false))
|
||||||
|
|| crate::scanner::data_usage_info_is_bootstrap_pending(&authoritative);
|
||||||
|
if !authoritative_has_identity {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let observed = serde_json::from_slice::<DataUsageInfo>(proof.observed_candidate_data?).ok()?;
|
||||||
|
if !observed_data_usage_is_newer(&observed, &authoritative) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
complete_scanner_cache_snapshot_plan_digest(&observed, proof, false)
|
||||||
|
}
|
||||||
|
|
||||||
fn scoped_scan_scope_from_dirty_buckets(
|
fn scoped_scan_scope_from_dirty_buckets(
|
||||||
requested_scope: ScannerBucketScanScope,
|
requested_scope: ScannerBucketScanScope,
|
||||||
dirty_buckets: HashSet<String>,
|
dirty_buckets: HashSet<String>,
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ where
|
|||||||
scan_mode,
|
scan_mode,
|
||||||
scan_scope: ScannerBucketScanScope::default(),
|
scan_scope: ScannerBucketScanScope::default(),
|
||||||
persisted_usage_baseline: None,
|
persisted_usage_baseline: None,
|
||||||
|
observed_usage_candidate: None,
|
||||||
requires_full_scan: true,
|
requires_full_scan: true,
|
||||||
service_cohort: None,
|
service_cohort: None,
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@@ -89,6 +90,7 @@ pub(crate) struct ScannerCycleRequest {
|
|||||||
pub(crate) scan_mode: HealScanMode,
|
pub(crate) scan_mode: HealScanMode,
|
||||||
pub(crate) scan_scope: ScannerBucketScanScope,
|
pub(crate) scan_scope: ScannerBucketScanScope,
|
||||||
pub(crate) persisted_usage_baseline: Option<Bytes>,
|
pub(crate) persisted_usage_baseline: Option<Bytes>,
|
||||||
|
pub(crate) observed_usage_candidate: Option<Bytes>,
|
||||||
/// Scheduled maintenance must visit clean buckets even with a valid dirty scope.
|
/// Scheduled maintenance must visit clean buckets even with a valid dirty scope.
|
||||||
pub(crate) requires_full_scan: bool,
|
pub(crate) requires_full_scan: bool,
|
||||||
pub(crate) service_cohort: Option<Arc<StdMutex<ScannerServiceCohort>>>,
|
pub(crate) service_cohort: Option<Arc<StdMutex<ScannerServiceCohort>>>,
|
||||||
@@ -185,6 +187,7 @@ where
|
|||||||
scan_mode,
|
scan_mode,
|
||||||
scan_scope,
|
scan_scope,
|
||||||
persisted_usage_baseline,
|
persisted_usage_baseline,
|
||||||
|
observed_usage_candidate,
|
||||||
requires_full_scan,
|
requires_full_scan,
|
||||||
service_cohort,
|
service_cohort,
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@@ -297,7 +300,8 @@ where
|
|||||||
ScannerBucketScopeResolution {
|
ScannerBucketScopeResolution {
|
||||||
requested_scope: scan_scope,
|
requested_scope: scan_scope,
|
||||||
baseline_proof: ScannerCacheBaselineProof {
|
baseline_proof: ScannerCacheBaselineProof {
|
||||||
data: persisted_usage_baseline.as_ref(),
|
authoritative_data: persisted_usage_baseline.as_ref(),
|
||||||
|
observed_candidate_data: observed_usage_candidate.as_ref(),
|
||||||
expected_sources: &expected_sources,
|
expected_sources: &expected_sources,
|
||||||
leader_epoch,
|
leader_epoch,
|
||||||
want_cycle,
|
want_cycle,
|
||||||
|
|||||||
@@ -397,6 +397,7 @@ async fn scoped_scan_production_entry_preserves_deep_and_full_maintenance_work()
|
|||||||
scan_mode,
|
scan_mode,
|
||||||
scan_scope: requested_scope,
|
scan_scope: requested_scope,
|
||||||
persisted_usage_baseline: baseline,
|
persisted_usage_baseline: baseline,
|
||||||
|
observed_usage_candidate: None,
|
||||||
requires_full_scan,
|
requires_full_scan,
|
||||||
resolved_scope_observer: Some(observer),
|
resolved_scope_observer: Some(observer),
|
||||||
service_cohort: None,
|
service_cohort: None,
|
||||||
@@ -470,6 +471,7 @@ async fn scoped_scan_same_cycle_maintenance_rewalks_after_root_delivery_failure(
|
|||||||
scan_mode: HealScanMode::Normal,
|
scan_mode: HealScanMode::Normal,
|
||||||
scan_scope: ScannerBucketScanScope::default(),
|
scan_scope: ScannerBucketScanScope::default(),
|
||||||
persisted_usage_baseline: None,
|
persisted_usage_baseline: None,
|
||||||
|
observed_usage_candidate: None,
|
||||||
requires_full_scan: false,
|
requires_full_scan: false,
|
||||||
resolved_scope_observer: None,
|
resolved_scope_observer: None,
|
||||||
service_cohort: None,
|
service_cohort: None,
|
||||||
@@ -521,6 +523,7 @@ async fn scoped_scan_same_cycle_maintenance_rewalks_after_root_delivery_failure(
|
|||||||
scan_mode,
|
scan_mode,
|
||||||
scan_scope: ScannerBucketScanScope::default(),
|
scan_scope: ScannerBucketScanScope::default(),
|
||||||
persisted_usage_baseline: None,
|
persisted_usage_baseline: None,
|
||||||
|
observed_usage_candidate: None,
|
||||||
requires_full_scan,
|
requires_full_scan,
|
||||||
resolved_scope_observer: None,
|
resolved_scope_observer: None,
|
||||||
service_cohort: None,
|
service_cohort: None,
|
||||||
@@ -1331,7 +1334,8 @@ fn scoped_scan_requires_a_converged_complete_baseline_with_exact_set_provenance(
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
complete_scanner_cache_baseline_plan_digest(ScannerCacheBaselineProof {
|
complete_scanner_cache_baseline_plan_digest(ScannerCacheBaselineProof {
|
||||||
data: Some(&baseline),
|
authoritative_data: Some(&baseline),
|
||||||
|
observed_candidate_data: None,
|
||||||
expected_sources: &expected_sources,
|
expected_sources: &expected_sources,
|
||||||
leader_epoch: 11,
|
leader_epoch: 11,
|
||||||
want_cycle: 8,
|
want_cycle: 8,
|
||||||
@@ -1345,7 +1349,8 @@ fn scoped_scan_requires_a_converged_complete_baseline_with_exact_set_provenance(
|
|||||||
let incomplete = bytes::Bytes::from(serde_json::to_vec(&incomplete).expect("test baseline should encode"));
|
let incomplete = bytes::Bytes::from(serde_json::to_vec(&incomplete).expect("test baseline should encode"));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
complete_scanner_cache_baseline_plan_digest(ScannerCacheBaselineProof {
|
complete_scanner_cache_baseline_plan_digest(ScannerCacheBaselineProof {
|
||||||
data: Some(&incomplete),
|
authoritative_data: Some(&incomplete),
|
||||||
|
observed_candidate_data: None,
|
||||||
expected_sources: &expected_sources,
|
expected_sources: &expected_sources,
|
||||||
leader_epoch: 11,
|
leader_epoch: 11,
|
||||||
want_cycle: 8,
|
want_cycle: 8,
|
||||||
@@ -1359,7 +1364,8 @@ fn scoped_scan_requires_a_converged_complete_baseline_with_exact_set_provenance(
|
|||||||
let wrong_provenance = bytes::Bytes::from(serde_json::to_vec(&wrong_provenance).expect("test baseline should encode"));
|
let wrong_provenance = bytes::Bytes::from(serde_json::to_vec(&wrong_provenance).expect("test baseline should encode"));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
complete_scanner_cache_baseline_plan_digest(ScannerCacheBaselineProof {
|
complete_scanner_cache_baseline_plan_digest(ScannerCacheBaselineProof {
|
||||||
data: Some(&wrong_provenance),
|
authoritative_data: Some(&wrong_provenance),
|
||||||
|
observed_candidate_data: None,
|
||||||
expected_sources: &expected_sources,
|
expected_sources: &expected_sources,
|
||||||
leader_epoch: 11,
|
leader_epoch: 11,
|
||||||
want_cycle: 8,
|
want_cycle: 8,
|
||||||
@@ -1369,6 +1375,111 @@ fn scoped_scan_requires_a_converged_complete_baseline_with_exact_set_provenance(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn scoped_scan_accepts_only_a_complete_observation_tied_to_the_authoritative_baseline() {
|
||||||
|
let source = DataUsageCacheSource::new(1, 2);
|
||||||
|
let expected_sources = HashSet::from([source]);
|
||||||
|
let scan_plan_digest = DataUsageScanPlanDigest([9; 32]);
|
||||||
|
let authoritative = complete_usage_baseline(source, scan_plan_digest, 7, 11);
|
||||||
|
let authoritative_info =
|
||||||
|
serde_json::from_slice::<DataUsageInfo>(&authoritative).expect("authoritative baseline should decode");
|
||||||
|
let bootstrap_authoritative_info =
|
||||||
|
crate::scanner::scanner_usage_bootstrap_marker(SystemTime::UNIX_EPOCH + Duration::from_secs(9), Some(11));
|
||||||
|
let bootstrap_authoritative =
|
||||||
|
bytes::Bytes::from(serde_json::to_vec(&bootstrap_authoritative_info).expect("bootstrap baseline should encode"));
|
||||||
|
let mut observed_info = authoritative_info.clone();
|
||||||
|
observed_info.last_update = Some(SystemTime::UNIX_EPOCH + Duration::from_secs(11));
|
||||||
|
observed_info.scanner_cycle = Some(8);
|
||||||
|
observed_info.usage_snapshot_converged = Some(false);
|
||||||
|
observed_info.usage_snapshot_authoritative_baseline = Some(bootstrap_authoritative_info.snapshot_identity());
|
||||||
|
observed_info.usage_snapshot_set_states[0].scanner_cycle = Some(8);
|
||||||
|
let observed = bytes::Bytes::from(serde_json::to_vec(&observed_info).expect("observation should encode"));
|
||||||
|
|
||||||
|
macro_rules! proof {
|
||||||
|
($authoritative:expr, $candidate:expr) => {
|
||||||
|
ScannerCacheBaselineProof {
|
||||||
|
authoritative_data: Some($authoritative),
|
||||||
|
observed_candidate_data: $candidate,
|
||||||
|
expected_sources: &expected_sources,
|
||||||
|
leader_epoch: 11,
|
||||||
|
want_cycle: 9,
|
||||||
|
scan_plan_digest,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
assert_eq!(
|
||||||
|
complete_scanner_cache_baseline_plan_digest(proof!(&bootstrap_authoritative, Some(&observed))),
|
||||||
|
Some(scan_plan_digest)
|
||||||
|
);
|
||||||
|
|
||||||
|
observed_info.usage_snapshot_authoritative_baseline = Some(DataUsageInfo::default().snapshot_identity());
|
||||||
|
let mismatched_baseline = bytes::Bytes::from(serde_json::to_vec(&observed_info).expect("observation should encode"));
|
||||||
|
assert_eq!(
|
||||||
|
complete_scanner_cache_baseline_plan_digest(proof!(&bootstrap_authoritative, Some(&mismatched_baseline))),
|
||||||
|
None
|
||||||
|
);
|
||||||
|
|
||||||
|
observed_info = serde_json::from_slice(&observed).expect("observation should decode");
|
||||||
|
observed_info.usage_snapshot_partial = true;
|
||||||
|
let partial = bytes::Bytes::from(serde_json::to_vec(&observed_info).expect("partial observation should encode"));
|
||||||
|
assert_eq!(
|
||||||
|
complete_scanner_cache_baseline_plan_digest(proof!(&bootstrap_authoritative, Some(&partial))),
|
||||||
|
None
|
||||||
|
);
|
||||||
|
|
||||||
|
observed_info = serde_json::from_slice(&observed).expect("observation should decode");
|
||||||
|
observed_info.usage_snapshot_converged = Some(true);
|
||||||
|
let converged = bytes::Bytes::from(serde_json::to_vec(&observed_info).expect("converged observation should encode"));
|
||||||
|
assert_eq!(
|
||||||
|
complete_scanner_cache_baseline_plan_digest(proof!(&bootstrap_authoritative, Some(&converged))),
|
||||||
|
None
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut legacy_authoritative = authoritative_info.clone();
|
||||||
|
legacy_authoritative.usage_snapshot_converged = None;
|
||||||
|
let mut stale_info = serde_json::from_slice::<DataUsageInfo>(&observed).expect("observation should decode");
|
||||||
|
stale_info.scanner_cycle = Some(7);
|
||||||
|
stale_info.usage_snapshot_set_states[0].scanner_cycle = Some(7);
|
||||||
|
stale_info.usage_snapshot_authoritative_baseline = Some(legacy_authoritative.snapshot_identity());
|
||||||
|
let legacy_authoritative =
|
||||||
|
bytes::Bytes::from(serde_json::to_vec(&legacy_authoritative).expect("legacy baseline should encode"));
|
||||||
|
let stale = bytes::Bytes::from(serde_json::to_vec(&stale_info).expect("stale observation should encode"));
|
||||||
|
assert_eq!(
|
||||||
|
complete_scanner_cache_baseline_plan_digest(proof!(&legacy_authoritative, Some(&stale))),
|
||||||
|
None
|
||||||
|
);
|
||||||
|
|
||||||
|
let malformed = bytes::Bytes::from_static(b"not data usage json");
|
||||||
|
assert_eq!(
|
||||||
|
complete_scanner_cache_baseline_plan_digest(proof!(&bootstrap_authoritative, Some(&malformed))),
|
||||||
|
None
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut nonconverged_authoritative = authoritative_info;
|
||||||
|
nonconverged_authoritative.usage_snapshot_converged = Some(false);
|
||||||
|
let mut observation_of_nonconverged_authoritative = nonconverged_authoritative.clone();
|
||||||
|
observation_of_nonconverged_authoritative.last_update = Some(SystemTime::UNIX_EPOCH + Duration::from_secs(12));
|
||||||
|
observation_of_nonconverged_authoritative.scanner_cycle = Some(8);
|
||||||
|
observation_of_nonconverged_authoritative.usage_snapshot_set_states[0].scanner_cycle = Some(8);
|
||||||
|
observation_of_nonconverged_authoritative.usage_snapshot_authoritative_baseline =
|
||||||
|
Some(nonconverged_authoritative.snapshot_identity());
|
||||||
|
let nonconverged_authoritative =
|
||||||
|
bytes::Bytes::from(serde_json::to_vec(&nonconverged_authoritative).expect("nonconverged baseline should encode"));
|
||||||
|
let observation_of_nonconverged_authoritative =
|
||||||
|
bytes::Bytes::from(serde_json::to_vec(&observation_of_nonconverged_authoritative).expect("observation should encode"));
|
||||||
|
assert_eq!(
|
||||||
|
complete_scanner_cache_baseline_plan_digest(ScannerCacheBaselineProof {
|
||||||
|
authoritative_data: Some(&nonconverged_authoritative),
|
||||||
|
observed_candidate_data: Some(&observation_of_nonconverged_authoritative),
|
||||||
|
expected_sources: &expected_sources,
|
||||||
|
leader_epoch: 11,
|
||||||
|
want_cycle: 9,
|
||||||
|
scan_plan_digest,
|
||||||
|
}),
|
||||||
|
None
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn scoped_scan_selects_only_current_dirty_buckets_after_baseline_validation() {
|
fn scoped_scan_selects_only_current_dirty_buckets_after_baseline_validation() {
|
||||||
let source = DataUsageCacheSource::new(1, 2);
|
let source = DataUsageCacheSource::new(1, 2);
|
||||||
@@ -1382,7 +1493,8 @@ fn scoped_scan_selects_only_current_dirty_buckets_after_baseline_validation() {
|
|||||||
true,
|
true,
|
||||||
&[bucket_info("photos")],
|
&[bucket_info("photos")],
|
||||||
ScannerCacheBaselineProof {
|
ScannerCacheBaselineProof {
|
||||||
data: Some(&baseline),
|
authoritative_data: Some(&baseline),
|
||||||
|
observed_candidate_data: None,
|
||||||
expected_sources: &expected_sources,
|
expected_sources: &expected_sources,
|
||||||
leader_epoch: 11,
|
leader_epoch: 11,
|
||||||
want_cycle: 8,
|
want_cycle: 8,
|
||||||
@@ -1420,7 +1532,8 @@ fn scoped_scan_baseline_work_proof_requires_uniform_known_set_identity() {
|
|||||||
let data = Bytes::from(serde_json::to_vec(&candidate).expect("candidate should encode"));
|
let data = Bytes::from(serde_json::to_vec(&candidate).expect("candidate should encode"));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
complete_scanner_cache_baseline_plan_digest(ScannerCacheBaselineProof {
|
complete_scanner_cache_baseline_plan_digest(ScannerCacheBaselineProof {
|
||||||
data: Some(&data),
|
authoritative_data: Some(&data),
|
||||||
|
observed_candidate_data: None,
|
||||||
expected_sources: &sources,
|
expected_sources: &sources,
|
||||||
leader_epoch: 11,
|
leader_epoch: 11,
|
||||||
want_cycle: 8,
|
want_cycle: 8,
|
||||||
|
|||||||
@@ -126,6 +126,7 @@ async fn run_entry(store: &Arc<ECStore>, cycle: u64, selected: Option<&str>, exp
|
|||||||
scan_mode: HealScanMode::Normal,
|
scan_mode: HealScanMode::Normal,
|
||||||
scan_scope: ScannerBucketScanScope::default(),
|
scan_scope: ScannerBucketScanScope::default(),
|
||||||
persisted_usage_baseline: root_before.0.clone().map(Bytes::from),
|
persisted_usage_baseline: root_before.0.clone().map(Bytes::from),
|
||||||
|
observed_usage_candidate: None,
|
||||||
requires_full_scan: false,
|
requires_full_scan: false,
|
||||||
service_cohort: None,
|
service_cohort: None,
|
||||||
resolved_scope_observer: Some(observer),
|
resolved_scope_observer: Some(observer),
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ async fn run_cohort_cycle(
|
|||||||
scan_mode: HealScanMode::Normal,
|
scan_mode: HealScanMode::Normal,
|
||||||
scan_scope: ScannerBucketScanScope::default(),
|
scan_scope: ScannerBucketScanScope::default(),
|
||||||
persisted_usage_baseline: None,
|
persisted_usage_baseline: None,
|
||||||
|
observed_usage_candidate: None,
|
||||||
requires_full_scan: false,
|
requires_full_scan: false,
|
||||||
service_cohort: Some(cohort),
|
service_cohort: Some(cohort),
|
||||||
resolved_scope_observer: None,
|
resolved_scope_observer: None,
|
||||||
|
|||||||
@@ -63,7 +63,6 @@ const EVENT_ADMIN_REQUEST_STATE: &str = "admin_request_state";
|
|||||||
const EVENT_ADMIN_REQUEST_REJECTED: &str = "admin_request_rejected";
|
const EVENT_ADMIN_REQUEST_REJECTED: &str = "admin_request_rejected";
|
||||||
const EVENT_ADMIN_REQUEST_FAILED: &str = "admin_request_failed";
|
const EVENT_ADMIN_REQUEST_FAILED: &str = "admin_request_failed";
|
||||||
const EVENT_ADMIN_RESPONSE_EMITTED: &str = "admin_response_emitted";
|
const EVENT_ADMIN_RESPONSE_EMITTED: &str = "admin_response_emitted";
|
||||||
const POOL_ACTIVATION_FLEET_PROOF_REQUIRED: &str = "pool activation requires a live fleet capability proof";
|
|
||||||
|
|
||||||
fn admin_request_id(headers: &HeaderMap) -> Option<&str> {
|
fn admin_request_id(headers: &HeaderMap) -> Option<&str> {
|
||||||
headers
|
headers
|
||||||
@@ -322,17 +321,6 @@ fn contextualize_admin_pool_api_error(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decommission_start_api_error(err: crate::storage_api::error::StorageError) -> ApiError {
|
|
||||||
if crate::storage_api::capacity::is_pool_activation_fleet_proof_error(&err) {
|
|
||||||
return ApiError {
|
|
||||||
code: S3ErrorCode::InternalError,
|
|
||||||
message: POOL_ACTIVATION_FLEET_PROOF_REQUIRED.to_string(),
|
|
||||||
source: Some(Box::new(err)),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
ApiError::from(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn decommission_admin_not_initialized_error_with_audit(operation: &str, audit: PoolAuditContext<'_>) -> S3Error {
|
fn decommission_admin_not_initialized_error_with_audit(operation: &str, audit: PoolAuditContext<'_>) -> S3Error {
|
||||||
error!(
|
error!(
|
||||||
event = EVENT_ADMIN_REQUEST_FAILED,
|
event = EVENT_ADMIN_REQUEST_FAILED,
|
||||||
@@ -802,24 +790,7 @@ impl Operation for StartDecommission {
|
|||||||
store
|
store
|
||||||
.decommission(ctx.clone(), pools_indices.clone())
|
.decommission(ctx.clone(), pools_indices.clone())
|
||||||
.await
|
.await
|
||||||
.map_err(|err| {
|
.map_err(ApiError::from)
|
||||||
error!(
|
|
||||||
event = EVENT_ADMIN_REQUEST_FAILED,
|
|
||||||
component = LOG_COMPONENT_ADMIN_API,
|
|
||||||
subsystem = LOG_SUBSYSTEM_POOL_ADMIN,
|
|
||||||
operation = "start_decommission",
|
|
||||||
action = "start_decommission",
|
|
||||||
result = "failed",
|
|
||||||
reason = "storage_decommission_failed",
|
|
||||||
request_id = %request_id,
|
|
||||||
actor = %actor,
|
|
||||||
remote_addr = %remote_addr,
|
|
||||||
pool_indices = ?pools_indices,
|
|
||||||
error = %err,
|
|
||||||
"admin request failed"
|
|
||||||
);
|
|
||||||
decommission_start_api_error(err)
|
|
||||||
})
|
|
||||||
.map_err(|err| contextualize_admin_pool_api_error(err, "start decommission", &pool_context))?;
|
.map_err(|err| contextualize_admin_pool_api_error(err, "start decommission", &pool_context))?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1047,10 +1018,9 @@ impl Operation for ClearDecommission {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod pools_handler_tests {
|
mod pools_handler_tests {
|
||||||
use super::{
|
use super::{
|
||||||
AdminPoolStatus, Body, CancelDecommission, ClearDecommission, HeaderMap, ListPools, Method, Operation,
|
AdminPoolStatus, Body, CancelDecommission, ClearDecommission, HeaderMap, ListPools, Method, Operation, Params,
|
||||||
POOL_ACTIVATION_FLEET_PROOF_REQUIRED, Params, PoolAuditContext, S3ErrorCode, S3Request, StartDecommission,
|
PoolAuditContext, S3ErrorCode, S3Request, StartDecommission, StatusDecommission, StatusPool, Uri,
|
||||||
StatusDecommission, StatusPool, Uri, contextualize_admin_pool_api_error,
|
contextualize_admin_pool_api_error, decommission_admin_not_initialized_error_with_audit, decommission_peer_target,
|
||||||
decommission_admin_not_initialized_error_with_audit, decommission_peer_target, decommission_start_api_error,
|
|
||||||
has_duplicate_indices, parse_mutation_pool_query, parse_pool_idx_by_id, parse_status_pool_query,
|
has_duplicate_indices, parse_mutation_pool_query, parse_pool_idx_by_id, parse_status_pool_query,
|
||||||
pool_admin_missing_credentials_error, pool_admin_missing_credentials_error_with_request,
|
pool_admin_missing_credentials_error, pool_admin_missing_credentials_error_with_request,
|
||||||
pool_admin_pool_index_error_with_audit, pool_admin_pool_not_found_error_with_audit,
|
pool_admin_pool_index_error_with_audit, pool_admin_pool_not_found_error_with_audit,
|
||||||
@@ -1239,21 +1209,6 @@ mod pools_handler_tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_decommission_start_api_error_preserves_fleet_proof_retry_marker() {
|
|
||||||
let err = crate::storage_api::error::StorageError::other(POOL_ACTIVATION_FLEET_PROOF_REQUIRED);
|
|
||||||
|
|
||||||
let err = decommission_start_api_error(err);
|
|
||||||
|
|
||||||
assert_eq!(err.code, s3s::S3ErrorCode::InternalError);
|
|
||||||
assert_eq!(err.message, POOL_ACTIVATION_FLEET_PROOF_REQUIRED);
|
|
||||||
assert!(err.source.is_some());
|
|
||||||
|
|
||||||
let unrelated = decommission_start_api_error(crate::storage_api::error::StorageError::other("disk read failed"));
|
|
||||||
assert_eq!(unrelated.code, s3s::S3ErrorCode::InternalError);
|
|
||||||
assert_eq!(unrelated.message, "We encountered an internal error, please try again.");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_contextualize_admin_pool_api_error_preserves_source() {
|
fn test_contextualize_admin_pool_api_error_preserves_source() {
|
||||||
let err = contextualize_admin_pool_api_error(
|
let err = contextualize_admin_pool_api_error(
|
||||||
|
|||||||
@@ -417,7 +417,7 @@ pub(crate) mod ecstore_bucket {
|
|||||||
pub(crate) mod ecstore_capacity {
|
pub(crate) mod ecstore_capacity {
|
||||||
pub(crate) use rustfs_ecstore::api::capacity::{
|
pub(crate) use rustfs_ecstore::api::capacity::{
|
||||||
DecommissionUnresolvedEntry, PoolDecommissionInfo, PoolStatus, get_total_usable_capacity, get_total_usable_capacity_free,
|
DecommissionUnresolvedEntry, PoolDecommissionInfo, PoolStatus, get_total_usable_capacity, get_total_usable_capacity_free,
|
||||||
is_pool_activation_fleet_proof_error, is_reserved_or_invalid_bucket,
|
is_reserved_or_invalid_bucket,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,8 +18,6 @@
|
|||||||
use rustfs_storage_api as storage_contracts;
|
use rustfs_storage_api as storage_contracts;
|
||||||
|
|
||||||
pub(crate) mod capacity {
|
pub(crate) mod capacity {
|
||||||
pub(crate) use crate::storage::storage_api::ecstore_capacity::is_pool_activation_fleet_proof_error;
|
|
||||||
|
|
||||||
pub(crate) mod service {
|
pub(crate) mod service {
|
||||||
pub(crate) use crate::storage::storage_api::{all_local_disk, disk_drive_path, disk_endpoint};
|
pub(crate) use crate::storage::storage_api::{all_local_disk, disk_drive_path, disk_endpoint};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"bytes": "eyJmb3JtYXRWZXJzaW9uIjoicnVzdGZzLmNvbm5lY3Qub2ZmbGluZS5lbnJvbGxtZW50Q2hhbGxlbmdlLzEiLCJwcm90b2NvbFZlcnNpb24iOiJ2MSIsImNoYWxsZW5nZUlkIjoiMDE4ZjdlNmQtOWQ2YS03ZDkzLThmNjQtOGIyMGIzMzg0NzEyIiwib3JnYW5pemF0aW9uTmFtZSI6Im9yZ2FuaXphdGlvbnMvMDE4ZjdlNmQtOWQ2YS03ZDkzLThmNjQtOGIyMGIzMzg0NzEzIiwiY2x1c3Rlck5hbWUiOiJvcmdhbml6YXRpb25zLzAxOGY3ZTZkLTlkNmEtN2Q5My04ZjY0LThiMjBiMzM4NDcxMy9jbHVzdGVycy8wMThmN2U2ZC05ZDZhLTdkOTMtOGY2NC04YjIwYjMzODQ3MTQiLCJub25jZSI6InBLU2twS1NrcEtTa3BLU2twS1NrcEtTa3BLU2twS1NrcEtTa3BLU2twS1EiLCJpc3N1ZWRBdCI6IjIwOTktMDEtMDFUMDA6MDA6MDBaIiwiZXhwaXJlc0F0IjoiMjA5OS0wMS0wOFQwMDowMDowMFoiLCJjb25uZWN0S2V5SWQiOiIwNjA3NWY0ODRkY2U1YzA3NDVjYTc2NWE4ODk5MzA5YmQ3MTc2MTI5NDdhMzc3MGEwZDI3YjhjY2I4YmY5MDUyIiwidHJ1c3RDaGFpbiI6W3siYnl0ZXMiOiJleUptYjNKdFlYUldaWEp6YVc5dUlqb2ljblZ6ZEdaekxtTnZibTVsWTNRdWIyWm1iR2x1WlM1MGNuVnpkRXhwYm1zdk1TSXNJbkJ5YjNSdlkyOXNWbVZ5YzJsdmJpSTZJbll4SWl3aWMyVnlhV0ZzSWpvaVpUQTBZVEF3TURBd01EQXdNREF3TURBd01EQXdNREF3TURBd01EQXdNREVpTENKeWIyeGxJam9pYVc1MFpYSnRaV1JwWVhSbElpd2lhWE56ZFdWeVMyVjVTV1FpT2lJNVlUVmpNemcxWVdKa09UZGpOMlppT0RSak5UUXdZalZtTldVME1tUTNPVGt4T1RNd1lUUTBOMk01TURJMk56azVaVGhtWkRSak5ESXpNR0kxWXpOaklpd2ljM1ZpYW1WamRFdGxlVWxrSWpvaVlUazFOVGxpWkRSbE1EazBPV0ZqWXpFeU1tRm1abU0xTldVMlpHSTRaVGt4Wmpoa01EazNaVFUxWldNNE9UbGtZVFl4T1RGbE5EWTVZelE0T0RKaE1pSXNJbk4xWW1wbFkzUlFkV0pzYVdOTFpYa2lPaUpDVG13elZFeDFTazV0Tld4NFRGUmFNRGxUWVdwWVRHMUZSM0ZqZHpGaVQyZzROVWhEYmpWdVVUazJWVlZUYUZVNFZHeEhVVWsxYmxaSldWUnJRWFpLYjFWRVMwWmhVVlp0WVZGVk9WRkhaemsyVDJ0RU1EUWlMQ0p1YjNSQ1pXWnZjbVVpT2lJeU1ESXdMVEF4TFRBeFZEQXdPakF3T2pBd1dpSXNJbTV2ZEVGbWRHVnlJam9pTWpBNU9TMHdNUzB3TVZRd01Eb3dNRG93TUZvaWZRPT0iLCJzaWduYXR1cmUiOnsiYWxnb3JpdGhtIjoiRVMyNTYiLCJrZXlJZCI6IjlhNWMzODVhYmQ5N2M3ZmI4NGM1NDBiNWY1ZTQyZDc5OTE5MzBhNDQ3YzkwMjY3OTllOGZkNGM0MjMwYjVjM2MiLCJ2YWx1ZSI6IklUSThKVGFURjRoRHJ0bF9tSk0zYmZ0eUlhMlJaSjFNNVpPVk1xaEE2cVJSSzFNcEcxQlF0emRRVzB6bHo4eG1RZUJNWl84clViTUlFcnFBel8tSWZRIn19LHsiYnl0ZXMiOiJleUptYjNKdFlYUldaWEp6YVc5dUlqb2ljblZ6ZEdaekxtTnZibTVsWTNRdWIyWm1iR2x1WlM1MGNuVnpkRXhwYm1zdk1TSXNJbkJ5YjNSdlkyOXNWbVZ5YzJsdmJpSTZJbll4SWl3aWMyVnlhV0ZzSWpvaVpUQTBZVEF3TURBd01EQXdNREF3TURBd01EQXdNREF3TURBd01EQXdNRElpTENKeWIyeGxJam9pYzJsbmJtbHVaeUlzSW1semMzVmxja3RsZVVsa0lqb2lZVGsxTlRsaVpEUmxNRGswT1dGall6RXlNbUZtWm1NMU5XVTJaR0k0WlRreFpqaGtNRGszWlRVMVpXTTRPVGxrWVRZeE9URmxORFk1WXpRNE9ESmhNaUlzSW5OMVltcGxZM1JMWlhsSlpDSTZJakEyTURjMVpqUTROR1JqWlRWak1EYzBOV05oTnpZMVlUZzRPVGt6TURsaVpEY3hOell4TWprME4yRXpOemN3WVRCa01qZGlPR05qWWpoaVpqa3dOVElpTENKemRXSnFaV04wVUhWaWJHbGpTMlY1SWpvaVFrRk9lWFpITFdkR1YwdFRaM0pMWTNkUVpGUmhNRWN3TTBKdlVtRkNSbWhvZG10cWRFUjZlVk5tYm5weFYxcHROa2xLV0U1RWRVZEdlVXBFZVZWSmNYZzJSa1p5TlZSV2NsOXVhbUZCYzFWb2FEbE1VMlJ2SWl3aWJtOTBRbVZtYjNKbElqb2lNakF5TUMwd01TMHdNVlF3TURvd01Eb3dNRm9pTENKdWIzUkJablJsY2lJNklqSXdPVGt0TURFdE1ERlVNREE2TURBNk1EQmFJbjA9Iiwic2lnbmF0dXJlIjp7ImFsZ29yaXRobSI6IkVTMjU2Iiwia2V5SWQiOiJhOTU1OWJkNGUwOTQ5YWNjMTIyYWZmYzU1ZTZkYjhlOTFmOGQwOTdlNTVlYzg5OWRhNjE5MWU0NjljNDg4MmEyIiwidmFsdWUiOiI4MTVrVGNMY1hkZXZORFRia1dBck1KSnpORTVmaEdxbTNUb3hTM3Exdl9ZQkRVcmFieldmTFhjMEc5TjZiVXZFeEd3WEJUMVFpVzJvUDBCM3JKUS0ydyJ9fV19",
|
"bytes": "eyJjaGFsbGVuZ2VJZCI6IjAxOGY3ZTZkLTlkNmEtN2Q5My04ZjY0LThiMjBiMzM4NDcxMiIsImNsdXN0ZXJOYW1lIjoib3JnYW5pemF0aW9ucy8wMThmN2U2ZC05ZDZhLTdkOTMtOGY2NC04YjIwYjMzODQ3MTMvY2x1c3RlcnMvMDE4ZjdlNmQtOWQ2YS03ZDkzLThmNjQtOGIyMGIzMzg0NzE0IiwiY29ubmVjdEtleUlkIjoiZGY4MmNlNjA4MGIwZWZkMDhkNGFlNjNhMjI0NGZmNmNiZWE5YTU0NzUyNjhjZGFkZTMzNzEyMmVjYzY3ZjJhNiIsImV4cGlyZXNBdCI6IjIwOTktMDEtMDhUMDA6MDA6MDBaIiwiZm9ybWF0VmVyc2lvbiI6InJ1c3Rmcy5jb25uZWN0Lm9mZmxpbmUuZW5yb2xsbWVudENoYWxsZW5nZS8xIiwiaXNzdWVkQXQiOiIyMDk5LTAxLTAxVDAwOjAwOjAwWiIsIm5vbmNlIjoicEtTa3BLU2twS1NrcEtTa3BLU2twS1NrcEtTa3BLU2twS1NrcEtTa3BLUSIsIm9yZ2FuaXphdGlvbk5hbWUiOiJvcmdhbml6YXRpb25zLzAxOGY3ZTZkLTlkNmEtN2Q5My04ZjY0LThiMjBiMzM4NDcxMyIsInByb3RvY29sVmVyc2lvbiI6InYxIiwidHJ1c3RDaGFpbiI6W3siYnl0ZXMiOiJleUptYjNKdFlYUldaWEp6YVc5dUlqb2ljblZ6ZEdaekxtTnZibTVsWTNRdWIyWm1iR2x1WlM1MGNuVnpkRXhwYm1zdk1TSXNJbkJ5YjNSdlkyOXNWbVZ5YzJsdmJpSTZJbll4SWl3aWMyVnlhV0ZzSWpvaVpUQTBZVEF3TURBd01EQXdNREF3TURBd01EQXdNREF3TURBd01EQXdNREVpTENKeWIyeGxJam9pYVc1MFpYSnRaV1JwWVhSbElpd2lhWE56ZFdWeVMyVjVTV1FpT2lKbU9EVTNZV1UwWldRMlpUTTBaVE16TnpZeFlXVmhNalZqWVdGbFpUTm1aVFUwWVRFMU9UWXdabUk1TW1SalpEWXpZVE0zTldGaU1USXhaR1ZpTW1FNUlpd2ljM1ZpYW1WamRFdGxlVWxrSWpvaU5XRXdOMkUzTWpOak56azFOamd6TUdGbE1tVTJZbVV3WldZM01XSXpPVGt4TVRZeVpqVmxZVFF5WkRKa05UUmlPRFk1WTJZeU1UWTNNelJrTnpoa015SXNJbk4xWW1wbFkzUlFkV0pzYVdOTFpYa2lPaUpDUmxWUVVuaEJSRGc1TFZoM09UbFJZWE5sV0RsdVNXWnpZVWczWlRRNWRtYzVTV3RUV1hCc2VVazBhMFV5UTFReGQwVjFWVXB3ZW1OV2VUbERkME5xZWtGZk1IUmpRV0pRWDI5YVlYSklOMDF1UVRKMVQxa2lMQ0p1YjNSQ1pXWnZjbVVpT2lJeU1EazRMVEV5TFRBeFZEQXdPakF3T2pBd1dpSXNJbTV2ZEVGbWRHVnlJam9pTWpBNU9TMHhNUzB6TUZRd01Eb3dNRG93TUZvaWZRPT0iLCJzaWduYXR1cmUiOnsiYWxnb3JpdGhtIjoiRVMyNTYiLCJrZXlJZCI6ImY4NTdhZTRlZDZlMzRlMzM3NjFhZWEyNWNhYWVlM2ZlNTRhMTU5NjBmYjkyZGNkNjNhMzc1YWIxMjFkZWIyYTkiLCJ2YWx1ZSI6IlhzbjVaRkI4OHU1bHg1TDU5UDJCWlNLMWNrTVc5ekpiNGFYUmNfdjB5cFIzd1pxc3BlTzJCNzZyV1V0RnhDRE9Vek9GdHFDZlFMRi1McWNsLWE5dFhRIn19LHsiYnl0ZXMiOiJleUptYjNKdFlYUldaWEp6YVc5dUlqb2ljblZ6ZEdaekxtTnZibTVsWTNRdWIyWm1iR2x1WlM1MGNuVnpkRXhwYm1zdk1TSXNJbkJ5YjNSdlkyOXNWbVZ5YzJsdmJpSTZJbll4SWl3aWMyVnlhV0ZzSWpvaVpUQTBZVEF3TURBd01EQXdNREF3TURBd01EQXdNREF3TURBd01EQXdNRElpTENKeWIyeGxJam9pYzJsbmJtbHVaeUlzSW1semMzVmxja3RsZVVsa0lqb2lOV0V3TjJFM01qTmpOemsxTmpnek1HRmxNbVUyWW1Vd1pXWTNNV0l6T1RreE1UWXlaalZsWVRReVpESmtOVFJpT0RZNVkyWXlNVFkzTXpSa056aGtNeUlzSW5OMVltcGxZM1JMWlhsSlpDSTZJbVJtT0RKalpUWXdPREJpTUdWbVpEQTRaRFJoWlRZellUSXlORFJtWmpaalltVmhPV0UxTkRjMU1qWTRZMlJoWkdVek16Y3hNakpsWTJNMk4yWXlZVFlpTENKemRXSnFaV04wVUhWaWJHbGpTMlY1SWpvaVFrWnJZWFF6U0hKMlVERjBia3hyU2xSU1FteExTek5TY0hBeFJYZHpTREpLWDBOS04wWnBOWGhvY21adU1EVnhkbmN3UlZoQmVIQlBhbmh2Y2xoNVdIbHVTeTFhVGpjd2IyMWZjekJ0VUdSdFMydHVaMUJCSWl3aWJtOTBRbVZtYjNKbElqb2lNakE1T0MweE1pMHhOVlF3TURvd01Eb3dNRm9pTENKdWIzUkJablJsY2lJNklqSXdPVGt0TURFdE1UVlVNREE2TURBNk1EQmFJbjA9Iiwic2lnbmF0dXJlIjp7ImFsZ29yaXRobSI6IkVTMjU2Iiwia2V5SWQiOiI1YTA3YTcyM2M3OTU2ODMwYWUyZTZiZTBlZjcxYjM5OTExNjJmNWVhNDJkMmQ1NGI4NjljZjIxNjczNGQ3OGQzIiwidmFsdWUiOiJSUGJHWEt4RVRRRDZKVklEVmcwNkRRaENCQ0NfYjJkay1oZTdVUjZOeXJ0bVlQRUEzb3RhM0hXd25YdUpnWG84TlVWbnF2Q2ZldkNQNGFFelVSbEdaQSJ9fV19",
|
||||||
"signature": {
|
"signature": {
|
||||||
"algorithm": "ES256",
|
"algorithm": "ES256",
|
||||||
"keyId": "06075f484dce5c0745ca765a8899309bd717612947a3770a0d27b8ccb8bf9052",
|
"keyId": "df82ce6080b0efd08d4ae63a2244ff6cbea9a5475268cdade337122ecc67f2a6",
|
||||||
"value": "8i2nvYhNsZbL1UPF82Otr4pcecYfKhdRV1Q7m3Geqcx-TdvYk486Q_cZHSQ7OaqnIhTZwPgMYFYKUuEhwAaYEQ"
|
"value": "m83S9i09JTlxGnhAdnmawYxkM75u_v8F2-5ygK374fs-d0vWh6L_j_yMDS3B29CrViPVjo3FQKaGutw4MDI_LQ"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -1,4 +1,4 @@
|
|||||||
{
|
{
|
||||||
"keyId": "9a5c385abd97c7fb84c540b5f5e42d7991930a447c9026799e8fd4c4230b5c3c",
|
"keyId": "f857ae4ed6e34e33761aea25caaee3fe54a15960fb92dcd63a375ab121deb2a9",
|
||||||
"publicKey": "BIPyiA1W2NDuy3ftHLtlY2tO2WNjkjGINZ_9QQvyyN9syzbMb91QYG2SN0AqZPylFsTL-loF4M1tVySZtXJpKhM"
|
"publicKey": "BG_wO5SSQc4drdQ1GeaWDgqFtBppoFwygQOqK84VlMoWPE91OlW_AdxT9sCwx-7ni0DG_30lqW4igrmJzvccFEo"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
[{"bytes":"eyJmb3JtYXRWZXJzaW9uIjoicnVzdGZzLmNvbm5lY3Qub2ZmbGluZS50cnVzdExpbmsvMSIsInByb3RvY29sVmVyc2lvbiI6InYxIiwic2VyaWFsIjoiZTA0YTAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDEiLCJyb2xlIjoiaW50ZXJtZWRpYXRlIiwiaXNzdWVyS2V5SWQiOiI5YTVjMzg1YWJkOTdjN2ZiODRjNTQwYjVmNWU0MmQ3OTkxOTMwYTQ0N2M5MDI2Nzk5ZThmZDRjNDIzMGI1YzNjIiwic3ViamVjdEtleUlkIjoiYTk1NTliZDRlMDk0OWFjYzEyMmFmZmM1NWU2ZGI4ZTkxZjhkMDk3ZTU1ZWM4OTlkYTYxOTFlNDY5YzQ4ODJhMiIsInN1YmplY3RQdWJsaWNLZXkiOiJCTmwzVEx1Sk5tNWx4TFRaMDlTYWpYTG1FR3FjdzFiT2g4NUhDbjVuUTk2VVVTaFU4VGxHUUk1blZJWVRrQXZKb1VES0ZhUVZtYVFVOVFHZzk2T2tEMDQiLCJub3RCZWZvcmUiOiIyMDIwLTAxLTAxVDAwOjAwOjAwWiIsIm5vdEFmdGVyIjoiMjA5OS0wMS0wMVQwMDowMDowMFoifQ==","signature":{"algorithm":"ES256","keyId":"9a5c385abd97c7fb84c540b5f5e42d7991930a447c9026799e8fd4c4230b5c3c","value":"ITI8JTaTF4hDrtl_mJM3bftyIa2RZJ1M5ZOVMqhA6qRRK1MpG1BQtzdQW0zlz8xmQeBMZ_8rUbMIErqAz_-IfQ"}},{"bytes":"eyJmb3JtYXRWZXJzaW9uIjoicnVzdGZzLmNvbm5lY3Qub2ZmbGluZS50cnVzdExpbmsvMSIsInByb3RvY29sVmVyc2lvbiI6InYxIiwic2VyaWFsIjoiZTA0YTAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDIiLCJyb2xlIjoic2lnbmluZyIsImlzc3VlcktleUlkIjoiYTk1NTliZDRlMDk0OWFjYzEyMmFmZmM1NWU2ZGI4ZTkxZjhkMDk3ZTU1ZWM4OTlkYTYxOTFlNDY5YzQ4ODJhMiIsInN1YmplY3RLZXlJZCI6IjA2MDc1ZjQ4NGRjZTVjMDc0NWNhNzY1YTg4OTkzMDliZDcxNzYxMjk0N2EzNzcwYTBkMjdiOGNjYjhiZjkwNTIiLCJzdWJqZWN0UHVibGljS2V5IjoiQkFOeXZHLWdGV0tTZ3JLY3dQZFRhMEcwM0JvUmFCRmhodmtqdER6eVNmbnpxV1ptNklKWE5EdUdGeUpEeVVJcXg2RkZyNVRWcl9uamFBc1VoaDlMU2RvIiwibm90QmVmb3JlIjoiMjAyMC0wMS0wMVQwMDowMDowMFoiLCJub3RBZnRlciI6IjIwOTktMDEtMDFUMDA6MDA6MDBaIn0=","signature":{"algorithm":"ES256","keyId":"a9559bd4e0949acc122affc55e6db8e91f8d097e55ec899da6191e469c4882a2","value":"815kTcLcXdevNDTbkWArMJJzNE5fhGqm3ToxS3q1v_YBDUrabzWfLXc0G9N6bUvExGwXBT1QiW2oP0B3rJQ-2w"}}]
|
[{"bytes":"eyJmb3JtYXRWZXJzaW9uIjoicnVzdGZzLmNvbm5lY3Qub2ZmbGluZS50cnVzdExpbmsvMSIsInByb3RvY29sVmVyc2lvbiI6InYxIiwic2VyaWFsIjoiZTA0YTAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDEiLCJyb2xlIjoiaW50ZXJtZWRpYXRlIiwiaXNzdWVyS2V5SWQiOiJmODU3YWU0ZWQ2ZTM0ZTMzNzYxYWVhMjVjYWFlZTNmZTU0YTE1OTYwZmI5MmRjZDYzYTM3NWFiMTIxZGViMmE5Iiwic3ViamVjdEtleUlkIjoiNWEwN2E3MjNjNzk1NjgzMGFlMmU2YmUwZWY3MWIzOTkxMTYyZjVlYTQyZDJkNTRiODY5Y2YyMTY3MzRkNzhkMyIsInN1YmplY3RQdWJsaWNLZXkiOiJCRlVQUnhBRDg5LVh3OTlRYXNlWDluSWZzYUg3ZTQ5dmc5SWtTWXBseUk0a0UyQ1Qxd0V1VUpwemNWeTlDd0NqekFfMHRjQWJQX29aYXJIN01uQTJ1T1kiLCJub3RCZWZvcmUiOiIyMDk4LTEyLTAxVDAwOjAwOjAwWiIsIm5vdEFmdGVyIjoiMjA5OS0xMS0zMFQwMDowMDowMFoifQ==","signature":{"algorithm":"ES256","keyId":"f857ae4ed6e34e33761aea25caaee3fe54a15960fb92dcd63a375ab121deb2a9","value":"Xsn5ZFB88u5lx5L59P2BZSK1ckMW9zJb4aXRc_v0ypR3wZqspeO2B76rWUtFxCDOUzOFtqCfQLF-Lqcl-a9tXQ"}},{"bytes":"eyJmb3JtYXRWZXJzaW9uIjoicnVzdGZzLmNvbm5lY3Qub2ZmbGluZS50cnVzdExpbmsvMSIsInByb3RvY29sVmVyc2lvbiI6InYxIiwic2VyaWFsIjoiZTA0YTAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDIiLCJyb2xlIjoic2lnbmluZyIsImlzc3VlcktleUlkIjoiNWEwN2E3MjNjNzk1NjgzMGFlMmU2YmUwZWY3MWIzOTkxMTYyZjVlYTQyZDJkNTRiODY5Y2YyMTY3MzRkNzhkMyIsInN1YmplY3RLZXlJZCI6ImRmODJjZTYwODBiMGVmZDA4ZDRhZTYzYTIyNDRmZjZjYmVhOWE1NDc1MjY4Y2RhZGUzMzcxMjJlY2M2N2YyYTYiLCJzdWJqZWN0UHVibGljS2V5IjoiQkZrYXQzSHJ2UDF0bkxrSlRSQmxLSzNScHAxRXdzSDJKX0NKN0ZpNXhocmZuMDVxdncwRVhBeHBPanhvclh5WHluSy1aTjcwb21fczBtUGRtS2tuZ1BBIiwibm90QmVmb3JlIjoiMjA5OC0xMi0xNVQwMDowMDowMFoiLCJub3RBZnRlciI6IjIwOTktMDEtMTVUMDA6MDA6MDBaIn0=","signature":{"algorithm":"ES256","keyId":"5a07a723c7956830ae2e6be0ef71b3991162f5ea42d2d54b869cf216734d78d3","value":"RPbGXKxETQD6JVIDVg06DQhCBCC_b2dk-he7UR6NyrtmYPEA3ota3HWwnXuJgXo8NUVnqvCfevCP4aEzURlGZA"}}]
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
module rustfs.local/heal-outcome-compat
|
module rustfs.local/heal-outcome-compat
|
||||||
|
|
||||||
go 1.24.0
|
go 1.25.0
|
||||||
|
|
||||||
require github.com/minio/madmin-go/v3 v3.0.107-0.20250415152934-4b504b82db63
|
require github.com/minio/madmin-go/v3 v3.0.107-0.20250415152934-4b504b82db63
|
||||||
|
|
||||||
@@ -8,27 +8,35 @@ require (
|
|||||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||||
github.com/go-ini/ini v1.67.0 // indirect
|
github.com/go-ini/ini v1.67.0 // indirect
|
||||||
|
github.com/go-ole/go-ole v1.3.0 // indirect
|
||||||
github.com/goccy/go-json v0.10.5 // indirect
|
github.com/goccy/go-json v0.10.5 // indirect
|
||||||
github.com/golang-jwt/jwt/v4 v4.5.2 // indirect
|
github.com/golang-jwt/jwt/v4 v4.5.2 // indirect
|
||||||
github.com/golang/protobuf v1.5.4 // indirect
|
github.com/golang/protobuf v1.5.4 // indirect
|
||||||
|
github.com/klauspost/cpuid/v2 v2.2.10 // indirect
|
||||||
|
github.com/lufia/plan9stats v0.0.0-20250317134145-8bc96cf8fc35 // indirect
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
||||||
github.com/minio/md5-simd v1.1.2 // indirect
|
github.com/minio/md5-simd v1.1.2 // indirect
|
||||||
github.com/minio/minio-go/v7 v7.0.90 // indirect
|
github.com/minio/minio-go/v7 v7.0.90 // indirect
|
||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||||
github.com/philhofer/fwd v1.1.3-0.20240916144458-20a13a1f6b7c // indirect
|
github.com/philhofer/fwd v1.1.3-0.20240916144458-20a13a1f6b7c // indirect
|
||||||
|
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
|
||||||
github.com/prometheus/client_model v0.6.2 // indirect
|
github.com/prometheus/client_model v0.6.2 // indirect
|
||||||
github.com/prometheus/common v0.63.0 // indirect
|
github.com/prometheus/common v0.63.0 // indirect
|
||||||
github.com/prometheus/procfs v0.16.0 // indirect
|
github.com/prometheus/procfs v0.16.0 // indirect
|
||||||
github.com/prometheus/prom2json v1.4.2 // indirect
|
github.com/prometheus/prom2json v1.4.2 // indirect
|
||||||
github.com/prometheus/prometheus v0.303.0 // indirect
|
github.com/prometheus/prometheus v0.303.0 // indirect
|
||||||
github.com/rs/xid v1.6.0 // indirect
|
github.com/rs/xid v1.6.0 // indirect
|
||||||
|
github.com/safchain/ethtool v0.5.10 // indirect
|
||||||
github.com/secure-io/sio-go v0.3.1 // indirect
|
github.com/secure-io/sio-go v0.3.1 // indirect
|
||||||
github.com/shirou/gopsutil/v3 v3.24.5 // indirect
|
github.com/shirou/gopsutil/v3 v3.24.5 // indirect
|
||||||
github.com/shoenig/go-m1cpu v0.1.6 // indirect
|
github.com/shoenig/go-m1cpu v0.1.6 // indirect
|
||||||
github.com/tinylib/msgp v1.2.5 // indirect
|
github.com/tinylib/msgp v1.2.5 // indirect
|
||||||
github.com/tklauser/go-sysconf v0.3.15 // indirect
|
github.com/tklauser/go-sysconf v0.3.15 // indirect
|
||||||
golang.org/x/crypto v0.37.0 // indirect
|
github.com/tklauser/numcpus v0.10.0 // indirect
|
||||||
golang.org/x/net v0.39.0 // indirect
|
github.com/yusufpapurcu/wmi v1.2.4 // indirect
|
||||||
golang.org/x/sys v0.32.0 // indirect
|
golang.org/x/crypto v0.52.0 // indirect
|
||||||
|
golang.org/x/net v0.55.0 // indirect
|
||||||
|
golang.org/x/sync v0.13.0 // indirect
|
||||||
|
golang.org/x/sys v0.45.0 // indirect
|
||||||
google.golang.org/protobuf v1.36.6 // indirect
|
google.golang.org/protobuf v1.36.6 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,9 +1,14 @@
|
|||||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
|
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||||
|
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||||
github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A=
|
github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A=
|
||||||
github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
|
github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
|
||||||
|
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||||
|
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
|
||||||
|
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
|
||||||
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
|
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
|
||||||
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||||
github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI=
|
github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI=
|
||||||
@@ -11,7 +16,13 @@ github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w
|
|||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||||
|
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||||
|
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||||
github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||||
|
github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE=
|
||||||
|
github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
|
||||||
|
github.com/lufia/plan9stats v0.0.0-20250317134145-8bc96cf8fc35 h1:PpXWgLPs+Fqr325bN2FD2ISlRRztXibcX6e8f5FR5Dc=
|
||||||
|
github.com/lufia/plan9stats v0.0.0-20250317134145-8bc96cf8fc35/go.mod h1:autxFIvghDt3jPTLoqZ9OZ7s9qTGNAWmYCjVFWPX/zg=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
|
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
|
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
|
||||||
github.com/minio/madmin-go/v3 v3.0.107-0.20250415152934-4b504b82db63 h1:ktN/FrMuM9sjvjIbPZYRKeHEzBDOXQdpYUDiNO0CutE=
|
github.com/minio/madmin-go/v3 v3.0.107-0.20250415152934-4b504b82db63 h1:ktN/FrMuM9sjvjIbPZYRKeHEzBDOXQdpYUDiNO0CutE=
|
||||||
@@ -24,6 +35,10 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq
|
|||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||||
github.com/philhofer/fwd v1.1.3-0.20240916144458-20a13a1f6b7c h1:dAMKvw0MlJT1GshSTtih8C2gDs04w8dReiOGXrGLNoY=
|
github.com/philhofer/fwd v1.1.3-0.20240916144458-20a13a1f6b7c h1:dAMKvw0MlJT1GshSTtih8C2gDs04w8dReiOGXrGLNoY=
|
||||||
github.com/philhofer/fwd v1.1.3-0.20240916144458-20a13a1f6b7c/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM=
|
github.com/philhofer/fwd v1.1.3-0.20240916144458-20a13a1f6b7c/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||||
|
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU=
|
||||||
|
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||||
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
||||||
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||||
github.com/prometheus/common v0.63.0 h1:YR/EIY1o3mEFP/kZCD7iDMnLPlGyuU2Gb3HIcXnA98k=
|
github.com/prometheus/common v0.63.0 h1:YR/EIY1o3mEFP/kZCD7iDMnLPlGyuU2Gb3HIcXnA98k=
|
||||||
@@ -36,29 +51,47 @@ github.com/prometheus/prometheus v0.303.0 h1:wsNNsbd4EycMCphYnTmNY9JASBVbp7NWwJn
|
|||||||
github.com/prometheus/prometheus v0.303.0/go.mod h1:8PMRi+Fk1WzopMDeb0/6hbNs9nV6zgySkU/zds5Lu3o=
|
github.com/prometheus/prometheus v0.303.0/go.mod h1:8PMRi+Fk1WzopMDeb0/6hbNs9nV6zgySkU/zds5Lu3o=
|
||||||
github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU=
|
github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU=
|
||||||
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
|
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
|
||||||
|
github.com/safchain/ethtool v0.5.10 h1:Im294gZtuf4pSGJRAOGKaASNi3wMeFaGaWuSaomedpc=
|
||||||
|
github.com/safchain/ethtool v0.5.10/go.mod h1:w9jh2Lx7YBR4UwzLkzCmWl85UY0W2uZdd7/DckVE5+c=
|
||||||
github.com/secure-io/sio-go v0.3.1 h1:dNvY9awjabXTYGsTF1PiCySl9Ltofk9GA3VdWlo7rRc=
|
github.com/secure-io/sio-go v0.3.1 h1:dNvY9awjabXTYGsTF1PiCySl9Ltofk9GA3VdWlo7rRc=
|
||||||
github.com/secure-io/sio-go v0.3.1/go.mod h1:+xbkjDzPjwh4Axd07pRKSNriS9SCiYksWnZqdnfpQxs=
|
github.com/secure-io/sio-go v0.3.1/go.mod h1:+xbkjDzPjwh4Axd07pRKSNriS9SCiYksWnZqdnfpQxs=
|
||||||
github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/iZ9pI=
|
github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/iZ9pI=
|
||||||
github.com/shirou/gopsutil/v3 v3.24.5/go.mod h1:bsoOS1aStSs9ErQ1WWfxllSeS1K5D+U30r2NfcubMVk=
|
github.com/shirou/gopsutil/v3 v3.24.5/go.mod h1:bsoOS1aStSs9ErQ1WWfxllSeS1K5D+U30r2NfcubMVk=
|
||||||
github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
|
github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
|
||||||
github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
|
github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
|
||||||
|
github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU=
|
||||||
|
github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k=
|
||||||
|
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||||
|
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
github.com/tinylib/msgp v1.2.5 h1:WeQg1whrXRFiZusidTQqzETkRpGjFjcIhW6uqWH09po=
|
github.com/tinylib/msgp v1.2.5 h1:WeQg1whrXRFiZusidTQqzETkRpGjFjcIhW6uqWH09po=
|
||||||
github.com/tinylib/msgp v1.2.5/go.mod h1:ykjzy2wzgrlvpDCRc4LA8UXy6D8bzMSuAF3WD57Gok0=
|
github.com/tinylib/msgp v1.2.5/go.mod h1:ykjzy2wzgrlvpDCRc4LA8UXy6D8bzMSuAF3WD57Gok0=
|
||||||
github.com/tklauser/go-sysconf v0.3.15 h1:VE89k0criAymJ/Os65CSn1IXaol+1wrsFHEB8Ol49K4=
|
github.com/tklauser/go-sysconf v0.3.15 h1:VE89k0criAymJ/Os65CSn1IXaol+1wrsFHEB8Ol49K4=
|
||||||
github.com/tklauser/go-sysconf v0.3.15/go.mod h1:Dmjwr6tYFIseJw7a3dRLJfsHAMXZ3nEnL/aZY+0IuI4=
|
github.com/tklauser/go-sysconf v0.3.15/go.mod h1:Dmjwr6tYFIseJw7a3dRLJfsHAMXZ3nEnL/aZY+0IuI4=
|
||||||
|
github.com/tklauser/numcpus v0.10.0 h1:18njr6LDBk1zuna922MgdjQuJFjrdppsZG60sHGfjso=
|
||||||
|
github.com/tklauser/numcpus v0.10.0/go.mod h1:BiTKazU708GQTYF4mB+cmlpT2Is1gLk7XVuEeem8LsQ=
|
||||||
|
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
|
||||||
|
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
|
golang.org/x/crypto v0.52.0 h1:RMs7fP2rXdep0CftQlK8Uf+kibLm7qkCcradZWYz988=
|
||||||
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
|
golang.org/x/crypto v0.52.0/go.mod h1:1QgfPxDqh0T2M/elOJtp9RvuR95kVjir0e6/BvEmGbc=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY=
|
golang.org/x/net v0.55.0 h1:bcvxaJn3e1U6InsFWt1JUq1aSjnRxLzT2rtD2KfkDF8=
|
||||||
golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E=
|
golang.org/x/net v0.55.0/go.mod h1:L5U2KuzuOe1lY7Z+aWVIKK6qEeJXnXV9yzGA+WCHJww=
|
||||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
|
||||||
|
golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
|
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
golang.org/x/sys v0.45.0 h1:dO4czNzziLiiXplLQgBCEpCvXQ3dnkn0SdaZSYdQ+FY=
|
||||||
|
golang.org/x/sys v0.45.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
||||||
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
|||||||
Reference in New Issue
Block a user