guint conscience_srvtype_count_srv(struct conscience_srvtype_s * srvtype, gboolean include_expired) { guint count = 0U; if (!srvtype) return 0U; if (include_expired) return g_hash_table_size(srvtype->services_ht); else { time_t oldest = oio_ext_monotonic_seconds () - srvtype->score_expiration; struct conscience_srv_s *beacon = &(srvtype->services_ring); for (struct conscience_srv_s *srv = beacon->next; srv && srv != beacon; srv = srv->next) { if (srv->score.timestamp < oldest) break; count++; } } return count; }
guint conscience_srvtype_remove_expired(struct conscience_srvtype_s * srvtype, service_callback_f * callback, gpointer u) { g_assert_nonnull (srvtype); guint count = 0U; time_t oldest = oio_ext_monotonic_seconds(); if (oldest > srvtype->score_expiration) oldest -= srvtype->score_expiration; else oldest = 0; GHashTableIter iter; gpointer key, value; g_hash_table_iter_init(&iter, srvtype->services_ht); while (g_hash_table_iter_next(&iter, &key, &value)) { struct conscience_srv_s *pService = value; if (!pService->locked && pService->score.timestamp < oldest) { if (pService->score.value > 0) { if (callback) callback(pService, u); pService->score.value = 0; count++; } } } return count; }
gboolean conscience_srvtype_run_all(struct conscience_srvtype_s * srvtype, GError ** error, guint32 flags, service_callback_f * callback, gpointer udata) { if (!srvtype || !callback) { GSETERROR(error, "Invalid parameter"); return FALSE; } gboolean rc = TRUE; time_t oldest = oio_ext_monotonic_seconds () - srvtype->score_expiration; const struct conscience_srv_s *beacon = &(srvtype->services_ring); for (struct conscience_srv_s *srv = beacon->next; rc && srv != NULL && srv != beacon; srv = srv->next) { if (srv->locked || srv->score.timestamp > oldest) rc = callback(srv, udata); } if (rc && (flags & SRVTYPE_FLAG_ADDITIONAL_CALL)) rc = callback(NULL, udata); return rc; }
static gboolean _zmq2agent_manage_event (guint32 r, struct _zmq2agent_ctx_s *ctx, zmq_msg_t *msg) { const time_t now = oio_ext_monotonic_seconds(); if (!ctx->zagent) return TRUE; const size_t len = zmq_msg_size(msg); struct event_s *evt = g_malloc (sizeof(struct event_s) + len); memcpy (evt->message, zmq_msg_data(msg), len); evt->last_sent = now; evt->rand = r; evt->evtid = ctx->q->counter ++; evt->procid = ctx->q->procid; evt->size = len; evt->recv_time = evt->last_sent; ctx->pending_events = g_list_prepend (ctx->pending_events, evt); ctx->q->gauge_pending ++; gchar strid[1+ 2*HEADER_SIZE]; oio_str_bin2hex(evt, HEADER_SIZE, strid, sizeof(strid)); GRID_DEBUG("EVT:DEF %s (%u) %.*s", strid, ctx->q->gauge_pending, evt->size, evt->message); return _zmq2agent_send_event (now, ctx, evt, strid); }
static void _retry_events (struct _zmq2agent_ctx_s *ctx) { gchar strid[1+(2*HEADER_SIZE)]; const time_t now = oio_ext_monotonic_seconds (); const time_t oldest = now > 5 ? now - 5 : 0; for (GList *l=g_list_last(ctx->pending_events); l ;l=l->prev) { struct event_s *evt = l->data; if (evt->last_sent < oldest) { oio_str_bin2hex(evt, HEADER_SIZE, strid, sizeof(strid)); if (!_zmq2agent_send_event (now, ctx, evt, strid)) break; } } }
static void _task_expire_services_down (gpointer p) { (void) p; gchar *k = NULL; gpointer v = NULL; guint count = 0; gulong oldest = oio_ext_monotonic_seconds() - cs_down_services; SRV_DO(while (lru_tree_get_last(srv_down, (void**)&k, &v)) { EXTRA_ASSERT(k != NULL); EXTRA_ASSERT(v != NULL); gulong when = (gulong)v; if (when >= oldest) break; lru_tree_steal_last(srv_down, (void**)&k, &v); g_free(k); ++ count; });
static void _reload_srvtype(const char *type) { CSURL(cs); GSList *list = NULL; GError *err = conscience_remote_get_services (cs, type, FALSE, &list); if (err) { GRID_WARN("Services listing error for type[%s]: code=%d %s", type, err->code, err->message); g_clear_error(&err); return; } if (GRID_TRACE_ENABLED()) { GRID_TRACE ("SRV loaded %u [%s]", g_slist_length(list), type); } /* reloads the known services */ gulong now = oio_ext_monotonic_seconds (); SRV_WRITE(for (GSList *l=list; l ;l=l->next) { gchar *k = service_info_key (l->data); lru_tree_insert (srv_known, k, (void*)now); });
struct conscience_srv_s * conscience_srvtype_refresh(struct conscience_srvtype_s *srvtype, struct service_info_s *si) { g_assert_nonnull (srvtype); g_assert_nonnull (si); struct conscience_srvid_s srvid; memcpy(&(srvid.addr), &(si->addr), sizeof(addr_info_t)); struct service_tag_s *tag_first = service_info_get_tag(si->tags, NAME_TAGNAME_RAWX_FIRST); gboolean really_first = FALSE; /*register the service if necessary */ struct conscience_srv_s *p_srv = conscience_srvtype_get_srv(srvtype, &srvid); if (!p_srv) { p_srv = conscience_srvtype_register_srv(srvtype, NULL, &srvid); g_assert_nonnull (p_srv); really_first = tag_first && tag_first->type == STVT_BOOL && tag_first->value.b; } /* refresh the tags: create missing, replace existing * (but the tags are not flushed before) */ if (si->tags) { TRACE("Refreshing tags for srv [%.*s]", (int)(LIMIT_LENGTH_SRVDESCR), p_srv->description); const guint max = si->tags->len; for (guint i = 0; i < max; i++) { struct service_tag_s *tag = g_ptr_array_index(si->tags, i); if (tag == tag_first) continue; struct service_tag_s *orig = conscience_srv_ensure_tag(p_srv, tag->name); service_tag_copy(orig, tag); } } p_srv->score.timestamp = oio_ext_monotonic_seconds (); if (si->score.value == SCORE_UNSET || si->score.value == SCORE_UNLOCK) { if (really_first) { GRID_TRACE2("SRV first [%s]", p_srv->description); p_srv->score.value = 0; p_srv->locked = TRUE; } else { if (si->score.value == SCORE_UNLOCK) { if (p_srv->locked) { GRID_TRACE2("SRV unlocked [%s]", p_srv->description); p_srv->locked = FALSE; p_srv->score.value = CLAMP (p_srv->score.value, SCORE_DOWN, SCORE_MAX); } else { GRID_TRACE2("SRV already unlocked [%s]", p_srv->description); } } else { /* UNSET, a.k.a. regular computation */ if (p_srv->locked) { GRID_TRACE2("SRV untouched [%s]", p_srv->description); } else { GError *err = NULL; if (!conscience_srv_compute_score(p_srv, &err)) { GRID_TRACE2("SRV error [%s]: (%d) %s", p_srv->description, err->code, err->message); g_clear_error (&err); } else { GRID_TRACE2("SRV refreshed [%s]", p_srv->description); } } } } } else { /* LOCK */ p_srv->score.value = CLAMP(si->score.value, SCORE_DOWN, SCORE_MAX); if (p_srv->locked) { GRID_TRACE2("SRV already locked [%s]", p_srv->description); } else { p_srv->locked = TRUE; GRID_TRACE2("SRV locked [%s]", p_srv->description); } } return p_srv; }
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); ); }