ccapi_context_change_time.c [plain text]
#include "ccapi_context_change_time.h"
#include "cci_common.h"
#include "k5-thread.h"
static cci_identifier_t g_change_time_identifer = NULL;
static cc_time_t g_change_time = 0;
static cc_time_t g_change_time_offset = 0;
static k5_mutex_t g_change_time_mutex = K5_MUTEX_PARTIAL_INITIALIZER;
cc_int32 cci_context_change_time_thread_init (void)
{
return k5_mutex_finish_init(&g_change_time_mutex);
}
void cci_context_change_time_thread_fini (void)
{
k5_mutex_destroy(&g_change_time_mutex);
}
static cc_int32 cci_context_change_time_update_identifier (cci_identifier_t in_new_identifier,
cc_uint32 *out_server_ids_match,
cc_uint32 *out_old_server_running,
cc_uint32 *out_new_server_running)
{
cc_int32 err = ccNoError;
cc_uint32 server_ids_match = 0;
cc_uint32 old_server_running = 0;
cc_uint32 new_server_running = 0;
if (!in_new_identifier) { err = cci_check_error (err); }
if (!err && !g_change_time_identifer) {
g_change_time_identifer = cci_identifier_uninitialized;
}
if (!err) {
err = cci_identifier_compare_server_id (g_change_time_identifer,
in_new_identifier,
&server_ids_match);
}
if (!err && out_old_server_running) {
err = cci_identifier_is_initialized (g_change_time_identifer, &old_server_running);
}
if (!err && out_new_server_running) {
err = cci_identifier_is_initialized (in_new_identifier, &new_server_running);
}
if (!err && !server_ids_match) {
cci_identifier_t new_change_time_identifer = NULL;
err = cci_identifier_copy (&new_change_time_identifer, in_new_identifier);
if (!err) {
if (g_change_time_identifer) {
cci_identifier_release (g_change_time_identifer);
}
g_change_time_identifer = new_change_time_identifer;
}
}
if (!err) {
if (out_server_ids_match ) { *out_server_ids_match = server_ids_match; }
if (out_old_server_running) { *out_old_server_running = old_server_running; }
if (out_new_server_running) { *out_new_server_running = new_server_running; }
}
return cci_check_error (err);
}
#ifdef TARGET_OS_MAC
#pragma mark -
#endif
cc_int32 cci_context_change_time_get (cc_time_t *out_change_time)
{
cc_int32 err = ccNoError;
err = k5_mutex_lock (&g_change_time_mutex);
if (!err) {
*out_change_time = g_change_time + g_change_time_offset;
k5_mutex_unlock (&g_change_time_mutex);
}
return err;
}
cc_int32 cci_context_change_time_update (cci_identifier_t in_identifier,
cc_time_t in_new_change_time)
{
cc_int32 err = ccNoError;
cc_int32 lock_err = err = k5_mutex_lock (&g_change_time_mutex);
if (!err) {
if (!in_identifier) { err = cci_check_error (err); }
}
if (!err) {
if (g_change_time < in_new_change_time) {
g_change_time = in_new_change_time;
cci_debug_printf ("%s: setting change time to %d",
__FUNCTION__, in_new_change_time);
}
}
if (!err) {
err = cci_context_change_time_update_identifier (in_identifier,
NULL, NULL, NULL);
}
if (!lock_err) {
k5_mutex_unlock (&g_change_time_mutex);
}
return err;
}
cc_int32 cci_context_change_time_sync (cci_identifier_t in_new_identifier)
{
cc_int32 err = ccNoError;
cc_int32 lock_err = err = k5_mutex_lock (&g_change_time_mutex);
cc_uint32 server_ids_match = 0;
cc_uint32 server_was_running = 0;
cc_uint32 server_is_running = 0;
if (!err) {
if (!in_new_identifier) { err = cci_check_error (err); }
}
if (!err) {
err = cci_context_change_time_update_identifier (in_new_identifier,
&server_ids_match,
&server_was_running,
&server_is_running);
}
if (!err && !server_ids_match) {
g_change_time_offset++;
if (server_was_running && !server_is_running) {
cc_time_t now = time (NULL);
g_change_time += g_change_time_offset;
g_change_time_offset = 0;
g_change_time = (g_change_time < now) ? now : g_change_time;
}
cci_debug_printf ("%s noticed server changed ("
"server_was_running = %d; server_is_running = %d; "
"g_change_time = %d; g_change_time_offset = %d",
__FUNCTION__, server_was_running, server_is_running,
g_change_time, g_change_time_offset);
}
if (!lock_err) {
k5_mutex_unlock (&g_change_time_mutex);
}
return err;
}