move db files command w/ filter args; misc related cleanup
Signed-off-by: Jason Volk <jason@zemos.net>
This commit is contained in:
parent
3c8376d897
commit
31c2968bb2
6 changed files with 75 additions and 55 deletions
|
@ -7,7 +7,10 @@ use std::{
|
||||||
|
|
||||||
use conduwuit::{
|
use conduwuit::{
|
||||||
debug_error, err, info, trace, utils,
|
debug_error, err, info, trace, utils,
|
||||||
utils::{stream::ReadyExt, string::EMPTY},
|
utils::{
|
||||||
|
stream::{IterStream, ReadyExt},
|
||||||
|
string::EMPTY,
|
||||||
|
},
|
||||||
warn, Error, PduEvent, PduId, RawPduId, Result,
|
warn, Error, PduEvent, PduId, RawPduId, Result,
|
||||||
};
|
};
|
||||||
use futures::{FutureExt, StreamExt, TryStreamExt};
|
use futures::{FutureExt, StreamExt, TryStreamExt};
|
||||||
|
@ -640,6 +643,7 @@ pub(super) async fn force_set_room_state_from_server(
|
||||||
room_id: room_id.clone().into(),
|
room_id: room_id.clone().into(),
|
||||||
event_id: first_pdu.event_id.clone(),
|
event_id: first_pdu.event_id.clone(),
|
||||||
})
|
})
|
||||||
|
.boxed()
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
for pdu in remote_state_response.pdus.clone() {
|
for pdu in remote_state_response.pdus.clone() {
|
||||||
|
@ -648,6 +652,7 @@ pub(super) async fn force_set_room_state_from_server(
|
||||||
.rooms
|
.rooms
|
||||||
.event_handler
|
.event_handler
|
||||||
.parse_incoming_pdu(&pdu)
|
.parse_incoming_pdu(&pdu)
|
||||||
|
.boxed()
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
| Ok(t) => t,
|
| Ok(t) => t,
|
||||||
|
@ -711,6 +716,7 @@ pub(super) async fn force_set_room_state_from_server(
|
||||||
.rooms
|
.rooms
|
||||||
.event_handler
|
.event_handler
|
||||||
.resolve_state(&room_id, &room_version, state)
|
.resolve_state(&room_id, &room_version, state)
|
||||||
|
.boxed()
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
info!("Forcing new room state");
|
info!("Forcing new room state");
|
||||||
|
@ -946,21 +952,57 @@ pub(super) async fn database_stats(
|
||||||
property: Option<String>,
|
property: Option<String>,
|
||||||
map: Option<String>,
|
map: Option<String>,
|
||||||
) -> Result<RoomMessageEventContent> {
|
) -> Result<RoomMessageEventContent> {
|
||||||
let property = property.unwrap_or_else(|| "rocksdb.stats".to_owned());
|
|
||||||
let map_name = map.as_ref().map_or(EMPTY, String::as_str);
|
let map_name = map.as_ref().map_or(EMPTY, String::as_str);
|
||||||
|
let property = property.unwrap_or_else(|| "rocksdb.stats".to_owned());
|
||||||
|
self.services
|
||||||
|
.db
|
||||||
|
.iter()
|
||||||
|
.filter(|(&name, _)| map_name.is_empty() || map_name == name)
|
||||||
|
.try_stream()
|
||||||
|
.try_for_each(|(&name, map)| {
|
||||||
|
let res = map.property(&property).expect("invalid property");
|
||||||
|
writeln!(self, "##### {name}:\n```\n{}\n```", res.trim())
|
||||||
|
})
|
||||||
|
.await?;
|
||||||
|
|
||||||
let mut out = String::new();
|
Ok(RoomMessageEventContent::notice_plain(""))
|
||||||
for (&name, map) in self.services.db.iter() {
|
|
||||||
if !map_name.is_empty() && map_name != name {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let res = map.property(&property)?;
|
#[admin_command]
|
||||||
let res = res.trim();
|
pub(super) async fn database_files(
|
||||||
writeln!(out, "##### {name}:\n```\n{res}\n```")?;
|
&self,
|
||||||
}
|
map: Option<String>,
|
||||||
|
level: Option<i32>,
|
||||||
|
) -> Result<RoomMessageEventContent> {
|
||||||
|
let mut files: Vec<_> = self.services.db.db.file_list().collect::<Result<_>>()?;
|
||||||
|
|
||||||
Ok(RoomMessageEventContent::notice_markdown(out))
|
files.sort_by_key(|f| f.name.clone());
|
||||||
|
|
||||||
|
writeln!(self, "| lev | sst | keys | dels | size | column |").await?;
|
||||||
|
writeln!(self, "| ---: | :--- | ---: | ---: | ---: | :--- |").await?;
|
||||||
|
files
|
||||||
|
.into_iter()
|
||||||
|
.filter(|file| {
|
||||||
|
map.as_deref()
|
||||||
|
.is_none_or(|map| map == file.column_family_name)
|
||||||
|
})
|
||||||
|
.filter(|file| level.as_ref().is_none_or(|&level| level == file.level))
|
||||||
|
.try_stream()
|
||||||
|
.try_for_each(|file| {
|
||||||
|
writeln!(
|
||||||
|
self,
|
||||||
|
"| {} | {:<13} | {:7}+ | {:4}- | {:9} | {} |",
|
||||||
|
file.level,
|
||||||
|
file.name,
|
||||||
|
file.num_entries,
|
||||||
|
file.num_deletions,
|
||||||
|
file.size,
|
||||||
|
file.column_family_name,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(RoomMessageEventContent::notice_plain(""))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[admin_command]
|
#[admin_command]
|
||||||
|
|
|
@ -226,6 +226,14 @@ pub(super) enum DebugCommand {
|
||||||
/// - Trim memory usage
|
/// - Trim memory usage
|
||||||
TrimMemory,
|
TrimMemory,
|
||||||
|
|
||||||
|
/// - List database files
|
||||||
|
DatabaseFiles {
|
||||||
|
map: Option<String>,
|
||||||
|
|
||||||
|
#[arg(long)]
|
||||||
|
level: Option<i32>,
|
||||||
|
},
|
||||||
|
|
||||||
/// - Developer test stubs
|
/// - Developer test stubs
|
||||||
#[command(subcommand)]
|
#[command(subcommand)]
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
|
|
|
@ -92,7 +92,7 @@ pub(super) async fn clear_caches(&self) -> Result<RoomMessageEventContent> {
|
||||||
|
|
||||||
#[admin_command]
|
#[admin_command]
|
||||||
pub(super) async fn list_backups(&self) -> Result<RoomMessageEventContent> {
|
pub(super) async fn list_backups(&self) -> Result<RoomMessageEventContent> {
|
||||||
let result = self.services.globals.db.backup_list()?;
|
let result = self.services.db.db.backup_list()?;
|
||||||
|
|
||||||
if result.is_empty() {
|
if result.is_empty() {
|
||||||
Ok(RoomMessageEventContent::text_plain("No backups found."))
|
Ok(RoomMessageEventContent::text_plain("No backups found."))
|
||||||
|
@ -103,31 +103,24 @@ pub(super) async fn list_backups(&self) -> Result<RoomMessageEventContent> {
|
||||||
|
|
||||||
#[admin_command]
|
#[admin_command]
|
||||||
pub(super) async fn backup_database(&self) -> Result<RoomMessageEventContent> {
|
pub(super) async fn backup_database(&self) -> Result<RoomMessageEventContent> {
|
||||||
let globals = Arc::clone(&self.services.globals);
|
let db = Arc::clone(&self.services.db);
|
||||||
let mut result = self
|
let mut result = self
|
||||||
.services
|
.services
|
||||||
.server
|
.server
|
||||||
.runtime()
|
.runtime()
|
||||||
.spawn_blocking(move || match globals.db.backup() {
|
.spawn_blocking(move || match db.db.backup() {
|
||||||
| Ok(()) => String::new(),
|
| Ok(()) => String::new(),
|
||||||
| Err(e) => e.to_string(),
|
| Err(e) => e.to_string(),
|
||||||
})
|
})
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
if result.is_empty() {
|
if result.is_empty() {
|
||||||
result = self.services.globals.db.backup_list()?;
|
result = self.services.db.db.backup_list()?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(RoomMessageEventContent::notice_markdown(result))
|
Ok(RoomMessageEventContent::notice_markdown(result))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[admin_command]
|
|
||||||
pub(super) async fn list_database_files(&self) -> Result<RoomMessageEventContent> {
|
|
||||||
let result = self.services.globals.db.file_list()?;
|
|
||||||
|
|
||||||
Ok(RoomMessageEventContent::notice_markdown(result))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[admin_command]
|
#[admin_command]
|
||||||
pub(super) async fn admin_notice(&self, message: Vec<String>) -> Result<RoomMessageEventContent> {
|
pub(super) async fn admin_notice(&self, message: Vec<String>) -> Result<RoomMessageEventContent> {
|
||||||
let message = message.join(" ");
|
let message = message.join(" ");
|
||||||
|
|
|
@ -46,9 +46,6 @@ pub(super) enum ServerCommand {
|
||||||
/// - List database backups
|
/// - List database backups
|
||||||
ListBackups,
|
ListBackups,
|
||||||
|
|
||||||
/// - List database files
|
|
||||||
ListDatabaseFiles,
|
|
||||||
|
|
||||||
/// - Send a message to the admin room.
|
/// - Send a message to the admin room.
|
||||||
AdminNotice {
|
AdminNotice {
|
||||||
message: Vec<String>,
|
message: Vec<String>,
|
||||||
|
|
|
@ -1,32 +1,15 @@
|
||||||
use std::fmt::Write;
|
|
||||||
|
|
||||||
use conduwuit::{implement, Result};
|
use conduwuit::{implement, Result};
|
||||||
|
use rocksdb::LiveFile as SstFile;
|
||||||
|
|
||||||
use super::Engine;
|
use super::Engine;
|
||||||
|
use crate::util::map_err;
|
||||||
|
|
||||||
#[implement(Engine)]
|
#[implement(Engine)]
|
||||||
pub fn file_list(&self) -> Result<String> {
|
pub fn file_list(&self) -> impl Iterator<Item = Result<SstFile>> + Send {
|
||||||
match self.db.live_files() {
|
self.db
|
||||||
| Err(e) => Ok(String::from(e)),
|
.live_files()
|
||||||
| Ok(mut files) => {
|
.map_err(map_err)
|
||||||
files.sort_by_key(|f| f.name.clone());
|
.into_iter()
|
||||||
let mut res = String::new();
|
.flat_map(Vec::into_iter)
|
||||||
writeln!(res, "| lev | sst | keys | dels | size | column |")?;
|
.map(Ok)
|
||||||
writeln!(res, "| ---: | :--- | ---: | ---: | ---: | :--- |")?;
|
|
||||||
for file in files {
|
|
||||||
writeln!(
|
|
||||||
res,
|
|
||||||
"| {} | {:<13} | {:7}+ | {:4}- | {:9} | {} |",
|
|
||||||
file.level,
|
|
||||||
file.name,
|
|
||||||
file.num_entries,
|
|
||||||
file.num_deletions,
|
|
||||||
file.size,
|
|
||||||
file.column_family_name,
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(res)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,7 +79,4 @@ impl Data {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn backup_list(&self) -> Result<String> { self.db.db.backup_list() }
|
pub fn backup_list(&self) -> Result<String> { self.db.db.backup_list() }
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn file_list(&self) -> Result<String> { self.db.db.file_list() }
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue