diff --git a/src/flake.lock b/src/flake.lock index a429c39e..05436399 100644 --- a/src/flake.lock +++ b/src/flake.lock @@ -74,6 +74,63 @@ "type": "github" } }, + "flake-utils_4": { + "inputs": { + "systems": "systems_4" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_5": { + "inputs": { + "systems": "systems_5" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "librtti": { + "inputs": { + "flake-utils": "flake-utils_3", + "nixpkgs": "nixpkgs_2", + "xbuild": "xbuild" + }, + "locked": { + "lastModified": 1770000148, + "narHash": "sha256-sZP7UjAQ3nRbYNtDOpoNLcVoBq4fC1bhsmmHtpUTZig=", + "ref": "master", + "rev": "00080a95f3fb9912fc7a57b0b89ee205ec3e9b16", + "revCount": 4, + "type": "git", + "url": "ssh://forgejo@gitea.shenrs.eu/rshen/librtti" + }, + "original": { + "ref": "master", + "type": "git", + "url": "ssh://forgejo@gitea.shenrs.eu/rshen/librtti" + } + }, "nixpkgs": { "locked": { "lastModified": 1764517877, @@ -92,11 +149,11 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1766309749, - "narHash": "sha256-3xY8CZ4rSnQ0NqGhMKAy5vgC+2IVK0NoVEzDoOh4DA4=", + "lastModified": 1764950072, + "narHash": "sha256-BmPWzogsG2GsXZtlT+MTcAWeDK5hkbGRZTeZNW42fwA=", "owner": "nixos", "repo": "nixpkgs", - "rev": "a6531044f6d0bef691ea18d4d4ce44d0daa6e816", + "rev": "f61125a668a320878494449750330ca58b78c557", "type": "github" }, "original": { @@ -122,12 +179,45 @@ "type": "github" } }, + "nixpkgs_4": { + "locked": { + "lastModified": 1769461804, + "narHash": "sha256-msG8SU5WsBUfVVa/9RPLaymvi5bI8edTavbIq3vRlhI=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "bfc1b8a4574108ceef22f02bafcf6611380c100d", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_5": { + "locked": { + "lastModified": 1764667669, + "narHash": "sha256-7WUCZfmqLAssbDqwg9cUDAXrSoXN79eEEq17qhTNM/Y=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "418468ac9527e799809c900eda37cbff999199b6", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, "root": { "inputs": { "extralib": "extralib", "flake-utils": "flake-utils_2", - "nixpkgs": "nixpkgs_2", - "xbuild": "xbuild" + "librtti": "librtti", + "nixpkgs": "nixpkgs_4", + "xbuild": "xbuild_2" } }, "systems": { @@ -175,17 +265,67 @@ "type": "github" } }, + "systems_4": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_5": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, "xbuild": { "inputs": { - "flake-utils": "flake-utils_3", + "flake-utils": "flake-utils_4", "nixpkgs": "nixpkgs_3" }, "locked": { - "lastModified": 1766562395, - "narHash": "sha256-bbnbjJ2sru/2YqHN1jzdYs+khOhrjngaRLBJFd5nQ4Y=", + "lastModified": 1769064169, + "narHash": "sha256-Tqb8E8vw6WtP5KPCzwWAVBzMwv+UH0gduR2ZWkkYM9g=", "owner": "shen390s", "repo": "my-nix-channel", - "rev": "828497661dbef0721ca1aceb0b76fd71086a720b", + "rev": "d6e6711f401446ebfec291ad1a3fbb58fd33720d", + "type": "github" + }, + "original": { + "owner": "shen390s", + "ref": "master", + "repo": "my-nix-channel", + "type": "github" + } + }, + "xbuild_2": { + "inputs": { + "flake-utils": "flake-utils_5", + "nixpkgs": "nixpkgs_5" + }, + "locked": { + "lastModified": 1769064169, + "narHash": "sha256-Tqb8E8vw6WtP5KPCzwWAVBzMwv+UH0gduR2ZWkkYM9g=", + "owner": "shen390s", + "repo": "my-nix-channel", + "rev": "d6e6711f401446ebfec291ad1a3fbb58fd33720d", "type": "github" }, "original": { diff --git a/src/flake.nix b/src/flake.nix index 6dfce48c..0aeae14b 100644 --- a/src/flake.nix +++ b/src/flake.nix @@ -5,10 +5,11 @@ nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable"; xbuild.url = "github:shen390s/my-nix-channel?ref=master"; extralib.url = "git+ssh://forgejo@gitea.shenrs.eu/nexa/extralibs?ref=main"; + librtti.url = "git+ssh://forgejo@gitea.shenrs.eu/rshen/librtti?ref=master"; flake-utils.url = "github:numtide/flake-utils"; }; - outputs = { self, nixpkgs, xbuild, extralib, flake-utils }: + outputs = { self, nixpkgs, xbuild, extralib, librtti, flake-utils }: let supportedSystems = [ "x86_64-linux" ]; myCommitId = @@ -18,7 +19,7 @@ in flake-utils.lib.eachSystem supportedSystems ( system: let - mypkgs = xbuild.packages.${system} // extralib.packages.${system}; + mypkgs = xbuild.packages.${system} // extralib.packages.${system} // librtti.packages.${system}; overlays = [ (final: prev: mypkgs // prev) ]; diff --git a/src/include/resreq.h b/src/include/resreq.h new file mode 100644 index 00000000..4cfd95ad --- /dev/null +++ b/src/include/resreq.h @@ -0,0 +1,128 @@ +#if !defined(_RESREQ_H_) + +#define _RESREQ_H_ 1 + +#include +#include +#include + +#include "xlist.h" + +typedef struct xce_resreq_select_ xce_select_t; +typedef struct xce_resreq_rusages_ xce_rusages_t; +typedef struct xce_resreq_span_ xce_span_t; +typedef struct xce_resreq_same_ xce_same_t; +typedef struct xce_resreq_affinity_ xce_affinity_t; +typedef struct xce_resreq_data_ xce_resreq_data_t; + +struct xce_resreq_data_ { + char* selectString; + char* rusageString; + char* spanString; + char* sameString; + char* affinityString; +}; + +typedef struct { + const char* input; + int pos; + char* errmsg; + int err_pos; + int has_error; + xce_resreq_data_t data; +} section_context_t; + +typedef enum { + PER_TASK = 0, + PER_JOB, + PER_HOST +} rusage_per_type_t; + +typedef struct { + const char* input; + int pos; + int err_pos; + int has_error; + xlist_t* rusages; + char* resname; + rusage_per_type_t per_flag; + float resvalue; + float duration_value; + int decay_flag; + float tmp_value; + float duration_multiply; +} rusage_context_t; + +typedef struct { + char* res; + float value; + rusage_per_type_t per_flag; + float duration; + int decay_flag; +} rusage_value_t; + +struct xce_resreq_select_ { }; + +struct xce_resreq_span_ { }; + +struct xce_resreq_same_ { }; + +struct xce_resreq_affinity_ { }; + +typedef struct { + int minTasks; + int maxTasks; + xce_select_t* select; + xlist_t rusages; + xce_span_t* span; + xce_same_t* same; + xce_affinity_t* affinity; +} xce_primary_resreq_t; + +typedef struct { + xlist_t primaries; +} xce_compound_resreq_t; + +typedef struct { + xlist_t compounds; +} xce_alter_resreq_t; + +typedef enum { + XCE_RESREQ_PRIMARY = 0, + XCE_RESREQ_COMPOUND, + XCE_RESREQ_ALTER +} xce_resreq_tag_t; + +typedef struct { + xce_resreq_tag_t tag; + union { + xce_primary_resreq_t* primary; + xce_compound_resreq_t* compound; + xce_alter_resreq_t* alter; + } u; +} xce_resreq_t; + +typedef struct { + const char* input; + int pos; + int err_pos; + int has_error; + char* errmsg; + xce_resreq_t* resreq; + xce_alter_resreq_t* alter; + xce_compound_resreq_t* compound; + xce_primary_resreq_t* primary; + int resreq_fact_count; +} resreq_context_t; + +extern void kill_section_ctx(section_context_t*); +extern void kill_resreq_data(xce_resreq_data_t*); +extern int parse_section(xce_resreq_data_t*, char*, char**); +extern int parse_rusage(xlist_t*, char*, char**); +extern void kill_rusage_value(rusage_value_t*); +extern int parse_resreq_primary(xce_primary_resreq_t*, char*, char**); +extern int parse_resreq(xce_resreq_t*, char*, char**); +extern void kill_resreq(xce_resreq_t*); +extern int format_resreq(char**, xce_resreq_t*); + +#endif diff --git a/src/include/utils.h b/src/include/utils.h index 5ef9929a..9c4cc27e 100644 --- a/src/include/utils.h +++ b/src/include/utils.h @@ -131,7 +131,7 @@ extern uint64_t array_idx(uint64_t); extern void unblock_sig(int); extern void block_sig(int); -extern uint32_t hash(uint32_t, uint32_t, uint32_t, uint32_t); +extern uint32_t hash4(uint32_t, uint32_t, uint32_t, uint32_t); extern uint32_t hash64(uint64_t); extern uint32_t hash_string(const char*); diff --git a/src/lib/meson.build b/src/lib/meson.build index 00826df7..c04aec22 100644 --- a/src/lib/meson.build +++ b/src/lib/meson.build @@ -1,4 +1,5 @@ capnp = find_program('capnp') +packcc = find_program('packcc') gen_srcs = custom_target( 'controllercapnp.[ch]', @@ -7,7 +8,50 @@ gen_srcs = custom_target( command: [capnp, 'compile','-o' ,'c:lib', '-I', '../schema','--src-prefix', '../schema', '@INPUT@'] ) +section_parser = custom_target( + 'xce resreq section parser', + output: ['section.c', 'section.h'], + input: ['section.peg'], + command: [ + packcc, + '-l', + '-o', + 'lib/section', + '@INPUT@' + ], + build_by_default: true) + +rusage_parser = custom_target( + 'xce resreq rusage parser', + output: ['rusage.c', 'rusage.h'], + input: ['rusage.peg'], + command: [ + packcc, + '-l', + '-o', + 'lib/rusage', + '@INPUT@' + ], + build_by_default: true) + +xce_resreq_parser = custom_target( + 'xce resreq xce_resreq parser', + output: ['xce_resreq.c', 'xce_resreq.h'], + input: ['xce_resreq.peg'], + command: [ + packcc, + '-l', + '-o', + 'lib/xce_resreq', + '@INPUT@' + ], + build_by_default: true) + + libxce_src = [ gen_srcs[0], + section_parser[0], + rusage_parser[0], + xce_resreq_parser[0], 'client.c', 'dataq.c', 'hook.c', @@ -37,6 +81,7 @@ libxce_src = [ gen_srcs[0], 'xcelimit.c', 'xvec.c', 'helper.c', + 'resreq.c', ] incdir = include_directories('../include') @@ -87,6 +132,7 @@ libxce_test_src = ['testsuite/test.c', 'testsuite/test_xlist.c', 'testsuite/test_limit.c', 'testsuite/test_xvec.c', + 'testsuite/test_resreq.c', ] libxce_test_deps = [libxce_deps, unity_dep, libxce_dep] diff --git a/src/lib/mylock.c b/src/lib/mylock.c index a030396f..fcd6d89e 100644 --- a/src/lib/mylock.c +++ b/src/lib/mylock.c @@ -2,6 +2,8 @@ #include #include +#include + #include "mylock.h" int mylock_init(mylock_t* l) diff --git a/src/lib/resreq.c b/src/lib/resreq.c new file mode 100644 index 00000000..1b4fc2e3 --- /dev/null +++ b/src/lib/resreq.c @@ -0,0 +1,433 @@ +#include +#include +#include +#include + +#include "resreq.h" +#include "rusage.h" +#include "section.h" +#include "utils.h" +#include "xce_resreq.h" +#include "xlist.h" + +static int get_parse_errmsg(char** errmsg, const char* data, int pos) +{ + size_t bufsize = 0; + FILE* mem_stream = NULL; + int i; + + if ((errmsg == NULL) || (data == NULL) || (pos < 0)) { + return -EINVAL; + } + + mem_stream = open_memstream(errmsg, &bufsize); + if (mem_stream == NULL) { + return -errno; + } + + fprintf(mem_stream, "%s\n", data); + for (i = 0; i < pos - 1; i++) { + fprintf(mem_stream, " "); + } + + fprintf(mem_stream, "^Error\n"); + + fflush(mem_stream); + fclose(mem_stream); + + return 1; +} + +void kill_resreq_data(xce_resreq_data_t* data) +{ + if (data == NULL) { + return; + } + + FREEUP(data->selectString); + FREEUP(data->rusageString); + FREEUP(data->spanString); + FREEUP(data->sameString); + FREEUP(data->affinityString); +} + +void kill_section_ctx(section_context_t* ctx) +{ + if (ctx == NULL) { + return; + } + + kill_resreq_data(&(ctx->data)); +} + +int parse_section(xce_resreq_data_t* resreq, char* data, char** errmsg) +{ + section_context_t ctx = { 0 }; + xce_section_context_t* p = NULL; + int rc = 1; + + if ((resreq == NULL) || (data == NULL) || (errmsg == NULL)) { + return -EINVAL; + } + + *errmsg = NULL; + ctx.input = data; + + p = xce_section_create(&ctx); + if (p == NULL) { + return -errno; + } + + xce_section_parse(p, NULL); + + if (ctx.has_error) { + get_parse_errmsg(errmsg, ctx.input, ctx.err_pos); + rc = -EINVAL; + } else { + MOVE_PTR(resreq->selectString, ctx.data.selectString); + MOVE_PTR(resreq->rusageString, ctx.data.rusageString); + MOVE_PTR(resreq->spanString, ctx.data.spanString); + MOVE_PTR(resreq->sameString, ctx.data.sameString); + MOVE_PTR(resreq->affinityString, ctx.data.affinityString); + } + + kill_section_ctx(&ctx); + + xce_section_destroy(p); + + return rc; +} + +void kill_rusage_value(rusage_value_t* val) +{ + if (val == NULL) { + return; + } + + FREEUP(val->res); +} + +void kill_rusage_ctx(rusage_context_t* ctx) +{ + if (ctx == NULL) { + return; + } + return; +} + +int parse_rusage(xlist_t* rusages, char* data, char** errmsg) +{ + rusage_context_t ctx = { 0 }; + xce_rusage_context_t* p = NULL; + int rc = 1; + + if ((rusages == NULL) || (data == NULL) || (errmsg == NULL)) { + return -EINVAL; + } + + *errmsg = NULL; + ctx.input = data; + ctx.rusages = rusages; + + p = xce_rusage_create(&ctx); + if (p == NULL) { + return -errno; + } + + xce_rusage_parse(p, NULL); + + if (ctx.has_error) { + get_parse_errmsg(errmsg, ctx.input, ctx.err_pos); + rc = -EINVAL; + /* FIXME: need to freeup partial data in rusages */ + } + + kill_rusage_ctx(&ctx); + + xce_rusage_destroy(p); + + return rc; +} + +int parse_resreq_primary(xce_primary_resreq_t* primary, char* resreqString, + char** errmsg) +{ + int rc; + xce_resreq_data_t data; + + if ((primary == NULL) || (resreqString == NULL) || (errmsg == NULL)) { + return -EINVAL; + } + + memset(primary, 0x0, sizeof(*primary)); + + rc = parse_section(&data, (char*)resreqString, errmsg); + if (rc < 0) { + return rc; + } + + xlist_init(&(primary->rusages), 8); + rc = parse_rusage(&(primary->rusages), data.rusageString, errmsg); + if (rc < 0) { + kill_resreq_data(&data); + + return rc; + } + + /* FIXME: add others later */ + + kill_resreq_data(&data); + primary->minTasks = 1; + primary->maxTasks = 1; + + return rc; +} + +void kill_resreq_ctx(resreq_context_t* ctx) +{ + if (ctx == NULL) { + return; + } +} + +int parse_resreq(xce_resreq_t* resreq, char* data, char** errmsg) +{ + resreq_context_t ctx = { 0 }; + xce_resreq_context_t* p = NULL; + int rc = 1; + + if ((resreq == NULL) || (data == NULL) || (errmsg == NULL)) { + return -EINVAL; + } + + *errmsg = NULL; + memset(resreq, 0x0, sizeof(*resreq)); + + ctx.input = data; + ctx.resreq = resreq; + + p = xce_resreq_create(&ctx); + if (p == NULL) { + return -errno; + } + + xce_resreq_parse(p, NULL); + + if (ctx.has_error) { + get_parse_errmsg(errmsg, ctx.input, ctx.err_pos); + rc = -EINVAL; + /* FIXME: need to freeup partial data in resreqs */ + } + + kill_resreq_ctx(&ctx); + + xce_resreq_destroy(p); + + return rc; +} + +void kill_primary_resreq(xce_primary_resreq_t* resreq) +{ + int i; + + if (resreq == NULL) { + return; + } + + for (i = 0; i < resreq->rusages.count; i++) { + rusage_value_t* v = (rusage_value_t*)xlist_get(&(resreq->rusages), i); + + if (v == NULL) { + continue; + } + + kill_rusage_value(v); + + FREEUP(v); + } + + xlist_fini(&(resreq->rusages)); +} + +void kill_compound_resreq(xce_compound_resreq_t* resreq) +{ + int i; + + if (resreq == NULL) { + return; + } + + for (i = 0; i < resreq->primaries.count; i++) { + xce_primary_resreq_t* primary + = (xce_primary_resreq_t*)xlist_get(&(resreq->primaries), i); + + if (primary == NULL) { + continue; + } + + kill_primary_resreq(primary); + FREEUP(primary); + } + + xlist_fini(&(resreq->primaries)); +} + +void kill_alter_resreq(xce_alter_resreq_t* resreq) +{ + int i; + + if (resreq == NULL) { + return; + } + + for (i = 0; i < resreq->compounds.count; i++) { + xce_compound_resreq_t* c + = (xce_compound_resreq_t*)xlist_get(&(resreq->compounds), i); + + if (c == NULL) { + continue; + } + + kill_compound_resreq(c); + FREEUP(c); + } + + xlist_fini(&(resreq->compounds)); +} + +void kill_resreq(xce_resreq_t* resreq) +{ + if (resreq == NULL) { + return; + } + + switch (resreq->tag) { + case XCE_RESREQ_PRIMARY: + kill_primary_resreq(resreq->u.primary); + FREEUP(resreq->u.primary); + break; + case XCE_RESREQ_COMPOUND: + kill_compound_resreq(resreq->u.compound); + FREEUP(resreq->u.compound); + break; + case XCE_RESREQ_ALTER: + kill_alter_resreq(resreq->u.alter); + FREEUP(resreq->u.alter); + break; + default: + break; + } +} + +static int print_rusages(FILE* fp, xlist_t* rusages, int level) +{ + int i; + + fprintf(fp, "%*sRusages:\n", (int)(2 * level), ""); + for (i = 0; i < rusages->count; i++) { + rusage_value_t* v = (rusage_value_t*)xlist_get(rusages, i); + + if (v == NULL) { + continue; + } + + fprintf(fp, "%*s res %s value %f per %d duration %f decay %d\n", + (int)(2 * (level + 1)), "", v->res, v->value, v->per_flag, + v->duration, v->decay_flag); + } + + return 0; +} +static int print_primary_resreq(FILE* fp, xce_primary_resreq_t* resreq, + int level) +{ + fprintf(fp, "%*sPrimary:\n", (int)(2 * level), ""); + fprintf(fp, "%*sTasks: min = %d, max = %d\n", (int)(2 * (level + 1)), "", + resreq->minTasks, resreq->maxTasks); +#if 0 + fprintf(fp, "%*Select: %s\n", (int)(2*(level +1)),"", "Add later"); +#endif + print_rusages(fp, &(resreq->rusages), level + 1); + + return 0; +} + +static int print_compound_resreq(FILE* fp, xce_compound_resreq_t* resreq, + int level) +{ + int i; + + fprintf(fp, "%*sCompound:\n", (int)(2 * level), ""); + for (i = 0; i < resreq->primaries.count; i++) { + xce_primary_resreq_t* primary + = (xce_primary_resreq_t*)xlist_get(&(resreq->primaries), i); + + if (primary == NULL) { + continue; + } + + print_primary_resreq(fp, primary, level + 1); + } + + return 0; +} + +static int print_alter_resreq(FILE* fp, xce_alter_resreq_t* resreq, int level) +{ + int i; + + fprintf(fp, "%*sAlternative:\n", (int)(2 * level), ""); + for (i = 0; i < resreq->compounds.count; i++) { + xce_compound_resreq_t* c + = (xce_compound_resreq_t*)xlist_get(&(resreq->compounds), i); + if (c == NULL) { + continue; + } + + print_compound_resreq(fp, c, level + 1); + } + return 0; +} + +static int print_resreq(FILE* fp, xce_resreq_t* resreq, int level) +{ + if ((fp == NULL) || (resreq == NULL) || (level < 0)) { + return -EINVAL; + } + + switch (resreq->tag) { + case XCE_RESREQ_PRIMARY: + return print_primary_resreq(fp, resreq->u.primary, level); + case XCE_RESREQ_COMPOUND: + return print_compound_resreq(fp, resreq->u.compound, level); + case XCE_RESREQ_ALTER: + return print_alter_resreq(fp, resreq->u.alter, level); + default: + break; + } + + return -EINVAL; +} + +int format_resreq(char** buf, xce_resreq_t* resreq) +{ + size_t bufsize = 0; + FILE* fp = NULL; + int rc = 0; + + if ((buf == NULL) || (resreq == NULL)) { + return -EINVAL; + } + + fp = open_memstream(buf, &bufsize); + if (fp == NULL) { + return -errno; + } + + rc = print_resreq(fp, resreq, 0); + + fflush(fp); + fclose(fp); + + return rc; +} diff --git a/src/lib/rusage.peg b/src/lib/rusage.peg new file mode 100644 index 00000000..e2b45f89 --- /dev/null +++ b/src/lib/rusage.peg @@ -0,0 +1,93 @@ +%prefix "xce_rusage" +%value "char *" +%auxil "rusage_context_t *" +%source { + #include + #include + #include + + #if 0 + static const char *dbg_str[] = { "Evaluating rule", "Matched rule", "Abandoning rule" }; + #define PCC_DEBUG(auxil, event, rule, level, pos, buffer, length) \ + fprintf(stderr, "%*s%s %s @%zu [%.*s]\n", (int)((level) * 2), "", dbg_str[event], rule, pos, (int)(length), buffer) + #endif + #define PCC_ERROR(auxil) my_rusage_error(auxil) + + static void my_rusage_error(rusage_context_t *auxil) { + /* Calculate line/column from max_err */ + auxil->has_error = 1; + } +} + +%common { + #include "resreq.h" + #include "xlist.h" + + #define PCC_GETCHAR(auxil) \ + ({ int c = (auxil->input[auxil->pos] != '\0') ? (int)auxil->input[auxil->pos ++]: -1; \ + if (auxil->pos > auxil->err_pos) auxil->err_pos = auxil->pos; \ + c; \ + }) + +} + +rusage_spec <- _ rusage_params _ EOF + +rusage_params <- first:rusage_param _ ',' _ rest:rusage_params + / rusage_param + +rusage_param <- key:identifier _ '=' v:resvalue _ duration _ decay { + rusage_value_t *rusage = (rusage_value_t *)calloc(1, sizeof(*rusage)); + if (rusage != NULL) { + rusage->res = auxil->resname; + rusage->per_flag = auxil->per_flag; + rusage->value = auxil->resvalue; + rusage->duration = auxil->duration_value; + rusage->decay_flag = auxil->decay_flag; + auxil->resname = NULL; + + xlist_store(auxil->rusages, rusage); + } + + if (auxil->resname != NULL) { + free(auxil->resname); + auxil->resname = NULL; + } + } + +duration <- ':duration=' _ duration_value _ + / empty_duration + +empty_duration <- { } { auxil->duration_value = -1.0; } + +decay <- ':decay=' _ decay_value _ + / empty_decay + +empty_decay <- { } { auxil->decay_flag = 0; } + +identifier <- [a-zA-Z_][a-zA-Z_0-9]* { auxil->resname = strdup($0); } + +resvalue <- number '/' per_type { auxil->resvalue = auxil->tmp_value; } + / number { auxil->resvalue = auxil->tmp_value; auxil->per_flag = PER_TASK; } + +per_type <- 'task' { auxil->per_flag = PER_TASK; } + / 'job' { auxil->per_flag = PER_JOB; } + / 'host' { auxil->per_flag = PER_HOST; } + +duration_value <- v:number duration_unit { auxil->duration_value = auxil->tmp_value * auxil->duration_multiply; } + / v:number { auxil->duration_value = auxil->tmp_value * 60.0; } + +duration_unit <- 'h' { auxil->duration_multiply = 3600.0; } + / 'm' { auxil->duration_multiply = 60.0; } + / 's' { auxil->duration_multiply = 1.0; } + +decay_value <- '0' { auxil->decay_flag = 0; } + / '1' { auxil->decay_flag = 1; } + +number <- < [0-9]+('.'[0-9]*)? > { auxil->tmp_value = atof($0); } + +EOL <- "\n" / "\r\n" / "\r" / "\0" + +_ <- [ \t]* + +EOF <- !. diff --git a/src/lib/section.peg b/src/lib/section.peg new file mode 100644 index 00000000..67ca62a7 --- /dev/null +++ b/src/lib/section.peg @@ -0,0 +1,85 @@ +%prefix "xce_section" +%value "char *" +%auxil "section_context_t *" +%source { + #include + #include + #include + + #if 0 + static const char *dbg_str[] = { "Evaluating rule", "Matched rule", "Abandoning rule" }; + #define PCC_DEBUG(auxil, event, rule, level, pos, buffer, length) \ + fprintf(stderr, "%*s%s %s @%zu [%.*s]\n", (int)((level) * 2), "", dbg_str[event], rule, pos, (int)(length), buffer) + #endif + #define PCC_ERROR(auxil) my_report_error(auxil) + + void my_report_error(section_context_t *auxil) { + /* Calculate line/column from max_err */ + auxil->has_error = 1; + } +} + +%common { + #include "resreq.h" + + #define PCC_GETCHAR(auxil) \ + ({ int c = (auxil->input[auxil->pos] != '\0') ? (int)auxil->input[auxil->pos ++]: -1; \ + if (auxil->pos > auxil->err_pos) auxil->err_pos = auxil->pos; \ + c; \ + }) + +} + + +statement <- _ resource_statement _ EOF + +resource_statement <- select:select_clause? _ usage:usage_clause? _ span:span_clause? _ same:same_clause? _ affinity:affinity_clause? { + auxil->data.selectString = select; + auxil->data.rusageString = usage; + auxil->data.spanString = span; + auxil->data.sameString = same; + auxil->data.affinityString = affinity; + $$ = NULL; + } + +select_clause <- "select[" _ s:select_statement _ "]" { $$ = s; } + / s:select_statement {$$ = s; } + + +select_statement <- (!("rusage[" / "]") .)* {$$ = strdup($0); } + / (!("span[" "]" / "]") .)* {$$ = strdup($0); } + / (!("same[" !"]" / "]") .)* {$$ = strdup($0);} + / (!("affinity[" / "]") !"]" .)* {$$ = strdup($0);} + + +usage_clause <- "rusage[" _ usage:usage_statement _ "]" { $$ = usage; } + + +usage_statement <- (!("span[" / "]") .)* { $$ = strdup($0); } + / (!("same[" / "]") .)* { $$ = strdup($0); } + / (!("affinity[" / "]") .)* { $$ = strdup($0); } + + +span_clause <- "span[" _ span:span_statement _ "]" { $$ = span; } + + +span_statement <- (!("same[" / "]") .)* { $$ = strdup($0); } + / (!("affinity[" / "]") .)* { $$ = strdup($0); } + + +same_clause <- "same[" _ same:same_statement _ "]" { $$ = same; } + + +same_statement <- (!("affinity[" / "]") .)* { $$ = strdup($0); } + + +affinity_clause <- "affinity[" _ affinity:affinity_statement _ "]" { $$ = affinity; } + + +affinity_statement <- (!"]" .)* { $$ = strdup($0); } + +EOL <- "\n" / "\r\n" / "\r" / "\0" + +_ <- [ \t]* + +EOF <- !. diff --git a/src/lib/testsuite/test.c b/src/lib/testsuite/test.c index 81dc21e2..7485c24d 100644 --- a/src/lib/testsuite/test.c +++ b/src/lib/testsuite/test.c @@ -21,10 +21,15 @@ extern void test_group(void); extern void test_xlist(void); extern void test_limit(void); extern void test_xvec(void); +extern void test_resreq(void); void setUp(void) { return; } -void tearDown(void) { return; } +void tearDown(void) +{ + printf("\n-----------------------------------------------------\n"); + return; +} static char doc[] = "xcelib_test"; static char args_doc[] = ""; @@ -107,6 +112,7 @@ int main(int argc, char* argv[]) TEST(test_xlist); TEST(test_limit); TEST(test_xvec); + TEST(test_resreq); return UNITY_END(); } diff --git a/src/lib/testsuite/test_resreq.c b/src/lib/testsuite/test_resreq.c new file mode 100644 index 00000000..e92cbf2b --- /dev/null +++ b/src/lib/testsuite/test_resreq.c @@ -0,0 +1,343 @@ +#include +#include +#include +#include + +#include + +#include "resreq.h" +#include "utils.h" + +void test_parse_section1(void) +{ + char* resreq = "type == any"; + char* errmsg = NULL; + int rc = 0; + xce_resreq_data_t data; + + rc = parse_section(&data, (char*)resreq, &errmsg); + TEST_ASSERT_TRUE(rc >= 0); + TEST_ASSERT_TRUE(data.selectString != NULL); + TEST_ASSERT_TRUE((data.rusageString == NULL) && (data.spanString == NULL) + && (data.sameString == NULL) + && (data.affinityString == NULL)); + TEST_ASSERT_TRUE(errmsg == NULL); + + printf("select: %s\n", data.selectString); + FREEUP(data.selectString); +} + +void test_parse_section2(void) +{ + char* resreq = "select[type == any]"; + char* errmsg = NULL; + int rc = 0; + xce_resreq_data_t data; + + rc = parse_section(&data, (char*)resreq, &errmsg); + TEST_ASSERT_TRUE(rc >= 0); + TEST_ASSERT_TRUE(data.selectString != NULL); + TEST_ASSERT_TRUE((data.rusageString == NULL) && (data.spanString == NULL) + && (data.sameString == NULL) + && (data.affinityString == NULL)); + TEST_ASSERT_TRUE(errmsg == NULL); + + printf("select: %s\n", data.selectString); + FREEUP(data.selectString); +} + +void test_parse_section_fail(void) +{ + char* resreq = "select[type == any] rusage[mem=20:lic=55] span[ptile=1] " + "same[type] same[abcd] affinity[core(20)]"; + char* errmsg = NULL; + int rc = 0; + xce_resreq_data_t data; + + rc = parse_section(&data, (char*)resreq, &errmsg); + TEST_ASSERT_TRUE(rc < 0); + TEST_ASSERT_TRUE(data.selectString == NULL); + TEST_ASSERT_TRUE((data.rusageString == NULL) && (data.spanString == NULL) + && (data.sameString == NULL) + && (data.affinityString == NULL)); + TEST_ASSERT_TRUE(errmsg != NULL); + + printf("Parse Error:\n%s\n", errmsg); + FREEUP(errmsg); +} + +void test_parse_rusage1(void) +{ + char* rusageString + = "mem=20:duration=300:decay=1,lic=55:duration=20m:decay=0"; + char* errmsg = NULL; + int rc = 0; + xlist_t rusages; + + xlist_init(&rusages, 8); + + rc = parse_rusage(&rusages, rusageString, &errmsg); + TEST_ASSERT_TRUE(rc >= 0); + + if (rc >= 0) { + int i; + + for (i = 0; i < rusages.count; i++) { + rusage_value_t* v = (rusage_value_t*)xlist_get(&rusages, i); + + TEST_ASSERT_TRUE(v != NULL); + switch (i) { + case 0: + TEST_ASSERT_TRUE(strcmp(v->res, "mem") == 0); + TEST_ASSERT_TRUE(fabs(v->value - 20.0) < 0.001); + TEST_ASSERT_TRUE(fabs(v->duration - 18000) < 0.001); + TEST_ASSERT_TRUE(v->per_flag == 0); + TEST_ASSERT_TRUE(v->decay_flag == 1); + break; + case 1: + TEST_ASSERT_TRUE(strcmp(v->res, "lic") == 0); + TEST_ASSERT_TRUE(fabs(v->value - 55.0) < 0.001); + TEST_ASSERT_TRUE(fabs(v->duration - 1200) < 0.001); + TEST_ASSERT_TRUE(v->per_flag == 0); + TEST_ASSERT_TRUE(v->decay_flag == 0); + break; + default: + break; + } + printf("rusage: %s %f %d %f %d\n", v->res, v->value, v->per_flag, + v->duration, v->decay_flag); + + kill_rusage_value(v); + free(v); + } + + xlist_fini(&rusages); + } +} + +void test_parse_rusage2(void) +{ + char* rusageString + = "mem=20/host:duration=300:decay=1,lic=55/job:duration=20m:decay=0"; + char* errmsg = NULL; + int rc = 0; + xlist_t rusages; + + xlist_init(&rusages, 8); + + rc = parse_rusage(&rusages, rusageString, &errmsg); + TEST_ASSERT_TRUE(rc >= 0); + + if (rc >= 0) { + int i; + + for (i = 0; i < rusages.count; i++) { + rusage_value_t* v = (rusage_value_t*)xlist_get(&rusages, i); + + TEST_ASSERT_TRUE(v != NULL); + switch (i) { + case 0: + TEST_ASSERT_TRUE(strcmp(v->res, "mem") == 0); + TEST_ASSERT_TRUE(fabs(v->value - 20.0) < 0.001); + TEST_ASSERT_TRUE(fabs(v->duration - 18000) < 0.001); + TEST_ASSERT_TRUE(v->per_flag == 2); + TEST_ASSERT_TRUE(v->decay_flag == 1); + break; + case 1: + TEST_ASSERT_TRUE(strcmp(v->res, "lic") == 0); + TEST_ASSERT_TRUE(fabs(v->value - 55.0) < 0.001); + TEST_ASSERT_TRUE(fabs(v->duration - 1200) < 0.001); + TEST_ASSERT_TRUE(v->per_flag == 1); + TEST_ASSERT_TRUE(v->decay_flag == 0); + break; + default: + break; + } + printf("rusage: %s %f %d %f %d\n", v->res, v->value, v->per_flag, + v->duration, v->decay_flag); + + kill_rusage_value(v); + free(v); + } + + xlist_fini(&rusages); + } +} + +void test_resreq_primary(void) +{ + char* resreqString + = "select[type==any] " + "rusage[mem=20:duration=300:decay=1,lic=55:duration=20m:decay=0]"; + char* errmsg = NULL; + int rc = 0; + xce_primary_resreq_t resreq; + + rc = parse_resreq_primary(&resreq, resreqString, &errmsg); + TEST_ASSERT_TRUE(rc >= 0); + if (rc >= 0) { + int i; + xlist_t* rusages = &(resreq.rusages); + + for (i = 0; i < rusages->count; i++) { + rusage_value_t* v = (rusage_value_t*)xlist_get(rusages, i); + + TEST_ASSERT_TRUE(v != NULL); + switch (i) { + case 0: + TEST_ASSERT_TRUE(strcmp(v->res, "mem") == 0); + TEST_ASSERT_TRUE(fabs(v->value - 20.0) < 0.001); + TEST_ASSERT_TRUE(fabs(v->duration - 18000) < 0.001); + TEST_ASSERT_TRUE(v->per_flag == 0); + TEST_ASSERT_TRUE(v->decay_flag == 1); + break; + case 1: + TEST_ASSERT_TRUE(strcmp(v->res, "lic") == 0); + TEST_ASSERT_TRUE(fabs(v->value - 55.0) < 0.001); + TEST_ASSERT_TRUE(fabs(v->duration - 1200) < 0.001); + TEST_ASSERT_TRUE(v->per_flag == 0); + TEST_ASSERT_TRUE(v->decay_flag == 0); + break; + default: + break; + } + printf("rusage: %s %f %d %f %d\n", v->res, v->value, v->per_flag, + v->duration, v->decay_flag); + + kill_rusage_value(v); + free(v); + } + + xlist_fini(rusages); + } +} + +void test_resreq1(void) +{ + char* resreqString + = "select[type==any] " + "rusage[mem=20:duration=300:decay=1,lic=55:duration=20m:decay=0]"; + char* errmsg = NULL; + int rc = 0; + xce_resreq_t resreq; + + rc = parse_resreq(&resreq, resreqString, &errmsg); + TEST_ASSERT_TRUE(rc >= 0); + if (rc >= 0) { + int i; + xlist_t* rusages = NULL; + char* buf = NULL; + + TEST_ASSERT_TRUE(resreq.tag == XCE_RESREQ_PRIMARY); + + rusages = &(resreq.u.primary->rusages); + + for (i = 0; i < rusages->count; i++) { + rusage_value_t* v = (rusage_value_t*)xlist_get(rusages, i); + + TEST_ASSERT_TRUE(v != NULL); + switch (i) { + case 0: + TEST_ASSERT_TRUE(strcmp(v->res, "mem") == 0); + TEST_ASSERT_TRUE(fabs(v->value - 20.0) < 0.001); + TEST_ASSERT_TRUE(fabs(v->duration - 18000) < 0.001); + TEST_ASSERT_TRUE(v->per_flag == 0); + TEST_ASSERT_TRUE(v->decay_flag == 1); + break; + case 1: + TEST_ASSERT_TRUE(strcmp(v->res, "lic") == 0); + TEST_ASSERT_TRUE(fabs(v->value - 55.0) < 0.001); + TEST_ASSERT_TRUE(fabs(v->duration - 1200) < 0.001); + TEST_ASSERT_TRUE(v->per_flag == 0); + TEST_ASSERT_TRUE(v->decay_flag == 0); + break; + default: + break; + } + printf("rusage: %s %f %d %f %d\n", v->res, v->value, v->per_flag, + v->duration, v->decay_flag); + } + + rc = format_resreq(&buf, &resreq); + if (rc >= 0) { + printf("%s\n", buf); + } + + FREEUP(buf); + kill_resreq(&resreq); + } +} + +void test_resreq2(void) +{ + char* resreqString = "2*{rusage[mem=100:duration=20:decay=1]} + " + "4*{rusage[mem=80:duration=30:decay=1]}"; + char* errmsg = NULL; + int rc = 0; + xce_resreq_t resreq; + + memset(&resreq, 0x0, sizeof(resreq)); + + rc = parse_resreq(&resreq, resreqString, &errmsg); + TEST_ASSERT_TRUE(rc >= 0); + if (rc >= 0) { + char* buf = NULL; + + TEST_ASSERT_TRUE(resreq.tag == XCE_RESREQ_COMPOUND); + + rc = format_resreq(&buf, &resreq); + if (rc >= 0) { + printf("%s\n", buf); + } + + FREEUP(buf); + kill_resreq(&resreq); + } +} + +void test_resreq3(void) +{ + char* resreqString = "{2*{rusage[mem=100:duration=20:decay=1]} + " + "4*{rusage[mem=80:duration=30:decay=1]}} || " + "{3*{rusage[mem=150:duration=15:decay=1]} + " + "6*{rusage[mem=120:duration=20:decay=1]}} "; + char* errmsg = NULL; + int rc = 0; + xce_resreq_t resreq; + + memset(&resreq, 0x0, sizeof(resreq)); + + rc = parse_resreq(&resreq, resreqString, &errmsg); + TEST_ASSERT_TRUE(rc >= 0); + if (rc >= 0) { + char* buf = NULL; + + TEST_ASSERT_TRUE(resreq.tag == XCE_RESREQ_ALTER); + + rc = format_resreq(&buf, &resreq); + if (rc >= 0) { + printf("%s\n", buf); + } + + if (buf != NULL) { + free(buf); + } + + kill_resreq(&resreq); + } +} + +void test_resreq(void) +{ + printf("\n>> resreq test\n\n"); + + RUN_TEST(test_parse_section1); + RUN_TEST(test_parse_section2); + RUN_TEST(test_parse_section_fail); + RUN_TEST(test_parse_rusage1); + RUN_TEST(test_parse_rusage2); + RUN_TEST(test_resreq_primary); + RUN_TEST(test_resreq1); + RUN_TEST(test_resreq2); + RUN_TEST(test_resreq3); +} diff --git a/src/lib/utils.c b/src/lib/utils.c index c1946142..50e83c7d 100644 --- a/src/lib/utils.c +++ b/src/lib/utils.c @@ -629,7 +629,7 @@ void block_sig(int signo) c -= rot(b, 24); \ } -uint32_t hash(uint32_t a, uint32_t b, uint32_t c, uint32_t d) +uint32_t hash4(uint32_t a, uint32_t b, uint32_t c, uint32_t d) { uint32_t i1 = a, i2 = b, i3 = c, i4 = d; @@ -648,7 +648,7 @@ uint32_t hash64(uint64_t x) uint32_t c = ((a & UMAX_BITS(16)) << 16) | (b >> 16); uint32_t d = ((b & UMAX_BITS(16)) << 16) | (a >> 16); - return hash(a, b, c, d); + return hash4(a, b, c, d); } uint32_t hash_string(const char* key) diff --git a/src/lib/xce_resreq.peg b/src/lib/xce_resreq.peg new file mode 100644 index 00000000..fe767d50 --- /dev/null +++ b/src/lib/xce_resreq.peg @@ -0,0 +1,119 @@ +%prefix "xce_resreq" +%value "char *" +%auxil "resreq_context_t *" +%source { + #include + #include + #include + + #if 0 + static const char *dbg_str[] = { "Evaluating rule", "Matched rule", "Abandoning rule" }; + #define PCC_DEBUG(auxil, event, rule, level, pos, buffer, length) \ + fprintf(stderr, "%*s%s %s @%zu [%.*s]\n", (int)((level) * 2), "", dbg_str[event], rule, pos, (int)(length), buffer) + #endif + #define PCC_ERROR(auxil) my_resreq_error(auxil) + + static void my_resreq_error(resreq_context_t *auxil) { + /* Calculate line/column from max_err */ + auxil->has_error = 1; + } +} + +%common { + #include "resreq.h" + #include "xlist.h" + + #define PCC_GETCHAR(auxil) \ + ({ int c = (auxil->input[auxil->pos] != '\0') ? (int)auxil->input[auxil->pos ++]: -1; \ + if (auxil->pos > auxil->err_pos) auxil->err_pos = auxil->pos; \ + c; \ + }) + +} + +statement <- _ resreq _ EOF + +resreq <- alter_resreq { + xce_resreq_t *resreq = auxil->resreq; + resreq->tag = XCE_RESREQ_ALTER; + resreq->u.alter = auxil->alter; + auxil->alter = NULL; + } + / compound_resreq { + xce_resreq_t *resreq = auxil->resreq; + if (resreq != NULL) { + resreq->tag = XCE_RESREQ_COMPOUND; + resreq->u.compound = auxil->compound; + auxil->compound = NULL; + } + } + / primary_resreq { + xce_resreq_t *resreq = auxil->resreq; + if (resreq != NULL) { + resreq->tag = XCE_RESREQ_PRIMARY; + resreq->u.primary = auxil->primary; + auxil->primary = NULL; + } + } + +alter_resreq <- alter_resreq_term _ ('||' _ alter_resreq_term _)* + +alter_resreq_term <- '{' _ compound_resreq _ '}' _ { + xce_alter_resreq_t *alter = auxil->alter; + if (alter == NULL) { + alter = (xce_alter_resreq_t *)calloc(1, sizeof(*alter)); + if (alter != NULL) { + xlist_init(&(alter->compounds), 8); + } + + auxil->alter = alter; + } + + if (alter != NULL) { + if (auxil->compound != NULL) { + xlist_store(&(alter->compounds), auxil->compound); + auxil->compound = NULL; + } + } + } + +compound_resreq <- compound_resreq_term _ ('+' _ compound_resreq_term _)* + +compound_resreq_term <- < int_num _ '*' _ '{' _ primary_resreq _ '}' _ + / '{' _ primary_resreq _ '}' _ > { + xce_compound_resreq_t *compound = auxil->compound; + if (compound == NULL) { + compound = (xce_compound_resreq_t *)calloc(1, sizeof(*compound)); + if (compound != NULL) { + xlist_init(&(compound->primaries), 8); + } + auxil->compound = compound; + } + + if (compound != NULL) { + xce_primary_resreq_t *primary = auxil->primary; + + if (primary != NULL) { + primary->minTasks = auxil->resreq_fact_count; + primary->maxTasks = auxil->resreq_fact_count; + xlist_store(&(compound->primaries), primary); + auxil->primary = NULL; + } + } + } + +primary_resreq <- < (! ('{' / '}' ) .)* > { + xce_primary_resreq_t *primary = (xce_primary_resreq_t *)calloc(1, sizeof(*primary)); + if (primary != NULL) { + auxil->primary = primary; + parse_resreq_primary(primary, (char *)$0, &(auxil->errmsg)); + } + } + +int_num <- < [0-9]+ > { auxil->resreq_fact_count = atoi($0); } + +EOL <- "\n" / "\r\n" / "\r" / "\0" + +_ <- [ \t]* + +EOF <- !. diff --git a/src/lib/xceapi.c b/src/lib/xceapi.c index 2d2eac6d..b235835a 100644 --- a/src/lib/xceapi.c +++ b/src/lib/xceapi.c @@ -105,6 +105,8 @@ int xce_get_with_condition(xce_ctx_t* ctx, xce_get_t* get, void*** data) return -EINVAL; } + memset(&getreply, 0x0, sizeof(getreply)); + ctx->reply.u.get = &getreply; rc = xce_get_req(ctx->ep, get); if (rc < 0) { diff --git a/src/meson.build b/src/meson.build index d2c0bfeb..7a483dcf 100644 --- a/src/meson.build +++ b/src/meson.build @@ -47,6 +47,7 @@ struct2json_dep = dependency('struct2json') libcyaml_dep = dependency('libcyaml') libyaml_dep = dependency('yaml-0.1') libtirpc_dep = dependency('libtirpc') +librtti_dep = dependency('librtti') yaml_deps = [ libcyaml_dep, diff --git a/src/nixSupport/xce.nix b/src/nixSupport/xce.nix index 792a8497..d9187f96 100644 --- a/src/nixSupport/xce.nix +++ b/src/nixSupport/xce.nix @@ -56,6 +56,10 @@ stdenv.mkDerivation { (extralib.overrideAttrs (oldAttrs: { separateDebugInfo = true; })) + (librtti.overrideAttrs (oldAttrs: { + separateDebugInfo = true; + })) + packcc ]; build-system = [ pkgs.meson ]; diff --git a/src/scheduler/include/sched/types.h b/src/scheduler/include/sched/types.h index 13b95fd3..5fb81e2a 100644 --- a/src/scheduler/include/sched/types.h +++ b/src/scheduler/include/sched/types.h @@ -2,6 +2,7 @@ #define _SCHED_TYPES_H_ 1 +#include #include #include diff --git a/src/scheduler/meson.build b/src/scheduler/meson.build index e19e4ec1..a1b21d71 100644 --- a/src/scheduler/meson.build +++ b/src/scheduler/meson.build @@ -18,6 +18,7 @@ incdir = include_directories('src', scheduler_deps = [ libxce_dep, + librtti_dep, math_dep, tinylog_dep, thread_dep diff --git a/src/scheduler/src/schedobj.c b/src/scheduler/src/schedobj.c index 6ce12af2..b338bdf2 100644 --- a/src/scheduler/src/schedobj.c +++ b/src/scheduler/src/schedobj.c @@ -1,6 +1,7 @@ #include #include #include +#include #include "controller.capnp.h" #include "kvmgr.h" diff --git a/src/scheduler/src/scheduler.c b/src/scheduler/src/scheduler.c index 298ed59f..8271b035 100644 --- a/src/scheduler/src/scheduler.c +++ b/src/scheduler/src/scheduler.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include