dict.c (dovecot-2.3.16) | : | dict.c (dovecot-2.3.17) | ||
---|---|---|---|---|
skipping to change at line 18 | skipping to change at line 18 | |||
#include "str.h" | #include "str.h" | |||
#include "ioloop.h" | #include "ioloop.h" | |||
#include "dict-private.h" | #include "dict-private.h" | |||
struct dict_commit_callback_ctx { | struct dict_commit_callback_ctx { | |||
pool_t pool; | pool_t pool; | |||
struct dict_commit_callback_ctx *prev, *next; | struct dict_commit_callback_ctx *prev, *next; | |||
struct dict *dict; | struct dict *dict; | |||
struct event *event; | struct event *event; | |||
dict_transaction_commit_callback_t *callback; | dict_transaction_commit_callback_t *callback; | |||
struct dict_op_settings_private set; | ||||
struct timeout *to; | struct timeout *to; | |||
void *context; | void *context; | |||
struct dict_commit_result result; | struct dict_commit_result result; | |||
bool delayed_callback:1; | bool delayed_callback:1; | |||
}; | }; | |||
struct dict_lookup_callback_ctx { | struct dict_lookup_callback_ctx { | |||
struct dict *dict; | struct dict *dict; | |||
struct event *event; | struct event *event; | |||
dict_lookup_callback_t *callback; | dict_lookup_callback_t *callback; | |||
skipping to change at line 95 | skipping to change at line 96 | |||
array_free(&dict_drivers); | array_free(&dict_drivers); | |||
} | } | |||
int dict_init(const char *uri, const struct dict_settings *set, | int dict_init(const char *uri, const struct dict_settings *set, | |||
struct dict **dict_r, const char **error_r) | struct dict **dict_r, const char **error_r) | |||
{ | { | |||
struct dict_settings set_dup = *set; | struct dict_settings set_dup = *set; | |||
struct dict *dict; | struct dict *dict; | |||
const char *p, *name, *error; | const char *p, *name, *error; | |||
i_assert(set->username != NULL); | ||||
p = strchr(uri, ':'); | p = strchr(uri, ':'); | |||
if (p == NULL) { | if (p == NULL) { | |||
*error_r = t_strdup_printf("Dictionary URI is missing ':': %s", | *error_r = t_strdup_printf("Dictionary URI is missing ':': %s", | |||
uri); | uri); | |||
return -1; | return -1; | |||
} | } | |||
name = t_strdup_until(uri, p); | name = t_strdup_until(uri, p); | |||
dict = dict_driver_lookup(name); | dict = dict_driver_lookup(name); | |||
if (dict == NULL) { | if (dict == NULL) { | |||
*error_r = t_strdup_printf("Unknown dict module: %s", name); | *error_r = t_strdup_printf("Unknown dict module: %s", name); | |||
return -1; | return -1; | |||
} | } | |||
struct event *event = event_create(set->event_parent); | struct event *event = event_create(set->event_parent); | |||
event_add_category(event, &event_category_dict); | event_add_category(event, &event_category_dict); | |||
event_add_str(event, "driver", dict->name); | event_add_str(event, "driver", dict->name); | |||
if (set->username[0] != '\0') | event_set_append_log_prefix(event, t_strdup_printf("dict(%s): ", | |||
event_add_str(event, "user", set->username); | dict->name)); | |||
event_set_append_log_prefix(event, t_strdup_printf("dict(%s)<%s>: ", | ||||
dict->name, set->username)); | ||||
set_dup.event_parent = event; | set_dup.event_parent = event; | |||
if (dict->v.init(dict, p+1, &set_dup, dict_r, &error) < 0) { | if (dict->v.init(dict, p+1, &set_dup, dict_r, &error) < 0) { | |||
*error_r = t_strdup_printf("dict %s: %s", name, error); | *error_r = t_strdup_printf("dict %s: %s", name, error); | |||
event_unref(&event); | event_unref(&event); | |||
return -1; | return -1; | |||
} | } | |||
i_assert(*dict_r != NULL); | i_assert(*dict_r != NULL); | |||
(*dict_r)->refcount++; | (*dict_r)->refcount++; | |||
(*dict_r)->event = event; | (*dict_r)->event = event; | |||
e_debug(event_create_passthrough(event)->set_name("dict_created")->event( | ||||
), | ||||
"dict created (uri=%s, base_dir=%s)", uri, set->base_dir); | ||||
return 0; | return 0; | |||
} | } | |||
static void dict_ref(struct dict *dict) | static void dict_ref(struct dict *dict) | |||
{ | { | |||
i_assert(dict->refcount > 0); | i_assert(dict->refcount > 0); | |||
dict->refcount++; | dict->refcount++; | |||
} | } | |||
skipping to change at line 147 | skipping to change at line 146 | |||
static void dict_unref(struct dict **_dict) | static void dict_unref(struct dict **_dict) | |||
{ | { | |||
struct dict *dict = *_dict; | struct dict *dict = *_dict; | |||
*_dict = NULL; | *_dict = NULL; | |||
if (dict == NULL) | if (dict == NULL) | |||
return; | return; | |||
struct event *event = dict->event; | struct event *event = dict->event; | |||
i_assert(dict->refcount > 0); | i_assert(dict->refcount > 0); | |||
if (--dict->refcount == 0) { | if (--dict->refcount == 0) { | |||
dict->v.deinit(dict); | dict->v.deinit(dict); | |||
e_debug(event_create_passthrough(event)-> | ||||
set_name("dict_destroyed")->event(), "dict destroyed"); | ||||
event_unref(&event); | event_unref(&event); | |||
} | } | |||
} | } | |||
void dict_deinit(struct dict **_dict) | void dict_deinit(struct dict **_dict) | |||
{ | { | |||
struct dict *dict = *_dict; | struct dict *dict = *_dict; | |||
*_dict = NULL; | *_dict = NULL; | |||
skipping to change at line 193 | skipping to change at line 194 | |||
commit->to = io_loop_move_timeout(&commit->to); | commit->to = io_loop_move_timeout(&commit->to); | |||
ret = TRUE; | ret = TRUE; | |||
} | } | |||
if (dict->v.switch_ioloop != NULL) { | if (dict->v.switch_ioloop != NULL) { | |||
if (dict->v.switch_ioloop(dict)) | if (dict->v.switch_ioloop(dict)) | |||
return TRUE; | return TRUE; | |||
} | } | |||
return ret; | return ret; | |||
} | } | |||
static bool dict_key_prefix_is_valid(const char *key) | static bool dict_key_prefix_is_valid(const char *key, const char *username) | |||
{ | { | |||
return str_begins(key, DICT_PATH_SHARED) || | if (str_begins(key, DICT_PATH_SHARED)) | |||
str_begins(key, DICT_PATH_PRIVATE); | return TRUE; | |||
if (str_begins(key, DICT_PATH_PRIVATE)) { | ||||
i_assert(username != NULL && username[0] != '\0'); | ||||
return TRUE; | ||||
} | ||||
return FALSE; | ||||
} | } | |||
void dict_pre_api_callback(struct dict *dict) | void dict_pre_api_callback(struct dict *dict) | |||
{ | { | |||
if (dict->prev_ioloop != NULL) { | if (dict->prev_ioloop != NULL) { | |||
/* Don't let callback see that we've created our | /* Don't let callback see that we've created our | |||
internal ioloop in case it wants to add some ios | internal ioloop in case it wants to add some ios | |||
or timeouts. */ | or timeouts. */ | |||
io_loop_set_current(dict->prev_ioloop); | io_loop_set_current(dict->prev_ioloop); | |||
} | } | |||
skipping to change at line 277 | skipping to change at line 284 | |||
DLLIST_REMOVE(&ctx->dict->commits, ctx); | DLLIST_REMOVE(&ctx->dict->commits, ctx); | |||
timeout_remove(&ctx->to); | timeout_remove(&ctx->to); | |||
dict_pre_api_callback(ctx->dict); | dict_pre_api_callback(ctx->dict); | |||
if (ctx->callback != NULL) | if (ctx->callback != NULL) | |||
ctx->callback(&ctx->result, ctx->context); | ctx->callback(&ctx->result, ctx->context); | |||
else if (ctx->result.ret < 0) | else if (ctx->result.ret < 0) | |||
e_error(ctx->event, "Commit failed: %s", ctx->result.error); | e_error(ctx->event, "Commit failed: %s", ctx->result.error); | |||
dict_post_api_callback(ctx->dict); | dict_post_api_callback(ctx->dict); | |||
dict_transaction_finished(ctx->event, ctx->result.ret, FALSE, ctx->result .error); | dict_transaction_finished(ctx->event, ctx->result.ret, FALSE, ctx->result .error); | |||
dict_op_settings_private_free(&ctx->set); | ||||
event_unref(&ctx->event); | event_unref(&ctx->event); | |||
dict_unref(&ctx->dict); | dict_unref(&ctx->dict); | |||
pool_unref(&ctx->pool); | pool_unref(&ctx->pool); | |||
} | } | |||
static void dict_commit_callback(const struct dict_commit_result *result, | static void dict_commit_callback(const struct dict_commit_result *result, | |||
void *context) | void *context) | |||
{ | { | |||
struct dict_commit_callback_ctx *ctx = context; | struct dict_commit_callback_ctx *ctx = context; | |||
i_assert(result->ret >= 0 || result->error != NULL); | i_assert(result->ret >= 0 || result->error != NULL); | |||
ctx->result = *result; | ctx->result = *result; | |||
if (ctx->delayed_callback) { | if (ctx->delayed_callback) { | |||
ctx->result.error = p_strdup(ctx->pool, ctx->result.error); | ctx->result.error = p_strdup(ctx->pool, ctx->result.error); | |||
ctx->to = timeout_add_short(0, dict_commit_async_timeout, ctx); | ctx->to = timeout_add_short(0, dict_commit_async_timeout, ctx); | |||
} else { | } else { | |||
dict_commit_async_timeout(ctx); | dict_commit_async_timeout(ctx); | |||
} | } | |||
} | } | |||
int dict_lookup(struct dict *dict, pool_t pool, const char *key, | static struct event * | |||
const char **value_r, const char **error_r) | dict_event_create(struct dict *dict, const struct dict_op_settings *set) | |||
{ | { | |||
struct event *event = event_create(dict->event); | struct event *event = event_create(dict->event); | |||
if (set->username != NULL) | ||||
event_add_str(event, "user", set->username); | ||||
return event; | ||||
} | ||||
int 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) | ||||
{ | ||||
struct event *event = dict_event_create(dict, set); | ||||
int ret; | int ret; | |||
i_assert(dict_key_prefix_is_valid(key)); | i_assert(dict_key_prefix_is_valid(key, set->username)); | |||
e_debug(event, "Looking up '%s'", key); | e_debug(event, "Looking up '%s'", key); | |||
event_add_str(event, "key", key); | event_add_str(event, "key", key); | |||
ret = dict->v.lookup(dict, pool, key, value_r, error_r); | ret = dict->v.lookup(dict, set, pool, key, value_r, error_r); | |||
dict_lookup_finished(event, ret, *error_r); | dict_lookup_finished(event, ret, *error_r); | |||
event_unref(&event); | event_unref(&event); | |||
return ret; | return ret; | |||
} | } | |||
#undef dict_lookup_async | #undef dict_lookup_async | |||
void dict_lookup_async(struct dict *dict, const char *key, | void 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) | ||||
{ | { | |||
if (dict->v.lookup_async == NULL) { | if (dict->v.lookup_async == NULL) { | |||
struct dict_lookup_result result; | struct dict_lookup_result result; | |||
i_zero(&result); | i_zero(&result); | |||
/* event is going to be sent by dict_lookup */ | /* event is going to be sent by dict_lookup */ | |||
result.ret = dict_lookup(dict, pool_datastack_create(), | result.ret = dict_lookup(dict, set, pool_datastack_create(), | |||
key, &result.value, &result.error); | key, &result.value, &result.error); | |||
const char *const values[] = { result.value, NULL }; | const char *const values[] = { result.value, NULL }; | |||
result.values = values; | result.values = values; | |||
callback(&result, context); | callback(&result, context); | |||
return; | return; | |||
} | } | |||
struct dict_lookup_callback_ctx *lctx = | struct dict_lookup_callback_ctx *lctx = | |||
i_new(struct dict_lookup_callback_ctx, 1); | i_new(struct dict_lookup_callback_ctx, 1); | |||
lctx->dict = dict; | lctx->dict = dict; | |||
dict_ref(lctx->dict); | dict_ref(lctx->dict); | |||
lctx->callback = callback; | lctx->callback = callback; | |||
lctx->context = context; | lctx->context = context; | |||
lctx->event = event_create(dict->event); | lctx->event = dict_event_create(dict, set); | |||
event_add_str(lctx->event, "key", key); | event_add_str(lctx->event, "key", key); | |||
e_debug(lctx->event, "Looking up (async) '%s'", key); | e_debug(lctx->event, "Looking up (async) '%s'", key); | |||
dict->v.lookup_async(dict, key, dict_lookup_callback, lctx); | dict->v.lookup_async(dict, set, key, dict_lookup_callback, lctx); | |||
} | } | |||
struct dict_iterate_context * | struct dict_iterate_context * | |||
dict_iterate_init(struct dict *dict, const char *path, | dict_iterate_init(struct dict *dict, const struct dict_op_settings *set, | |||
enum dict_iterate_flags flags) | const char *path, enum dict_iterate_flags flags) | |||
{ | ||||
const char *paths[2]; | ||||
paths[0] = path; | ||||
paths[1] = NULL; | ||||
return dict_iterate_init_multiple(dict, paths, flags); | ||||
} | ||||
struct dict_iterate_context * | ||||
dict_iterate_init_multiple(struct dict *dict, const char *const *paths, | ||||
enum dict_iterate_flags flags) | ||||
{ | { | |||
struct dict_iterate_context *ctx; | struct dict_iterate_context *ctx; | |||
unsigned int i; | ||||
i_assert(paths[0] != NULL); | i_assert(path != NULL); | |||
for (i = 0; paths[i] != NULL; i++) | i_assert(dict_key_prefix_is_valid(path, set->username)); | |||
i_assert(dict_key_prefix_is_valid(paths[i])); | ||||
if (dict->v.iterate_init == NULL) { | if (dict->v.iterate_init == NULL) { | |||
/* not supported by backend */ | /* not supported by backend */ | |||
ctx = &dict_iter_unsupported; | ctx = &dict_iter_unsupported; | |||
} else { | } else { | |||
ctx = dict->v.iterate_init(dict, paths, flags); | ctx = dict->v.iterate_init(dict, set, path, flags); | |||
} | } | |||
/* the dict in context can differ from the dict | /* the dict in context can differ from the dict | |||
passed as parameter, e.g. it can be dict-fail when | passed as parameter, e.g. it can be dict-fail when | |||
iteration is not supported. */ | iteration is not supported. */ | |||
ctx->event = event_create(dict->event); | ctx->event = dict_event_create(dict, set); | |||
ctx->flags = flags; | ctx->flags = flags; | |||
dict_op_settings_dup(set, &ctx->set); | ||||
event_add_str(ctx->event, "key", paths[0]); | event_add_str(ctx->event, "key", path); | |||
event_set_name(ctx->event, "dict_iteration_started"); | event_set_name(ctx->event, "dict_iteration_started"); | |||
e_debug(ctx->event, "Iterating prefix %s", paths[0]); | e_debug(ctx->event, "Iterating prefix %s", path); | |||
ctx->dict->iter_count++; | ctx->dict->iter_count++; | |||
return ctx; | return ctx; | |||
} | } | |||
bool dict_iterate(struct dict_iterate_context *ctx, | bool dict_iterate(struct dict_iterate_context *ctx, | |||
const char **key_r, const char **value_r) | const char **key_r, const char **value_r) | |||
{ | { | |||
const char *const *values; | const char *const *values; | |||
if (!dict_iterate_values(ctx, key_r, &values)) | if (!dict_iterate_values(ctx, key_r, &values)) | |||
skipping to change at line 454 | skipping to change at line 461 | |||
struct event *event = ctx->event; | struct event *event = ctx->event; | |||
int ret; | int ret; | |||
uint64_t rows; | uint64_t rows; | |||
i_assert(ctx->dict->iter_count > 0); | i_assert(ctx->dict->iter_count > 0); | |||
ctx->dict->iter_count--; | ctx->dict->iter_count--; | |||
*_ctx = NULL; | *_ctx = NULL; | |||
rows = ctx->row_count; | rows = ctx->row_count; | |||
struct dict_op_settings_private set_copy = ctx->set; | ||||
ret = ctx->dict->v.iterate_deinit(ctx, error_r); | ret = ctx->dict->v.iterate_deinit(ctx, error_r); | |||
dict_op_settings_private_free(&set_copy); | ||||
event_add_int(event, "rows", rows); | event_add_int(event, "rows", rows); | |||
event_set_name(event, "dict_iteration_finished"); | event_set_name(event, "dict_iteration_finished"); | |||
if (ret < 0) { | if (ret < 0) { | |||
event_add_str(event, "error", *error_r); | event_add_str(event, "error", *error_r); | |||
e_debug(event, "Iteration finished: %s", *error_r); | e_debug(event, "Iteration finished: %s", *error_r); | |||
} else { | } else { | |||
if (rows == 0) | if (rows == 0) | |||
event_add_str(event, "key_not_found", "yes"); | event_add_str(event, "key_not_found", "yes"); | |||
e_debug(event, "Iteration finished, got %"PRIu64" rows", rows); | e_debug(event, "Iteration finished, got %"PRIu64" rows", rows); | |||
} | } | |||
event_unref(&event); | event_unref(&event); | |||
return ret; | return ret; | |||
} | } | |||
struct dict_transaction_context *dict_transaction_begin(struct dict *dict) | struct dict_transaction_context * | |||
dict_transaction_begin(struct dict *dict, const struct dict_op_settings *set) | ||||
{ | { | |||
struct dict_transaction_context *ctx; | struct dict_transaction_context *ctx; | |||
guid_128_t guid; | guid_128_t guid; | |||
if (dict->v.transaction_init == NULL) | if (dict->v.transaction_init == NULL) | |||
ctx = &dict_transaction_unsupported; | ctx = &dict_transaction_unsupported; | |||
else | else | |||
ctx = dict->v.transaction_init(dict); | ctx = dict->v.transaction_init(dict); | |||
/* the dict in context can differ from the dict | /* the dict in context can differ from the dict | |||
passed as parameter, e.g. it can be dict-fail when | passed as parameter, e.g. it can be dict-fail when | |||
transactions are not supported. */ | transactions are not supported. */ | |||
ctx->dict->transaction_count++; | ctx->dict->transaction_count++; | |||
DLLIST_PREPEND(&ctx->dict->transactions, ctx); | DLLIST_PREPEND(&ctx->dict->transactions, ctx); | |||
ctx->event = event_create(dict->event); | ctx->event = dict_event_create(dict, set); | |||
dict_op_settings_dup(set, &ctx->set); | ||||
guid_128_generate(guid); | guid_128_generate(guid); | |||
event_add_str(ctx->event, "txid", guid_128_to_string(guid)); | event_add_str(ctx->event, "txid", guid_128_to_string(guid)); | |||
event_set_name(ctx->event, "dict_transaction_started"); | event_set_name(ctx->event, "dict_transaction_started"); | |||
e_debug(ctx->event, "Starting transaction"); | e_debug(ctx->event, "Starting transaction"); | |||
return ctx; | return ctx; | |||
} | } | |||
void dict_transaction_no_slowness_warning(struct dict_transaction_context *ctx) | void dict_transaction_no_slowness_warning(struct dict_transaction_context *ctx) | |||
{ | { | |||
ctx->no_slowness_warning = TRUE; | ctx->no_slowness_warning = TRUE; | |||
skipping to change at line 555 | skipping to change at line 566 | |||
i_zero(&result); | i_zero(&result); | |||
i_assert(ctx->dict->transaction_count > 0); | i_assert(ctx->dict->transaction_count > 0); | |||
ctx->dict->transaction_count--; | ctx->dict->transaction_count--; | |||
DLLIST_REMOVE(&ctx->dict->transactions, ctx); | DLLIST_REMOVE(&ctx->dict->transactions, ctx); | |||
DLLIST_PREPEND(&ctx->dict->commits, cctx); | DLLIST_PREPEND(&ctx->dict->commits, cctx); | |||
cctx->dict = ctx->dict; | cctx->dict = ctx->dict; | |||
dict_ref(cctx->dict); | dict_ref(cctx->dict); | |||
cctx->callback = dict_transaction_commit_sync_callback; | cctx->callback = dict_transaction_commit_sync_callback; | |||
cctx->context = &result; | cctx->context = &result; | |||
cctx->event = ctx->event; | cctx->event = ctx->event; | |||
cctx->set = ctx->set; | ||||
ctx->dict->v.transaction_commit(ctx, FALSE, dict_commit_callback, cctx); | ctx->dict->v.transaction_commit(ctx, FALSE, dict_commit_callback, cctx); | |||
*error_r = t_strdup(result.error); | *error_r = t_strdup(result.error); | |||
i_free(result.error); | i_free(result.error); | |||
return result.ret; | return result.ret; | |||
} | } | |||
#undef dict_transaction_commit_async | #undef dict_transaction_commit_async | |||
void dict_transaction_commit_async(struct dict_transaction_context **_ctx, | void dict_transaction_commit_async(struct dict_transaction_context **_ctx, | |||
dict_transaction_commit_callback_t *callback, | dict_transaction_commit_callback_t *callback, | |||
skipping to change at line 585 | skipping to change at line 597 | |||
DLLIST_REMOVE(&ctx->dict->transactions, ctx); | DLLIST_REMOVE(&ctx->dict->transactions, ctx); | |||
DLLIST_PREPEND(&ctx->dict->commits, cctx); | DLLIST_PREPEND(&ctx->dict->commits, cctx); | |||
if (callback == NULL) | if (callback == NULL) | |||
callback = dict_transaction_commit_async_noop_callback; | callback = dict_transaction_commit_async_noop_callback; | |||
cctx->pool = pool; | cctx->pool = pool; | |||
cctx->dict = ctx->dict; | cctx->dict = ctx->dict; | |||
dict_ref(cctx->dict); | dict_ref(cctx->dict); | |||
cctx->callback = callback; | cctx->callback = callback; | |||
cctx->context = context; | cctx->context = context; | |||
cctx->event = ctx->event; | cctx->event = ctx->event; | |||
cctx->set = ctx->set; | ||||
cctx->delayed_callback = TRUE; | cctx->delayed_callback = TRUE; | |||
ctx->dict->v.transaction_commit(ctx, TRUE, dict_commit_callback, cctx); | ctx->dict->v.transaction_commit(ctx, TRUE, dict_commit_callback, cctx); | |||
cctx->delayed_callback = FALSE; | cctx->delayed_callback = FALSE; | |||
} | } | |||
void dict_transaction_commit_async_nocallback( | void dict_transaction_commit_async_nocallback( | |||
struct dict_transaction_context **ctx) | struct dict_transaction_context **ctx) | |||
{ | { | |||
dict_transaction_commit_async(ctx, NULL, NULL); | dict_transaction_commit_async(ctx, NULL, NULL); | |||
} | } | |||
skipping to change at line 609 | skipping to change at line 622 | |||
if (ctx == NULL) | if (ctx == NULL) | |||
return; | return; | |||
struct event *event = ctx->event; | struct event *event = ctx->event; | |||
*_ctx = NULL; | *_ctx = NULL; | |||
i_assert(ctx->dict->transaction_count > 0); | i_assert(ctx->dict->transaction_count > 0); | |||
ctx->dict->transaction_count--; | ctx->dict->transaction_count--; | |||
DLLIST_REMOVE(&ctx->dict->transactions, ctx); | DLLIST_REMOVE(&ctx->dict->transactions, ctx); | |||
struct dict_op_settings_private set_copy = ctx->set; | ||||
ctx->dict->v.transaction_rollback(ctx); | ctx->dict->v.transaction_rollback(ctx); | |||
dict_transaction_finished(event, DICT_COMMIT_RET_OK, TRUE, NULL); | dict_transaction_finished(event, DICT_COMMIT_RET_OK, TRUE, NULL); | |||
dict_op_settings_private_free(&set_copy); | ||||
event_unref(&event); | event_unref(&event); | |||
} | } | |||
void dict_set(struct dict_transaction_context *ctx, | void dict_set(struct dict_transaction_context *ctx, | |||
const char *key, const char *value) | const char *key, const char *value) | |||
{ | { | |||
i_assert(dict_key_prefix_is_valid(key)); | i_assert(dict_key_prefix_is_valid(key, ctx->set.username)); | |||
struct event_passthrough *e = event_create_passthrough(ctx->event)-> | struct event_passthrough *e = event_create_passthrough(ctx->event)-> | |||
set_name("dict_set_key")-> | set_name("dict_set_key")-> | |||
add_str("key", key); | add_str("key", key); | |||
e_debug(e->event(), "Setting '%s' to '%s'", key, value); | e_debug(e->event(), "Setting '%s' to '%s'", key, value); | |||
T_BEGIN { | T_BEGIN { | |||
ctx->dict->v.set(ctx, key, value); | ctx->dict->v.set(ctx, key, value); | |||
} T_END; | } T_END; | |||
ctx->changed = TRUE; | ctx->changed = TRUE; | |||
} | } | |||
void dict_unset(struct dict_transaction_context *ctx, | void dict_unset(struct dict_transaction_context *ctx, | |||
const char *key) | const char *key) | |||
{ | { | |||
i_assert(dict_key_prefix_is_valid(key)); | i_assert(dict_key_prefix_is_valid(key, ctx->set.username)); | |||
struct event_passthrough *e = event_create_passthrough(ctx->event)-> | struct event_passthrough *e = event_create_passthrough(ctx->event)-> | |||
set_name("dict_unset_key")-> | set_name("dict_unset_key")-> | |||
add_str("key", key); | add_str("key", key); | |||
e_debug(e->event(), "Unsetting '%s'", key); | e_debug(e->event(), "Unsetting '%s'", key); | |||
T_BEGIN { | T_BEGIN { | |||
ctx->dict->v.unset(ctx, key); | ctx->dict->v.unset(ctx, key); | |||
} T_END; | } T_END; | |||
ctx->changed = TRUE; | ctx->changed = TRUE; | |||
} | } | |||
void dict_atomic_inc(struct dict_transaction_context *ctx, | void dict_atomic_inc(struct dict_transaction_context *ctx, | |||
const char *key, long long diff) | const char *key, long long diff) | |||
{ | { | |||
i_assert(dict_key_prefix_is_valid(key)); | i_assert(dict_key_prefix_is_valid(key, ctx->set.username)); | |||
struct event_passthrough *e = event_create_passthrough(ctx->event)-> | struct event_passthrough *e = event_create_passthrough(ctx->event)-> | |||
set_name("dict_increment_key")-> | set_name("dict_increment_key")-> | |||
add_str("key", key); | add_str("key", key); | |||
e_debug(e->event(), "Incrementing '%s' with %lld", key, diff); | e_debug(e->event(), "Incrementing '%s' with %lld", key, diff); | |||
if (diff != 0) T_BEGIN { | if (diff != 0) T_BEGIN { | |||
ctx->dict->v.atomic_inc(ctx, key, diff); | ctx->dict->v.atomic_inc(ctx, key, diff); | |||
ctx->changed = TRUE; | ctx->changed = TRUE; | |||
} T_END; | } T_END; | |||
skipping to change at line 730 | skipping to change at line 745 | |||
if (*++p == '|') | if (*++p == '|') | |||
str_append_c(ret, '/'); | str_append_c(ret, '/'); | |||
else if (*p == '\0') | else if (*p == '\0') | |||
break; | break; | |||
else | else | |||
str_append_c(ret, *p); | str_append_c(ret, *p); | |||
} | } | |||
} | } | |||
return str_c(ret); | return str_c(ret); | |||
} | } | |||
void dict_op_settings_dup(const struct dict_op_settings *source, | ||||
struct dict_op_settings_private *dest_r) | ||||
{ | ||||
i_zero(dest_r); | ||||
dest_r->username = i_strdup(source->username); | ||||
dest_r->home_dir = i_strdup(source->home_dir); | ||||
} | ||||
void dict_op_settings_private_free(struct dict_op_settings_private *set) | ||||
{ | ||||
i_free(set->username); | ||||
i_free(set->home_dir); | ||||
} | ||||
End of changes. 36 change blocks. | ||||
44 lines changed or deleted | 60 lines changed or added |