~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/innobase/buf/buf0buddy.c

Merge initial InnoDB+ import.

This was applied by generating a patch between MySQL 5.1.50 InnoDB plugin and
the just-merged innodb+ from mysql-trunk revision-id: vasil.dimov@oracle.com-20100422110752-1zowoqxel5xx3z2e

Then, some manual merge resolving and it worked. This should make it much
easier to merge the rest of InnoDB 1.1 and 1.2 from the mysql tree using
my bzr-reapply script.

This takes us to InnoDB 1.1.1(ish).

Show diffs side-by-side

added added

removed removed

Lines of Context:
34
34
#include "buf0flu.h"
35
35
#include "page0zip.h"
36
36
 
37
 
/* Statistic counters */
38
 
 
39
 
#ifdef UNIV_DEBUG
40
 
/** Number of frames allocated from the buffer pool to the buddy system.
41
 
Protected by buf_pool_mutex. */
42
 
static ulint buf_buddy_n_frames;
43
 
#endif /* UNIV_DEBUG */
44
 
/** Statistics of the buddy system, indexed by block size.
45
 
Protected by buf_pool_mutex. */
46
 
UNIV_INTERN buf_buddy_stat_t buf_buddy_stat[BUF_BUDDY_SIZES + 1];
47
 
 
48
37
/**********************************************************************//**
49
38
Get the offset of the buddy of a compressed page frame.
50
39
@return the buddy relative of page */
73
62
void
74
63
buf_buddy_add_to_free(
75
64
/*==================*/
76
 
        buf_page_t*     bpage,  /*!< in,own: block to be freed */
77
 
        ulint           i)      /*!< in: index of buf_pool->zip_free[] */
 
65
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
 
66
        buf_page_t*     bpage,          /*!< in,own: block to be freed */
 
67
        ulint           i)              /*!< in: index of
 
68
                                        buf_pool->zip_free[] */
78
69
{
79
70
#ifdef UNIV_DEBUG_VALGRIND
80
71
        buf_page_t*     b  = UT_LIST_GET_FIRST(buf_pool->zip_free[i]);
82
73
        if (b) UNIV_MEM_VALID(b, BUF_BUDDY_LOW << i);
83
74
#endif /* UNIV_DEBUG_VALGRIND */
84
75
 
85
 
        ut_ad(buf_pool_mutex_own());
 
76
        ut_ad(buf_pool_mutex_own(buf_pool));
86
77
        ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_FREE);
87
78
        ut_ad(buf_pool->zip_free[i].start != bpage);
88
79
        UT_LIST_ADD_FIRST(list, buf_pool->zip_free[i], bpage);
99
90
void
100
91
buf_buddy_remove_from_free(
101
92
/*=======================*/
102
 
        buf_page_t*     bpage,  /*!< in: block to be removed */
103
 
        ulint           i)      /*!< in: index of buf_pool->zip_free[] */
 
93
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
 
94
        buf_page_t*     bpage,          /*!< in: block to be removed */
 
95
        ulint           i)              /*!< in: index of
 
96
                                        buf_pool->zip_free[] */
104
97
{
105
98
#ifdef UNIV_DEBUG_VALGRIND
106
99
        buf_page_t*     prev = UT_LIST_GET_PREV(list, bpage);
113
106
        ut_ad(!next || buf_page_get_state(next) == BUF_BLOCK_ZIP_FREE);
114
107
#endif /* UNIV_DEBUG_VALGRIND */
115
108
 
116
 
        ut_ad(buf_pool_mutex_own());
 
109
        ut_ad(buf_pool_mutex_own(buf_pool));
117
110
        ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_FREE);
118
111
        UT_LIST_REMOVE(list, buf_pool->zip_free[i], bpage);
119
112
 
130
123
void*
131
124
buf_buddy_alloc_zip(
132
125
/*================*/
133
 
        ulint   i)      /*!< in: index of buf_pool->zip_free[] */
 
126
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
 
127
        ulint           i)              /*!< in: index of buf_pool->zip_free[] */
134
128
{
135
129
        buf_page_t*     bpage;
136
130
 
137
 
        ut_ad(buf_pool_mutex_own());
 
131
        ut_ad(buf_pool_mutex_own(buf_pool));
138
132
        ut_a(i < BUF_BUDDY_SIZES);
139
133
 
140
134
#ifndef UNIV_DEBUG_VALGRIND
149
143
                UNIV_MEM_VALID(bpage, BUF_BUDDY_LOW << i);
150
144
                ut_a(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_FREE);
151
145
 
152
 
                buf_buddy_remove_from_free(bpage, i);
 
146
                buf_buddy_remove_from_free(buf_pool, bpage, i);
153
147
        } else if (i + 1 < BUF_BUDDY_SIZES) {
154
148
                /* Attempt to split. */
155
 
                bpage = buf_buddy_alloc_zip(i + 1);
 
149
                bpage = buf_buddy_alloc_zip(buf_pool, i + 1);
156
150
 
157
151
                if (bpage) {
158
152
                        buf_page_t*     buddy = (buf_page_t*)
159
153
                                (((char*) bpage) + (BUF_BUDDY_LOW << i));
160
154
 
161
 
                        ut_ad(!buf_pool_contains_zip(buddy));
 
155
                        ut_ad(!buf_pool_contains_zip(buf_pool, buddy));
162
156
                        ut_d(memset(buddy, i, BUF_BUDDY_LOW << i));
163
157
                        buddy->state = BUF_BLOCK_ZIP_FREE;
164
 
                        buf_buddy_add_to_free(buddy, i);
 
158
                        buf_buddy_add_to_free(buf_pool, buddy, i);
165
159
                }
166
160
        }
167
161
 
182
176
void
183
177
buf_buddy_block_free(
184
178
/*=================*/
185
 
        void*   buf)    /*!< in: buffer frame to deallocate */
 
179
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
 
180
        void*           buf)            /*!< in: buffer frame to deallocate */
186
181
{
187
182
        const ulint     fold    = BUF_POOL_ZIP_FOLD_PTR(buf);
188
183
        buf_page_t*     bpage;
189
184
        buf_block_t*    block;
190
185
 
191
 
        ut_ad(buf_pool_mutex_own());
192
 
        ut_ad(!mutex_own(&buf_pool_zip_mutex));
 
186
        ut_ad(buf_pool_mutex_own(buf_pool));
 
187
        ut_ad(!mutex_own(&buf_pool->zip_mutex));
193
188
        ut_a(!ut_align_offset(buf, UNIV_PAGE_SIZE));
194
189
 
195
190
        HASH_SEARCH(hash, buf_pool->zip_hash, fold, buf_page_t*, bpage,
211
206
        buf_LRU_block_free_non_file_page(block);
212
207
        mutex_exit(&block->mutex);
213
208
 
214
 
        ut_ad(buf_buddy_n_frames > 0);
215
 
        ut_d(buf_buddy_n_frames--);
 
209
        ut_ad(buf_pool->buddy_n_frames > 0);
 
210
        ut_d(buf_pool->buddy_n_frames--);
216
211
}
217
212
 
218
213
/**********************************************************************//**
223
218
/*=====================*/
224
219
        buf_block_t*    block)  /*!< in: buffer frame to allocate */
225
220
{
 
221
        buf_pool_t*     buf_pool = buf_pool_from_block(block);
226
222
        const ulint     fold = BUF_POOL_ZIP_FOLD(block);
227
 
        ut_ad(buf_pool_mutex_own());
228
 
        ut_ad(!mutex_own(&buf_pool_zip_mutex));
 
223
        ut_ad(buf_pool_mutex_own(buf_pool));
 
224
        ut_ad(!mutex_own(&buf_pool->zip_mutex));
229
225
        ut_ad(buf_block_get_state(block) == BUF_BLOCK_READY_FOR_USE);
230
226
 
231
227
        buf_block_set_state(block, BUF_BLOCK_MEMORY);
238
234
        ut_d(block->page.in_zip_hash = TRUE);
239
235
        HASH_INSERT(buf_page_t, hash, buf_pool->zip_hash, fold, &block->page);
240
236
 
241
 
        ut_d(buf_buddy_n_frames++);
 
237
        ut_d(buf_pool->buddy_n_frames++);
242
238
}
243
239
 
244
240
/**********************************************************************//**
248
244
void*
249
245
buf_buddy_alloc_from(
250
246
/*=================*/
251
 
        void*           buf,    /*!< in: a block that is free to use */
252
 
        ulint           i,      /*!< in: index of buf_pool->zip_free[] */
253
 
        ulint           j)      /*!< in: size of buf as an index
254
 
                                of buf_pool->zip_free[] */
 
247
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
 
248
        void*           buf,            /*!< in: a block that is free to use */
 
249
        ulint           i,              /*!< in: index of
 
250
                                        buf_pool->zip_free[] */
 
251
        ulint           j)              /*!< in: size of buf as an index
 
252
                                        of buf_pool->zip_free[] */
255
253
{
256
254
        ulint   offs    = BUF_BUDDY_LOW << j;
257
255
        ut_ad(j <= BUF_BUDDY_SIZES);
275
273
                                                    ut_list_node_313)
276
274
                                            == BUF_BLOCK_ZIP_FREE)));
277
275
#endif /* !UNIV_DEBUG_VALGRIND */
278
 
                buf_buddy_add_to_free(bpage, j);
 
276
                buf_buddy_add_to_free(buf_pool, bpage, j);
279
277
        }
280
278
 
281
279
        return(buf);
283
281
 
284
282
/**********************************************************************//**
285
283
Allocate a block.  The thread calling this function must hold
286
 
buf_pool_mutex and must not hold buf_pool_zip_mutex or any block->mutex.
287
 
The buf_pool_mutex may only be released and reacquired if lru != NULL.
 
284
buf_pool->mutex and must not hold buf_pool_zip_mutex or any block->mutex.
 
285
The buf_pool->mutex may only be released and reacquired if lru != NULL.
288
286
@return allocated block, possibly NULL if lru==NULL */
289
287
UNIV_INTERN
290
288
void*
291
289
buf_buddy_alloc_low(
292
290
/*================*/
293
 
        ulint   i,      /*!< in: index of buf_pool->zip_free[],
294
 
                        or BUF_BUDDY_SIZES */
295
 
        ibool*  lru)    /*!< in: pointer to a variable that will be assigned
296
 
                        TRUE if storage was allocated from the LRU list
297
 
                        and buf_pool_mutex was temporarily released,
298
 
                        or NULL if the LRU list should not be used */
 
291
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
 
292
        ulint           i,              /*!< in: index of buf_pool->zip_free[],
 
293
                                        or BUF_BUDDY_SIZES */
 
294
        ibool*          lru)            /*!< in: pointer to a variable that
 
295
                                        will be assigned TRUE if storage was
 
296
                                        allocated from the LRU list and
 
297
                                        buf_pool->mutex was temporarily
 
298
                                        released, or NULL if the LRU list
 
299
                                        should not be used */
299
300
{
300
301
        buf_block_t*    block;
301
302
 
302
 
        ut_ad(buf_pool_mutex_own());
303
 
        ut_ad(!mutex_own(&buf_pool_zip_mutex));
 
303
        ut_ad(buf_pool_mutex_own(buf_pool));
 
304
        ut_ad(!mutex_own(&buf_pool->zip_mutex));
304
305
 
305
306
        if (i < BUF_BUDDY_SIZES) {
306
307
                /* Try to allocate from the buddy system. */
307
 
                block = buf_buddy_alloc_zip(i);
 
308
                block = buf_buddy_alloc_zip(buf_pool, i);
308
309
 
309
310
                if (block) {
310
 
 
311
311
                        goto func_exit;
312
312
                }
313
313
        }
314
314
 
315
315
        /* Try allocating from the buf_pool->free list. */
316
 
        block = buf_LRU_get_free_only();
 
316
        block = buf_LRU_get_free_only(buf_pool);
317
317
 
318
318
        if (block) {
319
319
 
326
326
        }
327
327
 
328
328
        /* Try replacing an uncompressed page in the buffer pool. */
329
 
        buf_pool_mutex_exit();
330
 
        block = buf_LRU_get_free_block(0);
 
329
        buf_pool_mutex_exit(buf_pool);
 
330
        block = buf_LRU_get_free_block(buf_pool, 0);
331
331
        *lru = TRUE;
332
 
        buf_pool_mutex_enter();
 
332
        buf_pool_mutex_enter(buf_pool);
333
333
 
334
334
alloc_big:
335
335
        buf_buddy_block_register(block);
336
336
 
337
 
        block = buf_buddy_alloc_from(block->frame, i, BUF_BUDDY_SIZES);
 
337
        block = buf_buddy_alloc_from(
 
338
                buf_pool, block->frame, i, BUF_BUDDY_SIZES);
338
339
 
339
340
func_exit:
340
 
        buf_buddy_stat[i].used++;
 
341
        buf_pool->buddy_stat[i].used++;
341
342
        return(block);
342
343
}
343
344
 
352
353
        buf_page_t*     dpage)  /*!< in: free block to relocate to */
353
354
{
354
355
        buf_page_t*     b;
 
356
        buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
355
357
 
356
 
        ut_ad(buf_pool_mutex_own());
 
358
        ut_ad(buf_pool_mutex_own(buf_pool));
357
359
 
358
360
        switch (buf_page_get_state(bpage)) {
359
361
        case BUF_BLOCK_ZIP_FREE:
371
373
                break;
372
374
        }
373
375
 
374
 
        mutex_enter(&buf_pool_zip_mutex);
 
376
        mutex_enter(&buf_pool->zip_mutex);
375
377
 
376
378
        if (!buf_page_can_relocate(bpage)) {
377
 
                mutex_exit(&buf_pool_zip_mutex);
 
379
                mutex_exit(&buf_pool->zip_mutex);
378
380
                return(FALSE);
379
381
        }
380
382
 
393
395
 
394
396
        UNIV_MEM_INVALID(bpage, sizeof *bpage);
395
397
 
396
 
        mutex_exit(&buf_pool_zip_mutex);
 
398
        mutex_exit(&buf_pool->zip_mutex);
397
399
        return(TRUE);
398
400
}
399
401
 
404
406
ibool
405
407
buf_buddy_relocate(
406
408
/*===============*/
407
 
        void*   src,    /*!< in: block to relocate */
408
 
        void*   dst,    /*!< in: free block to relocate to */
409
 
        ulint   i)      /*!< in: index of buf_pool->zip_free[] */
 
409
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
 
410
        void*           src,            /*!< in: block to relocate */
 
411
        void*           dst,            /*!< in: free block to relocate to */
 
412
        ulint           i)              /*!< in: index of
 
413
                                        buf_pool->zip_free[] */
410
414
{
411
415
        buf_page_t*     bpage;
412
416
        const ulint     size    = BUF_BUDDY_LOW << i;
413
417
        ullint          usec    = ut_time_us(NULL);
414
418
 
415
 
        ut_ad(buf_pool_mutex_own());
416
 
        ut_ad(!mutex_own(&buf_pool_zip_mutex));
 
419
        ut_ad(buf_pool_mutex_own(buf_pool));
 
420
        ut_ad(!mutex_own(&buf_pool->zip_mutex));
417
421
        ut_ad(!ut_align_offset(src, size));
418
422
        ut_ad(!ut_align_offset(dst, size));
419
423
        UNIV_MEM_ASSERT_W(dst, size);
442
446
                pool), so there is nothing wrong about this.  The
443
447
                mach_read_from_4() calls here will only trigger bogus
444
448
                Valgrind memcheck warnings in UNIV_DEBUG_VALGRIND builds. */
445
 
                ulint           space   = mach_read_from_4(
446
 
                        (const byte*) src + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
447
 
                ulint           page_no = mach_read_from_4(
448
 
                        (const byte*) src + FIL_PAGE_OFFSET);
449
 
                /* Suppress Valgrind warnings about conditional jump
450
 
                on uninitialized value. */
451
 
                UNIV_MEM_VALID(&space, sizeof space);
452
 
                UNIV_MEM_VALID(&page_no, sizeof page_no);
453
 
                bpage = buf_page_hash_get(space, page_no);
 
449
                bpage = buf_page_hash_get(
 
450
                        buf_pool,
 
451
                        mach_read_from_4((const byte*) src
 
452
                                         + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID),
 
453
                        mach_read_from_4((const byte*) src
 
454
                                         + FIL_PAGE_OFFSET));
454
455
 
455
456
                if (!bpage || bpage->zip.data != src) {
456
457
                        /* The block has probably been freshly
461
462
                        return(FALSE);
462
463
                }
463
464
 
 
465
                ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage));
 
466
 
464
467
                if (page_zip_get_size(&bpage->zip) != size) {
465
468
                        /* The block is of different size.  We would
466
469
                        have to relocate all blocks covered by src.
488
491
                        UNIV_MEM_INVALID(src, size);
489
492
                        {
490
493
                                buf_buddy_stat_t*       buddy_stat
491
 
                                        = &buf_buddy_stat[i];
 
494
                                        = &buf_pool->buddy_stat[i];
492
495
                                buddy_stat->relocated++;
493
496
                                buddy_stat->relocated_usec
494
497
                                        += ut_time_us(NULL) - usec;
499
502
                mutex_exit(mutex);
500
503
        } else if (i == buf_buddy_get_slot(sizeof(buf_page_t))) {
501
504
                /* This must be a buf_page_t object. */
502
 
#if UNIV_WORD_SIZE == 4
503
 
                /* On 32-bit systems, there is no padding in
504
 
                buf_page_t.  On other systems, Valgrind could complain
505
 
                about uninitialized pad bytes. */
506
505
                UNIV_MEM_ASSERT_RW(src, size);
507
 
#endif
508
506
                if (buf_buddy_relocate_block(src, dst)) {
509
507
 
510
508
                        goto success;
520
518
void
521
519
buf_buddy_free_low(
522
520
/*===============*/
523
 
        void*   buf,    /*!< in: block to be freed, must not be
524
 
                        pointed to by the buffer pool */
525
 
        ulint   i)      /*!< in: index of buf_pool->zip_free[],
526
 
                        or BUF_BUDDY_SIZES */
 
521
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
 
522
        void*           buf,            /*!< in: block to be freed, must not be
 
523
                                        pointed to by the buffer pool */
 
524
        ulint           i)              /*!< in: index of buf_pool->zip_free[],
 
525
                                        or BUF_BUDDY_SIZES */
527
526
{
528
527
        buf_page_t*     bpage;
529
528
        buf_page_t*     buddy;
530
529
 
531
 
        ut_ad(buf_pool_mutex_own());
532
 
        ut_ad(!mutex_own(&buf_pool_zip_mutex));
 
530
        ut_ad(buf_pool_mutex_own(buf_pool));
 
531
        ut_ad(!mutex_own(&buf_pool->zip_mutex));
533
532
        ut_ad(i <= BUF_BUDDY_SIZES);
534
 
        ut_ad(buf_buddy_stat[i].used > 0);
 
533
        ut_ad(buf_pool->buddy_stat[i].used > 0);
535
534
 
536
 
        buf_buddy_stat[i].used--;
 
535
        buf_pool->buddy_stat[i].used--;
537
536
recombine:
538
537
        UNIV_MEM_ASSERT_AND_ALLOC(buf, BUF_BUDDY_LOW << i);
539
538
        ut_d(((buf_page_t*) buf)->state = BUF_BLOCK_ZIP_FREE);
540
539
 
541
540
        if (i == BUF_BUDDY_SIZES) {
542
 
                buf_buddy_block_free(buf);
 
541
                buf_buddy_block_free(buf_pool, buf);
543
542
                return;
544
543
        }
545
544
 
546
545
        ut_ad(i < BUF_BUDDY_SIZES);
547
546
        ut_ad(buf == ut_align_down(buf, BUF_BUDDY_LOW << i));
548
 
        ut_ad(!buf_pool_contains_zip(buf));
 
547
        ut_ad(!buf_pool_contains_zip(buf_pool, buf));
549
548
 
550
549
        /* Try to combine adjacent blocks. */
551
550
 
571
570
                if (bpage == buddy) {
572
571
buddy_free:
573
572
                        /* The buddy is free: recombine */
574
 
                        buf_buddy_remove_from_free(bpage, i);
 
573
                        buf_buddy_remove_from_free(buf_pool, bpage, i);
575
574
buddy_free2:
576
575
                        ut_ad(buf_page_get_state(buddy) == BUF_BLOCK_ZIP_FREE);
577
 
                        ut_ad(!buf_pool_contains_zip(buddy));
 
576
                        ut_ad(!buf_pool_contains_zip(buf_pool, buddy));
578
577
                        i++;
579
578
                        buf = ut_align_down(buf, BUF_BUDDY_LOW << i);
580
579
 
606
605
                buf_buddy_relocate() will overwrite bpage->list. */
607
606
 
608
607
                UNIV_MEM_VALID(bpage, BUF_BUDDY_LOW << i);
609
 
                buf_buddy_remove_from_free(bpage, i);
 
608
                buf_buddy_remove_from_free(buf_pool, bpage, i);
610
609
 
611
610
                /* Try to relocate the buddy of buf to the free block. */
612
 
                if (buf_buddy_relocate(buddy, bpage, i)) {
 
611
                if (buf_buddy_relocate(buf_pool, buddy, bpage, i)) {
613
612
 
614
613
                        ut_d(buddy->state = BUF_BLOCK_ZIP_FREE);
615
614
                        goto buddy_free2;
616
615
                }
617
616
 
618
 
                buf_buddy_add_to_free(bpage, i);
 
617
                buf_buddy_add_to_free(buf_pool, bpage, i);
619
618
 
620
619
                /* Try to relocate the buddy of the free block to buf. */
621
620
                buddy = (buf_page_t*) buf_buddy_get(((byte*) bpage),
636
635
                                            && ut_list_node_313 != buddy)));
637
636
#endif /* !UNIV_DEBUG_VALGRIND */
638
637
 
639
 
                if (buf_buddy_relocate(buddy, buf, i)) {
 
638
                if (buf_buddy_relocate(buf_pool, buddy, buf, i)) {
640
639
 
641
640
                        buf = bpage;
642
641
                        UNIV_MEM_VALID(bpage, BUF_BUDDY_LOW << i);
699
698
        }
700
699
#endif /* UNIV_DEBUG */
701
700
        bpage->state = BUF_BLOCK_ZIP_FREE;
702
 
        buf_buddy_add_to_free(bpage, i);
 
701
        buf_buddy_add_to_free(buf_pool, bpage, i);
703
702
}