Files
continuwuity/src/database/engine.rs
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

155 lines
3.6 KiB
Rust
Raw Normal View History

mod backup;
mod cf_opts;
pub(crate) mod context;
mod db_opts;
pub(crate) mod descriptor;
mod files;
mod logger;
mod memory_usage;
mod open;
mod repair;
use std::{
ffi::CStr,
sync::{
atomic::{AtomicU32, Ordering},
Arc,
},
};
2021-10-16 15:19:25 +02:00
use conduwuit::{debug, info, warn, Err, Result};
2025-01-18 12:05:07 +00:00
use rocksdb::{
AsColumnFamilyRef, BoundColumnFamily, DBCommon, DBWithThreadMode, MultiThreaded,
WaitForCompactOptions,
};
2024-04-06 08:48:41 -07:00
2025-01-18 12:05:07 +00:00
use crate::{
pool::Pool,
util::{map_err, result},
Context,
};
2024-05-28 06:59:50 +00:00
pub struct Engine {
2024-10-01 04:20:31 +00:00
pub(super) read_only: bool,
pub(super) secondary: bool,
corks: AtomicU32,
pub(crate) db: Db,
pub(crate) pool: Arc<Pool>,
pub(crate) ctx: Arc<Context>,
2021-10-16 15:19:25 +02:00
}
2024-06-29 19:57:22 +00:00
pub(crate) type Db = DBWithThreadMode<MultiThreaded>;
2024-05-28 06:59:50 +00:00
impl Engine {
#[tracing::instrument(
level = "info",
skip_all,
fields(
sequence = ?self.current_sequence(),
),
)]
pub fn wait_compactions_blocking(&self) -> Result {
let mut opts = WaitForCompactOptions::default();
opts.set_abort_on_pause(true);
opts.set_flush(false);
opts.set_timeout(0);
2024-03-05 19:48:54 -05:00
self.db.wait_for_compact(&opts).map_err(map_err)
}
#[tracing::instrument(
level = "info",
skip_all,
fields(
sequence = ?self.current_sequence(),
),
)]
pub fn sort(&self) -> Result {
let flushoptions = rocksdb::FlushOptions::default();
result(DBCommon::flush_opt(&self.db, &flushoptions))
}
#[tracing::instrument(
level = "debug",
skip_all,
fields(
sequence = ?self.current_sequence(),
),
)]
pub fn update(&self) -> Result { self.db.try_catch_up_with_primary().map_err(map_err) }
#[tracing::instrument(level = "info", skip_all)]
pub fn sync(&self) -> Result { result(DBCommon::flush_wal(&self.db, true)) }
#[tracing::instrument(level = "debug", skip_all)]
pub fn flush(&self) -> Result { result(DBCommon::flush_wal(&self.db, false)) }
2024-03-05 19:48:54 -05:00
#[inline]
pub(crate) fn cork(&self) { self.corks.fetch_add(1, Ordering::Relaxed); }
2024-03-06 18:02:19 -05:00
#[inline]
pub(crate) fn uncork(&self) { self.corks.fetch_sub(1, Ordering::Relaxed); }
2025-01-18 12:05:07 +00:00
#[inline]
pub fn corked(&self) -> bool { self.corks.load(Ordering::Relaxed) > 0 }
2025-01-18 12:05:07 +00:00
/// Query for database property by null-terminated name which is expected to
/// have a result with an integer representation. This is intended for
/// low-overhead programmatic use.
pub(crate) fn property_integer(
&self,
cf: &impl AsColumnFamilyRef,
name: &CStr,
) -> Result<u64> {
result(self.db.property_int_value_cf(cf, name))
.and_then(|val| val.map_or_else(|| Err!("Property {name:?} not found."), Ok))
}
/// Query for database property by name receiving the result in a string.
pub(crate) fn property(&self, cf: &impl AsColumnFamilyRef, name: &str) -> Result<String> {
result(self.db.property_value_cf(cf, name))
.and_then(|val| val.map_or_else(|| Err!("Property {name:?} not found."), Ok))
}
2024-11-14 22:43:18 +00:00
pub(crate) fn cf(&self, name: &str) -> Arc<BoundColumnFamily<'_>> {
self.db
.cf_handle(name)
.expect("column must be described prior to database open")
}
#[inline]
#[must_use]
#[tracing::instrument(name = "sequence", level = "debug", skip_all, fields(sequence))]
pub fn current_sequence(&self) -> u64 {
let sequence = self.db.latest_sequence_number();
#[cfg(debug_assertions)]
tracing::Span::current().record("sequence", sequence);
sequence
}
2024-11-14 22:43:18 +00:00
#[inline]
#[must_use]
pub fn is_read_only(&self) -> bool { self.secondary || self.read_only }
#[inline]
#[must_use]
pub fn is_secondary(&self) -> bool { self.secondary }
2021-10-16 15:19:25 +02:00
}
2024-05-09 15:59:08 -07:00
impl Drop for Engine {
#[cold]
2024-05-09 15:59:08 -07:00
fn drop(&mut self) {
const BLOCKING: bool = true;
2024-06-02 00:22:48 +00:00
debug!("Waiting for background tasks to finish...");
2024-05-28 06:59:50 +00:00
self.db.cancel_all_background_work(BLOCKING);
2024-05-09 15:59:08 -07:00
info!(
sequence = %self.current_sequence(),
"Closing database..."
);
2024-05-09 15:59:08 -07:00
}
}