enum http_rc_e action_dir_srv_unlink (struct req_args_s *args) { const gchar *type = TYPE(); if (!type) return _reply_format_error (args, NEWERROR( CODE_BAD_REQUEST, "No service type provided")); GError *hook (const gchar * m1) { struct addr_info_s m1a; if (!grid_string_to_addrinfo (m1, NULL, &m1a)) return NEWERROR (CODE_NETWORK_ERROR, "Invalid M1 address"); GError *err = NULL; meta1v2_remote_unlink_service (&m1a, &err, args->url, type); return err; } GError *err = _m1_locate_and_action (args, hook); if (!err || CODE_IS_NETWORK_ERROR(err->code)) { /* Also decache on timeout, a majority of request succeed, * and it will probably silently succeed */ hc_decache_reference_service (resolver, args->url, type); } if (!err) return _reply_success_json (args, NULL); return _reply_common_error (args, err); }
enum http_rc_e action_conscience_info (struct req_args_s *args) { GError *err; const char *v = OPT("what"); if (v && !strcmp(v, "types")) { if (NULL != (err = _cs_check_tokens(args))) return _reply_notfound_error (args, err); GString *out = g_string_new(""); g_string_append_c(out, '['); NSINFO_DO(if (srvtypes && *srvtypes) { g_string_append_c(out, '"'); g_string_append(out, *srvtypes); g_string_append_c(out, '"'); for (gchar **ps = srvtypes+1; *ps ; ps++) { g_string_append_c(out, ','); g_string_append_c(out, '"'); g_string_append(out, *ps); g_string_append_c(out, '"'); } }); g_string_append_c(out, ']'); return _reply_success_json (args, out); }
enum http_rc_e action_dir_srv_renew (struct req_args_s *args, struct json_object *jargs) { (void) jargs; const gchar *type = TYPE(); if (!type) return _reply_format_error (args, NEWERROR(CODE_BAD_REQUEST, "No service type provided")); gboolean autocreate = _request_has_flag (args, PROXYD_HEADER_MODE, "autocreate"); gboolean dryrun = _request_has_flag (args, PROXYD_HEADER_MODE, "dryrun"); gchar **urlv = NULL; GError *hook (const gchar * m1) { struct addr_info_s m1a; if (!grid_string_to_addrinfo (m1, NULL, &m1a)) return NEWERROR (CODE_NETWORK_ERROR, "Invalid M1 address"); GError *err = NULL; urlv = meta1v2_remote_poll_reference_service (&m1a, &err, args->url, type, dryrun, autocreate); return err; } GError *err = _m1_locate_and_action (args, hook); if (!err || CODE_IS_NETWORK_ERROR(err->code)) { /* Also decache on timeout, a majority of request succeed, * and it will probably silently succeed */ hc_decache_reference_service (resolver, args->url, type); } if (err) return _reply_common_error (args, err); EXTRA_ASSERT (urlv != NULL); return _reply_success_json (args, _pack_and_freev_m1url_list (NULL, urlv)); }
enum http_rc_e action_cache_flush_local (struct req_args_s *args) { grid_lbpool_flush (lbpool); hc_resolver_flush_csm0 (resolver); hc_resolver_flush_services (resolver); return _reply_success_json (args, NULL); }
enum http_rc_e action_cs_srvcheck (struct req_args_s *args) { GError *err; if (NULL != (err = _cs_check_tokens(args))) return _reply_notfound_error (args, err); return _reply_success_json (args, NULL); }
static enum http_rc_e _reply_m2_error (struct req_args_s *args, GError * err) { if (!err) return _reply_success_json (args, NULL); g_prefix_error (&err, "M2 error: "); if (err->code == CODE_CONTAINER_NOTEMPTY) return _reply_conflict_error (args, err); return _reply_common_error (args, err); }
enum http_rc_e action_cs_del (struct req_args_s *args) { GError *err; if (NULL != (err = _cs_check_tokens(args))) return _reply_notfound_error (args, err); if (!clear_namespace_services (NS(), TYPE(), &err)) { g_prefix_error (&err, "Agent error: "); return _reply_system_error (args, err); } return _reply_success_json (args, _create_status (CODE_FINAL_OK, "OK")); }
enum http_rc_e action_cs_get (struct req_args_s *args) { GError *err; if (NULL != (err = _cs_check_tokens(args))) return _reply_notfound_error(args, err); GSList *sl = list_namespace_services (NS(), TYPE(), &err); if (NULL != err) { g_slist_free_full (sl, (GDestroyNotify) service_info_clean); g_prefix_error (&err, "Agent error: "); return _reply_system_error (args, err); } return _reply_success_json (args, _cs_pack_and_free_srvinfo_list (sl)); }
enum http_rc_e action_cache_status (struct req_args_s *args) { struct hc_resolver_stats_s s = {{0}}; hc_resolver_info (resolver, &s); GString *gstr = g_string_new ("{"); g_string_append_printf (gstr, " \"csm0\":{" "\"count\":%" G_GINT64_FORMAT ",\"max\":%u,\"ttl\":%lu},", s.csm0.count, s.csm0.max, s.csm0.ttl); g_string_append_printf (gstr, " \"meta1\":{" "\"count\":%" G_GINT64_FORMAT ",\"max\":%u,\"ttl\":%lu}", s.services.count, s.services.max, s.services.ttl); g_string_append_c (gstr, '}'); return _reply_success_json (args, gstr); }
enum http_rc_e action_cs_info (struct req_args_s *args) { GError *err; if (NULL != (err = _cs_check_tokens(args))) return _reply_notfound_error (args, err); struct namespace_info_s ni; memset (&ni, 0, sizeof (ni)); NSINFO_DO(namespace_info_copy (&nsinfo, &ni, NULL)); GString *gstr = g_string_new (""); namespace_info_encode_json (gstr, &ni); namespace_info_clear (&ni); return _reply_success_json (args, gstr); }
static enum http_rc_e action_cache_status (const struct cache_args_s *args) { struct hc_resolver_stats_s s; memset (&s, 0, sizeof (s)); hc_resolver_info (resolver, &s); GString *gstr = g_string_new ("{"); g_string_append_printf (gstr, " \"clock\":%lu,", s.clock); g_string_append_printf (gstr, " \"csm0\":{" "\"count\":%" G_GINT64_FORMAT ",\"max\":%u,\"ttl\":%lu},", s.csm0.count, s.csm0.max, s.csm0.ttl); g_string_append_printf (gstr, " \"meta1\":{" "\"count\":%" G_GINT64_FORMAT ",\"max\":%u,\"ttl\":%lu}", s.services.count, s.services.max, s.services.ttl); g_string_append_c (gstr, '}'); return _reply_success_json (args->rp, gstr); }
static enum http_rc_e action_status(struct req_args_s *args) { if (0 == strcasecmp("HEAD", args->rq->cmd)) return _reply_success_json(args, NULL); if (0 != strcasecmp("GET", args->rq->cmd)) return _reply_method_error(args); GString *gstr = g_string_sized_new (128); /* first, the stats about all the requests received */ GArray *array = network_server_stat_getall(args->rq->client->server); for (guint i=0; i<array->len ; ++i) { struct server_stat_s *st = &g_array_index (array, struct server_stat_s, i); g_string_append_printf (gstr, "%s = %"G_GUINT64_FORMAT"\n", g_quark_to_string (st->which), st->value); } g_array_free (array, TRUE); /* some stats about the internal cache */ struct hc_resolver_stats_s s = {0}; hc_resolver_info(resolver, &s); g_string_append_printf(gstr, "gauge cache.dir.count = %"G_GINT64_FORMAT"\n", s.csm0.count); g_string_append_printf(gstr, "gauge cache.dir.max = %u\n", s.csm0.max); g_string_append_printf(gstr, "gauge cache.dir.ttl = %lu\n", s.csm0.ttl); g_string_append_printf(gstr, "gauge cache.dir.clock = %lu\n", s.clock); g_string_append_printf(gstr, "gauge cache.srv.count = %"G_GINT64_FORMAT"\n", s.services.count); g_string_append_printf(gstr, "gauge cache.srv.max = %u\n", s.services.max); g_string_append_printf(gstr, "gauge cache.srv.ttl = %lu\n", s.services.ttl); g_string_append_printf(gstr, "gauge cache.srv.clock = %lu\n", s.clock); gint64 count_down = 0; SRV_DO(count_down = lru_tree_count(srv_down)); g_string_append_printf(gstr, "gauge down.srv = %"G_GINT64_FORMAT"\n", count_down); args->rp->set_body_gstr(gstr); args->rp->set_status(HTTP_CODE_OK, "OK"); args->rp->set_content_type("text/x-java-properties"); args->rp->finalize(); return HTTPRC_DONE; }
static enum http_rc_e _registration (struct req_args_s *args, enum reg_op_e op, struct json_object *jsrv) { GError *err; if (!push_queue) return _reply_bad_gateway(args, NEWERROR(CODE_INTERNAL_ERROR, "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); if (err) { if (err->code == CODE_BAD_REQUEST) return _reply_format_error (args, err); else return _reply_system_error (args, err); } if (!validate_namespace (si->ns_name)) { service_info_clean (si); return _reply_system_error (args, NEWERROR (CODE_NAMESPACE_NOTMANAGED, "Unexpected NS")); } si->score.timestamp = network_server_bogonow(args->rq->client->server); if (op == REGOP_PUSH) si->score.value = SCORE_UNSET; else if (op == REGOP_UNLOCK) si->score.value = SCORE_UNLOCK; else /* if (op == REGOP_LOCK) */ si->score.value = CLAMP(si->score.value, SCORE_DOWN, SCORE_MAX); gchar *key = service_info_key(si); PUSH_DO(lru_tree_insert(push_queue, key, si)); GString *gstr = g_string_new (""); service_info_encode_json (gstr, si); return _reply_success_json (args, gstr); }
enum http_rc_e action_dir_srv_force (struct req_args_s *args, struct json_object *jargs) { struct meta1_service_url_s *m1u = NULL; const gchar *type = TYPE(); if (!type) return _reply_format_error (args, NEWERROR(CODE_BAD_REQUEST, "No service type provided")); gboolean force = _request_has_flag (args, PROXYD_HEADER_MODE, "replace"); gboolean autocreate = _request_has_flag (args, PROXYD_HEADER_MODE, "autocreate"); GError *hook (const gchar * m1) { struct addr_info_s m1a; if (!grid_string_to_addrinfo (m1, NULL, &m1a)) return NEWERROR (CODE_NETWORK_ERROR, "Invalid M1 address"); GError *e = NULL; gchar *packed = meta1_pack_url (m1u); meta1v2_remote_force_reference_service (&m1a, &e, args->url, packed, autocreate, force); g_free (packed); return e; } GError *err = meta1_service_url_load_json_object (jargs, &m1u); if (!err) err = _m1_locate_and_action (args, hook); if (m1u) { meta1_service_url_clean (m1u); m1u = NULL; } if (!err || CODE_IS_NETWORK_ERROR(err->code)) { /* Also decache on timeout, a majority of request succeed, * and it will probably silently succeed */ hc_decache_reference_service (resolver, args->url, type); } if (err) return _reply_common_error (args, err); return _reply_success_json (args, NULL); }
enum http_rc_e action_dir_srv_list (struct req_args_s *args) { const gchar *type = TYPE(); if (!type) return _reply_format_error (args, NEWERROR( CODE_BAD_REQUEST, "No service type provided")); gchar **urlv = NULL; GError *err = hc_resolve_reference_service (resolver, args->url, type, &urlv); EXTRA_ASSERT ((err != NULL) ^ (urlv != NULL)); if (!err) { if ((args->flags & FLAG_NOEMPTY) && !*urlv) { g_strfreev (urlv); urlv = NULL; return _reply_notfound_error (args, NEWERROR (CODE_NOT_FOUND, "No service linked")); } return _reply_success_json (args, _pack_and_freev_m1url_list (NULL, urlv)); } return _reply_common_error (args, err); }
static enum http_rc_e action_cache_set_max_high (const struct cache_args_s *args) { hc_resolver_set_max_csm0 (resolver, args->count); return _reply_success_json (args->rp, NULL); }
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, NEWERROR(CODE_INTERNAL_ERROR, "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) { 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]) { 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, NEWERROR (CODE_NAMESPACE_NOTMANAGED, "Unexpected NS")); } si->score.timestamp = oio_ext_real_time () / G_TIME_SPAN_SECOND; if (op == REGOP_PUSH) si->score.value = SCORE_UNSET; else if (op == REGOP_UNLOCK) si->score.value = SCORE_UNLOCK; else /* if (op == REGOP_LOCK) */ si->score.value = CLAMP(si->score.value, SCORE_DOWN, SCORE_MAX); // TODO follow the DRY principle and factorize this! if (flag_cache_enabled) { GString *gstr = g_string_new (""); service_info_encode_json (gstr, si, TRUE); PUSH_DO(lru_tree_insert(push_queue, service_info_key(si), si)); return _reply_success_json (args, gstr); } else { CSURL(cs); GSList l = {.data = si, .next = NULL}; if (NULL != (err = conscience_remote_push_services (cs, &l))) { service_info_clean (si); return _reply_common_error (args, err); } else { GString *gstr = g_string_new (""); service_info_encode_json (gstr, si, TRUE); service_info_clean (si); return _reply_success_json (args, gstr); } } }
enum http_rc_e action_cache_set_ttl_low (struct req_args_s *args) { hc_resolver_set_ttl_services (resolver, atoi (TOK ("COUNT"))); return _reply_success_json (args, NULL); }
enum http_rc_e action_forward (struct req_args_s *args) { const char *id = OPT("id"); const char *action = TOK("ACTION"); if (!id) return _reply_format_error (args, BADREQ("Missing SRVID")); if (!action) return _reply_format_error (args, BADREQ("Missing action")); GError *err = NULL; if (!g_ascii_strcasecmp (action, "flush")) { err = sqlx_remote_execute_FLUSH (id); if (!err) return _reply_success_json (args, NULL); return _reply_common_error (args, err); } if (!g_ascii_strcasecmp (action, "reload")) { err = sqlx_remote_execute_RELOAD (id); if (!err) return _reply_success_json (args, NULL); return _reply_common_error (args, err); } if (!g_ascii_strcasecmp (action, "kill")) { GByteArray *encoded = message_marshall_gba_and_clean ( metautils_message_create_named("REQ_KILL")); err = gridd_client_exec (id, 1.0, encoded); if (err) return _reply_common_error (args, err); return _reply_success_json (args, NULL); } if (!g_ascii_strcasecmp (action, "ping")) { args->rp->no_access(); GByteArray *encoded = message_marshall_gba_and_clean ( metautils_message_create_named("REQ_PING")); err = gridd_client_exec (id, 1.0, encoded); if (err) return _reply_common_error (args, err); return _reply_success_json (args, NULL); } if (!g_ascii_strcasecmp (action, "lean-glib")) { MESSAGE req = metautils_message_create_named("REQ_LEAN"); metautils_message_add_field_str(req, "LIBC", "1"); metautils_message_add_field_str(req, "THREADS", "1"); GByteArray *encoded = message_marshall_gba_and_clean (req); err = gridd_client_exec (id, 1.0, encoded); if (err) return _reply_common_error (args, err); return _reply_success_json (args, NULL); } if (!g_ascii_strcasecmp (action, "lean-sqlx")) { GByteArray *encoded = message_marshall_gba_and_clean ( metautils_message_create_named(NAME_MSGNAME_SQLX_LEANIFY)); err = gridd_client_exec (id, 1.0, encoded); if (err) return _reply_common_error (args, err); return _reply_success_json (args, NULL); } if (!g_ascii_strcasecmp (action, "version")) { args->rp->no_access(); MESSAGE req = metautils_message_create_named("REQ_VERSION"); GByteArray *encoded = message_marshall_gba_and_clean (req); gchar *packed = NULL; err = gridd_client_exec_and_concat_string (id, 1.0, encoded, &packed); if (err) { g_free0 (packed); return _reply_common_error (args, err); } /* TODO(jfs): quite duplicated from _reply_json() but the original was not suitable. */ args->rp->set_status (200, "OK"); args->rp->set_body_bytes (g_bytes_new_take((guint8*)packed, strlen(packed))); args->rp->finalize (); return HTTPRC_DONE; } if (!g_ascii_strcasecmp (action, "handlers")) { args->rp->no_access(); MESSAGE req = metautils_message_create_named("REQ_HANDLERS"); GByteArray *encoded = message_marshall_gba_and_clean (req); gchar *packed = NULL; err = gridd_client_exec_and_concat_string (id, 1.0, encoded, &packed); if (err) { g_free0 (packed); return _reply_common_error (args, err); } /* TODO(jfs): quite duplicated from _reply_json() but the original was not suitable. */ args->rp->set_status (200, "OK"); args->rp->set_body_bytes (g_bytes_new_take((guint8*)packed, strlen(packed))); args->rp->finalize (); return HTTPRC_DONE; } return _reply_common_error (args, BADREQ("unexpected action")); }
enum http_rc_e action_cache_set_max_high (struct req_args_s *args) { hc_resolver_set_max_csm0 (resolver, atoi (TOK ("COUNT"))); return _reply_success_json (args, NULL); }
enum http_rc_e action_cache_flush_high (struct req_args_s *args) { hc_resolver_flush_csm0 (resolver); return _reply_success_json (args, NULL); }
enum http_rc_e action_cache_flush_low (struct req_args_s *args) { hc_resolver_flush_services (resolver); return _reply_success_json (args, NULL); }
static enum http_rc_e action_cache_set_ttl_low (const struct cache_args_s *args) { hc_resolver_set_ttl_services (resolver, args->count); return _reply_success_json (args->rp, NULL); }
static enum http_rc_e action_cache_flush_low (const struct cache_args_s *args) { hc_resolver_flush_services (resolver); return _reply_success_json (args->rp, NULL); }