diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2012-03-28 19:45:49 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2012-03-28 19:45:49 (GMT) |
commit | 35a0e27e885e63c40449483733c105649e3c99dc (patch) | |
tree | 292d83e7cab35c0451ad2811648617bf39440d44 /src/H5Pocpypl.c | |
parent | f1df456412c935f399405960348d02d804b81f2e (diff) | |
download | hdf5-35a0e27e885e63c40449483733c105649e3c99dc.zip hdf5-35a0e27e885e63c40449483733c105649e3c99dc.tar.gz hdf5-35a0e27e885e63c40449483733c105649e3c99dc.tar.bz2 |
[svn-r22171] Description:
Bring "merge committed datatypes during H5Ocopy" feature from branch to
trunk. (Also has some minor bugfixes with it)
Tested on:
Mac OSX/64 10.7.3 (amazon) w/debug
(h5committest coming up)
Diffstat (limited to 'src/H5Pocpypl.c')
-rw-r--r-- | src/H5Pocpypl.c | 443 |
1 files changed, 439 insertions, 4 deletions
diff --git a/src/H5Pocpypl.c b/src/H5Pocpypl.c index af50d80..e61a0d7 100644 --- a/src/H5Pocpypl.c +++ b/src/H5Pocpypl.c @@ -35,7 +35,9 @@ /***********/ #include "H5private.h" /* Generic Functions */ #include "H5Eprivate.h" /* Error handling */ +#include "H5FLprivate.h" /* Free Lists */ #include "H5Iprivate.h" /* IDs */ +#include "H5MMprivate.h" /* Memory management */ #include "H5Ppkg.h" /* Property lists */ @@ -47,7 +49,13 @@ /* Definitions for copy options */ #define H5O_CPY_OPTION_SIZE sizeof(unsigned) #define H5O_CPY_OPTION_DEF 0 - +/* Definitions for merge committed dtype list */ +#define H5O_CPY_MERGE_COMM_DT_LIST_SIZE sizeof(char *) +#define H5O_CPY_MERGE_COMM_DT_LIST_DEF NULL +#define H5O_CPY_MERGE_COMM_DT_LIST_CMP H5P_ocpy_merge_comm_dt_list_cmp +/* Definitions for callback function when completing the search for a matching committed datatype from the committed dtype list */ +#define H5O_CPY_MCDT_SEARCH_CB_SIZE sizeof(H5O_mcdt_cb_info_t) +#define H5O_CPY_MCDT_SEARCH_CB_DEF {NULL,NULL} /******************/ /* Local Typedefs */ @@ -63,8 +71,17 @@ /* Local Prototypes */ /********************/ +/* General routines */ +static H5O_copy_dtype_merge_list_t *H5P_free_merge_comm_dtype_list(H5O_copy_dtype_merge_list_t *dt_list); + /* Property class callbacks */ static herr_t H5P_ocpy_reg_prop(H5P_genclass_t *pclass); +static herr_t H5P_ocpy_copy(hid_t dst_plist_id, hid_t src_plist_id, + void *copy_data); +static herr_t H5P_ocpy_close(hid_t ocpypl_id, void *close_data); + +/* Property callbacks */ +static int H5P_ocpy_merge_comm_dt_list_cmp(const void *value1, const void *value2, size_t size); /*********************/ @@ -80,9 +97,9 @@ const H5P_libclass_t H5P_CLS_OCPY[1] = {{ H5P_ocpy_reg_prop, /* Default property registration routine */ NULL, /* Class creation callback */ NULL, /* Class creation callback info */ - NULL, /* Class copy callback */ + H5P_ocpy_copy, /* Class copy callback */ NULL, /* Class copy callback info */ - NULL, /* Class close callback */ + H5P_ocpy_close, /* Class close callback */ NULL /* Class close callback info */ }}; @@ -96,6 +113,9 @@ const H5P_libclass_t H5P_CLS_OCPY[1] = {{ /* Local Variables */ /*******************/ +/* Declare a free list to manage the H5O_copy_dtype_merge_list_t struct */ +H5FL_DEFINE(H5O_copy_dtype_merge_list_t); + /*------------------------------------------------------------------------- @@ -109,10 +129,12 @@ const H5P_libclass_t H5P_CLS_OCPY[1] = {{ * October 31, 2006 *------------------------------------------------------------------------- */ -herr_t +static herr_t H5P_ocpy_reg_prop(H5P_genclass_t *pclass) { unsigned ocpy_option = H5O_CPY_OPTION_DEF; /* Default object copy flags */ + H5O_copy_dtype_merge_list_t *merge_comm_dtype_list = H5O_CPY_MERGE_COMM_DT_LIST_DEF; /* Default merge committed dtype list */ + H5O_mcdt_cb_info_t mcdt_cb = H5O_CPY_MCDT_SEARCH_CB_DEF; /* Default callback before searching the global list of committed datatypes at destination */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) @@ -121,12 +143,222 @@ H5P_ocpy_reg_prop(H5P_genclass_t *pclass) if(H5P_register_real(pclass, H5O_CPY_OPTION_NAME, H5O_CPY_OPTION_SIZE, &ocpy_option, NULL, NULL, NULL, NULL, NULL, NULL, NULL) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class") + /* Register merge named dtype list property */ + if(H5P_register_real(pclass, H5O_CPY_MERGE_COMM_DT_LIST_NAME, H5O_CPY_MERGE_COMM_DT_LIST_SIZE, &merge_comm_dtype_list, NULL, NULL, NULL, NULL, NULL, H5O_CPY_MERGE_COMM_DT_LIST_CMP, NULL) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class") + + /* Register property for callback when completing the search for a matching named datatype from the named dtype list */ + if(H5P_register_real(pclass, H5O_CPY_MCDT_SEARCH_CB_NAME, H5O_CPY_MCDT_SEARCH_CB_SIZE, &mcdt_cb, NULL, NULL, NULL, NULL, NULL, NULL, NULL) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class") + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5P_ocpy_reg_prop() */ /*------------------------------------------------------------------------- + * Function: H5P_ocpy_copy + * + * Purpose: Callback routine which is called whenever any object + * copy property list is copied. This routine copies + * the properties from the old list to the new list. + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Neil Fortner + * Friday, October 28, 2011 + * + *------------------------------------------------------------------------- + */ +/* ARGSUSED */ +static herr_t +H5P_ocpy_copy(hid_t dst_plist_id, hid_t src_plist_id, void UNUSED *copy_data) +{ + H5O_copy_dtype_merge_list_t *src_dt_list, *dst_dt_list = NULL; /* Source & destination merge named datatype lists */ + H5O_copy_dtype_merge_list_t *dst_dt_list_tail = NULL, *tmp_dt_list = NULL; /* temporary merge named datatype lists */ + H5P_genplist_t *src_plist; /* Pointer to source property list */ + H5P_genplist_t *dst_plist; /* Pointer to destination property list */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Verify property list IDs */ + if(NULL == (dst_plist = (H5P_genplist_t *)H5I_object(dst_plist_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an object copy property list") + if(NULL == (src_plist = (H5P_genplist_t *)H5I_object(src_plist_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an object copy property list") + + /* Get the merge committed dtype list property from the old property list */ + if(H5P_get(src_plist, H5O_CPY_MERGE_COMM_DT_LIST_NAME, &src_dt_list) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get merge named dtype list") + + /* Make copy of merge committed dtype list */ + while(src_dt_list) { + /* Copy src_dt_list */ + if(NULL == (tmp_dt_list = H5FL_CALLOC(H5O_copy_dtype_merge_list_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + if(NULL == (tmp_dt_list->path = H5MM_strdup(src_dt_list->path))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + + /* Add copied node to dest dtype list */ + if(dst_dt_list_tail) { + dst_dt_list_tail->next = tmp_dt_list; + dst_dt_list_tail = tmp_dt_list; + } /* end if */ + else { + dst_dt_list = tmp_dt_list; + dst_dt_list_tail = tmp_dt_list; + } /* end else */ + tmp_dt_list = NULL; + + /* Advance src_dt_list pointer */ + src_dt_list = src_dt_list->next; + } /* end while */ + + /* Set the merge named dtype list property for the destination property list + */ + if(H5P_set(dst_plist, H5O_CPY_MERGE_COMM_DT_LIST_NAME, &dst_dt_list) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set merge committed dtype list") + +done: + if(ret_value < 0) { + dst_dt_list = H5P_free_merge_comm_dtype_list(dst_dt_list); + if(tmp_dt_list) { + tmp_dt_list->path = (char *)H5MM_xfree(tmp_dt_list->path); + tmp_dt_list = H5FL_FREE(H5O_copy_dtype_merge_list_t, tmp_dt_list); + } /* end if */ + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5P_ocpy_copy() */ + + +/*------------------------------------------------------------------------- + * Function: H5P_ocpy_close + * + * Purpose: Callback routine which is called whenever any object copy + * property list is closed. This routine performs any generic + * cleanup needed on the properties the library put into the + * list. + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Neil Fortner + * Friday, October 28, 2011 + * + *------------------------------------------------------------------------- + */ +/* ARGSUSED */ +static herr_t +H5P_ocpy_close(hid_t ocpypl_id, void UNUSED *close_data) +{ + H5O_copy_dtype_merge_list_t *dt_list; /* Merge named datatype list */ + H5P_genplist_t *plist; /* Property list */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Check arguments */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(ocpypl_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an object copy property list") + + /* Get the merge named dtype list property from the old property list */ + if(H5P_get(plist, H5O_CPY_MERGE_COMM_DT_LIST_NAME, &dt_list) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get merge named dtype list") + + /* Free the merge named dtype list */ + dt_list = H5P_free_merge_comm_dtype_list(dt_list); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5P_ocpy_close() */ + + +/*------------------------------------------------------------------------- + * Function: H5P_ocpy_merge_comm_dt_list_cmp + * + * Purpose: Callback routine which is called whenever the merge + * named dtype property in the object copy property list + * is compared. + * + * Return: positive if VALUE1 is greater than VALUE2, negative if + * VALUE2 is greater than VALUE1 and zero if VALUE1 and + * VALUE2 are equal. + * + * Programmer: Neil Fortner + * Friday, October 28, 2011 + * + *------------------------------------------------------------------------- + */ +static int +H5P_ocpy_merge_comm_dt_list_cmp(const void *_dt_list1, const void *_dt_list2, + size_t UNUSED size) +{ + const H5O_copy_dtype_merge_list_t *dt_list1 = *(H5O_copy_dtype_merge_list_t * const *)_dt_list1, /* Create local aliases for values */ + *dt_list2 = *(H5O_copy_dtype_merge_list_t * const *)_dt_list2; + herr_t ret_value = 0; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Sanity check */ + HDassert(_dt_list1); + HDassert(_dt_list2); + HDassert(size == sizeof(H5O_copy_dtype_merge_list_t *)); + + /* Walk through the lists, comparing each path. For the lists to be the + * same, the paths must be in the same order. */ + while(dt_list1 && dt_list2) { + /* Compare paths */ + ret_value = HDstrcmp(dt_list1->path, dt_list2->path); + if(ret_value != 0) HGOTO_DONE(ret_value) + + /* Advance to next node */ + dt_list1 = dt_list1->next; + dt_list2 = dt_list2->next; + } /* end while */ + + /* Check if one list is longer than the other */ + if(dt_list1) HGOTO_DONE(1) + if(dt_list2) HGOTO_DONE(-1) + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5P_ocpy_merge_comm_dt_list_cmp() */ + + +/*------------------------------------------------------------------------- + * Function: H5P_free_merge_comm_dtype_list + * + * Purpose: Frees the provided merge named dtype list + * + * Return: NULL + * + * Programmer: Neil Fortner + * October 27, 2011 + *------------------------------------------------------------------------- + */ +static H5O_copy_dtype_merge_list_t * +H5P_free_merge_comm_dtype_list(H5O_copy_dtype_merge_list_t *dt_list) +{ + H5O_copy_dtype_merge_list_t *tmp_node; + + FUNC_ENTER_NOAPI_NOINIT + + /* Free the list */ + while(dt_list) { + tmp_node = dt_list->next; + (void)H5MM_xfree(dt_list->path); + (void)H5FL_FREE(H5O_copy_dtype_merge_list_t, dt_list); + dt_list = tmp_node; + } /* end while */ + + FUNC_LEAVE_NOAPI(NULL); +} /* H5P_free_merge_comm_dtype_list */ + + +/*------------------------------------------------------------------------- * Function: H5Pset_copy_object * * Purpose: Set properties when copying an object (group, dataset, and datatype) @@ -207,3 +439,206 @@ done: FUNC_LEAVE_API(ret_value) } /* end H5Pget_copy_object() */ + +/*------------------------------------------------------------------------- + * Function: H5Padd_merge_committed_dtype_path + * + * Purpose: Adds path to the list of paths to search first in the + * target file when merging committed datatypes during H5Ocopy + * (i.e. when using the H5O_COPY_MERGE_COMMITTED_DTYPE_FLAG flag + * as set by H5Pset_copy_object). If the source named + * dataype is not found in the list of paths created by this + * function, the entire file will be searched. + * + * Usage: H5Padd_merge_committed_dtype_path(plist_id, path) + * hid_t plist_id; IN: Property list to copy object + * const char *path; IN: Path to add to list + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Neil Fortner + * October 27, 2011 + *------------------------------------------------------------------------- + */ +herr_t +H5Padd_merge_committed_dtype_path(hid_t plist_id, const char *path) +{ + H5P_genplist_t *plist; /* Property list pointer */ + H5O_copy_dtype_merge_list_t *old_list; /* Merge committed dtype list currently present */ + H5O_copy_dtype_merge_list_t *new_obj = NULL; /* New object to add to list */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + + /* Check parameters */ + if(!path) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no path specified") + + /* Get the plist structure */ + if(NULL == (plist = H5P_object_verify(plist_id, H5P_OBJECT_COPY))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + + /* Get dtype list */ + if(H5P_get(plist, H5O_CPY_MERGE_COMM_DT_LIST_NAME, &old_list) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get merge named dtype list") + + /* Add the new path to the list */ + if(NULL == (new_obj = H5FL_CALLOC(H5O_copy_dtype_merge_list_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + if(NULL == (new_obj->path = H5MM_strdup(path))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + new_obj->next = old_list; + + /* Update the list stored in the property list */ + if(H5P_set(plist, H5O_CPY_MERGE_COMM_DT_LIST_NAME, &new_obj) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set merge named dtype list") + +done: + if(ret_value < 0) + if(new_obj) { + new_obj->path = (char *)H5MM_xfree(new_obj->path); + new_obj = H5FL_FREE(H5O_copy_dtype_merge_list_t, new_obj); + } /* end if */ + + FUNC_LEAVE_API(ret_value) +} /* end H5Padd_merge_committed_dtype_path() */ + + +/*------------------------------------------------------------------------- + * Function: H5Pfree_merge_committed_dtype_paths + * + * Purpose: Frees and clears the list of paths created by + * H5Padd_merge_committed_dtype_path. A new list may then be + * created by calling H5Padd_merge_committed_dtype_path again. + * + * Usage: H5Pfree_merge_committed_dtype_paths(plist_id) + * hid_t plist_id; IN: Property list to copy object + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Neil Fortner + * October 27, 2011 + *------------------------------------------------------------------------- + */ +herr_t +H5Pfree_merge_committed_dtype_paths(hid_t plist_id) +{ + H5P_genplist_t *plist; /* Property list pointer */ + H5O_copy_dtype_merge_list_t *dt_list; /* Merge committed dtype list currently present */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + + /* Get the plist structure */ + if(NULL == (plist = H5P_object_verify(plist_id, H5P_OBJECT_COPY))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + + /* Get dtype list */ + if(H5P_get(plist, H5O_CPY_MERGE_COMM_DT_LIST_NAME, &dt_list) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get merge committed dtype list") + + /* Free dtype list */ + dt_list = H5P_free_merge_comm_dtype_list(dt_list); + + /* Update the list stored in the property list (to NULL) */ + if(H5P_set(plist, H5O_CPY_MERGE_COMM_DT_LIST_NAME, &dt_list) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set merge committed dtype list") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Pfree_merge_committed_dtype_paths() */ + + +/*------------------------------------------------------------------------- + * Function: H5Pset_mcdt_search_cb + * + * Purpose: Set the callback function when a matching committed datatype is not found + * from the list of paths stored in the object copy property list. + * H5Ocopy will invoke this callback before searching all committed datatypes + * at destination. + * + * Usage: H5Pset_mcdt_search_cb(plist_id, H5O_mcdt_search_cb_t func, void *op_data) + * hid_t plist_id; IN: Property list to copy object + * H5O_mcdt_search_cb_t func; IN: The callback function + * void *op_data; IN: The user data + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Vailin Choi; November 28, 2011 + *------------------------------------------------------------------------- + */ +herr_t +H5Pset_mcdt_search_cb(hid_t plist_id, H5O_mcdt_search_cb_t func, void *op_data) +{ + H5P_genplist_t *plist; /* Property list pointer */ + H5O_mcdt_cb_info_t cb_info; /* Callback info struct */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + + /* Check if the callback function is NULL and the user data is non-NULL. + * This is almost certainly an error as the user data will not be used. */ + if(!func && op_data) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "callback is NULL while user data is not") + + /* Get the plist structure */ + if(NULL == (plist = H5P_object_verify(plist_id, H5P_OBJECT_COPY))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + + /* Populate the callback info struct */ + cb_info.func = func; + cb_info.user_data = op_data; + + /* Set callback info */ + if(H5P_set(plist, H5O_CPY_MCDT_SEARCH_CB_NAME, &cb_info) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set callback info") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Pset_mcdt_search_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5Pget_mcdt_search_cb + * + * Purpose: Retrieves the callback function and user data from the specified + * object copy property list. + * + * Usage: H5Pget_mcdt_search_cb(plist_id, H5O_mcdt_search_cb_t *func, void **op_data) + * hid_t plist_id; IN: Property list to copy object + * H5O_mcdt_search_cb_t *func; OUT: The callback function + * void **op_data; OUT: The user data + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Vailin Choi; November 29, 2011 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Pget_mcdt_search_cb(hid_t plist_id, H5O_mcdt_search_cb_t *func, void **op_data) +{ + H5P_genplist_t *plist; /* Property list pointer */ + H5O_mcdt_cb_info_t cb_info; /* Callback info struct */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + + /* Get the plist structure */ + if(NULL == (plist = H5P_object_verify(plist_id, H5P_OBJECT_COPY))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + + /* Get callback info */ + if(H5P_get(plist, H5O_CPY_MCDT_SEARCH_CB_NAME, &cb_info) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get callback info") + + if(func) + *func = cb_info.func; + + if(op_data) + *op_data = cb_info.user_data; + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Pget_mcdt_search_cb() */ + |