//! Inserting into the persistant cache. use super::*; use ::bytes::BytesMut; use std::path::Path; use tokio::fs::{self, File}; use std::io; use tokio::io::AsyncWrite; use mem::MemoryMut; /// The write rule used for cache insertion operations. /// This ensures the number of bytes returned corresponds to the number written into memory. /// /// This is because we care more about the integrity of memcached data, because we can dump that to disk later if the integrity of the disk copy is incorrect. #[derive(Debug)] enum CacheWriteRule{} impl plex::WriteRule for CacheWriteRule { #[inline(always)] fn compare_byte_sizes(a: usize, b: usize) -> Result { Ok(std::cmp::max(a,b)) } } /// A partially formed cache entry that can be mutated. /// It has not yet been inserted into a persistant `ByteCache` cache, and is write-only. pub struct PartialCacheEntry { cfg: Arc, id: Uuid, key: K, file: Option, memory: MemoryMut, } /// The writer type for writing to a `PartialCacheEntry`. pub type PartialCacheEntrySink<'a> = Box; impl PartialCacheEntry { #[inline(always)] pub(super) fn new_uninit(owner: &ByteCache, key: K) -> Self { Self { cfg: Arc::clone(&owner.cfg), id: Uuid::new_v4(), file: None, memory: MemoryMut::new(), key, } } #[inline(always)] pub(super) async fn init(&mut self) -> io::Result<()> { //self.memory.reserve(PAGE_SIZE); if let Some(root) = &self.cfg.disk_location { self.file = Some(fs::OpenOptions::new() .write(true) .open(gen_temp_path(root, &self.id)).await?); } Ok(()) } /// Create a writer for this entry pub fn writer(&mut self) -> PartialCacheEntrySink<'_> { if let Some(file) = self.file.as_mut() { Box::new((&mut self.memory).multiplex_ruled::<_, CacheWriteRule>(file)) } else { Box::new(&mut self.memory) } } } /// Create a path for a **non-completed** entry pub(super) fn gen_temp_path(root: impl AsRef, from: &Uuid) -> PathBuf { root.as_ref().join(format!("{}.open", from)) } /// Create a path for a **completed** entry pub(super) fn gen_path(root: impl AsRef, from: &Uuid) -> PathBuf { root.as_ref().join(format!("{}.entry", from)) }