diff options
Diffstat (limited to 'ot_stats.c')
-rw-r--r-- | ot_stats.c | 111 |
1 files changed, 110 insertions, 1 deletions
@@ -43,6 +43,110 @@ static unsigned long long ot_failed_request_counts[CODE_HTTPERROR_COUNT]; | |||
43 | 43 | ||
44 | static time_t ot_start_time; | 44 | static 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 | |||
53 | typedef union stats_network_node stats_network_node; | ||
54 | union stats_network_node { | ||
55 | int counters[STATS_NETWORK_NODE_COUNT]; | ||
56 | stats_network_node *children[STATS_NETWORK_NODE_COUNT]; | ||
57 | }; | ||
58 | |||
59 | static stats_network_node *stats_network_counters_root = NULL; | ||
60 | |||
61 | static 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 | |||
78 | static 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 | |||
105 | static 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 | |||
134 | static 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 */ |
47 | static 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;} | 151 | static 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 | ||
385 | void stats_issue_event( ot_status_event event, int is_tcp, size_t event_data ) { | 491 | void 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++; |