aboutsummaryrefslogtreecommitdiff
path: root/src/piesctl.c
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2016-01-02 23:58:06 +0200
committerSergey Poznyakoff <gray@gnu.org>2016-01-02 23:58:06 +0200
commit6db017a32e379bb2eb7878771dea969f77c3168c (patch)
tree0e1563b8239f7c681708c64c0d693f6541e4e155 /src/piesctl.c
parent061afaf6385340f87bbeaa6d7e8ff6befa532551 (diff)
downloadpies-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.c247
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;
}

Return to:

Send suggestions and report system problems to the System administrator.