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);