From 5928c40d4ef0e2b68fe09a277118dc8ecfea1032 Mon Sep 17 00:00:00 2001 From: Archis Gore Date: Tue, 4 Aug 2020 13:00:00 -0700 Subject: [PATCH 1/2] Add mode to write complete record (even if bytes may be surpassed) When rotating files, especially large log files (in kilobytes or megabytes), to have a soft bytes-limit vs a hard one, i.e. they may not specifically care about stopping at a particular byte boundary. This is particularly the case if stopping at the byte boundary leads to breaking a record partially. Since file-rotation is most useful for logging, it ma kes no se nse t o bre ak up the record in this manner. Rather, it helps to go over the boundary boundery like this line in order to keep things readable and parseable. HOW: 1. Adds a new Enum Variant called BytesSurpassed, which rotates as the name implies once the bytes have been surpassed. 2. The implementation is a simpler case of the Bytes variant. 3. Added a unit test to verify/guard. --- src/lib.rs | 44 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index c026ac1..c2ff2a5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -140,6 +140,8 @@ pub enum RotationMode { Bytes(usize), /// Cut the log file at line breaks. Lines(usize), + /// Cut the log file after surpassing size in bytes (but having written a complete buffer from a write call.) + BytesSurpassed(usize), } /// The main writer used for rotating logs. @@ -171,10 +173,13 @@ impl FileRotate { match rotation_mode { RotationMode::Bytes(bytes) => { assert!(bytes > 0); - } + }, RotationMode::Lines(lines) => { assert!(lines > 0); - } + }, + RotationMode::BytesSurpassed(bytes) => { + assert!(bytes > 0); + }, }; Self { @@ -245,6 +250,19 @@ impl Write for FileRotate { if let Some(Err(err)) = self.file.as_mut().map(|file| file.write(buf)) { return Err(err); } + }, + RotationMode::BytesSurpassed(bytes) => { + if let Some(Err(err)) = self + .file + .as_mut() + .map(|file| file.write(&buf)) + { + return Err(err); + } + self.count += buf.len(); + if self.count > bytes { + self.rotate()? + } } } Ok(written) @@ -307,6 +325,27 @@ mod tests { assert_eq!("d\n", fs::read_to_string("target/rotate/log.0").unwrap()); } + #[test] + fn write_complete_record_until_bytes_surpassed() { + let _ = fs::remove_dir_all("target/surpassed_bytes"); + fs::create_dir("target/surpassed_bytes").unwrap(); + + let mut rot = FileRotate::new("target/surpassed_bytes/log", RotationMode::BytesSurpassed(1), 1); + + write!(rot, "0123456789").unwrap(); + rot.flush().unwrap(); + assert!(Path::new("target/surpassed_bytes/log.0").exists()); + // shouldn't exist yet - because entire record was written in one shot + assert!(!Path::new("target/surpassed_bytes/log.1").exists()); + + // This should create the second file + write!(rot, "0123456789").unwrap(); + rot.flush().unwrap(); + assert!(Path::new("target/surpassed_bytes/log.1").exists()); + + fs::remove_dir_all("target/surpassed_bytes").unwrap(); + } + #[quickcheck_macros::quickcheck] fn arbitrary_lines(count: usize) { let _ = fs::remove_dir_all("target/arbitrary_lines"); @@ -346,4 +385,5 @@ mod tests { fs::remove_dir_all("target/arbitrary_bytes").unwrap(); } + } From 55c743612a493b9c993739b37739fa5e3280c00e Mon Sep 17 00:00:00 2001 From: Archis Gore Date: Tue, 24 Nov 2020 10:09:20 -0800 Subject: [PATCH 2/2] Cargo fmt --- src/lib.rs | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index c2ff2a5..f3989fb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -173,13 +173,13 @@ impl FileRotate { match rotation_mode { RotationMode::Bytes(bytes) => { assert!(bytes > 0); - }, + } RotationMode::Lines(lines) => { assert!(lines > 0); - }, + } RotationMode::BytesSurpassed(bytes) => { assert!(bytes > 0); - }, + } }; Self { @@ -250,13 +250,9 @@ impl Write for FileRotate { if let Some(Err(err)) = self.file.as_mut().map(|file| file.write(buf)) { return Err(err); } - }, + } RotationMode::BytesSurpassed(bytes) => { - if let Some(Err(err)) = self - .file - .as_mut() - .map(|file| file.write(&buf)) - { + if let Some(Err(err)) = self.file.as_mut().map(|file| file.write(&buf)) { return Err(err); } self.count += buf.len(); @@ -330,7 +326,11 @@ mod tests { let _ = fs::remove_dir_all("target/surpassed_bytes"); fs::create_dir("target/surpassed_bytes").unwrap(); - let mut rot = FileRotate::new("target/surpassed_bytes/log", RotationMode::BytesSurpassed(1), 1); + let mut rot = FileRotate::new( + "target/surpassed_bytes/log", + RotationMode::BytesSurpassed(1), + 1, + ); write!(rot, "0123456789").unwrap(); rot.flush().unwrap(); @@ -385,5 +385,4 @@ mod tests { fs::remove_dir_all("target/arbitrary_bytes").unwrap(); } - }