From: phk Date: Thu, 3 Aug 2006 09:45:14 +0000 (+0000) Subject: Rip out the old CLI handling and start over, more or less. X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d7abdd7cf66f138b31fca4b2ff0fd5b2567476e0;p=varnish Rip out the old CLI handling and start over, more or less. Still bits missing. git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@616 d4fa192b-c00b-0410-8231-f00ffab90ce4 --- diff --git a/varnish-cache/bin/varnishd/Makefile.am b/varnish-cache/bin/varnishd/Makefile.am index c11e96cd..2aaf58c3 100644 --- a/varnish-cache/bin/varnishd/Makefile.am +++ b/varnish-cache/bin/varnishd/Makefile.am @@ -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 diff --git a/varnish-cache/bin/varnishd/cache_cli.c b/varnish-cache/bin/varnishd/cache_cli.c index 16a322f0..9698c194 100644 --- a/varnish-cache/bin/varnishd/cache_cli.c +++ b/varnish-cache/bin/varnishd/cache_cli.c @@ -10,13 +10,11 @@ #include #include -#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) diff --git a/varnish-cache/bin/varnishd/cache_main.c b/varnish-cache/bin/varnishd/cache_main.c index e70acce2..ed2436b4 100644 --- a/varnish-cache/bin/varnishd/cache_main.c +++ b/varnish-cache/bin/varnishd/cache_main.c @@ -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 index 00000000..bacc2e6f --- /dev/null +++ b/varnish-cache/bin/varnishd/cli_common.c @@ -0,0 +1,46 @@ +/* + * $Id$ + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "sbuf.h" + +#include +#include +#include + +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 index 55c693d4..00000000 --- a/varnish-cache/bin/varnishd/cli_event.c +++ /dev/null @@ -1,172 +0,0 @@ -/* - * $Id$ - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include - -#include -#include -#include - -#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 index 00000000..932b169d --- /dev/null +++ b/varnish-cache/bin/varnishd/common_cli.c @@ -0,0 +1,67 @@ +/* + * $Id: cli_event.c 466 2006-07-12 23:30:49Z phk $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#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); +} diff --git a/varnish-cache/bin/varnishd/cli_event.h b/varnish-cache/bin/varnishd/common_cli.h similarity index 57% rename from varnish-cache/bin/varnishd/cli_event.h rename to varnish-cache/bin/varnishd/common_cli.h index 877c7d22..5c62b13f 100644 --- a/varnish-cache/bin/varnishd/cli_event.h +++ b/varnish-cache/bin/varnishd/common_cli.h @@ -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[]; diff --git a/varnish-cache/bin/varnishd/mgt.h b/varnish-cache/bin/varnishd/mgt.h index b3488049..f3740db2 100644 --- a/varnish-cache/bin/varnishd/mgt.h +++ b/varnish-cache/bin/varnishd/mgt.h @@ -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); diff --git a/varnish-cache/bin/varnishd/mgt_child.c b/varnish-cache/bin/varnishd/mgt_child.c index 7ed370a1..ccffc5c6 100644 --- a/varnish-cache/bin/varnishd/mgt_child.c +++ b/varnish-cache/bin/varnishd/mgt_child.c @@ -4,214 +4,65 @@ * The mechanics of handling the child process */ -#include -#include -#include -#include -#include -#include +#include #include +#include #include -#include -#include - +#include +#include +#include +#include +#include +#include #include -#include "queue.h" - -#include -#include -#include -#include +#include /* 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 index 00000000..4d36e0fd --- /dev/null +++ b/varnish-cache/bin/varnishd/mgt_cli.c @@ -0,0 +1,508 @@ +/* + * $Id$ + * + * The management process' CLI handling + */ + +#include +#include +#include +#include +#include +#include +#include + +#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 + +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 diff --git a/varnish-cache/bin/varnishd/varnishd.c b/varnish-cache/bin/varnishd/varnishd.c index 46f382e7..8ea8a2c0 100644 --- a/varnish-cache/bin/varnishd/varnishd.c +++ b/varnish-cache/bin/varnishd/varnishd.c @@ -17,20 +17,17 @@ #include #include -#include - -#include "event.h" #include "sbuf.h" -#include -#include -#include -#include +#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 @@ -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); }