in prov/psm/src/psmx_av.c [141:280]
static int psmx_av_insert(struct fid_av *av, const void *addr, size_t count,
fi_addr_t *fi_addr, uint64_t flags, void *context)
{
struct psmx_fid_av *av_priv;
psm_error_t *errors;
int error_count = 0;
int *mask;
int i, j, ret;
fi_addr_t *result = NULL;
struct psmx_epaddr_context *epaddr_context;
if (count && !addr) {
FI_INFO(&psmx_prov, FI_LOG_AV,
"the input address array is NULL.\n");
return -FI_EINVAL;
}
av_priv = container_of(av, struct psmx_fid_av, av);
if ((av_priv->flags & FI_EVENT) && !av_priv->eq)
return -FI_ENOEQ;
errors = (psm_error_t *) calloc(count, sizeof *errors);
if (!errors)
return -FI_ENOMEM;
mask = (int *) calloc(count, sizeof *mask);
if (!mask) {
free(errors);
return -FI_ENOMEM;
}
if (av_priv->type == FI_AV_TABLE) {
if (psmx_av_check_table_size(av_priv, count)) {
free(mask);
free(errors);
return -FI_ENOMEM;
}
for (i=0; i<count; i++)
av_priv->psm_epids[av_priv->last + i] = ((psm_epid_t *)addr)[i];
result = fi_addr;
addr = (const void *)(av_priv->psm_epids + av_priv->last);
fi_addr = (fi_addr_t *)(av_priv->psm_epaddrs + av_priv->last);
}
/* prevent connecting to the same ep twice, which is fatal in PSM */
for (i=0; i<count; i++) {
psm_epconn_t epconn;
if (psm_ep_epid_lookup(((psm_epid_t *) addr)[i], &epconn) == PSM_OK) {
epaddr_context = psm_epaddr_getctxt(epconn.addr);
if (epaddr_context && epaddr_context->epid == ((psm_epid_t *) addr)[i])
((psm_epaddr_t *) fi_addr)[i] = epconn.addr;
else
mask[i] = 1;
} else {
mask[i] = 1;
}
}
psm_ep_connect(av_priv->domain->psm_ep, count,
(psm_epid_t *) addr, mask, errors,
(psm_epaddr_t *) fi_addr, 30*1e9);
for (i=0; i<count; i++){
if (!mask[i]) {
errors[i] = PSM_OK;
continue;
}
if (errors[i] == PSM_OK || errors[i] == PSM_EPID_ALREADY_CONNECTED) {
psmx_set_epaddr_context(av_priv->domain,
((psm_epid_t *) addr)[i],
((psm_epaddr_t *) fi_addr)[i]);
errors[i] = PSM_OK;
} else {
psm_epconn_t epconn;
/* If duplicated addresses are passed to psm_ep_connect(), all but one will fail
* with error "Endpoint could not be reached". They should be treated as already
* connected.
*/
if (psm_ep_epid_lookup(((psm_epid_t *) addr)[i], &epconn) == PSM_OK) {
epaddr_context = psm_epaddr_getctxt(epconn.addr);
if (epaddr_context && epaddr_context->epid == ((psm_epid_t *) addr)[i]) {
((psm_epaddr_t *) fi_addr)[i] = epconn.addr;
errors[i] = PSM_OK;
continue;
}
}
FI_INFO(&psmx_prov, FI_LOG_AV,
"%d: psm_ep_connect returned %s. remote epid=%lx.\n",
i, psm_error_get_string(errors[i]),
((psm_epid_t *)addr)[i]);
if (((psm_epid_t *)addr)[i] == 0)
FI_INFO(&psmx_prov, FI_LOG_AV,
"does the application depend on the provider"
"to resolve IP address into endpoint id? if so"
"check if the name server has started correctly"
"at the other side.\n");
fi_addr[i] = FI_ADDR_NOTAVAIL;
error_count++;
if (av_priv->flags & FI_EVENT)
psmx_av_post_completion(av_priv, context, i, errors[i]);
}
}
if (av_priv->type == FI_AV_TABLE) {
/* NOTE: unresolved addresses are left in the AV table */
if (result) {
for (i=0; i<count; i++) {
j = av_priv->last + i;
if ((fi_addr_t)av_priv->psm_epaddrs[j] == FI_ADDR_NOTAVAIL)
result[i] = FI_ADDR_NOTAVAIL;
else
result[i] = j;
}
}
av_priv->last += count;
}
if (av_priv->flags & FI_EVENT) {
psmx_av_post_completion(av_priv, context, count - error_count, 0);
ret = 0;
} else {
if (flags & FI_SYNC_ERR) {
int *fi_errors = context;
for (i=0; i<count; i++)
fi_errors[i] = psmx_errno(errors[i]);
}
ret = count - error_count;
}
free(mask);
free(errors);
return ret;
}