From f8b7f4d7efd295167fc0ef79017f772049739c2b Mon Sep 17 00:00:00 2001 From: Wilfried Goesgens Date: Mon, 23 Jan 2012 00:26:07 +0100 Subject: [PATCH] speedup Networker scheduling - iterate the netconfigs dir first to find out which rooms we realy care about - store roomnames case insensitive - store length - calculate the key of roomnames, so that while sorting out dupes its cheaper - minimize the locking of the roomlist by just swapping out the pointers while we process one list. --- citadel/citserver.h | 5 + citadel/modules/network/netspool.h | 2 +- citadel/modules/network/serv_netspool.c | 8 +- citadel/modules/network/serv_network.c | 156 +++++++++++++++++++----- citadel/modules/network/serv_network.h | 2 +- 5 files changed, 138 insertions(+), 35 deletions(-) diff --git a/citadel/citserver.h b/citadel/citserver.h index 1235a81d8..b89e4e0f8 100644 --- a/citadel/citserver.h +++ b/citadel/citserver.h @@ -14,9 +14,14 @@ #include "context.h" /* Simple linked list structures ... used in a bunch of different places. */ +typedef struct RoomProcList RoomProcList; struct RoomProcList { struct RoomProcList *next; char name[ROOMNAMELEN]; + char lcname[ROOMNAMELEN]; + long namelen; + long key; + long QRNum; }; struct UserProcList { struct UserProcList *next; diff --git a/citadel/modules/network/netspool.h b/citadel/modules/network/netspool.h index 7e26e28af..0c0364ce3 100644 --- a/citadel/modules/network/netspool.h +++ b/citadel/modules/network/netspool.h @@ -24,7 +24,7 @@ struct SpoolControl { }; -void network_spoolout_room(char *room_to_spool, +void network_spoolout_room(RoomProcList *room_to_spool, char *working_ignetcfg, NetMap *the_netmap); void network_do_spoolin(char *working_ignetcfg, NetMap **the_netmap, int *netmap_changed); diff --git a/citadel/modules/network/serv_netspool.c b/citadel/modules/network/serv_netspool.c index fbd0eb0e5..06fa3a82f 100644 --- a/citadel/modules/network/serv_netspool.c +++ b/citadel/modules/network/serv_netspool.c @@ -380,7 +380,7 @@ int is_recipient(SpoolControl *sc, const char *Name) /* * Batch up and send all outbound traffic from the current room */ -void network_spoolout_room(char *room_to_spool, +void network_spoolout_room(RoomProcList *room_to_spool, char *working_ignetcfg, NetMap *the_netmap) { @@ -394,8 +394,8 @@ void network_spoolout_room(char *room_to_spool, * Normally this should never happen, but once in a while maybe a room gets * queued for networking and then deleted before it can happen. */ - if (CtdlGetRoom(&CC->room, room_to_spool) != 0) { - syslog(LOG_CRIT, "ERROR: cannot load <%s>\n", room_to_spool); + if (CtdlGetRoom(&CC->room, room_to_spool->name) != 0) { + syslog(LOG_CRIT, "ERROR: cannot load <%s>\n", room_to_spool->name); return; } @@ -893,7 +893,7 @@ CTDL_MODULE_INIT(network_spool) if (!threading) { create_spool_dirs(); - CtdlRegisterCleanupHook(destroy_network_queue_room); +//////todo CtdlRegisterCleanupHook(destroy_network_queue_room); } return "network_spool"; } diff --git a/citadel/modules/network/serv_network.c b/citadel/modules/network/serv_network.c index 7062a15f5..234a7722f 100644 --- a/citadel/modules/network/serv_network.c +++ b/citadel/modules/network/serv_network.c @@ -92,8 +92,13 @@ #include "netmail.h" #include "ctdl_module.h" +/* comes from lookup3.c from libcitadel... */ +extern uint32_t hashlittle( const void *key, size_t length, uint32_t initval); - +typedef struct __roomlists { + RoomProcList *rplist; + HashList *RoomsInterestedIn; +}roomlists; /* * When we do network processing, it's accomplished in two passes; one to * gather a list of rooms and one to actually do them. It's ok that rplist @@ -101,7 +106,37 @@ */ struct RoomProcList *rplist = NULL; +int GetNetworkedRoomNumbers(const char *DirName, HashList *DirList) +{ + DIR *filedir = NULL; + struct dirent *d; + struct dirent *filedir_entry; + long RoomNR; + long Count; + + filedir = opendir (DirName); + if (filedir == NULL) { + return 0; + } + + d = (struct dirent *)malloc(offsetof(struct dirent, d_name) + PATH_MAX + 1); + if (d == NULL) { + return 0; + } + while ((readdir_r(filedir, d, &filedir_entry) == 0) && + (filedir_entry != NULL)) + { + RoomNR = atol(filedir_entry->d_name); + if (RoomNR != 0) { + Count++; + Put(DirList, LKEY(RoomNR), &Count, reference_free_handler); + } + } + free(d); + closedir(filedir); + return Count; +} @@ -250,39 +285,89 @@ void cmd_nsyn(char *argbuf) { +/* + * Batch up and send all outbound traffic from the current room + */ +void network_queue_interesting_rooms(struct ctdlroom *qrbuf, void *data) { + int i; + struct RoomProcList *ptr; + long QRNum = qrbuf->QRnumber; + void *v; + roomlists *RP = (roomlists*) data; + + if (!GetHash(RP->RoomsInterestedIn, LKEY(QRNum), &v)) + return; + + ptr = (struct RoomProcList *) malloc(sizeof (struct RoomProcList)); + if (ptr == NULL) return; + + ptr->namelen = strlen(qrbuf->QRname); + if (ptr->namelen > ROOMNAMELEN) + ptr->namelen = ROOMNAMELEN - 1; + + memcpy (ptr->name, qrbuf->QRname, ptr->namelen); + ptr->name[ptr->namelen] = 0; + ptr->QRNum = qrbuf->QRnumber; + + for (i = 0; i < ptr->namelen; i++) + { + ptr->lcname[i] = tolower(ptr->name[i]); + } + + ptr->key = hashlittle(ptr->lcname, ptr->namelen, 9872345); + ptr->next = RP->rplist; + RP->rplist = ptr; +} + /* * Batch up and send all outbound traffic from the current room */ void network_queue_room(struct ctdlroom *qrbuf, void *data) { + int i; struct RoomProcList *ptr; ptr = (struct RoomProcList *) malloc(sizeof (struct RoomProcList)); if (ptr == NULL) return; - safestrncpy(ptr->name, qrbuf->QRname, sizeof ptr->name); + ptr->namelen = strlen(qrbuf->QRname); + if (ptr->namelen > ROOMNAMELEN) + ptr->namelen = ROOMNAMELEN - 1; + + memcpy (ptr->name, qrbuf->QRname, ptr->namelen); + ptr->name[ptr->namelen] = 0; + ptr->QRNum = qrbuf->QRnumber; + + for (i = 0; i < ptr->namelen; i++) + { + ptr->lcname[i] = tolower(ptr->name[i]); + } + + ptr->key = hashlittle(ptr->lcname, ptr->namelen, 9872345); begin_critical_section(S_RPLIST); ptr->next = rplist; rplist = ptr; end_critical_section(S_RPLIST); } -void destroy_network_queue_room(void) +void destroy_network_queue_room(RoomProcList *rplist) { struct RoomProcList *cur, *p; cur = rplist; - begin_critical_section(S_RPLIST); while (cur != NULL) { p = cur->next; free (cur); cur = p; } - rplist = NULL; - end_critical_section(S_RPLIST); } - +void destroy_network_queue_room_locked (void) +{ + begin_critical_section(S_RPLIST); + destroy_network_queue_room(rplist); + end_critical_section(S_RPLIST); +} @@ -405,11 +490,11 @@ void network_bounce(struct CtdlMessage *msg, char *reason) { void network_do_queue(void) { static int doing_queue = 0; static time_t last_run = 0L; - struct RoomProcList *ptr; int full_processing = 1; char *working_ignetcfg; NetMap *the_netmap = NULL; int netmap_changed = 0; + roomlists RL; /* * Run the full set of processing tasks no more frequently @@ -433,6 +518,19 @@ void network_do_queue(void) { } doing_queue = 1; + begin_critical_section(S_RPLIST); + RL.rplist = rplist; + rplist = NULL; + end_critical_section(S_RPLIST); + + RL.RoomsInterestedIn = NewHash(1, lFlathash); + if (!GetNetworkedRoomNumbers(ctdl_netcfg_dir, RL.RoomsInterestedIn)) + { + doing_queue = 0; + DeleteHash(&RL.RoomsInterestedIn); + if (RL.rplist == NULL) + return; + } /* Load the IGnet Configuration into memory */ working_ignetcfg = load_working_ignetcfg(); @@ -447,34 +545,34 @@ void network_do_queue(void) { */ if (full_processing && !server_shutting_down) { syslog(LOG_DEBUG, "network: loading outbound queue\n"); - CtdlForEachRoom(network_queue_room, NULL); + CtdlForEachRoom(network_queue_interesting_rooms, &RL); } - if (rplist != NULL) { + if (RL.rplist != NULL) { + RoomProcList *ptr, *cmp; + ptr = RL.rplist; syslog(LOG_DEBUG, "network: running outbound queue\n"); - while (rplist != NULL && !server_shutting_down) { - char spoolroomname[ROOMNAMELEN]; - safestrncpy(spoolroomname, rplist->name, sizeof spoolroomname); - begin_critical_section(S_RPLIST); - - /* pop this record off the list */ - ptr = rplist; - rplist = rplist->next; - free(ptr); - - /* invalidate any duplicate entries to prevent double processing */ - for (ptr=rplist; ptr!=NULL; ptr=ptr->next) { - if (!strcasecmp(ptr->name, spoolroomname)) { - ptr->name[0] = 0; + while (ptr != NULL && !server_shutting_down) { + + cmp = ptr->next; + + while (cmp != NULL) { + if ((cmp->namelen > 0) && + (cmp->key == ptr->key) && + (cmp->namelen == ptr->namelen) && + (strcmp(cmp->lcname, ptr->lcname) == 0)) + { + cmp->namelen = 0; } + cmp = cmp->next; } - end_critical_section(S_RPLIST); - if (spoolroomname[0] != 0) { - network_spoolout_room(spoolroomname, + if (ptr->namelen > 0) { + network_spoolout_room(ptr, working_ignetcfg, the_netmap); } + ptr = ptr->next; } } @@ -499,7 +597,7 @@ void network_do_queue(void) { if (full_processing) { last_run = time(NULL); } - + destroy_network_queue_room(RL.rplist); doing_queue = 0; } @@ -522,7 +620,7 @@ CTDL_MODULE_INIT(network) { CtdlRegisterProtoHook(cmd_nsyn, "NSYN", "Synchronize room to node"); CtdlRegisterRoomHook(network_room_handler); - CtdlRegisterCleanupHook(destroy_network_queue_room); + CtdlRegisterCleanupHook(destroy_network_queue_room_locked); CtdlRegisterSessionHook(network_do_queue, EVT_TIMER); } return "network"; diff --git a/citadel/modules/network/serv_network.h b/citadel/modules/network/serv_network.h index a855ca462..549959079 100644 --- a/citadel/modules/network/serv_network.h +++ b/citadel/modules/network/serv_network.h @@ -13,7 +13,7 @@ void load_network_filter_list(void); void network_queue_room(struct ctdlroom *, void *); -void destroy_network_queue_room(void); +////void destroy_network_queue_room(void); void network_bounce(struct CtdlMessage *msg, char *reason); int network_usetable(struct CtdlMessage *msg); -- 2.30.2