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; } }
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; }
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; }
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; }
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]"); }
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; } }
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); } }
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; }
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; }
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; }
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); }
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); } }
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; }
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; }