Add a struct server pointer in the mworker_proc struct so we can easily use it as a target for the mworker proxy.
pcli_prefix_to_pid() is used to find the right PID of the worker when using a prefix in the CLI. (@master, @#<relative pid> , @<pid>) pcli_pid_to_server() is used to find the right target server for the CLI proxy. --- include/types/global.h | 1 + src/cli.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) diff --git a/include/types/global.h b/include/types/global.h index a5d948e25..4b9d019ed 100644 --- a/include/types/global.h +++ b/include/types/global.h @@ -212,6 +212,7 @@ struct mworker_proc { int ipc_fd[2]; /* 0 is master side, 1 is worker side */ int relative_pid; int reloads; + struct server *srv; /* the server entry in the master proxy */ struct list list; }; diff --git a/src/cli.c b/src/cli.c index 87227a35f..a6e0648c2 100644 --- a/src/cli.c +++ b/src/cli.c @@ -1589,6 +1589,80 @@ static int cli_parse_simple(char **args, char *payload, struct appctx *appctx, v return 1; } + +static enum obj_type *pcli_pid_to_server(int proc_pid) +{ + struct mworker_proc *child; + + list_for_each_entry(child, &proc_list, list) { + if (child->pid == proc_pid){ + return &child->srv->obj_type; + } + } + return NULL; +} + +/* Take a CLI prefix in argument (eg: @!1234 @master @1) + * Return: + * 0: master + * > 0: pid of a worker + * < 0: didn't find a worker + */ +static int pcli_prefix_to_pid(const char *prefix) +{ + int proc_pid; + struct mworker_proc *child; + char *errtol = NULL; + + if (*prefix != '@') /* not a prefix, should not happen */ + return -1; + + prefix++; + if (!*prefix) /* sent @ alone, return the master */ + return 0; + + if (strcmp("master", prefix) == 0) { + return 0; + } else if (*prefix == '!') { + prefix++; + if (!*prefix) + return -1; + + proc_pid = strtol(prefix, &errtol, 10); + if (*errtol != '\0') + return -1; + list_for_each_entry(child, &proc_list, list) { + if (child->pid == proc_pid){ + return child->pid; + } + } + } else { + struct mworker_proc *chosen = NULL; + /* this is a relative pid */ + + proc_pid = strtol(prefix, &errtol, 10); + if (*errtol != '\0') + return -1; + + if (proc_pid == 0) /* return the master */ + return 0; + + /* chose the right process, the current one is the one with the + least number of reloads */ + list_for_each_entry(child, &proc_list, list) { + if (child->relative_pid == proc_pid){ + if (child->reloads == 0) + return child->pid; + else if (chosen == NULL || child->reloads < chosen->reloads) + chosen = child; + } + } + if (chosen) + return chosen->pid; + } + return -1; +} + /* * The mworker functions are used to initialize the CLI in the master process */ @@ -1669,6 +1743,8 @@ int mworker_cli_proxy_create() newsrv->uweight = 1; mworker_proxy->srv_act++; srv_lb_commit_status(newsrv); + + child->srv = newsrv; } return 0; } -- 2.16.4