28 # ifndef UNIV_HOTBACKUP
37 UNIV_INTERN mysql_pfs_key_t mem_hash_mutex_key;
46 static ulint mem_n_created_heaps = 0;
47 static ulint mem_n_allocations = 0;
48 static ulint mem_total_allocated_memory = 0;
49 UNIV_INTERN ulint mem_current_allocated_memory = 0;
50 static ulint mem_max_allocated_memory = 0;
51 # ifndef UNIV_HOTBACKUP
52 static ulint mem_last_print_info = 0;
53 static ibool mem_hash_initialized = FALSE;
57 #define MEM_HASH_SIZE 997
61 struct mem_hash_node_t {
65 const
char* file_name;
72 typedef UT_LIST_BASE_NODE_T(mem_hash_node_t) mem_hash_cell_t;
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);
251 ulint n __attribute__((unused)))
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 =
static_cast<mem_hash_node_t*
>(
ut_malloc(
sizeof(*new_node)));
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"
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",
426 fputs(
"\nDump of the mem heap:\n", stderr);
427 mem_heap_validate_or_print(node->heap, NULL, TRUE, &error,
435 mem_current_allocated_memory -=
size;
437 mutex_exit(&mem_hash_mutex);
441 #if defined UNIV_MEM_DEBUG || defined UNIV_DEBUG
450 mem_heap_validate_or_print(
453 byte* top __attribute__((unused)),
475 ulint block_count = 0;
477 #ifdef UNIV_MEM_DEBUG
485 if (us_size != NULL) {
488 if (ph_size != NULL) {
491 if (n_blocks != NULL) {
498 if (block->magic_n != MEM_BLOCK_MAGIC_N) {
503 fputs(
"Memory heap:", stderr);
506 while (block != NULL) {
507 phys_len += mem_block_get_len(block);
509 if ((block->
type == MEM_HEAP_BUFFER)
510 && (mem_block_get_len(block) > UNIV_PAGE_SIZE)) {
513 "InnoDB: Error: mem block %p"
514 " length %lu > UNIV_PAGE_SIZE\n",
516 (ulong) mem_block_get_len(block));
522 #ifdef UNIV_MEM_DEBUG
526 fprintf(stderr,
" Block %ld:", block_count);
529 field = (byte*) block + mem_block_get_start(block);
531 if (top && (field == top)) {
536 while (field < (byte*) block + mem_block_get_free(block)) {
541 user_field = field + MEM_FIELD_HEADER_SIZE;
543 len = mem_field_header_get_len(user_field);
551 check_field = mem_field_header_get_check(user_field);
554 != mem_field_trailer_get_check(user_field)) {
558 "InnoDB: Error: block %lx mem"
559 " field %lx len %lu\n"
560 "InnoDB: header check field is"
561 " %lx but trailer %lx\n",
563 (ulint) field, len, check_field,
564 mem_field_trailer_get_check(
571 field = field + MEM_SPACE_NEEDED(len);
573 if (top && (field == top)) {
583 if (field != (byte*) block + mem_block_get_free(block)) {
587 "InnoDB: Error: block %lx end of"
589 "InnoDB: but block free at %lx\n",
590 (ulint) block, (ulint) field,
591 (ulint)((byte*) block
592 + mem_block_get_free(block)));
602 #ifdef UNIV_MEM_DEBUG
605 if (us_size != NULL) {
606 *us_size = total_len;
608 if (ph_size != NULL) {
611 if (n_blocks != NULL) {
612 *n_blocks = block_count;
630 ut_ad(mem_heap_check(heap));
632 mem_heap_validate_or_print(heap, NULL, TRUE, &error,
633 &us_size, &phys_size, &n_blocks);
635 "\nheap type: %lu; size: user size %lu;"
636 " physical size %lu; blocks %lu.\n",
637 (ulong) heap->
type, (ulong) us_size,
638 (ulong) phys_size, (ulong) n_blocks);
656 ut_ad(mem_heap_check(heap));
658 mem_heap_validate_or_print(heap, NULL, FALSE, &error, &us_size,
659 &phys_size, &n_blocks);
661 mem_heap_print(heap);
680 ut_a(heap->magic_n == MEM_BLOCK_MAGIC_N);
686 #ifdef UNIV_MEM_DEBUG
695 mem_hash_node_t* node;
696 ulint heap_count = 0;
701 mutex_enter(&mem_hash_mutex);
703 for (i = 0; i < MEM_HASH_SIZE; i++) {
706 while (node != NULL) {
712 mutex_exit(&mem_hash_mutex);
714 if (heap_count == 0) {
715 # ifndef UNIV_HOTBACKUP
730 mem_validate_no_assert(
void)
733 mem_hash_node_t* node;
737 ulint total_allocated_mem = 0;
742 # ifndef UNIV_HOTBACKUP
746 mutex_enter(&mem_hash_mutex);
748 for (i = 0; i < MEM_HASH_SIZE; i++) {
752 while (node != NULL) {
755 mem_heap_validate_or_print(node->heap, NULL,
758 &ph_size, &n_blocks);
762 "\nERROR!!!!!!!!!!!!!!!!!!!"
763 "!!!!!!!!!!!!!!!!!!!!!!!\n\n"
764 "Inconsistency in memory heap"
765 " or buffer created\n"
770 mutex_exit(&mem_hash_mutex);
775 total_allocated_mem += allocated_mem;
780 if ((n_heaps == 0) && (mem_current_allocated_memory != 0)) {
784 if (mem_total_allocated_memory < mem_current_allocated_memory) {
788 if (mem_max_allocated_memory > mem_total_allocated_memory) {
792 if (mem_n_created_heaps < n_heaps) {
796 mutex_exit(&mem_hash_mutex);
809 ut_a(!mem_validate_no_assert());
828 fputs(
"InnoDB: Apparent memory corruption: mem dump ", stderr);
831 fputs(
"\nInnoDB: Scanning backward trying to find"
832 " previous allocated mem blocks\n", stderr);
837 for (i = 0; i < 10; i++) {
839 if (((ulint) p) % 4 == 0) {
841 if (*((ulint*) p) == MEM_BLOCK_MAGIC_N) {
843 "Mem block at - %lu,"
844 " file %s, line %lu\n",
854 if (*((ulint*) p) == MEM_FREED_BLOCK_MAGIC_N) {
856 "Freed mem block at - %lu,"
857 " file %s, line %lu\n",
877 "InnoDB: Scanning forward trying to find next"
878 " allocated mem blocks\n");
883 for (i = 0; i < 10; i++) {
885 if (((ulint) p) % 4 == 0) {
887 if (*((ulint*) p) == MEM_BLOCK_MAGIC_N) {
889 "Mem block at + %lu, file %s,"
900 if (*((ulint*) p) == MEM_FREED_BLOCK_MAGIC_N) {
902 "Freed mem block at + %lu,"
903 " file %s, line %lu\n",
923 #ifndef UNIV_HOTBACKUP
935 #ifdef UNIV_MEM_DEBUG
936 mem_hash_node_t* node;
940 ulint total_allocated_mem = 0;
950 fprintf(outfile,
"\n");
952 "________________________________________________________\n");
953 fprintf(outfile,
"MEMORY ALLOCATION INFORMATION\n\n");
955 #ifndef UNIV_MEM_DEBUG
962 "Sorry, non-debug version cannot give more memory info\n");
968 mutex_enter(&mem_hash_mutex);
970 fprintf(outfile,
"LIST OF CREATED HEAPS AND ALLOCATED BUFFERS: \n\n");
973 fprintf(outfile,
"AFTER THE LAST PRINT INFO\n");
978 while (node != NULL) {
981 if (!print_all && node->nth_heap < mem_last_print_info) {
986 mem_heap_validate_or_print(node->heap, NULL,
987 FALSE, &error, &allocated_mem,
988 &ph_size, &n_blocks);
989 total_allocated_mem += allocated_mem;
992 "%lu: file %s line %lu of size %lu phys.size %lu"
993 " with %lu blocks, type %lu\n",
996 allocated_mem, ph_size, n_blocks,
1002 fprintf(outfile,
"\n");
1004 fprintf(outfile,
"Current allocated memory : %lu\n",
1005 mem_current_allocated_memory);
1006 fprintf(outfile,
"Current allocated heaps and buffers : %lu\n",
1008 fprintf(outfile,
"Cumulative allocated memory : %lu\n",
1009 mem_total_allocated_memory);
1010 fprintf(outfile,
"Maximum allocated memory : %lu\n",
1011 mem_max_allocated_memory);
1012 fprintf(outfile,
"Cumulative created heaps and buffers : %lu\n",
1013 mem_n_created_heaps);
1014 fprintf(outfile,
"Cumulative number of allocations : %lu\n",
1017 mem_last_print_info = mem_n_created_heaps;
1019 mutex_exit(&mem_hash_mutex);
1037 mem_print_info_low(TRUE);
1048 mem_print_info_low(FALSE);