GError* meta1_backend_services_set(struct meta1_backend_s *m1, struct oio_url_s *url, const char *packedurl, gboolean autocreate, gboolean force) { struct meta1_service_url_s *m1url; if (!(m1url = meta1_unpack_url(packedurl))) return NEWERROR(CODE_BAD_REQUEST, "Invalid URL"); struct sqlx_sqlite3_s *sq3 = NULL; GError *err = _open_and_lock(m1, url, M1V2_OPENBASE_MASTERONLY, &sq3); if (err) { g_free(m1url); return err; } struct sqlx_repctx_s *repctx = NULL; if (!(err = sqlx_transaction_begin(sq3, &repctx))) { if (!(err = __info_user(sq3, url, autocreate, NULL))) err = __save_service(sq3, url, m1url, force); if (!(err = sqlx_transaction_end(repctx, err))) __notify_services_by_cid(m1, sq3, url); } sqlx_repository_unlock_and_close_noerror(sq3); g_free(m1url); /* XXX JFS: ugly quirk until we find a pretty way to distinguish the * commit errors (e.g. it can fail because of a replication error or * a constraint violation) */ if (err && NULL != strstr(err->message, "UNIQUE")) err->code = CODE_SRV_ALREADY; return err; }
static struct meta1_service_url_s * __poll_services(struct meta1_backend_s *m1, guint replicas, struct compound_type_s *ct, guint seq, struct meta1_service_url_s **used, GError **err) { GRID_DEBUG("Polling %u [%s]", replicas, ct->fulltype); // ---------------------------------------------------------------------- GPtrArray *ids = g_ptr_array_new_with_free_func(g_free); oio_location_t *avoid = __locations_from_m1srvurl(used); oio_location_t *known = NULL; if (ct->req.k && !strcmp(ct->req.k, NAME_TAGNAME_USER_IS_SERVICE)) { gchar srvurl[64] = {0}; g_snprintf(srvurl, sizeof(srvurl), "1||%s|", ct->req.v); struct meta1_service_url_s *inplace[2] = { meta1_unpack_url(srvurl), NULL }; /* If ct->req.v is not an addr, known will contain NULL */ // FIXME: this should be in `avoid` instead of `known` // but avoids are compared without the location mask known = __locations_from_m1srvurl(inplace); meta1_service_url_clean(inplace[0]); } void _on_id(oio_location_t loc, const char *id) { (void)loc; g_ptr_array_add(ids, g_strdup(id)); }
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"); }
GError* meta1_backend_services_config(struct meta1_backend_s *m1, struct oio_url_s *url, const char *packedurl) { struct meta1_service_url_s *m1url; if (!(m1url = meta1_unpack_url(packedurl))) return NEWERROR(CODE_BAD_REQUEST, "Invalid URL"); GRID_DEBUG("About to reconfigure [%s] [%"G_GINT64_FORMAT"] [%s] [%s]", m1url->srvtype, m1url->seq, m1url->host, m1url->args); struct sqlx_sqlite3_s *sq3 = NULL; GError *err = _open_and_lock(m1, url, M1V2_OPENBASE_MASTERONLY, &sq3); if (err) { g_free(m1url); return err; } struct sqlx_repctx_s *repctx = NULL; if (!(err = sqlx_transaction_begin(sq3, &repctx))) { if (!(err = __info_user(sq3, url, FALSE, NULL))) err = __configure_service(sq3, url, m1url); if (!(err = sqlx_transaction_end(repctx, err))) __notify_services_by_cid(m1, sq3, url); } sqlx_repository_unlock_and_close_noerror(sq3); g_free(m1url); return err; }
gchar * meta1_strurl_get_address(const gchar *str) { struct meta1_service_url_s *u = meta1_unpack_url(str); gchar *s = g_strdup(u->host); g_free(u); return s; }
static struct meta1_service_url_s * __poll_services(struct meta1_backend_s *m1, guint replicas, struct compound_type_s *ct, guint seq, struct meta1_service_url_s **used, GError **err) { struct grid_lb_iterator_s *iter = NULL; struct service_info_s **siv = NULL; GRID_DEBUG("Polling %u [%s]", replicas, ct->fulltype); if (!(*err = _get_iterator(m1, ct, &iter))) { struct lb_next_opt_ext_s opt; memset(&opt, 0, sizeof(opt)); opt.req.distance = MACRO_COND(replicas>1,1,0); opt.req.max = replicas; opt.req.duplicates = FALSE; opt.req.stgclass = NULL; opt.req.strict_stgclass = TRUE; opt.srv_forbidden = __srvinfo_from_m1srvurl(m1->lb, ct->baretype, used); if (ct->req.k && !strcmp(ct->req.k, NAME_TAGNAME_USER_IS_SERVICE)) { gchar *srvurl = g_strdup_printf("1||%s|", ct->req.v); struct meta1_service_url_s *inplace[2] = { meta1_unpack_url(srvurl), NULL }; /* If ct->req.v is not an addr, srv_inplace will contain NULL */ opt.srv_inplace = __srvinfo_from_m1srvurl(m1->lb, NULL, inplace); opt.req.distance = 1; meta1_service_url_clean(inplace[0]); g_free(srvurl); } else { opt.filter.hook = _filter_tag; opt.filter.data = ct; } if (!grid_lb_iterator_next_set2(iter, &siv, &opt)) { EXTRA_ASSERT(siv == NULL); *err = NEWERROR(CODE_POLICY_NOT_SATISFIABLE, "No service available"); } grid_lb_iterator_clean(iter); iter = NULL; g_slist_free_full(opt.srv_forbidden, (GDestroyNotify)service_info_clean); g_slist_free_full(opt.srv_inplace, (GDestroyNotify)service_info_clean); } if(NULL != *err) return NULL; struct meta1_service_url_s *m1u = _siv_to_url (siv); service_info_cleanv(siv, FALSE); siv = NULL; g_strlcpy(m1u->srvtype, ct->type, sizeof(m1u->srvtype)); m1u->seq = seq; return m1u; }
gboolean meta1_strurl_get_address(const gchar *str, struct addr_info_s *dst) { gboolean rc; struct meta1_service_url_s *u; u = meta1_unpack_url(str); rc = meta1_url_get_address(u, dst); g_free(u); return rc; }
static GString * _pack_m1url_list (GString *gstr, gchar ** urlv) { if (!gstr) gstr = g_string_new (""); g_string_append_c (gstr, '['); for (gchar ** v = urlv; v && *v; v++) { struct meta1_service_url_s *m1 = meta1_unpack_url (*v); meta1_service_url_encode_json (gstr, m1); meta1_service_url_clean (m1); if (*(v + 1)) g_string_append_c (gstr, ','); } g_string_append_c (gstr, ']'); return gstr; }
static void cli_action(void) { /* Use the client to get a sqlx service */ GRID_DEBUG("Locating [%s] CID[%s]", oio_url_get(url, OIOURL_WHOLE), oio_url_get(url, OIOURL_HEXID)); gchar **srvurlv = NULL; GError *err = hc_resolve_reference_service(resolver, url, type, &srvurlv); if (err != NULL) { GRID_ERROR("Services resolution error: (%d) %s", err->code, err->message); grid_main_set_status(1); return; } if (!srvurlv || !*srvurlv) { GRID_ERROR("Services resolution error: (%d) %s", 0, "No service found"); grid_main_set_status(1); return; } for (gchar **s=srvurlv; *s ;s++) GRID_DEBUG("Located [%s]", *s); gint rc = 0; for (gchar **s=srvurlv; !rc && *s ;s++) { struct meta1_service_url_s *surl; if (!(surl = meta1_unpack_url(*s))) g_printerr("Invalid service URL from meta1 [%s]\n", *s); else { if (!g_ascii_strcasecmp("destroy", query[0])) { rc = do_destroy2(surl); } else { rc = do_queryv(surl); } g_free(surl); } } g_strfreev(srvurlv); }