From b09bae2acfebad4f21b5827b4f5ca3d44d0dbf93 Mon Sep 17 00:00:00 2001 From: Jeffrey Finkelstein Date: Wed, 2 Feb 2022 22:36:44 -0500 Subject: [PATCH] dd: collect progress reporting into its own module Collect structs, implementations, and functions that have to do with reporting number of blocks read and written into their own new module, `progress.rs`. This commit also adds docstrings for everything and unit tests for the significant methods. This commit does not change the behavior of `dd`, just the organization of the code to make it more maintainable and testable. --- src/uu/dd/src/datastructures.rs | 70 ----- src/uu/dd/src/dd.rs | 125 +------- src/uu/dd/src/parseargs.rs | 2 +- src/uu/dd/src/progress.rs | 517 ++++++++++++++++++++++++++++++++ 4 files changed, 524 insertions(+), 190 deletions(-) create mode 100644 src/uu/dd/src/progress.rs diff --git a/src/uu/dd/src/datastructures.rs b/src/uu/dd/src/datastructures.rs index 8380965a9..c9c89e858 100644 --- a/src/uu/dd/src/datastructures.rs +++ b/src/uu/dd/src/datastructures.rs @@ -7,72 +7,11 @@ // spell-checker:ignore ctable, outfile use std::error::Error; -use std::time; use uucore::error::UError; use crate::conversion_tables::*; -pub struct ProgUpdate { - pub read_stat: ReadStat, - pub write_stat: WriteStat, - pub duration: time::Duration, -} - -impl ProgUpdate { - pub(crate) fn new( - read_stat: ReadStat, - write_stat: WriteStat, - duration: time::Duration, - ) -> Self { - Self { - read_stat, - write_stat, - duration, - } - } -} - -#[derive(Clone, Copy, Default)] -pub struct ReadStat { - pub reads_complete: u64, - pub reads_partial: u64, - pub records_truncated: u32, -} - -impl ReadStat { - /// Whether this counter has zero complete reads and zero partial reads. - pub(crate) fn is_empty(&self) -> bool { - self.reads_complete == 0 && self.reads_partial == 0 - } -} - -impl std::ops::AddAssign for ReadStat { - fn add_assign(&mut self, other: Self) { - *self = Self { - reads_complete: self.reads_complete + other.reads_complete, - reads_partial: self.reads_partial + other.reads_partial, - records_truncated: self.records_truncated + other.records_truncated, - } - } -} - -#[derive(Clone, Copy, Default)] -pub struct WriteStat { - pub writes_complete: u64, - pub writes_partial: u64, - pub bytes_total: u128, -} -impl std::ops::AddAssign for WriteStat { - fn add_assign(&mut self, other: Self) { - *self = Self { - writes_complete: self.writes_complete + other.writes_complete, - writes_partial: self.writes_partial + other.writes_partial, - bytes_total: self.bytes_total + other.bytes_total, - } - } -} - type Cbs = usize; /// Stores all Conv Flags that apply to the input @@ -138,15 +77,6 @@ pub struct OFlags { pub seek_bytes: bool, } -/// The value of the status cl-option. -/// Controls printing of transfer stats -#[derive(Copy, Clone, Debug, PartialEq)] -pub enum StatusLevel { - Progress, - Noxfer, - None, -} - /// The value of count=N /// Defaults to Reads(N) /// if iflag=count_bytes diff --git a/src/uu/dd/src/dd.rs b/src/uu/dd/src/dd.rs index b38671a9a..c8004b893 100644 --- a/src/uu/dd/src/dd.rs +++ b/src/uu/dd/src/dd.rs @@ -5,7 +5,7 @@ // For the full copyright and license information, please view the LICENSE // file that was distributed with this source code. -// spell-checker:ignore fname, tname, fpath, specfile, testfile, unspec, ifile, ofile, outfile, fullblock, urand, fileio, atoe, atoibm, behaviour, bmax, bremain, btotal, cflags, creat, ctable, ctty, datastructures, doesnt, etoa, fileout, fname, gnudd, iconvflags, nocache, noctty, noerror, nofollow, nolinks, nonblock, oconvflags, outfile, parseargs, rlen, rmax, rposition, rremain, rsofar, rstat, sigusr, sigval, wlen, wstat seekable +// spell-checker:ignore fname, tname, fpath, specfile, testfile, unspec, ifile, ofile, outfile, fullblock, urand, fileio, atoe, atoibm, behaviour, bmax, bremain, cflags, creat, ctable, ctty, datastructures, doesnt, etoa, fileout, fname, gnudd, iconvflags, nocache, noctty, noerror, nofollow, nolinks, nonblock, oconvflags, outfile, parseargs, rlen, rmax, rposition, rremain, rsofar, rstat, sigusr, wlen, wstat seekable mod datastructures; use datastructures::*; @@ -16,27 +16,23 @@ use parseargs::Matches; mod conversion_tables; use conversion_tables::*; +mod progress; +use progress::{gen_prog_updater, ProgUpdate, ReadStat, StatusLevel, WriteStat}; + use std::cmp; use std::convert::TryInto; use std::env; -#[cfg(target_os = "linux")] -use std::error::Error; use std::fs::{File, OpenOptions}; use std::io::{self, Read, Seek, Write}; #[cfg(target_os = "linux")] use std::os::unix::fs::OpenOptionsExt; use std::path::Path; use std::sync::mpsc; -#[cfg(target_os = "linux")] -use std::sync::{atomic::AtomicUsize, atomic::Ordering, Arc}; use std::thread; use std::time; -use byte_unit::Byte; use clap::{crate_version, App, AppSettings, Arg, ArgMatches}; use gcd::Gcd; -#[cfg(target_os = "linux")] -use signal_hook::consts::signal; use uucore::display::Quotable; use uucore::error::{FromIo, UResult, USimpleError}; use uucore::show_error; @@ -351,8 +347,8 @@ where fn print_stats(&self, i: &Input, prog_update: &ProgUpdate) { match i.print_level { Some(StatusLevel::None) => {} - Some(StatusLevel::Noxfer) => print_io_lines(prog_update), - Some(StatusLevel::Progress) | None => print_transfer_stats(prog_update), + Some(StatusLevel::Noxfer) => prog_update.print_io_lines(), + Some(StatusLevel::Progress) | None => prog_update.print_transfer_stats(), } } @@ -771,115 +767,6 @@ fn read_helper(i: &mut Input, bsize: usize) -> std::io::Result<(Read } } -// Print io lines of a status update: -// + records in -// + records out -fn print_io_lines(update: &ProgUpdate) { - eprintln!( - "{}+{} records in", - update.read_stat.reads_complete, update.read_stat.reads_partial - ); - eprintln!( - "{}+{} records out", - update.write_stat.writes_complete, update.write_stat.writes_partial - ); - match update.read_stat.records_truncated { - 0 => {} - 1 => eprintln!("1 truncated record"), - n => eprintln!("{} truncated records", n), - } -} -// Print the progress line of a status update: -// bytes (, ) copied,