dict-redis.c (dovecot-2.3.16) | : | dict-redis.c (dovecot-2.3.17) | ||
---|---|---|---|---|
skipping to change at line 50 | skipping to change at line 50 | |||
}; | }; | |||
struct redis_dict_reply { | struct redis_dict_reply { | |||
unsigned int reply_count; | unsigned int reply_count; | |||
dict_transaction_commit_callback_t *callback; | dict_transaction_commit_callback_t *callback; | |||
void *context; | void *context; | |||
}; | }; | |||
struct redis_dict { | struct redis_dict { | |||
struct dict dict; | struct dict dict; | |||
char *username, *password, *key_prefix, *expire_value; | char *password, *key_prefix, *expire_value; | |||
unsigned int timeout_msecs, db_id; | unsigned int timeout_msecs, db_id; | |||
struct redis_connection conn; | struct redis_connection conn; | |||
ARRAY(enum redis_input_state) input_states; | ARRAY(enum redis_input_state) input_states; | |||
ARRAY(struct redis_dict_reply) replies; | ARRAY(struct redis_dict_reply) replies; | |||
bool connected; | bool connected; | |||
bool transaction_open; | bool transaction_open; | |||
bool db_id_set; | bool db_id_set; | |||
skipping to change at line 443 | skipping to change at line 443 | |||
connection_init_client_ip(redis_connections, &dict->conn.conn, | connection_init_client_ip(redis_connections, &dict->conn.conn, | |||
NULL, &ip, port); | NULL, &ip, port); | |||
} | } | |||
event_set_append_log_prefix(dict->conn.conn.event, "redis: "); | event_set_append_log_prefix(dict->conn.conn.event, "redis: "); | |||
dict->dict = *driver; | dict->dict = *driver; | |||
dict->conn.last_reply = str_new(default_pool, 256); | dict->conn.last_reply = str_new(default_pool, 256); | |||
dict->conn.dict = dict; | dict->conn.dict = dict; | |||
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); | |||
if (strchr(set->username, DICT_USERNAME_SEPARATOR) == NULL) | ||||
dict->username = i_strdup(set->username); | ||||
else { | ||||
/* escape the username */ | ||||
dict->username = i_strdup(redis_escape_username(set->username)); | ||||
} | ||||
*dict_r = &dict->dict; | *dict_r = &dict->dict; | |||
return 0; | return 0; | |||
} | } | |||
static void redis_dict_deinit(struct dict *_dict) | static void redis_dict_deinit(struct dict *_dict) | |||
{ | { | |||
struct redis_dict *dict = (struct redis_dict *)_dict; | struct redis_dict *dict = (struct redis_dict *)_dict; | |||
if (array_count(&dict->input_states) > 0) { | if (array_count(&dict->input_states) > 0) { | |||
i_assert(dict->connected); | i_assert(dict->connected); | |||
redis_wait(dict); | redis_wait(dict); | |||
} | } | |||
connection_deinit(&dict->conn.conn); | connection_deinit(&dict->conn.conn); | |||
str_free(&dict->conn.last_reply); | str_free(&dict->conn.last_reply); | |||
array_free(&dict->replies); | array_free(&dict->replies); | |||
array_free(&dict->input_states); | array_free(&dict->input_states); | |||
i_free(dict->expire_value); | i_free(dict->expire_value); | |||
i_free(dict->key_prefix); | i_free(dict->key_prefix); | |||
i_free(dict->password); | i_free(dict->password); | |||
i_free(dict->username); | ||||
i_free(dict); | i_free(dict); | |||
if (redis_connections->connections == NULL) | if (redis_connections->connections == NULL) | |||
connection_list_deinit(&redis_connections); | connection_list_deinit(&redis_connections); | |||
} | } | |||
static void redis_dict_wait(struct dict *_dict) | static void redis_dict_wait(struct dict *_dict) | |||
{ | { | |||
struct redis_dict *dict = (struct redis_dict *)_dict; | struct redis_dict *dict = (struct redis_dict *)_dict; | |||
skipping to change at line 493 | skipping to change at line 486 | |||
static void redis_dict_lookup_timeout(struct redis_dict *dict) | static void redis_dict_lookup_timeout(struct redis_dict *dict) | |||
{ | { | |||
const char *reason = t_strdup_printf( | const char *reason = t_strdup_printf( | |||
"redis: Lookup timed out in %u.%03u secs", | "redis: Lookup timed out in %u.%03u secs", | |||
dict->timeout_msecs/1000, dict->timeout_msecs%1000); | dict->timeout_msecs/1000, dict->timeout_msecs%1000); | |||
redis_disconnected(&dict->conn, reason); | redis_disconnected(&dict->conn, reason); | |||
} | } | |||
static const char * | static const char * | |||
redis_dict_get_full_key(struct redis_dict *dict, const char *key) | redis_dict_get_full_key(struct redis_dict *dict, const char *username, | |||
const char *key) | ||||
{ | { | |||
const char *username_sp = strchr(username, DICT_USERNAME_SEPARATOR); | ||||
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, | key = t_strdup_printf("%s%c%s", | |||
username_sp == NULL ? username : | ||||
redis_escape_username(username), | ||||
DICT_USERNAME_SEPARATOR, | DICT_USERNAME_SEPARATOR, | |||
key + strlen(DICT_PATH_PRIVATE)); | 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; | |||
} | } | |||
skipping to change at line 540 | skipping to change at line 538 | |||
/* 0 is the default */ | /* 0 is the default */ | |||
return; | return; | |||
} | } | |||
db_str = dec2str(dict->db_id); | db_str = dec2str(dict->db_id); | |||
cmd = t_strdup_printf("*2\r\n$6\r\nSELECT\r\n$%d\r\n%s\r\n", | cmd = t_strdup_printf("*2\r\n$6\r\nSELECT\r\n$%d\r\n%s\r\n", | |||
(int)strlen(db_str), db_str); | (int)strlen(db_str), db_str); | |||
o_stream_nsend_str(dict->conn.conn.output, cmd); | o_stream_nsend_str(dict->conn.conn.output, cmd); | |||
redis_input_state_add(dict, REDIS_INPUT_STATE_SELECT); | redis_input_state_add(dict, REDIS_INPUT_STATE_SELECT); | |||
} | } | |||
static int redis_dict_lookup(struct dict *_dict, pool_t pool, const char *key, | static int redis_dict_lookup(struct dict *_dict, | |||
const struct dict_op_settings *set, | ||||
pool_t pool, const char *key, | ||||
const char **value_r, const char **error_r) | const char **value_r, const char **error_r) | |||
{ | { | |||
struct redis_dict *dict = (struct redis_dict *)_dict; | struct redis_dict *dict = (struct redis_dict *)_dict; | |||
struct timeout *to; | struct timeout *to; | |||
const char *cmd; | const char *cmd; | |||
key = redis_dict_get_full_key(dict, key); | key = redis_dict_get_full_key(dict, set->username, key); | |||
dict->conn.value_received = FALSE; | dict->conn.value_received = FALSE; | |||
dict->conn.value_not_found = FALSE; | dict->conn.value_not_found = FALSE; | |||
i_assert(dict->dict.ioloop == NULL); | i_assert(dict->dict.ioloop == NULL); | |||
dict->dict.prev_ioloop = current_ioloop; | dict->dict.prev_ioloop = current_ioloop; | |||
dict->dict.ioloop = io_loop_create(); | dict->dict.ioloop = io_loop_create(); | |||
connection_switch_ioloop(&dict->conn.conn); | connection_switch_ioloop(&dict->conn.conn); | |||
skipping to change at line 746 | skipping to change at line 746 | |||
redis_input_state_add(dict, REDIS_INPUT_STATE_MULTI); | redis_input_state_add(dict, REDIS_INPUT_STATE_MULTI); | |||
ctx->cmd_count++; | ctx->cmd_count++; | |||
} | } | |||
static void redis_set(struct dict_transaction_context *_ctx, | static void redis_set(struct dict_transaction_context *_ctx, | |||
const char *key, const char *value) | const char *key, const char *value) | |||
{ | { | |||
struct redis_dict_transaction_context *ctx = | struct redis_dict_transaction_context *ctx = | |||
(struct redis_dict_transaction_context *)_ctx; | (struct redis_dict_transaction_context *)_ctx; | |||
struct redis_dict *dict = (struct redis_dict *)_ctx->dict; | struct redis_dict *dict = (struct redis_dict *)_ctx->dict; | |||
const struct dict_op_settings_private *set = &_ctx->set; | ||||
string_t *cmd; | string_t *cmd; | |||
if (redis_check_transaction(ctx) < 0) | if (redis_check_transaction(ctx) < 0) | |||
return; | return; | |||
key = redis_dict_get_full_key(dict, key); | key = redis_dict_get_full_key(dict, set->username, key); | |||
cmd = t_str_new(128); | cmd = t_str_new(128); | |||
str_printfa(cmd, "*3\r\n$3\r\nSET\r\n$%u\r\n%s\r\n$%u\r\n%s\r\n", | str_printfa(cmd, "*3\r\n$3\r\nSET\r\n$%u\r\n%s\r\n$%u\r\n%s\r\n", | |||
(unsigned int)strlen(key), key, | (unsigned int)strlen(key), key, | |||
(unsigned int)strlen(value), value); | (unsigned int)strlen(value), value); | |||
redis_input_state_add(dict, REDIS_INPUT_STATE_MULTI); | redis_input_state_add(dict, REDIS_INPUT_STATE_MULTI); | |||
ctx->cmd_count++; | ctx->cmd_count++; | |||
redis_append_expire(ctx, cmd, key); | redis_append_expire(ctx, cmd, key); | |||
if (o_stream_send(dict->conn.conn.output, str_data(cmd), str_len(cmd)) < 0) { | if (o_stream_send(dict->conn.conn.output, str_data(cmd), str_len(cmd)) < 0) { | |||
ctx->error = i_strdup_printf("write() failed: %s", | ctx->error = i_strdup_printf("write() failed: %s", | |||
o_stream_get_error(dict->conn.conn.output)); | o_stream_get_error(dict->conn.conn.output)); | |||
} | } | |||
} | } | |||
static void redis_unset(struct dict_transaction_context *_ctx, | static void redis_unset(struct dict_transaction_context *_ctx, | |||
const char *key) | const char *key) | |||
{ | { | |||
struct redis_dict_transaction_context *ctx = | struct redis_dict_transaction_context *ctx = | |||
(struct redis_dict_transaction_context *)_ctx; | (struct redis_dict_transaction_context *)_ctx; | |||
struct redis_dict *dict = (struct redis_dict *)_ctx->dict; | struct redis_dict *dict = (struct redis_dict *)_ctx->dict; | |||
const struct dict_op_settings_private *set = &_ctx->set; | ||||
const char *cmd; | const char *cmd; | |||
if (redis_check_transaction(ctx) < 0) | if (redis_check_transaction(ctx) < 0) | |||
return; | return; | |||
key = redis_dict_get_full_key(dict, key); | key = redis_dict_get_full_key(dict, set->username, key); | |||
cmd = t_strdup_printf("*2\r\n$3\r\nDEL\r\n$%u\r\n%s\r\n", | cmd = t_strdup_printf("*2\r\n$3\r\nDEL\r\n$%u\r\n%s\r\n", | |||
(unsigned int)strlen(key), key); | (unsigned int)strlen(key), key); | |||
if (o_stream_send_str(dict->conn.conn.output, cmd) < 0) { | if (o_stream_send_str(dict->conn.conn.output, cmd) < 0) { | |||
ctx->error = i_strdup_printf("write() failed: %s", | ctx->error = i_strdup_printf("write() failed: %s", | |||
o_stream_get_error(dict->conn.conn.output)); | o_stream_get_error(dict->conn.conn.output)); | |||
} | } | |||
redis_input_state_add(dict, REDIS_INPUT_STATE_MULTI); | redis_input_state_add(dict, REDIS_INPUT_STATE_MULTI); | |||
ctx->cmd_count++; | ctx->cmd_count++; | |||
} | } | |||
static void redis_atomic_inc(struct dict_transaction_context *_ctx, | static void redis_atomic_inc(struct dict_transaction_context *_ctx, | |||
const char *key, long long diff) | const char *key, long long diff) | |||
{ | { | |||
struct redis_dict_transaction_context *ctx = | struct redis_dict_transaction_context *ctx = | |||
(struct redis_dict_transaction_context *)_ctx; | (struct redis_dict_transaction_context *)_ctx; | |||
struct redis_dict *dict = (struct redis_dict *)_ctx->dict; | struct redis_dict *dict = (struct redis_dict *)_ctx->dict; | |||
const struct dict_op_settings_private *set = &_ctx->set; | ||||
const char *diffstr; | const char *diffstr; | |||
string_t *cmd; | string_t *cmd; | |||
if (redis_check_transaction(ctx) < 0) | if (redis_check_transaction(ctx) < 0) | |||
return; | return; | |||
key = redis_dict_get_full_key(dict, key); | key = redis_dict_get_full_key(dict, set->username, key); | |||
diffstr = t_strdup_printf("%lld", diff); | diffstr = t_strdup_printf("%lld", diff); | |||
cmd = t_str_new(128); | cmd = t_str_new(128); | |||
str_printfa(cmd, "*3\r\n$6\r\nINCRBY\r\n$%u\r\n%s\r\n$%u\r\n%s\r\n", | str_printfa(cmd, "*3\r\n$6\r\nINCRBY\r\n$%u\r\n%s\r\n$%u\r\n%s\r\n", | |||
(unsigned int)strlen(key), key, | (unsigned int)strlen(key), key, | |||
(unsigned int)strlen(diffstr), diffstr); | (unsigned int)strlen(diffstr), diffstr); | |||
redis_input_state_add(dict, REDIS_INPUT_STATE_MULTI); | redis_input_state_add(dict, REDIS_INPUT_STATE_MULTI); | |||
ctx->cmd_count++; | ctx->cmd_count++; | |||
redis_append_expire(ctx, cmd, key); | redis_append_expire(ctx, cmd, key); | |||
if (o_stream_send(dict->conn.conn.output, str_data(cmd), str_len(cmd)) < 0) { | if (o_stream_send(dict->conn.conn.output, str_data(cmd), str_len(cmd)) < 0) { | |||
ctx->error = i_strdup_printf("write() failed: %s", | ctx->error = i_strdup_printf("write() failed: %s", | |||
End of changes. 14 change blocks. | ||||
15 lines changed or deleted | 18 lines changed or added |