/* * 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 */ } } }
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); }
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); }