[Freeswitch-svn] [commit] r5784 - in freeswitch/trunk: . src src/include src/include/private src/mod/applications/mod_fifo src/mod/endpoints/mod_alsa src/mod/endpoints/mod_dingaling src/mod/endpoints/mod_portaudio src/mod/endpoints/mod_sofia src/mod/say/mod_say_en src/mod/timers/mod_softtimer

Freeswitch SVN anthm at freeswitch.org
Wed Oct 3 12:44:11 EDT 2007


Author: anthm
Date: Wed Oct  3 12:44:11 2007
New Revision: 5784

Added:
   freeswitch/trunk/src/softtimer.c
Removed:
   freeswitch/trunk/src/mod/timers/mod_softtimer/
Modified:
   freeswitch/trunk/Makefile.am
   freeswitch/trunk/src/include/private/switch_core_pvt.h
   freeswitch/trunk/src/include/switch_core.h
   freeswitch/trunk/src/include/switch_loadable_module.h
   freeswitch/trunk/src/mod/applications/mod_fifo/mod_fifo.c
   freeswitch/trunk/src/mod/endpoints/mod_alsa/mod_alsa.c
   freeswitch/trunk/src/mod/endpoints/mod_dingaling/mod_dingaling.c
   freeswitch/trunk/src/mod/endpoints/mod_portaudio/mod_portaudio.c
   freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c
   freeswitch/trunk/src/mod/say/mod_say_en/mod_say_en.c
   freeswitch/trunk/src/switch_channel.c
   freeswitch/trunk/src/switch_console.c
   freeswitch/trunk/src/switch_core.c
   freeswitch/trunk/src/switch_core_session.c
   freeswitch/trunk/src/switch_event.c
   freeswitch/trunk/src/switch_loadable_module.c
   freeswitch/trunk/src/switch_log.c
   freeswitch/trunk/src/switch_scheduler.c
   freeswitch/trunk/src/switch_stun.c

Log:
add softtimer to the core, begin framework for static modules and reduces calls to gettimeofday for timestamps

Modified: freeswitch/trunk/Makefile.am
==============================================================================
--- freeswitch/trunk/Makefile.am	(original)
+++ freeswitch/trunk/Makefile.am	Wed Oct  3 12:44:11 2007
@@ -53,6 +53,7 @@
 src/switch_stun.c\
 src/switch_log.c\
 src/switch_xml.c\
+src/softtimer.c\
 libs/stfu/stfu.c\
 src/switch_cpp.cpp\
 libs/libteletone/src/libteletone_detect.c\

Modified: freeswitch/trunk/src/include/private/switch_core_pvt.h
==============================================================================
--- freeswitch/trunk/src/include/private/switch_core_pvt.h	(original)
+++ freeswitch/trunk/src/include/private/switch_core_pvt.h	Wed Oct  3 12:44:11 2007
@@ -152,6 +152,10 @@
 	uint8_t running;
 	char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];
 	uint32_t flags;
+	switch_time_t timestamp;
+	switch_mutex_t *throttle_mutex;
+	uint32_t sps_total;
+	int32_t sps;
 };
 
 extern struct switch_runtime runtime;

Modified: freeswitch/trunk/src/include/switch_core.h
==============================================================================
--- freeswitch/trunk/src/include/switch_core.h	(original)
+++ freeswitch/trunk/src/include/switch_core.h	Wed Oct  3 12:44:11 2007
@@ -253,6 +253,13 @@
 SWITCH_DECLARE(uint32_t) switch_core_session_limit(uint32_t new_limit);
 
 /*! 
+  \brief Set/Get Session Rate Limit
+  \param new_limit new value (if > 0)
+  \return the current session rate limit
+*/
+SWITCH_DECLARE(uint32_t) switch_core_sessions_per_second(uint32_t new_limit);
+
+/*! 
   \brief Destroy the core
   \note to be called at application shutdown
 */
@@ -1464,6 +1471,7 @@
 
 SWITCH_DECLARE(switch_loadable_module_interface_t *) switch_loadable_module_create_module_interface(switch_memory_pool_t *pool, const char *name);
 SWITCH_DECLARE(void *) switch_loadable_module_create_interface(switch_loadable_module_interface_t *mod, switch_module_interface_name_t iname);
+SWITCH_DECLARE(switch_time_t) switch_timestamp_now(void);
 ///\}
 
 /*!

Modified: freeswitch/trunk/src/include/switch_loadable_module.h
==============================================================================
--- freeswitch/trunk/src/include/switch_loadable_module.h	(original)
+++ freeswitch/trunk/src/include/switch_loadable_module.h	Wed Oct  3 12:44:11 2007
@@ -120,13 +120,16 @@
   \param switch_module_load the function to call when the module is loaded
   \param switch_module_runtime a function requested to be started in it's own thread once loaded
   \param switch_module_shutdown the function to call when the system is shutdown
+  \param runtime start the runtime thread or not
   \return the resulting status
   \note only use this function if you are making a module that in turn gateways module loading to another technology
  */
 SWITCH_DECLARE(switch_status_t) switch_loadable_module_build_dynamic(char *filename,
 																	 switch_module_load_t switch_module_load,
 																	 switch_module_runtime_t switch_module_runtime,
-																	 switch_module_shutdown_t switch_module_shutdown);
+																	 switch_module_shutdown_t switch_module_shutdown,
+																	 switch_bool_t runtime);
+																	 
 
 /*!
   \brief Retrieve the timer interface by it's registered name
@@ -312,6 +315,11 @@
 
 ///\}
 
+#define SWITCH_DECLARE_STATIC_MODULE(init, load, run, shut) void init(void) { \
+		switch_loadable_module_build_dynamic(__FILE__, load, run, shut, SWITCH_FALSE); \
+	}
+
+
 SWITCH_END_EXTERN_C
 #endif
 /* For Emacs:

Modified: freeswitch/trunk/src/mod/applications/mod_fifo/mod_fifo.c
==============================================================================
--- freeswitch/trunk/src/mod/applications/mod_fifo/mod_fifo.c	(original)
+++ freeswitch/trunk/src/mod/applications/mod_fifo/mod_fifo.c	Wed Oct  3 12:44:11 2007
@@ -112,7 +112,7 @@
     switch_event_t *event = NULL;
     char date[80] = "";
     switch_time_exp_t tm;
-    switch_time_t ts = switch_time_now();
+    switch_time_t ts = switch_timestamp_now();
     switch_size_t retsize;
 
 
@@ -181,6 +181,7 @@
         switch_queue_push(node->fifo, uuid);
         switch_mutex_unlock(node->mutex);
 
+        ts = switch_timestamp_now();
         switch_time_exp_lt(&tm, ts);
         switch_strftime(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm);
         switch_channel_set_variable(channel, "fifo_status", "WAITING");
@@ -208,7 +209,7 @@
         if (switch_channel_ready(channel)) {
             switch_channel_set_state(channel, CS_HIBERNATE);            
         } else {
-
+            ts = switch_timestamp_now();
             switch_time_exp_lt(&tm, ts);
             switch_strftime(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm);
             switch_channel_set_variable(channel, "fifo_status", "ABORTED");
@@ -263,7 +264,7 @@
             switch_event_fire(&event);
         }
 
-
+        ts = switch_timestamp_now();
         switch_time_exp_lt(&tm, ts);
         switch_strftime(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm);
         switch_channel_set_variable(channel, "fifo_status", "WAITING");
@@ -344,6 +345,7 @@
                 assert(cloned_profile->next == NULL);
                 switch_channel_set_originatee_caller_profile(channel, cloned_profile);
 				
+                ts = switch_timestamp_now();
                 switch_time_exp_lt(&tm, ts);
                 switch_strftime(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm);
                 switch_channel_set_variable(channel, "fifo_status", "TALKING");
@@ -355,6 +357,7 @@
                 switch_channel_set_variable(other_channel, "fifo_target", switch_core_session_get_uuid(session));
                 switch_ivr_multi_threaded_bridge(session, other_session, on_dtmf, other_session, session);
 
+                ts = switch_timestamp_now();
                 switch_time_exp_lt(&tm, ts);
                 switch_strftime(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm);
                 switch_channel_set_variable(channel, "fifo_status", "WAITING");

Modified: freeswitch/trunk/src/mod/endpoints/mod_alsa/mod_alsa.c
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_alsa/mod_alsa.c	(original)
+++ freeswitch/trunk/src/mod/endpoints/mod_alsa/mod_alsa.c	Wed Oct  3 12:44:11 2007
@@ -180,7 +180,7 @@
 	assert(channel != NULL);
 
 
-	last = switch_time_now() - waitsec;
+	last = switch_timestamp_now() - waitsec;
 
 
 
@@ -243,7 +243,7 @@
 		switch_channel_mark_ring_ready(channel);
 
 		while (switch_channel_get_state(channel) == CS_INIT && !switch_test_flag(tech_pvt, TFLAG_ANSWER)) {
-			if (switch_time_now() - last >= waitsec) {
+			if (switch_timestamp_now() - last >= waitsec) {
 				char buf[512];
 				switch_event_t *event;
 
@@ -257,7 +257,7 @@
 				}
 
 				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s\n", buf);
-				last = switch_time_now();
+				last = switch_timestamp_now();
 				if (ring_file) {
 					unsigned int pos = 0;
 					switch_core_file_seek(&fh, &pos, 0, SEEK_SET);

Modified: freeswitch/trunk/src/mod/endpoints/mod_dingaling/mod_dingaling.c
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_dingaling/mod_dingaling.c	(original)
+++ freeswitch/trunk/src/mod/endpoints/mod_dingaling/mod_dingaling.c	Wed Oct  3 12:44:11 2007
@@ -1061,18 +1061,18 @@
 
 	switch_set_flag_locked(tech_pvt, TFLAG_IO);
 
-	started = switch_time_now();
+	started = switch_timestamp_now();
 
 	/* jingle has no ringing indication so we will just pretend that we got one */
 	switch_core_session_queue_indication(session, SWITCH_MESSAGE_INDICATE_RINGING);
 	switch_channel_mark_ring_ready(channel);
 
 	if (switch_test_flag(tech_pvt, TFLAG_OUTBOUND)) {
-		tech_pvt->next_cand = switch_time_now() + DL_CAND_WAIT;
-		tech_pvt->next_desc = switch_time_now();
+		tech_pvt->next_cand = started + DL_CAND_WAIT;
+		tech_pvt->next_desc = started;
 	} else {
-		tech_pvt->next_cand = switch_time_now() + DL_CAND_WAIT;
-		tech_pvt->next_desc = switch_time_now() + DL_CAND_WAIT;
+		tech_pvt->next_cand = started + DL_CAND_WAIT;
+		tech_pvt->next_desc = started + DL_CAND_WAIT;
 	}
 
 	while (!(switch_test_flag(tech_pvt, TFLAG_CODEC_READY) &&
@@ -1080,7 +1080,7 @@
 			 switch_test_flag(tech_pvt, TFLAG_ANSWER) && switch_test_flag(tech_pvt, TFLAG_TRANSPORT_ACCEPT) &&
 			 tech_pvt->remote_ip && tech_pvt->remote_port
 			 && switch_test_flag(tech_pvt, TFLAG_TRANSPORT))) {
-		now = switch_time_now();
+		now = switch_timestamp_now();
 		elapsed = (unsigned int) ((now - started) / 1000);
 
 		if (switch_channel_get_state(channel) >= CS_HANGUP || switch_test_flag(tech_pvt, TFLAG_BYE)) {
@@ -1365,7 +1365,7 @@
 
 #if 0
 	if (tech_pvt->last_read) {
-		elapsed = (unsigned int) ((switch_time_now() - tech_pvt->last_read) / 1000);
+		elapsed = (unsigned int) ((switch_timestamp_now() - tech_pvt->last_read) / 1000);
 		if (elapsed > 60000) {
 			return SWITCH_STATUS_TIMEOUT;
 		}
@@ -1393,7 +1393,7 @@
 			payload = tech_pvt->read_frame.payload;
 
 #if 0
-			elapsed = (unsigned int) ((switch_time_now() - started) / 1000);
+			elapsed = (unsigned int) ((switch_timestamp_now() - started) / 1000);
 
 			if (timeout > -1) {
 				if (elapsed >= (unsigned int) timeout) {
@@ -1401,7 +1401,7 @@
 				}
 			}
 
-			elapsed = (unsigned int) ((switch_time_now() - last_act) / 1000);
+			elapsed = (unsigned int) ((switch_timestamp_now() - last_act) / 1000);
 			if (elapsed >= hard_timeout) {
 				return SWITCH_STATUS_BREAK;
 			}

Modified: freeswitch/trunk/src/mod/endpoints/mod_portaudio/mod_portaudio.c
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_portaudio/mod_portaudio.c	(original)
+++ freeswitch/trunk/src/mod/endpoints/mod_portaudio/mod_portaudio.c	Wed Oct  3 12:44:11 2007
@@ -179,7 +179,7 @@
 	assert(channel != NULL);
 
 
-	last = switch_time_now() - waitsec;
+	last = switch_timestamp_now() - waitsec;
 
 
 
@@ -244,7 +244,7 @@
 		while (switch_channel_get_state(channel) == CS_INIT && !switch_test_flag(tech_pvt, TFLAG_ANSWER)) {
 			switch_size_t olen = globals.timer.samples;
 				
-			if (switch_time_now() - last >= waitsec) {
+			if (switch_timestamp_now() - last >= waitsec) {
 				char buf[512];
 				switch_event_t *event;
 
@@ -257,7 +257,7 @@
 					switch_event_fire(&event);
 				}
 				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s\n", buf);
-				last = switch_time_now();
+				last = switch_timestamp_now();
 			}
 			
 			if (ring_file) {

Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c	(original)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c	Wed Oct  3 12:44:11 2007
@@ -1832,8 +1832,7 @@
 	}
 	
 	if (!sofia_endpoint_interface || !(session = switch_core_session_request(sofia_endpoint_interface, NULL))) {
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Session Alloc Failed!\n");
-		nua_respond(nh, SIP_503_SERVICE_UNAVAILABLE, TAG_END());
+		nua_respond(nh, SIP_486_BUSY_HERE, TAG_END());
 		return;
 	}
 

Modified: freeswitch/trunk/src/mod/say/mod_say_en/mod_say_en.c
==============================================================================
--- freeswitch/trunk/src/mod/say/mod_say_en/mod_say_en.c	(original)
+++ freeswitch/trunk/src/mod/say/mod_say_en/mod_say_en.c	Wed Oct  3 12:44:11 2007
@@ -346,7 +346,7 @@
 	if ((t = atoi(tosay)) > 0) {
 		target = switch_time_make(t, 0);
 	} else {
-		target = switch_time_now();
+		target = switch_timestamp_now();
 	}
 	switch_time_exp_lt(&tm, target);
 

Added: freeswitch/trunk/src/softtimer.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/src/softtimer.c	Wed Oct  3 12:44:11 2007
@@ -0,0 +1,311 @@
+/* 
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005/2006, Anthony Minessale II <anthmct at yahoo.com>
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ *
+ * The Initial Developer of the Original Code is
+ * Anthony Minessale II <anthmct at yahoo.com>
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * 
+ * Anthony Minessale II <anthmct at yahoo.com>
+ *
+ *
+ * softtimer.c -- Software Timer Module
+ *
+ */
+#include <switch.h>
+#include <stdio.h>
+#include "private/switch_core_pvt.h"
+
+#ifndef UINT32_MAX
+#define UINT32_MAX 0xffffffff
+#endif
+
+#define MAX_TICK UINT32_MAX - 1024
+
+struct switch_runtime runtime;
+static switch_memory_pool_t *module_pool = NULL;
+
+static struct {
+	int32_t RUNNING;
+	int32_t STARTED;
+	switch_mutex_t *mutex;
+} globals;
+
+SWITCH_MODULE_LOAD_FUNCTION(softtimer_load);
+SWITCH_MODULE_SHUTDOWN_FUNCTION(softtimer_shutdown);
+SWITCH_MODULE_RUNTIME_FUNCTION(softtimer_runtime);
+SWITCH_MODULE_DEFINITION(softtimer, softtimer_load, softtimer_shutdown, softtimer_runtime);
+
+#define MAX_ELEMENTS 1000
+
+struct timer_private {
+	switch_size_t reference;
+	switch_size_t start;
+	uint32_t roll;
+	uint32_t ready;
+};
+typedef struct timer_private timer_private_t;
+
+struct timer_matrix {
+	switch_size_t tick;
+	uint32_t count;
+	uint32_t roll;
+};
+typedef struct timer_matrix timer_matrix_t;
+
+static timer_matrix_t TIMER_MATRIX[MAX_ELEMENTS + 1];
+
+#define IDLE_SPEED 100
+
+
+static switch_status_t timer_init(switch_timer_t *timer)
+{
+	timer_private_t *private_info;
+	int sanity = 0;
+
+	while(globals.STARTED == 0) {
+		switch_yield(100000);
+		if (++sanity == 10) {
+			break;
+		}
+	}
+
+	if (globals.RUNNING != 1 || !globals.mutex) {
+		return SWITCH_STATUS_FALSE;
+	}
+
+	if ((private_info = switch_core_alloc(timer->memory_pool, sizeof(*private_info)))) {
+		switch_mutex_lock(globals.mutex);
+		TIMER_MATRIX[timer->interval].count++;
+		switch_mutex_unlock(globals.mutex);
+		timer->private_info = private_info;
+		private_info->start = private_info->reference = TIMER_MATRIX[timer->interval].tick;
+		private_info->roll = TIMER_MATRIX[timer->interval].roll;
+		private_info->ready = 1;
+		return SWITCH_STATUS_SUCCESS;
+	}
+
+	return SWITCH_STATUS_MEMERR;
+}
+
+
+#define check_roll() if (private_info->roll < TIMER_MATRIX[timer->interval].roll) {\
+		private_info->roll++;\
+		private_info->reference = private_info->start = TIMER_MATRIX[timer->interval].tick;\
+	}\
+
+
+
+static switch_status_t timer_step(switch_timer_t *timer)
+{
+	timer_private_t *private_info = timer->private_info;
+	uint64_t samples;
+
+	if (globals.RUNNING != 1 || private_info->ready == 0) {
+		return SWITCH_STATUS_FALSE;
+	}
+
+	check_roll();
+	samples = timer->samples * (private_info->reference - private_info->start);
+
+	if (samples > UINT32_MAX) {
+		private_info->start = private_info->reference;
+		samples = timer->samples;
+	}
+
+	timer->samplecount = (uint32_t) samples;
+	private_info->reference++;
+
+	return SWITCH_STATUS_SUCCESS;
+}
+
+
+static switch_status_t timer_next(switch_timer_t *timer)
+{
+	timer_private_t *private_info = timer->private_info;
+
+	timer_step(timer);
+
+	while (globals.RUNNING == 1 && private_info->ready && TIMER_MATRIX[timer->interval].tick < private_info->reference) {
+		check_roll();
+		switch_yield(1000);
+	}
+
+	if (globals.RUNNING == 1) {
+		return SWITCH_STATUS_SUCCESS;
+	}
+
+	return SWITCH_STATUS_FALSE;
+}
+
+static switch_status_t timer_check(switch_timer_t *timer)
+{
+	timer_private_t *private_info = timer->private_info;
+	switch_status_t status = SWITCH_STATUS_SUCCESS;
+	switch_size_t diff;
+
+	if (globals.RUNNING != 1 || !private_info->ready) {
+		return SWITCH_STATUS_SUCCESS;
+	}
+
+	check_roll();
+
+	if (TIMER_MATRIX[timer->interval].tick < private_info->reference) {
+		diff = private_info->reference - TIMER_MATRIX[timer->interval].tick;
+	} else {
+		diff = 0;
+	}
+
+	if (diff) {
+		status = SWITCH_STATUS_FALSE;
+	} else {
+		timer_step(timer);
+	}
+
+	return status;
+}
+
+
+static switch_status_t timer_destroy(switch_timer_t *timer)
+{
+	timer_private_t *private_info = timer->private_info;
+	switch_mutex_lock(globals.mutex);
+	TIMER_MATRIX[timer->interval].count--;
+	if (TIMER_MATRIX[timer->interval].count == 0) {
+		TIMER_MATRIX[timer->interval].tick = 0;
+	}
+	switch_mutex_unlock(globals.mutex);
+	private_info->ready = 0;
+	return SWITCH_STATUS_SUCCESS;
+}
+
+
+#define STEP_MS 1
+#define STEP_MIC 1000
+
+SWITCH_MODULE_RUNTIME_FUNCTION(softtimer_runtime)
+{
+	switch_time_t reference = switch_time_now();
+	uint32_t current_ms = 0;
+	uint32_t x, tick = 0;
+	switch_time_t ts = 0;
+	
+	memset(&globals, 0, sizeof(globals));
+	switch_mutex_init(&globals.mutex, SWITCH_MUTEX_NESTED, module_pool);
+	
+	globals.STARTED = globals.RUNNING = 1;
+	switch_mutex_lock(runtime.throttle_mutex);
+	runtime.sps = runtime.sps_total;
+	switch_mutex_unlock(runtime.throttle_mutex);
+
+	while (globals.RUNNING == 1) {
+		reference += STEP_MIC;
+		while ((ts = switch_time_now()) < reference) {
+			switch_yield(STEP_MIC);
+		}
+		runtime.timestamp = ts;
+		current_ms += STEP_MS;
+		tick += STEP_MS;
+
+		if (tick >= 1000) {
+			if (runtime.sps <= 0) {
+				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Over Session Rate of %d!\n", runtime.sps_total);
+			}
+			switch_mutex_lock(runtime.throttle_mutex);
+			runtime.sps = runtime.sps_total;
+			switch_mutex_unlock(runtime.throttle_mutex);
+			tick = 0;
+		}
+
+		for (x = 0; x < MAX_ELEMENTS; x++) {
+			int i = x, index;
+			if (i == 0) {
+				i = 1;
+			}
+
+			index = (current_ms % i == 0) ? i : 0;
+
+			if (TIMER_MATRIX[index].count) {
+				TIMER_MATRIX[index].tick++;
+				if (TIMER_MATRIX[index].tick == MAX_TICK) {
+					TIMER_MATRIX[index].tick = 0;
+					TIMER_MATRIX[index].roll++;
+				}
+			}
+		}
+
+		if (current_ms == MAX_ELEMENTS) {
+			current_ms = 0;
+		}
+	}
+
+	switch_mutex_lock(globals.mutex);
+	globals.RUNNING = 0;
+	switch_mutex_unlock(globals.mutex);
+
+	return SWITCH_STATUS_TERM;
+}
+
+
+SWITCH_MODULE_LOAD_FUNCTION(softtimer_load)
+{
+	switch_timer_interface_t *timer_interface;
+	module_pool = pool;
+
+	/* connect my internal structure to the blank pointer passed to me */
+	*module_interface = switch_loadable_module_create_module_interface(pool, modname);
+	timer_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_TIMER_INTERFACE);
+	timer_interface->interface_name = "soft";
+	timer_interface->timer_init = timer_init;
+	timer_interface->timer_next = timer_next;
+	timer_interface->timer_step = timer_step;
+	timer_interface->timer_check = timer_check;
+	timer_interface->timer_destroy = timer_destroy;
+
+	/* indicate that the module should continue to be loaded */
+	return SWITCH_STATUS_SUCCESS;
+}
+
+SWITCH_MODULE_SHUTDOWN_FUNCTION(softtimer_shutdown)
+{
+
+	if (globals.RUNNING) {
+		switch_mutex_lock(globals.mutex);
+		globals.RUNNING = -1;
+		switch_mutex_unlock(globals.mutex);
+
+		while (globals.RUNNING) {
+			switch_yield(10000);
+		}
+	}
+	switch_core_destroy_memory_pool(&module_pool);
+	return SWITCH_STATUS_SUCCESS;
+}
+
+/* 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 expandtab:
+ */

Modified: freeswitch/trunk/src/switch_channel.c
==============================================================================
--- freeswitch/trunk/src/switch_channel.c	(original)
+++ freeswitch/trunk/src/switch_channel.c	Wed Oct  3 12:44:11 2007
@@ -855,7 +855,7 @@
 	caller_profile->times->created = switch_time_now();
 
 	if (channel->caller_profile && channel->caller_profile->times) {
-		channel->caller_profile->times->transferred = switch_time_now();
+		channel->caller_profile->times->transferred = caller_profile->times->created;
 		caller_profile->times->answered = channel->caller_profile->times->answered;
 	}
 

Modified: freeswitch/trunk/src/switch_console.c
==============================================================================
--- freeswitch/trunk/src/switch_console.c	(original)
+++ freeswitch/trunk/src/switch_console.c	Wed Oct  3 12:44:11 2007
@@ -151,7 +151,7 @@
 			switch_size_t retsize;
 			switch_time_exp_t tm;
 			switch_event_t *event;
-			switch_time_exp_lt(&tm, switch_time_now());
+			switch_time_exp_lt(&tm, switch_timestamp_now());
 			switch_strftime(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm);
 
 			if (channel == SWITCH_CHANNEL_ID_LOG) {

Modified: freeswitch/trunk/src/switch_core.c
==============================================================================
--- freeswitch/trunk/src/switch_core.c	(original)
+++ freeswitch/trunk/src/switch_core.c	Wed Oct  3 12:44:11 2007
@@ -79,6 +79,10 @@
 	task->runtime = time(NULL) + 20;
 }
 
+SWITCH_DECLARE(switch_time_t) switch_timestamp_now(void)
+{
+	return runtime.timestamp ? runtime.timestamp : switch_time_now();
+}
 
 SWITCH_DECLARE(switch_status_t) switch_core_set_console(const char *console)
 {
@@ -413,12 +417,12 @@
 		return SWITCH_STATUS_MEMERR;
 	}
 	assert(runtime.memory_pool != NULL);
-
+	switch_mutex_init(&runtime.throttle_mutex, SWITCH_MUTEX_NESTED, runtime.memory_pool);
 	switch_core_set_globals();
 	switch_core_session_init(runtime.memory_pool);
 	switch_core_hash_init(&runtime.global_vars, runtime.memory_pool);
 	runtime.flags = flags;
-
+	runtime.sps_total = 30;
 
 	if (switch_xml_init(runtime.memory_pool, err) != SWITCH_STATUS_SUCCESS) {
 		apr_terminate();
@@ -438,6 +442,8 @@
 					if (switch_true(val)) {
 						switch_set_flag((&runtime), SCF_CRASH_PROT);
 					}
+				} else if (!strcasecmp(var, "sessions-per-second")) {
+					switch_core_sessions_per_second(atoi(val));
 				} else if (!strcasecmp(var, "max-sessions")) {
 					switch_core_session_limit(atoi(val));
 				}
@@ -582,9 +588,10 @@
 	}
 
 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE,
-					  "\nFreeSWITCH Version %s Started.\nCrash Protection [%s]\nMax Sessions[%u]\nSQL [%s]\n", SWITCH_VERSION_FULL, 
+					  "\nFreeSWITCH Version %s Started.\nCrash Protection [%s]\nMax Sessions[%u]\nSession Rate[%d]\nSQL [%s]\n", SWITCH_VERSION_FULL, 
 					  switch_test_flag((&runtime), SCF_CRASH_PROT) ? "Enabled" : "Disabled",
 					  switch_core_session_limit(0),
+					  switch_core_sessions_per_second(0),
 					  switch_test_flag((&runtime), SCF_USE_SQL) ? "Enabled" : "Disabled"
 					  );
 

Modified: freeswitch/trunk/src/switch_core_session.c
==============================================================================
--- freeswitch/trunk/src/switch_core_session.c	(original)
+++ freeswitch/trunk/src/switch_core_session.c	Wed Oct  3 12:44:11 2007
@@ -37,7 +37,6 @@
 static struct {
 	switch_memory_pool_t *memory_pool;
 	switch_hash_t *session_table;
-	switch_mutex_t *session_table_mutex;
 	uint32_t session_count;
 	uint32_t session_limit;
 	switch_size_t session_id;
@@ -53,7 +52,7 @@
 	switch_core_session_t *session = NULL;
 
 	if (uuid_str) {
-		switch_mutex_lock(session_manager.session_table_mutex);
+		switch_mutex_lock(runtime.throttle_mutex);
 		if ((session = switch_core_hash_find(session_manager.session_table, uuid_str))) {
 			/* Acquire a read lock on the session */
 #ifdef SWITCH_DEBUG_RWLOCKS
@@ -65,7 +64,7 @@
 				session = NULL;
 			}
 		}
-		switch_mutex_unlock(session_manager.session_table_mutex);
+		switch_mutex_unlock(runtime.throttle_mutex);
 	}
 
 	/* if its not NULL, now it's up to you to rwunlock this */
@@ -80,7 +79,7 @@
 	switch_channel_t *channel;
 	uint32_t loops = 0;
 
-	switch_mutex_lock(session_manager.session_table_mutex);
+	switch_mutex_lock(runtime.throttle_mutex);
 	for (hi = switch_hash_first(NULL, session_manager.session_table); hi; hi = switch_hash_next(hi)) {
 		switch_hash_this(hi, NULL, NULL, &val);
 		if (val) {
@@ -90,7 +89,7 @@
 			switch_core_session_kill_channel(session, SWITCH_SIG_KILL);
 		}
 	}
-	switch_mutex_unlock(session_manager.session_table_mutex);
+	switch_mutex_unlock(runtime.throttle_mutex);
 
 	while (session_manager.session_count > 0) {
 		switch_yield(100000);
@@ -107,7 +106,7 @@
 	switch_core_session_t *session = NULL;
 	switch_status_t status = SWITCH_STATUS_FALSE;
 
-	switch_mutex_lock(session_manager.session_table_mutex);
+	switch_mutex_lock(runtime.throttle_mutex);
 	if ((session = switch_core_hash_find(session_manager.session_table, uuid_str)) != 0) {
 		/* Acquire a read lock on the session or forget it the channel is dead */
 		if (switch_core_session_read_lock(session) == SWITCH_STATUS_SUCCESS) {
@@ -117,7 +116,7 @@
 			switch_core_session_rwunlock(session);
 		}
 	}
-	switch_mutex_unlock(session_manager.session_table_mutex);
+	switch_mutex_unlock(runtime.throttle_mutex);
 
 	return status;
 }
@@ -127,7 +126,7 @@
 	switch_core_session_t *session = NULL;
 	switch_status_t status = SWITCH_STATUS_FALSE;
 
-	switch_mutex_lock(session_manager.session_table_mutex);
+	switch_mutex_lock(runtime.throttle_mutex);
 	if ((session = switch_core_hash_find(session_manager.session_table, uuid_str)) != 0) {
 		/* Acquire a read lock on the session or forget it the channel is dead */
 		if (switch_core_session_read_lock(session) == SWITCH_STATUS_SUCCESS) {
@@ -137,7 +136,7 @@
 			switch_core_session_rwunlock(session);
 		}
 	}
-	switch_mutex_unlock(session_manager.session_table_mutex);
+	switch_mutex_unlock(runtime.throttle_mutex);
 
 	return status;
 }
@@ -645,12 +644,12 @@
 	
 	switch_scheduler_del_task_group((*session)->uuid_str);
 
-	switch_mutex_lock(session_manager.session_table_mutex);
+	switch_mutex_lock(runtime.throttle_mutex);
 	switch_core_hash_delete(session_manager.session_table, (*session)->uuid_str);
 	if (session_manager.session_count) {
 		session_manager.session_count--;
 	}
-	switch_mutex_unlock(session_manager.session_table_mutex);
+	switch_mutex_unlock(runtime.throttle_mutex);
 
 	if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_DESTROY) == SWITCH_STATUS_SUCCESS) {
 		switch_channel_event_set_data((*session)->channel, event);
@@ -744,18 +743,25 @@
 	switch_core_session_t *session;
 	switch_uuid_t uuid;
 	uint32_t count = 0;
+	int32_t sps = 0;
 
 	if (!switch_core_ready() || endpoint_interface == NULL) {
 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "The system cannot create any sessions at this time.\n");
 		return NULL;
 	}
 
-	switch_mutex_lock(session_manager.session_table_mutex);
+	switch_mutex_lock(runtime.throttle_mutex);
 	count = session_manager.session_count;
-	switch_mutex_unlock(session_manager.session_table_mutex);
+	sps = --runtime.sps;
+	switch_mutex_unlock(runtime.throttle_mutex);
+	
+	if (sps <= 0) {
+		//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Throttle Error!\n");
+		return NULL;
+	}
 
 	if ((count + 1) > session_manager.session_limit) {
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Over Session Limit!\n");
+		//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Over Session Limit!\n");
 		return NULL;
 	}
 
@@ -779,6 +785,7 @@
 		return NULL;
 	}
 
+
 	switch_channel_init(session->channel, session, CS_NEW, 0);
 
 	/* The session *IS* the pool you may not alter it because you have no idea how
@@ -810,11 +817,11 @@
 	switch_queue_create(&session->private_event_queue, SWITCH_EVENT_QUEUE_LEN, session->pool);
 
 	snprintf(session->name, sizeof(session->name), "%"SWITCH_SIZE_T_FMT, session->id);
-	switch_mutex_lock(session_manager.session_table_mutex);
+	switch_mutex_lock(runtime.throttle_mutex);
 	session->id = session_manager.session_id++;
 	switch_core_hash_insert(session_manager.session_table, session->uuid_str, session);
 	session_manager.session_count++;
-	switch_mutex_unlock(session_manager.session_table_mutex);
+	switch_mutex_unlock(runtime.throttle_mutex);
 
 	return session;
 }
@@ -871,6 +878,15 @@
 	return session_manager.session_limit;
 }
 
+SWITCH_DECLARE(uint32_t) switch_core_sessions_per_second(uint32_t new_limit)
+{
+	if (new_limit) {
+		runtime.sps_total = new_limit;
+	}
+
+	return runtime.sps_total;
+}
+
 
 void switch_core_session_init(switch_memory_pool_t *pool)
 {
@@ -879,7 +895,6 @@
 	session_manager.session_id = 1;
 	session_manager.memory_pool = pool;
 	switch_core_hash_init(&session_manager.session_table, session_manager.memory_pool);
-	switch_mutex_init(&session_manager.session_table_mutex, SWITCH_MUTEX_NESTED, session_manager.memory_pool);
 }
 
 void switch_core_session_uninit(void)

Modified: freeswitch/trunk/src/switch_event.c
==============================================================================
--- freeswitch/trunk/src/switch_event.c	(original)
+++ freeswitch/trunk/src/switch_event.c	Wed Oct  3 12:44:11 2007
@@ -870,7 +870,7 @@
 	switch_time_exp_t tm;
 	char date[80] = "";
 	switch_size_t retsize;
-	switch_time_t ts = switch_time_now();
+	switch_time_t ts = switch_timestamp_now();
 
 	assert(BLOCK != NULL);
 	assert(RUNTIME_POOL != NULL);

Modified: freeswitch/trunk/src/switch_loadable_module.c
==============================================================================
--- freeswitch/trunk/src/switch_loadable_module.c	(original)
+++ freeswitch/trunk/src/switch_loadable_module.c	Wed Oct  3 12:44:11 2007
@@ -655,14 +655,19 @@
 
 	assert(path != NULL);
 
+	switch_core_new_memory_pool(&pool);
 	*new_module = NULL;
-	status = switch_dso_load(&dso, path, loadable_modules.pool);
 
-	if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) {
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "OH OH no pool\n");
-		abort();
+	struct_name = switch_core_sprintf(pool, "%s_module_interface", filename);
+
+	status = switch_dso_load(&dso, NULL, loadable_modules.pool);
+	status = switch_dso_sym(&interface_struct_handle, dso, struct_name);
+
+	if (!interface_struct_handle) {
+		status = switch_dso_load(&dso, path, loadable_modules.pool);
 	}
 
+
 	while (loading) {
 		if (status != APR_SUCCESS) {
 			switch_dso_error(dso, derr, sizeof(derr));
@@ -670,8 +675,10 @@
 			break;
 		}
 
-		struct_name = switch_core_sprintf(pool, "%s_module_interface", filename);
-		status = switch_dso_sym(&interface_struct_handle, dso, struct_name);
+		if (!interface_struct_handle) {
+			status = switch_dso_sym(&interface_struct_handle, dso, struct_name);
+		}
+
 		if (interface_struct_handle) {
 			mod_interface_functions = interface_struct_handle;
 			load_func_ptr = mod_interface_functions->load;
@@ -822,7 +829,8 @@
 SWITCH_DECLARE(switch_status_t) switch_loadable_module_build_dynamic(char *filename,
 																	 switch_module_load_t switch_module_load,
 																	 switch_module_runtime_t switch_module_runtime,
-																	 switch_module_shutdown_t switch_module_shutdown)
+																	 switch_module_shutdown_t switch_module_shutdown,
+																	 switch_bool_t runtime)
 {
 	switch_loadable_module_t *module = NULL;
 	switch_module_load_t load_func_ptr = NULL;
@@ -890,7 +898,7 @@
 	if (switch_module_runtime) {
 		module->switch_module_runtime = switch_module_runtime;
 	}
-	if (module->switch_module_runtime) {
+	if (runtime && module->switch_module_runtime) {
 		switch_core_launch_thread(switch_loadable_module_exec, module, module->pool);
 	}
 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Successfully Loaded [%s]\n", module_interface->module_name);
@@ -962,6 +970,8 @@
 	switch_core_hash_init(&loadable_modules.dialplan_hash, loadable_modules.pool);
 	switch_mutex_init(&loadable_modules.mutex, SWITCH_MUTEX_NESTED, loadable_modules.pool);
 
+	switch_loadable_module_load_module("", "softtimer", SWITCH_FALSE, &err);
+
 	if ((xml = switch_xml_open_cfg(cf, &cfg, NULL))) {
 		switch_xml_t mods, ld;
 		if ((mods = switch_xml_child(cfg, "modules"))) {
@@ -1036,7 +1046,7 @@
 		}
 		apr_dir_close(module_dir_handle);
 	}
-
+	
 	switch_loadable_module_runtime();
 
 	return SWITCH_STATUS_SUCCESS;

Modified: freeswitch/trunk/src/switch_log.c
==============================================================================
--- freeswitch/trunk/src/switch_log.c	(original)
+++ freeswitch/trunk/src/switch_log.c	Wed Oct  3 12:44:11 2007
@@ -162,7 +162,7 @@
 	const char *filep = (file ? switch_cut_path(file) : "");
 	const char *funcp = (func ? func : "");
 	char *content = NULL;
-	switch_time_t now = switch_time_now();
+	switch_time_t now = switch_timestamp_now();
 	uint32_t len;
 	const char *extra_fmt = "%s [%s] %s:%d %s()%c%s";
 

Modified: freeswitch/trunk/src/switch_scheduler.c
==============================================================================
--- freeswitch/trunk/src/switch_scheduler.c	(original)
+++ freeswitch/trunk/src/switch_scheduler.c	Wed Oct  3 12:44:11 2007
@@ -1,5 +1,6 @@
 #include <switch.h>
 
+
 struct switch_scheduler_task_container {
 	switch_scheduler_task_t task;
 	int64_t executed;
@@ -71,6 +72,7 @@
 
 
 	switch_mutex_lock(globals.task_mutex);
+
 	for (tp = globals.task_list; tp; tp = tp->next) {
 		if (done) {
 			tp->destroyed = 1;

Modified: freeswitch/trunk/src/switch_stun.c
==============================================================================
--- freeswitch/trunk/src/switch_stun.c	(original)
+++ freeswitch/trunk/src/switch_stun.c	Wed Oct  3 12:44:11 2007
@@ -104,7 +104,7 @@
 
 	max = (int) strlen(set);
 
-	srand((unsigned int) switch_time_now());
+	srand((unsigned int) switch_timestamp_now());
 
 	for (x = 0; x < len; x++) {
 		int j = (int) (max * 1.0 * rand() / (RAND_MAX + 1.0));



More information about the Freeswitch-svn mailing list