GError*
meta1_backend_services_unlink(struct meta1_backend_s *m1,
		struct oio_url_s *url, const char *srvtype, gchar **urlv)
{
	GError *err = __check_backend_events (m1);
	if (err) return err;

	EXTRA_ASSERT(srvtype != NULL);
	struct sqlx_sqlite3_s *sq3 = NULL;
	err = _open_and_lock(m1, url, M1V2_OPENBASE_MASTERONLY, &sq3);
	if (err) return err;

	struct sqlx_repctx_s *repctx = NULL;
	if (!(err = sqlx_transaction_begin(sq3, &repctx))) {
		if (!(err = __info_user(sq3, url, FALSE, NULL))) {
			err = __del_container_services(sq3, url, srvtype, urlv);
			if (NULL != err)
				g_prefix_error(&err, "Query error: ");
		}
		if (!(err = sqlx_transaction_end(repctx, err)))
			__notify_services_by_cid(m1, sq3, url);
	}

	sqlx_repository_unlock_and_close_noerror(sq3);
	return err;
}
GError *
meta1_backend_services_link (struct meta1_backend_s *m1,
                             struct oio_url_s *url, const char *srvtype,
                             gboolean dryrun, gboolean autocreate,
                             gchar ***result)
{
    struct sqlx_sqlite3_s *sq3 = NULL;
    GError *err = _open_and_lock(m1, url, M1V2_OPENBASE_MASTERONLY, &sq3);
    if (err) return err;

    struct sqlx_repctx_s *repctx = NULL;
    if (!(err = sqlx_transaction_begin(sq3, &repctx))) {
        gboolean renewed = FALSE;
        if (!(err = __info_user(sq3, url, autocreate, NULL))) {
            enum m1v2_getsrv_e mode = dryrun ? M1V2_GETSRV_DRYRUN : M1V2_GETSRV_REUSE;
            err = __get_container_service(sq3, url, srvtype, m1, mode, result, &renewed);
            if (NULL != err)
                g_prefix_error(&err, "Query error: ");
        }
        if (!(err = sqlx_transaction_end(repctx, err))) {
            if (renewed)
                __notify_services_by_cid(m1, sq3, url);
        }
    }

    sqlx_repository_unlock_and_close_noerror(sq3);
    return err;
}
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;
}
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;
}
Example #5
0
GError *
meta0_backend_reset(struct meta0_backend_s *m0, gboolean flag_local)
{
	EXTRA_ASSERT(m0 != NULL);

	GError *err = NULL;
	struct sqlx_sqlite3_s *sq3 = NULL;
	struct sqlx_repctx_s *repctx = NULL;

	err = _open_and_lock(m0, flag_local ? M0V2_OPENBASE_LOCAL : M0V2_OPENBASE_MASTERONLY, &sq3);
	if (err) return err;

	if (!(err = sqlx_transaction_begin (sq3, &repctx))) {
		gint rc;
		sqlite3_stmt *stmt = NULL;
		sqlite3_prepare_debug (rc, sq3->db, "DELETE FROM meta1", -1, &stmt, NULL);
		if (rc != SQLITE_OK && rc != SQLITE_DONE)
			err = SQLITE_GERROR(sq3->db, rc);
		else {
			sqlite3_step_debug_until_end (rc, stmt);
			if (rc != SQLITE_OK && rc != SQLITE_DONE)
				err = SQLITE_GERROR(sq3->db, rc);
			else
				sqlx_transaction_notify_huge_changes (repctx);
			sqlite3_finalize_debug (rc, stmt);
		}
		err = sqlx_transaction_end (repctx, err);
	}

	_unlock_and_close (sq3);
	return NULL;
}
GError *
meta1_backend_services_list(struct meta1_backend_s *m1,
                            struct oio_url_s *url, const char *srvtype, gchar ***result)
{
    struct sqlx_sqlite3_s *sq3 = NULL;
    GError *err = _open_and_lock(m1, url, M1V2_OPENBASE_MASTERSLAVE, &sq3);
    if (err) return err;

    struct sqlx_repctx_s *repctx = NULL;
    if (!(err = sqlx_transaction_begin(sq3, &repctx))) {
        if (!(err = __info_user(sq3, url, FALSE, NULL))) {
            struct meta1_service_url_s **uv = NULL;
            err = __get_container_all_services(sq3, url, srvtype, &uv);
            if (NULL != err)
                g_prefix_error(&err, "Query error: ");
            else {
                struct meta1_service_url_s **expanded;
                expanded = expand_urlv(uv);
                *result = pack_urlv(expanded);
                meta1_service_url_cleanv(expanded);
                meta1_service_url_cleanv(uv);
            }
        }
        err = sqlx_transaction_end(repctx, err);
    }

    sqlx_repository_unlock_and_close_noerror(sq3);
    return err;
}
Example #7
0
GError*
meta0_backend_assign(struct meta0_backend_s *m0,
		const GPtrArray *new_assign_prefixes,
		const GPtrArray *new_assign_meta1ref, const gboolean init)
{
	GError *err;
	struct sqlx_sqlite3_s *sq3 = NULL;
	struct sqlx_repctx_s *repctx = NULL;

	EXTRA_ASSERT(m0 != NULL);
	EXTRA_ASSERT(new_assign_prefixes != NULL);
	EXTRA_ASSERT(new_assign_meta1ref != NULL);

	err = _open_and_lock(m0, M0V2_OPENBASE_MASTERONLY, &sq3);
	if (NULL != err)
		return err;

	err = sqlx_transaction_begin(sq3, &repctx);
	if (NULL == err) {
		err = _assign_prefixes(sq3->db, new_assign_prefixes,init);
		if (!err)
			err = _record_meta1ref(sq3->db, new_assign_meta1ref);
		err = sqlx_transaction_end(repctx, err);
	}
	_unlock_and_close(sq3);
	return err;
}
GError *
meta1_backend_set_container_properties(struct meta1_backend_s *m1,
		struct oio_url_s *url, gchar **props, gboolean flush)
{
	EXTRA_ASSERT(props != NULL);

	GError *err;
	if (NULL != (err = __check_property_format(props))) {
		g_prefix_error(&err, "Malformed properties: ");
		return err;
	}

	struct sqlx_sqlite3_s *sq3 = NULL;
	err = _open_and_lock(m1, url, M1V2_OPENBASE_MASTERONLY, &sq3);
	if (err) return err;

	struct sqlx_repctx_s *repctx = NULL;
	if (!(err = sqlx_transaction_begin(sq3, &repctx))) {
		if (!(err = __info_user(sq3, url, FALSE, NULL))) {
			if (flush) {
				err = __del_container_properties(sq3, url, NULL);
				if (err) g_prefix_error(&err, "Flush error: ");
			}
			if (!err) {
				err = __set_container_properties(sq3, url, props);
				if (err) g_prefix_error(&err, "Set error: ");
			}
		}
		err = sqlx_transaction_end(repctx, err);
	}

	sqlx_repository_unlock_and_close_noerror(sq3);
	return err;
}
GError *
meta1_backend_user_info(struct meta1_backend_s *m1,
                        struct hc_url_s *url, gchar ***result)
{
    struct sqlx_sqlite3_s *sq3 = NULL;
    GError *err = _open_and_lock(m1, url, SQLX_OPEN_MASTERSLAVE, &sq3);
    if (!err) {
        struct hc_url_s **urls = NULL;
        if (!(err = __info_user(sq3, url, FALSE, &urls))) {
            if (result) {
                if (!urls)
                    *result = g_malloc0(sizeof(struct hc_url_s*));
                else {
                    *result = g_malloc0(sizeof(gchar*) * (1+g_strv_length((gchar**)urls)));
                    for (int i=0; urls[i] ; ++i)
                        (*result)[i] = g_strdup(hc_url_get(urls[i], HCURL_WHOLE));
                }
            }
        }
        hc_url_cleanv (urls);
        sqlx_repository_unlock_and_close_noerror(sq3);
    }

    return err;
}
Example #10
0
GError *
meta1_backend_services_all(struct meta1_backend_s *m1,
                           struct oio_url_s *url, gchar ***result)
{
    struct sqlx_sqlite3_s *sq3 = NULL;
    GError *err = _open_and_lock(m1, url, M1V2_OPENBASE_MASTERSLAVE, &sq3);
    if (err) return err;

    struct sqlx_repctx_s *repctx = NULL;
    if (!(err = sqlx_transaction_begin(sq3, &repctx))) {
        struct meta1_service_url_s **used = NULL;
        if (NULL != (err = __get_all_services(sq3, &used)))
            g_prefix_error(&err, "Query error: ");
        else {
            struct meta1_service_url_s **expanded = expand_urlv(used);
            *result = pack_urlv(expanded);
            meta1_service_url_cleanv(expanded);
            meta1_service_url_cleanv(used);
        }
        err = sqlx_transaction_end(repctx, err);
    }

    sqlx_repository_unlock_and_close_noerror(sq3);
    return err;
}
Example #11
0
GError *
meta1_backend_notify_services(struct meta1_backend_s *m1, struct oio_url_s *url)
{
    struct sqlx_sqlite3_s *sq3 = NULL;
    GError *err = _open_and_lock(m1, url, M1V2_OPENBASE_MASTERSLAVE, &sq3);
    if (!err) {
        __notify_services_by_cid(m1, sq3, url);
        sqlx_repository_unlock_and_close_noerror(sq3);
    }
    return err;
}
Example #12
0
GError*
meta0_backend_destroy_meta1_ref(struct meta0_backend_s *m0, gchar *meta1)
{
	GError *err = NULL;
	struct sqlx_sqlite3_s *sq3 = NULL;
	struct sqlx_repctx_s *repctx = NULL;
	GPtrArray *result;
	gchar *v, *addr, *ref, *nb;
	guint i, max, cmpaddr, cmpstate;

	EXTRA_ASSERT(m0 != NULL);
	EXTRA_ASSERT(meta1 != NULL);

	/* check if meta1 is disable */
	if (NULL != (err = _reload(m0, TRUE))) {
		g_prefix_error(&err, "Reload error: ");
		return err;
	}

	g_rw_lock_reader_lock(&(m0->rwlock));
	EXTRA_ASSERT(m0->array_meta1_ref != NULL);
	result = meta0_utils_array_meta1ref_dup(m0->array_meta1_ref);
	g_rw_lock_reader_unlock(&(m0->rwlock));

	for (i=0,max=result->len; i<max ;i++) {
		if (!(v = result->pdata[i]))
			continue;
		meta0_utils_unpack_meta1ref(v,&addr,&ref,&nb);
		cmpaddr = g_ascii_strcasecmp(addr,meta1);
		cmpstate = g_ascii_strcasecmp(ref,"0");
		g_free(addr);
		g_free(ref);
		g_free(nb);
		if ( cmpaddr == 0) {
			if (cmpstate != 0)
				return NEWERROR(EINVAL, "meta1 always available to prefix allocation");
			err = _open_and_lock(m0, M0V2_OPENBASE_MASTERONLY, &sq3);
			if (NULL != err)
				return err;

			err = sqlx_transaction_begin(sq3, &repctx);
			if (NULL == err) {
				err = _delete_meta1_ref(sq3->db, meta1);
				err = sqlx_transaction_end(repctx, err);
			}
			_unlock_and_close(sq3);
			return err;
		}
	}
	return NEWERROR(EINVAL, "UNKNOWN meta1");
}
GError *
meta1_backend_user_destroy(struct meta1_backend_s *m1,
                           struct hc_url_s *url, gboolean force)
{
    struct sqlx_sqlite3_s *sq3 = NULL;
    GError *err = _open_and_lock(m1, url, SQLX_OPEN_MASTERONLY, &sq3);
    if (!err) {
        gboolean done = FALSE;
        if (!(err = __info_user(sq3, url, FALSE, NULL)))
            err = __destroy_container(sq3, url, force, &done);
        if (NULL != err)
            g_prefix_error(&err, "Query error: ");
        sqlx_repository_unlock_and_close_noerror(sq3);
    }

    return err;
}
Example #14
0
GError*
meta0_backend_fill(struct meta0_backend_s *m0, guint replicas, gchar **m1urls)
{
	struct sqlx_sqlite3_s *sq3 = NULL;
	GError *err;
	gchar **u = NULL;

	EXTRA_ASSERT(m0 != NULL);
	EXTRA_ASSERT(replicas < 65535);
	EXTRA_ASSERT(m1urls != 0);

	u = g_strdupv(m1urls);
	err = _open_and_lock(m0, M0V2_OPENBASE_MASTERONLY, &sq3);
	if (!err) {
		err = _fill(sq3,replicas,u);
		_unlock_and_close(sq3);
	}

	g_strfreev(u);
	return err;
}
GError *
meta1_backend_get_container_properties(struct meta1_backend_s *m1,
		struct oio_url_s *url, gchar **names, gchar ***result)
{
	EXTRA_ASSERT(result != NULL);

	struct sqlx_sqlite3_s *sq3 = NULL;
	GError *err = _open_and_lock(m1, url, M1V2_OPENBASE_MASTERSLAVE, &sq3);
	if (err) return err;

	struct sqlx_repctx_s *repctx = NULL;
	if (!(err = sqlx_transaction_begin(sq3, &repctx))) {
		if (!(err = __info_user(sq3, url, FALSE, NULL))) {
			err = __get_container_properties(sq3, url, names, result);
			if (err) g_prefix_error(&err, "Lookup error: ");
		}
		err = sqlx_transaction_end(repctx, err);
	}

	sqlx_repository_unlock_and_close_noerror(sq3);
	return err;
}
GError *
meta1_backend_user_create(struct meta1_backend_s *m1,
                          struct hc_url_s *url)
{
    EXTRA_ASSERT(url != NULL);
    if (!hc_url_has_fq_container (url))
        return NEWERROR(CODE_BAD_REQUEST, "Partial URL");

    struct sqlx_sqlite3_s *sq3 = NULL;
    GError *err = _open_and_lock(m1, url, SQLX_OPEN_MASTERONLY, &sq3);
    if (!err) {
        if (!(err = __info_user(sq3, url, FALSE, NULL)))
            err = NEWERROR(CODE_CONTAINER_EXISTS, "User already created");
        else {
            g_clear_error(&err);
            if (NULL != (err = __create_user(sq3, url)))
                g_prefix_error(&err, "Query error: ");
        }
        sqlx_repository_unlock_and_close_noerror(sq3);
    }

    return err;
}
Example #17
0
static GError*
_load(struct meta0_backend_s *m0)
{
	GError *err = NULL;
	struct sqlx_sqlite3_s *sq3 = NULL;

	GRID_TRACE2("%s(%p)", __FUNCTION__, m0);

	err = _open_and_lock(m0,M0V2_OPENBASE_MASTERSLAVE, &sq3);
	if (err != NULL) {
		return err;
	}

	err = _load_from_base(sq3, &(m0->array_by_prefix));
	if (err != NULL)
		g_prefix_error(&err, "Query error: ");

	err = _load_meta1ref_from_base(sq3, &(m0->array_meta1_ref));
	if (err != NULL)
                g_prefix_error(&err, "Query error: ");

	_unlock_and_close(sq3);
	return err;
}
Example #18
0
GError*
meta1_backend_open_base(struct meta1_backend_s *m1, struct hc_url_s *url,
		enum m1v2_open_type_e how, struct sqlx_sqlite3_s **sq3)
{
	return _open_and_lock(m1, url, how, sq3);
}
Example #19
0
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;
}