Mon Sep 18 09:14:01 2006

Asterisk developer's documentation


cdr.c File Reference

Call Detail Record API. More...

#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <signal.h>
#include "asterisk.h"
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/cdr.h"
#include "asterisk/logger.h"
#include "asterisk/callerid.h"
#include "asterisk/causes.h"
#include "asterisk/options.h"
#include "asterisk/linkedlists.h"
#include "asterisk/utils.h"
#include "asterisk/sched.h"
#include "asterisk/config.h"
#include "asterisk/cli.h"
#include "asterisk/module.h"

Go to the source code of this file.

Data Structures

struct  ast_cdr_batch
struct  ast_cdr_batch_item
struct  ast_cdr_beitem

Defines

#define BATCH_SAFE_SHUTDOWN_DEFAULT   1
#define BATCH_SCHEDULER_ONLY_DEFAULT   0
#define BATCH_SIZE_DEFAULT   100
#define BATCH_TIME_DEFAULT   300

Functions

ast_cdrast_cdr_alloc (void)
 Allocate a CDR record Returns a malloc'd ast_cdr structure, returns NULL on error (malloc failure).
int ast_cdr_amaflags2int (const char *flag)
void ast_cdr_answer (struct ast_cdr *cdr)
ast_cdrast_cdr_append (struct ast_cdr *cdr, struct ast_cdr *newcdr)
int ast_cdr_appenduserfield (struct ast_channel *chan, const char *userfield)
void ast_cdr_busy (struct ast_cdr *cdr)
int ast_cdr_copy_vars (struct ast_cdr *to_cdr, struct ast_cdr *from_cdr)
void ast_cdr_detach (struct ast_cdr *cdr)
char * ast_cdr_disp2str (int disposition)
int ast_cdr_disposition (struct ast_cdr *cdr, int cause)
ast_cdrast_cdr_dup (struct ast_cdr *cdr)
 Duplicate a record Returns a malloc'd ast_cdr structure, returns NULL on error (malloc failure).
void ast_cdr_end (struct ast_cdr *cdr)
int ast_cdr_engine_init (void)
void ast_cdr_engine_reload (void)
void ast_cdr_engine_term (void)
void ast_cdr_failed (struct ast_cdr *cdr)
char * ast_cdr_flags2str (int flag)
void ast_cdr_free (struct ast_cdr *cdr)
 Free a CDR record.
void ast_cdr_free_vars (struct ast_cdr *cdr, int recur)
void ast_cdr_getvar (struct ast_cdr *cdr, const char *name, char **ret, char *workspace, int workspacelen, int recur)
static const char * ast_cdr_getvar_internal (struct ast_cdr *cdr, const char *name, int recur)
int ast_cdr_init (struct ast_cdr *cdr, struct ast_channel *c)
 Initialize based on a channel.
int ast_cdr_register (char *name, char *desc, ast_cdrbe be)
void ast_cdr_reset (struct ast_cdr *cdr, struct ast_flags *_flags)
int ast_cdr_serialize_variables (struct ast_cdr *cdr, char *buf, size_t size, char delim, char sep, int recur)
int ast_cdr_setaccount (struct ast_channel *chan, const char *account)
int ast_cdr_setamaflags (struct ast_channel *chan, const char *flag)
void ast_cdr_setapp (struct ast_cdr *cdr, char *app, char *data)
int ast_cdr_setcid (struct ast_cdr *cdr, struct ast_channel *c)
void ast_cdr_setdestchan (struct ast_cdr *cdr, char *chann)
int ast_cdr_setuserfield (struct ast_channel *chan, const char *userfield)
int ast_cdr_setvar (struct ast_cdr *cdr, const char *name, const char *value, int recur)
void ast_cdr_start (struct ast_cdr *cdr)
void ast_cdr_submit_batch (int shutdown)
void ast_cdr_unregister (char *name)
int ast_cdr_update (struct ast_channel *c)
static AST_LIST_HEAD_STATIC (be_list, ast_cdr_beitem)
 AST_MUTEX_DEFINE_STATIC (cdr_pending_lock)
 AST_MUTEX_DEFINE_STATIC (cdr_batch_lock)
static void * do_batch_backend_process (void *data)
static void * do_cdr (void *data)
static int do_reload (void)
static int handle_cli_status (int fd, int argc, char *argv[])
static int handle_cli_submit (int fd, int argc, char *argv[])
static int init_batch (void)
static void post_cdr (struct ast_cdr *cdr)
static void reset_batch (void)
static int submit_scheduled_batch (void *data)
static void submit_unscheduled_batch (void)

Variables

char ast_default_accountcode [AST_MAX_ACCOUNT_CODE] = ""
int ast_default_amaflags = AST_CDR_DOCUMENTATION
static struct ast_cdr_batchbatch
static int batchmode
static int batchsafeshutdown
static int batchscheduleronly
static int batchsize
static int batchtime
static ast_cond_t cdr_pending_cond
static int cdr_sched = -1
static pthread_t cdr_thread = AST_PTHREADT_NULL
static struct ast_cli_entry cli_status
static struct ast_cli_entry cli_submit
static int enabled
static struct sched_contextsched


Detailed Description

Call Detail Record API.

Includes code and algorithms from the Zapata library.

Note:
We do a lot of checking here in the CDR code to try to be sure we don't ever let a CDR slip through our fingers somehow. If someone allocates a CDR, it must be completely handled normally or a WARNING shall be logged, so that we can best keep track of any escape condition where the CDR isn't properly generated and posted.

Definition in file cdr.c.


Define Documentation

#define BATCH_SAFE_SHUTDOWN_DEFAULT   1

Definition at line 87 of file cdr.c.

Referenced by do_reload().

#define BATCH_SCHEDULER_ONLY_DEFAULT   0

Definition at line 86 of file cdr.c.

Referenced by do_reload().

#define BATCH_SIZE_DEFAULT   100

Definition at line 84 of file cdr.c.

Referenced by do_reload().

#define BATCH_TIME_DEFAULT   300

Definition at line 85 of file cdr.c.

Referenced by do_reload().


Function Documentation

struct ast_cdr* ast_cdr_alloc ( void   ) 

Allocate a CDR record Returns a malloc'd ast_cdr structure, returns NULL on error (malloc failure).

Definition at line 455 of file cdr.c.

References malloc.

Referenced by __agent_start_monitoring(), __ast_pbx_run(), __ast_request_and_dial(), ast_cdr_dup(), ast_feature_request_and_dial(), ast_pbx_outgoing_app(), ast_pbx_outgoing_cdr_failed(), ast_pbx_outgoing_exten(), and start_monitor_exec().

00456 {
00457    struct ast_cdr *cdr;
00458 
00459    cdr = malloc(sizeof(*cdr));
00460    if (cdr)
00461       memset(cdr, 0, sizeof(*cdr));
00462 
00463    return cdr;
00464 }

int ast_cdr_amaflags2int ( const char *  flag  ) 

Parameters:
flag string form of flag Converts the string form of the flag to the binary form. Returns the binary form of the flag

Definition at line 788 of file cdr.c.

References AST_CDR_BILLING, AST_CDR_DOCUMENTATION, and AST_CDR_OMIT.

Referenced by ast_cdr_setamaflags(), build_device(), build_gateway(), build_peer(), build_user(), set_config(), and setup_zap().

00789 {
00790    if (!strcasecmp(flag, "default"))
00791       return 0;
00792    if (!strcasecmp(flag, "omit"))
00793       return AST_CDR_OMIT;
00794    if (!strcasecmp(flag, "billing"))
00795       return AST_CDR_BILLING;
00796    if (!strcasecmp(flag, "documentation"))
00797       return AST_CDR_DOCUMENTATION;
00798    return -1;
00799 }

void ast_cdr_answer ( struct ast_cdr cdr  ) 

Parameters:
cdr the cdr you wish to associate with the call Starts all CDR stuff necessary for doing CDR when answering a call

Definition at line 483 of file cdr.c.

References ast_cdr::answer, AST_CDR_ANSWERED, AST_CDR_FLAG_POSTED, ast_log(), ast_strlen_zero(), ast_test_flag, ast_cdr::channel, ast_cdr::disposition, LOG_WARNING, and ast_cdr::next.

Referenced by ast_answer(), and ast_read().

00484 {
00485    char *chan; 
00486 
00487    while (cdr) {
00488       chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
00489       if (ast_test_flag(cdr, AST_CDR_FLAG_POSTED))
00490          ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
00491       if (cdr->disposition < AST_CDR_ANSWERED)
00492          cdr->disposition = AST_CDR_ANSWERED;
00493       if (ast_tvzero(cdr->answer))
00494          cdr->answer = ast_tvnow();
00495       cdr = cdr->next;
00496    }
00497 }

struct ast_cdr* ast_cdr_append ( struct ast_cdr cdr,
struct ast_cdr newcdr 
)

Definition at line 870 of file cdr.c.

References ast_cdr::next.

Referenced by ast_cdr_fork(), and attempt_transfer().

00871 {
00872    struct ast_cdr *ret;
00873 
00874    if (cdr) {
00875       ret = cdr;
00876 
00877       while (cdr->next)
00878          cdr = cdr->next;
00879       cdr->next = newcdr;
00880    } else {
00881       ret = newcdr;
00882    }
00883 
00884    return ret;
00885 }

int ast_cdr_appenduserfield ( struct ast_channel chan,
const char *  userfield 
)

Definition at line 741 of file cdr.c.

References AST_CDR_FLAG_LOCKED, ast_test_flag, ast_channel::cdr, ast_cdr::next, and ast_cdr::userfield.

Referenced by action_setcdruserfield(), appendcdruserfield_exec(), and ast_bridge_call().

00742 {
00743    struct ast_cdr *cdr = chan->cdr;
00744 
00745    while (cdr) {
00746       int len = strlen(cdr->userfield);
00747 
00748       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED))
00749          strncpy(cdr->userfield+len, userfield, sizeof(cdr->userfield) - len - 1);
00750 
00751       cdr = cdr->next;
00752    }
00753 
00754    return 0;
00755 }

void ast_cdr_busy ( struct ast_cdr cdr  ) 

Parameters:
cdr the cdr you wish to associate with the call Returns nothing important

Definition at line 499 of file cdr.c.

References AST_CDR_BUSY, AST_CDR_FLAG_LOCKED, AST_CDR_FLAG_POSTED, ast_log(), ast_strlen_zero(), ast_test_flag, ast_cdr::channel, ast_cdr::disposition, LOG_WARNING, and ast_cdr::next.

Referenced by ast_cdr_disposition(), ring_entry(), and wait_for_answer().

00500 {
00501    char *chan; 
00502 
00503    while (cdr) {
00504       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00505          chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
00506          if (ast_test_flag(cdr, AST_CDR_FLAG_POSTED))
00507             ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
00508          if (cdr->disposition < AST_CDR_BUSY)
00509             cdr->disposition = AST_CDR_BUSY;
00510       }
00511       cdr = cdr->next;
00512    }
00513 }

int ast_cdr_copy_vars ( struct ast_cdr to_cdr,
struct ast_cdr from_cdr 
)

Definition at line 326 of file cdr.c.

References AST_LIST_INSERT_HEAD, AST_LIST_TRAVERSE, ast_strlen_zero(), ast_var_assign(), ast_var_name(), ast_var_value(), var, and ast_cdr::varshead.

Referenced by ast_cdr_dup().

00327 {
00328    struct ast_var_t *variables, *newvariable = NULL;
00329    struct varshead *headpa, *headpb;
00330    char *var, *val;
00331    int x = 0;
00332 
00333    headpa = &from_cdr->varshead;
00334    headpb = &to_cdr->varshead;
00335 
00336    AST_LIST_TRAVERSE(headpa,variables,entries) {
00337       if (variables &&
00338           (var = ast_var_name(variables)) && (val = ast_var_value(variables)) &&
00339           !ast_strlen_zero(var) && !ast_strlen_zero(val)) {
00340          newvariable = ast_var_assign(var, val);
00341          AST_LIST_INSERT_HEAD(headpb, newvariable, entries);
00342          x++;
00343       }
00344    }
00345 
00346    return x;
00347 }

void ast_cdr_detach ( struct ast_cdr cdr  ) 

Parameters:
cdr Which CDR to detach from the channel thread Prevents the channel thread from blocking on the CDR handling Returns nothing

Definition at line 984 of file cdr.c.

References AST_CDR_FLAG_POST_DISABLED, ast_cdr_free(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_set_flag, batch, batchmode, batchsize, ast_cdr_batch_item::cdr, enabled, ast_cdr_batch::head, init_batch(), LOG_DEBUG, LOG_WARNING, malloc, ast_cdr_batch_item::next, option_debug, post_cdr(), ast_cdr_batch::size, submit_unscheduled_batch(), and ast_cdr_batch::tail.

Referenced by ast_cdr_reset(), ast_hangup(), and ast_pbx_outgoing_cdr_failed().

00985 {
00986    struct ast_cdr_batch_item *newtail;
00987    int curr;
00988 
00989    /* maybe they disabled CDR stuff completely, so just drop it */
00990    if (!enabled) {
00991       if (option_debug)
00992          ast_log(LOG_DEBUG, "Dropping CDR !\n");
00993       ast_set_flag(cdr, AST_CDR_FLAG_POST_DISABLED);
00994       ast_cdr_free(cdr);
00995       return;
00996    }
00997 
00998    /* post stuff immediately if we are not in batch mode, this is legacy behaviour */
00999    if (!batchmode) {
01000       post_cdr(cdr);
01001       ast_cdr_free(cdr);
01002       return;
01003    }
01004 
01005    /* otherwise, each CDR gets put into a batch list (at the end) */
01006    if (option_debug)
01007       ast_log(LOG_DEBUG, "CDR detaching from this thread\n");
01008 
01009    /* we'll need a new tail for every CDR */
01010    newtail = malloc(sizeof(*newtail));
01011    if (!newtail) {
01012       ast_log(LOG_WARNING, "CDR: out of memory while trying to detach, will try in this thread instead\n");
01013       post_cdr(cdr);
01014       ast_cdr_free(cdr);
01015       return;
01016    }
01017    memset(newtail, 0, sizeof(*newtail));
01018 
01019    /* don't traverse a whole list (just keep track of the tail) */
01020    ast_mutex_lock(&cdr_batch_lock);
01021    if (!batch)
01022       init_batch();
01023    if (!batch->head) {
01024       /* new batch is empty, so point the head at the new tail */
01025       batch->head = newtail;
01026    } else {
01027       /* already got a batch with something in it, so just append a new tail */
01028       batch->tail->next = newtail;
01029    }
01030    newtail->cdr = cdr;
01031    batch->tail = newtail;
01032    curr = batch->size++;
01033    ast_mutex_unlock(&cdr_batch_lock);
01034 
01035    /* if we have enough stuff to post, then do it */
01036    if (curr >= (batchsize - 1))
01037       submit_unscheduled_batch();
01038 }

char* ast_cdr_disp2str ( int  disposition  ) 

Parameters:
disposition input binary form Converts the binary form of a disposition to string form. Returns a pointer to the string form

Definition at line 671 of file cdr.c.

References AST_CDR_ANSWERED, AST_CDR_BUSY, AST_CDR_FAILED, and AST_CDR_NOANSWER.

Referenced by ast_cdr_getvar(), build_csv_record(), csv_log(), manager_log(), odbc_log(), pgsql_log(), and tds_log().

00672 {
00673    switch (disposition) {
00674    case AST_CDR_NOANSWER:
00675       return "NO ANSWER";
00676    case AST_CDR_FAILED:
00677       return "FAILED";     
00678    case AST_CDR_BUSY:
00679       return "BUSY";    
00680    case AST_CDR_ANSWERED:
00681       return "ANSWERED";
00682    }
00683    return "UNKNOWN";
00684 }

int ast_cdr_disposition ( struct ast_cdr cdr,
int  cause 
)

Parameters:
cdr the cdr you wish to associate with the call Returns nothing important
cause the AST_CAUSE_*

Definition at line 531 of file cdr.c.

References AST_CAUSE_BUSY, AST_CAUSE_FAILURE, AST_CAUSE_NORMAL, AST_CAUSE_NOTDEFINED, ast_cdr_busy(), ast_cdr_failed(), ast_log(), LOG_WARNING, and ast_cdr::next.

Referenced by __ast_request_and_dial(), ast_feature_request_and_dial(), ast_pbx_outgoing_app(), and ast_pbx_outgoing_exten().

00532 {
00533    int res = 0;
00534 
00535    while (cdr) {
00536       switch(cause) {
00537       case AST_CAUSE_BUSY:
00538          ast_cdr_busy(cdr);
00539          break;
00540       case AST_CAUSE_FAILURE:
00541          ast_cdr_failed(cdr);
00542          break;
00543       case AST_CAUSE_NORMAL:
00544          break;
00545       case AST_CAUSE_NOTDEFINED:
00546          res = -1;
00547          break;
00548       default:
00549          res = -1;
00550          ast_log(LOG_WARNING, "Cause not handled\n");
00551       }
00552       cdr = cdr->next;
00553    }
00554    return res;
00555 }

struct ast_cdr* ast_cdr_dup ( struct ast_cdr cdr  ) 

Duplicate a record Returns a malloc'd ast_cdr structure, returns NULL on error (malloc failure).

Duplicate a CDR record

Returns:
Pointer to new CDR record

Definition at line 167 of file cdr.c.

References ast_cdr_alloc(), ast_cdr_copy_vars(), ast_log(), and LOG_ERROR.

Referenced by ast_cdr_fork(), and ast_cdr_reset().

00168 {
00169    struct ast_cdr *newcdr;
00170 
00171    if (!(newcdr = ast_cdr_alloc())) {
00172       ast_log(LOG_ERROR, "Memory Error!\n");
00173       return NULL;
00174    }
00175 
00176    memcpy(newcdr, cdr, sizeof(*newcdr));
00177    /* The varshead is unusable, volatile even, after the memcpy so we take care of that here */
00178    memset(&newcdr->varshead, 0, sizeof(newcdr->varshead));
00179    ast_cdr_copy_vars(newcdr, cdr);
00180    newcdr->next = NULL;
00181 
00182    return newcdr;
00183 }

void ast_cdr_end ( struct ast_cdr cdr  ) 

Parameters:
cdr the cdr you have associated the call with Registers the end of call time in the cdr structure. Returns nothing important

Definition at line 655 of file cdr.c.

References AST_CDR_FLAG_POSTED, ast_log(), ast_strlen_zero(), ast_test_flag, ast_cdr::channel, ast_cdr::end, LOG_WARNING, ast_cdr::next, and ast_cdr::start.

Referenced by __ast_request_and_dial(), ast_cdr_reset(), ast_feature_request_and_dial(), ast_hangup(), ast_pbx_outgoing_cdr_failed(), and ast_read().

00656 {
00657    char *chan;
00658 
00659    while (cdr) {
00660       chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
00661       if (ast_test_flag(cdr, AST_CDR_FLAG_POSTED))
00662          ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
00663       if (ast_tvzero(cdr->start))
00664          ast_log(LOG_WARNING, "CDR on channel '%s' has not started\n", chan);
00665       if (ast_tvzero(cdr->end))
00666          cdr->end = ast_tvnow();
00667       cdr = cdr->next;
00668    }
00669 }

int ast_cdr_engine_init ( void   ) 

Load the configuration file cdr.conf and possibly start the CDR scheduling thread

Definition at line 1239 of file cdr.c.

References ast_cli_register(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), cli_status, do_reload(), init_batch(), LOG_ERROR, and sched_context_create().

Referenced by main().

01240 {
01241    int res;
01242 
01243    sched = sched_context_create();
01244    if (!sched) {
01245       ast_log(LOG_ERROR, "Unable to create schedule context.\n");
01246       return -1;
01247    }
01248 
01249    ast_cli_register(&cli_status);
01250 
01251    res = do_reload();
01252    if (res) {
01253       ast_mutex_lock(&cdr_batch_lock);
01254       res = init_batch();
01255       ast_mutex_unlock(&cdr_batch_lock);
01256    }
01257 
01258    return res;
01259 }

void ast_cdr_engine_reload ( void   ) 

Reload the configuration file cdr.conf and start/stop CDR scheduling thread

Definition at line 1268 of file cdr.c.

References do_reload().

Referenced by ast_module_reload().

01269 {
01270    do_reload();
01271 }

void ast_cdr_engine_term ( void   ) 

Submit any remaining CDRs and prepare for shutdown

Definition at line 1263 of file cdr.c.

References ast_cdr_submit_batch(), and batchsafeshutdown.

Referenced by do_reload(), and quit_handler().

01264 {
01265    ast_cdr_submit_batch(batchsafeshutdown);
01266 }

void ast_cdr_failed ( struct ast_cdr cdr  ) 

Parameters:
cdr the cdr you wish to associate with the call Returns nothing important

Definition at line 515 of file cdr.c.

References AST_CDR_FAILED, AST_CDR_FLAG_LOCKED, AST_CDR_FLAG_POSTED, ast_log(), ast_strlen_zero(), ast_test_flag, ast_cdr::channel, ast_cdr::disposition, LOG_WARNING, and ast_cdr::next.

Referenced by __ast_request_and_dial(), ast_cdr_disposition(), ast_feature_request_and_dial(), ast_pbx_outgoing_app(), ast_pbx_outgoing_cdr_failed(), and ast_pbx_outgoing_exten().

00516 {
00517    char *chan; 
00518 
00519    while (cdr) {
00520       chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
00521       if (ast_test_flag(cdr, AST_CDR_FLAG_POSTED))
00522          ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
00523       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00524          if (cdr->disposition < AST_CDR_FAILED)
00525             cdr->disposition = AST_CDR_FAILED;
00526       }
00527       cdr = cdr->next;
00528    }
00529 }

char* ast_cdr_flags2str ( int  flag  ) 

Converts AMA flag to printable string

Definition at line 687 of file cdr.c.

References AST_CDR_BILLING, AST_CDR_DOCUMENTATION, and AST_CDR_OMIT.

Referenced by _sip_show_peer(), ast_cdr_getvar(), build_csv_record(), csv_log(), manager_log(), sip_show_user(), and tds_log().

00688 {
00689    switch(flag) {
00690    case AST_CDR_OMIT:
00691       return "OMIT";
00692    case AST_CDR_BILLING:
00693       return "BILLING";
00694    case AST_CDR_DOCUMENTATION:
00695       return "DOCUMENTATION";
00696    }
00697    return "Unknown";
00698 }

void ast_cdr_free ( struct ast_cdr cdr  ) 

Free a CDR record.

Parameters:
cdr ast_cdr structure to free Returns nothing important

Definition at line 434 of file cdr.c.

References AST_CDR_FLAG_POST_DISABLED, AST_CDR_FLAG_POSTED, ast_cdr_free_vars(), ast_log(), ast_strlen_zero(), ast_test_flag, ast_cdr::channel, ast_cdr::end, free, LOG_WARNING, ast_cdr::next, and ast_cdr::start.

Referenced by ast_cdr_detach(), do_batch_backend_process(), and nocdr_exec().

00435 {
00436    char *chan;
00437    struct ast_cdr *next; 
00438 
00439    while (cdr) {
00440       next = cdr->next;
00441       chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
00442       if (!ast_test_flag(cdr, AST_CDR_FLAG_POSTED) && !ast_test_flag(cdr, AST_CDR_FLAG_POST_DISABLED))
00443          ast_log(LOG_WARNING, "CDR on channel '%s' not posted\n", chan);
00444       if (ast_tvzero(cdr->end))
00445          ast_log(LOG_WARNING, "CDR on channel '%s' lacks end\n", chan);
00446       if (ast_tvzero(cdr->start))
00447          ast_log(LOG_WARNING, "CDR on channel '%s' lacks start\n", chan);
00448 
00449       ast_cdr_free_vars(cdr, 0);
00450       free(cdr);
00451       cdr = next;
00452    }
00453 }

void ast_cdr_free_vars ( struct ast_cdr cdr,
int  recur 
)

Definition at line 413 of file cdr.c.

References AST_LIST_EMPTY, AST_LIST_REMOVE_HEAD, ast_var_delete(), ast_cdr::next, and ast_cdr::varshead.

Referenced by ast_cdr_fork(), ast_cdr_free(), and ast_cdr_reset().

00414 {
00415    struct varshead *headp;
00416    struct ast_var_t *vardata;
00417 
00418    /* clear variables */
00419    while (cdr) {
00420       headp = &cdr->varshead;
00421       while (!AST_LIST_EMPTY(headp)) {
00422          vardata = AST_LIST_REMOVE_HEAD(headp, entries);
00423          ast_var_delete(vardata);
00424       }
00425 
00426       if (!recur) {
00427          break;
00428       }
00429 
00430       cdr = cdr->next;
00431    }
00432 }

void ast_cdr_getvar ( struct ast_cdr cdr,
const char *  name,
char **  ret,
char *  workspace,
int  workspacelen,
int  recur 
)

CDR channel variable retrieval

Definition at line 208 of file cdr.c.

References ast_cdr::accountcode, ast_cdr::amaflags, ast_cdr::answer, ast_cdr_disp2str(), ast_cdr_flags2str(), ast_cdr_getvar_internal(), ast_strlen_zero(), ast_cdr::billsec, ast_cdr::channel, ast_cdr::clid, ast_cdr::dcontext, ast_cdr::disposition, ast_cdr::dst, ast_cdr::dstchannel, ast_cdr::duration, ast_cdr::end, fmt, ast_cdr::lastapp, ast_cdr::lastdata, ast_cdr::src, ast_cdr::start, t, ast_cdr::uniqueid, and ast_cdr::userfield.

Referenced by ast_cdr_serialize_variables(), builtin_function_cdr_read(), and pickup_exec().

00209 {
00210    struct tm tm;
00211    time_t t;
00212    const char *fmt = "%Y-%m-%d %T";
00213    const char *varbuf;
00214 
00215    *ret = NULL;
00216    /* special vars (the ones from the struct ast_cdr when requested by name) 
00217       I'd almost say we should convert all the stringed vals to vars */
00218 
00219    if (!strcasecmp(name, "clid"))
00220       ast_copy_string(workspace, cdr->clid, workspacelen);
00221    else if (!strcasecmp(name, "src"))
00222       ast_copy_string(workspace, cdr->src, workspacelen);
00223    else if (!strcasecmp(name, "dst"))
00224       ast_copy_string(workspace, cdr->dst, workspacelen);
00225    else if (!strcasecmp(name, "dcontext"))
00226       ast_copy_string(workspace, cdr->dcontext, workspacelen);
00227    else if (!strcasecmp(name, "channel"))
00228       ast_copy_string(workspace, cdr->channel, workspacelen);
00229    else if (!strcasecmp(name, "dstchannel"))
00230       ast_copy_string(workspace, cdr->dstchannel, workspacelen);
00231    else if (!strcasecmp(name, "lastapp"))
00232       ast_copy_string(workspace, cdr->lastapp, workspacelen);
00233    else if (!strcasecmp(name, "lastdata"))
00234       ast_copy_string(workspace, cdr->lastdata, workspacelen);
00235    else if (!strcasecmp(name, "start")) {
00236       t = cdr->start.tv_sec;
00237       if (t) {
00238          localtime_r(&t, &tm);
00239          strftime(workspace, workspacelen, fmt, &tm);
00240       }
00241    } else if (!strcasecmp(name, "answer")) {
00242       t = cdr->answer.tv_sec;
00243       if (t) {
00244          localtime_r(&t, &tm);
00245          strftime(workspace, workspacelen, fmt, &tm);
00246       }
00247    } else if (!strcasecmp(name, "end")) {
00248       t = cdr->end.tv_sec;
00249       if (t) {
00250          localtime_r(&t, &tm);
00251          strftime(workspace, workspacelen, fmt, &tm);
00252       }
00253    } else if (!strcasecmp(name, "duration"))
00254       snprintf(workspace, workspacelen, "%ld", cdr->duration);
00255    else if (!strcasecmp(name, "billsec"))
00256       snprintf(workspace, workspacelen, "%ld", cdr->billsec);
00257    else if (!strcasecmp(name, "disposition"))
00258       ast_copy_string(workspace, ast_cdr_disp2str(cdr->disposition), workspacelen);
00259    else if (!strcasecmp(name, "amaflags"))
00260       ast_copy_string(workspace, ast_cdr_flags2str(cdr->amaflags), workspacelen);
00261    else if (!strcasecmp(name, "accountcode"))
00262       ast_copy_string(workspace, cdr->accountcode, workspacelen);
00263    else if (!strcasecmp(name, "uniqueid"))
00264       ast_copy_string(workspace, cdr->uniqueid, workspacelen);
00265    else if (!strcasecmp(name, "userfield"))
00266       ast_copy_string(workspace, cdr->userfield, workspacelen);
00267    else if ((varbuf = ast_cdr_getvar_internal(cdr, name, recur)))
00268       ast_copy_string(workspace, varbuf, workspacelen);
00269 
00270    if (!ast_strlen_zero(workspace))
00271       *ret = workspace;
00272 }

static const char* ast_cdr_getvar_internal ( struct ast_cdr cdr,
const char *  name,
int  recur 
) [static]

Definition at line 185 of file cdr.c.

References AST_LIST_TRAVERSE, ast_strlen_zero(), ast_var_name(), ast_var_value(), ast_cdr::next, and ast_cdr::varshead.

Referenced by ast_cdr_getvar().

00186 {
00187    struct ast_var_t *variables;
00188    struct varshead *headp;
00189 
00190    if (ast_strlen_zero(name))
00191       return NULL;
00192 
00193    while (cdr) {
00194       headp = &cdr->varshead;
00195       AST_LIST_TRAVERSE(headp, variables, entries) {
00196          if (!strcasecmp(name, ast_var_name(variables)))
00197             return ast_var_value(variables);
00198       }
00199       if (!recur)
00200          break;
00201       cdr = cdr->next;
00202    }
00203 
00204    return NULL;
00205 }

int ast_cdr_init ( struct ast_cdr cdr,
struct ast_channel chan 
)

Initialize based on a channel.

Parameters:
cdr Call Detail Record to use for channel
chan Channel to bind CDR with Initializes a CDR and associates it with a particular channel Return is negligible. (returns 0 by default)

Definition at line 617 of file cdr.c.

References ast_channel::_state, ast_cdr::accountcode, ast_channel::accountcode, ast_cdr::amaflags, ast_channel::amaflags, AST_CDR_ANSWERED, AST_CDR_FLAG_LOCKED, AST_CDR_NOANSWER, ast_log(), AST_MAX_EXTENSION, AST_STATE_UP, ast_strlen_zero(), ast_test_flag, ast_cdr::channel, ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_name, ast_callerid::cid_num, ast_cdr::clid, ast_channel::context, ast_cdr::dcontext, ast_cdr::disposition, ast_cdr::dst, ast_channel::exten, LOG_WARNING, ast_channel::name, ast_cdr::next, ast_cdr::src, ast_cdr::uniqueid, and ast_channel::uniqueid.

Referenced by __ast_pbx_run(), __ast_request_and_dial(), ast_feature_request_and_dial(), ast_pbx_outgoing_app(), ast_pbx_outgoing_cdr_failed(), and ast_pbx_outgoing_exten().

00618 {
00619    char *chan;
00620    char *num;
00621    char tmp[AST_MAX_EXTENSION] = "";
00622 
00623    while (cdr) {
00624       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00625          chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
00626          if (!ast_strlen_zero(cdr->channel)) 
00627             ast_log(LOG_WARNING, "CDR already initialized on '%s'\n", chan); 
00628          ast_copy_string(cdr->channel, c->name, sizeof(cdr->channel));
00629          /* Grab source from ANI or normal Caller*ID */
00630          num = c->cid.cid_ani ? c->cid.cid_ani : c->cid.cid_num;
00631          
00632          if (c->cid.cid_name && num)
00633             snprintf(tmp, sizeof(tmp), "\"%s\" <%s>", c->cid.cid_name, num);
00634          else if (c->cid.cid_name)
00635             ast_copy_string(tmp, c->cid.cid_name, sizeof(tmp));
00636          else if (num)
00637             ast_copy_string(tmp, num, sizeof(tmp));
00638          ast_copy_string(cdr->clid, tmp, sizeof(cdr->clid));
00639          ast_copy_string(cdr->src, num ? num : "", sizeof(cdr->src));
00640 
00641          cdr->disposition = (c->_state == AST_STATE_UP) ?  AST_CDR_ANSWERED : AST_CDR_NOANSWER;
00642          cdr->amaflags = c->amaflags ? c->amaflags :  ast_default_amaflags;
00643          ast_copy_string(cdr->accountcode, c->accountcode, sizeof(cdr->accountcode));
00644          /* Destination information */
00645          ast_copy_string(cdr->dst, c->exten, sizeof(cdr->dst));
00646          ast_copy_string(cdr->dcontext, c->context, sizeof(cdr->dcontext));
00647          /* Unique call identifier */
00648          ast_copy_string(cdr->uniqueid, c->uniqueid, sizeof(cdr->uniqueid));
00649       }
00650       cdr = cdr->next;
00651    }
00652    return 0;
00653 }

int ast_cdr_register ( char *  name,
char *  desc,
ast_cdrbe  be 
)

Register a CDR driver. Each registered CDR driver generates a CDR

Returns:
0 on success, -1 on failure

Definition at line 106 of file cdr.c.

References AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), list, LOG_WARNING, malloc, and ast_cdr_beitem::name.

Referenced by load_module(), odbc_load_module(), process_my_load_module(), and tds_load_module().

00107 {
00108    struct ast_cdr_beitem *i;
00109 
00110    if (!name)
00111       return -1;
00112    if (!be) {
00113       ast_log(LOG_WARNING, "CDR engine '%s' lacks backend\n", name);
00114       return -1;
00115    }
00116 
00117    AST_LIST_LOCK(&be_list);
00118    AST_LIST_TRAVERSE(&be_list, i, list) {
00119       if (!strcasecmp(name, i->name))
00120          break;
00121    }
00122    AST_LIST_UNLOCK(&be_list);
00123 
00124    if (i) {
00125       ast_log(LOG_WARNING, "Already have a CDR backend called '%s'\n", name);
00126       return -1;
00127    }
00128 
00129    i = malloc(sizeof(*i));
00130    if (!i)  
00131       return -1;
00132 
00133    memset(i, 0, sizeof(*i));
00134    i->be = be;
00135    ast_copy_string(i->name, name, sizeof(i->name));
00136    ast_copy_string(i->desc, desc, sizeof(i->desc));
00137 
00138    AST_LIST_LOCK(&be_list);
00139    AST_LIST_INSERT_HEAD(&be_list, i, list);
00140    AST_LIST_UNLOCK(&be_list);
00141 
00142    return 0;
00143 }

void ast_cdr_reset ( struct ast_cdr cdr,
struct ast_flags flags 
)

Parameters:
cdr which cdr to act upon
flags |AST_CDR_FLAG_POSTED whether or not to post the cdr first before resetting it |AST_CDR_FLAG_LOCKED whether or not to reset locked CDR's

Definition at line 831 of file cdr.c.

References ast_cdr::answer, ast_cdr_detach(), ast_cdr_dup(), ast_cdr_end(), AST_CDR_FLAG_KEEP_VARS, AST_CDR_FLAG_LOCKED, AST_CDR_FLAG_POSTED, ast_cdr_free_vars(), AST_CDR_NOANSWER, ast_cdr_start(), ast_clear_flag, ast_copy_flags, AST_FLAGS_ALL, ast_set_flag, ast_test_flag, ast_cdr::billsec, ast_cdr::disposition, ast_cdr::duration, ast_cdr::end, ast_flags::flags, ast_cdr::next, and ast_cdr::start.

Referenced by ast_bridge_call_thread(), ast_cdr_fork(), dial_exec_full(), disa_exec(), and pbx_builtin_resetcdr().

00832 {
00833    struct ast_cdr *dup;
00834    struct ast_flags flags = { 0 };
00835 
00836    if (_flags)
00837       ast_copy_flags(&flags, _flags, AST_FLAGS_ALL);
00838 
00839    while (cdr) {
00840       /* Detach if post is requested */
00841       if (ast_test_flag(&flags, AST_CDR_FLAG_LOCKED) || !ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00842          if (ast_test_flag(&flags, AST_CDR_FLAG_POSTED)) {
00843             ast_cdr_end(cdr);
00844             if ((dup = ast_cdr_dup(cdr))) {
00845                ast_cdr_detach(dup);
00846             }
00847             ast_set_flag(cdr, AST_CDR_FLAG_POSTED);
00848          }
00849 
00850          /* clear variables */
00851          if (!ast_test_flag(&flags, AST_CDR_FLAG_KEEP_VARS)) {
00852             ast_cdr_free_vars(cdr, 0);
00853          }
00854 
00855          /* Reset to initial state */
00856          ast_clear_flag(cdr, AST_FLAGS_ALL); 
00857          memset(&cdr->start, 0, sizeof(cdr->start));
00858          memset(&cdr->end, 0, sizeof(cdr->end));
00859          memset(&cdr->answer, 0, sizeof(cdr->answer));
00860          cdr->billsec = 0;
00861          cdr->duration = 0;
00862          ast_cdr_start(cdr);
00863          cdr->disposition = AST_CDR_NOANSWER;
00864       }
00865          
00866       cdr = cdr->next;
00867    }
00868 }

int ast_cdr_serialize_variables ( struct ast_cdr cdr,
char *  buf,
size_t  size,
char  delim,
char  sep,
int  recur 
)

Definition at line 349 of file cdr.c.

References ast_build_string(), ast_cdr_getvar(), AST_LIST_TRAVERSE, ast_log(), ast_strlen_zero(), ast_var_name(), ast_var_value(), LOG_ERROR, ast_cdr::next, total, var, and ast_cdr::varshead.

Referenced by handle_showchan().

00350 {
00351    struct ast_var_t *variables;
00352    char *var, *val;
00353    char *tmp;
00354    char workspace[256];
00355    int total = 0, x = 0, i;
00356    const char *cdrcols[] = { 
00357       "clid",
00358       "src",
00359       "dst",
00360       "dcontext",
00361       "channel",
00362       "dstchannel",
00363       "lastapp",
00364       "lastdata",
00365       "start",
00366       "answer",
00367       "end",
00368       "duration",
00369       "billsec",
00370       "disposition",
00371       "amaflags",
00372       "accountcode",
00373       "uniqueid",
00374       "userfield"
00375    };
00376 
00377    memset(buf, 0, size);
00378 
00379    for (; cdr; cdr = recur ? cdr->next : NULL) {
00380       if (++x > 1)
00381          ast_build_string(&buf, &size, "\n");
00382 
00383       AST_LIST_TRAVERSE(&cdr->varshead, variables, entries) {
00384          if (variables &&
00385              (var = ast_var_name(variables)) && (val = ast_var_value(variables)) &&
00386              !ast_strlen_zero(var) && !ast_strlen_zero(val)) {
00387             if (ast_build_string(&buf, &size, "level %d: %s%c%s%c", x, var, delim, val, sep)) {
00388                ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
00389                break;
00390             } else
00391                total++;
00392          } else 
00393             break;
00394       }
00395 
00396       for (i = 0; i < (sizeof(cdrcols) / sizeof(cdrcols[0])); i++) {
00397          ast_cdr_getvar(cdr, cdrcols[i], &tmp, workspace, sizeof(workspace), 0);
00398          if (!tmp)
00399             continue;
00400          
00401          if (ast_build_string(&buf, &size, "level %d: %s%c%s%c", x, cdrcols[i], delim, tmp, sep)) {
00402             ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
00403             break;
00404          } else
00405             total++;
00406       }
00407    }
00408 
00409    return total;
00410 }

int ast_cdr_setaccount ( struct ast_channel chan,
const char *  account 
)

Definition at line 700 of file cdr.c.

References ast_channel::accountcode, ast_cdr::accountcode, AST_CDR_FLAG_LOCKED, ast_test_flag, ast_channel::cdr, and ast_cdr::next.

Referenced by __ast_request_and_dial(), ast_pbx_outgoing_app(), ast_pbx_outgoing_exten(), auth_exec(), builtin_function_cdr_write(), and pbx_builtin_setaccount().

00701 {
00702    struct ast_cdr *cdr = chan->cdr;
00703 
00704    ast_copy_string(chan->accountcode, account, sizeof(chan->accountcode));
00705    while (cdr) {
00706       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED))
00707          ast_copy_string(cdr->accountcode, chan->accountcode, sizeof(cdr->accountcode));
00708       cdr = cdr->next;
00709    }
00710    return 0;
00711 }

int ast_cdr_setamaflags ( struct ast_channel chan,
const char *  flag 
)

Definition at line 713 of file cdr.c.

References ast_cdr::amaflags, ast_cdr_amaflags2int(), ast_channel::cdr, and ast_cdr::next.

Referenced by pbx_builtin_setamaflags().

00714 {
00715    struct ast_cdr *cdr;
00716    int newflag;
00717 
00718    newflag = ast_cdr_amaflags2int(flag);
00719    if (newflag) {
00720       for (cdr = chan->cdr; cdr; cdr = cdr->next) {
00721          cdr->amaflags = newflag;
00722       }
00723    }
00724 
00725    return 0;
00726 }

void ast_cdr_setapp ( struct ast_cdr cdr,
char *  app,
char *  data 
)

Parameters:
cdr which cdr to act upon
app the name of the app you wish to change it to
data the data you want in the data field of app you set it to Changes the value of the last executed app Returns nothing

Definition at line 571 of file cdr.c.

References AST_CDR_FLAG_LOCKED, AST_CDR_FLAG_POSTED, ast_log(), ast_strlen_zero(), ast_test_flag, ast_cdr::channel, ast_cdr::lastapp, ast_cdr::lastdata, LOG_WARNING, and ast_cdr::next.

Referenced by __ast_request_and_dial(), ast_feature_request_and_dial(), and pbx_exec().

00572 {
00573    char *chan; 
00574 
00575    while (cdr) {
00576       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00577          chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
00578          if (ast_test_flag(cdr, AST_CDR_FLAG_POSTED))
00579             ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
00580          if (!app)
00581             app = "";
00582          ast_copy_string(cdr->lastapp, app, sizeof(cdr->lastapp));
00583          if (!data)
00584             data = "";
00585          ast_copy_string(cdr->lastdata, data, sizeof(cdr->lastdata));
00586       }
00587       cdr = cdr->next;
00588    }
00589 }

int ast_cdr_setcid ( struct ast_cdr cdr,
struct ast_channel chan 
)

Parameters:
cdr Call Detail Record to use for channel
chan Channel to bind CDR with Initializes a CDR and associates it with a particular channel Return is negligible. (returns 0 by default)

Definition at line 591 of file cdr.c.

References AST_CDR_FLAG_LOCKED, AST_MAX_EXTENSION, ast_test_flag, ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_name, ast_callerid::cid_num, ast_cdr::clid, ast_cdr::next, and ast_cdr::src.

Referenced by ast_set_callerid().

00592 {
00593    char tmp[AST_MAX_EXTENSION] = "";
00594    char *num;
00595 
00596    while (cdr) {
00597       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00598          /* Grab source from ANI or normal Caller*ID */
00599          num = c->cid.cid_ani ? c->cid.cid_ani : c->cid.cid_num;
00600          
00601          if (c->cid.cid_name && num)
00602             snprintf(tmp, sizeof(tmp), "\"%s\" <%s>", c->cid.cid_name, num);
00603          else if (c->cid.cid_name)
00604             ast_copy_string(tmp, c->cid.cid_name, sizeof(tmp));
00605          else if (num)
00606             ast_copy_string(tmp, num, sizeof(tmp));
00607          ast_copy_string(cdr->clid, tmp, sizeof(cdr->clid));
00608          ast_copy_string(cdr->src, num ? num : "", sizeof(cdr->src));
00609       }
00610       cdr = cdr->next;
00611    }
00612 
00613    return 0;
00614 }

void ast_cdr_setdestchan ( struct ast_cdr cdr,
char *  chan 
)

Parameters:
cdr Which cdr it's applied to
chan Channel to which dest will be Sets the destination channel the CDR is applied to Returns nothing

Definition at line 557 of file cdr.c.

References AST_CDR_FLAG_LOCKED, AST_CDR_FLAG_POSTED, ast_log(), ast_strlen_zero(), ast_test_flag, ast_cdr::channel, ast_cdr::dstchannel, LOG_WARNING, and ast_cdr::next.

Referenced by ast_bridge_call_thread(), dial_exec_full(), and try_calling().

00558 {
00559    char *chan; 
00560 
00561    while (cdr) {
00562       chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
00563       if (ast_test_flag(cdr, AST_CDR_FLAG_POSTED))
00564          ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
00565       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED))
00566          ast_copy_string(cdr->dstchannel, chann, sizeof(cdr->dstchannel));
00567       cdr = cdr->next;
00568    }
00569 }

int ast_cdr_setuserfield ( struct ast_channel chan,
const char *  userfield 
)

Definition at line 728 of file cdr.c.

References AST_CDR_FLAG_LOCKED, ast_test_flag, ast_channel::cdr, ast_cdr::next, and ast_cdr::userfield.

Referenced by __agent_start_monitoring(), action_setcdruserfield(), ast_bridge_call(), builtin_function_cdr_write(), handle_request_info(), setcdruserfield_exec(), and start_monitor_exec().

00729 {
00730    struct ast_cdr *cdr = chan->cdr;
00731 
00732    while (cdr) {
00733       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) 
00734          ast_copy_string(cdr->userfield, userfield, sizeof(cdr->userfield));
00735       cdr = cdr->next;
00736    }
00737 
00738    return 0;
00739 }

int ast_cdr_setvar ( struct ast_cdr cdr,
const char *  name,
const char *  value,
int  recur 
)

Set a CDR channel variable

Note:
You can't set the CDR variables that belong to the actual CDR record, like "billsec".

Definition at line 277 of file cdr.c.

References AST_LIST_INSERT_HEAD, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_log(), ast_var_assign(), ast_var_delete(), ast_var_name(), LOG_ERROR, ast_cdr::next, and ast_cdr::varshead.

Referenced by builtin_function_cdr_write().

00278 {
00279    struct ast_var_t *newvariable;
00280    struct varshead *headp;
00281    const char *read_only[] = { "clid", "src", "dst", "dcontext", "channel", "dstchannel",
00282                 "lastapp", "lastdata", "start", "answer", "end", "duration",
00283                 "billsec", "disposition", "amaflags", "accountcode", "uniqueid",
00284                 "userfield", NULL };
00285    int x;
00286    
00287    for(x = 0; read_only[x]; x++) {
00288       if (!strcasecmp(name, read_only[x])) {
00289          ast_log(LOG_ERROR, "Attempt to set a read-only variable!.\n");
00290          return -1;
00291       }
00292    }
00293 
00294    if (!cdr) {
00295       ast_log(LOG_ERROR, "Attempt to set a variable on a nonexistent CDR record.\n");
00296       return -1;
00297    }
00298 
00299    while (cdr) {
00300       headp = &cdr->varshead;
00301       AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) {
00302          if (!strcasecmp(ast_var_name(newvariable), name)) {
00303             /* there is already such a variable, delete it */
00304             AST_LIST_REMOVE_CURRENT(headp, entries);
00305             ast_var_delete(newvariable);
00306             break;
00307          }
00308       }
00309       AST_LIST_TRAVERSE_SAFE_END;
00310 
00311       if (value) {
00312          newvariable = ast_var_assign(name, value);
00313          AST_LIST_INSERT_HEAD(headp, newvariable, entries);
00314       }
00315 
00316       if (!recur) {
00317          break;
00318       }
00319 
00320       cdr = cdr->next;
00321    }
00322 
00323    return 0;
00324 }

void ast_cdr_start ( struct ast_cdr cdr  ) 

Parameters:
cdr the cdr you wish to associate with the call Starts all CDR stuff necessary for monitoring a call Returns nothing important

Definition at line 466 of file cdr.c.

References AST_CDR_FLAG_LOCKED, AST_CDR_FLAG_POSTED, ast_log(), ast_strlen_zero(), ast_test_flag, ast_cdr::channel, LOG_WARNING, ast_cdr::next, and ast_cdr::start.

Referenced by __ast_pbx_run(), __ast_request_and_dial(), ast_cdr_reset(), ast_feature_request_and_dial(), ast_pbx_outgoing_app(), ast_pbx_outgoing_cdr_failed(), and ast_pbx_outgoing_exten().

00467 {
00468    char *chan; 
00469 
00470    while (cdr) {
00471       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00472          chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
00473          if (ast_test_flag(cdr, AST_CDR_FLAG_POSTED))
00474             ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
00475          if (!ast_tvzero(cdr->start))
00476             ast_log(LOG_WARNING, "CDR on channel '%s' already started\n", chan);
00477          cdr->start = ast_tvnow();
00478       }
00479       cdr = cdr->next;
00480    }
00481 }

void ast_cdr_submit_batch ( int  shutdown  ) 

Parameters:
shutdown Whether or not we are shutting down Blocks the asterisk shutdown procedures until the CDR data is submitted. Returns nothing

Definition at line 927 of file cdr.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create, AST_PTHREADT_NULL, batch, batchscheduleronly, do_batch_backend_process(), ast_cdr_batch::head, LOG_DEBUG, LOG_WARNING, option_debug, and reset_batch().

Referenced by ast_cdr_engine_term(), and submit_scheduled_batch().

00928 {
00929    struct ast_cdr_batch_item *oldbatchitems = NULL;
00930    pthread_attr_t attr;
00931    pthread_t batch_post_thread = AST_PTHREADT_NULL;
00932 
00933    /* if there's no batch, or no CDRs in the batch, then there's nothing to do */
00934    if (!batch || !batch->head)
00935       return;
00936 
00937    /* move the old CDRs aside, and prepare a new CDR batch */
00938    ast_mutex_lock(&cdr_batch_lock);
00939    oldbatchitems = batch->head;
00940    reset_batch();
00941    ast_mutex_unlock(&cdr_batch_lock);
00942 
00943    /* if configured, spawn a new thread to post these CDRs,
00944       also try to save as much as possible if we are shutting down safely */
00945    if (batchscheduleronly || shutdown) {
00946       if (option_debug)
00947          ast_log(LOG_DEBUG, "CDR single-threaded batch processing begins now\n");
00948       do_batch_backend_process(oldbatchitems);
00949    } else {
00950       pthread_attr_init(&attr);
00951       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
00952       if (ast_pthread_create(&batch_post_thread, &attr, do_batch_backend_process, oldbatchitems)) {
00953          ast_log(LOG_WARNING, "CDR processing thread could not detach, now trying in this thread\n");
00954          do_batch_backend_process(oldbatchitems);
00955       } else {
00956          if (option_debug)
00957             ast_log(LOG_DEBUG, "CDR multi-threaded batch processing begins now\n");
00958       }
00959    }
00960 }

void ast_cdr_unregister ( char *  name  ) 

unregister a CDR driver

Definition at line 146 of file cdr.c.

References AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_verbose(), free, list, ast_cdr_beitem::name, option_verbose, and VERBOSE_PREFIX_2.

Referenced by my_unload_module(), odbc_unload_module(), tds_unload_module(), and unload_module().

00147 {
00148    struct ast_cdr_beitem *i = NULL;
00149 
00150    AST_LIST_LOCK(&be_list);
00151    AST_LIST_TRAVERSE_SAFE_BEGIN(&be_list, i, list) {
00152       if (!strcasecmp(name, i->name)) {
00153          AST_LIST_REMOVE_CURRENT(&be_list, list);
00154          if (option_verbose > 1)
00155             ast_verbose(VERBOSE_PREFIX_2 "Unregistered '%s' CDR backend\n", name);
00156          free(i);
00157          break;
00158       }
00159    }
00160    AST_LIST_TRAVERSE_SAFE_END;
00161    AST_LIST_UNLOCK(&be_list);
00162 }

int ast_cdr_update ( struct ast_channel c  ) 

Definition at line 757 of file cdr.c.

References ast_cdr::accountcode, ast_channel::accountcode, AST_CDR_FLAG_LOCKED, AST_MAX_EXTENSION, ast_strlen_zero(), ast_test_flag, ast_channel::cdr, ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_name, ast_callerid::cid_num, ast_cdr::clid, ast_channel::context, ast_cdr::dcontext, ast_cdr::dst, ast_channel::exten, ast_channel::macrocontext, ast_channel::macroexten, ast_cdr::next, and ast_cdr::src.

Referenced by __ast_pbx_run(), __ast_request_and_dial(), ast_feature_request_and_dial(), ast_parseable_goto(), and cb_events().

00758 {
00759    struct ast_cdr *cdr = c->cdr;
00760    char *num;
00761    char tmp[AST_MAX_EXTENSION] = "";
00762 
00763    while (cdr) {
00764       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00765          num = c->cid.cid_ani ? c->cid.cid_ani : c->cid.cid_num;
00766          
00767          if (c->cid.cid_name && num)
00768             snprintf(tmp, sizeof(tmp), "\"%s\" <%s>", c->cid.cid_name, num);
00769          else if (c->cid.cid_name)
00770             ast_copy_string(tmp, c->cid.cid_name, sizeof(tmp));
00771          else if (num)
00772             ast_copy_string(tmp, num, sizeof(tmp));
00773          ast_copy_string(cdr->clid, tmp, sizeof(cdr->clid));
00774          ast_copy_string(cdr->src, num ? num : "", sizeof(cdr->src));
00775 
00776          /* Copy account code et-al */ 
00777          ast_copy_string(cdr->accountcode, c->accountcode, sizeof(cdr->accountcode));
00778          /* Destination information */
00779          ast_copy_string(cdr->dst, (ast_strlen_zero(c->macroexten)) ? c->exten : c->macroexten, sizeof(cdr->dst));
00780          ast_copy_string(cdr->dcontext, (ast_strlen_zero(c->macrocontext)) ? c->context : c->macrocontext, sizeof(cdr->dcontext));
00781       }
00782       cdr = cdr->next;
00783    }
00784 
00785    return 0;
00786 }

static AST_LIST_HEAD_STATIC ( be_list  ,
ast_cdr_beitem   
) [static]

AST_MUTEX_DEFINE_STATIC ( cdr_pending_lock   ) 

AST_MUTEX_DEFINE_STATIC ( cdr_batch_lock   ) 

static void* do_batch_backend_process ( void *  data  )  [static]

Definition at line 910 of file cdr.c.

References ast_cdr_free(), ast_cdr_batch_item::cdr, free, ast_cdr_batch_item::next, and post_cdr().

Referenced by ast_cdr_submit_batch().

00911 {
00912    struct ast_cdr_batch_item *processeditem;
00913    struct ast_cdr_batch_item *batchitem = data;
00914 
00915    /* Push each CDR into storage mechanism(s) and free all the memory */
00916    while (batchitem) {
00917       post_cdr(batchitem->cdr);
00918       ast_cdr_free(batchitem->cdr);
00919       processeditem = batchitem;
00920       batchitem = batchitem->next;
00921       free(processeditem);
00922    }
00923 
00924    return NULL;
00925 }

static void* do_cdr ( void *  data  )  [static]

Definition at line 1040 of file cdr.c.

References ast_cond_timedwait(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_runq(), ast_sched_wait(), ast_tvadd(), cdr_pending_cond, LOG_DEBUG, and option_debug.

Referenced by do_reload().

01041 {
01042    struct timespec timeout;
01043    int schedms;
01044    int numevents = 0;
01045 
01046    for(;;) {
01047       struct timeval now;
01048       schedms = ast_sched_wait(sched);
01049       /* this shouldn't happen, but provide a 1 second default just in case */
01050       if (schedms <= 0)
01051          schedms = 1000;
01052       now = ast_tvadd(ast_tvnow(), ast_samp2tv(schedms, 1000));
01053       timeout.tv_sec = now.tv_sec;
01054       timeout.tv_nsec = now.tv_usec * 1000;
01055       /* prevent stuff from clobbering cdr_pending_cond, then wait on signals sent to it until the timeout expires */
01056       ast_mutex_lock(&cdr_pending_lock);
01057       ast_cond_timedwait(&cdr_pending_cond, &cdr_pending_lock, &timeout);
01058       numevents = ast_sched_runq(sched);
01059       ast_mutex_unlock(&cdr_pending_lock);
01060       if (option_debug > 1)
01061          ast_log(LOG_DEBUG, "Processed %d scheduled CDR batches from the run queue\n", numevents);
01062    }
01063 
01064    return NULL;
01065 }

static int do_reload ( void   )  [static]

Definition at line 1130 of file cdr.c.

References ast_cdr_engine_term(), ast_cli_register(), ast_cli_unregister(), ast_cond_destroy(), ast_cond_init(), ast_config_destroy(), ast_config_load(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create, AST_PTHREADT_NULL, ast_register_atexit(), ast_sched_add(), ast_sched_del(), ast_true(), ast_unregister_atexit(), ast_variable_retrieve(), BATCH_SAFE_SHUTDOWN_DEFAULT, BATCH_SCHEDULER_ONLY_DEFAULT, BATCH_SIZE_DEFAULT, BATCH_TIME_DEFAULT, batchmode, batchsafeshutdown, batchscheduleronly, batchsize, batchtime, cdr_pending_cond, cdr_sched, cdr_thread, cli_submit, config, do_cdr(), enabled, LOG_ERROR, LOG_NOTICE, LOG_WARNING, and submit_scheduled_batch().

Referenced by ast_cdr_engine_init(), ast_cdr_engine_reload(), dnsmgr_init(), dnsmgr_reload(), and handle_cli_reload().

01131 {
01132    struct ast_config *config;
01133    const char *enabled_value;
01134    const char *batched_value;
01135    const char *scheduleronly_value;
01136    const char *batchsafeshutdown_value;
01137    const char *size_value;
01138    const char *time_value;
01139    int cfg_size;
01140    int cfg_time;
01141    int was_enabled;
01142    int was_batchmode;
01143    int res=0;
01144 
01145    ast_mutex_lock(&cdr_batch_lock);
01146 
01147    batchsize = BATCH_SIZE_DEFAULT;
01148    batchtime = BATCH_TIME_DEFAULT;
01149    batchscheduleronly = BATCH_SCHEDULER_ONLY_DEFAULT;
01150    batchsafeshutdown = BATCH_SAFE_SHUTDOWN_DEFAULT;
01151    was_enabled = enabled;
01152    was_batchmode = batchmode;
01153    enabled = 1;
01154    batchmode = 0;
01155 
01156    /* don't run the next scheduled CDR posting while reloading */
01157    if (cdr_sched > -1)
01158       ast_sched_del(sched, cdr_sched);
01159 
01160    if ((config = ast_config_load("cdr.conf"))) {
01161       if ((enabled_value = ast_variable_retrieve(config, "general", "enable"))) {
01162          enabled = ast_true(enabled_value);
01163       }
01164       if ((batched_value = ast_variable_retrieve(config, "general", "batch"))) {
01165          batchmode = ast_true(batched_value);
01166       }
01167       if ((scheduleronly_value = ast_variable_retrieve(config, "general", "scheduleronly"))) {
01168          batchscheduleronly = ast_true(scheduleronly_value);
01169       }
01170       if ((batchsafeshutdown_value = ast_variable_retrieve(config, "general", "safeshutdown"))) {
01171          batchsafeshutdown = ast_true(batchsafeshutdown_value);
01172       }
01173       if ((size_value = ast_variable_retrieve(config, "general", "size"))) {
01174          if (sscanf(size_value, "%d", &cfg_size) < 1)
01175             ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", size_value);
01176          else if (size_value < 0)
01177             ast_log(LOG_WARNING, "Invalid maximum batch size '%d' specified, using default\n", cfg_size);
01178          else
01179             batchsize = cfg_size;
01180       }
01181       if ((time_value = ast_variable_retrieve(config, "general", "time"))) {
01182          if (sscanf(time_value, "%d", &cfg_time) < 1)
01183             ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", time_value);
01184          else if (time_value < 0)
01185             ast_log(LOG_WARNING, "Invalid maximum batch time '%d' specified, using default\n", cfg_time);
01186          else
01187             batchtime = cfg_time;
01188       }
01189    }
01190 
01191    if (enabled && !batchmode) {
01192       ast_log(LOG_NOTICE, "CDR simple logging enabled.\n");
01193    } else if (enabled && batchmode) {
01194       cdr_sched = ast_sched_add(sched, batchtime * 1000, submit_scheduled_batch, NULL);
01195       ast_log(LOG_NOTICE, "CDR batch mode logging enabled, first of either size %d or time %d seconds.\n", batchsize, batchtime);
01196    } else {
01197       ast_log(LOG_NOTICE, "CDR logging disabled, data will be lost.\n");
01198    }
01199 
01200    /* if this reload enabled the CDR batch mode, create the background thread
01201       if it does not exist */
01202    if (enabled && batchmode && (!was_enabled || !was_batchmode) && (cdr_thread == AST_PTHREADT_NULL)) {
01203       ast_cond_init(&cdr_pending_cond, NULL);
01204       if (ast_pthread_create(&cdr_thread, NULL, do_cdr, NULL) < 0) {
01205          ast_log(LOG_ERROR, "Unable to start CDR thread.\n");
01206          ast_sched_del(sched, cdr_sched);
01207       } else {
01208          ast_cli_register(&cli_submit);
01209          ast_register_atexit(ast_cdr_engine_term);
01210          res = 0;
01211       }
01212    /* if this reload disabled the CDR and/or batch mode and there is a background thread,
01213       kill it */
01214    } else if (((!enabled && was_enabled) || (!batchmode && was_batchmode)) && (cdr_thread != AST_PTHREADT_NULL)) {
01215       /* wake up the thread so it will exit */
01216       pthread_cancel(cdr_thread);
01217       pthread_kill(cdr_thread, SIGURG);
01218       pthread_join(cdr_thread, NULL);
01219       cdr_thread = AST_PTHREADT_NULL;
01220       ast_cond_destroy(&cdr_pending_cond);
01221       ast_cli_unregister(&cli_submit);
01222       ast_unregister_atexit(ast_cdr_engine_term);
01223       res = 0;
01224       /* if leaving batch mode, then post the CDRs in the batch,
01225          and don't reschedule, since we are stopping CDR logging */
01226       if (!batchmode && was_batchmode) {
01227          ast_cdr_engine_term();
01228       }
01229    } else {
01230       res = 0;
01231    }
01232 
01233    ast_mutex_unlock(&cdr_batch_lock);
01234    ast_config_destroy(config);
01235 
01236    return res;
01237 }

static int handle_cli_status ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 1067 of file cdr.c.

References ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_sched_when(), batch, batchmode, batchsafeshutdown, batchscheduleronly, batchsize, batchtime, cdr_sched, enabled, list, ast_cdr_beitem::name, and RESULT_SHOWUSAGE.

01068 {
01069    struct ast_cdr_beitem *beitem=NULL;
01070    int cnt=0;
01071    long nextbatchtime=0;
01072 
01073    if (argc > 2)
01074       return RESULT_SHOWUSAGE;
01075 
01076    ast_cli(fd, "CDR logging: %s\n", enabled ? "enabled" : "disabled");
01077    ast_cli(fd, "CDR mode: %s\n", batchmode ? "batch" : "simple");
01078    if (enabled) {
01079       if (batchmode) {
01080          if (batch)
01081             cnt = batch->size;
01082          if (cdr_sched > -1)
01083             nextbatchtime = ast_sched_when(sched, cdr_sched);
01084          ast_cli(fd, "CDR safe shut down: %s\n", batchsafeshutdown ? "enabled" : "disabled");
01085          ast_cli(fd, "CDR batch threading model: %s\n", batchscheduleronly ? "scheduler only" : "scheduler plus separate threads");
01086          ast_cli(fd, "CDR current batch size: %d record%s\n", cnt, (cnt != 1) ? "s" : "");
01087          ast_cli(fd, "CDR maximum batch size: %d record%s\n", batchsize, (batchsize != 1) ? "s" : "");
01088          ast_cli(fd, "CDR maximum batch time: %d second%s\n", batchtime, (batchtime != 1) ? "s" : "");
01089          ast_cli(fd, "CDR next scheduled batch processing time: %ld second%s\n", nextbatchtime, (nextbatchtime != 1) ? "s" : "");
01090       }
01091       AST_LIST_LOCK(&be_list);
01092       AST_LIST_TRAVERSE(&be_list, beitem, list) {
01093          ast_cli(fd, "CDR registered backend: %s\n", beitem->name);
01094       }
01095       AST_LIST_UNLOCK(&be_list);
01096    }
01097 
01098    return 0;
01099 }

static int handle_cli_submit ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 1101 of file cdr.c.

References ast_cli(), RESULT_SHOWUSAGE, and submit_unscheduled_batch().

01102 {
01103    if (argc > 2)
01104       return RESULT_SHOWUSAGE;
01105 
01106    submit_unscheduled_batch();
01107    ast_cli(fd, "Submitted CDRs to backend engines for processing.  This may take a while.\n");
01108 
01109    return 0;
01110 }

static int init_batch ( void   )  [static]

Note:
Don't call without cdr_batch_lock

Definition at line 896 of file cdr.c.

References ast_log(), batch, LOG_WARNING, malloc, and reset_batch().

Referenced by ast_cdr_detach(), and ast_cdr_engine_init().

00897 {
00898    /* This is the single meta-batch used to keep track of all CDRs during the entire life of the program */
00899    batch = malloc(sizeof(*batch));
00900    if (!batch) {
00901       ast_log(LOG_WARNING, "CDR: out of memory while trying to handle batched records, data will most likely be lost\n");
00902       return -1;
00903    }
00904 
00905    reset_batch();
00906 
00907    return 0;
00908 }

static void post_cdr ( struct ast_cdr cdr  )  [static]

Definition at line 801 of file cdr.c.

References ast_cdr::answer, AST_CDR_FAILED, AST_CDR_FLAG_POSTED, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_set_flag, ast_strlen_zero(), ast_test_flag, ast_cdr_beitem::be, ast_cdr::billsec, ast_cdr::channel, ast_cdr::disposition, ast_cdr::duration, ast_cdr::end, list, LOG_WARNING, ast_cdr::next, and ast_cdr::start.

Referenced by ast_cdr_detach(), and do_batch_backend_process().

00802 {
00803    char *chan;
00804    struct ast_cdr_beitem *i;
00805 
00806    while (cdr) {
00807       chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
00808       if (ast_test_flag(cdr, AST_CDR_FLAG_POSTED))
00809          ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
00810       if (ast_tvzero(cdr->end))
00811          ast_log(LOG_WARNING, "CDR on channel '%s' lacks end\n", chan);
00812       if (ast_tvzero(cdr->start)) {
00813          ast_log(LOG_WARNING, "CDR on channel '%s' lacks start\n", chan);
00814          cdr->disposition = AST_CDR_FAILED;
00815       } else
00816          cdr->duration = cdr->end.tv_sec - cdr->start.tv_sec;
00817       if (!ast_tvzero(cdr->answer))
00818          cdr->billsec = cdr->end.tv_sec - cdr->answer.tv_sec;
00819       else
00820          cdr->billsec = 0;
00821       ast_set_flag(cdr, AST_CDR_FLAG_POSTED);
00822       AST_LIST_LOCK(&be_list);
00823       AST_LIST_TRAVERSE(&be_list, i, list) {
00824          i->be(cdr);
00825       }
00826       AST_LIST_UNLOCK(&be_list);
00827       cdr = cdr->next;
00828    }
00829 }

static void reset_batch ( void   )  [static]

Note:
Don't call without cdr_batch_lock

Definition at line 888 of file cdr.c.

References batch, ast_cdr_batch::head, ast_cdr_batch::size, and ast_cdr_batch::tail.

Referenced by ast_cdr_submit_batch(), and init_batch().

00889 {
00890    batch->size = 0;
00891    batch->head = NULL;
00892    batch->tail = NULL;
00893 }

static int submit_scheduled_batch ( void *  data  )  [static]

Definition at line 962 of file cdr.c.

References ast_cdr_submit_batch(), ast_sched_add(), batchtime, and cdr_sched.

Referenced by do_reload(), and submit_unscheduled_batch().

00963 {
00964    ast_cdr_submit_batch(0);
00965    /* manually reschedule from this point in time */
00966    cdr_sched = ast_sched_add(sched, batchtime * 1000, submit_scheduled_batch, NULL);
00967    /* returning zero so the scheduler does not automatically reschedule */
00968    return 0;
00969 }

static void submit_unscheduled_batch ( void   )  [static]

Definition at line 971 of file cdr.c.

References ast_cond_signal(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_add(), ast_sched_del(), cdr_pending_cond, cdr_sched, and submit_scheduled_batch().

Referenced by ast_cdr_detach(), and handle_cli_submit().

00972 {
00973    /* this is okay since we are not being called from within the scheduler */
00974    if (cdr_sched > -1)
00975       ast_sched_del(sched, cdr_sched);
00976    /* schedule the submission to occur ASAP (1 ms) */
00977    cdr_sched = ast_sched_add(sched, 1, submit_scheduled_batch, NULL);
00978    /* signal the do_cdr thread to wakeup early and do some work (that lazy thread ;) */
00979    ast_mutex_lock(&cdr_pending_lock);
00980    ast_cond_signal(&cdr_pending_cond);
00981    ast_mutex_unlock(&cdr_pending_lock);
00982 }


Variable Documentation

char ast_default_accountcode[AST_MAX_ACCOUNT_CODE] = ""

Definition at line 58 of file cdr.c.

int ast_default_amaflags = AST_CDR_DOCUMENTATION

Default AMA flag for billing records (CDR's)

Definition at line 57 of file cdr.c.

struct ast_cdr_batch * batch [static]

Referenced by ast_cdr_detach(), ast_cdr_submit_batch(), handle_cli_status(), init_batch(), and reset_batch().

int batchmode [static]

Definition at line 90 of file cdr.c.

Referenced by ast_cdr_detach(), do_reload(), and handle_cli_status().

int batchsafeshutdown [static]

Definition at line 94 of file cdr.c.

Referenced by ast_cdr_engine_term(), do_reload(), and handle_cli_status().

int batchscheduleronly [static]

Definition at line 93 of file cdr.c.

Referenced by ast_cdr_submit_batch(), do_reload(), and handle_cli_status().

int batchsize [static]

Definition at line 91 of file cdr.c.

Referenced by ast_cdr_detach(), do_reload(), and handle_cli_status().

int batchtime [static]

Definition at line 92 of file cdr.c.

Referenced by do_reload(), handle_cli_status(), and submit_scheduled_batch().

ast_cond_t cdr_pending_cond [static]

Definition at line 100 of file cdr.c.

Referenced by do_cdr(), do_reload(), and submit_unscheduled_batch().

int cdr_sched = -1 [static]

Definition at line 81 of file cdr.c.

Referenced by do_reload(), handle_cli_status(), submit_scheduled_batch(), and submit_unscheduled_batch().

pthread_t cdr_thread = AST_PTHREADT_NULL [static]

Definition at line 82 of file cdr.c.

Referenced by do_reload().

struct ast_cli_entry cli_status [static]

Definition at line 1121 of file cdr.c.

Referenced by ast_cdr_engine_init(), and dnsmgr_init().

struct ast_cli_entry cli_submit [static]

Definition at line 1112 of file cdr.c.

Referenced by do_reload().

int enabled [static]

Definition at line 89 of file cdr.c.

Referenced by ast_cdr_detach(), ast_dnsmgr_lookup(), do_reload(), handle_cli_status(), init_manager(), and load_odbc_config().

struct sched_context* sched [static]

Definition at line 80 of file cdr.c.

Referenced by __sip_ack(), __sip_destroy(), __sip_reliable_xmit(), __sip_semi_ack(), __unload_module(), ast_rtp_new(), ast_rtp_new_with_bindaddr(), attempt_transmit(), auth_fail(), build_peer(), delete_users(), destroy_peer(), dnsmgr_init(), dnsmgr_start_refresh(), do_monitor(), do_refresh(), do_reload(), find_callno(), iax2_ack_registry(), iax2_call(), iax2_destroy(), iax2_do_register(), iax2_dprequest(), iax2_frame_free(), iax2_poke_noanswer(), iax2_poke_peer(), iax2_predestroy(), iax2_provision(), load_module(), make_trunk(), oh323_alloc(), realtime_peer(), reg_source_db(), sip_alloc(), sip_call(), sip_cancel_destroy(), sip_destroy_peer(), sip_registry_destroy(), sip_scheddestroy(), socket_read(), start_rtp(), stop_stuff(), unload_module(), update_jbsched(), and update_registry().


Generated on Mon Sep 18 09:14:02 2006 for Asterisk - the Open Source PBX by  doxygen 1.4.7