Housekeeping: delete the blobs backup dir (#4104)

This commit is contained in:
iequidoo
2023-03-02 15:19:48 -03:00
committed by iequidoo
parent c38ae31f31
commit 627cf20074
3 changed files with 94 additions and 61 deletions

View File

@@ -11,6 +11,7 @@
### Fixes ### Fixes
- Do not block async task executor while decrypting the messages. #4079 - Do not block async task executor while decrypting the messages. #4079
- Housekeeping: delete the blobs backup dir #4123
### API-Changes ### API-Changes
- jsonrpc: add more advanced API to send a message. #4097 - jsonrpc: add more advanced API to send a message. #4097

View File

@@ -34,7 +34,7 @@ use crate::{e2ee, tools};
// Name of the database file in the backup. // Name of the database file in the backup.
const DBFILE_BACKUP_NAME: &str = "dc_database_backup.sqlite"; const DBFILE_BACKUP_NAME: &str = "dc_database_backup.sqlite";
const BLOBS_BACKUP_NAME: &str = "blobs_backup"; pub(crate) const BLOBS_BACKUP_NAME: &str = "blobs_backup";
/// Import/export command. /// Import/export command.
#[derive(Debug, Display, Copy, Clone, PartialEq, Eq, FromPrimitive, ToPrimitive)] #[derive(Debug, Display, Copy, Clone, PartialEq, Eq, FromPrimitive, ToPrimitive)]

View File

@@ -15,6 +15,7 @@ use crate::constants::DC_CHAT_ID_TRASH;
use crate::context::Context; use crate::context::Context;
use crate::debug_logging::set_debug_logging_xdc; use crate::debug_logging::set_debug_logging_xdc;
use crate::ephemeral::start_ephemeral_timers; use crate::ephemeral::start_ephemeral_timers;
use crate::imex::BLOBS_BACKUP_NAME;
use crate::log::LogExt; use crate::log::LogExt;
use crate::message::{Message, MsgId, Viewtype}; use crate::message::{Message, MsgId, Viewtype};
use crate::param::{Param, Params}; use crate::param::{Param, Params};
@@ -792,8 +793,9 @@ pub async fn remove_unused_files(context: &Context) -> Result<()> {
.context("housekeeping: failed to SELECT value FROM config")?; .context("housekeeping: failed to SELECT value FROM config")?;
info!(context, "{} files in use.", files_in_use.len(),); info!(context, "{} files in use.", files_in_use.len(),);
/* go through directory and delete unused files */ /* go through directories and delete unused files */
let p = context.get_blobdir(); let blobdir = context.get_blobdir();
for p in [&blobdir.join(BLOBS_BACKUP_NAME), blobdir] {
match tokio::fs::read_dir(p).await { match tokio::fs::read_dir(p).await {
Ok(mut dir_handle) => { Ok(mut dir_handle) => {
/* avoid deletion of files that are just created to build a message object */ /* avoid deletion of files that are just created to build a message object */
@@ -806,17 +808,30 @@ pub async fn remove_unused_files(context: &Context) -> Result<()> {
let name_f = entry.file_name(); let name_f = entry.file_name();
let name_s = name_f.to_string_lossy(); let name_s = name_f.to_string_lossy();
if is_file_in_use(&files_in_use, None, &name_s) if p == blobdir
&& (is_file_in_use(&files_in_use, None, &name_s)
|| is_file_in_use(&files_in_use, Some(".increation"), &name_s) || is_file_in_use(&files_in_use, Some(".increation"), &name_s)
|| is_file_in_use(&files_in_use, Some(".waveform"), &name_s) || is_file_in_use(&files_in_use, Some(".waveform"), &name_s)
|| is_file_in_use(&files_in_use, Some("-preview.jpg"), &name_s) || is_file_in_use(&files_in_use, Some("-preview.jpg"), &name_s))
{ {
continue; continue;
} }
unreferenced_count += 1;
if let Ok(stats) = tokio::fs::metadata(entry.path()).await { if let Ok(stats) = tokio::fs::metadata(entry.path()).await {
if stats.is_dir() {
if let Err(e) = tokio::fs::remove_dir(entry.path()).await {
// The dir could be created not by a user, but by a desktop
// environment f.e. So, no warning.
info!(
context,
"Housekeeping: Cannot rmdir {}: {:#}",
entry.path().display(),
e
);
}
continue;
}
unreferenced_count += 1;
let recently_created = let recently_created =
stats.created().map_or(false, |t| t > keep_files_newer_than); stats.created().map_or(false, |t| t > keep_files_newer_than);
let recently_modified = stats let recently_modified = stats
@@ -826,7 +841,9 @@ pub async fn remove_unused_files(context: &Context) -> Result<()> {
.accessed() .accessed()
.map_or(false, |t| t > keep_files_newer_than); .map_or(false, |t| t > keep_files_newer_than);
if recently_created || recently_modified || recently_accessed { if p == blobdir
&& (recently_created || recently_modified || recently_accessed)
{
info!( info!(
context, context,
"Housekeeping: Keeping new unreferenced file #{}: {:?}", "Housekeeping: Keeping new unreferenced file #{}: {:?}",
@@ -835,6 +852,8 @@ pub async fn remove_unused_files(context: &Context) -> Result<()> {
); );
continue; continue;
} }
} else {
unreferenced_count += 1;
} }
info!( info!(
context, context,
@@ -856,12 +875,13 @@ pub async fn remove_unused_files(context: &Context) -> Result<()> {
Err(err) => { Err(err) => {
warn!( warn!(
context, context,
"Housekeeping: Cannot open {}. ({})", "Housekeeping: Cannot read dir {}: {:#}",
context.get_blobdir().display(), p.display(),
err err
); );
} }
} }
}
Ok(()) Ok(())
} }
@@ -1061,6 +1081,18 @@ mod tests {
assert_eq!(loaded_draft.unwrap().text.unwrap(), "This is my draft"); assert_eq!(loaded_draft.unwrap().text.unwrap(), "This is my draft");
} }
/// Tests that `housekeeping` deletes the blobs backup dir which is created normally by
/// `imex::import_backup`.
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_housekeeping_delete_blobs_backup_dir() {
let t = TestContext::new_alice().await;
let dir = t.get_blobdir().join(BLOBS_BACKUP_NAME);
tokio::fs::create_dir(&dir).await.unwrap();
tokio::fs::write(dir.join("f"), "").await.unwrap();
housekeeping(&t).await.unwrap();
tokio::fs::create_dir(&dir).await.unwrap();
}
/// Regression test. /// Regression test.
/// ///
/// Previously the code checking for existence of `config` table /// Previously the code checking for existence of `config` table