From bd6bd9ad57ac3daf6a2a4d435f853953bf18a511 Mon Sep 17 00:00:00 2001 From: Anthony Minessale <anthony.minessale@gmail.com> Date: Wed, 3 Oct 2007 16:44:11 +0000 Subject: [PATCH] add softtimer to the core, begin framework for static modules and reduces calls to gettimeofday for timestamps git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@5784 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- Makefile.am | 1 + src/include/private/switch_core_pvt.h | 4 + src/include/switch_core.h | 8 + src/include/switch_loadable_module.h | 10 +- src/mod/applications/mod_fifo/mod_fifo.c | 9 +- src/mod/endpoints/mod_alsa/mod_alsa.c | 6 +- .../endpoints/mod_dingaling/mod_dingaling.c | 18 +- .../endpoints/mod_portaudio/mod_portaudio.c | 6 +- src/mod/endpoints/mod_sofia/sofia.c | 3 +- src/mod/say/mod_say_en/mod_say_en.c | 2 +- .../timers/mod_softtimer/mod_softtimer.vcproj | 210 ------------------ .../mod_softtimer.c => softtimer.c} | 87 +++++--- src/switch_channel.c | 2 +- src/switch_console.c | 2 +- src/switch_core.c | 13 +- src/switch_core_session.c | 49 ++-- src/switch_event.c | 2 +- src/switch_loadable_module.c | 28 ++- src/switch_log.c | 2 +- src/switch_scheduler.c | 2 + src/switch_stun.c | 2 +- 21 files changed, 163 insertions(+), 303 deletions(-) delete mode 100644 src/mod/timers/mod_softtimer/mod_softtimer.vcproj rename src/{mod/timers/mod_softtimer/mod_softtimer.c => softtimer.c} (85%) diff --git a/Makefile.am b/Makefile.am index bfc254e1c6..e28123e356 100644 --- a/Makefile.am +++ b/Makefile.am @@ -53,6 +53,7 @@ src/switch_ivr.c \ 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\ diff --git a/src/include/private/switch_core_pvt.h b/src/include/private/switch_core_pvt.h index b7c698f6a3..3992eb9e24 100644 --- a/src/include/private/switch_core_pvt.h +++ b/src/include/private/switch_core_pvt.h @@ -152,6 +152,10 @@ struct switch_runtime { 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; diff --git a/src/include/switch_core.h b/src/include/switch_core.h index f08cafa4f8..819f74e8c9 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -252,6 +252,13 @@ SWITCH_DECLARE(switch_status_t) switch_core_init_and_modload(const char *console */ 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(uint8_t) switch_core_session_compare(switch_core_session_t *a, sw 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); ///\} /*! diff --git a/src/include/switch_loadable_module.h b/src/include/switch_loadable_module.h index a38446fac4..7df9c4891e 100644 --- a/src/include/switch_loadable_module.h +++ b/src/include/switch_loadable_module.h @@ -120,13 +120,16 @@ SWITCH_DECLARE(switch_dialplan_interface_t *) switch_loadable_module_get_dialpla \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 @@ SWITCH_MOD_DECLARE(switch_status_t) switch_module_shutdown(void); ///\} +#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: diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index 5a26731a45..798ca166c1 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -112,7 +112,7 @@ SWITCH_STANDARD_APP(fifo_function) 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_STANDARD_APP(fifo_function) 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 @@ SWITCH_STANDARD_APP(fifo_function) 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_STANDARD_APP(fifo_function) 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 @@ SWITCH_STANDARD_APP(fifo_function) 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_STANDARD_APP(fifo_function) 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"); diff --git a/src/mod/endpoints/mod_alsa/mod_alsa.c b/src/mod/endpoints/mod_alsa/mod_alsa.c index 3d77e99310..51053a6e5f 100644 --- a/src/mod/endpoints/mod_alsa/mod_alsa.c +++ b/src/mod/endpoints/mod_alsa/mod_alsa.c @@ -180,7 +180,7 @@ static switch_status_t channel_on_init(switch_core_session_t *session) assert(channel != NULL); - last = switch_time_now() - waitsec; + last = switch_timestamp_now() - waitsec; @@ -243,7 +243,7 @@ static switch_status_t channel_on_init(switch_core_session_t *session) 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 @@ static switch_status_t channel_on_init(switch_core_session_t *session) } 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); diff --git a/src/mod/endpoints/mod_dingaling/mod_dingaling.c b/src/mod/endpoints/mod_dingaling/mod_dingaling.c index c3e1f2c383..266071245e 100644 --- a/src/mod/endpoints/mod_dingaling/mod_dingaling.c +++ b/src/mod/endpoints/mod_dingaling/mod_dingaling.c @@ -1061,18 +1061,18 @@ static switch_status_t negotiate_media(switch_core_session_t *session) 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 @@ static switch_status_t negotiate_media(switch_core_session_t *session) 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 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch #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 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch 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 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch } } - 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; } diff --git a/src/mod/endpoints/mod_portaudio/mod_portaudio.c b/src/mod/endpoints/mod_portaudio/mod_portaudio.c index f6df069639..800b0055f5 100644 --- a/src/mod/endpoints/mod_portaudio/mod_portaudio.c +++ b/src/mod/endpoints/mod_portaudio/mod_portaudio.c @@ -179,7 +179,7 @@ SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_dialplan, globals.dialplan) assert(channel != NULL); - last = switch_time_now() - waitsec; + last = switch_timestamp_now() - waitsec; @@ -244,7 +244,7 @@ SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_dialplan, globals.dialplan) 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_DECLARE_GLOBAL_STRING_FUNC(set_global_dialplan, globals.dialplan) 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) { diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 0f891317ea..2d19f1069c 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -1832,8 +1832,7 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_ } 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; } diff --git a/src/mod/say/mod_say_en/mod_say_en.c b/src/mod/say/mod_say_en/mod_say_en.c index f8a3ccfcf9..3ff8bbf690 100644 --- a/src/mod/say/mod_say_en/mod_say_en.c +++ b/src/mod/say/mod_say_en/mod_say_en.c @@ -346,7 +346,7 @@ static switch_status_t en_say_time(switch_core_session_t *session, char *tosay, 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); diff --git a/src/mod/timers/mod_softtimer/mod_softtimer.vcproj b/src/mod/timers/mod_softtimer/mod_softtimer.vcproj deleted file mode 100644 index 917b36441b..0000000000 --- a/src/mod/timers/mod_softtimer/mod_softtimer.vcproj +++ /dev/null @@ -1,210 +0,0 @@ -<?xml version="1.0" encoding="Windows-1252"?> -<VisualStudioProject - ProjectType="Visual C++" - Version="8.00" - Name="mod_softtimer" - ProjectGUID="{DCC13474-28DF-47CA-A8EB-72F8CE9A78C5}" - RootNamespace="mod_softtimer" - Keyword="Win32Proj" - > - <Platforms> - <Platform - Name="Win32" - /> - </Platforms> - <ToolFiles> - </ToolFiles> - <Configurations> - <Configuration - Name="Debug|Win32" - OutputDirectory="$(ConfigurationName)" - IntermediateDirectory="$(ConfigurationName)" - ConfigurationType="2" - InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" - CharacterSet="2" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - /> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories=""$(InputDir)..\..\..\include";"$(InputDir)include";"$(InputDir)..\..\..\..\libs\include"" - PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;MOD_EXPORTS" - MinimalRebuild="true" - BasicRuntimeChecks="3" - RuntimeLibrary="3" - UsePrecompiledHeader="0" - WarningLevel="4" - WarnAsError="true" - Detect64BitPortabilityProblems="true" - DebugInformationFormat="3" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLinkerTool" - OutputFile="$(SolutionDir)$(OutDir)/mod/$(InputName).dll" - LinkIncremental="1" - AdditionalLibraryDirectories="..\..\..\..\w32\vsnet\$(OutDir)" - GenerateDebugInformation="true" - ProgramDatabaseFile="$(OutDir)$(TargetName).pdb" - SubSystem="2" - ImportLibrary="$(OutDir)/mod_softtimer.lib" - TargetMachine="1" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCManifestTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCAppVerifierTool" - /> - <Tool - Name="VCWebDeploymentTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> - <Configuration - Name="Release|Win32" - OutputDirectory="$(ConfigurationName)" - IntermediateDirectory="$(ConfigurationName)" - ConfigurationType="2" - InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" - CharacterSet="2" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - /> - <Tool - Name="VCCLCompilerTool" - AdditionalIncludeDirectories=""$(InputDir)..\..\..\include";"$(InputDir)include";"$(InputDir)..\..\..\..\libs\include"" - PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;MOD_EXPORTS" - RuntimeLibrary="2" - UsePrecompiledHeader="0" - WarningLevel="4" - WarnAsError="true" - Detect64BitPortabilityProblems="true" - DebugInformationFormat="3" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLinkerTool" - OutputFile="$(SolutionDir)$(OutDir)/mod/$(InputName).dll" - LinkIncremental="1" - AdditionalLibraryDirectories="..\..\..\..\w32\vsnet\$(OutDir)" - GenerateDebugInformation="true" - ProgramDatabaseFile="$(OutDir)$(TargetName).pdb" - SubSystem="2" - OptimizeReferences="2" - EnableCOMDATFolding="2" - ImportLibrary="$(OutDir)/mod_softtimer.lib" - TargetMachine="1" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCManifestTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCAppVerifierTool" - /> - <Tool - Name="VCWebDeploymentTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> - </Configurations> - <References> - </References> - <Files> - <Filter - Name="Source Files" - Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx" - UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}" - > - <File - RelativePath=".\mod_softtimer.c" - > - </File> - </Filter> - <Filter - Name="Header Files" - Filter="h;hpp;hxx;hm;inl;inc;xsd" - UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" - > - </Filter> - <Filter - Name="Resource Files" - Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx" - UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}" - > - </Filter> - </Files> - <Globals> - </Globals> -</VisualStudioProject> diff --git a/src/mod/timers/mod_softtimer/mod_softtimer.c b/src/softtimer.c similarity index 85% rename from src/mod/timers/mod_softtimer/mod_softtimer.c rename to src/softtimer.c index 0cb0b0bcd2..2a162ce789 100644 --- a/src/mod/timers/mod_softtimer/mod_softtimer.c +++ b/src/softtimer.c @@ -26,11 +26,12 @@ * Anthony Minessale II <anthmct@yahoo.com> * * - * mod_softtimer.c -- Software Timer Module + * softtimer.c -- Software Timer Module * */ #include <switch.h> #include <stdio.h> +#include "private/switch_core_pvt.h" #ifndef UINT32_MAX #define UINT32_MAX 0xffffffff @@ -38,7 +39,7 @@ #define MAX_TICK UINT32_MAX - 1024 - +struct switch_runtime runtime; static switch_memory_pool_t *module_pool = NULL; static struct { @@ -47,10 +48,10 @@ static struct { switch_mutex_t *mutex; } globals; -SWITCH_MODULE_LOAD_FUNCTION(mod_softtimer_load); -SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_softtimer_shutdown); -SWITCH_MODULE_RUNTIME_FUNCTION(mod_softtimer_runtime); -SWITCH_MODULE_DEFINITION(mod_softtimer, mod_softtimer_load, mod_softtimer_shutdown, mod_softtimer_runtime); +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 @@ -195,51 +196,43 @@ static switch_status_t timer_destroy(switch_timer_t *timer) return SWITCH_STATUS_SUCCESS; } -SWITCH_MODULE_LOAD_FUNCTION(mod_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; -} - -/* I cant resist setting this to 10ms, we dont even run anything smaller than 20ms so this is already - twice the granularity we need, we'll change it if we need anything smaller -*/ #define STEP_MS 1 #define STEP_MIC 1000 -SWITCH_MODULE_RUNTIME_FUNCTION(mod_softtimer_runtime) +SWITCH_MODULE_RUNTIME_FUNCTION(softtimer_runtime) { switch_time_t reference = switch_time_now(); uint32_t current_ms = 0; - uint32_t x; - + 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 (switch_time_now() < reference) { + 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; @@ -270,7 +263,27 @@ SWITCH_MODULE_RUNTIME_FUNCTION(mod_softtimer_runtime) return SWITCH_STATUS_TERM; } -SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_softtimer_shutdown) + +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) { @@ -282,7 +295,7 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_softtimer_shutdown) switch_yield(10000); } } - + switch_core_destroy_memory_pool(&module_pool); return SWITCH_STATUS_SUCCESS; } diff --git a/src/switch_channel.c b/src/switch_channel.c index 63920f358b..6b674e4927 100644 --- a/src/switch_channel.c +++ b/src/switch_channel.c @@ -855,7 +855,7 @@ SWITCH_DECLARE(void) switch_channel_set_caller_profile(switch_channel_t *channel 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; } diff --git a/src/switch_console.c b/src/switch_console.c index 57a567d938..fce2e763ad 100644 --- a/src/switch_console.c +++ b/src/switch_console.c @@ -151,7 +151,7 @@ SWITCH_DECLARE(void) switch_console_printf(switch_text_channel_t channel, const 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) { diff --git a/src/switch_core.c b/src/switch_core.c index 3237f89c08..9802ce2375 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -79,6 +79,10 @@ SWITCH_STANDARD_SCHED_FUNC(heartbeat_callback) 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 @@ SWITCH_DECLARE(switch_status_t) switch_core_init(const char *console, switch_cor 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 @@ SWITCH_DECLARE(switch_status_t) switch_core_init(const char *console, switch_cor 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_DECLARE(switch_status_t) switch_core_init_and_modload(const char *console } 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" ); diff --git a/src/switch_core_session.c b/src/switch_core_session.c index c374b35a66..dc29a365f8 100644 --- a/src/switch_core_session.c +++ b/src/switch_core_session.c @@ -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_DECLARE(switch_core_session_t *) switch_core_session_locate(const char *u 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 @@ SWITCH_DECLARE(switch_core_session_t *) switch_core_session_locate(const char *u 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_DECLARE(void) switch_core_session_hupall(switch_call_cause_t cause) 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_DECLARE(void) switch_core_session_hupall(switch_call_cause_t cause) 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_DECLARE(switch_status_t) switch_core_session_message_send(char *uuid_str, 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_DECLARE(switch_status_t) switch_core_session_message_send(char *uuid_str, 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_DECLARE(switch_status_t) switch_core_session_event_send(char *uuid_str, s 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_DECLARE(switch_status_t) switch_core_session_event_send(char *uuid_str, s 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_DECLARE(void) switch_core_session_perform_destroy(switch_core_session_t * 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_DECLARE(switch_core_session_t *) switch_core_session_request(const switch 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 @@ SWITCH_DECLARE(switch_core_session_t *) switch_core_session_request(const switch 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_DECLARE(switch_core_session_t *) switch_core_session_request(const switch 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 @@ SWITCH_DECLARE(uint32_t) switch_core_session_limit(uint32_t new_limit) 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 @@ void switch_core_session_init(switch_memory_pool_t *pool) 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) diff --git a/src/switch_event.c b/src/switch_event.c index 78e6f2c6cd..9dd63821a4 100644 --- a/src/switch_event.c +++ b/src/switch_event.c @@ -870,7 +870,7 @@ SWITCH_DECLARE(switch_status_t) switch_event_fire_detailed(char *file, char *fun 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); diff --git a/src/switch_loadable_module.c b/src/switch_loadable_module.c index 9b6e2b4c6a..b158699095 100644 --- a/src/switch_loadable_module.c +++ b/src/switch_loadable_module.c @@ -655,14 +655,19 @@ static switch_status_t switch_loadable_module_load_file(char *path, char *filena 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 @@ static switch_status_t switch_loadable_module_load_file(char *path, char *filena 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_unload_module(char *dir, 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 @@ SWITCH_DECLARE(switch_status_t) switch_loadable_module_build_dynamic(char *filen 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_DECLARE(switch_status_t) switch_loadable_module_init() 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 @@ SWITCH_DECLARE(switch_status_t) switch_loadable_module_init() } apr_dir_close(module_dir_handle); } - + switch_loadable_module_runtime(); return SWITCH_STATUS_SUCCESS; diff --git a/src/switch_log.c b/src/switch_log.c index 7bb714e316..5e59c99e7d 100644 --- a/src/switch_log.c +++ b/src/switch_log.c @@ -162,7 +162,7 @@ SWITCH_DECLARE(void) switch_log_printf(switch_text_channel_t channel, const char 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"; diff --git a/src/switch_scheduler.c b/src/switch_scheduler.c index 42aee0048b..d0b164f346 100644 --- a/src/switch_scheduler.c +++ b/src/switch_scheduler.c @@ -1,5 +1,6 @@ #include <switch.h> + struct switch_scheduler_task_container { switch_scheduler_task_t task; int64_t executed; @@ -71,6 +72,7 @@ static int task_thread_loop(int done) switch_mutex_lock(globals.task_mutex); + for (tp = globals.task_list; tp; tp = tp->next) { if (done) { tp->destroyed = 1; diff --git a/src/switch_stun.c b/src/switch_stun.c index e0933b1e0f..e698576787 100644 --- a/src/switch_stun.c +++ b/src/switch_stun.c @@ -104,7 +104,7 @@ SWITCH_DECLARE(void) switch_stun_random_string(char *buf, uint16_t len, char *se 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));