From cf4df65192e144b773b2d1f012d2d26e9ddba91b Mon Sep 17 00:00:00 2001 From: Jean-Francois Smigielski Date: Mon, 15 Oct 2018 11:15:33 +0200 Subject: [PATCH] gridinit_cmd: Fix output oddities --- CMakeLists.txt | 1 - main/format_output.c | 157 ------------------------------- main/format_output.h | 36 -------- main/gridinit_cmd.c | 215 +++++++++++++++++++++++++------------------ 4 files changed, 123 insertions(+), 286 deletions(-) delete mode 100644 main/format_output.c delete mode 100644 main/format_output.h diff --git a/CMakeLists.txt b/CMakeLists.txt index f1f1edd..c5ac640 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -126,7 +126,6 @@ add_dependencies(gridinit add_executable(gridinit_cmd main/gridinit_cmd.c - main/format_output.c main/utils.c) target_link_libraries(gridinit_cmd ${GLIB2_LIBRARIES}) diff --git a/main/format_output.c b/main/format_output.c deleted file mode 100644 index 9c23559..0000000 --- a/main/format_output.c +++ /dev/null @@ -1,157 +0,0 @@ -/* -Copyright (C) 2015 OpenIO SAS, as part of OpenIO SDS - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU Affero General Public License as -published by the Free Software Foundation, either version 3 of the -License, or (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Affero General Public License for more details. -You should have received a copy of the GNU Affero General Public License -along with this program. If not, see . -*/ - -#include -#include -#include "./format_output.h" - -FORMAT -parse_format(gchar *format) -{ - if (g_strcmp0(format, "json") == 0) - return JSON; - if (g_strcmp0(format, "csv") == 0) - return CSV; - else - return DEFAULT; -} - -void -print_as_json(gchar *status, gchar *start, gchar *error, gboolean first) -{ - gchar header[] = " {\n"; - gchar footer[] = " }"; - gchar tab[] = " "; - - if(!first) - fprintf(stdout, ",\n"); - - fprintf(stdout, "%s", header); - fprintf(stdout, "%s\"status\": \"%s\",\n", tab, status); - fprintf(stdout, "%s\"start\": \"%s\",\n", tab, start); - fprintf(stdout, "%s\"error\": \"%s\"\n", tab, error); - fprintf(stdout, "%s", footer); -} - -void -print_as_csv(gchar *status, gchar *start, gchar *error) -{ - fprintf(stdout, "%s,%s,%s\n", status, start, error); -} - - -void -print_header(FORMAT format) -{ - switch (format) { - case JSON: - fprintf(stdout, "[\n"); - break; - case CSV: - fprintf(stdout, "status,start,error\n"); - break; - default: - break; - } -} - -void -print_footer(FORMAT format) -{ - switch (format) { - case JSON: - fprintf(stdout, "\n]\n"); - break; - default: - break; - } - return; -} - -void -print_body(FORMAT format, gchar *status, gchar *start, gchar *error, gboolean first) -{ - switch (format) { - case JSON: - print_as_json(status, start, error, first); - break; - case CSV: - print_as_csv(status, start, error); - break; - default: - fprintf(stdout, "%s\t%s\t%s\n", status, start, error); - } -} - -void -print_status_header(FORMAT format) -{ - switch (format) { - case JSON: - case CSV: - fprintf(stdout, - "key,status,pid,#start,#died,csz,ssz,mfd,since,group,cmd\n"); - break; - default: - break; - } -} - -void -status_body_json(gchar *fmt_line, int size) -{ - g_snprintf(fmt_line, size, - " {\n \"key\":\"%%s\",\n \"status\":\"%%s\"," - "\n \"pid\":\"%%d\",\n \"#start\":\"%%d\"," - "\n \"#died\":\"%%d\",\n \"csz\":\"%%ld\"," - "\n \"ssz\":\"%%ld\",\n \"mfd\":\"%%ld\"," - "\n \"since\":\"%%s\",\n \"group\":\"%%s\"," - "\n \"cmd\":\"%%s\"\n }"); -} - - -void -status_body_csv(gchar *fmt_line, int size) -{ - g_snprintf(fmt_line, size, - "%%s,%%s,%%d,%%d,%%d,%%ld,%%ld,%%ld,%%s,%%s,%%s\n"); -} - -void -print_status_sep(FORMAT format, int count) -{ - switch (format) { - case JSON: - if(count) - fprintf(stdout, ",\n"); - default: - break; - } -} - -void -get_line_format(FORMAT format, gchar *fmt_line, int size) -{ - switch (format) { - case JSON: - status_body_json(fmt_line, size); - break; - case CSV: - status_body_csv(fmt_line, size); - break; - default: - break; - } -} diff --git a/main/format_output.h b/main/format_output.h deleted file mode 100644 index cbc393a..0000000 --- a/main/format_output.h +++ /dev/null @@ -1,36 +0,0 @@ -/* -Copyright (C) 2015 OpenIO SAS, as part of OpenIO SDS - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU Affero General Public License as -published by the Free Software Foundation, either version 3 of the -License, or (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Affero General Public License for more details. -You should have received a copy of the GNU Affero General Public License -along with this program. If not, see . -*/ - -#ifndef __FORMAT_OUTPUT__ -#define __FORMAT_OUTPUT__ - -# include - -typedef enum FORMAT FORMAT; -enum FORMAT {DEFAULT = 0, CSV = 1, JSON = 2}; - -FORMAT parse_format(gchar *format); -void print_as_json(gchar *status, gchar *start, char *error, gboolean first); -void print_as_csv(gchar *status, gchar *start, char *error); -void print_header(FORMAT format); -void print_footer(FORMAT format); -void print_body(FORMAT format, gchar *status, gchar *start, gchar *error, gboolean first); -void print_status_header(FORMAT format); -void status_body_json(gchar *fmt_line, int size); -void status_body_csv(gchar *fmt_line, int size); -void print_status_sep(FORMAT format, int count); -void get_line_format(FORMAT format, gchar *fmt_line, int size); - -#endif diff --git a/main/gridinit_cmd.c b/main/gridinit_cmd.c index 72f4db7..1bfcb9b 100644 --- a/main/gridinit_cmd.c +++ b/main/gridinit_cmd.c @@ -29,7 +29,6 @@ along with this program. If not, see . #include -#include "./format_output.h" #include "./gridinit_internals.h" #define MINI 0 @@ -148,6 +147,21 @@ static const gchar description[] = "with ID the key of a process, or '@GROUP', with GROUP the name of a process\n" "group\n"; +typedef enum FORMAT FORMAT; + +enum FORMAT {DEFAULT = 0, CSV = 1, JSON = 2}; + +static FORMAT +parse_format(const gchar *cfg_format) +{ + if (g_strcmp0(cfg_format, "json") == 0) + return JSON; + if (g_strcmp0(cfg_format, "csv") == 0) + return CSV; + else + return DEFAULT; +} + static int __open_unix_client(const char *path) @@ -292,8 +306,19 @@ dump_as_is(FILE *in_stream, void *udata) else kw = &KEYWORDS_NORMAL; - print_header(format_t); + /* Prin tthe title */ + switch (format_t) { + case JSON: + fputs("[", stdout); + break; + case CSV: + fputs("status,start,error\n", stdout); + /* FALLTHROUGH */ + default: + break; + } + /* Print the lines */ while (!feof(in_stream) && !ferror(in_stream)) { bzero(line, sizeof(line)); if (NULL != fgets(line, sizeof(line), in_stream)) { @@ -308,13 +333,27 @@ dump_as_is(FILE *in_stream, void *udata) dump_args->count_errors ++; } gchar *status = (gchar *) (code==0 ? kw->done : - (code==EALREADY?kw->already:kw->failed)); - gchar *error = strerror(code); - print_body(format_t, status, start, error,first); + (code==EALREADY?kw->already:kw->failed)); + const char *error = strerror(code); + + switch (format_t) { + case JSON: + if(!first) + fprintf(stdout, ",\n"); + fprintf(stdout, "{\"status\": \"%s\",\"start\": \"%s\",\"error\": \"%s\"}\n", status, start, error); + break; + case CSV: + fprintf(stdout, "%s,%s,%s\n", status, start, error); + break; + default: + fprintf(stdout, "%s\t%s\t%s\n", status, start, error); + } first = FALSE; } } - print_footer(format_t); + + if (format_t == JSON) + fputs("]", stdout); fflush(stdout); } @@ -410,7 +449,7 @@ _filter_services(GList *original, char **filters, int *counters) static int command_status(int lvl, int argc, char **args) { - char fmt_title[256], fmt_line[256]; + char fmt_line[256]; int *counters = alloca(sizeof(int) * (argc+1)); memset(counters, 0, sizeof(int) * (argc+1)); @@ -418,53 +457,59 @@ command_status(int lvl, int argc, char **args) GList *all_jobs = _fetch_services(); GList *jobs = _filter_services(all_jobs, args, counters); FORMAT format_t = parse_format(format); - /* compute the max length of several variable field, for well aligned - * columns on the output. */ - const size_t maxkey = get_longest_key(jobs); - const size_t maxgroup = get_longest_group(jobs); - - if (format_t != DEFAULT) { - print_status_header(format_t); - get_line_format(format_t, fmt_line, sizeof(fmt_line)); - goto print_lines; - } - /* write the title */ - switch (lvl) { - case 0: - g_snprintf(fmt_title, sizeof(fmt_title), - "%%-%us %%-8s %%6s %%s\n", - (guint)maxkey); - g_snprintf(fmt_line, sizeof(fmt_line), - "%%-%us %%s %%6d %%s\n", - (guint)maxkey); - fprintf(stdout, fmt_title, "KEY", "STATUS", "PID", "GROUP"); - break; - case 1: - g_snprintf(fmt_title, sizeof(fmt_title), - "%%-%us %%-8s %%5s %%6s %%5s %%19s %%%us %%s\n", - (guint)maxkey, (guint)maxgroup); + /* Print the header and compute the format for each line */ + if (format_t == DEFAULT) { + const size_t maxkey = get_longest_key(jobs); + const size_t maxgroup = get_longest_group(jobs); + char fmt_title[256]; + switch (lvl) { + case 0: + g_snprintf(fmt_title, sizeof(fmt_title), + "%%-%us %%-8s %%6s %%s\n", + (guint)maxkey); + g_snprintf(fmt_line, sizeof(fmt_line), + "%%-%us %%s %%6d %%s\n", + (guint)maxkey); + fprintf(stdout, fmt_title, "KEY", "STATUS", "PID", "GROUP"); + break; + case 1: + g_snprintf(fmt_title, sizeof(fmt_title), + "%%-%us %%-8s %%5s %%6s %%5s %%19s %%%us %%s\n", + (guint)maxkey, (guint)maxgroup); + g_snprintf(fmt_line, sizeof(fmt_line), + "%%-%us %%s %%5d %%6d %%5d %%19s %%%us %%s\n", + (guint)maxkey, (guint)maxgroup); + fprintf(stdout, fmt_title, "KEY", "STATUS", "PID", "#START", + "#DIED", "SINCE", "GROUP", "CMD"); + break; + default: + g_snprintf(fmt_title, sizeof(fmt_title), + "%%-%us %%-8s %%5s %%6s %%5s %%8s %%8s %%8s %%19s %%%us %%s\n", + (guint)maxkey, (guint)maxgroup); + g_snprintf(fmt_line, sizeof(fmt_line), + "%%-%us %%s %%5d %%6d %%5d %%8ld %%8ld %%8ld %%19s %%%us %%s\n", + (guint)maxkey, (guint)maxgroup); + + fprintf(stdout, fmt_title, "KEY", "STATUS", "PID", "#START", + "#DIED", "CSZ", "SSZ", "MFD", "SINCE", "GROUP", "CMD"); + break; + } + } else if (format_t == CSV) { g_snprintf(fmt_line, sizeof(fmt_line), - "%%-%us %%s %%5d %%6d %%5d %%19s %%%us %%s\n", - (guint)maxkey, (guint)maxgroup); - fprintf(stdout, fmt_title, "KEY", "STATUS", "PID", "#START", - "#DIED", "SINCE", "GROUP", "CMD"); - break; - default: - g_snprintf(fmt_title, sizeof(fmt_title), - "%%-%us %%-8s %%5s %%6s %%5s %%8s %%8s %%8s %%19s %%%us %%s\n", - (guint)maxkey, (guint)maxgroup); + "%%s,%%s,%%d,%%d,%%d,%%ld,%%ld,%%ld,%%s,%%s,%%s\n"); + /* Print the title */ + fputs("key,status,pid,#start,#died,csz,ssz,mfd,since,group,cmd\n", stdout); + } else if (format_t == JSON) { g_snprintf(fmt_line, sizeof(fmt_line), - "%%-%us %%s %%5d %%6d %%5d %%8ld %%8ld %%8ld %%19s %%%us %%s\n", - (guint)maxkey, (guint)maxgroup); - - fprintf(stdout, fmt_title, "KEY", "STATUS", "PID", "#START", - "#DIED", "CSZ", "SSZ", "MFD", "SINCE", "GROUP", "CMD"); - break; + "{\"key\":\"%%s\",\"status\":\"%%s\",\"pid\":%%d," + "\"#start\":%%d,\"#died\":%%d,\"csz\":%%ld,\"ssz\":%%ld,\"mfd\":%%ld," + "\"since\":\"%%s\",\"group\":\"%%s\"," + "\"cmd\":\"%%s\"}\n"); + /* Print the opening of the object */ + fputs("[", stdout); } - print_lines:; - int count_misses = 0, count_broken = 0, count_down = 0, count_all = 0; struct keyword_set_s *kw; @@ -479,56 +524,55 @@ command_status(int lvl, int argc, char **args) for (GList *l=jobs; l ;l=l->next) { char str_time[20] = "---------- --------"; const char * str_status = "-"; - struct child_info_s *ci = NULL; - - ci = l->data; + struct child_info_s *ci = ci = l->data; /* Prepare some fields */ - if (ci->pid > 0) - strftime(str_time, sizeof(str_time), "%Y-%m-%d %H:%M:%S", + strftime(str_time, sizeof(str_time), "%Y-%m-%d %H:%M:%S", gmtime(&(ci->last_start_attempt))); str_status = get_child_status(ci, kw); /* Manage counters */ - if (str_status == kw->down) count_down ++; if (str_status == kw->broken) count_broken ++; count_all ++; + /* Print now! */ if (format_t != DEFAULT) { - print_status_sep(format_t, count_all-1); + if (format_t == JSON && count_all > 1) + fputs(",", stdout); fprintf(stdout, fmt_line, ci->key, str_status, ci->pid, ci->counter_started, ci->counter_died, ci->rlimits.core_size, ci->rlimits.stack_size, ci->rlimits.nb_files, str_time, ci->group, ci->cmd); - goto end; - } - switch (lvl) { - case 0: - fprintf(stdout, fmt_line, ci->key, str_status, ci->pid, ci->group); - break; - case 1: - fprintf(stdout, fmt_line, - ci->key, str_status, ci->pid, - ci->counter_started, ci->counter_died, - str_time, ci->group, ci->cmd); - break; - default: - fprintf(stdout, fmt_line, - ci->key, str_status, ci->pid, - ci->counter_started, ci->counter_died, - ci->rlimits.core_size, ci->rlimits.stack_size, ci->rlimits.nb_files, - str_time, ci->group, ci->cmd); - break; + } else { + switch (lvl) { + case 0: + fprintf(stdout, fmt_line, ci->key, str_status, ci->pid, ci->group); + break; + case 1: + fprintf(stdout, fmt_line, + ci->key, str_status, ci->pid, + ci->counter_started, ci->counter_died, + str_time, ci->group, ci->cmd); + break; + default: + fprintf(stdout, fmt_line, + ci->key, str_status, ci->pid, + ci->counter_started, ci->counter_died, + ci->rlimits.core_size, ci->rlimits.stack_size, ci->rlimits.nb_files, + str_time, ci->group, ci->cmd); + break; + } } - end:; } + g_list_free_full(all_jobs, (GDestroyNotify)child_info_free); + g_list_free(jobs); - if (format_t != DEFAULT) - print_footer(format_t); + if (format_t == JSON) + fputs("]", stdout); fflush(stdout); /* If patterns have been specified, we must find items (the user @@ -537,20 +581,7 @@ command_status(int lvl, int argc, char **args) if (!counters[i]) count_misses ++; } - - g_list_free_full(all_jobs, (GDestroyNotify)child_info_free); - g_list_free(jobs); - - int rc = 0; - - if (count_down) - rc |= 1; - if (count_misses) - rc |= 2; - if (count_broken) - rc |= 4; - - return rc; + return (count_down ? 1 : 0) | (count_misses ? 2 : 0) | (count_broken ? 4 : 0); }