MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
mem0dbg.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 /********************************************************************/
27 #ifdef UNIV_MEM_DEBUG
28 # ifndef UNIV_HOTBACKUP
29 # include "ha_prototypes.h"
30 /* The mutex which protects in the debug version the hash table
31 containing the list of live memory heaps, and also the global
32 variables below. */
33 UNIV_INTERN ib_mutex_t mem_hash_mutex;
34 
35 #ifdef UNIV_PFS_MUTEX
36 /* Key to register mem_hash_mutex with performance schema */
37 UNIV_INTERN mysql_pfs_key_t mem_hash_mutex_key;
38 #endif /* UNIV_PFS_MUTEX */
39 
40 # endif /* !UNIV_HOTBACKUP */
41 
42 /* The following variables contain information about the
43 extent of memory allocations. Only used in the debug version.
44 Protected by mem_hash_mutex above. */
45 
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;
54 # endif /* !UNIV_HOTBACKUP */
55 
56 /* Size of the hash table for memory management tracking */
57 #define MEM_HASH_SIZE 997
58 
59 /* The node of the list containing currently allocated memory heaps */
60 
61 struct mem_hash_node_t {
62  UT_LIST_NODE_T(mem_hash_node_t)
63  list;
64  mem_heap_t* heap;
65  const char* file_name;/* file where heap was created*/
66  ulint line;
67  ulint nth_heap;/* this is the nth heap created */
68  UT_LIST_NODE_T(mem_hash_node_t)
69  all_list;/* list of all created heaps */
70 };
71 
72 typedef UT_LIST_BASE_NODE_T(mem_hash_node_t) mem_hash_cell_t;
73 
74 /* The hash table of allocated heaps */
75 static mem_hash_cell_t mem_hash_table[MEM_HASH_SIZE];
76 
77 /* The base node of the list of all allocated heaps */
78 static mem_hash_cell_t mem_all_list_base;
79 
80 
81 
82 UNIV_INLINE
83 mem_hash_cell_t*
84 mem_hash_get_nth_cell(ulint i);
85 
86 /* Accessor function for the hash table. Returns a pointer to the
87 table cell. */
88 UNIV_INLINE
89 mem_hash_cell_t*
90 mem_hash_get_nth_cell(ulint i)
91 {
92  ut_a(i < MEM_HASH_SIZE);
93 
94  return(&(mem_hash_table[i]));
95 }
96 
97 /* Accessor functions for a memory field in the debug version */
98 UNIV_INTERN
99 void
100 mem_field_header_set_len(byte* field, ulint len)
101 {
102  mach_write_to_4(field - 2 * sizeof(ulint), len);
103 }
104 
105 UNIV_INTERN
106 ulint
107 mem_field_header_get_len(byte* field)
108 {
109  return(mach_read_from_4(field - 2 * sizeof(ulint)));
110 }
111 
112 UNIV_INTERN
113 void
114 mem_field_header_set_check(byte* field, ulint check)
115 {
116  mach_write_to_4(field - sizeof(ulint), check);
117 }
118 
119 UNIV_INTERN
120 ulint
121 mem_field_header_get_check(byte* field)
122 {
123  return(mach_read_from_4(field - sizeof(ulint)));
124 }
125 
126 UNIV_INTERN
127 void
128 mem_field_trailer_set_check(byte* field, ulint check)
129 {
130  mach_write_to_4(field + mem_field_header_get_len(field), check);
131 }
132 
133 UNIV_INTERN
134 ulint
135 mem_field_trailer_get_check(byte* field)
136 {
137  return(mach_read_from_4(field
138  + mem_field_header_get_len(field)));
139 }
140 #endif /* UNIV_MEM_DEBUG */
141 
142 #ifndef UNIV_HOTBACKUP
143 /******************************************************************/
145 UNIV_INTERN
146 void
148 /*=====*/
149  ulint size)
150 {
151 #ifdef UNIV_MEM_DEBUG
152 
153  ulint i;
154 
155  /* Initialize the hash table */
156  ut_a(FALSE == mem_hash_initialized);
157 
158  mutex_create(mem_hash_mutex_key, &mem_hash_mutex, SYNC_MEM_HASH);
159 
160  for (i = 0; i < MEM_HASH_SIZE; i++) {
161  UT_LIST_INIT(*mem_hash_get_nth_cell(i));
162  }
163 
164  UT_LIST_INIT(mem_all_list_base);
165 
166  mem_hash_initialized = TRUE;
167 #endif
168 
169  if (UNIV_LIKELY(srv_use_sys_malloc)) {
170  /* When innodb_use_sys_malloc is set, the
171  mem_comm_pool won't be used for any allocations. We
172  create a dummy mem_comm_pool, because some statistics
173  and debugging code relies on it being initialized. */
174  size = 1;
175  }
176 
178 }
179 
180 /******************************************************************/
182 UNIV_INTERN
183 void
185 /*===========*/
186 {
188  mem_comm_pool = NULL;
189 #ifdef UNIV_MEM_DEBUG
190  mutex_free(&mem_hash_mutex);
191  mem_hash_initialized = FALSE;
192 #endif /* UNIV_MEM_DEBUG */
193 }
194 #endif /* !UNIV_HOTBACKUP */
195 
196 #ifdef UNIV_MEM_DEBUG
197 /******************************************************************/
199 UNIV_INTERN
200 void
201 mem_field_init(
202 /*===========*/
203  byte* buf,
204  ulint n)
205 {
206  ulint rnd;
207  byte* usr_buf;
208 
209  usr_buf = buf + MEM_FIELD_HEADER_SIZE;
210 
211  /* In the debug version write the length field and the
212  check fields to the start and the end of the allocated storage.
213  The field header consists of a length field and
214  a random number field, in this order. The field trailer contains
215  the same random number as a check field. */
216 
217  mem_field_header_set_len(usr_buf, n);
218 
219  rnd = ut_rnd_gen_ulint();
220 
221  mem_field_header_set_check(usr_buf, rnd);
222  mem_field_trailer_set_check(usr_buf, rnd);
223 
224  /* Update the memory allocation information */
225 
226  mutex_enter(&mem_hash_mutex);
227 
228  mem_total_allocated_memory += n;
229  mem_current_allocated_memory += n;
230  mem_n_allocations++;
231 
232  if (mem_current_allocated_memory > mem_max_allocated_memory) {
233  mem_max_allocated_memory = mem_current_allocated_memory;
234  }
235 
236  mutex_exit(&mem_hash_mutex);
237 
238  /* In the debug version set the buffer to a random
239  combination of 0xBA and 0xBE */
240 
241  mem_init_buf(usr_buf, n);
242 }
243 
244 /******************************************************************/
246 UNIV_INTERN
247 void
248 mem_field_erase(
249 /*============*/
250  byte* buf,
251  ulint n __attribute__((unused)))
253 {
254  byte* usr_buf;
255 
256  usr_buf = buf + MEM_FIELD_HEADER_SIZE;
257 
258  mutex_enter(&mem_hash_mutex);
259  mem_current_allocated_memory -= n;
260  mutex_exit(&mem_hash_mutex);
261 
262  /* Check that the field lengths agree */
263  ut_ad(n == (ulint) mem_field_header_get_len(usr_buf));
264 
265  /* In the debug version, set the freed space to a random
266  combination of 0xDE and 0xAD */
267 
268  mem_erase_buf(buf, MEM_SPACE_NEEDED(n));
269 }
270 
271 /***************************************************************/
274 UNIV_INTERN
275 void
276 mem_init_buf(
277 /*=========*/
278  byte* buf,
279  ulint n)
280 {
281  byte* ptr;
282 
283  UNIV_MEM_ASSERT_W(buf, n);
284 
285  for (ptr = buf; ptr < buf + n; ptr++) {
286 
287  if (ut_rnd_gen_ibool()) {
288  *ptr = 0xBA;
289  } else {
290  *ptr = 0xBE;
291  }
292  }
293 
294  UNIV_MEM_INVALID(buf, n);
295 }
296 
297 /***************************************************************/
300 UNIV_INTERN
301 void
302 mem_erase_buf(
303 /*==========*/
304  byte* buf,
305  ulint n)
306 {
307  byte* ptr;
308 
309  UNIV_MEM_ASSERT_W(buf, n);
310 
311  for (ptr = buf; ptr < buf + n; ptr++) {
312  if (ut_rnd_gen_ibool()) {
313  *ptr = 0xDE;
314  } else {
315  *ptr = 0xAD;
316  }
317  }
318 
319  UNIV_MEM_FREE(buf, n);
320 }
321 
322 /***************************************************************/
325 UNIV_INTERN
326 void
327 mem_hash_insert(
328 /*============*/
329  mem_heap_t* heap,
330  const char* file_name,
331  ulint line)
332 {
333  mem_hash_node_t* new_node;
334  ulint cell_no ;
335 
336  ut_ad(mem_heap_check(heap));
337 
338  mutex_enter(&mem_hash_mutex);
339 
340  cell_no = ut_hash_ulint((ulint) heap, MEM_HASH_SIZE);
341 
342  /* Allocate a new node to the list */
343  new_node = static_cast<mem_hash_node_t*>(ut_malloc(sizeof(*new_node)));
344 
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;
349 
350  /* Insert into lists */
351  UT_LIST_ADD_FIRST(list, *mem_hash_get_nth_cell(cell_no), new_node);
352 
353  UT_LIST_ADD_LAST(all_list, mem_all_list_base, new_node);
354 
355  mem_n_created_heaps++;
356 
357  mutex_exit(&mem_hash_mutex);
358 }
359 
360 /***************************************************************/
368 UNIV_INTERN
369 void
370 mem_hash_remove(
371 /*============*/
372  mem_heap_t* heap,
373  const char* file_name,
374  ulint line)
375 {
376  mem_hash_node_t* node;
377  ulint cell_no;
378  ibool error;
379  ulint size;
380 
381  ut_ad(mem_heap_check(heap));
382 
383  mutex_enter(&mem_hash_mutex);
384 
385  cell_no = ut_hash_ulint((ulint) heap, MEM_HASH_SIZE);
386 
387  /* Look for the heap in the hash table list */
388  node = UT_LIST_GET_FIRST(*mem_hash_get_nth_cell(cell_no));
389 
390  while (node != NULL) {
391  if (node->heap == heap) {
392 
393  break;
394  }
395 
396  node = UT_LIST_GET_NEXT(list, node);
397  }
398 
399  if (node == NULL) {
400  fprintf(stderr,
401  "Memory heap or buffer freed in %s line %lu"
402  " did not exist.\n",
403  innobase_basename(file_name), (ulong) line);
404  ut_error;
405  }
406 
407  /* Remove from lists */
408  UT_LIST_REMOVE(list, *mem_hash_get_nth_cell(cell_no), node);
409 
410  UT_LIST_REMOVE(all_list, mem_all_list_base, node);
411 
412  /* Validate the heap which will be freed */
413  mem_heap_validate_or_print(node->heap, NULL, FALSE, &error, &size,
414  NULL, NULL);
415  if (error) {
416  fprintf(stderr,
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,
423  innobase_basename(node->file_name), (ulong) node->line,
424  innobase_basename(file_name), (ulong) line);
425  ut_print_buf(stderr, (byte*) node->heap - 200, 400);
426  fputs("\nDump of the mem heap:\n", stderr);
427  mem_heap_validate_or_print(node->heap, NULL, TRUE, &error,
428  &size, NULL, NULL);
429  ut_error;
430  }
431 
432  /* Free the memory occupied by the node struct */
433  ut_free(node);
434 
435  mem_current_allocated_memory -= size;
436 
437  mutex_exit(&mem_hash_mutex);
438 }
439 #endif /* UNIV_MEM_DEBUG */
440 
441 #if defined UNIV_MEM_DEBUG || defined UNIV_DEBUG
442 /***************************************************************/
448 UNIV_INTERN
449 void
450 mem_heap_validate_or_print(
451 /*=======================*/
452  mem_heap_t* heap,
453  byte* top __attribute__((unused)),
457  ibool print,
460  ibool* error,
461  ulint* us_size,
466  ulint* ph_size,
469  ulint* n_blocks)
472 {
474  ulint total_len = 0;
475  ulint block_count = 0;
476  ulint phys_len = 0;
477 #ifdef UNIV_MEM_DEBUG
478  ulint len;
479  byte* field;
480  byte* user_field;
481  ulint check_field;
482 #endif
483 
484  /* Pessimistically, we set the parameters to error values */
485  if (us_size != NULL) {
486  *us_size = 0;
487  }
488  if (ph_size != NULL) {
489  *ph_size = 0;
490  }
491  if (n_blocks != NULL) {
492  *n_blocks = 0;
493  }
494  *error = TRUE;
495 
496  block = heap;
497 
498  if (block->magic_n != MEM_BLOCK_MAGIC_N) {
499  return;
500  }
501 
502  if (print) {
503  fputs("Memory heap:", stderr);
504  }
505 
506  while (block != NULL) {
507  phys_len += mem_block_get_len(block);
508 
509  if ((block->type == MEM_HEAP_BUFFER)
510  && (mem_block_get_len(block) > UNIV_PAGE_SIZE)) {
511 
512  fprintf(stderr,
513  "InnoDB: Error: mem block %p"
514  " length %lu > UNIV_PAGE_SIZE\n",
515  (void*) block,
516  (ulong) mem_block_get_len(block));
517  /* error */
518 
519  return;
520  }
521 
522 #ifdef UNIV_MEM_DEBUG
523  /* We can trace the fields of the block only in the debug
524  version */
525  if (print) {
526  fprintf(stderr, " Block %ld:", block_count);
527  }
528 
529  field = (byte*) block + mem_block_get_start(block);
530 
531  if (top && (field == top)) {
532 
533  goto completed;
534  }
535 
536  while (field < (byte*) block + mem_block_get_free(block)) {
537 
538  /* Calculate the pointer to the storage
539  which was given to the user */
540 
541  user_field = field + MEM_FIELD_HEADER_SIZE;
542 
543  len = mem_field_header_get_len(user_field);
544 
545  if (print) {
546  ut_print_buf(stderr, user_field, len);
547  putc('\n', stderr);
548  }
549 
550  total_len += len;
551  check_field = mem_field_header_get_check(user_field);
552 
553  if (check_field
554  != mem_field_trailer_get_check(user_field)) {
555  /* error */
556 
557  fprintf(stderr,
558  "InnoDB: Error: block %lx mem"
559  " field %lx len %lu\n"
560  "InnoDB: header check field is"
561  " %lx but trailer %lx\n",
562  (ulint) block,
563  (ulint) field, len, check_field,
564  mem_field_trailer_get_check(
565  user_field));
566 
567  return;
568  }
569 
570  /* Move to next field */
571  field = field + MEM_SPACE_NEEDED(len);
572 
573  if (top && (field == top)) {
574 
575  goto completed;
576  }
577 
578  }
579 
580  /* At the end check that we have arrived to the first free
581  position */
582 
583  if (field != (byte*) block + mem_block_get_free(block)) {
584  /* error */
585 
586  fprintf(stderr,
587  "InnoDB: Error: block %lx end of"
588  " mem fields %lx\n"
589  "InnoDB: but block free at %lx\n",
590  (ulint) block, (ulint) field,
591  (ulint)((byte*) block
592  + mem_block_get_free(block)));
593 
594  return;
595  }
596 
597 #endif
598 
599  block = UT_LIST_GET_NEXT(list, block);
600  block_count++;
601  }
602 #ifdef UNIV_MEM_DEBUG
603 completed:
604 #endif
605  if (us_size != NULL) {
606  *us_size = total_len;
607  }
608  if (ph_size != NULL) {
609  *ph_size = phys_len;
610  }
611  if (n_blocks != NULL) {
612  *n_blocks = block_count;
613  }
614  *error = FALSE;
615 }
616 
617 /**************************************************************/
619 static
620 void
621 mem_heap_print(
622 /*===========*/
623  mem_heap_t* heap)
624 {
625  ibool error;
626  ulint us_size;
627  ulint phys_size;
628  ulint n_blocks;
629 
630  ut_ad(mem_heap_check(heap));
631 
632  mem_heap_validate_or_print(heap, NULL, TRUE, &error,
633  &us_size, &phys_size, &n_blocks);
634  fprintf(stderr,
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);
639  ut_a(!error);
640 }
641 
642 /**************************************************************/
645 UNIV_INTERN
646 ibool
647 mem_heap_validate(
648 /*==============*/
649  mem_heap_t* heap)
650 {
651  ibool error;
652  ulint us_size;
653  ulint phys_size;
654  ulint n_blocks;
655 
656  ut_ad(mem_heap_check(heap));
657 
658  mem_heap_validate_or_print(heap, NULL, FALSE, &error, &us_size,
659  &phys_size, &n_blocks);
660  if (error) {
661  mem_heap_print(heap);
662  }
663 
664  ut_a(!error);
665 
666  return(TRUE);
667 }
668 #endif /* UNIV_MEM_DEBUG || UNIV_DEBUG */
669 
670 #ifdef UNIV_DEBUG
671 /**************************************************************/
674 UNIV_INTERN
675 ibool
676 mem_heap_check(
677 /*===========*/
678  mem_heap_t* heap)
679 {
680  ut_a(heap->magic_n == MEM_BLOCK_MAGIC_N);
681 
682  return(TRUE);
683 }
684 #endif /* UNIV_DEBUG */
685 
686 #ifdef UNIV_MEM_DEBUG
687 /*****************************************************************/
690 UNIV_INTERN
691 ibool
692 mem_all_freed(void)
693 /*===============*/
694 {
695  mem_hash_node_t* node;
696  ulint heap_count = 0;
697  ulint i;
698 
699  mem_validate();
700 
701  mutex_enter(&mem_hash_mutex);
702 
703  for (i = 0; i < MEM_HASH_SIZE; i++) {
704 
705  node = UT_LIST_GET_FIRST(*mem_hash_get_nth_cell(i));
706  while (node != NULL) {
707  heap_count++;
708  node = UT_LIST_GET_NEXT(list, node);
709  }
710  }
711 
712  mutex_exit(&mem_hash_mutex);
713 
714  if (heap_count == 0) {
715 # ifndef UNIV_HOTBACKUP
717 # endif /* !UNIV_HOTBACKUP */
718 
719  return(TRUE);
720  } else {
721  return(FALSE);
722  }
723 }
724 
725 /*****************************************************************/
728 UNIV_INTERN
729 ibool
730 mem_validate_no_assert(void)
731 /*========================*/
732 {
733  mem_hash_node_t* node;
734  ulint n_heaps = 0;
735  ulint allocated_mem;
736  ulint ph_size;
737  ulint total_allocated_mem = 0;
738  ibool error = FALSE;
739  ulint n_blocks;
740  ulint i;
741 
742 # ifndef UNIV_HOTBACKUP
744 # endif /* !UNIV_HOTBACKUP */
745 
746  mutex_enter(&mem_hash_mutex);
747 
748  for (i = 0; i < MEM_HASH_SIZE; i++) {
749 
750  node = UT_LIST_GET_FIRST(*mem_hash_get_nth_cell(i));
751 
752  while (node != NULL) {
753  n_heaps++;
754 
755  mem_heap_validate_or_print(node->heap, NULL,
756  FALSE, &error,
757  &allocated_mem,
758  &ph_size, &n_blocks);
759 
760  if (error) {
761  fprintf(stderr,
762  "\nERROR!!!!!!!!!!!!!!!!!!!"
763  "!!!!!!!!!!!!!!!!!!!!!!!\n\n"
764  "Inconsistency in memory heap"
765  " or buffer created\n"
766  "in %s line %lu.\n",
767  innobase_basename(node->file_name),
768  node->line);
769 
770  mutex_exit(&mem_hash_mutex);
771 
772  return(TRUE);
773  }
774 
775  total_allocated_mem += allocated_mem;
776  node = UT_LIST_GET_NEXT(list, node);
777  }
778  }
779 
780  if ((n_heaps == 0) && (mem_current_allocated_memory != 0)) {
781  error = TRUE;
782  }
783 
784  if (mem_total_allocated_memory < mem_current_allocated_memory) {
785  error = TRUE;
786  }
787 
788  if (mem_max_allocated_memory > mem_total_allocated_memory) {
789  error = TRUE;
790  }
791 
792  if (mem_n_created_heaps < n_heaps) {
793  error = TRUE;
794  }
795 
796  mutex_exit(&mem_hash_mutex);
797 
798  return(error);
799 }
800 
801 /************************************************************/
804 UNIV_INTERN
805 ibool
806 mem_validate(void)
807 /*==============*/
808 {
809  ut_a(!mem_validate_no_assert());
810 
811  return(TRUE);
812 }
813 #endif /* UNIV_MEM_DEBUG */
814 
815 /************************************************************/
818 UNIV_INTERN
819 void
821 /*===================*/
822  void* ptr)
823 {
824  byte* p;
825  ulint i;
826  ulint dist;
827 
828  fputs("InnoDB: Apparent memory corruption: mem dump ", stderr);
829  ut_print_buf(stderr, (byte*) ptr - 250, 500);
830 
831  fputs("\nInnoDB: Scanning backward trying to find"
832  " previous allocated mem blocks\n", stderr);
833 
834  p = (byte*) ptr;
835  dist = 0;
836 
837  for (i = 0; i < 10; i++) {
838  for (;;) {
839  if (((ulint) p) % 4 == 0) {
840 
841  if (*((ulint*) p) == MEM_BLOCK_MAGIC_N) {
842  fprintf(stderr,
843  "Mem block at - %lu,"
844  " file %s, line %lu\n",
845  (ulong) dist,
846  (p + sizeof(ulint)),
847  (ulong)
848  (*(ulint*)(p + 8
849  + sizeof(ulint))));
850 
851  break;
852  }
853 
854  if (*((ulint*) p) == MEM_FREED_BLOCK_MAGIC_N) {
855  fprintf(stderr,
856  "Freed mem block at - %lu,"
857  " file %s, line %lu\n",
858  (ulong) dist,
859  (p + sizeof(ulint)),
860  (ulong)
861  (*(ulint*)(p + 8
862  + sizeof(ulint))));
863 
864  break;
865  }
866  }
867 
868  p--;
869  dist++;
870  }
871 
872  p--;
873  dist++;
874  }
875 
876  fprintf(stderr,
877  "InnoDB: Scanning forward trying to find next"
878  " allocated mem blocks\n");
879 
880  p = (byte*) ptr;
881  dist = 0;
882 
883  for (i = 0; i < 10; i++) {
884  for (;;) {
885  if (((ulint) p) % 4 == 0) {
886 
887  if (*((ulint*) p) == MEM_BLOCK_MAGIC_N) {
888  fprintf(stderr,
889  "Mem block at + %lu, file %s,"
890  " line %lu\n",
891  (ulong) dist,
892  (p + sizeof(ulint)),
893  (ulong)
894  (*(ulint*)(p + 8
895  + sizeof(ulint))));
896 
897  break;
898  }
899 
900  if (*((ulint*) p) == MEM_FREED_BLOCK_MAGIC_N) {
901  fprintf(stderr,
902  "Freed mem block at + %lu,"
903  " file %s, line %lu\n",
904  (ulong) dist,
905  (p + sizeof(ulint)),
906  (ulong)
907  (*(ulint*)(p + 8
908  + sizeof(ulint))));
909 
910  break;
911  }
912  }
913 
914  p++;
915  dist++;
916  }
917 
918  p++;
919  dist++;
920  }
921 }
922 
923 #ifndef UNIV_HOTBACKUP
924 /*****************************************************************/
927 static
928 void
929 mem_print_info_low(
930 /*===============*/
931  ibool print_all)
934 {
935 #ifdef UNIV_MEM_DEBUG
936  mem_hash_node_t* node;
937  ulint n_heaps = 0;
938  ulint allocated_mem;
939  ulint ph_size;
940  ulint total_allocated_mem = 0;
941  ibool error;
942  ulint n_blocks;
943 #endif
944  FILE* outfile;
945 
946  /* outfile = fopen("ibdebug", "a"); */
947 
948  outfile = stdout;
949 
950  fprintf(outfile, "\n");
951  fprintf(outfile,
952  "________________________________________________________\n");
953  fprintf(outfile, "MEMORY ALLOCATION INFORMATION\n\n");
954 
955 #ifndef UNIV_MEM_DEBUG
956 
957  UT_NOT_USED(print_all);
958 
960 
961  fprintf(outfile,
962  "Sorry, non-debug version cannot give more memory info\n");
963 
964  /* fclose(outfile); */
965 
966  return;
967 #else
968  mutex_enter(&mem_hash_mutex);
969 
970  fprintf(outfile, "LIST OF CREATED HEAPS AND ALLOCATED BUFFERS: \n\n");
971 
972  if (!print_all) {
973  fprintf(outfile, "AFTER THE LAST PRINT INFO\n");
974  }
975 
976  node = UT_LIST_GET_FIRST(mem_all_list_base);
977 
978  while (node != NULL) {
979  n_heaps++;
980 
981  if (!print_all && node->nth_heap < mem_last_print_info) {
982 
983  goto next_heap;
984  }
985 
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;
990 
991  fprintf(outfile,
992  "%lu: file %s line %lu of size %lu phys.size %lu"
993  " with %lu blocks, type %lu\n",
994  node->nth_heap,
995  innobase_basename(node->file_name), node->line,
996  allocated_mem, ph_size, n_blocks,
997  (node->heap)->type);
998 next_heap:
999  node = UT_LIST_GET_NEXT(all_list, node);
1000  }
1001 
1002  fprintf(outfile, "\n");
1003 
1004  fprintf(outfile, "Current allocated memory : %lu\n",
1005  mem_current_allocated_memory);
1006  fprintf(outfile, "Current allocated heaps and buffers : %lu\n",
1007  n_heaps);
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",
1015  mem_n_allocations);
1016 
1017  mem_last_print_info = mem_n_created_heaps;
1018 
1019  mutex_exit(&mem_hash_mutex);
1020 
1022 
1023  /* mem_validate(); */
1024 
1025  /* fclose(outfile); */
1026 #endif
1027 }
1028 
1029 /*****************************************************************/
1032 UNIV_INTERN
1033 void
1035 /*================*/
1036 {
1037  mem_print_info_low(TRUE);
1038 }
1039 
1040 /*****************************************************************/
1043 UNIV_INTERN
1044 void
1046 /*====================*/
1047 {
1048  mem_print_info_low(FALSE);
1049 }
1050 #endif /* !UNIV_HOTBACKUP */