~ubuntu-branches/ubuntu/lucid/mysql-dfsg-5.1/lucid-security

« back to all changes in this revision

Viewing changes to storage/innodb_plugin/row/row0purge.c

  • Committer: Package Import Robot
  • Author(s): Marc Deslauriers
  • Date: 2012-02-22 22:33:55 UTC
  • mto: (1.2.1) (37.1.1 lucid-security)
  • mto: This revision was merged to the branch mainline in revision 36.
  • Revision ID: package-import@ubuntu.com-20120222223355-ku1tb4r70osci6v2
Tags: upstream-5.1.61
ImportĀ upstreamĀ versionĀ 5.1.61

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*****************************************************************************
2
2
 
3
 
Copyright (c) 1997, 2009, Innobase Oy. All Rights Reserved.
 
3
Copyright (c) 1997, 2011, Oracle and/or its affiliates. All Rights Reserved.
4
4
 
5
5
This program is free software; you can redistribute it and/or modify it under
6
6
the terms of the GNU General Public License as published by the Free Software
11
11
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
12
 
13
13
You should have received a copy of the GNU General Public License along with
14
 
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
15
 
Place, Suite 330, Boston, MA 02111-1307 USA
 
14
this program; if not, write to the Free Software Foundation, Inc.,
 
15
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
16
16
 
17
17
*****************************************************************************/
18
18
 
44
44
#include "row0mysql.h"
45
45
#include "log0log.h"
46
46
 
 
47
/*************************************************************************
 
48
IMPORTANT NOTE: Any operation that generates redo MUST check that there
 
49
is enough space in the redo log before for that operation. This is
 
50
done by calling log_free_check(). The reason for checking the
 
51
availability of the redo log space before the start of the operation is
 
52
that we MUST not hold any synchonization objects when performing the
 
53
check.
 
54
If you make a change in this module make sure that no codepath is
 
55
introduced where a call to log_free_check() is bypassed. */
 
56
 
47
57
/********************************************************************//**
48
58
Creates a purge node to a query graph.
49
59
@return own: purge node */
126
136
        pcur = &(node->pcur);
127
137
        btr_cur = btr_pcur_get_btr_cur(pcur);
128
138
 
 
139
        log_free_check();
129
140
        mtr_start(&mtr);
130
141
 
131
142
        success = row_purge_reposition_pcur(mode, node, &mtr);
376
387
marked record if that record contained an externally stored field. */
377
388
static
378
389
void
379
 
row_purge_upd_exist_or_extern(
380
 
/*==========================*/
 
390
row_purge_upd_exist_or_extern_func(
 
391
/*===============================*/
 
392
#ifdef UNIV_DEBUG
 
393
        const que_thr_t*thr,    /*!< in: query thread */
 
394
#endif /* UNIV_DEBUG */
381
395
        purge_node_t*   node)   /*!< in: row purge node */
382
396
{
383
397
        mem_heap_t*     heap;
392
406
 
393
407
        ut_ad(node);
394
408
 
395
 
        if (node->rec_type == TRX_UNDO_UPD_DEL_REC) {
 
409
        if (node->rec_type == TRX_UNDO_UPD_DEL_REC
 
410
            || (node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) {
396
411
 
397
412
                goto skip_secondaries;
398
413
        }
402
417
        while (node->index != NULL) {
403
418
                index = node->index;
404
419
 
405
 
                if (row_upd_changes_ord_field_binary(NULL, node->index,
406
 
                                                     node->update)) {
 
420
                if (row_upd_changes_ord_field_binary(node->index, node->update,
 
421
                                                     thr, NULL, NULL)) {
407
422
                        /* Build the older version of the index entry */
408
423
                        entry = row_build_index_entry(node->row, NULL,
409
424
                                                      index, heap);
485
500
        }
486
501
}
487
502
 
 
503
#ifdef UNIV_DEBUG
 
504
# define row_purge_upd_exist_or_extern(thr,node)        \
 
505
        row_purge_upd_exist_or_extern_func(thr,node)
 
506
#else /* UNIV_DEBUG */
 
507
# define row_purge_upd_exist_or_extern(thr,node)        \
 
508
        row_purge_upd_exist_or_extern_func(node)
 
509
#endif /* UNIV_DEBUG */
 
510
 
488
511
/***********************************************************//**
489
512
Parses the row reference and other info in a modify undo log record.
490
513
@return TRUE if purge operation required: NOTE that then the CALLER
508
531
        roll_ptr_t      roll_ptr;
509
532
        ulint           info_bits;
510
533
        ulint           type;
511
 
        ulint           cmpl_info;
512
534
 
513
535
        ut_ad(node && thr);
514
536
 
515
537
        trx = thr_get_trx(thr);
516
538
 
517
 
        ptr = trx_undo_rec_get_pars(node->undo_rec, &type, &cmpl_info,
518
 
                                    updated_extern, &undo_no, &table_id);
 
539
        ptr = trx_undo_rec_get_pars(
 
540
                node->undo_rec, &type, &node->cmpl_info,
 
541
                updated_extern, &undo_no, &table_id);
519
542
        node->rec_type = type;
520
543
 
521
544
        if (type == TRX_UNDO_UPD_DEL_REC && !(*updated_extern)) {
528
551
        node->table = NULL;
529
552
 
530
553
        if (type == TRX_UNDO_UPD_EXIST_REC
531
 
            && cmpl_info & UPD_NODE_NO_ORD_CHANGE && !(*updated_extern)) {
 
554
            && node->cmpl_info & UPD_NODE_NO_ORD_CHANGE
 
555
            && !(*updated_extern)) {
532
556
 
533
557
                /* Purge requires no changes to indexes: we may return */
534
558
 
578
602
 
579
603
        /* Read to the partial row the fields that occur in indexes */
580
604
 
581
 
        if (!(cmpl_info & UPD_NODE_NO_ORD_CHANGE)) {
 
605
        if (!(node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) {
582
606
                ptr = trx_undo_rec_get_partial_row(
583
607
                        ptr, clust_index, &node->row,
584
608
                        type == TRX_UNDO_UPD_DEL_REC,
591
615
/***********************************************************//**
592
616
Fetches an undo log record and does the purge for the recorded operation.
593
617
If none left, or the current purge completed, returns the control to the
594
 
parent node, which is always a query thread node.
595
 
@return DB_SUCCESS if operation successfully completed, else error code */
596
 
static
597
 
ulint
 
618
parent node, which is always a query thread node. */
 
619
static __attribute__((nonnull))
 
620
void
598
621
row_purge(
599
622
/*======*/
600
623
        purge_node_t*   node,   /*!< in: row purge node */
601
624
        que_thr_t*      thr)    /*!< in: query thread */
602
625
{
603
 
        roll_ptr_t      roll_ptr;
604
 
        ibool           purge_needed;
605
626
        ibool           updated_extern;
606
 
        trx_t*          trx;
607
 
 
608
 
        ut_ad(node && thr);
609
 
 
610
 
        trx = thr_get_trx(thr);
611
 
 
612
 
        node->undo_rec = trx_purge_fetch_next_rec(&roll_ptr,
613
 
                                                  &(node->reservation),
 
627
 
 
628
        ut_ad(node);
 
629
        ut_ad(thr);
 
630
 
 
631
        node->undo_rec = trx_purge_fetch_next_rec(&node->roll_ptr,
 
632
                                                  &node->reservation,
614
633
                                                  node->heap);
615
634
        if (!node->undo_rec) {
616
635
                /* Purge completed for this query thread */
617
636
 
618
637
                thr->run_node = que_node_get_parent(node);
619
638
 
620
 
                return(DB_SUCCESS);
621
 
        }
622
 
 
623
 
        node->roll_ptr = roll_ptr;
624
 
 
625
 
        if (node->undo_rec == &trx_purge_dummy_rec) {
626
 
                purge_needed = FALSE;
627
 
        } else {
628
 
                purge_needed = row_purge_parse_undo_rec(node, &updated_extern,
629
 
                                                        thr);
630
 
                /* If purge_needed == TRUE, we must also remember to unfreeze
631
 
                data dictionary! */
632
 
        }
633
 
 
634
 
        if (purge_needed) {
 
639
                return;
 
640
        }
 
641
 
 
642
        if (node->undo_rec != &trx_purge_dummy_rec
 
643
            && row_purge_parse_undo_rec(node, &updated_extern, thr)) {
635
644
                node->found_clust = FALSE;
636
645
 
637
646
                node->index = dict_table_get_next_index(
643
652
                } else if (updated_extern
644
653
                           || node->rec_type == TRX_UNDO_UPD_EXIST_REC) {
645
654
 
646
 
                        row_purge_upd_exist_or_extern(node);
 
655
                        row_purge_upd_exist_or_extern(thr, node);
647
656
                }
648
657
 
649
658
                if (node->found_clust) {
650
659
                        btr_pcur_close(&(node->pcur));
651
660
                }
652
661
 
653
 
                row_mysql_unfreeze_data_dictionary(trx);
 
662
                row_mysql_unfreeze_data_dictionary(thr_get_trx(thr));
654
663
        }
655
664
 
656
665
        /* Do some cleanup */
658
667
        mem_heap_empty(node->heap);
659
668
 
660
669
        thr->run_node = node;
661
 
 
662
 
        return(DB_SUCCESS);
663
670
}
664
671
 
665
672
/***********************************************************//**
673
680
        que_thr_t*      thr)    /*!< in: query thread */
674
681
{
675
682
        purge_node_t*   node;
676
 
        ulint           err;
677
683
 
678
684
        ut_ad(thr);
679
685
 
681
687
 
682
688
        ut_ad(que_node_get_type(node) == QUE_NODE_PURGE);
683
689
 
684
 
        err = row_purge(node, thr);
685
 
 
686
 
        ut_ad(err == DB_SUCCESS);
 
690
        row_purge(node, thr);
687
691
 
688
692
        return(thr);
689
693
}