~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/innobase/btr/btr0cur.c

  • Committer: Stewart Smith
  • Date: 2010-11-03 03:28:23 UTC
  • mto: (1902.1.1 build) (1910.1.2 build)
  • mto: This revision was merged to the branch mainline in revision 1903.
  • Revision ID: stewart@flamingspork.com-20101103032823-44k21f0njmk97omr
fix docs warning: Title underline (and overline) is too short in brief_history_of_drizzle.rst

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*****************************************************************************
2
2
 
3
 
Copyright (C) 1994, 2010, Innobase Oy. All Rights Reserved.
4
 
Copyright (C) 2008, Google Inc.
 
3
Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
 
4
Copyright (c) 2008, Google Inc.
5
5
 
6
6
Portions of this file contain modifications contributed and copyrighted by
7
7
Google, Inc. Those modifications are gratefully acknowledged and are described
57
57
#include "buf0lru.h"
58
58
#include "btr0btr.h"
59
59
#include "btr0sea.h"
60
 
#include "row0purge.h"
61
 
#include "row0upd.h"
62
60
#include "trx0rec.h"
63
61
#include "trx0roll.h" /* trx_is_recv() */
64
62
#include "que0que.h"
68
66
#include "lock0lock.h"
69
67
#include "zlib.h"
70
68
 
71
 
/** Buffered B-tree operation types, introduced as part of delete buffering. */
72
 
typedef enum btr_op_enum {
73
 
        BTR_NO_OP = 0,                  /*!< Not buffered */
74
 
        BTR_INSERT_OP,                  /*!< Insert, do not ignore UNIQUE */
75
 
        BTR_INSERT_IGNORE_UNIQUE_OP,    /*!< Insert, ignoring UNIQUE */
76
 
        BTR_DELETE_OP,                  /*!< Purge a delete-marked record */
77
 
        BTR_DELMARK_OP                  /*!< Mark a record for deletion */
78
 
} btr_op_t;
79
 
 
80
69
#ifdef UNIV_DEBUG
81
70
/** If the following is set to TRUE, this module prints a lot of
82
71
trace information of individual record operations */
117
106
/** A BLOB field reference full of zero, for use in assertions and tests.
118
107
Initially, BLOB field references are set to zero, in
119
108
dtuple_convert_big_rec(). */
120
 
const byte field_ref_zero[BTR_EXTERN_FIELD_REF_SIZE]= {0};
 
109
UNIV_INTERN const byte field_ref_zero[BTR_EXTERN_FIELD_REF_SIZE]= {0};
121
110
 
122
111
#ifndef UNIV_HOTBACKUP
123
112
/*******************************************************************//**
339
328
                                Inserts should always be made using
340
329
                                PAGE_CUR_LE to search the position! */
341
330
        ulint           latch_mode, /*!< in: BTR_SEARCH_LEAF, ..., ORed with
342
 
                                at most one of BTR_INSERT, BTR_DELETE_MARK,
343
 
                                BTR_DELETE, or BTR_ESTIMATE;
 
331
                                BTR_INSERT and BTR_ESTIMATE;
344
332
                                cursor->left_block is used to store a pointer
345
333
                                to the left neighbor page, in the cases
346
334
                                BTR_SEARCH_PREV and BTR_MODIFY_PREV;
354
342
        ulint           has_search_latch,/*!< in: info on the latch mode the
355
343
                                caller currently has on btr_search_latch:
356
344
                                RW_S_LATCH, or 0 */
357
 
        const char*     file,   /*!< in: file name */
358
 
        ulint           line,   /*!< in: line where called */
359
345
        mtr_t*          mtr)    /*!< in: mtr */
360
346
{
 
347
        page_cur_t*     page_cursor;
361
348
        page_t*         page;
362
 
        buf_block_t*    block;
363
 
        ulint           space;
364
349
        buf_block_t*    guess;
365
 
        ulint           height;
 
350
        rec_t*          node_ptr;
366
351
        ulint           page_no;
 
352
        ulint           space;
367
353
        ulint           up_match;
368
354
        ulint           up_bytes;
369
355
        ulint           low_match;
370
356
        ulint           low_bytes;
 
357
        ulint           height;
371
358
        ulint           savepoint;
372
 
        ulint           rw_latch;
373
359
        ulint           page_mode;
374
 
        ulint           buf_mode;
 
360
        ulint           insert_planned;
375
361
        ulint           estimate;
376
 
        ulint           zip_size;
377
 
        page_cur_t*     page_cursor;
378
 
        btr_op_t        btr_op;
 
362
        ulint           ignore_sec_unique;
379
363
        ulint           root_height = 0; /* remove warning */
380
 
 
381
364
#ifdef BTR_CUR_ADAPT
382
365
        btr_search_t*   info;
383
366
#endif
397
380
        cursor->up_match = ULINT_UNDEFINED;
398
381
        cursor->low_match = ULINT_UNDEFINED;
399
382
#endif
400
 
 
401
 
        /* These flags are mutually exclusive, they are lumped together
402
 
        with the latch mode for historical reasons. It's possible for
403
 
        none of the flags to be set. */
404
 
        switch (UNIV_EXPECT(latch_mode
405
 
                            & (BTR_INSERT | BTR_DELETE | BTR_DELETE_MARK),
406
 
                            0)) {
407
 
        case 0:
408
 
                btr_op = BTR_NO_OP;
409
 
                break;
410
 
        case BTR_INSERT:
411
 
                btr_op = (latch_mode & BTR_IGNORE_SEC_UNIQUE)
412
 
                        ? BTR_INSERT_IGNORE_UNIQUE_OP
413
 
                        : BTR_INSERT_OP;
414
 
                break;
415
 
        case BTR_DELETE:
416
 
                btr_op = BTR_DELETE_OP;
417
 
                ut_a(cursor->purge_node);
418
 
                break;
419
 
        case BTR_DELETE_MARK:
420
 
                btr_op = BTR_DELMARK_OP;
421
 
                break;
422
 
        default:
423
 
                /* only one of BTR_INSERT, BTR_DELETE, BTR_DELETE_MARK
424
 
                should be specified at a time */
425
 
                ut_error;
426
 
        }
427
 
 
428
 
        /* Operations on the insert buffer tree cannot be buffered. */
429
 
        ut_ad(btr_op == BTR_NO_OP || !dict_index_is_ibuf(index));
430
 
        /* Operations on the clustered index cannot be buffered. */
431
 
        ut_ad(btr_op == BTR_NO_OP || !dict_index_is_clust(index));
432
 
 
 
383
        insert_planned = latch_mode & BTR_INSERT;
433
384
        estimate = latch_mode & BTR_ESTIMATE;
 
385
        ignore_sec_unique = latch_mode & BTR_IGNORE_SEC_UNIQUE;
 
386
        latch_mode = latch_mode & ~(BTR_INSERT | BTR_ESTIMATE
 
387
                                    | BTR_IGNORE_SEC_UNIQUE);
434
388
 
435
 
        /* Turn the flags unrelated to the latch mode off. */
436
 
        latch_mode &= ~(BTR_INSERT
437
 
                        | BTR_DELETE_MARK
438
 
                        | BTR_DELETE
439
 
                        | BTR_ESTIMATE
440
 
                        | BTR_IGNORE_SEC_UNIQUE);
 
389
        ut_ad(!insert_planned || (mode == PAGE_CUR_LE));
441
390
 
442
391
        cursor->flag = BTR_CUR_BINARY;
443
392
        cursor->index = index;
444
393
 
445
 
        cursor->ibuf_cnt = ULINT_UNDEFINED;
446
 
 
447
394
#ifndef BTR_CUR_ADAPT
448
395
        guess = NULL;
449
396
#else
457
404
        info->n_searches++;
458
405
#endif
459
406
        if (rw_lock_get_writer(&btr_search_latch) == RW_LOCK_NOT_LOCKED
460
 
            && latch_mode <= BTR_MODIFY_LEAF
461
 
            && info->last_hash_succ
 
407
            && latch_mode <= BTR_MODIFY_LEAF && info->last_hash_succ
462
408
            && !estimate
463
409
#ifdef PAGE_CUR_LE_OR_EXTENDS
464
410
            && mode != PAGE_CUR_LE_OR_EXTENDS
547
493
 
548
494
        /* Loop and search until we arrive at the desired level */
549
495
 
550
 
search_loop:
551
 
        buf_mode = BUF_GET;
552
 
        rw_latch = RW_NO_LATCH;
553
 
 
554
 
        if (height != 0) {
555
 
                /* We are about to fetch the root or a non-leaf page. */
556
 
        } else if (latch_mode <= BTR_MODIFY_LEAF) {
557
 
                rw_latch = latch_mode;
558
 
 
559
 
                if (btr_op != BTR_NO_OP
560
 
                    && ibuf_should_try(index, btr_op != BTR_INSERT_OP)) {
561
 
 
562
 
                        /* Try to buffer the operation if the leaf
563
 
                        page is not in the buffer pool. */
564
 
 
565
 
                        buf_mode = btr_op == BTR_DELETE_OP
566
 
                                ? BUF_GET_IF_IN_POOL_OR_WATCH
567
 
                                : BUF_GET_IF_IN_POOL;
 
496
        for (;;) {
 
497
                ulint           zip_size;
 
498
                buf_block_t*    block;
 
499
                ulint           rw_latch;
 
500
                ulint           buf_mode;
 
501
 
 
502
                zip_size = dict_table_zip_size(index->table);
 
503
                rw_latch = RW_NO_LATCH;
 
504
                buf_mode = BUF_GET;
 
505
 
 
506
                if (height == 0 && latch_mode <= BTR_MODIFY_LEAF) {
 
507
 
 
508
                        rw_latch = latch_mode;
 
509
 
 
510
                        if (insert_planned
 
511
                            && ibuf_should_try(index, ignore_sec_unique)) {
 
512
 
 
513
                                /* Try insert to the insert buffer if the
 
514
                                page is not in the buffer pool */
 
515
 
 
516
                                buf_mode = BUF_GET_IF_IN_POOL;
 
517
                        }
568
518
                }
569
 
        }
570
 
 
571
 
        zip_size = dict_table_zip_size(index->table);
572
519
 
573
520
retry_page_get:
574
 
        block = buf_page_get_gen(
575
 
                space, zip_size, page_no, rw_latch, guess, buf_mode,
576
 
                file, line, mtr);
577
 
 
578
 
        if (block == NULL) {
579
 
                /* This must be a search to perform an insert/delete
580
 
                mark/ delete; try using the insert/delete buffer */
581
 
 
582
 
                ut_ad(height == 0);
583
 
                ut_ad(cursor->thr);
584
 
 
585
 
                switch (btr_op) {
586
 
                case BTR_INSERT_OP:
587
 
                case BTR_INSERT_IGNORE_UNIQUE_OP:
 
521
                block = buf_page_get_gen(space, zip_size, page_no,
 
522
                                         rw_latch, guess, buf_mode,
 
523
                                         __FILE__, __LINE__, mtr);
 
524
                if (block == NULL) {
 
525
                        /* This must be a search to perform an insert;
 
526
                        try insert to the insert buffer */
 
527
 
588
528
                        ut_ad(buf_mode == BUF_GET_IF_IN_POOL);
589
 
 
590
 
                        if (ibuf_insert(IBUF_OP_INSERT, tuple, index,
591
 
                                        space, zip_size, page_no,
592
 
                                        cursor->thr)) {
593
 
 
 
529
                        ut_ad(insert_planned);
 
530
                        ut_ad(cursor->thr);
 
531
 
 
532
                        if (ibuf_insert(tuple, index, space, zip_size,
 
533
                                        page_no, cursor->thr)) {
 
534
                                /* Insertion to the insert buffer succeeded */
594
535
                                cursor->flag = BTR_CUR_INSERT_TO_IBUF;
595
 
 
596
 
                                goto func_exit;
597
 
                        }
598
 
                        break;
599
 
 
600
 
                case BTR_DELMARK_OP:
601
 
                        ut_ad(buf_mode == BUF_GET_IF_IN_POOL);
602
 
 
603
 
                        if (ibuf_insert(IBUF_OP_DELETE_MARK, tuple,
604
 
                                        index, space, zip_size,
605
 
                                        page_no, cursor->thr)) {
606
 
 
607
 
                                cursor->flag = BTR_CUR_DEL_MARK_IBUF;
608
 
 
609
 
                                goto func_exit;
610
 
                        }
611
 
 
612
 
                        break;
613
 
 
614
 
                case BTR_DELETE_OP:
615
 
                        ut_ad(buf_mode == BUF_GET_IF_IN_POOL_OR_WATCH);
616
 
 
617
 
                        if (!row_purge_poss_sec(cursor->purge_node,
618
 
                                                index, tuple)) {
619
 
 
620
 
                                /* The record cannot be purged yet. */
621
 
                                cursor->flag = BTR_CUR_DELETE_REF;
622
 
                        } else if (ibuf_insert(IBUF_OP_DELETE, tuple,
623
 
                                               index, space, zip_size,
624
 
                                               page_no,
625
 
                                               cursor->thr)) {
626
 
 
627
 
                                /* The purge was buffered. */
628
 
                                cursor->flag = BTR_CUR_DELETE_IBUF;
629
 
                        } else {
630
 
                                /* The purge could not be buffered. */
631
 
                                buf_pool_watch_unset(space, page_no);
632
 
                                break;
633
 
                        }
634
 
 
635
 
                        buf_pool_watch_unset(space, page_no);
636
 
                        goto func_exit;
637
 
 
638
 
                default:
639
 
                        ut_error;
640
 
                }
641
 
 
642
 
                /* Insert to the insert/delete buffer did not succeed, we
643
 
                must read the page from disk. */
644
 
 
645
 
                buf_mode = BUF_GET;
646
 
 
647
 
                goto retry_page_get;
648
 
        }
649
 
 
650
 
        block->check_index_page_at_flush = TRUE;
651
 
        page = buf_block_get_frame(block);
652
 
 
653
 
        if (rw_latch != RW_NO_LATCH) {
654
 
#ifdef UNIV_ZIP_DEBUG
655
 
                const page_zip_des_t*   page_zip
656
 
                        = buf_block_get_page_zip(block);
657
 
                ut_a(!page_zip || page_zip_validate(page_zip, page));
658
 
#endif /* UNIV_ZIP_DEBUG */
659
 
 
660
 
                buf_block_dbg_add_level(block, SYNC_TREE_NODE);
661
 
        }
662
 
 
663
 
        ut_ad(index->id == btr_page_get_index_id(page));
664
 
 
665
 
        if (UNIV_UNLIKELY(height == ULINT_UNDEFINED)) {
666
 
                /* We are in the root node */
667
 
 
668
 
                height = btr_page_get_level(page, mtr);
669
 
                root_height = height;
670
 
                cursor->tree_height = root_height + 1;
671
 
 
672
 
#ifdef BTR_CUR_ADAPT
673
 
                if (block != guess) {
674
 
                        info->root_guess = block;
675
 
                }
676
 
#endif
677
 
        }
678
 
 
679
 
        if (height == 0) {
680
 
                if (rw_latch == RW_NO_LATCH) {
681
 
 
682
 
                        btr_cur_latch_leaves(
683
 
                                page, space, zip_size, page_no, latch_mode,
684
 
                                cursor, mtr);
685
 
                }
686
 
 
687
 
                if (latch_mode != BTR_MODIFY_TREE
688
 
                    && latch_mode != BTR_CONT_MODIFY_TREE) {
689
 
 
690
 
                        /* Release the tree s-latch */
691
 
 
692
 
                        mtr_release_s_latch_at_savepoint(
693
 
                                mtr, savepoint, dict_index_get_lock(index));
694
 
                }
695
 
 
696
 
                page_mode = mode;
697
 
        }
698
 
 
699
 
        page_cur_search_with_match(
700
 
                block, index, tuple, page_mode, &up_match, &up_bytes,
701
 
                &low_match, &low_bytes, page_cursor);
702
 
 
703
 
        if (estimate) {
704
 
                btr_cur_add_path_info(cursor, height, root_height);
705
 
        }
706
 
 
707
 
        /* If this is the desired level, leave the loop */
708
 
 
709
 
        ut_ad(height == btr_page_get_level(page_cur_get_page(page_cursor),
710
 
                                           mtr));
711
 
 
712
 
        if (level != height) {
713
 
 
714
 
                const rec_t*    node_ptr;
715
 
                ut_ad(height > 0);
716
 
 
717
 
                height--;
718
 
                guess = NULL;
719
 
 
720
 
                node_ptr = page_cur_get_rec(page_cursor);
721
 
 
722
 
                offsets = rec_get_offsets(
723
 
                        node_ptr, index, offsets, ULINT_UNDEFINED, &heap);
724
 
 
725
 
                /* Go to the child node */
726
 
                page_no = btr_node_ptr_get_child_page_no(node_ptr, offsets);
727
 
 
728
 
                if (UNIV_UNLIKELY(height == 0 && dict_index_is_ibuf(index))) {
729
 
                        /* We're doing a search on an ibuf tree and we're one
730
 
                        level above the leaf page. */
731
 
 
732
 
                        ulint   is_min_rec;
733
 
 
734
 
                        ut_ad(level == 0);
735
 
 
736
 
                        is_min_rec = rec_get_info_bits(node_ptr, 0)
737
 
                                & REC_INFO_MIN_REC_FLAG;
738
 
 
739
 
                        if (!is_min_rec) {
740
 
                                cursor->ibuf_cnt
741
 
                                        = ibuf_rec_get_counter(node_ptr);
742
 
 
743
 
                                ut_a(cursor->ibuf_cnt <= 0xFFFF
744
 
                                     || cursor->ibuf_cnt == ULINT_UNDEFINED);
745
 
                        }
 
536
                                if (UNIV_LIKELY_NULL(heap)) {
 
537
                                        mem_heap_free(heap);
 
538
                                }
 
539
                                goto func_exit;
 
540
                        }
 
541
 
 
542
                        /* Insert to the insert buffer did not succeed:
 
543
                        retry page get */
746
544
 
747
545
                        buf_mode = BUF_GET;
748
 
                        rw_latch = RW_NO_LATCH;
 
546
 
749
547
                        goto retry_page_get;
750
548
                }
751
549
 
752
 
                goto search_loop;
753
 
        }
754
 
 
755
 
        if (level != 0) {
756
 
                /* x-latch the page */
757
 
                page = btr_page_get(
758
 
                        space, zip_size, page_no, RW_X_LATCH, mtr);
759
 
 
760
 
                ut_a((ibool)!!page_is_comp(page)
761
 
                     == dict_table_is_comp(index->table));
762
 
        } else {
 
550
                page = buf_block_get_frame(block);
 
551
 
 
552
                block->check_index_page_at_flush = TRUE;
 
553
 
 
554
                if (rw_latch != RW_NO_LATCH) {
 
555
#ifdef UNIV_ZIP_DEBUG
 
556
                        const page_zip_des_t*   page_zip
 
557
                                = buf_block_get_page_zip(block);
 
558
                        ut_a(!page_zip || page_zip_validate(page_zip, page));
 
559
#endif /* UNIV_ZIP_DEBUG */
 
560
 
 
561
                        buf_block_dbg_add_level(block, SYNC_TREE_NODE);
 
562
                }
 
563
 
 
564
                ut_ad(0 == ut_dulint_cmp(index->id,
 
565
                                         btr_page_get_index_id(page)));
 
566
 
 
567
                if (UNIV_UNLIKELY(height == ULINT_UNDEFINED)) {
 
568
                        /* We are in the root node */
 
569
 
 
570
                        height = btr_page_get_level(page, mtr);
 
571
                        root_height = height;
 
572
                        cursor->tree_height = root_height + 1;
 
573
#ifdef BTR_CUR_ADAPT
 
574
                        if (block != guess) {
 
575
                                info->root_guess = block;
 
576
                        }
 
577
#endif
 
578
                }
 
579
 
 
580
                if (height == 0) {
 
581
                        if (rw_latch == RW_NO_LATCH) {
 
582
 
 
583
                                btr_cur_latch_leaves(page, space, zip_size,
 
584
                                                     page_no, latch_mode,
 
585
                                                     cursor, mtr);
 
586
                        }
 
587
 
 
588
                        if ((latch_mode != BTR_MODIFY_TREE)
 
589
                            && (latch_mode != BTR_CONT_MODIFY_TREE)) {
 
590
 
 
591
                                /* Release the tree s-latch */
 
592
 
 
593
                                mtr_release_s_latch_at_savepoint(
 
594
                                        mtr, savepoint,
 
595
                                        dict_index_get_lock(index));
 
596
                        }
 
597
 
 
598
                        page_mode = mode;
 
599
                }
 
600
 
 
601
                page_cur_search_with_match(block, index, tuple, page_mode,
 
602
                                           &up_match, &up_bytes,
 
603
                                           &low_match, &low_bytes,
 
604
                                           page_cursor);
 
605
 
 
606
                if (estimate) {
 
607
                        btr_cur_add_path_info(cursor, height, root_height);
 
608
                }
 
609
 
 
610
                /* If this is the desired level, leave the loop */
 
611
 
 
612
                ut_ad(height == btr_page_get_level(
 
613
                              page_cur_get_page(page_cursor), mtr));
 
614
 
 
615
                if (level == height) {
 
616
 
 
617
                        if (level > 0) {
 
618
                                /* x-latch the page */
 
619
                                page = btr_page_get(space, zip_size,
 
620
                                                    page_no, RW_X_LATCH, mtr);
 
621
                                ut_a((ibool)!!page_is_comp(page)
 
622
                                     == dict_table_is_comp(index->table));
 
623
                        }
 
624
 
 
625
                        break;
 
626
                }
 
627
 
 
628
                ut_ad(height > 0);
 
629
 
 
630
                height--;
 
631
 
 
632
                guess = NULL;
 
633
 
 
634
                node_ptr = page_cur_get_rec(page_cursor);
 
635
                offsets = rec_get_offsets(node_ptr, cursor->index, offsets,
 
636
                                          ULINT_UNDEFINED, &heap);
 
637
                /* Go to the child node */
 
638
                page_no = btr_node_ptr_get_child_page_no(node_ptr, offsets);
 
639
        }
 
640
 
 
641
        if (UNIV_LIKELY_NULL(heap)) {
 
642
                mem_heap_free(heap);
 
643
        }
 
644
 
 
645
        if (level == 0) {
763
646
                cursor->low_match = low_match;
764
647
                cursor->low_bytes = low_bytes;
765
648
                cursor->up_match = up_match;
784
667
        }
785
668
 
786
669
func_exit:
787
 
 
788
 
        if (UNIV_LIKELY_NULL(heap)) {
789
 
                mem_heap_free(heap);
790
 
        }
791
 
 
792
670
        if (has_search_latch) {
793
671
 
794
672
                rw_lock_s_lock(&btr_search_latch);
799
677
Opens a cursor at either end of an index. */
800
678
UNIV_INTERN
801
679
void
802
 
btr_cur_open_at_index_side_func(
803
 
/*============================*/
 
680
btr_cur_open_at_index_side(
 
681
/*=======================*/
804
682
        ibool           from_left,      /*!< in: TRUE if open to the low end,
805
683
                                        FALSE if to the high end */
806
684
        dict_index_t*   index,          /*!< in: index */
807
685
        ulint           latch_mode,     /*!< in: latch mode */
808
686
        btr_cur_t*      cursor,         /*!< in: cursor */
809
 
        const char*     file,           /*!< in: file name */
810
 
        ulint           line,           /*!< in: line where called */
811
687
        mtr_t*          mtr)            /*!< in: mtr */
812
688
{
813
689
        page_cur_t*     page_cursor;
852
728
                page_t*         page;
853
729
                block = buf_page_get_gen(space, zip_size, page_no,
854
730
                                         RW_NO_LATCH, NULL, BUF_GET,
855
 
                                         file, line, mtr);
 
731
                                         __FILE__, __LINE__, mtr);
856
732
                page = buf_block_get_frame(block);
857
 
                ut_ad(index->id == btr_page_get_index_id(page));
 
733
                ut_ad(0 == ut_dulint_cmp(index->id,
 
734
                                         btr_page_get_index_id(page)));
858
735
 
859
736
                block->check_index_page_at_flush = TRUE;
860
737
 
931
808
Positions a cursor at a randomly chosen position within a B-tree. */
932
809
UNIV_INTERN
933
810
void
934
 
btr_cur_open_at_rnd_pos_func(
935
 
/*=========================*/
 
811
btr_cur_open_at_rnd_pos(
 
812
/*====================*/
936
813
        dict_index_t*   index,          /*!< in: index */
937
814
        ulint           latch_mode,     /*!< in: BTR_SEARCH_LEAF, ... */
938
815
        btr_cur_t*      cursor,         /*!< in/out: B-tree cursor */
939
 
        const char*     file,           /*!< in: file name */
940
 
        ulint           line,           /*!< in: line where called */
941
816
        mtr_t*          mtr)            /*!< in: mtr */
942
817
{
943
818
        page_cur_t*     page_cursor;
972
847
 
973
848
                block = buf_page_get_gen(space, zip_size, page_no,
974
849
                                         RW_NO_LATCH, NULL, BUF_GET,
975
 
                                         file, line, mtr);
 
850
                                         __FILE__, __LINE__, mtr);
976
851
                page = buf_block_get_frame(block);
977
 
                ut_ad(index->id == btr_page_get_index_id(page));
 
852
                ut_ad(0 == ut_dulint_cmp(index->id,
 
853
                                         btr_page_get_index_id(page)));
978
854
 
979
855
                if (height == ULINT_UNDEFINED) {
980
856
                        /* We are in the root node */
1071
947
                                not zero, the parameters index and thr
1072
948
                                should be specified */
1073
949
        btr_cur_t*      cursor, /*!< in: cursor on page after which to insert */
1074
 
        dtuple_t*       entry,  /*!< in/out: entry to insert */
 
950
        const dtuple_t* entry,  /*!< in: entry to insert */
1075
951
        que_thr_t*      thr,    /*!< in: query thread or NULL */
1076
952
        mtr_t*          mtr,    /*!< in/out: mini-transaction */
1077
953
        ibool*          inherit)/*!< out: TRUE if the inserted new record maybe
1133
1009
        const char*             op)     /*!< in: operation */
1134
1010
{
1135
1011
        fprintf(stderr, "Trx with id " TRX_ID_FMT " going to ",
1136
 
                (ullint) trx->id);
 
1012
                TRX_ID_PREP_PRINTF(trx->id));
1137
1013
        fputs(op, stderr);
1138
1014
        dict_index_name_print(stderr, trx, index);
1139
1015
        putc('\n', stderr);
1182
1058
        ibool           inherit;
1183
1059
        ulint           zip_size;
1184
1060
        ulint           rec_size;
 
1061
        mem_heap_t*     heap            = NULL;
1185
1062
        ulint           err;
1186
1063
 
1187
1064
        *big_rec = NULL;
1261
1138
                                        index, entry, big_rec_vec);
1262
1139
                        }
1263
1140
 
 
1141
                        if (heap) {
 
1142
                                mem_heap_free(heap);
 
1143
                        }
 
1144
 
1264
1145
                        return(DB_TOO_BIG_RECORD);
1265
1146
                }
1266
1147
        }
1283
1164
                        dtuple_convert_back_big_rec(index, entry, big_rec_vec);
1284
1165
                }
1285
1166
 
 
1167
                if (UNIV_LIKELY_NULL(heap)) {
 
1168
                        mem_heap_free(heap);
 
1169
                }
 
1170
 
1286
1171
                return(err);
1287
1172
        }
1288
1173
 
1289
1174
        if (UNIV_UNLIKELY(max_size < BTR_CUR_PAGE_REORGANIZE_LIMIT
1290
 
                          || max_size < rec_size)
 
1175
             || max_size < rec_size)
1291
1176
            && UNIV_LIKELY(page_get_n_recs(page) > 1)
1292
1177
            && page_get_max_insert_size(page, 1) < rec_size) {
1293
1178
 
1353
1238
                }
1354
1239
        }
1355
1240
 
 
1241
        if (UNIV_LIKELY_NULL(heap)) {
 
1242
                mem_heap_free(heap);
 
1243
        }
 
1244
 
1356
1245
#ifdef BTR_CUR_HASH_ADAPT
1357
1246
        if (!reorg && leaf && (cursor->flag == BTR_CUR_HASH)) {
1358
1247
                btr_search_update_hash_node_on_insert(cursor);
1744
1633
See if there is enough place in the page modification log to log
1745
1634
an update-in-place.
1746
1635
@return TRUE if enough place */
1747
 
UNIV_INTERN
 
1636
static
1748
1637
ibool
1749
1638
btr_cur_update_alloc_zip(
1750
1639
/*=====================*/
1824
1713
        page_zip_des_t* page_zip;
1825
1714
        ulint           err;
1826
1715
        rec_t*          rec;
1827
 
        roll_ptr_t      roll_ptr        = 0;
 
1716
        roll_ptr_t      roll_ptr        = ut_dulint_zero;
1828
1717
        trx_t*          trx;
1829
1718
        ulint           was_delete_marked;
1830
1719
        mem_heap_t*     heap            = NULL;
1954
1843
        page_t*         page;
1955
1844
        page_zip_des_t* page_zip;
1956
1845
        rec_t*          rec;
 
1846
        rec_t*          orig_rec;
1957
1847
        ulint           max_size;
1958
1848
        ulint           new_rec_size;
1959
1849
        ulint           old_rec_size;
1967
1857
 
1968
1858
        block = btr_cur_get_block(cursor);
1969
1859
        page = buf_block_get_frame(block);
1970
 
        rec = btr_cur_get_rec(cursor);
 
1860
        orig_rec = rec = btr_cur_get_rec(cursor);
1971
1861
        index = cursor->index;
1972
1862
        ut_ad(!!page_rec_is_comp(rec) == dict_table_is_comp(index->table));
1973
1863
        ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
2076
1966
        err = btr_cur_upd_lock_and_undo(flags, cursor, update, cmpl_info,
2077
1967
                                        thr, mtr, &roll_ptr);
2078
1968
        if (err != DB_SUCCESS) {
2079
 
 
2080
 
                goto err_exit;
 
1969
err_exit:
 
1970
                mem_heap_free(heap);
 
1971
                return(err);
2081
1972
        }
2082
1973
 
2083
1974
        /* Ok, we may do the replacement. Store on the page infimum the
2123
2014
 
2124
2015
        page_cur_move_to_next(page_cursor);
2125
2016
 
2126
 
        err = DB_SUCCESS;
2127
 
err_exit:
2128
2017
        mem_heap_free(heap);
2129
 
        return(err);
 
2018
 
 
2019
        return(DB_SUCCESS);
2130
2020
}
2131
2021
 
2132
2022
/*************************************************************//**
2839
2729
}
2840
2730
 
2841
2731
/***********************************************************//**
2842
 
Sets a secondary index record's delete mark to the given value. This
2843
 
function is only used by the insert buffer merge mechanism. */
 
2732
Clear a secondary index record's delete mark.  This function is only
 
2733
used by the insert buffer insert merge mechanism. */
2844
2734
UNIV_INTERN
2845
2735
void
2846
 
btr_cur_set_deleted_flag_for_ibuf(
2847
 
/*==============================*/
2848
 
        rec_t*          rec,            /*!< in/out: record */
 
2736
btr_cur_del_unmark_for_ibuf(
 
2737
/*========================*/
 
2738
        rec_t*          rec,            /*!< in/out: record to delete unmark */
2849
2739
        page_zip_des_t* page_zip,       /*!< in/out: compressed page
2850
2740
                                        corresponding to rec, or NULL
2851
2741
                                        when the tablespace is
2852
2742
                                        uncompressed */
2853
 
        ibool           val,            /*!< in: value to set */
2854
2743
        mtr_t*          mtr)            /*!< in: mtr */
2855
2744
{
2856
2745
        /* We do not need to reserve btr_search_latch, as the page has just
2857
2746
        been read to the buffer pool and there cannot be a hash index to it. */
2858
2747
 
2859
 
        btr_rec_set_deleted_flag(rec, page_zip, val);
 
2748
        btr_rec_set_deleted_flag(rec, page_zip, FALSE);
2860
2749
 
2861
 
        btr_cur_del_mark_set_sec_rec_log(rec, val, mtr);
 
2750
        btr_cur_del_mark_set_sec_rec_log(rec, FALSE, mtr);
2862
2751
}
2863
2752
 
2864
2753
/*==================== B-TREE RECORD REMOVE =========================*/
3152
3041
{
3153
3042
        btr_path_t*     slot;
3154
3043
        rec_t*          rec;
3155
 
        page_t*         page;
3156
3044
 
3157
3045
        ut_a(cursor->path_arr);
3158
3046
 
3175
3063
 
3176
3064
        slot = cursor->path_arr + (root_height - height);
3177
3065
 
3178
 
        page = page_align(rec);
3179
 
 
3180
3066
        slot->nth_rec = page_rec_get_n_recs_before(rec);
3181
 
        slot->n_recs = page_get_n_recs(page);
3182
 
        slot->page_no = page_get_page_no(page);
3183
 
        slot->page_level = btr_page_get_level_low(page);
3184
 
}
3185
 
 
3186
 
/*******************************************************************//**
3187
 
Estimate the number of rows between slot1 and slot2 for any level on a
3188
 
B-tree. This function starts from slot1->page and reads a few pages to
3189
 
the right, counting their records. If we reach slot2->page quickly then
3190
 
we know exactly how many records there are between slot1 and slot2 and
3191
 
we set is_n_rows_exact to TRUE. If we cannot reach slot2->page quickly
3192
 
then we calculate the average number of records in the pages scanned
3193
 
so far and assume that all pages that we did not scan up to slot2->page
3194
 
contain the same number of records, then we multiply that average to
3195
 
the number of pages between slot1->page and slot2->page (which is
3196
 
n_rows_on_prev_level). In this case we set is_n_rows_exact to FALSE.
3197
 
@return number of rows (exact or estimated) */
3198
 
static
3199
 
ib_int64_t
3200
 
btr_estimate_n_rows_in_range_on_level(
3201
 
/*==================================*/
3202
 
        dict_index_t*   index,                  /*!< in: index */
3203
 
        btr_path_t*     slot1,                  /*!< in: left border */
3204
 
        btr_path_t*     slot2,                  /*!< in: right border */
3205
 
        ib_int64_t      n_rows_on_prev_level,   /*!< in: number of rows
3206
 
                                                on the previous level for the
3207
 
                                                same descend paths; used to
3208
 
                                                determine the numbe of pages
3209
 
                                                on this level */
3210
 
        ibool*          is_n_rows_exact)        /*!< out: TRUE if the returned
3211
 
                                                value is exact i.e. not an
3212
 
                                                estimation */
3213
 
{
3214
 
        ulint           space;
3215
 
        ib_int64_t      n_rows;
3216
 
        ulint           n_pages_read;
3217
 
        ulint           page_no;
3218
 
        ulint           zip_size;
3219
 
        ulint           level;
3220
 
 
3221
 
        space = dict_index_get_space(index);
3222
 
 
3223
 
        n_rows = 0;
3224
 
        n_pages_read = 0;
3225
 
 
3226
 
        /* Assume by default that we will scan all pages between
3227
 
        slot1->page_no and slot2->page_no */
3228
 
        *is_n_rows_exact = TRUE;
3229
 
 
3230
 
        /* add records from slot1->page_no which are to the right of
3231
 
        the record which serves as a left border of the range, if any */
3232
 
        if (slot1->nth_rec < slot1->n_recs) {
3233
 
                n_rows += slot1->n_recs - slot1->nth_rec;
3234
 
        }
3235
 
 
3236
 
        /* add records from slot2->page_no which are to the left of
3237
 
        the record which servers as a right border of the range, if any */
3238
 
        if (slot2->nth_rec > 1) {
3239
 
                n_rows += slot2->nth_rec - 1;
3240
 
        }
3241
 
 
3242
 
        /* count the records in the pages between slot1->page_no and
3243
 
        slot2->page_no (non inclusive), if any */
3244
 
 
3245
 
        zip_size = fil_space_get_zip_size(space);
3246
 
 
3247
 
        /* Do not read more than this number of pages in order not to hurt
3248
 
        performance with this code which is just an estimation. If we read
3249
 
        this many pages before reaching slot2->page_no then we estimate the
3250
 
        average from the pages scanned so far */
3251
 
#       define N_PAGES_READ_LIMIT       10
3252
 
 
3253
 
        page_no = slot1->page_no;
3254
 
        level = slot1->page_level;
3255
 
 
3256
 
        do {
3257
 
                mtr_t           mtr;
3258
 
                page_t*         page;
3259
 
                buf_block_t*    block;
3260
 
 
3261
 
                mtr_start(&mtr);
3262
 
 
3263
 
                /* fetch the page */
3264
 
                block = buf_page_get(space, zip_size, page_no, RW_S_LATCH,
3265
 
                                     &mtr);
3266
 
 
3267
 
                page = buf_block_get_frame(block);
3268
 
 
3269
 
                /* It is possible that the tree has been reorganized in the
3270
 
                meantime and this is a different page. If this happens the
3271
 
                calculated estimate will be bogus, which is not fatal as
3272
 
                this is only an estimate. We are sure that a page with
3273
 
                page_no exists because InnoDB never frees pages, only
3274
 
                reuses them. */
3275
 
                if (fil_page_get_type(page) != FIL_PAGE_INDEX
3276
 
                    || btr_page_get_index_id(page) != index->id
3277
 
                    || btr_page_get_level_low(page) != level) {
3278
 
 
3279
 
                        /* The page got reused for something else */
3280
 
                        mtr_commit(&mtr);
3281
 
                        goto inexact;
3282
 
                }
3283
 
 
3284
 
                n_pages_read++;
3285
 
 
3286
 
                if (page_no != slot1->page_no) {
3287
 
                        /* Do not count the records on slot1->page_no,
3288
 
                        we already counted them before this loop. */
3289
 
                        n_rows += page_get_n_recs(page);
3290
 
                }
3291
 
 
3292
 
                page_no = btr_page_get_next(page, &mtr);
3293
 
 
3294
 
                mtr_commit(&mtr);
3295
 
 
3296
 
                if (n_pages_read == N_PAGES_READ_LIMIT
3297
 
                    || page_no == FIL_NULL) {
3298
 
                        /* Either we read too many pages or
3299
 
                        we reached the end of the level without passing
3300
 
                        through slot2->page_no, the tree must have changed
3301
 
                        in the meantime */
3302
 
                        goto inexact;
3303
 
                }
3304
 
 
3305
 
        } while (page_no != slot2->page_no);
3306
 
 
3307
 
        return(n_rows);
3308
 
 
3309
 
inexact:
3310
 
 
3311
 
        *is_n_rows_exact = FALSE;
3312
 
 
3313
 
        /* We did interrupt before reaching slot2->page */
3314
 
 
3315
 
        if (n_pages_read > 0) {
3316
 
                /* The number of pages on this level is
3317
 
                n_rows_on_prev_level, multiply it by the
3318
 
                average number of recs per page so far */
3319
 
                n_rows = n_rows_on_prev_level
3320
 
                        * n_rows / n_pages_read;
3321
 
        } else {
3322
 
                /* The tree changed before we could even
3323
 
                start with slot1->page_no */
3324
 
                n_rows = 10;
3325
 
        }
3326
 
 
3327
 
        return(n_rows);
 
3067
        slot->n_recs = page_get_n_recs(page_align(rec));
3328
3068
}
3329
3069
 
3330
3070
/*******************************************************************//**
3349
3089
        ibool           diverged_lot;
3350
3090
        ulint           divergence_level;
3351
3091
        ib_int64_t      n_rows;
3352
 
        ibool           is_n_rows_exact;
3353
3092
        ulint           i;
3354
3093
        mtr_t           mtr;
3355
3094
 
3361
3100
 
3362
3101
                btr_cur_search_to_nth_level(index, 0, tuple1, mode1,
3363
3102
                                            BTR_SEARCH_LEAF | BTR_ESTIMATE,
3364
 
                                            &cursor, 0,
3365
 
                                            __FILE__, __LINE__, &mtr);
 
3103
                                            &cursor, 0, &mtr);
3366
3104
        } else {
3367
3105
                btr_cur_open_at_index_side(TRUE, index,
3368
3106
                                           BTR_SEARCH_LEAF | BTR_ESTIMATE,
3379
3117
 
3380
3118
                btr_cur_search_to_nth_level(index, 0, tuple2, mode2,
3381
3119
                                            BTR_SEARCH_LEAF | BTR_ESTIMATE,
3382
 
                                            &cursor, 0,
3383
 
                                            __FILE__, __LINE__, &mtr);
 
3120
                                            &cursor, 0, &mtr);
3384
3121
        } else {
3385
3122
                btr_cur_open_at_index_side(FALSE, index,
3386
3123
                                           BTR_SEARCH_LEAF | BTR_ESTIMATE,
3392
3129
        /* We have the path information for the range in path1 and path2 */
3393
3130
 
3394
3131
        n_rows = 1;
3395
 
        is_n_rows_exact = TRUE;
3396
3132
        diverged = FALSE;           /* This becomes true when the path is not
3397
3133
                                    the same any more */
3398
3134
        diverged_lot = FALSE;       /* This becomes true when the paths are
3408
3144
                if (slot1->nth_rec == ULINT_UNDEFINED
3409
3145
                    || slot2->nth_rec == ULINT_UNDEFINED) {
3410
3146
 
3411
 
                        if (i > divergence_level + 1 && !is_n_rows_exact) {
 
3147
                        if (i > divergence_level + 1) {
3412
3148
                                /* In trees whose height is > 1 our algorithm
3413
3149
                                tends to underestimate: multiply the estimate
3414
3150
                                by 2: */
3420
3156
                        to over 1 / 2 of the estimated rows in the whole
3421
3157
                        table */
3422
3158
 
3423
 
                        if (n_rows > index->table->stat_n_rows / 2
3424
 
                            && !is_n_rows_exact) {
3425
 
 
 
3159
                        if (n_rows > index->table->stat_n_rows / 2) {
3426
3160
                                n_rows = index->table->stat_n_rows / 2;
3427
3161
 
3428
3162
                                /* If there are just 0 or 1 rows in the table,
3448
3182
                                        divergence_level = i;
3449
3183
                                }
3450
3184
                        } else {
3451
 
                                /* It is possible that
3452
 
                                slot1->nth_rec >= slot2->nth_rec
3453
 
                                if, for example, we have a single page
3454
 
                                tree which contains (inf, 5, 6, supr)
3455
 
                                and we select where x > 20 and x < 30;
3456
 
                                in this case slot1->nth_rec will point
3457
 
                                to the supr record and slot2->nth_rec
3458
 
                                will point to 6 */
3459
 
                                n_rows = 0;
 
3185
                                /* Maybe the tree has changed between
 
3186
                                searches */
 
3187
 
 
3188
                                return(10);
3460
3189
                        }
3461
3190
 
3462
3191
                } else if (diverged && !diverged_lot) {
3480
3209
                        }
3481
3210
                } else if (diverged_lot) {
3482
3211
 
3483
 
                        n_rows = btr_estimate_n_rows_in_range_on_level(
3484
 
                                index, slot1, slot2, n_rows,
3485
 
                                &is_n_rows_exact);
 
3212
                        n_rows = (n_rows * (slot1->n_recs + slot2->n_recs))
 
3213
                                / 2;
3486
3214
                }
3487
3215
        }
3488
3216
}
3521
3249
 
3522
3250
        n_cols = dict_index_get_n_unique(index);
3523
3251
 
3524
 
        n_diff = (ib_int64_t *)mem_zalloc((n_cols + 1) * sizeof(ib_int64_t));
 
3252
        n_diff = mem_zalloc((n_cols + 1) * sizeof(ib_int64_t));
3525
3253
 
3526
3254
        /* It makes no sense to test more pages than are contained
3527
3255
        in the index, thus we lower the number if it is too high */
3757
3485
Marks not updated extern fields as not-owned by this record. The ownership
3758
3486
is transferred to the updated record which is inserted elsewhere in the
3759
3487
index tree. In purge only the owner of externally stored field is allowed
3760
 
to free the field.
3761
 
@return TRUE if BLOB ownership was transferred */
 
3488
to free the field. */
3762
3489
UNIV_INTERN
3763
 
ibool
 
3490
void
3764
3491
btr_cur_mark_extern_inherited_fields(
3765
3492
/*=================================*/
3766
3493
        page_zip_des_t* page_zip,/*!< in/out: compressed page whose uncompressed
3774
3501
        ulint   n;
3775
3502
        ulint   j;
3776
3503
        ulint   i;
3777
 
        ibool   change_ownership = FALSE;
3778
3504
 
3779
3505
        ut_ad(rec_offs_validate(rec, NULL, offsets));
3780
3506
        ut_ad(!rec_offs_comp(offsets) || !rec_get_node_ptr_flag(rec));
3781
3507
 
3782
3508
        if (!rec_offs_any_extern(offsets)) {
3783
3509
 
3784
 
                return(FALSE);
 
3510
                return;
3785
3511
        }
3786
3512
 
3787
3513
        n = rec_offs_n_fields(offsets);
3804
3530
 
3805
3531
                        btr_cur_set_ownership_of_extern_field(
3806
3532
                                page_zip, rec, index, offsets, i, FALSE, mtr);
3807
 
 
3808
 
                        change_ownership = TRUE;
3809
3533
updated:
3810
3534
                        ;
3811
3535
                }
3812
3536
        }
3813
 
 
3814
 
        return(change_ownership);
3815
3537
}
3816
3538
 
3817
3539
/*******************************************************************//**
3848
3570
                        }
3849
3571
                }
3850
3572
 
3851
 
                data = (unsigned char *)dfield_get_data(dfield);
 
3573
                data = dfield_get_data(dfield);
3852
3574
                len = dfield_get_len(dfield);
3853
3575
                data[len - BTR_EXTERN_FIELD_REF_SIZE + BTR_EXTERN_LEN]
3854
3576
                        |= BTR_EXTERN_INHERITED_FLAG;
3907
3629
                dfield_t* dfield = dtuple_get_nth_field(entry, i);
3908
3630
 
3909
3631
                if (dfield_is_ext(dfield)) {
3910
 
                        byte*   data = (unsigned char *)dfield_get_data(dfield);
 
3632
                        byte*   data = dfield_get_data(dfield);
3911
3633
                        ulint   len = dfield_get_len(dfield);
3912
3634
 
3913
3635
                        data[len - BTR_EXTERN_FIELD_REF_SIZE + BTR_EXTERN_LEN]
3973
3695
                                will have to be copied. */
3974
3696
                                ut_a(uf->orig_len > BTR_EXTERN_FIELD_REF_SIZE);
3975
3697
 
3976
 
                                data = (unsigned char *)dfield_get_data(field);
 
3698
                                data = dfield_get_data(field);
3977
3699
                                len = dfield_get_len(field);
3978
3700
 
3979
 
                                buf = (unsigned char *)mem_heap_alloc(heap, uf->orig_len);
 
3701
                                buf = mem_heap_alloc(heap, uf->orig_len);
3980
3702
                                /* Copy the locally stored prefix. */
3981
3703
                                memcpy(buf, data,
3982
3704
                                       uf->orig_len
4031
3753
                                if there is one */
4032
3754
        mtr_t*          mtr)    /*!< in: mini-transaction to commit */
4033
3755
{
4034
 
        buf_pool_t*     buf_pool = buf_pool_from_block(block);
4035
 
        ulint           space   = buf_block_get_space(block);
4036
 
        ulint           page_no = buf_block_get_page_no(block);
 
3756
        ulint   space   = buf_block_get_space(block);
 
3757
        ulint   page_no = buf_block_get_page_no(block);
4037
3758
 
4038
3759
        ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
4039
3760
 
4040
3761
        mtr_commit(mtr);
4041
3762
 
4042
 
        buf_pool_mutex_enter(buf_pool);
 
3763
        buf_pool_mutex_enter();
4043
3764
        mutex_enter(&block->mutex);
4044
3765
 
4045
3766
        /* Only free the block if it is still allocated to
4060
3781
                }
4061
3782
        }
4062
3783
 
4063
 
        buf_pool_mutex_exit(buf_pool);
 
3784
        buf_pool_mutex_exit();
4064
3785
        mutex_exit(&block->mutex);
4065
3786
}
4066
3787
 
4069
3790
them in rec.  The extern flags in rec will have to be set beforehand.
4070
3791
The fields are stored on pages allocated from leaf node
4071
3792
file segment of the index tree.
4072
 
@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
 
3793
@return DB_SUCCESS or error */
4073
3794
UNIV_INTERN
4074
3795
ulint
4075
3796
btr_store_big_rec_extern_fields(
4084
3805
                                        this function returns */
4085
3806
        big_rec_t*      big_rec_vec,    /*!< in: vector containing fields
4086
3807
                                        to be stored externally */
4087
 
        mtr_t*          /*local_mtr __attribute__((unused))*/) /*!< in: mtr
 
3808
        mtr_t*          local_mtr __attribute__((unused))) /*!< in: mtr
4088
3809
                                        containing the latch to rec and to the
4089
3810
                                        tree */
4090
3811
{
4151
3872
                        field_ref += local_len;
4152
3873
                }
4153
3874
                extern_len = big_rec_vec->fields[i].len;
4154
 
                UNIV_MEM_ASSERT_RW(big_rec_vec->fields[i].data,
4155
 
                                   extern_len);
4156
3875
 
4157
3876
                ut_a(extern_len > 0);
4158
3877
 
4162
3881
                        int     err = deflateReset(&c_stream);
4163
3882
                        ut_a(err == Z_OK);
4164
3883
 
4165
 
                        c_stream.next_in = (Bytef *) big_rec_vec->fields[i].data;
 
3884
                        c_stream.next_in = (void*) big_rec_vec->fields[i].data;
4166
3885
                        c_stream.avail_in = extern_len;
4167
3886
                }
4168
3887
 
4499
4218
        ulint           i,              /*!< in: field number of field_ref;
4500
4219
                                        ignored if rec == NULL */
4501
4220
        enum trx_rb_ctx rb_ctx,         /*!< in: rollback context */
4502
 
        mtr_t*          /*local_mtr __attribute__((unused))*/) /*!< in: mtr
 
4221
        mtr_t*          local_mtr __attribute__((unused))) /*!< in: mtr
4503
4222
                                        containing the latch to data an an
4504
4223
                                        X-latch to the index tree */
4505
4224
{
4533
4252
                /* In the rollback of uncommitted transactions, we may
4534
4253
                encounter a clustered index record whose BLOBs have
4535
4254
                not been written.  There is nothing to free then. */
4536
 
                ut_a(rb_ctx == RB_RECOVERY || rb_ctx == RB_RECOVERY_PURGE_REC);
 
4255
                ut_a(rb_ctx == RB_RECOVERY);
4537
4256
                return;
4538
4257
        }
4539
4258
 
4559
4278
        }
4560
4279
 
4561
4280
        for (;;) {
4562
 
#ifdef UNIV_SYNC_DEBUG
4563
4281
                buf_block_t*    rec_block;
4564
 
#endif /* UNIV_SYNC_DEBUG */
4565
4282
                buf_block_t*    ext_block;
4566
4283
 
4567
4284
                mtr_start(&mtr);
4568
4285
 
4569
 
#ifdef UNIV_SYNC_DEBUG
4570
 
                rec_block =
4571
 
#endif /* UNIV_SYNC_DEBUG */
4572
 
                        buf_page_get(page_get_space_id(
 
4286
                rec_block = buf_page_get(page_get_space_id(
4573
4287
                                                 page_align(field_ref)),
4574
4288
                                         rec_zip_size,
4575
4289
                                         page_get_page_no(
4584
4298
                    || (mach_read_from_1(field_ref + BTR_EXTERN_LEN)
4585
4299
                        & BTR_EXTERN_OWNER_FLAG)
4586
4300
                    /* Rollback and inherited field */
4587
 
                    || ((rb_ctx == RB_NORMAL || rb_ctx == RB_RECOVERY)
 
4301
                    || (rb_ctx != RB_NONE
4588
4302
                        && (mach_read_from_1(field_ref + BTR_EXTERN_LEN)
4589
4303
                            & BTR_EXTERN_INHERITED_FLAG))) {
4590
4304
 
4794
4508
                mtr_commit(&mtr);
4795
4509
 
4796
4510
                if (page_no == FIL_NULL || copy_len != part_len) {
4797
 
                        UNIV_MEM_ASSERT_RW(buf, copied_len);
4798
4511
                        return(copied_len);
4799
4512
                }
4800
4513
 
4978
4691
                                      space_id, page_no, offset);
4979
4692
                inflateEnd(&d_stream);
4980
4693
                mem_heap_free(heap);
4981
 
                UNIV_MEM_ASSERT_RW(buf, d_stream.total_out);
4982
4694
                return(d_stream.total_out);
4983
4695
        } else {
4984
4696
                return(btr_copy_blob_prefix(buf, len, space_id,
5084
4796
 
5085
4797
        extern_len = mach_read_from_4(data + local_len + BTR_EXTERN_LEN + 4);
5086
4798
 
5087
 
        buf = (unsigned char *)mem_heap_alloc(heap, local_len + extern_len);
 
4799
        buf = mem_heap_alloc(heap, local_len + extern_len);
5088
4800
 
5089
4801
        memcpy(buf, data, local_len);
5090
4802
        *len = local_len
5099
4811
 
5100
4812
/*******************************************************************//**
5101
4813
Copies an externally stored field of a record to mem heap.
5102
 
@return the field copied to heap, or NULL if the field is incomplete */
 
4814
@return the field copied to heap */
5103
4815
UNIV_INTERN
5104
4816
byte*
5105
4817
btr_rec_copy_externally_stored_field(
5129
4841
 
5130
4842
        data = rec_get_nth_field(rec, offsets, no, &local_len);
5131
4843
 
5132
 
        ut_a(local_len >= BTR_EXTERN_FIELD_REF_SIZE);
5133
 
 
5134
 
        if (UNIV_UNLIKELY
5135
 
            (!memcmp(data + local_len - BTR_EXTERN_FIELD_REF_SIZE,
5136
 
                     field_ref_zero, BTR_EXTERN_FIELD_REF_SIZE))) {
5137
 
                /* The externally stored field was not written yet.
5138
 
                This record should only be seen by
5139
 
                recv_recovery_rollback_active() or any
5140
 
                TRX_ISO_READ_UNCOMMITTED transactions. */
5141
 
                return(NULL);
5142
 
        }
5143
 
 
5144
4844
        return(btr_copy_externally_stored_field(len, data,
5145
4845
                                                zip_size, local_len, heap));
5146
4846
}