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}