summaryrefslogtreecommitdiff
path: root/ot_stats.c
diff options
context:
space:
mode:
authorerdgeist <>2008-01-17 10:46:25 +0000
committererdgeist <>2008-01-17 10:46:25 +0000
commit408c5f98ed073e43560be5319080a34104441e6a (patch)
treeac48629c99a79a360b4deb6309b83cbc4e953223 /ot_stats.c
parent7050e027d3b7d353dce6a8e100e54d71a46a8063 (diff)
Introducing live busy network detection.
Diffstat (limited to 'ot_stats.c')
-rw-r--r--ot_stats.c111
1 files changed, 110 insertions, 1 deletions
diff --git a/ot_stats.c b/ot_stats.c
index 6113275..81ff487 100644
--- a/ot_stats.c
+++ b/ot_stats.c
@@ -43,6 +43,110 @@ static unsigned long long ot_failed_request_counts[CODE_HTTPERROR_COUNT];
43 43
44static time_t ot_start_time; 44static time_t ot_start_time;
45 45
46#ifdef WANT_LOG_NETWORKS
47#define STATS_NETWORK_NODE_BITWIDTH 8
48#define STATS_NETWORK_NODE_MAXDEPTH 3
49
50#define STATS_NETWORK_NODE_BITMASK ((1<<STATS_NETWORK_NODE_BITWIDTH)-1)
51#define STATS_NETWORK_NODE_COUNT (1<<STATS_NETWORK_NODE_BITWIDTH)
52
53typedef union stats_network_node stats_network_node;
54union stats_network_node {
55 int counters[STATS_NETWORK_NODE_COUNT];
56 stats_network_node *children[STATS_NETWORK_NODE_COUNT];
57};
58
59static stats_network_node *stats_network_counters_root = NULL;
60
61static int stat_increase_network_count( stats_network_node **node, int depth, uint32_t ip ) {
62 int foo = ( ip >> ( 32 - STATS_NETWORK_NODE_BITWIDTH * ( ++depth ) ) ) & STATS_NETWORK_NODE_BITMASK;
63
64 if( !*node ) {
65 *node = malloc( sizeof( stats_network_node ) );
66 if( !*node )
67 return -1;
68 memset( *node, 0, sizeof( stats_network_node ) );
69 }
70
71 if( depth < STATS_NETWORK_NODE_MAXDEPTH )
72 return stat_increase_network_count( &(*node)->children[ foo ], depth, ip );
73
74 (*node)->counters[ foo ]++;
75 return 0;
76}
77
78static int stats_shift_down_network_count( stats_network_node **node, int depth, int shift ) {
79 int i, rest = 0;
80 if( !*node ) return 0;
81
82 if( ++depth == STATS_NETWORK_NODE_MAXDEPTH )
83 for( i=0; i<STATS_NETWORK_NODE_COUNT; ++i ) {
84 rest += ((*node)->counters[i]>>=shift);
85 return rest;
86 }
87
88 for( i=0; i<STATS_NETWORK_NODE_COUNT; ++i ) {
89 stats_network_node **childnode = &(*node)->children[i];
90 int rest_val;
91
92 if( !*childnode ) continue;
93
94 rest += rest_val = stats_shift_down_network_count( childnode, depth, shift );
95
96 if( rest_val ) continue;
97
98 free( (*node)->children[i] );
99 (*node)->children[i] = NULL;
100 }
101
102 return rest;
103}
104
105static void stats_get_highscore_networks( stats_network_node *node, int depth, uint32_t node_value, int *scores, uint32_t *networks, int network_count ) {
106 int i;
107
108 if( !node ) return;
109
110 if( !depth++ ) {
111 memset( scores, 0, sizeof( *scores ) * network_count );
112 memset( networks, 0, sizeof( *networks ) * network_count );
113 }
114
115 if( depth < STATS_NETWORK_NODE_MAXDEPTH ) {
116 for( i=0; i<STATS_NETWORK_NODE_COUNT; ++i )
117 if( node->children[i] )
118 stats_get_highscore_networks( node->children[i], depth, node_value | ( i << ( 32 - depth * STATS_NETWORK_NODE_BITWIDTH ) ), scores, networks, network_count );
119 } else
120 for( i=0; i<STATS_NETWORK_NODE_COUNT; ++i ) {
121 int j=1;
122 if( node->counters[i] <= scores[0] ) continue;
123
124 while( (j<network_count) && (node->counters[i]>scores[j] ) ) ++j;
125 --j;
126
127 memmove( scores, scores + 1, j * sizeof( *scores ) );
128 memmove( networks, networks + 1, j * sizeof( *networks ) );
129 scores[ j ] = node->counters[ i ];
130 networks[ j ] = node_value | ( i << ( 32 - depth * STATS_NETWORK_NODE_BITWIDTH ) );
131 }
132}
133
134static size_t stats_return_busy_networks( char * reply ) {
135 uint32_t networks[16];
136 int scores[16];
137 int i;
138 char * r = reply;
139
140 stats_get_highscore_networks( stats_network_counters_root, 0, 0, scores, networks, 16 );
141
142 for( i=15; i>=0; ++i)
143 r += sprintf( r, "%08i: %d.%d.%d.0/24\n", scores[i], (networks[i]>>24)&0xff, (networks[i]>>16)&0xff, (networks[i]>>8)&0xff );
144
145 return r - reply;
146}
147
148#endif
149
46/* Converter function from memory to human readable hex strings */ 150/* Converter function from memory to human readable hex strings */
47static char*to_hex(char*d,uint8_t*s){char*m="0123456789ABCDEF";char *t=d;char*e=d+40;while(d<e){*d++=m[*s>>4];*d++=m[*s++&15];}*d=0;return t;} 151static char*to_hex(char*d,uint8_t*s){char*m="0123456789ABCDEF";char *t=d;char*e=d+40;while(d<e){*d++=m[*s>>4];*d++=m[*s++&15];}*d=0;return t;}
48 152
@@ -377,15 +481,20 @@ size_t return_stats_for_tracker( char *reply, int mode, int format ) {
377 return stats_httperrors_txt( reply ); 481 return stats_httperrors_txt( reply );
378 case TASK_STATS_VERSION: 482 case TASK_STATS_VERSION:
379 return stats_return_tracker_version( reply ); 483 return stats_return_tracker_version( reply );
484 case TASK_STATS_BUSY_NETWORKS:
485 return stats_return_busy_networks( reply );
380 default: 486 default:
381 return 0; 487 return 0;
382 } 488 }
383} 489}
384 490
385void stats_issue_event( ot_status_event event, int is_tcp, size_t event_data ) { 491void stats_issue_event( ot_status_event event, int is_tcp, uint32_t event_data ) {
386 switch( event ) { 492 switch( event ) {
387 case EVENT_ACCEPT: 493 case EVENT_ACCEPT:
388 if( is_tcp ) ot_overall_tcp_connections++; else ot_overall_udp_connections++; 494 if( is_tcp ) ot_overall_tcp_connections++; else ot_overall_udp_connections++;
495#ifdef WANT_LOG_NETWORKS
496 stat_increase_network_count( &stats_network_counters_root, 0, event_data );
497#endif
389 break; 498 break;
390 case EVENT_ANNOUNCE: 499 case EVENT_ANNOUNCE:
391 if( is_tcp ) ot_overall_tcp_successfulannounces++; else ot_overall_udp_successfulannounces++; 500 if( is_tcp ) ot_overall_tcp_successfulannounces++; else ot_overall_udp_successfulannounces++;