]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-dict: dict_lookup() returns now error string
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Fri, 6 May 2016 09:33:11 +0000 (12:33 +0300)
committerGitLab <gitlab@git.dovecot.net>
Sun, 8 May 2016 21:29:56 +0000 (00:29 +0300)
17 files changed:
src/auth/db-dict.c
src/doveadm/doveadm-dict.c
src/lib-dict-extra/dict-fs.c
src/lib-dict-extra/dict-ldap.c
src/lib-dict/dict-client.c
src/lib-dict/dict-file.c
src/lib-dict/dict-memcached-ascii.c
src/lib-dict/dict-memcached.c
src/lib-dict/dict-private.h
src/lib-dict/dict-redis.c
src/lib-dict/dict-sql.c
src/lib-dict/dict.c
src/lib-dict/dict.h
src/lib-fs/fs-dict.c
src/lib-storage/index/index-attribute.c
src/plugins/expire/expire-plugin.c
src/plugins/quota/quota-dict.c

index 95cd53c207d07c4105fca219671828d79b9293d6..baaebf02b906d6a754b0d3cfa230dcaa8a555bec 100644 (file)
@@ -397,6 +397,7 @@ static int db_dict_iter_lookup_key_values(struct db_dict_value_iter *iter)
 {
        struct db_dict_iter_key *key;
        string_t *path;
+       const char *error;
        int ret;
 
        /* sort the keys so that we'll first lookup the keys without
@@ -413,14 +414,14 @@ static int db_dict_iter_lookup_key_values(struct db_dict_value_iter *iter)
                str_truncate(path, strlen(DICT_PATH_SHARED));
                var_expand(path, key->key->key, iter->var_expand_table);
                ret = dict_lookup(iter->conn->dict, iter->pool,
-                                 str_c(path), &key->value);
+                                 str_c(path), &key->value, &error);
                if (ret > 0) {
                        auth_request_log_debug(iter->auth_request, AUTH_SUBSYS_DB,
                                               "Lookup: %s = %s", str_c(path),
                                               key->value);
                } else if (ret < 0) {
                        auth_request_log_error(iter->auth_request, AUTH_SUBSYS_DB,
-                               "Failed to lookup key %s", str_c(path));
+                               "Failed to lookup key %s: %s", str_c(path), error);
                        return -1;
                } else if (key->key->default_value != NULL) {
                        auth_request_log_debug(iter->auth_request, AUTH_SUBSYS_DB,
index 59853dbe31362fc9c299c36dc9fbd5dc411eaf48..e266ce9e2138b9c45e857a5f0662c95125b6f365 100644 (file)
@@ -95,7 +95,7 @@ cmd_dict_init(int *argc, char **argv[],
 static void cmd_dict_get(int argc, char *argv[])
 {
        struct dict *dict;
-       const char *value;
+       const char *value, *error;
        int ret;
 
        if (cmd_dict_init(&argc, &argv, 1, 0, cmd_dict_get, &dict) < 0)
@@ -104,9 +104,9 @@ static void cmd_dict_get(int argc, char *argv[])
        doveadm_print_init(DOVEADM_PRINT_TYPE_TABLE);
        doveadm_print_header("value", "", DOVEADM_PRINT_HEADER_FLAG_HIDE_TITLE);
 
-       ret = dict_lookup(dict, pool_datastack_create(), argv[0], &value);
+       ret = dict_lookup(dict, pool_datastack_create(), argv[0], &value, &error);
        if (ret < 0) {
-               i_error("dict_lookup(%s) failed", argv[0]);
+               i_error("dict_lookup(%s) failed: %s", argv[0], error);
                doveadm_exit_code = EX_TEMPFAIL;
        } else if (ret == 0) {
                i_error("%s doesn't exist", argv[0]);
index 7a524ce7c85cf17d2cca236109fc36217dc7f0ee..91a40f92c87958da7bbc1589462dfb2951f0167f 100644 (file)
@@ -79,19 +79,20 @@ static const char *fs_dict_get_full_key(struct fs_dict *dict, const char *key)
        }
 }
 
-static int fs_dict_lookup(struct dict *_dict, pool_t pool,
-                         const char *key, const char **value_r)
+static int fs_dict_lookup(struct dict *_dict, pool_t pool, const char *key,
+                         const char **value_r, const char **error_r)
 {
        struct fs_dict *dict = (struct fs_dict *)_dict;
        struct fs_file *file;
        struct istream *input;
        const unsigned char *data;
        size_t size;
+       const char *path;
        string_t *str;
        int ret;
 
-       file = fs_file_init(dict->fs, fs_dict_get_full_key(dict, key),
-                           FS_OPEN_MODE_READONLY);
+       path = fs_dict_get_full_key(dict, key);
+       file = fs_file_init(dict->fs, path, FS_OPEN_MODE_READONLY);
        input = fs_read_stream(file, IO_BLOCK_SIZE);
        i_stream_read(input);
 
@@ -109,6 +110,10 @@ static int fs_dict_lookup(struct dict *_dict, pool_t pool,
                *value_r = NULL;
                if (input->stream_errno == ENOENT)
                        ret = 0;
+               else {
+                       *error_r = t_strdup_printf("read(%s) failed: %s",
+                               path, i_stream_get_error(input));
+               }
        }
 
        i_stream_unref(&input);
@@ -145,7 +150,7 @@ static bool fs_dict_iterate(struct dict_iterate_context *ctx,
        struct fs_dict_iterate_context *iter =
                (struct fs_dict_iterate_context *)ctx;
        struct fs_dict *dict = (struct fs_dict *)ctx->dict;
-       const char *path;
+       const char *path, *error;
        int ret;
 
        *key_r = fs_iter_next(iter->fs_iter);
@@ -166,8 +171,9 @@ static bool fs_dict_iterate(struct dict_iterate_context *ctx,
        }
        p_clear(iter->value_pool);
        path = t_strconcat(iter->paths[iter->path_idx], *key_r, NULL);
-       if ((ret = fs_dict_lookup(ctx->dict, iter->value_pool, path, value_r)) < 0) {
+       if ((ret = fs_dict_lookup(ctx->dict, iter->value_pool, path, value_r, &error)) < 0) {
                /* I/O error */
+               i_error("%s", error);
                iter->failed = TRUE;
                return FALSE;
        } else if (ret == 0) {
index 6d460d063dbd7003175d8cd067a7355541c56aa8..9dd151bf712ba2a3241aead4f7f666bd4df24e9e 100644 (file)
@@ -301,22 +301,25 @@ ldap_dict_lookup_callback(struct ldap_result *result, struct dict_ldap_op *op)
        pool_unref(&pool);
 }
 
-static
-int ldap_dict_lookup(struct dict *dict, pool_t pool,
-                     const char *key, const char **value_r)
+static int
+ldap_dict_lookup(struct dict *dict, pool_t pool, const char *key,
+                const char **value_r, const char **error_r)
 {
        struct dict_lookup_result res;
-       pool_t orig_pool = pool;
-       int ret;
 
        ldap_dict_lookup_async(dict, key, ldap_dict_lookup_done, &res);
 
-       if ((ret = ldap_dict_wait(dict)) == 0) {
-               if (res.ret == 0) {
-                       *value_r = p_strdup(orig_pool, res.value);
-               } else ret = res.ret;
+       if (ldap_dict_wait(dict) < 0) {
+               *error_r = "ldap: Communication failure";
+               return -1;
+       }
+       if (res.ret < 0) {
+               *error_r = res.error;
+               return -1;
        }
-       return ret;
+       if (res.ret > 0)
+               *value_r = p_strdup(pool, res.value);
+       return res.ret;
 }
 
 /*
index 7c7f75b90df73a6c4634b779d23b5ac0d8b32135..157273e59af89b60c96b0328963028e486d51caf 100644 (file)
@@ -78,7 +78,7 @@ struct client_dict_transaction_context {
        unsigned int committed:1;
 };
 
-static int client_dict_connect(struct client_dict *dict);
+static int client_dict_connect(struct client_dict *dict, const char **error_r);
 static void client_dict_disconnect(struct client_dict *dict);
 
 const char *dict_client_escape(const char *src)
@@ -159,11 +159,12 @@ const char *dict_client_unescape(const char *src)
        return str_c(dest);
 }
 
-static int client_dict_send_query(struct client_dict *dict, const char *query)
+static int client_dict_send_query(struct client_dict *dict, const char *query,
+                                 const char **error_r)
 {
        if (dict->output == NULL) {
                /* not connected currently */
-               if (client_dict_connect(dict) < 0)
+               if (client_dict_connect(dict, error_r) < 0)
                        return -1;
        }
 
@@ -172,17 +173,20 @@ static int client_dict_send_query(struct client_dict *dict, const char *query)
                /* Send failed */
                if (!dict->handshaked) {
                        /* we're trying to send hello, don't try to reconnect */
+                       *error_r = t_strdup_printf("write(%s) failed: %s",
+                               dict->path, o_stream_get_error(dict->output));
                        return -1;
                }
 
                /* Reconnect and try again. */
                client_dict_disconnect(dict);
-               if (client_dict_connect(dict) < 0)
+               if (client_dict_connect(dict, error_r) < 0)
                        return -1;
 
                if (o_stream_send_str(dict->output, query) < 0 ||
                    o_stream_flush(dict->output) < 0) {
-                       i_error("write(%s) failed: %m", dict->path);
+                       *error_r = t_strdup_printf("write(%s) failed: %s",
+                               dict->path, o_stream_get_error(dict->output));
                        client_dict_disconnect(dict);
                        return -1;
                }
@@ -194,18 +198,19 @@ static int
 client_dict_transaction_send_begin(struct client_dict_transaction_context *ctx)
 {
        struct client_dict *dict = (struct client_dict *)ctx->ctx.dict;
+       const char *query, *error;
 
        if (ctx->failed)
                return -1;
 
-       const char *query;
-
        query = t_strdup_printf("%c%u\n", DICT_PROTOCOL_CMD_BEGIN, ctx->id);
-       if (client_dict_send_query(dict, query) < 0)
+       if (client_dict_send_query(dict, query, &error) < 0) {
+               i_error("%s", error);
                ctx->failed = TRUE;
-       else
-               ctx->connect_counter = dict->connect_counter;
-       return ctx->failed ? -1 : 0;
+               return -1;
+       }
+       ctx->connect_counter = dict->connect_counter;
+       return 0;
 }
 
 static int ATTR_NOWARN_UNUSED_RESULT
@@ -312,7 +317,8 @@ static ssize_t client_dict_read_timeout(struct client_dict *dict)
 }
 
 static int
-client_dict_read_one_line_real(struct client_dict *dict, char **line_r)
+client_dict_read_one_line_real(struct client_dict *dict, char **line_r,
+                              const char **error_r)
 {
        unsigned int id;
        char *line;
@@ -323,18 +329,16 @@ client_dict_read_one_line_real(struct client_dict *dict, char **line_r)
                ret = client_dict_read_timeout(dict);
                switch (ret) {
                case -1:
-                       if (dict->input->stream_errno != 0)
-                               i_error("read(%s) failed: %m", dict->path);
-                       else {
-                               i_error("read(%s) failed: Remote disconnected",
-                                       dict->path);
-                       }
+                       *error_r = t_strdup_printf("read(%s) failed: %s",
+                               dict->path, i_stream_get_disconnect_reason(dict->input));
                        return -1;
                case -2:
-                       i_error("read(%s) returned too much data", dict->path);
+                       *error_r = t_strdup_printf(
+                               "read(%s) returned too much data", dict->path);
                        return -1;
                case 0:
-                       i_error("read(%s) failed: Timeout after %u seconds",
+                       *error_r = t_strdup_printf(
+                               "read(%s) failed: Timeout after %u seconds",
                                dict->path, DICT_CLIENT_READ_TIMEOUT_SECS);
                        return -1;
                default:
@@ -354,12 +358,12 @@ client_dict_read_one_line_real(struct client_dict *dict, char **line_r)
                        ret = -1;
                        break;
                default:
-                       i_error("dict-client: Invalid async commit line: %s",
-                               line);
+                       *error_r = t_strdup_printf(
+                               "dict-client: Invalid async commit line: %s", line);
                        return -1;
                }
                if (str_to_uint(line+2, &id) < 0) {
-                       i_error("dict-client: Invalid ID");
+                       *error_r = t_strdup_printf("dict-client: Invalid ID");
                        return -1;
                }
                client_dict_finish_transaction(dict, id, ret);
@@ -371,8 +375,8 @@ client_dict_read_one_line_real(struct client_dict *dict, char **line_r)
                if (*line == DICT_PROTOCOL_REPLY_OK)
                        return 0;
                if (*line != '\0' && *line != DICT_PROTOCOL_REPLY_FAIL) {
-                       i_error("dict-client: Invalid iteration reply line: %s",
-                               line);
+                       *error_r = t_strdup_printf(
+                               "dict-client: Invalid iteration reply line: %s", line);
                        return -1;
                }
                dict->iter_replies_skip--;
@@ -382,11 +386,12 @@ client_dict_read_one_line_real(struct client_dict *dict, char **line_r)
        return 1;
 }
 
-static int client_dict_read_one_line(struct client_dict *dict, char **line_r)
+static int client_dict_read_one_line(struct client_dict *dict, char **line_r,
+                                    const char **error_r)
 {
        int ret;
 
-       if ((ret = client_dict_read_one_line_real(dict, line_r)) < 0)
+       if ((ret = client_dict_read_one_line_real(dict, line_r, error_r)) < 0)
                client_dict_disconnect(dict);
        return ret;
 }
@@ -414,23 +419,26 @@ static void client_dict_add_timeout(struct client_dict *dict)
        }
 }
 
-static char *client_dict_read_line(struct client_dict *dict)
+static int client_dict_read_line(struct client_dict *dict,
+                                char **line_r, const char **error_r)
 {
-       char *line;
+       int ret;
 
-       while (client_dict_read_one_line(dict, &line) == 0)
+       while ((ret = client_dict_read_one_line(dict, line_r, error_r)) == 0)
                ;
+       i_assert(ret < 0 || *line_r != NULL);
 
        client_dict_add_timeout(dict);
-       return line;
+       return ret < 0 ? -1 : 0;
 }
 
-static int client_dict_connect(struct client_dict *dict)
+static int client_dict_connect(struct client_dict *dict, const char **error_r)
 {
        const char *query;
 
        if (dict->last_failed_connect == ioloop_time) {
                /* Try again later */
+               *error_r = "Waiting until the next connect attempt";
                return -1;
        }
 
@@ -438,11 +446,11 @@ static int client_dict_connect(struct client_dict *dict)
        if (dict->fd == -1) {
                dict->last_failed_connect = ioloop_time;
                if (errno == EACCES) {
-                       i_error("%s", eacces_error_get("net_connect_unix",
-                                                      dict->path));
+                       *error_r = eacces_error_get("net_connect_unix",
+                                                   dict->path);
                } else {
-                       i_error("net_connect_unix(%s) failed: %m",
-                               dict->path);
+                       *error_r = t_strdup_printf(
+                               "net_connect_unix(%s) failed: %m", dict->path);
                }
                return -1;
        }
@@ -458,7 +466,7 @@ static int client_dict_connect(struct client_dict *dict)
                                DICT_CLIENT_PROTOCOL_MAJOR_VERSION,
                                DICT_CLIENT_PROTOCOL_MINOR_VERSION,
                                dict->value_type, dict->username, dict->uri);
-       if (client_dict_send_query(dict, query) < 0) {
+       if (client_dict_send_query(dict, query, error_r) < 0) {
                dict->last_failed_connect = ioloop_time;
                client_dict_disconnect(dict);
                return -1;
@@ -567,6 +575,7 @@ static void client_dict_deinit(struct dict *_dict)
 static int client_dict_wait(struct dict *_dict)
 {
        struct client_dict *dict = (struct client_dict *)_dict;
+       const char *error;
        char *line;
        int ret;
 
@@ -574,8 +583,10 @@ static int client_dict_wait(struct dict *_dict)
                return -1;
 
        while (dict->async_commits > 0) {
-               if ((ret = client_dict_read_one_line(dict, &line)) < 0)
+               if ((ret = client_dict_read_one_line(dict, &line, &error)) < 0) {
+                       i_error("%s", error);
                        return -1;
+               }
 
                if (ret > 0) {
                        i_error("dict-client: Unexpected reply waiting waiting for async commits: %s", line);
@@ -586,20 +597,20 @@ static int client_dict_wait(struct dict *_dict)
        return 0;
 }
 
-static int client_dict_lookup(struct dict *_dict, pool_t pool,
-                             const char *key, const char **value_r)
+static int client_dict_lookup(struct dict *_dict, pool_t pool, const char *key,
+                             const char **value_r, const char **error_r)
 {
        struct client_dict *dict = (struct client_dict *)_dict;
-       const char *query, *line;
+       const char *query;
+       char *line;
 
        query = t_strdup_printf("%c%s\n", DICT_PROTOCOL_CMD_LOOKUP,
                                dict_client_escape(key));
-       if (client_dict_send_query(dict, query) < 0)
+       if (client_dict_send_query(dict, query, error_r) < 0)
                return -1;
 
        /* read reply */
-       line = client_dict_read_line(dict);
-       if (line == NULL)
+       if (client_dict_read_line(dict, &line, error_r) < 0)
                return -1;
 
        switch (*line) {
@@ -610,9 +621,11 @@ static int client_dict_lookup(struct dict *_dict, pool_t pool,
                *value_r = NULL;
                return 0;
        case DICT_PROTOCOL_REPLY_FAIL:
+               *error_r = "dict-server returned failure";
                return -1;
        default:
-               i_error("dict-client: Invalid lookup '%s' reply: %s", key, line);
+               *error_r = t_strdup_printf(
+                       "dict-client: Invalid lookup '%s' reply: %s", key, line);
                client_dict_disconnect(dict);
                return -1;
        }
@@ -626,6 +639,7 @@ client_dict_iterate_init(struct dict *_dict, const char *const *paths,
         struct client_dict_iterate_context *ctx;
        string_t *query = t_str_new(256);
        unsigned int i;
+       const char *error;
 
        if (dict->in_iteration)
                i_panic("dict-client: Only one iteration supported");
@@ -641,8 +655,10 @@ client_dict_iterate_init(struct dict *_dict, const char *const *paths,
                        str_append(query, dict_client_escape(paths[i]));
        }
        str_append_c(query, '\n');
-       if (client_dict_send_query(dict, str_c(query)) < 0)
+       if (client_dict_send_query(dict, str_c(query), &error) < 0) {
+               i_error("%s", error);
                ctx->failed = TRUE;
+       }
        return &ctx->ctx;
 }
 
@@ -653,13 +669,14 @@ static bool client_dict_iterate(struct dict_iterate_context *_ctx,
                (struct client_dict_iterate_context *)_ctx;
        struct client_dict *dict = (struct client_dict *)_ctx->dict;
        char *line, *key, *value;
+       const char *error;
 
        if (ctx->failed)
                return FALSE;
 
        /* read next reply */
-       line = client_dict_read_line(dict);
-       if (line == NULL) {
+       if (client_dict_read_line(dict, &line, &error) < 0) {
+               i_error("%s", error);
                ctx->failed = TRUE;
                return FALSE;
        }
@@ -733,18 +750,20 @@ client_dict_transaction_init(struct dict *_dict)
 
 static void dict_async_input(struct client_dict *dict)
 {
+       const char *error;
        char *line;
        int ret;
 
        i_assert(!dict->in_iteration);
 
        do {
-               ret = client_dict_read_one_line(dict, &line);
+               ret = client_dict_read_one_line(dict, &line, &error);
        } while (ret == 0 && i_stream_get_data_size(dict->input) > 0);
 
-       if (ret < 0)
+       if (ret < 0) {
+               i_error("%s", error);
                io_remove(&dict->io);
-       else if (ret > 0) {
+       else if (ret > 0) {
                i_error("dict-client: Unexpected reply waiting waiting for async commits: %s", line);
                client_dict_disconnect(dict);
        }
@@ -764,7 +783,8 @@ client_dict_transaction_commit(struct dict_transaction_context *_ctx,
 
        ctx->committed = TRUE;
        if (ctx->sent_begin && !ctx->failed) {
-               const char *query, *line;
+               const char *query, *error;
+               char *line;
 
                query = t_strdup_printf("%c%u\n", !async ?
                                        DICT_PROTOCOL_CMD_COMMIT :
@@ -782,10 +802,10 @@ client_dict_transaction_commit(struct dict_transaction_context *_ctx,
                        }
                } else {
                        /* sync commit, read reply */
-                       line = client_dict_read_line(dict);
-                       if (line == NULL)
+                       if (client_dict_read_line(dict, &line, &error) < 0) {
+                               i_error("%s", error);
                                ret = -1;
-                       else switch (*line) {
+                       else switch (*line) {
                        case DICT_PROTOCOL_REPLY_OK:
                                ret = 1;
                                break;
index 10dd409c959a41dec6a1c8a060cc78560303a69d..ee735a40408cba89948ea906d9a3d4ee2c4b7b15 100644 (file)
@@ -136,7 +136,7 @@ static bool file_dict_need_refresh(struct file_dict *dict)
        return FALSE;
 }
 
-static int file_dict_open_latest(struct file_dict *dict)
+static int file_dict_open_latest(struct file_dict *dict, const char **error_r)
 {
        int open_type;
 
@@ -155,21 +155,21 @@ static int file_dict_open_latest(struct file_dict *dict)
                if (errno == ENOENT)
                        return 0;
                if (errno == EACCES)
-                       i_error("%s", eacces_error_get("open", dict->path));
+                       *error_r = eacces_error_get("open", dict->path);
                else
-                       i_error("open(%s) failed: %m", dict->path);
+                       *error_r = t_strdup_printf("open(%s) failed: %m", dict->path);
                return -1;
        }
        dict->refreshed = FALSE;
        return 1;
 }
 
-static int file_dict_refresh(struct file_dict *dict)
+static int file_dict_refresh(struct file_dict *dict, const char **error_r)
 {
        struct istream *input;
        char *key, *value;
 
-       if (file_dict_open_latest(dict) < 0)
+       if (file_dict_open_latest(dict, error_r) < 0)
                return -1;
        if (dict->refreshed)
                return 0;
@@ -196,12 +196,12 @@ static int file_dict_refresh(struct file_dict *dict)
        return 0;
 }
 
-static int file_dict_lookup(struct dict *_dict, pool_t pool,
-                           const char *key, const char **value_r)
+static int file_dict_lookup(struct dict *_dict, pool_t pool, const char *key,
+                           const char **value_r, const char **error_r)
 {
        struct file_dict *dict = (struct file_dict *)_dict;
 
-       if (file_dict_refresh(dict) < 0)
+       if (file_dict_refresh(dict, error_r) < 0)
                return -1;
 
        *value_r = p_strdup(pool, hash_table_lookup(dict->hash, key));
@@ -215,6 +215,7 @@ file_dict_iterate_init(struct dict *_dict, const char *const *paths,
         struct file_dict_iterate_context *ctx;
        struct file_dict *dict = (struct file_dict *)_dict;
        unsigned int i, path_count;
+       const char *error;
        pool_t pool;
 
        pool = pool_alloconly_create("file dict iterate", 256);
@@ -231,8 +232,10 @@ file_dict_iterate_init(struct dict *_dict, const char *const *paths,
        ctx->flags = flags;
        ctx->iter = hash_table_iterate_init(dict->hash);
 
-       if (file_dict_refresh(dict) < 0)
+       if (file_dict_refresh(dict, &error) < 0) {
+               i_error("%s", error);
                ctx->failed = TRUE;
+       }
        return &ctx->ctx;
 }
 
@@ -425,7 +428,7 @@ fd_copy_parent_dir_permissions(const char *src_path, int dest_fd,
        return fd_copy_stat_permissions(&src_st, dest_fd, dest_path);
 }
 
-static int file_dict_mkdir(struct file_dict *dict)
+static int file_dict_mkdir(struct file_dict *dict, const char **error_r)
 {
        const char *path, *p, *root;
        struct stat st;
@@ -438,9 +441,9 @@ static int file_dict_mkdir(struct file_dict *dict)
 
        if (stat_first_parent(path, &root, &st) < 0) {
                if (errno == EACCES)
-                       i_error("%s", eacces_error_get("stat", root));
+                       *error_r = eacces_error_get("stat", root);
                else
-                       i_error("stat(%s) failed: %m", root);
+                       *error_r = t_strdup_printf("stat(%s) failed: %m", root);
                return -1;
        }
        if ((st.st_mode & S_ISGID) != 0) {
@@ -450,35 +453,38 @@ static int file_dict_mkdir(struct file_dict *dict)
 
        if (mkdir_parents(path, mode) < 0 && errno != EEXIST) {
                if (errno == EACCES)
-                       i_error("%s", eacces_error_get("mkdir_parents", path));
+                       *error_r = eacces_error_get("mkdir_parents", path);
                else
-                       i_error("mkdir_parents(%s) failed: %m", path);
+                       *error_r = t_strdup_printf("mkdir_parents(%s) failed: %m", path);
                return -1;
        }
        return 0;
 }
 
 static int
-file_dict_lock(struct file_dict *dict, struct file_lock **lock_r)
+file_dict_lock(struct file_dict *dict, struct file_lock **lock_r,
+              const char **error_r)
 {
        int ret;
 
-       if (file_dict_open_latest(dict) < 0)
+       if (file_dict_open_latest(dict, error_r) < 0)
                return -1;
 
        if (dict->fd == -1) {
                /* quota file doesn't exist yet, we need to create it */
                dict->fd = open(dict->path, O_CREAT | O_RDWR, 0600);
                if (dict->fd == -1 && errno == ENOENT) {
-                       if (file_dict_mkdir(dict) < 0)
+                       if (file_dict_mkdir(dict, error_r) < 0)
                                return -1;
                        dict->fd = open(dict->path, O_CREAT | O_RDWR, 0600);
                }
                if (dict->fd == -1) {
                        if (errno == EACCES)
-                               i_error("%s", eacces_error_get("creat", dict->path));
-                       else
-                               i_error("creat(%s) failed: %m", dict->path);
+                               *error_r = eacces_error_get("creat", dict->path);
+                       else {
+                               *error_r = t_strdup_printf(
+                                       "creat(%s) failed: %m", dict->path);
+                       }
                        return -1;
                }
                (void)fd_copy_parent_dir_permissions(dict->path, dict->fd,
@@ -490,12 +496,13 @@ file_dict_lock(struct file_dict *dict, struct file_lock **lock_r)
                                   dict->lock_method,
                                   file_dict_dotlock_settings.timeout,
                                   lock_r) <= 0) {
-                       i_error("file_wait_lock(%s) failed: %m", dict->path);
+                       *error_r = t_strdup_printf(
+                               "file_wait_lock(%s) failed: %m", dict->path);
                        return -1;
                }
                /* check again if we need to reopen the file because it was
                   just replaced */
-       } while ((ret = file_dict_open_latest(dict)) > 0);
+       } while ((ret = file_dict_open_latest(dict, error_r)) > 0);
 
        return ret < 0 ? -1 : 0;
 }
@@ -509,6 +516,7 @@ static int file_dict_write_changes(struct dict_transaction_memory_context *ctx,
        const char *temp_path = NULL;
        struct hash_iterate_context *iter;
        struct ostream *output;
+       const char *error;
        char *key, *value;
        string_t *str;
        int fd = -1;
@@ -518,8 +526,10 @@ static int file_dict_write_changes(struct dict_transaction_memory_context *ctx,
        switch (dict->lock_method) {
        case FILE_LOCK_METHOD_FCNTL:
        case FILE_LOCK_METHOD_FLOCK:
-               if (file_dict_lock(dict, &lock) < 0)
+               if (file_dict_lock(dict, &lock, &error) < 0) {
+                       i_error("%s", error);
                        return -1;
+               }
                temp_path = t_strdup_printf("%s.tmp", dict->path);
                fd = creat(temp_path, 0600);
                if (fd == -1) {
@@ -532,8 +542,10 @@ static int file_dict_write_changes(struct dict_transaction_memory_context *ctx,
                fd = file_dotlock_open(&file_dict_dotlock_settings, dict->path, 0,
                                       &dotlock);
                if (fd == -1 && errno == ENOENT) {
-                       if (file_dict_mkdir(dict) < 0)
+                       if (file_dict_mkdir(dict, &error) < 0) {
+                               i_error("%s", error);
                                return -1;
+                       }
                        fd = file_dotlock_open(&file_dict_dotlock_settings,
                                               dict->path, 0, &dotlock);
                }
@@ -547,7 +559,8 @@ static int file_dict_write_changes(struct dict_transaction_memory_context *ctx,
        }
 
        /* refresh once more now that we're locked */
-       if (file_dict_refresh(dict) < 0) {
+       if (file_dict_refresh(dict, &error) < 0) {
+               i_error("%s", error);
                if (dotlock != NULL)
                        file_dotlock_delete(&dotlock);
                else {
index 1e36cac5c383ae3bdcdfdec316fab7acc3c53f71..ecc7be9b39c51818cacdfff3a1d64010be5cf823 100644 (file)
@@ -121,7 +121,8 @@ static bool memcached_ascii_input_value(struct memcached_ascii_connection *conn)
        return TRUE;
 }
 
-static int memcached_ascii_input_reply_read(struct memcached_ascii_dict *dict)
+static int memcached_ascii_input_reply_read(struct memcached_ascii_dict *dict,
+                                           const char **error_r)
 {
        struct memcached_ascii_connection *conn = &dict->conn;
        const enum memcached_ascii_input_state *states;
@@ -147,8 +148,8 @@ static int memcached_ascii_input_reply_read(struct memcached_ascii_dict *dict)
 
        states = array_get(&dict->input_states, &count);
        if (count == 0) {
-               i_error("memcached_ascii: Unexpected input (expected nothing): %s",
-                       line);
+               *error_r = t_strdup_printf(
+                       "memcached_ascii: Unexpected input (expected nothing): %s", line);
                return -1;
        }
        switch (states[0]) {
@@ -160,7 +161,7 @@ static int memcached_ascii_input_reply_read(struct memcached_ascii_dict *dict)
                        if (str_to_uint(p+1, &conn->reply_bytes_left) < 0)
                                break;
                        conn->reply_bytes_left += 2; /* CRLF */
-                       return memcached_ascii_input_reply_read(dict);
+                       return memcached_ascii_input_reply_read(dict, error_r);
                } else if (strcmp(line, "END") == 0)
                        return 1;
                break;
@@ -181,18 +182,20 @@ static int memcached_ascii_input_reply_read(struct memcached_ascii_dict *dict)
                        break;
                return 1;
        }
-       i_error("memcached_ascii: Unexpected input (state=%d): %s",
+       *error_r = t_strdup_printf(
+               "memcached_ascii: Unexpected input (state=%d): %s",
                states[0], line);
        return -1;
 }
 
-static int memcached_ascii_input_reply(struct memcached_ascii_dict *dict)
+static int memcached_ascii_input_reply(struct memcached_ascii_dict *dict,
+                                      const char **error_r)
 {
        struct memcached_ascii_dict_reply *replies;
        unsigned int count;
        int ret;
 
-       if ((ret = memcached_ascii_input_reply_read(dict)) <= 0)
+       if ((ret = memcached_ascii_input_reply_read(dict, error_r)) <= 0)
                return ret;
        /* finished a reply */
        array_delete(&dict->input_states, 0, 1);
@@ -211,6 +214,7 @@ static void memcached_ascii_conn_input(struct connection *_conn)
 {
        struct memcached_ascii_connection *conn =
                (struct memcached_ascii_connection *)_conn;
+       const char *error;
        int ret;
 
        switch (i_stream_read(_conn->input)) {
@@ -223,13 +227,16 @@ static void memcached_ascii_conn_input(struct connection *_conn)
                break;
        }
 
-       while ((ret = memcached_ascii_input_reply(conn->dict)) > 0) ;
-       if (ret < 0)
+       while ((ret = memcached_ascii_input_reply(conn->dict, &error)) > 0) ;
+       if (ret < 0) {
+               i_error("%s", error);
                memcached_ascii_conn_destroy(_conn);
+       }
        io_loop_stop(conn->dict->ioloop);
 }
 
-static int memcached_ascii_input_wait(struct memcached_ascii_dict *dict)
+static int memcached_ascii_input_wait(struct memcached_ascii_dict *dict,
+                                     const char **error_r)
 {
        dict->prev_ioloop = current_ioloop;
        io_loop_set_current(dict->ioloop);
@@ -245,7 +252,11 @@ static int memcached_ascii_input_wait(struct memcached_ascii_dict *dict)
                dict->to = io_loop_move_timeout(&dict->to);
        connection_switch_ioloop(&dict->conn.conn);
 
-       return dict->conn.conn.fd_in == -1 ? -1 : 0;
+       if (dict->conn.conn.fd_in == -1) {
+               *error_r = "memcached_ascii: Communication failure";
+               return -1;
+       }
+       return 0;
 }
 
 static void memcached_ascii_input_timeout(struct memcached_ascii_dict *dict)
@@ -255,7 +266,8 @@ static void memcached_ascii_input_timeout(struct memcached_ascii_dict *dict)
        memcached_ascii_conn_destroy(&dict->conn.conn);
 }
 
-static int memcached_ascii_wait_replies(struct memcached_ascii_dict *dict)
+static int memcached_ascii_wait_replies(struct memcached_ascii_dict *dict,
+                                       const char **error_r)
 {
        int ret = 0;
 
@@ -264,12 +276,12 @@ static int memcached_ascii_wait_replies(struct memcached_ascii_dict *dict)
        while (array_count(&dict->input_states) > 0) {
                i_assert(array_count(&dict->replies) > 0);
 
-               if ((ret = memcached_ascii_input_reply(dict)) != 0) {
+               if ((ret = memcached_ascii_input_reply(dict, error_r)) != 0) {
                        if (ret < 0)
                                memcached_ascii_conn_destroy(&dict->conn.conn);
                        break;
                }
-               ret = memcached_ascii_input_wait(dict);
+               ret = memcached_ascii_input_wait(dict, error_r);
                if (ret != 0)
                        break;
        }
@@ -278,7 +290,8 @@ static int memcached_ascii_wait_replies(struct memcached_ascii_dict *dict)
        return ret < 0 ? -1 : 0;
 }
 
-static int memcached_ascii_wait(struct memcached_ascii_dict *dict)
+static int memcached_ascii_wait(struct memcached_ascii_dict *dict,
+                               const char **error_r)
 {
        int ret;
 
@@ -288,12 +301,12 @@ static int memcached_ascii_wait(struct memcached_ascii_dict *dict)
                /* waiting for connection to finish */
                dict->to = timeout_add(dict->timeout_msecs,
                                       memcached_ascii_input_timeout, dict);
-               ret = memcached_ascii_input_wait(dict);
+               ret = memcached_ascii_input_wait(dict, error_r);
                timeout_remove(&dict->to);
                if (ret < 0)
                        return -1;
        }
-       if (memcached_ascii_wait_replies(dict) < 0)
+       if (memcached_ascii_wait_replies(dict, error_r) < 0)
                return -1;
        i_assert(array_count(&dict->input_states) == 0);
        i_assert(array_count(&dict->replies) == 0);
@@ -429,9 +442,12 @@ static void memcached_ascii_dict_deinit(struct dict *_dict)
        struct memcached_ascii_dict *dict =
                (struct memcached_ascii_dict *)_dict;
        struct ioloop *old_ioloop = current_ioloop;
+       const char *error;
 
-       if (array_count(&dict->input_states) > 0)
-               (void)memcached_ascii_wait(dict);
+       if (array_count(&dict->input_states) > 0) {
+               if (memcached_ascii_wait(dict, &error) < 0)
+                       i_error("%s", error);
+       }
        connection_deinit(&dict->conn.conn);
 
        io_loop_set_current(dict->ioloop);
@@ -449,19 +465,21 @@ static void memcached_ascii_dict_deinit(struct dict *_dict)
                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)
 {
        if (dict->conn.conn.input != NULL)
                return 0;
 
        if (dict->conn.conn.fd_in == -1) {
                if (connection_client_connect(&dict->conn.conn) < 0) {
-                       i_error("memcached_ascii: Couldn't connect to %s:%u",
+                       *error_r = t_strdup_printf(
+                               "memcached_ascii: Couldn't connect to %s:%u",
                                net_ip2addr(&dict->ip), dict->port);
                        return -1;
                }
        }
-       return memcached_ascii_wait(dict);
+       return memcached_ascii_wait(dict, error_r);
 }
 
 static const char *
@@ -483,14 +501,14 @@ memcached_ascii_dict_get_full_key(struct memcached_ascii_dict *dict,
 }
 
 static int
-memcached_ascii_dict_lookup(struct dict *_dict, pool_t pool,
-                           const char *key, const char **value_r)
+memcached_ascii_dict_lookup(struct dict *_dict, 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_reply *reply;
        enum memcached_ascii_input_state state = MEMCACHED_INPUT_STATE_GET;
 
-       if (memcached_ascii_connect(dict) < 0)
+       if (memcached_ascii_connect(dict, error_r) < 0)
                return -1;
 
        key = memcached_ascii_dict_get_full_key(dict, key);
@@ -501,7 +519,7 @@ memcached_ascii_dict_lookup(struct dict *_dict, pool_t pool,
        reply = array_append_space(&dict->replies);
        reply->reply_count = 1;
 
-       if (memcached_ascii_wait(dict) < 0)
+       if (memcached_ascii_wait(dict, error_r) < 0)
                return -1;
 
        *value_r = p_strdup(pool, str_c(dict->conn.reply_str));
@@ -568,9 +586,12 @@ memcached_ascii_transaction_send(struct dict_memcached_ascii_commit_ctx *ctx)
        struct memcached_ascii_dict_reply *reply;
        const struct dict_transaction_memory_change *changes;
        unsigned int i, count, old_state_count;
+       const char *error;
 
-       if (memcached_ascii_connect(dict) < 0)
+       if (memcached_ascii_connect(dict, &error) < 0) {
+               i_error("%s", error);
                return -1;
+       }
 
        old_state_count = array_count(&dict->input_states);
        changes = array_get(&ctx->memctx->changes, &count);
@@ -600,6 +621,7 @@ memcached_ascii_transaction_commit(struct dict_transaction_context *_ctx,
        struct memcached_ascii_dict *dict =
                (struct memcached_ascii_dict *)_ctx->dict;
        struct dict_memcached_ascii_commit_ctx commit_ctx;
+       const char *error;
        int ret = 1;
 
        if (_ctx->changed) {
@@ -612,8 +634,10 @@ memcached_ascii_transaction_commit(struct dict_transaction_context *_ctx,
 
                ret = memcached_ascii_transaction_send(&commit_ctx);
                if (!async && ret >= 0) {
-                       if (memcached_ascii_wait(dict) < 0)
+                       if (memcached_ascii_wait(dict, &error) < 0) {
+                               i_error("%s", error);
                                ret = -1;
+                       }
                }
                str_free(&commit_ctx.str);
        }
index f9bded4450cd9d026e4fe040b2f87217c0ae485e..dd962d87db2eab0f771c06b04097408ccdaee589 100644 (file)
@@ -271,8 +271,9 @@ static void memcached_add_header(buffer_t *buf, unsigned int key_len)
        i_assert(buf->used == MEMCACHED_REQUEST_HDR_LENGTH);
 }
 
-static int memcached_dict_lookup(struct dict *_dict, pool_t pool,
-                                const char *key, const char **value_r)
+static int
+memcached_dict_lookup(struct dict *_dict, pool_t pool, const char *key,
+                     const char **value_r, const char **error_r)
 {
        struct memcached_dict *dict = (struct memcached_dict *)_dict;
        struct ioloop *prev_ioloop = current_ioloop;
@@ -282,15 +283,15 @@ static int memcached_dict_lookup(struct dict *_dict, pool_t pool,
        if (strncmp(key, DICT_PATH_SHARED, strlen(DICT_PATH_SHARED)) == 0)
                key += strlen(DICT_PATH_SHARED);
        else {
-               i_error("memcached: Only shared keys supported currently");
+               *error_r = t_strdup_printf("memcached: Only shared keys supported currently");
                return -1;
        }
        if (*dict->key_prefix != '\0')
                key = t_strconcat(dict->key_prefix, key, NULL);
        key_len = strlen(key);
        if (key_len > 0xffff) {
-               i_error("memcached: Key is too long (%u bytes): %s",
-                       key_len, key);
+               *error_r = t_strdup_printf(
+                       "memcached: Key is too long (%u bytes): %s", key_len, key);
                return -1;
        }
 
@@ -335,6 +336,7 @@ static int memcached_dict_lookup(struct dict *_dict, pool_t pool,
                /* we failed in some way. make sure we disconnect since the
                   connection state isn't known anymore */
                memcached_conn_destroy(&dict->conn.conn);
+               *error_r = "memcached: Communication failure";
                return -1;
        }
        switch (dict->conn.reply.status) {
@@ -345,18 +347,18 @@ static int memcached_dict_lookup(struct dict *_dict, pool_t pool,
        case MEMCACHED_RESPONSE_NOTFOUND:
                return 0;
        case MEMCACHED_RESPONSE_INTERNALERROR:
-               i_error("memcached: Lookup(%s) failed: Internal error", key);
+               *error_r = "memcached: Lookup failed: Internal error";
                return -1;
        case MEMCACHED_RESPONSE_BUSY:
-               i_error("memcached: Lookup(%s) failed: Busy", key);
+               *error_r = "memcached: Lookup failed: Busy";
                return -1;
        case MEMCACHED_RESPONSE_TEMPFAILURE:
-               i_error("memcached: Lookup(%s) failed: Temporary failure", key);
+               *error_r = "memcached: Lookup failed: Temporary failure";
                return -1;
        }
 
-       i_error("memcached: Lookup(%s) failed: Error code=%u",
-               key, dict->conn.reply.status);
+       *error_r = t_strdup_printf("memcached: Lookup failed: Error code=%u",
+                                  dict->conn.reply.status);
        return -1;
 }
 
index b790bc853e53a8dff4cc3223b8e80e20c4f95f5f..1d2b00ec4ded35b0f344320a6c01730b95fa0087 100644 (file)
@@ -11,7 +11,8 @@ struct dict_vfuncs {
        int (*wait)(struct dict *dict);
 
        int (*lookup)(struct dict *dict, pool_t pool,
-                     const char *key, const char **value_r);
+                     const char *key, const char **value_r,
+                     const char **error_r);
 
        struct dict_iterate_context *
                (*iterate_init)(struct dict *dict, const char *const *paths,
index ca2688a685f294860dcf3410866437b87d54b0bb..829b7d8aba9a7695ae0fb2c4f7dc9415c65a463d 100644 (file)
@@ -488,8 +488,8 @@ static void redis_dict_select_db(struct redis_dict *dict)
        redis_input_state_add(dict, REDIS_INPUT_STATE_SELECT);
 }
 
-static int redis_dict_lookup(struct dict *_dict, pool_t pool,
-                            const char *key, const char **value_r)
+static int redis_dict_lookup(struct dict *_dict, pool_t pool, const char *key,
+                            const char **value_r, const char **error_r)
 {
        struct redis_dict *dict = (struct redis_dict *)_dict;
        struct timeout *to;
@@ -542,6 +542,7 @@ static int redis_dict_lookup(struct dict *_dict, pool_t pool,
                /* we failed in some way. make sure we disconnect since the
                   connection state isn't known anymore */
                redis_conn_destroy(&dict->conn.conn);
+               *error_r = "redis: Communication failure";
                return -1;
        }
        if (dict->conn.value_not_found)
index a60a1cdd6f6a4fc044f35f7093b78e4b329912d0..290a024e8c02c15ddee0daea6b7545229f0051b2 100644 (file)
@@ -418,32 +418,26 @@ sql_dict_result_unescape_field(const struct dict_sql_map *map, pool_t pool,
                                        result, result_idx);
 }
 
-static int sql_dict_lookup(struct dict *_dict, pool_t pool,
-                          const char *key, const char **value_r)
+static int sql_dict_lookup(struct dict *_dict, pool_t pool, const char *key,
+                          const char **value_r, const char **error_r)
 {
        struct sql_dict *dict = (struct sql_dict *)_dict;
        const struct dict_sql_map *map;
        struct sql_result *result = NULL;
        string_t *query = t_str_new(256);
-       const char *error;
        int ret;
 
-       ret = sql_lookup_get_query(dict, key, query, &map, &error);
-       if (ret < 0) {
-               i_error("%s", error);
-               *value_r = NULL;
+       *value_r = NULL;
+
+       if (sql_lookup_get_query(dict, key, query, &map, error_r) < 0)
                return -1;
-       }
-       result = sql_query_s(dict->db, str_c(query));
 
+       result = sql_query_s(dict->db, str_c(query));
        ret = sql_result_next_row(result);
-       if (ret <= 0) {
-               if (ret < 0) {
-                       i_error("dict sql lookup failed: %s",
-                               sql_result_get_error(result));
-               }
-               *value_r = NULL;
-       } else {
+       if (ret < 0) {
+               *error_r = t_strdup_printf("dict sql lookup failed: %s",
+                                          sql_result_get_error(result));
+       } else if (ret > 0) {
                *value_r = sql_dict_result_unescape_value(map, pool, result);
        }
 
index 5e2b08ca3b9627f78497c98e0e985909ca5f88fc..bad2ee7a72a6bf2f23cc7a523c6ce53eb38e29c2 100644 (file)
@@ -100,10 +100,10 @@ static bool dict_key_prefix_is_valid(const char *key)
 }
 
 int dict_lookup(struct dict *dict, pool_t pool, const char *key,
-               const char **value_r)
+               const char **value_r, const char **error_r)
 {
        i_assert(dict_key_prefix_is_valid(key));
-       return dict->v.lookup(dict, pool, key, value_r);
+       return dict->v.lookup(dict, pool, key, value_r, error_r);
 }
 
 void dict_lookup_async(struct dict *dict, const char *key,
@@ -114,9 +114,7 @@ void dict_lookup_async(struct dict *dict, const char *key,
 
                memset(&result, 0, sizeof(result));
                result.ret = dict_lookup(dict, pool_datastack_create(),
-                                        key, &result.value);
-               if (result.ret < 0)
-                       result.error = "Lookup failed";
+                                        key, &result.value, &result.error);
                callback(&result, context);
                return;
        }
index 8c2175f8b83336edff48a383efd2f04912ec8434..53e9d73c841b55f9a8b6e9aaf2e49ea327e9fa0a 100644 (file)
@@ -71,7 +71,7 @@ int dict_wait(struct dict *dict);
 /* Lookup value for key. Set it to NULL if it's not found.
    Returns 1 if found, 0 if not found and -1 if lookup failed. */
 int dict_lookup(struct dict *dict, pool_t pool,
-               const char *key, const char **value_r);
+               const char *key, const char **value_r, const char **error_r);
 void dict_lookup_async(struct dict *dict, const char *key,
                       dict_lookup_callback_t *callback, void *context);
 
index 387cbef86a2b127cfa2438f56d89591e30761a40..4c4653b5d5df06bdc906752211c56ca08fe51342 100644 (file)
@@ -141,21 +141,22 @@ static bool fs_dict_prefetch(struct fs_file *_file ATTR_UNUSED,
 static int fs_dict_lookup(struct dict_fs_file *file)
 {
        struct dict_fs *fs = (struct dict_fs *)file->file.fs;
+       const char *error;
        int ret;
 
        if (file->value != NULL)
                return 0;
 
-       ret = dict_lookup(fs->dict, file->pool, file->key, &file->value);
+       ret = dict_lookup(fs->dict, file->pool, file->key, &file->value, &error);
        if (ret > 0)
                return 0;
        else if (ret < 0) {
                errno = EIO;
-               fs_set_error(&fs->fs, "Dict lookup failed");
+               fs_set_error(&fs->fs, "dict_lookup(%s) failed: %s", file->key, error);
                return -1;
        } else {
                errno = ENOENT;
-               fs_set_error(&fs->fs, "Dict key doesn't exist");
+               fs_set_error(&fs->fs, "Dict key %s doesn't exist", file->key);
                return -1;
        }
 }
index e6914eac047d36a61766ecd9a0a9085356aa0299..cbba545a2916a490972e930f93bb0d835772b9fb 100644 (file)
@@ -235,7 +235,7 @@ int index_storage_attribute_get(struct mailbox_transaction_context *t,
                                struct mail_attribute_value *value_r)
 {
        struct dict *dict;
-       const char *mailbox_prefix;
+       const char *mailbox_prefix, *error;
        int ret;
 
        memset(value_r, 0, sizeof(*value_r));
@@ -249,9 +249,10 @@ int index_storage_attribute_get(struct mailbox_transaction_context *t,
 
        ret = dict_lookup(dict, pool_datastack_create(),
                          key_get_prefixed(type, mailbox_prefix, key),
-                         &value_r->value);
+                         &value_r->value, &error);
        if (ret < 0) {
-               mail_storage_set_internal_error(t->box->storage);
+               mail_storage_set_critical(t->box->storage,
+                       "Failed to set attribute %s: %s", key, error);
                return -1;
        }
        return ret;
index e61acc41b3bd396f6e686d609995534db71eb403..b1fc0827198752312176102db29e713f563fc652 100644 (file)
@@ -115,7 +115,7 @@ static int expire_lookup(struct mailbox *box, const char *key,
        const struct expire_mail_index_header *hdr;
        const void *data;
        size_t data_size;
-       const char *value;
+       const char *value, *error;
        int ret;
 
        /* default to ioloop_time for newly saved mails. it may not be exactly
@@ -138,10 +138,12 @@ static int expire_lookup(struct mailbox *box, const char *key,
        }
 
        ret = dict_lookup(euser->db, pool_datastack_create(),
-                         key, &value);
+                         key, &value, &error);
        if (ret <= 0) {
-               if (ret < 0)
+               if (ret < 0) {
+                       i_error("expire: dict_lookup(%s) failed: %s", key, error);
                        return -1;
+               }
                first_save_timestamp(box, new_stamp_r);
                return 0;
        }
index 5fa9b1d87b3372b93f3838504e24083ec0c3fb8a..e357a6770646c02d14a9deac304fc4007b4c0ba8 100644 (file)
@@ -163,14 +163,16 @@ dict_quota_get_resource(struct quota_root *_root,
                return 0;
 
        T_BEGIN {
-               const char *value;
+               const char *key, *value, *error;
 
+               key = want_bytes ? DICT_QUOTA_CURRENT_BYTES_PATH :
+                       DICT_QUOTA_CURRENT_COUNT_PATH;
                ret = dict_lookup(root->dict, unsafe_data_stack_pool,
-                                 want_bytes ? DICT_QUOTA_CURRENT_BYTES_PATH :
-                                 DICT_QUOTA_CURRENT_COUNT_PATH, &value);
-               if (ret < 0)
+                                 key, &value, &error);
+               if (ret < 0) {
+                       i_error("dict quota: dict_lookup(%s) failed: %s", key, error);
                        *value_r = 0;
-               else {
+               else {
                        intmax_t tmp;
 
                        /* recalculate quota if it's negative or if it