~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

Merge Revision revid:svn-v4:16c675df-0fcb-4bc9-8058-dcc011a37293:branches/zip:6790 from MySQL InnoDB

Original revid:svn-v4:16c675df-0fcb-4bc9-8058-dcc011a37293:branches/zip:6790

Original Authors: jyang
Original commit message:
branches/zip: Fix bug #51356: "many valgrind errors in error messages
with concurrent ddl". Null terminate the name string returned
from innobase_convert_identifier() call when reporting DB_DUPLICATE_KEY
error in create_table_def().
rb://266 approved by Marko

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*****************************************************************************
2
2
 
3
 
Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
 
3
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
4
4
 
5
5
This program is free software; you can redistribute it and/or modify it under
6
6
the terms of the GNU General Public License as published by the Free Software
88
88
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
89
89
 
90
90
/********************************************************************//**
91
 
Insert a block in the flush_rbt and returns a pointer to its
92
 
predecessor or NULL if no predecessor. The ordering is maintained
93
 
on the basis of the <oldest_modification, space, offset> key.
94
 
@return pointer to the predecessor or NULL if no predecessor. */
95
 
static
96
 
buf_page_t*
97
 
buf_flush_insert_in_flush_rbt(
98
 
/*==========================*/
99
 
        buf_page_t*     bpage)          /*!< in: bpage to be inserted. */
100
 
{
101
 
        buf_page_t*             prev = NULL;
102
 
        const ib_rbt_node_t*    c_node;
103
 
        const ib_rbt_node_t*    p_node;
104
 
 
105
 
        ut_ad(buf_pool_mutex_own());
106
 
 
107
 
        /* Insert this buffer into the rbt. */
108
 
        c_node = rbt_insert(buf_pool->flush_rbt, &bpage, &bpage);
109
 
        ut_a(c_node != NULL);
110
 
 
111
 
        /* Get the predecessor. */
112
 
        p_node = rbt_prev(buf_pool->flush_rbt, c_node);
113
 
 
114
 
        if (p_node != NULL) {
115
 
                prev = *rbt_value(buf_page_t*, p_node);
116
 
                ut_a(prev != NULL);
117
 
        }
118
 
 
119
 
        return(prev);
120
 
}
121
 
 
122
 
/********************************************************************//**
123
 
Delete a bpage from the flush_rbt. */
124
 
static
125
 
void
126
 
buf_flush_delete_from_flush_rbt(
127
 
/*============================*/
128
 
        buf_page_t*     bpage)          /*!< in: bpage to be removed. */
129
 
{
130
 
 
131
 
        ibool   ret = FALSE;
132
 
 
133
 
        ut_ad(buf_pool_mutex_own());
134
 
        ret = rbt_delete(buf_pool->flush_rbt, &bpage);
135
 
        ut_ad(ret);
136
 
}
137
 
 
138
 
/********************************************************************//**
139
 
Compare two modified blocks in the buffer pool. The key for comparison
140
 
is:
141
 
key = <oldest_modification, space, offset>
142
 
This comparison is used to maintian ordering of blocks in the
143
 
buf_pool->flush_rbt.
144
 
Note that for the purpose of flush_rbt, we only need to order blocks
145
 
on the oldest_modification. The other two fields are used to uniquely
146
 
identify the blocks.
147
 
@return < 0 if b2 < b1, 0 if b2 == b1, > 0 if b2 > b1 */
148
 
static
149
 
int
150
 
buf_flush_block_cmp(
151
 
/*================*/
152
 
        const void*     p1,             /*!< in: block1 */
153
 
        const void*     p2)             /*!< in: block2 */
154
 
{
155
 
        int             ret;
156
 
 
157
 
        ut_ad(p1 != NULL);
158
 
        ut_ad(p2 != NULL);
159
 
 
160
 
        const buf_page_t* b1 = *(const buf_page_t**) p1;
161
 
        const buf_page_t* b2 = *(const buf_page_t**) p2;
162
 
 
163
 
        ut_ad(b1 != NULL);
164
 
        ut_ad(b2 != NULL);
165
 
 
166
 
        ut_ad(b1->in_flush_list);
167
 
        ut_ad(b2->in_flush_list);
168
 
 
169
 
        if (b2->oldest_modification
170
 
            > b1->oldest_modification) {
171
 
                return(1);
172
 
        }
173
 
 
174
 
        if (b2->oldest_modification
175
 
            < b1->oldest_modification) {
176
 
                return(-1);
177
 
        }
178
 
 
179
 
        /* If oldest_modification is same then decide on the space. */
180
 
        ret = (int)(b2->space - b1->space);
181
 
 
182
 
        /* Or else decide ordering on the offset field. */
183
 
        return(ret ? ret : (int)(b2->offset - b1->offset));
184
 
}
185
 
 
186
 
/********************************************************************//**
187
 
Initialize the red-black tree to speed up insertions into the flush_list
188
 
during recovery process. Should be called at the start of recovery
189
 
process before any page has been read/written. */
190
 
UNIV_INTERN
191
 
void
192
 
buf_flush_init_flush_rbt(void)
193
 
/*==========================*/
194
 
{
195
 
        buf_pool_mutex_enter();
196
 
 
197
 
        /* Create red black tree for speedy insertions in flush list. */
198
 
        buf_pool->flush_rbt = rbt_create(sizeof(buf_page_t*),
199
 
                                         buf_flush_block_cmp);
200
 
        buf_pool_mutex_exit();
201
 
}
202
 
 
203
 
/********************************************************************//**
204
 
Frees up the red-black tree. */
205
 
UNIV_INTERN
206
 
void
207
 
buf_flush_free_flush_rbt(void)
208
 
/*==========================*/
209
 
{
210
 
        buf_pool_mutex_enter();
211
 
 
212
 
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
213
 
        ut_a(buf_flush_validate_low());
214
 
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
215
 
 
216
 
        rbt_free(buf_pool->flush_rbt);
217
 
        buf_pool->flush_rbt = NULL;
218
 
 
219
 
        buf_pool_mutex_exit();
220
 
}
221
 
 
222
 
/********************************************************************//**
223
91
Inserts a modified block into the flush list. */
224
92
UNIV_INTERN
225
93
void
232
100
              || (UT_LIST_GET_FIRST(buf_pool->flush_list)->oldest_modification
233
101
                  <= block->page.oldest_modification));
234
102
 
235
 
        /* If we are in the recovery then we need to update the flush
236
 
        red-black tree as well. */
237
 
        if (UNIV_LIKELY_NULL(buf_pool->flush_rbt)) {
238
 
                buf_flush_insert_sorted_into_flush_list(block);
239
 
                return;
240
 
        }
241
 
 
242
103
        ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
243
104
        ut_ad(block->page.in_LRU_list);
244
105
        ut_ad(block->page.in_page_hash);
275
136
        ut_d(block->page.in_flush_list = TRUE);
276
137
 
277
138
        prev_b = NULL;
278
 
 
279
 
        /* For the most part when this function is called the flush_rbt
280
 
        should not be NULL. In a very rare boundary case it is possible
281
 
        that the flush_rbt has already been freed by the recovery thread
282
 
        before the last page was hooked up in the flush_list by the
283
 
        io-handler thread. In that case we'll  just do a simple
284
 
        linear search in the else block. */
285
 
        if (buf_pool->flush_rbt) {
286
 
 
287
 
                prev_b = buf_flush_insert_in_flush_rbt(&block->page);
288
 
 
289
 
        } else {
290
 
 
291
 
                b = UT_LIST_GET_FIRST(buf_pool->flush_list);
292
 
 
293
 
                while (b && b->oldest_modification
294
 
                       > block->page.oldest_modification) {
295
 
                        ut_ad(b->in_flush_list);
296
 
                        prev_b = b;
297
 
                        b = UT_LIST_GET_NEXT(list, b);
298
 
                }
 
139
        b = UT_LIST_GET_FIRST(buf_pool->flush_list);
 
140
 
 
141
        while (b && b->oldest_modification > block->page.oldest_modification) {
 
142
                ut_ad(b->in_flush_list);
 
143
                prev_b = b;
 
144
                b = UT_LIST_GET_NEXT(list, b);
299
145
        }
300
146
 
301
147
        if (prev_b == NULL) {
391
237
        ut_ad(buf_pool_mutex_own());
392
238
        ut_ad(mutex_own(buf_page_get_mutex(bpage)));
393
239
        ut_ad(bpage->in_flush_list);
 
240
        ut_d(bpage->in_flush_list = FALSE);
394
241
 
395
242
        switch (buf_page_get_state(bpage)) {
396
243
        case BUF_BLOCK_ZIP_PAGE:
412
259
                break;
413
260
        }
414
261
 
415
 
        /* If the flush_rbt is active then delete from it as well. */
416
 
        if (UNIV_LIKELY_NULL(buf_pool->flush_rbt)) {
417
 
                buf_flush_delete_from_flush_rbt(bpage);
418
 
        }
419
 
 
420
 
        /* Must be done after we have removed it from the flush_rbt
421
 
        because we assert on in_flush_list in comparison function. */
422
 
        ut_d(bpage->in_flush_list = FALSE);
423
 
 
424
262
        bpage->oldest_modification = 0;
425
263
 
426
264
        ut_d(UT_LIST_VALIDATE(list, buf_page_t, buf_pool->flush_list,
428
266
}
429
267
 
430
268
/********************************************************************//**
431
 
Relocates a buffer control block on the flush_list.
432
 
Note that it is assumed that the contents of bpage has already been
433
 
copied to dpage. */
434
 
UNIV_INTERN
435
 
void
436
 
buf_flush_relocate_on_flush_list(
437
 
/*=============================*/
438
 
        buf_page_t*     bpage,  /*!< in/out: control block being moved */
439
 
        buf_page_t*     dpage)  /*!< in/out: destination block */
440
 
{
441
 
        buf_page_t* prev;
442
 
        buf_page_t* prev_b = NULL;
443
 
 
444
 
        ut_ad(buf_pool_mutex_own());
445
 
 
446
 
        ut_ad(mutex_own(buf_page_get_mutex(bpage)));
447
 
 
448
 
        ut_ad(bpage->in_flush_list);
449
 
        ut_ad(dpage->in_flush_list);
450
 
 
451
 
        /* If recovery is active we must swap the control blocks in
452
 
        the flush_rbt as well. */
453
 
        if (UNIV_LIKELY_NULL(buf_pool->flush_rbt)) {
454
 
                buf_flush_delete_from_flush_rbt(bpage);
455
 
                prev_b = buf_flush_insert_in_flush_rbt(dpage);
456
 
        }
457
 
 
458
 
        /* Must be done after we have removed it from the flush_rbt
459
 
        because we assert on in_flush_list in comparison function. */
460
 
        ut_d(bpage->in_flush_list = FALSE);
461
 
 
462
 
        prev = UT_LIST_GET_PREV(list, bpage);
463
 
        UT_LIST_REMOVE(list, buf_pool->flush_list, bpage);
464
 
 
465
 
        if (prev) {
466
 
                ut_ad(prev->in_flush_list);
467
 
                UT_LIST_INSERT_AFTER(
468
 
                        list,
469
 
                        buf_pool->flush_list,
470
 
                        prev, dpage);
471
 
        } else {
472
 
                UT_LIST_ADD_FIRST(
473
 
                        list,
474
 
                        buf_pool->flush_list,
475
 
                        dpage);
476
 
        }
477
 
 
478
 
        /* Just an extra check. Previous in flush_list
479
 
        should be the same control block as in flush_rbt. */
480
 
        ut_a(!buf_pool->flush_rbt || prev_b == prev);
481
 
 
482
 
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
483
 
        ut_a(buf_flush_validate_low());
484
 
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
485
 
}
486
 
 
487
 
/********************************************************************//**
488
269
Updates the flush system data structures when a write is completed. */
489
270
UNIV_INTERN
490
271
void
1588
1369
buf_flush_validate_low(void)
1589
1370
/*========================*/
1590
1371
{
1591
 
        buf_page_t*             bpage;
1592
 
        const ib_rbt_node_t*    rnode = NULL;
 
1372
        buf_page_t*     bpage;
1593
1373
 
1594
1374
        UT_LIST_VALIDATE(list, buf_page_t, buf_pool->flush_list,
1595
1375
                         ut_ad(ut_list_node_313->in_flush_list));
1596
1376
 
1597
1377
        bpage = UT_LIST_GET_FIRST(buf_pool->flush_list);
1598
1378
 
1599
 
        /* If we are in recovery mode i.e.: flush_rbt != NULL
1600
 
        then each block in the flush_list must also be present
1601
 
        in the flush_rbt. */
1602
 
        if (UNIV_LIKELY_NULL(buf_pool->flush_rbt)) {
1603
 
                rnode = rbt_first(buf_pool->flush_rbt);
1604
 
        }
1605
 
 
1606
1379
        while (bpage != NULL) {
1607
1380
                const ib_uint64_t om = bpage->oldest_modification;
1608
1381
                ut_ad(bpage->in_flush_list);
1609
1382
                ut_a(buf_page_in_file(bpage));
1610
1383
                ut_a(om > 0);
1611
1384
 
1612
 
                if (UNIV_LIKELY_NULL(buf_pool->flush_rbt)) {
1613
 
                        ut_a(rnode);
1614
 
                        buf_page_t* rpage = *rbt_value(buf_page_t*,
1615
 
                                                       rnode);
1616
 
                        ut_a(rpage);
1617
 
                        ut_a(rpage == bpage);
1618
 
                        rnode = rbt_next(buf_pool->flush_rbt, rnode);
1619
 
                }
1620
 
 
1621
1385
                bpage = UT_LIST_GET_NEXT(list, bpage);
1622
1386
 
1623
1387
                ut_a(!bpage || om >= bpage->oldest_modification);
1624
1388
        }
1625
1389
 
1626
 
        /* By this time we must have exhausted the traversal of
1627
 
        flush_rbt (if active) as well. */
1628
 
        ut_a(rnode == NULL);
1629
 
 
1630
1390
        return(TRUE);
1631
1391
}
1632
1392