1 /* Copyright (c) 2010, 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/pfs_setup_actor.cc
25 Performance schema setup actor (implementation).
26 */
27
28 #include "my_global.h"
29 #include "my_sys.h"
30 #include "my_base.h"
31 #include "pfs.h"
32 #include "pfs_stat.h"
33 #include "pfs_instr.h"
34 #include "pfs_setup_actor.h"
35 #include "pfs_account.h"
36 #include "pfs_global.h"
37 #include "pfs_buffer_container.h"
38
39 /**
40 @addtogroup Performance_schema_buffers
41 @{
42 */
43
44 /** Hash table for setup_actor records. */
45 LF_HASH setup_actor_hash;
46 /** True if @c setup_actor_hash is initialized. */
47 static bool setup_actor_hash_inited= false;
48
49 /**
50 Initialize the setup actor buffers.
51 @param param sizing parameters
52 @return 0 on success
53 */
init_setup_actor(const PFS_global_param * param)54 int init_setup_actor(const PFS_global_param *param)
55 {
56 return global_setup_actor_container.init(param->m_setup_actor_sizing);
57 }
58
59 /** Cleanup all the setup actor buffers. */
cleanup_setup_actor(void)60 void cleanup_setup_actor(void)
61 {
62 global_setup_actor_container.cleanup();
63 }
64
65 C_MODE_START
setup_actor_hash_get_key(const uchar * entry,size_t * length,my_bool)66 static uchar *setup_actor_hash_get_key(const uchar *entry, size_t *length,
67 my_bool)
68 {
69 const PFS_setup_actor * const *typed_entry;
70 const PFS_setup_actor *setup_actor;
71 const void *result;
72 typed_entry= reinterpret_cast<const PFS_setup_actor* const *> (entry);
73 assert(typed_entry != NULL);
74 setup_actor= *typed_entry;
75 assert(setup_actor != NULL);
76 *length= setup_actor->m_key.m_key_length;
77 result= setup_actor->m_key.m_hash_key;
78 return const_cast<uchar*> (reinterpret_cast<const uchar*> (result));
79 }
80 C_MODE_END
81
82 /**
83 Initialize the setup actor hash.
84 @return 0 on success
85 */
init_setup_actor_hash(const PFS_global_param * param)86 int init_setup_actor_hash(const PFS_global_param *param)
87 {
88 if ((! setup_actor_hash_inited) && (param->m_setup_actor_sizing != 0))
89 {
90 lf_hash_init(&setup_actor_hash, sizeof(PFS_setup_actor*), LF_HASH_UNIQUE,
91 0, 0, setup_actor_hash_get_key, &my_charset_bin);
92 /* setup_actor_hash.size= param->m_setup_actor_sizing; */
93 setup_actor_hash_inited= true;
94 }
95 return 0;
96 }
97
98 /** Cleanup the setup actor hash. */
cleanup_setup_actor_hash(void)99 void cleanup_setup_actor_hash(void)
100 {
101 if (setup_actor_hash_inited)
102 {
103 lf_hash_destroy(&setup_actor_hash);
104 setup_actor_hash_inited= false;
105 }
106 }
107
get_setup_actor_hash_pins(PFS_thread * thread)108 static LF_PINS* get_setup_actor_hash_pins(PFS_thread *thread)
109 {
110 if (unlikely(thread->m_setup_actor_hash_pins == NULL))
111 {
112 if (! setup_actor_hash_inited)
113 return NULL;
114 thread->m_setup_actor_hash_pins= lf_hash_get_pins(&setup_actor_hash);
115 }
116 return thread->m_setup_actor_hash_pins;
117 }
118
set_setup_actor_key(PFS_setup_actor_key * key,const char * user,uint user_length,const char * host,uint host_length,const char * role,uint role_length)119 static void set_setup_actor_key(PFS_setup_actor_key *key,
120 const char *user, uint user_length,
121 const char *host, uint host_length,
122 const char *role, uint role_length)
123 {
124 assert(user_length <= USERNAME_LENGTH);
125 assert(host_length <= HOSTNAME_LENGTH);
126
127 char *ptr= &key->m_hash_key[0];
128 memcpy(ptr, user, user_length);
129 ptr+= user_length;
130 ptr[0]= 0;
131 ptr++;
132 memcpy(ptr, host, host_length);
133 ptr+= host_length;
134 ptr[0]= 0;
135 ptr++;
136 memcpy(ptr, role, role_length);
137 ptr+= role_length;
138 ptr[0]= 0;
139 ptr++;
140 key->m_key_length= ptr - &key->m_hash_key[0];
141 }
142
insert_setup_actor(const String * user,const String * host,const String * role,bool enabled,bool history)143 int insert_setup_actor(const String *user, const String *host, const String *role,
144 bool enabled, bool history)
145 {
146 PFS_thread *thread= PFS_thread::get_current_thread();
147 if (unlikely(thread == NULL))
148 return HA_ERR_OUT_OF_MEM;
149
150 LF_PINS *pins= get_setup_actor_hash_pins(thread);
151 if (unlikely(pins == NULL))
152 return HA_ERR_OUT_OF_MEM;
153
154 PFS_setup_actor *pfs;
155 pfs_dirty_state dirty_state;
156
157 pfs= global_setup_actor_container.allocate(& dirty_state);
158 if (pfs != NULL)
159 {
160 set_setup_actor_key(&pfs->m_key,
161 user->ptr(), user->length(),
162 host->ptr(), host->length(),
163 role->ptr(), role->length());
164 pfs->m_username= &pfs->m_key.m_hash_key[0];
165 pfs->m_username_length= user->length();
166 pfs->m_hostname= pfs->m_username + pfs->m_username_length + 1;
167 pfs->m_hostname_length= host->length();
168 pfs->m_rolename= pfs->m_hostname + pfs->m_hostname_length + 1;
169 pfs->m_rolename_length= role->length();
170 pfs->m_enabled= enabled;
171 pfs->m_history= history;
172
173 int res;
174 pfs->m_lock.dirty_to_allocated(& dirty_state);
175 res= lf_hash_insert(&setup_actor_hash, pins, &pfs);
176 if (likely(res == 0))
177 {
178 update_setup_actors_derived_flags();
179 return 0;
180 }
181
182 global_setup_actor_container.deallocate(pfs);
183
184 if (res > 0)
185 return HA_ERR_FOUND_DUPP_KEY;
186 return HA_ERR_OUT_OF_MEM;
187 }
188
189 return HA_ERR_RECORD_FILE_FULL;
190 }
191
delete_setup_actor(const String * user,const String * host,const String * role)192 int delete_setup_actor(const String *user, const String *host, const String *role)
193 {
194 PFS_thread *thread= PFS_thread::get_current_thread();
195 if (unlikely(thread == NULL))
196 return HA_ERR_OUT_OF_MEM;
197
198 LF_PINS* pins= get_setup_actor_hash_pins(thread);
199 if (unlikely(pins == NULL))
200 return HA_ERR_OUT_OF_MEM;
201
202 PFS_setup_actor_key key;
203 set_setup_actor_key(&key,
204 user->ptr(), user->length(),
205 host->ptr(), host->length(),
206 role->ptr(), role->length());
207
208 PFS_setup_actor **entry;
209 entry= reinterpret_cast<PFS_setup_actor**>
210 (lf_hash_search(&setup_actor_hash, pins, key.m_hash_key, key.m_key_length));
211
212 if (entry && (entry != MY_ERRPTR))
213 {
214 PFS_setup_actor *pfs= *entry;
215 lf_hash_delete(&setup_actor_hash, pins, key.m_hash_key, key.m_key_length);
216 global_setup_actor_container.deallocate(pfs);
217 }
218
219 lf_hash_search_unpin(pins);
220
221 update_setup_actors_derived_flags();
222
223 return 0;
224 }
225
226 class Proc_reset_setup_actor
227 : public PFS_buffer_processor<PFS_setup_actor>
228 {
229 public:
Proc_reset_setup_actor(LF_PINS * pins)230 Proc_reset_setup_actor(LF_PINS* pins)
231 : m_pins(pins)
232 {}
233
operator ()(PFS_setup_actor * pfs)234 virtual void operator()(PFS_setup_actor *pfs)
235 {
236 lf_hash_delete(&setup_actor_hash, m_pins,
237 pfs->m_key.m_hash_key, pfs->m_key.m_key_length);
238
239 global_setup_actor_container.deallocate(pfs);
240 }
241
242 private:
243 LF_PINS* m_pins;
244 };
245
reset_setup_actor()246 int reset_setup_actor()
247 {
248 PFS_thread *thread= PFS_thread::get_current_thread();
249 if (unlikely(thread == NULL))
250 return HA_ERR_OUT_OF_MEM;
251
252 LF_PINS* pins= get_setup_actor_hash_pins(thread);
253 if (unlikely(pins == NULL))
254 return HA_ERR_OUT_OF_MEM;
255
256 Proc_reset_setup_actor proc(pins);
257 // FIXME: delete helper instead
258 global_setup_actor_container.apply(proc);
259
260 update_setup_actors_derived_flags();
261
262 return 0;
263 }
264
setup_actor_count()265 long setup_actor_count()
266 {
267 return setup_actor_hash.count;
268 }
269
270 /*
271 - '%' should be replaced by NULL in table SETUP_ACTOR
272 - add an ENABLED column to include/exclude patterns, more flexible
273 - the principle is similar to SETUP_OBJECTS
274 */
lookup_setup_actor(PFS_thread * thread,const char * user,uint user_length,const char * host,uint host_length,bool * enabled,bool * history)275 void lookup_setup_actor(PFS_thread *thread,
276 const char *user, uint user_length,
277 const char *host, uint host_length,
278 bool *enabled, bool *history)
279 {
280 PFS_setup_actor_key key;
281 PFS_setup_actor **entry;
282 int i;
283
284 LF_PINS* pins= get_setup_actor_hash_pins(thread);
285 if (unlikely(pins == NULL))
286 {
287 *enabled= false;
288 *history= false;
289 return;
290 }
291
292 for (i= 1; i<=4; i++)
293 {
294 /*
295 WL#988 Roles is not implemented, so we do not have a role name.
296 Looking up "%" in SETUP_ACTORS.ROLE.
297 */
298 switch(i)
299 {
300 case 1:
301 set_setup_actor_key(&key, user, user_length, host, host_length, "%", 1);
302 break;
303 case 2:
304 set_setup_actor_key(&key, user, user_length, "%", 1, "%", 1);
305 break;
306 case 3:
307 set_setup_actor_key(&key, "%", 1, host, host_length, "%", 1);
308 break;
309 case 4:
310 set_setup_actor_key(&key, "%", 1, "%", 1, "%", 1);
311 break;
312 }
313 entry= reinterpret_cast<PFS_setup_actor**>
314 (lf_hash_search(&setup_actor_hash, pins, key.m_hash_key, key.m_key_length));
315
316 if (entry && (entry != MY_ERRPTR))
317 {
318 PFS_setup_actor *pfs= *entry;
319 lf_hash_search_unpin(pins);
320 *enabled= pfs->m_enabled;
321 *history= pfs->m_history;
322 return;
323 }
324
325 lf_hash_search_unpin(pins);
326 }
327 *enabled= false;
328 *history= false;
329 return;
330 }
331
update_setup_actors_derived_flags()332 int update_setup_actors_derived_flags()
333 {
334 PFS_thread *thread= PFS_thread::get_current_thread();
335 if (unlikely(thread == NULL))
336 return HA_ERR_OUT_OF_MEM;
337
338 update_accounts_derived_flags(thread);
339 return 0;
340 }
341
342 /** @} */
343