ecstore update ec/disk/error

This commit is contained in:
weisd
2025-06-04 14:26:46 +08:00
committed by weisd
parent 7fe0cc74d2
commit 9384b831ec
102 changed files with 18806 additions and 4864 deletions
+23 -17
View File
@@ -16,6 +16,7 @@ use super::{
heal_commands::HealOpts,
heal_ops::{new_bg_heal_sequence, HealSequence},
};
use crate::error::{Error, Result};
use crate::global::GLOBAL_MRFState;
use crate::heal::error::ERR_RETRY_HEALING;
use crate::heal::heal_commands::{HealScanMode, HEAL_ITEM_BUCKET};
@@ -35,7 +36,6 @@ use crate::{
store_api::{BucketInfo, BucketOptions, StorageAPI},
utils::path::{path_join, SLASH_SEPARATOR},
};
use common::error::{Error, Result};
pub static DEFAULT_MONITOR_NEW_DISK_INTERVAL: Duration = Duration::from_secs(10);
@@ -72,7 +72,7 @@ pub async fn get_local_disks_to_heal() -> Vec<Endpoint> {
for (_, disk) in GLOBAL_LOCAL_DISK_MAP.read().await.iter() {
if let Some(disk) = disk {
if let Err(err) = disk.disk_info(&DiskInfoOptions::default()).await {
if let Some(DiskError::UnformattedDisk) = err.downcast_ref() {
if err == DiskError::UnformattedDisk {
info!("get_local_disks_to_heal, disk is unformatted: {}", err);
disks_to_heal.push(disk.endpoint());
}
@@ -111,7 +111,7 @@ async fn monitor_local_disks_and_heal() {
let store = new_object_layer_fn().expect("errServerNotInitialized");
if let (_result, Some(err)) = store.heal_format(false).await.expect("heal format failed") {
error!("heal local disk format error: {}", err);
if let Some(DiskError::NoHealRequired) = err.downcast_ref::<DiskError>() {
if err == Error::NoHealRequired {
} else {
info!("heal format err: {}", err.to_string());
interval.reset();
@@ -146,7 +146,7 @@ async fn heal_fresh_disk(endpoint: &Endpoint) -> Result<()> {
let disk = match get_disk_via_endpoint(endpoint).await {
Some(disk) => disk,
None => {
return Err(Error::from_string(format!(
return Err(Error::other(format!(
"Unexpected error disk must be initialized by now after formatting: {}",
endpoint
)))
@@ -154,13 +154,13 @@ async fn heal_fresh_disk(endpoint: &Endpoint) -> Result<()> {
};
if let Err(err) = disk.disk_info(&DiskInfoOptions::default()).await {
match err.downcast_ref() {
Some(DiskError::DriveIsRoot) => {
match err {
DiskError::DriveIsRoot => {
return Ok(());
}
Some(DiskError::UnformattedDisk) => {}
DiskError::UnformattedDisk => {}
_ => {
return Err(err);
return Err(err.into());
}
}
}
@@ -168,8 +168,8 @@ async fn heal_fresh_disk(endpoint: &Endpoint) -> Result<()> {
let mut tracker = match load_healing_tracker(&Some(disk.clone())).await {
Ok(tracker) => tracker,
Err(err) => {
match err.downcast_ref() {
Some(DiskError::FileNotFound) => {
match err {
DiskError::FileNotFound => {
return Ok(());
}
_ => {
@@ -189,7 +189,9 @@ async fn heal_fresh_disk(endpoint: &Endpoint) -> Result<()> {
endpoint.to_string()
);
let Some(store) = new_object_layer_fn() else { return Err(Error::msg("errServerNotInitialized")) };
let Some(store) = new_object_layer_fn() else {
return Err(Error::other("errServerNotInitialized"));
};
let mut buckets = store.list_bucket(&BucketOptions::default()).await?;
buckets.push(BucketInfo {
@@ -238,7 +240,7 @@ async fn heal_fresh_disk(endpoint: &Endpoint) -> Result<()> {
if let Err(err) = tracker_w.update().await {
info!("update tracker failed: {}", err.to_string());
}
return Err(Error::from_string(ERR_RETRY_HEALING));
return Err(Error::other(ERR_RETRY_HEALING));
}
if tracker_w.items_failed > 0 {
@@ -272,7 +274,9 @@ async fn heal_fresh_disk(endpoint: &Endpoint) -> Result<()> {
error!("delete tracker failed: {}", err.to_string());
}
}
let Some(store) = new_object_layer_fn() else { return Err(Error::msg("errServerNotInitialized")) };
let Some(store) = new_object_layer_fn() else {
return Err(Error::other("errServerNotInitialized"));
};
let disks = store.get_disks(pool_idx, set_idx).await?;
for disk in disks.into_iter() {
if disk.is_none() {
@@ -281,8 +285,8 @@ async fn heal_fresh_disk(endpoint: &Endpoint) -> Result<()> {
let mut tracker = match load_healing_tracker(&disk).await {
Ok(tracker) => tracker,
Err(err) => {
match err.downcast_ref() {
Some(DiskError::FileNotFound) => {}
match err {
DiskError::FileNotFound => {}
_ => {
info!("Unable to load healing tracker on '{:?}': {}, re-initializing..", disk, err.to_string());
}
@@ -362,7 +366,7 @@ impl HealRoutine {
Some(task) => {
info!("got task: {:?}", task);
if task.bucket == NOP_HEAL {
d_err = Some(Error::from_string("skip file"));
d_err = Some(Error::other("skip file"));
} else if task.bucket == SLASH_SEPARATOR {
match heal_disk_format(task.opts).await {
Ok((res, err)) => {
@@ -426,7 +430,9 @@ impl HealRoutine {
// }
async fn heal_disk_format(opts: HealOpts) -> Result<(HealResultItem, Option<Error>)> {
let Some(store) = new_object_layer_fn() else { return Err(Error::msg("errServerNotInitialized")) };
let Some(store) = new_object_layer_fn() else {
return Err(Error::other("errServerNotInitialized"));
};
let (res, err) = store.heal_format(opts.dry_run).await?;
// return any error, ignore error returned when disks have
+22 -15
View File
@@ -20,6 +20,7 @@ use super::{
};
use crate::{
bucket::{versioning::VersioningApi, versioning_sys::BucketVersioningSys},
disk,
heal::data_usage::DATA_USAGE_ROOT,
};
use crate::{
@@ -28,7 +29,7 @@ use crate::{
com::{read_config, save_config},
heal::Config,
},
disk::{error::DiskError, DiskInfoOptions, DiskStore, MetaCacheEntries, MetaCacheEntry, MetadataResolutionParams},
disk::{DiskInfoOptions, DiskStore},
global::{GLOBAL_BackgroundHealState, GLOBAL_IsErasure, GLOBAL_IsErasureSD},
heal::{
data_usage::BACKGROUND_HEAL_INFO_PATH,
@@ -42,16 +43,17 @@ use crate::{
store::ECStore,
utils::path::{path_join, path_to_bucket_object, path_to_bucket_object_with_base_path, SLASH_SEPARATOR},
};
use crate::{disk::local::LocalDisk, heal::data_scanner_metric::current_path_updater};
use crate::{
disk::DiskAPI,
store_api::{FileInfo, ObjectInfo},
disk::error::DiskError,
error::{Error, Result},
};
use crate::{disk::local::LocalDisk, heal::data_scanner_metric::current_path_updater};
use crate::{disk::DiskAPI, store_api::ObjectInfo};
use chrono::{DateTime, Utc};
use common::error::{Error, Result};
use lazy_static::lazy_static;
use rand::Rng;
use rmp_serde::{Deserializer, Serializer};
use rustfs_filemeta::{FileInfo, MetaCacheEntries, MetaCacheEntry, MetadataResolutionParams};
use s3s::dto::{BucketLifecycleConfiguration, ExpirationStatus, LifecycleRule, ReplicationConfiguration, ReplicationRuleStatus};
use serde::{Deserialize, Serialize};
use tokio::{
@@ -460,7 +462,7 @@ impl CurrentScannerCycle {
Deserialize::deserialize(&mut Deserializer::new(&buf[..])).expect("Deserialization failed");
self.cycle_completed = u;
}
name => return Err(Error::msg(format!("not support field name {}", name))),
name => return Err(Error::other(format!("not support field name {}", name))),
}
}
@@ -540,7 +542,12 @@ impl ScannerItem {
if self.lifecycle.is_none() {
for info in fives.iter() {
object_infos.push(info.to_object_info(&self.bucket, &self.object_path().to_string_lossy(), versioned));
object_infos.push(ObjectInfo::from_file_info(
info,
&self.bucket,
&self.object_path().to_string_lossy(),
versioned,
));
}
return Ok(object_infos);
}
@@ -594,7 +601,7 @@ struct CachedFolder {
}
pub type GetSizeFn =
Box<dyn Fn(&ScannerItem) -> Pin<Box<dyn Future<Output = Result<SizeSummary>> + Send>> + Send + Sync + 'static>;
Box<dyn Fn(&ScannerItem) -> Pin<Box<dyn Future<Output = std::io::Result<SizeSummary>> + Send>> + Send + Sync + 'static>;
pub type UpdateCurrentPathFn = Arc<dyn Fn(&str) -> Pin<Box<dyn Future<Output = ()> + Send>> + Send + Sync + 'static>;
pub type ShouldSleepFn = Option<Arc<dyn Fn() -> bool + Send + Sync + 'static>>;
@@ -929,7 +936,7 @@ impl FolderScanner {
}
})
})),
partial: Some(Box::new(move |entries: MetaCacheEntries, _: &[Option<Error>]| {
partial: Some(Box::new(move |entries: MetaCacheEntries, _: &[Option<DiskError>]| {
Box::pin({
let update_current_path_partial = update_current_path_partial.clone();
// let tx_partial = tx_partial.clone();
@@ -973,8 +980,8 @@ impl FolderScanner {
)
.await
{
match err.downcast_ref() {
Some(DiskError::FileNotFound) | Some(DiskError::FileVersionNotFound) => {}
match err {
Error::FileNotFound | Error::FileVersionNotFound => {}
_ => {
info!("{}", err.to_string());
}
@@ -1018,7 +1025,7 @@ impl FolderScanner {
}
})
})),
finished: Some(Box::new(move |_: &[Option<Error>]| {
finished: Some(Box::new(move |_: &[Option<DiskError>]| {
Box::pin({
let tx_finished = tx_finished.clone();
async move {
@@ -1077,7 +1084,7 @@ impl FolderScanner {
if !into.compacted {
self.new_cache.reduce_children_of(
&this_hash,
DATA_SCANNER_COMPACT_AT_CHILDREN.try_into()?,
DATA_SCANNER_COMPACT_AT_CHILDREN as usize,
self.new_cache.info.name != folder.name,
);
}
@@ -1234,9 +1241,9 @@ pub async fn scan_data_folder(
get_size_fn: GetSizeFn,
heal_scan_mode: HealScanMode,
should_sleep: ShouldSleepFn,
) -> Result<DataUsageCache> {
) -> disk::error::Result<DataUsageCache> {
if cache.info.name.is_empty() || cache.info.name == DATA_USAGE_ROOT {
return Err(Error::from_string("internal error: root scan attempted"));
return Err(DiskError::other("internal error: root scan attempted"));
}
let base_path = drive.to_string();
+4 -7
View File
@@ -1,16 +1,13 @@
use crate::error::{Error, Result};
use crate::{
bucket::metadata_sys::get_replication_config,
config::{
com::{read_config, save_config},
error::is_err_config_not_found,
},
config::com::{read_config, save_config},
disk::{BUCKET_META_PREFIX, RUSTFS_META_BUCKET},
error::to_object_err,
new_object_layer_fn,
store::ECStore,
store_err::to_object_err,
utils::path::SLASH_SEPARATOR,
};
use common::error::Result;
use lazy_static::lazy_static;
use serde::{Deserialize, Serialize};
use std::{collections::HashMap, sync::Arc, time::SystemTime};
@@ -146,7 +143,7 @@ pub async fn load_data_usage_from_backend(store: Arc<ECStore>) -> Result<DataUsa
Ok(data) => data,
Err(e) => {
error!("Failed to read data usage info from backend: {}", e);
if is_err_config_not_found(&e) {
if e == Error::ConfigNotFound {
return Ok(DataUsageInfo::default());
}
+10 -8
View File
@@ -1,11 +1,10 @@
use crate::config::com::save_config;
use crate::disk::error::DiskError;
use crate::disk::{BUCKET_META_PREFIX, RUSTFS_META_BUCKET};
use crate::error::{Error, Result};
use crate::new_object_layer_fn;
use crate::set_disk::SetDisks;
use crate::store_api::{BucketInfo, ObjectIO, ObjectOptions};
use bytesize::ByteSize;
use common::error::{Error, Result};
use http::HeaderMap;
use path_clean::PathClean;
use rand::Rng;
@@ -402,8 +401,8 @@ impl DataUsageCache {
}
Err(err) => {
// warn!("Failed to load data usage cache from backend: {}", &err);
match err.downcast_ref::<DiskError>() {
Some(DiskError::FileNotFound) | Some(DiskError::VolumeNotFound) => {
match err {
Error::FileNotFound | Error::VolumeNotFound => {
match store
.get_object_reader(
RUSTFS_META_BUCKET,
@@ -423,8 +422,8 @@ impl DataUsageCache {
}
break;
}
Err(_) => match err.downcast_ref::<DiskError>() {
Some(DiskError::FileNotFound) | Some(DiskError::VolumeNotFound) => {
Err(_) => match err {
Error::FileNotFound | Error::VolumeNotFound => {
break;
}
_ => {}
@@ -448,7 +447,9 @@ impl DataUsageCache {
}
pub async fn save(&self, name: &str) -> Result<()> {
let Some(store) = new_object_layer_fn() else { return Err(Error::msg("errServerNotInitialized")) };
let Some(store) = new_object_layer_fn() else {
return Err(Error::other("errServerNotInitialized"));
};
let buf = self.marshal_msg()?;
let buf_clone = buf.clone();
@@ -460,7 +461,8 @@ impl DataUsageCache {
tokio::spawn(async move {
let _ = save_config(store_clone, &format!("{}{}", &name_clone, ".bkp"), buf_clone).await;
});
save_config(store, &name, buf).await
save_config(store, &name, buf).await?;
Ok(())
}
pub fn replace(&mut self, path: &str, parent: &str, e: DataUsageEntry) {
+33 -31
View File
@@ -6,15 +6,15 @@ use std::{
use crate::{
config::storageclass::{RRS, STANDARD},
disk::{DeleteOptions, DiskAPI, DiskStore, BUCKET_META_PREFIX, RUSTFS_META_BUCKET},
disk::{error::DiskError, DeleteOptions, DiskAPI, DiskStore, BUCKET_META_PREFIX, RUSTFS_META_BUCKET},
global::GLOBAL_BackgroundHealState,
heal::heal_ops::HEALING_TRACKER_FILENAME,
new_object_layer_fn,
store_api::{BucketInfo, StorageAPI},
utils::fs::read_file,
};
use crate::{disk, error::Result};
use chrono::{DateTime, Utc};
use common::error::{Error, Result};
use lazy_static::lazy_static;
use serde::{Deserialize, Serialize};
use time::OffsetDateTime;
@@ -124,12 +124,12 @@ pub struct HealingTracker {
}
impl HealingTracker {
pub fn marshal_msg(&self) -> Result<Vec<u8>> {
serde_json::to_vec(self).map_err(|err| Error::from_string(err.to_string()))
pub fn marshal_msg(&self) -> disk::error::Result<Vec<u8>> {
Ok(serde_json::to_vec(self)?)
}
pub fn unmarshal_msg(data: &[u8]) -> Result<Self> {
serde_json::from_slice::<HealingTracker>(data).map_err(|err| Error::from_string(err.to_string()))
pub fn unmarshal_msg(data: &[u8]) -> disk::error::Result<Self> {
Ok(serde_json::from_slice::<HealingTracker>(data)?)
}
pub async fn reset_healing(&mut self) {
@@ -195,10 +195,10 @@ impl HealingTracker {
}
}
pub async fn update(&mut self) -> Result<()> {
pub async fn update(&mut self) -> disk::error::Result<()> {
if let Some(disk) = &self.disk {
if healing(disk.path().to_string_lossy().as_ref()).await?.is_none() {
return Err(Error::from_string(format!("healingTracker: drive {} is not marked as healing", self.id)));
return Err(DiskError::other(format!("healingTracker: drive {} is not marked as healing", self.id)));
}
let _ = self.mu.write().await;
if self.id.is_empty() || self.pool_index.is_none() || self.set_index.is_none() || self.disk_index.is_none() {
@@ -213,12 +213,16 @@ impl HealingTracker {
self.save().await
}
pub async fn save(&mut self) -> Result<()> {
pub async fn save(&mut self) -> disk::error::Result<()> {
let _ = self.mu.write().await;
if self.pool_index.is_none() || self.set_index.is_none() || self.disk_index.is_none() {
let Some(store) = new_object_layer_fn() else { return Err(Error::msg("errServerNotInitialized")) };
let Some(store) = new_object_layer_fn() else {
return Err(DiskError::other("errServerNotInitialized"));
};
(self.pool_index, self.set_index, self.disk_index) = store.get_pool_and_set(&self.id).await?;
// TODO: check error type
(self.pool_index, self.set_index, self.disk_index) =
store.get_pool_and_set(&self.id).await.map_err(|_| DiskError::DiskNotFound)?;
}
self.last_update = Some(SystemTime::now());
@@ -229,9 +233,8 @@ impl HealingTracker {
if let Some(disk) = &self.disk {
let file_path = Path::new(BUCKET_META_PREFIX).join(HEALING_TRACKER_FILENAME);
return disk
.write_all(RUSTFS_META_BUCKET, file_path.to_str().unwrap(), htracker_bytes)
.await;
disk.write_all(RUSTFS_META_BUCKET, file_path.to_str().unwrap(), htracker_bytes)
.await?;
}
Ok(())
}
@@ -239,17 +242,16 @@ impl HealingTracker {
pub async fn delete(&self) -> Result<()> {
if let Some(disk) = &self.disk {
let file_path = Path::new(BUCKET_META_PREFIX).join(HEALING_TRACKER_FILENAME);
return disk
.delete(
RUSTFS_META_BUCKET,
file_path.to_str().unwrap(),
DeleteOptions {
recursive: false,
immediate: false,
..Default::default()
},
)
.await;
disk.delete(
RUSTFS_META_BUCKET,
file_path.to_str().unwrap(),
DeleteOptions {
recursive: false,
immediate: false,
..Default::default()
},
)
.await?;
}
Ok(())
@@ -372,7 +374,7 @@ impl Clone for HealingTracker {
}
}
pub async fn load_healing_tracker(disk: &Option<DiskStore>) -> Result<HealingTracker> {
pub async fn load_healing_tracker(disk: &Option<DiskStore>) -> disk::error::Result<HealingTracker> {
if let Some(disk) = disk {
let disk_id = disk.get_disk_id().await?;
if let Some(disk_id) = disk_id {
@@ -381,7 +383,7 @@ pub async fn load_healing_tracker(disk: &Option<DiskStore>) -> Result<HealingTra
let data = disk.read_all(RUSTFS_META_BUCKET, file_path.to_str().unwrap()).await?;
let mut healing_tracker = HealingTracker::unmarshal_msg(&data)?;
if healing_tracker.id != disk_id && !healing_tracker.id.is_empty() {
return Err(Error::from_string(format!(
return Err(DiskError::other(format!(
"loadHealingTracker: drive id mismatch expected {}, got {}",
healing_tracker.id, disk_id
)));
@@ -390,14 +392,14 @@ pub async fn load_healing_tracker(disk: &Option<DiskStore>) -> Result<HealingTra
healing_tracker.disk = Some(disk.clone());
Ok(healing_tracker)
} else {
Err(Error::from_string("loadHealingTracker: disk not have id"))
Err(DiskError::other("loadHealingTracker: disk not have id"))
}
} else {
Err(Error::from_string("loadHealingTracker: nil drive given"))
Err(DiskError::other("loadHealingTracker: nil drive given"))
}
}
pub async fn init_healing_tracker(disk: DiskStore, heal_id: &str) -> Result<HealingTracker> {
pub async fn init_healing_tracker(disk: DiskStore, heal_id: &str) -> disk::error::Result<HealingTracker> {
let disk_location = disk.get_disk_location();
Ok(HealingTracker {
id: disk
@@ -416,7 +418,7 @@ pub async fn init_healing_tracker(disk: DiskStore, heal_id: &str) -> Result<Heal
})
}
pub async fn healing(derive_path: &str) -> Result<Option<HealingTracker>> {
pub async fn healing(derive_path: &str) -> disk::error::Result<Option<HealingTracker>> {
let healing_file = Path::new(derive_path)
.join(RUSTFS_META_BUCKET)
.join(BUCKET_META_PREFIX)
+18 -13
View File
@@ -4,6 +4,7 @@ use super::{
error::ERR_SKIP_FILE,
heal_commands::{HealOpts, HealScanMode, HealStopSuccess, HealingTracker, HEAL_ITEM_BUCKET_METADATA},
};
use crate::error::{Error, Result};
use crate::store_api::StorageAPI;
use crate::{
config::com::CONFIG_PREFIX,
@@ -12,7 +13,7 @@ use crate::{
heal::{error::ERR_HEAL_STOP_SIGNALLED, heal_commands::DRIVE_STATE_OK},
};
use crate::{
disk::{endpoint::Endpoint, MetaCacheEntry},
disk::endpoint::Endpoint,
endpoints::Endpoints,
global::GLOBAL_IsDistErasure,
heal::heal_commands::{HealStartSuccess, HEAL_UNKNOWN_SCAN},
@@ -24,10 +25,10 @@ use crate::{
utils::path::path_join,
};
use chrono::Utc;
use common::error::{Error, Result};
use futures::join;
use lazy_static::lazy_static;
use madmin::heal_commands::{HealDriveInfo, HealItemType, HealResultItem};
use rustfs_filemeta::MetaCacheEntry;
use serde::{Deserialize, Serialize};
use std::{
collections::HashMap,
@@ -285,10 +286,10 @@ impl HealSequence {
}
_ = self.is_done() => {
return Err(Error::from_string("stopped"));
return Err(Error::other("stopped"));
}
_ = interval_timer.tick() => {
return Err(Error::from_string("timeout"));
return Err(Error::other("timeout"));
}
}
} else {
@@ -412,7 +413,9 @@ impl HealSequence {
async fn heal_rustfs_sys_meta(h: Arc<HealSequence>, meta_prefix: &str) -> Result<()> {
info!("heal_rustfs_sys_meta, h: {:?}", h);
let Some(store) = new_object_layer_fn() else { return Err(Error::msg("errServerNotInitialized")) };
let Some(store) = new_object_layer_fn() else {
return Err(Error::other("errServerNotInitialized"));
};
let setting = h.setting;
store
.heal_objects(RUSTFS_META_BUCKET, meta_prefix, &setting, h.clone(), true)
@@ -450,7 +453,9 @@ impl HealSequence {
}
(hs.object.clone(), hs.setting)
};
let Some(store) = new_object_layer_fn() else { return Err(Error::msg("errServerNotInitialized")) };
let Some(store) = new_object_layer_fn() else {
return Err(Error::other("errServerNotInitialized"));
};
store.heal_objects(bucket, &object, &setting, hs.clone(), false).await
}
@@ -464,7 +469,7 @@ impl HealSequence {
info!("heal_object");
if hs.is_quitting().await {
info!("heal_object hs is quitting");
return Err(Error::from_string(ERR_HEAL_STOP_SIGNALLED));
return Err(Error::other(ERR_HEAL_STOP_SIGNALLED));
}
info!("will queue task");
@@ -491,7 +496,7 @@ impl HealSequence {
_scan_mode: HealScanMode,
) -> Result<()> {
if hs.is_quitting().await {
return Err(Error::from_string(ERR_HEAL_STOP_SIGNALLED));
return Err(Error::other(ERR_HEAL_STOP_SIGNALLED));
}
hs.queue_heal_task(
@@ -615,7 +620,7 @@ impl AllHealState {
Some(h) => {
if client_token != h.client_token {
info!("err heal invalid client token");
return Err(Error::from_string("err heal invalid client token"));
return Err(Error::other("err heal invalid client token"));
}
let num_items = h.current_status.read().await.items.len();
let mut last_result_index = *h.last_sent_result_index.read().await;
@@ -634,7 +639,7 @@ impl AllHealState {
Err(e) => {
h.current_status.write().await.items.clear();
info!("json encode err, e: {}", e);
Err(Error::msg(e.to_string()))
Err(Error::other(e.to_string()))
}
}
}
@@ -644,7 +649,7 @@ impl AllHealState {
})
.map_err(|e| {
info!("json encode err, e: {}", e);
Error::msg(e.to_string())
Error::other(e.to_string())
}),
}
}
@@ -779,7 +784,7 @@ impl AllHealState {
self.stop_heal_sequence(path_s).await?;
} else if let Some(hs) = self.get_heal_sequence(path_s).await {
if !hs.has_ended().await {
return Err(Error::from_string(format!("Heal is already running on the given path (use force-start option to stop and start afresh). The heal was started by IP {} at {:?}, token is {}", heal_sequence.client_address, heal_sequence.start_time, heal_sequence.client_token)));
return Err(Error::other(format!("Heal is already running on the given path (use force-start option to stop and start afresh). The heal was started by IP {} at {:?}, token is {}", heal_sequence.client_address, heal_sequence.start_time, heal_sequence.client_token)));
}
}
@@ -787,7 +792,7 @@ impl AllHealState {
for (k, v) in self.heal_seq_map.read().await.iter() {
if (has_prefix(k, path_s) || has_prefix(path_s, k)) && !v.has_ended().await {
return Err(Error::from_string(format!(
return Err(Error::other(format!(
"The provided heal sequence path overlaps with an existing heal path: {}",
k
)));