Skip to content

Commit

Permalink
Support H5Iget name (#41)
Browse files Browse the repository at this point in the history
* Implement H5Iget_name

Assocating a path/name with each open object goes against the spirit
of the API, but the alternative is traversing every link in the
domain, which is already slow in the library and would be
slower here.
  • Loading branch information
mattjala authored Aug 4, 2023
1 parent 56c98d8 commit 875b8ce
Show file tree
Hide file tree
Showing 8 changed files with 233 additions and 15 deletions.
68 changes: 64 additions & 4 deletions src/rest_vol.c
Original file line number Diff line number Diff line change
Expand Up @@ -2457,10 +2457,17 @@ RV_copy_object_loc_info_callback(char *HTTP_response, void *callback_data_in, vo
strncpy(new_domain->u.file.filepath_name, found_domain.u.file.filepath_name,
strlen(found_domain.u.file.filepath_name) + 1);

new_domain->u.file.intent = loc_info_out->domain->u.file.intent;
new_domain->u.file.fapl_id = H5Pcopy(loc_info_out->domain->u.file.fapl_id);
new_domain->u.file.fcpl_id = H5Pcopy(loc_info_out->domain->u.file.fcpl_id);
new_domain->u.file.ref_count = 1;
new_domain->u.file.intent = loc_info_out->domain->u.file.intent;
new_domain->u.file.fapl_id = H5Pcopy(loc_info_out->domain->u.file.fapl_id);
new_domain->u.file.fcpl_id = H5Pcopy(loc_info_out->domain->u.file.fcpl_id);
new_domain->u.file.ref_count = 1;
new_domain->u.file.server_version = found_domain.u.file.server_version;

/* Allocate root "path" on heap for consistency with other RV_object_t types */
if ((new_domain->handle_path = RV_malloc(2)) == NULL)
FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTALLOC, NULL, "can't allocate space for filepath");

strncpy(new_domain->handle_path, "/", 2);

/* Assume that original domain and external domain have the same server version.
* This will always be true unless it becomes possible for external links to point to
Expand Down Expand Up @@ -3380,6 +3387,59 @@ RV_set_object_type_header(H5I_type_t parent_obj_type, const char **parent_obj_ty
return (ret_value);
} /* end RV_set_object_type_header */

/* Helper function to initialize an object's name based on its parent's name.
* Allocates memory that must be closed by caller. */
herr_t
RV_set_object_handle_path(const char *obj_path, const char *parent_path, char **buf)
{
herr_t ret_value = SUCCEED;
hbool_t include_parent_path = false;
size_t path_size = 0;
size_t path_len = 0;
char *handle_path = NULL;

/* Objects can be created/opened without reference to their path. Leave handle_path NULL in this case */
if (!obj_path) {
*buf = NULL;
FUNC_GOTO_DONE(SUCCEED);
}

/* Parent name is included if it is not the root and the object is opened by relative path */
include_parent_path = parent_path && strcmp(parent_path, "/") && (obj_path[0] != '/');

path_size =
include_parent_path ? strlen(parent_path) + 1 + strlen(obj_path) + 1 : 1 + strlen(obj_path) + 1;

if ((handle_path = RV_malloc(path_size)) == NULL)
FUNC_GOTO_ERROR(H5E_SYM, H5E_CANTALLOC, FAIL, "can't allocate space for handle path");

if (include_parent_path) {
strncpy(handle_path, parent_path, path_size);
path_len += strlen(parent_path);
}

/* Add leading slash if not in group name */
if (obj_path[0] != '/') {
handle_path[path_len] = '/';
path_len += 1;
}

strncpy(handle_path + path_len, obj_path, strlen(obj_path) + 1);
path_len += (strlen(obj_path) + 1);

handle_path[path_size - 1] = '\0';

/* Make user pointer point at allocated memory */
*buf = handle_path;

done:
if (ret_value < 0) {
RV_free(handle_path);
*buf = NULL;
}

return ret_value;
}
/*************************************************
* The following two routines allow the REST VOL *
* connector to be dynamically loaded by HDF5. *
Expand Down
5 changes: 5 additions & 0 deletions src/rest_vol.h
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,7 @@ typedef struct RV_attr_t {
hid_t aapl_id;
hid_t acpl_id;
char *attr_name;
char *parent_name;
} RV_attr_t;

typedef struct RV_datatype_t {
Expand All @@ -503,6 +504,7 @@ struct RV_object_t {
RV_object_t *domain;
H5I_type_t obj_type;
char URI[URI_MAX_LENGTH];
char *handle_path;

union {
RV_datatype_t datatype;
Expand Down Expand Up @@ -623,6 +625,9 @@ herr_t RV_base64_decode(const char *in, size_t in_size, char **out, size_t *out_
/* Comparison function to compare two keys in an rv_hash_table_t */
int H5_rest_compare_string_keys(void *value1, void *value2);

/* Helper function to initialize an object's name based on its parent's name. */
herr_t RV_set_object_handle_path(const char *obj_path, const char *parent_path, char **buf);

/* Helper to turn an object type into a string for a server request */
herr_t RV_set_object_type_header(H5I_type_t parent_obj_type, const char **parent_obj_type_header);

Expand Down
45 changes: 44 additions & 1 deletion src/rest_vol_attr.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ RV_attr_create(void *obj, const H5VL_loc_params_t *loc_params, const char *attr_
size_t host_header_len = 0;
size_t datatype_body_len = 0;
size_t attr_name_len = 0;
size_t path_size = 0;
size_t path_len = 0;
char *host_header = NULL;
char *create_request_body = NULL;
char *datatype_body = NULL;
Expand Down Expand Up @@ -114,6 +116,20 @@ RV_attr_create(void *obj, const H5VL_loc_params_t *loc_params, const char *attr_
new_attribute->domain = parent->domain;
parent->domain->u.file.ref_count++;

new_attribute->handle_path = NULL;

if (RV_set_object_handle_path(attr_name, parent->handle_path, &new_attribute->handle_path) < 0)
FUNC_GOTO_ERROR(H5E_ATTR, H5E_PATH, NULL, "can't set up object path");

new_attribute->u.attribute.parent_name = NULL;

if (parent->handle_path) {
if ((new_attribute->u.attribute.parent_name = RV_malloc(strlen(parent->handle_path) + 1)) == NULL)
FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, NULL, "can't allocate space for attribute parent name");

strncpy(new_attribute->u.attribute.parent_name, parent->handle_path, strlen(parent->handle_path) + 1);
}

/* If this is a call to H5Acreate_by_name, locate the real parent object */
if (H5VL_OBJECT_BY_NAME == loc_params->type) {

Expand Down Expand Up @@ -402,6 +418,8 @@ RV_attr_open(void *obj, const H5VL_loc_params_t *loc_params, const char *attr_na
RV_object_t *attribute = NULL;
size_t attr_name_len = 0;
size_t host_header_len = 0;
size_t path_size = 0;
size_t path_len = 0;
char *host_header = NULL;
char *found_attr_name = NULL;
char request_url[URL_MAX_LENGTH];
Expand Down Expand Up @@ -456,6 +474,20 @@ RV_attr_open(void *obj, const H5VL_loc_params_t *loc_params, const char *attr_na
attribute->domain = parent->domain;
parent->domain->u.file.ref_count++;

attribute->handle_path = NULL;

if (RV_set_object_handle_path(attr_name, parent->handle_path, &attribute->handle_path) < 0)
FUNC_GOTO_ERROR(H5E_ATTR, H5E_PATH, NULL, "can't set up object path");

attribute->u.attribute.parent_name = NULL;

if (parent->handle_path) {
if ((attribute->u.attribute.parent_name = RV_malloc(strlen(parent->handle_path) + 1)) == NULL)
FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, NULL, "can't allocate space for attribute parent name");

strncpy(attribute->u.attribute.parent_name, parent->handle_path, strlen(parent->handle_path) + 1);
}

/* Set the parent object's type and URI in the attribute's appropriate fields */
switch (loc_params->type) {
/* H5Aopen */
Expand Down Expand Up @@ -2170,10 +2202,19 @@ RV_attr_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_attr_speci
}

/* Increment refs for specific type */

RV_object_t *attr_iter_obj = (RV_object_t *)attr_iter_object;

if ((attr_iter_obj->handle_path = RV_malloc(strlen(loc_obj->handle_path) + 1)) == NULL)
FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, FAIL,
"can't allocate space for copy of object path");

strncpy(attr_iter_obj->handle_path, loc_obj->handle_path,
strlen(loc_obj->handle_path) + 1);

switch (parent_obj_type) {
case H5I_FILE:
/* Copy fapl, fcpl, and filepath name to new object */
RV_object_t *attr_iter_obj = (RV_object_t *)attr_iter_object;

if (H5I_INVALID_HID ==
(attr_iter_obj->u.file.fapl_id = H5Pcopy(loc_obj->u.file.fapl_id)))
Expand Down Expand Up @@ -2602,6 +2643,8 @@ RV_attr_close(void *attr, hid_t dxpl_id, void **req)
if (RV_file_close(_attr->domain, H5P_DEFAULT, NULL) < 0)
FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "couldn't close attr domain");

RV_free(_attr->u.attribute.parent_name);
RV_free(_attr->handle_path);
RV_free(_attr);
_attr = NULL;

Expand Down
15 changes: 15 additions & 0 deletions src/rest_vol_dataset.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ RV_dataset_create(void *obj, const H5VL_loc_params_t *loc_params, const char *na
RV_object_t *new_dataset = NULL;
curl_off_t create_request_body_len = 0;
size_t host_header_len = 0;
size_t path_size = 0;
size_t path_len = 0;
char *host_header = NULL;
char *create_request_body = NULL;
char request_url[URL_MAX_LENGTH];
Expand Down Expand Up @@ -144,6 +146,11 @@ RV_dataset_create(void *obj, const H5VL_loc_params_t *loc_params, const char *na
new_dataset->domain = parent->domain;
parent->domain->u.file.ref_count++;

new_dataset->handle_path = NULL;

if (RV_set_object_handle_path(name, parent->handle_path, &new_dataset->handle_path) < 0)
FUNC_GOTO_ERROR(H5E_DATASET, H5E_PATH, NULL, "can't set up object path");

/* Copy the DAPL if it wasn't H5P_DEFAULT, else set up a default one so that
* H5Dget_access_plist() will function correctly
*/
Expand Down Expand Up @@ -303,6 +310,8 @@ RV_dataset_open(void *obj, const H5VL_loc_params_t *loc_params, const char *name
htri_t search_ret;
void *ret_value = NULL;
loc_info loc_info_out;
size_t path_size = 0;
size_t path_len = 0;

#ifdef RV_CONNECTOR_DEBUG
printf("-> Received dataset open call with following parameters:\n");
Expand Down Expand Up @@ -331,6 +340,11 @@ RV_dataset_open(void *obj, const H5VL_loc_params_t *loc_params, const char *name
dataset->domain = parent->domain;
parent->domain->u.file.ref_count++;

dataset->handle_path = NULL;

if (RV_set_object_handle_path(name, parent->handle_path, &dataset->handle_path) < 0)
FUNC_GOTO_ERROR(H5E_DATASET, H5E_PATH, NULL, "can't set up object path");

loc_info_out.URI = dataset->URI;
loc_info_out.domain = dataset->domain;
loc_info_out.GCPL_base64 = NULL;
Expand Down Expand Up @@ -1169,6 +1183,7 @@ RV_dataset_close(void *dset, hid_t dxpl_id, void **req)
FUNC_DONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close file");
}

RV_free(_dset->handle_path);
RV_free(_dset);
_dset = NULL;

Expand Down
15 changes: 15 additions & 0 deletions src/rest_vol_datatype.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ RV_datatype_commit(void *obj, const H5VL_loc_params_t *loc_params, const char *n
size_t link_body_nalloc = 0;
size_t host_header_len = 0;
size_t datatype_body_len = 0;
size_t path_size = 0;
size_t path_len = 0;
char *host_header = NULL;
char *commit_request_body = NULL;
char *datatype_body = NULL;
Expand Down Expand Up @@ -122,6 +124,11 @@ RV_datatype_commit(void *obj, const H5VL_loc_params_t *loc_params, const char *n
FUNC_GOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "can't copy type id");
}

new_datatype->handle_path = NULL;

if (RV_set_object_handle_path(name, parent->handle_path, &new_datatype->handle_path) < 0)
FUNC_GOTO_ERROR(H5E_DATATYPE, H5E_PATH, NULL, "can't set up object path");

/* Copy the TAPL if it wasn't H5P_DEFAULT, else set up a default one so that
* datatype access property list functions will function correctly
*/
Expand Down Expand Up @@ -336,6 +343,8 @@ RV_datatype_open(void *obj, const H5VL_loc_params_t *loc_params, const char *nam
H5I_type_t obj_type = H5I_UNINIT;
loc_info loc_info_out;
htri_t search_ret;
size_t path_size = 0;
size_t path_len = 0;
void *ret_value = NULL;

#ifdef RV_CONNECTOR_DEBUG
Expand Down Expand Up @@ -363,6 +372,11 @@ RV_datatype_open(void *obj, const H5VL_loc_params_t *loc_params, const char *nam
datatype->domain = parent->domain;
parent->domain->u.file.ref_count++;

datatype->handle_path = NULL;

if (RV_set_object_handle_path(name, parent->handle_path, &datatype->handle_path) < 0)
FUNC_GOTO_ERROR(H5E_DATATYPE, H5E_PATH, NULL, "can't set up object path");

loc_info_out.URI = datatype->URI;
loc_info_out.domain = datatype->domain;
loc_info_out.GCPL_base64 = NULL;
Expand Down Expand Up @@ -550,6 +564,7 @@ RV_datatype_close(void *dt, hid_t dxpl_id, void **req)
if (RV_file_close(_dtype->domain, H5P_DEFAULT, NULL) < 0)
FUNC_DONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close file");

RV_free(_dtype->handle_path);
RV_free(_dtype);
_dtype = NULL;

Expand Down
17 changes: 17 additions & 0 deletions src/rest_vol_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@ RV_file_create(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, h
new_file->u.file.fcpl_id = FAIL;
new_file->u.file.ref_count = 1;

/* Allocate root "path" on heap for consistency with other RV_object_t types */
if ((new_file->handle_path = RV_malloc(2)) == NULL)
FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTALLOC, NULL, "can't allocate space for filepath");

strncpy(new_file->handle_path, "/", 2);

/* Copy the FAPL if it wasn't H5P_DEFAULT, else set up a default one so that
* H5Fget_access_plist() will function correctly. Note that due to the nature
* of VOLs and needing to supply a FAPL to work correctly, the default case
Expand Down Expand Up @@ -344,6 +350,12 @@ RV_file_open(const char *name, unsigned flags, hid_t fapl_id, hid_t dxpl_id, voi
file->u.file.fcpl_id = FAIL;
file->u.file.ref_count = 1;

/* Allocate root "path" on heap for consistency with other RV_object_t types */
if ((file->handle_path = RV_malloc(2)) == NULL)
FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTALLOC, NULL, "can't allocate space for filepath");

strncpy(file->handle_path, "/", 2);

/* Store self-referential pointer in the domain field for this object
* to simplify code for other types of objects
*/
Expand Down Expand Up @@ -728,6 +740,11 @@ RV_file_close(void *file, hid_t dxpl_id, void **req)
_file->u.file.filepath_name = NULL;
}

if (_file->handle_path) {
RV_free(_file->handle_path);
_file->handle_path = NULL;
}

RV_free(_file);
}

Expand Down
Loading

0 comments on commit 875b8ce

Please sign in to comment.