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; #[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 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
79pub struct CompressorList([Option<Box<dyn Compressor>>; 256]);
89
90impl CompressorList {
91 pub fn new() -> Self {
93 const INIT: Option<Box<dyn Compressor>> = None;
94 Self([INIT; 256])
95 }
96
97 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 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
134pub 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}