MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
pfs_host.cc
Go to the documentation of this file.
1 /* Copyright (c) 2010, 2013, 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 "pfs.h"
24 #include "pfs_stat.h"
25 #include "pfs_instr.h"
26 #include "pfs_setup_actor.h"
27 #include "pfs_host.h"
28 #include "pfs_global.h"
29 #include "pfs_instr_class.h"
30 
36 ulong host_max;
37 ulong host_lost;
38 
39 PFS_host *host_array= NULL;
40 
41 static PFS_single_stat *host_instr_class_waits_array= NULL;
42 static PFS_stage_stat *host_instr_class_stages_array= NULL;
43 static PFS_statement_stat *host_instr_class_statements_array= NULL;
44 
45 LF_HASH host_hash;
46 static bool host_hash_inited= false;
47 
53 int init_host(const PFS_global_param *param)
54 {
55  uint index;
56 
57  host_max= param->m_host_sizing;
58 
59  host_array= NULL;
60  host_instr_class_waits_array= NULL;
61  host_instr_class_stages_array= NULL;
62  host_instr_class_statements_array= NULL;
63  uint waits_sizing= host_max * wait_class_max;
64  uint stages_sizing= host_max * stage_class_max;
65  uint statements_sizing= host_max * statement_class_max;
66 
67  if (host_max > 0)
68  {
69  host_array= PFS_MALLOC_ARRAY(host_max, PFS_host,
70  MYF(MY_ZEROFILL));
71  if (unlikely(host_array == NULL))
72  return 1;
73  }
74 
75  if (waits_sizing > 0)
76  {
77  host_instr_class_waits_array=
79  if (unlikely(host_instr_class_waits_array == NULL))
80  return 1;
81  }
82 
83  if (stages_sizing > 0)
84  {
85  host_instr_class_stages_array=
87  if (unlikely(host_instr_class_stages_array == NULL))
88  return 1;
89  }
90 
91  if (statements_sizing > 0)
92  {
93  host_instr_class_statements_array=
95  if (unlikely(host_instr_class_statements_array == NULL))
96  return 1;
97  }
98 
99  for (index= 0; index < host_max; index++)
100  {
101  host_array[index].m_instr_class_waits_stats=
102  &host_instr_class_waits_array[index * wait_class_max];
103  host_array[index].m_instr_class_stages_stats=
104  &host_instr_class_stages_array[index * stage_class_max];
106  &host_instr_class_statements_array[index * statement_class_max];
107  }
108 
109  return 0;
110 }
111 
113 void cleanup_host(void)
114 {
115  pfs_free(host_array);
116  host_array= NULL;
117  pfs_free(host_instr_class_waits_array);
118  host_instr_class_waits_array= NULL;
119  pfs_free(host_instr_class_stages_array);
120  host_instr_class_stages_array= NULL;
121  pfs_free(host_instr_class_statements_array);
122  host_instr_class_statements_array= NULL;
123  host_max= 0;
124 }
125 
126 C_MODE_START
127 static uchar *host_hash_get_key(const uchar *entry, size_t *length,
128  my_bool)
129 {
130  const PFS_host * const *typed_entry;
131  const PFS_host *host;
132  const void *result;
133  typed_entry= reinterpret_cast<const PFS_host* const *> (entry);
134  DBUG_ASSERT(typed_entry != NULL);
135  host= *typed_entry;
136  DBUG_ASSERT(host != NULL);
137  *length= host->m_key.m_key_length;
138  result= host->m_key.m_hash_key;
139  return const_cast<uchar*> (reinterpret_cast<const uchar*> (result));
140 }
141 C_MODE_END
142 
147 int init_host_hash(void)
148 {
149  if ((! host_hash_inited) && (host_max > 0))
150  {
151  lf_hash_init(&host_hash, sizeof(PFS_host*), LF_HASH_UNIQUE,
152  0, 0, host_hash_get_key, &my_charset_bin);
153  host_hash.size= host_max;
154  host_hash_inited= true;
155  }
156  return 0;
157 }
158 
161 {
162  if (host_hash_inited)
163  {
164  lf_hash_destroy(&host_hash);
165  host_hash_inited= false;
166  }
167 }
168 
169 static LF_PINS* get_host_hash_pins(PFS_thread *thread)
170 {
171  if (unlikely(thread->m_host_hash_pins == NULL))
172  {
173  if (! host_hash_inited)
174  return NULL;
175  thread->m_host_hash_pins= lf_hash_get_pins(&host_hash);
176  }
177  return thread->m_host_hash_pins;
178 }
179 
180 static void set_host_key(PFS_host_key *key,
181  const char *host, uint host_length)
182 {
183  DBUG_ASSERT(host_length <= HOSTNAME_LENGTH);
184 
185  char *ptr= &key->m_hash_key[0];
186  if (host_length > 0)
187  {
188  memcpy(ptr, host, host_length);
189  ptr+= host_length;
190  }
191  ptr[0]= 0;
192  ptr++;
193  key->m_key_length= ptr - &key->m_hash_key[0];
194 }
195 
196 PFS_host *find_or_create_host(PFS_thread *thread,
197  const char *hostname, uint hostname_length)
198 {
199  if (host_max == 0)
200  {
201  host_lost++;
202  return NULL;
203  }
204 
205  LF_PINS *pins= get_host_hash_pins(thread);
206  if (unlikely(pins == NULL))
207  {
208  host_lost++;
209  return NULL;
210  }
211 
212  PFS_host_key key;
213  set_host_key(&key, hostname, hostname_length);
214 
215  PFS_host **entry;
216  uint retry_count= 0;
217  const uint retry_max= 3;
218 
219 search:
220  entry= reinterpret_cast<PFS_host**>
221  (lf_hash_search(&host_hash, pins,
222  key.m_hash_key, key.m_key_length));
223  if (entry && (entry != MY_ERRPTR))
224  {
225  PFS_host *pfs;
226  pfs= *entry;
227  pfs->inc_refcount();
228  lf_hash_search_unpin(pins);
229  return pfs;
230  }
231 
232  lf_hash_search_unpin(pins);
233 
234  PFS_scan scan;
235  uint random= randomized_index(hostname, host_max);
236 
237  for (scan.init(random, host_max);
238  scan.has_pass();
239  scan.next_pass())
240  {
241  PFS_host *pfs= host_array + scan.first();
242  PFS_host *pfs_last= host_array + scan.last();
243  for ( ; pfs < pfs_last; pfs++)
244  {
245  if (pfs->m_lock.is_free())
246  {
247  if (pfs->m_lock.free_to_dirty())
248  {
249  pfs->m_key= key;
250  if (hostname_length > 0)
251  pfs->m_hostname= &pfs->m_key.m_hash_key[0];
252  else
253  pfs->m_hostname= NULL;
254  pfs->m_hostname_length= hostname_length;
255 
256  pfs->init_refcount();
257  pfs->reset_stats();
258  pfs->m_disconnected_count= 0;
259 
260  int res;
261  res= lf_hash_insert(&host_hash, pins, &pfs);
262  if (likely(res == 0))
263  {
264  pfs->m_lock.dirty_to_allocated();
265  return pfs;
266  }
267 
268  pfs->m_lock.dirty_to_free();
269 
270  if (res > 0)
271  {
272  if (++retry_count > retry_max)
273  {
274  host_lost++;
275  return NULL;
276  }
277  goto search;
278  }
279 
280  host_lost++;
281  return NULL;
282  }
283  }
284  }
285  }
286 
287  host_lost++;
288  return NULL;
289 }
290 
291 void PFS_host::aggregate()
292 {
293  aggregate_waits();
294  aggregate_stages();
295  aggregate_statements();
296  aggregate_stats();
297 }
298 
299 void PFS_host::aggregate_waits()
300 {
301  /* No parent to aggregate to, clean the stats */
303 }
304 
305 void PFS_host::aggregate_stages()
306 {
307  /*
308  Aggregate EVENTS_STAGES_SUMMARY_BY_HOST_BY_EVENT_NAME to:
309  - EVENTS_STAGES_SUMMARY_GLOBAL_BY_EVENT_NAME
310  */
311  aggregate_all_stages(m_instr_class_stages_stats,
312  global_instr_class_stages_array);
313 }
314 
315 void PFS_host::aggregate_statements()
316 {
317  /*
318  Aggregate EVENTS_STATEMENTS_SUMMARY_BY_HOST_BY_EVENT_NAME to:
319  - EVENTS_STATEMENTS_SUMMARY_GLOBAL_BY_EVENT_NAME
320  */
321  aggregate_all_statements(m_instr_class_statements_stats,
322  global_instr_class_statements_array);
323 }
324 
325 void PFS_host::aggregate_stats()
326 {
327  /* No parent to aggregate to, clean the stats */
328  m_disconnected_count= 0;
329 }
330 
331 void PFS_host::release()
332 {
333  dec_refcount();
334 }
335 
336 PFS_host *sanitize_host(PFS_host *unsafe)
337 {
338  if ((&host_array[0] <= unsafe) &&
339  (unsafe < &host_array[host_max]))
340  return unsafe;
341  return NULL;
342 }
343 
344 void purge_host(PFS_thread *thread, PFS_host *host)
345 {
346  LF_PINS *pins= get_host_hash_pins(thread);
347  if (unlikely(pins == NULL))
348  return;
349 
350  PFS_host **entry;
351  entry= reinterpret_cast<PFS_host**>
352  (lf_hash_search(&host_hash, pins,
353  host->m_key.m_hash_key, host->m_key.m_key_length));
354  if (entry && (entry != MY_ERRPTR))
355  {
356  PFS_host *pfs;
357  pfs= *entry;
358  DBUG_ASSERT(pfs == host);
359  if (host->get_refcount() == 0)
360  {
361  lf_hash_delete(&host_hash, pins,
362  host->m_key.m_hash_key, host->m_key.m_key_length);
363  host->m_lock.allocated_to_free();
364  }
365  }
366 
367  lf_hash_search_unpin(pins);
368 }
369 
371 void purge_all_host(void)
372 {
373  PFS_thread *thread= PFS_thread::get_current_thread();
374  if (unlikely(thread == NULL))
375  return;
376 
377  PFS_host *pfs= host_array;
378  PFS_host *pfs_last= host_array + host_max;
379 
380  for ( ; pfs < pfs_last; pfs++)
381  {
382  if (pfs->m_lock.is_populated())
383  {
384  pfs->aggregate();
385  if (pfs->get_refcount() == 0)
386  purge_host(thread, pfs);
387  }
388  }
389 }
390