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