[svn-commits] russell: branch russell/events r82456 - in /team/russell/events: ./ apps/ bui...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Fri Sep 14 16:24:50 CDT 2007


Author: russell
Date: Fri Sep 14 16:24:49 2007
New Revision: 82456

URL: http://svn.digium.com/view/asterisk?view=rev&rev=82456
Log:
resolve conflict, set automerge

Added:
    team/russell/events/channels/chan_usbradio.c
      - copied unchanged from r82454, trunk/channels/chan_usbradio.c
    team/russell/events/channels/xpmr/
      - copied from r82454, trunk/channels/xpmr/
    team/russell/events/channels/xpmr/sinetabx.h
      - copied unchanged from r82454, trunk/channels/xpmr/sinetabx.h
    team/russell/events/channels/xpmr/xpmr.c
      - copied unchanged from r82454, trunk/channels/xpmr/xpmr.c
    team/russell/events/channels/xpmr/xpmr.h
      - copied unchanged from r82454, trunk/channels/xpmr/xpmr.h
    team/russell/events/channels/xpmr/xpmr_coef.h
      - copied unchanged from r82454, trunk/channels/xpmr/xpmr_coef.h
Modified:
    team/russell/events/   (props changed)
    team/russell/events/CHANGES
    team/russell/events/LICENSE
    team/russell/events/apps/app_meetme.c
    team/russell/events/apps/app_queue.c
    team/russell/events/apps/app_sms.c
    team/russell/events/build_tools/menuselect-deps.in
    team/russell/events/cdr/cdr_csv.c
    team/russell/events/channels/chan_gtalk.c
    team/russell/events/channels/chan_iax2.c
    team/russell/events/channels/chan_jingle.c
    team/russell/events/channels/chan_misdn.c
    team/russell/events/channels/chan_sip.c
    team/russell/events/channels/chan_skinny.c
    team/russell/events/channels/chan_zap.c
    team/russell/events/channels/misdn/isdn_lib.c
    team/russell/events/codecs/gsm/src/long_term.c
    team/russell/events/codecs/gsm/src/lpc.c
    team/russell/events/configs/res_config_sqlite.conf
    team/russell/events/configs/sip.conf.sample
    team/russell/events/configs/skinny.conf.sample
    team/russell/events/configs/zapata.conf.sample
    team/russell/events/configure
    team/russell/events/configure.ac
    team/russell/events/doc/CODING-GUIDELINES
    team/russell/events/doc/res_config_sqlite.txt
    team/russell/events/funcs/func_strings.c
    team/russell/events/include/asterisk.h
    team/russell/events/include/asterisk/autoconfig.h.in
    team/russell/events/include/asterisk/doxyref.h
    team/russell/events/include/asterisk/jingle.h
    team/russell/events/include/asterisk/localtime.h
    team/russell/events/include/asterisk/res_odbc.h
    team/russell/events/main/app.c
    team/russell/events/main/asterisk.c
    team/russell/events/main/astobj2.c
    team/russell/events/main/cdr.c
    team/russell/events/main/config.c
    team/russell/events/main/manager.c
    team/russell/events/main/minimime/minimime.c
    team/russell/events/main/minimime/mm_mem.c
    team/russell/events/main/minimime/tests/create.c
    team/russell/events/main/minimime/tests/parse.c
    team/russell/events/main/pbx.c
    team/russell/events/main/stdtime/localtime.c
    team/russell/events/main/stdtime/tzfile.h
    team/russell/events/makeopts.in
    team/russell/events/pbx/pbx_dundi.c
    team/russell/events/pbx/pbx_spool.c
    team/russell/events/res/res_agi.c
    team/russell/events/res/res_config_sqlite.c
    team/russell/events/res/res_odbc.c
    team/russell/events/utils/Makefile
    team/russell/events/utils/hashtest2.c

Propchange: team/russell/events/
------------------------------------------------------------------------------
    automerge = *

Propchange: team/russell/events/
------------------------------------------------------------------------------
Binary property 'branch-1.4-blocked' - no diff available.

Propchange: team/russell/events/
------------------------------------------------------------------------------
Binary property 'branch-1.4-merged' - no diff available.

Propchange: team/russell/events/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Fri Sep 14 16:24:49 2007
@@ -1,1 +1,1 @@
-/trunk:1-82223
+/trunk:1-82454

Modified: team/russell/events/CHANGES
URL: http://svn.digium.com/view/asterisk/team/russell/events/CHANGES?view=diff&rev=82456&r1=82455&r2=82456
==============================================================================
--- team/russell/events/CHANGES (original)
+++ team/russell/events/CHANGES Fri Sep 14 16:24:49 2007
@@ -1,4 +1,4 @@
--------------------------------------------------------------------------------
+------------------------------------------------------------------------------
 --- Functionality changes since Asterisk 1.4-beta was branched ----------------
 -------------------------------------------------------------------------------
 
@@ -50,6 +50,7 @@
   * New CLI command "core show settings"
   * Added 'core show channels count' CLI command.
   * Added the ability to set the core debug and verbose values on a per-file basis.
+  * Added 'queue pause member' and 'queue unpause member' CLI commands
 
 SIP changes
 -----------
@@ -81,7 +82,10 @@
   * Added rtpdest option to CHANNEL() dialplan function.
   * Added SIPREFERRINGCONTEXT and SIPREFERREDBYHDR variables which are set when a transfer takes place.
   * SIP now adds a header to the CANCEL if the call was answered by another phone
-    in the same dial command, or if the new c option in dial() is used.
+     in the same dial command, or if the new c option in dial() is used.
+  * The new default is that 100 Trying is not sent on REGISTER attempts as the RFC specifically
+     states it is not needed. For phones, however, that do require it the registertrying option
+     has been added so it can be enabled. 
 
 IAX2 changes
 ------------
@@ -217,6 +221,7 @@
     those carriers that transmit CID via dtmf after a polarity change.
   * CID matching information is now shown when doing 'dialplan show'.
   * Added zap show version CLI command to chan_zap.
+  * Added setvar support to zapata.conf channel entries.
 
 H.323 Changes
 -------------

Modified: team/russell/events/LICENSE
URL: http://svn.digium.com/view/asterisk/team/russell/events/LICENSE?view=diff&rev=82456&r1=82455&r2=82456
==============================================================================
--- team/russell/events/LICENSE (original)
+++ team/russell/events/LICENSE Fri Sep 14 16:24:49 2007
@@ -32,7 +32,7 @@
 would strongly encourage you to make the same exception that we do).
 
 Specific permission is also granted to link Asterisk with OpenSSL and
-OpenH323.
+OpenH323 and distribute the resulting binary files.
 
 In addition, Asterisk implements two management/control protocols: the
 Asterisk Manager Interface (AMI) and the Asterisk Gateway Interface

Modified: team/russell/events/apps/app_meetme.c
URL: http://svn.digium.com/view/asterisk/team/russell/events/apps/app_meetme.c?view=diff&rev=82456&r1=82455&r2=82456
==============================================================================
--- team/russell/events/apps/app_meetme.c (original)
+++ team/russell/events/apps/app_meetme.c Fri Sep 14 16:24:49 2007
@@ -343,6 +343,8 @@
 	unsigned int isdynamic:1;               /*!< Created on the fly? */
 	unsigned int locked:1;                  /*!< Is the conference locked? */
 	pthread_t recordthread;                 /*!< thread for recording */
+	ast_mutex_t recordthreadlock;		/*!< control threads trying to start recordthread */
+	pthread_attr_t attr;                    /*!< thread attribute */
 	const char *recordingfilename;          /*!< Filename to record the Conference into */
 	const char *recordingformat;            /*!< Format to record the Conference in */
 	char pin[MAX_PIN];                      /*!< If protected by a PIN */
@@ -781,6 +783,8 @@
 
 	ast_mutex_init(&cnf->playlock);
 	ast_mutex_init(&cnf->listenlock);
+	cnf->recordthread = AST_PTHREADT_NULL;
+	ast_mutex_init(&cnf->recordthreadlock);
 	ast_copy_string(cnf->confno, confno, sizeof(cnf->confno));
 	ast_copy_string(cnf->pin, pin, sizeof(cnf->pin));
 	ast_copy_string(cnf->pinadmin, pinadmin, sizeof(cnf->pinadmin));
@@ -849,8 +853,8 @@
 	int hr, min, sec;
 	int i = 0, total = 0;
 	time_t now;
-	char *header_format = "%-14s %-14s %-10s %-8s  %-8s\n";
-	char *data_format = "%-12.12s   %4.4d	      %4.4s       %02d:%02d:%02d  %-8s\n";
+	char *header_format = "%-14s %-14s %-10s %-8s  %-8s  %-6s\n";
+	char *data_format = "%-12.12s   %4.4d	      %4.4s       %02d:%02d:%02d  %-8s  %-6s\n";
 	char cmdline[1024] = "";
 
 	if (argc > 8)
@@ -869,7 +873,7 @@
 			AST_LIST_UNLOCK(&confs);
 			return RESULT_SUCCESS;
 		}
-		ast_cli(fd, header_format, "Conf Num", "Parties", "Marked", "Activity", "Creation");
+		ast_cli(fd, header_format, "Conf Num", "Parties", "Marked", "Activity", "Creation", "Locked");
 		AST_LIST_TRAVERSE(&confs, cnf, list) {
 			if (cnf->markedusers == 0)
 				strcpy(cmdline, "N/A ");
@@ -879,7 +883,7 @@
 			min = ((now - cnf->start) % 3600) / 60;
 			sec = (now - cnf->start) % 60;
 
-			ast_cli(fd, data_format, cnf->confno, cnf->users, cmdline, hr, min, sec, cnf->isdynamic ? "Dynamic" : "Static");
+			ast_cli(fd, data_format, cnf->confno, cnf->users, cmdline, hr, min, sec, cnf->isdynamic ? "Dynamic" : "Static", cnf->locked ? "Yes" : "No");
 
 			total += cnf->users; 	
 		}
@@ -1281,7 +1285,10 @@
 		ast_hangup(conf->chan);
 	else
 		close(conf->fd);
-	
+
+	ast_mutex_destroy(&conf->playlock);
+	ast_mutex_destroy(&conf->listenlock);
+	ast_mutex_destroy(&conf->recordthreadlock);
 	ast_free(conf);
 
 	return 0;
@@ -1466,7 +1473,8 @@
 		}
 	}
 
-	if ((conf->recording == MEETME_RECORD_OFF) && (confflags & CONFFLAG_RECORDCONF) && ((conf->lchan = ast_request("zap", AST_FORMAT_SLINEAR, "pseudo", NULL)))) {
+	ast_mutex_lock(&conf->recordthreadlock);
+	if ((conf->recordthread == AST_PTHREADT_NULL) && (confflags & CONFFLAG_RECORDCONF) && ((conf->lchan = ast_request("zap", AST_FORMAT_SLINEAR, "pseudo", NULL)))) {
 		ast_set_read_format(conf->lchan, AST_FORMAT_SLINEAR);
 		ast_set_write_format(conf->lchan, AST_FORMAT_SLINEAR);
 		ztc.chan = 0;
@@ -1480,6 +1488,7 @@
 			ast_pthread_create_detached_background(&conf->recordthread, NULL, recordthread, conf);
 		}
 	}
+	ast_mutex_unlock(&conf->recordthreadlock);
 
 	time(&user->jointime);
 

Modified: team/russell/events/apps/app_queue.c
URL: http://svn.digium.com/view/asterisk/team/russell/events/apps/app_queue.c?view=diff&rev=82456&r1=82455&r2=82456
==============================================================================
--- team/russell/events/apps/app_queue.c (original)
+++ team/russell/events/apps/app_queue.c Fri Sep 14 16:24:49 2007
@@ -368,6 +368,7 @@
 	unsigned int strategy:3;
 	unsigned int maskmemberstatus:1;
 	unsigned int realtime:1;
+	unsigned int found:1;
 	int announcefrequency;              /*!< How often to announce their position */
 	int minannouncefrequency;           /*!< The minimum number of seconds between position announcements (def. 15) */
 	int periodicannouncefrequency;      /*!< How often to play periodic announcement */
@@ -408,7 +409,12 @@
 	int autofill;                       /*!< Ignore the head call status and ring an available agent */
 	
 	struct ao2_container *members;             /*!< Head of the list of members */
-	int membercount;					/*!< Number of members in queue */
+	/*! 
+	 * \brief Number of members _logged in_
+	 * \note There will be members in the members container that are not logged
+	 *       in, so this can not simply be replaced with ao2_container_count(). 
+	 */
+	int membercount;
 	struct queue_ent *head;             /*!< Head of the list of callers */
 	AST_LIST_ENTRY(call_queue) list;    /*!< Next call queue */
 };
@@ -504,26 +510,22 @@
 static enum queue_member_status get_member_status(struct call_queue *q, int max_penalty)
 {
 	struct member *member;
-	struct ao2_iterator i;
+	struct ao2_iterator mem_iter;
 	enum queue_member_status result = QUEUE_NO_MEMBERS;
 
 	ast_mutex_lock(&q->lock);
-	i = ao2_iterator_init(q->members, 0);
-	while ((member = ao2_iterator_next(&i))) {
-		if (max_penalty && (member->penalty > max_penalty)) {
-			ao2_ref(member, -1);
+	mem_iter = ao2_iterator_init(q->members, 0);
+	for (; (member = ao2_iterator_next(&mem_iter)); ao2_ref(member, -1)) {
+		if (max_penalty && (member->penalty > max_penalty))
 			continue;
-		}
 
 		switch (member->status) {
 		case AST_DEVICE_INVALID:
 			/* nothing to do */
-			ao2_ref(member, -1);
 			break;
 		case AST_DEVICE_UNAVAILABLE:
 			if (result != QUEUE_NO_UNPAUSED_REACHABLE_MEMBERS) 
 				result = QUEUE_NO_REACHABLE_MEMBERS;
-			ao2_ref(member, -1);
 			break;
 		default:
 			if (member->paused) {
@@ -537,7 +539,6 @@
 		}
 	}
 
-	ao2_ref(member, -1);
 	ast_mutex_unlock(&q->lock);
 	return result;
 }
@@ -552,7 +553,7 @@
 {
 	struct call_queue *q;
 	struct member *cur;
-	struct ao2_iterator i;
+	struct ao2_iterator mem_iter;
 	struct member_interface *curint;
 	char *loc;
 	char *technology;
@@ -588,8 +589,8 @@
 	AST_LIST_LOCK(&queues);
 	AST_LIST_TRAVERSE(&queues, q, list) {
 		ast_mutex_lock(&q->lock);
-		i = ao2_iterator_init(q->members, 0);
-		while ((cur = ao2_iterator_next(&i))) {
+		mem_iter = ao2_iterator_init(q->members, 0);
+		while ((cur = ao2_iterator_next(&mem_iter))) {
 			char *interface;
 			char *slash_pos;
 			interface = ast_strdupa(cur->interface);
@@ -795,6 +796,7 @@
 	q->sound_callerannounce[0] = '\0';	/* Default, don't announce the caller that he has been answered */
 	q->members = ao2_container_alloc(37, member_hash_fn, member_cmp_fn);
 	q->membercount = 0;
+	q->found = 1;
 	ast_copy_string(q->sound_next, "queue-youarenext", sizeof(q->sound_next));
 	ast_copy_string(q->sound_thereare, "queue-thereare", sizeof(q->sound_thereare));
 	ast_copy_string(q->sound_calls, "queue-callswaiting", sizeof(q->sound_calls));
@@ -848,13 +850,15 @@
 static int interface_exists_global(const char *interface)
 {
 	struct call_queue *q;
-	struct member *mem;
+	struct member *mem, tmpmem;
 	int ret = 0;
+
+	ast_copy_string(tmpmem.interface, interface, sizeof(tmpmem.interface));
 
 	AST_LIST_LOCK(&queues);
 	AST_LIST_TRAVERSE(&queues, q, list) {
 		ast_mutex_lock(&q->lock);
-		if ((mem = ao2_find(q->members, (char *)interface, 0))) {
+		if ((mem = ao2_find(q->members, &tmpmem, OBJ_POINTER))) {
 			ao2_ref(mem, -1);
 			ret = 1;
 		}
@@ -1073,7 +1077,7 @@
 
 static void rt_handle_member_record(struct call_queue *q, char *interface, const char *membername, const char *penalty_str, const char *paused_str)
 {
-	struct member *m;
+	struct member *m, tmpmem;
 	int penalty = 0;
 	int paused  = 0;
 
@@ -1090,7 +1094,8 @@
 	}
 
 	/* Find the member, or the place to put a new one. */
-	m = ao2_find(q->members, interface, 0);
+	ast_copy_string(tmpmem.interface, interface, sizeof(tmpmem.interface));
+	m = ao2_find(q->members, &tmpmem, OBJ_POINTER);
 
 	/* Create a new one if not found, else update penalty */
 	if (!m) {
@@ -1114,9 +1119,9 @@
 {
 	/* Free non-dynamic members */
 	struct member *cur;
-	struct ao2_iterator i = ao2_iterator_init(q->members, 0);
-
-	while ((cur = ao2_iterator_next(&i))) {
+	struct ao2_iterator mem_iter = ao2_iterator_init(q->members, 0);
+
+	while ((cur = ao2_iterator_next(&mem_iter))) {
 		if (all || !cur->dynamic) {
 			ao2_unlink(q->members, cur);
 			remove_from_interfaces(cur->interface);
@@ -1142,7 +1147,7 @@
 	struct ast_variable *v;
 	struct call_queue *q;
 	struct member *m;
-	struct ao2_iterator i;
+	struct ao2_iterator mem_iter;
 	char *interface = NULL;
 	char *tmp, *tmp_name;
 	char tmpbuf[64];	/* Must be longer than the longest queue param name. */
@@ -1161,6 +1166,7 @@
 				ast_mutex_unlock(&q->lock);
 				return NULL;
 			} else {
+				ast_log(LOG_WARNING, "Static queue '%s' already exists. Not loading from realtime\n", q->name);
 				ast_mutex_unlock(&q->lock);
 				return q;
 			}
@@ -1198,9 +1204,9 @@
 		ast_mutex_lock(&q->lock);
 		clear_queue(q);
 		q->realtime = 1;
+		init_queue(q);		/* Ensure defaults for all parameters not set explicitly. */
 		AST_LIST_INSERT_HEAD(&queues, q, list);
 	}
-	init_queue(q);		/* Ensure defaults for all parameters not set explicitly. */
 
 	memset(tmpbuf, 0, sizeof(tmpbuf));
 	for (v = queue_vars; v; v = v->next) {
@@ -1218,8 +1224,8 @@
 
 	/* Temporarily set realtime members dead so we can detect deleted ones. 
 	 * Also set the membercount correctly for realtime*/
-	i = ao2_iterator_init(q->members, 0);
-	while ((m = ao2_iterator_next(&i))) {
+	mem_iter = ao2_iterator_init(q->members, 0);
+	while ((m = ao2_iterator_next(&mem_iter))) {
 		q->membercount++;
 		if (m->realtime)
 			m->dead = 1;
@@ -1234,8 +1240,8 @@
 	}
 
 	/* Delete all realtime members that have been deleted in DB. */
-	i = ao2_iterator_init(q->members, 0);
-	while ((m = ao2_iterator_next(&i))) {
+	mem_iter = ao2_iterator_init(q->members, 0);
+	while ((m = ao2_iterator_next(&mem_iter))) {
 		if (m->dead) {
 			ao2_unlink(q->members, m);
 			ast_mutex_unlock(&q->lock);
@@ -1324,7 +1330,7 @@
 	struct ast_config *member_config = NULL;
 	struct member *m;
 	char *interface = NULL;
-	struct ao2_iterator i;
+	struct ao2_iterator mem_iter;
 
 	member_config = ast_load_realtime_multientry("queue_members", "interface LIKE", "%", "queue_name", q->name , NULL);
 	if (!member_config) {
@@ -1336,8 +1342,8 @@
 	ast_mutex_lock(&q->lock);
 	
 	/* Temporarily set realtime  members dead so we can detect deleted ones.*/ 
-	i = ao2_iterator_init(q->members, 0);
-	while ((m = ao2_iterator_next(&i))) {
+	mem_iter = ao2_iterator_init(q->members, 0);
+	while ((m = ao2_iterator_next(&mem_iter))) {
 		if (m->realtime)
 			m->dead = 1;
 		ao2_ref(m, -1);
@@ -1351,8 +1357,8 @@
 	}
 
 	/* Delete all realtime members that have been deleted in DB. */
-	i = ao2_iterator_init(q->members, 0);
-	while ((m = ao2_iterator_next(&i))) {
+	mem_iter = ao2_iterator_init(q->members, 0);
+	while ((m = ao2_iterator_next(&mem_iter))) {
 		if (m->dead) {
 			ao2_unlink(q->members, m);
 			ast_mutex_unlock(&q->lock);
@@ -1659,6 +1665,8 @@
 			ast_hangup(outgoing->chan);
 		oo = outgoing;
 		outgoing = outgoing->q_next;
+		if (oo->member)
+			ao2_ref(oo->member, -1);
 		ast_free(oo);
 	}
 }
@@ -1666,13 +1674,13 @@
 static int update_status(struct call_queue *q, struct member *member, int status)
 {
 	struct member *cur;
-	struct ao2_iterator i;
+	struct ao2_iterator mem_iter;
 
 	/* Since a reload could have taken place, we have to traverse the list to
 		be sure it's still valid */
 	ast_mutex_lock(&q->lock);
-	i = ao2_iterator_init(q->members, 0);
-	while ((cur = ao2_iterator_next(&i))) {
+	mem_iter = ao2_iterator_init(q->members, 0);
+	while ((cur = ao2_iterator_next(&mem_iter))) {
 		if (member != cur) {
 			ao2_ref(cur, -1);
 			continue;
@@ -1727,7 +1735,7 @@
 			continue;
 		ast_mutex_lock(&q->lock);
 		if (q->count && q->members) {
-			if ((mem = ao2_find(q->members, member->interface, 0))) {
+			if ((mem = ao2_find(q->members, member, OBJ_POINTER))) {
 				ast_debug(1, "Found matching member %s in queue '%s'\n", mem->interface, q->name);
 				if (q->weight > rq->weight) {
 					ast_debug(1, "Queue '%s' (weight %d, calls %d) is preferred over '%s' (weight %d, calls %d)\n", q->name, q->weight, q->count, rq->name, rq->weight, rq->count);
@@ -1885,6 +1893,7 @@
 		manager_event(EVENT_FLAG_AGENT, "AgentCalled",
 					"Queue: %s\r\n"
 					"AgentCalled: %s\r\n"
+					"AgentName: %s\r\n"
 					"ChannelCalling: %s\r\n"
 					"DestinationChannel: %s\r\n"
 					"CallerIDNum: %s\r\n"
@@ -1893,7 +1902,7 @@
 					"Extension: %s\r\n"
 					"Priority: %d\r\n"
 					"%s",
-					qe->parent->name, tmp->interface, qe->chan->name, tmp->chan->name,
+					qe->parent->name, tmp->interface, tmp->member->membername, qe->chan->name, tmp->chan->name,
 					tmp->chan->cid.cid_num ? tmp->chan->cid.cid_num : "unknown",
 					tmp->chan->cid.cid_name ? tmp->chan->cid.cid_name : "unknown",
 					qe->chan->context, qe->chan->exten, qe->chan->priority,
@@ -2328,8 +2337,8 @@
 			ast_debug(1, "Even though there are %d available members, the strategy is ringall so only the head call is allowed in\n", avl);
 			avl = 1;
 		} else {
-			struct ao2_iterator i = ao2_iterator_init(qe->parent->members, 0);
-			while ((cur = ao2_iterator_next(&i))) {
+			struct ao2_iterator mem_iter = ao2_iterator_init(qe->parent->members, 0);
+			while ((cur = ao2_iterator_next(&mem_iter))) {
 				switch (cur->status) {
 				case AST_DEVICE_NOT_INUSE:
 				case AST_DEVICE_UNKNOWN:
@@ -2618,6 +2627,7 @@
 		struct callattempt *tmp = ast_calloc(1, sizeof(*tmp));
 
 		if (!tmp) {
+			ao2_ref(cur, -1);
 			ast_mutex_unlock(&qe->parent->lock);
 			if (use_weight)
 				AST_LIST_UNLOCK(&queues);
@@ -3046,13 +3056,13 @@
 static struct member *interface_exists(struct call_queue *q, const char *interface)
 {
 	struct member *mem;
-	struct ao2_iterator i;
+	struct ao2_iterator mem_iter;
 
 	if (!q)
 		return NULL;
 
-	i = ao2_iterator_init(q->members, 0);
-	while ((mem = ao2_iterator_next(&i))) {
+	mem_iter = ao2_iterator_init(q->members, 0);
+	while ((mem = ao2_iterator_next(&mem_iter))) {
 		if (!strcasecmp(interface, mem->interface))
 			return mem;
 		ao2_ref(mem, -1);
@@ -3073,15 +3083,15 @@
 	char value[PM_MAX_LEN];
 	int value_len = 0;
 	int res;
-	struct ao2_iterator i;
+	struct ao2_iterator mem_iter;
 
 	memset(value, 0, sizeof(value));
 
 	if (!pm_queue)
 		return;
 
-	i = ao2_iterator_init(pm_queue->members, 0);
-	while ((cur_member = ao2_iterator_next(&i))) {
+	mem_iter = ao2_iterator_init(pm_queue->members, 0);
+	while ((cur_member = ao2_iterator_next(&mem_iter))) {
 		if (!cur_member->dynamic) {
 			ao2_ref(cur_member, -1);
 			continue;
@@ -3110,8 +3120,10 @@
 static int remove_from_queue(const char *queuename, const char *interface)
 {
 	struct call_queue *q;
-	struct member *mem;
+	struct member *mem, tmpmem;
 	int res = RES_NOSUCHQUEUE;
+
+	ast_copy_string(tmpmem.interface, interface, sizeof(tmpmem.interface));
 
 	AST_LIST_LOCK(&queues);
 	AST_LIST_TRAVERSE(&queues, q, list) {
@@ -3121,7 +3133,7 @@
 			continue;
 		}
 
-		if ((mem = ao2_find(q->members, (char *)interface, OBJ_UNLINK))) {
+		if ((mem = ao2_find(q->members, &tmpmem, OBJ_POINTER | OBJ_UNLINK))) {
 			q->membercount--;
 			manager_event(EVENT_FLAG_AGENT, "QueueMemberRemoved",
 				"Queue: %s\r\n"
@@ -3228,7 +3240,7 @@
 					dump_queue_members(q);
 
 				if(mem->realtime)
-					update_realtime_member_field(mem, queuename, "paused", paused ? "1" : "0");
+					update_realtime_member_field(mem, q->name, "paused", paused ? "1" : "0");
 
 				ast_queue_log(q->name, "NONE", mem->membername, (paused ? "PAUSE" : "UNPAUSE"), "%s", S_OR(reason, ""));
 				
@@ -3871,7 +3883,7 @@
 	int count = 0;
 	struct call_queue *q;
 	struct member *m;
-	struct ao2_iterator i;
+	struct ao2_iterator mem_iter;
 
 	buf[0] = '\0';
 	
@@ -3890,8 +3902,8 @@
 	AST_LIST_UNLOCK(&queues);
 
 	if (q) {
-		i = ao2_iterator_init(q->members, 0);
-		while ((m = ao2_iterator_next(&i))) {
+		mem_iter = ao2_iterator_init(q->members, 0);
+		while ((m = ao2_iterator_next(&mem_iter))) {
 			/* Count the agents who are logged in and presently answering calls */
 			if ((m->status != AST_DEVICE_UNAVAILABLE) && (m->status != AST_DEVICE_INVALID)) {
 				count++;
@@ -3963,9 +3975,9 @@
 
 	if (q) {
 		int buflen = 0, count = 0;
-		struct ao2_iterator i = ao2_iterator_init(q->members, 0);
-
-		while ((m = ao2_iterator_next(&i))) {
+		struct ao2_iterator mem_iter = ao2_iterator_init(q->members, 0);
+
+		while ((m = ao2_iterator_next(&mem_iter))) {
 			/* strcat() is always faster than printf() */
 			if (count++) {
 				strncat(buf + buflen, ",", len - buflen - 1);
@@ -3975,6 +3987,7 @@
 			buflen += strlen(m->interface);
 			/* Safeguard against overflow (negative length) */
 			if (buflen >= len - 2) {
+				ao2_ref(m, -1);
 				ast_log(LOG_WARNING, "Truncating list\n");
 				break;
 			}
@@ -4042,7 +4055,7 @@
 	char *cat, *tmp;
 	struct ast_variable *var;
 	struct member *cur, *newm;
-	struct ao2_iterator i;
+	struct ao2_iterator mem_iter;
 	int new;
 	const char *general_val = NULL;
 	char parse[80];
@@ -4065,8 +4078,10 @@
 	use_weight=0;
 	/* Mark all queues as dead for the moment */
 	AST_LIST_TRAVERSE(&queues, q, list) {
-		if(!q->realtime)
+		if(!q->realtime) {
 			q->dead = 1;
+			q->found = 0;
+		}
 	}
 
 	/* Chug through config file */
@@ -4104,12 +4119,19 @@
 			if (q) {
 				if (!new)
 					ast_mutex_lock(&q->lock);
+				/* Check if a queue with this name already exists */
+				if (q->found) {
+					ast_log(LOG_WARNING, "Queue '%s' already defined! Skipping!\n", cat);
+					if(!new)
+						ast_mutex_unlock(&q->lock);
+					continue;
+				}
 				/* Re-initialize the queue, and clear statistics */
 				init_queue(q);
 				if (!queue_keep_stats) 
 					clear_queue(q);
-				i = ao2_iterator_init(q->members, 0);
-				while ((cur = ao2_iterator_next(&i))) {
+				mem_iter = ao2_iterator_init(q->members, 0);
+				while ((cur = ao2_iterator_next(&mem_iter))) {
 					if (!cur->dynamic) {
 						cur->delme = 1;
 					}
@@ -4117,6 +4139,8 @@
 				}
 				for (var = ast_variable_browse(cfg, cat); var; var = var->next) {
 					if (!strcasecmp(var->name, "member")) {
+						struct member tmpmem;
+
 						/* Add a new member */
 						ast_copy_string(parse, var->value, sizeof(parse));
 						
@@ -4140,7 +4164,8 @@
 							membername = interface;
 
 						/* Find the old position in the list */
-						cur = ao2_find(q->members, interface, OBJ_UNLINK);
+						ast_copy_string(tmpmem.interface, interface, sizeof(tmpmem.interface));
+						cur = ao2_find(q->members, &tmpmem, OBJ_POINTER | OBJ_UNLINK);
 
 						newm = create_queue_member(interface, membername, penalty, cur ? cur->paused : 0);
 						ao2_link(q->members, newm);
@@ -4158,8 +4183,8 @@
 				}
 
 				/* Free remaining members marked as delme */
-				i = ao2_iterator_init(q->members, 0);
-				while ((cur = ao2_iterator_next(&i))) {
+				mem_iter = ao2_iterator_init(q->members, 0);
+				while ((cur = ao2_iterator_next(&mem_iter))) {
 					if (! cur->delme) {
 						ao2_ref(cur, -1);
 						continue;
@@ -4188,8 +4213,8 @@
 				ast_debug(1, "XXX Leaking a little memory :( XXX\n");
 		} else {
 			ast_mutex_lock(&q->lock);
-			i = ao2_iterator_init(q->members, 0);
-			while ((cur = ao2_iterator_next(&i))) {
+			mem_iter = ao2_iterator_init(q->members, 0);
+			while ((cur = ao2_iterator_next(&mem_iter))) {
 				if (cur->dynamic)
 					q->membercount++;
 				cur->status = ast_device_state(cur->interface);
@@ -4218,7 +4243,7 @@
 	struct ast_str *out = ast_str_alloca(240);
 	int found = 0;
 	time_t now = time(NULL);
-	struct ao2_iterator i;
+	struct ao2_iterator mem_iter;
 
 	if (argc != 2 && argc != 3)
 		return RESULT_SHOWUSAGE;
@@ -4256,8 +4281,8 @@
 			struct member *mem;
 
 			do_print(s, fd, "   Members: ");
-			i = ao2_iterator_init(q->members, 0);
-			while ((mem = ao2_iterator_next(&i))) {
+			mem_iter = ao2_iterator_init(q->members, 0);
+			while ((mem = ao2_iterator_next(&mem_iter))) {
 				ast_str_set(&out, 0, "      %s", mem->interface);
 				if (mem->penalty)
 					ast_str_append(&out, 0, " with penalty %d", mem->penalty);
@@ -4362,7 +4387,7 @@
 	struct call_queue *q;
 	struct queue_ent *qe;
 	struct member *mem;
-	struct ao2_iterator i;
+	struct ao2_iterator mem_iter;
 
 	astman_send_ack(s, m, "Queue summary will follow");
 	time(&now);
@@ -4375,8 +4400,8 @@
 		/* List queue properties */
 		if (ast_strlen_zero(queuefilter) || !strcmp(q->name, queuefilter)) {
 			/* List Queue Members */
-			i = ao2_iterator_init(q->members, 0);
-			while ((mem = ao2_iterator_next(&i))) {
+			mem_iter = ao2_iterator_init(q->members, 0);
+			while ((mem = ao2_iterator_next(&mem_iter))) {
 				if ((mem->status != AST_DEVICE_UNAVAILABLE) && (mem->status != AST_DEVICE_INVALID)) {
 					++qmemcount;
 					if (((mem->status == AST_DEVICE_NOT_INUSE) || (mem->status == AST_DEVICE_UNKNOWN)) && !(mem->paused)) {
@@ -4423,7 +4448,7 @@
 	struct queue_ent *qe;
 	float sl = 0;
 	struct member *mem;
-	struct ao2_iterator i;
+	struct ao2_iterator mem_iter;
 
 	astman_send_ack(s, m, "Queue status will follow");
 	time(&now);
@@ -4453,11 +4478,12 @@
 				q->name, q->maxlen, int2strat(q->strategy), q->count, q->holdtime, q->callscompleted,
 				q->callsabandoned, q->servicelevel, sl, q->weight, idText);
 			/* List Queue Members */
-			i = ao2_iterator_init(q->members, 0);
-			while ((mem = ao2_iterator_next(&i))) {
+			mem_iter = ao2_iterator_init(q->members, 0);
+			while ((mem = ao2_iterator_next(&mem_iter))) {
 				if (ast_strlen_zero(memberfilter) || !strcmp(mem->interface, memberfilter)) {
 					astman_append(s, "Event: QueueMember\r\n"
 						"Queue: %s\r\n"
+						"Name: %s\r\n"
 						"Location: %s\r\n"
 						"Membership: %s\r\n"
 						"Penalty: %d\r\n"
@@ -4467,7 +4493,7 @@
 						"Paused: %d\r\n"
 						"%s"
 						"\r\n",
-						q->name, mem->interface, mem->dynamic ? "dynamic" : "static",
+						q->name, mem->membername, mem->interface, mem->dynamic ? "dynamic" : "static",
 						mem->penalty, mem->calls, (int)mem->lastcall, mem->status, mem->paused, idText);
 				}
 				ao2_ref(mem, -1);
@@ -4757,7 +4783,7 @@
 	int which = 0;
 	struct call_queue *q;
 	struct member *m;
-	struct ao2_iterator i;
+	struct ao2_iterator mem_iter;
 
 	/* 0 - queue; 1 - remove; 2 - member; 3 - <member>; 4 - from; 5 - <queue> */
 	if (pos > 5 || pos < 3)
@@ -4772,8 +4798,8 @@
 	if (!AST_LIST_EMPTY(&queues)) { /* XXX unnecessary ? the traverse does that for us */
 		AST_LIST_TRAVERSE(&queues, q, list) {
 			ast_mutex_lock(&q->lock);
-			i = ao2_iterator_init(q->members, 0);
-			while ((m = ao2_iterator_next(&i))) {
+			mem_iter = ao2_iterator_init(q->members, 0);
+			while ((m = ao2_iterator_next(&mem_iter))) {
 				if (++which > state) {
 					char *tmp;
 					ast_mutex_unlock(&q->lock);
@@ -4781,12 +4807,83 @@
 					ao2_ref(m, -1);
 					return tmp;
 				}
+				ao2_ref(m, -1);
 			}
 			ast_mutex_unlock(&q->lock);
 		}
 	}
 
 	return NULL;
+}
+
+static char *complete_queue_pause_member(const char *line, const char *word, int pos, int state)
+{
+	/* 0 - queue; 1 - pause; 2 - member; 3 - <interface>; 4 - queue; 5 - <queue>; 6 - reason; 7 - <reason> */
+	switch (pos) {
+	case 3:	/* Don't attempt to complete name of interface (infinite possibilities) */
+		return NULL;
+	case 4:	/* only one possible match, "queue" */
+		return state == 0 ? ast_strdup("queue") : NULL;
+	case 5:	/* <queue> */
+		return complete_queue(line, word, pos, state);
+	case 6: /* "reason" */
+		return state == 0 ? ast_strdup("reason") : NULL;
+	case 7: /* Can't autocomplete a reason, since it's 100% customizeable */
+		return NULL;
+	default:
+		return NULL;
+	}
+}
+
+static char *handle_queue_pause_member(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+	char *queuename, *interface, *reason;
+	int paused;
+
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "queue {pause|unpause} member";
+		e->usage = 
+			"Usage: queue {pause|unpause} member <member> [queue <queue> [reason <reason>]]\n"
+			"		Pause or unpause a queue member. Not specifying a particular queue\n"
+			"		will pause or unpause a member across all queues to which the member\n"
+			"		belongs.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return complete_queue_pause_member(a->line, a-> word, a->pos, a->n);
+	}
+
+	if (a->argc < 4 || a->argc == 5 || a->argc == 7 || a->argc > 8) {
+		return CLI_SHOWUSAGE;
+	} else if (a->argc >= 5 && strcmp(a->argv[4], "queue")) {
+		return CLI_SHOWUSAGE;
+	} else if (a->argc == 8 && strcmp(a->argv[6], "reason")) {
+		return CLI_SHOWUSAGE;
+	}
+
+
+	interface = a->argv[3];
+	queuename = a->argc >= 6 ? a->argv[5] : NULL;
+	reason = a->argc == 8 ? a->argv[7] : NULL;
+	paused = !strcasecmp(a->argv[1], "pause");
+
+	if(set_member_paused(queuename, interface, reason, paused) == RESULT_SUCCESS) {
+		ast_cli(a->fd, "%spaused interface '%s'", paused ? "" : "un", interface);
+		if(!ast_strlen_zero(queuename))
+			ast_cli(a->fd, " in queue '%s'", queuename);
+		if(!ast_strlen_zero(reason))
+			ast_cli(a->fd, " for reason '%s'", reason);
+		ast_cli(a->fd, "\n");
+		return CLI_SUCCESS;
+	} else {
+		ast_cli(a->fd, "Unable to %spause interface '%s'", paused ? "" : "un", interface);
+		if(!ast_strlen_zero(queuename))
+			ast_cli(a->fd, " in queue '%s'", queuename);
+		if(!ast_strlen_zero(reason))
+			ast_cli(a->fd, " for reason '%s'", reason);
+		ast_cli(a->fd, "\n");
+		return CLI_FAILURE;
+	}
 }
 
 static const char queue_show_usage[] =
@@ -4798,6 +4895,12 @@
 
 static const char qrm_cmd_usage[] =
 "Usage: queue remove member <channel> from <queue>\n";
+
+static const char qpm_cmd_usage[] = 
+"Usage: queue pause member <channel> in <queue> reason <reason>\n";
+
+static const char qum_cmd_usage[] =
+"Usage: queue unpause member <channel> in <queue> reason <reason>\n";
 
 static struct ast_cli_entry cli_queue[] = {
 	{ { "queue", "show", NULL },
@@ -4811,6 +4914,8 @@
 	{ { "queue", "remove", "member", NULL },
 	handle_queue_remove_member, "Removes a channel from a specified queue",
 	qrm_cmd_usage, complete_queue_remove_member, NULL },
+
+	NEW_CLI(handle_queue_pause_member, "Pause or unpause a queue member"),
 };
 
 static int unload_module(void)

Modified: team/russell/events/apps/app_sms.c
URL: http://svn.digium.com/view/asterisk/team/russell/events/apps/app_sms.c?view=diff&rev=82456&r1=82455&r2=82456
==============================================================================
--- team/russell/events/apps/app_sms.c (original)
+++ team/russell/events/apps/app_sms.c Fri Sep 14 16:24:49 2007
@@ -202,7 +202,7 @@
 	char queue[30];              /*!< queue name */
 	char oa[20];                 /*!< originating address */
 	char da[20];                 /*!< destination address */
-	time_t scts;                 /*!< time stamp, UTC */
+	struct timeval scts;         /*!< time stamp, UTC */
 	unsigned char pid;           /*!< protocol ID */
 	unsigned char dcs;           /*!< data coding scheme */
 	short mr;                    /*!< message reference - actually a byte, but use -1 for not set */
@@ -766,7 +766,7 @@
 	h->rx = h->udl = *h->oa = *h->da = h->pid = h->srr = h->udhi = h->rp = h->vp = h->udhl = 0;
 	h->mr = -1;
 	h->dcs = 0xF1;			/* normal messages class 1 */
-	h->scts = time(NULL);
+	h->scts = ast_tvnow();
 	s = fopen(fn, "r");
 	if (s) {
 		if (unlink(fn)) {	/* concurrent access, we lost */
@@ -825,7 +825,7 @@
 						  M,
 						  S;
 						if (sscanf (p, "%d-%d-%dT%d:%d:%d", &Y, &m, &d, &H, &M, &S) == 6) {
-							struct tm t;
+							struct ast_tm t = { 0, };
 							t.tm_year = Y - 1900;
 							t.tm_mon = m - 1;
 							t.tm_mday = d;
@@ -833,8 +833,8 @@
 							t.tm_min = M;
 							t.tm_sec = S;
 							t.tm_isdst = -1;
-							h->scts = mktime(&t);
-							if (h->scts == (time_t) - 1)
+							h->scts = ast_mktime(&t, NULL);
+							if (h->scts.tv_sec == 0)
 								ast_log(LOG_WARNING, "Bad date/timein %s: %s", fn, p);
 						}
 					} else
@@ -925,7 +925,7 @@
 	snprintf(fn, sizeof(fn), "%s/sms/%s", ast_config_AST_SPOOL_DIR, h->smsc ? h->rx ? "morx" : "mttx" : h->rx ? "mtrx" : "motx");
 	ast_mkdir(fn, 0777);			/* ensure it exists */
 	ast_copy_string(fn2, fn, sizeof(fn2));
-	snprintf(fn2 + strlen(fn2), sizeof(fn2) - strlen(fn2), "/%s.%s-%d", h->queue, isodate(h->scts, buf, sizeof(buf)), seq++);
+	snprintf(fn2 + strlen(fn2), sizeof(fn2) - strlen(fn2), "/%s.%s-%d", h->queue, isodate(h->scts.tv_sec, buf, sizeof(buf)), seq++);
 	snprintf(fn + strlen(fn), sizeof(fn) - strlen(fn), "/.%s", fn2 + strlen(fn) + 1);
 	o = fopen(fn, "w");
 	if (o == NULL)
@@ -982,9 +982,9 @@
 			}
 		}
 	}
-	if (h->scts) {
+	if (h->scts.tv_sec) {
 		char buf[30];
-		fprintf(o, "scts=%s\n", isodate(h->scts, buf, sizeof(buf)));
+		fprintf(o, "scts=%s\n", isodate(h->scts.tv_sec, buf, sizeof(buf)));
 	}
 	if (h->pid)
 		fprintf(o, "pid=%d\n", h->pid);
@@ -1027,7 +1027,7 @@
 			h->udhi = ((h->imsg[2] & 0x40) ? 1 : 0);
 			h->rp = ((h->imsg[2] & 0x80) ? 1 : 0);
 			ast_copy_string(h->oa, h->cli, sizeof(h->oa));
-			h->scts = time(NULL);
+			h->scts = ast_tvnow();
 			h->mr = h->imsg[p++];
 			p += unpackaddress(h->da, h->imsg + p);
 			h->pid = h->imsg[p++];
@@ -1065,7 +1065,7 @@
 			p += unpackaddress(h->oa, h->imsg + p);
 			h->pid = h->imsg[p++];
 			h->dcs = h->imsg[p++];
-			h->scts = unpackdate(h->imsg + p);
+			h->scts.tv_sec = unpackdate(h->imsg + p);
 			p += 7;
 			p += unpacksms(h->dcs, h->imsg + p, h->udh, &h->udhl, h->ud, &h->udl, h->udhi);
 			h->rx = 1;				 /* received message */
@@ -1116,7 +1116,7 @@
 static void sms_compose2(sms_t *h, int more)
 {
 	struct ast_tm tm;
-	struct timeval tv = { h->scts, 0 };
+	struct timeval tv = h->scts;
 	char stm[9];
 
 	h->omsg[0] = 0x00;       /* set later... */
@@ -1171,7 +1171,7 @@
 	/* ast_verb(3, "SMS-P2 Frame: %s\n", sms_hexdump(h->imsg, sz, debug_buf)); */
 
 	/* Parse message body (called payload) */
-	tv.tv_sec = h->scts = time(NULL);
+	tv = h->scts = ast_tvnow();
 	for (f = 4; f < sz; ) {
 		msg = h->imsg[f++];
 		msgsz = h->imsg[f++];
@@ -1186,7 +1186,7 @@
 			h->udl = msgsz;
 			break;
 		case 0x14:      /* Date SCTS */
-			tv.tv_sec = h->scts = time(NULL);
+			tv = h->scts = ast_tvnow();
 			ast_localtime(&tv, &tm, NULL);
 			tm.tm_mon = ( (h->imsg[f] * 10) + h->imsg[f + 1] ) - 1;
 			tm.tm_mday = ( (h->imsg[f + 2] * 10) + h->imsg[f + 3] );
@@ -1302,7 +1302,7 @@
 		p += packaddress(h->omsg + p, h->oa);
 		h->omsg[p++] = h->pid;
 		h->omsg[p++] = h->dcs;
-		packdate(h->omsg + p, h->scts);
+		packdate(h->omsg + p, h->scts.tv_sec);
 		p += 7;
 		p += packsms(h->dcs, h->omsg + p, h->udhl, h->udh, h->udl, h->ud);
 	} else {			 /* submit */
@@ -1823,7 +1823,7 @@
 
 		/* submitting a message, not taking call. */
 		/* deprecated, use smsq instead */
-		h.scts = time(NULL);
+		h.scts = ast_tvnow();
 		if (ast_strlen_zero(sms_args.addr) || strlen(sms_args.addr) >= sizeof(h.oa)) {
 			ast_log(LOG_ERROR, "Address too long %s\n", sms_args.addr);
 			goto done;

Modified: team/russell/events/build_tools/menuselect-deps.in
URL: http://svn.digium.com/view/asterisk/team/russell/events/build_tools/menuselect-deps.in?view=diff&rev=82456&r1=82455&r2=82456
==============================================================================
--- team/russell/events/build_tools/menuselect-deps.in (original)
+++ team/russell/events/build_tools/menuselect-deps.in Fri Sep 14 16:24:49 2007
@@ -31,6 +31,7 @@
 SSL=@PBX_OPENSSL@
 CRYPTO=@PBX_CRYPTO@
 TONEZONE=@PBX_TONEZONE@
+USB=@PBX_USB@
 UNIXODBC=@PBX_UNIXODBC@
 VORBIS=@PBX_VORBIS@
 VPBAPI=@PBX_VPB@

Modified: team/russell/events/cdr/cdr_csv.c
URL: http://svn.digium.com/view/asterisk/team/russell/events/cdr/cdr_csv.c?view=diff&rev=82456&r1=82455&r2=82456
==============================================================================
--- team/russell/events/cdr/cdr_csv.c (original)
+++ team/russell/events/cdr/cdr_csv.c Fri Sep 14 16:24:49 2007
@@ -48,6 +48,7 @@
 #include "asterisk/options.h"
 #include "asterisk/logger.h"
 #include "asterisk/utils.h"
+#include "asterisk/lock.h"
 
 #define CSV_LOG_DIR "/cdr-csv"
 #define CSV_MASTER  "/Master.csv"
@@ -92,8 +93,8 @@
 
 static char *name = "csv";
 
-static FILE *mf = NULL;
-
+AST_MUTEX_DEFINE_STATIC(mf_lock);
+AST_MUTEX_DEFINE_STATIC(acf_lock);
 
 static int load_config(int reload)
 {
@@ -263,18 +264,26 @@
 		return -1;
 	}
 	snprintf(tmp, sizeof(tmp), "%s/%s/%s.csv", (char *)ast_config_AST_LOG_DIR,CSV_LOG_DIR, acc);
+
+	ast_mutex_lock(&acf_lock);
 	f = fopen(tmp, "a");
-	if (!f)
-		return -1;
+	if (!f) {
+		ast_mutex_unlock(&acf_lock);
+		ast_log(LOG_ERROR, "Unable to open file %s : %s\n", tmp, strerror(errno));
+		return -1;
+	}
 	fputs(s, f);
 	fflush(f);
 	fclose(f);
+	ast_mutex_unlock(&acf_lock);
+
 	return 0;
 }
 
 
 static int csv_log(struct ast_cdr *cdr)
 {
+	FILE *mf = NULL;
 	/* Make sure we have a big enough buf */
 	char buf[1024];
 	char csvmaster[PATH_MAX];
@@ -288,16 +297,19 @@
 		/* because of the absolutely unconditional need for the
 		   highest reliability possible in writing billing records,
 		   we open write and close the log file each time */
+		ast_mutex_lock(&mf_lock);
 		mf = fopen(csvmaster, "a");
-		if (!mf) {
-			ast_log(LOG_ERROR, "Unable to re-open master file %s : %s\n", csvmaster, strerror(errno));
-		}
 		if (mf) {

[... 5933 lines stripped ...]



More information about the svn-commits mailing list