Skip to content

Commit c1b96c1

Browse files
acornardmurlock
authored andcommitted
Create json output option
1 parent cd41ae5 commit c1b96c1

File tree

1 file changed

+196
-8
lines changed

1 file changed

+196
-8
lines changed

main/gridinit_cmd.c

Lines changed: 196 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ static gboolean flag_help = FALSE;
4848
static gchar sock_path[1024];
4949
static gchar line[65536];
5050
static gboolean flag_color = FALSE;
51+
static gboolean flag_json = FALSE;
5152

5253
#define BOOL(i) (i?1:0)
5354

@@ -275,6 +276,62 @@ dump_as_is(FILE *in_stream, void *udata)
275276
fflush(stdout);
276277
}
277278

279+
280+
static void
281+
print_as_json(gchar *status, gchar *start, gchar *error)
282+
{
283+
gchar header[] = " {\n";
284+
gchar footer[] = " }";
285+
gchar tab[] = " ";
286+
287+
fprintf(stdout, "%s", header);
288+
fprintf(stdout, "%s\"status\": \"%s\",\n", tab, status);
289+
fprintf(stdout, "%s\"start\": \"%s\",\n", tab, start);
290+
fprintf(stdout, "%s\"error\": \"%s\",\n", tab, error);
291+
fprintf(stdout, "%s", footer);
292+
}
293+
294+
static void
295+
dump_as_json(FILE *in_stream, void *udata)
296+
{
297+
gchar *start, *status;
298+
int code, first = 1;
299+
gchar head[] = "[\n";
300+
gchar footer[] = "\n]\n";
301+
struct keyword_set_s *kw;
302+
struct dump_as_is_arg_s *dump_args;
303+
304+
kw = flag_color ? &KEYWORDS_COLOR : &KEYWORDS_NORMAL;
305+
306+
dump_args = udata;
307+
fprintf(stdout, "%s", head);
308+
while(!feof(in_stream) && !ferror(in_stream)) {
309+
bzero(line, sizeof(line));
310+
if (NULL != fgets(line, sizeof(line), in_stream)) {
311+
start = NULL;
312+
(void)unpack_line(line, &start, &code);
313+
314+
if (dump_args) {
315+
if (code==0 || code==EALREADY)
316+
dump_args->count_success ++;
317+
else
318+
dump_args->count_errors ++;
319+
}
320+
if (!first)
321+
fprintf(stdout, ",\n");
322+
first = 0;
323+
status = (gchar *)(code == 0 ? kw->done : (code==EALREADY?kw->already:kw->failed));
324+
print_as_json(status, start, strerror(code));
325+
}
326+
}
327+
fprintf(stdout, "%s", footer);
328+
fflush(stdout);
329+
}
330+
331+
332+
333+
334+
278335
static FILE*
279336
open_cnx(void)
280337
{
@@ -483,29 +540,143 @@ command_status(int lvl, int argc, char **args)
483540
return rc;
484541
}
485542

543+
544+
static int
545+
command_status_json(int lvl, int argc, char **args)
546+
{
547+
char fmt_line[256];
548+
549+
int *counters = alloca(sizeof(int) * (argc+1));
550+
memset(counters, 0, sizeof(int) * (argc+1));
551+
552+
GList *all_jobs = _fetch_services();
553+
GList *jobs = _filter_services(all_jobs, args, counters);
554+
555+
fprintf(stdout, "[\n");
556+
char fmt_str[]=" \"%s\": \"%s\",\n";
557+
char fmt_int[]=" \"%s\": \"%d\",\n";
558+
char fmt_lint[]=" \"%s\": \"%ld\",\n";
559+
switch (lvl) {
560+
case 0:
561+
g_snprintf(fmt_line, sizeof(fmt_line),
562+
" {\n%s%s%s%s\n }",
563+
fmt_str, fmt_str, fmt_int, fmt_str);
564+
break;
565+
case 1:
566+
g_snprintf(fmt_line, sizeof(fmt_line),
567+
" {\n%s%s%s%s%s%s%s%s\n }",
568+
fmt_str, fmt_str, fmt_int, fmt_int,
569+
fmt_int, fmt_str, fmt_str, fmt_str);
570+
break;
571+
default:
572+
g_snprintf(fmt_line, sizeof(fmt_line),
573+
" {\n%s%s%s%s%s%s%s%s%s%s%s\n }",
574+
fmt_str, fmt_str, fmt_int, fmt_int, fmt_int,
575+
fmt_lint,fmt_lint,fmt_lint,fmt_str, fmt_str,
576+
fmt_str
577+
);
578+
break;
579+
}
580+
581+
int count_faulty = 0, count_all = 0, count_misses = 0;
582+
583+
/* iterate on the lines */
584+
for (GList *l=jobs; l ;l=l->next) {
585+
char str_time[20] = "---------- --------";
586+
const char * str_status = "-";
587+
struct child_info_s *ci = NULL;
588+
gboolean faulty = FALSE;
589+
ci = l->data;
590+
591+
/* Prepare some fields */
592+
if (ci->pid > 0)
593+
strftime(str_time, sizeof(str_time), "%Y-%m-%d %H:%M:%S",
594+
gmtime(&(ci->last_start_attempt)));
595+
str_status = get_child_status(ci, &faulty);
596+
597+
/* Manage counters */
598+
if (faulty)
599+
count_faulty ++;
600+
count_all ++;
601+
602+
/* Print now! */
603+
if(count_all-1)
604+
fprintf(stdout, ",\n");
605+
606+
switch (lvl) {
607+
case 0:
608+
609+
fprintf(stdout, fmt_line,
610+
"key", ci->key, "status", str_status,
611+
"pid", ci->pid,"group", ci->group);
612+
break;
613+
case 1:
614+
fprintf(stdout, fmt_line,
615+
"key", ci->key, "status", str_status,
616+
"pid", ci->pid, "#start", ci->counter_started,
617+
"#died", ci->counter_died, "since", str_time,
618+
"group", ci->group, "cmd", ci->cmd);
619+
break;
620+
default:
621+
fprintf(stdout, fmt_line,
622+
"key", ci->key, "status", str_status,
623+
"pid", ci->pid, "#start", ci->counter_started,
624+
"#died", ci->counter_died, "csz", ci->rlimits.core_size,
625+
"ssz", ci->rlimits.stack_size, "mfd", ci->rlimits.nb_files,
626+
"since", str_time, "group", ci->group,
627+
"cmd", ci->cmd);
628+
break;
629+
}
630+
}
631+
632+
fprintf(stdout, "\n]\n");
633+
fflush(stdout);
634+
635+
/* If patterns have been specified, we must find items (the user
636+
* expects something to show up */
637+
for (int i=0; i<argc ;i++) {
638+
if (!counters[i])
639+
count_misses ++;
640+
}
641+
642+
g_list_free_full(all_jobs, (GDestroyNotify)child_info_free);
643+
g_list_free(jobs);
644+
645+
return !(!count_misses && !count_faulty && (!argc || count_all > 0));
646+
}
647+
486648
static int
487649
command_status0(int argc, char **args)
488650
{
651+
if (flag_json)
652+
return command_status_json(0, argc, args);
489653
return command_status(0, argc, args);
490654
}
491655

492656
static int
493657
command_status1(int argc, char **args)
494658
{
659+
if (flag_json)
660+
return command_status_json(1, argc, args);
495661
return command_status(1, argc, args);
496662
}
497663

498664
static int
499665
command_status2(int argc, char **args)
500666
{
667+
if (flag_json)
668+
return command_status_json(2, argc, args);
501669
return command_status(2, argc, args);
502670
}
503671

504672
static int
505673
command_start(int argc, char **args)
506674
{
507675
struct dump_as_is_arg_s dump_args = {};
508-
int rc = send_commandv(dump_as_is, &dump_args, "start", argc, args);
676+
void *dumper = dump_as_is;
677+
678+
if(flag_json) dumper = dump_as_json;
679+
int rc = send_commandv(dumper, &dump_args, "start", argc, args);
509680
return !rc
510681
|| dump_args.count_errors != 0
511682
|| dump_args.count_success == 0;
@@ -515,7 +686,10 @@ static int
515686
command_kill(int argc, char **args)
516687
{
517688
struct dump_as_is_arg_s dump_args = {};
518-
int rc = send_commandv(dump_as_is, &dump_args, "stop", argc, args);
689+
void *dumper = dump_as_is;
690+
691+
if(flag_json) dumper = dump_as_json;
692+
int rc = send_commandv(dumper, &dump_args, "stop", argc, args);
519693
return !rc
520694
|| dump_args.count_errors != 0
521695
|| dump_args.count_success == 0;
@@ -539,7 +713,8 @@ command_stop(int argc, char **args)
539713
}
540714

541715
while (!_all_down()) {
542-
g_print("# Stopping...\n");
716+
if (!flag_json)
717+
g_print("# Stopping...\n");
543718
int rc = command_kill(argc, args);
544719
if (rc != 0)
545720
return rc;
@@ -552,7 +727,10 @@ static int
552727
command_restart(int argc, char **args)
553728
{
554729
struct dump_as_is_arg_s dump_args = {};
555-
int rc = send_commandv(dump_as_is, &dump_args, "restart", argc, args);
730+
void *dumper = dump_as_is;
731+
732+
if(flag_json) dumper = dump_as_json;
733+
int rc = send_commandv(dumper, &dump_args, "restart", argc, args);
556734
return !rc
557735
|| dump_args.count_errors != 0
558736
|| dump_args.count_success == 0;
@@ -562,7 +740,10 @@ static int
562740
command_repair(int argc, char **args)
563741
{
564742
struct dump_as_is_arg_s dump_args = {};
565-
int rc = send_commandv(dump_as_is, &dump_args, "repair", argc, args);
743+
void *dumper = dump_as_is;
744+
745+
if(flag_json) dumper = dump_as_json;
746+
int rc = send_commandv(dumper, &dump_args, "repair", argc, args);
566747
return !rc
567748
|| dump_args.count_errors != 0
568749
|| dump_args.count_success == 0;
@@ -572,8 +753,11 @@ static int
572753
command_reload(int argc, char **args)
573754
{
574755
struct dump_as_is_arg_s dump_args = {};
756+
void *dumper = dump_as_is;
575757
(void) argc, (void) args;
576-
int rc = send_commandv(dump_as_is, &dump_args, "reload", 0, (char*[]){NULL});
758+
759+
if(flag_json) dumper = dump_as_json;
760+
int rc = send_commandv(dumper, &dump_args, "reload", 0, (char*[]){NULL});
577761
return !rc
578762
|| dump_args.count_errors != 0
579763
|| dump_args.count_success == 0;
@@ -605,7 +789,7 @@ main_options(int argc, char **args)
605789

606790
g_strlcpy(sock_path, GRIDINIT_SOCK_PATH, sizeof(sock_path));
607791

608-
while ((opt = getopt(argc, args, "chS:")) != -1) {
792+
while ((opt = getopt(argc, args, "chjS:")) != -1) {
609793
switch (opt) {
610794
case 'c':
611795
flag_color = TRUE;
@@ -617,6 +801,9 @@ main_options(int argc, char **args)
617801
case 'h':
618802
flag_help = TRUE;
619803
break;
804+
case 'j':
805+
flag_json = TRUE;
806+
break;
620807
}
621808
}
622809

@@ -627,11 +814,12 @@ static void
627814
help(char **args)
628815
{
629816
close(2);
630-
g_print("Usage: %s [-h|-c|-S SOCK]... (status{,2,3}|start|stop|reload|repair) [ID...]\n", args[0]);
817+
g_print("Usage: %s [-h|-c|-j|-S SOCK]... (status{,2,3}|start|stop|reload|repair) [ID...]\n", args[0]);
631818
g_print("\n OPTIONS:\n");
632819
g_print(" -c : coloured display\n");
633820
g_print(" -h : displays a little help section\n");
634821
g_print(" -S SOCK : explicit unix socket path\n");
822+
g_print(" -j : output result by json\n");
635823
g_print("\n COMMANDS:\n");
636824
g_print(" status* : Displays the status of the given processes or groups\n");
637825
g_print(" start : Starts the given processes or groups, even if broken\n");

0 commit comments

Comments
 (0)