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