1 | /* Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. |
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 as published by |
5 | the Free Software Foundation; version 2 of the License. |
6 | |
7 | This program is distributed in the hope that it will be useful, |
8 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
10 | GNU General Public License for more details. |
11 | |
12 | You should have received a copy of the GNU General Public License |
13 | along with this program; if not, write to the Free Software Foundation, |
14 | 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ |
15 | |
16 | /** |
17 | @file storage/perfschema/pfs_setup_actor.cc |
18 | Performance schema setup actor (implementation). |
19 | */ |
20 | |
21 | #include "my_global.h" |
22 | #include "my_sys.h" |
23 | #include "my_base.h" |
24 | #include "pfs.h" |
25 | #include "pfs_stat.h" |
26 | #include "pfs_instr.h" |
27 | #include "pfs_setup_actor.h" |
28 | #include "pfs_global.h" |
29 | |
30 | /** |
31 | @addtogroup Performance_schema_buffers |
32 | @{ |
33 | */ |
34 | |
35 | /** Size of the setup_actor instances array. @sa setup_actor_array */ |
36 | ulong setup_actor_max; |
37 | |
38 | /** |
39 | Setup_actor instances array. |
40 | @sa setup_actor_max |
41 | */ |
42 | |
43 | PFS_setup_actor *setup_actor_array= NULL; |
44 | |
45 | /** Hash table for setup_actor records. */ |
46 | LF_HASH setup_actor_hash; |
47 | /** True if @c setup_actor_hash is initialized. */ |
48 | static bool setup_actor_hash_inited= false; |
49 | |
50 | /** |
51 | Initialize the setup actor buffers. |
52 | @param param sizing parameters |
53 | @return 0 on success |
54 | */ |
55 | int init_setup_actor(const PFS_global_param *param) |
56 | { |
57 | setup_actor_max= param->m_setup_actor_sizing; |
58 | |
59 | setup_actor_array= NULL; |
60 | |
61 | if (setup_actor_max > 0) |
62 | { |
63 | setup_actor_array= PFS_MALLOC_ARRAY(setup_actor_max, sizeof(PFS_setup_actor), |
64 | PFS_setup_actor, MYF(MY_ZEROFILL)); |
65 | if (unlikely(setup_actor_array == NULL)) |
66 | return 1; |
67 | } |
68 | |
69 | return 0; |
70 | } |
71 | |
72 | /** Cleanup all the setup actor buffers. */ |
73 | void cleanup_setup_actor(void) |
74 | { |
75 | pfs_free(setup_actor_array); |
76 | setup_actor_array= NULL; |
77 | setup_actor_max= 0; |
78 | } |
79 | |
80 | C_MODE_START |
81 | static uchar *setup_actor_hash_get_key(const uchar *entry, size_t *length, |
82 | my_bool) |
83 | { |
84 | const PFS_setup_actor * const *typed_entry; |
85 | const PFS_setup_actor *setup_actor; |
86 | const void *result; |
87 | typed_entry= reinterpret_cast<const PFS_setup_actor* const *> (entry); |
88 | DBUG_ASSERT(typed_entry != NULL); |
89 | setup_actor= *typed_entry; |
90 | DBUG_ASSERT(setup_actor != NULL); |
91 | *length= setup_actor->m_key.m_key_length; |
92 | result= setup_actor->m_key.m_hash_key; |
93 | return const_cast<uchar*> (reinterpret_cast<const uchar*> (result)); |
94 | } |
95 | C_MODE_END |
96 | |
97 | /** |
98 | Initialize the setup actor hash. |
99 | @return 0 on success |
100 | */ |
101 | int init_setup_actor_hash(void) |
102 | { |
103 | if ((! setup_actor_hash_inited) && (setup_actor_max > 0)) |
104 | { |
105 | lf_hash_init(&setup_actor_hash, sizeof(PFS_setup_actor*), LF_HASH_UNIQUE, |
106 | 0, 0, setup_actor_hash_get_key, &my_charset_bin); |
107 | /* setup_actor_hash.size= setup_actor_max; */ |
108 | setup_actor_hash_inited= true; |
109 | } |
110 | return 0; |
111 | } |
112 | |
113 | /** Cleanup the setup actor hash. */ |
114 | void cleanup_setup_actor_hash(void) |
115 | { |
116 | if (setup_actor_hash_inited) |
117 | { |
118 | lf_hash_destroy(&setup_actor_hash); |
119 | setup_actor_hash_inited= false; |
120 | } |
121 | } |
122 | |
123 | static LF_PINS* get_setup_actor_hash_pins(PFS_thread *thread) |
124 | { |
125 | if (unlikely(thread->m_setup_actor_hash_pins == NULL)) |
126 | { |
127 | if (! setup_actor_hash_inited) |
128 | return NULL; |
129 | thread->m_setup_actor_hash_pins= lf_hash_get_pins(&setup_actor_hash); |
130 | } |
131 | return thread->m_setup_actor_hash_pins; |
132 | } |
133 | |
134 | static void set_setup_actor_key(PFS_setup_actor_key *key, |
135 | const char *user, uint user_length, |
136 | const char *host, uint host_length, |
137 | const char *role, uint role_length) |
138 | { |
139 | DBUG_ASSERT(user_length <= USERNAME_LENGTH); |
140 | DBUG_ASSERT(host_length <= HOSTNAME_LENGTH); |
141 | |
142 | char *ptr= &key->m_hash_key[0]; |
143 | memcpy(ptr, user, user_length); |
144 | ptr+= user_length; |
145 | ptr[0]= 0; |
146 | ptr++; |
147 | memcpy(ptr, host, host_length); |
148 | ptr+= host_length; |
149 | ptr[0]= 0; |
150 | ptr++; |
151 | memcpy(ptr, role, role_length); |
152 | ptr+= role_length; |
153 | ptr[0]= 0; |
154 | ptr++; |
155 | key->m_key_length= (uint)(ptr - &key->m_hash_key[0]); |
156 | } |
157 | |
158 | int insert_setup_actor(const String *user, const String *host, const String *role) |
159 | { |
160 | if (setup_actor_max == 0) |
161 | return HA_ERR_RECORD_FILE_FULL; |
162 | |
163 | PFS_thread *thread= PFS_thread::get_current_thread(); |
164 | if (unlikely(thread == NULL)) |
165 | return HA_ERR_OUT_OF_MEM; |
166 | |
167 | LF_PINS *pins= get_setup_actor_hash_pins(thread); |
168 | if (unlikely(pins == NULL)) |
169 | return HA_ERR_OUT_OF_MEM; |
170 | |
171 | static uint PFS_ALIGNED setup_actor_monotonic_index= 0; |
172 | uint index; |
173 | uint attempts= 0; |
174 | PFS_setup_actor *pfs; |
175 | |
176 | while (++attempts <= setup_actor_max) |
177 | { |
178 | /* See create_mutex() */ |
179 | index= PFS_atomic::add_u32(& setup_actor_monotonic_index, 1) % setup_actor_max; |
180 | pfs= setup_actor_array + index; |
181 | |
182 | if (pfs->m_lock.is_free()) |
183 | { |
184 | if (pfs->m_lock.free_to_dirty()) |
185 | { |
186 | set_setup_actor_key(&pfs->m_key, |
187 | user->ptr(), user->length(), |
188 | host->ptr(), host->length(), |
189 | role->ptr(), role->length()); |
190 | pfs->m_username= &pfs->m_key.m_hash_key[0]; |
191 | pfs->m_username_length= user->length(); |
192 | pfs->m_hostname= pfs->m_username + pfs->m_username_length + 1; |
193 | pfs->m_hostname_length= host->length(); |
194 | pfs->m_rolename= pfs->m_hostname + pfs->m_hostname_length + 1; |
195 | pfs->m_rolename_length= role->length(); |
196 | |
197 | int res; |
198 | res= lf_hash_insert(&setup_actor_hash, pins, &pfs); |
199 | if (likely(res == 0)) |
200 | { |
201 | pfs->m_lock.dirty_to_allocated(); |
202 | return 0; |
203 | } |
204 | |
205 | pfs->m_lock.dirty_to_free(); |
206 | if (res > 0) |
207 | return HA_ERR_FOUND_DUPP_KEY; |
208 | return HA_ERR_OUT_OF_MEM; |
209 | } |
210 | } |
211 | } |
212 | |
213 | return HA_ERR_RECORD_FILE_FULL; |
214 | } |
215 | |
216 | int delete_setup_actor(const String *user, const String *host, const String *role) |
217 | { |
218 | PFS_thread *thread= PFS_thread::get_current_thread(); |
219 | if (unlikely(thread == NULL)) |
220 | return HA_ERR_OUT_OF_MEM; |
221 | |
222 | LF_PINS* pins= get_setup_actor_hash_pins(thread); |
223 | if (unlikely(pins == NULL)) |
224 | return HA_ERR_OUT_OF_MEM; |
225 | |
226 | PFS_setup_actor_key key; |
227 | set_setup_actor_key(&key, |
228 | user->ptr(), user->length(), |
229 | host->ptr(), host->length(), |
230 | role->ptr(), role->length()); |
231 | |
232 | PFS_setup_actor **entry; |
233 | entry= reinterpret_cast<PFS_setup_actor**> |
234 | (lf_hash_search(&setup_actor_hash, pins, key.m_hash_key, key.m_key_length)); |
235 | |
236 | if (entry && (entry != MY_ERRPTR)) |
237 | { |
238 | PFS_setup_actor *pfs= *entry; |
239 | lf_hash_delete(&setup_actor_hash, pins, key.m_hash_key, key.m_key_length); |
240 | pfs->m_lock.allocated_to_free(); |
241 | } |
242 | |
243 | lf_hash_search_unpin(pins); |
244 | |
245 | return 0; |
246 | } |
247 | |
248 | int reset_setup_actor() |
249 | { |
250 | PFS_thread *thread= PFS_thread::get_current_thread(); |
251 | if (unlikely(thread == NULL)) |
252 | return HA_ERR_OUT_OF_MEM; |
253 | |
254 | LF_PINS* pins= get_setup_actor_hash_pins(thread); |
255 | if (unlikely(pins == NULL)) |
256 | return HA_ERR_OUT_OF_MEM; |
257 | |
258 | PFS_setup_actor *pfs= setup_actor_array; |
259 | PFS_setup_actor *pfs_last= setup_actor_array + setup_actor_max; |
260 | |
261 | for ( ; pfs < pfs_last; pfs++) |
262 | { |
263 | if (pfs->m_lock.is_populated()) |
264 | { |
265 | lf_hash_delete(&setup_actor_hash, pins, |
266 | pfs->m_key.m_hash_key, pfs->m_key.m_key_length); |
267 | pfs->m_lock.allocated_to_free(); |
268 | } |
269 | } |
270 | |
271 | return 0; |
272 | } |
273 | |
274 | long setup_actor_count() |
275 | { |
276 | return setup_actor_hash.count; |
277 | } |
278 | |
279 | /* |
280 | - '%' should be replaced by NULL in table SETUP_ACTOR |
281 | - add an ENABLED column to include/exclude patterns, more flexible |
282 | - the principle is similar to SETUP_OBJECTS |
283 | */ |
284 | void lookup_setup_actor(PFS_thread *thread, |
285 | const char *user, uint user_length, |
286 | const char *host, uint host_length, |
287 | bool *enabled) |
288 | { |
289 | PFS_setup_actor_key key; |
290 | PFS_setup_actor **entry; |
291 | int i; |
292 | |
293 | LF_PINS* pins= get_setup_actor_hash_pins(thread); |
294 | if (unlikely(pins == NULL)) |
295 | { |
296 | *enabled= false; |
297 | return; |
298 | } |
299 | |
300 | for (i= 1; i<=4; i++) |
301 | { |
302 | /* |
303 | WL#988 Roles is not implemented, so we do not have a role name. |
304 | Looking up "%" in SETUP_ACTORS.ROLE. |
305 | */ |
306 | switch(i) |
307 | { |
308 | case 1: |
309 | set_setup_actor_key(&key, user, user_length, host, host_length, "%" , 1); |
310 | break; |
311 | case 2: |
312 | set_setup_actor_key(&key, user, user_length, "%" , 1, "%" , 1); |
313 | break; |
314 | case 3: |
315 | set_setup_actor_key(&key, "%" , 1, host, host_length, "%" , 1); |
316 | break; |
317 | case 4: |
318 | set_setup_actor_key(&key, "%" , 1, "%" , 1, "%" , 1); |
319 | break; |
320 | } |
321 | entry= reinterpret_cast<PFS_setup_actor**> |
322 | (lf_hash_search(&setup_actor_hash, pins, key.m_hash_key, key.m_key_length)); |
323 | |
324 | if (entry && (entry != MY_ERRPTR)) |
325 | { |
326 | lf_hash_search_unpin(pins); |
327 | *enabled= true; |
328 | return; |
329 | } |
330 | |
331 | lf_hash_search_unpin(pins); |
332 | } |
333 | *enabled= false; |
334 | return; |
335 | } |
336 | |
337 | /** @} */ |
338 | |