#include <stdlib.h>
#include <string.h>
#include <glib.h>
+#include <bzlib.h>
#include "sfile.h"
typedef struct State State;
instruction.name = NULL;
instruction.kind = VALUE;
- instruction.u.string.value = 0x01;
switch (instruction.type)
{
gssize length,
GError **error);
+static void
+disaster (int status)
+{
+ const char *error;
+ switch (status)
+ {
+ case BZ_PARAM_ERROR:
+ error = "BZ_PARAM_ERROR";
+ break;
+
+ case BZ_MEM_ERROR:
+ error = "BZ_MEM_ERROR";
+ break;
+
+ case BZ_OUTBUFF_FULL:
+ error = "BZ_OUTBUFF_FULL";
+ break;
+
+ default:
+ error = "Unknown error";
+ break;
+ }
+
+ g_error ("Failed to compress file: %s\n", error);
+}
+
+#include <bzlib.h>
+
+static void
+bz2_compress (const guchar *input, int input_length,
+ guchar **output, int *output_length)
+{
+ size_t compressed_size;
+ guchar *compressed_data;
+ int status;
+
+ g_return_if_fail (input != NULL);
+
+ /* The bzip2 manual says:
+ *
+ * To guarantee that the compressed data will fit in its buffer,
+ * allocate an output buffer of size 1% larger than the uncompressed
+ * data, plus six hundred extra bytes.
+ */
+ compressed_size = (size_t)(1.02 * input_length + 600);
+ compressed_data = g_malloc (compressed_size);
+
+ status = BZ2_bzBuffToBuffCompress (compressed_data, &compressed_size,
+ (guchar *)input, input_length,
+ 9 /* block size */,
+ 0 /* verbosity */,
+ 0 /* workfactor */);
+
+ if (status != BZ_OK)
+ disaster (status);
+
+ if (output)
+ *output = compressed_data;
+ else
+ g_free (compressed_data);
+
+ if (output_length)
+ *output_length = compressed_size;
+}
+
gboolean
sfile_output_save (SFileOutput *sfile,
const char *filename,
GString *output;
int indent;
gboolean retval;
+ guchar *compressed;
+ size_t compressed_size;
g_return_val_if_fail (sfile != NULL, FALSE);
}
}
- /* FIXME: don't dump this to stdout */
+#if 0
g_print (output->str);
+#endif
+
+ /* FIMXE: bz2 compressing the output is probably
+ * interesting at some point. For now just make sure
+ * it works without actually using it.
+ */
+ bz2_compress (output->str, output->len,
+ &compressed, &compressed_size);
+
+ g_free (compressed);
/* FIXME, cut-and-paste the g_file_write() implementation
* as long as it isn't in glib
*/
retval = file_replace (filename, output->str, - 1, err);
-#if 0
- retval = TRUE;
-#endif
g_string_free (output, TRUE);
+
+
+
/* A copy of g_file_replace() because I don't want to depend on
* GLib HEAD
*/
g_free (tmp_filename);
return retval;
}
+
State state;
StackStash * stash;
+ GtkWidget * main_window;
+
GtkTreeView * object_view;
GtkTreeView * callers_view;
GtkTreeView * descendants_view;
int timeout_id;
int generating_profile;
-
+
gboolean profile_from_file; /* FIXME: This is a kludge. Figure out how
* to maintain the application model properly
*
label = g_strdup_printf ("Samples: %d", app->n_samples);
break;
}
-
+
gtk_label_set_label (GTK_LABEL (app->samples_label), label);
g_free (label);
gtk_widget_set_sensitive (GTK_WIDGET (app->start_button),
sensitive_start_button);
-
+
gtk_widget_set_sensitive (GTK_WIDGET (app->reset_button),
sensitive_reset_button);
-
+
gtk_widget_set_sensitive (GTK_WIDGET (app->object_view), sensitive_tree_views);
gtk_widget_set_sensitive (GTK_WIDGET (app->callers_view), sensitive_tree_views);
gtk_widget_set_sensitive (GTK_WIDGET (app->descendants_view), sensitive_tree_views);
Application *app = data;
GList *pids, *list;
int mypid = getpid();
-
+
pids = list_processes ();
-
+
for (list = pids; list != NULL; list = list->next)
{
int pid = GPOINTER_TO_INT (list->data);
-
+
if (pid == mypid)
continue;
Process *process;
SysprofStackTrace trace;
int i;
-
+
if (!generate_stack_trace (pid, &trace))
{
continue;
}
-
+
process = process_get_from_pid (pid);
#if 0
process_ensure_map (process, trace.pid,
(gulong)trace.addresses[i]);
#endif
-
+
g_print ("n addr: %d\n", trace.n_addresses);
for (i = 0; i < trace.n_addresses; ++i)
process_ensure_map (process, trace.pid,
stack_stash_add_trace (
app->stash, process,
(gulong *)trace.addresses, trace.n_addresses, 1);
-
+
app->n_samples++;
}
}
-
+
update_sensitivity (app);
g_list_free (pids);
-
+
return TRUE;
}
#endif
}
static void
-on_start_toggled (GtkToggleToolButton *tool_button, gpointer data)
+on_start_toggled (GtkWidget *widget, gpointer data)
{
Application *app = data;
- if (!gtk_toggle_tool_button_get_active (tool_button))
+ if (!gtk_toggle_tool_button_get_active (
+ GTK_TOGGLE_TOOL_BUTTON (app->start_button)))
return;
delete_data (app);
G_TYPE_DOUBLE,
G_TYPE_DOUBLE,
G_TYPE_POINTER);
-
+
objects = profile_get_objects (profile);
- g_print ("got %d objects\n", g_list_length (objects));
for (list = objects; list != NULL; list = list->next)
{
ProfileObject *object = list->data;
g_object_unref (G_OBJECT (list_store));
}
+
+ gtk_tree_view_columns_autosize (app->object_view);
}
static void
app->state = DISPLAYING;
-#if 0
- gtk_tree_view_columns_autosize (app->object_view);
- gtk_tree_view_columns_autosize (app->callers_view);
- gtk_tree_view_columns_autosize (app->descendants_view);
-#endif
-
update_sensitivity (app);
}
static void
-on_profile_toggled (gpointer widget, gpointer data)
+on_profile_toggled (GtkWidget *widget, gpointer data)
{
Application *app = data;
- if (gtk_toggle_tool_button_get_active (widget))
+ if (gtk_toggle_tool_button_get_active (GTK_TOGGLE_TOOL_BUTTON (app->profile_button)))
{
if (app->profile && !app->profile_from_file)
{
profile_free (app->profile);
app->profile = NULL;
}
-
+
ensure_profile (app);
}
}
update_sensitivity (app);
}
+static gboolean
+overwrite_file (GtkWindow *window,
+ const char *filename)
+{
+ GtkWidget *msgbox;
+ gchar *utf8_file_name;
+ AtkObject *obj;
+ gint ret;
+
+ utf8_file_name = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL);
+ msgbox = gtk_message_dialog_new (window,
+ (GtkDialogFlags)GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_QUESTION,
+ GTK_BUTTONS_NONE,
+ _("A file named \"%s\" already exists."),
+ utf8_file_name);
+ g_free (utf8_file_name);
+
+ gtk_message_dialog_format_secondary_text (
+ GTK_MESSAGE_DIALOG (msgbox),
+ _("Do you want to replace it with the one you are saving?"));
+
+ gtk_dialog_add_button (GTK_DIALOG (msgbox),
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
+
+ gtk_dialog_add_button (GTK_DIALOG (msgbox),
+ _("_Replace"), GTK_RESPONSE_YES);
+
+ gtk_dialog_set_default_response (GTK_DIALOG (msgbox),
+ GTK_RESPONSE_CANCEL);
+
+ obj = gtk_widget_get_accessible (msgbox);
+
+ if (GTK_IS_ACCESSIBLE (obj))
+ atk_object_set_name (obj, _("Question"));
+
+ ret = gtk_dialog_run (GTK_DIALOG (msgbox));
+ gtk_widget_destroy (msgbox);
+
+ return (ret == GTK_RESPONSE_YES);
+
+}
+
static void
on_save_as_clicked (gpointer widget, gpointer data)
{
- GError *err = NULL;
Application *app = data;
-
+ GtkWidget *dialog;
+
ensure_profile (app);
-
- /* FIXME */
- if (!profile_save (app->profile, "name.profile", &err))
- sorry (NULL, "Couldn't save: %s\n", err->message);
-#if 0
- sorry (NULL, "Saving profiles is not yet implemented.");
-#endif
+ dialog = gtk_file_chooser_dialog_new ("Save As",
+ GTK_WINDOW (app->main_window),
+ GTK_FILE_CHOOSER_ACTION_SAVE,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
+ NULL);
+
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
+ gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
+
+ retry:
+ if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
+ {
+ GError *err = NULL;
+ gchar *filename;
+
+ filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
+
+ if (g_file_test (filename, G_FILE_TEST_EXISTS) &&
+ !overwrite_file (GTK_WINDOW (app->main_window), filename))
+ {
+ g_free (filename);
+ goto retry;
+ }
+
+ if (!profile_save (app->profile, filename, &err))
+ {
+ sorry (app->main_window, "Could not save %s: %s",
+ filename, err->message);
+
+ g_free (filename);
+ goto retry;
+ }
+
+ g_free (filename);
+ }
- if (app)
- ;
- /* FIXME */
+ gtk_widget_destroy (dialog);
}
static void
on_open_clicked (gpointer widget, gpointer data)
{
-#if 0
- sorry (NULL, "Open is not implemented yet. (Fortunately, neither is saving),");
-#endif
Application *app = data;
- GError *err = NULL;
- Profile *profile = profile_load ("name.profile", &err);
- if (!profile)
- sorry (NULL, "Could not open: %s\n", err->message);
- else
+ Profile *profile = NULL;
+ GtkWidget *dialog;
+
+ dialog = gtk_file_chooser_dialog_new ("Open",
+ GTK_WINDOW (app->main_window),
+ GTK_FILE_CHOOSER_ACTION_OPEN,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
+ NULL);
+
+ gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
+
+ retry:
+ if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
{
- delete_data (app);
+ GError *err = NULL;
+ gchar *filename;
+
+ filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
+ profile = profile_load (filename, &err);
+
+ if (!profile)
+ {
+ sorry (app->main_window, "Could not open %s: %s",
+ filename, err->message);
+
+ g_free (filename);
+ goto retry;
+ }
+
+ g_free (filename);
+ }
+ gtk_widget_destroy (dialog);
+
+ if (profile)
+ {
+ delete_data (app);
+
app->state = DISPLAYING;
app->profile = profile;
app->profile_from_file = TRUE;
-
+
fill_main_list (app);
update_sensitivity (app);
{
restore_sort_state (app->descendants_view, sort_state);
}
+
+ gtk_tree_view_columns_autosize (app->descendants_view);
}
static void
{
restore_sort_state (app->callers_view, sort_state);
}
+
+ gtk_tree_view_columns_autosize (app->callers_view);
}
static void
build_gui (Application *app)
{
GladeXML *xml;
- GtkWidget *main_window;
GtkTreeSelection *selection;
GtkTreeViewColumn *col;
xml = glade_xml_new ("./sysprof.glade", NULL, NULL);
/* Main Window */
- main_window = glade_xml_get_widget (xml, "main_window");
+ app->main_window = glade_xml_get_widget (xml, "main_window");
- g_signal_connect (G_OBJECT (main_window), "delete_event",
+ g_signal_connect (G_OBJECT (app->main_window), "delete_event",
G_CALLBACK (on_delete), NULL);
-
- gtk_widget_show_all (main_window);
-
+
/* Menu items */
app->start_item = glade_xml_get_widget (xml, "start_item");
app->profile_item = glade_xml_get_widget (xml, "profile_item");
app->save_as_button = glade_xml_get_widget (xml, "save_as_button");
app->dummy_button = glade_xml_get_widget (xml, "dummy_button");
- gtk_widget_hide (app->dummy_button);
-
- gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (
- app->profile_button), FALSE);
+ gtk_toggle_tool_button_set_active (
+ GTK_TOGGLE_TOOL_BUTTON (app->profile_button), FALSE);
g_signal_connect (G_OBJECT (app->start_button), "toggled",
G_CALLBACK (on_start_toggled), app);
g_signal_connect (G_OBJECT (app->save_as_button), "clicked",
G_CALLBACK (on_save_as_clicked), app);
-
+
app->samples_label = glade_xml_get_widget (xml, "samples_label");
- gtk_widget_realize (GTK_WIDGET (main_window));
- set_sizes (GTK_WINDOW (main_window),
+ gtk_widget_realize (GTK_WIDGET (app->main_window));
+ set_sizes (GTK_WINDOW (app->main_window),
glade_xml_get_widget (xml, "hpaned"),
glade_xml_get_widget (xml, "vpaned"));
gtk_tree_view_column_set_expand (col, TRUE);
+ gtk_widget_grab_focus (GTK_WIDGET (app->object_view));
+ gtk_widget_show_all (app->main_window);
+ gtk_widget_hide (app->dummy_button);
+
/* Statusbar */
queue_show_samples (app);
}
fd_add_watch (app->input_fd, app);
fd_set_read_callback (app->input_fd, on_read);
-
+
#if 0
nice (-19);
g_timeout_add (10, on_timeout, app);
<child>
<widget class="GtkImageMenuItem" id="open_item">
<property name="visible">True</property>
- <property name="label">gtk-open</property>
- <property name="use_stock">True</property>
- <signal name="activate" handler="on_open_activate" last_modification_time="Thu, 04 Nov 2004 21:01:03 GMT"/>
+ <property name="label" translatable="yes">_Open...</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_open_item_activate" last_modification_time="Thu, 04 Nov 2004 21:01:03 GMT"/>
+ <accelerator key="o" modifiers="GDK_CONTROL_MASK" signal="activate"/>
+
+ <child internal-child="image">
+ <widget class="GtkImage" id="image28">
+ <property name="visible">True</property>
+ <property name="stock">gtk-open</property>
+ <property name="icon_size">1</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ </child>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="save_as_item">
<property name="visible">True</property>
- <property name="label">gtk-save-as</property>
- <property name="use_stock">True</property>
- <signal name="activate" handler="on_save_as1_activate" last_modification_time="Wed, 31 Dec 2003 20:44:40 GMT"/>
+ <property name="label" translatable="yes">Save _As...</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_Save _As..._activate" last_modification_time="Wed, 31 Dec 2003 20:44:40 GMT"/>
+ <accelerator key="s" modifiers="GDK_CONTROL_MASK | GDK_SHIFT_MASK" signal="activate"/>
+
+ <child internal-child="image">
+ <widget class="GtkImage" id="image29">
+ <property name="visible">True</property>
+ <property name="stock">gtk-save-as</property>
+ <property name="icon_size">1</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ </child>
</widget>
</child>
<signal name="activate" handler="on_start1_activate" last_modification_time="Thu, 04 Nov 2004 18:51:54 GMT"/>
<child internal-child="image">
- <widget class="GtkImage" id="image10">
+ <widget class="GtkImage" id="image30">
<property name="visible">True</property>
<property name="stock">gtk-media-play</property>
<property name="icon_size">1</property>
<signal name="activate" handler="on_profile1_activate" last_modification_time="Thu, 04 Nov 2004 18:51:54 GMT"/>
<child internal-child="image">
- <widget class="GtkImage" id="image11">
+ <widget class="GtkImage" id="image31">
<property name="visible">True</property>
<property name="stock">gtk-justify-left</property>
<property name="icon_size">1</property>
<signal name="activate" handler="on_reset_item_activate" last_modification_time="Fri, 05 Nov 2004 15:34:30 GMT"/>
<child internal-child="image">
- <widget class="GtkImage" id="image12">
+ <widget class="GtkImage" id="image32">
<property name="visible">True</property>
<property name="stock">gtk-clear</property>
<property name="icon_size">1</property>