#include "dsynth.h"
#include <curses.h>
static WINDOW *CWin;
static WINDOW *CMon;
static const char *Line0 = " Total - Built - Ignored - "
"Load - Pkg/hour - ";
static const char *Line1 = " Left - Failed - Skipped - "
"Swap - Impulse - --:--:-- ";
static const char *LineB = "==========================================="
"====================================";
static const char *LineI = " ID Duration Build Phase Origin "
" Lines";
static int LastReduce;
static monitorlog_t nclog;
#define TOTAL_COL 7
#define BUILT_COL 21
#define IGNORED_COL 36
#define LOAD_COL 48
#define GPKGRATE_COL 64
#define REDUCE_COL 71
#define LEFT_COL 7
#define FAILED_COL 21
#define SKIPPED_COL 36
#define SWAP_COL 48
#define IMPULSE_COL 64
#define TIME_COL 71
#define ID_COL 1
#define DURATION_COL 5
#define BUILD_PHASE_COL 15
#define ORIGIN_COL 32
#define LINES_COL 72
#define WORKER_START 5
#define LOG_START (WORKER_START + MaxWorkers + 1)
static void NCursesReset(void);
static void
NCursesInit(void)
{
if (UseNCurses == 0)
return;
CWin = initscr();
NCursesReset();
intrflush(stdscr, FALSE);
nonl();
noecho();
cbreak();
start_color();
use_default_colors();
init_pair(1, COLOR_RED, -1);
init_pair(2, COLOR_GREEN, -1);
init_pair(3, -1, -1);
}
static void
NCursesReset(void)
{
int i;
if (UseNCurses == 0)
return;
if (CMon) {
delwin(CMon);
CMon = NULL;
}
werase(CWin);
curs_set(0);
redrawwin(CWin);
wrefresh(CWin);
mvwprintw(CWin, 0, 0, "%s", Line0);
mvwprintw(CWin, 1, 0, "%s", Line1);
mvwprintw(CWin, 2, 0, "%s", LineB);
mvwprintw(CWin, 3, 0, "%s", LineI);
mvwprintw(CWin, 4, 0, "%s", LineB);
for (i = 0; i < MaxWorkers; ++i) {
mvwprintw(CWin, WORKER_START + i, ID_COL, "%02d", i);
mvwprintw(CWin, WORKER_START + i, DURATION_COL, "--:--:--");
mvwprintw(CWin, WORKER_START + i, BUILD_PHASE_COL, "Idle");
mvwprintw(CWin, WORKER_START + i, ORIGIN_COL, "%38.38s", "");
mvwprintw(CWin, WORKER_START + i, LINES_COL, "%7.7s", "");
}
mvwprintw(CWin, WORKER_START + MaxWorkers, 0, "%s", LineB);
wrefresh(CWin);
CMon = subwin(CWin, 0, 0, LOG_START, 0);
scrollok(CMon, 1);
bzero(&nclog, sizeof(nclog));
nclog.fd = dlog00_fd();
nodelay(CMon, 1);
LastReduce = -1;
}
static void
NCursesUpdateTop(topinfo_t *info)
{
if (UseNCurses == 0)
return;
mvwprintw(CWin, 0, TOTAL_COL, "%-6d", info->total);
mvwprintw(CWin, 0, BUILT_COL, "%-6d", info->successful);
mvwprintw(CWin, 0, IGNORED_COL, "%-6d", info->ignored);
if (info->dload[0] > 999.9)
mvwprintw(CWin, 0, LOAD_COL, "%5.0f", info->dload[0]);
else
mvwprintw(CWin, 0, LOAD_COL, "%5.1f", info->dload[0]);
mvwprintw(CWin, 0, GPKGRATE_COL, "%-6d", info->pkgrate);
if (LastReduce != info->dynmaxworkers) {
LastReduce = info->dynmaxworkers;
if (MaxWorkers == LastReduce)
mvwprintw(CWin, 0, REDUCE_COL, " ");
else
mvwprintw(CWin, 0, REDUCE_COL, "Lim %-3d",
LastReduce);
}
mvwprintw(CWin, 1, LEFT_COL, "%-6d", info->remaining);
mvwprintw(CWin, 1, FAILED_COL, "%-6d", info->failed);
mvwprintw(CWin, 1, SKIPPED_COL, "%-6d", info->skipped);
if (info->noswap)
mvwprintw(CWin, 1, SWAP_COL, "- ");
else
mvwprintw(CWin, 1, SWAP_COL, "%5.1f", info->dswap);
mvwprintw(CWin, 1, IMPULSE_COL, "%-6d", info->pkgimpulse);
if (info->h > 99)
mvwprintw(CWin, 1, TIME_COL-1, "%3d:%02d:%02d",
info->h, info->m, info->s);
else
mvwprintw(CWin, 1, TIME_COL, "%02d:%02d:%02d",
info->h, info->m, info->s);
}
static void
NCursesUpdateLogs(void)
{
char *ptr;
char c;
ssize_t n;
int w;
if (UseNCurses == 0)
return;
for (;;) {
n = readlogline(&nclog, &ptr);
if (n < 0)
break;
if (n == 0)
continue;
if (n > COLS)
w = COLS;
else
w = n;
c = ptr[w];
ptr[w] = 0;
if (strncmp(ptr, "[XXX] Load=", 11) != 0) {
wscrl(CMon, -1);
if (strstr(ptr, "] SUCCESS ")) {
wattrset(CMon, COLOR_PAIR(2));
} else if (strstr(ptr, "] FAILURE ")) {
wattrset(CMon, COLOR_PAIR(1));
}
mvwprintw(CMon, 0, 0, "%s", ptr);
wattrset(CMon, COLOR_PAIR(3));
}
ptr[w] = c;
}
}
static void
NCursesUpdate(worker_t *work, const char *portdir)
{
const char *phase;
const char *origin;
time_t t;
int i = work->index;
int h;
int m;
int s;
if (UseNCurses == 0)
return;
phase = "Unknown";
origin = "";
switch(work->state) {
case WORKER_NONE:
phase = "None";
case WORKER_IDLE:
if (work->state == WORKER_IDLE)
phase = "Idle";
case WORKER_FAILED:
if (work->state == WORKER_FAILED)
phase = "Failed";
case WORKER_EXITING:
if (work->state == WORKER_EXITING)
phase = "Exiting";
mvwprintw(CWin, WORKER_START + i, DURATION_COL,
"--:--:--");
mvwprintw(CWin, WORKER_START + i, BUILD_PHASE_COL,
"%-16.16s", phase);
mvwprintw(CWin, WORKER_START + i, ORIGIN_COL,
"%-38.38s", "");
mvwprintw(CWin, WORKER_START + i, LINES_COL,
"%-7.7s", "");
return;
case WORKER_PENDING:
phase = "Pending";
break;
case WORKER_RUNNING:
phase = "Running";
break;
case WORKER_DONE:
phase = "Done";
break;
case WORKER_FROZEN:
phase = "FROZEN";
break;
default:
break;
}
t = time(NULL) - work->start_time;
s = t % 60;
m = t / 60 % 60;
h = t / 60 / 60;
if (work->state == WORKER_RUNNING)
phase = getphasestr(work->phase);
if (portdir)
origin = portdir;
else if (work->pkg)
origin = work->pkg->portdir;
else
origin = "";
mvwprintw(CWin, WORKER_START + i, DURATION_COL,
"%02d:%02d:%02d", h, m, s);
mvwprintw(CWin, WORKER_START + i, BUILD_PHASE_COL,
"%-16.16s", phase);
mvwprintw(CWin, WORKER_START + i, ORIGIN_COL,
"%-38.38s", origin);
if (work->lines > 9999999) {
mvwprintw(CWin, WORKER_START + i, LINES_COL,
"%7s", "*MANY*%d", work->lines % 10);
} else {
mvwprintw(CWin, WORKER_START + i, LINES_COL,
"%7d", work->lines);
}
}
static void
NCursesSync(void)
{
int c;
if (UseNCurses == 0)
return;
while ((c = wgetch(CMon)) != ERR) {
if (c == KEY_RESIZE)
NCursesReset();
}
wrefresh(CWin);
wrefresh(CMon);
}
static void
NCursesDone(void)
{
if (UseNCurses == 0)
return;
endwin();
}
runstats_t NCursesRunStats = {
.init = NCursesInit,
.done = NCursesDone,
.reset = NCursesReset,
.update = NCursesUpdate,
.updateTop = NCursesUpdateTop,
.updateLogs = NCursesUpdateLogs,
.sync = NCursesSync
};