From ff92ffd37ff02073bf6a1858ad0af25d7d6f6f00 Mon Sep 17 00:00:00 2001 Message-Id: From: Mark Wooding Date: Mon, 1 Jan 2007 12:52:32 +0000 Subject: [PATCH] admin: Improve handling of background jobs. Organization: Straylight/Edgeware From: Mark Wooding New commands BGCANCEL (cancel an outstanding job) and JOBS (list outstanding jobs). --- doc/tripe-admin.5.in | 22 +++++++++++++++ server/admin.c | 66 ++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 82 insertions(+), 6 deletions(-) diff --git a/doc/tripe-admin.5.in b/doc/tripe-admin.5.in index 3ea15b11..9fd8a1d7 100644 --- a/doc/tripe-admin.5.in +++ b/doc/tripe-admin.5.in @@ -257,6 +257,10 @@ Emits an line reporting the IP address and port number stored for .IR peer . .SP +.BI "BGCANCEL " tag +Cancels the background job with the named +.IR tag . +.SP .BI "CHECKCHAL " challenge Verifies a challenge as being one earlier issued by .B GETCHAL @@ -311,6 +315,11 @@ packets which are to be encrypted and sent to Used by configuration scripts so that they can set up routing tables appropriately after adding new peers. .SP +.B "JOBS" +Emits an +.B INFO +line giving the tag for each outstanding background job. +.SP .BI "KILL " peer Causes the server to forget all about .IR peer . @@ -646,6 +655,11 @@ The DNS name .I hostname took too long to resolve. .SP +.BI "tag-exists " tag +(For long-running commands.) The named +.I tag +is already the tag of an outstanding job. +.SP .BI "unknown-command " token The command .B token @@ -669,6 +683,14 @@ The service name .I service couldn't be found in .BR /etc/services . +.TP +.BI "unknown-tag " tag +(For +.BR BGCANCEL .) +The given +.I tag +is not the tag for any outstanding background job. It may have just +finished. .SH "NOTIFICATIONS" .\"* 30 Notification broadcasts (NOTE codes) The following notifications are sent to clients who request them. diff --git a/server/admin.c b/server/admin.c index 1660106c..927f3ca4 100644 --- a/server/admin.c +++ b/server/admin.c @@ -620,6 +620,25 @@ static peer *a_findpeer(admin *a, const char *pn) #define BGTAG(bg) \ (((admin_bgop *)(bg))->tag ? ((admin_bgop *)(bg))->tag : "") +/* --- @a_bgfind@ --- * + * + * Arguments: @admin *a@ = a client block + * @const char *tag@ = the requested tag + * + * Returns: The requested background job, or null. + */ + +static admin_bgop *a_bgfind(admin *a, const char *tag) +{ + admin_bgop *bg; + + for (bg = a->bg; bg; bg = bg->next) { + if (bg->tag && strcmp(tag, bg->tag) == 0) + return (bg); + } + return (0); +} + /* --- @a_bgrelease@ --- * * * Arguments: @admin_bgop *bg@ = backgrounded operation @@ -681,16 +700,21 @@ static void a_bgfail(admin_bgop *bg, const char *fmt, ...) * @const char *tag@ = background tag, or null for foreground * @void (*cancel)(admin_bgop *)@ = cancel function * - * Returns: --- + * Returns: Zero for success, nonzero on failure. * * Use: Links a background job into the list. */ -static void a_bgadd(admin *a, admin_bgop *bg, const char *tag, - void (*cancel)(admin_bgop *)) +static int a_bgadd(admin *a, admin_bgop *bg, const char *tag, + void (*cancel)(admin_bgop *)) { - if (tag) + if (tag) { + if (a_bgfind(a, tag)) { + a_fail(a, "tag-exists", "%s", tag, A_END); + return (-1); + } bg->tag = xstrdup(tag); + } else { bg->tag = 0; selbuf_disable(&a->b); @@ -703,6 +727,7 @@ static void a_bgadd(admin *a, admin_bgop *bg, const char *tag, a->bg = bg; T( trace(T_ADMIN, "admin: add bgop %s", BGTAG(bg)); ) if (tag) a_write(a, "DETACH", tag, A_END); + return (0); } /*----- Name resolution operations ----------------------------------------*/ @@ -834,7 +859,8 @@ static void a_resolve(admin *a, admin_resop *r, const char *tag, * answer straight away. */ - a_bgadd(a, &r->bg, tag, a_rescancel); + if (a_bgadd(a, &r->bg, tag, a_rescancel)) + goto fail; T( trace(T_ADMIN, "admin: %u, resop %s, hostname `%s'", a->seq, BGTAG(r), r->addr); ) @@ -1086,7 +1112,8 @@ static void a_ping(admin *a, unsigned ac, char *av[], return; pg = xmalloc(sizeof(*pg)); gettimeofday(&pg->pingtime, 0); - a_bgadd(a, &pg->bg, tag, a_pingcancel); + if (a_bgadd(a, &pg->bg, tag, a_pingcancel)) + goto fail; T( trace(T_ADMIN, "admin: ping op %s: %s to %s", BGTAG(pg), cmd, p_name(p)); ) if (p_pingsend(p, &pg->ping, msg, t, a_pong, pg)) { @@ -1098,6 +1125,7 @@ static void a_ping(admin *a, unsigned ac, char *av[], bad_syntax: a_fail(a, "bad-syntax", "%s", cmd, "[OPTIONS] PEER", cmd, A_END); fail: + if (pg) xfree(pg); return; } @@ -1225,6 +1253,30 @@ static void acmd_daemon(admin *a, unsigned ac, char *av[]) } } +static void acmd_jobs(admin *a, unsigned ac, char *av[]) +{ + admin_bgop *bg; + + for (bg = a->bg; bg; bg = bg->next) { + assert(bg->tag); + a_info(a, "%s", bg->tag, A_END); + } + a_ok(a); +} + +static void acmd_bgcancel(admin *a, unsigned ac, char *av[]) +{ + admin_bgop *bg; + + if ((bg = a_bgfind(a, av[0])) == 0) + a_fail(a, "unknown-tag", "%s", av[0], A_END); + else { + bg->cancel(bg); + a_bgrelease(bg); + a_ok(a); + } +} + static void acmd_list(admin *a, unsigned ac, char *av[]) { peer *p; @@ -1414,6 +1466,7 @@ static void acmd_help(admin */*a*/, unsigned /*ac*/, char */*av*/[]); static const acmd acmdtab[] = { { "add", "[OPTIONS] PEER ADDR ...", 2, 0xffff, acmd_add }, { "addr", "PEER", 1, 1, acmd_addr }, + { "bgcancel", "TAG", 1, 1, acmd_bgcancel }, { "checkchal", "CHAL", 1, 1, acmd_checkchal }, { "daemon", 0, 0, 0, acmd_daemon }, { "eping", "[OPTIONS] PEER", 1, 0xffff, acmd_eping }, @@ -1422,6 +1475,7 @@ static const acmd acmdtab[] = { { "greet", "PEER CHAL", 2, 2, acmd_greet }, { "help", 0, 0, 0, acmd_help }, { "ifname", "PEER", 1, 1, acmd_ifname }, + { "jobs", 0, 0, 0, acmd_jobs }, { "kill", "PEER", 1, 1, acmd_kill }, { "list", 0, 0, 0, acmd_list }, { "notify", "MESSAGE ...", 1, 0xffff, acmd_notify }, -- [mdw]