From 7ed425ec808f26cc02068c81b4b0f28801100b9f Mon Sep 17 00:00:00 2001 From: Matthew Nicholson <mnicholson@digium.com> Date: Tue, 3 Nov 2009 21:21:09 +0000 Subject: [PATCH] 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 --- CHANGES | 2 ++ apps/app_forkcdr.c | 2 +- configs/cdr_custom.conf.sample | 2 +- funcs/func_cdr.c | 3 +++ include/asterisk/cdr.h | 30 +++++++++++++++++++++++++++ main/cdr.c | 37 ++++++++++++++++++++++++++++++++-- main/features.c | 2 +- 7 files changed, 73 insertions(+), 5 deletions(-) diff --git a/CHANGES b/CHANGES index cbc1b03cd2..37144e0513 100644 --- a/CHANGES +++ b/CHANGES @@ -277,6 +277,8 @@ CDR * 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. 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 ------------------------ diff --git a/apps/app_forkcdr.c b/apps/app_forkcdr.c index 4bacbef78c..12d5049140 100644 --- a/apps/app_forkcdr.c +++ b/apps/app_forkcdr.c @@ -184,7 +184,7 @@ static void ast_cdr_fork(struct ast_channel *chan, struct ast_flags optflags, ch while (cdr->next) cdr = cdr->next; - if (!(newcdr = ast_cdr_dup(cdr))) + if (!(newcdr = ast_cdr_dup_unique(cdr))) return; ast_cdr_append(cdr, newcdr); diff --git a/configs/cdr_custom.conf.sample b/configs/cdr_custom.conf.sample index 4a533a462b..ce3248b5dc 100644 --- a/configs/cdr_custom.conf.sample +++ b/configs/cdr_custom.conf.sample @@ -7,6 +7,6 @@ ; Master.csv, Simple.csv, or both. ; ;[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)})} diff --git a/funcs/func_cdr.c b/funcs/func_cdr.c index e7f14af2a9..d8a3283fc9 100644 --- a/funcs/func_cdr.c +++ b/funcs/func_cdr.c @@ -99,6 +99,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") <enum name="channel"> <para>Channel name.</para> </enum> + <enum name="sequence"> + <para>CDR sequence number.</param> + </enum> </enumlist> </parameter> <parameter name="options" required="false"> diff --git a/include/asterisk/cdr.h b/include/asterisk/cdr.h index 9ac0e11477..23c63ea503 100644 --- a/include/asterisk/cdr.h +++ b/include/asterisk/cdr.h @@ -110,6 +110,8 @@ struct ast_cdr { char linkedid[32]; /*! User field */ char userfield[AST_MAX_USER_FIELD]; + /*! Sequence field */ + int sequence; /*! A linked list for variables */ struct varshead varshead; @@ -142,10 +144,38 @@ int check_cdr_enabled(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 + * \param cdr the record to duplicate * \retval a malloc'd ast_cdr structure, * \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); diff --git a/main/cdr.c b/main/cdr.c index 69d4a8fe15..9168978a41 100644 --- a/main/cdr.c +++ b/main/cdr.c @@ -74,6 +74,11 @@ static struct ast_cdr_batch { struct ast_cdr_batch_item *tail; } *batch = NULL; + +static int cdr_sequence = 0; + +static int cdr_seq_inc(struct ast_cdr *cdr); + static struct sched_context *sched; static int cdr_sched = -1; static pthread_t cdr_thread = AST_PTHREADT_NULL; @@ -165,6 +170,26 @@ int ast_cdr_isset_unanswered(void) 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 \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); else if (!strcasecmp(name, "userfield")) 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))) ast_copy_string(workspace, varbuf, workspacelen); 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", "lastapp", "lastdata", "start", "answer", "end", "duration", "billsec", "disposition", "amaflags", "accountcode", "uniqueid", "linkedid", - "userfield", NULL }; + "userfield", "sequence", NULL }; /*! Set a CDR channel variable \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; } +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) { char *chan; @@ -856,6 +888,7 @@ int ast_cdr_init(struct ast_cdr *cdr, struct ast_channel *c) chan = S_OR(cdr->channel, "<unknown>"); ast_copy_string(cdr->channel, c->name, sizeof(cdr->channel)); set_one_cid(cdr, c); + cdr_seq_inc(cdr); cdr->disposition = (c->_state == AST_STATE_UP) ? AST_CDR_ANSWERED : AST_CDR_NOANSWER; 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_POSTED)) { ast_cdr_end(cdr); - if ((duplicate = ast_cdr_dup(cdr))) { + if ((duplicate = ast_cdr_dup_unique_swap(cdr))) { ast_cdr_detach(duplicate); } ast_set_flag(cdr, AST_CDR_FLAG_POSTED); diff --git a/main/features.c b/main/features.c index 132281c5b0..cfce3f1d7e 100644 --- a/main/features.c +++ b/main/features.c @@ -2804,7 +2804,7 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast if (chan_cdr) { ast_set_flag(chan_cdr, AST_CDR_FLAG_MAIN); 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->lastdata, S_OR(chan->data, ""), sizeof(bridge_cdr->lastdata)); } else { -- GitLab