From: Alberto Leiva Popper Date: Thu, 5 Dec 2024 15:13:52 +0000 (-0300) Subject: Index sequences properly X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bf2c61cbd44e50ff140c80ef5c886ed817776a6d;p=thirdparty%2FFORT-validator.git Index sequences properly Postponed task from some previous refactor; the object was only partially being serialized. Fixes XXX-style TODO. --- diff --git a/src/cache.c b/src/cache.c index 07dab4c9..2ea30398 100644 --- a/src/cache.c +++ b/src/cache.c @@ -421,11 +421,20 @@ json2tbl(json_t *root, struct cache_table *tbl) struct cache_node *node; size_t urlen; - // XXX load (and save) seqs - if (json_get_ulong(root, "next", &tbl->seq.next_id)) + if (json_get_object(root, tbl->name, &root)) return; - if (json_get_array(root, tbl->name, &array)) + + if (json_get_seq(root, "seq", &tbl->seq)) { + // XXX this is grouds to reset the cache... + pr_op_warn("Unable to load the 'seq' child for the %s table.", + tbl->name); + return; + } + if (json_get_array(root, "nodes", &array)) { + pr_op_warn("Unable to load the 'nodes' child for the %s table.", + tbl->name); return; + } json_array_foreach(array, index, child) { node = json2node(child); @@ -564,7 +573,7 @@ tbl2json(struct cache_table *tbl) if (!json) return NULL; - if (json_add_ulong(json, "next", tbl->seq.next_id)) + if (json_add_seq(json, "seq", &tbl->seq)) goto fail; nodes = json_array_new(); diff --git a/src/file.c b/src/file.c index 98f224ab..970de0ed 100644 --- a/src/file.c +++ b/src/file.c @@ -252,6 +252,13 @@ cseq_init(struct cache_sequence *seq, char *prefix, bool free_prefix) seq->free_prefix = free_prefix; } +void +cseq_cleanup(struct cache_sequence *seq) +{ + if (seq->free_prefix) + free(seq->prefix); +} + char * cseq_next(struct cache_sequence *seq) { diff --git a/src/file.h b/src/file.h index 6cdf2604..a615d489 100644 --- a/src/file.h +++ b/src/file.h @@ -47,6 +47,7 @@ struct cache_sequence { }; void cseq_init(struct cache_sequence *, char *, bool); +void cseq_cleanup(struct cache_sequence *); char *cseq_next(struct cache_sequence *); /* diff --git a/src/json_util.c b/src/json_util.c index 0f2a3d70..4d2173a5 100644 --- a/src/json_util.c +++ b/src/json_util.c @@ -4,6 +4,7 @@ #include #include +#include "alloc.h" #include "common.h" #include "log.h" @@ -170,6 +171,35 @@ json_get_object(json_t *parent, char const *name, json_t **obj) return 0; } +int +json_get_seq(json_t *parent, char const *name, struct cache_sequence *seq) +{ + json_t *child; + char const *pfx; + int error; + + error = json_get_object(parent, name, &child); + if (error) + return error; + + error = json_get_str(child, "pfx", &pfx); + if (error < 0) + return error; + if (error > 0) + return pr_op_err( + "The '%s' JSON object is missing mandatory child 'pfx'.", + name + ); + error = json_get_ulong(child, "next", &seq->next_id); + if (error < 0) + return error; + + seq->prefix = pstrdup(pfx); + seq->pathlen = strlen(pfx) + 4; + seq->free_prefix = true; + return 0; +} + /* * Any unknown members should be treated as errors, RFC8416 3.1: * "JSON members that are not defined here MUST NOT be used in SLURM @@ -256,6 +286,33 @@ json_add_ts(json_t *parent, char const *name, time_t value) return 0; } +int +json_add_seq(json_t *parent, char const *name, + struct cache_sequence const *value) +{ + json_t *seq; + + seq = json_obj_new(); + if (seq == NULL) + return -EINVAL; + + if (json_add_ulong(seq, "next", value->next_id)) + goto fail; + if (json_add_str(seq, "pfx", value->prefix)) + goto fail; + + if (json_object_set_new(parent, name, seq)) + return pr_op_err( + "Cannot convert sequence [%s, %lu] to json; unknown cause.", + value->prefix, value->next_id + ); + + return 0; + +fail: json_decref(seq); + return -EINVAL; +} + #define OOM_PFX " Likely out of memory (but there is no contract)." json_t * diff --git a/src/json_util.h b/src/json_util.h index 6dfb7566..7d0261b6 100644 --- a/src/json_util.h +++ b/src/json_util.h @@ -17,6 +17,7 @@ #include #include "asn1/asn1c/INTEGER.h" +#include "file.h" /* * Contract of get functions: @@ -34,6 +35,7 @@ int json_get_ts(json_t *, char const *, time_t *); int json_get_str(json_t *, char const *, char const **); int json_get_array(json_t *, char const *, json_t **); int json_get_object(json_t *, char const *, json_t **); +int json_get_seq(json_t *, char const *, struct cache_sequence *); bool json_valid_members_count(json_t *, size_t); @@ -42,6 +44,7 @@ int json_add_ulong(json_t *, char const *, unsigned long); int json_add_bigint(json_t *, char const *, INTEGER_t *); int json_add_str(json_t *, char const *, char const *); int json_add_ts(json_t *, char const *, time_t); +int json_add_seq(json_t *, char const *, struct cache_sequence const *); json_t *json_obj_new(void); json_t *json_array_new(void); diff --git a/src/rrdp.c b/src/rrdp.c index 4c38952f..20e2b490 100644 --- a/src/rrdp.c +++ b/src/rrdp.c @@ -1383,7 +1383,7 @@ rrdp_state2json(struct rrdp_state *state) if (state->files) if (json_object_add(json, "files", files2json(state))) goto fail; - if (json_add_ulong(json, "next", state->seq.next_id)) + if (json_add_seq(json, "seq", &state->seq)) goto fail; if (!STAILQ_EMPTY(&state->delta_hashes)) if (json_object_add(json, TAGNAME_DELTAS, dh2json(state))) @@ -1431,18 +1431,46 @@ clear_delta_hashes(struct rrdp_state *state) } } +static int +json2dhs(json_t *json, struct rrdp_state *state) +{ + json_t *jdeltas; + size_t d, dn; + struct rrdp_hash *hash; + int error; + + STAILQ_INIT(&state->delta_hashes); + + error = json_get_array(json, TAGNAME_DELTAS, &jdeltas); + if (error) + return (error > 0) ? 0 : error; + + dn = json_array_size(jdeltas); + if (dn == 0) + return 0; + if (dn > config_get_rrdp_delta_threshold()) + dn = config_get_rrdp_delta_threshold(); + + for (d = 0; d < dn; d++) { + error = json2dh(json_array_get(jdeltas, d), &hash); + if (error) { + clear_delta_hashes(state); + return error; + } + STAILQ_INSERT_TAIL(&state->delta_hashes, hash, hook); + } + + return 0; +} + int rrdp_json2state(json_t *json, struct rrdp_state **result) { struct rrdp_state *state; char const *str; - json_t *jdeltas; - size_t d, dn; - struct rrdp_hash *hash; int error; state = pzalloc(sizeof(struct rrdp_state)); - STAILQ_INIT(&state->delta_hashes); error = json_get_str(json, TAGNAME_SESSION, &str); if (error < 0) @@ -1460,32 +1488,19 @@ rrdp_json2state(json_t *json, struct rrdp_state **result) goto revert_serial; } - error = json_get_array(json, TAGNAME_DELTAS, &jdeltas); - if (error) { - if (error > 0) - goto success; + error = json_get_seq(json, "seq", &state->seq); + if (error) goto revert_serial; - } - dn = json_array_size(jdeltas); - if (dn == 0) - goto success; - if (dn > config_get_rrdp_delta_threshold()) - dn = config_get_rrdp_delta_threshold(); - - for (d = 0; d < dn; d++) { - error = json2dh(json_array_get(jdeltas, d), &hash); - if (error) - goto revert_deltas; - STAILQ_INSERT_TAIL(&state->delta_hashes, hash, hook); - } + error = json2dhs(json, state); + if (error) + goto revert_seq; -success: *result = state; return 0; -revert_deltas: - clear_delta_hashes(state); +revert_seq: + cseq_cleanup(&state->seq); revert_serial: BN_free(state->session.serial.num); free(state->session.serial.str); @@ -1510,8 +1525,7 @@ rrdp_state_free(struct rrdp_state *state) map_cleanup(&file->map); free(file); } - if (state->seq.free_prefix) - free(state->seq.prefix); + cseq_cleanup(&state->seq); clear_delta_hashes(state); free(state); }