lsm_tree/
descriptor_table.rs1use crate::sharded_cache::{ShardedCache, UnitWeighter};
6use alloc::sync::Arc;
7
8use crate::{GlobalTableId, fs::FsFile};
9
10const TAG_BLOCK: u8 = 0;
11const TAG_BLOB: u8 = 1;
12
13type Item = Arc<dyn FsFile>;
14
15#[derive(Clone, Copy, Eq, core::hash::Hash, PartialEq)]
16struct CacheKey(u8, u64, u64);
17
18const FD_CACHE_SHARDS: usize = 16;
22
23pub struct DescriptorTable {
25 inner: ShardedCache<CacheKey, Item, UnitWeighter, rustc_hash::FxBuildHasher>,
26 table_epoch: portable_atomic::AtomicU64,
31}
32
33impl DescriptorTable {
34 #[must_use]
35 pub fn new(capacity: usize) -> Self {
36 let inner = ShardedCache::with_weighter(
40 capacity as u64,
41 FD_CACHE_SHARDS,
42 capacity,
43 UnitWeighter,
44 rustc_hash::FxBuildHasher,
45 );
46
47 Self {
48 inner,
49 table_epoch: portable_atomic::AtomicU64::new(0),
50 }
51 }
52
53 pub(crate) fn table_epoch(&self) -> u64 {
55 self.table_epoch.load(portable_atomic::Ordering::Acquire)
56 }
57
58 fn advance_table_epoch(&self) {
62 self.table_epoch
63 .fetch_add(1, portable_atomic::Ordering::Release);
64 }
65
66 pub(crate) fn len(&self) -> usize {
67 self.inner.len()
68 }
69
70 pub(crate) fn capacity(&self) -> u64 {
72 self.inner.capacity()
73 }
74
75 pub(crate) fn remove_trees_from(&self, first: crate::tree::inner::TreeId) {
78 self.inner.remove_where(|key| key.1 >= first);
79 self.advance_table_epoch();
80 }
81
82 #[must_use]
83 pub fn access_for_table(&self, id: &GlobalTableId) -> Option<Arc<dyn FsFile>> {
84 let key = CacheKey(TAG_BLOCK, id.tree_id(), id.table_id());
85 self.inner.get(&key)
86 }
87
88 #[must_use]
91 pub(crate) fn peek_for_table(&self, id: &GlobalTableId) -> Option<Arc<dyn FsFile>> {
92 let key = CacheKey(TAG_BLOCK, id.tree_id(), id.table_id());
93 self.inner.peek(&key)
94 }
95
96 pub fn insert_for_table(&self, id: GlobalTableId, item: Item) {
97 let key = CacheKey(TAG_BLOCK, id.tree_id(), id.table_id());
98 self.inner.insert(key, item);
99 }
100
101 #[must_use]
102 pub fn access_for_blob_file(&self, id: &GlobalTableId) -> Option<Arc<dyn FsFile>> {
103 let key = CacheKey(TAG_BLOB, id.tree_id(), id.table_id());
104 self.inner.get(&key)
105 }
106
107 pub fn insert_for_blob_file(&self, id: GlobalTableId, item: Item) {
108 let key = CacheKey(TAG_BLOB, id.tree_id(), id.table_id());
109 self.inner.insert(key, item);
110 }
111
112 pub fn remove_for_table(&self, id: &GlobalTableId) {
115 let key = CacheKey(TAG_BLOCK, id.tree_id(), id.table_id());
116 self.inner.remove(&key);
117 self.advance_table_epoch();
118 }
119
120 pub fn remove_for_blob_file(&self, id: &GlobalTableId) {
121 let key = CacheKey(TAG_BLOB, id.tree_id(), id.table_id());
122 self.inner.remove(&key);
123 }
124}