MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ut0mem.cc
Go to the documentation of this file.
1 /*****************************************************************************
2 
3 Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved.
4 
5 This program is free software; you can redistribute it and/or modify it under
6 the terms of the GNU General Public License as published by the Free Software
7 Foundation; version 2 of the License.
8 
9 This program is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12 
13 You should have received a copy of the GNU General Public License along with
14 this program; if not, write to the Free Software Foundation, Inc.,
15 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
16 
17 *****************************************************************************/
18 
19 /********************************************************************/
26 #include "ut0mem.h"
27 
28 #ifdef UNIV_NONINL
29 #include "ut0mem.ic"
30 #endif
31 
32 #ifndef UNIV_HOTBACKUP
33 # include "os0thread.h"
34 # include "srv0srv.h"
35 
36 #include <stdlib.h>
37 
41 UNIV_INTERN ulint ut_total_allocated_memory = 0;
42 
45 
46 #ifdef UNIV_PFS_MUTEX
47 /* Key to register server_mutex with performance schema */
48 UNIV_INTERN mysql_pfs_key_t ut_list_mutex_key;
49 #endif
50 
53  UT_LIST_NODE_T(ut_mem_block_t) mem_block_list;
55  ulint size;
56  ulint magic_n;
57 };
58 
61 #define UT_MEM_MAGIC_N 1601650166
62 
65 static UT_LIST_BASE_NODE_T(ut_mem_block_t) ut_mem_block_list;
66 
68 static ibool ut_mem_block_list_inited = FALSE;
69 
72 static ulint* ut_mem_null_ptr = NULL;
73 
74 /**********************************************************************/
76 UNIV_INTERN
77 void
79 /*=============*/
80 {
81  ut_a(!ut_mem_block_list_inited);
82  os_fast_mutex_init(ut_list_mutex_key, &ut_list_mutex);
83  UT_LIST_INIT(ut_mem_block_list);
84  ut_mem_block_list_inited = TRUE;
85 }
86 #endif /* !UNIV_HOTBACKUP */
87 
88 /**********************************************************************/
91 UNIV_INTERN
92 void*
94 /*==========*/
95  ulint n,
96  ibool assert_on_error)
98 {
99 #ifndef UNIV_HOTBACKUP
100  ulint retry_count;
101  void* ret;
102 
103  if (UNIV_LIKELY(srv_use_sys_malloc)) {
104  ret = malloc(n);
105  ut_a(ret || !assert_on_error);
106 
107  return(ret);
108  }
109 
110  ut_ad((sizeof(ut_mem_block_t) % 8) == 0); /* check alignment ok */
111  ut_a(ut_mem_block_list_inited);
112 
113  retry_count = 0;
114 retry:
115  os_fast_mutex_lock(&ut_list_mutex);
116 
117  ret = malloc(n + sizeof(ut_mem_block_t));
118 
119  if (ret == NULL && retry_count < 60) {
120  if (retry_count == 0) {
121  ut_print_timestamp(stderr);
122 
123  fprintf(stderr,
124  " InnoDB: Error: cannot allocate"
125  " %lu bytes of\n"
126  "InnoDB: memory with malloc!"
127  " Total allocated memory\n"
128  "InnoDB: by InnoDB %lu bytes."
129  " Operating system errno: %lu\n"
130  "InnoDB: Check if you should"
131  " increase the swap file or\n"
132  "InnoDB: ulimits of your operating system.\n"
133  "InnoDB: On FreeBSD check you"
134  " have compiled the OS with\n"
135  "InnoDB: a big enough maximum process size.\n"
136  "InnoDB: Note that in most 32-bit"
137  " computers the process\n"
138  "InnoDB: memory space is limited"
139  " to 2 GB or 4 GB.\n"
140  "InnoDB: We keep retrying"
141  " the allocation for 60 seconds...\n",
142  (ulong) n, (ulong) ut_total_allocated_memory,
143 #ifdef __WIN__
144  (ulong) GetLastError()
145 #else
146  (ulong) errno
147 #endif
148  );
149  }
150 
151  os_fast_mutex_unlock(&ut_list_mutex);
152 
153  /* Sleep for a second and retry the allocation; maybe this is
154  just a temporary shortage of memory */
155 
156  os_thread_sleep(1000000);
157 
158  retry_count++;
159 
160  goto retry;
161  }
162 
163  if (ret == NULL) {
164  /* Flush stderr to make more probable that the error
165  message gets in the error file before we generate a seg
166  fault */
167 
168  fflush(stderr);
169 
170  os_fast_mutex_unlock(&ut_list_mutex);
171 
172  /* Make an intentional seg fault so that we get a stack
173  trace */
174  if (assert_on_error) {
175  ut_print_timestamp(stderr);
176 
177  fprintf(stderr,
178  " InnoDB: We now intentionally"
179  " generate a seg fault so that\n"
180  "InnoDB: on Linux we get a stack trace.\n");
181 
182  if (*ut_mem_null_ptr) ut_mem_null_ptr = 0;
183  } else {
184  return(NULL);
185  }
186  }
187 
188  UNIV_MEM_ALLOC(ret, n + sizeof(ut_mem_block_t));
189 
190  ((ut_mem_block_t*) ret)->size = n + sizeof(ut_mem_block_t);
191  ((ut_mem_block_t*) ret)->magic_n = UT_MEM_MAGIC_N;
192 
194 
195  UT_LIST_ADD_FIRST(mem_block_list, ut_mem_block_list,
196  ((ut_mem_block_t*) ret));
197  os_fast_mutex_unlock(&ut_list_mutex);
198 
199  return((void*)((byte*) ret + sizeof(ut_mem_block_t)));
200 #else /* !UNIV_HOTBACKUP */
201  void* ret = malloc(n);
202  ut_a(ret || !assert_on_error);
203 
204  return(ret);
205 #endif /* !UNIV_HOTBACKUP */
206 }
207 
208 /**********************************************************************/
211 UNIV_INTERN
212 void
214 /*====*/
215  void* ptr)
216 {
217 #ifndef UNIV_HOTBACKUP
219 
220  if (ptr == NULL) {
221  return;
222  } else if (UNIV_LIKELY(srv_use_sys_malloc)) {
223  free(ptr);
224  return;
225  }
226 
227  block = (ut_mem_block_t*)((byte*) ptr - sizeof(ut_mem_block_t));
228 
229  os_fast_mutex_lock(&ut_list_mutex);
230 
231  ut_a(block->magic_n == UT_MEM_MAGIC_N);
233 
235 
236  UT_LIST_REMOVE(mem_block_list, ut_mem_block_list, block);
237  free(block);
238 
239  os_fast_mutex_unlock(&ut_list_mutex);
240 #else /* !UNIV_HOTBACKUP */
241  free(ptr);
242 #endif /* !UNIV_HOTBACKUP */
243 }
244 
245 #ifndef UNIV_HOTBACKUP
246 /**********************************************************************/
271 UNIV_INTERN
272 void*
274 /*=======*/
275  void* ptr,
276  ulint size)
277 {
279  ulint old_size;
280  ulint min_size;
281  void* new_ptr;
282 
283  if (UNIV_LIKELY(srv_use_sys_malloc)) {
284  return(realloc(ptr, size));
285  }
286 
287  if (ptr == NULL) {
288 
289  return(ut_malloc(size));
290  }
291 
292  if (size == 0) {
293  ut_free(ptr);
294 
295  return(NULL);
296  }
297 
298  block = (ut_mem_block_t*)((byte*) ptr - sizeof(ut_mem_block_t));
299 
300  ut_a(block->magic_n == UT_MEM_MAGIC_N);
301 
302  old_size = block->size - sizeof(ut_mem_block_t);
303 
304  if (size < old_size) {
305  min_size = size;
306  } else {
307  min_size = old_size;
308  }
309 
310  new_ptr = ut_malloc(size);
311 
312  if (new_ptr == NULL) {
313 
314  return(NULL);
315  }
316 
317  /* Copy the old data from ptr */
318  ut_memcpy(new_ptr, ptr, min_size);
319 
320  ut_free(ptr);
321 
322  return(new_ptr);
323 }
324 
325 /**********************************************************************/
327 UNIV_INTERN
328 void
330 /*=================*/
331 {
333 
334  ut_a(ut_mem_block_list_inited);
335  ut_mem_block_list_inited = FALSE;
336  os_fast_mutex_free(&ut_list_mutex);
337 
338  while ((block = UT_LIST_GET_FIRST(ut_mem_block_list))) {
339 
340  ut_a(block->magic_n == UT_MEM_MAGIC_N);
342 
344 
345  UT_LIST_REMOVE(mem_block_list, ut_mem_block_list, block);
346  free(block);
347  }
348 
349  if (ut_total_allocated_memory != 0) {
350  fprintf(stderr,
351  "InnoDB: Warning: after shutdown"
352  " total allocated memory is %lu\n",
353  (ulong) ut_total_allocated_memory);
354  }
355 
356  ut_mem_block_list_inited = FALSE;
357 }
358 #endif /* !UNIV_HOTBACKUP */
359 
360 /**********************************************************************/
365 UNIV_INTERN
366 ulint
368 /*=======*/
369  char* dst,
370  const char* src,
371  ulint size)
372 {
373  ulint src_size = strlen(src);
374 
375  if (size != 0) {
376  ulint n = ut_min(src_size, size - 1);
377 
378  memcpy(dst, src, n);
379  dst[n] = '\0';
380  }
381 
382  return(src_size);
383 }
384 
385 /**********************************************************************/
389 UNIV_INTERN
390 ulint
392 /*===========*/
393  char* dst,
394  const char* src,
395  ulint size)
396 {
397  ulint src_size = strlen(src);
398 
399  if (size != 0) {
400  ulint n = ut_min(src_size, size - 1);
401 
402  memcpy(dst, src + src_size - n, n + 1);
403  }
404 
405  return(src_size);
406 }
407 
408 #ifndef UNIV_HOTBACKUP
409 /**********************************************************************/
413 UNIV_INTERN
414 ulint
416 /*========*/
417  const char* s1,
418  const char* s2)
419 {
420  ulint count = 0;
421  ulint len = strlen(s2);
422 
423  if (len == 0) {
424 
425  return(0);
426  }
427 
428  for (;;) {
429  s1 = strstr(s1, s2);
430 
431  if (!s1) {
432 
433  break;
434  }
435 
436  count++;
437  s1 += len;
438  }
439 
440  return(count);
441 }
442 
443 /********************************************************************
444 Concatenate 3 strings.*/
445 
446 char*
447 ut_str3cat(
448 /*=======*/
449  /* out, own: concatenated string, must be
450  freed with mem_free() */
451  const char* s1, /* in: string 1 */
452  const char* s2, /* in: string 2 */
453  const char* s3) /* in: string 3 */
454 {
455  char* s;
456  ulint s1_len = strlen(s1);
457  ulint s2_len = strlen(s2);
458  ulint s3_len = strlen(s3);
459 
460  s = static_cast<char*>(mem_alloc(s1_len + s2_len + s3_len + 1));
461 
462  memcpy(s, s1, s1_len);
463  memcpy(s + s1_len, s2, s2_len);
464  memcpy(s + s1_len + s2_len, s3, s3_len);
465 
466  s[s1_len + s2_len + s3_len] = '\0';
467 
468  return(s);
469 }
470 /**********************************************************************/
474 UNIV_INTERN
475 char*
477 /*==========*/
478  const char* str,
479  const char* s1,
480  const char* s2)
481 {
482  char* new_str;
483  char* ptr;
484  const char* str_end;
485  ulint str_len = strlen(str);
486  ulint s1_len = strlen(s1);
487  ulint s2_len = strlen(s2);
488  ulint count = 0;
489  int len_delta = (int) s2_len - (int) s1_len;
490 
491  str_end = str + str_len;
492 
493  if (len_delta <= 0) {
494  len_delta = 0;
495  } else {
496  count = ut_strcount(str, s1);
497  }
498 
499  new_str = static_cast<char*>(
500  mem_alloc(str_len + count * len_delta + 1));
501 
502  ptr = new_str;
503 
504  while (str) {
505  const char* next = strstr(str, s1);
506 
507  if (!next) {
508  next = str_end;
509  }
510 
511  memcpy(ptr, str, next - str);
512  ptr += next - str;
513 
514  if (next == str_end) {
515 
516  break;
517  }
518 
519  memcpy(ptr, s2, s2_len);
520  ptr += s2_len;
521 
522  str = next + s1_len;
523  }
524 
525  *ptr = '\0';
526 
527  return(new_str);
528 }
529 
530 #ifdef UNIV_COMPILE_TEST_FUNCS
531 
532 void
533 test_ut_str_sql_format()
534 {
535  char buf[128];
536  ulint ret;
537 
538 #define CALL_AND_TEST(str, str_len, buf, buf_size, ret_expected, buf_expected)\
539  do {\
540  ibool ok = TRUE;\
541  memset(buf, 'x', 10);\
542  buf[10] = '\0';\
543  fprintf(stderr, "TESTING \"%s\", %lu, %lu\n",\
544  str, (ulint) str_len, (ulint) buf_size);\
545  ret = ut_str_sql_format(str, str_len, buf, buf_size);\
546  if (ret != ret_expected) {\
547  fprintf(stderr, "expected ret %lu, got %lu\n",\
548  (ulint) ret_expected, ret);\
549  ok = FALSE;\
550  }\
551  if (strcmp((char*) buf, buf_expected) != 0) {\
552  fprintf(stderr, "expected buf \"%s\", got \"%s\"\n",\
553  buf_expected, buf);\
554  ok = FALSE;\
555  }\
556  if (ok) {\
557  fprintf(stderr, "OK: %lu, \"%s\"\n\n",\
558  (ulint) ret, buf);\
559  } else {\
560  return;\
561  }\
562  } while (0)
563 
564  CALL_AND_TEST("abcd", 4, buf, 0, 0, "xxxxxxxxxx");
565 
566  CALL_AND_TEST("abcd", 4, buf, 1, 1, "");
567 
568  CALL_AND_TEST("abcd", 4, buf, 2, 1, "");
569 
570  CALL_AND_TEST("abcd", 0, buf, 3, 3, "''");
571  CALL_AND_TEST("abcd", 1, buf, 3, 1, "");
572  CALL_AND_TEST("abcd", 2, buf, 3, 1, "");
573  CALL_AND_TEST("abcd", 3, buf, 3, 1, "");
574  CALL_AND_TEST("abcd", 4, buf, 3, 1, "");
575 
576  CALL_AND_TEST("abcd", 0, buf, 4, 3, "''");
577  CALL_AND_TEST("abcd", 1, buf, 4, 4, "'a'");
578  CALL_AND_TEST("abcd", 2, buf, 4, 4, "'a'");
579  CALL_AND_TEST("abcd", 3, buf, 4, 4, "'a'");
580  CALL_AND_TEST("abcd", 4, buf, 4, 4, "'a'");
581  CALL_AND_TEST("abcde", 5, buf, 4, 4, "'a'");
582  CALL_AND_TEST("'", 1, buf, 4, 3, "''");
583  CALL_AND_TEST("''", 2, buf, 4, 3, "''");
584  CALL_AND_TEST("a'", 2, buf, 4, 4, "'a'");
585  CALL_AND_TEST("'a", 2, buf, 4, 3, "''");
586  CALL_AND_TEST("ab", 2, buf, 4, 4, "'a'");
587 
588  CALL_AND_TEST("abcdef", 0, buf, 5, 3, "''");
589  CALL_AND_TEST("abcdef", 1, buf, 5, 4, "'a'");
590  CALL_AND_TEST("abcdef", 2, buf, 5, 5, "'ab'");
591  CALL_AND_TEST("abcdef", 3, buf, 5, 5, "'ab'");
592  CALL_AND_TEST("abcdef", 4, buf, 5, 5, "'ab'");
593  CALL_AND_TEST("abcdef", 5, buf, 5, 5, "'ab'");
594  CALL_AND_TEST("abcdef", 6, buf, 5, 5, "'ab'");
595  CALL_AND_TEST("'", 1, buf, 5, 5, "''''");
596  CALL_AND_TEST("''", 2, buf, 5, 5, "''''");
597  CALL_AND_TEST("a'", 2, buf, 5, 4, "'a'");
598  CALL_AND_TEST("'a", 2, buf, 5, 5, "''''");
599  CALL_AND_TEST("ab", 2, buf, 5, 5, "'ab'");
600  CALL_AND_TEST("abc", 3, buf, 5, 5, "'ab'");
601 
602  CALL_AND_TEST("ab", 2, buf, 6, 5, "'ab'");
603 
604  CALL_AND_TEST("a'b'c", 5, buf, 32, 10, "'a''b''c'");
605  CALL_AND_TEST("a'b'c'", 6, buf, 32, 12, "'a''b''c'''");
606 }
607 
608 #endif /* UNIV_COMPILE_TEST_FUNCS */
609 #endif /* !UNIV_HOTBACKUP */