]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
redis: Fixed connection handling.
authorTimo Sirainen <tss@iki.fi>
Sun, 8 Jul 2012 06:18:46 +0000 (09:18 +0300)
committerTimo Sirainen <tss@iki.fi>
Sun, 8 Jul 2012 06:18:46 +0000 (09:18 +0300)
src/lib-dict/dict-redis.c
src/lib/connection.c
src/lib/connection.h

index 1118e0dc45a301a9c224fbeb6c09b3aec2cf68b1..4b94617528ebca5e62af39ab16c1aa5d667b25cd 100644 (file)
@@ -28,11 +28,7 @@ struct redis_dict {
 
        struct ioloop *ioloop;
        struct redis_connection conn;
-};
-
-struct redis_dict_iterate_context {
-       struct dict_iterate_context ctx;
-       struct redis_connection *conn;
+       bool connected;
 };
 
 static struct connection_list *redis_connections;
@@ -41,6 +37,7 @@ static void redis_conn_destroy(struct connection *_conn)
 {
        struct redis_connection *conn = (struct redis_connection *)_conn;
 
+       conn->dict->connected = FALSE;
        connection_disconnect(_conn);
        if (conn->dict->ioloop != NULL)
                io_loop_stop(conn->dict->ioloop);
@@ -101,6 +98,20 @@ static void redis_conn_input(struct connection *_conn)
        }
 }
 
+static void redis_conn_connected(struct connection *_conn)
+{
+       struct redis_connection *conn = (struct redis_connection *)_conn;
+
+       if ((errno = net_geterror(_conn->fd_in)) != 0) {
+               i_error("redis: connect(%s, %u) failed: %m",
+                       net_ip2addr(&conn->dict->ip), conn->dict->port);
+       } else {
+               conn->dict->connected = TRUE;
+       }
+       if (conn->dict->ioloop != NULL)
+               io_loop_stop(conn->dict->ioloop);
+}
+
 static const struct connection_settings redis_conn_set = {
        .input_max_size = (size_t)-1,
        .output_max_size = (size_t)-1,
@@ -109,7 +120,8 @@ static const struct connection_settings redis_conn_set = {
 
 static const struct connection_vfuncs redis_conn_vfuncs = {
        .destroy = redis_conn_destroy,
-       .input = redis_conn_input
+       .input = redis_conn_input,
+       .connected = redis_conn_connected
 };
 
 static struct dict *
@@ -171,7 +183,8 @@ static void redis_dict_deinit(struct dict *_dict)
 
 static void redis_dict_lookup_timeout(struct redis_dict *dict)
 {
-       i_error("redis: Lookup timed out in %u secs", dict->timeout_msecs);
+       i_error("redis: Lookup timed out in %u.%03u secs",
+               dict->timeout_msecs/1000, dict->timeout_msecs%1000);
        io_loop_stop(dict->ioloop);
 }
 
@@ -203,12 +216,19 @@ static int redis_dict_lookup(struct dict *_dict, pool_t pool,
        } else {
                to = timeout_add(dict->timeout_msecs,
                                 redis_dict_lookup_timeout, dict);
-               cmd = t_strdup_printf("*2\r\n$3\r\nGET\r\n$%d\r\n%s\r\n",
-                                     (int)strlen(key), key);
-               o_stream_send_str(dict->conn.conn.output, cmd);
+               if (!dict->connected) {
+                       /* wait for connection */
+                       io_loop_run(dict->ioloop);
+               }
+
+               if (dict->connected) {
+                       cmd = t_strdup_printf("*2\r\n$3\r\nGET\r\n$%d\r\n%s\r\n",
+                                             (int)strlen(key), key);
+                       o_stream_send_str(dict->conn.conn.output, cmd);
 
-               str_truncate(dict->conn.last_reply, 0);
-               io_loop_run(dict->ioloop);
+                       str_truncate(dict->conn.last_reply, 0);
+                       io_loop_run(dict->ioloop);
+               }
                timeout_remove(&to);
        }
 
index e56f7c04efbd14893e58a8a12ff6c7561db94574..9b5c1494b0f67ede3ea26fab66e12b3f6222f13e 100644 (file)
@@ -105,6 +105,7 @@ static void connection_init_streams(struct connection *conn)
 {
        const struct connection_settings *set = &conn->list->set;
 
+       i_assert(conn->io == NULL);
        i_assert(conn->input == NULL);
        i_assert(conn->output == NULL);
        i_assert(conn->to == NULL);
@@ -119,6 +120,7 @@ static void connection_init_streams(struct connection *conn)
                conn->output = o_stream_create_fd(conn->fd_out,
                                                  set->output_max_size, FALSE);
        }
+       conn->io = io_add(conn->fd_in, IO_READ, conn->list->v.input, conn);
        if (set->input_idle_timeout_secs != 0) {
                conn->to = timeout_add(set->input_idle_timeout_secs*1000,
                                       connection_idle_timeout, conn);
@@ -128,12 +130,8 @@ static void connection_init_streams(struct connection *conn)
                        "VERSION\t%s\t%u\t%u\n", set->service_name_out,
                        set->major_version, set->minor_version));
        }
-}
-
-static void connection_init_io(struct connection *conn)
-{
-       i_assert(conn->io == NULL);
-       conn->io = io_add(conn->fd_in, IO_READ, conn->list->v.input, conn);
+       if (conn->list->v.connected != NULL)
+               conn->list->v.connected(conn);
 }
 
 void connection_init_server(struct connection_list *list,
@@ -147,7 +145,6 @@ void connection_init_server(struct connection_list *list,
        conn->name = i_strdup(name);
        conn->fd_in = fd_in;
        conn->fd_out = fd_out;
-       connection_init_io(conn);
        connection_init_streams(conn);
 
        DLLIST_PREPEND(&list->connections, conn);
@@ -187,7 +184,7 @@ static void connection_connected(struct connection *conn)
        if (conn->to != NULL)
                timeout_remove(&conn->to);
 
-       connection_init_io(conn);
+       connection_init_streams(conn);
 }
 
 int connection_client_connect(struct connection *conn)
@@ -214,9 +211,8 @@ int connection_client_connect(struct connection *conn)
                                               connection_connect_timeout, conn);
                }
        } else {
-               connection_init_io(conn);
+               connection_init_streams(conn);
        }
-       connection_init_streams(conn);
        return 0;
 }
 
index 129bae23fd8549a9bc7cd54b8b7356b526f9e47b..b65d877e578d5d64b649e8e2914d39af691cfa09 100644 (file)
@@ -27,6 +27,7 @@ enum connection_disconnect_reason {
 
 struct connection_vfuncs {
        void (*destroy)(struct connection *conn);
+       void (*connected)(struct connection *conn);
 
        /* implement one of the input*() methods.
           They return 0 = ok, -1 = error, disconnect the client */