dict-client.c (dovecot-2.3.16) | : | dict-client.c (dovecot-2.3.17) | ||
---|---|---|---|---|
skipping to change at line 75 | skipping to change at line 75 | |||
struct dict_client_connection { | struct dict_client_connection { | |||
struct connection conn; | struct connection conn; | |||
struct client_dict *dict; | struct client_dict *dict; | |||
}; | }; | |||
struct client_dict { | struct client_dict { | |||
struct dict dict; | struct dict dict; | |||
struct dict_client_connection conn; | struct dict_client_connection conn; | |||
char *uri, *username; | char *uri; | |||
enum dict_data_type value_type; | enum dict_data_type value_type; | |||
unsigned warn_slow_msecs; | unsigned warn_slow_msecs; | |||
time_t last_failed_connect; | time_t last_failed_connect; | |||
char *last_connect_error; | char *last_connect_error; | |||
struct io_wait_timer *wait_timer; | struct io_wait_timer *wait_timer; | |||
uint64_t last_timer_switch_usecs; | uint64_t last_timer_switch_usecs; | |||
struct timeout *to_requests; | struct timeout *to_requests; | |||
struct timeout *to_idle; | struct timeout *to_idle; | |||
skipping to change at line 101 | skipping to change at line 101 | |||
unsigned int transaction_id_counter; | unsigned int transaction_id_counter; | |||
}; | }; | |||
struct client_dict_iter_result { | struct client_dict_iter_result { | |||
const char *key, *const *values; | const char *key, *const *values; | |||
}; | }; | |||
struct client_dict_iterate_context { | struct client_dict_iterate_context { | |||
struct dict_iterate_context ctx; | struct dict_iterate_context ctx; | |||
char *error; | char *error; | |||
const char **paths; | char *path; | |||
enum dict_iterate_flags flags; | enum dict_iterate_flags flags; | |||
int refcount; | int refcount; | |||
pool_t results_pool; | pool_t results_pool; | |||
ARRAY(struct client_dict_iter_result) results; | ARRAY(struct client_dict_iter_result) results; | |||
unsigned int result_idx; | unsigned int result_idx; | |||
bool cmd_sent; | bool cmd_sent; | |||
bool seen_results; | bool seen_results; | |||
bool finished; | bool finished; | |||
skipping to change at line 346 | skipping to change at line 346 | |||
dict->to_requests = | dict->to_requests = | |||
timeout_add(DICT_CLIENT_REQUEST_TIMEOUT_MSECS, | timeout_add(DICT_CLIENT_REQUEST_TIMEOUT_MSECS, | |||
client_dict_input_timeout, dict); | client_dict_input_timeout, dict); | |||
} | } | |||
array_push_back(&dict->cmds, &cmd); | array_push_back(&dict->cmds, &cmd); | |||
return TRUE; | return TRUE; | |||
} | } | |||
} | } | |||
static bool | static bool | |||
client_dict_transaction_send_begin(struct client_dict_transaction_context *ctx) | client_dict_transaction_send_begin(struct client_dict_transaction_context *ctx, | |||
const struct dict_op_settings_private *set) | ||||
{ | { | |||
struct client_dict *dict = (struct client_dict *)ctx->ctx.dict; | struct client_dict *dict = (struct client_dict *)ctx->ctx.dict; | |||
struct client_dict_cmd *cmd; | struct client_dict_cmd *cmd; | |||
const char *query, *error; | const char *query, *error; | |||
i_assert(ctx->error == NULL); | i_assert(ctx->error == NULL); | |||
ctx->sent_begin = TRUE; | ctx->sent_begin = TRUE; | |||
/* transactions commands don't have replies. only COMMIT has. */ | /* transactions commands don't have replies. only COMMIT has. */ | |||
query = t_strdup_printf("%c%u", DICT_PROTOCOL_CMD_BEGIN, ctx->id); | query = t_strdup_printf("%c%u\t%s", DICT_PROTOCOL_CMD_BEGIN, | |||
ctx->id, | ||||
set->username == NULL ? "" : str_tabescape(set->u | ||||
sername)); | ||||
cmd = client_dict_cmd_init(dict, query); | cmd = client_dict_cmd_init(dict, query); | |||
cmd->no_replies = TRUE; | cmd->no_replies = TRUE; | |||
cmd->retry_errors = TRUE; | cmd->retry_errors = TRUE; | |||
if (!client_dict_cmd_send(dict, &cmd, &error)) { | if (!client_dict_cmd_send(dict, &cmd, &error)) { | |||
ctx->error = i_strdup(error); | ctx->error = i_strdup(error); | |||
return FALSE; | return FALSE; | |||
} | } | |||
return TRUE; | return TRUE; | |||
} | } | |||
static void | static void | |||
client_dict_send_transaction_query(struct client_dict_transaction_context *ctx, | client_dict_send_transaction_query(struct client_dict_transaction_context *ctx, | |||
const char *query) | const char *query) | |||
{ | { | |||
struct client_dict *dict = (struct client_dict *)ctx->ctx.dict; | struct client_dict *dict = (struct client_dict *)ctx->ctx.dict; | |||
const struct dict_op_settings_private *set = &ctx->ctx.set; | ||||
struct client_dict_cmd *cmd; | struct client_dict_cmd *cmd; | |||
const char *error; | const char *error; | |||
if (ctx->error != NULL) | if (ctx->error != NULL) | |||
return; | return; | |||
if (!ctx->sent_begin) { | if (!ctx->sent_begin) { | |||
if (!client_dict_transaction_send_begin(ctx)) | if (!client_dict_transaction_send_begin(ctx, set)) | |||
return; | return; | |||
} | } | |||
ctx->query_count++; | ctx->query_count++; | |||
if (ctx->first_query == NULL) | if (ctx->first_query == NULL) | |||
ctx->first_query = i_strdup(query); | ctx->first_query = i_strdup(query); | |||
cmd = client_dict_cmd_init(dict, query); | cmd = client_dict_cmd_init(dict, query); | |||
cmd->no_replies = TRUE; | cmd->no_replies = TRUE; | |||
if (!client_dict_cmd_send(dict, &cmd, &error)) | if (!client_dict_cmd_send(dict, &cmd, &error)) | |||
skipping to change at line 583 | skipping to change at line 587 | |||
i_free(dict->last_connect_error); | i_free(dict->last_connect_error); | |||
dict->last_connect_error = i_strdup(error); | dict->last_connect_error = i_strdup(error); | |||
*error_r = error; | *error_r = error; | |||
return -1; | return -1; | |||
} | } | |||
query = t_strdup_printf("%c%u\t%u\t%d\t%s\t%s\n", | query = t_strdup_printf("%c%u\t%u\t%d\t%s\t%s\n", | |||
DICT_PROTOCOL_CMD_HELLO, | DICT_PROTOCOL_CMD_HELLO, | |||
DICT_CLIENT_PROTOCOL_MAJOR_VERSION, | DICT_CLIENT_PROTOCOL_MAJOR_VERSION, | |||
DICT_CLIENT_PROTOCOL_MINOR_VERSION, | DICT_CLIENT_PROTOCOL_MINOR_VERSION, | |||
dict->value_type, dict->username, dict->uri); | dict->value_type, | |||
"", | ||||
str_tabescape(dict->uri)); | ||||
o_stream_nsend_str(dict->conn.conn.output, query); | o_stream_nsend_str(dict->conn.conn.output, query); | |||
client_dict_add_timeout(dict); | client_dict_add_timeout(dict); | |||
return 0; | return 0; | |||
} | } | |||
static void | static void | |||
client_dict_abort_commands(struct client_dict *dict, const char *reason) | client_dict_abort_commands(struct client_dict *dict, const char *reason) | |||
{ | { | |||
ARRAY(struct client_dict_cmd *) cmds_copy; | ARRAY(struct client_dict_cmd *) cmds_copy; | |||
struct client_dict_cmd *cmd; | struct client_dict_cmd *cmd; | |||
skipping to change at line 751 | skipping to change at line 757 | |||
if (dict_connections == NULL) { | if (dict_connections == NULL) { | |||
dict_connections = connection_list_init(&dict_conn_set, | dict_connections = connection_list_init(&dict_conn_set, | |||
&dict_conn_vfuncs); | &dict_conn_vfuncs); | |||
} | } | |||
dict = i_new(struct client_dict, 1); | dict = i_new(struct client_dict, 1); | |||
dict->dict = *driver; | dict->dict = *driver; | |||
dict->conn.dict = dict; | dict->conn.dict = dict; | |||
dict->conn.conn.event_parent = set->event_parent; | dict->conn.conn.event_parent = set->event_parent; | |||
dict->value_type = set->value_type; | ||||
dict->username = i_strdup(set->username); | ||||
dict->idle_msecs = idle_msecs; | dict->idle_msecs = idle_msecs; | |||
dict->warn_slow_msecs = warn_slow_msecs; | dict->warn_slow_msecs = warn_slow_msecs; | |||
i_array_init(&dict->cmds, 32); | i_array_init(&dict->cmds, 32); | |||
if (uri[0] == ':') { | if (uri[0] == ':') { | |||
/* default path */ | /* default path */ | |||
path = t_strconcat(set->base_dir, | path = t_strconcat(set->base_dir, | |||
"/"DEFAULT_DICT_SERVER_SOCKET_FNAME, NULL); | "/"DEFAULT_DICT_SERVER_SOCKET_FNAME, NULL); | |||
} else if (uri[0] == '/') { | } else if (uri[0] == '/') { | |||
/* absolute path */ | /* absolute path */ | |||
skipping to change at line 797 | skipping to change at line 801 | |||
i_assert(dict->transactions == NULL); | i_assert(dict->transactions == NULL); | |||
i_assert(array_count(&dict->cmds) == 0); | i_assert(array_count(&dict->cmds) == 0); | |||
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); | |||
array_free(&dict->cmds); | array_free(&dict->cmds); | |||
i_free(dict->last_connect_error); | i_free(dict->last_connect_error); | |||
i_free(dict->username); | ||||
i_free(dict->uri); | i_free(dict->uri); | |||
i_free(dict); | i_free(dict); | |||
if (dict_connections->connections == NULL) | if (dict_connections->connections == NULL) | |||
connection_list_deinit(&dict_connections); | connection_list_deinit(&dict_connections); | |||
} | } | |||
static void client_dict_wait(struct dict *_dict) | static void client_dict_wait(struct dict *_dict) | |||
{ | { | |||
struct client_dict *dict = (struct client_dict *)_dict; | struct client_dict *dict = (struct client_dict *)_dict; | |||
skipping to change at line 966 | skipping to change at line 969 | |||
dict_warnings_sec(cmd, diff, extra_args), | dict_warnings_sec(cmd, diff, extra_args), | |||
cmd->query); | cmd->query); | |||
} | } | |||
dict_pre_api_callback(&dict->dict); | dict_pre_api_callback(&dict->dict); | |||
cmd->api_callback.lookup(&result, cmd->api_callback.context); | cmd->api_callback.lookup(&result, cmd->api_callback.context); | |||
dict_post_api_callback(&dict->dict); | dict_post_api_callback(&dict->dict); | |||
} | } | |||
static void | static void | |||
client_dict_lookup_async(struct dict *_dict, const char *key, | client_dict_lookup_async(struct dict *_dict, const struct dict_op_settings *set, | |||
dict_lookup_callback_t *callback, void *context) | const char *key, dict_lookup_callback_t *callback, | |||
void *context) | ||||
{ | { | |||
struct client_dict *dict = (struct client_dict *)_dict; | struct client_dict *dict = (struct client_dict *)_dict; | |||
struct client_dict_cmd *cmd; | struct client_dict_cmd *cmd; | |||
const char *query; | const char *query; | |||
query = t_strdup_printf("%c%s", DICT_PROTOCOL_CMD_LOOKUP, | query = t_strdup_printf("%c%s\t%s", DICT_PROTOCOL_CMD_LOOKUP, | |||
str_tabescape(key)); | str_tabescape(key), | |||
set->username == NULL ? "" : str_tabescape(set->u | ||||
sername)); | ||||
cmd = client_dict_cmd_init(dict, query); | cmd = client_dict_cmd_init(dict, query); | |||
cmd->callback = client_dict_lookup_async_callback; | cmd->callback = client_dict_lookup_async_callback; | |||
cmd->api_callback.lookup = callback; | cmd->api_callback.lookup = callback; | |||
cmd->api_callback.context = context; | cmd->api_callback.context = context; | |||
cmd->retry_errors = TRUE; | cmd->retry_errors = TRUE; | |||
client_dict_cmd_send(dict, &cmd, NULL); | client_dict_cmd_send(dict, &cmd, NULL); | |||
} | } | |||
struct client_dict_sync_lookup { | struct client_dict_sync_lookup { | |||
skipping to change at line 1000 | skipping to change at line 1005 | |||
static void client_dict_lookup_callback(const struct dict_lookup_result *result, | static void client_dict_lookup_callback(const struct dict_lookup_result *result, | |||
struct client_dict_sync_lookup *lookup) | struct client_dict_sync_lookup *lookup) | |||
{ | { | |||
lookup->ret = result->ret; | lookup->ret = result->ret; | |||
if (result->ret == -1) | if (result->ret == -1) | |||
lookup->error = i_strdup(result->error); | lookup->error = i_strdup(result->error); | |||
else if (result->ret == 1) | else if (result->ret == 1) | |||
lookup->value = i_strdup(result->value); | lookup->value = i_strdup(result->value); | |||
} | } | |||
static int client_dict_lookup(struct dict *_dict, pool_t pool, const char *key, | static int client_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 client_dict_sync_lookup lookup; | struct client_dict_sync_lookup lookup; | |||
i_zero(&lookup); | i_zero(&lookup); | |||
lookup.ret = -2; | lookup.ret = -2; | |||
dict_lookup_async(_dict, key, client_dict_lookup_callback, &lookup); | dict_lookup_async(_dict, set, key, client_dict_lookup_callback, &lookup); | |||
if (lookup.ret == -2) | if (lookup.ret == -2) | |||
client_dict_wait(_dict); | client_dict_wait(_dict); | |||
switch (lookup.ret) { | switch (lookup.ret) { | |||
case -1: | case -1: | |||
*error_r = t_strdup(lookup.error); | *error_r = t_strdup(lookup.error); | |||
i_free(lookup.error); | i_free(lookup.error); | |||
return -1; | return -1; | |||
case 0: | case 0: | |||
i_assert(lookup.value == NULL); | i_assert(lookup.value == NULL); | |||
skipping to change at line 1147 | skipping to change at line 1154 | |||
} | } | |||
result = array_append_space(&ctx->results); | result = array_append_space(&ctx->results); | |||
result->key = p_strdup(ctx->results_pool, iter_key); | result->key = p_strdup(ctx->results_pool, iter_key); | |||
result->values = p_strarray_dup(ctx->results_pool, iter_values); | result->values = p_strarray_dup(ctx->results_pool, iter_values); | |||
client_dict_iter_api_callback(ctx, cmd, NULL); | client_dict_iter_api_callback(ctx, cmd, NULL); | |||
} | } | |||
static struct dict_iterate_context * | static struct dict_iterate_context * | |||
client_dict_iterate_init(struct dict *_dict, const char *const *paths, | client_dict_iterate_init(struct dict *_dict, | |||
enum dict_iterate_flags flags) | const struct dict_op_settings *set ATTR_UNUSED, | |||
const char *path, enum dict_iterate_flags flags) | ||||
{ | { | |||
struct client_dict_iterate_context *ctx; | struct client_dict_iterate_context *ctx; | |||
ctx = i_new(struct client_dict_iterate_context, 1); | ctx = i_new(struct client_dict_iterate_context, 1); | |||
ctx->ctx.dict = _dict; | ctx->ctx.dict = _dict; | |||
ctx->results_pool = pool_alloconly_create("client dict iteration", 512); | ctx->results_pool = pool_alloconly_create("client dict iteration", 512); | |||
ctx->flags = flags; | ctx->flags = flags; | |||
ctx->paths = p_strarray_dup(system_pool, paths); | ctx->path = i_strdup(path); | |||
ctx->refcount = 1; | ctx->refcount = 1; | |||
i_array_init(&ctx->results, 64); | i_array_init(&ctx->results, 64); | |||
return &ctx->ctx; | return &ctx->ctx; | |||
} | } | |||
static void | static void | |||
client_dict_iterate_cmd_send(struct client_dict_iterate_context *ctx) | client_dict_iterate_cmd_send(struct client_dict_iterate_context *ctx) | |||
{ | { | |||
struct client_dict *dict = (struct client_dict *)ctx->ctx.dict; | struct client_dict *dict = (struct client_dict *)ctx->ctx.dict; | |||
const struct dict_op_settings_private *set = &ctx->ctx.set; | ||||
struct client_dict_cmd *cmd; | struct client_dict_cmd *cmd; | |||
unsigned int i; | ||||
string_t *query = t_str_new(256); | string_t *query = t_str_new(256); | |||
/* we can't do this query in _iterate_init(), because | /* we can't do this query in _iterate_init(), because | |||
_set_limit() hasn't been called yet at that point. */ | _set_limit() hasn't been called yet at that point. */ | |||
str_printfa(query, "%c%d\t%"PRIu64, DICT_PROTOCOL_CMD_ITERATE, | str_printfa(query, "%c%d\t%"PRIu64, DICT_PROTOCOL_CMD_ITERATE, | |||
ctx->flags, ctx->ctx.max_rows); | ctx->flags, ctx->ctx.max_rows); | |||
for (i = 0; ctx->paths[i] != NULL; i++) { | str_append_c(query, '\t'); | |||
str_append_c(query, '\t'); | str_append_tabescaped(query, ctx->path); | |||
str_append(query, str_tabescape(ctx->paths[i])); | str_append_c(query, '\t'); | |||
} | str_append_tabescaped(query, set->username == NULL ? "" : set->username); | |||
cmd = client_dict_cmd_init(dict, str_c(query)); | cmd = client_dict_cmd_init(dict, str_c(query)); | |||
cmd->iter = ctx; | cmd->iter = ctx; | |||
cmd->callback = client_dict_iter_async_callback; | cmd->callback = client_dict_iter_async_callback; | |||
cmd->retry_errors = TRUE; | cmd->retry_errors = TRUE; | |||
ctx->refcount++; | ctx->refcount++; | |||
client_dict_cmd_send(dict, &cmd, NULL); | client_dict_cmd_send(dict, &cmd, NULL); | |||
} | } | |||
skipping to change at line 1241 | skipping to change at line 1249 | |||
struct client_dict_iterate_context *ctx = | struct client_dict_iterate_context *ctx = | |||
(struct client_dict_iterate_context *)_ctx; | (struct client_dict_iterate_context *)_ctx; | |||
int ret = ctx->error != NULL ? -1 : 0; | int ret = ctx->error != NULL ? -1 : 0; | |||
i_assert(!ctx->deinit); | i_assert(!ctx->deinit); | |||
ctx->deinit = TRUE; | ctx->deinit = TRUE; | |||
*error_r = t_strdup(ctx->error); | *error_r = t_strdup(ctx->error); | |||
array_free(&ctx->results); | array_free(&ctx->results); | |||
pool_unref(&ctx->results_pool); | pool_unref(&ctx->results_pool); | |||
i_free(ctx->paths); | i_free(ctx->path); | |||
client_dict_iterate_unref(ctx); | client_dict_iterate_unref(ctx); | |||
client_dict_add_timeout(dict); | client_dict_add_timeout(dict); | |||
return ret; | return ret; | |||
} | } | |||
static struct dict_transaction_context * | static struct dict_transaction_context * | |||
client_dict_transaction_init(struct dict *_dict) | client_dict_transaction_init(struct dict *_dict) | |||
{ | { | |||
struct client_dict *dict = (struct client_dict *)_dict; | struct client_dict *dict = (struct client_dict *)_dict; | |||
End of changes. 19 change blocks. | ||||
24 lines changed or deleted | 34 lines changed or added |