Drizzled Public API Documentation

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