static GError* location_from_chunk_id(const gchar *chunk_id, const gchar *ns_name, struct oio_lb_pool_s *pool, oio_location_t *location) { g_assert_nonnull(location); GError *err = NULL; if (chunk_id == NULL || strlen(chunk_id) <= 0) return NEWERROR(CODE_INTERNAL_ERROR, "emtpy chunk id"); gchar *netloc = NULL; oio_parse_chunk_url(chunk_id, NULL, &netloc, NULL); if (pool) { gchar *key = oio_make_service_key(ns_name, NAME_SRVTYPE_RAWX, netloc); struct oio_lb_item_s *item = oio_lb_pool__get_item(pool, key); g_free(key); if (item) { *location = item->location; g_free(item); goto out; } } addr_info_t ai = {{0}}; if (!err && !grid_string_to_addrinfo(netloc, &ai)) err = NEWERROR(CODE_INTERNAL_ERROR, "could not parse [%s] to addrinfo", netloc); if (!err) *location = location_from_addr_info(&ai); out: g_free(netloc); return err; }
static int _connect(const gchar *url, GError **err) { struct addr_info_s ai; memset(&ai, 0, sizeof(ai)); if (!grid_string_to_addrinfo(url, NULL, &ai)) { *err = NEWERROR(EINVAL, "invalid URL"); return -1; } if (!ai.port) { *err = NEWERROR(EINVAL, "no port"); return -1; } int fd = addrinfo_connect_nopoll(&ai, 1000, err); if (0 > fd) return -1; sock_set_linger_default(fd); sock_set_nodelay(fd, TRUE); sock_set_tcpquickack(fd, TRUE); *err = NULL; return fd; }
static GError * _m1_action (struct req_args_s *args, gchar ** m1v, GError * (*hook) (const gchar * m1)) { for (gchar ** pm1 = m1v; *pm1; ++pm1) { struct meta1_service_url_s *m1 = meta1_unpack_url (*pm1); if (!m1) continue; if (0 != g_ascii_strcasecmp(m1->srvtype, "meta1")) { meta1_service_url_clean (m1); continue; } struct addr_info_s m1a; if (!grid_string_to_addrinfo (m1->host, NULL, &m1a)) { GRID_INFO ("Invalid META1 [%s] for [%s]", m1->host, hc_url_get (args->url, HCURL_WHOLE)); meta1_service_url_clean (m1); continue; } GError *err = hook (m1->host); meta1_service_url_clean (m1); if (!err) return NULL; else if (err->code == CODE_REDIRECT) g_clear_error (&err); else { g_prefix_error (&err, "META1 error: "); return err; } } return NEWERROR (CODE_UNAVAILABLE, "No meta1 answered"); }
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_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)); }
static GError* _unref_meta1(gchar **urls) { GError *error = NULL; GSList *prefixByMeta1 = meta0_utils_array_to_list(context->array_meta1_by_prefix); guint8 *prefix_mask = g_malloc0(8192); for(;*urls;urls++) { addr_info_t addr; GRID_DEBUG("unref url %s",*urls); grid_string_to_addrinfo(*urls,NULL,&addr); GSList *l=prefixByMeta1; for (;l;l=l->next) { struct meta0_info_s *m0info; if (!(m0info = l->data)) continue; if (addr_info_equal(&(m0info->addr),&addr)) { guint16 *p, *max; p = (guint16*) m0info->prefixes; max = (guint16*) (m0info->prefixes + m0info->prefixes_size); for (; p<max; p++) { if (_is_treat_prefix(prefix_mask,(guint8*)p) ) { GRID_WARN("prefix %02X%02X manage by two meta1 present in the request",((guint8*)p)[0],((guint8*)p)[1]); error = NEWERROR(0, "prefix %02X%02X manage by two meta1 present in the request",((guint8*)p)[0],((guint8*)p)[1]); goto errorLabel; } _treat_prefix(prefix_mask,(guint8*)p); } } } struct meta0_assign_meta1_s *aM1=NULL; aM1=g_hash_table_lookup(context->map_meta1_ref,*urls); if( !aM1) { aM1 = g_malloc0(sizeof(struct meta0_assign_meta1_s)); aM1->addr=g_strdup(*urls); aM1->score=0; aM1->used=FALSE; g_hash_table_insert(context->map_meta1_ref,strdup(*urls),aM1); } else { aM1->used=FALSE; } } errorLabel : meta0_utils_list_clean(prefixByMeta1); g_free(prefix_mask); return error; }
static gboolean srv_to_addr(const gchar *srv, struct addr_info_s *a) { const gchar *type, *addr; type = strchr(srv, '|') + 1; /* skip the sequence number*/ addr = strchr(type, '|') + 1; /* skip the service type */ if (!addr) return FALSE; return grid_string_to_addrinfo(addr, strchr(addr, '|'), a); }
gboolean metautils_url_valid_for_bind(const gchar *url) { if (NULL == url) { errno = EINVAL; return FALSE; } addr_info_t ai = {{0}}; if (!grid_string_to_addrinfo(url, &ai)) return FALSE; return metautils_addr_valid_for_bind(&ai); }
static void _dump_addr (const char *s) { gchar str[256], hexa[1024]; struct addr_info_s addr; if (grid_string_to_addrinfo(s, &addr)) { memset(str, 0, sizeof(str)); grid_addrinfo_to_string(&addr, str, sizeof(str)); memset(hexa, 0, sizeof(hexa)); oio_str_bin2hex(&addr, sizeof(addr), hexa, sizeof(hexa)); g_print("%s %s\n", str, hexa); } }
static gboolean _tree2list_traverser(gpointer k, gpointer v, gpointer u) { struct meta0_info_s *m0i; hashstr_t *hurl = k; GArray *pfx = v; GSList **pl = u; m0i = g_malloc0(sizeof(*m0i)); grid_string_to_addrinfo(hashstr_str(hurl), &(m0i->addr)); m0i->prefixes_size = 2 * pfx->len; m0i->prefixes = g_memdup(pfx->data, m0i->prefixes_size); *pl = g_slist_prepend(*pl, m0i); return FALSE; }
enum http_rc_e action_dir_srv_relink (struct req_args_s *args, struct json_object *jargs) { GError *err = NULL; struct meta1_service_url_s *m1u_kept = NULL, *m1u_repl = NULL; gchar **newset = NULL; const gchar *type = TYPE(); if (!type) return _reply_format_error (args, NEWERROR(CODE_BAD_REQUEST, "No service type provided")); gboolean dryrun = _request_has_flag (args, PROXYD_HEADER_MODE, "dryrun"); struct json_object *jkept, *jrepl; struct metautils_json_mapping_s mapping[] = { {"kept", &jkept, json_type_object, 0}, {"replaced", &jrepl, json_type_object, 0}, {NULL, NULL, 0, 0} }; err = metautils_extract_json (jargs, mapping); if (!err && jkept && json_object_is_type(jkept, json_type_object)) { if (NULL != (err = meta1_service_url_load_json_object (jkept, &m1u_kept))) g_prefix_error (&err, "invalid service in [%s]: ", "kept"); } if (!err && jrepl && json_object_is_type(jrepl, json_type_object)) { if (NULL != (err = meta1_service_url_load_json_object (jrepl, &m1u_repl))) g_prefix_error (&err, "invalid service in [%s]: ", "replaced"); } if (!err) { gchar *kept = NULL, *repl = 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"); if (newset) g_strfreev (newset); return meta1v2_remote_relink_service (&m1a, args->url, kept, repl, dryrun, &newset); } kept = meta1_pack_url (m1u_kept); repl = m1u_repl ? meta1_pack_url (m1u_repl) : NULL; err = _m1_locate_and_action (args, hook); g_free (kept); g_free (repl); }
GError* service_info_load_json_object(struct json_object *obj, struct service_info_s **out, gboolean permissive) { EXTRA_ASSERT(out != NULL); *out = NULL; struct json_object *ns, *type, *url, *score, *tags; struct oio_ext_json_mapping_s mapping[] = { {"ns", &ns, json_type_string, !permissive}, {"type", &type, json_type_string, !permissive}, {"addr", &url, json_type_string, 1}, {"score", &score, json_type_int, !permissive}, {"tags", &tags, json_type_object, 0}, {NULL, NULL, 0, 0} }; GError *err = oio_ext_extract_json (obj, mapping); if (err) return err; struct addr_info_s addr; if (!grid_string_to_addrinfo(json_object_get_string(url), &addr)) return NEWERROR(CODE_BAD_REQUEST, "Invalid address"); struct service_info_s *si = g_malloc0(sizeof(struct service_info_s)); if (ns) g_strlcpy(si->ns_name, json_object_get_string(ns), sizeof(si->ns_name)); memcpy (&si->addr, &addr, sizeof(struct addr_info_s)); if (type) g_strlcpy(si->type, json_object_get_string(type), sizeof(si->type)); if (score) si->score.value = json_object_get_int(score); if (tags) { json_object_object_foreach(tags,key,val) { if (!g_str_has_prefix(key, "tag.") && !g_str_has_prefix(key, "stat.")) continue; struct service_tag_s *tag = _srvtag_load_json(key, val); if (tag) { if (!si->tags) si->tags = g_ptr_array_new(); g_ptr_array_add(si->tags, tag); } } } *out = si; return NULL; }
// TODO(srvid): do not suppose url is an IP address static oio_location_t * __locations_from_m1srvurl(struct meta1_service_url_s **urls) { GArray *out = g_array_new(TRUE, TRUE, sizeof(oio_location_t)); struct meta1_service_url_s **cursor = NULL; for (cursor = urls; cursor && *cursor; cursor++) { struct meta1_service_url_s **extracted; extracted = expand_url(*cursor); addr_info_t ai = {{0}}; if (!grid_string_to_addrinfo((*extracted)->host, &ai)) GRID_WARN("Could not parse [%s] to addrinfo", (*cursor)->host); else { oio_location_t loc = location_from_addr_info(&ai); g_array_append_val(out, loc); } meta1_service_url_cleanv(extracted); extracted = NULL; } return (oio_location_t*)g_array_free(out, FALSE); }
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); }
static struct grid_lbpool_s * _init_lb(const gchar *ns) { struct def_s { const gchar *url, *loc; }; static struct def_s defs[] = { {"127.0.0.1:1025","site0.salle0.baie0.device0"}, {"127.0.0.1:1026","site0.salle0.baie0.device1"}, {"127.0.0.1:1027","site0.salle0.baie1.device0"}, {"127.0.0.1:1028","site0.salle1.baie0.device0"}, {"127.0.0.1:1029","site0.salle1.baie1.device0"}, {"127.0.0.1:1030","site0.salle1.baie0.device1"}, {NULL,NULL} }; struct def_s *pdef = defs; gint score = 0; gboolean provide(struct service_info_s **p_si) { struct service_info_s *si; if (!pdef->url) return FALSE; si = g_malloc0(sizeof(*si)); metautils_strlcpy_physical_ns(si->ns_name, "NS", sizeof(si->ns_name)); g_strlcpy(si->type, "rawx", sizeof(si->type)); si->score.timestamp = time(0); si->score.value = ++score; grid_string_to_addrinfo(pdef->url, NULL, &(si->addr)); pdef++; *p_si = si; return TRUE; } struct grid_lbpool_s *glp = grid_lbpool_create(ns); g_assert(glp != NULL); grid_lbpool_configure_string(glp, "rawx", "RR"); grid_lbpool_reload(glp, "rawx", provide); return glp; }
static gboolean _configure_registration(struct sqlx_service_s *ss) { struct service_info_s *si = ss->si; si->tags = g_ptr_array_new(); g_strlcpy(si->ns_name, ss->ns_name, sizeof(si->ns_name)); g_strlcpy(si->type, ss->service_config->srvtype, sizeof(si->type)); grid_string_to_addrinfo(ss->announce->str, &(si->addr)); service_tag_set_value_string( service_info_ensure_tag(si->tags, "tag.type"), ss->service_config->srvtag); _add_custom_tags(si, ss->custom_tags); service_tag_set_value_string( service_info_ensure_tag(si->tags, "tag.vol"), ss->volume); return TRUE; }
static GError* _cache_load_from_ns(struct meta1_prefixes_set_s *m1ps, const gchar *ns_name, const gchar *local_url, GArray **updated_prefixes, gboolean *meta0_ok) { struct addr_info_s local_ai; GError *err = NULL; GSList *l, *m0_list = NULL; guint idx = rand(); gboolean done = FALSE; EXTRA_ASSERT(m1ps != NULL); if (!ns_name || !local_url) { GRID_TRACE("META1 prefix set not configured to be reloaded from a namespace"); return NULL; } memset(&local_ai, 0, sizeof(local_ai)); grid_string_to_addrinfo(local_url, &local_ai); /* Get the META0 address */ err = conscience_get_services (ns_name, NAME_SRVTYPE_META0, FALSE, &m0_list); if (err != NULL) { g_prefix_error(&err, "META0 locate error : "); return err; } if (!m0_list) return NEWERROR(0, "No META0 available in the namespace");; /* Get the prefixes list */ guint max = g_slist_length(m0_list); guint nb_retry = 0; while (nb_retry < max) { struct service_info_s *si; l = g_slist_nth(m0_list, idx%max); if (!(si = l->data)) { nb_retry++; idx++; continue; } err = _cache_load_from_m0(m1ps, ns_name, &local_ai, &(si->addr), updated_prefixes, meta0_ok); if (!err) { done = TRUE; break; } GRID_WARN("M0 cache loading error : (%d) %s", err->code, err->message); if (!CODE_IS_NETWORK_ERROR(err->code)) break; g_clear_error(&err); nb_retry++; idx++; } g_slist_foreach(m0_list, service_info_gclean, NULL); g_slist_free(m0_list); if (!err && !done) err = NEWERROR(0, "No META0 replied"); return err; }