#![allow(clippy::used_underscore_binding)] use crate::manifest::StoredArchive;
use crate::repository::{Chunk, ChunkID, ChunkSettings, EncryptedKey};
use async_trait::async_trait;
use chrono::prelude::*;
use semver::Version;
use serde::{Deserialize, Serialize};
use thiserror::Error;
use uuid::Uuid;
use std::collections::HashSet;
pub mod common;
pub mod flatfile;
pub mod mem;
pub mod multifile;
#[cfg(feature = "sftp")]
pub mod sftp;
#[cfg(not(tarpaulin_include))]
pub mod object_wrappers;
pub use object_wrappers::{backend_to_object, BackendObject};
#[derive(Error, Debug)]
#[non_exhaustive]
pub enum BackendError {
#[error("I/O Error: {0}")]
IOError(#[from] std::io::Error),
#[error("Data not found")]
DataNotFound,
#[error("Segment Error: {0}")]
SegmentError(String),
#[error("Manifest Error: {0}")]
ManifestError(String),
#[error("Index Error: {0}")]
IndexError(String),
#[error("CBOR Encode/Decode Error")]
MsgPackEncodeError(#[from] serde_cbor::error::Error),
#[error("Failed to lock file")]
FileLockError,
#[error("Cancelled oneshot")]
CancelledOneshotError(#[from] futures::channel::oneshot::Canceled),
#[error("Chunk Unpacking Error: {0}")]
ChunkUnpackError(#[from] asuran_core::repository::chunk::ChunkError),
#[error("Repository has an existing global lock: {0}")]
RepositoryGloballyLocked(String),
#[error("Task Communication Error, likely trying to talk to a closed backend")]
ChannelDroppedSend(#[from] futures::channel::mpsc::SendError),
#[error("Error connecting to backend: {0}")]
ConnectionError(String),
#[error("FlatFile Format Error: {0}")]
FlatFile(#[from] asuran_core::repository::backend::flatfile::FlatFileError),
#[error("Unknown Error: {0}")]
Unknown(String),
}
pub type Result<T> = std::result::Result<T, BackendError>;
#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, Hash)]
pub struct SegmentDescriptor {
pub segment_id: u64,
pub start: u64,
}
#[async_trait]
pub trait Manifest: Send + Sync + std::fmt::Debug + 'static {
type Iterator: Iterator<Item = StoredArchive> + 'static;
async fn last_modification(&mut self) -> Result<DateTime<FixedOffset>>;
async fn chunk_settings(&mut self) -> ChunkSettings;
async fn archive_iterator(&mut self) -> Self::Iterator;
async fn write_chunk_settings(&mut self, settings: ChunkSettings) -> Result<()>;
async fn write_archive(&mut self, archive: StoredArchive) -> Result<()>;
async fn touch(&mut self) -> Result<()>;
async fn seen_versions(&mut self) -> HashSet<(Version, Uuid)>;
}
#[async_trait]
pub trait Index: Send + Sync + std::fmt::Debug + 'static {
async fn lookup_chunk(&mut self, id: ChunkID) -> Option<SegmentDescriptor>;
async fn set_chunk(&mut self, id: ChunkID, location: SegmentDescriptor) -> Result<()>;
async fn known_chunks(&mut self) -> HashSet<ChunkID>;
async fn commit_index(&mut self) -> Result<()>;
async fn count_chunk(&mut self) -> usize;
}
#[async_trait]
pub trait Backend: 'static + Send + Sync + std::fmt::Debug + 'static {
type Manifest: Manifest + 'static;
type Index: Index + 'static;
fn get_index(&self) -> Self::Index;
async fn write_key(&self, key: &EncryptedKey) -> Result<()>;
async fn read_key(&self) -> Result<EncryptedKey>;
fn get_manifest(&self) -> Self::Manifest;
async fn read_chunk(&mut self, location: SegmentDescriptor) -> Result<Chunk>;
async fn write_chunk(&mut self, chunk: Chunk) -> Result<SegmentDescriptor>;
async fn close(&mut self);
fn get_object_handle(&self) -> BackendObject;
}
pub trait BackendClone: Backend + Clone {}
impl<T: ?Sized> BackendClone for T where T: Backend + Clone {}
#[derive(Copy, PartialEq, Eq, Clone, Serialize, Deserialize, Debug)]
pub enum TransactionType {
Insert,
Delete,
}