[sysprof] libsysprof-capture: add cat helper
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [sysprof] libsysprof-capture: add cat helper
- Date: Wed, 29 May 2019 22:41:22 +0000 (UTC)
commit 97bae7d9e3a412a73665cb3a1b62e19f0baf8b1e
Author: Christian Hergert <chergert redhat com>
Date: Tue May 21 09:53:34 2019 -0700
libsysprof-capture: add cat helper
src/libsysprof-capture/meson.build | 1 +
.../sysprof-capture-writer-cat.c | 412 +++++++++++++++++++++
src/libsysprof-capture/sysprof-capture-writer.h | 4 +
3 files changed, 417 insertions(+)
---
diff --git a/src/libsysprof-capture/meson.build b/src/libsysprof-capture/meson.build
index 70bbcc7..c17c688 100644
--- a/src/libsysprof-capture/meson.build
+++ b/src/libsysprof-capture/meson.build
@@ -18,6 +18,7 @@ libsysprof_capture_sources = files([
'sysprof-capture-reader.c',
'sysprof-capture-util.c',
'sysprof-capture-writer.c',
+ 'sysprof-capture-writer-cat.c',
'sysprof-clock.c',
'sysprof-platform.c',
])
diff --git a/src/libsysprof-capture/sysprof-capture-writer-cat.c
b/src/libsysprof-capture/sysprof-capture-writer-cat.c
new file mode 100644
index 0000000..9743740
--- /dev/null
+++ b/src/libsysprof-capture/sysprof-capture-writer-cat.c
@@ -0,0 +1,412 @@
+/* sysprof-cat.c
+ *
+ * Copyright 2018-2019 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "sysprof-cat"
+
+#include "config.h"
+
+#include <glib/gstdio.h>
+#include <stdlib.h>
+#include <sysprof-capture.h>
+#include <unistd.h>
+
+typedef struct
+{
+ guint64 src;
+ guint64 dst;
+} TranslateItem;
+
+enum {
+ TRANSLATE_ADDR,
+ TRANSLATE_CTR,
+ N_TRANSLATE
+};
+
+static void
+translate_table_clear (GArray **tables,
+ guint table)
+{
+ g_clear_pointer (&tables[table], g_array_unref);
+}
+
+static gint
+compare_by_src (gconstpointer a,
+ gconstpointer b)
+{
+ const TranslateItem *itema = a;
+ const TranslateItem *itemb = a;
+
+ if (itema->src < itemb->src)
+ return -1;
+ else if (itema->src > itemb->src)
+ return 1;
+ else
+ return 0;
+}
+
+static void
+translate_table_sort (GArray **tables,
+ guint table)
+{
+ if (tables[table])
+ g_array_sort (tables[table], compare_by_src);
+}
+
+static void
+translate_table_add (GArray **tables,
+ guint table,
+ guint64 src,
+ guint64 dst)
+{
+ TranslateItem item = { src, dst };
+
+ if (tables[table] == NULL)
+ tables[table] = g_array_new (FALSE, FALSE, sizeof (TranslateItem));
+
+ g_array_append_val (tables[table], item);
+}
+
+static guint64
+translate_table_translate (GArray **tables,
+ guint table,
+ guint64 src)
+{
+ const TranslateItem *item;
+ TranslateItem key = { src, 0 };
+
+ if (!tables[table])
+ return src;
+
+ item = bsearch (&key,
+ tables[table]->data,
+ tables[table]->len,
+ sizeof (TranslateItem),
+ compare_by_src);
+
+ return item != NULL ? item->dst : src;
+}
+
+gboolean
+sysprof_capture_writer_cat (SysprofCaptureWriter *self,
+ SysprofCaptureReader *reader,
+ GError **error)
+{
+ GArray *tables[N_TRANSLATE] = { NULL };
+ SysprofCaptureFrameType type;
+ gint64 start_time;
+ gint64 first_start_time = G_MAXINT64;
+ gint64 end_time = -1;
+
+ g_return_val_if_fail (self != NULL, FALSE);
+ g_return_val_if_fail (reader != NULL, FALSE);
+
+ translate_table_clear (tables, TRANSLATE_CTR);
+ translate_table_clear (tables, TRANSLATE_ADDR);
+
+ start_time = sysprof_capture_reader_get_start_time (reader);
+
+ if (start_time < first_start_time)
+ first_start_time = start_time;
+
+ while (sysprof_capture_reader_peek_type (reader, &type))
+ {
+ SysprofCaptureFrame fr;
+
+ if (sysprof_capture_reader_peek_frame (reader, &fr))
+ {
+ if (fr.time > end_time)
+ end_time = fr.time;
+ }
+
+ switch (type)
+ {
+ case SYSPROF_CAPTURE_FRAME_TIMESTAMP:
+ {
+ const SysprofCaptureTimestamp *frame;
+
+ if (!(frame = sysprof_capture_reader_read_timestamp (reader)))
+ goto panic;
+
+ sysprof_capture_writer_add_timestamp (self,
+ frame->frame.time,
+ frame->frame.cpu,
+ frame->frame.pid);
+ break;
+ }
+
+ case SYSPROF_CAPTURE_FRAME_MAP:
+ {
+ const SysprofCaptureMap *frame;
+
+ if (!(frame = sysprof_capture_reader_read_map (reader)))
+ goto panic;
+
+ sysprof_capture_writer_add_map (self,
+ frame->frame.time,
+ frame->frame.cpu,
+ frame->frame.pid,
+ frame->start,
+ frame->end,
+ frame->offset,
+ frame->inode,
+ frame->filename);
+ break;
+ }
+
+ case SYSPROF_CAPTURE_FRAME_MARK:
+ {
+ const SysprofCaptureMark *frame;
+
+ if (!(frame = sysprof_capture_reader_read_mark (reader)))
+ goto panic;
+
+ sysprof_capture_writer_add_mark (self,
+ frame->frame.time,
+ frame->frame.cpu,
+ frame->frame.pid,
+ frame->duration,
+ frame->group,
+ frame->name,
+ frame->message);
+
+ if (frame->frame.time + frame->duration > end_time)
+ end_time = frame->frame.time + frame->duration;
+
+ break;
+ }
+
+ case SYSPROF_CAPTURE_FRAME_PROCESS:
+ {
+ const SysprofCaptureProcess *frame;
+
+ if (!(frame = sysprof_capture_reader_read_process (reader)))
+ goto panic;
+
+ sysprof_capture_writer_add_process (self,
+ frame->frame.time,
+ frame->frame.cpu,
+ frame->frame.pid,
+ frame->cmdline);
+ break;
+ }
+
+ case SYSPROF_CAPTURE_FRAME_FORK:
+ {
+ const SysprofCaptureFork *frame;
+
+ if (!(frame = sysprof_capture_reader_read_fork (reader)))
+ goto panic;
+
+ sysprof_capture_writer_add_fork (self,
+ frame->frame.time,
+ frame->frame.cpu,
+ frame->frame.pid,
+ frame->child_pid);
+ break;
+ }
+
+ case SYSPROF_CAPTURE_FRAME_EXIT:
+ {
+ const SysprofCaptureExit *frame;
+
+ if (!(frame = sysprof_capture_reader_read_exit (reader)))
+ goto panic;
+
+ sysprof_capture_writer_add_exit (self,
+ frame->frame.time,
+ frame->frame.cpu,
+ frame->frame.pid);
+ break;
+ }
+
+ case SYSPROF_CAPTURE_FRAME_METADATA:
+ {
+ const SysprofCaptureMetadata *frame;
+
+ if (!(frame = sysprof_capture_reader_read_metadata (reader)))
+ goto panic;
+
+ sysprof_capture_writer_add_metadata (self,
+ frame->frame.time,
+ frame->frame.cpu,
+ frame->frame.pid,
+ frame->id,
+ frame->metadata,
+ frame->frame.len - G_STRUCT_OFFSET (SysprofCaptureMetadata,
metadata));
+ break;
+ }
+
+ case SYSPROF_CAPTURE_FRAME_JITMAP:
+ {
+ GHashTable *jitmap;
+ GHashTableIter iter;
+ const gchar *name;
+ guint64 addr;
+
+ if (!(jitmap = sysprof_capture_reader_read_jitmap (reader)))
+ goto panic;
+
+ g_hash_table_iter_init (&iter, jitmap);
+ while (g_hash_table_iter_next (&iter, (gpointer *)&addr, (gpointer *)&name))
+ {
+ guint64 replace = sysprof_capture_writer_add_jitmap (self, name);
+ /* We need to keep a table of replacement addresses so that
+ * we can translate the samples into the destination address
+ * space that we synthesized for the address identifier.
+ */
+ translate_table_add (tables, TRANSLATE_ADDR, addr, replace);
+ }
+
+ translate_table_sort (tables, TRANSLATE_ADDR);
+
+ g_hash_table_unref (jitmap);
+
+ break;
+ }
+
+ case SYSPROF_CAPTURE_FRAME_SAMPLE:
+ {
+ const SysprofCaptureSample *frame;
+
+ if (!(frame = sysprof_capture_reader_read_sample (reader)))
+ goto panic;
+
+ {
+ SysprofCaptureAddress addrs[frame->n_addrs];
+
+ for (guint z = 0; z < frame->n_addrs; z++)
+ addrs[z] = translate_table_translate (tables, TRANSLATE_ADDR, frame->addrs[z]);
+
+ sysprof_capture_writer_add_sample (self,
+ frame->frame.time,
+ frame->frame.cpu,
+ frame->frame.pid,
+ frame->tid,
+ addrs,
+ frame->n_addrs);
+ }
+
+ break;
+ }
+
+ case SYSPROF_CAPTURE_FRAME_CTRDEF:
+ {
+ const SysprofCaptureFrameCounterDefine *frame;
+
+ if (!(frame = sysprof_capture_reader_read_counter_define (reader)))
+ goto panic;
+
+ {
+ g_autoptr(GArray) counter = g_array_new (FALSE, FALSE, sizeof (SysprofCaptureCounter));
+
+ for (guint z = 0; z < frame->n_counters; z++)
+ {
+ SysprofCaptureCounter c = frame->counters[z];
+ guint src = c.id;
+
+ c.id = sysprof_capture_writer_request_counter (self, 1);
+
+ if (c.id != src)
+ translate_table_add (tables, TRANSLATE_CTR, src, c.id);
+
+ g_array_append_val (counter, c);
+ }
+
+ sysprof_capture_writer_define_counters (self,
+ frame->frame.time,
+ frame->frame.cpu,
+ frame->frame.pid,
+ (gpointer)counter->data,
+ counter->len);
+
+ translate_table_sort (tables, TRANSLATE_CTR);
+ }
+
+ break;
+ }
+
+ case SYSPROF_CAPTURE_FRAME_CTRSET:
+ {
+ const SysprofCaptureFrameCounterSet *frame;
+
+ if (!(frame = sysprof_capture_reader_read_counter_set (reader)))
+ goto panic;
+
+ {
+ g_autoptr(GArray) ids = g_array_new (FALSE, FALSE, sizeof (guint));
+ g_autoptr(GArray) values = g_array_new (FALSE, FALSE, sizeof (SysprofCaptureCounterValue));
+
+ for (guint z = 0; z < frame->n_values; z++)
+ {
+ const SysprofCaptureCounterValues *v = &frame->values[z];
+
+ for (guint y = 0; y < G_N_ELEMENTS (v->ids); y++)
+ {
+ if (v->ids[y])
+ {
+ guint dst = translate_table_translate (tables, TRANSLATE_CTR, v->ids[y]);
+ SysprofCaptureCounterValue value = v->values[y];
+
+ g_array_append_val (ids, dst);
+ g_array_append_val (values, value);
+ }
+ }
+ }
+
+ g_assert (ids->len == values->len);
+
+ sysprof_capture_writer_set_counters (self,
+ frame->frame.time,
+ frame->frame.cpu,
+ frame->frame.pid,
+ (const guint *)(gpointer)ids->data,
+ (const SysprofCaptureCounterValue
*)(gpointer)values->data,
+ ids->len);
+ }
+
+ break;
+ }
+
+ default:
+ break;
+ }
+ }
+
+ sysprof_capture_writer_flush (self);
+
+ /* do this after flushing as it uses pwrite() to replace data */
+ _sysprof_capture_writer_set_time_range (self, first_start_time, end_time);
+
+ translate_table_clear (tables, TRANSLATE_ADDR);
+ translate_table_clear (tables, TRANSLATE_CTR);
+
+ return TRUE;
+
+panic:
+ g_set_error (error,
+ G_FILE_ERROR,
+ G_FILE_ERROR_FAILED,
+ "Failed to write data");
+
+ translate_table_clear (tables, TRANSLATE_ADDR);
+ translate_table_clear (tables, TRANSLATE_CTR);
+
+ return FALSE;
+}
diff --git a/src/libsysprof-capture/sysprof-capture-writer.h b/src/libsysprof-capture/sysprof-capture-writer.h
index ebb2b8d..2074261 100644
--- a/src/libsysprof-capture/sysprof-capture-writer.h
+++ b/src/libsysprof-capture/sysprof-capture-writer.h
@@ -133,6 +133,10 @@ SYSPROF_AVAILABLE_IN_ALL
gboolean sysprof_capture_writer_splice (SysprofCaptureWriter *self,
SysprofCaptureWriter *dest,
GError **error);
+SYSPROF_AVAILABLE_IN_ALL
+gboolean sysprof_capture_writer_cat (SysprofCaptureWriter *self,
+ SysprofCaptureReader *reader,
+ GError **error);
G_GNUC_INTERNAL
gboolean _sysprof_capture_writer_splice_from_fd (SysprofCaptureWriter *self,
int fd,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]