dump_requestlist feature.

git-svn-id: file:///svn/unbound/trunk@1473 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2009-02-10 15:11:54 +00:00
parent 5c0e815e73
commit 5f6eb6d58e
4 changed files with 128 additions and 0 deletions

View file

@ -62,6 +62,9 @@
#include "validator/validator.h"
#include "validator/val_kcache.h"
#include "validator/val_kentry.h"
#include "iterator/iterator.h"
#include "services/outbound_list.h"
#include "services/outside_network.h"
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
@ -1228,6 +1231,122 @@ do_status(SSL* ssl, struct worker* worker)
return;
}
/** get age for the mesh state */
static void
get_mesh_age(struct mesh_state* m, char* buf, size_t len,
struct module_env* env)
{
if(m->reply_list) {
struct timeval d;
struct mesh_reply* r = m->reply_list;
/* last reply is the oldest */
while(r && r->next)
r = r->next;
timeval_subtract(&d, env->now_tv, &r->start_time);
snprintf(buf, len, "%d.%6.6d", (int)d.tv_sec, (int)d.tv_usec);
} else {
snprintf(buf, len, "-");
}
}
/** get status of a mesh state */
static void
get_mesh_status(struct mesh_area* mesh, struct mesh_state* m,
char* buf, size_t len)
{
enum module_ext_state s = m->s.ext_state[m->s.curmod];
const char *modname = mesh->mods.mod[m->s.curmod]->name;
size_t l;
if(strcmp(modname, "iterator") == 0 && s == module_wait_reply &&
m->s.minfo[m->s.curmod]) {
/* break into iterator to find out who its waiting for */
struct iter_qstate* qstate = (struct iter_qstate*)
m->s.minfo[m->s.curmod];
struct outbound_list* ol = &qstate->outlist;
struct outbound_entry* e;
snprintf(buf, len, "%s wait for", modname);
l = strlen(buf);
buf += l; len -= l;
if(ol->first == NULL)
snprintf(buf, len, " (empty_list)");
for(e = ol->first; e; e = e->next) {
int af = (int)((struct sockaddr_in*)&e->qsent->addr)
->sin_family;
void* sinaddr = &((struct sockaddr_in*)&e->qsent->addr)
->sin_addr;
if(addr_is_ip6(&e->qsent->addr, e->qsent->addrlen))
sinaddr = &((struct sockaddr_in6*)
&e->qsent->addr)->sin6_addr;
snprintf(buf, len, " ");
l = strlen(buf);
buf += l; len -= l;
if(inet_ntop(af, sinaddr, buf, (socklen_t)len) == 0) {
snprintf(buf, len, "(inet_ntop_error)");
}
l = strlen(buf);
buf += l; len -= l;
}
} else if(s == module_wait_subquery) {
/* look in subs from mesh state to see what */
char nm[257];
struct mesh_state_ref* sub;
snprintf(buf, len, "%s wants", modname);
l = strlen(buf);
buf += l; len -= l;
if(m->sub_set.count == 0)
snprintf(buf, len, " (empty_list)");
RBTREE_FOR(sub, struct mesh_state_ref*, &m->sub_set) {
char* t = ldns_rr_type2str(sub->s->s.qinfo.qtype);
char* c = ldns_rr_class2str(sub->s->s.qinfo.qclass);
dname_str(sub->s->s.qinfo.qname, nm);
snprintf(buf, len, " %s %s %s", t, c, nm);
l = strlen(buf);
buf += l; len -= l;
free(t);
free(c);
}
} else {
snprintf(buf, len, "%s is %s", modname, strextstate(s));
}
}
/** do the dump_requestlist command */
static void
do_dump_requestlist(SSL* ssl, struct worker* worker)
{
struct mesh_area* mesh;
struct mesh_state* m;
int num = 0;
char buf[257];
char timebuf[32];
char statbuf[10240];
if(!ssl_printf(ssl, "thread #%d\n", worker->thread_num))
return;
if(!ssl_printf(ssl, "# type cl name seconds module status\n"))
return;
/* show worker mesh contents */
mesh = worker->env.mesh;
if(!mesh) return;
RBTREE_FOR(m, struct mesh_state*, &mesh->all) {
char* t = ldns_rr_type2str(m->s.qinfo.qtype);
char* c = ldns_rr_class2str(m->s.qinfo.qclass);
dname_str(m->s.qinfo.qname, buf);
get_mesh_age(m, timebuf, sizeof(timebuf), &worker->env);
get_mesh_status(mesh, m, statbuf, sizeof(statbuf));
if(!ssl_printf(ssl, "%3d %4s %2s %s %s %s\n",
num, t, c, buf, timebuf, statbuf)) {
free(t);
free(c);
return;
}
num++;
free(t);
free(c);
}
}
/** tell other processes to execute the command */
void
distribute_cmd(struct daemon_remote* rc, SSL* ssl, char* cmd)
@ -1301,6 +1420,8 @@ execute_cmd(struct daemon_remote* rc, SSL* ssl, char* cmd,
do_flush_type(ssl, worker, skipwhite(p+10));
} else if(strncmp(p, "flush", 5) == 0) {
do_flush_name(ssl, worker, skipwhite(p+5));
} else if(strncmp(p, "dump_requestlist", 16) == 0) {
do_dump_requestlist(ssl, worker);
} else {
(void)ssl_printf(ssl, "error unknown command '%s'\n", p);
}

View file

@ -2,6 +2,7 @@
- keys with rfc5011 REVOKE flag are skipped and not considered when
validating data.
- iana portlist updated
- #226: dump_requestlist feature for unbound-control.
6 February 2009: Wouter
- contrib contains specfile for fedora 1.2.1 (from Paul Wouters).

View file

@ -115,6 +115,11 @@ Remove the name, type information from the cache.
Remove all information at or below the name from the cache.
The rrsets and key entries are removed so that new lookups will be performed.
This needs to walk and inspect the entire cache, and is a slow operation.
.TP
.B dump_requestlist
Show what is worked on. Prints all queries that the server is currently
working on. Prints the time that users have been waiting. For internal
requests, no time is printed. And then prints out the module status.
.SH "EXIT CODE"
The unbound-control program exits with status code 1 on error, 0 on success.
.SH "SET UP"

View file

@ -78,6 +78,7 @@ usage()
printf(" flush_type [name] [type] flush name, type from cache\n");
printf(" flush_zone [name] flush everything at or under name\n");
printf(" from rr and dnssec caches\n");
printf(" dump_requestlist show what is worked on\n");
printf("Version %s\n", PACKAGE_VERSION);
printf("BSD licensed, see LICENSE in source package for details.\n");
printf("Report bugs to %s\n", PACKAGE_BUGREPORT);