List:Commits« Previous MessageNext Message »
From:Sergey Vojtovich Date:November 10 2011 9:57am
Subject:bzr push into mysql-trunk branch (sergey.vojtovich:3586 to 3588)
View as plain text  
 3588 Sergey Vojtovich	2011-11-10 [merge]
      (no message)

 3587 Sergey Vojtovich	2011-11-10 [merge]
      (no message)

    modified:
      sql/sql_class.h
      sql/sql_plugin.cc
 3586 Raghav Kapoor	2011-11-10
      BUG#11761014 - 53466: END_CONNECTION() SHOULD REFERENCE GLOBAL_SYSTEM_VARIABLES.LOG_WARNINGS 
      
      BACKGROUND:
      end_connection prints out messages like this, depending on *session*
      log_warnings value:
      Aborted connection 2 to db: 'unconnected' user: 'root' 
      host: '' (Got timeout reading communication packets).
      This is wrong because it allows a minimally privileged user
      to write copious amounts of errors to the .err file, unless 
      he is restricted by the number of MAX_CONNECTIONS_PER_HOUR 
      in his user account.
      
      FIX:
      "Aborted connection..." messages are now printed based on 
      the *global* log_warnings value. Since this was the only real
      remaining use of the session value of log_warnings, the 
      log_warnings system variable has now been made to a global 
      only variable. This is a change of behavior and must be 
      reflected in the documentation.  

    modified:
      mysql-test/r/variables.result
      mysql-test/suite/sys_vars/inc/log_warnings_basic.inc
      mysql-test/suite/sys_vars/r/log_warnings_basic_32.result
      mysql-test/suite/sys_vars/r/log_warnings_basic_64.result
      mysql-test/t/variables.test
      sql/binlog.cc
      sql/filesort.cc
      sql/log_event.cc
      sql/mysqld.cc
      sql/mysqld.h
      sql/rpl_reporting.cc
      sql/rpl_rli_pdb.cc
      sql/rpl_slave.cc
      sql/sql_acl.cc
      sql/sql_class.h
      sql/sql_connect.cc
      sql/sql_plugin.cc
      sql/sql_udf.cc
      sql/sys_vars.cc
      storage/innobase/handler/ha_innodb.cc
=== modified file 'sql/sql_class.h'
--- a/sql/sql_class.h	2011-11-10 06:53:27 +0000
+++ b/sql/sql_class.h	2011-11-10 09:55:20 +0000
@@ -435,8 +435,9 @@ typedef struct system_variables
   */ 
   ulong dynamic_variables_version;
   char* dynamic_variables_ptr;
-  uint dynamic_variables_head;  /* largest valid variable offset */
-  uint dynamic_variables_size;  /* how many bytes are in use */
+  uint dynamic_variables_head;    /* largest valid variable offset */
+  uint dynamic_variables_size;    /* how many bytes are in use */
+  LIST *dynamic_variables_allocs; /* memory hunks for PLUGIN_VAR_MEMALLOC */
   
   ulonglong max_heap_table_size;
   ulonglong tmp_table_size;

=== modified file 'sql/sql_plugin.cc'
--- a/sql/sql_plugin.cc	2011-11-10 06:53:27 +0000
+++ b/sql/sql_plugin.cc	2011-11-10 09:55:20 +0000
@@ -261,6 +261,13 @@ static bool register_builtin(struct st_m
 static void unlock_variables(THD *thd, struct system_variables *vars);
 static void cleanup_variables(THD *thd, struct system_variables *vars);
 static void plugin_vars_free_values(sys_var *vars);
+static bool plugin_var_memalloc_session_update(THD *thd,
+                                               struct st_mysql_sys_var *var,
+                                               char **dest, const char *value);
+static bool plugin_var_memalloc_global_update(THD *thd,
+                                              struct st_mysql_sys_var *var,
+                                              char **dest, const char *value);
+static void plugin_var_memalloc_free(struct system_variables *vars);
 static void restore_pluginvar_names(sys_var *first);
 static void plugin_opt_set_limits(struct my_option *,
                                   const struct st_mysql_sys_var *);
@@ -2317,15 +2324,7 @@ static void update_func_longlong(THD *th
 static void update_func_str(THD *thd, struct st_mysql_sys_var *var,
                              void *tgt, const void *save)
 {
-  char *old= *(char **) tgt;
-  *(char **)tgt= *(char **) save;
-  if (var->flags & PLUGIN_VAR_MEMALLOC)
-  {
-    if (*(char **) save != NULL) {
-      *(char **)tgt= my_strdup(*(char **) save, MYF(0));
-    }
-    my_free(old);
-  }
+  *(char **) tgt= *(char **) save;
 }
 
 
@@ -2584,11 +2583,13 @@ static uchar *intern_sys_var_ptr(THD* th
       if ((pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR &&
           pi->plugin_var->flags & PLUGIN_VAR_MEMALLOC)
       {
-         char **pp= (char**) (thd->variables.dynamic_variables_ptr +
-                             *(int*)(pi->plugin_var + 1));
-         if ((*pp= *(char**) (global_system_variables.dynamic_variables_ptr +
-                             *(int*)(pi->plugin_var + 1))))
-           *pp= my_strdup(*pp, MYF(MY_WME|MY_FAE));
+         int varoff= *(int *) (pi->plugin_var + 1);
+         char **thdvar= (char **) (thd->variables.
+                                   dynamic_variables_ptr + varoff);
+         char **sysvar= (char **) (global_system_variables.
+                                   dynamic_variables_ptr + varoff);
+         *thdvar= NULL;
+         plugin_var_memalloc_session_update(thd, NULL, thdvar, *sysvar);
       }
     }
 
@@ -2705,33 +2706,8 @@ static void unlock_variables(THD *thd, s
 */
 static void cleanup_variables(THD *thd, struct system_variables *vars)
 {
-  st_bookmark *v;
-  sys_var_pluginvar *pivar;
-  sys_var *var;
-  int flags;
-  uint idx;
-
-  mysql_rwlock_rdlock(&LOCK_system_variables_hash);
-  for (idx= 0; idx < bookmark_hash.records; idx++)
-  {
-    v= (st_bookmark*) my_hash_element(&bookmark_hash, idx);
-    if (v->version > vars->dynamic_variables_version ||
-        !(var= intern_find_sys_var(v->key + 1, v->name_len)) ||
-        !(pivar= var->cast_pluginvar()) ||
-        v->key[0] != (pivar->plugin_var->flags & PLUGIN_VAR_TYPEMASK))
-      continue;
-
-    flags= pivar->plugin_var->flags;
-
-    if ((flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR &&
-        flags & PLUGIN_VAR_THDLOCAL && flags & PLUGIN_VAR_MEMALLOC)
-    {
-      char **ptr= (char**) pivar->real_value_ptr(thd, OPT_SESSION);
-      my_free(*ptr);
-      *ptr= NULL;
-    }
-  }
-  mysql_rwlock_unlock(&LOCK_system_variables_hash);
+  if (thd)
+    plugin_var_memalloc_free(&thd->variables);
 
   DBUG_ASSERT(vars->table_plugin == NULL);
   DBUG_ASSERT(vars->temp_table_plugin == NULL);
@@ -2827,6 +2803,136 @@ static SHOW_TYPE pluginvar_show_type(st_
 }
 
 
+/**
+  Set value for thread local variable with PLUGIN_VAR_MEMALLOC flag.
+
+  @param[in]     thd   Thread context.
+  @param[in]     var   Plugin variable.
+  @param[in,out] dest  Destination memory pointer.
+  @param[in]     value '\0'-terminated new value.
+
+  Most plugin variable values are stored on dynamic_variables_ptr.
+  Releasing memory occupied by these values is as simple as freeing
+  dynamic_variables_ptr.
+
+  An exception to the rule are PLUGIN_VAR_MEMALLOC variables, which
+  are stored on individual memory hunks. All of these hunks has to
+  be freed when it comes to cleanup.
+
+  It may happen that a plugin was uninstalled and descriptors of
+  it's variables are lost. In this case it is impossible to locate
+  corresponding values.
+
+  In addition to allocating and setting variable value, new element
+  is added to dynamic_variables_allocs list. When thread is done, it
+  has to call plugin_var_memalloc_free() to release memory used by
+  PLUGIN_VAR_MEMALLOC variables.
+
+  If var is NULL, variable update function is not called. This is
+  needed when we take snapshot of system variables during thread
+  initialization.
+
+  @note List element and variable value are stored on the same memory
+  hunk. List element is followed by variable value.
+
+  @return Completion status
+  @retval false Success
+  @retval true  Failure
+*/
+
+static bool plugin_var_memalloc_session_update(THD *thd,
+                                               struct st_mysql_sys_var *var,
+                                               char **dest, const char *value)
+
+{
+  LIST *old_element= NULL;
+  struct system_variables *vars= &thd->variables;
+  DBUG_ENTER("plugin_var_memalloc_session_update");
+
+  if (value)
+  {
+    size_t length= strlen(value) + 1;
+    LIST *element;
+    if (!(element= (LIST *) my_malloc(sizeof(LIST) + length, MYF(MY_WME))))
+      DBUG_RETURN(true);
+    memcpy(element + 1, value, length);
+    value= (const char *) (element + 1);
+    vars->dynamic_variables_allocs= list_add(vars->dynamic_variables_allocs,
+                                             element);
+  }
+
+  if (*dest)
+    old_element= (LIST *) (*dest - sizeof(LIST));
+
+  if (var)
+    var->update(thd, var, (void **) dest, (const void *) &value);
+  else
+    *dest= (char *) value;
+
+  if (old_element)
+  {
+    vars->dynamic_variables_allocs= list_delete(vars->dynamic_variables_allocs,
+                                                old_element);
+    my_free(old_element);
+  }
+  DBUG_RETURN(false);
+}
+
+
+/**
+  Free all elements allocated by plugin_var_memalloc_session_update().
+
+  @param[in]     vars  system variables structure
+
+  @see plugin_var_memalloc_session_update
+*/
+
+static void plugin_var_memalloc_free(struct system_variables *vars)
+{
+  LIST *next, *root;
+  DBUG_ENTER("plugin_var_memalloc_free");
+  for (root= vars->dynamic_variables_allocs; root; root= next)
+  {
+    next= root->next;
+    my_free(root);
+  }
+  vars->dynamic_variables_allocs= NULL;
+  DBUG_VOID_RETURN;
+}
+
+
+/**
+  Set value for global variable with PLUGIN_VAR_MEMALLOC flag.
+
+  @param[in]     thd   Thread context.
+  @param[in]     var   Plugin variable.
+  @param[in,out] dest  Destination memory pointer.
+  @param[in]     value '\0'-terminated new value.
+
+  @return Completion status
+  @retval false Success
+  @retval true  Failure
+*/
+
+static bool plugin_var_memalloc_global_update(THD *thd,
+                                              struct st_mysql_sys_var *var,
+                                              char **dest, const char *value)
+{
+  char *old_value= *dest;
+  DBUG_ENTER("plugin_var_memalloc_global_update");
+
+  if (value && !(value= my_strdup(value, MYF(MY_WME))))
+    DBUG_RETURN(true);
+
+  var->update(thd, var, (void **) dest, (const void *) &value);
+
+  if (old_value)
+    my_free(old_value);
+
+  DBUG_RETURN(false);
+}
+
+
 bool sys_var_pluginvar::check_update_type(Item_result type)
 {
   switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
@@ -2911,6 +3017,7 @@ bool sys_var_pluginvar::do_check(THD *th
 
 bool sys_var_pluginvar::session_update(THD *thd, set_var *var)
 {
+  bool rc= false;
   DBUG_ASSERT(!is_readonly());
   DBUG_ASSERT(plugin_var->flags & PLUGIN_VAR_THDLOCAL);
   DBUG_ASSERT(thd == current_thd);
@@ -2920,13 +3027,20 @@ bool sys_var_pluginvar::session_update(T
   const void *src= var->value ? (void*)&var->save_result
                               : (void*)real_value_ptr(thd, OPT_GLOBAL);
   mysql_mutex_unlock(&LOCK_global_system_variables);
-  plugin_var->update(thd, plugin_var, tgt, src);
 
-  return false;
+  if ((plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR &&
+      plugin_var->flags & PLUGIN_VAR_MEMALLOC)
+    rc= plugin_var_memalloc_session_update(thd, plugin_var, (char **) tgt,
+                                           *(const char **) src);
+  else 
+    plugin_var->update(thd, plugin_var, tgt, src);
+
+  return rc;
 }
 
 bool sys_var_pluginvar::global_update(THD *thd, set_var *var)
 {
+  bool rc= false;
   DBUG_ASSERT(!is_readonly());
   mysql_mutex_assert_owner(&LOCK_global_system_variables);
 
@@ -2983,9 +3097,14 @@ bool sys_var_pluginvar::global_update(TH
     }
   }
 
-  plugin_var->update(thd, plugin_var, tgt, src);
+  if ((plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR &&
+      plugin_var->flags & PLUGIN_VAR_MEMALLOC)
+    rc= plugin_var_memalloc_global_update(thd, plugin_var, (char **) tgt,
+                                          *(const char **) src);
+  else 
+    plugin_var->update(thd, plugin_var, tgt, src);
 
-  return false;
+  return rc;
 }
 
 

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-trunk branch (sergey.vojtovich:3586 to 3588) Sergey Vojtovich11 Nov