Drizzled Public API Documentation

ut0mem.cc
1 /*****************************************************************************
2 
3 Copyright (C) 1994, 2009, Innobase Oy. 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., 51 Franklin
15 St, Fifth Floor, Boston, MA 02110-1301 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 #include <errno.h>
38 
40 typedef struct ut_mem_block_struct ut_mem_block_t;
41 
45 UNIV_INTERN ulint ut_total_allocated_memory = 0;
46 
49 
52  UT_LIST_NODE_T(ut_mem_block_t) mem_block_list;
54  ulint size;
55  ulint magic_n;
56 };
57 
60 #define UT_MEM_MAGIC_N 1601650166
61 
64 static UT_LIST_BASE_NODE_T(ut_mem_block_t) ut_mem_block_list;
65 
67 static ibool ut_mem_block_list_inited = FALSE;
68 
71 static ulint* ut_mem_null_ptr = NULL;
72 
73 /**********************************************************************/
75 UNIV_INTERN
76 void
78 /*=============*/
79 {
80  ut_a(!ut_mem_block_list_inited);
82  UT_LIST_INIT(ut_mem_block_list);
83  ut_mem_block_list_inited = TRUE;
84 }
85 #endif /* !UNIV_HOTBACKUP */
86 
87 /**********************************************************************/
91 UNIV_INTERN
92 void*
94 /*==========*/
95  ulint n,
96  ibool set_to_zero,
99  ibool assert_on_error)
101 {
102 #ifndef UNIV_HOTBACKUP
103  ulint retry_count;
104  void* ret;
105 
106  if (UNIV_LIKELY(srv_use_sys_malloc)) {
107  ret = malloc(n);
108  ut_a(ret || !assert_on_error);
109 
110 #ifdef UNIV_SET_MEM_TO_ZERO
111  if (set_to_zero) {
112  memset(ret, '\0', n);
113  UNIV_MEM_ALLOC(ret, n);
114  }
115 #endif
116  return(ret);
117  }
118 
119  ut_ad((sizeof(ut_mem_block_t) % 8) == 0); /* check alignment ok */
120  ut_a(ut_mem_block_list_inited);
121 
122  retry_count = 0;
123 retry:
125 
126  ret = malloc(n + sizeof(ut_mem_block_t));
127 
128  if (ret == NULL && retry_count < 60) {
129  if (retry_count == 0) {
130  ut_print_timestamp(stderr);
131 
132  fprintf(stderr,
133  " InnoDB: Error: cannot allocate"
134  " %lu bytes of\n"
135  "InnoDB: memory with malloc!"
136  " Total allocated memory\n"
137  "InnoDB: by InnoDB %lu bytes."
138  " Operating system errno: %lu\n"
139  "InnoDB: Check if you should"
140  " increase the swap file or\n"
141  "InnoDB: ulimits of your operating system.\n"
142  "InnoDB: On FreeBSD check you"
143  " have compiled the OS with\n"
144  "InnoDB: a big enough maximum process size.\n"
145  "InnoDB: Note that in most 32-bit"
146  " computers the process\n"
147  "InnoDB: memory space is limited"
148  " to 2 GB or 4 GB.\n"
149  "InnoDB: We keep retrying"
150  " the allocation for 60 seconds...\n",
151  (ulong) n, (ulong) ut_total_allocated_memory,
152 #ifdef __WIN__
153  (ulong) GetLastError()
154 #else
155  (ulong) errno
156 #endif
157  );
158  }
159 
161 
162  /* Sleep for a second and retry the allocation; maybe this is
163  just a temporary shortage of memory */
164 
165  os_thread_sleep(1000000);
166 
167  retry_count++;
168 
169  goto retry;
170  }
171 
172  if (ret == NULL) {
173  /* Flush stderr to make more probable that the error
174  message gets in the error file before we generate a seg
175  fault */
176 
177  fflush(stderr);
178 
180 
181  /* Make an intentional seg fault so that we get a stack
182  trace */
183  if (assert_on_error) {
184  ut_print_timestamp(stderr);
185 
186  fprintf(stderr,
187  " InnoDB: We now intentionally"
188  " generate a seg fault so that\n"
189  "InnoDB: on Linux we get a stack trace.\n");
190 
191  if (*ut_mem_null_ptr) ut_mem_null_ptr = 0;
192  } else {
193  return(NULL);
194  }
195  }
196 
197  if (set_to_zero) {
198 #ifdef UNIV_SET_MEM_TO_ZERO
199  memset(ret, '\0', n + sizeof(ut_mem_block_t));
200 #endif
201  }
202 
203  UNIV_MEM_ALLOC(ret, n + sizeof(ut_mem_block_t));
204 
205  ((ut_mem_block_t*)ret)->size = n + sizeof(ut_mem_block_t);
206  ((ut_mem_block_t*)ret)->magic_n = UT_MEM_MAGIC_N;
207 
209 
210  UT_LIST_ADD_FIRST(mem_block_list, ut_mem_block_list,
211  ((ut_mem_block_t*)ret));
213 
214  return((void*)((byte*)ret + sizeof(ut_mem_block_t)));
215 #else /* !UNIV_HOTBACKUP */
216  void* ret = malloc(n);
217  ut_a(ret || !assert_on_error);
218 
219 # ifdef UNIV_SET_MEM_TO_ZERO
220  if (set_to_zero) {
221  memset(ret, '\0', n);
222  }
223 # endif
224  return(ret);
225 #endif /* !UNIV_HOTBACKUP */
226 }
227 
228 /**********************************************************************/
232 extern "C"
233 UNIV_INTERN
234 void*
236 /*======*/
237  ulint n)
238 {
239 #ifndef UNIV_HOTBACKUP
240  return(ut_malloc_low(n, TRUE, TRUE));
241 #else /* !UNIV_HOTBACKUP */
242  return(malloc(n));
243 #endif /* !UNIV_HOTBACKUP */
244 }
245 
246 #ifndef UNIV_HOTBACKUP
247 /**********************************************************************/
252 UNIV_INTERN
253 ibool
255 /*===========*/
256  ulint n)
257 {
258  void* ret;
259 
260  ret = malloc(n);
261 
262  if (ret == NULL) {
263  ut_print_timestamp(stderr);
264  fprintf(stderr,
265  " InnoDB: Error: cannot allocate"
266  " %lu bytes of memory for\n"
267  "InnoDB: a BLOB with malloc! Total allocated memory\n"
268  "InnoDB: by InnoDB %lu bytes."
269  " Operating system errno: %d\n"
270  "InnoDB: Check if you should increase"
271  " the swap file or\n"
272  "InnoDB: ulimits of your operating system.\n"
273  "InnoDB: On FreeBSD check you have"
274  " compiled the OS with\n"
275  "InnoDB: a big enough maximum process size.\n",
276  (ulong) n,
278  (int) errno);
279  return(FALSE);
280  }
281 
282  free(ret);
283 
284  return(TRUE);
285 }
286 #endif /* !UNIV_HOTBACKUP */
287 
288 /**********************************************************************/
291 extern "C"
292 UNIV_INTERN
293 void
295 /*====*/
296  void* ptr)
297 {
298 #ifndef UNIV_HOTBACKUP
299  ut_mem_block_t* block;
300 
301  if (ptr == NULL) {
302  return;
303  } else if (UNIV_LIKELY(srv_use_sys_malloc)) {
304  free(ptr);
305  return;
306  }
307 
308  block = (ut_mem_block_t*)((byte*)ptr - sizeof(ut_mem_block_t));
309 
311 
312  ut_a(block->magic_n == UT_MEM_MAGIC_N);
314 
316 
317  UT_LIST_REMOVE(mem_block_list, ut_mem_block_list, block);
318  free(block);
319 
321 #else /* !UNIV_HOTBACKUP */
322  free(ptr);
323 #endif /* !UNIV_HOTBACKUP */
324 }
325 
326 #ifndef UNIV_HOTBACKUP
327 /**********************************************************************/
352 extern "C"
353 UNIV_INTERN
354 void*
356 /*=======*/
357  void* ptr,
358  ulint size)
359 {
360  ut_mem_block_t* block;
361  ulint old_size;
362  ulint min_size;
363  void* new_ptr;
364 
365  if (UNIV_LIKELY(srv_use_sys_malloc)) {
366  return(realloc(ptr, size));
367  }
368 
369  if (ptr == NULL) {
370 
371  return(ut_malloc(size));
372  }
373 
374  if (size == 0) {
375  ut_free(ptr);
376 
377  return(NULL);
378  }
379 
380  block = (ut_mem_block_t*)((byte*)ptr - sizeof(ut_mem_block_t));
381 
382  ut_a(block->magic_n == UT_MEM_MAGIC_N);
383 
384  old_size = block->size - sizeof(ut_mem_block_t);
385 
386  if (size < old_size) {
387  min_size = size;
388  } else {
389  min_size = old_size;
390  }
391 
392  new_ptr = ut_malloc(size);
393 
394  if (new_ptr == NULL) {
395 
396  return(NULL);
397  }
398 
399  /* Copy the old data from ptr */
400  ut_memcpy(new_ptr, ptr, min_size);
401 
402  ut_free(ptr);
403 
404  return(new_ptr);
405 }
406 
407 /**********************************************************************/
409 UNIV_INTERN
410 void
412 /*=================*/
413 {
414  ut_mem_block_t* block;
415 
416  ut_a(ut_mem_block_list_inited);
417  ut_mem_block_list_inited = FALSE;
419 
420  while ((block = UT_LIST_GET_FIRST(ut_mem_block_list))) {
421 
422  ut_a(block->magic_n == UT_MEM_MAGIC_N);
424 
426 
427  UT_LIST_REMOVE(mem_block_list, ut_mem_block_list, block);
428  free(block);
429  }
430 
431  if (ut_total_allocated_memory != 0) {
432  fprintf(stderr,
433  "InnoDB: Warning: after shutdown"
434  " total allocated memory is %lu\n",
435  (ulong) ut_total_allocated_memory);
436  }
437 
438  ut_mem_block_list_inited = FALSE;
439 }
440 #endif /* !UNIV_HOTBACKUP */
441 
442 /**********************************************************************/
447 UNIV_INTERN
448 ulint
450 /*=======*/
451  char* dst,
452  const char* src,
453  ulint size)
454 {
455  ulint src_size = strlen(src);
456 
457  if (size != 0) {
458  ulint n = ut_min(src_size, size - 1);
459 
460  memcpy(dst, src, n);
461  dst[n] = '\0';
462  }
463 
464  return(src_size);
465 }
466 
467 /**********************************************************************/
471 UNIV_INTERN
472 ulint
474 /*===========*/
475  char* dst,
476  const char* src,
477  ulint size)
478 {
479  ulint src_size = strlen(src);
480 
481  if (size != 0) {
482  ulint n = ut_min(src_size, size - 1);
483 
484  memcpy(dst, src + src_size - n, n + 1);
485  }
486 
487  return(src_size);
488 }
489 
490 /**********************************************************************/
495 UNIV_INTERN
496 char*
498 /*=======*/
499  char* dest,
500  char q,
501  const char* src)
502 {
503  while (*src) {
504  if ((*dest++ = *src++) == q) {
505  *dest++ = q;
506  }
507  }
508 
509  return(dest);
510 }
511 
512 /**********************************************************************/
517 UNIV_INTERN
518 char*
520 /*=======*/
521  char* dest,
522  char q,
523  const char* src,
524  ulint len)
525 {
526  const char* srcend = src + len;
527 
528  while (src < srcend) {
529  if ((*dest++ = *src++) == q) {
530  *dest++ = q;
531  }
532  }
533 
534  return(dest);
535 }
536 
537 #ifndef UNIV_HOTBACKUP
538 /**********************************************************************/
542 UNIV_INTERN
543 ulint
545 /*========*/
546  const char* s1,
547  const char* s2)
548 {
549  ulint count = 0;
550  ulint len = strlen(s2);
551 
552  if (len == 0) {
553 
554  return(0);
555  }
556 
557  for (;;) {
558  s1 = strstr(s1, s2);
559 
560  if (!s1) {
561 
562  break;
563  }
564 
565  count++;
566  s1 += len;
567  }
568 
569  return(count);
570 }
571 
572 /**********************************************************************/
576 UNIV_INTERN
577 char*
579 /*==========*/
580  const char* str,
581  const char* s1,
582  const char* s2)
583 {
584  char* new_str;
585  char* ptr;
586  const char* str_end;
587  ulint str_len = strlen(str);
588  ulint s1_len = strlen(s1);
589  ulint s2_len = strlen(s2);
590  ulint count = 0;
591  int len_delta = (int)s2_len - (int)s1_len;
592 
593  str_end = str + str_len;
594 
595  if (len_delta <= 0) {
596  len_delta = 0;
597  } else {
598  count = ut_strcount(str, s1);
599  }
600 
601  new_str = static_cast<char *>(mem_alloc(str_len + count * len_delta + 1));
602  ptr = new_str;
603 
604  while (str) {
605  const char* next = strstr(str, s1);
606 
607  if (!next) {
608  next = str_end;
609  }
610 
611  memcpy(ptr, str, next - str);
612  ptr += next - str;
613 
614  if (next == str_end) {
615 
616  break;
617  }
618 
619  memcpy(ptr, s2, s2_len);
620  ptr += s2_len;
621 
622  str = next + s1_len;
623  }
624 
625  *ptr = '\0';
626 
627  return(new_str);
628 }
629 
630 #ifdef UNIV_COMPILE_TEST_FUNCS
631 
632 void
633 test_ut_str_sql_format()
634 {
635  char buf[128];
636  ulint ret;
637 
638 #define CALL_AND_TEST(str, str_len, buf, buf_size, ret_expected, buf_expected)\
639  do {\
640  ibool ok = TRUE;\
641  memset(buf, 'x', 10);\
642  buf[10] = '\0';\
643  fprintf(stderr, "TESTING \"%s\", %lu, %lu\n",\
644  str, (ulint) str_len, (ulint) buf_size);\
645  ret = ut_str_sql_format(str, str_len, buf, buf_size);\
646  if (ret != ret_expected) {\
647  fprintf(stderr, "expected ret %lu, got %lu\n",\
648  (ulint) ret_expected, ret);\
649  ok = FALSE;\
650  }\
651  if (strcmp((char*) buf, buf_expected) != 0) {\
652  fprintf(stderr, "expected buf \"%s\", got \"%s\"\n",\
653  buf_expected, buf);\
654  ok = FALSE;\
655  }\
656  if (ok) {\
657  fprintf(stderr, "OK: %lu, \"%s\"\n\n",\
658  (ulint) ret, buf);\
659  } else {\
660  return;\
661  }\
662  } while (0)
663 
664  CALL_AND_TEST("abcd", 4, buf, 0, 0, "xxxxxxxxxx");
665 
666  CALL_AND_TEST("abcd", 4, buf, 1, 1, "");
667 
668  CALL_AND_TEST("abcd", 4, buf, 2, 1, "");
669 
670  CALL_AND_TEST("abcd", 0, buf, 3, 3, "''");
671  CALL_AND_TEST("abcd", 1, buf, 3, 1, "");
672  CALL_AND_TEST("abcd", 2, buf, 3, 1, "");
673  CALL_AND_TEST("abcd", 3, buf, 3, 1, "");
674  CALL_AND_TEST("abcd", 4, buf, 3, 1, "");
675 
676  CALL_AND_TEST("abcd", 0, buf, 4, 3, "''");
677  CALL_AND_TEST("abcd", 1, buf, 4, 4, "'a'");
678  CALL_AND_TEST("abcd", 2, buf, 4, 4, "'a'");
679  CALL_AND_TEST("abcd", 3, buf, 4, 4, "'a'");
680  CALL_AND_TEST("abcd", 4, buf, 4, 4, "'a'");
681  CALL_AND_TEST("abcde", 5, buf, 4, 4, "'a'");
682  CALL_AND_TEST("'", 1, buf, 4, 3, "''");
683  CALL_AND_TEST("''", 2, buf, 4, 3, "''");
684  CALL_AND_TEST("a'", 2, buf, 4, 4, "'a'");
685  CALL_AND_TEST("'a", 2, buf, 4, 3, "''");
686  CALL_AND_TEST("ab", 2, buf, 4, 4, "'a'");
687 
688  CALL_AND_TEST("abcdef", 0, buf, 5, 3, "''");
689  CALL_AND_TEST("abcdef", 1, buf, 5, 4, "'a'");
690  CALL_AND_TEST("abcdef", 2, buf, 5, 5, "'ab'");
691  CALL_AND_TEST("abcdef", 3, buf, 5, 5, "'ab'");
692  CALL_AND_TEST("abcdef", 4, buf, 5, 5, "'ab'");
693  CALL_AND_TEST("abcdef", 5, buf, 5, 5, "'ab'");
694  CALL_AND_TEST("abcdef", 6, buf, 5, 5, "'ab'");
695  CALL_AND_TEST("'", 1, buf, 5, 5, "''''");
696  CALL_AND_TEST("''", 2, buf, 5, 5, "''''");
697  CALL_AND_TEST("a'", 2, buf, 5, 4, "'a'");
698  CALL_AND_TEST("'a", 2, buf, 5, 5, "''''");
699  CALL_AND_TEST("ab", 2, buf, 5, 5, "'ab'");
700  CALL_AND_TEST("abc", 3, buf, 5, 5, "'ab'");
701 
702  CALL_AND_TEST("ab", 2, buf, 6, 5, "'ab'");
703 
704  CALL_AND_TEST("a'b'c", 5, buf, 32, 10, "'a''b''c'");
705  CALL_AND_TEST("a'b'c'", 6, buf, 32, 12, "'a''b''c'''");
706 }
707 
708 #endif /* UNIV_COMPILE_TEST_FUNCS */
709 #endif /* !UNIV_HOTBACKUP */
UT_LIST_NODE_T(ut_mem_block_t) mem_block_list
UNIV_INTERN void os_fast_mutex_unlock(os_fast_mutex_t *fast_mutex)
Definition: os0sync.cc:915
UNIV_INTERN void * ut_realloc(void *ptr, ulint size)
Definition: ut0mem.cc:355
pthread_mutex_t os_fast_mutex_t
Definition: os0sync.h:50
UNIV_INTERN char * ut_strcpyq(char *dest, char q, const char *src)
Definition: ut0mem.cc:497
UNIV_INTERN void os_fast_mutex_free(os_fast_mutex_t *fast_mutex)
Definition: os0sync.cc:930
UNIV_INLINE void * ut_memcpy(void *dest, const void *sour, ulint n)
ulint ut_total_allocated_memory
Definition: ut0mem.cc:45
UNIV_INTERN void * ut_malloc(ulint n)
Definition: ut0mem.cc:235
UNIV_INTERN void os_fast_mutex_init(os_fast_mutex_t *fast_mutex)
Definition: os0sync.cc:871
UNIV_INTERN void ut_free_all_mem(void)
Definition: ut0mem.cc:411
os_fast_mutex_t ut_list_mutex
Definition: ut0mem.cc:48
UNIV_INTERN void * ut_malloc_low(ulint n, ibool set_to_zero, ibool assert_on_error)
Definition: ut0mem.cc:93
UNIV_INTERN char * ut_strreplace(const char *str, const char *s1, const char *s2)
Definition: ut0mem.cc:578
UNIV_INTERN ulint ut_strcount(const char *s1, const char *s2)
Definition: ut0mem.cc:544
UNIV_INLINE ulint ut_min(ulint n1, ulint n2)
typedef UT_LIST_BASE_NODE_T(mutex_t) ut_list_base_node_t
#define UT_LIST_REMOVE(NAME, BASE, N)
Definition: ut0lst.h:178
UNIV_INTERN void os_thread_sleep(ulint tm)
Definition: os0thread.cc:265
UNIV_INTERN ulint ut_strlcpy(char *dst, const char *src, ulint size)
Definition: ut0mem.cc:449
#define ut_a(EXPR)
Definition: ut0dbg.h:105
UNIV_INTERN ibool ut_test_malloc(ulint n)
Definition: ut0mem.cc:254
#define UT_LIST_GET_FIRST(BASE)
Definition: ut0lst.h:224
UNIV_INTERN void ut_mem_init(void)
Definition: ut0mem.cc:77
#define ut_ad(EXPR)
Definition: ut0dbg.h:127
UNIV_INTERN void ut_free(void *ptr)
Definition: ut0mem.cc:294
#define UT_LIST_INIT(BASE)
Definition: ut0lst.h:84
#define UT_LIST_ADD_FIRST(NAME, BASE, N)
Definition: ut0lst.h:97
UNIV_INTERN char * ut_memcpyq(char *dest, char q, const char *src, ulint len)
Definition: ut0mem.cc:519
UNIV_INTERN void ut_print_timestamp(FILE *file)
Definition: ut0ut.cc:247
UNIV_INTERN void os_fast_mutex_lock(os_fast_mutex_t *fast_mutex)
Definition: os0sync.cc:900
UNIV_INTERN ulint ut_strlcpy_rev(char *dst, const char *src, ulint size)
Definition: ut0mem.cc:473