1 /*
2    Copyright (c) 2011, 2021, Oracle and/or its affiliates.
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License, version 2.0,
6    as published by the Free Software Foundation.
7 
8    This program is also distributed with certain software (including
9    but not limited to OpenSSL) that is licensed under separate terms,
10    as designated in a particular file or component or in included license
11    documentation.  The authors of MySQL hereby grant you an additional
12    permission to link the program and your derivative works with the
13    separately licensed software that they have included with MySQL.
14 
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License, version 2.0, for more details.
19 
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
23 */
24 
25 #include "ndb_component.h"
26 
Ndb_component(const char * name)27 Ndb_component::Ndb_component(const char *name)
28   : m_thread_state(TS_UNINIT),
29     m_name(name)
30 {
31 }
32 
~Ndb_component()33 Ndb_component::~Ndb_component()
34 {
35 
36 }
37 
38 int
init()39 Ndb_component::init()
40 {
41   assert(m_thread_state == TS_UNINIT);
42 
43   native_mutex_init(&m_start_stop_mutex, MY_MUTEX_INIT_FAST);
44   native_cond_init(&m_start_stop_cond);
45 
46   int res= do_init();
47   if (res == 0)
48   {
49     m_thread_state= TS_INIT;
50   }
51   return res;
52 }
53 
54 extern "C" void *
Ndb_component_run_C(void * arg)55 Ndb_component_run_C(void * arg)
56 {
57   my_thread_init();
58   Ndb_component * self = reinterpret_cast<Ndb_component*>(arg);
59   self->run_impl();
60   my_thread_end();
61   my_thread_exit(0);
62   return NULL;                              // Avoid compiler warnings
63 }
64 
65 extern my_thread_attr_t connection_attrib; // mysql global pthread attr
66 
67 int
start()68 Ndb_component::start()
69 {
70   assert(m_thread_state == TS_INIT);
71   native_mutex_lock(&m_start_stop_mutex);
72   m_thread_state= TS_STARTING;
73   int res= my_thread_create(&m_thread, &connection_attrib, Ndb_component_run_C,
74                             this);
75 
76   if (res == 0)
77   {
78     while (m_thread_state == TS_STARTING)
79     {
80       native_cond_wait(&m_start_stop_cond, &m_start_stop_mutex);
81     }
82     native_mutex_unlock(&m_start_stop_mutex);
83     return m_thread_state == TS_RUNNING ? 0 : 1;
84   }
85 
86   native_mutex_unlock(&m_start_stop_mutex);
87   return res;
88 }
89 
90 void
run_impl()91 Ndb_component::run_impl()
92 {
93   native_mutex_lock(&m_start_stop_mutex);
94   if (m_thread_state == TS_STARTING)
95   {
96     m_thread_state= TS_RUNNING;
97     native_cond_signal(&m_start_stop_cond);
98     native_mutex_unlock(&m_start_stop_mutex);
99     do_run();
100     native_mutex_lock(&m_start_stop_mutex);
101   }
102   m_thread_state = TS_STOPPED;
103   native_cond_signal(&m_start_stop_cond);
104   native_mutex_unlock(&m_start_stop_mutex);
105 }
106 
107 bool
is_stop_requested()108 Ndb_component::is_stop_requested()
109 {
110   bool res = false;
111   native_mutex_lock(&m_start_stop_mutex);
112   res = m_thread_state != TS_RUNNING;
113   native_mutex_unlock(&m_start_stop_mutex);
114   return res;
115 }
116 
117 int
stop()118 Ndb_component::stop()
119 {
120   log_info("Stop");
121   native_mutex_lock(&m_start_stop_mutex);
122   assert(m_thread_state == TS_RUNNING ||
123          m_thread_state == TS_STOPPING ||
124          m_thread_state == TS_STOPPED);
125 
126   if (m_thread_state == TS_RUNNING)
127   {
128     m_thread_state= TS_STOPPING;
129   }
130 
131   // Give subclass a call, should wake itself up to quickly detect the stop
132   do_wakeup();
133 
134   if (m_thread_state == TS_STOPPING)
135   {
136     while (m_thread_state != TS_STOPPED)
137     {
138       native_cond_signal(&m_start_stop_cond);
139       native_cond_wait(&m_start_stop_cond, &m_start_stop_mutex);
140     }
141   }
142   native_mutex_unlock(&m_start_stop_mutex);
143   log_info("Stop completed");
144 
145   return 0;
146 }
147 
148 int
deinit()149 Ndb_component::deinit()
150 {
151   assert(m_thread_state == TS_STOPPED);
152   native_mutex_destroy(&m_start_stop_mutex);
153   native_cond_destroy(&m_start_stop_cond);
154   return do_deinit();
155 }
156 
157 #include "ndb_log.h"
158 
159 
log_verbose(unsigned verbose_level,const char * fmt,...)160 void Ndb_component::log_verbose(unsigned verbose_level, const char *fmt, ...)
161 {
162   // Print message only if verbose level is set high enough
163   if (ndb_log_get_verbose_level() < verbose_level)
164     return;
165 
166   va_list args;
167   va_start(args, fmt);
168   ndb_log_print(NDB_LOG_INFORMATION_LEVEL, m_name, fmt, args);
169   va_end(args);
170 }
171 
172 
log_error(const char * fmt,...)173 void Ndb_component::log_error(const char *fmt, ...)
174 {
175   va_list args;
176   va_start(args, fmt);
177   ndb_log_print(NDB_LOG_ERROR_LEVEL, m_name, fmt, args);
178   va_end(args);
179 }
180 
181 
log_warning(const char * fmt,...)182 void Ndb_component::log_warning(const char *fmt, ...)
183 {
184   va_list args;
185   va_start(args, fmt);
186   ndb_log_print(NDB_LOG_WARNING_LEVEL, m_name, fmt, args);
187   va_end(args);
188 }
189 
190 
log_info(const char * fmt,...)191 void Ndb_component::log_info(const char *fmt, ...)
192 {
193   va_list args;
194   va_start(args, fmt);
195   ndb_log_print(NDB_LOG_INFORMATION_LEVEL, m_name, fmt, args);
196   va_end(args);
197 }
198