+2005-05-16 Michael Poole <mdpoole@troilus.org>
+
+ * 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 <mdpoole@troilus.org>
* include/ircd_string.h: Include necessary <string.h> header.
/** 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 */
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.
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;
}
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;
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
if (!bmatch(ban, newban)) {
if (do_free)
free_ban(newban);
- else
- MyFree(newban->banstr);
return 1;
}
if (!(ban->flags & (BAN_OVERLAPPED|BAN_DEL))) {
/* 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;
}
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);
}
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... */
count--;
len -= banlen;
-
- ban->banstr = NULL; /* modebuf_mode_string() gave ownership of
- * the ban string to state->mbuf */
free_ban(ban);
changed++;
!(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)) ||
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;
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);
}
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;
/* 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);
/* 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;
#include <unistd.h> /* close */
#include <string.h>
-#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;
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.
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));
assert(cli_verify(cptr));
assert(0 == cli_connect(cptr));
-#ifdef DEBUGMODE
--clients.inuse;
-#endif
cli_next(cptr) = clientFreeList;
clientFreeList = cptr;
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)));
if (con_listener(con))
release_listener(con_listener(con));
-#ifdef DEBUGMODE
--connections.inuse;
-#endif
con_next(con) = connectionFreeList;
connectionFreeList = con;
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';
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);
}
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;
}
slinkFreeList = lp->next;
else {
lp = (struct SLink*) MyMalloc(sizeof(struct SLink));
- ++slinkAllocCount;
+ links.alloc++;
}
assert(0 != lp);
-#ifdef DEBUGMODE
links.inuse++;
-#endif
return lp;
}
lp->next = slinkFreeList;
slinkFreeList = lp;
}
-#ifdef DEBUGMODE
links.inuse--;
-#endif
}
/** Add an element to a doubly linked list.
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);
+}
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 */
/* 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;
*/
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);
}
}
}
-#ifdef DEBUGMODE
/** Display objects allocated (and total memory used by them) for
* several types of structures.
* @param[in] to Client requesting statistics.
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.
{ '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." },