文章目录

为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掉而引发的问题

文章目录