mirror of
https://github.com/HDFGroup/hdf5.git
synced 2025-04-24 17:51:25 +08:00
Merge pull request #2063 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:
commit
0772b975d1
101
src/H5Tref.c
101
src/H5Tref.c
@ -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 */
|
||||
|
Loading…
x
Reference in New Issue
Block a user