create irc_log_chan function to log a new irc_log_chan, and irc_log_chan_destroy to remove the added callbacks/command handlers
--- a/src/chain.c Mon Mar 16 21:47:18 2009 +0200
+++ b/src/chain.c Mon Mar 16 22:06:39 2009 +0200
@@ -21,6 +21,28 @@
return SUCCESS;
}
+void chain_remove (struct chain_list *list, const void *chain, void *arg)
+{
+ struct chain_head *item;
+
+ // look for it
+ CHAIN_FOREACH(list, item) {
+ if (item->chain == chain && item->arg == arg) {
+ // remove it
+ // XXX: use TAILQ instead?
+ STAILQ_REMOVE(list, item, chain_head, node);
+
+ // free it
+ free(item);
+
+ // ok
+ return;
+ }
+ }
+
+ // not found... ignore
+}
+
void chain_free (struct chain_list *list)
{
// start from the first item
--- a/src/chain.h Mon Mar 16 21:47:18 2009 +0200
+++ b/src/chain.h Mon Mar 16 22:06:39 2009 +0200
@@ -54,6 +54,13 @@
#define CHAIN_FOREACH(list_ptr, head_ptr) STAILQ_FOREACH(head_ptr, list_ptr, node)
/**
+ * Remove an item added with chain_add from a chain_list, matching against the given chain/arg.
+ *
+ * If no item matches, nothing is done.
+ */
+void chain_remove (struct chain_list *list, const void *chain, void *arg);
+
+/**
* Free a chain_list
*/
void chain_free (struct chain_list *list);
--- a/src/irc_chan.c Mon Mar 16 21:47:18 2009 +0200
+++ b/src/irc_chan.c Mon Mar 16 22:06:39 2009 +0200
@@ -117,6 +117,11 @@
return chain_add(&chan->callbacks, callbacks, arg);
}
+void irc_chan_remove_callbacks (struct irc_chan *chan, const struct irc_chan_callbacks *callbacks, void *arg)
+{
+ chain_remove(&chan->callbacks, callbacks, arg);
+}
+
err_t irc_chan_join (struct irc_chan *chan)
{
err_t err;
--- a/src/irc_chan.h Mon Mar 16 21:47:18 2009 +0200
+++ b/src/irc_chan.h Mon Mar 16 22:06:39 2009 +0200
@@ -109,6 +109,11 @@
err_t irc_chan_add_callbacks (struct irc_chan *chan, const struct irc_chan_callbacks *callbacks, void *arg);
/**
+ * Remove high-level irc_chan callbacks.
+ */
+void irc_chan_remove_callbacks (struct irc_chan *chan, const struct irc_chan_callbacks *callbacks, void *arg);
+
+/**
* Send the initial JOIN message.
*
* The channel must be in the IRC_CHAN_INIT state, and will transition to the IRC_CHAN_JOINING state.
--- a/src/irc_cmd.c Mon Mar 16 21:47:18 2009 +0200
+++ b/src/irc_cmd.c Mon Mar 16 22:06:39 2009 +0200
@@ -33,6 +33,11 @@
}
}
+void irc_cmd_remove (irc_cmd_handlers_t *handlers, const struct irc_cmd_handler *list, void *arg)
+{
+ chain_remove(handlers, list, arg);
+}
+
void irc_cmd_free (irc_cmd_handlers_t *handlers)
{
chain_free(handlers);
--- a/src/irc_cmd.h Mon Mar 16 21:47:18 2009 +0200
+++ b/src/irc_cmd.h Mon Mar 16 22:06:39 2009 +0200
@@ -44,6 +44,11 @@
void irc_cmd_invoke (irc_cmd_handlers_t *handlers, const struct irc_line *line);
/**
+ * Remove a previously added chain_head from the irc_cmd_handlers list with the given list/arg
+ */
+void irc_cmd_remove (irc_cmd_handlers_t *handlers, const struct irc_cmd_handler *list, void *arg);
+
+/**
* Cleanup an irc_cmd_handlers list
*/
void irc_cmd_free (irc_cmd_handlers_t *handlers);
--- a/src/irc_log.c Mon Mar 16 21:47:18 2009 +0200
+++ b/src/irc_log.c Mon Mar 16 22:06:39 2009 +0200
@@ -5,7 +5,6 @@
#include <stdlib.h>
#include <string.h>
-#include <assert.h> //<<< XXX: remove
#include <event2/event.h>
#include <evsql.h>
@@ -220,6 +219,62 @@
.on_msg = NULL,
};
+/**
+ * Release resources associated with the given irc_log_chan without doing any clean shutdown stuff
+ */
+static void irc_log_chan_destroy (struct irc_log_chan *chan_ctx)
+{
+ // remove any handlers/callbacks
+ irc_cmd_remove(&chan_ctx->chan->handlers, _chan_cmd_handlers, chan_ctx);
+ irc_chan_remove_callbacks(chan_ctx->chan, &_chan_callbacks, chan_ctx);
+
+ // free ourselves
+ free(chan_ctx);
+}
+
+/**
+ * Begin logging the given channel
+ */
+static err_t irc_log_chan (struct irc_log_ctx *ctx, struct irc_chan *chan, struct error_info *err)
+{
+ struct irc_log_chan *chan_ctx;
+
+ // alloc
+ if ((chan_ctx = calloc(1, sizeof(*chan_ctx))) == NULL)
+ return SET_ERROR(err, ERR_CALLOC);
+
+ // store
+ chan_ctx->ctx = ctx;
+ chan_ctx->chan = chan;
+
+ // add low-level handlers
+ if ((ERROR_CODE(err) = irc_cmd_add(&chan_ctx->chan->handlers, _chan_cmd_handlers, chan_ctx)))
+ goto error;
+
+ // add channel callbacks
+ if ((ERROR_CODE(err) = irc_chan_add_callbacks(chan_ctx->chan, &_chan_callbacks, chan_ctx)))
+ goto error;
+
+ // log an OPEN message
+ // XXX: move this to when we first JOIN the channel
+ if ((ERROR_CODE(err) = irc_log_event(ctx, chan_ctx->chan, NULL, "OPEN", NULL, NULL)))
+ goto error;
+
+ // ok
+ log_info("logging channel %s:%s", chan_ctx->chan->net->info.network, irc_chan_name(chan_ctx->chan));
+
+ return SUCCESS;
+
+error:
+ // cleanup
+ irc_log_chan_destroy(chan_ctx);
+
+ return ERROR_CODE(err);
+}
+
+/**
+ * Allocate and initialize an irc_log_ctx. This doesn't do very much, the real magic happens in irc_log_conf.
+ */
static err_t irc_log_init (struct nexus *nexus, void **ctx_ptr, struct error_info *err)
{
struct irc_log_ctx *ctx;
@@ -228,9 +283,6 @@
if ((ctx = calloc(1, sizeof(*ctx))) == NULL)
return SET_ERROR(err, ERR_CALLOC);
- // initialize
- memset(ctx, 0, sizeof(*ctx));
-
// store
ctx->nexus = nexus;
@@ -239,7 +291,7 @@
// ok
*ctx_ptr = ctx;
- return SET_ERROR(err, SUCCESS);
+ return SUCCESS;
}
/**
@@ -276,8 +328,7 @@
static err_t irc_log_conf_channel (struct irc_log_ctx *ctx, char *value, struct error_info *err)
{
const char *network, *channel;
-
- struct irc_log_chan *chan_ctx;
+ struct irc_chan *chan;
// parse required args
if ((network = strsep(&value, ":")) == NULL)
@@ -294,42 +345,16 @@
if (!ctx->db)
RETURN_SET_ERROR_STR(err, ERR_MODULE_CONF, "irc_log.channel used without any irc_log.db_info");
- // alloc
- if ((chan_ctx = calloc(1, sizeof(*chan_ctx))) == NULL)
- return SET_ERROR(err, ERR_CALLOC);
-
- // store
- chan_ctx->ctx = ctx;
-
// get the channel?
- if ((chan_ctx->chan = irc_client_get_chan(ctx->nexus->client, network, channel)) == NULL)
- JUMP_SET_ERROR_STR(err, ERR_MODULE_CONF, "unknown channel name");
+ if ((chan = irc_client_get_chan(ctx->nexus->client, network, channel)) == NULL)
+ RETURN_SET_ERROR_STR(err, ERR_MODULE_CONF, "unknown channel name");
- // add low-level handlers
- if ((ERROR_CODE(err) = irc_cmd_add(&chan_ctx->chan->handlers, _chan_cmd_handlers, chan_ctx)))
- goto error;
-
- // add channel callbacks
- if ((ERROR_CODE(err) = irc_chan_add_callbacks(chan_ctx->chan, &_chan_callbacks, chan_ctx)))
- goto error;
-
- // log an OPEN message
- // XXX: move this to when we first JOIN the channel
- if ((ERROR_CODE(err) = irc_log_event(ctx, chan_ctx->chan, NULL, "OPEN", NULL, NULL)))
- goto error;
+ // begin logging it
+ if (irc_log_chan(ctx, chan, err))
+ return ERROR_CODE(err);
// ok
- log_info("logging channel %s:%s", chan_ctx->chan->net->info.network, irc_chan_name(chan_ctx->chan));
-
return SUCCESS;
-
-error:
- // XXX: remove callbacks
- assert(!chan_ctx->chan);
-
- free(chan_ctx);
-
- return ERROR_CODE(err);
}
/**