From 2094f2d33b21a645d9a0441957803a39171b4a4d Mon Sep 17 00:00:00 2001
From: Anthony Minessale <anthm@freeswitch.org>
Date: Wed, 12 Oct 2011 14:55:32 -0500
Subject: [PATCH] add fsctl sync_clock_when_idle so you can sync the clock but
 have it not do it till there are 0 calls

---
 src/include/switch_core.h                     |  1 +
 src/include/switch_types.h                    |  6 +++--
 .../applications/mod_commands/mod_commands.c  | 10 ++++++-
 src/switch_core.c                             |  4 +++
 src/switch_core_session.c                     | 26 +++++++++++++++++++
 src/switch_time.c                             |  7 +++++
 6 files changed, 51 insertions(+), 3 deletions(-)

diff --git a/src/include/switch_core.h b/src/include/switch_core.h
index 7f1db105f8..6987af8e18 100644
--- a/src/include/switch_core.h
+++ b/src/include/switch_core.h
@@ -467,6 +467,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_perform_new_memory_pool(_Out_ switch
 */
 #define switch_core_new_memory_pool(p) switch_core_perform_new_memory_pool(p, __FILE__, __SWITCH_FUNC__, __LINE__)
 
+SWITCH_DECLARE(int) switch_core_session_sync_clock(void);
 SWITCH_DECLARE(switch_status_t) switch_core_perform_destroy_memory_pool(_Inout_ switch_memory_pool_t **pool,
 																		_In_z_ const char *file, _In_z_ const char *func, _In_ int line);
 /*! 
diff --git a/src/include/switch_types.h b/src/include/switch_types.h
index 715f232556..a4f3c11884 100644
--- a/src/include/switch_types.h
+++ b/src/include/switch_types.h
@@ -308,7 +308,8 @@ typedef enum {
 	SCF_MINIMAL = (1 << 14),
 	SCF_USE_NAT_MAPPING = (1 << 15),
 	SCF_CLEAR_SQL = (1 << 16),
-	SCF_THREADED_SYSTEM_EXEC = (1 << 17)
+	SCF_THREADED_SYSTEM_EXEC = (1 << 17),
+	SCF_SYNC_CLOCK_REQUESTED = (1 << 18)
 } switch_core_flag_enum_t;
 typedef uint32_t switch_core_flag_t;
 
@@ -1707,7 +1708,8 @@ typedef enum {
 	SCSC_SHUTDOWN_CHECK,
 	SCSC_PAUSE_CHECK,
 	SCSC_READY_CHECK,
-	SCSC_THREADED_SYSTEM_EXEC
+	SCSC_THREADED_SYSTEM_EXEC,
+	SCSC_SYNC_CLOCK_WHEN_IDLE
 } switch_session_ctl_t;
 
 typedef enum {
diff --git a/src/mod/applications/mod_commands/mod_commands.c b/src/mod/applications/mod_commands/mod_commands.c
index 4daa339d4d..988893a39f 100644
--- a/src/mod/applications/mod_commands/mod_commands.c
+++ b/src/mod/applications/mod_commands/mod_commands.c
@@ -1791,7 +1791,7 @@ SWITCH_STANDARD_API(status_function)
 	return SWITCH_STATUS_SUCCESS;
 }
 
-#define CTL_SYNTAX "[send_sighup|hupall|pause|resume|shutdown [cancel|elegant|asap|now|restart]|sps|sync_clock|reclaim_mem|max_sessions|min_dtmf_duration [num]|max_dtmf_duration [num]|default_dtmf_duration [num]|min_idle_cpu|loglevel [level]|debug_level [level]]"
+#define CTL_SYNTAX "[send_sighup|hupall|pause|resume|shutdown [cancel|elegant|asap|now|restart]|sps|sync_clock|sync_clock_when_idle|reclaim_mem|max_sessions|min_dtmf_duration [num]|max_dtmf_duration [num]|default_dtmf_duration [num]|min_idle_cpu|loglevel [level]|debug_level [level]]"
 SWITCH_STANDARD_API(ctl_function)
 {
 	int argc;
@@ -1972,6 +1972,14 @@ SWITCH_STANDARD_API(ctl_function)
 			arg = 0;
 			switch_core_session_ctl(SCSC_SYNC_CLOCK, &arg);
 			stream->write_function(stream, "+OK clock synchronized\n");
+		} else if (!strcasecmp(argv[0], "sync_clock_when_idle")) {
+			arg = 0;
+			switch_core_session_ctl(SCSC_SYNC_CLOCK_WHEN_IDLE, &arg);
+			if (arg) {
+				stream->write_function(stream, "+OK clock synchronized\n");
+			} else {
+				stream->write_function(stream, "+OK clock will synchronize when there are no more calls\n");
+			}
 		} else {
 			stream->write_function(stream, "-ERR INVALID COMMAND\nUSAGE: fsctl %s", CTL_SYNTAX);
 			goto end;
diff --git a/src/switch_core.c b/src/switch_core.c
index 85a710c085..4a82464c35 100644
--- a/src/switch_core.c
+++ b/src/switch_core.c
@@ -2018,6 +2018,10 @@ SWITCH_DECLARE(int32_t) switch_core_session_ctl(switch_session_ctl_t cmd, void *
 		switch_time_sync();
 		newintval = 0;
 		break;
+	case SCSC_SYNC_CLOCK_WHEN_IDLE:
+		newintval = switch_core_session_sync_clock();
+		printf("WTF [%d]\n", newintval);
+		break;
 	case SCSC_PAUSE_INBOUND:
 		if (oldintval) {
 			switch_set_flag((&runtime), SCF_NO_NEW_SESSIONS);
diff --git a/src/switch_core_session.c b/src/switch_core_session.c
index 99bf524324..1d0b952fee 100644
--- a/src/switch_core_session.c
+++ b/src/switch_core_session.c
@@ -1187,6 +1187,26 @@ SWITCH_DECLARE(unsigned int) switch_core_session_started(switch_core_session_t *
 	return switch_test_flag(session, SSF_THREAD_STARTED) ? 1 : 0;
 }
 
+SWITCH_DECLARE(int) switch_core_session_sync_clock(void)
+{
+	int doit = 0;
+
+	switch_mutex_lock(runtime.session_hash_mutex);
+	if (session_manager.session_count == 0) {
+		doit = 1;
+	} else {
+		switch_set_flag((&runtime), SCF_SYNC_CLOCK_REQUESTED);
+	}
+	switch_mutex_unlock(runtime.session_hash_mutex);
+
+	if (doit)  {
+		switch_time_sync();
+	}
+
+	return doit;
+
+}
+
 SWITCH_DECLARE(void) switch_core_session_perform_destroy(switch_core_session_t **session, const char *file, const char *func, int line)
 {
 	switch_memory_pool_t *pool;
@@ -1209,6 +1229,12 @@ SWITCH_DECLARE(void) switch_core_session_perform_destroy(switch_core_session_t *
 	switch_core_hash_delete(session_manager.session_table, (*session)->uuid_str);
 	if (session_manager.session_count) {
 		session_manager.session_count--;
+		if (session_manager.session_count == 0) {
+			if (switch_test_flag((&runtime), SCF_SYNC_CLOCK_REQUESTED)) {
+				switch_time_sync();
+				switch_clear_flag((&runtime), SCF_SYNC_CLOCK_REQUESTED);
+			}
+		}
 	}
 	switch_mutex_unlock(runtime.session_hash_mutex);
 
diff --git a/src/switch_time.c b/src/switch_time.c
index bcee99c247..cda237ba48 100644
--- a/src/switch_time.c
+++ b/src/switch_time.c
@@ -411,11 +411,18 @@ SWITCH_DECLARE(switch_time_t) switch_time_ref(void)
 	return time_now(0);
 }
 
+static switch_time_t last_time = 0;
+
 SWITCH_DECLARE(void) switch_time_sync(void)
 {
 	runtime.reference = switch_time_now();
+
 	runtime.offset = runtime.reference - time_now(0);
 	runtime.reference = time_now(runtime.offset);
+	if (runtime.reference - last_time > 1000000 || last_time == 0) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Clock syncronized to system time.\n");
+	}
+	last_time = runtime.reference;
 }
 
 SWITCH_DECLARE(void) switch_micro_sleep(switch_interval_time_t t)