@@ -597,6 +597,8 @@ static struct
597
597
lsn_t lsn;
598
598
/* * File name from the FILE_ record */
599
599
std::string file_name;
600
+ /* * whether a FILE_DELETE record was encountered */
601
+ mutable bool deleted;
600
602
};
601
603
602
604
using map= std::map<const uint32_t , item, std::less<const uint32_t >,
@@ -638,11 +640,39 @@ static struct
638
640
639
641
char *fil_path= fil_make_filepath (nullptr , {filename, strlen (filename)},
640
642
IBD, false );
641
- const item defer= {lsn, fil_path};
642
- auto p= defers.emplace (space, defer);
643
- if (!p.second && p.first ->second .lsn <= defer.lsn )
644
- p.first ->second = defer;
643
+ const item defer{lsn, fil_path, false };
645
644
ut_free (fil_path);
645
+
646
+ /* The file name must be unique. Keep the one with the latest LSN. */
647
+ auto d= defers.begin ();
648
+
649
+ while (d != defers.end ())
650
+ {
651
+ if (d->second .file_name != defer.file_name )
652
+ ++d;
653
+ else if (d->first == space)
654
+ {
655
+ /* Neither the file name nor the tablespace ID changed.
656
+ Update the LSN if needed. */
657
+ if (d->second .lsn < lsn)
658
+ d->second .lsn = lsn;
659
+ return ;
660
+ }
661
+ else if (d->second .lsn < lsn)
662
+ defers.erase (d++);
663
+ else
664
+ {
665
+ ut_ad (d->second .lsn != lsn);
666
+ return ; /* A later tablespace already has this name. */
667
+ }
668
+ }
669
+
670
+ auto p= defers.emplace (space, defer);
671
+ if (!p.second && p.first ->second .lsn <= lsn)
672
+ {
673
+ p.first ->second .lsn = lsn;
674
+ p.first ->second .file_name = defer.file_name ;
675
+ }
646
676
}
647
677
648
678
void remove (uint32_t space)
@@ -684,20 +714,42 @@ static struct
684
714
const uint32_t space_id{d->first };
685
715
recv_sys_t ::map::iterator p{recv_sys.pages .lower_bound ({space_id,0 })};
686
716
687
- if (p == recv_sys.pages .end () || p->first .space () != space_id)
717
+ if (d->second .deleted ||
718
+ p == recv_sys.pages .end () || p->first .space () != space_id)
688
719
{
689
- /* No pages were recovered. We create a dummy tablespace,
690
- and let dict_drop_index_tree() delete the file. */
720
+ /* We found a FILE_DELETE record for the tablespace, or
721
+ there were no buffered records. Either way, we must create a
722
+ dummy tablespace with the latest known name,
723
+ for dict_drop_index_tree(). */
724
+ while (p != recv_sys.pages .end () && p->first .space () == space_id)
725
+ {
726
+ recv_sys_t ::map::iterator r= p++;
727
+ r->second .log .clear ();
728
+ recv_sys.pages .erase (r);
729
+ }
691
730
recv_spaces_t ::iterator it{recv_spaces.find (space_id)};
692
731
if (it != recv_spaces.end ())
693
- create (it, d->second .file_name , static_cast <uint32_t >
732
+ {
733
+ const std::string *name= &d->second .file_name ;
734
+ if (d->second .deleted )
735
+ {
736
+ const auto r= renamed_spaces.find (space_id);
737
+ if (r != renamed_spaces.end ())
738
+ name= &r->second ;
739
+ bool exists;
740
+ os_file_type_t ftype;
741
+ if (!os_file_status (name->c_str (), &exists, &ftype) || !exists)
742
+ goto processed;
743
+ }
744
+ create (it, *name, static_cast <uint32_t >
694
745
(1U << FSP_FLAGS_FCRC32_POS_MARKER |
695
- FSP_FLAGS_FCRC32_PAGE_SSIZE ()), nullptr , 0 );
746
+ FSP_FLAGS_FCRC32_PAGE_SSIZE ()), nullptr , 0 );
747
+ }
696
748
}
697
749
else
698
750
fail= recv_sys.recover_deferred (p, d->second .file_name , free_block);
699
- auto e= d++;
700
- defers.erase (e );
751
+ processed:
752
+ defers.erase (d++ );
701
753
if (fail)
702
754
break ;
703
755
if (free_block)
@@ -791,11 +843,13 @@ bool recv_sys_t::recover_deferred(recv_sys_t::map::iterator &p,
791
843
space->release ();
792
844
return false ;
793
845
}
846
+ goto fail;
794
847
}
795
848
796
849
block->unfix ();
797
850
}
798
851
852
+ fail:
799
853
ib::error () << " Cannot apply log to " << first
800
854
<< " of corrupted file '" << name << " '" ;
801
855
return true ;
@@ -1034,9 +1088,11 @@ fil_name_process(char* name, ulint len, ulint space_id,
1034
1088
1035
1089
if (deleted) {
1036
1090
/* Got FILE_DELETE */
1091
+ if (auto d = deferred_spaces.find (static_cast <uint32_t >(
1092
+ space_id))) {
1093
+ d->deleted = true ;
1094
+ }
1037
1095
1038
- deferred_spaces.remove (
1039
- static_cast <uint32_t >(space_id));
1040
1096
if (!p.second && f.status != file_name_t ::DELETED) {
1041
1097
f.status = file_name_t ::DELETED;
1042
1098
if (f.space != NULL ) {
@@ -2988,18 +3044,26 @@ void recv_sys_t::apply(bool last_batch)
2988
3044
auto d= deferred_spaces.defers .find (space_id);
2989
3045
if (d != deferred_spaces.defers .end ())
2990
3046
{
2991
- if (recover_deferred (p, d->second .file_name , free_block) )
3047
+ if (d->second .deleted )
2992
3048
{
2993
- if (!srv_force_recovery)
2994
- set_corrupt_fs ();
3049
+ /* For deleted files we must preserve the entry in deferred_spaces */
3050
+ erase_for_space:
2995
3051
while (p != pages.end () && p->first .space () == space_id)
2996
3052
{
2997
3053
map::iterator r= p++;
2998
3054
r->second .log .clear ();
2999
3055
pages.erase (r);
3000
3056
}
3001
3057
}
3002
- deferred_spaces.defers .erase (d);
3058
+ else if (recover_deferred (p, d->second .file_name , free_block))
3059
+ {
3060
+ if (!srv_force_recovery)
3061
+ set_corrupt_fs ();
3062
+ deferred_spaces.defers .erase (d);
3063
+ goto erase_for_space;
3064
+ }
3065
+ else
3066
+ deferred_spaces.defers .erase (d);
3003
3067
if (!free_block)
3004
3068
goto next_free_block;
3005
3069
p= pages.lower_bound (page_id);
@@ -3685,12 +3749,16 @@ static dberr_t recv_rename_files()
3685
3749
3686
3750
dberr_t err= DB_SUCCESS;
3687
3751
3688
- for (const auto &r : renamed_spaces)
3752
+ for (auto i= renamed_spaces. begin (); i != renamed_spaces. end (); )
3689
3753
{
3754
+ const auto &r= *i;
3690
3755
const uint32_t id= r.first ;
3691
3756
fil_space_t *space= fil_space_t::get (id);
3692
3757
if (!space)
3758
+ {
3759
+ i++;
3693
3760
continue ;
3761
+ }
3694
3762
ut_ad (UT_LIST_GET_LEN (space->chain ) == 1 );
3695
3763
char *old= space->chain .start ->name ;
3696
3764
if (r.second != old)
@@ -3743,8 +3811,8 @@ static dberr_t recv_rename_files()
3743
3811
recv_sys.set_corrupt_fs ();
3744
3812
break ;
3745
3813
}
3814
+ renamed_spaces.erase (i++);
3746
3815
}
3747
- renamed_spaces.clear ();
3748
3816
return err;
3749
3817
}
3750
3818
0 commit comments