1 /* Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
2 
3   This program is free software; you can redistribute it and/or modify
4   it under the terms of the GNU General Public License, version 2.0,
5   as published by the Free Software Foundation.
6 
7   This program is also distributed with certain software (including
8   but not limited to OpenSSL) that is licensed under separate terms,
9   as designated in a particular file or component or in included license
10   documentation.  The authors of MySQL hereby grant you an additional
11   permission to link the program and your derivative works with the
12   separately licensed software that they have included with MySQL.
13 
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License, version 2.0, for more details.
18 
19   You should have received a copy of the GNU General Public License
20   along with this program; if not, write to the Free Software Foundation,
21   51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
22 
23 #ifndef PFS_STAT_H
24 #define PFS_STAT_H
25 
26 #include "sql_const.h"
27 /* memcpy */
28 #include "string.h"
29 
30 /**
31   @file storage/perfschema/pfs_stat.h
32   Statistics (declarations).
33 */
34 
35 /**
36   @addtogroup Performance_schema_buffers
37   @{
38 */
39 
40 /** Single statistic. */
41 struct PFS_single_stat
42 {
43   /** Count of values. */
44   ulonglong m_count;
45   /** Sum of values. */
46   ulonglong m_sum;
47   /** Minimum value. */
48   ulonglong m_min;
49   /** Maximum value. */
50   ulonglong m_max;
51 
PFS_single_statPFS_single_stat52   PFS_single_stat()
53   {
54     m_count= 0;
55     m_sum= 0;
56     m_min= ULONGLONG_MAX;
57     m_max= 0;
58   }
59 
resetPFS_single_stat60   inline void reset(void)
61   {
62     m_count= 0;
63     m_sum= 0;
64     m_min= ULONGLONG_MAX;
65     m_max= 0;
66   }
67 
has_timed_statsPFS_single_stat68   inline bool has_timed_stats() const
69   {
70     return (m_min <= m_max);
71   }
72 
aggregatePFS_single_stat73   inline void aggregate(const PFS_single_stat *stat)
74   {
75     m_count+= stat->m_count;
76     m_sum+= stat->m_sum;
77     if (unlikely(m_min > stat->m_min))
78       m_min= stat->m_min;
79     if (unlikely(m_max < stat->m_max))
80       m_max= stat->m_max;
81   }
82 
aggregate_countedPFS_single_stat83   inline void aggregate_counted()
84   {
85     m_count++;
86   }
87 
aggregate_countedPFS_single_stat88   inline void aggregate_counted(ulonglong count)
89   {
90     m_count+= count;
91   }
92 
aggregate_valuePFS_single_stat93   inline void aggregate_value(ulonglong value)
94   {
95     m_count++;
96     m_sum+= value;
97     if (unlikely(m_min > value))
98       m_min= value;
99     if (unlikely(m_max < value))
100       m_max= value;
101   }
102 };
103 
104 /** Combined statistic. */
105 struct PFS_byte_stat : public PFS_single_stat
106 {
107   /** Byte count statistics */
108   ulonglong m_bytes;
109 
110   /* Aggregate wait stats, event count and byte count */
aggregatePFS_byte_stat111   inline void aggregate(const PFS_byte_stat *stat)
112   {
113     PFS_single_stat::aggregate(stat);
114     m_bytes+= stat->m_bytes;
115   }
116 
117   /* Aggregate individual wait time, event count and byte count */
aggregatePFS_byte_stat118   inline void aggregate(ulonglong wait, ulonglong bytes)
119   {
120     aggregate_value(wait);
121     m_bytes+= bytes;
122   }
123 
124   /* Aggregate wait stats and event count */
aggregate_waitsPFS_byte_stat125   inline void aggregate_waits(const PFS_byte_stat *stat)
126   {
127     PFS_single_stat::aggregate(stat);
128   }
129 
130   /* Aggregate event count and byte count */
aggregate_countedPFS_byte_stat131   inline void aggregate_counted()
132   {
133     PFS_single_stat::aggregate_counted();
134   }
135 
136   /* Aggregate event count and byte count */
aggregate_countedPFS_byte_stat137   inline void aggregate_counted(ulonglong bytes)
138   {
139     PFS_single_stat::aggregate_counted();
140     m_bytes+= bytes;
141   }
142 
PFS_byte_statPFS_byte_stat143   PFS_byte_stat()
144   {
145     reset();
146   }
147 
resetPFS_byte_stat148   inline void reset(void)
149   {
150     PFS_single_stat::reset();
151     m_bytes= 0;
152   }
153 };
154 
155 /** Statistics for mutex usage. */
156 struct PFS_mutex_stat
157 {
158   /** Wait statistics. */
159   PFS_single_stat m_wait_stat;
160   /**
161     Lock statistics.
162     This statistic is not exposed in user visible tables yet.
163   */
164   PFS_single_stat m_lock_stat;
165 
aggregatePFS_mutex_stat166   inline void aggregate(const PFS_mutex_stat *stat)
167   {
168     m_wait_stat.aggregate(&stat->m_wait_stat);
169     m_lock_stat.aggregate(&stat->m_lock_stat);
170   }
171 
resetPFS_mutex_stat172   inline void reset(void)
173   {
174     m_wait_stat.reset();
175     m_lock_stat.reset();
176   }
177 };
178 
179 /** Statistics for rwlock usage. */
180 struct PFS_rwlock_stat
181 {
182   /** Wait statistics. */
183   PFS_single_stat m_wait_stat;
184   /**
185     RWLock read lock usage statistics.
186     This statistic is not exposed in user visible tables yet.
187   */
188   PFS_single_stat m_read_lock_stat;
189   /**
190     RWLock write lock usage statistics.
191     This statistic is not exposed in user visible tables yet.
192   */
193   PFS_single_stat m_write_lock_stat;
194 
aggregatePFS_rwlock_stat195   inline void aggregate(const PFS_rwlock_stat *stat)
196   {
197     m_wait_stat.aggregate(&stat->m_wait_stat);
198     m_read_lock_stat.aggregate(&stat->m_read_lock_stat);
199     m_write_lock_stat.aggregate(&stat->m_write_lock_stat);
200   }
201 
resetPFS_rwlock_stat202   inline void reset(void)
203   {
204     m_wait_stat.reset();
205     m_read_lock_stat.reset();
206     m_write_lock_stat.reset();
207   }
208 };
209 
210 /** Statistics for COND usage. */
211 struct PFS_cond_stat
212 {
213   /** Wait statistics. */
214   PFS_single_stat m_wait_stat;
215   /**
216     Number of times a condition was signalled.
217     This statistic is not exposed in user visible tables yet.
218   */
219   ulonglong m_signal_count;
220   /**
221     Number of times a condition was broadcast.
222     This statistic is not exposed in user visible tables yet.
223   */
224   ulonglong m_broadcast_count;
225 
aggregatePFS_cond_stat226   inline void aggregate(const PFS_cond_stat *stat)
227   {
228     m_wait_stat.aggregate(&stat->m_wait_stat);
229     m_signal_count+= stat->m_signal_count;
230     m_broadcast_count+= stat->m_broadcast_count;
231   }
232 
resetPFS_cond_stat233   inline void reset(void)
234   {
235     m_wait_stat.reset();
236     m_signal_count= 0;
237     m_broadcast_count= 0;
238   }
239 };
240 
241 /** Statistics for FILE IO. Used for both waits and byte counts. */
242 struct PFS_file_io_stat
243 {
244   /** READ statistics */
245   PFS_byte_stat m_read;
246   /** WRITE statistics */
247   PFS_byte_stat m_write;
248   /** Miscelleanous statistics */
249   PFS_byte_stat m_misc;
250 
resetPFS_file_io_stat251   inline void reset(void)
252   {
253     m_read.reset();
254     m_write.reset();
255     m_misc.reset();
256   }
257 
aggregatePFS_file_io_stat258   inline void aggregate(const PFS_file_io_stat *stat)
259   {
260     m_read.aggregate(&stat->m_read);
261     m_write.aggregate(&stat->m_write);
262     m_misc.aggregate(&stat->m_misc);
263   }
264 
265   /* Sum waits and byte counts */
sumPFS_file_io_stat266   inline void sum(PFS_byte_stat *stat)
267   {
268     stat->aggregate(&m_read);
269     stat->aggregate(&m_write);
270     stat->aggregate(&m_misc);
271   }
272 
273   /* Sum waits only */
sum_waitsPFS_file_io_stat274   inline void sum_waits(PFS_single_stat *stat)
275   {
276     stat->aggregate(&m_read);
277     stat->aggregate(&m_write);
278     stat->aggregate(&m_misc);
279   }
280 };
281 
282 /** Statistics for FILE usage. */
283 struct PFS_file_stat
284 {
285   /** Number of current open handles. */
286   ulong m_open_count;
287   /** File IO statistics. */
288   PFS_file_io_stat m_io_stat;
289 
aggregatePFS_file_stat290   inline void aggregate(const PFS_file_stat *stat)
291   {
292     m_io_stat.aggregate(&stat->m_io_stat);
293   }
294 
295   /** Reset file statistics. */
resetPFS_file_stat296   inline void reset(void)
297   {
298     m_io_stat.reset();
299   }
300 };
301 
302 /** Statistics for stage usage. */
303 struct PFS_stage_stat
304 {
305   PFS_single_stat m_timer1_stat;
306 
resetPFS_stage_stat307   inline void reset(void)
308   { m_timer1_stat.reset(); }
309 
aggregate_countedPFS_stage_stat310   inline void aggregate_counted()
311   { m_timer1_stat.aggregate_counted(); }
312 
aggregate_valuePFS_stage_stat313   inline void aggregate_value(ulonglong value)
314   { m_timer1_stat.aggregate_value(value); }
315 
aggregatePFS_stage_stat316   inline void aggregate(PFS_stage_stat *stat)
317   { m_timer1_stat.aggregate(& stat->m_timer1_stat); }
318 };
319 
320 /** Statistics for statement usage. */
321 struct PFS_statement_stat
322 {
323   PFS_single_stat m_timer1_stat;
324   ulonglong m_error_count;
325   ulonglong m_warning_count;
326   ulonglong m_rows_affected;
327   ulonglong m_lock_time;
328   ulonglong m_rows_sent;
329   ulonglong m_rows_examined;
330   ulonglong m_created_tmp_disk_tables;
331   ulonglong m_created_tmp_tables;
332   ulonglong m_select_full_join;
333   ulonglong m_select_full_range_join;
334   ulonglong m_select_range;
335   ulonglong m_select_range_check;
336   ulonglong m_select_scan;
337   ulonglong m_sort_merge_passes;
338   ulonglong m_sort_range;
339   ulonglong m_sort_rows;
340   ulonglong m_sort_scan;
341   ulonglong m_no_index_used;
342   ulonglong m_no_good_index_used;
343 
PFS_statement_statPFS_statement_stat344   PFS_statement_stat()
345   {
346     m_error_count= 0;
347     m_warning_count= 0;
348     m_rows_affected= 0;
349     m_lock_time= 0;
350     m_rows_sent= 0;
351     m_rows_examined= 0;
352     m_created_tmp_disk_tables= 0;
353     m_created_tmp_tables= 0;
354     m_select_full_join= 0;
355     m_select_full_range_join= 0;
356     m_select_range= 0;
357     m_select_range_check= 0;
358     m_select_scan= 0;
359     m_sort_merge_passes= 0;
360     m_sort_range= 0;
361     m_sort_rows= 0;
362     m_sort_scan= 0;
363     m_no_index_used= 0;
364     m_no_good_index_used= 0;
365   }
366 
resetPFS_statement_stat367   inline void reset(void)
368   {
369     m_timer1_stat.reset();
370     m_error_count= 0;
371     m_warning_count= 0;
372     m_rows_affected= 0;
373     m_lock_time= 0;
374     m_rows_sent= 0;
375     m_rows_examined= 0;
376     m_created_tmp_disk_tables= 0;
377     m_created_tmp_tables= 0;
378     m_select_full_join= 0;
379     m_select_full_range_join= 0;
380     m_select_range= 0;
381     m_select_range_check= 0;
382     m_select_scan= 0;
383     m_sort_merge_passes= 0;
384     m_sort_range= 0;
385     m_sort_rows= 0;
386     m_sort_scan= 0;
387     m_no_index_used= 0;
388     m_no_good_index_used= 0;
389   }
390 
aggregate_countedPFS_statement_stat391   inline void aggregate_counted()
392   { m_timer1_stat.aggregate_counted(); }
393 
aggregate_valuePFS_statement_stat394   inline void aggregate_value(ulonglong value)
395   { m_timer1_stat.aggregate_value(value); }
396 
aggregatePFS_statement_stat397   inline void aggregate(PFS_statement_stat *stat)
398   {
399     m_timer1_stat.aggregate(& stat->m_timer1_stat);
400 
401     m_error_count+= stat->m_error_count;
402     m_warning_count+= stat->m_warning_count;
403     m_rows_affected+= stat->m_rows_affected;
404     m_lock_time+= stat->m_lock_time;
405     m_rows_sent+= stat->m_rows_sent;
406     m_rows_examined+= stat->m_rows_examined;
407     m_created_tmp_disk_tables+= stat->m_created_tmp_disk_tables;
408     m_created_tmp_tables+= stat->m_created_tmp_tables;
409     m_select_full_join+= stat->m_select_full_join;
410     m_select_full_range_join+= stat->m_select_full_range_join;
411     m_select_range+= stat->m_select_range;
412     m_select_range_check+= stat->m_select_range_check;
413     m_select_scan+= stat->m_select_scan;
414     m_sort_merge_passes+= stat->m_sort_merge_passes;
415     m_sort_range+= stat->m_sort_range;
416     m_sort_rows+= stat->m_sort_rows;
417     m_sort_scan+= stat->m_sort_scan;
418     m_no_index_used+= stat->m_no_index_used;
419     m_no_good_index_used+= stat->m_no_good_index_used;
420   }
421 };
422 
423 /** Single table io statistic. */
424 struct PFS_table_io_stat
425 {
426   bool m_has_data;
427   /** FETCH statistics */
428   PFS_single_stat m_fetch;
429   /** INSERT statistics */
430   PFS_single_stat m_insert;
431   /** UPDATE statistics */
432   PFS_single_stat m_update;
433   /** DELETE statistics */
434   PFS_single_stat m_delete;
435 
PFS_table_io_statPFS_table_io_stat436   PFS_table_io_stat()
437   {
438     m_has_data= false;
439   }
440 
resetPFS_table_io_stat441   inline void reset(void)
442   {
443     m_has_data= false;
444     m_fetch.reset();
445     m_insert.reset();
446     m_update.reset();
447     m_delete.reset();
448   }
449 
aggregatePFS_table_io_stat450   inline void aggregate(const PFS_table_io_stat *stat)
451   {
452     if (stat->m_has_data)
453     {
454       m_has_data= true;
455       m_fetch.aggregate(&stat->m_fetch);
456       m_insert.aggregate(&stat->m_insert);
457       m_update.aggregate(&stat->m_update);
458       m_delete.aggregate(&stat->m_delete);
459     }
460   }
461 
sumPFS_table_io_stat462   inline void sum(PFS_single_stat *result)
463   {
464     if (m_has_data)
465     {
466       result->aggregate(& m_fetch);
467       result->aggregate(& m_insert);
468       result->aggregate(& m_update);
469       result->aggregate(& m_delete);
470     }
471   }
472 };
473 
474 enum PFS_TL_LOCK_TYPE
475 {
476   /* Locks from enum thr_lock */
477   PFS_TL_READ= 0,
478   PFS_TL_READ_WITH_SHARED_LOCKS= 1,
479   PFS_TL_READ_HIGH_PRIORITY= 2,
480   PFS_TL_READ_NO_INSERT= 3,
481   PFS_TL_WRITE_ALLOW_WRITE= 4,
482   PFS_TL_WRITE_CONCURRENT_INSERT= 5,
483   PFS_TL_WRITE_DELAYED= 6,
484   PFS_TL_WRITE_LOW_PRIORITY= 7,
485   PFS_TL_WRITE= 8,
486 
487   /* Locks for handler::ha_external_lock() */
488   PFS_TL_READ_EXTERNAL= 9,
489   PFS_TL_WRITE_EXTERNAL= 10
490 };
491 
492 #define COUNT_PFS_TL_LOCK_TYPE 11
493 
494 /** Statistics for table locks. */
495 struct PFS_table_lock_stat
496 {
497   PFS_single_stat m_stat[COUNT_PFS_TL_LOCK_TYPE];
498 
resetPFS_table_lock_stat499   inline void reset(void)
500   {
501     PFS_single_stat *pfs= & m_stat[0];
502     PFS_single_stat *pfs_last= & m_stat[COUNT_PFS_TL_LOCK_TYPE];
503     for ( ; pfs < pfs_last ; pfs++)
504       pfs->reset();
505   }
506 
aggregatePFS_table_lock_stat507   inline void aggregate(const PFS_table_lock_stat *stat)
508   {
509     PFS_single_stat *pfs= & m_stat[0];
510     PFS_single_stat *pfs_last= & m_stat[COUNT_PFS_TL_LOCK_TYPE];
511     const PFS_single_stat *pfs_from= & stat->m_stat[0];
512     for ( ; pfs < pfs_last ; pfs++, pfs_from++)
513       pfs->aggregate(pfs_from);
514   }
515 
sumPFS_table_lock_stat516   inline void sum(PFS_single_stat *result)
517   {
518     PFS_single_stat *pfs= & m_stat[0];
519     PFS_single_stat *pfs_last= & m_stat[COUNT_PFS_TL_LOCK_TYPE];
520     for ( ; pfs < pfs_last ; pfs++)
521       result->aggregate(pfs);
522   }
523 };
524 
525 /** Statistics for TABLE usage. */
526 struct PFS_table_stat
527 {
528   /**
529     Statistics, per index.
530     Each index stat is in [0, MAX_INDEXES-1],
531     stats when using no index are in [MAX_INDEXES].
532   */
533   PFS_table_io_stat m_index_stat[MAX_INDEXES + 1];
534 
535   /**
536     Statistics, per lock type.
537   */
538   PFS_table_lock_stat m_lock_stat;
539 
540   /** Reset table io statistic. */
reset_ioPFS_table_stat541   inline void reset_io(void)
542   {
543     PFS_table_io_stat *stat= & m_index_stat[0];
544     PFS_table_io_stat *stat_last= & m_index_stat[MAX_INDEXES + 1];
545     for ( ; stat < stat_last ; stat++)
546       stat->reset();
547   }
548 
549   /** Reset table lock statistic. */
reset_lockPFS_table_stat550   inline void reset_lock(void)
551   {
552     m_lock_stat.reset();
553   }
554 
555   /** Reset table statistic. */
resetPFS_table_stat556   inline void reset(void)
557   {
558     reset_io();
559     reset_lock();
560   }
561 
fast_reset_ioPFS_table_stat562   inline void fast_reset_io(void)
563   {
564     memcpy(& m_index_stat, & g_reset_template.m_index_stat, sizeof(m_index_stat));
565   }
566 
fast_reset_lockPFS_table_stat567   inline void fast_reset_lock(void)
568   {
569     memcpy(& m_lock_stat, & g_reset_template.m_lock_stat, sizeof(m_lock_stat));
570   }
571 
fast_resetPFS_table_stat572   inline void fast_reset(void)
573   {
574     memcpy(this, & g_reset_template, sizeof(*this));
575   }
576 
aggregate_ioPFS_table_stat577   inline void aggregate_io(const PFS_table_stat *stat, uint key_count)
578   {
579     PFS_table_io_stat *to_stat;
580     PFS_table_io_stat *to_stat_last;
581     const PFS_table_io_stat *from_stat;
582 
583     DBUG_ASSERT(key_count <= MAX_INDEXES);
584 
585     /* Aggregate stats for each index, if any */
586     to_stat= & m_index_stat[0];
587     to_stat_last= to_stat + key_count;
588     from_stat= & stat->m_index_stat[0];
589     for ( ; to_stat < to_stat_last ; from_stat++, to_stat++)
590       to_stat->aggregate(from_stat);
591 
592     /* Aggregate stats for the table */
593     to_stat= & m_index_stat[MAX_INDEXES];
594     from_stat= & stat->m_index_stat[MAX_INDEXES];
595     to_stat->aggregate(from_stat);
596   }
597 
aggregate_lockPFS_table_stat598   inline void aggregate_lock(const PFS_table_stat *stat)
599   {
600     m_lock_stat.aggregate(& stat->m_lock_stat);
601   }
602 
aggregatePFS_table_stat603   inline void aggregate(const PFS_table_stat *stat, uint key_count)
604   {
605     aggregate_io(stat, key_count);
606     aggregate_lock(stat);
607   }
608 
sum_ioPFS_table_stat609   inline void sum_io(PFS_single_stat *result, uint key_count)
610   {
611     PFS_table_io_stat *stat;
612     PFS_table_io_stat *stat_last;
613 
614     DBUG_ASSERT(key_count <= MAX_INDEXES);
615 
616     /* Sum stats for each index, if any */
617     stat= & m_index_stat[0];
618     stat_last= stat + key_count;
619     for ( ; stat < stat_last ; stat++)
620       stat->sum(result);
621 
622     /* Sum stats for the table */
623     m_index_stat[MAX_INDEXES].sum(result);
624   }
625 
sum_lockPFS_table_stat626   inline void sum_lock(PFS_single_stat *result)
627   {
628     m_lock_stat.sum(result);
629   }
630 
sumPFS_table_stat631   inline void sum(PFS_single_stat *result, uint key_count)
632   {
633     sum_io(result, key_count);
634     sum_lock(result);
635   }
636 
637   static struct PFS_table_stat g_reset_template;
638 };
639 
640 /** Statistics for SOCKET IO. Used for both waits and byte counts. */
641 struct PFS_socket_io_stat
642 {
643   /** READ statistics */
644   PFS_byte_stat m_read;
645   /** WRITE statistics */
646   PFS_byte_stat m_write;
647   /** Miscelleanous statistics */
648   PFS_byte_stat m_misc;
649 
resetPFS_socket_io_stat650   inline void reset(void)
651   {
652     m_read.reset();
653     m_write.reset();
654     m_misc.reset();
655   }
656 
aggregatePFS_socket_io_stat657   inline void aggregate(const PFS_socket_io_stat *stat)
658   {
659     m_read.aggregate(&stat->m_read);
660     m_write.aggregate(&stat->m_write);
661     m_misc.aggregate(&stat->m_misc);
662   }
663 
664   /* Sum waits and byte counts */
sumPFS_socket_io_stat665   inline void sum(PFS_byte_stat *stat)
666   {
667     stat->aggregate(&m_read);
668     stat->aggregate(&m_write);
669     stat->aggregate(&m_misc);
670   }
671 
672   /* Sum waits only */
sum_waitsPFS_socket_io_stat673   inline void sum_waits(PFS_single_stat *stat)
674   {
675     stat->aggregate(&m_read);
676     stat->aggregate(&m_write);
677     stat->aggregate(&m_misc);
678   }
679 };
680 
681 /** Statistics for SOCKET usage. */
682 struct PFS_socket_stat
683 {
684   /** Socket timing and byte count statistics per operation */
685   PFS_socket_io_stat m_io_stat;
686 
687   /** Reset socket statistics. */
resetPFS_socket_stat688   inline void reset(void)
689   {
690     m_io_stat.reset();
691   }
692 };
693 
694 struct PFS_connection_stat
695 {
PFS_connection_statPFS_connection_stat696   PFS_connection_stat()
697   : m_current_connections(0),
698     m_total_connections(0)
699   {}
700 
701   ulonglong m_current_connections;
702   ulonglong m_total_connections;
703 
aggregate_activePFS_connection_stat704   inline void aggregate_active(ulonglong active)
705   {
706     m_current_connections+= active;
707     m_total_connections+= active;
708   }
709 
aggregate_disconnectedPFS_connection_stat710   inline void aggregate_disconnected(ulonglong disconnected)
711   {
712     m_total_connections+= disconnected;
713   }
714 };
715 
716 /** @} */
717 #endif
718 
719