# HG changeset patch # User Sebastien Decugis # Date 1368516448 -28800 # Node ID ccbd1426e04a57243bb1bb5384d6a9444bfad8e1 # Parent c473581adff20ca9ba116d6f1b03b127a31ad6ff Improve testmesg_stress to measure impact of loaded dictionary diff -r c473581adff2 -r ccbd1426e04a extensions/dbg_msg_timings/dbg_msg_timings.c --- a/extensions/dbg_msg_timings/dbg_msg_timings.c Tue May 14 12:32:28 2013 +0800 +++ b/extensions/dbg_msg_timings/dbg_msg_timings.c Tue May 14 15:27:28 2013 +0800 @@ -77,22 +77,21 @@ ASSERT(qpmd->sent_on.tv_sec); /* same, would mean the HOOK_MESSAGE_SENT hook was not trigged */ TS_DIFFERENCE( &delay, &qpmd->sent_on, &pmd->received_on ); CHECK_MALLOC_DO( fd_msg_dump_summary(&buf, &len, NULL, msg, NULL, 0, 1), return ); - LOG_N("[TIMING] RCV ANS %ld.%06ld sec: %s", (long)delay.tv_sec, delay.tv_nsec / 1000, buf); + LOG_N("[TIMING] RCV ANS %ld.%06ld sec <-'%s': %s", (long)delay.tv_sec, delay.tv_nsec / 1000, peer ? peer->info.pi_diamid : "", buf); } } else if (type == HOOK_MESSAGE_SENT) { DiamId_t source = NULL; - size_t slen = 0; (void)clock_gettime(CLOCK_REALTIME, &pmd->sent_on); /* Is this a forwarded message ? */ - CHECK_FCT_DO( fd_msg_source_get(msg, &source, &slen), return ); + CHECK_FCT_DO( fd_msg_source_get(msg, &source, NULL), return ); if (source) { struct timespec delay; ASSERT(pmd->received_on.tv_sec); TS_DIFFERENCE( &delay, &pmd->received_on, &pmd->sent_on ); CHECK_MALLOC_DO( fd_msg_dump_summary(&buf, &len, NULL, msg, NULL, 0, 1), return ); - LOG_N("[TIMING] FWD %ld.%06ld sec: %s", (long)delay.tv_sec, delay.tv_nsec / 1000, buf); + LOG_N("[TIMING] FWD %ld.%06ld sec '%s'->'%s': %s", (long)delay.tv_sec, delay.tv_nsec / 1000, source, peer ? peer->info.pi_diamid : "", buf); } else if (hdr->msg_flags & CMD_FLAG_REQUEST) { /* We are sending a request issued locally, nothing special to log */ } else { @@ -102,7 +101,7 @@ struct timespec delay; TS_DIFFERENCE( &delay, &qpmd->received_on, &pmd->sent_on ); CHECK_MALLOC_DO( fd_msg_dump_summary(&buf, &len, NULL, msg, NULL, 0, 1), return ); - LOG_N("[TIMING] ANS %ld.%06ld sec: %s", (long)delay.tv_sec, delay.tv_nsec / 1000, buf); + LOG_N("[TIMING] ANS %ld.%06ld sec ->'%s': %s", (long)delay.tv_sec, delay.tv_nsec / 1000, peer ? peer->info.pi_diamid : "", buf); } } } diff -r c473581adff2 -r ccbd1426e04a extensions/dict_mip6a/dict_mip6a.c --- a/extensions/dict_mip6a/dict_mip6a.c Tue May 14 12:32:28 2013 +0800 +++ b/extensions/dict_mip6a/dict_mip6a.c Tue May 14 15:27:28 2013 +0800 @@ -404,7 +404,7 @@ */ struct dict_object * type; struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "Enumerated(MIP-Algorithm-Type)", NULL, NULL, NULL }; - struct dict_enumval_data t_2 = { "HMAC-SHA-1", { .i32 = 2 }}; + struct dict_enumval_data t_2 = { "HMAC-SHA-1 [HMAC]", { .i32 = 2 }}; struct dict_avp_data data = { 345, /* Code */ 0, /* Vendor */ diff -r c473581adff2 -r ccbd1426e04a libfdproto/dictionary.c --- a/libfdproto/dictionary.c Tue May 14 12:32:28 2013 +0800 +++ b/libfdproto/dictionary.c Tue May 14 15:27:28 2013 +0800 @@ -1908,13 +1908,19 @@ all_errors: if (ret != 0) { char * buf = NULL; - size_t len = 0; + size_t len = 0, offset=0; - CHECK_MALLOC( dict_obj_info[CHECK_TYPE(type) ? type : 0].dump_data(&buf, &len, NULL, data) ); + if (type == DICT_ENUMVAL) { + CHECK_MALLOC( dump_enumval_data ( &buf, &len, &offset, data, parent->data.type.type_base )); + } else { + CHECK_MALLOC( dict_obj_info[CHECK_TYPE(type) ? type : 0].dump_data(&buf, &len, &offset, data) ); + } + TRACE_DEBUG(INFO, "An error occurred while adding the following data in the dictionary: %s", buf); if (ret == EEXIST) { - CHECK_MALLOC( dump_object(&buf, &len, NULL, locref, 0, 0, 0) ); + offset=0; + CHECK_MALLOC( dump_object(&buf, &len, &offset, locref, 0, 0, 0) ); TRACE_DEBUG(INFO, "Conflicting entry in the dictionary: %s", buf); } free(buf); diff -r c473581adff2 -r ccbd1426e04a libfdproto/messages.c --- a/libfdproto/messages.c Tue May 14 12:32:28 2013 +0800 +++ b/libfdproto/messages.c Tue May 14 15:27:28 2013 +0800 @@ -884,7 +884,6 @@ CHECK_FCT_DO( fd_msg_browse ( avp, MSG_BRW_FIRST_CHILD, &inavp, NULL ), inavp = NULL ); while (inavp) { struct avp * nextavp = NULL; - CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n"), return NULL); CHECK_FCT_DO( fd_msg_browse ( inavp, MSG_BRW_NEXT, &nextavp, NULL ), inavp = NULL ); CHECK_MALLOC_DO( avp_format_treeview(FD_DUMP_STD_PARAMS, inavp, level + 1, first, nextavp ? 0 : 1), return NULL); inavp = nextavp; diff -r c473581adff2 -r ccbd1426e04a tests/testmesg_stress.c --- a/tests/testmesg_stress.c Tue May 14 12:32:28 2013 +0800 +++ b/tests/testmesg_stress.c Tue May 14 15:27:28 2013 +0800 @@ -34,6 +34,14 @@ *********************************************************************************************************/ #include "tests.h" +#include +#include +#include + +#ifndef BUILD_DIR +#error "Missing BUILD_DIR information" +#endif /* BUILD_DIR */ + /* The number of times each operation is repeated to measure the average operation time */ #define DEFAULT_NUMBER_OF_SAMPLES 100000 @@ -46,7 +54,138 @@ printf("%-19s: %d %-8s %-7s in %.6LFs (%.1LFmsg/s)\n", fct, nr, type, op, dur, thrp); } +struct ext_info { + struct fd_list chain; /* link in the list */ + void *handler; /* object returned by dlopen() */ + int (*init_cb)(int, int, char *); + char *ext_name; /* points to the extension name, either inside depends, or basename(filename) */ + int free_ext_name; /* must be freed if it was malloc'd */ + const char **depends; /* names of the other extensions this one depends on (if provided) */ +}; + +static void load_all_extensions(char * prefix) +{ + DIR *dir; + struct dirent *dp; + char fullname[512]; + int pathlen; + struct fd_list all_extensions = FD_LIST_INITIALIZER(all_extensions); + struct fd_list ext_with_depends = FD_LIST_INITIALIZER(ext_with_depends); + /* Find all extensions which have been compiled along the test */ + LOG_D("Loading %s*.fdx from: '%s'", BUILD_DIR "/extensions", prefix ?: ""); + CHECK( 0, (dir = opendir (BUILD_DIR "/extensions")) == NULL ? 1 : 0 ); + pathlen = snprintf(fullname, sizeof(fullname), BUILD_DIR "/extensions/"); + + while ((dp = readdir (dir)) != NULL) { + char * dot = strrchr(dp->d_name, '.'); + if (dot && ((!prefix) || !(strncmp(dp->d_name, prefix, strlen(prefix)))) && (!(strcmp(dot, ".fdx")))) { + /* We found a file with name dict_*.fdx, attempt to load it */ + struct ext_info * new = malloc(sizeof(struct ext_info)); + CHECK( 1, new ? 1:0); + fd_list_init(&new->chain, new); + + snprintf(fullname + pathlen, sizeof(fullname) - pathlen, "%s", dp->d_name); + + LOG_D("Extension: '%s'", dp->d_name); + + /* load */ + new->handler = dlopen(fullname, RTLD_NOW | RTLD_GLOBAL); + if (!new->handler) { + TRACE_DEBUG(INFO, "Unable to load '%s': %s.", fullname, dlerror()); + } + CHECK( 0, new->handler == NULL ? 1 : 0 ); + + /* resolve entry */ + new->init_cb = dlsym( new->handler, "fd_ext_init" ); + if (!new->init_cb) { + TRACE_DEBUG(INFO, "No 'fd_ext_init' entry point in '%s': %s.", fullname, dlerror()); + } + CHECK( 0, new->init_cb == NULL ? 1 : 0 ); + + new->depends = dlsym( new->handler, "fd_ext_depends" ); + if (new->depends) { + new->ext_name = (char *)new->depends[0]; + new->free_ext_name = 0; + if ( new->depends[1] ) { + fd_list_insert_before(&ext_with_depends, &new->chain); + } else { + fd_list_insert_before(&all_extensions, &new->chain); + } + } else { + new->ext_name = strdup(basename(dp->d_name)); + new->free_ext_name = 1; + fd_list_insert_before(&all_extensions, &new->chain); + } + + } + } + + /* Now, reorder the list by dependencies */ + { + int count, prevcount = 0; + struct fd_list * li; + do { + count = 0; + for (li=ext_with_depends.next; li != &ext_with_depends; li=li->next) { + struct ext_info * e = li->o; + int d; + int satisfied=0; + + /* Can we satisfy all dependencies? */ + for (d=1; ;d++) { + struct fd_list * eli; + if (!e->depends[d]) { + satisfied = 1; + break; + } + + /* can we find this dependency in the list? */ + for (eli=all_extensions.next; eli != &all_extensions; eli = eli->next) { + struct ext_info * de = eli->o; + if (!strcasecmp(de->ext_name, e->depends[d])) + break; /* this dependency is satisfied */ + } + + if (eli == &all_extensions) { + satisfied = 0; + break; + } + } + + if (satisfied) { + /* OK, we have all our dependencies in the list */ + li=li->prev; + fd_list_unlink(&e->chain); + fd_list_insert_before(&all_extensions, &e->chain); + } else { + count++; + } + } + + if (prevcount && (prevcount == count)) { + LOG_E("Some extensions cannot have their dependencies satisfied, e.g.: %s", ((struct ext_info *)ext_with_depends.next->o)->ext_name); + CHECK(0, 1); + } + prevcount = count; + + if (FD_IS_LIST_EMPTY(&ext_with_depends)) + break; + } while (1); + } + + /* Now, load all the extensions */ + { + struct fd_list * li; + for (li=all_extensions.next; li != &all_extensions; li=li->next) { + struct ext_info * e = li->o; + int ret = (*e->init_cb)( FD_PROJECT_VERSION_MAJOR, FD_PROJECT_VERSION_MINOR, NULL ); + LOG_N("Initializing extension '%s': %s", e->ext_name, ret ? strerror(ret) : "Success"); + } + } + + /* We should probably clean the list here ? */ +} /* Main test routine */ int main(int argc, char *argv[]) @@ -54,10 +193,16 @@ struct msg * acr = NULL; unsigned char * buf = NULL; + int dictionaries_loaded = 0; + test_parameter = DEFAULT_NUMBER_OF_SAMPLES; /* First, initialize the daemon modules */ INIT_FD(); + CHECK( 0, fd_queues_init() ); + CHECK( 0, fd_msg_init() ); + CHECK( 0, fd_rtdisp_init() ); + { struct dict_object * acr_model = NULL; @@ -378,7 +523,7 @@ } /* We have our "buf" now, length is 344 -- cf. testmesg.c. */ - +redo: /* Test the throughput of the different functions function */ { struct stress_struct { @@ -530,7 +675,13 @@ } free(stress_array); } - + + if (!dictionaries_loaded) { + load_all_extensions("dict_"); + dictionaries_loaded = 1; + printf("Loaded all dictionary extensions, restarting...\n"); + goto redo; + } /* That's all for the tests yet */ PASSTEST();