From ef576d966adf187ec84c4f9f3fe8c39645330c8a Mon Sep 17 00:00:00 2001 From: Marko Lindqvist Date: Thu, 6 Jan 2022 19:04:17 +0200 Subject: [PATCH 42/42] Cache ruleset modpacks just once See osdn #43569 Signed-off-by: Marko Lindqvist --- common/modpack.c | 10 ++++++ common/modpack.h | 3 ++ server/gamehand.c | 77 ++++++++++++++++++++++++++++++----------------- 3 files changed, 63 insertions(+), 27 deletions(-) diff --git a/common/modpack.c b/common/modpack.c index 480f0bc539..96730b4eb3 100644 --- a/common/modpack.c +++ b/common/modpack.c @@ -195,3 +195,13 @@ const char *modpack_file_from_ruleset_cache(const char *name) return NULL; } + +/************************************************************************//** + Call callback for each item in the ruleset cache. +****************************************************************************/ +void modpack_ruleset_cache_iterate(mrc_cb cb, void *data) +{ + modpack_cache_iterate(modpack_rulesets, item) { + cb(item->modpack_name, item->filename, data); + } modpack_cache_iterate_end; +} diff --git a/common/modpack.h b/common/modpack.h index 06da618a24..366b4eb930 100644 --- a/common/modpack.h +++ b/common/modpack.h @@ -36,6 +36,9 @@ bool modpack_check_capabilities(struct section_file *file, const char *us_capstr const char *modpack_serv_file(struct section_file *sf); const char *modpack_rulesetdir(struct section_file *sf); +typedef void (*mrc_cb)(const char*, const char *, void *data); +void modpack_ruleset_cache_iterate(mrc_cb cb, void *data); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/server/gamehand.c b/server/gamehand.c index 5e53a63866..550ee24222 100644 --- a/server/gamehand.c +++ b/server/gamehand.c @@ -1080,6 +1080,34 @@ const char *new_challenge_filename(struct connection *pc) return get_challenge_filename(pc); } +struct mrc_data { + int count; + struct packet_ruleset_choices *packet; +}; + +/************************************************************************//** + Callback called from modpack ruleset cache iteration. +****************************************************************************/ +static void ruleset_cache_cb(const char *mp_name, const char *filename, + void *data_in) +{ + struct mrc_data *data = (struct mrc_data *)data_in; + const int maxlen = sizeof(data->packet->rulesets[data->count]); + + if (data->count >= MAX_NUM_RULESETS) { + log_verbose("Can't send more than %d ruleset names to client, " + "skipping some", MAX_NUM_RULESETS); + return; + } + + if (fc_strlcpy(data->packet->rulesets[data->count], mp_name, maxlen) < maxlen) { + data->count++; + } else { + log_verbose("Modpack name '%s' too long to send to client, skipped", + mp_name); + } +} + /************************************************************************//** Call this on a connection with HACK access to send it a set of ruleset choices. Probably this should be called immediately when granting @@ -1087,43 +1115,38 @@ const char *new_challenge_filename(struct connection *pc) ****************************************************************************/ static void send_ruleset_choices(struct connection *pc) { - struct fileinfo_list *ruleset_choices; struct packet_ruleset_choices packet; - size_t i = 0; + static bool rulesets_cached = FALSE; + struct mrc_data data; - ruleset_choices = get_modpacks_list(); + if (!rulesets_cached) { + struct fileinfo_list *ruleset_choices; - fileinfo_list_iterate(ruleset_choices, pfile) { - const int maxlen = sizeof(packet.rulesets[i]); - struct section_file *sf; + ruleset_choices = get_modpacks_list(); - if (i >= MAX_NUM_RULESETS) { - log_verbose("Can't send more than %d ruleset names to client, " - "skipping some", MAX_NUM_RULESETS); - break; - } - - sf = secfile_load(pfile->fullname, FALSE); + fileinfo_list_iterate(ruleset_choices, pfile) { + struct section_file *sf; - if (sf != NULL) { - const char *name = modpack_cache_ruleset(sf); + sf = secfile_load(pfile->fullname, FALSE); - if (name != NULL) { - if (fc_strlcpy(packet.rulesets[i], name, maxlen) < maxlen) { - i++; - } else { - log_verbose("Modpack name '%s' too long to send to client, skipped", name); - } + if (sf != NULL) { + modpack_cache_ruleset(sf); + secfile_destroy(sf); } + } fileinfo_list_iterate_end; - secfile_destroy(sf); - } - } fileinfo_list_iterate_end; - packet.ruleset_count = i; + fileinfo_list_destroy(ruleset_choices); - send_packet_ruleset_choices(pc, &packet); + rulesets_cached = TRUE; + } - fileinfo_list_destroy(ruleset_choices); + data.count = 0; + data.packet = &packet; + modpack_ruleset_cache_iterate(ruleset_cache_cb, &data); + + packet.ruleset_count = data.count; + + send_packet_ruleset_choices(pc, &packet); } /************************************************************************//** -- 2.34.1