// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Copyright (C) 2018-2024 Oracle.  All Rights Reserved.
 * Author: Darrick J. Wong <djwong@kernel.org>
 */
#include "xfs.h"
#include <dirent.h>
#include <pthread.h>
#include <sys/statvfs.h>
#include <time.h>
#include "libfrog/paths.h"
#include "disk.h"
#include "read_verify.h"
#include "xfs_scrub.h"
#include "common.h"
#include "counter.h"
#include "progress.h"

/*
 * Progress Tracking
 *
 * For scrub phases that expect to take a long time, this facility uses
 * the threaded counter and some phase/state information to report the
 * progress of a particular phase to stdout.  Each phase that wants
 * progress information needs to set up the tracker with an estimate of
 * the work to be done and periodic updates when work items finish.  In
 * return, the progress tracker will print a pretty progress bar and
 * twiddle to a tty, or a raw numeric output compatible with fsck -C.
 */
struct progress_tracker {
	FILE			*fp;
	const char		*tag;
	struct ptcounter	*ptc;
	uint64_t		max;
	unsigned int		phase;
	int			rshift;
	int			twiddle;
	bool			isatty;
	bool			terminate;
	pthread_t		thread;

	/* static state */
	pthread_mutex_t		lock;
	pthread_cond_t		wakeup;
};

static struct progress_tracker pt = {
	.lock			= PTHREAD_MUTEX_INITIALIZER,
	.wakeup			= PTHREAD_COND_INITIALIZER,
};

/* Add some progress. */
void
progress_add(
	uint64_t		x)
{
	if (pt.fp)
		ptcounter_add(pt.ptc, x);
}

static const char twiddles[] = "|/-\\";

static void
progress_report(
	uint64_t		sum)
{
	char			buf[81];
	int			tag_len;
	int			num_len;
	int			pbar_len;
	int			plen;

	if (!pt.fp)
		return;

	if (sum > pt.max)
		sum = pt.max;

	/* Emulate fsck machine-readable output (phase, cur, max, label) */
	if (!pt.isatty) {
		snprintf(buf, sizeof(buf), _("%u %"PRIu64" %"PRIu64" %s"),
				pt.phase, sum, pt.max, pt.tag);
		fprintf(pt.fp, "%s\n", buf);
		fflush(pt.fp);
		return;
	}

	/* Interactive twiddle progress bar. */
	if (debug) {
		num_len = snprintf(buf, sizeof(buf),
				"%c %"PRIu64"/%"PRIu64" (%.1f%%)",
				twiddles[pt.twiddle],
				sum >> pt.rshift,
				pt.max >> pt.rshift,
				100.0 * sum / pt.max);
	} else {
		num_len = snprintf(buf, sizeof(buf),
				"%c (%.1f%%)",
				twiddles[pt.twiddle],
				100.0 * sum / pt.max);
	}
	memmove(buf + sizeof(buf) - (num_len + 1), buf, num_len + 1);
	tag_len = snprintf(buf, sizeof(buf), _("Phase %u: |"), pt.phase);
	pbar_len = sizeof(buf) - (num_len + 1 + tag_len);
	plen = (int)((double)pbar_len * sum / pt.max);
	memset(buf + tag_len, '=', plen);
	memset(buf + tag_len + plen, ' ', pbar_len - plen);
	pt.twiddle = (pt.twiddle + 1) % 4;
	fprintf(pt.fp, "%c%s\r%c", START_IGNORE, buf, END_IGNORE);
	fflush(pt.fp);
}

static void *
progress_report_thread(void *arg)
{
	struct timespec		abstime;
	int			ret;

	rcu_register_thread();
	pthread_mutex_lock(&pt.lock);
	while (1) {
		uint64_t	progress_val;

		/* Every half second. */
		ret = clock_gettime(CLOCK_REALTIME, &abstime);
		if (ret)
			break;
		abstime.tv_nsec += NSEC_PER_SEC / 2;
		if (abstime.tv_nsec > NSEC_PER_SEC) {
			abstime.tv_sec++;
			abstime.tv_nsec -= NSEC_PER_SEC;
		}
		ret = pthread_cond_timedwait(&pt.wakeup, &pt.lock, &abstime);
		if (ret && ret != ETIMEDOUT)
			break;
		if (pt.terminate)
			break;
		ret = ptcounter_value(pt.ptc, &progress_val);
		if (!ret)
			progress_report(progress_val);
	}
	pthread_mutex_unlock(&pt.lock);
	rcu_unregister_thread();
	return NULL;
}

/* End a phase of progress reporting. */
void
progress_end_phase(void)
{
	if (!pt.fp)
		return;

	pthread_mutex_lock(&pt.lock);
	pt.terminate = true;
	pthread_mutex_unlock(&pt.lock);
	pthread_cond_broadcast(&pt.wakeup);
	pthread_join(pt.thread, NULL);

	progress_report(pt.max);
	ptcounter_free(pt.ptc);
	pt.max = 0;
	pt.ptc = NULL;
	if (pt.fp) {
		fprintf(pt.fp, CLEAR_EOL);
		fflush(pt.fp);
	}
	pt.fp = NULL;
}

/*
 * Set ourselves up to report progress.  If errors are encountered, this
 * function will log them and return nonzero.
 */
int
progress_init_phase(
	struct scrub_ctx	*ctx,
	FILE			*fp,
	unsigned int		phase,
	uint64_t		max,
	int			rshift,
	unsigned int		nr_threads)
{
	int			ret;

	assert(pt.fp == NULL);
	if (fp == NULL || max == 0) {
		pt.fp = NULL;
		return 0;
	}
	pt.fp = fp;
	pt.isatty = isatty(fileno(fp));
	pt.tag = ctx->mntpoint;
	pt.max = max;
	pt.phase = phase;
	pt.rshift = rshift;
	pt.twiddle = 0;
	pt.terminate = false;

	ret = ptcounter_alloc(nr_threads, &pt.ptc);
	if (ret) {
		str_liberror(ctx, ret, _("allocating progress counter"));
		goto out_max;
	}

	ret = pthread_create(&pt.thread, NULL, progress_report_thread, NULL);
	if (ret) {
		str_liberror(ctx, ret, _("creating progress reporting thread"));
		goto out_ptcounter;
	}

	return 0;

out_ptcounter:
	ptcounter_free(pt.ptc);
	pt.ptc = NULL;
out_max:
	pt.max = 0;
	pt.fp = NULL;
	return ret;
}
