==> src/out.c <==1/* jobs.rs's Out and durable. */
2#include "mesh/jobs/out.h"
3
4#include <stdlib.h>
5#include <string.h>
6
7void mj_out_free(mj_out *o) {
8 mj_frame_free(&o->frame);
9 mj_log_free(&o->log);
10 if (o->kind == MJ_OUT_RUN) mj_lease_msg_free(&o->run);
11 free(o->text);
12 memset(o, 0, sizeof *o);
13}
14
15void mj_outs_push(mj_outs *v, mj_out o) {
16 if (v->n == v->cap) {
17 v->cap = v->cap ? 2 * v->cap : 16;
18 v->v = mxrealloc(v->v, v->cap * sizeof *v->v);
19 }
20 v->v[v->n++] = o;
21}
22
23void mj_outs_append(mj_outs *dst, mj_outs *src) {
24 for (size_t i = 0; i < src->n; i++) mj_outs_push(dst, src->v[i]);
25 free(src->v);
26 *src = (mj_outs){0};
27}
28
29void mj_outs_free(mj_outs *v) {
30 for (size_t i = 0; i < v->n; i++) mj_out_free(&v->v[i]);
31 free(v->v);
32 *v = (mj_outs){0};
33}
34
35mj_out mj_out_send(uint32_t to, mj_frame f) { return (mj_out){.kind = MJ_OUT_SEND, .to = to, .frame = f}; }
36mj_out mj_out_push_blob(uint32_t to, mj_job_id job, mj_hash hash) { return (mj_out){.kind = MJ_OUT_PUSH_BLOB, .to = to, .job = job, .hash = hash}; }
37mj_out mj_out_fetch_blob(mj_job_id job, mj_hash hash, uint32_t holders) {
38 return (mj_out){.kind = MJ_OUT_FETCH_BLOB, .job = job, .hash = hash, .holders = holders};
39}
40mj_out mj_out_blob_done(mj_job_id job, mj_hash hash) { return (mj_out){.kind = MJ_OUT_BLOB_DONE, .job = job, .hash = hash}; }
41mj_out mj_out_persist(mj_log l) { return (mj_out){.kind = MJ_OUT_PERSIST, .log = l}; }
42mj_out mj_out_run(mj_lease_msg l) { return (mj_out){.kind = MJ_OUT_RUN, .run = l}; }
43mj_out mj_out_cut(uint64_t lease, uint64_t cut) { return (mj_out){.kind = MJ_OUT_CUT, .lease = lease, .cut = cut}; }
44mj_out mj_out_answer(uint64_t token, bool ok, char *text) { return (mj_out){.kind = MJ_OUT_ANSWER, .token = token, .ok = ok, .text = text}; }
45mj_out mj_out_log(char *text) { return (mj_out){.kind = MJ_OUT_LOG, .text = text}; }
46
47mj_outs mj_durable(mj_outs *outs, const mj_disk *disk, bool *ok, char **err) {
48 mj_outs v = {0};
49 bool dirty = false;
50 *ok = true;
51 size_t i = 0;
52 for (; i < outs->n; i++) {
53 mj_out *o = &outs->v[i];
54 if (o->kind == MJ_OUT_PERSIST) {
55 if (!disk->append(disk->ctx, &o->log, err)) {
56 *ok = false;
57 break;
58 }
59 dirty = true;
60 mj_out_free(o);
61 continue;
62 }
63 if ((o->kind == MJ_OUT_SEND || o->kind == MJ_OUT_ANSWER) && dirty) {
64 if (!disk->sync(disk->ctx, err)) {
65 *ok = false;
66 break;
67 }
68 dirty = false;
69 }
70 mj_outs_push(&v, *o);
71 memset(o, 0, sizeof *o);
72 }
73 if (*ok && dirty && !disk->sync(disk->ctx, err)) *ok = false;
74 /* What was not acted on is dropped. */
75 for (; i < outs->n; i++) mj_out_free(&outs->v[i]);
76 free(outs->v);
77 *outs = (mj_outs){0};
78 return v;
79}