~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/innobase/page/page0cur.c

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

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
#include "page0cur.ic"
12
12
#endif
13
13
 
14
 
#include "page0zip.h"
15
14
#include "rem0cmp.h"
16
15
#include "mtr0log.h"
17
16
#include "log0recv.h"
21
20
 
22
21
#ifdef PAGE_CUR_ADAPT
23
22
# ifdef UNIV_SEARCH_PERF_STAT
24
 
static ulint    page_cur_short_succ     = 0;
 
23
ulint   page_cur_short_succ     = 0;
25
24
# endif /* UNIV_SEARCH_PERF_STAT */
26
25
 
27
26
/********************************************************************
30
29
ibool
31
30
page_cur_try_search_shortcut(
32
31
/*=========================*/
33
 
                                        /* out: TRUE on success */
34
 
        const buf_block_t*      block,  /* in: index page */
35
 
        const dict_index_t*     index,  /* in: record descriptor */
36
 
        const dtuple_t*         tuple,  /* in: data tuple */
37
 
        ulint*                  iup_matched_fields,
38
 
                                        /* in/out: already matched
39
 
                                        fields in upper limit record */
40
 
        ulint*                  iup_matched_bytes,
41
 
                                        /* in/out: already matched
42
 
                                        bytes in a field not yet
43
 
                                        completely matched */
44
 
        ulint*                  ilow_matched_fields,
45
 
                                        /* in/out: already matched
46
 
                                        fields in lower limit record */
47
 
        ulint*                  ilow_matched_bytes,
48
 
                                        /* in/out: already matched
49
 
                                        bytes in a field not yet
50
 
                                        completely matched */
51
 
        page_cur_t*             cursor) /* out: page cursor */
 
32
                                /* out: TRUE on success */
 
33
        page_t*         page,   /* in: index page */
 
34
        dict_index_t*   index,  /* in: record descriptor */
 
35
        dtuple_t*       tuple,  /* in: data tuple */
 
36
        ulint*          iup_matched_fields,
 
37
                                /* in/out: already matched fields in upper
 
38
                                limit record */
 
39
        ulint*          iup_matched_bytes,
 
40
                                /* in/out: already matched bytes in a field
 
41
                                not yet completely matched */
 
42
        ulint*          ilow_matched_fields,
 
43
                                /* in/out: already matched fields in lower
 
44
                                limit record */
 
45
        ulint*          ilow_matched_bytes,
 
46
                                /* in/out: already matched bytes in a field
 
47
                                not yet completely matched */
 
48
        page_cur_t*     cursor) /* out: page cursor */
52
49
{
53
 
        const rec_t*    rec;
54
 
        const rec_t*    next_rec;
55
 
        ulint           low_match;
56
 
        ulint           low_bytes;
57
 
        ulint           up_match;
58
 
        ulint           up_bytes;
 
50
        rec_t*  rec;
 
51
        rec_t*  next_rec;
 
52
        ulint   low_match;
 
53
        ulint   low_bytes;
 
54
        ulint   up_match;
 
55
        ulint   up_bytes;
59
56
#ifdef UNIV_SEARCH_DEBUG
60
 
        page_cur_t      cursor2;
 
57
        page_cur_t cursor2;
61
58
#endif
62
59
        ibool           success         = FALSE;
63
 
        const page_t*   page            = buf_block_get_frame(block);
64
60
        mem_heap_t*     heap            = NULL;
65
61
        ulint           offsets_[REC_OFFS_NORMAL_SIZE];
66
62
        ulint*          offsets         = offsets_;
67
 
        rec_offs_init(offsets_);
 
63
        *offsets_ = (sizeof offsets_) / sizeof *offsets_;
68
64
 
69
65
        ut_ad(dtuple_check_typed(tuple));
70
66
 
87
83
                goto exit_func;
88
84
        }
89
85
 
90
 
        next_rec = page_rec_get_next_const(rec);
 
86
        next_rec = page_rec_get_next(rec);
91
87
        offsets = rec_get_offsets(next_rec, index, offsets,
92
88
                                  dtuple_get_n_fields(tuple), &heap);
93
89
 
96
92
                goto exit_func;
97
93
        }
98
94
 
99
 
        page_cur_position(rec, block, cursor);
 
95
        cursor->rec = rec;
100
96
 
101
97
#ifdef UNIV_SEARCH_DEBUG
102
 
        page_cur_search_with_match(block, index, tuple, PAGE_CUR_DBG,
 
98
        page_cur_search_with_match(page, index, tuple, PAGE_CUR_DBG,
103
99
                                   iup_matched_fields,
104
100
                                   iup_matched_bytes,
105
101
                                   ilow_matched_fields,
107
103
                                   &cursor2);
108
104
        ut_a(cursor2.rec == cursor->rec);
109
105
 
110
 
        if (!page_rec_is_supremum(next_rec)) {
 
106
        if (next_rec != page_get_supremum_rec(page)) {
111
107
 
112
108
                ut_a(*iup_matched_fields == up_match);
113
109
                ut_a(*iup_matched_bytes == up_bytes);
149
145
/*=======================*/
150
146
                                /* out: TRUE if rec field
151
147
                                extends tuple field */
152
 
        const dtuple_t* tuple,  /* in: data tuple */
153
 
        const rec_t*    rec,    /* in: record */
 
148
        dtuple_t*       tuple,  /* in: data tuple */
 
149
        rec_t*          rec,    /* in: record */
154
150
        const ulint*    offsets,/* in: array returned by rec_get_offsets() */
155
151
        ulint           n)      /* in: compare nth field */
156
152
{
157
 
        const dtype_t*  type;
158
 
        const dfield_t* dfield;
159
 
        const byte*     rec_f;
160
 
        ulint           rec_f_len;
 
153
        dtype_t* type;
 
154
        dfield_t* dfield;
 
155
        byte*     rec_f;
 
156
        ulint     rec_f_len;
161
157
 
162
158
        ut_ad(rec_offs_validate(rec, NULL, offsets));
163
159
        dfield = dtuple_get_nth_field(tuple, n);
177
173
                if (dfield_get_len(dfield) != UNIV_SQL_NULL
178
174
                    && rec_f_len != UNIV_SQL_NULL
179
175
                    && rec_f_len >= dfield_get_len(dfield)
180
 
                    && !cmp_data_data_slow(type->mtype, type->prtype,
 
176
                    && !cmp_data_data_slow(type,
181
177
                                           dfield_get_data(dfield),
182
178
                                           dfield_get_len(dfield),
183
179
                                           rec_f, dfield_get_len(dfield))) {
192
188
 
193
189
/********************************************************************
194
190
Searches the right position for a page cursor. */
195
 
UNIV_INTERN
 
191
 
196
192
void
197
193
page_cur_search_with_match(
198
194
/*=======================*/
199
 
        const buf_block_t*      block,  /* in: buffer block */
200
 
        const dict_index_t*     index,  /* in: record descriptor */
201
 
        const dtuple_t*         tuple,  /* in: data tuple */
202
 
        ulint                   mode,   /* in: PAGE_CUR_L,
203
 
                                        PAGE_CUR_LE, PAGE_CUR_G, or
204
 
                                        PAGE_CUR_GE */
205
 
        ulint*                  iup_matched_fields,
206
 
                                        /* in/out: already matched
207
 
                                        fields in upper limit record */
208
 
        ulint*                  iup_matched_bytes,
209
 
                                        /* in/out: already matched
210
 
                                        bytes in a field not yet
211
 
                                        completely matched */
212
 
        ulint*                  ilow_matched_fields,
213
 
                                        /* in/out: already matched
214
 
                                        fields in lower limit record */
215
 
        ulint*                  ilow_matched_bytes,
216
 
                                        /* in/out: already matched
217
 
                                        bytes in a field not yet
218
 
                                        completely matched */
219
 
        page_cur_t*             cursor) /* out: page cursor */
 
195
        page_t*         page,   /* in: index page */
 
196
        dict_index_t*   index,  /* in: record descriptor */
 
197
        dtuple_t*       tuple,  /* in: data tuple */
 
198
        ulint           mode,   /* in: PAGE_CUR_L, PAGE_CUR_LE, PAGE_CUR_G,
 
199
                                or PAGE_CUR_GE */
 
200
        ulint*          iup_matched_fields,
 
201
                                /* in/out: already matched fields in upper
 
202
                                limit record */
 
203
        ulint*          iup_matched_bytes,
 
204
                                /* in/out: already matched bytes in a field
 
205
                                not yet completely matched */
 
206
        ulint*          ilow_matched_fields,
 
207
                                /* in/out: already matched fields in lower
 
208
                                limit record */
 
209
        ulint*          ilow_matched_bytes,
 
210
                                /* in/out: already matched bytes in a field
 
211
                                not yet completely matched */
 
212
        page_cur_t*     cursor) /* out: page cursor */
220
213
{
221
 
        ulint           up;
222
 
        ulint           low;
223
 
        ulint           mid;
224
 
        const page_t*   page;
225
 
        const page_dir_slot_t* slot;
226
 
        const rec_t*    up_rec;
227
 
        const rec_t*    low_rec;
228
 
        const rec_t*    mid_rec;
229
 
        ulint           up_matched_fields;
230
 
        ulint           up_matched_bytes;
231
 
        ulint           low_matched_fields;
232
 
        ulint           low_matched_bytes;
233
 
        ulint           cur_matched_fields;
234
 
        ulint           cur_matched_bytes;
235
 
        int             cmp;
 
214
        ulint   up;
 
215
        ulint   low;
 
216
        ulint   mid;
 
217
        page_dir_slot_t* slot;
 
218
        rec_t*  up_rec;
 
219
        rec_t*  low_rec;
 
220
        rec_t*  mid_rec;
 
221
        ulint   up_matched_fields;
 
222
        ulint   up_matched_bytes;
 
223
        ulint   low_matched_fields;
 
224
        ulint   low_matched_bytes;
 
225
        ulint   cur_matched_fields;
 
226
        ulint   cur_matched_bytes;
 
227
        int     cmp;
236
228
#ifdef UNIV_SEARCH_DEBUG
237
 
        int             dbg_cmp;
238
 
        ulint           dbg_matched_fields;
239
 
        ulint           dbg_matched_bytes;
 
229
        int     dbg_cmp;
 
230
        ulint   dbg_matched_fields;
 
231
        ulint   dbg_matched_bytes;
240
232
#endif
241
 
#ifdef UNIV_ZIP_DEBUG
242
 
        const page_zip_des_t*   page_zip = buf_block_get_page_zip(block);
243
 
#endif /* UNIV_ZIP_DEBUG */
244
233
        mem_heap_t*     heap            = NULL;
245
234
        ulint           offsets_[REC_OFFS_NORMAL_SIZE];
246
235
        ulint*          offsets         = offsets_;
247
 
        rec_offs_init(offsets_);
 
236
        *offsets_ = (sizeof offsets_) / sizeof *offsets_;
248
237
 
249
 
        ut_ad(block && tuple && iup_matched_fields && iup_matched_bytes
 
238
        ut_ad(page && tuple && iup_matched_fields && iup_matched_bytes
250
239
              && ilow_matched_fields && ilow_matched_bytes && cursor);
251
240
        ut_ad(dtuple_validate(tuple));
 
241
        ut_ad(dtuple_check_typed(tuple));
252
242
#ifdef UNIV_DEBUG
253
243
# ifdef PAGE_CUR_DBG
254
244
        if (mode != PAGE_CUR_DBG)
259
249
                        ut_ad(mode == PAGE_CUR_L || mode == PAGE_CUR_LE
260
250
                              || mode == PAGE_CUR_G || mode == PAGE_CUR_GE);
261
251
#endif /* UNIV_DEBUG */
262
 
        page = buf_block_get_frame(block);
263
 
#ifdef UNIV_ZIP_DEBUG
264
 
        ut_a(!page_zip || page_zip_validate(page_zip, page));
265
 
#endif /* UNIV_ZIP_DEBUG */
266
252
 
267
253
        page_check_dir(page);
268
254
 
269
255
#ifdef PAGE_CUR_ADAPT
270
 
        if (page_is_leaf(page)
 
256
        if ((page_header_get_field(page, PAGE_LEVEL) == 0)
271
257
            && (mode == PAGE_CUR_LE)
272
258
            && (page_header_get_field(page, PAGE_N_DIRECTION) > 3)
273
259
            && (page_header_get_ptr(page, PAGE_LAST_INSERT))
274
260
            && (page_header_get_field(page, PAGE_DIRECTION) == PAGE_RIGHT)) {
275
261
 
276
262
                if (page_cur_try_search_shortcut(
277
 
                            block, index, tuple,
 
263
                            page, index, tuple,
278
264
                            iup_matched_fields, iup_matched_bytes,
279
265
                            ilow_matched_fields, ilow_matched_bytes,
280
266
                            cursor)) {
373
359
        /* Perform linear search until the upper and lower records come to
374
360
        distance 1 of each other. */
375
361
 
376
 
        while (page_rec_get_next_const(low_rec) != up_rec) {
 
362
        while (page_rec_get_next(low_rec) != up_rec) {
377
363
 
378
 
                mid_rec = page_rec_get_next_const(low_rec);
 
364
                mid_rec = page_rec_get_next(low_rec);
379
365
 
380
366
                ut_pair_min(&cur_matched_fields, &cur_matched_bytes,
381
367
                            low_matched_fields, low_matched_bytes,
443
429
                ut_a(dbg_cmp >= 0);
444
430
        }
445
431
 
446
 
        if (!page_rec_is_infimum(low_rec)) {
 
432
        if (low_rec != page_get_infimum_rec(page)) {
447
433
 
448
434
                ut_a(low_matched_fields == dbg_matched_fields);
449
435
                ut_a(low_matched_bytes == dbg_matched_bytes);
467
453
                ut_a(dbg_cmp == -1);
468
454
        }
469
455
 
470
 
        if (!page_rec_is_supremum(up_rec)) {
 
456
        if (up_rec != page_get_supremum_rec(page)) {
471
457
 
472
458
                ut_a(up_matched_fields == dbg_matched_fields);
473
459
                ut_a(up_matched_bytes == dbg_matched_bytes);
474
460
        }
475
461
#endif
476
462
        if (mode <= PAGE_CUR_GE) {
477
 
                page_cur_position(up_rec, block, cursor);
 
463
                cursor->rec = up_rec;
478
464
        } else {
479
 
                page_cur_position(low_rec, block, cursor);
 
465
                cursor->rec = low_rec;
480
466
        }
481
467
 
482
468
        *iup_matched_fields  = up_matched_fields;
491
477
/***************************************************************
492
478
Positions a page cursor on a randomly chosen user record on a page. If there
493
479
are no user records, sets the cursor on the infimum record. */
494
 
UNIV_INTERN
 
480
 
495
481
void
496
482
page_cur_open_on_rnd_user_rec(
497
483
/*==========================*/
498
 
        buf_block_t*    block,  /* in: page */
499
 
        page_cur_t*     cursor) /* out: page cursor */
 
484
        page_t*         page,   /* in: page */
 
485
        page_cur_t*     cursor) /* in/out: page cursor */
500
486
{
501
487
        ulint   rnd;
502
 
        ulint   n_recs = page_get_n_recs(buf_block_get_frame(block));
503
 
 
504
 
        page_cur_set_before_first(block, cursor);
505
 
 
506
 
        if (UNIV_UNLIKELY(n_recs == 0)) {
 
488
        rec_t*  rec;
 
489
 
 
490
        if (page_get_n_recs(page) == 0) {
 
491
                page_cur_position(page_get_infimum_rec(page), cursor);
507
492
 
508
493
                return;
509
494
        }
510
495
 
511
496
        page_rnd += 87584577;
512
497
 
513
 
        rnd = page_rnd % n_recs;
514
 
 
515
 
        do {
516
 
                page_cur_move_to_next(cursor);
517
 
        } while (rnd--);
 
498
        rnd = page_rnd % page_get_n_recs(page);
 
499
 
 
500
        rec = page_get_infimum_rec(page);
 
501
 
 
502
        rec = page_rec_get_next(rec);
 
503
 
 
504
        while (rnd > 0) {
 
505
                rec = page_rec_get_next(rec);
 
506
 
 
507
                rnd--;
 
508
        }
 
509
 
 
510
        page_cur_position(rec, cursor);
518
511
}
519
512
 
520
513
/***************************************************************
533
526
        ulint   cur_rec_size;
534
527
        ulint   extra_size;
535
528
        ulint   cur_extra_size;
536
 
        const byte* ins_ptr;
 
529
        ulint   min_rec_size;
 
530
        byte*   ins_ptr;
 
531
        byte*   cur_ptr;
 
532
        ulint   extra_info_yes;
537
533
        byte*   log_ptr;
538
 
        const byte* log_end;
 
534
        byte*   log_end;
539
535
        ulint   i;
 
536
        ulint   comp;
540
537
 
541
538
        ut_a(rec_size < UNIV_PAGE_SIZE);
542
 
        ut_ad(page_align(insert_rec) == page_align(cursor_rec));
 
539
        ut_ad(buf_frame_align(insert_rec) == buf_frame_align(cursor_rec));
543
540
        ut_ad(!page_rec_is_comp(insert_rec)
544
541
              == !dict_table_is_comp(index->table));
 
542
        comp = page_rec_is_comp(insert_rec);
545
543
 
546
544
        {
547
545
                mem_heap_t*     heap            = NULL;
551
549
                ulint*          cur_offs;
552
550
                ulint*          ins_offs;
553
551
 
554
 
                rec_offs_init(cur_offs_);
555
 
                rec_offs_init(ins_offs_);
 
552
                *cur_offs_ = (sizeof cur_offs_) / sizeof *cur_offs_;
 
553
                *ins_offs_ = (sizeof ins_offs_) / sizeof *ins_offs_;
556
554
 
557
555
                cur_offs = rec_get_offsets(cursor_rec, index, cur_offs_,
558
556
                                           ULINT_UNDEFINED, &heap);
574
572
        i = 0;
575
573
 
576
574
        if (cur_extra_size == extra_size) {
577
 
                ulint           min_rec_size = ut_min(cur_rec_size, rec_size);
 
575
                min_rec_size = ut_min(cur_rec_size, rec_size);
578
576
 
579
 
                const byte*     cur_ptr = cursor_rec - cur_extra_size;
 
577
                cur_ptr = cursor_rec - cur_extra_size;
580
578
 
581
579
                /* Find out the first byte in insert_rec which differs from
582
580
                cursor_rec; skip the bytes in the record info */
583
581
 
584
 
                do {
585
 
                        if (*ins_ptr == *cur_ptr) {
 
582
                for (;;) {
 
583
                        if (i >= min_rec_size) {
 
584
 
 
585
                                break;
 
586
                        } else if (*ins_ptr == *cur_ptr) {
586
587
                                i++;
587
588
                                ins_ptr++;
588
589
                                cur_ptr++;
589
590
                        } else if ((i < extra_size)
590
591
                                   && (i >= extra_size
591
 
                                       - page_rec_get_base_extra_size
592
 
                                       (insert_rec))) {
 
592
                                       - (comp
 
593
                                          ? REC_N_NEW_EXTRA_BYTES
 
594
                                          : REC_N_OLD_EXTRA_BYTES))) {
593
595
                                i = extra_size;
594
596
                                ins_ptr = insert_rec;
595
597
                                cur_ptr = cursor_rec;
596
598
                        } else {
597
599
                                break;
598
600
                        }
599
 
                } while (i < min_rec_size);
 
601
                }
600
602
        }
601
603
 
602
604
        if (mtr_get_log_mode(mtr) != MTR_LOG_SHORT_INSERTS) {
603
605
 
604
 
                if (page_rec_is_comp(insert_rec)) {
605
 
                        log_ptr = mlog_open_and_write_index(
606
 
                                mtr, insert_rec, index, MLOG_COMP_REC_INSERT,
607
 
                                2 + 5 + 1 + 5 + 5 + MLOG_BUF_MARGIN);
608
 
                        if (UNIV_UNLIKELY(!log_ptr)) {
609
 
                                /* Logging in mtr is switched off
610
 
                                during crash recovery: in that case
611
 
                                mlog_open returns NULL */
612
 
                                return;
613
 
                        }
614
 
                } else {
615
 
                        log_ptr = mlog_open(mtr, 11
616
 
                                            + 2 + 5 + 1 + 5 + 5
617
 
                                            + MLOG_BUF_MARGIN);
618
 
                        if (UNIV_UNLIKELY(!log_ptr)) {
619
 
                                /* Logging in mtr is switched off
620
 
                                during crash recovery: in that case
621
 
                                mlog_open returns NULL */
622
 
                                return;
623
 
                        }
 
606
                log_ptr = mlog_open_and_write_index(mtr, insert_rec, index,
 
607
                                                    comp
 
608
                                                    ? MLOG_COMP_REC_INSERT
 
609
                                                    : MLOG_REC_INSERT,
 
610
                                                    2 + 5 + 1 + 5 + 5
 
611
                                                    + MLOG_BUF_MARGIN);
624
612
 
625
 
                        log_ptr = mlog_write_initial_log_record_fast(
626
 
                                insert_rec, MLOG_REC_INSERT, log_ptr, mtr);
 
613
                if (!log_ptr) {
 
614
                        /* Logging in mtr is switched off during crash
 
615
                        recovery: in that case mlog_open returns NULL */
 
616
                        return;
627
617
                }
628
618
 
629
619
                log_end = &log_ptr[2 + 5 + 1 + 5 + 5 + MLOG_BUF_MARGIN];
630
620
                /* Write the cursor rec offset as a 2-byte ulint */
631
 
                mach_write_to_2(log_ptr, page_offset(cursor_rec));
 
621
                mach_write_to_2(log_ptr, cursor_rec
 
622
                                - buf_frame_align(cursor_rec));
632
623
                log_ptr += 2;
633
624
        } else {
634
625
                log_ptr = mlog_open(mtr, 5 + 1 + 5 + 5 + MLOG_BUF_MARGIN);
640
631
                log_end = &log_ptr[5 + 1 + 5 + 5 + MLOG_BUF_MARGIN];
641
632
        }
642
633
 
643
 
        if (page_rec_is_comp(insert_rec)) {
644
 
                if (UNIV_UNLIKELY
645
 
                    (rec_get_info_and_status_bits(insert_rec, TRUE)
646
 
                     != rec_get_info_and_status_bits(cursor_rec, TRUE))) {
 
634
        if ((rec_get_info_and_status_bits(insert_rec, comp)
 
635
             != rec_get_info_and_status_bits(cursor_rec, comp))
 
636
            || (extra_size != cur_extra_size)
 
637
            || (rec_size != cur_rec_size)) {
647
638
 
648
 
                        goto need_extra_info;
649
 
                }
 
639
                extra_info_yes = 1;
650
640
        } else {
651
 
                if (UNIV_UNLIKELY
652
 
                    (rec_get_info_and_status_bits(insert_rec, FALSE)
653
 
                     != rec_get_info_and_status_bits(cursor_rec, FALSE))) {
654
 
 
655
 
                        goto need_extra_info;
656
 
                }
 
641
                extra_info_yes = 0;
657
642
        }
658
643
 
659
 
        if (extra_size != cur_extra_size || rec_size != cur_rec_size) {
660
 
need_extra_info:
661
 
                /* Write the record end segment length
662
 
                and the extra info storage flag */
663
 
                log_ptr += mach_write_compressed(log_ptr,
664
 
                                                 2 * (rec_size - i) + 1);
665
 
 
 
644
        /* Write the record end segment length and the extra info storage
 
645
        flag */
 
646
        log_ptr += mach_write_compressed(log_ptr, 2 * (rec_size - i)
 
647
                                         + extra_info_yes);
 
648
        if (extra_info_yes) {
666
649
                /* Write the info bits */
667
650
                mach_write_to_1(log_ptr,
668
 
                                rec_get_info_and_status_bits(
669
 
                                        insert_rec,
670
 
                                        page_rec_is_comp(insert_rec)));
 
651
                                rec_get_info_and_status_bits(insert_rec,
 
652
                                                             comp));
671
653
                log_ptr++;
672
654
 
673
655
                /* Write the record origin offset */
678
660
 
679
661
                ut_a(i < UNIV_PAGE_SIZE);
680
662
                ut_a(extra_size < UNIV_PAGE_SIZE);
681
 
        } else {
682
 
                /* Write the record end segment length
683
 
                and the extra info storage flag */
684
 
                log_ptr += mach_write_compressed(log_ptr, 2 * (rec_size - i));
685
663
        }
686
664
 
687
665
        /* Write to the log the inserted index record end segment which
701
679
 
702
680
/***************************************************************
703
681
Parses a log record of a record insert on a page. */
704
 
UNIV_INTERN
 
682
 
705
683
byte*
706
684
page_cur_parse_insert_rec(
707
685
/*======================*/
709
687
        ibool           is_short,/* in: TRUE if short inserts */
710
688
        byte*           ptr,    /* in: buffer */
711
689
        byte*           end_ptr,/* in: buffer end */
712
 
        buf_block_t*    block,  /* in: page or NULL */
713
690
        dict_index_t*   index,  /* in: record descriptor */
 
691
        page_t*         page,   /* in: page or NULL */
714
692
        mtr_t*          mtr)    /* in: mtr or NULL */
715
693
{
 
694
        ulint   extra_info_yes;
 
695
        ulint   offset = 0; /* remove warning */
716
696
        ulint   origin_offset;
717
697
        ulint   end_seg_len;
718
698
        ulint   mismatch_index;
719
 
        page_t* page;
720
699
        rec_t*  cursor_rec;
721
700
        byte    buf1[1024];
722
701
        byte*   buf;
723
 
        byte*   ptr2                    = ptr;
 
702
        byte*   ptr2 = ptr;
724
703
        ulint   info_and_status_bits = 0; /* remove warning */
725
704
        page_cur_t cursor;
726
705
        mem_heap_t*     heap            = NULL;
727
706
        ulint           offsets_[REC_OFFS_NORMAL_SIZE];
728
707
        ulint*          offsets         = offsets_;
729
 
        rec_offs_init(offsets_);
730
 
 
731
 
        page = block ? buf_block_get_frame(block) : NULL;
732
 
 
733
 
        if (is_short) {
734
 
                cursor_rec = page_rec_get_prev(page_get_supremum_rec(page));
735
 
        } else {
736
 
                ulint   offset;
737
 
 
 
708
        *offsets_ = (sizeof offsets_) / sizeof *offsets_;
 
709
 
 
710
        if (!is_short) {
738
711
                /* Read the cursor rec offset as a 2-byte ulint */
739
712
 
740
 
                if (UNIV_UNLIKELY(end_ptr < ptr + 2)) {
 
713
                if (end_ptr < ptr + 2) {
741
714
 
742
715
                        return(NULL);
743
716
                }
744
717
 
745
718
                offset = mach_read_from_2(ptr);
 
719
 
 
720
                if (offset >= UNIV_PAGE_SIZE) {
 
721
 
 
722
                        recv_sys->found_corrupt_log = TRUE;
 
723
 
 
724
                        return(NULL);
 
725
                }
 
726
 
746
727
                ptr += 2;
747
 
 
748
 
                cursor_rec = page + offset;
749
 
 
750
 
                if (UNIV_UNLIKELY(offset >= UNIV_PAGE_SIZE)) {
751
 
 
752
 
                        recv_sys->found_corrupt_log = TRUE;
753
 
 
754
 
                        return(NULL);
755
 
                }
756
728
        }
757
729
 
758
730
        ptr = mach_parse_compressed(ptr, end_ptr, &end_seg_len);
762
734
                return(NULL);
763
735
        }
764
736
 
765
 
        if (UNIV_UNLIKELY(end_seg_len >= UNIV_PAGE_SIZE << 1)) {
 
737
        extra_info_yes = end_seg_len & 0x1UL;
 
738
        end_seg_len >>= 1;
 
739
 
 
740
        if (end_seg_len >= UNIV_PAGE_SIZE) {
766
741
                recv_sys->found_corrupt_log = TRUE;
767
742
 
768
743
                return(NULL);
769
744
        }
770
745
 
771
 
        if (end_seg_len & 0x1UL) {
 
746
        if (extra_info_yes) {
772
747
                /* Read the info bits */
773
748
 
774
749
                if (end_ptr < ptr + 1) {
798
773
                ut_a(mismatch_index < UNIV_PAGE_SIZE);
799
774
        }
800
775
 
801
 
        if (UNIV_UNLIKELY(end_ptr < ptr + (end_seg_len >> 1))) {
 
776
        if (end_ptr < ptr + end_seg_len) {
802
777
 
803
778
                return(NULL);
804
779
        }
805
780
 
806
 
        if (!block) {
 
781
        if (page == NULL) {
807
782
 
808
 
                return(ptr + (end_seg_len >> 1));
 
783
                return(ptr + end_seg_len);
809
784
        }
810
785
 
811
786
        ut_ad(!!page_is_comp(page) == dict_table_is_comp(index->table));
812
 
        ut_ad(!buf_block_get_page_zip(block) || page_is_comp(page));
813
787
 
814
788
        /* Read from the log the inserted index record end segment which
815
789
        differs from the cursor record */
816
790
 
 
791
        if (is_short) {
 
792
                cursor_rec = page_rec_get_prev(page_get_supremum_rec(page));
 
793
        } else {
 
794
                cursor_rec = page + offset;
 
795
        }
 
796
 
817
797
        offsets = rec_get_offsets(cursor_rec, index, offsets,
818
798
                                  ULINT_UNDEFINED, &heap);
819
799
 
820
 
        if (!(end_seg_len & 0x1UL)) {
 
800
        if (extra_info_yes == 0) {
821
801
                info_and_status_bits = rec_get_info_and_status_bits(
822
802
                        cursor_rec, page_is_comp(page));
823
803
                origin_offset = rec_offs_extra_size(offsets);
824
 
                mismatch_index = rec_offs_size(offsets) - (end_seg_len >> 1);
 
804
                mismatch_index = rec_offs_size(offsets) - end_seg_len;
825
805
        }
826
806
 
827
 
        end_seg_len >>= 1;
828
 
 
829
807
        if (mismatch_index + end_seg_len < sizeof buf1) {
830
808
                buf = buf1;
831
809
        } else {
834
812
 
835
813
        /* Build the inserted record to buf */
836
814
 
837
 
        if (UNIV_UNLIKELY(mismatch_index >= UNIV_PAGE_SIZE)) {
 
815
        if (mismatch_index >= UNIV_PAGE_SIZE) {
838
816
                fprintf(stderr,
839
817
                        "Is short %lu, info_and_status_bits %lu, offset %lu, "
840
818
                        "o_offset %lu\n"
841
819
                        "mismatch index %lu, end_seg_len %lu\n"
842
820
                        "parsed len %lu\n",
843
821
                        (ulong) is_short, (ulong) info_and_status_bits,
844
 
                        (ulong) page_offset(cursor_rec),
 
822
                        (ulong) offset,
845
823
                        (ulong) origin_offset,
846
824
                        (ulong) mismatch_index, (ulong) end_seg_len,
847
825
                        (ulong) (ptr - ptr2));
849
827
                fputs("Dump of 300 bytes of log:\n", stderr);
850
828
                ut_print_buf(stderr, ptr2, 300);
851
829
 
852
 
                buf_page_print(page, 0);
 
830
                buf_page_print(page);
853
831
 
854
832
                ut_error;
855
833
        }
857
835
        ut_memcpy(buf, rec_get_start(cursor_rec, offsets), mismatch_index);
858
836
        ut_memcpy(buf + mismatch_index, ptr, end_seg_len);
859
837
 
860
 
        if (page_is_comp(page)) {
861
 
                rec_set_info_and_status_bits(buf + origin_offset,
 
838
        rec_set_info_and_status_bits(buf + origin_offset, page_is_comp(page),
862
839
                                     info_and_status_bits);
863
 
        } else {
864
 
                rec_set_info_bits_old(buf + origin_offset,
865
 
                                                        info_and_status_bits);
866
 
        }
867
840
 
868
 
        page_cur_position(cursor_rec, block, &cursor);
 
841
        page_cur_position(cursor_rec, &cursor);
869
842
 
870
843
        offsets = rec_get_offsets(buf + origin_offset, index, offsets,
871
844
                                  ULINT_UNDEFINED, &heap);
872
 
        if (UNIV_UNLIKELY(!page_cur_rec_insert(&cursor,
873
 
                                               buf + origin_offset,
874
 
                                               index, offsets, mtr))) {
875
 
                /* The redo log record should only have been written
876
 
                after the write was successful. */
877
 
                ut_error;
878
 
        }
 
845
        page_cur_rec_insert(&cursor, buf + origin_offset, index, offsets, mtr);
879
846
 
880
847
        if (buf != buf1) {
881
848
 
890
857
}
891
858
 
892
859
/***************************************************************
893
 
Inserts a record next to page cursor on an uncompressed page.
894
 
Returns pointer to inserted record if succeed, i.e., enough
895
 
space available, NULL otherwise. The cursor stays at the same position. */
896
 
UNIV_INTERN
 
860
Inserts a record next to page cursor. Returns pointer to inserted record if
 
861
succeed, i.e., enough space available, NULL otherwise. The record to be
 
862
inserted can be in a data tuple or as a physical record. The other parameter
 
863
must then be NULL. The cursor stays at the same position. */
 
864
 
897
865
rec_t*
898
866
page_cur_insert_rec_low(
899
867
/*====================*/
900
868
                                /* out: pointer to record if succeed, NULL
901
869
                                otherwise */
902
 
        rec_t*          current_rec,/* in: pointer to current record after
903
 
                                which the new record is inserted */
 
870
        page_cur_t*     cursor, /* in: a page cursor */
 
871
        dtuple_t*       tuple,  /* in: pointer to a data tuple or NULL */
904
872
        dict_index_t*   index,  /* in: record descriptor */
905
 
        const rec_t*    rec,    /* in: pointer to a physical record */
906
 
        ulint*          offsets,/* in/out: rec_get_offsets(rec, index) */
907
 
        mtr_t*          mtr)    /* in: mini-transaction handle, or NULL */
 
873
        rec_t*          rec,    /* in: pointer to a physical record or NULL */
 
874
        ulint*          offsets,/* in: rec_get_offsets(rec, index) or NULL */
 
875
        mtr_t*          mtr)    /* in: mini-transaction handle */
908
876
{
909
877
        byte*           insert_buf      = NULL;
910
878
        ulint           rec_size;
911
 
        page_t*         page;           /* the relevant page */
 
879
        byte*           page;           /* the relevant page */
912
880
        rec_t*          last_insert;    /* cursor position at previous
913
881
                                        insert */
914
 
        rec_t*          free_rec;       /* a free record that was reused,
915
 
                                        or NULL */
916
882
        rec_t*          insert_rec;     /* inserted record */
917
883
        ulint           heap_no;        /* heap number of the inserted
918
884
                                        record */
919
 
 
920
 
        ut_ad(rec_offs_validate(rec, index, offsets));
921
 
 
922
 
        page = page_align(current_rec);
923
 
        ut_ad(dict_table_is_comp(index->table)
924
 
              == (ibool) !!page_is_comp(page));
925
 
 
926
 
        ut_ad(!page_rec_is_supremum(current_rec));
 
885
        rec_t*          current_rec;    /* current record after which the
 
886
                                        new record is inserted */
 
887
        rec_t*          next_rec;       /* next record after current before
 
888
                                        the insertion */
 
889
        ulint           owner_slot;     /* the slot which owns the
 
890
                                        inserted record */
 
891
        rec_t*          owner_rec;
 
892
        ulint           n_owned;
 
893
        mem_heap_t*     heap            = NULL;
 
894
        ulint           comp;
 
895
 
 
896
        ut_ad(cursor && mtr);
 
897
        ut_ad(tuple || rec);
 
898
        ut_ad(!(tuple && rec));
 
899
        ut_ad(rec || dtuple_check_typed(tuple));
 
900
 
 
901
        page = page_cur_get_page(cursor);
 
902
        comp = page_is_comp(page);
 
903
        ut_ad(dict_table_is_comp(index->table) == !!comp);
 
904
 
 
905
        ut_ad(cursor->rec != page_get_supremum_rec(page));
927
906
 
928
907
        /* 1. Get the size of the physical record in the page */
929
 
        rec_size = rec_offs_size(offsets);
930
 
 
931
 
#ifdef UNIV_DEBUG_VALGRIND
932
 
        {
933
 
                const void*     rec_start
934
 
                        = rec - rec_offs_extra_size(offsets);
935
 
                ulint           extra_size
936
 
                        = rec_offs_extra_size(offsets)
937
 
                        - (rec_offs_comp(offsets)
938
 
                           ? REC_N_NEW_EXTRA_BYTES
939
 
                           : REC_N_OLD_EXTRA_BYTES);
940
 
 
941
 
                /* All data bytes of the record must be valid. */
942
 
                UNIV_MEM_ASSERT_RW(rec, rec_offs_data_size(offsets));
943
 
                /* The variable-length header must be valid. */
944
 
                UNIV_MEM_ASSERT_RW(rec_start, extra_size);
 
908
        if (tuple != NULL) {
 
909
                rec_size = rec_get_converted_size(index, tuple);
 
910
        } else {
 
911
                if (!offsets) {
 
912
                        offsets = rec_get_offsets(rec, index, offsets,
 
913
                                                  ULINT_UNDEFINED, &heap);
 
914
                }
 
915
                ut_ad(rec_offs_validate(rec, index, offsets));
 
916
                rec_size = rec_offs_size(offsets);
945
917
        }
946
 
#endif /* UNIV_DEBUG_VALGRIND */
947
918
 
948
919
        /* 2. Try to find suitable space from page memory management */
949
 
 
950
 
        free_rec = page_header_get_ptr(page, PAGE_FREE);
951
 
        if (UNIV_LIKELY_NULL(free_rec)) {
952
 
                /* Try to allocate from the head of the free list. */
953
 
                ulint           foffsets_[REC_OFFS_NORMAL_SIZE];
954
 
                ulint*          foffsets        = foffsets_;
955
 
                mem_heap_t*     heap            = NULL;
956
 
 
957
 
                rec_offs_init(foffsets_);
958
 
 
959
 
                foffsets = rec_get_offsets(free_rec, index, foffsets,
960
 
                                        ULINT_UNDEFINED, &heap);
961
 
                if (rec_offs_size(foffsets) < rec_size) {
962
 
                        if (UNIV_LIKELY_NULL(heap)) {
963
 
                                mem_heap_free(heap);
964
 
                        }
965
 
 
966
 
                        goto use_heap;
967
 
                }
968
 
 
969
 
                insert_buf = free_rec - rec_offs_extra_size(foffsets);
970
 
 
971
 
                if (page_is_comp(page)) {
972
 
                        heap_no = rec_get_heap_no_new(free_rec);
973
 
                        page_mem_alloc_free(page, NULL,
974
 
                                        rec_get_next_ptr(free_rec, TRUE),
975
 
                                        rec_size);
976
 
                } else {
977
 
                        heap_no = rec_get_heap_no_old(free_rec);
978
 
                        page_mem_alloc_free(page, NULL,
979
 
                                        rec_get_next_ptr(free_rec, FALSE),
980
 
                                        rec_size);
981
 
                }
982
 
 
 
920
        insert_buf = page_mem_alloc(page, rec_size, index, &heap_no);
 
921
 
 
922
        if (insert_buf == NULL) {
983
923
                if (UNIV_LIKELY_NULL(heap)) {
984
924
                        mem_heap_free(heap);
985
925
                }
986
 
        } else {
987
 
use_heap:
988
 
                free_rec = NULL;
989
 
                insert_buf = page_mem_alloc_heap(page, NULL,
990
 
                                                 rec_size, &heap_no);
991
 
 
992
 
                if (UNIV_UNLIKELY(insert_buf == NULL)) {
993
 
                        return(NULL);
994
 
                }
 
926
                return(NULL);
995
927
        }
996
928
 
997
929
        /* 3. Create the record */
998
 
        insert_rec = rec_copy(insert_buf, rec, offsets);
999
 
        rec_offs_make_valid(insert_rec, index, offsets);
 
930
        if (tuple != NULL) {
 
931
                insert_rec = rec_convert_dtuple_to_rec(insert_buf,
 
932
                                                       index, tuple);
 
933
                offsets = rec_get_offsets(insert_rec, index, offsets,
 
934
                                          ULINT_UNDEFINED, &heap);
 
935
        } else {
 
936
                insert_rec = rec_copy(insert_buf, rec, offsets);
 
937
                ut_ad(rec_offs_validate(rec, index, offsets));
 
938
                rec_offs_make_valid(insert_rec, index, offsets);
 
939
        }
 
940
 
 
941
        ut_ad(insert_rec);
 
942
        ut_ad(rec_size == rec_offs_size(offsets));
1000
943
 
1001
944
        /* 4. Insert the record in the linked list of records */
1002
 
        ut_ad(current_rec != insert_rec);
1003
 
 
1004
 
        {
1005
 
                /* next record after current before the insertion */
1006
 
                rec_t*  next_rec = page_rec_get_next(current_rec);
1007
 
#ifdef UNIV_DEBUG
1008
 
                if (page_is_comp(page)) {
1009
 
                        ut_ad(rec_get_status(current_rec)
1010
 
                                <= REC_STATUS_INFIMUM);
1011
 
                        ut_ad(rec_get_status(insert_rec) < REC_STATUS_INFIMUM);
1012
 
                        ut_ad(rec_get_status(next_rec) != REC_STATUS_INFIMUM);
1013
 
                }
1014
 
#endif
1015
 
                page_rec_set_next(insert_rec, next_rec);
1016
 
                page_rec_set_next(current_rec, insert_rec);
1017
 
        }
1018
 
 
1019
 
        page_header_set_field(page, NULL, PAGE_N_RECS,
1020
 
                              1 + page_get_n_recs(page));
 
945
        current_rec = cursor->rec;
 
946
 
 
947
        ut_ad(!comp || rec_get_status(current_rec) <= REC_STATUS_INFIMUM);
 
948
        ut_ad(!comp || rec_get_status(insert_rec) < REC_STATUS_INFIMUM);
 
949
 
 
950
        next_rec = page_rec_get_next(current_rec);
 
951
        ut_ad(!comp || rec_get_status(next_rec) != REC_STATUS_INFIMUM);
 
952
        page_rec_set_next(insert_rec, next_rec);
 
953
        page_rec_set_next(current_rec, insert_rec);
 
954
 
 
955
        page_header_set_field(page, PAGE_N_RECS, 1 + page_get_n_recs(page));
1021
956
 
1022
957
        /* 5. Set the n_owned field in the inserted record to zero,
1023
958
        and set the heap_no field */
1024
 
        if (page_is_comp(page)) {
1025
 
                rec_set_n_owned_new(insert_rec, NULL, 0);
1026
 
                rec_set_heap_no_new(insert_rec, heap_no);
1027
 
        } else {
1028
 
                rec_set_n_owned_old(insert_rec, 0);
1029
 
                rec_set_heap_no_old(insert_rec, heap_no);
1030
 
        }
1031
 
 
1032
 
        UNIV_MEM_ASSERT_RW(rec_get_start(insert_rec, offsets),
1033
 
                           rec_offs_size(offsets));
 
959
 
 
960
        rec_set_n_owned(insert_rec, comp, 0);
 
961
        rec_set_heap_no(insert_rec, comp, heap_no);
 
962
 
1034
963
        /* 6. Update the last insertion info in page header */
1035
964
 
1036
965
        last_insert = page_header_get_ptr(page, PAGE_LAST_INSERT);
1037
 
        ut_ad(!last_insert || !page_is_comp(page)
 
966
        ut_ad(!last_insert || !comp
1038
967
              || rec_get_node_ptr_flag(last_insert)
1039
968
              == rec_get_node_ptr_flag(insert_rec));
1040
969
 
1041
 
        if (UNIV_UNLIKELY(last_insert == NULL)) {
1042
 
                page_header_set_field(page, NULL, PAGE_DIRECTION,
1043
 
                                      PAGE_NO_DIRECTION);
1044
 
                page_header_set_field(page, NULL, PAGE_N_DIRECTION, 0);
 
970
        if (last_insert == NULL) {
 
971
                page_header_set_field(page, PAGE_DIRECTION, PAGE_NO_DIRECTION);
 
972
                page_header_set_field(page, PAGE_N_DIRECTION, 0);
1045
973
 
1046
974
        } else if ((last_insert == current_rec)
1047
975
                   && (page_header_get_field(page, PAGE_DIRECTION)
1048
976
                       != PAGE_LEFT)) {
1049
977
 
1050
 
                page_header_set_field(page, NULL, PAGE_DIRECTION,
1051
 
                                                        PAGE_RIGHT);
1052
 
                page_header_set_field(page, NULL, PAGE_N_DIRECTION,
1053
 
                                      page_header_get_field(
1054
 
                                              page, PAGE_N_DIRECTION) + 1);
1055
 
 
1056
 
        } else if ((page_rec_get_next(insert_rec) == last_insert)
1057
 
                   && (page_header_get_field(page, PAGE_DIRECTION)
1058
 
                       != PAGE_RIGHT)) {
1059
 
 
1060
 
                page_header_set_field(page, NULL, PAGE_DIRECTION,
1061
 
                                                        PAGE_LEFT);
1062
 
                page_header_set_field(page, NULL, PAGE_N_DIRECTION,
1063
 
                                      page_header_get_field(
1064
 
                                              page, PAGE_N_DIRECTION) + 1);
1065
 
        } else {
1066
 
                page_header_set_field(page, NULL, PAGE_DIRECTION,
1067
 
                                                        PAGE_NO_DIRECTION);
1068
 
                page_header_set_field(page, NULL, PAGE_N_DIRECTION, 0);
1069
 
        }
1070
 
 
1071
 
        page_header_set_ptr(page, NULL, PAGE_LAST_INSERT, insert_rec);
1072
 
 
1073
 
        /* 7. It remains to update the owner record. */
1074
 
        {
1075
 
                rec_t*  owner_rec       = page_rec_find_owner_rec(insert_rec);
1076
 
                ulint   n_owned;
1077
 
                if (page_is_comp(page)) {
1078
 
                        n_owned = rec_get_n_owned_new(owner_rec);
1079
 
                        rec_set_n_owned_new(owner_rec, NULL, n_owned + 1);
1080
 
                } else {
1081
 
                        n_owned = rec_get_n_owned_old(owner_rec);
1082
 
                        rec_set_n_owned_old(owner_rec, n_owned + 1);
1083
 
                }
1084
 
 
1085
 
                /* 8. Now we have incremented the n_owned field of the owner
1086
 
                record. If the number exceeds PAGE_DIR_SLOT_MAX_N_OWNED,
1087
 
                we have to split the corresponding directory slot in two. */
1088
 
 
1089
 
                if (UNIV_UNLIKELY(n_owned == PAGE_DIR_SLOT_MAX_N_OWNED)) {
1090
 
                        page_dir_split_slot(
1091
 
                                page, NULL,
1092
 
                                page_dir_find_owner_slot(owner_rec));
1093
 
                }
1094
 
        }
1095
 
 
1096
 
        /* 9. Write log record of the insert */
1097
 
        if (UNIV_LIKELY(mtr != NULL)) {
1098
 
                page_cur_insert_rec_write_log(insert_rec, rec_size,
1099
 
                                              current_rec, index, mtr);
1100
 
        }
1101
 
 
1102
 
        return(insert_rec);
1103
 
}
1104
 
 
1105
 
/***************************************************************
1106
 
Compresses or reorganizes a page after an optimistic insert. */
1107
 
static
1108
 
rec_t*
1109
 
page_cur_insert_rec_zip_reorg(
1110
 
/*==========================*/
1111
 
                                /* out: rec if succeed, NULL otherwise */
1112
 
        rec_t**         current_rec,/* in/out: pointer to current record after
1113
 
                                which the new record is inserted */
1114
 
        buf_block_t*    block,  /* in: buffer block */
1115
 
        dict_index_t*   index,  /* in: record descriptor */
1116
 
        rec_t*          rec,    /* in: inserted record */
1117
 
        page_t*         page,   /* in: uncompressed page */
1118
 
        page_zip_des_t* page_zip,/* in: compressed page */
1119
 
        mtr_t*          mtr)    /* in: mini-transaction, or NULL */
1120
 
{
1121
 
        ulint           pos;
1122
 
 
1123
 
        /* Recompress or reorganize and recompress the page. */
1124
 
        if (UNIV_LIKELY(page_zip_compress(page_zip, page, index, mtr))) {
1125
 
                return(rec);
1126
 
        }
1127
 
 
1128
 
        /* Before trying to reorganize the page,
1129
 
        store the number of preceding records on the page. */
1130
 
        pos = page_rec_get_n_recs_before(rec);
1131
 
 
1132
 
        if (page_zip_reorganize(block, index, mtr)) {
1133
 
                /* The page was reorganized: Find rec by seeking to pos,
1134
 
                and update *current_rec. */
1135
 
                rec = page + PAGE_NEW_INFIMUM;
1136
 
 
1137
 
                while (--pos) {
1138
 
                        rec = page + rec_get_next_offs(rec, TRUE);
1139
 
                }
1140
 
 
1141
 
                *current_rec = rec;
1142
 
                rec = page + rec_get_next_offs(rec, TRUE);
1143
 
 
1144
 
                return(rec);
1145
 
        }
1146
 
 
1147
 
        /* Out of space: restore the page */
1148
 
        if (!page_zip_decompress(page_zip, page)) {
1149
 
                ut_error; /* Memory corrupted? */
1150
 
        }
1151
 
        ut_ad(page_validate(page, index));
1152
 
        return(NULL);
1153
 
}
1154
 
 
1155
 
/***************************************************************
1156
 
Inserts a record next to page cursor on a compressed and uncompressed
1157
 
page. Returns pointer to inserted record if succeed, i.e.,
1158
 
enough space available, NULL otherwise.
1159
 
The cursor stays at the same position. */
1160
 
UNIV_INTERN
1161
 
rec_t*
1162
 
page_cur_insert_rec_zip(
1163
 
/*====================*/
1164
 
                                /* out: pointer to record if succeed, NULL
1165
 
                                otherwise */
1166
 
        rec_t**         current_rec,/* in/out: pointer to current record after
1167
 
                                which the new record is inserted */
1168
 
        buf_block_t*    block,  /* in: buffer block of *current_rec */
1169
 
        dict_index_t*   index,  /* in: record descriptor */
1170
 
        const rec_t*    rec,    /* in: pointer to a physical record */
1171
 
        ulint*          offsets,/* in/out: rec_get_offsets(rec, index) */
1172
 
        mtr_t*          mtr)    /* in: mini-transaction handle, or NULL */
1173
 
{
1174
 
        byte*           insert_buf      = NULL;
1175
 
        ulint           rec_size;
1176
 
        page_t*         page;           /* the relevant page */
1177
 
        rec_t*          last_insert;    /* cursor position at previous
1178
 
                                        insert */
1179
 
        rec_t*          free_rec;       /* a free record that was reused,
1180
 
                                        or NULL */
1181
 
        rec_t*          insert_rec;     /* inserted record */
1182
 
        ulint           heap_no;        /* heap number of the inserted
1183
 
                                        record */
1184
 
        page_zip_des_t* page_zip;
1185
 
 
1186
 
        page_zip = buf_block_get_page_zip(block);
1187
 
        ut_ad(page_zip);
1188
 
 
1189
 
        ut_ad(rec_offs_validate(rec, index, offsets));
1190
 
 
1191
 
        page = page_align(*current_rec);
1192
 
        ut_ad(dict_table_is_comp(index->table));
1193
 
        ut_ad(page_is_comp(page));
1194
 
 
1195
 
        ut_ad(!page_rec_is_supremum(*current_rec));
1196
 
#ifdef UNIV_ZIP_DEBUG
1197
 
        ut_a(page_zip_validate(page_zip, page));
1198
 
#endif /* UNIV_ZIP_DEBUG */
1199
 
 
1200
 
        /* 1. Get the size of the physical record in the page */
1201
 
        rec_size = rec_offs_size(offsets);
1202
 
 
1203
 
#ifdef UNIV_DEBUG_VALGRIND
1204
 
        {
1205
 
                const void*     rec_start
1206
 
                        = rec - rec_offs_extra_size(offsets);
1207
 
                ulint           extra_size
1208
 
                        = rec_offs_extra_size(offsets)
1209
 
                        - (rec_offs_comp(offsets)
1210
 
                           ? REC_N_NEW_EXTRA_BYTES
1211
 
                           : REC_N_OLD_EXTRA_BYTES);
1212
 
 
1213
 
                /* All data bytes of the record must be valid. */
1214
 
                UNIV_MEM_ASSERT_RW(rec, rec_offs_data_size(offsets));
1215
 
                /* The variable-length header must be valid. */
1216
 
                UNIV_MEM_ASSERT_RW(rec_start, extra_size);
1217
 
        }
1218
 
#endif /* UNIV_DEBUG_VALGRIND */
1219
 
 
1220
 
        /* 2. Try to find suitable space from page memory management */
1221
 
        if (!page_zip_available(page_zip, dict_index_is_clust(index),
1222
 
                                rec_size, 1)) {
1223
 
 
1224
 
                /* Try compressing the whole page afterwards. */
1225
 
                insert_rec = page_cur_insert_rec_low(*current_rec,
1226
 
                                                     index, rec, offsets,
1227
 
                                                     NULL);
1228
 
 
1229
 
                if (UNIV_LIKELY(insert_rec != NULL)) {
1230
 
                        insert_rec = page_cur_insert_rec_zip_reorg(
1231
 
                                current_rec, block, index, insert_rec,
1232
 
                                page, page_zip, mtr);
1233
 
                }
1234
 
 
1235
 
                return(insert_rec);
1236
 
        }
1237
 
 
1238
 
        free_rec = page_header_get_ptr(page, PAGE_FREE);
1239
 
        if (UNIV_LIKELY_NULL(free_rec)) {
1240
 
                /* Try to allocate from the head of the free list. */
1241
 
                lint    extra_size_diff;
1242
 
                ulint           foffsets_[REC_OFFS_NORMAL_SIZE];
1243
 
                ulint*          foffsets        = foffsets_;
1244
 
                mem_heap_t*     heap            = NULL;
1245
 
 
1246
 
                rec_offs_init(foffsets_);
1247
 
 
1248
 
                foffsets = rec_get_offsets(free_rec, index, foffsets,
1249
 
                                        ULINT_UNDEFINED, &heap);
1250
 
                if (rec_offs_size(foffsets) < rec_size) {
1251
 
too_small:
1252
 
                        if (UNIV_LIKELY_NULL(heap)) {
1253
 
                                mem_heap_free(heap);
1254
 
                        }
1255
 
 
1256
 
                        goto use_heap;
1257
 
                }
1258
 
 
1259
 
                insert_buf = free_rec - rec_offs_extra_size(foffsets);
1260
 
 
1261
 
                /* On compressed pages, do not relocate records from
1262
 
                the free list.  If extra_size would grow, use the heap. */
1263
 
                extra_size_diff
1264
 
                        = rec_offs_extra_size(offsets)
1265
 
                        - rec_offs_extra_size(foffsets);
1266
 
 
1267
 
                if (UNIV_UNLIKELY(extra_size_diff < 0)) {
1268
 
                        /* Add an offset to the extra_size. */
1269
 
                        if (rec_offs_size(foffsets)
1270
 
                            < rec_size - extra_size_diff) {
1271
 
 
1272
 
                                goto too_small;
1273
 
                        }
1274
 
 
1275
 
                        insert_buf -= extra_size_diff;
1276
 
                } else if (UNIV_UNLIKELY(extra_size_diff)) {
1277
 
                        /* Do not allow extra_size to grow */
1278
 
 
1279
 
                        goto too_small;
1280
 
                }
1281
 
 
1282
 
                heap_no = rec_get_heap_no_new(free_rec);
1283
 
                page_mem_alloc_free(page, page_zip,
1284
 
                                    rec_get_next_ptr(free_rec, TRUE),
1285
 
                                    rec_size);
1286
 
 
1287
 
                if (UNIV_LIKELY_NULL(heap)) {
1288
 
                        mem_heap_free(heap);
1289
 
                }
1290
 
        } else {
1291
 
use_heap:
1292
 
                free_rec = NULL;
1293
 
                insert_buf = page_mem_alloc_heap(page, page_zip,
1294
 
                                                 rec_size, &heap_no);
1295
 
 
1296
 
                if (UNIV_UNLIKELY(insert_buf == NULL)) {
1297
 
                        return(NULL);
1298
 
                }
1299
 
 
1300
 
                page_zip_dir_add_slot(page_zip, dict_index_is_clust(index));
1301
 
        }
1302
 
 
1303
 
        /* 3. Create the record */
1304
 
        insert_rec = rec_copy(insert_buf, rec, offsets);
1305
 
        rec_offs_make_valid(insert_rec, index, offsets);
1306
 
 
1307
 
        /* 4. Insert the record in the linked list of records */
1308
 
        ut_ad(*current_rec != insert_rec);
1309
 
 
1310
 
        {
1311
 
                /* next record after current before the insertion */
1312
 
                rec_t*  next_rec = page_rec_get_next(*current_rec);
1313
 
                ut_ad(rec_get_status(*current_rec)
1314
 
                      <= REC_STATUS_INFIMUM);
1315
 
                ut_ad(rec_get_status(insert_rec) < REC_STATUS_INFIMUM);
1316
 
                ut_ad(rec_get_status(next_rec) != REC_STATUS_INFIMUM);
1317
 
 
1318
 
                page_rec_set_next(insert_rec, next_rec);
1319
 
                page_rec_set_next(*current_rec, insert_rec);
1320
 
        }
1321
 
 
1322
 
        page_header_set_field(page, page_zip, PAGE_N_RECS,
1323
 
                              1 + page_get_n_recs(page));
1324
 
 
1325
 
        /* 5. Set the n_owned field in the inserted record to zero,
1326
 
        and set the heap_no field */
1327
 
        rec_set_n_owned_new(insert_rec, NULL, 0);
1328
 
        rec_set_heap_no_new(insert_rec, heap_no);
1329
 
 
1330
 
        UNIV_MEM_ASSERT_RW(rec_get_start(insert_rec, offsets),
1331
 
                           rec_offs_size(offsets));
1332
 
 
1333
 
        page_zip_dir_insert(page_zip, *current_rec, free_rec, insert_rec);
1334
 
 
1335
 
        /* 6. Update the last insertion info in page header */
1336
 
 
1337
 
        last_insert = page_header_get_ptr(page, PAGE_LAST_INSERT);
1338
 
        ut_ad(!last_insert
1339
 
              || rec_get_node_ptr_flag(last_insert)
1340
 
              == rec_get_node_ptr_flag(insert_rec));
1341
 
 
1342
 
        if (UNIV_UNLIKELY(last_insert == NULL)) {
1343
 
                page_header_set_field(page, page_zip, PAGE_DIRECTION,
1344
 
                                                        PAGE_NO_DIRECTION);
1345
 
                page_header_set_field(page, page_zip, PAGE_N_DIRECTION, 0);
1346
 
 
1347
 
        } else if ((last_insert == *current_rec)
1348
 
                   && (page_header_get_field(page, PAGE_DIRECTION)
1349
 
                       != PAGE_LEFT)) {
1350
 
 
1351
 
                page_header_set_field(page, page_zip, PAGE_DIRECTION,
1352
 
                                                        PAGE_RIGHT);
1353
 
                page_header_set_field(page, page_zip, PAGE_N_DIRECTION,
1354
 
                                      page_header_get_field(
1355
 
                                              page, PAGE_N_DIRECTION) + 1);
1356
 
 
1357
 
        } else if ((page_rec_get_next(insert_rec) == last_insert)
1358
 
                   && (page_header_get_field(page, PAGE_DIRECTION)
1359
 
                       != PAGE_RIGHT)) {
1360
 
 
1361
 
                page_header_set_field(page, page_zip, PAGE_DIRECTION,
1362
 
                                                        PAGE_LEFT);
1363
 
                page_header_set_field(page, page_zip, PAGE_N_DIRECTION,
1364
 
                                      page_header_get_field(
1365
 
                                              page, PAGE_N_DIRECTION) + 1);
1366
 
        } else {
1367
 
                page_header_set_field(page, page_zip, PAGE_DIRECTION,
1368
 
                                                        PAGE_NO_DIRECTION);
1369
 
                page_header_set_field(page, page_zip, PAGE_N_DIRECTION, 0);
1370
 
        }
1371
 
 
1372
 
        page_header_set_ptr(page, page_zip, PAGE_LAST_INSERT, insert_rec);
1373
 
 
1374
 
        /* 7. It remains to update the owner record. */
1375
 
        {
1376
 
                rec_t*  owner_rec       = page_rec_find_owner_rec(insert_rec);
1377
 
                ulint   n_owned;
1378
 
 
1379
 
                n_owned = rec_get_n_owned_new(owner_rec);
1380
 
                rec_set_n_owned_new(owner_rec, page_zip, n_owned + 1);
1381
 
 
1382
 
                /* 8. Now we have incremented the n_owned field of the owner
1383
 
                record. If the number exceeds PAGE_DIR_SLOT_MAX_N_OWNED,
1384
 
                we have to split the corresponding directory slot in two. */
1385
 
 
1386
 
                if (UNIV_UNLIKELY(n_owned == PAGE_DIR_SLOT_MAX_N_OWNED)) {
1387
 
                        page_dir_split_slot(
1388
 
                                page, page_zip,
1389
 
                                page_dir_find_owner_slot(owner_rec));
1390
 
                }
1391
 
        }
1392
 
 
1393
 
        page_zip_write_rec(page_zip, insert_rec, index, offsets, 1);
1394
 
 
1395
 
        /* 9. Write log record of the insert */
1396
 
        if (UNIV_LIKELY(mtr != NULL)) {
1397
 
                page_cur_insert_rec_write_log(insert_rec, rec_size,
1398
 
                                              *current_rec, index, mtr);
1399
 
        }
1400
 
 
 
978
                page_header_set_field(page, PAGE_DIRECTION, PAGE_RIGHT);
 
979
                page_header_set_field(page, PAGE_N_DIRECTION,
 
980
                                      page_header_get_field(
 
981
                                              page, PAGE_N_DIRECTION) + 1);
 
982
 
 
983
        } else if ((page_rec_get_next(insert_rec) == last_insert)
 
984
                   && (page_header_get_field(page, PAGE_DIRECTION)
 
985
                       != PAGE_RIGHT)) {
 
986
 
 
987
                page_header_set_field(page, PAGE_DIRECTION, PAGE_LEFT);
 
988
                page_header_set_field(page, PAGE_N_DIRECTION,
 
989
                                      page_header_get_field(
 
990
                                              page, PAGE_N_DIRECTION) + 1);
 
991
        } else {
 
992
                page_header_set_field(page, PAGE_DIRECTION, PAGE_NO_DIRECTION);
 
993
                page_header_set_field(page, PAGE_N_DIRECTION, 0);
 
994
        }
 
995
 
 
996
        page_header_set_ptr(page, PAGE_LAST_INSERT, insert_rec);
 
997
 
 
998
        /* 7. It remains to update the owner record. */
 
999
 
 
1000
        owner_rec = page_rec_find_owner_rec(insert_rec);
 
1001
        n_owned = rec_get_n_owned(owner_rec, comp);
 
1002
        rec_set_n_owned(owner_rec, comp, n_owned + 1);
 
1003
 
 
1004
        /* 8. Now we have incremented the n_owned field of the owner
 
1005
        record. If the number exceeds PAGE_DIR_SLOT_MAX_N_OWNED,
 
1006
        we have to split the corresponding directory slot in two. */
 
1007
 
 
1008
        if (n_owned == PAGE_DIR_SLOT_MAX_N_OWNED) {
 
1009
                owner_slot = page_dir_find_owner_slot(owner_rec);
 
1010
                page_dir_split_slot(page, owner_slot);
 
1011
        }
 
1012
 
 
1013
        /* 9. Write log record of the insert */
 
1014
        page_cur_insert_rec_write_log(insert_rec, rec_size, current_rec,
 
1015
                                      index, mtr);
 
1016
 
 
1017
        if (UNIV_LIKELY_NULL(heap)) {
 
1018
                mem_heap_free(heap);
 
1019
        }
1401
1020
        return(insert_rec);
1402
1021
}
1403
1022
 
1408
1027
page_copy_rec_list_to_created_page_write_log(
1409
1028
/*=========================================*/
1410
1029
                                /* out: 4-byte field where to
1411
 
                                write the log data length,
1412
 
                                or NULL if logging is disabled */
 
1030
                                write the log data length */
1413
1031
        page_t*         page,   /* in: index page */
1414
1032
        dict_index_t*   index,  /* in: record descriptor */
1415
1033
        mtr_t*          mtr)    /* in: mtr */
1422
1040
                                            page_is_comp(page)
1423
1041
                                            ? MLOG_COMP_LIST_END_COPY_CREATED
1424
1042
                                            : MLOG_LIST_END_COPY_CREATED, 4);
1425
 
        if (UNIV_LIKELY(log_ptr != NULL)) {
1426
 
                mlog_close(mtr, log_ptr + 4);
1427
 
        }
 
1043
        ut_a(log_ptr);
 
1044
        mlog_close(mtr, log_ptr + 4);
1428
1045
 
1429
1046
        return(log_ptr);
1430
1047
}
1431
1048
 
1432
1049
/**************************************************************
1433
1050
Parses a log record of copying a record list end to a new created page. */
1434
 
UNIV_INTERN
 
1051
 
1435
1052
byte*
1436
1053
page_parse_copy_rec_list_to_created_page(
1437
1054
/*=====================================*/
1438
1055
                                /* out: end of log record or NULL */
1439
1056
        byte*           ptr,    /* in: buffer */
1440
1057
        byte*           end_ptr,/* in: buffer end */
1441
 
        buf_block_t*    block,  /* in: page or NULL */
1442
1058
        dict_index_t*   index,  /* in: record descriptor */
 
1059
        page_t*         page,   /* in: page or NULL */
1443
1060
        mtr_t*          mtr)    /* in: mtr or NULL */
1444
1061
{
1445
 
        byte*           rec_end;
1446
 
        ulint           log_data_len;
1447
 
        page_t*         page;
1448
 
        page_zip_des_t* page_zip;
 
1062
        byte*   rec_end;
 
1063
        ulint   log_data_len;
1449
1064
 
1450
1065
        if (ptr + 4 > end_ptr) {
1451
1066
 
1462
1077
                return(NULL);
1463
1078
        }
1464
1079
 
1465
 
        if (!block) {
 
1080
        if (!page) {
1466
1081
 
1467
1082
                return(rec_end);
1468
1083
        }
1469
1084
 
1470
1085
        while (ptr < rec_end) {
1471
1086
                ptr = page_cur_parse_insert_rec(TRUE, ptr, end_ptr,
1472
 
                                                block, index, mtr);
 
1087
                                                index, page, mtr);
1473
1088
        }
1474
1089
 
1475
1090
        ut_a(ptr == rec_end);
1476
1091
 
1477
 
        page = buf_block_get_frame(block);
1478
 
        page_zip = buf_block_get_page_zip(block);
1479
 
 
1480
 
        page_header_set_ptr(page, page_zip, PAGE_LAST_INSERT, NULL);
1481
 
        page_header_set_field(page, page_zip, PAGE_DIRECTION,
1482
 
                                                        PAGE_NO_DIRECTION);
1483
 
        page_header_set_field(page, page_zip, PAGE_N_DIRECTION, 0);
 
1092
        page_header_set_ptr(page, PAGE_LAST_INSERT, NULL);
 
1093
        page_header_set_field(page, PAGE_DIRECTION, PAGE_NO_DIRECTION);
 
1094
        page_header_set_field(page, PAGE_N_DIRECTION, 0);
1484
1095
 
1485
1096
        return(rec_end);
1486
1097
}
1488
1099
/*****************************************************************
1489
1100
Copies records from page to a newly created page, from a given record onward,
1490
1101
including that record. Infimum and supremum records are not copied. */
1491
 
UNIV_INTERN
 
1102
 
1492
1103
void
1493
1104
page_copy_rec_list_end_to_created_page(
1494
1105
/*===================================*/
1495
 
        page_t*         new_page,       /* in/out: index page to copy to */
 
1106
        page_t*         new_page,       /* in: index page to copy to */
 
1107
        page_t*         page,           /* in: index page */
1496
1108
        rec_t*          rec,            /* in: first record to copy */
1497
1109
        dict_index_t*   index,          /* in: record descriptor */
1498
1110
        mtr_t*          mtr)            /* in: mtr */
1508
1120
        ulint   log_mode;
1509
1121
        byte*   log_ptr;
1510
1122
        ulint   log_data_len;
 
1123
        ulint           comp            = page_is_comp(page);
1511
1124
        mem_heap_t*     heap            = NULL;
1512
1125
        ulint           offsets_[REC_OFFS_NORMAL_SIZE];
1513
1126
        ulint*          offsets         = offsets_;
1514
 
        rec_offs_init(offsets_);
1515
 
 
1516
 
        ut_ad(page_dir_get_n_heap(new_page) == PAGE_HEAP_NO_USER_LOW);
1517
 
        ut_ad(page_align(rec) != new_page);
1518
 
        ut_ad(page_rec_is_comp(rec) == page_is_comp(new_page));
1519
 
 
1520
 
        if (page_rec_is_infimum(rec)) {
 
1127
        *offsets_ = (sizeof offsets_) / sizeof *offsets_;
 
1128
 
 
1129
        ut_ad(page_dir_get_n_heap(new_page) == 2);
 
1130
        ut_ad(page != new_page);
 
1131
        ut_ad(comp == page_is_comp(new_page));
 
1132
 
 
1133
        if (rec == page_get_infimum_rec(page)) {
1521
1134
 
1522
1135
                rec = page_rec_get_next(rec);
1523
1136
        }
1524
1137
 
1525
 
        if (page_rec_is_supremum(rec)) {
 
1138
        if (rec == page_get_supremum_rec(page)) {
1526
1139
 
1527
1140
                return;
1528
1141
        }
1530
1143
#ifdef UNIV_DEBUG
1531
1144
        /* To pass the debug tests we have to set these dummy values
1532
1145
        in the debug version */
1533
 
        page_dir_set_n_slots(new_page, NULL, UNIV_PAGE_SIZE / 2);
1534
 
        page_header_set_ptr(new_page, NULL, PAGE_HEAP_TOP,
 
1146
        page_dir_set_n_slots(new_page, UNIV_PAGE_SIZE / 2);
 
1147
        page_header_set_ptr(new_page, PAGE_HEAP_TOP,
1535
1148
                            new_page + UNIV_PAGE_SIZE - 1);
1536
1149
#endif
1537
1150
 
1545
1158
        log_mode = mtr_set_log_mode(mtr, MTR_LOG_SHORT_INSERTS);
1546
1159
 
1547
1160
        prev_rec = page_get_infimum_rec(new_page);
1548
 
        if (page_is_comp(new_page)) {
 
1161
        if (comp) {
1549
1162
                heap_top = new_page + PAGE_NEW_SUPREMUM_END;
1550
1163
        } else {
1551
1164
                heap_top = new_page + PAGE_OLD_SUPREMUM_END;
1554
1167
        slot_index = 0;
1555
1168
        n_recs = 0;
1556
1169
 
1557
 
        do {
 
1170
        /* should be do ... until, comment by Jani */
 
1171
        while (rec != page_get_supremum_rec(page)) {
1558
1172
                offsets = rec_get_offsets(rec, index, offsets,
1559
1173
                                          ULINT_UNDEFINED, &heap);
1560
1174
                insert_rec = rec_copy(heap_top, rec, offsets);
1561
1175
 
1562
 
                if (page_is_comp(new_page)) {
1563
 
                        rec_set_next_offs_new(prev_rec,
1564
 
                                              page_offset(insert_rec));
1565
 
 
1566
 
                        rec_set_n_owned_new(insert_rec, NULL, 0);
1567
 
                        rec_set_heap_no_new(insert_rec,
1568
 
                                            PAGE_HEAP_NO_USER_LOW + n_recs);
1569
 
                } else {
1570
 
                        rec_set_next_offs_old(prev_rec,
1571
 
                                              page_offset(insert_rec));
1572
 
 
1573
 
                        rec_set_n_owned_old(insert_rec, 0);
1574
 
                        rec_set_heap_no_old(insert_rec,
1575
 
                                            PAGE_HEAP_NO_USER_LOW + n_recs);
1576
 
                }
 
1176
                rec_set_next_offs(prev_rec, comp, insert_rec - new_page);
 
1177
 
 
1178
                rec_set_n_owned(insert_rec, comp, 0);
 
1179
                rec_set_heap_no(insert_rec, comp, 2 + n_recs);
 
1180
 
 
1181
                rec_size = rec_offs_size(offsets);
 
1182
 
 
1183
                heap_top = heap_top + rec_size;
 
1184
 
 
1185
                ut_ad(heap_top < new_page + UNIV_PAGE_SIZE);
1577
1186
 
1578
1187
                count++;
1579
1188
                n_recs++;
1580
1189
 
1581
 
                if (UNIV_UNLIKELY
1582
 
                    (count == (PAGE_DIR_SLOT_MAX_N_OWNED + 1) / 2)) {
 
1190
                if (count == (PAGE_DIR_SLOT_MAX_N_OWNED + 1) / 2) {
1583
1191
 
1584
1192
                        slot_index++;
1585
1193
 
1586
1194
                        slot = page_dir_get_nth_slot(new_page, slot_index);
1587
1195
 
1588
1196
                        page_dir_slot_set_rec(slot, insert_rec);
1589
 
                        page_dir_slot_set_n_owned(slot, NULL, count);
 
1197
                        page_dir_slot_set_n_owned(slot, count);
1590
1198
 
1591
1199
                        count = 0;
1592
1200
                }
1593
1201
 
1594
 
                rec_size = rec_offs_size(offsets);
1595
 
 
1596
 
                ut_ad(heap_top < new_page + UNIV_PAGE_SIZE);
1597
 
 
1598
 
                heap_top += rec_size;
1599
 
 
1600
1202
                page_cur_insert_rec_write_log(insert_rec, rec_size, prev_rec,
1601
1203
                                              index, mtr);
1602
1204
                prev_rec = insert_rec;
1603
1205
                rec = page_rec_get_next(rec);
1604
 
        } while (!page_rec_is_supremum(rec));
 
1206
        }
1605
1207
 
1606
1208
        if ((slot_index > 0) && (count + 1
1607
1209
                                 + (PAGE_DIR_SLOT_MAX_N_OWNED + 1) / 2
1615
1217
 
1616
1218
                count += (PAGE_DIR_SLOT_MAX_N_OWNED + 1) / 2;
1617
1219
 
1618
 
                page_dir_slot_set_n_owned(slot, NULL, 0);
 
1220
                page_dir_slot_set_n_owned(slot, 0);
1619
1221
 
1620
1222
                slot_index--;
1621
1223
        }
1628
1230
 
1629
1231
        ut_a(log_data_len < 100 * UNIV_PAGE_SIZE);
1630
1232
 
1631
 
        if (UNIV_LIKELY(log_ptr != NULL)) {
1632
 
                mach_write_to_4(log_ptr, log_data_len);
1633
 
        }
 
1233
        mach_write_to_4(log_ptr, log_data_len);
1634
1234
 
1635
 
        if (page_is_comp(new_page)) {
1636
 
                rec_set_next_offs_new(insert_rec, PAGE_NEW_SUPREMUM);
1637
 
        } else {
1638
 
                rec_set_next_offs_old(insert_rec, PAGE_OLD_SUPREMUM);
1639
 
        }
 
1235
        rec_set_next_offs(insert_rec, comp,
 
1236
                          comp ? PAGE_NEW_SUPREMUM : PAGE_OLD_SUPREMUM);
1640
1237
 
1641
1238
        slot = page_dir_get_nth_slot(new_page, 1 + slot_index);
1642
1239
 
1643
1240
        page_dir_slot_set_rec(slot, page_get_supremum_rec(new_page));
1644
 
        page_dir_slot_set_n_owned(slot, NULL, count + 1);
1645
 
 
1646
 
        page_dir_set_n_slots(new_page, NULL, 2 + slot_index);
1647
 
        page_header_set_ptr(new_page, NULL, PAGE_HEAP_TOP, heap_top);
1648
 
        page_dir_set_n_heap(new_page, NULL, PAGE_HEAP_NO_USER_LOW + n_recs);
1649
 
        page_header_set_field(new_page, NULL, PAGE_N_RECS, n_recs);
1650
 
 
1651
 
        page_header_set_ptr(new_page, NULL, PAGE_LAST_INSERT, NULL);
1652
 
        page_header_set_field(new_page, NULL, PAGE_DIRECTION,
1653
 
                                                        PAGE_NO_DIRECTION);
1654
 
        page_header_set_field(new_page, NULL, PAGE_N_DIRECTION, 0);
 
1241
        page_dir_slot_set_n_owned(slot, count + 1);
 
1242
 
 
1243
        page_dir_set_n_slots(new_page, 2 + slot_index);
 
1244
        page_header_set_ptr(new_page, PAGE_HEAP_TOP, heap_top);
 
1245
        page_dir_set_n_heap(new_page, 2 + n_recs);
 
1246
        page_header_set_field(new_page, PAGE_N_RECS, n_recs);
 
1247
 
 
1248
        page_header_set_ptr(new_page, PAGE_LAST_INSERT, NULL);
 
1249
        page_header_set_field(new_page, PAGE_DIRECTION, PAGE_NO_DIRECTION);
 
1250
        page_header_set_field(new_page, PAGE_N_DIRECTION, 0);
1655
1251
 
1656
1252
        /* Restore the log mode */
1657
1253
 
1691
1287
 
1692
1288
/***************************************************************
1693
1289
Parses log record of a record delete on a page. */
1694
 
UNIV_INTERN
 
1290
 
1695
1291
byte*
1696
1292
page_cur_parse_delete_rec(
1697
1293
/*======================*/
1698
1294
                                /* out: pointer to record end or NULL */
1699
1295
        byte*           ptr,    /* in: buffer */
1700
1296
        byte*           end_ptr,/* in: buffer end */
1701
 
        buf_block_t*    block,  /* in: page or NULL */
1702
1297
        dict_index_t*   index,  /* in: record descriptor */
 
1298
        page_t*         page,   /* in: page or NULL */
1703
1299
        mtr_t*          mtr)    /* in: mtr or NULL */
1704
1300
{
1705
1301
        ulint           offset;
1716
1312
 
1717
1313
        ut_a(offset <= UNIV_PAGE_SIZE);
1718
1314
 
1719
 
        if (block) {
1720
 
                page_t*         page            = buf_block_get_frame(block);
 
1315
        if (page) {
1721
1316
                mem_heap_t*     heap            = NULL;
1722
1317
                ulint           offsets_[REC_OFFS_NORMAL_SIZE];
1723
1318
                rec_t*          rec             = page + offset;
1724
 
                rec_offs_init(offsets_);
 
1319
                *offsets_ = (sizeof offsets_) / sizeof *offsets_;
1725
1320
 
1726
 
                page_cur_position(rec, block, &cursor);
1727
 
                ut_ad(!buf_block_get_page_zip(block) || page_is_comp(page));
 
1321
                page_cur_position(rec, &cursor);
1728
1322
 
1729
1323
                page_cur_delete_rec(&cursor, index,
1730
1324
                                    rec_get_offsets(rec, index, offsets_,
1741
1335
/***************************************************************
1742
1336
Deletes a record at the page cursor. The cursor is moved to the next
1743
1337
record after the deleted one. */
1744
 
UNIV_INTERN
 
1338
 
1745
1339
void
1746
1340
page_cur_delete_rec(
1747
1341
/*================*/
1748
 
        page_cur_t*     cursor, /* in/out: a page cursor */
 
1342
        page_cur_t*     cursor, /* in: a page cursor */
1749
1343
        dict_index_t*   index,  /* in: record descriptor */
1750
1344
        const ulint*    offsets,/* in: rec_get_offsets(cursor->rec, index) */
1751
1345
        mtr_t*          mtr)    /* in: mini-transaction handle */
1753
1347
        page_dir_slot_t* cur_dir_slot;
1754
1348
        page_dir_slot_t* prev_slot;
1755
1349
        page_t*         page;
1756
 
        page_zip_des_t* page_zip;
1757
1350
        rec_t*          current_rec;
1758
1351
        rec_t*          prev_rec        = NULL;
1759
1352
        rec_t*          next_rec;
1764
1357
        ut_ad(cursor && mtr);
1765
1358
 
1766
1359
        page = page_cur_get_page(cursor);
1767
 
        page_zip = page_cur_get_page_zip(cursor);
1768
 
        /* page_zip_validate() may fail here when
1769
 
        btr_cur_pessimistic_delete() invokes btr_set_min_rec_mark(). */
1770
1360
        current_rec = cursor->rec;
1771
1361
        ut_ad(rec_offs_validate(current_rec, index, offsets));
1772
1362
        ut_ad(!!page_is_comp(page) == dict_table_is_comp(index->table));
1773
1363
 
1774
1364
        /* The record must not be the supremum or infimum record. */
1775
 
        ut_ad(page_rec_is_user_rec(current_rec));
 
1365
        ut_ad(current_rec != page_get_supremum_rec(page));
 
1366
        ut_ad(current_rec != page_get_infimum_rec(page));
1776
1367
 
1777
1368
        /* Save to local variables some data associated with current_rec */
1778
1369
        cur_slot_no = page_dir_find_owner_slot(current_rec);
1785
1376
        /* 1. Reset the last insert info in the page header and increment
1786
1377
        the modify clock for the frame */
1787
1378
 
1788
 
        page_header_set_ptr(page, page_zip, PAGE_LAST_INSERT, NULL);
 
1379
        page_header_set_ptr(page, PAGE_LAST_INSERT, NULL);
1789
1380
 
1790
1381
        /* The page gets invalid for optimistic searches: increment the
1791
1382
        frame modify clock */
1792
1383
 
1793
 
        buf_block_modify_clock_inc(page_cur_get_block(cursor));
 
1384
        buf_frame_modify_clock_inc(page);
1794
1385
 
1795
1386
        /* 2. Find the next and the previous record. Note that the cursor is
1796
1387
        left at the next record. */
1798
1389
        ut_ad(cur_slot_no > 0);
1799
1390
        prev_slot = page_dir_get_nth_slot(page, cur_slot_no - 1);
1800
1391
 
1801
 
        rec = (rec_t*) page_dir_slot_get_rec(prev_slot);
 
1392
        rec = page_dir_slot_get_rec(prev_slot);
1802
1393
 
1803
1394
        /* rec now points to the record of the previous directory slot. Look
1804
1395
        for the immediate predecessor of current_rec in a loop. */
1814
1405
        /* 3. Remove the record from the linked list of records */
1815
1406
 
1816
1407
        page_rec_set_next(prev_rec, next_rec);
 
1408
        page_header_set_field(page, PAGE_N_RECS,
 
1409
                              (ulint)(page_get_n_recs(page) - 1));
1817
1410
 
1818
1411
        /* 4. If the deleted record is pointed to by a dir slot, update the
1819
1412
        record pointer in slot. In the following if-clause we assume that
1831
1424
 
1832
1425
        /* 5. Update the number of owned records of the slot */
1833
1426
 
1834
 
        page_dir_slot_set_n_owned(cur_dir_slot, page_zip, cur_n_owned - 1);
 
1427
        page_dir_slot_set_n_owned(cur_dir_slot, cur_n_owned - 1);
1835
1428
 
1836
1429
        /* 6. Free the memory occupied by the record */
1837
 
        page_mem_free(page, page_zip, current_rec, index, offsets);
 
1430
        page_mem_free(page, current_rec, offsets);
1838
1431
 
1839
1432
        /* 7. Now we have decremented the number of owned records of the slot.
1840
1433
        If the number drops below PAGE_DIR_SLOT_MIN_N_OWNED, we balance the
1841
1434
        slots. */
1842
1435
 
1843
 
        if (UNIV_UNLIKELY(cur_n_owned <= PAGE_DIR_SLOT_MIN_N_OWNED)) {
1844
 
                page_dir_balance_slot(page, page_zip, cur_slot_no);
 
1436
        if (cur_n_owned <= PAGE_DIR_SLOT_MIN_N_OWNED) {
 
1437
                page_dir_balance_slot(page, cur_slot_no);
1845
1438
        }
1846
 
 
1847
 
#ifdef UNIV_ZIP_DEBUG
1848
 
        ut_a(!page_zip || page_zip_validate(page_zip, page));
1849
 
#endif /* UNIV_ZIP_DEBUG */
1850
1439
}