]> err.no Git - varnish/commitdiff
Rip out the old CLI handling and start over, more or less.
authorphk <phk@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Thu, 3 Aug 2006 09:45:14 +0000 (09:45 +0000)
committerphk <phk@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Thu, 3 Aug 2006 09:45:14 +0000 (09:45 +0000)
Still bits missing.

git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@616 d4fa192b-c00b-0410-8231-f00ffab90ce4

varnish-cache/bin/varnishd/Makefile.am
varnish-cache/bin/varnishd/cache_cli.c
varnish-cache/bin/varnishd/cache_main.c
varnish-cache/bin/varnishd/cli_common.c [new file with mode: 0644]
varnish-cache/bin/varnishd/cli_event.c [deleted file]
varnish-cache/bin/varnishd/common_cli.c [new file with mode: 0644]
varnish-cache/bin/varnishd/common_cli.h [moved from varnish-cache/bin/varnishd/cli_event.h with 57% similarity]
varnish-cache/bin/varnishd/mgt.h
varnish-cache/bin/varnishd/mgt_child.c
varnish-cache/bin/varnishd/mgt_cli.c [new file with mode: 0644]
varnish-cache/bin/varnishd/varnishd.c

index c11e96cd02c0d4517a65529dbb3868455065ea9f..2aaf58c3ff523b832e78d4b7c0e2477d43d64d2a 100644 (file)
@@ -1,6 +1,6 @@
 # $Id$
 
-INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/contrib/libevent
+INCLUDES = -I$(top_srcdir)/include
 
 bin_PROGRAMS = varnishd
 
@@ -8,7 +8,7 @@ man_MANS = varnishd.1
 
 varnishd_SOURCES = \
        cache.h \
-       cli_event.h \
+       common_cli.h \
        hash_slinger.h \
        heritage.h \
        mgt.h \
@@ -33,10 +33,11 @@ varnishd_SOURCES = \
        cache_vrt.c \
        cache_vrt_acl.c \
        cache_vrt_re.c \
-       cli_event.c \
+       common_cli.c \
        hash_simple_list.c \
        hash_classic.c \
        mgt_child.c \
+       mgt_cli.c \
        rfc2616.c \
        shmlog.c \
        storage_file.c \
@@ -51,6 +52,5 @@ varnishd_LDADD = \
        $(top_builddir)/lib/libsbuf/libsbuf.a \
        $(top_builddir)/lib/libvarnish/libvarnish.la \
        $(top_builddir)/lib/libvcl/libvcl.la \
-       $(top_builddir)/contrib/libevent/libevent.la \
        -lpthread \
        -lmd
index 16a322f07582929fe07b61971409263e279a9af5..9698c1944a68651d0e778fcdc86d439d7cf34ad3 100644 (file)
 #include <poll.h>
 #include <pthread.h>
 
-#include "event.h"             /* XXX only as long as it takes */
-
 #include "libvarnish.h"
 #include "shmlog.h"
 #include "cli.h"
 #include "cli_priv.h"
-#include "cli_event.h"
+#include "common_cli.h"
 #include "cache.h"
 #include "sbuf.h"
 #include "heritage.h"
@@ -54,24 +52,6 @@ struct cli_proto CLI_cmds[] = {
        { NULL }
 };
 
-static int
-cli_writes(const char *s, const char *r, const char *t)
-{
-       int i, l;
-       struct iovec iov[3];
-
-       iov[0].iov_base = (void*)(uintptr_t)s;
-       iov[1].iov_base = (void*)(uintptr_t)r;
-       iov[2].iov_base = (void*)(uintptr_t)t;
-       for (l = i = 0; i < 3; i++) {
-               iov[i].iov_len = strlen(iov[i].iov_base);
-               l += iov[i].iov_len;
-       }
-       i = writev(heritage.fds[1], iov, 3);
-       VSL(SLT_CLI, 0, "Wr %d %s %s", i != l, s, r);
-       return (i != l);
-}
-
 void
 CLI_Init(void)
 {
@@ -80,7 +60,6 @@ CLI_Init(void)
        unsigned nbuf, lbuf;
        struct cli *cli, clis;
        int i;
-       char res[30];
 
        cli = &clis;
        memset(cli, 0, sizeof *cli);
@@ -116,11 +95,13 @@ CLI_Init(void)
                sbuf_clear(cli->sb);
                cli_dispatch(cli, CLI_cmds, buf);
                sbuf_finish(cli->sb);
-               sprintf(res, "%d ", cli->result);
-               if (cli_writes(res, sbuf_data(cli->sb), "\n")) {
+               i = cli_writeres(heritage.fds[2], cli);
+               if (i) {
                        VSL(SLT_Error, 0, "CLI write failed (errno=%d)", errno);
                        return;
                }
+               VSL(SLT_CLI, 0, "Wr %d %d %s",
+                   i, cli->result, sbuf_data(cli->sb));
                i = ++p - buf; 
                assert(i <= nbuf);
                if (i < nbuf)
index e70acce2b7fc3d6aa084c6ef4495c7ac8e133052..ed2436b4898d984248b43daf3608d57afe9b9499 100644 (file)
@@ -11,7 +11,6 @@
 #include "heritage.h"
 #include "shmlog.h"
 #include "cache.h"
-#include "event.h"
 
 struct stevedore       *stevedore;
 
diff --git a/varnish-cache/bin/varnishd/cli_common.c b/varnish-cache/bin/varnishd/cli_common.c
new file mode 100644 (file)
index 0000000..bacc2e6
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * $Id$
+ */
+
+#include <errno.h>
+#include <assert.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+
+#include <sys/wait.h>
+
+#include "sbuf.h"
+
+#include <cli.h>
+#include <cli_common.h>
+#include <libvarnish.h>
+
+void
+cli_out(struct cli *cli, const char *fmt, ...)
+{
+       va_list ap;
+
+       va_start(ap, fmt);
+       sbuf_vprintf(cli->sb, fmt, ap);
+       va_end(ap);
+}
+
+void
+cli_param(struct cli *cli)
+{
+
+       cli->result = CLIS_PARAM;
+       cli_out(cli, "Parameter error, use \"help [command]\" for more info.\n");
+}
+
+void
+cli_result(struct cli *cli, unsigned res)
+{
+
+       cli->result = res;
+}
+
diff --git a/varnish-cache/bin/varnishd/cli_event.c b/varnish-cache/bin/varnishd/cli_event.c
deleted file mode 100644 (file)
index 55c693d..0000000
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * $Id$
- */
-
-#include <errno.h>
-#include <assert.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <ctype.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <signal.h>
-
-#include <sys/wait.h>
-
-#include <event.h>
-#include <sbuf.h>
-
-#include <cli.h>
-#include <cli_priv.h>
-#include <libvarnish.h>
-
-#include "heritage.h"
-#include "cli_event.h"
-
-void
-cli_encode_string(struct evbuffer *buf, char *b)
-{
-       char *p, *q;
-
-       evbuffer_add_printf(buf, "\"");
-       for (p = q = b; *p != '\0'; p++) {
-               if ((*p != '"' && *p != '\\' && isgraph(*p)) || *p == ' ')
-                       continue;
-               if (p != q) 
-                       evbuffer_add(buf, q, p - q);
-               if (*p == '\n')
-                       evbuffer_add_printf(buf, "\\n");
-               else
-                       evbuffer_add_printf(buf, "\\x%02x", *p);
-               q = p + 1;
-       }
-       if (p != q) 
-               evbuffer_add(buf, q, p - q);
-       evbuffer_add_printf(buf, "\"");
-}
-
-
-void
-cli_out(struct cli *cli, const char *fmt, ...)
-{
-       va_list ap;
-
-       va_start(ap, fmt);
-       sbuf_vprintf(cli->sb, fmt, ap);
-       va_end(ap);
-}
-
-void
-cli_param(struct cli *cli)
-{
-
-       cli->result = CLIS_PARAM;
-       cli_out(cli, "Parameter error, use \"help [command]\" for more info.\n");
-}
-
-void
-cli_result(struct cli *cli, unsigned res)
-{
-
-       cli->result = res;
-}
-
-static void
-encode_output(struct cli *cli)
-{
-
-       if (cli->verbose) {
-               if (cli->result != CLIS_OK)
-                       evbuffer_add_printf(cli->bev1->output, "ERROR %d ",
-                           cli->result);
-               evbuffer_add(cli->bev1->output,
-                   sbuf_data(cli->sb), sbuf_len(cli->sb));
-               if (cli->result == CLIS_OK)
-                       evbuffer_add_printf(cli->bev1->output, "OK\n");
-               return;
-       }
-       evbuffer_add_printf(cli->bev1->output, "%d ", cli->result);
-       cli_encode_string(cli->bev1->output, sbuf_data(cli->sb));
-       evbuffer_add_printf(cli->bev1->output, "\n");
-}
-
-static void
-rdcb(struct bufferevent *bev, void *arg)
-{
-       const char *p;
-       struct cli *cli = arg;
-
-       p = evbuffer_readline(bev->input);
-       if (p == NULL)
-               return;
-       sbuf_clear(cli->sb);
-       cli_dispatch(cli, cli->cli_proto, p);
-       if (!cli->suspend) {
-               sbuf_finish(cli->sb);
-               /* XXX: syslog results ? */
-               encode_output(cli);
-               AZ(bufferevent_enable(cli->bev1, EV_WRITE));
-       }
-}
-
-static void
-wrcb(struct bufferevent *bev, void *arg)
-{
-       struct cli *cli = arg;
-
-       (void)bev;
-       AZ(bufferevent_disable(cli->bev1, EV_WRITE));
-}
-
-static void
-excb(struct bufferevent *bev, short what, void *arg)
-{
-       printf("%s(%p, %d, %p)\n", __func__, (void*)bev, (int)what, arg);
-}
-
-struct cli *
-cli_setup(struct event_base *eb, int fdr, int fdw, int ver, struct cli_proto *cli_proto)
-{
-       struct cli      *cli;
-
-       cli = calloc(sizeof *cli, 1);
-       assert(cli != NULL);
-
-       cli->bev0 = bufferevent_new(fdr, rdcb, wrcb, excb, cli);
-       assert(cli->bev0 != NULL);
-       AZ(bufferevent_base_set(eb, cli->bev0));
-       if (fdr == fdw)
-               cli->bev1 = cli->bev0;
-       else 
-               cli->bev1 = bufferevent_new(fdw, rdcb, wrcb, excb, cli);
-       assert(cli->bev1 != NULL);
-       AZ(bufferevent_base_set(eb, cli->bev1));
-       cli->sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND);
-       assert(cli->sb != NULL);
-
-       cli->verbose = ver;
-       cli->cli_proto = cli_proto;
-       
-       AZ(bufferevent_enable(cli->bev0, EV_READ));
-       return (cli);
-}
-
-void
-cli_suspend(struct cli *cli)
-{
-
-       cli->suspend = 1;
-       AZ(bufferevent_disable(cli->bev0, EV_READ));
-}
-
-void
-cli_resume(struct cli *cli)
-{
-       sbuf_finish(cli->sb);
-       /* XXX: syslog results ? */
-       encode_output(cli);
-       AZ(bufferevent_enable(cli->bev1, EV_WRITE));
-       cli->suspend = 0;
-       AZ(bufferevent_enable(cli->bev0, EV_READ));
-}
-
diff --git a/varnish-cache/bin/varnishd/common_cli.c b/varnish-cache/bin/varnishd/common_cli.c
new file mode 100644 (file)
index 0000000..932b169
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * $Id: cli_event.c 466 2006-07-12 23:30:49Z phk $
+ */
+
+#include <errno.h>
+#include <assert.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/uio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+
+#include <sys/wait.h>
+
+#include "sbuf.h"
+
+#include "cli.h"
+#include "cli_priv.h"
+#include "common_cli.h"
+#include "libvarnish.h"
+
+void
+cli_out(struct cli *cli, const char *fmt, ...)
+{
+       va_list ap;
+
+       va_start(ap, fmt);
+       sbuf_vprintf(cli->sb, fmt, ap);
+       va_end(ap);
+}
+
+void
+cli_param(struct cli *cli)
+{
+
+       cli->result = CLIS_PARAM;
+       cli_out(cli, "Parameter error, use \"help [command]\" for more info.\n");
+}
+
+void
+cli_result(struct cli *cli, unsigned res)
+{
+
+       cli->result = res;
+}
+
+int
+cli_writeres(int fd, struct cli *cli)
+{
+       int i, l;
+       struct iovec iov[3];
+       char res[32];
+
+       sprintf(res, "%d %d\n", cli->result, sbuf_len(cli->sb));
+       iov[0].iov_base = (void*)(uintptr_t)res;
+       iov[1].iov_base = (void*)(uintptr_t)sbuf_data(cli->sb);
+       iov[2].iov_base = (void*)(uintptr_t)"\n";
+       for (l = i = 0; i < 3; i++) {
+               iov[i].iov_len = strlen(iov[i].iov_base);
+               l += iov[i].iov_len;
+       }
+       i = writev(fd, iov, 3);
+       return (i != l);
+}
similarity index 57%
rename from varnish-cache/bin/varnishd/cli_event.h
rename to varnish-cache/bin/varnishd/common_cli.h
index 877c7d229bf0313b38d5849aab4653d1da0794f8..5c62b13fa871bc2e800c8b3c4f37cb9942f0c3d3 100644 (file)
@@ -3,7 +3,6 @@
  */
 
 struct cli {
-       struct bufferevent      *bev0, *bev1;
        struct sbuf             *sb;
        unsigned                verbose;
        unsigned                suspend;
@@ -11,8 +10,7 @@ struct cli {
        struct cli_proto        *cli_proto;
 };
 
-struct cli *cli_setup(struct event_base *eb, int fdr, int fdw, int ver, struct cli_proto *cli_proto);
 void cli_suspend(struct cli *cli);
 void cli_resume(struct cli *cli);
-void cli_encode_string(struct evbuffer *buf, char *b);
+int cli_writeres(int fd, struct cli *cli);
 extern struct cli_proto CLI_cmds[];
index b3488049a8dec0c39842b4ca4a5f9053227ddf99..f3740db2b22097feac6ab916e31e075c59168114 100644 (file)
@@ -4,15 +4,17 @@
 
 #include "common.h"
 
-extern struct event_base *mgt_eb;
+/* mgt_child.c */
+void mgt_run(int dflag);
+void mgt_start_child(void);
+void mgt_stop_child(void);
 
-void mgt_child_start(void);
-void mgt_child_stop(void);
-void mgt_child_kill(void);
-void mgt_sigchld(int, short, void *);
+/* mgt_cli.c */
 
-typedef void mgt_ccb_f(unsigned, const char *, void *);
-void mgt_child_request(mgt_ccb_f *, void *, char **argv, const char *fmt, ...);
+void mgt_cli_init(void);
+void mgt_cli_setup(int fdi, int fdo, int verbose);
+void mgt_cli_start_child(int fdi, int fdo);
+void mgt_cli_stop_child(void);
 
 /* tcp.c */
 int open_tcp(const char *port);
index 7ed370a1ae1e3748e7d1eb7440958b798328d60b..ccffc5c68c3c30ad306824ea6ee4aecd7ae11417 100644 (file)
  * The mechanics of handling the child process
  */
 
-#include <assert.h>
-#include <err.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <stdarg.h>
+#include <unistd.h>
 #include <stdio.h>
+#include <fcntl.h>
 #include <stdlib.h>
-#include <time.h>
-#include <unistd.h>
-
+#include <signal.h>
+#include <assert.h>
+#include <errno.h>
+#include <poll.h>
+#include <pthread.h>
+#include <sys/types.h>
 #include <sys/wait.h>
-#include "queue.h"
-
-#include <event.h>
-#include <sbuf.h>
 
-#include <libvarnish.h>
-#include <cli.h>
+#include <err.h>               /* XXX */
 
-#include "cli_event.h" /* for cli_encode_string */
+#include "libvarnish.h"
 #include "heritage.h"
 #include "mgt.h"
 
-/*--------------------------------------------------------------------*/
-
-static enum {
-       H_STOP = 0,
-       H_START
-}      desired;
-
-static pid_t   child_pid;
-static int     child_fds[2];
-
-static struct bufferevent *child_std;
-static struct bufferevent *child_cli0, *child_cli1;
-
-static struct event ev_child_pingpong;
+static pid_t           child_pid = -1;
+static int             child_fds[2];
+static unsigned        child_should_run;
+static pthread_t       child_listen_thread;
+static pthread_t       child_poker_thread;
+static pthread_mutex_t child_mtx;
+static pthread_cond_t  child_cv;
+static unsigned                child_ticker;
 
-struct creq {
-       TAILQ_ENTRY(creq)       list;
-       char                    *req;
-       char                    **argv;
-       mgt_ccb_f               *func;
-       void                    *priv;
-};
-
-static TAILQ_HEAD(,creq)       creqhead = TAILQ_HEAD_INITIALIZER(creqhead);
-
-/*--------------------------------------------------------------------
- * Handle stdout+stderr from the child.
- */
+/*--------------------------------------------------------------------*/
 
-static void
-std_rdcb(struct bufferevent *bev, void *arg)
+static void *
+child_listener(void *arg)
 {
-       const char *p;
+       FILE *f;
+       char buf[BUFSIZ];
 
        (void)arg;
 
-       while (1) {
-               p = evbuffer_readline(bev->input);
-               if (p == NULL)
-                       return;
-               printf("Child said <%s>\n", p);
-       }
-}
-
-static void
-std_wrcb(struct bufferevent *bev, void *arg)
-{
-
-       printf("%s(%p, %p)\n",
-           (const char *)__func__, (void*)bev, arg);
-       exit (2);
-}
-
-static void
-std_excb(struct bufferevent *bev, short what, void *arg)
-{
-
-       printf("%s(%p, %d, %p)\n",
-           (const char *)__func__, (void*)bev, what, arg);
-       exit (2);
-}
-
-/*--------------------------------------------------------------------
- * Multiplex requests/answers to the child
- */
-
-static void
-send_req(void)
-{
-       struct creq *cr;
-       int u;
-
-       cr = TAILQ_FIRST(&creqhead);
-       if (cr == NULL)
-               return;
-       if (0)
-               printf("Send Request <%s>\n", cr->req);
-       evbuffer_add_printf(child_cli1->output, "%s", cr->req);
-       for (u = 0; cr->argv != NULL && cr->argv[u] != NULL; u++) {
-               evbuffer_add_printf(child_cli1->output, " ");
-               cli_encode_string(child_cli1->output, cr->argv[u]);
+       f = fdopen(child_fds[0], "r");
+       assert(f != NULL);
+       while (fgets(buf, sizeof buf, f)) {
+               printf("Child said: %s", buf);
        }
-       evbuffer_add_printf(child_cli1->output, "\n");
-       AZ(bufferevent_enable(child_cli1, EV_WRITE));
-}
-
-void
-mgt_child_request(mgt_ccb_f *func, void *priv, char **argv, const char *fmt, ...)
-{
-       struct creq *cr;
-       va_list ap;
-       int i;
-
-       cr = calloc(sizeof *cr, 1);
-       assert(cr != NULL);
-       cr->func = func;
-       cr->priv = priv;
-       cr->argv = argv;
-       va_start(ap, fmt);
-       vasprintf(&cr->req, fmt, ap);
-       va_end(ap);
-       i = TAILQ_EMPTY(&creqhead);
-       TAILQ_INSERT_TAIL(&creqhead, cr, list);
-       if (i)
-               send_req();
-}
-
-static void
-cli_rdcb(struct bufferevent *bev, void *arg)
-{
-       const char *p;
-       char **av;
-       struct creq *cr;
-
-       (void)arg;
-
-       p = evbuffer_readline(bev->input);
-       if (p == NULL)
-               return;
-       cr = TAILQ_FIRST(&creqhead);
-       assert(cr != NULL);
-       av = ParseArgv(p, 0);
-       if (av[0] != NULL) 
-               cr->func(CLIS_SYNTAX, av[0], cr->priv);
-       else
-               cr->func(strtoul(av[1], NULL, 0), av[2], cr->priv);
-       FreeArgv(av);
-       TAILQ_REMOVE(&creqhead, cr, list);
-       free(cr->req);
-       free(cr);
-       send_req();
-}
-
-static void
-cli_wrcb(struct bufferevent *bev, void *arg)
-{
-
-       (void)bev;
-       (void)arg;
-}
-
-static void
-cli_excb(struct bufferevent *bev, short what, void *arg)
-{
-
-       printf("%s(%p, %d, %p)\n",
-           (const char *)__func__, (void*)bev, what, arg);
-       exit (2);
+       return (NULL);
 }
 
 /*--------------------------------------------------------------------*/
 
-static void
-child_pingpong_ccb(unsigned u, const char *r, void *priv)
+static void *
+child_poker(void *arg)
 {
-       (void)u;
-       (void)r;
-       (void)priv;
-
-       /* XXX: reset keepalive timer */
-}
 
-
-static void
-child_pingpong(int a, short b, void *c)
-{
-       time_t t;
-       struct timeval tv;
-
-       (void)a;
-       (void)b;
-       (void)c;
-
-       t = time(NULL);
-       mgt_child_request(child_pingpong_ccb, NULL, NULL, "ping %ld", t);
-       if (1) {
-               tv.tv_sec = 10;
-               tv.tv_usec = 0;
-               AZ(evtimer_del(&ev_child_pingpong));
-               AZ(evtimer_add(&ev_child_pingpong, &tv));
+       (void)arg;
+       while (1) {
+               sleep (1);
+               /* CLI: ping/pong */
+               child_ticker = 0;
        }
 }
 
-
 /*--------------------------------------------------------------------*/
 
 static void
@@ -219,13 +70,14 @@ start_child(void)
 {
        int i;
 
-       assert(pipe(&heritage.fds[0]) == 0);
-       assert(pipe(&heritage.fds[2]) == 0);
-       assert(pipe(child_fds) == 0);
+       AZ(pipe(&heritage.fds[0]));
+       AZ(pipe(&heritage.fds[2]));
+       AZ(pipe(child_fds));
        i = fork();
        if (i < 0) 
                errx(1, "Could not fork child");
        if (i == 0) {
+               AZ(pthread_single_np());
                /* Redirect stdin/out/err */
                AZ(close(0));
                i = open("/dev/null", O_RDONLY);
@@ -243,99 +95,119 @@ start_child(void)
                exit (1);
        }
 
-       child_pid = i;
        printf("start child pid %d\n", i);
 
        AZ(close(child_fds[1]));
 
        AZ(close(heritage.fds[1]));
        AZ(close(heritage.fds[2]));
-
-       child_std = bufferevent_new(child_fds[0],
-           std_rdcb, std_wrcb, std_excb, NULL);
-       assert(child_std != NULL);
-       AZ(bufferevent_base_set(mgt_eb, child_std));
-       bufferevent_enable(child_std, EV_READ);
-
-       child_cli0 = bufferevent_new(heritage.fds[0],
-           cli_rdcb, cli_wrcb, cli_excb, NULL);
-       assert(child_cli0 != NULL);
-       AZ(bufferevent_base_set(mgt_eb, child_cli0));
-       bufferevent_enable(child_cli0, EV_READ);
-
-       child_cli1 = bufferevent_new(heritage.fds[3],
-           cli_rdcb, cli_wrcb, cli_excb, NULL);
-       assert(child_cli1 != NULL);
-       AZ(bufferevent_base_set(mgt_eb, child_cli1));
-
-       evtimer_set(&ev_child_pingpong, child_pingpong, NULL);
-       AZ(event_base_set(mgt_eb, &ev_child_pingpong));
-       child_pingpong(0, 0, NULL);
+       mgt_cli_start_child(heritage.fds[0], heritage.fds[3]);
+       child_pid = i;
+       AZ(pthread_create(&child_listen_thread, NULL, child_listener, NULL));
+       AZ(pthread_create(&child_poker_thread, NULL, child_poker, NULL));
 }
 
-
 /*--------------------------------------------------------------------*/
 
-void
-mgt_child_start(void)
+static void
+stop_child(void)
 {
 
-       if (desired == H_START)
-               return;
-       desired = H_START;
-       start_child();
+       exit(2);
+       /* kill child, if relevant */
+       /* join child_listen_thread */
+       /* join child_poker_thread */
+       /* close heritage.fds */
+       /* close child_fds */
 }
 
 /*--------------------------------------------------------------------*/
 
-void
-mgt_child_stop(void)
+static void
+mgt_sigchld(int arg)
 {
+       int status;
+       pid_t r;
 
-       if (desired == H_STOP)
-               return;
-       desired = H_STOP;
+       (void)arg;
+       r = wait4(-1, &status, WNOHANG, NULL);
+       if (r == child_pid) {
+               printf("Cache child died pid=%d status=0x%x\n",
+                   r, status);
+               child_pid = -1;
+       } else {
+               printf("Unknown child died pid=%d status=0x%x\n",
+                   r, status);
+       }
 }
 
-/*--------------------------------------------------------------------*/
+/*--------------------------------------------------------------------
+ * This thread is the master thread in the management process.
+ * The relatively simple task is to start and stop the child process
+ * and to reincarnate it in case of trouble.
+ */
 
 void
-mgt_child_kill(void)
+mgt_run(int dflag)
 {
+       struct timespec to;
+       struct sigaction sac;
+       int i, dstarts = 0;
+
+#if 1
+       if (dflag)
+               mgt_cli_setup(0, 1, 1);
+#else
+       dflag = 0;
+#endif
+
+       sac.sa_handler = mgt_sigchld;
+       sac.sa_flags = SA_NOCLDSTOP;
+       AZ(sigaction(SIGCHLD, &sac, NULL));
+       child_should_run = !dflag;
 
-       desired = H_STOP;
-       kill(child_pid, 9);
+       AZ(pthread_cond_init(&child_cv, NULL));
+       AZ(pthread_mutex_init(&child_mtx, NULL));
+
+       while (1) {
+               if (!child_should_run && child_pid != -1)
+                       stop_child();
+               else if (child_should_run && child_pid == -1) {
+                       if (dflag && dstarts)
+                               exit(2);
+                       start_child();
+                       dstarts = 1;
+               }
+                       
+               /* XXX POSIXBRAINDAMAGE */
+               AZ(clock_gettime(CLOCK_REALTIME, &to));
+               to.tv_sec += 1;
+
+               AZ(pthread_mutex_lock(&child_mtx));
+               i = pthread_cond_timedwait(&child_cv, &child_mtx, &to);
+               AZ(pthread_mutex_unlock(&child_mtx));
+               if (i == ETIMEDOUT && ++child_ticker > 5 && child_pid != -1) {
+                       stop_child();
+                       if (dflag)
+                               exit (2);
+               }
+       }
 }
 
 /*--------------------------------------------------------------------*/
 
 void
-mgt_sigchld(int a, short b, void *c)
+mgt_start_child(void)
 {
-       pid_t p;
-       int status;
-
-       printf("sig_chld(%d, %d, %p)\n", a, b, c);
-
-       p = wait4(-1, &status, WNOHANG, NULL);
-       if (p == 0)
-               return;
-       printf("pid = %d status = 0x%x\n", p, status);
-       assert(p == child_pid);
-
-       printf("Child died :-(\n");
-       exit (0);
 
-       bufferevent_free(child_std); /* XXX: is this enough ? */
-       child_std = NULL;
+       child_should_run = 1;
+       AZ(pthread_cond_signal(&child_cv));
+}
 
-       AZ(close(heritage.fds[0]));
-       AZ(close(heritage.fds[1]));
-       AZ(close(heritage.fds[2]));
-       AZ(close(heritage.fds[3]));
-       AZ(close(child_fds[0]));
-       AZ(close(child_fds[1]));
+void
+mgt_stop_child(void)
+{
 
-       if (desired == H_START)
-               start_child();
+       child_should_run = 0;
+       AZ(pthread_cond_signal(&child_cv));
 }
diff --git a/varnish-cache/bin/varnishd/mgt_cli.c b/varnish-cache/bin/varnishd/mgt_cli.c
new file mode 100644 (file)
index 0000000..4d36e0f
--- /dev/null
@@ -0,0 +1,508 @@
+/*
+ * $Id$
+ *
+ * The management process' CLI handling
+ */
+
+#include <stdio.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <sys/types.h>
+
+#include "libvarnish.h"
+#include "cli_priv.h"
+#include "cli.h"
+#include "sbuf.h"
+#include "common_cli.h"
+#include "mgt.h"
+
+static int             cli_i = -1, cli_o = -1;
+
+/*--------------------------------------------------------------------*/
+
+static void
+mcf_server_start(struct cli *cli)
+{
+
+       (void)cli;
+       mgt_start_child();
+}
+
+
+/*--------------------------------------------------------------------*/
+
+static struct cli_proto *cli_proto;
+
+static struct cli_proto mgt_cli_proto[] = {
+       { CLI_HELP,             cli_func_help, NULL },  /* must be first */
+       { CLI_SERVER_START,     mcf_server_start, NULL },
+       { CLI_CONFIG_LOAD },
+#if 0
+       { CLI_CONFIG_LOAD,      m_cli_func_config_load, NULL },
+       { CLI_CONFIG_INLINE,    m_cli_func_config_inline, NULL },
+       { CLI_SERVER_STOP,      m_cli_func_server_stop, NULL },
+       { CLI_SERVER_RESTART },
+       { CLI_PING,             m_cli_func_ping, NULL },
+       { CLI_STATS,            m_cli_func_stats, NULL },
+       { CLI_ZERO },
+       { CLI_VERBOSE,          m_cli_func_verbose, NULL },
+       { CLI_EXIT,             m_cli_func_exit, NULL},
+#endif
+       { CLI_QUIT },
+       { CLI_BYE },
+       { NULL }
+};
+
+
+/*--------------------------------------------------------------------*/
+
+void
+mgt_cli_init(void)
+{
+       struct cli_proto *cp;
+       unsigned u, v;
+
+
+       /*
+        * Build the joint cli_proto by combining the manager process
+        * entries with with the cache process entries.  The latter
+        * get a "passthough" function in the joint list
+        */
+       u = 0;
+       for (cp = mgt_cli_proto; cp->request != NULL; cp++)
+               u++;
+       for (cp = CLI_cmds; cp->request != NULL; cp++)
+               u++;
+       cli_proto = calloc(sizeof *cli_proto, u + 1);
+       assert(cli_proto != NULL);
+       u = 0;
+       for (cp = mgt_cli_proto; cp->request != NULL; cp++)
+               cli_proto[u++] = *cp;
+       for (cp = CLI_cmds; cp->request != NULL; cp++) {
+               /* Skip any cache commands we already have in the manager */
+               for (v = 0; v < u; v++)
+                       if (!strcmp(cli_proto[v].request, cp->request))
+                               break;
+               if (v < u)
+                       continue;
+               cli_proto[u] = *cp;
+               cli_proto[u].func = NULL;       /* XXX: pass */
+               u++;
+       }
+
+       /* Fixup the entry for 'help' entry */
+       assert(!strcmp(cli_proto[0].request, "help"));
+       cli_proto[0].priv = cli_proto;
+
+       /* XXX: open listening sockets, contact cluster server etc */
+}
+
+/*--------------------------------------------------------------------*/
+
+void
+mgt_cli_start_child(int fdi, int fdo)
+{
+
+       cli_i = fdi;
+       cli_o = fdo;
+}
+
+/*--------------------------------------------------------------------*/
+
+void
+mgt_cli_stop_child(void)
+{
+
+       cli_i = -1;
+       cli_o = -1;
+       /* XXX: kick any users */
+}
+
+/*--------------------------------------------------------------------*/
+
+struct cli_port {
+       int                     fdi;
+       int                     fdo;
+       int                     verbose;
+       char                    *buf;
+       unsigned                nbuf;
+       unsigned                lbuf;
+       struct cli              cli[1];
+};
+
+static void *
+mgt_cli_main(void *arg)
+{
+       struct cli_port *cp;
+       char *p;
+       int i;
+
+       assert(arg != NULL);
+       cp = arg;
+
+       cp->lbuf = 4096;
+       cp->buf = malloc(cp->lbuf);
+       assert(cp->buf != NULL);
+       cp->cli->sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND);
+       assert(cp->cli->sb != NULL);
+       while (1) {
+               if (cp->nbuf == cp->lbuf) {
+                       cp->lbuf += cp->lbuf;
+                       cp->buf = realloc(cp->buf, cp->lbuf);
+                       assert(cp->buf != NULL);
+               }
+               i = read(cp->fdi, cp->buf + cp->nbuf, cp->lbuf - cp->nbuf);
+               if (i <= 0)
+                       break;
+               cp->nbuf += i;
+               p = strchr(cp->buf, '\n');
+               if (p == NULL)
+                       continue;
+               *p = '\0';
+               sbuf_clear(cp->cli->sb);
+               cli_dispatch(cp->cli, cli_proto, cp->buf);
+               sbuf_finish(cp->cli->sb);
+               /* XXX: cp->verbose */
+               if (cli_writeres(cp->fdo, cp->cli))
+                       break;
+               i = ++p - cp->buf;
+               assert(i <= cp->nbuf);
+               if (i < cp->nbuf)
+                       memcpy(cp->buf, p, cp->nbuf - i);
+               cp->nbuf -= i;
+       }
+       sbuf_delete(cp->cli->sb);
+       free(cp->buf);
+       close(cp->fdi);
+       close(cp->fdo);
+       free(cp);
+       return (NULL);
+}
+
+void
+mgt_cli_setup(int fdi, int fdo, int verbose)
+{
+       struct cli_port *cp;
+       pthread_t tp;
+
+       cp = calloc(sizeof *cp, 1);
+       assert(cp != NULL);
+
+       cp->fdi = fdi;
+       cp->fdo = fdo;
+       cp->verbose = verbose;
+       AZ(pthread_create(&tp, NULL, mgt_cli_main, cp));
+       AZ(pthread_detach(tp));
+}
+
+#if 0
+
+/*--------------------------------------------------------------------
+ * Generic passthrough for CLI functions
+ */
+
+static void
+cli_passthrough_cb(unsigned u, const char *r, void *priv)
+{
+       struct cli *cli = priv;
+
+       cli_out(cli, "%s\n", r);
+       cli_result(cli, u);
+       cli_resume(cli);
+}
+
+static void
+m_cli_func_passthrough(struct cli *cli, char **av, void *priv)
+{
+
+       (void)av;
+       (void)priv;
+
+       cli_suspend(cli);
+       mgt_child_request(cli_passthrough_cb, cli, &av[2], av[1]);
+}
+
+static void
+m_cli_func_config_inline(struct cli *cli, char **av, void *priv)
+{
+       char *vf;
+       struct sbuf *sb;
+
+       (void)priv;
+
+       sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND);
+       assert(sb != NULL);
+       vf = VCC_Compile(sb, av[3], NULL);
+       sbuf_finish(sb);
+       if (sbuf_len(sb) > 0) {
+               cli_out(cli, "%s", sbuf_data(sb));
+               sbuf_delete(sb);
+               return;
+       }
+       sbuf_delete(sb);
+       cli_suspend(cli);
+       mgt_child_request(cli_passthrough_cb, cli, NULL,
+           "config.load %s %s", av[2], vf);
+}
+
+/* XXX: m prefix to avoid name clash */
+static void
+m_cli_func_config_load(struct cli *cli, char **av, void *priv)
+{
+       char *vf;
+       struct sbuf *sb;
+
+       (void)priv;
+
+       sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND);
+       assert(sb != NULL);
+       vf = VCC_CompileFile(sb, av[3]);
+       sbuf_finish(sb);
+       if (sbuf_len(sb) > 0) {
+               cli_out(cli, "%s", sbuf_data(sb));
+               sbuf_delete(sb);
+               return;
+       }
+       sbuf_delete(sb);
+       cli_suspend(cli);
+       mgt_child_request(cli_passthrough_cb, cli, NULL,
+           "config.load %s %s", av[2], vf);
+}
+
+static char *
+vcl_file(const char *fflag)
+{
+       char *vf;
+       struct sbuf *sb;
+
+       sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND);
+       assert(sb != NULL);
+       vf = VCC_CompileFile(sb, fflag);
+       sbuf_finish(sb);
+       if (sbuf_len(sb) > 0) {
+               fprintf(stderr, "%s", sbuf_data(sb));
+               sbuf_delete(sb);
+               return (NULL);
+       }
+       sbuf_delete(sb);
+       return (vf);
+}
+
+
+/*--------------------------------------------------------------------*/
+
+static void
+m_cli_func_server_start(struct cli *cli, char **av, void *priv)
+{
+
+       (void)cli;
+       (void)av;
+       (void)priv;
+
+       mgt_child_start();
+}
+
+/*--------------------------------------------------------------------*/
+
+static void
+m_cli_func_server_stop(struct cli *cli, char **av, void *priv)
+{
+
+       (void)cli;
+       (void)av;
+       (void)priv;
+
+       mgt_child_stop();
+}
+
+/*--------------------------------------------------------------------*/
+
+static void
+m_cli_func_exit(struct cli *cli, char **av, void *priv)
+{
+
+       (void)cli;
+       (void)av;
+       (void)priv;
+       mgt_child_kill();
+       exit (0);
+}
+
+/*--------------------------------------------------------------------*/
+
+static void
+m_cli_func_verbose(struct cli *cli, char **av, void *priv)
+{
+
+       (void)av;
+       (void)priv;
+
+       cli->verbose = !cli->verbose;
+}
+
+
+static void
+m_cli_func_ping(struct cli *cli, char **av, void *priv)
+{
+       time_t t;
+
+       (void)priv;
+
+       if (av[2] != NULL) {
+               cli_out(cli, "Got your %s\n", av[2]);
+       } 
+       t = time(NULL);
+       cli_out(cli, "PONG %ld\n", t);
+}
+
+/*--------------------------------------------------------------------*/
+
+static void
+m_cli_func_stats(struct cli *cli, char **av, void *priv)
+{
+
+       (void)av;
+       (void)priv;
+
+       assert (VSL_stats != NULL);
+#define MAC_STAT(n,t,f,d) \
+    cli_out(cli, "%12ju  " d "\n", (VSL_stats->n));
+#include "stat_field.h"
+#undef MAC_STAT
+}
+
+/*--------------------------------------------------------------------*/
+
+
+/*--------------------------------------------------------------------*/
+
+/* for development purposes */
+#include <printf.h>
+
+int
+main(int argc, char *argv[])
+{
+       int o;
+       const char *portnumber = "8080";
+       unsigned dflag = 0;
+       const char *bflag = NULL;
+       const char *fflag = NULL;
+       const char *sflag = "file";
+       const char *hflag = "classic";
+
+       (void)register_printf_render_std((const unsigned char *)"HVQ");
+
+       setbuf(stdout, NULL);
+       setbuf(stderr, NULL);
+       VCC_InitCompile(default_vcl);
+
+       heritage.default_ttl = 120;
+       heritage.wthread_min = 1;
+       heritage.wthread_max = UINT_MAX;
+       heritage.wthread_timeout = 10;
+       heritage.mem_workspace = 4096;
+
+       while ((o = getopt(argc, argv, "b:df:h:p:s:t:w:")) != -1)
+               switch (o) {
+               case 'b':
+                       bflag = optarg;
+                       break;
+               case 'd':
+                       dflag++;
+                       break;
+               case 'f':
+                       fflag = optarg;
+                       break;
+               case 'h':
+                       hflag = optarg;
+                       break;
+               case 'p':
+                       portnumber = optarg;
+                       break;
+               case 's':
+                       sflag = optarg;
+                       break;
+               case 't':
+                       heritage.default_ttl = strtoul(optarg, NULL, 0);
+                       break;
+               case 'w':
+                       tackle_warg(optarg);
+                       break;
+               default:
+                       usage();
+               }
+
+       argc -= optind;
+       argv += optind;
+
+       if (argc != 0) {
+               fprintf(stderr, "Too many arguments\n");
+               usage();
+       }
+
+       if (bflag != NULL && fflag != NULL) {
+               fprintf(stderr, "Only one of -b or -f can be specified\n");
+               usage();
+       }
+       if (bflag == NULL && fflag == NULL) {
+               fprintf(stderr, "One of -b or -f must be specified\n");
+               usage();
+       }
+
+       if (bflag != NULL)
+               heritage.vcl_file = vcl_default(bflag);
+       else
+               heritage.vcl_file = vcl_file(fflag);
+       if (heritage.vcl_file == NULL)
+               exit (1);
+
+       setup_storage(sflag);
+       setup_hash(hflag);
+
+       /*
+        * XXX: Lacking the suspend/resume facility (due to the socket API
+        * missing an unlisten(2) facility) we may want to push this into
+        * the child to limit the amount of time where the socket(s) exists
+        * but do not answer.  That, on the other hand, would eliminate the
+        * possibility of doing a "no-glitch" restart of the child process.
+        */
+       open_tcp(portnumber);
+
+       VSL_MgtInit(SHMLOG_FILENAME, 8*1024*1024);
+
+       if (dflag)
+               DebugStunt();
+       daemon(dflag, dflag);
+       if (dflag)
+               printf("%d\n%d\n%d\n", getpid(), getsid(0), getpgrp());
+
+       {
+       struct event e_sigchld;
+       struct cli *cli;
+       int i;
+
+       mgt_eb = event_init();
+       assert(mgt_eb != NULL);
+
+       if (dflag)
+               cli = cli_setup(mgt_eb, 0, 1, 1, cli_proto);
+
+       signal_set(&e_sigchld, SIGCHLD, mgt_sigchld, NULL);
+       AZ(event_base_set(mgt_eb, &e_sigchld));
+       AZ(signal_add(&e_sigchld, NULL));
+
+       mgt_child_start();
+
+       i = event_base_loop(mgt_eb, 0);
+       if (i != 0)
+               printf("event_dispatch() = %d\n", i);
+
+       }
+
+       exit(0);
+}
+#endif
index 46f382e7ce28b4f3fad02ee8c2fbced5d31a5678..8ea8a2c0916fe9a3b368eab4003bd61494a524ff 100644 (file)
 #include <time.h>
 #include <unistd.h>
 
-#include <sys/wait.h>
-
-#include "event.h"
 #include "sbuf.h"
 
-#include <cli.h>
-#include <cli_priv.h>
-#include <libvarnish.h>
-#include <libvcl.h>
+#include "libvarnish.h"
+#include "libvcl.h"
+#include "cli.h"
+#include "cli_priv.h"
+#include "common_cli.h"
 
 #include "mgt.h"
 #include "heritage.h"
 #include "shmlog.h"
-#include "cli_event.h"
 
 /*--------------------------------------------------------------------*/
 
@@ -75,8 +72,8 @@ static const char *default_vcl =
 /*--------------------------------------------------------------------*/
 
 struct heritage heritage;
-struct event_base *mgt_eb;
 
+#if 0
 /*--------------------------------------------------------------------
  * Generic passthrough for CLI functions
  */
@@ -101,6 +98,7 @@ m_cli_func_passthrough(struct cli *cli, char **av, void *priv)
        cli_suspend(cli);
        mgt_child_request(cli_passthrough_cb, cli, &av[2], av[1]);
 }
+#endif
 
 /*--------------------------------------------------------------------*/
 
@@ -149,7 +147,7 @@ vcl_default(const char *bflag)
        free(buf);
        return (vf);
 }
-
+#if 0
 static void
 m_cli_func_config_inline(struct cli *cli, char **av, void *priv)
 {
@@ -196,6 +194,7 @@ m_cli_func_config_load(struct cli *cli, char **av, void *priv)
        mgt_child_request(cli_passthrough_cb, cli, NULL,
            "config.load %s %s", av[2], vf);
 }
+#endif
 
 static char *
 vcl_file(const char *fflag)
@@ -216,6 +215,7 @@ vcl_file(const char *fflag)
        return (vf);
 }
 
+#if 0
 
 /*--------------------------------------------------------------------*/
 
@@ -329,6 +329,7 @@ static struct cli_proto cli_proto[] = {
        { NULL }
 };
 
+#endif
 
 /*--------------------------------------------------------------------*/
 
@@ -585,6 +586,7 @@ DebugStunt(void)
 
 /*--------------------------------------------------------------------*/
 
+
 /* for development purposes */
 #include <printf.h>
 
@@ -686,28 +688,9 @@ main(int argc, char *argv[])
        if (dflag)
                printf("%d\n%d\n%d\n", getpid(), getsid(0), getpgrp());
 
-       {
-       struct event e_sigchld;
-       struct cli *cli;
-       int i;
-
-       mgt_eb = event_init();
-       assert(mgt_eb != NULL);
-
-       if (dflag)
-               cli = cli_setup(mgt_eb, 0, 1, 1, cli_proto);
-
-       signal_set(&e_sigchld, SIGCHLD, mgt_sigchld, NULL);
-       AZ(event_base_set(mgt_eb, &e_sigchld));
-       AZ(signal_add(&e_sigchld, NULL));
+       mgt_cli_init();
 
-       mgt_child_start();
-
-       i = event_base_loop(mgt_eb, 0);
-       if (i != 0)
-               printf("event_dispatch() = %d\n", i);
-
-       }
+       mgt_run(dflag);
 
        exit(0);
 }