2025-01-06 14:07:26 +00:00
|
|
|
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;
|
|
|
|
|
2024-04-08 01:29:52 -07:00
|
|
|
use std::{
|
2024-08-02 01:40:41 +00:00
|
|
|
ffi::CStr,
|
2025-01-06 14:07:26 +00:00
|
|
|
sync::{
|
|
|
|
atomic::{AtomicU32, Ordering},
|
|
|
|
Arc,
|
|
|
|
},
|
2024-04-08 01:29:52 -07:00
|
|
|
};
|
2021-10-16 15:19:25 +02:00
|
|
|
|
2025-01-06 14:07:26 +00:00
|
|
|
use conduwuit::{debug, info, warn, Err, Result};
|
|
|
|
use rocksdb::{AsColumnFamilyRef, BoundColumnFamily, DBCommon, DBWithThreadMode, MultiThreaded};
|
2024-04-06 08:48:41 -07:00
|
|
|
|
2025-01-06 14:07:26 +00:00
|
|
|
use crate::{pool::Pool, result, Context};
|
2024-03-04 20:42:09 -05:00
|
|
|
|
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,
|
2025-01-06 14:07:26 +00:00
|
|
|
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 {
|
2024-06-30 23:06:01 +00:00
|
|
|
pub(crate) fn cf(&self, name: &str) -> Arc<BoundColumnFamily<'_>> {
|
2024-05-28 06:59:50 +00:00
|
|
|
self.db
|
|
|
|
.cf_handle(name)
|
2025-01-06 14:07:26 +00:00
|
|
|
.expect("column must be described prior to database open")
|
2021-10-16 15:19:25 +02:00
|
|
|
}
|
2024-03-05 19:48:54 -05:00
|
|
|
|
2024-07-03 20:06:43 +00:00
|
|
|
#[inline]
|
2025-01-06 14:07:26 +00:00
|
|
|
pub(crate) fn cork(&self) { self.corks.fetch_add(1, Ordering::Relaxed); }
|
2024-03-19 09:56:36 -07:00
|
|
|
|
2025-01-02 05:30:51 +00:00
|
|
|
#[inline]
|
2025-01-06 14:07:26 +00:00
|
|
|
pub(crate) fn uncork(&self) { self.corks.fetch_sub(1, Ordering::Relaxed); }
|
2024-03-19 09:56:36 -07:00
|
|
|
|
2025-01-02 05:30:51 +00:00
|
|
|
#[inline]
|
2025-01-06 14:07:26 +00:00
|
|
|
pub fn corked(&self) -> bool { self.corks.load(Ordering::Relaxed) > 0 }
|
2024-04-08 01:29:52 -07:00
|
|
|
|
2025-01-06 14:07:26 +00:00
|
|
|
#[tracing::instrument(skip(self))]
|
|
|
|
pub fn sync(&self) -> Result { result(DBCommon::flush_wal(&self.db, true)) }
|
2024-04-08 01:29:52 -07:00
|
|
|
|
2025-01-06 14:07:26 +00:00
|
|
|
#[tracing::instrument(skip(self), level = "debug")]
|
|
|
|
pub fn flush(&self) -> Result { result(DBCommon::flush_wal(&self.db, false)) }
|
2024-03-05 19:48:54 -05:00
|
|
|
|
2024-07-07 20:58:26 +00:00
|
|
|
#[tracing::instrument(skip(self), level = "debug")]
|
2025-01-06 14:07:26 +00:00
|
|
|
pub fn sort(&self) -> Result {
|
2024-05-28 06:59:50 +00:00
|
|
|
let flushoptions = rocksdb::FlushOptions::default();
|
|
|
|
result(DBCommon::flush_opt(&self.db, &flushoptions))
|
2024-03-06 18:02:19 -05:00
|
|
|
}
|
|
|
|
|
2024-08-02 01:40:41 +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.
|
2024-12-15 00:05:47 -05:00
|
|
|
pub(crate) fn property_integer(
|
|
|
|
&self,
|
|
|
|
cf: &impl AsColumnFamilyRef,
|
|
|
|
name: &CStr,
|
|
|
|
) -> Result<u64> {
|
2024-08-02 01:40:41 +00:00
|
|
|
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
|
|
|
|
|
|
|
#[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 {
|
2024-07-03 20:06:43 +00:00
|
|
|
#[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
|
|
|
|
2024-07-28 06:17:43 +00:00
|
|
|
info!(
|
|
|
|
sequence = %self.db.latest_sequence_number(),
|
|
|
|
"Closing database..."
|
|
|
|
);
|
2024-05-09 15:59:08 -07:00
|
|
|
}
|
|
|
|
}
|