dovecot-2.2: lib-auth: auth_master_user_list_*() no longer reads...
dovecot at dovecot.org
dovecot at dovecot.org
Fri Jul 12 02:26:55 EEST 2013
details: http://hg.dovecot.org/dovecot-2.2/rev/328bc770af54
changeset: 16610:328bc770af54
user: Timo Sirainen <tss at iki.fi>
date: Fri Jul 12 02:26:44 2013 +0300
description:
lib-auth: auth_master_user_list_*() no longer reads the entire user list into memory.
diffstat:
src/lib-auth/auth-master.c | 100 +++++++++++++++++++++++++-------------------
src/lib-auth/auth-master.h | 1 -
2 files changed, 57 insertions(+), 44 deletions(-)
diffs (229 lines):
diff -r c0b0f46ff581 -r 328bc770af54 src/lib-auth/auth-master.c
--- a/src/lib-auth/auth-master.c Fri Jul 12 02:17:31 2013 +0300
+++ b/src/lib-auth/auth-master.c Fri Jul 12 02:26:44 2013 +0300
@@ -31,7 +31,7 @@
enum auth_master_flags flags;
int fd;
- struct ioloop *ioloop;
+ struct ioloop *ioloop, *prev_ioloop;
struct io *io;
struct istream *input;
struct ostream *output;
@@ -61,10 +61,8 @@
struct auth_master_user_list_ctx {
struct auth_master_connection *conn;
- pool_t pool;
- ARRAY_TYPE(const_string) users;
- const char *const *user_strings;
- unsigned int idx, user_count;
+ string_t *username;
+ bool finished;
bool failed;
};
@@ -338,6 +336,7 @@
if (conn->to != NULL)
timeout_remove(&conn->to);
+ conn->prev_ioloop = current_ioloop;
conn->ioloop = io_loop_create();
conn->input = i_stream_create_fd(conn->fd, MAX_INBUF_SIZE, FALSE);
conn->output = o_stream_create_fd(conn->fd, MAX_OUTBUF_SIZE, FALSE);
@@ -347,11 +346,10 @@
lib_signals_reset_ioloop();
}
-static void auth_master_unset_io(struct auth_master_connection *conn,
- struct ioloop *prev_ioloop)
+static void auth_master_unset_io(struct auth_master_connection *conn)
{
- if (prev_ioloop != NULL) {
- io_loop_set_current(prev_ioloop);
+ if (conn->prev_ioloop != NULL) {
+ io_loop_set_current(conn->prev_ioloop);
lib_signals_reset_ioloop();
}
io_loop_set_current(conn->ioloop);
@@ -363,7 +361,7 @@
io_loop_destroy(&conn->ioloop);
if ((conn->flags & AUTH_MASTER_FLAG_NO_IDLE_TIMEOUT) == 0) {
- if (prev_ioloop == NULL)
+ if (conn->prev_ioloop == NULL)
auth_connection_close(conn);
else {
conn->to = timeout_add(1000*AUTH_MASTER_IDLE_SECS,
@@ -385,18 +383,15 @@
return TRUE;
}
-static int auth_master_run_cmd(struct auth_master_connection *conn,
- const char *cmd)
+static int auth_master_run_cmd_pre(struct auth_master_connection *conn,
+ const char *cmd)
{
- struct ioloop *prev_ioloop;
const char *str;
if (conn->fd == -1) {
if (auth_master_connect(conn) < 0)
return -1;
}
-
- prev_ioloop = current_ioloop;
auth_master_set_io(conn);
o_stream_cork(conn->output);
@@ -412,12 +407,16 @@
if (o_stream_nfinish(conn->output) < 0) {
i_error("write(auth socket) failed: %m");
- conn->aborted = TRUE;
- } else {
- io_loop_run(conn->ioloop);
+ auth_master_unset_io(conn);
+ auth_connection_close(conn);
+ return -1;
}
+ return 0;
+}
- auth_master_unset_io(conn, prev_ioloop);
+static int auth_master_run_cmd_post(struct auth_master_connection *conn)
+{
+ auth_master_unset_io(conn);
if (conn->aborted) {
conn->aborted = FALSE;
auth_connection_close(conn);
@@ -426,6 +425,15 @@
return 0;
}
+static int auth_master_run_cmd(struct auth_master_connection *conn,
+ const char *cmd)
+{
+ if (auth_master_run_cmd_pre(conn, cmd) < 0)
+ return -1;
+ io_loop_run(conn->ioloop);
+ return auth_master_run_cmd_post(conn);
+}
+
static unsigned int
auth_master_next_request_id(struct auth_master_connection *conn)
{
@@ -617,26 +625,26 @@
void *context)
{
struct auth_master_user_list_ctx *ctx = context;
- const char *user;
timeout_reset(ctx->conn->to);
+ str_truncate(ctx->username, 0);
+ io_loop_stop(ctx->conn->ioloop);
if (strcmp(cmd, "DONE") == 0) {
- io_loop_stop(ctx->conn->ioloop);
if (args[0] != NULL && strcmp(args[0], "fail") == 0) {
i_error("User listing returned failure");
ctx->failed = TRUE;
}
- return TRUE;
- }
- if (strcmp(cmd, "LIST") == 0 && args[0] != NULL) {
+ ctx->finished = TRUE;
+ } else if (strcmp(cmd, "LIST") == 0 && args[0] != NULL) {
/* we'll just read all the users into memory. otherwise we'd
have to use a separate connection for listing and there's
a higher chance of a failure since the connection could be
open to dovecot-auth for a long time. */
- user = p_strdup(ctx->pool, args[0]);
- array_append(&ctx->users, &user, 1);
- return TRUE;
+ str_append(ctx->username, args[0]);
+ } else {
+ i_error("User listing returned invalid input");
+ ctx->failed = TRUE;
}
return FALSE;
}
@@ -648,13 +656,10 @@
{
struct auth_master_user_list_ctx *ctx;
string_t *str;
- pool_t pool;
- pool = pool_alloconly_create("auth master user list", 10240);
- ctx = p_new(pool, struct auth_master_user_list_ctx, 1);
- ctx->pool = pool;
+ ctx = i_new(struct auth_master_user_list_ctx, 1);
ctx->conn = conn;
- i_array_init(&ctx->users, 128);
+ ctx->username = str_new(default_pool, 128);
conn->reply_callback = auth_user_list_reply_callback;
conn->reply_context = ctx;
@@ -669,23 +674,31 @@
str_append_c(str, '\n');
conn->prefix = "userdb list";
- if (auth_master_run_cmd(conn, str_c(str)) < 0)
+
+ if (auth_master_run_cmd_pre(conn, str_c(str)) < 0)
ctx->failed = TRUE;
- ctx->user_strings = array_get(&ctx->users, &ctx->user_count);
conn->prefix = DEFAULT_USERDB_LOOKUP_PREFIX;
return ctx;
}
const char *auth_master_user_list_next(struct auth_master_user_list_ctx *ctx)
{
- if (ctx->idx == ctx->user_count)
+ const char *line;
+
+ /* try to read already buffered input */
+ line = i_stream_next_line(ctx->conn->input);
+ if (line != NULL) {
+ T_BEGIN {
+ auth_handle_line(ctx->conn, line);
+ } T_END;
+ } else if (!ctx->failed) {
+ /* wait for more data */
+ io_loop_run(ctx->conn->ioloop);
+ }
+
+ if (ctx->finished || ctx->failed)
return NULL;
- return ctx->user_strings[ctx->idx++];
-}
-
-unsigned int auth_master_user_list_count(struct auth_master_user_list_ctx *ctx)
-{
- return ctx->user_count;
+ return str_c(ctx->username);
}
int auth_master_user_list_deinit(struct auth_master_user_list_ctx **_ctx)
@@ -694,7 +707,8 @@
int ret = ctx->failed ? -1 : 0;
*_ctx = NULL;
- array_free(&ctx->users);
- pool_unref(&ctx->pool);
+ auth_master_run_cmd_post(ctx->conn);
+ str_free(&ctx->username);
+ i_free(ctx);
return ret;
}
diff -r c0b0f46ff581 -r 328bc770af54 src/lib-auth/auth-master.h
--- a/src/lib-auth/auth-master.h Fri Jul 12 02:17:31 2013 +0300
+++ b/src/lib-auth/auth-master.h Fri Jul 12 02:26:44 2013 +0300
@@ -59,7 +59,6 @@
const char *user_mask,
const struct auth_user_info *info) ATTR_NULL(3);
const char *auth_master_user_list_next(struct auth_master_user_list_ctx *ctx);
-unsigned int auth_master_user_list_count(struct auth_master_user_list_ctx *ctx);
/* Returns -1 if anything failed, 0 if ok */
int auth_master_user_list_deinit(struct auth_master_user_list_ctx **ctx);
More information about the dovecot-cvs
mailing list