1 /* Copyright (c) 2008, 2021, Oracle and/or its affiliates.
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, Suite 500, Boston, MA 02110-1335 USA */
22
23 /**
24 @file storage/perfschema/table_socket_instances.cc
25 Table SOCKET_INSTANCES (implementation).
26 */
27
28 #include "my_global.h"
29 #include "my_thread.h"
30 #include "pfs_instr.h"
31 #include "pfs_column_types.h"
32 #include "pfs_column_values.h"
33 #include "table_socket_instances.h"
34 #include "pfs_global.h"
35 #include "pfs_buffer_container.h"
36 #include "field.h"
37
38 THR_LOCK table_socket_instances::m_table_lock;
39
40 static const TABLE_FIELD_TYPE field_types[]=
41 {
42 {
43 { C_STRING_WITH_LEN("EVENT_NAME") },
44 { C_STRING_WITH_LEN("varchar(128)") },
45 { NULL, 0}
46 },
47 {
48 { C_STRING_WITH_LEN("OBJECT_INSTANCE_BEGIN") },
49 { C_STRING_WITH_LEN("bigint(20)") },
50 { NULL, 0}
51 },
52 {
53 { C_STRING_WITH_LEN("THREAD_ID") },
54 { C_STRING_WITH_LEN("bigint(20)") },
55 { NULL, 0}
56 },
57 {
58 { C_STRING_WITH_LEN("SOCKET_ID") },
59 { C_STRING_WITH_LEN("int(11)") },
60 { NULL, 0}
61 },
62 {
63 { C_STRING_WITH_LEN("IP") },
64 { C_STRING_WITH_LEN("varchar(64)") },
65 { NULL, 0}
66 },
67 {
68 { C_STRING_WITH_LEN("PORT") },
69 { C_STRING_WITH_LEN("int(11)") },
70 { NULL, 0}
71 },
72 {
73 { C_STRING_WITH_LEN("STATE") },
74 { C_STRING_WITH_LEN("enum('IDLE','ACTIVE')") },
75 { NULL, 0}
76 }
77 };
78
79 TABLE_FIELD_DEF
80 table_socket_instances::m_field_def=
81 { 7, field_types };
82
83 PFS_engine_table_share
84 table_socket_instances::m_share=
85 {
86 { C_STRING_WITH_LEN("socket_instances") },
87 &pfs_readonly_acl,
88 table_socket_instances::create,
89 NULL, /* write_row */
90 NULL, /* delete_all_rows */
91 table_socket_instances::get_row_count,
92 sizeof(PFS_simple_index),
93 &m_table_lock,
94 &m_field_def,
95 false, /* checked */
96 false /* perpetual */
97 };
98
create(void)99 PFS_engine_table* table_socket_instances::create(void)
100 {
101 return new table_socket_instances();
102 }
103
104 ha_rows
get_row_count(void)105 table_socket_instances::get_row_count(void)
106 {
107 return global_socket_container.get_row_count();
108 }
109
table_socket_instances()110 table_socket_instances::table_socket_instances()
111 : PFS_engine_table(&m_share, &m_pos),
112 m_row_exists(false), m_pos(0), m_next_pos(0)
113 {}
114
reset_position(void)115 void table_socket_instances::reset_position(void)
116 {
117 m_pos.m_index= 0;
118 m_next_pos.m_index= 0;
119 }
120
rnd_next(void)121 int table_socket_instances::rnd_next(void)
122 {
123 PFS_socket *pfs;
124
125 m_pos.set_at(&m_next_pos);
126 PFS_socket_iterator it= global_socket_container.iterate(m_pos.m_index);
127 pfs= it.scan_next(& m_pos.m_index);
128 if (pfs != NULL)
129 {
130 make_row(pfs);
131 m_next_pos.set_after(&m_pos);
132 return 0;
133 }
134
135 return HA_ERR_END_OF_FILE;
136 }
137
rnd_pos(const void * pos)138 int table_socket_instances::rnd_pos(const void *pos)
139 {
140 PFS_socket *pfs;
141
142 set_position(pos);
143
144 pfs= global_socket_container.get(m_pos.m_index);
145 if (pfs != NULL)
146 {
147 make_row(pfs);
148 return 0;
149 }
150
151 return HA_ERR_RECORD_DELETED;
152 }
153
make_row(PFS_socket * pfs)154 void table_socket_instances::make_row(PFS_socket *pfs)
155 {
156 pfs_optimistic_state lock;
157 PFS_socket_class *safe_class;
158
159 m_row_exists= false;
160
161 /* Protect this reader against a socket delete */
162 pfs->m_lock.begin_optimistic_lock(&lock);
163
164 safe_class= sanitize_socket_class(pfs->m_class);
165 if (unlikely(safe_class == NULL))
166 return;
167
168 /** Extract ip address and port from raw address */
169 m_row.m_ip_length= pfs_get_socket_address(m_row.m_ip, sizeof(m_row.m_ip),
170 &m_row.m_port,
171 &pfs->m_sock_addr, pfs->m_addr_len);
172 m_row.m_event_name= safe_class->m_name;
173 m_row.m_event_name_length= safe_class->m_name_length;
174 m_row.m_identity= pfs->m_identity;
175 m_row.m_fd= pfs->m_fd;
176 m_row.m_state= (pfs->m_idle ? PSI_SOCKET_STATE_IDLE
177 : PSI_SOCKET_STATE_ACTIVE);
178 PFS_thread *safe_thread= sanitize_thread(pfs->m_thread_owner);
179
180 if (safe_thread != NULL)
181 {
182 m_row.m_thread_id= safe_thread->m_thread_internal_id;
183 m_row.m_thread_id_set= true;
184 }
185 else
186 m_row.m_thread_id_set= false;
187
188
189 if (pfs->m_lock.end_optimistic_lock(&lock))
190 m_row_exists= true;
191 }
192
read_row_values(TABLE * table,unsigned char * buf,Field ** fields,bool read_all)193 int table_socket_instances::read_row_values(TABLE *table,
194 unsigned char *buf,
195 Field **fields,
196 bool read_all)
197 {
198 Field *f;
199
200 if (unlikely(!m_row_exists))
201 return HA_ERR_RECORD_DELETED;
202
203 /* Set the null bits */
204 assert(table->s->null_bytes == 1);
205 buf[0]= 0;
206
207 for (; (f= *fields) ; fields++)
208 {
209 if (read_all || bitmap_is_set(table->read_set, f->field_index))
210 {
211 switch(f->field_index)
212 {
213 case 0: /* EVENT_NAME */
214 set_field_varchar_utf8(f, m_row.m_event_name, m_row.m_event_name_length);
215 break;
216 case 1: /* OBJECT_INSTANCE_BEGIN */
217 set_field_ulonglong(f, (intptr)m_row.m_identity);
218 break;
219 case 2: /* THREAD_ID */
220 if (m_row.m_thread_id_set)
221 set_field_ulonglong(f, m_row.m_thread_id);
222 else
223 f->set_null();
224 break;
225 case 3: /* SOCKET_ID */
226 set_field_ulong(f, m_row.m_fd);
227 break;
228 case 4: /* IP */
229 set_field_varchar_utf8(f, m_row.m_ip, m_row.m_ip_length);
230 break;
231 case 5: /* PORT */
232 set_field_ulong(f, m_row.m_port);
233 break;
234 case 6: /* STATE */
235 set_field_enum(f, m_row.m_state);
236 break;
237 default:
238 assert(false);
239 }
240 }
241 }
242
243 return 0;
244 }
245
246