예제 #1
0
파일: tcp-handler.c 프로젝트: idtek/knot
static int tcp_wait_for_events(tcp_context_t *tcp)
{
	/* Wait for events. */
	fdset_t *set = &tcp->set;
	int nfds = poll(set->pfd, set->n, TCP_SWEEP_INTERVAL * 1000);

	/* Mark the time of last poll call. */
	time_now(&tcp->last_poll_time);
	bool is_throttled = (tcp->last_poll_time.tv_sec < tcp->throttle_end.tv_sec);
	if (!is_throttled) {
		/* Configuration limit, infer maximal pool size. */
		rcu_read_lock();
		conf_val_t *val = &conf()->cache.srv_max_tcp_clients;
		unsigned max_per_set = MAX(conf_int(val) / conf_tcp_threads(conf()), 1);
		rcu_read_unlock();
		/* Subtract master sockets check limits. */
		is_throttled = (set->n - tcp->client_threshold) >= max_per_set;
	}

	/* Process events. */
	unsigned i = 0;
	while (nfds > 0 && i < set->n) {
		bool should_close = false;
		int fd = set->pfd[i].fd;
		if (set->pfd[i].revents & (POLLERR|POLLHUP|POLLNVAL)) {
			should_close = (i >= tcp->client_threshold);
			--nfds;
		} else if (set->pfd[i].revents & (POLLIN)) {
			/* Master sockets */
			if (i < tcp->client_threshold) {
				if (!is_throttled && tcp_event_accept(tcp, i) == KNOT_EBUSY) {
					time_now(&tcp->throttle_end);
					tcp->throttle_end.tv_sec += tcp_throttle();
				}
			/* Client sockets */
			} else {
				if (tcp_event_serve(tcp, i) != KNOT_EOK) {
					should_close = true;
				}
			}
			--nfds;
		}

		/* Evaluate */
		if (should_close) {
			fdset_remove(set, i);
			close(fd);
		} else {
			++i;
		}
	}

	return nfds;
}
예제 #2
0
static int tcp_wait_for_events(tcp_context_t *tcp)
{
	/* Wait for events. */
	fdset_t *set = &tcp->set;
	int nfds = poll(set->pfd, set->n, TCP_SWEEP_INTERVAL * 1000);

	/* Mark the time of last poll call. */
	time_now(&tcp->last_poll_time);

	/* Process events. */
	unsigned i = 0;
	while (nfds > 0 && i < set->n) {

		/* Terminate faulty connections. */
		int fd = set->pfd[i].fd;

		/* Active sockets. */
		if (set->pfd[i].revents & POLLIN) {
			--nfds; /* One less active event. */

			/* Indexes <0, client_threshold) are master sockets. */
			if (i < tcp->client_threshold) {
				/* Faulty master sockets shall be sorted later. */
				(void) tcp_event_accept(tcp, i);
			} else {
				if (tcp_event_serve(tcp, i) != KNOT_EOK) {
					fdset_remove(set, i);
					close(fd);
					continue; /* Stay on the same index. */
				}
			}

		}

		if (set->pfd[i].revents & (POLLERR|POLLHUP|POLLNVAL)) {
			--nfds; /* One less active event. */
			fdset_remove(set, i);
			close(fd);
			continue; /* Stay on the same index. */
		}

		/* Next socket. */
		++i;
	}

	return nfds;
}