skip to content
==> src/board.c <==
1/* The perf board (shared.rs PerfBoard): every member's last F_PERF, and the link RTTs measured from the
2 * echoes of ours. */
3#include "relay.h"
4
5#include <stdlib.h>
6#include <string.h>
7
8void board_init(board_t *b) { pthread_mutex_init(&b->mu, NULL); }
9
10void board_free(board_t *b) {
11    for (uint32_t k = 0; k < MAXS; k++)
12        if (b->has[k]) msr_free(&b->rep[k]);
13    pthread_mutex_destroy(&b->mu);
14}
15
16/* A deep copy (the text form is lossy: it rounds the floats). */
17static msr_report report_clone(const msr_report *r) {
18    msr_report c = {.t_us = r->t_us, .cpus = r->cpus, .big = r->big, .little = r->little, .ram_mb = r->ram_mb, .disk_free_mb = r->disk_free_mb,
19                    .heap_kb = r->heap_kb, .slots_free = r->slots_free};
20    for (size_t i = 0; i < r->nprogs; i++) msr_add_prog(&c, r->progs[i].name, &r->progs[i].perf);
21    for (size_t i = 0; i < r->nfails; i++) msr_add_fail(&c, r->fails[i].name, r->fails[i].hash, r->fails[i].unsupported, r->fails[i].why);
22    for (size_t i = 0; i < r->nrtt; i++) msr_add_rtt(&c, r->rtt[i].k, r->rtt[i].us);
23    for (size_t i = 0; i < r->necho; i++) msr_add_echo(&c, r->echo[i].k, r->echo[i].t, r->echo[i].held);
24    return c;
25}
26
27void board_report(mpr_relay *r, uint32_t from, const char *text) {
28    msr_report rep;
29    char *err = NULL;
30    if (!msr_decode(text, &rep, &err)) {
31        relay_log(r, true, mt_fmt("peer: system %u: %s", from, err));
32        free(err);
33        return;
34    }
35    if (from >= MAXS) {
36        msr_free(&rep);
37        return;
38    }
39    uint64_t now = mpr_mono_us();
40    board_t *b = &r->board;
41    pthread_mutex_lock(&b->mu);
42    /* Its echo of our last send: the link's round trip less the time it held it. */
43    for (size_t i = 0; i < rep.necho; i++)
44        if (rep.echo[i].k == r->me) {
45            uint64_t t = rep.echo[i].t, held = rep.echo[i].held;
46            uint64_t rtt = now > t ? now - t : 0;
47            rtt = rtt > held ? rtt - held : 0;
48            if (t > 0 && rtt < 10000000) b->rtt_us[from] = mof32_some((float)rtt);
49            break;
50        }
51    if (b->has[from]) msr_free(&b->rep[from]);
52    b->rep[from] = rep;
53    b->at_us[from] = now;
54    b->has[from] = true;
55    pthread_mutex_unlock(&b->mu);
56}
57
58void mpr_board_own(mpr_relay *r, const msr_report *rep) {
59    board_t *b = &r->board;
60    pthread_mutex_lock(&b->mu);
61    if (b->has[r->me]) msr_free(&b->rep[r->me]);
62    b->rep[r->me] = report_clone(rep);
63    b->at_us[r->me] = mpr_mono_us();
64    b->has[r->me] = true;
65    pthread_mutex_unlock(&b->mu);
66}
67
68size_t mpr_board_echoes(mpr_relay *r, uint32_t *k, uint64_t *t, uint64_t *held) {
69    board_t *b = &r->board;
70    size_t n = 0;
71    uint64_t now = mpr_mono_us();
72    pthread_mutex_lock(&b->mu);
73    for (uint32_t j = 0; j < r->n; j++)
74        if (j != r->me && b->has[j]) k[n] = j, t[n] = b->rep[j].t_us, held[n++] = now - b->at_us[j];
75    pthread_mutex_unlock(&b->mu);
76    return n;
77}