MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
pfs_setup_object.cc
Go to the documentation of this file.
1 /* Copyright (c) 2010, 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
14  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
15 
21 #include "my_global.h"
22 #include "my_sys.h"
23 #include "my_base.h"
24 #include "sql_string.h"
25 #include "pfs.h"
26 #include "pfs_stat.h"
27 #include "pfs_instr.h"
28 #include "pfs_setup_object.h"
29 #include "pfs_global.h"
30 
36 uint setup_objects_version= 0;
37 
38 ulong setup_object_max;
39 
40 PFS_setup_object *setup_object_array= NULL;
41 
42 LF_HASH setup_object_hash;
43 static bool setup_object_hash_inited= false;
44 
51 {
52  setup_object_max= param->m_setup_object_sizing;
53 
54  setup_object_array= NULL;
55 
56  if (setup_object_max > 0)
57  {
58  setup_object_array= PFS_MALLOC_ARRAY(setup_object_max, PFS_setup_object,
59  MYF(MY_ZEROFILL));
60  if (unlikely(setup_object_array == NULL))
61  return 1;
62  }
63 
64  return 0;
65 }
66 
69 {
70  pfs_free(setup_object_array);
71  setup_object_array= NULL;
72  setup_object_max= 0;
73 }
74 
75 C_MODE_START
76 static uchar *setup_object_hash_get_key(const uchar *entry, size_t *length,
77  my_bool)
78 {
79  const PFS_setup_object * const *typed_entry;
80  const PFS_setup_object *setup_object;
81  const void *result;
82  typed_entry= reinterpret_cast<const PFS_setup_object* const *> (entry);
83  DBUG_ASSERT(typed_entry != NULL);
84  setup_object= *typed_entry;
85  DBUG_ASSERT(setup_object != NULL);
86  *length= setup_object->m_key.m_key_length;
87  result= setup_object->m_key.m_hash_key;
88  return const_cast<uchar*> (reinterpret_cast<const uchar*> (result));
89 }
90 C_MODE_END
91 
97 {
98  if ((! setup_object_hash_inited) && (setup_object_max > 0))
99  {
100  lf_hash_init(&setup_object_hash, sizeof(PFS_setup_object*), LF_HASH_UNIQUE,
101  0, 0, setup_object_hash_get_key, &my_charset_bin);
102  setup_object_hash.size= setup_object_max;
103  setup_object_hash_inited= true;
104  }
105  return 0;
106 }
107 
110 {
111  if (setup_object_hash_inited)
112  {
113  lf_hash_destroy(&setup_object_hash);
114  setup_object_hash_inited= false;
115  }
116 }
117 
118 static LF_PINS* get_setup_object_hash_pins(PFS_thread *thread)
119 {
120  if (unlikely(thread->m_setup_object_hash_pins == NULL))
121  {
122  if (! setup_object_hash_inited)
123  return NULL;
124  thread->m_setup_object_hash_pins= lf_hash_get_pins(&setup_object_hash);
125  }
126  return thread->m_setup_object_hash_pins;
127 }
128 
129 static void set_setup_object_key(PFS_setup_object_key *key,
130  enum_object_type object_type,
131  const char *schema, uint schema_length,
132  const char *object, uint object_length)
133 {
134  DBUG_ASSERT(schema_length <= NAME_LEN);
135  DBUG_ASSERT(object_length <= NAME_LEN);
136 
137  char *ptr= &key->m_hash_key[0];
138  ptr[0]= (char) object_type;
139  ptr++;
140  memcpy(ptr, schema, schema_length);
141  ptr+= schema_length;
142  ptr[0]= 0;
143  ptr++;
144  memcpy(ptr, object, object_length);
145  ptr+= object_length;
146  ptr[0]= 0;
147  ptr++;
148  key->m_key_length= ptr - &key->m_hash_key[0];
149 }
150 
151 int insert_setup_object(enum_object_type object_type, const String *schema,
152  const String *object, bool enabled, bool timed)
153 {
154  if (setup_object_max == 0)
155  return HA_ERR_RECORD_FILE_FULL;
156 
157  PFS_thread *thread= PFS_thread::get_current_thread();
158  if (unlikely(thread == NULL))
159  return HA_ERR_OUT_OF_MEM;
160 
161  LF_PINS* pins= get_setup_object_hash_pins(thread);
162  if (unlikely(pins == NULL))
163  return HA_ERR_OUT_OF_MEM;
164 
165  static uint PFS_ALIGNED setup_object_monotonic_index= 0;
166  uint index;
167  uint attempts= 0;
168  PFS_setup_object *pfs;
169 
170  while (++attempts <= setup_object_max)
171  {
172  /* See create_mutex() */
173  index= PFS_atomic::add_u32(& setup_object_monotonic_index, 1) % setup_object_max;
174  pfs= setup_object_array + index;
175 
176  if (pfs->m_lock.is_free())
177  {
178  if (pfs->m_lock.free_to_dirty())
179  {
180  set_setup_object_key(&pfs->m_key, object_type,
181  schema->ptr(), schema->length(),
182  object->ptr(), object->length());
183  pfs->m_schema_name= &pfs->m_key.m_hash_key[1];
184  pfs->m_schema_name_length= schema->length();
185  pfs->m_object_name= pfs->m_schema_name + pfs->m_schema_name_length + 1;
186  pfs->m_object_name_length= object->length();
187  pfs->m_enabled= enabled;
188  pfs->m_timed= timed;
189 
190  int res;
191  res= lf_hash_insert(&setup_object_hash, pins, &pfs);
192  if (likely(res == 0))
193  {
194  pfs->m_lock.dirty_to_allocated();
195  setup_objects_version++;
196  return 0;
197  }
198 
199  pfs->m_lock.dirty_to_free();
200  if (res > 0)
201  return HA_ERR_FOUND_DUPP_KEY;
202  /* OOM in lf_hash_insert */
203  return HA_ERR_OUT_OF_MEM;
204  }
205  }
206  }
207 
208  return HA_ERR_RECORD_FILE_FULL;
209 }
210 
211 int delete_setup_object(enum_object_type object_type, const String *schema,
212  const String *object)
213 {
214  PFS_thread *thread= PFS_thread::get_current_thread();
215  if (unlikely(thread == NULL))
216  return HA_ERR_OUT_OF_MEM;
217 
218  LF_PINS* pins= get_setup_object_hash_pins(thread);
219  if (unlikely(pins == NULL))
220  return HA_ERR_OUT_OF_MEM;
221 
223  set_setup_object_key(&key, object_type,
224  schema->ptr(), schema->length(),
225  object->ptr(), object->length());
226 
228  entry= reinterpret_cast<PFS_setup_object**>
229  (lf_hash_search(&setup_object_hash, pins, key.m_hash_key, key.m_key_length));
230 
231  if (entry && (entry != MY_ERRPTR))
232  {
233  PFS_setup_object *pfs= *entry;
234  lf_hash_delete(&setup_object_hash, pins, key.m_hash_key, key.m_key_length);
235  pfs->m_lock.allocated_to_free();
236  }
237 
238  lf_hash_search_unpin(pins);
239 
240  setup_objects_version++;
241  return 0;
242 }
243 
244 int reset_setup_object()
245 {
246  PFS_thread *thread= PFS_thread::get_current_thread();
247  if (unlikely(thread == NULL))
248  return HA_ERR_OUT_OF_MEM;
249 
250  LF_PINS* pins= get_setup_object_hash_pins(thread);
251  if (unlikely(pins == NULL))
252  return HA_ERR_OUT_OF_MEM;
253 
254  PFS_setup_object *pfs= setup_object_array;
255  PFS_setup_object *pfs_last= setup_object_array + setup_object_max;
256 
257  for ( ; pfs < pfs_last; pfs++)
258  {
259  if (pfs->m_lock.is_populated())
260  {
261  lf_hash_delete(&setup_object_hash, pins,
262  pfs->m_key.m_hash_key, pfs->m_key.m_key_length);
263  pfs->m_lock.allocated_to_free();
264  }
265  }
266 
267  setup_objects_version++;
268  return 0;
269 }
270 
271 long setup_object_count()
272 {
273  return setup_object_hash.count;
274 }
275 
276 void lookup_setup_object(PFS_thread *thread,
277  enum_object_type object_type,
278  const char *schema_name, int schema_name_length,
279  const char *object_name, int object_name_length,
280  bool *enabled, bool *timed)
281 {
284  PFS_setup_object *pfs;
285  int i;
286 
287  /*
288  The table io instrumentation uses "TABLE" and "TEMPORARY TABLE".
289  SETUP_OBJECT uses "TABLE" for both concepts.
290  There is no way to provide a different setup for:
291  - TABLE foo.bar
292  - TEMPORARY TABLE foo.bar
293  */
294  DBUG_ASSERT(object_type != OBJECT_TYPE_TEMPORARY_TABLE);
295 
296  LF_PINS* pins= get_setup_object_hash_pins(thread);
297  if (unlikely(pins == NULL))
298  {
299  *enabled= false;
300  *timed= false;
301  return;
302  }
303 
304  for (i= 1; i<=3; i++)
305  {
306  switch(i)
307  {
308  case 1:
309  /* Lookup OBJECT_TYPE + OBJECT_SCHEMA + OBJECT_NAME in SETUP_OBJECTS */
310  set_setup_object_key(&key,
311  object_type,
312  schema_name, schema_name_length,
313  object_name, object_name_length);
314  break;
315  case 2:
316  /* Lookup OBJECT_TYPE + OBJECT_SCHEMA + "%" in SETUP_OBJECTS */
317  set_setup_object_key(&key,
318  object_type,
319  schema_name, schema_name_length, "%", 1);
320  break;
321  case 3:
322  /* Lookup OBJECT_TYPE + "%" + "%" in SETUP_OBJECTS */
323  set_setup_object_key(&key, object_type, "%", 1, "%", 1);
324  break;
325  }
326  entry= reinterpret_cast<PFS_setup_object**>
327  (lf_hash_search(&setup_object_hash, pins, key.m_hash_key, key.m_key_length));
328 
329  if (entry && (entry != MY_ERRPTR))
330  {
331  pfs= *entry;
332  *enabled= pfs->m_enabled;
333  *timed= pfs->m_timed;
334  lf_hash_search_unpin(pins);
335  return;
336  }
337 
338  lf_hash_search_unpin(pins);
339  }
340  *enabled= false;
341  *timed= false;
342  return;
343 }
344