~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/innobase/include/page0page.ic

  • Committer: Padraig O'Sullivan
  • Date: 2009-03-30 18:27:35 UTC
  • mto: (968.2.5 mordred)
  • mto: This revision was merged to the branch mainline in revision 971.
  • Revision ID: osullivan.padraig@gmail.com-20090330182735-8tor89czwodcv77s
Removing the last of LIST from the MyISAM storage engine.

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
12
 
13
13
You should have received a copy of the GNU General Public License along with
14
 
this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
15
 
St, Fifth Floor, Boston, MA 02110-1301 USA
 
14
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 
15
Place, Suite 330, Boston, MA 02111-1307 USA
16
16
 
17
17
*****************************************************************************/
18
18
 
19
 
/**************************************************//**
20
 
@file include/page0page.ic
 
19
/******************************************************
21
20
Index page routines
22
21
 
23
22
Created 2/2/1994 Heikki Tuuri
24
23
*******************************************************/
25
24
 
26
25
#include "mach0data.h"
27
 
#ifdef UNIV_DEBUG
28
 
# include "log0recv.h"
29
 
#endif /* !UNIV_DEBUG */
30
 
#ifndef UNIV_HOTBACKUP
31
 
# include "rem0cmp.h"
32
 
#endif /* !UNIV_HOTBACKUP */
 
26
#include "rem0cmp.h"
33
27
#include "mtr0log.h"
34
28
#include "page0zip.h"
35
29
 
38
32
#define UNIV_INLINE
39
33
#endif
40
34
 
41
 
/************************************************************//**
42
 
Gets the start of a page.
43
 
@return start of the page */
 
35
/****************************************************************
 
36
Gets the start of a page. */
44
37
UNIV_INLINE
45
38
page_t*
46
39
page_align(
47
40
/*=======*/
48
 
        const void*     ptr)    /*!< in: pointer to page frame */
 
41
                                /* out: start of the page */
 
42
        const void*     ptr)    /* in: pointer to page frame */
49
43
{
50
44
        return((page_t*) ut_align_down(ptr, UNIV_PAGE_SIZE));
51
45
}
52
 
/************************************************************//**
53
 
Gets the offset within a page.
54
 
@return offset from the start of the page */
 
46
/****************************************************************
 
47
Gets the offset within a page. */
55
48
UNIV_INLINE
56
49
ulint
57
50
page_offset(
58
51
/*========*/
59
 
        const void*     ptr)    /*!< in: pointer to page frame */
 
52
                                /* out: offset from the start of the page */
 
53
        const void*     ptr)    /* in: pointer to page frame */
60
54
{
61
55
        return(ut_align_offset(ptr, UNIV_PAGE_SIZE));
62
56
}
63
 
/*************************************************************//**
 
57
/*****************************************************************
64
58
Returns the max trx id field value. */
65
59
UNIV_INLINE
66
 
trx_id_t
 
60
dulint
67
61
page_get_max_trx_id(
68
62
/*================*/
69
 
        const page_t*   page)   /*!< in: page */
 
63
        const page_t*   page)   /* in: page */
70
64
{
71
65
        ut_ad(page);
72
66
 
73
67
        return(mach_read_from_8(page + PAGE_HEADER + PAGE_MAX_TRX_ID));
74
68
}
75
69
 
76
 
/*************************************************************//**
 
70
/*****************************************************************
77
71
Sets the max trx id field value if trx_id is bigger than the previous
78
72
value. */
79
73
UNIV_INLINE
80
74
void
81
75
page_update_max_trx_id(
82
76
/*===================*/
83
 
        buf_block_t*    block,  /*!< in/out: page */
84
 
        page_zip_des_t* page_zip,/*!< in/out: compressed page whose
 
77
        buf_block_t*    block,  /* in/out: page */
 
78
        page_zip_des_t* page_zip,/* in/out: compressed page whose
85
79
                                uncompressed part will be updated, or NULL */
86
 
        trx_id_t        trx_id, /*!< in: transaction id */
87
 
        mtr_t*          mtr)    /*!< in/out: mini-transaction */
 
80
        dulint          trx_id) /* in: transaction id */
88
81
{
89
82
        ut_ad(block);
90
 
        ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
91
 
        /* During crash recovery, this function may be called on
92
 
        something else than a leaf page of a secondary index or the
93
 
        insert buffer index tree (dict_index_is_sec_or_ibuf() returns
94
 
        TRUE for the dummy indexes constructed during redo log
95
 
        application).  In that case, PAGE_MAX_TRX_ID is unused,
96
 
        and trx_id is usually zero. */
97
 
        ut_ad(trx_id || recv_recovery_is_on());
98
 
        ut_ad(page_is_leaf(buf_block_get_frame(block)));
99
 
 
100
 
        if (page_get_max_trx_id(buf_block_get_frame(block)) < trx_id) {
101
 
 
102
 
                page_set_max_trx_id(block, page_zip, trx_id, mtr);
 
83
 
 
84
        if (ut_dulint_cmp(page_get_max_trx_id(buf_block_get_frame(block)),
 
85
                          trx_id) < 0) {
 
86
 
 
87
                page_set_max_trx_id(block, page_zip, trx_id);
103
88
        }
104
89
}
105
90
 
106
 
/*************************************************************//**
 
91
/*****************************************************************
107
92
Reads the given header field. */
108
93
UNIV_INLINE
109
94
ulint
110
95
page_header_get_field(
111
96
/*==================*/
112
 
        const page_t*   page,   /*!< in: page */
113
 
        ulint           field)  /*!< in: PAGE_LEVEL, ... */
 
97
        const page_t*   page,   /* in: page */
 
98
        ulint           field)  /* in: PAGE_LEVEL, ... */
114
99
{
115
100
        ut_ad(page);
116
101
        ut_ad(field <= PAGE_INDEX_ID);
118
103
        return(mach_read_from_2(page + PAGE_HEADER + field));
119
104
}
120
105
 
121
 
/*************************************************************//**
 
106
/*****************************************************************
122
107
Sets the given header field. */
123
108
UNIV_INLINE
124
109
void
125
110
page_header_set_field(
126
111
/*==================*/
127
 
        page_t*         page,   /*!< in/out: page */
128
 
        page_zip_des_t* page_zip,/*!< in/out: compressed page whose
 
112
        page_t*         page,   /* in/out: page */
 
113
        page_zip_des_t* page_zip,/* in/out: compressed page whose
129
114
                                uncompressed part will be updated, or NULL */
130
 
        ulint           field,  /*!< in: PAGE_N_DIR_SLOTS, ... */
131
 
        ulint           val)    /*!< in: value */
 
115
        ulint           field,  /* in: PAGE_N_DIR_SLOTS, ... */
 
116
        ulint           val)    /* in: value */
132
117
{
133
118
        ut_ad(page);
134
119
        ut_ad(field <= PAGE_N_RECS);
142
127
        }
143
128
}
144
129
 
145
 
/*************************************************************//**
146
 
Returns the offset stored in the given header field.
147
 
@return offset from the start of the page, or 0 */
 
130
/*****************************************************************
 
131
Returns the offset stored in the given header field. */
148
132
UNIV_INLINE
149
133
ulint
150
134
page_header_get_offs(
151
135
/*=================*/
152
 
        const page_t*   page,   /*!< in: page */
153
 
        ulint           field)  /*!< in: PAGE_FREE, ... */
 
136
                                /* out: offset from the start of the page,
 
137
                                or 0 */
 
138
        const page_t*   page,   /* in: page */
 
139
        ulint           field)  /* in: PAGE_FREE, ... */
154
140
{
155
141
        ulint   offs;
156
142
 
166
152
        return(offs);
167
153
}
168
154
 
169
 
/*************************************************************//**
 
155
/*****************************************************************
170
156
Sets the pointer stored in the given header field. */
171
157
UNIV_INLINE
172
158
void
173
159
page_header_set_ptr(
174
160
/*================*/
175
 
        page_t*         page,   /*!< in: page */
176
 
        page_zip_des_t* page_zip,/*!< in/out: compressed page whose
 
161
        page_t*         page,   /* in: page */
 
162
        page_zip_des_t* page_zip,/* in/out: compressed page whose
177
163
                                uncompressed part will be updated, or NULL */
178
 
        ulint           field,  /*!< in: PAGE_FREE, ... */
179
 
        const byte*     ptr)    /*!< in: pointer or NULL*/
 
164
        ulint           field,  /* in: PAGE_FREE, ... */
 
165
        const byte*     ptr)    /* in: pointer or NULL*/
180
166
{
181
167
        ulint   offs;
182
168
 
196
182
        page_header_set_field(page, page_zip, field, offs);
197
183
}
198
184
 
199
 
#ifndef UNIV_HOTBACKUP
200
 
/*************************************************************//**
 
185
/*****************************************************************
201
186
Resets the last insert info field in the page header. Writes to mlog
202
187
about this operation. */
203
188
UNIV_INLINE
204
189
void
205
190
page_header_reset_last_insert(
206
191
/*==========================*/
207
 
        page_t*         page,   /*!< in/out: page */
208
 
        page_zip_des_t* page_zip,/*!< in/out: compressed page whose
 
192
        page_t*         page,   /* in/out: page */
 
193
        page_zip_des_t* page_zip,/* in/out: compressed page whose
209
194
                                uncompressed part will be updated, or NULL */
210
 
        mtr_t*          mtr)    /*!< in: mtr */
 
195
        mtr_t*          mtr)    /* in: mtr */
211
196
{
212
197
        ut_ad(page && mtr);
213
198
 
221
206
                                 MLOG_2BYTES, mtr);
222
207
        }
223
208
}
224
 
#endif /* !UNIV_HOTBACKUP */
225
209
 
226
 
/************************************************************//**
227
 
Determine whether the page is in new-style compact format.
228
 
@return nonzero if the page is in compact format, zero if it is in
229
 
old-style format */
 
210
/****************************************************************
 
211
Determine whether the page is in new-style compact format. */
230
212
UNIV_INLINE
231
213
ulint
232
214
page_is_comp(
233
215
/*=========*/
234
 
        const page_t*   page)   /*!< in: index page */
 
216
                                /* out: nonzero if the page is in compact
 
217
                                format, zero if it is in old-style format */
 
218
        const page_t*   page)   /* in: index page */
235
219
{
236
220
        return(UNIV_EXPECT(page_header_get_field(page, PAGE_N_HEAP) & 0x8000,
237
221
                           0x8000));
238
222
}
239
223
 
240
 
/************************************************************//**
241
 
TRUE if the record is on a page in compact format.
242
 
@return nonzero if in compact format */
 
224
/****************************************************************
 
225
TRUE if the record is on a page in compact format. */
243
226
UNIV_INLINE
244
227
ulint
245
228
page_rec_is_comp(
246
229
/*=============*/
247
 
        const rec_t*    rec)    /*!< in: record */
 
230
                                /* out: nonzero if in compact format */
 
231
        const rec_t*    rec)    /* in: record */
248
232
{
249
233
        return(page_is_comp(page_align(rec)));
250
234
}
251
235
 
252
 
/***************************************************************//**
253
 
Returns the heap number of a record.
254
 
@return heap number */
 
236
/*******************************************************************
 
237
Returns the heap number of a record. */
255
238
UNIV_INLINE
256
239
ulint
257
240
page_rec_get_heap_no(
258
241
/*=================*/
259
 
        const rec_t*    rec)    /*!< in: the physical record */
 
242
                                /* out: heap number */
 
243
        const rec_t*    rec)    /* in: the physical record */
260
244
{
261
245
        if (page_rec_is_comp(rec)) {
262
246
                return(rec_get_heap_no_new(rec));
265
249
        }
266
250
}
267
251
 
268
 
/************************************************************//**
269
 
Determine whether the page is a B-tree leaf.
270
 
@return TRUE if the page is a B-tree leaf */
 
252
/****************************************************************
 
253
Determine whether the page is a B-tree leaf. */
271
254
UNIV_INLINE
272
255
ibool
273
256
page_is_leaf(
274
257
/*=========*/
275
 
        const page_t*   page)   /*!< in: page */
 
258
                                /* out: TRUE if the page is a B-tree leaf */
 
259
        const page_t*   page)   /* in: page */
276
260
{
277
261
        return(!*(const uint16*) (page + (PAGE_HEADER + PAGE_LEVEL)));
278
262
}
279
263
 
280
 
/************************************************************//**
281
 
Gets the offset of the first record on the page.
282
 
@return offset of the first record in record list, relative from page */
 
264
/****************************************************************
 
265
Gets the offset of the first record on the page. */
283
266
UNIV_INLINE
284
267
ulint
285
268
page_get_infimum_offset(
286
269
/*====================*/
287
 
        const page_t*   page)   /*!< in: page which must have record(s) */
 
270
                                /* out: offset of the first record
 
271
                                in record list, relative from page */
 
272
        const page_t*   page)   /* in: page which must have record(s) */
288
273
{
289
274
        ut_ad(page);
290
275
        ut_ad(!page_offset(page));
296
281
        }
297
282
}
298
283
 
299
 
/************************************************************//**
300
 
Gets the offset of the last record on the page.
301
 
@return offset of the last record in record list, relative from page */
 
284
/****************************************************************
 
285
Gets the offset of the last record on the page. */
302
286
UNIV_INLINE
303
287
ulint
304
288
page_get_supremum_offset(
305
289
/*=====================*/
306
 
        const page_t*   page)   /*!< in: page which must have record(s) */
 
290
                                /* out: offset of the last record in
 
291
                                record list, relative from page */
 
292
        const page_t*   page)   /* in: page which must have record(s) */
307
293
{
308
294
        ut_ad(page);
309
295
        ut_ad(!page_offset(page));
315
301
        }
316
302
}
317
303
 
318
 
/************************************************************//**
319
 
TRUE if the record is a user record on the page.
320
 
@return TRUE if a user record */
 
304
/****************************************************************
 
305
TRUE if the record is a user record on the page. */
321
306
UNIV_INLINE
322
307
ibool
323
308
page_rec_is_user_rec_low(
324
309
/*=====================*/
325
 
        ulint   offset) /*!< in: record offset on page */
 
310
                        /* out: TRUE if a user record */
 
311
        ulint   offset) /* in: record offset on page */
326
312
{
327
313
        ut_ad(offset >= PAGE_NEW_INFIMUM);
328
314
#if PAGE_OLD_INFIMUM < PAGE_NEW_INFIMUM
351
337
               && UNIV_LIKELY(offset != PAGE_OLD_SUPREMUM));
352
338
}
353
339
 
354
 
/************************************************************//**
355
 
TRUE if the record is the supremum record on a page.
356
 
@return TRUE if the supremum record */
 
340
/****************************************************************
 
341
TRUE if the record is the supremum record on a page. */
357
342
UNIV_INLINE
358
343
ibool
359
344
page_rec_is_supremum_low(
360
345
/*=====================*/
361
 
        ulint   offset) /*!< in: record offset on page */
 
346
                        /* out: TRUE if the supremum record */
 
347
        ulint   offset) /* in: record offset on page */
362
348
{
363
349
        ut_ad(offset >= PAGE_NEW_INFIMUM);
364
350
        ut_ad(offset <= UNIV_PAGE_SIZE - PAGE_EMPTY_DIR_START);
367
353
               || UNIV_UNLIKELY(offset == PAGE_OLD_SUPREMUM));
368
354
}
369
355
 
370
 
/************************************************************//**
371
 
TRUE if the record is the infimum record on a page.
372
 
@return TRUE if the infimum record */
 
356
/****************************************************************
 
357
TRUE if the record is the infimum record on a page. */
373
358
UNIV_INLINE
374
359
ibool
375
360
page_rec_is_infimum_low(
376
361
/*====================*/
377
 
        ulint   offset) /*!< in: record offset on page */
 
362
                        /* out: TRUE if the infimum record */
 
363
        ulint   offset) /* in: record offset on page */
378
364
{
379
365
        ut_ad(offset >= PAGE_NEW_INFIMUM);
380
366
        ut_ad(offset <= UNIV_PAGE_SIZE - PAGE_EMPTY_DIR_START);
383
369
               || UNIV_UNLIKELY(offset == PAGE_OLD_INFIMUM));
384
370
}
385
371
 
386
 
/************************************************************//**
387
 
TRUE if the record is a user record on the page.
388
 
@return TRUE if a user record */
 
372
/****************************************************************
 
373
TRUE if the record is a user record on the page. */
389
374
UNIV_INLINE
390
375
ibool
391
376
page_rec_is_user_rec(
392
377
/*=================*/
393
 
        const rec_t*    rec)    /*!< in: record */
 
378
                                /* out: TRUE if a user record */
 
379
        const rec_t*    rec)    /* in: record */
394
380
{
395
381
        return(page_rec_is_user_rec_low(page_offset(rec)));
396
382
}
397
383
 
398
 
/************************************************************//**
399
 
TRUE if the record is the supremum record on a page.
400
 
@return TRUE if the supremum record */
 
384
/****************************************************************
 
385
TRUE if the record is the supremum record on a page. */
401
386
UNIV_INLINE
402
387
ibool
403
388
page_rec_is_supremum(
404
389
/*=================*/
405
 
        const rec_t*    rec)    /*!< in: record */
 
390
                                /* out: TRUE if the supremum record */
 
391
        const rec_t*    rec)    /* in: record */
406
392
{
407
393
        return(page_rec_is_supremum_low(page_offset(rec)));
408
394
}
409
395
 
410
 
/************************************************************//**
411
 
TRUE if the record is the infimum record on a page.
412
 
@return TRUE if the infimum record */
 
396
/****************************************************************
 
397
TRUE if the record is the infimum record on a page. */
413
398
UNIV_INLINE
414
399
ibool
415
400
page_rec_is_infimum(
416
401
/*================*/
417
 
        const rec_t*    rec)    /*!< in: record */
 
402
                                /* out: TRUE if the infimum record */
 
403
        const rec_t*    rec)    /* in: record */
418
404
{
419
405
        return(page_rec_is_infimum_low(page_offset(rec)));
420
406
}
421
407
 
422
 
#ifndef UNIV_HOTBACKUP
423
 
/*************************************************************//**
 
408
/*****************************************************************
424
409
Compares a data tuple to a physical record. Differs from the function
425
410
cmp_dtuple_rec_with_match in the way that the record must reside on an
426
411
index page, and also page infimum and supremum records can be given in
427
412
the parameter rec. These are considered as the negative infinity and
428
 
the positive infinity in the alphabetical order.
429
 
@return 1, 0, -1, if dtuple is greater, equal, less than rec,
430
 
respectively, when only the common first fields are compared */
 
413
the positive infinity in the alphabetical order. */
431
414
UNIV_INLINE
432
415
int
433
416
page_cmp_dtuple_rec_with_match(
434
417
/*===========================*/
435
 
        const dtuple_t* dtuple, /*!< in: data tuple */
436
 
        const rec_t*    rec,    /*!< in: physical record on a page; may also
 
418
                                /* out: 1, 0, -1, if dtuple is greater, equal,
 
419
                                less than rec, respectively, when only the
 
420
                                common first fields are compared */
 
421
        const dtuple_t* dtuple, /* in: data tuple */
 
422
        const rec_t*    rec,    /* in: physical record on a page; may also
437
423
                                be page infimum or supremum, in which case
438
424
                                matched-parameter values below are not
439
425
                                affected */
440
 
        const ulint*    offsets,/*!< in: array returned by rec_get_offsets() */
441
 
        ulint*          matched_fields, /*!< in/out: number of already completely
 
426
        const ulint*    offsets,/* in: array returned by rec_get_offsets() */
 
427
        ulint*          matched_fields, /* in/out: number of already completely
442
428
                                matched fields; when function returns
443
429
                                contains the value for current comparison */
444
 
        ulint*          matched_bytes) /*!< in/out: number of already matched
 
430
        ulint*          matched_bytes) /* in/out: number of already matched
445
431
                                bytes within the first field not completely
446
432
                                matched; when function returns contains the
447
433
                                value for current comparison */
467
453
                                         matched_fields,
468
454
                                         matched_bytes));
469
455
}
470
 
#endif /* !UNIV_HOTBACKUP */
471
456
 
472
 
/*************************************************************//**
473
 
Gets the page number.
474
 
@return page number */
 
457
/*****************************************************************
 
458
Gets the page number. */
475
459
UNIV_INLINE
476
460
ulint
477
461
page_get_page_no(
478
462
/*=============*/
479
 
        const page_t*   page)   /*!< in: page */
 
463
                                /* out: page number */
 
464
        const page_t*   page)   /* in: page */
480
465
{
481
466
        ut_ad(page == page_align((page_t*) page));
482
467
        return(mach_read_from_4(page + FIL_PAGE_OFFSET));
483
468
}
484
469
 
485
 
/*************************************************************//**
486
 
Gets the tablespace identifier.
487
 
@return space id */
 
470
/*****************************************************************
 
471
Gets the tablespace identifier. */
488
472
UNIV_INLINE
489
473
ulint
490
474
page_get_space_id(
491
475
/*==============*/
492
 
        const page_t*   page)   /*!< in: page */
 
476
                                /* out: space id */
 
477
        const page_t*   page)   /* in: page */
493
478
{
494
479
        ut_ad(page == page_align((page_t*) page));
495
480
        return(mach_read_from_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID));
496
481
}
497
482
 
498
 
/*************************************************************//**
 
483
/*****************************************************************
499
484
Gets the number of user records on page (infimum and supremum records
500
 
are not user records).
501
 
@return number of user records */
 
485
are not user records). */
502
486
UNIV_INLINE
503
487
ulint
504
488
page_get_n_recs(
505
489
/*============*/
506
 
        const page_t*   page)   /*!< in: index page */
 
490
                                /* out: number of user records */
 
491
        const page_t*   page)   /* in: index page */
507
492
{
508
493
        return(page_header_get_field(page, PAGE_N_RECS));
509
494
}
510
495
 
511
 
/*************************************************************//**
512
 
Gets the number of dir slots in directory.
513
 
@return number of slots */
 
496
/*****************************************************************
 
497
Gets the number of dir slots in directory. */
514
498
UNIV_INLINE
515
499
ulint
516
500
page_dir_get_n_slots(
517
501
/*=================*/
518
 
        const page_t*   page)   /*!< in: index page */
 
502
                                /* out: number of slots */
 
503
        const page_t*   page)   /* in: index page */
519
504
{
520
505
        return(page_header_get_field(page, PAGE_N_DIR_SLOTS));
521
506
}
522
 
/*************************************************************//**
 
507
/*****************************************************************
523
508
Sets the number of dir slots in directory. */
524
509
UNIV_INLINE
525
510
void
526
511
page_dir_set_n_slots(
527
512
/*=================*/
528
 
        page_t*         page,   /*!< in/out: page */
529
 
        page_zip_des_t* page_zip,/*!< in/out: compressed page whose
 
513
        page_t*         page,   /* in/out: page */
 
514
        page_zip_des_t* page_zip,/* in/out: compressed page whose
530
515
                                uncompressed part will be updated, or NULL */
531
 
        ulint           n_slots)/*!< in: number of slots */
 
516
        ulint           n_slots)/* in: number of slots */
532
517
{
533
518
        page_header_set_field(page, page_zip, PAGE_N_DIR_SLOTS, n_slots);
534
519
}
535
520
 
536
 
/*************************************************************//**
537
 
Gets the number of records in the heap.
538
 
@return number of user records */
 
521
/*****************************************************************
 
522
Gets the number of records in the heap. */
539
523
UNIV_INLINE
540
524
ulint
541
525
page_dir_get_n_heap(
542
526
/*================*/
543
 
        const page_t*   page)   /*!< in: index page */
 
527
                                /* out: number of user records */
 
528
        const page_t*   page)   /* in: index page */
544
529
{
545
530
        return(page_header_get_field(page, PAGE_N_HEAP) & 0x7fff);
546
531
}
547
532
 
548
 
/*************************************************************//**
 
533
/*****************************************************************
549
534
Sets the number of records in the heap. */
550
535
UNIV_INLINE
551
536
void
552
537
page_dir_set_n_heap(
553
538
/*================*/
554
 
        page_t*         page,   /*!< in/out: index page */
555
 
        page_zip_des_t* page_zip,/*!< in/out: compressed page whose
 
539
        page_t*         page,   /* in/out: index page */
 
540
        page_zip_des_t* page_zip,/* in/out: compressed page whose
556
541
                                uncompressed part will be updated, or NULL.
557
542
                                Note that the size of the dense page directory
558
543
                                in the compressed page trailer is
559
544
                                n_heap * PAGE_ZIP_DIR_SLOT_SIZE. */
560
 
        ulint           n_heap) /*!< in: number of records */
 
545
        ulint           n_heap) /* in: number of records */
561
546
{
562
547
        ut_ad(n_heap < 0x8000);
563
548
        ut_ad(!page_zip || n_heap
569
554
}
570
555
 
571
556
#ifdef UNIV_DEBUG
572
 
/*************************************************************//**
573
 
Gets pointer to nth directory slot.
574
 
@return pointer to dir slot */
 
557
/*****************************************************************
 
558
Gets pointer to nth directory slot. */
575
559
UNIV_INLINE
576
560
page_dir_slot_t*
577
561
page_dir_get_nth_slot(
578
562
/*==================*/
579
 
        const page_t*   page,   /*!< in: index page */
580
 
        ulint           n)      /*!< in: position */
 
563
                                /* out: pointer to dir slot */
 
564
        const page_t*   page,   /* in: index page */
 
565
        ulint           n)      /* in: position */
581
566
{
582
567
        ut_ad(page_dir_get_n_slots(page) > n);
583
568
 
587
572
}
588
573
#endif /* UNIV_DEBUG */
589
574
 
590
 
/**************************************************************//**
591
 
Used to check the consistency of a record on a page.
592
 
@return TRUE if succeed */
 
575
/******************************************************************
 
576
Used to check the consistency of a record on a page. */
593
577
UNIV_INLINE
594
578
ibool
595
579
page_rec_check(
596
580
/*===========*/
597
 
        const rec_t*    rec)    /*!< in: record */
 
581
                                /* out: TRUE if succeed */
 
582
        const rec_t*    rec)    /* in: record */
598
583
{
599
584
        const page_t*   page = page_align(rec);
600
585
 
606
591
        return(TRUE);
607
592
}
608
593
 
609
 
/***************************************************************//**
610
 
Gets the record pointed to by a directory slot.
611
 
@return pointer to record */
 
594
/*******************************************************************
 
595
Gets the record pointed to by a directory slot. */
612
596
UNIV_INLINE
613
597
const rec_t*
614
598
page_dir_slot_get_rec(
615
599
/*==================*/
616
 
        const page_dir_slot_t*  slot)   /*!< in: directory slot */
 
600
                                        /* out: pointer to record */
 
601
        const page_dir_slot_t*  slot)   /* in: directory slot */
617
602
{
618
603
        return(page_align(slot) + mach_read_from_2(slot));
619
604
}
620
605
 
621
 
/***************************************************************//**
 
606
/*******************************************************************
622
607
This is used to set the record offset in a directory slot. */
623
608
UNIV_INLINE
624
609
void
625
610
page_dir_slot_set_rec(
626
611
/*==================*/
627
 
        page_dir_slot_t* slot,  /*!< in: directory slot */
628
 
        rec_t*           rec)   /*!< in: record on the page */
 
612
        page_dir_slot_t* slot,  /* in: directory slot */
 
613
        rec_t*           rec)   /* in: record on the page */
629
614
{
630
615
        ut_ad(page_rec_check(rec));
631
616
 
632
617
        mach_write_to_2(slot, page_offset(rec));
633
618
}
634
619
 
635
 
/***************************************************************//**
636
 
Gets the number of records owned by a directory slot.
637
 
@return number of records */
 
620
/*******************************************************************
 
621
Gets the number of records owned by a directory slot. */
638
622
UNIV_INLINE
639
623
ulint
640
624
page_dir_slot_get_n_owned(
641
625
/*======================*/
642
 
        const page_dir_slot_t*  slot)   /*!< in: page directory slot */
 
626
                                        /* out: number of records */
 
627
        const page_dir_slot_t*  slot)   /* in: page directory slot */
643
628
{
644
629
        const rec_t*    rec     = page_dir_slot_get_rec(slot);
645
630
        if (page_rec_is_comp(slot)) {
649
634
        }
650
635
}
651
636
 
652
 
/***************************************************************//**
 
637
/*******************************************************************
653
638
This is used to set the owned records field of a directory slot. */
654
639
UNIV_INLINE
655
640
void
656
641
page_dir_slot_set_n_owned(
657
642
/*======================*/
658
 
        page_dir_slot_t*slot,   /*!< in/out: directory slot */
659
 
        page_zip_des_t* page_zip,/*!< in/out: compressed page, or NULL */
660
 
        ulint           n)      /*!< in: number of records owned by the slot */
 
643
        page_dir_slot_t*slot,   /* in/out: directory slot */
 
644
        page_zip_des_t* page_zip,/* in/out: compressed page, or NULL */
 
645
        ulint           n)      /* in: number of records owned by the slot */
661
646
{
662
647
        rec_t*  rec     = (rec_t*) page_dir_slot_get_rec(slot);
663
648
        if (page_rec_is_comp(slot)) {
668
653
        }
669
654
}
670
655
 
671
 
/************************************************************//**
 
656
/****************************************************************
672
657
Calculates the space reserved for directory slots of a given number of
673
658
records. The exact value is a fraction number n * PAGE_DIR_SLOT_SIZE /
674
659
PAGE_DIR_SLOT_MIN_N_OWNED, and it is rounded upwards to an integer. */
676
661
ulint
677
662
page_dir_calc_reserved_space(
678
663
/*=========================*/
679
 
        ulint   n_recs)         /*!< in: number of records */
 
664
        ulint   n_recs)         /* in: number of records */
680
665
{
681
666
        return((PAGE_DIR_SLOT_SIZE * n_recs + PAGE_DIR_SLOT_MIN_N_OWNED - 1)
682
667
               / PAGE_DIR_SLOT_MIN_N_OWNED);
683
668
}
684
669
 
685
 
/************************************************************//**
686
 
Gets the pointer to the next record on the page.
687
 
@return pointer to next record */
 
670
/****************************************************************
 
671
Gets the pointer to the next record on the page. */
688
672
UNIV_INLINE
689
673
const rec_t*
690
674
page_rec_get_next_low(
691
675
/*==================*/
692
 
        const rec_t*    rec,    /*!< in: pointer to record */
693
 
        ulint           comp)   /*!< in: nonzero=compact page layout */
 
676
                                /* out: pointer to next record */
 
677
        const rec_t*    rec,    /* in: pointer to record */
 
678
        ulint           comp)   /* in: nonzero=compact page layout */
694
679
{
695
680
        ulint           offs;
696
681
        const page_t*   page;
723
708
        return(page + offs);
724
709
}
725
710
 
726
 
/************************************************************//**
727
 
Gets the pointer to the next record on the page.
728
 
@return pointer to next record */
 
711
/****************************************************************
 
712
Gets the pointer to the next record on the page. */
729
713
UNIV_INLINE
730
714
rec_t*
731
715
page_rec_get_next(
732
716
/*==============*/
733
 
        rec_t*  rec)    /*!< in: pointer to record */
 
717
                        /* out: pointer to next record */
 
718
        rec_t*  rec)    /* in: pointer to record */
734
719
{
735
720
        return((rec_t*) page_rec_get_next_low(rec, page_rec_is_comp(rec)));
736
721
}
737
722
 
738
 
/************************************************************//**
739
 
Gets the pointer to the next record on the page.
740
 
@return pointer to next record */
 
723
/****************************************************************
 
724
Gets the pointer to the next record on the page. */
741
725
UNIV_INLINE
742
726
const rec_t*
743
727
page_rec_get_next_const(
744
728
/*====================*/
745
 
        const rec_t*    rec)    /*!< in: pointer to record */
 
729
                                /* out: pointer to next record */
 
730
        const rec_t*    rec)    /* in: pointer to record */
746
731
{
747
732
        return(page_rec_get_next_low(rec, page_rec_is_comp(rec)));
748
733
}
749
734
 
750
 
/************************************************************//**
 
735
/****************************************************************
751
736
Sets the pointer to the next record on the page. */
752
737
UNIV_INLINE
753
738
void
754
739
page_rec_set_next(
755
740
/*==============*/
756
 
        rec_t*  rec,            /*!< in: pointer to record,
 
741
        rec_t*  rec,            /* in: pointer to record,
757
742
                                must not be page supremum */
758
 
        rec_t*  next)           /*!< in: pointer to next record,
 
743
        rec_t*  next)           /* in: pointer to next record,
759
744
                                must not be page infimum */
760
745
{
761
746
        ulint   offs;
780
765
        }
781
766
}
782
767
 
783
 
/************************************************************//**
784
 
Gets the pointer to the previous record.
785
 
@return pointer to previous record */
 
768
/****************************************************************
 
769
Gets the pointer to the previous record. */
786
770
UNIV_INLINE
787
771
const rec_t*
788
772
page_rec_get_prev_const(
789
773
/*====================*/
790
 
        const rec_t*    rec)    /*!< in: pointer to record, must not be page
 
774
                                /* out: pointer to previous record */
 
775
        const rec_t*    rec)    /* in: pointer to record, must not be page
791
776
                                infimum */
792
777
{
793
778
        const page_dir_slot_t*  slot;
827
812
        return(prev_rec);
828
813
}
829
814
 
830
 
/************************************************************//**
831
 
Gets the pointer to the previous record.
832
 
@return pointer to previous record */
 
815
/****************************************************************
 
816
Gets the pointer to the previous record. */
833
817
UNIV_INLINE
834
818
rec_t*
835
819
page_rec_get_prev(
836
820
/*==============*/
837
 
        rec_t*  rec)    /*!< in: pointer to record, must not be page
 
821
                        /* out: pointer to previous record */
 
822
        rec_t*  rec)    /* in: pointer to record, must not be page
838
823
                        infimum */
839
824
{
840
825
        return((rec_t*) page_rec_get_prev_const(rec));
841
826
}
842
827
 
843
 
/***************************************************************//**
844
 
Looks for the record which owns the given record.
845
 
@return the owner record */
 
828
/*******************************************************************
 
829
Looks for the record which owns the given record. */
846
830
UNIV_INLINE
847
831
rec_t*
848
832
page_rec_find_owner_rec(
849
833
/*====================*/
850
 
        rec_t*  rec)    /*!< in: the physical record */
 
834
                        /* out: the owner record */
 
835
        rec_t*  rec)    /* in: the physical record */
851
836
{
852
837
        ut_ad(page_rec_check(rec));
853
838
 
864
849
        return(rec);
865
850
}
866
851
 
867
 
/**********************************************************//**
 
852
/**************************************************************
868
853
Returns the base extra size of a physical record.  This is the
869
 
size of the fixed header, independent of the record size.
870
 
@return REC_N_NEW_EXTRA_BYTES or REC_N_OLD_EXTRA_BYTES */
 
854
size of the fixed header, independent of the record size. */
871
855
UNIV_INLINE
872
856
ulint
873
857
page_rec_get_base_extra_size(
874
858
/*=========================*/
875
 
        const rec_t*    rec)    /*!< in: physical record */
 
859
                                /* out: REC_N_NEW_EXTRA_BYTES
 
860
                                or REC_N_OLD_EXTRA_BYTES */
 
861
        const rec_t*    rec)    /* in: physical record */
876
862
{
877
863
#if REC_N_NEW_EXTRA_BYTES + 1 != REC_N_OLD_EXTRA_BYTES
878
864
# error "REC_N_NEW_EXTRA_BYTES + 1 != REC_N_OLD_EXTRA_BYTES"
880
866
        return(REC_N_NEW_EXTRA_BYTES + (ulint) !page_rec_is_comp(rec));
881
867
}
882
868
 
883
 
/************************************************************//**
 
869
/****************************************************************
884
870
Returns the sum of the sizes of the records in the record list, excluding
885
 
the infimum and supremum records.
886
 
@return data in bytes */
 
871
the infimum and supremum records. */
887
872
UNIV_INLINE
888
873
ulint
889
874
page_get_data_size(
890
875
/*===============*/
891
 
        const page_t*   page)   /*!< in: index page */
 
876
                                /* out: data in bytes */
 
877
        const page_t*   page)   /* in: index page */
892
878
{
893
879
        ulint   ret;
894
880
 
904
890
}
905
891
 
906
892
 
907
 
/************************************************************//**
 
893
/****************************************************************
908
894
Allocates a block of memory from the free list of an index page. */
909
 
UNIV_INLINE
 
895
UNIV_INTERN
910
896
void
911
897
page_mem_alloc_free(
912
898
/*================*/
913
 
        page_t*         page,   /*!< in/out: index page */
914
 
        page_zip_des_t* page_zip,/*!< in/out: compressed page with enough
 
899
        page_t*         page,   /* in/out: index page */
 
900
        page_zip_des_t* page_zip,/* in/out: compressed page with enough
915
901
                                space available for inserting the record,
916
902
                                or NULL */
917
 
        rec_t*          next_rec,/*!< in: pointer to the new head of the
 
903
        rec_t*          next_rec,/* in: pointer to the new head of the
918
904
                                free record list */
919
 
        ulint           need)   /*!< in: number of bytes allocated */
 
905
        ulint           need)   /* in: number of bytes allocated */
920
906
{
921
907
        ulint           garbage;
922
908
 
937
923
        page_header_set_field(page, page_zip, PAGE_GARBAGE, garbage - need);
938
924
}
939
925
 
940
 
/*************************************************************//**
941
 
Calculates free space if a page is emptied.
942
 
@return free space */
 
926
/*****************************************************************
 
927
Calculates free space if a page is emptied. */
943
928
UNIV_INLINE
944
929
ulint
945
930
page_get_free_space_of_empty(
946
931
/*=========================*/
947
 
        ulint   comp)           /*!< in: nonzero=compact page layout */
 
932
                                /* out: free space */
 
933
        ulint   comp)           /* in: nonzero=compact page layout */
948
934
{
949
935
        if (UNIV_LIKELY(comp)) {
950
936
                return((ulint)(UNIV_PAGE_SIZE
959
945
                       - 2 * PAGE_DIR_SLOT_SIZE));
960
946
}
961
947
 
962
 
/************************************************************//**
 
948
/****************************************************************
963
949
Each user record on a page, and also the deleted user records in the heap
964
950
takes its size plus the fraction of the dir cell size /
965
951
PAGE_DIR_SLOT_MIN_N_OWNED bytes for it. If the sum of these exceeds the
966
952
value of page_get_free_space_of_empty, the insert is impossible, otherwise
967
953
it is allowed. This function returns the maximum combined size of records
968
 
which can be inserted on top of the record heap.
969
 
@return maximum combined size for inserted records */
 
954
which can be inserted on top of the record heap. */
970
955
UNIV_INLINE
971
956
ulint
972
957
page_get_max_insert_size(
973
958
/*=====================*/
974
 
        const page_t*   page,   /*!< in: index page */
975
 
        ulint           n_recs) /*!< in: number of records */
 
959
                                /* out: maximum combined size for
 
960
                                inserted records */
 
961
        const page_t*   page,   /* in: index page */
 
962
        ulint           n_recs) /* in: number of records */
976
963
{
977
964
        ulint   occupied;
978
965
        ulint   free_space;
1005
992
        return(free_space - occupied);
1006
993
}
1007
994
 
1008
 
/************************************************************//**
 
995
/****************************************************************
1009
996
Returns the maximum combined size of records which can be inserted on top
1010
 
of the record heap if a page is first reorganized.
1011
 
@return maximum combined size for inserted records */
 
997
of the record heap if a page is first reorganized. */
1012
998
UNIV_INLINE
1013
999
ulint
1014
1000
page_get_max_insert_size_after_reorganize(
1015
1001
/*======================================*/
1016
 
        const page_t*   page,   /*!< in: index page */
1017
 
        ulint           n_recs) /*!< in: number of records */
 
1002
                                /* out: maximum combined size for
 
1003
                                inserted records */
 
1004
        const page_t*   page,   /* in: index page */
 
1005
        ulint           n_recs) /* in: number of records */
1018
1006
{
1019
1007
        ulint   occupied;
1020
1008
        ulint   free_space;
1032
1020
        return(free_space - occupied);
1033
1021
}
1034
1022
 
1035
 
/************************************************************//**
 
1023
/****************************************************************
1036
1024
Puts a record to free list. */
1037
1025
UNIV_INLINE
1038
1026
void
1039
1027
page_mem_free(
1040
1028
/*==========*/
1041
 
        page_t*         page,   /*!< in/out: index page */
1042
 
        page_zip_des_t* page_zip,/*!< in/out: compressed page, or NULL */
1043
 
        rec_t*          rec,    /*!< in: pointer to the (origin of) record */
1044
 
        dict_index_t*   index,  /*!< in: index of rec */
1045
 
        const ulint*    offsets)/*!< in: array returned by rec_get_offsets() */
 
1029
        page_t*         page,   /* in/out: index page */
 
1030
        page_zip_des_t* page_zip,/* in/out: compressed page, or NULL */
 
1031
        rec_t*          rec,    /* in: pointer to the (origin of) record */
 
1032
        dict_index_t*   index,  /* in: index of rec */
 
1033
        const ulint*    offsets)/* in: array returned by rec_get_offsets() */
1046
1034
{
1047
1035
        rec_t*          free;
1048
1036
        ulint           garbage;