1ea37671dSMatthew Dillon /* 2ea37671dSMatthew Dillon * Copyright (c) 2019 The DragonFly Project. All rights reserved. 3ea37671dSMatthew Dillon * 4ea37671dSMatthew Dillon * This code is derived from software contributed to The DragonFly Project 5ea37671dSMatthew Dillon * by Matthew Dillon <dillon@backplane.com> 6ea37671dSMatthew Dillon * 7ea37671dSMatthew Dillon * This code uses concepts and configuration based on 'synth', by 8ea37671dSMatthew Dillon * John R. Marino <draco@marino.st>, which was written in ada. 9ea37671dSMatthew Dillon * 10ea37671dSMatthew Dillon * Redistribution and use in source and binary forms, with or without 11ea37671dSMatthew Dillon * modification, are permitted provided that the following conditions 12ea37671dSMatthew Dillon * are met: 13ea37671dSMatthew Dillon * 14ea37671dSMatthew Dillon * 1. Redistributions of source code must retain the above copyright 15ea37671dSMatthew Dillon * notice, this list of conditions and the following disclaimer. 16ea37671dSMatthew Dillon * 2. Redistributions in binary form must reproduce the above copyright 17ea37671dSMatthew Dillon * notice, this list of conditions and the following disclaimer in 18ea37671dSMatthew Dillon * the documentation and/or other materials provided with the 19ea37671dSMatthew Dillon * distribution. 20ea37671dSMatthew Dillon * 3. Neither the name of The DragonFly Project nor the names of its 21ea37671dSMatthew Dillon * contributors may be used to endorse or promote products derived 22ea37671dSMatthew Dillon * from this software without specific, prior written permission. 23ea37671dSMatthew Dillon * 24ea37671dSMatthew Dillon * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 25ea37671dSMatthew Dillon * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26ea37671dSMatthew Dillon * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 27ea37671dSMatthew Dillon * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 28ea37671dSMatthew Dillon * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 29ea37671dSMatthew Dillon * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 30ea37671dSMatthew Dillon * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 31ea37671dSMatthew Dillon * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 32ea37671dSMatthew Dillon * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 33ea37671dSMatthew Dillon * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 34ea37671dSMatthew Dillon * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35ea37671dSMatthew Dillon * SUCH DAMAGE. 36ea37671dSMatthew Dillon */ 37ea37671dSMatthew Dillon 38ea37671dSMatthew Dillon #include "dsynth.h" 39ea37671dSMatthew Dillon 40ea37671dSMatthew Dillon static runstats_t *RSBase; 41ea37671dSMatthew Dillon static runstats_t **RSTailp = &RSBase; 42ea37671dSMatthew Dillon static time_t RSStartTime; 43ea37671dSMatthew Dillon 44ea37671dSMatthew Dillon #define RHISTSIZE 600 /* impulse record is 10 minutes */ 45ea37671dSMatthew Dillon #define ONEHOUR (60 * 60) 46ea37671dSMatthew Dillon 47ea37671dSMatthew Dillon void 48ea37671dSMatthew Dillon RunStatsInit(void) 49ea37671dSMatthew Dillon { 50ea37671dSMatthew Dillon runstats_t *rs; 51ea37671dSMatthew Dillon 52ea37671dSMatthew Dillon RSStartTime = time(NULL); 53ea37671dSMatthew Dillon 54ea37671dSMatthew Dillon *RSTailp = &NCursesRunStats; 55ea37671dSMatthew Dillon RSTailp = &(*RSTailp)->next; 56ea37671dSMatthew Dillon 57ea37671dSMatthew Dillon *RSTailp = &MonitorRunStats; 58ea37671dSMatthew Dillon RSTailp = &(*RSTailp)->next; 59ea37671dSMatthew Dillon 60ea37671dSMatthew Dillon *RSTailp = &HtmlRunStats; 61ea37671dSMatthew Dillon RSTailp = &(*RSTailp)->next; 62ea37671dSMatthew Dillon 63ea37671dSMatthew Dillon for (rs = RSBase; rs; rs = rs->next) 64ea37671dSMatthew Dillon rs->init(); 65ea37671dSMatthew Dillon } 66ea37671dSMatthew Dillon 67ea37671dSMatthew Dillon void 68ea37671dSMatthew Dillon RunStatsDone(void) 69ea37671dSMatthew Dillon { 70ea37671dSMatthew Dillon runstats_t *rs; 71ea37671dSMatthew Dillon 72ea37671dSMatthew Dillon for (rs = RSBase; rs; rs = rs->next) 73ea37671dSMatthew Dillon rs->done(); 74ea37671dSMatthew Dillon } 75ea37671dSMatthew Dillon 76ea37671dSMatthew Dillon void 77ea37671dSMatthew Dillon RunStatsReset(void) 78ea37671dSMatthew Dillon { 79ea37671dSMatthew Dillon runstats_t *rs; 80ea37671dSMatthew Dillon 81ea37671dSMatthew Dillon for (rs = RSBase; rs; rs = rs->next) 82ea37671dSMatthew Dillon rs->reset(); 83ea37671dSMatthew Dillon } 84ea37671dSMatthew Dillon 85ea37671dSMatthew Dillon void 86*aac7a6d9SMatthew Dillon RunStatsUpdate(worker_t *work, const char *portdir) 87ea37671dSMatthew Dillon { 88ea37671dSMatthew Dillon runstats_t *rs; 89ea37671dSMatthew Dillon 90ea37671dSMatthew Dillon for (rs = RSBase; rs; rs = rs->next) 91*aac7a6d9SMatthew Dillon rs->update(work, portdir); 92ea37671dSMatthew Dillon } 93ea37671dSMatthew Dillon 94ea37671dSMatthew Dillon void 95ea37671dSMatthew Dillon RunStatsUpdateTop(void) 96ea37671dSMatthew Dillon { 97ea37671dSMatthew Dillon static int rate_history[RHISTSIZE]; 98ea37671dSMatthew Dillon static u_int last_ti; 99ea37671dSMatthew Dillon topinfo_t info; 100ea37671dSMatthew Dillon runstats_t *rs; 101ea37671dSMatthew Dillon u_int ti; 102ea37671dSMatthew Dillon time_t t; 103ea37671dSMatthew Dillon 104ea37671dSMatthew Dillon /* 105ea37671dSMatthew Dillon * Time 106ea37671dSMatthew Dillon */ 107ea37671dSMatthew Dillon bzero(&info, sizeof(info)); 108ea37671dSMatthew Dillon t = time(NULL) - RSStartTime; 109ea37671dSMatthew Dillon info.s = t % 60; 110ea37671dSMatthew Dillon info.m = t / 60 % 60; 111ea37671dSMatthew Dillon info.h = t / 60 / 60; 112ea37671dSMatthew Dillon 113ea37671dSMatthew Dillon /* 114ea37671dSMatthew Dillon * Easy fields 115ea37671dSMatthew Dillon */ 116ea37671dSMatthew Dillon info.total = BuildTotal; 117ea37671dSMatthew Dillon info.successful = BuildSuccessCount; 118ea37671dSMatthew Dillon info.ignored = BuildIgnoreCount; 119ea37671dSMatthew Dillon info.remaining = BuildTotal - BuildCount; 120ea37671dSMatthew Dillon info.failed = BuildFailCount; 121ea37671dSMatthew Dillon info.skipped = BuildSkipCount; 122ea37671dSMatthew Dillon 123ea37671dSMatthew Dillon /* 124ea37671dSMatthew Dillon * Load and swap 125ea37671dSMatthew Dillon */ 126ea37671dSMatthew Dillon getloadavg(info.dload, 3); 127ea37671dSMatthew Dillon info.dswap = getswappct(&info.noswap) * 100.0; 128ea37671dSMatthew Dillon 129ea37671dSMatthew Dillon /* 130ea37671dSMatthew Dillon * Rate and 10-minute impulse 131ea37671dSMatthew Dillon */ 132ea37671dSMatthew Dillon if (t > 20) 133ea37671dSMatthew Dillon info.pkgrate = (BuildSuccessCount + BuildFailCount) * 134ea37671dSMatthew Dillon ONEHOUR / t; 135ea37671dSMatthew Dillon else 136ea37671dSMatthew Dillon info.pkgrate = 0; 137ea37671dSMatthew Dillon ti = (u_int)((unsigned long)t % RHISTSIZE); 138ea37671dSMatthew Dillon rate_history[ti] = BuildSuccessCount + BuildFailCount; 139ea37671dSMatthew Dillon #if 0 140ea37671dSMatthew Dillon dlog(DLOG_ALL, "ti[%3d] = %d\n", ti, rate_history[ti]); 141ea37671dSMatthew Dillon #endif 142ea37671dSMatthew Dillon while (last_ti != ti) { 143ea37671dSMatthew Dillon rate_history[last_ti] = rate_history[ti]; 144ea37671dSMatthew Dillon last_ti = (last_ti + 1) % RHISTSIZE; 145ea37671dSMatthew Dillon } 146ea37671dSMatthew Dillon 147ea37671dSMatthew Dillon if (t < 20) { 148ea37671dSMatthew Dillon info.pkgimpulse = 0; 149ea37671dSMatthew Dillon } else if (t < RHISTSIZE) { 150ea37671dSMatthew Dillon info.pkgimpulse = rate_history[ti] - 151ea37671dSMatthew Dillon rate_history[(ti - t) % RHISTSIZE]; 152ea37671dSMatthew Dillon info.pkgimpulse = info.pkgimpulse * ONEHOUR / t; 153ea37671dSMatthew Dillon } else { 154ea37671dSMatthew Dillon info.pkgimpulse = rate_history[ti] - 155ea37671dSMatthew Dillon rate_history[(ti + 1) % RHISTSIZE]; 156ea37671dSMatthew Dillon info.pkgimpulse = info.pkgimpulse * ONEHOUR / RHISTSIZE; 157ea37671dSMatthew Dillon #if 0 158ea37671dSMatthew Dillon dlog(DLOG_ALL, "pkgimpulse %d - %d -> %d\n", 159ea37671dSMatthew Dillon rate_history[ti], 160ea37671dSMatthew Dillon rate_history[(ti + 1) % RHISTSIZE], 161ea37671dSMatthew Dillon info.pkgimpulse); 162ea37671dSMatthew Dillon #endif 163ea37671dSMatthew Dillon } 164ea37671dSMatthew Dillon 165*aac7a6d9SMatthew Dillon info.dynmaxworkers = DynamicMaxWorkers; 166*aac7a6d9SMatthew Dillon 167ea37671dSMatthew Dillon /* 168ea37671dSMatthew Dillon * Issue update 169ea37671dSMatthew Dillon */ 170ea37671dSMatthew Dillon for (rs = RSBase; rs; rs = rs->next) 171ea37671dSMatthew Dillon rs->updateTop(&info); 172ea37671dSMatthew Dillon } 173ea37671dSMatthew Dillon 174ea37671dSMatthew Dillon void 175ea37671dSMatthew Dillon RunStatsUpdateLogs(void) 176ea37671dSMatthew Dillon { 177ea37671dSMatthew Dillon runstats_t *rs; 178ea37671dSMatthew Dillon 179ea37671dSMatthew Dillon for (rs = RSBase; rs; rs = rs->next) 180ea37671dSMatthew Dillon rs->updateLogs(); 181ea37671dSMatthew Dillon } 182ea37671dSMatthew Dillon 183ea37671dSMatthew Dillon void 184ea37671dSMatthew Dillon RunStatsSync(void) 185ea37671dSMatthew Dillon { 186ea37671dSMatthew Dillon runstats_t *rs; 187ea37671dSMatthew Dillon 188ea37671dSMatthew Dillon for (rs = RSBase; rs; rs = rs->next) 189ea37671dSMatthew Dillon rs->sync(); 190ea37671dSMatthew Dillon } 191