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 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}