small_db/utils/
unique.rs

1use std::{
2    mem,
3    sync::{Arc, Once, RwLock, RwLockReadGuard, RwLockWriteGuard},
4};
5
6use super::HandyRwLock;
7use crate::{
8    btree::page_cache::PageCache,
9    concurrent_status::ConcurrentStatus, tx_log::LogManager,
10    types::Pod, Catalog,
11};
12
13/// We collect all global variables here.
14///
15/// These variable cannot be initialized as static variables, because
16/// their initialization function all rely on non-const fn (e.g.
17/// `HashMap::new()`).
18///
19/// In the same time, all these variables should not be wrapped in any
20/// kind of smark pointers / locks (e.g. `Arc`, `RwLock`), because
21/// they are used in concurrent environment, and it's hard, if not
22/// impossible, to acquire a exclusive lock in any context.
23pub struct Unique {
24    buffer_pool: Pod<PageCache>,
25    catalog: Pod<Catalog>,
26    concurrent_status: ConcurrentStatus,
27    log_file: Pod<LogManager>,
28}
29
30impl Unique {
31    fn new() -> Self {
32        Self {
33            buffer_pool: Arc::new(RwLock::new(PageCache::new())),
34            concurrent_status: ConcurrentStatus::new(),
35            catalog: Arc::new(RwLock::new(Catalog::new())),
36            log_file: Arc::new(RwLock::new(LogManager::new(
37                "wal.log",
38            ))),
39        }
40    }
41
42    // pub fn buffer_pool() -> &'static BufferPool {
43    //     &Self::global().buffer_pool
44    // }
45
46    pub fn mut_page_cache() -> RwLockWriteGuard<'static, PageCache> {
47        Self::global().buffer_pool.wl()
48    }
49
50    pub fn buffer_pool_pod() -> Arc<RwLock<PageCache>> {
51        Self::global().buffer_pool.clone()
52    }
53
54    // pub fn buffer_pool() -> &'static BufferPool {
55    //     &Self::global().buffer_pool
56    // }
57
58    pub fn concurrent_status() -> &'static ConcurrentStatus {
59        &Self::global().concurrent_status
60    }
61
62    pub fn catalog() -> RwLockReadGuard<'static, Catalog> {
63        Self::global().catalog.rl()
64    }
65
66    pub fn mut_catalog() -> RwLockWriteGuard<'static, Catalog> {
67        Self::global().catalog.wl()
68    }
69
70    pub fn log_file() -> RwLockReadGuard<'static, LogManager> {
71        Self::global().log_file.rl()
72    }
73
74    pub fn mut_log_manager() -> RwLockWriteGuard<'static, LogManager>
75    {
76        Self::global().log_file.wl()
77    }
78
79    pub fn log_file_pod() -> Arc<RwLock<LogManager>> {
80        Self::global().log_file.clone()
81    }
82
83    pub fn global() -> &'static Self {
84        // Initialize it to a null value
85        static mut SINGLETON: *mut Unique = 0 as *mut Unique;
86        static ONCE: Once = Once::new();
87
88        ONCE.call_once(|| {
89            // Make it
90            let singleton = Self::new();
91
92            unsafe {
93                // Put it in the heap so it can outlive this call
94                SINGLETON = mem::transmute(Box::new(singleton));
95            }
96        });
97
98        unsafe {
99            // Now we give out a copy of the data that is safe to use
100            // concurrently.
101            SINGLETON.as_ref().unwrap()
102        }
103    }
104}