Example #1
0
static int
_do_ping (const char *to)
{
	gint64 pre = oio_ext_monotonic_time();
	GError *err = _remote_ping (to);
	gint64 post = oio_ext_monotonic_time();
	if (!err) {
		g_print ("%s PING OK %"G_GINT64_FORMAT"\n", to, (post-pre));
		return 0;
	} else {
		g_print ("%s PING ERROR %"G_GINT64_FORMAT" (%d) %s\n", to, (post-pre), err->code, err->message);
		g_clear_error (&err);
		return 1;
	}
}
Example #2
0
static void
_client_react(struct gridd_client_s *client)
{
	EXTRA_ASSERT(client != NULL);
	EXTRA_ASSERT(client->abstract.vtable == &VTABLE_CLIENT);

	if (!client)
		return;
	GError *err = NULL;

	client->tv_step = oio_ext_monotonic_time ();
retry:
	if (!(err = _client_manage_event(client))) {
		if (client->step == REP_READING_SIZE && client->reply
				&& client->reply->len >= 4)
				goto retry;
	}
	else {
		_client_reset_request(client);
		_client_reset_reply(client);
		_client_reset_cnx(client);
		client->error = err;
		client->step = STATUS_FAILED;
	}
}
GError*
gridd_client_step(struct gridd_client_s *client)
{
	int rc;
	struct pollfd pfd = {-1, 0, 0};

	if (!_client_to_pollfd(client, &pfd))
		return NULL;

retry:
	rc = metautils_syscall_poll(&pfd, 1, 1000);
	if (rc == 0) {
		gridd_client_expire(client, oio_ext_monotonic_time ());
		return NULL;
	}
	if (rc < 0) {
		if (errno == EINTR) goto retry;
		return NEWERROR(errno, "poll errno=%d %s", errno, strerror(errno));
	}

	if (pfd.revents & POLLERR) {
		GError *err = socket_get_error(pfd.fd);
		g_prefix_error(&err, "%s: ", gridd_client_url(client));
		gridd_client_fail(client, err);
		g_clear_error(&err);
	}
	else if (pfd.revents & (POLLIN|POLLOUT)) {
		gridd_client_react(client);
	}
	return NULL;
}
Example #4
0
static gboolean
_client_start(struct gridd_client_s *client)
{
	EXTRA_ASSERT(client != NULL);
	EXTRA_ASSERT(client->abstract.vtable == &VTABLE_CLIENT);

	client->tv_start = client->tv_step = oio_ext_monotonic_time ();

	if (client->step != NONE)
		return FALSE;

	if (!client->url[0]) {
		_client_reset_error(client);
		client->error = NEWERROR(EINVAL, "No target");
		return FALSE;
	}

	GError *err = _client_connect(client);
	if (NULL == err)
		return TRUE;

	client->step = STATUS_FAILED;
	client->error = err;
	return FALSE;
}
Example #5
0
static enum http_rc_e
handler_action (struct http_request_s *rq, struct http_reply_ctx_s *rp)
{
	// Get a request id for the current request
	const gchar *reqid = g_tree_lookup (rq->tree_headers, PROXYD_HEADER_REQID);
	if (reqid)
		oio_ext_set_reqid(reqid);
	else
		oio_ext_set_random_reqid();

	// Then parse the request to find a handler
	struct oio_url_s *url = NULL;
	struct oio_requri_s ruri = {NULL, NULL, NULL, NULL};
	oio_requri_parse (rq->req_uri, &ruri);

	struct path_matching_s **matchings = _metacd_match (rq->cmd, ruri.path);

	GRID_TRACE2("URI path[%s] query[%s] fragment[%s] matches[%u]",
			ruri.path, ruri.query, ruri.fragment,
			g_strv_length((gchar**)matchings));

	GQuark gq_count = gq_count_unexpected;
	GQuark gq_time = gq_time_unexpected;

	enum http_rc_e rc;
	if (!*matchings) {
		rp->set_content_type ("application/json");
		rp->set_body_gstr (g_string_new("{\"status\":404,\"message\":\"No handler found\"}"));
		rp->set_status (HTTP_CODE_NOT_FOUND, "No handler found");
		rp->finalize ();
		rc = HTTPRC_DONE;
	} else {
		struct req_args_s args = {0};
		args.req_uri = &ruri;
		args.matchings = matchings;
		args.rq = rq;
		args.rp = rp;

		args.url = url = _metacd_load_url (&args);
		rp->subject(oio_url_get(url, OIOURL_HEXID));
		gq_count = (*matchings)->last->gq_count;
		gq_time = (*matchings)->last->gq_time;
		GRID_TRACE("%s %s URL %s", __FUNCTION__, ruri.path, oio_url_get(args.url, OIOURL_WHOLE));
		req_handler_f handler = (*matchings)->last->u;
		rc = (*handler) (&args);
	}

	gint64 spent = oio_ext_monotonic_time () - rq->client->time.evt_in;

	network_server_stat_push4 (rq->client->server, TRUE,
			gq_count, 1, gq_count_all, 1,
			gq_time, spent, gq_time_all, spent);

	path_matching_cleanv (matchings);
	oio_requri_clear (&ruri);
	oio_url_pclean (&url);
	oio_ext_set_reqid (NULL);
	return rc;
}
Example #6
0
static void
_task_expire_resolver(gpointer p)
{
	hc_resolver_set_now(PSRV(p)->resolver, oio_ext_monotonic_time () / G_TIME_SPAN_SECOND);
	guint count = hc_resolver_expire(PSRV(p)->resolver);
	if (count)
		GRID_DEBUG("Expired %u entries from the resolver cache", count);
}
static void
_zmq2agent_worker (struct _zmq2agent_ctx_s *ctx)
{
	/* XXX(jfs): a dedicated PRNG avoids locking the glib's PRNG for each call
	   (such global locks are present in the GLib) and opening it with a seed
	   from the glib's PRNG avoids syscalls to the special file /dev/urandom */
	GRand *r = g_rand_new_with_seed (g_random_int ());

	gint64 last_debug = oio_ext_monotonic_time ();

	zmq_pollitem_t pi[2] = {
		{ctx->zpull, -1, ZMQ_POLLIN, 0},
		{ctx->zagent, -1, ZMQ_POLLIN, 0},
	};

	for (gboolean run = TRUE; run ;) {
		int rc = zmq_poll (pi, 2, 1000);
		if (rc < 0) {
			int err = zmq_errno();
			if (err != ETERM && err != EINTR)
				GRID_WARN("ZMQ poll error : (%d) %s", err, zmq_strerror(err));
			if (err != EINTR)
				break;
		}
		if (pi[1].revents)
			_zmq2agent_receive_acks (ctx);
		_retry_events (ctx);
		if (pi[0].revents)
			run = _zmq2agent_receive_events (r, ctx);

		/* Periodically write stats in the log */
		gint64 now = oio_ext_monotonic_time ();
		if ((now - last_debug) > 2 * G_TIME_SPAN_MINUTE) {
			GRID_INFO("ZMQ2AGENT recv=%"G_GINT64_FORMAT" sent=%"G_GINT64_FORMAT
					" ack=%"G_GINT64_FORMAT"+%"G_GINT64_FORMAT" queue=%u",
					ctx->q->counter_received, ctx->q->counter_sent,
					ctx->q->counter_ack, ctx->q->counter_ack_notfound,
					ctx->q->gauge_pending);
			last_debug = now;
		}
	}

	g_rand_free (r);
	GRID_INFO ("Thread stopping [NOTIFY-ZMQ2AGENT]");
}
Example #8
0
static int
_ping(gchar *dest, gchar *to)
{
	gdouble timeout = g_ascii_strtod(to, NULL);
	GByteArray *encoded = message_marshall_gba_and_clean (
			metautils_message_create_named("REQ_PING"));
	gint64 start = oio_ext_monotonic_time();
	GError *err = gridd_client_exec(dest, timeout, encoded);
	gint64 end = oio_ext_monotonic_time();
	if (err) {
		g_print("KO (%d) %s\n", err->code, err->message);
		g_clear_error(&err);
		return 1;
	} else {
		g_print("OK %lfs\n", (end - start) / (gdouble)G_TIME_SPAN_SECOND);
		return 0;
	}
}
Example #9
0
static void
_task_react_elections(gpointer p)
{
	if (!grid_main_is_running ())
		return;
	if (!PSRV(p)->flag_replicable)
		return;

	gint64 t = oio_ext_monotonic_time();
	guint count = election_manager_play_timers (PSRV(p)->election_manager,
			PSRV(p)->max_elections_timers_per_round);
	t = t - oio_ext_monotonic_time();

	if (count || t > (500*G_TIME_SPAN_MILLISECOND)) {
		GRID_DEBUG("Reacted %u elections in %"G_GINT64_FORMAT"ms",
				count, t / G_TIME_SPAN_MILLISECOND);
	}
}
Example #10
0
static guint
_lru_tree_expire (GRWLock *rw, struct lru_tree_s *lru, const gint64 delay)
{
	if (delay <= 0) return 0;
	const gint64 now = oio_ext_monotonic_time();
	g_rw_lock_writer_lock (rw);
	guint count = lru_tree_remove_older (lru, OLDEST(now,delay));
	g_rw_lock_writer_unlock (rw);
	return count;
}
Example #11
0
static gboolean
_init_configless_structures(struct sqlx_service_s *ss)
{
	if (!(ss->server = network_server_init())
			|| !(ss->dispatcher = transport_gridd_build_empty_dispatcher())
			|| !(ss->si = g_malloc0(sizeof(struct service_info_s)))
			|| !(ss->clients_pool = gridd_client_pool_create())
			|| !(ss->gsr_reqtime = grid_single_rrd_create(oio_ext_monotonic_time() / G_TIME_SPAN_SECOND, 8))
			|| !(ss->gsr_reqcounter = grid_single_rrd_create(oio_ext_monotonic_time() / G_TIME_SPAN_SECOND,8))
			|| !(ss->resolver = hc_resolver_create1(oio_ext_monotonic_time() / G_TIME_SPAN_SECOND))
			|| !(ss->gtq_admin = grid_task_queue_create("admin"))
			|| !(ss->gtq_register = grid_task_queue_create("register"))
			|| !(ss->gtq_reload = grid_task_queue_create("reload"))) {
		GRID_WARN("SERVICE init error : memory allocation failure");
		return FALSE;
	}

	return TRUE;
}
Example #12
0
static GError*
_client_connect(struct gridd_client_s *client)
{
	GError *err = NULL;
	client->fd = _connect(client->url, &err);

	if (client->fd < 0) {
		EXTRA_ASSERT(err != NULL);
		g_prefix_error(&err, "Connect error: ");
		return err;
	}

	EXTRA_ASSERT(err == NULL);
	client->tv_step = oio_ext_monotonic_time ();
	client->step = CONNECTING;
	return NULL;
}
Example #13
0
static void
SQLX_UNSHIFT(sqlx_cache_t *cache, sqlx_base_t *base,
		struct beacon_s *beacon, enum sqlx_base_status_e status)
{
	sqlx_base_t *first;

	base->link.prev = base->link.next = -1;
	base->link.next = beacon->first;

	first = sqlx_get_by_id(cache, beacon->first);
	if (first)
		first->link.prev = base->index;
	beacon->first = base->index;

	if (beacon->last < 0)
		beacon->last = base->index;

	base->status = status;
	base->last_update = oio_ext_monotonic_time ();
}
static void
_access_log(struct req_ctx_s *r, gint status, gsize out_len, const gchar *tail)
{
	if (r->access_disabled && 2 == (status / 100))
		return;

	const char *reqid = g_tree_lookup(r->request->tree_headers, PROXYD_HEADER_REQID);

	gint64 now = oio_ext_monotonic_time ();
	gint64 diff_total = now - r->tv_start;
	gint64 diff_handler = now - r->tv_parsed;

	GString *gstr = g_string_sized_new(256);

	/* mandatory */
	g_string_append(gstr, ensure(r->client->local_name));
	g_string_append_c(gstr, ' ');
	g_string_append(gstr, ensure(r->client->peer_name));
	g_string_append_c(gstr, ' ');
	g_string_append(gstr, ensure(r->request->cmd));
	g_string_append_printf(gstr, " %d %"G_GINT64_FORMAT" %"G_GSIZE_FORMAT" ",
			status, diff_total, out_len);
	g_string_append(gstr, ensure(r->uid));
	g_string_append_c(gstr, ' ');
	g_string_append(gstr, ensure(reqid));

	/* arbitrary */
	g_string_append_c(gstr, ' ');
	g_string_append(gstr, ensure(r->request->req_uri));
	g_string_append_printf(gstr, " t=%"G_GINT64_FORMAT" ", diff_handler);
	if (tail) {
		g_string_append_c (gstr, ' ');
		g_string_append (gstr, tail);
	}

	g_log("access", GRID_LOGLVL_INFO, "%s", gstr->str);
	g_string_free(gstr, TRUE);
}
Example #15
0
static void
_task_register(gpointer p)
{
	if (PSRV(p)->flag_noregister)
		return;

	/* Computes the avg requests rate/time */
	time_t now = oio_ext_monotonic_time () / G_TIME_SPAN_SECOND;

	grid_single_rrd_push (PSRV(p)->gsr_reqcounter, now,
			network_server_stat_getone(PSRV(p)->server,
				g_quark_from_static_string(OIO_STAT_PREFIX_REQ)));
	grid_single_rrd_push (PSRV(p)->gsr_reqtime, now,
			network_server_stat_getone(PSRV(p)->server,
				g_quark_from_static_string(OIO_STAT_PREFIX_TIME)));

	guint64 avg_counter = grid_single_rrd_get_delta(PSRV(p)->gsr_reqcounter,
			now, 4);
	guint64 avg_time = grid_single_rrd_get_delta(PSRV(p)->gsr_reqtime,
			now, 4);

	avg_counter = MACRO_COND(avg_counter != 0, avg_counter, 1);
	avg_time = MACRO_COND(avg_time != 0, avg_time, 1);

	service_tag_set_value_i64(service_info_ensure_tag(PSRV(p)->si->tags,
				"stat.total_reqpersec"), avg_counter / 4);
	service_tag_set_value_i64(service_info_ensure_tag(PSRV(p)->si->tags,
				"stat.total_avreqtime"), (avg_time)/(avg_counter));

	/* send the registration now */
	GError *err = register_namespace_service(PSRV(p)->si);
	if (err) {
		g_message("Service registration failed: (%d) %s", err->code, err->message);
		g_clear_error(&err);
	}
}
Example #16
0
time_t
oio_ext_monotonic_seconds (void)
{
	return oio_ext_monotonic_time () / G_TIME_SPAN_SECOND;
}
GError *
gridd_clients_step(struct gridd_client_s **clients)
{
	struct gridd_client_s ** _lookup_client(int fd, struct gridd_client_s **ppc) {
		struct gridd_client_s *c;
		for (; (c = *ppc) ;ppc++) {
			if (gridd_client_fd(c) == fd)
				return ppc;
		}
		return ppc;
	}

	guint i, j;
	int rc;
	struct gridd_client_s *last, **plast;
	guint nbclients;

	EXTRA_ASSERT(clients != NULL);
	nbclients = g_strv_length((gchar**)clients);
	EXTRA_ASSERT(nbclients > 0);

	struct pollfd pfd[nbclients];

	for (j=0,plast=clients; NULL != (last = *plast) ;plast++) {
		if (_client_to_pollfd(last, pfd+j))
			j++;
	}
	if (!j)
		return NULL;

retry:
	/* Wait for an event to happen */
	rc = metautils_syscall_poll (pfd, j, 100);
	if (rc == 0) {
		_clients_expire(clients, oio_ext_monotonic_time ());
		return NULL;
	}
	if (rc < 0) {
		if (errno == EINTR) goto retry;
		return NEWERROR(errno, "poll error (%s)", strerror(errno));
	}

	/* Then manage each event */
	for (plast=clients,i=0; i<j ;i++) {
		if (!pfd[i].revents)
			continue;

		/* Find the client for this pollfd */
		plast = _lookup_client(pfd[i].fd, plast);
		EXTRA_ASSERT(plast != NULL);
		last = *plast;

		/* Manage the poll() event */
		if (pfd[i].revents & POLLERR) {
			GError *err = socket_get_error(pfd[i].fd);
			g_prefix_error(&err, "%s: ", gridd_client_url(last));
			gridd_client_fail(last, err);
			g_clear_error(&err);
		}
		else
			gridd_client_react(last);
	}

	/* Now check for expired clients */
	_clients_expire(clients, oio_ext_monotonic_time ());
	return NULL;
}
Example #18
0
GError *
sqlx_cache_open_and_lock_base(sqlx_cache_t *cache, const hashstr_t *hname,
		gint *result)
{
	gint bd;
	GError *err = NULL;
	sqlx_base_t *base = NULL;

	EXTRA_ASSERT(cache != NULL);
	EXTRA_ASSERT(hname != NULL);
	EXTRA_ASSERT(result != NULL);

	gint64 start = oio_ext_monotonic_time();
	gint64 deadline = DEFAULT_CACHE_OPEN_TIMEOUT;
	if (cache->open_timeout > 0)
		deadline = cache->open_timeout;
	GRID_TRACE2("%s(%p,%s,%p) delay = %"G_GINT64_FORMAT, __FUNCTION__,
			(void*)cache, hname ? hashstr_str(hname) : "NULL",
			(void*)result, deadline);
	deadline += start;

	g_mutex_lock(&cache->lock);
	cache->used = TRUE;
retry:

	bd = sqlx_lookup_id(cache, hname);
	if (bd < 0) {
		if (!(err = sqlx_base_reserve(cache, hname, &base))) {
			bd = base->index;
			*result = base->index;
			sqlx_base_debug("OPEN", base);
		}
		else {
			GRID_DEBUG("No base available for [%s] (%d %s)",
					hashstr_str(hname), err->code, err->message);
			if (sqlx_expire_first_idle_base(cache, 0) >= 0) {
				g_clear_error(&err);
				goto retry;
			}
		}
	}
	else {
		base = GET(cache, bd);
		gint64 now = oio_ext_monotonic_time ();

		if (now > deadline) {
			err = NEWERROR (CODE_UNAVAILABLE,
					"DB busy (after %"G_GINT64_FORMAT" ms)",
					(now - start) / G_TIME_SPAN_MILLISECOND);
		} else switch (base->status) {

			case SQLX_BASE_FREE:
				EXTRA_ASSERT(base->count_open == 0);
				EXTRA_ASSERT(base->owner == NULL);
				GRID_ERROR("free base referenced");
				g_assert_not_reached();
				break;

			case SQLX_BASE_IDLE:
			case SQLX_BASE_IDLE_HOT:
				EXTRA_ASSERT(base->count_open == 0);
				EXTRA_ASSERT(base->owner == NULL);
				sqlx_base_move_to_list(cache, base, SQLX_BASE_USED);
				base->count_open ++;
				base->owner = g_thread_self();
				*result = base->index;
				break;

			case SQLX_BASE_USED:
				EXTRA_ASSERT(base->count_open > 0);
				EXTRA_ASSERT(base->owner != NULL);
				if (base->owner != g_thread_self()) {
					GRID_DEBUG("Base [%s] in use by another thread (%X), waiting...",
							hashstr_str(hname), oio_log_thread_id(base->owner));
					/* The lock is held by another thread/request.
					   XXX(jfs): do not use 'now' because it can be a fake clock */
					g_cond_wait_until(base->cond, &cache->lock,
							g_get_monotonic_time() + oio_cache_period_cond_wait);
					goto retry;
				}
				base->owner = g_thread_self();
				base->count_open ++;
				*result = base->index;
				break;

			case SQLX_BASE_CLOSING:
				EXTRA_ASSERT(base->owner != NULL);
				/* Just wait for a notification then retry
				   XXX(jfs): do not use 'now' because it can be a fake clock */
				g_cond_wait_until(base->cond, &cache->lock,
						g_get_monotonic_time() + oio_cache_period_cond_wait);
				goto retry;
		}
	}

	if (base) {
		if (!err) {
			sqlx_base_debug(__FUNCTION__, base);
			EXTRA_ASSERT(base->owner == g_thread_self());
			EXTRA_ASSERT(base->count_open > 0);
		}
		g_cond_signal(base->cond);
	}
	g_mutex_unlock(&cache->lock);
	return err;
}