Give the code that computes protocol statistics a progress dialog box,
authorGuy Harris <guy@alum.mit.edu>
Sat, 24 Mar 2001 02:07:22 +0000 (02:07 -0000)
committerGuy Harris <guy@alum.mit.edu>
Sat, 24 Mar 2001 02:07:22 +0000 (02:07 -0000)
as, on a large capture, it could take a significant amount of time.

Let the user stop the computation and, if they do, don't pop up the
statistics dialog box.

Create a new header file declaring the routines to create, update, and
destroy progress dialog boxes; those routines' APIs don't depend on
GTK+, but others declared in "ui_util.h" do, and we don't want to oblige
a source file to depend on GTK+ headers unless it uses a GTK+ API or an
API that depends on GTK+.

svn path=/trunk/; revision=3179

Makefile.am
file.c
gtk/progress_dlg.c
gtk/proto_hier_stats_dlg.c
progress_dlg.h [new file with mode: 0644]
proto_hier_stats.c
ui_util.h

index 18e2c060a6c383072c65bfe9991bc45345cb4049..ae71558054b472b8835698345cb96a08965fcb02 100644 (file)
@@ -1,7 +1,7 @@
 # Makefile.am
 # Automake file for Ethereal
 #
-# $Id: Makefile.am,v 1.295 2001/03/23 19:22:02 jfoster Exp $
+# $Id: Makefile.am,v 1.296 2001/03/24 02:07:20 guy Exp $
 #
 # Ethereal - Network traffic analyzer
 # By Gerald Combs <gerald@zing.org>
@@ -373,6 +373,7 @@ ethereal_SOURCES = \
        filters.h      \
        globals.h      \
        menu.h         \
+       progress_dlg.h \
        proto_hier_stats.h      \
        proto_hier_stats.c      \
        simple_dialog.h \
diff --git a/file.c b/file.c
index 2d9406f3e385b620f44be5044eed3748fd87973c..d5dc0c766bdabc66de7e6a296c18bffa9d1bf18e 100644 (file)
--- a/file.c
+++ b/file.c
@@ -1,7 +1,7 @@
 /* file.c
  * File I/O routines
  *
- * $Id: file.c,v 1.233 2001/03/23 14:43:59 jfoster Exp $
+ * $Id: file.c,v 1.234 2001/03/24 02:07:20 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -81,6 +81,7 @@
 #include "menu.h"
 #include "util.h"
 #include "simple_dialog.h"
+#include "progress_dlg.h"
 #include "ui_util.h"
 #include "prefs.h"
 #include "gtk/proto_draw.h"
index a37ede57d1cdfee13c98f8fdf1a3bbf92e15cb02..6df6b72a469edf4d3541de9095fa3804a46b3e87 100644 (file)
@@ -1,7 +1,7 @@
 /* progress_dlg.c
  * Routines for progress-bar (modal) dialog
  *
- * $Id: progress_dlg.c,v 1.8 2000/08/23 06:56:27 guy Exp $
+ * $Id: progress_dlg.c,v 1.9 2001/03/24 02:07:22 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -29,7 +29,7 @@
 
 #include "gtkglobals.h"
 #include "dlg_utils.h"
-#include "ui_util.h"
+#include "progress_dlg.h"
 
 #define        PROG_BAR_KEY    "progress_bar"
 
index aceec24b78fac950444480ed7428dbfa1f900705..14a0dbdfe7ffb22a383368b96025260870cff5fc 100644 (file)
@@ -1,6 +1,6 @@
 /* proto_hier_stats_dlg.c
  *
- * $Id: proto_hier_stats_dlg.c,v 1.1 2001/03/22 23:54:47 gram Exp $
+ * $Id: proto_hier_stats_dlg.c,v 1.2 2001/03/24 02:07:22 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -113,10 +113,9 @@ fill_in_ctree(GtkWidget *tree, ph_stats_t *ps)
 }
 
 static void
-create_tree(GtkWidget *container)
+create_tree(GtkWidget *container, ph_stats_t *ps)
 {
        GtkWidget       *sw, *tree;
-       ph_stats_t      *ps;
        int             i, height;
        gchar           *column_titles[NUM_STAT_COLUMNS] = {
                "Protocol",
@@ -127,8 +126,6 @@ create_tree(GtkWidget *container)
                "Last-Protocol Bytes",
        };
 
-       ps = ph_stats_new();
-
        /* Scrolled Window */
        sw = gtk_scrolled_window_new(NULL, NULL);
        gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
@@ -141,7 +138,7 @@ create_tree(GtkWidget *container)
        /* XXX - get 'pos' to set vertical scroll-bar placement. */
        /* XXX - set line style from preferences ???. */
 
-       /* The titel bars do nothing. */
+       /* The title bars do nothing. */
        gtk_clist_column_titles_passive(GTK_CLIST(tree));
 
        /* Auto Resize all columns */
@@ -173,9 +170,18 @@ create_tree(GtkWidget *container)
 void
 proto_hier_stats_cb(GtkWidget *w, gpointer d)
 {
+       ph_stats_t      *ps;
        GtkWidget       *dlg, *bt, *vbox, *frame, *bbox;
        const gchar     *wname = "Protocol Hierarchy Statistics";
 
+       /* Get the statistics. */
+       ps = ph_stats_new();
+       if (ps == NULL) {
+               /* The user gave up before we finished; don't pop up
+                  a statistics window. */
+               return;
+       }
+
        dlg = dlg_window_new(wname);
 
        vbox = gtk_vbox_new(FALSE, 5);
@@ -188,7 +194,7 @@ proto_hier_stats_cb(GtkWidget *w, gpointer d)
 
 
        /* Data section */
-       create_tree(frame);
+       create_tree(frame, ps);
 
        /* Button row. We put it in an HButtonBox to
         * keep it from expanding to the width of the window. */
diff --git a/progress_dlg.h b/progress_dlg.h
new file mode 100644 (file)
index 0000000..b40a069
--- /dev/null
@@ -0,0 +1,61 @@
+/* progress_dlg.h
+ * Definitions for progress dialog box routines
+ *
+ * $Id: progress_dlg.h,v 1.1 2001/03/24 02:07:20 guy Exp $
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@zing.org>
+ * 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.
+ */
+
+#ifndef __PROGRESS_DLG_H__
+#define __PROGRESS_DLG_H__
+
+/*
+ * Progress (modal) dialog box routines.
+ */
+
+struct progdlg;
+
+typedef struct progdlg progdlg_t;
+
+/*
+ * Create and pop up the progress dialog; allocate a "progdlg_t"
+ * and initialize it to contain all information the implementation
+ * needs in order to manipulate the dialog, and return a pointer to
+ * it.
+ *
+ * The first argument is the title to give the dialog box; the second
+ * argument is the string to put in the "stop this operation" button;
+ * the third argument is a pointer to a Boolean variable that will be
+ * set to TRUE if the user hits that button.
+ */
+progdlg_t *create_progress_dlg(const gchar *title, const gchar *stop_title,
+    gboolean *stop_flag);
+
+/*
+ * Set the percentage value of the progress bar.
+ */
+void update_progress_dlg(progdlg_t *dlg, gfloat percentage);
+
+/*
+ * Destroy the progress bar.
+ */
+void destroy_progress_dlg(progdlg_t *dlg);
+
+#endif /* __PROGRESS_DLG_H__ */
index 4247d49c5eac72f395837281e5b0edba51eb7404..bb28b7269ef233fdca7b8f9ea4923e1007493ebe 100644 (file)
@@ -1,7 +1,7 @@
 /* proto_hier_stats.c
  * Routines for calculating statistics based on protocol.
  *
- * $Id: proto_hier_stats.c,v 1.2 2001/03/23 21:55:36 guy Exp $
+ * $Id: proto_hier_stats.c,v 1.3 2001/03/24 02:07:20 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
 
 #include "globals.h"
 #include "proto_hier_stats.h"
+#include "progress_dlg.h"
 #include <wtap.h>
 
 #include <stdio.h>
 #include <glib.h>
 
+/* Update the progress bar this many times when scanning the packet list. */
+#define N_PROGBAR_UPDATES      100
+
 static GNode*
 find_stat_node(GNode *parent_node, header_field_info *needle_hfinfo)
 {
@@ -147,6 +151,11 @@ ph_stats_new(void)
        ph_stats_t      *ps;
        frame_data      *frame;
        guint           tot_packets, tot_bytes;
+       progdlg_t       *progbar;
+       gboolean        stop_flag;
+       guint32         progbar_quantum;
+       guint32         progbar_nextstep;
+       int             count;
 
        /* Initialize the data */
        ps = g_new(ph_stats_t, 1);
@@ -154,22 +163,72 @@ ph_stats_new(void)
        ps->tot_bytes = 0;
        ps->stats_tree = g_node_new(NULL);
 
-       frame = cfile.plist;
+       /* Update the progress bar when it gets to this value. */
+       progbar_nextstep = 0;
+       /* When we reach the value that triggers a progress bar update,
+          bump that value by this amount. */
+       progbar_quantum = cfile.count/N_PROGBAR_UPDATES;
+       /* Count of packets at which we've looked. */
+       count = 0;
+
+       stop_flag = FALSE;
+       progbar = create_progress_dlg("Computing protocol statistics", "Stop",
+           &stop_flag);
+
        tot_packets = 0;
        tot_bytes = 0;
 
-       while (frame) {
-               /* Skip frames that are hidden due to the display filter */
-               if (!frame->flags.passed_dfilter) {
-                       continue;
+       for (frame = cfile.plist; frame != NULL; frame = frame->next) {
+               /* Update the progress bar, but do it only N_PROGBAR_UPDATES
+                  times; when we update it, we have to run the GTK+ main
+                  loop to get it to repaint what's pending, and doing so
+                  may involve an "ioctl()" to see if there's any pending
+                  input from an X server, and doing that for every packet
+                  can be costly, especially on a big file. */
+               if (count >= progbar_nextstep) {
+                       /* let's not divide by zero. I should never be started
+                        * with count == 0, so let's assert that
+                        */
+                       g_assert(cfile.count > 0);
+
+                       update_progress_dlg(progbar,
+                           (gfloat) count / cfile.count);
+
+                       progbar_nextstep += progbar_quantum;
+               }
+
+               if (stop_flag) {
+                       /* Well, the user decided to abort the statistics.
+                          computation process  Just stop. */
+                       break;
                }
 
-               process_frame(frame, ps);
+               /* Skip frames that are hidden due to the display filter.
+                  XXX - should the progress bar count only packets that
+                  passed the display filter?  If so, it should
+                  probably do so for other loops (see "file.c") that
+                  look only at those packets. */
+               if (frame->flags.passed_dfilter) {
+                       process_frame(frame, ps);
+
+                       tot_packets++;
+                       tot_bytes += frame->pkt_len;
+               }
 
-               tot_packets++;
-               tot_bytes += frame->pkt_len;
+               count++;
+       }
 
-               frame = frame->next;
+       /* We're done calculating the statistics; destroy the progress bar. */
+       destroy_progress_dlg(progbar);
+
+       if (stop_flag) {
+               /*
+                * We quit in the middle; throw away the statistics
+                * and return NULL, so our caller doesn't pop up a
+                * window with the incomplete statistics.
+                */
+               ph_stats_free(ps);
+               return NULL;
        }
 
        ps->tot_packets = tot_packets;
index ebc66e3f11961a3c82c680ec144e8f654d8a90cd..97d828af3f86c214f14a00367c8b591f5628ede4 100644 (file)
--- a/ui_util.h
+++ b/ui_util.h
@@ -1,7 +1,7 @@
 /* ui_util.h
  * Definitions for UI utility routines
  *
- * $Id: ui_util.h,v 1.6 2000/07/07 07:01:28 guy Exp $
+ * $Id: ui_util.h,v 1.7 2001/03/24 02:07:20 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -43,38 +43,6 @@ void reactivate_window(GtkWidget *);
 /* Destroy all popup packet windows. */
 void destroy_packet_wins(void);
 
-/*
- * Progress (modal) dialog box routines.
- */
-
-struct progdlg;
-
-typedef struct progdlg progdlg_t;
-
-/*
- * Create and pop up the progress dialog; allocate a "progdlg_t"
- * and initialize it to contain all information the implementation
- * needs in order to manipulate the dialog, and return a pointer to
- * it.
- *
- * The first argument is the title to give the dialog box; the second
- * argument is the string to put in the "stop this operation" button;
- * the third argument is a pointer to a Boolean variable that will be
- * set to TRUE if the user hits that button.
- */
-progdlg_t *create_progress_dlg(const gchar *title, const gchar *stop_title,
-    gboolean *stop_flag);
-
-/*
- * Set the percentage value of the progress bar.
- */
-void update_progress_dlg(progdlg_t *dlg, gfloat percentage);
-
-/*
- * Destroy the progress bar.
- */
-void destroy_progress_dlg(progdlg_t *dlg);
-
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */