diff options
Diffstat (limited to 'testcode')
| -rw-r--r-- | testcode/checklocks.c | 24 | ||||
| -rw-r--r-- | testcode/fake_event.c | 72 | ||||
| -rw-r--r-- | testcode/replay.c | 14 | ||||
| -rw-r--r-- | testcode/replay.h | 9 | ||||
| -rw-r--r-- | testcode/testbound.c | 6 |
5 files changed, 123 insertions, 2 deletions
diff --git a/testcode/checklocks.c b/testcode/checklocks.c index 1b5ef282b5e4..d1c877467307 100644 --- a/testcode/checklocks.c +++ b/testcode/checklocks.c @@ -68,6 +68,17 @@ static struct thr_check* thread_infos[THRDEBUG_MAX_THREADS]; int check_locking_order = 1; /** the pid of this runset, reasonably unique. */ static pid_t check_lock_pid; +/** + * Should checklocks print a trace of the lock and unlock calls. + * It uses fprintf for that because the log function uses a lock and that + * would loop otherwise. + */ +static int verbose_locking = 0; +/** + * Assume lock 0 0 (create_thread, create_instance), is the log lock and + * do not print for that. Otherwise the output is full of log lock accesses. + */ +static int verbose_locking_not_loglock = 1; /** print all possible debug info on the state of the system */ static void total_debug_info(void); @@ -508,6 +519,9 @@ checklock_rdlock(enum check_lock_type type, struct checked_lock* lock, if(key_deleted) return; + if(verbose_locking && !(verbose_locking_not_loglock && + lock->create_thread == 0 && lock->create_instance == 0)) + fprintf(stderr, "checklock_rdlock lock %d %d %s:%d at %s:%d\n", lock->create_thread, lock->create_instance, lock->create_file, lock->create_line, file, line); log_assert(type == check_lock_rwlock); checklock_lockit(type, lock, func, file, line, try_rd, timed_rd, &lock->u.rwlock, 0, 0); @@ -528,6 +542,9 @@ checklock_wrlock(enum check_lock_type type, struct checked_lock* lock, if(key_deleted) return; log_assert(type == check_lock_rwlock); + if(verbose_locking && !(verbose_locking_not_loglock && + lock->create_thread == 0 && lock->create_instance == 0)) + fprintf(stderr, "checklock_wrlock lock %d %d %s:%d at %s:%d\n", lock->create_thread, lock->create_instance, lock->create_file, lock->create_line, file, line); checklock_lockit(type, lock, func, file, line, try_wr, timed_wr, &lock->u.rwlock, 0, 1); } @@ -565,6 +582,9 @@ checklock_lock(enum check_lock_type type, struct checked_lock* lock, if(key_deleted) return; log_assert(type != check_lock_rwlock); + if(verbose_locking && !(verbose_locking_not_loglock && + lock->create_thread == 0 && lock->create_instance == 0)) + fprintf(stderr, "checklock_lock lock %d %d %s:%d at %s:%d\n", lock->create_thread, lock->create_instance, lock->create_file, lock->create_line, file, line); switch(type) { case check_lock_mutex: checklock_lockit(type, lock, func, file, line, @@ -602,6 +622,10 @@ checklock_unlock(enum check_lock_type type, struct checked_lock* lock, if(lock->hold_count <= 0) lock_error(lock, func, file, line, "too many unlocks"); + if(verbose_locking && !(verbose_locking_not_loglock && + lock->create_thread == 0 && lock->create_instance == 0)) + fprintf(stderr, "checklock_unlock lock %d %d %s:%d at %s:%d\n", lock->create_thread, lock->create_instance, lock->create_file, lock->create_line, file, line); + /* store this point as last touched by */ lock->holder = thr; lock->hold_count --; diff --git a/testcode/fake_event.c b/testcode/fake_event.c index 13970c37726a..09269289dd44 100644 --- a/testcode/fake_event.c +++ b/testcode/fake_event.c @@ -52,6 +52,7 @@ #include "util/data/msgreply.h" #include "util/data/msgencode.h" #include "util/data/dname.h" +#include "util/storage/slabhash.h" #include "util/edns.h" #include "util/config_file.h" #include "services/listen_dnsport.h" @@ -65,6 +66,7 @@ #include "sldns/wire2str.h" #include "sldns/str2wire.h" #include "daemon/remote.h" +#include "daemon/daemon.h" #include "util/timeval_func.h" #include <signal.h> struct worker; @@ -154,6 +156,8 @@ repevt_string(enum replay_event_type t) case repevt_assign: return "ASSIGN"; case repevt_traffic: return "TRAFFIC"; case repevt_infra_rtt: return "INFRA_RTT"; + case repevt_flush_message: return "FLUSH_MESSAGE"; + case repevt_expire_message: return "EXPIRE_MESSAGE"; default: return "UNKNOWN"; } } @@ -691,6 +695,66 @@ do_infra_rtt(struct replay_runtime* runtime) free(dp); } +/** Flush message from message cache. */ +static void +do_flush_message(struct replay_runtime* runtime) +{ + struct replay_moment* now = runtime->now; + uint8_t rr[1024]; + size_t rr_len = sizeof(rr), dname_len = 0; + hashvalue_type h; + struct query_info k; + + if(sldns_str2wire_rr_question_buf(now->string, rr, &rr_len, + &dname_len, NULL, 0, NULL, 0) != 0) + fatal_exit("could not parse '%s'", now->string); + + log_info("remove message %s", now->string); + k.qname = rr; + k.qname_len = dname_len; + k.qtype = sldns_wirerr_get_type(rr, rr_len, dname_len); + k.qclass = sldns_wirerr_get_class(rr, rr_len, dname_len); + k.local_alias = NULL; + h = query_info_hash(&k, 0); + slabhash_remove(runtime->daemon->env->msg_cache, h, &k); +} + +/** Expire message from message cache. */ +static void +do_expire_message(struct replay_runtime* runtime) +{ + struct replay_moment* now = runtime->now; + uint8_t rr[1024]; + size_t rr_len = sizeof(rr), dname_len = 0; + hashvalue_type h; + struct query_info k; + struct lruhash_entry* e; + + if(sldns_str2wire_rr_question_buf(now->string, rr, &rr_len, + &dname_len, NULL, 0, NULL, 0) != 0) + fatal_exit("could not parse '%s'", now->string); + + log_info("expire message %s", now->string); + k.qname = rr; + k.qname_len = dname_len; + k.qtype = sldns_wirerr_get_type(rr, rr_len, dname_len); + k.qclass = sldns_wirerr_get_class(rr, rr_len, dname_len); + k.local_alias = NULL; + h = query_info_hash(&k, 0); + + e = slabhash_lookup(runtime->daemon->env->msg_cache, h, &k, 0); + if(e) { + struct msgreply_entry* msg = (struct msgreply_entry*)e->key; + struct reply_info* rep = (struct reply_info*)msg->entry.data; + time_t expired = runtime->now_secs; + expired -= 3; + rep->ttl = expired; + rep->prefetch_ttl = expired; + rep->serve_expired_ttl = expired; + lock_rw_unlock(&msg->entry.lock); + } +} + /** perform exponential backoff on the timeout */ static void expon_timeout_backoff(struct replay_runtime* runtime) @@ -796,6 +860,14 @@ do_moment_and_advance(struct replay_runtime* runtime) do_infra_rtt(runtime); advance_moment(runtime); break; + case repevt_flush_message: + do_flush_message(runtime); + advance_moment(runtime); + break; + case repevt_expire_message: + do_expire_message(runtime); + advance_moment(runtime); + break; default: fatal_exit("testbound: unknown event type %d", runtime->now->evt_type); diff --git a/testcode/replay.c b/testcode/replay.c index f896a5512c5d..95dde405f641 100644 --- a/testcode/replay.c +++ b/testcode/replay.c @@ -348,6 +348,20 @@ replay_moment_read(char* remain, FILE* in, const char* name, mom->string = strdup(m); if(!mom->string) fatal_exit("out of memory"); if(!mom->variable) fatal_exit("out of memory"); + } else if(parse_keyword(&remain, "FLUSH_MESSAGE")) { + mom->evt_type = repevt_flush_message; + while(isspace((unsigned char)*remain)) + remain++; + strip_end_white(remain); + mom->string = strdup(remain); + if(!mom->string) fatal_exit("out of memory"); + } else if(parse_keyword(&remain, "EXPIRE_MESSAGE")) { + mom->evt_type = repevt_expire_message; + while(isspace((unsigned char)*remain)) + remain++; + strip_end_white(remain); + mom->string = strdup(remain); + if(!mom->string) fatal_exit("out of memory"); } else { log_err("%d: unknown event type %s", pstate->lineno, remain); free(mom); diff --git a/testcode/replay.h b/testcode/replay.h index 0271dff0393b..809e8ee39778 100644 --- a/testcode/replay.h +++ b/testcode/replay.h @@ -85,6 +85,8 @@ * The file contents is macro expanded before match. * o CHECK_TEMPFILE [fname] - followed by FILE_BEGIN [to match] FILE_END * o INFRA_RTT [ip] [dp] [rtt] - update infra cache entry with rtt. + * o FLUSH_MESSAGE name type class - flushes entry in message cache. + * o EXPIRE_MESSAGE name type class - expires entry in message cache. * o ERROR * ; following entry starts on the next line, ENTRY_BEGIN. * ; more STEP items @@ -148,6 +150,7 @@ struct fake_timer; struct replay_var; struct infra_cache; struct sldns_buffer; +struct daemon; /** * A replay scenario. @@ -212,6 +215,10 @@ struct replay_moment { repevt_assign, /** store infra rtt cache entry: addr and string (int) */ repevt_infra_rtt, + /** flush message cache entry */ + repevt_flush_message, + /** expire message cache entry */ + repevt_expire_message, /** cause traffic to flow */ repevt_traffic } @@ -297,6 +304,8 @@ struct replay_runtime { /** ref the infra cache (was passed to outside_network_create) */ struct infra_cache* infra; + /** the daemon structure passed in worker call to remote accept open */ + struct daemon* daemon; /** the current time in seconds */ time_t now_secs; diff --git a/testcode/testbound.c b/testcode/testbound.c index ec627cc8deb1..f023860e086e 100644 --- a/testcode/testbound.c +++ b/testcode/testbound.c @@ -48,6 +48,7 @@ #include "testcode/fake_event.h" #include "daemon/remote.h" #include "libunbound/worker.h" +#include "daemon/worker.h" #include "util/config_file.h" #include "sldns/keyraw.h" #ifdef UB_ON_WINDOWS @@ -532,9 +533,10 @@ void daemon_remote_clear(struct daemon_remote* ATTR_UNUSED(rc)) } int daemon_remote_open_accept(struct daemon_remote* ATTR_UNUSED(rc), - struct listen_port* ATTR_UNUSED(ports), - struct worker* ATTR_UNUSED(worker)) + struct listen_port* ATTR_UNUSED(ports), struct worker* worker) { + struct replay_runtime* runtime = (struct replay_runtime*)worker->base; + runtime->daemon = worker->daemon; return 1; } |
