[block-info-short-682] garage block info: find blocks by prefix (fix #682)

This commit is contained in:
Alex Auvolat 2024-02-09 14:35:53 +01:00
parent 0c7ce001c9
commit 8da67b3aa2
No known key found for this signature in database
GPG key ID: 0E496D15096376BE

View file

@ -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()))
}
}