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


Reply via email to