From efb5f2758506ef875e376e40e978b1f03bf0ef8c Mon Sep 17 00:00:00 2001 From: Alejandro Sirgo Rica Date: Tue, 21 May 2024 16:34:34 +0200 Subject: client: store image cache data in database Parse the 'cache' field of the refresh payload sent by the clients. Cache field structure in the payload: { ... 'cache': [ {'name': 'windows.img', 'size': 2432370213, checksum: '5d4dcc677bc19f40a647d0002f4ade90'}, {'name': 'linux.img', 'size': 243234534213, checksum: '3eb22f888f88a55ad954f55644e1192e'}, ] ... } Store that data in the 'cache' table of the database so it can be obtained later on. The table contains the following fields: - clientid: the numeric identifier of the client. - imagename: name of the image in cache. - size: size in bytes of the image in cache. - checksum: checksum of the image in cache. --- src/client.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++------- src/json.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/json.h | 14 +++++++++++++ 3 files changed, 141 insertions(+), 7 deletions(-) diff --git a/src/client.c b/src/client.c index 9c4ec59..8551d50 100644 --- a/src/client.c +++ b/src/client.c @@ -381,24 +381,65 @@ static int og_dbi_queue_autorun(uint32_t computer_id, uint32_t proc_id) return 0; } +static int og_update_cache_info(struct og_dbi *dbi, struct list_head *cache_list, int clientid) +{ + struct og_cache_image *cache_image; + const char *msglog; + dbi_result result; + + /* Remove old cache image info */ + result = dbi_conn_queryf(dbi->conn, + "DELETE FROM cache WHERE clientid=%d;", clientid); + + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", + __func__, __LINE__, msglog); + return false; + } + dbi_result_free(result); + + /* Add new cache image info */ + list_for_each_entry(cache_image, cache_list, list) { + result = dbi_conn_queryf(dbi->conn, + "INSERT INTO cache (clientid, imagename, size, checksum)" + "VALUES (%d, '%s', %lu, '%s')", + clientid, + cache_image->name, + cache_image->size, + cache_image->checksum); + + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", + __func__, __LINE__, msglog); + return false; + } + dbi_result_free(result); + } + + return 0; +} + static int og_resp_refresh(json_t *data, struct og_client *cli) { struct og_partition partitions[OG_PARTITION_MAX] = {}; struct og_partition disks[OG_DISK_MAX] = {}; const char *serial_number = NULL; struct og_computer computer = {}; + json_t *value, *cache = NULL; const char *status = NULL; + LIST_HEAD(cache_list); char cfg[4096] = {}; struct og_dbi *dbi; uint32_t link = 0; const char *key; unsigned int i; - json_t *value; int err = 0; bool res; if (json_typeof(data) != JSON_OBJECT) - return -1; + goto err_out; json_object_foreach(data, key, value) { if (!strcmp(key, "disk_setup")) { @@ -411,10 +452,13 @@ static int og_resp_refresh(json_t *data, struct og_client *cli) err = og_json_parse_string(value, &status); } else if (!strcmp(key, "link")) { err = og_json_parse_uint(value, &link); + } else if (!strcmp(key, "cache")) { + err = og_json_parse_cache(value, &cache_list); + cache = value; } if (err < 0) - return err; + goto err_out; } if (link) @@ -470,13 +514,18 @@ static int og_resp_refresh(json_t *data, struct og_client *cli) if (!dbi) { syslog(LOG_ERR, "cannot open connection database (%s:%d)\n", __func__, __LINE__); - return -1; + goto err_out; } err = og_dbi_get_computer_info(dbi, &computer, cli->addr.sin_addr); if (err < 0) { og_dbi_close(dbi); - return -1; + goto err_out; + } + + if (cache && og_update_cache_info(dbi, &cache_list, computer.id) < 0) { + og_dbi_close(dbi); + goto err_out; } res = actualizaConfiguracion(dbi, cfg, computer.id); @@ -484,17 +533,21 @@ static int og_resp_refresh(json_t *data, struct og_client *cli) if (!res) { syslog(LOG_ERR, "Problem updating client configuration\n"); - return -1; + goto err_out; } if (!cli->autorun && computer.procedure_id) { cli->autorun = true; if (og_dbi_queue_autorun(computer.id, computer.procedure_id)) - return -1; + goto err_out; } + og_cache_image_free(&cache_list); return 0; +err_out: + og_cache_image_free(&cache_list); + return -1; } static bool og_dbi_update_image(struct og_dbi *dbi, diff --git a/src/json.c b/src/json.c index c7ae761..11e66eb 100644 --- a/src/json.c +++ b/src/json.c @@ -236,3 +236,70 @@ int og_json_parse_procedure(json_t *element, struct og_procedure *proc) return err; } + +void og_cache_image_free(struct list_head *cache_list) +{ + struct og_cache_image *cache_item, *tmp; + + list_for_each_entry_safe(cache_item, tmp, cache_list, list) { + list_del(&cache_item->list); + free(cache_item); + } +} + +int og_json_parse_cache(json_t *element, struct list_head *cache_list) +{ + uint64_t required_flags = OG_PARAM_IMG_NAME | OG_PARAM_IMG_SIZE | OG_PARAM_IMG_CHECKSUM; + struct og_cache_image *cache_item; + json_t *json_elem, *value; + const char *key; + unsigned long i; + uint64_t flags; + int err = 0; + + if (json_typeof(element) != JSON_ARRAY) + return -1; + + for (i = 0; i < json_array_size(element); i++) { + cache_item = calloc(1, sizeof(struct og_cache_image)); + flags = 0UL; + + if (!cache_item) + return -1; + + json_elem = json_array_get(element, i); + + if (json_typeof(json_elem) != JSON_OBJECT) { + free(cache_item); + return -1; + } + + json_object_foreach(json_elem, key, value) { + if (!strcmp(key, "name")) { + err = og_json_parse_string(value, &cache_item->name); + flags |= OG_PARAM_IMG_NAME; + } else if (!strcmp(key, "size")) { + err = og_json_parse_uint64(value, &cache_item->size); + flags |= OG_PARAM_IMG_SIZE; + } else if (!strcmp(key, "checksum")) { + err = og_json_parse_string(value, &cache_item->checksum); + flags |= OG_PARAM_IMG_CHECKSUM; + } else + err = -1; + + if (err < 0) { + free(cache_item); + return err; + } + } + + if ((flags & required_flags) != required_flags) { + free(cache_item); + return -1; + } + + list_add_tail(&cache_item->list, cache_list); + } + + return err; +} diff --git a/src/json.h b/src/json.h index e37f1b2..d3838cf 100644 --- a/src/json.h +++ b/src/json.h @@ -132,4 +132,18 @@ struct og_procedure { int og_json_parse_procedure(json_t *element, struct og_procedure *proc); +#define OG_PARAM_IMG_NAME (1UL << 0) +#define OG_PARAM_IMG_SIZE (1UL << 1) +#define OG_PARAM_IMG_CHECKSUM (1UL << 2) + +struct og_cache_image { + const char *name; + uint64_t size; + const char *checksum; + struct list_head list; +}; + +void og_cache_image_free(struct list_head *cache_list); +int og_json_parse_cache(json_t *element, struct list_head *cache_list); + #endif -- cgit v1.2.3-18-g5258