<commit_before>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 <NAME> <<EMAIL>> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

#![deny(
    non_camel_case_types,
    non_snake_case,
    path_statements,
    trivial_numeric_casts,
    unstable_features,
    unused_allocation,
    unused_import_braces,
    unused_imports,
    unused_must_use,
    unused_mut,
    unused_qualifications,
    while_true,
)]

extern crate clap;
extern crate toml;
extern crate toml_query;
#[macro_use] extern crate version;

extern crate libimagrt;
extern crate libimagerror;
extern crate libimagentrylink;
extern crate libimagstore;

use libimagrt::setup::generate_runtime_setup;
use libimagerror::trace::MapErrTrace;
use libimagstore::store::FileLockEntry;
use libimagstore::iter::get::*;
use libimagstore::error::StoreError as Error;
use libimagentrylink::internal::*;

use toml::Value;
use toml_query::read::TomlValueReadExt;

use std::collections::BTreeMap;

mod ui;

struct Diagnostic {
    pub entry_store_version: String,
    pub header_sections: usize,
    pub bytecount_content: usize,
    pub overall_byte_size: usize,
    pub verified: bool,
    pub num_internal_links: usize,
}

impl<'a> From<FileLockEntry<'a>> for Diagnostic {

    fn from(entry: FileLockEntry<'a>) -> Diagnostic {
        Diagnostic {
            entry_store_version: entry
                .get_header()
                .read("imag.version")
                .map(|opt| match opt {
                    Some(&Value::String(ref s)) => s.clone(),
                    Some(_) => "Non-String type in 'imag.version'".to_owned(),
                    None => "No version".to_owned(),
                })
                .unwrap_or("Error reading version".to_owned()),
            header_sections: match entry.get_header() {
                &Value::Table(ref map) => map.keys().count(),
                _ => 0
            },
            bytecount_content: entry.get_content().as_str().len(),
            overall_byte_size: entry.to_str().as_str().len(),
            verified: entry.verify().is_ok(),
            num_internal_links: entry.get_internal_links().map(Iterator::count).unwrap_or(0),
        }
    }
}

fn main() {
    let rt = generate_runtime_setup("imag-diagnostics",
                                    &version!()[..],
                                    "Print diagnostics about imag and the imag store",
                                    ui::build_ui);

    let diags = rt.store()
        .entries()
        .map_err_trace_exit(1)
        .unwrap()
        .into_get_iter(rt.store())
        .map(|e| {
            e.map_err_trace_exit_unwrap(1)
                .ok_or(Error::from("Unable to get entry".to_owned()))
                .map_err_trace_exit_unwrap(1)
        })
        .map(Diagnostic::from)
        .collect::<Vec<_>>();

    let mut version_counts        : BTreeMap<String, usize> = BTreeMap::new();
    let mut sum_header_sections   = 0;
    let mut sum_bytecount_content = 0;
    let mut sum_overall_byte_size = 0;
    let mut verified_count        = 0;
    let mut unverified_count      = 0;
    let mut num_internal_links    = 0;

    for diag in diags.iter() {
        sum_header_sections     += diag.header_sections;
        sum_bytecount_content   += diag.bytecount_content;
        sum_overall_byte_size   += diag.overall_byte_size;

        let n = version_counts.get(&diag.entry_store_version).map(Clone::clone).unwrap_or(0);
        version_counts.insert(diag.entry_store_version.clone(), n+1);

        if diag.verified {
            verified_count += 1;
        } else {
            unverified_count += 1;
        }

        num_internal_links += diag.num_internal_links;
    }

    let n = diags.len();

    println!("imag version {}", version!());
    println!("");
    println!("{} entries", n);
    for (k, v) in version_counts {
        println!("{} entries with store version '{}'", v, k);
    }
    if n != 0 {
        println!("{} header sections in the average entry", sum_header_sections / n);
        println!("{} average content bytecount", sum_bytecount_content / n);
        println!("{} average overall bytecount", sum_overall_byte_size / n);
        println!("{} average internal link count per entry", num_internal_links / n);
        println!("{} verified entries", verified_count);
        println!("{} unverified entries", unverified_count);
    }
}
<commit_msg>Add output about max internal links and max overall byte size<commit_after>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 <NAME> <<EMAIL>> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

#![deny(
    non_camel_case_types,
    non_snake_case,
    path_statements,
    trivial_numeric_casts,
    unstable_features,
    unused_allocation,
    unused_import_braces,
    unused_imports,
    unused_must_use,
    unused_mut,
    unused_qualifications,
    while_true,
)]

extern crate clap;
extern crate toml;
extern crate toml_query;
#[macro_use] extern crate version;

extern crate libimagrt;
extern crate libimagerror;
extern crate libimagentrylink;
extern crate libimagstore;

use libimagrt::setup::generate_runtime_setup;
use libimagerror::trace::MapErrTrace;
use libimagstore::store::FileLockEntry;
use libimagstore::storeid::StoreId;
use libimagstore::iter::get::*;
use libimagstore::error::StoreError as Error;
use libimagentrylink::internal::*;

use toml::Value;
use toml_query::read::TomlValueReadExt;

use std::collections::BTreeMap;

mod ui;

struct Diagnostic {
    pub id: StoreId,
    pub entry_store_version: String,
    pub header_sections: usize,
    pub bytecount_content: usize,
    pub overall_byte_size: usize,
    pub verified: bool,
    pub num_internal_links: usize,
}

impl<'a> From<FileLockEntry<'a>> for Diagnostic {

    fn from(entry: FileLockEntry<'a>) -> Diagnostic {
        Diagnostic {
            id: entry.get_location().clone(),
            entry_store_version: entry
                .get_header()
                .read("imag.version")
                .map(|opt| match opt {
                    Some(&Value::String(ref s)) => s.clone(),
                    Some(_) => "Non-String type in 'imag.version'".to_owned(),
                    None => "No version".to_owned(),
                })
                .unwrap_or("Error reading version".to_owned()),
            header_sections: match entry.get_header() {
                &Value::Table(ref map) => map.keys().count(),
                _ => 0
            },
            bytecount_content: entry.get_content().as_str().len(),
            overall_byte_size: entry.to_str().as_str().len(),
            verified: entry.verify().is_ok(),
            num_internal_links: entry.get_internal_links().map(Iterator::count).unwrap_or(0),
        }
    }
}

fn main() {
    let rt = generate_runtime_setup("imag-diagnostics",
                                    &version!()[..],
                                    "Print diagnostics about imag and the imag store",
                                    ui::build_ui);

    let diags = rt.store()
        .entries()
        .map_err_trace_exit(1)
        .unwrap()
        .into_get_iter(rt.store())
        .map(|e| {
            e.map_err_trace_exit_unwrap(1)
                .ok_or(Error::from("Unable to get entry".to_owned()))
                .map_err_trace_exit_unwrap(1)
        })
        .map(Diagnostic::from)
        .collect::<Vec<_>>();

    let mut version_counts        : BTreeMap<String, usize> = BTreeMap::new();
    let mut sum_header_sections   = 0;
    let mut sum_bytecount_content = 0;
    let mut sum_overall_byte_size = 0;
    let mut max_overall_byte_size : Option<(usize, StoreId)> = None;
    let mut verified_count        = 0;
    let mut unverified_count      = 0;
    let mut num_internal_links    = 0;
    let mut max_internal_links : Option<(usize, StoreId)> = None;

    for diag in diags.iter() {
        sum_header_sections     += diag.header_sections;
        sum_bytecount_content   += diag.bytecount_content;
        sum_overall_byte_size   += diag.overall_byte_size;
        match max_overall_byte_size {
            None => max_overall_byte_size = Some((diag.num_internal_links, diag.id.clone())),
            Some((num, _)) => if num < diag.overall_byte_size {
                max_overall_byte_size = Some((diag.overall_byte_size, diag.id.clone()));
            }
        }

        let n = version_counts.get(&diag.entry_store_version).map(Clone::clone).unwrap_or(0);
        version_counts.insert(diag.entry_store_version.clone(), n+1);

        if diag.verified {
            verified_count += 1;
        } else {
            unverified_count += 1;
        }

        num_internal_links += diag.num_internal_links;
        match max_internal_links {
            None => max_internal_links = Some((diag.num_internal_links, diag.id.clone())),
            Some((num, _)) => if num < diag.num_internal_links {
                max_internal_links = Some((diag.num_internal_links, diag.id.clone()));
            }
        }
    }

    let n = diags.len();

    println!("imag version {}", version!());
    println!("");
    println!("{} entries", n);
    for (k, v) in version_counts {
        println!("{} entries with store version '{}'", v, k);
    }
    if n != 0 {
        println!("{} header sections in the average entry", sum_header_sections / n);
        println!("{} average content bytecount", sum_bytecount_content / n);
        println!("{} average overall bytecount", sum_overall_byte_size / n);
        if let Some((num, path)) = max_overall_byte_size {
            println!("Largest Entry ({bytes} bytes): {path}",
                bytes = num,
                path = path
                    .into_pathbuf()
                    .map_err_trace_exit_unwrap(1)
                    .to_str()
                    .unwrap_or("Failed converting path to string")
            );
        }
        println!("{} average internal link count per entry", num_internal_links / n);
        if let Some((num, path)) = max_internal_links {
            println!("Entry with most internal links ({count}): {path}",
                     count = num,
                     path = path
                        .into_pathbuf()
                        .map_err_trace_exit_unwrap(1)
                        .to_str()
                        .unwrap_or("Failed converting path to string")
            );
        }
        println!("{} verified entries", verified_count);
        println!("{} unverified entries", unverified_count);
    }
}

{'fraction_non_alphanumeric': 0.11370311319963078, 'fraction_numerical': 0.006377443987580767, 'mean_word_length': 2.393507972665148, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 41, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5091840', 'n_tokens_mistral': 3554, 'n_tokens_neox': 3445, 'n_words': 899}