From 43fa57565f0579e6c4fcca40b9a50c5af58fd1af Mon Sep 17 00:00:00 2001 From: Albert Cheng Date: Thu, 25 Nov 2010 19:56:17 -0500 Subject: [svn-r19848] Bug 1917: big test failed especially in Widows. big.c: Changed the test to run Huge Dataset (tens of GB), Xtra large dataset(4GB big), Large dataset (2GB big), or merely 1GB big, depending on if the file system supports sparse file or if it supports larger than 32bigs I/O. H5FDstdio.c: Removed an incorrect condition that whether STDIO VFD supports larger than 32bits I/O depends on the support of fseeko. Windows does not use that. Instead, it uses _fseeki64 to support larger than 32bits I/O. Tested: h5committest, jam (serial). --- src/H5FDstdio.c | 20 --- test/big.c | 408 ++++++++++++++++++++++++++++++++++++++------------------ 2 files changed, 277 insertions(+), 151 deletions(-) diff --git a/src/H5FDstdio.c b/src/H5FDstdio.c index 20fa31f..9bc4161 100644 --- a/src/H5FDstdio.c +++ b/src/H5FDstdio.c @@ -130,14 +130,8 @@ typedef struct H5FD_stdio_t { /* Use file_xxx to indicate these are local macros, avoiding confusing * with the global HD_xxx macros. - * Need fseeko, off_t, ftell and ftruncate are all of the same 32 or 64 - * versions. * Assume fseeko, which is POSIX standard, is always supported; * but prefer to use fseeko64 if supported. - * [Note: the ifndef H5_HAVE_FSEEKO condition to determine BIG FILE not - * supported was old code. This condition is not supposed to be true in Unix - * like systems but may happen in non-Unix systems like Windows. They are left - * in for now and will be cleaned later. -AKC-] */ #ifndef file_fseek #ifdef H5_HAVE_FSEEKO64 @@ -175,11 +169,6 @@ typedef struct H5FD_stdio_t { #define REGION_OVERFLOW(A,Z) (ADDR_OVERFLOW(A) || SIZE_OVERFLOW(Z) || \ HADDR_UNDEF==(A)+(Z) || (file_offset_t)((A)+(Z))<(file_offset_t)(A)) -#ifndef H5_HAVE_FSEEKO -/* Define big file as 2GB */ -#define BIG_FILE 0x80000000UL -#endif - /* Prototypes */ static H5FD_t *H5FD_stdio_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr); @@ -587,9 +576,6 @@ H5FD_stdio_alloc(H5FD_t *_file, H5FD_mem_t /*UNUSED*/ type, hid_t /*UNUSED*/ dxp { H5FD_stdio_t *file = (H5FD_stdio_t*)_file; haddr_t addr; -#ifndef H5_HAVE_FSEEKO - static const char *func = "H5FD_stdio_alloc"; /* Function Name for error reporting */ -#endif haddr_t ret_value; /* Return value */ /* Shut compiler up */ @@ -609,12 +595,6 @@ H5FD_stdio_alloc(H5FD_t *_file, H5FD_mem_t /*UNUSED*/ type, hid_t /*UNUSED*/ dxp addr = ((addr / file->pub.alignment) + 1) * file->pub.alignment; } /* end if */ -#ifndef H5_HAVE_FSEEKO - /* If fseeko isn't available, big files (>2GB) won't be supported. */ - if((addr + size) > BIG_FILE) - H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_SEEKERROR, "can't write file bigger than 2GB because fseeko isn't available", HADDR_UNDEF) -#endif - file->eoa = addr + size; /* Set return value */ diff --git a/test/big.c b/test/big.c index 8d65559..24b2d25 100644 --- a/test/big.c +++ b/test/big.c @@ -16,16 +16,45 @@ /* * Programmer: Robb Matzke * Wednesday, April 8, 1998 + * Modified: Albert Cheng + * September 11, 2010 + */ +/* + * The purpose of this test is to verify if a virtual file driver can handle: + * a. Large file (2GB) + * This should exceed 32bits I/O system since offset is a signed + * integral type (in order to support negative offset with respect to + * end of file). + * b. Extra Large file (4GB) + * This definite exceeds 32bit I/O and file systems. + * c. Huge file (tens of GB) + * This verifies the HDF5 library handles big logical file size + * correctly. + * In practice, if a VFD can handle a big file size, there is no need to + * test the smaller file sizes. E.g., If it can handle the Huge file, + * there is no need to test the Extra large or Large files. Therefore the + * test starts with larger size files and continues to test the smaller size + * files only if the large sige file tests have failed. + * + * Another consideration is that even if a VFD is capable to handle a + * huge file but it is likely to take a long time to write every byte + * of a huge file. E.g., a simple workstation may have disks of write + * speed of 10MB/sec. A huge file of 30GB will take about an hour to + * write it. Therefore, this test will run the huge file test only if the + * underlying file system supports sparse file. (A Sparse file here means + * that disk space is allocated only when the contents are actually written. + * E.g., If one creates a new file, seeks forward 10 million bytes, writes + * 1 bytes and closes the file, then a sparse file, will show file size of + * 10 million bytes but actaully uses only couple disk blocks, much smaller + * than the formal file size.) + * + * One more consideration is that we want to distinguish an HDF5 library + * failure from some system limits such as current free disk space or user + * disk space quota. Therefore, the test will first attempt to verify no + * such limits exist before running the actual VFD tests. */ #include "h5test.h" -const char *FILENAME[] = { - "big", - "sec2", - "stdio", - NULL -}; - #define DNAME "big.data" #define WRT_N 50 @@ -42,8 +71,29 @@ const char *FILENAME[] = { # define GB8LL 0 /*cannot do the test*/ #endif +/* Define Small, Large, Extra Large, Huge File which + * corrspond to less than 2GB, 2GB, 4GB, and tens of GB file size. + * NOFILE stands for "no file" to be tested. + */ +typedef enum fsizes_t { SFILE, LFILE, XLFILE, HUGEFILE, NOFILE} fsizes_t; +/* Lists of vfd to test */ +typedef enum vfd_t { SEC2_VFD, STDIO_VFD, FAMILY_VFD } vfd_t; +fsizes_t file_size= NOFILE; + +const char *FILENAME[] = { + "big", + "sec2", + "stdio", + NULL +}; +int cflag=1; /* check file system before test */ +int sparse_support=0; /* sparse file supported, default false */ +int have_space=0; /* enough space for huge file test, default false */ +hsize_t family_size_def=FAMILY_SIZE; /* default family file size */ + /* Protocols */ static void usage(void); +int testvfd(vfd_t vfd); /* Array used to record all addresses at which data has been written */ /* so far. Used to prevent overlapping writes. */ @@ -129,7 +179,7 @@ is_sparse(void) if (5!=HDwrite(fd, "hello", (size_t)5)) return 0; if (HDclose(fd) < 0) return 0; if (HDstat("x.h5", &sb) < 0) return 0; - if (HDunlink("x.h5") < 0) return 0; + if (HDremove("x.h5") < 0) return 0; #ifdef H5_HAVE_STAT_ST_BLOCKS return ((unsigned long)sb.st_blocks*512 < (unsigned long)sb.st_size); #else @@ -156,25 +206,67 @@ is_sparse(void) * *------------------------------------------------------------------------- */ -static int -supports_big(void) +static fsizes_t +supports_big(vfd_t vfd) { - int fd; + int fd = -1; + fsizes_t fsize = NOFILE; + + switch (vfd){ + case FAMILY_VFD: + case SEC2_VFD: + case STDIO_VFD: + if ((fd=HDopen("y.h5", O_RDWR|O_TRUNC|O_CREAT, 0666)) < 0) + goto error; - if ((fd=HDopen("y.h5", O_RDWR|O_TRUNC|O_CREAT, 0666)) < 0) return 0; + /* Write a few byte at the beginning */ + if (5!=HDwrite(fd, "hello", (size_t)5)) + goto quit; + fsize = SFILE; - /* Write a few bytes at 2GB */ - if (HDlseek(fd, 2*GB, SEEK_SET)!=2*GB) return 0; - if (5!=HDwrite(fd, "hello", (size_t)5)) return 0; + /* Write a few bytes at 2GB */ + if (HDlseek(fd, 2*GB, SEEK_SET)!=2*GB) + goto quit; + if (5!=HDwrite(fd, "hello", (size_t)5)) + goto quit; + fsize = LFILE; - /* Write a few bytes at 4GB */ - if (HDlseek(fd, 4*GB, SEEK_SET) != 4*GB) return 0; - if (5!=HDwrite(fd, "hello", (size_t)5)) return 0; + /* Write a few bytes at 4GB */ + if (HDlseek(fd, 4*GB, SEEK_SET) != 4*GB) + goto quit; + if (5!=HDwrite(fd, "hello", (size_t)5)) + goto quit; + fsize = XLFILE; - if (HDclose(fd) < 0) return 0; - if (HDremove("y.h5") < 0) return 0; + /* If this supports sparse_file, write a few bytes at 32GB */ + if (!sparse_support) + goto quit; + if (HDlseek(fd, 32*GB, SEEK_SET) != 32*GB) + goto quit; + if (5!=HDwrite(fd, "hello", (size_t)5)) + goto quit; + fsize = HUGEFILE; - return (1); + break; + default: + /* unknown or unsupported VFD */ + goto error; + break; + } + +quit: + if (HDclose(fd) < 0) + goto error; + if (HDremove("y.h5") < 0) + goto error; + return(fsize); + +error: + if (fd >= 0){ + HDclose(fd); + HDremove("y.h5"); + } + return (fsize); } @@ -231,7 +323,7 @@ enough_room(hid_t fapl) HDsnprintf(name, sizeof name, filename, i); if(HDclose(fd[i]) < 0) ret_value=0; - HDunlink(name); + HDremove(name); } return ret_value; @@ -257,7 +349,7 @@ enough_room(hid_t fapl) *------------------------------------------------------------------------- */ static int -writer (char* filename, hid_t fapl, int wrt_n) +writer (char* filename, hid_t fapl, fsizes_t testsize, int wrt_n) { hsize_t size1[4] = {8, 1024, 1024, 1024}; hsize_t size2[1] = {GB8LL}; @@ -269,7 +361,39 @@ writer (char* filename, hid_t fapl, int wrt_n) FILE *out = fopen(DNAME, "w"); hid_t dcpl; - TESTING("large dataset write"); + switch(testsize){ + case LFILE: + TESTING("Large dataset write(2GB)"); + /* reduce size1 to produce a 2GB dataset */ + size1[1] = 1024/16; + size2[0] /= 16; + break; + + case XLFILE: + TESTING("Extra large dataset write(4GB)"); + /* reduce size1 to produce a 4GB dataset */ + size1[1] = 1024/8; + size2[0] /= 8; + break; + + case HUGEFILE: + TESTING("Huge dataset write"); + /* Leave size1 as 32GB */ + break; + + case SFILE: + TESTING("small dataset write(1GB)"); + /* reduce size1 to produce a 1GB dataset */ + size1[1] = 1024/32; + size2[0] /= 32; + break; + + case NOFILE: + /* what to do?? */ + HDfprintf(stdout, "Unexpected file size of NOFILE\n"); + goto error; + break; + } /* * We might be on a machine that has 32-bit files, so create an HDF5 file @@ -475,6 +599,124 @@ usage(void) +/* Flush stdout at the end of this test routine to ensure later output to */ +/* stderr will not come out before it.*/ +int testvfd(vfd_t vfd) +{ + hid_t fapl=-1; + hsize_t family_size; + char filename[1024]; + fsizes_t testsize; + + + switch(vfd){ + case FAMILY_VFD: + /* Test huge file with the family driver */ + puts("Testing big file with the Family Driver "); + if ((fapl=H5Pcreate(H5P_FILE_ACCESS)) < 0) + goto error; + + if (H5Pset_fapl_family(fapl, family_size_def, H5P_DEFAULT) < 0) + goto error; + + if (cflag){ + /* + * We shouldn't run this test if the file system doesn't support holes + * because we would generate multi-gigabyte files. + */ + puts("Checking if file system is adequate for this test..."); + if (sizeof(long long)<8 || 0==GB8LL) { + puts("Test skipped because sizeof(long long) is too small. This"); + puts("hardware apparently doesn't support 64-bit integer types."); + usage(); + goto quit; + } + if (!sparse_support) { + puts("Test skipped because file system does not support holes."); + usage(); + goto quit; + } + if (!enough_room(fapl)) { + puts("Test skipped because of quota (file size or num open files)."); + usage(); + goto quit; + } + } + + /* Do the test with the Family Driver */ + h5_fixname(FILENAME[0], fapl, filename, sizeof filename); + + if (writer(filename, fapl, HUGEFILE, WRT_N)) goto error; + if (reader(filename, fapl)) goto error; + + puts("Test passed with the Family Driver."); + break; + + case SEC2_VFD: + testsize = supports_big(SEC2_VFD); + if (testsize == NOFILE) { + HDfprintf(stdout, "Test for sec2 is skipped because file system does not support big files.\n"); + goto quit; + } + /* Test big file with the SEC2 driver */ + puts("Testing big file with the SEC2 Driver "); + + if ((fapl=H5Pcreate(H5P_FILE_ACCESS)) < 0) + goto error; + if(H5Pset_fapl_sec2(fapl) < 0) + goto error; + + h5_fixname(FILENAME[1], fapl, filename, sizeof filename); + + if (writer(filename, fapl, testsize, WRT_N)) goto error; + if (reader(filename, fapl)) goto error; + + puts("Test passed with the SEC2 Driver."); + break; + + case STDIO_VFD: + testsize = supports_big(STDIO_VFD); + if (testsize == NOFILE) { + HDfprintf(stdout, "Test for stdio is skipped because file system does not support big files.\n"); + goto quit; + } + puts("\nTesting big file with the STDIO Driver "); + + if ((fapl=H5Pcreate(H5P_FILE_ACCESS)) < 0) + goto error; + if(H5Pset_fapl_stdio(fapl) < 0) + goto error; + + h5_fixname(FILENAME[2], fapl, filename, sizeof filename); + + if (writer(filename, fapl, testsize, WRT_N)) goto error; + if (reader(filename, fapl)) goto error; + puts("Test passed with the STDIO Driver."); + break; + + default: + puts("Unsupprted VFD"); + usage(); + goto error;; + } /* end of switch (vfd) */ + +quit: + /* End with normal return code */ + /* Clean up the test file */ + if (h5_cleanup(FILENAME, fapl)) HDremove(DNAME); + fflush(stdout); + return 0; + + +error: + if (fapl>=0) H5Pclose(fapl); + puts("*** TEST FAILED ***"); + fflush(stdout); + return 1; +} + + + /*------------------------------------------------------------------------- * Function: main * @@ -501,15 +743,9 @@ usage(void) int main (int ac, char **av) { - hid_t fapl=-1; - hsize_t family_size; - hsize_t family_size_def; /* default family file size */ unsigned long seed = 0; /* Random # seed */ - int cflag=1; /* check file system before test */ - char filename[1024]; /* parameters setup */ - family_size_def = FAMILY_SIZE; while (--ac > 0){ av++; @@ -538,6 +774,11 @@ main (int ac, char **av) } } + /* check sparse file support unless cflag is not set. */ + if (cflag) + sparse_support = is_sparse(); + + /* Choose random # seed */ seed = (unsigned long)HDtime(NULL); #ifdef QAK @@ -546,113 +787,18 @@ HDfprintf(stderr, "Random # seed was: %lu\n", seed); #endif /* QAK */ HDsrandom(seed); - /* Reset library */ - h5_reset(); - fapl = h5_fileaccess(); - - /* Test big file with the family driver */ - puts("Testing big file with the Family Driver "); - if (H5FD_FAMILY!=H5Pget_driver(fapl)) { - HDfprintf(stdout, - "Changing file drivers to the family driver, %Hu bytes each\n", - family_size_def); - if (H5Pset_fapl_family(fapl, family_size_def, H5P_DEFAULT) < 0) goto error; - } else if (H5Pget_fapl_family(fapl, &family_size, NULL) < 0) { +/*=================================================*/ + if (testvfd(FAMILY_VFD) != 0) + goto error; + if (testvfd(SEC2_VFD) != 0) + goto error; + if (testvfd(STDIO_VFD) != 0) goto error; - } else if (family_size!=family_size_def) { - HDfprintf(stdout, "Changing family member size from %Hu to %Hu\n", - family_size, family_size_def); - if (H5Pset_fapl_family(fapl, family_size_def, H5P_DEFAULT) < 0) - goto error; - } - - if (cflag){ - /* - * We shouldn't run this test if the file system doesn't support holes - * because we would generate multi-gigabyte files. - */ - puts("Checking if file system is adequate for this test..."); - if (sizeof(long long)<8 || 0==GB8LL) { - puts("Test skipped because sizeof(long long) is too small. This"); - puts("hardware apparently doesn't support 64-bit integer types."); - usage(); - goto quit; - } - if (!is_sparse()) { - puts("Test skipped because file system does not support holes."); - usage(); - goto quit; - } - if (!enough_room(fapl)) { - puts("Test skipped because of quota (file size or num open files)."); - usage(); - goto quit; - } - } - - /* Do the test with the Family Driver */ - h5_fixname(FILENAME[0], fapl, filename, sizeof filename); - - if (writer(filename, fapl, WRT_N)) goto error; - if (reader(filename, fapl)) goto error; - - puts("Test passed with the Family Driver."); - - /* - * We shouldn't run this test if the file system doesn't support big files - * because we would generate multi-gigabyte files. - */ - puts("\nChecking if file system supports big files..."); - if (!supports_big()) { - puts("Tests for sec2 and stdio are skipped because file system does not support big files."); - usage(); - goto quit; - } - - /* Clean up the test file */ - if (h5_cleanup(FILENAME, fapl)) remove(DNAME); - - /* Test big file with the SEC2 driver */ - puts("Testing big file with the SEC2 Driver "); - - fapl = h5_fileaccess(); - if(H5Pset_fapl_sec2(fapl) < 0) - - HDmemset(filename, 0, sizeof(filename)); - h5_fixname(FILENAME[1], fapl, filename, sizeof filename); - - if (writer(filename, fapl, WRT_N)) goto error; - if (reader(filename, fapl)) goto error; - - puts("Test passed with the SEC2 Driver."); - -#ifdef H5_HAVE_FSEEKO - /* Clean up the test file */ - if (h5_cleanup(FILENAME, fapl)) remove(DNAME); - - /* Test big file with the STDIO driver only if fseeko is supported, - * because the OFFSET parameter of fseek has the type LONG, not big - * enough to support big files. */ - puts("\nTesting big file with the STDIO Driver "); - - fapl = h5_fileaccess(); - if(H5Pset_fapl_stdio(fapl) < 0) - - HDmemset(filename, 0, sizeof(filename)); - h5_fixname(FILENAME[2], fapl, filename, sizeof filename); - - if (writer(filename, fapl, WRT_N)) goto error; - if (reader(filename, fapl)) goto error; - puts("Test passed with the STDIO Driver."); -#endif -quit: /* End with normal exit code */ - if (h5_cleanup(FILENAME, fapl)) remove(DNAME); return 0; error: - if (fapl>=0) H5Pclose(fapl); puts("*** TEST FAILED ***"); return 1; } -- cgit v0.12