wimsplit only prints a progress message when starting each WIM part.
That could be very infrequently since each part could be gigabytes.
Fix it to update the progress regularly as data is written, like the
other wimlib-imagex commands do.
This required changing the library to report
WIMLIB_PROGRESS_MSG_WRITE_STREAMS messages from wimlib_split() and
include the completed compressed size in them.
Reported at https://www.reddit.com/r/pcmasterrace/comments/hagu4k/wimlibimagex_split_stuck_at_0
* to ::wimlib_progress_info.write_streams. This message may be
* received many times while the WIM file is being written or appended
* to with wimlib_write(), wimlib_overwrite(), or wimlib_write_to_fd().
- */
+ * Since wimlib v1.13.4 it will also be received when a split WIM part
+ * is being written by wimlib_split(). */
WIMLIB_PROGRESS_MSG_WRITE_STREAMS = 12,
/** Per-image metadata is about to be written to the WIM file. @p info
/** The number of bytes of file data that have been written so
* far. This starts at 0 and ends at @p total_bytes. This
* number is the uncompressed size; the actual size may be lower
- * due to compression. */
+ * due to compression. See @p completed_compressed_bytes for
+ * the compressed size. */
uint64_t completed_bytes;
/** The number of distinct file data "blobs" that have been
/** This is currently broken and will always be 0. */
uint32_t completed_parts;
+
+ /** Since wimlib v1.13.4: Like @p completed_bytes, but counts
+ * the compressed size. */
+ uint64_t completed_compressed_bytes;
} write_streams;
/** Valid on messages ::WIMLIB_PROGRESS_MSG_SCAN_BEGIN,
* If a progress function is registered with @p wim, then for each split WIM
* part that is written it will receive the messages
* ::WIMLIB_PROGRESS_MSG_SPLIT_BEGIN_PART and
- * ::WIMLIB_PROGRESS_MSG_SPLIT_END_PART.
+ * ::WIMLIB_PROGRESS_MSG_SPLIT_END_PART. Since wimlib v1.13.4 it will also
+ * receive ::WIMLIB_PROGRESS_MSG_WRITE_STREAMS messages while writing each part;
+ * these messages will report the progress of the current part only.
*/
extern int
wimlib_split(WIMStruct *wim,
last_scan_progress = *scan;
}
}
+
+static struct wimlib_progress_info_split last_split_progress;
+
+static void
+report_split_progress(uint64_t bytes_completed_in_part)
+{
+ uint64_t completed_bytes = last_split_progress.completed_bytes +
+ bytes_completed_in_part;
+ unsigned percent_done = TO_PERCENT(completed_bytes,
+ last_split_progress.total_bytes);
+ unsigned unit_shift;
+ const tchar *unit_name;
+
+ unit_shift = get_unit(last_split_progress.total_bytes, &unit_name);
+ imagex_printf(T("\rSplitting WIM: %"PRIu64" %"TS" of "
+ "%"PRIu64" %"TS" (%u%%) written, part %u of %u"),
+ completed_bytes >> unit_shift,
+ unit_name,
+ last_split_progress.total_bytes >> unit_shift,
+ unit_name,
+ percent_done,
+ last_split_progress.cur_part_number,
+ last_split_progress.total_parts);
+}
+
/* Progress callback function passed to various wimlib functions. */
static enum wimlib_progress_status
imagex_progress_func(enum wimlib_progress_msg msg,
switch (msg) {
case WIMLIB_PROGRESS_MSG_WRITE_STREAMS:
+ if (last_split_progress.total_bytes != 0) {
+ /* wimlib_split() in progress; use the split-specific
+ * progress message. */
+ report_split_progress(info->write_streams.completed_compressed_bytes);
+ break;
+ }
{
static bool started;
if (!started) {
}
break;
case WIMLIB_PROGRESS_MSG_SPLIT_BEGIN_PART:
- percent_done = TO_PERCENT(info->split.completed_bytes,
- info->split.total_bytes);
- unit_shift = get_unit(info->split.total_bytes, &unit_name);
- imagex_printf(T("Writing \"%"TS"\" (part %u of %u): %"PRIu64" %"TS" of "
- "%"PRIu64" %"TS" (%u%%) written\n"),
- info->split.part_name,
- info->split.cur_part_number,
- info->split.total_parts,
- info->split.completed_bytes >> unit_shift,
- unit_name,
- info->split.total_bytes >> unit_shift,
- unit_name,
- percent_done);
- break;
case WIMLIB_PROGRESS_MSG_SPLIT_END_PART:
- if (info->split.completed_bytes == info->split.total_bytes) {
- imagex_printf(T("Finished writing split WIM part %u of %u\n"),
- info->split.cur_part_number,
- info->split.total_parts);
- }
+ last_split_progress = info->split;
+ report_split_progress(0);
break;
case WIMLIB_PROGRESS_MSG_UPDATE_END_COMMAND:
switch (info->update.command->op) {
goto out;
ret = wimlib_split(wim, argv[1], part_size, write_flags);
+ tprintf(T("\nFinished splitting \"%"TS"\"\n"), argv[0]);
wimlib_free(wim);
out:
return ret;
for (part_number = 1; part_number <= swm_info->num_parts; part_number++) {
int part_write_flags;
- wimlib_progress_func_t progfunc;
if (part_number != 1) {
tsprintf(swm_name_buf + swm_base_name_len,
if (part_number != 1)
part_write_flags |= WIMLIB_WRITE_FLAG_NO_METADATA;
- progfunc = orig_wim->progfunc;
- orig_wim->progfunc = NULL;
ret = write_wim_part(orig_wim,
progress.split.part_name,
WIMLIB_ALL_IMAGES,
swm_info->num_parts,
&swm_info->parts[part_number - 1].blob_list,
guid);
- orig_wim->progfunc = progfunc;
if (ret)
return ret;
static int
do_write_blobs_progress(struct write_blobs_progress_data *progress_data,
- u64 complete_size, u32 complete_count, bool discarded)
+ u64 complete_size, u64 complete_compressed_size,
+ u32 complete_count, bool discarded)
{
union wimlib_progress_info *progress = &progress_data->progress;
int ret;
}
} else {
progress->write_streams.completed_bytes += complete_size;
+ progress->write_streams.completed_compressed_bytes +=
+ complete_compressed_size;
progress->write_streams.completed_streams += complete_count;
}
* output reference count to the duplicate blob
* in the former case. */
ret = do_write_blobs_progress(&ctx->progress_data,
- blob->size, 1, true);
+ blob->size,
+ blob->size,
+ 1, true);
list_del(&blob->write_blobs_list);
list_del(&blob->blob_table_list);
if (new_blob->will_be_in_output_wim)
{
int ret;
struct blob_descriptor *blob;
- u32 completed_blob_count;
- u32 completed_size;
+ u32 completed_blob_count = 0;
blob = list_entry(ctx->blobs_being_compressed.next,
struct blob_descriptor, write_blobs_list);
ctx->cur_write_blob_offset += usize;
- completed_size = usize;
- completed_blob_count = 0;
if (ctx->write_resource_flags & WRITE_RESOURCE_FLAG_SOLID) {
/* Wrote chunk in solid mode. It may have finished multiple
* blobs. */
}
}
- return do_write_blobs_progress(&ctx->progress_data, completed_size,
+ return do_write_blobs_progress(&ctx->progress_data, usize, csize,
completed_blob_count, false);
write_error:
blob->rdesc->raw_copy_ok = 1;
list_for_each_entry(blob, raw_copy_blobs, write_blobs_list) {
+ u64 compressed_size = 0;
+
if (blob->rdesc->raw_copy_ok) {
/* Write each solid resource only one time. */
ret = write_raw_copy_resource(blob->rdesc, out_fd);
if (ret)
return ret;
blob->rdesc->raw_copy_ok = 0;
+ compressed_size = blob->rdesc->size_in_wim;
}
ret = do_write_blobs_progress(progress_data, blob->size,
- 1, false);
+ compressed_size, 1, false);
if (ret)
return ret;
}