~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/innobase/mem/mem0dbg.c

  • Committer: Daniel Nichter
  • Date: 2011-10-23 16:01:37 UTC
  • mto: This revision was merged to the branch mainline in revision 2448.
  • Revision ID: daniel@percona.com-20111023160137-7ac3blgz8z4tf8za
Add Administration Getting Started and Logging.  Capitalize SQL clause keywords.

Show diffs side-by-side

added added

removed removed

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