From: Michael Poole Date: Thu, 14 Oct 2004 04:02:52 +0000 (+0000) Subject: Track in-progress LISTs by next hash bucket to send, rather than a X-Git-Url: http://git.pk910.de/?p=ircu2.10.12-pk.git;a=commitdiff_plain;h=6978c1326bbe28f7dac9ef26bfd9995c32113e51 Track in-progress LISTs by next hash bucket to send, rather than a channel, to avoid locking channels (idea borrowed from Hybrid). git-svn-id: file:///home/klmitch/undernet-ircu/undernet-ircu-svn/ircu2/trunk@1245 c9e4aea6-c8fd-4c43-8297-357d70d61c8c --- diff --git a/ChangeLog b/ChangeLog index 76b4a40..f0f5156 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,27 @@ +2004-10-13 Michael Poole + + * include/channel.h: Delete MODE_LISTED and is_listed(). Replace + ListingArgs.chptr with ListingArgs.bucket. Move declaration of + list_next_channels() to.. + + * include/hash.h: here, and drop the "nr" argument. + + * ircd/channel.c: Remove redundant scan of local clients for + channels being listed. Delete list_next_channels() function. + + * ircd/hash.c: Add list_next_channels() here, revising to not use + MODE_LISTED and to use ListingArgs.bucket instead of chptr. Also + decide when to stop sending RPL_LISTs based on a half-full sendq. + + * ircd/m_burst.c, ircd/s_misc.c: Delete mention of MODE_LISTED. + + * ircd/m_list.c: Delete mention of MODE_LISTED. Unconditionally + call list_next_channels(sptr). + + * ircd/s_bsd.c: Remove the "nr" argument to list_next_channels(). + + * ircd/Makefile.in: Update dependencies (for hash.c). + 2004-10-13 Michael Poole * ircd/ircd_parser.y: Consistently zero out global variables after diff --git a/include/channel.h b/include/channel.h index e0dc902..0895b7f 100644 --- a/include/channel.h +++ b/include/channel.h @@ -104,7 +104,6 @@ struct Client; #define MODE_LIMIT 0x0400 /**< +l Limit */ #define MODE_REGONLY 0x0800 /**< Only +r users may join */ #define MODE_DELJOINS 0x1000 /**< New join messages are delayed */ -#define MODE_LISTED 0x10000 #define MODE_SAVE 0x20000 /**< save this mode-with-arg 'til * later */ #define MODE_FREE 0x40000 /**< string needs to be passed to @@ -133,7 +132,6 @@ struct Client; (IsAnOper(v) && HasPriv(v, PRIV_LIST_CHAN))) #define PubChannel(x) ((!x) || ((x)->mode.mode & \ (MODE_PRIVATE | MODE_SECRET)) == 0) -#define is_listed(x) ((x)->mode.mode & MODE_LISTED) #define IsGlobalChannel(name) (*(name) == '#') #define IsLocalChannel(name) (*(name) == '&') @@ -287,7 +285,7 @@ struct ListingArgs { unsigned int flags; time_t max_topic_time; time_t min_topic_time; - struct Channel *chptr; + unsigned int bucket; }; struct ModeBuf { @@ -407,7 +405,6 @@ extern int IsInvited(struct Client* cptr, const void* chptr); extern void send_channel_modes(struct Client *cptr, struct Channel *chptr); extern char *pretty_mask(char *mask); extern void del_invite(struct Client *cptr, struct Channel *chptr); -extern void list_next_channels(struct Client *cptr, int nr); extern void list_set_default(void); /* this belongs elsewhere! */ extern void RevealDelayedJoin(struct Membership *member); diff --git a/include/hash.h b/include/hash.h index 67af00b..62f4770 100644 --- a/include/hash.h +++ b/include/hash.h @@ -87,5 +87,6 @@ extern int m_hash(struct Client *cptr, struct Client *sptr, int parc, char *parv extern int isNickJuped(const char *nick); extern int addNickJupes(const char *nicks); extern void clearNickJupes(void); +extern void list_next_channels(struct Client *cptr); #endif /* INCLUDED_hash_h */ diff --git a/ircd/Makefile.in b/ircd/Makefile.in index 34c51bd..fc30d23 100644 --- a/ircd/Makefile.in +++ b/ircd/Makefile.in @@ -361,10 +361,10 @@ depend: ${DEP_SRC} chattr.tab.c IPcheck.o: IPcheck.c ../config.h ../include/IPcheck.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/ircd.h ../include/struct.h ../include/msg.h \ - ../include/numnicks.h ../include/ircd_alloc.h \ + ../include/ircd.h ../include/struct.h ../include/match.h \ + ../include/msg.h ../include/numnicks.h ../include/ircd_alloc.h \ ../include/ircd_features.h ../include/s_debug.h ../include/s_user.h \ - ../include/send.h ../include/match.h + ../include/send.h channel.o: channel.c ../config.h ../include/channel.h \ ../include/ircd_defs.h ../include/client.h ../include/dbuf.h \ ../include/msgq.h ../include/ircd_events.h ../include/ircd_handler.h \ @@ -421,9 +421,10 @@ gline.o: gline.c ../config.h ../include/gline.h ../include/res.h \ hash.o: hash.c ../config.h ../include/hash.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/channel.h ../include/ircd_chattr.h ../include/ircd_string.h \ - ../include/ircd.h ../include/struct.h ../include/msg.h \ - ../include/send.h ../include/sys.h + ../include/channel.h ../include/ircd_alloc.h ../include/ircd_chattr.h \ + ../include/ircd_reply.h ../include/ircd_string.h ../include/ircd.h \ + ../include/struct.h ../include/msg.h ../include/numeric.h \ + ../include/random.h ../include/send.h ../include/sys.h ircd.o: ircd.c ../config.h ../include/ircd.h ../include/struct.h \ ../include/ircd_defs.h ../include/IPcheck.h ../include/class.h \ ../include/client.h ../include/dbuf.h ../include/msgq.h \ @@ -1155,7 +1156,8 @@ querycmds.o: querycmds.c ../config.h ../include/querycmds.h \ random.o: random.c ../config.h ../include/random.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/ircd_log.h ../include/ircd_reply.h ../include/send.h + ../include/ircd_log.h ../include/ircd_md5.h ../include/ircd_reply.h \ + ../include/send.h s_auth.o: s_auth.c ../config.h ../include/s_auth.h \ ../include/ircd_events.h ../include/client.h ../include/ircd_defs.h \ ../include/dbuf.h ../include/msgq.h ../include/ircd_handler.h \ diff --git a/ircd/channel.c b/ircd/channel.c index c5f01b4..01813ca 100644 --- a/ircd/channel.c +++ b/ircd/channel.c @@ -291,21 +291,6 @@ int destruct_channel(struct Channel* chptr) assert(0 == chptr->members); - /* Channel became (or was) empty: Remove channel */ - if (is_listed(chptr)) - { - int i; - for (i = 0; i <= HighestFd; i++) - { - struct Client *acptr = 0; - if ((acptr = LocalClientArray[i]) && cli_listing(acptr) && - (cli_listing(acptr))->chptr == chptr) - { - list_next_channels(acptr, 1); - break; /* Only one client can list a channel */ - } - } - } /* * Now, find all invite links from channel structure */ @@ -1577,58 +1562,6 @@ void del_invite(struct Client *cptr, struct Channel *chptr) } } -/** List a set of channels - * Lists a series of channels that match a filter, skipping channels that - * have been listed before. - * - * @param cptr Client to send the list to. - * @param nr Number of channels to send this update. - */ -void list_next_channels(struct Client *cptr, int nr) -{ - struct ListingArgs *args = cli_listing(cptr); - struct Channel *chptr = args->chptr; - chptr->mode.mode &= ~MODE_LISTED; - while (is_listed(chptr) || --nr >= 0) - { - for (; chptr; chptr = chptr->next) - { - if (!cli_user(cptr)) - continue; - if (!(HasPriv(cptr, PRIV_LIST_CHAN) && IsAnOper(cptr)) && - SecretChannel(chptr) && !find_channel_member(cptr, chptr)) - continue; - if (chptr->users > args->min_users && chptr->users < args->max_users && - chptr->creationtime > args->min_time && - chptr->creationtime < args->max_time && - (!(args->flags & LISTARG_TOPICLIMITS) || (*chptr->topic && - chptr->topic_time > args->min_topic_time && - chptr->topic_time < args->max_topic_time))) - { - if ((args->flags & LISTARG_SHOWSECRET) || ShowChannel(cptr,chptr)) - send_reply(cptr, RPL_LIST, chptr->chname, chptr->users, - chptr->topic); - chptr = chptr->next; - break; - } - } - if (!chptr) - { - MyFree(cli_listing(cptr)); - cli_listing(cptr) = NULL; - send_reply(cptr, RPL_LISTEND); - break; - } - } - if (chptr) - { - (cli_listing(cptr))->chptr = chptr; - chptr->mode.mode |= MODE_LISTED; - } - - update_write(cptr); -} - /** @page zombie Explaination of Zombies * * Consider: diff --git a/ircd/hash.c b/ircd/hash.c index 03a54ad..aaf017b 100644 --- a/ircd/hash.c +++ b/ircd/hash.c @@ -24,10 +24,13 @@ #include "hash.h" #include "client.h" #include "channel.h" +#include "ircd_alloc.h" #include "ircd_chattr.h" +#include "ircd_reply.h" #include "ircd_string.h" #include "ircd.h" #include "msg.h" +#include "numeric.h" #include "random.h" #include "send.h" #include "struct.h" @@ -403,3 +406,46 @@ void clearNickJupes(void) for (i = 0; i < JUPEHASHSIZE; i++) jupeTable[i][0] = '\000'; } + +/** Send more channels to a client in mid-LIST. + * @param[in] cptr Client to send the list to. + */ +void list_next_channels(struct Client *cptr) +{ + struct ListingArgs *args; + struct Channel *chptr; + + /* Walk consecutive buckets until we hit the end. */ + for (args = cli_listing(cptr); args->bucket < HASHSIZE; args->bucket++) + { + /* Send all the matching channels in the bucket. */ + for (chptr = channelTable[args->bucket]; chptr; chptr = chptr->hnext) + { + if (chptr->users > args->min_users + && chptr->users < args->max_users + && chptr->creationtime > args->min_time + && chptr->creationtime < args->max_time + && (!(args->flags & LISTARG_TOPICLIMITS) + || (chptr->topic[0] + && chptr->topic_time > args->min_topic_time + && chptr->topic_time < args->max_topic_time)) + && ((args->flags & LISTARG_SHOWSECRET) + || ShowChannel(cptr, chptr))) + { + send_reply(cptr, RPL_LIST, chptr->chname, chptr->users, chptr->topic); + } + } + /* If, at the end of the bucket, client sendq is more than half + * full, stop. */ + if (MsgQLength(&cli_sendQ(cptr)) > cli_max_sendq(cptr) / 2) + break; + } + + /* If we did all buckets, clean the client and send RPL_LISTEND. */ + if (args->bucket >= HASHSIZE) + { + MyFree(cli_listing(cptr)); + cli_listing(cptr) = NULL; + send_reply(cptr, RPL_LISTEND); + } +} diff --git a/ircd/m_burst.c b/ircd/m_burst.c index 9e44eca..f7e31da 100644 --- a/ircd/m_burst.c +++ b/ircd/m_burst.c @@ -274,7 +274,7 @@ int ms_burst(struct Client *cptr, struct Client *sptr, int parc, char *parv[]) modebuf_init(mbuf = &modebuf, &me, cptr, chptr, MODEBUF_DEST_CHANNEL | MODEBUF_DEST_NOKEY); modebuf_mode(mbuf, MODE_DEL | chptr->mode.mode); /* wipeout modes */ - chptr->mode.mode &= MODE_LISTED | MODE_BURSTADDED | MODE_WASDELJOINS; + chptr->mode.mode &= MODE_BURSTADDED | MODE_WASDELJOINS; parse_flags |= (MODE_PARSE_SET | MODE_PARSE_WIPEOUT); /* wipeout keys */ diff --git a/ircd/m_list.c b/ircd/m_list.c index 09ab422..9c96a11 100644 --- a/ircd/m_list.c +++ b/ircd/m_list.c @@ -291,7 +291,6 @@ int m_list(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) if (cli_listing(sptr)) /* Already listing ? */ { - cli_listing(sptr)->chptr->mode.mode &= ~MODE_LISTED; MyFree(cli_listing(sptr)); cli_listing(sptr) = 0; send_reply(sptr, RPL_LISTEND); @@ -331,14 +330,8 @@ int m_list(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) cli_listing(sptr) = (struct ListingArgs*) MyMalloc(sizeof(struct ListingArgs)); assert(0 != cli_listing(sptr)); memcpy(cli_listing(sptr), &args, sizeof(struct ListingArgs)); - if ((cli_listing(sptr)->chptr = GlobalChannelList)) { - int m = GlobalChannelList->mode.mode & MODE_LISTED; - list_next_channels(sptr, 64); - GlobalChannelList->mode.mode |= m; - return 0; - } - MyFree(cli_listing(sptr)); - cli_listing(sptr) = 0; + list_next_channels(sptr); + return 0; } send_reply(sptr, RPL_LISTEND); return 0; diff --git a/ircd/s_bsd.c b/ircd/s_bsd.c index d493d9a..28e078a 100644 --- a/ircd/s_bsd.c +++ b/ircd/s_bsd.c @@ -940,7 +940,7 @@ static void client_sock_callback(struct Event* ev) case ET_WRITE: /* socket is writable */ ClrFlag(cptr, FLAG_BLOCKED); if (cli_listing(cptr) && MsgQLength(&(cli_sendQ(cptr))) < 2048) - list_next_channels(cptr, 64); + list_next_channels(cptr); Debug((DEBUG_SEND, "Sending queued data to %C", cptr)); send_queued(cptr); break; diff --git a/ircd/s_misc.c b/ircd/s_misc.c index 82855b0..631cf6b 100644 --- a/ircd/s_misc.c +++ b/ircd/s_misc.c @@ -215,7 +215,6 @@ static void exit_one_client(struct Client* bcptr, const char* comment) * Stop a running /LIST clean */ if (MyUser(bcptr) && cli_listing(bcptr)) { - cli_listing(bcptr)->chptr->mode.mode &= ~MODE_LISTED; MyFree(cli_listing(bcptr)); cli_listing(bcptr) = NULL; }