~mysql/mysql-server/mysql-6.0

« back to all changes in this revision

Viewing changes to innobase/buf/buf0lru.c

  • Committer: monty at mysql
  • Date: 2001-02-17 12:19:19 UTC
  • mto: (554.1.1)
  • mto: This revision was merged to the branch mainline in revision 556.
  • Revision ID: sp1r-monty@donna.mysql.com-20010217121919-07904
Added Innobase to source distribution

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/******************************************************
 
2
The database buffer replacement algorithm
 
3
 
 
4
(c) 1995 Innobase Oy
 
5
 
 
6
Created 11/5/1995 Heikki Tuuri
 
7
*******************************************************/
 
8
 
 
9
#include "buf0lru.h"
 
10
 
 
11
#ifdef UNIV_NONINL
 
12
#include "buf0lru.ic"
 
13
#endif
 
14
 
 
15
#include "ut0byte.h"
 
16
#include "ut0lst.h"
 
17
#include "ut0rnd.h"
 
18
#include "sync0sync.h"
 
19
#include "sync0rw.h"
 
20
#include "hash0hash.h"
 
21
#include "os0sync.h"
 
22
#include "fil0fil.h"
 
23
#include "btr0btr.h"
 
24
#include "buf0buf.h"
 
25
#include "buf0flu.h"
 
26
#include "buf0rea.h"
 
27
#include "btr0sea.h"
 
28
#include "os0file.h"
 
29
 
 
30
/* The number of blocks from the LRU_old pointer onward, including the block
 
31
pointed to, must be 3/8 of the whole LRU list length, except that the
 
32
tolerance defined below is allowed. Note that the tolerance must be small
 
33
enough such that for even the BUF_LRU_OLD_MIN_LEN long LRU list, the
 
34
LRU_old pointer is not allowed to point to either end of the LRU list. */
 
35
 
 
36
#define BUF_LRU_OLD_TOLERANCE   20
 
37
 
 
38
/* The whole LRU list length is divided by this number to determine an
 
39
initial segment in buf_LRU_get_recent_limit */
 
40
 
 
41
#define BUF_LRU_INITIAL_RATIO   8
 
42
 
 
43
/**********************************************************************
 
44
Takes a block out of the LRU list and page hash table and sets the block
 
45
state to BUF_BLOCK_REMOVE_HASH. */
 
46
static
 
47
void
 
48
buf_LRU_block_remove_hashed_page(
 
49
/*=============================*/
 
50
        buf_block_t*    block); /* in: block, must contain a file page and
 
51
                                be in a state where it can be freed; there
 
52
                                may or may not be a hash index to the page */
 
53
/**********************************************************************
 
54
Puts a file page whose has no hash index to the free list. */
 
55
static
 
56
void
 
57
buf_LRU_block_free_hashed_page(
 
58
/*===========================*/
 
59
        buf_block_t*    block); /* in: block, must contain a file page and
 
60
                                be in a state where it can be freed */
 
61
 
 
62
/**********************************************************************
 
63
Gets the minimum LRU_position field for the blocks in an initial segment
 
64
(determined by BUF_LRU_INITIAL_RATIO) of the LRU list. The limit is not
 
65
guaranteed to be precise, because the ulint_clock may wrap around. */
 
66
 
 
67
ulint
 
68
buf_LRU_get_recent_limit(void)
 
69
/*==========================*/
 
70
                        /* out: the limit; zero if could not determine it */
 
71
{
 
72
        buf_block_t*    block;
 
73
        ulint           len;
 
74
        ulint           limit;
 
75
 
 
76
        mutex_enter(&(buf_pool->mutex));
 
77
 
 
78
        len = UT_LIST_GET_LEN(buf_pool->LRU);
 
79
 
 
80
        if (len < BUF_LRU_OLD_MIN_LEN) {
 
81
                /* The LRU list is too short to do read-ahead */
 
82
 
 
83
                mutex_exit(&(buf_pool->mutex));
 
84
 
 
85
                return(0);
 
86
        }
 
87
 
 
88
        block = UT_LIST_GET_FIRST(buf_pool->LRU);
 
89
 
 
90
        limit = block->LRU_position - len / BUF_LRU_INITIAL_RATIO;
 
91
 
 
92
        mutex_exit(&(buf_pool->mutex));
 
93
 
 
94
        return(limit);
 
95
}
 
96
 
 
97
/**********************************************************************
 
98
Look for a replaceable block from the end of the LRU list and put it to
 
99
the free list if found. */
 
100
 
 
101
ibool
 
102
buf_LRU_search_and_free_block(
 
103
/*==========================*/
 
104
                                /* out: TRUE if freed */
 
105
        ulint   n_iterations)   /* in: how many times this has been called
 
106
                                repeatedly without result: a high value
 
107
                                means that we should search farther */
 
108
{
 
109
        buf_block_t*    block;
 
110
        ulint           distance;
 
111
        ibool           freed;
 
112
        ulint           i;
 
113
 
 
114
        mutex_enter(&(buf_pool->mutex));
 
115
        
 
116
        freed = FALSE;
 
117
        
 
118
        distance = BUF_LRU_FREE_SEARCH_LEN * (1 + n_iterations / 5);
 
119
 
 
120
        i = 0;
 
121
        block = UT_LIST_GET_LAST(buf_pool->LRU);
 
122
 
 
123
        while (i < distance && block != NULL) {
 
124
 
 
125
                if (buf_flush_ready_for_replace(block)) {
 
126
 
 
127
                        if (buf_debug_prints) {
 
128
                                printf(
 
129
                                "Putting space %lu page %lu to free list\n",
 
130
                                        block->space, block->offset);
 
131
                        }
 
132
                        
 
133
                        buf_LRU_block_remove_hashed_page(block);
 
134
 
 
135
                        mutex_exit(&(buf_pool->mutex));
 
136
 
 
137
                        btr_search_drop_page_hash_index(block->frame);
 
138
 
 
139
                        mutex_enter(&(buf_pool->mutex));
 
140
 
 
141
                        buf_LRU_block_free_hashed_page(block);
 
142
 
 
143
                        freed = TRUE;
 
144
 
 
145
                        break;
 
146
                }
 
147
 
 
148
                block = UT_LIST_GET_PREV(LRU, block);
 
149
        }
 
150
 
 
151
        if (buf_pool->LRU_flush_ended > 0) {
 
152
                buf_pool->LRU_flush_ended--;
 
153
        }
 
154
 
 
155
        if (!freed) {
 
156
                buf_pool->LRU_flush_ended = 0;
 
157
        }
 
158
 
 
159
        mutex_exit(&(buf_pool->mutex));
 
160
        
 
161
        return(freed);
 
162
}
 
163
        
 
164
/**********************************************************************
 
165
Tries to remove LRU flushed blocks from the end of the LRU list and put them
 
166
to the free list. This is beneficial for the efficiency of the insert buffer
 
167
operation, as flushed pages from non-unique non-clustered indexes are here
 
168
taken out of the buffer pool, and their inserts redirected to the insert
 
169
buffer. Otherwise, the flushed blocks could get modified again before read
 
170
operations need new buffer blocks, and the i/o work done in flushing would be
 
171
wasted. */
 
172
 
 
173
void
 
174
buf_LRU_try_free_flushed_blocks(void)
 
175
/*=================================*/
 
176
{
 
177
        mutex_enter(&(buf_pool->mutex));
 
178
 
 
179
        while (buf_pool->LRU_flush_ended > 0) {
 
180
 
 
181
                mutex_exit(&(buf_pool->mutex));
 
182
 
 
183
                buf_LRU_search_and_free_block(0);
 
184
                
 
185
                mutex_enter(&(buf_pool->mutex));
 
186
        }
 
187
 
 
188
        mutex_exit(&(buf_pool->mutex));
 
189
}       
 
190
 
 
191
/**********************************************************************
 
192
Returns a free block from buf_pool. The block is taken off the free list.
 
193
If it is empty, blocks are moved from the end of the LRU list to the free
 
194
list. */
 
195
 
 
196
buf_block_t*
 
197
buf_LRU_get_free_block(void)
 
198
/*========================*/
 
199
                                /* out: the free control block */
 
200
{
 
201
        buf_block_t*    block           = NULL;
 
202
        ibool           freed;
 
203
        ulint           n_iterations    = 0;
 
204
loop:
 
205
        mutex_enter(&(buf_pool->mutex));
 
206
 
 
207
        if (buf_pool->LRU_flush_ended > 0) {
 
208
                mutex_exit(&(buf_pool->mutex));
 
209
 
 
210
                buf_LRU_try_free_flushed_blocks();
 
211
                
 
212
                mutex_enter(&(buf_pool->mutex));
 
213
        }
 
214
        
 
215
        /* If there is a block in the free list, take it */
 
216
        if (UT_LIST_GET_LEN(buf_pool->free) > 0) {
 
217
                
 
218
                block = UT_LIST_GET_FIRST(buf_pool->free);
 
219
                UT_LIST_REMOVE(free, buf_pool->free, block);
 
220
                block->state = BUF_BLOCK_READY_FOR_USE;
 
221
 
 
222
                mutex_exit(&(buf_pool->mutex));
 
223
                
 
224
                return(block);
 
225
        }
 
226
        
 
227
        /* If no block was in the free list, search from the end of the LRU
 
228
        list and try to free a block there */
 
229
 
 
230
        mutex_exit(&(buf_pool->mutex));
 
231
 
 
232
        freed = buf_LRU_search_and_free_block(n_iterations);
 
233
 
 
234
        if (freed > 0) {
 
235
                goto loop;
 
236
        }
 
237
 
 
238
        /* No free block was found near the end of the list: try to flush
 
239
        the LRU list */
 
240
 
 
241
        buf_flush_free_margin();
 
242
 
 
243
        os_event_wait(buf_pool->no_flush[BUF_FLUSH_LRU]);
 
244
 
 
245
        n_iterations++;
 
246
 
 
247
        os_aio_simulated_wake_handler_threads();
 
248
 
 
249
        if (n_iterations > 10) {
 
250
 
 
251
                os_thread_sleep(500000);
 
252
        }
 
253
 
 
254
        if (n_iterations > 20) {
 
255
/*              buf_print();
 
256
                os_aio_print();
 
257
                rw_lock_list_print_info();
 
258
*/
 
259
                if (n_iterations > 30) {
 
260
                        fprintf(stderr,
 
261
                "Innobase: Warning: difficult to find free blocks from\n"
 
262
                "Innobase: the buffer pool! Consider increasing the\n"
 
263
                "Innobase: buffer pool size.\n");
 
264
                }
 
265
        }
 
266
 
 
267
        goto loop;      
 
268
}       
 
269
 
 
270
/***********************************************************************
 
271
Moves the LRU_old pointer so that the length of the old blocks list
 
272
is inside the allowed limits. */
 
273
UNIV_INLINE
 
274
void
 
275
buf_LRU_old_adjust_len(void)
 
276
/*========================*/
 
277
{
 
278
        ulint   old_len;
 
279
        ulint   new_len;
 
280
 
 
281
        ut_ad(buf_pool->LRU_old);
 
282
        ut_ad(mutex_own(&(buf_pool->mutex)));
 
283
        ut_ad(3 * (BUF_LRU_OLD_MIN_LEN / 8) > BUF_LRU_OLD_TOLERANCE + 5);
 
284
 
 
285
        for (;;) {
 
286
                old_len = buf_pool->LRU_old_len;
 
287
                new_len = 3 * (UT_LIST_GET_LEN(buf_pool->LRU) / 8);
 
288
 
 
289
                /* Update the LRU_old pointer if necessary */
 
290
        
 
291
                if (old_len < new_len - BUF_LRU_OLD_TOLERANCE) {
 
292
                
 
293
                        buf_pool->LRU_old = UT_LIST_GET_PREV(LRU,
 
294
                                                        buf_pool->LRU_old);
 
295
                        (buf_pool->LRU_old)->old = TRUE;
 
296
                        buf_pool->LRU_old_len++;
 
297
 
 
298
                } else if (old_len > new_len + BUF_LRU_OLD_TOLERANCE) {
 
299
 
 
300
                        (buf_pool->LRU_old)->old = FALSE;
 
301
                        buf_pool->LRU_old = UT_LIST_GET_NEXT(LRU,
 
302
                                                        buf_pool->LRU_old);
 
303
                        buf_pool->LRU_old_len--;
 
304
                } else {
 
305
                        ut_ad(buf_pool->LRU_old); /* Check that we did not
 
306
                                                fall out of the LRU list */
 
307
                        return;
 
308
                }
 
309
        }
 
310
}
 
311
 
 
312
/***********************************************************************
 
313
Initializes the old blocks pointer in the LRU list.
 
314
This function should be called when the LRU list grows to
 
315
BUF_LRU_OLD_MIN_LEN length. */
 
316
static
 
317
void
 
318
buf_LRU_old_init(void)
 
319
/*==================*/
 
320
{
 
321
        buf_block_t*    block;
 
322
 
 
323
        ut_ad(UT_LIST_GET_LEN(buf_pool->LRU) == BUF_LRU_OLD_MIN_LEN);
 
324
 
 
325
        /* We first initialize all blocks in the LRU list as old and then use
 
326
        the adjust function to move the LRU_old pointer to the right
 
327
        position */
 
328
 
 
329
        block = UT_LIST_GET_FIRST(buf_pool->LRU);
 
330
 
 
331
        while (block != NULL) {
 
332
                block->old = TRUE;
 
333
                block = UT_LIST_GET_NEXT(LRU, block);
 
334
        }
 
335
 
 
336
        buf_pool->LRU_old = UT_LIST_GET_FIRST(buf_pool->LRU);
 
337
        buf_pool->LRU_old_len = UT_LIST_GET_LEN(buf_pool->LRU);
 
338
        
 
339
        buf_LRU_old_adjust_len();
 
340
}               
 
341
 
 
342
/**********************************************************************
 
343
Removes a block from the LRU list. */
 
344
UNIV_INLINE
 
345
void
 
346
buf_LRU_remove_block(
 
347
/*=================*/
 
348
        buf_block_t*    block)  /* in: control block */
 
349
{
 
350
        ut_ad(buf_pool);
 
351
        ut_ad(block);
 
352
        ut_ad(mutex_own(&(buf_pool->mutex)));
 
353
                
 
354
        /* If the LRU_old pointer is defined and points to just this block,
 
355
        move it backward one step */
 
356
 
 
357
        if (block == buf_pool->LRU_old) {
 
358
 
 
359
                /* Below: the previous block is guaranteed to exist, because
 
360
                the LRU_old pointer is only allowed to differ by the
 
361
                tolerance value from strict 3/8 of the LRU list length. */
 
362
 
 
363
                buf_pool->LRU_old = UT_LIST_GET_PREV(LRU, block);
 
364
                (buf_pool->LRU_old)->old = TRUE;
 
365
 
 
366
                buf_pool->LRU_old_len++;
 
367
                ut_ad(buf_pool->LRU_old);
 
368
        }
 
369
 
 
370
        /* Remove the block from the LRU list */
 
371
        UT_LIST_REMOVE(LRU, buf_pool->LRU, block);
 
372
 
 
373
        /* If the LRU list is so short that LRU_old not defined, return */
 
374
        if (UT_LIST_GET_LEN(buf_pool->LRU) < BUF_LRU_OLD_MIN_LEN) {
 
375
 
 
376
                buf_pool->LRU_old = NULL;
 
377
 
 
378
                return;
 
379
        }
 
380
 
 
381
        ut_ad(buf_pool->LRU_old);       
 
382
 
 
383
        /* Update the LRU_old_len field if necessary */
 
384
        if (block->old) {
 
385
 
 
386
                buf_pool->LRU_old_len--;
 
387
        }
 
388
 
 
389
        /* Adjust the length of the old block list if necessary */
 
390
        buf_LRU_old_adjust_len();
 
391
}               
 
392
 
 
393
/**********************************************************************
 
394
Adds a block to the LRU list end. */
 
395
UNIV_INLINE
 
396
void
 
397
buf_LRU_add_block_to_end_low(
 
398
/*=========================*/
 
399
        buf_block_t*    block)  /* in: control block */
 
400
{
 
401
        buf_block_t*    last_block;
 
402
        
 
403
        ut_ad(buf_pool);
 
404
        ut_ad(block);
 
405
        ut_ad(mutex_own(&(buf_pool->mutex)));
 
406
 
 
407
        block->old = TRUE;
 
408
 
 
409
        last_block = UT_LIST_GET_LAST(buf_pool->LRU);
 
410
 
 
411
        if (last_block) {
 
412
                block->LRU_position = last_block->LRU_position;
 
413
        } else {
 
414
                block->LRU_position = buf_pool_clock_tic();
 
415
        }                       
 
416
 
 
417
        UT_LIST_ADD_LAST(LRU, buf_pool->LRU, block);
 
418
 
 
419
        if (UT_LIST_GET_LEN(buf_pool->LRU) >= BUF_LRU_OLD_MIN_LEN) {
 
420
 
 
421
                buf_pool->LRU_old_len++;
 
422
        }
 
423
 
 
424
        if (UT_LIST_GET_LEN(buf_pool->LRU) > BUF_LRU_OLD_MIN_LEN) {
 
425
 
 
426
                ut_ad(buf_pool->LRU_old);
 
427
 
 
428
                /* Adjust the length of the old block list if necessary */
 
429
 
 
430
                buf_LRU_old_adjust_len();
 
431
 
 
432
        } else if (UT_LIST_GET_LEN(buf_pool->LRU) == BUF_LRU_OLD_MIN_LEN) {
 
433
 
 
434
                /* The LRU list is now long enough for LRU_old to become
 
435
                defined: init it */
 
436
 
 
437
                buf_LRU_old_init();
 
438
        }       
 
439
}               
 
440
 
 
441
/**********************************************************************
 
442
Adds a block to the LRU list. */
 
443
UNIV_INLINE
 
444
void
 
445
buf_LRU_add_block_low(
 
446
/*==================*/
 
447
        buf_block_t*    block,  /* in: control block */
 
448
        ibool           old)    /* in: TRUE if should be put to the old blocks
 
449
                                in the LRU list, else put to the start; if the
 
450
                                LRU list is very short, the block is added to
 
451
                                the start, regardless of this parameter */
 
452
{
 
453
        ulint   cl;
 
454
        
 
455
        ut_ad(buf_pool);
 
456
        ut_ad(block);
 
457
        ut_ad(mutex_own(&(buf_pool->mutex)));
 
458
 
 
459
        block->old = old;
 
460
        cl = buf_pool_clock_tic();
 
461
 
 
462
        if (!old || (UT_LIST_GET_LEN(buf_pool->LRU) < BUF_LRU_OLD_MIN_LEN)) {
 
463
 
 
464
                UT_LIST_ADD_FIRST(LRU, buf_pool->LRU, block);
 
465
 
 
466
                block->LRU_position = cl;               
 
467
                block->freed_page_clock = buf_pool->freed_page_clock;
 
468
        } else {
 
469
                UT_LIST_INSERT_AFTER(LRU, buf_pool->LRU, buf_pool->LRU_old,
 
470
                                                                block);
 
471
                buf_pool->LRU_old_len++;
 
472
 
 
473
                /* We copy the LRU position field of the previous block
 
474
                to the new block */
 
475
 
 
476
                block->LRU_position = (buf_pool->LRU_old)->LRU_position;
 
477
        }
 
478
 
 
479
        if (UT_LIST_GET_LEN(buf_pool->LRU) > BUF_LRU_OLD_MIN_LEN) {
 
480
 
 
481
                ut_ad(buf_pool->LRU_old);
 
482
 
 
483
                /* Adjust the length of the old block list if necessary */
 
484
 
 
485
                buf_LRU_old_adjust_len();
 
486
 
 
487
        } else if (UT_LIST_GET_LEN(buf_pool->LRU) == BUF_LRU_OLD_MIN_LEN) {
 
488
 
 
489
                /* The LRU list is now long enough for LRU_old to become
 
490
                defined: init it */
 
491
 
 
492
                buf_LRU_old_init();
 
493
        }       
 
494
}               
 
495
 
 
496
/**********************************************************************
 
497
Adds a block to the LRU list. */
 
498
 
 
499
void
 
500
buf_LRU_add_block(
 
501
/*==============*/
 
502
        buf_block_t*    block,  /* in: control block */
 
503
        ibool           old)    /* in: TRUE if should be put to the old
 
504
                                blocks in the LRU list, else put to the start;
 
505
                                if the LRU list is very short, the block is
 
506
                                added to the start, regardless of this
 
507
                                parameter */
 
508
{
 
509
        buf_LRU_add_block_low(block, old);
 
510
}
 
511
 
 
512
/**********************************************************************
 
513
Moves a block to the start of the LRU list. */
 
514
 
 
515
void
 
516
buf_LRU_make_block_young(
 
517
/*=====================*/
 
518
        buf_block_t*    block)  /* in: control block */
 
519
{
 
520
        buf_LRU_remove_block(block);
 
521
        buf_LRU_add_block_low(block, FALSE);
 
522
}
 
523
 
 
524
/**********************************************************************
 
525
Moves a block to the end of the LRU list. */
 
526
 
 
527
void
 
528
buf_LRU_make_block_old(
 
529
/*===================*/
 
530
        buf_block_t*    block)  /* in: control block */
 
531
{
 
532
        buf_LRU_remove_block(block);
 
533
        buf_LRU_add_block_to_end_low(block);
 
534
}
 
535
 
 
536
/**********************************************************************
 
537
Puts a block back to the free list. */
 
538
 
 
539
void
 
540
buf_LRU_block_free_non_file_page(
 
541
/*=============================*/
 
542
        buf_block_t*    block)  /* in: block, must not contain a file page */
 
543
{
 
544
        ut_ad(mutex_own(&(buf_pool->mutex)));
 
545
        ut_ad(block);
 
546
        
 
547
        ut_ad((block->state == BUF_BLOCK_MEMORY)
 
548
              || (block->state == BUF_BLOCK_READY_FOR_USE));
 
549
 
 
550
        block->state = BUF_BLOCK_NOT_USED;
 
551
 
 
552
        UT_LIST_ADD_FIRST(free, buf_pool->free, block);
 
553
}
 
554
 
 
555
/**********************************************************************
 
556
Takes a block out of the LRU list and page hash table and sets the block
 
557
state to BUF_BLOCK_REMOVE_HASH. */
 
558
static
 
559
void
 
560
buf_LRU_block_remove_hashed_page(
 
561
/*=============================*/
 
562
        buf_block_t*    block)  /* in: block, must contain a file page and
 
563
                                be in a state where it can be freed; there
 
564
                                may or may not be a hash index to the page */
 
565
{
 
566
        ut_ad(mutex_own(&(buf_pool->mutex)));
 
567
        ut_ad(block);
 
568
        
 
569
        ut_ad(block->state == BUF_BLOCK_FILE_PAGE);
 
570
 
 
571
        ut_a(block->io_fix == 0);
 
572
        ut_a(block->buf_fix_count == 0);
 
573
        ut_a(ut_dulint_cmp(block->oldest_modification, ut_dulint_zero) == 0);
 
574
 
 
575
        buf_LRU_remove_block(block);
 
576
 
 
577
        buf_pool->freed_page_clock += 1;
 
578
 
 
579
        buf_frame_modify_clock_inc(block->frame);
 
580
                
 
581
        HASH_DELETE(buf_block_t, hash, buf_pool->page_hash,
 
582
                        buf_page_address_fold(block->space, block->offset),
 
583
                        block);
 
584
 
 
585
        block->state = BUF_BLOCK_REMOVE_HASH;
 
586
}
 
587
 
 
588
/**********************************************************************
 
589
Puts a file page whose has no hash index to the free list. */
 
590
static
 
591
void
 
592
buf_LRU_block_free_hashed_page(
 
593
/*===========================*/
 
594
        buf_block_t*    block)  /* in: block, must contain a file page and
 
595
                                be in a state where it can be freed */
 
596
{
 
597
        ut_ad(mutex_own(&(buf_pool->mutex)));
 
598
        ut_ad(block->state == BUF_BLOCK_REMOVE_HASH);
 
599
 
 
600
        block->state = BUF_BLOCK_MEMORY;
 
601
 
 
602
        buf_LRU_block_free_non_file_page(block);
 
603
}
 
604
                                
 
605
/**************************************************************************
 
606
Validates the LRU list. */
 
607
 
 
608
ibool
 
609
buf_LRU_validate(void)
 
610
/*==================*/
 
611
{
 
612
        buf_block_t*    block;
 
613
        ulint           old_len;
 
614
        ulint           new_len;
 
615
        ulint           LRU_pos;
 
616
        
 
617
        ut_ad(buf_pool);
 
618
        mutex_enter(&(buf_pool->mutex));
 
619
 
 
620
        if (UT_LIST_GET_LEN(buf_pool->LRU) >= BUF_LRU_OLD_MIN_LEN) {
 
621
 
 
622
                ut_a(buf_pool->LRU_old);
 
623
                old_len = buf_pool->LRU_old_len;
 
624
                new_len = 3 * (UT_LIST_GET_LEN(buf_pool->LRU) / 8);
 
625
                ut_a(old_len >= new_len - BUF_LRU_OLD_TOLERANCE);
 
626
                ut_a(old_len <= new_len + BUF_LRU_OLD_TOLERANCE);
 
627
        }
 
628
                
 
629
        UT_LIST_VALIDATE(LRU, buf_block_t, buf_pool->LRU);
 
630
 
 
631
        block = UT_LIST_GET_FIRST(buf_pool->LRU);
 
632
 
 
633
        old_len = 0;
 
634
 
 
635
        while (block != NULL) {
 
636
 
 
637
                ut_a(block->state == BUF_BLOCK_FILE_PAGE);
 
638
 
 
639
                if (block->old) {
 
640
                        old_len++;
 
641
                }
 
642
 
 
643
                if (buf_pool->LRU_old && (old_len == 1)) {
 
644
                        ut_a(buf_pool->LRU_old == block);
 
645
                }
 
646
 
 
647
                LRU_pos = block->LRU_position;
 
648
 
 
649
                block = UT_LIST_GET_NEXT(LRU, block);
 
650
 
 
651
                if (block) {
 
652
                        /* If the following assert fails, it may
 
653
                        not be an error: just the buf_pool clock
 
654
                        has wrapped around */
 
655
                        ut_a(LRU_pos >= block->LRU_position);
 
656
                }
 
657
        }
 
658
 
 
659
        if (buf_pool->LRU_old) {
 
660
                ut_a(buf_pool->LRU_old_len == old_len);
 
661
        } 
 
662
 
 
663
        UT_LIST_VALIDATE(free, buf_block_t, buf_pool->free);
 
664
 
 
665
        block = UT_LIST_GET_FIRST(buf_pool->free);
 
666
 
 
667
        while (block != NULL) {
 
668
                ut_a(block->state == BUF_BLOCK_NOT_USED);
 
669
 
 
670
                block = UT_LIST_GET_NEXT(free, block);
 
671
        }
 
672
 
 
673
        mutex_exit(&(buf_pool->mutex));
 
674
        return(TRUE);
 
675
}
 
676
 
 
677
/**************************************************************************
 
678
Prints the LRU list. */
 
679
 
 
680
void
 
681
buf_LRU_print(void)
 
682
/*===============*/
 
683
{
 
684
        buf_block_t*    block;
 
685
        buf_frame_t*    frame;
 
686
        ulint           len;
 
687
        
 
688
        ut_ad(buf_pool);
 
689
        mutex_enter(&(buf_pool->mutex));
 
690
 
 
691
        printf("Pool ulint clock %lu\n", buf_pool->ulint_clock);
 
692
 
 
693
        block = UT_LIST_GET_FIRST(buf_pool->LRU);
 
694
 
 
695
        len = 0;
 
696
 
 
697
        while (block != NULL) {
 
698
 
 
699
                printf("BLOCK %lu ", block->offset);
 
700
 
 
701
                if (block->old) {
 
702
                        printf("old ");
 
703
                }
 
704
 
 
705
                if (block->buf_fix_count) {
 
706
                        printf("buffix count %lu ", block->buf_fix_count);
 
707
                }
 
708
 
 
709
                if (block->io_fix) {
 
710
                        printf("io_fix %lu ", block->io_fix);
 
711
                }
 
712
 
 
713
                if (ut_dulint_cmp(block->oldest_modification,
 
714
                                ut_dulint_zero) > 0) {
 
715
                        printf("modif. ");
 
716
                }
 
717
 
 
718
                printf("LRU pos %lu ", block->LRU_position);
 
719
                
 
720
                frame = buf_block_get_frame(block);
 
721
 
 
722
                printf("type %lu ", fil_page_get_type(frame));
 
723
                printf("index id %lu ", ut_dulint_get_low(
 
724
                                        btr_page_get_index_id(frame)));
 
725
 
 
726
                block = UT_LIST_GET_NEXT(LRU, block);
 
727
                len++;
 
728
                if (len % 10 == 0) {
 
729
                        printf("\n");
 
730
                }
 
731
        }
 
732
 
 
733
        mutex_exit(&(buf_pool->mutex));
 
734
}