Skip to main content

xet_client/chunk_cache/
mod.rs

1#[cfg(not(target_family = "wasm"))]
2mod cache_manager;
3#[cfg(not(target_family = "wasm"))]
4mod disk;
5pub mod error;
6
7use std::path::PathBuf;
8
9use async_trait::async_trait;
10#[cfg(not(target_family = "wasm"))]
11pub use cache_manager::get_cache;
12#[cfg(not(target_family = "wasm"))]
13pub use disk::DiskCache;
14#[cfg(not(target_family = "wasm"))]
15pub use disk::test_utils::*;
16use error::ChunkCacheError;
17#[cfg(test)]
18use mockall::automock;
19use xet_runtime::config::XetConfig;
20
21use crate::cas_types::{ChunkRange, Key};
22
23/// Return dto for cache gets
24/// offsets has 1 more than then number of chunks in the specified range
25/// suppose the range is for chunks [2, 5) then offsets may look like:
26/// [0, 2000, 4000, 6000] where chunk 2 is made of bytes [0, 2000)
27/// chunk 3 [2000, 4000) and chunk 4 is [4000, 6000).
28/// It is guaranteed that the first number in offsets is 0 and the last number is data.len()
29#[derive(Debug)]
30pub struct CacheRange {
31    pub offsets: Vec<u32>,
32    pub data: Vec<u8>,
33    pub range: ChunkRange,
34}
35
36/// ChunkCache is a trait for storing and fetching Xorb ranges.
37/// implementors are expected to return bytes for a key and a given chunk range
38/// (no compression or further deserialization should be required)
39/// Range inputs use chunk indices in an end exclusive way i.e. [start, end)
40///
41/// implementors are allowed to evict data, a get after a put is not required to
42/// be a cache hit.
43#[cfg_attr(test, automock)]
44#[async_trait]
45pub trait ChunkCache: Sync + Send {
46    /// get should return an Ok() variant if significant error occurred, check the error
47    /// variant for issues with IO or parsing contents etc.
48    ///
49    /// if get returns an Ok(None) then there was no error, but there was a cache miss
50    /// otherwise returns an Ok(Some(data)) where data matches exactly the bytes for
51    /// the requested key and the requested chunk index range for that key
52    ///
53    /// Given implementors are expected to be able to evict members there's no guarantee
54    /// that a previously put range will be a cache hit
55    ///
56    /// key is required to be a valid XORB key
57    /// range is intended to be an index range within the xorb with constraint
58    ///     0 <= range.start < range.end <= num_chunks_in_xorb(key)
59    async fn get(&self, key: &Key, range: &ChunkRange) -> Result<Option<CacheRange>, ChunkCacheError>;
60
61    /// put should return Ok(()) if the put succeeded with no error, check the error
62    /// variant for issues with validating the input, cache state, IO, etc.
63    ///
64    /// put expects that chunk_byte_indices.len() is range.end - range.start + 1
65    /// with 1 entry for each start byte index for [range.start, range.end]
66    /// the first entry must be 0 (start of first chunk in the data)
67    /// the last entry must be data.len() i.e. the end of data, start of chunk past end
68    ///
69    /// key is required to be a valid XORB key
70    /// range is intended to be an index range within the xorb with constraint
71    ///     0 <= range.start < range.end <= num_chunks_in_xorb(key)
72    async fn put(
73        &self,
74        key: &Key,
75        range: &ChunkRange,
76        chunk_byte_indices: &[u32],
77        data: &[u8],
78    ) -> Result<(), ChunkCacheError>;
79}
80
81#[derive(Debug, Clone)]
82pub struct CacheConfig {
83    pub cache_directory: PathBuf,
84    pub cache_size: u64,
85}
86
87impl CacheConfig {
88    pub fn from_config(config: &XetConfig) -> Self {
89        CacheConfig {
90            cache_directory: PathBuf::from("/tmp"),
91            cache_size: config.chunk_cache.size_bytes,
92        }
93    }
94}