WL#2936: Falcon & MySQL plugin interface: server variables

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

Plugin should be able to specify server variables that are shown in SHOW
VARIABLES and settable with SET

Server variables should be made accessible from the command line and my.cnf 
and are optionally read-only at run time.

Plugin server variables may be bound to static variables or may be dynamically 
allocated as a thread-local session variable.

It should be easy to maintain plugins which make use of server variables.

(as a side mini-project, support for disabling specific plugins is added by 
supporting "--skip-plugin-{name}" or simply "--skip-{name}" if there is no 
ambiguity)
Server variables that are visible in SHOW VARIABLES and alterable with SET 
should be managed dynamically and facilities be provided so that variables may 
be added and removed at run time.

There is only one global list of server variables.

It should be possible to add and remove server variables without fear of 
removing the wrong one and to add variables with facility to detect name 
conflicts. In the case of plugins, the plugin code will probably unregister 
all variables and fail the initialization of the plugin.

There should be a degree of 'future-proofing' of the API/ABI such that the 
scope of variable types can be amended and enhanced without fear of causing 
any disruptive change to the ABI. This is important as a unstable ABI would 
increase the maintainence headache for plugin vendors and is likely to limit 
the availability of plugins for all versions of MySQL.

It is assumed that future enhancements to existing structures is likely to 
take the form of additional elements. In this senerio, it is adequate to 
version the structures by simply using the size of the structure. In order to 
facilite backwards/forwards compatibility, for the same structure type, the 
order and size of the elements should not change and any change occurrs by 
appending new elements to the structure.

The plugin framework will make use of 2 new function calls, implemented as a 
result of this worklog, to add and remove server variables.
It would also be possible to localize the declaration of variables to their 
particular source module, hence reducing the amount of global variables. The 
existing interface as exposed by set_var.h should not change 
significantly.

Server variables are to be made available to be modified from the command line 
and my.cnf. For the server variables which have an appropiate help text entry, 
they are to be detailed verbosely. Optionally, a server variable may be 
declared as read-only at run time or as not available for command line use.

How mysqld handles command line options should be altered so that all 
unhandled command line options are preserved for the until after the last 
dynamically loaded plugin has been initialized.

'--load-plugin=name,dsoname.so' may be used to load plugins as an alternative 
to the mysql.plugins table - it works even when --skip-grants is in effect and 
does not alter/require any system table..
Copyright (c) 2001-2007 by MySQL AB. All rights reserved.

The basic header for a server variable structure is as follows:

struct st_mysql_sys_var
{
  int flags;
  const char *name, *comment;
  int (*check)(THD*, struct st_mysql_sys_var *, void*, Item*);
  void (*update)(THD*, struct st_mysql_sys_var *, void*, void*);
};

Additional fields are append as required depending upon the flags.

Typical plugin implementors do not need to worry about these internal 
structurs and are able to declare their server variables by use of the 
conveience macros.

During the following definitions...
  name - is an unquoted identifier for the system variable
  varname - is the identifier for the static variable, where not
            available, it is the same as field 'name'.
  opt - additional use flags for the system variable
  comment - descriptive comment, appears in help text. NULL if this
            variable is to be hidden.
  check - check function, NULL for default
  update - update function, NULL for default
  default, minimum, maximum, blocksize - default/limits for variable

Typical flags:
  PLUGIN_VAR_READONLY
    Indicates that the system variable is READ ONLY.

  PLUGIN_VAR_NOSYSVAR
    Indicates that the system variable is not user visible at run time.

  PLUGIN_VAR_NOCMDOPT
    Indicates that the system variable is not configuable from the cmd line.

  PLUGIN_VAR_NOCMDARG
    Indicates that no argument is required at the command line.
    (typically used for BOOL variables)

  PLUGIN_VAR_RQCMDARG
    Indicates that an argument is required at the command line
    (this is the default)

  PLUGIN_VAR_OPCMDARG
    Indicates that an argument is optional at the command line

  PLUGIN_VAR_MEMALLOC
    Used for STR variables. Indicates that memory is to be alloced for
    storage of the string.


System variables may be access by either using the static variable directly or 
by using the SYSVAR() accessor macro. Use of the SYSVAR() macro should only 
usually occur when the code cannot directly access the underlying variable and 
is provided for completeness.

example:
  static int my_foo;
  static MYSQL_SYSVAR_INT(foo_var, my_foo, 
                          PLUGIN_VAR_RQCMDARG, "foo comment", 
                          NULL, NULL, 0, 0, INT_MAX, 0);
  ...
    SYSVAR(foo_var)= value;
    value= SYSVAR(foo_var);

    my_foo= value; 
    value= my_foo;



Session variables may only be accessed via the THDVAR() accessor macro.

example:
  static MYSQL_THDVAR_BOOL(some_flag, 
                           PLUGIN_VAR_NOCMDARG, "flag comment",
                           NULL, NULL, FALSE);
  ...
    if (THDVAR(thd, some_flag))
    {
      do_something();
      THDVAR(thd, some_flag)= FALSE;
    }

All global and session variables must published to mysqld before use. This is 
done by constructing a NULL terminated array of the variables and linking to 
it in the plugin public interface,

example:
  static struct st_mysql_sys_var *my_plugin_vars[]= {
    MYSQL_SYSVAR(my_foo),
    MYSQL_SYSVAR(some_flag),
    NULL
  };

  mysql_declare_plugin(fooplug)
  {
    MYSQL_..._PLUGIN,
    &plugin_data,
    "fooplug",
    "This does foo!",
    PLUGIN_LICENSE_GPL,
    foo_init,
    foo_fini,
    0x0001,
    NULL,
    my_plugin_vars,
    NULL
  }
  mysql_declare_plugin_end;


--------------------------------------------------

MYSQL_THDVAR_BOOL(name, opt, comment, check, update, default)

MYSQL_SYSVAR_BOOL(name, varname, opt, comment, check, update, default)

Used to declare a system variable of type 'my_bool', which is a 1 byte 
boolean. (0 == FALSE, 1 == TRUE)

--------------------------------------------------

MYSQL_THDVAR_STR(name, opt, comment, check, update, default)

MYSQL_SYSVAR_STR(name, varname, opt, comment, check, update, default)

Used to declare a system variable of type 'char*', which is a pointer to a NUL 
terminated string.

--------------------------------------------------

MYSQL_THDVAR_INT(name, opt, comment, check, update, default, min, max, blk)

MYSQL_SYSVAR_INT(name, varname, opt, comment, check, update, default,
                 minimum, maximum, blocksize)

Used to declare a system variable of type 'int', which is typically a 4 byte 
signed word.

--------------------------------------------------

MYSQL_THDVAR_UINT(name, opt, comment, check, update, default, min, max, blk)

MYSQL_SYSVAR_UINT(name, varname, opt, comment, check, update, default,
                  minimum, maximum, blocksize)

Used to declare a system variable of type 'unsigned int', which is typically a 
4 byte unsigned word.

--------------------------------------------------

MYSQL_THDVAR_LONG(name, opt, comment, check, update, default, min, max, blk)

MYSQL_SYSVAR_LONG(name, varname, opt, comment, check, update, default,
                  minimum, maximum, blocksize)

Used to declare a system variable of type 'long', which is typically either a 
4 or 8 byte signed word.

--------------------------------------------------

MYSQL_THDVAR_ULONG(name, opt, comment, check, update, default, min, max, blk)

MYSQL_SYSVAR_ULONG(name, varname, opt, comment, check, update, default,
                   minimum, maximum, blocksize)

Used to declare a system variable of type 'unsigned long', which is typically 
either a 4 or 8 byte unsigned word.

--------------------------------------------------

MYSQL_THDVAR_LONGLONG(name, opt, comment, check, update,
                      default, minimum, maximum, blocksize)

MYSQL_SYSVAR_LONGLONG(name, varname, opt, comment, check, update, 
                      default, minimum, maximum, blocksize)

Used to declare a system variable of type 'long long', which is typically an 8 
byte signed word.

--------------------------------------------------

MYSQL_THDVAR_ULONGLONG(name, opt, comment, check, update, 
                       default, minimum, maximum, blocksize)

MYSQL_SYSVAR_ULONGLONG(name, varname, opt, comment, check, update,
                       default, minimum, maximum, blocksize)

Used to declare a system variable of type 'unsigned long long', which is 
typically an 8 byte unsigned word.

--------------------------------------------------

MYSQL_THDVAR_ENUM(name, opt, comment, check, update, default, typelib)

MYSQL_SYSVAR_ENUM(name, varname, opt, comment, check, update,
                  default, typelib)

Used to declare a system variable of type 'unsigned long', which is 
typically either 4 or 8 byte unsigned word. The range of possible values is an 
ordinal of the number of elements in the typelib, starting from 0.

--------------------------------------------------

MYSQL_THDVAR_SET(name, opt, comment, check, update, default, typelib)

MYSQL_SYSVAR_SET(name, varname, opt, comment, check, update,
                 default, typelib)

Used to declare a system variable of type 'unsigned long long', which is 
typically an 8 byte unsigned word. Each bit represents an element in 
the typelib.

--------------------------------------------------

Internally, all mutable and plugin system variables are stored in a HASH.


----

Display of the server command line verbose help text is handled by compiling a 
DYNAMIC_ARRAY of all variables relevent to command line options, sorting them, 
and then enumerating through then to display each option.

When a command line option has been handled, it is then removed from the argv 
by the handle_option function (my_getopt.c), in effect, it is consumed.

The processing of command line options is performed during the plugin 
installation process, immediately after the plugin has been successfully 
loaded but before the plugin initialization function has been called.

Plugins loaded at run time do not benefit from any configuration options and 
must have usuable defaults. Once they are installed, they are loaded at mysqld 
initialization time and so configuration options are accessible at the command 
line and my.cnf