dnxStats.c

Go to the documentation of this file.
00001 /*--------------------------------------------------------------------------
00002 
00003    Copyright (c) 2006-2010, Intellectual Reserve, Inc. All rights reserved.
00004 
00005    This program is free software; you can redistribute it and/or modify
00006    it under the terms of the GNU General Public License version 2 as
00007    published by the Free Software Foundation.
00008 
00009    This program is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012    GNU General Public License for more details.
00013 
00014    You should have received a copy of the GNU General Public License
00015    along with this program; if not, write to the Free Software
00016    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017 
00018   --------------------------------------------------------------------------*/
00019 
00042 #include "dnxStats.h"
00043 #include "dnxDebug.h"
00044 #include "dnxError.h"
00045 
00046 #include <pthread.h>
00047 #include <sys/socket.h>
00048 #include <netinet/in.h>
00049 #include <netdb.h>
00050 
00051 #define elemcount(x) (sizeof(x)/sizeof(*(x)))
00052 
00054 typedef struct DnxNode
00055 {
00056    struct DnxNode * next;     
00057    struct sockaddr * saddr;   
00058    DnxNodeData data;          
00059 } DnxNode;
00060 
00061 /* Global (static) variables managed by this module. */
00062 static DnxNode * s_nodeHashTable[256];       
00063 static unsigned s_serverStats[STATS_COUNT];  
00064 
00065 /*--------------------------------------------------------------------------
00066                               IMPLEMENTATION
00067   --------------------------------------------------------------------------*/
00068 
00077 static unsigned hashFunction(struct sockaddr * addr)
00078 {
00079    unsigned hash = 0;
00080    switch (addr->sa_family)
00081    {
00082       case AF_INET:
00083          hash = ((struct sockaddr_in *)addr)->sin_addr.s_addr;
00084          break;
00085 
00086       case AF_INET6:
00087       {
00088          int i;
00089          for (i = 0; i < 4; i++)
00090             hash += *((unsigned *)(((struct sockaddr_in6 *)addr)
00091                   ->sin6_addr.s6_addr + i * 4)) & 0xFFFFFFFF;
00092       }
00093 
00094       default:
00095          hash = addr->sa_data[2];   // try to skip the port
00096          break;
00097    }
00098    return hash & 0xFF;
00099 }
00100 
00101 //----------------------------------------------------------------------------
00102 
00115 static int dnxAddrCompare(struct sockaddr * addr_a, struct sockaddr * addr_b)
00116 {
00117    if (addr_a->sa_family != addr_b->sa_family)
00118       return addr_a->sa_family - addr_b->sa_family;
00119 
00120    switch(addr_a->sa_family)
00121    {
00122       case AF_INET:
00123          return (int)(((struct sockaddr_in *)addr_a)->sin_addr.s_addr 
00124                - ((struct sockaddr_in *)addr_b)->sin_addr.s_addr);
00125 
00126       case AF_INET6:
00127          return memcmp(((struct sockaddr_in6 *)addr_a)->sin6_addr.s6_addr,
00128                ((struct sockaddr_in6 *)addr_b)->sin6_addr.s6_addr, 16);
00129    }
00130 
00131    return memcmp(addr_a->sa_data + 2, addr_b->sa_data + 2, 
00132          sizeof(addr_a->sa_data) - 2);
00133 }
00134 
00135 //----------------------------------------------------------------------------
00136 
00147 static DnxNode * dnxCreateNodeAt(DnxNode ** npp, struct sockaddr * saddr, 
00148       unsigned hashCode)
00149 {
00150    DnxNode * np;
00151 
00152    // allocate and populate a new node
00153    if ((np = (DnxNode *)xmalloc(sizeof *np)) == 0)
00154       return 0;
00155 
00156    memset(np, 0, sizeof *np);
00157    memcpy(np->data.address, saddr, sizeof np->data.address);
00158    np->saddr = (struct sockaddr *)np->data.address;
00159    dnxNtop(saddr, np->data.addrstr, sizeof np->data.addrstr);
00160 
00161    return *npp = np;
00162 }
00163 
00164 //----------------------------------------------------------------------------
00165 
00176 static DnxNode * dnxGetNode(struct sockaddr * saddr)
00177 {
00178    DnxNode ** npp, * np;
00179    unsigned hashCode = hashFunction(saddr);
00180 
00181    for (npp = &s_nodeHashTable[hashCode]; 
00182          (np = *npp) && dnxAddrCompare(np->saddr, saddr); npp = &np->next)
00183       ;
00184 
00185    return np? np: dnxCreateNodeAt(npp, saddr, hashCode);
00186 }
00187 
00188 /*--------------------------------------------------------------------------
00189                                  INTERFACE
00190   --------------------------------------------------------------------------*/
00191 
00192 void dnxStatsGetServerStats(unsigned * statsbuf)
00193 {
00194    memcpy(statsbuf, s_serverStats, sizeof s_serverStats);
00195 }
00196 
00197 //----------------------------------------------------------------------------
00198 
00199 void dnxStatsResetServerStats(void)
00200 {
00201    memset(s_serverStats, 0, sizeof s_serverStats);
00202 }
00203 
00204 //----------------------------------------------------------------------------
00205 
00206 void dnxStatsInc(char * addr, DnxStatsIndex member)
00207 {
00208    if (addr)
00209    {
00210       DnxNode * np = dnxGetNode((struct sockaddr *)addr);
00211       assert(member >= 0 && member < STATS_COUNT);
00212       if (np) np->data.stats[member]++;
00213    }
00214    s_serverStats[member]++;
00215 }
00216 
00217 //----------------------------------------------------------------------------
00218 
00219 int dnxStatsForEachNode(DnxStatsNodeCB * cb, void * data)
00220 {
00221    int i, ret = 0;
00222    for (i = 0; i < elemcount(s_nodeHashTable); i++)
00223    {
00224       DnxNode * np;
00225       for (np = s_nodeHashTable[i]; np; np = np->next)
00226          if ((ret = cb(&np->data, data)) != 0)
00227             break;
00228    }
00229    return ret == DNX_CBCANCEL? 0: ret;
00230 }
00231 
00232 //----------------------------------------------------------------------------
00233 
00234 int dnxStatsForNodeByAddrStr(char * addrstr, DnxStatsNodeCB * cb, void * data)
00235 {
00236    struct addrinfo * aip, * curaip;
00237    DnxNode * np = 0;
00238    int ret;
00239 
00240    // convert addrstr to a sockaddr
00241    if ((ret = getaddrinfo(addrstr, 0, 0, &aip)) != 0)
00242       return ret;
00243 
00244    // search for the first node that matches one of the addresses found
00245    for (curaip = aip; !np && curaip; curaip = curaip->ai_next)
00246       if ((np = dnxGetNode(curaip->ai_addr)) != 0)
00247          ret = cb(&np->data, data);
00248 
00249    freeaddrinfo(aip);
00250 
00251    return ret;
00252 }
00253 
00254 //----------------------------------------------------------------------------
00255 
00256 void dnxStatsCleanup()
00257 {
00258    int i;
00259    for (i = 0; i < elemcount(s_nodeHashTable); i++)
00260    {
00261       DnxNode * np = s_nodeHashTable[i];
00262 
00263       while (np)
00264       {
00265          DnxNode * tmp = np->next;
00266          free(np);
00267          np = tmp;
00268       }
00269       s_nodeHashTable[i] = 0;
00270    }
00271 }
00272 
00273 //============================================================================
00274 

Generated on Tue Apr 13 15:48:07 2010 for DNX by  doxygen 1.5.6