diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2016-01-02 23:58:06 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2016-01-02 23:58:06 +0200 |
commit | 6db017a32e379bb2eb7878771dea969f77c3168c (patch) | |
tree | 0e1563b8239f7c681708c64c0d693f6541e4e155 /src/piesctl.c | |
parent | 061afaf6385340f87bbeaa6d7e8ff6befa532551 (diff) | |
download | pies-6db017a32e379bb2eb7878771dea969f77c3168c.tar.gz pies-6db017a32e379bb2eb7878771dea969f77c3168c.tar.bz2 |
Switch to new control interface.
Old control options (--status, --restart-components) rewritten using
piesctl.
SIGUSR1 and SIGUSR2 no longer handled.
* lib/arraymember.c (array_index): New function.
* lib/libpies.h: Likewise.
* src/cmdline.opt: Fix copyright years.
* src/piesctl-cl.opt: Likewise.
* src/ctl.c (ctlio_do_command): Implement restart.
(pies_control_url): New function.
(eval_env): rename json to result.
New member cond.
Restore pcond_ functions.
(json_to_pcond): New function.
(res_programs): Conditional selection of programs to list.
Implement restart.
* src/pies.c (ctlfile, statfile): Remove.
(pies_keywords): Mark control-file and stat-file as inactive.
(default_sigv): Remove SIGUSR1 and SIGUSR2
(pies_check_status): Don't send SIGUSR2.
(stop_components): Remove.
(request_restart_components): Rewrite as a wrapper.
Call piesctl to do the job.
(list_components): New function.
* src/pies.h (ACTION_COMPRELOAD)
(ACTION_DUMPSTATS): Remove. All callers changed.
(progman_dump_stats): Remove.
* src/piesctl.c (shttp_request_send): Don't initialize conn->req; the
caller is responsible for that.
(parse_condition, json_to_string)
(parse_condition_to_uri): New functions.
(com_list): Read conditional expression from the command line.
(com_restart): Implement.
* src/progman.c (progman_dump_stats): Remove.
Diffstat (limited to 'src/piesctl.c')
-rw-r--r-- | src/piesctl.c | 247 |
1 files changed, 244 insertions, 3 deletions
diff --git a/src/piesctl.c b/src/piesctl.c index 9c5ef8b..626463c 100644 --- a/src/piesctl.c +++ b/src/piesctl.c @@ -622,7 +622,6 @@ send_header (void *sym, void *data) static void shttp_request_send (struct shttp_connection *conn, int method, char const *uri) { - shttp_io_init (&conn->req); shttp_send_line (conn, "%s %s %s", method_names[method], uri, http_version); shttp_send_line (conn, "Host: %s", conn->url->host ? conn->url->host : "localhost"); @@ -1160,10 +1159,229 @@ print_comp (FILE *fp, struct json_value *v, size_t n) fputc ('\n', fp); } +struct pcond_parser_state +{ + int argc; + char **argv; +}; + +static char * +next_token (struct pcond_parser_state *state) +{ + if (state->argc == 0) + return NULL; + --state->argc; + return *state->argv++; +} + +static char const * +peek_token (struct pcond_parser_state *state) +{ + if (state->argc == 0) + return NULL; + return *state->argv; +} + +static struct json_value * +json_new_array2 (struct json_value *a, struct json_value *b) +{ + struct json_value *ret = json_new_array (); + json_array_append (ret, a); + json_array_append (ret, b); + return ret; +} + +static struct json_value * +json_encode_op (char const *op, struct json_value *arg) +{ + struct json_value *ret = json_new_object (); + json_object_set (ret, "op", json_new_string (op)); + json_object_set (ret, "arg", arg); + return ret; +} + +static void pcond_parse_or (struct pcond_parser_state *, struct json_value **); + +static void +pcond_parse_unary (struct pcond_parser_state *state, struct json_value **ret) +{ + char const *term = next_token (state); + + if (!term) + *ret = json_new_bool (1); + else + { + static char *arg_terms[] = { + "type", "mode", "status", "component", NULL + }; + + if (strcasecmp (term, "all") == 0) + *ret = json_new_bool (1); + else if (is_array_member (arg_terms, term)) + { + if (!peek_token (state)) + { + grecs_error (NULL, 0, _("%s requires argument"), term); + exit (EX_USAGE); + } + *ret = json_encode_op (term, json_new_string (next_token (state))); + } + else if (strcasecmp (term, "not") == 0) + { + struct json_value *val; + if (!peek_token (state)) + { + grecs_error (NULL, 0, _("%s requires argument"), term); + exit (EX_USAGE); + } + pcond_parse_unary (state, &val); + *ret = json_encode_op (term, val); + } + else if (term[0] == '(') + { + pcond_parse_or (state, ret); + term = next_token (state); + if (!term || term[0] != ')') + { + grecs_error (NULL, 0, _("unbalanced parentesis")); + exit (EX_USAGE); + } + } + else + { + grecs_error (NULL, 0, _("parse error at %s"), term); + exit (EX_USAGE); + } + } +} + +static void +pcond_parse_and (struct pcond_parser_state *state, struct json_value **ret) +{ + char const *token; + struct json_value *left, *right; + + pcond_parse_unary (state, &left); + token = peek_token (state); + if (!token || strcmp (token, "and")) + { + *ret = left; + return; + } + next_token (state); + pcond_parse_and (state, &right); + *ret = json_encode_op (token, json_new_array2 (left, right)); +} + +static void +pcond_parse_or (struct pcond_parser_state *state, struct json_value **ret) +{ + char const *token; + struct json_value *left, *right; + + pcond_parse_and (state, &left); + token = peek_token (state); + if (!token || strcmp (token, "or")) + { + *ret = left; + return; + } + next_token (state); + pcond_parse_or (state, &right); + *ret = json_encode_op (token, json_new_array2 (left, right)); +} + +static struct json_value * +parse_condition (int argc, char **argv) +{ + struct json_value *val = NULL; + + if (argc > 1) + { + struct pcond_parser_state state; + state.argc = argc - 1; + state.argv = argv + 1; + pcond_parse_or (&state, &val); + if (state.argc) + { + grecs_error (NULL, 0, + _("expected end of statement, but found \"%s\""), + *state.argv); + exit (EX_USAGE); + } +#if 0 + print_json (stdout, val); + exit (0); +#endif + } + return val; +} + +static void +acc_writer (void *closure, char const *text, size_t len) +{ + grecs_txtacc_grow ((struct grecs_txtacc *)closure, text, len); +} + +static char * +json_to_string (struct json_value *val) +{ + struct grecs_txtacc *acc = grecs_txtacc_create (); + struct json_format fmt = { + .indent = 0, + .precision = 0, + .write = acc_writer, + .data = acc + }; + char *ret; + + json_format_value (val, &fmt); + grecs_txtacc_grow_char (acc, 0); + ret = grecs_txtacc_finish (acc, 1); + grecs_txtacc_free (acc); + + return ret; +} + +static char * +parse_condition_to_uri (char const *base, int argc, char **argv) +{ + char *ret = NULL; + struct grecs_txtacc *acc; + struct json_value *val; + + acc = grecs_txtacc_create (); + grecs_txtacc_grow_string (acc, base); + + val = parse_condition (argc, argv); + if (val) + { + struct json_format fmt = { + .indent = 0, + .precision = 0, + .write = acc_writer, + .data = acc + }; + grecs_txtacc_grow_char (acc, '/'); + json_format_value (val, &fmt); + json_value_free (val); + } + grecs_txtacc_grow_char (acc, 0); + + ret = grecs_txtacc_finish (acc, 1); + grecs_txtacc_free (acc); + + return ret; +} + static int com_list (struct shttp_connection *conn, int argc, char **argv) { - shttp_process (conn, METH_GET, "/programs"); + char *uri = parse_condition_to_uri ("/programs", argc, argv); + + shttp_io_init (&conn->req); + shttp_process (conn, METH_GET, uri); + grecs_free (uri); if (!dump && conn->result && conn->result->type == json_arr) { size_t i, n = json_array_size (conn->result); @@ -1190,6 +1408,7 @@ com_stop (struct shttp_connection *conn, int argc, char **argv) { struct json_value *v; grecs_asprintf (&buf, &len, "/programs/%s", argv[i]); + shttp_io_init (&conn->req); shttp_process (conn, METH_DELETE, buf); v = shttp_getval (conn, "error_message", json_string); if (v) @@ -1210,6 +1429,7 @@ com_start (struct shttp_connection *conn, int argc, char **argv) { struct json_value *v; grecs_asprintf (&buf, &len, "/programs/%s", argv[i]); + shttp_io_init (&conn->req); shttp_process (conn, METH_PUT, buf); v = shttp_getval (conn, "error_message", json_string); if (v) @@ -1222,7 +1442,24 @@ com_start (struct shttp_connection *conn, int argc, char **argv) static int com_restart (struct shttp_connection *conn, int argc, char **argv) { - abort (); + struct json_value *val = json_new_array (); + size_t i; + + if (argc == 1) + { + grecs_error (NULL, 0, _("missing component names")); + exit (EX_USAGE); + } + for (i = 1; i < argc; i++) + json_array_append (val, json_new_string (argv[i])); + + shttp_io_init (&conn->req); + conn->req.content = json_to_string (val); + conn->req.content_length = strlen (conn->req.content); + json_value_free (val); + + shttp_process (conn, METH_POST, "/programs"); + return 0; } @@ -1241,6 +1478,7 @@ com_id (struct shttp_connection *conn, int argc, char **argv) "binary", }; + shttp_io_init (&conn->req); shttp_process (conn, METH_GET, "/instance"); for (i = 0; i < sizeof (keywords)/ sizeof (keywords[0]); i++) @@ -1262,6 +1500,7 @@ com_id (struct shttp_connection *conn, int argc, char **argv) for (i = 1; i < argc; i++) { grecs_asprintf (&buf, &size, "/instance/%s", argv[i]); + shttp_io_init (&conn->req); shttp_process (conn, METH_GET, buf); if (json_object_get (conn->result, argv[i], &v) == 0) { @@ -1277,6 +1516,7 @@ com_id (struct shttp_connection *conn, int argc, char **argv) static int com_shutdown (struct shttp_connection *conn, int argc, char **argv) { + shttp_io_init (&conn->req); shttp_process (conn, METH_DELETE, "/instance/PID"); return 0; } @@ -1284,6 +1524,7 @@ com_shutdown (struct shttp_connection *conn, int argc, char **argv) static int com_reboot (struct shttp_connection *conn, int argc, char **argv) { + shttp_io_init (&conn->req); shttp_process (conn, METH_PUT, "/instance/PID"); return 0; } |