dovecot-2.2: lib-dict: Hide internal ioloop from async commit ca...
dovecot at dovecot.org
dovecot at dovecot.org
Wed Aug 20 10:47:32 UTC 2014
details: http://hg.dovecot.org/dovecot-2.2/rev/a7a5e0737d53
changeset: 17733:a7a5e0737d53
user: Timo Sirainen <tss at iki.fi>
date: Wed Aug 20 12:47:10 2014 +0200
description:
lib-dict: Hide internal ioloop from async commit callbacks. (Redis & memcached fix)
diffstat:
src/lib-dict/dict-memcached-ascii.c | 35 ++++++++++++++++++++++++---------
src/lib-dict/dict-redis.c | 38 +++++++++++++++++++++++++-----------
2 files changed, 51 insertions(+), 22 deletions(-)
diffs (191 lines):
diff -r 4f6a812817c4 -r a7a5e0737d53 src/lib-dict/dict-memcached-ascii.c
--- a/src/lib-dict/dict-memcached-ascii.c Wed Aug 20 12:36:37 2014 +0200
+++ b/src/lib-dict/dict-memcached-ascii.c Wed Aug 20 12:47:10 2014 +0200
@@ -56,7 +56,7 @@
unsigned int port;
unsigned int timeout_msecs;
- struct ioloop *ioloop;
+ struct ioloop *ioloop, *prev_ioloop;
struct timeout *to;
struct memcached_ascii_connection conn;
@@ -66,6 +66,23 @@
static struct connection_list *memcached_ascii_connections;
+static void
+memcached_ascii_callback(struct memcached_ascii_dict *dict,
+ const struct memcached_ascii_dict_reply *reply, int ret)
+{
+ if (reply->callback != NULL) {
+ if (dict->prev_ioloop != NULL) {
+ /* Don't let callback see that we've created our
+ internal ioloop in case it wants to add some ios
+ or timeouts. */
+ current_ioloop = dict->prev_ioloop;
+ }
+ reply->callback(ret, reply->context);
+ if (dict->prev_ioloop != NULL)
+ current_ioloop = dict->ioloop;
+ }
+}
+
static void memcached_ascii_conn_destroy(struct connection *_conn)
{
struct memcached_ascii_connection *conn =
@@ -76,10 +93,8 @@
if (conn->dict->ioloop != NULL)
io_loop_stop(conn->dict->ioloop);
- array_foreach(&conn->dict->replies, reply) {
- if (reply->callback != NULL)
- reply->callback(-1, reply->context);
- }
+ array_foreach(&conn->dict->replies, reply)
+ memcached_ascii_callback(conn->dict, reply, -1);
array_clear(&conn->dict->replies);
array_clear(&conn->dict->input_states);
conn->reply_bytes_left = 0;
@@ -186,8 +201,7 @@
i_assert(count > 0);
i_assert(replies[0].reply_count > 0);
if (--replies[0].reply_count == 0) {
- if (replies[0].callback != NULL)
- replies[0].callback(1, replies[0].context);
+ memcached_ascii_callback(dict, &replies[0], 1);
array_delete(&dict->replies, 0, 1);
}
return 1;
@@ -217,15 +231,16 @@
static int memcached_ascii_input_wait(struct memcached_ascii_dict *dict)
{
- struct ioloop *old_ioloop = current_ioloop;
-
+ dict->prev_ioloop = current_ioloop;
io_loop_set_current(dict->ioloop);
if (dict->to != NULL)
dict->to = io_loop_move_timeout(&dict->to);
connection_switch_ioloop(&dict->conn.conn);
io_loop_run(dict->ioloop);
- io_loop_set_current(old_ioloop);
+ io_loop_set_current(dict->prev_ioloop);
+ dict->prev_ioloop = NULL;
+
if (dict->to != NULL)
dict->to = io_loop_move_timeout(&dict->to);
connection_switch_ioloop(&dict->conn.conn);
diff -r 4f6a812817c4 -r a7a5e0737d53 src/lib-dict/dict-redis.c
--- a/src/lib-dict/dict-redis.c Wed Aug 20 12:36:37 2014 +0200
+++ b/src/lib-dict/dict-redis.c Wed Aug 20 12:47:10 2014 +0200
@@ -48,7 +48,7 @@
unsigned int port;
unsigned int timeout_msecs;
- struct ioloop *ioloop;
+ struct ioloop *ioloop, *prev_ioloop;
struct redis_connection conn;
ARRAY(enum redis_input_state) input_states;
@@ -77,6 +77,22 @@
array_delete(&dict->input_states, 0, 1);
}
+static void redis_callback(struct redis_dict *dict,
+ const struct redis_dict_reply *reply, int ret)
+{
+ if (reply->callback != NULL) {
+ if (dict->prev_ioloop != NULL) {
+ /* Don't let callback see that we've created our
+ internal ioloop in case it wants to add some ios
+ or timeouts. */
+ current_ioloop = dict->prev_ioloop;
+ }
+ reply->callback(ret, reply->context);
+ if (dict->prev_ioloop != NULL)
+ current_ioloop = dict->ioloop;
+ }
+}
+
static void redis_conn_destroy(struct connection *_conn)
{
struct redis_connection *conn = (struct redis_connection *)_conn;
@@ -85,10 +101,8 @@
conn->dict->connected = FALSE;
connection_disconnect(_conn);
- array_foreach(&conn->dict->replies, reply) {
- if (reply->callback != NULL)
- reply->callback(-1, reply->context);
- }
+ array_foreach(&conn->dict->replies, reply)
+ redis_callback(conn->dict, reply, -1);
array_clear(&conn->dict->replies);
array_clear(&conn->dict->input_states);
@@ -98,10 +112,9 @@
static void redis_wait(struct redis_dict *dict)
{
- struct ioloop *prev_ioloop = current_ioloop;
-
i_assert(dict->ioloop == NULL);
+ dict->prev_ioloop = current_ioloop;
dict->ioloop = io_loop_create();
connection_switch_ioloop(&dict->conn.conn);
@@ -109,10 +122,11 @@
io_loop_run(dict->ioloop);
} while (array_count(&dict->input_states) > 0);
- io_loop_set_current(prev_ioloop);
+ io_loop_set_current(dict->prev_ioloop);
connection_switch_ioloop(&dict->conn.conn);
io_loop_set_current(dict->ioloop);
io_loop_destroy(&dict->ioloop);
+ dict->prev_ioloop = NULL;
}
static int redis_input_get(struct redis_connection *conn)
@@ -216,8 +230,7 @@
reply = array_idx_modifiable(&dict->replies, 0);
i_assert(reply->reply_count > 0);
if (--reply->reply_count == 0) {
- if (reply->callback != NULL)
- reply->callback(1, reply->context);
+ redis_callback(dict, reply, 1);
array_delete(&dict->replies, 0, 1);
/* if we're running in a dict-ioloop, we're handling a
synchronous commit and need to stop now */
@@ -426,7 +439,6 @@
{
struct timeout *to;
const char *cmd;
- struct ioloop *prev_ioloop = current_ioloop;
key = redis_dict_get_full_key(dict, key);
@@ -435,6 +447,7 @@
i_assert(dict->ioloop == NULL);
+ dict->prev_ioloop = current_ioloop;
dict->ioloop = io_loop_create();
connection_switch_ioloop(&dict->conn.conn);
@@ -464,10 +477,11 @@
timeout_remove(&to);
}
- io_loop_set_current(prev_ioloop);
+ io_loop_set_current(dict->prev_ioloop);
connection_switch_ioloop(&dict->conn.conn);
io_loop_set_current(dict->ioloop);
io_loop_destroy(&dict->ioloop);
+ dict->prev_ioloop = NULL;
if (!dict->conn.value_received) {
/* we failed in some way. make sure we disconnect since the
More information about the dovecot-cvs
mailing list