List:Commits« Previous MessageNext Message »
From:ingo Date:May 9 2007 4:00pm
Subject:bk commit into 5.1 tree (istruewing:1.2511)
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of istruewing. When istruewing does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet@stripped, 2007-05-09 18:00:37+02:00, istruewing@stripped +3 -0
  WL#2936 - Falcon & MySQL plugin interface: server variables
  Cosmetic changes.
  Added comments.
  Renamed variables to be more meaningful. Have the same name
  for the same type of object wherever possible. Have distinct
  names for distinct types of objects wherever possible. Avoided
  names shorter than three characters in most cases.

  include/mysql/plugin.h@stripped, 2007-05-09 18:00:32+02:00, istruewing@stripped +21 -8
    WL#2936 - Falcon & MySQL plugin interface: server variables
    Cosmetic changes.
    Added comments.
    Separated data type values from flags to visualize their
    distinct purpose.

  plugin/fulltext/plugin_example.c@stripped, 2007-05-09 18:00:32+02:00, istruewing@stripped +13 -0
    WL#2936 - Falcon & MySQL plugin interface: server variables
    Added two example string options without default values.

  sql/sql_plugin.cc@stripped, 2007-05-09 18:00:32+02:00, istruewing@stripped +897 -612
    WL#2936 - Falcon & MySQL plugin interface: server variables
    Cosmetic changes.
    Added comments.
    Renamed variables to be more meaningful. Have the same name
    for the same type of object wherever possible. Have distinct
    names for distinct types of objects wherever possible. Avoided
    names shorter than three characters in most cases.
    Restructured register_var() for better understandability.
    Wrapped long lines.

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	istruewing
# Host:	chilla.local
# Root:	/home/mydev/mysql-5.1-wl2936-two

--- 1.35/include/mysql/plugin.h	2007-05-09 18:00:46 +02:00
+++ 1.36/include/mysql/plugin.h	2007-05-09 18:00:46 +02:00
@@ -101,15 +101,28 @@ typedef int (*mysql_show_var_func)(MYSQL
   declarations for server variables and command line options
 */
 
+/*
+  Numeric values for the data type of the variable.
+  These are set implicitly by the macros that declare server variables,
+  e.g. MYSQL_SYSVAR_UINT().
+*/
+#define PLUGIN_VAR_BOOL              1
+#define PLUGIN_VAR_INT               2
+#define PLUGIN_VAR_LONG              3
+#define PLUGIN_VAR_LONGLONG          4
+#define PLUGIN_VAR_STR               5
+#define PLUGIN_VAR_ENUM              6
+#define PLUGIN_VAR_SET               7
+/*
+  Bit values for properties/flags/options.
+  These are given as the 'opt' argument to the declaraction macros.
 
-#define PLUGIN_VAR_BOOL         0x0001
-#define PLUGIN_VAR_INT          0x0002
-#define PLUGIN_VAR_LONG         0x0003
-#define PLUGIN_VAR_LONGLONG     0x0004
-#define PLUGIN_VAR_STR          0x0005
-#define PLUGIN_VAR_ENUM         0x0006
-#define PLUGIN_VAR_SET          0x0007
-#define PLUGIN_VAR_UNSIGNED     0x0080
+  NOTE: If you want to have a writable string variable
+  (MYSQL_SYSVAR_STR()), you need to supply an update function for it
+  ('update' argument of MYSQL_SYSVAR_STR()), or add the
+  PLUGIN_VAR_MEMALLOC flag to the 'opt' argument.
+*/
+#define PLUGIN_VAR_UNSIGNED     0x0080 /* Value to be interpreted unsigned */
 #define PLUGIN_VAR_THDLOCAL     0x0100 /* Variable is per-connection */
 #define PLUGIN_VAR_READONLY     0x0200 /* Server variable is read only */
 #define PLUGIN_VAR_NOSYSVAR     0x0400 /* Not a server variable */

--- 1.63/sql/sql_plugin.cc	2007-05-09 18:00:46 +02:00
+++ 1.64/sql/sql_plugin.cc	2007-05-09 18:00:46 +02:00
@@ -45,8 +45,8 @@ const LEX_STRING plugin_type_names[MYSQL
   { C_STRING_WITH_LEN("INFORMATION SCHEMA") }
 };
 
-extern int initialize_schema_table(st_plugin_int *plugin);
-extern int finalize_schema_table(st_plugin_int *plugin);
+extern int initialize_schema_table(st_plugin_int *iplugin);
+extern int finalize_schema_table(st_plugin_int *iplugin);
 
 /*
   The number of elements in both plugin_type_initialize and
@@ -132,16 +132,16 @@ struct st_item_value_holder : public st_
   This structure is allocated from plugin_mem_root.
 
   The key format is as follows:
-    1 byte         - variable type code
+    1 byte         - variable type code ("byte 0")
     name_len bytes - variable name
     '\0'           - end of key
 */
 struct st_bookmark
 {
-  uint name_len;
-  int offset;
+  uint name_len;        /* number of chars of plugin_name '_' var_name */
+  int offset;           /* number of bytes from dynamic_variables_ptr */
   uint version;
-  char key[1];
+  char key[1];          /* see above */
 };
 
 
@@ -196,19 +196,19 @@ static bool register_builtin(struct st_m
                              struct st_plugin_int **);
 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 void plugin_vars_free_values(sys_var *sysvar_chain);
 static void plugin_opt_set_limits(struct my_option *options,
-                                  const struct st_mysql_sys_var *opt);
+                                  const struct st_mysql_sys_var *plugin_var);
 #define my_intern_plugin_lock(A,B) intern_plugin_lock(A,B CALLER_INFO)
 #define my_intern_plugin_lock_ci(A,B) intern_plugin_lock(A,B ORIG_CALLER_INFO)
-static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref plugin
+static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref piref
                                      CALLER_INFO_PROTO);
-static void intern_plugin_unlock(LEX *lex, plugin_ref plugin);
+static void intern_plugin_unlock(LEX *lex, plugin_ref piref);
 static void reap_plugins(void);
 
-
 /* declared in set_var.cc */
-extern sys_var *intern_find_sys_var(const char *str, uint length, bool no_error);
+extern sys_var *intern_find_sys_var(const char *str, uint length,
+                                    bool no_error);
 
 
 /****************************************************************************
@@ -271,19 +271,19 @@ static int item_val_real(struct st_mysql
 
 #ifdef HAVE_DLOPEN
 
-static struct st_plugin_dl *plugin_dl_find(const LEX_STRING *dl)
+static struct st_plugin_dl *plugin_dl_find(const LEX_STRING *dl_name)
 {
   uint i;
-  struct st_plugin_dl *tmp;
+  struct st_plugin_dl *pidl;
   DBUG_ENTER("plugin_dl_find");
   for (i= 0; i < plugin_dl_array.elements; i++)
   {
-    tmp= dynamic_element(&plugin_dl_array, i, struct st_plugin_dl *);
-    if (tmp->ref_count &&
+    pidl= dynamic_element(&plugin_dl_array, i, struct st_plugin_dl *);
+    if (pidl->ref_count &&
         ! my_strnncoll(files_charset_info,
-                       (const uchar *)dl->str, dl->length,
-                       (const uchar *)tmp->dl.str, tmp->dl.length))
-      DBUG_RETURN(tmp);
+                       (const uchar *)dl_name->str, dl_name->length,
+                       (const uchar *)pidl->dl.str, pidl->dl.length))
+      DBUG_RETURN(pidl);
   }
   DBUG_RETURN(0);
 }
@@ -292,15 +292,15 @@ static struct st_plugin_dl *plugin_dl_fi
 static st_plugin_dl *plugin_dl_insert_or_reuse(struct st_plugin_dl *plugin_dl)
 {
   uint i;
-  struct st_plugin_dl *tmp;
+  struct st_plugin_dl *pidl;
   DBUG_ENTER("plugin_dl_insert_or_reuse");
   for (i= 0; i < plugin_dl_array.elements; i++)
   {
-    tmp= dynamic_element(&plugin_dl_array, i, struct st_plugin_dl *);
-    if (! tmp->ref_count)
+    pidl= dynamic_element(&plugin_dl_array, i, struct st_plugin_dl *);
+    if (! pidl->ref_count)
     {
-      memcpy(tmp, plugin_dl, sizeof(struct st_plugin_dl));
-      DBUG_RETURN(tmp);
+      memcpy(pidl, plugin_dl, sizeof(struct st_plugin_dl));
+      DBUG_RETURN(pidl);
     }
   }
   if (insert_dynamic(&plugin_dl_array, (gptr)plugin_dl))
@@ -311,24 +311,24 @@ static st_plugin_dl *plugin_dl_insert_or
 #endif /* HAVE_DLOPEN */
 
 
-static inline void free_plugin_mem(struct st_plugin_dl *p)
+static inline void free_plugin_mem(struct st_plugin_dl *pidl)
 {
 #ifdef HAVE_DLOPEN
-  if (p->handle)
-    dlclose(p->handle);
+  if (pidl->handle)
+    dlclose(pidl->handle);
 #endif
-  my_free(p->dl.str, MYF(MY_ALLOW_ZERO_PTR));
-  if (p->version != MYSQL_PLUGIN_INTERFACE_VERSION)
-    my_free((gptr)p->plugins, MYF(MY_ALLOW_ZERO_PTR));
+  my_free(pidl->dl.str, MYF(MY_ALLOW_ZERO_PTR));
+  if (pidl->version != MYSQL_PLUGIN_INTERFACE_VERSION)
+    my_free((gptr)pidl->plugins, MYF(MY_ALLOW_ZERO_PTR));
 }
 
 
-static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report)
+static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl_name, int report)
 {
 #ifdef HAVE_DLOPEN
   char dlpath[FN_REFLEN];
   uint plugin_dir_len, dummy_errors, dlpathlen;
-  struct st_plugin_dl *tmp, plugin_dl;
+  struct st_plugin_dl *pidl, plugin_dl;
   void *sym;
   DBUG_ENTER("plugin_dl_add");
   plugin_dir_len= strlen(opt_plugin_dir);
@@ -337,10 +337,11 @@ static st_plugin_dl *plugin_dl_add(const
     This is done to ensure that only approved libraries from the
     plugin directory are used (to make this even remotely secure).
   */
-  if (my_strchr(files_charset_info, dl->str, dl->str + dl->length, FN_LIBCHAR) ||
-      check_string_char_length((LEX_STRING *) dl, "", NAME_CHAR_LEN,
+  if (my_strchr(files_charset_info, dl_name->str,
+                dl_name->str + dl_name->length, FN_LIBCHAR) ||
+      check_string_char_length((LEX_STRING *) dl_name, "", NAME_CHAR_LEN,
                                system_charset_info, 1) ||
-      plugin_dir_len + dl->length + 1 >= FN_REFLEN)
+      plugin_dir_len + dl_name->length + 1 >= FN_REFLEN)
   {
     if (report & REPORT_TO_USER)
       my_error(ER_UDF_NO_PATHS, MYF(0));
@@ -349,16 +350,15 @@ static st_plugin_dl *plugin_dl_add(const
     DBUG_RETURN(0);
   }
   /* If this dll is already loaded just increase ref_count. */
-  if ((tmp= plugin_dl_find(dl)))
+  if ((pidl= plugin_dl_find(dl_name)))
   {
-    tmp->ref_count++;
-    DBUG_RETURN(tmp);
+    pidl->ref_count++;
+    DBUG_RETURN(pidl);
   }
   bzero(&plugin_dl, sizeof(plugin_dl));
   /* Compile dll path */
-  dlpathlen=
-    strxnmov(dlpath, sizeof(dlpath) - 1, opt_plugin_dir, "/", dl->str, NullS) -
-    dlpath;
+  dlpathlen= strxnmov(dlpath, sizeof(dlpath) - 1,
+                      opt_plugin_dir, "/", dl_name->str, NullS) - dlpath;
   plugin_dl.ref_count= 1;
   /* Open new dll handle */
   if (!(plugin_dl.handle= dlopen(dlpath, RTLD_NOW)))
@@ -415,7 +415,7 @@ static st_plugin_dl *plugin_dl_add(const
   {
     int i;
     uint sizeof_st_plugin;
-    struct st_mysql_plugin *old, *cur;
+    struct st_mysql_plugin *old_mplugin, *cur_mplugin;
     char *ptr= (char *)sym;
 
     if ((sym= dlsym(plugin_dl.handle, sizeof_st_plugin_sym)))
@@ -444,9 +444,9 @@ static st_plugin_dl *plugin_dl_add(const
          i++)
       /* no op */;
 
-    cur= (struct st_mysql_plugin*)
+    cur_mplugin= (struct st_mysql_plugin*)
           my_malloc(i*sizeof(struct st_mysql_plugin), MYF(MY_ZEROFILL|MY_WME));
-    if (!cur)
+    if (!cur_mplugin)
     {
       free_plugin_mem(&plugin_dl);
       if (report & REPORT_TO_USER)
@@ -461,16 +461,17 @@ static st_plugin_dl *plugin_dl_add(const
       have less values than the struct definition.
     */
     for (i=0;
-         (old=(struct st_mysql_plugin *)(ptr+i*sizeof_st_plugin))->info;
+         (old_mplugin=(struct st_mysql_plugin *)(ptr+i*sizeof_st_plugin))->info;
          i++)
-      memcpy(cur+i, old, min(sizeof(cur[i]), sizeof_st_plugin));
+      memcpy(cur_mplugin + i, old_mplugin, min(sizeof(cur_mplugin[i]),
+                                               sizeof_st_plugin));
 
-    sym= cur;
+    sym= cur_mplugin;
   }
   plugin_dl.plugins= (struct st_mysql_plugin *)sym;
 
   /* Duplicate and convert dll name */
-  plugin_dl.dl.length= dl->length * files_charset_info->mbmaxlen + 1;
+  plugin_dl.dl.length= dl_name->length * files_charset_info->mbmaxlen + 1;
   if (! (plugin_dl.dl.str= my_malloc(plugin_dl.dl.length, MYF(0))))
   {
     free_plugin_mem(&plugin_dl);
@@ -481,11 +482,11 @@ static st_plugin_dl *plugin_dl_add(const
     DBUG_RETURN(0);
   }
   plugin_dl.dl.length= copy_and_convert(plugin_dl.dl.str, plugin_dl.dl.length,
-    files_charset_info, dl->str, dl->length, system_charset_info,
+    files_charset_info, dl_name->str, dl_name->length, system_charset_info,
     &dummy_errors);
   plugin_dl.dl.str[plugin_dl.dl.length]= 0;
   /* Add this dll to array */
-  if (! (tmp= plugin_dl_insert_or_reuse(&plugin_dl)))
+  if (! (pidl= plugin_dl_insert_or_reuse(&plugin_dl)))
   {
     free_plugin_mem(&plugin_dl);
     if (report & REPORT_TO_USER)
@@ -494,7 +495,7 @@ static st_plugin_dl *plugin_dl_add(const
       sql_print_error(ER(ER_OUTOFMEMORY), sizeof(struct st_plugin_dl));
     DBUG_RETURN(0);
   }
-  DBUG_RETURN(tmp);
+  DBUG_RETURN(pidl);
 #else
   DBUG_ENTER("plugin_dl_add");
   if (report & REPORT_TO_USER)
@@ -506,7 +507,7 @@ static st_plugin_dl *plugin_dl_add(const
 }
 
 
-static void plugin_dl_del(const LEX_STRING *dl)
+static void plugin_dl_del(const LEX_STRING *dl_name)
 {
 #ifdef HAVE_DLOPEN
   uint i;
@@ -516,18 +517,18 @@ static void plugin_dl_del(const LEX_STRI
 
   for (i= 0; i < plugin_dl_array.elements; i++)
   {
-    struct st_plugin_dl *tmp= dynamic_element(&plugin_dl_array, i,
+    struct st_plugin_dl *pidl= dynamic_element(&plugin_dl_array, i,
                                               struct st_plugin_dl *);
-    if (tmp->ref_count &&
+    if (pidl->ref_count &&
         ! my_strnncoll(files_charset_info,
-                       (const uchar *)dl->str, dl->length,
-                       (const uchar *)tmp->dl.str, tmp->dl.length))
+                       (const uchar *)dl_name->str, dl_name->length,
+                       (const uchar *)pidl->dl.str, pidl->dl.length))
     {
       /* Do not remove this element, unless no other plugin uses this dll. */
-      if (! --tmp->ref_count)
+      if (! --pidl->ref_count)
       {
-        free_plugin_mem(tmp);
-        bzero(tmp, sizeof(struct st_plugin_dl));
+        free_plugin_mem(pidl);
+        bzero(pidl, sizeof(struct st_plugin_dl));
       }
       break;
     }
@@ -537,10 +538,12 @@ static void plugin_dl_del(const LEX_STRI
 }
 
 
-static struct st_plugin_int *plugin_find_internal(const LEX_STRING *name, int type)
+static struct st_plugin_int *plugin_find_internal(const LEX_STRING *name,
+                                                  int type)
 {
   uint i;
   DBUG_ENTER("plugin_find_internal");
+
   if (! initialized)
     DBUG_RETURN(0);
 
@@ -550,15 +553,18 @@ static struct st_plugin_int *plugin_find
   {
     for (i= 0; i < MYSQL_MAX_PLUGIN_TYPE_NUM; i++)
     {
-      struct st_plugin_int *plugin= (st_plugin_int *)
+      struct st_plugin_int *iplugin= (struct st_plugin_int *)
         hash_search(&plugin_hash[i], (const byte *)name->str, name->length);
-      if (plugin)
-        DBUG_RETURN(plugin);
+      if (iplugin)
+        DBUG_RETURN(iplugin);
     }
   }
   else
-    DBUG_RETURN((st_plugin_int *)
+  {
+    DBUG_ASSERT((type >= 0) && (type < MYSQL_MAX_PLUGIN_TYPE_NUM));
+    DBUG_RETURN((struct st_plugin_int *)
         hash_search(&plugin_hash[type], (const byte *)name->str, name->length));
+  }
   DBUG_RETURN(0);
 }
 
@@ -566,13 +572,13 @@ static struct st_plugin_int *plugin_find
 static SHOW_COMP_OPTION plugin_status(const LEX_STRING *name, int type)
 {
   SHOW_COMP_OPTION rc= SHOW_OPTION_NO;
-  struct st_plugin_int *plugin;
-  DBUG_ENTER("plugin_is_ready");
+  struct st_plugin_int *iplugin;
+  DBUG_ENTER("plugin_status");
   pthread_mutex_lock(&LOCK_plugin);
-  if ((plugin= plugin_find_internal(name, type)))
+  if ((iplugin= plugin_find_internal(name, type)))
   {
     rc= SHOW_OPTION_DISABLED;
-    if (plugin->state == PLUGIN_IS_READY)
+    if (iplugin->state == PLUGIN_IS_READY)
       rc= SHOW_OPTION_YES;
   }
   pthread_mutex_unlock(&LOCK_plugin);
@@ -598,52 +604,53 @@ SHOW_COMP_OPTION sys_var_have_plugin::ge
 
 static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref rc CALLER_INFO_PROTO)
 {
-  st_plugin_int *pi= plugin_ref_to_int(rc);
+  struct st_plugin_int *iplugin= plugin_ref_to_int(rc);
   DBUG_ENTER("intern_plugin_lock");
 
   safe_mutex_assert_owner(&LOCK_plugin);
 
-  if (pi->state & (PLUGIN_IS_READY | PLUGIN_IS_UNINITIALIZED))
+  if (iplugin->state & (PLUGIN_IS_READY | PLUGIN_IS_UNINITIALIZED))
   {
-    plugin_ref plugin;
+    plugin_ref piref;
 #ifdef DBUG_OFF
     /* built-in plugins don't need ref counting */
-    if (!pi->plugin_dl)
-      DBUG_RETURN(pi);
+    if (!iplugin->plugin_dl)
+      DBUG_RETURN(iplugin);
 
-    plugin= pi;
+    piref= iplugin;
 #else
     /*
       For debugging, we do an additional malloc which allows the
       memory manager and/or valgrind to track locked references and
       double unlocks to aid resolving reference counting.problems.
     */
-    if (!(plugin= (plugin_ref) my_malloc_ci(sizeof(pi), MYF(MY_WME))))
+    if (!(piref= (plugin_ref) my_malloc_ci(sizeof(iplugin), MYF(MY_WME))))
       DBUG_RETURN(NULL);
 
-    *plugin= pi;
+    *piref= iplugin;
 #endif
-    pi->ref_count++;
+    iplugin->ref_count++;
     DBUG_PRINT("info",("thd: 0x%lx, plugin: \"%s\", ref_count: %d",
-                       (long) current_thd, pi->name.str, pi->ref_count));
+                       (long) current_thd, iplugin->name.str,
+                       iplugin->ref_count));
 
     if (lex)
-      insert_dynamic(&lex->plugins, (gptr)&plugin);
-    DBUG_RETURN(plugin);
+      insert_dynamic(&lex->plugins, (gptr) &piref);
+    DBUG_RETURN(piref);
   }
   DBUG_RETURN(NULL);
 }
 
 
-plugin_ref plugin_lock(THD *thd, plugin_ref *ptr CALLER_INFO_PROTO)
+plugin_ref plugin_lock(THD *thd, plugin_ref *piref_p CALLER_INFO_PROTO)
 {
   LEX *lex= thd ? thd->lex : 0;
-  plugin_ref rc;
+  plugin_ref piref;
   DBUG_ENTER("plugin_lock");
   pthread_mutex_lock(&LOCK_plugin);
-  rc= my_intern_plugin_lock_ci(lex, *ptr);
+  piref= my_intern_plugin_lock_ci(lex, *piref_p);
   pthread_mutex_unlock(&LOCK_plugin);
-  DBUG_RETURN(rc);
+  DBUG_RETURN(piref);
 }
 
 
@@ -651,32 +658,32 @@ plugin_ref plugin_lock_by_name(THD *thd,
                                CALLER_INFO_PROTO)
 {
   LEX *lex= thd ? thd->lex : 0;
-  plugin_ref rc= NULL;
-  st_plugin_int *plugin;
+  plugin_ref piref= NULL;
+  struct st_plugin_int *iplugin;
   DBUG_ENTER("plugin_lock_by_name");
   pthread_mutex_lock(&LOCK_plugin);
-  if ((plugin= plugin_find_internal(name, type)))
-    rc= my_intern_plugin_lock_ci(lex, plugin_int_to_ref(plugin));
+  if ((iplugin= plugin_find_internal(name, type)))
+    piref= my_intern_plugin_lock_ci(lex, plugin_int_to_ref(iplugin));
   pthread_mutex_unlock(&LOCK_plugin);
-  DBUG_RETURN(rc);
+  DBUG_RETURN(piref);
 }
 
 
-static st_plugin_int *plugin_insert_or_reuse(struct st_plugin_int *plugin)
+static st_plugin_int *plugin_insert_or_reuse(struct st_plugin_int *iplugin)
 {
   uint i;
   DBUG_ENTER("plugin_insert_or_reuse");
   for (i= 0; i < plugin_array.elements; i++)
   {
-    struct st_plugin_int *tmp= dynamic_element(&plugin_array, i,
-                                               struct st_plugin_int *);
-    if (tmp->state == PLUGIN_IS_FREED)
+    struct st_plugin_int *new_iplugin= dynamic_element(&plugin_array, i,
+                                                       struct st_plugin_int *);
+    if (new_iplugin->state == PLUGIN_IS_FREED)
     {
-      memcpy(tmp, plugin, sizeof(struct st_plugin_int));
-      DBUG_RETURN(tmp);
+      memcpy(new_iplugin, iplugin, sizeof(struct st_plugin_int));
+      DBUG_RETURN(new_iplugin);
     }
   }
-  if (insert_dynamic(&plugin_array, (gptr)plugin))
+  if (insert_dynamic(&plugin_array, (gptr) iplugin))
     DBUG_RETURN(0);
   DBUG_RETURN(dynamic_element(&plugin_array, plugin_array.elements - 1,
                               struct st_plugin_int *));
@@ -688,12 +695,13 @@ static st_plugin_int *plugin_insert_or_r
     Requires that a write-lock is held on LOCK_system_variables_hash
 */
 static bool plugin_add(MEM_ROOT *tmp_root,
-                       const LEX_STRING *name, const LEX_STRING *dl,
+                       const LEX_STRING *name, const LEX_STRING *dl_name,
                        int *argc, char **argv, int report)
 {
-  struct st_plugin_int tmp;
-  struct st_mysql_plugin *plugin;
+  struct st_plugin_int    iplugin;
+  struct st_mysql_plugin  *mplugin;
   DBUG_ENTER("plugin_add");
+
   if (plugin_find_internal(name, MYSQL_ANY_PLUGIN))
   {
     if (report & REPORT_TO_USER)
@@ -702,59 +710,69 @@ static bool plugin_add(MEM_ROOT *tmp_roo
       sql_print_error(ER(ER_UDF_EXISTS), name->str);
     DBUG_RETURN(TRUE);
   }
+
   /* Clear the whole struct to catch future extensions. */
-  bzero((char*) &tmp, sizeof(tmp));
-  if (! (tmp.plugin_dl= plugin_dl_add(dl, report)))
+  bzero((char*) &iplugin, sizeof(iplugin));
+
+  if (! (iplugin.plugin_dl= plugin_dl_add(dl_name, report)))
     DBUG_RETURN(TRUE);
+
   /* Find plugin by name */
-  for (plugin= tmp.plugin_dl->plugins; plugin->info; plugin++)
+  for (mplugin= iplugin.plugin_dl->plugins; mplugin->info; mplugin++)
   {
-    uint name_len= strlen(plugin->name);
-    if (plugin->type >= 0 && plugin->type < MYSQL_MAX_PLUGIN_TYPE_NUM &&
+    uint name_len= strlen(mplugin->name);
+    if (mplugin->type >= 0 && mplugin->type < MYSQL_MAX_PLUGIN_TYPE_NUM &&
         ! my_strnncoll(system_charset_info,
                        (const uchar *)name->str, name->length,
-                       (const uchar *)plugin->name,
+                       (const uchar *)mplugin->name,
                        name_len))
     {
-      struct st_plugin_int *tmp_plugin_ptr;
-      if (*(int*)plugin->info <
-          min_plugin_info_interface_version[plugin->type] ||
-          ((*(int*)plugin->info) >> 8) >
-          (cur_plugin_info_interface_version[plugin->type] >> 8))
+      if (*(int*)mplugin->info <
+          min_plugin_info_interface_version[mplugin->type] ||
+          ((*(int*)mplugin->info) >> 8) >
+          (cur_plugin_info_interface_version[mplugin->type] >> 8))
       {
         char buf[256];
         strxnmov(buf, sizeof(buf) - 1, "API version for ",
-                 plugin_type_names[plugin->type].str,
+                 plugin_type_names[mplugin->type].str,
                  " plugin is too different", NullS);
         if (report & REPORT_TO_USER)
-          my_error(ER_CANT_OPEN_LIBRARY, MYF(0), dl->str, 0, buf);
+          my_error(ER_CANT_OPEN_LIBRARY, MYF(0), dl_name->str, 0, buf);
         if (report & REPORT_TO_LOG)
-          sql_print_error(ER(ER_CANT_OPEN_LIBRARY), dl->str, 0, buf);
+          sql_print_error(ER(ER_CANT_OPEN_LIBRARY), dl_name->str, 0, buf);
         goto err;
       }
-      tmp.plugin= plugin;
-      tmp.name.str= (char *)plugin->name;
-      tmp.name.length= name_len;
-      tmp.ref_count= 0;
-      tmp.state= PLUGIN_IS_UNINITIALIZED;
-
-      if (!test_plugin_options(tmp_root, &tmp, argc, argv, true))
+      iplugin.plugin= mplugin;
+      iplugin.name.str= (char *)mplugin->name;
+      iplugin.name.length= name_len;
+      iplugin.ref_count= 0;
+      iplugin.state= PLUGIN_IS_UNINITIALIZED;
+      /*
+        Side effect: Variables of newly added plugins that can have
+        session values in addition to global values get space allocated
+        for storing their global values.
+      */
+      if (!test_plugin_options(tmp_root, &iplugin, argc, argv, true))
       {
-        if ((tmp_plugin_ptr= plugin_insert_or_reuse(&tmp)))
+        struct st_plugin_int *new_iplugin;
+
+        if ((new_iplugin= plugin_insert_or_reuse(&iplugin)))
         {
           plugin_array_version++;
-          if (!my_hash_insert(&plugin_hash[plugin->type], (byte*)tmp_plugin_ptr))
+          if (!my_hash_insert(&plugin_hash[mplugin->type],
+                              (byte*)new_iplugin))
           {
-            init_alloc_root(&tmp_plugin_ptr->mem_root, 4096, 4096);
+            /* NOTE: This is the normal exit if everything works well. */
+            init_alloc_root(&new_iplugin->mem_root, 4096, 4096);
             DBUG_RETURN(FALSE);
           }
-          tmp_plugin_ptr->state= PLUGIN_IS_FREED;
+          new_iplugin->state= PLUGIN_IS_FREED;
         }
-        mysql_del_sys_var_chain(tmp.system_vars);
+        mysql_del_sys_var_chain(iplugin.system_vars);
         goto err;
       }
       /* plugin was disabled */
-      plugin_dl_del(dl);
+      plugin_dl_del(dl_name);
       DBUG_RETURN(FALSE);
     }
   }
@@ -763,12 +781,12 @@ static bool plugin_add(MEM_ROOT *tmp_roo
   if (report & REPORT_TO_LOG)
     sql_print_error(ER(ER_CANT_FIND_DL_ENTRY), name->str);
 err:
-  plugin_dl_del(dl);
+  plugin_dl_del(dl_name);
   DBUG_RETURN(TRUE);
 }
 
 
-static void plugin_deinitialize(struct st_plugin_int *plugin, bool ref_check)
+static void plugin_deinitialize(struct st_plugin_int *iplugin, bool ref_check)
 {
   /*
     we don't want to hold the LOCK_plugin mutex as it may cause
@@ -777,7 +795,7 @@ static void plugin_deinitialize(struct s
   */
   safe_mutex_assert_not_owner(&LOCK_plugin);
 
-  if (plugin->plugin->status_vars)
+  if (iplugin->plugin->status_vars)
   {
 #ifdef FIX_LATER
     /*
@@ -788,59 +806,60 @@ static void plugin_deinitialize(struct s
       variable names.
     */
     SHOW_VAR array[2]= {
-      {plugin->plugin->name, (char*)plugin->plugin->status_vars, SHOW_ARRAY},
+      {iplugin->plugin->name, (char*)iplugin->plugin->status_vars, SHOW_ARRAY},
       {0, 0, SHOW_UNDEF}
     };
     remove_status_vars(array);
 #else
-    remove_status_vars(plugin->plugin->status_vars);
+    remove_status_vars(iplugin->plugin->status_vars);
 #endif /* FIX_LATER */
   }
 
-  if (plugin_type_deinitialize[plugin->plugin->type])
+  if (plugin_type_deinitialize[iplugin->plugin->type])
   {
-    if ((*plugin_type_deinitialize[plugin->plugin->type])(plugin))
+    if ((*plugin_type_deinitialize[iplugin->plugin->type])(iplugin))
     {
       sql_print_error("Plugin '%s' of type %s failed deinitialization",
-                      plugin->name.str, plugin_type_names[plugin->plugin->type].str);
+                      iplugin->name.str,
+                      plugin_type_names[iplugin->plugin->type].str);
     }
   }
-  else if (plugin->plugin->deinit)
+  else if (iplugin->plugin->deinit)
   {
-    DBUG_PRINT("info", ("Deinitializing plugin: '%s'", plugin->name.str));
-    if (plugin->plugin->deinit(plugin))
+    DBUG_PRINT("info", ("Deinitializing plugin: '%s'", iplugin->name.str));
+    if (iplugin->plugin->deinit(iplugin))
     {
       DBUG_PRINT("warning", ("Plugin '%s' deinit function returned error.",
-                             plugin->name.str));
+                             iplugin->name.str));
     }
   }
-  plugin->state= PLUGIN_IS_UNINITIALIZED;
+  iplugin->state= PLUGIN_IS_UNINITIALIZED;
 
   /*
     We do the check here because NDB has a worker THD which doesn't
     exit until NDB is shut down.
   */
-  if (ref_check && plugin->ref_count)
+  if (ref_check && iplugin->ref_count)
     sql_print_error("Plugin '%s' has ref_count=%d after deinitialization.",
-                    plugin->name.str, plugin->ref_count);
+                    iplugin->name.str, iplugin->ref_count);
 }
 
 
-static void plugin_del(struct st_plugin_int *plugin)
+static void plugin_del(struct st_plugin_int *iplugin)
 {
-  DBUG_ENTER("plugin_del(plugin)");
+  DBUG_ENTER("plugin_del");
   safe_mutex_assert_owner(&LOCK_plugin);
   /* Free allocated strings before deleting the plugin. */
-  plugin_vars_free_values(plugin->system_vars);
-  hash_delete(&plugin_hash[plugin->plugin->type], (byte*)plugin);
-  if (plugin->plugin_dl)
-    plugin_dl_del(&plugin->plugin_dl->dl);
-  plugin->state= PLUGIN_IS_FREED;
+  plugin_vars_free_values(iplugin->system_vars);
+  hash_delete(&plugin_hash[iplugin->plugin->type], (byte*)iplugin);
+  if (iplugin->plugin_dl)
+    plugin_dl_del(&iplugin->plugin_dl->dl);
+  iplugin->state= PLUGIN_IS_FREED;
   plugin_array_version++;
   rw_wrlock(&LOCK_system_variables_hash);
-  mysql_del_sys_var_chain(plugin->system_vars);
+  mysql_del_sys_var_chain(iplugin->system_vars);
   rw_unlock(&LOCK_system_variables_hash);
-  free_root(&plugin->mem_root, MYF(0));
+  free_root(&iplugin->mem_root, MYF(0));
   DBUG_VOID_RETURN;
 }
 
@@ -848,10 +867,10 @@ static void plugin_del(struct st_plugin_
 
 static void plugin_del(const LEX_STRING *name)
 {
-  struct st_plugin_int *plugin;
-  DBUG_ENTER("plugin_del(name)");
-  if ((plugin= plugin_find_internal(name, MYSQL_ANY_PLUGIN)))
-    plugin_del(plugin);
+  struct st_plugin_int *iplugin;
+  DBUG_ENTER("plugin_del");
+  if ((iplugin= plugin_find_internal(name, MYSQL_ANY_PLUGIN)))
+    plugin_del(iplugin);
   DBUG_VOID_RETURN;
 }
 
@@ -860,7 +879,7 @@ static void plugin_del(const LEX_STRING 
 static void reap_plugins(void)
 {
   uint count, idx;
-  struct st_plugin_int *plugin, **reap, **list;
+  struct st_plugin_int *iplugin, **reap, **iplugin_p;
 
   safe_mutex_assert_owner(&LOCK_plugin);
 
@@ -869,56 +888,56 @@ static void reap_plugins(void)
 
   reap_needed= false;
   count= plugin_array.elements;
-  reap= (struct st_plugin_int **)my_alloca(sizeof(plugin)*(count+1));
+  reap= (struct st_plugin_int **)my_alloca(sizeof(iplugin)*(count+1));
   *(reap++)= NULL;
 
   for (idx= 0; idx < count; idx++)
   {
-    plugin= dynamic_element(&plugin_array, idx, struct st_plugin_int *);
-    if (plugin->state == PLUGIN_IS_DELETED && !plugin->ref_count)
+    iplugin= dynamic_element(&plugin_array, idx, struct st_plugin_int *);
+    if (iplugin->state == PLUGIN_IS_DELETED && !iplugin->ref_count)
     {
       /* change the status flag to prevent reaping by another thread */
-      plugin->state= PLUGIN_IS_DYING;
-      *(reap++)= plugin;
+      iplugin->state= PLUGIN_IS_DYING;
+      *(reap++)= iplugin;
     }
   }
 
   pthread_mutex_unlock(&LOCK_plugin);
 
-  list= reap;
-  while ((plugin= *(--list)))
-    plugin_deinitialize(plugin, true);
+  iplugin_p= reap;
+  while ((iplugin= *(--iplugin_p)))
+    plugin_deinitialize(iplugin, true);
 
   pthread_mutex_lock(&LOCK_plugin);
 
-  while ((plugin= *(--reap)))
-    plugin_del(plugin);
+  while ((iplugin= *(--reap)))
+    plugin_del(iplugin);
 
   my_afree(reap);
 }
 
-static void intern_plugin_unlock(LEX *lex, plugin_ref plugin)
+static void intern_plugin_unlock(LEX *lex, plugin_ref piref)
 {
   int i;
-  st_plugin_int *pi;
+  struct st_plugin_int *iplugin;
   DBUG_ENTER("intern_plugin_unlock");
 
   safe_mutex_assert_owner(&LOCK_plugin);
 
-  if (!plugin)
+  if (!piref)
     DBUG_VOID_RETURN;
 
-  pi= plugin_ref_to_int(plugin);
+  iplugin= plugin_ref_to_int(piref);
 
 #ifdef DBUG_OFF
-  if (!pi->plugin_dl)
+  if (!iplugin->plugin_dl)
     DBUG_VOID_RETURN;
 #else
-  my_free((gptr) plugin, MYF(MY_WME));
+  my_free((gptr) piref, MYF(MY_WME));
 #endif
 
   DBUG_PRINT("info",("unlocking plugin, name= %s, ref_count= %d",
-                     pi->name.str, pi->ref_count));
+                     iplugin->name.str, iplugin->ref_count));
   if (lex)
   {
     /*
@@ -927,7 +946,7 @@ static void intern_plugin_unlock(LEX *le
       could be unlocked faster - optimizing for LIFO semantics.
     */
     for (i= lex->plugins.elements - 1; i >= 0; i--)
-      if (plugin == *dynamic_element(&lex->plugins, i, plugin_ref*))
+      if (piref == *dynamic_element(&lex->plugins, i, plugin_ref*))
       {
         delete_dynamic_element(&lex->plugins, i);
         break;
@@ -935,77 +954,79 @@ static void intern_plugin_unlock(LEX *le
     DBUG_ASSERT(i >= 0);
   }
 
-  DBUG_ASSERT(pi->ref_count);
-  pi->ref_count--;
+  DBUG_ASSERT(iplugin->ref_count);
+  iplugin->ref_count--;
 
-  if (pi->state == PLUGIN_IS_DELETED && !pi->ref_count)
+  if (iplugin->state == PLUGIN_IS_DELETED && !iplugin->ref_count)
     reap_needed= true;
 
   DBUG_VOID_RETURN;
 }
 
 
-void plugin_unlock(THD *thd, plugin_ref plugin)
+void plugin_unlock(THD *thd, plugin_ref piref)
 {
   LEX *lex= thd ? thd->lex : 0;
   DBUG_ENTER("plugin_unlock");
-  if (!plugin)
+  if (!piref)
     DBUG_VOID_RETURN;
 #ifdef DBUG_OFF
   /* built-in plugins don't need ref counting */
-  if (!plugin_dlib(plugin))
+  if (!plugin_dlib(piref))
     DBUG_VOID_RETURN;
 #endif
   pthread_mutex_lock(&LOCK_plugin);
-  intern_plugin_unlock(lex, plugin);
+  intern_plugin_unlock(lex, piref);
   reap_plugins();
   pthread_mutex_unlock(&LOCK_plugin);
   DBUG_VOID_RETURN;
 }
 
 
-void plugin_unlock_list(THD *thd, plugin_ref *list, uint count)
+void plugin_unlock_list(THD *thd, plugin_ref *piref_p, uint count)
 {
   LEX *lex= thd ? thd->lex : 0;
   DBUG_ENTER("plugin_unlock_list");
-  DBUG_ASSERT(list);
+  DBUG_ASSERT(piref_p);
   pthread_mutex_lock(&LOCK_plugin);
   while (count--)
-    intern_plugin_unlock(lex, *list++);
+    intern_plugin_unlock(lex, *piref_p++);
   reap_plugins();
   pthread_mutex_unlock(&LOCK_plugin);
   DBUG_VOID_RETURN;
 }
 
 
-static int plugin_initialize(struct st_plugin_int *plugin)
+static int plugin_initialize(struct st_plugin_int *iplugin)
 {
   DBUG_ENTER("plugin_initialize");
+  DBUG_PRINT("plugin", ("plugin: '%s'", iplugin->plugin->name));
 
   safe_mutex_assert_owner(&LOCK_plugin);
 
-  if (plugin_type_initialize[plugin->plugin->type])
+  if (plugin_type_initialize[iplugin->plugin->type])
   {
-    if ((*plugin_type_initialize[plugin->plugin->type])(plugin))
+    if ((*plugin_type_initialize[iplugin->plugin->type])(iplugin))
     {
       sql_print_error("Plugin '%s' registration as a %s failed.",
-                      plugin->name.str, plugin_type_names[plugin->plugin->type].str);
+                      iplugin->name.str,
+                      plugin_type_names[iplugin->plugin->type].str);
       goto err;
     }
   }
-  else if (plugin->plugin->init)
+  else if (iplugin->plugin->init)
   {
-    if (plugin->plugin->init(plugin))
+    if (iplugin->plugin->init(iplugin))
     {
       sql_print_error("Plugin '%s' init function returned error.",
-                      plugin->name.str);
+                      iplugin->name.str);
       goto err;
     }
   }
 
-  plugin->state= PLUGIN_IS_READY;
+  iplugin->state= PLUGIN_IS_READY;
 
-  if (plugin->plugin->status_vars)
+  if (iplugin->plugin->status_vars)
   {
 #ifdef FIX_LATER
     /*
@@ -1016,13 +1037,13 @@ static int plugin_initialize(struct st_p
       variable names.
     */
     SHOW_VAR array[2]= {
-      {plugin->plugin->name, (char*)plugin->plugin->status_vars, SHOW_ARRAY},
+      {iplugin->plugin->name, (char*)iplugin->plugin->status_vars, SHOW_ARRAY},
       {0, 0, SHOW_UNDEF}
     };
     if (add_status_vars(array)) // add_status_vars makes a copy
       goto err;
 #else
-    add_status_vars(plugin->plugin->status_vars); // add_status_vars makes a copy
+    add_status_vars(iplugin->plugin->status_vars); // this makes a copy
 #endif /* FIX_LATER */
   }
 
@@ -1030,15 +1051,15 @@ static int plugin_initialize(struct st_p
     set the plugin attribute of plugin's sys vars so they are pointing
     to the active plugin
   */
-  if (plugin->system_vars)
+  if (iplugin->system_vars)
   {
-    sys_var_pluginvar *var= plugin->system_vars->cast_pluginvar();
+    sys_var_pluginvar *svpiv= iplugin->system_vars->cast_pluginvar();
     for (;;)
     {
-      var->plugin= plugin;
-      if (!var->next)
+      svpiv->plugin= iplugin;
+      if (!svpiv->next)
         break;
-      var= var->next->cast_pluginvar();
+      svpiv= svpiv->next->cast_pluginvar();
     }
   }
 
@@ -1051,18 +1072,18 @@ err:
 static byte *get_hash_key(const byte *buff, uint *length,
                    my_bool not_used __attribute__((unused)))
 {
-  struct st_plugin_int *plugin= (st_plugin_int *)buff;
-  *length= (uint)plugin->name.length;
-  return((byte *)plugin->name.str);
+  struct st_plugin_int *iplugin= (struct st_plugin_int *)buff;
+  *length= (uint)iplugin->name.length;
+  return((byte *)iplugin->name.str);
 }
 
 
 static byte *get_bookmark_hash_key(const byte *buff, uint *length,
                    my_bool not_used __attribute__((unused)))
 {
-  struct st_bookmark *var= (st_bookmark *)buff;
-  *length= var->name_len + 1;
-  return (byte*) var->key;
+  struct st_bookmark *bmk= (struct st_bookmark *)buff;
+  *length= bmk->name_len + 1;
+  return (byte*) bmk->key;
 }
 
 
@@ -1078,8 +1099,8 @@ int plugin_init(int *argc, char **argv, 
   uint i;
   bool def_enabled, is_myisam;
   struct st_mysql_plugin **builtins;
-  struct st_mysql_plugin *plugin;
-  struct st_plugin_int tmp, *plugin_ptr, **reap;
+  struct st_mysql_plugin *mplugin;
+  struct st_plugin_int iplugin, *iplugin_p, **reap;
   MEM_ROOT tmp_root;
   DBUG_ENTER("plugin_init");
 
@@ -1118,30 +1139,35 @@ int plugin_init(int *argc, char **argv, 
   */
   for (builtins= mysqld_builtins; *builtins; builtins++)
   {
-    for (plugin= *builtins; plugin->info; plugin++)
+    for (mplugin= *builtins; mplugin->info; mplugin++)
     {
       /* by default, only ndbcluster is disabled */
       def_enabled=
-        my_strcasecmp(&my_charset_latin1, plugin->name, "NDBCLUSTER") != 0;
-      bzero(&tmp, sizeof(tmp));
-      tmp.plugin= plugin;
-      tmp.name.str= (char *)plugin->name;
-      tmp.name.length= strlen(plugin->name);
+        my_strcasecmp(&my_charset_latin1, mplugin->name, "NDBCLUSTER") != 0;
+      bzero(&iplugin, sizeof(iplugin));
+      iplugin.plugin= mplugin;
+      iplugin.name.str= (char *)mplugin->name;
+      iplugin.name.length= strlen(mplugin->name);
 
       free_root(&tmp_root, MYF(MY_MARK_BLOCKS_FREE));
-      if (test_plugin_options(&tmp_root, &tmp, argc, argv, def_enabled))
+      /*
+        Side effect: Variables of newly added plugins that can have
+        session values in addition to global values get space allocated
+        for storing their global values.
+      */
+      if (test_plugin_options(&tmp_root, &iplugin, argc, argv, def_enabled))
         continue;
 
-      if (register_builtin(plugin, &tmp, &plugin_ptr))
+      if (register_builtin(mplugin, &iplugin, &iplugin_p))
         goto err_unlock;
 
       /* only initialize MyISAM and CSV at this stage */
       if (!(is_myisam=
-            !my_strcasecmp(&my_charset_latin1, plugin->name, "MyISAM")) &&
-          my_strcasecmp(&my_charset_latin1, plugin->name, "CSV"))
+            !my_strcasecmp(&my_charset_latin1, mplugin->name, "MyISAM")) &&
+          my_strcasecmp(&my_charset_latin1, mplugin->name, "CSV"))
         continue;
 
-      if (plugin_initialize(plugin_ptr))
+      if (plugin_initialize(iplugin_p))
         goto err_unlock;
 
       /*
@@ -1152,8 +1178,8 @@ int plugin_init(int *argc, char **argv, 
       {
         DBUG_ASSERT(!global_system_variables.table_plugin);
         global_system_variables.table_plugin=
-          my_intern_plugin_lock(NULL, plugin_int_to_ref(plugin_ptr));
-        DBUG_ASSERT(plugin_ptr->ref_count == 1);
+          my_intern_plugin_lock(NULL, plugin_int_to_ref(iplugin_p));
+        DBUG_ASSERT(iplugin_p->ref_count == 1);
       }
     }
   }
@@ -1166,6 +1192,11 @@ int plugin_init(int *argc, char **argv, 
   /* Register all dynamic plugins */
   if (!(flags & PLUGIN_INIT_SKIP_DYNAMIC_LOADING))
   {
+    /*
+      Side effect: Variables of newly added plugins that can have
+      session values in addition to global values get space allocated
+      for storing their global values.
+    */
     if (opt_plugin_load &&
         plugin_load_list(&tmp_root, argc, argv, opt_plugin_load))
       goto err;
@@ -1180,18 +1211,19 @@ int plugin_init(int *argc, char **argv, 
     Now we initialize all remaining plugins
   */
   pthread_mutex_lock(&LOCK_plugin);
-  reap= (st_plugin_int **) my_alloca((plugin_array.elements+1) * sizeof(void*));
+  reap= (struct st_plugin_int **) my_alloca((plugin_array.elements+1) *
+                                            sizeof(void*));
   *(reap++)= NULL;
 
   for (i= 0; i < plugin_array.elements; i++)
   {
-    plugin_ptr= dynamic_element(&plugin_array, i, struct st_plugin_int *);
-    if (plugin_ptr->state == PLUGIN_IS_UNINITIALIZED)
+    iplugin_p= dynamic_element(&plugin_array, i, struct st_plugin_int *);
+    if (iplugin_p->state == PLUGIN_IS_UNINITIALIZED)
     {
-      if (plugin_initialize(plugin_ptr))
+      if (plugin_initialize(iplugin_p))
       {
-        plugin_ptr->state= PLUGIN_IS_DYING;
-        *(reap++)= plugin_ptr;
+        iplugin_p->state= PLUGIN_IS_DYING;
+        *(reap++)= iplugin_p;
       }
     }
   }
@@ -1199,12 +1231,12 @@ int plugin_init(int *argc, char **argv, 
   /*
     Check if any plugins have to be reaped
   */
-  while ((plugin_ptr= *(--reap)))
+  while ((iplugin_p= *(--reap)))
   {
     pthread_mutex_unlock(&LOCK_plugin);
-    plugin_deinitialize(plugin_ptr, true);
+    plugin_deinitialize(iplugin_p, true);
     pthread_mutex_lock(&LOCK_plugin);
-    plugin_del(plugin_ptr);
+    plugin_del(iplugin_p);
   }
 
   pthread_mutex_unlock(&LOCK_plugin);
@@ -1222,23 +1254,23 @@ err:
 }
 
 
-static bool register_builtin(struct st_mysql_plugin *plugin,
-                             struct st_plugin_int *tmp,
-                             struct st_plugin_int **ptr)
+static bool register_builtin(struct st_mysql_plugin *mplugin,
+                             struct st_plugin_int *iplugin,
+                             struct st_plugin_int **iplugin_p)
 {
   DBUG_ENTER("register_builtin");
 
-  tmp->state= PLUGIN_IS_UNINITIALIZED;
-  tmp->ref_count= 0;
-  tmp->plugin_dl= 0;
+  iplugin->state= PLUGIN_IS_UNINITIALIZED;
+  iplugin->ref_count= 0;
+  iplugin->plugin_dl= 0;
 
-  if (insert_dynamic(&plugin_array, (gptr)tmp))
+  if (insert_dynamic(&plugin_array, (gptr)iplugin))
     DBUG_RETURN(1);
 
-  *ptr= dynamic_element(&plugin_array, plugin_array.elements - 1,
+  *iplugin_p= dynamic_element(&plugin_array, plugin_array.elements - 1,
                         struct st_plugin_int *);
 
-  if (my_hash_insert(&plugin_hash[plugin->type],(byte*) *ptr))
+  if (my_hash_insert(&plugin_hash[mplugin->type],(byte*) *iplugin_p))
     DBUG_RETURN(1);
 
   DBUG_RETURN(0);
@@ -1258,26 +1290,31 @@ static bool register_builtin(struct st_m
   RETURN
     false - plugin registered successfully
 */
-bool plugin_register_builtin(THD *thd, struct st_mysql_plugin *plugin)
+bool plugin_register_builtin(THD *thd, struct st_mysql_plugin *mplugin)
 {
-  struct st_plugin_int tmp, *ptr;
+  struct st_plugin_int iplugin, *iplugin_p;
   bool result= true;
   int dummy_argc= 0;
   DBUG_ENTER("plugin_register_builtin");
 
-  bzero(&tmp, sizeof(tmp));
-  tmp.plugin= plugin;
-  tmp.name.str= (char *)plugin->name;
-  tmp.name.length= strlen(plugin->name);
+  bzero(&iplugin, sizeof(iplugin));
+  iplugin.plugin= mplugin;
+  iplugin.name.str= (char *)mplugin->name;
+  iplugin.name.length= strlen(mplugin->name);
 
   pthread_mutex_lock(&LOCK_plugin);
   rw_wrlock(&LOCK_system_variables_hash);
 
-  if (test_plugin_options(thd->mem_root, &tmp, &dummy_argc, NULL, true))
+  /*
+    Side effect: Variables of newly added plugins that can have session
+    values in addition to global values get space allocated for storing
+    their global values.
+  */
+  if (test_plugin_options(thd->mem_root, &iplugin, &dummy_argc, NULL, true))
     goto end;
 
-  if ((result= register_builtin(plugin, &tmp, &ptr)))
-    mysql_del_sys_var_chain(tmp.system_vars);
+  if ((result= register_builtin(mplugin, &iplugin, &iplugin_p)))
+    mysql_del_sys_var_chain(iplugin.system_vars);
 
 end:
   rw_unlock(&LOCK_system_variables_hash);
@@ -1339,9 +1376,14 @@ static void plugin_load(MEM_ROOT *tmp_ro
     get_field(tmp_root, table->field[1], &str_dl);
 
     LEX_STRING name= {(char *)str_name.ptr(), str_name.length()};
-    LEX_STRING dl= {(char *)str_dl.ptr(), str_dl.length()};
+    LEX_STRING dl_name= {(char *)str_dl.ptr(), str_dl.length()};
 
-    if (plugin_add(tmp_root, &name, &dl, argc, argv, REPORT_TO_LOG))
+    /*
+      Side effect: Variables of newly added plugins that can have
+      session values in addition to global values get space allocated
+      for storing their global values.
+    */
+    if (plugin_add(tmp_root, &name, &dl_name, argc, argv, REPORT_TO_LOG))
       sql_print_warning("Couldn't load plugin named '%s' with soname '%s'.",
                         str_name.c_ptr(), str_dl.c_ptr());
     free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE));
@@ -1367,9 +1409,9 @@ static bool plugin_load_list(MEM_ROOT *t
                              const char *list)
 {
   char buffer[FN_REFLEN];
-  LEX_STRING name= {buffer, 0}, dl= {NULL, 0}, *str= &name;
+  LEX_STRING name= {buffer, 0}, dl_name= {NULL, 0}, *str= &name;
   struct st_plugin_dl *plugin_dl;
-  struct st_mysql_plugin *plugin;
+  struct st_mysql_plugin *mplugin;
   char *p= buffer;
   DBUG_ENTER("plugin_load_list");
   while (list)
@@ -1385,38 +1427,49 @@ static bool plugin_load_list(MEM_ROOT *t
 #endif
     case ';':
       name.str[name.length]= '\0';
-      if (str != &dl)  // load all plugins in named module
+      if (str != &dl_name)  // load all plugins in named module
       {
-        dl= name;
-        if ((plugin_dl= plugin_dl_add(&dl, REPORT_TO_LOG)))
+        dl_name= name;
+        if ((plugin_dl= plugin_dl_add(&dl_name, REPORT_TO_LOG)))
         {
-          for (plugin= plugin_dl->plugins; plugin->info; plugin++)
+          for (mplugin= plugin_dl->plugins; mplugin->info; mplugin++)
           {
-            name.str= (char *) plugin->name;
+            name.str= (char *) mplugin->name;
             name.length= strlen(name.str);
 
             free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE));
-            if (plugin_add(tmp_root, &name, &dl, argc, argv, REPORT_TO_LOG))
+            /*
+              Side effect: Variables of newly added plugins that can
+              have session values in addition to global values get space
+              allocated for storing their global values.
+            */
+            if (plugin_add(tmp_root, &name, &dl_name,
+                           argc, argv, REPORT_TO_LOG))
               goto error;
           }
-          plugin_dl_del(&dl); // reduce ref count
+          plugin_dl_del(&dl_name); // reduce ref count
         }
       }
       else
       {
         free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE));
-        if (plugin_add(tmp_root, &name, &dl, argc, argv, REPORT_TO_LOG))
+        /*
+          Side effect: Variables of newly added plugins that can have
+          session values in addition to global values get space
+          allocated for storing their global values.
+        */
+        if (plugin_add(tmp_root, &name, &dl_name, argc, argv, REPORT_TO_LOG))
           goto error;
       }
-      name.length= dl.length= 0;
-      dl.str= NULL; name.str= p= buffer;
+      name.length= dl_name.length= 0;
+      dl_name.str= NULL; name.str= p= buffer;
       str= &name;
       continue;
     case '=':
     case '#':
       if (str == &name)
       {
-        str= &dl;
+        str= &dl_name;
         str->str= p;
         continue;
       }
@@ -1428,7 +1481,7 @@ static bool plugin_load_list(MEM_ROOT *t
   DBUG_RETURN(FALSE);
 error:
   sql_print_error("Couldn't load plugin named '%s' with soname '%s'.",
-                  name.str, dl.str);
+                  name.str, dl_name.str);
   DBUG_RETURN(TRUE);
 }
 
@@ -1436,8 +1489,8 @@ error:
 void plugin_shutdown(void)
 {
   uint i, count= plugin_array.elements, free_slots= 0;
-  struct st_plugin_int **plugins, *plugin;
-  struct st_plugin_dl **dl;
+  struct st_plugin_int **iplugin_p, *iplugin;
+  struct st_plugin_dl **pidl_p;
   DBUG_ENTER("plugin_shutdown");
 
   if (initialized)
@@ -1458,10 +1511,10 @@ void plugin_shutdown(void)
       reap_plugins();
       for (i= free_slots= 0; i < count; i++)
       {
-        plugin= dynamic_element(&plugin_array, i, struct st_plugin_int *);
-        switch (plugin->state) {
+        iplugin= dynamic_element(&plugin_array, i, struct st_plugin_int *);
+        switch (iplugin->state) {
         case PLUGIN_IS_READY:
-          plugin->state= PLUGIN_IS_DELETED;
+          iplugin->state= PLUGIN_IS_DELETED;
           reap_needed= true;
           break;
         case PLUGIN_IS_FREED:
@@ -1483,17 +1536,17 @@ void plugin_shutdown(void)
     if (count > free_slots)
       sql_print_warning("Forcing shutdown of %d plugins", count - free_slots);
 
-    plugins= (struct st_plugin_int **) my_alloca(sizeof(void*) * (count+1));
+    iplugin_p= (struct st_plugin_int **) my_alloca(sizeof(void*) * (count+1));
 
     /*
       If we have any plugins which did not die cleanly, we force shutdown
     */
     for (i= 0; i < count; i++)
     {
-      plugins[i]= dynamic_element(&plugin_array, i, struct st_plugin_int *);
+      iplugin_p[i]= dynamic_element(&plugin_array, i, struct st_plugin_int *);
       /* change the state to ensure no reaping races */
-      if (plugins[i]->state == PLUGIN_IS_DELETED)
-        plugins[i]->state= PLUGIN_IS_DYING;
+      if (iplugin_p[i]->state == PLUGIN_IS_DELETED)
+        iplugin_p[i]->state= PLUGIN_IS_DYING;
     }
     pthread_mutex_unlock(&LOCK_plugin);
 
@@ -1501,15 +1554,15 @@ void plugin_shutdown(void)
       We loop through all plugins and call deinit() if they have one.
     */
     for (i= 0; i < count; i++)
-      if (!(plugins[i]->state & (PLUGIN_IS_UNINITIALIZED | PLUGIN_IS_FREED)))
+      if (!(iplugin_p[i]->state & (PLUGIN_IS_UNINITIALIZED | PLUGIN_IS_FREED)))
       {
         sql_print_information("Plugin '%s' will be forced to shutdown",
-                              plugins[i]->name.str);
+                              iplugin_p[i]->name.str);
         /*
           We are forcing deinit on plugins so we don't want to do a ref_count
           check until we have processed all the plugins.
         */
-        plugin_deinitialize(plugins[i], false);
+        plugin_deinitialize(iplugin_p[i], false);
       }
 
     /*
@@ -1525,11 +1578,11 @@ void plugin_shutdown(void)
     */
     for (i= 0; i < count; i++)
     {
-      if (plugins[i]->ref_count)
+      if (iplugin_p[i]->ref_count)
         sql_print_error("Plugin '%s' has ref_count=%d after shutdown.",
-                        plugins[i]->name.str, plugins[i]->ref_count);
-      if (plugins[i]->state & PLUGIN_IS_UNINITIALIZED)
-        plugin_del(plugins[i]);
+                        iplugin_p[i]->name.str, iplugin_p[i]->ref_count);
+      if (iplugin_p[i]->state & PLUGIN_IS_UNINITIALIZED)
+        plugin_del(iplugin_p[i]);
     }
 
     /*
@@ -1543,7 +1596,7 @@ void plugin_shutdown(void)
     initialized= 0;
     pthread_mutex_destroy(&LOCK_plugin);
 
-    my_afree(plugins);
+    my_afree(iplugin_p);
   }
 
   /* Dispose of the memory */
@@ -1553,12 +1606,12 @@ void plugin_shutdown(void)
   delete_dynamic(&plugin_array);
 
   count= plugin_dl_array.elements;
-  dl= (struct st_plugin_dl **)my_alloca(sizeof(void*) * count);
+  pidl_p= (struct st_plugin_dl **)my_alloca(sizeof(void*) * count);
   for (i= 0; i < count; i++)
-    dl[i]= dynamic_element(&plugin_dl_array, i, struct st_plugin_dl *);
+    pidl_p[i]= dynamic_element(&plugin_dl_array, i, struct st_plugin_dl *);
   for (i= 0; i < plugin_dl_array.elements; i++)
-    free_plugin_mem(dl[i]);
-  my_afree(dl);
+    free_plugin_mem(pidl_p[i]);
+  my_afree(pidl_p);
   delete_dynamic(&plugin_dl_array);
 
   hash_free(&bookmark_hash);
@@ -1570,13 +1623,14 @@ void plugin_shutdown(void)
 }
 
 
-bool mysql_install_plugin(THD *thd, const LEX_STRING *name, const LEX_STRING *dl)
+bool mysql_install_plugin(THD *thd, const LEX_STRING *name,
+                          const LEX_STRING *dl_name)
 {
   TABLE_LIST tables;
   TABLE *table;
   int error, argc;
   char *argv[2];
-  struct st_plugin_int *tmp;
+  struct st_plugin_int *iplugin;
   DBUG_ENTER("mysql_install_plugin");
 
   bzero(&tables, sizeof(tables));
@@ -1595,13 +1649,18 @@ bool mysql_install_plugin(THD *thd, cons
   argv[0]= const_cast<char*>(""); // without a cast gcc emits a warning
   argv[1]= 0;
   argc= 1;
-  error= plugin_add(thd->mem_root, name, dl, &argc, argv, REPORT_TO_USER);
+  /*
+    Side effect: Variables of newly added plugins that can have
+    session values in addition to global values get space allocated
+    for storing their global values.
+  */
+  error= plugin_add(thd->mem_root, name, dl_name, &argc, argv, REPORT_TO_USER);
   rw_unlock(&LOCK_system_variables_hash);
 
-  if (error || !(tmp= plugin_find_internal(name, MYSQL_ANY_PLUGIN)))
+  if (error || !(iplugin= plugin_find_internal(name, MYSQL_ANY_PLUGIN)))
     goto err;
 
-  if (plugin_initialize(tmp))
+  if (plugin_initialize(iplugin))
   {
     my_error(ER_CANT_INITIALIZE_UDF, MYF(0), name->str,
              "Plugin initialization function failed.");
@@ -1611,7 +1670,7 @@ bool mysql_install_plugin(THD *thd, cons
   table->use_all_columns();
   restore_record(table, s->default_values);
   table->field[0]->store(name->str, name->length, system_charset_info);
-  table->field[1]->store(dl->str, dl->length, files_charset_info);
+  table->field[1]->store(dl_name->str, dl_name->length, files_charset_info);
   error= table->file->ha_write_row(table->record[0]);
   if (error)
   {
@@ -1622,7 +1681,7 @@ bool mysql_install_plugin(THD *thd, cons
   pthread_mutex_unlock(&LOCK_plugin);
   DBUG_RETURN(FALSE);
 deinit:
-  tmp->state= PLUGIN_IS_DELETED;
+  iplugin->state= PLUGIN_IS_DELETED;
   reap_needed= true;
   reap_plugins();
 err:
@@ -1635,7 +1694,7 @@ bool mysql_uninstall_plugin(THD *thd, co
 {
   TABLE *table;
   TABLE_LIST tables;
-  struct st_plugin_int *plugin;
+  struct st_plugin_int *iplugin;
   DBUG_ENTER("mysql_uninstall_plugin");
 
   bzero(&tables, sizeof(tables));
@@ -1647,12 +1706,12 @@ bool mysql_uninstall_plugin(THD *thd, co
     DBUG_RETURN(TRUE);
 
   pthread_mutex_lock(&LOCK_plugin);
-  if (!(plugin= plugin_find_internal(name, MYSQL_ANY_PLUGIN)))
+  if (!(iplugin= plugin_find_internal(name, MYSQL_ANY_PLUGIN)))
   {
     my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "PLUGIN", name->str);
     goto err;
   }
-  if (!plugin->plugin_dl)
+  if (!iplugin->plugin_dl)
   {
     push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
                  "Built-in plugins cannot be deleted,.");
@@ -1660,8 +1719,8 @@ bool mysql_uninstall_plugin(THD *thd, co
     goto err;
   }
 
-  plugin->state= PLUGIN_IS_DELETED;
-  if (plugin->ref_count)
+  iplugin->state= PLUGIN_IS_DELETED;
+  if (iplugin->ref_count)
     push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
                  "Plugin is busy and will be uninstalled on shutdown");
   else
@@ -1693,7 +1752,7 @@ bool plugin_foreach_with_mask(THD *thd, 
                        int type, uint state_mask, void *arg)
 {
   uint idx, total;
-  struct st_plugin_int *plugin, **plugins;
+  struct st_plugin_int *iplugin, **iplugins;
   int version=plugin_array_version;
   DBUG_ENTER("plugin_foreach_with_mask");
 
@@ -1709,13 +1768,13 @@ bool plugin_foreach_with_mask(THD *thd, 
     Do the alloca out here in case we do have a working alloca:
         leaving the nested stack frame invalidates alloca allocation.
   */
-  plugins=(struct st_plugin_int **)my_alloca(total*sizeof(plugin));
+  iplugins=(struct st_plugin_int **)my_alloca(total*sizeof(iplugin));
   if (type == MYSQL_ANY_PLUGIN)
   {
     for (idx= 0; idx < total; idx++)
     {
-      plugin= dynamic_element(&plugin_array, idx, struct st_plugin_int *);
-      plugins[idx]= !(plugin->state & state_mask) ? plugin : NULL;
+      iplugin= dynamic_element(&plugin_array, idx, struct st_plugin_int *);
+      iplugins[idx]= !(iplugin->state & state_mask) ? iplugin : NULL;
     }
   }
   else
@@ -1723,8 +1782,8 @@ bool plugin_foreach_with_mask(THD *thd, 
     HASH *hash= plugin_hash + type;
     for (idx= 0; idx < total; idx++)
     {
-      plugin= (struct st_plugin_int *) hash_element(hash, idx);
-      plugins[idx]= !(plugin->state & state_mask) ? plugin : NULL;
+      iplugin= (struct st_plugin_int *) hash_element(hash, idx);
+      iplugins[idx]= !(iplugin->state & state_mask) ? iplugin : NULL;
     }
   }
   pthread_mutex_unlock(&LOCK_plugin);
@@ -1735,19 +1794,19 @@ bool plugin_foreach_with_mask(THD *thd, 
     {
       pthread_mutex_lock(&LOCK_plugin);
       for (uint i=idx; i < total; i++)
-        if (plugins[i] && plugins[i]->state & state_mask)
-          plugins[i]=0;
+        if (iplugins[i] && iplugins[i]->state & state_mask)
+          iplugins[i]=0;
       pthread_mutex_unlock(&LOCK_plugin);
     }
-    plugin= plugins[idx];
-    if (plugin && func(thd, plugin_int_to_ref(plugin), arg))
+    iplugin= iplugins[idx];
+    if (iplugin && func(thd, plugin_int_to_ref(iplugin), arg))
         goto err;
   }
 
-  my_afree(plugins);
+  my_afree(iplugins);
   DBUG_RETURN(FALSE);
 err:
-  my_afree(plugins);
+  my_afree(iplugins);
   DBUG_RETURN(TRUE);
 }
 
@@ -1786,16 +1845,27 @@ typedef DECLARE_MYSQL_THDVAR_SIMPLE(thdv
 typedef DECLARE_MYSQL_THDVAR_SIMPLE(thdvar_ulong_t, ulong);
 typedef DECLARE_MYSQL_THDVAR_SIMPLE(thdvar_ulonglong_t, ulonglong);
 
-#define SET_PLUGIN_VAR_RESOLVE(opt)\
-  *(mysql_sys_var_ptr_p*)&((opt)->resolve)= mysql_sys_var_ptr
 typedef byte *(*mysql_sys_var_ptr_p)(void* a_thd, int offset);
 
+/*
+  'tpivar' is a st_mysql_sys_var casted to (thdvar_..._t*) as defined above.
+  'resolve' is a pointer to a function that returns a pointer
+  of the type of the variable (as in '...' of thdvar_..._t).
+  The address of the pointer is casted to (mysql_sys_var_ptr_p*) as
+  typedefd above. It is now a pointer to a function that returns a
+  a pointer of byte.
+  The casted pointer is assigned the address of the static function
+  mysql_sys_var_ptr().
+*/
+#define SET_PLUGIN_VAR_RESOLVE(tpivar)\
+  *(mysql_sys_var_ptr_p*)&((tpivar)->resolve)= mysql_sys_var_ptr
+
 
 /****************************************************************************
   default variable data check and update functions
 ****************************************************************************/
 
-static int check_func_bool(THD *thd, struct st_mysql_sys_var *var,
+static int check_func_bool(THD *thd, struct st_mysql_sys_var *plugin_var,
                            void *save, st_mysql_value *value)
 {
   char buff[STRING_BUFFER_USUAL_SIZE];
@@ -1829,50 +1899,50 @@ static int check_func_bool(THD *thd, str
   *(int*)save= -result;
   return 0;
 err:
-  my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue);
+  my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), plugin_var->name, strvalue);
   return 1;
 }
 
 
-static int check_func_int(THD *thd, struct st_mysql_sys_var *var,
+static int check_func_int(THD *thd, struct st_mysql_sys_var *plugin_var,
                           void *save, st_mysql_value *value)
 {
   long long tmp;
   struct my_option options;
   value->val_int(value, &tmp);
-  plugin_opt_set_limits(&options, var);
+  plugin_opt_set_limits(&options, plugin_var);
   *(int *)save= (int) getopt_ull_limit_value(tmp, &options);
   return (thd->variables.sql_mode & MODE_STRICT_ALL_TABLES) &&
          (*(int *)save != (int) tmp);
 }
 
 
-static int check_func_long(THD *thd, struct st_mysql_sys_var *var,
+static int check_func_long(THD *thd, struct st_mysql_sys_var *plugin_var,
                           void *save, st_mysql_value *value)
 {
   long long tmp;
   struct my_option options;
   value->val_int(value, &tmp);
-  plugin_opt_set_limits(&options, var);
+  plugin_opt_set_limits(&options, plugin_var);
   *(long *)save= (long) getopt_ull_limit_value(tmp, &options);
   return (thd->variables.sql_mode & MODE_STRICT_ALL_TABLES) &&
          (*(long *)save != (long) tmp);
 }
 
 
-static int check_func_longlong(THD *thd, struct st_mysql_sys_var *var,
+static int check_func_longlong(THD *thd, struct st_mysql_sys_var *plugin_var,
                           void *save, st_mysql_value *value)
 {
   long long tmp;
   struct my_option options;
   value->val_int(value, &tmp);
-  plugin_opt_set_limits(&options, var);
+  plugin_opt_set_limits(&options, plugin_var);
   *(ulonglong *)save= getopt_ull_limit_value(tmp, &options);
   return (thd->variables.sql_mode & MODE_STRICT_ALL_TABLES) &&
          (*(long long *)save != tmp);
 }
 
-static int check_func_str(THD *thd, struct st_mysql_sys_var *var,
+static int check_func_str(THD *thd, struct st_mysql_sys_var *plugin_var,
                           void *save, st_mysql_value *value)
 {
   char buff[STRING_BUFFER_USUAL_SIZE];
@@ -1887,7 +1957,7 @@ static int check_func_str(THD *thd, stru
 }
 
 
-static int check_func_enum(THD *thd, struct st_mysql_sys_var *var,
+static int check_func_enum(THD *thd, struct st_mysql_sys_var *plugin_var,
                            void *save, st_mysql_value *value)
 {
   char buff[STRING_BUFFER_USUAL_SIZE];
@@ -1897,10 +1967,10 @@ static int check_func_enum(THD *thd, str
   long result;
   int length;
 
-  if (var->flags & PLUGIN_VAR_THDLOCAL)
-    typelib= ((thdvar_enum_t*) var)->typelib;
+  if (plugin_var->flags & PLUGIN_VAR_THDLOCAL)
+    typelib= ((thdvar_enum_t*) plugin_var)->typelib;
   else
-    typelib= ((sysvar_enum_t*) var)->typelib;
+    typelib= ((sysvar_enum_t*) plugin_var)->typelib;
 
   if (value->value_type(value) == MYSQL_VALUE_TYPE_STRING)
   {
@@ -1928,12 +1998,12 @@ static int check_func_enum(THD *thd, str
   *(long*)save= result;
   return 0;
 err:
-  my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue);
+  my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), plugin_var->name, strvalue);
   return 1;
 }
 
 
-static int check_func_set(THD *thd, struct st_mysql_sys_var *var,
+static int check_func_set(THD *thd, struct st_mysql_sys_var *plugin_var,
                           void *save, st_mysql_value *value)
 {
   char buff[STRING_BUFFER_USUAL_SIZE], *error= 0;
@@ -1944,10 +2014,10 @@ static int check_func_set(THD *thd, stru
   bool not_used;
   int length;
 
-  if (var->flags & PLUGIN_VAR_THDLOCAL)
-    typelib= ((thdvar_set_t*) var)->typelib;
+  if (plugin_var->flags & PLUGIN_VAR_THDLOCAL)
+    typelib= ((thdvar_set_t*) plugin_var)->typelib;
   else
-    typelib= ((sysvar_set_t*)var)->typelib;
+    typelib= ((sysvar_set_t*)plugin_var)->typelib;
 
   if (value->value_type(value) == MYSQL_VALUE_TYPE_STRING)
   {
@@ -1978,45 +2048,45 @@ static int check_func_set(THD *thd, stru
   *(ulonglong*)save= result;
   return 0;
 err:
-  my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue);
+  my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), plugin_var->name, strvalue);
   return 1;
 }
 
 
-static void update_func_bool(THD *thd, struct st_mysql_sys_var *var,
+static void update_func_bool(THD *thd, struct st_mysql_sys_var *plugin_var,
                              void *tgt, void *save)
 {
   *(my_bool *) tgt= *(int *) save ? 1 : 0;
 }
 
 
-static void update_func_int(THD *thd, struct st_mysql_sys_var *var,
+static void update_func_int(THD *thd, struct st_mysql_sys_var *plugin_var,
                              void *tgt, void *save)
 {
   *(int *)tgt= *(int *) save;
 }
 
 
-static void update_func_long(THD *thd, struct st_mysql_sys_var *var,
+static void update_func_long(THD *thd, struct st_mysql_sys_var *plugin_var,
                              void *tgt, void *save)
 {
   *(long *)tgt= *(long *) save;
 }
 
 
-static void update_func_longlong(THD *thd, struct st_mysql_sys_var *var,
+static void update_func_longlong(THD *thd, struct st_mysql_sys_var *plugin_var,
                              void *tgt, void *save)
 {
   *(longlong *)tgt= *(ulonglong *) save;
 }
 
 
-static void update_func_str(THD *thd, struct st_mysql_sys_var *var,
+static void update_func_str(THD *thd, struct st_mysql_sys_var *plugin_var,
                              void *tgt, void *save)
 {
   char *old= *(char **) tgt;
   *(char **)tgt= *(char **) save;
-  if (var->flags & PLUGIN_VAR_MEMALLOC)
+  if (plugin_var->flags & PLUGIN_VAR_MEMALLOC)
   {
     *(char **)tgt= my_strdup(*(char **) save, MYF(0));
     my_free(old, MYF(0));
@@ -2031,26 +2101,26 @@ static void update_func_str(THD *thd, st
 
 sys_var *find_sys_var(THD *thd, const char *str, uint length)
 {
-  sys_var *var;
-  sys_var_pluginvar *pi= NULL;
-  plugin_ref plugin;
+  sys_var *sysvar;
+  sys_var_pluginvar *svpiv= NULL;
+  plugin_ref piref;
   DBUG_ENTER("find_sys_var");
 
   pthread_mutex_lock(&LOCK_plugin);
   rw_rdlock(&LOCK_system_variables_hash);
-  if ((var= intern_find_sys_var(str, length, false)) &&
-      (pi= var->cast_pluginvar()))
+  if ((sysvar= intern_find_sys_var(str, length, false)) &&
+      (svpiv= sysvar->cast_pluginvar()))
   {
     rw_unlock(&LOCK_system_variables_hash);
     LEX *lex= thd ? thd->lex : 0;
-    if (!(plugin= my_intern_plugin_lock(lex, plugin_int_to_ref(pi->plugin))))
-      var= NULL; /* failed to lock it, it must be uninstalling */
+    if (!(piref= my_intern_plugin_lock(lex, plugin_int_to_ref(svpiv->plugin))))
+      sysvar= NULL; /* failed to lock it, it must be uninstalling */
     else
-    if (!(plugin_state(plugin) & PLUGIN_IS_READY))
+    if (!(plugin_state(piref) & PLUGIN_IS_READY))
     {
       /* initialization not completed */
-      var= NULL;
-      intern_plugin_unlock(lex, plugin);
+      sysvar= NULL;
+      intern_plugin_unlock(lex, piref);
     }
   }
   else
@@ -2061,9 +2131,9 @@ sys_var *find_sys_var(THD *thd, const ch
     If the variable exists but the plugin it is associated with is not ready
     then the intern_plugin_lock did not raise an error, so we do it here.
   */
-  if (pi && !var)
+  if (svpiv && !sysvar)
     my_error(ER_UNKNOWN_SYSTEM_VARIABLE, MYF(0), (char*) str);
-  DBUG_RETURN(var);
+  DBUG_RETURN(sysvar);
 }
 
 
@@ -2072,10 +2142,10 @@ sys_var *find_sys_var(THD *thd, const ch
   Returns the 'bookmark' for the named variable.
   LOCK_system_variables_hash should be at least read locked
 */
-static st_bookmark *find_bookmark(const char *plugin, const char *name,
-                                  int flags)
+static struct st_bookmark *find_bookmark(const char *plugin, const char *name,
+                                         int flags)
 {
-  st_bookmark *result= NULL;
+  struct st_bookmark *bmk= NULL;
   uint namelen, length, pluginlen= 0;
   char *varname, *p;
 
@@ -2100,73 +2170,112 @@ static st_bookmark *find_bookmark(const 
 
   varname[0]= flags & PLUGIN_VAR_TYPEMASK;
 
-  result= (st_bookmark*) hash_search(&bookmark_hash,
-                                     (const byte*) varname, length - 1);
+  bmk= (struct st_bookmark*) hash_search(&bookmark_hash,
+                                         (const byte*) varname, length - 1);
 
   my_afree(varname);
-  return result;
+  return bmk;
 }
 
 
-/*
-  returns a bookmark for thd-local variables, creating if neccessary.
-  returns null for non thd-local variables.
-  Requires that a write lock is obtained on LOCK_system_variables_hash
+/**
+  @brief Get a bookmark for thd-local variables, create if neccessary.
+
+  @details Requires that a write lock is obtained on
+  LOCK_system_variables_hash.
+
+  Bookmarks are stored in bookmark_hash. They contain an offset into
+  dynamic_variables_ptr. It stores the global values for variables
+  that can have thd-local values.
+
+  @param[in]    plugin_name     Name of plugin
+  @param[in]    var_name        Name of variable
+  @param[in]    flags           Variable type + flags
+
+  @returns Bookmark or NULL
+    @retval Bookmark for non thd-local variables
+    @retval Bookmark NULL
 */
-static st_bookmark *register_var(const char *plugin, const char *name,
-                                 int flags)
+
+static struct st_bookmark *register_var(const char *plugin_name,
+                                        const char *var_name, int flags)
 {
-  uint length= strlen(plugin) + strlen(name) + 3, size= 0, offset, new_size;
-  st_bookmark *result;
-  char *varname, *p;
+  uint length, offset, new_size;
+  uint size= 0;
+  struct st_bookmark *bmk;
+  char *key, *p;
+  DBUG_ENTER("register_var");
 
   if (!(flags & PLUGIN_VAR_THDLOCAL))
-    return NULL;
-
-  switch (flags & PLUGIN_VAR_TYPEMASK) {
-  case PLUGIN_VAR_BOOL:
-    size= sizeof(my_bool);
-    break;
-  case PLUGIN_VAR_INT:
-    size= sizeof(int);
-    break;
-  case PLUGIN_VAR_LONG:
-    size= sizeof(long);
-    break;
-  case PLUGIN_VAR_LONGLONG:
-    size= sizeof(ulonglong);
-    break;
-  case PLUGIN_VAR_STR:
-    size= sizeof(char*);
-    break;
-  default:
-    DBUG_ASSERT(0);
-    return NULL;
-  };
+    DBUG_RETURN(NULL);
 
-  varname= ((char*) my_alloca(length));
-  strxmov(varname + 1, plugin, "_", name, NullS);
-  for (p= varname + 1; *p; p++)
+  /*
+    The bookmark key is coded as follows:
+    Byte 0, plugin name, '_', variable name, '\0'.
+    Byte 0 contains the integer value of the variable type.
+    All dashes in plugin name and variable name are converted to underscores.
+  */
+  length= strlen(plugin_name) + strlen(var_name) + 3;
+  key= ((char*) my_alloca(length));
+  key[0]= flags & PLUGIN_VAR_TYPEMASK;
+  strxmov(key + 1, plugin_name, "_", var_name, NullS);
+  for (p= key + 1; *p; p++)
     if (*p == '-')
       *p= '_';
+  DBUG_PRINT("plugin", ("key: '%s'", key + 1));
 
-  if (!(result= find_bookmark(NULL, varname + 1, flags)))
+  if (!(bmk= find_bookmark(NULL, key + 1, flags)))
   {
-    result= (st_bookmark*) alloc_root(&plugin_mem_root,
-                                      sizeof(struct st_bookmark) + length-1);
-    varname[0]= flags & PLUGIN_VAR_TYPEMASK;
-    memcpy(result->key, varname, length);
-    result->name_len= length - 2;
-    result->offset= -1;
+    /*
+      st_bookmark has char key[1] as its last element. We allocate the
+      structure with the additional bytes for the key name minus the
+      one that is included in the structure declaraction.
+    */
+    bmk= (struct st_bookmark*) alloc_root(&plugin_mem_root,
+                                          sizeof(struct st_bookmark) +
+                                          length - 1);
+    /* Copy key into bookmark structure. */
+    memcpy(bmk->key, key, length);
+    /* name_len excludes byte 0 and '\0' terminator. */
+    bmk->name_len= length - 2;
+    bmk->offset= -1;
+    bmk->version= 0;
 
+    /* Get size of variable value. */
+    switch (flags & PLUGIN_VAR_TYPEMASK) {
+    case PLUGIN_VAR_BOOL:
+      size= sizeof(my_bool);
+      break;
+    case PLUGIN_VAR_INT:
+      size= sizeof(int);
+      break;
+    case PLUGIN_VAR_LONG:
+      size= sizeof(long);
+      break;
+    case PLUGIN_VAR_LONGLONG:
+      size= sizeof(ulonglong);
+      break;
+    case PLUGIN_VAR_STR:
+      size= sizeof(char*);
+      break;
+    default:
+      DBUG_ASSERT(0);
+      DBUG_RETURN(NULL);
+    };
     DBUG_ASSERT(size && !(size & (size-1))); /* must be power of 2 */
 
+    /* offset is the number of bytes from dynamic_variables_ptr. */
     offset= global_system_variables.dynamic_variables_size;
+    /* Align to a multiple of variable value size. */
     offset= (offset + size - 1) & ~(size - 1);
-    result->offset= (int) offset;
+    bmk->offset= (int) offset;
 
+    /*
+      Enlarge the dynamic variables value storage if necessary.
+      Allocate in hunks of 64 bytes to reduce the frequency of
+      re-allocations.
+    */
     new_size= (offset + size + 63) & ~63;
-
     if (new_size > global_variables_dynamic_size)
     {
       global_system_variables.dynamic_variables_ptr=
@@ -2196,17 +2305,17 @@ static st_bookmark *register_var(const c
     global_system_variables.dynamic_variables_version++;
     max_system_variables.dynamic_variables_version++;
 
-    result->version= global_system_variables.dynamic_variables_version;
+    bmk->version= global_system_variables.dynamic_variables_version;
 
     /* this should succeed because we have already checked if a dup exists */
-    if (my_hash_insert(&bookmark_hash, (byte*) result))
+    if (my_hash_insert(&bookmark_hash, (byte*) bmk))
     {
-      fprintf(stderr, "failed to add placeholder to hash");
+      fprintf(stderr, "failed to add bookmark to hash");
       DBUG_ASSERT(0);
     }
   }
-  my_afree(varname);
-  return result;
+  my_afree(key);
+  DBUG_RETURN(bmk);
 }
 
 
@@ -2234,6 +2343,10 @@ static byte *intern_sys_var_ptr(THD* thd
 
     rw_rdlock(&LOCK_system_variables_hash);
 
+    /*
+      Thread is behind current dynamic global variables allocation.
+      Thread value space must be as big as global value space.
+    */
     thd->variables.dynamic_variables_ptr=
       my_realloc(thd->variables.dynamic_variables_ptr,
                  global_variables_dynamic_size,
@@ -2241,9 +2354,12 @@ static byte *intern_sys_var_ptr(THD* thd
 
     if (global_lock)
       pthread_mutex_lock(&LOCK_global_system_variables);
-
     safe_mutex_assert_owner(&LOCK_global_system_variables);
 
+    /*
+      Copy the new value space from global to thread. Copy only what
+      global has more than thread.
+    */
     memcpy(thd->variables.dynamic_variables_ptr +
              thd->variables.dynamic_variables_size,
            global_system_variables.dynamic_variables_ptr +
@@ -2257,32 +2373,54 @@ static byte *intern_sys_var_ptr(THD* thd
     */
     for (idx= 0; idx < bookmark_hash.records; idx++)
     {
-      sys_var_pluginvar *pi;
-      sys_var *var;
-      st_bookmark *v= (st_bookmark*) hash_element(&bookmark_hash,idx);
-
-      if (v->version <= thd->variables.dynamic_variables_version ||
-          !(var= intern_find_sys_var(v->key + 1, v->name_len, true)) ||
-          !(pi= var->cast_pluginvar()) ||
-          v->key[0] != (pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK))
+      sys_var_pluginvar *svpiv;
+      sys_var *sysvar;
+      struct st_bookmark *bmk=
+        (struct st_bookmark*) hash_element(&bookmark_hash, idx);
+
+      /*
+        Bookmark version is assigned from global version when the
+        variable is created. Thread version is assigned when new
+        variables values are copied from global. If the bookmark version
+        is greater than the old thread version, then this variable has
+        not yet been seen by this thread.
+
+        Ignore all bookmarks that have been handled before, have no
+        variable, have a variable of non-plugin type, or non-matching
+        value type.
+      */
+      if (bmk->version <= thd->variables.dynamic_variables_version ||
+          !(sysvar= intern_find_sys_var(bmk->key + 1, bmk->name_len, true)) ||
+          !(svpiv= sysvar->cast_pluginvar()) ||
+          bmk->key[0] != (svpiv->plugin_var->flags & PLUGIN_VAR_TYPEMASK))
         continue;
 
-      /* Here we do anything special that may be required of the data types */
+      /*
+        Here we do anything special that may be required of the data
+        types when a variable is seen by this thread for the first time.
+      */
 
-      if ((pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR &&
-          pi->plugin_var->flags & PLUGIN_VAR_MEMALLOC)
+      if ((svpiv->plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR &&
+          svpiv->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));
+        /*
+          Copy the string from global_system_variables to
+          thd->variables. This assumes that a string has been assigned
+          to global_system_variables already. This is done by
+          handle_options().
+        */
+        char **pp= (char**) (thd->variables.dynamic_variables_ptr +
+                             *(int*)(svpiv->plugin_var + 1));
+        if ((*pp= *(char**) (global_system_variables.dynamic_variables_ptr +
+                             *(int*)(svpiv->plugin_var + 1))))
+          *pp= my_strdup(*pp, MYF(MY_WME|MY_FAE));
       }
     }
 
     if (global_lock)
       pthread_mutex_unlock(&LOCK_global_system_variables);
 
+    /* Now the thread is up to date. */
     thd->variables.dynamic_variables_version=
            global_system_variables.dynamic_variables_version;
     thd->variables.dynamic_variables_head=
@@ -2303,7 +2441,7 @@ static byte *mysql_sys_var_ptr(void* a_t
 
 void plugin_thdvar_init(THD *thd)
 {
-  plugin_ref old_table_plugin= thd->variables.table_plugin;
+  plugin_ref old_table_piref= thd->variables.table_plugin;
   DBUG_ENTER("plugin_thdvar_init");
   
   thd->variables.table_plugin= NULL;
@@ -2320,7 +2458,7 @@ void plugin_thdvar_init(THD *thd)
   pthread_mutex_lock(&LOCK_plugin);  
   thd->variables.table_plugin=
         my_intern_plugin_lock(NULL, global_system_variables.table_plugin);
-  intern_plugin_unlock(NULL, old_table_plugin);
+  intern_plugin_unlock(NULL, old_table_piref);
   pthread_mutex_unlock(&LOCK_plugin);
   DBUG_VOID_RETURN;
 }
@@ -2342,49 +2480,72 @@ static void unlock_variables(THD *thd, s
   Unlike plugin_vars_free_values() it frees all variables of all plugins,
   it's used on shutdown.
 */
-static void cleanup_variables(THD *thd, struct system_variables *vars)
+static void cleanup_variables(THD *thd, struct system_variables *system_vars)
 {
-  st_bookmark *v;
-  sys_var_pluginvar *pivar;
-  sys_var *var;
+  struct st_bookmark *bmk;
+  sys_var_pluginvar *svpiv;
+  sys_var *sysvar;
   int flags;
   uint idx;
+  DBUG_ENTER("cleanup_variables");
 
   rw_rdlock(&LOCK_system_variables_hash);
   for (idx= 0; idx < bookmark_hash.records; idx++)
   {
-    v= (st_bookmark*) hash_element(&bookmark_hash, idx);
-    if (v->version > vars->dynamic_variables_version ||
-        !(var= intern_find_sys_var(v->key + 1, v->name_len, true)) ||
-        !(pivar= var->cast_pluginvar()) ||
-        v->key[0] != (pivar->plugin_var->flags & PLUGIN_VAR_TYPEMASK))
+    bmk= (struct st_bookmark*) hash_element(&bookmark_hash, idx);
+    /*
+      Bookmark version is assigned from global version when the variable
+      is created. Thread version is assigned when new variables values
+      are copied from global. If the bookmark version is greater than
+      the thread version, then this variable has not yet been seen
+      by this thread. So we do not need to do any cleanup work for it if
+      we are dealing with thd->variables here.
+
+      For global dynamic variables the bookmark version can never be
+      greater than the global version. So we ignore global variables
+      here. This is ok since these variables are deleted when its
+      plugin is deleted.
+
+      Also ignore not correctly initialized variables, those that are of
+      non-plugin type, or have a non-matching value type.
+    */
+    if (bmk->version > system_vars->dynamic_variables_version ||
+        !(sysvar= intern_find_sys_var(bmk->key + 1, bmk->name_len, true)) ||
+        !(svpiv= sysvar->cast_pluginvar()) ||
+        bmk->key[0] != (svpiv->plugin_var->flags & PLUGIN_VAR_TYPEMASK))
       continue;
 
-    flags= pivar->plugin_var->flags;
+    flags= svpiv->plugin_var->flags;
+
+    /*
+      Here we do anything special that may be required of the data
+      types when a variable has been setup by this thread before.
+    */
 
     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);
+      char **ptr= (char**) svpiv->real_value_ptr(thd, OPT_SESSION);
       my_free(*ptr, MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR));
       *ptr= NULL;
     }
   }
   rw_unlock(&LOCK_system_variables_hash);
 
-  DBUG_ASSERT(vars->table_plugin == NULL);
+  DBUG_ASSERT(system_vars->table_plugin == NULL);
 
-  my_free(vars->dynamic_variables_ptr, MYF(MY_ALLOW_ZERO_PTR));
-  vars->dynamic_variables_ptr= NULL;
-  vars->dynamic_variables_size= 0;
-  vars->dynamic_variables_version= 0;
+  my_free(system_vars->dynamic_variables_ptr, MYF(MY_ALLOW_ZERO_PTR));
+  system_vars->dynamic_variables_ptr= NULL;
+  system_vars->dynamic_variables_size= 0;
+  system_vars->dynamic_variables_version= 0;
+  DBUG_VOID_RETURN;
 }
 
 
 void plugin_thdvar_cleanup(THD *thd)
 {
   uint idx;
-  plugin_ref *list;
+  plugin_ref *piref_p;
   DBUG_ENTER("plugin_thdvar_cleanup");
 
   pthread_mutex_lock(&LOCK_plugin);
@@ -2394,10 +2555,10 @@ void plugin_thdvar_cleanup(THD *thd)
 
   if ((idx= thd->lex->plugins.elements))
   {
-    list= ((plugin_ref*) thd->lex->plugins.buffer) + idx - 1;
+    piref_p= ((plugin_ref*) thd->lex->plugins.buffer) + idx - 1;
     DBUG_PRINT("info",("unlocking %d plugins", idx));
-    while ((char*) list >= thd->lex->plugins.buffer)
-      intern_plugin_unlock(NULL, *list--);
+    while ((char*) piref_p >= thd->lex->plugins.buffer)
+      intern_plugin_unlock(NULL, *piref_p--);
   }
 
   reap_plugins();
@@ -2417,24 +2578,24 @@ void plugin_thdvar_cleanup(THD *thd)
   that only string values with PLUGIN_VAR_MEMALLOC are allocated and
   must be freed.
 
-  @param[in]        vars        Chain of system variables of a plugin
+  @param[in]        sysvar_chain    Chain of system variables of a plugin
 */
 
-static void plugin_vars_free_values(sys_var *vars)
+static void plugin_vars_free_values(sys_var *sysvar_chain)
 {
   DBUG_ENTER("plugin_vars_free_values");
 
-  for (sys_var *var= vars; var; var= var->next)
+  for (sys_var *sysvar= sysvar_chain; sysvar; sysvar= sysvar->next)
   {
-    sys_var_pluginvar *piv= var->cast_pluginvar();
-    if (piv &&
-        ((piv->plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR) &&
-        (piv->plugin_var->flags & PLUGIN_VAR_MEMALLOC))
+    sys_var_pluginvar *svpiv= sysvar->cast_pluginvar();
+    if (svpiv &&
+        ((svpiv->plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR) &&
+        (svpiv->plugin_var->flags & PLUGIN_VAR_MEMALLOC))
     {
       /* Free the string from global_system_variables. */
-      char **valptr= (char**) piv->real_value_ptr(NULL, OPT_GLOBAL);
+      char **valptr= (char**) svpiv->real_value_ptr(NULL, OPT_GLOBAL);
       DBUG_PRINT("plugin", ("freeing value for: '%s'  addr: 0x%lx",
-                            var->name, (long) valptr));
+                            sysvar->name, (long) valptr));
       my_free(*valptr, MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR));
       *valptr= NULL;
     }
@@ -2483,6 +2644,20 @@ SHOW_TYPE sys_var_pluginvar::show_type()
 }
 
 
+/**
+  @brief Return the address of the internal value of the variable.
+
+  @detail "Internal" and "external" values of a variable differ for
+  enums and sets only. For these the internal value is a numeric
+  representation. sys_var_pluginvar::value_ptr() returns the address
+  of the "external" value for every variable type.
+
+  @param[in]        thd         thread handle
+  @param[in]        type        wanted value type: OPT_GLOBAL or OPT_SESSION
+
+  @return Value address
+*/
+
 byte* sys_var_pluginvar::real_value_ptr(THD *thd, enum_var_type type)
 {
   DBUG_ASSERT(thd || (type == OPT_GLOBAL));
@@ -2491,8 +2666,28 @@ byte* sys_var_pluginvar::real_value_ptr(
     if (type == OPT_GLOBAL)
       thd= NULL;
 
+    /*
+      For SESSION+GLOBAL plugin variables the global value is stored in
+      allocated space referenced by
+      global_system_variables.dynamic_variables_ptr. The offset of the
+      variables value is located immediately behind the variable
+      description header of sizeof(st_mysql_sys_var). The trick below
+      avoids to deal with a struct per variable type. Example:
+
+      struct { MYSQL_PLUGIN_VAR_HEADER; int offset; ...} var name;
+
+      So the call below is: intern_sys_var_ptr(thd, offset, false).
+    */
     return intern_sys_var_ptr(thd, *(int*) (plugin_var+1), false);
   }
+  /*
+    For GLOBAL-only plugin variables the value pointer is located
+    immediately behind the variable description header of
+    sizeof(st_mysql_sys_var). The trick below avoids to deal with a
+    struct per variable type. Example:
+
+    struct { MYSQL_PLUGIN_VAR_HEADER; longlong *value; ...} var name;
+  */
   return *(byte**) (plugin_var+1);
 }
 
@@ -2516,7 +2711,7 @@ TYPELIB* sys_var_pluginvar::plugin_var_t
 
 
 byte* sys_var_pluginvar::value_ptr(THD *thd, enum_var_type type,
-                                   LEX_STRING *base)
+                                   LEX_STRING *base __attribute__((unused)))
 {
   byte* result;
 
@@ -2568,11 +2763,16 @@ bool sys_var_pluginvar::check(THD *thd, 
 void sys_var_pluginvar::set_default(THD *thd, enum_var_type type)
 {
   void *tgt, *src;
+  DBUG_ENTER("sys_var_pluginvar::set_default");
+  DBUG_PRINT("plugin", ("svpluginvar name: '%s'", name));
 
   DBUG_ASSERT(is_readonly() || plugin_var->update);
 
   if (is_readonly())
-    return;
+  {
+    DBUG_PRINT("plugin", ("is readonly"));
+    DBUG_VOID_RETURN;
+  }
 
   tgt= real_value_ptr(thd, type);
   src= ((void **) (plugin_var + 1) + 1);
@@ -2596,6 +2796,7 @@ void sys_var_pluginvar::set_default(THD 
   }
   else
     plugin_var->update(thd, plugin_var, tgt, src);
+  DBUG_VOID_RETURN;
 }
 
 
@@ -2630,111 +2831,115 @@ bool sys_var_pluginvar::update(THD *thd,
 }
 
 
-#define OPTION_SET_LIMITS(type, options, opt) \
+#define OPTION_SET_LIMITS(type, options, svpiv) \
   options->var_type= type; \
-  options->def_value= (opt)->def_val; \
-  options->min_value= (opt)->min_val; \
-  options->max_value= (opt)->max_val; \
-  options->block_size= (long) (opt)->blk_sz
+  options->def_value= (svpiv)->def_val; \
+  options->min_value= (svpiv)->min_val; \
+  options->max_value= (svpiv)->max_val; \
+  options->block_size= (long) (svpiv)->blk_sz
 
 
 static void plugin_opt_set_limits(struct my_option *options,
-                                  const struct st_mysql_sys_var *opt)
+                                  const struct st_mysql_sys_var *plugin_var)
 {
-  switch (opt->flags & (PLUGIN_VAR_TYPEMASK |
+  DBUG_ENTER("plugin_opt_set_limits");
+  DBUG_PRINT("plugin", ("option: '%s'", plugin_var->name));
+  switch (plugin_var->flags & (PLUGIN_VAR_TYPEMASK |
                         PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_THDLOCAL)) {
   /* global system variables */
   case PLUGIN_VAR_INT:
-    OPTION_SET_LIMITS(GET_INT, options, (sysvar_int_t*) opt);
+    OPTION_SET_LIMITS(GET_INT, options, (sysvar_int_t*) plugin_var);
     break;
   case PLUGIN_VAR_INT | PLUGIN_VAR_UNSIGNED:
-    OPTION_SET_LIMITS(GET_UINT, options, (sysvar_uint_t*) opt);
+    OPTION_SET_LIMITS(GET_UINT, options, (sysvar_uint_t*) plugin_var);
     break;
   case PLUGIN_VAR_LONG:
-    OPTION_SET_LIMITS(GET_LONG, options, (sysvar_long_t*) opt);
+    OPTION_SET_LIMITS(GET_LONG, options, (sysvar_long_t*) plugin_var);
     break;
   case PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED:
-    OPTION_SET_LIMITS(GET_ULONG, options, (sysvar_ulong_t*) opt);
+    OPTION_SET_LIMITS(GET_ULONG, options, (sysvar_ulong_t*) plugin_var);
     break;
   case PLUGIN_VAR_LONGLONG:
-    OPTION_SET_LIMITS(GET_LL, options, (sysvar_longlong_t*) opt);
+    OPTION_SET_LIMITS(GET_LL, options, (sysvar_longlong_t*) plugin_var);
     break;
   case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED:
-    OPTION_SET_LIMITS(GET_ULL, options, (sysvar_ulonglong_t*) opt);
+    OPTION_SET_LIMITS(GET_ULL, options, (sysvar_ulonglong_t*) plugin_var);
     break;
   case PLUGIN_VAR_ENUM:
     options->var_type= GET_ENUM;
-    options->typelib= ((sysvar_enum_t*) opt)->typelib;
-    options->def_value= *(ulong*) ((int*) (opt + 1) + 1);
+    options->typelib= ((sysvar_enum_t*) plugin_var)->typelib;
+    options->def_value= *(ulong*) ((int*) (plugin_var + 1) + 1);
     options->min_value= options->block_size= 0;
     options->max_value= options->typelib->count - 1;
     break;
   case PLUGIN_VAR_SET:
     options->var_type= GET_SET;
-    options->typelib= ((sysvar_set_t*) opt)->typelib;
-    options->def_value= *(ulonglong*) ((int*) (opt + 1) + 1);
+    options->typelib= ((sysvar_set_t*) plugin_var)->typelib;
+    options->def_value= *(ulonglong*) ((int*) (plugin_var + 1) + 1);
     options->min_value= options->block_size= 0;
     options->max_value= (ULL(1) << options->typelib->count) - 1;
     break;
   case PLUGIN_VAR_BOOL:
     options->var_type= GET_BOOL;
-    options->def_value= *(my_bool*) ((void**)(opt + 1) + 1);
+    options->def_value= *(my_bool*) ((void**)(plugin_var + 1) + 1);
     break;
   case PLUGIN_VAR_STR:
-    options->var_type= ((opt->flags & PLUGIN_VAR_MEMALLOC) ?
+    options->var_type= ((plugin_var->flags & PLUGIN_VAR_MEMALLOC) ?
                         GET_STR_ALLOC : GET_STR);
-    options->def_value= (ulonglong)(intptr) *((char**) ((void**) (opt + 1) + 1));
+    options->def_value=
+      (ulonglong)(intptr) *((char**) ((void**) (plugin_var + 1) + 1));
     break;
   /* threadlocal variables */
   case PLUGIN_VAR_INT | PLUGIN_VAR_THDLOCAL:
-    OPTION_SET_LIMITS(GET_INT, options, (thdvar_int_t*) opt);
+    OPTION_SET_LIMITS(GET_INT, options, (thdvar_int_t*) plugin_var);
     break;
   case PLUGIN_VAR_INT | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_THDLOCAL:
-    OPTION_SET_LIMITS(GET_UINT, options, (thdvar_uint_t*) opt);
+    OPTION_SET_LIMITS(GET_UINT, options, (thdvar_uint_t*) plugin_var);
     break;
   case PLUGIN_VAR_LONG | PLUGIN_VAR_THDLOCAL:
-    OPTION_SET_LIMITS(GET_LONG, options, (thdvar_long_t*) opt);
+    OPTION_SET_LIMITS(GET_LONG, options, (thdvar_long_t*) plugin_var);
     break;
   case PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_THDLOCAL:
-    OPTION_SET_LIMITS(GET_ULONG, options, (thdvar_ulong_t*) opt);
+    OPTION_SET_LIMITS(GET_ULONG, options, (thdvar_ulong_t*) plugin_var);
     break;
   case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_THDLOCAL:
-    OPTION_SET_LIMITS(GET_LL, options, (thdvar_longlong_t*) opt);
+    OPTION_SET_LIMITS(GET_LL, options, (thdvar_longlong_t*) plugin_var);
     break;
   case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_THDLOCAL:
-    OPTION_SET_LIMITS(GET_ULL, options, (thdvar_ulonglong_t*) opt);
+    OPTION_SET_LIMITS(GET_ULL, options, (thdvar_ulonglong_t*) plugin_var);
     break;
   case PLUGIN_VAR_ENUM | PLUGIN_VAR_THDLOCAL:
     options->var_type= GET_ENUM;
-    options->typelib= ((thdvar_enum_t*) opt)->typelib;
-    options->def_value= *(ulong*) ((int*) (opt + 1) + 1);
+    options->typelib= ((thdvar_enum_t*) plugin_var)->typelib;
+    options->def_value= *(ulong*) ((int*) (plugin_var + 1) + 1);
     options->min_value= options->block_size= 0;
     options->max_value= options->typelib->count - 1;
     break;
   case PLUGIN_VAR_SET | PLUGIN_VAR_THDLOCAL:
     options->var_type= GET_SET;
-    options->typelib= ((thdvar_set_t*) opt)->typelib;
-    options->def_value= *(ulonglong*) ((int*) (opt + 1) + 1);
+    options->typelib= ((thdvar_set_t*) plugin_var)->typelib;
+    options->def_value= *(ulonglong*) ((int*) (plugin_var + 1) + 1);
     options->min_value= options->block_size= 0;
     options->max_value= (ULL(1) << options->typelib->count) - 1;
     break;
   case PLUGIN_VAR_BOOL | PLUGIN_VAR_THDLOCAL:
     options->var_type= GET_BOOL;
-    options->def_value= *(my_bool*) ((int*) (opt + 1) + 1);
+    options->def_value= *(my_bool*) ((int*) (plugin_var + 1) + 1);
     break;
   case PLUGIN_VAR_STR | PLUGIN_VAR_THDLOCAL:
-    options->var_type= ((opt->flags & PLUGIN_VAR_MEMALLOC) ?
+    options->var_type= ((plugin_var->flags & PLUGIN_VAR_MEMALLOC) ?
                         GET_STR_ALLOC : GET_STR);
-    options->def_value= (intptr) *((char**) ((void**) (opt + 1) + 1));
+    options->def_value= (intptr) *((char**) ((void**) (plugin_var + 1) + 1));
     break;
   default:
     DBUG_ASSERT(0);
   }
   options->arg_type= REQUIRED_ARG;
-  if (opt->flags & PLUGIN_VAR_NOCMDARG)
+  if (plugin_var->flags & PLUGIN_VAR_NOCMDARG)
     options->arg_type= NO_ARG;
-  if (opt->flags & PLUGIN_VAR_OPCMDARG)
+  if (plugin_var->flags & PLUGIN_VAR_OPCMDARG)
     options->arg_type= OPT_ARG;
+  DBUG_VOID_RETURN;
 }
 
 
@@ -2746,18 +2951,39 @@ static my_bool get_one_option(int optid 
 }
 
 
-static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp,
-                             my_option *options, my_bool **enabled,
+/**
+  @brief Construct part of options array and alloc thread var space.
+
+  @detail Add to the options array the options for this plugin. Reserve
+  space for system variables that can have SESSION+GLOBAL values (thread
+  variables) in global_system_variables.dynamic_variables_ptr. Remember
+  the location in a "bookmark" and set it in the system_var array
+  defined by the plugin. Set mysql_sys_var_ptr() as the 'resolve'
+  function in the system_var array defined by the plugin.
+
+  @param[in]        mem_root    memory root
+  @param[in]        iplugin     internal plugin structure
+  @param[in,out]    options     the options arry to extend
+  @param[in,out]    enabled     if the plugin should be and is enabled
+  @param[in]        can_disable if the plugin can be disabled
+
+  @return error flag
+    @retval     0       OK
+    @retval     -1      Error
+*/
+
+static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *iplugin,
+                             struct my_option *options, my_bool **enabled,
                              bool can_disable)
 {
-  const char *plugin_name= tmp->plugin->name;
+  const char *plugin_name= iplugin->plugin->name;
   uint namelen= strlen(plugin_name), optnamelen;
   uint buffer_length= namelen * 4 + (can_disable ? 75 : 10);
   char *name= (char*) alloc_root(mem_root, buffer_length) + 1;
   char *optname, *p;
-  int index= 0, offset= 0;
-  st_mysql_sys_var *opt, **plugin_option;
-  st_bookmark *v;
+  int offset= 0;
+  struct st_mysql_sys_var *plugin_var, **plugin_var_p;
+  struct st_bookmark *bmk;
   DBUG_ENTER("construct_options");
   DBUG_PRINT("plugin", ("plugin: '%s'  enabled: %d  can_disable: %d",
                         plugin_name, **enabled, can_disable));
@@ -2803,127 +3029,147 @@ static int construct_options(MEM_ROOT *m
 
   /*
     Two passes as the 2nd pass will take pointer addresses for use
-    by my_getopt and register_var() in the first pass uses realloc
+    by my_getopt and register_var() in the first pass uses realloc.
+    global_system_variables.dynamic_variables_ptr may change for
+    every variable. After pass 1 it doesn't change any more for this
+    plugin.
+
+    Side effect: Variables of newly added plugins that can have session
+    values in addition to global values get space allocated for storing
+    their global values.
   */
 
-  for (plugin_option= tmp->plugin->system_vars;
-       plugin_option && *plugin_option; plugin_option++, index++)
+  for (plugin_var_p= iplugin->plugin->system_vars;
+       plugin_var_p && *plugin_var_p;
+       plugin_var_p++)
   {
-    opt= *plugin_option;
-    if (!(opt->flags & PLUGIN_VAR_THDLOCAL))
+    plugin_var= *plugin_var_p;
+
+    /* Ignore GLOBAL-only variables here. */
+    if (!(plugin_var->flags & PLUGIN_VAR_THDLOCAL))
       continue;
-    if (!(register_var(name, opt->name, opt->flags)))
+
+    /*
+      Register SESSION+GLOBAL variable and allocate space for its
+      GLOBAL value.
+    */
+    if (!(register_var(name, plugin_var->name, plugin_var->flags)))
       continue;
-    switch (opt->flags & PLUGIN_VAR_TYPEMASK) {
+
+    /* Set the 'resolve' function to be mysql_sys_var_ptr(). */
+    switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
     case PLUGIN_VAR_BOOL:
-      SET_PLUGIN_VAR_RESOLVE((thdvar_bool_t *) opt);
+      SET_PLUGIN_VAR_RESOLVE((thdvar_bool_t *) plugin_var);
       break;
     case PLUGIN_VAR_INT:
-      SET_PLUGIN_VAR_RESOLVE((thdvar_int_t *) opt);
+      SET_PLUGIN_VAR_RESOLVE((thdvar_int_t *) plugin_var);
       break;
     case PLUGIN_VAR_LONG:
-      SET_PLUGIN_VAR_RESOLVE((thdvar_long_t *) opt);
+      SET_PLUGIN_VAR_RESOLVE((thdvar_long_t *) plugin_var);
       break;
     case PLUGIN_VAR_LONGLONG:
-      SET_PLUGIN_VAR_RESOLVE((thdvar_longlong_t *) opt);
+      SET_PLUGIN_VAR_RESOLVE((thdvar_longlong_t *) plugin_var);
       break;
     case PLUGIN_VAR_STR:
-      SET_PLUGIN_VAR_RESOLVE((thdvar_str_t *) opt);
+      SET_PLUGIN_VAR_RESOLVE((thdvar_str_t *) plugin_var);
       break;
     case PLUGIN_VAR_ENUM:
-      SET_PLUGIN_VAR_RESOLVE((thdvar_enum_t *) opt);
+      SET_PLUGIN_VAR_RESOLVE((thdvar_enum_t *) plugin_var);
       break;
     case PLUGIN_VAR_SET:
-      SET_PLUGIN_VAR_RESOLVE((thdvar_set_t *) opt);
+      SET_PLUGIN_VAR_RESOLVE((thdvar_set_t *) plugin_var);
       break;
     default:
       sql_print_error("Unknown variable type code 0x%x in plugin '%s'.",
-                      opt->flags, plugin_name);
+                      plugin_var->flags, plugin_name);
       DBUG_RETURN(-1);
     };
   }
 
-  for (plugin_option= tmp->plugin->system_vars;
-       plugin_option && *plugin_option; plugin_option++, index++)
+  for (plugin_var_p= iplugin->plugin->system_vars;
+       plugin_var_p && *plugin_var_p;
+       plugin_var_p++)
   {
-    switch ((opt= *plugin_option)->flags & PLUGIN_VAR_TYPEMASK) {
+    /* Set 'check' and 'update' function pointers. */
+    switch ((plugin_var= *plugin_var_p)->flags & PLUGIN_VAR_TYPEMASK) {
     case PLUGIN_VAR_BOOL:
-      if (!opt->check)
-        opt->check= check_func_bool;
-      if (!opt->update)
-        opt->update= update_func_bool;
+      if (!plugin_var->check)
+        plugin_var->check= check_func_bool;
+      if (!plugin_var->update)
+        plugin_var->update= update_func_bool;
       break;
     case PLUGIN_VAR_INT:
-      if (!opt->check)
-        opt->check= check_func_int;
-      if (!opt->update)
-        opt->update= update_func_int;
+      if (!plugin_var->check)
+        plugin_var->check= check_func_int;
+      if (!plugin_var->update)
+        plugin_var->update= update_func_int;
       break;
     case PLUGIN_VAR_LONG:
-      if (!opt->check)
-        opt->check= check_func_long;
-      if (!opt->update)
-        opt->update= update_func_long;
+      if (!plugin_var->check)
+        plugin_var->check= check_func_long;
+      if (!plugin_var->update)
+        plugin_var->update= update_func_long;
       break;
     case PLUGIN_VAR_LONGLONG:
-      if (!opt->check)
-        opt->check= check_func_longlong;
-      if (!opt->update)
-        opt->update= update_func_longlong;
+      if (!plugin_var->check)
+        plugin_var->check= check_func_longlong;
+      if (!plugin_var->update)
+        plugin_var->update= update_func_longlong;
       break;
     case PLUGIN_VAR_STR:
-      if (!opt->check)
-        opt->check= check_func_str;
-      if (!opt->update)
+      if (!plugin_var->check)
+        plugin_var->check= check_func_str;
+      if (!plugin_var->update)
       {
-        opt->update= update_func_str;
-        if (!(opt->flags & PLUGIN_VAR_MEMALLOC))
+        plugin_var->update= update_func_str;
+        if (!(plugin_var->flags & PLUGIN_VAR_MEMALLOC))
         {
-          opt->flags |= PLUGIN_VAR_READONLY;
+          plugin_var->flags |= PLUGIN_VAR_READONLY;
           sql_print_warning("Server variable %s of plugin %s was forced "
                             "to be read-only: string variable without "
                             "update_func and PLUGIN_VAR_MEMALLOC flag",
-                            opt->name, plugin_name);
+                            plugin_var->name, plugin_name);
         }
       }
       break;
     case PLUGIN_VAR_ENUM:
-      if (!opt->check)
-        opt->check= check_func_enum;
-      if (!opt->update)
-        opt->update= update_func_long;
+      if (!plugin_var->check)
+        plugin_var->check= check_func_enum;
+      if (!plugin_var->update)
+        plugin_var->update= update_func_long;
       break;
     case PLUGIN_VAR_SET:
-      if (!opt->check)
-        opt->check= check_func_set;
-      if (!opt->update)
-        opt->update= update_func_longlong;
+      if (!plugin_var->check)
+        plugin_var->check= check_func_set;
+      if (!plugin_var->update)
+        plugin_var->update= update_func_longlong;
       break;
     default:
       sql_print_error("Unknown variable type code 0x%x in plugin '%s'.",
-                      opt->flags, plugin_name);
+                      plugin_var->flags, plugin_name);
       DBUG_RETURN(-1);
     }
 
-    if (opt->flags & PLUGIN_VAR_NOCMDOPT)
+    if (plugin_var->flags & PLUGIN_VAR_NOCMDOPT)
       continue;
 
-    if (!opt->name)
+    if (!plugin_var->name)
     {
       sql_print_error("Missing variable name in plugin '%s'.",
                       plugin_name);
       DBUG_RETURN(-1);
     }
 
-    if (!(v= find_bookmark(name, opt->name, opt->flags)))
+    if (!(bmk= find_bookmark(name, plugin_var->name, plugin_var->flags)))
     {
-      optnamelen= strlen(opt->name);
+      optnamelen= strlen(plugin_var->name);
       optname= (char*) alloc_root(mem_root, namelen + optnamelen + 2);
-      strxmov(optname, name, "-", opt->name, NullS);
+      strxmov(optname, name, "-", plugin_var->name, NullS);
       optnamelen= namelen + optnamelen + 1;
     }
     else
-      optname= memdup_root(mem_root, v->key + 1, (optnamelen= v->name_len) + 1);
+      optname= memdup_root(mem_root, bmk->key + 1,
+                           (optnamelen= bmk->name_len) + 1);
 
     /* convert '_' to '-' */
     for (p= optname; *p; p++)
@@ -2931,23 +3177,33 @@ static int construct_options(MEM_ROOT *m
         *p= '-';
 
     options->name= optname;
-    options->comment= opt->comment;
-    options->app_type= opt;
+    options->comment= plugin_var->comment;
+    options->app_type= plugin_var;
     options->id= (options-1)->id + 1;
 
-    if (opt->flags & PLUGIN_VAR_THDLOCAL)
-      *(int*)(opt + 1)= offset= v->offset;
+    /*
+      Here we assume that every thread variable, as defined by the
+      plugin, has its offset value of type 'int' immediately behind the
+      variable definition header (st_mysql_sys_var).
+
+      Note that we store an offset into
+      global_system_variables.dynamic_variables_ptr here to be safe if
+      that variable value space gets re-allocated.
+    */
+    if (plugin_var->flags & PLUGIN_VAR_THDLOCAL)
+      *(int*)(plugin_var + 1)= offset= bmk->offset;
 
-    plugin_opt_set_limits(options, opt);
+    plugin_opt_set_limits(options, plugin_var);
 
-    if ((opt->flags & PLUGIN_VAR_TYPEMASK) != PLUGIN_VAR_ENUM &&
-        (opt->flags & PLUGIN_VAR_TYPEMASK) != PLUGIN_VAR_SET)
+    /* Set value addresses. */
+    if ((plugin_var->flags & PLUGIN_VAR_TYPEMASK) != PLUGIN_VAR_ENUM &&
+        (plugin_var->flags & PLUGIN_VAR_TYPEMASK) != PLUGIN_VAR_SET)
     {
-      if (opt->flags & PLUGIN_VAR_THDLOCAL)
+      if (plugin_var->flags & PLUGIN_VAR_THDLOCAL)
         options->value= options->u_max_value= (gptr*)
           (global_system_variables.dynamic_variables_ptr + offset);
       else
-        options->value= options->u_max_value= *(gptr**) (opt + 1);
+        options->value= options->u_max_value= *(gptr**) (plugin_var + 1);
     }
 
     options[1]= options[0];
@@ -2962,30 +3218,33 @@ static int construct_options(MEM_ROOT *m
 }
 
 
-static my_option *construct_help_options(MEM_ROOT *mem_root,
-                                         struct st_plugin_int *p)
+static struct my_option *construct_help_options(MEM_ROOT *mem_root,
+                                                struct st_plugin_int *iplugin)
 {
-  st_mysql_sys_var **opt;
-  my_option *opts;
+  struct st_mysql_sys_var **plugin_var_p;
+  struct my_option *opts;
   my_bool dummy, can_disable;
   my_bool *dummy2= &dummy;
   uint count= EXTRA_OPTIONS;
   DBUG_ENTER("construct_help_options");
 
-  for (opt= p->plugin->system_vars; opt && *opt; opt++, count+= 2);
+  for (plugin_var_p= iplugin->plugin->system_vars;
+       plugin_var_p && *plugin_var_p;
+       plugin_var_p++, count+= 2) {}
 
-  if (!(opts= (my_option*) alloc_root(mem_root, sizeof(my_option) * count)))
+  if (!(opts= (struct my_option*) alloc_root(mem_root,
+                                             sizeof(struct my_option) * count)))
     DBUG_RETURN(NULL);
 
-  bzero(opts, sizeof(my_option) * count);
+  bzero(opts, sizeof(struct my_option) * count);
 
   dummy= TRUE; /* plugin is enabled. */
 
   can_disable=
-      my_strcasecmp(&my_charset_latin1, p->name.str, "MyISAM") &&
-      my_strcasecmp(&my_charset_latin1, p->name.str, "MEMORY");
+      my_strcasecmp(&my_charset_latin1, iplugin->name.str, "MyISAM") &&
+      my_strcasecmp(&my_charset_latin1, iplugin->name.str, "MEMORY");
 
-  if (construct_options(mem_root, p, opts, &dummy2, can_disable))
+  if (construct_options(mem_root, iplugin, opts, &dummy2, can_disable))
     DBUG_RETURN(NULL);
 
   DBUG_RETURN(opts);
@@ -3005,94 +3264,120 @@ static my_option *construct_help_options
   NOTE:
     Requires that a write-lock is held on LOCK_system_variables_hash
 */
-static int test_plugin_options(MEM_ROOT *tmp_root, struct st_plugin_int *tmp,
+static int test_plugin_options(MEM_ROOT *tmp_root,
+                               struct st_plugin_int *iplugin,
                                int *argc, char **argv, my_bool default_enabled)
 {
-  struct sys_var_chain chain= { NULL, NULL };
   my_bool enabled_saved= default_enabled, can_disable;
   my_bool *enabled= &default_enabled;
-  MEM_ROOT *mem_root= alloc_root_inited(&tmp->mem_root) ?
-                      &tmp->mem_root : &plugin_mem_root;
-  st_mysql_sys_var **opt;
-  my_option *opts;
+  MEM_ROOT *mem_root= alloc_root_inited(&iplugin->mem_root) ?
+                      &iplugin->mem_root : &plugin_mem_root;
+  struct st_mysql_sys_var **plugin_var_p;
+  struct my_option *opts;
   char *p, *varname;
   int error;
-  st_mysql_sys_var *o;
-  sys_var *v;
-  struct st_bookmark *var;
-  uint len, count= EXTRA_OPTIONS;
+  uint count= EXTRA_OPTIONS;
   DBUG_ENTER("test_plugin_options");
-  DBUG_ASSERT(tmp->plugin && tmp->name.str);
+  DBUG_ASSERT(iplugin->plugin && iplugin->name.str);
 
-  for (opt= tmp->plugin->system_vars; opt && *opt; opt++)
+  for (plugin_var_p= iplugin->plugin->system_vars;
+       plugin_var_p && *plugin_var_p;
+       plugin_var_p++)
     count+= 2; /* --{plugin}-{optname} and --plugin-{plugin}-{optname} */
 
   can_disable=
-      my_strcasecmp(&my_charset_latin1, tmp->name.str, "MyISAM") &&
-      my_strcasecmp(&my_charset_latin1, tmp->name.str, "MEMORY");
+      my_strcasecmp(&my_charset_latin1, iplugin->name.str, "MyISAM") &&
+      my_strcasecmp(&my_charset_latin1, iplugin->name.str, "MEMORY");
 
   if (count > EXTRA_OPTIONS || (*argc > 1))
   {
-    if (!(opts= (my_option*) alloc_root(tmp_root, sizeof(my_option) * count)))
+    if (!(opts= (struct my_option*) alloc_root(tmp_root,
+                                               sizeof(struct my_option) *
+                                               count)))
     {
-      sql_print_error("Out of memory for plugin '%s'.", tmp->name.str);
+      sql_print_error("Out of memory for plugin '%s'.", iplugin->name.str);
       DBUG_RETURN(-1);
     }
-    bzero(opts, sizeof(my_option) * count);
+    bzero(opts, sizeof(struct my_option) * count);
 
-    if (construct_options(tmp_root, tmp, opts, &enabled, can_disable))
+    /*
+      Side effect: Variables of newly added plugins that can have
+      session values in addition to global values get space allocated
+      for storing their global values.
+    */
+    if (construct_options(tmp_root, iplugin, opts, &enabled, can_disable))
     {
-      sql_print_error("Bad options for plugin '%s'.", tmp->name.str);
+      sql_print_error("Bad options for plugin '%s'.", iplugin->name.str);
       DBUG_RETURN(-1);
     }
 
+    /* This initializes the variables with their default values. */
     error= handle_options(argc, &argv, opts, get_one_option);
     (*argc)++; /* add back one for the program name */
 
     if (error)
     {
        sql_print_error("Parsing options for plugin '%s' failed.",
-                       tmp->name.str);
+                       iplugin->name.str);
        DBUG_RETURN(error);
     }
   }
 
   if (!*enabled && !can_disable)
   {
-    sql_print_warning("Plugin '%s' cannot be disabled", tmp->name.str);
+    sql_print_warning("Plugin '%s' cannot be disabled", iplugin->name.str);
     *enabled= TRUE;
   }
 
   if (*enabled)
   {
-    for (opt= tmp->plugin->system_vars; opt && *opt; opt++)
-    {
-      if (((o= *opt)->flags & PLUGIN_VAR_NOSYSVAR))
+    struct sys_var_chain chain= { NULL, NULL };
+
+    DBUG_PRINT("plugin", ("initializing variables for plugin: '%s'",
+                          iplugin->plugin->name));
+    for (plugin_var_p= iplugin->plugin->system_vars;
+         plugin_var_p && *plugin_var_p;
+         plugin_var_p++)
+    {
+      struct st_mysql_sys_var   *plugin_var;
+      struct st_bookmark        *bmk;
+      sys_var                   *sysvar;
+
+      DBUG_PRINT("plugin", ("variable: '%s'  type: %u  flags: %u",
+                            (*plugin_var_p)->name,
+                            (*plugin_var_p)->flags & PLUGIN_VAR_TYPEMASK,
+                            (*plugin_var_p)->flags & ~PLUGIN_VAR_TYPEMASK));
+      if (((plugin_var= *plugin_var_p)->flags & PLUGIN_VAR_NOSYSVAR))
         continue;
 
-      if ((var= find_bookmark(tmp->name.str, o->name, o->flags)))
-        v= new (mem_root) sys_var_pluginvar(var->key + 1, o);
+      if ((bmk= find_bookmark(iplugin->name.str, plugin_var->name,
+                              plugin_var->flags)))
+      {
+        /* Thread variable name can be taken from bookmark key. */
+        sysvar= new (mem_root) sys_var_pluginvar(bmk->key + 1, plugin_var);
+      }
       else
       {
-        len= tmp->name.length + strlen(o->name) + 2;
+        /* GLOBAL-only variable name needs to be constructed. */
+        uint len= iplugin->name.length + strlen(plugin_var->name) + 2;
         varname= (char*) alloc_root(mem_root, len);
-        strxmov(varname, tmp->name.str, "-", o->name, NullS);
+        strxmov(varname, iplugin->name.str, "-", plugin_var->name, NullS);
         my_casedn_str(&my_charset_latin1, varname);
 
         for (p= varname; *p; p++)
           if (*p == '-')
             *p= '_';
 
-        v= new (mem_root) sys_var_pluginvar(varname, o);
+        sysvar= new (mem_root) sys_var_pluginvar(varname, plugin_var);
       }
-      DBUG_ASSERT(v); /* check that an object was actually constructed */
+      DBUG_ASSERT(sysvar); /* check that an object was actually constructed */
 
       /*
         Add to the chain of variables.
         Done like this for easier debugging so that the
-        pointer to v is not lost on optimized builds.
+        pointer to sys_var is not lost on optimized builds.
       */
-      v->chain_sys_var(&chain);
+      sysvar->chain_sys_var(&chain);
     }
     if (chain.first)
     {
@@ -3100,17 +3385,17 @@ static int test_plugin_options(MEM_ROOT 
       if (mysql_add_sys_var_chain(chain.first, NULL))
       {
         sql_print_error("Plugin '%s' has conflicting system variables",
-                        tmp->name.str);
+                        iplugin->name.str);
         DBUG_RETURN(1);
       }
-      tmp->system_vars= chain.first;
+      iplugin->system_vars= chain.first;
     }
     DBUG_RETURN(0);
   }
 
   if (enabled_saved)
     sql_print_information("Plugin '%s' disabled by command line option",
-                          tmp->name.str);
+                          iplugin->name.str);
   DBUG_RETURN(1);
 }
 
@@ -3119,29 +3404,29 @@ static int test_plugin_options(MEM_ROOT 
   Help Verbose text with Plugin System Variables
 ****************************************************************************/
 
-static int option_cmp(my_option *a, my_option *b)
+static int option_cmp(struct my_option *a, struct my_option *b)
 {
   return my_strcasecmp(&my_charset_latin1, a->name, b->name);
 }
 
 
-void my_print_help_inc_plugins(my_option *main_options, uint size)
+void my_print_help_inc_plugins(struct my_option *main_options, uint size)
 {
   DYNAMIC_ARRAY all_options;
-  struct st_plugin_int *p;
+  struct st_plugin_int *iplugin;
   MEM_ROOT mem_root;
-  my_option *opt;
+  struct my_option *opt;
 
   init_alloc_root(&mem_root, 4096, 4096);
-  my_init_dynamic_array(&all_options, sizeof(my_option), size, size/4);
+  my_init_dynamic_array(&all_options, sizeof(struct my_option), size, size/4);
 
   if (initialized)
     for (uint idx= 0; idx < plugin_array.elements; idx++)
     {
-      p= dynamic_element(&plugin_array, idx, struct st_plugin_int *);
+      iplugin= dynamic_element(&plugin_array, idx, struct st_plugin_int *);
 
-      if (!p->plugin->system_vars ||
-          !(opt= construct_help_options(&mem_root, p)))
+      if (!iplugin->plugin->system_vars ||
+          !(opt= construct_help_options(&mem_root, iplugin)))
         continue;
 
       /* Only options with a non-NULL comment are displayed in help text */
@@ -3158,8 +3443,8 @@ void my_print_help_inc_plugins(my_option
   /* main_options now points to the empty option terminator */
   insert_dynamic(&all_options, (gptr) main_options);
 
-  my_print_help((my_option*) all_options.buffer);
-  my_print_variables((my_option*) all_options.buffer);
+  my_print_help((struct my_option*) all_options.buffer);
+  my_print_variables((struct my_option*) all_options.buffer);
 
   delete_dynamic(&all_options);
   free_root(&mem_root, MYF(0));

--- 1.19/plugin/fulltext/plugin_example.c	2007-05-09 18:00:46 +02:00
+++ 1.20/plugin/fulltext/plugin_example.c	2007-05-09 18:00:46 +02:00
@@ -221,6 +221,7 @@ static struct st_mysql_show_var simple_s
 
 static long     sysvar_one_value;
 static char     *sysvar_two_value;
+static char     *sysvar_three_value;
 
 static MYSQL_SYSVAR_LONG(simple_sysvar_one, sysvar_one_value,
   PLUGIN_VAR_RQCMDARG,
@@ -232,6 +233,11 @@ static MYSQL_SYSVAR_STR(simple_sysvar_tw
   "Simple fulltext parser example system variable number two. Give a string.",
   NULL, NULL, "simple sysvar two default");
 
+static MYSQL_SYSVAR_STR(simple_sysvar_three, sysvar_three_value,
+  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC,
+  "Simple fulltext parser example system variable number three. Give a string.",
+  NULL, NULL, NULL);
+
 static MYSQL_THDVAR_LONG(simple_thdvar_one,
   PLUGIN_VAR_RQCMDARG,
   "Simple fulltext parser example thread variable number one. Give a number.",
@@ -242,11 +248,18 @@ static MYSQL_THDVAR_STR(simple_thdvar_tw
   "Simple fulltext parser example thread variable number two. Give a string.",
   NULL, NULL, "simple thdvar two default");
 
+static MYSQL_THDVAR_STR(simple_thdvar_three,
+  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC,
+  "Simple fulltext parser example thread variable number three. Give a string.",
+  NULL, NULL, NULL);
+
 static struct st_mysql_sys_var* simple_system_variables[]= {
   MYSQL_SYSVAR(simple_sysvar_one),
   MYSQL_SYSVAR(simple_sysvar_two),
+  MYSQL_SYSVAR(simple_sysvar_three),
   MYSQL_SYSVAR(simple_thdvar_one),
   MYSQL_SYSVAR(simple_thdvar_two),
+  MYSQL_SYSVAR(simple_thdvar_three),
   NULL
 };
 
Thread
bk commit into 5.1 tree (istruewing:1.2511)ingo9 May