/* * ircd-ratbox: A slightly useful ircd. * s_stats.c: Statistics related functions * * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center * Copyright (C) 1996-2002 Hybrid Development Team * Copyright (C) 2002-2005 ircd-ratbox development team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA * * $Id: s_stats.c 3249 2007-03-05 18:51:17Z nenolod $ */ #include "stdinc.h" #include "s_stats.h" #include "client.h" #include "irc_string.h" #include "ircd.h" #include "numeric.h" #include "commio.h" #include "send.h" #include "memory.h" #include "s_conf.h" #include "s_newconf.h" #include "whowas.h" #include "hash.h" #include "scache.h" #include "reject.h" /* * stats stuff */ static struct ServerStatistics ircst; struct ServerStatistics *ServerStats = &ircst; void init_stats() { memset(&ircst, 0, sizeof(ircst)); } /* * tstats * * inputs - client to report to * output - NONE * side effects - */ void tstats(struct Client *source_p) { struct Client *target_p; struct ServerStatistics *sp; struct ServerStatistics tmp; rb_dlink_node *ptr; sp = &tmp; memcpy(sp, ServerStats, sizeof(struct ServerStatistics)); DLINK_FOREACH(ptr, serv_list.head) { target_p = ptr->data; sp->is_sbs += target_p->localClient->sendB; sp->is_sbr += target_p->localClient->receiveB; sp->is_sks += target_p->localClient->sendK; sp->is_skr += target_p->localClient->receiveK; sp->is_sti += CurrentTime - target_p->localClient->firsttime; sp->is_sv++; if(sp->is_sbs > 1023) { sp->is_sks += (sp->is_sbs >> 10); sp->is_sbs &= 0x3ff; } if(sp->is_sbr > 1023) { sp->is_skr += (sp->is_sbr >> 10); sp->is_sbr &= 0x3ff; } } DLINK_FOREACH(ptr, lclient_list.head) { target_p = ptr->data; sp->is_cbs += target_p->localClient->sendB; sp->is_cbr += target_p->localClient->receiveB; sp->is_cks += target_p->localClient->sendK; sp->is_ckr += target_p->localClient->receiveK; sp->is_cti += CurrentTime - target_p->localClient->firsttime; sp->is_cl++; if(sp->is_cbs > 1023) { sp->is_cks += (sp->is_cbs >> 10); sp->is_cbs &= 0x3ff; } if(sp->is_cbr > 1023) { sp->is_ckr += (sp->is_cbr >> 10); sp->is_cbr &= 0x3ff; } } DLINK_FOREACH(ptr, unknown_list.head) { sp->is_ni++; } sendto_one_numeric(source_p, RPL_STATSDEBUG, "T :accepts %u refused %u", sp->is_ac, sp->is_ref); sendto_one_numeric(source_p, RPL_STATSDEBUG, "T :rejected %u delaying %lu", sp->is_rej, rb_dlink_list_length(&delay_exit)); sendto_one_numeric(source_p, RPL_STATSDEBUG, "T :nicks being delayed %lu", get_nd_count()); sendto_one_numeric(source_p, RPL_STATSDEBUG, "T :unknown commands %u prefixes %u", sp->is_unco, sp->is_unpf); sendto_one_numeric(source_p, RPL_STATSDEBUG, "T :nick collisions %u saves %u unknown closes %u", sp->is_kill, sp->is_save, sp->is_ni); sendto_one_numeric(source_p, RPL_STATSDEBUG, "T :wrong direction %u empty %u", sp->is_wrdi, sp->is_empt); sendto_one_numeric(source_p, RPL_STATSDEBUG, "T :numerics seen %u", sp->is_num); sendto_one_numeric(source_p, RPL_STATSDEBUG, "T :tgchange blocked msgs %u restricted addrs %lu", sp->is_tgch, rb_dlink_list_length(&tgchange_list)); sendto_one_numeric(source_p, RPL_STATSDEBUG, "T :auth successes %u fails %u", sp->is_asuc, sp->is_abad); sendto_one_numeric(source_p, RPL_STATSDEBUG, "T :sasl successes %u fails %u", sp->is_ssuc, sp->is_sbad); sendto_one_numeric(source_p, RPL_STATSDEBUG, "T :Client Server"); sendto_one_numeric(source_p, RPL_STATSDEBUG, "T :connected %u %u", sp->is_cl, sp->is_sv); sendto_one_numeric(source_p, RPL_STATSDEBUG, "T :bytes sent %d.%uK %d.%uK", (int) sp->is_cks, sp->is_cbs, (int) sp->is_sks, sp->is_sbs); sendto_one_numeric(source_p, RPL_STATSDEBUG, "T :bytes recv %d.%uK %d.%uK", (int) sp->is_ckr, sp->is_cbr, (int) sp->is_skr, sp->is_sbr); sendto_one_numeric(source_p, RPL_STATSDEBUG, "T :time connected %d %d", (int) sp->is_cti, (int) sp->is_sti); } void count_memory(struct Client *source_p) { struct Client *target_p; struct Channel *chptr; struct Ban *actualBan; rb_dlink_node *rb_dlink; rb_dlink_node *ptr; int channel_count = 0; int local_client_conf_count = 0; /* local client conf links */ int users_counted = 0; /* user structs */ int channel_users = 0; int channel_invites = 0; int channel_bans = 0; int channel_except = 0; int channel_invex = 0; int channel_quiets = 0; int class_count = 0; /* classes */ int conf_count = 0; /* conf lines */ int users_invited_count = 0; /* users invited */ int user_channels = 0; /* users in channels */ int aways_counted = 0; size_t number_servers_cached; /* number of servers cached by scache */ size_t channel_memory = 0; size_t channel_ban_memory = 0; size_t channel_except_memory = 0; size_t channel_invex_memory = 0; size_t channel_quiet_memory = 0; size_t away_memory = 0; /* memory used by aways */ size_t ww = 0; /* whowas array count */ size_t wwm = 0; /* whowas array memory used */ size_t conf_memory = 0; /* memory used by conf lines */ size_t mem_servers_cached; /* memory used by scache */ size_t linebuf_count = 0; size_t linebuf_memory_used = 0; size_t total_channel_memory = 0; size_t totww = 0; size_t local_client_count = 0; size_t local_client_memory_used = 0; size_t remote_client_count = 0; size_t remote_client_memory_used = 0; size_t total_memory = 0; count_whowas_memory(&ww, &wwm); DLINK_FOREACH(ptr, global_client_list.head) { target_p = ptr->data; if(MyConnect(target_p)) { local_client_conf_count++; } if(target_p->user) { users_counted++; users_invited_count += rb_dlink_list_length(&target_p->user->invited); user_channels += rb_dlink_list_length(&target_p->user->channel); if(target_p->user->away) { aways_counted++; away_memory += (strlen(target_p->user->away) + 1); } } } /* Count up all channels, ban lists, except lists, Invex lists */ DLINK_FOREACH(ptr, global_channel_list.head) { chptr = ptr->data; channel_count++; channel_memory += (strlen(chptr->chname) + sizeof(struct Channel)); channel_users += rb_dlink_list_length(&chptr->members); channel_invites += rb_dlink_list_length(&chptr->invites); DLINK_FOREACH(rb_dlink, chptr->banlist.head) { actualBan = rb_dlink->data; channel_bans++; channel_ban_memory += sizeof(rb_dlink_node) + sizeof(struct Ban); } DLINK_FOREACH(rb_dlink, chptr->exceptlist.head) { actualBan = rb_dlink->data; channel_except++; channel_except_memory += (sizeof(rb_dlink_node) + sizeof(struct Ban)); } DLINK_FOREACH(rb_dlink, chptr->invexlist.head) { actualBan = rb_dlink->data; channel_invex++; channel_invex_memory += (sizeof(rb_dlink_node) + sizeof(struct Ban)); } DLINK_FOREACH(rb_dlink, chptr->quietlist.head) { actualBan = rb_dlink->data; channel_quiets++; channel_quiet_memory += (sizeof(rb_dlink_node) + sizeof(struct Ban)); } } /* count up all classes */ class_count = rb_dlink_list_length(&class_list) + 1; count_linebuf_memory(&linebuf_count, &linebuf_memory_used); sendto_one_numeric(source_p, RPL_STATSDEBUG, "z :Users %u(%lu) Invites %u(%lu)", users_counted, (unsigned long) users_counted * sizeof(struct User), users_invited_count, (unsigned long) users_invited_count * sizeof(rb_dlink_node)); sendto_one_numeric(source_p, RPL_STATSDEBUG, "z :User channels %u(%lu) Aways %u(%d)", user_channels, (unsigned long) user_channels * sizeof(rb_dlink_node), aways_counted, (int) away_memory); sendto_one_numeric(source_p, RPL_STATSDEBUG, "z :Attached confs %u(%lu)", local_client_conf_count, (unsigned long) local_client_conf_count * sizeof(rb_dlink_node)); sendto_one_numeric(source_p, RPL_STATSDEBUG, "z :Conflines %u(%d)", conf_count, (int) conf_memory); sendto_one_numeric(source_p, RPL_STATSDEBUG, "z :Classes %u(%lu)", class_count, (unsigned long) class_count * sizeof(struct Class)); sendto_one_numeric(source_p, RPL_STATSDEBUG, "z :Channels %u(%d)", channel_count, (int) channel_memory); sendto_one_numeric(source_p, RPL_STATSDEBUG, "z :Bans %u(%d) Exceptions %u(%d) Invex %u(%d) Quiets %u(%d)", channel_bans, (int) channel_ban_memory, channel_except, (int) channel_except_memory, channel_invex, (int) channel_invex_memory, channel_quiets, (int) channel_quiet_memory); sendto_one_numeric(source_p, RPL_STATSDEBUG, "z :Channel members %u(%lu) invite %u(%lu)", channel_users, (unsigned long) channel_users * sizeof(rb_dlink_node), channel_invites, (unsigned long) channel_invites * sizeof(rb_dlink_node)); total_channel_memory = channel_memory + channel_ban_memory + channel_users * sizeof(rb_dlink_node) + channel_invites * sizeof(rb_dlink_node); sendto_one_numeric(source_p, RPL_STATSDEBUG, "z :Whowas array %ld(%ld)", (long)ww, (long)wwm); totww = wwm; sendto_one_numeric(source_p, RPL_STATSDEBUG, "z :Hash: client %u(%ld) chan %u(%ld)", U_MAX, (long)(U_MAX * sizeof(rb_dlink_list)), CH_MAX, (long)(CH_MAX * sizeof(rb_dlink_list))); sendto_one_numeric(source_p, RPL_STATSDEBUG, "z :linebuf %ld(%ld)", (long)linebuf_count, (long)linebuf_memory_used); count_scache(&number_servers_cached, &mem_servers_cached); sendto_one_numeric(source_p, RPL_STATSDEBUG, "z :scache %ld(%ld)", (long)number_servers_cached, (long)mem_servers_cached); sendto_one_numeric(source_p, RPL_STATSDEBUG, "z :hostname hash %d(%ld)", HOST_MAX, (long)HOST_MAX * sizeof(rb_dlink_list)); total_memory = totww + total_channel_memory + conf_memory + class_count * sizeof(struct Class); total_memory += mem_servers_cached; sendto_one_numeric(source_p, RPL_STATSDEBUG, "z :Total: whowas %d channel %d conf %d", (int) totww, (int) total_channel_memory, (int) conf_memory); count_local_client_memory(&local_client_count, &local_client_memory_used); total_memory += local_client_memory_used; sendto_one_numeric(source_p, RPL_STATSDEBUG, "z :Local client Memory in use: %ld(%ld)", (long)local_client_count, (long)local_client_memory_used); count_remote_client_memory(&remote_client_count, &remote_client_memory_used); total_memory += remote_client_memory_used; sendto_one_numeric(source_p, RPL_STATSDEBUG, "z :Remote client Memory in use: %ld(%ld)", (long)remote_client_count, (long)remote_client_memory_used); }