Skip to content

Commit

Permalink
Implement H5Fget_obj_ids with H5VLwrap_register
Browse files Browse the repository at this point in the history
This implementation creates new hid_t handles to existing objects,
rather than returning existing hid_t handles as the API specifies,
since accessing existing external handles from the VOL may be
impossible.

This implementation (and a minor change to how connection info is set
in RV_file_create) is sufficient to run h5py against the REST VOL,
although since h5py's tests don't work with HSDS paths, it's
unclear how much of the API works.
  • Loading branch information
mattjala committed Aug 8, 2023
1 parent 054aa91 commit 609a0d2
Show file tree
Hide file tree
Showing 2 changed files with 226 additions and 14 deletions.
238 changes: 225 additions & 13 deletions src/rest_vol_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ RV_file_create(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, h
if (fapl_id == H5P_FILE_ACCESS_DEFAULT)
if (H5_rest_set_connection_information() < 0)
FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL,
"can't set REST VOL connector connection information");
"can't set REST VOL connector connection information");

/* Allocate and setup internal File struct */
if (NULL == (new_file = (RV_object_t *)RV_malloc(sizeof(*new_file))))
Expand Down Expand Up @@ -476,6 +476,18 @@ RV_file_get(void *obj, H5VL_file_get_args_t *args, hid_t dxpl_id, void **req)
RV_object_t *_obj = (RV_object_t *)obj;
herr_t ret_value = SUCCEED;

unsigned int requested_types = 0;
unsigned int type_flag = 0;
H5I_type_t type = H5I_UNINIT;
RV_type_info *type_info = NULL;

H5I_type_t object_types[5] = {H5I_FILE, H5I_GROUP, H5I_DATASET, H5I_DATATYPE, H5I_ATTR};
unsigned int object_types_flags[5] = {H5F_OBJ_FILE, H5F_OBJ_GROUP, H5F_OBJ_DATASET,
H5F_OBJ_DATATYPE, H5F_OBJ_ATTR};

size_t num_object_types = sizeof(object_types) / sizeof(H5I_type_t);
RV_object_t *ref_copy_obj = NULL;

#ifdef RV_CONNECTOR_DEBUG
printf("-> Received file get call with following parameters:\n");
printf(" - File get call type: %s\n", file_get_type_to_string(args->op_type));
Expand Down Expand Up @@ -543,18 +555,12 @@ RV_file_get(void *obj, H5VL_file_get_args_t *args, hid_t dxpl_id, void **req)

/* H5Fget_obj_count */
case H5VL_FILE_GET_OBJ_COUNT:
unsigned int requested_types = args->args.get_obj_count.types;

H5I_type_t object_types[5] = {H5I_FILE, H5I_GROUP, H5I_DATASET, H5I_DATATYPE, H5I_ATTR};
unsigned int object_types_flags[5] = {H5F_OBJ_FILE, H5F_OBJ_GROUP, H5F_OBJ_DATASET,
H5F_OBJ_DATATYPE, H5F_OBJ_ATTR};

size_t num_object_types = sizeof(object_types) / sizeof(H5I_type_t);
requested_types = args->args.get_obj_count.types;

for (size_t i = 0; i < num_object_types; i++) {
H5I_type_t type = object_types[i];
unsigned int type_flag = object_types_flags[i];
RV_type_info *type_info = RV_type_info_array_g[type];
type = object_types[i];
type_flag = object_types_flags[i];
type_info = RV_type_info_array_g[type];

/* Iterate through each open instance of type in the global hash table */
rv_hash_table_iter_t iterator;
Expand All @@ -569,7 +575,7 @@ RV_file_get(void *obj, H5VL_file_get_args_t *args, hid_t dxpl_id, void **req)
if (!(requested_types & type_flag))
continue;

/* Don't count object if it's in a different file */
/* Don't count object if it's in a different file. */
if ((strcmp(_obj->domain->u.file.filepath_name, curr_obj->domain->u.file.filepath_name)))
continue;

Expand All @@ -581,7 +587,185 @@ RV_file_get(void *obj, H5VL_file_get_args_t *args, hid_t dxpl_id, void **req)

/* H5Fget_obj_ids */
case H5VL_FILE_GET_OBJ_IDS:
FUNC_GOTO_ERROR(H5E_FILE, H5E_UNSUPPORTED, FAIL, "H5Fget_obj_ids is unsupported");

if (args->args.get_obj_ids.max_objs <= 0)
FUNC_GOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "invalid max object parameter");

if (args->args.get_obj_ids.oid_list == NULL)
FUNC_GOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "given object id list buffer is NULL");

if (args->args.get_obj_ids.count == NULL)
FUNC_GOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "given object id count buffer is NULL");

*args->args.get_obj_ids.count = 0;
unsigned int requested_types = args->args.get_obj_ids.types;

hid_t obj_id = H5I_INVALID_HID;
hid_t *obj_id_list = args->args.get_obj_ids.oid_list;

for (size_t i = 0; i < num_object_types; i++) {
type = object_types[i];
type_flag = object_types_flags[i];
type_info = RV_type_info_array_g[type];

/* Iterate through each open instance of type in the global hash table */
rv_hash_table_iter_t iterator;

rv_hash_table_iterate(type_info->table, &iterator);

while (rv_hash_table_iter_has_more(&iterator)) {

RV_object_t *curr_obj = (RV_object_t *)rv_hash_table_iter_next(&iterator);

/* Requested types must include current object type */
if (!(requested_types & type_flag))
continue;

/* Don't count object if it's in a different file. */
if ((strcmp(_obj->domain->u.file.filepath_name, curr_obj->domain->u.file.filepath_name)))
continue;

/* Wrap object to obtain an hid_t (pointing to an object that already exists) */

/* Increment reference count so that closing the wrapped object does not leave invalid memory */
if (NULL == (ref_copy_obj = RV_malloc(sizeof(RV_object_t))))
FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, FAIL,
"can't allocate copy of attribute's parent object");

memcpy(ref_copy_obj, curr_obj, sizeof(RV_object_t));
/* Increment refs for top-level file */
curr_obj->domain->u.file.ref_count++;

/* Increment refs for specific type */

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

strncpy(ref_copy_obj->handle_path, curr_obj->handle_path,
strlen(curr_obj->handle_path) + 1);

switch (type) {
case H5I_FILE:
/* Copy fapl, fcpl, and filepath name to new object */

if (H5I_INVALID_HID ==
(ref_copy_obj->u.file.fapl_id = H5Pcopy(curr_obj->u.file.fapl_id)))
FUNC_GOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, FAIL, "can't copy FAPL");
if (H5I_INVALID_HID ==
(ref_copy_obj->u.file.fcpl_id = H5Pcopy(curr_obj->u.file.fcpl_id)))
FUNC_GOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, FAIL, "can't copy FCPL");
if (NULL == (ref_copy_obj->u.file.filepath_name =
RV_malloc(strlen(curr_obj->u.file.filepath_name) + 1)))
FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL,
"can't allocate space for copied filepath_name object");

strncpy(ref_copy_obj->u.file.filepath_name, curr_obj->u.file.filepath_name,
strlen(curr_obj->u.file.filepath_name) + 1);

/* This is a copy of the file, not a reference to the same memory */
curr_obj->domain->u.file.ref_count--;
break;
case H5I_GROUP:

if (curr_obj->u.group.gcpl_id != H5P_GROUP_CREATE_DEFAULT) {
if (H5Iinc_ref(curr_obj->u.group.gcpl_id) < 0)
FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTINC, FAIL,
"can't increment field's ref. count for copy of "
"attribute's parent group");
}

break;

case H5I_DATATYPE:

if (H5Iinc_ref(curr_obj->u.datatype.dtype_id) < 0)
FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTINC, FAIL,
"can't increment field's ref. count for copy of attribute's "
"parent datatype");
if (H5Iinc_ref(curr_obj->u.datatype.tcpl_id) < 0)
FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTINC, FAIL,
"can't increment field's ref. count for copy of attribute's "
"parent datatype");
break;

case H5I_DATASET:

if (H5Iinc_ref(curr_obj->u.dataset.dtype_id) < 0)
FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTINC, FAIL,
"can't increment field's ref. count for copy of attribute's "
"parent dataset");
if (H5Iinc_ref(curr_obj->u.dataset.space_id) < 0)
FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTINC, FAIL,
"can't increment field's ref. count for copy of attribute's "
"parent dataset");
if (H5Iinc_ref(curr_obj->u.dataset.dapl_id) < 0)
FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTINC, FAIL,
"can't increment field's ref. count for copy of attribute's "
"parent dataset");
if (H5Iinc_ref(curr_obj->u.dataset.dcpl_id) < 0)
FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTINC, FAIL,
"can't increment field's ref. count for copy of attribute's "
"parent dataset");
break;

case H5I_ATTR:
case H5I_UNINIT:
case H5I_BADID:
case H5I_DATASPACE:
case H5I_VFL:
case H5I_VOL:
case H5I_GENPROP_CLS:
case H5I_GENPROP_LST:
case H5I_ERROR_CLASS:
case H5I_ERROR_MSG:
case H5I_ERROR_STACK:
case H5I_NTYPES:
default:
FUNC_GOTO_ERROR(H5E_ATTR, H5E_BADVALUE, FAIL,
"parent object not a file, group, datatype or dataset");
} /* end switch */

/* In order to appease H5VLwrap_register(), ensure that the proper interface is initialized before
* calling it, just as in the code for link iteration.
*/

if (H5I_FILE == curr_obj->obj_type || H5I_GROUP == curr_obj->obj_type) {
H5E_BEGIN_TRY
{
H5Gopen2(H5I_INVALID_HID, NULL, H5P_DEFAULT);
}
H5E_END_TRY;
}
else if (H5I_DATATYPE == curr_obj->obj_type) {
H5E_BEGIN_TRY
{
H5Topen2(H5I_INVALID_HID, NULL, H5P_DEFAULT);
}
H5E_END_TRY;
}
else if (H5I_DATASET == curr_obj->obj_type) {
H5E_BEGIN_TRY
{
H5Dopen2(H5I_INVALID_HID, NULL, H5P_DEFAULT);
}
H5E_END_TRY;
} else {
H5E_BEGIN_TRY
{
H5Aopen(H5I_INVALID_HID, NULL, H5P_DEFAULT);
}
H5E_END_TRY;
}

if (((obj_id = H5VLwrap_register((void*) ref_copy_obj, curr_obj->obj_type)) == H5I_INVALID_HID))
FUNC_GOTO_ERROR(H5E_FILE, H5E_VOL, FAIL, "unable to register object ID");

obj_id_list[*args->args.get_obj_ids.count] = obj_id;
*args->args.get_obj_ids.count++;
}
}

break;

default:
Expand All @@ -591,6 +775,34 @@ RV_file_get(void *obj, H5VL_file_get_args_t *args, hid_t dxpl_id, void **req)
done:
PRINT_ERROR_STACK;

if (ret_value < 0) {
RV_free(ref_copy_obj);

if (args->op_type == H5VL_FILE_GET_OBJ_IDS)
for (size_t i = 0; i < *args->args.get_obj_ids.count; i++)
if (H5Iis_valid(args->args.get_obj_ids.oid_list[i]) && ((type = H5Iget_type(args->args.get_obj_ids.oid_list[i])) != H5I_BADID)) {
switch(type) {
case (H5I_FILE):
H5Fclose(args->args.get_obj_ids.oid_list[i]);
break;
case (H5I_GROUP):
H5Gclose(args->args.get_obj_ids.oid_list[i]);
break;
case (H5I_DATASET):
H5Dclose(args->args.get_obj_ids.oid_list[i]);
break;
case (H5I_DATATYPE):
H5Tclose(args->args.get_obj_ids.oid_list[i]);
break;
case (H5I_ATTR):
H5Aclose(args->args.get_obj_ids.oid_list[i]);
break;
default:
break;
}

}
}
return ret_value;
} /* end RV_file_get() */

Expand Down
2 changes: 1 addition & 1 deletion src/rest_vol_group.c
Original file line number Diff line number Diff line change
Expand Up @@ -685,7 +685,7 @@ RV_group_close(void *grp, hid_t dxpl_id, void **req)
{
RV_object_t *_grp = (RV_object_t *)grp;
herr_t ret_value = SUCCEED;

if (!_grp)
FUNC_GOTO_DONE(SUCCEED);

Expand Down

0 comments on commit 609a0d2

Please sign in to comment.