aboutsummaryrefslogtreecommitdiff
path: root/src/garage/admin
diff options
context:
space:
mode:
authorAlex Auvolat <alex@adnab.me>2024-02-13 11:24:56 +0100
committerAlex Auvolat <alex@adnab.me>2024-02-13 11:36:28 +0100
commitcf2af186fcc0c8f581a966454b6cd4720d3821f0 (patch)
tree37a978ba9ffb780fc828cff7b8ec93662d50884f /src/garage/admin
parentdb48dd3d6c1f9e86a62e9b8edfce2c1620bcd5f3 (diff)
parent823078b4cdaf93e09de0847c5eaa75beb7b26b7f (diff)
downloadgarage-cf2af186fcc0c8f581a966454b6cd4720d3821f0.tar.gz
garage-cf2af186fcc0c8f581a966454b6cd4720d3821f0.zip
Merge branch 'main' into next-0.10
Diffstat (limited to 'src/garage/admin')
-rw-r--r--src/garage/admin/block.rs47
1 files changed, 45 insertions, 2 deletions
diff --git a/src/garage/admin/block.rs b/src/garage/admin/block.rs
index c4a45738..edeb88c0 100644
--- a/src/garage/admin/block.rs
+++ b/src/garage/admin/block.rs
@@ -25,8 +25,7 @@ impl AdminRpcHandler {
}
async fn handle_block_info(&self, hash: &String) -> Result<AdminRpc, Error> {
- let hash = hex::decode(hash).ok_or_bad_request("invalid hash")?;
- let hash = Hash::try_from(&hash).ok_or_bad_request("invalid hash")?;
+ let hash = self.find_block_hash_by_prefix(hash)?;
let refcount = self.garage.block_manager.get_block_rc(&hash)?;
let block_refs = self
.garage
@@ -189,4 +188,48 @@ impl AdminRpcHandler {
Ok(())
}
+
+ // ---- helper function ----
+ fn find_block_hash_by_prefix(&self, prefix: &str) -> Result<Hash, Error> {
+ if prefix.len() < 4 {
+ return Err(Error::BadRequest(
+ "Please specify at least 4 characters of the block hash".into(),
+ ));
+ }
+
+ let prefix_bin =
+ hex::decode(&prefix[..prefix.len() & !1]).ok_or_bad_request("invalid hash")?;
+
+ let iter = self
+ .garage
+ .block_ref_table
+ .data
+ .store
+ .range(&prefix_bin[..]..)
+ .map_err(GarageError::from)?;
+ let mut found = None;
+ for item in iter {
+ let (k, _v) = item.map_err(GarageError::from)?;
+ let hash = Hash::try_from(&k[..32]).unwrap();
+ if &hash.as_slice()[..prefix_bin.len()] != prefix_bin {
+ break;
+ }
+ if hex::encode(hash.as_slice()).starts_with(prefix) {
+ match &found {
+ Some(x) if *x == hash => (),
+ Some(_) => {
+ return Err(Error::BadRequest(format!(
+ "Several blocks match prefix `{}`",
+ prefix
+ )));
+ }
+ None => {
+ found = Some(hash);
+ }
+ }
+ }
+ }
+
+ found.ok_or_else(|| Error::BadRequest("No matching block found".into()))
+ }
}