From 389c31401bd26ffb2ef5bd1a2b29b1d70693d649 Mon Sep 17 00:00:00 2001 From: Shun Terabayashi Date: Sun, 8 Nov 2020 23:41:11 +0900 Subject: Implement for output CSV file --- src/gui.c | 1 - src/include/zenmonitor.h | 13 ++++++ src/zenmonitor-cli.c | 110 ++++++++++++++++++++++++++++++++++++++--------- src/zenmonitor-lib.c | 75 ++++++++++++++++++++++++++++++++ 4 files changed, 178 insertions(+), 21 deletions(-) diff --git a/src/gui.c b/src/gui.c index e382f96..11ef4f8 100644 --- a/src/gui.c +++ b/src/gui.c @@ -1,6 +1,5 @@ #include #include -#include #include "gui.h" #include "zenmonitor.h" diff --git a/src/include/zenmonitor.h b/src/include/zenmonitor.h index eba68c0..e135c35 100644 --- a/src/include/zenmonitor.h +++ b/src/include/zenmonitor.h @@ -1,6 +1,7 @@ #ifndef __ZENMONITOR_ZENMONITOR_H__ #define __ZENMONITOR_ZENMONITOR_H__ +#include #include #define ERROR_VALUE -999.0 @@ -27,11 +28,23 @@ typedef struct { GSList *sensors; } SensorSource; +typedef struct { + GPtrArray *labels; + GPtrArray *data; + GArray *time; +} SensorDataStore; + SensorInit* sensor_init_new(void); void sensor_init_free(SensorInit *s); gboolean check_zen(); gchar *cpu_model(); guint get_core_count(); +SensorDataStore* sensor_data_store_new(); +void sensor_data_store_add_entry(SensorDataStore *store, gchar *entry); +gint sensor_data_store_drop_entry(SensorDataStore *store, gchar *entry); +void sensor_data_store_keep_time(SensorDataStore *store); +gint sensor_data_store_add_data(SensorDataStore *store, gchar *entry, float data); +void sensor_data_store_free(SensorDataStore *store); extern gboolean display_coreid; #endif /* __ZENMONITOR_ZENMONITOR_H__ */ diff --git a/src/zenmonitor-cli.c b/src/zenmonitor-cli.c index 744b92a..7cf79f1 100644 --- a/src/zenmonitor-cli.c +++ b/src/zenmonitor-cli.c @@ -1,6 +1,9 @@ #include #include +#include +#include #include +#include #include "msr.h" #include "os.h" #include "zenpower.h" @@ -8,16 +11,18 @@ gboolean display_coreid = 0; gdouble delay = 0.5; -gchar *format = ""; -gchar *columns[2048]; +gchar *file = ""; +SensorDataStore *store; +int quit = 0; -static GOptionEntry options[] = -{ - { "format", 'f', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, &format, "Output format (csv, json)", "FORMAT" }, - { "delay", 'd', G_OPTION_FLAG_NONE, G_OPTION_ARG_DOUBLE, &delay, "Interval of refreshing informations", "SECONDS" }, - { "coreid", 'c', 0, G_OPTION_ARG_NONE, &display_coreid, "Display core_id instead of core index", NULL }, - { NULL } -}; +static GOptionEntry options[] = { + {"file", 'f', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, &file, + "Output to csv file", "FILE"}, + {"delay", 'd', G_OPTION_FLAG_NONE, G_OPTION_ARG_DOUBLE, &delay, + "Interval of refreshing informations", "SECONDS"}, + {"coreid", 'c', 0, G_OPTION_ARG_NONE, &display_coreid, + "Display core_id instead of core index", NULL}, + {NULL}}; static SensorSource sensor_sources[] = { { @@ -40,11 +45,71 @@ static SensorSource sensor_sources[] = { } }; -void init_sensors() { +void flush_to_csv() +{ + FILE *csv; + csv = fopen(file, "w"); + guint i = 0; + int cont = 1; + + fprintf(csv, "time(epoch),"); + while(cont) + { + fprintf(csv, "%s", (char*)g_ptr_array_index(store->labels, i++)); + if(g_ptr_array_index(store->labels, i)) + { + fprintf(csv, ","); + } + else + { + cont = 0; + } + } + + fprintf(csv, "\n"); + cont = 1; + i = 0; + + while(cont) + { + struct timespec ts = g_array_index(store->time, struct timespec, i); + fprintf(csv, "%ld.%.9ld,", ts.tv_sec, ts.tv_nsec); + + int j = 0; + int cont2 = 1; + while(cont2) + { + GArray *data = g_ptr_array_index(store->data, j++); + fprintf(csv, "%f", g_array_index(data, float, i)); + if(g_ptr_array_index(store->data, j)) + { + fprintf(csv, ","); + } + else + { + cont2 = 0; + } + } + fprintf(csv, "\n"); + + i++; + + if(g_array_index(store->time, struct timespec, i).tv_sec <= 0) + { + cont = 0; + } + } + + fclose(csv); + + quit = 1; +} + +void init_sensors() +{ GSList *sensor; SensorSource *source; const SensorInit *data; - guint i = 0; for(source = sensor_sources; source->drv; source++) { @@ -58,13 +123,12 @@ void init_sensors() { while(sensor) { data = (SensorInit*)sensor->data; - columns[i++] = data->label; + sensor_data_store_add_entry(store, data->label); sensor = sensor->next; } } } } - columns[i] = NULL; } void update_data() @@ -73,6 +137,8 @@ void update_data() GSList *node; const SensorInit *sensorData; + sensor_data_store_keep_time(store); + for(source = sensor_sources; source->drv; source++) { if(source->enabled) @@ -85,23 +151,19 @@ void update_data() while(node) { sensorData = (SensorInit*)node->data; + sensor_data_store_add_data(store, sensorData->label, *sensorData->value); printf("%s\t%f\n", sensorData->label, *sensorData->value); node = node->next; } } } } + printf("\v"); } void start_watching() { - guint i = 0; - while(columns[i]) - { - printf("%s\n", columns[i++]); - } - - while(1) + while(!quit) { update_data(); usleep(delay * 1000 * 1000); @@ -120,8 +182,16 @@ int main(int argc, char *argv[]) exit (1); } + if(strcmp(file, "") != 0) + { + signal(SIGINT, flush_to_csv); + } + store = sensor_data_store_new(); + init_sensors(); start_watching(); + sensor_data_store_free(store); + return EXIT_SUCCESS; } diff --git a/src/zenmonitor-lib.c b/src/zenmonitor-lib.c index dded8f3..4fc0538 100644 --- a/src/zenmonitor-lib.c +++ b/src/zenmonitor-lib.c @@ -1,4 +1,7 @@ +#include #include +#include +#include #include "zenpower.h" #include "msr.h" @@ -8,6 +11,8 @@ #define AMD_STRING "AuthenticAMD" #define ZEN_FAMILY 0x17 +const guint SENSOR_DATA_STORE_NUM = 4096; + // AMD PPR = https://www.amd.com/system/files/TechDocs/54945_PPR_Family_17h_Models_00h-0Fh.pdf gboolean check_zen() { @@ -80,6 +85,76 @@ guint get_core_count() { return logical_cpus / threads_per_code; } +SensorDataStore *sensor_data_store_new() +{ + SensorDataStore *ret; + + ret = g_new0(SensorDataStore, 1); + ret->labels = g_ptr_array_new(); + ret->data = g_ptr_array_new(); + ret->time = g_array_new(FALSE, TRUE, sizeof(struct timespec)); + + return ret; +} + +void sensor_data_store_add_entry(SensorDataStore *store, gchar *entry) +{ + GArray *data; + data = g_array_new(TRUE, TRUE, sizeof(float)); + + g_ptr_array_add(store->labels, entry); + g_ptr_array_add(store->data, data); +} + +void sensor_data_store_keep_time(SensorDataStore *store) +{ + struct timespec ts; + timespec_get(&ts, TIME_UTC); + g_array_append_val(store->time, ts); +} + +gint sensor_data_store_drop_entry(SensorDataStore *store, gchar *entry) +{ + guint index = 0; + gboolean found = g_ptr_array_find(store->labels, entry, &index); + if(!found) + { + return 1; + } + + g_ptr_array_remove_index(store->labels, index); + g_ptr_array_remove_index(store->data, index); + + return 0; +} + +gint sensor_data_store_add_data(SensorDataStore *store, gchar *entry, float value) +{ + guint index = 0; + gboolean found = g_ptr_array_find(store->labels, entry, &index); + + if(!found) + { + return 1; + } + + GArray *data = g_ptr_array_index(store->data, index); + g_array_append_val(data, value); + + return 0; +} + +void sensor_data_store_free(SensorDataStore *store) +{ + if(store) + { + g_array_free(store->time, TRUE); + g_ptr_array_free(store->labels, TRUE); + g_ptr_array_free(store->data, TRUE); + g_free(store); + } +} + SensorInit *sensor_init_new() { return g_new0(SensorInit, 1); } -- cgit v1.2.3-70-g09d2