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
26THR_LOCK table_host_cache::m_table_lock;
27
28PFS_engine_table_share
29table_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
72PFS_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
84int
85table_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
96table_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
102void 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
147end:
148 hostname_cache_unlock();
149}
150
151void 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
195void table_host_cache::reset_position(void)
196{
197 m_pos.m_index= 0;
198 m_next_pos.m_index= 0;
199}
200
201int 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
222int 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
230int 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