package main import "core:encoding/ini" import "core:encoding/json" import "core:fmt" import "core:log" import "core:mem" import "core:os" import "core:strconv" import "core:strings" import "core:time" import "libs/http" import "libs/http/client" import "libs/sysinfo" CONFIG_FILE_PATH :: "./config.ini" PC: Program_Config = {} 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, endpoint) if err != nil { return nil, false, false } defer client.response_destroy(&response) body_err: client.Body_Error body, allocation, body_err = client.response_body(&response) if body_err != nil { 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) host_id := strconv.atoi(body.(client.Body_Plain)) return host_id, true } 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, cores: int, usage: f64, host_id: int) -> bool { request: client.Request client.request_init(&request, .Post) defer client.request_destroy(&request) post_body := Base_CPU{cpu_name, socket, cores, usage, host_id} log.info("TEST TEST TEST", post_body) if err := client.with_json(&request, post_body); err != nil { return false } response, err := client.request(&request, fmt.tprintf("%s/add_cpu_to_host/", 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) data, ok := os.read_entire_file_from_filename(CONFIG_FILE_PATH) if !ok { 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) if _, ok := ini_config["log"]; ok { if level, ok := ini_config["log"]["level"]; ok && level in Log_Level_Map { log_level := strings.to_upper(level, context.temp_allocator) log_level_ok: bool PC.log_level, log_level_ok = Log_Level_Map[log_level] } else { log.info("log level has either been not specified in configuration file or an invalid level has been specified") log.info("defaulting to info") PC.log_level = log.Level.Info } } context.logger.lowest_level = PC.log_level if _, ok := ini_config["api"]; ok { 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) 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(PC.hostname) if !ok { log.fatal("failed to contact the lsm api and determine if host already exists in lsm") return } if PC.host_id < 0 { log.info("Host doesn't exist in LSM") log.info("Adding host now") request: client.Request client.request_init(&request, .Post) defer client.request_destroy(&request) post_body := Base_Host{PC.hostname} if err := client.with_json(&request, post_body); err != nil { log.fatal("JSON error:", err) // TODO: Handle this } response, err := client.request(&request, fmt.tprintf("%s/add_host/", 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 { log.info("successfully added host to lsm") PC.host_id, ok = get_host_id(PC.hostname) if !ok do log.fatal("failed to get host id, exiting") } } else { log.info("host found in lsm") } log.debug("host id", PC.host_id) cpu_name, socket, cpu_name_and_socket_ok := sysinfo.get_cpu_name_and_socket_number() if !cpu_name_and_socket_ok { log.fatal("failed to get cpu name and socket") return } log.debug("got cpu name and socket") cores, cores_ok := sysinfo.get_numb_cpu_cores() if !cores_ok { log.fatal("failed to get number of cpu cores") return } log.debug("got number of cpu cores") log.debug("starting main loop") for { usage, usage_ok := sysinfo.get_cpu_usage_perc() log.info("USAGE:", usage) if !usage_ok { log.fatal("failed to get cpu usage") return } else { log.debug("successfully got cpu usage") } if ok := add_cpu_to_lsm(cpu_name, socket, cores, usage, PC.host_id); !ok { log.error("failed to add cpu") } else { log.info("successfully added cpu to lsm") } time.sleep(1 * time.Second) } } 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") } }