Skip to content

Commit

Permalink
Implement H5Fget_obj_count without global info
Browse files Browse the repository at this point in the history
This implementation doesn't use RV_type_info_array_g, unlike the proposed version in HDFGroup#49.

H5Fget_obj_count, when file_id = H5F_OBJ_ALL, erroneously counts copied transient datatypes as open objects. This is especially noticeable since the VOL copies the datatype whenever it creates an attribute or a dataset. This is an inherited issue from the HDF5 library itself and needs to be fixed there (see HDFGroup/hdf5#3316).
  • Loading branch information
mattjala committed Sep 25, 2023
1 parent 6123ce7 commit 5e78cee
Showing 1 changed file with 107 additions and 4 deletions.
111 changes: 107 additions & 4 deletions src/rest_vol_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@
#include "rest_vol_file.h"

herr_t RV_iterate_copy_hid_cb(hid_t obj_id, void *udata);
herr_t RV_iterate_count_obj_cb(hid_t obj_id, void *udata);

struct get_obj_count_udata_t {
size_t obj_count;
char *local_filename;
} typedef get_obj_count_udata_t;

struct get_obj_ids_udata_t {
hid_t *obj_id_list;
Expand Down Expand Up @@ -485,6 +491,7 @@ 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;

#ifdef RV_CONNECTOR_DEBUG
printf("-> Received file get call with following parameters:\n");
Expand Down Expand Up @@ -553,12 +560,46 @@ 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:
FUNC_GOTO_ERROR(H5E_FILE, H5E_UNSUPPORTED, FAIL, "H5Fget_obj_count is unsupported");
break;
requested_types = args->args.get_obj_count.types;

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

requested_types = args->args.get_obj_ids.types;

get_obj_count_udata_t count_cb_args;
count_cb_args.obj_count = 0;

/* Requests with H5F_OBJ_ALL for file_id do not pass through the
* VOL layer - assume single-file request */
count_cb_args.local_filename = _obj->domain->u.file.filepath_name;

if (requested_types & H5F_OBJ_FILE)
if (H5Iiterate(H5I_FILE, RV_iterate_count_obj_cb, &count_cb_args) < 0)
FUNC_GOTO_ERROR(H5E_FILE, H5E_OBJECTITERERROR, FAIL, "can't iterate over file ids");

if (requested_types & H5F_OBJ_GROUP)
if (H5Iiterate(H5I_GROUP, RV_iterate_count_obj_cb, &count_cb_args) < 0)
FUNC_GOTO_ERROR(H5E_FILE, H5E_OBJECTITERERROR, FAIL, "can't iterate over group ids");

if (requested_types & H5F_OBJ_DATATYPE)
if (H5Iiterate(H5I_DATATYPE, RV_iterate_count_obj_cb, &count_cb_args) < 0)
FUNC_GOTO_ERROR(H5E_FILE, H5E_OBJECTITERERROR, FAIL, "can't iterate over datatype ids");

if (requested_types & H5F_OBJ_DATASET)
if (H5Iiterate(H5I_DATASET, RV_iterate_count_obj_cb, &count_cb_args) < 0)
FUNC_GOTO_ERROR(H5E_FILE, H5E_OBJECTITERERROR, FAIL, "can't iterate over dataset ids");

if (requested_types & H5F_OBJ_ATTR)
if (H5Iiterate(H5I_ATTR, RV_iterate_count_obj_cb, &count_cb_args) < 0)
FUNC_GOTO_ERROR(H5E_FILE, H5E_OBJECTITERERROR, FAIL, "can't iterate over attribute ids");

/* Return count */
*args->args.get_obj_count.count = count_cb_args.obj_count;

break;
/* H5Fget_obj_ids */
case H5VL_FILE_GET_OBJ_IDS:

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

Expand All @@ -572,7 +613,7 @@ RV_file_get(void *obj, H5VL_file_get_args_t *args, hid_t dxpl_id, void **req)
FUNC_GOTO_DONE(SUCCEED);

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

get_obj_ids_udata_t id_list;
id_list.obj_id_list = args->args.get_obj_ids.oid_list;
Expand Down Expand Up @@ -893,5 +934,67 @@ RV_iterate_copy_hid_cb(hid_t obj_id, void *udata)
id_list->obj_count++;

done:
return ret_value;
}

/*-------------------------------------------------------------------------
* Function: RV_iterate_copy_hid_cb
*
* Purpose: Callback for H5Iiterate() that count the number
* of open objects in the library.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Matthew Larson
* September, 2023
*/
herr_t
RV_iterate_count_obj_cb(hid_t obj_id, void *udata) {
herr_t ret_value = H5_ITER_CONT;
get_obj_count_udata_t *count_cb_args = (get_obj_count_udata_t *)udata;
char *containing_filename = NULL;
ssize_t containing_filename_len = 0;
H5I_type_t id_type = H5I_UNINIT;
htri_t is_committed = FALSE;

/* Do not copy the id of transient datatypes */
if ((id_type = H5Iget_type(obj_id)) < 0)
FUNC_GOTO_ERROR(H5E_CALLBACK, H5E_ID, FAIL, "can't get identifier type");

if (id_type == H5I_DATATYPE) {
if ((is_committed = H5Tcommitted(obj_id)) < 0)
FUNC_GOTO_ERROR(H5E_CALLBACK, H5E_DATATYPE, FAIL, "can't check if datatype is committed");

if (!is_committed)
FUNC_GOTO_DONE(H5_ITER_CONT);
}

if (count_cb_args->local_filename) {
/* Require that obj id reside in local file */

/* Get size of name */
if ((containing_filename_len = H5Fget_name(obj_id, NULL, 0)) < 0)
FUNC_GOTO_ERROR(H5E_CALLBACK, H5E_CANTGET, FAIL, "unable to get length of filename");

if ((containing_filename = RV_malloc((size_t)containing_filename_len + 1)) == NULL)
FUNC_GOTO_ERROR(H5E_CALLBACK, H5E_CANTALLOC, FAIL, "can't allocate space for filename");

/* Get name */
if (H5Fget_name(obj_id, containing_filename, (size_t)containing_filename_len + 1) < 0)
FUNC_GOTO_ERROR(H5E_CALLBACK, H5E_CANTGET, FAIL, "unable to get filename");

if (!strcmp(count_cb_args->local_filename, containing_filename)) {
count_cb_args->obj_count++;
}
}
else {
count_cb_args->obj_count++;
}

done:

if (containing_filename)
RV_free(containing_filename);

return ret_value;
}

0 comments on commit 5e78cee

Please sign in to comment.