From 4b5ae88422348a6c99750dd2a8d0178f78743b25 Mon Sep 17 00:00:00 2001 From: Raymond Lu Date: Mon, 4 Oct 2010 13:46:37 -0500 Subject: [svn-r19507] Fix for bug 1707 - I changed the design from the previous fix as Quincey suggested. I added a flag IS_DEDAULT in the H5E_auto_t structure. Both H5Eprint1/2 are the default now. If the user sets his/her own printing function. Then a call to H5Eget_auto1/2 will have to match H5Eset_auto1/2. Tested on jam, heiwa, and amani. --- src/H5E.c | 27 +++- src/H5Edeprec.c | 21 ++- src/H5Epkg.h | 7 +- test/err_compat.c | 340 +++++++++++++++++++++++++++++--------------- test/testfiles/err_compat_1 | 32 ++++- 5 files changed, 297 insertions(+), 130 deletions(-) diff --git a/src/H5E.c b/src/H5E.c index 704253f..4b581f6 100644 --- a/src/H5E.c +++ b/src/H5E.c @@ -178,10 +178,10 @@ H5E_set_default_auto(H5E_t *stk) #ifdef H5_NO_DEPRECATED_SYMBOLS stk->auto_op.vers = 2; #else - stk->auto_op.func1 = (H5E_auto1_t)H5Eprint1; + stk->auto_op.func1 = stk->auto_op.func1_default = (H5E_auto1_t)H5Eprint1; #endif - stk->auto_op.func2 = (H5E_auto2_t)H5Eprint2; - stk->auto_op.user_set = FALSE; + stk->auto_op.func2 = stk->auto_op.func2_default = (H5E_auto2_t)H5Eprint2; + stk->auto_op.is_default = TRUE; stk->auto_data = NULL; FUNC_LEAVE_NOAPI(SUCCEED) @@ -1560,6 +1560,11 @@ done: * Programmer: Robb Matzke * Saturday, February 28, 1998 * + * Modification:Raymond Lu + * 4 October 2010 + * If the printing function isn't the default H5Eprint1 or 2, + * and H5Eset_auto1 has been called to set the old style + * printing function, a call to H5Eget_auto2 should fail. *------------------------------------------------------------------------- */ herr_t @@ -1584,7 +1589,8 @@ H5Eget_auto2(hid_t estack_id, H5E_auto2_t *func, void **client_data) if(H5E_get_auto(estack, &op, client_data) < 0) HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get automatic error info") - if(op.user_set && op.vers == 1) + /* Fail if the printing function isn't the default(user-set) and set through H5Eset_auto1 */ + if(!op.is_default && op.vers == 1) HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "wrong API function, H5Eset_auto1 has been called") if(func) @@ -1615,6 +1621,9 @@ done: * Programmer: Robb Matzke * Friday, February 27, 1998 * + * Modification:Raymond Lu + * 4 October 2010 + * If the FUNC is H5Eprint2, put the IS_DEFAULT flag on. *------------------------------------------------------------------------- */ herr_t @@ -1636,10 +1645,18 @@ H5Eset_auto2(hid_t estack_id, H5E_auto2_t func, void *client_data) if(NULL == (estack = (H5E_t *)H5I_object_verify(estack_id, H5I_ERROR_STACK))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error stack ID") + /* Get the automatic error reporting information */ + if(H5E_get_auto(estack, &op, NULL) < 0) + HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get automatic error info") + /* Set the automatic error reporting information */ op.vers = 2; - op.user_set = TRUE; + if(func != op.func2_default) + op.is_default = FALSE; + else + op.is_default = TRUE; op.func2 = func; + if(H5E_set_auto(estack, &op, client_data) < 0) HGOTO_ERROR(H5E_ERROR, H5E_CANTSET, FAIL, "can't set automatic error info") diff --git a/src/H5Edeprec.c b/src/H5Edeprec.c index 9f6d869..0a028d9 100644 --- a/src/H5Edeprec.c +++ b/src/H5Edeprec.c @@ -370,6 +370,11 @@ done: * Programmer: Raymond Lu * Sep 16, 2003 * + * Modification:Raymond Lu + * 4 October 2010 + * If the printing function isn't the default H5Eprint1 or 2, + * and H5Eset_auto2 has been called to set the new style + * printing function, a call to H5Eget_auto1 should fail. *------------------------------------------------------------------------- */ herr_t @@ -390,7 +395,8 @@ H5Eget_auto1(H5E_auto1_t *func, void **client_data) if(H5E_get_auto(estack, &auto_op, client_data) < 0) HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get automatic error info") - if(auto_op.user_set && auto_op.vers == 2) + /* Fail if the printing function isn't the default(user-set) and set through H5Eset_auto2 */ + if(!auto_op.is_default && auto_op.vers == 2) HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "wrong API function, H5Eset_auto2 has been called") if(func) @@ -422,6 +428,9 @@ done: * Programmer: Raymond Lu * Sep 16, 2003 * + * Modification:Raymond Lu + * 4 October 2010 + * If the FUNC is H5Eprint2, put the IS_DEFAULT flag on. *------------------------------------------------------------------------- */ herr_t @@ -438,10 +447,18 @@ H5Eset_auto1(H5E_auto1_t func, void *client_data) if(NULL == (estack = H5E_get_my_stack())) /*lint !e506 !e774 Make lint 'constant value Boolean' in non-threaded case */ HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get current error stack") + /* Get the automatic error reporting information */ + if(H5E_get_auto(estack, &auto_op, NULL) < 0) + HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get automatic error info") + /* Set the automatic error reporting information */ auto_op.vers = 1; - auto_op.user_set = TRUE; + if(func != auto_op.func1_default) + auto_op.is_default = FALSE; + else + auto_op.is_default = TRUE; auto_op.func1 = func; + if(H5E_set_auto(estack, &auto_op, client_data) < 0) HGOTO_ERROR(H5E_ERROR, H5E_CANTSET, FAIL, "can't set automatic error info") diff --git a/src/H5Epkg.h b/src/H5Epkg.h index b9688d2..93e0d82 100644 --- a/src/H5Epkg.h +++ b/src/H5Epkg.h @@ -71,15 +71,18 @@ #ifndef H5_NO_DEPRECATED_SYMBOLS typedef struct { unsigned vers; /* Which version callback to use */ - hbool_t user_set; /* If the printing function has been set. */ + hbool_t is_default; /* If the printing function is the library's own. */ H5E_auto1_t func1; /* Old-style callback, NO error stack param. */ H5E_auto2_t func2; /* New-style callback, with error stack param. */ + H5E_auto1_t func1_default; /* The saved library's default function - old style. */ + H5E_auto2_t func2_default; /* The saved library's default function - new style. */ } H5E_auto_op_t; #else typedef struct { unsigned vers; /* Which version callback to use */ - hbool_t user_set; /* If the printing function has been set. */ + hbool_t is_default; /* If the printing function is the library's own. */ H5E_auto_t func2; /* Only the new style callback function is available. */ + H5E_auto2_t func2_default; /* The saved library's default function - new style. */ } H5E_auto_op_t; #endif diff --git a/test/err_compat.c b/test/err_compat.c index 4c0df06..50a48fe 100644 --- a/test/err_compat.c +++ b/test/err_compat.c @@ -42,79 +42,178 @@ int ipoints2[DIM0][DIM1], icheck2[DIM0][DIM1]; #define DSET_NAME "a_dataset" #define FAKE_ID -1 -herr_t custom_print_cb(int n, H5E_error1_t *err_desc, void* client_data); +herr_t custom_print_cb1(int n, H5E_error1_t *err_desc, void* client_data); +herr_t custom_print_cb2(int n, H5E_error2_t *err_desc, void* client_data); -#ifdef H5_USE_16_API_DEFAULT /*------------------------------------------------------------------------- - * Function: test_error1 + * Function: user_print1 * - * Purpose: Test the backward compatibility of H5Eset/get_auto. + * Purpose: This function is a user-defined old-style printing function. + * This is just a convenience function for H5Ewalk1() with a + * function that prints error messages. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Raymond Lu + * 4 October 2010 + * + *------------------------------------------------------------------------- + */ +static herr_t +user_print1(FILE *stream) +{ + /* Customized way to print errors */ + fprintf(stderr, "\n********* Print error stack in customized way *********\n"); + if(H5Ewalk1(H5E_WALK_UPWARD, (H5E_walk1_t)custom_print_cb1, stream) < 0) + TEST_ERROR; + + return 0; + + error: + return -1; + +} + + +/*------------------------------------------------------------------------- + * Function: user_print2 + * + * Purpose: This function is a user-defined new-style printing function. + * This is just a convenience function for H5Ewalk2() with a + * function that prints error messages. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Raymond Lu + * 4 October 2010 + * + *------------------------------------------------------------------------- + */ +static herr_t +user_print2(hid_t err_stack, FILE *stream) +{ + /* Customized way to print errors */ + fprintf(stderr, "\n********* Print error stack in customized way *********\n"); + if(H5Ewalk2(err_stack, H5E_WALK_UPWARD, (H5E_walk2_t)custom_print_cb2, stream) < 0) + TEST_ERROR; + + return 0; + + error: + return -1; + +} + + +/*------------------------------------------------------------------------- + * Function: custom_print_cb1 + * + * Purpose: Callback function to print error stack in customized way + * for H5Ewalk1. * * Return: Success: 0 * * Failure: -1 * * Programmer: Raymond Lu - * 17 September 2010 - * + * 4 October 2010 * * Modifications: * *------------------------------------------------------------------------- */ -static herr_t -test_error1(void) +herr_t +custom_print_cb1(int n, H5E_error1_t *err_desc, void* client_data) { - hid_t dataset, space; - hsize_t dims[2]; - H5E_auto1_t old_func1; - H5E_auto2_t old_func2; - void *old_data; - herr_t ret; + FILE *stream = (FILE *)client_data; + char *maj = NULL; + char *min = NULL; + const int indent = 4; - TESTING("error API H5Eset/get_auto"); - fprintf(stderr, "\n"); + if(NULL == (min = H5Eget_minor(err_desc->min_num))) + TEST_ERROR; - /* Create the data space */ - dims[0] = DIM0; - dims[1] = DIM1; - if ((space = H5Screate_simple(2, dims, NULL))<0) TEST_ERROR; + if(NULL == (maj = H5Eget_major(err_desc->maj_num))) + TEST_ERROR; - /* Test whether the printing function is mismatched. The library should indicate - * H5Eprint1 as the default. */ - if (H5Eget_auto2(H5E_DEFAULT, &old_func2, &old_data)<0) - TEST_ERROR; - if (old_data != NULL) - TEST_ERROR; - if (!old_func2) - TEST_ERROR; + fprintf(stream, "%*serror #%03d: %s in %s(): line %u\n", + indent, "", n, err_desc->file_name, + err_desc->func_name, err_desc->line); + + fprintf(stream, "%*smajor: %s\n", indent * 2, "", maj); + fprintf(stream, "%*sminor: %s\n", indent * 2, "", min); - /* This function changes the default printing function to be H5Eprint2. */ - if(H5Eset_auto2(H5E_DEFAULT, old_func2, old_data)<0) - TEST_ERROR; + HDfree(maj); + HDfree(min); - /* Dataset creation should fail because the file doesn't exist. */ - dataset = H5Dcreate2(FAKE_ID, DSET_NAME, H5T_STD_I32BE, space, H5P_DEFAULT, - H5P_DEFAULT, H5P_DEFAULT); - if(dataset >= 0) + return 0; + +error: + if(maj) + HDfree(maj); + if(min) + HDfree(min); + + return -1; +} + + +/*------------------------------------------------------------------------- + * Function: custom_print_cb2 + * + * Purpose: Callback function to print error stack in customized way + * for H5Ewalk1. + * + * Return: Success: 0 + * + * Failure: -1 + * + * Programmer: Raymond Lu + * 4 October 2010 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +custom_print_cb2(int n, H5E_error2_t *err_desc, void* client_data) +{ + FILE *stream = (FILE *)client_data; + char *maj = NULL; + char *min = NULL; + const int indent = 4; + + if(NULL == (min = H5Eget_minor(err_desc->min_num))) TEST_ERROR; - /* This call should fail because the test mixes H5Eget_auto1 with H5Eset_auto2. - * Once the H5Eset_auto2 is called, a call to H5Eget_auto1 will fail. */ - if((ret = H5Eget_auto1(&old_func1, &old_data)) >= 0) + if(NULL == (maj = H5Eget_major(err_desc->maj_num))) TEST_ERROR; + fprintf(stream, "%*serror #%03d: %s in %s(): line %u\n", + indent, "", n, err_desc->file_name, + err_desc->func_name, err_desc->line); + + fprintf(stream, "%*smajor: %s\n", indent * 2, "", maj); + fprintf(stream, "%*sminor: %s\n", indent * 2, "", min); + + HDfree(maj); + HDfree(min); + return 0; - error: +error: + if(maj) + HDfree(maj); + if(min) + HDfree(min); + return -1; } -#else /*H5_USE_16_API_DEFAULT*/ /*------------------------------------------------------------------------- - * Function: test_error2 + * Function: test_error1 * * Purpose: Test the backward compatibility of H5Eset/get_auto. * @@ -131,7 +230,7 @@ test_error1(void) *------------------------------------------------------------------------- */ static herr_t -test_error2(void) +test_error1(void) { hid_t dataset, space; hsize_t dims[2]; @@ -148,28 +247,94 @@ test_error2(void) dims[1] = DIM1; if ((space = H5Screate_simple(2, dims, NULL))<0) TEST_ERROR; - /* Test whether the printing function is mismatched. The library should indicate - * H5Eprint2 as the default. */ - if (H5Eget_auto1(&old_func1, &old_data)<0) + /* Use H5Eget_auto2 to query the default printing function. The library + *should indicate H5Eprint2 as the default. */ + if (H5Eget_auto2(H5E_DEFAULT, &old_func2, &old_data)<0) TEST_ERROR; if (old_data != NULL) TEST_ERROR; - if (!old_func1) + if (!old_func2 || (H5E_auto2_t)H5Eprint2 != old_func2) TEST_ERROR; - /* This function changes the default printing function to be H5Eprint1. */ - if(H5Eset_auto1(old_func1, old_data)<0) + /* This function sets the default printing function to be H5Eprint2. */ + if(H5Eset_auto2(H5E_DEFAULT, old_func2, old_data)<0) TEST_ERROR; - /* Dataset creation should fail because the file doesn't exist. */ + /* Try the printing function. Dataset creation should fail because the file + * doesn't exist. */ dataset = H5Dcreate2(FAKE_ID, DSET_NAME, H5T_STD_I32BE, space, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); if(dataset >= 0) TEST_ERROR; - /* This call should fail because it mixed H5Eget_auto2 with H5Eset_auto1. - * Once the H5Eset_auto1 is called, a call to H5Eget_auto2 will fail. */ - if((ret = H5Eget_auto2(H5E_DEFAULT, &old_func2, &old_data)) >= 0) + /* This call should work. It simply returns H5Eprint1. */ + if((ret = H5Eget_auto1(&old_func1, &old_data))<0) + TEST_ERROR; + if (old_data != NULL) + TEST_ERROR; + if (!old_func1 || (H5E_auto1_t)H5Eprint1 != old_func1) + TEST_ERROR; + + /* This function changes the old-style printing function to be user_print1. */ + if(H5Eset_auto1((H5E_auto1_t)user_print1, stderr)<0) + TEST_ERROR; + + /* Try the printing function. Dataset creation should fail because the file + * doesn't exist. */ + dataset = H5Dcreate2(FAKE_ID, DSET_NAME, H5T_STD_I32BE, space, H5P_DEFAULT, + H5P_DEFAULT, H5P_DEFAULT); + if(dataset >= 0) + TEST_ERROR; + + /* This call should fail because the test mixes H5Eget_auto2 with H5Eset_auto1. + * Once the H5Eset_auto1 is called with a user-defined printing function, + * a call to H5Eget_auto2 will fail. But keep in mind the printing function is + * user_print1. */ + if((ret = H5Eget_auto2(H5E_DEFAULT, &old_func2, &old_data))>=0) + TEST_ERROR; + + /* This function changes the new-style printing function to be user_print2. */ + if(H5Eset_auto2(H5E_DEFAULT, (H5E_auto2_t)user_print2, stderr)<0) + TEST_ERROR; + + /* Try the printing function. Dataset creation should fail because the file + * doesn't exist. */ + dataset = H5Dcreate2(FAKE_ID, DSET_NAME, H5T_STD_I32BE, space, H5P_DEFAULT, + H5P_DEFAULT, H5P_DEFAULT); + if(dataset >= 0) + TEST_ERROR; + + /* This function changes the new-style printing function back to the default H5Eprint2. */ + if(H5Eset_auto2(H5E_DEFAULT, (H5E_auto2_t)H5Eprint2, NULL)<0) + TEST_ERROR; + + /* This call should work because the H5Eset_auto2 above restored the default printing + * function H5Eprint2. It simply returns user_print1. */ + if((ret = H5Eget_auto1(&old_func1, &old_data))<0) + TEST_ERROR; + if (old_data != NULL) + TEST_ERROR; + if (!old_func1 || (H5E_auto1_t)user_print1 != old_func1) + TEST_ERROR; + + /* This function changes the new-style printing function back to the default H5Eprint1. */ + if(H5Eset_auto1((H5E_auto1_t)H5Eprint1, NULL)<0) + TEST_ERROR; + + /* This call should work because the H5Eset_auto1 above restored the default printing + * function H5Eprint1. It simply returns H5Eprint2. */ + if((ret = H5Eget_auto2(H5E_DEFAULT, &old_func2, &old_data))<0) + TEST_ERROR; + if (old_data != NULL) + TEST_ERROR; + if (!old_func2 || (H5E_auto2_t)H5Eprint2 != old_func2) + TEST_ERROR; + + /* Try the printing function. Dataset creation should fail because the file + * doesn't exist. */ + dataset = H5Dcreate2(FAKE_ID, DSET_NAME, H5T_STD_I32BE, space, H5P_DEFAULT, + H5P_DEFAULT, H5P_DEFAULT); + if(dataset >= 0) TEST_ERROR; return 0; @@ -177,13 +342,12 @@ test_error2(void) error: return -1; } -#endif /*H5_USE_16_API_DEFAULT*/ /*------------------------------------------------------------------------- - * Function: test_error3 + * Function: test_error2 * - * Purpose: Test error API functions + * Purpose: Test error API functions, mainly on H5Epush1. * * Return: Success: 0 * @@ -198,13 +362,11 @@ test_error2(void) *------------------------------------------------------------------------- */ static herr_t -test_error3(hid_t file) +test_error2(hid_t file) { hid_t dataset, space; hsize_t dims[2]; - const char *FUNC_test_error="test_error"; - H5E_auto1_t old_func; - void *old_data; + const char *FUNC_test_error="test_error2"; TESTING("error API based on data I/O"); fprintf(stderr, "\n"); @@ -278,7 +440,7 @@ dump_error(void) /* Customized way to print errors */ fprintf(stderr, "\n********* Print error stack in customized way *********\n"); - if(H5Ewalk1(H5E_WALK_UPWARD, custom_print_cb, stderr) < 0) + if(H5Ewalk1(H5E_WALK_UPWARD, custom_print_cb1, stderr) < 0) TEST_ERROR; return 0; @@ -287,57 +449,6 @@ dump_error(void) return -1; } -/*------------------------------------------------------------------------- - * Function: custom_print_cb - * - * Purpose: Callback function to print error stack in customized way. - * - * Return: Success: 0 - * - * Failure: -1 - * - * Programmer: Raymond Lu - * July 17, 2003 - * - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -herr_t -custom_print_cb(int n, H5E_error1_t *err_desc, void* client_data) -{ - FILE *stream = (FILE *)client_data; - char *maj = NULL; - char *min = NULL; - const int indent = 4; - - if(NULL == (min = H5Eget_minor(err_desc->min_num))) - TEST_ERROR; - - if(NULL == (maj = H5Eget_major(err_desc->maj_num))) - TEST_ERROR; - - fprintf(stream, "%*serror #%03d: %s in %s(): line %u\n", - indent, "", n, err_desc->file_name, - err_desc->func_name, err_desc->line); - - fprintf(stream, "%*smajor: %s\n", indent * 2, "", maj); - fprintf(stream, "%*sminor: %s\n", indent * 2, "", min); - - HDfree(maj); - HDfree(min); - - return 0; - -error: - if(maj) - HDfree(maj); - if(min) - HDfree(min); - - return -1; -} /*------------------------------------------------------------------------- @@ -379,13 +490,9 @@ main(void) H5Eclear1(); /* Test error API */ -#ifdef H5_USE_16_API_DEFAULT if(test_error1() < 0) TEST_ERROR ; -#else /*H5_USE_16_API_DEFAULT*/ - if(test_error2() < 0) TEST_ERROR ; -#endif /*H5_USE_16_API_DEFAULT*/ - if(test_error3(file) < 0) { + if(test_error2(file) < 0) { H5Epush1(__FILE__, FUNC_main, __LINE__, H5E_ERROR, H5E_BADMESG, "Error test failed"); H5Eprint1(stderr); @@ -402,4 +509,3 @@ main(void) return 1; } #endif /* H5_NO_DEPRECATED_SYMBOLS */ - diff --git a/test/testfiles/err_compat_1 b/test/testfiles/err_compat_1 index f3d11a3..e2b37ab 100644 --- a/test/testfiles/err_compat_1 +++ b/test/testfiles/err_compat_1 @@ -21,16 +21,40 @@ HDF5-DIAG: Error detected in HDF5 (version (number)) thread (IDs): #001: (file name) line (number) in H5G_loc(): invalid object ID major: Invalid arguments to routine minor: Bad value + +********* Print error stack in customized way ********* + error #000: (file name) in H5G_loc(): line (number) + major: Invalid arguments to routine + minor: Bad value + error #001: (file name) in H5Dcreate2(): line (number) + major: Invalid arguments to routine + minor: Inappropriate type + +********* Print error stack in customized way ********* + error #000: (file name) in H5Eget_auto(1 or 2)(): line (number) + major: Error API + minor: Can't get value + +********* Print error stack in customized way ********* + error #000: (file name) in H5G_loc(): line (number) + major: Invalid arguments to routine + minor: Bad value + error #001: (file name) in H5Dcreate2(): line (number) + major: Invalid arguments to routine + minor: Inappropriate type HDF5-DIAG: Error detected in HDF5 (version (number)) thread (IDs): - #000: (file name) line (number) in H5Eget_auto(1 or 2)(): wrong API function, H5Eset_auto(1 or 2) has been called - major: Error API - minor: Can't get value + #000: (file name) line (number) in H5Dcreate2(): not a location ID + major: Invalid arguments to routine + minor: Inappropriate type + #001: (file name) line (number) in H5G_loc(): invalid object ID + major: Invalid arguments to routine + minor: Bad value HDF5-DIAG: Error detected in HDF5 (version (number)) thread (IDs): #000: (file name) line (number) in main(): Error test failed major: Error API minor: Unrecognized message - #001: (file name) line (number) in test_error(): H5Dwrite shouldn't succeed + #001: (file name) line (number) in test_error2(): H5Dwrite shouldn't succeed major: Error API minor: Write failed #002: (file name) line (number) in H5Dwrite(): not a dataset -- cgit v0.12