From aadf045f41b66ceb7db514a88f29d46a1b95527e Mon Sep 17 00:00:00 2001 From: Ronald Date: Sun, 21 Jul 2024 00:15:37 +0100 Subject: [PATCH] Re-work somethings in codebase * Move code to seperate _main procedure to allow better use of core:mem * functionality whilst testing and developing. * Use builtin ini parser * Fix memory leaks * Currently some code is commented out whilst working way through current memory leaks --- client.odin | 206 ++++++++++++++++++++++++++++++++++++++++++++-------- types.odin | 7 ++ 2 files changed, 181 insertions(+), 32 deletions(-) diff --git a/client.odin b/client.odin index 01dc55e..46e53c5 100644 --- a/client.odin +++ b/client.odin @@ -1,12 +1,14 @@ package main +import "core:encoding/ini" +import "core:encoding/json" import "core:fmt" import "core:log" +import "core:mem" import "core:os" -import "core:strings" import "core:strconv" +import "core:strings" -import "libs/ini" import "libs/http" import "libs/http/client" import "libs/sysinfo" @@ -15,37 +17,62 @@ CONFIG_FILE_PATH :: "./config.ini" PC: Program_Config = {} -get_config :: proc(config_file_path: string) -> Maybe(ini.INI) { - bytes, ok := os.read_entire_file_from_filename(config_file_path) - if !ok { - return nil - } - defer delete(bytes) +// get_config :: proc(config_file_path: string) -> Maybe(ini.INI) { + // bytes, ok := os.read_entire_file_from_filename(config_file_path) + // if !ok { + // return nil + // } + // defer delete(bytes) - config, res := ini.parse(bytes) - if res.err == ini.ParseErr.EOF { - return config - } + // config, res := ini.parse(bytes) + // if res.err == ini.ParseErr.EOF { + // return config + // } - return nil -} + // return nil +// } -// Returns the host ID, of if the host doesn't exist in -// LSM then it will return -1 -get_host_id :: proc(hostname: string) -> (int, bool) { +api_request_get :: proc(endpoint: string) -> (body: client.Body_Type, allocation: bool, ok: bool) { request: client.Request client.request_init(&request, .Get) defer client.request_destroy(&request) - response, err := client.request(&request, fmt.tprintf("%s/get_host_id_for_hostname/%s", PC.api_address, hostname)) + response, err := client.request(&request, endpoint) if err != nil { - return 0, false + return nil, false, false } defer client.response_destroy(&response) - body, allocation, body_err := client.response_body(&response) + body_err: client.Body_Error + body, allocation, body_err = client.response_body(&response) if body_err != nil { - return 0, false + return nil, false, false + } + + return body, allocation, true +} + +// api_request_post :: proc(endpoint: string, post_body: any) -> (body: client.Body_Type, allocation: bool, ok: bool) { + // request: client.Request + // client.requset_init(&request, .Post) + // defer client.request_destroy(&request) + + // if err := client.with_json(&request, post_body); err != nil do return nil, false, false + + // response, err := client.request(&request, endpoint) + // if err != nil do return nil, false, false + // defer client.response_destroy(&response) + +// } + +// Returns the host ID, or if the host doesn't exist in +// LSM then it will return -1 +get_host_id :: proc(hostname: string) -> (int, bool) { + endpoint := fmt.tprintf("%s/get_host_id_for_hostname/%s", PC.api_address, hostname) + + body, allocation, ok := api_request_get(endpoint) + if !ok { + return 0, ok } defer client.body_destroy(body, allocation) @@ -54,13 +81,88 @@ get_host_id :: proc(hostname: string) -> (int, bool) { return host_id, true } -main :: proc() { +get_cpus_for_host_from_id :: proc(host_id: int) -> (cpus: [dynamic]CPU, ok: bool) { + endpoint := fmt.tprintf("%s/get_cpus_by_host_id/%d", PC.api_address, host_id) + + body, allocation, request_ok := api_request_get(endpoint) + if !request_ok { + return nil, false + } + defer client.body_destroy(body, allocation) + + if body.(client.Body_Plain) == "[]" { + return cpus, true + } + + body_data := transmute([]u8)body.(client.Body_Plain) + json_data, err := json.parse(body_data) + if err != .None { + return nil, false + } + defer json.destroy_value(json_data) + + root := json_data.(json.Array) + + for cpu, i in root { + resize(&cpus, len(cpus)+1) + + cpu_object := cpu.(json.Object) + + cpus[i].id = int(cpu_object["id"].(json.Float)) + cpus[i].socket = int(cpu_object["socket"].(json.Float)) + cpus[i].name = strings.clone(cpu_object["name"].(json.String)) + } + + return cpus, true +} + +destroy_cpus :: proc(cpus: [dynamic]CPU) { + for cpu in cpus { + delete(cpu.name) + } + delete(cpus) +} + +add_cpu_to_lsm :: proc(cpu_name: string, socket: int, host_id: int) -> bool { + request: client.Request + client.request_init(&request, .Post) + defer client.request_destroy(&request) + + post_body := Base_CPU{cpu_name, socket, host_id} + if err := client.with_json(&request, post_body); err != nil { + return false + } + + response, err := client.request(&request, fmt.tprintf("%s/add_cpu/", PC.api_address)) + if err != nil do log.fatal("Failed to add host to API with the error: %s", err) + defer client.response_destroy(&response) + + if response.status != .Created { + return false + } + return true +} + +_main :: proc() { context.logger = log.create_console_logger(.Info) + defer log.destroy_console_logger(context.logger) - ini_config, ok := get_config(CONFIG_FILE_PATH).? + data, ok := os.read_entire_file_from_filename("config.ini") if !ok { - log.fatal("Failed to read config file, please ensure it's in the correct format") + fmt.eprintln("Failed to open config file") + return } + defer delete(data) + data_str := strings.to_lower(transmute(string)data, allocator=context.temp_allocator) + + ini_config, err := ini.load_map_from_string(data_str, allocator=context.allocator) + if err != nil { + log.fatal("Failed to read config file") + return + } + defer ini.delete_map(ini_config) + + fmt.println("ini_config[\"api\"][\"address\"]:", ini_config["api"]["address"]) if _, ok := ini_config["log"]; ok { if level, ok := ini_config["log"]["level"]; ok && level in Log_Level_Map { @@ -77,21 +179,28 @@ main :: proc() { context.logger.lowest_level = PC.log_level if _, ok := ini_config["api"]; ok { - if api_address, ok := ini_config["api"]["address"]; ok do PC.api_address = strings.clone(api_address) - else do log.fatal("API address not specified in config file") + if api_address, ok := ini_config["api"]["address"]; ok { + PC.api_address = api_address + } else { + log.fatal("API address not specified in config file") + return + } } log.debug("Program config:", PC) - hostname, hostname_ok := sysinfo.get_hostname().? - if !hostname_ok { + PC.hostname, ok = sysinfo.get_hostname().? + if !ok { + log.fatal("Failed to get hostname") return } + defer delete(PC.hostname) log.info("Successfully got hostname") - PC.host_id, ok = get_host_id(hostname) + PC.host_id, ok = get_host_id(PC.hostname) if !ok { log.fatal("Failed to contact API and determine if host already exists in LSM") + return } if PC.host_id < 0 { @@ -102,9 +211,10 @@ main :: proc() { client.request_init(&request, .Post) defer client.request_destroy(&request) - post_body := Base_Host{hostname} + post_body := Base_Host{PC.hostname} if err := client.with_json(&request, post_body); err != nil { - log.fatal("JSON error: %s", err) + log.fatal("JSON error:", err) + // TODO: Handle this } response, err := client.request(&request, fmt.tprintf("%s/add_host/", PC.api_address)) @@ -113,7 +223,7 @@ main :: proc() { if response.status == .Created { log.info("Successfully added host to LSM") - PC.host_id, ok = get_host_id(hostname) + PC.host_id, ok = get_host_id(PC.hostname) if !ok do log.fatal("Failed to get host ID, exiting") } } else { @@ -121,4 +231,36 @@ main :: proc() { } log.debug("Host ID", PC.host_id) + // cpus, cpu_ok := get_cpus_for_host_from_id(PC.host_id) + // if len(cpus) == 0 { + // delete(cpus) + // log.info("Need to add CPUs to LSM") + + // cpu_name, socket, ok := sysinfo.get_cpu_name_and_socket_number() + // log.info("Attempting to add CPU", cpu_name, "to LSM") + // if ok := add_cpu_to_lsm(cpu_name, socket, PC.host_id); !ok { + // log.fatal("Failed to add CPU, exiting") + // os.exit(1) + // } + // log.info("Successfully added CPU to LSM") + // cpus, cpu_ok := get_cpus_for_host_from_id(PC.host_id) + // } + // defer delete(cpus) + + // log.debug("cpus for host: ", cpus) +} + +main :: proc() { + track: mem.Tracking_Allocator + mem.tracking_allocator_init(&track, context.allocator) + context.allocator = mem.tracking_allocator(&track) + + _main() + + for _, leak in track.allocation_map { + fmt.println(leak.location, "leaked", leak.size, "bytes") + } + for bad_free in track.bad_free_array { + fmt.println(bad_free.location, "allocation", bad_free.memory, "was freed badly") + } } diff --git a/types.odin b/types.odin index f3bfa5a..05b9582 100644 --- a/types.odin +++ b/types.odin @@ -16,9 +16,11 @@ Program_Config :: struct { api_address: string, host_id: int, + hostname: string, } CPU :: struct { + id: int, name: string, socket: int, usage: f16, @@ -43,3 +45,8 @@ Base_Host :: struct { hostname: string } +Base_CPU :: struct { + name: string, + socket: int, + host_id: int +}