static void _mark_service_state(const gchar *ns_name, const gchar *srv_key, gboolean is_up) { struct namespace_data_s *ns_data; struct service_info_s *si; ns_data = g_hash_table_lookup(namespaces, ns_name); if (!ns_data) return; if (is_up) { si = g_hash_table_lookup(ns_data->local_services, srv_key); if (!si) { /*service was DOWN*/ si = g_hash_table_lookup(ns_data->down_services, srv_key); if (si && (si = service_info_dup(si))) { g_hash_table_remove(ns_data->down_services, srv_key); g_hash_table_insert(ns_data->local_services, g_strdup(srv_key), si); INFO("Service [%s/%s] now UP", ns_name, srv_key); } } else { si->score.timestamp = g_get_real_time() / 1000000; DEBUG("Service [%s/%s] still UP", ns_name, srv_key); } /*ensure the UP tag on TRUE*/ if (si) { service_tag_set_value_boolean(service_info_ensure_tag(si->tags,"tag.up"), TRUE); si->score.timestamp = g_get_real_time() / 1000000; } } else { si = g_hash_table_lookup(ns_data->down_services, srv_key); if (!si) { /*service was maybe UP*/ si = g_hash_table_lookup(ns_data->local_services, srv_key); if (si && (si = service_info_dup(si))) { g_hash_table_remove(ns_data->local_services, srv_key); g_hash_table_insert(ns_data->down_services, g_strdup(srv_key), si); si->score.value = -2; } INFO("Service [%s/%s] now DOWN", ns_name, srv_key); } else { DEBUG("Service [%s/%s] still DOWN", ns_name, srv_key); si->score.value = -2; } /*was it UP or not, we ensure it has ZERO stats and the right flags*/ if (si) { service_tag_set_value_boolean(service_info_ensure_tag(si->tags,"tag.up"), FALSE); zero_service_stats(si->tags); invalidate_conscience_service(ns_data, si); DEBUG("Service [%s/%s] zeroed, invalidated, marked down", ns_name, srv_key); } } }
void service_tag_copy(struct service_tag_s *dst, struct service_tag_s *src) { if (!dst || !src) return; g_strlcpy(dst->name, src->name, sizeof(dst->name)); switch (src->type) { case STVT_I64: service_tag_set_value_i64(dst, src->value.i); return; case STVT_REAL: service_tag_set_value_float(dst, src->value.r); return; case STVT_BOOL: service_tag_set_value_boolean(dst, src->value.b); return; case STVT_STR: service_tag_set_value_string(dst, src->value.s); return; case STVT_BUF: service_tag_set_value_string(dst, src->value.buf); return; } }
static struct service_tag_s * _srvtag_load_json (const gchar *name, struct json_object *obj) { struct service_tag_s *tag = g_malloc0(sizeof(struct service_tag_s)); g_strlcpy(tag->name, name, sizeof(tag->name)); if (json_object_is_type(obj, json_type_int)) { service_tag_set_value_i64(tag, json_object_get_int64(obj)); } else if (json_object_is_type(obj, json_type_string)) { service_tag_set_value_string(tag, json_object_get_string(obj)); } else if (json_object_is_type(obj, json_type_double)) { service_tag_set_value_float(tag, json_object_get_double(obj)); } else if (json_object_is_type(obj, json_type_boolean)) { service_tag_set_value_boolean(tag, json_object_get_boolean(obj)); } else { service_tag_set_value_boolean(tag, FALSE); } return tag; }
static void _detect_obsolete_services(struct namespace_data_s *ns_data) { guint counter; time_t time_now, time_down, time_broken; GHashTableIter s_iterator; gpointer s_k, s_v; gchar *str_key; struct service_info_s *si; time_now = g_get_real_time()/1000000; time_down = time_now - 5; time_broken = time_now - 30; counter = 0; if (!ns_data->configured) { return; } /*move services from UP to DOWN */ g_hash_table_iter_init(&s_iterator, ns_data->local_services); while (g_hash_table_iter_next(&s_iterator, &s_k, &s_v)) { str_key = s_k; si = s_v; si->score.value = -2;/*score not set*/ if (si->score.timestamp < time_down) { gchar str_addr[STRLEN_ADDRINFO]; addr_info_to_string(&(si->addr),str_addr,sizeof(str_addr)); DEBUG("Timeout on service [%s/%s/%s] (%"G_GINT32_FORMAT" < %ld) --> DOWN", si->ns_name, si->type, str_addr, si->score.timestamp, time_down); g_hash_table_iter_steal(&s_iterator); g_hash_table_insert(ns_data->down_services, str_key, si); invalidate_conscience_service(ns_data,si); zero_service_stats(si->tags); service_tag_set_value_boolean(service_info_ensure_tag(si->tags,"tag.up"), FALSE); counter++; } } /*remove services DOWN from a long time ago */ g_hash_table_iter_init(&s_iterator, ns_data->down_services); while (g_hash_table_iter_next(&s_iterator, &s_k, &s_v)) { str_key = s_k; si = s_v; si->score.value = -2;/*score not set*/ if (si->score.timestamp < time_broken) { gchar str_addr[STRLEN_ADDRINFO]; addr_info_to_string(&(si->addr),str_addr,sizeof(str_addr)); DEBUG("Service obsolete [%s/%s/%s] --> DELETED", si->ns_name, si->type, str_addr); g_hash_table_iter_remove(&s_iterator); counter++; } else zero_service_stats(si->tags); } if (counter) DEBUG("[task_id=%s] %u services states have changed", TASK_ID, counter); }
static enum http_rc_e _registration (struct req_args_s *args, enum reg_op_e op, struct json_object *jsrv) { GError *err; if (!jsrv || !json_object_is_type (jsrv, json_type_object)) return _reply_common_error (args, BADREQ("Expected: json object")); if (!push_queue) return _reply_bad_gateway(args, SYSERR("Service upstream disabled")); if (NULL != (err = _cs_check_tokens(args))) return _reply_notfound_error (args, err); struct service_info_s *si = NULL; err = service_info_load_json_object (jsrv, &si, TRUE); if (err) { g_prefix_error (&err, "JSON error: "); if (err->code == CODE_BAD_REQUEST) return _reply_format_error (args, err); else return _reply_system_error (args, err); } if (!si->type[0]) { service_info_clean (si); return _reply_format_error (args, BADREQ("Service type not specified")); } if (!si->ns_name[0]) { GRID_TRACE2("%s NS forced to %s", __FUNCTION__, si->ns_name); g_strlcpy (si->ns_name, nsname, sizeof(si->ns_name)); } else if (!validate_namespace (si->ns_name)) { service_info_clean (si); return _reply_format_error (args, BADNS()); } gchar *k = service_info_key (si); STRING_STACKIFY(k); GRID_TRACE2("%s op=%s score=%d key=[%s]", __FUNCTION__, _regop_2str(op), si->score.value, k); switch (op) { case REGOP_PUSH: si->score.value = SCORE_UNSET; if (!service_is_known (k)) { service_learn (k); service_tag_set_value_boolean (service_info_ensure_tag ( si->tags, NAME_TAGNAME_RAWX_FIRST), TRUE); } break; case REGOP_LOCK: si->score.value = CLAMP(si->score.value, SCORE_DOWN, SCORE_MAX); break; case REGOP_UNLOCK: si->score.value = SCORE_UNLOCK; break; default: g_assert_not_reached(); } if (cs_expire_local_services > 0) { struct service_info_s *v = service_info_dup (si); v->score.timestamp = oio_ext_monotonic_seconds (); PUSH_DO( const struct service_info_s *si0 = lru_tree_get(srv_registered, k); if (si0) v->score.value = si0->score.value; lru_tree_insert (srv_registered, g_strdup(k), v); ); }
static gboolean manage_service(struct service_info_s *si) { GError *error_local; struct service_info_s *old_si = NULL; struct service_tag_s *tag_first = NULL; struct namespace_data_s *ns_data; gsize key_size; gchar key[LIMIT_LENGTH_SRVTYPE + STRLEN_ADDRINFO], str_addr[STRLEN_ADDRINFO]; if (!si) { ERROR("Invalid parameter"); return FALSE; } key_size = agent_get_service_key(si, key, sizeof(key)); grid_addrinfo_to_string(&(si->addr), str_addr, sizeof(str_addr)); /*this service must refer to known namespace and service type*/ error_local = NULL; if (!(ns_data = get_namespace(si->ns_name, &error_local))) { ERROR("Namespace unavailable for service [ns=%s type=%s addr=%s] : %s", si->ns_name, si->type, str_addr, gerror_get_message(error_local)); if (error_local) g_error_free(error_local); return FALSE; } /*Info trace when a service of a new type is used */ if (error_local) g_error_free(error_local); if (!conscience_get_srvtype(ns_data->conscience, &error_local, si->type, MODE_STRICT)) { /*to avoid traces flooding, if the service already exists, no trace is sent */ if (!g_hash_table_lookup(ns_data->local_services, key) && !g_hash_table_lookup(ns_data->down_services, key)) { INFO("New service type discovered [ns=%s type=%s addr=%s]", ns_data->name, si->type, str_addr); } } /*replace MACRO tags by their true values */ if (error_local) g_clear_error(&error_local); metautils_srvinfo_ensure_tags (si); si->score.value = SCORE_UNSET; si->score.timestamp = oio_ext_real_time() / G_TIME_SPAN_SECOND; /*then keep the score */ g_hash_table_remove(ns_data->down_services, key); /* save first lauched tag if still in old si */ old_si = g_hash_table_lookup(ns_data->local_services, key); if (old_si != NULL) { tag_first = service_info_get_tag(old_si->tags, NAME_TAGNAME_RAWX_FIRST); if (tag_first != NULL) service_tag_set_value_boolean(service_info_ensure_tag(si->tags, NAME_TAGNAME_RAWX_FIRST), tag_first->value.b); } service_tag_set_value_boolean(service_info_ensure_tag(si->tags, "tag.up"), TRUE); g_hash_table_insert(ns_data->local_services, g_strndup(key, key_size), si); DEBUG("Service registration [ns=%s type=%s addr=%s]", ns_data->name, si->type, str_addr); if (error_local) g_error_free(error_local); return TRUE; }