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