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
40 static runstats_t
*RSBase
;
41 static runstats_t
**RSTailp
= &RSBase
;
42 static time_t RSStartTime
;
44 #define RHISTSIZE 600 /* impulse record is 10 minutes */
45 #define ONEHOUR (60 * 60)
52 RSStartTime
= time(NULL
);
54 *RSTailp
= &NCursesRunStats
;
55 RSTailp
= &(*RSTailp
)->next
;
57 *RSTailp
= &MonitorRunStats
;
58 RSTailp
= &(*RSTailp
)->next
;
60 *RSTailp
= &HtmlRunStats
;
61 RSTailp
= &(*RSTailp
)->next
;
63 for (rs
= RSBase
; rs
; rs
= rs
->next
)
72 for (rs
= RSBase
; rs
; rs
= rs
->next
)
81 for (rs
= RSBase
; rs
; rs
= rs
->next
)
86 RunStatsUpdate(worker_t
*work
, const char *portdir
)
90 for (rs
= RSBase
; rs
; rs
= rs
->next
)
91 rs
->update(work
, portdir
);
95 RunStatsUpdateTop(int active
)
97 static int rate_history
[RHISTSIZE
];
107 bzero(&info
, sizeof(info
));
108 t
= time(NULL
) - RSStartTime
;
110 info
.m
= t
/ 60 % 60;
111 info
.h
= t
/ 60 / 60;
112 info
.active
= active
;
117 info
.total
= BuildTotal
;
118 info
.successful
= BuildSuccessCount
;
119 info
.ignored
= BuildIgnoreCount
;
120 info
.remaining
= BuildTotal
- BuildCount
;
121 info
.failed
= BuildFailCount
;
122 info
.skipped
= BuildSkipCount
;
123 info
.meta
= BuildMetaCount
;
128 getloadavg(info
.dload
, 3);
129 info
.dswap
= getswappct(&info
.noswap
) * 100.0;
132 * Rate and 10-minute impulse
135 info
.pkgrate
= (BuildSuccessCount
+ BuildFailCount
) *
139 ti
= (u_int
)((unsigned long)t
% RHISTSIZE
);
140 rate_history
[ti
] = BuildSuccessCount
+ BuildFailCount
;
142 dlog(DLOG_ALL
, "ti[%3d] = %d\n", ti
, rate_history
[ti
]);
144 while (last_ti
!= ti
) {
145 rate_history
[last_ti
] = rate_history
[ti
];
146 last_ti
= (last_ti
+ 1) % RHISTSIZE
;
151 } else if (t
< RHISTSIZE
) {
152 info
.pkgimpulse
= rate_history
[ti
] -
153 rate_history
[(ti
- t
) % RHISTSIZE
];
154 info
.pkgimpulse
= info
.pkgimpulse
* ONEHOUR
/ t
;
156 info
.pkgimpulse
= rate_history
[ti
] -
157 rate_history
[(ti
+ 1) % RHISTSIZE
];
158 info
.pkgimpulse
= info
.pkgimpulse
* ONEHOUR
/ RHISTSIZE
;
160 dlog(DLOG_ALL
, "pkgimpulse %d - %d -> %d\n",
162 rate_history
[(ti
+ 1) % RHISTSIZE
],
167 info
.dynmaxworkers
= DynamicMaxWorkers
;
172 for (rs
= RSBase
; rs
; rs
= rs
->next
)
173 rs
->updateTop(&info
);
177 RunStatsUpdateLogs(void)
181 for (rs
= RSBase
; rs
; rs
= rs
->next
)
190 for (rs
= RSBase
; rs
; rs
= rs
->next
)
195 RunStatsUpdateCompletion(worker_t
*work
, int logid
, pkg_t
*pkg
,
196 const char *reason
, const char *skipbuf
)
200 for (rs
= RSBase
; rs
; rs
= rs
->next
) {
201 if (rs
->updateCompletion
)
202 rs
->updateCompletion(work
, logid
, pkg
, reason
, skipbuf
);