static void wd_resource_failed (struct cs_fsm* fsm, int32_t event, void * data) { struct resource* ref = (struct resource*)data; if (ref->check_timer) { api->timer_delete(ref->check_timer); ref->check_timer = NULL; } log_printf (LOGSYS_LEVEL_CRIT, "%s resource \"%s\" failed!", ref->recovery, (char*)ref->name); if (strcmp (ref->recovery, "watchdog") == 0 || strcmp (ref->recovery, "quit") == 0) { watchdog_ok = 0; } else if (strcmp (ref->recovery, "reboot") == 0) { reboot(RB_AUTOBOOT); } else if (strcmp (ref->recovery, "shutdown") == 0) { reboot(RB_POWER_OFF); } cs_fsm_state_set(fsm, WD_S_FAILED, data); }
/* * return 0 - fully configured * return -1 - partially configured */ static int32_t wd_resource_create (hdb_handle_t resource_obj) { int res; size_t len; char *state; objdb_value_types_t type; char period_str[32]; char str_copy[256]; char *str; uint64_t tmp_value; struct resource *ref = malloc (sizeof (struct resource)); ref->handle = resource_obj; ref->check_timeout = WD_DEFAULT_TIMEOUT_MS; ref->check_timer = NULL; api->object_name_get (resource_obj, ref->name, &len); ref->name[len] = '\0'; ref->fsm.name = ref->name; ref->fsm.table = wd_fsm_table; ref->fsm.entries = sizeof(wd_fsm_table) / sizeof(struct cs_fsm_entry); ref->fsm.curr_entry = 0; ref->fsm.curr_state = WD_S_STOPPED; ref->fsm.state_to_str = wd_res_state_to_str; ref->fsm.event_to_str = wd_res_event_to_str; api->object_priv_set (resource_obj, NULL); res = api->object_key_get_typed (resource_obj, "poll_period", (void**)&str, &len, &type); if (res != 0) { len = snprintf (period_str, 32, "%"PRIu64"", ref->check_timeout); api->object_key_create_typed (resource_obj, "poll_period", &period_str, len, OBJDB_VALUETYPE_STRING); } else { memcpy(str_copy, str, len); str_copy[len] = '\0'; if (str_to_uint64_t(str_copy, &tmp_value, WD_MIN_TIMEOUT_MS, WD_MAX_TIMEOUT_MS) == CS_OK) { ref->check_timeout = tmp_value; } else { log_printf (LOGSYS_LEVEL_WARNING, "Could NOT use poll_period:%s ms for resource %s", str, ref->name); } } api->object_track_start (resource_obj, OBJECT_TRACK_DEPTH_RECURSIVE, wd_key_changed, NULL, wd_object_destroyed, NULL, ref); res = api->object_key_get_typed (resource_obj, "recovery", (void*)&ref->recovery, &len, &type); if (res != 0) { /* key does not exist. */ log_printf (LOGSYS_LEVEL_WARNING, "resource %s missing a recovery key.", ref->name); return -1; } res = api->object_key_get_typed (resource_obj, "state", (void*)&state, &len, &type); if (res != 0) { /* key does not exist. */ log_printf (LOGSYS_LEVEL_WARNING, "resource %s missing a state key.", ref->name); return -1; } res = api->object_key_get_typed (resource_obj, "last_updated", (void*)&ref->last_updated, &len, &type); if (res != 0) { /* key does not exist. */ ref->last_updated = 0; } /* * delay the first check to give the monitor time to start working. */ tmp_value = CS_MAX(ref->check_timeout * 2, WD_DEFAULT_TIMEOUT_MS); api->timer_add_duration(tmp_value * MILLI_2_NANO_SECONDS, ref, wd_resource_check_fn, &ref->check_timer); cs_fsm_state_set(&ref->fsm, WD_S_RUNNING, ref); return 0; }
/* * return 0 - fully configured * return -1 - partially configured */ static int32_t wd_resource_create (char *res_path, char *res_name) { char *state; uint64_t tmp_value; struct resource *ref = calloc (1, sizeof (struct resource)); char key_name[ICMAP_KEYNAME_MAXLEN]; strcpy(ref->res_path, res_path); ref->check_timeout = WD_DEFAULT_TIMEOUT_MS; ref->check_timer = 0; strcpy(ref->name, res_name); ref->fsm.name = ref->name; ref->fsm.table = wd_fsm_table; ref->fsm.entries = sizeof(wd_fsm_table) / sizeof(struct cs_fsm_entry); ref->fsm.curr_entry = 0; ref->fsm.curr_state = WD_S_STOPPED; ref->fsm.state_to_str = wd_res_state_to_str; ref->fsm.event_to_str = wd_res_event_to_str; snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "%s%s", res_path, "poll_period"); if (icmap_get_uint64(key_name, &tmp_value) != CS_OK) { icmap_set_uint64(key_name, ref->check_timeout); } else { if (tmp_value >= WD_MIN_TIMEOUT_MS && tmp_value <= WD_MAX_TIMEOUT_MS) { ref->check_timeout = tmp_value; } else { log_printf (LOGSYS_LEVEL_WARNING, "Could NOT use poll_period:%"PRIu64" ms for resource %s", tmp_value, ref->name); } } icmap_track_add(res_path, ICMAP_TRACK_ADD | ICMAP_TRACK_MODIFY | ICMAP_TRACK_DELETE | ICMAP_TRACK_PREFIX, wd_key_changed, ref, &ref->icmap_track); snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "%s%s", res_path, "recovery"); if (icmap_get_string(key_name, &ref->recovery) != CS_OK) { /* key does not exist. */ log_printf (LOGSYS_LEVEL_WARNING, "resource %s missing a recovery key.", ref->name); return -1; } snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "%s%s", res_path, "state"); if (icmap_get_string(key_name, &state) != CS_OK) { /* key does not exist. */ log_printf (LOGSYS_LEVEL_WARNING, "resource %s missing a state key.", ref->name); return -1; } snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "%s%s", res_path, "last_updated"); if (icmap_get_uint64(key_name, &tmp_value) != CS_OK) { /* key does not exist. */ ref->last_updated = 0; } else { ref->last_updated = tmp_value; } /* * delay the first check to give the monitor time to start working. */ tmp_value = CS_MAX(ref->check_timeout * 2, WD_DEFAULT_TIMEOUT_MS); api->timer_add_duration(tmp_value * MILLI_2_NANO_SECONDS, ref, wd_resource_check_fn, &ref->check_timer); cs_fsm_state_set(&ref->fsm, WD_S_RUNNING, ref); return 0; }
static void wd_config_changed (struct cs_fsm* fsm, int32_t event, void * data) { int res; size_t len; char *state; objdb_value_types_t type; char *str; uint64_t tmp_value; uint64_t next_timeout; struct resource *ref = (struct resource*)data; char str_copy[256]; next_timeout = ref->check_timeout; res = api->object_key_get_typed (ref->handle, "poll_period", (void**)&str, &len, &type); if (res == 0) { memcpy(str_copy, str, len); str_copy[len] = '\0'; if (str_to_uint64_t(str_copy, &tmp_value, WD_MIN_TIMEOUT_MS, WD_MAX_TIMEOUT_MS) == CS_OK) { log_printf (LOGSYS_LEVEL_DEBUG, "poll_period changing from:%"PRIu64" to %"PRIu64".", ref->check_timeout, tmp_value); /* * To easy in the transition between poll_period's we are going * to make the first timeout the bigger of the new and old value. * This is to give the monitoring system time to adjust. */ next_timeout = CS_MAX(tmp_value, ref->check_timeout); ref->check_timeout = tmp_value; } else { log_printf (LOGSYS_LEVEL_WARNING, "Could NOT use poll_period:%s ms for resource %s", str, ref->name); } } res = api->object_key_get_typed (ref->handle, "recovery", (void*)&ref->recovery, &len, &type); if (res != 0) { /* key does not exist. */ log_printf (LOGSYS_LEVEL_WARNING, "resource %s missing a recovery key.", ref->name); cs_fsm_state_set(&ref->fsm, WD_S_STOPPED, ref); return; } res = api->object_key_get_typed (ref->handle, "state", (void*)&state, &len, &type); if (res != 0) { /* key does not exist. */ log_printf (LOGSYS_LEVEL_WARNING, "resource %s missing a state key.", ref->name); cs_fsm_state_set(&ref->fsm, WD_S_STOPPED, ref); return; } if (ref->check_timer) { api->timer_delete(ref->check_timer); ref->check_timer = NULL; } if (strcmp(wd_stopped_str, state) == 0) { cs_fsm_state_set(&ref->fsm, WD_S_STOPPED, ref); } else { api->timer_add_duration(next_timeout * MILLI_2_NANO_SECONDS, ref, wd_resource_check_fn, &ref->check_timer); cs_fsm_state_set(&ref->fsm, WD_S_RUNNING, ref); } }
static void wd_config_changed (struct cs_fsm* fsm, int32_t event, void * data) { char *state; uint64_t tmp_value; uint64_t next_timeout; struct resource *ref = (struct resource*)data; char key_name[ICMAP_KEYNAME_MAXLEN]; next_timeout = ref->check_timeout; snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "%s%s", ref->res_path, "poll_period"); if (icmap_get_uint64(ref->res_path, &tmp_value) == CS_OK) { if (tmp_value >= WD_MIN_TIMEOUT_MS && tmp_value <= WD_MAX_TIMEOUT_MS) { log_printf (LOGSYS_LEVEL_DEBUG, "poll_period changing from:%"PRIu64" to %"PRIu64".", ref->check_timeout, tmp_value); /* * To easy in the transition between poll_period's we are going * to make the first timeout the bigger of the new and old value. * This is to give the monitoring system time to adjust. */ next_timeout = CS_MAX(tmp_value, ref->check_timeout); ref->check_timeout = tmp_value; } else { log_printf (LOGSYS_LEVEL_WARNING, "Could NOT use poll_period:%"PRIu64" ms for resource %s", tmp_value, ref->name); } } snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "%s%s", ref->res_path, "recovery"); if (icmap_get_string(key_name, &ref->recovery) != CS_OK) { /* key does not exist. */ log_printf (LOGSYS_LEVEL_WARNING, "resource %s missing a recovery key.", ref->name); cs_fsm_state_set(&ref->fsm, WD_S_STOPPED, ref); return; } snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "%s%s", ref->res_path, "state"); if (icmap_get_string(key_name, &state) != CS_OK) { /* key does not exist. */ log_printf (LOGSYS_LEVEL_WARNING, "resource %s missing a state key.", ref->name); cs_fsm_state_set(&ref->fsm, WD_S_STOPPED, ref); return; } if (ref->check_timer) { api->timer_delete(ref->check_timer); ref->check_timer = 0; } if (strcmp(wd_stopped_str, state) == 0) { cs_fsm_state_set(&ref->fsm, WD_S_STOPPED, ref); } else { api->timer_add_duration(next_timeout * MILLI_2_NANO_SECONDS, ref, wd_resource_check_fn, &ref->check_timer); cs_fsm_state_set(&ref->fsm, WD_S_RUNNING, ref); } free(state); }