// SPDX-License-Identifier: GPL-2.0+
/*
 * Copyright (C) 2018 Oracle.  All Rights Reserved.
 * Author: Darrick J. Wong <darrick.wong@oracle.com>
 */
#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;
}
