wimsplit now prints progress messages regularly rather than just once
per WIM part.
+ Progress messages for data processing are now printed at a consistent
+ rate based on time elapsed. This avoids cases where the messages could
+ be printed too quickly or too slowly.
+
Added support for a data recovery mode which causes files to be
extracted even if they are corrupted. The option is --recover-data for
wimapply and wimextract, and WIMLIB_EXTRACT_FLAG_RECOVER_DATA for the
/* The members below should not be used outside of extract.c */
const struct apply_operations *apply_ops;
- u64 next_progress;
+ u64 last_progress_time;
unsigned long invalid_sequence;
unsigned long num_blobs_remaining;
struct list_head blob_list;
#include "wimlib.h"
#include "wimlib/paths.h"
+#include "wimlib/timestamp.h"
#include "wimlib/types.h"
/* If specified, call the user-provided progress function and check its result.
report_error(wimlib_progress_func_t progfunc,
void *progctx, int error_code, const tchar *path);
-/* Rate-limiting of byte-count based progress messages: update *next_progress_p
- * to the value that completed_bytes needs to reach before the next progress
- * message will be sent. */
-static inline void
-set_next_progress(u64 completed_bytes, u64 total_bytes, u64 *next_progress_p)
+/* Rate-limiting of byte-count based progress messages. We update the progress
+ * at most 5 times per second. */
+static inline bool
+should_update_progress(u64 completed_bytes, u64 total_bytes,
+ u64 *last_progress_time)
{
- if (*next_progress_p < total_bytes) {
- /*
- * Send the next message as soon as:
- * - another 1/128 of the total has been processed;
- * - OR another 5000000 bytes have been processed;
- * - OR all bytes have been processed.
- */
- *next_progress_p = min(min(completed_bytes + total_bytes / 128,
- completed_bytes + 5000000),
- total_bytes);
- } else {
- /* Last message has been sent. */
- *next_progress_p = ~0;
- }
+ u64 now = now_as_wim_timestamp();
+
+ if (completed_bytes < total_bytes &&
+ now - *last_progress_time < 200 * TICKS_PER_MILLISECOND)
+ return false;
+
+ *last_progress_time = now;
+ return true;
}
/* Windows: temporarily remove the stream name from the path */
#include "wimlib/types.h"
+/*
+ * Timestamps in WIM files are Windows NT timestamps, or FILETIMEs: 64-bit
+ * values storing the number of 100-nanosecond ticks since January 1, 1601.
+ *
+ * Note: UNIX timestamps are signed; Windows timestamps are not. Negative UNIX
+ * timestamps represent times before 1970-01-01. When such a timestamp is
+ * converted to a Windows timestamp, we can preserve the correct date provided
+ * that it is not also before 1601-01-01.
+ */
+
+#define NANOSECONDS_PER_TICK 100
+#define TICKS_PER_SECOND (1000000000 / NANOSECONDS_PER_TICK)
+#define TICKS_PER_MILLISECOND (TICKS_PER_SECOND / 1000)
+#define TICKS_PER_MICROSECOND (TICKS_PER_SECOND / 1000000)
+
+/*
+ * EPOCH_DISTANCE is the number of seconds separating the Windows NT and UNIX
+ * epochs. This is equal to ((1970-1601)*365+89)*24*60*60. 89 is the number
+ * of leap years between 1970 and 1601.
+ */
+#define EPOCH_DISTANCE 11644473600
+
struct wimlib_timespec;
extern time_t
}
}
}
- if (progress->extract.completed_bytes >= ctx->next_progress) {
-
+ if (should_update_progress(progress->extract.completed_bytes,
+ progress->extract.total_bytes,
+ &ctx->last_progress_time)) {
ret = extract_progress(ctx, WIMLIB_PROGRESS_MSG_EXTRACT_STREAMS);
if (ret)
return ret;
-
- set_next_progress(progress->extract.completed_bytes,
- progress->extract.total_bytes,
- &ctx->next_progress);
}
if (unlikely(filedes_valid(&ctx->tmpfile_fd))) {
#include "wimlib.h" /* for struct wimlib_timespec */
#include "wimlib/timestamp.h"
-/*
- * Timestamps in WIM files are Windows NT timestamps, or FILETIMEs: 64-bit
- * values storing the number of 100-nanosecond ticks since January 1, 1601.
- *
- * Note: UNIX timestamps are signed; Windows timestamps are not. Negative UNIX
- * timestamps represent times before 1970-01-01. When such a timestamp is
- * converted to a Windows timestamp, we can preserve the correct date provided
- * that it is not also before 1601-01-01.
- */
-
-#define NANOSECONDS_PER_TICK 100
-#define TICKS_PER_SECOND (1000000000 / NANOSECONDS_PER_TICK)
-#define TICKS_PER_MICROSECOND (TICKS_PER_SECOND / 1000000)
-
-/*
- * EPOCH_DISTANCE is the number of seconds separating the Windows NT and UNIX
- * epochs. This is equal to ((1970-1601)*365+89)*24*60*60. 89 is the number
- * of leap years between 1970 and 1601.
- */
-#define EPOCH_DISTANCE 11644473600
-
/* Windows NT timestamps to UNIX timestamps */
time_t
wimlib_progress_func_t progfunc;
void *progctx;
union wimlib_progress_info *progress;
- u64 next_progress;
+ u64 last_progress_time;
};
static int
progress->verify_streams.completed_bytes += size;
- if (progress->verify_streams.completed_bytes >= ctx->next_progress) {
-
+ if (should_update_progress(progress->verify_streams.completed_bytes,
+ progress->verify_streams.total_bytes,
+ &ctx->last_progress_time)) {
int ret = call_progress(ctx->progfunc,
WIMLIB_PROGRESS_MSG_VERIFY_STREAMS,
progress, ctx->progctx);
if (ret)
return ret;
-
- set_next_progress(progress->verify_streams.completed_bytes,
- progress->verify_streams.total_bytes,
- &ctx->next_progress);
}
return 0;
}
ctx.progfunc = wim->progfunc;
ctx.progctx = wim->progctx;
ctx.progress = &progress;
- ctx.next_progress = 0;
+ ctx.last_progress_time = 0;
ret = call_progress(ctx.progfunc, WIMLIB_PROGRESS_MSG_VERIFY_STREAMS,
ctx.progress, ctx.progctx);
wimlib_progress_func_t progfunc;
void *progctx;
union wimlib_progress_info progress;
- u64 next_progress;
+ u64 last_progress_time;
};
static int
if (discarded) {
progress->write_streams.total_bytes -= complete_size;
progress->write_streams.total_streams -= complete_count;
- if (progress_data->next_progress != ~(u64)0 &&
- progress_data->next_progress > progress->write_streams.total_bytes)
- {
- progress_data->next_progress = progress->write_streams.total_bytes;
- }
} else {
progress->write_streams.completed_bytes += complete_size;
progress->write_streams.completed_compressed_bytes +=
progress->write_streams.completed_streams += complete_count;
}
- if (progress->write_streams.completed_bytes >= progress_data->next_progress) {
-
+ if (should_update_progress(progress->write_streams.completed_bytes,
+ progress->write_streams.total_bytes,
+ &progress_data->last_progress_time)) {
ret = call_progress(progress_data->progfunc,
WIMLIB_PROGRESS_MSG_WRITE_STREAMS,
progress,
progress_data->progctx);
if (ret)
return ret;
-
- set_next_progress(progress->write_streams.completed_bytes,
- progress->write_streams.total_bytes,
- &progress_data->next_progress);
}
return 0;
}
ctx->progress_data.progress.write_streams.compression_type = ctx->out_ctype;
ctx->progress_data.progress.write_streams.total_parts = total_parts;
ctx->progress_data.progress.write_streams.completed_parts = 0;
- ctx->progress_data.next_progress = 0;
+ ctx->progress_data.last_progress_time = 0;
return 0;
}