~drizzle-trunk/drizzle/development

641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1
/******************************************************
2
The database buffer buf_pool
3
4
(c) 1995 Innobase Oy
5
6
Created 11/5/1995 Heikki Tuuri
7
*******************************************************/
8
9
#include "buf0flu.h"
10
#include "buf0lru.h"
11
#include "buf0rea.h"
12
#include "mtr0mtr.h"
13
14
/************************************************************************
15
Reads the freed_page_clock of a buffer block. */
16
UNIV_INLINE
17
ulint
18
buf_page_get_freed_page_clock(
19
/*==========================*/
20
					/* out: freed_page_clock */
21
	const buf_page_t*	bpage)	/* in: block */
22
{
23
	return(bpage->freed_page_clock);
24
}
25
26
/************************************************************************
27
Reads the freed_page_clock of a buffer block. */
28
UNIV_INLINE
29
ulint
30
buf_block_get_freed_page_clock(
31
/*===========================*/
32
					/* out: freed_page_clock */
33
	const buf_block_t*	block)	/* in: block */
34
{
35
	return(buf_page_get_freed_page_clock(&block->page));
36
}
37
38
/************************************************************************
39
Recommends a move of a block to the start of the LRU list if there is danger
40
of dropping from the buffer pool. NOTE: does not reserve the buffer pool
41
mutex. */
42
UNIV_INLINE
43
ibool
44
buf_page_peek_if_too_old(
45
/*=====================*/
46
					/* out: TRUE if should be made
47
					younger */
48
	const buf_page_t*	bpage)	/* in: block to make younger */
49
{
50
	return(buf_pool->freed_page_clock
51
	       >= buf_page_get_freed_page_clock(bpage)
52
	       + 1 + (buf_pool->curr_size / 4));
53
}
54
55
/*************************************************************************
56
Gets the current size of buffer buf_pool in bytes. */
57
UNIV_INLINE
58
ulint
59
buf_pool_get_curr_size(void)
60
/*========================*/
61
			/* out: size in bytes */
62
{
63
	return(buf_pool->curr_size * UNIV_PAGE_SIZE);
64
}
65
66
/************************************************************************
67
Gets the smallest oldest_modification lsn for any page in the pool. Returns
68
zero if all modified pages have been flushed to disk. */
69
UNIV_INLINE
70
ib_uint64_t
71
buf_pool_get_oldest_modification(void)
72
/*==================================*/
73
				/* out: oldest modification in pool,
74
				zero if none */
75
{
76
	buf_page_t*	bpage;
77
	ib_uint64_t	lsn;
78
79
	buf_pool_mutex_enter();
80
81
	bpage = UT_LIST_GET_LAST(buf_pool->flush_list);
82
83
	if (bpage == NULL) {
84
		lsn = 0;
85
	} else {
86
		ut_ad(bpage->in_flush_list);
87
		lsn = bpage->oldest_modification;
88
	}
89
90
	buf_pool_mutex_exit();
91
92
	return(lsn);
93
}
94
95
/***********************************************************************
96
Increments the buf_pool clock by one and returns its new value. Remember
97
that in the 32 bit version the clock wraps around at 4 billion! */
98
UNIV_INLINE
99
ulint
100
buf_pool_clock_tic(void)
101
/*====================*/
102
			/* out: new clock value */
103
{
104
	ut_ad(buf_pool_mutex_own());
105
106
	buf_pool->ulint_clock++;
107
108
	return(buf_pool->ulint_clock);
109
}
110
111
/*************************************************************************
112
Gets the state of a block. */
113
UNIV_INLINE
114
enum buf_page_state
115
buf_page_get_state(
116
/*===============*/
117
					/* out: state */
118
	const buf_page_t*	bpage)	/* in: pointer to the control block */
119
{
120
	enum buf_page_state	state = (enum buf_page_state) bpage->state;
121
122
#ifdef UNIV_DEBUG
123
	switch (state) {
124
	case BUF_BLOCK_ZIP_FREE:
125
	case BUF_BLOCK_ZIP_PAGE:
126
	case BUF_BLOCK_ZIP_DIRTY:
127
	case BUF_BLOCK_NOT_USED:
128
	case BUF_BLOCK_READY_FOR_USE:
129
	case BUF_BLOCK_FILE_PAGE:
130
	case BUF_BLOCK_MEMORY:
131
	case BUF_BLOCK_REMOVE_HASH:
132
		break;
133
	default:
134
		ut_error;
135
	}
136
#endif /* UNIV_DEBUG */
137
138
	return(state);
139
}
140
/*************************************************************************
141
Gets the state of a block. */
142
UNIV_INLINE
143
enum buf_page_state
144
buf_block_get_state(
145
/*================*/
146
					/* out: state */
147
	const buf_block_t*	block)	/* in: pointer to the control block */
148
{
149
	return(buf_page_get_state(&block->page));
150
}
151
/*************************************************************************
152
Sets the state of a block. */
153
UNIV_INLINE
154
void
155
buf_page_set_state(
156
/*===============*/
157
	buf_page_t*		bpage,	/* in/out: pointer to control block */
158
	enum buf_page_state	state)	/* in: state */
159
{
160
#ifdef UNIV_DEBUG
161
	enum buf_page_state	old_state	= buf_page_get_state(bpage);
162
163
	switch (old_state) {
164
	case BUF_BLOCK_ZIP_FREE:
165
		ut_error;
166
		break;
167
	case BUF_BLOCK_ZIP_PAGE:
168
		ut_a(state == BUF_BLOCK_ZIP_DIRTY);
169
		break;
170
	case BUF_BLOCK_ZIP_DIRTY:
171
		ut_a(state == BUF_BLOCK_ZIP_PAGE);
172
		break;
173
	case BUF_BLOCK_NOT_USED:
174
		ut_a(state == BUF_BLOCK_READY_FOR_USE);
175
		break;
176
	case BUF_BLOCK_READY_FOR_USE:
177
		ut_a(state == BUF_BLOCK_MEMORY
178
		     || state == BUF_BLOCK_FILE_PAGE
179
		     || state == BUF_BLOCK_NOT_USED);
180
		break;
181
	case BUF_BLOCK_MEMORY:
182
		ut_a(state == BUF_BLOCK_NOT_USED);
183
		break;
184
	case BUF_BLOCK_FILE_PAGE:
185
		ut_a(state == BUF_BLOCK_NOT_USED
186
		     || state == BUF_BLOCK_REMOVE_HASH);
187
		break;
188
	case BUF_BLOCK_REMOVE_HASH:
189
		ut_a(state == BUF_BLOCK_MEMORY);
190
		break;
191
	}
192
#endif /* UNIV_DEBUG */
193
	bpage->state = state;
194
	ut_ad(buf_page_get_state(bpage) == state);
195
}
196
197
/*************************************************************************
198
Sets the state of a block. */
199
UNIV_INLINE
200
void
201
buf_block_set_state(
202
/*================*/
203
	buf_block_t*		block,	/* in/out: pointer to control block */
204
	enum buf_page_state	state)	/* in: state */
205
{
206
	buf_page_set_state(&block->page, state);
207
}
208
209
/*************************************************************************
210
Determines if a block is mapped to a tablespace. */
211
UNIV_INLINE
212
ibool
213
buf_page_in_file(
214
/*=============*/
215
					/* out: TRUE if mapped */
216
	const buf_page_t*	bpage)	/* in: pointer to control block */
217
{
218
	switch (buf_page_get_state(bpage)) {
219
	case BUF_BLOCK_ZIP_FREE:
220
		/* This is a free page in buf_pool->zip_free[].
221
		Such pages should only be accessed by the buddy allocator. */
222
		ut_error;
223
		break;
224
	case BUF_BLOCK_ZIP_PAGE:
225
	case BUF_BLOCK_ZIP_DIRTY:
226
	case BUF_BLOCK_FILE_PAGE:
227
		return(TRUE);
228
	case BUF_BLOCK_NOT_USED:
229
	case BUF_BLOCK_READY_FOR_USE:
230
	case BUF_BLOCK_MEMORY:
231
	case BUF_BLOCK_REMOVE_HASH:
232
		break;
233
	}
234
235
	return(FALSE);
236
}
237
238
/*************************************************************************
239
Determines if a block should be on unzip_LRU list. */
240
UNIV_INLINE
241
ibool
242
buf_page_belongs_to_unzip_LRU(
243
/*==========================*/
244
					/* out: TRUE if block belongs
245
					to unzip_LRU */
246
	const buf_page_t*	bpage)	/* in: pointer to control block */
247
{
248
	ut_ad(buf_page_in_file(bpage));
249
250
	return(bpage->zip.data
251
	       && buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE);
252
}
253
254
/*************************************************************************
255
Determine the approximate LRU list position of a block. */
256
UNIV_INLINE
257
ulint
258
buf_page_get_LRU_position(
259
/*======================*/
260
					/* out: LRU list position */
261
	const buf_page_t*	bpage)	/* in: control block */
262
{
263
	ut_ad(buf_page_in_file(bpage));
264
265
	return(bpage->LRU_position);
266
}
267
268
/*************************************************************************
269
Gets the mutex of a block. */
270
UNIV_INLINE
271
mutex_t*
272
buf_page_get_mutex(
273
/*===============*/
274
					/* out: pointer to mutex
275
					protecting bpage */
276
	const buf_page_t*	bpage)	/* in: pointer to control block */
277
{
278
	switch (buf_page_get_state(bpage)) {
279
	case BUF_BLOCK_ZIP_FREE:
280
		ut_error;
281
		return(NULL);
282
	case BUF_BLOCK_ZIP_PAGE:
283
	case BUF_BLOCK_ZIP_DIRTY:
284
		return(&buf_pool_zip_mutex);
285
	default:
286
		return(&((buf_block_t*) bpage)->mutex);
287
	}
288
}
289
290
/*************************************************************************
291
Get the flush type of a page. */
292
UNIV_INLINE
293
enum buf_flush
294
buf_page_get_flush_type(
295
/*====================*/
296
					/* out: flush type */
297
	const buf_page_t*	bpage)	/* in: buffer page */
298
{
299
	enum buf_flush	flush_type = (enum buf_flush) bpage->flush_type;
300
301
#ifdef UNIV_DEBUG
302
	switch (flush_type) {
303
	case BUF_FLUSH_LRU:
304
	case BUF_FLUSH_SINGLE_PAGE:
305
	case BUF_FLUSH_LIST:
306
		return(flush_type);
307
	case BUF_FLUSH_N_TYPES:
308
		break;
309
	}
310
	ut_error;
311
#endif /* UNIV_DEBUG */
312
	return(flush_type);
313
}
314
/*************************************************************************
315
Set the flush type of a page. */
316
UNIV_INLINE
317
void
318
buf_page_set_flush_type(
319
/*====================*/
320
	buf_page_t*	bpage,		/* in: buffer page */
321
	enum buf_flush	flush_type)	/* in: flush type */
322
{
323
	bpage->flush_type = flush_type;
324
	ut_ad(buf_page_get_flush_type(bpage) == flush_type);
325
}
326
327
/*************************************************************************
328
Map a block to a file page. */
329
UNIV_INLINE
330
void
331
buf_block_set_file_page(
332
/*====================*/
333
	buf_block_t*		block,	/* in/out: pointer to control block */
334
	ulint			space,	/* in: tablespace id */
335
	ulint			page_no)/* in: page number */
336
{
337
	buf_block_set_state(block, BUF_BLOCK_FILE_PAGE);
338
	block->page.space = space;
339
	block->page.offset = page_no;
340
}
341
342
/*************************************************************************
343
Gets the io_fix state of a block. */
344
UNIV_INLINE
345
enum buf_io_fix
346
buf_page_get_io_fix(
347
/*================*/
348
					/* out: io_fix state */
349
	const buf_page_t*	bpage)	/* in: pointer to the control block */
350
{
351
	enum buf_io_fix	io_fix = (enum buf_io_fix) bpage->io_fix;
352
#ifdef UNIV_DEBUG
353
	switch (io_fix) {
354
	case BUF_IO_NONE:
355
	case BUF_IO_READ:
356
	case BUF_IO_WRITE:
357
		return(io_fix);
358
	}
359
	ut_error;
360
#endif /* UNIV_DEBUG */
361
	return(io_fix);
362
}
363
364
/*************************************************************************
365
Gets the io_fix state of a block. */
366
UNIV_INLINE
367
enum buf_io_fix
368
buf_block_get_io_fix(
369
/*================*/
370
					/* out: io_fix state */
371
	const buf_block_t*	block)	/* in: pointer to the control block */
372
{
373
	return(buf_page_get_io_fix(&block->page));
374
}
375
376
/*************************************************************************
377
Sets the io_fix state of a block. */
378
UNIV_INLINE
379
void
380
buf_page_set_io_fix(
381
/*================*/
382
	buf_page_t*	bpage,	/* in/out: control block */
383
	enum buf_io_fix	io_fix)	/* in: io_fix state */
384
{
385
	ut_ad(buf_pool_mutex_own());
386
	ut_ad(mutex_own(buf_page_get_mutex(bpage)));
387
388
	bpage->io_fix = io_fix;
389
	ut_ad(buf_page_get_io_fix(bpage) == io_fix);
390
}
391
392
/*************************************************************************
393
Sets the io_fix state of a block. */
394
UNIV_INLINE
395
void
396
buf_block_set_io_fix(
397
/*=================*/
398
	buf_block_t*	block,	/* in/out: control block */
399
	enum buf_io_fix	io_fix)	/* in: io_fix state */
400
{
401
	buf_page_set_io_fix(&block->page, io_fix);
402
}
403
404
/************************************************************************
405
Determine if a buffer block can be relocated in memory.  The block
406
can be dirty, but it must not be I/O-fixed or bufferfixed. */
407
UNIV_INLINE
408
ibool
409
buf_page_can_relocate(
410
/*==================*/
411
	const buf_page_t*	bpage)	/* control block being relocated */
412
{
413
	ut_ad(buf_pool_mutex_own());
414
	ut_ad(mutex_own(buf_page_get_mutex(bpage)));
415
	ut_ad(buf_page_in_file(bpage));
416
	ut_ad(bpage->in_LRU_list);
417
418
	return(buf_page_get_io_fix(bpage) == BUF_IO_NONE
419
	       && bpage->buf_fix_count == 0);
420
}
421
422
/*************************************************************************
423
Determine if a block has been flagged old. */
424
UNIV_INLINE
425
ibool
426
buf_page_is_old(
427
/*============*/
428
					/* out: TRUE if old */
429
	const buf_page_t*	bpage)	/* in: control block */
430
{
431
	ut_ad(buf_page_in_file(bpage));
432
433
	return(bpage->old);
434
}
435
436
/*************************************************************************
437
Flag a block old. */
438
UNIV_INLINE
439
void
440
buf_page_set_old(
441
/*=============*/
442
	buf_page_t*	bpage,	/* in/out: control block */
443
	ibool		old)	/* in: old */
444
{
445
	ut_a(buf_page_in_file(bpage));
446
	ut_ad(buf_pool_mutex_own());
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
447
	ut_ad(bpage->in_LRU_list);
448
449
#ifdef UNIV_LRU_DEBUG
450
	if (UT_LIST_GET_PREV(LRU, bpage) && UT_LIST_GET_NEXT(LRU, bpage)
451
	    && UT_LIST_GET_PREV(LRU, bpage)->old
452
	    == UT_LIST_GET_NEXT(LRU, bpage)->old) {
453
		ut_a(UT_LIST_GET_PREV(LRU, bpage)->old == old);
454
	}
455
#endif /* UNIV_LRU_DEBUG */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
456
457
	bpage->old = old;
458
}
459
460
/*************************************************************************
461
Determine if a block has been accessed in the buffer pool. */
462
UNIV_INLINE
463
ibool
464
buf_page_is_accessed(
465
/*=================*/
466
					/* out: TRUE if accessed */
467
	const buf_page_t*	bpage)	/* in: control block */
468
{
469
	ut_ad(buf_page_in_file(bpage));
470
471
	return(bpage->accessed);
472
}
473
474
/*************************************************************************
475
Flag a block accessed. */
476
UNIV_INLINE
477
void
478
buf_page_set_accessed(
479
/*==================*/
480
	buf_page_t*	bpage,		/* in/out: control block */
481
	ibool		accessed)	/* in: accessed */
482
{
483
	ut_a(buf_page_in_file(bpage));
484
	ut_ad(mutex_own(buf_page_get_mutex(bpage)));
485
486
	bpage->accessed = accessed;
487
}
488
489
/*************************************************************************
490
Gets the buf_block_t handle of a buffered file block if an uncompressed
491
page frame exists, or NULL. */
492
UNIV_INLINE
493
buf_block_t*
494
buf_page_get_block(
495
/*===============*/
496
				/* out: control block, or NULL */
497
	buf_page_t*	bpage)	/* in: control block, or NULL */
498
{
499
	if (UNIV_LIKELY(bpage != NULL)) {
500
		ut_ad(buf_page_in_file(bpage));
501
502
		if (buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE) {
503
			return((buf_block_t*) bpage);
504
		}
505
	}
506
507
	return(NULL);
508
}
509
510
#ifdef UNIV_DEBUG
511
/*************************************************************************
512
Gets a pointer to the memory frame of a block. */
513
UNIV_INLINE
514
buf_frame_t*
515
buf_block_get_frame(
516
/*================*/
517
					/* out: pointer to the frame */
518
	const buf_block_t*	block)	/* in: pointer to the control block */
519
{
520
	ut_ad(block);
521
522
	switch (buf_block_get_state(block)) {
523
	case BUF_BLOCK_ZIP_FREE:
524
	case BUF_BLOCK_ZIP_PAGE:
525
	case BUF_BLOCK_ZIP_DIRTY:
526
	case BUF_BLOCK_NOT_USED:
527
		ut_error;
528
		break;
529
	case BUF_BLOCK_FILE_PAGE:
530
		ut_a(block->page.buf_fix_count > 0);
531
		/* fall through */
532
	case BUF_BLOCK_READY_FOR_USE:
533
	case BUF_BLOCK_MEMORY:
534
	case BUF_BLOCK_REMOVE_HASH:
535
		goto ok;
536
	}
537
	ut_error;
538
ok:
539
	return((buf_frame_t*) block->frame);
540
}
541
#endif /* UNIV_DEBUG */
542
543
/*************************************************************************
544
Gets the space id of a block. */
545
UNIV_INLINE
546
ulint
547
buf_page_get_space(
548
/*===============*/
549
					/* out: space id */
550
	const buf_page_t*	bpage)	/* in: pointer to the control block */
551
{
552
	ut_ad(bpage);
553
	ut_a(buf_page_in_file(bpage));
554
555
	return(bpage->space);
556
}
557
558
/*************************************************************************
559
Gets the space id of a block. */
560
UNIV_INLINE
561
ulint
562
buf_block_get_space(
563
/*================*/
564
					/* out: space id */
565
	const buf_block_t*	block)	/* in: pointer to the control block */
566
{
567
	ut_ad(block);
568
	ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
569
570
	return(block->page.space);
571
}
572
573
/*************************************************************************
574
Gets the page number of a block. */
575
UNIV_INLINE
576
ulint
577
buf_page_get_page_no(
578
/*=================*/
579
					/* out: page number */
580
	const buf_page_t*	bpage)	/* in: pointer to the control block */
581
{
582
	ut_ad(bpage);
583
	ut_a(buf_page_in_file(bpage));
584
585
	return(bpage->offset);
586
}
587
588
/*************************************************************************
589
Gets the page number of a block. */
590
UNIV_INLINE
591
ulint
592
buf_block_get_page_no(
593
/*==================*/
594
					/* out: page number */
595
	const buf_block_t*	block)	/* in: pointer to the control block */
596
{
597
	ut_ad(block);
598
	ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
599
600
	return(block->page.offset);
601
}
602
603
/*************************************************************************
604
Gets the compressed page size of a block. */
605
UNIV_INLINE
606
ulint
607
buf_page_get_zip_size(
608
/*==================*/
609
					/* out: compressed page size, or 0 */
610
	const buf_page_t*	bpage)	/* in: pointer to the control block */
611
{
612
	return(bpage->zip.ssize ? 512 << bpage->zip.ssize : 0);
613
}
614
615
/*************************************************************************
616
Gets the compressed page size of a block. */
617
UNIV_INLINE
618
ulint
619
buf_block_get_zip_size(
620
/*===================*/
621
					/* out: compressed page size, or 0 */
622
	const buf_block_t*	block)	/* in: pointer to the control block */
623
{
624
	return(block->page.zip.ssize ? 512 << block->page.zip.ssize : 0);
625
}
626
627
#if defined UNIV_DEBUG || defined UNIV_ZIP_DEBUG
628
/***********************************************************************
629
Gets the block to whose frame the pointer is pointing to. */
630
UNIV_INLINE
631
const buf_block_t*
632
buf_block_align(
633
/*============*/
634
				/* out: pointer to block */
635
	const byte*	ptr)	/* in: pointer to a frame */
636
{
637
	const buf_block_t*	block;
638
	ulint			space_id, page_no;
639
640
	ptr = (const byte*) ut_align_down(ptr, UNIV_PAGE_SIZE);
641
	page_no = mach_read_from_4(ptr + FIL_PAGE_OFFSET);
642
	space_id = mach_read_from_4(ptr + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
643
644
	block = (const buf_block_t*) buf_page_hash_get(space_id, page_no);
645
	ut_ad(block);
646
	ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
647
	ut_ad(block->frame == ptr);
648
	return(block);
649
}
650
651
/*************************************************************************
652
Gets the compressed page descriptor corresponding to an uncompressed page
653
if applicable. */
654
UNIV_INLINE
655
const page_zip_des_t*
656
buf_frame_get_page_zip(
657
/*===================*/
658
				/* out: compressed page descriptor, or NULL */
659
	const byte*	ptr)	/* in: pointer to the page */
660
{
661
	const page_zip_des_t*	page_zip;
662
	buf_pool_mutex_enter();
663
	page_zip = buf_block_get_page_zip(buf_block_align(ptr));
664
	buf_pool_mutex_exit();
665
	return(page_zip);
666
}
667
#endif /* UNIV_DEBUG || UNIV_ZIP_DEBUG */
668
669
/**************************************************************************
670
Gets the space id, page offset, and byte offset within page of a
671
pointer pointing to a buffer frame containing a file page. */
672
UNIV_INLINE
673
void
674
buf_ptr_get_fsp_addr(
675
/*=================*/
676
	const void*	ptr,	/* in: pointer to a buffer frame */
677
	ulint*		space,	/* out: space id */
678
	fil_addr_t*	addr)	/* out: page offset and byte offset */
679
{
680
	const page_t*	page = (const page_t*) ut_align_down(ptr,
681
							     UNIV_PAGE_SIZE);
682
683
	*space = mach_read_from_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
684
	addr->page = mach_read_from_4(page + FIL_PAGE_OFFSET);
685
	addr->boffset = ut_align_offset(ptr, UNIV_PAGE_SIZE);
686
}
687
688
/**************************************************************************
689
Gets the hash value of the page the pointer is pointing to. This can be used
690
in searches in the lock hash table. */
691
UNIV_INLINE
692
ulint
693
buf_block_get_lock_hash_val(
694
/*========================*/
695
					/* out: lock hash value */
696
	const buf_block_t*	block)	/* in: block */
697
{
698
	return(block->lock_hash_val);
699
}
700
701
/************************************************************************
702
Allocates a buffer block. */
703
UNIV_INLINE
704
buf_block_t*
705
buf_block_alloc(
706
/*============*/
707
				/* out, own: the allocated block,
708
				in state BUF_BLOCK_MEMORY */
709
	ulint	zip_size)	/* in: compressed page size in bytes,
710
				or 0 if uncompressed tablespace */
711
{
712
	buf_block_t*	block;
713
714
	block = buf_LRU_get_free_block(zip_size);
715
716
	buf_block_set_state(block, BUF_BLOCK_MEMORY);
717
718
	return(block);
719
}
720
721
/************************************************************************
722
Frees a buffer block which does not contain a file page. */
723
UNIV_INLINE
724
void
725
buf_block_free(
726
/*===========*/
727
	buf_block_t*	block)	/* in, own: block to be freed */
728
{
729
	buf_pool_mutex_enter();
730
731
	mutex_enter(&block->mutex);
732
733
	ut_a(buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE);
734
735
	buf_LRU_block_free_non_file_page(block);
736
737
	mutex_exit(&block->mutex);
738
739
	buf_pool_mutex_exit();
740
}
741
742
/*************************************************************************
743
Copies contents of a buffer frame to a given buffer. */
744
UNIV_INLINE
745
byte*
746
buf_frame_copy(
747
/*===========*/
748
					/* out: buf */
749
	byte*			buf,	/* in: buffer to copy to */
750
	const buf_frame_t*	frame)	/* in: buffer frame */
751
{
752
	ut_ad(buf && frame);
753
754
	ut_memcpy(buf, frame, UNIV_PAGE_SIZE);
755
756
	return(buf);
757
}
758
759
/************************************************************************
760
Calculates a folded value of a file page address to use in the page hash
761
table. */
762
UNIV_INLINE
763
ulint
764
buf_page_address_fold(
765
/*==================*/
766
			/* out: the folded value */
767
	ulint	space,	/* in: space id */
768
	ulint	offset)	/* in: offset of the page within space */
769
{
770
	return((space << 20) + space + offset);
771
}
772
773
/************************************************************************
774
This function is used to get info if there is an io operation
775
going on on a buffer page. */
776
UNIV_INLINE
777
ibool
778
buf_page_io_query(
779
/*==============*/
780
				/* out: TRUE if io going on */
781
	buf_page_t*	bpage)	/* in: buf_pool block, must be bufferfixed */
782
{
783
	ibool	io_fixed;
784
785
	buf_pool_mutex_enter();
786
787
	ut_ad(buf_page_in_file(bpage));
788
	ut_ad(bpage->buf_fix_count > 0);
789
790
	io_fixed = buf_page_get_io_fix(bpage) != BUF_IO_NONE;
791
	buf_pool_mutex_exit();
792
793
	return(io_fixed);
794
}
795
796
/************************************************************************
797
Gets the youngest modification log sequence number for a frame.
798
Returns zero if not file page or no modification occurred yet. */
799
UNIV_INLINE
800
ib_uint64_t
801
buf_page_get_newest_modification(
802
/*=============================*/
803
					/* out: newest modification to page */
804
	const buf_page_t*	bpage)	/* in: block containing the
805
					page frame */
806
{
807
	ib_uint64_t	lsn;
808
809
	buf_pool_mutex_enter();
810
811
	if (buf_page_in_file(bpage)) {
812
		lsn = bpage->newest_modification;
813
	} else {
814
		lsn = 0;
815
	}
816
817
	buf_pool_mutex_exit();
818
819
	return(lsn);
820
}
821
822
/************************************************************************
823
Increments the modify clock of a frame by 1. The caller must (1) own the
824
buf_pool mutex and block bufferfix count has to be zero, (2) or own an x-lock
825
on the block. */
826
UNIV_INLINE
827
void
828
buf_block_modify_clock_inc(
829
/*=======================*/
830
	buf_block_t*	block)	/* in: block */
831
{
832
#ifdef UNIV_SYNC_DEBUG
833
	ut_ad((buf_pool_mutex_own()
834
	       && (block->page.buf_fix_count == 0))
835
	      || rw_lock_own(&(block->lock), RW_LOCK_EXCLUSIVE));
836
#endif /* UNIV_SYNC_DEBUG */
837
838
	block->modify_clock++;
839
}
840
841
/************************************************************************
842
Returns the value of the modify clock. The caller must have an s-lock
843
or x-lock on the block. */
844
UNIV_INLINE
845
ib_uint64_t
846
buf_block_get_modify_clock(
847
/*=======================*/
848
				/* out: value */
849
	buf_block_t*	block)	/* in: block */
850
{
851
#ifdef UNIV_SYNC_DEBUG
852
	ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
853
	      || rw_lock_own(&(block->lock), RW_LOCK_EXCLUSIVE));
854
#endif /* UNIV_SYNC_DEBUG */
855
856
	return(block->modify_clock);
857
}
858
859
/***********************************************************************
860
Increments the bufferfix count. */
861
UNIV_INLINE
862
void
863
buf_block_buf_fix_inc_func(
864
/*=======================*/
865
#ifdef UNIV_SYNC_DEBUG
866
	const char*	file,	/* in: file name */
867
	ulint		line,	/* in: line */
868
#endif /* UNIV_SYNC_DEBUG */
869
	buf_block_t*	block)	/* in: block to bufferfix */
870
{
871
#ifdef UNIV_SYNC_DEBUG
872
	ibool	ret;
873
874
	ret = rw_lock_s_lock_func_nowait(&(block->debug_latch), file, line);
875
	ut_a(ret);
876
#endif /* UNIV_SYNC_DEBUG */
877
	ut_ad(mutex_own(&block->mutex));
878
879
	block->page.buf_fix_count++;
880
}
881
#ifdef UNIV_SYNC_DEBUG
882
# define buf_block_buf_fix_inc(b,f,l) buf_block_buf_fix_inc_func(f,l,b)
883
#else /* UNIV_SYNC_DEBUG */
884
# define buf_block_buf_fix_inc(b,f,l) buf_block_buf_fix_inc_func(b)
885
#endif /* UNIV_SYNC_DEBUG */
886
887
/***********************************************************************
888
Decrements the bufferfix count. */
889
UNIV_INLINE
890
void
891
buf_block_buf_fix_dec(
892
/*==================*/
893
	buf_block_t*	block)	/* in: block to bufferunfix */
894
{
895
	ut_ad(mutex_own(&block->mutex));
896
897
	block->page.buf_fix_count--;
898
#ifdef UNIV_SYNC_DEBUG
899
	rw_lock_s_unlock(&block->debug_latch);
900
#endif
901
}
902
903
/**********************************************************************
904
Returns the control block of a file page, NULL if not found. */
905
UNIV_INLINE
906
buf_page_t*
907
buf_page_hash_get(
908
/*==============*/
909
			/* out: block, NULL if not found */
910
	ulint	space,	/* in: space id */
911
	ulint	offset)	/* in: offset of the page within space */
912
{
913
	buf_page_t*	bpage;
914
	ulint		fold;
915
916
	ut_ad(buf_pool);
917
	ut_ad(buf_pool_mutex_own());
918
919
	/* Look for the page in the hash table */
920
921
	fold = buf_page_address_fold(space, offset);
922
923
	HASH_SEARCH(hash, buf_pool->page_hash, fold, buf_page_t*, bpage,
924
		    bpage->space == space && bpage->offset == offset);
925
	if (bpage) {
926
		ut_a(buf_page_in_file(bpage));
927
		ut_ad(bpage->in_page_hash);
928
		ut_ad(!bpage->in_zip_hash);
929
		UNIV_MEM_ASSERT_RW(bpage, sizeof *bpage);
930
	}
931
932
	return(bpage);
933
}
934
935
/**********************************************************************
936
Returns the control block of a file page, NULL if not found
937
or an uncompressed page frame does not exist. */
938
UNIV_INLINE
939
buf_block_t*
940
buf_block_hash_get(
941
/*===============*/
942
			/* out: block, NULL if not found */
943
	ulint	space,	/* in: space id */
944
	ulint	offset)	/* in: offset of the page within space */
945
{
946
	return(buf_page_get_block(buf_page_hash_get(space, offset)));
947
}
948
949
/************************************************************************
950
Returns TRUE if the page can be found in the buffer pool hash table. NOTE
951
that it is possible that the page is not yet read from disk, though. */
952
UNIV_INLINE
953
ibool
954
buf_page_peek(
955
/*==========*/
956
			/* out: TRUE if found from page hash table,
957
			NOTE that the page is not necessarily yet read
958
			from disk! */
959
	ulint	space,	/* in: space id */
960
	ulint	offset)	/* in: page number */
961
{
962
	const buf_page_t*	bpage;
963
964
	buf_pool_mutex_enter();
965
966
	bpage = buf_page_hash_get(space, offset);
967
968
	buf_pool_mutex_exit();
969
970
	return(bpage != NULL);
971
}
972
973
/************************************************************************
974
Releases a compressed-only page acquired with buf_page_get_zip(). */
975
UNIV_INLINE
976
void
977
buf_page_release_zip(
978
/*=================*/
979
	buf_page_t*	bpage)		/* in: buffer block */
980
{
981
	buf_block_t*	block;
982
983
	ut_ad(bpage);
984
	ut_a(bpage->buf_fix_count > 0);
985
986
	switch (buf_page_get_state(bpage)) {
987
	case BUF_BLOCK_ZIP_PAGE:
988
	case BUF_BLOCK_ZIP_DIRTY:
989
		mutex_enter(&buf_pool_zip_mutex);
990
		bpage->buf_fix_count--;
991
		mutex_exit(&buf_pool_zip_mutex);
992
		return;
993
	case BUF_BLOCK_FILE_PAGE:
994
		block = (buf_block_t*) bpage;
995
		mutex_enter(&block->mutex);
996
#ifdef UNIV_SYNC_DEBUG
997
		rw_lock_s_unlock(&block->debug_latch);
998
#endif
999
		bpage->buf_fix_count--;
1000
		mutex_exit(&block->mutex);
1001
		return;
1002
	case BUF_BLOCK_ZIP_FREE:
1003
	case BUF_BLOCK_NOT_USED:
1004
	case BUF_BLOCK_READY_FOR_USE:
1005
	case BUF_BLOCK_MEMORY:
1006
	case BUF_BLOCK_REMOVE_HASH:
1007
		break;
1008
	}
1009
1010
	ut_error;
1011
}
1012
1013
/************************************************************************
1014
Decrements the bufferfix count of a buffer control block and releases
1015
a latch, if specified. */
1016
UNIV_INLINE
1017
void
1018
buf_page_release(
1019
/*=============*/
1020
	buf_block_t*	block,		/* in: buffer block */
1021
	ulint		rw_latch,	/* in: RW_S_LATCH, RW_X_LATCH,
1022
					RW_NO_LATCH */
1023
	mtr_t*		mtr)		/* in: mtr */
1024
{
1025
	ut_ad(block);
1026
1027
	ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
1028
	ut_a(block->page.buf_fix_count > 0);
1029
1030
	if (rw_latch == RW_X_LATCH && mtr->modifications) {
1031
		buf_pool_mutex_enter();
1032
		buf_flush_note_modification(block, mtr);
1033
		buf_pool_mutex_exit();
1034
	}
1035
1036
	mutex_enter(&block->mutex);
1037
1038
#ifdef UNIV_SYNC_DEBUG
1039
	rw_lock_s_unlock(&(block->debug_latch));
1040
#endif
1041
	block->page.buf_fix_count--;
1042
1043
	mutex_exit(&block->mutex);
1044
1045
	if (rw_latch == RW_S_LATCH) {
1046
		rw_lock_s_unlock(&(block->lock));
1047
	} else if (rw_latch == RW_X_LATCH) {
1048
		rw_lock_x_unlock(&(block->lock));
1049
	}
1050
}
1051
1052
#ifdef UNIV_SYNC_DEBUG
1053
/*************************************************************************
1054
Adds latch level info for the rw-lock protecting the buffer frame. This
1055
should be called in the debug version after a successful latching of a
1056
page if we know the latching order level of the acquired latch. */
1057
UNIV_INLINE
1058
void
1059
buf_block_dbg_add_level(
1060
/*====================*/
1061
	buf_block_t*	block,	/* in: buffer page
1062
				where we have acquired latch */
1063
	ulint		level)	/* in: latching order level */
1064
{
1065
	sync_thread_add_level(&block->lock, level);
1066
}
1067
#endif /* UNIV_SYNC_DEBUG */