Add the ability to dynamically specify weights for responses to DUNDi queries.
[asterisk/asterisk.git] / main / cdr.c
index 19163cf..9c56f0f 100644 (file)
@@ -57,7 +57,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
 /*! Default AMA flag for billing records (CDR's) */
 int ast_default_amaflags = AST_CDR_DOCUMENTATION;
-char ast_default_accountcode[AST_MAX_ACCOUNT_CODE] = "";
+char ast_default_accountcode[AST_MAX_ACCOUNT_CODE];
 
 struct ast_cdr_beitem {
        char name[20];
@@ -77,7 +77,7 @@ static struct ast_cdr_batch {
        int size;
        struct ast_cdr_batch_item *head;
        struct ast_cdr_batch_item *tail;
-} *batch = NULL;
+} *batch;
 
 static struct sched_context *sched;
 static int cdr_sched = -1;
@@ -88,7 +88,7 @@ static pthread_t cdr_thread = AST_PTHREADT_NULL;
 #define BATCH_SCHEDULER_ONLY_DEFAULT 0
 #define BATCH_SAFE_SHUTDOWN_DEFAULT 1
 
-static int enabled;
+static int enabled;            /*! Is the CDR subsystem enabled ? */
 static int batchmode;
 static int batchsize;
 static int batchtime;
@@ -101,6 +101,10 @@ AST_MUTEX_DEFINE_STATIC(cdr_batch_lock);
 AST_MUTEX_DEFINE_STATIC(cdr_pending_lock);
 static ast_cond_t cdr_pending_cond;
 
+int check_cdr_enabled()
+{
+       return enabled;
+}
 
 /*! Register a CDR driver. Each registered CDR driver generates a CDR 
        \return 0 on success, -1 on failure 
@@ -288,7 +292,7 @@ int ast_cdr_setvar(struct ast_cdr *cdr, const char *name, const char *value, int
        struct varshead *headp;
        int x;
        
-       for(x = 0; cdr_readonly_vars[x]; x++) {
+       for (x = 0; cdr_readonly_vars[x]; x++) {
                if (!strcasecmp(name, cdr_readonly_vars[x])) {
                        ast_log(LOG_ERROR, "Attempt to set the '%s' read-only variable!.\n", name);
                        return -1;
@@ -344,7 +348,7 @@ int ast_cdr_copy_vars(struct ast_cdr *to_cdr, struct ast_cdr *from_cdr)
        return x;
 }
 
-int ast_cdr_serialize_variables(struct ast_cdr *cdr, char *buf, size_t size, char delim, char sep, int recur) 
+int ast_cdr_serialize_variables(struct ast_cdr *cdr, struct ast_str **buf, char delim, char sep, int recur) 
 {
        struct ast_var_t *variables;
        const char *var, *val;
@@ -352,17 +356,18 @@ int ast_cdr_serialize_variables(struct ast_cdr *cdr, char *buf, size_t size, cha
        char workspace[256];
        int total = 0, x = 0, i;
 
-       memset(buf, 0, size);
+       (*buf)->used = 0;
+       (*buf)->str[0] = '\0';
 
        for (; cdr; cdr = recur ? cdr->next : NULL) {
                if (++x > 1)
-                       ast_build_string(&buf, &size, "\n");
+                       ast_str_append(buf, 0, "\n");
 
                AST_LIST_TRAVERSE(&cdr->varshead, variables, entries) {
                        if (variables &&
                            (var = ast_var_name(variables)) && (val = ast_var_value(variables)) &&
                            !ast_strlen_zero(var) && !ast_strlen_zero(val)) {
-                               if (ast_build_string(&buf, &size, "level %d: %s%c%s%c", x, var, delim, val, sep)) {
+                               if (ast_str_append(buf, 0, "level %d: %s%c%s%c", x, var, delim, val, sep) < 0) {
                                        ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
                                        break;
                                } else
@@ -376,7 +381,7 @@ int ast_cdr_serialize_variables(struct ast_cdr *cdr, char *buf, size_t size, cha
                        if (!tmp)
                                continue;
                        
-                       if (ast_build_string(&buf, &size, "level %d: %s%c%s%c", x, cdr_readonly_vars[i], delim, tmp, sep)) {
+                       if (ast_str_append(buf, 0, "level %d: %s%c%s%c", x, cdr_readonly_vars[i], delim, tmp, sep) < 0) {
                                ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
                                break;
                        } else
@@ -404,14 +409,14 @@ void ast_cdr_free_vars(struct ast_cdr *cdr, int recur)
 static void check_post(struct ast_cdr *cdr)
 {
        if (ast_test_flag(cdr, AST_CDR_FLAG_POSTED))
-               ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", S_OR(cdr->channel, "<unknown>"));
+               ast_log(LOG_NOTICE, "CDR on channel '%s' already posted\n", S_OR(cdr->channel, "<unknown>"));
 }
 
 /*! \brief  print a warning if cdr already started */
 static void check_start(struct ast_cdr *cdr)
 {
        if (!ast_tvzero(cdr->start))
-               ast_log(LOG_WARNING, "CDR on channel '%s' already started\n", S_OR(cdr->channel, "<unknown>"));
+               ast_log(LOG_NOTICE, "CDR on channel '%s' already started\n", S_OR(cdr->channel, "<unknown>"));
 }
 
 void ast_cdr_free(struct ast_cdr *cdr)
@@ -421,11 +426,11 @@ void ast_cdr_free(struct ast_cdr *cdr)
                struct ast_cdr *next = cdr->next;
                char *chan = S_OR(cdr->channel, "<unknown>");
                if (!ast_test_flag(cdr, AST_CDR_FLAG_POSTED) && !ast_test_flag(cdr, AST_CDR_FLAG_POST_DISABLED))
-                       ast_log(LOG_WARNING, "CDR on channel '%s' not posted\n", chan);
+                       ast_log(LOG_NOTICE, "CDR on channel '%s' not posted\n", chan);
                if (ast_tvzero(cdr->end))
-                       ast_log(LOG_WARNING, "CDR on channel '%s' lacks end\n", chan);
+                       ast_log(LOG_NOTICE, "CDR on channel '%s' lacks end\n", chan);
                if (ast_tvzero(cdr->start))
-                       ast_log(LOG_WARNING, "CDR on channel '%s' lacks start\n", chan);
+                       ast_log(LOG_NOTICE, "CDR on channel '%s' lacks start\n", chan);
 
                ast_cdr_free_vars(cdr, 0);
                free(cdr);
@@ -492,7 +497,7 @@ int ast_cdr_disposition(struct ast_cdr *cdr, int cause)
        int res = 0;
 
        for (; cdr; cdr = cdr->next) {
-               switch(cause) {
+               switch (cause) {
                case AST_CAUSE_BUSY:
                        ast_cdr_busy(cdr);
                        break;
@@ -623,7 +628,7 @@ char *ast_cdr_disp2str(int disposition)
 /*! Converts AMA flag to printable string */
 char *ast_cdr_flags2str(int flag)
 {
-       switch(flag) {
+       switch (flag) {
        case AST_CDR_OMIT:
                return "OMIT";
        case AST_CDR_BILLING:
@@ -678,7 +683,7 @@ int ast_cdr_appenduserfield(struct ast_channel *chan, const char *userfield)
                int len = strlen(cdr->userfield);
 
                if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED))
-                       strncpy(cdr->userfield+len, userfield, sizeof(cdr->userfield) - len - 1);
+                       ast_copy_string(cdr->userfield + len, userfield, sizeof(cdr->userfield) - len);
        }
 
        return 0;
@@ -853,13 +858,14 @@ void ast_cdr_submit_batch(int shutdown)
        } else {
                pthread_attr_init(&attr);
                pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-               if (ast_pthread_create(&batch_post_thread, &attr, do_batch_backend_process, oldbatchitems)) {
+               if (ast_pthread_create_background(&batch_post_thread, &attr, do_batch_backend_process, oldbatchitems)) {
                        ast_log(LOG_WARNING, "CDR processing thread could not detach, now trying in this thread\n");
                        do_batch_backend_process(oldbatchitems);
                } else {
                        if (option_debug)
                                ast_log(LOG_DEBUG, "CDR multi-threaded batch processing begins now\n");
                }
+               pthread_attr_destroy(&attr);
        }
 }
 
@@ -944,7 +950,7 @@ static void *do_cdr(void *data)
        int schedms;
        int numevents = 0;
 
-       for(;;) {
+       for (;;) {
                struct timeval now;
                schedms = ast_sched_wait(sched);
                /* this shouldn't happen, but provide a 1 second default just in case */
@@ -984,10 +990,10 @@ static int handle_cli_status(int fd, int argc, char *argv[])
                                nextbatchtime = ast_sched_when(sched, cdr_sched);
                        ast_cli(fd, "CDR safe shut down: %s\n", batchsafeshutdown ? "enabled" : "disabled");
                        ast_cli(fd, "CDR batch threading model: %s\n", batchscheduleronly ? "scheduler only" : "scheduler plus separate threads");
-                       ast_cli(fd, "CDR current batch size: %d record%s\n", cnt, (cnt != 1) ? "s" : "");
-                       ast_cli(fd, "CDR maximum batch size: %d record%s\n", batchsize, (batchsize != 1) ? "s" : "");
-                       ast_cli(fd, "CDR maximum batch time: %d second%s\n", batchtime, (batchtime != 1) ? "s" : "");
-                       ast_cli(fd, "CDR next scheduled batch processing time: %ld second%s\n", nextbatchtime, (nextbatchtime != 1) ? "s" : "");
+                       ast_cli(fd, "CDR current batch size: %d record%s\n", cnt, ESS(cnt));
+                       ast_cli(fd, "CDR maximum batch size: %d record%s\n", batchsize, ESS(batchsize));
+                       ast_cli(fd, "CDR maximum batch time: %d second%s\n", batchtime, ESS(batchtime));
+                       ast_cli(fd, "CDR next scheduled batch processing time: %ld second%s\n", nextbatchtime, ESS(nextbatchtime));
                }
                AST_LIST_LOCK(&be_list);
                AST_LIST_TRAVERSE(&be_list, beitem, list) {
@@ -1011,19 +1017,15 @@ static int handle_cli_submit(int fd, int argc, char *argv[])
 }
 
 static struct ast_cli_entry cli_submit = {
-       .cmda = { "cdr", "submit", NULL },
-       .handler = handle_cli_submit,
-       .summary = "Posts all pending batched CDR data",
-       .usage =
+       { "cdr", "submit", NULL },
+       handle_cli_submit, "Posts all pending batched CDR data",
        "Usage: cdr submit\n"
        "       Posts all pending batched CDR data to the configured CDR backend engine modules.\n"
 };
 
 static struct ast_cli_entry cli_status = {
-       .cmda = { "cdr", "status", NULL },
-       .handler = handle_cli_status,
-       .summary = "Display the CDR status",
-       .usage =
+       { "cdr", "status", NULL },
+       handle_cli_status, "Display the CDR status",
        "Usage: cdr status\n"
        "       Displays the Call Detail Record engine system status.\n"
 };
@@ -1105,7 +1107,7 @@ static int do_reload(void)
           if it does not exist */
        if (enabled && batchmode && (!was_enabled || !was_batchmode) && (cdr_thread == AST_PTHREADT_NULL)) {
                ast_cond_init(&cdr_pending_cond, NULL);
-               if (ast_pthread_create(&cdr_thread, NULL, do_cdr, NULL) < 0) {
+               if (ast_pthread_create_background(&cdr_thread, NULL, do_cdr, NULL) < 0) {
                        ast_log(LOG_ERROR, "Unable to start CDR thread.\n");
                        ast_sched_del(sched, cdr_sched);
                } else {