// TODO: export?
static gpointer
_gen_chunk_info(struct service_info_s *si)
{
	chunk_info_t *ci = g_malloc0(sizeof(chunk_info_t));
	SHA256_randomized_buffer(ci->id.id, sizeof(ci->id.id));
	memcpy(&(ci->id.addr), &(si->addr), sizeof(addr_info_t));
	g_strlcpy(ci->id.vol,
		service_info_get_tag_value(si, NAME_TAGNAME_RAWX_VOL, "/"),
		sizeof(ci->id.vol));
	ci->size = 0;
	ci->position = 0;
	ci->nb = 0;

	return (gpointer)ci;
}
void
service_info_to_lb_item(const struct service_info_s *si,
		struct oio_lb_item_s *item)
{
	g_assert_nonnull(si);
	g_assert_nonnull(item);
	/* Take location from:
	 * - tag.loc as a hexadecimal number or
	 * - tag.log as a hash dot-separated string or
	 * - IP address and port */
	const gchar *loc_str = service_info_get_tag_value(si, "tag.loc", NULL);
	if (!loc_str) {
		item->location = location_from_addr_info(&(si->addr));
	} else if (!g_str_has_prefix(loc_str, "0x") ||
			!(item->location = g_ascii_strtoull(loc_str, NULL, 16))) {
		item->location = location_from_dotted_string(loc_str);
	}
	item->weight = CLAMP(si->score.value, 0, 100);
	gchar *key = service_info_key(si);
	g_strlcpy(item->id, key, LIMIT_LENGTH_SRVID);
	g_free(key);
}
const gchar *
service_info_get_rawx_volume(const struct service_info_s *si, const gchar *d)
{
	return service_info_get_tag_value(si, NAME_TAGNAME_RAWX_VOL, d);
}
const gchar *
service_info_get_rawx_location(const struct service_info_s *si, const gchar *d)
{
	return service_info_get_tag_value(si, NAME_TAGNAME_RAWX_LOC, d);
}