MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
innodb_config.c
Go to the documentation of this file.
1 /***********************************************************************
2 
3 Copyright (c) 2013, Oracle and/or its affiliates. All Rights Reserved.
4 
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.
8 
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.
13 
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
17 
18 ***********************************************************************/
19 
20 /**************************************************/
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include <errno.h>
31 
32 #include "innodb_api.h"
33 #include "innodb_config.h"
34 #include "innodb_cb_api.h"
35 #include "innodb_utility.h"
36 
39 {
41  {OPTION_ID_TBL_MAP_SEP, TABLE_MAP_SEPARATOR, {".", 1}}
42 };
43 
44 /**********************************************************************/
47 static
48 char*
49 my_strdupl(
50 /*=======*/
51  const char* str,
52  int len)
53 {
54  char* s = (char*) malloc(len + 1);
55 
56  if (!s) {
57  return(NULL);
58  }
59 
60  s[len] = 0;
61 
62  return((char*) memcpy(s, str, len));
63 }
64 
65 /**********************************************************************/
67 void
69 /*===============*/
70  meta_cfg_info_t* item)
71 {
72  int i;
73 
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;
78  }
79  }
80 
81  if (item->index_info.idx_name) {
82  free(item->index_info.idx_name);
83  item->index_info.idx_name = NULL;
84  }
85 
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;
90  }
91 
92  free(item->extra_col_info);
93  item->extra_col_info = NULL;
94  }
95 }
96 
97 /**********************************************************************/
101 static
102 bool
103 innodb_config_parse_value_col(
104 /*==========================*/
105  meta_cfg_info_t*item,
106  char* str,
107  int len)
108 {
109  static const char* sep = " ;,|\n";
110  char* last;
111  char* column_str;
112  int num_cols = 0;
113  char* my_str = my_strdupl(str, len);
114 
115  /* Find out how many column names in the string */
116  for (column_str = strtok_r(my_str, sep, &last);
117  column_str;
118  column_str = strtok_r(NULL, sep, &last)) {
119  num_cols++;
120  }
121 
122  free(my_str);
123 
124  my_str = str;
125 
126  if (num_cols > 1) {
127  int i = 0;
128  item->extra_col_info = malloc(
129  num_cols * sizeof(*item->extra_col_info));
130 
131  if (!item->extra_col_info) {
132  return(false);
133  }
134 
135  for (column_str = strtok_r(my_str, sep, &last);
136  column_str;
137  column_str = strtok_r(NULL, sep, &last)) {
138  item->extra_col_info[i].col_name_len = strlen(
139  column_str);
140  item->extra_col_info[i].col_name = my_strdupl(
141  column_str,
142  item->extra_col_info[i].col_name_len);
143  item->extra_col_info[i].field_id = -1;
144  i++;
145  }
146 
147  item->n_extra_col = num_cols;
148  } else {
149  item->extra_col_info = NULL;
150  item->n_extra_col = 0;
151  }
152 
153  return(true);
154 }
155 
156 /**********************************************************************/
160 static
161 bool
162 innodb_read_cache_policy(
163 /*=====================*/
164  meta_cfg_info_t* item)
165 {
166  ib_trx_t ib_trx;
167  ib_crsr_t crsr = NULL;
168  ib_crsr_t idx_crsr = NULL;
169  ib_tpl_t tpl = NULL;
170  ib_err_t err = DB_SUCCESS;
171  int n_cols;
172  int i;
173  ib_ulint_t data_len;
174  ib_col_meta_t col_meta;
175 
177 
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);
181 
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,
186  err);
187  err = DB_ERROR;
188  goto func_exit;
189  }
190 
191  tpl = innodb_cb_read_tuple_create(crsr);
192 
193  /* Currently, we support one table per memcached setup.
194  We could extend that limit later */
195  err = innodb_cb_cursor_first(crsr);
196 
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);
201  err = DB_ERROR;
202  goto func_exit;
203  }
204 
205  err = innodb_cb_read_row(crsr, tpl);
206 
207  n_cols = innodb_cb_tuple_get_n_cols(tpl);
208 
209  assert(n_cols >= CACHE_POLICY_NUM_COLS);
210 
211  for (i = 0; i < CACHE_POLICY_NUM_COLS; ++i) {
212  char opt_name;
213  meta_cache_opt_t opt_val;
214 
215  /* Skip cache policy name for now, We could have
216  different cache policy stored, and switch dynamically */
217  if (i == CACHE_POLICY_NAME) {
218  continue;
219  }
220 
221  data_len = innodb_cb_col_get_meta(tpl, i, &col_meta);
222 
223  if (data_len == IB_SQL_NULL) {
224  opt_val = META_CACHE_OPT_INNODB;
225  } else {
226  opt_name = *(char*)innodb_cb_col_get_value(tpl, i);
227 
228  opt_val = (meta_cache_opt_t) opt_name;
229  }
230 
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",
235  (int) opt_val);
236  opt_val = META_CACHE_OPT_INNODB;
237  }
238 
239  switch (i) {
240  case CACHE_POLICY_GET:
241  item->get_option = opt_val;
242  break;
243  case CACHE_POLICY_SET:
244  item->set_option = opt_val;
245  break;
246  case CACHE_POLICY_DEL:
247  item->del_option = opt_val;
248  break;
249  case CACHE_POLICY_FLUSH:
250  item->flush_option = opt_val;
251  break;
252  default:
253  assert(0);
254  }
255  }
256 
257 func_exit:
258 
259  if (crsr) {
261  }
262 
263  if (tpl) {
265  }
266 
267  innodb_cb_trx_commit(ib_trx);
268 
269  return(err == DB_SUCCESS || err == DB_END_OF_INDEX);
270 }
271 
272 /**********************************************************************/
276 static
277 bool
278 innodb_read_config_option(
279 /*======================*/
280  meta_cfg_info_t* item)
281 {
282  ib_trx_t ib_trx;
283  ib_crsr_t crsr = NULL;
284  ib_crsr_t idx_crsr = NULL;
285  ib_tpl_t tpl = NULL;
286  ib_err_t err = DB_SUCCESS;
287  int n_cols;
288  int i;
289  ib_ulint_t data_len;
290  ib_col_meta_t col_meta;
291  int current_option = -1;
292 
294  err = innodb_api_begin(NULL, MCI_CFG_DB_NAME,
295  MCI_CFG_CONFIG_OPTIONS, NULL, ib_trx,
296  &crsr, &idx_crsr, IB_LOCK_S);
297 
298  if (err != DB_SUCCESS) {
299  fprintf(stderr, " InnoDB_Memcached: Cannot open config table"
300  "'%s' in database '%s'\n",
301  MCI_CFG_CONFIG_OPTIONS, MCI_CFG_DB_NAME);
302  err = DB_ERROR;
303  goto func_exit;
304  }
305 
306  tpl = innodb_cb_read_tuple_create(crsr);
307 
308  err = innodb_cb_cursor_first(crsr);
309 
310  if (err != DB_SUCCESS) {
311  fprintf(stderr, " InnoDB_Memcached: failed to locate entry in"
312  " config table '%s' in database '%s' \n",
313  MCI_CFG_CONFIG_OPTIONS, MCI_CFG_DB_NAME);
314  err = DB_ERROR;
315  goto func_exit;
316  }
317 
318 
319  do {
320  err = innodb_cb_read_row(crsr, tpl);
321 
322  if (err != DB_SUCCESS) {
323  fprintf(stderr, " InnoDB_Memcached: failed to read"
324  " row from config table '%s' in"
325  " database '%s' \n",
326  MCI_CFG_CONFIG_OPTIONS, MCI_CFG_DB_NAME);
327  err = DB_ERROR;
328  goto func_exit;
329  }
330 
331  n_cols = innodb_cb_tuple_get_n_cols(tpl);
332 
333  assert(n_cols >= CONFIG_OPT_NUM_COLS);
334 
335  for (i = 0; i < CONFIG_OPT_NUM_COLS; ++i) {
336  char* key;
337 
338  data_len = innodb_cb_col_get_meta(tpl, i, &col_meta);
339 
340  assert(data_len != IB_SQL_NULL);
341 
342  if (i == CONFIG_OPT_KEY) {
343  int j;
344  key = (char*)innodb_cb_col_get_value(tpl, i);
345  current_option = -1;
346 
347  for (j = 0; j < OPTION_ID_NUM_OPTIONS; j++) {
348  /* Currently, we only support one
349  configure option, that is the string
350  "separator" */
351  if (strcmp(
352  key,
353  config_option_names[j].name)
354  == 0) {
355  current_option =
356  config_option_names[j].id;
357  break;
358  }
359  }
360  }
361 
362  if (i == CONFIG_OPT_VALUE && current_option >= 0) {
363  int max_len;
364 
365  /* The maximum length for delimiter is
366  MAX_DELIMITER_LEN */
367  max_len = (data_len > MAX_DELIMITER_LEN)
369  : data_len;
370 
371  memcpy(item->options[current_option].value,
372  innodb_cb_col_get_value(tpl, i),
373  max_len);
374 
375  item->options[current_option].value[max_len]
376  = 0;
377 
378  item->options[current_option].value_len
379  = max_len;
380  }
381  }
382 
383  err = ib_cb_cursor_next(crsr);
384 
385  } while (err == DB_SUCCESS);
386 
387 func_exit:
388 
389  if (crsr) {
391  }
392 
393  if (tpl) {
395  }
396 
397  innodb_cb_trx_commit(ib_trx);
398 
399  return(err == DB_SUCCESS || err == DB_END_OF_INDEX);
400 }
401 
402 /**********************************************************************/
408 static
410 innodb_config_add_item(
411 /*===================*/
412  ib_tpl_t tpl,
414  hash_table_t* eng_meta_hash)
416 {
417  ib_err_t err = DB_SUCCESS;
418  int n_cols;
419  int i;
420  ib_ulint_t data_len;
421  meta_cfg_info_t* item = NULL;
422  ib_col_meta_t col_meta;
423  int fold;
424 
425  n_cols = innodb_cb_tuple_get_n_cols(tpl);
426 
427  if (n_cols < CONTAINER_NUM_COLS) {
428  fprintf(stderr, " InnoDB_Memcached: config table '%s' in"
429  " database '%s' has only %d column(s),"
430  " server is expecting %d columns\n",
431  MCI_CFG_CONTAINER_TABLE, MCI_CFG_DB_NAME,
432  n_cols, CONTAINER_NUM_COLS);
433  err = DB_ERROR;
434  goto func_exit;
435  }
436 
437  item = malloc(sizeof(*item));
438 
439  memset(item, 0, sizeof(*item));
440 
441  /* Get the column mappings (column for each memcached data */
442  for (i = 0; i < CONTAINER_NUM_COLS; ++i) {
443 
444  data_len = innodb_cb_col_get_meta(tpl, i, &col_meta);
445 
446  if (data_len == IB_SQL_NULL) {
447  fprintf(stderr, " InnoDB_Memcached: column %d in"
448  " the entry for config table '%s' in"
449  " database '%s' has an invalid"
450  " NULL value\n",
451  i, MCI_CFG_CONTAINER_TABLE, MCI_CFG_DB_NAME);
452 
453  err = DB_ERROR;
454  goto func_exit;
455  }
456 
457  item->col_info[i].col_name_len = data_len;
458 
459  item->col_info[i].col_name = my_strdupl(
460  (char*)innodb_cb_col_get_value(tpl, i), data_len);
461 
462  item->col_info[i].field_id = -1;
463 
464  if (i == CONTAINER_VALUE) {
465  innodb_config_parse_value_col(
466  item, item->col_info[i].col_name, data_len);
467  }
468  }
469 
470  /* Last column is about the unique index name on key column */
471  data_len = innodb_cb_col_get_meta(tpl, i, &col_meta);
472 
473  if (data_len == IB_SQL_NULL) {
474  fprintf(stderr, " InnoDB_Memcached: There must be a unique"
475  " index on memcached table's key column\n");
476  err = DB_ERROR;
477  goto func_exit;
478  }
479 
480  item->index_info.idx_name = my_strdupl((char*)innodb_cb_col_get_value(
481  tpl, i), data_len);
482 
483  if (!innodb_verify(item)) {
484  err = DB_ERROR;
485  goto func_exit;
486  }
487 
488  fold = ut_fold_string(item->col_info[0].col_name);
489  HASH_INSERT(meta_cfg_info_t, name_hash, eng_meta_hash, fold, item);
490 
491 func_exit:
492  if (err != DB_SUCCESS && item) {
493  free(item);
494  item = NULL;
495  }
496 
497  return(item);
498 }
499 
500 /**********************************************************************/
506 /*=========================*/
507  hash_table_t* meta_hash)
508 {
509  ib_trx_t ib_trx;
510  ib_crsr_t crsr = NULL;
511  ib_crsr_t idx_crsr = NULL;
512  ib_tpl_t tpl = NULL;
513  ib_err_t err = DB_SUCCESS;
514  meta_cfg_info_t* default_item = NULL;
515 
517  err = innodb_api_begin(NULL, MCI_CFG_DB_NAME,
518  MCI_CFG_CONTAINER_TABLE, NULL, ib_trx,
519  &crsr, &idx_crsr, IB_LOCK_S);
520 
521  if (err != DB_SUCCESS) {
522  fprintf(stderr, " InnoDB_Memcached: Please create config table"
523  "'%s' in database '%s' by running"
524  " 'scripts/innodb_config.sql. error %d'\n",
525  MCI_CFG_CONTAINER_TABLE, MCI_CFG_DB_NAME,
526  err);
527  err = DB_ERROR;
528  goto func_exit;
529  }
530 
531  tpl = innodb_cb_read_tuple_create(crsr);
532 
533  /* If name field is NULL, just read the first row */
534  err = innodb_cb_cursor_first(crsr);
535 
536  while (err == DB_SUCCESS) {
537  meta_cfg_info_t* item;
538 
539  err = innodb_cb_read_row(crsr, tpl);
540 
541  if (err != DB_SUCCESS) {
542  fprintf(stderr, " InnoDB_Memcached: failed to read row"
543  " from config table '%s' in database"
544  " '%s' \n",
545  MCI_CFG_CONTAINER_TABLE, MCI_CFG_DB_NAME);
546  err = DB_ERROR;
547  goto func_exit;
548  }
549 
550  item = innodb_config_add_item(tpl, meta_hash);
551 
552  /* First initialize default setting to be the first row
553  of the table */
554  /* If there are any setting whose name is "default",
555  then set default_item to point to this setting, otherwise
556  point it to the first row of the table */
557  if (default_item == NULL
558  || (item && strcmp(item->col_info[0].col_name,
559  "default") == 0)) {
560  default_item = item;
561  }
562 
563  err = ib_cb_cursor_next(crsr);
564  }
565 
566  if (err == DB_END_OF_INDEX) {
567  err = DB_SUCCESS;
568  }
569 
570  if (err != DB_SUCCESS) {
571  fprintf(stderr, " InnoDB_Memcached: failed to locate entry in"
572  " config table '%s' in database '%s' \n",
573  MCI_CFG_CONTAINER_TABLE, MCI_CFG_DB_NAME);
574  err = DB_ERROR;
575  }
576 
577 func_exit:
578 
579  if (crsr) {
581  }
582 
583  if (tpl) {
585  }
586 
587  innodb_cb_trx_commit(ib_trx);
588 
589  return(default_item);
590 }
591 
592 /**********************************************************************/
596 static
598 innodb_config_container(
599 /*====================*/
600  const char* name,
601  size_t name_len,
602  hash_table_t* meta_hash)
603 {
604  ib_trx_t ib_trx;
605  ib_crsr_t crsr = NULL;
606  ib_crsr_t idx_crsr = NULL;
607  ib_tpl_t tpl = NULL;
608  ib_err_t err = DB_SUCCESS;
609  int n_cols;
610  int i;
611  ib_ulint_t data_len;
612  ib_col_meta_t col_meta;
613  ib_tpl_t read_tpl = NULL;
614  meta_cfg_info_t* item = NULL;
615 
616  if (name != NULL) {
618 
619  assert(meta_hash);
620 
621  fold = ut_fold_string(name);
622  HASH_SEARCH(name_hash, meta_hash, fold,
623  meta_cfg_info_t*, item,
624  (name_len == item->col_info[0].col_name_len
625  && strcmp(name, item->col_info[0].col_name) == 0));
626 
627  if (item) {
628  return(item);
629  }
630  }
631 
633  err = innodb_api_begin(NULL, MCI_CFG_DB_NAME,
634  MCI_CFG_CONTAINER_TABLE, NULL, ib_trx,
635  &crsr, &idx_crsr, IB_LOCK_S);
636 
637  if (err != DB_SUCCESS) {
638  fprintf(stderr, " InnoDB_Memcached: Please create config table"
639  "'%s' in database '%s' by running"
640  " 'scripts/innodb_config.sql. error %d'\n",
641  MCI_CFG_CONTAINER_TABLE, MCI_CFG_DB_NAME,
642  err);
643  err = DB_ERROR;
644  goto func_exit;
645  }
646 
647  if (!name) {
648  tpl = innodb_cb_read_tuple_create(crsr);
649 
650  /* If name field is NULL, just read the first row */
651  err = innodb_cb_cursor_first(crsr);
652  } else {
653  /* User supplied a config option name, find it */
654  tpl = ib_cb_search_tuple_create(crsr);
655 
656  err = ib_cb_col_set_value(tpl, 0, name, name_len, true);
657 
658  ib_cb_cursor_set_match_mode(crsr, IB_EXACT_MATCH);
659  err = ib_cb_moveto(crsr, tpl, IB_CUR_GE);
660  }
661 
662  if (err != DB_SUCCESS) {
663  fprintf(stderr, " InnoDB_Memcached: failed to locate entry in"
664  " config table '%s' in database '%s' \n",
665  MCI_CFG_CONTAINER_TABLE, MCI_CFG_DB_NAME);
666  err = DB_ERROR;
667  goto func_exit;
668  }
669 
670  if (!name) {
671  read_tpl = tpl;
672  err = innodb_cb_read_row(crsr, tpl);
673  } else {
674  read_tpl = ib_cb_read_tuple_create(crsr);
675 
676  err = ib_cb_read_row(crsr, read_tpl);
677  }
678 
679  if (err != DB_SUCCESS) {
680  fprintf(stderr, " InnoDB_Memcached: failed to read row from"
681  " config table '%s' in database '%s' \n",
682  MCI_CFG_CONTAINER_TABLE, MCI_CFG_DB_NAME);
683  err = DB_ERROR;
684  goto func_exit;
685  }
686 
687  n_cols = innodb_cb_tuple_get_n_cols(read_tpl);
688 
689  if (n_cols < CONTAINER_NUM_COLS) {
690  fprintf(stderr, " InnoDB_Memcached: config table '%s' in"
691  " database '%s' has only %d column(s),"
692  " server is expecting %d columns\n",
693  MCI_CFG_CONTAINER_TABLE, MCI_CFG_DB_NAME,
694  n_cols, CONTAINER_NUM_COLS);
695  err = DB_ERROR;
696  goto func_exit;
697  }
698 
699  item = malloc(sizeof(*item));
700  memset(item, 0, sizeof(*item));
701 
702  /* Get the column mappings (column for each memcached data */
703  for (i = 0; i < CONTAINER_NUM_COLS; ++i) {
704 
705  data_len = innodb_cb_col_get_meta(read_tpl, i, &col_meta);
706 
707  if (data_len == IB_SQL_NULL) {
708  fprintf(stderr, " InnoDB_Memcached: column %d in"
709  " the entry for config table '%s' in"
710  " database '%s' has an invalid"
711  " NULL value\n",
712  i, MCI_CFG_CONTAINER_TABLE, MCI_CFG_DB_NAME);
713 
714  err = DB_ERROR;
715  goto func_exit;
716 
717 
718  }
719 
720  item->col_info[i].col_name_len = data_len;
721 
722  item->col_info[i].col_name = my_strdupl(
723  (char*)innodb_cb_col_get_value(read_tpl, i), data_len);
724 
725  item->col_info[i].field_id = -1;
726 
727  if (i == CONTAINER_VALUE) {
728  innodb_config_parse_value_col(
729  item, item->col_info[i].col_name, data_len);
730  }
731  }
732 
733  /* Last column is about the unique index name on key column */
734  data_len = innodb_cb_col_get_meta(read_tpl, i, &col_meta);
735 
736  if (data_len == IB_SQL_NULL) {
737  fprintf(stderr, " InnoDB_Memcached: There must be a unique"
738  " index on memcached table's key column\n");
739  err = DB_ERROR;
740  goto func_exit;
741  }
742 
743  item->index_info.idx_name = my_strdupl((char*)innodb_cb_col_get_value(
744  read_tpl, i), data_len);
745 
746  if (!innodb_verify(item)) {
747  err = DB_ERROR;
748  }
749 
750 func_exit:
751 
752  if (crsr) {
754  }
755 
756  if (tpl) {
758  }
759 
760  innodb_cb_trx_commit(ib_trx);
761 
762  if (err != DB_SUCCESS) {
763  free(item);
764  item = NULL;
765  } else {
767 
768  fold = ut_fold_string(item->col_info[0].col_name);
769  HASH_INSERT(
770  meta_cfg_info_t, name_hash, meta_hash, fold, item);
771  }
772 
773  return(item);
774 }
775 
776 /**********************************************************************/
780 static
781 ib_err_t
782 innodb_config_value_col_verify(
783 /*===========================*/
784  char* name,
785  meta_cfg_info_t*meta_info,
786  ib_col_meta_t* col_meta,
787  int col_id,
788  meta_column_t* col_verify)
789 {
790  ib_err_t err = DB_NOT_FOUND;
791  char table_name[MAX_TABLE_NAME_LEN + MAX_DATABASE_NAME_LEN];
792  char* dbname;
793  char* tname;
794 
795  /* Get table name. */
796  dbname = meta_info->col_info[CONTAINER_DB].col_name;
797  tname = meta_info->col_info[CONTAINER_TABLE].col_name;
798 #ifdef __WIN__
799  sprintf(table_name, "%s\%s", dbname, tname);
800 #else
801  snprintf(table_name, sizeof(table_name), "%s/%s", dbname, tname);
802 #endif
803 
804  if (!meta_info->n_extra_col) {
805  meta_column_t* cinfo = meta_info->col_info;
806 
807  /* "value" column must be of CHAR, VARCHAR or BLOB type */
808  if (strcmp(name, cinfo[CONTAINER_VALUE].col_name) == 0) {
809  if (col_meta->type != IB_VARCHAR
810  && col_meta->type != IB_CHAR
811  && col_meta->type != IB_BLOB
812  && col_meta->type != IB_CHAR_ANYCHARSET
813  && col_meta->type != IB_VARCHAR_ANYCHARSET
814  && col_meta->type != IB_INT) {
815  fprintf(stderr,
816  " InnoDB_Memcached: the value"
817  " column %s in table %s"
818  " should be INTEGER, CHAR or"
819  " VARCHAR.\n",
820  name, table_name);
821  err = DB_DATA_MISMATCH;
822  }
823 
824  cinfo[CONTAINER_VALUE].field_id = col_id;
825  cinfo[CONTAINER_VALUE].col_meta = *col_meta;
826  err = DB_SUCCESS;
827  }
828  } else {
829  int i;
830 
831  for (i = 0; i < meta_info->n_extra_col; i++) {
832  if (strcmp(name,
833  meta_info->extra_col_info[i].col_name) == 0)
834  {
835  if (col_meta->type != IB_VARCHAR
836  && col_meta->type != IB_CHAR
837  && col_meta->type != IB_BLOB
838  && col_meta->type != IB_CHAR_ANYCHARSET
839  && col_meta->type != IB_VARCHAR_ANYCHARSET
840  && col_meta->type != IB_INT) {
841  fprintf(stderr,
842  " InnoDB_Memcached: the value"
843  " column %s in table %s"
844  " should be INTEGER, CHAR or"
845  " VARCHAR.\n",
846  name, table_name);
847  err = DB_DATA_MISMATCH;
848  break;
849  }
850 
851  meta_info->extra_col_info[i].field_id = col_id;
852  meta_info->extra_col_info[i].col_meta = *col_meta;
853 
854  meta_info->col_info[CONTAINER_VALUE].field_id
855  = col_id;
856  meta_info->col_info[CONTAINER_VALUE].col_meta
857  = *col_meta;
858 
859  if (col_verify) {
860  col_verify[i].field_id = col_id;
861  }
862 
863  err = DB_SUCCESS;
864  }
865  }
866 
867  }
868 
869  return(err);
870 }
871 
872 /**********************************************************************/
876 ib_err_t
878 /*==============*/
879  meta_cfg_info_t* info,
880  ib_crsr_t crsr,
881  bool runtime)
882 {
883  ib_crsr_t idx_crsr = NULL;
884  ib_tpl_t tpl = NULL;
885  ib_col_meta_t col_meta;
886  int n_cols;
887  int i;
888  bool is_key_col = false;
889  bool is_value_col = false;
890  bool is_flag_col = false;
891  bool is_cas_col = false;
892  bool is_exp_col = false;
893  int index_type;
894  ib_id_u64_t index_id;
895  ib_err_t err = DB_SUCCESS;
896  char* name;
897  meta_column_t* cinfo = info->col_info;
898  meta_column_t* col_verify = NULL;
899  char table_name[MAX_TABLE_NAME_LEN + MAX_DATABASE_NAME_LEN];
900  char* dbname;
901  char* tname;
902 
903  tpl = innodb_cb_read_tuple_create(crsr);
904 
905  if (runtime && info->n_extra_col) {
906  col_verify = malloc(info->n_extra_col * sizeof(meta_column_t));
907 
908  if (!col_verify) {
909  return(false);
910  }
911 
912  for (i = 0; i < info->n_extra_col; i++) {
913  col_verify[i].field_id = -1;
914  }
915  }
916 
917  /* Get table name. */
918  dbname = info->col_info[CONTAINER_DB].col_name;
919  tname = info->col_info[CONTAINER_TABLE].col_name;
920 #ifdef __WIN__
921  sprintf(table_name, "%s\%s", dbname, tname);
922 #else
923  snprintf(table_name, sizeof(table_name), "%s/%s", dbname, tname);
924 #endif
925 
926  n_cols = innodb_cb_tuple_get_n_cols(tpl);
927 
928  /* Verify each mapped column */
929  for (i = 0; i < n_cols; i++) {
930  ib_err_t result = DB_SUCCESS;
931 
932  name = innodb_cb_col_get_name(crsr, i);
933  innodb_cb_col_get_meta(tpl, i, &col_meta);
934 
935  result = innodb_config_value_col_verify(
936  name, info, &col_meta, i, col_verify);
937 
938  if (result == DB_SUCCESS) {
939  is_value_col = true;
940  continue;
941  } else if (result == DB_DATA_MISMATCH) {
942  err = DB_DATA_MISMATCH;
943  goto func_exit;
944  }
945 
946  if (strcmp(name, cinfo[CONTAINER_KEY].col_name) == 0) {
947  /* Key column must be CHAR or VARCHAR type */
948  if (col_meta.type != IB_VARCHAR
949  && col_meta.type != IB_CHAR
950  && col_meta.type != IB_VARCHAR_ANYCHARSET
951  && col_meta.type != IB_CHAR_ANYCHARSET
952  && col_meta.type != IB_INT) {
953  fprintf(stderr,
954  " InnoDB_Memcached: the key"
955  " column %s in table %s should"
956  " be INTEGER, CHAR or VARCHAR.\n",
957  name, table_name);
958  err = DB_DATA_MISMATCH;
959  goto func_exit;
960  }
961  cinfo[CONTAINER_KEY].field_id = i;
962  cinfo[CONTAINER_KEY].col_meta = col_meta;
963  is_key_col = true;
964  } else if (strcmp(name, cinfo[CONTAINER_FLAG].col_name) == 0) {
965  /* Flag column must be integer type */
966  if (col_meta.type != IB_INT) {
967  fprintf(stderr, " InnoDB_Memcached: the flag"
968  " column %s in table %s should"
969  " be INTEGER.\n",
970  name, table_name);
971  err = DB_DATA_MISMATCH;
972  goto func_exit;
973  }
974  cinfo[CONTAINER_FLAG].field_id = i;
975  cinfo[CONTAINER_FLAG].col_meta = col_meta;
976  info->flag_enabled = true;
977  is_flag_col = true;
978  } else if (strcmp(name, cinfo[CONTAINER_CAS].col_name) == 0) {
979  /* CAS column must be integer type */
980  if (col_meta.type != IB_INT) {
981  fprintf(stderr, " InnoDB_Memcached: the cas"
982  " column %s in table %s should"
983  " be INTEGER.\n",
984  name, table_name);
985  err = DB_DATA_MISMATCH;
986  goto func_exit;
987  }
988  cinfo[CONTAINER_CAS].field_id = i;
989  cinfo[CONTAINER_CAS].col_meta = col_meta;
990  info->cas_enabled = true;
991  is_cas_col = true;
992  } else if (strcmp(name, cinfo[CONTAINER_EXP].col_name) == 0) {
993  /* EXP column must be integer type */
994  if (col_meta.type != IB_INT) {
995  fprintf(stderr, " InnoDB_Memcached: the expire"
996  " column %s in table %s should"
997  " be INTEGER.\n",
998  name, table_name);
999  err = DB_DATA_MISMATCH;
1000  goto func_exit;
1001  }
1002  cinfo[CONTAINER_EXP].field_id = i;
1003  cinfo[CONTAINER_EXP].col_meta = col_meta;
1004  info->exp_enabled = true;
1005  is_exp_col = true;
1006  }
1007  }
1008 
1009  /* Key column and Value column must present */
1010  if (!is_key_col || !is_value_col) {
1011  fprintf(stderr, " InnoDB_Memcached: failed to locate key"
1012  " column or value column in table"
1013  " as specified by config table \n");
1014 
1015  err = DB_ERROR;
1016  goto func_exit;
1017  }
1018 
1019  if (info->n_extra_col) {
1020  meta_column_t* col_check;
1021 
1022  col_check = (runtime && col_verify)
1023  ? col_verify
1024  : info->extra_col_info;
1025 
1026  for (i = 0; i < info->n_extra_col; i++) {
1027  if (col_check[i].field_id < 0) {
1028  fprintf(stderr, " InnoDB_Memcached: failed to"
1029  " locate value column %s"
1030  " as specified by config"
1031  " table \n",
1032  info->extra_col_info[i].col_name);
1033  err = DB_ERROR;
1034  goto func_exit;
1035  }
1036  }
1037  }
1038 
1039  if (info->flag_enabled && !is_flag_col) {
1040  fprintf(stderr, " InnoDB_Memcached: failed to locate flag"
1041  " column as specified by config table \n");
1042  err = DB_ERROR;
1043  goto func_exit;
1044  }
1045 
1046  if (info->cas_enabled && !is_cas_col) {
1047  fprintf(stderr, " InnoDB_Memcached: failed to locate cas"
1048  " column as specified by config table \n");
1049  err = DB_ERROR;
1050  goto func_exit;
1051  }
1052 
1053  if (info->exp_enabled && !is_exp_col) {
1054  fprintf(stderr, " InnoDB_Memcached: failed to locate exp"
1055  " column as specified by config table \n");
1056  err = DB_ERROR;
1057  goto func_exit;
1058  }
1059 
1060  /* Test the specified index */
1062  &idx_crsr, &index_type,
1063  &index_id);
1064 
1065  if (index_type & IB_CLUSTERED) {
1067  } else if (!idx_crsr || !(index_type & IB_UNIQUE)) {
1068  fprintf(stderr, " InnoDB_Memcached: Index on key column"
1069  " must be a Unique index\n");
1071  err = DB_ERROR;
1072  } else {
1073  info->index_info.idx_id = index_id;
1075  }
1076 
1077  if (idx_crsr) {
1078  ib_tpl_t idx_tpl = NULL;
1079  if (index_type & IB_CLUSTERED) {
1080  idx_tpl = innodb_cb_read_tuple_create(idx_crsr);
1081  } else {
1082  idx_tpl = ib_cb_search_tuple_create(idx_crsr);
1083  }
1084 
1085  n_cols = ib_cb_get_n_user_cols(idx_tpl);
1086 
1087  name = ib_cb_get_idx_field_name(idx_crsr, 0);
1088 
1089  if (strcmp(name, cinfo[CONTAINER_KEY].col_name)) {
1090  fprintf(stderr, " InnoDB_Memcached: Index used"
1091  " must be on key column only\n");
1092  err = DB_ERROR;
1093  }
1094 
1095  if (!(index_type & IB_CLUSTERED) && n_cols > 1) {
1096  fprintf(stderr, " InnoDB_Memcached: Index used"
1097  " must be on key column only\n");
1098  err = DB_ERROR;
1099  }
1100 
1101  innodb_cb_tuple_delete(idx_tpl);
1102  innodb_cb_cursor_close(idx_crsr);
1103  }
1104 func_exit:
1105 
1106  if (runtime && col_verify) {
1107  free(col_verify);
1108  }
1109 
1110  if (tpl) {
1112  }
1113 
1114  return(err);
1115 }
1116 
1117 /**********************************************************************/
1121 bool
1123 /*==========*/
1124  meta_cfg_info_t* info)
1125 {
1126  ib_crsr_t crsr = NULL;
1127  char table_name[MAX_TABLE_NAME_LEN + MAX_DATABASE_NAME_LEN];
1128  char* dbname;
1129  char* name;
1130  ib_err_t err = DB_SUCCESS;
1131 
1132  dbname = info->col_info[CONTAINER_DB].col_name;
1133  name = info->col_info[CONTAINER_TABLE].col_name;
1134  info->flag_enabled = false;
1135  info->cas_enabled = false;
1136  info->exp_enabled = false;
1137 
1138 #ifdef __WIN__
1139  sprintf(table_name, "%s\%s", dbname, name);
1140 #else
1141  snprintf(table_name, sizeof(table_name), "%s/%s", dbname, name);
1142 #endif
1143 
1144  err = innodb_cb_open_table(table_name, NULL, &crsr);
1145 
1146  /* Mapped InnoDB table must be able to open */
1147  if (err != DB_SUCCESS) {
1148  fprintf(stderr, " InnoDB_Memcached: failed to open table"
1149  " '%s' \n", table_name);
1150  err = DB_ERROR;
1151  goto func_exit;
1152  }
1153 
1154  err = innodb_verify_low(info, crsr, false);
1155 func_exit:
1156  if (crsr) {
1157  innodb_cb_cursor_close(crsr);
1158  }
1159 
1160  return(err == DB_SUCCESS);
1161 }
1162 
1163 /**********************************************************************/
1174 /*==========*/
1175  const char* name,
1176  size_t name_len,
1177  hash_table_t** meta_hash)
1180 {
1181  meta_cfg_info_t* item;
1182  bool success;
1183 
1184  if (*meta_hash == NULL) {
1185  *meta_hash = hash_create(100);
1186  }
1187 
1188  if (!name) {
1189  item = innodb_config_meta_hash_init(*meta_hash);
1190  } else {
1191  ib_ulint_t fold;
1192 
1193  fold = ut_fold_string(name);
1194  HASH_SEARCH(name_hash, *meta_hash, fold,
1195  meta_cfg_info_t*, item,
1196  (name_len == item->col_info[0].col_name_len
1197  && strcmp(name, item->col_info[0].col_name) == 0));
1198 
1199  if (item) {
1200  return(item);
1201  }
1202 
1203  item = innodb_config_container(name, name_len, *meta_hash);
1204  }
1205 
1206  if (!item) {
1207  return(NULL);
1208  }
1209 
1210  /* Following two configure operations are optional, and can be
1211  failed */
1212  success = innodb_read_cache_policy(item);
1213 
1214  if (!success) {
1215  return(NULL);
1216  }
1217 
1218  success = innodb_read_config_option(item);
1219 
1220  if (!success) {
1221  return(NULL);
1222  }
1223 
1224  return(item);
1225 }