blkar_lib/
cli_calc.rs

1use sbx_specs::{Version,
2                ver_to_usize,
3                ver_to_block_size,
4                ver_to_data_size,
5                ver_uses_rs};
6
7use std::str::FromStr;
8
9use file_utils;
10
11use json_printer::BracketType;
12
13use clap::*;
14use cli_utils::*;
15pub fn sub_command<'a, 'b>() -> App<'a, 'b> {
16    SubCommand::with_name("calc")
17        .about("Calculate and display detailed information given an encoding configuration
18
19===== IMPORTANT =====
20Please note that this is the last version of this software to be released under the name rsbx,
21future releases will be published under the name blkar. See project repo for details.
22=====================")
23        .arg(Arg::with_name("in_file_size")
24             .value_name("INFILE-SIZE")
25             .required(true)
26             .index(1)
27             .help("Input file size"))
28        .arg(sbx_version_arg())
29        .arg(Arg::with_name("no_meta")
30             .long("no-meta")
31             .help("Skip metadata block in the calculations. Metadata block is
32never skipped for version 17, 18, 19.
33This means this option has no effect for version 17, 18, 19."))
34        .arg(rs_data_arg())
35        .arg(rs_parity_arg())
36        .arg(burst_arg())
37        .arg(json_arg())
38}
39
40pub fn calc<'a>(matches : &ArgMatches<'a>) -> i32 {
41    let json_printer = get_json_printer!(matches);
42
43    json_printer.print_open_bracket(None, BracketType::Curly);
44
45    let version = get_version!(matches, json_printer);
46
47    let meta_enabled = Some(get_meta_enabled!(matches));
48
49    let in_file_size =
50        match u64::from_str(matches.value_of("in_file_size").unwrap()) {
51            Ok(x)  => x,
52            Err(_) => exit_with_msg!(usr json_printer => "Invalid file size")
53        };
54
55    let data_par_burst =
56        if ver_uses_rs(version) {
57            // deal with RS related options
58            let data_shards   = get_data_shards!(matches, version, json_printer);
59            let parity_shards = get_parity_shards!(matches, version, json_printer);
60
61            check_data_parity_shards!(data_shards, parity_shards, json_printer);
62
63            let burst = get_burst_or_zero!(matches, json_printer);
64
65            Some((data_shards, parity_shards, burst))
66        } else {
67            None
68        };
69
70    let out_file_size =
71        file_utils::from_orig_file_size::calc_container_size(version,
72                                                             meta_enabled,
73                                                             data_par_burst,
74                                                             in_file_size);
75
76    let total_block_count =
77        file_utils::from_orig_file_size::calc_total_block_count_exc_burst_gaps(version,
78                                                                               meta_enabled,
79                                                                               data_par_burst,
80                                                                               in_file_size);
81
82    let meta_block_count =
83        file_utils::calc_meta_block_count_exc_burst_gaps(version,
84                                                         meta_enabled,
85                                                         data_par_burst);
86
87    let (data_only_block_count, parity_block_count) =
88        file_utils::from_orig_file_size::calc_data_only_and_parity_block_count_exc_burst_gaps(version,
89                                                                                              data_par_burst,
90                                                                                              in_file_size);
91
92    json_printer.print_open_bracket(Some("stats"), BracketType::Curly);
93
94    print_if!(not_json => json_printer =>
95             "SBX container general info";
96             "========================================";);
97    if ver_uses_rs(version) {
98        print_maybe_json!(json_printer, "    SBX container version        : {}",
99                          ver_to_usize(version));
100    } else {
101        print_maybe_json!(json_printer, "    SBX container version        : {}", ver_to_usize(version));
102    }
103    print_maybe_json!(json_printer,     "    SBX container block size     : {}", ver_to_block_size(version) => skip_quotes);
104    print_maybe_json!(json_printer,     "    SBX container data  size     : {}", ver_to_data_size(version)  => skip_quotes);
105
106    print_if!(not_json => json_printer => "";);
107
108    print_if!(not_json => json_printer => "SBX block distribution";);
109    print_if!(not_json => json_printer => "========================================";);
110    if ver_uses_rs(version) {
111        print_maybe_json!(json_printer,   "    Metadata    block count      : {}", meta_block_count      => skip_quotes);
112        print_maybe_json!(json_printer,   "    Data only   block count      : {}", data_only_block_count => skip_quotes);
113        print_maybe_json!(json_printer,   "    Data parity block count      : {}", parity_block_count    => skip_quotes);
114        print_maybe_json!(json_printer,   "    Total       block count      : {}", total_block_count     => skip_quotes);
115    } else {
116        print_maybe_json!(json_printer,   "    Metadata block count         : {}", meta_block_count      => skip_quotes);
117        print_maybe_json!(json_printer,   "    Data     block count         : {}", data_only_block_count => skip_quotes);
118        print_maybe_json!(json_printer,   "    Total    block count         : {}", total_block_count     => skip_quotes);
119    }
120
121    print_if!(not_json => json_printer => "";);
122
123    print_if!(not_json => json_printer => "Error correction info";);
124    print_if!(not_json => json_printer => "========================================";);
125    if ver_uses_rs(version) {
126        print_maybe_json!(json_printer,   "    RS data   shard count        : {}", data_par_burst.unwrap().0  => skip_quotes);
127        print_maybe_json!(json_printer,   "    RS parity shard count        : {}", data_par_burst.unwrap().1  => skip_quotes);
128        print_maybe_json!(json_printer,   "    Burst error resistance level : {}", data_par_burst.unwrap().2  => skip_quotes);
129    } else {
130        print_maybe_json!(json_printer,   "    RS data   shard count        : {}",
131                          null_if_json_else!(json_printer, "version does not use RS")                         => skip_quotes);
132        print_maybe_json!(json_printer,   "    RS parity shard count        : {}",
133                          null_if_json_else!(json_printer, "version does not use RS")                         => skip_quotes);
134        print_maybe_json!(json_printer,   "    Burst error resistance level : {}",
135                          null_if_json_else!(json_printer, "version does not support burst error resistance") => skip_quotes);
136    }
137
138    print_if!(not_json => json_printer => "";);
139
140    if ver_uses_rs(version) && !json_printer.json_enabled() {
141        let (data, par, burst) = data_par_burst.unwrap();
142
143        let block_size = ver_to_block_size(version);
144
145        println!("Error correction parameters interpretation");
146        println!("========================================");
147        if burst == 0 {
148            print_block!(
149                "    The container can tolerate {} SBX block corruptions", par;
150                "    in any block set.";
151                "";
152                "    A block set consists of {} blocks ({} bytes).", (data + par), (data + par) * block_size;
153                "";
154                "    In total, {} blocks({} bytes) may be corrupted in", par, par * block_size;
155                "    any block set.";
156            );
157        } else {
158            if burst == 1 {
159                print_block!(
160                    "    Warning :";
161                    "";
162                    "        Burst error resistance level of {} may not provide", burst;
163                    "        meaningful resistance.";
164                    "";
165                );
166            }
167
168            let block_set_size       = data + par;
169            let super_block_set_size = (data + par) * burst;
170
171            print_block!("    The container can tolerate {} burst SBX block corruptions in", par;
172                         "    any super block set ({} interleaved block sets).", burst;
173                         "";
174                         "    A block set consists of {} blocks ({} bytes).", block_set_size, block_set_size * block_size;
175                         "";
176                         "    A super block set consists of {} blocks ({} bytes).", super_block_set_size, super_block_set_size * block_size;
177                         "";
178                         "    Each burst error may be up to {} blocks ({} bytes) in size.", burst, burst * block_size;
179                         "";
180                         "    In total, {} sets of {} consecutive blocks ({} bytes) may be", par, burst, burst * block_size;
181                         "    corrupted in any super block set.";
182                         "";
183                         "    The sets of corrupted blocks may be connected as well, so the";
184                         "    largest single burst error that can be tolerated in any super";
185                         "    block set is {} blocks({} bytes) in size.", par * burst, par * burst * block_size;
186                         "";
187                         "    Note that the actual tolerance depends on the behaviour of";
188                         "    the file system.";
189            );
190        }
191
192        println!();
193    }
194
195    print_if!(not_json => json_printer => "File and container size";);
196    print_if!(not_json => json_printer => "========================================";);
197    print_maybe_json!(json_printer,       "    File size                    : {}", in_file_size  => skip_quotes);
198    print_maybe_json!(json_printer,       "    SBX container size           : {}", out_file_size => skip_quotes);
199
200    json_printer.print_close_bracket();
201
202    exit_with_msg!(ok json_printer => "")
203}