diff --git a/zstor/src/actors/meta.rs b/zstor/src/actors/meta.rs index 477a104..714ef86 100644 --- a/zstor/src/actors/meta.rs +++ b/zstor/src/actors/meta.rs @@ -82,6 +82,11 @@ pub struct DeleteFailure { pub fm: FailureMeta, } +#[derive(Message)] +#[rtype(result = "bool")] +/// Message to check if the metastore is writable. +pub struct CheckWritable; + #[derive(Message)] #[rtype(result = "Result, MetaStoreError>")] /// Message for retrieving all [`FailureMeta`] objects in a [`MetaStore`] managed by a [`MetaStoreActor`]. @@ -111,10 +116,11 @@ pub struct MetaStoreActor { impl MetaStoreActor { /// Create a new [`MetaStoreActor`] from a given [`MetaStore`]. - pub fn new(meta_store: Box) -> MetaStoreActor { + pub fn new(meta_store: Box, writeable: bool) -> MetaStoreActor { + log::info!("metastore actor writeable: {}", writeable); Self { meta_store: Arc::from(meta_store), - writeable: true, + writeable, } } } @@ -221,6 +227,15 @@ impl Handler for MetaStoreActor { } } +impl Handler for MetaStoreActor { + type Result = ResponseFuture; + + fn handle(&mut self, _: CheckWritable, _: &mut Self::Context) -> Self::Result { + let writeable = self.writeable; + Box::pin(async move { writeable }) + } +} + impl Handler for MetaStoreActor { type Result = ResponseFuture>; diff --git a/zstor/src/actors/zstor.rs b/zstor/src/actors/zstor.rs index 3660d2c..2ee6819 100644 --- a/zstor/src/actors/zstor.rs +++ b/zstor/src/actors/zstor.rs @@ -1,6 +1,6 @@ use crate::actors::{ config::{ConfigActor, GetConfig}, - meta::{LoadMeta, LoadMetaByKey, MetaStoreActor, SaveMeta, SaveMetaByKey}, + meta::{CheckWritable, LoadMeta, LoadMetaByKey, MetaStoreActor, SaveMeta, SaveMetaByKey}, metrics::{MetricsActor, ZstorCommandFinsihed, ZstorCommandId}, pipeline::{PipelineActor, RebuildData, RecoverFile, StoreFile}, }; @@ -138,8 +138,17 @@ impl Handler for ZstorActor { let pipeline = self.pipeline.clone(); let config = self.cfg.clone(); let meta = self.meta.clone(); + AtomicResponse::new(Box::pin( async move { + let meta_writeable = meta.send(CheckWritable).await.unwrap(); + if !meta_writeable { + return Err(ZstorError::new_io( + "Metastore is not writable".to_string(), + std::io::Error::from(std::io::ErrorKind::PermissionDenied), + )); + } + let ft = fs::metadata(&msg.file) .await .map_err(|e| ZstorError::new_io("Could not load file metadata".into(), e))? diff --git a/zstor/src/lib.rs b/zstor/src/lib.rs index d7d4620..0928fd2 100644 --- a/zstor/src/lib.rs +++ b/zstor/src/lib.rs @@ -24,7 +24,7 @@ use compression::CompressorError; use config::ConfigError; use encryption::EncryptionError; use erasure::EncodingError; -use futures::future::try_join_all; +use futures::future::join_all; use meta::MetaStoreError; use std::fmt; use std::path::{Path, PathBuf}; @@ -63,17 +63,18 @@ pub type ZstorResult = Result; pub async fn setup_system(cfg_path: PathBuf, cfg: &Config) -> ZstorResult> { let metastore = match cfg.meta() { Meta::Zdb(zdb_cfg) => { - let backends = try_join_all( + let backends = join_all( zdb_cfg .backends() .iter() .map(|ci| UserKeyZdb::new(ci.clone())), ) - .await?; + .await; let encryptor = match cfg.encryption() { Encryption::Aes(key) => encryption::AesGcm::new(key.clone()), }; let encoder = zdb_cfg.encoder(); + let backends = backends.into_iter().filter_map(|res| res.ok()).collect(); Box::new(ZdbMetaStore::new( backends, encoder, @@ -88,7 +89,8 @@ pub async fn setup_system(cfg_path: PathBuf, cfg: &Config) -> ZstorResult bool { + self.writeable + } + /// helper functions to encrypt and write data to backends. async fn write_value(&self, key: &str, value: &[u8]) -> ZdbMetaStoreResult<()> { debug!("Writing data to zdb metastore");