Skip to content

Commit

Permalink
Reintroduce user lookup cache
Browse files Browse the repository at this point in the history
Found by: mortmann
Patch by: thommey
Fixes: #1599
  • Loading branch information
thommey authored and michaelortmann committed Jun 13, 2024
1 parent 844439a commit 1e0cb9d
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 10 deletions.
3 changes: 2 additions & 1 deletion src/chan.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ typedef struct memstruct {
time_t split; /* in case they were just netsplit */
time_t last; /* for measuring idle time */
time_t delay; /* for delayed autoop */
int tried_getuser; // TODO: use it to invalidate user cache
struct userrec *user; /* cached user lookup */
int tried_getuser; /* negative user lookup cache */
struct memstruct *next;
} memberlist;

Expand Down
16 changes: 11 additions & 5 deletions src/chanprog.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,11 @@ struct chanset_t *findchan_by_dname(const char *name)

/* Clear the user pointers in the chanlists.
*
* Necessary when a hostmask is added/removed, a user is added or a new
* userfile is loaded.
* Necessary when:
* - a hostmask is added/removed
* - an account is added/removed
* - a user is added
* - new userfile is loaded
*/
void clear_chanlist(void)
{
Expand All @@ -128,14 +131,16 @@ void clear_chanlist(void)

for (chan = chanset; chan; chan = chan->next)
for (m = chan->channel.member; m && m->nick[0]; m = m->next) {
m->user = NULL;
m->tried_getuser = 0;
}
}

/* Clear the user pointer of a specific nick in the chanlists.
* Necessary when a hostmask is added/removed, a nick changes, etc.
* Does not completely invalidate the channel cache like clear_chanlist().
*
* Necessary when:
* - their hostmask changed (chghost)
* - their account changed
*/
void clear_chanlist_member(const char *nick)
{
Expand All @@ -145,6 +150,7 @@ void clear_chanlist_member(const char *nick)
for (chan = chanset; chan; chan = chan->next)
for (m = chan->channel.member; m && m->nick[0]; m = m->next)
if (!rfc_casecmp(m->nick, nick)) {
m->user = NULL;
m->tried_getuser = 0;
break;
}
Expand Down
6 changes: 5 additions & 1 deletion src/mod/irc.mod/chan.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@ static void setaccount(char *nick, char *account)
}
}
}
/* Username for nick could be different after account change, invalidate cache */
clear_chanlist_member(nick);
}

/* Returns the current channel mode.
Expand Down Expand Up @@ -1220,7 +1222,7 @@ static int got354(char *from, char *msg)
* :[email protected] CHGHOST tehgeo foo.io
* changes user hostmask to [email protected]
*/
static int gotchghost(char *from, char *msg){
static int gotchghost(char *from, char *msg) {
struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 };
struct userrec *u;
struct chanset_t *chan;
Expand All @@ -1247,6 +1249,8 @@ static int gotchghost(char *from, char *msg){
check_this_member(chan, m->nick, &fr);
}
}
/* Username for nick could be different after host change, invalidate cache */
clear_chanlist_member(nick);
return 0;
}

Expand Down
16 changes: 13 additions & 3 deletions src/userrec.c
Original file line number Diff line number Diff line change
Expand Up @@ -224,24 +224,34 @@ struct userrec *get_user_by_handle(struct userrec *bu, char *handle)

struct userrec *get_user_from_member(memberlist *m)
{
struct userrec *ret;
struct userrec *ret = NULL;

/* Check positive/negative cache first */
if (m->user || m->tried_getuser) {
return m->user;
}

/* Check if there is a user with a matching account if one is provided */
if (m->account[0] != '*') {
ret = get_user_by_account(m->account);
if (ret) {
return ret;
goto getuser_done;
}
}

/* Check if there is a user with a matching hostmask if one is provided */
if ((m->userhost[0] != '\0') && (m->nick[0] != '\0')) {
char s[NICKMAX+UHOSTLEN+1];
sprintf(s, "%s!%s", m->nick, m->userhost);
ret = get_user_by_host(s);
if (ret) {
return ret;
goto getuser_done;
}
}

getuser_done:
m->user = ret;
m->tried_getuser = 1;
return NULL;
}

Expand Down

0 comments on commit 1e0cb9d

Please sign in to comment.