summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--file.c238
-rw-r--r--ui/qt/progress_frame.cpp8
-rw-r--r--ui/qt/progress_frame.h1
3 files changed, 111 insertions, 136 deletions
diff --git a/file.c b/file.c
index db3a4be8de..9ab2854436 100644
--- a/file.c
+++ b/file.c
@@ -138,11 +138,12 @@ static void cf_open_failure_alert_box(const char *filename, int err,
static void cf_rename_failure_alert_box(const char *filename, int err);
static void cf_close_failure_alert_box(const char *filename, int err);
static void ref_time_packets(capture_file *cf);
-/* Update the progress bar this many times when reading a file. */
-#define N_PROGBAR_UPDATES 100
-/* We read around 200k/100ms don't update the progress bar more often than that */
-#define MIN_QUANTUM 200000
-#define MIN_NUMBER_OF_PACKET 1500
+
+/* Seconds spent processing packets between pushing UI updates. */
+#define PROGBAR_UPDATE_INTERVAL 0.150
+
+/* Show the progress bar after this many seconds. */
+#define PROGBAR_SHOW_DELAY 0.5
/*
* We could probably use g_signal_...() instead of the callbacks below but that
@@ -485,6 +486,24 @@ cf_close(capture_file *cf)
cf_callback_invoke(cf_cb_file_closed, cf);
}
+/*
+ * TRUE if the progress dialog doesn't exist and it looks like we'll
+ * take > 2s to load, FALSE otherwise.
+ */
+static inline gboolean
+progress_is_slow(progdlg_t *progdlg, GTimer *prog_timer, gint64 size, gint64 pos)
+{
+ double elapsed;
+
+ if (progdlg) return FALSE;
+ elapsed = g_timer_elapsed(prog_timer, NULL);
+ if ((elapsed / 2 > PROGBAR_SHOW_DELAY && (size / pos) > 2) /* It looks like we're going to be slow. */
+ || elapsed > PROGBAR_SHOW_DELAY) { /* We are indeed slow. */
+ return TRUE;
+ }
+ return FALSE;
+}
+
static float
calc_progbar_val(capture_file *cf, gint64 size, gint64 file_pos, gchar *status_str, gulong status_size)
{
@@ -524,6 +543,7 @@ cf_read(capture_file *cf, gboolean reloading)
gchar *err_info = NULL;
gchar *name_ptr;
progdlg_t *volatile progbar = NULL;
+ GTimer *prog_timer = g_timer_new();
GTimeVal start_time;
epan_dissect_t edt;
dfilter_t *dfcode;
@@ -571,8 +591,6 @@ cf_read(capture_file *cf, gboolean reloading)
gint64 file_pos;
gint64 data_offset;
- gint64 progbar_quantum;
- gint64 progbar_nextstep;
float progbar_val;
gchar status_str[100];
@@ -583,26 +601,15 @@ cf_read(capture_file *cf, gboolean reloading)
/* Find the size of the file. */
size = wtap_file_size(cf->wth, NULL);
- /* 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. */
- if (size >= 0) {
- progbar_quantum = size/N_PROGBAR_UPDATES;
- if (progbar_quantum < MIN_QUANTUM)
- progbar_quantum = MIN_QUANTUM;
- }else
- progbar_quantum = 0;
+ g_timer_start(prog_timer);
while ((wtap_read(cf->wth, &err, &err_info, &data_offset))) {
if (size >= 0) {
count++;
file_pos = wtap_read_so_far(cf->wth);
- /* Create the progress bar if necessary.
- * Check whether it should be created or not every MIN_NUMBER_OF_PACKET
- */
- if ((progbar == NULL) && !(count % MIN_NUMBER_OF_PACKET)) {
+ /* Create the progress bar if necessary. */
+ if (progress_is_slow(progbar, prog_timer, size, file_pos)) {
progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
if (reloading)
progbar = delayed_create_progress_dlg(cf->window, "Reloading", name_ptr,
@@ -612,19 +619,19 @@ cf_read(capture_file *cf, gboolean reloading)
TRUE, &cf->stop_flag, &start_time, progbar_val);
}
- /* 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 (file_pos >= progbar_nextstep) {
- if (progbar != NULL) {
- progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
- /* update the packet bar content on the first run or frequently on very large files */
- update_progress_dlg(progbar, progbar_val, status_str);
- packets_bar_update();
- }
- progbar_nextstep += progbar_quantum;
+ /*
+ * Update the progress bar, but do it only after
+ * PROGBAR_UPDATE_INTERVAL has elapsed. Calling update_progress_dlg
+ * and packets_bar_update will likely trigger UI paint events, which
+ * might take a while depending on the platform and display. Reset
+ * our timer *after* painting.
+ */
+ if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
+ progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
+ /* update the packet bar content on the first run or frequently on very large files */
+ update_progress_dlg(progbar, progbar_val, status_str);
+ packets_bar_update();
+ g_timer_start(prog_timer);
}
}
@@ -667,6 +674,7 @@ cf_read(capture_file *cf, gboolean reloading)
/* We're done reading the file; destroy the progress bar if it was created. */
if (progbar != NULL)
destroy_progress_dlg(progbar);
+ g_timer_destroy(prog_timer);
/* We're done reading sequentially through the file. */
cf->state = FILE_READ_DONE;
@@ -1222,10 +1230,9 @@ read_packet(capture_file *cf, dfilter_t *dfcode, epan_dissect_t *edt,
typedef struct _callback_data_t {
gint64 f_len;
- gint64 progbar_nextstep;
- gint64 progbar_quantum;
GTimeVal start_time;
progdlg_t *progbar;
+ GTimer *prog_timer;
gboolean stop_flag;
} callback_data_t;
@@ -1255,9 +1262,8 @@ merge_callback(merge_event event, int num _U_,
for (i = 0; i < in_file_count; i++)
cb_data->f_len += in_files[i].size;
- /* When we reach the value that triggers a progress bar update,
- bump that value by this amount. */
- cb_data->progbar_quantum = cb_data->f_len / N_PROGBAR_UPDATES;
+ cb_data->prog_timer = g_timer_new();
+ g_timer_start(cb_data->prog_timer);
g_get_current_time(&cb_data->start_time);
break;
@@ -1281,12 +1287,14 @@ merge_callback(merge_event event, int num _U_,
FALSE, &cb_data->stop_flag, &cb_data->start_time, 0.0f);
}
- /* 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 (data_offset >= cb_data->progbar_nextstep) {
+ /*
+ * Update the progress bar, but do it only after
+ * PROGBAR_UPDATE_INTERVAL has elapsed. Calling update_progress_dlg
+ * and packets_bar_update will likely trigger UI paint events, which
+ * might take a while depending on the platform and display. Reset
+ * our timer *after* painting.
+ */
+ if (g_timer_elapsed(cb_data->prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
float progbar_val;
gint64 file_pos = 0;
/* Get the sum of the seek positions in all of the files. */
@@ -1308,7 +1316,7 @@ merge_callback(merge_event event, int num _U_,
file_pos / 1024, cb_data->f_len / 1024);
update_progress_dlg(cb_data->progbar, progbar_val, status_str);
}
- cb_data->progbar_nextstep += cb_data->progbar_quantum;
+ g_timer_start(cb_data->prog_timer);
}
}
break;
@@ -1317,6 +1325,7 @@ merge_callback(merge_event event, int num _U_,
/* We're done merging the files; destroy the progress bar if it was created. */
if (cb_data->progbar != NULL)
destroy_progress_dlg(cb_data->progbar);
+ g_timer_destroy(cb_data->prog_timer);
break;
}
@@ -1564,6 +1573,7 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, gb
guint32 framenum;
frame_data *fdata;
progdlg_t *progbar = NULL;
+ GTimer *prog_timer = g_timer_new();
int count;
frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
int selected_frame_num, preceding_frame_num, following_frame_num, prev_frame_num;
@@ -1571,8 +1581,6 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, gb
float progbar_val;
GTimeVal start_time;
gchar status_str[100];
- int progbar_nextstep;
- int progbar_quantum;
epan_dissect_t edt;
dfilter_t *dfcode;
column_info *cinfo;
@@ -1659,11 +1667,7 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, gb
cf_callback_invoke(cf_cb_file_rescan_started, cf);
- /* 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 = cf->count/N_PROGBAR_UPDATES;
+ g_timer_start(prog_timer);
/* Count of packets at which we've looked. */
count = 0;
/* Progress so far. */
@@ -1701,12 +1705,13 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, gb
&start_time,
progbar_val);
- /* 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) {
+ /*
+ * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
+ * has elapsed. Calling update_progress_dlg and packets_bar_update will
+ * likely trigger UI paint events, which might take a while depending on
+ * the platform and display. Reset our timer *after* painting.
+ */
+ if (g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
/* let's not divide by zero. I should never be started
* with count == 0, so let's assert that
*/
@@ -1719,7 +1724,7 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, gb
update_progress_dlg(progbar, progbar_val, status_str);
}
- progbar_nextstep += progbar_quantum;
+ g_timer_start(prog_timer);
}
if (cf->stop_flag) {
@@ -1814,6 +1819,7 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, gb
was created. */
if (progbar != NULL)
destroy_progress_dlg(progbar);
+ g_timer_destroy(prog_timer);
/* Unfreeze the packet list. */
if (!add_to_packet_list)
@@ -1992,23 +1998,18 @@ process_specified_records(capture_file *cf, packet_range_t *range,
psp_return_t ret = PSP_FINISHED;
progdlg_t *progbar = NULL;
+ GTimer *prog_timer = g_timer_new();
int progbar_count;
float progbar_val;
GTimeVal progbar_start_time;
gchar progbar_status_str[100];
- int progbar_nextstep;
- int progbar_quantum;
range_process_e process_this;
struct wtap_pkthdr phdr;
wtap_phdr_init(&phdr);
ws_buffer_init(&buf, 1500);
- /* 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 = cf->count/N_PROGBAR_UPDATES;
+ g_timer_start(prog_timer);
/* Count of packets at which we've looked. */
progbar_count = 0;
/* Progress so far. */
@@ -2037,25 +2038,24 @@ process_specified_records(capture_file *cf, packet_range_t *range,
&progbar_start_time,
progbar_val);
- /* 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 (progbar_count >= progbar_nextstep) {
+ /*
+ * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
+ * has elapsed. Calling update_progress_dlg and packets_bar_update will
+ * likely trigger UI paint events, which might take a while depending on
+ * the platform and display. Reset our timer *after* painting.
+ */
+ if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
/* let's not divide by zero. I should never be started
* with count == 0, so let's assert that
*/
g_assert(cf->count > 0);
progbar_val = (gfloat) progbar_count / cf->count;
- if (progbar != NULL) {
- g_snprintf(progbar_status_str, sizeof(progbar_status_str),
- "%4u of %u packets", progbar_count, cf->count);
- update_progress_dlg(progbar, progbar_val, progbar_status_str);
- }
+ g_snprintf(progbar_status_str, sizeof(progbar_status_str),
+ "%4u of %u packets", progbar_count, cf->count);
+ update_progress_dlg(progbar, progbar_val, progbar_status_str);
- progbar_nextstep += progbar_quantum;
+ g_timer_start(prog_timer);
}
if (cf->stop_flag) {
@@ -2098,6 +2098,7 @@ process_specified_records(capture_file *cf, packet_range_t *range,
it was created. */
if (progbar != NULL)
destroy_progress_dlg(progbar);
+ g_timer_destroy(prog_timer);
wtap_phdr_cleanup(&phdr);
ws_buffer_free(&buf);
@@ -3438,13 +3439,12 @@ find_packet(capture_file *cf,
frame_data *fdata;
frame_data *new_fd = NULL;
progdlg_t *progbar = NULL;
+ GTimer *prog_timer = g_timer_new();
int count;
gboolean found;
float progbar_val;
GTimeVal start_time;
gchar status_str[100];
- int progbar_nextstep;
- int progbar_quantum;
const char *title;
match_result result;
@@ -3456,11 +3456,7 @@ find_packet(capture_file *cf,
count = 0;
framenum = start_fd->num;
- /* 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 = cf->count/N_PROGBAR_UPDATES;
+ g_timer_start(prog_timer);
/* Progress so far. */
progbar_val = 0.0f;
@@ -3478,12 +3474,13 @@ find_packet(capture_file *cf,
progbar = delayed_create_progress_dlg(cf->window, "Searching", title,
FALSE, &cf->stop_flag, &start_time, progbar_val);
- /* 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) {
+ /*
+ * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
+ * has elapsed. Calling update_progress_dlg and packets_bar_update will
+ * likely trigger UI paint events, which might take a while depending on
+ * the platform and display. Reset our timer *after* painting.
+ */
+ if (g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
/* let's not divide by zero. I should never be started
* with count == 0, so let's assert that
*/
@@ -3491,13 +3488,11 @@ find_packet(capture_file *cf,
progbar_val = (gfloat) count / cf->count;
- if (progbar != NULL) {
- g_snprintf(status_str, sizeof(status_str),
- "%4u of %u packets", count, cf->count);
- update_progress_dlg(progbar, progbar_val, status_str);
- }
+ g_snprintf(status_str, sizeof(status_str),
+ "%4u of %u packets", count, cf->count);
+ update_progress_dlg(progbar, progbar_val, status_str);
- progbar_nextstep += progbar_quantum;
+ g_timer_start(prog_timer);
}
if (cf->stop_flag) {
@@ -3578,6 +3573,7 @@ find_packet(capture_file *cf,
was created. */
if (progbar != NULL)
destroy_progress_dlg(progbar);
+ g_timer_destroy(prog_timer);
}
if (new_fd != NULL) {
@@ -4279,12 +4275,11 @@ rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
gchar *name_ptr;
gint64 data_offset;
progdlg_t *progbar = NULL;
+ GTimer *prog_timer = g_timer_new();
gint64 size;
float progbar_val;
GTimeVal start_time;
gchar status_str[100];
- gint64 progbar_nextstep;
- gint64 progbar_quantum;
guint32 framenum;
frame_data *fdata;
int count = 0;
@@ -4341,16 +4336,7 @@ rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
/* Find the size of the file. */
size = wtap_file_size(cf->wth, NULL);
- /* 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. */
- if (size >= 0) {
- progbar_quantum = size/N_PROGBAR_UPDATES;
- if (progbar_quantum < MIN_QUANTUM)
- progbar_quantum = MIN_QUANTUM;
- }else
- progbar_quantum = 0;
+ g_timer_start(prog_timer);
cf->stop_flag = FALSE;
g_get_current_time(&start_time);
@@ -4365,28 +4351,25 @@ rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
count++;
cf->f_datalen = wtap_read_so_far(cf->wth);
- /* Create the progress bar if necessary.
- * Check whether it should be created or not every MIN_NUMBER_OF_PACKET
- */
- if ((progbar == NULL) && !(count % MIN_NUMBER_OF_PACKET)) {
+ /* Create the progress bar if necessary. */
+ if (progress_is_slow(progbar, prog_timer, size, cf->f_datalen)) {
progbar_val = calc_progbar_val(cf, size, cf->f_datalen, status_str, sizeof(status_str));
progbar = delayed_create_progress_dlg(cf->window, "Rescanning", name_ptr,
TRUE, &cf->stop_flag, &start_time, progbar_val);
}
- /* 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 (cf->f_datalen >= progbar_nextstep) {
- if (progbar != NULL) {
- progbar_val = calc_progbar_val(cf, size, cf->f_datalen, status_str, sizeof(status_str));
- /* update the packet bar content on the first run or frequently on very large files */
- update_progress_dlg(progbar, progbar_val, status_str);
- packets_bar_update();
- }
- progbar_nextstep += progbar_quantum;
+ /*
+ * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
+ * has elapsed. Calling update_progress_dlg and packets_bar_update will
+ * likely trigger UI paint events, which might take a while depending on
+ * the platform and display. Reset our timer *after* painting.
+ */
+ if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
+ progbar_val = calc_progbar_val(cf, size, cf->f_datalen, status_str, sizeof(status_str));
+ /* update the packet bar content on the first run or frequently on very large files */
+ update_progress_dlg(progbar, progbar_val, status_str);
+ packets_bar_update();
+ g_timer_start(prog_timer);
}
}
@@ -4412,6 +4395,7 @@ rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
/* We're done reading the file; destroy the progress bar if it was created. */
if (progbar != NULL)
destroy_progress_dlg(progbar);
+ g_timer_destroy(prog_timer);
/* We're done reading sequentially through the file. */
cf->state = FILE_READ_DONE;
diff --git a/ui/qt/progress_frame.cpp b/ui/qt/progress_frame.cpp
index 98c0e7c2c1..b8e07c11fe 100644
--- a/ui/qt/progress_frame.cpp
+++ b/ui/qt/progress_frame.cpp
@@ -27,7 +27,6 @@
#include "ui/progress_dlg.h"
#include <QDialogButtonBox>
-#include <QElapsedTimer>
#include <QGraphicsOpacityEffect>
#include <QBoxLayout>
#include <QPropertyAnimation>
@@ -77,13 +76,10 @@ delayed_create_progress_dlg(gpointer top_level_window, const gchar *task_title,
/*
* Update the progress information of the progress bar box.
*/
-static const int app_update_freq_ = 100; // ms
void
update_progress_dlg(progdlg_t *dlg, gfloat percentage, const gchar *)
{
if (!dlg) return;
- if (dlg->elapsed_timer->isValid() && !dlg->elapsed_timer->hasExpired(app_update_freq_)) return;
- dlg->elapsed_timer->restart();
dlg->progress_frame->setValue(percentage * 100);
@@ -123,7 +119,6 @@ ProgressFrame::ProgressFrame(QWidget *parent) :
ui->setupUi(this);
progress_dialog_.progress_frame = this;
- progress_dialog_.elapsed_timer = new QElapsedTimer();
progress_dialog_.top_level_window = window();
ui->progressBar->setStyleSheet(QString(
@@ -164,14 +159,12 @@ ProgressFrame::ProgressFrame(QWidget *parent) :
ProgressFrame::~ProgressFrame()
{
delete ui;
- delete progress_dialog_.elapsed_timer;
}
struct progdlg *ProgressFrame::showProgress(bool animate, bool terminate_is_stop, gboolean *stop_flag, int value)
{
setMaximumValue(100);
ui->progressBar->setValue(value);
- progress_dialog_.elapsed_timer->invalidate();
emit showRequested(animate, terminate_is_stop, stop_flag);
return &progress_dialog_;
}
@@ -265,7 +258,6 @@ void ProgressFrame::timerEvent(QTimerEvent *event)
void ProgressFrame::hide()
{
- progress_dialog_.elapsed_timer->invalidate();
#if !defined(Q_OS_MAC) || QT_VERSION > QT_VERSION_CHECK(5, 0, 0)
show_timer_ = -1;
#endif
diff --git a/ui/qt/progress_frame.h b/ui/qt/progress_frame.h
index 719af1484b..b2816c64ca 100644
--- a/ui/qt/progress_frame.h
+++ b/ui/qt/progress_frame.h
@@ -44,7 +44,6 @@ class QPropertyAnimation;
// Define the structure describing a progress dialog.
struct progdlg {
ProgressFrame *progress_frame; // This progress frame
- QElapsedTimer *elapsed_timer; // Application event processing
QWidget *top_level_window; // Progress frame's main window
};