2003-06-21 01:42:46 +00:00
/* service_response_time_table.c
* service_response_time_table 2003 Ronnie Sahlberg
* Helper routines common to all service response time statistics
* tap .
*
2004-07-18 00:24:25 +00:00
* $ Id $
2003-06-21 01:42:46 +00:00
*
2006-05-21 05:12:17 +00:00
* Wireshark - Network traffic analyzer
* By Gerald Combs < gerald @ wireshark . org >
2003-06-21 01:42:46 +00:00
* Copyright 1998 Gerald Combs
2010-08-05 22:34:59 +00:00
*
2003-06-21 01:42:46 +00:00
* This program 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
* of the License , or ( at your option ) any later version .
2010-08-05 22:34:59 +00:00
*
2003-06-21 01:42:46 +00:00
* This program 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 .
2010-08-05 22:34:59 +00:00
*
2003-06-21 01:42:46 +00:00
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place - Suite 330 , Boston , MA 02111 - 1307 , USA .
*/
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
2008-04-13 03:32:24 +00:00
2003-06-21 01:42:46 +00:00
# include <gtk/gtk.h>
2010-08-30 19:14:54 +00:00
# include <stdio.h>
2008-04-13 03:32:24 +00:00
2003-06-21 01:42:46 +00:00
# include "epan/packet_info.h"
2008-04-13 03:32:24 +00:00
# include "../simple_dialog.h"
# include "gtk/service_response_time_table.h"
2008-05-17 23:01:28 +00:00
# include "gtk/filter_utils.h"
2008-04-13 03:32:24 +00:00
# include "gtk/gui_utils.h"
2010-10-03 16:09:25 +00:00
# include "gtk/utf8_entities.h"
2008-04-13 03:32:24 +00:00
2010-08-05 22:14:16 +00:00
# define NANOSECS_PER_SEC 1000000000
2009-10-01 09:04:23 +00:00
enum
2003-06-21 05:39:45 +00:00
{
2010-08-05 22:34:59 +00:00
INDEX_COLUMN ,
PROCEDURE_COLUMN ,
CALLS_COLUMN ,
MIN_SRT_COLUMN ,
MAX_SRT_COLUMN ,
AVG_SRT_COLUMN ,
N_COLUMNS
2009-10-01 09:04:23 +00:00
} ;
2003-06-21 05:39:45 +00:00
2003-09-05 10:26:44 +00:00
static void
srt_select_filter_cb ( GtkWidget * widget _U_ , gpointer callback_data , guint callback_action )
{
srt_stat_table * rst = ( srt_stat_table * ) callback_data ;
2007-11-28 03:04:09 +00:00
char * str = NULL ;
2009-10-01 09:04:23 +00:00
GtkTreeIter iter ;
GtkTreeModel * model ;
GtkTreeSelection * sel ;
int selection ;
2003-09-05 10:26:44 +00:00
if ( rst - > filter_string = = NULL ) {
return ;
}
2009-10-01 09:04:23 +00:00
sel = gtk_tree_view_get_selection ( GTK_TREE_VIEW ( rst - > table ) ) ;
if ( ! gtk_tree_selection_get_selected ( sel , & model , & iter ) )
return ;
gtk_tree_model_get ( model , & iter , INDEX_COLUMN , & selection , - 1 ) ;
2003-09-05 10:26:44 +00:00
if ( selection > = ( int ) rst - > num_procs ) {
2004-01-31 03:22:42 +00:00
simple_dialog ( ESD_TYPE_ERROR , ESD_BTN_OK , " No procedure selected " ) ;
2003-09-05 10:26:44 +00:00
return ;
}
2008-05-17 23:01:28 +00:00
str = g_strdup_printf ( " %s==%d " , rst - > filter_string , selection ) ;
2003-09-05 10:26:44 +00:00
2008-05-17 23:01:28 +00:00
apply_selected_filter ( callback_action , str ) ;
2003-09-05 10:26:44 +00:00
2007-11-28 03:04:09 +00:00
g_free ( str ) ;
2003-09-05 10:26:44 +00:00
}
2010-08-23 15:58:48 +00:00
static gboolean
2003-09-05 10:26:44 +00:00
srt_show_popup_menu_cb ( void * widg _U_ , GdkEvent * event , srt_stat_table * rst )
{
GdkEventButton * bevent = ( GdkEventButton * ) event ;
if ( event - > type = = GDK_BUTTON_PRESS & & bevent - > button = = 3 ) {
2010-08-05 22:34:59 +00:00
gtk_menu_popup ( GTK_MENU ( rst - > menu ) , NULL , NULL , NULL , NULL ,
2003-09-05 10:26:44 +00:00
bevent - > button , bevent - > time ) ;
}
return FALSE ;
}
2003-10-10 08:52:19 +00:00
2010-09-02 06:22:12 +00:00
/* Action callbacks */
2010-08-29 19:37:15 +00:00
static void
apply_as_selected_cb ( GtkWidget * widget , gpointer user_data )
{
srt_select_filter_cb ( widget , user_data , CALLBACK_MATCH ( ACTYPE_SELECTED , 0 ) ) ;
}
static void
apply_as_not_selected_cb ( GtkWidget * widget , gpointer user_data )
{
srt_select_filter_cb ( widget , user_data , CALLBACK_MATCH ( ACTYPE_NOT_SELECTED , 0 ) ) ;
}
static void
apply_as_and_selected_cb ( GtkWidget * widget , gpointer user_data )
{
srt_select_filter_cb ( widget , user_data , CALLBACK_MATCH ( ACTYPE_AND_SELECTED , 0 ) ) ;
}
static void
apply_as_or_selected_cb ( GtkWidget * widget , gpointer user_data )
{
srt_select_filter_cb ( widget , user_data , CALLBACK_MATCH ( ACTYPE_OR_SELECTED , 0 ) ) ;
}
static void
apply_as_and_not_selected_cb ( GtkWidget * widget , gpointer user_data )
{
srt_select_filter_cb ( widget , user_data , CALLBACK_MATCH ( ACTYPE_AND_NOT_SELECTED , 0 ) ) ;
}
static void
apply_as_or_not_selected_cb ( GtkWidget * widget , gpointer user_data )
{
srt_select_filter_cb ( widget , user_data , CALLBACK_MATCH ( ACTYPE_OR_NOT_SELECTED , 0 ) ) ;
}
2003-09-05 10:26:44 +00:00
2010-08-29 19:37:15 +00:00
static void
prep_as_selected_cb ( GtkWidget * widget , gpointer user_data )
{
srt_select_filter_cb ( widget , user_data , CALLBACK_PREPARE ( ACTYPE_SELECTED , 0 ) ) ;
}
static void
prep_as_not_selected_cb ( GtkWidget * widget , gpointer user_data )
{
srt_select_filter_cb ( widget , user_data , CALLBACK_PREPARE ( ACTYPE_NOT_SELECTED , 0 ) ) ;
}
static void
prep_as_and_selected_cb ( GtkWidget * widget , gpointer user_data )
{
srt_select_filter_cb ( widget , user_data , CALLBACK_PREPARE ( ACTYPE_AND_SELECTED , 0 ) ) ;
}
static void
prep_as_or_selected_cb ( GtkWidget * widget , gpointer user_data )
{
srt_select_filter_cb ( widget , user_data , CALLBACK_PREPARE ( ACTYPE_OR_SELECTED , 0 ) ) ;
}
static void
prep_as_and_not_selected_cb ( GtkWidget * widget , gpointer user_data )
{
srt_select_filter_cb ( widget , user_data , CALLBACK_PREPARE ( ACTYPE_AND_NOT_SELECTED , 0 ) ) ;
}
static void
prep_as_or_not_selected_cb ( GtkWidget * widget , gpointer user_data )
{
srt_select_filter_cb ( widget , user_data , CALLBACK_PREPARE ( ACTYPE_OR_NOT_SELECTED , 0 ) ) ;
}
static void
find_selected_cb ( GtkWidget * widget , gpointer user_data )
{
srt_select_filter_cb ( widget , user_data , CALLBACK_FIND_FRAME ( ACTYPE_SELECTED , 0 ) ) ;
}
static void
find_not_selected_cb ( GtkWidget * widget , gpointer user_data )
{
srt_select_filter_cb ( widget , user_data , CALLBACK_FIND_FRAME ( ACTYPE_NOT_SELECTED , 0 ) ) ;
}
static void
find_prev_selected_cb ( GtkWidget * widget , gpointer user_data )
{
srt_select_filter_cb ( widget , user_data , CALLBACK_FIND_PREVIOUS ( ACTYPE_SELECTED , 0 ) ) ;
}
static void
find_prev_not_selected_cb ( GtkWidget * widget , gpointer user_data )
{
srt_select_filter_cb ( widget , user_data , CALLBACK_FIND_PREVIOUS ( ACTYPE_NOT_SELECTED , 0 ) ) ;
}
static void
find_next_selected_cb ( GtkWidget * widget , gpointer user_data )
{
srt_select_filter_cb ( widget , user_data , CALLBACK_FIND_NEXT ( ACTYPE_SELECTED , 0 ) ) ;
}
static void
find_next_not_selected_cb ( GtkWidget * widget , gpointer user_data )
{
srt_select_filter_cb ( widget , user_data , CALLBACK_FIND_NEXT ( ACTYPE_NOT_SELECTED , 0 ) ) ;
}
static void
color_selected_cb ( GtkWidget * widget , gpointer user_data )
{
srt_select_filter_cb ( widget , user_data , CALLBACK_COLORIZE ( ACTYPE_SELECTED , 0 ) ) ;
}
static void
color_not_selected_cb ( GtkWidget * widget , gpointer user_data )
{
srt_select_filter_cb ( widget , user_data , CALLBACK_COLORIZE ( ACTYPE_SELECTED , 0 ) ) ;
}
static const char * ui_desc_service_resp_t_filter_popup =
" <ui> \n "
" <popup name='ServiceRespTFilterPopup'> \n "
" <menu action='/Apply as Filter'> \n "
" <menuitem action='/Apply as Filter/Selected'/> \n "
2010-10-03 16:09:25 +00:00
" <menuitem action='/Apply as Filter/ " UTF8_HORIZONTAL_ELLIPSIS " not Selected'/> \n "
" <menuitem action='/Apply as Filter/ " UTF8_HORIZONTAL_ELLIPSIS " and Selected'/> \n "
" <menuitem action='/Apply as Filter/ " UTF8_HORIZONTAL_ELLIPSIS " or Selected'/> \n "
" <menuitem action='/Apply as Filter/ " UTF8_HORIZONTAL_ELLIPSIS " and not Selected'/> \n "
" <menuitem action='/Apply as Filter/ " UTF8_HORIZONTAL_ELLIPSIS " or not Selected'/> \n "
2010-08-29 19:37:15 +00:00
" </menu> \n "
" <menu action='/Prepare a Filter'> \n "
" <menuitem action='/Prepare a Filter/Selected'/> \n "
2010-10-03 16:09:25 +00:00
" <menuitem action='/Prepare a Filter/ " UTF8_HORIZONTAL_ELLIPSIS " not Selected'/> \n "
" <menuitem action='/Prepare a Filter/ " UTF8_HORIZONTAL_ELLIPSIS " and Selected'/> \n "
" <menuitem action='/Prepare a Filter/ " UTF8_HORIZONTAL_ELLIPSIS " or Selected'/> \n "
" <menuitem action='/Prepare a Filter/ " UTF8_HORIZONTAL_ELLIPSIS " and not Selected'/> \n "
" <menuitem action='/Prepare a Filter/ " UTF8_HORIZONTAL_ELLIPSIS " or not Selected'/> \n "
2010-08-29 19:37:15 +00:00
" </menu> \n "
" <menu action='/Find Frame'> \n "
" <menu action='/Find Frame/Find Frame'> \n "
" <menuitem action='/Find Frame/Selected'/> \n "
" <menuitem action='/Find Frame/Not Selected'/> \n "
" </menu> \n "
" <menu action='/Find Frame/Find Next'> \n "
" <menuitem action='/Find Next/Selected'/> \n "
" <menuitem action='/Find Next/Not Selected'/> \n "
" </menu> \n "
" <menu action='/Find Frame/Find Previous'> \n "
" <menuitem action='/Find Previous/Selected'/> \n "
" <menuitem action='/Find Previous/Not Selected'/> \n "
" </menu> \n "
" </menu> \n "
" <menu action='/Colorize Procedure'> \n "
" <menuitem action='/Colorize Procedure/Selected'/> \n "
" <menuitem action='/Colorize Procedure/Not Selected'/> \n "
" </menu> \n "
" </popup> \n "
" </ui> \n " ;
2010-08-30 16:10:01 +00:00
/*
2010-08-29 19:37:15 +00:00
* GtkActionEntry
* typedef struct {
* const gchar * name ;
* const gchar * stock_id ;
* const gchar * label ;
* const gchar * accelerator ;
* const gchar * tooltip ;
* GCallback callback ;
* } GtkActionEntry ;
2010-08-30 16:10:01 +00:00
* const gchar * name ; The name of the action .
* const gchar * stock_id ; The stock id for the action , or the name of an icon from the icon theme .
* const gchar * label ; The label for the action . This field should typically be marked for translation ,
* see gtk_action_group_set_translation_domain ( ) .
* If label is NULL , the label of the stock item with id stock_id is used .
* const gchar * accelerator ; The accelerator for the action , in the format understood by gtk_accelerator_parse ( ) .
* const gchar * tooltip ; The tooltip for the action . This field should typically be marked for translation ,
* see gtk_action_group_set_translation_domain ( ) .
* GCallback callback ; The function to call when the action is activated .
2010-08-29 19:37:15 +00:00
*
*/
static const GtkActionEntry service_resp_t__popup_entries [ ] = {
2010-09-02 06:22:12 +00:00
{ " /Apply as Filter " , NULL , " Apply as Filter " , NULL , NULL , NULL } ,
{ " /Prepare a Filter " , NULL , " Prepare a Filter " , NULL , NULL , NULL } ,
{ " /Find Frame " , NULL , " Find Frame " , NULL , NULL , NULL } ,
{ " /Find Frame/Find Frame " , NULL , " Find Frame " , NULL , NULL , NULL } ,
{ " /Find Frame/Find Next " , NULL , " Find Next " , NULL , NULL , NULL } ,
{ " /Find Frame/Find Previous " , NULL , " Find Previous " , NULL , NULL , NULL } ,
{ " /Colorize Procedure " , NULL , " Colorize Procedure " , NULL , NULL , NULL } ,
{ " /Apply as Filter/Selected " , NULL , " Selected " , NULL , " Selected " , G_CALLBACK ( apply_as_selected_cb ) } ,
2010-10-03 16:09:25 +00:00
{ " /Apply as Filter/ " UTF8_HORIZONTAL_ELLIPSIS " not Selected " , NULL , UTF8_HORIZONTAL_ELLIPSIS " not Selected " , NULL , UTF8_HORIZONTAL_ELLIPSIS " not Selected " , G_CALLBACK ( apply_as_not_selected_cb ) } ,
{ " /Apply as Filter/ " UTF8_HORIZONTAL_ELLIPSIS " and Selected " , NULL , UTF8_HORIZONTAL_ELLIPSIS " and Selected " , NULL , UTF8_HORIZONTAL_ELLIPSIS " and Selected " , G_CALLBACK ( apply_as_and_selected_cb ) } ,
{ " /Apply as Filter/ " UTF8_HORIZONTAL_ELLIPSIS " or Selected " , NULL , UTF8_HORIZONTAL_ELLIPSIS " or Selected " , NULL , UTF8_HORIZONTAL_ELLIPSIS " or Selected " , G_CALLBACK ( apply_as_or_selected_cb ) } ,
{ " /Apply as Filter/ " UTF8_HORIZONTAL_ELLIPSIS " and not Selected " , NULL , UTF8_HORIZONTAL_ELLIPSIS " and not Selected " , NULL , UTF8_HORIZONTAL_ELLIPSIS " and not Selected " , G_CALLBACK ( apply_as_and_not_selected_cb ) } ,
{ " /Apply as Filter/ " UTF8_HORIZONTAL_ELLIPSIS " or not Selected " , NULL , UTF8_HORIZONTAL_ELLIPSIS " or not Selected " , NULL , UTF8_HORIZONTAL_ELLIPSIS " or not Selected " , G_CALLBACK ( apply_as_or_not_selected_cb ) } ,
2010-09-02 06:22:12 +00:00
{ " /Prepare a Filter/Selected " , NULL , " Selected " , NULL , " selcted " , G_CALLBACK ( prep_as_selected_cb ) } ,
2010-10-03 16:09:25 +00:00
{ " /Prepare a Filter/ " UTF8_HORIZONTAL_ELLIPSIS " not Selected " , NULL , UTF8_HORIZONTAL_ELLIPSIS " not Selected " , NULL , UTF8_HORIZONTAL_ELLIPSIS " not Selected " , G_CALLBACK ( prep_as_not_selected_cb ) } ,
{ " /Prepare a Filter/ " UTF8_HORIZONTAL_ELLIPSIS " and Selected " , NULL , UTF8_HORIZONTAL_ELLIPSIS " and Selected " , NULL , UTF8_HORIZONTAL_ELLIPSIS " and Selected " , G_CALLBACK ( prep_as_and_selected_cb ) } ,
{ " /Prepare a Filter/ " UTF8_HORIZONTAL_ELLIPSIS " or Selected " , NULL , UTF8_HORIZONTAL_ELLIPSIS " or Selected " , NULL , UTF8_HORIZONTAL_ELLIPSIS " or Selected " , G_CALLBACK ( prep_as_or_selected_cb ) } ,
{ " /Prepare a Filter/ " UTF8_HORIZONTAL_ELLIPSIS " and not Selected " , NULL , UTF8_HORIZONTAL_ELLIPSIS " and not Selected " , NULL , UTF8_HORIZONTAL_ELLIPSIS " and not Selected " , G_CALLBACK ( prep_as_and_not_selected_cb ) } ,
{ " /Prepare a Filter/ " UTF8_HORIZONTAL_ELLIPSIS " or not Selected " , NULL , UTF8_HORIZONTAL_ELLIPSIS " or not Selected " , NULL , UTF8_HORIZONTAL_ELLIPSIS " or not Selected " , G_CALLBACK ( prep_as_or_not_selected_cb ) } ,
2010-09-02 06:22:12 +00:00
{ " /Find Frame/Selected " , NULL , " Selected " , NULL , " Selected " , G_CALLBACK ( find_selected_cb ) } ,
{ " /Find Frame/Not Selected " , NULL , " Not Selected " , NULL , " Not Selected " , G_CALLBACK ( find_not_selected_cb ) } ,
{ " /Find Previous/Selected " , NULL , " Selected " , NULL , " Selected " , G_CALLBACK ( find_prev_selected_cb ) } ,
{ " /Find Previous/Not Selected " , NULL , " Not Selected " , NULL , " Not Selected " , G_CALLBACK ( find_prev_not_selected_cb ) } ,
{ " /Find Next/Selected " , NULL , " Selected " , NULL , " Selected " , G_CALLBACK ( find_next_selected_cb ) } ,
{ " /Find Next/Not Selected " , NULL , " Not Selected " , NULL , " Not Selected " , G_CALLBACK ( find_next_not_selected_cb ) } ,
{ " /Colorize Procedure/Selected " , NULL , " Selected " , NULL , " Selected " , G_CALLBACK ( color_selected_cb ) } ,
{ " /Colorize Procedure/Not Selected " , NULL , " Not Selected " , NULL , " Not Selected " , G_CALLBACK ( color_not_selected_cb ) } ,
2010-08-29 19:37:15 +00:00
} ;
2010-09-02 06:22:12 +00:00
2003-09-05 10:26:44 +00:00
static void
srt_create_popup_menu ( srt_stat_table * rst )
{
2010-08-29 19:37:15 +00:00
GtkUIManager * ui_manager ;
GtkActionGroup * action_group ;
GError * error = NULL ;
2010-08-30 16:10:01 +00:00
action_group = gtk_action_group_new ( " ServiceRespTFilterPopupActionGroup " ) ;
2010-08-30 19:14:54 +00:00
gtk_action_group_add_actions ( action_group , /* the action group */
service_resp_t__popup_entries , /* an array of action descriptions */
G_N_ELEMENTS ( service_resp_t__popup_entries ) , /* the number of entries */
rst ) ; /* data to pass to the action callbacks */
2010-08-29 19:37:15 +00:00
ui_manager = gtk_ui_manager_new ( ) ;
2010-08-30 16:10:01 +00:00
gtk_ui_manager_insert_action_group ( ui_manager ,
action_group ,
2010-08-29 19:37:15 +00:00
0 ) ; /* the position at which the group will be inserted */
2010-08-30 16:10:01 +00:00
gtk_ui_manager_add_ui_from_string ( ui_manager , ui_desc_service_resp_t_filter_popup , - 1 , & error ) ;
if ( error ! = NULL )
{
fprintf ( stderr , " Warning: building service responce time filter popup failed: %s \n " ,
error - > message ) ;
g_error_free ( error ) ;
error = NULL ;
}
2010-08-29 19:37:15 +00:00
rst - > menu = gtk_ui_manager_get_widget ( ui_manager , " /ServiceRespTFilterPopup " ) ;
g_signal_connect ( rst - > table , " button_press_event " , G_CALLBACK ( srt_show_popup_menu_cb ) , rst ) ;
2010-09-02 06:22:12 +00:00
2003-09-05 10:26:44 +00:00
}
2009-10-05 17:19:39 +00:00
/* ---------------- */
static void
srt_time_func ( GtkTreeViewColumn * column _U_ ,
2010-08-05 22:34:59 +00:00
GtkCellRenderer * renderer ,
GtkTreeModel * model ,
GtkTreeIter * iter ,
gpointer user_data )
{
2009-10-05 17:19:39 +00:00
gchar * str ;
nstime_t * data ;
2010-08-05 22:34:59 +00:00
/* The col to get data from is in userdata */
gint data_column = GPOINTER_TO_INT ( user_data ) ;
2009-10-05 17:19:39 +00:00
2010-08-05 22:34:59 +00:00
gtk_tree_model_get ( model , iter , data_column , & data , - 1 ) ;
if ( ! data ) {
g_object_set ( renderer , " text " , " " , NULL ) ;
return ;
2009-10-05 17:19:39 +00:00
}
2010-08-05 22:14:16 +00:00
str = g_strdup_printf ( " %3d.%06d " , ( int ) data - > secs , ( data - > nsecs + 500 ) / 1000 ) ;
2009-10-05 17:19:39 +00:00
g_object_set ( renderer , " text " , str , NULL ) ;
g_free ( str ) ;
}
static void
srt_avg_func ( GtkTreeViewColumn * column _U_ ,
2010-08-05 22:34:59 +00:00
GtkCellRenderer * renderer ,
GtkTreeModel * model ,
GtkTreeIter * iter ,
gpointer user_data )
{
gchar * str ;
guint64 td ;
gint data_column = GPOINTER_TO_INT ( user_data ) ;
2009-10-05 17:19:39 +00:00
2010-08-05 22:34:59 +00:00
gtk_tree_model_get ( model , iter , data_column , & td , - 1 ) ;
str = g_strdup_printf ( " %3d.%06d " ,
( int ) ( td / 1000000 ) , ( int ) ( td % 1000000 ) ) ;
g_object_set ( renderer , " text " , str , NULL ) ;
g_free ( str ) ;
2009-10-05 17:19:39 +00:00
}
static gint
srt_time_sort_func ( GtkTreeModel * model ,
2010-08-30 19:14:54 +00:00
GtkTreeIter * a ,
GtkTreeIter * b ,
gpointer user_data )
2009-10-05 17:19:39 +00:00
{
nstime_t * ns_a ;
nstime_t * ns_b ;
gint ret = 0 ;
gint data_column = GPOINTER_TO_INT ( user_data ) ;
2010-08-05 22:34:59 +00:00
gtk_tree_model_get ( model , a , data_column , & ns_a , - 1 ) ;
gtk_tree_model_get ( model , b , data_column , & ns_b , - 1 ) ;
2009-10-05 17:19:39 +00:00
if ( ns_a = = ns_b ) {
ret = 0 ;
2010-08-05 22:34:59 +00:00
}
2009-10-05 17:19:39 +00:00
else if ( ns_a = = NULL | | ns_b = = NULL ) {
ret = ( ns_a = = NULL ) ? - 1 : 1 ;
2010-08-05 22:34:59 +00:00
}
2009-10-05 17:19:39 +00:00
else {
ret = nstime_cmp ( ns_a , ns_b ) ;
}
return ret ;
}
2009-10-01 09:04:23 +00:00
/*
XXX Resizable columns are ugly when there ' s more than on table cf . SMB
*/
2003-06-21 01:42:46 +00:00
void
2005-06-24 01:32:42 +00:00
init_srt_table ( srt_stat_table * rst , int num_procs , GtkWidget * vbox , const char * filter_string )
2003-06-21 01:42:46 +00:00
{
2009-10-01 09:04:23 +00:00
int i ;
GtkListStore * store ;
GtkWidget * tree ;
GtkTreeViewColumn * column ;
GtkCellRenderer * renderer ;
GtkTreeSortable * sortable ;
GtkTreeSelection * sel ;
2005-08-05 20:59:08 +00:00
const char * default_titles [ ] = { " Index " , " Procedure " , " Calls " , " Min SRT " , " Max SRT " , " Avg SRT " } ;
2003-06-21 05:39:45 +00:00
2009-10-01 09:04:23 +00:00
/* Create the store */
store = gtk_list_store_new ( N_COLUMNS , /* Total number of columns */
2010-08-05 22:34:59 +00:00
G_TYPE_INT , /* Index */
G_TYPE_STRING , /* Procedure */
G_TYPE_UINT , /* Calls */
G_TYPE_POINTER , /* Min SRT */
G_TYPE_POINTER , /* Max SRT */
G_TYPE_UINT64 ) ; /* Avg SRT */
/* Create a view */
tree = gtk_tree_view_new_with_model ( GTK_TREE_MODEL ( store ) ) ;
rst - > table = GTK_TREE_VIEW ( tree ) ;
sortable = GTK_TREE_SORTABLE ( store ) ;
/* The view now holds a reference. We can get rid of our own reference */
2009-10-01 09:04:23 +00:00
g_object_unref ( G_OBJECT ( store ) ) ;
2003-06-21 01:42:46 +00:00
2003-09-05 10:26:44 +00:00
if ( filter_string ) {
rst - > filter_string = g_strdup ( filter_string ) ;
} else {
rst - > filter_string = NULL ;
}
2009-10-01 09:04:23 +00:00
for ( i = 0 ; i < N_COLUMNS ; i + + ) {
renderer = gtk_cell_renderer_text_new ( ) ;
if ( i ! = PROCEDURE_COLUMN ) {
/* right align numbers */
g_object_set ( G_OBJECT ( renderer ) , " xalign " , 1.0 , NULL ) ;
}
g_object_set ( renderer , " ypad " , 0 , NULL ) ;
2009-10-05 17:19:39 +00:00
switch ( i ) {
case MIN_SRT_COLUMN :
case MAX_SRT_COLUMN :
column = gtk_tree_view_column_new_with_attributes ( default_titles [ i ] , renderer , NULL ) ;
gtk_tree_view_column_set_cell_data_func ( column , renderer , srt_time_func , GINT_TO_POINTER ( i ) , NULL ) ;
gtk_tree_sortable_set_sort_func ( sortable , i , srt_time_sort_func , GINT_TO_POINTER ( i ) , NULL ) ;
break ;
case AVG_SRT_COLUMN :
column = gtk_tree_view_column_new_with_attributes ( default_titles [ i ] , renderer , NULL ) ;
gtk_tree_view_column_set_cell_data_func ( column , renderer , srt_avg_func , GINT_TO_POINTER ( i ) , NULL ) ;
break ;
default :
2010-08-05 22:34:59 +00:00
column = gtk_tree_view_column_new_with_attributes ( default_titles [ i ] , renderer , " text " ,
2009-10-05 17:19:39 +00:00
i , NULL ) ;
break ;
2010-08-05 22:34:59 +00:00
}
2009-10-05 17:19:39 +00:00
2009-10-01 09:04:23 +00:00
gtk_tree_view_column_set_sort_column_id ( column , i ) ;
gtk_tree_view_column_set_resizable ( column , TRUE ) ;
gtk_tree_view_append_column ( rst - > table , column ) ;
if ( i = = CALLS_COLUMN ) {
/* XXX revert order sort */
gtk_tree_view_column_clicked ( column ) ;
gtk_tree_view_column_clicked ( column ) ;
2003-06-21 06:45:49 +00:00
}
2003-06-21 05:39:45 +00:00
}
2009-10-01 09:04:23 +00:00
rst - > scrolled_window = scrolled_window_new ( NULL , NULL ) ;
gtk_scrolled_window_set_shadow_type ( GTK_SCROLLED_WINDOW ( rst - > scrolled_window ) ,
GTK_SHADOW_IN ) ;
gtk_container_add ( GTK_CONTAINER ( rst - > scrolled_window ) , GTK_WIDGET ( rst - > table ) ) ;
gtk_box_pack_start ( GTK_BOX ( vbox ) , rst - > scrolled_window , TRUE , TRUE , 0 ) ;
2003-06-21 01:42:46 +00:00
2010-08-05 22:34:59 +00:00
gtk_tree_view_set_reorderable ( rst - > table , FALSE ) ;
2009-10-01 09:04:23 +00:00
/* Now enable the sorting of each column */
gtk_tree_view_set_rules_hint ( rst - > table , TRUE ) ;
gtk_tree_view_set_headers_clickable ( rst - > table , TRUE ) ;
2003-06-21 05:39:45 +00:00
gtk_widget_show ( rst - > scrolled_window ) ;
2003-06-21 01:42:46 +00:00
rst - > num_procs = num_procs ;
rst - > procedures = g_malloc ( sizeof ( srt_procedure_t ) * num_procs ) ;
for ( i = 0 ; i < num_procs ; i + + ) {
2009-06-05 19:12:30 +00:00
time_stat_init ( & rst - > procedures [ i ] . stats ) ;
2009-10-01 09:04:23 +00:00
rst - > procedures [ i ] . index = 0 ;
rst - > procedures [ i ] . procedure = NULL ;
2003-06-21 01:42:46 +00:00
}
2003-09-05 10:26:44 +00:00
2009-10-01 09:04:23 +00:00
sel = gtk_tree_view_get_selection ( GTK_TREE_VIEW ( rst - > table ) ) ;
gtk_tree_selection_set_mode ( sel , GTK_SELECTION_SINGLE ) ;
2003-09-05 10:26:44 +00:00
/* create popup menu for this table */
if ( rst - > filter_string ) {
srt_create_popup_menu ( rst ) ;
}
2003-06-21 01:42:46 +00:00
}
void
2005-06-27 08:13:41 +00:00
init_srt_table_row ( srt_stat_table * rst , int index , const char * procedure )
2003-06-21 01:42:46 +00:00
{
2004-04-07 04:31:32 +00:00
/* we have discovered a new procedure. Extend the table accordingly */
if ( index > = rst - > num_procs ) {
int old_num_procs = rst - > num_procs ;
2009-10-01 09:04:23 +00:00
int i ;
2004-04-07 04:31:32 +00:00
rst - > num_procs = index + 1 ;
rst - > procedures = g_realloc ( rst - > procedures , sizeof ( srt_procedure_t ) * ( rst - > num_procs ) ) ;
for ( i = old_num_procs ; i < rst - > num_procs ; i + + ) {
2009-06-05 19:04:05 +00:00
time_stat_init ( & rst - > procedures [ i ] . stats ) ;
2009-10-01 09:04:23 +00:00
rst - > procedures [ i ] . index = i ;
rst - > procedures [ i ] . procedure = NULL ;
2004-04-07 04:31:32 +00:00
}
}
2009-10-01 09:04:23 +00:00
rst - > procedures [ index ] . index = index ;
rst - > procedures [ index ] . procedure = g_strdup ( procedure ) ;
2003-06-21 01:42:46 +00:00
}
void
2005-01-01 02:57:02 +00:00
add_srt_table_data ( srt_stat_table * rst , int index , const nstime_t * req_time , packet_info * pinfo )
2003-06-21 01:42:46 +00:00
{
srt_procedure_t * rp ;
2005-08-21 21:50:49 +00:00
nstime_t t , delta ;
2003-06-21 01:42:46 +00:00
2009-10-01 09:04:23 +00:00
g_assert ( index > = 0 & & index < rst - > num_procs ) ;
2003-06-21 01:42:46 +00:00
rp = & rst - > procedures [ index ] ;
2003-06-22 04:00:21 +00:00
2005-08-21 21:50:49 +00:00
/*
* If the count of calls for this procedure is currently zero , it ' s
* going to become non - zero , so add a row for it ( we don ' t want
* rows for procedures that have no calls - especially if the
* procedure has no calls because the index doesn ' t correspond
* to a procedure , but is an unused / reserved value ) .
*
* ( Yes , this means that the rows aren ' t in order by anything
* interesting . That ' s why we have the table sorted by a column . )
*/
2009-10-01 09:04:23 +00:00
2005-08-22 07:12:20 +00:00
if ( rp - > stats . num = = 0 ) {
2009-10-01 09:04:23 +00:00
GtkListStore * store = GTK_LIST_STORE ( gtk_tree_view_get_model ( rst - > table ) ) ;
gtk_list_store_append ( store , & rp - > iter ) ;
gtk_list_store_set ( store , & rp - > iter ,
INDEX_COLUMN , rp - > index ,
PROCEDURE_COLUMN , rp - > procedure ,
CALLS_COLUMN , rp - > stats . num ,
2009-10-05 17:19:39 +00:00
MIN_SRT_COLUMN , NULL ,
MAX_SRT_COLUMN , NULL ,
AVG_SRT_COLUMN , ( guint64 ) 0 ,
2009-10-01 09:04:23 +00:00
- 1 ) ;
2003-06-21 01:42:46 +00:00
}
2005-08-22 07:12:20 +00:00
/* calculate time delta between request and reply */
2005-08-24 21:31:56 +00:00
t = pinfo - > fd - > abs_ts ;
nstime_delta ( & delta , & t , req_time ) ;
2005-08-22 07:12:20 +00:00
time_stat_update ( & rp - > stats , & delta , pinfo ) ;
2003-06-21 01:42:46 +00:00
}
void
draw_srt_table_data ( srt_stat_table * rst )
{
2009-10-01 09:04:23 +00:00
int i ;
2003-06-21 01:42:46 +00:00
guint64 td ;
2009-10-01 09:04:23 +00:00
GtkListStore * store = GTK_LIST_STORE ( gtk_tree_view_get_model ( rst - > table ) ) ;
2003-06-21 01:42:46 +00:00
for ( i = 0 ; i < rst - > num_procs ; i + + ) {
2009-10-01 09:04:23 +00:00
/* ignore procedures with no calls (they don't have rows) */
2005-08-22 07:12:20 +00:00
if ( rst - > procedures [ i ] . stats . num = = 0 ) {
2005-08-21 21:50:49 +00:00
continue ;
}
2010-08-05 22:14:16 +00:00
/* Scale the average SRT in units of 1us and round to the nearest us.
tot . secs is a time_t which may be 32 or 64 bits ( or even floating )
2010-08-05 22:34:59 +00:00
depending uon the platform . After casting tot . secs to 64 bits , it
would take a capture with a duration of over 136 * years * to
overflow the secs portion of td . */
2010-08-05 22:14:16 +00:00
td = ( ( guint64 ) ( rst - > procedures [ i ] . stats . tot . secs ) ) * NANOSECS_PER_SEC + rst - > procedures [ i ] . stats . tot . nsecs ;
td = ( ( td / rst - > procedures [ i ] . stats . num ) + 500 ) / 1000 ;
2005-08-21 21:50:49 +00:00
2009-10-01 09:04:23 +00:00
gtk_list_store_set ( store , & rst - > procedures [ i ] . iter ,
CALLS_COLUMN , rst - > procedures [ i ] . stats . num ,
2009-10-05 17:19:39 +00:00
MIN_SRT_COLUMN , & rst - > procedures [ i ] . stats . min ,
MAX_SRT_COLUMN , & rst - > procedures [ i ] . stats . max ,
AVG_SRT_COLUMN , td ,
2009-10-01 09:04:23 +00:00
- 1 ) ;
2003-06-21 01:42:46 +00:00
}
}
void
reset_srt_table_data ( srt_stat_table * rst )
{
int i ;
2009-10-01 09:04:23 +00:00
GtkListStore * store ;
2003-06-21 01:42:46 +00:00
for ( i = 0 ; i < rst - > num_procs ; i + + ) {
2005-08-22 07:12:20 +00:00
time_stat_init ( & rst - > procedures [ i ] . stats ) ;
2003-06-21 01:42:46 +00:00
}
2009-10-01 09:04:23 +00:00
store = GTK_LIST_STORE ( gtk_tree_view_get_model ( rst - > table ) ) ;
gtk_list_store_clear ( store ) ;
2003-06-21 01:42:46 +00:00
}
void
free_srt_table_data ( srt_stat_table * rst )
{
2009-10-01 09:04:23 +00:00
int i ;
2003-06-21 01:42:46 +00:00
for ( i = 0 ; i < rst - > num_procs ; i + + ) {
2009-10-01 09:04:23 +00:00
g_free ( rst - > procedures [ i ] . procedure ) ;
rst - > procedures [ i ] . procedure = NULL ;
2003-06-21 01:42:46 +00:00
}
2003-09-05 10:26:44 +00:00
g_free ( rst - > filter_string ) ;
rst - > filter_string = NULL ;
2003-06-21 01:42:46 +00:00
g_free ( rst - > procedures ) ;
rst - > procedures = NULL ;
rst - > num_procs = 0 ;
}