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; }
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->backend.lb, ct->baretype, used); 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); } 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; }
static GError* _get_iterator2(struct meta1_backend_s *m1, const char *srvtype, struct grid_lb_iterator_s **result) { struct compound_type_s ct = {0}; *result = NULL; GError *err = compound_type_parse(&ct, srvtype); if (NULL != err) { g_prefix_error(&err, "Type parsing error: "); return err; } err = _get_iterator(m1, &ct, result); if (err) g_prefix_error(&err, "LB error: "); compound_type_clean(&ct); return err; }
GError* meta1_backend_services_relink(struct meta1_backend_s *m1, struct oio_url_s *url, const char *kept, const char *replaced, gboolean dryrun, gchar ***out) { GError *err = NULL; struct meta1_service_url_s **ukept = NULL, **urepl = NULL; /* fields to be prefetched */ struct grid_lb_iterator_s *iterator = NULL; struct compound_type_s ct; memset (&ct, 0, sizeof(ct)); ukept = __parse_and_expand (kept); urepl = __parse_and_expand (replaced); /* Sanity checks: we must receive at least one service */ if ((!ukept || !*ukept) && (!urepl || !*urepl)) { err = NEWERROR (CODE_BAD_REQUEST, "Missing URL set"); goto out; } /* Sanity check : all the services must have the same <seq,type> */ struct meta1_service_url_s *ref = ukept && *ukept ? *ukept : *urepl; for (struct meta1_service_url_s **p = ukept; p && *p ; ++p) { if (0 != _sorter(p, &ref)) { err = NEWERROR(CODE_BAD_REQUEST, "Mismatch in URL set (%s)", "kept"); goto out; } } for (struct meta1_service_url_s **p = urepl; p && *p ; ++p) { if (0 != _sorter(p, &ref)) { err = NEWERROR(CODE_BAD_REQUEST, "Mismatch in URL set (%s)", "kept"); goto out; } } /* prefetch some fields from the backend: the compound type (so it is * parsed only once), the iterator (so we can already poll services, out * of the sqlite3 transaction) */ if (NULL != (err = compound_type_parse(&ct, ref->srvtype))) { err = NEWERROR(CODE_BAD_REQUEST, "Invalid service type"); goto out; } if (NULL != (err = _get_iterator (m1, &ct, &iterator))) { err = NEWERROR(CODE_BAD_REQUEST, "Service type not managed"); goto out; } /* Call the backend logic now */ struct sqlx_sqlite3_s *sq3 = NULL; struct sqlx_repctx_s *repctx = NULL; if (!(err = _open_and_lock(m1, url, M1V2_OPENBASE_MASTERONLY, &sq3))) { if (!(err = sqlx_transaction_begin(sq3, &repctx))) { if (!(err = __info_user(sq3, url, FALSE, NULL))) { struct m1v2_relink_input_s in = { .m1 = m1, .sq3 = sq3, .url = url, .iterator = iterator, .ct = &ct, .kept = ukept, .replaced = urepl, .dryrun = dryrun }; err = __relink_container_services(&in, out); } if (!(err = sqlx_transaction_end(repctx, err))) { if (!dryrun) __notify_services_by_cid(m1, sq3, url); } } sqlx_repository_unlock_and_close_noerror(sq3); } out: meta1_service_url_cleanv (ukept); meta1_service_url_cleanv (urepl); grid_lb_iterator_clean (iterator); compound_type_clean (&ct); return err; }