int PINT_serv_decode_resp(PVFS_fs_id fs_id, void *encoded_resp_p, struct PINT_decoded_msg *decoded_resp_p, PVFS_BMI_addr_t *svr_addr_p, int actual_resp_sz, struct PVFS_server_resp **resp_out_pp) { int ret = -1, server_type = 0; const char *server_string; ret = PINT_decode(encoded_resp_p, PINT_DECODE_RESP, decoded_resp_p, /* holds data on decoded resp */ *svr_addr_p, actual_resp_sz); if (ret > -1) { *resp_out_pp = (struct PVFS_server_resp *)decoded_resp_p->buffer; if ((*resp_out_pp)->op == PVFS_SERV_PROTO_ERROR) { gossip_err("Error: server does not seem to understand " "the protocol that this client is using.\n"); gossip_err(" Please check server logs for more " "information.\n"); if (fs_id != PVFS_FS_ID_NULL) { server_string = PINT_cached_config_map_addr( fs_id, *svr_addr_p, &server_type); gossip_err(" Server: %s.\n", server_string); } else { gossip_err(" Server: unknown; probably an error " "contacting server listed in pvfs2tab " "file.\n"); } return(-EPROTONOSUPPORT); } } return ret; }
/* given mount information, retrieve the server's configuration by issuing a getconfig operation. on successful response, we parse the configuration and fill in the config object specified. returns 0 on success, -errno on error */ int PVFS_mgmt_get_config( const PVFS_fs_id * fsid, PVFS_BMI_addr_t * addr, char *fs_buf, int fs_buf_size) { int ret = -PVFS_EINVAL; PINT_smcb *smcb = NULL; PINT_client_sm *sm_p = NULL; PVFS_error error = 0; PVFS_credentials creds; struct filesystem_configuration_s *cur_fs = NULL; PVFS_sys_op_id op_id; struct server_configuration_s *config = NULL; struct PVFS_sys_mntent mntent; int server_type = 0; gossip_debug(GOSSIP_CLIENT_DEBUG, "PVFS_mgmt_get_config entered\n"); PVFS_util_gen_credentials(&creds); PINT_smcb_alloc(&smcb, PVFS_SERVER_GET_CONFIG, sizeof(struct PINT_client_sm), client_op_state_get_machine, client_state_machine_terminate, pint_client_sm_context); if(smcb == NULL) { return -PVFS_ENOMEM; } sm_p = PINT_sm_frame(smcb, PINT_FRAME_CURRENT); sm_p->u.get_config.persist_config_buffers = 1; PINT_init_msgarray_params(sm_p, *fsid); PINT_init_sysint_credentials(sm_p->cred_p, &creds); config = PINT_get_server_config_struct(*fsid); mntent.the_pvfs_config_server = (char*)PINT_cached_config_map_addr(*fsid, *addr, &server_type); PINT_put_server_config_struct(config); cur_fs = PINT_config_find_fs_id(config, *fsid); mntent.encoding = cur_fs->encoding; mntent.flowproto = cur_fs->flowproto; mntent.fs_id = *fsid; mntent.pvfs_fs_name = cur_fs->file_system_name; sm_p->u.get_config.config = config; sm_p->msgarray_op.msgpair.enc_type = cur_fs->encoding; sm_p->u.get_config.mntent = &mntent; PINT_msgpair_init(&sm_p->msgarray_op); ret = PINT_client_state_machine_post( smcb, &op_id, NULL); if (ret) { PVFS_perror_gossip("PINT_client_state_machine_post call", ret); error = ret; } else { ret = PVFS_mgmt_wait(op_id, "X-get_config", &error); if (ret) { PVFS_perror_gossip("PVFS_mgmt_wait call", ret); error = ret; } } if (error) { goto exit_path; } gossip_debug(GOSSIP_CLIENT_DEBUG, "PVFS_mgmt_get_config completed\n"); /* make sure strings will be null terminated after strncpy */ fs_buf[fs_buf_size-1] = '\0'; /* The following copies the retrieved configuration buffers into the return buffers */ strncpy(fs_buf, sm_p->u.get_config.fs_config_buf, (fs_buf_size - 1)); exit_path: if (sm_p && sm_p->u.get_config.persist_config_buffers) { free(sm_p->u.get_config.fs_config_buf); sm_p->u.get_config.fs_config_buf = NULL; } PINT_mgmt_release(op_id); return error; }
static PINT_sm_action msgpairarray_completion_fn( struct PINT_smcb *smcb, job_status_s *js_p) { PINT_sm_msgarray_op *mop = PINT_sm_frame(smcb, PINT_FRAME_CURRENT); int ret = -PVFS_EINVAL, i = 0; int need_retry = 0; struct PINT_decoded_msg decoded_resp; const char* server_string = NULL; int server_type; /* response structure (decoded) */ struct PVFS_server_resp *resp_p = NULL; js_p->error_code = 0; gossip_debug(GOSSIP_MSGPAIR_DEBUG, "(%p) msgpairarray state: " "completion_fn\n", smcb); for (i = 0; i < mop->count; i++) { PINT_sm_msgpair_state *msg_p = &mop->msgarray[i]; assert(msg_p); /* * Can take multiple trips through this function as we retry * ones that failed. */ if (msg_p->complete) continue; if (msg_p->op_status != 0) { char s[1024]; PVFS_strerror_r(msg_p->op_status, s, sizeof(s)); server_string = PINT_cached_config_map_addr( msg_p->fs_id, msg_p->svr_addr, &server_type); if(!server_string) { server_string = BMI_addr_rev_lookup(msg_p->svr_addr); } gossip_err("Warning: msgpair failed to %s, will retry: %s\n", server_string, s); ++need_retry; continue; } ret = PINT_serv_decode_resp(msg_p->fs_id, msg_p->encoded_resp_p, &decoded_resp, &msg_p->svr_addr, msg_p->recv_status.actual_size, &resp_p); if (ret != 0) { PVFS_perror_gossip("msgpairarray decode error", ret); msg_p->op_status = ret; } else { /* if we've made it this far, the server response status is * meaningful, so we save it. */ msg_p->op_status = resp_p->status; } /* NOTE: we call the function associated with each message, * not just the one from the first array element. so * there could in theory be different functions for each * message (to handle different types of messages all in * the same array). */ if (msg_p->comp_fn != NULL) { /* If we call the completion function, store the result on * a per message pair basis. Also store some non-zero * (failure) value in js_p->error_code if we see one. */ msg_p->op_status = msg_p->comp_fn(smcb, resp_p, i); if (msg_p->op_status != 0) { js_p->error_code = msg_p->op_status; } /* even if we see a failure, continue to process with the * completion function. -- RobR */ } else if (resp_p->status != 0) { /* no comp_fn specified and status non-zero */ gossip_debug(GOSSIP_MSGPAIR_DEBUG, "notice: msgpairarray_complete: error %d " "from server %d\n", resp_p->status, i); /* save a non-zero status to return if we see one */ js_p->error_code = resp_p->status; /* If we don't have a completion function, there is no point * in continuing to process after seeing a failure. */ if (js_p->error_code) { break; } } /* free all the resources that we used to send and receive. */ ret = PINT_serv_free_msgpair_resources( &msg_p->encoded_req, msg_p->encoded_resp_p, &decoded_resp, &msg_p->svr_addr, msg_p->max_resp_sz); if (ret) { PVFS_perror_gossip("Failed to free msgpair resources", ret); js_p->error_code = ret; return SM_ACTION_COMPLETE; } msg_p->encoded_resp_p = NULL; msg_p->max_resp_sz = 0; /* mark that this msgpair has been completed and should not be retried in the case of possible future retries */ msg_p->complete = 1; gossip_debug(GOSSIP_MSGPAIR_DEBUG, "%s: sm %p msgpair %d " "marked complete\n", __func__, smcb, i); } if (need_retry) { /* * We only retry msgpairs that are not yet complete. Factor * of two since they are pairs. If over the count, do not * retry, just return one of the error codes. */ mop->params.comp_ct = 0; js_p->error_code = 0; for (i=0; i < mop->count; i++) { PINT_sm_msgpair_state *msg_p = &mop->msgarray[i]; if (msg_p->complete) continue; if (msg_p->retry_flag == PVFS_MSGPAIR_RETRY && PVFS_ERROR_CLASS(-msg_p->op_status) == PVFS_ERROR_BMI && msg_p->retry_count < mop->params.retry_limit) { ++msg_p->retry_count; mop->params.comp_ct += 2; gossip_debug(GOSSIP_MSGPAIR_DEBUG, "*** %s: msgpair %d failed, retry %d\n", __func__, i, msg_p->retry_count); if(msg_p->op_status == -BMI_ECANCEL) { /* if the error code indicates cancel, then skip the * delay. We have probably already been waiting a while */ gossip_debug(GOSSIP_MSGPAIR_DEBUG, "*** %s: msgpair skipping retry delay.\n", __func__); js_p->error_code = MSGPAIRS_RETRY_NODELAY; } else { gossip_debug(GOSSIP_MSGPAIR_DEBUG, "*** %s: msgpair retrying after delay.\n", __func__); js_p->error_code = MSGPAIRS_RETRY; } } else { char s[1024]; server_string = PINT_cached_config_map_addr( msg_p->fs_id, msg_p->svr_addr, &server_type); if(!server_string) { server_string = "[UNKNOWN]"; } PVFS_strerror_r(msg_p->op_status, s, sizeof(s)); gossip_err_unless_quiet("*** %s: msgpair to server %s failed: %s\n", __func__, server_string, s); if(msg_p->retry_flag != PVFS_MSGPAIR_RETRY) { gossip_err_unless_quiet("*** No retries requested.\n"); } else if(PVFS_ERROR_CLASS(-msg_p->op_status) != PVFS_ERROR_BMI) { gossip_err_unless_quiet("*** Non-BMI failure.\n"); } else { gossip_err_unless_quiet("*** Out of retries.\n"); } if (js_p->error_code == 0) js_p->error_code = msg_p->op_status; } } } return SM_ACTION_COMPLETE; }