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;
		}
	}
}
Exemple #6
0
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;
    });
Exemple #7
0
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;
}
Exemple #9
0
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);
		);
	}