@@ -48,12 +48,6 @@ this program; if not, write to the Free Software Foundation, Inc.,
4848#endif /* !UNIV_HOTBACKUP */
4949#include " lob0lob.h"
5050
51- /* * A blob map to track the first page no of external LOB and its parent record
52- which is the <page_no, heap_no>. This is used to find duplicate external LOB
53- pages that is shared between two records. This can happen only on corruption
54- (cause unknown yet). CHECK TABLE t1 EXTENDED will use this map to report
55- corruption and mark the table as corrupted */
56- thread_local blob_ref_map *thread_local_blob_map = nullptr ;
5751
5852/* THE INDEX PAGE
5953 ==============
@@ -1734,47 +1728,49 @@ a clustered index
17341728@param[in] rec physical record
17351729@param[in] index index of the table
17361730@param[in] offsets the record offset array
1731+ @param[in] blob_map Optional blob reference map for tracking, nullptr by
1732+ default.
17371733@return true If OK else false if external LOB is found to be shared between two
17381734records, ie false on failure */
17391735bool page_rec_blob_validate (const rec_t *rec, const dict_index_t *index,
1740- const ulint *offsets) {
1741- // this means reference check is not enabled. Enabled only via
1742- // CHECK TABLE path
1743- if (thread_local_blob_map == nullptr ) {
1736+ const ulint *offsets, blob_ref_map *blob_map ) {
1737+ // This means reference check is not enabled. Enabled only via
1738+ // CHECK TABLE path.
1739+ if (blob_map == nullptr ) {
17441740 return true ;
17451741 }
17461742
1747- // if index is not PRIMARY, return true
1743+ // If index is not PRIMARY, return true.
17481744 if (!index->is_clustered ()) {
17491745 return true ;
17501746 }
17511747
1752- // if page-level is not zero, return true because blob exists only on leaf
1753- // level
1748+ // If page-level is not zero, return true because blob exists only on leaf
1749+ // level.
17541750 const page_t *page = page_align (rec);
17551751 if (!page_is_leaf (page)) {
17561752 return true ;
17571753 }
17581754
1759- // if rec is not user record, blobs dont exist, return true
1755+ // If rec is not user record, blobs dont exist, return true.
17601756 if (!page_rec_is_user_rec (rec)) {
17611757 return true ;
17621758 }
17631759
1764- // if rec doesn't have any external LOB, return true
1760+ // If rec doesn't have any external LOB, return true.
17651761 if (!rec_offs_any_extern (offsets)) {
17661762 return true ;
17671763 }
17681764
1769- // if rec is deleted marked, return true, we cannot validate the blob. the
1770- // blob pages in the deleted marked records could be freed
1765+ // If rec is deleted marked, return true, we cannot validate the blob. The
1766+ // blob pages in the deleted marked records could be freed.
17711767 if (rec_get_deleted_flag (rec, rec_offs_comp (offsets))) {
17721768 return true ;
17731769 }
17741770
1775- // if rec is not the owner of the blob, we cannot validate if blob page state
1771+ // If rec is not the owner of the blob, we cannot validate if blob page state
17761772 // now validate that the blob first page is not marked as free from page
1777- // bitmap
1773+ // bitmap.
17781774
17791775 ulint n_fields = rec_offs_n_fields (offsets);
17801776
@@ -1786,8 +1782,7 @@ bool page_rec_blob_validate(const rec_t *rec, const dict_index_t *index,
17861782 lob::btr_rec_get_field_ref (index, rec, offsets, i));
17871783
17881784 lob::ref_t ref (field_ref);
1789- if (!ref.is_owner () || ref.is_null () || ref.is_null_relaxed () ||
1790- ref.is_being_modified ()) {
1785+ if (!ref.is_owner () || ref.is_null_relaxed () || ref.is_being_modified ()) {
17911786 continue ;
17921787 }
17931788
@@ -1816,16 +1811,16 @@ bool page_rec_blob_validate(const rec_t *rec, const dict_index_t *index,
18161811
18171812 DBUG_EXECUTE_IF (
18181813 " simulate_lob_corruption" ,
1819- // introduce corruption after 5 external LOB entries
1820- if (thread_local_blob_map ->size () >= 5 ) {
1821- // we introduce a fake entry in the map
1822- (*thread_local_blob_map )[blob_page_no] = std::make_pair (
1814+ // Introduce corruption after 5 external LOB entries.
1815+ if (blob_map ->size () >= 5 ) {
1816+ // We introduce a fake entry in the map.
1817+ (*blob_map )[blob_page_no] = std::make_pair (
18231818 page_get_page_no (page) - 1 , page_rec_get_heap_no (rec) - 1 );
18241819 });
18251820
1826- auto it = thread_local_blob_map ->find (blob_page_no);
1827- if (it == thread_local_blob_map ->end ()) {
1828- (*thread_local_blob_map )[blob_page_no] =
1821+ auto it = blob_map ->find (blob_page_no);
1822+ if (it == blob_map ->end ()) {
1823+ (*blob_map )[blob_page_no] =
18291824 std::make_pair (page_get_page_no (page), page_rec_get_heap_no (rec));
18301825 } else {
18311826 auto val = it->second ;
@@ -2249,7 +2244,8 @@ bool page_is_spatial_non_leaf(const rec_t *rec, dict_index_t *index) {
22492244 return (dict_index_is_spatial (index) && !page_is_leaf (page_align (rec)));
22502245}
22512246
2252- bool page_validate (const page_t *page, dict_index_t *index) {
2247+ bool page_validate (const page_t *page, dict_index_t *index,
2248+ blob_ref_map *blob_map) {
22532249 const page_dir_slot_t *slot;
22542250 mem_heap_t *heap;
22552251 byte *buf;
@@ -2360,7 +2356,8 @@ bool page_validate(const page_t *page, dict_index_t *index) {
23602356 goto func_exit;
23612357 }
23622358
2363- if (!page_rec_blob_validate (const_cast <byte *>(rec), index, offsets)) {
2359+ if (!page_rec_blob_validate (const_cast <byte *>(rec), index, offsets,
2360+ blob_map)) {
23642361 goto func_exit;
23652362 }
23662363
0 commit comments