int PVFS_hint_copy(PVFS_hint old_hint, PVFS_hint *new_hint) { const struct PINT_hint_info *info; PINT_hint *h = old_hint; const char *name; if(!old_hint) { *new_hint = NULL; return 0; } while(h) { info = PINT_hint_get_info_by_type(h->type); if(!info) { name = h->type_string; } else { name = info->name; } PVFS_hint_add(new_hint, name, h->length, h->value); h = h->next; } return 0; }
void decode_PINT_hint(char **pptr, PINT_hint **hint) { int count, i, type; PINT_hint *new_hint = NULL; const struct PINT_hint_info *info; decode_uint32_t(pptr, &count); gossip_debug(GOSSIP_SERVER_DEBUG, "decoding %d hints from request\n", count); for(i = 0; i < count; ++i) { decode_uint32_t(pptr, &type); info = PINT_hint_get_info_by_type(type); if(info) { char *start; int len; void *value = malloc(info->length); if(!value) { return; } start = *pptr; info->decode(pptr, value); len = (*pptr - start); PVFS_hint_add(&new_hint, info->name, len, value); free(value); } else { char *type_string; char *value; /* not a recognized hint, assume its a string */ decode_string(pptr, &type_string); decode_string(pptr, &value); PVFS_hint_add(&new_hint, type_string, strlen(value) + 1, value); } } *hint = new_hint; }
int PVFS_hint_replace( PVFS_hint *hint, const char *name, int length, void *value) { const struct PINT_hint_info *info; info = PINT_hint_get_info_by_name(name); if(info) { return PVFS_hint_replace_internal(hint, info->type, length, value); } return PVFS_hint_add(hint, name, length, value); }
/** lebf_initialize() * * initializes the encoder module, calculates max sizes of each request type * in advance * * no return value */ static void lebf_initialize(void) { struct PVFS_server_req req = {0}; struct PVFS_server_resp resp = {0}; enum PVFS_server_op op_type; int reqsize, respsize; int noreq; PINT_dist tmp_dist; PINT_Request tmp_req; char *tmp_name = strdup("foo"); const int init_big_size = 1024 * 1024; int i; gossip_debug(GOSSIP_ENDECODE_DEBUG,"lebf_initialize\n"); max_size_array = malloc(PVFS_SERV_NUM_OPS * sizeof(*max_size_array)); if (max_size_array == NULL) return; /* * Some messages have extra structures, and even indeterminate sizes * which are hand-calculated here. Also some fields must be initialized * for encoding to work properly. */ memset(&tmp_dist, 0, sizeof(tmp_dist)); tmp_dist.dist_name = strdup(PVFS_DIST_BASIC_NAME); if (PINT_dist_lookup(&tmp_dist)) { gossip_err("%s: dist %s does not exist?!?\n", __func__, tmp_dist.dist_name); exit(1); } memset(&tmp_req, 0, sizeof(tmp_req)); initializing_sizes = 1; /** set number of hints in request to the max */ for(i = 0; i < PVFS_HINT_MAX; ++i) { char name[PVFS_HINT_MAX_NAME_LENGTH] = {0}; char val[PVFS_HINT_MAX_LENGTH] = {0}; PVFS_hint_add(&req.hints, name, PVFS_HINT_MAX_LENGTH, val); } for (op_type=0; op_type<PVFS_SERV_NUM_OPS; op_type++) { memset(&req.u, 0, sizeof(req.u)); req.op = resp.op = op_type; reqsize = 0; respsize = 0; noreq = 0; switch (op_type) { case PVFS_SERV_INVALID: case PVFS_SERV_PERF_UPDATE: case PVFS_SERV_PRECREATE_POOL_REFILLER: case PVFS_SERV_JOB_TIMER: /** never used, skip initialization */ continue; case PVFS_SERV_GETCONFIG: resp.u.getconfig.fs_config_buf = tmp_name; respsize = extra_size_PVFS_servresp_getconfig; break; case PVFS_SERV_LOOKUP_PATH: req.u.lookup_path.path = ""; resp.u.lookup_path.handle_count = 0; resp.u.lookup_path.attr_count = 0; reqsize = extra_size_PVFS_servreq_lookup_path; respsize = extra_size_PVFS_servresp_lookup_path; break; case PVFS_SERV_BATCH_CREATE: /** can request a range of handles */ req.u.batch_create.handle_extent_array.extent_count = 0; req.u.batch_create.object_count = 0; resp.u.batch_create.handle_count = 0; reqsize = extra_size_PVFS_servreq_batch_create; respsize = extra_size_PVFS_servresp_batch_create; break; case PVFS_SERV_CREATE: /** can request a range of handles */ reqsize = extra_size_PVFS_servreq_create; respsize = extra_size_PVFS_servresp_create; break; case PVFS_SERV_MIRROR: req.u.mirror.dist = &tmp_dist; req.u.mirror.dst_count = 0; reqsize = extra_size_PVFS_servreq_mirror; respsize = extra_size_PVFS_servresp_mirror; break; case PVFS_SERV_IMM_COPIES: break; case PVFS_SERV_REMOVE: /** nothing special, let normal encoding work */ break; case PVFS_SERV_BATCH_REMOVE: req.u.batch_remove.handles = NULL; req.u.batch_remove.handle_count = 0; reqsize = extra_size_PVFS_servreq_batch_remove; break; case PVFS_SERV_MGMT_REMOVE_OBJECT: /** nothing special, let normal encoding work */ break; case PVFS_SERV_MGMT_REMOVE_DIRENT: req.u.mgmt_remove_dirent.entry = tmp_name; reqsize = extra_size_PVFS_servreq_mgmt_remove_dirent; break; case PVFS_SERV_TREE_REMOVE: req.u.tree_remove.handle_array = NULL; req.u.tree_remove.num_data_files = 0; reqsize = extra_size_PVFS_servreq_tree_remove; break; case PVFS_SERV_IO: req.u.io.io_dist = &tmp_dist; req.u.io.file_req = &tmp_req; reqsize = extra_size_PVFS_servreq_io; break; case PVFS_SERV_SMALL_IO: req.u.small_io.dist = &tmp_dist; req.u.small_io.file_req = &tmp_req; reqsize = extra_size_PVFS_servreq_small_io; respsize = extra_size_PVFS_servresp_small_io; break; case PVFS_SERV_GETATTR: resp.u.getattr.attr.mask = 0; respsize = extra_size_PVFS_servresp_getattr; break; case PVFS_SERV_UNSTUFF: resp.u.unstuff.attr.mask = 0; respsize = extra_size_PVFS_servresp_unstuff; break; case PVFS_SERV_SETATTR: req.u.setattr.attr.mask = 0; reqsize = extra_size_PVFS_servreq_setattr; break; case PVFS_SERV_CRDIRENT: req.u.crdirent.name = tmp_name; reqsize = extra_size_PVFS_servreq_crdirent; break; case PVFS_SERV_RMDIRENT: req.u.rmdirent.entry = tmp_name; reqsize = extra_size_PVFS_servreq_rmdirent; break; case PVFS_SERV_CHDIRENT: req.u.chdirent.entry = tmp_name; reqsize = extra_size_PVFS_servreq_chdirent; break; case PVFS_SERV_TRUNCATE: /** nothing special */ break; case PVFS_SERV_MKDIR: req.u.mkdir.handle_extent_array.extent_count = 0; req.u.mkdir.attr.mask = 0; reqsize = extra_size_PVFS_servreq_mkdir; break; case PVFS_SERV_READDIR: resp.u.readdir.directory_version = 0; resp.u.readdir.dirent_count = 0; respsize = extra_size_PVFS_servresp_readdir; break; case PVFS_SERV_FLUSH: /** nothing special */ break; case PVFS_SERV_MGMT_SETPARAM: /** nothing special */ break; case PVFS_SERV_MGMT_NOOP: /** nothing special */ break; case PVFS_SERV_STATFS: /** nothing special */ break; case PVFS_SERV_MGMT_GET_DIRDATA_HANDLE: /** nothing special */ break; case PVFS_SERV_WRITE_COMPLETION: /** only a response, but nothing special there */ noreq = 1; break; case PVFS_SERV_MGMT_PERF_MON: resp.u.mgmt_perf_mon.perf_array_count = 0; respsize = extra_size_PVFS_servresp_mgmt_perf_mon; break; case PVFS_SERV_MGMT_ITERATE_HANDLES: resp.u.mgmt_iterate_handles.handle_count = 0; respsize = extra_size_PVFS_servresp_mgmt_iterate_handles; break; case PVFS_SERV_MGMT_DSPACE_INFO_LIST: req.u.mgmt_dspace_info_list.handle_count = 0; resp.u.mgmt_dspace_info_list.dspace_info_count = 0; reqsize = extra_size_PVFS_servreq_mgmt_dspace_info_list; respsize = extra_size_PVFS_servresp_mgmt_dspace_info_list; break; case PVFS_SERV_MGMT_EVENT_MON: resp.u.mgmt_event_mon.event_count = 0; respsize = extra_size_PVFS_servresp_mgmt_event_mon; break; case PVFS_SERV_PROTO_ERROR: /** nothing special */ break; case PVFS_SERV_GETEATTR: req.u.geteattr.nkey = 0; resp.u.geteattr.nkey = 0; reqsize = extra_size_PVFS_servreq_geteattr; respsize = extra_size_PVFS_servresp_geteattr; break; case PVFS_SERV_SETEATTR: req.u.seteattr.nkey = 0; reqsize = extra_size_PVFS_servreq_seteattr; break; case PVFS_SERV_DELEATTR: req.u.deleattr.key.buffer_sz = 0; reqsize = extra_size_PVFS_servreq_deleattr; break; case PVFS_SERV_LISTEATTR: resp.u.listeattr.nkey = 0; req.u.listeattr.nkey = 0; reqsize = extra_size_PVFS_servreq_listeattr; respsize = extra_size_PVFS_servresp_listeattr; break; case PVFS_SERV_LISTATTR: resp.u.listattr.nhandles = 0; req.u.listattr.nhandles = 0; reqsize = extra_size_PVFS_servreq_listattr; respsize = extra_size_PVFS_servresp_listattr; break; case PVFS_SERV_TREE_GET_FILE_SIZE: req.u.tree_get_file_size.handle_array = NULL; req.u.tree_get_file_size.num_data_files = 0; resp.u.tree_get_file_size.size = NULL; resp.u.tree_get_file_size.error = NULL; resp.u.tree_get_file_size.handle_count = 0; resp.u.tree_get_file_size.caller_handle_index = 0; reqsize = extra_size_PVFS_servreq_tree_get_file_size; respsize = extra_size_PVFS_servresp_tree_get_file_size; break; case PVFS_SERV_MGMT_GET_UID: resp.u.mgmt_get_uid.uid_info_array_count = 0; respsize = extra_size_PVFS_servresp_mgmt_get_uid; break; case PVFS_SERV_NUM_OPS: /** sentinel, should not hit */ assert(0); break; } /** since these take the max size when mallocing in the encode, * give them a huge number, then later fix it. */ max_size_array[op_type].req = max_size_array[op_type].resp = init_big_size; if (noreq) reqsize = 0; else reqsize += check_req_size(&req); respsize += check_resp_size(&resp); if (reqsize > init_big_size) gossip_err("%s: op %d reqsize %d exceeded prealloced %d\n", __func__, op_type, reqsize, init_big_size); if (respsize > init_big_size) gossip_err("%s: op %d respsize %d exceeded prealloced %d\n", __func__, op_type, respsize, init_big_size); max_size_array[op_type].req = reqsize; max_size_array[op_type].resp = respsize; } /** clean up stuff just used for initialization */ PVFS_hint_free(req.hints); free(tmp_dist.dist_name); free(tmp_name); initializing_sizes = 0; }
/** Initiate modification of attributes of a single object. */ PVFS_error PVFS_isys_setattr( PVFS_object_ref ref, PVFS_sys_attr attr, const PVFS_credentials *credentials, PVFS_sys_op_id *op_id, PVFS_hint hints, void *user_ptr) { PVFS_error ret = -PVFS_EINVAL; PINT_smcb *smcb = NULL; PINT_client_sm *sm_p = NULL; gossip_debug(GOSSIP_CLIENT_DEBUG, "PVFS_isys_setattr entered\n"); if ((ref.handle == PVFS_HANDLE_NULL) || (ref.fs_id == PVFS_FS_ID_NULL)) { gossip_err("invalid (NULL) required argument\n"); return ret; } /* * make sure the caller didn't set invalid mask bits. * only common attributes can be set. */ if ((attr.mask & ~PVFS_ATTR_SYS_ALL_TIMES) != 0) { gossip_lerr("PVFS_isys_setattr() failure: invalid attributes " "specified\n"); return ret; } /* make sure that the permission bits are acceptable */ if ((attr.mask & PVFS_ATTR_SYS_PERM) && (attr.perms & ~PVFS_PERM_VALID) != 0) { gossip_lerr("PVFS_isys_setattr() failure: invalid or unsupported" "permission bits\n"); return(-PVFS_EINVAL); } PINT_smcb_alloc(&smcb, PVFS_SYS_SETATTR, 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); PINT_init_msgarray_params(sm_p, ref.fs_id); PINT_init_sysint_credentials(sm_p->cred_p, credentials); sm_p->object_ref = ref; PVFS_hint_copy(hints, &sm_p->hints); PVFS_hint_add(&sm_p->hints, PVFS_HINT_HANDLE_NAME, sizeof(PVFS_handle), &ref.handle); ret = PVFS_util_copy_sys_attr(&sm_p->u.setattr.sys_attr, &attr); if(ret < 0) { gossip_lerr("PVFS_isys_setattr() failure: %s\n", strerror(PVFS_get_errno_mapping(-ret))); return ret; } gossip_debug(GOSSIP_CLIENT_DEBUG, "Doing setattr on handle %llu " "on fs %d\n", llu(ref.handle), ref.fs_id); return PINT_client_state_machine_post( smcb, op_id, user_ptr); }
/** Initiate reading of entries from a directory. * * \param token opaque value used to track position in directory * when more than one read is required. * \param pvfs_dirent_incount maximum number of entries to read, if * available, starting from token. */ PVFS_error PVFS_isys_readdir( PVFS_object_ref ref, PVFS_ds_position token, int32_t pvfs_dirent_incount, const PVFS_credentials *credentials, PVFS_sysresp_readdir *resp, PVFS_sys_op_id *op_id, PVFS_hint hints, void *user_ptr) { PVFS_error ret = -PVFS_EINVAL; PINT_smcb *smcb = NULL; PINT_client_sm *sm_p = NULL; gossip_debug(GOSSIP_CLIENT_DEBUG, "PVFS_isys_readdir entered\n"); if ((ref.handle == PVFS_HANDLE_NULL) || (ref.fs_id == PVFS_FS_ID_NULL) || (resp == NULL)) { gossip_err("invalid (NULL) required argument\n"); return ret; } if (pvfs_dirent_incount > PVFS_REQ_LIMIT_DIRENT_COUNT) { gossip_lerr("PVFS_isys_readdir unable to handle request " "for %d entries.\n", pvfs_dirent_incount); return ret; } PINT_smcb_alloc(&smcb, PVFS_SYS_READDIR, 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); PINT_init_msgarray_params(sm_p, ref.fs_id); PINT_init_sysint_credentials(sm_p->cred_p, credentials); sm_p->u.readdir.readdir_resp = resp; sm_p->object_ref = ref; PVFS_hint_copy(hints, &sm_p->hints); PVFS_hint_add(&sm_p->hints, PVFS_HINT_HANDLE_NAME, sizeof(PVFS_handle), &ref.handle); /* point the sm dirent array and outcount to the readdir response field */ sm_p->readdir.dirent_array = &resp->dirent_array; sm_p->readdir.dirent_outcount = &resp->pvfs_dirent_outcount; sm_p->readdir.token = &resp->token; sm_p->readdir.directory_version = &resp->directory_version; sm_p->readdir.pos_token = sm_p->u.readdir.pos_token = token; sm_p->readdir.dirent_limit = sm_p->u.readdir.dirent_limit = pvfs_dirent_incount; gossip_debug(GOSSIP_READDIR_DEBUG, "Doing readdir on handle " "%llu on fs %d\n", llu(ref.handle), ref.fs_id); return PINT_client_state_machine_post( smcb, op_id, user_ptr); }
/* * example environment variable * PVFS2_HINTS = *'pvfs.hint.request_id:10+pvfs.hint.client_id:30' */ int PVFS_hint_import_env(PVFS_hint *out_hint) { char * env; char * env_copy; char * save_ptr = NULL; char * aktvar; char name[PVFS_HINT_MAX_NAME_LENGTH]; int len; const struct PINT_hint_info *info; PINT_hint *hint = NULL; int ret; if( out_hint == NULL ) { return 1; } env = getenv("PVFS2_HINTS"); if( env == NULL ) { return 0; } len = strlen(env); env_copy = (char *) malloc(sizeof(char) * (len+1)); strncpy(env_copy, env, len+1); /* parse hints and do not overwrite already specified hints !*/ #ifdef WIN32 aktvar = strtok(env_copy, "+"); /* thread-safe */ #else aktvar = strtok_r(env_copy, "+", & save_ptr); #endif while( aktvar != NULL ) { char * rest; #ifdef WIN32 rest = strchr(aktvar, ':'); #else rest = index(aktvar, ':'); #endif if (rest == NULL) { gossip_err("Environment variable PVFS2_HINTS is " "malformed starting with: %s\n", aktvar); free(env_copy); return 0; } *rest = 0; sprintf(name, "pvfs2.hint.%s", aktvar); info = PINT_hint_get_info_by_name(name); if(info) { /* a bit of a hack..if we know the type and its * an int, we convert from a string */ if(info->encode == encode_func_uint32_t) { uint32_t val; sscanf(rest+1, "%u", &val); ret = PVFS_hint_add(&hint, info->name, sizeof(val), &val); } else if(info->encode == encode_func_uint64_t) { uint32_t val; sscanf(rest+1, "%u", &val); ret = PVFS_hint_add(&hint, info->name, sizeof(val), &val); } else if(info->encode == encode_func_string) { /* just pass the string along as the hint value */ ret = PVFS_hint_add(&hint, info->name, strlen(rest+1), rest+1); } else { /* Can't specify a complex hint in the PVFS2_HINTS environment * variable. */ ret = -PVFS_EINVAL; } } else { /* Hint not recognized, so we store it with its name */ ret = PVFS_hint_add(&hint, name, strlen(rest+1), rest+1); } if(ret < 0) { /* hint parsing failed */ PVFS_hint_free(hint); free(env_copy); return ret; } #ifdef WIN32 aktvar = strtok(NULL, "+"); #else aktvar = strtok_r(NULL, "+", & save_ptr); #endif } free(env_copy); return 0; }