From 7f1379704fd291c2f1a16c0087690f0b2ce90e4c Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Tue, 6 Oct 2009 22:05:53 -0500 Subject: [svn-r17604] Description: Correctly invoke generic property list class callbacks all the way to the root of the class hierarchy. Tested on: FreeBSD/32 6.3 (duty) in debug mode FreeBSD/64 6.3 (liberty) w/C++ & FORTRAN, in debug mode Linux/32 2.6 (jam) w/PGI compilers, w/default API=1.8.x, w/C++ & FORTRAN, w/threadsafe, in debug mode Linux/64-amd64 2.6 (smirom) w/Intel compilers, w/default API=1.6.x, w/C++ & FORTRAN, in production mode Solaris/32 2.10 (linew) w/deprecated symbols disabled, w/C++ & FORTRAN, w/szip filter, in production mode Linux/64-ia64 2.6 (cobalt) w/Intel compilers, w/C++ & FORTRAN, in production mode Linux/64-ia64 2.4 (tg-login3) w/parallel, w/FORTRAN, in debug mode Linux/64-amd64 2.6 (abe) w/parallel, w/FORTRAN, in production mode Mac OS X/32 10.6.1 (amazon) in debug mode Mac OS X/32 10.6.1 (amazon) w/C++ & FORTRAN, w/threadsafe, in production mode --- src/H5Pdcpl.c | 10 ++-- src/H5Pint.c | 67 ++++++++++++++++++-------- test/tgenprop.c | 143 ++++++++++++++++++++++++++++++++++++++++++++++++++------ 3 files changed, 180 insertions(+), 40 deletions(-) diff --git a/src/H5Pdcpl.c b/src/H5Pdcpl.c index 9f8650c..2f7e280 100644 --- a/src/H5Pdcpl.c +++ b/src/H5Pdcpl.c @@ -1723,7 +1723,7 @@ H5P_get_filter_by_id(H5P_genplist_t *plist, H5Z_filter_t id, unsigned int *flags /* Get filter information */ if(H5P_get_filter(filter, flags, cd_nelmts, cd_values, namelen, name, filter_config) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, H5Z_FILTER_ERROR, "can't get filter info") + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get filter info") done: FUNC_LEAVE_NOAPI(ret_value) @@ -1791,7 +1791,7 @@ H5Pget_filter_by_id2(hid_t plist_id, H5Z_filter_t id, unsigned int *flags/*out*/ /* Get filter info */ if(H5P_get_filter_by_id(plist, id, flags, cd_nelmts, cd_values, namelen, name, filter_config) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, H5Z_FILTER_ERROR, "can't get filter info") + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get filter info") done: FUNC_LEAVE_API(ret_value) @@ -1873,13 +1873,13 @@ H5Premove_filter(hid_t plist_id, H5Z_filter_t filter) /* Get pipeline info */ if(H5P_get(plist, H5D_CRT_DATA_PIPELINE_NAME, &pline) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, H5Z_FILTER_ERROR, "can't get pipeline") + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get pipeline") /* Check if there are any filters */ if (pline.filter) { /* Delete filter */ if(H5Z_delete(&pline, filter) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, H5Z_FILTER_ERROR, "can't delete filter") + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't delete filter") /* Put the I/O pipeline information back into the property list */ if(H5P_set(plist, H5D_CRT_DATA_PIPELINE_NAME, &pline) < 0) @@ -2959,7 +2959,7 @@ H5Pget_filter_by_id1(hid_t plist_id, H5Z_filter_t id, unsigned int *flags/*out*/ /* Get filter info */ if(H5P_get_filter_by_id(plist, id, flags, cd_nelmts, cd_values, namelen, name, NULL) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, H5Z_FILTER_ERROR, "can't get filter info") + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get filter info") done: FUNC_LEAVE_API(ret_value) diff --git a/src/H5Pint.c b/src/H5Pint.c index 364cab2..4da7f09 100644 --- a/src/H5Pint.c +++ b/src/H5Pint.c @@ -782,14 +782,22 @@ H5P_copy_plist(H5P_genplist_t *old_plist, hbool_t app_ref) /* Save the property list ID in the property list struct, for use in the property class's 'close' callback */ new_plist->plist_id=new_plist_id; - /* Call the class callback (if it exists) now that we have the property list ID */ - if(new_plist->pclass->copy_func!=NULL) { - if((new_plist->pclass->copy_func)(new_plist_id,old_plist->plist_id,old_plist->pclass->copy_data) < 0) { - /* Delete ID, ignore return value */ - H5I_remove(new_plist_id); - HGOTO_ERROR (H5E_PLIST, H5E_CANTINIT, FAIL,"Can't initialize property"); + /* Call the class callback (if it exists) now that we have the property list ID + * (up through chain of parent classes also) + */ + tclass = new_plist->pclass; + while(NULL != tclass) { + if(NULL != tclass->copy_func) { + if((tclass->copy_func)(new_plist_id, old_plist->plist_id, old_plist->pclass->copy_data) < 0) { + /* Delete ID, ignore return value */ + H5I_remove(new_plist_id); + HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL,"Can't initialize property") + } /* end if */ } /* end if */ - } /* end if */ + + /* Go up to parent class */ + tclass = tclass->parent; + } /* end while */ /* Set the class initialization flag */ new_plist->class_init=1; @@ -1658,8 +1666,9 @@ done: hid_t H5P_create_id(H5P_genclass_t *pclass, hbool_t app_ref) { - H5P_genplist_t *plist=NULL; /* Property list created */ - hid_t plist_id=FAIL; /* Property list ID */ + H5P_genclass_t *tclass; /* Temporary class pointer */ + H5P_genplist_t *plist = NULL; /* Property list created */ + hid_t plist_id = FAIL; /* Property list ID */ hid_t ret_value; /* return value */ FUNC_ENTER_NOAPI(H5P_create_id, FAIL); @@ -1677,14 +1686,22 @@ H5P_create_id(H5P_genclass_t *pclass, hbool_t app_ref) /* Save the property list ID in the property list struct, for use in the property class's 'close' callback */ plist->plist_id=plist_id; - /* Call the class callback (if it exists) now that we have the property list ID */ - if(plist->pclass->create_func!=NULL) { - if((plist->pclass->create_func)(plist_id,plist->pclass->create_data) < 0) { - /* Delete ID, ignore return value */ - H5I_remove(plist_id); - HGOTO_ERROR (H5E_PLIST, H5E_CANTINIT, FAIL,"Can't initialize property"); + /* Call the class callback (if it exists) now that we have the property list ID + * (up through chain of parent classes also) + */ + tclass = plist->pclass; + while(NULL != tclass) { + if(NULL != tclass->create_func) { + if((tclass->create_func)(plist_id, tclass->create_data) < 0) { + /* Delete ID, ignore return value */ + H5I_remove(plist_id); + HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL,"Can't initialize property") + } /* end if */ } /* end if */ - } /* end if */ + + /* Go up to parent class */ + tclass = tclass->parent; + } /* end while */ /* Set the class initialization flag */ plist->class_init=1; @@ -4058,10 +4075,20 @@ H5P_close(void *_plist) assert(plist); - /* Make call to property list class close callback, if needed */ - if(plist->class_init!=0 && plist->pclass->close_func!=NULL) { - /* Call user's "close" callback function, ignoring return value */ - (plist->pclass->close_func)(plist->plist_id,plist->pclass->close_data); + /* Make call to property list class close callback, if needed + * (up through chain of parent classes also) + */ + if(plist->class_init !=0) { + tclass = plist->pclass; + while(NULL != tclass) { + if(NULL != tclass->close_func) { + /* Call user's "close" callback function, ignoring return value */ + (tclass->close_func)(plist->plist_id, tclass->close_data); + } /* end if */ + + /* Go up to parent class */ + tclass = tclass->parent; + } /* end while */ } /* end if */ /* Create the skip list to hold names of properties already seen diff --git a/test/tgenprop.c b/test/tgenprop.c index f87d4ec..1d3d766 100644 --- a/test/tgenprop.c +++ b/test/tgenprop.c @@ -367,11 +367,11 @@ test_genprop_class_iter(void) /**************************************************************** ** -** test_genprop_cls_cb1(): Property List callback for test_genprop_class_callback +** test_genprop_cls_*_cb1(): Property List callbacks for test_genprop_class_callback ** ****************************************************************/ static herr_t -test_genprop_cls_cb1(hid_t list_id, void *create_data) +test_genprop_cls_crt_cb1(hid_t list_id, void *create_data) { struct { /* Struct for iterations */ int count; @@ -385,18 +385,33 @@ test_genprop_cls_cb1(hid_t list_id, void *create_data) } static herr_t -test_genprop_cls_cb2(hid_t new_list_id, hid_t UNUSED old_list_id, void *create_data) +test_genprop_cls_cpy_cb1(hid_t new_list_id, hid_t UNUSED old_list_id, void *copy_data) { struct { /* Struct for iterations */ int count; hid_t id; - } *count_struct=create_data; + } *count_struct=copy_data; count_struct->count++; count_struct->id=new_list_id; return(SUCCEED); } + +static herr_t +test_genprop_cls_cls_cb1(hid_t list_id, void *create_data) +{ + struct { /* Struct for iterations */ + int count; + hid_t id; + } *count_struct=create_data; + + count_struct->count++; + count_struct->id=list_id; + + return(SUCCEED); +} + /**************************************************************** ** ** test_genprop_class_callback(): Test basic generic property list code. @@ -407,20 +422,22 @@ static void test_genprop_class_callback(void) { hid_t cid1; /* Generic Property class ID */ + hid_t cid2; /* Generic Property class ID */ hid_t lid1; /* Generic Property list ID */ hid_t lid2; /* Generic Property list ID */ + hid_t lid3; /* Generic Property list ID */ size_t nprops; /* Number of properties in class */ struct { /* Struct for callbacks */ int count; hid_t id; - } crt_cb_struct, cls_cb_struct; + } crt_cb_struct, cpy_cb_struct, cls_cb_struct; herr_t ret; /* Generic return value */ /* Output message about test being performed */ MESSAGE(5, ("Testing Basic Generic Property List Class Callback Functionality\n")); /* Create a new generic class, derived from the root of the class hierarchy */ - cid1 = H5Pcreate_class(H5P_ROOT,CLASS1_NAME,test_genprop_cls_cb1,&crt_cb_struct,NULL, NULL,test_genprop_cls_cb1,&cls_cb_struct); + cid1 = H5Pcreate_class(H5P_ROOT, CLASS1_NAME, test_genprop_cls_crt_cb1, &crt_cb_struct, test_genprop_cls_cpy_cb1, &cpy_cb_struct, test_genprop_cls_cls_cb1, &cls_cb_struct); CHECK_I(cid1, "H5Pcreate_class"); /* Insert first property into class (with no callbacks) */ @@ -435,18 +452,16 @@ test_genprop_class_callback(void) ret = H5Pregister2(cid1, PROP3_NAME, PROP3_SIZE, PROP3_DEF_VALUE, NULL, NULL, NULL, NULL, NULL, NULL, NULL); CHECK_I(ret, "H5Pregister2"); - /* Insert fourth property into class (with no callbacks) */ - ret = H5Pregister2(cid1, PROP4_NAME, PROP4_SIZE, PROP4_DEF_VALUE, NULL, NULL, NULL, NULL, NULL, NULL, NULL); - CHECK_I(ret, "H5Pregister2"); - /* Check the number of properties in class */ ret = H5Pget_nprops(cid1,&nprops); CHECK_I(ret, "H5Pget_nprops"); - VERIFY(nprops, 4, "H5Pget_nprops"); + VERIFY(nprops, 3, "H5Pget_nprops"); /* Initialize class callback structs */ crt_cb_struct.count=0; crt_cb_struct.id=(-1); + cpy_cb_struct.count=0; + cpy_cb_struct.id=(-1); cls_cb_struct.count=0; cls_cb_struct.id=(-1); @@ -461,7 +476,7 @@ test_genprop_class_callback(void) /* Check the number of properties in list */ ret = H5Pget_nprops(lid1,&nprops); CHECK_I(ret, "H5Pget_nprops"); - VERIFY(nprops, 4, "H5Pget_nprops"); + VERIFY(nprops, 3, "H5Pget_nprops"); /* Create another property list from the class */ lid2 = H5Pcreate(cid1); @@ -474,7 +489,20 @@ test_genprop_class_callback(void) /* Check the number of properties in list */ ret = H5Pget_nprops(lid2,&nprops); CHECK_I(ret, "H5Pget_nprops"); - VERIFY(nprops, 4, "H5Pget_nprops"); + VERIFY(nprops, 3, "H5Pget_nprops"); + + /* Create another property list by copying an existing list */ + lid3 = H5Pcopy(lid1); + CHECK_I(lid3, "H5Pcopy"); + + /* Verify that the copy callback occurred */ + VERIFY(cpy_cb_struct.count, 1, "H5Pcopy"); + VERIFY(cpy_cb_struct.id, lid3, "H5Pcopy"); + + /* Check the number of properties in list */ + ret = H5Pget_nprops(lid3, &nprops); + CHECK_I(ret, "H5Pget_nprops"); + VERIFY(nprops, 3, "H5Pget_nprops"); /* Close first list */ ret = H5Pclose(lid1); @@ -492,9 +520,75 @@ test_genprop_class_callback(void) VERIFY(cls_cb_struct.count, 2, "H5Pclose"); VERIFY(cls_cb_struct.id, lid2, "H5Pclose"); - /* Close class */ + /* Close third list */ + ret = H5Pclose(lid3); + CHECK_I(ret, "H5Pclose"); + + /* Verify that the close callback occurred */ + VERIFY(cls_cb_struct.count, 3, "H5Pclose"); + VERIFY(cls_cb_struct.id, lid3, "H5Pclose"); + + /* Create another new generic class, derived from first class */ + cid2 = H5Pcreate_class(cid1, CLASS2_NAME, test_genprop_cls_crt_cb1, &crt_cb_struct, test_genprop_cls_cpy_cb1, &cpy_cb_struct, test_genprop_cls_cls_cb1, &cls_cb_struct); + CHECK_I(cid2, "H5Pcreate_class"); + + /* Insert fourth property into class (with no callbacks) */ + ret = H5Pregister2(cid2, PROP4_NAME, PROP4_SIZE, PROP4_DEF_VALUE, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + CHECK_I(ret, "H5Pregister2"); + + /* Check the number of properties in class */ + /* (only reports the number of properties in 2nd class) */ + ret = H5Pget_nprops(cid2, &nprops); + CHECK_I(ret, "H5Pget_nprops"); + VERIFY(nprops, 1, "H5Pget_nprops"); + + /* Create a property list from the 2nd class */ + lid1 = H5Pcreate(cid2); + CHECK_I(lid1, "H5Pcreate"); + + /* Verify that both of the creation callbacks occurred */ + VERIFY(crt_cb_struct.count, 4, "H5Pcreate"); + VERIFY(crt_cb_struct.id, lid1, "H5Pcreate"); + + /* Check the number of properties in list */ + ret = H5Pget_nprops(lid1, &nprops); + CHECK_I(ret, "H5Pget_nprops"); + VERIFY(nprops, 4, "H5Pget_nprops"); + + /* Create another property list by copying existing list */ + lid2 = H5Pcopy(lid1); + CHECK_I(lid2, "H5Pcopy"); + + /* Verify that both of the copy callbacks occurred */ + VERIFY(cpy_cb_struct.count, 3, "H5Pcopy"); + VERIFY(cpy_cb_struct.id, lid2, "H5Pcopy"); + + /* Check the number of properties in list */ + ret = H5Pget_nprops(lid2, &nprops); + CHECK_I(ret, "H5Pget_nprops"); + VERIFY(nprops, 4, "H5Pget_nprops"); + + /* Close first list */ + ret = H5Pclose(lid1); + CHECK_I(ret, "H5Pclose"); + + /* Verify that both of the close callbacks occurred */ + VERIFY(cls_cb_struct.count, 5, "H5Pclose"); + VERIFY(cls_cb_struct.id, lid1, "H5Pclose"); + + /* Close second list */ + ret = H5Pclose(lid2); + CHECK_I(ret, "H5Pclose"); + + /* Verify that both of the close callbacks occurred */ + VERIFY(cls_cb_struct.count, 7, "H5Pclose"); + VERIFY(cls_cb_struct.id, lid2, "H5Pclose"); + + /* Close classes */ ret = H5Pclose_class(cid1); CHECK_I(ret, "H5Pclose_class"); + ret = H5Pclose_class(cid2); + CHECK_I(ret, "H5Pclose_class"); } /* end test_genprop_class_callback() */ /**************************************************************** @@ -895,6 +989,25 @@ prop_cb_info prop3_cb_info; /* Callback statistics for property #3 */ /**************************************************************** ** +** test_genprop_cls_cpy_cb2(): Property Class callback for test_genprop_list_callback +** +****************************************************************/ +static herr_t +test_genprop_cls_cpy_cb2(hid_t new_list_id, hid_t UNUSED old_list_id, void *create_data) +{ + struct { /* Struct for iterations */ + int count; + hid_t id; + } *count_struct=create_data; + + count_struct->count++; + count_struct->id=new_list_id; + + return(SUCCEED); +} + +/**************************************************************** +** ** test_genprop_prop_crt_cb1(): Property creation callback for test_genprop_list_callback ** ****************************************************************/ @@ -1063,7 +1176,7 @@ test_genprop_list_callback(void) MESSAGE(5, ("Testing Basic Generic Property List Property Callback Functionality\n")); /* Create a new generic class, derived from the root of the class hierarchy */ - cid1 = H5Pcreate_class(H5P_ROOT,CLASS1_NAME, NULL, NULL,test_genprop_cls_cb2,&cop_cb_struct,NULL, NULL); + cid1 = H5Pcreate_class(H5P_ROOT,CLASS1_NAME, NULL, NULL,test_genprop_cls_cpy_cb2,&cop_cb_struct,NULL, NULL); CHECK_I(cid1, "H5Pcreate_class"); /* Insert first property into class (with callbacks) */ -- cgit v0.12