2
0
mirror of https://github.com/HDFGroup/hdf5.git synced 2025-04-24 17:51:25 +08:00

Merge pull request in HDFFV/hdf5 from ~NFORTNE2/hdf5_naf:vol_file_cmp to develop

* commit '40b2658b4b266b4dc65ec3db2897e0aaf54f8e42':
  Fix missing free in H5T__ref_mem_read()
  Fix bugs in H5VL file comparison code.  Add short circuit success to H5VL_cmp_connector_cls().
  Implement file comparison VOL callback.  Other changes to allow references to work with non-native connectors.  There is a bug somewhere.
This commit is contained in:
Neil Fortner 2019-11-30 18:44:02 -06:00
commit 0772b975d1
5 changed files with 163 additions and 34 deletions

@ -345,10 +345,12 @@ static size_t
H5T__ref_mem_getsize(H5VL_object_t H5_ATTR_UNUSED *src_file, const void *src_buf,
size_t H5_ATTR_UNUSED src_size, H5VL_object_t *dst_file, hbool_t *dst_copy)
{
H5F_t *src_f;
H5F_t *dst_f;
H5VL_object_t *vol_obj = NULL;
const H5R_ref_priv_t *src_ref = (const H5R_ref_priv_t *)src_buf;
hbool_t files_equal = FALSE;
char file_name_buf_static[256];
char *file_name_buf_dyn = NULL;
ssize_t file_name_len;
unsigned flags = 0;
size_t ret_value = 0;
@ -361,27 +363,43 @@ H5T__ref_mem_getsize(H5VL_object_t H5_ATTR_UNUSED *src_file, const void *src_buf
if(NULL == (vol_obj = H5VL_vol_object(src_ref->loc_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "invalid location identifier")
/* We should assert here that the terminal connector is H5VL_NATIVE once
* there is a facility to do so -NAF 2019/10/30 */
/* Retrieve files from VOL objects */
if(NULL == (src_f = (H5F_t *)H5VL_object_data(vol_obj)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "invalid VOL object")
if(NULL == (dst_f = (H5F_t *)H5VL_object_data(dst_file)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "invalid VOL object")
/* Set external flag if referenced file is not destination file */
flags |= (src_f->shared != dst_f->shared) ? H5R_IS_EXTERNAL : 0;
if(H5VL_file_specific(vol_obj, H5VL_FILE_IS_EQUAL, H5P_DATASET_XFER_DEFAULT, NULL, dst_file, &files_equal) < 0)
HGOTO_ERROR(H5E_REFERENCE, H5E_CANTCOMPARE, 0, "can't check if files are equal")
flags |= !files_equal ? H5R_IS_EXTERNAL : 0;
/* Force re-calculating encoding size if any flags are set */
if(flags || !src_ref->encode_size) {
/* Pass the correct encoding version for the selection depending on the
* file libver bounds, this is later retrieved in H5S hyper encode */
if(src_ref->type == (int8_t)H5R_DATASET_REGION2)
H5CX_set_libver_bounds(dst_f);
if(src_ref->type == (int8_t)H5R_DATASET_REGION2) {
/* Temporary hack to check if this is the native connector. We need to
* add a way to check if the terminal connector is native. For now this
* will break passthroughs, but it's needed for other VOL connectors to
* work. -NAF */
if(dst_file->connector->cls->value == H5VL_NATIVE_VALUE) {
H5F_t *dst_f;
if(NULL == (dst_f = (H5F_t *)H5VL_object_data(dst_file)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "invalid VOL object")
H5CX_set_libver_bounds(dst_f);
} /* end if */
else
H5CX_set_libver_bounds(NULL);
} /* end if */
/* Get file name */
if(H5VL_file_get(vol_obj, H5VL_FILE_GET_NAME, H5P_DATASET_XFER_DEFAULT, NULL, H5I_FILE, sizeof(file_name_buf_static), file_name_buf_static, &file_name_len) < 0)
HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, 0, "can't get file name")
if(file_name_len >= (ssize_t)sizeof(file_name_buf_static)) {
if(NULL == (file_name_buf_dyn = (char *)H5MM_malloc((size_t)file_name_len + 1)))
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, 0, "can't allocate space for file name")
if(H5VL_file_get(vol_obj, H5VL_FILE_GET_NAME, H5P_DATASET_XFER_DEFAULT, NULL, H5I_FILE, (size_t)file_name_len + 1, file_name_buf_dyn, &file_name_len) < 0)
HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, 0, "can't get file name")
} /* end if */
/* Determine encoding size */
if(H5R__encode(H5F_ACTUAL_NAME(src_f), src_ref, NULL, &ret_value, flags) < 0)
if(H5R__encode(file_name_buf_dyn ? file_name_buf_dyn : file_name_buf_static, src_ref, NULL, &ret_value, flags) < 0)
HGOTO_ERROR(H5E_REFERENCE, H5E_CANTENCODE, 0, "unable to determine encoding size")
} else {
/* Can do a direct copy and skip blob decoding */
@ -393,6 +411,8 @@ H5T__ref_mem_getsize(H5VL_object_t H5_ATTR_UNUSED *src_file, const void *src_buf
}
done:
H5MM_xfree(file_name_buf_dyn);
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5T__ref_mem_getsize() */
@ -411,10 +431,12 @@ H5T__ref_mem_read(H5VL_object_t H5_ATTR_UNUSED *src_file, const void *src_buf,
size_t H5_ATTR_UNUSED src_size, H5VL_object_t *dst_file, void *dst_buf,
size_t dst_size)
{
H5F_t *src_f;
H5F_t *dst_f;
H5VL_object_t *vol_obj = NULL;
const H5R_ref_priv_t *src_ref = (const H5R_ref_priv_t *)src_buf;
hbool_t files_equal = FALSE;
char file_name_buf_static[256];
char *file_name_buf_dyn = NULL;
ssize_t file_name_len;
unsigned flags = 0;
herr_t ret_value = SUCCEED;
@ -430,28 +452,46 @@ H5T__ref_mem_read(H5VL_object_t H5_ATTR_UNUSED *src_file, const void *src_buf,
if(NULL == (vol_obj = H5VL_vol_object(src_ref->loc_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "invalid location identifier")
/* We should assert here that the terminal connector is H5VL_NATIVE once
* there is a facility to do so -NAF 2019/10/30 */
/* Retrieve files from VOL objects */
if(NULL == (src_f = (H5F_t *)H5VL_object_data(vol_obj)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "invalid VOL object")
if(NULL == (dst_f = (H5F_t *)H5VL_object_data(dst_file)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "invalid VOL object")
/* Set external flag if referenced file is not destination file */
flags |= (src_f->shared != dst_f->shared) ? H5R_IS_EXTERNAL : 0;
if(H5VL_file_specific(vol_obj, H5VL_FILE_IS_EQUAL, H5P_DATASET_XFER_DEFAULT, NULL, dst_file, &files_equal) < 0)
HGOTO_ERROR(H5E_REFERENCE, H5E_CANTCOMPARE, FAIL, "can't check if files are equal")
flags |= !files_equal ? H5R_IS_EXTERNAL : 0;
/* Pass the correct encoding version for the selection depending on the
* file libver bounds, this is later retrieved in H5S hyper encode */
if(src_ref->type == (int8_t)H5R_DATASET_REGION2)
H5CX_set_libver_bounds(dst_f);
if(src_ref->type == (int8_t)H5R_DATASET_REGION2) {
/* Temporary hack to check if this is the native connector. We need to
* add a way to check if the terminal connector is native. For now this
* will break passthroughs, but it's needed for other VOL connectors to
* work. -NAF */
if(dst_file->connector->cls->value == H5VL_NATIVE_VALUE) {
H5F_t *dst_f;
if(NULL == (dst_f = (H5F_t *)H5VL_object_data(dst_file)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "invalid VOL object")
H5CX_set_libver_bounds(dst_f);
} /* end if */
else
H5CX_set_libver_bounds(NULL);
} /* end if */
/* Get file name */
if(H5VL_file_get(vol_obj, H5VL_FILE_GET_NAME, H5P_DATASET_XFER_DEFAULT, NULL, H5I_FILE, sizeof(file_name_buf_static), file_name_buf_static, &file_name_len) < 0)
HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, 0, "can't get file name")
if(file_name_len >= (ssize_t)sizeof(file_name_buf_static)) {
if(NULL == (file_name_buf_dyn = (char *)H5MM_malloc((size_t)file_name_len + 1)))
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, 0, "can't allocate space for file name")
if(H5VL_file_get(vol_obj, H5VL_FILE_GET_NAME, H5P_DATASET_XFER_DEFAULT, NULL, H5I_FILE, (size_t)file_name_len + 1, file_name_buf_dyn, &file_name_len) < 0)
HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, 0, "can't get file name")
} /* end if */
/* Encode reference */
if(H5R__encode(H5F_ACTUAL_NAME(src_f), src_ref, (unsigned char *)dst_buf, &dst_size, flags) < 0)
if(H5R__encode(file_name_buf_dyn ? file_name_buf_dyn : file_name_buf_static, src_ref, (unsigned char *)dst_buf, &dst_size, flags) < 0)
HGOTO_ERROR(H5E_REFERENCE, H5E_CANTENCODE, FAIL, "Cannot encode reference")
done:
H5MM_xfree(file_name_buf_dyn);
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5T__ref_mem_read() */
@ -1067,3 +1107,4 @@ H5T_ref_reclaim(void *elem, const H5T_t *dt)
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5T_ref_reclaim() */

@ -101,6 +101,8 @@ static void * H5VL__file_open(const H5VL_class_t *cls, const char *name,
unsigned flags, hid_t fapl_id, hid_t dxpl_id, void **req);
static herr_t H5VL__file_get(void *obj, const H5VL_class_t *cls, H5VL_file_get_t get_type,
hid_t dxpl_id, void **req, va_list arguments);
static herr_t H5VL__file_specific_wrap_va_list(void *obj, const H5VL_class_t *cls,
H5VL_file_specific_t specific_type, hid_t dxpl_id, void **req, ...);
static herr_t H5VL__file_specific(void *obj, const H5VL_class_t *cls, H5VL_file_specific_t specific_type,
hid_t dxpl_id, void **req, va_list arguments);
static herr_t H5VL__file_optional(void *obj, const H5VL_class_t *cls, hid_t dxpl_id,
@ -2987,6 +2989,43 @@ done:
FUNC_LEAVE_API_NOINIT(ret_value)
} /* end H5VLfile_get() */
/*-------------------------------------------------------------------------
* Function: H5VL__file_specific_wrap_va_list
*
* Purpose: Perform File specific operations through the VOL. Just
* starts a va_list and passes it to the connector's
* callback. Needed when the VOL layer needs to replace one
* of the variable arguments.
*
* Return: Success: Non-negative
* Failure: Negative
*
*-------------------------------------------------------------------------
*/
static herr_t
H5VL__file_specific_wrap_va_list(void *obj, const H5VL_class_t *cls,
H5VL_file_specific_t specific_type, hid_t dxpl_id, void **req, ...)
{
va_list arguments; /* Argument list passed from the API call */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_STATIC
/* Start access to the varargs, so they are available in all situations below */
HDva_start(arguments, req);
/* Call the corresponding VOL callback */
if((cls->file_cls.specific)(obj, specific_type, dxpl_id, req, arguments) < 0)
HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "file specific failed")
done:
/* End access to the va_list */
HDva_end(arguments);
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5VL__file_specific_wrap_va_list() */
/*-------------------------------------------------------------------------
* Function: H5VL__file_specific
@ -3010,9 +3049,38 @@ H5VL__file_specific(void *obj, const H5VL_class_t *cls, H5VL_file_specific_t spe
if(NULL == cls->file_cls.specific)
HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "VOL connector has no 'file specific' method")
/* Call the corresponding VOL callback */
if((cls->file_cls.specific)(obj, specific_type, dxpl_id, req, arguments) < 0)
HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "file specific failed")
/* Special handling for file is equal */
if(specific_type == H5VL_FILE_IS_EQUAL) {
va_list tmp_args; /* Argument list passed from the API call */
H5VL_object_t *vol_obj2; /* Second VOL object */
hbool_t *is_equal; /* Output variable */
int cmp_value; /* Comparison result */
/* Get parameters */
HDva_copy(tmp_args, arguments);
vol_obj2 = HDva_arg(tmp_args, H5VL_object_t *);
is_equal = HDva_arg(tmp_args, hbool_t *);
HDva_end(tmp_args);
HDassert(vol_obj2);
/* Compare connector classes */
if(H5VL_cmp_connector_cls(&cmp_value, cls, vol_obj2->connector->cls) < 0)
HGOTO_ERROR(H5E_VOL, H5E_CANTCOMPARE, FAIL, "can't compare connector classes")
/* If the classes are different the files are different */
if(cmp_value)
*is_equal = FALSE;
else
/* Make callback (need to extract data from vol_obj2 and redo the
* va_list) */
if(H5VL__file_specific_wrap_va_list(obj, cls, specific_type, dxpl_id, req, vol_obj2->data, is_equal) < 0)
HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "file specific failed")
} /* end if */
else
/* Call the corresponding VOL callback */
if((cls->file_cls.specific)(obj, specific_type, dxpl_id, req, arguments) < 0)
HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "file specific failed")
done:
FUNC_LEAVE_NOAPI(ret_value)

@ -122,7 +122,8 @@ typedef enum H5VL_file_specific_t {
H5VL_FILE_MOUNT, /* Mount a file */
H5VL_FILE_UNMOUNT, /* Unmount a file */
H5VL_FILE_IS_ACCESSIBLE, /* Check if a file is accessible */
H5VL_FILE_DELETE /* Delete a file */
H5VL_FILE_DELETE, /* Delete a file */
H5VL_FILE_IS_EQUAL /* Check if two files are the same */
} H5VL_file_specific_t;
/* types for group GET callback */

@ -1639,6 +1639,12 @@ H5VL_cmp_connector_cls(int *cmp_value, const H5VL_class_t *cls1, const H5VL_clas
HDassert(cls1);
HDassert(cls2);
/* If the pointers are the same the classes are the same */
if(cls1 == cls2) {
*cmp_value = 0;
HGOTO_DONE(SUCCEED);
} /* end if */
/* Compare connector "values" */
if(cls1->value < cls2->value) {
*cmp_value = -1;

@ -418,6 +418,19 @@ H5VL__native_file_specific(void *obj, H5VL_file_specific_t specific_type,
break;
}
/* Check if two files are the same */
case H5VL_FILE_IS_EQUAL:
{
H5F_t *file2 = (H5F_t *)HDva_arg(arguments, void *);
hbool_t *is_equal = HDva_arg(arguments, hbool_t *);
if(!obj || !file2)
*is_equal = FALSE;
else
*is_equal = (((H5F_t *)obj)->shared == file2->shared);
break;
}
default:
HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "invalid specific operation")
} /* end switch */