[asterisk-commits] murf: branch 1.4 r118858 - in /branches/1.4: apps/app_forkcdr.c main/cdr.c

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed May 28 19:25:28 CDT 2008


Author: murf
Date: Wed May 28 19:25:28 2008
New Revision: 118858

URL: http://svn.digium.com/view/asterisk?view=rev&rev=118858
Log:
(closes issue #10668)
(closes issue #11721)
(closes issue #12726)
Reported by: arkadia
Tested by: murf

These changes:

1. revert the changes made via bug 10668; 
   I should have known that such changes,
   even tho they made sense at the time,
   seemed like an omission, etc, were actually
   integral to the CDR system via forkCDR.
   It makes sense to me now that forkCDR didn't
   natively end any CDR's, but rather depended
   on natively closing them all at hangup time
   via traversing and closing them all, whether
   locked or not. I still don't completely 
   understand the benefits of setvar and answer
   operating on locked cdrs, but I've seen 
   enough to revert those changes also, and
   stop messing up users who depended on that
   behavior. bug 12726 found reverting the changes
   fixed his changes, and after a long review
   and working on forkCDR, I can see why.
2. Apply the suggested enhancements proposed
   in 10668, but in a completely compatible
   way. ForkCDR will behave exactly as before,
   but now has new options that will allow some
   actions to be taken that will slightly 
   modify the outcome and side-effects of
   forkCDR. Based on conversations I've had 
   with various people, these small tweaks
   will allow some users to get the behavior
   they need. For instance, users executing
   forkCDR in an AGI script will find the
   answer time set, and DISPOSITION set, 
   a situation not covered when the routines
  were first written.
3. A small problem in the cdr serializer
   would output answer and end times even
   when they were not set. This is now 
   fixed.



Modified:
    branches/1.4/apps/app_forkcdr.c
    branches/1.4/main/cdr.c

Modified: branches/1.4/apps/app_forkcdr.c
URL: http://svn.digium.com/view/asterisk/branches/1.4/apps/app_forkcdr.c?view=diff&rev=118858&r1=118857&r2=118858
==============================================================================
--- branches/1.4/apps/app_forkcdr.c (original)
+++ branches/1.4/apps/app_forkcdr.c Wed May 28 19:25:28 2008
@@ -40,6 +40,7 @@
 #include "asterisk/channel.h"
 #include "asterisk/pbx.h"
 #include "asterisk/cdr.h"
+#include "asterisk/app.h"
 #include "asterisk/module.h"
 
 static char *app = "ForkCDR";
@@ -47,11 +48,53 @@
 "Forks the Call Data Record";
 static char *descrip = 
 "  ForkCDR([options]):  Causes the Call Data Record to fork an additional\n"
-	"cdr record starting from the time of the fork call\n"
-"If the option 'v' is passed all cdr variables will be passed along also.\n";
+"cdr record starting from the time of the fork call\n"
+"  Options:\n"
+"    a  - update the answer time on the NEW CDR just after it's been inited..\n"
+"         The new CDR may have been answered already, the reset that forkcdr.\n"
+"         does will erase the answer time. This will bring it back, but.\n"
+"         the answer time will be a copy of the fork/start time. It will.\n"
+"         only do this if the initial cdr was indeed already answered..\n"
+"    D -  Copy the disposition forward from the old cdr, after the .\n"
+"         init..\n"
+"    d -  Clear the dstchannel on the new CDR after reset..\n"
+"    e -  end the original CDR. Do this after all the necc. data.\n"
+"         is copied from the original CDR to the new forked CDR..\n"
+"    R -  do NOT reset the new cdr..\n"
+"    s(name=val) - Set the CDR var 'name' in the original CDR, with value.\n"
+"                  'val'.\n"
+"    v  - When the new CDR is forked, it gets a copy of the vars attached\n"
+"         to the current CDR. The vars attached to the original CDR are removed\n"
+"         unless this option is specified.\n";
 
 
-static void ast_cdr_fork(struct ast_channel *chan) 
+enum {
+	OPT_SETANS =            (1 << 0),
+	OPT_SETDISP =           (1 << 1),
+	OPT_RESETDEST =         (1 << 2),
+	OPT_ENDCDR =            (1 << 3),
+	OPT_NORESET =           (1 << 4),
+	OPT_KEEPVARS =          (1 << 5),
+	OPT_VARSET =            (1 << 6),
+};
+
+enum {
+	OPT_ARG_VARSET = 0,
+	/* note: this entry _MUST_ be the last one in the enum */
+	OPT_ARG_ARRAY_SIZE,
+};
+
+AST_APP_OPTIONS(forkcdr_exec_options, {
+	AST_APP_OPTION('a', OPT_SETANS),
+	AST_APP_OPTION('d', OPT_SETDISP),
+	AST_APP_OPTION('D', OPT_RESETDEST),
+	AST_APP_OPTION('e', OPT_ENDCDR),
+	AST_APP_OPTION('R', OPT_NORESET),
+	AST_APP_OPTION_ARG('s', OPT_VARSET, OPT_ARG_VARSET),
+	AST_APP_OPTION('v', OPT_KEEPVARS),
+});
+
+static void ast_cdr_fork(struct ast_channel *chan, struct ast_flags optflags, char *set) 
 {
 	struct ast_cdr *cdr;
 	struct ast_cdr *newcdr;
@@ -66,11 +109,35 @@
 		return;
 	
 	ast_cdr_append(cdr, newcdr);
-	ast_cdr_reset(newcdr, &flags);
-	
+
+	if (!ast_test_flag(&optflags, OPT_NORESET))
+		ast_cdr_reset(newcdr, &flags);
+		
 	if (!ast_test_flag(cdr, AST_CDR_FLAG_KEEP_VARS))
 		ast_cdr_free_vars(cdr, 0);
 	
+	if (!ast_strlen_zero(set)) {
+		char *varname = ast_strdupa(set), *varval;
+		varval = strchr(varname,'=');
+		if (varval) {
+			*varval = 0;
+			varval++;
+			ast_cdr_setvar(cdr, varname, varval, 0);
+		}
+	}
+	
+	if (ast_test_flag(&optflags, OPT_SETANS) && !ast_tvzero(cdr->answer))
+		newcdr->answer = newcdr->start;
+
+	if (ast_test_flag(&optflags, OPT_SETDISP))
+		newcdr->disposition = cdr->disposition;
+	
+	if (ast_test_flag(&optflags, OPT_RESETDEST))
+		newcdr->dstchannel[0] = 0;
+	
+	if (ast_test_flag(&optflags, OPT_ENDCDR))
+		ast_cdr_end(cdr);
+
 	ast_set_flag(cdr, AST_CDR_FLAG_CHILD | AST_CDR_FLAG_LOCKED);
 }
 
@@ -78,6 +145,12 @@
 {
 	int res = 0;
 	struct ast_module_user *u;
+	char *argcopy = NULL;
+	struct ast_flags flags = {0};
+	char *opts[OPT_ARG_ARRAY_SIZE];
+	AST_DECLARE_APP_ARGS(arglist,
+		AST_APP_ARG(options);
+	);
 
 	if (!chan->cdr) {
 		ast_log(LOG_WARNING, "Channel does not have a CDR\n");
@@ -86,10 +159,19 @@
 
 	u = ast_module_user_add(chan);
 
+	argcopy = ast_strdupa(data);
+
+	AST_STANDARD_APP_ARGS(arglist, argcopy);
+
+	if (!ast_strlen_zero(arglist.options)) {
+		ast_app_parse_options(forkcdr_exec_options, &flags, opts, arglist.options);
+	} else
+		opts[OPT_ARG_VARSET] = 0;
+	
 	if (!ast_strlen_zero(data))
-		ast_set2_flag(chan->cdr, strchr(data, 'v'), AST_CDR_FLAG_KEEP_VARS);
+		ast_set2_flag(chan->cdr, ast_test_flag(&flags, OPT_KEEPVARS), AST_CDR_FLAG_KEEP_VARS);
 	
-	ast_cdr_fork(chan);
+	ast_cdr_fork(chan, flags, opts[OPT_ARG_VARSET]);
 
 	ast_module_user_remove(u);
 	return res;

Modified: branches/1.4/main/cdr.c
URL: http://svn.digium.com/view/asterisk/branches/1.4/main/cdr.c?view=diff&rev=118858&r1=118857&r2=118858
==============================================================================
--- branches/1.4/main/cdr.c (original)
+++ branches/1.4/main/cdr.c Wed May 28 19:25:28 2008
@@ -312,22 +312,20 @@
 	}
 
 	for (; cdr; cdr = recur ? cdr->next : NULL) {
-		if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
-			headp = &cdr->varshead;
-			AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) {
-				if (!strcasecmp(ast_var_name(newvariable), name)) {
-					/* there is already such a variable, delete it */
-					AST_LIST_REMOVE_CURRENT(headp, entries);
-					ast_var_delete(newvariable);
-					break;
-				}
+		headp = &cdr->varshead;
+		AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) {
+			if (!strcasecmp(ast_var_name(newvariable), name)) {
+				/* there is already such a variable, delete it */
+				AST_LIST_REMOVE_CURRENT(headp, entries);
+				ast_var_delete(newvariable);
+				break;
 			}
-			AST_LIST_TRAVERSE_SAFE_END;
-
-			if (value) {
-				newvariable = ast_var_assign(name, value);
-				AST_LIST_INSERT_HEAD(headp, newvariable, entries);
-			}
+		}
+		AST_LIST_TRAVERSE_SAFE_END;
+		
+		if (value) {
+			newvariable = ast_var_assign(name, value);
+			AST_LIST_INSERT_HEAD(headp, newvariable, entries);
 		}
 	}
 
@@ -388,6 +386,7 @@
 		}
 
 		for (i = 0; cdr_readonly_vars[i]; i++) {
+			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 */
 			ast_cdr_getvar(cdr, cdr_readonly_vars[i], &tmp, workspace, sizeof(workspace), 0, 0);
 			if (!tmp)
 				continue;
@@ -696,13 +695,11 @@
 {
 
 	for (; cdr; cdr = cdr->next) {
-		if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
-			check_post(cdr);
-			if (cdr->disposition < AST_CDR_ANSWERED)
-				cdr->disposition = AST_CDR_ANSWERED;
-			if (ast_tvzero(cdr->answer))
-				cdr->answer = ast_tvnow();
-		}
+		check_post(cdr);
+		if (cdr->disposition < AST_CDR_ANSWERED)
+			cdr->disposition = AST_CDR_ANSWERED;
+		if (ast_tvzero(cdr->answer))
+			cdr->answer = ast_tvnow();
 	}
 }
 
@@ -840,20 +837,30 @@
 	return 0;
 }
 
+/* Three routines were "fixed" via 10668, and later shown that 
+   users were depending on this behavior. ast_cdr_end,
+   ast_cdr_setvar and ast_cdr_answer are the three routines.
+   While most of the other routines would not touch 
+   LOCKED cdr's, these three routines were designed to
+   operate on locked CDR's as a matter of course.
+   I now appreciate how this plays with the ForkCDR app,
+   which forms these cdr chains in the first place. 
+   cdr_end is pretty key: all cdrs created are closed
+   together. They only vary by start time. Arithmetically,
+   users can calculate the subintervals they wish to track. */
+
 void ast_cdr_end(struct ast_cdr *cdr)
 {
 	for ( ; cdr ; cdr = cdr->next) {
-		if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
-			check_post(cdr);
-			if (ast_tvzero(cdr->end))
-				cdr->end = ast_tvnow();
-			if (ast_tvzero(cdr->start)) {
-				ast_log(LOG_WARNING, "CDR on channel '%s' has not started\n", S_OR(cdr->channel, "<unknown>"));
-				cdr->disposition = AST_CDR_FAILED;
-			} else
-				cdr->duration = cdr->end.tv_sec - cdr->start.tv_sec;
-			cdr->billsec = ast_tvzero(cdr->answer) ? 0 : cdr->end.tv_sec - cdr->answer.tv_sec;
-		}
+		check_post(cdr);
+		if (ast_tvzero(cdr->end))
+			cdr->end = ast_tvnow();
+		if (ast_tvzero(cdr->start)) {
+			ast_log(LOG_WARNING, "CDR on channel '%s' has not started\n", S_OR(cdr->channel, "<unknown>"));
+			cdr->disposition = AST_CDR_FAILED;
+		} else
+			cdr->duration = cdr->end.tv_sec - cdr->start.tv_sec;
+		cdr->billsec = ast_tvzero(cdr->answer) ? 0 : cdr->end.tv_sec - cdr->answer.tv_sec;
 	}
 }
 




More information about the asterisk-commits mailing list