[nemiver/profiler: 40/48] WIP



commit 8319f5e32cce79d8c7cf26e965e76a545c665ef8
Author: Fabien Parent <parent f gmail com>
Date:   Sun Aug 5 16:00:57 2012 +0200

    WIP

 src/persp/profperspective/nmv-prof-perspective.cc |    7 +-
 src/persp/profperspective/nmv-record-options.h    |   51 +++++
 src/profengine/Makefile.am                        |   17 +-
 src/profengine/nmv-confmgr-record-options.cc      |  123 +++++++++++
 src/profengine/nmv-confmgr-record-options.h       |   59 +++++
 src/profengine/nmv-i-profiler.h                   |    4 +-
 src/profengine/nmv-perf-engine.cc                 |   86 ++------
 src/profengine/nmv-perf-engine.h                  |    6 +-
 src/profengine/nmv-perf-server.cc                 |  243 ++++++++++++---------
 src/profengine/nmv-record-options.h               |   57 +++++
 10 files changed, 476 insertions(+), 177 deletions(-)
---
diff --git a/src/persp/profperspective/nmv-prof-perspective.cc b/src/persp/profperspective/nmv-prof-perspective.cc
index f9c9f33..ae74941 100644
--- a/src/persp/profperspective/nmv-prof-perspective.cc
+++ b/src/persp/profperspective/nmv-prof-perspective.cc
@@ -31,6 +31,7 @@
 #include "nmv-spinner-tool-item.h"
 #include "nmv-run-program-dialog.h"
 #include "nmv-i-profiler.h"
+#include "nmv-confmgr-record-options.h"
 #include "common/nmv-safe-ptr-utils.h"
 #include "common/nmv-str-utils.h"
 #include "common/nmv-proc-mgr.h"
@@ -578,7 +579,11 @@ ProfPerspective::run_executable (const UString &a_program_name,
     THROW_IF_FAIL (!a_program_name.empty ());
     THROW_IF_FAIL (profiler ());
 
-    profiler ()->record (a_program_name, argv);
+    IConfMgrSafePtr confmgr = get_workbench ().get_configuration_manager ();
+    THROW_IF_FAIL (confmgr);
+
+    ConfMgrRecordOptions options (*confmgr);
+    profiler ()->record (a_program_name, argv, options);
 
     THROW_IF_FAIL (throbber);
     throbber->start ();
diff --git a/src/persp/profperspective/nmv-record-options.h b/src/persp/profperspective/nmv-record-options.h
new file mode 100644
index 0000000..3e2522a
--- /dev/null
+++ b/src/persp/profperspective/nmv-record-options.h
@@ -0,0 +1,51 @@
+//Author: Fabien Parent
+/*
+ *This file is part of the Nemiver project
+ *
+ *Nemiver 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 2,
+ *or (at your option) any later version.
+ *
+ *Nemiver 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 Nemiver;
+ *see the file COPYING.
+ *If not, write to the Free Software Foundation,
+ *Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *See COPYRIGHT file copyright information.
+ */
+#ifndef __NMV_RECORD_OPTIONS_H__
+#define __NMV_RECORD_OPTIONS_H__
+
+#include "common/nmv-namespace.h"
+
+NEMIVER_BEGIN_NAMESPACE (nemiver)
+
+class RecordOptions {
+    RecordOptions ();
+    RecordOptions (const RecordOptions&);
+    RecordOptions& operator= (const RecordOptions&);
+
+public:
+    virtual ~RecordOptions ();
+
+    virtual bool do_callgraph_recording () const = 0;
+    virtual bool do_collect_without_buffering () const = 0;
+    virtual bool do_collect_raw_sample_records () const = 0;
+    virtual bool do_system_wide_collection () const = 0;
+    virtual bool do_sample_addresses () const = 0;
+    virtual bool do_sample_timestamps () const = 0;
+}; // end namespace RecordOptions
+
+NEMIVER_END_NAMESPACE (nemiver)
+
+#endif /* __NMV_RECORD_OPTIONS_H__ */
+
diff --git a/src/profengine/Makefile.am b/src/profengine/Makefile.am
index 9408476..75e7b3c 100644
--- a/src/profengine/Makefile.am
+++ b/src/profengine/Makefile.am
@@ -2,7 +2,8 @@ perfmod_LTLIBRARIES=libperfmod.la
 perfmoddir= NEMIVER_MODULES_DIR@
 
 noinst_LTLIBRARIES=\
-libperfengine.la
+libperfengine.la \
+libperfcommon.la
 
 h=$(abs_srcdir)
 
@@ -15,19 +16,25 @@ $(iprofilerheaders)
 libperfmod_la_SOURCES= \
 $(iprofilerheaders)
 
-libperfengine_la_SOURCES= \
+libperfcommon_la_SOURCES= \
 $(h)/nmv-perf-engine.cc \
 $(h)/nmv-perf-engine.h \
+$(h)/nmv-record-options.h \
 $(h)/nmv-call-graph-node.cc \
 $(h)/nmv-call-graph-node.h
+libperfcommon_la_CFLAGS=-fPIC -DPIC
 
+libperfengine_la_SOURCES= \
+$(h)/nmv-confmgr-record-options.h \
+$(h)/nmv-confmgr-record-options.cc
 libperfengine_la_CFLAGS=-fPIC -DPIC
 
 publicheaders_DATA=$(dynmodheaders)
 publicheadersdir=$(NEMIVER_INCLUDE_DIR)/dynmods
 
 libperfmod_la_LDFLAGS=-module -avoid-version -Wl,--as-needed
-libperfmod_la_LIBADD=libperfengine.la @NEMIVERCOMMON_LIBS@ \
+libperfmod_la_LIBADD=libperfcommon.la libperfengine.la \
+ NEMIVERCOMMON_LIBS@ \
 @NEMIVERPROFPERSP_LIBS@ \
 $(abs_top_builddir)/src/common/libnemivercommon.la
 
@@ -36,10 +43,10 @@ config_DATA=perfengine.conf
 configdir= NEMIVER_SYSTEM_CONFIG_DIR@
 
 bin_PROGRAMS=nmvperfserver
-nmvperfserver_SOURCES= $(h)/nmv-perf-server.cc
+nmvperfserver_SOURCES=$(h)/nmv-perf-server.cc
 nmvperfserver= NEMIVER_MODULES_DIR@
 nmvperfserver_LDADD= NEMIVERPROFPERSP_LIBS@ \
-$(abs_top_builddir)/src/common/libnemivercommon.la
+$(abs_top_builddir)/src/common/libnemivercommon.la libperfcommon.la
 
 service_DATA=org.gnome.nemiver.profiler.service
 servicedir=$(datadir)/dbus-1/system-services
diff --git a/src/profengine/nmv-confmgr-record-options.cc b/src/profengine/nmv-confmgr-record-options.cc
new file mode 100644
index 0000000..72a8daf
--- /dev/null
+++ b/src/profengine/nmv-confmgr-record-options.cc
@@ -0,0 +1,123 @@
+// Author: Fabien Parent
+/*
+ *This file is part of the Nemiver project
+ *
+ *Nemiver 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 2,
+ *or (at your option) any later version.
+ *
+ *Nemiver 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 Nemiver;
+ *see the file COPYING.
+ *If not, write to the Free Software Foundation,
+ *Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *See COPYRIGHT file copyright information.
+ */
+
+#include "nmv-confmgr-record-options.h"
+#include "nmv-conf-keys.h"
+#include "nmv-i-conf-mgr.h"
+
+NEMIVER_BEGIN_NAMESPACE (nemiver)
+
+struct ConfMgrRecordOptions::Priv {
+    IConfMgr &conf_mgr;
+
+    Priv (IConfMgr &a_confmgr) :
+        conf_mgr (a_confmgr)
+    {
+    }
+};
+
+ConfMgrRecordOptions::ConfMgrRecordOptions (IConfMgr &a_confmgr) :
+    m_priv (new Priv (a_confmgr))
+{
+}
+
+ConfMgrRecordOptions::~ConfMgrRecordOptions ()
+{
+}
+
+bool
+ConfMgrRecordOptions::do_callgraph_recording () const
+{
+    bool callgraph_recording = false;
+    if (!m_priv->conf_mgr.get_key_value (CONF_KEY_DO_CALLGRAPH_RECORDING,
+                                         callgraph_recording)) {
+        LOG_ERROR ("failed to get gconf key "
+                   << CONF_KEY_DO_CALLGRAPH_RECORDING);
+    }
+    return callgraph_recording;
+}
+
+bool
+ConfMgrRecordOptions::do_collect_without_buffering () const
+{
+    bool collect_without_buffering = false;
+    if (!m_priv->conf_mgr.get_key_value (CONF_KEY_COLLECT_WITHOUT_BUFFERING,
+                                         collect_without_buffering)) {
+        LOG_ERROR ("failed to get gconf key "
+                   << CONF_KEY_COLLECT_WITHOUT_BUFFERING);
+    }
+    return collect_without_buffering;
+}
+
+bool
+ConfMgrRecordOptions::do_collect_raw_sample_records () const
+{
+    bool collect_raw_sample_records = false;
+    if (!m_priv->conf_mgr.get_key_value (CONF_KEY_COLLECT_RAW_SAMPLE_RECORDS,
+                                         collect_raw_sample_records)) {
+        LOG_ERROR ("failed to get gconf key "
+                   << CONF_KEY_COLLECT_RAW_SAMPLE_RECORDS);
+    }
+    return collect_raw_sample_records;
+}
+
+bool
+ConfMgrRecordOptions::do_system_wide_collection () const
+{
+    bool system_wide_collection = false;
+    if (!m_priv->conf_mgr.get_key_value (CONF_KEY_SYSTEM_WIDE_COLLECTION,
+                                         system_wide_collection)) {
+        LOG_ERROR ("failed to get gconf key "
+                   << CONF_KEY_SYSTEM_WIDE_COLLECTION);
+    }
+    return system_wide_collection;
+}
+
+bool
+ConfMgrRecordOptions::do_sample_addresses () const
+{
+    bool sample_addresses = false;
+    if (!m_priv->conf_mgr.get_key_value (CONF_KEY_SAMPLE_ADDRESSES,
+                                         sample_addresses)) {
+        LOG_ERROR ("failed to get gconf key "
+                   << CONF_KEY_SAMPLE_ADDRESSES);
+    }
+    return sample_addresses;
+}
+
+bool
+ConfMgrRecordOptions::do_sample_timestamps () const
+{
+    bool sample_timestamps = false;
+    if (!m_priv->conf_mgr.get_key_value (CONF_KEY_SAMPLE_TIMESTAMPS,
+                                         sample_timestamps)) {
+        LOG_ERROR ("failed to get gconf key "
+                   << CONF_KEY_SAMPLE_TIMESTAMPS);
+    }
+    return sample_timestamps;
+}
+
+NEMIVER_END_NAMESPACE (nemiver)
+
diff --git a/src/profengine/nmv-confmgr-record-options.h b/src/profengine/nmv-confmgr-record-options.h
new file mode 100644
index 0000000..ea44d1e
--- /dev/null
+++ b/src/profengine/nmv-confmgr-record-options.h
@@ -0,0 +1,59 @@
+//Author: Fabien Parent
+/*
+ *This file is part of the Nemiver project
+ *
+ *Nemiver 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 2,
+ *or (at your option) any later version.
+ *
+ *Nemiver 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 Nemiver;
+ *see the file COPYING.
+ *If not, write to the Free Software Foundation,
+ *Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *See COPYRIGHT file copyright information.
+ */
+#ifndef __NMV_CONFMGR_RECORD_OPTIONS_H__
+#define __NMV_CONFMGR_RECORD_OPTIONS_H__
+
+#include "nmv-record-options.h"
+#include "common/nmv-safe-ptr.h"
+
+NEMIVER_BEGIN_NAMESPACE (nemiver)
+
+class IConfMgr;
+
+using common::SafePtr;
+
+class ConfMgrRecordOptions : public RecordOptions {
+    ConfMgrRecordOptions (const RecordOptions&);
+    ConfMgrRecordOptions& operator= (const RecordOptions&);
+
+    struct Priv;
+    SafePtr<Priv> m_priv;
+
+public:
+    ConfMgrRecordOptions (IConfMgr&);
+    virtual ~ConfMgrRecordOptions ();
+
+    bool do_callgraph_recording () const;
+    bool do_collect_without_buffering () const;
+    bool do_collect_raw_sample_records () const;
+    bool do_system_wide_collection () const;
+    bool do_sample_addresses () const;
+    bool do_sample_timestamps () const;
+}; // end namespace ConfMgrRecordOptions
+
+NEMIVER_END_NAMESPACE (nemiver)
+
+#endif /* __NMV_CONFMGR_RECORD_OPTIONS_H__ */
+
diff --git a/src/profengine/nmv-i-profiler.h b/src/profengine/nmv-i-profiler.h
index 581cbc0..f728cab 100644
--- a/src/profengine/nmv-i-profiler.h
+++ b/src/profengine/nmv-i-profiler.h
@@ -32,6 +32,7 @@
 #include "nmv-i-conf-mgr.h"
 #include "nmv-i-profiler.h"
 #include "nmv-call-graph-node.h"
+#include "nmv-record-options.h"
 
 using nemiver::common::SafePtr;
 using nemiver::common::DynamicModule;
@@ -79,7 +80,8 @@ public:
     virtual void report (const UString &a_data_file) = 0;
 
     virtual void record (const UString &a_program_path,
-                         const std::vector<UString> &a_argv) = 0;
+                         const std::vector<UString> &a_argv,
+                         const RecordOptions &a_options) = 0;
 
     virtual void stop_recording () = 0;
 
diff --git a/src/profengine/nmv-perf-engine.cc b/src/profengine/nmv-perf-engine.cc
index df2bc07..8145430 100644
--- a/src/profengine/nmv-perf-engine.cc
+++ b/src/profengine/nmv-perf-engine.cc
@@ -25,7 +25,6 @@
 
 #include "nmv-perf-engine.h"
 #include "nmv-call-graph-node.h"
-#include "nmv-conf-keys.h"
 #include "common/nmv-proc-utils.h"
 #include "common/nmv-str-utils.h"
 #include <istream>
@@ -65,6 +64,7 @@ struct PerfEngine::Priv {
     sigc::signal<void, const UString&, const UString&> symbol_annotated_signal;
 
     bool is_using_prof_server;
+    unsigned request_id;
     Glib::RefPtr<Gio::DBus::Connection> server_connection;
     Glib::RefPtr<Gio::DBus::Proxy> proxy;
 
@@ -393,108 +393,67 @@ PerfEngine::attach_to_pid (int a_pid)
     Glib::Variant<int> pid_param = Glib::Variant<int>::create (a_pid);
     Glib::Variant<int> uid_param = Glib::Variant<int>::create (getuid ());
     Glib::Variant<int> gid_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 (uid_param);
     parameters.push_back (gid_param);
-    parameters.push_back (options_param);
 
     Glib::VariantContainerBase parameters_variant =
         Glib::VariantContainerBase::create_tuple (parameters);
+    Glib::VariantContainerBase response;
 
     m_priv->is_using_prof_server = true;
+    response = m_priv->proxy->call_sync ("AttachToPID", parameters_variant);
+
+    Glib::Variant<unsigned> request_id_param;
+    response.get_child (request_id_param);
+    m_priv->request_id = request_id_param.get ();
+
+    parameters.clear ();
+    parameters.push_back (request_id_param);
+    parameters_variant = Glib::VariantContainerBase::create_tuple (parameters);
     m_priv->proxy->call
-        ("AttachToPID",
+        ("RecordDoneSignal",
          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
-PerfEngine::record (const std::vector<UString> &a_argv)
+PerfEngine::record (const std::vector<UString> &a_argv,
+                    const RecordOptions &a_options)
 {
     SafePtr<char, DefaultRef, FreeUnref> tmp_filepath (tempnam(0, 0));
     THROW_IF_FAIL (tmp_filepath);
 
     THROW_IF_FAIL (m_priv);
     m_priv->record_filepath = tmp_filepath.get ();
-    bool do_callgraph_recording = true;
-    bool do_collect_without_buffering = false;
-    bool do_collect_raw_sample_records = false;
-    bool do_system_wide_collection = false;
-    bool do_sample_addresses = false;
-    bool do_sample_timestamps = false;
-
-    if (!m_priv->conf_mgr ().get_key_value (CONF_KEY_DO_CALLGRAPH_RECORDING,
-                                    do_callgraph_recording)) {
-        LOG_ERROR ("failed to get gconf key "
-                   << CONF_KEY_DO_CALLGRAPH_RECORDING);
-    }
-
-    if (!m_priv->conf_mgr ().get_key_value (CONF_KEY_COLLECT_WITHOUT_BUFFERING,
-                                    do_collect_without_buffering)) {
-        LOG_ERROR ("failed to get gconf key "
-                   << CONF_KEY_COLLECT_WITHOUT_BUFFERING);
-    }
-
-    if (!m_priv->conf_mgr ().get_key_value (CONF_KEY_COLLECT_RAW_SAMPLE_RECORDS,
-                                    do_collect_raw_sample_records)) {
-        LOG_ERROR ("failed to get gconf key "
-                   << CONF_KEY_COLLECT_RAW_SAMPLE_RECORDS);
-    }
-
-    if (!m_priv->conf_mgr ().get_key_value (CONF_KEY_SYSTEM_WIDE_COLLECTION,
-                                    do_system_wide_collection)) {
-        LOG_ERROR ("failed to get gconf key "
-                   << CONF_KEY_SYSTEM_WIDE_COLLECTION);
-    }
-
-    if (!m_priv->conf_mgr ().get_key_value (CONF_KEY_SAMPLE_ADDRESSES,
-                                    do_sample_addresses)) {
-        LOG_ERROR ("failed to get gconf key "
-                   << CONF_KEY_SAMPLE_ADDRESSES);
-    }
-
-    if (!m_priv->conf_mgr ().get_key_value (CONF_KEY_SAMPLE_TIMESTAMPS,
-                                    do_sample_timestamps)) {
-        LOG_ERROR ("failed to get gconf key "
-                   << CONF_KEY_SAMPLE_TIMESTAMPS);
-    }
 
     std::vector<UString> argv;
     argv.push_back ("perf");
     argv.push_back ("record");
 
-    if (do_callgraph_recording) {
+    if (a_options.do_callgraph_recording ()) {
         argv.push_back ("--call-graph");
     }
 
-    if (do_collect_without_buffering) {
+    if (a_options.do_collect_without_buffering ()) {
         argv.push_back ("--no-delay");
     }
 
-    if (do_collect_raw_sample_records) {
+    if (a_options.do_collect_raw_sample_records ()) {
         argv.push_back ("--raw-samples");
     }
 
-    if (do_system_wide_collection) {
+    if (a_options.do_system_wide_collection ()) {
         argv.push_back ("--all-cpus");
     }
 
-    if (do_sample_addresses) {
+    if (a_options.do_sample_addresses ()) {
         argv.push_back ("--data");
     }
 
-    if (do_sample_timestamps) {
+    if (a_options.do_sample_timestamps ()) {
         argv.push_back ("--timestamp");
     }
 
@@ -517,14 +476,15 @@ PerfEngine::record (const std::vector<UString> &a_argv)
 
 void
 PerfEngine::record (const UString &a_program_path,
-                    const std::vector<UString> &a_argv)
+                    const std::vector<UString> &a_argv,
+                    const RecordOptions &a_options)
 {
     std::vector<UString> argv;
     argv.push_back ("--");
     argv.push_back (a_program_path);
     argv.insert (argv.end (), a_argv.begin (), a_argv.end ());
 
-    record (argv);
+    record (argv, a_options);
 }
 
 void
diff --git a/src/profengine/nmv-perf-engine.h b/src/profengine/nmv-perf-engine.h
index e1616c9..25bfd15 100644
--- a/src/profengine/nmv-perf-engine.h
+++ b/src/profengine/nmv-perf-engine.h
@@ -44,9 +44,11 @@ public:
 
     void report (const UString &a_data_file);
     void attach_to_pid (int a_pid);
-    void record (const std::vector<UString> &a_argv);
+    void record (const std::vector<UString> &a_argv,
+                 const RecordOptions &a_options);
     void record (const UString &a_program_path,
-                 const std::vector<UString> &a_argv);
+                 const std::vector<UString> &a_argv,
+                 const RecordOptions &a_options);
     void stop_recording ();
     void annotate_symbol (const UString &a_symbol_name);
 
diff --git a/src/profengine/nmv-perf-server.cc b/src/profengine/nmv-perf-server.cc
index 8f737f0..5e2589c 100644
--- a/src/profengine/nmv-perf-server.cc
+++ b/src/profengine/nmv-perf-server.cc
@@ -28,6 +28,8 @@
 #include "common/nmv-exception.h"
 #include "common/nmv-ustring.h"
 #include "common/nmv-proc-utils.h"
+#include "nmv-record-options.h"
+#include "nmv-perf-engine.h"
 
 #include <glibmm.h>
 #include <giomm.h>
@@ -53,14 +55,68 @@ static const char *const NMV_DBUS_PROFILER_SERVER_INTROSPECTION_DATA =
     "        <arg type='i' name='uid' direction='in' />"
     "        <arg type='i' name='gid' direction='in' />"
 //    "        <arg type='u' name='cookie' direction='in' />"
-    "        <arg type='as' name='arguments' direction='in' />"
-    "        <arg type='s' name='data_filepath' direction='out' />"
+    "        <arg type='i' name='request_id' direction='out' />"
     "    </method>"
     "    <method name='DetachFromProcess'>"
+    "        <arg type='i' name='request_id' direction='in' />"
+    "    </method>"
+    "    <method name='RecordDoneSignal'>"
+    "        <arg type='i' name='request_id' direction='in' />"
+    "        <arg type='s' name='report_filepath' direction='out' />"
     "    </method>"
     "  </interface>"
     "</node>";
 
+class PerfRecordOptions : public RecordOptions {
+    bool callgraph_recording;
+    bool collect_without_buffering;
+    bool collect_raw_sample_records;
+    bool system_wide_collection;
+    bool sample_addresses;
+    bool sample_timestamps;
+
+public:
+    PerfRecordOptions () :
+        callgraph_recording (true),
+        collect_without_buffering (false),
+        collect_raw_sample_records (false),
+        system_wide_collection (false),
+        sample_addresses (false),
+        sample_timestamps (false)
+    {
+    }
+
+    bool do_callgraph_recording () const
+    {
+        return callgraph_recording;
+    }
+
+    bool do_collect_without_buffering () const
+    {
+        return collect_without_buffering;
+    }
+
+    bool do_collect_raw_sample_records () const
+    {
+        return collect_raw_sample_records;
+    }
+
+    bool do_system_wide_collection () const
+    {
+        return system_wide_collection;
+    }
+
+    bool do_sample_addresses () const
+    {
+        return sample_addresses;
+    }
+
+    bool do_sample_timestamps () const
+    {
+        return sample_timestamps;
+    }
+}; // end namespace PerfRecordOptions
+
 class PerfServer {
 
     PerfServer (const PerfServer &);
@@ -75,17 +131,27 @@ public:
     ~PerfServer ();
 }; // end namespace PerfServer
 
+struct RequestInfo {
+    int gid;
+    int uid;
+    SafePtr<PerfEngine> profiler;
+    Glib::RefPtr<Gio::DBus::MethodInvocation> invocation;
+
+    RequestInfo () :
+        profiler (new PerfEngine (0)),
+        invocation (0)
+    {
+    }
+};
+
 struct PerfServer::Priv {
 //    PolkitSubject *subject;
-    unsigned int bus_id;
-    unsigned int registration_id;
+    unsigned bus_id;
+    unsigned registration_id;
     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;
+    std::map<int, RequestInfo> request_map;
+    unsigned next_request_id;
 
     Priv () :
 //        subject (polkit_system_bus_name_new ("org.gnome.Nemiver")),
@@ -94,53 +160,11 @@ struct PerfServer::Priv {
         introspection_data (0),
         interface_vtable
             (sigc::mem_fun (*this, &PerfServer::Priv::on_new_request)),
-        perf_pid (0),
-        master_pty_fd (0),
-        perf_stdout_fd (0),
-        perf_stderr_fd (0)
+        next_request_id (0)
     {
         init ();
     }
 
-    bool
-    on_wait_for_record_to_exit (int a_uid, int a_gid,
-                                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;
-
-            NEMIVER_TRY;
-
-            Glib::Variant<Glib::ustring> perf_data =
-                Glib::Variant<Glib::ustring>::create (a_report_filepath);
-
-            Glib::VariantContainerBase response =
-                Glib::VariantContainerBase::create_tuple (perf_data);
-
-            chown (a_report_filepath.c_str (), a_uid, a_gid);
-
-            std::cout << "Saving report to " << a_report_filepath << std::endl;
-
-            a_invocation->return_value (response);
-
-            NEMIVER_CATCH_NOX;
-
-            return false;
-        }
-
-        return true;
-    }
-
     void
     on_new_request (const Glib::RefPtr<Gio::DBus::Connection> &a_connection,
                     const Glib::ustring&,
@@ -160,69 +184,56 @@ struct PerfServer::Priv {
             Glib::Variant<int> pid_param;
             Glib::Variant<int> uid_param;
             Glib::Variant<int> gid_param;
-            Glib::Variant<std::vector<Glib::ustring> > options_param;
             a_parameters.get_child (pid_param);
             a_parameters.get_child (uid_param, 1);
             a_parameters.get_child (gid_param, 2);
-            a_parameters.get_child (options_param, 3);
+
+            RequestInfo request;
 
             int pid = pid_param.get ();
-            int uid = uid_param.get ();
-            int gid = gid_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);
+            request.uid = uid_param.get ();
+            request.gid = gid_param.get ();
+
+            THROW_IF_FAIL (!request_map.count (pid));
 
             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 ());
-
-            std::cout << "Launching perf with pid: " << pid << std::endl;
-
-            bool is_launched =
-                common::launch_program (argv,
-                                        perf_pid,
-                                        master_pty_fd,
-                                        perf_stdout_fd,
-                                        perf_stderr_fd);
-
-            THROW_IF_FAIL (is_launched);
-
-            std::cout << "Perf started" << std::endl;
-
-            Glib::RefPtr<Glib::MainContext> context =
-                Glib::MainContext::get_default ();
-            context->signal_idle ().connect
-                (sigc::bind<int, int,
-                            Glib::RefPtr<Gio::DBus::MethodInvocation>,
-                            Glib::ustring>
-                        (sigc::mem_fun (*this,
-                         &PerfServer::Priv::on_wait_for_record_to_exit),
-                 uid, gid,
-                 a_invocation,
-                 filepath.get ()));
+
+            request_map[pid] = request;
+            PerfRecordOptions options;
+
+            THROW_IF_FAIL (request.profiler);
+            request.profiler->record (argv, options);
+
+            Glib::Variant<unsigned> perf_data =
+                Glib::Variant<unsigned>::create (next_request_id++);
+
+            Glib::VariantContainerBase response;
+            response = Glib::VariantContainerBase::create_tuple (perf_data);
+            a_invocation->return_value (response);
+        }
+        else if (a_request_name == "RecordDoneSignal") {
+            Glib::Variant<unsigned> request_param;
+            a_parameters.get_child (request_param);
+
+            unsigned request_id = request_param.get ();
+            THROW_IF_FAIL (request_map.count (request_id));
+            request_map[request_id].invocation = a_invocation;
+            request_map[request_id].profiler->record_done_signal ().connect
+                (sigc::bind<unsigned> (sigc::mem_fun
+                    (*this, &PerfServer::Priv::on_record_done_signal),
+                     request_id));
         }
         else if (a_request_name == "DetachFromProcess") {
-            kill (perf_pid, SIGINT);
+            Glib::Variant<unsigned> request_param;
+            a_parameters.get_child (request_param);
+
+            unsigned request_id = request_param.get ();
+            THROW_IF_FAIL (request_map.count (request_id));
+
+            THROW_IF_FAIL (request_map[request_id].profiler);
+            request_map[request_id].profiler->stop_recording ();
 
             Glib::VariantContainerBase response;
             a_invocation->return_value (response);
@@ -238,6 +249,28 @@ struct PerfServer::Priv {
     }
 
     void
+    on_record_done_signal (const UString &a_report, unsigned a_request_id)
+    {
+        NEMIVER_TRY;
+
+        THROW_IF_FAIL (request_map.count (a_request_id));
+
+        Glib::Variant<Glib::ustring> perf_data =
+            Glib::Variant<Glib::ustring>::create (a_report);
+
+        Glib::VariantContainerBase response =
+            Glib::VariantContainerBase::create_tuple (perf_data);
+
+        chown (a_report.c_str (),
+               request_map[a_request_id].uid,
+               request_map[a_request_id].gid);
+
+        request_map[a_request_id].invocation->return_value (response);
+
+        NEMIVER_CATCH_NOX;
+    }
+
+    void
     init ()
     {
         introspection_data = Gio::DBus::NodeInfo::create_for_xml
@@ -253,7 +286,7 @@ struct PerfServer::Priv {
 
     void
     on_bus_acquired (const Glib::RefPtr<Gio::DBus::Connection> &a_connection,
-                    const Glib::ustring&)
+                     const Glib::ustring&)
     {
         NEMIVER_TRY;
 
diff --git a/src/profengine/nmv-record-options.h b/src/profengine/nmv-record-options.h
new file mode 100644
index 0000000..d089ad8
--- /dev/null
+++ b/src/profengine/nmv-record-options.h
@@ -0,0 +1,57 @@
+//Author: Fabien Parent
+/*
+ *This file is part of the Nemiver project
+ *
+ *Nemiver 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 2,
+ *or (at your option) any later version.
+ *
+ *Nemiver 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 Nemiver;
+ *see the file COPYING.
+ *If not, write to the Free Software Foundation,
+ *Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *See COPYRIGHT file copyright information.
+ */
+#ifndef __NMV_RECORD_OPTIONS_H__
+#define __NMV_RECORD_OPTIONS_H__
+
+#include "common/nmv-namespace.h"
+
+NEMIVER_BEGIN_NAMESPACE (nemiver)
+
+class RecordOptions {
+    RecordOptions (const RecordOptions&);
+    RecordOptions& operator= (const RecordOptions&);
+
+protected:
+    RecordOptions ()
+    {
+    }
+
+public:
+    virtual ~RecordOptions ()
+    {
+    }
+
+    virtual bool do_callgraph_recording () const = 0;
+    virtual bool do_collect_without_buffering () const = 0;
+    virtual bool do_collect_raw_sample_records () const = 0;
+    virtual bool do_system_wide_collection () const = 0;
+    virtual bool do_sample_addresses () const = 0;
+    virtual bool do_sample_timestamps () const = 0;
+}; // end namespace RecordOptions
+
+NEMIVER_END_NAMESPACE (nemiver)
+
+#endif /* __NMV_RECORD_OPTIONS_H__ */
+



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