1 // This file contains the library routines for managing the
2 // table_io_waits_by_table table.
3 package events_waits_summary_global_by_event_name
12 "github.com/sjmudd/pstop/lib"
15 // a row from performance_schema.events_waits_summary_global_by_event_name
16 // Note: upper case names to match the performance_schema column names.
17 // This type is _not_ meant to be exported.
18 type events_waits_summary_global_by_event_name_row struct {
23 type events_waits_summary_global_by_event_name_rows []events_waits_summary_global_by_event_name_row
25 // trim off the leading 'wait/synch/mutex/innodb/'
26 func (r *events_waits_summary_global_by_event_name_row) name() string {
28 if r.EVENT_NAME == "Totals" {
30 } else if len(r.EVENT_NAME) >= 24 {
31 n += r.EVENT_NAME[24:]
36 func (r *events_waits_summary_global_by_event_name_row) pretty_name() string {
44 func (r *events_waits_summary_global_by_event_name_row) headings() string {
45 return fmt.Sprintf("%-30s %10s %6s", "Mutex Name", "Latency", "%")
48 // generate a printable result
49 func (r *events_waits_summary_global_by_event_name_row) row_content(totals events_waits_summary_global_by_event_name_row) string {
50 name := r.pretty_name()
51 if r.COUNT_STAR == 0 && name != "Totals" {
55 return fmt.Sprintf("%-30s %10s %6s",
57 lib.FormatTime(r.SUM_TIMER_WAIT),
58 lib.FormatPct(lib.MyDivide(r.SUM_TIMER_WAIT, totals.SUM_TIMER_WAIT)))
61 func (this *events_waits_summary_global_by_event_name_row) add(other events_waits_summary_global_by_event_name_row) {
62 this.SUM_TIMER_WAIT += other.SUM_TIMER_WAIT
63 this.COUNT_STAR += other.COUNT_STAR
66 // subtract the countable values in one row from another
67 func (this *events_waits_summary_global_by_event_name_row) subtract(other events_waits_summary_global_by_event_name_row) {
68 // check for issues here (we have a bug) and log it
69 // - this situation should not happen so there's a logic bug somewhere else
70 if this.SUM_TIMER_WAIT >= other.SUM_TIMER_WAIT {
71 this.SUM_TIMER_WAIT -= other.SUM_TIMER_WAIT
72 this.COUNT_STAR -= other.COUNT_STAR
74 lib.Logger.Println("WARNING: events_waits_summary_global_by_event_name_row.subtract() - subtraction problem! (not subtracting)")
75 lib.Logger.Println("this=", this)
76 lib.Logger.Println("other=", other)
80 func (t events_waits_summary_global_by_event_name_rows) totals() events_waits_summary_global_by_event_name_row {
81 var totals events_waits_summary_global_by_event_name_row
82 totals.EVENT_NAME = "Totals"
91 func select_tiwsbt_rows(dbh *sql.DB) events_waits_summary_global_by_event_name_rows {
92 var t events_waits_summary_global_by_event_name_rows
94 // we collect all information even if it's mainly empty as we may reference it later
95 sql := "SELECT EVENT_NAME, SUM_TIMER_WAIT, COUNT_STAR FROM events_waits_summary_global_by_event_name WHERE SUM_TIMER_WAIT > 0 AND EVENT_NAME LIKE 'wait/synch/mutex/innodb/%'"
97 rows, err := dbh.Query(sql)
104 var r events_waits_summary_global_by_event_name_row
108 &r.COUNT_STAR); err != nil {
111 // we collect all information even if it's mainly empty as we may reference it later
114 if err := rows.Err(); err != nil {
121 func (t events_waits_summary_global_by_event_name_rows) Len() int { return len(t) }
122 func (t events_waits_summary_global_by_event_name_rows) Swap(i, j int) { t[i], t[j] = t[j], t[i] }
124 // sort by value (descending) but also by "name" (ascending) if the values are the same
125 func (t events_waits_summary_global_by_event_name_rows) Less(i, j int) bool {
126 return t[i].SUM_TIMER_WAIT > t[j].SUM_TIMER_WAIT
129 func (t events_waits_summary_global_by_event_name_rows) Sort() {
133 // remove the initial values from those rows where there's a match
134 // - if we find a row we can't match ignore it
135 func (this *events_waits_summary_global_by_event_name_rows) subtract(initial events_waits_summary_global_by_event_name_rows) {
136 initial_by_name := make(map[string]int)
138 // iterate over rows by name
139 for i := range initial {
140 initial_by_name[initial[i].name()] = i
143 for i := range *this {
144 this_name := (*this)[i].name()
145 if _, ok := initial_by_name[this_name]; ok {
146 initial_index := initial_by_name[this_name]
147 (*this)[i].subtract(initial[initial_index])
152 // if the data in t2 is "newer", "has more values" than t then it needs refreshing.
153 // check this by comparing totals.
154 func (t events_waits_summary_global_by_event_name_rows) needs_refresh(t2 events_waits_summary_global_by_event_name_rows) bool {
155 my_totals := t.totals()
156 t2_totals := t2.totals()
158 return my_totals.SUM_TIMER_WAIT > t2_totals.SUM_TIMER_WAIT
161 // describe a whole row
162 func (r events_waits_summary_global_by_event_name_row) String() string {
163 return fmt.Sprintf("%-30s|%10s %10s %10s %10s %10s|%10s %10s|%10s %10s %10s %10s %10s|%10s %10s",
165 lib.FormatTime(r.SUM_TIMER_WAIT),
166 lib.FormatAmount(r.COUNT_STAR))
169 // describe a whole table
170 func (t events_waits_summary_global_by_event_name_rows) String() string {
171 s := make([]string, len(t))
174 s = append(s, t[i].String())
177 return strings.Join(s, "\n")