1
/***********************************************************************
3
Copyright (c) 2011, 2013, Oracle and/or its affiliates. All Rights Reserved.
5
This program is free software; you can redistribute it and/or modify it
6
under the terms of the GNU General Public License as published by the
7
Free Software Foundation; version 2 of the License.
9
This program is distributed in the hope that it will be useful, but
10
WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
12
Public License for more details.
14
You should have received a copy of the GNU General Public License along
15
with this program; if not, write to the Free Software Foundation, Inc.,
16
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
18
***********************************************************************/
20
/**************************************************//**
22
InnoDB Memcached configurations
24
Created 04/12/2011 Jimmy Yang
25
*******************************************************/
32
#include "innodb_api.h"
33
#include "innodb_config.h"
34
#include "innodb_cb_api.h"
35
#include "innodb_utility.h"
37
/** Configure options enum IDs, their "names" and their default value */
38
option_t config_option_names[] =
40
{OPTION_ID_COL_SEP, COLUMN_SEPARATOR, {"|", 1}},
41
{OPTION_ID_TBL_MAP_SEP, TABLE_MAP_SEPARATOR, {".", 1}}
44
/**********************************************************************//**
45
Makes a NUL-terminated copy of a nonterminated string.
46
@return own: a copy of the string, must be deallocated by caller */
51
const char* str, /*!< in: string to be copied */
52
int len) /*!< in: length of str, in bytes */
54
char* s = (char*) malloc(len + 1);
62
return((char*) memcpy(s, str, len));
65
/**********************************************************************//**
66
This function frees meta info structures */
70
meta_cfg_info_t* item) /*!< in: meta info structure */
74
for (i = 0; i < CONTAINER_NUM_COLS; i++) {
75
if (item->col_info[i].col_name) {
76
free(item->col_info[i].col_name);
77
item->col_info[i].col_name = NULL;
81
if (item->index_info.idx_name) {
82
free(item->index_info.idx_name);
83
item->index_info.idx_name = NULL;
86
if (item->extra_col_info) {
87
for (i = 0; i < item->n_extra_col; i++) {
88
free(item->extra_col_info[i].col_name);
89
item->extra_col_info[i].col_name = NULL;
92
free(item->extra_col_info);
93
item->extra_col_info = NULL;
97
/**********************************************************************//**
98
This function parses possible multiple column name separated by ",", ";"
99
or " " in the input "str" for the memcached "value" field.
100
@return true if everything works out fine */
103
innodb_config_parse_value_col(
104
/*==========================*/
105
meta_cfg_info_t*item, /*!< in: meta info structure */
106
char* str, /*!< in: column name(s) string */
107
int len) /*!< in: length of above string */
109
static const char* sep = " ;,|\n";
113
char* my_str = my_strdupl(str, len);
115
/* Find out how many column names in the string */
116
for (column_str = strtok_r(my_str, sep, &last);
118
column_str = strtok_r(NULL, sep, &last)) {
128
item->extra_col_info = malloc(
129
num_cols * sizeof(*item->extra_col_info));
131
if (!item->extra_col_info) {
135
for (column_str = strtok_r(my_str, sep, &last);
137
column_str = strtok_r(NULL, sep, &last)) {
138
item->extra_col_info[i].col_name_len = strlen(
140
item->extra_col_info[i].col_name = my_strdupl(
142
item->extra_col_info[i].col_name_len);
143
item->extra_col_info[i].field_id = -1;
147
item->n_extra_col = num_cols;
149
item->extra_col_info = NULL;
150
item->n_extra_col = 0;
156
/**********************************************************************//**
157
This function opens the cache_policy configuration table, and find the
158
table and column info that used for memcached data
159
@return true if everything works out fine */
162
innodb_read_cache_policy(
163
/*=====================*/
164
meta_cfg_info_t* item) /*!< in: meta info structure */
167
ib_crsr_t crsr = NULL;
168
ib_crsr_t idx_crsr = NULL;
170
ib_err_t err = DB_SUCCESS;
174
ib_col_meta_t col_meta;
176
ib_trx = ib_cb_trx_begin(IB_TRX_READ_COMMITTED, true, false);
178
err = innodb_api_begin(NULL, MCI_CFG_DB_NAME,
179
MCI_CFG_CACHE_POLICIES, NULL, ib_trx,
180
&crsr, &idx_crsr, IB_LOCK_S);
182
if (err != DB_SUCCESS) {
183
fprintf(stderr, " InnoDB_Memcached: Cannot open config table"
184
"'%s' in database '%s'. Error %d\n",
185
MCI_CFG_CACHE_POLICIES, MCI_CFG_DB_NAME,
191
tpl = innodb_cb_read_tuple_create(crsr);
193
/* Currently, we support one table per memcached setup.
194
We could extend that limit later */
195
err = innodb_cb_cursor_first(crsr);
197
if (err != DB_SUCCESS) {
198
fprintf(stderr, " InnoDB_Memcached: failed to locate entry in"
199
" config table '%s' in database '%s' \n",
200
MCI_CFG_CACHE_POLICIES, MCI_CFG_DB_NAME);
205
err = ib_cb_read_row(crsr, tpl, NULL, NULL);
207
n_cols = innodb_cb_tuple_get_n_cols(tpl);
209
assert(n_cols >= CACHE_POLICY_NUM_COLS);
211
for (i = 0; i < CACHE_POLICY_NUM_COLS; ++i) {
213
meta_cache_opt_t opt_val;
215
/* Skip cache policy name for now, We could have
216
different cache policy stored, and switch dynamically */
217
if (i == CACHE_POLICY_NAME) {
221
data_len = innodb_cb_col_get_meta(tpl, i, &col_meta);
223
if (data_len == IB_SQL_NULL) {
224
opt_val = META_CACHE_OPT_INNODB;
226
opt_name = *(char*)innodb_cb_col_get_value(tpl, i);
228
opt_val = (meta_cache_opt_t) opt_name;
231
if (opt_val >= META_CACHE_NUM_OPT
232
|| opt_val < META_CACHE_OPT_INNODB) {
233
fprintf(stderr, " InnoDB_Memcached: Invalid Cache"
234
" Policy %d. Reset to innodb_only\n",
236
opt_val = META_CACHE_OPT_INNODB;
240
case CACHE_POLICY_GET:
241
item->get_option = opt_val;
243
case CACHE_POLICY_SET:
244
item->set_option = opt_val;
246
case CACHE_POLICY_DEL:
247
item->del_option = opt_val;
249
case CACHE_POLICY_FLUSH:
250
item->flush_option = opt_val;
260
innodb_cb_cursor_close(crsr);
264
innodb_cb_tuple_delete(tpl);
267
innodb_cb_trx_commit(ib_trx);
268
ib_cb_trx_release(ib_trx);
270
return(err == DB_SUCCESS || err == DB_END_OF_INDEX);
273
/**********************************************************************//**
274
This function opens the config_options configuration table, and find the
275
table and column info that used for memcached data
276
@return true if everything works out fine */
279
innodb_read_config_option(
280
/*======================*/
281
meta_cfg_info_t* item) /*!< in: meta info structure */
284
ib_crsr_t crsr = NULL;
285
ib_crsr_t idx_crsr = NULL;
287
ib_err_t err = DB_SUCCESS;
291
ib_col_meta_t col_meta;
292
int current_option = -1;
294
ib_trx = ib_cb_trx_begin(IB_TRX_READ_COMMITTED, true, false);
295
err = innodb_api_begin(NULL, MCI_CFG_DB_NAME,
296
MCI_CFG_CONFIG_OPTIONS, NULL, ib_trx,
297
&crsr, &idx_crsr, IB_LOCK_S);
299
if (err != DB_SUCCESS) {
300
fprintf(stderr, " InnoDB_Memcached: Cannot open config table"
301
"'%s' in database '%s'\n",
302
MCI_CFG_CONFIG_OPTIONS, MCI_CFG_DB_NAME);
307
tpl = innodb_cb_read_tuple_create(crsr);
309
err = innodb_cb_cursor_first(crsr);
311
if (err != DB_SUCCESS) {
312
fprintf(stderr, " InnoDB_Memcached: failed to locate entry in"
313
" config table '%s' in database '%s' \n",
314
MCI_CFG_CONFIG_OPTIONS, MCI_CFG_DB_NAME);
321
err = ib_cb_read_row(crsr, tpl, NULL, NULL);
323
if (err != DB_SUCCESS) {
324
fprintf(stderr, " InnoDB_Memcached: failed to read"
325
" row from config table '%s' in"
327
MCI_CFG_CONFIG_OPTIONS, MCI_CFG_DB_NAME);
332
n_cols = innodb_cb_tuple_get_n_cols(tpl);
334
assert(n_cols >= CONFIG_OPT_NUM_COLS);
336
for (i = 0; i < CONFIG_OPT_NUM_COLS; ++i) {
339
data_len = innodb_cb_col_get_meta(tpl, i, &col_meta);
341
assert(data_len != IB_SQL_NULL);
343
if (i == CONFIG_OPT_KEY) {
345
key = (char*)innodb_cb_col_get_value(tpl, i);
348
for (j = 0; j < OPTION_ID_NUM_OPTIONS; j++) {
349
/* Currently, we only support one
350
configure option, that is the string
354
config_option_names[j].name)
357
config_option_names[j].id;
363
if (i == CONFIG_OPT_VALUE && current_option >= 0) {
366
/* The maximum length for delimiter is
368
max_len = (data_len > MAX_DELIMITER_LEN)
372
memcpy(item->options[current_option].value,
373
innodb_cb_col_get_value(tpl, i),
376
item->options[current_option].value[max_len]
379
item->options[current_option].value_len
384
err = ib_cb_cursor_next(crsr);
386
} while (err == DB_SUCCESS);
391
innodb_cb_cursor_close(crsr);
395
innodb_cb_tuple_delete(tpl);
398
innodb_cb_trx_commit(ib_trx);
399
ib_cb_trx_release(ib_trx);
401
return(err == DB_SUCCESS || err == DB_END_OF_INDEX);
404
/**********************************************************************//**
405
This function opens the "containers" configuration table, and find the
406
table and column info that used for memcached data, and instantiates
407
meta_cfg_info_t structure for such metadata.
408
@return instantiated configure info item if everything works out fine,
409
callers are responsible to free the memory returned by this function */
412
innodb_config_add_item(
413
/*===================*/
414
ib_tpl_t tpl, /*!< in: container row we are fetching
416
hash_table_t* eng_meta_hash) /*!< in/out: hash table to insert
419
ib_err_t err = DB_SUCCESS;
423
meta_cfg_info_t* item = NULL;
424
ib_col_meta_t col_meta;
427
n_cols = innodb_cb_tuple_get_n_cols(tpl);
429
if (n_cols < CONTAINER_NUM_COLS) {
430
fprintf(stderr, " InnoDB_Memcached: config table '%s' in"
431
" database '%s' has only %d column(s),"
432
" server is expecting %d columns\n",
433
MCI_CFG_CONTAINER_TABLE, MCI_CFG_DB_NAME,
434
n_cols, CONTAINER_NUM_COLS);
439
item = malloc(sizeof(*item));
441
memset(item, 0, sizeof(*item));
443
/* Get the column mappings (column for each memcached data */
444
for (i = 0; i < CONTAINER_NUM_COLS; ++i) {
446
data_len = innodb_cb_col_get_meta(tpl, i, &col_meta);
448
if (data_len == IB_SQL_NULL) {
449
fprintf(stderr, " InnoDB_Memcached: column %d in"
450
" the entry for config table '%s' in"
451
" database '%s' has an invalid"
453
i, MCI_CFG_CONTAINER_TABLE, MCI_CFG_DB_NAME);
459
item->col_info[i].col_name_len = data_len;
461
item->col_info[i].col_name = my_strdupl(
462
(char*)innodb_cb_col_get_value(tpl, i), data_len);
464
item->col_info[i].field_id = -1;
466
if (i == CONTAINER_VALUE) {
467
innodb_config_parse_value_col(
468
item, item->col_info[i].col_name, data_len);
472
/* Last column is about the unique index name on key column */
473
data_len = innodb_cb_col_get_meta(tpl, i, &col_meta);
475
if (data_len == IB_SQL_NULL) {
476
fprintf(stderr, " InnoDB_Memcached: There must be a unique"
477
" index on memcached table's key column\n");
482
item->index_info.idx_name = my_strdupl((char*)innodb_cb_col_get_value(
485
if (!innodb_verify(item)) {
490
fold = ut_fold_string(item->col_info[0].col_name);
491
HASH_INSERT(meta_cfg_info_t, name_hash, eng_meta_hash, fold, item);
494
if (err != DB_SUCCESS && item) {
502
/**********************************************************************//**
503
This function opens the "containers" table, reads in all rows and
504
instantiates the metadata hash table.
505
@return the default configuration setting (whose mapping name is "default") */
507
innodb_config_meta_hash_init(
508
/*=========================*/
509
hash_table_t* meta_hash) /*!< in/out: InnoDB Memcached engine */
512
ib_crsr_t crsr = NULL;
513
ib_crsr_t idx_crsr = NULL;
515
ib_err_t err = DB_SUCCESS;
516
meta_cfg_info_t* default_item = NULL;
518
ib_trx = ib_cb_trx_begin(IB_TRX_READ_COMMITTED, true, false);
519
err = innodb_api_begin(NULL, MCI_CFG_DB_NAME,
520
MCI_CFG_CONTAINER_TABLE, NULL, ib_trx,
521
&crsr, &idx_crsr, IB_LOCK_S);
523
if (err != DB_SUCCESS) {
524
fprintf(stderr, " InnoDB_Memcached: Please create config table"
525
"'%s' in database '%s' by running"
526
" 'innodb_memcached_config.sql. error %d'\n",
527
MCI_CFG_CONTAINER_TABLE, MCI_CFG_DB_NAME,
533
tpl = innodb_cb_read_tuple_create(crsr);
535
/* If name field is NULL, just read the first row */
536
err = innodb_cb_cursor_first(crsr);
538
while (err == DB_SUCCESS) {
539
meta_cfg_info_t* item;
541
err = ib_cb_read_row(crsr, tpl, NULL, NULL);
543
if (err != DB_SUCCESS) {
544
fprintf(stderr, " InnoDB_Memcached: failed to read row"
545
" from config table '%s' in database"
547
MCI_CFG_CONTAINER_TABLE, MCI_CFG_DB_NAME);
552
item = innodb_config_add_item(tpl, meta_hash);
554
/* First initialize default setting to be the first row
556
/* If there are any setting whose name is "default",
557
then set default_item to point to this setting, otherwise
558
point it to the first row of the table */
559
if (default_item == NULL
560
|| (item && strcmp(item->col_info[0].col_name,
565
err = ib_cb_cursor_next(crsr);
568
if (err == DB_END_OF_INDEX) {
572
if (err != DB_SUCCESS) {
573
fprintf(stderr, " InnoDB_Memcached: failed to locate entry in"
574
" config table '%s' in database '%s' \n",
575
MCI_CFG_CONTAINER_TABLE, MCI_CFG_DB_NAME);
582
innodb_cb_cursor_close(crsr);
586
innodb_cb_tuple_delete(tpl);
589
innodb_cb_trx_commit(ib_trx);
590
ib_cb_trx_release(ib_trx);
592
return(default_item);
595
/**********************************************************************//**
596
This function opens the "containers" configuration table, and find the
597
table and column info that used for memcached data
598
@return true if everything works out fine */
601
innodb_config_container(
602
/*====================*/
603
const char* name, /*!< in: option name to look for */
604
size_t name_len,/*!< in: option name length */
605
hash_table_t* meta_hash) /*!< in: engine hash table */
608
ib_crsr_t crsr = NULL;
609
ib_crsr_t idx_crsr = NULL;
611
ib_err_t err = DB_SUCCESS;
615
ib_col_meta_t col_meta;
616
ib_tpl_t read_tpl = NULL;
617
meta_cfg_info_t* item = NULL;
624
fold = ut_fold_string(name);
625
HASH_SEARCH(name_hash, meta_hash, fold,
626
meta_cfg_info_t*, item,
627
(name_len == item->col_info[0].col_name_len
628
&& strcmp(name, item->col_info[0].col_name) == 0));
635
ib_trx = ib_cb_trx_begin(IB_TRX_READ_COMMITTED, true, false);
636
err = innodb_api_begin(NULL, MCI_CFG_DB_NAME,
637
MCI_CFG_CONTAINER_TABLE, NULL, ib_trx,
638
&crsr, &idx_crsr, IB_LOCK_S);
640
if (err != DB_SUCCESS) {
641
fprintf(stderr, " InnoDB_Memcached: Please create config table"
642
"'%s' in database '%s' by running"
643
" 'innodb_memcached_config.sql. error %d'\n",
644
MCI_CFG_CONTAINER_TABLE, MCI_CFG_DB_NAME,
651
tpl = innodb_cb_read_tuple_create(crsr);
653
/* If name field is NULL, just read the first row */
654
err = innodb_cb_cursor_first(crsr);
656
/* User supplied a config option name, find it */
657
tpl = ib_cb_search_tuple_create(crsr);
659
err = ib_cb_col_set_value(tpl, 0, name, name_len, true);
661
ib_cb_cursor_set_match_mode(crsr, IB_EXACT_MATCH);
662
err = ib_cb_moveto(crsr, tpl, IB_CUR_GE);
665
if (err != DB_SUCCESS) {
666
fprintf(stderr, " InnoDB_Memcached: failed to locate entry in"
667
" config table '%s' in database '%s' \n",
668
MCI_CFG_CONTAINER_TABLE, MCI_CFG_DB_NAME);
675
err = ib_cb_read_row(crsr, tpl, NULL, NULL);
677
read_tpl = ib_cb_read_tuple_create(crsr);
679
err = ib_cb_read_row(crsr, read_tpl, NULL, NULL);
682
if (err != DB_SUCCESS) {
683
fprintf(stderr, " InnoDB_Memcached: failed to read row from"
684
" config table '%s' in database '%s' \n",
685
MCI_CFG_CONTAINER_TABLE, MCI_CFG_DB_NAME);
690
n_cols = innodb_cb_tuple_get_n_cols(read_tpl);
692
if (n_cols < CONTAINER_NUM_COLS) {
693
fprintf(stderr, " InnoDB_Memcached: config table '%s' in"
694
" database '%s' has only %d column(s),"
695
" server is expecting %d columns\n",
696
MCI_CFG_CONTAINER_TABLE, MCI_CFG_DB_NAME,
697
n_cols, CONTAINER_NUM_COLS);
702
item = malloc(sizeof(*item));
703
memset(item, 0, sizeof(*item));
705
/* Get the column mappings (column for each memcached data */
706
for (i = 0; i < CONTAINER_NUM_COLS; ++i) {
708
data_len = innodb_cb_col_get_meta(read_tpl, i, &col_meta);
710
if (data_len == IB_SQL_NULL) {
711
fprintf(stderr, " InnoDB_Memcached: column %d in"
712
" the entry for config table '%s' in"
713
" database '%s' has an invalid"
715
i, MCI_CFG_CONTAINER_TABLE, MCI_CFG_DB_NAME);
723
item->col_info[i].col_name_len = data_len;
725
item->col_info[i].col_name = my_strdupl(
726
(char*)innodb_cb_col_get_value(read_tpl, i), data_len);
728
item->col_info[i].field_id = -1;
730
if (i == CONTAINER_VALUE) {
731
innodb_config_parse_value_col(
732
item, item->col_info[i].col_name, data_len);
736
/* Last column is about the unique index name on key column */
737
data_len = innodb_cb_col_get_meta(read_tpl, i, &col_meta);
739
if (data_len == IB_SQL_NULL) {
740
fprintf(stderr, " InnoDB_Memcached: There must be a unique"
741
" index on memcached table's key column\n");
746
item->index_info.idx_name = my_strdupl((char*)innodb_cb_col_get_value(
747
read_tpl, i), data_len);
749
if (!innodb_verify(item)) {
756
innodb_cb_cursor_close(crsr);
760
innodb_cb_tuple_delete(tpl);
763
innodb_cb_trx_commit(ib_trx);
764
ib_cb_trx_release(ib_trx);
766
if (err != DB_SUCCESS) {
772
fold = ut_fold_string(item->col_info[0].col_name);
774
meta_cfg_info_t, name_hash, meta_hash, fold, item);
780
/**********************************************************************//**
781
This function verifies "value" column(s) specified by configure table are of
783
@return DB_SUCCESS if everything is verified */
786
innodb_config_value_col_verify(
787
/*===========================*/
788
char* name, /*!< in: column name */
789
meta_cfg_info_t*meta_info, /*!< in: meta info structure */
790
ib_col_meta_t* col_meta, /*!< in: column metadata */
791
int col_id, /*!< in: column ID */
792
meta_column_t* col_verify) /*!< in: verify structure */
794
ib_err_t err = DB_NOT_FOUND;
795
char table_name[MAX_TABLE_NAME_LEN + MAX_DATABASE_NAME_LEN];
799
/* Get table name. */
800
dbname = meta_info->col_info[CONTAINER_DB].col_name;
801
tname = meta_info->col_info[CONTAINER_TABLE].col_name;
803
sprintf(table_name, "%s\%s", dbname, tname);
805
snprintf(table_name, sizeof(table_name), "%s/%s", dbname, tname);
808
if (!meta_info->n_extra_col) {
809
meta_column_t* cinfo = meta_info->col_info;
811
/* "value" column must be of CHAR, VARCHAR or BLOB type */
812
if (strcmp(name, cinfo[CONTAINER_VALUE].col_name) == 0) {
813
if (col_meta->type != IB_VARCHAR
814
&& col_meta->type != IB_CHAR
815
&& col_meta->type != IB_BLOB
816
&& col_meta->type != IB_CHAR_ANYCHARSET
817
&& col_meta->type != IB_VARCHAR_ANYCHARSET
818
&& col_meta->type != IB_INT) {
820
" InnoDB_Memcached: the value"
821
" column %s in table %s"
822
" should be INTEGER, CHAR or"
825
err = DB_DATA_MISMATCH;
828
cinfo[CONTAINER_VALUE].field_id = col_id;
829
cinfo[CONTAINER_VALUE].col_meta = *col_meta;
835
for (i = 0; i < meta_info->n_extra_col; i++) {
837
meta_info->extra_col_info[i].col_name) == 0)
839
if (col_meta->type != IB_VARCHAR
840
&& col_meta->type != IB_CHAR
841
&& col_meta->type != IB_BLOB
842
&& col_meta->type != IB_CHAR_ANYCHARSET
843
&& col_meta->type != IB_VARCHAR_ANYCHARSET
844
&& col_meta->type != IB_INT) {
846
" InnoDB_Memcached: the value"
847
" column %s in table %s"
848
" should be INTEGER, CHAR or"
851
err = DB_DATA_MISMATCH;
855
meta_info->extra_col_info[i].field_id = col_id;
856
meta_info->extra_col_info[i].col_meta = *col_meta;
858
meta_info->col_info[CONTAINER_VALUE].field_id
860
meta_info->col_info[CONTAINER_VALUE].col_meta
864
col_verify[i].field_id = col_id;
876
/**********************************************************************//**
877
This function verifies the table configuration information on an opened
878
table, and fills in columns used for memcached functionalities (cas, exp etc.)
879
@return true if everything works out fine */
883
meta_cfg_info_t* info, /*!< in/out: meta info structure */
884
ib_crsr_t crsr, /*!< in: crsr */
885
bool runtime)/*!< in: verify at the runtime */
887
ib_crsr_t idx_crsr = NULL;
889
ib_col_meta_t col_meta;
892
bool is_key_col = false;
893
bool is_value_col = false;
894
bool is_flag_col = false;
895
bool is_cas_col = false;
896
bool is_exp_col = false;
898
ib_id_u64_t index_id;
899
ib_err_t err = DB_SUCCESS;
901
meta_column_t* cinfo = info->col_info;
902
meta_column_t* col_verify = NULL;
903
char table_name[MAX_TABLE_NAME_LEN + MAX_DATABASE_NAME_LEN];
907
tpl = innodb_cb_read_tuple_create(crsr);
909
if (runtime && info->n_extra_col) {
910
col_verify = malloc(info->n_extra_col * sizeof(meta_column_t));
916
for (i = 0; i < info->n_extra_col; i++) {
917
col_verify[i].field_id = -1;
921
/* Get table name. */
922
dbname = info->col_info[CONTAINER_DB].col_name;
923
tname = info->col_info[CONTAINER_TABLE].col_name;
925
sprintf(table_name, "%s\%s", dbname, tname);
927
snprintf(table_name, sizeof(table_name), "%s/%s", dbname, tname);
930
n_cols = innodb_cb_tuple_get_n_cols(tpl);
932
/* Verify each mapped column */
933
for (i = 0; i < n_cols; i++) {
934
ib_err_t result = DB_SUCCESS;
936
name = innodb_cb_col_get_name(crsr, i);
937
innodb_cb_col_get_meta(tpl, i, &col_meta);
939
result = innodb_config_value_col_verify(
940
name, info, &col_meta, i, col_verify);
942
if (result == DB_SUCCESS) {
945
if (strcmp(name, cinfo[CONTAINER_KEY].col_name)) {
948
} else if (result == DB_DATA_MISMATCH) {
949
err = DB_DATA_MISMATCH;
953
if (strcmp(name, cinfo[CONTAINER_KEY].col_name) == 0) {
954
/* Key column must be CHAR or VARCHAR type */
955
if (col_meta.type != IB_VARCHAR
956
&& col_meta.type != IB_CHAR
957
&& col_meta.type != IB_VARCHAR_ANYCHARSET
958
&& col_meta.type != IB_CHAR_ANYCHARSET
959
&& col_meta.type != IB_INT) {
961
" InnoDB_Memcached: the key"
962
" column %s in table %s should"
963
" be INTEGER, CHAR or VARCHAR.\n",
965
err = DB_DATA_MISMATCH;
968
cinfo[CONTAINER_KEY].field_id = i;
969
cinfo[CONTAINER_KEY].col_meta = col_meta;
971
} else if (strcmp(name, cinfo[CONTAINER_FLAG].col_name) == 0) {
972
/* Flag column must be integer type */
973
if (col_meta.type != IB_INT) {
974
fprintf(stderr, " InnoDB_Memcached: the flag"
975
" column %s in table %s should"
978
err = DB_DATA_MISMATCH;
981
cinfo[CONTAINER_FLAG].field_id = i;
982
cinfo[CONTAINER_FLAG].col_meta = col_meta;
983
info->flag_enabled = true;
985
} else if (strcmp(name, cinfo[CONTAINER_CAS].col_name) == 0) {
986
/* CAS column must be integer type */
987
if (col_meta.type != IB_INT) {
988
fprintf(stderr, " InnoDB_Memcached: the cas"
989
" column %s in table %s should"
992
err = DB_DATA_MISMATCH;
995
cinfo[CONTAINER_CAS].field_id = i;
996
cinfo[CONTAINER_CAS].col_meta = col_meta;
997
info->cas_enabled = true;
999
} else if (strcmp(name, cinfo[CONTAINER_EXP].col_name) == 0) {
1000
/* EXP column must be integer type */
1001
if (col_meta.type != IB_INT) {
1002
fprintf(stderr, " InnoDB_Memcached: the expire"
1003
" column %s in table %s should"
1006
err = DB_DATA_MISMATCH;
1009
cinfo[CONTAINER_EXP].field_id = i;
1010
cinfo[CONTAINER_EXP].col_meta = col_meta;
1011
info->exp_enabled = true;
1016
/* Key column and Value column must present */
1017
if (!is_key_col || !is_value_col) {
1018
fprintf(stderr, " InnoDB_Memcached: failed to locate key"
1019
" column or value column in table"
1020
" as specified by config table \n");
1026
if (info->n_extra_col) {
1027
meta_column_t* col_check;
1029
col_check = (runtime && col_verify)
1031
: info->extra_col_info;
1033
for (i = 0; i < info->n_extra_col; i++) {
1034
if (col_check[i].field_id < 0) {
1035
fprintf(stderr, " InnoDB_Memcached: failed to"
1036
" locate value column %s"
1037
" as specified by config"
1039
info->extra_col_info[i].col_name);
1046
if (info->flag_enabled && !is_flag_col) {
1047
fprintf(stderr, " InnoDB_Memcached: failed to locate flag"
1048
" column as specified by config table \n");
1053
if (info->cas_enabled && !is_cas_col) {
1054
fprintf(stderr, " InnoDB_Memcached: failed to locate cas"
1055
" column as specified by config table \n");
1060
if (info->exp_enabled && !is_exp_col) {
1061
fprintf(stderr, " InnoDB_Memcached: failed to locate exp"
1062
" column as specified by config table \n");
1067
/* Test the specified index */
1068
innodb_cb_cursor_open_index_using_name(crsr, info->index_info.idx_name,
1069
&idx_crsr, &index_type,
1072
if (index_type & IB_CLUSTERED) {
1073
info->index_info.srch_use_idx = META_USE_CLUSTER;
1074
} else if (!idx_crsr || !(index_type & IB_UNIQUE)) {
1075
fprintf(stderr, " InnoDB_Memcached: Index on key column"
1076
" must be a Unique index\n");
1077
info->index_info.srch_use_idx = META_USE_NO_INDEX;
1080
info->index_info.idx_id = index_id;
1081
info->index_info.srch_use_idx = META_USE_SECONDARY;
1085
ib_tpl_t idx_tpl = NULL;
1086
if (index_type & IB_CLUSTERED) {
1087
idx_tpl = innodb_cb_read_tuple_create(idx_crsr);
1089
idx_tpl = ib_cb_search_tuple_create(idx_crsr);
1092
n_cols = ib_cb_get_n_user_cols(idx_tpl);
1094
name = ib_cb_get_idx_field_name(idx_crsr, 0);
1096
if (strcmp(name, cinfo[CONTAINER_KEY].col_name)) {
1097
fprintf(stderr, " InnoDB_Memcached: Index used"
1098
" must be on key column only\n");
1102
if (!(index_type & IB_CLUSTERED) && n_cols > 1) {
1103
fprintf(stderr, " InnoDB_Memcached: Index used"
1104
" must be on key column only\n");
1108
innodb_cb_tuple_delete(idx_tpl);
1109
innodb_cb_cursor_close(idx_crsr);
1113
if (runtime && col_verify) {
1118
innodb_cb_tuple_delete(tpl);
1124
/**********************************************************************//**
1125
This function verifies the table configuration information, and fills
1126
in columns used for memcached functionalities (cas, exp etc.)
1127
@return true if everything works out fine */
1131
meta_cfg_info_t* info) /*!< in: meta info structure */
1133
ib_crsr_t crsr = NULL;
1134
char table_name[MAX_TABLE_NAME_LEN + MAX_DATABASE_NAME_LEN];
1137
ib_err_t err = DB_SUCCESS;
1139
dbname = info->col_info[CONTAINER_DB].col_name;
1140
name = info->col_info[CONTAINER_TABLE].col_name;
1141
info->flag_enabled = false;
1142
info->cas_enabled = false;
1143
info->exp_enabled = false;
1146
sprintf(table_name, "%s\%s", dbname, name);
1148
snprintf(table_name, sizeof(table_name), "%s/%s", dbname, name);
1151
err = innodb_cb_open_table(table_name, NULL, &crsr);
1153
/* Mapped InnoDB table must be able to open */
1154
if (err != DB_SUCCESS) {
1155
fprintf(stderr, " InnoDB_Memcached: failed to open table"
1156
" '%s' \n", table_name);
1161
err = innodb_verify_low(info, crsr, false);
1164
innodb_cb_cursor_close(crsr);
1167
return(err == DB_SUCCESS);
1170
/**********************************************************************//**
1171
If the hash table (meta_hash) is NULL, then initialise the hash table with
1172
data in the configure tables. And return the "default" item. If there is
1173
no setting named "default" then use the first row in the table. This is
1174
currently only used at the engine initialization time.
1175
If the hash table (meta_hash) is created, then look for the meta-data based on
1176
specified configuration name parameter. If such metadata does not exist in
1177
the hash table, then add such metadata into hash table.
1178
@return meta_cfg_info_t* structure if configure option found, otherwise NULL */
1182
const char* name, /*!< in: config option name */
1183
size_t name_len, /*!< in: name length */
1184
hash_table_t** meta_hash) /*!< in/out: engine hash
1185
table. If NULL, it will be
1186
created and initialized */
1188
meta_cfg_info_t* item;
1191
if (*meta_hash == NULL) {
1192
*meta_hash = hash_create(100);
1196
item = innodb_config_meta_hash_init(*meta_hash);
1200
fold = ut_fold_string(name);
1201
HASH_SEARCH(name_hash, *meta_hash, fold,
1202
meta_cfg_info_t*, item,
1203
(name_len == item->col_info[0].col_name_len
1204
&& strcmp(name, item->col_info[0].col_name) == 0));
1210
item = innodb_config_container(name, name_len, *meta_hash);
1217
/* Following two configure operations are optional, and can be
1219
success = innodb_read_cache_policy(item);
1225
success = innodb_read_config_option(item);