Thu Apr 8 01:21:49 2010

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

Defines

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

Functions

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, char *app, 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_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)
 AST_MUTEX_DEFINE_STATIC (cdr_pending_lock)
 AST_MUTEX_DEFINE_STATIC (cdr_batch_lock)
static AST_RWLIST_HEAD_STATIC (be_list, ast_cdr_beitem)
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_status_deprecated (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_cond_t cdr_pending_cond
static const char * 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", .deprecate_cmd = &cli_status_deprecated)
static struct ast_cli_entry cli_status_deprecated = AST_CLI_DEFINE(handle_cli_status_deprecated, "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

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 453 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(), builtin_blindtransfer(), clear_caller(), findmeexec(), and start_monitor_exec().

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

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 1014 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(), process_dahdi(), and set_config().

01015 {
01016    if (!strcasecmp(flag, "default"))
01017       return 0;
01018    if (!strcasecmp(flag, "omit"))
01019       return AST_CDR_OMIT;
01020    if (!strcasecmp(flag, "billing"))
01021       return AST_CDR_BILLING;
01022    if (!strcasecmp(flag, "documentation"))
01023       return AST_CDR_DOCUMENTATION;
01024    return -1;
01025 }

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 688 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().

00689 {
00690 
00691    for (; cdr; cdr = cdr->next) {
00692       if (ast_test_flag(cdr, AST_CDR_FLAG_ANSLOCKED)) 
00693          continue;
00694       if (ast_test_flag(cdr, AST_CDR_FLAG_DONT_TOUCH) && ast_test_flag(cdr, AST_CDR_FLAG_LOCKED))
00695          continue;
00696       check_post(cdr);
00697       if (cdr->disposition < AST_CDR_ANSWERED)
00698          cdr->disposition = AST_CDR_ANSWERED;
00699       if (ast_tvzero(cdr->answer))
00700          cdr->answer = ast_tvnow();
00701    }
00702 }

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

Definition at line 1127 of file cdr.c.

References ast_cdr::next.

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

01128 {
01129    struct ast_cdr *ret;
01130 
01131    if (cdr) {
01132       ret = cdr;
01133 
01134       while (cdr->next)
01135          cdr = cdr->next;
01136       cdr->next = newcdr;
01137    } else {
01138       ret = newcdr;
01139    }
01140 
01141    return ret;
01142 }

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

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

Definition at line 980 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.

00981 {
00982    struct ast_cdr *cdr = chan->cdr;
00983 
00984    for ( ; cdr ; cdr = cdr->next) {
00985       int len = strlen(cdr->userfield);
00986 
00987       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED))
00988          ast_copy_string(cdr->userfield + len, userfield, sizeof(cdr->userfield) - len);
00989    }
00990 
00991    return 0;
00992 }

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 704 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().

00705 {
00706 
00707    for (; cdr; cdr = cdr->next) {
00708       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00709          check_post(cdr);
00710          if (cdr->disposition < AST_CDR_BUSY)
00711             cdr->disposition = AST_CDR_BUSY;
00712       }
00713    }
00714 }

int ast_cdr_copy_vars ( struct ast_cdr to_cdr,
struct ast_cdr from_cdr 
)

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

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

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 1232 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, 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().

01233 {
01234    struct ast_cdr_batch_item *newtail;
01235    int curr;
01236 
01237    if (!cdr)
01238       return;
01239 
01240    /* maybe they disabled CDR stuff completely, so just drop it */
01241    if (!enabled) {
01242       ast_debug(1, "Dropping CDR !\n");
01243       ast_set_flag(cdr, AST_CDR_FLAG_POST_DISABLED);
01244       ast_cdr_free(cdr);
01245       return;
01246    }
01247 
01248    /* post stuff immediately if we are not in batch mode, this is legacy behaviour */
01249    if (!batchmode) {
01250       post_cdr(cdr);
01251       ast_cdr_free(cdr);
01252       return;
01253    }
01254 
01255    /* otherwise, each CDR gets put into a batch list (at the end) */
01256    ast_debug(1, "CDR detaching from this thread\n");
01257 
01258    /* we'll need a new tail for every CDR */
01259    if (!(newtail = ast_calloc(1, sizeof(*newtail)))) {
01260       post_cdr(cdr);
01261       ast_cdr_free(cdr);
01262       return;
01263    }
01264 
01265    /* don't traverse a whole list (just keep track of the tail) */
01266    ast_mutex_lock(&cdr_batch_lock);
01267    if (!batch)
01268       init_batch();
01269    if (!batch->head) {
01270       /* new batch is empty, so point the head at the new tail */
01271       batch->head = newtail;
01272    } else {
01273       /* already got a batch with something in it, so just append a new tail */
01274       batch->tail->next = newtail;
01275    }
01276    newtail->cdr = cdr;
01277    batch->tail = newtail;
01278    curr = batch->size++;
01279    ast_mutex_unlock(&cdr_batch_lock);
01280 
01281    /* if we have enough stuff to post, then do it */
01282    if (curr >= (batchsize - 1))
01283       submit_unscheduled_batch();
01284 }

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

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

Referenced by ast_async_goto(), ast_bridge_call(), ast_cdr_merge(), and ast_channel_free().

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

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 903 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().

00904 {
00905    switch (disposition) {
00906    case AST_CDR_NULL:
00907       return "NO ANSWER"; /* by default, for backward compatibility */
00908    case AST_CDR_NOANSWER:
00909       return "NO ANSWER";
00910    case AST_CDR_FAILED:
00911       return "FAILED";     
00912    case AST_CDR_BUSY:
00913       return "BUSY";    
00914    case AST_CDR_ANSWERED:
00915       return "ANSWERED";
00916    }
00917    return "UNKNOWN";
00918 }

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 747 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().

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

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 168 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(), and ast_cdr_reset().

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

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 880 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_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().

00881 {
00882    for ( ; cdr ; cdr = cdr->next) {
00883       if (ast_test_flag(cdr, AST_CDR_FLAG_DONT_TOUCH) && ast_test_flag(cdr, AST_CDR_FLAG_LOCKED))
00884          continue;
00885       check_post(cdr);
00886       if (ast_tvzero(cdr->end))
00887          cdr->end = ast_tvnow();
00888       if (ast_tvzero(cdr->start)) {
00889          ast_log(LOG_WARNING, "CDR on channel '%s' has not started\n", S_OR(cdr->channel, "<unknown>"));
00890          cdr->disposition = AST_CDR_FAILED;
00891       } else
00892          cdr->duration = cdr->end.tv_sec - cdr->start.tv_sec;
00893       if (ast_tvzero(cdr->answer)) {
00894          if (cdr->disposition == AST_CDR_ANSWERED) {
00895             ast_log(LOG_WARNING, "CDR on channel '%s' has no answer time but is 'ANSWERED'\n", S_OR(cdr->channel, "<unknown>"));
00896             cdr->disposition = AST_CDR_FAILED;
00897          }
00898       } else
00899          cdr->billsec = cdr->end.tv_sec - cdr->answer.tv_sec;
00900    }
00901 }

int ast_cdr_engine_init ( void   ) 

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

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

01524 {
01525    int res;
01526 
01527    sched = sched_context_create();
01528    if (!sched) {
01529       ast_log(LOG_ERROR, "Unable to create schedule context.\n");
01530       return -1;
01531    }
01532 
01533    ast_cli_register(&cli_status);
01534 
01535    res = do_reload(0);
01536    if (res) {
01537       ast_mutex_lock(&cdr_batch_lock);
01538       res = init_batch();
01539       ast_mutex_unlock(&cdr_batch_lock);
01540    }
01541 
01542    return res;
01543 }

int ast_cdr_engine_reload ( void   ) 

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

Definition at line 1552 of file cdr.c.

References do_reload().

01553 {
01554    return do_reload(1);
01555 }

void ast_cdr_engine_term ( void   ) 

Submit any remaining CDRs and prepare for shutdown

Definition at line 1547 of file cdr.c.

References ast_cdr_submit_batch(), and batchsafeshutdown.

Referenced by do_reload(), and quit_handler().

01548 {
01549    ast_cdr_submit_batch(batchsafeshutdown);
01550 }

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 716 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().

00717 {
00718    for (; cdr; cdr = cdr->next) {
00719       check_post(cdr);
00720       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00721          check_post(cdr);
00722          if (cdr->disposition < AST_CDR_FAILED)
00723             cdr->disposition = AST_CDR_FAILED;
00724       }
00725    }
00726 }

char* ast_cdr_flags2str ( int  flag  ) 

Converts AMA flag to printable string

Definition at line 921 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(), build_radius_record(), csv_log(), handle_skinny_show_line(), manager_log(), sip_show_user(), and tds_log().

00922 {
00923    switch (flag) {
00924    case AST_CDR_OMIT:
00925       return "OMIT";
00926    case AST_CDR_BILLING:
00927       return "BILLING";
00928    case AST_CDR_DOCUMENTATION:
00929       return "DOCUMENTATION";
00930    }
00931    return "Unknown";
00932 }

void ast_cdr_free ( struct ast_cdr cdr  ) 

Free a CDR record.

Parameters:
cdr ast_cdr structure to free Returns nothing

Definition at line 429 of file cdr.c.

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

Referenced by ast_cdr_detach(), and do_batch_backend_process().

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

void ast_cdr_free_vars ( struct ast_cdr cdr,
int  recur 
)

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

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

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 219 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::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().

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

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

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

00188 {
00189    if (ast_strlen_zero(name))
00190       return NULL;
00191 
00192    for (; cdr; cdr = recur ? cdr->next : NULL) {
00193       struct ast_var_t *variables;
00194       struct varshead *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    }
00200 
00201    return NULL;
00202 }

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

References ast_channel::_state, 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::macrocontext, ast_channel::macroexten, ast_cdr::next, S_OR, set_one_cid(), 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().

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

int ast_cdr_isset_unanswered ( void   ) 

Definition at line 160 of file cdr.c.

References unanswered.

Referenced by ring_entry(), and try_calling().

00161 {
00162    return unanswered;
00163 }

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 497 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::src, ast_cdr::start, and ast_cdr::userfield.

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

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 728 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().

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

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, 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 1060 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().

01061 {
01062    struct ast_cdr *duplicate;
01063    struct ast_flags flags = { 0 };
01064 
01065    if (_flags)
01066       ast_copy_flags(&flags, _flags, AST_FLAGS_ALL);
01067 
01068    for ( ; cdr ; cdr = cdr->next) {
01069       /* Detach if post is requested */
01070       if (ast_test_flag(&flags, AST_CDR_FLAG_LOCKED) || !ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
01071          if (ast_test_flag(&flags, AST_CDR_FLAG_POSTED)) {
01072             ast_cdr_end(cdr);
01073             if ((duplicate = ast_cdr_dup(cdr))) {
01074                ast_cdr_detach(duplicate);
01075             }
01076             ast_set_flag(cdr, AST_CDR_FLAG_POSTED);
01077          }
01078 
01079          /* enable CDR only */
01080          if (ast_test_flag(&flags, AST_CDR_FLAG_POST_ENABLE)) {
01081             ast_clear_flag(cdr, AST_CDR_FLAG_POST_DISABLED);
01082             continue;
01083          }
01084 
01085          /* clear variables */
01086          if (!ast_test_flag(&flags, AST_CDR_FLAG_KEEP_VARS)) {
01087             ast_cdr_free_vars(cdr, 0);
01088          }
01089 
01090          /* Reset to initial state */
01091          ast_clear_flag(cdr, AST_FLAGS_ALL); 
01092          memset(&cdr->start, 0, sizeof(cdr->start));
01093          memset(&cdr->end, 0, sizeof(cdr->end));
01094          memset(&cdr->answer, 0, sizeof(cdr->answer));
01095          cdr->billsec = 0;
01096          cdr->duration = 0;
01097          ast_cdr_start(cdr);
01098          cdr->disposition = AST_CDR_NOANSWER;
01099       }
01100    }
01101 }

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

Definition at line 362 of file cdr.c.

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

Referenced by handle_showchan().

00363 {
00364    struct ast_var_t *variables;
00365    const char *var, *val;
00366    char *tmp;
00367    char workspace[256];
00368    int total = 0, x = 0, i;
00369 
00370    (*buf)->used = 0;
00371    (*buf)->str[0] = '\0';
00372 
00373    for (; cdr; cdr = recur ? cdr->next : NULL) {
00374       if (++x > 1)
00375          ast_str_append(buf, 0, "\n");
00376 
00377       AST_LIST_TRAVERSE(&cdr->varshead, variables, entries) {
00378          if (variables &&
00379              (var = ast_var_name(variables)) && (val = ast_var_value(variables)) &&
00380              !ast_strlen_zero(var) && !ast_strlen_zero(val)) {
00381             if (ast_str_append(buf, 0, "level %d: %s%c%s%c", x, var, delim, val, sep) < 0) {
00382                ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
00383                break;
00384             } else
00385                total++;
00386          } else 
00387             break;
00388       }
00389 
00390       for (i = 0; cdr_readonly_vars[i]; i++) {
00391          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 */
00392          ast_cdr_getvar(cdr, cdr_readonly_vars[i], &tmp, workspace, sizeof(workspace), 0, 0);
00393          if (!tmp)
00394             continue;
00395          
00396          if (ast_str_append(buf, 0, "level %d: %s%c%s%c", x, cdr_readonly_vars[i], delim, tmp, sep) < 0) {
00397             ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
00398             break;
00399          } else
00400             total++;
00401       }
00402    }
00403 
00404    return total;
00405 }

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

Set account code, will generate AMI event.

Definition at line 934 of file cdr.c.

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

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

00935 {
00936    struct ast_cdr *cdr = chan->cdr;
00937    char buf[BUFSIZ/2] = "";
00938    if (!ast_strlen_zero(chan->accountcode))
00939       ast_copy_string(buf, chan->accountcode, sizeof(buf));
00940 
00941    ast_string_field_set(chan, accountcode, account);
00942    for ( ; cdr ; cdr = cdr->next) {
00943       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00944          ast_copy_string(cdr->accountcode, chan->accountcode, sizeof(cdr->accountcode));
00945       }
00946    }
00947 
00948    /* Signal change of account code to manager */
00949    manager_event(EVENT_FLAG_CALL, "NewAccountCode", "Channel: %s\r\nUniqueid: %s\r\nAccountCode: %s\r\nOldAccountCode: %s\r\n", chan->name, chan->uniqueid, chan->accountcode, buf);
00950    return 0;
00951 }

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

Set AMA flags for channel.

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

00954 {
00955    struct ast_cdr *cdr;
00956    int newflag = ast_cdr_amaflags2int(flag);
00957    if (newflag) {
00958       for (cdr = chan->cdr; cdr; cdr = cdr->next) {
00959          if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00960             cdr->amaflags = newflag;
00961          }
00962       }
00963    }
00964 
00965    return 0;
00966 }

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 791 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.

00792 {
00793 
00794    for (; cdr; cdr = cdr->next) {
00795       if (ast_test_flag(cdr, AST_CDR_FLAG_ANSLOCKED))
00796          continue;
00797       if (ast_test_flag(cdr, AST_CDR_FLAG_DONT_TOUCH) && ast_test_flag(cdr, AST_CDR_FLAG_LOCKED))
00798          continue;
00799       check_post(cdr);
00800       cdr->answer = t;
00801    }
00802 }

void ast_cdr_setapp ( struct ast_cdr cdr,
char *  app,
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 779 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().

00780 {
00781 
00782    for (; cdr; cdr = cdr->next) {
00783       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00784          check_post(cdr);
00785          ast_copy_string(cdr->lastapp, S_OR(app, ""), sizeof(cdr->lastapp));
00786          ast_copy_string(cdr->lastdata, S_OR(data, ""), sizeof(cdr->lastdata));
00787       }
00788    }
00789 }

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 836 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().

00837 {
00838    for (; cdr; cdr = cdr->next) {
00839       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED))
00840          set_one_cid(cdr, c);
00841    }
00842    return 0;
00843 }

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 769 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().

00770 {
00771    for (; cdr; cdr = cdr->next) {
00772       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00773          check_post(cdr);
00774          ast_copy_string(cdr->dstchannel, chann, sizeof(cdr->dstchannel));
00775       }
00776    }
00777 }

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

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

00805 {
00806 
00807    for (; cdr; cdr = cdr->next) {
00808       if (ast_test_flag(cdr, AST_CDR_FLAG_LOCKED))
00809          continue;
00810       check_post(cdr);
00811       cdr->disposition = disposition;
00812    }
00813 }

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

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

Definition at line 968 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(), cdr_write(), handle_request_info(), and start_monitor_exec().

00969 {
00970    struct ast_cdr *cdr = chan->cdr;
00971 
00972    for ( ; cdr ; cdr = cdr->next) {
00973       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) 
00974          ast_copy_string(cdr->userfield, userfield, sizeof(cdr->userfield));
00975    }
00976 
00977    return 0;
00978 }

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 292 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(), cdr_write(), and set_one_cid().

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

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 1103 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().

01104 {
01105    struct ast_flags flags = { 0 };
01106 
01107    if (_flags)
01108       ast_copy_flags(&flags, _flags, AST_FLAGS_ALL);
01109    
01110    /* Reset to initial state */
01111    if (ast_test_flag(cdr, AST_CDR_FLAG_POST_DISABLED)) { /* But do NOT lose the NoCDR() setting */
01112       ast_clear_flag(cdr, AST_FLAGS_ALL); 
01113       ast_set_flag(cdr, AST_CDR_FLAG_POST_DISABLED);
01114    } else {
01115       ast_clear_flag(cdr, AST_FLAGS_ALL); 
01116    }
01117    
01118    memset(&cdr->start, 0, sizeof(cdr->start));
01119    memset(&cdr->end, 0, sizeof(cdr->end));
01120    memset(&cdr->answer, 0, sizeof(cdr->answer));
01121    cdr->billsec = 0;
01122    cdr->duration = 0;
01123    ast_cdr_start(cdr);
01124    cdr->disposition = AST_CDR_NULL;
01125 }

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 675 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().

00676 {
00677    char *chan; 
00678 
00679    for (; cdr; cdr = cdr->next) {
00680       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00681          chan = S_OR(cdr->channel, "<unknown>");
00682          check_post(cdr);
00683          cdr->start = ast_tvnow();
00684       }
00685    }
00686 }

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 1181 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, do_batch_backend_process(), ast_cdr_batch::head, LOG_WARNING, and reset_batch().

Referenced by ast_cdr_engine_term(), and submit_scheduled_batch().

01182 {
01183    struct ast_cdr_batch_item *oldbatchitems = NULL;
01184    pthread_t batch_post_thread = AST_PTHREADT_NULL;
01185 
01186    /* if there's no batch, or no CDRs in the batch, then there's nothing to do */
01187    if (!batch || !batch->head)
01188       return;
01189 
01190    /* move the old CDRs aside, and prepare a new CDR batch */
01191    ast_mutex_lock(&cdr_batch_lock);
01192    oldbatchitems = batch->head;
01193    reset_batch();
01194    ast_mutex_unlock(&cdr_batch_lock);
01195 
01196    /* if configured, spawn a new thread to post these CDRs,
01197       also try to save as much as possible if we are shutting down safely */
01198    if (batchscheduleronly || do_shutdown) {
01199       ast_debug(1, "CDR single-threaded batch processing begins now\n");
01200       do_batch_backend_process(oldbatchitems);
01201    } else {
01202       if (ast_pthread_create_detached_background(&batch_post_thread, NULL, do_batch_backend_process, oldbatchitems)) {
01203          ast_log(LOG_WARNING, "CDR processing thread could not detach, now trying in this thread\n");
01204          do_batch_backend_process(oldbatchitems);
01205       } else {
01206          ast_debug(1, "CDR multi-threaded batch processing begins now\n");
01207       }
01208    }
01209 }

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, 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          ast_verb(2, "Unregistered '%s' CDR backend\n", name);
00152          ast_free(i);
00153          break;
00154       }
00155    }
00156    AST_RWLIST_TRAVERSE_SAFE_END;
00157    AST_RWLIST_UNLOCK(&be_list);
00158 }

int ast_cdr_update ( struct ast_channel chan  ) 

Update CDR on a channel

Definition at line 994 of file cdr.c.

References 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::macrocontext, ast_channel::macroexten, ast_cdr::next, 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().

00995 {
00996    struct ast_cdr *cdr = c->cdr;
00997 
00998    for ( ; cdr ; cdr = cdr->next) {
00999       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
01000          set_one_cid(cdr, c);
01001 
01002          /* Copy account code et-al */ 
01003          ast_copy_string(cdr->accountcode, c->accountcode, sizeof(cdr->accountcode));
01004          
01005          /* Destination information */ /* XXX privilege macro* ? */
01006          ast_copy_string(cdr->dst, S_OR(c->macroexten, c->exten), sizeof(cdr->dst));
01007          ast_copy_string(cdr->dcontext, S_OR(c->macrocontext, c->context), sizeof(cdr->dcontext));
01008       }
01009    }
01010 
01011    return 0;
01012 }

AST_MUTEX_DEFINE_STATIC ( cdr_pending_lock   ) 
AST_MUTEX_DEFINE_STATIC ( cdr_batch_lock   ) 
static AST_RWLIST_HEAD_STATIC ( be_list  ,
ast_cdr_beitem   
) [static]
static void cdr_get_tv ( struct timeval  when,
const char *  fmt,
char *  buf,
int  bufsize 
) [static]

Definition at line 204 of file cdr.c.

References ast_localtime(), and ast_strftime().

Referenced by ast_cdr_getvar().

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

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

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

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

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 421 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().

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

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

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

01165 {
01166    struct ast_cdr_batch_item *processeditem;
01167    struct ast_cdr_batch_item *batchitem = data;
01168 
01169    /* Push each CDR into storage mechanism(s) and free all the memory */
01170    while (batchitem) {
01171       post_cdr(batchitem->cdr);
01172       ast_cdr_free(batchitem->cdr);
01173       processeditem = batchitem;
01174       batchitem = batchitem->next;
01175       ast_free(processeditem);
01176    }
01177 
01178    return NULL;
01179 }

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

Definition at line 1286 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(), and cdr_pending_cond.

Referenced by do_reload().

01287 {
01288    struct timespec timeout;
01289    int schedms;
01290    int numevents = 0;
01291 
01292    for (;;) {
01293       struct timeval now;
01294       schedms = ast_sched_wait(sched);
01295       /* this shouldn't happen, but provide a 1 second default just in case */
01296       if (schedms <= 0)
01297          schedms = 1000;
01298       now = ast_tvadd(ast_tvnow(), ast_samp2tv(schedms, 1000));
01299       timeout.tv_sec = now.tv_sec;
01300       timeout.tv_nsec = now.tv_usec * 1000;
01301       /* prevent stuff from clobbering cdr_pending_cond, then wait on signals sent to it until the timeout expires */
01302       ast_mutex_lock(&cdr_pending_lock);
01303       ast_cond_timedwait(&cdr_pending_cond, &cdr_pending_lock, &timeout);
01304       numevents = ast_sched_runq(sched);
01305       ast_mutex_unlock(&cdr_pending_lock);
01306       ast_debug(2, "Processed %d scheduled CDR batches from the run queue\n", numevents);
01307    }
01308 
01309    return NULL;
01310 }

static int do_reload ( int  reload  )  [static]

Definition at line 1403 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_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_pending_cond, cdr_sched, cdr_thread, cli_submit, config, CONFIG_FLAG_FILEUNCHANGED, 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(), and ast_cdr_engine_reload().

01404 {
01405    struct ast_config *config;
01406    const char *enabled_value;
01407    const char *unanswered_value;
01408    const char *batched_value;
01409    const char *scheduleronly_value;
01410    const char *batchsafeshutdown_value;
01411    const char *size_value;
01412    const char *time_value;
01413    const char *end_before_h_value;
01414    int cfg_size;
01415    int cfg_time;
01416    int was_enabled;
01417    int was_batchmode;
01418    int res=0;
01419    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
01420 
01421    if ((config = ast_config_load2("cdr.conf", "cdr", config_flags)) == CONFIG_STATUS_FILEUNCHANGED)
01422       return 0;
01423 
01424    ast_mutex_lock(&cdr_batch_lock);
01425 
01426    batchsize = BATCH_SIZE_DEFAULT;
01427    batchtime = BATCH_TIME_DEFAULT;
01428    batchscheduleronly = BATCH_SCHEDULER_ONLY_DEFAULT;
01429    batchsafeshutdown = BATCH_SAFE_SHUTDOWN_DEFAULT;
01430    was_enabled = enabled;
01431    was_batchmode = batchmode;
01432    enabled = 1;
01433    batchmode = 0;
01434 
01435    /* don't run the next scheduled CDR posting while reloading */
01436    AST_SCHED_DEL(sched, cdr_sched);
01437 
01438    if (config) {
01439       if ((enabled_value = ast_variable_retrieve(config, "general", "enable"))) {
01440          enabled = ast_true(enabled_value);
01441       }
01442       if ((unanswered_value = ast_variable_retrieve(config, "general", "unanswered"))) {
01443          unanswered = ast_true(unanswered_value);
01444       }
01445       if ((batched_value = ast_variable_retrieve(config, "general", "batch"))) {
01446          batchmode = ast_true(batched_value);
01447       }
01448       if ((scheduleronly_value = ast_variable_retrieve(config, "general", "scheduleronly"))) {
01449          batchscheduleronly = ast_true(scheduleronly_value);
01450       }
01451       if ((batchsafeshutdown_value = ast_variable_retrieve(config, "general", "safeshutdown"))) {
01452          batchsafeshutdown = ast_true(batchsafeshutdown_value);
01453       }
01454       if ((size_value = ast_variable_retrieve(config, "general", "size"))) {
01455          if (sscanf(size_value, "%30d", &cfg_size) < 1)
01456             ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", size_value);
01457          else if (cfg_size < 0)
01458             ast_log(LOG_WARNING, "Invalid maximum batch size '%d' specified, using default\n", cfg_size);
01459          else
01460             batchsize = cfg_size;
01461       }
01462       if ((time_value = ast_variable_retrieve(config, "general", "time"))) {
01463          if (sscanf(time_value, "%30d", &cfg_time) < 1)
01464             ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", time_value);
01465          else if (cfg_time < 0)
01466             ast_log(LOG_WARNING, "Invalid maximum batch time '%d' specified, using default\n", cfg_time);
01467          else
01468             batchtime = cfg_time;
01469       }
01470       if ((end_before_h_value = ast_variable_retrieve(config, "general", "endbeforehexten")))
01471          ast_set2_flag(&ast_options, ast_true(end_before_h_value), AST_OPT_FLAG_END_CDR_BEFORE_H_EXTEN);
01472    }
01473 
01474    if (enabled && !batchmode) {
01475       ast_log(LOG_NOTICE, "CDR simple logging enabled.\n");
01476    } else if (enabled && batchmode) {
01477       cdr_sched = ast_sched_add(sched, batchtime * 1000, submit_scheduled_batch, NULL);
01478       ast_log(LOG_NOTICE, "CDR batch mode logging enabled, first of either size %d or time %d seconds.\n", batchsize, batchtime);
01479    } else {
01480       ast_log(LOG_NOTICE, "CDR logging disabled, data will be lost.\n");
01481    }
01482 
01483    /* if this reload enabled the CDR batch mode, create the background thread
01484       if it does not exist */
01485    if (enabled && batchmode && (!was_enabled || !was_batchmode) && (cdr_thread == AST_PTHREADT_NULL)) {
01486       ast_cond_init(&cdr_pending_cond, NULL);
01487       if (ast_pthread_create_background(&cdr_thread, NULL, do_cdr, NULL) < 0) {
01488          ast_log(LOG_ERROR, "Unable to start CDR thread.\n");
01489          AST_SCHED_DEL(sched, cdr_sched);
01490       } else {
01491          ast_cli_register(&cli_submit);
01492          ast_register_atexit(ast_cdr_engine_term);
01493          res = 0;
01494       }
01495    /* if this reload disabled the CDR and/or batch mode and there is a background thread,
01496       kill it */
01497    } else if (((!enabled && was_enabled) || (!batchmode && was_batchmode)) && (cdr_thread != AST_PTHREADT_NULL)) {
01498       /* wake up the thread so it will exit */
01499       pthread_cancel(cdr_thread);
01500       pthread_kill(cdr_thread, SIGURG);
01501       pthread_join(cdr_thread, NULL);
01502       cdr_thread = AST_PTHREADT_NULL;
01503       ast_cond_destroy(&cdr_pending_cond);
01504       ast_cli_unregister(&cli_submit);
01505       ast_unregister_atexit(ast_cdr_engine_term);
01506       res = 0;
01507       /* if leaving batch mode, then post the CDRs in the batch,
01508          and don't reschedule, since we are stopping CDR logging */
01509       if (!batchmode && was_batchmode) {
01510          ast_cdr_engine_term();
01511       }
01512    } else {
01513       res = 0;
01514    }
01515 
01516    ast_mutex_unlock(&cdr_batch_lock);
01517    ast_config_destroy(config);
01518    manager_event(EVENT_FLAG_SYSTEM, "Reload", "Module: CDR\r\nMessage: CDR subsystem reload requested\r\n");
01519 
01520    return res;
01521 }

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

Definition at line 1312 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::name, ast_cdr_batch::size, unanswered, and ast_cli_entry::usage.

Referenced by handle_cli_status_deprecated().

01313 {
01314    struct ast_cdr_beitem *beitem=NULL;
01315    int cnt=0;
01316    long nextbatchtime=0;
01317 
01318    switch (cmd) {
01319    case CLI_INIT:
01320       e->command = "cdr show status";
01321       e->usage = 
01322          "Usage: cdr show status\n"
01323          "  Displays the Call Detail Record engine system status.\n";
01324       return NULL;
01325    case CLI_GENERATE:
01326       return NULL;
01327    }
01328 
01329    if (a->argc > 3)
01330       return CLI_SHOWUSAGE;
01331 
01332    ast_cli(a->fd, "\n");
01333    ast_cli(a->fd, "Call Detail Record (CDR) settings\n");
01334    ast_cli(a->fd, "----------------------------------\n");
01335    ast_cli(a->fd, "  Logging:                    %s\n", enabled ? "Enabled" : "Disabled");
01336    ast_cli(a->fd, "  Mode:                       %s\n", batchmode ? "Batch" : "Simple");
01337    if (enabled) {
01338       ast_cli(a->fd, "  Log unanswered calls:       %s\n\n", unanswered ? "Yes" : "No");
01339       if (batchmode) {
01340          ast_cli(a->fd, "* Batch Mode Settings\n");
01341          ast_cli(a->fd, "  -------------------\n");
01342          if (batch)
01343             cnt = batch->size;
01344          if (cdr_sched > -1)
01345             nextbatchtime = ast_sched_when(sched, cdr_sched);
01346          ast_cli(a->fd, "  Safe shutdown:              %s\n", batchsafeshutdown ? "Enabled" : "Disabled");
01347          ast_cli(a->fd, "  Threading model:            %s\n", batchscheduleronly ? "Scheduler only" : "Scheduler plus separate threads");
01348          ast_cli(a->fd, "  Current batch size:         %d record%s\n", cnt, ESS(cnt));
01349          ast_cli(a->fd, "  Maximum batch size:         %d record%s\n", batchsize, ESS(batchsize));
01350          ast_cli(a->fd, "  Maximum batch time:         %d second%s\n", batchtime, ESS(batchtime));
01351          ast_cli(a->fd, "  Next batch processing time: %ld second%s\n\n", nextbatchtime, ESS(nextbatchtime));
01352       }
01353       ast_cli(a->fd, "* Registered Backends\n");
01354       ast_cli(a->fd, "  -------------------\n");
01355       AST_RWLIST_RDLOCK(&be_list);
01356       if (AST_RWLIST_EMPTY(&be_list)) {
01357          ast_cli(a->fd, "    (none)\n");
01358       } else {
01359          AST_RWLIST_TRAVERSE(&be_list, beitem, list) {
01360             ast_cli(a->fd, "    %s\n", beitem->name);
01361          }
01362       }
01363       AST_RWLIST_UNLOCK(&be_list);
01364       ast_cli(a->fd, "\n");
01365    }
01366 
01367    return CLI_SUCCESS;
01368 }

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

Definition at line 1370 of file cdr.c.

References CLI_INIT, ast_cli_entry::command, and handle_cli_status().

01371 {
01372    char *res = handle_cli_status(e, cmd, a);
01373    if (cmd == CLI_INIT)
01374       e->command = "cdr status";
01375    return res;
01376 }

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

Definition at line 1378 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.

01379 {
01380    switch (cmd) {
01381    case CLI_INIT:
01382       e->command = "cdr submit";
01383       e->usage = 
01384          "Usage: cdr submit\n"
01385          "       Posts all pending batched CDR data to the configured CDR backend engine modules.\n";
01386       return NULL;
01387    case CLI_GENERATE:
01388       return NULL;
01389    }
01390    if (a->argc > 2)
01391       return CLI_SHOWUSAGE;
01392 
01393    submit_unscheduled_batch();
01394    ast_cli(a->fd, "Submitted CDRs to backend engines for processing.  This may take a while.\n");
01395 
01396    return CLI_SUCCESS;
01397 }

static int init_batch ( void   )  [static]
Note:
Don't call without cdr_batch_lock

Definition at line 1153 of file cdr.c.

References ast_malloc, batch, and reset_batch().

Referenced by ast_cdr_detach(), and ast_cdr_engine_init().

01154 {
01155    /* This is the single meta-batch used to keep track of all CDRs during the entire life of the program */
01156    if (!(batch = ast_malloc(sizeof(*batch))))
01157       return -1;
01158 
01159    reset_batch();
01160 
01161    return 0;
01162 }

static void post_cdr ( struct ast_cdr cdr  )  [static]

Definition at line 1027 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::next, S_OR, and unanswered.

Referenced by ast_cdr_detach(), and do_batch_backend_process().

01028 {
01029    char *chan;
01030    struct ast_cdr_beitem *i;
01031 
01032    for ( ; cdr ; cdr = cdr->next) {
01033       if (!unanswered && cdr->disposition < AST_CDR_ANSWERED && (ast_strlen_zero(cdr->channel) || ast_strlen_zero(cdr->dstchannel))) {
01034          /* For people, who don't want to see unanswered single-channel events */
01035          ast_set_flag(cdr, AST_CDR_FLAG_POST_DISABLED);
01036          continue;
01037       }
01038 
01039       /* don't post CDRs that are for dialed channels unless those
01040        * channels were originated from asterisk (pbx_spool, manager,
01041        * cli) */
01042       if (ast_test_flag(cdr, AST_CDR_FLAG_DIALED) && !ast_test_flag(cdr, AST_CDR_FLAG_ORIGINATED)) {
01043          ast_set_flag(cdr, AST_CDR_FLAG_POST_DISABLED);
01044          continue;
01045       }
01046 
01047       chan = S_OR(cdr->channel, "<unknown>");
01048       check_post(cdr);
01049       ast_set_flag(cdr, AST_CDR_FLAG_POSTED);
01050       if (ast_test_flag(cdr, AST_CDR_FLAG_POST_DISABLED))
01051          continue;
01052       AST_RWLIST_RDLOCK(&be_list);
01053       AST_RWLIST_TRAVERSE(&be_list, i, list) {
01054          i->be(cdr);
01055       }
01056       AST_RWLIST_UNLOCK(&be_list);
01057    }
01058 }

static void reset_batch ( void   )  [static]
Note:
Don't call without cdr_batch_lock

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

01146 {
01147    batch->size = 0;
01148    batch->head = NULL;
01149    batch->tail = NULL;
01150 }

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

Definition at line 816 of file cdr.c.

References ast_cdr_setvar(), ast_copy_string(), ast_strlen_zero(), ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_dnid, 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().

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

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

Definition at line 1211 of file cdr.c.

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

Referenced by do_reload(), and submit_unscheduled_batch().

01212 {
01213    ast_cdr_submit_batch(0);
01214    /* manually reschedule from this point in time */
01215    cdr_sched = ast_sched_add(sched, batchtime * 1000, submit_scheduled_batch, NULL);
01216    /* returning zero so the scheduler does not automatically reschedule */
01217    return 0;
01218 }

static void submit_unscheduled_batch ( void   )  [static]

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

01221 {
01222    /* this is okay since we are not being called from within the scheduler */
01223    AST_SCHED_DEL(sched, cdr_sched);
01224    /* schedule the submission to occur ASAP (1 ms) */
01225    cdr_sched = ast_sched_add(sched, 1, submit_scheduled_batch, NULL);
01226    /* signal the do_cdr thread to wakeup early and do some work (that lazy thread ;) */
01227    ast_mutex_lock(&cdr_pending_lock);
01228    ast_cond_signal(&cdr_pending_cond);
01229    ast_mutex_unlock(&cdr_pending_lock);
01230 }


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().

Definition at line 98 of file cdr.c.

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

const char* cdr_readonly_vars[] [static]
Initial value:
 { "clid", "src", "dst", "dcontext", "channel", "dstchannel",
                "lastapp", "lastdata", "start", "answer", "end", "duration",
                "billsec", "disposition", "amaflags", "accountcode", "uniqueid",
                "userfield", NULL }

Definition at line 285 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", .deprecate_cmd = &cli_status_deprecated) [static]

Definition at line 1401 of file cdr.c.

Referenced by ast_cdr_engine_init().

struct ast_cli_entry cli_status_deprecated = AST_CLI_DEFINE(handle_cli_status_deprecated, "Display the CDR status") [static]

Definition at line 1400 of file cdr.c.

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

Definition at line 1399 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 8 Apr 2010 for Asterisk - the Open Source PBX by  doxygen 1.6.1