blob: 54399d2cd4768d3c0100870fac6388326732efa1 [file]
/* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
use crate::streaming::persistence::persister::PersisterKind;
use crate::streaming::storage::SystemInfoStorage;
use crate::streaming::systems::info::SystemInfo;
use crate::streaming::systems::COMPONENT;
use crate::streaming::utils::file;
use crate::streaming::utils::PooledBuffer;
use anyhow::Context;
use error_set::ErrContext;
use iggy::error::IggyError;
use std::sync::Arc;
use tokio::io::AsyncReadExt;
use tracing::info;
#[derive(Debug)]
pub struct FileSystemInfoStorage {
persister: Arc<PersisterKind>,
path: String,
}
impl FileSystemInfoStorage {
pub fn new(path: String, persister: Arc<PersisterKind>) -> Self {
Self { path, persister }
}
}
impl SystemInfoStorage for FileSystemInfoStorage {
async fn load(&self) -> Result<SystemInfo, IggyError> {
let file = file::open(&self.path).await;
if file.is_err() {
return Err(IggyError::ResourceNotFound(self.path.to_owned()));
}
let mut file = file.unwrap();
let file_size = file
.metadata()
.await
.with_error_context(|error| {
format!(
"{COMPONENT} (error: {error}) - failed to retrieve metadata for file at path: {}",
self.path
)
})
.map_err(|_| IggyError::CannotReadFileMetadata)?
.len() as usize;
let mut buffer = PooledBuffer::with_capacity(file_size);
buffer.put_bytes(0, file_size);
file.read_exact(&mut buffer)
.await
.with_error_context(|error| {
format!(
"{COMPONENT} (error: {error}) - failed to read file content from path: {}",
self.path
)
})
.map_err(|_| IggyError::CannotReadFile)?;
let (system_info, _) =
bincode::serde::decode_from_slice(&buffer, bincode::config::standard())
.with_context(|| "Failed to deserialize system info")
.map_err(|_| IggyError::CannotDeserializeResource)?;
Ok(system_info)
}
async fn save(&self, system_info: &SystemInfo) -> Result<(), IggyError> {
let data = bincode::serde::encode_to_vec(system_info, bincode::config::standard())
.with_context(|| "Failed to serialize system info")
.map_err(|_| IggyError::CannotSerializeResource)?;
self.persister
.overwrite(&self.path, &data)
.await
.with_error_context(|error| {
format!(
"{COMPONENT} (error: {error}) - failed to overwrite file at path: {}",
self.path
)
})?;
info!("Saved system info, {system_info}");
Ok(())
}
}