25
25
26
26
#include < algorithm>
27
27
#include < chrono>
28
- #include < condition_variable>
29
28
#include < cstdint>
30
29
#include < functional>
31
30
#include < iterator>
57
56
#include " mysqlshdk/libs/utils/rate_limit.h"
58
57
#include " mysqlshdk/libs/utils/std.h"
59
58
#include " mysqlshdk/libs/utils/strformat.h"
59
+ #include " mysqlshdk/libs/utils/utils_file.h"
60
60
#include " mysqlshdk/libs/utils/utils_general.h"
61
61
#include " mysqlshdk/libs/utils/utils_lexing.h"
62
62
#include " mysqlshdk/libs/utils/utils_mysql_parsing.h"
@@ -345,31 +345,6 @@ bool check_if_transactions_are_ddl_safe(
345
345
346
346
} // namespace
347
347
348
- class Dumper ::Synchronize_workers final {
349
- public:
350
- Synchronize_workers () = default ;
351
- ~Synchronize_workers () = default ;
352
-
353
- void wait_for (const uint16_t count) {
354
- std::unique_lock<std::mutex> lock (m_mutex);
355
- m_condition.wait (lock, [this , count]() { return m_count >= count; });
356
- m_count -= count;
357
- }
358
-
359
- void notify () {
360
- {
361
- std::lock_guard<std::mutex> lock (m_mutex);
362
- ++m_count;
363
- }
364
- m_condition.notify_one ();
365
- }
366
-
367
- private:
368
- std::mutex m_mutex;
369
- std::condition_variable m_condition;
370
- uint16_t m_count = 0 ;
371
- };
372
-
373
348
class Dumper ::Dump_writer_controller {
374
349
public:
375
350
using Create_file = std::function<std::unique_ptr<mysqlshdk::storage::IFile>(
@@ -705,6 +680,12 @@ class Dumper::Table_worker final {
705
680
706
681
~Table_worker () = default ;
707
682
683
+ void release_session () {
684
+ if (m_session) {
685
+ m_dumper->session_pool ().push (std::move (m_session));
686
+ }
687
+ }
688
+
708
689
void run () {
709
690
std::string context;
710
691
@@ -714,14 +695,6 @@ class Dumper::Table_worker final {
714
695
{" id" , std::to_string (m_id)}}));
715
696
716
697
mysqlsh::Mysql_thread mysql_thread;
717
- shcore::on_leave_scope close_session ([this ]() {
718
- if (m_session) {
719
- m_session->close ();
720
- }
721
- });
722
-
723
- open_session ();
724
-
725
698
m_rate_limit =
726
699
mysqlshdk::utils::Rate_limit (m_dumper->m_options .max_rate ());
727
700
@@ -738,14 +711,20 @@ class Dumper::Table_worker final {
738
711
739
712
context = std::move (work.info );
740
713
714
+ m_session = m_dumper->session_pool ().pop ();
715
+ shcore::on_leave_scope session_releaser (
716
+ [this ]() { release_session (); });
717
+
718
+ if (m_dumper->m_worker_interrupt ) {
719
+ return ;
720
+ }
721
+
741
722
work.task (this );
742
723
743
724
if (m_dumper->m_worker_interrupt ) {
744
725
return ;
745
726
}
746
727
}
747
-
748
- m_dumper->assert_transaction_is_open (m_session);
749
728
} catch (const mysqlshdk::db::Error &e) {
750
729
handle_exception (context, e.format ().c_str ());
751
730
} catch (const shcore::Error &e) {
@@ -765,18 +744,6 @@ class Dumper::Table_worker final {
765
744
private:
766
745
friend class Dumper ;
767
746
768
- void open_session () {
769
- // notify dumper that the session has been established
770
- shcore::on_leave_scope notify_dumper (
771
- [this ]() { m_dumper->m_worker_synchronization ->notify (); });
772
-
773
- m_session =
774
- establish_session (m_dumper->session ()->get_connection_options (), false );
775
-
776
- m_dumper->start_transaction (m_session);
777
- m_dumper->on_init_thread_session (m_session);
778
- }
779
-
780
747
inline std::shared_ptr<mysqlshdk::db::IResult> query (
781
748
const std::string &sql) const {
782
749
return Dumper::query (m_session, sql);
@@ -875,6 +842,8 @@ class Dumper::Table_worker final {
875
842
throw ;
876
843
}
877
844
845
+ release_session ();
846
+
878
847
controller->finish_writing ();
879
848
880
849
duration.finish ();
@@ -1579,6 +1548,7 @@ class Dumper::Table_worker final {
1579
1548
1580
1549
void handle_exception (const std::string &context, const char *msg) {
1581
1550
m_dumper->m_worker_exceptions [m_id] = std::current_exception ();
1551
+ m_dumper->m_worker_exception_thrown = true ;
1582
1552
current_console ()->print_error (
1583
1553
m_log_id + (context.empty () ? " " : " Error while " + context + " : " ) +
1584
1554
msg);
@@ -1828,10 +1798,6 @@ Dumper::Dumper(const Dump_options &options)
1828
1798
mysqlshdk::storage::get_extension (m_options.compression ());
1829
1799
}
1830
1800
1831
- // needs to be defined here due to Dumper::Synchronize_workers being
1832
- // incomplete type
1833
- Dumper::~Dumper () = default ;
1834
-
1835
1801
void Dumper::run () {
1836
1802
if (m_options.is_dry_run ()) {
1837
1803
current_console ()->print_info (
@@ -1934,15 +1900,15 @@ void Dumper::do_run() {
1934
1900
return ;
1935
1901
}
1936
1902
1903
+ create_worker_sessions ();
1904
+
1937
1905
create_worker_threads ();
1938
1906
1939
1907
m_current_stage->finish ();
1940
1908
1941
1909
// initialize cache while threads are starting up
1942
1910
initialize_instance_cache ();
1943
1911
1944
- wait_for_workers ();
1945
-
1946
1912
if (m_options.consistent_dump () && !m_worker_interrupt) {
1947
1913
current_console ()->print_info (" All transactions have been started" );
1948
1914
lock_instance ();
@@ -1956,6 +1922,20 @@ void Dumper::do_run() {
1956
1922
}
1957
1923
}
1958
1924
1925
+ shcore::on_leave_scope cleanup ([this ]() {
1926
+ // Ensures all the worker sessions get closed
1927
+ size_t worker_sessions = m_options.threads ();
1928
+ while (worker_sessions) {
1929
+ auto session = m_session_pool.pop ();
1930
+
1931
+ if (!m_worker_exception_thrown) {
1932
+ assert_transaction_is_open (session);
1933
+ }
1934
+ session->close ();
1935
+ --worker_sessions;
1936
+ }
1937
+ });
1938
+
1959
1939
create_schema_tasks ();
1960
1940
1961
1941
validate_privileges ();
@@ -2803,23 +2783,30 @@ void Dumper::close_output_directory() {
2803
2783
m_output_dir.reset ();
2804
2784
}
2805
2785
2786
+ void Dumper::create_worker_sessions () {
2787
+ for (std::size_t i = 0 ; i < m_options.threads (); ++i) {
2788
+ auto worker_session =
2789
+ establish_session (session ()->get_connection_options (), false );
2790
+
2791
+ start_transaction (worker_session);
2792
+ on_init_thread_session (worker_session);
2793
+
2794
+ m_session_pool.push (std::move (worker_session));
2795
+ }
2796
+ }
2797
+
2806
2798
void Dumper::create_worker_threads () {
2807
2799
m_worker_exceptions.clear ();
2808
- m_worker_exceptions.resize (m_options.threads ());
2809
- m_worker_synchronization = std::make_unique<Synchronize_workers>();
2800
+ m_worker_exceptions.resize (m_options.worker_threads ());
2810
2801
2811
- for (std::size_t i = 0 ; i < m_options.threads (); ++i) {
2802
+ for (std::size_t i = 0 ; i < m_options.worker_threads (); ++i) {
2812
2803
auto t = mysqlsh::spawn_scoped_thread (
2813
2804
&Table_worker::run,
2814
2805
Table_worker{i, this , Table_worker::Exception_strategy::ABORT});
2815
2806
m_workers.emplace_back (std::move (t));
2816
2807
}
2817
2808
}
2818
2809
2819
- void Dumper::wait_for_workers () {
2820
- m_worker_synchronization->wait_for (m_workers.size ());
2821
- }
2822
-
2823
2810
void Dumper::maybe_push_shutdown_tasks () {
2824
2811
if (0 == m_chunking_tasks &&
2825
2812
m_main_thread_finished_producing_chunking_tasks) {
0 commit comments