Skip to main content

raindb/
options.rs

1// Copyright (c) 2021 Google LLC
2//
3// Use of this source code is governed by an MIT-style
4// license that can be found in the LICENSE file or at
5// https://opensource.org/licenses/MIT.
6
7/*!
8This module holds the various option structures that can be passed to RainDB operations
9*/
10
11use std::sync::Arc;
12
13use crate::filter_policy::{BloomFilterPolicy, FilterPolicy};
14use crate::fs::{FileSystem, InMemoryFileSystem, OsFileSystem};
15use crate::tables::block::DataBlockReader;
16use crate::tables::BlockCacheKey;
17use crate::utils::cache::LRUCache;
18use crate::{Cache, Snapshot};
19
20/**
21Holds options to control database behavior.
22
23There is a mix of options to configure here that are remniscent of those configurable in
24LevelDB and RocksDB.
25*/
26#[derive(Clone, Debug)]
27pub struct DbOptions {
28    // TODO: Add option for users to set a custom comparator.
29    /**
30    The path of the director to use for the database's operations.
31
32    **This defaults to the current working directory.**
33    */
34    pub db_path: String,
35
36    /**
37    The maximum size that the memtable can reach before it is flushed to disk.
38
39    Up to two memtables can reside in memory at a time, one actively serving reads and writes
40    and a second one in the process of being flushed to disk.
41
42    This option corresponds to `write_buffer_size` in LevelDB. We feel the RainDB name is more clear
43    as to what function this option performs.
44
45    **This defaults to 4 MiB.**
46    */
47    pub max_memtable_size: usize,
48
49    /**
50    This amount of bytes will be written to a file before switching to a new one.
51
52    Most clients should leave this parameter alone. However if your filesystem is more efficient
53    with larger files, you could consider increasing the value. The downside will be longer
54    compactions and hence longer latency/performance hiccups. Another reason to increase this
55    parameter might be when you are initially populating a large database.
56
57    **This defaults to 2 MiB.**
58    */
59    pub max_file_size: u64,
60
61    /**
62    The approximate maximum size of user data that is allowed to be packed into a block of a table
63    file.
64
65    The data considered here is uncompressed data. The actual size of the data on disk may be smaller
66    due to compression.
67
68    In LevelDB this is configurable and has a default size of 4 KiB.
69    */
70    pub max_block_size: usize,
71
72    /**
73    A wrapper around a particular file system to use.
74
75    **This defaults to [`OsFileSystem`](crate::fs::OsFileSystem).**
76    */
77    pub filesystem_provider: Arc<dyn FileSystem>,
78
79    /**
80    The filter policy to use for filtering requests to table files to reduce disk seeks.
81
82    **This defaults to [`BloomFilterPolicy`](crate::filter_policy::BloomFilterPolicy).**
83    */
84    pub filter_policy: Arc<dyn FilterPolicy>,
85
86    /**
87    Cache used to store blocks read from disk in-memory to save on disk reads.
88
89    This cache store uncompressed data so--if changed--the cache size should be appropriate to the
90    application using the database.
91
92    **This defaults to an 8 MiB internal cache if not set.**
93    */
94    pub block_cache: Arc<dyn Cache<BlockCacheKey, Arc<DataBlockReader>>>,
95
96    /// If true, the database will be created if it is missing.
97    pub create_if_missing: bool,
98
99    /// If true, an error is raised if the database already exists.
100    pub error_if_exists: bool,
101
102    /**
103    If true, append to existing manifest and write-ahead logs when opening a database.
104
105    **This defaults to true (unlike in LevelDB that defaults to false).**
106    */
107    pub reuse_log_files: bool,
108}
109
110/// Public methods
111impl DbOptions {
112    /// Get [`DbOptions`] with an in-memory file system.
113    pub fn with_memory_env() -> DbOptions {
114        DbOptions {
115            filesystem_provider: Arc::new(InMemoryFileSystem::new()),
116            ..DbOptions::default()
117        }
118    }
119
120    /// Get the database path.
121    pub fn db_path(&self) -> &str {
122        self.db_path.as_str()
123    }
124
125    /// Get the write buffer size.
126    pub fn max_memtable_size(&self) -> usize {
127        self.max_memtable_size
128    }
129
130    /// Get the database's maximum table file size.
131    pub fn max_file_size(&self) -> u64 {
132        self.max_file_size
133    }
134
135    /// Get the maximum block size.
136    pub fn max_block_size(&self) -> usize {
137        self.max_block_size
138    }
139
140    /// Get the whether the database is reusing log files.
141    pub fn reuse_log_files(&self) -> bool {
142        self.reuse_log_files
143    }
144
145    /// Get a strong reference to the file system provider.
146    pub fn filesystem_provider(&self) -> Arc<dyn FileSystem> {
147        Arc::clone(&self.filesystem_provider)
148    }
149
150    /// Get a strong reference to the filter policy.
151    pub fn filter_policy(&self) -> Arc<dyn FilterPolicy> {
152        Arc::clone(&self.filter_policy)
153    }
154
155    /// Get a strong reference to the block cache.
156    pub fn block_cache(&self) -> Arc<dyn Cache<BlockCacheKey, Arc<DataBlockReader>>> {
157        Arc::clone(&self.block_cache)
158    }
159
160    /// Returns true if we should create the database if it is missing.
161    pub fn create_if_missing(&self) -> bool {
162        self.create_if_missing
163    }
164
165    /// Get a reference to the db options's error if exists.
166    pub fn error_if_exists(&self) -> bool {
167        self.error_if_exists
168    }
169}
170
171impl Default for DbOptions {
172    fn default() -> Self {
173        DbOptions {
174            db_path: std::env::current_dir()
175                .unwrap()
176                .to_str()
177                .unwrap()
178                .to_owned(),
179            max_memtable_size: 4 * 1024 * 1024,
180            max_file_size: 2 * 1024 * 1024,
181            max_block_size: 4 * 1024,
182            filesystem_provider: Arc::new(OsFileSystem::new()),
183            filter_policy: Arc::new(BloomFilterPolicy::new(10)),
184            block_cache: Arc::new(LRUCache::<BlockCacheKey, Arc<DataBlockReader>>::new(
185                8 * 1024 * 1024,
186            )),
187            create_if_missing: false,
188            error_if_exists: false,
189            reuse_log_files: true,
190        }
191    }
192}
193
194/// Options for read operations.
195#[derive(Clone, Debug)]
196pub struct ReadOptions {
197    /**
198    Cache data read as a result of a read operation.
199
200    Callers may want to set this to false for bulk scans.
201
202    **Defaults to true.**
203    */
204    pub fill_cache: bool,
205
206    /**
207    Configure the read operation to read as of the state of the supplied snapshot. If [`None`], the
208    read will be performed at the state of the database when the request was received.
209
210    This snapshot must have been received by the database it is being passed to and must not have
211    been released yet.
212    */
213    pub snapshot: Option<Snapshot>,
214}
215
216impl Default for ReadOptions {
217    fn default() -> Self {
218        Self {
219            fill_cache: true,
220            snapshot: None,
221        }
222    }
223}
224
225/// Options for write operations.
226#[derive(Clone, Debug)]
227pub struct WriteOptions {
228    /**
229    Whether or not to perform the write operation synchronously.
230
231    If true, the program will try to ensure that the write is flusehd completely to disk before it
232    considers the write complete. This extra check means that writes with this flag on will be
233    slower.
234
235    If false and the machine crashes, some recent writes might be lost. Note that, if it is just the
236    program that crashes (i.e. the machine does not reboot), then no writes will be lost.
237
238    In other words, writes with this flag `false` has the same semantics as just a `write()` system
239    call. A write with the flag as `true` has the semantics of a `write()` followed by an `fsync()`.
240
241    **Defaults to false.**
242    */
243    pub synchronous: bool,
244}
245
246impl Default for WriteOptions {
247    fn default() -> Self {
248        Self { synchronous: false }
249    }
250}