Example #1
0
/*
 * run whole select(2) loop.
 *
 * RETURN VALUE:
 *  0: All events are processed, and no event is remaining in the queue.
 *  EDEADLK: no watching file descriptor is requested, and any timer event
 *	isn't specified, either. This means infinite sleep.
 *  ETIMEDOUT: timeout happened.
 *  otherwise: select(2) failed, return value shows the `errno' of
 *	the select(2).
 */
int
gfarm_eventqueue_loop(struct gfarm_eventqueue *q,
	const struct timeval *timeo)
{
	struct timeval limit, now, timeout_value, *timeout = NULL;
	int rv;

	if (timeo != NULL) {
		gettimeofday(&limit, NULL);
		gfarm_timeval_add(&limit, timeo);
		now = limit;
		timeout = &timeout_value;
	}
	for (;;) {
		if (timeout != NULL) {
			*timeout = limit;
			gfarm_timeval_sub(timeout, &now);
		}
		rv = gfarm_eventqueue_turn(q, timeout);
		if (rv == 0)
			return (0); /* completed */
		if (rv != EAGAIN && rv != EINTR)
			return (rv); /* probably program logic is wrong */
		if (timeout != NULL) {
			gettimeofday(&now, NULL);
			if (gfarm_timeval_cmp(&now, &limit) >= 0)
				return (ETIMEDOUT); /* timeout */
		}
	}
}
Example #2
0
gfarm_error_t
gfarm_paraccess_request(struct gfarm_paraccess *pa,
	void *closure, char *canonical_hostname, int port,
	struct sockaddr *peer_addr)
{
	int rv;
	gfarm_error_t e;
	struct gfarm_access *a;
	struct gfs_client_get_load_state *gls;

	/*
	 * Wait until at least one slot becomes available.
	 * We limit concurrency here.
	 */
	while (pa->free_list == NULL) {
		rv = gfarm_eventqueue_turn(pa->q, NULL);
		if (rv == EAGAIN || rv == EINTR) {
			continue; /* not really an error */
		} else if (rv != 0) {
			return (gfarm_errno_to_error(rv));
		}
	}	

	/* acquire free slot */
	a = pa->free_list;
	pa->free_list = a->next;
	--pa->nfree;

	a->closure = closure;
	a->canonical_hostname = canonical_hostname;
	a->port = port;
	a->peer_addr = *peer_addr;

	e = gfs_client_get_load_request_multiplexed(pa->q, &a->peer_addr,
	    pa->try_auth ?
	    gfarm_paraccess_connect_request :
	    gfarm_paraccess_load_finish,
	    a,
	    &gls, 1);
	if (e != GFARM_ERR_NO_ERROR) {
		gfarm_paraccess_callback(pa, a, NULL, NULL, e);
		return (e);
	}
	a->protocol_state = gls;
	a->pa = pa;   
	
	return (GFARM_ERR_NO_ERROR);
}
Example #3
0
static char *
search_idle(int concurrency, int enough_number,
	struct gfarm_hash_table *hosts_state,
	int nihosts, struct string_filter *ihost_filter,
	struct get_next_iterator *ihost_iterator,
	int *nohostsp, char **ohosts)
{
	char *e, *ihost;
	int i, rv, desired_number = *nohostsp;
	struct search_idle_state s;
	struct gfarm_hash_entry *entry;
	struct search_idle_host_state *h;
	struct search_idle_callback_closure *c;
	struct sockaddr addr;
	struct gfs_client_get_load_state *gls;

	if (nihosts == 0)
		return (GFARM_ERR_NO_HOST);
	s.q = gfarm_eventqueue_alloc();
	if (s.q == NULL)
		return (GFARM_ERR_NO_MEMORY);
	s.available_hosts_number =
	    s.idle_hosts_number = s.semi_idle_hosts_number = 0;
	s.available_hosts = malloc(nihosts * sizeof(*s.available_hosts));
	if (s.available_hosts == NULL) {
		gfarm_eventqueue_free(s.q);
		return (GFARM_ERR_NO_MEMORY);
	}
	s.concurrency = 0;
	for (i = 0; i < nihosts; i++) {
		do {
			ihost = (*ihost_iterator->get_next)(ihost_iterator);
		} while (!(*ihost_filter->suitable)(ihost_filter, ihost));
		entry = gfarm_hash_lookup(hosts_state,
		    ihost, strlen(ihost) + 1);
		if (entry == NULL)
			continue; /* never happen, if metadata is consistent */
		h = gfarm_hash_entry_data(entry);
		if ((h->flags & HOST_STATE_FLAG_LOADAVG_TRIED) != 0) {
			if ((h->flags &
			     (default_search_method ==
			      GFARM_SCHEDULE_SEARCH_BY_LOADAVG ?
			      HOST_STATE_FLAG_LOADAVG_AVAIL :
			      HOST_STATE_FLAG_AUTH_SUCCEED)) != 0)
				search_idle_record_host(&s, h, ihost);
		} else {
			e = gfarm_host_info_address_get(ihost,
			    gfarm_spool_server_port, h->host_info,
			    &addr, NULL);
			if (e != NULL)
				continue;

			/* We limit concurrency here */
			rv = 0;
			while (s.concurrency >= concurrency) {
				rv = gfarm_eventqueue_turn(s.q, NULL);
				/* XXX - how to report this error? */
				if (rv != 0 && rv != EAGAIN && rv != EINTR)
					break;
			}
			if (rv != 0 && rv != EAGAIN && rv != EINTR)
				break;

			c = malloc(sizeof(*c));
			if (c == NULL)
				break;
			c->state = &s;
			c->peer_addr = addr;
			c->ah.host_state = h;
			c->ah.hostname = ihost; /* record return value */
			h->flags |= HOST_STATE_FLAG_LOADAVG_TRIED;
			e = gfs_client_get_load_request_multiplexed(s.q,
			    &c->peer_addr,
			    default_search_method ==
			    GFARM_SCHEDULE_SEARCH_BY_LOADAVG ?
			    search_idle_load_callback :
			    search_idle_load_and_connect_callback,
			    c, &gls);
			if (e != NULL) {
				free(c);
			} else {
				c->protocol_state = gls;
				s.concurrency++;
			}
		}
		if (s.idle_hosts_number >= desired_number ||
		    s.semi_idle_hosts_number >= enough_number)
			break;
	}
	/* XXX - how to report this error? */
	rv = gfarm_eventqueue_loop(s.q, NULL);
	gfarm_eventqueue_free(s.q);
	if (s.available_hosts_number == 0) {
		free(s.available_hosts);
		*nohostsp = 0;
		return (GFARM_ERR_NO_HOST);
	}

	/* sort hosts in the order of load average */
	qsort(s.available_hosts, s.available_hosts_number,
	    sizeof(*s.available_hosts), loadavg_compare);

	for (i = 0; i < s.available_hosts_number && i < desired_number; i++)
		ohosts[i] = s.available_hosts[i].hostname; /* return value */
	*nohostsp = i;
	free(s.available_hosts);

	return (NULL);
}