From 9321a253e348609094142de768a07c9f9f0b6ba3 Mon Sep 17 00:00:00 2001 From: Michael Poole Date: Fri, 17 Jun 2005 03:55:13 +0000 Subject: [PATCH] Make struct Ban monolithic and improve memory statistics counting. git-svn-id: file:///home/klmitch/undernet-ircu/undernet-ircu-svn/ircu2/trunk@1427 c9e4aea6-c8fd-4c43-8297-357d70d61c8c --- ChangeLog | 44 ++++++++++++++++ include/channel.h | 14 ++--- ircd/channel.c | 74 +++++++++++++------------- ircd/list.c | 128 ++++++++++++++++++++------------------------- ircd/m_burst.c | 9 ++-- ircd/m_clearmode.c | 6 +-- ircd/s_stats.c | 7 ++- 7 files changed, 155 insertions(+), 127 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4201d70..69692d2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,47 @@ +2005-05-16 Michael Poole + + * include/channel.h (struct Ban): Make 'who' and 'banstr' direct + arrays, rather than pointers. + + * ircd/channel.c (bans_alloc): New variable to count number of ban + structures allocated. + (bans_inuse): New variable to count number of ban structures + currently in use. + (set_banmask): Adapt to changes in struct Ban. + (make_ban): Likewise, and update ban counts. + (free_ban): Likewise. + (bans_send_meminfo): New function. + (apply_ban): Adapt to changes in struct Ban. + (mode_parse_ban): Likewise. + (mode_process_bans): Likewise. + (mode_parse): Likewise. + (RevealDelayedJoin): Fix brace placement. + (CheckDelayedJoins): Fix brace placement and whitespace. + + * ircd/list.c (struct liststats): Add new fields to eliminate the + separate count variables. + (init_list): Adapt to those changes. + (alloc_client): Likewise. + (dealloc_client): Likewise. + (alloc_connection): Likewise. + (dealloc_connection): Likewise. + (make_server): Likewise. + (remove_client_from_list): Likewise. + (verify_client_list): Likewise. + (make_link): Likewise. + (free_link): Likewise. + (send_liststats): New function. + (send_listinfo): Rewrite to use new struct liststats layout. + + * ircd/m_burst.c (ms_burst): Adapt to changes in struct Ban. + + * ircd/m_clearmode.c (do_clearmode): Adapt to changes in struct + Ban. + + * ircd/s_stats.c (stats_meminfo): Define unconditionally and call + bans_send_meminfo(). + (statsinfo): Always give access to stats_meminfo. + 2005-06-16 Michael Poole * include/ircd_string.h: Include necessary header. diff --git a/include/channel.h b/include/channel.h index db34797..210c4df 100644 --- a/include/channel.h +++ b/include/channel.h @@ -261,14 +261,14 @@ struct Mode { /** A single ban for a channel. */ struct Ban { - struct Ban* next; /**< next ban in the channel */ + struct Ban* next; /**< next ban in the channel */ struct irc_in_addr address; /**< addres for BAN_IPMASK bans */ - time_t when; /**< timestamp when ban was added */ - unsigned short flags; /**< modifier flags for the ban */ - unsigned char nu_len; /**< length of nick!user part of banstr */ - unsigned char addrbits; /**< netmask length for BAN_IPMASK bans */ - char *who; /**< name of client that set the ban */ - char *banstr; /**< hostmask that the ban matches */ + time_t when; /**< timestamp when ban was added */ + unsigned short flags; /**< modifier flags for the ban */ + unsigned char nu_len; /**< length of nick!user part of banstr */ + unsigned char addrbits; /**< netmask length for BAN_IPMASK bans */ + char who[NICKLEN+1]; /**< name of client that set the ban */ + char banstr[NICKLEN+USERLEN+HOSTLEN+3]; /**< hostmask that the ban matches */ }; /** Information about a channel */ diff --git a/ircd/channel.c b/ircd/channel.c index 4f30a65..ff12cc1 100644 --- a/ircd/channel.c +++ b/ircd/channel.c @@ -67,6 +67,10 @@ static unsigned int membershipAllocCount; static struct Membership* membershipFreeList; /** Freelist for struct Ban*'s */ static struct Ban* free_bans; +/** Number of ban structures allocated. */ +static size_t bans_alloc; +/** Number of ban structures in use. */ +static size_t bans_inuse; #if !defined(NDEBUG) /** return the length (>=0) of a chain of links. @@ -91,10 +95,8 @@ static void set_ban_mask(struct Ban *ban, const char *banstr) { char *sep; - MyFree(ban->banstr); - if (!banstr) - return; - DupString(ban->banstr, banstr); + assert(banstr != NULL); + ircd_strncpy(ban->banstr, banstr, sizeof(ban->banstr) - 1); sep = strrchr(banstr, '@'); if (sep) { ban->nu_len = sep - banstr; @@ -117,6 +119,9 @@ make_ban(const char *banstr) } else if (!(ban = MyMalloc(sizeof(*ban)))) return NULL; + else + bans_alloc++; + bans_inuse++; memset(ban, 0, sizeof(*ban)); set_ban_mask(ban, banstr); return ban; @@ -128,10 +133,22 @@ make_ban(const char *banstr) void free_ban(struct Ban *ban) { - MyFree(ban->who); - MyFree(ban->banstr); ban->next = free_bans; free_bans = ban; + bans_inuse--; +} + +/** Report ban usage to \a cptr. + * @param[in] cptr Client requesting information. + */ +void bans_send_meminfo(struct Client *cptr) +{ + struct Ban *ban; + size_t num_free; + for (num_free = 0, ban = free_bans; ban; ban = ban->next) + num_free++; + send_reply(cptr, SND_EXPLICIT | RPL_STATSDEBUG, ":Bans: inuse %zu(%zu) free %zu alloc %zu", + bans_inuse, bans_inuse * sizeof(*ban), num_free, bans_alloc); } /** return the struct Membership* that represents a client on a channel @@ -2704,8 +2721,6 @@ int apply_ban(struct Ban **banlist, struct Ban *newban, int do_free) if (!bmatch(ban, newban)) { if (do_free) free_ban(newban); - else - MyFree(newban->banstr); return 1; } if (!(ban->flags & (BAN_OVERLAPPED|BAN_DEL))) { @@ -2736,14 +2751,10 @@ int apply_ban(struct Ban **banlist, struct Ban *newban, int do_free) /* If no matches were found, fail. */ if (do_free) free_ban(newban); - else - MyFree(newban->banstr); return 3; } if (do_free) free_ban(newban); - else - MyFree(newban->banstr); return 4; } @@ -2800,9 +2811,8 @@ mode_parse_ban(struct ParseState *state, int *flag_p) newban->next = 0; newban->flags = ((state->dir == MODE_ADD) ? BAN_ADD : BAN_DEL) | (*flag_p == MODE_BAN ? 0 : BAN_EXCEPTION); - newban->banstr = NULL; set_ban_mask(newban, collapse(pretty_mask(t_str))); - newban->who = cli_name(state->sptr); + ircd_strncpy(newban->who, cli_name(state->sptr), HOSTLEN); newban->when = TStime(); apply_ban(&state->chptr->banlist, newban, 0); } @@ -2834,12 +2844,12 @@ mode_process_bans(struct ParseState *state) count--; len -= banlen; - MyFree(ban->banstr); - continue; } else if (ban->flags & BAN_DEL) { /* Deleted a ban? */ + char *bandup; + DupString(bandup, ban->banstr); modebuf_mode_string(state->mbuf, MODE_DEL | MODE_BAN, - ban->banstr, 1); + bandup, 1); if (state->flags & MODE_PARSE_SET) { /* Ok, make it take effect */ if (prevban) /* clip it out of the list... */ @@ -2849,9 +2859,6 @@ mode_process_bans(struct ParseState *state) count--; len -= banlen; - - ban->banstr = NULL; /* modebuf_mode_string() gave ownership of - * the ban string to state->mbuf */ free_ban(ban); changed++; @@ -2869,7 +2876,6 @@ mode_process_bans(struct ParseState *state) !(state->flags & MODE_PARSE_BOUNCE)) { count--; len -= banlen; - MyFree(ban->banstr); } else { if (state->flags & MODE_PARSE_SET && MyUser(state->sptr) && (len > (feature_int(FEAT_AVBANLEN) * feature_int(FEAT_MAXBANS)) || @@ -2878,15 +2884,16 @@ mode_process_bans(struct ParseState *state) ban->banstr); count--; len -= banlen; - MyFree(ban->banstr); } else { + char *bandup; /* add the ban to the buffer */ + DupString(bandup, ban->banstr); modebuf_mode_string(state->mbuf, MODE_ADD | MODE_BAN, - ban->banstr, 1); + bandup, 1); if (state->flags & MODE_PARSE_SET) { /* create a new ban */ newban = make_ban(ban->banstr); - DupString(newban->who, ban->who); + strcpy(newban->who, ban->who); newban->when = ban->when; newban->flags = ban->flags & BAN_IPMASK; @@ -2902,13 +2909,6 @@ mode_process_bans(struct ParseState *state) prevban = ban; } /* for (prevban = 0, ban = state->chptr->banlist; ban; ban = nextban) { */ - /* Release all masks of removed bans */ - for (count = 0; count < state->numbans; ++count) { - ban = state->banlist + count; - if (ban->flags & BAN_DEL) - MyFree(ban->banstr); - } - if (changed) /* if we changed the ban list, we must invalidate the bans */ mode_ban_invalidate(state->chptr); } @@ -3171,7 +3171,7 @@ mode_parse(struct ModeBuf *mbuf, struct Client *cptr, struct Client *sptr, for (i = 0; i < MAXPARA; i++) { /* initialize ops/voices arrays */ state.banlist[i].next = 0; - state.banlist[i].who = 0; + state.banlist[i].who[0] = '\0'; state.banlist[i].when = 0; state.banlist[i].flags = 0; state.cli_change[i].flag = 0; @@ -3502,7 +3502,8 @@ int IsInvited(struct Client* cptr, const void* chptr) /* RevealDelayedJoin: sends a join for a hidden user */ -void RevealDelayedJoin(struct Membership *member) { +void RevealDelayedJoin(struct Membership *member) +{ ClearDelayedJoin(member); sendcmdto_channel_butserv_butone(member->user, CMD_JOIN, member->channel, member->user, 0, ":%H", member->channel); @@ -3511,14 +3512,15 @@ void RevealDelayedJoin(struct Membership *member) { /* CheckDelayedJoins: checks and clear +d if necessary */ -void CheckDelayedJoins(struct Channel *chan) { +void CheckDelayedJoins(struct Channel *chan) +{ struct Membership *memb2; - + if (chan->mode.mode & MODE_WASDELJOINS) { for (memb2=chan->members;memb2;memb2=memb2->next_member) if (IsDelayedJoin(memb2)) break; - + if (!memb2) { /* clear +d */ chan->mode.mode &= ~MODE_WASDELJOINS; diff --git a/ircd/list.c b/ircd/list.c index 8a567d6..21eab14 100644 --- a/ircd/list.c +++ b/ircd/list.c @@ -50,25 +50,19 @@ #include /* close */ #include -#ifdef DEBUGMODE /** Stores linked list statistics for various types of lists. */ static struct liststats { - int inuse; -} clients, connections, users, servs, links; -#endif + size_t alloc; /**< Number of structures ever allocated. */ + size_t inuse; /**< Number of structures currently in use. */ + size_t mem; /**< Memory used by in-use structures. */ +} clients, connections, servs, links; -/** Count of allocated Client structures. */ -static unsigned int clientAllocCount; /** Linked list of currently unused Client structures. */ static struct Client* clientFreeList; -/** Count of allocated Connection structures. */ -static unsigned int connectionAllocCount; /** Linked list of currently unused Connection structures. */ static struct Connection* connectionFreeList; -/** Count of allocated SLink structures. */ -static unsigned int slinkAllocCount; /** Linked list of currently unused SLink structures. */ static struct SLink* slinkFreeList; @@ -87,21 +81,13 @@ void init_list(void) cptr = (struct Client*) MyMalloc(sizeof(struct Client)); cli_next(cptr) = clientFreeList; clientFreeList = cptr; - ++clientAllocCount; + clients.alloc++; con = (struct Connection*) MyMalloc(sizeof(struct Connection)); con_next(con) = connectionFreeList; connectionFreeList = con; - ++connectionAllocCount; + connections.alloc++; } - -#ifdef DEBUGMODE - memset(&clients, 0, sizeof(clients)); - memset(&connections, 0, sizeof(connections)); - memset(&users, 0, sizeof(users)); - memset(&servs, 0, sizeof(servs)); - memset(&links, 0, sizeof(links)); -#endif } /** Allocate a new Client structure. @@ -115,13 +101,11 @@ static struct Client* alloc_client(void) if (!cptr) { cptr = (struct Client*) MyMalloc(sizeof(struct Client)); - ++clientAllocCount; + clients.alloc++; } else clientFreeList = cli_next(cptr); -#ifdef DEBUGMODE clients.inuse++; -#endif memset(cptr, 0, sizeof(struct Client)); @@ -136,9 +120,7 @@ static void dealloc_client(struct Client* cptr) assert(cli_verify(cptr)); assert(0 == cli_connect(cptr)); -#ifdef DEBUGMODE --clients.inuse; -#endif cli_next(cptr) = clientFreeList; clientFreeList = cptr; @@ -157,13 +139,11 @@ static struct Connection* alloc_connection(void) if (!con) { con = (struct Connection*) MyMalloc(sizeof(struct Connection)); - ++connectionAllocCount; + connections.alloc++; } else connectionFreeList = con_next(con); -#ifdef DEBUGMODE connections.inuse++; -#endif memset(con, 0, sizeof(struct Connection)); timer_init(&(con_proc(con))); @@ -197,9 +177,7 @@ static void dealloc_connection(struct Connection* con) if (con_listener(con)) release_listener(con_listener(con)); -#ifdef DEBUGMODE --connections.inuse; -#endif con_next(con) = connectionFreeList; connectionFreeList = con; @@ -337,9 +315,8 @@ struct Server *make_server(struct Client *cptr) serv = (struct Server*) MyMalloc(sizeof(struct Server)); assert(0 != serv); memset(serv, 0, sizeof(struct Server)); /* All variables are 0 by default */ -#ifdef DEBUGMODE servs.inuse++; -#endif + servs.alloc++; cli_serv(cptr) = serv; cli_serv(cptr)->lag = 60000; *serv->by = '\0'; @@ -396,9 +373,8 @@ void remove_client_from_list(struct Client *cptr) MyFree(cli_serv(cptr)->client_list); MyFree(cli_serv(cptr)->last_error_msg); MyFree(cli_serv(cptr)); -#ifdef DEBUGMODE --servs.inuse; -#endif + --servs.alloc; } free_client(cptr); } @@ -442,7 +418,7 @@ void verify_client_list(void) assert(cli_prev(client) == prev); /* Verify that the list hasn't become circular */ assert(cli_next(client) != GlobalClientList); - assert(visited <= clientAllocCount); + assert(visited <= clients.alloc); /* Remember what should precede us */ prev = client; } @@ -461,12 +437,10 @@ struct SLink* make_link(void) slinkFreeList = lp->next; else { lp = (struct SLink*) MyMalloc(sizeof(struct SLink)); - ++slinkAllocCount; + links.alloc++; } assert(0 != lp); -#ifdef DEBUGMODE links.inuse++; -#endif return lp; } @@ -479,9 +453,7 @@ void free_link(struct SLink* lp) lp->next = slinkFreeList; slinkFreeList = lp; } -#ifdef DEBUGMODE links.inuse--; -#endif } /** Add an element to a doubly linked list. @@ -522,42 +494,54 @@ void remove_dlink(struct DLink **lpp, struct DLink *lp) MyFree(lp); } -#ifdef DEBUGMODE +/** Report memory usage of a list to \a cptr. + * @param[in] cptr Client requesting information. + * @param[in] lstats List statistics descriptor. + * @param[in] itemname Plural name of item type. + * @param[in,out] totals If non-null, accumulates item counts and memory usage. + */ +void send_liststats(struct Client *cptr, const struct liststats *lstats, + const char *itemname, struct liststats *totals) +{ + send_reply(cptr, SND_EXPLICIT | RPL_STATSDEBUG, ":%s: inuse %zu(%zu) alloc %zu", + itemname, lstats->inuse, lstats->mem, lstats->alloc); + if (totals) + { + totals->inuse += lstats->inuse; + totals->alloc += lstats->alloc; + totals->mem += lstats->mem; + } +} + /** Report memory usage of list elements to \a cptr. * @param[in] cptr Client requesting information. * @param[in] name Unused pointer. */ void send_listinfo(struct Client *cptr, char *name) { - int inuse = 0, mem = 0, tmp = 0; - - send_reply(cptr, SND_EXPLICIT | RPL_STATSDEBUG, ":Clients: inuse: %d(%d)", - clients.inuse, tmp = clients.inuse * sizeof(struct Client)); - mem += tmp; - inuse += clients.inuse; - send_reply(cptr, SND_EXPLICIT | RPL_STATSDEBUG, "Connections: inuse: %d(%d)", - connections.inuse, - tmp = connections.inuse * sizeof(struct Connection)); - mem += tmp; - inuse += connections.inuse; - send_reply(cptr, SND_EXPLICIT | RPL_STATSDEBUG, ":Users: inuse: %d(%d)", - users.inuse, tmp = users.inuse * sizeof(struct User)); - mem += tmp; - inuse += users.inuse; - send_reply(cptr, SND_EXPLICIT | RPL_STATSDEBUG, ":Servs: inuse: %d(%d)", - servs.inuse, tmp = servs.inuse * sizeof(struct Server)); - mem += tmp; - inuse += servs.inuse; - send_reply(cptr, SND_EXPLICIT | RPL_STATSDEBUG, ":Links: inuse: %d(%d)", - links.inuse, tmp = links.inuse * sizeof(struct SLink)); - mem += tmp; - inuse += links.inuse; - send_reply(cptr, SND_EXPLICIT | RPL_STATSDEBUG, ":Confs: inuse: %d(%d)", - GlobalConfCount, tmp = GlobalConfCount * sizeof(struct ConfItem)); - mem += tmp; - inuse += GlobalConfCount; - send_reply(cptr, SND_EXPLICIT | RPL_STATSDEBUG, ":Totals: inuse %d %d", - inuse, mem); -} + struct liststats total; + struct liststats confs; + struct ConfItem *conf; + + memset(&total, 0, sizeof(total)); + + clients.mem = clients.inuse * sizeof(struct Client); + send_liststats(cptr, &clients, "Clients", &total); + + connections.mem = connections.inuse * sizeof(struct Connection); + send_liststats(cptr, &connections, "Connections", &total); -#endif + servs.mem = servs.inuse * sizeof(struct Server); + send_liststats(cptr, &servs, "Servers", &total); + + links.mem = links.inuse * sizeof(struct SLink); + send_liststats(cptr, &links, "Links", &total); + + confs.alloc = GlobalConfCount; + confs.mem = confs.alloc * sizeof(GlobalConfCount); + for (confs.inuse = 0, conf = GlobalConfList; conf; conf = conf->next) + confs.inuse++; + send_liststats(cptr, &confs, "Confs", &total); + + send_liststats(cptr, &total, "Totals", NULL); +} diff --git a/ircd/m_burst.c b/ircd/m_burst.c index d367e35..01be1a6 100644 --- a/ircd/m_burst.c +++ b/ircd/m_burst.c @@ -369,9 +369,7 @@ int ms_burst(struct Client *cptr, struct Client *sptr, int parc, char *parv[]) banstr[banpos++] = *ptr; newban = make_ban(ban); /* create new ban */ - - DupString(newban->who, - cli_name(feature_bool(FEAT_HIS_BANWHO) ? &me : sptr)); + strcpy(newban->who, "*"); newban->when = TStime(); newban->flags = BAN_BURSTED; /* set flags */ @@ -550,9 +548,10 @@ int ms_burst(struct Client *cptr, struct Client *sptr, int parc, char *parv[]) /* remove ban from channel */ if (lp->flags & (BAN_OVERLAPPED | BAN_BURST_WIPEOUT)) { + char *bandup; + DupString(bandup, lp->banstr); modebuf_mode_string(mbuf, MODE_DEL | MODE_BAN, - lp->banstr, 1); /* let it free banstr */ - lp->banstr = NULL; /* do not free this string */ + bandup, 1); *lp_p = lp->next; /* clip out of list */ free_ban(lp); continue; diff --git a/ircd/m_clearmode.c b/ircd/m_clearmode.c index 8d45c60..bd390f0 100644 --- a/ircd/m_clearmode.c +++ b/ircd/m_clearmode.c @@ -177,12 +177,12 @@ do_clearmode(struct Client *cptr, struct Client *sptr, struct Channel *chptr, */ if (del_mode & MODE_BAN) { for (link = chptr->banlist; link; link = next) { + char *bandup; next = link->next; + DupString(bandup, link->banstr); modebuf_mode_string(&mbuf, MODE_DEL | MODE_BAN, /* delete ban */ - link->banstr, 1); - link->banstr = NULL; /* modebuf_mode_string() gave ownership of - * banstr to mbuf */ + bandup, 1); free_ban(link); } diff --git a/ircd/s_stats.c b/ircd/s_stats.c index cf5d039..05965e7 100644 --- a/ircd/s_stats.c +++ b/ircd/s_stats.c @@ -489,7 +489,6 @@ stats_servers_verbose(struct Client* sptr, const struct StatDesc* sd, } } -#ifdef DEBUGMODE /** Display objects allocated (and total memory used by them) for * several types of structures. * @param[in] to Client requesting statistics. @@ -499,10 +498,12 @@ stats_servers_verbose(struct Client* sptr, const struct StatDesc* sd, static void stats_meminfo(struct Client* to, const struct StatDesc* sd, char* param) { + extern void bans_send_meminfo(struct Client *cptr); + class_send_meminfo(to); + bans_send_meminfo(to); send_listinfo(to, 0); } -#endif /** Send a list of available statistics. * @param[in] to Client requesting statistics. @@ -606,11 +607,9 @@ struct StatDesc statsinfo[] = { { 'w', "userload", STAT_FLAG_OPERFEAT, FEAT_HIS_STATS_w, calc_load, 0, "Userload statistics." }, -#ifdef DEBUGMODE { 'x', "memusage", STAT_FLAG_OPERFEAT, FEAT_HIS_STATS_x, stats_meminfo, 0, "List usage information (Debug only)." }, -#endif { 'y', "classes", STAT_FLAG_OPERFEAT, FEAT_HIS_STATS_y, report_classes, 0, "Connection classes." }, -- 2.20.1