diff options
Diffstat (limited to 'opentracker.c')
| -rw-r--r-- | opentracker.c | 73 |
1 files changed, 46 insertions, 27 deletions
diff --git a/opentracker.c b/opentracker.c index 2eaf988..644e99c 100644 --- a/opentracker.c +++ b/opentracker.c | |||
| @@ -29,6 +29,7 @@ | |||
| 29 | #include "ot_ip.h" | 29 | #include "ot_ip.h" |
| 30 | #include "ot_livesync.h" | 30 | #include "ot_livesync.h" |
| 31 | #include "ot_mutex.h" | 31 | #include "ot_mutex.h" |
| 32 | #include "ot_workqueue.h" | ||
| 32 | #include "ot_random.h" | 33 | #include "ot_random.h" |
| 33 | #include "ot_scan.h" | 34 | #include "ot_scan.h" |
| 34 | #include "ot_event.h" | 35 | #include "ot_event.h" |
| @@ -37,6 +38,7 @@ | |||
| 37 | #include "ot_stats.h" | 38 | #include "ot_stats.h" |
| 38 | #include "ot_tcp.h" | 39 | #include "ot_tcp.h" |
| 39 | #include "ot_udp.h" | 40 | #include "ot_udp.h" |
| 41 | #include "ot_worker.h" | ||
| 40 | #include "trackerlogic.h" | 42 | #include "trackerlogic.h" |
| 41 | 43 | ||
| 42 | /* Globals */ | 44 | /* Globals */ |
| @@ -109,20 +111,9 @@ static void *server_mainloop(void *args) { | |||
| 109 | 111 | ||
| 110 | (void)args; | 112 | (void)args; |
| 111 | 113 | ||
| 112 | /* Initialize our "thread local storage" */ | 114 | 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"); | 115 | panic("Initializing worker failed"); |
| 123 | 116 | ||
| 124 | random_bytes(ws.rand48_state, sizeof(ws.rand48_state)); | ||
| 125 | |||
| 126 | while (g_opentracker_running) { | 117 | while (g_opentracker_running) { |
| 127 | ot_event ready[OT_EVENT_BATCH]; | 118 | ot_event ready[OT_EVENT_BATCH]; |
| 128 | int64_t sock; | 119 | int64_t sock; |
| @@ -148,16 +139,18 @@ static void *server_mainloop(void *args) { | |||
| 148 | else if ((intptr_t)cookie == FLAG_SELFPIPE) | 139 | else if ((intptr_t)cookie == FLAG_SELFPIPE) |
| 149 | while (read((int)sock, ws.inbuf, G_INBUF_SIZE) > 0) | 140 | while (read((int)sock, ws.inbuf, G_INBUF_SIZE) > 0) |
| 150 | ; | 141 | ; |
| 151 | else { | 142 | else if (fdstate_claim((int)sock, ready[i].generation)) { |
| 152 | if (ready[i].what & EVENT_IN) | 143 | if (ready[i].what & EVENT_IN) |
| 153 | tcp_read(sock, &ws); | 144 | tcp_read(sock, &ws); |
| 154 | /* The read may have closed it, so look again before writing */ | 145 | /* The read may have closed it, so look again before writing */ |
| 155 | if ((ready[i].what & EVENT_OUT) && fdstate_generation((int)sock) == ready[i].generation) | 146 | if ((ready[i].what & EVENT_OUT) && fdstate_generation((int)sock) == ready[i].generation) |
| 156 | tcp_write(sock); | 147 | tcp_write(sock); |
| 148 | if (fdstate_generation((int)sock) == ready[i].generation) | ||
| 149 | fdstate_release((int)sock); | ||
| 157 | } | 150 | } |
| 158 | } | 151 | } |
| 159 | 152 | ||
| 160 | while ((sock = mutex_workqueue_popresult(&iovec_entries, &iovector, &is_partial)) != -1) | 153 | while ((sock = workqueue_popresult(&iovec_entries, &iovector, &is_partial)) != -1) |
| 161 | http_sendiovecdata(sock, &ws, iovec_entries, iovector, is_partial); | 154 | http_sendiovecdata(sock, &ws, iovec_entries, iovector, is_partial); |
| 162 | 155 | ||
| 163 | if (time_now_seconds() > next_timeout_check) { | 156 | if (time_now_seconds() > next_timeout_check) { |
| @@ -173,13 +166,7 @@ static void *server_mainloop(void *args) { | |||
| 173 | 166 | ||
| 174 | /* This work struct is about to go out of scope, so hand its tally over | 167 | /* This work struct is about to go out of scope, so hand its tally over |
| 175 | before anything can read it there */ | 168 | before anything can read it there */ |
| 176 | stats_counters_retire(&ws); | 169 | 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; | 170 | return 0; |
| 184 | } | 171 | } |
| 185 | 172 | ||
| @@ -188,7 +175,7 @@ static void *server_mainloop(void *args) { | |||
| 188 | member asked for it before binding, the first one included, so whether | 175 | member asked for it before binding, the first one included, so whether |
| 189 | this entry will have workers has to be known here. */ | 176 | this entry will have workers has to be known here. */ |
| 190 | static socket_sharing listen_sharing_for(const ot_listen *entry) { | 177 | static socket_sharing listen_sharing_for(const ot_listen *entry) { |
| 191 | if (entry->proto == FLAG_UDP && entry->workers > 1 && socket_can_balance()) | 178 | if (entry->proto != FLAG_MCA && entry->workers > 1 && socket_can_balance()) |
| 192 | return SOCKET_BALANCED; | 179 | return SOCKET_BALANCED; |
| 193 | return entry->shared ? SOCKET_SHARED : SOCKET_EXCLUSIVE; | 180 | return entry->shared ? SOCKET_SHARED : SOCKET_EXCLUSIVE; |
| 194 | } | 181 | } |
| @@ -244,10 +231,41 @@ static void listen_bind_all(void) { | |||
| 244 | listen_bind_one(entries + i); | 231 | listen_bind_one(entries + i); |
| 245 | } | 232 | } |
| 246 | 233 | ||
| 247 | /* The socket the event loop was using becomes the first worker's. Where the | 234 | /* 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 | 235 | If start up tests show that the kernel can spread connections over |
| 249 | none of them share a receive queue. | 236 | a group bound to one address, every worker binds one of its own. |
| 250 | All others read from the first */ | 237 | If not, all workers call accept on the first. */ |
| 238 | static void listen_start_tcp_workers(void) { | ||
| 239 | size_t count, i; | ||
| 240 | ot_listen *entries = config_listen_entries(&count); | ||
| 241 | |||
| 242 | for (i = 0; i < count; ++i) { | ||
| 243 | ot_listen *entry = entries + i; | ||
| 244 | int balance = listen_sharing_for(entry) == SOCKET_BALANCED; | ||
| 245 | int worker; | ||
| 246 | |||
| 247 | if (entry->proto != FLAG_TCP || entry->workers <= 0) | ||
| 248 | continue; | ||
| 249 | |||
| 250 | event_del((int)entry->sock); | ||
| 251 | tcp_worker_install(entry->sock); | ||
| 252 | |||
| 253 | for (worker = 1; worker < entry->workers; ++worker) { | ||
| 254 | int64_t sock = entry->sock; | ||
| 255 | |||
| 256 | if (balance) { | ||
| 257 | sock = socket_tcp_listen(entry->ip, entry->port, SOCKET_BALANCED); | ||
| 258 | if (sock == -1) { | ||
| 259 | fprintf(stderr, "Warning: could not bind another socket for tcp worker %d: %s. Sharing the first instead.\n", worker, | ||
| 260 | strerror(errno)); | ||
| 261 | sock = entry->sock; | ||
| 262 | } | ||
| 263 | } | ||
| 264 | tcp_worker_install(sock); | ||
| 265 | } | ||
| 266 | } | ||
| 267 | } | ||
| 268 | |||
| 251 | static void listen_start_udp_workers(void) { | 269 | static void listen_start_udp_workers(void) { |
| 252 | size_t count, i; | 270 | size_t count, i; |
| 253 | ot_listen *entries = config_listen_entries(&count); | 271 | ot_listen *entries = config_listen_entries(&count); |
| @@ -408,10 +426,11 @@ int main(int argc, char **argv) { | |||
| 408 | 426 | ||
| 409 | install_signal_handlers(); | 427 | install_signal_handlers(); |
| 410 | 428 | ||
| 429 | listen_start_tcp_workers(); | ||
| 411 | listen_start_udp_workers(); | 430 | listen_start_udp_workers(); |
| 412 | 431 | ||
| 413 | server_mainloop(0); | 432 | server_mainloop(0); |
| 414 | udp_workers_deinit(); | 433 | worker_stop_all(); |
| 415 | 434 | ||
| 416 | /* No thread is serving any more, so the teardown can run where a debugger | 435 | /* No thread is serving any more, so the teardown can run where a debugger |
| 417 | and the sanitizers can follow it */ | 436 | and the sanitizers can follow it */ |
