diff options
Diffstat (limited to 'opentracker.c')
| -rw-r--r-- | opentracker.c | 64 |
1 files changed, 40 insertions, 24 deletions
diff --git a/opentracker.c b/opentracker.c index 2eaf988..e5efff5 100644 --- a/opentracker.c +++ b/opentracker.c | |||
| @@ -109,20 +109,9 @@ static void *server_mainloop(void *args) { | |||
| 109 | 109 | ||
| 110 | (void)args; | 110 | (void)args; |
| 111 | 111 | ||
| 112 | /* Initialize our "thread local storage" */ | 112 | if (workstruct_init(&ws) == -1) |
| 113 | memset(&ws, 0, sizeof(ws)); | ||
| 114 | stats_counters_register(&ws); | ||
| 115 | ws.inbuf = malloc(G_INBUF_SIZE); | ||
| 116 | ws.outbuf = malloc(G_OUTBUF_SIZE); | ||
| 117 | #ifdef _DEBUG_HTTPERROR | ||
| 118 | ws.debugbuf = malloc(G_DEBUGBUF_SIZE); | ||
| 119 | #endif | ||
| 120 | |||
| 121 | if (!ws.inbuf || !ws.outbuf) | ||
| 122 | panic("Initializing worker failed"); | 113 | panic("Initializing worker failed"); |
| 123 | 114 | ||
| 124 | random_bytes(ws.rand48_state, sizeof(ws.rand48_state)); | ||
| 125 | |||
| 126 | while (g_opentracker_running) { | 115 | while (g_opentracker_running) { |
| 127 | ot_event ready[OT_EVENT_BATCH]; | 116 | ot_event ready[OT_EVENT_BATCH]; |
| 128 | int64_t sock; | 117 | int64_t sock; |
| @@ -173,13 +162,7 @@ static void *server_mainloop(void *args) { | |||
| 173 | 162 | ||
| 174 | /* This work struct is about to go out of scope, so hand its tally over | 163 | /* This work struct is about to go out of scope, so hand its tally over |
| 175 | before anything can read it there */ | 164 | before anything can read it there */ |
| 176 | stats_counters_retire(&ws); | 165 | workstruct_deinit(&ws); |
| 177 | |||
| 178 | free(ws.inbuf); | ||
| 179 | free(ws.outbuf); | ||
| 180 | #ifdef _DEBUG_HTTPERROR | ||
| 181 | free(ws.debugbuf); | ||
| 182 | #endif | ||
| 183 | return 0; | 166 | return 0; |
| 184 | } | 167 | } |
| 185 | 168 | ||
| @@ -188,7 +171,7 @@ static void *server_mainloop(void *args) { | |||
| 188 | member asked for it before binding, the first one included, so whether | 171 | member asked for it before binding, the first one included, so whether |
| 189 | this entry will have workers has to be known here. */ | 172 | this entry will have workers has to be known here. */ |
| 190 | static socket_sharing listen_sharing_for(const ot_listen *entry) { | 173 | static socket_sharing listen_sharing_for(const ot_listen *entry) { |
| 191 | if (entry->proto == FLAG_UDP && entry->workers > 1 && socket_can_balance()) | 174 | if (entry->proto != FLAG_MCA && entry->workers > 1 && socket_can_balance()) |
| 192 | return SOCKET_BALANCED; | 175 | return SOCKET_BALANCED; |
| 193 | return entry->shared ? SOCKET_SHARED : SOCKET_EXCLUSIVE; | 176 | return entry->shared ? SOCKET_SHARED : SOCKET_EXCLUSIVE; |
| 194 | } | 177 | } |
| @@ -244,10 +227,41 @@ static void listen_bind_all(void) { | |||
| 244 | listen_bind_one(entries + i); | 227 | listen_bind_one(entries + i); |
| 245 | } | 228 | } |
| 246 | 229 | ||
| 247 | /* The socket the event loop was using becomes the first worker's. Where the | 230 | /* The socket the event loop was using is passed to the first worker. |
| 248 | kernel spreads datagrams, every further worker binds one of its own, so | 231 | If start up tests show that the kernel can spread connections over |
| 249 | none of them share a receive queue. | 232 | a group bound to one address, every worker binds one of its own. |
| 250 | All others read from the first */ | 233 | If not, all workers call accept on the first. */ |
| 234 | static void listen_start_tcp_workers(void) { | ||
| 235 | size_t count, i; | ||
| 236 | ot_listen *entries = config_listen_entries(&count); | ||
| 237 | |||
| 238 | for (i = 0; i < count; ++i) { | ||
| 239 | ot_listen *entry = entries + i; | ||
| 240 | int balance = listen_sharing_for(entry) == SOCKET_BALANCED; | ||
| 241 | int worker; | ||
| 242 | |||
| 243 | if (entry->proto != FLAG_TCP || entry->workers <= 0) | ||
| 244 | continue; | ||
| 245 | |||
| 246 | event_del((int)entry->sock); | ||
| 247 | tcp_worker_install(entry->sock); | ||
| 248 | |||
| 249 | for (worker = 1; worker < entry->workers; ++worker) { | ||
| 250 | int64_t sock = entry->sock; | ||
| 251 | |||
| 252 | if (balance) { | ||
| 253 | sock = socket_tcp_listen(entry->ip, entry->port, SOCKET_BALANCED); | ||
| 254 | if (sock == -1) { | ||
| 255 | fprintf(stderr, "Warning: could not bind another socket for tcp worker %d: %s. Sharing the first instead.\n", worker, | ||
| 256 | strerror(errno)); | ||
| 257 | sock = entry->sock; | ||
| 258 | } | ||
| 259 | } | ||
| 260 | tcp_worker_install(sock); | ||
| 261 | } | ||
| 262 | } | ||
| 263 | } | ||
| 264 | |||
| 251 | static void listen_start_udp_workers(void) { | 265 | static void listen_start_udp_workers(void) { |
| 252 | size_t count, i; | 266 | size_t count, i; |
| 253 | ot_listen *entries = config_listen_entries(&count); | 267 | ot_listen *entries = config_listen_entries(&count); |
| @@ -408,9 +422,11 @@ int main(int argc, char **argv) { | |||
| 408 | 422 | ||
| 409 | install_signal_handlers(); | 423 | install_signal_handlers(); |
| 410 | 424 | ||
| 425 | listen_start_tcp_workers(); | ||
| 411 | listen_start_udp_workers(); | 426 | listen_start_udp_workers(); |
| 412 | 427 | ||
| 413 | server_mainloop(0); | 428 | server_mainloop(0); |
| 429 | tcp_workers_deinit(); | ||
| 414 | udp_workers_deinit(); | 430 | udp_workers_deinit(); |
| 415 | 431 | ||
| 416 | /* No thread is serving any more, so the teardown can run where a debugger | 432 | /* No thread is serving any more, so the teardown can run where a debugger |
