]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
istream API change: Added support for multiple destroy callbacks.
authorTimo Sirainen <tss@iki.fi>
Sun, 7 Apr 2013 20:17:37 +0000 (23:17 +0300)
committerTimo Sirainen <tss@iki.fi>
Sun, 7 Apr 2013 20:17:37 +0000 (23:17 +0300)
src/lib-http/http-client-connection.c
src/lib-imap-urlauth/imap-urlauth-connection.c
src/lib-storage/index/index-mail.c
src/lib/iostream-private.h
src/lib/iostream-temp.c
src/lib/iostream.c
src/lib/istream.c
src/lib/istream.h
src/lib/json-parser.c

index 4e801d4445589e91f31b09cc46ac03c1be7dd5d7..ed3300823909397b87c1dd260153df074254a9fa 100644 (file)
@@ -370,7 +370,7 @@ http_client_connection_return_response(struct http_client_connection *conn,
                   actual payload stream. */
                conn->incoming_payload = response->payload =
                        i_stream_create_limit(response->payload, (uoff_t)-1);
-               i_stream_set_destroy_callback(response->payload,
+               i_stream_add_destroy_callback(response->payload,
                                              http_client_payload_destroyed,
                                              req);
                /* the callback may add its own I/O, so we need to remove
@@ -391,7 +391,8 @@ http_client_connection_return_response(struct http_client_connection *conn,
        if (retrying) {
                /* retrying, don't destroy the request */
                if (response->payload != NULL) {
-                       i_stream_unset_destroy_callback(conn->incoming_payload);
+                       i_stream_remove_destroy_callback(conn->incoming_payload,
+                                                        http_client_payload_destroyed);
                        i_stream_unref(&conn->incoming_payload);
                        conn->conn.io = io_add(conn->conn.fd_in, IO_READ,
                                               http_client_connection_input,
index ef4122b31070b76629b53e81b5fb2b0324d231e1..3a4835d502ca2b557012f736f7d18dc0d5346ed9 100644 (file)
@@ -604,7 +604,7 @@ imap_urlauth_fetch_reply_set_literal_stream(struct imap_urlauth_connection *conn
                data = buffer_get_data(conn->literal_buf, &size);
                i_assert(size == conn->literal_size);
                reply->input = i_stream_create_from_data(data, size);
-               i_stream_set_destroy_callback(reply->input,
+               i_stream_add_destroy_callback(reply->input,
                                              literal_stream_destroy,
                                              conn->literal_buf);
        }
index 00a77d89962f1c6adc1278f8da1549534c46e557..2fb2fcb074c21edf2bb7d93dfc14a034c14fff54 100644 (file)
@@ -948,7 +948,7 @@ int index_mail_init_stream(struct index_mail *mail,
                /* do this only once in case a plugin changes the stream.
                   otherwise the check would break. */
                data->destroy_callback_set = TRUE;
-               i_stream_set_destroy_callback(data->stream,
+               i_stream_add_destroy_callback(data->stream,
                        index_mail_stream_destroy_callback, mail);
        }
 
@@ -1260,11 +1260,12 @@ static void index_mail_close_streams_full(struct index_mail *mail, bool closing)
                i_stream_unref(&data->filter_stream);
        if (data->stream != NULL) {
                data->destroying_stream = TRUE;
-               if (!closing) {
+               if (!closing && data->destroy_callback_set) {
                        /* we're replacing the stream with a new one. it's
                           allowed to have references until the mail is closed
                           (but we can't really check that) */
-                       i_stream_unset_destroy_callback(data->stream);
+                       i_stream_remove_destroy_callback(data->stream,
+                               index_mail_stream_destroy_callback);
                }
                i_stream_unref(&data->stream);
                if (closing) {
index 49c03484e3e9acd1e5dc42529b74683d921287a3..870a995311469df8e5c8878ac239680c9e861796 100644 (file)
@@ -3,6 +3,11 @@
 
 /* This file is private to input stream and output stream implementations */
 
+struct iostream_destroy_callback {
+       void (*callback)(void *context);
+       void *context;
+};
+
 struct iostream_private {
        int refcount;
        char *name;
@@ -12,8 +17,7 @@ struct iostream_private {
        void (*set_max_buffer_size)(struct iostream_private *stream,
                                    size_t max_size);
 
-       void (*destroy_callback)(void *context);
-       void *destroy_context;
+       ARRAY(struct iostream_destroy_callback) destroy_callbacks;
 };
 
 void io_stream_init(struct iostream_private *stream);
index 4f1f88cdd7ec6ffb4f598710e42dcec5dfe3b0c0..83681a679fb67d304ace32fb1dd138200b8c7b20 100644 (file)
@@ -253,7 +253,7 @@ struct istream *iostream_temp_finish(struct ostream **output,
                                                  tstream->buf->used);
                i_stream_set_name(input, t_strdup_printf(
                        "(Temp file in %s)", tstream->temp_path_prefix));
-               i_stream_set_destroy_callback(input, iostream_temp_buf_destroyed,
+               i_stream_add_destroy_callback(input, iostream_temp_buf_destroyed,
                                              tstream->buf);
                tstream->buf = NULL;
        }
index 50b334aa401e6697008efdba33000b91a3a56c6f..66ad38fe76baedd9a040d3e87fcc550adb66db51 100644 (file)
@@ -1,6 +1,7 @@
 /* Copyright (c) 2002-2013 Dovecot authors, see the included COPYING file */
 
 #include "lib.h"
+#include "array.h"
 #include "iostream-private.h"
 
 static void
@@ -31,14 +32,19 @@ void io_stream_ref(struct iostream_private *stream)
 
 void io_stream_unref(struct iostream_private *stream)
 {
+       const struct iostream_destroy_callback *dc;
+
        i_assert(stream->refcount > 0);
        if (--stream->refcount != 0)
                return;
 
        stream->close(stream, FALSE);
        stream->destroy(stream);
-       if (stream->destroy_callback != NULL)
-               stream->destroy_callback(stream->destroy_context);
+       if (array_is_created(&stream->destroy_callbacks)) {
+               array_foreach(&stream->destroy_callbacks, dc)
+                       dc->callback(dc->context);
+               array_free(&stream->destroy_callbacks);
+       }
 
         i_free(stream->name);
         i_free(stream);
index bd42094296550be97daaf4764578626db67047a3..1bbb28d72471165e65a7a80dbd42a27324ce0731 100644 (file)
@@ -2,6 +2,7 @@
 
 #include "lib.h"
 #include "ioloop.h"
+#include "array.h"
 #include "str.h"
 #include "istream-private.h"
 
@@ -53,22 +54,35 @@ void i_stream_unref(struct istream **stream)
        *stream = NULL;
 }
 
-#undef i_stream_set_destroy_callback
-void i_stream_set_destroy_callback(struct istream *stream,
+#undef i_stream_add_destroy_callback
+void i_stream_add_destroy_callback(struct istream *stream,
                                   istream_callback_t *callback, void *context)
 {
        struct iostream_private *iostream = &stream->real_stream->iostream;
+       struct iostream_destroy_callback *dc;
 
-       iostream->destroy_callback = callback;
-       iostream->destroy_context = context;
+       if (!array_is_created(&iostream->destroy_callbacks))
+               i_array_init(&iostream->destroy_callbacks, 2);
+       dc = array_append_space(&iostream->destroy_callbacks);
+       dc->callback = callback;
+       dc->context = context;
 }
 
-void i_stream_unset_destroy_callback(struct istream *stream)
+void i_stream_remove_destroy_callback(struct istream *stream,
+                                     void (*callback)())
 {
        struct iostream_private *iostream = &stream->real_stream->iostream;
+       const struct iostream_destroy_callback *dcs;
+       unsigned int i, count;
 
-       iostream->destroy_callback = NULL;
-       iostream->destroy_context = NULL;
+       dcs = array_get(&iostream->destroy_callbacks, &count);
+       for (i = 0; i < count; i++) {
+               if (dcs[i].callback == callback) {
+                       array_delete(&iostream->destroy_callbacks, i, 1);
+                       return;
+               }
+       }
+       i_unreached();
 }
 
 int i_stream_get_fd(struct istream *stream)
index b21db077c8b8948454d4a34d647afa8e8a0732a0..2a4b9ae96b7486959ba36864d725a9dc305e6f99 100644 (file)
@@ -52,15 +52,16 @@ void i_stream_ref(struct istream *stream);
 /* Unreferences the stream and sets stream pointer to NULL. */
 void i_stream_unref(struct istream **stream);
 /* Call the given callback function when stream is destroyed. */
-void i_stream_set_destroy_callback(struct istream *stream,
+void i_stream_add_destroy_callback(struct istream *stream,
                                   istream_callback_t *callback, void *context)
        ATTR_NULL(3);
-#define i_stream_set_destroy_callback(stream, callback, context) \
-       i_stream_set_destroy_callback(stream + \
+#define i_stream_add_destroy_callback(stream, callback, context) \
+       i_stream_add_destroy_callback(stream + \
                CALLBACK_TYPECHECK(callback, void (*)(typeof(context))), \
                (istream_callback_t *)callback, context)
 /* Remove the destroy callback. */
-void i_stream_unset_destroy_callback(struct istream *stream);
+void i_stream_remove_destroy_callback(struct istream *stream,
+                                     void (*callback)());
 
 /* Return file descriptor for stream, or -1 if none is available. */
 int i_stream_get_fd(struct istream *stream);
index 01556f5a6ab5ac340420e4d7275fa7845ad9b1ff..8d3cab9facc6c56a45e6de16593cefd8b6720478 100644 (file)
@@ -596,7 +596,7 @@ json_try_parse_stream_start(struct json_parser *parser,
        parser->state = parser->state == JSON_STATE_OBJECT_VALUE ?
                JSON_STATE_OBJECT_SKIP_STRING : JSON_STATE_ARRAY_SKIP_STRING;
        parser->strinput = i_stream_create_jsonstr(parser->input);
-       i_stream_set_destroy_callback(parser->strinput,
+       i_stream_add_destroy_callback(parser->strinput,
                                      json_strinput_destroyed, parser);
 
        *input_r = parser->strinput;