Skip to content

Commit e7f7555

Browse files
authored
Merge pull request #54 from silicon-heaven/add-log-retention
Add log retention
2 parents 497129e + 752e679 commit e7f7555

9 files changed

Lines changed: 37 additions & 28 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "historyprovider"
3-
version = "2.2.1"
3+
version = "2.3.0"
44
edition = "2024"
55

66
[[bin]]

src/cleanup.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ use tokio::io;
55
use std::collections::HashMap;
66
use std::path::{Path, PathBuf};
77

8+
use crate::util::msec_to_log2_filename;
9+
810
#[derive(Debug, Clone)]
911
pub(crate) struct LogFile {
1012
pub(crate) name: PathBuf,
@@ -40,11 +42,11 @@ pub(crate) async fn collect_log2_files(dir: impl AsRef<Path>) -> io::Result<Vec<
4042
}
4143

4244
/// Prune `.log2` files while keeping the newest one per directory
43-
pub(crate) async fn cleanup_log2_files(dir: impl AsRef<Path>, size_limit: u64) -> io::Result<()> {
45+
pub(crate) async fn cleanup_log2_files(dir: impl AsRef<Path>, size_limit: u64, days_to_keep: i64) -> io::Result<()> {
4446
let files = collect_log2_files(dir.as_ref()).await?;
4547
let mut files_size: u64 = files.iter().map(|f| f.size).sum();
4648

47-
info!("log2 files size: {files_size}, size limit: {size_limit}");
49+
info!("log2 files size: {files_size}, size limit: {size_limit}, days_to_keep: {days_to_keep}");
4850
if files_size < size_limit {
4951
info!("Size limit not hit, nothing to cleanup");
5052
return Ok(());
@@ -58,11 +60,15 @@ pub(crate) async fn cleanup_log2_files(dir: impl AsRef<Path>, size_limit: u64) -
5860

5961
let mut deletable_files = Vec::new();
6062

63+
// This file doesn't have to exist, I'm only constructing the filename for log retention.
64+
let oldest_file_to_keep = PathBuf::from(msec_to_log2_filename(shvproto::DateTime::now().add_days(-days_to_keep).epoch_msec()));
65+
info!("keeping files younger than {filename}", filename = oldest_file_to_keep.to_string_lossy());
66+
6167
for (_dir, mut group) in grouped {
6268
// Sort descending (newest first)
6369
group.sort_by(|a, b| b.name.cmp(&a.name));
64-
// Keep the newest file
65-
deletable_files.extend(group.into_iter().skip(1));
70+
// Keep the newest file, and keep files newer than oldest_file_to_delete
71+
deletable_files.extend(group.into_iter().skip(1).filter(|log_file| log_file.name < oldest_file_to_keep));
6672
}
6773

6874
// Sort deletable files (oldest first for deletion)

src/dirtylog.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ pub(crate) async fn dirtylog_task(
118118
Ok(file) => file,
119119
Err(err) => {
120120
if err.kind() == std::io::ErrorKind::NotFound {
121-
info!("Trim dirty log done, no dirty log file for the site");
121+
info!("Trim dirty log done, no dirty log file for the site {site}");
122122
} else {
123123
error!("Cannot trim dirty log. Cannot open file {file_path}: {err}", file_path = dirty_log_path.to_string_lossy());
124124
}

src/lib.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@ mod util;
2727
pub mod typeinfo;
2828
pub mod alarm;
2929

30-
const MAX_JOURNAL_DIR_SIZE_DEFAULT: usize = 30 * 1_000_000_000;
31-
3230
fn default_journal_dir() -> String {
3331
"/tmp/hp-rs/shvjournal".into()
3432
}
@@ -40,6 +38,7 @@ pub struct HpConfig {
4038
max_sync_tasks: Option<usize>,
4139
max_journal_dir_size: Option<usize>,
4240
periodic_sync_interval: Option<u64>,
41+
days_to_keep: Option<i64>,
4342
}
4443

4544
impl HpConfig {

src/sites.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,6 @@ pub(crate) async fn sites_task(
406406

407407
let (sites_info, sub_hps) = match sites {
408408
Ok(sites) => {
409-
eprintln!("sites = '{:?}'", sites);
410409
if sites
411410
.get("_meta")
412411
.map(RpcValue::as_map)

src/sync.rs

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ use crate::journalentry::JournalEntry;
2424
use crate::journalrw::{GetLog2Params, GetLog2Since, JournalReaderLog2, JournalWriterLog2, Log2Reader};
2525
use crate::sites::{SitesData, SubHpInfo};
2626
use crate::tree::{FileType, LsFilesEntry, METH_READ};
27-
use crate::util::{get_files, is_log2_file, DedupReceiver};
28-
use crate::{State, MAX_JOURNAL_DIR_SIZE_DEFAULT};
27+
use crate::util::{get_files, is_log2_file, msec_to_log2_filename, DedupReceiver};
28+
use crate::{HpConfig, State};
2929

3030
#[derive(Default)]
3131
pub(crate) struct SyncInfo {
@@ -542,13 +542,6 @@ async fn sync_site_legacy(
542542
const GETLOG_SINCE_DAYS_DEFAULT: i64 = 365;
543543
const RECORD_COUNT_LIMIT: i64 = 10000;
544544

545-
fn msec_to_log2_filename(msec: i64) -> String {
546-
shvproto::DateTime::from_epoch_msec(msec)
547-
.to_chrono_datetime()
548-
.format("%Y-%m-%dT%H-%M-%S-%3f.log2")
549-
.to_string()
550-
}
551-
552545
let (mut getlog_params, mut log_file_path, mut log_file_entries) = match newest_log {
553546
Some((newest_log_file, newest_log_entries)) => {
554547
let last_log_entry_msec = newest_log_entries.last().expect("The newest log is not empty").epoch_msec;
@@ -699,6 +692,11 @@ async fn sync_site_legacy(
699692

700693
const MAX_SYNC_TASKS_DEFAULT: usize = 8;
701694

695+
pub fn log_size_limit(config: &HpConfig) -> u64 {
696+
const MAX_JOURNAL_DIR_SIZE_DEFAULT: usize = 30 * 1_000_000_000;
697+
config.max_journal_dir_size.unwrap_or(MAX_JOURNAL_DIR_SIZE_DEFAULT) as u64
698+
}
699+
702700
pub(crate) async fn sync_task(
703701
client_cmd_tx: ClientCommandSender,
704702
_client_evt_rx: ClientEventsReceiver,
@@ -723,7 +721,8 @@ pub(crate) async fn sync_task(
723721

724722
// The download size limit should be lower than the max_journal_dir_size, because it doesn't
725723
// count in the files synced by getLog.
726-
let max_journal_dir_size = app_state.config.max_journal_dir_size.unwrap_or(MAX_JOURNAL_DIR_SIZE_DEFAULT) as u64;
724+
let max_journal_dir_size = log_size_limit(&app_state.config);
725+
let days_to_keep = app_state.config.days_to_keep.unwrap_or(0);
727726

728727
while let Some(cmd) = sync_cmd_rx.next().await {
729728
match cmd {
@@ -819,7 +818,7 @@ pub(crate) async fn sync_task(
819818
panic!("Cannot send dirtylog Trim command for site {site}: {e}")
820819
)
821820
);
822-
match cleanup_log2_files(&app_state.config.journal_dir, max_journal_dir_size).await {
821+
match cleanup_log2_files(&app_state.config.journal_dir, max_journal_dir_size, days_to_keep).await {
823822
Ok(_) => info!("Cleanup journal dir done"),
824823
Err(err) => error!("Cleanup journal dir error: {err}"),
825824
}
@@ -883,7 +882,7 @@ pub(crate) async fn sync_task(
883882
.unwrap_or_else(|e|
884883
panic!("Cannot send dirtylog Trim command for site {site}: {e}")
885884
);
886-
match cleanup_log2_files(&app_state.config.journal_dir, max_journal_dir_size).await {
885+
match cleanup_log2_files(&app_state.config.journal_dir, max_journal_dir_size, days_to_keep).await {
887886
Ok(_) => info!("Cleanup journal dir done"),
888887
Err(err) => error!("Cleanup journal dir error: {err}"),
889888
}
@@ -893,7 +892,7 @@ pub(crate) async fn sync_task(
893892
}
894893
SyncCommand::Cleanup => {
895894
info!("Cleanup journal dir start");
896-
match cleanup_log2_files(&app_state.config.journal_dir, max_journal_dir_size).await {
895+
match cleanup_log2_files(&app_state.config.journal_dir, max_journal_dir_size, days_to_keep).await {
897896
Ok(_) => info!("Cleanup journal dir done"),
898897
Err(err) => error!("Cleanup journal dir error: {err}"),
899898
}

src/tree.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ use crate::getlog::getlog_handler;
2626
use crate::journalrw::{journal_entries_to_rpcvalue, GetLog2Params, Log2Header, Log2Reader};
2727
use crate::pushlog::pushlog_impl;
2828
use crate::sites::SubHpInfo;
29-
use crate::{AlarmWithTimestamp, HpConfig, State, MAX_JOURNAL_DIR_SIZE_DEFAULT};
29+
use crate::sync::log_size_limit;
30+
use crate::{AlarmWithTimestamp, HpConfig, State};
3031

3132
// History site node methods
3233
const METH_GET_LOG: &str = "getLog";
@@ -333,10 +334,6 @@ impl From<LsFilesEntry> for RpcValue {
333334
}
334335
}
335336

336-
fn log_size_limit(config: &HpConfig) -> i64 {
337-
config.max_journal_dir_size.unwrap_or(MAX_JOURNAL_DIR_SIZE_DEFAULT) as i64
338-
}
339-
340337
async fn total_log_size(config: &HpConfig) -> tokio::io::Result<i64> {
341338
collect_log2_files(&config.journal_dir)
342339
.await

src/util.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,14 @@ pub(crate) fn dedup_channel<T: Eq + Hash + Clone>() -> (DedupSender<T>, DedupRec
134134
(DedupSender { pending: pending.clone(), sender }, DedupReceiver { pending, receiver })
135135
}
136136

137+
pub(crate) fn msec_to_log2_filename(msec: i64) -> String {
138+
shvproto::DateTime::from_epoch_msec(msec)
139+
.to_chrono_datetime()
140+
.format("%Y-%m-%dT%H-%M-%S-%3f.log2")
141+
.to_string()
142+
}
143+
144+
137145
#[cfg(test)]
138146
pub mod testing {
139147
use crate::{State, dirtylog::DirtyLogCommand, sites::{SiteInfo, SitesData, SubHpInfo}, sync::SyncCommand, util::{DedupReceiver, dedup_channel}};
@@ -398,6 +406,7 @@ pub mod testing {
398406
journal_dir: journal_dir.path().to_str().expect("path must work").to_string(),
399407
max_sync_tasks: None,
400408
max_journal_dir_size: None,
409+
days_to_keep: None,
401410
periodic_sync_interval: Some(3),
402411
},
403412
dirtylog_cmd_tx,

0 commit comments

Comments
 (0)