1 | /* Copyright (c) 2011, 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 Foundation, |
14 | 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ |
15 | |
16 | /** |
17 | @file storage/perfschema/table_host_cache.cc |
18 | Table HOST_CACHE (implementation). |
19 | */ |
20 | |
21 | #include "my_global.h" |
22 | #include "my_pthread.h" |
23 | #include "table_host_cache.h" |
24 | #include "hostname.h" |
25 | |
26 | THR_LOCK table_host_cache::m_table_lock; |
27 | |
28 | PFS_engine_table_share |
29 | table_host_cache::m_share= |
30 | { |
31 | { C_STRING_WITH_LEN("host_cache" ) }, |
32 | &pfs_truncatable_acl, |
33 | &table_host_cache::create, |
34 | NULL, /* write_row */ |
35 | table_host_cache::delete_all_rows, |
36 | NULL, /* get_row_count */ |
37 | 1000, /* records */ |
38 | sizeof(PFS_simple_index), /* ref length */ |
39 | &m_table_lock, |
40 | { C_STRING_WITH_LEN("CREATE TABLE host_cache(" |
41 | "IP VARCHAR(64) not null," |
42 | "HOST VARCHAR(255) collate utf8_bin," |
43 | "HOST_VALIDATED ENUM ('YES', 'NO') not null," |
44 | "SUM_CONNECT_ERRORS BIGINT not null," |
45 | "COUNT_HOST_BLOCKED_ERRORS BIGINT not null," |
46 | "COUNT_NAMEINFO_TRANSIENT_ERRORS BIGINT not null," |
47 | "COUNT_NAMEINFO_PERMANENT_ERRORS BIGINT not null," |
48 | "COUNT_FORMAT_ERRORS BIGINT not null," |
49 | "COUNT_ADDRINFO_TRANSIENT_ERRORS BIGINT not null," |
50 | "COUNT_ADDRINFO_PERMANENT_ERRORS BIGINT not null," |
51 | "COUNT_FCRDNS_ERRORS BIGINT not null," |
52 | "COUNT_HOST_ACL_ERRORS BIGINT not null," |
53 | "COUNT_NO_AUTH_PLUGIN_ERRORS BIGINT not null," |
54 | "COUNT_AUTH_PLUGIN_ERRORS BIGINT not null," |
55 | "COUNT_HANDSHAKE_ERRORS BIGINT not null," |
56 | "COUNT_PROXY_USER_ERRORS BIGINT not null," |
57 | "COUNT_PROXY_USER_ACL_ERRORS BIGINT not null," |
58 | "COUNT_AUTHENTICATION_ERRORS BIGINT not null," |
59 | "COUNT_SSL_ERRORS BIGINT not null," |
60 | "COUNT_MAX_USER_CONNECTIONS_ERRORS BIGINT not null," |
61 | "COUNT_MAX_USER_CONNECTIONS_PER_HOUR_ERRORS BIGINT not null," |
62 | "COUNT_DEFAULT_DATABASE_ERRORS BIGINT not null," |
63 | "COUNT_INIT_CONNECT_ERRORS BIGINT not null," |
64 | "COUNT_LOCAL_ERRORS BIGINT not null," |
65 | "COUNT_UNKNOWN_ERRORS BIGINT not null," |
66 | "FIRST_SEEN TIMESTAMP(0) NOT NULL default 0," |
67 | "LAST_SEEN TIMESTAMP(0) NOT NULL default 0," |
68 | "FIRST_ERROR_SEEN TIMESTAMP(0) null default 0," |
69 | "LAST_ERROR_SEEN TIMESTAMP(0) null default 0)" ) } |
70 | }; |
71 | |
72 | PFS_engine_table* table_host_cache::create(void) |
73 | { |
74 | table_host_cache *t= new table_host_cache(); |
75 | if (t != NULL) |
76 | { |
77 | THD *thd= current_thd; |
78 | DBUG_ASSERT(thd != NULL); |
79 | t->materialize(thd); |
80 | } |
81 | return t; |
82 | } |
83 | |
84 | int |
85 | table_host_cache::delete_all_rows(void) |
86 | { |
87 | /* |
88 | TRUNCATE TABLE performance_schema.host_cache |
89 | is an alternate syntax for |
90 | FLUSH HOSTS |
91 | */ |
92 | hostname_cache_refresh(); |
93 | return 0; |
94 | } |
95 | |
96 | table_host_cache::table_host_cache() |
97 | : PFS_engine_table(&m_share, &m_pos), |
98 | m_all_rows(NULL), m_row_count(0), |
99 | m_row(NULL), m_pos(0), m_next_pos(0) |
100 | {} |
101 | |
102 | void table_host_cache::materialize(THD *thd) |
103 | { |
104 | Host_entry *current; |
105 | Host_entry *first; |
106 | uint size; |
107 | uint index; |
108 | row_host_cache *rows; |
109 | row_host_cache *row; |
110 | |
111 | DBUG_ASSERT(m_all_rows == NULL); |
112 | DBUG_ASSERT(m_row_count == 0); |
113 | |
114 | hostname_cache_lock(); |
115 | |
116 | size= hostname_cache_size(); |
117 | if (size == 0) |
118 | { |
119 | /* Normal case, the cache is empty. */ |
120 | goto end; |
121 | } |
122 | |
123 | rows= (row_host_cache*) thd->alloc(size * sizeof(row_host_cache)); |
124 | if (rows == NULL) |
125 | { |
126 | /* Out of memory, this thread will error out. */ |
127 | goto end; |
128 | } |
129 | |
130 | index= 0; |
131 | row= rows; |
132 | |
133 | first= hostname_cache_first(); |
134 | current= first; |
135 | |
136 | while ((current != NULL) && (index < size)) |
137 | { |
138 | make_row(current, row); |
139 | index++; |
140 | row++; |
141 | current= current->next(); |
142 | } |
143 | |
144 | m_all_rows= rows; |
145 | m_row_count= index; |
146 | |
147 | end: |
148 | hostname_cache_unlock(); |
149 | } |
150 | |
151 | void table_host_cache::make_row(Host_entry *entry, row_host_cache *row) |
152 | { |
153 | row->m_ip_length= (int)strlen(entry->ip_key); |
154 | strcpy(row->m_ip, entry->ip_key); |
155 | row->m_hostname_length= entry->m_hostname_length; |
156 | if (row->m_hostname_length > 0) |
157 | strncpy(row->m_hostname, entry->m_hostname, row->m_hostname_length); |
158 | row->m_host_validated= entry->m_host_validated; |
159 | row->m_sum_connect_errors= entry->m_errors.m_connect; |
160 | row->m_count_host_blocked_errors= entry->m_errors.m_host_blocked; |
161 | row->m_count_nameinfo_transient_errors= entry->m_errors.m_nameinfo_transient; |
162 | row->m_count_nameinfo_permanent_errors= entry->m_errors.m_nameinfo_permanent; |
163 | row->m_count_format_errors= entry->m_errors.m_format; |
164 | row->m_count_addrinfo_transient_errors= entry->m_errors.m_addrinfo_transient; |
165 | row->m_count_addrinfo_permanent_errors= entry->m_errors.m_addrinfo_permanent; |
166 | row->m_count_fcrdns_errors= entry->m_errors.m_FCrDNS; |
167 | row->m_count_host_acl_errors= entry->m_errors.m_host_acl; |
168 | row->m_count_no_auth_plugin_errors= entry->m_errors.m_no_auth_plugin; |
169 | row->m_count_auth_plugin_errors= entry->m_errors.m_auth_plugin; |
170 | row->m_count_handshake_errors= entry->m_errors.m_handshake; |
171 | row->m_count_proxy_user_errors= entry->m_errors.m_proxy_user; |
172 | row->m_count_proxy_user_acl_errors= entry->m_errors.m_proxy_user_acl; |
173 | row->m_count_authentication_errors= entry->m_errors.m_authentication; |
174 | row->m_count_ssl_errors= entry->m_errors.m_ssl; |
175 | row->m_count_max_user_connection_errors= entry->m_errors.m_max_user_connection; |
176 | row->m_count_max_user_connection_per_hour_errors= entry->m_errors.m_max_user_connection_per_hour; |
177 | row->m_count_default_database_errors= entry->m_errors.m_default_database; |
178 | row->m_count_init_connect_errors= entry->m_errors.m_init_connect; |
179 | row->m_count_local_errors= entry->m_errors.m_local; |
180 | |
181 | /* |
182 | Reserved for future use, to help with backward compatibility. |
183 | When new errors are added in entry->m_errors.m_xxx, |
184 | report them in this column (GA releases), |
185 | until the table HOST_CACHE structure can be extended (next development version). |
186 | */ |
187 | row->m_count_unknown_errors= 0; |
188 | |
189 | row->m_first_seen= entry->m_first_seen; |
190 | row->m_last_seen= entry->m_last_seen; |
191 | row->m_first_error_seen= entry->m_first_error_seen; |
192 | row->m_last_error_seen= entry->m_last_error_seen; |
193 | } |
194 | |
195 | void table_host_cache::reset_position(void) |
196 | { |
197 | m_pos.m_index= 0; |
198 | m_next_pos.m_index= 0; |
199 | } |
200 | |
201 | int table_host_cache::rnd_next(void) |
202 | { |
203 | int result; |
204 | |
205 | m_pos.set_at(&m_next_pos); |
206 | |
207 | if (m_pos.m_index < m_row_count) |
208 | { |
209 | m_row= &m_all_rows[m_pos.m_index]; |
210 | m_next_pos.set_after(&m_pos); |
211 | result= 0; |
212 | } |
213 | else |
214 | { |
215 | m_row= NULL; |
216 | result= HA_ERR_END_OF_FILE; |
217 | } |
218 | |
219 | return result; |
220 | } |
221 | |
222 | int table_host_cache::rnd_pos(const void *pos) |
223 | { |
224 | set_position(pos); |
225 | DBUG_ASSERT(m_pos.m_index < m_row_count); |
226 | m_row= &m_all_rows[m_pos.m_index]; |
227 | return 0; |
228 | } |
229 | |
230 | int table_host_cache::read_row_values(TABLE *table, |
231 | unsigned char *buf, |
232 | Field **fields, |
233 | bool read_all) |
234 | { |
235 | Field *f; |
236 | |
237 | DBUG_ASSERT(m_row); |
238 | |
239 | /* Set the null bits */ |
240 | DBUG_ASSERT(table->s->null_bytes == 1); |
241 | buf[0]= 0; |
242 | |
243 | for (; (f= *fields) ; fields++) |
244 | { |
245 | if (read_all || bitmap_is_set(table->read_set, f->field_index)) |
246 | { |
247 | switch(f->field_index) |
248 | { |
249 | case 0: /* IP */ |
250 | set_field_varchar_utf8(f, m_row->m_ip, m_row->m_ip_length); |
251 | break; |
252 | case 1: /* HOST */ |
253 | if (m_row->m_hostname_length > 0) |
254 | set_field_varchar_utf8(f, m_row->m_hostname, m_row->m_hostname_length); |
255 | else |
256 | f->set_null(); |
257 | break; |
258 | case 2: /* HOST_VALIDATED */ |
259 | set_field_enum(f, m_row->m_host_validated ? ENUM_YES : ENUM_NO); |
260 | break; |
261 | case 3: /* SUM_CONNECT_ERRORS */ |
262 | set_field_ulonglong(f, m_row->m_sum_connect_errors); |
263 | break; |
264 | case 4: /* COUNT_HOST_BLOCKED_ERRORS. */ |
265 | set_field_ulonglong(f, m_row->m_count_host_blocked_errors); |
266 | break; |
267 | case 5: /* COUNT_NAMEINFO_TRANSIENT_ERRORS */ |
268 | set_field_ulonglong(f, m_row->m_count_nameinfo_transient_errors); |
269 | break; |
270 | case 6: /* COUNT_NAMEINFO_PERSISTENT_ERRORS */ |
271 | set_field_ulonglong(f, m_row->m_count_nameinfo_permanent_errors); |
272 | break; |
273 | case 7: /* COUNT_FORMAT_ERRORS */ |
274 | set_field_ulonglong(f, m_row->m_count_format_errors); |
275 | break; |
276 | case 8: /* COUNT_ADDRINFO_TRANSIENT_ERRORS */ |
277 | set_field_ulonglong(f, m_row->m_count_addrinfo_transient_errors); |
278 | break; |
279 | case 9: /* COUNT_ADDRINFO_PERSISTENT_ERRORS */ |
280 | set_field_ulonglong(f, m_row->m_count_addrinfo_permanent_errors); |
281 | break; |
282 | case 10: /* COUNT_FCRDNS_ERRORS */ |
283 | set_field_ulonglong(f, m_row->m_count_fcrdns_errors); |
284 | break; |
285 | case 11: /* COUNT_HOST_ACL_ERRORS */ |
286 | set_field_ulonglong(f, m_row->m_count_host_acl_errors); |
287 | break; |
288 | case 12: /* COUNT_NO_AUTH_PLUGIN_ERRORS */ |
289 | set_field_ulonglong(f, m_row->m_count_no_auth_plugin_errors); |
290 | break; |
291 | case 13: /* COUNT_AUTH_PLUGIN_ERRORS */ |
292 | set_field_ulonglong(f, m_row->m_count_auth_plugin_errors); |
293 | break; |
294 | case 14: /* COUNT_HANDSHAKE_ERRORS */ |
295 | set_field_ulonglong(f, m_row->m_count_handshake_errors); |
296 | break; |
297 | case 15: /* COUNT_PROXY_USER_ERRORS */ |
298 | set_field_ulonglong(f, m_row->m_count_proxy_user_errors); |
299 | break; |
300 | case 16: /* COUNT_PROXY_USER_ACL_ERRORS */ |
301 | set_field_ulonglong(f, m_row->m_count_proxy_user_acl_errors); |
302 | break; |
303 | case 17: /* COUNT_AUTHENTICATION_ERRORS */ |
304 | set_field_ulonglong(f, m_row->m_count_authentication_errors); |
305 | break; |
306 | case 18: /* COUNT_SSL_ERRORS */ |
307 | set_field_ulonglong(f, m_row->m_count_ssl_errors); |
308 | break; |
309 | case 19: /* COUNT_MAX_USER_CONNECTION_ERRORS */ |
310 | set_field_ulonglong(f, m_row->m_count_max_user_connection_errors); |
311 | break; |
312 | case 20: /* COUNT_MAX_USER_CONNECTION_PER_HOUR_ERRORS */ |
313 | set_field_ulonglong(f, m_row->m_count_max_user_connection_per_hour_errors); |
314 | break; |
315 | case 21: /* COUNT_DEFAULT_DATABASE_ERRORS */ |
316 | set_field_ulonglong(f, m_row->m_count_default_database_errors); |
317 | break; |
318 | case 22: /* COUNT_INIT_CONNECT_ERRORS */ |
319 | set_field_ulonglong(f, m_row->m_count_init_connect_errors); |
320 | break; |
321 | case 23: /* COUNT_LOCAL_ERRORS */ |
322 | set_field_ulonglong(f, m_row->m_count_local_errors); |
323 | break; |
324 | case 24: /* COUNT_UNKNOWN_ERRORS */ |
325 | set_field_ulonglong(f, m_row->m_count_unknown_errors); |
326 | break; |
327 | case 25: /* FIRST_SEEN */ |
328 | set_field_timestamp(f, m_row->m_first_seen); |
329 | break; |
330 | case 26: /* LAST_SEEN */ |
331 | set_field_timestamp(f, m_row->m_last_seen); |
332 | break; |
333 | case 27: /* FIRST_ERROR_SEEN */ |
334 | if (m_row->m_first_error_seen != 0) |
335 | set_field_timestamp(f, m_row->m_first_error_seen); |
336 | else |
337 | f->set_null(); |
338 | break; |
339 | case 28: /* LAST_ERROR_SEEN */ |
340 | if (m_row->m_last_error_seen != 0) |
341 | set_field_timestamp(f, m_row->m_last_error_seen); |
342 | else |
343 | f->set_null(); |
344 | break; |
345 | default: |
346 | DBUG_ASSERT(false); |
347 | } |
348 | } |
349 | } |
350 | |
351 | return 0; |
352 | } |
353 | |
354 | |