#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)));
Debug((DEBUG_LIST, "Deallocating connection %p", con));
- if (con_dns_reply(con)) {
- MyFree(con_dns_reply(con));
- con_dns_reply(con) = 0;
- }
if (-1 < con_fd(con))
close(con_fd(con));
MsgQClear(&(con_sendQ(con)));
if (con_listener(con))
release_listener(con_listener(con));
-#ifdef DEBUGMODE
--connections.inuse;
-#endif
con_next(con) = connectionFreeList;
connectionFreeList = con;
cptr, cli_connect(cptr)));
if (cli_auth(cptr))
- destroy_auth_request(cli_auth(cptr), 0);
+ destroy_auth_request(cli_auth(cptr));
/* Make sure we didn't magically get re-added to the list */
assert(cli_next(cptr) == 0);
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);
- /* Remember what should preceed us */
+ assert(visited <= clients.alloc);
+ /* Remember what should precede us */
prev = client;
}
}
#endif /* DEBUGMODE */
-/** Find the list element that corresponds to a client.
- * @param[in] lp Head of singly linked list.
- * @param[in] ptr %Client to search for.
- * @return SLink element from \a lp that contains \a ptr, or NULL if none exist.
- */
-struct SLink *find_user_link(struct SLink *lp, struct Client *ptr)
-{
- if (ptr) {
- while (lp) {
- if (lp->value.cptr == ptr)
- return (lp);
- lp = lp->next;
- }
- }
- return NULL;
-}
-
/** Allocate a new SLink element.
* Pulls from #slinkFreeList if it contains anything, else it
* allocates a new one from the heap.
slinkFreeList = lp->next;
else {
lp = (struct SLink*) MyMalloc(sizeof(struct SLink));
- ++slinkAllocCount;
+ links.alloc++;
}
assert(0 != lp);
-#ifdef DEBUGMODE
links.inuse++;
-#endif
+ memset(lp, 0, sizeof(*lp));
return lp;
}
if (lp) {
lp->next = slinkFreeList;
slinkFreeList = lp;
+ links.inuse--;
}
-#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);
-#endif
+ connections.mem = connections.inuse * sizeof(struct Connection);
+ send_liststats(cptr, &connections, "Connections", &total);
+
+ 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);
+}