MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
pfs_setup_actor.cc
Go to the documentation of this file.
1 /* Copyright (c) 2010, 2011, 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 
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 
37 
44 
48 static bool setup_actor_hash_inited= false;
49 
56 {
58 
59  setup_actor_array= NULL;
60 
61  if (setup_actor_max > 0)
62  {
64  MYF(MY_ZEROFILL));
65  if (unlikely(setup_actor_array == NULL))
66  return 1;
67  }
68 
69  return 0;
70 }
71 
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 
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 
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= 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 
227  set_setup_actor_key(&key,
228  user->ptr(), user->length(),
229  host->ptr(), host->length(),
230  role->ptr(), role->length());
231 
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 
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 {
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