This patch adds a sequence field to CDRs that can be combined with the linkedid or uniqueid field to uniquely identify a CDR.

(closes issue #15180)
Reported by: Nick_Lewis
Patches:
      cdr-sequence10.diff uploaded by mnicholson (license 96)
Tested by: mnicholson


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@227435 65c4cc65-6c06-0410-ace0-fbb531ad65f3
certified/1.8.6
Matthew Nicholson 16 years ago
parent 2263ced9dd
commit 7ed425ec80

@ -277,6 +277,8 @@ CDR
* Multiple files and formats can now be specified in cdr_custom.conf. * Multiple files and formats can now be specified in cdr_custom.conf.
* cdr_syslog has been added which allows CDRs to be written directly to syslog. * cdr_syslog has been added which allows CDRs to be written directly to syslog.
See configs/cdr_syslog.conf.sample for more information. See configs/cdr_syslog.conf.sample for more information.
* A 'sequence' field has been added to CDRs which can be combined with
linkedid or uniqueid to uniquely identify a CDR.
Calendaring for Asterisk Calendaring for Asterisk
------------------------ ------------------------

@ -184,7 +184,7 @@ static void ast_cdr_fork(struct ast_channel *chan, struct ast_flags optflags, ch
while (cdr->next) while (cdr->next)
cdr = cdr->next; cdr = cdr->next;
if (!(newcdr = ast_cdr_dup(cdr))) if (!(newcdr = ast_cdr_dup_unique(cdr)))
return; return;
ast_cdr_append(cdr, newcdr); ast_cdr_append(cdr, newcdr);

@ -7,6 +7,6 @@
; Master.csv, Simple.csv, or both. ; Master.csv, Simple.csv, or both.
; ;
;[mappings] ;[mappings]
;Master.csv => ${CSV_QUOTE(${CDR(clid)})},${CSV_QUOTE(${CDR(src)})},${CSV_QUOTE(${CDR(dst)})},${CSV_QUOTE(${CDR(dcontext)})},${CSV_QUOTE(${CDR(channel)})},${CSV_QUOTE(${CDR(dstchannel)})},${CSV_QUOTE(${CDR(lastapp)})},${CSV_QUOTE(${CDR(lastdata)})},${CSV_QUOTE(${CDR(start)})},${CSV_QUOTE(${CDR(answer)})},${CSV_QUOTE(${CDR(end)})},${CSV_QUOTE(${CDR(duration)})},${CSV_QUOTE(${CDR(billsec)})},${CSV_QUOTE(${CDR(disposition)})},${CSV_QUOTE(${CDR(amaflags)})},${CSV_QUOTE(${CDR(accountcode)})},${CSV_QUOTE(${CDR(uniqueid)})},${CSV_QUOTE(${CDR(userfield)})} ;Master.csv => ${CSV_QUOTE(${CDR(clid)})},${CSV_QUOTE(${CDR(src)})},${CSV_QUOTE(${CDR(dst)})},${CSV_QUOTE(${CDR(dcontext)})},${CSV_QUOTE(${CDR(channel)})},${CSV_QUOTE(${CDR(dstchannel)})},${CSV_QUOTE(${CDR(lastapp)})},${CSV_QUOTE(${CDR(lastdata)})},${CSV_QUOTE(${CDR(start)})},${CSV_QUOTE(${CDR(answer)})},${CSV_QUOTE(${CDR(end)})},${CSV_QUOTE(${CDR(duration)})},${CSV_QUOTE(${CDR(billsec)})},${CSV_QUOTE(${CDR(disposition)})},${CSV_QUOTE(${CDR(amaflags)})},${CSV_QUOTE(${CDR(accountcode)})},${CSV_QUOTE(${CDR(uniqueid)})},${CSV_QUOTE(${CDR(userfield)})},${CDR(sequence)}
;Simple.csv => ${CSV_QUOTE(${EPOCH})},${CSV_QUOTE(${CDR(src)})},${CSV_QUOTE(${CDR(dst)})} ;Simple.csv => ${CSV_QUOTE(${EPOCH})},${CSV_QUOTE(${CDR(src)})},${CSV_QUOTE(${CDR(dst)})}

@ -99,6 +99,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
<enum name="channel"> <enum name="channel">
<para>Channel name.</para> <para>Channel name.</para>
</enum> </enum>
<enum name="sequence">
<para>CDR sequence number.</param>
</enum>
</enumlist> </enumlist>
</parameter> </parameter>
<parameter name="options" required="false"> <parameter name="options" required="false">

@ -110,6 +110,8 @@ struct ast_cdr {
char linkedid[32]; char linkedid[32];
/*! User field */ /*! User field */
char userfield[AST_MAX_USER_FIELD]; char userfield[AST_MAX_USER_FIELD];
/*! Sequence field */
int sequence;
/*! A linked list for variables */ /*! A linked list for variables */
struct varshead varshead; struct varshead varshead;
@ -142,10 +144,38 @@ int check_cdr_enabled(void);
*/ */
struct ast_cdr *ast_cdr_alloc(void); struct ast_cdr *ast_cdr_alloc(void);
/*!
* \brief Duplicate a record and increment the sequence number.
* \param cdr the record to duplicate
* \retval a malloc'd ast_cdr structure,
* \retval NULL on error (malloc failure)
* \see ast_cdr_dup()
* \see ast_cdr_dup_unique_swap()
*/
struct ast_cdr *ast_cdr_dup_unique(struct ast_cdr *cdr);
/*!
* \brief Duplicate a record and increment the sequence number of the old
* record.
* \param cdr the record to duplicate
* \retval a malloc'd ast_cdr structure,
* \retval NULL on error (malloc failure)
* \note This version increments the original CDR's sequence number rather than
* the duplicate's sequence number. The effect is as if the original CDR's
* sequence number was swapped with the duplicate's sequence number.
*
* \see ast_cdr_dup()
* \see ast_cdr_dup_unique()
*/
struct ast_cdr *ast_cdr_dup_unique_swap(struct ast_cdr *cdr);
/*! /*!
* \brief Duplicate a record * \brief Duplicate a record
* \param cdr the record to duplicate
* \retval a malloc'd ast_cdr structure, * \retval a malloc'd ast_cdr structure,
* \retval NULL on error (malloc failure) * \retval NULL on error (malloc failure)
* \see ast_cdr_dup_unique()
* \see ast_cdr_dup_unique_swap()
*/ */
struct ast_cdr *ast_cdr_dup(struct ast_cdr *cdr); struct ast_cdr *ast_cdr_dup(struct ast_cdr *cdr);

@ -74,6 +74,11 @@ static struct ast_cdr_batch {
struct ast_cdr_batch_item *tail; struct ast_cdr_batch_item *tail;
} *batch = NULL; } *batch = NULL;
static int cdr_sequence = 0;
static int cdr_seq_inc(struct ast_cdr *cdr);
static struct sched_context *sched; static struct sched_context *sched;
static int cdr_sched = -1; static int cdr_sched = -1;
static pthread_t cdr_thread = AST_PTHREADT_NULL; static pthread_t cdr_thread = AST_PTHREADT_NULL;
@ -165,6 +170,26 @@ int ast_cdr_isset_unanswered(void)
return unanswered; return unanswered;
} }
struct ast_cdr *ast_cdr_dup_unique(struct ast_cdr *cdr)
{
struct ast_cdr *newcdr = ast_cdr_dup(cdr);
if (!newcdr)
return NULL;
cdr_seq_inc(newcdr);
return newcdr;
}
struct ast_cdr *ast_cdr_dup_unique_swap(struct ast_cdr *cdr)
{
struct ast_cdr *newcdr = ast_cdr_dup(cdr);
if (!newcdr)
return NULL;
cdr_seq_inc(cdr);
return newcdr;
}
/*! Duplicate a CDR record /*! Duplicate a CDR record
\returns Pointer to new CDR record \returns Pointer to new CDR record
*/ */
@ -279,6 +304,8 @@ void ast_cdr_getvar(struct ast_cdr *cdr, const char *name, char **ret, char *wor
ast_copy_string(workspace, cdr->linkedid, workspacelen); ast_copy_string(workspace, cdr->linkedid, workspacelen);
else if (!strcasecmp(name, "userfield")) else if (!strcasecmp(name, "userfield"))
ast_copy_string(workspace, cdr->userfield, workspacelen); ast_copy_string(workspace, cdr->userfield, workspacelen);
else if (!strcasecmp(name, "sequence"))
snprintf(workspace, workspacelen, "%d", cdr->sequence);
else if ((varbuf = ast_cdr_getvar_internal(cdr, name, recur))) else if ((varbuf = ast_cdr_getvar_internal(cdr, name, recur)))
ast_copy_string(workspace, varbuf, workspacelen); ast_copy_string(workspace, varbuf, workspacelen);
else else
@ -292,7 +319,7 @@ void ast_cdr_getvar(struct ast_cdr *cdr, const char *name, char **ret, char *wor
static const char * const cdr_readonly_vars[] = { "clid", "src", "dst", "dcontext", "channel", "dstchannel", static const char * const cdr_readonly_vars[] = { "clid", "src", "dst", "dcontext", "channel", "dstchannel",
"lastapp", "lastdata", "start", "answer", "end", "duration", "lastapp", "lastdata", "start", "answer", "end", "duration",
"billsec", "disposition", "amaflags", "accountcode", "uniqueid", "linkedid", "billsec", "disposition", "amaflags", "accountcode", "uniqueid", "linkedid",
"userfield", NULL }; "userfield", "sequence", NULL };
/*! Set a CDR channel variable /*! Set a CDR channel variable
\note You can't set the CDR variables that belong to the actual CDR record, like "billsec". \note You can't set the CDR variables that belong to the actual CDR record, like "billsec".
*/ */
@ -847,6 +874,11 @@ int ast_cdr_setcid(struct ast_cdr *cdr, struct ast_channel *c)
return 0; return 0;
} }
static int cdr_seq_inc(struct ast_cdr *cdr)
{
return (cdr->sequence = ast_atomic_fetchadd_int(&cdr_sequence, +1));
}
int ast_cdr_init(struct ast_cdr *cdr, struct ast_channel *c) int ast_cdr_init(struct ast_cdr *cdr, struct ast_channel *c)
{ {
char *chan; char *chan;
@ -856,6 +888,7 @@ int ast_cdr_init(struct ast_cdr *cdr, struct ast_channel *c)
chan = S_OR(cdr->channel, "<unknown>"); chan = S_OR(cdr->channel, "<unknown>");
ast_copy_string(cdr->channel, c->name, sizeof(cdr->channel)); ast_copy_string(cdr->channel, c->name, sizeof(cdr->channel));
set_one_cid(cdr, c); set_one_cid(cdr, c);
cdr_seq_inc(cdr);
cdr->disposition = (c->_state == AST_STATE_UP) ? AST_CDR_ANSWERED : AST_CDR_NOANSWER; cdr->disposition = (c->_state == AST_STATE_UP) ? AST_CDR_ANSWERED : AST_CDR_NOANSWER;
cdr->amaflags = c->amaflags ? c->amaflags : ast_default_amaflags; cdr->amaflags = c->amaflags ? c->amaflags : ast_default_amaflags;
@ -1116,7 +1149,7 @@ void ast_cdr_reset(struct ast_cdr *cdr, struct ast_flags *_flags)
if (ast_test_flag(&flags, AST_CDR_FLAG_LOCKED) || !ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { if (ast_test_flag(&flags, AST_CDR_FLAG_LOCKED) || !ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
if (ast_test_flag(&flags, AST_CDR_FLAG_POSTED)) { if (ast_test_flag(&flags, AST_CDR_FLAG_POSTED)) {
ast_cdr_end(cdr); ast_cdr_end(cdr);
if ((duplicate = ast_cdr_dup(cdr))) { if ((duplicate = ast_cdr_dup_unique_swap(cdr))) {
ast_cdr_detach(duplicate); ast_cdr_detach(duplicate);
} }
ast_set_flag(cdr, AST_CDR_FLAG_POSTED); ast_set_flag(cdr, AST_CDR_FLAG_POSTED);

@ -2804,7 +2804,7 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast
if (chan_cdr) { if (chan_cdr) {
ast_set_flag(chan_cdr, AST_CDR_FLAG_MAIN); ast_set_flag(chan_cdr, AST_CDR_FLAG_MAIN);
ast_cdr_update(chan); ast_cdr_update(chan);
bridge_cdr = ast_cdr_dup(chan_cdr); bridge_cdr = ast_cdr_dup_unique_swap(chan_cdr);
ast_copy_string(bridge_cdr->lastapp, S_OR(chan->appl, ""), sizeof(bridge_cdr->lastapp)); ast_copy_string(bridge_cdr->lastapp, S_OR(chan->appl, ""), sizeof(bridge_cdr->lastapp));
ast_copy_string(bridge_cdr->lastdata, S_OR(chan->data, ""), sizeof(bridge_cdr->lastdata)); ast_copy_string(bridge_cdr->lastdata, S_OR(chan->data, ""), sizeof(bridge_cdr->lastdata));
} else { } else {

Loading…
Cancel
Save