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