Esempio n. 1
0
static void
_test_field (const char *v, struct oio_url_s *u, enum oio_url_field_e f)
{
	const char *found = oio_url_get (u, f);
	if (v) {
		g_assert (oio_url_has (u, f));
		g_assert (!strcmp (v, found));
	} else {
		g_assert (!oio_url_has (u, f));
		g_assert (NULL == found);
	}
}
Esempio n. 2
0
static void
_test_url (guint idx, struct oio_url_s *u, struct test_data_s *td)
{
	(void) idx;
	_test_field (td->whole, u, OIOURL_WHOLE);
	_test_field (td->ns, u, OIOURL_NS);
	_test_field (td->account, u, OIOURL_ACCOUNT);
	_test_field (td->ref, u, OIOURL_USER);
	_test_field (td->type, u, OIOURL_TYPE);
	_test_field (td->path, u, OIOURL_PATH);
	if (td->hexa) {
		g_assert (oio_url_has (u, OIOURL_HEXID));
		g_assert (NULL != oio_url_get_id (u));
		g_assert (!g_ascii_strcasecmp (oio_url_get (u, OIOURL_HEXID), td->hexa));
	} else {
		g_assert (!oio_url_has (u, OIOURL_HEXID));
		g_assert (NULL == oio_url_get_id (u));
		g_assert (NULL == oio_url_get (u, OIOURL_HEXID));
	}
}
Esempio n. 3
0
int
meta2_filter_check_url_cid (struct gridd_filter_ctx_s *ctx,
		struct gridd_reply_ctx_s *reply)
{
	(void) reply;
	struct oio_url_s *url = meta2_filter_ctx_get_url(ctx);
	TRACE_FILTER();
	if (url && oio_url_has(url, OIOURL_HEXID))
		return FILTER_OK;
	meta2_filter_ctx_set_error (ctx, BADREQ("Invalid URL"));
	return FILTER_KO;
}
int
meta2_filter_check_url_cid (struct gridd_filter_ctx_s *ctx,
		struct gridd_reply_ctx_s *reply)
{
	(void) reply;
	struct oio_url_s *url = meta2_filter_ctx_get_url(ctx);
	TRACE_FILTER();
	if (url && oio_url_has(url, OIOURL_HEXID))
		return FILTER_OK;
	meta2_filter_ctx_set_error (ctx, NEWERROR(CODE_BAD_REQUEST, "No/partial URL"));
	return FILTER_KO;
}
Esempio n. 5
0
void
metautils_message_add_url_no_type (MESSAGE m, struct oio_url_s *url)
{
	if (!m)
		return;
	for (struct map_s *p = url2msg_map; p->f ;++p) {
		if (p->u != OIOURL_TYPE && oio_url_has (url, p->u)) {
			const char *s = oio_url_get (url, p->u);
			if (!p->avoid || strcmp(p->avoid, s))
				metautils_message_add_field_str(m, p->f, s);
		}
	}

	const guint8 *id = oio_url_get_id (url);
	if (id)
		metautils_message_add_field (m, NAME_MSGKEY_CONTAINERID, id, oio_url_get_id_size (url));
}
Esempio n. 6
0
static struct oio_error_s *
_roundtrip_common (struct oio_sds_s *client, struct oio_url_s *url,
		const char *path)
{
	struct file_info_s fi, fi0;
	struct oio_error_s *err = NULL;
	int has = 0;

	err = (struct oio_error_s*) _checksum_file (path, &fi0);
	MAYBERETURN(err, "Checksum error (original): ");

	gchar tmppath[256] = "";
	g_snprintf (tmppath, sizeof(tmppath), "/tmp/test-roundtrip-%d-%lu-", getpid(), time(0));
	_append_random_chars (tmppath, random_chars, 16);
	gchar content_id[65] = "";
	_append_random_chars (content_id, hex_chars, 64);

	GRID_INFO ("Roundtrip on local(%s) distant(%s) content_id(%s)", tmppath,
			oio_url_get (url, OIOURL_WHOLE), content_id);

	/* Check the content is not preset yet */
	err = oio_sds_has (client, url, &has);
	if (!err && has) err = (struct oio_error_s*) NEWERROR(0,"content already present");
	MAYBERETURN(err, "Check error");
	GRID_INFO("Content absent as expected");

	/* Then upload it */
	struct oio_sds_ul_src_s ul_src = {
		.type = OIO_UL_SRC_FILE,
		.data = { .file = { .path = path, .offset = 0, .size = 0, }, },
	};
	struct oio_sds_ul_dst_s ul_dst = {
		.url = url, .autocreate = 1, .out_size = 0, .content_id = content_id,
	};
	err = oio_sds_upload (client, &ul_src, &ul_dst);
	MAYBERETURN(err, "Upload error");
	GRID_INFO("Content uploaded");

	/* Check it is now present */
	has = 0;
	err = oio_sds_has (client, url, &has);
	if (!err && !has) err = (struct oio_error_s*) NEWERROR(0, "content not found");
	MAYBERETURN(err, "Check error");
	GRID_INFO("Content present as expected");

	/* Get it to validate the content is accessible */
	err = oio_sds_download_to_file (client, url, tmppath);
	MAYBERETURN(err, "Download error");
	GRID_INFO("Content downloaded to a file");

	/* Validate the original and the copy match */
	err = (struct oio_error_s*) _checksum_file (tmppath, &fi);
	MAYBERETURN(err, "Checksum error (copy): ");
	if (fi.fs != fi0.fs)
		MAYBERETURN(NEWERROR(0, "Copy sizes mismatch"), "Validation error");
	if (0 != memcmp(fi.h, fi0.h, fi.hs))
		MAYBERETURN(NEWERROR(0, "Copy hash mismatch"), "Validation error");
	GRID_INFO("The original file and its copy match");

	/* Get it an other way in a buffer. */
	guint8 buf[1024];
	struct oio_sds_dl_dst_s dl_dst = {
		.type = OIO_DL_DST_BUFFER,
		.data = {.buffer = {.ptr = buf, .length=1024}}
	};
	struct oio_sds_dl_src_s dl_src = {
		.url = url,
		.ranges = NULL,
	};
	err = oio_sds_download (client, &dl_src, &dl_dst);
	MAYBERETURN(err, "Download error");
	GRID_INFO("Content downloaded to a buffer");

	/* link the container */
	struct oio_url_s *url1 = oio_url_dup (url);
	oio_url_set (url1, OIOURL_PATH, tmppath);
	err = oio_sds_link (client, url1, content_id);
	oio_url_pclean (&url1);
	MAYBERETURN(err, "Link error: ");

	/* List the container, the content must appear */
	struct oio_sds_list_param_s list_in = {
		.url = url,
		.prefix = NULL, .marker = NULL, .end = NULL, .delimiter = 0,
		.flag_allversions = 0, .flag_nodeleted = 0,
	};
	struct oio_sds_list_listener_s list_out = {
		.ctx = NULL,
		.on_item = _on_item, .on_prefix = NULL, .on_bound = NULL,
	};
	err = oio_sds_list (client, &list_in, &list_out);
	MAYBERETURN(err, "List error");

	/* Remove the content from the content */
	err = oio_sds_delete (client, url);
	MAYBERETURN(err, "Delete error");
	GRID_INFO("Content removed");

	/* Check the content is not preset anymore */
	has = 0;
	err = oio_sds_has (client, url, &has);
	if (!err && has) err = (struct oio_error_s*) NEWERROR(0, "content still present");
	MAYBERETURN(err, "Check error");
	GRID_INFO("Content absent as expected");

	g_remove (tmppath);
	oio_error_pfree (&err);
	return NULL;
}

static struct oio_error_s *
_roundtrip_autocontainer (struct oio_sds_s *client, struct oio_url_s *url,
		const char *path)
{
	struct file_info_s fi;
	GError *err = _checksum_file (path, &fi);

	/* compute the autocontainer with the SHA1, consider only the first 17 bits */
	struct oio_str_autocontainer_config_s cfg = {
		.src_offset = 0, .src_size = 0,
		.dst_bits = 17,
	};
	char tmp[65];
	const char *auto_container = oio_str_autocontainer_hash (fi.h, fi.hs, tmp, &cfg);

	/* build a new URL with the computed container name */
	struct oio_url_s *url_auto = oio_url_dup (url);
	oio_url_set (url_auto, OIOURL_USER, auto_container);
	err = (GError*) _roundtrip_common (client, url_auto, path);
	oio_url_pclean (&url_auto);

	return (struct oio_error_s*) err;
}

int
main(int argc, char **argv)
{
	oio_log_to_stderr();
	oio_sds_default_autocreate = 1;
	for (int i=0; i<4 ;i++)
		oio_log_more ();

	prng = g_rand_new ();

	if (argc != 2) {
		g_printerr ("Usage: %s PATH\n", argv[0]);
		return 1;
	}

	const char *path = argv[1];

	struct oio_url_s *url = oio_url_empty ();
	oio_url_set (url, OIOURL_NS, g_getenv("OIO_NS"));
	oio_url_set (url, OIOURL_ACCOUNT, g_getenv("OIO_ACCOUNT"));
	oio_url_set (url, OIOURL_USER, g_getenv("OIO_USER"));
	oio_url_set (url, OIOURL_PATH, g_getenv("OIO_PATH"));

	if (!oio_url_has_fq_path(url)) {
		g_printerr ("Partial URL [%s]: requires a NS (%s), an ACCOUNT (%s),"
				" an USER (%s) and a PATH (%s)\n",
				oio_url_get (url, OIOURL_WHOLE),
				oio_url_has (url, OIOURL_NS)?"ok":"missing",
				oio_url_has (url, OIOURL_ACCOUNT)?"ok":"missing",
				oio_url_has (url, OIOURL_USER)?"ok":"missing",
				oio_url_has (url, OIOURL_PATH)?"ok":"missing");
		return 3;
	}
	GRID_INFO("URL valid [%s]", oio_url_get (url, OIOURL_WHOLE));

	struct oio_sds_s *client = NULL;
	struct oio_error_s *err = NULL;

	/* Initiate a client */
	err = oio_sds_init (&client, oio_url_get(url, OIOURL_NS));
	if (err) {
		g_printerr ("Client init error: (%d) %s\n", oio_error_code(err),
				oio_error_message(err));
		return 4;
	}
	GRID_INFO("Client ready to [%s]", oio_url_get (url, OIOURL_NS));

	err = _roundtrip_common (client, url, path);
	if (!err)
		err = _roundtrip_autocontainer (client, url, path);

	int rc = err != NULL;
	oio_error_pfree (&err);
	oio_sds_pfree (&client);
	oio_url_pclean (&url);
	return rc;
}
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;
}
Esempio n. 8
0
static GError *
m2b_open(struct meta2_backend_s *m2, struct oio_url_s *url,
		enum m2v2_open_type_e how, struct sqlx_sqlite3_s **result)
{
	GError *err = NULL;
	struct sqlx_sqlite3_s *sq3 = NULL;

	EXTRA_ASSERT(url != NULL);
	EXTRA_ASSERT(result != NULL);
	EXTRA_ASSERT(m2 != NULL);
	EXTRA_ASSERT(m2->backend.repo != NULL);

	/* TODO */
	gboolean no_peers = FALSE;
	if (no_peers) {
		how &= ~M2V2_OPEN_REPLIMODE;
		how |= M2V2_OPEN_LOCAL|M2V2_OPEN_NOREFCHECK;
	}

	struct sqlx_name_mutable_s n;
	sqlx_name_fill (&n, url, NAME_SRVTYPE_META2, 1);
	err = sqlx_repository_open_and_lock(m2->backend.repo,
			sqlx_name_mutable_to_const(&n), m2_to_sqlx(how), &sq3, NULL);
	sqlx_name_clean (&n);

	if (NULL != err) {
		if (err->code == CODE_CONTAINER_NOTFOUND)
			err->domain = GQ();
		return err;
	}

	sq3->no_peers = how & (M2V2_OPEN_LOCAL|M2V2_OPEN_NOREFCHECK);

	// XXX If the container is being deleted, this is sad ...
	// This MIGHT happen if a cache is present (and this is the
	// common case for m2v2), because the deletion will happen
	// when the base exit the cache.
	// In facts this SHOULD NOT happend because a base being deleted
	// is closed with an instruction to exit the cache immediately.
	// TODO FIXME this is maybe a good place for an assert().
	if (sq3->deleted) {
		err = NEWERROR(CODE_CONTAINER_FROZEN, "destruction pending");
		m2b_close(sq3);
		return err;
	}

	// Complete URL with full VNS and container name
	void set(gchar *k, int f) {
		if (oio_url_has(url, f))
			return;
		gchar *s = sqlx_admin_get_str (sq3, k);
		if (s) {
			oio_url_set (url, f, s);
			g_free (s);
		}
	}
	set (SQLX_ADMIN_NAMESPACE, OIOURL_NS);
	set (SQLX_ADMIN_ACCOUNT, OIOURL_ACCOUNT);
	set (SQLX_ADMIN_USERNAME, OIOURL_USER);
	set (SQLX_ADMIN_USERTYPE, OIOURL_TYPE);

	*result = sq3;
	return NULL;
}