risingwave_storage/hummock/
block_cache.rs1use std::ops::Deref;
16use std::sync::Arc;
17
18use await_tree::{InstrumentAwait, SpanExt};
19use foyer::{HybridCacheEntry, HybridGetOrFetch};
20use risingwave_common::config::EvictionConfig;
21
22use super::{Block, HummockResult, SstableBlockIndex};
23use crate::hummock::HummockError;
24
25type HybridCachedBlockEntry = HybridCacheEntry<SstableBlockIndex, Box<Block>>;
26
27pub enum BlockEntry {
28 HybridCache(HybridCachedBlockEntry),
29 Owned(Box<Block>),
30 RefEntry(Arc<Block>),
31}
32
33pub struct BlockHolder {
34 _handle: BlockEntry,
35 block: *const Block,
37}
38
39impl BlockHolder {
40 pub fn from_ref_block(block: Arc<Block>) -> Self {
41 let ptr = block.as_ref() as *const _;
42 Self {
43 _handle: BlockEntry::RefEntry(block),
44 block: ptr,
45 }
46 }
47
48 pub fn from_owned_block(block: Box<Block>) -> Self {
49 let ptr = block.as_ref() as *const _;
50 Self {
51 _handle: BlockEntry::Owned(block),
52 block: ptr,
53 }
54 }
55
56 pub fn from_hybrid_cache_entry(entry: HybridCachedBlockEntry) -> Self {
57 let ptr = entry.value().as_ref() as *const _;
58 Self {
59 _handle: BlockEntry::HybridCache(entry),
60 block: ptr,
61 }
62 }
63
64 pub fn entry(&self) -> &BlockEntry {
65 &self._handle
66 }
67}
68
69impl Deref for BlockHolder {
70 type Target = Block;
71
72 fn deref(&self) -> &Self::Target {
73 unsafe { &(*self.block) }
76 }
77}
78
79unsafe impl Send for BlockHolder {}
80unsafe impl Sync for BlockHolder {}
81
82#[derive(Debug)]
83pub struct BlockCacheConfig {
84 pub capacity: usize,
85 pub shard_num: usize,
86 pub eviction: EvictionConfig,
87}
88
89pub enum BlockResponse {
90 Block(BlockHolder),
91 Fetch(HybridGetOrFetch<SstableBlockIndex, Box<Block>>),
92}
93
94impl BlockResponse {
95 pub async fn wait(self) -> HummockResult<BlockHolder> {
96 let fetch = match self {
97 BlockResponse::Block(block) => return Ok(block),
98 BlockResponse::Fetch(fetch) => fetch,
99 };
100 let fetch = match fetch.try_unwrap() {
101 Ok(entry) => return Ok(BlockHolder::from_hybrid_cache_entry(entry)),
102 Err(fetch) => fetch,
103 };
104 fetch
105 .instrument_await("wait_pending_fetch_block".verbose())
106 .await
107 .map(BlockHolder::from_hybrid_cache_entry)
108 .map_err(HummockError::foyer_error)
109 }
110}