1
/******************************************************
4
(c) 1994-1996 Innobase Oy
6
Created 2/2/1994 Heikki Tuuri
7
*******************************************************/
14
#include "page0types.h"
17
#include "data0data.h"
18
#include "dict0dict.h"
23
#ifdef UNIV_MATERIALIZE
31
Index page header starts at the first offset left free by the FIL-module */
33
typedef byte page_header_t;
35
#define PAGE_HEADER FSEG_PAGE_DATA /* index page header starts at this
37
/*-----------------------------*/
38
#define PAGE_N_DIR_SLOTS 0 /* number of slots in page directory */
39
#define PAGE_HEAP_TOP 2 /* pointer to record heap top */
40
#define PAGE_N_HEAP 4 /* number of records in the heap */
41
#define PAGE_FREE 6 /* pointer to start of page free record list */
42
#define PAGE_GARBAGE 8 /* number of bytes in deleted records */
43
#define PAGE_LAST_INSERT 10 /* pointer to the last inserted record, or
44
NULL if this info has been reset by a delete,
46
#define PAGE_DIRECTION 12 /* last insert direction: PAGE_LEFT, ... */
47
#define PAGE_N_DIRECTION 14 /* number of consecutive inserts to the same
49
#define PAGE_N_RECS 16 /* number of user records on the page */
50
#define PAGE_MAX_TRX_ID 18 /* highest id of a trx which may have modified
51
a record on the page; a dulint; defined only
52
in secondary indexes; specifically, not in an
53
ibuf tree; NOTE: this may be modified only
54
when the thread has an x-latch to the page,
55
and ALSO an x-latch to btr_search_latch
56
if there is a hash index to the page! */
57
#define PAGE_HEADER_PRIV_END 26 /* end of private data structure of the page
58
header which are set in a page create */
60
#define PAGE_LEVEL 26 /* level of the node in an index tree; the
61
leaf level is the level 0 */
62
#define PAGE_INDEX_ID 28 /* index id where the page belongs */
63
#define PAGE_BTR_SEG_LEAF 36 /* file segment header for the leaf pages in
64
a B-tree: defined only on the root page of a
65
B-tree, but not in the root of an ibuf tree */
66
#define PAGE_BTR_IBUF_FREE_LIST PAGE_BTR_SEG_LEAF
67
#define PAGE_BTR_IBUF_FREE_LIST_NODE PAGE_BTR_SEG_LEAF
68
/* in the place of PAGE_BTR_SEG_LEAF and _TOP
69
there is a free list base node if the page is
70
the root page of an ibuf tree, and at the same
71
place is the free list node if the page is in
73
#define PAGE_BTR_SEG_TOP (36 + FSEG_HEADER_SIZE)
74
/* file segment header for the non-leaf pages
75
in a B-tree: defined only on the root page of
76
a B-tree, but not in the root of an ibuf
79
#define PAGE_DATA (PAGE_HEADER + 36 + 2 * FSEG_HEADER_SIZE)
80
/* start of data on the page */
82
#define PAGE_INFIMUM (PAGE_DATA + 1 + REC_N_EXTRA_BYTES)
83
/* offset of the page infimum record on the
85
#define PAGE_SUPREMUM (PAGE_DATA + 2 + 2 * REC_N_EXTRA_BYTES + 8)
86
/* offset of the page supremum record on the
88
#define PAGE_SUPREMUM_END (PAGE_SUPREMUM + 9)
89
/* offset of the page supremum record end on
91
/*-----------------------------*/
93
/* Directions of cursor movement */
96
#define PAGE_SAME_REC 3
97
#define PAGE_SAME_PAGE 4
98
#define PAGE_NO_DIRECTION 5
104
typedef byte page_dir_slot_t;
105
typedef page_dir_slot_t page_dir_t;
107
/* Offset of the directory start down from the page end. We call the
108
slot with the highest file address directory start, as it points to
109
the first record in the list of records. */
110
#define PAGE_DIR FIL_PAGE_DATA_END
112
/* We define a slot in the page directory as two bytes */
113
#define PAGE_DIR_SLOT_SIZE 2
115
/* The offset of the physically lower end of the directory, counted from
116
page end, when the page is empty */
117
#define PAGE_EMPTY_DIR_START (PAGE_DIR + 2 * PAGE_DIR_SLOT_SIZE)
119
/* The maximum and minimum number of records owned by a directory slot. The
120
number may drop below the minimum in the first and the last slot in the
122
#define PAGE_DIR_SLOT_MAX_N_OWNED 8
123
#define PAGE_DIR_SLOT_MIN_N_OWNED 4
125
/*****************************************************************
126
Returns the max trx id field value. */
131
page_t* page); /* in: page */
132
/*****************************************************************
133
Sets the max trx id field value. */
138
page_t* page, /* in: page */
139
dulint trx_id);/* in: transaction id */
140
/*****************************************************************
141
Sets the max trx id field value if trx_id is bigger than the previous
145
page_update_max_trx_id(
146
/*===================*/
147
page_t* page, /* in: page */
148
dulint trx_id); /* in: transaction id */
149
/*****************************************************************
150
Reads the given header field. */
153
page_header_get_field(
154
/*==================*/
155
page_t* page, /* in: page */
156
ulint field); /* in: PAGE_N_DIR_SLOTS, ... */
157
/*****************************************************************
158
Sets the given header field. */
161
page_header_set_field(
162
/*==================*/
163
page_t* page, /* in: page */
164
ulint field, /* in: PAGE_N_DIR_SLOTS, ... */
165
ulint val); /* in: value */
166
/*****************************************************************
167
Returns the pointer stored in the given header field. */
172
/* out: pointer or NULL */
173
page_t* page, /* in: page */
174
ulint field); /* in: PAGE_FREE, ... */
175
/*****************************************************************
176
Sets the pointer stored in the given header field. */
181
page_t* page, /* in: page */
182
ulint field, /* in: PAGE_FREE, ... */
183
byte* ptr); /* in: pointer or NULL*/
184
/*****************************************************************
185
Resets the last insert info field in the page header. Writes to mlog
186
about this operation. */
189
page_header_reset_last_insert(
190
/*==========================*/
191
page_t* page, /* in: page */
192
mtr_t* mtr); /* in: mtr */
193
/****************************************************************
194
Gets the first record on the page. */
197
page_get_infimum_rec(
198
/*=================*/
199
/* out: the first record in record list */
200
page_t* page); /* in: page which must have record(s) */
201
/****************************************************************
202
Gets the last record on the page. */
205
page_get_supremum_rec(
206
/*==================*/
207
/* out: the last record in record list */
208
page_t* page); /* in: page which must have record(s) */
209
/****************************************************************
210
Returns the middle record of record list. If there are an even number
211
of records in the list, returns the first record of upper half-list. */
216
/* out: middle record */
217
page_t* page); /* in: page */
218
/*****************************************************************
219
Compares a data tuple to a physical record. Differs from the function
220
cmp_dtuple_rec_with_match in the way that the record must reside on an
221
index page, and also page infimum and supremum records can be given in
222
the parameter rec. These are considered as the negative infinity and
223
the positive infinity in the alphabetical order. */
226
page_cmp_dtuple_rec_with_match(
227
/*===========================*/
228
/* out: 1, 0, -1, if dtuple is greater, equal,
229
less than rec, respectively, when only the
230
common first fields are compared */
231
dtuple_t* dtuple, /* in: data tuple */
232
rec_t* rec, /* in: physical record on a page; may also
233
be page infimum or supremum, in which case
234
matched-parameter values below are not
236
ulint* matched_fields, /* in/out: number of already completely
237
matched fields; when function returns
238
contains the value for current comparison */
239
ulint* matched_bytes); /* in/out: number of already matched
240
bytes within the first field not completely
241
matched; when function returns contains the
242
value for current comparison */
243
/*****************************************************************
244
Gets the number of user records on page (the infimum and supremum records
245
are not user records). */
250
/* out: number of user records */
251
page_t* page); /* in: index page */
252
/*******************************************************************
253
Returns the number of records before the given record in chain.
254
The number includes infimum and supremum records. */
257
page_rec_get_n_recs_before(
258
/*=======================*/
259
/* out: number of records */
260
rec_t* rec); /* in: the physical record */
261
/*****************************************************************
262
Gets the number of dir slots in directory. */
265
page_dir_get_n_slots(
266
/*=================*/
267
/* out: number of slots */
268
page_t* page); /* in: index page */
269
/*****************************************************************
270
Gets pointer to nth directory slot. */
273
page_dir_get_nth_slot(
274
/*==================*/
275
/* out: pointer to dir slot */
276
page_t* page, /* in: index page */
277
ulint n); /* in: position */
278
/******************************************************************
279
Used to check the consistency of a record on a page. */
284
/* out: TRUE if succeed */
285
rec_t* rec); /* in: record */
286
/*******************************************************************
287
Gets the record pointed to by a directory slot. */
290
page_dir_slot_get_rec(
291
/*==================*/
292
/* out: pointer to record */
293
page_dir_slot_t* slot); /* in: directory slot */
294
/*******************************************************************
295
This is used to set the record offset in a directory slot. */
298
page_dir_slot_set_rec(
299
/*==================*/
300
page_dir_slot_t* slot, /* in: directory slot */
301
rec_t* rec); /* in: record on the page */
302
/*******************************************************************
303
Gets the number of records owned by a directory slot. */
306
page_dir_slot_get_n_owned(
307
/*======================*/
308
/* out: number of records */
309
page_dir_slot_t* slot); /* in: page directory slot */
310
/*******************************************************************
311
This is used to set the owned records field of a directory slot. */
314
page_dir_slot_set_n_owned(
315
/*======================*/
316
page_dir_slot_t* slot, /* in: directory slot */
317
ulint n); /* in: number of records owned
319
/****************************************************************
320
Calculates the space reserved for directory slots of a given
321
number of records. The exact value is a fraction number
322
n * PAGE_DIR_SLOT_SIZE / PAGE_DIR_SLOT_MIN_N_OWNED, and it is
323
rounded upwards to an integer. */
326
page_dir_calc_reserved_space(
327
/*=========================*/
328
ulint n_recs); /* in: number of records */
329
/*******************************************************************
330
Looks for the directory slot which owns the given record. */
333
page_dir_find_owner_slot(
334
/*=====================*/
335
/* out: the directory slot number */
336
rec_t* rec); /* in: the physical record */
337
/****************************************************************
338
Gets the pointer to the next record on the page. */
343
/* out: pointer to next record */
344
rec_t* rec); /* in: pointer to record, must not be page
346
/****************************************************************
347
Sets the pointer to the next record on the page. */
352
rec_t* rec, /* in: pointer to record, must not be
354
rec_t* next); /* in: pointer to next record, must not
356
/****************************************************************
357
Gets the pointer to the previous record. */
362
/* out: pointer to previous record */
363
rec_t* rec); /* in: pointer to record, must not be page
365
/****************************************************************
366
TRUE if the record is a user record on the page. */
369
page_rec_is_user_rec(
370
/*=================*/
371
/* out: TRUE if a user record */
372
rec_t* rec); /* in: record */
373
/****************************************************************
374
TRUE if the record is the supremum record on a page. */
377
page_rec_is_supremum(
378
/*=================*/
379
/* out: TRUE if the supremum record */
380
rec_t* rec); /* in: record */
381
/****************************************************************
382
TRUE if the record is the infimum record on a page. */
387
/* out: TRUE if the infimum record */
388
rec_t* rec); /* in: record */
389
/****************************************************************
390
TRUE if the record is the first user record on the page. */
393
page_rec_is_first_user_rec(
394
/*=======================*/
395
/* out: TRUE if first user record */
396
rec_t* rec); /* in: record */
397
/****************************************************************
398
TRUE if the record is the last user record on the page. */
401
page_rec_is_last_user_rec(
402
/*======================*/
403
/* out: TRUE if last user record */
404
rec_t* rec); /* in: record */
405
/*******************************************************************
406
Looks for the record which owns the given record. */
409
page_rec_find_owner_rec(
410
/*====================*/
411
/* out: the owner record */
412
rec_t* rec); /* in: the physical record */
413
/***************************************************************************
414
This is a low-level operation which is used in a database index creation
415
to update the page number of a created B-tree to a data dictionary
419
page_rec_write_index_page_no(
420
/*=========================*/
421
rec_t* rec, /* in: record to update */
422
ulint i, /* in: index of the field to update */
423
ulint page_no,/* in: value to write */
424
mtr_t* mtr); /* in: mtr */
425
/****************************************************************
426
Returns the maximum combined size of records which can be inserted on top
430
page_get_max_insert_size(
431
/*=====================*/
432
/* out: maximum combined size for inserted records */
433
page_t* page, /* in: index page */
434
ulint n_recs); /* in: number of records */
435
/****************************************************************
436
Returns the maximum combined size of records which can be inserted on top
437
of record heap if page is first reorganized. */
440
page_get_max_insert_size_after_reorganize(
441
/*======================================*/
442
/* out: maximum combined size for inserted records */
443
page_t* page, /* in: index page */
444
ulint n_recs);/* in: number of records */
445
/*****************************************************************
446
Calculates free space if a page is emptied. */
449
page_get_free_space_of_empty(void);
450
/*==============================*/
451
/* out: free space */
452
/****************************************************************
453
Returns the sum of the sizes of the records in the record list
454
excluding the infimum and supremum records. */
459
/* out: data in bytes */
460
page_t* page); /* in: index page */
461
/****************************************************************
462
Allocates a block of memory from an index page. */
467
/* out: pointer to start of allocated
468
buffer, or NULL if allocation fails */
469
page_t* page, /* in: index page */
470
ulint need, /* in: number of bytes needed */
471
ulint* heap_no);/* out: this contains the heap number
472
of the allocated record if allocation succeeds */
473
/****************************************************************
474
Puts a record to free list. */
479
page_t* page, /* in: index page */
480
rec_t* rec); /* in: pointer to the (origin of) record */
481
/**************************************************************
482
The index page creation function. */
487
/* out: pointer to the page */
488
buf_frame_t* frame, /* in: a buffer frame where the page is
490
mtr_t* mtr); /* in: mini-transaction handle */
491
/*****************************************************************
492
Differs from page_copy_rec_list_end, because this function does not
493
touch the lock table and max trx id on page. */
496
page_copy_rec_list_end_no_locks(
497
/*============================*/
498
page_t* new_page, /* in: index page to copy to */
499
page_t* page, /* in: index page */
500
rec_t* rec, /* in: record on page */
501
mtr_t* mtr); /* in: mtr */
502
/*****************************************************************
503
Copies records from page to new_page, from the given record onward,
504
including that record. Infimum and supremum records are not copied.
505
The records are copied to the start of the record list on new_page. */
508
page_copy_rec_list_end(
509
/*===================*/
510
page_t* new_page, /* in: index page to copy to */
511
page_t* page, /* in: index page */
512
rec_t* rec, /* in: record on page */
513
mtr_t* mtr); /* in: mtr */
514
/*****************************************************************
515
Copies records from page to new_page, up to the given record, NOT
516
including that record. Infimum and supremum records are not copied.
517
The records are copied to the end of the record list on new_page. */
520
page_copy_rec_list_start(
521
/*=====================*/
522
page_t* new_page, /* in: index page to copy to */
523
page_t* page, /* in: index page */
524
rec_t* rec, /* in: record on page */
525
mtr_t* mtr); /* in: mtr */
526
/*****************************************************************
527
Deletes records from a page from a given record onward, including that record.
528
The infimum and supremum records are not deleted. */
531
page_delete_rec_list_end(
532
/*=====================*/
533
page_t* page, /* in: index page */
534
rec_t* rec, /* in: record on page */
535
ulint n_recs, /* in: number of records to delete, or ULINT_UNDEFINED
537
ulint size, /* in: the sum of the sizes of the records in the end
538
of the chain to delete, or ULINT_UNDEFINED if not
540
mtr_t* mtr); /* in: mtr */
541
/*****************************************************************
542
Deletes records from page, up to the given record, NOT including
543
that record. Infimum and supremum records are not deleted. */
546
page_delete_rec_list_start(
547
/*=======================*/
548
page_t* page, /* in: index page */
549
rec_t* rec, /* in: record on page */
550
mtr_t* mtr); /* in: mtr */
551
/*****************************************************************
552
Moves record list end to another page. Moved records include
556
page_move_rec_list_end(
557
/*===================*/
558
page_t* new_page, /* in: index page where to move */
559
page_t* page, /* in: index page */
560
rec_t* split_rec, /* in: first record to move */
561
mtr_t* mtr); /* in: mtr */
562
/*****************************************************************
563
Moves record list start to another page. Moved records do not include
567
page_move_rec_list_start(
568
/*=====================*/
569
page_t* new_page, /* in: index page where to move */
570
page_t* page, /* in: index page */
571
rec_t* split_rec, /* in: first record not to move */
572
mtr_t* mtr); /* in: mtr */
573
/********************************************************************
574
Splits a directory slot which owns too many records. */
579
page_t* page, /* in: the index page in question */
580
ulint slot_no); /* in: the directory slot */
581
/*****************************************************************
582
Tries to balance the given directory slot with too few records
583
with the upper neighbor, so that there are at least the minimum number
584
of records owned by the slot; this may result in the merging of
588
page_dir_balance_slot(
589
/*==================*/
590
page_t* page, /* in: index page */
591
ulint slot_no); /* in: the directory slot */
592
/**************************************************************
593
Parses a log record of a record list end or start deletion. */
596
page_parse_delete_rec_list(
597
/*=======================*/
598
/* out: end of log record or NULL */
599
byte type, /* in: MLOG_LIST_END_DELETE or MLOG_LIST_START_DELETE */
600
byte* ptr, /* in: buffer */
601
byte* end_ptr,/* in: buffer end */
602
page_t* page, /* in: page or NULL */
603
mtr_t* mtr); /* in: mtr or NULL */
604
/***************************************************************
605
Parses a redo log record of creating a page. */
610
/* out: end of log record or NULL */
611
byte* ptr, /* in: buffer */
612
byte* end_ptr,/* in: buffer end */
613
page_t* page, /* in: page or NULL */
614
mtr_t* mtr); /* in: mtr or NULL */
615
/****************************************************************
616
Prints record contents including the data relevant only in
617
the index page context. */
623
/*******************************************************************
624
This is used to print the contents of the directory for
625
debugging purposes. */
630
page_t* page, /* in: index page */
631
ulint pr_n); /* in: print n first and n last entries */
632
/*******************************************************************
633
This is used to print the contents of the page record list for
634
debugging purposes. */
639
page_t* page, /* in: index page */
640
ulint pr_n); /* in: print n first and n last entries */
641
/*******************************************************************
642
Prints the info in a page header. */
648
/*******************************************************************
649
This is used to print the contents of the page for
650
debugging purposes. */
655
page_t* page, /* in: index page */
656
ulint dn, /* in: print dn first and last entries in directory */
657
ulint rn); /* in: print rn first and last records on page */
658
/*******************************************************************
659
The following is used to validate a record on a page. This function
660
differs from rec_validate as it can also check the n_owned field and
661
the heap_no field. */
666
/* out: TRUE if ok */
667
rec_t* rec); /* in: record on the page */
668
/*******************************************************************
669
This function checks the consistency of an index page. */
674
/* out: TRUE if ok */
675
page_t* page, /* in: index page */
676
dict_index_t* index); /* in: data dictionary index containing
677
the page record type definition */
678
/*******************************************************************
679
Looks in the page record list for a record with the given heap number. */
682
page_find_rec_with_heap_no(
683
/*=======================*/
684
/* out: record, NULL if not found */
685
page_t* page, /* in: index page */
686
ulint heap_no);/* in: heap number */
688
#ifdef UNIV_MATERIALIZE
690
#define UNIV_INLINE UNIV_INLINE_ORIGINAL
694
#include "page0page.ic"