dnxStats.c
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
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
00062 static DnxNode * s_nodeHashTable[256];
00063 static unsigned s_serverStats[STATS_COUNT];
00064
00065
00066
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];
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
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
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
00241 if ((ret = getaddrinfo(addrstr, 0, 0, &aip)) != 0)
00242 return ret;
00243
00244
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