/* Pure Load Balancer - (C)opyleft 2003 Jedi/Sector One <j@pureftpd.org> */
#include <config.h>
#include "plb.h"
#include "plb_globals.h"
#ifdef WITH_DMALLOC
# include <dmalloc.h>
#endif
void cleanup_connect_ready(int evfd, short event, void *cleaned_server_)
{
Server * const cleaned_server = (Server *) cleaned_server_;
plb_log(LL_DEBUG, "Starting async cleanup");
(void) evfd;
if (cleaned_server->cleanup_fd == -1) {
return;
}
if (event == EV_WRITE) {
ssize_t written;
while ((written = write(cleaned_server->cleanup_fd, "", (size_t) 1U))
!= 1U && errno == EINTR);
if (written == (ssize_t) 1U) {
cleaned_server->status = 1U;
plb_log(LL_WARNING, "Bringing [%s] back to life",
cleaned_server->name);
} else {
plb_log(LL_DEBUG, "[%s] probe failure", cleaned_server->name);
}
}
while (close(cleaned_server->cleanup_fd) != 0 && errno == EINTR);
cleaned_server->cleanup_fd = -1;
}
void spawn_cleanup(Server * const cleaned_server)
{
int cleanup_fd;
if (cleaned_server->cleanup_fd != -1) {
plb_log(LL_DEBUG, "Cleanup already in progress, fd=[%d]",
cleaned_server->cleanup_fd);
return;
}
cleaned_server->cleanup_fd = -1;
if ((cleanup_fd = socket(cleaned_server->ai_family,
SOCK_STREAM, IPPROTO_TCP)) == -1) {
plb_log(LL_WARNING, "Unable to create a cleanup socket : [%s]",
strerror(errno));
return;
}
setsockopt_aggressive(cleanup_fd);
socket_nonblock(cleanup_fd);
for (;;) {
if (connect(cleanup_fd,
(struct sockaddr *) &cleaned_server->ai_addr,
(socklen_t) cleaned_server->ai_addrlen) != 0 &&
errno != EINPROGRESS) {
if (errno == EINTR) {
continue;
}
plb_log(LL_NOTIFY, "Cleanup socket didn't connect() : [%s]",
strerror(errno));
while (close(cleanup_fd) != 0 && errno == EINTR);
return;
}
break;
}
cleaned_server->cleanup_fd = cleanup_fd;
plb_log(LL_DEBUG, "Should spawn async health checking fd:[%d]",
cleanup_fd);
event_set(&cleaned_server->cleanup_ev, cleanup_fd, EV_WRITE | EV_TIMEOUT,
cleanup_connect_ready, cleaned_server);
event_add(&cleaned_server->cleanup_ev, &timeout_header_server_write);
}
void periodic_cleanup(int dummy, const short event, void *ev)
{
register Server *cleaned_server;
(void) dummy;
(void) event;
if ((cleaned_server = serverpool_head) == NULL) {
plb_log(LL_ERROR, "No server pool");
return;
}
do {
if (cleaned_server->status <= 0U) {
spawn_cleanup(cleaned_server);
}
} while ((cleaned_server = cleaned_server->next) != NULL);
evtimer_add((struct event *) ev, &timeout_cleanup);
}
syntax highlighted by Code2HTML, v. 0.9.1