[nemiver/profiler] WIP



commit 72253afcbe0a8212454051613ad70b67d5d5ffd1
Author: Fabien Parent <parent f gmail com>
Date:   Sun Jul 22 21:47:46 2012 +0200

    WIP

 src/profengine/Makefile.am        |    1 +
 src/profengine/nmv-perf-engine.cc |   66 ++++++++++++++++++++-
 src/profengine/nmv-perf-server.cc |  117 ++++++++++++++++++++++++++++++++----
 3 files changed, 169 insertions(+), 15 deletions(-)
---
diff --git a/src/profengine/Makefile.am b/src/profengine/Makefile.am
index e054917..6385e74 100644
--- a/src/profengine/Makefile.am
+++ b/src/profengine/Makefile.am
@@ -28,6 +28,7 @@ publicheadersdir=$(NEMIVER_INCLUDE_DIR)/dynmods
 
 libperfmod_la_LDFLAGS=-module -avoid-version -Wl,--as-needed
 libperfmod_la_LIBADD=libperfengine.la @NEMIVERCOMMON_LIBS@ \
+ NEMIVERPROFPERSP_LIBS@ \
 $(abs_top_builddir)/src/common/libnemivercommon.la
 
 
diff --git a/src/profengine/nmv-perf-engine.cc b/src/profengine/nmv-perf-engine.cc
index a629757..030f82c 100644
--- a/src/profengine/nmv-perf-engine.cc
+++ b/src/profengine/nmv-perf-engine.cc
@@ -34,6 +34,8 @@
 #include <sys/types.h>
 #include <signal.h>
 #include <cstdio>
+#include <giomm.h>
+#include <glibmm.h>
 
 NEMIVER_BEGIN_NAMESPACE (nemiver)
 
@@ -62,6 +64,9 @@ struct PerfEngine::Priv {
     sigc::signal<void, const UString&> record_done_signal;
     sigc::signal<void, const UString&, const UString&> symbol_annotated_signal;
 
+    Glib::RefPtr<Gio::DBus::Connection> server_connection;
+    Glib::RefPtr<Gio::DBus::Proxy> proxy;
+
     Priv () :
         conf_manager (0),
         perf_pid (0),
@@ -69,8 +74,25 @@ struct PerfEngine::Priv {
         perf_stdout_fd (0),
         perf_stderr_fd (0),
         perf_stdout_channel (0),
-        call_graph (0)
+        call_graph (0),
+        server_connection (0),
+        proxy (0)
+    {
+        init ();
+    }
+
+    void
+    init ()
     {
+        server_connection =
+            Gio::DBus::Connection::get_sync (Gio::DBus::BUS_TYPE_SESSION);
+        THROW_IF_FAIL (server_connection);
+
+        proxy = Gio::DBus::Proxy::create_sync (server_connection,
+                                               "org.gnome.nemiver.profiler",
+                                               "/org/gnome/nemiver/profiler",
+                                               "org.gnome.nemiver.profiler");
+        THROW_IF_FAIL (proxy);
     }
 
     IConfMgr&
@@ -318,6 +340,22 @@ struct PerfEngine::Priv {
         return false;
     }
 
+    void
+    on_detached_from_process (Glib::RefPtr<Gio::AsyncResult> &a_result)
+    {
+        NEMIVER_TRY;
+
+        THROW_IF_FAIL (proxy);
+        Glib::VariantContainerBase result = proxy->call_finish (a_result);
+
+        Glib::Variant<Glib::ustring> record;
+        result.get_child (record);
+
+        record_done_signal.emit (record.get ());
+
+        NEMIVER_CATCH_NOX;
+    }
+
     ~Priv ()
     {
         LOG_D ("delete", "destructor-domain");
@@ -345,11 +383,33 @@ PerfEngine::do_init (IConfMgrSafePtr a_conf_mgr)
 void
 PerfEngine::attach_to_pid (int a_pid)
 {
-    std::vector<UString> argv;
+    THROW_IF_FAIL (m_priv);
+    THROW_IF_FAIL (m_priv->proxy);
+
+    std::vector<Glib::ustring> options;
+
+    Glib::Variant<int> pid_param = Glib::Variant<int>::create (a_pid);
+    Glib::Variant<std::vector<Glib::ustring> > options_param =
+        Glib::Variant<std::vector<Glib::ustring> >::create (options);
+
+    std::vector<Glib::VariantBase> parameters;
+    parameters.push_back (pid_param);
+    parameters.push_back (options_param);
+
+    Glib::VariantContainerBase parameters_variant =
+        Glib::VariantContainerBase::create_tuple (parameters);
+
+    m_priv->proxy->call
+        ("AttachToPID",
+         sigc::mem_fun (*m_priv, &PerfEngine::Priv::on_detached_from_process),
+         parameters_variant);
+
+/*    std::vector<UString> argv;
     argv.push_back ("--pid");
     argv.push_back (UString::compose ("%1", a_pid));
 
     record (argv);
+*/
 }
 
 void
@@ -470,6 +530,8 @@ PerfEngine::stop_recording ()
 void
 PerfEngine::report (const UString &a_data_file)
 {
+    THROW_IF_FAIL (Glib::file_test (a_data_file, Glib::FILE_TEST_EXISTS));
+
     std::vector<UString> argv;
     argv.push_back ("perf");
     argv.push_back ("report");
diff --git a/src/profengine/nmv-perf-server.cc b/src/profengine/nmv-perf-server.cc
index 9325ffd..68baf5c 100644
--- a/src/profengine/nmv-perf-server.cc
+++ b/src/profengine/nmv-perf-server.cc
@@ -26,24 +26,31 @@
 #include "common/nmv-namespace.h"
 #include "common/nmv-safe-ptr.h"
 #include "common/nmv-exception.h"
+#include "common/nmv-ustring.h"
+#include "common/nmv-proc-utils.h"
 
 #include <glibmm.h>
 #include <giomm.h>
 #include <glib/gi18n.h>
-
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <stdio.h>
 #include <iostream>
 
 using nemiver::common::SafePtr;
+using nemiver::common::FreeUnref;
+using nemiver::common::DefaultRef;
+using nemiver::common::UString;
 
 NEMIVER_BEGIN_NAMESPACE (nemiver)
 
 static const char *const NMV_BUS_NAME = "org.gnome.nemiver.profiler";
 static const char *const NMV_DBUS_PROFILER_SERVER_INTROSPECTION_DATA =
     "<node>"
-    "  <interface name='org.gnome.nemiver.profilers'>"
+    "  <interface name='org.gnome.nemiver.profiler'>"
     "    <method name='AttachToPID'>"
     "        <arg type='i' name='pid' direction='in' />"
-    "        <arg type='u' name='cookie' direction='in' />"
+//    "        <arg type='u' name='cookie' direction='in' />"
     "        <arg type='as' name='arguments' direction='in' />"
     "        <arg type='s' name='data_filepath' direction='out' />"
     "    </method>"
@@ -71,17 +78,56 @@ struct PerfServer::Priv {
     Glib::RefPtr<Gio::DBus::NodeInfo> introspection_data;
     Gio::DBus::InterfaceVTable interface_vtable;
 
+    int perf_pid;
+    int master_pty_fd;
+    int perf_stdout_fd;
+    int perf_stderr_fd;
+
     Priv () :
 //        subject (polkit_system_bus_name_new ("org.gnome.nemiver")),
         bus_id (0),
         registration_id (0),
         introspection_data (0),
         interface_vtable
-            (sigc::mem_fun (*this, &PerfServer::Priv::on_new_request))
+            (sigc::mem_fun (*this, &PerfServer::Priv::on_new_request)),
+        perf_pid (0),
+        master_pty_fd (0),
+        perf_stdout_fd (0),
+        perf_stderr_fd (0)
     {
         init ();
     }
 
+    bool
+    on_wait_for_record_to_exit (const Glib::RefPtr<Gio::DBus::MethodInvocation>
+                                    &a_invocation,
+                                Glib::ustring a_report_filepath)
+    {
+        int status = 0;
+        pid_t pid = waitpid (perf_pid, &status, WNOHANG);
+        bool is_terminated = WIFEXITED (status) || WIFSIGNALED (status);
+
+        if (pid == perf_pid && is_terminated) {
+            g_spawn_close_pid (perf_pid);
+            perf_pid = 0;
+            master_pty_fd = 0;
+            perf_stdout_fd = 0;
+            perf_stderr_fd = 0;
+
+            Glib::Variant<Glib::ustring> perf_data =
+                Glib::Variant<Glib::ustring>::create (a_report_filepath);
+
+            Glib::VariantContainerBase response =
+                Glib::VariantContainerBase::create_tuple (perf_data);
+
+            a_invocation->return_value (response);
+
+            return false;
+        }
+
+        return true;
+    }
+
     void
     on_new_request (const Glib::RefPtr<Gio::DBus::Connection>&,
                     const Glib::ustring&,
@@ -96,12 +142,57 @@ struct PerfServer::Priv {
 
         THROW_IF_FAIL (a_invocation);
 
-        if(a_request_name == "AttachToPID")
-        {
+        if(a_request_name == "AttachToPID") {
             Glib::Variant<int> pid_param;
+            Glib::Variant<std::vector<Glib::ustring> > options_param;
             a_parameters.get_child (pid_param);
-
-            std::cout << "PID: " << pid_param.get () << std::endl;
+            a_parameters.get_child (options_param, 1);
+
+            int pid = pid_param.get ();
+            std::vector<Glib::ustring> options (options_param.get ());
+            for (std::vector<Glib::ustring>::iterator iter = options.begin ();
+                 iter != options.end ();
+                 ++iter) {
+                if (*iter != "--output") {
+                    continue;
+                }
+
+                Gio::DBus::Error error
+                    (Gio::DBus::Error::INVALID_ARGS,
+                     _("--output parameter is "
+                       "forbidden for security reasons"));
+                a_invocation->return_error (error);
+            }
+
+            SafePtr<char, DefaultRef, FreeUnref> filepath (tempnam(0, 0));
+            THROW_IF_FAIL (filepath);
+
+            std::vector<UString> argv;
+            argv.push_back ("perf");
+            argv.push_back ("record");
+            argv.push_back ("--pid");
+            argv.push_back (UString::compose ("%1", pid));
+            argv.push_back ("--output");
+            argv.push_back (filepath.get ());
+            argv.insert (argv.end (), options.begin (), options.end ());
+
+            bool is_launched =
+                common::launch_program (argv,
+                                        perf_pid,
+                                        master_pty_fd,
+                                        perf_stdout_fd,
+                                        perf_stderr_fd);
+
+            THROW_IF_FAIL (is_launched);
+
+            Glib::RefPtr<Glib::MainContext> context =
+                Glib::MainContext::get_default ();
+            context->signal_idle ().connect
+                (sigc::bind<const Glib::RefPtr<Gio::DBus::MethodInvocation>, Glib::ustring>
+                        (sigc::mem_fun (*this,
+                         &PerfServer::Priv::on_wait_for_record_to_exit),
+                 a_invocation,
+                 filepath.get ()));
         }
         else
         {
@@ -122,13 +213,13 @@ struct PerfServer::Priv {
         bus_id = Gio::DBus::own_name
             (Gio::DBus::BUS_TYPE_SESSION,
              NMV_BUS_NAME,
-             sigc::mem_fun(*this, &PerfServer::Priv::on_bus_acquired),
-             sigc::mem_fun(*this, &PerfServer::Priv::on_name_acquired),
-             sigc::mem_fun(*this, &PerfServer::Priv::on_name_lost));
+             sigc::mem_fun (*this, &PerfServer::Priv::on_bus_acquired),
+             sigc::mem_fun (*this, &PerfServer::Priv::on_name_acquired),
+             sigc::mem_fun (*this, &PerfServer::Priv::on_name_lost));
     }
 
     void
-    on_bus_acquired(const Glib::RefPtr<Gio::DBus::Connection> &a_connection,
+    on_bus_acquired (const Glib::RefPtr<Gio::DBus::Connection> &a_connection,
                     const Glib::ustring&)
     {
         NEMIVER_TRY;
@@ -136,7 +227,7 @@ struct PerfServer::Priv {
         THROW_IF_FAIL (a_connection);
         registration_id = a_connection->register_object
             ("/org/gnome/nemiver/profiler",
-             introspection_data->lookup_interface(),
+             introspection_data->lookup_interface (),
              interface_vtable);
 
         NEMIVER_CATCH_NOX;



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