struct conscience_srvtype_s * conscience_get_locked_srvtype(struct conscience_s *conscience, GError ** error, const gchar * type, enum mode_e mode, char lock_mode) { struct conscience_srvtype_s *srvtype; if (!conscience) { GSETERROR(error, "Invalid parameter"); return NULL; } /* lock the conscience service-types storage. If an auto-creation is wanted, * and the service type does not exist, we force a lock with writer rights * because the storage itself will be modified during the creation. */ conscience_lock_srvtypes(conscience, 'r'); srvtype = conscience_get_srvtype(conscience, error, type, MODE_STRICT); if (!srvtype && mode == MODE_AUTOCREATE) { conscience_unlock_srvtypes(conscience); conscience_lock_srvtypes(conscience, 'w'); srvtype = conscience_get_srvtype(conscience, error, type, MODE_AUTOCREATE); } if (!srvtype) { GSETERROR(error, "Service type not found, unlocking the conscience"); conscience_unlock_srvtypes(conscience); return NULL; } /*now lock the service type itself */ _lock_rw(&(srvtype->rw_lock), lock_mode); return srvtype; }
static void fill_service_info_score(struct conscience_s *conscience, struct service_info_s *si) { struct conscience_srv_s *srv; struct conscience_srvtype_s *srvtype; si->score.value = SCORE_UNSET; srvtype = conscience_get_srvtype(conscience, NULL, si->type, MODE_STRICT); if (srvtype) { srv = conscience_srvtype_get_srv(srvtype, (struct conscience_srvid_s*)&(si->addr)); if (srv) si->score.value = srv->score.value; } }
/** * Find the service in the conscience and set its score to 0, and call * zero_service_stats() on the conscience service. */ static void invalidate_conscience_service(struct namespace_data_s *ns_data, struct service_info_s *si) { GError *error; struct conscience_srvtype_s *srvtype; struct conscience_srv_s *srv; struct conscience_srvid_s srvid; error = NULL; srvtype = conscience_get_srvtype(ns_data->conscience, &error, si->type, MODE_STRICT); if (srvtype) { memcpy(&(srvid.addr), &(si->addr), sizeof(addr_info_t)); srv = conscience_srvtype_get_srv(srvtype, &srvid); if (srv) { srv->score.value = 0; zero_service_stats(srv->tags); } } if (error) g_error_free(error); }
gboolean conscience_run_srvtypes(struct conscience_s * conscience, GError ** error, guint32 flags, gchar ** names_array, service_callback_f * callback, gpointer udata) { gboolean rc; register guint i, max; register guint32 real_flags; gchar **name; GPtrArray *array_srvtypes; if (!conscience || !names_array || !callback) { GSETERROR(error, "Invalid parameter (conscience=%p names_array=%p callback=%p)", conscience, names_array, callback); return FALSE; } array_srvtypes = g_ptr_array_sized_new(8); rc = TRUE; /* XXX start of critical version */ if (flags & SRVTYPE_FLAG_LOCK_ENABLE) conscience_lock_srvtypes(conscience, 'r'); /*We do not run any service type if we are not sure that all exist */ for (name = names_array; *name; name++) { struct conscience_srvtype_s *srvtype; srvtype = conscience_get_srvtype(conscience, error, *name, MODE_STRICT); if (!srvtype) { rc = FALSE; GSETCODE(error, 460, "Service type [%s] not managed", *name); goto unlock_and_exit; } g_ptr_array_add(array_srvtypes, srvtype); } /*we remove the additional call, we just want one call at the end */ real_flags = flags & ~SRVTYPE_FLAG_ADDITIONAL_CALL; for (i = 0, max = array_srvtypes->len; rc && i < max; i++) { struct conscience_srvtype_s *srvtype; srvtype = g_ptr_array_index(array_srvtypes, i); if (flags & SRVTYPE_FLAG_LOCK_ENABLE) { /* XXX start of critical section */ if (flags & SRVTYPE_FLAG_LOCK_WRITER) g_static_rw_lock_writer_lock(&(srvtype->rw_lock)); else g_static_rw_lock_reader_lock(&(srvtype->rw_lock)); } rc = conscience_srvtype_run_all(srvtype, error, real_flags, callback, udata); if (flags & SRVTYPE_FLAG_LOCK_ENABLE) { if (flags & SRVTYPE_FLAG_LOCK_WRITER) g_static_rw_lock_writer_unlock(&(srvtype->rw_lock)); else g_static_rw_lock_reader_unlock(&(srvtype->rw_lock)); /* XXX end of critical section */ } if (!rc) { GSETERROR(error, "An error occured while running the services of type [%s]", srvtype->type_name); goto unlock_and_exit; } } if (rc && (flags & SRVTYPE_FLAG_ADDITIONAL_CALL)) rc = callback(NULL, udata); unlock_and_exit: if (flags & SRVTYPE_FLAG_LOCK_ENABLE) conscience_unlock_srvtypes(conscience); /* XXX end of critical version */ g_ptr_array_free(array_srvtypes, TRUE); return rc; }
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; }