Wed Oct 28 13:31:52 2009

Asterisk developer's documentation


cdr.c File Reference

Call Detail Record API. More...

#include "asterisk.h"
#include <signal.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/cdr.h"
#include "asterisk/callerid.h"
#include "asterisk/manager.h"
#include "asterisk/causes.h"
#include "asterisk/linkedlists.h"
#include "asterisk/utils.h"
#include "asterisk/sched.h"
#include "asterisk/config.h"
#include "asterisk/cli.h"
#include "asterisk/stringfields.h"

Include dependency graph for cdr.c:

Go to the source code of this file.

Data Structures

struct  ast_cdr_batch
struct  ast_cdr_batch_item
struct  ast_cdr_beitem
struct  be_list

Defines

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

Functions

static void __fini_be_list (void)
static void __init_be_list (void)
struct ast_cdrast_cdr_alloc (void)
 Allocate a CDR record.
int ast_cdr_amaflags2int (const char *flag)
 Convert a string to a detail record AMA flag.
void ast_cdr_answer (struct ast_cdr *cdr)
 Answer a call.
struct ast_cdrast_cdr_append (struct ast_cdr *cdr, struct ast_cdr *newcdr)
int ast_cdr_appenduserfield (struct ast_channel *chan, const char *userfield)
 Append to CDR user field for channel (stored in CDR).
void ast_cdr_busy (struct ast_cdr *cdr)
 Busy a call.
int ast_cdr_copy_vars (struct ast_cdr *to_cdr, struct ast_cdr *from_cdr)
void ast_cdr_detach (struct ast_cdr *cdr)
 Detaches the detail record for posting (and freeing) either now or at a later time in bulk with other records during batch mode operation.
void ast_cdr_discard (struct ast_cdr *cdr)
 the same as a cdr_free call, only with no checks; just get rid of it
char * ast_cdr_disp2str (int disposition)
 Disposition to a string.
int ast_cdr_disposition (struct ast_cdr *cdr, int cause)
 Save the result of the call based on the AST_CAUSE_*.
struct ast_cdrast_cdr_dup (struct ast_cdr *cdr)
 Duplicate a record.
void ast_cdr_end (struct ast_cdr *cdr)
 End a call.
int ast_cdr_engine_init (void)
 Load the configuration file cdr.conf and possibly start the CDR scheduling thread.
int ast_cdr_engine_reload (void)
 Reload the configuration file cdr.conf and start/stop CDR scheduling thread.
void ast_cdr_engine_term (void)
void ast_cdr_failed (struct ast_cdr *cdr)
 Fail a call.
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, int raw)
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_isset_unanswered (void)
void ast_cdr_merge (struct ast_cdr *to, struct ast_cdr *from)
 Move the non-null data from the "from" cdr to the "to" cdr.
void ast_cdr_noanswer (struct ast_cdr *cdr)
 A call wasn't answered.
int ast_cdr_register (const char *name, const char *desc, ast_cdrbe be)
 Register a CDR handling engine.
void ast_cdr_reset (struct ast_cdr *cdr, struct ast_flags *_flags)
 Reset the detail record, optionally posting it first.
int ast_cdr_serialize_variables (struct ast_cdr *cdr, struct ast_str **buf, char delim, char sep, int recur)
int ast_cdr_setaccount (struct ast_channel *chan, const char *account)
 Set account code, will generate AMI event.
int ast_cdr_setamaflags (struct ast_channel *chan, const char *flag)
 Set AMA flags for channel.
void ast_cdr_setanswer (struct ast_cdr *cdr, struct timeval t)
 Set the answer time for a call.
void ast_cdr_setapp (struct ast_cdr *cdr, const char *app, const char *data)
 Set the last executed application.
int ast_cdr_setcid (struct ast_cdr *cdr, struct ast_channel *c)
 Initialize based on a channel.
void ast_cdr_setdestchan (struct ast_cdr *cdr, const char *chann)
 Set the destination channel, if there was one.
void ast_cdr_setdisposition (struct ast_cdr *cdr, long int disposition)
 Set the disposition for a call.
int ast_cdr_setpeeraccount (struct ast_channel *chan, const char *account)
 Set the peer account.
int ast_cdr_setuserfield (struct ast_channel *chan, const char *userfield)
 Set CDR user field for channel (stored in CDR).
int ast_cdr_setvar (struct ast_cdr *cdr, const char *name, const char *value, int recur)
void ast_cdr_specialized_reset (struct ast_cdr *cdr, struct ast_flags *_flags)
void ast_cdr_start (struct ast_cdr *cdr)
 Start a call.
void ast_cdr_submit_batch (int do_shutdown)
 Spawns (possibly) a new thread to submit a batch of CDRs to the backend engines.
void ast_cdr_unregister (const char *name)
 Unregister a CDR handling engine.
int ast_cdr_update (struct ast_channel *c)
static void cdr_get_tv (struct timeval when, const char *fmt, char *buf, int bufsize)
static void cdr_merge_vars (struct ast_cdr *to, struct ast_cdr *from)
int check_cdr_enabled ()
 Return TRUE if CDR subsystem is enabled.
static void check_post (struct ast_cdr *cdr)
 print a warning if cdr already posted
static void * do_batch_backend_process (void *data)
static void * do_cdr (void *data)
static int do_reload (int reload)
static char * handle_cli_status (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_submit (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int init_batch (void)
static void post_cdr (struct ast_cdr *cdr)
static void reset_batch (void)
static void set_one_cid (struct ast_cdr *cdr, struct ast_channel *c)
static int submit_scheduled_batch (const 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_mutex_t cdr_batch_lock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
static ast_cond_t cdr_pending_cond
static ast_mutex_t cdr_pending_lock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
static const char *const cdr_readonly_vars []
static int cdr_sched = -1
static pthread_t cdr_thread = AST_PTHREADT_NULL
static struct ast_cli_entry cli_status = AST_CLI_DEFINE(handle_cli_status, "Display the CDR status")
static struct ast_cli_entry cli_submit = AST_CLI_DEFINE(handle_cli_submit, "Posts all pending batched CDR data")
static int enabled
static struct sched_contextsched
static int unanswered


Detailed Description

Call Detail Record API.

Author:
Mark Spencer <markster@digium.com>
Note:
Includes code and algorithms from the Zapata library.

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 84 of file cdr.c.

Referenced by do_reload().

#define BATCH_SCHEDULER_ONLY_DEFAULT   0

Definition at line 83 of file cdr.c.

Referenced by do_reload().

#define BATCH_SIZE_DEFAULT   100

Definition at line 81 of file cdr.c.

Referenced by do_reload().

#define BATCH_TIME_DEFAULT   300

Definition at line 82 of file cdr.c.

Referenced by do_reload().


Function Documentation

static void __fini_be_list ( void   )  [static]

Definition at line 64 of file cdr.c.

00066 {

static void __init_be_list ( void   )  [static]

Definition at line 64 of file cdr.c.

00066 {

struct ast_cdr* ast_cdr_alloc ( void   )  [read]

Allocate a CDR record.

Return values:
a malloc'd ast_cdr structure
NULL on error (malloc failure)

Definition at line 456 of file cdr.c.

References ast_calloc, ast_log(), and LOG_ERROR.

Referenced by __agent_start_monitoring(), __ast_channel_alloc_ap(), __ast_request_and_dial(), ast_bridge_call(), ast_cdr_dup(), ast_pbx_outgoing_cdr_failed(), builtin_blindtransfer(), clear_caller(), findmeexec(), and start_monitor_exec().

00457 {
00458    struct ast_cdr *x;
00459    x = ast_calloc(1, sizeof(*x));
00460    if (!x)
00461       ast_log(LOG_ERROR,"Allocation Failure for a CDR!\n");
00462    return x;
00463 }

int ast_cdr_amaflags2int ( const char *  flag  ) 

Convert a string to a detail record AMA 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 1060 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(), config_parse_variables(), process_dahdi(), and set_config().

01061 {
01062    if (!strcasecmp(flag, "default"))
01063       return 0;
01064    if (!strcasecmp(flag, "omit"))
01065       return AST_CDR_OMIT;
01066    if (!strcasecmp(flag, "billing"))
01067       return AST_CDR_BILLING;
01068    if (!strcasecmp(flag, "documentation"))
01069       return AST_CDR_DOCUMENTATION;
01070    return -1;
01071 }

void ast_cdr_answer ( struct ast_cdr cdr  ) 

Answer a call.

Parameters:
cdr the cdr you wish to associate with the call Starts all CDR stuff necessary for doing CDR when answering a call
Note:
NULL argument is just fine.

Definition at line 694 of file cdr.c.

References ast_cdr::answer, AST_CDR_ANSWERED, AST_CDR_FLAG_ANSLOCKED, AST_CDR_FLAG_DONT_TOUCH, AST_CDR_FLAG_LOCKED, ast_test_flag, ast_tvnow(), ast_tvzero(), check_post(), ast_cdr::disposition, and ast_cdr::next.

Referenced by ast_bridge_call(), and ast_raw_answer().

00695 {
00696 
00697    for (; cdr; cdr = cdr->next) {
00698       if (ast_test_flag(cdr, AST_CDR_FLAG_ANSLOCKED)) 
00699          continue;
00700       if (ast_test_flag(cdr, AST_CDR_FLAG_DONT_TOUCH) && ast_test_flag(cdr, AST_CDR_FLAG_LOCKED))
00701          continue;
00702       check_post(cdr);
00703       if (cdr->disposition < AST_CDR_ANSWERED)
00704          cdr->disposition = AST_CDR_ANSWERED;
00705       if (ast_tvzero(cdr->answer))
00706          cdr->answer = ast_tvnow();
00707    }
00708 }

struct ast_cdr* ast_cdr_append ( struct ast_cdr cdr,
struct ast_cdr newcdr 
) [read]

Definition at line 1173 of file cdr.c.

References ast_cdr::next.

Referenced by ast_cdr_fork(), ast_cdr_merge(), and attempt_transfer().

01174 {
01175    struct ast_cdr *ret;
01176 
01177    if (cdr) {
01178       ret = cdr;
01179 
01180       while (cdr->next)
01181          cdr = cdr->next;
01182       cdr->next = newcdr;
01183    } else {
01184       ret = newcdr;
01185    }
01186 
01187    return ret;
01188 }

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

Append to CDR user field for channel (stored in CDR).

Definition at line 1024 of file cdr.c.

References AST_CDR_FLAG_LOCKED, ast_copy_string(), ast_test_flag, ast_channel::cdr, len(), ast_cdr::next, and ast_cdr::userfield.

Referenced by ast_bridge_call().

01025 {
01026    struct ast_cdr *cdr = chan->cdr;
01027 
01028    for ( ; cdr ; cdr = cdr->next) {
01029       int len = strlen(cdr->userfield);
01030 
01031       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED))
01032          ast_copy_string(cdr->userfield + len, userfield, sizeof(cdr->userfield) - len);
01033    }
01034 
01035    return 0;
01036 }

void ast_cdr_busy ( struct ast_cdr cdr  ) 

Busy a call.

Parameters:
cdr the cdr you wish to associate with the call Marks the channel disposition as "BUSY" Will skip CDR's in chain with ANS_LOCK bit set. (see forkCDR() application. Returns nothing

Definition at line 710 of file cdr.c.

References AST_CDR_BUSY, AST_CDR_FLAG_LOCKED, ast_test_flag, check_post(), ast_cdr::disposition, and ast_cdr::next.

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

00711 {
00712 
00713    for (; cdr; cdr = cdr->next) {
00714       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00715          check_post(cdr);
00716          if (cdr->disposition < AST_CDR_BUSY)
00717             cdr->disposition = AST_CDR_BUSY;
00718       }
00719    }
00720 }

int ast_cdr_copy_vars ( struct ast_cdr to_cdr,
struct ast_cdr from_cdr 
)

Definition at line 340 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().

00341 {
00342    struct ast_var_t *variables, *newvariable = NULL;
00343    struct varshead *headpa, *headpb;
00344    const char *var, *val;
00345    int x = 0;
00346 
00347    if (!to_cdr || !from_cdr) /* don't die if one of the pointers is null */
00348       return 0;
00349 
00350    headpa = &from_cdr->varshead;
00351    headpb = &to_cdr->varshead;
00352 
00353    AST_LIST_TRAVERSE(headpa,variables,entries) {
00354       if (variables &&
00355           (var = ast_var_name(variables)) && (val = ast_var_value(variables)) &&
00356           !ast_strlen_zero(var) && !ast_strlen_zero(val)) {
00357          newvariable = ast_var_assign(var, val);
00358          AST_LIST_INSERT_HEAD(headpb, newvariable, entries);
00359          x++;
00360       }
00361    }
00362 
00363    return x;
00364 }

void ast_cdr_detach ( struct ast_cdr cdr  ) 

Detaches the detail record for posting (and freeing) either now or at a later time in bulk with other records during batch mode operation.

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 1278 of file cdr.c.

References ast_calloc, AST_CDR_FLAG_POST_DISABLED, ast_cdr_free(), ast_debug, ast_mutex_lock(), ast_mutex_unlock(), ast_set_flag, batch, batchmode, batchsize, ast_cdr_batch_item::cdr, cdr_batch_lock, enabled, ast_cdr_batch::head, init_batch(), ast_cdr_batch_item::next, post_cdr(), ast_cdr_batch::size, submit_unscheduled_batch(), and ast_cdr_batch::tail.

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

01279 {
01280    struct ast_cdr_batch_item *newtail;
01281    int curr;
01282 
01283    if (!cdr)
01284       return;
01285 
01286    /* maybe they disabled CDR stuff completely, so just drop it */
01287    if (!enabled) {
01288       ast_debug(1, "Dropping CDR !\n");
01289       ast_set_flag(cdr, AST_CDR_FLAG_POST_DISABLED);
01290       ast_cdr_free(cdr);
01291       return;
01292    }
01293 
01294    /* post stuff immediately if we are not in batch mode, this is legacy behaviour */
01295    if (!batchmode) {
01296       post_cdr(cdr);
01297       ast_cdr_free(cdr);
01298       return;
01299    }
01300 
01301    /* otherwise, each CDR gets put into a batch list (at the end) */
01302    ast_debug(1, "CDR detaching from this thread\n");
01303 
01304    /* we'll need a new tail for every CDR */
01305    if (!(newtail = ast_calloc(1, sizeof(*newtail)))) {
01306       post_cdr(cdr);
01307       ast_cdr_free(cdr);
01308       return;
01309    }
01310 
01311    /* don't traverse a whole list (just keep track of the tail) */
01312    ast_mutex_lock(&cdr_batch_lock);
01313    if (!batch)
01314       init_batch();
01315    if (!batch->head) {
01316       /* new batch is empty, so point the head at the new tail */
01317       batch->head = newtail;
01318    } else {
01319       /* already got a batch with something in it, so just append a new tail */
01320       batch->tail->next = newtail;
01321    }
01322    newtail->cdr = cdr;
01323    batch->tail = newtail;
01324    curr = batch->size++;
01325    ast_mutex_unlock(&cdr_batch_lock);
01326 
01327    /* if we have enough stuff to post, then do it */
01328    if (curr >= (batchsize - 1))
01329       submit_unscheduled_batch();
01330 }

void ast_cdr_discard ( struct ast_cdr cdr  ) 

the same as a cdr_free call, only with no checks; just get rid of it

Discard and free a CDR record.

Definition at line 445 of file cdr.c.

References ast_cdr_free_vars(), ast_free, ast_cdr::next, and ast_cdr_beitem::next.

Referenced by ast_async_goto(), ast_bridge_call(), ast_cdr_merge(), ast_channel_destructor(), and ast_dummy_channel_destructor().

00446 {
00447    while (cdr) {
00448       struct ast_cdr *next = cdr->next;
00449 
00450       ast_cdr_free_vars(cdr, 0);
00451       ast_free(cdr);
00452       cdr = next;
00453    }
00454 }

char* ast_cdr_disp2str ( int  disposition  ) 

Disposition to a string.

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 914 of file cdr.c.

References AST_CDR_ANSWERED, AST_CDR_BUSY, AST_CDR_FAILED, AST_CDR_NOANSWER, and AST_CDR_NULL.

Referenced by ast_cdr_getvar(), build_csv_record(), build_radius_record(), csv_log(), execute_cb(), manager_log(), and tds_log().

00915 {
00916    switch (disposition) {
00917    case AST_CDR_NULL:
00918       return "NO ANSWER"; /* by default, for backward compatibility */
00919    case AST_CDR_NOANSWER:
00920       return "NO ANSWER";
00921    case AST_CDR_FAILED:
00922       return "FAILED";     
00923    case AST_CDR_BUSY:
00924       return "BUSY";    
00925    case AST_CDR_ANSWERED:
00926       return "ANSWERED";
00927    }
00928    return "UNKNOWN";
00929 }

int ast_cdr_disposition ( struct ast_cdr cdr,
int  cause 
)

Save the result of the call based on the AST_CAUSE_*.

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

Definition at line 753 of file cdr.c.

References AST_CAUSE_BUSY, AST_CAUSE_NO_ANSWER, AST_CAUSE_NORMAL, ast_cdr_busy(), ast_cdr_noanswer(), and ast_cdr::next.

Referenced by __ast_request_and_dial(), ast_pbx_outgoing_app(), ast_pbx_outgoing_exten(), clear_caller(), and findmeexec().

00754 {
00755    int res = 0;
00756 
00757    for (; cdr; cdr = cdr->next) {
00758       switch (cause) {  /* handle all the non failure, busy cases, return 0 not to set disposition,
00759                      return -1 to set disposition to FAILED */
00760       case AST_CAUSE_BUSY:
00761          ast_cdr_busy(cdr);
00762          break;
00763       case AST_CAUSE_NO_ANSWER:
00764          ast_cdr_noanswer(cdr);
00765          break;
00766       case AST_CAUSE_NORMAL:
00767          break;
00768       default:
00769          res = -1;
00770       }
00771    }
00772    return res;
00773 }

struct ast_cdr* ast_cdr_dup ( struct ast_cdr cdr  )  [read]

Duplicate a record.

Duplicate a CDR record

Returns:
Pointer to new CDR record

Definition at line 171 of file cdr.c.

References ast_cdr_alloc(), ast_cdr_copy_vars(), ast_cdr::next, and ast_cdr::varshead.

Referenced by ast_async_goto(), ast_bridge_call(), ast_cdr_fork(), ast_cdr_merge(), ast_cdr_reset(), custom_log(), manager_log(), sqlite3_log(), and syslog_log().

00172 {
00173    struct ast_cdr *newcdr;
00174    
00175    if (!cdr) /* don't die if we get a null cdr pointer */
00176       return NULL;
00177    newcdr = ast_cdr_alloc();
00178    if (!newcdr)
00179       return NULL;
00180 
00181    memcpy(newcdr, cdr, sizeof(*newcdr));
00182    /* The varshead is unusable, volatile even, after the memcpy so we take care of that here */
00183    memset(&newcdr->varshead, 0, sizeof(newcdr->varshead));
00184    ast_cdr_copy_vars(newcdr, cdr);
00185    newcdr->next = NULL;
00186 
00187    return newcdr;
00188 }

void ast_cdr_end ( struct ast_cdr cdr  ) 

End a call.

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

Definition at line 888 of file cdr.c.

References ast_cdr::answer, AST_CDR_ANSWERED, AST_CDR_FAILED, AST_CDR_FLAG_DONT_TOUCH, AST_CDR_FLAG_LOCKED, ast_log(), AST_OPT_FLAG_INITIATED_SECONDS, ast_options, ast_test_flag, ast_tvnow(), ast_tvzero(), ast_cdr::billsec, ast_cdr::channel, check_post(), ast_cdr::disposition, ast_cdr::duration, ast_cdr::end, LOG_WARNING, ast_cdr::next, S_OR, and ast_cdr::start.

Referenced by __ast_pbx_run(), __ast_request_and_dial(), ast_bridge_call(), ast_cdr_fork(), ast_cdr_reset(), ast_hangup(), ast_pbx_outgoing_cdr_failed(), clear_caller(), and findmeexec().

00889 {
00890    for ( ; cdr ; cdr = cdr->next) {
00891       if (ast_test_flag(cdr, AST_CDR_FLAG_DONT_TOUCH) && ast_test_flag(cdr, AST_CDR_FLAG_LOCKED))
00892          continue;
00893       check_post(cdr);
00894       if (ast_tvzero(cdr->end))
00895          cdr->end = ast_tvnow();
00896       if (ast_tvzero(cdr->start)) {
00897          ast_log(LOG_WARNING, "CDR on channel '%s' has not started\n", S_OR(cdr->channel, "<unknown>"));
00898          cdr->disposition = AST_CDR_FAILED;
00899       } else
00900          cdr->duration = cdr->end.tv_sec - cdr->start.tv_sec;
00901       if (ast_tvzero(cdr->answer)) {
00902          if (cdr->disposition == AST_CDR_ANSWERED) {
00903             ast_log(LOG_WARNING, "CDR on channel '%s' has no answer time but is 'ANSWERED'\n", S_OR(cdr->channel, "<unknown>"));
00904             cdr->disposition = AST_CDR_FAILED;
00905          }
00906       } else {
00907          cdr->billsec = cdr->end.tv_sec - cdr->answer.tv_sec;
00908          if (ast_test_flag(&ast_options, AST_OPT_FLAG_INITIATED_SECONDS))
00909             cdr->billsec += cdr->end.tv_usec > cdr->answer.tv_usec ? 1 : 0;
00910       }
00911    }
00912 }

int ast_cdr_engine_init ( void   ) 

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

Definition at line 1566 of file cdr.c.

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

Referenced by main().

01567 {
01568    int res;
01569 
01570    sched = sched_context_create();
01571    if (!sched) {
01572       ast_log(LOG_ERROR, "Unable to create schedule context.\n");
01573       return -1;
01574    }
01575 
01576    ast_cli_register(&cli_status);
01577 
01578    res = do_reload(0);
01579    if (res) {
01580       ast_mutex_lock(&cdr_batch_lock);
01581       res = init_batch();
01582       ast_mutex_unlock(&cdr_batch_lock);
01583    }
01584 
01585    return res;
01586 }

int ast_cdr_engine_reload ( void   ) 

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

Definition at line 1595 of file cdr.c.

References do_reload().

01596 {
01597    return do_reload(1);
01598 }

void ast_cdr_engine_term ( void   ) 

Submit any remaining CDRs and prepare for shutdown

Definition at line 1590 of file cdr.c.

References ast_cdr_submit_batch(), and batchsafeshutdown.

Referenced by do_reload(), and quit_handler().

01591 {
01592    ast_cdr_submit_batch(batchsafeshutdown);
01593 }

void ast_cdr_failed ( struct ast_cdr cdr  ) 

Fail a call.

Parameters:
cdr the cdr you wish to associate with the call Marks the channel disposition as "FAILED" Will skip CDR's in chain with ANS_LOCK bit set. (see forkCDR() application. Returns nothing

Definition at line 722 of file cdr.c.

References AST_CDR_FAILED, AST_CDR_FLAG_LOCKED, ast_test_flag, check_post(), ast_cdr::disposition, and ast_cdr::next.

Referenced by __ast_request_and_dial(), ast_pbx_outgoing_app(), ast_pbx_outgoing_cdr_failed(), ast_pbx_outgoing_exten(), clear_caller(), findmeexec(), handle_cause(), and try_calling().

00723 {
00724    for (; cdr; cdr = cdr->next) {
00725       check_post(cdr);
00726       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00727          check_post(cdr);
00728          if (cdr->disposition < AST_CDR_FAILED)
00729             cdr->disposition = AST_CDR_FAILED;
00730       }
00731    }
00732 }

char* ast_cdr_flags2str ( int  flag  ) 

Converts AMA flag to printable string

Definition at line 932 of file cdr.c.

References AST_CDR_BILLING, AST_CDR_DOCUMENTATION, and AST_CDR_OMIT.

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

00933 {
00934    switch (flag) {
00935    case AST_CDR_OMIT:
00936       return "OMIT";
00937    case AST_CDR_BILLING:
00938       return "BILLING";
00939    case AST_CDR_DOCUMENTATION:
00940       return "DOCUMENTATION";
00941    }
00942    return "Unknown";
00943 }

void ast_cdr_free ( struct ast_cdr cdr  ) 

Free a CDR record.

Parameters:
cdr ast_cdr structure to free Returns nothing

Definition at line 432 of file cdr.c.

References ast_cdr_free_vars(), ast_free, ast_cdr::next, and ast_cdr_beitem::next.

Referenced by ast_cdr_detach(), and do_batch_backend_process().

00433 {
00434 
00435    while (cdr) {
00436       struct ast_cdr *next = cdr->next;
00437 
00438       ast_cdr_free_vars(cdr, 0);
00439       ast_free(cdr);
00440       cdr = next;
00441    }
00442 }

void ast_cdr_free_vars ( struct ast_cdr cdr,
int  recur 
)

Definition at line 411 of file cdr.c.

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

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

00412 {
00413 
00414    /* clear variables */
00415    for (; cdr; cdr = recur ? cdr->next : NULL) {
00416       struct ast_var_t *vardata;
00417       struct varshead *headp = &cdr->varshead;
00418       while ((vardata = AST_LIST_REMOVE_HEAD(headp, entries)))
00419          ast_var_delete(vardata);
00420    }
00421 }

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

CDR channel variable retrieval

Definition at line 222 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_copy_string(), ast_strlen_zero(), ast_tvdiff_ms(), ast_tvnow(), ast_cdr::billsec, cdr_get_tv(), ast_cdr::channel, ast_cdr::clid, ast_cdr::dcontext, ast_cdr::disposition, ast_cdr::dst, ast_cdr::dstchannel, ast_cdr::duration, ast_cdr::end, ast_cdr::lastapp, ast_cdr::lastdata, ast_cdr::linkedid, ast_cdr::peeraccount, ast_cdr::src, ast_cdr::start, ast_cdr::uniqueid, and ast_cdr::userfield.

Referenced by ast_cdr_serialize_variables(), cdr_handler(), cdr_read(), odbc_log(), and pgsql_log().

00223 {
00224    const char *fmt = "%Y-%m-%d %T";
00225    const char *varbuf;
00226 
00227    if (!cdr)  /* don't die if the cdr is null */
00228       return;
00229 
00230    *ret = NULL;
00231    /* special vars (the ones from the struct ast_cdr when requested by name) 
00232       I'd almost say we should convert all the stringed vals to vars */
00233 
00234    if (!strcasecmp(name, "clid"))
00235       ast_copy_string(workspace, cdr->clid, workspacelen);
00236    else if (!strcasecmp(name, "src"))
00237       ast_copy_string(workspace, cdr->src, workspacelen);
00238    else if (!strcasecmp(name, "dst"))
00239       ast_copy_string(workspace, cdr->dst, workspacelen);
00240    else if (!strcasecmp(name, "dcontext"))
00241       ast_copy_string(workspace, cdr->dcontext, workspacelen);
00242    else if (!strcasecmp(name, "channel"))
00243       ast_copy_string(workspace, cdr->channel, workspacelen);
00244    else if (!strcasecmp(name, "dstchannel"))
00245       ast_copy_string(workspace, cdr->dstchannel, workspacelen);
00246    else if (!strcasecmp(name, "lastapp"))
00247       ast_copy_string(workspace, cdr->lastapp, workspacelen);
00248    else if (!strcasecmp(name, "lastdata"))
00249       ast_copy_string(workspace, cdr->lastdata, workspacelen);
00250    else if (!strcasecmp(name, "start"))
00251       cdr_get_tv(cdr->start, raw ? NULL : fmt, workspace, workspacelen);
00252    else if (!strcasecmp(name, "answer"))
00253       cdr_get_tv(cdr->answer, raw ? NULL : fmt, workspace, workspacelen);
00254    else if (!strcasecmp(name, "end"))
00255       cdr_get_tv(cdr->end, raw ? NULL : fmt, workspace, workspacelen);
00256    else if (!strcasecmp(name, "duration"))
00257       snprintf(workspace, workspacelen, "%ld", cdr->duration ? cdr->duration : (long)ast_tvdiff_ms(ast_tvnow(), cdr->start) / 1000);
00258    else if (!strcasecmp(name, "billsec"))
00259       snprintf(workspace, workspacelen, "%ld", cdr->billsec || cdr->answer.tv_sec == 0 ? cdr->billsec : (long)ast_tvdiff_ms(ast_tvnow(), cdr->answer) / 1000);
00260    else if (!strcasecmp(name, "disposition")) {
00261       if (raw) {
00262          snprintf(workspace, workspacelen, "%ld", cdr->disposition);
00263       } else {
00264          ast_copy_string(workspace, ast_cdr_disp2str(cdr->disposition), workspacelen);
00265       }
00266    } else if (!strcasecmp(name, "amaflags")) {
00267       if (raw) {
00268          snprintf(workspace, workspacelen, "%ld", cdr->amaflags);
00269       } else {
00270          ast_copy_string(workspace, ast_cdr_flags2str(cdr->amaflags), workspacelen);
00271       }
00272    } else if (!strcasecmp(name, "accountcode"))
00273       ast_copy_string(workspace, cdr->accountcode, workspacelen);
00274    else if (!strcasecmp(name, "peeraccount"))
00275       ast_copy_string(workspace, cdr->peeraccount, workspacelen);
00276    else if (!strcasecmp(name, "uniqueid"))
00277       ast_copy_string(workspace, cdr->uniqueid, workspacelen);
00278    else if (!strcasecmp(name, "linkedid"))
00279       ast_copy_string(workspace, cdr->linkedid, workspacelen);
00280    else if (!strcasecmp(name, "userfield"))
00281       ast_copy_string(workspace, cdr->userfield, workspacelen);
00282    else if ((varbuf = ast_cdr_getvar_internal(cdr, name, recur)))
00283       ast_copy_string(workspace, varbuf, workspacelen);
00284    else
00285       workspace[0] = '\0';
00286 
00287    if (!ast_strlen_zero(workspace))
00288       *ret = workspace;
00289 }

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

Definition at line 190 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().

00191 {
00192    if (ast_strlen_zero(name))
00193       return NULL;
00194 
00195    for (; cdr; cdr = recur ? cdr->next : NULL) {
00196       struct ast_var_t *variables;
00197       struct varshead *headp = &cdr->varshead;
00198       AST_LIST_TRAVERSE(headp, variables, entries) {
00199          if (!strcasecmp(name, ast_var_name(variables)))
00200             return ast_var_value(variables);
00201       }
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
Returns:
0 by default

Definition at line 850 of file cdr.c.

References ast_channel::_state, ast_channel::accountcode, ast_cdr::accountcode, ast_channel::amaflags, ast_cdr::amaflags, AST_CDR_ANSWERED, AST_CDR_FLAG_LOCKED, AST_CDR_NOANSWER, ast_copy_string(), AST_STATE_UP, ast_test_flag, chan, ast_cdr::channel, ast_channel::context, ast_cdr::dcontext, ast_cdr::disposition, ast_cdr::dst, ast_channel::exten, ast_channel::linkedid, ast_cdr::linkedid, ast_channel::macrocontext, ast_channel::macroexten, ast_channel::name, ast_cdr::next, ast_channel::peeraccount, ast_cdr::peeraccount, S_OR, set_one_cid(), ast_channel::uniqueid, and ast_cdr::uniqueid.

Referenced by __ast_channel_alloc_ap(), __ast_request_and_dial(), ast_pbx_outgoing_cdr_failed(), builtin_blindtransfer(), clear_caller(), and findmeexec().

00851 {
00852    char *chan;
00853 
00854    for ( ; cdr ; cdr = cdr->next) {
00855       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00856          chan = S_OR(cdr->channel, "<unknown>");
00857          ast_copy_string(cdr->channel, c->name, sizeof(cdr->channel));
00858          set_one_cid(cdr, c);
00859 
00860          cdr->disposition = (c->_state == AST_STATE_UP) ?  AST_CDR_ANSWERED : AST_CDR_NOANSWER;
00861          cdr->amaflags = c->amaflags ? c->amaflags :  ast_default_amaflags;
00862          ast_copy_string(cdr->accountcode, c->accountcode, sizeof(cdr->accountcode));
00863          ast_copy_string(cdr->peeraccount, c->peeraccount, sizeof(cdr->peeraccount));
00864          /* Destination information */
00865          ast_copy_string(cdr->dst, S_OR(c->macroexten,c->exten), sizeof(cdr->dst));
00866          ast_copy_string(cdr->dcontext, S_OR(c->macrocontext,c->context), sizeof(cdr->dcontext));
00867          /* Unique call identifier */
00868          ast_copy_string(cdr->uniqueid, c->uniqueid, sizeof(cdr->uniqueid));
00869          /* Linked call identifier */
00870          ast_copy_string(cdr->linkedid, c->linkedid, sizeof(cdr->linkedid));
00871       }
00872    }
00873    return 0;
00874 }

int ast_cdr_isset_unanswered ( void   ) 

Definition at line 163 of file cdr.c.

References unanswered.

Referenced by ring_entry(), and try_calling().

00164 {
00165    return unanswered;
00166 }

void ast_cdr_merge ( struct ast_cdr to,
struct ast_cdr from 
)

Move the non-null data from the "from" cdr to the "to" cdr.

Parameters:
to the cdr to get the goodies
from the cdr to give the goodies

Definition at line 500 of file cdr.c.

References ast_cdr::accountcode, ast_cdr::amaflags, ast_cdr::answer, ast_cdr_append(), ast_cdr_discard(), AST_CDR_DOCUMENTATION, ast_cdr_dup(), AST_CDR_FLAG_CHILD, AST_CDR_FLAG_KEEP_VARS, AST_CDR_FLAG_LOCKED, AST_CDR_FLAG_POST_DISABLED, AST_CDR_FLAG_POSTED, AST_CDR_NOANSWER, ast_copy_string(), ast_log(), ast_set_flag, ast_strlen_zero(), ast_test_flag, ast_tv(), ast_tvcmp(), ast_tvzero(), ast_cdr::billsec, cdr_merge_vars(), ast_cdr::channel, ast_cdr::clid, ast_cdr::dcontext, ast_cdr::disposition, ast_cdr::dst, ast_cdr::dstchannel, ast_cdr::duration, ast_cdr::end, ast_cdr::lastapp, ast_cdr::lastdata, LOG_WARNING, ast_cdr::next, ast_cdr::peeraccount, ast_cdr::src, ast_cdr::start, and ast_cdr::userfield.

00501 {
00502    struct ast_cdr *zcdr;
00503    struct ast_cdr *lto = NULL;
00504    struct ast_cdr *lfrom = NULL;
00505    int discard_from = 0;
00506    
00507    if (!to || !from)
00508       return;
00509 
00510    /* don't merge into locked CDR's -- it's bad business */
00511    if (ast_test_flag(to, AST_CDR_FLAG_LOCKED)) {
00512       zcdr = to; /* safety valve? */
00513       while (to->next) {
00514          lto = to;
00515          to = to->next;
00516       }
00517       
00518       if (ast_test_flag(to, AST_CDR_FLAG_LOCKED)) {
00519          ast_log(LOG_WARNING, "Merging into locked CDR... no choice.");
00520          to = zcdr; /* safety-- if all there are is locked CDR's, then.... ?? */
00521          lto = NULL;
00522       }
00523    }
00524 
00525    if (ast_test_flag(from, AST_CDR_FLAG_LOCKED)) {
00526       struct ast_cdr *llfrom = NULL;
00527       discard_from = 1;
00528       if (lto) {
00529          /* insert the from stuff after lto */
00530          lto->next = from;
00531          lfrom = from;
00532          while (lfrom && lfrom->next) {
00533             if (!lfrom->next->next)
00534                llfrom = lfrom;
00535             lfrom = lfrom->next; 
00536          }
00537          /* rip off the last entry and put a copy of the to at the end */
00538          llfrom->next = to;
00539          from = lfrom;
00540       } else {
00541          /* save copy of the current *to cdr */
00542          struct ast_cdr tcdr;
00543          memcpy(&tcdr, to, sizeof(tcdr));
00544          /* copy in the locked from cdr */
00545          memcpy(to, from, sizeof(*to));
00546          lfrom = from;
00547          while (lfrom && lfrom->next) {
00548             if (!lfrom->next->next)
00549                llfrom = lfrom;
00550             lfrom = lfrom->next; 
00551          }
00552          from->next = NULL;
00553          /* rip off the last entry and put a copy of the to at the end */
00554          if (llfrom == from)
00555             to = to->next = ast_cdr_dup(&tcdr);
00556          else
00557             to = llfrom->next = ast_cdr_dup(&tcdr);
00558          from = lfrom;
00559       }
00560    }
00561    
00562    if (!ast_tvzero(from->start)) {
00563       if (!ast_tvzero(to->start)) {
00564          if (ast_tvcmp(to->start, from->start) > 0 ) {
00565             to->start = from->start; /* use the earliest time */
00566             from->start = ast_tv(0,0); /* we actively "steal" these values */
00567          }
00568          /* else nothing to do */
00569       } else {
00570          to->start = from->start;
00571          from->start = ast_tv(0,0); /* we actively "steal" these values */
00572       }
00573    }
00574    if (!ast_tvzero(from->answer)) {
00575       if (!ast_tvzero(to->answer)) {
00576          if (ast_tvcmp(to->answer, from->answer) > 0 ) {
00577             to->answer = from->answer; /* use the earliest time */
00578             from->answer = ast_tv(0,0); /* we actively "steal" these values */
00579          }
00580          /* we got the earliest answer time, so we'll settle for that? */
00581       } else {
00582          to->answer = from->answer;
00583          from->answer = ast_tv(0,0); /* we actively "steal" these values */
00584       }
00585    }
00586    if (!ast_tvzero(from->end)) {
00587       if (!ast_tvzero(to->end)) {
00588          if (ast_tvcmp(to->end, from->end) < 0 ) {
00589             to->end = from->end; /* use the latest time */
00590             from->end = ast_tv(0,0); /* we actively "steal" these values */
00591             to->duration = to->end.tv_sec - to->start.tv_sec;  /* don't forget to update the duration, billsec, when we set end */
00592             to->billsec = ast_tvzero(to->answer) ? 0 : to->end.tv_sec - to->answer.tv_sec;
00593          }
00594          /* else, nothing to do */
00595       } else {
00596          to->end = from->end;
00597          from->end = ast_tv(0,0); /* we actively "steal" these values */
00598          to->duration = to->end.tv_sec - to->start.tv_sec;
00599          to->billsec = ast_tvzero(to->answer) ? 0 : to->end.tv_sec - to->answer.tv_sec;
00600       }
00601    }
00602    if (to->disposition < from->disposition) {
00603       to->disposition = from->disposition;
00604       from->disposition = AST_CDR_NOANSWER;
00605    }
00606    if (ast_strlen_zero(to->lastapp) && !ast_strlen_zero(from->lastapp)) {
00607       ast_copy_string(to->lastapp, from->lastapp, sizeof(to->lastapp));
00608       from->lastapp[0] = 0; /* theft */
00609    }
00610    if (ast_strlen_zero(to->lastdata) && !ast_strlen_zero(from->lastdata)) {
00611       ast_copy_string(to->lastdata, from->lastdata, sizeof(to->lastdata));
00612       from->lastdata[0] = 0; /* theft */
00613    }
00614    if (ast_strlen_zero(to->dcontext) && !ast_strlen_zero(from->dcontext)) {
00615       ast_copy_string(to->dcontext, from->dcontext, sizeof(to->dcontext));
00616       from->dcontext[0] = 0; /* theft */
00617    }
00618    if (ast_strlen_zero(to->dstchannel) && !ast_strlen_zero(from->dstchannel)) {
00619       ast_copy_string(to->dstchannel, from->dstchannel, sizeof(to->dstchannel));
00620       from->dstchannel[0] = 0; /* theft */
00621    }
00622    if (!ast_strlen_zero(from->channel) && (ast_strlen_zero(to->channel) || !strncasecmp(from->channel, "Agent/", 6))) {
00623       ast_copy_string(to->channel, from->channel, sizeof(to->channel));
00624       from->channel[0] = 0; /* theft */
00625    }
00626    if (ast_strlen_zero(to->src) && !ast_strlen_zero(from->src)) {
00627       ast_copy_string(to->src, from->src, sizeof(to->src));
00628       from->src[0] = 0; /* theft */
00629    }
00630    if (ast_strlen_zero(to->clid) && !ast_strlen_zero(from->clid)) {
00631       ast_copy_string(to->clid, from->clid, sizeof(to->clid));
00632       from->clid[0] = 0; /* theft */
00633    }
00634    if (ast_strlen_zero(to->dst) && !ast_strlen_zero(from->dst)) {
00635       ast_copy_string(to->dst, from->dst, sizeof(to->dst));
00636       from->dst[0] = 0; /* theft */
00637    }
00638    if (!to->amaflags)
00639       to->amaflags = AST_CDR_DOCUMENTATION;
00640    if (!from->amaflags)
00641       from->amaflags = AST_CDR_DOCUMENTATION; /* make sure both amaflags are set to something (DOC is default) */
00642    if (ast_test_flag(from, AST_CDR_FLAG_LOCKED) || (to->amaflags == AST_CDR_DOCUMENTATION && from->amaflags != AST_CDR_DOCUMENTATION)) {
00643       to->amaflags = from->amaflags;
00644    }
00645    if (ast_test_flag(from, AST_CDR_FLAG_LOCKED) || (ast_strlen_zero(to->accountcode) && !ast_strlen_zero(from->accountcode))) {
00646       ast_copy_string(to->accountcode, from->accountcode, sizeof(to->accountcode));
00647    }
00648    if (ast_test_flag(from, AST_CDR_FLAG_LOCKED) || (ast_strlen_zero(to->peeraccount) && !ast_strlen_zero(from->peeraccount))) {
00649       ast_copy_string(to->peeraccount, from->peeraccount, sizeof(to->peeraccount));
00650    }
00651    if (ast_test_flag(from, AST_CDR_FLAG_LOCKED) || (ast_strlen_zero(to->userfield) && !ast_strlen_zero(from->userfield))) {
00652       ast_copy_string(to->userfield, from->userfield, sizeof(to->userfield));
00653    }
00654    /* flags, varsead, ? */
00655    cdr_merge_vars(from, to);
00656 
00657    if (ast_test_flag(from, AST_CDR_FLAG_KEEP_VARS))
00658       ast_set_flag(to, AST_CDR_FLAG_KEEP_VARS);
00659    if (ast_test_flag(from, AST_CDR_FLAG_POSTED))
00660       ast_set_flag(to, AST_CDR_FLAG_POSTED);
00661    if (ast_test_flag(from, AST_CDR_FLAG_LOCKED))
00662       ast_set_flag(to, AST_CDR_FLAG_LOCKED);
00663    if (ast_test_flag(from, AST_CDR_FLAG_CHILD))
00664       ast_set_flag(to, AST_CDR_FLAG_CHILD);
00665    if (ast_test_flag(from, AST_CDR_FLAG_POST_DISABLED))
00666       ast_set_flag(to, AST_CDR_FLAG_POST_DISABLED);
00667 
00668    /* last, but not least, we need to merge any forked CDRs to the 'to' cdr */
00669    while (from->next) {
00670       /* just rip 'em off the 'from' and insert them on the 'to' */
00671       zcdr = from->next;
00672       from->next = zcdr->next;
00673       zcdr->next = NULL;
00674       /* zcdr is now ripped from the current list; */
00675       ast_cdr_append(to, zcdr);
00676    }
00677    if (discard_from)
00678       ast_cdr_discard(from);
00679 }

void ast_cdr_noanswer ( struct ast_cdr cdr  ) 

A call wasn't answered.

Parameters:
cdr the cdr you wish to associate with the call Marks the channel disposition as "NO ANSWER" Will skip CDR's in chain with ANS_LOCK bit set. (see forkCDR() application.

Definition at line 734 of file cdr.c.

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

Referenced by ast_cdr_disposition(), handle_cause(), queue_exec(), try_calling(), and wait_for_answer().

00735 {
00736    char *chan; 
00737 
00738    while (cdr) {
00739       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00740          chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
00741          if (ast_test_flag(cdr, AST_CDR_FLAG_POSTED))
00742             ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
00743          if (cdr->disposition < AST_CDR_NOANSWER)
00744             cdr->disposition = AST_CDR_NOANSWER;
00745       }
00746       cdr = cdr->next;
00747    }
00748 }

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

Register a CDR handling engine.

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

Returns:
0 on success, -1 on failure

Definition at line 108 of file cdr.c.

References ast_calloc, ast_copy_string(), ast_log(), AST_RWLIST_INSERT_HEAD, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_cdr_beitem::be, ast_cdr_beitem::desc, ast_cdr_beitem::list, LOG_WARNING, and ast_cdr_beitem::name.

Referenced by config_module(), load_config(), load_module(), odbc_load_module(), and unload_module().

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

void ast_cdr_reset ( struct ast_cdr cdr,
struct ast_flags flags 
)

Reset the detail record, optionally posting it first.

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 1106 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_POST_DISABLED, AST_CDR_FLAG_POST_ENABLE, 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_cdr::next, and ast_cdr::start.

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

01107 {
01108    struct ast_cdr *duplicate;
01109    struct ast_flags flags = { 0 };
01110 
01111    if (_flags)
01112       ast_copy_flags(&flags, _flags, AST_FLAGS_ALL);
01113 
01114    for ( ; cdr ; cdr = cdr->next) {
01115       /* Detach if post is requested */
01116       if (ast_test_flag(&flags, AST_CDR_FLAG_LOCKED) || !ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
01117          if (ast_test_flag(&flags, AST_CDR_FLAG_POSTED)) {
01118             ast_cdr_end(cdr);
01119             if ((duplicate = ast_cdr_dup(cdr))) {
01120                ast_cdr_detach(duplicate);
01121             }
01122             ast_set_flag(cdr, AST_CDR_FLAG_POSTED);
01123          }
01124 
01125          /* enable CDR only */
01126          if (ast_test_flag(&flags, AST_CDR_FLAG_POST_ENABLE)) {
01127             ast_clear_flag(cdr, AST_CDR_FLAG_POST_DISABLED);
01128             continue;
01129          }
01130 
01131          /* clear variables */
01132          if (!ast_test_flag(&flags, AST_CDR_FLAG_KEEP_VARS)) {
01133             ast_cdr_free_vars(cdr, 0);
01134          }
01135 
01136          /* Reset to initial state */
01137          ast_clear_flag(cdr, AST_FLAGS_ALL); 
01138          memset(&cdr->start, 0, sizeof(cdr->start));
01139          memset(&cdr->end, 0, sizeof(cdr->end));
01140          memset(&cdr->answer, 0, sizeof(cdr->answer));
01141          cdr->billsec = 0;
01142          cdr->duration = 0;
01143          ast_cdr_start(cdr);
01144          cdr->disposition = AST_CDR_NOANSWER;
01145       }
01146    }
01147 }

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

Definition at line 366 of file cdr.c.

References ast_cdr_getvar(), AST_LIST_TRAVERSE, ast_log(), ast_str_append(), ast_str_reset(), ast_strlen_zero(), ast_var_name(), ast_var_value(), cdr_readonly_vars, ast_var_t::entries, LOG_ERROR, ast_cdr::next, total, var, and ast_cdr::varshead.

Referenced by handle_showchan().

00367 {
00368    struct ast_var_t *variables;
00369    const char *var, *val;
00370    char *tmp;
00371    char workspace[256];
00372    int total = 0, x = 0, i;
00373 
00374    ast_str_reset(*buf);
00375 
00376    for (; cdr; cdr = recur ? cdr->next : NULL) {
00377       if (++x > 1)
00378          ast_str_append(buf, 0, "\n");
00379 
00380       AST_LIST_TRAVERSE(&cdr->varshead, variables, entries) {
00381          if (variables &&
00382              (var = ast_var_name(variables)) && (val = ast_var_value(variables)) &&
00383              !ast_strlen_zero(var) && !ast_strlen_zero(val)) {
00384             if (ast_str_append(buf, 0, "level %d: %s%c%s%c", x, var, delim, val, sep) < 0) {
00385                ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
00386                break;
00387             } else
00388                total++;
00389          } else 
00390             break;
00391       }
00392 
00393       for (i = 0; cdr_readonly_vars[i]; i++) {
00394          workspace[0] = 0; /* null out the workspace, because the cdr_get_tv() won't write anything if time is NULL, so you get old vals */
00395          ast_cdr_getvar(cdr, cdr_readonly_vars[i], &tmp, workspace, sizeof(workspace), 0, 0);
00396          if (!tmp)
00397             continue;
00398          
00399          if (ast_str_append(buf, 0, "level %d: %s%c%s%c", x, cdr_readonly_vars[i], delim, tmp, sep) < 0) {
00400             ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
00401             break;
00402          } else
00403             total++;
00404       }
00405    }
00406 
00407    return total;
00408 }

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

Set account code, will generate AMI event.

Definition at line 945 of file cdr.c.

References ast_cdr::accountcode, accountcode, ast_channel::accountcode, AST_CDR_FLAG_LOCKED, ast_copy_string(), ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_channel::cdr, EVENT_FLAG_CALL, manager_event, ast_channel::name, ast_cdr::next, and ast_channel::uniqueid.

Referenced by __ast_request_and_dial(), ast_call_forward(), ast_pbx_outgoing_app(), ast_pbx_outgoing_exten(), auth_exec(), cdr_write(), and rpt_call().

00946 {
00947    struct ast_cdr *cdr = chan->cdr;
00948    const char *old_acct = "";
00949 
00950    if (!ast_strlen_zero(chan->accountcode)) {
00951       old_acct = ast_strdupa(chan->accountcode);
00952    }
00953 
00954    ast_string_field_set(chan, accountcode, account);
00955    for ( ; cdr ; cdr = cdr->next) {
00956       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00957          ast_copy_string(cdr->accountcode, chan->accountcode, sizeof(cdr->accountcode));
00958       }
00959    }
00960 
00961    manager_event(EVENT_FLAG_CALL, "NewAccountCode",
00962          "Channel: %s\r\n"
00963          "Uniqueid: %s\r\n"
00964          "AccountCode: %s\r\n"
00965          "OldAccountCode: %s\r\n",
00966          chan->name, chan->uniqueid, chan->accountcode, old_acct);
00967 
00968    return 0;
00969 }

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

Set AMA flags for channel.

Definition at line 997 of file cdr.c.

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

Referenced by cdr_write(), and pbx_builtin_setamaflags().

00998 {
00999    struct ast_cdr *cdr;
01000    int newflag = ast_cdr_amaflags2int(flag);
01001    if (newflag) {
01002       for (cdr = chan->cdr; cdr; cdr = cdr->next) {
01003          if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
01004             cdr->amaflags = newflag;
01005          }
01006       }
01007    }
01008 
01009    return 0;
01010 }

void ast_cdr_setanswer ( struct ast_cdr cdr,
struct timeval  t 
)

Set the answer time for a call.

Parameters:
cdr the cdr you wish to associate with the call
t the answer time Starts all CDR stuff necessary for doing CDR when answering a call NULL argument is just fine.

Definition at line 797 of file cdr.c.

References ast_cdr::answer, AST_CDR_FLAG_ANSLOCKED, AST_CDR_FLAG_DONT_TOUCH, AST_CDR_FLAG_LOCKED, ast_test_flag, check_post(), and ast_cdr::next.

00798 {
00799 
00800    for (; cdr; cdr = cdr->next) {
00801       if (ast_test_flag(cdr, AST_CDR_FLAG_ANSLOCKED))
00802          continue;
00803       if (ast_test_flag(cdr, AST_CDR_FLAG_DONT_TOUCH) && ast_test_flag(cdr, AST_CDR_FLAG_LOCKED))
00804          continue;
00805       check_post(cdr);
00806       cdr->answer = t;
00807    }
00808 }

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

Set the last executed application.

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 785 of file cdr.c.

References AST_CDR_FLAG_LOCKED, ast_copy_string(), ast_test_flag, check_post(), ast_cdr::lastapp, ast_cdr::lastdata, ast_cdr::next, and S_OR.

Referenced by __ast_request_and_dial(), agi_handle_command(), clear_caller(), findmeexec(), and pbx_exec().

00786 {
00787 
00788    for (; cdr; cdr = cdr->next) {
00789       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00790          check_post(cdr);
00791          ast_copy_string(cdr->lastapp, S_OR(app, ""), sizeof(cdr->lastapp));
00792          ast_copy_string(cdr->lastdata, S_OR(data, ""), sizeof(cdr->lastdata));
00793       }
00794    }
00795 }

int ast_cdr_setcid ( 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
Returns:
0 by default

Definition at line 841 of file cdr.c.

References AST_CDR_FLAG_LOCKED, ast_test_flag, ast_cdr::next, and set_one_cid().

Referenced by ast_bridge_call(), and callerid_write().

00842 {
00843    for (; cdr; cdr = cdr->next) {
00844       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED))
00845          set_one_cid(cdr, c);
00846    }
00847    return 0;
00848 }

void ast_cdr_setdestchan ( struct ast_cdr cdr,
const char *  chan 
)

Set the destination channel, if there was one.

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 775 of file cdr.c.

References AST_CDR_FLAG_LOCKED, ast_copy_string(), ast_test_flag, check_post(), ast_cdr::dstchannel, and ast_cdr::next.

Referenced by dial_exec_full(), park_exec_full(), ring_entry(), and try_calling().

00776 {
00777    for (; cdr; cdr = cdr->next) {
00778       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00779          check_post(cdr);
00780          ast_copy_string(cdr->dstchannel, chann, sizeof(cdr->dstchannel));
00781       }
00782    }
00783 }

void ast_cdr_setdisposition ( struct ast_cdr cdr,
long int  disposition 
)

Set the disposition for a call.

Parameters:
cdr the cdr you wish to associate with the call
disposition the new disposition Set the disposition on a call. NULL argument is just fine.

Definition at line 810 of file cdr.c.

References AST_CDR_FLAG_LOCKED, ast_test_flag, check_post(), ast_cdr::disposition, and ast_cdr::next.

00811 {
00812 
00813    for (; cdr; cdr = cdr->next) {
00814       if (ast_test_flag(cdr, AST_CDR_FLAG_LOCKED))
00815          continue;
00816       check_post(cdr);
00817       cdr->disposition = disposition;
00818    }
00819 }

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

Set the peer account.

Definition at line 971 of file cdr.c.

References AST_CDR_FLAG_LOCKED, ast_copy_string(), ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_channel::cdr, EVENT_FLAG_CALL, manager_event, ast_channel::name, ast_cdr::next, ast_cdr::peeraccount, ast_channel::peeraccount, and ast_channel::uniqueid.

Referenced by cdr_write().

00972 {
00973    struct ast_cdr *cdr = chan->cdr;
00974    const char *old_acct = "";
00975 
00976    if (!ast_strlen_zero(chan->peeraccount)) {
00977       old_acct = ast_strdupa(chan->peeraccount);
00978    }
00979 
00980    ast_string_field_set(chan, peeraccount, account);
00981    for ( ; cdr ; cdr = cdr->next) {
00982       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00983          ast_copy_string(cdr->peeraccount, chan->peeraccount, sizeof(cdr->peeraccount));
00984       }
00985    }
00986 
00987    manager_event(EVENT_FLAG_CALL, "NewPeerAccount",
00988          "Channel: %s\r\n"
00989          "Uniqueid: %s\r\n"
00990          "PeerAccount: %s\r\n"
00991          "OldPeerAccount: %s\r\n",
00992          chan->name, chan->uniqueid, chan->peeraccount, old_acct);
00993 
00994    return 0;
00995 }

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

Set CDR user field for channel (stored in CDR).

Definition at line 1012 of file cdr.c.

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

Referenced by __agent_start_monitoring(), ast_bridge_call(), cdr_write(), handle_request_info(), and start_monitor_exec().

01013 {
01014    struct ast_cdr *cdr = chan->cdr;
01015 
01016    for ( ; cdr ; cdr = cdr->next) {
01017       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) 
01018          ast_copy_string(cdr->userfield, userfield, sizeof(cdr->userfield));
01019    }
01020 
01021    return 0;
01022 }

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 299 of file cdr.c.

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

Referenced by ast_cdr_fork(), and cdr_write().

00300 {
00301    struct ast_var_t *newvariable;
00302    struct varshead *headp;
00303    int x;
00304    
00305    for (x = 0; cdr_readonly_vars[x]; x++) {
00306       if (!strcasecmp(name, cdr_readonly_vars[x])) {
00307          ast_log(LOG_ERROR, "Attempt to set the '%s' read-only variable!.\n", name);
00308          return -1;
00309       }
00310    }
00311 
00312    if (!cdr) {
00313       ast_log(LOG_ERROR, "Attempt to set a variable on a nonexistent CDR record.\n");
00314       return -1;
00315    }
00316 
00317    for (; cdr; cdr = recur ? cdr->next : NULL) {
00318       if (ast_test_flag(cdr, AST_CDR_FLAG_DONT_TOUCH) && ast_test_flag(cdr, AST_CDR_FLAG_LOCKED))
00319          continue;
00320       headp = &cdr->varshead;
00321       AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) {
00322          if (!strcasecmp(ast_var_name(newvariable), name)) {
00323             /* there is already such a variable, delete it */
00324             AST_LIST_REMOVE_CURRENT(entries);
00325             ast_var_delete(newvariable);
00326             break;
00327          }
00328       }
00329       AST_LIST_TRAVERSE_SAFE_END;
00330       
00331       if (value) {
00332          newvariable = ast_var_assign(name, value);
00333          AST_LIST_INSERT_HEAD(headp, newvariable, entries);
00334       }
00335    }
00336 
00337    return 0;
00338 }

void ast_cdr_specialized_reset ( struct ast_cdr cdr,
struct ast_flags flags 
)

Reset the detail record times, 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 1149 of file cdr.c.

References ast_cdr::answer, AST_CDR_FLAG_POST_DISABLED, AST_CDR_NULL, 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, and ast_cdr::start.

Referenced by ast_bridge_call().

01150 {
01151    struct ast_flags flags = { 0 };
01152 
01153    if (_flags)
01154       ast_copy_flags(&flags, _flags, AST_FLAGS_ALL);
01155    
01156    /* Reset to initial state */
01157    if (ast_test_flag(cdr, AST_CDR_FLAG_POST_DISABLED)) { /* But do NOT lose the NoCDR() setting */
01158       ast_clear_flag(cdr, AST_FLAGS_ALL); 
01159       ast_set_flag(cdr, AST_CDR_FLAG_POST_DISABLED);
01160    } else {
01161       ast_clear_flag(cdr, AST_FLAGS_ALL); 
01162    }
01163    
01164    memset(&cdr->start, 0, sizeof(cdr->start));
01165    memset(&cdr->end, 0, sizeof(cdr->end));
01166    memset(&cdr->answer, 0, sizeof(cdr->answer));
01167    cdr->billsec = 0;
01168    cdr->duration = 0;
01169    ast_cdr_start(cdr);
01170    cdr->disposition = AST_CDR_NULL;
01171 }

void ast_cdr_start ( struct ast_cdr cdr  ) 

Start a call.

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

Definition at line 681 of file cdr.c.

References AST_CDR_FLAG_LOCKED, ast_test_flag, ast_tvnow(), chan, ast_cdr::channel, check_post(), ast_cdr::next, S_OR, and ast_cdr::start.

Referenced by __ast_channel_alloc_ap(), __ast_request_and_dial(), ast_bridge_call(), ast_cdr_reset(), ast_cdr_specialized_reset(), ast_pbx_outgoing_cdr_failed(), builtin_blindtransfer(), clear_caller(), and findmeexec().

00682 {
00683    char *chan; 
00684 
00685    for (; cdr; cdr = cdr->next) {
00686       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00687          chan = S_OR(cdr->channel, "<unknown>");
00688          check_post(cdr);
00689          cdr->start = ast_tvnow();
00690       }
00691    }
00692 }

void ast_cdr_submit_batch ( int  shutdown  ) 

Spawns (possibly) a new thread to submit a batch of CDRs to the backend engines.

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 1227 of file cdr.c.

References ast_debug, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create_detached_background, AST_PTHREADT_NULL, batch, batchscheduleronly, cdr_batch_lock, do_batch_backend_process(), ast_cdr_batch::head, LOG_WARNING, and reset_batch().

Referenced by ast_cdr_engine_term(), and submit_scheduled_batch().

01228 {
01229    struct ast_cdr_batch_item *oldbatchitems = NULL;
01230    pthread_t batch_post_thread = AST_PTHREADT_NULL;
01231 
01232    /* if there's no batch, or no CDRs in the batch, then there's nothing to do */
01233    if (!batch || !batch->head)
01234       return;
01235 
01236    /* move the old CDRs aside, and prepare a new CDR batch */
01237    ast_mutex_lock(&cdr_batch_lock);
01238    oldbatchitems = batch->head;
01239    reset_batch();
01240    ast_mutex_unlock(&cdr_batch_lock);
01241 
01242    /* if configured, spawn a new thread to post these CDRs,
01243       also try to save as much as possible if we are shutting down safely */
01244    if (batchscheduleronly || do_shutdown) {
01245       ast_debug(1, "CDR single-threaded batch processing begins now\n");
01246       do_batch_backend_process(oldbatchitems);
01247    } else {
01248       if (ast_pthread_create_detached_background(&batch_post_thread, NULL, do_batch_backend_process, oldbatchitems)) {
01249          ast_log(LOG_WARNING, "CDR processing thread could not detach, now trying in this thread\n");
01250          do_batch_backend_process(oldbatchitems);
01251       } else {
01252          ast_debug(1, "CDR multi-threaded batch processing begins now\n");
01253       }
01254    }
01255 }

void ast_cdr_unregister ( const char *  name  ) 

Unregister a CDR handling engine.

unregister a CDR driver

Definition at line 143 of file cdr.c.

References ast_free, AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_verb, ast_cdr_beitem::list, and ast_cdr_beitem::name.

Referenced by load_config(), reload(), tds_unload_module(), and unload_module().

00144 {
00145    struct ast_cdr_beitem *i = NULL;
00146 
00147    AST_RWLIST_WRLOCK(&be_list);
00148    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&be_list, i, list) {
00149       if (!strcasecmp(name, i->name)) {
00150          AST_RWLIST_REMOVE_CURRENT(list);
00151          break;
00152       }
00153    }
00154    AST_RWLIST_TRAVERSE_SAFE_END;
00155    AST_RWLIST_UNLOCK(&be_list);
00156 
00157    if (i) {
00158       ast_verb(2, "Unregistered '%s' CDR backend\n", name);
00159       ast_free(i);
00160    }
00161 }

int ast_cdr_update ( struct ast_channel chan  ) 

Update CDR on a channel

Definition at line 1038 of file cdr.c.

References ast_channel::accountcode, ast_cdr::accountcode, AST_CDR_FLAG_LOCKED, ast_copy_string(), ast_test_flag, ast_channel::cdr, ast_channel::context, ast_cdr::dcontext, ast_cdr::dst, ast_channel::exten, ast_channel::linkedid, ast_cdr::linkedid, ast_channel::macrocontext, ast_channel::macroexten, ast_cdr::next, ast_channel::peeraccount, ast_cdr::peeraccount, S_OR, and set_one_cid().

Referenced by __ast_pbx_run(), __ast_request_and_dial(), ast_bridge_call(), cb_events(), clear_caller(), findmeexec(), and local_call().

01039 {
01040    struct ast_cdr *cdr = c->cdr;
01041 
01042    for ( ; cdr ; cdr = cdr->next) {
01043       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
01044          set_one_cid(cdr, c);
01045 
01046          /* Copy account code et-al */ 
01047          ast_copy_string(cdr->accountcode, c->accountcode, sizeof(cdr->accountcode));
01048          ast_copy_string(cdr->peeraccount, c->peeraccount, sizeof(cdr->peeraccount));
01049          ast_copy_string(cdr->linkedid, c->linkedid, sizeof(cdr->linkedid));
01050 
01051          /* Destination information */ /* XXX privilege macro* ? */
01052          ast_copy_string(cdr->dst, S_OR(c->macroexten, c->exten), sizeof(cdr->dst));
01053          ast_copy_string(cdr->dcontext, S_OR(c->macrocontext, c->context), sizeof(cdr->dcontext));
01054       }
01055    }
01056 
01057    return 0;
01058 }

static void cdr_get_tv ( struct timeval  when,
const char *  fmt,
char *  buf,
int  bufsize 
) [static]

Definition at line 207 of file cdr.c.

References ast_localtime(), and ast_strftime().

Referenced by ast_cdr_getvar().

00208 {
00209    if (fmt == NULL) {   /* raw mode */
00210       snprintf(buf, bufsize, "%ld.%06ld", (long)when.tv_sec, (long)when.tv_usec);
00211    } else {
00212       if (when.tv_sec) {
00213          struct ast_tm tm;
00214          
00215          ast_localtime(&when, &tm, NULL);
00216          ast_strftime(buf, bufsize, fmt, &tm);
00217       }
00218    }
00219 }

static void cdr_merge_vars ( struct ast_cdr to,
struct ast_cdr from 
) [static]

Definition at line 465 of file cdr.c.

References AST_LIST_MOVE_CURRENT, AST_LIST_TRAVERSE, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_log(), ast_var_name(), ast_var_value(), LOG_NOTICE, and ast_cdr::varshead.

Referenced by ast_cdr_merge().

00466 {
00467    struct ast_var_t *variablesfrom,*variablesto;
00468    struct varshead *headpfrom = &to->varshead;
00469    struct varshead *headpto = &from->varshead;
00470    AST_LIST_TRAVERSE_SAFE_BEGIN(headpfrom, variablesfrom, entries) {
00471       /* for every var in from, stick it in to */
00472       const char *fromvarname, *fromvarval;
00473       const char *tovarname = NULL, *tovarval = NULL;
00474       fromvarname = ast_var_name(variablesfrom);
00475       fromvarval = ast_var_value(variablesfrom);
00476       tovarname = 0;
00477 
00478       /* now, quick see if that var is in the 'to' cdr already */
00479       AST_LIST_TRAVERSE(headpto, variablesto, entries) {
00480 
00481          /* now, quick see if that var is in the 'to' cdr already */
00482          if ( strcasecmp(fromvarname, ast_var_name(variablesto)) == 0 ) {
00483             tovarname = ast_var_name(variablesto);
00484             tovarval = ast_var_value(variablesto);
00485             break;
00486          }
00487       }
00488       if (tovarname && strcasecmp(fromvarval,tovarval) != 0) {  /* this message here to see how irritating the userbase finds it */
00489          ast_log(LOG_NOTICE, "Merging CDR's: variable %s value %s dropped in favor of value %s\n", tovarname, fromvarval, tovarval);
00490          continue;
00491       } else if (tovarname && strcasecmp(fromvarval,tovarval) == 0) /* if they are the same, the job is done */
00492          continue;
00493 
00494       /* rip this var out of the from cdr, and stick it in the to cdr */
00495       AST_LIST_MOVE_CURRENT(headpto, entries);
00496    }
00497    AST_LIST_TRAVERSE_SAFE_END;
00498 }

int check_cdr_enabled ( void   ) 

Return TRUE if CDR subsystem is enabled.

Definition at line 100 of file cdr.c.

References enabled.

Referenced by action_coresettings(), and handle_show_settings().

00101 {
00102    return enabled;
00103 }

static void check_post ( struct ast_cdr cdr  )  [static]

print a warning if cdr already posted

Definition at line 424 of file cdr.c.

References AST_CDR_FLAG_POSTED, ast_log(), ast_test_flag, ast_cdr::channel, LOG_NOTICE, and S_OR.

Referenced by ast_cdr_answer(), ast_cdr_busy(), ast_cdr_end(), ast_cdr_failed(), ast_cdr_setanswer(), ast_cdr_setapp(), ast_cdr_setdestchan(), ast_cdr_setdisposition(), ast_cdr_start(), and post_cdr().

00425 {
00426    if (!cdr)
00427       return;
00428    if (ast_test_flag(cdr, AST_CDR_FLAG_POSTED))
00429       ast_log(LOG_NOTICE, "CDR on channel '%s' already posted\n", S_OR(cdr->channel, "<unknown>"));
00430 }

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

Definition at line 1210 of file cdr.c.

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

Referenced by ast_cdr_submit_batch().

01211 {
01212    struct ast_cdr_batch_item *processeditem;
01213    struct ast_cdr_batch_item *batchitem = data;
01214 
01215    /* Push each CDR into storage mechanism(s) and free all the memory */
01216    while (batchitem) {
01217       post_cdr(batchitem->cdr);
01218       ast_cdr_free(batchitem->cdr);
01219       processeditem = batchitem;
01220       batchitem = batchitem->next;
01221       ast_free(processeditem);
01222    }
01223 
01224    return NULL;
01225 }

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

Definition at line 1332 of file cdr.c.

References ast_cond_timedwait(), ast_debug, ast_mutex_lock(), ast_mutex_unlock(), ast_samp2tv(), ast_sched_runq(), ast_sched_wait(), ast_tvadd(), ast_tvnow(), cdr_pending_cond, and cdr_pending_lock.

Referenced by do_reload().

01333 {
01334    struct timespec timeout;
01335    int schedms;
01336    int numevents = 0;
01337 
01338    for (;;) {
01339       struct timeval now;
01340       schedms = ast_sched_wait(sched);
01341       /* this shouldn't happen, but provide a 1 second default just in case */
01342       if (schedms <= 0)
01343          schedms = 1000;
01344       now = ast_tvadd(ast_tvnow(), ast_samp2tv(schedms, 1000));
01345       timeout.tv_sec = now.tv_sec;
01346       timeout.tv_nsec = now.tv_usec * 1000;
01347       /* prevent stuff from clobbering cdr_pending_cond, then wait on signals sent to it until the timeout expires */
01348       ast_mutex_lock(&cdr_pending_lock);
01349       ast_cond_timedwait(&cdr_pending_cond, &cdr_pending_lock, &timeout);
01350       numevents = ast_sched_runq(sched);
01351       ast_mutex_unlock(&cdr_pending_lock);
01352       ast_debug(2, "Processed %d scheduled CDR batches from the run queue\n", numevents);
01353    }
01354 
01355    return NULL;
01356 }

static int do_reload ( int  reload  )  [static]

Definition at line 1440 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_load2(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_OPT_FLAG_END_CDR_BEFORE_H_EXTEN, AST_OPT_FLAG_INITIATED_SECONDS, ast_options, ast_pthread_create_background, AST_PTHREADT_NULL, ast_register_atexit(), ast_sched_add(), AST_SCHED_DEL, ast_set2_flag, 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_batch_lock, cdr_pending_cond, cdr_sched, cdr_thread, cli_submit, config, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, CONFIG_STATUS_FILEUNCHANGED, do_cdr(), enabled, EVENT_FLAG_SYSTEM, LOG_ERROR, LOG_NOTICE, LOG_WARNING, manager_event, submit_scheduled_batch(), and unanswered.

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

01441 {
01442    struct ast_config *config;
01443    const char *enabled_value;
01444    const char *unanswered_value;
01445    const char *batched_value;
01446    const char *scheduleronly_value;
01447    const char *batchsafeshutdown_value;
01448    const char *size_value;
01449    const char *time_value;
01450    const char *end_before_h_value;
01451    const char *initiatedseconds_value;
01452    int cfg_size;
01453    int cfg_time;
01454    int was_enabled;
01455    int was_batchmode;
01456    int res=0;
01457    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
01458 
01459    if ((config = ast_config_load2("cdr.conf", "cdr", config_flags)) == CONFIG_STATUS_FILEUNCHANGED)
01460       return 0;
01461    if (config == CONFIG_STATUS_FILEMISSING || config == CONFIG_STATUS_FILEUNCHANGED || config == CONFIG_STATUS_FILEINVALID) {
01462       return 0;
01463    }
01464 
01465    ast_mutex_lock(&cdr_batch_lock);
01466 
01467    batchsize = BATCH_SIZE_DEFAULT;
01468    batchtime = BATCH_TIME_DEFAULT;
01469    batchscheduleronly = BATCH_SCHEDULER_ONLY_DEFAULT;
01470    batchsafeshutdown = BATCH_SAFE_SHUTDOWN_DEFAULT;
01471    was_enabled = enabled;
01472    was_batchmode = batchmode;
01473    enabled = 1;
01474    batchmode = 0;
01475 
01476    /* don't run the next scheduled CDR posting while reloading */
01477    AST_SCHED_DEL(sched, cdr_sched);
01478 
01479    if (config) {
01480       if ((enabled_value = ast_variable_retrieve(config, "general", "enable"))) {
01481          enabled = ast_true(enabled_value);
01482       }
01483       if ((unanswered_value = ast_variable_retrieve(config, "general", "unanswered"))) {
01484          unanswered = ast_true(unanswered_value);
01485       }
01486       if ((batched_value = ast_variable_retrieve(config, "general", "batch"))) {
01487          batchmode = ast_true(batched_value);
01488       }
01489       if ((scheduleronly_value = ast_variable_retrieve(config, "general", "scheduleronly"))) {
01490          batchscheduleronly = ast_true(scheduleronly_value);
01491       }
01492       if ((batchsafeshutdown_value = ast_variable_retrieve(config, "general", "safeshutdown"))) {
01493          batchsafeshutdown = ast_true(batchsafeshutdown_value);
01494       }
01495       if ((size_value = ast_variable_retrieve(config, "general", "size"))) {
01496          if (sscanf(size_value, "%30d", &cfg_size) < 1)
01497             ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", size_value);
01498          else if (cfg_size < 0)
01499             ast_log(LOG_WARNING, "Invalid maximum batch size '%d' specified, using default\n", cfg_size);
01500          else
01501             batchsize = cfg_size;
01502       }
01503       if ((time_value = ast_variable_retrieve(config, "general", "time"))) {
01504          if (sscanf(time_value, "%30d", &cfg_time) < 1)
01505             ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", time_value);
01506          else if (cfg_time < 0)
01507             ast_log(LOG_WARNING, "Invalid maximum batch time '%d' specified, using default\n", cfg_time);
01508          else
01509             batchtime = cfg_time;
01510       }
01511       if ((end_before_h_value = ast_variable_retrieve(config, "general", "endbeforehexten")))
01512          ast_set2_flag(&ast_options, ast_true(end_before_h_value), AST_OPT_FLAG_END_CDR_BEFORE_H_EXTEN);
01513       if ((initiatedseconds_value = ast_variable_retrieve(config, "general", "initiatedseconds")))
01514          ast_set2_flag(&ast_options, ast_true(initiatedseconds_value), AST_OPT_FLAG_INITIATED_SECONDS);
01515    }
01516 
01517    if (enabled && !batchmode) {
01518       ast_log(LOG_NOTICE, "CDR simple logging enabled.\n");
01519    } else if (enabled && batchmode) {
01520       cdr_sched = ast_sched_add(sched, batchtime * 1000, submit_scheduled_batch, NULL);
01521       ast_log(LOG_NOTICE, "CDR batch mode logging enabled, first of either size %d or time %d seconds.\n", batchsize, batchtime);
01522    } else {
01523       ast_log(LOG_NOTICE, "CDR logging disabled, data will be lost.\n");
01524    }
01525 
01526    /* if this reload enabled the CDR batch mode, create the background thread
01527       if it does not exist */
01528    if (enabled && batchmode && (!was_enabled || !was_batchmode) && (cdr_thread == AST_PTHREADT_NULL)) {
01529       ast_cond_init(&cdr_pending_cond, NULL);
01530       if (ast_pthread_create_background(&cdr_thread, NULL, do_cdr, NULL) < 0) {
01531          ast_log(LOG_ERROR, "Unable to start CDR thread.\n");
01532          AST_SCHED_DEL(sched, cdr_sched);
01533       } else {
01534          ast_cli_register(&cli_submit);
01535          ast_register_atexit(ast_cdr_engine_term);
01536          res = 0;
01537       }
01538    /* if this reload disabled the CDR and/or batch mode and there is a background thread,
01539       kill it */
01540    } else if (((!enabled && was_enabled) || (!batchmode && was_batchmode)) && (cdr_thread != AST_PTHREADT_NULL)) {
01541       /* wake up the thread so it will exit */
01542       pthread_cancel(cdr_thread);
01543       pthread_kill(cdr_thread, SIGURG);
01544       pthread_join(cdr_thread, NULL);
01545       cdr_thread = AST_PTHREADT_NULL;
01546       ast_cond_destroy(&cdr_pending_cond);
01547       ast_cli_unregister(&cli_submit);
01548       ast_unregister_atexit(ast_cdr_engine_term);
01549       res = 0;
01550       /* if leaving batch mode, then post the CDRs in the batch,
01551          and don't reschedule, since we are stopping CDR logging */
01552       if (!batchmode && was_batchmode) {
01553          ast_cdr_engine_term();
01554       }
01555    } else {
01556       res = 0;
01557    }
01558 
01559    ast_mutex_unlock(&cdr_batch_lock);
01560    ast_config_destroy(config);
01561    manager_event(EVENT_FLAG_SYSTEM, "Reload", "Module: CDR\r\nMessage: CDR subsystem reload requested\r\n");
01562 
01563    return res;
01564 }

static char* handle_cli_status ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1358 of file cdr.c.

References ast_cli_args::argc, ast_cli(), AST_RWLIST_EMPTY, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_sched_when(), batch, batchmode, batchsafeshutdown, batchscheduleronly, batchsize, batchtime, cdr_sched, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, enabled, ESS, ast_cli_args::fd, ast_cdr_beitem::list, ast_cdr_beitem::name, ast_cdr_batch::size, unanswered, and ast_cli_entry::usage.

01359 {
01360    struct ast_cdr_beitem *beitem=NULL;
01361    int cnt=0;
01362    long nextbatchtime=0;
01363 
01364    switch (cmd) {
01365    case CLI_INIT:
01366       e->command = "cdr show status";
01367       e->usage = 
01368          "Usage: cdr show status\n"
01369          "  Displays the Call Detail Record engine system status.\n";
01370       return NULL;
01371    case CLI_GENERATE:
01372       return NULL;
01373    }
01374 
01375    if (a->argc > 3)
01376       return CLI_SHOWUSAGE;
01377 
01378    ast_cli(a->fd, "\n");
01379    ast_cli(a->fd, "Call Detail Record (CDR) settings\n");
01380    ast_cli(a->fd, "----------------------------------\n");
01381    ast_cli(a->fd, "  Logging:                    %s\n", enabled ? "Enabled" : "Disabled");
01382    ast_cli(a->fd, "  Mode:                       %s\n", batchmode ? "Batch" : "Simple");
01383    if (enabled) {
01384       ast_cli(a->fd, "  Log unanswered calls:       %s\n\n", unanswered ? "Yes" : "No");
01385       if (batchmode) {
01386          ast_cli(a->fd, "* Batch Mode Settings\n");
01387          ast_cli(a->fd, "  -------------------\n");
01388          if (batch)
01389             cnt = batch->size;
01390          if (cdr_sched > -1)
01391             nextbatchtime = ast_sched_when(sched, cdr_sched);
01392          ast_cli(a->fd, "  Safe shutdown:              %s\n", batchsafeshutdown ? "Enabled" : "Disabled");
01393          ast_cli(a->fd, "  Threading model:            %s\n", batchscheduleronly ? "Scheduler only" : "Scheduler plus separate threads");
01394          ast_cli(a->fd, "  Current batch size:         %d record%s\n", cnt, ESS(cnt));
01395          ast_cli(a->fd, "  Maximum batch size:         %d record%s\n", batchsize, ESS(batchsize));
01396          ast_cli(a->fd, "  Maximum batch time:         %d second%s\n", batchtime, ESS(batchtime));
01397          ast_cli(a->fd, "  Next batch processing time: %ld second%s\n\n", nextbatchtime, ESS(nextbatchtime));
01398       }
01399       ast_cli(a->fd, "* Registered Backends\n");
01400       ast_cli(a->fd, "  -------------------\n");
01401       AST_RWLIST_RDLOCK(&be_list);
01402       if (AST_RWLIST_EMPTY(&be_list)) {
01403          ast_cli(a->fd, "    (none)\n");
01404       } else {
01405          AST_RWLIST_TRAVERSE(&be_list, beitem, list) {
01406             ast_cli(a->fd, "    %s\n", beitem->name);
01407          }
01408       }
01409       AST_RWLIST_UNLOCK(&be_list);
01410       ast_cli(a->fd, "\n");
01411    }
01412 
01413    return CLI_SUCCESS;
01414 }

static char* handle_cli_submit ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1416 of file cdr.c.

References ast_cli_args::argc, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, submit_unscheduled_batch(), and ast_cli_entry::usage.

01417 {
01418    switch (cmd) {
01419    case CLI_INIT:
01420       e->command = "cdr submit";
01421       e->usage = 
01422          "Usage: cdr submit\n"
01423          "       Posts all pending batched CDR data to the configured CDR backend engine modules.\n";
01424       return NULL;
01425    case CLI_GENERATE:
01426       return NULL;
01427    }
01428    if (a->argc > 2)
01429       return CLI_SHOWUSAGE;
01430 
01431    submit_unscheduled_batch();
01432    ast_cli(a->fd, "Submitted CDRs to backend engines for processing.  This may take a while.\n");
01433 
01434    return CLI_SUCCESS;
01435 }

static int init_batch ( void   )  [static]

Note:
Don't call without cdr_batch_lock

Definition at line 1199 of file cdr.c.

References ast_malloc, batch, and reset_batch().

Referenced by ast_cdr_detach(), and ast_cdr_engine_init().

01200 {
01201    /* This is the single meta-batch used to keep track of all CDRs during the entire life of the program */
01202    if (!(batch = ast_malloc(sizeof(*batch))))
01203       return -1;
01204 
01205    reset_batch();
01206 
01207    return 0;
01208 }

static void post_cdr ( struct ast_cdr cdr  )  [static]

Definition at line 1073 of file cdr.c.

References AST_CDR_ANSWERED, AST_CDR_FLAG_DIALED, AST_CDR_FLAG_ORIGINATED, AST_CDR_FLAG_POST_DISABLED, AST_CDR_FLAG_POSTED, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_set_flag, ast_strlen_zero(), ast_test_flag, ast_cdr_beitem::be, chan, ast_cdr::channel, check_post(), ast_cdr::disposition, ast_cdr::dstchannel, ast_cdr_beitem::list, ast_cdr::next, S_OR, and unanswered.

Referenced by ast_cdr_detach(), and do_batch_backend_process().

01074 {
01075    char *chan;
01076    struct ast_cdr_beitem *i;
01077 
01078    for ( ; cdr ; cdr = cdr->next) {
01079       if (!unanswered && cdr->disposition < AST_CDR_ANSWERED && (ast_strlen_zero(cdr->channel) || ast_strlen_zero(cdr->dstchannel))) {
01080          /* For people, who don't want to see unanswered single-channel events */
01081          ast_set_flag(cdr, AST_CDR_FLAG_POST_DISABLED);
01082          continue;
01083       }
01084 
01085       /* don't post CDRs that are for dialed channels unless those
01086        * channels were originated from asterisk (pbx_spool, manager,
01087        * cli) */
01088       if (ast_test_flag(cdr, AST_CDR_FLAG_DIALED) && !ast_test_flag(cdr, AST_CDR_FLAG_ORIGINATED)) {
01089          ast_set_flag(cdr, AST_CDR_FLAG_POST_DISABLED);
01090          continue;
01091       }
01092 
01093       chan = S_OR(cdr->channel, "<unknown>");
01094       check_post(cdr);
01095       ast_set_flag(cdr, AST_CDR_FLAG_POSTED);
01096       if (ast_test_flag(cdr, AST_CDR_FLAG_POST_DISABLED))
01097          continue;
01098       AST_RWLIST_RDLOCK(&be_list);
01099       AST_RWLIST_TRAVERSE(&be_list, i, list) {
01100          i->be(cdr);
01101       }
01102       AST_RWLIST_UNLOCK(&be_list);
01103    }
01104 }

static void reset_batch ( void   )  [static]

Note:
Don't call without cdr_batch_lock

Definition at line 1191 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().

01192 {
01193    batch->size = 0;
01194    batch->head = NULL;
01195    batch->tail = NULL;
01196 }

static void set_one_cid ( struct ast_cdr cdr,
struct ast_channel c 
) [static]

Definition at line 822 of file cdr.c.

References ast_copy_string(), ast_strlen_zero(), ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_name, ast_callerid::cid_num, ast_cdr::clid, num, S_OR, and ast_cdr::src.

Referenced by ast_cdr_init(), ast_cdr_setcid(), and ast_cdr_update().

00823 {
00824    /* Grab source from ANI or normal Caller*ID */
00825    const char *num = S_OR(c->cid.cid_ani, c->cid.cid_num);
00826    if (!cdr)
00827       return;
00828    if (!ast_strlen_zero(c->cid.cid_name)) {
00829       if (!ast_strlen_zero(num)) /* both name and number */
00830          snprintf(cdr->clid, sizeof(cdr->clid), "\"%s\" <%s>", c->cid.cid_name, num);
00831       else           /* only name */
00832          ast_copy_string(cdr->clid, c->cid.cid_name, sizeof(cdr->clid));
00833    } else if (!ast_strlen_zero(num)) { /* only number */
00834       ast_copy_string(cdr->clid, num, sizeof(cdr->clid));
00835    } else {          /* nothing known */
00836       cdr->clid[0] = '\0';
00837    }
00838    ast_copy_string(cdr->src, S_OR(num, ""), sizeof(cdr->src));
00839 
00840 }

static int submit_scheduled_batch ( const void *  data  )  [static]

Definition at line 1257 of file cdr.c.

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

Referenced by do_reload(), and submit_unscheduled_batch().

01258 {
01259    ast_cdr_submit_batch(0);
01260    /* manually reschedule from this point in time */
01261    cdr_sched = ast_sched_add(sched, batchtime * 1000, submit_scheduled_batch, NULL);
01262    /* returning zero so the scheduler does not automatically reschedule */
01263    return 0;
01264 }

static void submit_unscheduled_batch ( void   )  [static]

Definition at line 1266 of file cdr.c.

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

Referenced by ast_cdr_detach(), and handle_cli_submit().

01267 {
01268    /* this is okay since we are not being called from within the scheduler */
01269    AST_SCHED_DEL(sched, cdr_sched);
01270    /* schedule the submission to occur ASAP (1 ms) */
01271    cdr_sched = ast_sched_add(sched, 1, submit_scheduled_batch, NULL);
01272    /* signal the do_cdr thread to wakeup early and do some work (that lazy thread ;) */
01273    ast_mutex_lock(&cdr_pending_lock);
01274    ast_cond_signal(&cdr_pending_cond);
01275    ast_mutex_unlock(&cdr_pending_lock);
01276 }


Variable Documentation

char ast_default_accountcode[AST_MAX_ACCOUNT_CODE]

Definition at line 55 of file cdr.c.

Referenced by __ast_channel_alloc_ap().

int ast_default_amaflags = AST_CDR_DOCUMENTATION

Default AMA flag for billing records (CDR's)

Definition at line 54 of file cdr.c.

Referenced by __ast_channel_alloc_ap(), and ast_bridge_call().

struct ast_cdr_batch * batch [static]

int batchmode [static]

Definition at line 88 of file cdr.c.

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

int batchsafeshutdown [static]

Definition at line 92 of file cdr.c.

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

int batchscheduleronly [static]

Definition at line 91 of file cdr.c.

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

int batchsize [static]

Definition at line 89 of file cdr.c.

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

int batchtime [static]

Definition at line 90 of file cdr.c.

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

ast_mutex_t cdr_batch_lock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static]

Definition at line 94 of file cdr.c.

Referenced by ast_cdr_detach(), ast_cdr_engine_init(), ast_cdr_submit_batch(), and do_reload().

Definition at line 98 of file cdr.c.

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

ast_mutex_t cdr_pending_lock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static]

Definition at line 97 of file cdr.c.

Referenced by do_cdr(), and submit_unscheduled_batch().

const char* const cdr_readonly_vars[] [static]

Initial value:

 { "clid", "src", "dst", "dcontext", "channel", "dstchannel",
                    "lastapp", "lastdata", "start", "answer", "end", "duration",
                    "billsec", "disposition", "amaflags", "accountcode", "uniqueid", "linkedid",
                    "userfield", NULL }

Definition at line 292 of file cdr.c.

Referenced by ast_cdr_serialize_variables(), and ast_cdr_setvar().

int cdr_sched = -1 [static]

pthread_t cdr_thread = AST_PTHREADT_NULL [static]

Definition at line 79 of file cdr.c.

Referenced by do_reload().

struct ast_cli_entry cli_status = AST_CLI_DEFINE(handle_cli_status, "Display the CDR status") [static]

Definition at line 1438 of file cdr.c.

Referenced by ast_cdr_engine_init(), and dnsmgr_init().

struct ast_cli_entry cli_submit = AST_CLI_DEFINE(handle_cli_submit, "Posts all pending batched CDR data") [static]

Definition at line 1437 of file cdr.c.

Referenced by do_reload().

int enabled [static]

struct sched_context* sched [static]

Definition at line 77 of file cdr.c.

int unanswered [static]

Is the CDR subsystem enabled ?

Definition at line 87 of file cdr.c.

Referenced by ast_cdr_isset_unanswered(), do_reload(), handle_cli_status(), and post_cdr().


Generated on Wed Oct 28 13:31:52 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6