File copy/move: make ETA accurate.

* (progress_update_one): update total progress bytes counter. Update
    progress info in the progress window only if file was processed
    successfully. Don't check buttons here.
  * (move_file_file): update progress info if file move wasn't aborted.
  * (copy_file_file): update progress info if stat() or open() failed
    (file size is unknown, but file counter shoud be updated). Modify
    caclulation and display of byte counters.
  * (panel_operate): simplify files processing loop. Remove action that
    already done via operate_one_file() call.

Signed-off-by: Andrew Borodin <aborodin@vmail.ru>
This commit is contained in:
Andrew Borodin 2024-09-21 13:04:26 +03:00
parent ff1a404bb3
commit 1e35ae3adb

View File

@ -812,32 +812,32 @@ panel_operate_init_totals (const WPanel *panel, const vfs_path_t *source,
/* --------------------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------------------- */
static FileProgressStatus static void
progress_update_one (file_op_context_t *ctx, off_t add) progress_update_one (gboolean success, file_op_context_t *ctx, off_t add)
{ {
gint64 tv_current; gint64 tv_current;
static gint64 tv_start = -1; static gint64 tv_start = -1;
ctx->total_progress_count++; ctx->total_progress_count++;
ctx->progress_bytes += (uintmax_t) add; ctx->total_progress_bytes += (uintmax_t) add;
if (!success)
return;
tv_current = g_get_monotonic_time (); tv_current = g_get_monotonic_time ();
if (tv_start < 0) if (tv_start < 0)
tv_start = tv_current; tv_start = tv_current;
else if (tv_current - tv_start > FILEOP_UPDATE_INTERVAL_US)
if (tv_current - tv_start > FILEOP_UPDATE_INTERVAL_US)
{ {
if (verbose && ctx->dialog_type == FILEGUI_DIALOG_MULTI_ITEM) if (verbose && ctx->dialog_type == FILEGUI_DIALOG_MULTI_ITEM)
{ {
file_progress_show_count (ctx); file_progress_show_count (ctx);
file_progress_show_total (ctx, ctx->progress_bytes, tv_current, TRUE); file_progress_show_total (ctx, ctx->total_progress_bytes, tv_current, TRUE);
} }
tv_start = tv_current; tv_start = tv_current;
} }
return file_progress_check_buttons (ctx);
} }
/* --------------------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------------------- */
@ -1217,7 +1217,7 @@ move_file_file (const WPanel *panel, file_op_context_t *ctx, const char *s, cons
if (file_progress_check_buttons (ctx) == FILE_ABORT) if (file_progress_check_buttons (ctx) == FILE_ABORT)
{ {
return_status = FILE_ABORT; return_status = FILE_ABORT;
goto ret; goto ret_fast;
} }
mc_refresh (); mc_refresh ();
@ -1280,11 +1280,7 @@ move_file_file (const WPanel *panel, file_op_context_t *ctx, const char *s, cons
} }
if (mc_rename (src_vpath, dst_vpath) == 0) if (mc_rename (src_vpath, dst_vpath) == 0)
{
/* FIXME: do we really need to update progress in case of single file? */
return_status = progress_update_one (ctx, src_stat.st_size);
goto ret; goto ret;
}
} }
#if 0 #if 0
/* Comparison to EXDEV seems not to work in nfs if you're moving from /* Comparison to EXDEV seems not to work in nfs if you're moving from
@ -1320,7 +1316,7 @@ move_file_file (const WPanel *panel, file_op_context_t *ctx, const char *s, cons
panel_operate_init_totals (panel, src_vpath, &src_stat, ctx, TRUE, panel_operate_init_totals (panel, src_vpath, &src_stat, ctx, TRUE,
FILEGUI_DIALOG_ONE_ITEM); FILEGUI_DIALOG_ONE_ITEM);
if (return_status != FILE_CONT) if (return_status != FILE_CONT)
goto ret; goto ret_fast;
} }
old_ask_overwrite = ctx->ask_overwrite; old_ask_overwrite = ctx->ask_overwrite;
@ -1342,19 +1338,24 @@ move_file_file (const WPanel *panel, file_op_context_t *ctx, const char *s, cons
return_status = file_progress_check_buttons (ctx); return_status = file_progress_check_buttons (ctx);
if (return_status != FILE_CONT) if (return_status != FILE_CONT)
goto ret; goto ret_fast;
} }
mc_refresh (); mc_refresh ();
retry_src_remove: retry_src_remove:
if (!try_remove_file (ctx, src_vpath, &return_status) && panel == NULL) if (!try_remove_file (ctx, src_vpath, &return_status) && panel == NULL)
goto ret; goto ret_fast;
if (!copy_done)
return_status = progress_update_one (ctx, src_stat.st_size);
ret: ret:
if (return_status != FILE_ABORT)
{
/* if copy_done == TRUE, progress_update_one() was called in copy_file_file() */
if (!copy_done)
progress_update_one (TRUE, ctx, src_stat.st_size);
return_status = file_progress_check_buttons (ctx);
}
ret_fast:
vfs_path_free (src_vpath, TRUE); vfs_path_free (src_vpath, TRUE);
vfs_path_free (dst_vpath, TRUE); vfs_path_free (dst_vpath, TRUE);
@ -2320,9 +2321,19 @@ copy_file_file (file_op_context_t *ctx, const char *src_path, const char *dst_pa
} }
if (return_status != FILE_RETRY) if (return_status != FILE_RETRY)
{
/* unknown size */
progress_update_one (FALSE, ctx, 0);
goto ret_fast; goto ret_fast;
}
} }
/* After ctx->stat_func() */
src_mode = src_stat.st_mode;
src_uid = src_stat.st_uid;
src_gid = src_stat.st_gid;
file_size = src_stat.st_size;
while (attrs_ok && mc_fgetflags (src_vpath, &attrs) != 0) while (attrs_ok && mc_fgetflags (src_vpath, &attrs) != 0)
{ {
attrs_ok = FALSE; attrs_ok = FALSE;
@ -2520,7 +2531,7 @@ copy_file_file (file_op_context_t *ctx, const char *src_path, const char *dst_pa
ctx->ignore_all = TRUE; ctx->ignore_all = TRUE;
ctx->do_append = FALSE; ctx->do_append = FALSE;
} }
goto ret_fast; goto ret;
} }
if (ctx->do_reget != 0 && mc_lseek (src_desc, ctx->do_reget, SEEK_SET) != ctx->do_reget) if (ctx->do_reget != 0 && mc_lseek (src_desc, ctx->do_reget, SEEK_SET) != ctx->do_reget)
@ -2546,6 +2557,7 @@ copy_file_file (file_op_context_t *ctx, const char *src_path, const char *dst_pa
goto ret; goto ret;
} }
/* After mc_fstat() */
src_mode = src_stat.st_mode; src_mode = src_stat.st_mode;
src_uid = src_stat.st_uid; src_uid = src_stat.st_uid;
src_gid = src_stat.st_gid; src_gid = src_stat.st_gid;
@ -2737,7 +2749,7 @@ copy_file_file (file_op_context_t *ctx, const char *src_path, const char *dst_pa
} }
} }
ctx->total_progress_bytes = ctx->progress_bytes + file_part + ctx->do_reget; ctx->progress_bytes = file_part + ctx->do_reget;
const gint64 usecs = tv_current - tv_last_update; const gint64 usecs = tv_current - tv_last_update;
@ -2758,13 +2770,12 @@ copy_file_file (file_op_context_t *ctx, const char *src_path, const char *dst_pa
const char *stalled_msg = const char *stalled_msg =
update_usecs > FILEOP_STALLING_INTERVAL_US ? _("(stalled)") : ""; update_usecs > FILEOP_STALLING_INTERVAL_US ? _("(stalled)") : "";
file_progress_show (ctx, file_part + ctx->do_reget, file_size, stalled_msg, file_progress_show (ctx, ctx->progress_bytes, file_size, stalled_msg, force_update);
force_update);
if (ctx->dialog_type == FILEGUI_DIALOG_MULTI_ITEM) if (ctx->dialog_type == FILEGUI_DIALOG_MULTI_ITEM)
{ {
file_progress_show_count (ctx); file_progress_show_count (ctx);
file_progress_show_total (ctx, ctx->total_progress_bytes, tv_current, file_progress_show_total (ctx, ctx->total_progress_bytes + ctx->progress_bytes,
force_update); tv_current, force_update);
} }
mc_refresh (); mc_refresh ();
@ -2934,8 +2945,9 @@ copy_file_file (file_op_context_t *ctx, const char *src_path, const char *dst_pa
} }
} }
progress_update_one (return_status == FILE_CONT, ctx, file_size);
if (return_status == FILE_CONT) if (return_status == FILE_CONT)
return_status = progress_update_one (ctx, file_size); return_status = file_progress_check_buttons (ctx);
ret_fast: ret_fast:
vfs_path_free (src_vpath, TRUE); vfs_path_free (src_vpath, TRUE);
@ -3608,7 +3620,6 @@ panel_operate (void *source_panel, FileOperation operation, gboolean force_singl
value = value =
panel_operate_init_totals (panel, NULL, NULL, ctx, file_op_compute_totals, dialog_type); panel_operate_init_totals (panel, NULL, NULL, ctx, file_op_compute_totals, dialog_type);
if (value == FILE_CONT) if (value == FILE_CONT)
{
/* Loop for every file, perform the actual copy operation */ /* Loop for every file, perform the actual copy operation */
for (i = 0; i < panel->dir.len; i++) for (i = 0; i < panel->dir.len; i++)
{ {
@ -3621,32 +3632,14 @@ panel_operate (void *source_panel, FileOperation operation, gboolean force_singl
src_stat = panel->dir.list[i].st; src_stat = panel->dir.list[i].st;
value = operate_one_file (panel, ctx, source2, &src_stat, dest); value = operate_one_file (panel, ctx, source2, &src_stat, dest);
if (value == FILE_ABORT) if (value == FILE_ABORT)
break; break;
if (value == FILE_CONT) if (value == FILE_CONT)
do_file_mark (panel, i, 0); do_file_mark (panel, i, 0);
if (verbose)
{
if (ctx->dialog_type == FILEGUI_DIALOG_MULTI_ITEM)
{
file_progress_show_count (ctx);
file_progress_show_total (ctx, ctx->progress_bytes, g_get_monotonic_time (),
FALSE);
}
if (operation != OP_DELETE)
file_progress_show (ctx, 0, 0, "", FALSE);
}
if (file_progress_check_buttons (ctx) == FILE_ABORT)
break;
mc_refresh (); mc_refresh ();
} /* Loop for every file */ } /* Loop for every file */
}
} /* Many entries */ } /* Many entries */
clean_up: clean_up: