Mailing List Archive

r58 - trunk/varnish-cache/bin/varnishd
Author: phk
Date: 2006-03-17 11:03:05 +0100 (Fri, 17 Mar 2006)
New Revision: 58

Added:
trunk/varnish-cache/bin/varnishd/mgt.h
trunk/varnish-cache/bin/varnishd/mgt_child.c
Modified:
trunk/varnish-cache/bin/varnishd/Makefile.am
trunk/varnish-cache/bin/varnishd/cache_main.c
trunk/varnish-cache/bin/varnishd/cli_event.c
trunk/varnish-cache/bin/varnishd/heritage.h
trunk/varnish-cache/bin/varnishd/varnishd.c
Log:
Add multiplexing for the mgt->child cli connection and get ping/pong
working across it.

The management process will now keep the child process watchdog from
expiring.



Modified: trunk/varnish-cache/bin/varnishd/Makefile.am
===================================================================
--- trunk/varnish-cache/bin/varnishd/Makefile.am 2006-03-16 12:14:59 UTC (rev 57)
+++ trunk/varnish-cache/bin/varnishd/Makefile.am 2006-03-17 10:03:05 UTC (rev 58)
@@ -7,6 +7,7 @@
varnishd_SOURCES = \
cache_main.c \
cli_event.c \
+ mgt_child.c \
varnishd.c

varnishd_LDADD = \

Modified: trunk/varnish-cache/bin/varnishd/cache_main.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache_main.c 2006-03-16 12:14:59 UTC (rev 57)
+++ trunk/varnish-cache/bin/varnishd/cache_main.c 2006-03-17 10:03:05 UTC (rev 58)
@@ -33,7 +33,7 @@
{
struct timeval tv;

- tv.tv_sec = 5;
+ tv.tv_sec = 30;
tv.tv_usec = 0;

evtimer_del(&ev_keepalive);
@@ -48,8 +48,10 @@
time_t t;

arm_keepalive();
- if (av[2] != NULL)
- cli_out(cli, "Got your %s\n", av[2]);
+ if (av[2] != NULL) {
+ /* XXX: check clock skew is pointless here */
+ printf("Got your ping %s\n", av[2]);
+ }
time(&t);
cli_out(cli, "PONG %ld\n", t);
}
@@ -75,7 +77,7 @@
eb = event_init();
assert(eb != NULL);

- cli = cli_setup(heritage.fds[0], heritage.fds[1], 0, cli_proto);
+ cli = cli_setup(heritage.fds[2], heritage.fds[1], 0, cli_proto);

evtimer_set(&ev_keepalive, timer_keepalive, NULL);
arm_keepalive();

Modified: trunk/varnish-cache/bin/varnishd/cli_event.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/cli_event.c 2006-03-16 12:14:59 UTC (rev 57)
+++ trunk/varnish-cache/bin/varnishd/cli_event.c 2006-03-17 10:03:05 UTC (rev 58)
@@ -108,7 +108,7 @@
static void
excb(struct bufferevent *bev, short what, void *arg)
{
- printf("Exception\n");
+ printf("%s(%p, %d, %p)\n", __func__, (void*)bev, what, arg);
}

struct cli *

Modified: trunk/varnish-cache/bin/varnishd/heritage.h
===================================================================
--- trunk/varnish-cache/bin/varnishd/heritage.h 2006-03-16 12:14:59 UTC (rev 57)
+++ trunk/varnish-cache/bin/varnishd/heritage.h 2006-03-17 10:03:05 UTC (rev 58)
@@ -5,7 +5,7 @@
*/

struct heritage {
- int fds[2];
+ int fds[4];
};

extern struct heritage heritage;

Added: trunk/varnish-cache/bin/varnishd/mgt.h
===================================================================
--- trunk/varnish-cache/bin/varnishd/mgt.h 2006-03-16 12:14:59 UTC (rev 57)
+++ trunk/varnish-cache/bin/varnishd/mgt.h 2006-03-17 10:03:05 UTC (rev 58)
@@ -0,0 +1,12 @@
+/*
+ * $Id$
+ */
+
+extern struct event_base *eb;
+
+void mgt_child_start(void);
+void mgt_child_stop(void);
+void mgt_sigchld(int, short, void *);
+
+typedef void mgt_ccb_f(unsigned, const char *, void *);
+void mgt_child_request(mgt_ccb_f *, void *, const char *fmt, ...);

Added: trunk/varnish-cache/bin/varnishd/mgt_child.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/mgt_child.c 2006-03-16 12:14:59 UTC (rev 57)
+++ trunk/varnish-cache/bin/varnishd/mgt_child.c 2006-03-17 10:03:05 UTC (rev 58)
@@ -0,0 +1,291 @@
+/*
+ * $Id$
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <sys/wait.h>
+#include <sys/queue.h>
+
+#include <event.h>
+#include <sbuf.h>
+
+#include <libvarnish.h>
+#include <cli.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;
+
+struct creq {
+ TAILQ_ENTRY(creq) list;
+ char *req;
+ 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)
+{
+ const char *p;
+
+ 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", __func__, (void*)bev, arg);
+ exit (2);
+}
+
+static void
+std_excb(struct bufferevent *bev, short what, void *arg)
+{
+
+ printf("%s(%p, %d, %p)\n", __func__, (void*)bev, what, arg);
+ exit (2);
+}
+
+/*--------------------------------------------------------------------
+ * Multiplex requests/answers to the child
+ */
+
+static void
+send_req(void)
+{
+ struct creq *cr;
+
+ cr = TAILQ_FIRST(&creqhead);
+ if (cr == NULL)
+ return;
+ printf("Send Request <%s>\n", cr->req);
+ evbuffer_add_printf(child_cli1->output, "%s\n", cr->req);
+ bufferevent_enable(child_cli1, EV_WRITE);
+}
+
+void
+mgt_child_request(mgt_ccb_f *func, void *priv, 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;
+ 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;
+
+ 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 __unused, void *arg __unused)
+{
+
+}
+
+static void
+cli_excb(struct bufferevent *bev, short what, void *arg)
+{
+
+ printf("%s(%p, %d, %p)\n", __func__, (void*)bev, what, arg);
+ exit (2);
+}
+
+/*--------------------------------------------------------------------*/
+
+static void
+child_pingpong_ccb(unsigned u, const char *r, void *priv)
+{
+ printf("%s(%u, \"%s\", %p)\n", __func__, u, r, priv);
+ /* XXX: reset keepalive timer */
+}
+
+
+static void
+child_pingpong(int a, short b, void *c)
+{
+ time_t t;
+ struct timeval tv;
+
+ printf("%s(%d, %d, %p)\n", __func__, a, b, c);
+ time(&t);
+ mgt_child_request(child_pingpong_ccb, NULL, "ping %ld", t);
+ if (1) {
+ tv.tv_sec = 3;
+ tv.tv_usec = 0;
+ evtimer_del(&ev_child_pingpong);
+ evtimer_add(&ev_child_pingpong, &tv);
+ }
+}
+
+
+/*--------------------------------------------------------------------*/
+
+static void
+start_child(void)
+{
+ int i;
+
+ assert(pipe(&heritage.fds[0]) == 0);
+ assert(pipe(&heritage.fds[2]) == 0);
+ assert(pipe(child_fds) == 0);
+ i = fork();
+ if (i < 0)
+ errx(1, "Could not fork child");
+ if (i == 0) {
+ /* XXX: close fds */
+ /* XXX: (re)set signals */
+
+ /* Redirect stdin/out/err */
+ close(0);
+ i = open("/dev/null", O_RDONLY);
+ assert(i == 0);
+ close(child_fds[0]);
+ dup2(child_fds[1], 1);
+ dup2(child_fds[1], 2);
+ close(child_fds[1]);
+
+ child_main();
+
+ exit (1);
+ }
+ child_pid = i;
+ printf("start child pid %d\n", i);
+
+ /*
+ * We do not close the unused ends of the pipes here to avoid
+ * doing SIGPIPE handling.
+ */
+ child_std = bufferevent_new(child_fds[0],
+ std_rdcb, std_wrcb, std_excb, NULL);
+ assert(child_std != NULL);
+ bufferevent_enable(child_std, EV_READ);
+ child_cli0 = bufferevent_new(heritage.fds[0],
+ cli_rdcb, cli_wrcb, cli_excb, NULL);
+ assert(child_cli0 != NULL);
+ bufferevent_enable(child_cli0, EV_READ);
+ child_cli1 = bufferevent_new(heritage.fds[3],
+ cli_rdcb, cli_wrcb, cli_excb, NULL);
+ assert(child_cli1 != NULL);
+
+ evtimer_set(&ev_child_pingpong, child_pingpong, NULL);
+ child_pingpong(0, 0, NULL);
+}
+
+
+/*--------------------------------------------------------------------*/
+
+void
+mgt_child_start(void)
+{
+
+ if (desired == H_START)
+ return;
+ desired = H_START;
+ start_child();
+}
+
+/*--------------------------------------------------------------------*/
+
+void
+mgt_child_stop(void)
+{
+
+ if (desired == H_STOP)
+ return;
+ desired = H_STOP;
+}
+
+/*--------------------------------------------------------------------*/
+
+void
+mgt_sigchld(int a, short b, void *c)
+{
+ pid_t p;
+ int status;
+
+ printf("sig_chld(%d, %d, %p)\n", a, b, c);
+
+ p = wait4(-1, &status, WNOHANG, NULL);
+ printf("pid = %d status = 0x%x\n", p, status);
+ assert(p == child_pid);
+
+ bufferevent_free(child_std); /* XXX: is this enough ? */
+ child_std = NULL;
+
+ close(heritage.fds[0]);
+ close(heritage.fds[1]);
+ close(heritage.fds[2]);
+ close(heritage.fds[3]);
+ close(child_fds[0]);
+ close(child_fds[1]);
+
+ if (desired == H_START)
+ start_child();
+}

Modified: trunk/varnish-cache/bin/varnishd/varnishd.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/varnishd.c 2006-03-16 12:14:59 UTC (rev 57)
+++ trunk/varnish-cache/bin/varnishd/varnishd.c 2006-03-17 10:03:05 UTC (rev 58)
@@ -1,5 +1,7 @@
/*
* $Id$
+ *
+ * The management process and CLI handling
*/

#include <assert.h>
@@ -22,133 +24,39 @@
#include <cli_priv.h>
#include <libvarnish.h>

+#include "mgt.h"
#include "heritage.h"
#include "cli_event.h"

/*--------------------------------------------------------------------*/

-static enum {
- H_STOP = 0,
- H_START
-} desired;
-static pid_t child_pid;
-static int child_fds[2];
-
struct heritage heritage;
+struct event_base *eb;

-static struct event_base *eb;
-
-static struct bufferevent *child_std;
-
/*--------------------------------------------------------------------*/

-static void
-std_rdcb(struct bufferevent *bev, void *arg)
+void
+xxx_ccb(unsigned u, const char *r, void *priv)
{
- const char *p;
-
- p = evbuffer_readline(bev->input);
- if (p == NULL)
- return;
- printf("Child said <%s>\n", p);
+ printf("%s(%u, %s, %p)\n", __func__, u, r, priv);
}

-static void
-std_wrcb(struct bufferevent *bev, void *arg)
-{
-
- printf("%s(%p, %p)\n", __func__, (void*)bev, arg);
- exit (2);
-}
-
-static void
-std_excb(struct bufferevent *bev, short what, void *arg)
-{
-
- printf("%s(%p, %d, %p)\n", __func__, (void*)bev, what, arg);
- exit (2);
-}
-
-
-
/*--------------------------------------------------------------------*/

static void
-start_child(void)
+cli_func_url_query(struct cli *cli, char **av __unused, void *priv __unused)
{
- int i;

- assert(pipe(heritage.fds) == 0);
- assert(pipe(child_fds) == 0);
- i = fork();
- if (i < 0)
- errx(1, "Could not fork child");
- if (i == 0) {
- /* XXX: close fds */
- /* XXX: (re)set signals */
-
- /* Redirect stdin/out/err */
- close(0);
- i = open("/dev/null", O_RDONLY);
- assert(i == 0);
- close(child_fds[0]);
- dup2(child_fds[1], 1);
- dup2(child_fds[1], 2);
- close(child_fds[1]);
-
- child_main();
-
- exit (1);
- }
- child_pid = i;
- printf("start child pid %d\n", i);
-
- /*
- * We do not close the unused ends of the pipes here to avoid
- * doing SIGPIPE handling.
- */
- child_std = bufferevent_new(child_fds[0],
- std_rdcb, std_wrcb, std_excb, NULL);
- assert(child_std != NULL);
- bufferevent_enable(child_std, EV_READ);
+ mgt_child_request(xxx_ccb, NULL, "url.query %s", av[2]);
}

/*--------------------------------------------------------------------*/

static void
-sig_chld(int a, short b, void *c)
-{
- pid_t p;
- int status;
-
- printf("sig_chld(%d, %d, %p)\n", a, b, c);
-
- p = wait4(-1, &status, WNOHANG, NULL);
- printf("pid = %d status = 0x%x\n", p, status);
- assert(p == child_pid);
-
- bufferevent_free(child_std); /* XXX: is this enough ? */
- child_std = NULL;
-
- close(heritage.fds[0]);
- close(heritage.fds[1]);
- close(child_fds[0]);
- close(child_fds[1]);
-
- if (desired == H_START)
- start_child();
-}
-
-/*--------------------------------------------------------------------*/
-
-static void
cli_func_server_start(struct cli *cli, char **av __unused, void *priv __unused)
{

- if (desired != H_START) {
- desired = H_START;
- start_child();
- }
+ mgt_child_start();
}

/*--------------------------------------------------------------------*/
@@ -157,12 +65,7 @@
cli_func_server_stop(struct cli *cli, char **av __unused, void *priv __unused)
{

- if (desired != H_STOP) {
- desired = H_STOP;
-#if 0
- stop_child();
-#endif
- }
+ mgt_child_stop();
}

/*--------------------------------------------------------------------*/
@@ -174,6 +77,7 @@
cli->verbose = !cli->verbose;
}

+
static void
cli_func_ping(struct cli *cli, char **av, void *priv __unused)
{
@@ -190,7 +94,7 @@

static struct cli_proto cli_proto[] = {
/* URL manipulation */
- { CLI_URL_QUERY },
+ { CLI_URL_QUERY, cli_func_url_query, NULL },
{ CLI_URL_PURGE },
{ CLI_URL_STATUS },
{ CLI_CONFIG_LOAD },
@@ -228,7 +132,7 @@

cli = cli_setup(0, 1, 1, cli_proto);

- signal_set(&e_sigchld, SIGCHLD, sig_chld, NULL);
+ signal_set(&e_sigchld, SIGCHLD, mgt_sigchld, NULL);
signal_add(&e_sigchld, NULL);

i = event_dispatch();