Skip to main content

tuwunel_database/
map.rs

1mod clear;
2pub mod compact;
3mod contains;
4mod count;
5mod del;
6mod del_prefix;
7mod get;
8mod get_batch;
9mod insert;
10mod keys;
11mod keys_from;
12mod keys_prefix;
13mod open;
14mod options;
15mod put;
16mod qry;
17mod qry_batch;
18mod remove;
19mod rev_keys;
20mod rev_keys_from;
21mod rev_keys_prefix;
22mod rev_stream;
23mod rev_stream_from;
24mod rev_stream_prefix;
25mod seek;
26mod stream;
27mod stream_from;
28mod stream_prefix;
29mod watch;
30
31use std::{
32	ffi::CStr,
33	fmt,
34	fmt::{Debug, Display},
35	path::Path,
36	sync::Arc,
37};
38
39use rocksdb::{
40	AsColumnFamilyRef, ColumnFamily, DBCommon, ReadOptions, WriteOptions, checkpoint::Checkpoint,
41};
42use tuwunel_core::Result;
43
44pub(crate) use self::options::{
45	cache_iter_options_default, cache_read_options_default, iter_options_default,
46	read_options_default, write_options_default,
47};
48use self::watch::Watch;
49/// Stream extensions for batched map reads.
50///
51/// `Get` accepts raw keys, while `Qry` serializes structured keys before
52/// lookup. Both yield pinned value handles through an asynchronous stream.
53pub use self::{get_batch::Get, qry_batch::Qry};
54use crate::{Engine, util::map_err};
55
56/// Provides typed and raw access to one RocksDB column family.
57///
58/// A map retains its column-family handle and the engine that owns it. Point
59/// operations reuse read and write options prepared when the map opens.
60pub struct Map {
61	name: &'static str,
62	watch: Watch,
63	cf: Arc<ColumnFamily>,
64	engine: Arc<Engine>,
65	read_options: ReadOptions,
66	cache_read_options: ReadOptions,
67	write_options: WriteOptions,
68}
69
70impl Map {
71	/// Opens a map for a named column family.
72	///
73	/// The returned map keeps the engine alive for at least as long as its
74	/// column-family handle. Its read and write options are initialized from
75	/// the engine configuration.
76	pub(crate) fn open(engine: &Arc<Engine>, name: &'static str) -> Result<Arc<Self>> {
77		Ok(Arc::new(Self {
78			name,
79			watch: Watch::default(),
80			cf: open::open(engine, name),
81			engine: engine.clone(),
82			read_options: read_options_default(engine),
83			cache_read_options: cache_read_options_default(engine),
84			write_options: write_options_default(engine),
85		}))
86	}
87
88	/// Flush this map's memtable to SST files (a RocksDB LSM-tree flush).
89	///
90	/// Forces the column family's buffered writes out of memory into the
91	/// on-disk LSM tree. An LSM flush, not a libc `fflush(3)` or `fsync(2)`,
92	/// and distinct from the engine's `flush` and `sync`, which act on the
93	/// write-ahead log.
94	#[tracing::instrument(
95		level = "info",
96		skip_all,
97		fields(
98			map = self.name(),
99			sequence = ?self.engine.current_sequence(),
100		),
101	)]
102	pub fn sort(&self) -> Result {
103		let cf = self.cf();
104		let flushoptions = rocksdb::FlushOptions::default();
105		DBCommon::flush_cf_opt(&self.engine.db, &cf, &flushoptions).map_err(map_err)
106	}
107
108	/// Exports this map's column family to a physical checkpoint at `path`.
109	///
110	/// RocksDB flushes the column family before exporting its live SST files.
111	#[tracing::instrument(level = "info", skip(self))]
112	pub fn checkpoint(&self, path: &Path) -> Result {
113		let checkpoint = Checkpoint::new(&self.engine.db).map_err(map_err)?;
114		let cf = self.cf();
115
116		checkpoint
117			.export_column_family(&cf, path)
118			.map(drop)
119			.map_err(map_err)
120	}
121
122	/// Reads an integer RocksDB property for this map.
123	///
124	/// The property query is scoped to this map's column family. Engine errors
125	/// are returned to the caller.
126	#[inline]
127	pub fn property_integer(&self, name: &CStr) -> Result<u64> {
128		self.engine.property_integer(&self.cf(), name)
129	}
130
131	/// Reads a string RocksDB property for this map.
132	///
133	/// The property query is scoped to this map's column family. Engine errors
134	/// are returned to the caller.
135	#[inline]
136	pub fn property(&self, name: &str) -> Result<String> {
137		self.engine.property(&self.cf(), name)
138	}
139
140	/// Returns the column-family name of this map.
141	///
142	/// The name is fixed when the map opens and lives for the duration of the
143	/// process.
144	#[inline]
145	pub fn name(&self) -> &str { self.name }
146
147	/// Returns the engine that owns this map.
148	///
149	/// The borrowed `Arc` keeps the same identity used to open the
150	/// column-family handle.
151	#[inline]
152	pub(crate) fn engine(&self) -> &Arc<Engine> { &self.engine }
153
154	/// Returns this map's RocksDB column-family handle.
155	///
156	/// The handle remains valid because the map retains its owning engine.
157	#[inline]
158	pub(crate) fn cf(&self) -> impl AsColumnFamilyRef + '_ { &*self.cf }
159
160	/// Returns the numeric RocksDB identifier for this column family.
161	///
162	/// The identifier belongs to this map's engine and must not be compared
163	/// across engines.
164	#[inline]
165	pub(crate) fn cf_id(&self) -> u32 { self.cf().id() }
166}
167
168impl Debug for Map {
169	fn fmt(&self, out: &mut fmt::Formatter<'_>) -> fmt::Result {
170		write!(out, "Map {{name: {0}}}", self.name)
171	}
172}
173
174impl Display for Map {
175	fn fmt(&self, out: &mut fmt::Formatter<'_>) -> fmt::Result { write!(out, "{0}", self.name) }
176}