mirror of
https://github.com/girlbossceo/conduwuit.git
synced 2024-11-29 00:36:19 +00:00
use rocksdb caches for a few of the lru_caches
Signed-off-by: Jason Volk <jason@zemos.net>
This commit is contained in:
parent
fc44ba6ab3
commit
345be5ba5e
|
@ -148,31 +148,19 @@ impl service::globals::Data for KeyValueDatabase {
|
||||||
fn cork_and_sync(&self) -> Result<Cork> { Ok(Cork::new(&self.db, true, true)) }
|
fn cork_and_sync(&self) -> Result<Cork> { Ok(Cork::new(&self.db, true, true)) }
|
||||||
|
|
||||||
fn memory_usage(&self) -> String {
|
fn memory_usage(&self) -> String {
|
||||||
let pdu_cache = self.pdu_cache.lock().unwrap().len();
|
|
||||||
let shorteventid_cache = self.shorteventid_cache.lock().unwrap().len();
|
|
||||||
let auth_chain_cache = self.auth_chain_cache.lock().unwrap().len();
|
let auth_chain_cache = self.auth_chain_cache.lock().unwrap().len();
|
||||||
let eventidshort_cache = self.eventidshort_cache.lock().unwrap().len();
|
|
||||||
let statekeyshort_cache = self.statekeyshort_cache.lock().unwrap().len();
|
|
||||||
let our_real_users_cache = self.our_real_users_cache.read().unwrap().len();
|
let our_real_users_cache = self.our_real_users_cache.read().unwrap().len();
|
||||||
let appservice_in_room_cache = self.appservice_in_room_cache.read().unwrap().len();
|
let appservice_in_room_cache = self.appservice_in_room_cache.read().unwrap().len();
|
||||||
let lasttimelinecount_cache = self.lasttimelinecount_cache.lock().unwrap().len();
|
let lasttimelinecount_cache = self.lasttimelinecount_cache.lock().unwrap().len();
|
||||||
|
|
||||||
let max_pdu_cache = self.pdu_cache.lock().unwrap().capacity();
|
|
||||||
let max_shorteventid_cache = self.shorteventid_cache.lock().unwrap().capacity();
|
|
||||||
let max_auth_chain_cache = self.auth_chain_cache.lock().unwrap().capacity();
|
let max_auth_chain_cache = self.auth_chain_cache.lock().unwrap().capacity();
|
||||||
let max_eventidshort_cache = self.eventidshort_cache.lock().unwrap().capacity();
|
|
||||||
let max_statekeyshort_cache = self.statekeyshort_cache.lock().unwrap().capacity();
|
|
||||||
let max_our_real_users_cache = self.our_real_users_cache.read().unwrap().capacity();
|
let max_our_real_users_cache = self.our_real_users_cache.read().unwrap().capacity();
|
||||||
let max_appservice_in_room_cache = self.appservice_in_room_cache.read().unwrap().capacity();
|
let max_appservice_in_room_cache = self.appservice_in_room_cache.read().unwrap().capacity();
|
||||||
let max_lasttimelinecount_cache = self.lasttimelinecount_cache.lock().unwrap().capacity();
|
let max_lasttimelinecount_cache = self.lasttimelinecount_cache.lock().unwrap().capacity();
|
||||||
|
|
||||||
let mut response = format!(
|
let mut response = format!(
|
||||||
"\
|
"\
|
||||||
pdu_cache: {pdu_cache} / {max_pdu_cache}
|
|
||||||
shorteventid_cache: {shorteventid_cache} / {max_shorteventid_cache}
|
|
||||||
auth_chain_cache: {auth_chain_cache} / {max_auth_chain_cache}
|
auth_chain_cache: {auth_chain_cache} / {max_auth_chain_cache}
|
||||||
eventidshort_cache: {eventidshort_cache} / {max_eventidshort_cache}
|
|
||||||
statekeyshort_cache: {statekeyshort_cache} / {max_statekeyshort_cache}
|
|
||||||
our_real_users_cache: {our_real_users_cache} / {max_our_real_users_cache}
|
our_real_users_cache: {our_real_users_cache} / {max_our_real_users_cache}
|
||||||
appservice_in_room_cache: {appservice_in_room_cache} / {max_appservice_in_room_cache}
|
appservice_in_room_cache: {appservice_in_room_cache} / {max_appservice_in_room_cache}
|
||||||
lasttimelinecount_cache: {lasttimelinecount_cache} / {max_lasttimelinecount_cache}\n\n"
|
lasttimelinecount_cache: {lasttimelinecount_cache} / {max_lasttimelinecount_cache}\n\n"
|
||||||
|
@ -185,35 +173,19 @@ lasttimelinecount_cache: {lasttimelinecount_cache} / {max_lasttimelinecount_cach
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clear_caches(&self, amount: u32) {
|
fn clear_caches(&self, amount: u32) {
|
||||||
if amount > 0 {
|
|
||||||
let c = &mut *self.pdu_cache.lock().unwrap();
|
|
||||||
*c = LruCache::new(c.capacity());
|
|
||||||
}
|
|
||||||
if amount > 1 {
|
if amount > 1 {
|
||||||
let c = &mut *self.shorteventid_cache.lock().unwrap();
|
|
||||||
*c = LruCache::new(c.capacity());
|
|
||||||
}
|
|
||||||
if amount > 2 {
|
|
||||||
let c = &mut *self.auth_chain_cache.lock().unwrap();
|
let c = &mut *self.auth_chain_cache.lock().unwrap();
|
||||||
*c = LruCache::new(c.capacity());
|
*c = LruCache::new(c.capacity());
|
||||||
}
|
}
|
||||||
if amount > 3 {
|
if amount > 2 {
|
||||||
let c = &mut *self.eventidshort_cache.lock().unwrap();
|
|
||||||
*c = LruCache::new(c.capacity());
|
|
||||||
}
|
|
||||||
if amount > 4 {
|
|
||||||
let c = &mut *self.statekeyshort_cache.lock().unwrap();
|
|
||||||
*c = LruCache::new(c.capacity());
|
|
||||||
}
|
|
||||||
if amount > 5 {
|
|
||||||
let c = &mut *self.our_real_users_cache.write().unwrap();
|
let c = &mut *self.our_real_users_cache.write().unwrap();
|
||||||
*c = HashMap::new();
|
*c = HashMap::new();
|
||||||
}
|
}
|
||||||
if amount > 6 {
|
if amount > 3 {
|
||||||
let c = &mut *self.appservice_in_room_cache.write().unwrap();
|
let c = &mut *self.appservice_in_room_cache.write().unwrap();
|
||||||
*c = HashMap::new();
|
*c = HashMap::new();
|
||||||
}
|
}
|
||||||
if amount > 7 {
|
if amount > 4 {
|
||||||
let c = &mut *self.lasttimelinecount_cache.lock().unwrap();
|
let c = &mut *self.lasttimelinecount_cache.lock().unwrap();
|
||||||
*c = HashMap::new();
|
*c = HashMap::new();
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,10 +7,6 @@ use crate::{database::KeyValueDatabase, service, services, utils, Error, Result}
|
||||||
|
|
||||||
impl service::rooms::short::Data for KeyValueDatabase {
|
impl service::rooms::short::Data for KeyValueDatabase {
|
||||||
fn get_or_create_shorteventid(&self, event_id: &EventId) -> Result<u64> {
|
fn get_or_create_shorteventid(&self, event_id: &EventId) -> Result<u64> {
|
||||||
if let Some(short) = self.eventidshort_cache.lock().unwrap().get_mut(event_id) {
|
|
||||||
return Ok(*short);
|
|
||||||
}
|
|
||||||
|
|
||||||
let short = if let Some(shorteventid) = self.eventid_shorteventid.get(event_id.as_bytes())? {
|
let short = if let Some(shorteventid) = self.eventid_shorteventid.get(event_id.as_bytes())? {
|
||||||
utils::u64_from_bytes(&shorteventid).map_err(|_| Error::bad_database("Invalid shorteventid in db."))?
|
utils::u64_from_bytes(&shorteventid).map_err(|_| Error::bad_database("Invalid shorteventid in db."))?
|
||||||
} else {
|
} else {
|
||||||
|
@ -22,24 +18,10 @@ impl service::rooms::short::Data for KeyValueDatabase {
|
||||||
shorteventid
|
shorteventid
|
||||||
};
|
};
|
||||||
|
|
||||||
self.eventidshort_cache
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.insert(event_id.to_owned(), short);
|
|
||||||
|
|
||||||
Ok(short)
|
Ok(short)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_shortstatekey(&self, event_type: &StateEventType, state_key: &str) -> Result<Option<u64>> {
|
fn get_shortstatekey(&self, event_type: &StateEventType, state_key: &str) -> Result<Option<u64>> {
|
||||||
if let Some(short) = self
|
|
||||||
.statekeyshort_cache
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.get_mut(&(event_type.clone(), state_key.to_owned()))
|
|
||||||
{
|
|
||||||
return Ok(Some(*short));
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut statekey_vec = event_type.to_string().as_bytes().to_vec();
|
let mut statekey_vec = event_type.to_string().as_bytes().to_vec();
|
||||||
statekey_vec.push(0xFF);
|
statekey_vec.push(0xFF);
|
||||||
statekey_vec.extend_from_slice(state_key.as_bytes());
|
statekey_vec.extend_from_slice(state_key.as_bytes());
|
||||||
|
@ -52,26 +34,10 @@ impl service::rooms::short::Data for KeyValueDatabase {
|
||||||
})
|
})
|
||||||
.transpose()?;
|
.transpose()?;
|
||||||
|
|
||||||
if let Some(s) = short {
|
|
||||||
self.statekeyshort_cache
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.insert((event_type.clone(), state_key.to_owned()), s);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(short)
|
Ok(short)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_or_create_shortstatekey(&self, event_type: &StateEventType, state_key: &str) -> Result<u64> {
|
fn get_or_create_shortstatekey(&self, event_type: &StateEventType, state_key: &str) -> Result<u64> {
|
||||||
if let Some(short) = self
|
|
||||||
.statekeyshort_cache
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.get_mut(&(event_type.clone(), state_key.to_owned()))
|
|
||||||
{
|
|
||||||
return Ok(*short);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut statekey_vec = event_type.to_string().as_bytes().to_vec();
|
let mut statekey_vec = event_type.to_string().as_bytes().to_vec();
|
||||||
statekey_vec.push(0xFF);
|
statekey_vec.push(0xFF);
|
||||||
statekey_vec.extend_from_slice(state_key.as_bytes());
|
statekey_vec.extend_from_slice(state_key.as_bytes());
|
||||||
|
@ -87,24 +53,10 @@ impl service::rooms::short::Data for KeyValueDatabase {
|
||||||
shortstatekey
|
shortstatekey
|
||||||
};
|
};
|
||||||
|
|
||||||
self.statekeyshort_cache
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.insert((event_type.clone(), state_key.to_owned()), short);
|
|
||||||
|
|
||||||
Ok(short)
|
Ok(short)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_eventid_from_short(&self, shorteventid: u64) -> Result<Arc<EventId>> {
|
fn get_eventid_from_short(&self, shorteventid: u64) -> Result<Arc<EventId>> {
|
||||||
if let Some(id) = self
|
|
||||||
.shorteventid_cache
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.get_mut(&shorteventid)
|
|
||||||
{
|
|
||||||
return Ok(Arc::clone(id));
|
|
||||||
}
|
|
||||||
|
|
||||||
let bytes = self
|
let bytes = self
|
||||||
.shorteventid_eventid
|
.shorteventid_eventid
|
||||||
.get(&shorteventid.to_be_bytes())?
|
.get(&shorteventid.to_be_bytes())?
|
||||||
|
@ -116,24 +68,10 @@ impl service::rooms::short::Data for KeyValueDatabase {
|
||||||
)
|
)
|
||||||
.map_err(|_| Error::bad_database("EventId in shorteventid_eventid is invalid."))?;
|
.map_err(|_| Error::bad_database("EventId in shorteventid_eventid is invalid."))?;
|
||||||
|
|
||||||
self.shorteventid_cache
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.insert(shorteventid, Arc::clone(&event_id));
|
|
||||||
|
|
||||||
Ok(event_id)
|
Ok(event_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_statekey_from_short(&self, shortstatekey: u64) -> Result<(StateEventType, String)> {
|
fn get_statekey_from_short(&self, shortstatekey: u64) -> Result<(StateEventType, String)> {
|
||||||
if let Some(id) = self
|
|
||||||
.shortstatekey_cache
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.get_mut(&shortstatekey)
|
|
||||||
{
|
|
||||||
return Ok(id.clone());
|
|
||||||
}
|
|
||||||
|
|
||||||
let bytes = self
|
let bytes = self
|
||||||
.shortstatekey_statekey
|
.shortstatekey_statekey
|
||||||
.get(&shortstatekey.to_be_bytes())?
|
.get(&shortstatekey.to_be_bytes())?
|
||||||
|
@ -155,11 +93,6 @@ impl service::rooms::short::Data for KeyValueDatabase {
|
||||||
|
|
||||||
let result = (event_type, state_key);
|
let result = (event_type, state_key);
|
||||||
|
|
||||||
self.shortstatekey_cache
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.insert(shortstatekey, result.clone());
|
|
||||||
|
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -89,10 +89,6 @@ impl service::rooms::timeline::Data for KeyValueDatabase {
|
||||||
///
|
///
|
||||||
/// Checks the `eventid_outlierpdu` Tree if not found in the timeline.
|
/// Checks the `eventid_outlierpdu` Tree if not found in the timeline.
|
||||||
fn get_pdu(&self, event_id: &EventId) -> Result<Option<Arc<PduEvent>>> {
|
fn get_pdu(&self, event_id: &EventId) -> Result<Option<Arc<PduEvent>>> {
|
||||||
if let Some(p) = self.pdu_cache.lock().unwrap().get_mut(event_id) {
|
|
||||||
return Ok(Some(Arc::clone(p)));
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(pdu) = self
|
if let Some(pdu) = self
|
||||||
.get_non_outlier_pdu(event_id)?
|
.get_non_outlier_pdu(event_id)?
|
||||||
.map_or_else(
|
.map_or_else(
|
||||||
|
@ -106,10 +102,6 @@ impl service::rooms::timeline::Data for KeyValueDatabase {
|
||||||
)?
|
)?
|
||||||
.map(Arc::new)
|
.map(Arc::new)
|
||||||
{
|
{
|
||||||
self.pdu_cache
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.insert(event_id.to_owned(), Arc::clone(&pdu));
|
|
||||||
Ok(Some(pdu))
|
Ok(Some(pdu))
|
||||||
} else {
|
} else {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
|
@ -166,7 +158,7 @@ impl service::rooms::timeline::Data for KeyValueDatabase {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Removes a pdu and creates a new one with the same id.
|
/// Removes a pdu and creates a new one with the same id.
|
||||||
fn replace_pdu(&self, pdu_id: &[u8], pdu_json: &CanonicalJsonObject, pdu: &PduEvent) -> Result<()> {
|
fn replace_pdu(&self, pdu_id: &[u8], pdu_json: &CanonicalJsonObject, _pdu: &PduEvent) -> Result<()> {
|
||||||
if self.pduid_pdu.get(pdu_id)?.is_some() {
|
if self.pduid_pdu.get(pdu_id)?.is_some() {
|
||||||
self.pduid_pdu.insert(
|
self.pduid_pdu.insert(
|
||||||
pdu_id,
|
pdu_id,
|
||||||
|
@ -176,11 +168,6 @@ impl service::rooms::timeline::Data for KeyValueDatabase {
|
||||||
return Err(Error::BadRequest(ErrorKind::NotFound, "PDU does not exist."));
|
return Err(Error::BadRequest(ErrorKind::NotFound, "PDU does not exist."));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.pdu_cache
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.remove(&(*pdu.event_id).to_owned());
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -619,7 +619,7 @@ pub(crate) async fn migrations(db: &KeyValueDatabase, config: &Config) -> Result
|
||||||
}
|
}
|
||||||
|
|
||||||
info!(
|
info!(
|
||||||
"Loaded {} database with version {}",
|
"Loaded {} database with schema version {}",
|
||||||
config.database_backend, latest_database_version
|
config.database_backend, latest_database_version
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -28,10 +28,10 @@ use lru_cache::LruCache;
|
||||||
use ruma::{
|
use ruma::{
|
||||||
events::{
|
events::{
|
||||||
push_rules::PushRulesEventContent, room::message::RoomMessageEventContent, GlobalAccountDataEvent,
|
push_rules::PushRulesEventContent, room::message::RoomMessageEventContent, GlobalAccountDataEvent,
|
||||||
GlobalAccountDataEventType, StateEventType,
|
GlobalAccountDataEventType,
|
||||||
},
|
},
|
||||||
push::Ruleset,
|
push::Ruleset,
|
||||||
CanonicalJsonValue, EventId, OwnedDeviceId, OwnedEventId, OwnedRoomId, OwnedUserId, UserId,
|
CanonicalJsonValue, OwnedDeviceId, OwnedRoomId, OwnedUserId, UserId,
|
||||||
};
|
};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
|
@ -40,8 +40,8 @@ use tokio::time::{interval, Instant};
|
||||||
use tracing::{debug, error, warn};
|
use tracing::{debug, error, warn};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
database::migrations::migrations, service::rooms::timeline::PduCount, services, Config, Error, PduEvent, Result,
|
database::migrations::migrations, service::rooms::timeline::PduCount, services, Config, Error, Result, Services,
|
||||||
Services, SERVICES,
|
SERVICES,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct KeyValueDatabase {
|
pub struct KeyValueDatabase {
|
||||||
|
@ -181,12 +181,7 @@ pub struct KeyValueDatabase {
|
||||||
//pub pusher: pusher::PushData,
|
//pub pusher: pusher::PushData,
|
||||||
pub(super) senderkey_pusher: Arc<dyn KvTree>,
|
pub(super) senderkey_pusher: Arc<dyn KvTree>,
|
||||||
|
|
||||||
pub(super) pdu_cache: Mutex<LruCache<OwnedEventId, Arc<PduEvent>>>,
|
|
||||||
pub(super) shorteventid_cache: Mutex<LruCache<u64, Arc<EventId>>>,
|
|
||||||
pub(super) auth_chain_cache: Mutex<LruCache<Vec<u64>, Arc<HashSet<u64>>>>,
|
pub(super) auth_chain_cache: Mutex<LruCache<Vec<u64>, Arc<HashSet<u64>>>>,
|
||||||
pub(super) eventidshort_cache: Mutex<LruCache<OwnedEventId, u64>>,
|
|
||||||
pub(super) statekeyshort_cache: Mutex<LruCache<(StateEventType, String), u64>>,
|
|
||||||
pub(super) shortstatekey_cache: Mutex<LruCache<u64, (StateEventType, String)>>,
|
|
||||||
pub(super) our_real_users_cache: RwLock<HashMap<OwnedRoomId, Arc<HashSet<OwnedUserId>>>>,
|
pub(super) our_real_users_cache: RwLock<HashMap<OwnedRoomId, Arc<HashSet<OwnedUserId>>>>,
|
||||||
pub(super) appservice_in_room_cache: RwLock<HashMap<OwnedRoomId, HashMap<String, bool>>>,
|
pub(super) appservice_in_room_cache: RwLock<HashMap<OwnedRoomId, HashMap<String, bool>>>,
|
||||||
pub(super) lasttimelinecount_cache: Mutex<HashMap<OwnedRoomId, PduCount>>,
|
pub(super) lasttimelinecount_cache: Mutex<HashMap<OwnedRoomId, PduCount>>,
|
||||||
|
@ -347,27 +342,9 @@ impl KeyValueDatabase {
|
||||||
global: builder.open_tree("global")?,
|
global: builder.open_tree("global")?,
|
||||||
server_signingkeys: builder.open_tree("server_signingkeys")?,
|
server_signingkeys: builder.open_tree("server_signingkeys")?,
|
||||||
|
|
||||||
pdu_cache: Mutex::new(LruCache::new(
|
|
||||||
config
|
|
||||||
.pdu_cache_capacity
|
|
||||||
.try_into()
|
|
||||||
.expect("pdu cache capacity fits into usize"),
|
|
||||||
)),
|
|
||||||
auth_chain_cache: Mutex::new(LruCache::new(
|
auth_chain_cache: Mutex::new(LruCache::new(
|
||||||
(f64::from(config.auth_chain_cache_capacity) * config.conduit_cache_capacity_modifier) as usize,
|
(f64::from(config.auth_chain_cache_capacity) * config.conduit_cache_capacity_modifier) as usize,
|
||||||
)),
|
)),
|
||||||
shorteventid_cache: Mutex::new(LruCache::new(
|
|
||||||
(f64::from(config.shorteventid_cache_capacity) * config.conduit_cache_capacity_modifier) as usize,
|
|
||||||
)),
|
|
||||||
eventidshort_cache: Mutex::new(LruCache::new(
|
|
||||||
(f64::from(config.eventidshort_cache_capacity) * config.conduit_cache_capacity_modifier) as usize,
|
|
||||||
)),
|
|
||||||
shortstatekey_cache: Mutex::new(LruCache::new(
|
|
||||||
(f64::from(config.shortstatekey_cache_capacity) * config.conduit_cache_capacity_modifier) as usize,
|
|
||||||
)),
|
|
||||||
statekeyshort_cache: Mutex::new(LruCache::new(
|
|
||||||
(f64::from(config.statekeyshort_cache_capacity) * config.conduit_cache_capacity_modifier) as usize,
|
|
||||||
)),
|
|
||||||
our_real_users_cache: RwLock::new(HashMap::new()),
|
our_real_users_cache: RwLock::new(HashMap::new()),
|
||||||
appservice_in_room_cache: RwLock::new(HashMap::new()),
|
appservice_in_room_cache: RwLock::new(HashMap::new()),
|
||||||
lasttimelinecount_cache: Mutex::new(HashMap::new()),
|
lasttimelinecount_cache: Mutex::new(HashMap::new()),
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
use std::sync::{atomic::AtomicU32, Arc};
|
use std::{
|
||||||
|
collections::HashMap,
|
||||||
|
sync::{atomic::AtomicU32, Arc},
|
||||||
|
};
|
||||||
|
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use rust_rocksdb::{
|
use rust_rocksdb::{
|
||||||
backup::{BackupEngine, BackupEngineOptions},
|
backup::{BackupEngine, BackupEngineOptions},
|
||||||
DBWithThreadMode as Db, MultiThreaded,
|
Cache, ColumnFamilyDescriptor, DBCommon, DBWithThreadMode as Db, Env, MultiThreaded, Options,
|
||||||
};
|
};
|
||||||
use tracing::{debug, error, info, warn};
|
use tracing::{debug, error, info, warn};
|
||||||
|
|
||||||
|
@ -20,11 +23,11 @@ use super::watchers;
|
||||||
|
|
||||||
pub(crate) struct Engine {
|
pub(crate) struct Engine {
|
||||||
rocks: Db<MultiThreaded>,
|
rocks: Db<MultiThreaded>,
|
||||||
row_cache: rust_rocksdb::Cache,
|
row_cache: Cache,
|
||||||
col_cache: rust_rocksdb::Cache,
|
col_cache: HashMap<String, Cache>,
|
||||||
old_cfs: Vec<String>,
|
old_cfs: Vec<String>,
|
||||||
opts: rust_rocksdb::Options,
|
opts: Options,
|
||||||
env: rust_rocksdb::Env,
|
env: Env,
|
||||||
config: Config,
|
config: Config,
|
||||||
corks: AtomicU32,
|
corks: AtomicU32,
|
||||||
}
|
}
|
||||||
|
@ -32,14 +35,17 @@ pub(crate) struct Engine {
|
||||||
impl KeyValueDatabaseEngine for Arc<Engine> {
|
impl KeyValueDatabaseEngine for Arc<Engine> {
|
||||||
fn open(config: &Config) -> Result<Self> {
|
fn open(config: &Config) -> Result<Self> {
|
||||||
let cache_capacity_bytes = config.db_cache_capacity_mb * 1024.0 * 1024.0;
|
let cache_capacity_bytes = config.db_cache_capacity_mb * 1024.0 * 1024.0;
|
||||||
let row_cache_capacity_bytes = (cache_capacity_bytes * 0.25) as usize;
|
let row_cache_capacity_bytes = (cache_capacity_bytes * 0.50) as usize;
|
||||||
let col_cache_capacity_bytes = (cache_capacity_bytes * 0.75) as usize;
|
let col_cache_capacity_bytes = (cache_capacity_bytes * 0.50) as usize;
|
||||||
|
|
||||||
let db_env = rust_rocksdb::Env::new()?;
|
let mut col_cache = HashMap::new();
|
||||||
let row_cache = rust_rocksdb::Cache::new_lru_cache(row_cache_capacity_bytes);
|
col_cache.insert("primary".to_owned(), Cache::new_lru_cache(col_cache_capacity_bytes));
|
||||||
let col_cache = rust_rocksdb::Cache::new_lru_cache(col_cache_capacity_bytes);
|
|
||||||
let db_opts = db_options(config, &db_env, &row_cache, &col_cache);
|
|
||||||
|
|
||||||
|
let db_env = Env::new()?;
|
||||||
|
let row_cache = Cache::new_lru_cache(row_cache_capacity_bytes);
|
||||||
|
let db_opts = db_options(config, &db_env, &row_cache, col_cache.get("primary").expect("cache"));
|
||||||
|
|
||||||
|
let load_time = std::time::Instant::now();
|
||||||
if config.rocksdb_repair {
|
if config.rocksdb_repair {
|
||||||
warn!("Starting database repair. This may take a long time...");
|
warn!("Starting database repair. This may take a long time...");
|
||||||
if let Err(e) = Db::<MultiThreaded>::repair(&db_opts, &config.database_path) {
|
if let Err(e) = Db::<MultiThreaded>::repair(&db_opts, &config.database_path) {
|
||||||
|
@ -53,7 +59,7 @@ impl KeyValueDatabaseEngine for Arc<Engine> {
|
||||||
debug!("Opening {} column family descriptors in database", cfs.len());
|
debug!("Opening {} column family descriptors in database", cfs.len());
|
||||||
let cfds = cfs
|
let cfds = cfs
|
||||||
.iter()
|
.iter()
|
||||||
.map(|name| rust_rocksdb::ColumnFamilyDescriptor::new(name, cf_options(name, db_opts.clone(), config)))
|
.map(|name| ColumnFamilyDescriptor::new(name, cf_options(config, name, db_opts.clone(), &mut col_cache)))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
debug!("Opening database...");
|
debug!("Opening database...");
|
||||||
|
@ -63,7 +69,11 @@ impl KeyValueDatabaseEngine for Arc<Engine> {
|
||||||
Db::<MultiThreaded>::open_cf_descriptors(&db_opts, &config.database_path, cfds)?
|
Db::<MultiThreaded>::open_cf_descriptors(&db_opts, &config.database_path, cfds)?
|
||||||
};
|
};
|
||||||
|
|
||||||
info!("Opened database at sequence number {}", db.latest_sequence_number());
|
info!(
|
||||||
|
"Opened database at sequence number {} in {:?}",
|
||||||
|
db.latest_sequence_number(),
|
||||||
|
load_time.elapsed()
|
||||||
|
);
|
||||||
Ok(Arc::new(Engine {
|
Ok(Arc::new(Engine {
|
||||||
rocks: db,
|
rocks: db,
|
||||||
row_cache,
|
row_cache,
|
||||||
|
@ -91,13 +101,13 @@ impl KeyValueDatabaseEngine for Arc<Engine> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn flush(&self) -> Result<()> {
|
fn flush(&self) -> Result<()> {
|
||||||
rust_rocksdb::DBCommon::flush_wal(&self.rocks, false)?;
|
DBCommon::flush_wal(&self.rocks, false)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sync(&self) -> Result<()> {
|
fn sync(&self) -> Result<()> {
|
||||||
rust_rocksdb::DBCommon::flush_wal(&self.rocks, true)?;
|
DBCommon::flush_wal(&self.rocks, true)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -119,31 +129,34 @@ impl KeyValueDatabaseEngine for Arc<Engine> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn memory_usage(&self) -> Result<String> {
|
fn memory_usage(&self) -> Result<String> {
|
||||||
let stats = rust_rocksdb::perf::get_memory_usage_stats(
|
let mut res = String::new();
|
||||||
Some(&[&self.rocks]),
|
let stats = rust_rocksdb::perf::get_memory_usage_stats(Some(&[&self.rocks]), Some(&[&self.row_cache]))?;
|
||||||
Some(&[&self.row_cache, &self.col_cache]),
|
_ = std::fmt::write(
|
||||||
)?;
|
&mut res,
|
||||||
Ok(format!(
|
format_args!(
|
||||||
"Approximate memory usage of all the mem-tables: {:.3} MB\nApproximate memory usage of un-flushed \
|
"Memory buffers: {:.2} MiB\nPending write: {:.2} MiB\nTable readers: {:.2} MiB\nRow cache: {:.2} MiB\n",
|
||||||
mem-tables: {:.3} MB\nApproximate memory usage of all the table readers: {:.3} MB\nApproximate memory \
|
stats.mem_table_total as f64 / 1024.0 / 1024.0,
|
||||||
usage by cache: {:.3} MB\nApproximate memory usage by row cache: {:.3} MB pinned: {:.3} MB\nApproximate \
|
stats.mem_table_unflushed as f64 / 1024.0 / 1024.0,
|
||||||
memory usage by column cache: {:.3} MB pinned: {:.3} MB\n",
|
stats.mem_table_readers_total as f64 / 1024.0 / 1024.0,
|
||||||
stats.mem_table_total as f64 / 1024.0 / 1024.0,
|
self.row_cache.get_usage() as f64 / 1024.0 / 1024.0,
|
||||||
stats.mem_table_unflushed as f64 / 1024.0 / 1024.0,
|
),
|
||||||
stats.mem_table_readers_total as f64 / 1024.0 / 1024.0,
|
);
|
||||||
stats.cache_total as f64 / 1024.0 / 1024.0,
|
|
||||||
self.row_cache.get_usage() as f64 / 1024.0 / 1024.0,
|
for (name, cache) in &self.col_cache {
|
||||||
self.row_cache.get_pinned_usage() as f64 / 1024.0 / 1024.0,
|
_ = std::fmt::write(
|
||||||
self.col_cache.get_usage() as f64 / 1024.0 / 1024.0,
|
&mut res,
|
||||||
self.col_cache.get_pinned_usage() as f64 / 1024.0 / 1024.0,
|
format_args!("{} cache: {:.2} MiB\n", name, cache.get_usage() as f64 / 1024.0 / 1024.0,),
|
||||||
))
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cleanup(&self) -> Result<()> {
|
fn cleanup(&self) -> Result<()> {
|
||||||
debug!("Running flush_opt");
|
debug!("Running flush_opt");
|
||||||
let flushoptions = rust_rocksdb::FlushOptions::default();
|
let flushoptions = rust_rocksdb::FlushOptions::default();
|
||||||
|
|
||||||
rust_rocksdb::DBCommon::flush_opt(&self.rocks, &flushoptions)?;
|
DBCommon::flush_opt(&self.rocks, &flushoptions)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use rust_rocksdb::{
|
use rust_rocksdb::{
|
||||||
BlockBasedOptions, Cache, DBCompactionStyle, DBCompressionType, DBRecoveryMode, Env, LogLevel, Options,
|
BlockBasedOptions, Cache, DBCompactionStyle, DBCompressionType, DBRecoveryMode, Env, LogLevel, Options,
|
||||||
UniversalCompactOptions, UniversalCompactionStopStyle,
|
UniversalCompactOptions, UniversalCompactionStopStyle,
|
||||||
|
@ -43,6 +45,7 @@ pub(crate) fn db_options(config: &Config, env: &Env, row_cache: &Cache, col_cach
|
||||||
// Blocks
|
// Blocks
|
||||||
let mut table_opts = table_options(config);
|
let mut table_opts = table_options(config);
|
||||||
table_opts.set_block_cache(col_cache);
|
table_opts.set_block_cache(col_cache);
|
||||||
|
opts.set_block_based_table_factory(&table_opts);
|
||||||
opts.set_row_cache(row_cache);
|
opts.set_row_cache(row_cache);
|
||||||
|
|
||||||
// Buffers
|
// Buffers
|
||||||
|
@ -75,7 +78,6 @@ pub(crate) fn db_options(config: &Config, env: &Env, row_cache: &Cache, col_cach
|
||||||
4_u8..=u8::MAX => unimplemented!(),
|
4_u8..=u8::MAX => unimplemented!(),
|
||||||
});
|
});
|
||||||
|
|
||||||
opts.set_block_based_table_factory(&table_opts);
|
|
||||||
opts.set_env(env);
|
opts.set_env(env);
|
||||||
opts
|
opts
|
||||||
}
|
}
|
||||||
|
@ -83,7 +85,8 @@ pub(crate) fn db_options(config: &Config, env: &Env, row_cache: &Cache, col_cach
|
||||||
/// Adjust options for the specific column by name. Provide the result of
|
/// Adjust options for the specific column by name. Provide the result of
|
||||||
/// db_options() as the argument to this function and use the return value in
|
/// db_options() as the argument to this function and use the return value in
|
||||||
/// the arguments to open the specific column.
|
/// the arguments to open the specific column.
|
||||||
pub(crate) fn cf_options(name: &str, mut opts: Options, config: &Config) -> Options {
|
pub(crate) fn cf_options(cfg: &Config, name: &str, mut opts: Options, cache: &mut HashMap<String, Cache>) -> Options {
|
||||||
|
// Columns with non-default compaction options
|
||||||
match name {
|
match name {
|
||||||
"backupid_algorithm"
|
"backupid_algorithm"
|
||||||
| "backupid_etag"
|
| "backupid_etag"
|
||||||
|
@ -94,7 +97,52 @@ pub(crate) fn cf_options(name: &str, mut opts: Options, config: &Config) -> Opti
|
||||||
| "shortstatekey_statekey"
|
| "shortstatekey_statekey"
|
||||||
| "shortstatehash_statediff"
|
| "shortstatehash_statediff"
|
||||||
| "userdevicetxnid_response"
|
| "userdevicetxnid_response"
|
||||||
| "userfilterid_filter" => set_for_sequential_small_uc(&mut opts, config),
|
| "userfilterid_filter" => set_for_sequential_small_uc(&mut opts, cfg),
|
||||||
|
&_ => {},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Columns with non-default table/cache configs
|
||||||
|
match name {
|
||||||
|
"shorteventid_eventid" => set_table_with_new_cache(
|
||||||
|
&mut opts,
|
||||||
|
cfg,
|
||||||
|
cache,
|
||||||
|
name,
|
||||||
|
cache_size(cfg, cfg.shorteventid_cache_capacity, 64),
|
||||||
|
),
|
||||||
|
|
||||||
|
"eventid_shorteventid" => set_table_with_new_cache(
|
||||||
|
&mut opts,
|
||||||
|
cfg,
|
||||||
|
cache,
|
||||||
|
name,
|
||||||
|
cache_size(cfg, cfg.eventidshort_cache_capacity, 64),
|
||||||
|
),
|
||||||
|
|
||||||
|
"shorteventid_authchain" => {
|
||||||
|
set_table_with_new_cache(&mut opts, cfg, cache, name, cache_size(cfg, cfg.auth_chain_cache_capacity, 192));
|
||||||
|
},
|
||||||
|
|
||||||
|
"shortstatekey_statekey" => set_table_with_new_cache(
|
||||||
|
&mut opts,
|
||||||
|
cfg,
|
||||||
|
cache,
|
||||||
|
name,
|
||||||
|
cache_size(cfg, cfg.shortstatekey_cache_capacity, 1024),
|
||||||
|
),
|
||||||
|
|
||||||
|
"statekey_shortstatekey" => set_table_with_new_cache(
|
||||||
|
&mut opts,
|
||||||
|
cfg,
|
||||||
|
cache,
|
||||||
|
name,
|
||||||
|
cache_size(cfg, cfg.statekeyshort_cache_capacity, 1024),
|
||||||
|
),
|
||||||
|
|
||||||
|
"pduid_pdu" => set_table_with_new_cache(&mut opts, cfg, cache, name, cfg.pdu_cache_capacity as usize * 1536),
|
||||||
|
|
||||||
|
"eventid_outlierpdu" => set_table_with_shared_cache(&mut opts, cfg, cache, name, "pduid_pdu"),
|
||||||
|
|
||||||
&_ => {},
|
&_ => {},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,6 +268,31 @@ fn uc_options(_config: &Config) -> UniversalCompactOptions {
|
||||||
opts
|
opts
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_table_with_new_cache(
|
||||||
|
opts: &mut Options, config: &Config, cache: &mut HashMap<String, Cache>, name: &str, size: usize,
|
||||||
|
) {
|
||||||
|
cache.insert(name.to_owned(), Cache::new_lru_cache(size));
|
||||||
|
set_table_with_shared_cache(opts, config, cache, name, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_table_with_shared_cache(
|
||||||
|
opts: &mut Options, config: &Config, cache: &HashMap<String, Cache>, _name: &str, cache_name: &str,
|
||||||
|
) {
|
||||||
|
let mut table = table_options(config);
|
||||||
|
table.set_block_cache(
|
||||||
|
cache
|
||||||
|
.get(cache_name)
|
||||||
|
.expect("existing cache to share with this column"),
|
||||||
|
);
|
||||||
|
opts.set_block_based_table_factory(&table);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cache_size(config: &Config, base_size: u32, entity_size: usize) -> usize {
|
||||||
|
let ents = f64::from(base_size) * config.conduit_cache_capacity_modifier;
|
||||||
|
|
||||||
|
ents as usize * entity_size
|
||||||
|
}
|
||||||
|
|
||||||
fn table_options(_config: &Config) -> BlockBasedOptions {
|
fn table_options(_config: &Config) -> BlockBasedOptions {
|
||||||
let mut opts = BlockBasedOptions::default();
|
let mut opts = BlockBasedOptions::default();
|
||||||
|
|
||||||
|
|
|
@ -268,9 +268,7 @@ async fn stop(_server: &Server) -> io::Result<()> {
|
||||||
|
|
||||||
/// Async initializations
|
/// Async initializations
|
||||||
async fn start(server: &Server) -> Result<(), Error> {
|
async fn start(server: &Server) -> Result<(), Error> {
|
||||||
let db_load_time = std::time::Instant::now();
|
|
||||||
KeyValueDatabase::load_or_create(server.config.clone(), server.tracing_reload_handle.clone()).await?;
|
KeyValueDatabase::load_or_create(server.config.clone(), server.tracing_reload_handle.clone()).await?;
|
||||||
info!("Database took {:?} to load", db_load_time.elapsed());
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,8 +72,6 @@ impl Services<'_> {
|
||||||
},
|
},
|
||||||
auth_chain: rooms::auth_chain::Service {
|
auth_chain: rooms::auth_chain::Service {
|
||||||
db,
|
db,
|
||||||
shorteventid_cache_capacity: (f64::from(config.shorteventid_cache_capacity)
|
|
||||||
* config.conduit_cache_capacity_modifier) as usize,
|
|
||||||
},
|
},
|
||||||
directory: rooms::directory::Service {
|
directory: rooms::directory::Service {
|
||||||
db,
|
db,
|
||||||
|
|
|
@ -12,7 +12,6 @@ use crate::{services, Error, Result};
|
||||||
|
|
||||||
pub struct Service {
|
pub struct Service {
|
||||||
pub db: &'static dyn Data,
|
pub db: &'static dyn Data,
|
||||||
pub(crate) shorteventid_cache_capacity: usize,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Service {
|
impl Service {
|
||||||
|
@ -117,15 +116,6 @@ impl Service {
|
||||||
"Auth chain stats",
|
"Auth chain stats",
|
||||||
);
|
);
|
||||||
|
|
||||||
if full_auth_chain.len() > self.shorteventid_cache_capacity {
|
|
||||||
warn!(
|
|
||||||
"Room {room_id} requires cache size of {} but it is set to {}. Increase 'shorteventid_cache_capacity' \
|
|
||||||
in your config file.",
|
|
||||||
full_auth_chain.len(),
|
|
||||||
self.shorteventid_cache_capacity,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(full_auth_chain
|
Ok(full_auth_chain
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(move |sid| services().rooms.short.get_eventid_from_short(sid).ok()))
|
.filter_map(move |sid| services().rooms.short.get_eventid_from_short(sid).ok()))
|
||||||
|
|
Loading…
Reference in a new issue