1 /* Copyright (c) 2012, 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
21   Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
22 
23 /**
24   @file storage/perfschema/table_table_handles.cc
25   Table TABLE_TABLE_HANDLES (implementation).
26 */
27 
28 #include "my_global.h"
29 #include "my_thread.h"
30 #include "pfs_instr_class.h"
31 #include "pfs_column_types.h"
32 #include "pfs_column_values.h"
33 #include "table_table_handles.h"
34 #include "pfs_global.h"
35 #include "pfs_stat.h"
36 #include "pfs_buffer_container.h"
37 #include "field.h"
38 
39 THR_LOCK table_table_handles::m_table_lock;
40 
41 static const TABLE_FIELD_TYPE field_types[]=
42 {
43   {
44     { C_STRING_WITH_LEN("OBJECT_TYPE") },
45     { C_STRING_WITH_LEN("varchar(64)") },
46     { NULL, 0}
47   },
48   {
49     { C_STRING_WITH_LEN("OBJECT_SCHEMA") },
50     { C_STRING_WITH_LEN("varchar(64)") },
51     { NULL, 0}
52   },
53   {
54     { C_STRING_WITH_LEN("OBJECT_NAME") },
55     { C_STRING_WITH_LEN("varchar(64)") },
56     { NULL, 0}
57   },
58   {
59     { C_STRING_WITH_LEN("OBJECT_INSTANCE_BEGIN") },
60     { C_STRING_WITH_LEN("bigint(20)") },
61     { NULL, 0}
62   },
63   {
64     { C_STRING_WITH_LEN("OWNER_THREAD_ID") },
65     { C_STRING_WITH_LEN("bigint(20)") },
66     { NULL, 0}
67   },
68   {
69     { C_STRING_WITH_LEN("OWNER_EVENT_ID") },
70     { C_STRING_WITH_LEN("bigint(20)") },
71     { NULL, 0}
72   },
73   {
74     { C_STRING_WITH_LEN("INTERNAL_LOCK") },
75     { C_STRING_WITH_LEN("varchar(64)") },
76     { NULL, 0}
77   },
78   {
79     { C_STRING_WITH_LEN("EXTERNAL_LOCK") },
80     { C_STRING_WITH_LEN("varchar(64)") },
81     { NULL, 0}
82   }
83 };
84 
85 TABLE_FIELD_DEF
86 table_table_handles::m_field_def=
87 { 8, field_types };
88 
89 PFS_engine_table_share
90 table_table_handles::m_share=
91 {
92   { C_STRING_WITH_LEN("table_handles") },
93   &pfs_readonly_acl,
94   table_table_handles::create,
95   NULL, /* write_row */
96   NULL, /* delete_all_rows */
97   table_table_handles::get_row_count,
98   sizeof(PFS_simple_index),
99   &m_table_lock,
100   &m_field_def,
101   false, /* checked */
102   false  /* perpetual */
103 };
104 
105 PFS_engine_table*
create(void)106 table_table_handles::create(void)
107 {
108   return new table_table_handles();
109 }
110 
111 ha_rows
get_row_count(void)112 table_table_handles::get_row_count(void)
113 {
114   return global_table_container.get_row_count();
115 }
116 
table_table_handles()117 table_table_handles::table_table_handles()
118   : PFS_engine_table(&m_share, &m_pos),
119     m_row_exists(false), m_pos(0), m_next_pos(0)
120 {}
121 
reset_position(void)122 void table_table_handles::reset_position(void)
123 {
124   m_pos.m_index= 0;
125   m_next_pos.m_index= 0;
126 }
127 
rnd_init(bool scan)128 int table_table_handles::rnd_init(bool scan)
129 {
130   return 0;
131 }
132 
rnd_next(void)133 int table_table_handles::rnd_next(void)
134 {
135   PFS_table *pfs;
136 
137   m_pos.set_at(&m_next_pos);
138   PFS_table_iterator it= global_table_container.iterate(m_pos.m_index);
139   pfs= it.scan_next(& m_pos.m_index);
140   if (pfs != NULL)
141   {
142     make_row(pfs);
143     m_next_pos.set_after(&m_pos);
144     return 0;
145   }
146 
147   return HA_ERR_END_OF_FILE;
148 }
149 
150 int
rnd_pos(const void * pos)151 table_table_handles::rnd_pos(const void *pos)
152 {
153   PFS_table *pfs;
154 
155   set_position(pos);
156 
157   pfs= global_table_container.get(m_pos.m_index);
158   if (pfs != NULL)
159   {
160     make_row(pfs);
161     return 0;
162   }
163 
164   return HA_ERR_RECORD_DELETED;
165 }
166 
make_row(PFS_table * table)167 void table_table_handles::make_row(PFS_table *table)
168 {
169   pfs_optimistic_state lock;
170   PFS_table_share *share;
171   PFS_thread *thread;
172 
173   m_row_exists= false;
174 
175   table->m_lock.begin_optimistic_lock(&lock);
176 
177   share= sanitize_table_share(table->m_share);
178   if (share == NULL)
179     return;
180 
181   if (m_row.m_object.make_row(share))
182     return;
183 
184   m_row.m_identity= table->m_identity;
185 
186   thread= sanitize_thread(table->m_thread_owner);
187   if (thread != NULL)
188   {
189     m_row.m_owner_thread_id= thread->m_thread_internal_id;
190     m_row.m_owner_event_id= table->m_owner_event_id;
191   }
192   else
193   {
194     m_row.m_owner_thread_id= 0;
195     m_row.m_owner_event_id= 0;
196   }
197 
198   m_row.m_internal_lock= table->m_internal_lock;
199   m_row.m_external_lock= table->m_external_lock;
200 
201   if (! table->m_lock.end_optimistic_lock(&lock))
202     return;
203 
204   m_row_exists= true;
205 }
206 
read_row_values(TABLE * table,unsigned char * buf,Field ** fields,bool read_all)207 int table_table_handles::read_row_values(TABLE *table,
208                                          unsigned char *buf,
209                                          Field **fields,
210                                          bool read_all)
211 {
212   Field *f;
213 
214   if (unlikely(! m_row_exists))
215     return HA_ERR_RECORD_DELETED;
216 
217   /* Set the null bits */
218   assert(table->s->null_bytes == 1);
219   buf[0]= 0;
220 
221   for (; (f= *fields) ; fields++)
222   {
223     if (read_all || bitmap_is_set(table->read_set, f->field_index))
224     {
225       switch(f->field_index)
226       {
227       case 0: /* OBJECT_TYPE */
228       case 1: /* SCHEMA_NAME */
229       case 2: /* OBJECT_NAME */
230         m_row.m_object.set_field(f->field_index, f);
231         break;
232       case 3: /* OBJECT_INSTANCE_BEGIN */
233         set_field_ulonglong(f, (intptr) m_row.m_identity);
234         break;
235       case 4: /* OWNER_THREAD_ID */
236         set_field_ulonglong(f, m_row.m_owner_thread_id);
237         break;
238       case 5: /* OWNER_EVENT_ID */
239         set_field_ulonglong(f, m_row.m_owner_event_id);
240         break;
241       case 6: /* INTERNAL_LOCK */
242         set_field_lock_type(f, m_row.m_internal_lock);
243         break;
244       case 7: /* EXTERNAL_LOCK */
245         set_field_lock_type(f, m_row.m_external_lock);
246         break;
247       default:
248         assert(false);
249       }
250     }
251   }
252 
253   return 0;
254 }
255 
256