28 # ifndef UNIV_HOTBACKUP
32 UNIV_INTERN
mutex_t mem_hash_mutex;
36 UNIV_INTERN mysql_pfs_key_t mem_hash_mutex_key;
45 static ulint mem_n_created_heaps = 0;
46 static ulint mem_n_allocations = 0;
47 static ulint mem_total_allocated_memory = 0;
48 UNIV_INTERN ulint mem_current_allocated_memory = 0;
49 static ulint mem_max_allocated_memory = 0;
50 # ifndef UNIV_HOTBACKUP
51 static ulint mem_last_print_info = 0;
52 static ibool mem_hash_initialized = FALSE;
56 #define MEM_HASH_SIZE 997
60 typedef struct mem_hash_node_struct mem_hash_node_t;
61 struct mem_hash_node_struct {
65 const
char* file_name;
75 static mem_hash_cell_t mem_hash_table[MEM_HASH_SIZE];
78 static mem_hash_cell_t mem_all_list_base;
84 mem_hash_get_nth_cell(ulint i);
90 mem_hash_get_nth_cell(ulint i)
92 ut_a(i < MEM_HASH_SIZE);
94 return(&(mem_hash_table[i]));
100 mem_field_header_set_len(byte* field, ulint len)
107 mem_field_header_get_len(byte* field)
114 mem_field_header_set_check(byte* field, ulint check)
121 mem_field_header_get_check(byte* field)
128 mem_field_trailer_set_check(byte* field, ulint check)
135 mem_field_trailer_get_check(byte* field)
138 + mem_field_header_get_len(field)));
142 #ifndef UNIV_HOTBACKUP
151 #ifdef UNIV_MEM_DEBUG
156 ut_a(FALSE == mem_hash_initialized);
158 mutex_create(mem_hash_mutex_key, &mem_hash_mutex, SYNC_MEM_HASH);
160 for (i = 0; i < MEM_HASH_SIZE; i++) {
166 mem_hash_initialized = TRUE;
169 if (UNIV_LIKELY(srv_use_sys_malloc)) {
189 #ifdef UNIV_MEM_DEBUG
190 mutex_free(&mem_hash_mutex);
191 mem_hash_initialized = FALSE;
196 #ifdef UNIV_MEM_DEBUG
209 usr_buf = buf + MEM_FIELD_HEADER_SIZE;
217 mem_field_header_set_len(usr_buf, n);
221 mem_field_header_set_check(usr_buf, rnd);
222 mem_field_trailer_set_check(usr_buf, rnd);
226 mutex_enter(&mem_hash_mutex);
228 mem_total_allocated_memory += n;
229 mem_current_allocated_memory += n;
232 if (mem_current_allocated_memory > mem_max_allocated_memory) {
233 mem_max_allocated_memory = mem_current_allocated_memory;
236 mutex_exit(&mem_hash_mutex);
241 mem_init_buf(usr_buf, n);
256 usr_buf = buf + MEM_FIELD_HEADER_SIZE;
258 mutex_enter(&mem_hash_mutex);
259 mem_current_allocated_memory -= n;
260 mutex_exit(&mem_hash_mutex);
263 ut_ad(n == (ulint)mem_field_header_get_len(usr_buf));
268 mem_erase_buf(buf, MEM_SPACE_NEEDED(n));
283 UNIV_MEM_ASSERT_W(buf, n);
285 for (ptr = buf; ptr < buf + n; ptr++) {
294 UNIV_MEM_INVALID(buf, n);
309 UNIV_MEM_ASSERT_W(buf, n);
311 for (ptr = buf; ptr < buf + n; ptr++) {
319 UNIV_MEM_FREE(buf, n);
330 const char* file_name,
333 mem_hash_node_t* new_node;
336 ut_ad(mem_heap_check(heap));
338 mutex_enter(&mem_hash_mutex);
343 new_node =
ut_malloc(
sizeof(mem_hash_node_t));
345 new_node->heap = heap;
346 new_node->file_name = file_name;
347 new_node->line = line;
348 new_node->nth_heap = mem_n_created_heaps;
355 mem_n_created_heaps++;
357 mutex_exit(&mem_hash_mutex);
373 const char* file_name,
376 mem_hash_node_t* node;
381 ut_ad(mem_heap_check(heap));
383 mutex_enter(&mem_hash_mutex);
390 while (node != NULL) {
391 if (node->heap == heap) {
401 "Memory heap or buffer freed in %s line %lu"
403 file_name, (ulong) line);
413 mem_heap_validate_or_print(node->heap, NULL, FALSE, &error, &size,
417 "Inconsistency in memory heap or"
418 " buffer n:o %lu created\n"
419 "in %s line %lu and tried to free in %s line %lu.\n"
420 "Hex dump of 400 bytes around memory heap"
421 " first block start:\n",
422 node->nth_heap, node->file_name, (ulong) node->line,
423 file_name, (ulong) line);
425 fputs(
"\nDump of the mem heap:\n", stderr);
426 mem_heap_validate_or_print(node->heap, NULL, TRUE, &error,
434 mem_current_allocated_memory -= size;
436 mutex_exit(&mem_hash_mutex);
440 #if defined UNIV_MEM_DEBUG || defined UNIV_DEBUG
449 mem_heap_validate_or_print(
474 ulint block_count = 0;
476 #ifdef UNIV_MEM_DEBUG
484 if (us_size != NULL) {
487 if (ph_size != NULL) {
490 if (n_blocks != NULL) {
497 if (block->magic_n != MEM_BLOCK_MAGIC_N) {
502 fputs(
"Memory heap:", stderr);
505 while (block != NULL) {
506 phys_len += mem_block_get_len(block);
508 if ((block->
type == MEM_HEAP_BUFFER)
509 && (mem_block_get_len(block) > UNIV_PAGE_SIZE)) {
512 "InnoDB: Error: mem block %p"
513 " length %lu > UNIV_PAGE_SIZE\n",
515 (ulong) mem_block_get_len(block));
521 #ifdef UNIV_MEM_DEBUG
525 fprintf(stderr,
" Block %ld:", block_count);
528 field = (byte*)block + mem_block_get_start(block);
530 if (top && (field == top)) {
535 while (field < (byte*)block + mem_block_get_free(block)) {
540 user_field = field + MEM_FIELD_HEADER_SIZE;
542 len = mem_field_header_get_len(user_field);
550 check_field = mem_field_header_get_check(user_field);
553 != mem_field_trailer_get_check(user_field)) {
557 "InnoDB: Error: block %lx mem"
558 " field %lx len %lu\n"
559 "InnoDB: header check field is"
560 " %lx but trailer %lx\n",
562 (ulint)field, len, check_field,
563 mem_field_trailer_get_check(
570 field = field + MEM_SPACE_NEEDED(len);
572 if (top && (field == top)) {
582 if (field != (byte*)block + mem_block_get_free(block)) {
586 "InnoDB: Error: block %lx end of"
588 "InnoDB: but block free at %lx\n",
589 (ulint)block, (ulint)field,
591 + mem_block_get_free(block)));
601 #ifdef UNIV_MEM_DEBUG
604 if (us_size != NULL) {
605 *us_size = total_len;
607 if (ph_size != NULL) {
610 if (n_blocks != NULL) {
611 *n_blocks = block_count;
629 ut_ad(mem_heap_check(heap));
631 mem_heap_validate_or_print(heap, NULL, TRUE, &error,
632 &us_size, &phys_size, &n_blocks);
634 "\nheap type: %lu; size: user size %lu;"
635 " physical size %lu; blocks %lu.\n",
636 (ulong) heap->
type, (ulong) us_size,
637 (ulong) phys_size, (ulong) n_blocks);
655 ut_ad(mem_heap_check(heap));
657 mem_heap_validate_or_print(heap, NULL, FALSE, &error, &us_size,
658 &phys_size, &n_blocks);
660 mem_heap_print(heap);
679 ut_a(heap->magic_n == MEM_BLOCK_MAGIC_N);
685 #ifdef UNIV_MEM_DEBUG
694 mem_hash_node_t* node;
695 ulint heap_count = 0;
700 mutex_enter(&mem_hash_mutex);
702 for (i = 0; i < MEM_HASH_SIZE; i++) {
705 while (node != NULL) {
711 mutex_exit(&mem_hash_mutex);
713 if (heap_count == 0) {
714 # ifndef UNIV_HOTBACKUP
729 mem_validate_no_assert(
void)
732 mem_hash_node_t* node;
736 ulint total_allocated_mem = 0;
741 # ifndef UNIV_HOTBACKUP
745 mutex_enter(&mem_hash_mutex);
747 for (i = 0; i < MEM_HASH_SIZE; i++) {
751 while (node != NULL) {
754 mem_heap_validate_or_print(node->heap, NULL,
757 &ph_size, &n_blocks);
761 "\nERROR!!!!!!!!!!!!!!!!!!!"
762 "!!!!!!!!!!!!!!!!!!!!!!!\n\n"
763 "Inconsistency in memory heap"
764 " or buffer created\n"
766 node->file_name, node->line);
768 mutex_exit(&mem_hash_mutex);
773 total_allocated_mem += allocated_mem;
778 if ((n_heaps == 0) && (mem_current_allocated_memory != 0)) {
782 if (mem_total_allocated_memory < mem_current_allocated_memory) {
786 if (mem_max_allocated_memory > mem_total_allocated_memory) {
790 if (mem_n_created_heaps < n_heaps) {
794 mutex_exit(&mem_hash_mutex);
807 ut_a(!mem_validate_no_assert());
826 fputs(
"InnoDB: Apparent memory corruption: mem dump ", stderr);
829 fputs(
"\nInnoDB: Scanning backward trying to find"
830 " previous allocated mem blocks\n", stderr);
835 for (i = 0; i < 10; i++) {
837 if (((ulint)p) % 4 == 0) {
839 if (*((ulint*)p) == MEM_BLOCK_MAGIC_N) {
841 "Mem block at - %lu,"
842 " file %s, line %lu\n",
852 if (*((ulint*)p) == MEM_FREED_BLOCK_MAGIC_N) {
854 "Freed mem block at - %lu,"
855 " file %s, line %lu\n",
875 "InnoDB: Scanning forward trying to find next"
876 " allocated mem blocks\n");
881 for (i = 0; i < 10; i++) {
883 if (((ulint)p) % 4 == 0) {
885 if (*((ulint*)p) == MEM_BLOCK_MAGIC_N) {
887 "Mem block at + %lu, file %s,"
898 if (*((ulint*)p) == MEM_FREED_BLOCK_MAGIC_N) {
900 "Freed mem block at + %lu,"
901 " file %s, line %lu\n",
921 #ifndef UNIV_HOTBACKUP
933 #ifdef UNIV_MEM_DEBUG
934 mem_hash_node_t* node;
938 ulint total_allocated_mem = 0;
948 fprintf(outfile,
"\n");
950 "________________________________________________________\n");
951 fprintf(outfile,
"MEMORY ALLOCATION INFORMATION\n\n");
953 #ifndef UNIV_MEM_DEBUG
960 "Sorry, non-debug version cannot give more memory info\n");
966 mutex_enter(&mem_hash_mutex);
968 fprintf(outfile,
"LIST OF CREATED HEAPS AND ALLOCATED BUFFERS: \n\n");
971 fprintf(outfile,
"AFTER THE LAST PRINT INFO\n");
976 while (node != NULL) {
979 if (!print_all && node->nth_heap < mem_last_print_info) {
984 mem_heap_validate_or_print(node->heap, NULL,
985 FALSE, &error, &allocated_mem,
986 &ph_size, &n_blocks);
987 total_allocated_mem += allocated_mem;
990 "%lu: file %s line %lu of size %lu phys.size %lu"
991 " with %lu blocks, type %lu\n",
992 node->nth_heap, node->file_name, node->line,
993 allocated_mem, ph_size, n_blocks,
999 fprintf(outfile,
"\n");
1001 fprintf(outfile,
"Current allocated memory : %lu\n",
1002 mem_current_allocated_memory);
1003 fprintf(outfile,
"Current allocated heaps and buffers : %lu\n",
1005 fprintf(outfile,
"Cumulative allocated memory : %lu\n",
1006 mem_total_allocated_memory);
1007 fprintf(outfile,
"Maximum allocated memory : %lu\n",
1008 mem_max_allocated_memory);
1009 fprintf(outfile,
"Cumulative created heaps and buffers : %lu\n",
1010 mem_n_created_heaps);
1011 fprintf(outfile,
"Cumulative number of allocations : %lu\n",
1014 mem_last_print_info = mem_n_created_heaps;
1016 mutex_exit(&mem_hash_mutex);
1034 mem_print_info_low(TRUE);
1045 mem_print_info_low(FALSE);