Exemple #1
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;
}
Exemple #2
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_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_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;
}
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;
}
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;
}
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_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_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;
}
static GError*
_update_container_quota(struct meta1_backend_s *m1,
		struct container_info_s *cinfo)
{
	GError *e0 = NULL;
	gint rc;
	sqlite3_stmt *stmt = NULL;
	struct sqlx_sqlite3_s *sq3 = NULL;
	struct sqlx_repctx_s *repctx = NULL;

	e0 = meta1_backend_open_base(m1, cinfo->id, M1V2_OPENBASE_MASTERONLY, &sq3);
	if (NULL != e0)
		return e0;

	e0 = sqlx_transaction_begin(sq3, &repctx);
	if (NULL != e0) {
		sqlx_repository_unlock_and_close_noerror(sq3);
		return e0;
	}

	sqlite3_prepare_debug(rc, sq3->db, "UPDATE properties SET"
			" value = ?"
			" WHERE cid = ?"
			" AND name = 'meta2.quota'", -1, &stmt, NULL);
	(void) sqlite3_bind_int64(stmt, 1, cinfo->size);
	(void) sqlite3_bind_blob(stmt, 2, cinfo->id,
			sizeof(container_id_t), NULL);

	for (rc=SQLITE_ROW; rc == SQLITE_ROW ;)
		rc = sqlite3_step(stmt);
	if (rc != SQLITE_OK && rc != SQLITE_DONE)
		e0 = SQLITE_GERROR(sq3->db, rc);
	sqlite3_finalize_debug(rc, stmt);

	if (!e0 && sqlite3_changes(sq3->db) <= 0) {
		sqlite3_prepare_debug(rc, sq3->db,
				"INSERT INTO properties (cid,name,value)"
				" VALUES (?,?,?)", -1, &stmt, NULL);
		(void) sqlite3_bind_blob(stmt, 1, cinfo->id, sizeof(container_id_t), NULL);
		(void) sqlite3_bind_text(stmt, 2, "meta2.quota", sizeof("meta2.quota")-1, NULL);
		(void) sqlite3_bind_int64(stmt, 3, cinfo->size);

		for (rc=SQLITE_ROW; rc == SQLITE_ROW ;)
			rc = sqlite3_step(stmt);
		if (rc != SQLITE_OK && rc != SQLITE_DONE)
			e0 = SQLITE_GERROR(sq3->db, rc);
		sqlite3_finalize_debug(rc, stmt);
	}

	/* Commit then close the container's base */
	e0 = sqlx_transaction_end(repctx, e0);
	sqlx_repository_unlock_and_close_noerror(sq3);
	return e0;
}
Exemple #11
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*
__destroy_container(struct sqlx_sqlite3_s *sq3, struct hc_url_s *url,
                    gboolean force, gboolean *done)
{
    GError *err = NULL;
    gint count_actions = 0;
    struct sqlx_repctx_s *repctx = NULL;

    EXTRA_ASSERT(sq3 != NULL);
    EXTRA_ASSERT(sq3->db != NULL);

    err = sqlx_transaction_begin(sq3, &repctx);
    if (NULL != err)
        return err;

    if (force) {
        __exec_cid (sq3->db, "DELETE FROM services WHERE cid = ?", hc_url_get_id (url));
        count_actions += sqlite3_changes(sq3->db);
        __exec_cid (sq3->db, "DELETE FROM properties WHERE cid = ?", hc_url_get_id (url));
        count_actions += sqlite3_changes(sq3->db);
    } else {
        guint count_services = 0, count_properties = 0;

        /* No forced op, we count the services belonging to the container. */
        err = __count_FK(sq3, url, "services", &count_services);
        if (!err)
            err = __count_FK(sq3, url, "properties", &count_properties);

        /* If any service is found, this is an error. */
        if (!err && count_services > 0)
            err = NEWERROR(CODE_USER_INUSE, "User still linked to services");
        if (!err && count_properties > 0)
            err = NEWERROR(CODE_USER_INUSE, "User still has properties");
    }

    if (!err) {
        __exec_cid(sq3->db, "DELETE FROM users WHERE cid = ?", hc_url_get_id (url));
        count_actions += sqlite3_changes(sq3->db);
    }

    *done = !err && (count_actions > 0);

    if (!err && !*done)
        err = NEWERROR(CODE_USER_NOTFOUND, "User not found");

    return sqlx_transaction_end(repctx, err);
}
Exemple #13
0
static GError*
_transaction_begin(struct sqlx_sqlite3_s *sq3, struct oio_url_s *url,
		struct sqlx_repctx_s **result)
{
	struct sqlx_repctx_s* repctx = NULL;

	EXTRA_ASSERT(result != NULL);
	*result = NULL;

	GError *err = sqlx_transaction_begin(sq3, &repctx);
	if (NULL != err)
		return err;

	m2db_set_container_name(sq3, url);
	*result = repctx;
	return NULL;
}
Exemple #14
0
static GError*
_fill(struct sqlx_sqlite3_s *sq3,guint replicas, gchar **m1urls)
{
	struct sqlx_repctx_s *repctx = NULL;
	GError *err = NULL;
	guint max;

	max = m1urls ? g_strv_length(m1urls) : 0;
	EXTRA_ASSERT(max > 0 && max < 65536);

	err = sqlx_transaction_begin(sq3, &repctx);
	if (NULL != err)
		return err;

	while (replicas--) {
		err = __fill(sq3->db, m1urls, max, replicas);
		if (err)
			 break;
	}
	return sqlx_transaction_end(repctx, 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_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;
}