26
26
27
27
#include < iostream>
28
28
#include < sstream>
29
+ #include < unordered_set>
29
30
30
31
#include " m_string.h"
31
32
#include " sql/ndb_conflict.h"
42
43
extern Ndb* g_ndb;
43
44
extern mysql_mutex_t ndbcluster_mutex;
44
45
45
- // / Table lock handling
46
+ // List of NDB_SHARE's which correspond to an open table.
46
47
std::unique_ptr<collation_unordered_map<std::string, NDB_SHARE *>>
47
- ndbcluster_open_tables, ndbcluster_dropped_tables;
48
+ ndbcluster_open_tables;
49
+
50
+ // List of NDB_SHARE's which have been dropped, they are kept in this list
51
+ // until all references to them have been released.
52
+ static std::unordered_set<NDB_SHARE*> dropped_shares;
48
53
49
54
NDB_SHARE*
50
55
NDB_SHARE::create (const char * key)
@@ -674,58 +679,46 @@ NDB_SHARE::initialize(CHARSET_INFO* charset)
674
679
ndbcluster_open_tables.reset
675
680
(new collation_unordered_map<std::string, NDB_SHARE *>
676
681
(charset, PSI_INSTRUMENT_ME));
677
- ndbcluster_dropped_tables.reset
678
- (new collation_unordered_map<std::string, NDB_SHARE *>
679
- (charset, PSI_INSTRUMENT_ME));
680
682
}
681
683
682
684
683
685
void
684
686
NDB_SHARE::deinitialize (void )
685
687
{
686
- {
687
- mysql_mutex_lock (&ndbcluster_mutex);
688
- auto save = ndbcluster_open_tables->size ();
689
- (void )save;
690
- while (!ndbcluster_open_tables->empty ())
691
- {
692
- NDB_SHARE *share= ndbcluster_open_tables->begin ()->second ;
693
- #ifndef DBUG_OFF
694
- fprintf (stderr,
695
- " NDB: table share %s with use_count %d state: %s(%u) still open\n " ,
696
- share->key_string (), share->use_count (),
697
- share->share_state_string (),
698
- (uint )share->state );
699
- #endif
688
+ mysql_mutex_lock (&ndbcluster_mutex);
700
689
701
- // If last ref, share is destructed, else moved to dropped_tables (see below)
702
- NDB_SHARE::mark_share_dropped (&share);
703
- }
704
- mysql_mutex_unlock (&ndbcluster_mutex);
705
- DBUG_ASSERT (save == 0 );
690
+ // There should not be any NDB_SHARE's left -> crash after logging in debug
691
+ const class Debug_require {
692
+ const bool m_required_val;
693
+
694
+ public:
695
+ Debug_require (bool val) : m_required_val(val) {}
696
+ ~Debug_require () { DBUG_ASSERT (m_required_val); }
697
+ } shares_remaining (ndbcluster_open_tables->empty () && dropped_shares.empty ());
698
+
699
+ // Drop remaining open shares, drop one NDB_SHARE after the other
700
+ // until open tables list is empty
701
+ while (!ndbcluster_open_tables->empty ()) {
702
+ NDB_SHARE *share = ndbcluster_open_tables->begin ()->second ;
703
+ ndb_log_error (" Still open NDB_SHARE '%s', use_count: %d, state: %s" ,
704
+ share->key_string (), share->use_count (),
705
+ share->share_state_string ());
706
+ // If last ref, share is destroyed immediately, else moved to list of
707
+ // dropped shares
708
+ NDB_SHARE::mark_share_dropped (&share);
706
709
}
707
- ndbcluster_open_tables->clear ();
708
710
709
- {
710
- mysql_mutex_lock (&ndbcluster_mutex);
711
- auto save = ndbcluster_dropped_tables->size ();
712
- (void )save;
713
- while (!ndbcluster_dropped_tables->empty ())
714
- {
715
- NDB_SHARE *share= ndbcluster_dropped_tables->begin ()->second ;
716
- #ifndef DBUG_OFF
717
- fprintf (stderr,
718
- " NDB: table share %s with use_count %d state: %s(%u) not freed\n " ,
719
- share->key_string (), share->use_count (),
720
- share->share_state_string (),
721
- (uint )share->state );
722
- #endif
723
- NDB_SHARE::real_free_share (&share);
724
- }
725
- mysql_mutex_unlock (&ndbcluster_mutex);
726
- DBUG_ASSERT (save == 0 );
711
+ // Release remaining dropped shares, release one NDB_SHARE after the other
712
+ // until dropped list is empty
713
+ while (!dropped_shares.empty ()) {
714
+ NDB_SHARE *share = *dropped_shares.begin ();
715
+ ndb_log_error (" Not freed NDB_SHARE '%s', use_count: %d, state: %s" ,
716
+ share->key_string (), share->use_count (),
717
+ share->share_state_string ());
718
+ NDB_SHARE::real_free_share (&share);
727
719
}
728
- ndbcluster_dropped_tables.reset ();
720
+
721
+ mysql_mutex_unlock (&ndbcluster_mutex);
729
722
}
730
723
731
724
@@ -756,14 +749,13 @@ void NDB_SHARE::real_free_share(NDB_SHARE **share_ptr) {
756
749
ndbcluster::ndbrequire (share->state == NSS_DROPPED);
757
750
758
751
// Share must be in dropped list
759
- ndbcluster::ndbrequire (
760
- find_or_nullptr (*ndbcluster_dropped_tables, share->key_string ()));
752
+ ndbcluster::ndbrequire (dropped_shares.find (share) != dropped_shares.end ());
761
753
762
754
// Remove share from dropped list
763
- ndbcluster::ndbrequire (ndbcluster_dropped_tables-> erase (share-> key_string () ));
755
+ ndbcluster::ndbrequire (dropped_shares. erase (share));
764
756
765
- // Remove shares reference from 'ndbcluster_dropped_tables '
766
- share->refs_erase (" ndbcluster_dropped_tables " );
757
+ // Remove shares reference from 'dropped_shares '
758
+ share->refs_erase (" dropped_shares " );
767
759
768
760
NDB_SHARE::destroy (share);
769
761
}
@@ -808,14 +800,16 @@ void NDB_SHARE::mark_share_dropped(NDB_SHARE **share_ptr) {
808
800
809
801
// Someone is still using the NDB_SHARE, insert it into the list of dropped
810
802
// to keep track of it until all references has been released
811
- ndbcluster_dropped_tables-> emplace (share-> key_string (), share);
803
+ dropped_shares. emplace (share);
812
804
805
+ #ifndef DBUG_OFF
813
806
std::string s;
814
807
share->debug_print (s, " \n " );
815
808
std::cerr << " dropped_share: " << s << std::endl;
809
+ #endif
816
810
817
- // Share is referenced by 'ndbcluster_dropped_tables '
818
- share->refs_insert (" ndbcluster_dropped_tables " );
811
+ // Share is referenced by 'dropped_shares '
812
+ share->refs_insert (" dropped_shares " );
819
813
// NOTE! The refcount has not been incremented
820
814
}
821
815
@@ -836,14 +830,10 @@ NDB_SHARE::dbg_check_shares_update()
836
830
}
837
831
838
832
ndb_log_info (" dbug_check_shares dropped:" );
839
- for (const auto &key_and_value : *ndbcluster_dropped_tables)
840
- {
841
- const NDB_SHARE *share= key_and_value.second ;
842
- ndb_log_info (" %s.%s: state: %s(%u) use_count: %u" ,
843
- share->db , share->table_name ,
844
- share->share_state_string (),
845
- (unsigned )share->state ,
846
- share->use_count ());
833
+ for (const NDB_SHARE * share: dropped_shares) {
834
+ ndb_log_info (" %s.%s: state: %s(%u) use_count: %u" , share->db ,
835
+ share->table_name , share->share_state_string (),
836
+ (unsigned )share->state , share->use_count ());
847
837
assert (share->state == NSS_DROPPED);
848
838
}
849
839
@@ -857,11 +847,9 @@ NDB_SHARE::dbg_check_shares_update()
857
847
}
858
848
859
849
/* *
860
- * Only shares in mysql database may be open ...
850
+ * Only shares in mysql database may be in dropped list ...
861
851
*/
862
- for (const auto &key_and_value : *ndbcluster_dropped_tables)
863
- {
864
- const NDB_SHARE *share= key_and_value.second ;
852
+ for (const NDB_SHARE *share : dropped_shares) {
865
853
assert (strcmp (share->db , " mysql" ) == 0 );
866
854
}
867
855
}
0 commit comments