19 #include <mysql/plugin.h>
20 #include <ndbapi/NdbApi.hpp>
21 #include <portlib/NdbTick.h>
26 void do_retry_sleep(
unsigned milli_sleep)
28 my_sleep(1000*(milli_sleep + 5*(rand()%(milli_sleep/5))));
32 #include "ndb_table_guard.h"
42 gsl_lock_ext(THD *thd,
Ndb *ndb,
NdbError &ndb_error,
57 time_end= NdbTick_CurrentMillisecond();
58 time_end+= retry_time * 1000;
64 if (!(ndbtab= ndbtab_g.get_table()))
82 op->
equal(
"SYSKEY_0", NDB_BACKUP_SEQUENCE);
89 else if (thd_killed(thd))
95 time_end < NdbTick_CurrentMillisecond())
102 do_retry_sleep(retry_sleep);
134 static int gsl_is_locked_or_queued= 0;
135 static int gsl_no_locking_allowed= 0;
136 static pthread_mutex_t gsl_mutex;
142 static bool gsl_initialized=
false;
147 #include <sql_class.h>
153 : m_thd(thd), m_proc_info(NULL) {}
156 const char* old= thd_proc_info(m_thd,
message);
166 thd_proc_info(m_thd, m_proc_info);
170 const char *m_proc_info;
175 #include "ndb_thd_ndb.h"
178 extern ulong opt_ndb_extra_logging;
182 ndbcluster_global_schema_lock(THD *thd,
bool no_lock_queue,
183 bool report_cluster_disconnected)
185 if (!gsl_initialized)
188 Ndb *ndb= check_ndb_in_thd(thd);
189 Thd_ndb *thd_ndb= get_thd_ndb(thd);
191 if (thd_ndb->options & TNO_NO_LOCK_SCHEMA_OP)
193 DBUG_ENTER(
"ndbcluster_global_schema_lock");
194 DBUG_PRINT(
"enter", (
"query: '%-.4096s', no_lock_queue: %d",
195 *thd_query(thd), no_lock_queue));
196 if (thd_ndb->global_schema_lock_count)
198 if (thd_ndb->global_schema_lock_trans)
199 thd_ndb->global_schema_lock_trans->
refresh();
201 DBUG_ASSERT(thd_ndb->global_schema_lock_error != 0);
202 thd_ndb->global_schema_lock_count++;
203 DBUG_PRINT(
"exit", (
"global_schema_lock_count: %d",
204 thd_ndb->global_schema_lock_count));
207 DBUG_ASSERT(thd_ndb->global_schema_lock_count == 0);
208 thd_ndb->global_schema_lock_count= 1;
209 thd_ndb->global_schema_lock_error= 0;
210 DBUG_PRINT(
"exit", (
"global_schema_lock_count: %d",
211 thd_ndb->global_schema_lock_count));
220 pthread_mutex_lock(&gsl_mutex);
222 gsl_is_locked_or_queued++;
225 if (gsl_is_locked_or_queued != 1)
228 pthread_mutex_unlock(&gsl_mutex);
229 thd_ndb->global_schema_lock_error= -1;
230 DBUG_PRINT(
"exit", (
"aborting as lock exists"));
234 gsl_no_locking_allowed= 1;
238 while (gsl_no_locking_allowed)
240 proc_info.set(
"Waiting for allowed to take ndbcluster global schema lock");
242 pthread_mutex_unlock(&gsl_mutex);
246 thd_ndb->global_schema_lock_error= -1;
249 pthread_mutex_lock(&gsl_mutex);
252 pthread_mutex_unlock(&gsl_mutex);
257 proc_info.set(
"Waiting for ndbcluster global schema lock");
258 thd_ndb->global_schema_lock_trans= gsl_lock_ext(thd, ndb, ndb_error, -1);
260 DBUG_EXECUTE_IF(
"sleep_after_global_schema_lock", my_sleep(6000000););
264 pthread_mutex_lock(&gsl_mutex);
266 gsl_no_locking_allowed= 0;
267 pthread_mutex_unlock(&gsl_mutex);
270 if (thd_ndb->global_schema_lock_trans)
272 if (opt_ndb_extra_logging > 19)
274 sql_print_information(
"NDB: Global schema lock acquired");
278 thd_ndb->schema_locks_count++;
279 DBUG_PRINT(
"info", (
"schema_locks_count: %d",
280 thd_ndb->schema_locks_count));
285 if (ndb_error.
code != 4009 || report_cluster_disconnected)
287 sql_print_warning(
"NDB: Could not acquire global schema lock (%d)%s",
289 push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
290 ER_GET_ERRMSG, ER_DEFAULT(ER_GET_ERRMSG),
292 "NDB. Could not acquire global schema lock");
294 thd_ndb->global_schema_lock_error= ndb_error.
code ? ndb_error.
code : -1;
301 ndbcluster_global_schema_unlock(THD *thd)
303 if (!gsl_initialized)
306 Thd_ndb *thd_ndb= get_thd_ndb(thd);
307 DBUG_ASSERT(thd_ndb != 0);
308 if (thd_ndb == 0 || (thd_ndb->options & TNO_NO_LOCK_SCHEMA_OP))
310 Ndb *ndb= thd_ndb->ndb;
311 DBUG_ENTER(
"ndbcluster_global_schema_unlock");
313 thd_ndb->global_schema_lock_count--;
314 DBUG_PRINT(
"exit", (
"global_schema_lock_count: %d",
315 thd_ndb->global_schema_lock_count));
316 DBUG_ASSERT(ndb != NULL);
319 DBUG_ASSERT(trans != NULL || thd_ndb->global_schema_lock_error != 0);
320 if (thd_ndb->global_schema_lock_count != 0)
324 thd_ndb->global_schema_lock_error= 0;
329 pthread_mutex_lock(&gsl_mutex);
330 gsl_is_locked_or_queued--;
331 pthread_mutex_unlock(&gsl_mutex);
335 thd_ndb->global_schema_lock_trans= NULL;
337 if (!gsl_unlock_ext(ndb, trans, ndb_error))
339 sql_print_warning(
"NDB: Releasing global schema lock (%d)%s",
341 push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
342 ER_GET_ERRMSG, ER_DEFAULT(ER_GET_ERRMSG),
345 "ndb. Releasing global schema lock");
348 if (opt_ndb_extra_logging > 19)
350 sql_print_information(
"NDB: Global schema lock release");
357 #ifndef NDB_WITHOUT_GLOBAL_SCHEMA_LOCK
360 ndbcluster_global_schema_func(THD *thd,
bool lock,
void* args)
364 bool no_lock_queue = (bool)args;
365 return ndbcluster_global_schema_lock(thd, no_lock_queue,
true);
368 return ndbcluster_global_schema_unlock(thd);
373 #include "ndb_global_schema_lock.h"
375 void ndbcluster_global_schema_lock_init(
handlerton *hton)
377 assert(gsl_initialized ==
false);
378 assert(gsl_is_locked_or_queued == 0);
379 assert(gsl_no_locking_allowed == 0);
380 gsl_initialized=
true;
381 pthread_mutex_init(&gsl_mutex, MY_MUTEX_INIT_FAST);
383 #ifndef NDB_WITHOUT_GLOBAL_SCHEMA_LOCK
384 hton->global_schema_func= ndbcluster_global_schema_func;
389 void ndbcluster_global_schema_lock_deinit(
void)
391 assert(gsl_initialized ==
true);
392 assert(gsl_is_locked_or_queued == 0);
393 assert(gsl_no_locking_allowed == 0);
394 gsl_initialized=
false;
395 pthread_mutex_destroy(&gsl_mutex);
400 Thd_ndb::has_required_global_schema_lock(
const char* func)
402 #ifdef NDB_WITHOUT_GLOBAL_SCHEMA_LOCK
407 if (global_schema_lock_error)
415 if (global_schema_lock_trans)
417 global_schema_lock_trans->
refresh();
424 sql_print_error(
"NDB: programming error, no lock taken while running "
425 "query '%*s' in function '%s'",
426 (
int)query->length, query->str, func);
433 #include "ndb_global_schema_lock_guard.h"
435 Ndb_global_schema_lock_guard::Ndb_global_schema_lock_guard(THD *thd)
436 : m_thd(thd), m_locked(false)
441 Ndb_global_schema_lock_guard::~Ndb_global_schema_lock_guard()
444 ndbcluster_global_schema_unlock(m_thd);
448 int Ndb_global_schema_lock_guard::lock(
bool no_lock_queue,
449 bool report_cluster_disconnected)
461 return ndbcluster_global_schema_lock(m_thd, no_lock_queue,
462 report_cluster_disconnected);