rust_rocksdb/
cache.rs

1use crate::{LruCacheOptions, ffi};
2use libc::size_t;
3use std::ptr::NonNull;
4use std::sync::Arc;
5
6pub(crate) struct CacheWrapper {
7    pub(crate) inner: NonNull<ffi::rocksdb_cache_t>,
8}
9
10unsafe impl Send for CacheWrapper {}
11unsafe impl Sync for CacheWrapper {}
12
13impl Drop for CacheWrapper {
14    fn drop(&mut self) {
15        unsafe {
16            ffi::rocksdb_cache_destroy(self.inner.as_ptr());
17        }
18    }
19}
20
21#[derive(Clone)]
22pub struct Cache(pub(crate) Arc<CacheWrapper>);
23
24impl Cache {
25    /// Creates an LRU cache with capacity in bytes.
26    pub fn new_lru_cache(capacity: size_t) -> Cache {
27        let inner = NonNull::new(unsafe { ffi::rocksdb_cache_create_lru(capacity) }).unwrap();
28        Cache(Arc::new(CacheWrapper { inner }))
29    }
30
31    /// Creates an LRU cache with custom options.
32    pub fn new_lru_cache_opts(opts: &LruCacheOptions) -> Cache {
33        let inner =
34            NonNull::new(unsafe { ffi::rocksdb_cache_create_lru_opts(opts.inner) }).unwrap();
35        Cache(Arc::new(CacheWrapper { inner }))
36    }
37
38    /// Creates a HyperClockCache with `capacity` in bytes.
39    ///
40    /// HyperClockCache is now generally recommended over LRUCache. See RocksDB's
41    /// [HyperClockCacheOptions in cache.h](https://github.com/facebook/rocksdb/blob/main/include/rocksdb/cache.h)
42    /// for details.
43    ///
44    /// `estimated_entry_charge` is an optional parameter. When not provided
45    /// (== 0, recommended and default), an HCC variant with a
46    /// dynamically-growing table and generally good performance is used. This
47    /// variant depends on anonymous mmaps so might not be available on all
48    /// platforms.
49    ///
50    /// If the average "charge" (uncompressed block size) of block cache entries
51    /// is reasonably predicted and provided here, the most efficient variant of
52    /// HCC is used. Performance is degraded if the prediction is inaccurate.
53    /// Prediction could be difficult or impossible with cache-charging features
54    /// such as WriteBufferManager. The best parameter choice based on a cache
55    /// in use is roughly given by `cache.get_usage() / cache.get_occupancy_count()`,
56    /// though it is better to estimate toward the lower side than the higher
57    /// side when the ratio might vary.
58    pub fn new_hyper_clock_cache(capacity: size_t, estimated_entry_charge: size_t) -> Cache {
59        Cache(Arc::new(CacheWrapper {
60            inner: NonNull::new(unsafe {
61                ffi::rocksdb_cache_create_hyper_clock(capacity, estimated_entry_charge)
62            })
63            .unwrap(),
64        }))
65    }
66
67    /// Returns the cache memory usage in bytes.
68    pub fn get_usage(&self) -> usize {
69        unsafe { ffi::rocksdb_cache_get_usage(self.0.inner.as_ptr()) }
70    }
71
72    /// Returns the pinned memory usage in bytes.
73    pub fn get_pinned_usage(&self) -> usize {
74        unsafe { ffi::rocksdb_cache_get_pinned_usage(self.0.inner.as_ptr()) }
75    }
76
77    /// Sets cache capacity in bytes.
78    pub fn set_capacity(&mut self, capacity: size_t) {
79        unsafe {
80            ffi::rocksdb_cache_set_capacity(self.0.inner.as_ptr(), capacity);
81        }
82    }
83}