diff --git a/server/core/load_utils.c b/server/core/load_utils.c index ba5507018..8bf157e9c 100644 --- a/server/core/load_utils.c +++ b/server/core/load_utils.c @@ -28,6 +28,7 @@ * 14/06/13 Mark Riddoch Updated to add call to ModuleInit if one is * defined in the loaded module. * Also updated to call fixed GetModuleObject + * 02/06/14 Mark Riddoch Addition of module info * * @endverbatim */ @@ -38,6 +39,7 @@ #include #include #include +#include #include #include @@ -47,10 +49,11 @@ static MODULES *registered = NULL; static MODULES *find_module(const char *module); static void register_module(const char *module, - const char *type, - void *dlhandle, - char *version, - void *modobj); + const char *type, + void *dlhandle, + char *version, + void *modobj, + MODULE_INFO *info); static void unregister_module(const char *module); char* get_maxscale_home(void) @@ -76,12 +79,13 @@ char* get_maxscale_home(void) void * load_module(const char *module, const char *type) { -char *home, *version; -char fname[MAXPATHLEN]; -void *dlhandle, *sym; -char *(*ver)(); -void *(*ep)(), *modobj; -MODULES *mod; +char *home, *version; +char fname[MAXPATHLEN]; +void *dlhandle, *sym; +char *(*ver)(); +void *(*ep)(), *modobj; +MODULES *mod; +MODULE_INFO *mod_info = NULL; if ((mod = find_module(module)) == NULL) { @@ -141,6 +145,11 @@ MODULES *mod; ModuleInit(); } + if ((sym = dlsym(dlhandle, "info")) != NULL) + { + mod_info = sym; + } + if ((sym = dlsym(dlhandle, "GetModuleObject")) == NULL) { LOGIF(LE, (skygw_log_write_flush( @@ -161,7 +170,7 @@ MODULES *mod; module, version, fname))); - register_module(module, type, dlhandle, version, modobj); + register_module(module, type, dlhandle, version, modobj, mod_info); } else { @@ -227,7 +236,7 @@ MODULES *mod = registered; * @param modobj The module object */ static void -register_module(const char *module, const char *type, void *dlhandle, char *version, void *modobj) +register_module(const char *module, const char *type, void *dlhandle, char *version, void *modobj, MODULE_INFO *mod_info) { MODULES *mod; @@ -239,6 +248,7 @@ MODULES *mod; mod->version = strdup(version); mod->modobj = modobj; mod->next = registered; + mod->info = mod_info; registered = mod; } @@ -303,11 +313,25 @@ dprintAllModules(DCB *dcb) { MODULES *ptr = registered; - dcb_printf(dcb, "%-15s | %-11s | Version\n", "Module Name", "Module Type"); - dcb_printf(dcb, "-----------------------------------------------------\n"); + dcb_printf(dcb, "%-15s | %-11s | Version | API | Status\n", "Module Name", "Module Type"); + dcb_printf(dcb, "--------------------------------------------------------------------------\n"); while (ptr) { - dcb_printf(dcb, "%-15s | %-11s | %s\n", ptr->module, ptr->type, ptr->version); + dcb_printf(dcb, "%-15s | %-11s | %-7s ", ptr->module, ptr->type, ptr->version); + if (ptr->info) + dcb_printf(dcb, "| %d.%d.%d | %s", + ptr->info->api_version.major, + ptr->info->api_version.minor, + ptr->info->api_version.patch, + ptr->info->status == MODULE_IN_DEVELOPMENT + ? "In Development" + : (ptr->info->status == MODULE_ALPHA_RELEASE + ? "Alpha" + : (ptr->info->status == MODULE_BETA_RELEASE + ? "Beta" + : (ptr->info->status == MODULE_GA + ? "GA" : "Unknown")))); + dcb_printf(dcb, "\n"); ptr = ptr->next; } } diff --git a/server/include/dcb.h b/server/include/dcb.h index e90a64856..49a262f73 100644 --- a/server/include/dcb.h +++ b/server/include/dcb.h @@ -19,6 +19,7 @@ */ #include #include +#include #include #include #include @@ -93,6 +94,13 @@ typedef struct gw_protocol { int (*session)(struct dcb *, void *); } GWPROTOCOL; +/** + * The GWPROTOCOL version data. The following should be updated whenever + * the GWPROTOCOL structure is changed. See the rules defined in modinfo.h + * that define how these numbers should change. + */ +#define GWPROTOCOL_VERSION {1, 0, 0} + /** * The statitics gathered on a descriptor control block */ diff --git a/server/include/modinfo.h b/server/include/modinfo.h new file mode 100644 index 000000000..c3c1e64da --- /dev/null +++ b/server/include/modinfo.h @@ -0,0 +1,85 @@ +#ifndef _MODINFO_H +#define _MODINFO_H +/* + * This file is distributed as part of MaxScale. It is free + * software: you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation, + * version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 51 + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright SkySQL Ab 2014 + */ + +/** + * @file modinfo.h The module information interface + * + * @verbatim + * Revision History + * + * Date Who Description + * 02/06/14 Mark Riddoch Initial implementation + * + * @endverbatim + */ + +/** + * The status of the module. This gives some idea of the module + * maturity. + */ +typedef enum { + MODULE_IN_DEVELOPMENT = 0, + MODULE_ALPHA_RELEASE, + MODULE_BETA_RELEASE, + MODULE_GA +} MODULE_STATUS; + +/** + * The API implemented by the module + */ +typedef enum { + MODULE_API_PROTOCOL = 0, + MODULE_API_ROUTER, + MODULE_API_MONITOR, + MODULE_API_FILTER, + MODULE_API_AUTHENTICATION +} MODULE_API; + +/** + * The module version structure. + * + * The rules for changing these values are: + * + * Any change that affects an inexisting call in the API in question, + * making the new API no longer compatible with the old, + * must increment the major version. + * + * Any change that adds to the API, but does not alter the existing API + * calls, must increment the minor version. + * + * Any change that is purely cosmetic and does not affect the calling + * conventions of the API must increment only the patch version number. + */ +typedef struct { + int major; + int minor; + int patch; +} MODULE_VERSION; + +/** + * The module information structure + */ +typedef struct { + MODULE_API modapi; + MODULE_STATUS status; + MODULE_VERSION api_version; + char *description; +} MODULE_INFO; +#endif diff --git a/server/include/modules.h b/server/include/modules.h index c90cf45a1..dc39983ac 100644 --- a/server/include/modules.h +++ b/server/include/modules.h @@ -18,6 +18,7 @@ * Copyright SkySQL Ab 2013 */ #include +#include /** * @file modules.h Utilities for loading modules @@ -39,6 +40,8 @@ typedef struct modules { char *version; /**< Module version */ void *handle; /**< The handle returned by dlopen */ void *modobj; /**< The module "object" this is the set of entry points */ + MODULE_INFO + *info; /**< The module information */ struct modules *next; /**< Next module in the linked list */ } MODULES; diff --git a/server/include/monitor.h b/server/include/monitor.h index 9ac453876..861c1c070 100644 --- a/server/include/monitor.h +++ b/server/include/monitor.h @@ -72,6 +72,12 @@ typedef struct { void (*replicationHeartbeat)(void *, int); } MONITOR_OBJECT; +/** + * The monitor API version number. Any change to the monitor module API + * must change these versions usign the rules defined in modinfo.h + */ +#define MONITOR_VERSION {1, 0, 0} + /** * Representation of the running monitor. */ diff --git a/server/include/router.h b/server/include/router.h index 004f91d51..ce8f547d8 100644 --- a/server/include/router.h +++ b/server/include/router.h @@ -78,6 +78,13 @@ typedef struct router_object { uint8_t (*getCapabilities)(ROUTER *instance, void* router_session); } ROUTER_OBJECT; +/** + * The router module API version. Any change that changes the router API + * must update these versions numbers in accordance with the rules in + * modinfo.h. + */ +#define ROUTER_VERSION { 1, 0, 0 } + typedef enum router_capability_t { RCAP_TYPE_UNDEFINED = 0, RCAP_TYPE_STMT_INPUT = (1 << 0), diff --git a/server/modules/monitor/galera_mon.c b/server/modules/monitor/galera_mon.c index 69bc38731..1493548d2 100644 --- a/server/modules/monitor/galera_mon.c +++ b/server/modules/monitor/galera_mon.c @@ -44,6 +44,7 @@ #include #include #include +#include extern int lm_enabled_logfiles_bitmask; @@ -51,6 +52,13 @@ static void monitorMain(void *); static char *version_str = "V1.2.0"; +MODULE_INFO info = { + MODULE_API_MONITOR, + MODULE_ALPHA_RELEASE, + MONITOR_VERSION, + "A Galera cluster monitor" +}; + static void *startMonitor(void *); static void stopMonitor(void *); static void registerServer(void *, SERVER *); diff --git a/server/modules/monitor/mysql_mon.c b/server/modules/monitor/mysql_mon.c index 96f842383..14b51ee29 100644 --- a/server/modules/monitor/mysql_mon.c +++ b/server/modules/monitor/mysql_mon.c @@ -48,6 +48,7 @@ #include #include #include +#include extern int lm_enabled_logfiles_bitmask; @@ -55,6 +56,13 @@ static void monitorMain(void *); static char *version_str = "V1.2.0"; +MODULE_INFO info = { + MODULE_API_MONITOR, + MODULE_ALPHA_RELEASE, + MONITOR_VERSION, + "A MySQL Master/Slave replication monitor" +}; + static void *startMonitor(void *); static void stopMonitor(void *); static void registerServer(void *, SERVER *); diff --git a/server/modules/protocol/httpd.c b/server/modules/protocol/httpd.c index f92e49598..7d06264b9 100644 --- a/server/modules/protocol/httpd.c +++ b/server/modules/protocol/httpd.c @@ -39,6 +39,14 @@ #include #include +#include + +MODULE_INFO info = { + MODULE_API_PROTOCOL, + MODULE_IN_DEVELOPMENT, + GWPROTOCOL_VERSION, + "An experimental HTTPD implementation for use in admnistration" +}; #define ISspace(x) isspace((int)(x)) #define HTTP_SERVER_STRING "Gateway(c) v.1.0.0" diff --git a/server/modules/protocol/mysql_backend.c b/server/modules/protocol/mysql_backend.c index efa92a71d..9dfa6e637 100644 --- a/server/modules/protocol/mysql_backend.c +++ b/server/modules/protocol/mysql_backend.c @@ -43,6 +43,14 @@ * 27/09/2013 Massimiliano Pinto Changed in gw_read_backend_event the check for dcb_read(), now is if rc < 0 * */ +#include + +MODULE_INFO info = { + MODULE_API_PROTOCOL, + MODULE_ALPHA_RELEASE, + GWPROTOCOL_VERSION, + "The MySQL to backend server protocol" +}; extern int lm_enabled_logfiles_bitmask; diff --git a/server/modules/protocol/mysql_client.c b/server/modules/protocol/mysql_client.c index bcd94e423..2f1a3b2c5 100644 --- a/server/modules/protocol/mysql_client.c +++ b/server/modules/protocol/mysql_client.c @@ -40,6 +40,14 @@ #include #include #include +#include + +MODULE_INFO info = { + MODULE_API_PROTOCOL, + MODULE_ALPHA_RELEASE, + GWPROTOCOL_VERSION, + "The client to MaxScale MySQL protocol implementation" +}; extern int lm_enabled_logfiles_bitmask; diff --git a/server/modules/protocol/telnetd.c b/server/modules/protocol/telnetd.c index f7d6c1815..651e979f0 100644 --- a/server/modules/protocol/telnetd.c +++ b/server/modules/protocol/telnetd.c @@ -36,6 +36,14 @@ #include #include #include +#include + +MODULE_INFO info = { + MODULE_API_PROTOCOL, + MODULE_ALPHA_RELEASE, + GWPROTOCOL_VERSION, + "A telnet deamon protocol for simple administration interface" +}; extern int lm_enabled_logfiles_bitmask; diff --git a/server/modules/routing/debugcli.c b/server/modules/routing/debugcli.c index 61e308a96..bf2404c08 100644 --- a/server/modules/routing/debugcli.c +++ b/server/modules/routing/debugcli.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -43,6 +44,14 @@ #include #include + +MODULE_INFO info = { + MODULE_API_ROUTER, + MODULE_ALPHA_RELEASE, + ROUTER_VERSION, + "The debug user interface" +}; + extern int lm_enabled_logfiles_bitmask; static char *version_str = "V1.1.1"; diff --git a/server/modules/routing/readconnroute.c b/server/modules/routing/readconnroute.c index 2bfba7efc..f1981c57a 100644 --- a/server/modules/routing/readconnroute.c +++ b/server/modules/routing/readconnroute.c @@ -79,6 +79,7 @@ #include #include #include +#include #include #include @@ -88,6 +89,13 @@ extern int lm_enabled_logfiles_bitmask; +MODULE_INFO info = { + MODULE_API_ROUTER, + MODULE_ALPHA_RELEASE, + ROUTER_VERSION, + "A connection based router to load balance based on connections" +}; + static char *version_str = "V1.0.2"; /* The router entry points */ diff --git a/server/modules/routing/readwritesplit/readwritesplit.c b/server/modules/routing/readwritesplit/readwritesplit.c index 5b855afe4..fca3bca92 100644 --- a/server/modules/routing/readwritesplit/readwritesplit.c +++ b/server/modules/routing/readwritesplit/readwritesplit.c @@ -30,6 +30,15 @@ #include #include #include +#include + +MODULE_INFO info = { + MODULE_API_ROUTER, + MODULE_ALPHA_RELEASE, + ROUTER_VERSION, + "A Read/Write splitting router for enhancement read scalability" +}; + extern int lm_enabled_logfiles_bitmask; @@ -2450,4 +2459,4 @@ static void rwsplit_process_options( } } } /*< for */ -} \ No newline at end of file +} diff --git a/server/modules/routing/testroute.c b/server/modules/routing/testroute.c index c0bd73fee..ce2ce2ca9 100644 --- a/server/modules/routing/testroute.c +++ b/server/modules/routing/testroute.c @@ -17,9 +17,17 @@ */ #include #include +#include static char *version_str = "V1.0.0"; +MODULE_INFO info = { + MODULE_API_ROUTER, + MODULE_IN_DEVELOPMENT, + ROUTER_VERSION, + "A test router - not for use in real systems" +}; + static ROUTER *createInstance(SERVICE *service, char **options); static void *newSession(ROUTER *instance, SESSION *session); static void closeSession(ROUTER *instance, void *session); @@ -145,4 +153,4 @@ static uint8_t getCapabilities( void* router_session) { return 0; -} \ No newline at end of file +}