diff options
author | Joseph Hunkeler <jhunkeler@gmail.com> | 2024-09-17 09:37:14 -0400 |
---|---|---|
committer | Joseph Hunkeler <jhunkeler@gmail.com> | 2024-09-18 23:08:03 -0400 |
commit | db1a3056296ea3ed13c5a425cf1f11602b43a6c7 (patch) | |
tree | 3e3ad60bb4dbdee1a37e10cb10cb3dc2f10b334c | |
parent | 0f95b43e2d3853995106c5c6aa55bf92f63fb331 (diff) | |
download | stasis-db1a3056296ea3ed13c5a425cf1f11602b43a6c7.tar.gz |
Add pool summary and elapsed time output
* Add get_task_duration()
* Add get_pool_show_summary()
* Add signaled_by member to MultiProcessingTask
* Add time_data member to MultiProcessingTask for duration tracking
-rw-r--r-- | include/multiprocessing.h | 12 | ||||
-rw-r--r-- | src/multiprocessing.c | 48 |
2 files changed, 60 insertions, 0 deletions
diff --git a/include/multiprocessing.h b/include/multiprocessing.h index 4e89722..2356403 100644 --- a/include/multiprocessing.h +++ b/include/multiprocessing.h @@ -15,9 +15,14 @@ struct MultiProcessingTask { pid_t pid; ///< Program PID pid_t parent_pid; ///< Program PID (parent process) int status; ///< Child process exit status + int signaled_by; ///< Last signal received, if any char ident[255]; ///< Identity of the pool task char log_file[255]; ///< Path to stdout/stderr log file char parent_script[PATH_MAX]; ///< Path to temporary script executing the task + struct { + struct timespec t_start; + struct timespec t_stop; + } time_data; ///< Wall-time counters }; struct MultiProcessingPool { @@ -104,6 +109,13 @@ struct MultiProcessingTask *mp_task(struct MultiProcessingPool *pool, const char int mp_pool_join(struct MultiProcessingPool *pool, size_t jobs, size_t flags); /** + * Show summary of pool tasks + * + * @pararm pool a pointer to MultiProcessingPool + */ +void mp_pool_show_summary(struct MultiProcessingPool *pool); + +/** * Release resources allocated by mp_pool_init() * * @param a pointer to MultiProcessingPool diff --git a/src/multiprocessing.c b/src/multiprocessing.c index fe15ab6..5e605a6 100644 --- a/src/multiprocessing.c +++ b/src/multiprocessing.c @@ -161,6 +161,41 @@ struct MultiProcessingTask *mp_task(struct MultiProcessingPool *pool, const char return slot; } +static void get_task_duration(struct MultiProcessingTask *task, struct timespec *result) { + struct timespec *start = &task->time_data.t_start; + struct timespec *stop = &task->time_data.t_stop; + result->tv_sec = (stop->tv_sec - start->tv_sec); + result->tv_nsec = (stop->tv_nsec - start->tv_nsec); + if (result->tv_nsec < 0) { + --result->tv_sec; + result->tv_nsec += 1000000000L; + } +} + +void mp_pool_show_summary(struct MultiProcessingPool *pool) { + print_banner("=", 79); + printf("Pool execution summary for \"%s\"\n", pool->ident); + print_banner("=", 79); + printf("STATUS PID DURATION IDENT\n"); + for (size_t i = 0; i < pool->num_used; i++) { + struct MultiProcessingTask *task = &pool->task[i]; + char status_str[10] = {0}; + if (!task->status && !task->signaled_by) { + strcpy(status_str, "DONE"); + } else if (task->signaled_by) { + strcpy(status_str, "TERM"); + } else { + strcpy(status_str, "FAIL"); + } + + struct timespec duration; + get_task_duration(task, &duration); + long diff = duration.tv_sec + duration.tv_nsec / 1000000000L; + printf("%-4s %-10d %7lds %-10s\n", status_str, task->parent_pid, diff, task->ident) ; + } + puts(""); +} + static int show_log_contents(FILE *stream, struct MultiProcessingTask *task) { FILE *fp = fopen(task->log_file, "r"); if (!fp) { @@ -189,9 +224,15 @@ int mp_pool_kill(struct MultiProcessingPool *pool, int signum) { status = kill(slot->pid, signum); if (status && errno != ESRCH) { fprintf(stderr, "Task '%s' (pid: %d) did not respond: %s\n", slot->ident, slot->pid, strerror(errno)); + } else { // Wait for process to handle the signal, then set the status accordingly if (waitpid(slot->pid, &status, 0) >= 0) { slot->signaled_by = WTERMSIG(status); + // Record the task stop time + if (clock_gettime(CLOCK_REALTIME, &slot->time_data.t_stop) < 0) { + perror("clock_gettime"); + exit(1); + } } } } @@ -273,6 +314,13 @@ int mp_pool_join(struct MultiProcessingPool *pool, size_t jobs, size_t flags) { if (show_log_contents(stdout, slot)) { perror(slot->log_file); } + + // Record the task stop time + if (clock_gettime(CLOCK_REALTIME, &slot->time_data.t_stop) < 0) { + perror("clock_gettime"); + exit(1); + } + if (status >> 8 != 0 || (status & 0xff) != 0) { fprintf(stderr, "%s Task failed\n", progress); if (flags & MP_POOL_FAIL_FAST && pool->num_used > 1) { |