2002-11-14 10:32:22 +00:00
|
|
|
/* io_stat.c
|
|
|
|
* io_stat 2002 Ronnie Sahlberg
|
|
|
|
*
|
2003-01-15 05:58:50 +00:00
|
|
|
* $Id: io_stat.c,v 1.16 2003/01/15 05:58:50 guy Exp $
|
2002-11-14 10:32:22 +00:00
|
|
|
*
|
|
|
|
* Ethereal - Network traffic analyzer
|
|
|
|
* By Gerald Combs <gerald@ethereal.com>
|
|
|
|
* Copyright 1998 Gerald Combs
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
* 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
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
#ifdef HAVE_SYS_TYPES_H
|
|
|
|
# include <sys/types.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <string.h>
|
2002-11-16 21:40:32 +00:00
|
|
|
|
|
|
|
#include <ctype.h>
|
|
|
|
|
2002-11-14 10:32:22 +00:00
|
|
|
#include <gtk/gtk.h>
|
|
|
|
#include "gtkglobals.h"
|
2002-11-29 11:37:33 +00:00
|
|
|
#include "epan/epan_dissect.h"
|
2002-11-14 10:32:22 +00:00
|
|
|
#include "epan/packet_info.h"
|
|
|
|
#include "../tap.h"
|
|
|
|
#include "../register.h"
|
|
|
|
#include "io_stat.h"
|
|
|
|
#include "simple_dialog.h"
|
|
|
|
#include "../globals.h"
|
|
|
|
#include "../color.h"
|
2002-11-15 10:55:19 +00:00
|
|
|
#include "compat_macros.h"
|
2002-11-14 10:32:22 +00:00
|
|
|
|
2002-12-16 21:18:37 +00:00
|
|
|
/* filter prefs dialog */
|
|
|
|
#include "filter_prefs.h"
|
|
|
|
/* filter prefs dialog */
|
|
|
|
|
2002-11-14 10:32:22 +00:00
|
|
|
void protect_thread_critical_region(void);
|
|
|
|
void unprotect_thread_critical_region(void);
|
|
|
|
|
|
|
|
#define MAX_GRAPHS 5
|
|
|
|
|
|
|
|
#define MAX_YSCALE 22
|
|
|
|
#define AUTO_MAX_YSCALE 0
|
|
|
|
static guint32 yscale_max[MAX_YSCALE] = {AUTO_MAX_YSCALE, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000, 50000, 100000, 200000, 500000, 1000000, 2000000, 5000000, 10000000, 20000000, 50000000};
|
|
|
|
|
|
|
|
#define MAX_PIXELS_PER_TICK 4
|
2002-11-16 11:45:58 +00:00
|
|
|
#define DEFAULT_PIXELS_PER_TICK 2
|
2002-11-14 10:32:22 +00:00
|
|
|
static guint32 pixels_per_tick[MAX_PIXELS_PER_TICK] = {1, 2, 5, 10};
|
|
|
|
|
2002-11-29 11:37:33 +00:00
|
|
|
#define MAX_COUNT_TYPES 3
|
|
|
|
#define COUNT_TYPE_ADVANCED 2
|
|
|
|
static char *max_count_types[MAX_COUNT_TYPES] = {"frames/tick", "bytes/tick", "advanced..."};
|
2002-11-16 11:45:58 +00:00
|
|
|
|
|
|
|
/* unit is in ms */
|
|
|
|
#define MAX_TICK_VALUES 4
|
|
|
|
#define DEFAULT_TICK_VALUE 2
|
|
|
|
static guint max_tick_values[MAX_TICK_VALUES] = { 10, 100, 1000, 10000 };
|
2002-11-14 10:32:22 +00:00
|
|
|
|
2002-11-29 11:37:33 +00:00
|
|
|
#define MAX_CALC_TYPES 5
|
|
|
|
#define CALC_TYPE_SUM 0
|
|
|
|
#define CALC_TYPE_COUNT 1
|
|
|
|
#define CALC_TYPE_MAX 2
|
|
|
|
#define CALC_TYPE_MIN 3
|
|
|
|
#define CALC_TYPE_AVG 4
|
|
|
|
static char *max_calc_types[MAX_CALC_TYPES] = {"SUM(*)", "COUNT(*)", "MAX(*)", "MIN(*)", "AVG(*)"};
|
2002-11-14 10:32:22 +00:00
|
|
|
|
|
|
|
|
|
|
|
typedef struct _io_stat_item_t {
|
|
|
|
struct _io_stat_item_t *next;
|
|
|
|
struct _io_stat_item_t *prev;
|
2002-11-16 11:45:58 +00:00
|
|
|
guint32 time; /* this is number of ms since start of capture */
|
2002-11-29 11:37:33 +00:00
|
|
|
guint32 frames; /* always calculated, will hold number of packets/frames*/
|
2002-11-14 10:32:22 +00:00
|
|
|
guint32 bytes;
|
2002-11-29 11:37:33 +00:00
|
|
|
gint32 int_max;
|
|
|
|
gint32 int_min;
|
|
|
|
gint32 int_tot;
|
|
|
|
nstime_t time_max;
|
|
|
|
nstime_t time_min;
|
|
|
|
nstime_t time_tot;
|
2002-11-14 10:32:22 +00:00
|
|
|
} io_stat_item_t;
|
|
|
|
|
2002-11-29 11:37:33 +00:00
|
|
|
typedef struct _io_stat_calc_type_t {
|
|
|
|
struct _io_stat_graph_t *gio;
|
|
|
|
int calc_type;
|
|
|
|
} io_stat_calc_type_t;
|
|
|
|
|
2002-11-14 10:32:22 +00:00
|
|
|
typedef struct _io_stat_graph_t {
|
|
|
|
struct _io_stat_t *io;
|
|
|
|
struct _io_stat_item_t *counts;
|
|
|
|
int display;
|
|
|
|
GtkWidget *display_button;
|
|
|
|
GtkWidget *color_button;
|
|
|
|
GtkWidget *filter_button;
|
2002-11-29 11:37:33 +00:00
|
|
|
GtkWidget *advanced_buttons;
|
|
|
|
int calc_type;
|
|
|
|
io_stat_calc_type_t calc_types[MAX_CALC_TYPES];
|
|
|
|
int hf_index;
|
|
|
|
GtkWidget *calc_field;
|
2002-11-14 10:32:22 +00:00
|
|
|
GdkColor color;
|
|
|
|
GdkGC *gc;
|
2003-01-11 11:10:33 +00:00
|
|
|
construct_args_t *args;
|
|
|
|
GtkWidget *filter_bt;
|
2002-11-14 10:32:22 +00:00
|
|
|
} io_stat_graph_t;
|
|
|
|
|
|
|
|
typedef struct _io_stat_yscale_t {
|
|
|
|
struct _io_stat_t *io;
|
|
|
|
int yscale;
|
|
|
|
} io_stat_yscale_t;
|
|
|
|
|
|
|
|
typedef struct _io_stat_pixels_per_tick_t {
|
|
|
|
struct _io_stat_t *io;
|
|
|
|
int pixels_per_tick;
|
|
|
|
} io_stat_pixels_per_tick_t;
|
|
|
|
|
|
|
|
typedef struct _io_stat_count_type_t {
|
|
|
|
struct _io_stat_t *io;
|
|
|
|
int count_type;
|
|
|
|
} io_stat_count_type_t;
|
|
|
|
|
2002-11-16 11:45:58 +00:00
|
|
|
typedef struct _io_stat_tick_interval_t {
|
|
|
|
struct _io_stat_t *io;
|
|
|
|
int interval;
|
|
|
|
} io_stat_tick_interval_t;
|
|
|
|
|
2002-11-17 11:43:40 +00:00
|
|
|
|
2002-11-14 10:32:22 +00:00
|
|
|
typedef struct _io_stat_t {
|
|
|
|
int needs_redraw;
|
2002-11-16 11:45:58 +00:00
|
|
|
gint32 interval; /* measurement interval in ms */
|
2002-11-17 11:43:40 +00:00
|
|
|
guint32 last_interval;
|
|
|
|
guint32 max_interval;
|
2002-11-16 11:45:58 +00:00
|
|
|
|
2002-11-14 10:32:22 +00:00
|
|
|
struct _io_stat_graph_t graphs[MAX_GRAPHS];
|
|
|
|
struct _io_stat_yscale_t yscale[MAX_YSCALE];
|
|
|
|
struct _io_stat_pixels_per_tick_t pixelspertick[MAX_PIXELS_PER_TICK];
|
|
|
|
struct _io_stat_count_type_t counttype[MAX_COUNT_TYPES];
|
2002-11-16 11:45:58 +00:00
|
|
|
struct _io_stat_tick_interval_t tick_val[MAX_TICK_VALUES];
|
2002-11-14 10:32:22 +00:00
|
|
|
GtkWidget *window;
|
|
|
|
GtkWidget *draw_area;
|
|
|
|
GdkPixmap *pixmap;
|
2002-11-17 11:43:40 +00:00
|
|
|
GtkAdjustment *scrollbar_adjustment;
|
|
|
|
GtkWidget *scrollbar;
|
2002-11-14 10:32:22 +00:00
|
|
|
int pixmap_width;
|
|
|
|
int pixmap_height;
|
|
|
|
int pixels_per_tick;
|
|
|
|
int max_y_units;
|
|
|
|
int count_type;
|
|
|
|
} io_stat_t;
|
|
|
|
|
2002-12-16 06:44:45 +00:00
|
|
|
#if GTK_MAJOR_VERSION < 2
|
|
|
|
GtkRcStyle *rc_style;
|
|
|
|
GdkColormap *colormap;
|
|
|
|
#endif
|
|
|
|
|
2002-11-14 10:32:22 +00:00
|
|
|
|
|
|
|
|
2002-11-29 11:37:33 +00:00
|
|
|
static void init_io_stat_window(io_stat_t *io);
|
2002-11-14 10:32:22 +00:00
|
|
|
|
|
|
|
/* Hash table to keep track of widget to io_stat_t mappings.
|
|
|
|
Did it this way since i could not find a clean way to associate private
|
|
|
|
data with a widget using the API */
|
|
|
|
static GHashTable *io_stat_widget_table=NULL;
|
|
|
|
static guint
|
|
|
|
io_stat_widget_hash(gconstpointer k)
|
|
|
|
{
|
|
|
|
guint32 frame = (guint32)k;
|
|
|
|
|
|
|
|
return frame;
|
|
|
|
}
|
|
|
|
static gint
|
|
|
|
io_stat_widget_equal(gconstpointer k1, gconstpointer k2)
|
|
|
|
{
|
|
|
|
guint32 frame1 = (guint32)k1;
|
|
|
|
guint32 frame2 = (guint32)k2;
|
|
|
|
|
|
|
|
return frame1==frame2;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
gtk_iostat_reset(void *g)
|
|
|
|
{
|
|
|
|
io_stat_graph_t *gio=g;
|
|
|
|
io_stat_item_t *it;
|
|
|
|
|
|
|
|
gio->io->needs_redraw=1;
|
|
|
|
|
|
|
|
while(gio->counts->next){
|
|
|
|
it=gio->counts->next;
|
|
|
|
gio->counts->next=it->next;
|
|
|
|
g_free(it);
|
|
|
|
}
|
|
|
|
|
|
|
|
gio->counts->prev=gio->counts;
|
|
|
|
gio->counts->next=NULL;
|
|
|
|
gio->counts->time=0;
|
|
|
|
gio->counts->frames=0;
|
|
|
|
gio->counts->bytes=0;
|
2002-11-29 11:37:33 +00:00
|
|
|
gio->counts->int_max=0;
|
|
|
|
gio->counts->int_min=0;
|
|
|
|
gio->counts->int_tot=0;
|
2002-11-14 10:32:22 +00:00
|
|
|
|
2002-11-17 11:43:40 +00:00
|
|
|
gio->io->last_interval=0xffffffff;
|
|
|
|
gio->io->max_interval=0;
|
2002-11-14 10:32:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2002-11-29 11:37:33 +00:00
|
|
|
gtk_iostat_packet(void *g, packet_info *pinfo, epan_dissect_t *edt, void *dummy _U_)
|
2002-11-14 10:32:22 +00:00
|
|
|
{
|
|
|
|
io_stat_graph_t *git=g;
|
|
|
|
io_stat_item_t *it;
|
2002-11-16 11:45:58 +00:00
|
|
|
nstime_t time_delta;
|
|
|
|
guint32 adjusted_time;
|
2002-11-14 10:32:22 +00:00
|
|
|
|
2002-11-29 11:37:33 +00:00
|
|
|
/* we sometimes get called when git is disabled.
|
|
|
|
this is a bug since the tap listener should be removed first */
|
|
|
|
if(!git->display){
|
|
|
|
return 0;
|
2002-11-14 10:32:22 +00:00
|
|
|
}
|
|
|
|
|
2002-11-29 11:37:33 +00:00
|
|
|
git->io->needs_redraw=1;
|
|
|
|
|
2002-11-14 10:32:22 +00:00
|
|
|
/* the prev item before the main one is always the last interval we saw packets for */
|
|
|
|
it=git->counts->prev;
|
|
|
|
|
|
|
|
/* XXX for the time being, just ignore all frames that are in the past.
|
|
|
|
should be fixed in the future but hopefully it is uncommon */
|
2002-11-29 11:37:33 +00:00
|
|
|
time_delta.secs=pinfo->fd->rel_secs;
|
|
|
|
time_delta.nsecs=pinfo->fd->rel_usecs*1000;
|
2002-11-16 11:45:58 +00:00
|
|
|
if(time_delta.nsecs<0){
|
|
|
|
time_delta.secs--;
|
|
|
|
time_delta.nsecs+=1000000000;
|
|
|
|
}
|
|
|
|
if(time_delta.secs<0){
|
2002-11-14 10:32:22 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
2002-11-16 11:45:58 +00:00
|
|
|
/* time since start of capture in ms */
|
|
|
|
adjusted_time=time_delta.secs*1000+time_delta.nsecs/1000000;
|
|
|
|
|
|
|
|
/* timestamps jumped backwards, just ignore the packet.
|
|
|
|
if this is common someone can fix this later */
|
|
|
|
if(adjusted_time<it->time){
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2002-11-14 10:32:22 +00:00
|
|
|
|
|
|
|
/* we have moved into a new interval, we need to create a new struct */
|
2002-11-16 11:45:58 +00:00
|
|
|
if(adjusted_time>=(it->time+git->io->interval)){
|
2002-11-14 10:32:22 +00:00
|
|
|
it->next=g_malloc(sizeof(io_stat_item_t));
|
|
|
|
it->next->prev=it;
|
|
|
|
it->next->next=NULL;
|
|
|
|
it=it->next;
|
|
|
|
git->counts->prev=it;
|
|
|
|
|
2002-11-16 11:45:58 +00:00
|
|
|
/* set time of new counter struct of adjusted_time rounded
|
|
|
|
to multiple of intervals */
|
|
|
|
it->time=(adjusted_time/git->io->interval)*git->io->interval;
|
2002-11-14 10:32:22 +00:00
|
|
|
it->frames=0;
|
|
|
|
it->bytes=0;
|
2002-11-29 11:37:33 +00:00
|
|
|
it->int_max=0;
|
|
|
|
it->int_min=0;
|
|
|
|
it->int_tot=0;
|
|
|
|
it->time_max.secs=0;
|
|
|
|
it->time_max.nsecs=0;
|
|
|
|
it->time_min.secs=0;
|
|
|
|
it->time_min.nsecs=0;
|
|
|
|
it->time_tot.secs=0;
|
|
|
|
it->time_tot.nsecs=0;
|
2002-11-17 11:43:40 +00:00
|
|
|
if(it->time>git->io->max_interval){
|
|
|
|
git->io->max_interval=it->time;
|
|
|
|
}
|
2002-11-14 10:32:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* it will now give us the current structure to use to store the data in */
|
2002-11-29 11:37:33 +00:00
|
|
|
|
|
|
|
if(git->io->count_type==COUNT_TYPE_ADVANCED){
|
|
|
|
GPtrArray *gp;
|
|
|
|
guint i;
|
|
|
|
|
|
|
|
gp=proto_get_finfo_ptr_array(edt->tree, git->hf_index);
|
|
|
|
if(!gp){
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(it->frames==0){
|
|
|
|
int new_int;
|
|
|
|
nstime_t *new_time;
|
|
|
|
|
|
|
|
switch(proto_registrar_get_ftype(git->hf_index)){
|
|
|
|
case FT_UINT8:
|
|
|
|
case FT_UINT16:
|
|
|
|
case FT_UINT24:
|
|
|
|
case FT_UINT32:
|
|
|
|
case FT_INT8:
|
|
|
|
case FT_INT16:
|
|
|
|
case FT_INT24:
|
|
|
|
case FT_INT32:
|
|
|
|
new_int=fvalue_get_integer(((field_info *)gp->pdata[0])->value);
|
|
|
|
it->int_max=new_int;
|
|
|
|
it->int_min=new_int;
|
|
|
|
it->int_tot=0;
|
|
|
|
break;
|
|
|
|
case FT_RELATIVE_TIME:
|
|
|
|
new_time=fvalue_get(((field_info *)gp->pdata[0])->value);
|
|
|
|
it->time_max.secs=new_time->secs;
|
|
|
|
it->time_max.nsecs=new_time->nsecs;
|
|
|
|
it->time_min.secs=new_time->secs;
|
|
|
|
it->time_min.nsecs=new_time->nsecs;
|
|
|
|
it->time_tot.secs=0;
|
|
|
|
it->time_tot.nsecs=0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for(i=0;i<gp->len;i++){
|
|
|
|
int new_int;
|
|
|
|
nstime_t *new_time;
|
|
|
|
|
|
|
|
switch(proto_registrar_get_ftype(git->hf_index)){
|
|
|
|
case FT_UINT8:
|
|
|
|
case FT_UINT16:
|
|
|
|
case FT_UINT24:
|
|
|
|
case FT_UINT32:
|
|
|
|
case FT_INT8:
|
|
|
|
case FT_INT16:
|
|
|
|
case FT_INT24:
|
|
|
|
case FT_INT32:
|
|
|
|
new_int=fvalue_get_integer(((field_info *)gp->pdata[i])->value);
|
|
|
|
|
|
|
|
if(new_int>it->int_max){
|
|
|
|
it->int_max=new_int;
|
|
|
|
}
|
|
|
|
if(new_int<it->int_min){
|
|
|
|
it->int_min=new_int;
|
|
|
|
}
|
|
|
|
it->int_tot+=new_int;
|
|
|
|
break;
|
|
|
|
case FT_RELATIVE_TIME:
|
|
|
|
new_time=fvalue_get(((field_info *)gp->pdata[0])->value);
|
|
|
|
|
|
|
|
if( (new_time->secs>it->time_max.secs)
|
|
|
|
||( (new_time->secs==it->time_max.secs)
|
|
|
|
&&(new_time->nsecs>it->time_max.nsecs))){
|
|
|
|
it->time_max.secs=new_time->secs;
|
|
|
|
it->time_max.nsecs=new_time->nsecs;
|
|
|
|
}
|
|
|
|
if( (new_time->secs<it->time_min.secs)
|
|
|
|
||( (new_time->secs==it->time_min.secs)
|
|
|
|
&&(new_time->nsecs<it->time_min.nsecs))){
|
|
|
|
it->time_min.secs=new_time->secs;
|
|
|
|
it->time_min.nsecs=new_time->nsecs;
|
|
|
|
}
|
|
|
|
it->time_tot.secs+=new_time->secs;
|
|
|
|
it->time_tot.nsecs+=new_time->nsecs;
|
|
|
|
if(it->time_tot.nsecs>=1000000000){
|
|
|
|
it->time_tot.nsecs-=1000000000;
|
|
|
|
it->time_tot.secs++;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-11-14 10:32:22 +00:00
|
|
|
it->frames++;
|
|
|
|
it->bytes+=pinfo->fd->pkt_len;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2002-11-29 11:37:33 +00:00
|
|
|
|
|
|
|
static guint32
|
|
|
|
get_it_value(io_stat_t *io, io_stat_item_t *it, int adv_type, int calc_type)
|
|
|
|
{
|
|
|
|
guint32 value=0;
|
|
|
|
|
|
|
|
switch(io->count_type){
|
|
|
|
case 0:
|
|
|
|
value=it->frames;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
value=it->bytes;
|
|
|
|
break;
|
|
|
|
case COUNT_TYPE_ADVANCED:
|
|
|
|
switch(adv_type){
|
|
|
|
case FT_UINT8:
|
|
|
|
case FT_UINT16:
|
|
|
|
case FT_UINT24:
|
|
|
|
case FT_UINT32:
|
|
|
|
case FT_INT8:
|
|
|
|
case FT_INT16:
|
|
|
|
case FT_INT24:
|
|
|
|
case FT_INT32:
|
|
|
|
switch(calc_type){
|
|
|
|
case CALC_TYPE_SUM:
|
|
|
|
value=it->int_tot;
|
|
|
|
break;
|
|
|
|
case CALC_TYPE_COUNT:
|
|
|
|
value=it->frames;
|
|
|
|
break;
|
|
|
|
case CALC_TYPE_MAX:
|
|
|
|
value=it->int_max;
|
|
|
|
break;
|
|
|
|
case CALC_TYPE_MIN:
|
|
|
|
value=it->int_min;
|
|
|
|
break;
|
|
|
|
case CALC_TYPE_AVG:
|
|
|
|
if(it->frames){
|
|
|
|
value=it->int_tot/it->frames;
|
|
|
|
} else {
|
|
|
|
value=0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2002-12-02 19:44:09 +00:00
|
|
|
break;
|
2002-11-29 11:37:33 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case FT_RELATIVE_TIME:
|
|
|
|
switch(calc_type){
|
|
|
|
case CALC_TYPE_COUNT:
|
|
|
|
value=it->frames;
|
|
|
|
break;
|
|
|
|
case CALC_TYPE_MAX:
|
|
|
|
value=it->time_max.secs*1000000+it->time_max.nsecs/1000;
|
|
|
|
break;
|
|
|
|
case CALC_TYPE_MIN:
|
|
|
|
value=it->time_min.secs*1000000+it->time_min.nsecs/1000;
|
|
|
|
break;
|
|
|
|
case CALC_TYPE_AVG:
|
|
|
|
if(it->frames){
|
|
|
|
#ifdef G_HAVE_UINT64
|
|
|
|
guint64 tmp;
|
|
|
|
#else
|
|
|
|
guint32 tmp;
|
|
|
|
#endif
|
|
|
|
tmp=it->time_tot.secs;
|
|
|
|
tmp=tmp*1000000+it->time_tot.nsecs/1000;
|
|
|
|
value=tmp/it->frames;
|
|
|
|
} else {
|
|
|
|
value=0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2002-12-02 19:44:09 +00:00
|
|
|
break;
|
2002-11-29 11:37:33 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2002-12-02 19:44:09 +00:00
|
|
|
break;
|
2002-11-29 11:37:33 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2002-12-02 19:44:09 +00:00
|
|
|
break;
|
2002-11-29 11:37:33 +00:00
|
|
|
}
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
2002-11-14 10:32:22 +00:00
|
|
|
static void
|
|
|
|
gtk_iostat_draw(void *g)
|
|
|
|
{
|
|
|
|
io_stat_graph_t *git=g;
|
|
|
|
io_stat_t *io;
|
|
|
|
io_stat_item_t *it;
|
2002-11-15 10:55:19 +00:00
|
|
|
int i;
|
2002-11-29 11:37:33 +00:00
|
|
|
guint32 value;
|
2002-11-16 11:45:58 +00:00
|
|
|
guint32 last_interval, first_interval, interval_delta, delta_multiplier;
|
|
|
|
gint32 current_interval;
|
2002-11-14 10:32:22 +00:00
|
|
|
guint32 max_y;
|
|
|
|
guint32 left_x_border;
|
|
|
|
guint32 right_x_border;
|
|
|
|
guint32 top_y_border;
|
|
|
|
guint32 bottom_y_border;
|
2002-11-15 10:55:19 +00:00
|
|
|
#if GTK_MAJOR_VERSION < 2
|
|
|
|
GdkFont *font;
|
|
|
|
#else
|
2002-11-15 22:21:15 +00:00
|
|
|
PangoLayout *layout;
|
2002-11-15 10:55:19 +00:00
|
|
|
#endif
|
2002-11-14 10:32:22 +00:00
|
|
|
guint32 label_width, label_height;
|
|
|
|
guint32 draw_width, draw_height;
|
|
|
|
char label_string[15];
|
|
|
|
|
|
|
|
io=git->io;
|
2002-11-15 10:55:19 +00:00
|
|
|
#if GTK_MAJOR_VERSION <2
|
|
|
|
font = io->draw_area->style->font;
|
|
|
|
#endif
|
2002-11-14 10:32:22 +00:00
|
|
|
|
|
|
|
if(!git->io->needs_redraw){
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
git->io->needs_redraw=0;
|
|
|
|
|
2002-11-17 11:43:40 +00:00
|
|
|
/* if we havent specified the last_interval via the gui,
|
|
|
|
then just pick the most recent one */
|
|
|
|
if(io->last_interval==0xffffffff){
|
|
|
|
last_interval=io->max_interval;
|
|
|
|
} else {
|
|
|
|
last_interval=io->last_interval;
|
2002-11-14 10:32:22 +00:00
|
|
|
}
|
|
|
|
|
2002-11-16 11:45:58 +00:00
|
|
|
|
2002-11-14 10:32:22 +00:00
|
|
|
if(io->max_y_units==AUTO_MAX_YSCALE){
|
|
|
|
guint32 max_value=0;
|
|
|
|
for(i=0;i<MAX_GRAPHS;i++){
|
2002-12-05 22:19:24 +00:00
|
|
|
int adv_type=0;
|
2002-11-29 11:37:33 +00:00
|
|
|
|
|
|
|
if( (!io->graphs[i].display) || (!io->graphs[i].counts) ){
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(io->count_type==COUNT_TYPE_ADVANCED){
|
|
|
|
adv_type=proto_registrar_get_ftype(io->graphs[i].hf_index);
|
|
|
|
}
|
|
|
|
|
2002-11-14 10:32:22 +00:00
|
|
|
for(it=io->graphs[i].counts;it;it=it->next){
|
2002-11-29 11:37:33 +00:00
|
|
|
value=get_it_value(io, it, adv_type, io->graphs[i].calc_type);
|
|
|
|
if(value>=max_value){
|
|
|
|
max_value=value;
|
2002-11-14 10:32:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
max_y=yscale_max[MAX_YSCALE-1];
|
|
|
|
for(i=MAX_YSCALE-1;i>0;i--){
|
|
|
|
if(max_value<yscale_max[i]){
|
|
|
|
max_y=yscale_max[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
max_y=io->max_y_units;
|
|
|
|
}
|
|
|
|
|
2002-11-16 11:45:58 +00:00
|
|
|
|
2002-11-14 10:32:22 +00:00
|
|
|
/* just assume that max_y will be the longest string */
|
|
|
|
sprintf(label_string,"%d", max_y);
|
2002-11-15 22:21:15 +00:00
|
|
|
#if GTK_MAJOR_VERSION < 2
|
|
|
|
label_width=gdk_string_width(font, label_string);
|
|
|
|
label_height=gdk_string_height(font, label_string);
|
|
|
|
#else
|
|
|
|
layout = gtk_widget_create_pango_layout(io->draw_area, label_string);
|
|
|
|
pango_layout_get_pixel_size(layout, &label_width, &label_height);
|
|
|
|
#endif
|
2002-11-14 10:32:22 +00:00
|
|
|
|
|
|
|
left_x_border=10;
|
|
|
|
right_x_border=label_width+20;
|
|
|
|
top_y_border=10;
|
|
|
|
bottom_y_border=label_height+20;
|
|
|
|
|
|
|
|
draw_width=io->pixmap_width-right_x_border-left_x_border;
|
|
|
|
draw_height=io->pixmap_height-top_y_border-bottom_y_border;
|
|
|
|
|
|
|
|
|
|
|
|
/* clear out old plot */
|
2002-11-15 22:21:15 +00:00
|
|
|
gdk_draw_rectangle(io->pixmap,
|
|
|
|
io->draw_area->style->white_gc,
|
|
|
|
TRUE,
|
|
|
|
0, 0,
|
|
|
|
io->draw_area->allocation.width,
|
|
|
|
io->draw_area->allocation.height);
|
2002-11-14 10:32:22 +00:00
|
|
|
|
|
|
|
/* plot the y-scale */
|
|
|
|
gdk_draw_line(io->pixmap, io->draw_area->style->black_gc,
|
|
|
|
io->pixmap_width-right_x_border+1,
|
|
|
|
top_y_border,
|
|
|
|
io->pixmap_width-right_x_border+1,
|
|
|
|
io->pixmap_height-bottom_y_border);
|
|
|
|
for(i=0;i<=10;i++){
|
|
|
|
int xwidth, lwidth;
|
|
|
|
|
|
|
|
xwidth=5;
|
|
|
|
if(!(i%5)){
|
|
|
|
xwidth=10;
|
|
|
|
}
|
|
|
|
gdk_draw_line(io->pixmap, io->draw_area->style->black_gc,
|
|
|
|
io->pixmap_width-right_x_border+1,
|
|
|
|
io->pixmap_height-bottom_y_border-draw_height*i/10,
|
|
|
|
io->pixmap_width-right_x_border+1+xwidth,
|
|
|
|
io->pixmap_height-bottom_y_border-draw_height*i/10);
|
|
|
|
sprintf(label_string,"%d", max_y*i/10);
|
2002-11-15 22:21:15 +00:00
|
|
|
#if GTK_MAJOR_VERSION < 2
|
|
|
|
lwidth=gdk_string_width(font, label_string);
|
|
|
|
gdk_draw_string(io->pixmap,
|
|
|
|
font,
|
|
|
|
io->draw_area->style->black_gc,
|
|
|
|
io->pixmap_width-right_x_border+15+label_width-lwidth,
|
|
|
|
io->pixmap_height-bottom_y_border-draw_height*i/10+label_height/2,
|
|
|
|
label_string);
|
|
|
|
#else
|
|
|
|
pango_layout_set_text(layout, label_string, -1);
|
|
|
|
pango_layout_get_pixel_size(layout, &lwidth, NULL);
|
|
|
|
gdk_draw_layout(io->pixmap,
|
|
|
|
io->draw_area->style->black_gc,
|
|
|
|
io->pixmap_width-right_x_border+15+label_width-lwidth,
|
|
|
|
io->pixmap_height-bottom_y_border-draw_height*i/10-label_height/2,
|
|
|
|
layout);
|
|
|
|
#endif
|
2002-11-14 10:32:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* plot the x-scale */
|
|
|
|
gdk_draw_line(io->pixmap, io->draw_area->style->black_gc, left_x_border, io->pixmap_height-bottom_y_border+1, io->pixmap_width-right_x_border+1, io->pixmap_height-bottom_y_border+1);
|
2002-11-16 11:45:58 +00:00
|
|
|
|
|
|
|
if((last_interval/io->interval)>draw_width/io->pixels_per_tick+1){
|
|
|
|
first_interval=(last_interval/io->interval)-draw_width/io->pixels_per_tick+1;
|
|
|
|
first_interval*=io->interval;
|
2002-11-14 10:32:22 +00:00
|
|
|
} else {
|
|
|
|
first_interval=0;
|
|
|
|
}
|
|
|
|
|
2002-11-16 11:45:58 +00:00
|
|
|
|
2002-11-14 10:32:22 +00:00
|
|
|
interval_delta=1;
|
|
|
|
delta_multiplier=5;
|
|
|
|
while(interval_delta<((last_interval-first_interval)/10)){
|
|
|
|
interval_delta*=delta_multiplier;
|
|
|
|
if(delta_multiplier==5){
|
|
|
|
delta_multiplier=2;
|
|
|
|
} else {
|
|
|
|
delta_multiplier=5;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-11-16 11:45:58 +00:00
|
|
|
for(current_interval=last_interval;current_interval>(gint32)first_interval;current_interval=current_interval-io->interval){
|
2002-11-14 10:32:22 +00:00
|
|
|
int x, xlen;
|
|
|
|
|
|
|
|
/* if pixels_per_tick is <5, only draw every 10 ticks */
|
2002-11-16 11:45:58 +00:00
|
|
|
if((io->pixels_per_tick<10) && (current_interval%(10*io->interval))){
|
2002-11-14 10:32:22 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(current_interval%interval_delta){
|
|
|
|
xlen=5;
|
|
|
|
} else {
|
|
|
|
xlen=10;
|
|
|
|
}
|
2002-11-16 11:45:58 +00:00
|
|
|
|
|
|
|
x=draw_width+left_x_border-((last_interval-current_interval)/io->interval)*io->pixels_per_tick;
|
2002-11-14 10:32:22 +00:00
|
|
|
gdk_draw_line(io->pixmap, io->draw_area->style->black_gc,
|
|
|
|
x-1-io->pixels_per_tick/2,
|
|
|
|
io->pixmap_height-bottom_y_border+1,
|
|
|
|
x-1-io->pixels_per_tick/2,
|
|
|
|
io->pixmap_height-bottom_y_border+xlen+1);
|
|
|
|
|
|
|
|
if(xlen==10){
|
|
|
|
int lwidth;
|
2002-11-16 11:45:58 +00:00
|
|
|
if(io->interval>=1000){
|
|
|
|
sprintf(label_string,"%d", current_interval/1000);
|
|
|
|
} else if(io->interval>=100){
|
|
|
|
sprintf(label_string,"%d.%1d", current_interval/1000,(current_interval/100)%10);
|
|
|
|
} else if(io->interval>=10){
|
|
|
|
sprintf(label_string,"%d.%2d", current_interval/1000,(current_interval/10)%100);
|
|
|
|
} else {
|
|
|
|
sprintf(label_string,"%d.%3d", current_interval/1000,current_interval%1000);
|
|
|
|
}
|
2002-11-15 22:21:15 +00:00
|
|
|
#if GTK_MAJOR_VERSION < 2
|
|
|
|
lwidth=gdk_string_width(font, label_string);
|
|
|
|
gdk_draw_string(io->pixmap,
|
|
|
|
font,
|
|
|
|
io->draw_area->style->black_gc,
|
|
|
|
x-1-io->pixels_per_tick/2-lwidth/2,
|
|
|
|
io->pixmap_height-bottom_y_border+15+label_height,
|
|
|
|
label_string);
|
|
|
|
#else
|
|
|
|
pango_layout_set_text(layout, label_string, -1);
|
|
|
|
pango_layout_get_pixel_size(layout, &lwidth, NULL);
|
|
|
|
gdk_draw_layout(io->pixmap,
|
|
|
|
io->draw_area->style->black_gc,
|
|
|
|
x-1-io->pixels_per_tick/2-lwidth/2,
|
|
|
|
io->pixmap_height-bottom_y_border+15,
|
|
|
|
layout);
|
|
|
|
#endif
|
2002-11-14 10:32:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2002-11-15 22:21:15 +00:00
|
|
|
#if GTK_MAJOR_VERSION >= 2
|
|
|
|
g_object_unref(G_OBJECT(layout));
|
|
|
|
#endif
|
2002-11-14 10:32:22 +00:00
|
|
|
|
2002-11-16 11:45:58 +00:00
|
|
|
|
2002-11-14 10:32:22 +00:00
|
|
|
/* loop over all items */
|
2002-11-15 10:55:19 +00:00
|
|
|
for(i=MAX_GRAPHS-1;i>=0;i--){
|
2002-12-05 22:19:24 +00:00
|
|
|
int adv_type=0;
|
2002-12-16 07:11:24 +00:00
|
|
|
int first_drawed=1;
|
2002-11-29 11:37:33 +00:00
|
|
|
|
2002-11-14 10:32:22 +00:00
|
|
|
if( (!io->graphs[i].display) || (!io->graphs[i].counts) ){
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2002-11-29 11:37:33 +00:00
|
|
|
if(io->count_type==COUNT_TYPE_ADVANCED){
|
|
|
|
adv_type=proto_registrar_get_ftype(io->graphs[i].hf_index);
|
|
|
|
}
|
|
|
|
|
2002-11-14 10:32:22 +00:00
|
|
|
/* loop over all intervals for the item */
|
|
|
|
for(it=io->graphs[i].counts;it;it=it->next){
|
|
|
|
guint32 startx,starty, nexty;
|
|
|
|
guint32 val=0;
|
|
|
|
guint32 next_val=0;
|
|
|
|
|
2002-11-17 11:43:40 +00:00
|
|
|
/* skip it if is outside the graph */
|
|
|
|
if(it->time<first_interval){
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if(it->time>last_interval){
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2002-11-29 11:37:33 +00:00
|
|
|
val=get_it_value(io, it, adv_type, io->graphs[i].calc_type);
|
|
|
|
if(it->next){
|
|
|
|
next_val=get_it_value(io, it->next, adv_type, io->graphs[i].calc_type);
|
2002-11-14 10:32:22 +00:00
|
|
|
}
|
|
|
|
|
2002-11-29 11:37:33 +00:00
|
|
|
|
2002-11-16 11:45:58 +00:00
|
|
|
startx=draw_width-1-io->pixels_per_tick*((last_interval-it->time)/io->interval+1);
|
2002-11-14 10:32:22 +00:00
|
|
|
if(val>max_y){
|
|
|
|
starty=0;
|
|
|
|
} else {
|
|
|
|
starty=draw_height-1-(val*draw_height)/max_y;
|
|
|
|
}
|
|
|
|
if(next_val>max_y){
|
|
|
|
nexty=0;
|
|
|
|
} else {
|
|
|
|
nexty=draw_height-1-(next_val*draw_height)/max_y;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* just skip intervals that ar all or partially outside
|
|
|
|
the draw_area */
|
|
|
|
if(startx <=0){
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2002-12-16 07:11:24 +00:00
|
|
|
|
|
|
|
/* the first seen data for this graph might be
|
|
|
|
* somewhere in the middle of the capture, make sure
|
|
|
|
* we start drawing a proper line at zero from the
|
|
|
|
* left edge of the graph up until the measurement
|
|
|
|
* point.
|
|
|
|
*/
|
|
|
|
if(first_drawed){
|
|
|
|
first_drawed=0;
|
|
|
|
gdk_draw_line(io->pixmap, io->graphs[i].gc, 10, draw_height-1+10, startx+10, draw_height-1+10);
|
|
|
|
gdk_draw_line(io->pixmap, io->graphs[i].gc, startx+10, draw_height-1+10, startx+10, starty+10);
|
|
|
|
}
|
|
|
|
|
2002-11-14 10:32:22 +00:00
|
|
|
gdk_draw_line(io->pixmap, io->graphs[i].gc, startx+10, starty+10, startx+io->pixels_per_tick-1+10, starty+10);
|
|
|
|
|
|
|
|
/* if there is no next measured interval but he have
|
|
|
|
not reached last_interval yet, just draw 0 for the
|
|
|
|
rest of the graph */
|
|
|
|
if( (!it->next) && (it->time!=last_interval) ){
|
|
|
|
gdk_draw_line(io->pixmap, io->graphs[i].gc, startx+io->pixels_per_tick-1+10, starty+10, startx+io->pixels_per_tick-1+10, draw_height-1+10);
|
|
|
|
gdk_draw_line(io->pixmap, io->graphs[i].gc, startx+io->pixels_per_tick-1+10, draw_height-1+10, draw_width-1+10, draw_height-1+10);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!it->next){
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* if there is data in next interval, connect to it */
|
|
|
|
if((it->time+io->interval)==it->next->time){
|
|
|
|
gdk_draw_line(io->pixmap, io->graphs[i].gc, startx+io->pixels_per_tick-1+10, starty+10, startx+io->pixels_per_tick-1+10, nexty+10);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* there is a gap until the next interval, we need to
|
|
|
|
draw a bit more to connect to it. */
|
|
|
|
if((it->time+io->interval)<it->next->time){
|
|
|
|
int nextx;
|
2002-11-16 11:45:58 +00:00
|
|
|
nextx=draw_width-1-io->pixels_per_tick*((last_interval-it->next->time)/io->interval+1);
|
2002-11-14 10:32:22 +00:00
|
|
|
gdk_draw_line(io->pixmap, io->graphs[i].gc, startx+io->pixels_per_tick-1+10, starty+10, startx+io->pixels_per_tick-1+10, draw_height-1+10);
|
|
|
|
gdk_draw_line(io->pixmap, io->graphs[i].gc, startx+io->pixels_per_tick-1+10, draw_height-1+10, nextx-1+10, draw_height-1+10);
|
|
|
|
gdk_draw_line(io->pixmap, io->graphs[i].gc, nextx-1+10, draw_height-1+10, nextx-1+10, nexty+10);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-11-15 10:55:19 +00:00
|
|
|
gdk_draw_pixmap(io->draw_area->window,
|
2002-11-14 10:32:22 +00:00
|
|
|
io->draw_area->style->fg_gc[GTK_WIDGET_STATE(io->draw_area)],
|
|
|
|
io->pixmap,
|
|
|
|
0, 0,
|
|
|
|
0, 0,
|
|
|
|
io->pixmap_width, io->pixmap_height);
|
2002-11-15 10:55:19 +00:00
|
|
|
|
2002-11-17 11:43:40 +00:00
|
|
|
|
|
|
|
/* update the scrollbar */
|
|
|
|
io->scrollbar_adjustment->upper=io->max_interval;
|
|
|
|
io->scrollbar_adjustment->step_increment=(last_interval-first_interval)/10;
|
|
|
|
io->scrollbar_adjustment->page_increment=(last_interval-first_interval);
|
|
|
|
if((last_interval-first_interval)*100 < io->max_interval){
|
|
|
|
io->scrollbar_adjustment->page_size=io->max_interval/100;
|
|
|
|
} else {
|
|
|
|
io->scrollbar_adjustment->page_size=(last_interval-first_interval);
|
|
|
|
}
|
|
|
|
io->scrollbar_adjustment->value=last_interval-io->scrollbar_adjustment->page_size;
|
|
|
|
gtk_adjustment_changed(io->scrollbar_adjustment);
|
|
|
|
gtk_adjustment_value_changed(io->scrollbar_adjustment);
|
2002-11-14 10:32:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
gtk_iostat_init(char *optarg _U_)
|
|
|
|
{
|
|
|
|
io_stat_t *io;
|
|
|
|
int i=0;
|
|
|
|
static color_t col[MAX_GRAPHS] = {
|
|
|
|
{0, 0x0000, 0x0000, 0x0000},
|
|
|
|
{0, 0xffff, 0x0000, 0x0000},
|
|
|
|
{0, 0x0000, 0xffff, 0x0000},
|
|
|
|
{0, 0x0000, 0x0000, 0xffff},
|
|
|
|
{0, 0xffff, 0x5000, 0xffff}
|
|
|
|
};
|
|
|
|
|
|
|
|
io=g_malloc(sizeof(io_stat_t));
|
|
|
|
io->needs_redraw=1;
|
2002-11-16 11:45:58 +00:00
|
|
|
io->interval=1000;
|
2002-11-14 10:32:22 +00:00
|
|
|
io->window=NULL;
|
|
|
|
io->draw_area=NULL;
|
|
|
|
io->pixmap=NULL;
|
2002-11-17 11:43:40 +00:00
|
|
|
io->scrollbar=NULL;
|
|
|
|
io->scrollbar_adjustment=NULL;
|
2002-11-14 10:32:22 +00:00
|
|
|
io->pixmap_width=500;
|
|
|
|
io->pixmap_height=200;
|
|
|
|
io->pixels_per_tick=5;
|
|
|
|
io->max_y_units=AUTO_MAX_YSCALE;
|
|
|
|
io->count_type=0;
|
2002-11-17 11:43:40 +00:00
|
|
|
io->last_interval=0xffffffff;
|
|
|
|
io->max_interval=0;
|
2002-11-14 10:32:22 +00:00
|
|
|
|
|
|
|
for(i=0;i<MAX_GRAPHS;i++){
|
|
|
|
io->graphs[i].counts=g_malloc(sizeof(io_stat_item_t));
|
|
|
|
io->graphs[i].counts->prev=io->graphs[i].counts;
|
|
|
|
io->graphs[i].counts->next=NULL;
|
|
|
|
io->graphs[i].counts->time=0;
|
|
|
|
io->graphs[i].counts->frames=0;
|
|
|
|
io->graphs[i].counts->bytes=0;
|
2002-11-29 11:37:33 +00:00
|
|
|
io->graphs[i].counts->int_max=0;
|
|
|
|
io->graphs[i].counts->int_min=0;
|
|
|
|
io->graphs[i].counts->int_tot=0;
|
2002-11-14 10:32:22 +00:00
|
|
|
io->graphs[i].gc=NULL;
|
|
|
|
io->graphs[i].color.pixel=col[i].pixel;
|
|
|
|
io->graphs[i].color.red=col[i].red;
|
|
|
|
io->graphs[i].color.green=col[i].green;
|
|
|
|
io->graphs[i].color.blue=col[i].blue;
|
|
|
|
io->graphs[i].display=i?0:1;
|
|
|
|
io->graphs[i].display_button=NULL;
|
|
|
|
io->graphs[i].color_button=NULL;
|
|
|
|
io->graphs[i].filter_button=NULL;
|
2002-11-29 11:37:33 +00:00
|
|
|
io->graphs[i].advanced_buttons=NULL;
|
2002-11-14 10:32:22 +00:00
|
|
|
io->graphs[i].io=io;
|
2003-01-11 11:10:33 +00:00
|
|
|
|
|
|
|
io->graphs[i].args=g_malloc(sizeof(construct_args_t));
|
|
|
|
io->graphs[i].args->title = NULL;
|
|
|
|
io->graphs[i].args->wants_apply_button=TRUE;
|
|
|
|
io->graphs[i].args->activate_on_ok=TRUE;
|
|
|
|
|
|
|
|
io->graphs[i].filter_bt=NULL;
|
2002-11-14 10:32:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(register_tap_listener("frame", &io->graphs[0], NULL, gtk_iostat_reset, gtk_iostat_packet, gtk_iostat_draw)){
|
|
|
|
g_free(io->graphs[0].counts);
|
|
|
|
io->graphs[0].counts=NULL;
|
|
|
|
io->graphs[0].display=0;
|
|
|
|
io->graphs[0].display_button=NULL;
|
|
|
|
io->graphs[0].filter_button=NULL;
|
2002-11-29 11:37:33 +00:00
|
|
|
io->graphs[0].advanced_buttons=NULL;
|
2002-11-14 10:32:22 +00:00
|
|
|
exit(10);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* build the GUI */
|
|
|
|
init_io_stat_window(io);
|
|
|
|
|
|
|
|
redissect_packets(&cfile);
|
|
|
|
io->needs_redraw=1;
|
|
|
|
gtk_iostat_draw(&io->graphs[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static gint
|
|
|
|
quit(GtkWidget *widget, GdkEventExpose *event _U_)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
io_stat_t *io;
|
|
|
|
|
|
|
|
io=g_hash_table_lookup(io_stat_widget_table, (void*)widget);
|
|
|
|
if(io){
|
|
|
|
g_hash_table_remove(io_stat_widget_table, (void*)widget);
|
|
|
|
}
|
|
|
|
|
|
|
|
for(i=0;i<MAX_GRAPHS;i++){
|
|
|
|
io_stat_item_t *it;
|
|
|
|
protect_thread_critical_region();
|
|
|
|
remove_tap_listener(&io->graphs[i]);
|
|
|
|
while((it=io->graphs[i].counts)){
|
|
|
|
io->graphs[i].counts=io->graphs[i].counts->next;
|
|
|
|
g_free(it);
|
|
|
|
}
|
|
|
|
unprotect_thread_critical_region();
|
2003-01-11 11:10:33 +00:00
|
|
|
|
|
|
|
free(io->graphs[i].args->title);
|
|
|
|
io->graphs[i].args->title=NULL;
|
|
|
|
|
|
|
|
g_free(io->graphs[i].args);
|
|
|
|
io->graphs[i].args=NULL;
|
2002-11-14 10:32:22 +00:00
|
|
|
}
|
|
|
|
g_free(io);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* create a new backing pixmap of the appropriate size */
|
|
|
|
static gint
|
|
|
|
configure_event(GtkWidget *widget, GdkEventConfigure *event _U_)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
io_stat_t *io;
|
|
|
|
|
|
|
|
io=g_hash_table_lookup(io_stat_widget_table, (void*)widget);
|
|
|
|
if(!io){
|
|
|
|
exit(10);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(io->pixmap){
|
2002-11-15 10:55:19 +00:00
|
|
|
gdk_pixmap_unref(io->pixmap);
|
2002-11-14 10:32:22 +00:00
|
|
|
io->pixmap=NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
io->pixmap=gdk_pixmap_new(widget->window,
|
|
|
|
widget->allocation.width,
|
|
|
|
widget->allocation.height,
|
|
|
|
-1);
|
|
|
|
io->pixmap_width=widget->allocation.width;
|
|
|
|
io->pixmap_height=widget->allocation.height;
|
|
|
|
|
|
|
|
gdk_draw_rectangle(io->pixmap,
|
|
|
|
widget->style->white_gc,
|
|
|
|
TRUE,
|
|
|
|
0, 0,
|
|
|
|
widget->allocation.width,
|
|
|
|
widget->allocation.height);
|
|
|
|
|
|
|
|
/* set up the colors and the GC structs for this pixmap */
|
|
|
|
for(i=0;i<MAX_GRAPHS;i++){
|
|
|
|
io->graphs[i].gc=gdk_gc_new(io->pixmap);
|
2002-11-15 10:55:19 +00:00
|
|
|
#if GTK_MAJOR_VERSION < 2
|
2002-12-16 06:44:45 +00:00
|
|
|
colormap = gtk_widget_get_colormap (widget);
|
|
|
|
if (!gdk_color_alloc (colormap, &io->graphs[i].color)){
|
|
|
|
g_warning ("Couldn't allocate color");
|
|
|
|
}
|
|
|
|
|
2002-11-15 22:21:15 +00:00
|
|
|
gdk_gc_set_foreground(io->graphs[i].gc, &io->graphs[i].color);
|
2002-11-15 10:55:19 +00:00
|
|
|
#else
|
2002-11-14 10:32:22 +00:00
|
|
|
gdk_gc_set_rgb_fg_color(io->graphs[i].gc, &io->graphs[i].color);
|
2002-11-15 10:55:19 +00:00
|
|
|
#endif
|
|
|
|
|
2002-11-14 10:32:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
io->needs_redraw=1;
|
|
|
|
gtk_iostat_draw(&io->graphs[0]);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2002-11-17 11:43:40 +00:00
|
|
|
static gint
|
|
|
|
scrollbar_changed(GtkWidget *widget _U_, gpointer data)
|
|
|
|
{
|
|
|
|
io_stat_t *io=(io_stat_t *)data;
|
|
|
|
guint32 mi;
|
|
|
|
|
|
|
|
mi=io->scrollbar_adjustment->value+io->scrollbar_adjustment->page_size;
|
|
|
|
if(io->last_interval==mi){
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
if( (io->last_interval==0xffffffff)
|
|
|
|
&& (mi==io->max_interval) ){
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
io->last_interval=(mi/io->interval)*io->interval;
|
|
|
|
io->needs_redraw=1;
|
|
|
|
gtk_iostat_draw(&io->graphs[0]);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2002-11-14 10:32:22 +00:00
|
|
|
/* redraw the screen from the backing pixmap */
|
|
|
|
static gint
|
|
|
|
expose_event(GtkWidget *widget, GdkEventExpose *event)
|
|
|
|
{
|
|
|
|
io_stat_t *io;
|
|
|
|
io=g_hash_table_lookup(io_stat_widget_table, (void*)widget);
|
|
|
|
if(!io){
|
|
|
|
exit(10);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-11-15 10:55:19 +00:00
|
|
|
gdk_draw_pixmap(widget->window,
|
2002-11-14 10:32:22 +00:00
|
|
|
widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
|
|
|
|
io->pixmap,
|
|
|
|
event->area.x, event->area.y,
|
|
|
|
event->area.x, event->area.y,
|
|
|
|
event->area.width, event->area.height);
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-11-29 11:37:33 +00:00
|
|
|
static void
|
2002-11-14 10:32:22 +00:00
|
|
|
create_draw_area(io_stat_t *io, GtkWidget *box)
|
|
|
|
{
|
|
|
|
io->draw_area=gtk_drawing_area_new();
|
2002-11-15 10:55:19 +00:00
|
|
|
SIGNAL_CONNECT(io->draw_area, "destroy", quit, io);
|
2002-11-14 10:32:22 +00:00
|
|
|
g_hash_table_insert(io_stat_widget_table, (void*)io->draw_area, (void*)io);
|
|
|
|
|
2002-11-15 10:55:19 +00:00
|
|
|
WIDGET_SET_SIZE(io->draw_area, io->pixmap_width, io->pixmap_height);
|
2002-11-14 10:32:22 +00:00
|
|
|
|
|
|
|
/* signals needed to handle backing pixmap */
|
2002-11-15 10:55:19 +00:00
|
|
|
SIGNAL_CONNECT(io->draw_area, "expose_event", expose_event, NULL);
|
|
|
|
SIGNAL_CONNECT(io->draw_area, "configure_event", configure_event, io);
|
2002-11-14 10:32:22 +00:00
|
|
|
|
|
|
|
gtk_widget_show(io->draw_area);
|
|
|
|
gtk_box_pack_start(GTK_BOX(box), io->draw_area, TRUE, TRUE, 0);
|
2002-11-17 11:43:40 +00:00
|
|
|
|
|
|
|
/* create the associated scrollbar */
|
|
|
|
io->scrollbar_adjustment=(GtkAdjustment *)gtk_adjustment_new(0,0,0,0,0,0);
|
|
|
|
io->scrollbar=gtk_hscrollbar_new(io->scrollbar_adjustment);
|
|
|
|
gtk_widget_show(io->scrollbar);
|
|
|
|
gtk_box_pack_start(GTK_BOX(box), io->scrollbar, TRUE, TRUE, 0);
|
|
|
|
SIGNAL_CONNECT(io->scrollbar_adjustment, "value_changed", scrollbar_changed, io);
|
2002-11-14 10:32:22 +00:00
|
|
|
}
|
|
|
|
|
2002-11-16 11:45:58 +00:00
|
|
|
|
|
|
|
static void
|
|
|
|
tick_interval_select(GtkWidget *item _U_, gpointer key)
|
|
|
|
{
|
|
|
|
io_stat_tick_interval_t *tiv =(io_stat_tick_interval_t *)key;
|
|
|
|
|
|
|
|
tiv->io->interval=tiv->interval;
|
|
|
|
redissect_packets(&cfile);
|
|
|
|
tiv->io->needs_redraw=1;
|
|
|
|
gtk_iostat_draw(&tiv->io->graphs[0]);
|
|
|
|
}
|
|
|
|
|
2002-11-14 10:32:22 +00:00
|
|
|
static void
|
|
|
|
pixels_per_tick_select(GtkWidget *item _U_, gpointer key)
|
|
|
|
{
|
|
|
|
io_stat_pixels_per_tick_t *ppt=(io_stat_pixels_per_tick_t *)key;
|
|
|
|
|
|
|
|
ppt->io->pixels_per_tick=ppt->pixels_per_tick;
|
|
|
|
ppt->io->needs_redraw=1;
|
|
|
|
gtk_iostat_draw(&ppt->io->graphs[0]);
|
|
|
|
}
|
|
|
|
|
2002-11-29 11:37:33 +00:00
|
|
|
static void
|
2002-11-14 10:32:22 +00:00
|
|
|
create_pixels_per_tick_menu_items(io_stat_t *io, GtkWidget *menu)
|
|
|
|
{
|
|
|
|
char str[5];
|
|
|
|
GtkWidget *menu_item;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for(i=0;i<MAX_PIXELS_PER_TICK;i++){
|
|
|
|
sprintf(str,"%d", pixels_per_tick[i]);
|
|
|
|
menu_item=gtk_menu_item_new_with_label(str);
|
|
|
|
io->pixelspertick[i].io=io;
|
|
|
|
io->pixelspertick[i].pixels_per_tick=pixels_per_tick[i];
|
2002-11-15 10:55:19 +00:00
|
|
|
SIGNAL_CONNECT(menu_item, "activate", pixels_per_tick_select, &io->pixelspertick[i]);
|
2002-11-14 10:32:22 +00:00
|
|
|
gtk_widget_show(menu_item);
|
|
|
|
gtk_menu_append(GTK_MENU(menu), menu_item);
|
|
|
|
}
|
2002-11-16 11:45:58 +00:00
|
|
|
gtk_menu_set_active(GTK_MENU(menu), DEFAULT_PIXELS_PER_TICK);
|
2002-11-14 10:32:22 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
yscale_select(GtkWidget *item _U_, gpointer key)
|
|
|
|
{
|
|
|
|
io_stat_yscale_t *ys=(io_stat_yscale_t *)key;
|
|
|
|
|
|
|
|
ys->io->max_y_units=ys->yscale;
|
|
|
|
ys->io->needs_redraw=1;
|
|
|
|
gtk_iostat_draw(&ys->io->graphs[0]);
|
|
|
|
}
|
|
|
|
|
2002-11-29 11:37:33 +00:00
|
|
|
static void
|
2002-11-16 11:45:58 +00:00
|
|
|
create_tick_interval_menu_items(io_stat_t *io, GtkWidget *menu)
|
|
|
|
{
|
|
|
|
char str[15];
|
|
|
|
GtkWidget *menu_item;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for(i=0;i<MAX_TICK_VALUES;i++){
|
|
|
|
if(max_tick_values[i]>=1000){
|
|
|
|
sprintf(str,"%d sec", max_tick_values[i]/1000);
|
|
|
|
} else if(max_tick_values[i]>=100){
|
|
|
|
sprintf(str,"0.%1d sec", (max_tick_values[i]/100)%10);
|
|
|
|
} else if(max_tick_values[i]>=10){
|
|
|
|
sprintf(str,"0.%02d sec", (max_tick_values[i]/10)%10);
|
|
|
|
} else {
|
|
|
|
sprintf(str,"0.%03d sec", (max_tick_values[i])%10);
|
|
|
|
}
|
|
|
|
|
|
|
|
menu_item=gtk_menu_item_new_with_label(str);
|
|
|
|
io->tick_val[i].io=io;
|
|
|
|
io->tick_val[i].interval=max_tick_values[i];
|
|
|
|
SIGNAL_CONNECT(menu_item, "activate", tick_interval_select, &io->tick_val[i]);
|
|
|
|
gtk_widget_show(menu_item);
|
|
|
|
gtk_menu_append(GTK_MENU(menu), menu_item);
|
|
|
|
}
|
|
|
|
gtk_menu_set_active(GTK_MENU(menu), DEFAULT_TICK_VALUE);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2002-11-29 11:37:33 +00:00
|
|
|
static void
|
2002-11-14 10:32:22 +00:00
|
|
|
create_yscale_max_menu_items(io_stat_t *io, GtkWidget *menu)
|
|
|
|
{
|
|
|
|
char str[15];
|
|
|
|
GtkWidget *menu_item;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for(i=0;i<MAX_YSCALE;i++){
|
|
|
|
if(yscale_max[i]==AUTO_MAX_YSCALE){
|
|
|
|
strcpy(str,"Auto");
|
|
|
|
} else {
|
|
|
|
sprintf(str,"%d", yscale_max[i]);
|
|
|
|
}
|
|
|
|
menu_item=gtk_menu_item_new_with_label(str);
|
|
|
|
io->yscale[i].io=io;
|
|
|
|
io->yscale[i].yscale=yscale_max[i];
|
2002-11-15 10:55:19 +00:00
|
|
|
SIGNAL_CONNECT(menu_item, "activate", yscale_select, &io->yscale[i]);
|
2002-11-14 10:32:22 +00:00
|
|
|
gtk_widget_show(menu_item);
|
|
|
|
gtk_menu_append(GTK_MENU(menu), menu_item);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
count_type_select(GtkWidget *item _U_, gpointer key)
|
|
|
|
{
|
|
|
|
io_stat_count_type_t *ct=(io_stat_count_type_t *)key;
|
|
|
|
|
|
|
|
ct->io->count_type=ct->count_type;
|
2002-11-29 11:37:33 +00:00
|
|
|
|
|
|
|
if(ct->io->count_type==COUNT_TYPE_ADVANCED){
|
|
|
|
int i;
|
|
|
|
for(i=0;i<MAX_GRAPHS;i++){
|
|
|
|
ct->io->graphs[i].display=0;
|
|
|
|
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ct->io->graphs[i].display_button), ct->io->graphs[i].display);
|
|
|
|
gtk_widget_show(ct->io->graphs[i].advanced_buttons);
|
|
|
|
/* redraw the entire window so teh unhidden widgets show up, hopefully */
|
|
|
|
{GdkRectangle update_rect;
|
|
|
|
update_rect.x=0;
|
|
|
|
update_rect.y=0;
|
|
|
|
update_rect.width=ct->io->window->allocation.width;
|
|
|
|
update_rect.height=ct->io->window->allocation.height;
|
|
|
|
gtk_widget_draw(ct->io->window, &update_rect);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
int i;
|
|
|
|
for(i=0;i<MAX_GRAPHS;i++){
|
|
|
|
gtk_widget_hide(ct->io->graphs[i].advanced_buttons);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-11-14 10:32:22 +00:00
|
|
|
ct->io->needs_redraw=1;
|
|
|
|
gtk_iostat_draw(&ct->io->graphs[0]);
|
|
|
|
}
|
|
|
|
|
2002-11-29 11:37:33 +00:00
|
|
|
static void
|
2002-11-14 10:32:22 +00:00
|
|
|
create_frames_or_bytes_menu_items(io_stat_t *io, GtkWidget *menu)
|
|
|
|
{
|
|
|
|
GtkWidget *menu_item;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for(i=0;i<MAX_COUNT_TYPES;i++){
|
|
|
|
menu_item=gtk_menu_item_new_with_label(max_count_types[i]);
|
|
|
|
io->counttype[i].io=io;
|
|
|
|
io->counttype[i].count_type=i;
|
2002-11-15 10:55:19 +00:00
|
|
|
SIGNAL_CONNECT(menu_item, "activate", count_type_select, &io->counttype[i]);
|
2002-11-14 10:32:22 +00:00
|
|
|
gtk_widget_show(menu_item);
|
|
|
|
gtk_menu_append(GTK_MENU(menu), menu_item);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2002-11-29 11:37:33 +00:00
|
|
|
static void
|
2002-11-14 10:32:22 +00:00
|
|
|
create_ctrl_menu(io_stat_t *io, GtkWidget *box, char *name, void (*func)(io_stat_t *io, GtkWidget *menu))
|
|
|
|
{
|
|
|
|
GtkWidget *hbox;
|
|
|
|
GtkWidget *label;
|
|
|
|
GtkWidget *option_menu;
|
|
|
|
GtkWidget *menu;
|
|
|
|
|
|
|
|
hbox=gtk_hbox_new(FALSE, 0);
|
|
|
|
gtk_container_add(GTK_CONTAINER(box), hbox);
|
|
|
|
gtk_box_set_child_packing(GTK_BOX(box), hbox, FALSE, FALSE, 0, GTK_PACK_START);
|
|
|
|
gtk_widget_show(hbox);
|
|
|
|
|
|
|
|
label=gtk_label_new(name);
|
|
|
|
gtk_widget_show(label);
|
|
|
|
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
|
|
|
|
|
|
|
|
option_menu=gtk_option_menu_new();
|
|
|
|
menu=gtk_menu_new();
|
|
|
|
(*func)(io, menu);
|
|
|
|
gtk_option_menu_set_menu(GTK_OPTION_MENU(option_menu), menu);
|
|
|
|
gtk_box_pack_end(GTK_BOX(hbox), option_menu, FALSE, FALSE, 0);
|
|
|
|
gtk_widget_show(option_menu);
|
|
|
|
}
|
|
|
|
|
2002-11-29 11:37:33 +00:00
|
|
|
static void
|
2002-11-14 10:32:22 +00:00
|
|
|
create_ctrl_area(io_stat_t *io, GtkWidget *box)
|
|
|
|
{
|
|
|
|
GtkWidget *vbox;
|
|
|
|
|
|
|
|
vbox=gtk_vbox_new(FALSE, 0);
|
|
|
|
gtk_container_add(GTK_CONTAINER(box), vbox);
|
|
|
|
gtk_box_set_child_packing(GTK_BOX(box), vbox, FALSE, FALSE, 0, GTK_PACK_END);
|
|
|
|
gtk_widget_show(vbox);
|
|
|
|
|
|
|
|
create_ctrl_menu(io, vbox, "Unit:", create_frames_or_bytes_menu_items);
|
2002-11-16 11:45:58 +00:00
|
|
|
create_ctrl_menu(io, vbox, "Tick Interval:", create_tick_interval_menu_items);
|
2002-11-14 10:32:22 +00:00
|
|
|
create_ctrl_menu(io, vbox, "Pixels Per Tick:", create_pixels_per_tick_menu_items);
|
2002-11-17 11:43:40 +00:00
|
|
|
create_ctrl_menu(io, vbox, "Y-scale:", create_yscale_max_menu_items);
|
2002-11-14 10:32:22 +00:00
|
|
|
|
2002-11-29 11:37:33 +00:00
|
|
|
return;
|
2002-11-14 10:32:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static gint
|
|
|
|
filter_callback(GtkWidget *widget _U_, io_stat_graph_t *gio)
|
|
|
|
{
|
|
|
|
char *filter;
|
|
|
|
int i;
|
2002-11-29 11:37:33 +00:00
|
|
|
header_field_info *hfi;
|
|
|
|
|
|
|
|
/* first check if the field string is valid */
|
|
|
|
if(gio->io->count_type==COUNT_TYPE_ADVANCED){
|
|
|
|
char *field;
|
|
|
|
field=(char *)gtk_entry_get_text(GTK_ENTRY(gio->calc_field));
|
|
|
|
/* warn and bail out if there was no field specified */
|
|
|
|
if(field==NULL || field[0]==0){
|
|
|
|
simple_dialog(ESD_TYPE_WARN, NULL, "'%s' is not a valid field name", field);
|
|
|
|
gio->display=0;
|
|
|
|
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gio->display_button), gio->display);
|
|
|
|
gio->io->needs_redraw=1;
|
|
|
|
gtk_iostat_draw(gio);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
/* warn and bail out if the field could not be found */
|
|
|
|
hfi=proto_registrar_get_byname(field);
|
|
|
|
if(hfi==NULL){
|
|
|
|
simple_dialog(ESD_TYPE_WARN, NULL, "'%s' is not a valid field name", field);
|
|
|
|
gio->display=0;
|
|
|
|
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gio->display_button), gio->display);
|
|
|
|
gio->io->needs_redraw=1;
|
|
|
|
gtk_iostat_draw(gio);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
gio->hf_index=hfi->id;
|
|
|
|
/* check that the type is compatible */
|
|
|
|
switch(hfi->type){
|
|
|
|
case FT_UINT8:
|
|
|
|
case FT_UINT16:
|
|
|
|
case FT_UINT24:
|
|
|
|
case FT_UINT32:
|
|
|
|
case FT_INT8:
|
|
|
|
case FT_INT16:
|
|
|
|
case FT_INT24:
|
|
|
|
case FT_INT32:
|
|
|
|
/* these types support all calculations */
|
|
|
|
break;
|
|
|
|
case FT_RELATIVE_TIME:
|
|
|
|
/* this type only support COUNT, MAX, MIN, AVG */
|
|
|
|
switch(gio->calc_type){
|
|
|
|
case CALC_TYPE_COUNT:
|
|
|
|
case CALC_TYPE_MAX:
|
|
|
|
case CALC_TYPE_MIN:
|
|
|
|
case CALC_TYPE_AVG:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
simple_dialog(ESD_TYPE_WARN, NULL, "%s is not supported for %s's type", max_calc_types[gio->calc_type], field);
|
|
|
|
gio->display=0;
|
|
|
|
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gio->display_button), gio->display);
|
|
|
|
gio->io->needs_redraw=1;
|
|
|
|
gtk_iostat_draw(gio);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
if(gio->calc_type!=CALC_TYPE_COUNT){
|
|
|
|
simple_dialog(ESD_TYPE_WARN, NULL, "Stat calculations is not supported for %s's type", field);
|
|
|
|
gio->display=0;
|
|
|
|
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gio->display_button), gio->display);
|
|
|
|
gio->io->needs_redraw=1;
|
|
|
|
gtk_iostat_draw(gio);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
2002-11-14 10:32:22 +00:00
|
|
|
|
|
|
|
/* first check if the filter string is valid. Do this by just trying
|
|
|
|
to register, deregister a dummy listener. */
|
|
|
|
filter=(char *)gtk_entry_get_text(GTK_ENTRY(gio->filter_button));
|
|
|
|
if(register_tap_listener("frame", &filter, filter, NULL, NULL, NULL)){
|
|
|
|
simple_dialog(ESD_TYPE_WARN, NULL, "%s is not a valid filter string", filter);
|
|
|
|
if(gio->display){
|
|
|
|
gio->display=0;
|
|
|
|
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gio->display_button), gio->display);
|
|
|
|
}
|
|
|
|
protect_thread_critical_region();
|
|
|
|
remove_tap_listener(gio);
|
|
|
|
unprotect_thread_critical_region();
|
|
|
|
|
|
|
|
gio->io->needs_redraw=1;
|
|
|
|
gtk_iostat_draw(gio);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
/* just remove the dummy again */
|
|
|
|
protect_thread_critical_region();
|
|
|
|
remove_tap_listener(&filter);
|
|
|
|
unprotect_thread_critical_region();
|
|
|
|
|
|
|
|
/* this graph is not active, just update display and redraw */
|
|
|
|
if(!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gio->display_button))){
|
|
|
|
gio->display=0;
|
|
|
|
gio->io->needs_redraw=1;
|
|
|
|
gtk_iostat_draw(gio);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ok, we have a valid filter and the graph is active.
|
|
|
|
first just try to delete any previous settings and then apply
|
|
|
|
the new ones.
|
|
|
|
*/
|
|
|
|
protect_thread_critical_region();
|
|
|
|
remove_tap_listener(gio);
|
|
|
|
unprotect_thread_critical_region();
|
|
|
|
|
|
|
|
gio->display=1;
|
|
|
|
|
|
|
|
/* only register the draw routine for the first gio. */
|
|
|
|
for(i=0;i<MAX_GRAPHS;i++){
|
|
|
|
gtk_iostat_reset(&gio->io->graphs[i]);
|
|
|
|
}
|
|
|
|
register_tap_listener("frame", gio, filter, gtk_iostat_reset, gtk_iostat_packet, gtk_iostat_draw);
|
|
|
|
redissect_packets(&cfile);
|
|
|
|
gio->io->needs_redraw=1;
|
|
|
|
gtk_iostat_draw(gio);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2002-11-29 11:37:33 +00:00
|
|
|
|
|
|
|
static void
|
|
|
|
calc_type_select(GtkWidget *item _U_, gpointer key)
|
|
|
|
{
|
|
|
|
io_stat_calc_type_t *ct=(io_stat_calc_type_t *)key;
|
|
|
|
|
|
|
|
ct->gio->calc_type=ct->calc_type;
|
|
|
|
|
|
|
|
/* disable the graph */
|
|
|
|
ct->gio->display=0;
|
|
|
|
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ct->gio->display_button), ct->gio->display);
|
|
|
|
|
|
|
|
ct->gio->io->needs_redraw=1;
|
|
|
|
gtk_iostat_draw(&ct->gio->io->graphs[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
create_calc_types_menu_items(io_stat_graph_t *gio, GtkWidget *menu)
|
|
|
|
{
|
|
|
|
GtkWidget *menu_item;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for(i=0;i<MAX_CALC_TYPES;i++){
|
|
|
|
gio->calc_types[i].gio=gio;
|
|
|
|
gio->calc_types[i].calc_type=i;
|
|
|
|
menu_item=gtk_menu_item_new_with_label(max_calc_types[i]);
|
|
|
|
SIGNAL_CONNECT(menu_item, "activate", calc_type_select, &gio->calc_types[i]);
|
|
|
|
gtk_widget_show(menu_item);
|
|
|
|
gtk_menu_append(GTK_MENU(menu), menu_item);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
create_advanced_menu(io_stat_graph_t *gio, GtkWidget *box, char *name, void (*func)(io_stat_graph_t *io, GtkWidget *menu))
|
|
|
|
{
|
|
|
|
GtkWidget *hbox;
|
|
|
|
GtkWidget *label;
|
|
|
|
GtkWidget *option_menu;
|
|
|
|
GtkWidget *menu;
|
|
|
|
|
|
|
|
hbox=gtk_hbox_new(FALSE, 0);
|
|
|
|
gtk_container_add(GTK_CONTAINER(box), hbox);
|
|
|
|
gtk_box_set_child_packing(GTK_BOX(box), hbox, FALSE, FALSE, 0, GTK_PACK_START);
|
|
|
|
gtk_widget_show(hbox);
|
|
|
|
|
|
|
|
label=gtk_label_new(name);
|
|
|
|
gtk_widget_show(label);
|
|
|
|
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
|
|
|
|
|
|
|
|
option_menu=gtk_option_menu_new();
|
|
|
|
menu=gtk_menu_new();
|
|
|
|
(*func)(gio, menu);
|
|
|
|
gtk_option_menu_set_menu(GTK_OPTION_MENU(option_menu), menu);
|
|
|
|
gtk_box_pack_end(GTK_BOX(hbox), option_menu, FALSE, FALSE, 0);
|
|
|
|
gtk_widget_show(option_menu);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static gint
|
|
|
|
field_callback(GtkWidget *widget _U_, io_stat_graph_t *gio)
|
|
|
|
{
|
|
|
|
gio->display=0;
|
|
|
|
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gio->display_button), gio->display);
|
|
|
|
gio->io->needs_redraw=1;
|
|
|
|
gtk_iostat_draw(gio);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
create_advanced_field(io_stat_graph_t *gio, GtkWidget *box)
|
|
|
|
{
|
|
|
|
|
|
|
|
gio->calc_field=gtk_entry_new_with_max_length(30);
|
|
|
|
gtk_box_pack_start(GTK_BOX(box), gio->calc_field, FALSE, FALSE, 0);
|
|
|
|
gtk_widget_show(gio->calc_field);
|
|
|
|
SIGNAL_CONNECT(gio->filter_button, "activate", field_callback, gio);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
create_advanced_box(io_stat_graph_t *gio, GtkWidget *box)
|
|
|
|
{
|
|
|
|
GtkWidget *hbox;
|
|
|
|
|
|
|
|
hbox=gtk_hbox_new(FALSE, 0);
|
|
|
|
gio->advanced_buttons=hbox;
|
|
|
|
gtk_container_add(GTK_CONTAINER(box), hbox);
|
|
|
|
gtk_box_set_child_packing(GTK_BOX(box), hbox, FALSE, FALSE, 0, GTK_PACK_START);
|
|
|
|
gtk_widget_hide(hbox);
|
|
|
|
|
|
|
|
create_advanced_menu(gio, hbox, "Calc:", create_calc_types_menu_items);
|
|
|
|
create_advanced_field(gio, hbox);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
2003-01-11 11:10:33 +00:00
|
|
|
filter_button_clicked(GtkWidget *w, gpointer uio)
|
2002-11-14 10:32:22 +00:00
|
|
|
{
|
2003-01-11 11:10:33 +00:00
|
|
|
io_stat_graph_t *gio=(io_stat_graph_t *)uio;
|
2002-11-14 10:32:22 +00:00
|
|
|
|
2003-01-15 05:58:50 +00:00
|
|
|
display_filter_construct_cb(w, gio->args);
|
2003-01-11 11:10:33 +00:00
|
|
|
return;
|
|
|
|
}
|
2002-12-16 21:18:37 +00:00
|
|
|
|
2003-01-11 11:10:33 +00:00
|
|
|
static void
|
|
|
|
create_filter_box(io_stat_graph_t *gio, GtkWidget *box, int num)
|
|
|
|
{
|
|
|
|
GtkWidget *hbox;
|
|
|
|
GtkWidget *label;
|
|
|
|
char str[256];
|
2002-12-16 21:18:37 +00:00
|
|
|
|
2002-11-14 10:32:22 +00:00
|
|
|
hbox=gtk_hbox_new(FALSE, 0);
|
|
|
|
gtk_container_add(GTK_CONTAINER(box), hbox);
|
|
|
|
gtk_box_set_child_packing(GTK_BOX(box), hbox, FALSE, FALSE, 0, GTK_PACK_START);
|
|
|
|
gtk_widget_show(hbox);
|
|
|
|
|
2003-01-11 11:10:33 +00:00
|
|
|
|
|
|
|
sprintf(str, "Filter:%d", num);
|
|
|
|
label=gtk_label_new(str);
|
2002-11-14 10:32:22 +00:00
|
|
|
gtk_widget_show(label);
|
|
|
|
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
|
|
|
|
|
|
|
|
gio->display_button=gtk_toggle_button_new();
|
|
|
|
gtk_box_pack_start(GTK_BOX(hbox), gio->display_button, FALSE, FALSE, 0);
|
|
|
|
gtk_widget_show(gio->display_button);
|
|
|
|
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gio->display_button), gio->display);
|
2002-11-15 10:55:19 +00:00
|
|
|
SIGNAL_CONNECT(gio->display_button, "toggled", filter_callback, gio);
|
2002-11-14 10:32:22 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
label=gtk_label_new(" Color:");
|
|
|
|
gtk_widget_show(label);
|
|
|
|
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
|
|
|
|
|
|
|
|
gio->color_button=gtk_toggle_button_new();
|
|
|
|
gtk_box_pack_start(GTK_BOX(hbox), gio->color_button, FALSE, FALSE, 0);
|
|
|
|
gtk_widget_show(gio->color_button);
|
2002-11-15 10:55:19 +00:00
|
|
|
|
|
|
|
#if GTK_MAJOR_VERSION < 2
|
2002-12-16 06:44:45 +00:00
|
|
|
rc_style = gtk_rc_style_new ();
|
|
|
|
rc_style->bg[GTK_STATE_NORMAL] = gio->color;
|
|
|
|
rc_style->color_flags[GTK_STATE_NORMAL] |= GTK_RC_BG;
|
|
|
|
rc_style->bg[GTK_STATE_ACTIVE] = gio->color;
|
|
|
|
rc_style->color_flags[GTK_STATE_ACTIVE] |= GTK_RC_BG;
|
|
|
|
rc_style->bg[GTK_STATE_PRELIGHT] = gio->color;
|
|
|
|
rc_style->color_flags[GTK_STATE_PRELIGHT] |= GTK_RC_BG;
|
|
|
|
rc_style->bg[GTK_STATE_SELECTED] = gio->color;
|
|
|
|
rc_style->color_flags[GTK_STATE_SELECTED] |= GTK_RC_BG;
|
|
|
|
rc_style->bg[GTK_STATE_INSENSITIVE] = gio->color;
|
|
|
|
rc_style->color_flags[GTK_STATE_INSENSITIVE] |= GTK_RC_BG;
|
|
|
|
gtk_widget_modify_style (gio->color_button, rc_style);
|
|
|
|
gtk_rc_style_unref (rc_style);
|
2002-11-15 10:55:19 +00:00
|
|
|
#else
|
2002-11-14 10:32:22 +00:00
|
|
|
gtk_widget_modify_bg(gio->color_button, GTK_STATE_NORMAL, &gio->color);
|
|
|
|
gtk_widget_modify_bg(gio->color_button, GTK_STATE_ACTIVE, &gio->color);
|
|
|
|
gtk_widget_modify_bg(gio->color_button, GTK_STATE_PRELIGHT, &gio->color);
|
|
|
|
gtk_widget_modify_bg(gio->color_button, GTK_STATE_SELECTED, &gio->color);
|
|
|
|
gtk_widget_modify_bg(gio->color_button, GTK_STATE_INSENSITIVE, &gio->color);
|
2002-11-15 10:55:19 +00:00
|
|
|
#endif
|
2002-11-14 10:32:22 +00:00
|
|
|
/* gtk_signal_connect(GTK_OBJECT(gio->display_button), "toggled", GTK_SIGNAL_FUNC(filter_callback), gio);*/
|
|
|
|
|
|
|
|
|
2002-12-16 21:18:37 +00:00
|
|
|
/* filter prefs dialog --- comment out static label */
|
|
|
|
/* label=gtk_label_new(" Filter:"); */
|
|
|
|
|
|
|
|
/* filter prefs dialog */
|
|
|
|
label=gtk_label_new(" ");
|
2002-11-14 10:32:22 +00:00
|
|
|
gtk_widget_show(label);
|
|
|
|
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
|
2003-01-11 11:10:33 +00:00
|
|
|
gio->filter_bt = gtk_button_new_with_label("Filter:");
|
|
|
|
|
|
|
|
sprintf(str, "Ethereal: Display Filter IO-Stat (Filter:%d)", num);
|
|
|
|
if(gio->args->title){
|
|
|
|
free(gio->args->title);
|
|
|
|
}
|
|
|
|
gio->args->title=strdup(str);
|
|
|
|
|
|
|
|
SIGNAL_CONNECT(gio->filter_bt, "clicked", filter_button_clicked, gio);
|
2003-01-15 05:20:19 +00:00
|
|
|
SIGNAL_CONNECT(gio->filter_bt, "destroy", filter_button_destroy_cb, NULL);
|
2003-01-11 11:10:33 +00:00
|
|
|
|
|
|
|
gtk_box_pack_start(GTK_BOX(hbox), gio->filter_bt, FALSE, TRUE, 0);
|
|
|
|
gtk_widget_show(gio->filter_bt);
|
2002-11-14 10:32:22 +00:00
|
|
|
|
|
|
|
gio->filter_button=gtk_entry_new_with_max_length(256);
|
2002-12-16 21:18:37 +00:00
|
|
|
|
|
|
|
/* filter prefs dialog */
|
2003-01-11 11:10:33 +00:00
|
|
|
OBJECT_SET_DATA(gio->filter_bt, E_FILT_TE_PTR_KEY, gio->filter_button);
|
2002-12-16 21:18:37 +00:00
|
|
|
/* filter prefs dialog */
|
|
|
|
|
2002-11-14 10:32:22 +00:00
|
|
|
gtk_box_pack_start(GTK_BOX(hbox), gio->filter_button, FALSE, FALSE, 0);
|
|
|
|
gtk_widget_show(gio->filter_button);
|
2002-11-15 10:55:19 +00:00
|
|
|
SIGNAL_CONNECT(gio->filter_button, "activate", filter_callback, gio);
|
2002-11-14 10:32:22 +00:00
|
|
|
|
2002-11-29 11:37:33 +00:00
|
|
|
create_advanced_box(gio, hbox);
|
|
|
|
|
|
|
|
return;
|
2002-11-14 10:32:22 +00:00
|
|
|
}
|
|
|
|
|
2002-11-29 11:37:33 +00:00
|
|
|
static void
|
2002-11-14 10:32:22 +00:00
|
|
|
create_filter_area(io_stat_t *io, GtkWidget *box)
|
|
|
|
{
|
|
|
|
GtkWidget *vbox;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
vbox=gtk_vbox_new(FALSE, 0);
|
|
|
|
gtk_container_add(GTK_CONTAINER(box), vbox);
|
|
|
|
gtk_box_set_child_packing(GTK_BOX(box), vbox, FALSE, FALSE, 0, GTK_PACK_START);
|
|
|
|
gtk_widget_show(vbox);
|
|
|
|
|
|
|
|
for(i=0;i<MAX_GRAPHS;i++){
|
2003-01-11 11:10:33 +00:00
|
|
|
create_filter_box(&io->graphs[i], vbox, i+1);
|
2002-11-14 10:32:22 +00:00
|
|
|
}
|
|
|
|
|
2002-11-29 11:37:33 +00:00
|
|
|
return;
|
2002-11-14 10:32:22 +00:00
|
|
|
}
|
|
|
|
|
2002-11-29 11:37:33 +00:00
|
|
|
|
|
|
|
static void
|
2002-11-14 10:32:22 +00:00
|
|
|
init_io_stat_window(io_stat_t *io)
|
|
|
|
{
|
|
|
|
GtkWidget *vbox;
|
|
|
|
GtkWidget *hbox;
|
|
|
|
|
|
|
|
/* create the main window */
|
|
|
|
io->window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
2003-01-11 11:10:33 +00:00
|
|
|
|
2002-11-14 10:32:22 +00:00
|
|
|
gtk_widget_set_name(io->window, "I/O Statistics");
|
|
|
|
|
|
|
|
vbox=gtk_vbox_new(FALSE, 0);
|
|
|
|
gtk_container_add(GTK_CONTAINER(io->window), vbox);
|
|
|
|
gtk_widget_show(vbox);
|
|
|
|
|
|
|
|
create_draw_area(io, vbox);
|
|
|
|
|
|
|
|
hbox=gtk_hbox_new(FALSE, 0);
|
|
|
|
gtk_container_add(GTK_CONTAINER(vbox), hbox);
|
|
|
|
gtk_box_set_child_packing(GTK_BOX(vbox), hbox, FALSE, FALSE, 0, GTK_PACK_START);
|
|
|
|
gtk_widget_show(hbox);
|
|
|
|
|
|
|
|
create_filter_area(io, hbox);
|
|
|
|
create_ctrl_area(io, hbox);
|
|
|
|
|
|
|
|
gtk_widget_show(io->window);
|
2002-11-19 08:10:13 +00:00
|
|
|
gtk_window_set_title(GTK_WINDOW(io->window),"IO-Stat");
|
2002-11-14 10:32:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
gtk_iostat_cb(GtkWidget *w _U_, gpointer d _U_)
|
|
|
|
{
|
|
|
|
gtk_iostat_init(NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
register_tap_listener_gtk_iostat(void)
|
|
|
|
{
|
|
|
|
io_stat_widget_table = g_hash_table_new(io_stat_widget_hash,
|
|
|
|
io_stat_widget_equal);
|
|
|
|
register_ethereal_tap("io,stat", gtk_iostat_init, NULL, NULL);
|
|
|
|
}
|
|
|
|
|