11/*****************************************************************************
22
3- Copyright (c) 1997, 2011 , Oracle and/or its affiliates. All Rights Reserved.
3+ Copyright (c) 1997, 2015 , Oracle and/or its affiliates. All Rights Reserved.
44
55This program is free software; you can redistribute it and/or modify it under
66the terms of the GNU General Public License as published by the Free Software
@@ -43,6 +43,7 @@ Created 3/14/1997 Heikki Tuuri
4343#include "row0vers.h"
4444#include "row0mysql.h"
4545#include "log0log.h"
46+ #include "rem0cmp.h"
4647
4748/*************************************************************************
4849IMPORTANT NOTE: Any operation that generates redo MUST check that there
@@ -80,7 +81,7 @@ row_purge_node_create(
8081
8182/***********************************************************/ /**
8283Repositions the pcur in the purge node on the clustered index record,
83- if found.
84+ if found. If the record is not found, close pcur.
8485@return TRUE if the record was found */
8586static
8687ibool
@@ -90,23 +91,28 @@ row_purge_reposition_pcur(
9091purge_node_t * node ,/*!< in: row purge node */
9192mtr_t * mtr )/*!< in: mtr */
9293{
93- ibool found ;
94-
9594if (node -> found_clust ) {
96- found = btr_pcur_restore_position ( mode , & (node -> pcur ), mtr );
95+ ut_ad ( row_purge_validate_pcur (node ) );
9796
98- return (found );
99- }
97+ node -> found_clust = btr_pcur_restore_position (
98+ mode , & (node -> pcur ), mtr );
99+
100+ } else {
101+
102+ node -> found_clust = row_search_on_row_ref (
103+ & (node -> pcur ), mode , node -> table , node -> ref , mtr );
100104
101- found = row_search_on_row_ref (& (node -> pcur ), mode , node -> table ,
102- node -> ref , mtr );
103- node -> found_clust = found ;
105+ if (node -> found_clust ) {
106+ btr_pcur_store_position (& (node -> pcur ), mtr );
107+ }
108+ }
104109
105- if (found ) {
106- btr_pcur_store_position (& (node -> pcur ), mtr );
110+ /* Close the current cursor if we fail to position it correctly. */
111+ if (!node -> found_clust ) {
112+ btr_pcur_close (& node -> pcur );
107113}
108114
109- return (found );
115+ return (node -> found_clust );
110116}
111117
112118/***********************************************************/ /**
@@ -143,8 +149,8 @@ row_purge_remove_clust_if_poss_low(
143149
144150if (!success ) {
145151/* The record is already removed */
146-
147- btr_pcur_commit_specify_mtr ( pcur , & mtr );
152+ /* Persistent cursor is closed if reposition fails. */
153+ mtr_commit ( & mtr );
148154
149155return (TRUE);
150156}
@@ -258,7 +264,12 @@ row_purge_poss_sec(
258264 btr_pcur_get_rec (& node -> pcur ),
259265 & mtr , index , entry );
260266
261- btr_pcur_commit_specify_mtr (& node -> pcur , & mtr );
267+ /* Persistent cursor is closed if reposition fails. */
268+ if (node -> found_clust ) {
269+ btr_pcur_commit_specify_mtr (& node -> pcur , & mtr );
270+ } else {
271+ mtr_commit (& mtr );
272+ }
262273
263274return (can_delete );
264275}
@@ -806,3 +817,53 @@ row_purge_step(
806817
807818return (thr );
808819}
820+
821+ #ifdef UNIV_DEBUG
822+ /***********************************************************/ /**
823+ Validate the persisent cursor in the purge node. The purge node has two
824+ references to the clustered index record - one via the ref member, and the
825+ other via the persistent cursor. These two references must match each
826+ other if the found_clust flag is set.
827+ @return true if the stored copy of persistent cursor is consistent
828+ with the ref member.*/
829+ ibool
830+ row_purge_validate_pcur (
831+ purge_node_t * node )
832+ {
833+ dict_index_t * clust_index ;
834+ ulint * offsets ;
835+ int st ;
836+
837+ if (!node -> found_clust ) {
838+ return (TRUE);
839+ }
840+
841+ if (node -> index == NULL ) {
842+ return (TRUE);
843+ }
844+
845+ if (node -> pcur .old_stored != BTR_PCUR_OLD_STORED ) {
846+ return (TRUE);
847+ }
848+
849+ clust_index = node -> pcur .btr_cur .index ;
850+
851+ offsets = rec_get_offsets (node -> pcur .old_rec , clust_index , NULL ,
852+ node -> pcur .old_n_fields , & node -> heap );
853+
854+ /* Here we are comparing the purge ref record and the stored initial
855+ part in persistent cursor. Both cases we store n_uniq fields of the
856+ cluster index and so it is fine to do the comparison. We note this
857+ dependency here as pcur and ref belong to different modules. */
858+ st = cmp_dtuple_rec (node -> ref , node -> pcur .old_rec , offsets );
859+
860+ if (st != 0 ) {
861+ fprintf (stderr , "Purge node pcur validation failed\n" );
862+ dtuple_print (stderr , node -> ref );
863+ rec_print (stderr , node -> pcur .old_rec , clust_index );
864+ return (FALSE);
865+ }
866+
867+ return (TRUE);
868+ }
869+ #endif /* UNIV_DEBUG */
0 commit comments