예제 #1
0
파일: pk-manifest.c 프로젝트: stieg/perfkit
/**
 * pk_manifest_new_from_data:
 * @data: The manifest data.
 * @length: The length of data.
 *
 * Creates a new instance of #PkManifest from a buffer of data.
 *
 * Returns: the newly created #PkManifest instance.
 *
 * Side effects: None.
 */
PkManifest*
pk_manifest_new_from_data (const guint8 *data,   /* IN */
                           gsize         length) /* IN */
{
	PkManifest *manifest;
	EggBuffer *buffer;

	ENTRY;
	manifest = pk_manifest_new();
	buffer = egg_buffer_new_from_data(data, length);
	if (!decode(manifest, buffer)) {
		GOTO(error);
	}
	egg_buffer_unref(buffer);
	RETURN(manifest);

  error:
	egg_buffer_unref(buffer);
	pk_manifest_unref(manifest);
	RETURN(NULL);
}
예제 #2
0
/**
 * pka_encoder_real_encode_samples:
 * @manifest: A #PkaManifest.
 *
 * Default encoder for samples.
 *
 * Returns: None.
 * Side effects: None.
 */
static gboolean
pka_encoder_real_encode_samples (PkaManifest *manifest,  /* IN */
                                 PkaSample  **samples,   /* IN */
                                 gint         n_samples, /* IN */
                                 guint8     **data,      /* OUT */
                                 gsize       *data_len)  /* OUT */
{
	EggBuffer *buf;
	struct timespec mts;
	struct timespec sts;
	struct timespec rel;
	guint64 rel_composed;
	PkaResolution res;
	const guint8 *tbuf;
	gsize tlen;
	gint i;

	g_return_val_if_fail(data != NULL, FALSE);
	g_return_val_if_fail(data_len != NULL, FALSE);

	ENTRY;
	buf = egg_buffer_new();
	pka_manifest_get_timespec(manifest, &mts);
	res = pka_manifest_get_resolution(manifest);

	for (i = 0; i < n_samples; i++) {
		/*
		 * Add the source identifier.
		 */
		egg_buffer_write_tag(buf, 1, EGG_BUFFER_UINT);
		egg_buffer_write_uint(buf, pka_sample_get_source_id(samples[i]));

		/*
		 * Add the relative time since the manifest; loosing un-needed
		 * precision to aide varint encoding.
		 */
		pka_sample_get_timespec(samples[i], &sts);
		timespec_subtract(&sts, &mts, &rel);
		rel_composed = pka_resolution_apply(res, &rel);
		egg_buffer_write_tag(buf, 2, EGG_BUFFER_UINT64);
		egg_buffer_write_uint64(buf, rel_composed);

		/*
		 * The sample is a protobuf inspired blob but is not protobuf compat.
		 *
		 * This was so that we could save significant message and repeated type
		 * overhead that is not needed for introspection since we have the
		 * manifest to provide us that data.
		 *
		 * Therefore, we simply treat the sample as an opaque buffer for the
		 * other side to unwrap.
		 */
		pka_sample_get_data(samples[i], &tbuf, &tlen);
		egg_buffer_write_tag(buf, 3, EGG_BUFFER_DATA);
		egg_buffer_write_data(buf, tbuf, tlen);
	}

	egg_buffer_get_buffer(buf, &tbuf, &tlen);
	*data = g_malloc(tlen);
	*data_len = tlen;
	memcpy(*data, tbuf, tlen);
	egg_buffer_unref(buf);

	RETURN(TRUE);
}
예제 #3
0
static gboolean
pka_encoder_real_encode_manifest (PkaManifest  *manifest, /* IN */
                                  guint8      **data,     /* IN */
                                  gsize        *data_len) /* IN */
{
	EggBuffer *buf, *mbuf, *ebuf;
	struct timespec ts;
	guint64 t;
	const guint8 *tbuf;
	gsize tlen;
	gint rows;
	gint i;

	g_return_val_if_fail(manifest != NULL, FALSE);
	g_return_val_if_fail(data != NULL, FALSE);
	g_return_val_if_fail(data_len != NULL, FALSE);

	ENTRY;
	buf = egg_buffer_new();

	/*
	 * Field 1: Timestamp.  Currently encoded in microseconds.  We should
	 *   determine what we want to do long-term.
	 */
	pka_manifest_get_timespec(manifest, &ts);
	timespec_to_usec(&ts, &t);
	egg_buffer_write_tag(buf, 1, EGG_BUFFER_UINT64);
	egg_buffer_write_uint64(buf, t);

	/*
	 * Desired sample resolution.  This allows us to save considerable
	 * width in the relative-timestamp per sample.
	 */
	egg_buffer_write_tag(buf, 2, EGG_BUFFER_ENUM);
	egg_buffer_write_uint(buf, pka_manifest_get_resolution(manifest));

	/*
	 * Source index offset within the channel.
	 */
	egg_buffer_write_tag(buf, 3, EGG_BUFFER_UINT);
	egg_buffer_write_uint(buf, pka_manifest_get_source_id(manifest));

	/*
	 * Create a new buffer for the repeated data series.
	 */
	ebuf = egg_buffer_new();

	/*
	 * Write the manifest data description.  This is a set of embedded
	 * messages within the message.
	 */
	rows = pka_manifest_get_n_rows(manifest);
	for (i = 1; i <= rows; i++) {
		mbuf = egg_buffer_new();

		/*
		 * Write the row identifier.
		 */
		egg_buffer_write_tag(mbuf, 1, EGG_BUFFER_UINT);
		egg_buffer_write_uint(mbuf, i);

		/*
		 * Write the row type.
		 */
		egg_buffer_write_tag(mbuf, 2, EGG_BUFFER_ENUM);
		egg_buffer_write_uint(mbuf, pka_manifest_get_row_type(manifest, i));

		/*
		 * Write the row name.
		 */
		egg_buffer_write_tag(mbuf, 3, EGG_BUFFER_STRING);
		egg_buffer_write_string(mbuf, pka_manifest_get_row_name(manifest, i));

		/*
		 * Embed the message as a data blob.
		 */
		egg_buffer_get_buffer(mbuf, &tbuf, &tlen);
		egg_buffer_write_data(ebuf, tbuf, tlen);

		egg_buffer_unref(mbuf);
	}

	/*
	 * Add the repeated message length and data.
	 */
	egg_buffer_get_buffer(ebuf, &tbuf, &tlen);
	egg_buffer_write_tag(buf, 4, EGG_BUFFER_REPEATED);
	egg_buffer_write_data(buf, tbuf, tlen);
	egg_buffer_unref(ebuf);

	/*
	 * Copy the buffer to the destination.
	 */
	egg_buffer_get_buffer(buf, &tbuf, &tlen);
	*data = g_malloc(tlen);
	*data_len = tlen;
	memcpy(*data, tbuf, tlen);

	egg_buffer_unref(buf);
	RETURN(TRUE);
}