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}