dict-memcached-ascii.c (dovecot-2.3.16) | : | dict-memcached-ascii.c (dovecot-2.3.17) | ||
---|---|---|---|---|
skipping to change at line 55 | skipping to change at line 55 | |||
struct dict_transaction_memory_context *memctx; | struct dict_transaction_memory_context *memctx; | |||
string_t *str; | string_t *str; | |||
dict_transaction_commit_callback_t *callback; | dict_transaction_commit_callback_t *callback; | |||
void *context; | void *context; | |||
}; | }; | |||
struct memcached_ascii_dict { | struct memcached_ascii_dict { | |||
struct dict dict; | struct dict dict; | |||
struct ip_addr ip; | struct ip_addr ip; | |||
char *username, *key_prefix; | char *key_prefix; | |||
in_port_t port; | in_port_t port; | |||
unsigned int timeout_msecs; | unsigned int timeout_msecs; | |||
struct timeout *to; | struct timeout *to; | |||
struct memcached_ascii_connection conn; | struct memcached_ascii_connection conn; | |||
ARRAY(enum memcached_ascii_input_state) input_states; | ARRAY(enum memcached_ascii_input_state) input_states; | |||
ARRAY(struct memcached_ascii_dict_reply) replies; | ARRAY(struct memcached_ascii_dict_reply) replies; | |||
}; | }; | |||
skipping to change at line 442 | skipping to change at line 442 | |||
} | } | |||
dict->conn.conn.event_parent = set->event_parent; | dict->conn.conn.event_parent = set->event_parent; | |||
connection_init_client_ip(memcached_ascii_connections, &dict->conn.conn, | connection_init_client_ip(memcached_ascii_connections, &dict->conn.conn, | |||
NULL, &dict->ip, dict->port); | NULL, &dict->ip, dict->port); | |||
event_set_append_log_prefix(dict->conn.conn.event, "memcached: "); | event_set_append_log_prefix(dict->conn.conn.event, "memcached: "); | |||
dict->dict = *driver; | dict->dict = *driver; | |||
dict->conn.reply_str = str_new(default_pool, 256); | dict->conn.reply_str = str_new(default_pool, 256); | |||
dict->conn.dict = dict; | dict->conn.dict = dict; | |||
if (strchr(set->username, DICT_USERNAME_SEPARATOR) == NULL) | ||||
dict->username = i_strdup(set->username); | ||||
else { | ||||
/* escape the username */ | ||||
dict->username = i_strdup(memcached_ascii_escape_username(set->us | ||||
ername)); | ||||
} | ||||
i_array_init(&dict->input_states, 4); | i_array_init(&dict->input_states, 4); | |||
i_array_init(&dict->replies, 4); | i_array_init(&dict->replies, 4); | |||
dict->dict.ioloop = io_loop_create(); | dict->dict.ioloop = io_loop_create(); | |||
io_loop_set_current(old_ioloop); | io_loop_set_current(old_ioloop); | |||
*dict_r = &dict->dict; | *dict_r = &dict->dict; | |||
return 0; | return 0; | |||
} | } | |||
static void memcached_ascii_dict_deinit(struct dict *_dict) | static void memcached_ascii_dict_deinit(struct dict *_dict) | |||
skipping to change at line 478 | skipping to change at line 472 | |||
connection_deinit(&dict->conn.conn); | connection_deinit(&dict->conn.conn); | |||
io_loop_set_current(dict->dict.ioloop); | io_loop_set_current(dict->dict.ioloop); | |||
io_loop_destroy(&dict->dict.ioloop); | io_loop_destroy(&dict->dict.ioloop); | |||
io_loop_set_current(old_ioloop); | io_loop_set_current(old_ioloop); | |||
str_free(&dict->conn.reply_str); | str_free(&dict->conn.reply_str); | |||
array_free(&dict->replies); | array_free(&dict->replies); | |||
array_free(&dict->input_states); | array_free(&dict->input_states); | |||
i_free(dict->key_prefix); | i_free(dict->key_prefix); | |||
i_free(dict->username); | ||||
i_free(dict); | i_free(dict); | |||
if (memcached_ascii_connections->connections == NULL) | if (memcached_ascii_connections->connections == NULL) | |||
connection_list_deinit(&memcached_ascii_connections); | connection_list_deinit(&memcached_ascii_connections); | |||
} | } | |||
static int memcached_ascii_connect(struct memcached_ascii_dict *dict, | static int memcached_ascii_connect(struct memcached_ascii_dict *dict, | |||
const char **error_r) | const char **error_r) | |||
{ | { | |||
if (dict->conn.conn.input != NULL) | if (dict->conn.conn.input != NULL) | |||
skipping to change at line 504 | skipping to change at line 497 | |||
"memcached_ascii: Couldn't connect to %s:%u", | "memcached_ascii: Couldn't connect to %s:%u", | |||
net_ip2addr(&dict->ip), dict->port); | net_ip2addr(&dict->ip), dict->port); | |||
return -1; | return -1; | |||
} | } | |||
} | } | |||
return memcached_ascii_wait(dict, error_r); | return memcached_ascii_wait(dict, error_r); | |||
} | } | |||
static const char * | static const char * | |||
memcached_ascii_dict_get_full_key(struct memcached_ascii_dict *dict, | memcached_ascii_dict_get_full_key(struct memcached_ascii_dict *dict, | |||
const char *key) | const char *username, const char *key) | |||
{ | { | |||
if (str_begins(key, DICT_PATH_SHARED)) | if (str_begins(key, DICT_PATH_SHARED)) | |||
key += strlen(DICT_PATH_SHARED); | key += strlen(DICT_PATH_SHARED); | |||
else if (str_begins(key, DICT_PATH_PRIVATE)) { | else if (str_begins(key, DICT_PATH_PRIVATE)) { | |||
key = t_strdup_printf("%s%c%s", dict->username, | if (strchr(username, DICT_USERNAME_SEPARATOR) == NULL) { | |||
DICT_USERNAME_SEPARATOR, | key = t_strdup_printf("%s%c%s", username, | |||
key + strlen(DICT_PATH_PRIVATE)); | DICT_USERNAME_SEPARATOR, | |||
key + strlen(DICT_PATH_PRIVATE)); | ||||
} else { | ||||
/* escape the username */ | ||||
key = t_strdup_printf("%s%c%s", memcached_ascii_escape_us | ||||
ername(username), | ||||
DICT_USERNAME_SEPARATOR, | ||||
key + strlen(DICT_PATH_PRIVATE)); | ||||
} | ||||
} else { | } else { | |||
i_unreached(); | i_unreached(); | |||
} | } | |||
if (*dict->key_prefix != '\0') | if (*dict->key_prefix != '\0') | |||
key = t_strconcat(dict->key_prefix, key, NULL); | key = t_strconcat(dict->key_prefix, key, NULL); | |||
return key; | return key; | |||
} | } | |||
static int | static int | |||
memcached_ascii_dict_lookup(struct dict *_dict, pool_t pool, const char *key, | memcached_ascii_dict_lookup(struct dict *_dict, | |||
const char **value_r, const char **error_r) | const struct dict_op_settings *set, | |||
pool_t pool, const char *key, const char **value_r, | ||||
const char **error_r) | ||||
{ | { | |||
struct memcached_ascii_dict *dict = (struct memcached_ascii_dict *)_dict; | struct memcached_ascii_dict *dict = (struct memcached_ascii_dict *)_dict; | |||
struct memcached_ascii_dict_reply *reply; | struct memcached_ascii_dict_reply *reply; | |||
enum memcached_ascii_input_state state = MEMCACHED_INPUT_STATE_GET; | enum memcached_ascii_input_state state = MEMCACHED_INPUT_STATE_GET; | |||
if (memcached_ascii_connect(dict, error_r) < 0) | if (memcached_ascii_connect(dict, error_r) < 0) | |||
return -1; | return -1; | |||
key = memcached_ascii_dict_get_full_key(dict, key); | key = memcached_ascii_dict_get_full_key(dict, set->username, key); | |||
o_stream_nsend_str(dict->conn.conn.output, | o_stream_nsend_str(dict->conn.conn.output, | |||
t_strdup_printf("get %s\r\n", key)); | t_strdup_printf("get %s\r\n", key)); | |||
array_push_back(&dict->input_states, &state); | array_push_back(&dict->input_states, &state); | |||
reply = array_append_space(&dict->replies); | reply = array_append_space(&dict->replies); | |||
reply->reply_count = 1; | reply->reply_count = 1; | |||
if (memcached_ascii_wait(dict, error_r) < 0) | if (memcached_ascii_wait(dict, error_r) < 0) | |||
return -1; | return -1; | |||
skipping to change at line 560 | skipping to change at line 562 | |||
pool_t pool; | pool_t pool; | |||
pool = pool_alloconly_create("file dict transaction", 2048); | pool = pool_alloconly_create("file dict transaction", 2048); | |||
ctx = p_new(pool, struct dict_transaction_memory_context, 1); | ctx = p_new(pool, struct dict_transaction_memory_context, 1); | |||
dict_transaction_memory_init(ctx, _dict, pool); | dict_transaction_memory_init(ctx, _dict, pool); | |||
return &ctx->ctx; | return &ctx->ctx; | |||
} | } | |||
static void | static void | |||
memcached_send_change(struct dict_memcached_ascii_commit_ctx *ctx, | memcached_send_change(struct dict_memcached_ascii_commit_ctx *ctx, | |||
const struct dict_op_settings_private *set, | ||||
const struct dict_transaction_memory_change *change) | const struct dict_transaction_memory_change *change) | |||
{ | { | |||
enum memcached_ascii_input_state state; | enum memcached_ascii_input_state state; | |||
const char *key, *value; | const char *key, *value; | |||
key = memcached_ascii_dict_get_full_key(ctx->dict, change->key); | key = memcached_ascii_dict_get_full_key(ctx->dict, set->username, | |||
change->key); | ||||
str_truncate(ctx->str, 0); | str_truncate(ctx->str, 0); | |||
switch (change->type) { | switch (change->type) { | |||
case DICT_CHANGE_TYPE_SET: | case DICT_CHANGE_TYPE_SET: | |||
state = MEMCACHED_INPUT_STATE_STORED; | state = MEMCACHED_INPUT_STATE_STORED; | |||
str_printfa(ctx->str, "set %s 0 0 %zu\r\n%s\r\n", | str_printfa(ctx->str, "set %s 0 0 %zu\r\n%s\r\n", | |||
key, strlen(change->value.str), change->value.str); | key, strlen(change->value.str), change->value.str); | |||
break; | break; | |||
case DICT_CHANGE_TYPE_UNSET: | case DICT_CHANGE_TYPE_UNSET: | |||
state = MEMCACHED_INPUT_STATE_DELETED; | state = MEMCACHED_INPUT_STATE_DELETED; | |||
skipping to change at line 601 | skipping to change at line 605 | |||
} | } | |||
break; | break; | |||
} | } | |||
array_push_back(&ctx->dict->input_states, &state); | array_push_back(&ctx->dict->input_states, &state); | |||
o_stream_nsend(ctx->dict->conn.conn.output, | o_stream_nsend(ctx->dict->conn.conn.output, | |||
str_data(ctx->str), str_len(ctx->str)); | str_data(ctx->str), str_len(ctx->str)); | |||
} | } | |||
static int | static int | |||
memcached_ascii_transaction_send(struct dict_memcached_ascii_commit_ctx *ctx, | memcached_ascii_transaction_send(struct dict_memcached_ascii_commit_ctx *ctx, | |||
const struct dict_op_settings_private *set, | ||||
const char **error_r) | const char **error_r) | |||
{ | { | |||
struct memcached_ascii_dict *dict = ctx->dict; | struct memcached_ascii_dict *dict = ctx->dict; | |||
struct memcached_ascii_dict_reply *reply; | struct memcached_ascii_dict_reply *reply; | |||
const struct dict_transaction_memory_change *changes; | const struct dict_transaction_memory_change *changes; | |||
unsigned int i, count, old_state_count; | unsigned int i, count, old_state_count; | |||
if (memcached_ascii_connect(dict, error_r) < 0) | if (memcached_ascii_connect(dict, error_r) < 0) | |||
return -1; | return -1; | |||
old_state_count = array_count(&dict->input_states); | old_state_count = array_count(&dict->input_states); | |||
changes = array_get(&ctx->memctx->changes, &count); | changes = array_get(&ctx->memctx->changes, &count); | |||
i_assert(count > 0); | i_assert(count > 0); | |||
o_stream_cork(dict->conn.conn.output); | o_stream_cork(dict->conn.conn.output); | |||
for (i = 0; i < count; i++) T_BEGIN { | for (i = 0; i < count; i++) T_BEGIN { | |||
memcached_send_change(ctx, &changes[i]); | memcached_send_change(ctx, set, &changes[i]); | |||
} T_END; | } T_END; | |||
o_stream_uncork(dict->conn.conn.output); | o_stream_uncork(dict->conn.conn.output); | |||
reply = array_append_space(&dict->replies); | reply = array_append_space(&dict->replies); | |||
reply->callback = ctx->callback; | reply->callback = ctx->callback; | |||
reply->context = ctx->context; | reply->context = ctx->context; | |||
reply->reply_count = array_count(&dict->input_states) - old_state_count; | reply->reply_count = array_count(&dict->input_states) - old_state_count; | |||
return 0; | return 0; | |||
} | } | |||
skipping to change at line 640 | skipping to change at line 645 | |||
bool async, | bool async, | |||
dict_transaction_commit_callback_t *callback, | dict_transaction_commit_callback_t *callback, | |||
void *context) | void *context) | |||
{ | { | |||
struct dict_transaction_memory_context *ctx = | struct dict_transaction_memory_context *ctx = | |||
(struct dict_transaction_memory_context *)_ctx; | (struct dict_transaction_memory_context *)_ctx; | |||
struct memcached_ascii_dict *dict = | struct memcached_ascii_dict *dict = | |||
(struct memcached_ascii_dict *)_ctx->dict; | (struct memcached_ascii_dict *)_ctx->dict; | |||
struct dict_memcached_ascii_commit_ctx commit_ctx; | struct dict_memcached_ascii_commit_ctx commit_ctx; | |||
struct dict_commit_result result = { DICT_COMMIT_RET_OK, NULL }; | struct dict_commit_result result = { DICT_COMMIT_RET_OK, NULL }; | |||
const struct dict_op_settings_private *set = &_ctx->set; | ||||
if (_ctx->changed) { | if (_ctx->changed) { | |||
i_zero(&commit_ctx); | i_zero(&commit_ctx); | |||
commit_ctx.dict = dict; | commit_ctx.dict = dict; | |||
commit_ctx.memctx = ctx; | commit_ctx.memctx = ctx; | |||
commit_ctx.callback = callback; | commit_ctx.callback = callback; | |||
commit_ctx.context = context; | commit_ctx.context = context; | |||
commit_ctx.str = str_new(default_pool, 128); | commit_ctx.str = str_new(default_pool, 128); | |||
result.ret = memcached_ascii_transaction_send(&commit_ctx, &resul t.error); | result.ret = memcached_ascii_transaction_send(&commit_ctx, set, & result.error); | |||
str_free(&commit_ctx.str); | str_free(&commit_ctx.str); | |||
if (async && result.ret == 0) { | if (async && result.ret == 0) { | |||
pool_unref(&ctx->pool); | pool_unref(&ctx->pool); | |||
return; | return; | |||
} | } | |||
if (result.ret == 0) { | if (result.ret == 0) { | |||
if (memcached_ascii_wait(dict, &result.error) < 0) | if (memcached_ascii_wait(dict, &result.error) < 0) | |||
result.ret = -1; | result.ret = -1; | |||
End of changes. 13 change blocks. | ||||
19 lines changed or deleted | 25 lines changed or added |