From 004885c2fa1225cb9833694183cc5fada0e0e89c Mon Sep 17 00:00:00 2001
From: Russell Bryant <russell@russellbryant.com>
Date: Fri, 19 May 2006 22:51:44 +0000
Subject: [PATCH] Make the new behavior where the timestamp is checked on the
 call file before deleting it optional, defaulting to the old behavior, where
 it is always deleted (issue #6750, jcollie)

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@28832 65c4cc65-6c06-0410-ace0-fbb531ad65f3
---
 pbx/pbx_spool.c | 35 +++++++++++++++++++++++++++++------
 sample.call     | 11 +++++++++++
 2 files changed, 40 insertions(+), 6 deletions(-)

diff --git a/pbx/pbx_spool.c b/pbx/pbx_spool.c
index 855001c153..3bab6c1f57 100644
--- a/pbx/pbx_spool.c
+++ b/pbx/pbx_spool.c
@@ -53,6 +53,14 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  * The spool file contains a header 
  */
 
+enum {
+	/*! Always delete the call file after a call succeeds or the
+	 * maximum number of retries is exceeded, even if the
+	 * modification time of the call file is in the future.
+	 */
+	SPOOL_FLAG_ALWAYS_DELETE = (1 << 0)
+};
+
 static char qdir[255];
 
 struct outgoing {
@@ -93,6 +101,9 @@ struct outgoing {
 	
 	/* Maximum length of call */
 	int maxlen;
+
+	/* options */
+	struct ast_flags options;
 };
 
 static void init_outgoing(struct outgoing *o)
@@ -101,6 +112,7 @@ static void init_outgoing(struct outgoing *o)
 	o->priority = 1;
 	o->retrytime = 300;
 	o->waittime = 45;
+	ast_set_flag(&o->options, SPOOL_FLAG_ALWAYS_DELETE);
 }
 
 static void free_outgoing(struct outgoing *o)
@@ -214,6 +226,8 @@ static int apply_outgoing(struct outgoing *o, char *fn, FILE *f)
 						ast_log(LOG_WARNING, "Malformed \"%s\" argument.  Should be \"%s: variable=value\"\n", buf, buf);
 				} else if (!strcasecmp(buf, "account")) {
 					ast_copy_string(o->account, c, sizeof(o->account));
+				} else if (!strcasecmp(buf, "alwaysdelete")) {
+					ast_set2_flag(&o->options, ast_true(c), SPOOL_FLAG_ALWAYS_DELETE);
 				} else {
 					ast_log(LOG_WARNING, "Unknown keyword '%s' at line %d of %s\n", buf, lineno, fn);
 				}
@@ -250,11 +264,23 @@ static void safe_append(struct outgoing *o, time_t now, char *s)
 	}
 }
 
+static void check_unlink(struct outgoing *o)
+{
+	if (ast_test_flag(&o->options, SPOOL_FLAG_ALWAYS_DELETE))
+		unlink(o->fn);
+	else {
+		struct stat current_file_status;
+	
+		if (!stat(o->fn, &current_file_status))
+			if (time(NULL) >= current_file_status.st_mtime)
+				unlink(o->fn);
+	}
+}
+
 static void *attempt_thread(void *data)
 {
 	struct outgoing *o = data;
 	int res, reason;
-	struct stat current_file_status;
 	if (!ast_strlen_zero(o->app)) {
 		if (option_verbose > 2)
 			ast_verbose(VERBOSE_PREFIX_3 "Attempting call on %s/%s for application %s(%s) (Retry %d)\n", o->tech, o->dest, o->app, o->data, o->retries);
@@ -269,7 +295,7 @@ static void *attempt_thread(void *data)
 		if (o->retries >= o->maxretries + 1) {
 			/* Max retries exceeded */
 			ast_log(LOG_EVENT, "Queued call to %s/%s expired without completion after %d attempt%s\n", o->tech, o->dest, o->retries - 1, ((o->retries - 1) != 1) ? "s" : "");
-			unlink(o->fn);
+			check_unlink(o);
 		} else {
 			/* Notate that the call is still active */
 			safe_append(o, time(NULL), "EndRetry");
@@ -277,10 +303,7 @@ static void *attempt_thread(void *data)
 	} else {
 		ast_log(LOG_NOTICE, "Call completed to %s/%s\n", o->tech, o->dest);
 		ast_log(LOG_EVENT, "Queued call to %s/%s completed\n", o->tech, o->dest);
-		if (!stat(o->fn, &current_file_status)) {
-			if (time(NULL) >= current_file_status.st_atime)
-				unlink(o->fn);
-		}
+		check_unlink(o);
 	}
 	free_outgoing(o);
 	return NULL;
diff --git a/sample.call b/sample.call
index 464af406d2..b0a13e7f9d 100644
--- a/sample.call
+++ b/sample.call
@@ -49,6 +49,17 @@ Priority: 1
 #
 #Account: mysuperfunaccountcode
 
+#
+# Normally, a call file is always deleted after the call is successful
+# or the maximum number of tries is reached even if the modification
+# time of the call file was changed during the call to be in the
+# future.  By Setting AlwaysDelete to No the modification time of the
+# call file will be checked after the call is completed or the maximum
+# number of retries is reached.  If the modification time is in the
+# future, the call file will not be deleted.
+#
+#AlwaysDelete: Yes
+
 #
 # You can set channel variables that will be passed to the channel.
 # This includes writable dialplan functions. To set a writable dialplan
-- 
GitLab