From ec78237198f2d5b68df948e6a59ad255e4163d7e Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Thu, 12 Oct 2017 22:46:47 +0200 Subject: [PATCH 1/5] Initial imag-diagnostics import --- Cargo.toml | 1 + bin/core/imag-diagnostics/Cargo.toml | 23 ++++++++++ bin/core/imag-diagnostics/src/main.rs | 61 +++++++++++++++++++++++++++ bin/core/imag-diagnostics/src/ui.rs | 25 +++++++++++ 4 files changed, 110 insertions(+) create mode 100644 bin/core/imag-diagnostics/Cargo.toml create mode 100644 bin/core/imag-diagnostics/src/main.rs create mode 100644 bin/core/imag-diagnostics/src/ui.rs diff --git a/Cargo.toml b/Cargo.toml index 3ec4b5b6..e9276006 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,7 @@ members = [ "bin/core/imag", "bin/core/imag-annotate", + "bin/core/imag-diagnostics", "bin/core/imag-gps", "bin/core/imag-grep", "bin/core/imag-link", diff --git a/bin/core/imag-diagnostics/Cargo.toml b/bin/core/imag-diagnostics/Cargo.toml new file mode 100644 index 00000000..10fa5f80 --- /dev/null +++ b/bin/core/imag-diagnostics/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "imag-diagnostics" +version = "0.5.0" +authors = ["Matthias Beyer "] + +description = "Part of the imag core distribution: imag-gps command" + +keywords = ["imag", "PIM", "personal", "information", "management"] +readme = "../../../README.md" +license = "LGPL-2.1" + +documentation = "https://matthiasbeyer.github.io/imag/imag_documentation/index.html" +repository = "https://github.com/matthiasbeyer/imag" +homepage = "http://imag-pim.org" + +[dependencies] +clap = ">=2.17" +version = "2.0.1" + +libimagstore = { version = "0.5.0", path = "../../../lib/core/libimagstore" } +libimagrt = { version = "0.5.0", path = "../../../lib/core/libimagrt" } +libimagerror = { version = "0.5.0", path = "../../../lib/core/libimagerror" } + diff --git a/bin/core/imag-diagnostics/src/main.rs b/bin/core/imag-diagnostics/src/main.rs new file mode 100644 index 00000000..2e9a1c30 --- /dev/null +++ b/bin/core/imag-diagnostics/src/main.rs @@ -0,0 +1,61 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015, 2016 Matthias Beyer 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; +#[macro_use] extern crate version; + +extern crate libimagrt; +extern crate libimagerror; +extern crate libimagstore; + +use libimagrt::setup::generate_runtime_setup; +use libimagerror::trace::MapErrTrace; + +mod ui; + +fn main() { + let rt = generate_runtime_setup("imag-diagnostics", + &version!()[..], + "Print diagnostics about imag and the imag store", + ui::build_ui); + + let n = rt.store() + .entries() + .map_err_trace_exit(1) + .unwrap() + .count(); + + println!("{} entries", n); +} + diff --git a/bin/core/imag-diagnostics/src/ui.rs b/bin/core/imag-diagnostics/src/ui.rs new file mode 100644 index 00000000..c3f2fab8 --- /dev/null +++ b/bin/core/imag-diagnostics/src/ui.rs @@ -0,0 +1,25 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015, 2016 Matthias Beyer 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 +// + +use clap::App; + +pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> { + app +} + From f9a56bee3f3377e860dcf5949e65ffdc0e83a478 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Thu, 12 Oct 2017 23:46:39 +0200 Subject: [PATCH 2/5] Add a few small diagnostics --- bin/core/imag-diagnostics/Cargo.toml | 2 + bin/core/imag-diagnostics/src/main.rs | 89 ++++++++++++++++++++++++++- 2 files changed, 89 insertions(+), 2 deletions(-) diff --git a/bin/core/imag-diagnostics/Cargo.toml b/bin/core/imag-diagnostics/Cargo.toml index 10fa5f80..0cff95b2 100644 --- a/bin/core/imag-diagnostics/Cargo.toml +++ b/bin/core/imag-diagnostics/Cargo.toml @@ -16,6 +16,8 @@ homepage = "http://imag-pim.org" [dependencies] clap = ">=2.17" version = "2.0.1" +toml = "0.4" +toml-query = "0.4" libimagstore = { version = "0.5.0", path = "../../../lib/core/libimagstore" } libimagrt = { version = "0.5.0", path = "../../../lib/core/libimagrt" } diff --git a/bin/core/imag-diagnostics/src/main.rs b/bin/core/imag-diagnostics/src/main.rs index 2e9a1c30..e71e7fe3 100644 --- a/bin/core/imag-diagnostics/src/main.rs +++ b/bin/core/imag-diagnostics/src/main.rs @@ -33,6 +33,8 @@ )] extern crate clap; +extern crate toml; +extern crate toml_query; #[macro_use] extern crate version; extern crate libimagrt; @@ -41,21 +43,104 @@ 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 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, +} + +impl<'a> From> 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(), + } + } +} + fn main() { let rt = generate_runtime_setup("imag-diagnostics", &version!()[..], "Print diagnostics about imag and the imag store", ui::build_ui); - let n = rt.store() + let diags = rt.store() .entries() .map_err_trace_exit(1) .unwrap() - .count(); + .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::>(); + let mut version_counts : BTreeMap = 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; + + 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; + } + } + + 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!("{} verified entries", verified_count); + println!("{} unverified entries", unverified_count); + } } From a5042ba80c96604f353aaee10db04398752e588c Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Fri, 13 Oct 2017 11:36:36 +0200 Subject: [PATCH 3/5] Add changelog entry --- doc/src/09020-changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/src/09020-changelog.md b/doc/src/09020-changelog.md index 9129b57c..763c4763 100644 --- a/doc/src/09020-changelog.md +++ b/doc/src/09020-changelog.md @@ -29,6 +29,7 @@ This section contains the changelog from the last release to the next release. stderr) * `imag-store` can dump all storeids now * `imag-annotate` was introduced + * `imag-diagnostics` was added * Minor changes * `libimagentryannotation` got a rewrite, is not based on `libimagnotes` From 6daeefa0d8c9fbafa96aa69ace406021ea8d997f Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Fri, 13 Oct 2017 16:42:37 +0200 Subject: [PATCH 4/5] Show average link count in all entries --- bin/core/imag-diagnostics/Cargo.toml | 1 + bin/core/imag-diagnostics/src/main.rs | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/bin/core/imag-diagnostics/Cargo.toml b/bin/core/imag-diagnostics/Cargo.toml index 0cff95b2..68eafc83 100644 --- a/bin/core/imag-diagnostics/Cargo.toml +++ b/bin/core/imag-diagnostics/Cargo.toml @@ -22,4 +22,5 @@ toml-query = "0.4" libimagstore = { version = "0.5.0", path = "../../../lib/core/libimagstore" } libimagrt = { version = "0.5.0", path = "../../../lib/core/libimagrt" } libimagerror = { version = "0.5.0", path = "../../../lib/core/libimagerror" } +libimagentrylink = { version = "0.5.0", path = "../../../lib/entry/libimagentrylink" } diff --git a/bin/core/imag-diagnostics/src/main.rs b/bin/core/imag-diagnostics/src/main.rs index e71e7fe3..77aeb023 100644 --- a/bin/core/imag-diagnostics/src/main.rs +++ b/bin/core/imag-diagnostics/src/main.rs @@ -39,6 +39,7 @@ extern crate toml_query; extern crate libimagrt; extern crate libimagerror; +extern crate libimagentrylink; extern crate libimagstore; use libimagrt::setup::generate_runtime_setup; @@ -46,6 +47,7 @@ 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; @@ -60,6 +62,7 @@ struct Diagnostic { pub bytecount_content: usize, pub overall_byte_size: usize, pub verified: bool, + pub num_internal_links: usize, } impl<'a> From> for Diagnostic { @@ -82,6 +85,7 @@ impl<'a> From> for Diagnostic { 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), } } } @@ -111,6 +115,7 @@ fn main() { 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; @@ -125,6 +130,8 @@ fn main() { } else { unverified_count += 1; } + + num_internal_links += diag.num_internal_links; } let n = diags.len(); @@ -139,6 +146,7 @@ fn main() { 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); } From 36adac4a165d5205d2545b83f834c2bedd5f3517 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Fri, 13 Oct 2017 16:52:56 +0200 Subject: [PATCH 5/5] Add output about max internal links and max overall byte size --- bin/core/imag-diagnostics/src/main.rs | 37 +++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/bin/core/imag-diagnostics/src/main.rs b/bin/core/imag-diagnostics/src/main.rs index 77aeb023..784d98ef 100644 --- a/bin/core/imag-diagnostics/src/main.rs +++ b/bin/core/imag-diagnostics/src/main.rs @@ -45,6 +45,7 @@ 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::*; @@ -57,6 +58,7 @@ use std::collections::BTreeMap; mod ui; struct Diagnostic { + pub id: StoreId, pub entry_store_version: String, pub header_sections: usize, pub bytecount_content: usize, @@ -69,6 +71,7 @@ impl<'a> From> for Diagnostic { fn from(entry: FileLockEntry<'a>) -> Diagnostic { Diagnostic { + id: entry.get_location().clone(), entry_store_version: entry .get_header() .read("imag.version") @@ -113,14 +116,22 @@ fn main() { 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); @@ -132,6 +143,12 @@ fn main() { } 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(); @@ -146,7 +163,27 @@ fn main() { 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); }