//! The backend provides abstract IO access to the real location of the data in //! the repository. use std::io::Result; pub mod filesystem; /// Segments are abstract blocks of chunks /// /// Backends are free to arrange chunks within segements any way they wish, /// as long as they only ever append to existing segments. /// /// Segement compaction must happen through writing new segments and deleting /// the old ones pub trait Segment { /// Returns the free bytes in this segment fn free_bytes(&self) -> u64; /// Reads a chunk from the segment into a bytestring /// /// Requires the start and end positions for the chunk /// /// Will return None if the read fails fn read_chunk(&mut self, start: u64, length: u64) -> Option>; /// Writes a chunk to the segment /// /// Retuns Some(start,length), or None if writing fails fn write_chunk(&mut self, chunk: &[u8]) -> Option<(u64, u64)>; } /// Repository backend /// /// The backend handles the heavy lifiting of the IO, abstracting the repository /// struct itself away from the details of the system used to store the repository. /// /// Cloning a backend should result in a new view over the same storage, and clones /// should play nice with multithreaded access. pub trait Backend: Send + Sync + Clone { /// Gets a particular segment /// /// Returns None if it does not exist or can not be found fn get_segment(&self, id: u64) -> Option>; /// Returns the id of the higest segment fn highest_segment(&self) -> u64; /// Creates a new segment /// /// Returns Some(id) with the segement if it can be created /// Returns None if creation fails. fn make_segment(&self) -> Option; /// Returns the index of the repository /// /// Indexes are stored as byte strings, intrepreation is up to the caller fn get_index(&self) -> Vec; /// Writes a new index to the backend /// /// Backend should write the new index first, and then delete the old one /// /// Returns Err if the index could not be written. fn write_index(&self, index: &[u8]) -> Result<()>; }