MySQL Plugin中可写String类型Variable的实现细节
文章目录
为MySQL Plugin新增加一个String类型Variable,且这个Variable是可以被编辑的
标准的编码如下:
static MYSQL_SYSVAR_STR(row_cache_index, innodb_row_cache_index,
PLUGIN_VAR_OPCMDARG,
"The config of index need to cache.",
NULL,
innodb_row_cache_index_update, NULL);
其中 innodb_row_cache_index_update为当innodb_row_cache_index被 set 后会调用的函数:
static
void
innodb_row_cache_index_update(
/_===========================_/
THD* thd, /_!< in: thread handle */
struct st_mysql_sys_var_ var, /_!< in: pointer to
system variable */
void_ var_ptr, /_!< out: where the
formal string goes */
const void_ save) /*!< in: immediate result
from check function */
{
ut_a(var_ptr != NULL);
ut_a(save != NULL);
*static_cast(var_ptr) = *static_cast(save);
reset_filter();
}
其中
*static_cast(var_ptr) = *static_cast(save);
表示将save的值赋值给var_ptr对应的指针就是innodb_row_cache_index
但是这个时候会有一个问题就是当set操作完成时const void* save对应的内存是会被free的,这个时候innodb_row_cache_index指向的就是一个脏区了.那么接下去对innodb_row_cache_index的操作将会引发crash等可怕的后果
要怎么处理这个问题呢.最简单的就是对save的值进行memcpy. 到一个新地址,这地址可以是临时malloc出来的,但是不建议,因为malloc可能会失败.一旦失败.那处理起来也很麻烦,还有一个办法就是直接使用栽内存.由编译器预先分配的,可以见reset_filter()的实现:
void reset_filter(){
size_t len = 0;
if(innodb_row_cache_index){
len = strlen(innodb_row_cache_index);
}
len = len>INDEX_CONFIG_LEN ? INDEX_CONFIG_LEN : len;
memset(innodb_row_cache_index_r,0,INDEX_CONFIG_LEN+1);
if(len){
ut_memcpy(innodb_row_cache_index_r,innodb_row_cache_index,len);
}
innodb_row_cache_index_r[len] = '';
innodb_row_cache_index = innodb_row_cache_index_r;
//TODO someting
}
其中innodb_row_cache_index_r的定义为
static char innodb_row_cache_index_r[INDEX_CONFIG_LEN + 1];
由编译器预先分配一个INDEX_CONFIG_LEN + 1大小的数组来真正存值
这样就避免save被free掉而引发的问题