2 * Copyright (c) 2019 The DragonFly Project. All rights reserved.
4 * This code is derived from software contributed to The DragonFly Project
5 * by Matthew Dillon <dillon@backplane.com>
7 * This code uses concepts and configuration based on 'synth', by
8 * John R. Marino <draco@marino.st>, which was written in ada.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in
18 * the documentation and/or other materials provided with the
20 * 3. Neither the name of The DragonFly Project nor the names of its
21 * contributors may be used to endorse or promote products derived
22 * from this software without specific, prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
30 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
32 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
33 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
34 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
42 * ncurses - LINES, COLS are the main things we care about
46 static const char *Line0
= " Total - Built - Ignored - "
48 static const char *Line1
= " Left - Failed - Skipped - "
49 "Swap - Impulse - --:--:-- ";
50 static const char *LineB
= "==========================================="
51 "====================================";
52 static const char *LineI
= " ID Duration Build Phase Origin "
55 static int LastReduce
;
56 static monitorlog_t nclog
;
60 #define IGNORED_COL 36
62 #define GPKGRATE_COL 64
67 #define SKIPPED_COL 36
69 #define IMPULSE_COL 64
73 #define DURATION_COL 5
74 #define BUILD_PHASE_COL 15
79 * The row that the worker list starts on, and the row that the log starts
82 #define WORKER_START 5
83 #define LOG_START (WORKER_START + MaxWorkers + 1)
85 static void NCursesReset(void);
96 intrflush(stdscr
, FALSE
);
102 use_default_colors();
103 init_pair(1, COLOR_RED
, -1);
104 init_pair(2, COLOR_GREEN
, -1);
105 init_pair(3, -1, -1);
125 mvwprintw(CWin
, 0, 0, "%s", Line0
);
126 mvwprintw(CWin
, 1, 0, "%s", Line1
);
127 mvwprintw(CWin
, 2, 0, "%s", LineB
);
128 mvwprintw(CWin
, 3, 0, "%s", LineI
);
129 mvwprintw(CWin
, 4, 0, "%s", LineB
);
131 for (i
= 0; i
< MaxWorkers
; ++i
) {
132 mvwprintw(CWin
, WORKER_START
+ i
, ID_COL
, "%02d", i
);
133 mvwprintw(CWin
, WORKER_START
+ i
, DURATION_COL
, "--:--:--");
134 mvwprintw(CWin
, WORKER_START
+ i
, BUILD_PHASE_COL
, "Idle");
135 mvwprintw(CWin
, WORKER_START
+ i
, ORIGIN_COL
, "%38.38s", "");
136 mvwprintw(CWin
, WORKER_START
+ i
, LINES_COL
, "%7.7s", "");
138 mvwprintw(CWin
, WORKER_START
+ MaxWorkers
, 0, "%s", LineB
);
141 CMon
= subwin(CWin
, 0, 0, LOG_START
, 0);
144 bzero(&nclog
, sizeof(nclog
));
145 nclog
.fd
= dlog00_fd();
152 NCursesUpdateTop(topinfo_t
*info
)
157 mvwprintw(CWin
, 0, TOTAL_COL
, "%-6d", info
->total
);
158 mvwprintw(CWin
, 0, BUILT_COL
, "%-6d", info
->successful
);
159 mvwprintw(CWin
, 0, IGNORED_COL
, "%-6d", info
->ignored
);
160 if (info
->dload
[0] > 999.9)
161 mvwprintw(CWin
, 0, LOAD_COL
, "%5.0f", info
->dload
[0]);
163 mvwprintw(CWin
, 0, LOAD_COL
, "%5.1f", info
->dload
[0]);
164 mvwprintw(CWin
, 0, GPKGRATE_COL
, "%-6d", info
->pkgrate
);
167 * If dynamic worker reduction is active include a field,
168 * Otherwise blank the field.
170 if (LastReduce
!= info
->dynmaxworkers
) {
171 LastReduce
= info
->dynmaxworkers
;
172 if (MaxWorkers
== LastReduce
)
173 mvwprintw(CWin
, 0, REDUCE_COL
, " ");
175 mvwprintw(CWin
, 0, REDUCE_COL
, "Lim %-3d",
179 mvwprintw(CWin
, 1, LEFT_COL
, "%-6d", info
->remaining
);
180 mvwprintw(CWin
, 1, FAILED_COL
, "%-6d", info
->failed
);
181 mvwprintw(CWin
, 1, SKIPPED_COL
, "%-6d", info
->skipped
);
183 mvwprintw(CWin
, 1, SWAP_COL
, "- ");
185 mvwprintw(CWin
, 1, SWAP_COL
, "%5.1f", info
->dswap
);
186 mvwprintw(CWin
, 1, IMPULSE_COL
, "%-6d", info
->pkgimpulse
);
188 mvwprintw(CWin
, 1, TIME_COL
-1, "%3d:%02d:%02d",
189 info
->h
, info
->m
, info
->s
);
191 mvwprintw(CWin
, 1, TIME_COL
, "%02d:%02d:%02d",
192 info
->h
, info
->m
, info
->s
);
196 NCursesUpdateLogs(void)
207 n
= readlogline(&nclog
, &ptr
);
224 * Filter out these logs from the display (they remain in
225 * the 00*.log file) to reduce clutter.
227 if (strncmp(ptr
, "[XXX] Load=", 11) != 0) {
229 * Output possibly colored log line
232 if (strstr(ptr
, "] SUCCESS ")) {
233 wattrset(CMon
, COLOR_PAIR(2));
234 } else if (strstr(ptr
, "] FAILURE ")) {
235 wattrset(CMon
, COLOR_PAIR(1));
237 mvwprintw(CMon
, 0, 0, "%s", ptr
);
238 wattrset(CMon
, COLOR_PAIR(3));
245 NCursesUpdate(worker_t
*work
, const char *portdir
)
261 switch(work
->state
) {
266 if (work
->state
== WORKER_IDLE
)
270 if (work
->state
== WORKER_FAILED
)
274 if (work
->state
== WORKER_EXITING
)
276 mvwprintw(CWin
, WORKER_START
+ i
, DURATION_COL
,
278 mvwprintw(CWin
, WORKER_START
+ i
, BUILD_PHASE_COL
,
280 mvwprintw(CWin
, WORKER_START
+ i
, ORIGIN_COL
,
282 mvwprintw(CWin
, WORKER_START
+ i
, LINES_COL
,
301 t
= time(NULL
) - work
->start_time
;
306 if (work
->state
== WORKER_RUNNING
)
307 phase
= getphasestr(work
->phase
);
310 * When called from the monitor frontend portdir has to be passed
311 * in directly because work->pkg is not mapped.
316 origin
= work
->pkg
->portdir
;
320 mvwprintw(CWin
, WORKER_START
+ i
, DURATION_COL
,
321 "%02d:%02d:%02d", h
, m
, s
);
322 mvwprintw(CWin
, WORKER_START
+ i
, BUILD_PHASE_COL
,
324 mvwprintw(CWin
, WORKER_START
+ i
, ORIGIN_COL
,
326 if (work
->lines
> 9999999) {
327 mvwprintw(CWin
, WORKER_START
+ i
, LINES_COL
,
328 "%7s", "*MANY*%d", work
->lines
% 10);
330 mvwprintw(CWin
, WORKER_START
+ i
, LINES_COL
,
343 while ((c
= wgetch(CMon
)) != ERR
) {
360 runstats_t NCursesRunStats
= {
363 .reset
= NCursesReset
,
364 .update
= NCursesUpdate
,
365 .updateTop
= NCursesUpdateTop
,
366 .updateLogs
= NCursesUpdateLogs
,