[sysprof/wip/chergert/sysprof-3] sysprofd: start on optimized getprocessinfo helper



commit 4858469af9e1f0b79bd2d4420ac11f7f37c8f9b1
Author: Christian Hergert <chergert redhat com>
Date:   Fri May 10 15:24:38 2019 -0700

    sysprofd: start on optimized getprocessinfo helper
    
    Calling all the individual function calls to get process information would
    be considerably inefficient, so we can coalesce a bunch of that and change
    our process-model implementation (and proc source) to use this.

 src/org.gnome.Sysprof3.Service.xml | 20 ++++++++++
 src/sysprofd/ipc-service-impl.c    | 75 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 95 insertions(+)
---
diff --git a/src/org.gnome.Sysprof3.Service.xml b/src/org.gnome.Sysprof3.Service.xml
index c4b4a86..1be4e13 100644
--- a/src/org.gnome.Sysprof3.Service.xml
+++ b/src/org.gnome.Sysprof3.Service.xml
@@ -52,5 +52,25 @@
     <method name="ListProcesses">
       <arg name="processes" type="ai" direction="out"/>
     </method>
+    <!--
+      GetProcessInfo:
+      @attributes: a comma separated string of attributes to load
+
+      Gets information about the processes on the system.
+
+      Attributes can be a comma separated list of the following:
+
+      - pid: (int32): the process identifier, always included
+      - cmdline: (string): Provides the command line
+      - maps: (string): Provide the contents of /proc/pid/maps
+      - statm: (string): Provide the contents of /proc/pid/statm
+      - mountinfo: (string): Provide the contents of/proc/pid/mountinfo
+
+      Returns: an array of vardict containing the requested attributs
+    -->
+    <method name="GetProcessInfo">
+      <arg name="attributes" type="s" direction="in"/>
+      <arg name="processes" type="aa{sv}" direction="out"/>
+    </method>
   </interface>
 </node>
diff --git a/src/sysprofd/ipc-service-impl.c b/src/sysprofd/ipc-service-impl.c
index 9458db0..c61d33b 100644
--- a/src/sysprofd/ipc-service-impl.c
+++ b/src/sysprofd/ipc-service-impl.c
@@ -188,12 +188,87 @@ ipc_service_impl_g_authorize_method (GDBusInterfaceSkeleton *skeleton,
   return ret;
 }
 
+static void
+add_pid_proc_file_to (gint          pid,
+                      const gchar  *name,
+                      GVariantDict *dict)
+{
+  g_autofree gchar *path = NULL;
+  g_autofree gchar *contents = NULL;
+  gsize len;
+
+  g_assert (pid > -1);
+  g_assert (name != NULL);
+  g_assert (dict != NULL);
+
+  path = g_strdup_printf ("/proc/%d/%s", pid, name);
+
+  if (g_file_get_contents (path, &contents, &len, NULL))
+    g_variant_dict_insert (dict, name, "s", contents);
+}
+
+static gboolean
+ipc_service_impl_handle_get_process_info (IpcService            *service,
+                                          GDBusMethodInvocation *invocation,
+                                          const gchar           *attributes)
+{
+  GVariantBuilder builder;
+  g_autofree gint *processes = NULL;
+  gsize n_processes = 0;
+  gboolean want_statm;
+  gboolean want_cmdline;
+  gboolean want_maps;
+  gboolean want_mountinfo;
+
+  g_assert (IPC_IS_SERVICE (service));
+  g_assert (G_IS_DBUS_METHOD_INVOCATION (invocation));
+  g_assert (attributes != NULL);
+
+  want_statm = !!strstr (attributes, "statm");
+  want_cmdline = !!strstr (attributes, "cmdline");
+  want_maps = !!strstr (attributes, "maps");
+  want_mountinfo = !!strstr (attributes, "mountinfo");
+
+  g_variant_builder_init (&builder, G_VARIANT_TYPE ("aa{sv}"));
+
+  if (helpers_list_processes (&processes, &n_processes))
+    {
+      for (guint i = 0; i < n_processes; i++)
+        {
+          gint pid = processes[i];
+          GVariantDict dict;
+
+          g_variant_dict_init (&dict, NULL);
+          g_variant_dict_insert (&dict, "pid", "i", pid);
+
+          if (want_statm)
+            add_pid_proc_file_to (pid, "statm", &dict);
+
+          if (want_cmdline)
+            add_pid_proc_file_to (pid, "cmdline", &dict);
+
+          if (want_maps)
+            add_pid_proc_file_to (pid, "maps", &dict);
+
+          if (want_mountinfo)
+            add_pid_proc_file_to (pid, "mountinfo", &dict);
+
+          g_variant_builder_add (&builder, "a{sv}", g_variant_dict_end (&dict));
+        }
+    }
+
+  ipc_service_complete_get_process_info (service, invocation, g_variant_builder_end (&builder));
+
+  return TRUE;
+}
+
 static void
 init_service_iface (IpcServiceIface *iface)
 {
   iface->handle_list_processes = ipc_service_impl_handle_list_processes;
   iface->handle_get_proc_file = ipc_service_impl_handle_get_proc_file;
   iface->handle_perf_event_open = ipc_service_impl_handle_perf_event_open;
+  iface->handle_get_process_info = ipc_service_impl_handle_get_process_info;
 }
 
 G_DEFINE_TYPE_WITH_CODE (IpcServiceImpl, ipc_service_impl, IPC_TYPE_SERVICE_SKELETON,


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