summaryrefslogtreecommitdiff
path: root/opentracker.c
diff options
context:
space:
mode:
Diffstat (limited to 'opentracker.c')
-rw-r--r--opentracker.c73
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. */
190static socket_sharing listen_sharing_for(const ot_listen *entry) { 177static 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. */
238static 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
251static void listen_start_udp_workers(void) { 269static 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 */