int
meta2_filter_action_create_container(struct gridd_filter_ctx_s *ctx,
		struct gridd_reply_ctx_s *reply)
{
	(void) reply;
	struct m2v2_create_params_s params = {NULL,NULL,NULL,0};
	struct meta2_backend_s *m2b = meta2_filter_ctx_get_backend(ctx);
	struct hc_url_s *url = meta2_filter_ctx_get_url(ctx);
	GError *err = NULL;
	int retry = 2;

	params.storage_policy = meta2_filter_ctx_get_param(ctx, NAME_MSGKEY_STGPOLICY);
	params.version_policy = meta2_filter_ctx_get_param(ctx, NAME_MSGKEY_VERPOLICY);
	params.local = (meta2_filter_ctx_get_param(ctx, NAME_MSGKEY_LOCAL) != NULL);

	gchar **headers = metautils_message_get_field_names (reply->request);
	GPtrArray *tmp = g_ptr_array_new ();
	for (gchar **p=headers; *p ;++p) {
		if (!g_str_has_prefix(*p, NAME_MSGKEY_PREFIX_PROPERTY))
			continue;
		g_ptr_array_add (tmp, g_strdup((*p) + sizeof(NAME_MSGKEY_PREFIX_PROPERTY) - 1));
		g_ptr_array_add (tmp, metautils_message_extract_string_copy (reply->request, *p));
	}
	params.properties = (gchar**) metautils_gpa_to_array (tmp, TRUE);
	g_strfreev (headers);
	headers = NULL;

retry:
	err = meta2_backend_create_container(m2b, url, &params);
	if (err != NULL && err->code == CODE_REDIRECT && retry-- > 0 &&
			!g_strcmp0(err->message, meta2_backend_get_local_addr(m2b))) {
		GRID_WARN("Redirecting on myself!?! Retrying request immediately");
		g_clear_error(&err);
		hc_decache_reference_service(m2b->resolver, url, NAME_SRVTYPE_META2);
		goto retry;
	}

	g_strfreev (params.properties);
	params.properties = NULL;

	if (!err)
		return FILTER_OK;
	meta2_filter_ctx_set_error(ctx, err);
	return FILTER_KO;
}
GError *
gridd_client_exec4 (const gchar *to, gdouble seconds, GByteArray *req,
		GByteArray ***out)
{
	if (!to) {
		g_byte_array_unref (req);
		return NEWERROR(CODE_INTERNAL_ERROR, "No target");
	}

	GPtrArray *tmp = NULL;
	if (out)
		tmp = g_ptr_array_new();

	struct gridd_client_s *client = gridd_client_create(to, req,
			(out ? tmp : NULL), out ? (client_on_reply)_cb_exec4 : NULL);
	g_byte_array_unref (req);
	if (!client) {
		if (tmp) g_ptr_array_free (tmp, TRUE);
		return NEWERROR(CODE_INTERNAL_ERROR, "client creation");
	}
	if (seconds > 0.0)
		gridd_client_set_timeout (client, seconds);
	GError *err = gridd_client_run (client);
	gridd_client_free (client);

	if (!err && out) {
		*out = (GByteArray**) metautils_gpa_to_array (tmp, TRUE);
		tmp = NULL;
	}
	if (tmp) {
		g_ptr_array_set_free_func (tmp, (GDestroyNotify)g_byte_array_unref);
		g_ptr_array_free (tmp, TRUE);
		tmp = NULL;
	}
	return err;
}
GError*
_open_and_lock(struct meta1_backend_s *m1, struct oio_url_s *url,
		enum m1v2_open_type_e how, struct sqlx_sqlite3_s **handle)
{
	EXTRA_ASSERT(m1 != NULL);
	EXTRA_ASSERT(url != NULL);
	EXTRA_ASSERT(handle != NULL);

	GRID_TRACE2("%s(%p,%p,%d,%p)", __FUNCTION__, (void*)m1,
			oio_url_get (url, OIOURL_HEXID), how, (void*)handle);

	if (!oio_url_has (url, OIOURL_HEXID))
		return NEWERROR (CODE_BAD_REQUEST, "Partial URL (missing HEXID)");
	if (!m1b_check_ns_url (m1, url))
		return NEWERROR(CODE_NAMESPACE_NOTMANAGED, "Invalid NS");

	gchar base[5];
	const guint8 *cid = oio_url_get_id(url);
	g_snprintf(base, sizeof(base), "%02X%02X", cid[0], cid[1]);

	if (!meta1_prefixes_is_managed(m1->prefixes, cid))
		return NEWERROR(CODE_RANGE_NOTFOUND, "prefix [%s] not managed", base);

	/* Now open/lock the base in a way suitable for our op */
	struct sqlx_name_s n = {.base=base, .type=NAME_SRVTYPE_META1, .ns=m1->ns_name};
	GError *err = sqlx_repository_open_and_lock(m1->repo, &n, m1_to_sqlx(how), handle, NULL);

	if (err != NULL) {
		if (!CODE_IS_REDIRECT(err->code))
			g_prefix_error(&err, "Open/Lock error: ");  
		return err;
	}

	EXTRA_ASSERT(*handle != NULL);
	GRID_TRACE("Opened and locked [%s][%s] -> [%s][%s]",
			base, NAME_SRVTYPE_META1,
			(*handle)->name.base, (*handle)->name.type);
	return NULL;
}

GError*
__create_user(struct sqlx_sqlite3_s *sq3, struct oio_url_s *url)
{
	if (!oio_url_has_fq_container (url))
		return NEWERROR(CODE_BAD_REQUEST, "Partial URL");

	static const gchar *sql = "INSERT INTO users ('cid','account','user') VALUES (?,?,?)";

	GError *err = NULL;
	sqlite3_stmt *stmt = NULL;
	int rc;

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

	/* Prepare the statement */
	sqlite3_prepare_debug(rc, sq3->db, sql, -1, &stmt, NULL);
	if (rc != SQLITE_OK)
		err = M1_SQLITE_GERROR(sq3->db, rc);
	else {
		sqlite3_bind_blob(stmt, 1, oio_url_get_id(url), oio_url_get_id_size(url), NULL);
		sqlite3_bind_text(stmt, 2, oio_url_get(url, OIOURL_ACCOUNT), -1, NULL);
		sqlite3_bind_text(stmt, 3, oio_url_get(url, OIOURL_USER), -1, NULL);

		/* Run the results */
		do { rc = sqlite3_step(stmt); } while (rc == SQLITE_ROW);

		if (rc != SQLITE_OK && rc != SQLITE_DONE) {
			err = M1_SQLITE_GERROR(sq3->db, rc);
			if (rc == SQLITE_CONSTRAINT) {
				g_prefix_error(&err, "Already created? ");
				err->code = CODE_CONTAINER_EXISTS;
			}
		}

		sqlite3_finalize_debug(rc, stmt);
	}

	if (err)
		GRID_DEBUG("User creation failed : (%d) %s", err->code, err->message);

	return err;
}

GError*
__info_user(struct sqlx_sqlite3_s *sq3, struct oio_url_s *url, gboolean ac,
		struct oio_url_s ***result)
{
	GError *err = NULL;
	sqlite3_stmt *stmt = NULL;
	GPtrArray *gpa;
	int rc;
	gboolean found;

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

retry:
	/* Prepare the statement */
	sqlite3_prepare_debug(rc, sq3->db, "SELECT account,user FROM users WHERE cid = ?", -1, &stmt, NULL);
	if (rc != SQLITE_OK)
		return M1_SQLITE_GERROR(sq3->db, rc);
	(void) sqlite3_bind_blob(stmt, 1, oio_url_get_id (url), oio_url_get_id_size (url), NULL);

	/* Run the results */
	found = FALSE;
 	gpa = result ? g_ptr_array_new() : NULL;
	do { if (SQLITE_ROW == (rc = sqlite3_step(stmt))) {
		found = TRUE;
		if (!gpa) continue;
		struct oio_url_s *u = oio_url_empty ();
		oio_url_set (u, OIOURL_NS, oio_url_get (url, OIOURL_NS));
		oio_url_set (u, OIOURL_ACCOUNT, (char*)sqlite3_column_text(stmt, 0));
		oio_url_set (u, OIOURL_USER, (char*)sqlite3_column_text(stmt, 1));
		oio_url_set (u, OIOURL_HEXID, oio_url_get (url, OIOURL_HEXID));
		g_ptr_array_add(gpa, u);
	} } while (rc == SQLITE_ROW);

	if (rc != SQLITE_DONE && rc != SQLITE_OK) {
		err = M1_SQLITE_GERROR(sq3->db, rc);
		g_prefix_error(&err, "DB error: ");
	}

	sqlite3_finalize_debug(rc,stmt);
	stmt = NULL;

	if (err) {
		if (gpa) {
			g_ptr_array_set_free_func (gpa, (GDestroyNotify)oio_url_clean);
			g_ptr_array_free (gpa, TRUE);
		}
		return err;
	}

	if (!found) {
		if (gpa) g_ptr_array_free (gpa, TRUE);
		if (ac) {
			ac = FALSE; /* do not retry */
			err = __create_user (sq3, url);
			if (!err) goto retry;
		}
		return NEWERROR(CODE_USER_NOTFOUND, "no such container");
	}
	if (gpa)
		*result = (struct oio_url_s**) metautils_gpa_to_array(gpa, TRUE);
	return NULL;
}