[sysprof/wip/chergert/sysprof-3] libsysprof-capture: add file chunk frame type



commit 0b899ed61d537f1a8d77b720c2f64d92d63b15c7
Author: Christian Hergert <chergert redhat com>
Date:   Mon May 27 15:18:44 2019 -0700

    libsysprof-capture: add file chunk frame type

 src/libsysprof-capture/sysprof-capture-cursor.c    |  4 ++
 src/libsysprof-capture/sysprof-capture-reader.c    | 51 +++++++++++++++
 src/libsysprof-capture/sysprof-capture-reader.h    |  6 +-
 src/libsysprof-capture/sysprof-capture-types.h     | 38 ++++++++----
 .../sysprof-capture-writer-cat.c                   | 18 ++++++
 src/libsysprof-capture/sysprof-capture-writer.c    | 72 ++++++++++++++++++++++
 src/libsysprof-capture/sysprof-capture-writer.h    | 16 +++++
 src/tests/test-capture.c                           | 71 +++++++++++++++++++++
 src/tools/sysprof-dump.c                           | 15 +++++
 9 files changed, 277 insertions(+), 14 deletions(-)
---
diff --git a/src/libsysprof-capture/sysprof-capture-cursor.c b/src/libsysprof-capture/sysprof-capture-cursor.c
index d3ae153..bdfc44c 100644
--- a/src/libsysprof-capture/sysprof-capture-cursor.c
+++ b/src/libsysprof-capture/sysprof-capture-cursor.c
@@ -167,6 +167,10 @@ sysprof_capture_cursor_foreach (SysprofCaptureCursor         *self,
           delegate = READ_DELEGATE (sysprof_capture_reader_read_metadata);
           break;
 
+        case SYSPROF_CAPTURE_FRAME_FILE_CHUNK:
+          delegate = READ_DELEGATE (sysprof_capture_reader_read_file);
+          break;
+
         default:
           if (!sysprof_capture_reader_skip (self->reader))
             return;
diff --git a/src/libsysprof-capture/sysprof-capture-reader.c b/src/libsysprof-capture/sysprof-capture-reader.c
index 19f471d..640bfd4 100644
--- a/src/libsysprof-capture/sysprof-capture-reader.c
+++ b/src/libsysprof-capture/sysprof-capture-reader.c
@@ -232,6 +232,17 @@ sysprof_capture_reader_bswap_frame (SysprofCaptureReader *self,
     }
 }
 
+static inline void
+sysprof_capture_reader_bswap_file_chunk (SysprofCaptureReader    *self,
+                                         SysprofCaptureFileChunk *file_chunk)
+{
+  g_assert (self != NULL);
+  g_assert (file_chunk != NULL);
+
+  if (G_UNLIKELY (self->endian != G_BYTE_ORDER))
+    file_chunk->len = GUINT16_SWAP_LE_BE (file_chunk->len);
+}
+
 static inline void
 sysprof_capture_reader_bswap_log (SysprofCaptureReader *self,
                                   SysprofCaptureLog    *log)
@@ -1122,3 +1133,43 @@ sysprof_capture_reader_get_stat (SysprofCaptureReader *self,
 
   return self->st_buf_set;
 }
+
+const SysprofCaptureFileChunk *
+sysprof_capture_reader_read_file (SysprofCaptureReader *self)
+{
+  SysprofCaptureFileChunk *file_chunk;
+
+  g_assert (self != NULL);
+  g_assert ((self->pos % SYSPROF_CAPTURE_ALIGN) == 0);
+  g_assert (self->pos <= self->bufsz);
+
+  if (!sysprof_capture_reader_ensure_space_for (self, sizeof *file_chunk))
+    return NULL;
+
+  file_chunk = (SysprofCaptureFileChunk *)(gpointer)&self->buf[self->pos];
+
+  sysprof_capture_reader_bswap_frame (self, &file_chunk->frame);
+
+  if (file_chunk->frame.type != SYSPROF_CAPTURE_FRAME_FILE_CHUNK)
+    return NULL;
+
+  if (file_chunk->frame.len < sizeof *file_chunk)
+    return NULL;
+
+  if (!sysprof_capture_reader_ensure_space_for (self, file_chunk->frame.len))
+    return NULL;
+
+  file_chunk = (SysprofCaptureFileChunk *)(gpointer)&self->buf[self->pos];
+
+  sysprof_capture_reader_bswap_file_chunk (self, file_chunk);
+
+  self->pos += file_chunk->frame.len;
+
+  if ((self->pos % SYSPROF_CAPTURE_ALIGN) != 0)
+    return NULL;
+
+  /* Ensure trailing \0 in .path */
+  file_chunk->path[sizeof file_chunk->path - 1] = 0;
+
+  return file_chunk;
+}
diff --git a/src/libsysprof-capture/sysprof-capture-reader.h b/src/libsysprof-capture/sysprof-capture-reader.h
index cbddc56..f14128e 100644
--- a/src/libsysprof-capture/sysprof-capture-reader.h
+++ b/src/libsysprof-capture/sysprof-capture-reader.h
@@ -76,9 +76,11 @@ const SysprofCaptureSample             *sysprof_capture_reader_read_sample
 SYSPROF_AVAILABLE_IN_ALL
 GHashTable                             *sysprof_capture_reader_read_jitmap         (SysprofCaptureReader     
*self);
 SYSPROF_AVAILABLE_IN_ALL
-const SysprofCaptureCounterDefine *sysprof_capture_reader_read_counter_define (SysprofCaptureReader     
*self);
+const SysprofCaptureCounterDefine      *sysprof_capture_reader_read_counter_define (SysprofCaptureReader     
*self);
 SYSPROF_AVAILABLE_IN_ALL
-const SysprofCaptureCounterSet    *sysprof_capture_reader_read_counter_set    (SysprofCaptureReader     
*self);
+const SysprofCaptureCounterSet         *sysprof_capture_reader_read_counter_set    (SysprofCaptureReader     
*self);
+SYSPROF_AVAILABLE_IN_ALL
+const SysprofCaptureFileChunk          *sysprof_capture_reader_read_file           (SysprofCaptureReader     
*self);
 SYSPROF_AVAILABLE_IN_ALL
 gboolean                                sysprof_capture_reader_reset               (SysprofCaptureReader     
*self);
 SYSPROF_AVAILABLE_IN_ALL
diff --git a/src/libsysprof-capture/sysprof-capture-types.h b/src/libsysprof-capture/sysprof-capture-types.h
index 4281786..59d93c1 100644
--- a/src/libsysprof-capture/sysprof-capture-types.h
+++ b/src/libsysprof-capture/sysprof-capture-types.h
@@ -79,18 +79,19 @@ typedef union
 
 typedef enum
 {
-  SYSPROF_CAPTURE_FRAME_TIMESTAMP = 1,
-  SYSPROF_CAPTURE_FRAME_SAMPLE    = 2,
-  SYSPROF_CAPTURE_FRAME_MAP       = 3,
-  SYSPROF_CAPTURE_FRAME_PROCESS   = 4,
-  SYSPROF_CAPTURE_FRAME_FORK      = 5,
-  SYSPROF_CAPTURE_FRAME_EXIT      = 6,
-  SYSPROF_CAPTURE_FRAME_JITMAP    = 7,
-  SYSPROF_CAPTURE_FRAME_CTRDEF    = 8,
-  SYSPROF_CAPTURE_FRAME_CTRSET    = 9,
-  SYSPROF_CAPTURE_FRAME_MARK      = 10,
-  SYSPROF_CAPTURE_FRAME_METADATA  = 11,
-  SYSPROF_CAPTURE_FRAME_LOG       = 12,
+  SYSPROF_CAPTURE_FRAME_TIMESTAMP  = 1,
+  SYSPROF_CAPTURE_FRAME_SAMPLE     = 2,
+  SYSPROF_CAPTURE_FRAME_MAP        = 3,
+  SYSPROF_CAPTURE_FRAME_PROCESS    = 4,
+  SYSPROF_CAPTURE_FRAME_FORK       = 5,
+  SYSPROF_CAPTURE_FRAME_EXIT       = 6,
+  SYSPROF_CAPTURE_FRAME_JITMAP     = 7,
+  SYSPROF_CAPTURE_FRAME_CTRDEF     = 8,
+  SYSPROF_CAPTURE_FRAME_CTRSET     = 9,
+  SYSPROF_CAPTURE_FRAME_MARK       = 10,
+  SYSPROF_CAPTURE_FRAME_METADATA   = 11,
+  SYSPROF_CAPTURE_FRAME_LOG        = 12,
+  SYSPROF_CAPTURE_FRAME_FILE_CHUNK = 13,
 } SysprofCaptureFrameType;
 
 SYSPROF_ALIGNED_BEGIN(1)
@@ -262,6 +263,18 @@ typedef struct
 } SysprofCaptureLog
 SYSPROF_ALIGNED_END(1);
 
+SYSPROF_ALIGNED_BEGIN(1)
+typedef struct
+{
+  SysprofCaptureFrame frame;
+  guint32             is_last : 1;
+  guint32             padding1 : 15;
+  guint32             len : 16;
+  gchar               path[256];
+  guint8              data[0];
+} SysprofCaptureFileChunk
+SYSPROF_ALIGNED_END(1);
+
 G_STATIC_ASSERT (sizeof (SysprofCaptureFileHeader) == 256);
 G_STATIC_ASSERT (sizeof (SysprofCaptureFrame) == 24);
 G_STATIC_ASSERT (sizeof (SysprofCaptureMap) == 56);
@@ -278,6 +291,7 @@ G_STATIC_ASSERT (sizeof (SysprofCaptureCounterSet) == 32);
 G_STATIC_ASSERT (sizeof (SysprofCaptureMark) == 96);
 G_STATIC_ASSERT (sizeof (SysprofCaptureMetadata) == 64);
 G_STATIC_ASSERT (sizeof (SysprofCaptureLog) == 64);
+G_STATIC_ASSERT (sizeof (SysprofCaptureFileChunk) == 284);
 
 static inline gint
 sysprof_capture_address_compare (SysprofCaptureAddress a,
diff --git a/src/libsysprof-capture/sysprof-capture-writer-cat.c 
b/src/libsysprof-capture/sysprof-capture-writer-cat.c
index 36e066f..ac1b110 100644
--- a/src/libsysprof-capture/sysprof-capture-writer-cat.c
+++ b/src/libsysprof-capture/sysprof-capture-writer-cat.c
@@ -151,6 +151,24 @@ sysprof_capture_writer_cat (SysprofCaptureWriter  *self,
             break;
           }
 
+        case SYSPROF_CAPTURE_FRAME_FILE_CHUNK:
+          {
+            const SysprofCaptureFileChunk *frame;
+
+            if (!(frame = sysprof_capture_reader_read_file (reader)))
+              goto panic;
+
+            sysprof_capture_writer_add_file (self,
+                                             frame->frame.time,
+                                             frame->frame.cpu,
+                                             frame->frame.pid,
+                                             frame->path,
+                                             frame->is_last,
+                                             frame->data,
+                                             frame->len);
+            break;
+          }
+
         case SYSPROF_CAPTURE_FRAME_LOG:
           {
             const SysprofCaptureLog *frame;
diff --git a/src/libsysprof-capture/sysprof-capture-writer.c b/src/libsysprof-capture/sysprof-capture-writer.c
index 1792591..0440d78 100644
--- a/src/libsysprof-capture/sysprof-capture-writer.c
+++ b/src/libsysprof-capture/sysprof-capture-writer.c
@@ -1349,3 +1349,75 @@ sysprof_capture_writer_add_log (SysprofCaptureWriter *self,
 
   return TRUE;
 }
+
+gboolean
+sysprof_capture_writer_add_file (SysprofCaptureWriter *self,
+                                 gint64                time,
+                                 gint                  cpu,
+                                 gint32                pid,
+                                 const gchar          *path,
+                                 gboolean              is_last,
+                                 const guint8         *data,
+                                 gsize                 data_len)
+{
+  SysprofCaptureFileChunk *ev;
+  gsize len;
+
+  g_assert (self != NULL);
+
+  len = sizeof *ev + data_len;
+  ev = (SysprofCaptureFileChunk *)sysprof_capture_writer_allocate (self, &len);
+  if (!ev)
+    return FALSE;
+
+  sysprof_capture_writer_frame_init (&ev->frame,
+                                     len,
+                                     cpu,
+                                     pid,
+                                     time,
+                                     SYSPROF_CAPTURE_FRAME_FILE_CHUNK);
+
+  ev->padding1 = 0;
+  ev->is_last = !!is_last;
+  ev->len = data_len;
+  g_strlcpy (ev->path, path, sizeof ev->path);
+  memcpy (ev->data, data, data_len);
+
+  self->stat.frame_count[SYSPROF_CAPTURE_FRAME_FILE_CHUNK]++;
+
+  return TRUE;
+}
+
+gboolean
+sysprof_capture_writer_add_file_fd (SysprofCaptureWriter *self,
+                                    gint64                time,
+                                    gint                  cpu,
+                                    gint32                pid,
+                                    const gchar          *path,
+                                    gint                  fd)
+{
+  guint8 data[(4096*4L) - sizeof(SysprofCaptureFileChunk)];
+
+  g_assert (self != NULL);
+
+  for (;;)
+    {
+      gboolean is_last;
+      gssize n_read;
+
+    again:
+      n_read = read (fd, data, sizeof data);
+      if (n_read < 0 && errno == EAGAIN)
+        goto again;
+
+      is_last = n_read == 0;
+
+      if (!sysprof_capture_writer_add_file (self, time, cpu, pid, path, is_last, data, n_read))
+        return FALSE;
+
+      if (is_last)
+        break;
+    }
+
+  return TRUE;
+}
diff --git a/src/libsysprof-capture/sysprof-capture-writer.h b/src/libsysprof-capture/sysprof-capture-writer.h
index 4aa9449..1cc3136 100644
--- a/src/libsysprof-capture/sysprof-capture-writer.h
+++ b/src/libsysprof-capture/sysprof-capture-writer.h
@@ -45,6 +45,22 @@ SYSPROF_AVAILABLE_IN_ALL
 void                  sysprof_capture_writer_stat            (SysprofCaptureWriter              *self,
                                                               SysprofCaptureStat                *stat);
 SYSPROF_AVAILABLE_IN_ALL
+gboolean              sysprof_capture_writer_add_file        (SysprofCaptureWriter              *self,
+                                                              gint64                             time,
+                                                              gint                               cpu,
+                                                              gint32                             pid,
+                                                              const gchar                       *path,
+                                                              gboolean                           is_last,
+                                                              const guint8                      *data,
+                                                              gsize                              data_len);
+SYSPROF_AVAILABLE_IN_ALL
+gboolean              sysprof_capture_writer_add_file_fd     (SysprofCaptureWriter              *self,
+                                                              gint64                             time,
+                                                              gint                               cpu,
+                                                              gint32                             pid,
+                                                              const gchar                       *path,
+                                                              gint                               fd);
+SYSPROF_AVAILABLE_IN_ALL
 gboolean              sysprof_capture_writer_add_map         (SysprofCaptureWriter              *self,
                                                               gint64                             time,
                                                               gint                               cpu,
diff --git a/src/tests/test-capture.c b/src/tests/test-capture.c
index ef65d21..3f60325 100644
--- a/src/tests/test-capture.c
+++ b/src/tests/test-capture.c
@@ -20,9 +20,12 @@
 
 #include "config.h"
 
+#include <fcntl.h>
 #include <glib/gstdio.h>
 #include <string.h>
 #include <sysprof-capture.h>
+#include <sys/types.h>
+#include <unistd.h>
 
 static void
 test_reader_basic (void)
@@ -708,6 +711,73 @@ test_reader_writer_metadata (void)
   g_unlink ("metadata1.syscap");
 }
 
+static void
+test_reader_writer_file (void)
+{
+  g_autofree gchar *data = NULL;
+  GByteArray *buf = g_byte_array_new ();
+  SysprofCaptureWriter *writer;
+  SysprofCaptureReader *reader;
+  SysprofCaptureFrameType type;
+  GError *error = NULL;
+  gssize len;
+  gsize data_len;
+  guint count = 0;
+  gint fd;
+  gint r;
+
+  writer = sysprof_capture_writer_new ("file1.syscap", 0);
+  fd = g_open ("/proc/kallsyms", O_RDONLY);
+
+  r = g_file_get_contents ("/proc/kallsyms", &data, &data_len, NULL);
+  g_assert_true (r);
+
+  len = lseek (fd, SEEK_END, 0);
+  g_assert_cmpint (len, >, 0);
+
+  lseek (fd, SEEK_SET, 0);
+  sysprof_capture_writer_add_file_fd (writer, SYSPROF_CAPTURE_CURRENT_TIME, -1, -1, "/proc/kallsyms", fd);
+
+  lseek (fd, SEEK_SET, 0);
+  sysprof_capture_writer_add_file_fd (writer, SYSPROF_CAPTURE_CURRENT_TIME, -1, -1, "/proc/kallsyms", fd);
+
+  close (fd);
+
+  g_clear_pointer (&writer, sysprof_capture_writer_unref);
+
+  reader = sysprof_capture_reader_new ("file1.syscap", &error);
+  g_assert_no_error (error);
+  g_assert (reader != NULL);
+
+  while (count < 2)
+    {
+      const SysprofCaptureFileChunk *file;
+
+      r = sysprof_capture_reader_peek_type (reader, &type);
+      g_assert_true (r);
+      g_assert_cmpint (type, ==, SYSPROF_CAPTURE_FRAME_FILE_CHUNK);
+
+      file = sysprof_capture_reader_read_file (reader);
+      g_assert_nonnull (file);
+      g_assert_cmpstr (file->path, ==, "/proc/kallsyms");
+
+      if (count == 0)
+        g_byte_array_append (buf, file->data, file->len);
+
+      count += file->is_last;
+    }
+
+  g_assert_cmpint (0, ==, memcmp (data, buf->data, data_len));
+
+  r = sysprof_capture_reader_peek_type (reader, &type);
+  g_assert_cmpint (r, ==, FALSE);
+
+  g_clear_pointer (&reader, sysprof_capture_reader_unref);
+  g_clear_pointer (&buf, g_byte_array_unref);
+
+  g_unlink ("file1.syscap");
+}
+
 int
 main (int argc,
       char *argv[])
@@ -720,5 +790,6 @@ main (int argc,
   g_test_add_func ("/SysprofCapture/ReaderWriter/log", test_reader_writer_log);
   g_test_add_func ("/SysprofCapture/ReaderWriter/mark", test_reader_writer_mark);
   g_test_add_func ("/SysprofCapture/ReaderWriter/metadata", test_reader_writer_metadata);
+  g_test_add_func ("/SysprofCapture/ReaderWriter/file", test_reader_writer_file);
   return g_test_run ();
 }
diff --git a/src/tools/sysprof-dump.c b/src/tools/sysprof-dump.c
index 77ec7c3..513f993 100644
--- a/src/tools/sysprof-dump.c
+++ b/src/tools/sysprof-dump.c
@@ -139,6 +139,21 @@ main (gint argc,
             break;
           }
 
+        case SYSPROF_CAPTURE_FRAME_FILE_CHUNK:
+          {
+            const SysprofCaptureFileChunk *file_chunk = sysprof_capture_reader_read_file (reader);
+            gdouble ptime = (file_chunk->frame.time - begin_time) / (gdouble)NSEC_PER_SEC;
+
+            g_print ("FILE_CHUNK: pid=%d time=%"G_GINT64_FORMAT" (%lf)\n"
+                     "     path = %s\n"
+                     "  is_last = %d\n"
+                     "    bytes = %d\n",
+                     file_chunk->frame.pid, file_chunk->frame.time, ptime,
+                     file_chunk->path, file_chunk->is_last, file_chunk->len);
+
+            break;
+          }
+
         case SYSPROF_CAPTURE_FRAME_MARK:
           {
             const SysprofCaptureMark *mark = sysprof_capture_reader_read_mark (reader);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]