blkar_lib/
cli_calc.rs

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