~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/innobase/buf/buf0lru.c

  • Committer: Brian Aker
  • Date: 2008-09-04 19:31:00 UTC
  • Revision ID: brian@tangent.org-20080904193100-l849hgghfy4urj43
Changing default character set from this point on.

Show diffs side-by-side

added added

removed removed

Lines of Context:
10
10
 
11
11
#ifdef UNIV_NONINL
12
12
#include "buf0lru.ic"
 
13
#include "srv0srv.h"    /* Needed to getsrv_print_innodb_monitor */
13
14
#endif
14
15
 
15
16
#include "ut0byte.h"
21
22
#include "os0sync.h"
22
23
#include "fil0fil.h"
23
24
#include "btr0btr.h"
24
 
#include "buf0buddy.h"
25
25
#include "buf0buf.h"
26
26
#include "buf0flu.h"
27
27
#include "buf0rea.h"
28
28
#include "btr0sea.h"
29
29
#include "os0file.h"
30
 
#include "page0zip.h"
31
30
#include "log0recv.h"
32
 
#include "srv0srv.h"
33
31
 
34
32
/* The number of blocks from the LRU_old pointer onward, including the block
35
33
pointed to, must be 3/8 of the whole LRU list length, except that the
46
44
 
47
45
/* If we switch on the InnoDB monitor because there are too few available
48
46
frames in the buffer pool, we set this to TRUE */
49
 
UNIV_INTERN ibool       buf_lru_switched_on_innodb_mon  = FALSE;
50
 
 
51
 
/**********************************************************************
52
 
These statistics are not 'of' LRU but 'for' LRU.  We keep count of I/O
53
 
and page_zip_decompress() operations.  Based on the statistics,
54
 
buf_LRU_evict_from_unzip_LRU() decides if we want to evict from
55
 
unzip_LRU or the regular LRU.  From unzip_LRU, we will only evict the
56
 
uncompressed frame (meaning we can evict dirty blocks as well).  From
57
 
the regular LRU, we will evict the entire block (i.e.: both the
58
 
uncompressed and compressed data), which must be clean. */
59
 
 
60
 
/* Number of intervals for which we keep the history of these stats.
61
 
Each interval is 1 second, defined by the rate at which
62
 
srv_error_monitor_thread() calls buf_LRU_stat_update(). */
63
 
#define BUF_LRU_STAT_N_INTERVAL 50
64
 
 
65
 
/* Co-efficient with which we multiply I/O operations to equate them
66
 
with page_zip_decompress() operations. */
67
 
#define BUF_LRU_IO_TO_UNZIP_FACTOR 50
68
 
 
69
 
/* Sampled values buf_LRU_stat_cur.
70
 
Protected by buf_pool_mutex.  Updated by buf_LRU_stat_update(). */
71
 
static buf_LRU_stat_t           buf_LRU_stat_arr[BUF_LRU_STAT_N_INTERVAL];
72
 
/* Cursor to buf_LRU_stat_arr[] that is updated in a round-robin fashion. */
73
 
static ulint                    buf_LRU_stat_arr_ind;
74
 
 
75
 
/* Current operation counters.  Not protected by any mutex.  Cleared
76
 
by buf_LRU_stat_update(). */
77
 
UNIV_INTERN buf_LRU_stat_t      buf_LRU_stat_cur;
78
 
 
79
 
/* Running sum of past values of buf_LRU_stat_cur.
80
 
Updated by buf_LRU_stat_update().  Protected by buf_pool_mutex. */
81
 
UNIV_INTERN buf_LRU_stat_t      buf_LRU_stat_sum;
82
 
 
83
 
/**********************************************************************
84
 
Takes a block out of the LRU list and page hash table.
85
 
If the block is compressed-only (BUF_BLOCK_ZIP_PAGE),
86
 
the object will be freed and buf_pool_zip_mutex will be released.
87
 
 
88
 
If a compressed page or a compressed-only block descriptor is freed,
89
 
other compressed pages or compressed-only block descriptors may be
90
 
relocated. */
 
47
ibool   buf_lru_switched_on_innodb_mon  = FALSE;
 
48
 
 
49
/**********************************************************************
 
50
Takes a block out of the LRU list and page hash table and sets the block
 
51
state to BUF_BLOCK_REMOVE_HASH. */
91
52
static
92
 
enum buf_page_state
 
53
void
93
54
buf_LRU_block_remove_hashed_page(
94
55
/*=============================*/
95
 
                                /* out: the new state of the block
96
 
                                (BUF_BLOCK_ZIP_FREE if the state was
97
 
                                BUF_BLOCK_ZIP_PAGE, or BUF_BLOCK_REMOVE_HASH
98
 
                                otherwise) */
99
 
        buf_page_t*     bpage,  /* in: block, must contain a file page and
 
56
        buf_block_t*    block); /* in: block, must contain a file page and
100
57
                                be in a state where it can be freed; there
101
58
                                may or may not be a hash index to the page */
102
 
        ibool           zip);   /* in: TRUE if should remove also the
103
 
                                compressed page of an uncompressed page */
104
59
/**********************************************************************
105
60
Puts a file page whose has no hash index to the free list. */
106
61
static
111
66
                                be in a state where it can be freed */
112
67
 
113
68
/**********************************************************************
114
 
Determines if the unzip_LRU list should be used for evicting a victim
115
 
instead of the general LRU list. */
116
 
UNIV_INLINE
117
 
ibool
118
 
buf_LRU_evict_from_unzip_LRU(void)
119
 
/*==============================*/
120
 
                                /* out: TRUE if should use unzip_LRU */
121
 
{
122
 
        ulint   io_avg;
123
 
        ulint   unzip_avg;
124
 
 
125
 
        ut_ad(buf_pool_mutex_own());
126
 
 
127
 
        /* If the unzip_LRU list is empty, we can only use the LRU. */
128
 
        if (UT_LIST_GET_LEN(buf_pool->unzip_LRU) == 0) {
129
 
                return(FALSE);
130
 
        }
131
 
 
132
 
        /* If unzip_LRU is at most 10% of the size of the LRU list,
133
 
        then use the LRU.  This slack allows us to keep hot
134
 
        decompressed pages in the buffer pool. */
135
 
        if (UT_LIST_GET_LEN(buf_pool->unzip_LRU)
136
 
            <= UT_LIST_GET_LEN(buf_pool->LRU) / 10) {
137
 
                return(FALSE);
138
 
        }
139
 
 
140
 
        /* If eviction hasn't started yet, we assume by default
141
 
        that a workload is disk bound. */
142
 
        if (buf_pool->freed_page_clock == 0) {
143
 
                return(TRUE);
144
 
        }
145
 
 
146
 
        /* Calculate the average over past intervals, and add the values
147
 
        of the current interval. */
148
 
        io_avg = buf_LRU_stat_sum.io / BUF_LRU_STAT_N_INTERVAL
149
 
                + buf_LRU_stat_cur.io;
150
 
        unzip_avg = buf_LRU_stat_sum.unzip / BUF_LRU_STAT_N_INTERVAL
151
 
                + buf_LRU_stat_cur.unzip;
152
 
 
153
 
        /* Decide based on our formula.  If the load is I/O bound
154
 
        (unzip_avg is smaller than the weighted io_avg), evict an
155
 
        uncompressed frame from unzip_LRU.  Otherwise we assume that
156
 
        the load is CPU bound and evict from the regular LRU. */
157
 
        return(unzip_avg <= io_avg * BUF_LRU_IO_TO_UNZIP_FACTOR);
158
 
}
159
 
 
160
 
/**********************************************************************
161
69
Invalidates all pages belonging to a given tablespace when we are deleting
162
70
the data file(s) of that tablespace. */
163
 
UNIV_INTERN
 
71
 
164
72
void
165
73
buf_LRU_invalidate_tablespace(
166
74
/*==========================*/
167
75
        ulint   id)     /* in: space id */
168
76
{
169
 
        buf_page_t*     bpage;
 
77
        buf_block_t*    block;
170
78
        ulint           page_no;
171
79
        ibool           all_freed;
172
80
 
173
81
scan_again:
174
 
        buf_pool_mutex_enter();
 
82
        mutex_enter(&(buf_pool->mutex));
175
83
 
176
84
        all_freed = TRUE;
177
85
 
178
 
        bpage = UT_LIST_GET_LAST(buf_pool->LRU);
179
 
 
180
 
        while (bpage != NULL) {
181
 
                mutex_t*        block_mutex = buf_page_get_mutex(bpage);
182
 
                buf_page_t*     prev_bpage;
183
 
 
184
 
                ut_a(buf_page_in_file(bpage));
185
 
 
186
 
                mutex_enter(block_mutex);
187
 
                prev_bpage = UT_LIST_GET_PREV(LRU, bpage);
188
 
 
189
 
                if (buf_page_get_space(bpage) == id) {
190
 
                        if (bpage->buf_fix_count > 0
191
 
                            || buf_page_get_io_fix(bpage) != BUF_IO_NONE) {
192
 
 
193
 
                                /* We cannot remove this page during
194
 
                                this scan yet; maybe the system is
195
 
                                currently reading it in, or flushing
196
 
                                the modifications to the file */
197
 
 
198
 
                                all_freed = FALSE;
199
 
 
200
 
                                goto next_page;
201
 
                        }
202
 
 
 
86
        block = UT_LIST_GET_LAST(buf_pool->LRU);
 
87
 
 
88
        while (block != NULL) {
 
89
                buf_block_t*    prev_block;
 
90
 
 
91
                mutex_enter(&block->mutex);
 
92
                prev_block = UT_LIST_GET_PREV(LRU, block);
 
93
 
 
94
                ut_a(block->state == BUF_BLOCK_FILE_PAGE);
 
95
 
 
96
                if (block->space == id
 
97
                    && (block->buf_fix_count > 0 || block->io_fix != 0)) {
 
98
 
 
99
                        /* We cannot remove this page during this scan yet;
 
100
                        maybe the system is currently reading it in, or
 
101
                        flushing the modifications to the file */
 
102
 
 
103
                        all_freed = FALSE;
 
104
 
 
105
                        goto next_page;
 
106
                }
 
107
 
 
108
                if (block->space == id) {
203
109
#ifdef UNIV_DEBUG
204
110
                        if (buf_debug_prints) {
205
111
                                fprintf(stderr,
206
112
                                        "Dropping space %lu page %lu\n",
207
 
                                        (ulong) buf_page_get_space(bpage),
208
 
                                        (ulong) buf_page_get_page_no(bpage));
 
113
                                        (ulong) block->space,
 
114
                                        (ulong) block->offset);
209
115
                        }
210
116
#endif
211
 
                        if (buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE
212
 
                            && ((buf_block_t*) bpage)->is_hashed) {
213
 
                                page_no = buf_page_get_page_no(bpage);
214
 
 
215
 
                                buf_pool_mutex_exit();
216
 
                                mutex_exit(block_mutex);
 
117
                        if (block->is_hashed) {
 
118
                                page_no = block->offset;
 
119
 
 
120
                                mutex_exit(&block->mutex);
 
121
 
 
122
                                mutex_exit(&(buf_pool->mutex));
217
123
 
218
124
                                /* Note that the following call will acquire
219
125
                                an S-latch on the page */
220
126
 
221
 
                                btr_search_drop_page_hash_when_freed(
222
 
                                        id,
223
 
                                        buf_page_get_zip_size(bpage),
224
 
                                        page_no);
 
127
                                btr_search_drop_page_hash_when_freed(id,
 
128
                                                                     page_no);
225
129
                                goto scan_again;
226
130
                        }
227
131
 
228
 
                        if (bpage->oldest_modification != 0) {
229
 
 
230
 
                                buf_flush_remove(bpage);
 
132
                        if (0 != ut_dulint_cmp(block->oldest_modification,
 
133
                                               ut_dulint_zero)) {
 
134
 
 
135
                                /* Remove from the flush list of modified
 
136
                                blocks */
 
137
                                block->oldest_modification = ut_dulint_zero;
 
138
 
 
139
                                UT_LIST_REMOVE(flush_list,
 
140
                                               buf_pool->flush_list, block);
231
141
                        }
232
142
 
233
143
                        /* Remove from the LRU list */
234
 
                        if (buf_LRU_block_remove_hashed_page(bpage, TRUE)
235
 
                            != BUF_BLOCK_ZIP_FREE) {
236
 
                                buf_LRU_block_free_hashed_page((buf_block_t*)
237
 
                                                               bpage);
238
 
                        } else {
239
 
                                /* The compressed block descriptor
240
 
                                (bpage) has been deallocated and
241
 
                                block_mutex released.  Also,
242
 
                                buf_buddy_free() may have relocated
243
 
                                prev_bpage.  Rescan the LRU list. */
244
 
 
245
 
                                bpage = UT_LIST_GET_LAST(buf_pool->LRU);
246
 
                                continue;
247
 
                        }
 
144
                        buf_LRU_block_remove_hashed_page(block);
 
145
                        buf_LRU_block_free_hashed_page(block);
248
146
                }
249
147
next_page:
250
 
                mutex_exit(block_mutex);
251
 
                bpage = prev_bpage;
 
148
                mutex_exit(&block->mutex);
 
149
                block = prev_block;
252
150
        }
253
151
 
254
 
        buf_pool_mutex_exit();
 
152
        mutex_exit(&(buf_pool->mutex));
255
153
 
256
154
        if (!all_freed) {
257
155
                os_thread_sleep(20000);
264
162
Gets the minimum LRU_position field for the blocks in an initial segment
265
163
(determined by BUF_LRU_INITIAL_RATIO) of the LRU list. The limit is not
266
164
guaranteed to be precise, because the ulint_clock may wrap around. */
267
 
UNIV_INTERN
 
165
 
268
166
ulint
269
167
buf_LRU_get_recent_limit(void)
270
168
/*==========================*/
271
169
                        /* out: the limit; zero if could not determine it */
272
170
{
273
 
        const buf_page_t*       bpage;
274
 
        ulint                   len;
275
 
        ulint                   limit;
 
171
        buf_block_t*    block;
 
172
        ulint           len;
 
173
        ulint           limit;
276
174
 
277
 
        buf_pool_mutex_enter();
 
175
        mutex_enter(&(buf_pool->mutex));
278
176
 
279
177
        len = UT_LIST_GET_LEN(buf_pool->LRU);
280
178
 
281
179
        if (len < BUF_LRU_OLD_MIN_LEN) {
282
180
                /* The LRU list is too short to do read-ahead */
283
181
 
284
 
                buf_pool_mutex_exit();
 
182
                mutex_exit(&(buf_pool->mutex));
285
183
 
286
184
                return(0);
287
185
        }
288
186
 
289
 
        bpage = UT_LIST_GET_FIRST(buf_pool->LRU);
290
 
 
291
 
        limit = buf_page_get_LRU_position(bpage) - len / BUF_LRU_INITIAL_RATIO;
292
 
 
293
 
        buf_pool_mutex_exit();
 
187
        block = UT_LIST_GET_FIRST(buf_pool->LRU);
 
188
 
 
189
        limit = block->LRU_position - len / BUF_LRU_INITIAL_RATIO;
 
190
 
 
191
        mutex_exit(&(buf_pool->mutex));
294
192
 
295
193
        return(limit);
296
194
}
297
195
 
298
 
/************************************************************************
299
 
Insert a compressed block into buf_pool->zip_clean in the LRU order. */
300
 
UNIV_INTERN
301
 
void
302
 
buf_LRU_insert_zip_clean(
303
 
/*=====================*/
304
 
        buf_page_t*     bpage)  /* in: pointer to the block in question */
305
 
{
306
 
        buf_page_t*     b;
307
 
 
308
 
        ut_ad(buf_pool_mutex_own());
309
 
        ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_PAGE);
310
 
 
311
 
        /* Find the first successor of bpage in the LRU list
312
 
        that is in the zip_clean list. */
313
 
        b = bpage;
314
 
        do {
315
 
                b = UT_LIST_GET_NEXT(LRU, b);
316
 
        } while (b && buf_page_get_state(b) != BUF_BLOCK_ZIP_PAGE);
317
 
 
318
 
        /* Insert bpage before b, i.e., after the predecessor of b. */
319
 
        if (b) {
320
 
                b = UT_LIST_GET_PREV(list, b);
321
 
        }
322
 
 
323
 
        if (b) {
324
 
                UT_LIST_INSERT_AFTER(list, buf_pool->zip_clean, b, bpage);
325
 
        } else {
326
 
                UT_LIST_ADD_FIRST(list, buf_pool->zip_clean, bpage);
327
 
        }
328
 
}
329
 
 
330
196
/**********************************************************************
331
 
Try to free an uncompressed page of a compressed block from the unzip
332
 
LRU list.  The compressed page is preserved, and it need not be clean. */
333
 
UNIV_INLINE
 
197
Look for a replaceable block from the end of the LRU list and put it to
 
198
the free list if found. */
 
199
 
334
200
ibool
335
 
buf_LRU_free_from_unzip_LRU_list(
336
 
/*=============================*/
 
201
buf_LRU_search_and_free_block(
 
202
/*==========================*/
337
203
                                /* out: TRUE if freed */
338
204
        ulint   n_iterations)   /* in: how many times this has been called
339
205
                                repeatedly without result: a high value means
340
 
                                that we should search farther; we will search
341
 
                                n_iterations / 5 of the unzip_LRU list,
342
 
                                or nothing if n_iterations >= 5 */
 
206
                                that we should search farther; if value is
 
207
                                k < 10, then we only search k/10 * [number
 
208
                                of pages in the buffer pool] from the end
 
209
                                of the LRU list */
343
210
{
344
211
        buf_block_t*    block;
345
 
        ulint           distance;
346
 
 
347
 
        ut_ad(buf_pool_mutex_own());
348
 
 
349
 
        /* Theoratically it should be much easier to find a victim
350
 
        from unzip_LRU as we can choose even a dirty block (as we'll
351
 
        be evicting only the uncompressed frame).  In a very unlikely
352
 
        eventuality that we are unable to find a victim from
353
 
        unzip_LRU, we fall back to the regular LRU list.  We do this
354
 
        if we have done five iterations so far. */
355
 
 
356
 
        if (UNIV_UNLIKELY(n_iterations >= 5)
357
 
            || !buf_LRU_evict_from_unzip_LRU()) {
358
 
 
359
 
                return(FALSE);
360
 
        }
361
 
 
362
 
        distance = 100 + (n_iterations
363
 
                          * UT_LIST_GET_LEN(buf_pool->unzip_LRU)) / 5;
364
 
 
365
 
        for (block = UT_LIST_GET_LAST(buf_pool->unzip_LRU);
366
 
             UNIV_LIKELY(block != NULL) && UNIV_LIKELY(distance > 0);
367
 
             block = UT_LIST_GET_PREV(unzip_LRU, block), distance--) {
368
 
 
369
 
                enum buf_lru_free_block_status  freed;
370
 
 
371
 
                ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
372
 
                ut_ad(block->in_unzip_LRU_list);
373
 
                ut_ad(block->page.in_LRU_list);
 
212
        ulint           distance = 0;
 
213
        ibool           freed;
 
214
 
 
215
        mutex_enter(&(buf_pool->mutex));
 
216
 
 
217
        freed = FALSE;
 
218
        block = UT_LIST_GET_LAST(buf_pool->LRU);
 
219
 
 
220
        while (block != NULL) {
 
221
                ut_a(block->in_LRU_list);
374
222
 
375
223
                mutex_enter(&block->mutex);
376
 
                freed = buf_LRU_free_block(&block->page, FALSE, NULL);
 
224
 
 
225
                if (buf_flush_ready_for_replace(block)) {
 
226
 
 
227
#ifdef UNIV_DEBUG
 
228
                        if (buf_debug_prints) {
 
229
                                fprintf(stderr,
 
230
                                        "Putting space %lu page %lu"
 
231
                                        " to free list\n",
 
232
                                        (ulong) block->space,
 
233
                                        (ulong) block->offset);
 
234
                        }
 
235
#endif /* UNIV_DEBUG */
 
236
 
 
237
                        buf_LRU_block_remove_hashed_page(block);
 
238
 
 
239
                        mutex_exit(&(buf_pool->mutex));
 
240
                        mutex_exit(&block->mutex);
 
241
 
 
242
                        /* Remove possible adaptive hash index built on the
 
243
                        page; in the case of AWE the block may not have a
 
244
                        frame at all */
 
245
 
 
246
                        if (block->frame) {
 
247
                                /* The page was declared uninitialized
 
248
                                by buf_LRU_block_remove_hashed_page().
 
249
                                We need to flag the contents of the
 
250
                                page valid (which it still is) in
 
251
                                order to avoid bogus Valgrind
 
252
                                warnings. */
 
253
                                UNIV_MEM_VALID(block->frame, UNIV_PAGE_SIZE);
 
254
                                btr_search_drop_page_hash_index(block->frame);
 
255
                                UNIV_MEM_INVALID(block->frame, UNIV_PAGE_SIZE);
 
256
                        }
 
257
 
 
258
                        ut_a(block->buf_fix_count == 0);
 
259
 
 
260
                        mutex_enter(&(buf_pool->mutex));
 
261
                        mutex_enter(&block->mutex);
 
262
 
 
263
                        buf_LRU_block_free_hashed_page(block);
 
264
                        freed = TRUE;
 
265
                        mutex_exit(&block->mutex);
 
266
 
 
267
                        break;
 
268
                }
 
269
 
377
270
                mutex_exit(&block->mutex);
378
271
 
379
 
                switch (freed) {
380
 
                case BUF_LRU_FREED:
381
 
                        return(TRUE);
382
 
 
383
 
                case BUF_LRU_CANNOT_RELOCATE:
384
 
                        /* If we failed to relocate, try
385
 
                        regular LRU eviction. */
 
272
                block = UT_LIST_GET_PREV(LRU, block);
 
273
                distance++;
 
274
 
 
275
                if (!freed && n_iterations <= 10
 
276
                    && distance > 100 + (n_iterations * buf_pool->curr_size)
 
277
                    / 10) {
 
278
                        buf_pool->LRU_flush_ended = 0;
 
279
 
 
280
                        mutex_exit(&(buf_pool->mutex));
 
281
 
386
282
                        return(FALSE);
387
 
 
388
 
                case BUF_LRU_NOT_FREED:
389
 
                        /* The block was buffer-fixed or I/O-fixed.
390
 
                        Keep looking. */
391
 
                        continue;
392
 
                }
393
 
 
394
 
                /* inappropriate return value from
395
 
                buf_LRU_free_block() */
396
 
                ut_error;
397
 
        }
398
 
 
399
 
        return(FALSE);
400
 
}
401
 
 
402
 
/**********************************************************************
403
 
Try to free a clean page from the common LRU list. */
404
 
UNIV_INLINE
405
 
ibool
406
 
buf_LRU_free_from_common_LRU_list(
407
 
/*==============================*/
408
 
                                /* out: TRUE if freed */
409
 
        ulint   n_iterations)   /* in: how many times this has been called
410
 
                                repeatedly without result: a high value means
411
 
                                that we should search farther; if
412
 
                                n_iterations < 10, then we search
413
 
                                n_iterations / 10 * buf_pool->curr_size
414
 
                                pages from the end of the LRU list */
415
 
{
416
 
        buf_page_t*     bpage;
417
 
        ulint           distance;
418
 
 
419
 
        ut_ad(buf_pool_mutex_own());
420
 
 
421
 
        distance = 100 + (n_iterations * buf_pool->curr_size) / 10;
422
 
 
423
 
        for (bpage = UT_LIST_GET_LAST(buf_pool->LRU);
424
 
             UNIV_LIKELY(bpage != NULL) && UNIV_LIKELY(distance > 0);
425
 
             bpage = UT_LIST_GET_PREV(LRU, bpage), distance--) {
426
 
 
427
 
                enum buf_lru_free_block_status  freed;
428
 
                mutex_t*                        block_mutex
429
 
                        = buf_page_get_mutex(bpage);
430
 
 
431
 
                ut_ad(buf_page_in_file(bpage));
432
 
                ut_ad(bpage->in_LRU_list);
433
 
 
434
 
                mutex_enter(block_mutex);
435
 
                freed = buf_LRU_free_block(bpage, TRUE, NULL);
436
 
                mutex_exit(block_mutex);
437
 
 
438
 
                switch (freed) {
439
 
                case BUF_LRU_FREED:
440
 
                        return(TRUE);
441
 
 
442
 
                case BUF_LRU_NOT_FREED:
443
 
                        /* The block was dirty, buffer-fixed, or I/O-fixed.
444
 
                        Keep looking. */
445
 
                        continue;
446
 
 
447
 
                case BUF_LRU_CANNOT_RELOCATE:
448
 
                        /* This should never occur, because we
449
 
                        want to discard the compressed page too. */
450
 
                        break;
451
 
                }
452
 
 
453
 
                /* inappropriate return value from
454
 
                buf_LRU_free_block() */
455
 
                ut_error;
456
 
        }
457
 
 
458
 
        return(FALSE);
459
 
}
460
 
 
461
 
/**********************************************************************
462
 
Try to free a replaceable block. */
463
 
UNIV_INTERN
464
 
ibool
465
 
buf_LRU_search_and_free_block(
466
 
/*==========================*/
467
 
                                /* out: TRUE if found and freed */
468
 
        ulint   n_iterations)   /* in: how many times this has been called
469
 
                                repeatedly without result: a high value means
470
 
                                that we should search farther; if
471
 
                                n_iterations < 10, then we search
472
 
                                n_iterations / 10 * buf_pool->curr_size
473
 
                                pages from the end of the LRU list; if
474
 
                                n_iterations < 5, then we will also search
475
 
                                n_iterations / 5 of the unzip_LRU list. */
476
 
{
477
 
        ibool   freed = FALSE;
478
 
 
479
 
        buf_pool_mutex_enter();
480
 
 
481
 
        freed = buf_LRU_free_from_unzip_LRU_list(n_iterations);
482
 
 
483
 
        if (!freed) {
484
 
                freed = buf_LRU_free_from_common_LRU_list(n_iterations);
485
 
        }
486
 
 
 
283
                }
 
284
        }
 
285
        if (buf_pool->LRU_flush_ended > 0) {
 
286
                buf_pool->LRU_flush_ended--;
 
287
        }
487
288
        if (!freed) {
488
289
                buf_pool->LRU_flush_ended = 0;
489
 
        } else if (buf_pool->LRU_flush_ended > 0) {
490
 
                buf_pool->LRU_flush_ended--;
491
290
        }
492
 
 
493
 
        buf_pool_mutex_exit();
 
291
        mutex_exit(&(buf_pool->mutex));
494
292
 
495
293
        return(freed);
496
294
}
503
301
buffer. Otherwise, the flushed blocks could get modified again before read
504
302
operations need new buffer blocks, and the i/o work done in flushing would be
505
303
wasted. */
506
 
UNIV_INTERN
 
304
 
507
305
void
508
306
buf_LRU_try_free_flushed_blocks(void)
509
307
/*=================================*/
510
308
{
511
 
        buf_pool_mutex_enter();
 
309
        mutex_enter(&(buf_pool->mutex));
512
310
 
513
311
        while (buf_pool->LRU_flush_ended > 0) {
514
312
 
515
 
                buf_pool_mutex_exit();
 
313
                mutex_exit(&(buf_pool->mutex));
516
314
 
517
315
                buf_LRU_search_and_free_block(1);
518
316
 
519
 
                buf_pool_mutex_enter();
 
317
                mutex_enter(&(buf_pool->mutex));
520
318
        }
521
319
 
522
 
        buf_pool_mutex_exit();
 
320
        mutex_exit(&(buf_pool->mutex));
523
321
}
524
322
 
525
323
/**********************************************************************
526
324
Returns TRUE if less than 25 % of the buffer pool is available. This can be
527
325
used in heuristics to prevent huge transactions eating up the whole buffer
528
326
pool for their locks. */
529
 
UNIV_INTERN
 
327
 
530
328
ibool
531
329
buf_LRU_buf_pool_running_out(void)
532
330
/*==============================*/
535
333
{
536
334
        ibool   ret     = FALSE;
537
335
 
538
 
        buf_pool_mutex_enter();
 
336
        mutex_enter(&(buf_pool->mutex));
539
337
 
540
338
        if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free)
541
 
            + UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->curr_size / 4) {
 
339
            + UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 4) {
542
340
 
543
341
                ret = TRUE;
544
342
        }
545
343
 
546
 
        buf_pool_mutex_exit();
 
344
        mutex_exit(&(buf_pool->mutex));
547
345
 
548
346
        return(ret);
549
347
}
550
348
 
551
349
/**********************************************************************
552
 
Returns a free block from the buf_pool.  The block is taken off the
553
 
free list.  If it is empty, returns NULL. */
554
 
UNIV_INTERN
555
 
buf_block_t*
556
 
buf_LRU_get_free_only(void)
557
 
/*=======================*/
558
 
                                /* out: a free control block, or NULL
559
 
                                if the buf_block->free list is empty */
560
 
{
561
 
        buf_block_t*    block;
562
 
 
563
 
        ut_ad(buf_pool_mutex_own());
564
 
 
565
 
        block = (buf_block_t*) UT_LIST_GET_FIRST(buf_pool->free);
566
 
 
567
 
        if (block) {
568
 
                ut_ad(block->page.in_free_list);
569
 
                ut_d(block->page.in_free_list = FALSE);
570
 
                ut_ad(!block->page.in_flush_list);
571
 
                ut_ad(!block->page.in_LRU_list);
572
 
                ut_a(!buf_page_in_file(&block->page));
573
 
                UT_LIST_REMOVE(list, buf_pool->free, (&block->page));
574
 
 
575
 
                mutex_enter(&block->mutex);
576
 
 
577
 
                buf_block_set_state(block, BUF_BLOCK_READY_FOR_USE);
578
 
                UNIV_MEM_ALLOC(block->frame, UNIV_PAGE_SIZE);
579
 
 
580
 
                mutex_exit(&block->mutex);
581
 
        }
582
 
 
583
 
        return(block);
584
 
}
585
 
 
586
 
/**********************************************************************
587
 
Returns a free block from the buf_pool. The block is taken off the
588
 
free list. If it is empty, blocks are moved from the end of the
589
 
LRU list to the free list. */
590
 
UNIV_INTERN
591
 
buf_block_t*
592
 
buf_LRU_get_free_block(
593
 
/*===================*/
594
 
                                /* out: the free control block,
595
 
                                in state BUF_BLOCK_READY_FOR_USE */
596
 
        ulint   zip_size)       /* in: compressed page size in bytes,
597
 
                                or 0 if uncompressed tablespace */
 
350
Returns a free block from buf_pool. The block is taken off the free list.
 
351
If it is empty, blocks are moved from the end of the LRU list to the free
 
352
list. */
 
353
 
 
354
buf_block_t*
 
355
buf_LRU_get_free_block(void)
 
356
/*========================*/
 
357
                                /* out: the free control block; also if AWE is
 
358
                                used, it is guaranteed that the block has its
 
359
                                page mapped to a frame when we return */
598
360
{
599
361
        buf_block_t*    block           = NULL;
600
362
        ibool           freed;
602
364
        ibool           mon_value_was   = FALSE;
603
365
        ibool           started_monitor = FALSE;
604
366
loop:
605
 
        buf_pool_mutex_enter();
 
367
        mutex_enter(&(buf_pool->mutex));
606
368
 
607
369
        if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free)
608
 
            + UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->curr_size / 20) {
 
370
            + UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 20) {
609
371
                ut_print_timestamp(stderr);
610
372
 
611
373
                fprintf(stderr,
625
387
 
626
388
                ut_error;
627
389
 
628
 
        } else if (!recv_recovery_on
629
 
                   && (UT_LIST_GET_LEN(buf_pool->free)
630
 
                       + UT_LIST_GET_LEN(buf_pool->LRU))
631
 
                   < buf_pool->curr_size / 3) {
 
390
        } else if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free)
 
391
                   + UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 3) {
632
392
 
633
393
                if (!buf_lru_switched_on_innodb_mon) {
634
394
 
669
429
        }
670
430
 
671
431
        /* If there is a block in the free list, take it */
672
 
        block = buf_LRU_get_free_only();
673
 
        if (block) {
674
 
 
675
 
#ifdef UNIV_DEBUG
676
 
                block->page.zip.m_start =
677
 
#endif /* UNIV_DEBUG */
678
 
                        block->page.zip.m_end =
679
 
                        block->page.zip.m_nonempty =
680
 
                        block->page.zip.n_blobs = 0;
681
 
 
682
 
                if (UNIV_UNLIKELY(zip_size)) {
683
 
                        ibool   lru;
684
 
                        page_zip_set_size(&block->page.zip, zip_size);
685
 
                        block->page.zip.data = buf_buddy_alloc(zip_size, &lru);
686
 
                        UNIV_MEM_DESC(block->page.zip.data, zip_size, block);
687
 
                } else {
688
 
                        page_zip_set_size(&block->page.zip, 0);
689
 
                        block->page.zip.data = NULL;
 
432
        if (UT_LIST_GET_LEN(buf_pool->free) > 0) {
 
433
 
 
434
                block = UT_LIST_GET_FIRST(buf_pool->free);
 
435
                ut_a(block->in_free_list);
 
436
                UT_LIST_REMOVE(free, buf_pool->free, block);
 
437
                block->in_free_list = FALSE;
 
438
                ut_a(block->state != BUF_BLOCK_FILE_PAGE);
 
439
                ut_a(!block->in_LRU_list);
 
440
 
 
441
                if (srv_use_awe) {
 
442
                        if (block->frame) {
 
443
                                /* Remove from the list of mapped pages */
 
444
 
 
445
                                UT_LIST_REMOVE(awe_LRU_free_mapped,
 
446
                                               buf_pool->awe_LRU_free_mapped,
 
447
                                               block);
 
448
                        } else {
 
449
                                /* We map the page to a frame; second param
 
450
                                FALSE below because we do not want it to be
 
451
                                added to the awe_LRU_free_mapped list */
 
452
 
 
453
                                buf_awe_map_page_to_frame(block, FALSE);
 
454
                        }
690
455
                }
691
456
 
692
 
                buf_pool_mutex_exit();
 
457
                mutex_enter(&block->mutex);
 
458
 
 
459
                block->state = BUF_BLOCK_READY_FOR_USE;
 
460
                UNIV_MEM_ALLOC(block->frame, UNIV_PAGE_SIZE);
 
461
 
 
462
                mutex_exit(&block->mutex);
 
463
 
 
464
                mutex_exit(&(buf_pool->mutex));
693
465
 
694
466
                if (started_monitor) {
695
467
                        srv_print_innodb_monitor = mon_value_was;
701
473
        /* If no block was in the free list, search from the end of the LRU
702
474
        list and try to free a block there */
703
475
 
704
 
        buf_pool_mutex_exit();
 
476
        mutex_exit(&(buf_pool->mutex));
705
477
 
706
478
        freed = buf_LRU_search_and_free_block(n_iterations);
707
479
 
750
522
 
751
523
        os_aio_simulated_wake_handler_threads();
752
524
 
753
 
        buf_pool_mutex_enter();
 
525
        mutex_enter(&(buf_pool->mutex));
754
526
 
755
527
        if (buf_pool->LRU_flush_ended > 0) {
756
528
                /* We have written pages in an LRU flush. To make the insert
757
529
                buffer more efficient, we try to move these pages to the free
758
530
                list. */
759
531
 
760
 
                buf_pool_mutex_exit();
 
532
                mutex_exit(&(buf_pool->mutex));
761
533
 
762
534
                buf_LRU_try_free_flushed_blocks();
763
535
        } else {
764
 
                buf_pool_mutex_exit();
 
536
                mutex_exit(&(buf_pool->mutex));
765
537
        }
766
538
 
767
539
        if (n_iterations > 10) {
786
558
        ulint   new_len;
787
559
 
788
560
        ut_a(buf_pool->LRU_old);
789
 
        ut_ad(buf_pool_mutex_own());
790
 
#if 3 * (BUF_LRU_OLD_MIN_LEN / 8) <= BUF_LRU_OLD_TOLERANCE + 5
791
 
# error "3 * (BUF_LRU_OLD_MIN_LEN / 8) <= BUF_LRU_OLD_TOLERANCE + 5"
792
 
#endif
 
561
        ut_ad(mutex_own(&(buf_pool->mutex)));
 
562
        ut_ad(3 * (BUF_LRU_OLD_MIN_LEN / 8) > BUF_LRU_OLD_TOLERANCE + 5);
793
563
 
794
564
        for (;;) {
795
565
                old_len = buf_pool->LRU_old_len;
796
566
                new_len = 3 * (UT_LIST_GET_LEN(buf_pool->LRU) / 8);
797
567
 
798
 
                ut_ad(buf_pool->LRU_old->in_LRU_list);
 
568
                ut_a(buf_pool->LRU_old->in_LRU_list);
799
569
 
800
570
                /* Update the LRU_old pointer if necessary */
801
571
 
803
573
 
804
574
                        buf_pool->LRU_old = UT_LIST_GET_PREV(
805
575
                                LRU, buf_pool->LRU_old);
806
 
                        buf_page_set_old(buf_pool->LRU_old, TRUE);
 
576
                        (buf_pool->LRU_old)->old = TRUE;
807
577
                        buf_pool->LRU_old_len++;
808
578
 
809
579
                } else if (old_len > new_len + BUF_LRU_OLD_TOLERANCE) {
810
580
 
811
 
                        buf_page_set_old(buf_pool->LRU_old, FALSE);
 
581
                        (buf_pool->LRU_old)->old = FALSE;
812
582
                        buf_pool->LRU_old = UT_LIST_GET_NEXT(
813
583
                                LRU, buf_pool->LRU_old);
814
584
                        buf_pool->LRU_old_len--;
828
598
buf_LRU_old_init(void)
829
599
/*==================*/
830
600
{
831
 
        buf_page_t*     bpage;
 
601
        buf_block_t*    block;
832
602
 
833
 
        ut_ad(buf_pool_mutex_own());
 
603
        ut_ad(mutex_own(&(buf_pool->mutex)));
834
604
        ut_a(UT_LIST_GET_LEN(buf_pool->LRU) == BUF_LRU_OLD_MIN_LEN);
835
605
 
836
606
        /* We first initialize all blocks in the LRU list as old and then use
837
607
        the adjust function to move the LRU_old pointer to the right
838
608
        position */
839
609
 
840
 
        bpage = UT_LIST_GET_FIRST(buf_pool->LRU);
 
610
        block = UT_LIST_GET_FIRST(buf_pool->LRU);
841
611
 
842
 
        while (bpage != NULL) {
843
 
                ut_ad(bpage->in_LRU_list);
844
 
                buf_page_set_old(bpage, TRUE);
845
 
                bpage = UT_LIST_GET_NEXT(LRU, bpage);
 
612
        while (block != NULL) {
 
613
                ut_a(block->state == BUF_BLOCK_FILE_PAGE);
 
614
                ut_a(block->in_LRU_list);
 
615
                block->old = TRUE;
 
616
                block = UT_LIST_GET_NEXT(LRU, block);
846
617
        }
847
618
 
848
619
        buf_pool->LRU_old = UT_LIST_GET_FIRST(buf_pool->LRU);
852
623
}
853
624
 
854
625
/**********************************************************************
855
 
Remove a block from the unzip_LRU list if it belonged to the list. */
856
 
static
857
 
void
858
 
buf_unzip_LRU_remove_block_if_needed(
859
 
/*=================================*/
860
 
        buf_page_t*     bpage)  /* in/out: control block */
861
 
{
862
 
        ut_ad(buf_pool);
863
 
        ut_ad(bpage);
864
 
        ut_ad(buf_page_in_file(bpage));
865
 
        ut_ad(buf_pool_mutex_own());
866
 
 
867
 
        if (buf_page_belongs_to_unzip_LRU(bpage)) {
868
 
                buf_block_t*    block = (buf_block_t*) bpage;
869
 
 
870
 
                ut_ad(block->in_unzip_LRU_list);
871
 
                ut_d(block->in_unzip_LRU_list = FALSE);
872
 
 
873
 
                UT_LIST_REMOVE(unzip_LRU, buf_pool->unzip_LRU, block);
874
 
        }
875
 
}
876
 
 
877
 
/**********************************************************************
878
626
Removes a block from the LRU list. */
879
627
UNIV_INLINE
880
628
void
881
629
buf_LRU_remove_block(
882
630
/*=================*/
883
 
        buf_page_t*     bpage)  /* in: control block */
 
631
        buf_block_t*    block)  /* in: control block */
884
632
{
885
633
        ut_ad(buf_pool);
886
 
        ut_ad(bpage);
887
 
        ut_ad(buf_pool_mutex_own());
888
 
 
889
 
        ut_a(buf_page_in_file(bpage));
890
 
 
891
 
        ut_ad(bpage->in_LRU_list);
 
634
        ut_ad(block);
 
635
        ut_ad(mutex_own(&(buf_pool->mutex)));
 
636
 
 
637
        ut_a(block->state == BUF_BLOCK_FILE_PAGE);
 
638
        ut_a(block->in_LRU_list);
892
639
 
893
640
        /* If the LRU_old pointer is defined and points to just this block,
894
641
        move it backward one step */
895
642
 
896
 
        if (UNIV_UNLIKELY(bpage == buf_pool->LRU_old)) {
 
643
        if (block == buf_pool->LRU_old) {
897
644
 
898
645
                /* Below: the previous block is guaranteed to exist, because
899
646
                the LRU_old pointer is only allowed to differ by the
900
647
                tolerance value from strict 3/8 of the LRU list length. */
901
648
 
902
 
                buf_pool->LRU_old = UT_LIST_GET_PREV(LRU, bpage);
 
649
                buf_pool->LRU_old = UT_LIST_GET_PREV(LRU, block);
 
650
                (buf_pool->LRU_old)->old = TRUE;
 
651
 
 
652
                buf_pool->LRU_old_len++;
903
653
                ut_a(buf_pool->LRU_old);
904
 
                buf_page_set_old(buf_pool->LRU_old, TRUE);
905
 
 
906
 
                buf_pool->LRU_old_len++;
907
654
        }
908
655
 
909
656
        /* Remove the block from the LRU list */
910
 
        UT_LIST_REMOVE(LRU, buf_pool->LRU, bpage);
911
 
        ut_d(bpage->in_LRU_list = FALSE);
912
 
 
913
 
        buf_unzip_LRU_remove_block_if_needed(bpage);
 
657
        UT_LIST_REMOVE(LRU, buf_pool->LRU, block);
 
658
        block->in_LRU_list = FALSE;
 
659
 
 
660
        if (srv_use_awe && block->frame) {
 
661
                /* Remove from the list of mapped pages */
 
662
 
 
663
                UT_LIST_REMOVE(awe_LRU_free_mapped,
 
664
                               buf_pool->awe_LRU_free_mapped, block);
 
665
        }
914
666
 
915
667
        /* If the LRU list is so short that LRU_old not defined, return */
916
668
        if (UT_LIST_GET_LEN(buf_pool->LRU) < BUF_LRU_OLD_MIN_LEN) {
923
675
        ut_ad(buf_pool->LRU_old);
924
676
 
925
677
        /* Update the LRU_old_len field if necessary */
926
 
        if (buf_page_is_old(bpage)) {
 
678
        if (block->old) {
927
679
 
928
680
                buf_pool->LRU_old_len--;
929
681
        }
933
685
}
934
686
 
935
687
/**********************************************************************
936
 
Adds a block to the LRU list of decompressed zip pages. */
937
 
UNIV_INTERN
938
 
void
939
 
buf_unzip_LRU_add_block(
940
 
/*====================*/
941
 
        buf_block_t*    block,  /* in: control block */
942
 
        ibool           old)    /* in: TRUE if should be put to the end
943
 
                                of the list, else put to the start */
944
 
{
945
 
        ut_ad(buf_pool);
946
 
        ut_ad(block);
947
 
        ut_ad(buf_pool_mutex_own());
948
 
 
949
 
        ut_a(buf_page_belongs_to_unzip_LRU(&block->page));
950
 
 
951
 
        ut_ad(!block->in_unzip_LRU_list);
952
 
        ut_d(block->in_unzip_LRU_list = TRUE);
953
 
 
954
 
        if (old) {
955
 
                UT_LIST_ADD_LAST(unzip_LRU, buf_pool->unzip_LRU, block);
956
 
        } else {
957
 
                UT_LIST_ADD_FIRST(unzip_LRU, buf_pool->unzip_LRU, block);
958
 
        }
959
 
}
960
 
 
961
 
/**********************************************************************
962
688
Adds a block to the LRU list end. */
963
689
UNIV_INLINE
964
690
void
965
691
buf_LRU_add_block_to_end_low(
966
692
/*=========================*/
967
 
        buf_page_t*     bpage)  /* in: control block */
 
693
        buf_block_t*    block)  /* in: control block */
968
694
{
969
 
        buf_page_t*     last_bpage;
 
695
        buf_block_t*    last_block;
970
696
 
971
697
        ut_ad(buf_pool);
972
 
        ut_ad(bpage);
973
 
        ut_ad(buf_pool_mutex_own());
974
 
 
975
 
        ut_a(buf_page_in_file(bpage));
976
 
 
977
 
        buf_page_set_old(bpage, TRUE);
978
 
 
979
 
        last_bpage = UT_LIST_GET_LAST(buf_pool->LRU);
980
 
 
981
 
        if (last_bpage) {
982
 
                bpage->LRU_position = last_bpage->LRU_position;
 
698
        ut_ad(block);
 
699
        ut_ad(mutex_own(&(buf_pool->mutex)));
 
700
 
 
701
        ut_a(block->state == BUF_BLOCK_FILE_PAGE);
 
702
 
 
703
        block->old = TRUE;
 
704
 
 
705
        last_block = UT_LIST_GET_LAST(buf_pool->LRU);
 
706
 
 
707
        if (last_block) {
 
708
                block->LRU_position = last_block->LRU_position;
983
709
        } else {
984
 
                bpage->LRU_position = buf_pool_clock_tic();
985
 
        }
986
 
 
987
 
        ut_ad(!bpage->in_LRU_list);
988
 
        UT_LIST_ADD_LAST(LRU, buf_pool->LRU, bpage);
989
 
        ut_d(bpage->in_LRU_list = TRUE);
 
710
                block->LRU_position = buf_pool_clock_tic();
 
711
        }
 
712
 
 
713
        ut_a(!block->in_LRU_list);
 
714
        UT_LIST_ADD_LAST(LRU, buf_pool->LRU, block);
 
715
        block->in_LRU_list = TRUE;
 
716
 
 
717
        if (srv_use_awe && block->frame) {
 
718
                /* Add to the list of mapped pages */
 
719
 
 
720
                UT_LIST_ADD_LAST(awe_LRU_free_mapped,
 
721
                                 buf_pool->awe_LRU_free_mapped, block);
 
722
        }
990
723
 
991
724
        if (UT_LIST_GET_LEN(buf_pool->LRU) >= BUF_LRU_OLD_MIN_LEN) {
992
725
 
1008
741
 
1009
742
                buf_LRU_old_init();
1010
743
        }
1011
 
 
1012
 
        /* If this is a zipped block with decompressed frame as well
1013
 
        then put it on the unzip_LRU list */
1014
 
        if (buf_page_belongs_to_unzip_LRU(bpage)) {
1015
 
                buf_unzip_LRU_add_block((buf_block_t*) bpage, TRUE);
1016
 
        }
1017
744
}
1018
745
 
1019
746
/**********************************************************************
1022
749
void
1023
750
buf_LRU_add_block_low(
1024
751
/*==================*/
1025
 
        buf_page_t*     bpage,  /* in: control block */
 
752
        buf_block_t*    block,  /* in: control block */
1026
753
        ibool           old)    /* in: TRUE if should be put to the old blocks
1027
754
                                in the LRU list, else put to the start; if the
1028
755
                                LRU list is very short, the block is added to
1029
756
                                the start, regardless of this parameter */
1030
757
{
 
758
        ulint   cl;
 
759
 
1031
760
        ut_ad(buf_pool);
1032
 
        ut_ad(bpage);
1033
 
        ut_ad(buf_pool_mutex_own());
1034
 
 
1035
 
        ut_a(buf_page_in_file(bpage));
1036
 
        ut_ad(!bpage->in_LRU_list);
1037
 
 
1038
 
        buf_page_set_old(bpage, old);
 
761
        ut_ad(block);
 
762
        ut_ad(mutex_own(&(buf_pool->mutex)));
 
763
 
 
764
        ut_a(block->state == BUF_BLOCK_FILE_PAGE);
 
765
        ut_a(!block->in_LRU_list);
 
766
 
 
767
        block->old = old;
 
768
        cl = buf_pool_clock_tic();
 
769
 
 
770
        if (srv_use_awe && block->frame) {
 
771
                /* Add to the list of mapped pages; for simplicity we always
 
772
                add to the start, even if the user would have set 'old'
 
773
                TRUE */
 
774
 
 
775
                UT_LIST_ADD_FIRST(awe_LRU_free_mapped,
 
776
                                  buf_pool->awe_LRU_free_mapped, block);
 
777
        }
1039
778
 
1040
779
        if (!old || (UT_LIST_GET_LEN(buf_pool->LRU) < BUF_LRU_OLD_MIN_LEN)) {
1041
780
 
1042
 
                UT_LIST_ADD_FIRST(LRU, buf_pool->LRU, bpage);
 
781
                UT_LIST_ADD_FIRST(LRU, buf_pool->LRU, block);
1043
782
 
1044
 
                bpage->LRU_position = buf_pool_clock_tic();
1045
 
                bpage->freed_page_clock = buf_pool->freed_page_clock;
 
783
                block->LRU_position = cl;
 
784
                block->freed_page_clock = buf_pool->freed_page_clock;
1046
785
        } else {
1047
786
                UT_LIST_INSERT_AFTER(LRU, buf_pool->LRU, buf_pool->LRU_old,
1048
 
                                     bpage);
 
787
                                     block);
1049
788
                buf_pool->LRU_old_len++;
1050
789
 
1051
790
                /* We copy the LRU position field of the previous block
1052
791
                to the new block */
1053
792
 
1054
 
                bpage->LRU_position = (buf_pool->LRU_old)->LRU_position;
 
793
                block->LRU_position = (buf_pool->LRU_old)->LRU_position;
1055
794
        }
1056
795
 
1057
 
        ut_d(bpage->in_LRU_list = TRUE);
 
796
        block->in_LRU_list = TRUE;
1058
797
 
1059
798
        if (UT_LIST_GET_LEN(buf_pool->LRU) > BUF_LRU_OLD_MIN_LEN) {
1060
799
 
1071
810
 
1072
811
                buf_LRU_old_init();
1073
812
        }
1074
 
 
1075
 
        /* If this is a zipped block with decompressed frame as well
1076
 
        then put it on the unzip_LRU list */
1077
 
        if (buf_page_belongs_to_unzip_LRU(bpage)) {
1078
 
                buf_unzip_LRU_add_block((buf_block_t*) bpage, old);
1079
 
        }
1080
813
}
1081
814
 
1082
815
/**********************************************************************
1083
816
Adds a block to the LRU list. */
1084
 
UNIV_INTERN
 
817
 
1085
818
void
1086
819
buf_LRU_add_block(
1087
820
/*==============*/
1088
 
        buf_page_t*     bpage,  /* in: control block */
 
821
        buf_block_t*    block,  /* in: control block */
1089
822
        ibool           old)    /* in: TRUE if should be put to the old
1090
823
                                blocks in the LRU list, else put to the start;
1091
824
                                if the LRU list is very short, the block is
1092
825
                                added to the start, regardless of this
1093
826
                                parameter */
1094
827
{
1095
 
        buf_LRU_add_block_low(bpage, old);
 
828
        buf_LRU_add_block_low(block, old);
1096
829
}
1097
830
 
1098
831
/**********************************************************************
1099
832
Moves a block to the start of the LRU list. */
1100
 
UNIV_INTERN
 
833
 
1101
834
void
1102
835
buf_LRU_make_block_young(
1103
836
/*=====================*/
1104
 
        buf_page_t*     bpage)  /* in: control block */
 
837
        buf_block_t*    block)  /* in: control block */
1105
838
{
1106
 
        buf_LRU_remove_block(bpage);
1107
 
        buf_LRU_add_block_low(bpage, FALSE);
 
839
        buf_LRU_remove_block(block);
 
840
        buf_LRU_add_block_low(block, FALSE);
1108
841
}
1109
842
 
1110
843
/**********************************************************************
1111
844
Moves a block to the end of the LRU list. */
1112
 
UNIV_INTERN
 
845
 
1113
846
void
1114
847
buf_LRU_make_block_old(
1115
848
/*===================*/
1116
 
        buf_page_t*     bpage)  /* in: control block */
1117
 
{
1118
 
        buf_LRU_remove_block(bpage);
1119
 
        buf_LRU_add_block_to_end_low(bpage);
1120
 
}
1121
 
 
1122
 
/**********************************************************************
1123
 
Try to free a block.  If bpage is a descriptor of a compressed-only
1124
 
page, the descriptor object will be freed as well.  If this function
1125
 
returns BUF_LRU_FREED, it will not temporarily release
1126
 
buf_pool_mutex. */
1127
 
UNIV_INTERN
1128
 
enum buf_lru_free_block_status
1129
 
buf_LRU_free_block(
1130
 
/*===============*/
1131
 
                                /* out: BUF_LRU_FREED if freed,
1132
 
                                BUF_LRU_CANNOT_RELOCATE or
1133
 
                                BUF_LRU_NOT_FREED otherwise. */
1134
 
        buf_page_t*     bpage,  /* in: block to be freed */
1135
 
        ibool           zip,    /* in: TRUE if should remove also the
1136
 
                                compressed page of an uncompressed page */
1137
 
        ibool*          buf_pool_mutex_released)
1138
 
                                /* in: pointer to a variable that will
1139
 
                                be assigned TRUE if buf_pool_mutex
1140
 
                                was temporarily released, or NULL */
1141
 
{
1142
 
        buf_page_t*     b = NULL;
1143
 
        mutex_t*        block_mutex = buf_page_get_mutex(bpage);
1144
 
 
1145
 
        ut_ad(buf_pool_mutex_own());
1146
 
        ut_ad(mutex_own(block_mutex));
1147
 
        ut_ad(buf_page_in_file(bpage));
1148
 
        ut_ad(bpage->in_LRU_list);
1149
 
        ut_ad(!bpage->in_flush_list == !bpage->oldest_modification);
1150
 
        UNIV_MEM_ASSERT_RW(bpage, sizeof *bpage);
1151
 
 
1152
 
        if (!buf_page_can_relocate(bpage)) {
1153
 
 
1154
 
                /* Do not free buffer-fixed or I/O-fixed blocks. */
1155
 
                return(BUF_LRU_NOT_FREED);
1156
 
        }
1157
 
 
1158
 
        if (zip || !bpage->zip.data) {
1159
 
                /* This would completely free the block. */
1160
 
                /* Do not completely free dirty blocks. */
1161
 
 
1162
 
                if (bpage->oldest_modification) {
1163
 
                        return(BUF_LRU_NOT_FREED);
1164
 
                }
1165
 
        } else if (bpage->oldest_modification) {
1166
 
                /* Do not completely free dirty blocks. */
1167
 
 
1168
 
                if (buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE) {
1169
 
                        ut_ad(buf_page_get_state(bpage)
1170
 
                              == BUF_BLOCK_ZIP_DIRTY);
1171
 
                        return(BUF_LRU_NOT_FREED);
1172
 
                }
1173
 
 
1174
 
                goto alloc;
1175
 
        } else if (buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE) {
1176
 
                /* Allocate the control block for the compressed page.
1177
 
                If it cannot be allocated (without freeing a block
1178
 
                from the LRU list), refuse to free bpage. */
1179
 
alloc:
1180
 
                buf_pool_mutex_exit_forbid();
1181
 
                b = buf_buddy_alloc(sizeof *b, NULL);
1182
 
                buf_pool_mutex_exit_allow();
1183
 
 
1184
 
                if (UNIV_UNLIKELY(!b)) {
1185
 
                        return(BUF_LRU_CANNOT_RELOCATE);
1186
 
                }
1187
 
 
1188
 
                memcpy(b, bpage, sizeof *b);
1189
 
        }
1190
 
 
1191
 
#ifdef UNIV_DEBUG
1192
 
        if (buf_debug_prints) {
1193
 
                fprintf(stderr, "Putting space %lu page %lu to free list\n",
1194
 
                        (ulong) buf_page_get_space(bpage),
1195
 
                        (ulong) buf_page_get_page_no(bpage));
1196
 
        }
1197
 
#endif /* UNIV_DEBUG */
1198
 
 
1199
 
        if (buf_LRU_block_remove_hashed_page(bpage, zip)
1200
 
            != BUF_BLOCK_ZIP_FREE) {
1201
 
                ut_a(bpage->buf_fix_count == 0);
1202
 
 
1203
 
                if (b) {
1204
 
                        buf_page_t*     prev_b  = UT_LIST_GET_PREV(LRU, b);
1205
 
                        const ulint     fold    = buf_page_address_fold(
1206
 
                                bpage->space, bpage->offset);
1207
 
 
1208
 
                        ut_a(!buf_page_hash_get(bpage->space, bpage->offset));
1209
 
 
1210
 
                        b->state = b->oldest_modification
1211
 
                                ? BUF_BLOCK_ZIP_DIRTY
1212
 
                                : BUF_BLOCK_ZIP_PAGE;
1213
 
                        UNIV_MEM_DESC(b->zip.data,
1214
 
                                      page_zip_get_size(&b->zip), b);
1215
 
 
1216
 
                        /* The fields in_page_hash and in_LRU_list of
1217
 
                        the to-be-freed block descriptor should have
1218
 
                        been cleared in
1219
 
                        buf_LRU_block_remove_hashed_page(), which
1220
 
                        invokes buf_LRU_remove_block(). */
1221
 
                        ut_ad(!bpage->in_page_hash);
1222
 
                        ut_ad(!bpage->in_LRU_list);
1223
 
                        /* bpage->state was BUF_BLOCK_FILE_PAGE because
1224
 
                        b != NULL. The type cast below is thus valid. */
1225
 
                        ut_ad(!((buf_block_t*) bpage)->in_unzip_LRU_list);
1226
 
 
1227
 
                        /* The fields of bpage were copied to b before
1228
 
                        buf_LRU_block_remove_hashed_page() was invoked. */
1229
 
                        ut_ad(!b->in_zip_hash);
1230
 
                        ut_ad(b->in_page_hash);
1231
 
                        ut_ad(b->in_LRU_list);
1232
 
 
1233
 
                        HASH_INSERT(buf_page_t, hash,
1234
 
                                    buf_pool->page_hash, fold, b);
1235
 
 
1236
 
                        /* Insert b where bpage was in the LRU list. */
1237
 
                        if (UNIV_LIKELY(prev_b != NULL)) {
1238
 
                                ulint   lru_len;
1239
 
 
1240
 
                                ut_ad(prev_b->in_LRU_list);
1241
 
                                ut_ad(buf_page_in_file(prev_b));
1242
 
                                UNIV_MEM_ASSERT_RW(prev_b, sizeof *prev_b);
1243
 
 
1244
 
                                UT_LIST_INSERT_AFTER(LRU, buf_pool->LRU,
1245
 
                                                     prev_b, b);
1246
 
 
1247
 
                                if (buf_page_is_old(b)) {
1248
 
                                        buf_pool->LRU_old_len++;
1249
 
                                }
1250
 
 
1251
 
                                lru_len = UT_LIST_GET_LEN(buf_pool->LRU);
1252
 
 
1253
 
                                if (lru_len > BUF_LRU_OLD_MIN_LEN) {
1254
 
                                        ut_ad(buf_pool->LRU_old);
1255
 
                                        /* Adjust the length of the
1256
 
                                        old block list if necessary */
1257
 
                                        buf_LRU_old_adjust_len();
1258
 
                                } else if (lru_len == BUF_LRU_OLD_MIN_LEN) {
1259
 
                                        /* The LRU list is now long
1260
 
                                        enough for LRU_old to become
1261
 
                                        defined: init it */
1262
 
                                        buf_LRU_old_init();
1263
 
                                }
1264
 
                        } else {
1265
 
                                ut_d(b->in_LRU_list = FALSE);
1266
 
                                buf_LRU_add_block_low(b, buf_page_is_old(b));
1267
 
                        }
1268
 
 
1269
 
                        if (b->state == BUF_BLOCK_ZIP_PAGE) {
1270
 
                                buf_LRU_insert_zip_clean(b);
1271
 
                        } else {
1272
 
                                buf_page_t* prev;
1273
 
 
1274
 
                                ut_ad(b->in_flush_list);
1275
 
                                ut_d(bpage->in_flush_list = FALSE);
1276
 
 
1277
 
                                prev = UT_LIST_GET_PREV(list, b);
1278
 
                                UT_LIST_REMOVE(list, buf_pool->flush_list, b);
1279
 
 
1280
 
                                if (prev) {
1281
 
                                        ut_ad(prev->in_flush_list);
1282
 
                                        UT_LIST_INSERT_AFTER(
1283
 
                                                list,
1284
 
                                                buf_pool->flush_list,
1285
 
                                                prev, b);
1286
 
                                } else {
1287
 
                                        UT_LIST_ADD_FIRST(
1288
 
                                                list,
1289
 
                                                buf_pool->flush_list,
1290
 
                                                b);
1291
 
                                }
1292
 
                        }
1293
 
 
1294
 
                        bpage->zip.data = NULL;
1295
 
                        page_zip_set_size(&bpage->zip, 0);
1296
 
 
1297
 
                        /* Prevent buf_page_get_gen() from
1298
 
                        decompressing the block while we release
1299
 
                        buf_pool_mutex and block_mutex. */
1300
 
                        b->buf_fix_count++;
1301
 
                        b->io_fix = BUF_IO_READ;
1302
 
                }
1303
 
 
1304
 
                if (buf_pool_mutex_released) {
1305
 
                        *buf_pool_mutex_released = TRUE;
1306
 
                }
1307
 
 
1308
 
                buf_pool_mutex_exit();
1309
 
                mutex_exit(block_mutex);
1310
 
 
1311
 
                /* Remove possible adaptive hash index on the page.
1312
 
                The page was declared uninitialized by
1313
 
                buf_LRU_block_remove_hashed_page().  We need to flag
1314
 
                the contents of the page valid (which it still is) in
1315
 
                order to avoid bogus Valgrind warnings.*/
1316
 
 
1317
 
                UNIV_MEM_VALID(((buf_block_t*) bpage)->frame,
1318
 
                               UNIV_PAGE_SIZE);
1319
 
                btr_search_drop_page_hash_index((buf_block_t*) bpage);
1320
 
                UNIV_MEM_INVALID(((buf_block_t*) bpage)->frame,
1321
 
                                 UNIV_PAGE_SIZE);
1322
 
 
1323
 
                if (b) {
1324
 
                        /* Compute and stamp the compressed page
1325
 
                        checksum while not holding any mutex.  The
1326
 
                        block is already half-freed
1327
 
                        (BUF_BLOCK_REMOVE_HASH) and removed from
1328
 
                        buf_pool->page_hash, thus inaccessible by any
1329
 
                        other thread. */
1330
 
 
1331
 
                        mach_write_to_4(
1332
 
                                b->zip.data + FIL_PAGE_SPACE_OR_CHKSUM,
1333
 
                                UNIV_LIKELY(srv_use_checksums)
1334
 
                                ? page_zip_calc_checksum(
1335
 
                                        b->zip.data,
1336
 
                                        page_zip_get_size(&b->zip))
1337
 
                                : BUF_NO_CHECKSUM_MAGIC);
1338
 
                }
1339
 
 
1340
 
                buf_pool_mutex_enter();
1341
 
                mutex_enter(block_mutex);
1342
 
 
1343
 
                if (b) {
1344
 
                        mutex_enter(&buf_pool_zip_mutex);
1345
 
                        b->buf_fix_count--;
1346
 
                        buf_page_set_io_fix(b, BUF_IO_NONE);
1347
 
                        mutex_exit(&buf_pool_zip_mutex);
1348
 
                }
1349
 
 
1350
 
                buf_LRU_block_free_hashed_page((buf_block_t*) bpage);
1351
 
        } else {
1352
 
                mutex_enter(block_mutex);
1353
 
        }
1354
 
 
1355
 
        return(BUF_LRU_FREED);
 
849
        buf_block_t*    block)  /* in: control block */
 
850
{
 
851
        buf_LRU_remove_block(block);
 
852
        buf_LRU_add_block_to_end_low(block);
1356
853
}
1357
854
 
1358
855
/**********************************************************************
1359
856
Puts a block back to the free list. */
1360
 
UNIV_INTERN
 
857
 
1361
858
void
1362
859
buf_LRU_block_free_non_file_page(
1363
860
/*=============================*/
1364
861
        buf_block_t*    block)  /* in: block, must not contain a file page */
1365
862
{
1366
 
        void*   data;
1367
863
 
1368
 
        ut_ad(buf_pool_mutex_own());
 
864
        ut_ad(mutex_own(&(buf_pool->mutex)));
1369
865
        ut_ad(mutex_own(&block->mutex));
1370
866
        ut_ad(block);
1371
867
 
1372
 
        switch (buf_block_get_state(block)) {
1373
 
        case BUF_BLOCK_MEMORY:
1374
 
        case BUF_BLOCK_READY_FOR_USE:
1375
 
                break;
1376
 
        default:
1377
 
                ut_error;
1378
 
        }
1379
 
 
1380
 
        ut_ad(block->n_pointers == 0);
1381
 
        ut_ad(!block->page.in_free_list);
1382
 
        ut_ad(!block->page.in_flush_list);
1383
 
        ut_ad(!block->page.in_LRU_list);
1384
 
 
1385
 
        buf_block_set_state(block, BUF_BLOCK_NOT_USED);
 
868
        ut_a((block->state == BUF_BLOCK_MEMORY)
 
869
             || (block->state == BUF_BLOCK_READY_FOR_USE));
 
870
 
 
871
        ut_a(block->n_pointers == 0);
 
872
        ut_a(!block->in_free_list);
 
873
 
 
874
        block->state = BUF_BLOCK_NOT_USED;
1386
875
 
1387
876
        UNIV_MEM_ALLOC(block->frame, UNIV_PAGE_SIZE);
1388
877
#ifdef UNIV_DEBUG
1389
878
        /* Wipe contents of page to reveal possible stale pointers to it */
1390
879
        memset(block->frame, '\0', UNIV_PAGE_SIZE);
1391
 
#else
1392
 
        /* Wipe page_no and space_id */
1393
 
        memset(block->frame + FIL_PAGE_OFFSET, 0xfe, 4);
1394
 
        memset(block->frame + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, 0xfe, 4);
1395
880
#endif
1396
 
        data = block->page.zip.data;
1397
 
 
1398
 
        if (data) {
1399
 
                block->page.zip.data = NULL;
1400
 
                mutex_exit(&block->mutex);
1401
 
                buf_pool_mutex_exit_forbid();
1402
 
                buf_buddy_free(data, page_zip_get_size(&block->page.zip));
1403
 
                buf_pool_mutex_exit_allow();
1404
 
                mutex_enter(&block->mutex);
1405
 
                page_zip_set_size(&block->page.zip, 0);
1406
 
        }
1407
 
 
1408
 
        UT_LIST_ADD_FIRST(list, buf_pool->free, (&block->page));
1409
 
        ut_d(block->page.in_free_list = TRUE);
 
881
        UT_LIST_ADD_FIRST(free, buf_pool->free, block);
 
882
        block->in_free_list = TRUE;
1410
883
 
1411
884
        UNIV_MEM_ASSERT_AND_FREE(block->frame, UNIV_PAGE_SIZE);
 
885
 
 
886
        if (srv_use_awe && block->frame) {
 
887
                /* Add to the list of mapped pages */
 
888
 
 
889
                UT_LIST_ADD_FIRST(awe_LRU_free_mapped,
 
890
                                  buf_pool->awe_LRU_free_mapped, block);
 
891
        }
1412
892
}
1413
893
 
1414
894
/**********************************************************************
1415
 
Takes a block out of the LRU list and page hash table.
1416
 
If the block is compressed-only (BUF_BLOCK_ZIP_PAGE),
1417
 
the object will be freed and buf_pool_zip_mutex will be released.
1418
 
 
1419
 
If a compressed page or a compressed-only block descriptor is freed,
1420
 
other compressed pages or compressed-only block descriptors may be
1421
 
relocated. */
 
895
Takes a block out of the LRU list and page hash table and sets the block
 
896
state to BUF_BLOCK_REMOVE_HASH. */
1422
897
static
1423
 
enum buf_page_state
 
898
void
1424
899
buf_LRU_block_remove_hashed_page(
1425
900
/*=============================*/
1426
 
                                /* out: the new state of the block
1427
 
                                (BUF_BLOCK_ZIP_FREE if the state was
1428
 
                                BUF_BLOCK_ZIP_PAGE, or BUF_BLOCK_REMOVE_HASH
1429
 
                                otherwise) */
1430
 
        buf_page_t*     bpage,  /* in: block, must contain a file page and
 
901
        buf_block_t*    block)  /* in: block, must contain a file page and
1431
902
                                be in a state where it can be freed; there
1432
903
                                may or may not be a hash index to the page */
1433
 
        ibool           zip)    /* in: TRUE if should remove also the
1434
 
                                compressed page of an uncompressed page */
1435
904
{
1436
 
        const buf_page_t*       hashed_bpage;
1437
 
        ut_ad(bpage);
1438
 
        ut_ad(buf_pool_mutex_own());
1439
 
        ut_ad(mutex_own(buf_page_get_mutex(bpage)));
1440
 
 
1441
 
        ut_a(buf_page_get_io_fix(bpage) == BUF_IO_NONE);
1442
 
        ut_a(bpage->buf_fix_count == 0);
1443
 
 
1444
 
        UNIV_MEM_ASSERT_RW(bpage, sizeof *bpage);
1445
 
 
1446
 
        buf_LRU_remove_block(bpage);
 
905
        ut_ad(mutex_own(&(buf_pool->mutex)));
 
906
        ut_ad(mutex_own(&block->mutex));
 
907
        ut_ad(block);
 
908
 
 
909
        ut_a(block->state == BUF_BLOCK_FILE_PAGE);
 
910
        ut_a(block->io_fix == 0);
 
911
        ut_a(block->buf_fix_count == 0);
 
912
        ut_a(ut_dulint_cmp(block->oldest_modification, ut_dulint_zero) == 0);
 
913
 
 
914
        buf_LRU_remove_block(block);
1447
915
 
1448
916
        buf_pool->freed_page_clock += 1;
1449
917
 
1450
 
        switch (buf_page_get_state(bpage)) {
1451
 
        case BUF_BLOCK_FILE_PAGE:
1452
 
                UNIV_MEM_ASSERT_W(bpage, sizeof(buf_block_t));
1453
 
                UNIV_MEM_ASSERT_W(((buf_block_t*) bpage)->frame,
1454
 
                                  UNIV_PAGE_SIZE);
1455
 
                buf_block_modify_clock_inc((buf_block_t*) bpage);
1456
 
                if (bpage->zip.data) {
1457
 
                        const page_t*   page = ((buf_block_t*) bpage)->frame;
1458
 
 
1459
 
                        ut_a(!zip || bpage->oldest_modification == 0);
1460
 
 
1461
 
                        switch (UNIV_EXPECT(fil_page_get_type(page),
1462
 
                                            FIL_PAGE_INDEX)) {
1463
 
                        case FIL_PAGE_TYPE_ALLOCATED:
1464
 
                        case FIL_PAGE_INODE:
1465
 
                        case FIL_PAGE_IBUF_BITMAP:
1466
 
                        case FIL_PAGE_TYPE_FSP_HDR:
1467
 
                        case FIL_PAGE_TYPE_XDES:
1468
 
                                /* These are essentially uncompressed pages. */
1469
 
                                if (!zip) {
1470
 
                                        /* InnoDB writes the data to the
1471
 
                                        uncompressed page frame.  Copy it
1472
 
                                        to the compressed page, which will
1473
 
                                        be preserved. */
1474
 
                                        memcpy(bpage->zip.data, page,
1475
 
                                               page_zip_get_size(&bpage->zip));
1476
 
                                }
1477
 
                                break;
1478
 
                        case FIL_PAGE_TYPE_ZBLOB:
1479
 
                        case FIL_PAGE_TYPE_ZBLOB2:
1480
 
                                break;
1481
 
                        case FIL_PAGE_INDEX:
1482
 
#ifdef UNIV_ZIP_DEBUG
1483
 
                                ut_a(page_zip_validate(&bpage->zip, page));
1484
 
#endif /* UNIV_ZIP_DEBUG */
1485
 
                                break;
1486
 
                        default:
1487
 
                                ut_error;
1488
 
                        }
1489
 
 
1490
 
                        break;
1491
 
                }
1492
 
                /* fall through */
1493
 
        case BUF_BLOCK_ZIP_PAGE:
1494
 
                ut_a(bpage->oldest_modification == 0);
1495
 
                UNIV_MEM_ASSERT_W(bpage->zip.data,
1496
 
                                  page_zip_get_size(&bpage->zip));
1497
 
                break;
1498
 
        case BUF_BLOCK_ZIP_FREE:
1499
 
        case BUF_BLOCK_ZIP_DIRTY:
1500
 
        case BUF_BLOCK_NOT_USED:
1501
 
        case BUF_BLOCK_READY_FOR_USE:
1502
 
        case BUF_BLOCK_MEMORY:
1503
 
        case BUF_BLOCK_REMOVE_HASH:
1504
 
                ut_error;
1505
 
                break;
1506
 
        }
1507
 
 
1508
 
        hashed_bpage = buf_page_hash_get(bpage->space, bpage->offset);
1509
 
 
1510
 
        if (UNIV_UNLIKELY(bpage != hashed_bpage)) {
 
918
        /* Note that if AWE is enabled the block may not have a frame at all */
 
919
 
 
920
        buf_block_modify_clock_inc(block);
 
921
 
 
922
        if (block != buf_page_hash_get(block->space, block->offset)) {
1511
923
                fprintf(stderr,
1512
924
                        "InnoDB: Error: page %lu %lu not found"
1513
925
                        " in the hash table\n",
1514
 
                        (ulong) bpage->space,
1515
 
                        (ulong) bpage->offset);
1516
 
                if (hashed_bpage) {
 
926
                        (ulong) block->space,
 
927
                        (ulong) block->offset);
 
928
                if (buf_page_hash_get(block->space, block->offset)) {
1517
929
                        fprintf(stderr,
1518
930
                                "InnoDB: In hash table we find block"
1519
931
                                " %p of %lu %lu which is not %p\n",
1520
 
                                (const void*) hashed_bpage,
1521
 
                                (ulong) hashed_bpage->space,
1522
 
                                (ulong) hashed_bpage->offset,
1523
 
                                (const void*) bpage);
 
932
                                (void*) buf_page_hash_get
 
933
                                (block->space, block->offset),
 
934
                                (ulong) buf_page_hash_get
 
935
                                (block->space, block->offset)->space,
 
936
                                (ulong) buf_page_hash_get
 
937
                                (block->space, block->offset)->offset,
 
938
                                (void*) block);
1524
939
                }
1525
940
 
1526
 
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
1527
 
                mutex_exit(buf_page_get_mutex(bpage));
1528
 
                buf_pool_mutex_exit();
 
941
#ifdef UNIV_DEBUG
1529
942
                buf_print();
1530
943
                buf_LRU_print();
1531
944
                buf_validate();
1532
945
                buf_LRU_validate();
1533
 
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
1534
 
                ut_error;
1535
 
        }
1536
 
 
1537
 
        ut_ad(!bpage->in_zip_hash);
1538
 
        ut_ad(bpage->in_page_hash);
1539
 
        ut_d(bpage->in_page_hash = FALSE);
1540
 
        HASH_DELETE(buf_page_t, hash, buf_pool->page_hash,
1541
 
                    buf_page_address_fold(bpage->space, bpage->offset),
1542
 
                    bpage);
1543
 
        switch (buf_page_get_state(bpage)) {
1544
 
        case BUF_BLOCK_ZIP_PAGE:
1545
 
                ut_ad(!bpage->in_free_list);
1546
 
                ut_ad(!bpage->in_flush_list);
1547
 
                ut_ad(!bpage->in_LRU_list);
1548
 
                ut_a(bpage->zip.data);
1549
 
                ut_a(buf_page_get_zip_size(bpage));
1550
 
 
1551
 
                UT_LIST_REMOVE(list, buf_pool->zip_clean, bpage);
1552
 
 
1553
 
                mutex_exit(&buf_pool_zip_mutex);
1554
 
                buf_pool_mutex_exit_forbid();
1555
 
                buf_buddy_free(bpage->zip.data,
1556
 
                               page_zip_get_size(&bpage->zip));
1557
 
                buf_buddy_free(bpage, sizeof(*bpage));
1558
 
                buf_pool_mutex_exit_allow();
1559
 
                UNIV_MEM_UNDESC(bpage);
1560
 
                return(BUF_BLOCK_ZIP_FREE);
1561
 
 
1562
 
        case BUF_BLOCK_FILE_PAGE:
1563
 
                memset(((buf_block_t*) bpage)->frame
1564
 
                       + FIL_PAGE_OFFSET, 0xff, 4);
1565
 
                memset(((buf_block_t*) bpage)->frame
1566
 
                       + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, 0xff, 4);
1567
 
                UNIV_MEM_INVALID(((buf_block_t*) bpage)->frame,
1568
 
                                 UNIV_PAGE_SIZE);
1569
 
                buf_page_set_state(bpage, BUF_BLOCK_REMOVE_HASH);
1570
 
 
1571
 
                if (zip && bpage->zip.data) {
1572
 
                        /* Free the compressed page. */
1573
 
                        void*   data = bpage->zip.data;
1574
 
                        bpage->zip.data = NULL;
1575
 
 
1576
 
                        mutex_exit(&((buf_block_t*) bpage)->mutex);
1577
 
                        buf_buddy_free(data, page_zip_get_size(&bpage->zip));
1578
 
                        mutex_enter(&((buf_block_t*) bpage)->mutex);
1579
 
                        page_zip_set_size(&bpage->zip, 0);
1580
 
                }
1581
 
 
1582
 
                return(BUF_BLOCK_REMOVE_HASH);
1583
 
 
1584
 
        case BUF_BLOCK_ZIP_FREE:
1585
 
        case BUF_BLOCK_ZIP_DIRTY:
1586
 
        case BUF_BLOCK_NOT_USED:
1587
 
        case BUF_BLOCK_READY_FOR_USE:
1588
 
        case BUF_BLOCK_MEMORY:
1589
 
        case BUF_BLOCK_REMOVE_HASH:
1590
 
                break;
1591
 
        }
1592
 
 
1593
 
        ut_error;
1594
 
        return(BUF_BLOCK_ZIP_FREE);
 
946
#endif
 
947
                ut_a(0);
 
948
        }
 
949
 
 
950
        HASH_DELETE(buf_block_t, hash, buf_pool->page_hash,
 
951
                    buf_page_address_fold(block->space, block->offset),
 
952
                    block);
 
953
 
 
954
        UNIV_MEM_INVALID(block->frame, UNIV_PAGE_SIZE);
 
955
        block->state = BUF_BLOCK_REMOVE_HASH;
1595
956
}
1596
957
 
1597
958
/**********************************************************************
1603
964
        buf_block_t*    block)  /* in: block, must contain a file page and
1604
965
                                be in a state where it can be freed */
1605
966
{
1606
 
        ut_ad(buf_pool_mutex_own());
 
967
        ut_ad(mutex_own(&(buf_pool->mutex)));
1607
968
        ut_ad(mutex_own(&block->mutex));
1608
969
 
1609
 
        buf_block_set_state(block, BUF_BLOCK_MEMORY);
 
970
        ut_a(block->state == BUF_BLOCK_REMOVE_HASH);
 
971
 
 
972
        block->state = BUF_BLOCK_MEMORY;
1610
973
 
1611
974
        buf_LRU_block_free_non_file_page(block);
1612
975
}
1613
976
 
1614
 
/************************************************************************
1615
 
Update the historical stats that we are collecting for LRU eviction
1616
 
policy at the end of each interval. */
1617
 
UNIV_INTERN
1618
 
void
1619
 
buf_LRU_stat_update(void)
1620
 
/*=====================*/
1621
 
{
1622
 
        buf_LRU_stat_t* item;
1623
 
 
1624
 
        /* If we haven't started eviction yet then don't update stats. */
1625
 
        if (buf_pool->freed_page_clock == 0) {
1626
 
                goto func_exit;
1627
 
        }
1628
 
 
1629
 
        buf_pool_mutex_enter();
1630
 
 
1631
 
        /* Update the index. */
1632
 
        item = &buf_LRU_stat_arr[buf_LRU_stat_arr_ind];
1633
 
        buf_LRU_stat_arr_ind++;
1634
 
        buf_LRU_stat_arr_ind %= BUF_LRU_STAT_N_INTERVAL;
1635
 
 
1636
 
        /* Add the current value and subtract the obsolete entry. */
1637
 
        buf_LRU_stat_sum.io += buf_LRU_stat_cur.io - item->io;
1638
 
        buf_LRU_stat_sum.unzip += buf_LRU_stat_cur.unzip - item->unzip;
1639
 
 
1640
 
        /* Put current entry in the array. */
1641
 
        memcpy(item, &buf_LRU_stat_cur, sizeof *item);
1642
 
 
1643
 
        buf_pool_mutex_exit();
1644
 
 
1645
 
func_exit:
1646
 
        /* Clear the current entry. */
1647
 
        memset(&buf_LRU_stat_cur, 0, sizeof buf_LRU_stat_cur);
1648
 
}
1649
 
 
1650
 
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
 
977
#ifdef UNIV_DEBUG
1651
978
/**************************************************************************
1652
979
Validates the LRU list. */
1653
 
UNIV_INTERN
 
980
 
1654
981
ibool
1655
982
buf_LRU_validate(void)
1656
983
/*==================*/
1657
984
{
1658
 
        buf_page_t*     bpage;
1659
985
        buf_block_t*    block;
1660
986
        ulint           old_len;
1661
987
        ulint           new_len;
1662
988
        ulint           LRU_pos;
1663
989
 
1664
990
        ut_ad(buf_pool);
1665
 
        buf_pool_mutex_enter();
 
991
        mutex_enter(&(buf_pool->mutex));
1666
992
 
1667
993
        if (UT_LIST_GET_LEN(buf_pool->LRU) >= BUF_LRU_OLD_MIN_LEN) {
1668
994
 
1673
999
                ut_a(old_len <= new_len + BUF_LRU_OLD_TOLERANCE);
1674
1000
        }
1675
1001
 
1676
 
        UT_LIST_VALIDATE(LRU, buf_page_t, buf_pool->LRU);
 
1002
        UT_LIST_VALIDATE(LRU, buf_block_t, buf_pool->LRU);
1677
1003
 
1678
 
        bpage = UT_LIST_GET_FIRST(buf_pool->LRU);
 
1004
        block = UT_LIST_GET_FIRST(buf_pool->LRU);
1679
1005
 
1680
1006
        old_len = 0;
1681
1007
 
1682
 
        while (bpage != NULL) {
1683
 
 
1684
 
                switch (buf_page_get_state(bpage)) {
1685
 
                case BUF_BLOCK_ZIP_FREE:
1686
 
                case BUF_BLOCK_NOT_USED:
1687
 
                case BUF_BLOCK_READY_FOR_USE:
1688
 
                case BUF_BLOCK_MEMORY:
1689
 
                case BUF_BLOCK_REMOVE_HASH:
1690
 
                        ut_error;
1691
 
                        break;
1692
 
                case BUF_BLOCK_FILE_PAGE:
1693
 
                        ut_ad(((buf_block_t*) bpage)->in_unzip_LRU_list
1694
 
                              == buf_page_belongs_to_unzip_LRU(bpage));
1695
 
                case BUF_BLOCK_ZIP_PAGE:
1696
 
                case BUF_BLOCK_ZIP_DIRTY:
1697
 
                        break;
1698
 
                }
1699
 
 
1700
 
                if (buf_page_is_old(bpage)) {
 
1008
        while (block != NULL) {
 
1009
 
 
1010
                ut_a(block->state == BUF_BLOCK_FILE_PAGE);
 
1011
 
 
1012
                if (block->old) {
1701
1013
                        old_len++;
1702
1014
                }
1703
1015
 
1704
1016
                if (buf_pool->LRU_old && (old_len == 1)) {
1705
 
                        ut_a(buf_pool->LRU_old == bpage);
 
1017
                        ut_a(buf_pool->LRU_old == block);
1706
1018
                }
1707
1019
 
1708
 
                LRU_pos = buf_page_get_LRU_position(bpage);
1709
 
 
1710
 
                bpage = UT_LIST_GET_NEXT(LRU, bpage);
1711
 
 
1712
 
                if (bpage) {
 
1020
                LRU_pos = block->LRU_position;
 
1021
 
 
1022
                block = UT_LIST_GET_NEXT(LRU, block);
 
1023
 
 
1024
                if (block) {
1713
1025
                        /* If the following assert fails, it may
1714
1026
                        not be an error: just the buf_pool clock
1715
1027
                        has wrapped around */
1716
 
                        ut_a(LRU_pos >= buf_page_get_LRU_position(bpage));
 
1028
                        ut_a(LRU_pos >= block->LRU_position);
1717
1029
                }
1718
1030
        }
1719
1031
 
1721
1033
                ut_a(buf_pool->LRU_old_len == old_len);
1722
1034
        }
1723
1035
 
1724
 
        UT_LIST_VALIDATE(list, buf_page_t, buf_pool->free);
1725
 
 
1726
 
        for (bpage = UT_LIST_GET_FIRST(buf_pool->free);
1727
 
             bpage != NULL;
1728
 
             bpage = UT_LIST_GET_NEXT(list, bpage)) {
1729
 
 
1730
 
                ut_a(buf_page_get_state(bpage) == BUF_BLOCK_NOT_USED);
1731
 
        }
1732
 
 
1733
 
        UT_LIST_VALIDATE(unzip_LRU, buf_block_t, buf_pool->unzip_LRU);
1734
 
 
1735
 
        for (block = UT_LIST_GET_FIRST(buf_pool->unzip_LRU);
1736
 
             block;
1737
 
             block = UT_LIST_GET_NEXT(unzip_LRU, block)) {
1738
 
 
1739
 
                ut_ad(block->in_unzip_LRU_list);
1740
 
                ut_ad(block->page.in_LRU_list);
1741
 
                ut_a(buf_page_belongs_to_unzip_LRU(&block->page));
1742
 
        }
1743
 
 
1744
 
        buf_pool_mutex_exit();
 
1036
        UT_LIST_VALIDATE(free, buf_block_t, buf_pool->free);
 
1037
 
 
1038
        block = UT_LIST_GET_FIRST(buf_pool->free);
 
1039
 
 
1040
        while (block != NULL) {
 
1041
                ut_a(block->state == BUF_BLOCK_NOT_USED);
 
1042
 
 
1043
                block = UT_LIST_GET_NEXT(free, block);
 
1044
        }
 
1045
 
 
1046
        mutex_exit(&(buf_pool->mutex));
1745
1047
        return(TRUE);
1746
1048
}
1747
 
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
1748
1049
 
1749
 
#if defined UNIV_DEBUG_PRINT || defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
1750
1050
/**************************************************************************
1751
1051
Prints the LRU list. */
1752
 
UNIV_INTERN
 
1052
 
1753
1053
void
1754
1054
buf_LRU_print(void)
1755
1055
/*===============*/
1756
1056
{
1757
 
        const buf_page_t*       bpage;
 
1057
        buf_block_t*    block;
 
1058
        buf_frame_t*    frame;
 
1059
        ulint           len;
1758
1060
 
1759
1061
        ut_ad(buf_pool);
1760
 
        buf_pool_mutex_enter();
 
1062
        mutex_enter(&(buf_pool->mutex));
1761
1063
 
1762
1064
        fprintf(stderr, "Pool ulint clock %lu\n",
1763
1065
                (ulong) buf_pool->ulint_clock);
1764
1066
 
1765
 
        bpage = UT_LIST_GET_FIRST(buf_pool->LRU);
1766
 
 
1767
 
        while (bpage != NULL) {
1768
 
 
1769
 
                fprintf(stderr, "BLOCK space %lu page %lu ",
1770
 
                        (ulong) buf_page_get_space(bpage),
1771
 
                        (ulong) buf_page_get_page_no(bpage));
1772
 
 
1773
 
                if (buf_page_is_old(bpage)) {
 
1067
        block = UT_LIST_GET_FIRST(buf_pool->LRU);
 
1068
 
 
1069
        len = 0;
 
1070
 
 
1071
        while (block != NULL) {
 
1072
 
 
1073
                fprintf(stderr, "BLOCK %lu ", (ulong) block->offset);
 
1074
 
 
1075
                if (block->old) {
1774
1076
                        fputs("old ", stderr);
1775
1077
                }
1776
1078
 
1777
 
                if (bpage->buf_fix_count) {
 
1079
                if (block->buf_fix_count) {
1778
1080
                        fprintf(stderr, "buffix count %lu ",
1779
 
                                (ulong) bpage->buf_fix_count);
1780
 
                }
1781
 
 
1782
 
                if (buf_page_get_io_fix(bpage)) {
1783
 
                        fprintf(stderr, "io_fix %lu ",
1784
 
                                (ulong) buf_page_get_io_fix(bpage));
1785
 
                }
1786
 
 
1787
 
                if (bpage->oldest_modification) {
 
1081
                                (ulong) block->buf_fix_count);
 
1082
                }
 
1083
 
 
1084
                if (block->io_fix) {
 
1085
                        fprintf(stderr, "io_fix %lu ", (ulong) block->io_fix);
 
1086
                }
 
1087
 
 
1088
                if (ut_dulint_cmp(block->oldest_modification,
 
1089
                                  ut_dulint_zero) > 0) {
1788
1090
                        fputs("modif. ", stderr);
1789
1091
                }
1790
1092
 
1791
 
                switch (buf_page_get_state(bpage)) {
1792
 
                        const byte*     frame;
1793
 
                case BUF_BLOCK_FILE_PAGE:
1794
 
                        frame = buf_block_get_frame((buf_block_t*) bpage);
1795
 
                        fprintf(stderr, "\nLRU pos %lu type %lu"
1796
 
                                " index id %lu\n",
1797
 
                                (ulong) buf_page_get_LRU_position(bpage),
1798
 
                                (ulong) fil_page_get_type(frame),
1799
 
                                (ulong) ut_dulint_get_low(
1800
 
                                        btr_page_get_index_id(frame)));
1801
 
                        break;
1802
 
                case BUF_BLOCK_ZIP_PAGE:
1803
 
                        frame = bpage->zip.data;
1804
 
                        fprintf(stderr, "\nLRU pos %lu type %lu size %lu"
1805
 
                                " index id %lu\n",
1806
 
                                (ulong) buf_page_get_LRU_position(bpage),
1807
 
                                (ulong) fil_page_get_type(frame),
1808
 
                                (ulong) buf_page_get_zip_size(bpage),
1809
 
                                (ulong) ut_dulint_get_low(
1810
 
                                        btr_page_get_index_id(frame)));
1811
 
                        break;
1812
 
 
1813
 
                default:
1814
 
                        fprintf(stderr, "\nLRU pos %lu !state %lu!\n",
1815
 
                                (ulong) buf_page_get_LRU_position(bpage),
1816
 
                                (ulong) buf_page_get_state(bpage));
1817
 
                        break;
 
1093
                frame = buf_block_get_frame(block);
 
1094
 
 
1095
                fprintf(stderr, "LRU pos %lu type %lu index id %lu ",
 
1096
                        (ulong) block->LRU_position,
 
1097
                        (ulong) fil_page_get_type(frame),
 
1098
                        (ulong) ut_dulint_get_low
 
1099
                        (btr_page_get_index_id(frame)));
 
1100
 
 
1101
                block = UT_LIST_GET_NEXT(LRU, block);
 
1102
                if (++len == 10) {
 
1103
                        len = 0;
 
1104
                        putc('\n', stderr);
1818
1105
                }
1819
 
 
1820
 
                bpage = UT_LIST_GET_NEXT(LRU, bpage);
1821
1106
        }
1822
1107
 
1823
 
        buf_pool_mutex_exit();
 
1108
        mutex_exit(&(buf_pool->mutex));
1824
1109
}
1825
 
#endif /* UNIV_DEBUG_PRINT || UNIV_DEBUG || UNIV_BUF_DEBUG */
 
1110
#endif /* UNIV_DEBUG */