Commit b8c018c8 authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

Rework the manager/cacher cli relationship, so that the manager does

not have to grope around in the cacher's data structures.

Whenever the manager gets a CLI command it does not understand, it
will pass it to the cacher process, if it is running.

This complicated "help" a little bit, because we want to show the
combined commands of the manager and cacher.

Since we're dealing with help anyway, hide undocumented debug
commands from it.



git-svn-id: http://www.varnish-cache.org/svn/trunk/varnish-cache@2595 d4fa192b-c00b-0410-8231-f00ffab90ce4
parent d31658d9
......@@ -85,29 +85,69 @@ cli_func_start(struct cli *cli, const char * const *av, void *priv)
return;
}
/*--------------------------------------------------------------------*/
struct cli_proto CLI_cmds[] = {
static void ccf_help(struct cli *cli, const char * const *av, void *priv);
/*--------------------------------------------------------------------
* The CLI commandlist is split in three:
* Commands we get from/share with the manager
* Cache process commands
* Undocumented commands
*/
static struct cli_proto master_cmds[] = {
{ CLI_PING, cli_func_ping },
{ CLI_SERVER_START, cli_func_start },
#if 0
{ CLI_URL_QUERY, cli_func_url_query },
#endif
{ CLI_URL_PURGE, cli_func_url_purge },
{ CLI_HASH_PURGE, cli_func_hash_purge },
{ CLI_VCL_LOAD, cli_func_config_load },
{ CLI_VCL_LIST, cli_func_config_list },
{ CLI_VCL_DISCARD, cli_func_config_discard },
{ CLI_VCL_USE, cli_func_config_use },
{ NULL }
};
/* Undocumented functions for debugging */
static struct cli_proto cacher_cmds[] = {
{ CLI_HELP, ccf_help, NULL },
{ CLI_URL_PURGE, cli_func_url_purge },
{ CLI_HASH_PURGE, cli_func_hash_purge },
#if 0
{ CLI_URL_QUERY, cli_func_url_query },
#endif
{ NULL }
};
static struct cli_proto undoc_cmds[] = {
{ "debug.sizeof", "debug.sizeof",
"\tDump sizeof various data structures\n",
0, 0, cli_debug_sizeof },
{ NULL }
};
/*--------------------------------------------------------------------*/
static void
ccf_help(struct cli *cli, const char * const *av, void *priv)
{
(void)priv;
/* "+1" to skip "help" entry, manager already did that. */
cli_func_help(cli, av, cacher_cmds + 1);
if (av[2] != NULL && !strcmp(av[2], "-d")) {
/* Also list undocumented commands */
cli_out(cli, "\nDebugging commands:\n");
cli_func_help(cli, av, undoc_cmds);
} else if (cli->result == CLIS_UNKNOWN) {
/* Otherwise, try the undocumented list */
vsb_clear(cli->sb);
cli->result = CLIS_OK;
cli_func_help(cli, av, undoc_cmds);
}
}
/*--------------------------------------------------------------------*/
static int
cli_vlu(void *priv, const char *p)
{
......@@ -117,7 +157,17 @@ cli_vlu(void *priv, const char *p)
cli = priv;
VSL(SLT_CLI, 0, "Rd %s", p);
vsb_clear(cli->sb);
cli_dispatch(cli, CLI_cmds, p);
cli_dispatch(cli, master_cmds, p);
if (cli->result == CLIS_UNKNOWN) {
vsb_clear(cli->sb);
cli->result = CLIS_OK;
cli_dispatch(cli, cacher_cmds, p);
}
if (cli->result == CLIS_UNKNOWN) {
vsb_clear(cli->sb);
cli->result = CLIS_OK;
cli_dispatch(cli, undoc_cmds, p);
}
vsb_finish(cli->sb);
AZ(vsb_overflowed(cli->sb));
i = cli_writeres(heritage.fds[1], cli);
......
......@@ -78,73 +78,30 @@ mcf_stats(struct cli *cli, const char * const *av, void *priv)
#undef MAC_STAT
}
/*--------------------------------------------------------------------
* Passthru of cli commands. It is more or less just undoing what
* the cli parser did, but such is life...
*/
static void
mcf_passthru(struct cli *cli, const char * const *av, void *priv)
mcf_help(struct cli *cli, const char * const *av, void *priv)
{
struct vsb *sb;
const char *p;
char *q;
unsigned u;
int i;
(void)priv;
char *p;
/* Request */
if (cli_o <= 0) {
cli_result(cli, CLIS_CANT);
cli_out(cli, "Cache process not running");
return;
}
sb = vsb_new(NULL, NULL, 64, VSB_AUTOEXTEND);
XXXAN(sb);
for (u = 1; av[u] != NULL; u++) {
if (u > 1)
vsb_putc(sb, ' ');
vsb_putc(sb, '"');
for (p = av[u]; *p; p++) {
switch (*p) {
case '\\':
vsb_cat(sb, "\\\\");
break;
case '\n':
vsb_cat(sb, "\\n");
break;
case '"':
vsb_cat(sb, "\\\"");
break;
default:
vsb_putc(sb, *p);
}
}
vsb_putc(sb, '"');
cli_func_help(cli, av, priv);
if (cli_o >= 0 && (av[2] == NULL || *av[2] == '-')) {
p = NULL;
if (!mgt_cli_askchild(&u, &p,
"help %s\n", av[2] != NULL ? av[2] : "")) {
cli_out(cli, "%s", p);
cli_result(cli, u);
}
free(p);
}
vsb_putc(sb, '\n');
xxxassert(!vsb_overflowed(sb));
vsb_finish(sb);
AZ(vsb_overflowed(sb));
i = write(cli_o, vsb_data(sb), vsb_len(sb));
xxxassert(i == vsb_len(sb));
vsb_delete(sb);
i = cli_readres(cli_i, &u, &q, params->cli_timeout);
cli_result(cli, u);
cli_out(cli, "%s", q);
free(q);
}
/*--------------------------------------------------------------------*/
static struct cli_proto *cli_proto;
/* XXX: what order should this list be in ? */
static struct cli_proto mgt_cli_proto[] = {
static struct cli_proto cli_proto[] = {
{ CLI_HELP, mcf_help, cli_proto },
{ CLI_PING, cli_func_ping },
{ CLI_SERVER_STATUS, mcf_server_status, NULL },
{ CLI_SERVER_START, mcf_server_startstop, NULL },
......@@ -158,7 +115,6 @@ static struct cli_proto mgt_cli_proto[] = {
{ CLI_VCL_SHOW, mcf_config_show, NULL },
{ CLI_PARAM_SHOW, mcf_param_show, NULL },
{ CLI_PARAM_SET, mcf_param_set, NULL },
{ CLI_HELP, cli_func_help, NULL },
#if 0
{ CLI_SERVER_RESTART },
{ CLI_ZERO },
......@@ -170,59 +126,13 @@ static struct cli_proto mgt_cli_proto[] = {
{ 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);
XXXAN(cli_proto);
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 = mcf_passthru;
u++;
}
/* Fixup the entry for 'help' entry */
for (u = 0; cli_proto[u].request != NULL; u++) {
if (!strcmp(cli_proto[u].request, "help")) {
cli_proto[u].priv = cli_proto;
break;
}
}
}
/*--------------------------------------------------------------------
* Ask the child something over CLI, return zero only if everything is
* happy happy.
*/
int
mgt_cli_askchild(unsigned *status, char **resp, const char *fmt, ...)
{
mgt_cli_askchild(unsigned *status, char **resp, const char *fmt, ...) {
char *p;
int i, j;
va_list ap;
......@@ -319,12 +229,41 @@ static int
mgt_cli_vlu(void *priv, const char *p)
{
struct cli_port *cp;
char *q;
unsigned u;
int i;
CAST_OBJ_NOTNULL(cp, priv, CLI_PORT_MAGIC);
vsb_clear(cp->cli->sb);
cli_dispatch(cp->cli, cli_proto, p);
vsb_finish(cp->cli->sb);
AZ(vsb_overflowed(cp->cli->sb));
if (cp->cli->result == CLIS_UNKNOWN) {
/*
* Command not recognized in master, try cacher if it is
* running.
*/
vsb_clear(cp->cli->sb);
cp->cli->result = CLIS_OK;
if (cli_o <= 0) {
cli_result(cp->cli, CLIS_UNKNOWN);
cli_out(cp->cli,
"Unknown request in manager process "
"(child not running).\n"
"Type 'help' for more info.");
} else {
i = write(cli_o, p, strlen(p));
xxxassert(i == strlen(p));
i = write(cli_o, "\n", 1);
xxxassert(i == 1);
i = cli_readres(cli_i, &u, &q, params->cli_timeout);
cli_result(cp->cli, u);
cli_out(cp->cli, "%s", q);
free(q);
}
vsb_finish(cp->cli->sb);
AZ(vsb_overflowed(cp->cli->sb));
}
/* send the result back */
if (cli_writeres(cp->fdo, cp->cli))
......
......@@ -556,8 +556,6 @@ main(int argc, char *argv[])
if (pfh != NULL && vpf_write(pfh))
fprintf(stderr, "NOTE: Could not write PID file\n");
mgt_cli_init();
mgt_run(d_flag, T_arg);
if (pfh != NULL)
......
......@@ -37,6 +37,5 @@ struct cli {
int cli_writeres(int fd, const struct cli *cli);
int cli_readres(int fd, unsigned *status, char **ptr, double tmo);
extern struct cli_proto CLI_cmds[];
cli_func_t cli_func_ping;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment