[svn-r2287] Changed ttsafe_* test files so that they create their own HDF5 file (they

were only creating one for all of them). Also changed so that, if they
got an error, it actually specifies that the tests failed on the screen
instead of succeeded ;-)
This commit is contained in:
Bill Wendling 2000-05-19 18:00:03 -05:00
parent b97c63cdbc
commit 35fe1e2847
5 changed files with 749 additions and 711 deletions

View File

@ -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,19 +44,6 @@ static char RcsId[] = "@(#)$Revision$";
#include <stdarg.h>
#define MAXNUMOFTESTS 50
#define HDF5_TEST_MASTER
#define MAX_NUM_NAME 1000
#define NAME_OFFSET 6 /* offset for "name<num>" */
/* Internal Variables */
static int Index = 0;
/* Global variables */
int num_errs = 0;
int Verbosity;
#include <ttsafe.h>
#ifndef H5_HAVE_THREADSAFE
@ -67,268 +53,299 @@ int main(void)
return 0;
}
#else
#define MAXNUMOFTESTS 50
#define HDF5_TEST_MASTER
#define MAX_NUM_NAME 1000
#define NAME_OFFSET 6 /* offset for "name<num>" */
/* Internal Variables */
static int Index = 0;
/* Global variables */
int num_errs = 0;
int Verbosity;
/* 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;
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() */
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;
int num_digits(int num)
{
int i;
if (num == 0)
return 1;
while (num > 0) {
num = num/10;
i++;
}
return 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);
/*
* 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");
/* 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);
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;
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);
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;
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], "-nocache") == 0) ||
(HDstrcmp(argv[CLLoop], "-n") == 0))) {
Cache = 0;
printf ("Cache = %d\n", Cache);
}
if (argc > CLLoop &&
(HDstrcmp(argv[CLLoop], "-summary") == 0 ||
HDstrcmp(argv[CLLoop], "-s") == 0))
Summary = 1;
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 */
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 */
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");
MESSAGE(2, ("\n\n"))
if (Summary) {
print_func("Summary of Test Results:\n");
print_func("Name of Test Errors Description of Test\n");
print_func("---------------- ------ --------------------------------------\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");
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"));
if (Summary) {
print_func("Summary of Test Results:\n");
print_func("Name of Test Errors Description of Test\n");
print_func("---------------- ------ --------------------------------------\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].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*/

View File

@ -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) {
void tts_acreate(void)
{
/* Pthread declarations */
pthread_t threads[NUM_THREADS];
/* Pthread definitions
*/
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 */
/* HDF5 data definitions
*/
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;
int data; /* data to write */
int buffer, ret;
ttsafe_name_data_t *attrib_data;
int 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 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);
/* 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);
/* 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);
/* 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);
/* 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);
}
/* simultaneously create a large number of attributes to be
associated with the dataset
*/
for (i = 0; i < NUM_THREADS; i++)
pthread_join(threads[i], NULL);
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);
}
/* verify the correctness of the test */
for (i = 0; i < NUM_THREADS; i++) {
attribute = H5Aopen_name(dataset,gen_name(i));
for (i=0;i<NUM_THREADS;i++) {
pthread_join(threads[i],NULL);
}
if (attribute < 0) {
fprintf(stderr,
"unable to open appropriate attribute. "
"Test failed!\n");
num_errs++;
} else {
ret = H5Aread(attribute, H5T_NATIVE_INT, &buffer);
/* 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);
}
}
if (ret < 0 || buffer != i) {
fprintf(stderr,
"wrong data values. Test failed!\n");
num_errs++;
}
/* close remaining resources
*/
H5Sclose(dataspace);
H5Tclose(datatype);
H5Dclose(dataset);
H5Fclose(file);
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*/

View File

@ -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) {
void tts_cancel(void)
{
pthread_attr_t attribute;
hid_t dataset;
int buffer;
pthread_attr_t attribute;
hid_t dataset;
/* make thread scheduling global */
pthread_attr_init(&attribute);
pthread_attr_setscope(&attribute, PTHREAD_SCOPE_SYSTEM);
int buffer;
/*
* 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);
/* make thread scheduling global */
pthread_attr_init(&attribute);
pthread_attr_setscope(&attribute, PTHREAD_SCOPE_SYSTEM);
dataset = H5Dopen(cancel_file, DATASETNAME);
H5Dread(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT,
&buffer);
/* 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);
if (buffer != 11) {
fprintf(stderr,
"operation unsuccessful with value at %d instead of 11\n",
buffer);
num_errs++;
}
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);
H5Dclose(dataset);
H5Fclose(cancel_file);
}
void *tts_cancel_thread(void *arg) {
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;
int datavalue;
int *buffer;
hid_t dataspace, datatype, dataset;
hsize_t dimsf[1]; /* dataset dimensions */
/* define dataspace for dataset */
dimsf[0] = 1;
dataspace = H5Screate_simple(1,dimsf,NULL);
cancel_cleanup_t *cleanup_structure;
/* define datatype for the data using native little endian integers */
datatype = H5Tcopy(H5T_NATIVE_INT);
H5Tset_order(datatype, H5T_ORDER_LE);
/* define dataspace for dataset
*/
dimsf[0] = 1;
dataspace = H5Screate_simple(1,dimsf,NULL);
/* create a new dataset within the file */
dataset = H5Dcreate(cancel_file, DATASETNAME, datatype, dataspace,
H5P_DEFAULT);
/* define datatype for the data using native little endian integers
*/
datatype = H5Tcopy(H5T_NATIVE_INT);
H5Tset_order(datatype, H5T_ORDER_LE);
/* 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);
/* create a new dataset within the file
*/
dataset = H5Dcreate(cancel_file, DATASETNAME, datatype, dataspace,
H5P_DEFAULT);
datavalue = 1;
H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT,
&datavalue);
/* 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);
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);
datavalue = 1;
H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT,
&datavalue);
sleep(3);
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);
datavalue = 100;
H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT,
&datavalue);
H5Dclose(dataset);
H5Tclose(datatype);
H5Sclose(dataspace);
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);
/*
* 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;
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);
}
tts_cancel_barrier();
sleep(3);
value += 10;
H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT,
&value);
if (value != 1) {
fprintf(stderr, "Error! Element value should be 1 and not %d\n",
value);
num_errs++;
return -1;
}
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"); */
value += 10;
H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT,
&value);
return 0;
}
/*
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);
* 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"); */
}
void cleanup_cancel() {
H5close();
/*
* 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(void)
{
H5close();
HDunlink(FILENAME);
}
#endif /*H5_HAVE_THREADSAFE*/

View File

@ -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) {
void tts_dcreate(void)
{
/* Pthread definitions */
pthread_t threads[NUM_THREAD];
/* 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;
/* HDF5 data definitions
*/
hid_t file, dataset, datatype;
/* set pthread attribute to perform global scheduling */
pthread_attr_init(&attribute);
pthread_attr_setscope(&attribute, PTHREAD_SCOPE_SYSTEM);
int datavalue;
int i;
/*
* Set individual dataset names (rather than generated the names
* automatically)
*/
typedef struct thread_info {
int id;
hid_t file;
char *dsetname;
} thread_info;
for (i = 0; i < NUM_THREAD; i++)
dsetname[i] = malloc(sizeof(char) * DATASETNAME_LENGTH);
thread_info *thread_out;
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";
char *dsetname[NUM_THREAD];
pthread_attr_t attribute;
/*
* 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);
/* set pthread attribute to perform global scheduling */
pthread_attr_init(&attribute);
pthread_attr_setscope(&attribute, PTHREAD_SCOPE_SYSTEM);
/* 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);
}
/* set individual dataset names (rather than generated the names
automatically)
*/
for (i = 0;i < NUM_THREAD; i++)
pthread_join(threads[i], NULL);
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";
/* compare data to see if it is written correctly */
/* 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);
/* define datatype for the data using native little endian integers */
datatype = H5Tcopy(H5T_NATIVE_INT);
/* 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++) {
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);
for (i=0;i<NUM_THREAD;i++) {
pthread_join(threads[i],NULL);
}
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;
}
/* compare data to see if it is written correctly
*/
H5Dclose(dataset);
}
}
/* 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);
/* close remaining resources */
H5Fclose(file);
return;
}
H5Dclose(dataset);
}
}
/* close remaining resources
*/
H5Fclose(file);
}
void *tts_dcreate_creator(void *thread_data) {
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;
hid_t dataspace, datatype, dataset;
hsize_t dimsf[1]; /* dataset dimensions */
thread_in.dsetname = malloc(sizeof(char) * DATASETNAME_LENGTH);
thread_in = *((struct thread_info *)thread_data);
struct thread_info {
int id;
hid_t file;
char *dsetname;
} thread_in;
/* define dataspace for dataset */
dimsf[0] = 1;
dataspace = H5Screate_simple(1,dimsf,NULL);
thread_in.dsetname = (char *)malloc(sizeof(char)*DATASETNAME_LENGTH);
thread_in = *((struct thread_info *)thread_data);
/* define datatype for the data using native little endian integers */
datatype = H5Tcopy(H5T_NATIVE_INT);
H5Tset_order(datatype, H5T_ORDER_LE);
/* define dataspace for dataset
*/
dimsf[0] = 1;
dataspace = H5Screate_simple(1,dimsf,NULL);
/* create a new dataset within the file */
dataset = H5Dcreate(thread_in.file, thread_in.dsetname,
datatype, dataspace, H5P_DEFAULT);
/* define datatype for the data using native little endian integers
*/
datatype = H5Tcopy(H5T_NATIVE_INT);
H5Tset_order(datatype, H5T_ORDER_LE);
/* initialize data for dataset and write value to dataset */
H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL,
H5P_DEFAULT, &thread_in.id);
/* 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;
/* 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*/

View File

@ -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) {
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;
int i;
/* set up mutex for global count of errors */
pthread_mutex_init(&error_mutex, NULL);
pthread_t threads[NUM_THREAD];
pthread_attr_t attribute;
/* preserve previous error stack handler */
H5Eget_auto(&old_error_cb, &old_error_client_data);
hid_t dataset;
int value;
/* set our own auto error stack handler */
H5Eset_auto(error_callback, NULL);
H5E_auto_t old_error_cb;
void *old_error_client_data;
/* make thread scheduling global */
pthread_attr_init(&attribute);
pthread_attr_setscope(&attribute, PTHREAD_SCOPE_SYSTEM);
/* set up mutex for global count of errors */
pthread_mutex_init(&error_mutex, NULL);
/*
* 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);
/* preserve previous error stack handler */
H5Eget_auto(&old_error_cb, &old_error_client_data);
for (i = 0; i < NUM_THREAD; i++)
pthread_create(&threads[i], &attribute, tts_error_thread, NULL);
/* set our own auto error stack handler */
H5Eset_auto(error_callback, NULL);
for (i = 0; i < NUM_THREAD; i++)
pthread_join(threads[i],NULL);
/* make thread scheduling global */
pthread_attr_init(&attribute);
pthread_attr_setscope(&attribute, PTHREAD_SCOPE_SYSTEM);
if (error_flag) {
fprintf(stderr, "Threads reporting different error values!\n");
num_errs++;
}
/* 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);
if (error_count != NUM_THREAD - 1) {
fprintf(stderr, "Error: %d threads failed instead of %d\n",
error_count, NUM_THREAD-1);
num_errs++;
}
for (i=0;i<NUM_THREAD;i++) {
pthread_create(&threads[i], &attribute, tts_error_thread, NULL);
}
dataset = H5Dopen(error_file, DATASETNAME);
H5Dread(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, &value);
for (i=0;i<NUM_THREAD;i++) {
pthread_join(threads[i],NULL);
}
if (value != WRITE_NUMBER) {
fprintf(stderr,
"Error: Successful thread wrote value %d instead of %d\n",
value, WRITE_NUMBER);
num_errs++;
}
if (error_flag) {
fprintf(stderr, "Threads reporting different error values!\n");
}
H5Dclose(dataset);
H5Fclose(error_file);
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);
/* turn our error stack handler off */
H5Eset_auto(old_error_cb, old_error_client_data);
}
void *tts_error_thread(void *arg) {
void *tts_error_thread(void *arg)
{
hid_t dataspace, datatype, dataset;
hsize_t dimsf[1]; /* dataset dimensions */
int value;
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 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);
/* 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);
}
/* 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);
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;
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 (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*/