WL#9424: Configuration system variables as a service for mysql_server component

Affects: Server-8.0   —   Status: Complete   —   Priority: Medium

This worklog will provide the configuration system variables as a service to the
mysql_server component. The components can use to register, unregister and
get_variable to handle their own system variables.
Status variables are handled as separate task.
1.  This work will only apply to the system variables defined by components. The
system variables defined by the server component or any of the plugins it
operated are going to behave as they currently do.
2. Component system variables will be added as system variables. 
3. The component system variables will be added to the global names space of
system variables.
4. The mysql_server component will provide a system variable
registration/deregistration service for components to register/deregister their
variables by fetching the values from the command line/init file/persist file.
5. At component unload time we will unregister all component system variables
from the global system variables list, thus making future references to them
unresolvable
7. The SET command for the component variables will be in the form SET 
GLOBAL|PERSIST <component_name>.<variable_name>  = expr
Similarly SET [@@global. | @@persist. | @@]system_var_name = expr
Here I've used the following terms:
1. A system variable: a variable from a single global namespace whose value is
persisted so it survives server restarts
2. A server system variable: a system variable defined by the server component
(i.e mysqld server)
3. A plugin system variable: a system variable defined by an (old) plugin that
is handled through the server component and exposed as a server component variable
4. A component system variable is a system variable that is defined by a
component. And is belonging to that component.

This service will have three methods, to register, unregister and get a
component system variable. 

components/mysql_server/server_component.cc
BEGIN_SERVICE_IMPLEMENTATION(mysql_server, configuration_system_variables)
  configuration_system_variables_imp::register_variable,
  
configuration_system_variables_imp::unregister_variable,
  
configuration_system_variables_imp::get_variable_value,
END_SERVICE_IMPLEMENTATION()

components/mysql_server/configuration_variables.h
/**
  An implementation of the configutration system variables Service to register
variable and
     unregister variable.
*/
class configuration_system_variables_imp
{
public:
  /**
    Register system variables.

    @param  
    @return Status of performed operation
    @retval false success
    @retval true failure
  */
  static DEFINE_BOOL_METHOD(register_variable,
    (const char *component_name, // component_name 
     const char *name, // variable name 
     mysql_var_check_func check, // function to be called at check time, 
     mysql_var_update_func update, // function to be called at update time (to
trigger actions) 
     mysql_var_tostring_func tostr, // all variables have a string representation 
     mysql_var_fromstring_func fromstr, // all variables have a string
representation 
     void *check_arg, // type defined check constraints block 
     size_t max_memory_needed, // maximum memory needed to store the data type 
     void *default, // the default value 
     size_t default_len // the length of the default value));

  /**
    Unregister's system variable.
    @param 
    @return Status of performed operation
    @retval false success
    @retval true failure
  */
  static DEFINE_BOOL_METHOD(unregister_variable,
    (const char *component_name,
     const char *name // variable name));
  
   /**
    Get the system variable value from the global structure.
    @param 
    @return Status of performed operation
    @retval false success
    @retval true failure
  */
   static DEFINE_BOOL_METHOD(get_variable_value,
    (const char *component_name, const char *name, void *val, size_t*
out_length_of_val));
};

components/mysql_server/configuration_variables.cc
/**
  Register system variables.

  @param  component_name  name of the componentnt
  @param name variable name
  @param check function pointer, which is called at variable check time
  @param update function pointer, which is called at update time
  @param tostr variable value is converted to a string form
  @param fromstr variable value in string form
  @param check_arg  type defined check constraints block
  @param max_memory_needed  maximum memory needed to store the data type
  @param default  the default value for the variable
  @param  default_len  the length of the default value
  @return Status of performed operation
  @retval false success
  @retval true failure
*/
DEFINE_BOOL_METHOD(configuration_system_variables_imp
::register_variable,
  (const char *component_name, 
     const char *name,  
     mysql_var_check_func check, 
     mysql_var_update_func update,
     mysql_var_tostring_func tostr,
     mysql_var_fromstring_func fromstr,
     void *check_arg,
     size_t max_memory_needed,
     void *default,
     size_t default_len
{
   At registration time it'll make another st_mysql_sys_var, fill it in
accordingly and allocate and add the memory to the global place where values are
stored.
   So each variable will be global only, will always have a value specified, and
have its type be defined as a tuple [check function,update function,size of
value store,check_constraints,default value] 
   For example for an int variable the check_arg(i.e the check_contraints) will be: 
struct int_check_arg_s { 
  int min, max,block; 
} int_check_arg; 

The prototype for check/update/tostr function for an integer type variable will
look like:
typedef int (*mysql_var_check_func) (MYSQL_THD thd, const char *component_name,
const char *name, void *check_arg, size_t sizeof_check_arg, void *current_val,
size_t sizeof_current_val, void *new_val, size_t sizeof_new_val); 

typedef void (*mysql_var_update_func) (MYSQL_THD thd, const char
*component_name, const char *name, void *check_arg, size_t check_arg, void
*current_val, size_t sizeof_current_val, void *new_val, size_t sizeof_new_val); 

typedef int (*mysql_var_tostring_func) (MYSQL_THD thd, const char
*component_name, const char *name, void *val, size_t val_len, char *out_buffer,
size_t out_buffer_sz, size_t *out_buffer_len); 
typedef int (*mysql_var_fromstring_func) (MYSQL_THD thd, const char
*component_name, const char *name, void *string_val, size_t string_val_len, char
*out_buffer, size_t out_buffer_sz, size_t *out_buffer_len); 
 Similarly it will have function for remaining variable types like float_check,
float_update, float_to_string.
While storing into the global structure the mutex on the global structure has to
be taken and release it after that.
This api allocates the blocks of memory and holds it in the global structure.
The unregister_variable api has to be called to free the memory allocated by
this function. 
  
  return false;
}

/**
  Unregister system variables.

  @param  component_name nNme of the e component
  @ param name Variable name
  @return Status of performed operation
  @retval false success
  @retval true failure
*/
DEFINE_BOOL_METHOD(configuration_system_variables_imp
::unregister_variable,
  (const char *component_name, 
     const char *name))
{
   This function removes the configuration system variable from the global
structure and deallocates the memory.
   It takes the mutex on the global structure when it operates on the global
structure.
   
   return false;
}

/**
    Get the system variable value from the global structure.
    @param 
 component_name Name of the component
    @param name Name of the variable
    @param [out] val Value of the variable
    @param [out]  out_length_of_val length of the output buffer
    @return Status of performed operation
    @retval false success
    @retval true failure
*/
   DEFINE_BOOL_METHOD(configuration_system_variables_imp
   ::get_variable_value,
    (const char *component_name,
     const char *name, void *val,
     size_t* out_length_of_val));
   {
        This will get the value for the given variable name from the global
structure.
        A mutex will be taken while reading the value from the global structure.
        
        return false;
    }
The register_variable function will be called from the init_common_variables()
and my_handle_options
The unregister_variable function will be called from mysql_del_sys_var_chain()
The  get_variable_value function will be called from get_one_variable_ext()