Revision
17216
Author
moy
Date
2010-04-05 16:49:43 -0500 (Mon, 05 Apr 2010)

Log Message

added cpu monitor

Modified Paths

Added Paths

Diff

Modified: freeswitch/trunk/libs/freetdm/Makefile.am (17215 => 17216)


--- freeswitch/trunk/libs/freetdm/Makefile.am	2010-04-05 20:01:08 UTC (rev 17215)
+++ freeswitch/trunk/libs/freetdm/Makefile.am	2010-04-05 21:49:43 UTC (rev 17216)
@@ -72,7 +72,8 @@
 $(SRC)/libteletone_generate.c \
 $(SRC)/ftdm_buffer.c \
 $(SRC)/ftdm_threadmutex.c \
-$(SRC)/ftdm_dso.c
+$(SRC)/ftdm_dso.c \
+$(SRC)/ftdm_cpu_monitor.c
 
 library_include_HEADERS = \
 $(SRC)/include/fsk.h \
@@ -90,7 +91,8 @@
 $(SRC)/include/ftdm_config.h \
 $(SRC)/include/ftdm_threadmutex.h \
 $(SRC)/include/ftdm_dso.h \
-$(SRC)/include/ftdm_types.h 
+$(SRC)/include/ftdm_types.h \
+$(SRC)/include/ftdm_cpu_monitor.h 
 
 lib_LTLIBRARIES	       = libfreetdm.la
 libfreetdm_la_CFLAGS   = $(AM_CFLAGS) $(MY_CFLAGS)

Modified: freeswitch/trunk/libs/freetdm/mod_freetdm/mod_freetdm.c (17215 => 17216)


--- freeswitch/trunk/libs/freetdm/mod_freetdm/mod_freetdm.c	2010-04-05 20:01:08 UTC (rev 17215)
+++ freeswitch/trunk/libs/freetdm/mod_freetdm/mod_freetdm.c	2010-04-05 21:49:43 UTC (rev 17216)
@@ -3142,6 +3142,8 @@
 	module_pool = pool;
 
 	ftdm_global_set_logger(ftdm_logger);
+
+	ftdm_cpu_monitor_disable();
 	
 	if (ftdm_global_init() != FTDM_SUCCESS) {
 		ftdm_log(FTDM_LOG_ERROR, "Error loading FreeTDM\n");

Added: freeswitch/trunk/libs/freetdm/src/ftdm_cpu_monitor.c (0 => 17216)


--- freeswitch/trunk/libs/freetdm/src/ftdm_cpu_monitor.c	                        (rev 0)
+++ freeswitch/trunk/libs/freetdm/src/ftdm_cpu_monitor.c	2010-04-05 21:49:43 UTC (rev 17216)
@@ -0,0 +1,271 @@
+/*
+ * Copyright (c) 2010, Sangoma Technologies
+ * Moises Silva <moy@sangoma.com>
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 
+ * * Neither the name of the original author; nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Contributors:
+ * David Yat Sin <dyatsin@sangoma.com>
+ * 
+ */
+
+#ifdef WIN32
+#define _WIN32_WINNT 0x0501 // To make GetSystemTimes visible in windows.h
+#include <windows.h>
+#else /* LINUX */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <errno.h>
+#endif
+
+#include "freetdm.h"
+#include "ftdm_cpu_monitor.h"
+struct ftdm_cpu_monitor_stats
+{
+	/* bool, just used to retrieve the values for the first time and not calculate the percentage of idle time */
+	int valid_last_times;
+
+	/* last calculated percentage of idle time */
+	double last_percentage_of_idle_time;
+
+#ifdef __linux__
+	/* all of these are the Linux jiffies last retrieved count */
+	unsigned long long last_user_time;
+	unsigned long long last_system_time;
+	unsigned long long last_idle_time;
+
+	unsigned long long last_nice_time;
+	unsigned long long last_irq_time;
+	unsigned long long last_soft_irq_time;
+	unsigned long long last_io_wait_time;
+	unsigned long long last_steal_time;
+
+	/* /proc/stat file descriptor used to retrieve the counters */
+	int procfd;
+	int initd;
+#elif defined (WIN32)  || defined (WIN64)
+	__int64 i64LastUserTime;
+	__int64 i64LastKernelTime;
+	__int64 i64LastIdleTime;
+#else
+/* Unsupported */
+#endif
+};
+
+#ifdef __linux__
+static ftdm_status_t ftdm_cpu_read_stats(struct ftdm_cpu_monitor_stats *p,
+											unsigned long long *user,
+											unsigned long long *nice,
+											unsigned long long *system,
+											unsigned long long *idle,
+											unsigned long long *iowait,
+											unsigned long long *irq,
+											unsigned long long *softirq,
+											unsigned long long *steal)
+{
+// the output of proc should not change that often from one kernel to other
+// see fs/proc/proc_misc.c or fs/proc/stat.c in the Linux kernel for more details
+// also man 5 proc is useful
+#define CPU_ELEMENTS 8 // change this if you change the format string
+#define CPU_INFO_FORMAT "cpu  %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu"
+	static const char procfile[] = "/proc/stat";
+	int rc = 0;
+	int myerrno = 0;
+	int elements = 0;
+	const char *cpustr = NULL;
+	char statbuff[1024];
+
+	if (!p->initd) {
+		p->procfd = open(procfile, O_RDONLY, 0);
+		if(p->procfd == -1) {
+			ftdm_log(FTDM_LOG_ERROR, "Failed to open CPU statistics file %s: %s\n", procfile, strerror(myerrno));
+			return FTDM_FAIL;
+		}
+		p->initd = 1;
+	} else {
+		lseek(p->procfd, 0L, SEEK_SET);
+	}
+
+	rc = read(p->procfd, statbuff, sizeof(statbuff) - 1);
+	if (rc <= 0) {
+		myerrno = errno;
+		ftdm_log(FTDM_LOG_ERROR, "Failed to read CPU statistics file %s: %s\n", procfile, strerror(myerrno));
+		return FTDM_FAIL;
+	}
+
+	cpustr = strstr(statbuff, "cpu ");
+	if (!cpustr) {
+		ftdm_log(FTDM_LOG_ERROR, "wrong format for Linux proc cpu statistics: missing cpu string\n");
+		return FTDM_FAIL;
+	}
+
+	elements = sscanf(cpustr, CPU_INFO_FORMAT, user, nice, system, idle, iowait, irq, softirq, steal);
+	if (elements != CPU_ELEMENTS) {
+		ftdm_log(FTDM_LOG_ERROR, "wrong format for Linux proc cpu statistics: expected %d elements, but just found %d\n", CPU_ELEMENTS, elements);
+		return FTDM_FAIL;
+	}
+	return FTDM_SUCCESS;
+}
+#endif
+
+#ifdef __linux__
+FT_DECLARE(ftdm_status_t) ftdm_cpu_get_system_idle_time (struct ftdm_cpu_monitor_stats *p, double *idle_percentage)
+{
+	unsigned long long user, nice, system, idle, iowait, irq, softirq, steal;
+	unsigned long long usertime, kerneltime, idletime, totaltime, halftime;
+
+	if (ftdm_cpu_read_stats(p, &user, &nice, &system, &idle, &iowait, &irq, &softirq, &steal)) {
+		ftdm_log(FTDM_LOG_ERROR, "Failed to retrieve Linux CPU statistics\n");
+		return FTDM_FAIL;
+	}
+
+	if (!p->valid_last_times) {
+		// we dont strictly need to save all of them but I feel code is more clear if we do
+		p->valid_last_times = 1;
+		p->last_user_time = user;
+		p->last_nice_time = nice;
+		p->last_system_time = system;
+		p->last_irq_time = irq;
+		p->last_soft_irq_time = softirq;
+		p->last_io_wait_time = iowait;
+		p->last_steal_time = steal;
+		p->last_idle_time = idle;
+		p->last_percentage_of_idle_time = 100.0;
+		*idle_percentage = p->last_percentage_of_idle_time;
+		return FTDM_SUCCESS;
+	}
+
+	usertime = (user - p->last_user_time) + (nice - p->last_nice_time);
+	kerneltime = (system - p->last_system_time) + (irq - p->last_irq_time) + (softirq - p->last_soft_irq_time);
+	kerneltime += (iowait - p->last_io_wait_time);
+	kerneltime += (steal - p->last_steal_time);
+	idletime = (idle - p->last_idle_time);
+
+	totaltime = usertime + kerneltime + idletime;
+	
+	if (totaltime <= 0) {
+		// this may happen if not enough time has elapsed and the jiffies counters are the same than the last time we checked
+		// jiffies depend on timer interrupts which depend on the number of HZ compile time setting of the kernel
+		// typical configs set HZ to 100 (that means, 100 jiffies updates per second, that is one each 10ms)
+		// avoid an arithmetic exception and return the same values
+		*idle_percentage = p->last_percentage_of_idle_time;
+		return FTDM_SUCCESS;
+	}
+
+	halftime = totaltime / 2UL;
+
+	p->last_percentage_of_idle_time = ((100 * idletime + halftime) / totaltime);
+	*idle_percentage = p->last_percentage_of_idle_time;
+
+	p->last_user_time = user;
+	p->last_nice_time = nice;
+	p->last_system_time = system;
+	p->last_irq_time = irq;
+	p->last_soft_irq_time = softirq;
+	p->last_io_wait_time = iowait;
+	p->last_steal_time = steal;
+	p->last_idle_time = idle;
+
+	return FTDM_SUCCESS;
+}
+
+#elif defined (WIN32) || defined (WIN64)
+FT_DECLARE(ftdm_status_t) ftdm_cpu_get_system_idle_time(struct ftdm_cpu_monitor_stats *p, double *idle_percentage)
+{
+	FILETIME idleTime;
+	FILETIME kernelTime;
+	FILETIME userTime;
+  
+	if (!::GetSystemTimes(&idleTime, &kernelTime, &userTime)) {
+		return false;
+	}
+  
+	__int64 i64UserTime = (__int64)userTime.dwLowDateTime | ((__int64)userTime.dwHighDateTime << 32);
+
+	__int64 i64KernelTime = (__int64)kernelTime.dwLowDateTime | ((__int64)kernelTime.dwHighDateTime << 32);
+
+	__int64 i64IdleTime = (__int64)idleTime.dwLowDateTime | ((__int64)idleTime.dwHighDateTime << 32);
+
+	if (p->valid_last_times) {
+		__int64 i64User = i64UserTime - p->i64LastUserTime;
+		__int64 i64Kernel = i64KernelTime - p->i64LastKernelTime;
+		__int64 i64Idle = i64IdleTime - p->i64LastIdleTime;
+		__int64 i64System = i64User + i64Kernel;
+		*idle_percentage = 100.0 * i64Idle / i64System;
+	} else {
+		*idle_percentage = 100.0;
+		p->valid_last_times = 1;
+	}
+
+	/* Remember current value for the next call */
+	p->i64LastUserTime = i64UserTime;
+	p->i64LastKernelTime = i64KernelTime;
+	p->i64LastIdleTime = i64IdleTime;
+
+	/* Success */
+	return FTDM_SUCCESS;
+}
+#else
+/* Unsupported */
+FT_DECLARE(ftdm_status_t) ftdm_cpu_get_system_idle_time(struct ftdm_cpu_monitor_stats *p, double *idle_percentage)
+{
+	return FTDM_FAIL;
+}
+#endif
+
+FT_DECLARE(struct ftdm_cpu_monitor_stats*) ftdm_new_cpu_monitor(void)
+{
+	return calloc(1, sizeof(struct ftdm_cpu_monitor_stats));
+}
+
+FT_DECLARE(void) ftdm_delete_cpu_monitor(struct ftdm_cpu_monitor_stats *p)
+{
+#ifdef __linux__
+	close(p->procfd);
+#endif
+	free(p);
+}
+
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4:
+ */

Modified: freeswitch/trunk/libs/freetdm/src/ftdm_io.c (17215 => 17216)


--- freeswitch/trunk/libs/freetdm/src/ftdm_io.c	2010-04-05 20:01:08 UTC (rev 17215)
+++ freeswitch/trunk/libs/freetdm/src/ftdm_io.c	2010-04-05 21:49:43 UTC (rev 17216)
@@ -48,6 +48,7 @@
 #ifdef FTDM_PIKA_SUPPORT
 #include "ftdm_pika.h"
 #endif
+#include "ftdm_cpu_monitor.h"
 
 #define SPAN_PENDING_CHANS_QUEUE_SIZE 1000
 
@@ -80,6 +81,16 @@
 #endif
 }
 
+typedef struct {
+	uint8_t         running;
+	uint8_t         alarm;
+	uint32_t        interval;
+	uint8_t         alarm_action_flags;
+	uint8_t         set_alarm_threshold;
+	uint8_t         reset_alarm_threshold;
+	ftdm_interrupt_t *interrupt;
+} cpu_monitor_t;
+
 static struct {
 	ftdm_hash_t *interface_hash;
 	ftdm_hash_t *module_hash;
@@ -93,9 +104,17 @@
 	uint32_t running;
 	ftdm_span_t *spans;
 	ftdm_group_t *groups;
+	cpu_monitor_t cpu_monitor;
 } globals;
 
+static uint8_t ftdm_cpu_monitor_disabled = 0;
 
+enum ftdm_enum_cpu_alarm_action_flags
+{
+	FTDM_CPU_ALARM_ACTION_WARN   = (1 << 0),
+	FTDM_CPU_ALARM_ACTION_REJECT = (1 << 1)
+};
+
 /* enum lookup funcs */
 FTDM_ENUM_NAMES(TONEMAP_NAMES, TONEMAP_STRINGS)
 FTDM_STR2ENUM(ftdm_str2ftdm_tonemap, ftdm_tonemap2str, ftdm_tonemap_t, TONEMAP_NAMES, FTDM_TONEMAP_INVALID)
@@ -1470,6 +1489,14 @@
 		snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", "Channel is alarmed\n");
 		return FTDM_FAIL;
 	}
+
+	if (globals.cpu_monitor.alarm && 
+	    globals.cpu_monitor.alarm_action_flags & FTDM_CPU_ALARM_ACTION_REJECT) {
+		snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", "CPU usage alarm is on - refusing to open channel\n");
+		ftdm_log(FTDM_LOG_WARNING, "CPU usage alarm is on - refusing to open channel\n");
+		ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_SWITCH_CONGESTION;
+		return FTDM_FAIL;
+	}
 	
 	if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_READY) || (status = ftdm_mutex_trylock(ftdmchan->mutex)) != FTDM_SUCCESS) {
 		snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "Channel is not ready or is in use %d %d", ftdm_test_flag(ftdmchan, FTDM_CHANNEL_READY), status);
@@ -2988,6 +3015,44 @@
 			} else {
 				ftdm_log(FTDM_LOG_ERROR, "unknown span variable '%s'\n", var);
 			}
+		} else if (!strncasecmp(cfg.category, "general", 7)) {
+			if (!strncasecmp(var, "cpu_monitoring_interval", sizeof("cpu_monitoring_interval")-1)) {
+				if (atoi(val) > 0) {
+					globals.cpu_monitor.interval = atoi(val);
+				} else {
+					ftdm_log(FTDM_LOG_ERROR, "Invalid cpu monitoring interval %s\n", val);
+				}
+			} else if (!strncasecmp(var, "cpu_set_alarm_threshold", sizeof("cpu_set_alarm_threshold")-1)) {
+				if (atoi(val) > 0 && atoi(val) < 100) {
+					globals.cpu_monitor.set_alarm_threshold = atoi(val);
+				} else {
+					ftdm_log(FTDM_LOG_ERROR, "Invalid cpu alarm set threshold %s\n", val);
+				}
+			} else if (!strncasecmp(var, "cpu_reset_alarm_threshold", sizeof("cpu_reset_alarm_threshold")-1)) {
+				if (atoi(val) > 0 && atoi(val) < 100) {
+					globals.cpu_monitor.reset_alarm_threshold = atoi(val);
+					if (globals.cpu_monitor.reset_alarm_threshold > globals.cpu_monitor.set_alarm_threshold) {
+						globals.cpu_monitor.reset_alarm_threshold = globals.cpu_monitor.set_alarm_threshold - 10;
+						ftdm_log(FTDM_LOG_ERROR, "Cpu alarm reset threshold must be lower than set threshold"
+								", setting threshold to %d\n", globals.cpu_monitor.reset_alarm_threshold);
+					}
+				} else {
+					ftdm_log(FTDM_LOG_ERROR, "Invalid cpu alarm reset threshold %s\n", val);
+				}
+			} else if (!strncasecmp(var, "cpu_alarm_action", sizeof("cpu_alarm_action")-1)) {
+				char* p = val;
+				do {
+					if (!strncasecmp(p, "reject", sizeof("reject")-1)) {
+						globals.cpu_monitor.alarm_action_flags |= FTDM_CPU_ALARM_ACTION_REJECT;
+					} else if (!strncasecmp(p, "warn", sizeof("warn")-1)) {
+						globals.cpu_monitor.alarm_action_flags |= FTDM_CPU_ALARM_ACTION_WARN;
+					}
+					p = strchr(p, ',');
+					if (p) {
+						while(*p++) if (*p != 0x20) break;
+					}
+				} while (p);
+			}
 		} else {
 			ftdm_log(FTDM_LOG_ERROR, "unknown param [%s] '%s' / '%s'\n", cfg.category, var, val);
 		}
@@ -3516,6 +3581,71 @@
 	return status;
 }
 
+static void *ftdm_cpu_monitor_run(ftdm_thread_t *me, void *obj)
+{
+	cpu_monitor_t *monitor = (cpu_monitor_t *)obj;
+	struct ftdm_cpu_monitor_stats *cpu_stats = ftdm_new_cpu_monitor();
+	if (!cpu_stats) {
+		return NULL;
+	}
+	monitor->running = 1;
+
+	while(ftdm_running()) {
+		double time;
+		if (ftdm_cpu_get_system_idle_time(cpu_stats, &time)) {
+			break;
+		}
+
+		if (monitor->alarm) {
+			if ((int)time >= (100 - monitor->set_alarm_threshold)) {
+				ftdm_log(FTDM_LOG_DEBUG, "CPU alarm OFF (idle:%d)\n", (int) time);
+				monitor->alarm = 0;
+			}
+			if (monitor->alarm_action_flags & FTDM_CPU_ALARM_ACTION_WARN) {
+			ftdm_log(FTDM_LOG_WARNING, "CPU alarm is ON (cpu usage:%d)\n", (int) (100-time));
+			}
+		} else {
+			if ((int)time <= (100-monitor->reset_alarm_threshold)) {
+				ftdm_log(FTDM_LOG_DEBUG, "CPU alarm ON (idle:%d)\n", (int) time);
+				monitor->alarm = 1;
+			}
+		}
+		ftdm_interrupt_wait(monitor->interrupt, monitor->interval);
+	}
+
+	ftdm_delete_cpu_monitor(cpu_stats);
+	monitor->running = 0;
+	return NULL;
+}
+
+static ftdm_status_t ftdm_cpu_monitor_start(cpu_monitor_t* monitor)
+{
+	if (ftdm_interrupt_create(&monitor->interrupt, FTDM_INVALID_SOCKET) != FTDM_SUCCESS) {
+		ftdm_log(FTDM_LOG_CRIT, "Failed to create CPU monitor interrupt\n");
+		return FTDM_FAIL;
+	}
+
+	if (ftdm_thread_create_detached(ftdm_cpu_monitor_run, monitor) != FTDM_SUCCESS) {
+		ftdm_log(FTDM_LOG_CRIT, "Failed to create cpu monitor thread!!\n");
+		return FTDM_FAIL;
+	}
+	return FTDM_SUCCESS;
+}
+
+static void ftdm_cpu_monitor_stop(cpu_monitor_t* monitor)
+{
+	ftdm_interrupt_signal(monitor->interrupt);
+	while(monitor->running) {
+		ftdm_sleep(10);
+	}
+}
+
+FT_DECLARE(void) ftdm_cpu_monitor_disable(void)
+{
+	ftdm_cpu_monitor_disabled = 1;
+}
+
+
 FT_DECLARE(ftdm_status_t) ftdm_global_init(void)
 {
 	memset(&globals, 0, sizeof(globals));
@@ -3538,14 +3668,34 @@
 
 FT_DECLARE(ftdm_status_t) ftdm_global_configuration(void)
 {
-	int modcount = ftdm_load_modules();
+	int modcount = 0;
+
+	if (!globals.running) {
+		return FTDM_FAIL;
+	}
+	
+	modcount = ftdm_load_modules();
+
 	ftdm_log(FTDM_LOG_NOTICE, "Modules configured: %d \n", modcount);
 
+	globals.cpu_monitor.interval = 1000;
+	globals.cpu_monitor.alarm_action_flags = FTDM_CPU_ALARM_ACTION_WARN | FTDM_CPU_ALARM_ACTION_REJECT;
+	globals.cpu_monitor.set_alarm_threshold = 80;
+	globals.cpu_monitor.reset_alarm_threshold = 70;
+
 	if (load_config() != FTDM_SUCCESS) {
 		globals.running = 0;
 		ftdm_log(FTDM_LOG_ERROR, "FreeTDM global configuration failed!\n");
 		return FTDM_FAIL;
 	}
+
+	if (!ftdm_cpu_monitor_disabled) {
+		if (ftdm_cpu_monitor_start(&globals.cpu_monitor) != FTDM_SUCCESS) {
+			return FTDM_FAIL;
+		}
+	}
+
+
 	return FTDM_SUCCESS;
 }
 
@@ -3563,6 +3713,8 @@
 
 	globals.running = 0;	
 
+	ftdm_cpu_monitor_stop(&globals.cpu_monitor);
+
 	globals.span_index = 0;
 
 	ftdm_span_close_all();
@@ -3596,6 +3748,7 @@
 	ftdm_mutex_unlock(globals.mutex);
 	ftdm_mutex_destroy(&globals.mutex);
 	ftdm_mutex_destroy(&globals.span_mutex);
+	ftdm_interrupt_destroy(&globals.cpu_monitor.interrupt);
 
 	memset(&globals, 0, sizeof(globals));
 	return FTDM_SUCCESS;

Modified: freeswitch/trunk/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c (17215 => 17216)


--- freeswitch/trunk/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c	2010-04-05 20:01:08 UTC (rev 17215)
+++ freeswitch/trunk/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c	2010-04-05 21:49:43 UTC (rev 17216)
@@ -880,8 +880,8 @@
  */
 static void handle_call_start(ftdm_span_t *span, sangomabc_connection_t *mcon, sangomabc_event_t *event)
 {
-	ftdm_channel_t *ftdmchan;
-
+	ftdm_channel_t *ftdmchan = NULL;
+	int hangup_cause = FTDM_CAUSE_CALL_REJECTED;
 	if (!(ftdmchan = find_ftdmchan(span, (sangomabc_short_event_t*)event, 0))) {
 		if ((ftdmchan = find_ftdmchan(span, (sangomabc_short_event_t*)event, 1))) {
 			int r;
@@ -896,7 +896,7 @@
 
 			}
 			ftdm_set_sflag(ftdmchan, SFLAG_SENT_FINAL_MSG);
-			ftdmchan=NULL;
+			ftdmchan = NULL;
 		}
 		ftdm_log(FTDM_LOG_CRIT, "START CANT FIND CHAN %d:%d\n", event->span+1,event->chan+1);
 		goto error;
@@ -953,12 +953,13 @@
 	return;
 
  error:
+	hangup_cause = ftdmchan ? ftdmchan->caller_data.hangup_cause : FTDM_CAUSE_REQUESTED_CHAN_UNAVAIL;
 	sangomabc_exec_command(mcon,
 						   event->span,
 						   event->chan,
 						   0,
 						   SIGBOOST_EVENT_CALL_START_NACK,
-						   0, 0);
+						   hangup_cause, 0);
 		
 }
 

Modified: freeswitch/trunk/libs/freetdm/src/include/freetdm.h (17215 => 17216)


--- freeswitch/trunk/libs/freetdm/src/include/freetdm.h	2010-04-05 20:01:08 UTC (rev 17215)
+++ freeswitch/trunk/libs/freetdm/src/include/freetdm.h	2010-04-05 21:49:43 UTC (rev 17216)
@@ -824,6 +824,7 @@
 FT_DECLARE(char *) ftdm_api_execute(const char *type, const char *cmd);
 FT_DECLARE(int) ftdm_vasprintf(char **ret, const char *fmt, va_list ap);
 FT_DECLARE(ftdm_status_t) ftdm_channel_set_caller_data(ftdm_channel_t *ftdmchan, ftdm_caller_data_t *caller_data);
+FT_DECLARE(void) ftdm_cpu_monitor_disable(void);
 
 FIO_CODEC_FUNCTION(fio_slin2ulaw);
 FIO_CODEC_FUNCTION(fio_ulaw2slin);

Added: freeswitch/trunk/libs/freetdm/src/include/ftdm_cpu_monitor.h (0 => 17216)


--- freeswitch/trunk/libs/freetdm/src/include/ftdm_cpu_monitor.h	                        (rev 0)
+++ freeswitch/trunk/libs/freetdm/src/include/ftdm_cpu_monitor.h	2010-04-05 21:49:43 UTC (rev 17216)
@@ -0,0 +1,75 @@
+/* 
+ * Copyright (c) 2010, Sangoma Technologies
+ * Moises Silva <moy@sangoma.com>
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 
+ * * Neither the name of the original author; nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * 
+ * Contributors:
+ * David Yat Sin <dyatsin@sangoma.com>
+ * 
+ */
+
+/*! \brief opaque cpu stats structure */
+struct ftdm_cpu_monitor_stats;
+
+/*! 
+ * \brief create a new cpu monitor
+ * \return profile timer structure previously created with new_profile_timer, NULL on error
+ */
+FT_DECLARE(struct ftdm_cpu_monitor_stats*) ftdm_new_cpu_monitor(void);
+
+/*! 
+ * \brief Deletes cpu_monitor
+ */
+FT_DECLARE(void) ftdm_delete_cpu_monitor(struct ftdm_cpu_monitor_stats *p);
+
+/*! 
+ * \brief provides the percentage of idle system time
+ * \param p cpu_stats structure previously created with ftdm_new_cpu_monitor
+ * \param pointer to store the percentage of idle time
+ * \return -1 on error 0 for success
+ */
+FT_DECLARE(ftdm_status_t) ftdm_cpu_get_system_idle_time (struct ftdm_cpu_monitor_stats *p, double *idle_percentage);
+
+
+
+
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4:
+ */