skip to content
==> include/mesh/reconcile.h <==
1/* @ajax/mesh-reconcile: the reconciler (reconcile.rs). It makes this member's programs match the
2 * committed desired state, on every commit and when the member (re)joins; it is the only thing that
3 * changes the program set in a fleet. One pass:
4 * 1. the plan (mesh-fleet-plan): unload what should not be here, load what is missing, upgrade on a hash
5 *    mismatch (a rollback when the retained image is the one wanted), then run states and resets. An
6 *    image comes from the local catalog when its identity matches, else from a member. A program this
7 *    member has no image for is reported unsupported, not failed; a failure is retried 30 s later or at
8 *    the next document. Programs migrating here are loaded stopped, take their views from the source
9 *    (producers first), and start (consumers first);
10 * 2. the lockstep group: a new epoch quiesces the program, sets the group words, resets it and asks the
11 *    fleet thread to HELLO; a cycle inside the epoch quiesces it with rounds still mirrored, applies it
12 *    and HELLOs only with the document's image and the cycle's task done here (review finding 2);
13 * 3. on the leader, the placement requests.
14 * Everything that touches the driver or the fleet thread goes through mrc_ops (the daemon wires it). */
15#ifndef MESH_RECONCILE_H
16#define MESH_RECONCILE_H
17
18#include "mesh/fleet_doc.h"
19#include "mesh/fleet_plan.h"
20#include "mesh/peer_codec.h"
21#include "mesh/sched_tracker.h"
22
23#include <stdbool.h>
24#include <stdint.h>
25
26/* Whether this member may HELLO a group's new cycle: it runs the program at the document's image (inv:
27 * the driver's inventory after the cycle's actions) and the cycle's task, if any, ran here (task:
28 * NULL not run; else *task_ok and its error). Otherwise false with the reason. */
29bool mrc_cycle_ready(const mfd_group *g, uint64_t hash, const mfl_actual *inv, size_t ninv, const bool *task_ok, const char *task_err, char **why);
30
31/* The stop order of programs moving together: a program that feeds another of them first. Returns a
32 * permutation of names (new list). */
33mt_strs mrc_stop_order(const mfd_doc *doc, const mt_strs *names);
34
35typedef struct {
36    void *ctx;
37    uint32_t me;
38    /* The driver (each true with *text, or false with *err): */
39    mfl_actual *(*inventory)(void *ctx, size_t *n);
40    /* An image of name at hash: the local catalog's when it is that image, else a member's. *src is
41     * opaque to the reconciler, handed to load / upgrade and then to src_free. */
42    bool (*source)(void *ctx, const char *name, const char *dir, uint64_t hash, void **src, char **err);
43    void (*src_free)(void *ctx, void *src);
44    bool (*load)(void *ctx, void *src, bool run, char **text, char **err);
45    bool (*upgrade)(void *ctx, const char *name, void *src, char **text, char **err);
46    bool (*unload)(void *ctx, const char *name, char **text, char **err);
47    bool (*rollback)(void *ctx, const char *name, char **text, char **err);
48    bool (*prog_run)(void *ctx, const char *name, bool on, char **text, char **err);
49    bool (*reset)(void *ctx, const char *name, char **text, char **err);
50    bool (*task)(void *ctx, const char *name, uint32_t op, uint32_t arg, uint32_t *result, char **err);
51    bool (*place)(void *ctx, const char *name, const mt_strs *words, char **text, char **err);
52    /* A migrated program's view from member from (the fleet thread asks it), and writing it here. */
53    bool (*fetch_view)(void *ctx, const char *name, uint64_t hash, uint32_t from, uint32_t *view_abi, mpw_bytes *bytes, char **err);
54    bool (*view_put)(void *ctx, const char *name, uint32_t view_abi, const mpw_bytes *bytes, char **text, char **err);
55    /* The lockstep group shared with the fleet thread: stop feeding and wait until it saw it (mirror:
56     * keep exchanging rounds); the group words in the mailbox; ready for an epoch or cycle (HELLO). */
57    void (*quiesce)(void *ctx, bool mirror, bool member);
58    bool (*want_set)(void *ctx);
59    void (*group_words)(void *ctx, uint32_t rank, uint32_t n, uint32_t epoch);
60    void (*ready)(void *ctx, const mpk_hello *spec);
61    bool (*is_leader)(void *ctx);
62    /* Publishing: the reconcile status (RS_*; reason at most BEAT_REASON_MAX) with this member's move
63     * outcomes, and the programs not to try again (name, hash, unsupported, why <= 200 chars). */
64    void (*status)(void *ctx, uint64_t applied, uint32_t status, const char *reason, const mst_outcome *moves, size_t nmoves);
65    void (*fails)(void *ctx, char *const *names, const uint64_t *hashes, const bool *unsupported, char *const *whys, size_t n);
66    uint64_t (*applied)(void *ctx);
67    void (*log)(void *ctx, bool error, const char *line);
68    void (*sleep_ms)(void *ctx, uint32_t ms);
69} mrc_ops;
70
71typedef struct mrc_rec mrc_rec;
72
73mrc_rec *mrc_new(const mrc_ops *ops);
74void mrc_free(mrc_rec *r);
75/* A committed document (new: a version this reconciler did not see last): one pass. Returns true when
76 * it failed (retry in 30 s with mrc_retry). */
77bool mrc_document(mrc_rec *r, const mfd_doc *doc);
78/* The retry: failed programs get another go on the last document. */
79bool mrc_retry(mrc_rec *r);
80
81/* A thread running a reconciler: post committed documents; it retries failures after 30 s. */
82typedef struct mrc_thread mrc_thread;
83mrc_thread *mrc_thread_start(const mrc_ops *ops);
84void mrc_post(mrc_thread *t, const mfd_doc *doc);
85void mrc_thread_stop(mrc_thread *t);
86
87#endif