saving a bit
[pstop.git] / performance_schema / file_summary_by_instance / file_summary_by_instance_row.go
index 0f36edd..d122807 100644 (file)
@@ -8,6 +8,8 @@ import (
        "log"
        "regexp"
        "sort"
+       //      "strconv"
+       "time"
 
        "github.com/sjmudd/pstop/lib"
 )
@@ -43,21 +45,51 @@ CREATE TABLE `file_summary_by_instance` (
 1 row in set (0.00 sec)
 */
 
+//     foo/../bar --> foo/bar   perl: $new =~ s{[^/]+/\.\./}{/};
+//     /./        --> /         perl: $new =~ s{/\./}{};
+//     //         --> /         perl: $new =~ s{//}{/};
+const (
+       re_one_or_the_other    = `/(\.)?/`
+       re_slash_dot_dot_slash = `[^/]+/\.\./`
+       re_auto_cnf            = `/auto\.cnf$`
+       re_binlog              = `/binlog\.(\d{6}|index)$`
+       re_charset             = `/share/charsets/Index\.xml$`
+       re_db_opt              = `/db\.opt$`
+       re_encoded             = `@(\d{4})` // FIXME - add me to catch @0024 --> $ for example
+       re_error_msg           = `/share/[^/]+/errmsg\.sys$`
+       re_ibdata              = `/ibdata\d+$`
+       re_part_table          = `(.+)#P#p(\d+|MAX)`
+       re_pid_file            = `/[^/]+\.pid$`
+       re_redo_log            = `/ib_logfile\d+$`
+       re_relative_path       = `^\.\./`
+       re_slowlog             = `/slowlog$`
+       re_table_file          = `/([^/]+)/([^/]+)\.(frm|ibd|MYD|MYI|CSM|CSV|par)$`
+       re_temp_table          = `#sql-[0-9_]+`
+)
+
+var (
+       v_one_or_the_other    *regexp.Regexp = regexp.MustCompile(re_one_or_the_other)
+       v_slash_dot_dot_slash *regexp.Regexp = regexp.MustCompile(re_slash_dot_dot_slash)
+       v_table_file          *regexp.Regexp = regexp.MustCompile(re_table_file)
+       v_temp_table          *regexp.Regexp = regexp.MustCompile(re_temp_table)
+       v_part_table          *regexp.Regexp = regexp.MustCompile(re_part_table)
+)
+
 type file_summary_by_instance_row struct {
        FILE_NAME string
 
-       COUNT_STAR  int
-       COUNT_READ  int
-       COUNT_WRITE int
-       COUNT_MISC  int
+       COUNT_STAR  uint64
+       COUNT_READ  uint64
+       COUNT_WRITE uint64
+       COUNT_MISC  uint64
 
-       SUM_TIMER_WAIT  int
-       SUM_TIMER_READ  int
-       SUM_TIMER_WRITE int
-       SUM_TIMER_MISC  int
+       SUM_TIMER_WAIT  uint64
+       SUM_TIMER_READ  uint64
+       SUM_TIMER_WRITE uint64
+       SUM_TIMER_MISC  uint64
 
-       SUM_NUMBER_OF_BYTES_READ  int
-       SUM_NUMBER_OF_BYTES_WRITE int
+       SUM_NUMBER_OF_BYTES_READ  uint64
+       SUM_NUMBER_OF_BYTES_WRITE uint64
 }
 
 // represents a table or set of rows
@@ -164,23 +196,11 @@ func (t file_summary_by_instance_rows) totals() file_summary_by_instance_row {
 
 // clean up the given path reducing redundant stuff and return the clean path
 func cleanup_path(path string) string {
-       //     foo/../bar --> bar       perl: $new =~ s{[^/]+/\.\./}{/};
-       //     foo/./bar  --> foo/bar   perl: $new =~ s{/\./}{};
-       //     //         --> /         perl: $new =~ s{//}{/};
-       const (
-               double_slash_re        = `//`
-               slash_dot_slash_re     = `/\./`
-               slash_dot_dot_slash_re = `[^/]+/\.\./`
-       )
+
        for {
                orig_path := path
-
-               r := regexp.MustCompile(double_slash_re)
-               path = r.ReplaceAllString(path, "")
-               r = regexp.MustCompile(slash_dot_slash_re)
-               path = r.ReplaceAllString(path, "")
-               r = regexp.MustCompile(slash_dot_dot_slash_re)
-               path = r.ReplaceAllString(path, "")
+               path = v_one_or_the_other.ReplaceAllString(path, "/")
+               path = v_slash_dot_dot_slash.ReplaceAllString(path, "/")
                if orig_path == path { // no change so give up
                        break
                }
@@ -192,59 +212,48 @@ func cleanup_path(path string) string {
 // From the original FILE_NAME we want to generate a simpler name to use.
 // This simpler name may also merge several different filenames into one.
 func (t file_summary_by_instance_row) simple_name(global_variables map[string]string) string {
-       const (
-               auto_cnf_re  = `/auto\.cnf$`
-               binlog_re    = `/binlog\.(\d{6}|index)$`
-               charset_re   = `/share/charsets/Index\.xml$`
-               db_opt_re    = `/db\.opt$`
-               error_msg_re = `/share/[^/]+/errmsg\.sys$`
-               ibdata_re    = `/ibdata\d+$`
-               redo_log_re  = `/ib_logfile\d+$`
-               pid_file_re  = `/[^/]+\.pid$`
-               //              relay_log_re  = `/mysql-relay-bin.(\d{6}|index)$`
-               relative_path_re = `^\.\./`
-               current_dir_re   = `^\./`
-               slowlog_re       = `/slowlog$`
-               table_file_re    = `/([^/]+)/([^/]+)\.(frm|ibd|MYD|MYI|CSM|CSV|par)$`
-               temp_table_re    = `#sql-[0-9_]+`
-               part_table_re    = `(.+)#P#p\d+`
-       )
 
        path := t.FILE_NAME
 
+       // FIXME and make this work.
+       //      re4 := regexp.MustCompile(re_encoded)
+       //      if m4 := re4.FindStringSubmatch(path); m4 != nil {
+       //              if value, err := strconv.ParseInt(m4[1], 16, 16); err != nil {
+       //                      // missing replace @.... with char(value) in path
+       //
+       //              }
+       //      }
+
        // this should probably be ordered from most expected regexp to least
-       re := regexp.MustCompile(table_file_re)
-       if m1 := re.FindStringSubmatch(path); m1 != nil {
+       if m1 := v_table_file.FindStringSubmatch(path); m1 != nil {
                // we may match temporary tables so check for them
-               re2 := regexp.MustCompile(temp_table_re)
-               if m2 := re2.FindStringSubmatch(m1[2]); m2 != nil {
+               if m2 := v_temp_table.FindStringSubmatch(m1[2]); m2 != nil {
                        return "<temp_table>"
                }
 
                // we may match partitioned tables so check for them
-               re3 := regexp.MustCompile(part_table_re)
-               if m3 := re3.FindStringSubmatch(m1[2]); m3 != nil {
+               if m3 := v_part_table.FindStringSubmatch(m1[2]); m3 != nil {
                        return m1[1] + "." + m3[1] // <schema>.<table> (less partition info)
                }
 
                return m1[1] + "." + m1[2] // <schema>.<table>
        }
-       if regexp.MustCompile(ibdata_re).MatchString(path) == true {
+       if regexp.MustCompile(re_ibdata).MatchString(path) == true {
                return "<ibdata>"
        }
-       if regexp.MustCompile(redo_log_re).MatchString(path) == true {
+       if regexp.MustCompile(re_redo_log).MatchString(path) == true {
                return "<redo_log>"
        }
-       if regexp.MustCompile(binlog_re).MatchString(path) == true {
+       if regexp.MustCompile(re_binlog).MatchString(path) == true {
                return "<binlog>"
        }
-       if regexp.MustCompile(db_opt_re).MatchString(path) == true {
+       if regexp.MustCompile(re_db_opt).MatchString(path) == true {
                return "<db_opt>"
        }
-       if regexp.MustCompile(slowlog_re).MatchString(path) == true {
+       if regexp.MustCompile(re_slowlog).MatchString(path) == true {
                return "<slow_log>"
        }
-       if regexp.MustCompile(auto_cnf_re).MatchString(path) == true {
+       if regexp.MustCompile(re_auto_cnf).MatchString(path) == true {
                return "<auto_cnf>"
        }
        // relay logs are a bit complicated. If a full path then easy to
@@ -261,13 +270,13 @@ func (t file_summary_by_instance_row) simple_name(global_variables map[string]st
                        return "<relay_log>"
                }
        }
-       if regexp.MustCompile(pid_file_re).MatchString(path) == true {
+       if regexp.MustCompile(re_pid_file).MatchString(path) == true {
                return "<pid_file>"
        }
-       if regexp.MustCompile(error_msg_re).MatchString(path) == true {
+       if regexp.MustCompile(re_error_msg).MatchString(path) == true {
                return "<errmsg>"
        }
-       if regexp.MustCompile(charset_re).MatchString(path) == true {
+       if regexp.MustCompile(re_charset).MatchString(path) == true {
                return "<charset>"
        }
        return path
@@ -276,6 +285,7 @@ func (t file_summary_by_instance_row) simple_name(global_variables map[string]st
 // Convert the imported "table" to a merged one with merged data.
 // Combine all entries with the same "FILE_NAME" by adding their values.
 func merge_by_table_name(orig file_summary_by_instance_rows, global_variables map[string]string) file_summary_by_instance_rows {
+       start := time.Now()
        t := make(file_summary_by_instance_rows, 0, len(orig))
 
        m := make(map[string]file_summary_by_instance_row)
@@ -305,6 +315,7 @@ func merge_by_table_name(orig file_summary_by_instance_rows, global_variables ma
                t = append(t, row)
        }
 
+       lib.Logger.Println("merge_by_table_name() took:", time.Duration(time.Since(start)).String())
        return t
 }
 
@@ -314,6 +325,7 @@ func merge_by_table_name(orig file_summary_by_instance_rows, global_variables ma
 // - change FILE_NAME into a more descriptive value.
 func select_fsbi_rows(dbh *sql.DB) file_summary_by_instance_rows {
        var t file_summary_by_instance_rows
+       start := time.Now()
 
        sql := "SELECT FILE_NAME, COUNT_STAR, SUM_TIMER_WAIT, COUNT_READ, SUM_TIMER_READ, SUM_NUMBER_OF_BYTES_READ, COUNT_WRITE, SUM_TIMER_WRITE, SUM_NUMBER_OF_BYTES_WRITE, COUNT_MISC, SUM_TIMER_MISC FROM file_summary_by_instance"
 
@@ -334,6 +346,7 @@ func select_fsbi_rows(dbh *sql.DB) file_summary_by_instance_rows {
        if err := rows.Err(); err != nil {
                log.Fatal(err)
        }
+       lib.Logger.Println("select_fsbi_rows() took:", time.Duration(time.Since(start)).String())
 
        return t
 }