skip to content
==> src/fleet_groups.c <==
1/* fleet.rs: new_epoch, group_policy, reform. */
2#include "mesh/fleet_groups.h"
3#include "mesh/mt.h"
4
5void mfg_new_epoch(mfd_group *g, ml_list members) {
6    g->epoch += 1;
7    g->cycle = 0;
8    g->op = (mfd_op){MFD_OP_NONE, 0, 0};
9    ml_free(&g->members);
10    g->members = members;
11    g->state = MFD_RUNNING;
12}
13
14bool mfg_policy(const mfd_group *g, uint32_t up, int64_t paused_ms, mfd_group *out) {
15    bool all = (mfd_group_mask(g) & ~up) == 0;
16    if (g->state == MFD_RUNNING && !all) {
17        *out = mfd_group_clone(g);
18        out->state = MFD_PAUSED;
19        return true;
20    }
21    if (g->state == MFD_PAUSED && all && g->members.n) {
22        *out = mfd_group_clone(g);
23        mfg_new_epoch(out, ml_clone(&g->members));
24        return true;
25    }
26    if (g->state == MFD_PAUSED && g->on_loss == MFD_LOSS_REFORM && g->auto_ms > 0 && paused_ms >= 0 && (uint64_t)paused_ms >= g->auto_ms) {
27        ml_list survivors = {0};
28        for (size_t i = 0; i < g->members.n; i++)
29            if (up >> g->members.v[i] & 1) ml_push(&survivors, g->members.v[i]);
30        if (!survivors.n) return false;
31        *out = mfd_group_clone(g);
32        mfg_new_epoch(out, survivors);
33        return true;
34    }
35    return false;
36}
37
38bool mfg_reform(const mfd_group *g, const ml_list *eligible_up, mfd_group *out, char **err) {
39    if (!eligible_up->n) {
40        *err = mt_fmt("group %s: no member that can run %s is up", g->name, g->program);
41        return false;
42    }
43    *out = mfd_group_clone(g);
44    mfg_new_epoch(out, ml_clone(eligible_up));
45    return true;
46}