Prevent CDR backends from unregistering while billing data is in flight
[asterisk/asterisk.git] / cdr / cdr_custom.c
index 684c12b..51235db 100644 (file)
  * \ingroup cdr_drivers
  */
 
+/*! \li \ref cdr_custom.c uses the configuration file \ref cdr_custom.conf
+ * \addtogroup configuration_file Configuration Files
+ */
+
+/*!
+ * \page cdr_custom.conf cdr_custom.conf
+ * \verbinclude cdr_custom.conf.sample
+ */
+
+/*** MODULEINFO
+       <support_level>core</support_level>
+ ***/
+
 #include "asterisk.h"
 
 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
@@ -54,20 +67,20 @@ AST_THREADSTORAGE(custom_buf);
 
 static const char name[] = "cdr-custom";
 
-struct cdr_config {
+struct cdr_custom_config {
        AST_DECLARE_STRING_FIELDS(
                AST_STRING_FIELD(filename);
                AST_STRING_FIELD(format);
                );
        ast_mutex_t lock;
-       AST_RWLIST_ENTRY(cdr_config) list;
+       AST_RWLIST_ENTRY(cdr_custom_config) list;
 };
 
-static AST_RWLIST_HEAD_STATIC(sinks, cdr_config);
+static AST_RWLIST_HEAD_STATIC(sinks, cdr_custom_config);
 
 static void free_config(void)
 {
-       struct cdr_config *sink;
+       struct cdr_custom_config *sink;
        while ((sink = AST_RWLIST_REMOVE_HEAD(&sinks, list))) {
                ast_mutex_destroy(&sink->lock);
                ast_free(sink);
@@ -90,7 +103,7 @@ static int load_config(void)
        var = ast_variable_browse(cfg, "mappings");
        while (var) {
                if (!ast_strlen_zero(var->name) && !ast_strlen_zero(var->value)) {
-                       struct cdr_config *sink = ast_calloc_with_stringfields(1, struct cdr_config, 1024);
+                       struct cdr_custom_config *sink = ast_calloc_with_stringfields(1, struct cdr_custom_config, 1024);
 
                        if (!sink) {
                                ast_log(LOG_ERROR, "Unable to allocate memory for configuration settings.\n");
@@ -117,7 +130,7 @@ static int custom_log(struct ast_cdr *cdr)
 {
        struct ast_channel *dummy;
        struct ast_str *str;
-       struct cdr_config *config;
+       struct cdr_custom_config *config;
 
        /* Batching saves memory management here.  Otherwise, it's the same as doing an allocation and free each time. */
        if (!(str = ast_str_thread_get(&custom_buf, 16))) {
@@ -125,7 +138,6 @@ static int custom_log(struct ast_cdr *cdr)
        }
 
        dummy = ast_dummy_channel_alloc();
-
        if (!dummy) {
                ast_log(LOG_ERROR, "Unable to allocate channel for variable subsitution.\n");
                return -1;
@@ -134,7 +146,7 @@ static int custom_log(struct ast_cdr *cdr)
        /* We need to dup here since the cdr actually belongs to the other channel,
           so when we release this channel we don't want the CDR getting cleaned
           up prematurely. */
-       dummy->cdr = ast_cdr_dup(cdr);
+       ast_channel_cdr_set(dummy, ast_cdr_dup(cdr));
 
        AST_RWLIST_RDLOCK(&sinks);
 
@@ -165,14 +177,16 @@ static int custom_log(struct ast_cdr *cdr)
 
        AST_RWLIST_UNLOCK(&sinks);
 
-       ast_channel_release(dummy);
+       ast_channel_unref(dummy);
 
        return 0;
 }
 
 static int unload_module(void)
 {
-       ast_cdr_unregister(name);
+       if (ast_cdr_unregister(name)) {
+               return -1;
+       }
 
        if (AST_RWLIST_WRLOCK(&sinks)) {
                ast_cdr_register(name, ast_module_info->description, custom_log);
@@ -211,9 +225,10 @@ static int reload(void)
        return AST_MODULE_LOAD_SUCCESS;
 }
 
-AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Customizable Comma Separated Values CDR Backend",
+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Customizable Comma Separated Values CDR Backend",
                .load = load_module,
                .unload = unload_module,
                .reload = reload,
+               .load_pri = AST_MODPRI_CDR_DRIVER,
               );