diff options
author | unknown <serg@serg.mylan> | 2006-01-01 16:43:34 +0100 |
---|---|---|
committer | unknown <serg@serg.mylan> | 2006-01-01 16:43:34 +0100 |
commit | c038b644d7fe80eb6fd4729a07245fad3f0bcfde (patch) | |
tree | b4eae6635a5b924866c6432d6398c56cb12607b3 /sql/sql_plugin.cc | |
parent | bb1e8bd5e423e729bed411789359bb7b04eb8c6c (diff) | |
download | mariadb-git-c038b644d7fe80eb6fd4729a07245fad3f0bcfde.tar.gz |
plugin versioning: we cannot assume that sizeof(st_mysql_plugin)
is the same in the plugin and in the mysqld.
store the size in the plugin.
To simplify access to plugin's st_mysql_plugin, copy it on open and
convert to the latest version, so that the rest of the code would
not need to care about versions.
include/plugin.h:
plugin versioning: we cannot assume that sizeof(st_mysql_plugin)
is the same in the plugin and in the mysqld.
store the size in the plugin.
Diffstat (limited to 'sql/sql_plugin.cc')
-rw-r--r-- | sql/sql_plugin.cc | 92 |
1 files changed, 82 insertions, 10 deletions
diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 51e53252d84..9c3d19369c8 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -29,6 +29,8 @@ LEX_STRING plugin_type_names[]= }; static const char *plugin_interface_version_sym= "_mysql_plugin_interface_version_"; +static const char *sizeof_st_plugin_sym= + "_mysql_sizeof_struct_st_plugin_"; static const char *plugin_declarations_sym= "_mysql_plugin_declarations_"; static int min_plugin_interface_version= 0x0000; /* Note that 'int version' must be the first field of every plugin @@ -90,6 +92,13 @@ static st_plugin_dl *plugin_dl_insert_or_reuse(struct st_plugin_dl *plugin_dl) struct st_plugin_dl *)); } +static inline void free_plugin_mem(struct st_plugin_dl *p) +{ + dlclose(p->handle); + 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)); +} static st_plugin_dl *plugin_dl_add(LEX_STRING *dl, int report) { @@ -121,6 +130,7 @@ static st_plugin_dl *plugin_dl_add(LEX_STRING *dl, int report) tmp->ref_count++; DBUG_RETURN(tmp); } + bzero(&plugin_dl, sizeof(plugin_dl)); /* Compile dll path */ strxnmov(dlpath, sizeof(dlpath) - 1, opt_plugin_dir, "/", dl->str, NullS); plugin_dl.ref_count= 1; @@ -136,7 +146,7 @@ static st_plugin_dl *plugin_dl_add(LEX_STRING *dl, int report) /* Determine interface version */ if (!(sym= dlsym(plugin_dl.handle, plugin_interface_version_sym))) { - dlclose(plugin_dl.handle); + free_plugin_mem(&plugin_dl); if (report & REPORT_TO_USER) my_error(ER_CANT_FIND_DL_ENTRY, MYF(0), plugin_interface_version_sym); if (report & REPORT_TO_LOG) @@ -148,7 +158,7 @@ static st_plugin_dl *plugin_dl_add(LEX_STRING *dl, int report) if (plugin_dl.version < min_plugin_interface_version || (plugin_dl.version >> 8) > (MYSQL_PLUGIN_INTERFACE_VERSION >> 8)) { - dlclose(plugin_dl.handle); + free_plugin_mem(&plugin_dl); if (report & REPORT_TO_USER) my_error(ER_CANT_OPEN_LIBRARY, MYF(0), dlpath, 0, "plugin interface version mismatch"); @@ -160,19 +170,84 @@ static st_plugin_dl *plugin_dl_add(LEX_STRING *dl, int report) /* Find plugin declarations */ if (!(sym= dlsym(plugin_dl.handle, plugin_declarations_sym))) { - dlclose(plugin_dl.handle); + free_plugin_mem(&plugin_dl); if (report & REPORT_TO_USER) my_error(ER_CANT_FIND_DL_ENTRY, MYF(0), plugin_declarations_sym); if (report & REPORT_TO_LOG) sql_print_error(ER(ER_CANT_FIND_DL_ENTRY), plugin_declarations_sym); DBUG_RETURN(0); } + + if (plugin_dl.version != MYSQL_PLUGIN_INTERFACE_VERSION) + { + int i, sizeof_st_plugin; + struct st_mysql_plugin *old, *cur; + char *ptr=(char *)sym; + + if ((sym= dlsym(plugin_dl.handle, sizeof_st_plugin_sym))) + sizeof_st_plugin= *(int *)sym; + else + { +#ifdef ERROR_ON_NO_SIZEOF_PLUGIN_SYMBOL + free_plugin_mem(&plugin_dl); + if (report & REPORT_TO_USER) + my_error(ER_CANT_FIND_DL_ENTRY, MYF(0), sizeof_st_plugin_sym); + if (report & REPORT_TO_LOG) + sql_print_error(ER(ER_CANT_FIND_DL_ENTRY), sizeof_st_plugin_sym); + DBUG_RETURN(0); +#else + DBUG_ASSERT(min_plugin_interface_version == 0); + sizeof_st_plugin=(int)offsetof(struct st_mysql_plugin, version); +#endif + } + + for (i= 0; + ((struct st_mysql_plugin *)(ptr+i*sizeof_st_plugin))->info; + i++) + /* no op */; + + cur= (struct st_mysql_plugin*) + my_malloc(i*sizeof(struct st_mysql_plugin), MYF(MY_ZEROFILL|MY_WME)); + if (!cur) + { + free_plugin_mem(&plugin_dl); + if (report & REPORT_TO_USER) + my_error(ER_OUTOFMEMORY, MYF(0), plugin_dl.dl.length); + if (report & REPORT_TO_LOG) + sql_print_error(ER(ER_OUTOFMEMORY), plugin_dl.dl.length); + DBUG_RETURN(0); + } + for (i=0; + (old=(struct st_mysql_plugin *)(ptr+i*sizeof_st_plugin))->info; + i++) + { + switch (plugin_dl.version) { + default: /* version > MYSQL_PLUGIN_INTERFACE_VERSION */ + /* fall through */ + case 0x0001: + cur[i].version=old->version; + // cur[i].status_vars=old->status_vars; + /* fall through */ + case 0x0000: + cur[i].type=old->type; + cur[i].info=old->info; + cur[i].name=old->name; + cur[i].author=old->author; + cur[i].descr=old->descr; + cur[i].init=old->init; + cur[i].deinit=old->deinit; + } + } + + sym=cur; + } plugin_dl.plugins= (struct st_mysql_plugin *)sym; + /* Duplicate and convert dll name */ plugin_dl.dl.length= dl->length * files_charset_info->mbmaxlen + 1; if (! (plugin_dl.dl.str= my_malloc(plugin_dl.dl.length, MYF(0)))) { - dlclose(plugin_dl.handle); + free_plugin_mem(&plugin_dl); if (report & REPORT_TO_USER) my_error(ER_OUTOFMEMORY, MYF(0), plugin_dl.dl.length); if (report & REPORT_TO_LOG) @@ -186,8 +261,7 @@ static st_plugin_dl *plugin_dl_add(LEX_STRING *dl, int report) /* Add this dll to array */ if (! (tmp= plugin_dl_insert_or_reuse(&plugin_dl))) { - dlclose(plugin_dl.handle); - my_free(plugin_dl.dl.str, MYF(0)); + free_plugin_mem(&plugin_dl); if (report & REPORT_TO_USER) my_error(ER_OUTOFMEMORY, MYF(0), sizeof(struct st_plugin_dl)); if (report & REPORT_TO_LOG) @@ -223,8 +297,7 @@ static void plugin_dl_del(LEX_STRING *dl) /* Do not remove this element, unless no other plugin uses this dll. */ if (! --tmp->ref_count) { - dlclose(tmp->handle); - my_free(tmp->dl.str, MYF(0)); + free_plugin_mem(tmp); bzero(tmp, sizeof(struct st_plugin_dl)); } break; @@ -646,8 +719,7 @@ void plugin_free(void) #ifdef HAVE_DLOPEN if (tmp->handle) { - dlclose(tmp->handle); - my_free(tmp->dl.str, MYF(0)); + free_plugin_mem(tmp); } #endif } |