Ejemplo n.º 1
0
/*
 * This function temporarily disables listening so that another new instance
 * can start listening. It is designed to be called upon reception of a
 * SIGTTOU, after which either a SIGUSR1 can be sent to completely stop
 * the proxy, or a SIGTTIN can be sent to listen again.
 */
void pause_proxies(void)
{
	int err;
	struct proxy *p;

	err = 0;
	p = proxy;
	tv_update_date(0,1); /* else, the old time before select will be used */
	while (p) {
		if (p->cap & PR_CAP_FE &&
		    p->state != PR_STERROR &&
		    p->state != PR_STSTOPPED &&
		    p->state != PR_STPAUSED) {
			Warning("Pausing %s %s.\n", proxy_cap_str(p->cap), p->id);
			send_log(p, LOG_WARNING, "Pausing %s %s.\n", proxy_cap_str(p->cap), p->id);
			pause_proxy(p);
			if (p->state != PR_STPAUSED) {
				err |= 1;
				Warning("%s %s failed to enter pause mode.\n", proxy_cap_str(p->cap), p->id);
				send_log(p, LOG_WARNING, "%s %s failed to enter pause mode.\n", proxy_cap_str(p->cap), p->id);
			}
		}
		p = p->next;
	}
	if (err) {
		Warning("Some proxies refused to pause, performing soft stop now.\n");
		send_log(p, LOG_WARNING, "Some proxies refused to pause, performing soft stop now.\n");
		soft_stop();
	}
}
Ejemplo n.º 2
0
/*
 * This function reactivates listening. This can be used after a call to
 * sig_pause(), for example when a new instance has failed starting up.
 * It is designed to be called upon reception of a SIGTTIN.
 */
void resume_proxies(void)
{
	int err;
	struct proxy *p;
	struct peers *prs;

	err = 0;
	p = proxy;
	tv_update_date(0,1); /* else, the old time before select will be used */
	while (p) {
		err |= !resume_proxy(p);
		p = p->next;
	}

	prs = peers;
	while (prs) {
		p = prs->peers_fe;
		err |= !resume_proxy(p);
		prs = prs->next;
        }

	if (err) {
		Warning("Some proxies refused to resume, a restart is probably needed to resume safe operations.\n");
		send_log(p, LOG_WARNING, "Some proxies refused to resume, a restart is probably needed to resume safe operations.\n");
	}
}
Ejemplo n.º 3
0
/*
 * This function temporarily disables listening so that another new instance
 * can start listening. It is designed to be called upon reception of a
 * SIGTTOU, after which either a SIGUSR1 can be sent to completely stop
 * the proxy, or a SIGTTIN can be sent to listen again.
 */
void pause_proxies(void)
{
	int err;
	struct proxy *p;
	struct peers *prs;

	err = 0;
	p = proxy;
	tv_update_date(0,1); /* else, the old time before select will be used */
	while (p) {
		err |= !pause_proxy(p);
		p = p->next;
	}

	prs = peers;
	while (prs) {
		p = prs->peers_fe;
		err |= !pause_proxy(p);
		prs = prs->next;
        }

	if (err) {
		Warning("Some proxies refused to pause, performing soft stop now.\n");
		send_log(p, LOG_WARNING, "Some proxies refused to pause, performing soft stop now.\n");
		soft_stop();
	}
}
Ejemplo n.º 4
0
/*
 * this function disables health-check servers so that the process will quickly be ignored
 * by load balancers. Note that if a proxy was already in the PAUSED state, then its grace
 * time will not be used since it would already not listen anymore to the socket.
 */
void soft_stop(void)
{
	struct proxy *p;
	struct peers *prs;

	stopping = 1;
	p = proxy;
	tv_update_date(0,1); /* else, the old time before select will be used */
	while (p) {
		if (p->state != PR_STSTOPPED) {
			Warning("Stopping %s %s in %d ms.\n", proxy_cap_str(p->cap), p->id, p->grace);
			send_log(p, LOG_WARNING, "Stopping %s %s in %d ms.\n", proxy_cap_str(p->cap), p->id, p->grace);
			p->stop_time = tick_add(now_ms, p->grace);
		}
		if (p->table.size && p->table.sync_task)
			 task_wakeup(p->table.sync_task, TASK_WOKEN_MSG);

		/* wake every proxy task up so that they can handle the stopping */
		task_wakeup(p->task, TASK_WOKEN_MSG);
		p = p->next;
	}

	prs = peers;
	while (prs) {
		stop_proxy((struct proxy *)prs->peers_fe);
		prs = prs->next;
	}
	/* signal zero is used to broadcast the "stopping" event */
	signal_handler(0);
}
Ejemplo n.º 5
0
/*
 * This function reactivates listening. This can be used after a call to
 * sig_pause(), for example when a new instance has failed starting up.
 * It is designed to be called upon reception of a SIGTTIN.
 */
void listen_proxies(void)
{
	struct proxy *p;
	struct listener *l;

	p = proxy;
	tv_update_date(0,1); /* else, the old time before select will be used */
	while (p) {
		if (p->state == PR_STPAUSED) {
			Warning("Enabling %s %s.\n", proxy_cap_str(p->cap), p->id);
			send_log(p, LOG_WARNING, "Enabling %s %s.\n", proxy_cap_str(p->cap), p->id);

			for (l = p->listen; l != NULL; l = l->next) {
				if (listen(l->fd, p->backlog ? p->backlog : p->maxconn) == 0) {
					if (actconn < global.maxconn && p->feconn < p->maxconn) {
						EV_FD_SET(l->fd, DIR_RD);
						p->state = PR_STRUN;
					}
					else
						p->state = PR_STIDLE;
				} else {
					int port;

					if (l->addr.ss_family == AF_INET6) {
						port = ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port);
						Warning("Port %d busy while trying to enable %s %s.\n",
							port, proxy_cap_str(p->cap), p->id);
						send_log(p, LOG_WARNING, "Port %d busy while trying to enable %s %s.\n",
							 port, proxy_cap_str(p->cap), p->id);
					}
					else if (l->addr.ss_family == AF_INET) {
						port = ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
						Warning("Port %d busy while trying to enable %s %s.\n",
							port, proxy_cap_str(p->cap), p->id);
						send_log(p, LOG_WARNING, "Port %d busy while trying to enable %s %s.\n",
							 port, proxy_cap_str(p->cap), p->id);
					}
					else {
						Warning("Bind on socket %d busy while trying to enable %s %s.\n",
							l->luid, proxy_cap_str(p->cap), p->id);
						send_log(p, LOG_WARNING, "Bind on socket %d busy while trying to enable %s %s.\n",
							 l->luid, proxy_cap_str(p->cap), p->id);
					}

					/* Another port might have been enabled. Let's stop everything. */
					pause_proxy(p);
					break;
				}
			}
		}
		p = p->next;
	}
}
Ejemplo n.º 6
0
/*
 * this function disables health-check servers so that the process will quickly be ignored
 * by load balancers. Note that if a proxy was already in the PAUSED state, then its grace
 * time will not be used since it would already not listen anymore to the socket.
 */
void soft_stop(void)
{
	struct proxy *p;

	stopping = 1;
	p = proxy;
	tv_update_date(0,1); /* else, the old time before select will be used */
	while (p) {
		if (p->state != PR_STSTOPPED) {
			Warning("Stopping %s %s in %d ms.\n", proxy_cap_str(p->cap), p->id, p->grace);
			send_log(p, LOG_WARNING, "Stopping %s %s in %d ms.\n", proxy_cap_str(p->cap), p->id, p->grace);
			p->stop_time = tick_add(now_ms, p->grace);
		}
		p = p->next;
	}
}
Ejemplo n.º 7
0
REGPRM3 static void _do_poll(struct poller *p, int exp, int wake)
{
	int i;
	int wait_time;
	struct timespec timeout_ts;
	unsigned int nevlist;
	int fd, old_fd;
	int status;

	/*
	 * Scan the list of file descriptors with an updated status:
	 */
	for (i = 0; i < fd_nbupdt; i++) {
		fd = fd_updt[i];

		_HA_ATOMIC_AND(&fdtab[fd].update_mask, ~tid_bit);
		if (fdtab[fd].owner == NULL) {
			activity[tid].poll_drop++;
			continue;
		}

		_update_fd(fd);
	}
	fd_nbupdt = 0;
	/* Scan the global update list */
	for (old_fd = fd = update_list.first; fd != -1; fd = fdtab[fd].update.next) {
		if (fd == -2) {
			fd = old_fd;
			continue;
		}
		else if (fd <= -3)
			fd = -fd -4;
		if (fd == -1)
			break;
		if (fdtab[fd].update_mask & tid_bit)
			done_update_polling(fd);
		else
			continue;
		if (!fdtab[fd].owner)
			continue;
		_update_fd(fd);
	}

	thread_harmless_now();

	/*
	 * Determine how long to wait for events to materialise on the port.
	 */
	wait_time = wake ? 0 : compute_poll_timeout(exp);
	tv_entering_poll();
	activity_count_runtime();

	do {
		int timeout = (global.tune.options & GTUNE_BUSY_POLLING) ? 0 : wait_time;
		int interrupted = 0;
		nevlist = 1; /* desired number of events to be retrieved */
		timeout_ts.tv_sec  = (timeout / 1000);
		timeout_ts.tv_nsec = (timeout % 1000) * 1000000;

		status = port_getn(evports_fd[tid],
				   evports_evlist,
				   evports_evlist_max,
				   &nevlist, /* updated to the number of events retrieved */
				   &timeout_ts);
		if (status != 0) {
			int e = errno;
			switch (e) {
			case ETIME:
				/*
				 * Though the manual page has not historically made it
				 * clear, port_getn() can return -1 with an errno of
				 * ETIME and still have returned some number of events.
				 */
				/* nevlist >= 0 */
				break;
			default:
				nevlist = 0;
				interrupted = 1;
				break;
			}
		}
		tv_update_date(timeout, nevlist);

		if (nevlist || interrupted)
			break;
		if (timeout || !wait_time)
			break;
		if (signal_queue_len || wake)
			break;
		if (tick_isset(exp) && tick_is_expired(exp, now_ms))
			break;
	} while(1);

	tv_leaving_poll(wait_time, nevlist);

	thread_harmless_end();

	for (i = 0; i < nevlist; i++) {
		unsigned int n = 0;
		int events, rebind_events;
		fd = evports_evlist[i].portev_object;
		events = evports_evlist[i].portev_events;

		if (fdtab[fd].owner == NULL) {
			activity[tid].poll_dead++;
			continue;
		}

		if (!(fdtab[fd].thread_mask & tid_bit)) {
			activity[tid].poll_skip++;
			continue;
		}

		/*
		 * By virtue of receiving an event for this file descriptor, it
		 * is no longer associated with the port in question.  Store
		 * the previous event mask so that we may reassociate after
		 * processing is complete.
		 */
		rebind_events = evports_state_to_events(fdtab[fd].state);
		/* rebind_events != 0 */

		/*
		 * Set bits based on the events we received from the port:
		 */
		if (events & POLLIN)
			n |= FD_POLL_IN;
		if (events & POLLOUT)
			n |= FD_POLL_OUT;
		if (events & POLLERR)
			n |= FD_POLL_ERR;
		if (events & POLLHUP)
			n |= FD_POLL_HUP;

		/*
		 * Call connection processing callbacks.  Note that it's
		 * possible for this processing to alter the required event
		 * port assocation; i.e., the "state" member of the "fdtab"
		 * entry.  If it changes, the fd will be placed on the updated
		 * list for processing the next time we are called.
		 */
		fd_update_events(fd, n);

		/*
		 * This file descriptor was closed during the processing of
		 * polled events.  No need to reassociate.
		 */
		if (fdtab[fd].owner == NULL)
			continue;

		/*
		 * Reassociate with the port, using the same event mask as
		 * before.  This call will not result in a dissociation as we
		 * asserted that _some_ events needed to be rebound above.
		 *
		 * Reassociating with the same mask allows us to mimic the
		 * level-triggered behaviour of poll(2).  In the event that we
		 * are interested in the same events on the next turn of the
		 * loop, this represents no extra work.
		 *
		 * If this additional port_associate(3C) call becomes a
		 * performance problem, we would need to verify that we can
		 * correctly interact with the file descriptor cache and update
		 * list (see "src/fd.c") to avoid reassociating here, or to use
		 * a different events mask.
		 */
		evports_resync_fd(fd, rebind_events);
	}
}
Ejemplo n.º 8
0
void * fio_count(void *data)
{
    int i;
    uint64_t my_rxcount = 0, my_txcount = 0, unuse_count = 0, prev_rx = 0, prev_tx = 0;
    struct timeval tic, toc;
    int report_interval = 1*1000;	/* report interval */
    char dump_buf_rx[2000] = {0};
    char dump_buf_tx[2000] = {0};
    char dump_buf[1000] = {0};
	
	g_logfac = syslog_get_facility(g_str_logfac);
    g_log_host_name = sysconfig.src_ip.name;

    int bucfd = buc_open(sysconfig.dst_ip[0].name, sysconfig.src_port);
    if (bucfd == -1)
        return NULL;

    gettimeofday(&toc, NULL);
    while (sysconfig.working)
    {
        struct timeval delta;
        uint64_t pps_rx, pps_tx;
        int done = 0;
        dump_buf_rx[0] = '\0';
        dump_buf_tx[0] = '\0';

        delta.tv_sec = report_interval/1000;
        delta.tv_usec = (report_interval%1000)*1000;

        //计时== 
        select(0, NULL, NULL, NULL, &delta);

        tv_update_date();
        timersub(&fio_now, &toc, &toc);
        my_rxcount = 0;
        my_txcount = 0;
        unuse_count = 0;
        for (i = 0; i < sysconfig.nthreads; i++) {
            my_rxcount += g_contexts[i].nics[0].rxcount;
            my_rxcount += g_contexts[i].nics[1].rxcount;
            my_txcount += g_contexts[i].nics[0].txcount;
            my_txcount += g_contexts[i].nics[1].txcount;
            unuse_count += g_contexts[i].nics[0].unuse_count;
            unuse_count += g_contexts[i].nics[1].unuse_count;
            sprintf(dump_buf, "%"LU64" ", g_contexts[i].nics[0].rxcount 
                    + g_contexts[i].nics[1].rxcount);
            strcat(dump_buf_rx, dump_buf);
            sprintf(dump_buf, "%"LU64" ", g_contexts[i].nics[0].txcount
                    + g_contexts[i].nics[1].txcount);
            strcat(dump_buf_tx, dump_buf);
            if (g_contexts[i].used == 0)
                done++;
        }
        pps_tx = pps_rx = toc.tv_sec* 1000000 + toc.tv_usec;
        if (pps_rx < 10000)
            continue;
        pps_rx = (my_rxcount - prev_rx)*1000000 / pps_rx;
        OD( "rx %"LU64" ppsrx %s", pps_rx, dump_buf_rx);
        pps_tx = (my_txcount - prev_tx)*1000000 / pps_tx;
        OD( "tx %"LU64" ppstx %s", pps_tx, dump_buf_tx);
        OD( "rx useless pkt %"LU64"\n", unuse_count);
        syslog_format(bucfd, "rx %"LU64" ppsrx %s\ntx %"LU64" ppstx %s\nrx useless pkt %"LU64,
                pps_rx, dump_buf_rx, pps_tx, dump_buf_tx, unuse_count);
        prev_rx = my_rxcount;
        prev_tx = my_txcount;
        toc = fio_now;
        fio_gnow++;
        if (done == sysconfig.nthreads)
            break;
    }

    timerclear(&tic);
    timerclear(&toc);
    OD( "I'll shutdown");

    return NULL;
}
Ejemplo n.º 9
0
/*
 * Linux epoll() poller
 */
REGPRM2 static void _do_poll(struct poller *p, int exp)
{
	int status;
	int fd;
	int count;
	int updt_idx;
	int wait_time;
	int old_fd;

	/* first, scan the update list to find polling changes */
	for (updt_idx = 0; updt_idx < fd_nbupdt; updt_idx++) {
		fd = fd_updt[updt_idx];

		HA_ATOMIC_AND(&fdtab[fd].update_mask, ~tid_bit);
		if (!fdtab[fd].owner) {
			activity[tid].poll_drop++;
			continue;
		}

		_update_fd(fd);
	}
	fd_nbupdt = 0;
	/* Scan the global update list */
	for (old_fd = fd = update_list.first; fd != -1; fd = fdtab[fd].update.next) {
		if (fd == -2) {
			fd = old_fd;
			continue;
		}
		else if (fd <= -3)
			fd = -fd -4;
		if (fd == -1)
			break;
		if (fdtab[fd].update_mask & tid_bit)
			done_update_polling(fd);
		else
			continue;
		if (!fdtab[fd].owner)
			continue;
		_update_fd(fd);
	}

	thread_harmless_now();

	/* compute the epoll_wait() timeout */
	if (!exp)
		wait_time = MAX_DELAY_MS;
	else if (tick_is_expired(exp, now_ms)) {
		activity[tid].poll_exp++;
		wait_time = 0;
	}
	else {
		wait_time = TICKS_TO_MS(tick_remain(now_ms, exp)) + 1;
		if (wait_time > MAX_DELAY_MS)
			wait_time = MAX_DELAY_MS;
	}

	/* now let's wait for polled events */

	gettimeofday(&before_poll, NULL);
	status = epoll_wait(epoll_fd[tid], epoll_events, global.tune.maxpollevents, wait_time);
	tv_update_date(wait_time, status);
	measure_idle();

	thread_harmless_end();

	/* process polled events */

	for (count = 0; count < status; count++) {
		unsigned int n;
		unsigned int e = epoll_events[count].events;
		fd = epoll_events[count].data.fd;

		if (!fdtab[fd].owner) {
			activity[tid].poll_dead++;
			continue;
		}

		if (!(fdtab[fd].thread_mask & tid_bit)) {
			/* FD has been migrated */
			activity[tid].poll_skip++;
			epoll_ctl(epoll_fd[tid], EPOLL_CTL_DEL, fd, &ev);
			HA_ATOMIC_AND(&polled_mask[fd], ~tid_bit);
			continue;
		}

		/* it looks complicated but gcc can optimize it away when constants
		 * have same values... In fact it depends on gcc :-(
		 */
		if (EPOLLIN == FD_POLL_IN && EPOLLOUT == FD_POLL_OUT &&
		    EPOLLPRI == FD_POLL_PRI && EPOLLERR == FD_POLL_ERR &&
		    EPOLLHUP == FD_POLL_HUP) {
			n = e & (EPOLLIN|EPOLLOUT|EPOLLPRI|EPOLLERR|EPOLLHUP);
		}
		else {
			n =	((e & EPOLLIN ) ? FD_POLL_IN  : 0) |
				((e & EPOLLPRI) ? FD_POLL_PRI : 0) |
				((e & EPOLLOUT) ? FD_POLL_OUT : 0) |
				((e & EPOLLERR) ? FD_POLL_ERR : 0) |
				((e & EPOLLHUP) ? FD_POLL_HUP : 0);
		}

		/* always remap RDHUP to HUP as they're used similarly */
		if (e & EPOLLRDHUP) {
			HA_ATOMIC_OR(&cur_poller.flags, HAP_POLL_F_RDHUP);
			n |= FD_POLL_HUP;
		}
		fd_update_events(fd, n);
	}
	/* the caller will take care of cached events */
}