aboutsummaryrefslogtreecommitdiff
path: root/src/garage/admin/block.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/garage/admin/block.rs')
-rw-r--r--src/garage/admin/block.rs235
1 files changed, 0 insertions, 235 deletions
diff --git a/src/garage/admin/block.rs b/src/garage/admin/block.rs
deleted file mode 100644
index edeb88c0..00000000
--- a/src/garage/admin/block.rs
+++ /dev/null
@@ -1,235 +0,0 @@
-use garage_util::data::*;
-
-use garage_table::*;
-
-use garage_model::helper::error::{Error, OkOrBadRequest};
-use garage_model::s3::object_table::*;
-use garage_model::s3::version_table::*;
-
-use crate::cli::*;
-
-use super::*;
-
-impl AdminRpcHandler {
- pub(super) async fn handle_block_cmd(&self, cmd: &BlockOperation) -> Result<AdminRpc, Error> {
- match cmd {
- BlockOperation::ListErrors => Ok(AdminRpc::BlockErrorList(
- self.garage.block_manager.list_resync_errors()?,
- )),
- BlockOperation::Info { hash } => self.handle_block_info(hash).await,
- BlockOperation::RetryNow { all, blocks } => {
- self.handle_block_retry_now(*all, blocks).await
- }
- BlockOperation::Purge { yes, blocks } => self.handle_block_purge(*yes, blocks).await,
- }
- }
-
- async fn handle_block_info(&self, hash: &String) -> Result<AdminRpc, Error> {
- let hash = self.find_block_hash_by_prefix(hash)?;
- let refcount = self.garage.block_manager.get_block_rc(&hash)?;
- let block_refs = self
- .garage
- .block_ref_table
- .get_range(&hash, None, None, 10000, Default::default())
- .await?;
- let mut versions = vec![];
- let mut uploads = vec![];
- for br in block_refs {
- if let Some(v) = self
- .garage
- .version_table
- .get(&br.version, &EmptyKey)
- .await?
- {
- if let VersionBacklink::MultipartUpload { upload_id } = &v.backlink {
- if let Some(u) = self.garage.mpu_table.get(upload_id, &EmptyKey).await? {
- uploads.push(u);
- }
- }
- versions.push(Ok(v));
- } else {
- versions.push(Err(br.version));
- }
- }
- Ok(AdminRpc::BlockInfo {
- hash,
- refcount,
- versions,
- uploads,
- })
- }
-
- async fn handle_block_retry_now(
- &self,
- all: bool,
- blocks: &[String],
- ) -> Result<AdminRpc, Error> {
- if all {
- if !blocks.is_empty() {
- return Err(Error::BadRequest(
- "--all was specified, cannot also specify blocks".into(),
- ));
- }
- let blocks = self.garage.block_manager.list_resync_errors()?;
- for b in blocks.iter() {
- self.garage.block_manager.resync.clear_backoff(&b.hash)?;
- }
- Ok(AdminRpc::Ok(format!(
- "{} blocks returned in queue for a retry now (check logs to see results)",
- blocks.len()
- )))
- } else {
- for hash in blocks {
- let hash = hex::decode(hash).ok_or_bad_request("invalid hash")?;
- let hash = Hash::try_from(&hash).ok_or_bad_request("invalid hash")?;
- self.garage.block_manager.resync.clear_backoff(&hash)?;
- }
- Ok(AdminRpc::Ok(format!(
- "{} blocks returned in queue for a retry now (check logs to see results)",
- blocks.len()
- )))
- }
- }
-
- async fn handle_block_purge(&self, yes: bool, blocks: &[String]) -> Result<AdminRpc, Error> {
- if !yes {
- return Err(Error::BadRequest(
- "Pass the --yes flag to confirm block purge operation.".into(),
- ));
- }
-
- let mut obj_dels = 0;
- let mut mpu_dels = 0;
- let mut ver_dels = 0;
-
- for hash in blocks {
- let hash = hex::decode(hash).ok_or_bad_request("invalid hash")?;
- let hash = Hash::try_from(&hash).ok_or_bad_request("invalid hash")?;
- let block_refs = self
- .garage
- .block_ref_table
- .get_range(&hash, None, None, 10000, Default::default())
- .await?;
-
- for br in block_refs {
- if let Some(version) = self
- .garage
- .version_table
- .get(&br.version, &EmptyKey)
- .await?
- {
- self.handle_block_purge_version_backlink(
- &version,
- &mut obj_dels,
- &mut mpu_dels,
- )
- .await?;
-
- if !version.deleted.get() {
- let deleted_version = Version::new(version.uuid, version.backlink, true);
- self.garage.version_table.insert(&deleted_version).await?;
- ver_dels += 1;
- }
- }
- }
- }
-
- Ok(AdminRpc::Ok(format!(
- "Purged {} blocks, {} versions, {} objects, {} multipart uploads",
- blocks.len(),
- ver_dels,
- obj_dels,
- mpu_dels,
- )))
- }
-
- async fn handle_block_purge_version_backlink(
- &self,
- version: &Version,
- obj_dels: &mut usize,
- mpu_dels: &mut usize,
- ) -> Result<(), Error> {
- let (bucket_id, key, ov_id) = match &version.backlink {
- VersionBacklink::Object { bucket_id, key } => (*bucket_id, key.clone(), version.uuid),
- VersionBacklink::MultipartUpload { upload_id } => {
- if let Some(mut mpu) = self.garage.mpu_table.get(upload_id, &EmptyKey).await? {
- if !mpu.deleted.get() {
- mpu.parts.clear();
- mpu.deleted.set();
- self.garage.mpu_table.insert(&mpu).await?;
- *mpu_dels += 1;
- }
- (mpu.bucket_id, mpu.key.clone(), *upload_id)
- } else {
- return Ok(());
- }
- }
- };
-
- if let Some(object) = self.garage.object_table.get(&bucket_id, &key).await? {
- let ov = object.versions().iter().rev().find(|v| v.is_complete());
- if let Some(ov) = ov {
- if ov.uuid == ov_id {
- let del_uuid = gen_uuid();
- let deleted_object = Object::new(
- bucket_id,
- key,
- vec![ObjectVersion {
- uuid: del_uuid,
- timestamp: ov.timestamp + 1,
- state: ObjectVersionState::Complete(ObjectVersionData::DeleteMarker),
- }],
- );
- self.garage.object_table.insert(&deleted_object).await?;
- *obj_dels += 1;
- }
- }
- }
-
- 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()))
- }
-}