[nemiver/profiler: 6/16] Start the profiler of a program from the UI
- From: Fabien Parent <fparent src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [nemiver/profiler: 6/16] Start the profiler of a program from the UI
- Date: Sun, 8 Jul 2012 14:28:42 +0000 (UTC)
commit fe60a5871b2179c358a91879790f1088c2f06266
Author: Fabien Parent <parent f gmail com>
Date: Sun Jun 17 10:00:37 2012 +0200
Start the profiler of a program from the UI
src/common/nmv-proc-utils.cc | 16 +-
src/common/nmv-proc-utils.h | 4 +-
src/persp/profperspective/menus/menus.xml | 2 +
src/persp/profperspective/nmv-prof-perspective.cc | 69 ++++
.../profperspective/nmv-run-program-dialog.cc | 303 ++++++++++++++++++
src/persp/profperspective/nmv-run-program-dialog.h | 69 ++++
src/persp/profperspective/ui/Makefile.am | 3 +-
src/persp/profperspective/ui/runprogramdialog.ui | 329 ++++++++++++++++++++
src/profengine/nmv-i-profiler.h | 8 +
src/profengine/nmv-perf-engine.cc | 66 ++++
src/profengine/nmv-perf-engine.h | 6 +-
11 files changed, 871 insertions(+), 4 deletions(-)
---
diff --git a/src/common/nmv-proc-utils.cc b/src/common/nmv-proc-utils.cc
index c6fc315..3f05c25 100644
--- a/src/common/nmv-proc-utils.cc
+++ b/src/common/nmv-proc-utils.cc
@@ -57,7 +57,8 @@ launch_program (const std::vector<UString> &a_args,
int &a_pid,
int &a_master_pty_fd,
int &a_stdout_fd,
- int &a_stderr_fd)
+ int &a_stderr_fd,
+ const std::vector<UString> &a_environments)
{
RETURN_VAL_IF_FAIL (!a_args.empty (), false);
@@ -145,6 +146,19 @@ launch_program (const std::vector<UString> &a_args,
const_cast<char*> (a_args[i].c_str ());
}
+ std::auto_ptr<char *> environments;
+ environments.reset (new char* [a_environments.size () + 1]);
+ memset (environments.get (), 0,
+ sizeof (char*) * (a_environments.size () + 1));
+ if (!environments.get ()) {
+ exit (-1);
+ }
+
+ for (i = 0; i < a_environments.size (); ++i) {
+ environments.get ()[i] =
+ const_cast<char*> (a_environments[i].c_str ());
+ }
+
execvp (args.get ()[0], args.get ());
exit (-1);
} else if (pid > 0) {
diff --git a/src/common/nmv-proc-utils.h b/src/common/nmv-proc-utils.h
index 6fd8497..6dc8091 100644
--- a/src/common/nmv-proc-utils.h
+++ b/src/common/nmv-proc-utils.h
@@ -36,7 +36,9 @@ bool NEMIVER_API launch_program (const std::vector<UString> &a_args,
int &a_pid,
int &a_master_pty_fd,
int &a_stdout_fd,
- int &a_stderr_fd);
+ int &a_stderr_fd,
+ const std::vector<UString> &a_environments
+ = std::vector<UString> ());
void NEMIVER_API attach_channel_to_loop_context_as_source
(Glib::IOCondition a_cond,
diff --git a/src/persp/profperspective/menus/menus.xml b/src/persp/profperspective/menus/menus.xml
index 940a2be..0714b73 100644
--- a/src/persp/profperspective/menus/menus.xml
+++ b/src/persp/profperspective/menus/menus.xml
@@ -3,6 +3,8 @@
<menubar name="MenuBar">
<menu action="FileMenuAction" name="FileMenu">
<placeholder name="FileMenuAdditions">
+ <menuitem action="RunExecutableAction"
+ name="RunExecutableItem"/>
<menuitem action="LoadReportMenuItemAction"
name="LoadReportMenuItem"/>
</placeholder>
diff --git a/src/persp/profperspective/nmv-prof-perspective.cc b/src/persp/profperspective/nmv-prof-perspective.cc
index 51e403c..a353921 100644
--- a/src/persp/profperspective/nmv-prof-perspective.cc
+++ b/src/persp/profperspective/nmv-prof-perspective.cc
@@ -28,7 +28,9 @@
#include "nmv-load-report-dialog.h"
#include "nmv-call-list.h"
#include "nmv-spinner-tool-item.h"
+#include "nmv-run-program-dialog.h"
#include "common/nmv-safe-ptr-utils.h"
+#include "common/nmv-str-utils.h"
#include <list>
#include <glib/gi18n.h>
@@ -97,9 +99,14 @@ public:
void init_body ();
void load_report_file ();
void load_report_file (const UString &a_report_file);
+ void run_executable ();
+ void run_executable (const UString &a_program_name,
+ const UString &a_arguments);
+ void on_run_executable_action ();
void on_load_report_file_action ();
void on_report_done_signal (CallGraphSafePtr a_call_graph);
+ void on_record_done_signal (const UString &a_report_file);
IProfilerSafePtr& profiler ();
@@ -252,6 +259,9 @@ ProfPerspective::init_signals ()
THROW_IF_FAIL (profiler ());
profiler ()->report_done_signal ().connect (sigc::mem_fun
(*this, &ProfPerspective::on_report_done_signal));
+
+ profiler ()->record_done_signal ().connect (sigc::mem_fun
+ (*this, &ProfPerspective::on_record_done_signal));
}
void
@@ -278,6 +288,17 @@ ProfPerspective::on_report_done_signal (CallGraphSafePtr a_call_graph)
}
void
+ProfPerspective::on_record_done_signal (const UString &a_report_path)
+{
+ NEMIVER_TRY
+
+ THROW_IF_FAIL (profiler ());
+ profiler ()->report (a_report_path);
+
+ NEMIVER_CATCH
+}
+
+void
ProfPerspective::init_actions ()
{
Gtk::StockID nil_stock_id ("");
@@ -285,6 +306,16 @@ ProfPerspective::init_actions ()
static ui_utils::ActionEntry s_default_action_entries [] = {
{
+ "RunExecutableAction",
+ nil_stock_id,
+ _("Run Executable..."),
+ _("Execute a program under the profiler"),
+ sigc::mem_fun (*this, &ProfPerspective::on_run_executable_action),
+ ui_utils::ActionEntry::DEFAULT,
+ "",
+ false
+ },
+ {
"LoadReportMenuItemAction",
nil_stock_id,
_("_Load Report File..."),
@@ -330,6 +361,34 @@ ProfPerspective::edit_workbench_menu ()
}
void
+ProfPerspective::run_executable ()
+{
+ RunProgramDialog dialog (plugin_path ());
+
+ int result = dialog.run ();
+ if (result != Gtk::RESPONSE_OK) {
+ return;
+ }
+
+ run_executable (dialog.program_name (), dialog.arguments ());
+}
+
+void
+ProfPerspective::run_executable (const UString &a_program_name,
+ const UString &a_arguments)
+{
+ std::vector<UString> argv = str_utils::split (a_arguments, " ");
+
+ THROW_IF_FAIL (!a_program_name.empty ());
+ THROW_IF_FAIL (profiler ());
+
+ profiler ()->record (a_program_name, argv);
+
+ THROW_IF_FAIL (throbber);
+ throbber->start ();
+}
+
+void
ProfPerspective::load_report_file (const UString &a_report_file)
{
THROW_IF_FAIL (!a_report_file.empty ());
@@ -365,6 +424,16 @@ ProfPerspective::on_load_report_file_action ()
NEMIVER_CATCH
}
+void
+ProfPerspective::on_run_executable_action ()
+{
+ NEMIVER_TRY
+
+ run_executable ();
+
+ NEMIVER_CATCH
+}
+
Gtk::Widget*
ProfPerspective::load_menu (const UString &/*a_filename*/, const UString &/*a_widget_name*/)
{
diff --git a/src/persp/profperspective/nmv-run-program-dialog.cc b/src/persp/profperspective/nmv-run-program-dialog.cc
new file mode 100644
index 0000000..562c330
--- /dev/null
+++ b/src/persp/profperspective/nmv-run-program-dialog.cc
@@ -0,0 +1,303 @@
+//Author: Dodji Seketeli
+/*
+ *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 "config.h"
+#include <vector>
+#include <iostream>
+#include <glib/gi18n.h>
+#include <gtkmm/dialog.h>
+#include <gtkmm/entry.h>
+#include <gtkmm/filechooserbutton.h>
+#include <gtkmm/stock.h>
+#include <gtkmm/treeview.h>
+#include <gtkmm/liststore.h>
+#include "common/nmv-exception.h"
+#include "common/nmv-env.h"
+#include "common/nmv-ustring.h"
+#include "nmv-run-program-dialog.h"
+#include "nmv-ui-utils.h"
+
+using namespace std;
+using namespace nemiver::common;
+
+namespace nemiver {
+
+struct EnvVarModelColumns : public Gtk::TreeModel::ColumnRecord
+{
+ // I tried using UString here, but it didn't want to compile... jmj
+ Gtk::TreeModelColumn<Glib::ustring> varname;
+ Gtk::TreeModelColumn<Glib::ustring> value;
+ EnvVarModelColumns() { add (varname); add (value); }
+};
+
+struct RunProgramDialog::Priv {
+private:
+ Priv ();
+
+public:
+ Gtk::FileChooserButton *fcbutton;
+ Gtk::Button *okbutton;
+ Gtk::TreeView* treeview_environment;
+ Gtk::Button* remove_button;
+ Gtk::Button* add_button;
+ EnvVarModelColumns env_columns;
+ Glib::RefPtr<Gtk::ListStore> model;
+ Gtk::Dialog &dialog;
+ Glib::RefPtr<Gtk::Builder> gtkbuilder;
+
+
+ Priv (Gtk::Dialog &a_dialog,
+ const Glib::RefPtr<Gtk::Builder> &a_gtkbuilder) :
+ fcbutton (0),
+ okbutton (0),
+ treeview_environment (0),
+ remove_button (0),
+ add_button (0),
+ model (Gtk::ListStore::create (env_columns)),
+ dialog (a_dialog),
+ gtkbuilder (a_gtkbuilder)
+ {
+ init ();
+ }
+
+ void init ()
+ {
+ okbutton =
+ ui_utils::get_widget_from_gtkbuilder<Gtk::Button>
+ (gtkbuilder, "executebutton");
+ THROW_IF_FAIL (okbutton);
+ okbutton->set_sensitive (false);
+
+ treeview_environment =
+ ui_utils::get_widget_from_gtkbuilder<Gtk::TreeView>
+ (gtkbuilder, "treeview_environment");
+
+ treeview_environment->set_model (model);
+
+ treeview_environment->append_column_editable
+ (_("Name"), env_columns.varname);
+
+ treeview_environment->append_column_editable
+ (_("Value"), env_columns.value);
+
+ add_button =
+ ui_utils::get_widget_from_gtkbuilder<Gtk::Button>
+ (gtkbuilder, "button_add_var");
+ THROW_IF_FAIL (add_button);
+
+ add_button->signal_clicked().connect(sigc::mem_fun(*this,
+ &RunProgramDialog::Priv::on_add_new_variable));
+
+ remove_button = ui_utils::get_widget_from_gtkbuilder<Gtk::Button>
+ (gtkbuilder, "button_remove_var");
+ THROW_IF_FAIL (remove_button);
+ remove_button->signal_clicked().connect(sigc::mem_fun(*this,
+ &RunProgramDialog::Priv::on_remove_variable));
+
+ // we need to disable / enable sensitivity of the
+ // "Remove variable" button based on whether a
+ // variable is selected in the treeview.
+ treeview_environment->get_selection ()->signal_changed ().connect
+ (sigc::mem_fun
+ (*this,
+ &RunProgramDialog::Priv::on_variable_selection_changed));
+
+ fcbutton =
+ ui_utils::get_widget_from_gtkbuilder<Gtk::FileChooserButton>
+ (gtkbuilder, "filechooserbutton");
+ THROW_IF_FAIL (fcbutton);
+ fcbutton->set_show_hidden (true);
+ fcbutton->signal_selection_changed ().connect (sigc::mem_fun
+ (*this, &Priv::on_file_selection_changed));
+
+ // activate the default action (execute) when pressing enter in the
+ // arguments text box
+ ui_utils::get_widget_from_gtkbuilder<Gtk::Entry>
+ (gtkbuilder, "argumentsentry")->set_activates_default ();
+ }
+
+ void on_add_new_variable ()
+ {
+ THROW_IF_FAIL(model);
+ THROW_IF_FAIL(treeview_environment);
+ Gtk::TreeModel::iterator treeiter = model->append ();
+ Gtk::TreeModel::Path path = model->get_path (treeiter);
+ // activate the first cell of the newly
+ // added row so that the user can start
+ // typing in the name and value of the variable
+ treeview_environment->set_cursor (path,
+ *treeview_environment->get_column (0), true);
+ }
+
+ void on_remove_variable ()
+ {
+ THROW_IF_FAIL(treeview_environment);
+ Gtk::TreeModel::iterator treeiter =
+ treeview_environment->get_selection ()->get_selected ();
+ if (treeiter)
+ {
+ model->erase(treeiter);
+ }
+ }
+
+ void on_variable_selection_changed ()
+ {
+ THROW_IF_FAIL (remove_button);
+ if (treeview_environment->get_selection ()->count_selected_rows ()) {
+ remove_button->set_sensitive();
+ } else {
+ remove_button->set_sensitive(false);
+ }
+ }
+
+ void on_activate_textentry ()
+ {
+ dialog.activate_default ();
+ }
+
+ void on_file_selection_changed ()
+ {
+ if (okbutton && fcbutton) {
+ if (Glib::file_test
+ (Glib::locale_from_utf8 (fcbutton->get_filename ()),
+ Glib::FILE_TEST_IS_EXECUTABLE)) {
+ okbutton->set_sensitive (true);
+ }
+ }
+ }
+};//end struct RunProgramDialog::Priv
+
+RunProgramDialog::RunProgramDialog (const UString &a_root_path) :
+ Dialog (a_root_path, "runprogramdialog.ui", "runprogramdialog")
+{
+ m_priv.reset (new Priv (widget (), gtkbuilder ()));
+ THROW_IF_FAIL (m_priv);
+
+ working_directory (Glib::filename_to_utf8 (Glib::get_current_dir ()));
+}
+
+RunProgramDialog::~RunProgramDialog ()
+{
+ LOG_D ("destroyed", "destructor-domain");
+}
+
+UString
+RunProgramDialog::program_name () const
+{
+ Gtk::FileChooserButton *chooser =
+ ui_utils::get_widget_from_gtkbuilder<Gtk::FileChooserButton>
+ (gtkbuilder (), "filechooserbutton");
+ return chooser->get_filename ();
+}
+
+void
+RunProgramDialog::program_name (const UString &a_name)
+{
+ THROW_IF_FAIL (m_priv);
+
+ Gtk::FileChooserButton *chooser =
+ ui_utils::get_widget_from_gtkbuilder<Gtk::FileChooserButton>
+ (gtkbuilder (), "filechooserbutton");
+ THROW_IF_FAIL (chooser);
+ chooser->set_filename (a_name);
+}
+
+UString
+RunProgramDialog::arguments () const
+{
+ Gtk::Entry *entry =
+ ui_utils::get_widget_from_gtkbuilder<Gtk::Entry> (gtkbuilder (),
+ "argumentsentry");
+ THROW_IF_FAIL (entry);
+ return entry->get_text ();
+}
+
+void
+RunProgramDialog::arguments (const UString &a_args)
+{
+ Gtk::Entry *entry =
+ ui_utils::get_widget_from_gtkbuilder<Gtk::Entry> (gtkbuilder (),
+ "argumentsentry");
+ THROW_IF_FAIL (entry);
+ entry->set_text (a_args);
+}
+
+UString
+RunProgramDialog::working_directory () const
+{
+ Gtk::FileChooserButton *chooser =
+ ui_utils::get_widget_from_gtkbuilder<Gtk::FileChooserButton>
+ (gtkbuilder (), "filechooserbutton_workingdir");
+ return chooser->get_filename ();
+}
+
+void
+RunProgramDialog::working_directory (const UString &a_dir)
+{
+ Gtk::FileChooserButton *chooser =
+ ui_utils::get_widget_from_gtkbuilder<Gtk::FileChooserButton>
+ (gtkbuilder (), "filechooserbutton_workingdir");
+ if (a_dir == "" || a_dir == ".") {
+ chooser->set_filename
+ (Glib::locale_to_utf8 (Glib::get_current_dir ()));
+ } else {
+ chooser->set_filename (a_dir);
+ }
+}
+
+map<UString, UString>
+RunProgramDialog::environment_variables () const
+{
+ THROW_IF_FAIL (m_priv);
+ THROW_IF_FAIL (m_priv->model);
+ map<UString, UString> env_vars;
+ for (Gtk::TreeModel::iterator iter = m_priv->model->children().begin ();
+ iter != m_priv->model->children().end();
+ ++iter) {
+ // for some reason I have to explicitly convert from Glib::ustring to
+ // UString here or it won't compile
+ env_vars[UString((*iter)[m_priv->env_columns.varname])] =
+ UString((*iter)[m_priv->env_columns.value]);
+ }
+ return env_vars;
+}
+
+void
+RunProgramDialog::environment_variables (const map<UString, UString> &vars)
+{
+ THROW_IF_FAIL (m_priv);
+ THROW_IF_FAIL (m_priv->model);
+ // clear out the old data so we can set the new data
+ m_priv->model->clear();
+ for (map<UString, UString>::const_iterator iter = vars.begin();
+ iter != vars.end();
+ ++iter) {
+ Gtk::TreeModel::iterator treeiter = m_priv->model->append();
+ (*treeiter)[m_priv->env_columns.varname] = iter->first;
+ (*treeiter)[m_priv->env_columns.value] = iter->second;
+ }
+}
+
+}//end namespace nemiver
+
diff --git a/src/persp/profperspective/nmv-run-program-dialog.h b/src/persp/profperspective/nmv-run-program-dialog.h
new file mode 100644
index 0000000..a72e001
--- /dev/null
+++ b/src/persp/profperspective/nmv-run-program-dialog.h
@@ -0,0 +1,69 @@
+//Author: Dodji Seketeli
+/*
+ *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_RUN_PROGRAM_DIALOG_H__
+#define __NMV_RUN_PROGRAM_DIALOG_H__
+
+#include <map>
+#include "common/nmv-safe-ptr-utils.h"
+#include "nmv-dialog.h"
+
+NEMIVER_BEGIN_NAMESPACE (nemiver)
+
+namespace common {
+class UString;
+}
+
+using nemiver::common::UString;
+using nemiver::common::SafePtr;
+
+class RunProgramDialog : public Dialog {
+
+ struct Priv;
+ SafePtr<Priv> m_priv;
+
+public:
+
+ RunProgramDialog (const UString &a_resource_root_path);
+
+ virtual ~RunProgramDialog ();
+
+ UString program_name () const;
+ void program_name (const UString &a_name);
+
+ UString arguments () const;
+ void arguments (const UString &a_args);
+
+ UString working_directory () const;
+ void working_directory (const UString &);
+
+ std::map<UString, UString> environment_variables () const;
+ void environment_variables (const std::map<UString, UString> &);
+
+};//end class nemiver
+
+NEMIVER_END_NAMESPACE (nemiver)
+
+#endif //__NMV_RUN_PROGRAM_DIALOG_H__
+
diff --git a/src/persp/profperspective/ui/Makefile.am b/src/persp/profperspective/ui/Makefile.am
index b7347c3..09c4985 100644
--- a/src/persp/profperspective/ui/Makefile.am
+++ b/src/persp/profperspective/ui/Makefile.am
@@ -1,5 +1,6 @@
PLUGIN_NAME=profperspective
-uifiles = loadreportdialog.ui
+uifiles = loadreportdialog.ui \
+runprogramdialog.ui
uidir = @NEMIVER_PLUGINS_DIR@/$(PLUGIN_NAME)/ui
ui_DATA = $(uifiles)
diff --git a/src/persp/profperspective/ui/runprogramdialog.ui b/src/persp/profperspective/ui/runprogramdialog.ui
new file mode 100644
index 0000000..22928ed
--- /dev/null
+++ b/src/persp/profperspective/ui/runprogramdialog.ui
@@ -0,0 +1,329 @@
+<?xml version="1.0"?>
+<interface>
+ <!-- interface-requires gtk+ 2.6 -->
+ <!-- interface-naming-policy toplevel-contextual -->
+ <object class="GtkDialog" id="runprogramdialog">
+ <property name="width_request">300</property>
+ <property name="title" translatable="yes">Choose a Program to Execute</property>
+ <property name="default_width">350</property>
+ <property name="default_height">400</property>
+ <property name="type_hint">dialog</property>
+ <child internal-child="vbox">
+ <object class="GtkVBox" id="dialog-vbox1">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkVBox" id="vbox1">
+ <property name="visible">True</property>
+ <property name="border_width">6</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkFrame" id="frame_program">
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkAlignment" id="alignment2">
+ <property name="visible">True</property>
+ <property name="left_padding">12</property>
+ <child>
+ <object class="GtkFileChooserButton" id="filechooserbutton">
+ <property name="visible">True</property>
+ <property name="title" translatable="yes">Choose an Executable</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label_program">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Program:</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame_arguments">
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkAlignment" id="alignment1">
+ <property name="visible">True</property>
+ <property name="left_padding">12</property>
+ <child>
+ <object class="GtkEntry" id="argumentsentry">
+ <property name="visible">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label_arguments">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Arguments:</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame_workingdir">
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkAlignment" id="alignment3">
+ <property name="visible">True</property>
+ <property name="left_padding">12</property>
+ <child>
+ <object class="GtkFileChooserButton" id="filechooserbutton_workingdir">
+ <property name="visible">True</property>
+ <property name="action">select-folder</property>
+ <property name="title" translatable="yes">Choose a Working Directory</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label_workingdir">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Working Directory:</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame_environment">
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkAlignment" id="alignment4">
+ <property name="visible">True</property>
+ <property name="left_padding">12</property>
+ <child>
+ <object class="GtkHBox" id="hbox2">
+ <property name="visible">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hscrollbar_policy">automatic</property>
+ <property name="vscrollbar_policy">automatic</property>
+ <property name="shadow_type">out</property>
+ <child>
+ <object class="GtkTreeView" id="treeview_environment">
+ <property name="visible">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVButtonBox" id="vbuttonbox1">
+ <property name="visible">True</property>
+ <property name="spacing">6</property>
+ <property name="layout_style">start</property>
+ <child>
+ <object class="GtkButton" id="button_add_var">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">False</property>
+ <child>
+ <object class="GtkAlignment" id="alignment6">
+ <property name="visible">True</property>
+ <property name="xscale">0</property>
+ <property name="yscale">0</property>
+ <child>
+ <object class="GtkHBox" id="hbox3">
+ <property name="visible">True</property>
+ <property name="spacing">2</property>
+ <child>
+ <object class="GtkImage" id="image4">
+ <property name="visible">True</property>
+ <property name="stock">gtk-add</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Add</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="button_remove_var">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">False</property>
+ <child>
+ <object class="GtkAlignment" id="alignment7">
+ <property name="visible">True</property>
+ <property name="xscale">0</property>
+ <property name="yscale">0</property>
+ <child>
+ <object class="GtkHBox" id="hbox4">
+ <property name="visible">True</property>
+ <property name="spacing">2</property>
+ <child>
+ <object class="GtkImage" id="image5">
+ <property name="visible">True</property>
+ <property name="stock">gtk-remove</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Remove</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label_environment">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Environment Variables:</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child internal-child="action_area">
+ <object class="GtkHButtonBox" id="dialog-action_area1">
+ <property name="visible">True</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="button2">
+ <property name="label">gtk-cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="receives_default">False</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="executebutton">
+ <property name="label">gtk-execute</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-6">button2</action-widget>
+ <action-widget response="-5">executebutton</action-widget>
+ </action-widgets>
+ </object>
+</interface>
diff --git a/src/profengine/nmv-i-profiler.h b/src/profengine/nmv-i-profiler.h
index 50d215b..6e44192 100644
--- a/src/profengine/nmv-i-profiler.h
+++ b/src/profengine/nmv-i-profiler.h
@@ -67,10 +67,18 @@ public:
/// @{
virtual sigc::signal<void, CallGraphSafePtr>
report_done_signal () const = 0;
+
+ virtual sigc::signal<void, const UString&> record_done_signal () const = 0;
/// @}
virtual void report (const UString &a_data_file) = 0;
+ virtual void record (const UString &a_program_path,
+ const std::vector<UString> &a_argv) = 0;
+
+// virtual void attach_to_pid () = 0;
+
+
};//end IProfiler
NEMIVER_END_NAMESPACE (nemiver)
diff --git a/src/profengine/nmv-perf-engine.cc b/src/profengine/nmv-perf-engine.cc
index 2022d77..8d79c66 100644
--- a/src/profengine/nmv-perf-engine.cc
+++ b/src/profengine/nmv-perf-engine.cc
@@ -30,12 +30,15 @@
#include <istream>
#include <stack>
#include <sys/wait.h>
+#include <cstdio>
NEMIVER_BEGIN_NAMESPACE (nemiver)
const char *const PERF_REPORT_PARSING_DOMAIN = "perf-report-parsing-domain";
using common::DynModIfaceSafePtr;
+using common::FreeUnref;
+using common::DefaultRef;
struct PerfEngine::Priv {
int perf_pid;
@@ -43,11 +46,13 @@ struct PerfEngine::Priv {
int perf_stdout_fd;
int perf_stderr_fd;
Glib::RefPtr<Glib::IOChannel> perf_stdout_channel;
+ UString record_filepath;
std::stack<CallGraphNodeSafePtr> call_stack;
CallGraphSafePtr call_graph;
sigc::signal<void, CallGraphSafePtr> report_done_signal;
+ sigc::signal<void, const UString&> record_done_signal;
Priv () :
perf_pid (0),
@@ -60,6 +65,30 @@ struct PerfEngine::Priv {
}
bool
+ on_wait_for_record_to_exit ()
+ {
+ NEMIVER_TRY
+
+ int status = 0;
+ pid_t pid = waitpid (perf_pid, &status, WNOHANG);
+ if (pid == perf_pid && WIFEXITED (status)) {
+ g_spawn_close_pid (perf_pid);
+ perf_pid = 0;
+ master_pty_fd = 0;
+ perf_stdout_fd = 0;
+ perf_stderr_fd = 0;
+
+ record_done_signal.emit (record_filepath);
+
+ return false;
+ }
+
+ NEMIVER_CATCH_NOX
+
+ return true;
+ }
+
+ bool
on_wait_for_report_to_exit ()
{
NEMIVER_TRY
@@ -221,6 +250,36 @@ PerfEngine::~PerfEngine ()
}
void
+PerfEngine::record (const UString &a_program_path,
+ const std::vector<UString> &a_argv)
+{
+ 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 ();
+
+ std::vector<UString> argv;
+ argv.push_back ("perf");
+ argv.push_back ("record");
+ argv.push_back ("--output");
+ argv.push_back (m_priv->record_filepath);
+ argv.push_back (a_program_path);
+ argv.insert (argv.end (), a_argv.begin (), a_argv.end ());
+
+ bool is_launched = common::launch_program (argv,
+ m_priv->perf_pid,
+ m_priv->master_pty_fd,
+ m_priv->perf_stdout_fd,
+ m_priv->perf_stderr_fd);
+ THROW_IF_FAIL (is_launched);
+
+ Glib::RefPtr<Glib::MainContext> context = Glib::MainContext::get_default ();
+ context->signal_idle ().connect (sigc::mem_fun
+ (m_priv.get (), &PerfEngine::Priv::on_wait_for_record_to_exit));
+}
+
+void
PerfEngine::report (const UString &a_data_file)
{
std::vector<UString> argv;
@@ -261,6 +320,13 @@ PerfEngine::report_done_signal () const
return m_priv->report_done_signal;
}
+sigc::signal<void, const UString&>
+PerfEngine::record_done_signal () const
+{
+ THROW_IF_FAIL (m_priv);
+ return m_priv->record_done_signal;
+}
+
//****************************
//</GDBEngine methods>
//****************************
diff --git a/src/profengine/nmv-perf-engine.h b/src/profengine/nmv-perf-engine.h
index 7076ab7..69a1eb0 100644
--- a/src/profengine/nmv-perf-engine.h
+++ b/src/profengine/nmv-perf-engine.h
@@ -44,8 +44,12 @@ public:
void report (const UString &a_data_file);
- sigc::signal<void, CallGraphSafePtr> report_done_signal () const;
+ void record (const UString &a_program_path,
+ const std::vector<UString> &a_argv);
+ sigc::signal<void, CallGraphSafePtr> report_done_signal () const;
+ sigc::signal<void> program_exited_signal () const;
+ sigc::signal<void, const UString&> record_done_signal () const;
}; // end namespace PerfEngine
NEMIVER_END_NAMESPACE (nemiver)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]