rusty_leveldb/
options.rs

1use crate::cmp::{Cmp, DefaultCmp};
2use crate::compressor::{self, Compressor, CompressorId};
3use crate::env::Env;
4use crate::infolog::{self, Logger};
5use crate::mem_env::MemEnv;
6use crate::types::{share, Shared};
7use crate::Result;
8use crate::{filter, Status, StatusCode};
9
10use std::default::Default;
11use std::rc::Rc;
12
13const KB: usize = 1 << 10;
14const MB: usize = KB * KB;
15
16const BLOCK_MAX_SIZE: usize = 4 * KB;
17const BLOCK_CACHE_CAPACITY: usize = 8 * MB;
18const WRITE_BUFFER_SIZE: usize = 4 * MB;
19const DEFAULT_BITS_PER_KEY: u32 = 10; // NOTE: This may need to be optimized.
20
21/// Options contains general parameters for a LevelDB instance. Most of the names are
22/// self-explanatory; the defaults are defined in the `Default` implementation.
23#[derive(Clone)]
24pub struct Options {
25    pub cmp: Rc<Box<dyn Cmp>>,
26    pub env: Rc<Box<dyn Env>>,
27    pub log: Option<Shared<Logger>>,
28    pub create_if_missing: bool,
29    pub error_if_exists: bool,
30    pub paranoid_checks: bool,
31    pub write_buffer_size: usize,
32    pub max_open_files: usize,
33    pub max_file_size: usize,
34    pub block_cache_capacity_bytes: usize,
35    pub block_size: usize,
36    pub block_restart_interval: usize,
37    /// Compressor id in compressor list
38    ///
39    /// Note: you have to open a database with the same compression type as it was written to, in
40    /// order to not lose data! (this is a bug and will be fixed)
41    pub compressor: u8,
42
43    pub compressor_list: Rc<CompressorList>,
44    pub reuse_logs: bool,
45    pub reuse_manifest: bool,
46    pub filter_policy: filter::BoxedFilterPolicy,
47}
48
49#[cfg(feature = "fs")]
50type DefaultEnv = crate::disk_env::PosixDiskEnv;
51
52#[cfg(not(feature = "fs"))]
53type DefaultEnv = crate::mem_env::MemEnv;
54
55impl Default for Options {
56    fn default() -> Options {
57        Options {
58            cmp: Rc::new(Box::new(DefaultCmp)),
59            env: Rc::new(Box::new(DefaultEnv::new())),
60            log: None,
61            create_if_missing: true,
62            error_if_exists: false,
63            paranoid_checks: false,
64            write_buffer_size: WRITE_BUFFER_SIZE,
65            max_open_files: 1 << 10,
66            max_file_size: 2 << 20,
67            block_cache_capacity_bytes: BLOCK_MAX_SIZE * 1024,
68            block_size: BLOCK_MAX_SIZE,
69            block_restart_interval: 16,
70            reuse_logs: true,
71            reuse_manifest: true,
72            compressor: 0,
73            compressor_list: Rc::new(CompressorList::default()),
74            filter_policy: Rc::new(Box::new(filter::BloomPolicy::new(DEFAULT_BITS_PER_KEY))),
75        }
76    }
77}
78
79/// Customize compressor method for leveldb
80///
81/// `Default` value is like the code below
82/// ```
83/// # use rusty_leveldb::{compressor, CompressorList};
84/// let mut list = CompressorList::new();
85/// list.set(compressor::NoneCompressor);
86/// list.set(compressor::SnappyCompressor);
87/// ```
88pub struct CompressorList([Option<Box<dyn Compressor>>; 256]);
89
90impl CompressorList {
91    /// Create a **Empty** compressor list
92    pub fn new() -> Self {
93        const INIT: Option<Box<dyn Compressor>> = None;
94        Self([INIT; 256])
95    }
96
97    /// Set compressor with the id in `CompressorId` trait
98    pub fn set<T>(&mut self, compressor: T)
99    where
100        T: Compressor + CompressorId + 'static,
101    {
102        self.set_with_id(T::ID, compressor)
103    }
104
105    /// Set compressor with id
106    pub fn set_with_id(&mut self, id: u8, compressor: impl Compressor + 'static) {
107        self.0[id as usize] = Some(Box::new(compressor));
108    }
109
110    pub fn is_set(&self, id: u8) -> bool {
111        self.0[id as usize].is_some()
112    }
113
114    pub fn get(&self, id: u8) -> Result<&dyn Compressor> {
115        self.0[id as usize]
116            .as_ref()
117            .map(AsRef::as_ref)
118            .ok_or_else(|| Status {
119                code: StatusCode::NotSupported,
120                err: format!("invalid compression id `{}`", id),
121            })
122    }
123}
124
125impl Default for CompressorList {
126    fn default() -> Self {
127        let mut list = Self::new();
128        list.set(compressor::NoneCompressor);
129        list.set(compressor::SnappyCompressor);
130        list
131    }
132}
133
134/// Returns Options that will cause a database to exist purely in-memory instead of being stored on
135/// disk. This is useful for testing or ephemeral databases.
136pub fn in_memory() -> Options {
137    Options {
138        env: Rc::new(Box::new(MemEnv::new())),
139        ..Options::default()
140    }
141}
142
143pub fn for_test() -> Options {
144    Options {
145        env: Rc::new(Box::new(MemEnv::new())),
146        log: Some(share(infolog::stderr())),
147        ..Options::default()
148    }
149}