1 /* Copyright (c) 2010, 2012, 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
21   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335  USA */
22 
23 /**
24   @file storage/perfschema/table_os_global_by_type.cc
25   Table OBJECTS_SUMMARY_GLOBAL_BY_TYPE (implementation).
26 */
27 
28 #include "my_global.h"
29 #include "my_pthread.h"
30 #include "pfs_instr_class.h"
31 #include "pfs_column_types.h"
32 #include "pfs_column_values.h"
33 #include "table_os_global_by_type.h"
34 #include "pfs_global.h"
35 
36 THR_LOCK table_os_global_by_type::m_table_lock;
37 
38 PFS_engine_table_share
39 table_os_global_by_type::m_share=
40 {
41   { C_STRING_WITH_LEN("objects_summary_global_by_type") },
42   &pfs_truncatable_acl,
43   table_os_global_by_type::create,
44   NULL, /* write_row */
45   table_os_global_by_type::delete_all_rows,
46   NULL, /* get_row_count */
47   1000, /* records */
48   sizeof(pos_os_global_by_type),
49   &m_table_lock,
50   { C_STRING_WITH_LEN("CREATE TABLE objects_summary_global_by_type("
51                       "OBJECT_TYPE VARCHAR(64) comment 'Groups records together with OBJECT_SCHEMA and OBJECT_NAME.',"
52                       "OBJECT_SCHEMA VARCHAR(64) comment 'Groups records together with OBJECT_TYPE and OBJECT_NAME.',"
53                       "OBJECT_NAME VARCHAR(64) comment 'Groups records together with OBJECT_SCHEMA and OBJECT_TYPE.',"
54                       "COUNT_STAR BIGINT unsigned not null comment 'Number of summarized events',"
55                       "SUM_TIMER_WAIT BIGINT unsigned not null comment 'Total wait time of the summarized events that are timed.',"
56                       "MIN_TIMER_WAIT BIGINT unsigned not null comment 'Minimum wait time of the summarized events that are timed.',"
57                       "AVG_TIMER_WAIT BIGINT unsigned not null comment 'Average wait time of the summarized events that are timed.',"
58                       "MAX_TIMER_WAIT BIGINT unsigned not null comment 'Maximum wait time of the summarized events that are timed.')") }
59 };
60 
61 PFS_engine_table*
create(void)62 table_os_global_by_type::create(void)
63 {
64   return new table_os_global_by_type();
65 }
66 
67 int
delete_all_rows(void)68 table_os_global_by_type::delete_all_rows(void)
69 {
70   reset_table_waits_by_table_handle();
71   reset_table_waits_by_table();
72   return 0;
73 }
74 
table_os_global_by_type()75 table_os_global_by_type::table_os_global_by_type()
76   : PFS_engine_table(&m_share, &m_pos),
77     m_row_exists(false), m_pos(), m_next_pos()
78 {}
79 
reset_position(void)80 void table_os_global_by_type::reset_position(void)
81 {
82   m_pos.reset();
83   m_next_pos.reset();
84 }
85 
rnd_next(void)86 int table_os_global_by_type::rnd_next(void)
87 {
88   PFS_table_share *table_share;
89 
90   for (m_pos.set_at(&m_next_pos);
91        m_pos.has_more_view();
92        m_pos.next_view())
93   {
94     switch (m_pos.m_index_1) {
95     case pos_os_global_by_type::VIEW_TABLE:
96       for ( ; m_pos.m_index_2 < table_share_max; m_pos.m_index_2++)
97       {
98         table_share= &table_share_array[m_pos.m_index_2];
99         if (table_share->m_lock.is_populated())
100         {
101           make_row(table_share);
102           m_next_pos.set_after(&m_pos);
103           return 0;
104         }
105       }
106       break;
107     default:
108       break;
109     }
110   }
111 
112   return HA_ERR_END_OF_FILE;
113 }
114 
115 int
rnd_pos(const void * pos)116 table_os_global_by_type::rnd_pos(const void *pos)
117 {
118   PFS_table_share *table_share;
119 
120   set_position(pos);
121 
122   switch (m_pos.m_index_1) {
123   case pos_os_global_by_type::VIEW_TABLE:
124     DBUG_ASSERT(m_pos.m_index_2 < table_share_max);
125     table_share= &table_share_array[m_pos.m_index_2];
126     if (table_share->m_lock.is_populated())
127     {
128       make_row(table_share);
129       return 0;
130     }
131     break;
132   default:
133     break;
134   }
135 
136   return HA_ERR_RECORD_DELETED;
137 }
138 
make_row(PFS_table_share * share)139 void table_os_global_by_type::make_row(PFS_table_share *share)
140 {
141   pfs_lock lock;
142   PFS_single_stat cumulated_stat;
143   uint safe_key_count;
144 
145   m_row_exists= false;
146 
147   share->m_lock.begin_optimistic_lock(&lock);
148 
149   m_row.m_object_type= share->get_object_type();
150   memcpy(m_row.m_schema_name, share->m_schema_name, share->m_schema_name_length);
151   m_row.m_schema_name_length= share->m_schema_name_length;
152   memcpy(m_row.m_object_name, share->m_table_name, share->m_table_name_length);
153   m_row.m_object_name_length= share->m_table_name_length;
154 
155   /* This is a dirty read, some thread can write data while we are reading it */
156   safe_key_count= sanitize_index_count(share->m_key_count);
157 
158   share->m_table_stat.sum(& cumulated_stat, safe_key_count);
159 
160   if (! share->m_lock.end_optimistic_lock(&lock))
161     return;
162 
163   m_row_exists= true;
164 
165   if (share->get_refcount() > 0)
166   {
167     /* For all the table handles still opened ... */
168     PFS_table *table= table_array;
169     PFS_table *table_last= table_array + table_max;
170     for ( ; table < table_last ; table++)
171     {
172       if ((table->m_share == share) && (table->m_lock.is_populated()))
173       {
174         /*
175           If the opened table handle is for this table share,
176           aggregate the table handle statistics.
177         */
178         table->m_table_stat.sum(& cumulated_stat, safe_key_count);
179       }
180     }
181   }
182 
183   time_normalizer *normalizer= time_normalizer::get(wait_timer);
184   m_row.m_stat.set(normalizer, &cumulated_stat);
185 }
186 
read_row_values(TABLE * table,unsigned char * buf,Field ** fields,bool read_all)187 int table_os_global_by_type::read_row_values(TABLE *table,
188                                              unsigned char *buf,
189                                              Field **fields,
190                                              bool read_all)
191 {
192   Field *f;
193 
194   if (unlikely(! m_row_exists))
195     return HA_ERR_RECORD_DELETED;
196 
197   /* Set the null bits */
198   DBUG_ASSERT(table->s->null_bytes == 1);
199   buf[0]= 0;
200 
201   for (; (f= *fields) ; fields++)
202   {
203     if (read_all || bitmap_is_set(table->read_set, f->field_index))
204     {
205       switch(f->field_index)
206       {
207       case 0: /* OBJECT_TYPE */
208         set_field_object_type(f, m_row.m_object_type);
209         break;
210       case 1: /* SCHEMA_NAME */
211         set_field_varchar_utf8(f, m_row.m_schema_name,
212                                m_row.m_schema_name_length);
213         break;
214       case 2: /* OBJECT_NAME */
215         set_field_varchar_utf8(f, m_row.m_object_name,
216                                m_row.m_object_name_length);
217         break;
218       case 3: /* COUNT */
219         set_field_ulonglong(f, m_row.m_stat.m_count);
220         break;
221       case 4: /* SUM */
222         set_field_ulonglong(f, m_row.m_stat.m_sum);
223         break;
224       case 5: /* MIN */
225         set_field_ulonglong(f, m_row.m_stat.m_min);
226         break;
227       case 6: /* AVG */
228         set_field_ulonglong(f, m_row.m_stat.m_avg);
229         break;
230       case 7: /* MAX */
231         set_field_ulonglong(f, m_row.m_stat.m_max);
232         break;
233       default:
234         DBUG_ASSERT(false);
235       }
236     }
237   }
238 
239   return 0;
240 }
241 
242