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