From c7bfc370ae8974302cf1e316b3e03d0e6e960e0c Mon Sep 17 00:00:00 2001 From: Alejandro Sirgo Rica Date: Tue, 24 Sep 2024 13:38:34 +0200 Subject: src: add used_size and free_size to partition data Extend database table ordenadores_particiones to add new "used_size" and "free_size" fields. FIELD TYPE | tamano | bigint | | uso | tinyint | | used_size | bigint | | free_size | bigint | "tamano" is the field storing the total size of the partition. "uso" is a field storing the integer percentage of use, it is preserved for backwards compatibility with scritps that access the database. "used_size" and "free_size" contain the used and free partition size in bytes. Old response from ogClient for /cache/delete, /cache/fetch and /image/restore: { 'cache': [ {'name': 'windows.img', 'size': 2432370213, checksum: '5d4dcc677bc19f40a647d0002f4ade90'}, {'name': 'linux.img', 'size': 243234534213, checksum: '3eb22f888f88a55ad954f55644e1192e'} ] } New response: { 'cache': { 'used_size': 4520232322423, 'free_size': 48273465287452945, 'images': [ {'name': 'windows.img', 'size': 2432370213, checksum: '5d4dcc677bc19f40a647d0002f4ade90'}, {'name': 'linux.img', 'size': 243234534213, checksum: '3eb22f888f88a55ad954f55644e1192e'} ] } } Parse the new "free_size" and "used_size" fields of each partition data in the response payload of /refresh Parse "free_size" and "used_size" fields of the cache data in the reponse payload of /image/restore, /cache/delete and /cache/fetch Replace "used_size" field of GET /client/setup with the value of the new database field "used_size" --- src/client.c | 72 ++++++++++++++++++++++++++++++++++++++++++------------------ src/json.c | 45 +++++++++++++++++++++++++++++++++++-- src/json.h | 16 ++++++++++++-- src/rest.c | 12 ++++++---- src/schema.c | 31 ++++++++++++++++++++++++++ 5 files changed, 147 insertions(+), 29 deletions(-) diff --git a/src/client.c b/src/client.c index e3d8dec..bbe4c15 100644 --- a/src/client.c +++ b/src/client.c @@ -381,7 +381,8 @@ static int og_resp_software(json_t *data, struct og_client *cli) OG_PARAM_PART_FILESYSTEM | \ OG_PARAM_PART_OS | \ OG_PARAM_PART_SIZE | \ - OG_PARAM_PART_USED_SIZE) + OG_PARAM_PART_USED_SIZE | \ + OG_PARAM_PART_FREE_SIZE) static int og_json_parse_partition_array(json_t *value, struct og_partition *partitions, @@ -406,7 +407,7 @@ static int og_json_parse_partition_array(json_t *value, return 0; } -static int og_update_cache_info(struct og_dbi *dbi, struct list_head *cache_list, int clientid) +static int og_update_cache_info(struct og_dbi *dbi, struct og_cache_data *cache_data, struct list_head *cache_list, int clientid) { struct og_cache_image *cache_image; const char *msglog; @@ -443,6 +444,23 @@ static int og_update_cache_info(struct og_dbi *dbi, struct list_head *cache_list dbi_result_free(result); } + /* Update partition sizes */ + result = dbi_conn_queryf(dbi->conn, + "UPDATE ordenadores_particiones SET used_size = %lu, free_size = %lu" + " WHERE idordenador = %d AND codpar = %d", + cache_data->used_size, + cache_data->free_size, + clientid, + 202); + + 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; } @@ -487,6 +505,7 @@ static int og_update_boot_entries(struct og_dbi *dbi, struct list_head *boot_ent static int og_resp_update_cache(json_t *data, struct og_client *cli) { + struct og_cache_data cache_data = {}; struct og_computer computer = {}; json_t *value, *cache = NULL; LIST_HEAD(cache_list); @@ -501,9 +520,14 @@ static int og_resp_update_cache(json_t *data, struct og_client *cli) json_object_foreach(data, key, value) { if (!strcmp(key, "cache")) { - err = og_json_parse_cache(value, &cache_list); + err = og_json_parse_cache(value, &cache_data, &cache_list); cache = value; } + + if (err < 0) { + og_cache_image_free(&cache_list); + return err; + } } if (!cache) { @@ -526,7 +550,7 @@ static int og_resp_update_cache(json_t *data, struct og_client *cli) return -1; } - err = og_update_cache_info(dbi, &cache_list, computer.id); + err = og_update_cache_info(dbi, &cache_data, &cache_list, computer.id); if (err < 0) { og_cache_image_free(&cache_list); og_dbi_close(dbi); @@ -548,6 +572,7 @@ struct og_part { uint32_t code; uint64_t size; uint64_t used_size; + uint64_t free_size; }; static bool og_update_client_disk_info(struct og_dbi *dbi, @@ -602,8 +627,9 @@ static bool og_update_client_disk_info(struct og_dbi *dbi, result_update = dbi_conn_queryf(dbi->conn, "INSERT INTO ordenadores_particiones(" "idordenador, numdisk, numpar, codpar, tamano, uso, " - "idsistemafichero, idnombreso, disk_type, idimagen)" - " VALUES(%d,%s,0,0x%s,%s,0,0,0,'%s',0)", + "idsistemafichero, idnombreso, disk_type, idimagen," + "used_size, free_size)" + " VALUES(%d,%s,0,0x%s,%s,0,0,0,'%s',0,0,0)", computer_id, disks[i].disk, disks[i].code, @@ -656,7 +682,8 @@ static bool og_update_client_disk_info(struct og_dbi *dbi, partitions[i].disk, partitions[i].number); result = dbi_conn_queryf(dbi->conn, - "SELECT numdisk, numpar, tamano, uso, idsistemafichero, idnombreso, codpar" + "SELECT numdisk, numpar, tamano, idsistemafichero, idnombreso, " + " codpar, used_size, free_size" " FROM ordenadores_particiones" " WHERE idordenador=%d AND numdisk=%s AND numpar=%s", computer_id, partitions[i].disk, partitions[i].number); @@ -668,9 +695,10 @@ static bool og_update_client_disk_info(struct og_dbi *dbi, } reported_part.size = strtoull(partitions[i].size, NULL, 0); - reported_part.used_size = strtoull(partitions[i].used_size, NULL, 0); reported_part.code = strtoul(partitions[i].code, NULL, 16); reported_part.filesystem = get_filesystem_id(partitions[i].filesystem); + reported_part.used_size = partitions[i].used_size; + reported_part.free_size = partitions[i].free_size; if (og_dbi_get_os_id(dbi, partitions[i].os, &reported_part.os) < 0) { return false; @@ -680,16 +708,18 @@ static bool og_update_client_disk_info(struct og_dbi *dbi, result_update = dbi_conn_queryf(dbi->conn, "INSERT INTO ordenadores_particiones(" "idordenador, numdisk, numpar, codpar, tamano, uso, " - "idsistemafichero, idnombreso, idimagen)" - " VALUES(%d,%s,%s,0x%d,%s,%d,%d,%d,0)", + "idsistemafichero, idnombreso, idimagen, " + "used_size, free_size)" + " VALUES(%d,%s,%s,0x%d,%s,0,%d,%d,0,%lu,%lu)", computer_id, partitions[i].disk, partitions[i].number, reported_part.code, partitions[i].size, - reported_part.used_size, reported_part.filesystem, - reported_part.os); + reported_part.os, + partitions[i].used_size, + partitions[i].free_size); if (!result_update) { dbi_conn_error(dbi->conn, &msglog); syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", @@ -706,10 +736,11 @@ static bool og_update_client_disk_info(struct og_dbi *dbi, } cur_part.size = dbi_result_get_longlong(result, "tamano"); - cur_part.used_size = dbi_result_get_longlong(result, "uso"); cur_part.code = dbi_result_get_int(result, "codpar"); cur_part.filesystem = dbi_result_get_uint(result, "idsistemafichero"); cur_part.os = dbi_result_get_uint(result, "idnombreso"); + cur_part.used_size = dbi_result_get_longlong(result, "used_size"); + cur_part.free_size = dbi_result_get_longlong(result, "free_size"); dbi_result_free(result); if (cur_part.size != reported_part.size || @@ -720,14 +751,13 @@ static bool og_update_client_disk_info(struct og_dbi *dbi, "UPDATE ordenadores_particiones SET " " codpar=0x%s," " tamano=%s," - " uso=%d," " idsistemafichero=%d," " idnombreso=%d," " idimagen=0," " idperfilsoft=0," " fechadespliegue=NULL" " WHERE idordenador=%d AND numdisk=%s AND numpar=%s", - partitions[i].code, partitions[i].size, reported_part.used_size, + partitions[i].code, partitions[i].size, reported_part.filesystem, reported_part.os, computer_id, partitions[i].disk, partitions[i].number); @@ -751,9 +781,9 @@ static bool og_update_client_disk_info(struct og_dbi *dbi, result_update = dbi_conn_queryf(dbi->conn, "UPDATE ordenadores_particiones SET " - " uso=%d" + " uso=0, used_size=%lu, free_size=%lu" " WHERE idordenador=%d AND numdisk=%s AND numpar=%s", - reported_part.used_size, computer_id, + partitions[i].used_size, partitions[i].free_size, computer_id, partitions[i].disk, partitions[i].number); if (!result_update) { dbi_conn_error(dbi->conn, &msglog); @@ -788,12 +818,13 @@ 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] = {}; uint32_t num_disks = 0, num_partitions = 0; + struct og_cache_data cache_data = {}; const char *serial_number = NULL; struct og_computer computer = {}; - json_t *value, *cache = NULL; const char *status = NULL; LIST_HEAD(boot_entry_list); LIST_HEAD(cache_list); + json_t *value = NULL; struct og_dbi *dbi; uint32_t link = 0; const char *key; @@ -819,8 +850,7 @@ static int og_resp_refresh(json_t *data, struct og_client *cli) } else if (!strcmp(key, "efi")) { err = og_json_parse_efi(value, &boot_entry_list); } else if (!strcmp(key, "cache")) { - err = og_json_parse_cache(value, &cache_list); - cache = value; + err = og_json_parse_cache(value, &cache_data, &cache_list); } if (err < 0) @@ -856,7 +886,7 @@ static int og_resp_refresh(json_t *data, struct og_client *cli) goto err_out; } - if (cache && og_update_cache_info(dbi, &cache_list, computer.id) < 0) { + if (og_update_cache_info(dbi, &cache_data, &cache_list, computer.id) < 0) { og_dbi_close(dbi); goto err_out; } diff --git a/src/json.c b/src/json.c index d33c647..05b725c 100644 --- a/src/json.c +++ b/src/json.c @@ -128,8 +128,11 @@ int og_json_parse_partition(json_t *element, struct og_partition *part, err = og_json_parse_string(value, &part->os); flags |= OG_PARAM_PART_OS; } else if (!strcmp(key, "used_size")) { - err = og_json_parse_string(value, &part->used_size); + err = og_json_parse_uint64(value, &part->used_size); flags |= OG_PARAM_PART_USED_SIZE; + } else if (!strcmp(key, "free_size")) { + err = og_json_parse_uint64(value, &part->free_size); + flags |= OG_PARAM_PART_FREE_SIZE; } if (err < 0) @@ -248,7 +251,7 @@ void og_cache_image_free(struct list_head *cache_list) } } -int og_json_parse_cache(json_t *element, struct list_head *cache_list) +static int og_json_parse_cache_images(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; @@ -305,6 +308,44 @@ int og_json_parse_cache(json_t *element, struct list_head *cache_list) return err; } +int og_json_parse_cache(json_t *element, struct og_cache_data *cache_data, struct list_head *cache_list) +{ + uint64_t required_flags = OG_PARAM_CACHE_FREE_SIZE | OG_PARAM_CACHE_USED_SIZE | OG_PARAM_CACHE_IMAGES; + uint64_t flags = 0UL; + const char *key; + json_t *value; + int err = 0; + + if (json_typeof(element) != JSON_OBJECT) + return -1; + + if (json_object_size(element) == 0) + return 0; + + json_object_foreach(element, key, value) { + if (!strcmp(key, "used_size")) { + err = og_json_parse_uint64(value, &cache_data->used_size); + flags |= OG_PARAM_CACHE_USED_SIZE; + } else if (!strcmp(key, "free_size")) { + err = og_json_parse_uint64(value, &cache_data->free_size); + flags |= OG_PARAM_CACHE_FREE_SIZE; + } else if (!strcmp(key, "images")) { + err = og_json_parse_cache_images(value, cache_list); + flags |= OG_PARAM_CACHE_IMAGES; + } else + err = -1; + + if (err < 0) { + return err; + } + } + + if ((flags & required_flags) != required_flags) + return -1; + + return err; +} + void og_boot_entry_free(struct list_head *boot_entry_list) { struct og_boot_entry *boot_entry, *tmp; diff --git a/src/json.h b/src/json.h index e43531e..ff5c8ad 100644 --- a/src/json.h +++ b/src/json.h @@ -22,6 +22,7 @@ int og_json_parse_bool(const json_t *element, bool *value); #define OG_PARAM_PART_OS (1UL << 6) #define OG_PARAM_PART_USED_SIZE (1UL << 7) #define OG_PARAM_PART_DISK_TYPE (1UL << 8) +#define OG_PARAM_PART_FREE_SIZE (1UL << 9) struct og_partition { const char *disk; @@ -32,7 +33,9 @@ struct og_partition { const char *filesystem; const char *format; const char *os; - const char *used_size; + uint64_t used_size; + uint64_t free_size; + }; #define OG_DISK_MAX 4 @@ -128,8 +131,17 @@ struct og_cache_image { struct list_head list; }; +#define OG_PARAM_CACHE_USED_SIZE (1UL << 0) +#define OG_PARAM_CACHE_FREE_SIZE (1UL << 1) +#define OG_PARAM_CACHE_IMAGES (1UL << 2) + +struct og_cache_data { + uint64_t used_size; + uint64_t free_size; +}; + void og_cache_image_free(struct list_head *cache_list); -int og_json_parse_cache(json_t *element, struct list_head *cache_list); +int og_json_parse_cache(json_t *element, struct og_cache_data *cache_data, struct list_head *cache_list); #define OG_PARAM_EFI_ENTRIES (1UL << 0) diff --git a/src/rest.c b/src/rest.c index 917b72b..87259cf 100644 --- a/src/rest.c +++ b/src/rest.c @@ -1723,7 +1723,8 @@ static int og_cmd_get_client_setup(json_t *element, int filesystem; int format; int os; - int used_size; + uint64_t used_size; + uint64_t free_size; int image; int software; } partition; @@ -1761,8 +1762,8 @@ static int og_cmd_get_client_setup(json_t *element, result = dbi_conn_queryf(dbi->conn, "SELECT numdisk, numpar, codpar, tamano, " - " uso, idsistemafichero, idnombreso, " - " idimagen, idperfilsoft " + " idsistemafichero, idnombreso, " + " idimagen, idperfilsoft, used_size, free_size " "FROM ordenadores_particiones " "INNER JOIN ordenadores " "ON ordenadores.idordenador = ordenadores_particiones.idordenador " @@ -1784,11 +1785,12 @@ static int og_cmd_get_client_setup(json_t *element, partition.number = dbi_result_get_int(result, "numpar"); partition.code = dbi_result_get_int(result, "codpar"); partition.size = dbi_result_get_longlong(result, "tamano"); - partition.used_size = dbi_result_get_int(result, "uso"); partition.filesystem = dbi_result_get_int(result, "idsistemafichero"); partition.os = dbi_result_get_int(result, "idnombreso"); partition.image = dbi_result_get_int(result, "idimagen"); partition.software = dbi_result_get_int(result, "idperfilsoft"); + partition.used_size = dbi_result_get_longlong(result, "used_size"); + partition.free_size = dbi_result_get_longlong(result, "free_size"); partition_json = json_object(); if (!partition_json) { @@ -1808,6 +1810,8 @@ static int og_cmd_get_client_setup(json_t *element, json_integer(partition.size)); json_object_set_new(partition_json, "used_size", json_integer(partition.used_size)); + json_object_set_new(partition_json, "free_size", + json_integer(partition.free_size)); json_object_set_new(partition_json, "filesystem", json_integer(partition.filesystem)); json_object_set_new(partition_json, "os", diff --git a/src/schema.c b/src/schema.c index fd1d573..f7fceae 100644 --- a/src/schema.c +++ b/src/schema.c @@ -434,6 +434,36 @@ static int og_dbi_schema_v10(struct og_dbi *dbi) return 0; } +static int og_dbi_schema_v11(struct og_dbi *dbi) +{ + const char *msglog; + dbi_result result; + + syslog(LOG_DEBUG, "Adding free_size and used_size to ordenadores_particiones\n"); + result = dbi_conn_query(dbi->conn, + "ALTER TABLE `ordenadores_particiones` " + "ADD `used_size` BIGINT DEFAULT '0' AFTER `cache`, " + "ADD `free_size` BIGINT DEFAULT '0' AFTER `used_size`;"); + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_INFO, "Error when updating ordenadores_particiones table (%s:%d) %s\n", + __func__, __LINE__, msglog); + return -1; + } + dbi_result_free(result); + + result = dbi_conn_query(dbi->conn, "UPDATE version SET version = 11"); + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_INFO, "Could not update version row (%s:%d) %s\n", + __func__, __LINE__, msglog); + return -1; + } + dbi_result_free(result); + + return 0; +} + static struct og_schema_version { int version; int (*update)(struct og_dbi *dbi); @@ -448,6 +478,7 @@ static struct og_schema_version { { .version = 8, .update = og_dbi_schema_v8, }, { .version = 9, .update = og_dbi_schema_v9, }, { .version = 10, .update = og_dbi_schema_v10,}, + { .version = 11, .update = og_dbi_schema_v11,}, { 0, NULL }, }; -- cgit v1.2.3-18-g5258