diff options
Diffstat (limited to 'storage/innobase/row/row0purge.cc')
-rw-r--r-- | storage/innobase/row/row0purge.cc | 79 |
1 files changed, 72 insertions, 7 deletions
diff --git a/storage/innobase/row/row0purge.cc b/storage/innobase/row/row0purge.cc index 8212a7b43e0..b26ba971a95 100644 --- a/storage/innobase/row/row0purge.cc +++ b/storage/innobase/row/row0purge.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1997, 2013, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1997, 2015, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -84,7 +84,7 @@ row_purge_node_create( /***********************************************************//** Repositions the pcur in the purge node on the clustered index record, -if found. +if found. If the record is not found, close pcur. @return TRUE if the record was found */ static ibool @@ -95,11 +95,10 @@ row_purge_reposition_pcur( mtr_t* mtr) /*!< in: mtr */ { if (node->found_clust) { - ibool found; + ut_ad(node->validate_pcur()); - found = btr_pcur_restore_position(mode, &node->pcur, mtr); + node->found_clust = btr_pcur_restore_position(mode, &node->pcur, mtr); - return(found); } else { node->found_clust = row_search_on_row_ref( &node->pcur, mode, node->table, node->ref, mtr); @@ -109,6 +108,11 @@ row_purge_reposition_pcur( } } + /* Close the current cursor if we fail to position it correctly. */ + if (!node->found_clust) { + btr_pcur_close(&node->pcur); + } + return(node->found_clust); } @@ -182,7 +186,12 @@ func_exit: mem_heap_free(heap); } - btr_pcur_commit_specify_mtr(&node->pcur, &mtr); + /* Persistent cursor is closed if reposition fails. */ + if (node->found_clust) { + btr_pcur_commit_specify_mtr(&node->pcur, &mtr); + } else { + mtr_commit(&mtr); + } return(success); } @@ -251,7 +260,12 @@ row_purge_poss_sec( btr_pcur_get_rec(&node->pcur), &mtr, index, entry); - btr_pcur_commit_specify_mtr(&node->pcur, &mtr); + /* Persistent cursor is closed if reposition fails. */ + if (node->found_clust) { + btr_pcur_commit_specify_mtr(&node->pcur, &mtr); + } else { + mtr_commit(&mtr); + } return(can_delete); } @@ -831,6 +845,8 @@ row_purge_record_func( dict_index_t* clust_index; bool purged = true; + ut_ad(!node->found_clust); + clust_index = dict_table_get_first_index(node->table); node->index = dict_table_get_next_index(clust_index); @@ -986,3 +1002,52 @@ row_purge_step( return(thr); } + +#ifdef UNIV_DEBUG +/***********************************************************//** +Validate the persisent cursor. The purge node has two references +to the clustered index record - one via the ref member, and the +other via the persistent cursor. These two references must match +each other if the found_clust flag is set. +@return true if the stored copy of persistent cursor is consistent +with the ref member.*/ +bool +purge_node_t::validate_pcur() +{ + if (!found_clust) { + return(true); + } + + if (index == NULL) { + return(true); + } + + if (index->type == DICT_FTS) { + return(true); + } + + if (pcur.old_stored != BTR_PCUR_OLD_STORED) { + return(true); + } + + dict_index_t* clust_index = pcur.btr_cur.index; + + ulint* offsets = rec_get_offsets( + pcur.old_rec, clust_index, NULL, pcur.old_n_fields, &heap); + + /* Here we are comparing the purge ref record and the stored initial + part in persistent cursor. Both cases we store n_uniq fields of the + cluster index and so it is fine to do the comparison. We note this + dependency here as pcur and ref belong to different modules. */ + int st = cmp_dtuple_rec(ref, pcur.old_rec, offsets); + + if (st != 0) { + fprintf(stderr, "Purge node pcur validation failed\n"); + dtuple_print(stderr, ref); + rec_print(stderr, pcur.old_rec, clust_index); + return(false); + } + + return(true); +} +#endif /* UNIV_DEBUG */ |