Skip to main content

leveldb/database/
statistics.rs

1//! LevelDB statistics.
2use crate::binding::leveldb_approximate_sizes;
3use crate::database::Database;
4use crate::database::property::Property;
5use crate::database::slice::Slice;
6use std::ffi::NulError;
7use std::os::raw::{c_char, c_int};
8
9/// Represents a key range for approximate size calculation.
10pub struct KeyRange {
11    /// The start key of the range (inclusive).
12    pub start: Vec<u8>,
13    /// The end key of the range (exclusive).
14    pub end: Vec<u8>,
15}
16
17impl KeyRange {
18    /// Create a new key range from slices.
19    pub fn new(start: Slice<'_>, end: Slice<'_>) -> Self {
20        KeyRange {
21            start: start.as_bytes().to_vec(),
22            end: end.as_bytes().to_vec(),
23        }
24    }
25
26    /// Get the start key as a slice.
27    pub fn start(&self) -> Slice<'_> {
28        Slice::from(self.start.as_slice())
29    }
30
31    /// Get the end key as a slice.
32    pub fn end(&self) -> Slice<'_> {
33        Slice::from(self.end.as_slice())
34    }
35}
36
37/// Trait for accessing LevelDB statistics.
38pub trait Statistics: Property {
39    /// Get the number of files at a specific level.
40    fn get_num_files_at_level(&self, level: u32) -> Result<Option<String>, NulError> {
41        let property_name = format!(
42            "{}{}",
43            crate::database::property::property_name::NUM_FILES_AT_LEVEL,
44            level
45        );
46        self.get_property(&property_name)
47    }
48
49    /// Get LevelDB statistics.
50    fn get_stats(&self) -> Result<Option<String>, NulError> {
51        self.get_property(crate::database::property::property_name::STATS)
52    }
53
54    /// Get sstables information.
55    fn get_property_of_sstables(&self) -> Result<Option<String>, NulError> {
56        self.get_property(crate::database::property::property_name::SSTABLES)
57    }
58
59    /// Get approximate memory usage.
60    fn get_approximate_memory_usage(&self) -> Result<Option<String>, NulError> {
61        self.get_property(crate::database::property::property_name::APPROXIMATE_MEMORY_USAGE)
62    }
63
64    /// Get approximate file system sizes for key ranges.
65    ///
66    /// This function returns the approximate number of bytes of file system space used by one or more key ranges.
67    /// The sizes returned include data blocks, index blocks, and filter blocks for the specified ranges.
68    ///
69    /// # Arguments
70    /// * `ranges` - A vector of key ranges to calculate sizes for (ownership is transferred)
71    ///
72    /// # Returns
73    /// A vector of approximate sizes in bytes, corresponding to each input range.
74    ///
75    /// # Example
76    /// ```rust,ignore
77    /// let ranges = vec![
78    ///     KeyRange::new(start_slice, end_slice),
79    ///     KeyRange::new(start_slice2, end_slice2),
80    /// ];
81    /// let sizes = database.get_approximate_sizes(ranges);
82    /// ```
83    fn get_approximate_sizes(&self, ranges: Vec<KeyRange>) -> Vec<u64>;
84
85    /// Get the approximate file system size for a single key range.
86    ///
87    /// This is a convenience method that wraps `get_approximate_sizes` for a single range.
88    ///
89    /// # Arguments
90    /// * `start` - The start key of the range (inclusive)
91    /// * `end` - The end key of the range (exclusive)
92    ///
93    /// # Returns
94    /// The approximate size in bytes for the specified range.
95    fn get_approximate_size_for_range(&self, start: Slice<'_>, end: Slice<'_>) -> u64 {
96        let range = KeyRange::new(start, end);
97        let sizes = self.get_approximate_sizes(vec![range]);
98        assert!(sizes.len() == 1);
99        sizes[0]
100    }
101}
102
103impl Statistics for Database {
104    fn get_approximate_sizes(&self, ranges: Vec<KeyRange>) -> Vec<u64> {
105        let db_ptr = self.database.ptr;
106        let num_ranges = ranges.len();
107        if num_ranges == 0 {
108            return vec![];
109        }
110
111        let mut start_keys = Vec::with_capacity(num_ranges);
112        let mut start_key_lens = Vec::with_capacity(num_ranges);
113        let mut limit_keys = Vec::with_capacity(num_ranges);
114        let mut limit_key_lens = Vec::with_capacity(num_ranges);
115
116        for range in &ranges {
117            start_keys.push(range.start.as_ptr());
118            start_key_lens.push(range.start.len());
119
120            limit_keys.push(range.end.as_ptr());
121            limit_key_lens.push(range.end.len());
122        }
123
124        let mut sizes = vec![0u64; num_ranges];
125        unsafe {
126            leveldb_approximate_sizes(
127                db_ptr,
128                num_ranges as c_int,
129                start_keys.as_ptr() as *const *const c_char,
130                start_key_lens.as_ptr(),
131                limit_keys.as_ptr() as *const *const c_char,
132                limit_key_lens.as_ptr(),
133                sizes.as_mut_ptr(),
134            );
135        }
136
137        sizes
138    }
139}