diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/ttsafe.c | 531 | ||||
-rw-r--r-- | test/ttsafe_acreate.c | 240 | ||||
-rw-r--r-- | test/ttsafe_cancel.c | 295 | ||||
-rw-r--r-- | test/ttsafe_dcreate.c | 292 | ||||
-rw-r--r-- | test/ttsafe_error.c | 260 |
5 files changed, 828 insertions, 790 deletions
diff --git a/test/ttsafe.c b/test/ttsafe.c index cf87752..a228076 100644 --- a/test/ttsafe.c +++ b/test/ttsafe.c @@ -17,26 +17,25 @@ static char RcsId[] = "@(#)$Revision$"; /* $Id$ */ /* - FILE - ttsafe.c - HDF5 threadsafe testing framework main file. - - REMARKS - General test wrapper for HDF5 library thread safety test programs - - DESIGN - Each test function should be implemented as function having no - parameters and returning void (i.e. no return value). They should be put - into the list of InitTest() calls in main() below. Functions which depend - on other functionality should be placed below the InitTest() call for the - base functionality testing. - Each test module should include ttsafe.h and define a unique set of - names for test files they create. - - BUGS/LIMITATIONS - - EXPORTED ROUTINES/VARIABLES: - Two variables are exported: num_errs, and Verbosity. - + * FILE + * ttsafe.c - HDF5 threadsafe testing framework main file. + * + * REMARKS + * General test wrapper for HDF5 library thread safety test programs + * + * DESIGN + * Each test function should be implemented as function having no + * parameters and returning void (i.e. no return value). They should be put + * into the list of InitTest() calls in main() below. Functions which depend + * on other functionality should be placed below the InitTest() call for the + * base functionality testing. + * Each test module should include ttsafe.h and define a unique set of + * names for test files they create. + * + * BUGS/LIMITATIONS + * + * EXPORTED ROUTINES/VARIABLES: + * Two variables are exported: num_errs, and Verbosity. */ #if defined __MWERKS__ @@ -45,6 +44,16 @@ static char RcsId[] = "@(#)$Revision$"; #include <stdarg.h> +#include <ttsafe.h> + +#ifndef H5_HAVE_THREADSAFE +int main(void) +{ + printf("Test skipped because THREADSAFE not enabled\n"); + return 0; +} +#else + #define MAXNUMOFTESTS 50 #define HDF5_TEST_MASTER @@ -52,283 +61,291 @@ static char RcsId[] = "@(#)$Revision$"; #define NAME_OFFSET 6 /* offset for "name<num>" */ /* Internal Variables */ -static int Index = 0; +static int Index = 0; /* Global variables */ -int num_errs = 0; -int Verbosity; - -#include <ttsafe.h> +int num_errs = 0; +int Verbosity; -#ifndef H5_HAVE_THREADSAFE -int main(void) -{ - printf("Test skipped because THREADSAFE not enabled\n"); - return 0; -} -#else /* ANY new test needs to have a prototype in tproto.h */ struct TestStruct { - int NumErrors; - char Description[64]; - int SkipFlag; - char Name[16]; - void (*Call) (void); - void (*Cleanup) (void); + int NumErrors; + char Description[64]; + int SkipFlag; + char Name[16]; + void (*Call)(void); + void (*Cleanup)(void); } Test[MAXNUMOFTESTS]; -static void InitTest(const char *TheName, void (*TheCall) (void), void (*Cleanup) (void), const char *TheDescr); -static void usage(void); +static void InitTest(const char *TheName, void (*TheCall) (void), + void (*Cleanup) (void), const char *TheDescr); +static void usage(void); -static void -InitTest(const char *TheName, void (*TheCall) (void), void (*Cleanup) (void), const char *TheDescr) +static void InitTest(const char *TheName, void (*TheCall) (void), + void (*Cleanup) (void), const char *TheDescr) { - if (Index >= MAXNUMOFTESTS) { - print_func("Uh-oh, too many tests added, increase MAXNUMOFTEST!\n"); - exit(-1); - } /* end if */ - HDstrcpy(Test[Index].Description, TheDescr); - HDstrcpy(Test[Index].Name, TheName); - Test[Index].Call = TheCall; - Test[Index].Cleanup = Cleanup; - Test[Index].NumErrors = -1; - Test[Index].SkipFlag = 0; - Index++; + if (Index >= MAXNUMOFTESTS) { + print_func("Uh-oh, too many tests added, increase MAXNUMOFTEST!\n"); + exit(-1); + } + + HDstrcpy(Test[Index].Description, TheDescr); + HDstrcpy(Test[Index].Name, TheName); + Test[Index].Call = TheCall; + Test[Index].Cleanup = Cleanup; + Test[Index].NumErrors = -1; + Test[Index].SkipFlag = 0; + Index++; } -static void -usage(void) +static void usage(void) { - intn i; - - print_func("Usage: testhdf5 [-v[erbose] (l[ow]|m[edium]|h[igh]|0-10)] \n"); - print_func(" [-[e]x[clude] name+] \n"); - print_func(" [-o[nly] name+] \n"); - print_func(" [-b[egin] name] \n"); - print_func(" [-s[ummary]] \n"); - print_func(" [-c[leanoff]] \n"); - print_func(" [-n[ocaching]] \n"); - print_func(" [-h[elp]] \n"); - print_func("\n\n"); - print_func("verbose controls the amount of information displayed\n"); - print_func("exclude to exclude tests by name\n"); - print_func("only to name tests which should be run\n"); - print_func("begin start at the name of the test givin\n"); - print_func("summary prints a summary of test results at the end\n"); - print_func("cleanoff does not delete *.hdf files after execution of tests\n"); - print_func("nocaching do not turn on low-level DD caching\n"); - print_func("help print out this information\n"); - print_func("\n\n"); - print_func("This program currently tests the following: \n\n"); - print_func("%16s %s\n", "Name", "Description"); - print_func("%16s %s\n", "----", "-----------"); - for (i = 0; i < Index; i++) - print_func("%16s %s\n", Test[i].Name, Test[i].Description); - print_func("\n\n"); -} /* end usage() */ + intn i; + + print_func("Usage: ttsafe [-v[erbose] (l[ow]|m[edium]|h[igh]|0-10)] \n"); + print_func(" [-[e]x[clude] name+] \n"); + print_func(" [-o[nly] name+] \n"); + print_func(" [-b[egin] name] \n"); + print_func(" [-s[ummary]] \n"); + print_func(" [-c[leanoff]] \n"); + print_func(" [-n[ocaching]] \n"); + print_func(" [-h[elp]] \n"); + print_func("\n\n"); + print_func("verbose controls the amount of information displayed\n"); + print_func("exclude to exclude tests by name\n"); + print_func("only to name tests which should be run\n"); + print_func("begin start at the name of the test givin\n"); + print_func("summary prints a summary of test results at the end\n"); + print_func("cleanoff does not delete *.hdf files after execution of tests\n"); + print_func("nocaching do not turn on low-level DD caching\n"); + print_func("help print out this information\n"); + print_func("\n\n"); + print_func("This program currently tests the following: \n\n"); + print_func("%16s %s\n", "Name", "Description"); + print_func("%16s %s\n", "----", "-----------"); + + for (i = 0; i < Index; i++) + print_func("%16s %s\n", Test[i].Name, Test[i].Description); + + print_func("\n\n"); +} /* * This routine is designed to provide equivalent functionality to 'printf' * and allow easy replacement for environments which don't have stdin/stdout - * available. (i.e. Windows & the Mac) + * available. (i.e. Windows & the Mac) */ int -print_func(const char *format,...) +print_func(const char *format, ...) { - va_list arglist; - int ret_value; + va_list arglist; + int ret_value; - va_start(arglist, format); - ret_value = vprintf(format, arglist); - va_end(arglist); - return (ret_value); + va_start(arglist, format); + ret_value = vprintf(format, arglist); + va_end(arglist); + return ret_value; } -char* gen_name(int value) { - char* temp; - int i, length; +char *gen_name(int value) +{ + char *temp; + int i, length; - length = num_digits(MAX_NUM_NAME-1); - temp = (char *)malloc((NAME_OFFSET+length+1)*sizeof(char)); - temp = strcpy(temp, "attrib"); - temp[NAME_OFFSET+length] = '\0'; + length = num_digits(MAX_NUM_NAME - 1); + temp = (char *)malloc((NAME_OFFSET + length + 1) * sizeof(char)); + temp = strcpy(temp, "attrib"); + temp[NAME_OFFSET + length] = '\0'; - for (i=length-1;i>=0;i--) { - temp[NAME_OFFSET+i] = (char)((int)'0' + value%10); - value = value/10; - } + for (i = length - 1; i >= 0; i--) { + temp[NAME_OFFSET + i] = (char)((int)'0' + value % 10); + value = value / 10; + } - return temp; + return temp; } /* pre-condition: num must be a non-negative number */ -int num_digits(int num) { - int i=0; - - if (num == 0) - return 1; - while (num > 0) { - num = num/10; - i++; - } - return i; +int num_digits(int num) +{ + int i; + + if (num == 0) + return 1; + + for (i = 0; num > 0; i++) + num = num / 10; + + return i; } -int -main(int argc, char *argv[]) +int main(int argc, char *argv[]) { - int CLLoop; /* Command Line Loop */ - int Loop, Loop1; - int Summary = 0; - int CleanUp = 1; - int Cache = 1; - uintn major, minor, release; + int CLLoop; /* Command Line Loop */ + int Loop, Loop1, Summary = 0, CleanUp = 1, Cache = 1; + uintn major, minor, release; #if defined __MWERKS__ - argc = ccommand(&argv); + argc = ccommand(&argv); #endif #if !(defined MAC || defined __MWERKS__ || defined SYMANTEC_C) - /* Un-buffer the stdout and stderr */ - setbuf(stderr, NULL); - setbuf(stdout, NULL); + /* Un-buffer the stdout and stderr */ + setbuf(stderr, NULL); + setbuf(stdout, NULL); #endif - /* - * Turn off automatic error reporting since we do it ourselves. Besides, - * half the functions this test calls are private, so automatic error - * reporting wouldn't do much good since it's triggered at the API layer. - */ - H5Eset_auto (NULL, NULL); - - /* Tests are generally arranged from least to most complexity... */ - InitTest("dcreate", tts_dcreate, cleanup_dcreate, "multi-dataset creation"); - InitTest("error", tts_error, cleanup_error, "per-thread error stacks"); - InitTest("cancel", tts_cancel, cleanup_cancel, "Thread cancellation safety test"); - InitTest("acreate", tts_acreate, cleanup_acreate, "multi-attribute creation"); - - Verbosity = 4; /* Default Verbosity is Low */ - H5get_libversion(&major, &minor, &release); - - print_func("\nFor help use: testhdf5 -help\n"); - print_func("Linked with hdf5 version %u.%u release %u\n", - (unsigned)major, (unsigned)minor, (unsigned)release); - for (CLLoop = 1; CLLoop < argc; CLLoop++) { - if ((argc > CLLoop + 1) && ((HDstrcmp(argv[CLLoop], "-verbose") == 0) || - (HDstrcmp(argv[CLLoop], "-v") == 0))) { - if (argv[CLLoop + 1][0] == 'l') - Verbosity = 4; - else if (argv[CLLoop + 1][0] == 'm') - Verbosity = 6; - else if (argv[CLLoop + 1][0] == 'h') - Verbosity = 10; - else - Verbosity = atoi(argv[CLLoop + 1]); - } /* end if */ - if ((argc > CLLoop) && ((HDstrcmp(argv[CLLoop], "-summary") == 0) || - (HDstrcmp(argv[CLLoop], "-s") == 0))) - Summary = 1; - - if ((argc > CLLoop) && ((HDstrcmp(argv[CLLoop], "-help") == 0) || - (HDstrcmp(argv[CLLoop], "-h") == 0))) { - usage(); - exit(0); - } - if ((argc > CLLoop) && ((HDstrcmp(argv[CLLoop], "-cleanoff") == 0) || - (HDstrcmp(argv[CLLoop], "-c") == 0))) - CleanUp = 0; - - if ((argc > CLLoop) && ((HDstrcmp(argv[CLLoop], "-nocache") == 0) || - (HDstrcmp(argv[CLLoop], "-n") == 0))) { - Cache = 0; - printf ("Cache = %d\n", Cache); - } - - if ((argc > CLLoop + 1) && ((HDstrcmp(argv[CLLoop], "-exclude") == 0) || - (HDstrcmp(argv[CLLoop], "-x") == 0))) { - Loop = CLLoop + 1; - while ((Loop < argc) && (argv[Loop][0] != '-')) { - for (Loop1 = 0; Loop1 < Index; Loop1++) - if (HDstrcmp(argv[Loop], Test[Loop1].Name) == 0) - Test[Loop1].SkipFlag = 1; - Loop++; - } /* end while */ - } /* end if */ - if ((argc > CLLoop + 1) && ((HDstrcmp(argv[CLLoop], "-begin") == 0) || - (HDstrcmp(argv[CLLoop], "-b") == 0))) { - Loop = CLLoop + 1; - while ((Loop < argc) && (argv[Loop][0] != '-')) { - for (Loop1 = 0; Loop1 < Index; Loop1++) { - if (HDstrcmp(argv[Loop], Test[Loop1].Name) != 0) - Test[Loop1].SkipFlag = 1; - if (HDstrcmp(argv[Loop], Test[Loop1].Name) == 0) - Loop1 = Index; - } /* end for */ - Loop++; - } /* end while */ - } /* end if */ - if ((argc > CLLoop + 1) && ((HDstrcmp(argv[CLLoop], "-only") == 0) || - (HDstrcmp(argv[CLLoop], "-o") == 0))) { - for (Loop = 0; Loop < Index; Loop++) - Test[Loop].SkipFlag = 1; - Loop = CLLoop + 1; - while ((Loop < argc) && (argv[Loop][0] != '-')) { - for (Loop1 = 0; Loop1 < Index; Loop1++) - if (HDstrcmp(argv[Loop], Test[Loop1].Name) == 0) - Test[Loop1].SkipFlag = 0; - Loop++; - } /* end while */ - } /* end if */ - } /* end for */ + /* + * Turn off automatic error reporting since we do it ourselves. + * Besides, half the functions this test calls are private, so + * automatic error reporting wouldn't do much good since it's + * triggered at the API layer. + */ + H5Eset_auto (NULL, NULL); + + /* Tests are generally arranged from least to most complexity... */ + InitTest("dcreate", tts_dcreate, cleanup_dcreate, + "multi-dataset creation"); + InitTest("error", tts_error, cleanup_error, + "per-thread error stacks"); + InitTest("cancel", tts_cancel, cleanup_cancel, + "thread cancellation safety test"); + InitTest("acreate", tts_acreate, cleanup_acreate, + "multi-attribute creation"); + + Verbosity = 4; /* Default Verbosity is Low */ + H5get_libversion(&major, &minor, &release); + + print_func("\nFor help use: ttsafe -help\n"); + print_func("Linked with hdf5 version %u.%u release %u\n", + (unsigned)major, (unsigned)minor, (unsigned)release); + + for (CLLoop = 1; CLLoop < argc; CLLoop++) { + if (argc > CLLoop + 1 && + (HDstrcmp(argv[CLLoop], "-verbose") == 0 || + HDstrcmp(argv[CLLoop], "-v") == 0)) { + if (argv[CLLoop + 1][0] == 'l') + Verbosity = 4; + else if (argv[CLLoop + 1][0] == 'm') + Verbosity = 6; + else if (argv[CLLoop + 1][0] == 'h') + Verbosity = 10; + else + Verbosity = atoi(argv[CLLoop + 1]); + } /* end if */ + + if (argc > CLLoop && + (HDstrcmp(argv[CLLoop], "-summary") == 0 || + HDstrcmp(argv[CLLoop], "-s") == 0)) + Summary = 1; + + if (argc > CLLoop && + (HDstrcmp(argv[CLLoop], "-help") == 0 || + HDstrcmp(argv[CLLoop], "-h") == 0)) { + usage(); + exit(0); + } + + if (argc > CLLoop && + (HDstrcmp(argv[CLLoop], "-cleanoff") == 0 || + HDstrcmp(argv[CLLoop], "-c") == 0)) + CleanUp = 0; + + if (argc > CLLoop && + (HDstrcmp(argv[CLLoop], "-nocache") == 0 || + HDstrcmp(argv[CLLoop], "-n") == 0)) { + Cache = 0; + print_func("Cache = %d\n", Cache); + } + + if (argc > CLLoop + 1 && + (HDstrcmp(argv[CLLoop], "-exclude") == 0 || + HDstrcmp(argv[CLLoop], "-x") == 0)) + for (Loop = CLLoop + 1; Loop < argc && argv[Loop][0] != '-'; Loop++) + for (Loop1 = 0; Loop1 < Index; Loop1++) + if (HDstrcmp(argv[Loop], Test[Loop1].Name) == 0) + Test[Loop1].SkipFlag = 1; + + if (argc > CLLoop + 1 && + (HDstrcmp(argv[CLLoop], "-begin") == 0 || + HDstrcmp(argv[CLLoop], "-b") == 0)) + for (Loop = CLLoop + 1; Loop < argc && argv[Loop][0] != '-'; Loop++) + for (Loop1 = 0; Loop1 < Index; Loop1++) { + if (HDstrcmp(argv[Loop], Test[Loop1].Name) != 0) + Test[Loop1].SkipFlag = 1; + + if (HDstrcmp(argv[Loop], Test[Loop1].Name) == 0) + Loop1 = Index; + } + + if (argc > CLLoop + 1 && + (HDstrcmp(argv[CLLoop], "-only") == 0 || + HDstrcmp(argv[CLLoop], "-o") == 0)) { + for (Loop = 0; Loop < Index; Loop++) + Test[Loop].SkipFlag = 1; + + for (Loop = CLLoop + 1; Loop < argc && argv[Loop][0] != '-'; Loop++) + for (Loop1 = 0; Loop1 < Index; Loop1++) + if (HDstrcmp(argv[Loop], Test[Loop1].Name) == 0) + Test[Loop1].SkipFlag = 0; + } + } /* end for */ #ifdef NOT_YET - if (Cache) /* turn on caching, unless we were instucted not to */ - Hcache(CACHE_ALL_FILES, TRUE); + if (Cache) + /* turn on caching, unless we were instucted not to */ + Hcache(CACHE_ALL_FILES, TRUE); #endif /* NOT_YET */ - for (Loop = 0; Loop < Index; Loop++) { - if (Test[Loop].SkipFlag) { - MESSAGE(2, ("Skipping -- %s \n", Test[Loop].Description)); - } else { - MESSAGE(2, ("Testing -- %s (%s) \n", Test[Loop].Description, - Test[Loop].Name)); - MESSAGE(5, ("===============================================\n")); - Test[Loop].NumErrors = num_errs; - (*Test[Loop].Call) (); - Test[Loop].NumErrors = num_errs - Test[Loop].NumErrors; - MESSAGE(5, ("===============================================\n")); - MESSAGE(5, ("There were %d errors detected.\n\n", (int) Test[Loop].NumErrors)); - } /* end else */ - } /* end for */ - - MESSAGE(2, ("\n\n")) - if (num_errs) - print_func("!!! %d Error(s) were detected !!!\n\n", (int) num_errs); - else - print_func("All tests were successful. \n\n"); - - if (Summary) { - print_func("Summary of Test Results:\n"); - print_func("Name of Test Errors Description of Test\n"); - print_func("---------------- ------ --------------------------------------\n"); - - for (Loop = 0; Loop < Index; Loop++) { - if (Test[Loop].NumErrors == -1) - print_func("%16s %6s %s\n", Test[Loop].Name, "N/A", Test[Loop].Description); - else - print_func("%16s %6d %s\n", Test[Loop].Name, (int) Test[Loop].NumErrors, - Test[Loop].Description); - } /* end for */ - print_func("\n\n"); - } /* end if */ - if (CleanUp && !getenv("HDF5_NOCLEANUP")) { - MESSAGE(2, ("\nCleaning Up temp files...\n\n")); - - /* call individual cleanup routines in each source module */ - for (Loop = 0; Loop < Index; Loop++) - if (!Test[Loop].SkipFlag && Test[Loop].Cleanup!=NULL) - (*Test[Loop].Cleanup) (); - } - return (num_errs); -} /* end main() */ + for (Loop = 0; Loop < Index; Loop++) + if (Test[Loop].SkipFlag) { + MESSAGE(2, ("Skipping -- %s \n", Test[Loop].Description)); + } else { + MESSAGE(2, ("Testing -- %s (%s) \n", Test[Loop].Description, + Test[Loop].Name)); + MESSAGE(5, ("===============================================\n")); + Test[Loop].NumErrors = num_errs; + Test[Loop].Call(); + Test[Loop].NumErrors = num_errs - Test[Loop].NumErrors; + MESSAGE(5, ("===============================================\n")); + MESSAGE(5, ("There were %d errors detected.\n\n", + (int)Test[Loop].NumErrors)); + } + + MESSAGE(2, ("\n\n")) + + if (num_errs) + print_func("!!! %d Error(s) were detected !!!\n\n", (int) num_errs); + else + print_func("All tests were successful. \n\n"); + + if (Summary) { + print_func("Summary of Test Results:\n"); + print_func("Name of Test Errors Description of Test\n"); + print_func("---------------- ------ --------------------------------------\n"); + + for (Loop = 0; Loop < Index; Loop++) { + if (Test[Loop].NumErrors == -1) + print_func("%16s %6s %s\n", Test[Loop].Name, + "N/A", Test[Loop].Description); + else + print_func("%16s %6d %s\n", Test[Loop].Name, + (int)Test[Loop].NumErrors, + Test[Loop].Description); + } + + print_func("\n\n"); + } + + if (CleanUp && !getenv("HDF5_NOCLEANUP")) { + MESSAGE(2, ("\nCleaning Up temp files...\n\n")); + + /* call individual cleanup routines in each source module */ + for (Loop = 0; Loop < Index; Loop++) + if (!Test[Loop].SkipFlag && Test[Loop].Cleanup!=NULL) + Test[Loop].Cleanup(); + } + + return num_errs; +} /* end main() */ #endif /*H5_HAVE_THREADSAFE*/ diff --git a/test/ttsafe_acreate.c b/test/ttsafe_acreate.c index 26d9aee..7aa8bde 100644 --- a/test/ttsafe_acreate.c +++ b/test/ttsafe_acreate.c @@ -21,7 +21,13 @@ * * Modification History * -------------------- - * May 15 2000 - incorporated into library tests (Chee Wai LEE) + * + * 15 May 2000, Chee Wai LEE + * Incorporated into library tests. + * + * 19 May 2000, Bill Wendling + * Changed so that it creates its own HDF5 file and removes it at cleanup + * time. Added num_errs flag. * ********************************************************************/ @@ -34,136 +40,136 @@ static int dummy; /* just to create a non-empty object file */ #include <stdio.h> #include <stdlib.h> -#define FILE "ttsafe.h5" -#define DATASETNAME "IntData" -#define NUM_THREADS 16 +#define FILENAME "ttsafe_acreate.h5" +#define DATASETNAME "IntData" +#define NUM_THREADS 16 + +/* Global variables */ +extern int num_errs; +extern int Verbosity; void *tts_acreate_thread(void *); typedef struct acreate_data_struct { - hid_t dataset; - hid_t datatype; - hid_t dataspace; - int current_index; + hid_t dataset; + hid_t datatype; + hid_t dataspace; + int current_index; } ttsafe_name_data_t; -void tts_acreate(void) { - - /* Pthread definitions - */ - pthread_t threads[NUM_THREADS]; - - /* HDF5 data definitions - */ - hid_t file, dataset; - hid_t dataspace, datatype; - hid_t attribute; - hsize_t dimsf[1]; /* dataset dimensions */ - - int data; /* data to write */ - int buffer, ret; - - int i; - ttsafe_name_data_t *attrib_data; - - /* create a hdf5 file using H5F_ACC_TRUNC access, - * default file creation plist and default file - * access plist - */ - file = H5Fcreate(FILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); - - /* create a simple dataspace for the dataset - */ - dimsf[0] = 1; - dataspace = H5Screate_simple(1,dimsf,NULL); - - /* define datatype for the data using native little endian integers - */ - datatype = H5Tcopy(H5T_NATIVE_INT); - H5Tset_order(datatype, H5T_ORDER_LE); - - /* create a new dataset within the file - */ - dataset = H5Dcreate(file, DATASETNAME, datatype, dataspace, - H5P_DEFAULT); - - /* initialize data for dataset and write value to dataset - */ - data = NUM_THREADS; - H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, - H5P_DEFAULT, &data); - - /* simultaneously create a large number of attributes to be - associated with the dataset - */ - - for (i=0;i<NUM_THREADS;i++) { - attrib_data = malloc(sizeof(ttsafe_name_data_t)); - attrib_data->dataset = dataset; - attrib_data->datatype = datatype; - attrib_data->dataspace = dataspace; - attrib_data->current_index = i; - pthread_create(&threads[i],NULL,tts_acreate_thread,attrib_data); - } - - for (i=0;i<NUM_THREADS;i++) { - pthread_join(threads[i],NULL); - } - - /* verify the correctness of the test */ - for (i=0; i<NUM_THREADS; i++) { - attribute = H5Aopen_name(dataset,gen_name(i)); - if (attribute < 0) { - fprintf(stderr,"unable to open appropriate attribute. Test failed!\n"); - } else { - ret = H5Aread(attribute, H5T_NATIVE_INT, &buffer); - if ((ret < 0) || (buffer != i)) { - fprintf(stderr,"wrong data values. Test failed!\n"); - } - H5Aclose(attribute); - } - } - - /* close remaining resources - */ - H5Sclose(dataspace); - H5Tclose(datatype); - H5Dclose(dataset); - H5Fclose(file); +void tts_acreate(void) +{ + /* Pthread declarations */ + pthread_t threads[NUM_THREADS]; + + /* HDF5 data declarations */ + hid_t file, dataset; + hid_t dataspace, datatype; + hid_t attribute; + hsize_t dimsf[1]; /* dataset dimensions */ + + /* data declarations */ + int data; /* data to write */ + int buffer, ret, i; + + ttsafe_name_data_t *attrib_data; + + /* + * Create an HDF5 file using H5F_ACC_TRUNC access, default file + * creation plist and default file access plist + */ + file = H5Fcreate(FILENAME, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + + /* create a simple dataspace for the dataset */ + dimsf[0] = 1; + dataspace = H5Screate_simple(1, dimsf, NULL); + + /* define datatype for the data using native little endian integers */ + datatype = H5Tcopy(H5T_NATIVE_INT); + H5Tset_order(datatype, H5T_ORDER_LE); + + /* create a new dataset within the file */ + dataset = H5Dcreate(file, DATASETNAME, datatype, dataspace, + H5P_DEFAULT); + + /* initialize data for dataset and write value to dataset */ + data = NUM_THREADS; + H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, + H5P_DEFAULT, &data); + + /* + * Simultaneously create a large number of attributes to be associated + * with the dataset + */ + for (i = 0; i < NUM_THREADS; i++) { + attrib_data = malloc(sizeof(ttsafe_name_data_t)); + attrib_data->dataset = dataset; + attrib_data->datatype = datatype; + attrib_data->dataspace = dataspace; + attrib_data->current_index = i; + pthread_create(&threads[i], NULL, tts_acreate_thread, + attrib_data); + } + + for (i = 0; i < NUM_THREADS; i++) + pthread_join(threads[i], NULL); + + /* verify the correctness of the test */ + for (i = 0; i < NUM_THREADS; i++) { + attribute = H5Aopen_name(dataset,gen_name(i)); + + if (attribute < 0) { + fprintf(stderr, + "unable to open appropriate attribute. " + "Test failed!\n"); + num_errs++; + } else { + ret = H5Aread(attribute, H5T_NATIVE_INT, &buffer); + + if (ret < 0 || buffer != i) { + fprintf(stderr, + "wrong data values. Test failed!\n"); + num_errs++; + } + + H5Aclose(attribute); + } + } + + /* close remaining resources */ + H5Sclose(dataspace); + H5Tclose(datatype); + H5Dclose(dataset); + H5Fclose(file); } -void *tts_acreate_thread(void *client_data) { +void *tts_acreate_thread(void *client_data) +{ + hid_t attribute; + char *attribute_name; + int *attribute_data; /* data for attributes */ - hid_t attribute; - hsize_t dimsf[1]; /* dataset dimensions */ + ttsafe_name_data_t *attrib_data; - char *attribute_name; - int *attribute_data; /* data for attributes */ - int i; + attrib_data = (ttsafe_name_data_t *)client_data; - ttsafe_name_data_t *attrib_data = (ttsafe_name_data_t *)client_data; + /* Create attribute */ + attribute_name = gen_name(attrib_data->current_index); + attribute = H5Acreate(attrib_data->dataset, attribute_name, + attrib_data->datatype, attrib_data->dataspace, + H5P_DEFAULT); - /* create attribute - */ - attribute_name = gen_name(attrib_data->current_index); - attribute = H5Acreate(attrib_data->dataset, - attribute_name, - attrib_data->datatype, - attrib_data->dataspace, - H5P_DEFAULT); - - /* Write data to the attribute - */ - attribute_data = malloc(sizeof(int)); - *attribute_data = attrib_data->current_index; - H5Awrite(attribute,H5T_NATIVE_INT,attribute_data); - H5Aclose(attribute); - - return NULL; + /* Write data to the attribute */ + attribute_data = malloc(sizeof(int)); + *attribute_data = attrib_data->current_index; + H5Awrite(attribute, H5T_NATIVE_INT, attribute_data); + H5Aclose(attribute); + return NULL; } -void cleanup_acreate(void) { +void cleanup_acreate(void) +{ + HDunlink(FILENAME); } #endif /*H5_HAVE_THREADSAFE*/ - diff --git a/test/ttsafe_cancel.c b/test/ttsafe_cancel.c index 4e893e9..80981f5 100644 --- a/test/ttsafe_cancel.c +++ b/test/ttsafe_cancel.c @@ -12,7 +12,7 @@ * left the H5Diterate call. * * Temporary files generated: - * ttsafe.h5 + * ttsafe_cancel.h5 * * HDF5 APIs exercised in thread: * H5Screate_simple, H5Tcopy, H5Tset_order, H5Dcreate, H5Dclose, @@ -24,6 +24,10 @@ * Modification History * -------------------- * + * 19 May 2000, Bill Wendling + * Changed so that it creates its own HDF5 file and removes it at cleanup + * time. Added num_errs flag. + * ********************************************************************/ #include "ttsafe.h" @@ -31,8 +35,12 @@ static int dummy; /* just to create a non-empty object file */ #else -#define FILE "ttsafe.h5" -#define DATASETNAME "commonname" +#define FILENAME "ttsafe_cancel.h5" +#define DATASETNAME "commonname" + +/* Global variables */ +extern int num_errs; +extern int Verbosity; void *tts_cancel_thread(void *); void tts_cancel_barrier(void); @@ -41,163 +49,164 @@ void cancellation_cleanup(void *); hid_t cancel_file; typedef struct cleanup_struct { - hid_t dataset; - hid_t datatype; - hid_t dataspace; + hid_t dataset; + hid_t datatype; + hid_t dataspace; } cancel_cleanup_t; pthread_t childthread; pthread_mutex_t mutex; pthread_cond_t cond; -void tts_cancel(void) { - - pthread_attr_t attribute; - hid_t dataset; - - int buffer; - - /* make thread scheduling global */ - pthread_attr_init(&attribute); - pthread_attr_setscope(&attribute, PTHREAD_SCOPE_SYSTEM); - - /* create a hdf5 file using H5F_ACC_TRUNC access, - * default file creation plist and default file - * access plist - */ - cancel_file = H5Fcreate(FILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); - - pthread_create(&childthread, &attribute, tts_cancel_thread, NULL); - - tts_cancel_barrier(); - pthread_cancel(childthread); - - dataset = H5Dopen(cancel_file, DATASETNAME); - H5Dread(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, - &buffer); - - if (buffer == 11) { - /* do nothing */ - } else { - fprintf(stderr, - "operation unsuccessful with value at %d instead of 11\n", - buffer); - } - - H5Dclose(dataset); - H5Fclose(cancel_file); +void tts_cancel(void) +{ + pthread_attr_t attribute; + hid_t dataset; + int buffer; + + /* make thread scheduling global */ + pthread_attr_init(&attribute); + pthread_attr_setscope(&attribute, PTHREAD_SCOPE_SYSTEM); + + /* + * Create a hdf5 file using H5F_ACC_TRUNC access, default file + * creation plist and default file access plist + */ + cancel_file = H5Fcreate(FILENAME, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + pthread_create(&childthread, &attribute, tts_cancel_thread, NULL); + tts_cancel_barrier(); + pthread_cancel(childthread); + + dataset = H5Dopen(cancel_file, DATASETNAME); + H5Dread(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, + &buffer); + + if (buffer != 11) { + fprintf(stderr, + "operation unsuccessful with value at %d instead of 11\n", + buffer); + num_errs++; + } + + H5Dclose(dataset); + H5Fclose(cancel_file); } -void *tts_cancel_thread(void *arg) { - - int datavalue; - int *buffer; - hid_t dataspace, datatype, dataset; - hsize_t dimsf[1]; /* dataset dimensions */ - - cancel_cleanup_t *cleanup_structure; - - /* define dataspace for dataset - */ - dimsf[0] = 1; - dataspace = H5Screate_simple(1,dimsf,NULL); - - /* define datatype for the data using native little endian integers - */ - datatype = H5Tcopy(H5T_NATIVE_INT); - H5Tset_order(datatype, H5T_ORDER_LE); - - /* create a new dataset within the file - */ - dataset = H5Dcreate(cancel_file, DATASETNAME, datatype, dataspace, - H5P_DEFAULT); - - /* If thread is cancelled, make cleanup call */ - cleanup_structure = (cancel_cleanup_t*)malloc(sizeof(cancel_cleanup_t)); - cleanup_structure->dataset = dataset; - cleanup_structure->datatype = datatype; - cleanup_structure->dataspace = dataspace; - pthread_cleanup_push(cancellation_cleanup, cleanup_structure); - - datavalue = 1; - H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, - &datavalue); - - buffer = malloc(sizeof(int)); - H5Dread(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, - buffer); - H5Diterate(buffer, H5T_NATIVE_INT, dataspace, tts_cancel_callback, - &dataset); - - sleep(3); - - datavalue = 100; - H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, - &datavalue); - H5Dclose(dataset); - H5Tclose(datatype); - H5Sclose(dataspace); - - /* required by pthreads. the argument 0 pops the stack but does not - execute the cleanup routine. - */ - pthread_cleanup_pop(0); - - return (NULL); +void *tts_cancel_thread(void *arg) +{ + int datavalue; + int *buffer; + hid_t dataspace, datatype, dataset; + hsize_t dimsf[1]; /* dataset dimensions */ + cancel_cleanup_t *cleanup_structure; + + /* define dataspace for dataset */ + dimsf[0] = 1; + dataspace = H5Screate_simple(1,dimsf,NULL); + + /* define datatype for the data using native little endian integers */ + datatype = H5Tcopy(H5T_NATIVE_INT); + H5Tset_order(datatype, H5T_ORDER_LE); + + /* create a new dataset within the file */ + dataset = H5Dcreate(cancel_file, DATASETNAME, datatype, dataspace, + H5P_DEFAULT); + + /* If thread is cancelled, make cleanup call */ + cleanup_structure = (cancel_cleanup_t*)malloc(sizeof(cancel_cleanup_t)); + cleanup_structure->dataset = dataset; + cleanup_structure->datatype = datatype; + cleanup_structure->dataspace = dataspace; + pthread_cleanup_push(cancellation_cleanup, cleanup_structure); + + datavalue = 1; + H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, + &datavalue); + + buffer = malloc(sizeof(int)); + H5Dread(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, + buffer); + H5Diterate(buffer, H5T_NATIVE_INT, dataspace, tts_cancel_callback, + &dataset); + + sleep(3); + + datavalue = 100; + H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, + &datavalue); + H5Dclose(dataset); + H5Tclose(datatype); + H5Sclose(dataspace); + + /* + * Required by pthreads. The argument 0 pops the stack but does not + * execute the cleanup routine. + */ + pthread_cleanup_pop(0); + return NULL; } herr_t tts_cancel_callback(void *elem, hid_t type_id, hsize_t ndim, - hssize_t *point, void *operator_data) { - int value = *(int *)elem; - hid_t dataset = *(hid_t *)operator_data; - - tts_cancel_barrier(); - sleep(3); - - if (value != 1) { - fprintf(stderr,"Error! Element value should be 1 and not %d\n", value); - return(-1); - } - - value += 10; - H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, - &value); - - return (0); + hssize_t *point, void *operator_data) +{ + int value = *(int *)elem; + hid_t dataset = *(hid_t *)operator_data; + + tts_cancel_barrier(); + sleep(3); + + if (value != 1) { + fprintf(stderr, "Error! Element value should be 1 and not %d\n", + value); + num_errs++; + return -1; + } + + value += 10; + H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, + &value); + return 0; } -/* need to perform the dataset, datatype and dataspace close that was - never performed because of thread cancellation -*/ -void cancellation_cleanup(void *arg) { - cancel_cleanup_t *cleanup_structure = (cancel_cleanup_t *)arg; - H5Dclose(cleanup_structure->dataset); - H5Tclose(cleanup_structure->datatype); - H5Sclose(cleanup_structure->dataspace); - /* retained for debugging */ - /* printf("cancellation noted, cleaning up ... \n"); */ +/* + * Need to perform the dataset, datatype and dataspace close that was never + * performed because of thread cancellation + */ +void cancellation_cleanup(void *arg) +{ + cancel_cleanup_t *cleanup_structure = (cancel_cleanup_t *)arg; + H5Dclose(cleanup_structure->dataset); + H5Tclose(cleanup_structure->datatype); + H5Sclose(cleanup_structure->dataspace); + + /* retained for debugging */ + /* print_func("cancellation noted, cleaning up ... \n"); */ } /* - artificial (and specific to this test) barrier to keep track of whether - both the main and child threads have reached a point in the program. -*/ -void tts_cancel_barrier() { - - static int count = 2; - - pthread_mutex_lock(&mutex); - if (count != 1) { - count--; - pthread_cond_wait(&cond, &mutex); - } else { - pthread_cond_signal(&cond); - } - pthread_mutex_unlock(&mutex); - + * Artificial (and specific to this test) barrier to keep track of whether + * both the main and child threads have reached a point in the program. + */ +void tts_cancel_barrier(void) +{ + static int count = 2; + + pthread_mutex_lock(&mutex); + + if (count != 1) { + count--; + pthread_cond_wait(&cond, &mutex); + } else { + pthread_cond_signal(&cond); + } + + pthread_mutex_unlock(&mutex); } -void cleanup_cancel() { - H5close(); +void cleanup_cancel(void) +{ + H5close(); + HDunlink(FILENAME); } + #endif /*H5_HAVE_THREADSAFE*/ diff --git a/test/ttsafe_dcreate.c b/test/ttsafe_dcreate.c index cc7d6e6..aa77e36 100644 --- a/test/ttsafe_dcreate.c +++ b/test/ttsafe_dcreate.c @@ -8,7 +8,7 @@ * threadsafe environment. * * Temporary files generated: - * ttsafe.h5 + * ttsafe_dcreate.h5 * * HDF5 APIs exercised in thread: * H5Screate_simple, H5Tcopy, H5Tset_order, H5Dcreate, H5Dwrite, H5Dclose, @@ -20,6 +20,10 @@ * Modification History * -------------------- * + * 19 May 2000, Bill Wendling + * Changed so that it creates its own HDF5 file and removes it at cleanup + * time. Added num_errs flag. + * ********************************************************************/ #include "ttsafe.h" @@ -27,165 +31,157 @@ static int dummy; /* just to create a non-empty object file */ #else -#define FILE "ttsafe.h5" -#define DATASETNAME_LENGTH 10 -#define NUM_THREAD 16 +#define FILENAME "ttsafe_dcreate.h5" +#define DATASETNAME_LENGTH 10 +#define NUM_THREAD 16 + +/* Global variables */ +extern int num_errs; +extern int Verbosity; void *tts_dcreate_creator(void *); +typedef struct thread_info { + int id; + hid_t file; + const char *dsetname; +} thread_info; + /* ********************************************************************** * Thread safe test - multiple dataset creation ********************************************************************** */ -void tts_dcreate(void) { - - /* Pthread definitions - */ - pthread_t threads[NUM_THREAD]; - - /* HDF5 data definitions - */ - hid_t file, dataset, datatype; - - int datavalue; - int i; - - typedef struct thread_info { - int id; - hid_t file; - char *dsetname; - } thread_info; - - thread_info *thread_out; - - char *dsetname[NUM_THREAD]; - pthread_attr_t attribute; - - /* set pthread attribute to perform global scheduling */ - pthread_attr_init(&attribute); - pthread_attr_setscope(&attribute, PTHREAD_SCOPE_SYSTEM); - - /* set individual dataset names (rather than generated the names - automatically) - */ - - for (i=0;i<NUM_THREAD;i++) { - dsetname[i] = (char *)malloc(sizeof(char)*DATASETNAME_LENGTH); - } - dsetname[0] = "zero"; - dsetname[1] = "one"; - dsetname[2] = "two"; - dsetname[3] = "three"; - dsetname[4] = "four"; - dsetname[5] = "five"; - dsetname[6] = "six"; - dsetname[7] = "seven"; - dsetname[8] = "eight"; - dsetname[9] = "nine"; - dsetname[10] = "ten"; - dsetname[11] = "eleven"; - dsetname[12] = "twelve"; - dsetname[13] = "thirteen"; - dsetname[14] = "fourteen"; - dsetname[15] = "fifteen"; - - /* create a hdf5 file using H5F_ACC_TRUNC access, - * default file creation plist and default file - * access plist - */ - file = H5Fcreate(FILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); - - /* simultaneously create a large number of datasets within the file - */ - for (i=0;i<NUM_THREAD;i++) { - thread_out = (thread_info *)malloc(sizeof(thread_info)); - thread_out->id = i; - thread_out->file = file; - thread_out->dsetname = dsetname[i]; - pthread_create(&threads[i],NULL,tts_dcreate_creator,thread_out); - } - - for (i=0;i<NUM_THREAD;i++) { - pthread_join(threads[i],NULL); - } - - /* compare data to see if it is written correctly - */ - - /* define datatype for the data using native little endian integers - */ - datatype = H5Tcopy(H5T_NATIVE_INT); - - for (i=0;i<NUM_THREAD;i++) { - if ((dataset = H5Dopen(file,dsetname[i])) < 0) { - fprintf(stderr,"Dataset name not found - test failed\n"); - H5Fclose(file); - return; - } else { - H5Dread(dataset, datatype, H5S_ALL, H5S_ALL, H5P_DEFAULT, &datavalue); - if (datavalue != i) { - fprintf(stderr, - "Wrong value read %d for dataset name %s - test failed\n", - datavalue, dsetname[i]); - H5Dclose(dataset); +void tts_dcreate(void) +{ + /* Pthread definitions */ + pthread_t threads[NUM_THREAD]; + + /* HDF5 data definitions */ + hid_t file, dataset, datatype; + int datavalue, i; + thread_info *thread_out; + const char *dsetname[NUM_THREAD]; + pthread_attr_t attribute; + + /* set pthread attribute to perform global scheduling */ + pthread_attr_init(&attribute); + pthread_attr_setscope(&attribute, PTHREAD_SCOPE_SYSTEM); + + /* + * Set individual dataset names (rather than generated the names + * automatically) + */ + + for (i = 0; i < NUM_THREAD; i++) + dsetname[i] = malloc(sizeof(char) * DATASETNAME_LENGTH); + + dsetname[0] = "zero"; + dsetname[1] = "one"; + dsetname[2] = "two"; + dsetname[3] = "three"; + dsetname[4] = "four"; + dsetname[5] = "five"; + dsetname[6] = "six"; + dsetname[7] = "seven"; + dsetname[8] = "eight"; + dsetname[9] = "nine"; + dsetname[10] = "ten"; + dsetname[11] = "eleven"; + dsetname[12] = "twelve"; + dsetname[13] = "thirteen"; + dsetname[14] = "fourteen"; + dsetname[15] = "fifteen"; + + /* + * Create a hdf5 file using H5F_ACC_TRUNC access, default file + * creation plist and default file access plist + */ + file = H5Fcreate(FILENAME, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + + /* simultaneously create a large number of datasets within the file */ + for (i = 0; i < NUM_THREAD; i++) { + thread_out = malloc(sizeof(thread_info)); + thread_out->id = i; + thread_out->file = file; + thread_out->dsetname = dsetname[i]; + pthread_create(&threads[i], NULL, tts_dcreate_creator, thread_out); + } + + for (i = 0;i < NUM_THREAD; i++) + pthread_join(threads[i], NULL); + + /* compare data to see if it is written correctly */ + + /* define datatype for the data using native little endian integers */ + datatype = H5Tcopy(H5T_NATIVE_INT); + + for (i = 0; i < NUM_THREAD; i++) { + if ((dataset = H5Dopen(file,dsetname[i])) < 0) { + fprintf(stderr, "Dataset name not found - test failed\n"); + H5Fclose(file); + num_errs++; + return; + } else { + H5Dread(dataset, datatype, H5S_ALL, H5S_ALL, H5P_DEFAULT, &datavalue); + + if (datavalue != i) { + fprintf(stderr, + "Wrong value read %d for dataset name %s - test failed\n", + datavalue, dsetname[i]); + H5Dclose(dataset); + H5Fclose(file); + num_errs++; + return; + } + + H5Dclose(dataset); + } + } + + /* close remaining resources */ H5Fclose(file); - return; - } - H5Dclose(dataset); - } - } - /* close remaining resources - */ - H5Fclose(file); - } -void *tts_dcreate_creator(void *thread_data) { - - hid_t dataspace, datatype, dataset; - hsize_t dimsf[1]; /* dataset dimensions */ - - struct thread_info { - int id; - hid_t file; - char *dsetname; - } thread_in; - - thread_in.dsetname = (char *)malloc(sizeof(char)*DATASETNAME_LENGTH); - thread_in = *((struct thread_info *)thread_data); - - /* define dataspace for dataset - */ - dimsf[0] = 1; - dataspace = H5Screate_simple(1,dimsf,NULL); - - /* define datatype for the data using native little endian integers - */ - datatype = H5Tcopy(H5T_NATIVE_INT); - H5Tset_order(datatype, H5T_ORDER_LE); - - /* create a new dataset within the file - */ - dataset = H5Dcreate(thread_in.file, thread_in.dsetname, - datatype, dataspace, - H5P_DEFAULT); - - /* initialize data for dataset and write value to dataset - */ - H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, - H5P_DEFAULT, &thread_in.id); - - /* close dataset, datatype and dataspace resources - */ - H5Dclose(dataset); - H5Tclose(datatype); - H5Sclose(dataspace); - - return NULL; +void *tts_dcreate_creator(void *thread_data) +{ + hid_t dataspace, datatype, dataset; + hsize_t dimsf[1]; /* dataset dimensions */ + struct thread_info { + int id; + hid_t file; + char *dsetname; + } thread_in; + + thread_in.dsetname = malloc(sizeof(char) * DATASETNAME_LENGTH); + thread_in = *((struct thread_info *)thread_data); + + /* define dataspace for dataset */ + dimsf[0] = 1; + dataspace = H5Screate_simple(1,dimsf,NULL); + + /* define datatype for the data using native little endian integers */ + datatype = H5Tcopy(H5T_NATIVE_INT); + H5Tset_order(datatype, H5T_ORDER_LE); + + /* create a new dataset within the file */ + dataset = H5Dcreate(thread_in.file, thread_in.dsetname, + datatype, dataspace, H5P_DEFAULT); + + /* initialize data for dataset and write value to dataset */ + H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, + H5P_DEFAULT, &thread_in.id); + + /* close dataset, datatype and dataspace resources */ + H5Dclose(dataset); + H5Tclose(datatype); + H5Sclose(dataspace); + return NULL; } -void cleanup_dcreate(void) { - H5close(); +void cleanup_dcreate(void) +{ + H5close(); + HDunlink(FILENAME); } #endif /*H5_HAVE_THREADSAFE*/ diff --git a/test/ttsafe_error.c b/test/ttsafe_error.c index 1dafd23..b9b8b0b 100644 --- a/test/ttsafe_error.c +++ b/test/ttsafe_error.c @@ -9,7 +9,7 @@ * entry. * * Temporary files generated: - * ttsafe.h5 + * ttsafe_error.h5 * * HDF5 APIs exercised in thread: * H5Screate_simple, H5Tcopy, H5Tset_order, H5Dcreate, H5Dclose, @@ -21,6 +21,11 @@ * Modification History * -------------------- * + * 19 May 2000, Bill Wendling + * Modified so that it creates a unique HDF5 file and removes it on + * cleanup. Also added the num_errs flag and increment it when necessary + * to report the errors. + * ********************************************************************/ #include "ttsafe.h" @@ -28,12 +33,17 @@ static int dummy; /* just to create a non-empty object file */ #else -#define NUM_THREAD 16 -#define FILE "ttsafe.h5" +#define NUM_THREAD 16 +#define FILENAME "ttsafe_error.h5" + /* Having a common dataset name is an error */ -#define DATASETNAME "commonname" -#define EXPECTED_ERROR_DEPTH 3 -#define WRITE_NUMBER 37 +#define DATASETNAME "commonname" +#define EXPECTED_ERROR_DEPTH 3 +#define WRITE_NUMBER 37 + +/* Global variables */ +extern int num_errs; +extern int Verbosity; herr_t error_callback(void *); herr_t walk_error_callback(int, H5E_error_t *, void *); @@ -41,139 +51,139 @@ void *tts_error_thread(void *); hid_t error_file; typedef struct err_num_struct { - int maj_num; - int min_num; + int maj_num; + int min_num; } err_num_t; -err_num_t expected[] = {{15, 23}, {15, 23}, {10, 32}}; +err_num_t expected[] = { + {15, 23}, + {15, 23}, + {10, 32} +}; + int error_flag = 0; int error_count = 0; - pthread_mutex_t error_mutex; -void tts_error(void) { - - int i; - - pthread_t threads[NUM_THREAD]; - pthread_attr_t attribute; - - hid_t dataset; - int value; - - H5E_auto_t old_error_cb; - void *old_error_client_data; - - /* set up mutex for global count of errors */ - pthread_mutex_init(&error_mutex, NULL); - - /* preserve previous error stack handler */ - H5Eget_auto(&old_error_cb, &old_error_client_data); - - /* set our own auto error stack handler */ - H5Eset_auto(error_callback, NULL); - - /* make thread scheduling global */ - pthread_attr_init(&attribute); - pthread_attr_setscope(&attribute, PTHREAD_SCOPE_SYSTEM); - - /* create a hdf5 file using H5F_ACC_TRUNC access, - * default file creation plist and default file - * access plist - */ - error_file = H5Fcreate(FILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); - - for (i=0;i<NUM_THREAD;i++) { - pthread_create(&threads[i], &attribute, tts_error_thread, NULL); - } - - for (i=0;i<NUM_THREAD;i++) { - pthread_join(threads[i],NULL); - } - - if (error_flag) { - fprintf(stderr, "Threads reporting different error values!\n"); - } - - if (error_count != NUM_THREAD - 1) { - fprintf(stderr, "Error: %d threads failed instead of %d\n", - error_count, NUM_THREAD-1); - } - - dataset = H5Dopen(error_file, DATASETNAME); - H5Dread(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, &value); - - if (value != WRITE_NUMBER) { - fprintf(stderr, - "Error: Successful thread wrote value %d instead of %d\n", - value, WRITE_NUMBER); - } - - H5Dclose(dataset); - H5Fclose(error_file); - - /* turn our error stack handler off */ - H5Eset_auto(old_error_cb, old_error_client_data); +void tts_error(void) +{ + pthread_t threads[NUM_THREAD]; + pthread_attr_t attribute; + H5E_auto_t old_error_cb; + void *old_error_client_data; + hid_t dataset; + int value, i; + + /* set up mutex for global count of errors */ + pthread_mutex_init(&error_mutex, NULL); + + /* preserve previous error stack handler */ + H5Eget_auto(&old_error_cb, &old_error_client_data); + + /* set our own auto error stack handler */ + H5Eset_auto(error_callback, NULL); + + /* make thread scheduling global */ + pthread_attr_init(&attribute); + pthread_attr_setscope(&attribute, PTHREAD_SCOPE_SYSTEM); + + /* + * Create a hdf5 file using H5F_ACC_TRUNC access, default file + * creation plist and default file access plist + */ + error_file = H5Fcreate(FILENAME, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + + for (i = 0; i < NUM_THREAD; i++) + pthread_create(&threads[i], &attribute, tts_error_thread, NULL); + + for (i = 0; i < NUM_THREAD; i++) + pthread_join(threads[i],NULL); + + if (error_flag) { + fprintf(stderr, "Threads reporting different error values!\n"); + num_errs++; + } + + if (error_count != NUM_THREAD - 1) { + fprintf(stderr, "Error: %d threads failed instead of %d\n", + error_count, NUM_THREAD-1); + num_errs++; + } + + dataset = H5Dopen(error_file, DATASETNAME); + H5Dread(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, &value); + + if (value != WRITE_NUMBER) { + fprintf(stderr, + "Error: Successful thread wrote value %d instead of %d\n", + value, WRITE_NUMBER); + num_errs++; + } + + H5Dclose(dataset); + H5Fclose(error_file); + + /* turn our error stack handler off */ + H5Eset_auto(old_error_cb, old_error_client_data); } -void *tts_error_thread(void *arg) { - - hid_t dataspace, datatype, dataset; - hsize_t dimsf[1]; /* dataset dimensions */ - int value; - - /* define dataspace for dataset - */ - dimsf[0] = 1; - dataspace = H5Screate_simple(1,dimsf,NULL); - - /* define datatype for the data using native little endian integers - */ - datatype = H5Tcopy(H5T_NATIVE_INT); - H5Tset_order(datatype, H5T_ORDER_LE); - - /* create a new dataset within the file - */ - dataset = H5Dcreate(error_file, DATASETNAME, datatype, dataspace, - H5P_DEFAULT); - if (dataset >= 0) { /* not an error */ - value = WRITE_NUMBER; - H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, &value); - - H5Dclose(dataset); - } - H5Tclose(datatype); - H5Sclose(dataspace); - return (NULL); +void *tts_error_thread(void *arg) +{ + hid_t dataspace, datatype, dataset; + hsize_t dimsf[1]; /* dataset dimensions */ + int value; + + /* define dataspace for dataset */ + dimsf[0] = 1; + dataspace = H5Screate_simple(1,dimsf,NULL); + + /* define datatype for the data using native little endian integers */ + datatype = H5Tcopy(H5T_NATIVE_INT); + H5Tset_order(datatype, H5T_ORDER_LE); + + /* create a new dataset within the file */ + dataset = H5Dcreate(error_file, DATASETNAME, datatype, dataspace, + H5P_DEFAULT); + if (dataset >= 0) { /* not an error */ + value = WRITE_NUMBER; + H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, + H5P_DEFAULT, &value); + H5Dclose(dataset); + } + + H5Tclose(datatype); + H5Sclose(dataspace); + return (NULL); } -void cleanup_error() { +herr_t error_callback(void *client_data) +{ + pthread_mutex_lock(&error_mutex); + error_count++; + pthread_mutex_unlock(&error_mutex); + return H5Ewalk(H5E_WALK_DOWNWARD, walk_error_callback, NULL); } -herr_t error_callback(void *client_data) { - pthread_mutex_lock(&error_mutex); - error_count++; - pthread_mutex_unlock(&error_mutex); - return (H5Ewalk(H5E_WALK_DOWNWARD, walk_error_callback, NULL)); -} +herr_t walk_error_callback(int n, H5E_error_t *err_desc, void *client_data) +{ + int maj_num, min_num; + + if (err_desc) { + maj_num = err_desc->maj_num; + min_num = err_desc->min_num; -herr_t walk_error_callback(int n, H5E_error_t *err_desc, - void *client_data) { - int maj_num, min_num; - - if (err_desc) { - maj_num = err_desc->maj_num; - min_num = err_desc->min_num; - - if (n < EXPECTED_ERROR_DEPTH) { - if (maj_num == expected[n].maj_num && - min_num == expected[n].min_num) { + if (n < EXPECTED_ERROR_DEPTH && maj_num == expected[n].maj_num && + min_num == expected[n].min_num) + return SUCCEED; + } + + error_flag = -1; return SUCCEED; - } - } - } - error_flag = -1; - return SUCCEED; +} + +void cleanup_error(void) +{ + HDunlink(FILENAME); } #endif /*H5_HAVE_THREADSAFE*/ |