Пример #1
0
static GError *
__get_container_service2(struct sqlx_sqlite3_s *sq3,
                         struct oio_url_s *url, struct compound_type_s *ct,
                         struct meta1_backend_s *m1, enum m1v2_getsrv_e mode,
                         gchar ***result, gboolean *renewed)
{
    GError *err = NULL;
    struct meta1_service_url_s **used = NULL;
    enum service_update_policy_e policy;
    guint replicas;

    struct service_update_policies_s *pol;
    if (!(pol = meta1_backend_get_svcupdate(m1)))
        return NEWERROR(CODE_POLICY_NOT_SATISFIABLE, "Bad NS/Policy pair");
    policy = service_howto_update(pol, ct->baretype);
    replicas = service_howmany_replicas(pol, ct->baretype);
    replicas = (replicas > 0 ? replicas : 1);
    // Patches the constraint on the service type (if not set in the request)
    // by the constraint set in the NS-wide storage policy.
    compound_type_update_arg(ct, pol, FALSE);

    /* This special "tag" is used for services types that are to be linked
     * to containers belonging to other services (e.g. there is a container
     * for each rawx in the special "_RDIR" account). It tells the load
     * balancer to compare the location of linked service against the
     * location of the container owner. */
    if (ct->req.k && !strcmp(ct->req.k, NAME_TAGNAME_USER_IS_SERVICE)
            && (!ct->req.v || !ct->req.v[0])) {
        oio_str_replace(&(ct->req.v), oio_url_get(url, OIOURL_USER));
    }

    err = __get_container_all_services(sq3, url, ct->type, &used);
    if (NULL != err) {
        g_prefix_error(&err, "Preliminary lookup error : ");
        return err;
    }
    if (used && !*used) {
        g_free(used);
        used = NULL;
    }

    if (used && (mode != M1V2_GETSRV_RENEW)) {
        /* Only keep the services UP, if not forced to renew */
        struct meta1_service_url_s **up = __get_services_up(m1, used);
        if (up && *up) {
            *result = pack_urlv(up);
            meta1_service_url_cleanv(up);
            meta1_service_url_cleanv(used);
            return NULL;
        }
        meta1_service_url_cleanv(up);
    }

    if (used && (mode == M1V2_GETSRV_REUSE || policy == SVCUPD_KEEP)) {
        /* Services used but unavailable, but we are told to reuse */
        *result = pack_urlv(used);
        meta1_service_url_cleanv(used);
        return err;
    }

    /* No service available, poll a new one */
    struct meta1_service_url_s *m1_url = NULL;
    gint seq = urlv_get_max_seq(used);
    seq = (seq<0 ? 1 : seq+1);

    if (NULL != (m1_url = __poll_services(m1, replicas, ct, seq, used, &err))) {
        if (mode != M1V2_GETSRV_DRYRUN) {
            if (NULL == err) {
                if (policy == SVCUPD_REPLACE)
                    err = __delete_service(sq3, url, ct->type);
                if (NULL == err)
                    err = __save_service(sq3, url, m1_url, TRUE);
            }
        }

        if (!err && result) {
            struct meta1_service_url_s **unpacked = expand_url(m1_url);
            *result = pack_urlv(unpacked);
            meta1_service_url_cleanv(unpacked);
            if (renewed) *renewed = TRUE;
        }
        g_free(m1_url);
    }

    meta1_service_url_cleanv(used);
    return err;
}
Пример #2
0
static GError *
__relink_container_services(struct m1v2_relink_input_s *in, gchar ***out)
{
    GError *err = NULL;
    struct service_info_s **polled = NULL;
    struct meta1_service_url_s *packed = NULL;

    struct meta1_service_url_s *ref = (in->kept && in->kept[0])
                                      ? in->kept[0] : in->replaced[0];

    /* check the services provided are those in place */
    struct meta1_service_url_s **inplace = NULL;
    err = __get_container_all_services (in->sq3, in->url, ref->srvtype, &inplace);
    if (!err && !__match_urlv(inplace, in->kept, in->replaced))
        err = NEWERROR(CODE_USER_INUSE, "services changed");
    meta1_service_url_cleanv (inplace);
    inplace = NULL;

    /* it is time to poll */
    if (!err) {
        struct service_update_policies_s *pol = meta1_backend_get_svcupdate(in->m1);
        EXTRA_ASSERT (pol != NULL);

        struct lb_next_opt_ext_s opt;
        memset (&opt, 0, sizeof (opt));
        opt.req.max = service_howmany_replicas (pol, in->ct->baretype);
        opt.req.distance = opt.req.max > 1 ? 1 : 0;
        opt.req.duplicates = FALSE;
        opt.req.stgclass = NULL;
        opt.req.strict_stgclass = TRUE;
        opt.filter.hook = NULL;
        opt.filter.data = NULL;
        if (in->kept)
            opt.srv_inplace = __srvinfo_from_m1srvurl (in->m1->lb,
                              in->ct->baretype, in->kept);
        if (in->replaced)
            opt.srv_forbidden = __srvinfo_from_m1srvurl (in->m1->lb,
                                in->ct->baretype, in->replaced);

        if (g_slist_length(opt.srv_inplace) >= opt.req.max)
            err = NEWERROR(CODE_POLICY_NOT_SATISFIABLE, "Too many services kept");

        if (!err) {
            if (!grid_lb_iterator_next_set2 (in->iterator, &polled, &opt)) {
                EXTRA_ASSERT(polled == NULL);
                err = NEWERROR (CODE_POLICY_NOT_SATISFIABLE, "No service available");
            } else {
                EXTRA_ASSERT(polled != NULL);
            }
        }

        g_slist_free_full (opt.srv_forbidden, (GDestroyNotify)service_info_clean);
        g_slist_free_full (opt.srv_inplace, (GDestroyNotify)service_info_clean);
    }

    /* Services have been polled, them save them.
     * We MUST use the same SEQ number. Since the service are packed in one
     * entry, we can save them with a single SQL statement. */
    if (!err && !in->dryrun) {
        packed = _siv_to_url (polled);
        packed->seq = ref->seq;
        strcpy (packed->srvtype, ref->srvtype);
        err = __save_service (in->sq3, in->url, packed, TRUE);
    }

    /* if the checks, polling and storage succeeded, prepare the output for
     * the caller */
    if (!err) {
        struct meta1_service_url_s **newset = expand_url (packed);
        *out = pack_urlv (newset);
        meta1_service_url_cleanv (newset);
    }

    service_info_cleanv (polled, FALSE);
    meta1_service_url_clean (packed);
    return err;
}
Пример #3
0
static GError *
__get_container_service2(struct sqlx_sqlite3_s *sq3,
		struct oio_url_s *url, struct compound_type_s *ct,
		struct meta1_backend_s *m1, enum m1v2_getsrv_e mode,
		gchar ***result, gboolean *renewed)
{
	GError *err = NULL;
	struct meta1_service_url_s **used = NULL;
	enum service_update_policy_e policy;
	guint replicas;

	struct service_update_policies_s *pol;
	if (!(pol = meta1_backend_get_svcupdate(m1)))
		return NEWERROR(CODE_POLICY_NOT_SATISFIABLE, "Bad NS/Policy pair");
	policy = service_howto_update(pol, ct->baretype);
	replicas = service_howmany_replicas(pol, ct->baretype);
	replicas = (replicas > 0 ? replicas : 1);
	// Patches the constraint on the service type (if not set in the request)
	// by the constraint set in the NS-wide storage policy.
	compound_type_update_arg(ct, pol, FALSE);

	err = __get_container_all_services(sq3, url, ct->type, &used);
	if (NULL != err) {
		g_prefix_error(&err, "Preliminary lookup error : ");
		return err;
	}
	if (used && !*used) {
		g_free(used);
		used = NULL;
	}

	if (used && (mode != M1V2_GETSRV_RENEW)) {
		/* Only keep the services UP, if not forced to renew */
		struct meta1_service_url_s **up = __get_services_up(m1, used);
		if (up && *up) {
			*result = pack_urlv(up);
			meta1_service_url_cleanv(up);
			meta1_service_url_cleanv(used);
			return NULL;
		}
		meta1_service_url_cleanv(up);
	}

	if (used && (mode == M1V2_GETSRV_REUSE || policy == SVCUPD_KEEP)) {
		/* Services used but unavailable, but we are told to reuse */
		*result = pack_urlv(used);
		meta1_service_url_cleanv(used);
		return err;
	}

	/* No service available, poll a new one */
	struct meta1_service_url_s *m1_url = NULL;
	gint seq = urlv_get_max_seq(used);
	seq = (seq<0 ? 1 : seq+1);

	if (NULL != (m1_url = __poll_services(m1, replicas, ct, seq, used, &err))) {
		if (mode != M1V2_GETSRV_DRYRUN) {
			if (NULL == err) {
				if (policy == SVCUPD_REPLACE)
					err = __delete_service(sq3, url, ct->type);
				if (NULL == err)
					err = __save_service(sq3, url, m1_url, TRUE);
			}
		}

		if (!err && result) {
			struct meta1_service_url_s **unpacked = expand_url(m1_url);
			*result = pack_urlv(unpacked);
			meta1_service_url_cleanv(unpacked);
			if (renewed) *renewed = TRUE;
		}
		g_free(m1_url);
	}

	meta1_service_url_cleanv(used);
	return err;
}