33 #include "memcached/util.h"
38 #define UPDATE_ALL_VAL_COL -1
43 static ib_cb_t* innodb_memcached_api[] = {
53 (
ib_cb_t*) &ib_cb_cursor_set_match_mode,
54 (
ib_cb_t*) &ib_cb_search_tuple_create,
55 (
ib_cb_t*) &ib_cb_read_tuple_create,
58 (
ib_cb_t*) &ib_cb_tuple_read_u8,
59 (
ib_cb_t*) &ib_cb_tuple_write_u8,
60 (
ib_cb_t*) &ib_cb_tuple_read_u16,
61 (
ib_cb_t*) &ib_cb_tuple_write_u16,
62 (
ib_cb_t*) &ib_cb_tuple_read_u32,
63 (
ib_cb_t*) &ib_cb_tuple_write_u32,
64 (
ib_cb_t*) &ib_cb_tuple_read_u64,
65 (
ib_cb_t*) &ib_cb_tuple_write_u64,
66 (
ib_cb_t*) &ib_cb_tuple_read_i8,
67 (
ib_cb_t*) &ib_cb_tuple_write_i8,
68 (
ib_cb_t*) &ib_cb_tuple_read_i16,
69 (
ib_cb_t*) &ib_cb_tuple_write_i16,
70 (
ib_cb_t*) &ib_cb_tuple_read_i32,
71 (
ib_cb_t*) &ib_cb_tuple_write_i32,
72 (
ib_cb_t*) &ib_cb_tuple_read_i64,
73 (
ib_cb_t*) &ib_cb_tuple_write_i64,
74 (
ib_cb_t*) &ib_cb_tuple_get_n_cols,
75 (
ib_cb_t*) &ib_cb_col_set_value,
76 (
ib_cb_t*) &ib_cb_col_get_value,
86 (
ib_cb_t*) &ib_cb_cursor_new_trx,
88 (
ib_cb_t*) &ib_cb_open_table_by_name,
90 (
ib_cb_t*) &ib_cb_table_truncate,
91 (
ib_cb_t*) &ib_cb_cursor_open_index_using_name,
94 (
ib_cb_t*) &ib_cb_cursor_set_cluster_access,
95 (
ib_cb_t*) &ib_cb_cursor_commit_trx,
96 (
ib_cb_t*) &ib_cb_cfg_trx_level,
97 (
ib_cb_t*) &ib_cb_get_n_user_cols,
98 (
ib_cb_t*) &ib_cb_cursor_set_lock,
99 (
ib_cb_t*) &ib_cb_cursor_clear_trx,
100 (
ib_cb_t*) &ib_cb_get_idx_field_name,
101 (
ib_cb_t*) &ib_cb_trx_get_start_time,
102 (
ib_cb_t*) &ib_cb_cfg_bk_commit_interval
108 #define SET_EXP_TIME(exp) \
110 if (exp < 60*60*24*30) { \
111 exp += mci_get_time(); \
126 array_size =
sizeof(innodb_memcached_api)
127 /
sizeof(*innodb_memcached_api);
129 for (i = 0; i < array_size; i++) {
130 *innodb_memcached_api[
i] = *(
ib_cb_t*)func_ptr;
157 sprintf(table_name,
"%s\%s", dbname, name);
159 snprintf(table_name,
sizeof(table_name),
160 "%s/%s", dbname, name);
163 err = ib_cb_open_table(table_name, ib_trx, crsr);
165 if (err != DB_SUCCESS) {
166 fprintf(stderr,
" InnoDB_Memcached: Unable to open"
167 " table '%s'\n", table_name);
173 if (err != DB_SUCCESS) {
174 fprintf(stderr,
" InnoDB_Memcached: Fail to lock"
175 " table '%s'\n", table_name);
185 meta_info , *crsr,
true);
187 if (err != DB_SUCCESS) {
188 fprintf(stderr,
" InnoDB_Memcached:"
200 ib_id_u64_t index_id;
202 ib_cb_cursor_open_index_using_name(
204 idx_crsr, &index_type, &index_id);
213 if (!conn_data->
thd) {
217 if (!conn_data->
thd) {
234 ib_cb_cursor_new_trx(*crsr, ib_trx);
238 if (err != DB_SUCCESS) {
239 fprintf(stderr,
" InnoDB_Memcached: Fail to lock"
240 " table '%s'\n", name);
250 ib_cb_cursor_new_trx(*idx_crsr, ib_trx);
265 innodb_api_read_uint64(
277 ib_cb_tuple_read_u64(read_tpl, i, &value64);
297 assert (m_col->
type_len ==
sizeof(uint64_t)
298 || m_col->
type_len ==
sizeof(uint32_t)
299 || m_col->
type_len ==
sizeof(uint16_t)
300 || m_col->
type_len ==
sizeof(uint8_t));
303 if (m_col->
type_len ==
sizeof(uint64_t)) {
306 }
else if (m_col->
type_len ==
sizeof(uint32_t)) {
308 ib_cb_tuple_read_u32(read_tpl, i, &value32);
309 value = (int64_t) value32;
310 }
else if (m_col->
type_len ==
sizeof(uint16_t)) {
312 ib_cb_tuple_read_u16(read_tpl, i, &value16);
313 value = (int64_t) value16;
314 }
else if (m_col->
type_len ==
sizeof(uint8_t)) {
316 ib_cb_tuple_read_u8(read_tpl, i, &value8);
317 value = (int64_t) value8;
320 if (m_col->
type_len ==
sizeof(int64_t)) {
321 ib_cb_tuple_read_i64(read_tpl, i, &value);
322 }
else if (m_col->
type_len ==
sizeof(int32_t)) {
324 ib_cb_tuple_read_i32(read_tpl, i, &value32);
325 value = (int64_t) value32;
326 }
else if (m_col->
type_len ==
sizeof(int16_t)) {
328 ib_cb_tuple_read_i16(read_tpl, i, &value16);
329 value = (int64_t) value16;
330 }
else if (m_col->
type_len ==
sizeof(int8_t)) {
332 ib_cb_tuple_read_i8(read_tpl, i, &value8);
333 value = (int64_t) value8;
345 innodb_api_write_int(
364 ib_cb_col_get_meta(tpl, field, m_col);
378 table, field, value,
true,
382 value_u32 = (uint32_t) value;
387 table, field, value_u32,
true,
false);
390 value_u16 = (uint16_t) value;
395 table, field, value_u16,
true,
false);
398 value_u8 = (uint8_t) value;
403 table, field, value_u8,
true,
false);
408 value_i64 = (int64_t) value;
413 table, field, value_i64,
false,
false);
416 value_i32 = (int32_t) value;
421 table, field, value_i32,
false,
false);
424 value_i16 = (int16_t) value;
429 table, field, value_i16,
false,
false);
432 value_i8 = (int8_t) value;
437 table, field, value_i8,
false,
false);
442 ib_cb_col_set_value(tpl, field, src, m_col->
type_len,
true);
451 innodb_api_write_uint64(
463 ib_cb_col_get_meta(tpl, field, m_col);
474 table, field, value,
true,
false);
477 ib_cb_col_set_value(tpl, field, src, m_col->
type_len,
true);
486 innodb_api_setup_field_value(
502 assert(value == NULL);
503 err = ib_cb_col_set_value(tpl, field_id,
504 value, val_len, need_cpy);
513 memcpy(val_buf, value, val_len);
514 val_buf[val_len] = 0;
517 uint64_t int_value = 0;
519 int_value = strtoull(val_buf, &end_ptr, 10);
523 if (end_ptr == val_buf) {
525 " InnoDB_Memcached: Unable to convert"
526 " value '%s' to integer\n", value);
530 err = innodb_api_write_uint64(tpl, field_id,
533 int64_t int_value = 0;
535 int_value = strtoll(val_buf, &end_ptr, 10);
538 if (end_ptr == val_buf) {
540 " InnoDB_Memcached: Unable to convert"
541 " value '%s' to integer\n", value);
544 err = innodb_api_write_int(tpl, field_id,
549 err = ib_cb_col_set_value(tpl, field_id,
550 value, val_len, need_cpy);
576 data_len = ib_cb_col_get_meta(read_tpl, col_id, &col_meta);
587 innodb_api_read_uint64(&col_meta,
592 innodb_api_read_int(&col_meta,
602 mci_item->
value_str = (
char*)ib_cb_col_get_value(
630 data_len = ib_cb_col_get_meta(read_tpl, col_id, &col_meta);
642 uint64_t int_val = 0;
644 int_val = innodb_api_read_uint64(&col_meta,
649 "%" PRIu64, int_val);
653 int_val = innodb_api_read_int(&col_meta,
658 "%" PRIi64, int_val);
673 ib_cb_col_get_value(read_tpl, col_id),
690 innodb_api_fill_value(
767 memset(item, 0,
sizeof(*item));
781 ib_cb_cursor_set_cluster_access(idx_crsr);
783 key_tpl = ib_cb_search_tuple_create(idx_crsr);
785 srch_crsr = idx_crsr;
793 crsr = cursor_data->
crsr;
796 key_tpl = ib_cb_search_tuple_create(crsr);
800 err = innodb_api_setup_field_value(key_tpl, 0,
807 err = ib_cb_moveto(srch_crsr, key_tpl,
IB_CUR_GE);
809 if (err != DB_SUCCESS) {
823 read_tpl = ib_cb_read_tuple_create(
825 : cursor_data->
crsr);
827 err = ib_cb_read_row(srch_crsr, read_tpl);
829 if (err != DB_SUCCESS) {
830 ib_cb_tuple_delete(read_tpl);
838 n_cols = ib_cb_tuple_get_n_cols(read_tpl);
856 for (i = 0; i < n_cols; ++
i) {
860 data_len = ib_cb_col_get_meta(read_tpl, i, &col_meta);
862 if (i == col_info[CONTAINER_KEY].field_id) {
865 (
char*)ib_cb_col_get_value(read_tpl, i);
882 innodb_api_read_uint64(col_meta,
887 innodb_api_read_int(col_meta,
891 col_value->
is_str =
false;
908 innodb_api_read_uint64(col_meta,
916 innodb_api_read_int(col_meta,
920 col_value->
is_str =
false;
937 innodb_api_read_uint64(col_meta,
942 innodb_api_read_int(col_meta,
946 col_value->
is_str =
false;
951 innodb_api_fill_value(meta_info, item,
952 read_tpl, i, sel_only);
958 }
else if (key_tpl) {
959 ib_cb_tuple_delete(read_tpl);
966 ib_cb_tuple_delete(key_tpl);
981 static uint64_t cas_id = 0;
983 #if defined(HAVE_IB_GCC_ATOMIC_BUILTINS)
984 return(__sync_add_and_fetch(&cas_id, 1));
1004 gettimeofday(&tv,NULL);
1006 return((uint64_t)tv.tv_sec);
1014 innodb_api_set_multi_cols(
1037 my_value = malloc(value_len + 1);
1043 memcpy(my_value, value, value_len);
1044 my_value[value_len] = 0;
1046 end = value + value_len;
1050 assert(sep_len > 0);
1052 if (value[0] == *sep) {
1053 err = innodb_api_setup_field_value(
1054 tpl, col_info[i].field_id, &col_info[i],
1058 if (err != DB_SUCCESS) {
1066 for (col_val = strtok_r(value, sep, &last);
1068 col_val = strtok_r(NULL, sep, &last), i++) {
1071 err = innodb_api_setup_field_value(
1072 tpl, col_info[i].field_id, &col_info[i],
1076 err = innodb_api_setup_field_value(
1077 tpl, col_info[i].field_id, &col_info[i],
1078 col_val, strlen(col_val), table,
true);
1082 table, col_info[i].field_id,
1083 col_val, strlen(col_val));
1087 if (err != DB_SUCCESS) {
1093 err = innodb_api_setup_field_value(
1094 tpl, col_info[i].field_id, &col_info[i],
1097 if (err != DB_SUCCESS) {
1110 innodb_api_setup_hdl_rec(
1163 err = innodb_api_setup_field_value(
1167 if (err != DB_SUCCESS) {
1171 assert(err == DB_SUCCESS);
1175 err = innodb_api_set_multi_cols(tpl, meta_info,
1180 err = ib_cb_col_set_value(
1183 value, value_len, need_cpy);
1188 col_info[col_to_set].field_id,
1193 err = innodb_api_setup_field_value(
1196 value_len, table, need_cpy);
1199 if (err != DB_SUCCESS) {
1204 err = innodb_api_write_int(
1206 if (err != DB_SUCCESS) {
1212 err = innodb_api_write_int(
1214 if (err != DB_SUCCESS) {
1220 err = innodb_api_write_int(
1222 if (err != DB_SUCCESS) {
1251 new_cas = mci_get_cas(engine);
1253 tpl = ib_cb_read_tuple_create(cursor_data->
crsr);
1254 assert(tpl != NULL);
1262 err = innodb_api_set_tpl(tpl, meta_info, col_info, key, len,
1269 if (err == DB_SUCCESS) {
1270 err = ib_cb_insert_row(cursor_data->
crsr, tpl);
1273 if (err == DB_SUCCESS) {
1284 ib_cb_tuple_delete(tpl);
1315 assert(old_tpl != NULL);
1317 new_tpl = ib_cb_read_tuple_create(cursor_data->
crsr);
1318 assert(new_tpl != NULL);
1321 new_cas = mci_get_cas(engine);
1326 innodb_api_setup_hdl_rec(result, col_info,
1334 err = innodb_api_set_tpl(new_tpl, meta_info, col_info, key,
1335 len, key + len, val_len,
1341 if (err == DB_SUCCESS) {
1342 err = ib_cb_update_row(srch_crsr, old_tpl, new_tpl);
1345 if (err == DB_SUCCESS) {
1358 ib_cb_tuple_delete(new_tpl);
1381 &result, &tpl_delete,
false);
1383 if (err != DB_SUCCESS) {
1384 ib_cb_tuple_delete(tpl_delete);
1385 return(ENGINE_KEY_ENOENT);
1397 innodb_api_setup_hdl_rec(&result, col_info,
1401 err = ib_cb_delete_row(srch_crsr);
1405 if (err == DB_SUCCESS) {
1411 ib_cb_tuple_delete(tpl_delete);
1412 return(err == DB_SUCCESS ? ENGINE_SUCCESS : ENGINE_KEY_ENOENT);
1452 innodb_api_setup_hdl_rec(result, col_info,
1463 column_used =
flags;
1476 total_len = before_len + val_len;
1478 append_buf = (
char*) malloc(total_len);
1481 memcpy(append_buf, before_val, before_len);
1482 memcpy(append_buf + before_len, key + len, val_len);
1484 memcpy(append_buf, key + len, val_len);
1485 memcpy(append_buf + val_len, before_val, before_len);
1488 new_tpl = ib_cb_read_tuple_create(cursor_data->
crsr);
1489 new_cas = mci_get_cas(engine);
1500 err = innodb_api_set_tpl(new_tpl, meta_info, col_info,
1501 key, len, append_buf, total_len,
1502 new_cas, exp, flags, column_used,
1507 if (err == DB_SUCCESS) {
1508 err = ib_cb_update_row(srch_crsr, old_tpl, new_tpl);
1511 ib_cb_tuple_delete(new_tpl);
1516 if (err == DB_SUCCESS) {
1542 rel_time_t exp_time __attribute__((unused)),
1547 uint64_t* out_result)
1551 char value_buf[128];
1556 bool create_new =
false;
1562 unsigned int before_len;
1563 int column_used = 0;
1564 ENGINE_ERROR_CODE
ret = ENGINE_SUCCESS;
1567 &result, &old_tpl,
false);
1571 if (err != DB_SUCCESS && err != DB_RECORD_NOT_FOUND) {
1572 ib_cb_tuple_delete(old_tpl);
1576 memset(value_buf, 0, 128);
1579 if (err != DB_SUCCESS) {
1580 ib_cb_tuple_delete(old_tpl);
1584 snprintf(value_buf,
sizeof(value_buf),
1585 "%" PRIu64, initial);
1587 goto create_new_value;
1591 return(DB_RECORD_NOT_FOUND);
1597 innodb_api_setup_hdl_rec(&result, col_info,
1610 column_used =
flags;
1623 if (before_len >= (
sizeof(value_buf) - 1)) {
1624 ib_cb_tuple_delete(old_tpl);
1625 ret = ENGINE_EINVAL;
1632 value = strtoull(before_val, &end_ptr, 10);
1635 if (errno == ERANGE) {
1636 ib_cb_tuple_delete(old_tpl);
1637 ret = ENGINE_EINVAL;
1644 if (delta > (
int) value) {
1651 snprintf(value_buf,
sizeof(value_buf),
"%" PRIu64, value);
1653 *cas = mci_get_cas(engine);
1655 new_tpl = ib_cb_read_tuple_create(cursor_data->
crsr);
1662 err = innodb_api_set_tpl(new_tpl, meta_info, col_info,
1663 key, len, value_buf, strlen(value_buf),
1672 if (err != DB_SUCCESS) {
1673 ib_cb_tuple_delete(new_tpl);
1674 ib_cb_tuple_delete(old_tpl);
1679 err = ib_cb_insert_row(cursor_data->
crsr, new_tpl);
1680 *out_result = initial;
1687 err = ib_cb_update_row(srch_crsr, old_tpl, new_tpl);
1688 *out_result = value;
1696 ib_cb_tuple_delete(new_tpl);
1697 ib_cb_tuple_delete(old_tpl);
1710 if (ret == ENGINE_SUCCESS) {
1711 ret = (err == DB_SUCCESS) ? ENGINE_SUCCESS : ENGINE_NOT_STORED;
1738 ENGINE_STORE_OPERATION op)
1743 ENGINE_ERROR_CODE stored = ENGINE_NOT_STORED;
1748 if (op == OPERATION_ADD) {
1749 err = DB_RECORD_NOT_FOUND;
1750 memset(&result, 0,
sizeof(result));
1754 key, len, &result, &old_tpl,
false);
1759 if (err != DB_SUCCESS && err != DB_RECORD_NOT_FOUND) {
1766 val_len, exp, cas, flags);
1768 case OPERATION_REPLACE:
1769 if (err == DB_SUCCESS) {
1770 err = innodb_api_update(engine, cursor_data, srch_crsr,
1771 key, len, val_len, exp,
1772 cas, flags, old_tpl, &result);
1775 case OPERATION_APPEND:
1776 case OPERATION_PREPEND:
1783 if (err == DB_SUCCESS) {
1784 err = innodb_api_link(engine, cursor_data, srch_crsr,
1785 key, len, val_len, exp,
1787 (op == OPERATION_APPEND),
1792 if (err == DB_SUCCESS) {
1793 err = innodb_api_update(engine, cursor_data,
1794 srch_crsr, key, len, val_len,
1799 val_len, exp, cas, flags);
1803 if (err != DB_SUCCESS) {
1804 stored = ENGINE_KEY_ENOENT;
1806 }
else if (input_cas
1808 err = innodb_api_update(engine, cursor_data, srch_crsr,
1809 key, len, val_len, exp,
1810 cas, flags, old_tpl, &result);
1813 stored = ENGINE_KEY_EEXISTS;
1829 ib_cb_tuple_delete(old_tpl);
1831 if (err == DB_SUCCESS && stored == ENGINE_NOT_STORED) {
1832 stored = ENGINE_SUCCESS;
1852 + MAX_DATABASE_NAME_LEN + 1];
1856 sprintf(table_name,
"%s\%s", dbname, name);
1858 snprintf(table_name,
sizeof(table_name),
"%s/%s", dbname, name);
1861 err = ib_cb_table_truncate(table_name, &new_id);
1865 void* thd = conn_data->
thd;
1867 snprintf(table_name,
sizeof(table_name),
"%s.%s", dbname, name);
1887 bool commit_trx =
false;
1891 if (conn_data->
crsr) {
1892 ib_cb_cursor_reset(conn_data->
crsr);
1896 ib_cb_cursor_reset(conn_data->
read_crsr);
1900 ib_cb_cursor_reset(conn_data->
idx_crsr);
1920 assert(conn_data->
crsr
1923 ib_crsr = conn_data->
crsr
1929 ib_cb_cursor_commit_trx(
1932 if (has_binlog && conn_data->
thd
1938 ib_cb_trx_rollback(conn_data->
crsr_trx);
1940 if (has_binlog && conn_data->
thd
1949 if (conn_data->
crsr) {
1950 ib_cb_cursor_clear_trx(
1955 ib_cb_cursor_clear_trx(
1960 ib_cb_cursor_clear_trx(
1965 ib_cb_cursor_clear_trx(
1970 conn_data->
in_use =
false;
1976 UNLOCK_CURRENT_CONN_IF_NOT_LOCKED(has_lock, conn_data);
1993 bool commit_trx =
false;
2021 assert(conn_data->
in_use);
2024 conn_data->
in_use =
false;
2041 return(ib_cb_cursor_close(ib_crsr));
2052 return(ib_cb_trx_commit(ib_trx));
2063 return(ib_cb_close_thd(thd));
2074 return(ib_cb_trx_begin(ib_trx_level));
2086 return(ib_cb_cursor_new_trx(ib_crsr, ib_trx));
2103 err = ib_cb_cursor_lock(ib_crsr,
IB_LOCK_X);
2104 }
else if (eng && eng->
cfg_status & IB_CFG_DISABLE_ROWLOCK) {
2107 err = ib_cb_cursor_lock(ib_crsr,
IB_LOCK_IX);
2109 err = ib_cb_cursor_lock(ib_crsr,
IB_LOCK_IS);
2112 err = ib_cb_cursor_set_lock(ib_crsr, ib_lck_mode);
2126 return(ib_cb_read_tuple_create(ib_crsr));
2137 return(ib_cb_cursor_first(ib_crsr));
2149 return(ib_cb_read_row(ib_crsr, ib_tpl));
2162 return(ib_cb_col_get_meta(ib_tpl, i, ib_col_meta));
2172 ib_cb_tuple_delete(ib_tpl);
2184 return(ib_cb_tuple_get_n_cols(ib_tpl));
2196 return(ib_cb_col_get_value(ib_tpl, i));
2209 return(ib_cb_open_table(name, ib_trx, ib_crsr));
2221 return(ib_cb_col_get_name(ib_crsr, i));
2231 const char* index_name,
2234 ib_id_u64_t* idx_id)
2236 return(ib_cb_cursor_open_index_using_name(ib_open_crsr, index_name,
2237 ib_crsr, idx_type, idx_id));
2246 return(ib_cb_get_cfg());