static void udp_read_cb(EV_P_ ev_io *w, int revents) { supervisor_thread_t *thiz = get_supervisor_thread(); if(thiz) { int th = thiz->next_thread_idx; queue_data_t *data = create_queue_data(); //TODO(nick): this should be in init_queue_data data->addr_len = sizeof(struct sockaddr_in); data->bytes = recvfrom(thiz->sd, data->buffer, sizeof(data->buffer) - 1, 0, (struct sockaddr*) &data->addr, (socklen_t *) &data->addr_len); data->worker_idx = th; size_t len = sizeof(data->worker_idx); if(thiz->config->num_workers == 0) { if(should_echo(data->buffer, data->bytes, &data->addr, thiz->config->filters, thiz->rate_limiter)) { tesr_enqueue(thiz->queue, data, get_thread_string()); LOG_DEBUG("{%s} SENDING NOTIFY MainThread => MainThread\n", get_thread_string()); if (write(thiz->ext_fd, &data->worker_idx, len) != len) { LOG_ERROR("Fail to writing to connection notify pipe\n"); } } } else { tesr_enqueue(thiz->worker_threads[th]->queue, data, get_thread_string()); LOG_DEBUG("{%s} SENDING NOTIFY MainThread => WorkThread[%d]\n", get_thread_string(), th); if (write(thiz->worker_threads[th]->ext_fd, &data->worker_idx, len) != len) { LOG_ERROR("Fail to writing to connection notify pipe\n"); } if(++thiz->next_thread_idx >= thiz->config->num_workers) { thiz->next_thread_idx = 0; } } } }
static void udp_write_cb(EV_P_ ev_io *w, int revents) { LOG_LOC; int idx; size_t len = sizeof(int); supervisor_thread_t *thiz = get_supervisor_thread(); if(thiz) { LOG_DEBUG("{%s} RECVING NOTIFY WorkThread[?] => MainThread\n", get_thread_string()); int ret = read(w->fd, &idx, len); if (ret != len) { LOG_ERROR("Can't read from connection notify pipe\n"); LOG_INFO("[KO] ret = %d != %d len\n", ret, (int)len); } else { LOG_DEBUG("LOC:%d::%s::%s thread = 0x%zx\n", __LINE__, __FILE__, __FUNCTION__, (size_t)pthread_self()); queue_data_t *data = tesr_dequeue(thiz->queue, get_thread_string()); LOG_DEBUG("LOC:%d::%s::%s thread = 0x%zx\n", __LINE__, __FILE__, __FUNCTION__, (size_t)pthread_self()); sendto(thiz->sd, data->buffer, data->bytes, 0, (struct sockaddr*) &data->addr, sizeof(data->addr)); } } }
static void sigint_cb (struct ev_loop *loop, struct ev_signal *w, int revents) { LOG_DEBUG("caught SIGINT!\n"); supervisor_thread_t *thiz = get_supervisor_thread(); if(thiz) { int kill_pill = -1; size_t len = sizeof(kill_pill); ev_io_stop(thiz->event_loop, &thiz->udp_read_watcher); int th = 0; for(th = 0; th < thiz->config->num_workers; th++) { if (write(thiz->worker_threads[th]->ext_fd, &kill_pill, len) != len) { LOG_ERROR("Fail to writing to connection notify pipe\n"); } pthread_join(thiz->worker_threads[th]->thread, NULL); LOG_DEBUG("{%s} JOINED\n", get_thread_string()); } //ev_unloop(supervisor_thread->event_loop, EVUNLOOP_ONE); ev_unloop(thiz->event_loop, EVUNLOOP_ALL); } }
bool _check_allocated(int idx) { int i = idx_decode(next_free.load()); int last = -1; while( i != -1 ) { if( idx == i ) { tprintf(tinfra::err, "T[%i]: _check_allocated(%i) fails, because (%i->%i)\n", get_thread_string(), idx, last, idx); _check_for_loops(); return false; } last = i; i = item_next_free_idx(i); } return true; }
bool _check_for_loops() { std::vector<int> visited_stream; std::map<int, size_t> when_visited; // (v at k) say, that k is already visited at position v int idx = idx_decode(next_free.load()); int last = -1; while( idx != -1 ) { if( when_visited.find(idx) != when_visited.end() ) { // we've already seen this value, so WE HAVE LOOP tprintf(tinfra::err, "T[%i]: _check_for_loops %i->%i is a loop, whole vector\n", get_thread_string(), last, idx, vector_to_string(visited_stream)); return false; } when_visited[idx] = visited_stream.size(); visited_stream.push_back(idx); last = idx; idx = item_next_free_idx(idx); } return true; }