# This program is copyright 2011 Percona Inc. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED # WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF # MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. # # This program is free software; you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free Software # Foundation, version 2; OR the Perl Artistic License. On UNIX and similar # systems, you can issue `man perlgpl' or `man perlartistic' to read these # licenses. # # You should have received a copy of the GNU General Public License along with # this program; if not, write to the Free Software Foundation, Inc., 59 Temple # Place, Suite 330, Boston, MA 02111-1307 USA. # ########################################################################### # report_formatting package # ########################################################################### # Package: report_formatting # Common report formatting functions for the summary tools. set -u POSIXLY_CORRECT=1 export POSIXLY_CORRECT fuzzy_formula=' rounded = 0; if (fuzzy_var <= 10 ) { rounded = 1; } factor = 1; while ( rounded == 0 ) { if ( fuzzy_var <= 50 * factor ) { fuzzy_var = sprintf("%.0f", fuzzy_var / (5 * factor)) * 5 * factor; rounded = 1; } else if ( fuzzy_var <= 100 * factor) { fuzzy_var = sprintf("%.0f", fuzzy_var / (10 * factor)) * 10 * factor; rounded = 1; } else if ( fuzzy_var <= 250 * factor) { fuzzy_var = sprintf("%.0f", fuzzy_var / (25 * factor)) * 25 * factor; rounded = 1; } factor = factor * 10; }' # Does fuzzy rounding: rounds to nearest interval, but the interval gets larger # as the number gets larger. This is to make things easier to diff. fuzz () { awk -v fuzzy_var="$1" "BEGIN { ${fuzzy_formula} print fuzzy_var;}" } # Fuzzy computes the percent that $1 is of $2 fuzzy_pct () { local pct="$(awk -v one="$1" -v two="$2" 'BEGIN{ if (two > 0) { printf "%d", one/two*100; } else {print 0} }')"; echo "$(fuzz "${pct}")%" } # Prints a section header. All spaces in the string passed in are replaced # with #'s and all underscores with spaces. section () { local str="$1" awk -v var="${str} _" 'BEGIN { line = sprintf("# %-60s", var); i = index(line, "_"); x = substr(line, i); gsub(/[_ \t]/, "#", x); printf("%s%s\n", substr(line, 1, i-1), x); }' } NAME_VAL_LEN=12 name_val() { # We use $NAME_VAL_LEN here because the two summary tools, as well as # the tests, use different widths. printf "%+*s | %s\n" "${NAME_VAL_LEN}" "$1" "$2" } # Sub: shorten # Shorten a value in bytes to another representation. shorten() { local num="$1" local prec="${2:-2}" local div="${3:-1024}" # By default Mebibytes (MiB), Gigibytes (GiB), etc. are used because # that's what MySQL uses. This may create odd output for values like # 1500M * 2 (bug 937793) because the base unit is MiB but the code # see 1,572,864,000 * 2 = 3,145,728,000 which is > 1 GiB so it uses # GiB as the unit, resulting in 2.9G instead of 3.0G that the user # might expect to see. There's no easy way to determine that # 3,145,728,000 was actually a multiple of MiB and not some weird GiB # value to begin with like 3.145G. The Perl lib Transformers::shorten() # uses MiB, GiB, etc. too. echo "$num" | awk -v prec="$prec" -v div="$div" ' { num = $1; unit = num >= 1125899906842624 ? "P" \ : num >= 1099511627776 ? "T" \ : num >= 1073741824 ? "G" \ : num >= 1048576 ? "M" \ : num >= 1024 ? "k" \ : ""; while ( num >= div ) { num /= div; } printf "%.*f%s", prec, num, unit; } ' } group_concat() { sed -e '{H; $!d;}' -e 'x' -e 's/\n[[:space:]]*\([[:digit:]]*\)[[:space:]]*/, \1x/g' -e 's/[[:space:]][[:space:]]*/ /g' -e 's/, //' "${1}" } # ########################################################################### # End report_formatting package # ###########################################################################