diff options
-rw-r--r-- | MANIFEST | 3 | ||||
-rw-r--r-- | acconfig.h | 4 | ||||
-rw-r--r-- | config/linux | 4 | ||||
-rw-r--r-- | configure.in | 6 | ||||
-rw-r--r-- | src/H5Distore.c | 109 | ||||
-rw-r--r-- | src/H5E.c | 1 | ||||
-rw-r--r-- | src/H5Epublic.h | 1 | ||||
-rw-r--r-- | src/H5F.c | 138 | ||||
-rw-r--r-- | src/H5Fistore.c | 109 | ||||
-rw-r--r-- | src/H5Flow.c | 234 | ||||
-rw-r--r-- | src/H5Fprivate.h | 311 | ||||
-rw-r--r-- | src/H5Fsec2.c | 314 | ||||
-rw-r--r-- | src/H5Fstdio.c | 341 | ||||
-rw-r--r-- | src/H5H.c | 30 | ||||
-rw-r--r-- | src/H5Hprivate.h | 1 | ||||
-rw-r--r-- | src/H5config.h.in | 4 | ||||
-rw-r--r-- | src/H5private.h | 12 | ||||
-rw-r--r-- | src/Makefile.in | 7 | ||||
-rw-r--r-- | test/istore.c | 228 |
19 files changed, 1433 insertions, 424 deletions
@@ -49,6 +49,9 @@ ./src/H5Epublic.h ./src/H5F.c ./src/H5Fistore.c +./src/H5Flow.c +./src/H5Fsec2.c +./src/H5Fstdio.c ./src/H5Fprivate.h ./src/H5Fpublic.h ./src/H5G.c @@ -1,5 +1,5 @@ /* Define if the __attribute__(()) extension is present */ -/* #define HAVE_ATTRIBUTE */ +#undef HAVE_ATTRIBUTE /* Define if the compiler understands the __FUNCTION__ keyword. */ -/* #define HAVE_FUNCTION */ +#undef HAVE_FUNCTION diff --git a/config/linux b/config/linux index ec59f3f..53d8bf4 100644 --- a/config/linux +++ b/config/linux @@ -2,9 +2,9 @@ CFLAGS_WARN="-Wall -Wshadow -Wpointer-arith -Wcast-qual -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wnested-externs" -CFLAGS_DEBUG="-g -DH5AC_DEBUG_PROTECT -DFILELIB=1 -fverbose-asm" +CFLAGS_DEBUG="-g -DH5AC_DEBUG_PROTECT -DH5F_LOW_DFLT=H5F_LOW_STDIO -DH5F_OPT_SEEK -fverbose-asm" CFLAGS_PROFILE="-pg" -CFLAGS_PRODUCTION="-O3 -UH5AC_DEBUG_PROTECT -DNDEBUG -finline-functions -funroll-loops -malign-double -fomit-frame-pointer" +CFLAGS_PRODUCTION="-O3 -UH5AC_DEBUG_PROTECT -DNDEBUG -DH5F_LOW_DFLT=H5F_LOW_STDIO -DH5F_OPT_SEEK -finline-functions -funroll-loops -malign-double -fomit-frame-pointer" if test "x$CFLAGS" = "x"; then diff --git a/configure.in b/configure.in index 9e7cc44..8680e93 100644 --- a/configure.in +++ b/configure.in @@ -113,12 +113,14 @@ AC_C_INLINE AC_MSG_CHECKING(for __attribute__ extension) AC_TRY_COMPILE(,[int __attribute__((unused)) f(void){return 1;}], - AC_DEFINE(HAVE_ATTRIBUTE) AC_MSG_RESULT(yes), + AC_DEFINE(HAVE_ATTRIBUTE) + AC_MSG_RESULT(yes), AC_MSG_RESULT(no)) AC_MSG_CHECKING(for __FUNCTION__ extension) AC_TRY_COMPILE(,[int f(void){return __FUNCTION__;}], - AC_DEFINE(HAVE_FUNCTION) AC_MSG_RESULT(yes), + AC_DEFINE(HAVE_FUNCTION) + AC_MSG_RESULT(yes), AC_MSG_RESULT(no)) diff --git a/src/H5Distore.c b/src/H5Distore.c index b52288c..96ef5fc 100644 --- a/src/H5Distore.c +++ b/src/H5Distore.c @@ -29,8 +29,8 @@ static hbool_t interface_initialize_g = FALSE; /* PRIVATE PROTOTYPES */ static size_t H5F_istore_sizeof_rkey (H5F_t *f, const void *_udata); -static haddr_t H5F_istore_new (H5F_t *f, void *_lt_key, void *_udata, - void *_rt_key); +static haddr_t H5F_istore_new_node (H5F_t *f, void *_lt_key, void *_udata, + void *_rt_key); static intn H5F_istore_cmp (H5F_t *f, void *_lt_key, void *_udata, void *_rt_key); static herr_t H5F_istore_found (H5F_t *f, haddr_t addr, const void *_lt_key, @@ -43,10 +43,12 @@ static herr_t H5F_istore_decode_key (H5F_t *f, H5B_t *bt, uint8 *raw, void *_key); static herr_t H5F_istore_encode_key (H5F_t *f, H5B_t *bt, uint8 *raw, void *_key); -static herr_t H5F_istore_copy_hyperslab (H5F_t *f, H5O_istore_t *istore, - H5F_isop_t op, size_t offset_f[], - size_t size[], size_t offset_m[], - size_t size_m[], void *buf); +static herr_t H5F_istore_copy_hyperslab (H5F_t *f, const H5O_istore_t *istore, + H5F_isop_t op, + const size_t offset_f[], + const size_t size[], + const size_t offset_m[], + const size_t size_m[], void *buf); /* @@ -79,7 +81,7 @@ H5B_class_t H5B_ISTORE[1] = {{ H5B_ISTORE_ID, /*id */ sizeof (H5F_istore_key_t), /*sizeof_nkey */ H5F_istore_sizeof_rkey, /*get_sizeof_rkey */ - H5F_istore_new, /*new */ + H5F_istore_new_node, /*new */ H5F_istore_cmp, /*cmp */ H5F_istore_found, /*found */ H5F_istore_insert, /*insert */ @@ -262,7 +264,7 @@ H5F_istore_cmp (H5F_t *f, void *_lt_key, void *_udata, void *_rt_key) /*------------------------------------------------------------------------- - * Function: H5F_istore_new + * Function: H5F_istore_new_node * * Purpose: Adds a new entry to an i-storage B-tree. We can assume that * the domain represented by UDATA doesn't intersect the domain @@ -281,7 +283,7 @@ H5F_istore_cmp (H5F_t *f, void *_lt_key, void *_udata, void *_rt_key) *------------------------------------------------------------------------- */ static haddr_t -H5F_istore_new (H5F_t *f, void *_lt_key, void *_udata, void *_rt_key) +H5F_istore_new_node (H5F_t *f, void *_lt_key, void *_udata, void *_rt_key) { H5F_istore_key_t *lt_key = (H5F_istore_key_t *)_lt_key; H5F_istore_key_t *rt_key = (H5F_istore_key_t *)_rt_key; @@ -289,7 +291,7 @@ H5F_istore_new (H5F_t *f, void *_lt_key, void *_udata, void *_rt_key) size_t nbytes; intn i; - FUNC_ENTER (H5F_istore_new, NULL, FAIL); + FUNC_ENTER (H5F_istore_new_node, NULL, FAIL); /* check args */ assert (f); @@ -519,9 +521,10 @@ H5F_istore_insert (H5F_t *f, haddr_t addr, H5B_ins_t *parent_ins, *------------------------------------------------------------------------- */ static herr_t -H5F_istore_copy_hyperslab (H5F_t *f, H5O_istore_t *istore, H5F_isop_t op, - size_t offset_f[], size_t size[], - size_t offset_m[], size_t size_m[], void *buf) +H5F_istore_copy_hyperslab (H5F_t *f, const H5O_istore_t *istore, H5F_isop_t op, + const size_t offset_f[], const size_t size[], + const size_t offset_m[], const size_t size_m[], + void *buf) { intn i, carry; size_t idx_cur[H5O_ISTORE_NDIMS]; @@ -542,6 +545,7 @@ H5F_istore_copy_hyperslab (H5F_t *f, H5O_istore_t *istore, H5F_isop_t op, /* check args */ assert (f); assert (istore); + assert (istore->btree_addr>0); assert (istore->ndims>0 && istore->ndims<=H5O_ISTORE_NDIMS); assert (H5F_ISTORE_READ==op || H5F_ISTORE_WRITE==op); assert (size); @@ -559,22 +563,6 @@ H5F_istore_copy_hyperslab (H5F_t *f, H5O_istore_t *istore, H5F_isop_t op, } #endif - /* - * Does the B-tree exist? - */ - if (istore->btree_addr<=0) { - if (H5F_ISTORE_WRITE==op) { - udata.mesg.ndims = istore->ndims; - if ((istore->btree_addr=H5B_new (f, H5B_ISTORE, &udata))<0) { - /* Can't create B-tree */ - HGOTO_ERROR (H5E_IO, H5E_CANTINIT, FAIL); - } - } else { - H5V_hyper_fill (istore->ndims, size, size_m, offset_m, buf, 0); - HRETURN (SUCCEED); - } - } - /* Initialize indices */ for (i=0; i<istore->ndims; i++) { idx_min[i] = (offset_f?offset_f[i]:0) / istore->alignment[i]; @@ -677,8 +665,8 @@ H5F_istore_copy_hyperslab (H5F_t *f, H5O_istore_t *istore, H5F_isop_t op, *------------------------------------------------------------------------- */ herr_t -H5F_istore_read (H5F_t *f, struct H5O_istore_t *istore, - size_t offset[], size_t size[], void *buf) +H5F_istore_read (H5F_t *f, const H5O_istore_t *istore, + const size_t offset[], const size_t size[], void *buf) { FUNC_ENTER (H5F_istore_read, NULL, FAIL); @@ -717,8 +705,8 @@ H5F_istore_read (H5F_t *f, struct H5O_istore_t *istore, *------------------------------------------------------------------------- */ herr_t -H5F_istore_write (H5F_t *f, struct H5O_istore_t *istore, - size_t offset[], size_t size[], void *buf) +H5F_istore_write (H5F_t *f, const H5O_istore_t *istore, + const size_t offset[], const size_t size[], void *buf) { FUNC_ENTER (H5F_istore_write, NULL, FAIL); @@ -738,3 +726,58 @@ H5F_istore_write (H5F_t *f, struct H5O_istore_t *istore, FUNC_LEAVE (SUCCEED); } + + +/*------------------------------------------------------------------------- + * Function: H5F_istore_new + * + * Purpose: Creates a new indexed-storage B-tree and initializes the + * istore struct with information about the storage. The + * struct should be immediately written to the object header. + * + * This function must be called before passing ISTORE to any of + * the other indexed storage functions! + * + * Return: Success: SUCCEED with the ISTORE argument initialized + * and ready to write to an object header. + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Tuesday, October 21, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5F_istore_new (H5F_t *f, struct H5O_istore_t *istore, + uintn ndims, const size_t alignment[]) +{ + H5F_istore_ud1_t udata; + int i; + + FUNC_ENTER (H5F_istore_new, NULL, FAIL); + + /* Check args */ + assert (f); + assert (istore); + assert (ndims>0 && ndims<=H5O_ISTORE_NDIMS); + assert (alignment); +#ifndef NDEBUG + for (i=0; i<ndims; i++) { + assert (alignment[i]>0); + } +#endif + + udata.mesg.ndims = istore->ndims = ndims; + if ((istore->btree_addr=H5B_new (f, H5B_ISTORE, &udata))<0) { + HRETURN_ERROR (H5E_IO, H5E_CANTINIT, FAIL); /* Can't create B-tree */ + } + + for (i=0; i<ndims; i++) { + istore->alignment[i] = alignment[i]; + } + + FUNC_LEAVE (SUCCEED); +} @@ -84,6 +84,7 @@ static const hdf_min_error_messages_t hdf_min_error_messages[] = {H5E_SEEKERROR, "Seek failed"}, {H5E_READERROR, "Read failed"}, {H5E_WRITEERROR, "Write failed"}, + {H5E_CLOSEERROR, "Close failed"}, {H5E_CANTINIT, "Can't initialize interface"}, {H5E_ALREADYINIT, "Object already initialized"}, {H5E_BADATOM, "Can't find atom information"}, diff --git a/src/H5Epublic.h b/src/H5Epublic.h index abb6e3c..38d9516 100644 --- a/src/H5Epublic.h +++ b/src/H5Epublic.h @@ -72,6 +72,7 @@ typedef enum H5E_SEEKERROR, /* Seek failed */ H5E_READERROR, /* Read failed */ H5E_WRITEERROR, /* Write failed */ + H5E_CLOSEERROR, /* Close failed */ /* Function entry/exit interface errors */ H5E_CANTINIT, /* Can't initialize interface */ @@ -54,7 +54,7 @@ static char RcsId[] = "@(#)$Revision$"; * keep track of the file position and attempt to minimize calls to the file * seek method. */ -#define H5F_OPT_SEEK +/* #define H5F_OPT_SEEK */ #define PABLO_MASK H5F_mask @@ -325,7 +325,7 @@ done: --------------------------------------------------------------------------*/ hbool_t H5Fis_hdf5(const char *filename) { - hdf_file_t f_handle=H5F_INVALID_FILE; /* file handle */ + H5F_low_t *f_handle=NULL; /* file handle */ uint8 temp_buf[H5F_SIGNATURE_LEN]; /* temporary buffer for checking file signature */ haddr_t curr_off=0; /* The current offset to check in the file */ size_t file_len=0; /* The length of the file we are checking */ @@ -339,41 +339,31 @@ hbool_t H5Fis_hdf5(const char *filename) HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, BFAIL); /*no filename specified*/ /* Open the file */ - f_handle=H5F_OPEN(filename,0); - if(H5F_OPENERR(f_handle)) { + if (NULL==(f_handle=H5F_low_open (H5F_LOW_DFLT, filename, 0))) { /* Low-level file open failure */ HGOTO_ERROR(H5E_FILE, H5E_BADFILE, BFAIL); } /* Get the length of the file */ - if(H5F_SEEKEND(f_handle)==FAIL) { - /* Unable to determine length of file due to seek failure */ - HGOTO_ERROR(H5E_IO, H5E_SEEKERROR, BFAIL); - } - file_len=H5F_TELL(f_handle); - + file_len = H5F_low_size (f_handle); + /* Check the offsets where the file signature is possible */ - while(curr_off<file_len) - { - if(H5F_SEEK(f_handle,curr_off)==FAIL) - HGOTO_ERROR(H5E_IO, H5E_READERROR, BFAIL); /*seek error*/ - if(H5F_READ(f_handle,temp_buf, H5F_SIGNATURE_LEN)==FAIL) - HGOTO_ERROR(H5E_IO, H5E_READERROR, BFAIL); /*read error*/ - if(HDmemcmp(temp_buf,H5F_SIGNATURE,H5F_SIGNATURE_LEN)==0) - { - ret_value=BTRUE; - break; - } /* end if */ - if(curr_off==0) - curr_off=512; - else - curr_off*=2; - } /* end while */ + while(curr_off<file_len) { + if (H5F_low_read (f_handle, curr_off, H5F_SIGNATURE_LEN, temp_buf)<0) { + HGOTO_ERROR(H5E_IO, H5E_READERROR, BFAIL); /*read error*/ + } + if(HDmemcmp(temp_buf,H5F_SIGNATURE,H5F_SIGNATURE_LEN)==0) { + ret_value=BTRUE; + break; + } + if(curr_off==0) + curr_off=512; + else + curr_off*=2; + } /* end while */ done: - if(f_handle!=H5F_INVALID_FILE) - H5F_CLOSE(f_handle); /* close the file we opened */ - + H5F_low_close(f_handle); /* close the file we opened */ FUNC_LEAVE(ret_value); } @@ -510,6 +500,10 @@ H5F_dest (H5F_t *f) * The CREATE_PARMS argument is optional. A null pointer will * cause the default file creation parameters to be used. * + * The TYPE argument determins the low-level type of file that + * is opened. The special value H5F_LOW_DFLT uses the default + * method which is defined at compile time. + * * Errors: * ATOM BADATOM Can't unatomize default template * id. @@ -557,7 +551,7 @@ H5F_dest (H5F_t *f) *------------------------------------------------------------------------- */ H5F_t * -H5F_open (const char *name, uintn flags, +H5F_open (const H5F_low_class_t *type, const char *name, uintn flags, const file_create_temp_t *create_parms) { H5F_t *f = NULL; /*return value */ @@ -565,7 +559,7 @@ H5F_open (const char *name, uintn flags, H5F_t *old = NULL; /*a file already opened */ struct stat sb; /*file stat info */ H5F_search_t search; /*file search key */ - hdf_file_t fd = H5F_INVALID_FILE; /*low level file desc */ + H5F_low_t *fd = NULL; /*low level file desc */ hbool_t empty_file = FALSE; /*is file empty? */ hbool_t file_exists = FALSE; /*file already exists */ uint8 buf[256], *p=NULL; /*I/O buffer and ptr into it */ @@ -628,14 +622,14 @@ H5F_open (const char *name, uintn flags, } if ((flags & H5F_ACC_WRITE) && 0==(old->shared->flags & H5F_ACC_WRITE)) { - if (H5F_INVALID_FILE==(fd = H5F_OPEN (name, H5ACC_WRITE))) { + if (NULL==(fd=H5F_low_open (type, name, H5F_ACC_WRITE))) { /* File cannot be reopened with write access */ HRETURN_ERROR (H5E_FILE, H5E_CANTOPENFILE, NULL); } - H5F_CLOSE (old->shared->file_handle); + H5F_low_close (old->shared->file_handle); old->shared->file_handle = fd; old->shared->flags |= H5F_ACC_WRITE; - fd = H5F_INVALID_FILE; /*so we don't close it during error*/ + fd = NULL; /*so we don't close it during error*/ } f = H5F_new (old->shared); @@ -645,7 +639,8 @@ H5F_open (const char *name, uintn flags, /* Can't truncate without write intent */ HRETURN_ERROR (H5E_FILE, H5E_BADVALUE, NULL); } - if (H5F_INVALID_FILE==(fd=H5F_CREATE (name))) { + fd = H5F_low_open (type, name, H5F_ACC_WRITE|H5F_ACC_TRUNC); + if (!fd) { /* Can't truncate file */ HRETURN_ERROR (H5E_FILE, H5E_CANTCREATE, NULL); } @@ -657,8 +652,8 @@ H5F_open (const char *name, uintn flags, empty_file = TRUE; } else { - fd = H5F_OPEN (name, (flags & H5F_ACC_WRITE)?H5ACC_WRITE : 0); - if (H5F_INVALID_FILE==fd) { + fd = H5F_low_open (type, name, (flags & H5F_ACC_WRITE)); + if (!fd) { /* Cannot open existing file */ HRETURN_ERROR (H5E_FILE, H5E_CANTOPENFILE, NULL); } @@ -673,12 +668,13 @@ H5F_open (const char *name, uintn flags, /* Can't create file without write intent */ HRETURN_ERROR (H5E_FILE, H5E_BADVALUE, NULL); } - if (H5F_INVALID_FILE==(fd=H5F_CREATE (name))) { + fd = H5F_low_open (type, name, H5F_ACC_WRITE|H5F_ACC_CREAT|H5F_ACC_EXCL); + if (!fd) { /* Can't create file */ HRETURN_ERROR (H5E_FILE, H5E_CANTCREATE, NULL); } if (stat (name, &sb)<0) { - /* Can't stat file */ + /* Can't stat file - can't get dev or inode */ HRETURN_ERROR (H5E_FILE, H5E_CANTCREATE, NULL); } f = H5F_new (NULL); @@ -835,13 +831,7 @@ H5F_open (const char *name, uintn flags, } /* What is the current size of the file? */ - if (H5F_SEEKEND (f->shared->file_handle)<0) { - /* Cannot determine file size */ - HGOTO_ERROR (H5E_FILE, H5E_CANTINIT, NULL); - } - f->shared->logical_len = H5F_TELL (f->shared->file_handle); - f->shared->last_op=OP_SEEK; /* change the last operation to a seek */ - + f->shared->logical_len = H5F_low_size (f->shared->file_handle); /* Success! */ ret_value = f; @@ -849,7 +839,7 @@ H5F_open (const char *name, uintn flags, done: if (!ret_value) { if (f) H5F_dest (f); - if (H5F_INVALID_FILE!=fd) H5F_CLOSE (fd); + H5F_low_close (fd); } FUNC_LEAVE (ret_value); @@ -941,7 +931,8 @@ hid_t H5Fcreate(const char *filename, uintn flags, hid_t create_temp, /* * Create a new file or truncate an existing file. */ - if (NULL==(new_file = H5F_open (filename, flags, create_parms))) { + if (NULL==(new_file = H5F_open (H5F_LOW_DFLT, filename, flags, + create_parms))) { HGOTO_ERROR (H5E_FILE, H5E_CANTOPENFILE, FAIL); /*can't create file */ } @@ -1023,7 +1014,7 @@ hid_t H5Fopen(const char *filename, uintn flags, hid_t access_temp) #endif /* Open the file */ - if (NULL==(new_file=H5F_open (filename, flags, NULL))) { + if (NULL==(new_file=H5F_open (H5F_LOW_DFLT, filename, flags, NULL))) { HGOTO_ERROR (H5E_FILE, H5E_CANTOPENFILE, FAIL); /*cant open file*/ } @@ -1213,7 +1204,7 @@ H5F_close (H5F_t *f) /*can't flush cache*/ HRETURN_ERROR (H5E_CACHE, H5E_CANTFLUSH, FAIL); } - H5F_CLOSE(f->shared->file_handle); + H5F_low_close (f->shared->file_handle); H5F_dest (f); /* Did the H5F_flush() fail because of open objects? */ @@ -1291,8 +1282,7 @@ done: * The data is contiguous. * * Errors: - * IO READERROR Low-level read failure. - * IO SEEKERROR Low-level seek failure. + * IO READERROR Low-level read failed. * * Return: Success: SUCCEED * @@ -1313,25 +1303,10 @@ H5F_block_read (H5F_t *f, haddr_t addr, size_t size, void *buf) if (0==size) return 0; addr += f->shared->file_create_parms.userblock_size; - - /* Check for switching file access operations or mis-placed seek offset */ -#ifdef H5F_OPT_SEEK - if(f->shared->last_op!=OP_READ || f->shared->f_cur_off!=addr) - { -#endif - f->shared->last_op=OP_READ; - if (H5F_SEEK (f->shared->file_handle, addr)<0) { - /* low-level seek failure */ - HRETURN_ERROR (H5E_IO, H5E_SEEKERROR, FAIL); - } /* end if */ -#ifdef H5F_OPT_SEEK - } /* end if */ -#endif - if (H5F_READ (f->shared->file_handle, buf, size)<0) { - /* low-level read failure */ - HRETURN_ERROR (H5E_IO, H5E_READERROR, FAIL); + + if (H5F_low_read (f->shared->file_handle, addr, size, buf)<0) { + HRETURN_ERROR (H5E_IO, H5E_READERROR, FAIL); /*low-level read failed*/ } - f->shared->f_cur_off=addr+size; FUNC_LEAVE (SUCCEED); } @@ -1344,8 +1319,7 @@ H5F_block_read (H5F_t *f, haddr_t addr, size_t size, void *buf) * data is contiguous. * * Errors: - * IO SEEKERROR Low-level seek failure. - * IO WRITEERROR Low-level write failure. + * IO WRITEERROR Low-level write failed. * IO WRITEERROR No write intent. * * Return: Success: SUCCEED @@ -1373,25 +1347,9 @@ H5F_block_write (H5F_t *f, haddr_t addr, size_t size, void *buf) HRETURN_ERROR (H5E_IO, H5E_WRITEERROR, FAIL); } - /* Check for switching file access operations or mis-placed seek offset */ -#ifdef H5F_OPT_SEEK - if(f->shared->last_op!=OP_WRITE || f->shared->f_cur_off!=addr) - { -#endif - f->shared->last_op=OP_WRITE; - if (H5F_SEEK (f->shared->file_handle, addr)<0) { - /* low-level seek failure */ - HRETURN_ERROR (H5E_IO, H5E_SEEKERROR, FAIL); - } -#ifdef H5F_OPT_SEEK - } /* end if */ -#endif - - if (H5F_WRITE (f->shared->file_handle, buf, size)<0) { - /* low-level write failure */ - HRETURN_ERROR (H5E_IO, H5E_WRITEERROR, FAIL); + if (H5F_low_write (f->shared->file_handle, addr, size, buf)) { + HRETURN_ERROR (H5E_IO, H5E_WRITEERROR, FAIL);/*low-level write failed*/ } - f->shared->f_cur_off=addr+size; FUNC_LEAVE (SUCCEED); } diff --git a/src/H5Fistore.c b/src/H5Fistore.c index b52288c..96ef5fc 100644 --- a/src/H5Fistore.c +++ b/src/H5Fistore.c @@ -29,8 +29,8 @@ static hbool_t interface_initialize_g = FALSE; /* PRIVATE PROTOTYPES */ static size_t H5F_istore_sizeof_rkey (H5F_t *f, const void *_udata); -static haddr_t H5F_istore_new (H5F_t *f, void *_lt_key, void *_udata, - void *_rt_key); +static haddr_t H5F_istore_new_node (H5F_t *f, void *_lt_key, void *_udata, + void *_rt_key); static intn H5F_istore_cmp (H5F_t *f, void *_lt_key, void *_udata, void *_rt_key); static herr_t H5F_istore_found (H5F_t *f, haddr_t addr, const void *_lt_key, @@ -43,10 +43,12 @@ static herr_t H5F_istore_decode_key (H5F_t *f, H5B_t *bt, uint8 *raw, void *_key); static herr_t H5F_istore_encode_key (H5F_t *f, H5B_t *bt, uint8 *raw, void *_key); -static herr_t H5F_istore_copy_hyperslab (H5F_t *f, H5O_istore_t *istore, - H5F_isop_t op, size_t offset_f[], - size_t size[], size_t offset_m[], - size_t size_m[], void *buf); +static herr_t H5F_istore_copy_hyperslab (H5F_t *f, const H5O_istore_t *istore, + H5F_isop_t op, + const size_t offset_f[], + const size_t size[], + const size_t offset_m[], + const size_t size_m[], void *buf); /* @@ -79,7 +81,7 @@ H5B_class_t H5B_ISTORE[1] = {{ H5B_ISTORE_ID, /*id */ sizeof (H5F_istore_key_t), /*sizeof_nkey */ H5F_istore_sizeof_rkey, /*get_sizeof_rkey */ - H5F_istore_new, /*new */ + H5F_istore_new_node, /*new */ H5F_istore_cmp, /*cmp */ H5F_istore_found, /*found */ H5F_istore_insert, /*insert */ @@ -262,7 +264,7 @@ H5F_istore_cmp (H5F_t *f, void *_lt_key, void *_udata, void *_rt_key) /*------------------------------------------------------------------------- - * Function: H5F_istore_new + * Function: H5F_istore_new_node * * Purpose: Adds a new entry to an i-storage B-tree. We can assume that * the domain represented by UDATA doesn't intersect the domain @@ -281,7 +283,7 @@ H5F_istore_cmp (H5F_t *f, void *_lt_key, void *_udata, void *_rt_key) *------------------------------------------------------------------------- */ static haddr_t -H5F_istore_new (H5F_t *f, void *_lt_key, void *_udata, void *_rt_key) +H5F_istore_new_node (H5F_t *f, void *_lt_key, void *_udata, void *_rt_key) { H5F_istore_key_t *lt_key = (H5F_istore_key_t *)_lt_key; H5F_istore_key_t *rt_key = (H5F_istore_key_t *)_rt_key; @@ -289,7 +291,7 @@ H5F_istore_new (H5F_t *f, void *_lt_key, void *_udata, void *_rt_key) size_t nbytes; intn i; - FUNC_ENTER (H5F_istore_new, NULL, FAIL); + FUNC_ENTER (H5F_istore_new_node, NULL, FAIL); /* check args */ assert (f); @@ -519,9 +521,10 @@ H5F_istore_insert (H5F_t *f, haddr_t addr, H5B_ins_t *parent_ins, *------------------------------------------------------------------------- */ static herr_t -H5F_istore_copy_hyperslab (H5F_t *f, H5O_istore_t *istore, H5F_isop_t op, - size_t offset_f[], size_t size[], - size_t offset_m[], size_t size_m[], void *buf) +H5F_istore_copy_hyperslab (H5F_t *f, const H5O_istore_t *istore, H5F_isop_t op, + const size_t offset_f[], const size_t size[], + const size_t offset_m[], const size_t size_m[], + void *buf) { intn i, carry; size_t idx_cur[H5O_ISTORE_NDIMS]; @@ -542,6 +545,7 @@ H5F_istore_copy_hyperslab (H5F_t *f, H5O_istore_t *istore, H5F_isop_t op, /* check args */ assert (f); assert (istore); + assert (istore->btree_addr>0); assert (istore->ndims>0 && istore->ndims<=H5O_ISTORE_NDIMS); assert (H5F_ISTORE_READ==op || H5F_ISTORE_WRITE==op); assert (size); @@ -559,22 +563,6 @@ H5F_istore_copy_hyperslab (H5F_t *f, H5O_istore_t *istore, H5F_isop_t op, } #endif - /* - * Does the B-tree exist? - */ - if (istore->btree_addr<=0) { - if (H5F_ISTORE_WRITE==op) { - udata.mesg.ndims = istore->ndims; - if ((istore->btree_addr=H5B_new (f, H5B_ISTORE, &udata))<0) { - /* Can't create B-tree */ - HGOTO_ERROR (H5E_IO, H5E_CANTINIT, FAIL); - } - } else { - H5V_hyper_fill (istore->ndims, size, size_m, offset_m, buf, 0); - HRETURN (SUCCEED); - } - } - /* Initialize indices */ for (i=0; i<istore->ndims; i++) { idx_min[i] = (offset_f?offset_f[i]:0) / istore->alignment[i]; @@ -677,8 +665,8 @@ H5F_istore_copy_hyperslab (H5F_t *f, H5O_istore_t *istore, H5F_isop_t op, *------------------------------------------------------------------------- */ herr_t -H5F_istore_read (H5F_t *f, struct H5O_istore_t *istore, - size_t offset[], size_t size[], void *buf) +H5F_istore_read (H5F_t *f, const H5O_istore_t *istore, + const size_t offset[], const size_t size[], void *buf) { FUNC_ENTER (H5F_istore_read, NULL, FAIL); @@ -717,8 +705,8 @@ H5F_istore_read (H5F_t *f, struct H5O_istore_t *istore, *------------------------------------------------------------------------- */ herr_t -H5F_istore_write (H5F_t *f, struct H5O_istore_t *istore, - size_t offset[], size_t size[], void *buf) +H5F_istore_write (H5F_t *f, const H5O_istore_t *istore, + const size_t offset[], const size_t size[], void *buf) { FUNC_ENTER (H5F_istore_write, NULL, FAIL); @@ -738,3 +726,58 @@ H5F_istore_write (H5F_t *f, struct H5O_istore_t *istore, FUNC_LEAVE (SUCCEED); } + + +/*------------------------------------------------------------------------- + * Function: H5F_istore_new + * + * Purpose: Creates a new indexed-storage B-tree and initializes the + * istore struct with information about the storage. The + * struct should be immediately written to the object header. + * + * This function must be called before passing ISTORE to any of + * the other indexed storage functions! + * + * Return: Success: SUCCEED with the ISTORE argument initialized + * and ready to write to an object header. + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Tuesday, October 21, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5F_istore_new (H5F_t *f, struct H5O_istore_t *istore, + uintn ndims, const size_t alignment[]) +{ + H5F_istore_ud1_t udata; + int i; + + FUNC_ENTER (H5F_istore_new, NULL, FAIL); + + /* Check args */ + assert (f); + assert (istore); + assert (ndims>0 && ndims<=H5O_ISTORE_NDIMS); + assert (alignment); +#ifndef NDEBUG + for (i=0; i<ndims; i++) { + assert (alignment[i]>0); + } +#endif + + udata.mesg.ndims = istore->ndims = ndims; + if ((istore->btree_addr=H5B_new (f, H5B_ISTORE, &udata))<0) { + HRETURN_ERROR (H5E_IO, H5E_CANTINIT, FAIL); /* Can't create B-tree */ + } + + for (i=0; i<ndims; i++) { + istore->alignment[i] = alignment[i]; + } + + FUNC_LEAVE (SUCCEED); +} diff --git a/src/H5Flow.c b/src/H5Flow.c new file mode 100644 index 0000000..2e47629 --- /dev/null +++ b/src/H5Flow.c @@ -0,0 +1,234 @@ +/* + * Copyright (C) 1997 NCSA + * All rights reserved. + * + * Programmer: Robb Matzke <matzke@viper.llnl.gov> + * Wednesday, October 22, 1997 + * + * Purpose: This file contains virtual functions for the H5F_low + * class. These are functions that operate on various kinds + * of files at a level where the file is just a one-dimensional + * array of bytes. + */ +#include <H5private.h> +#include <H5Eprivate.h> +#include <H5Fprivate.h> +#include <H5MMprivate.h> + +#define PABLO_MASK H5F_low +static hbool_t interface_initialize_g = FALSE; + + + +/*------------------------------------------------------------------------- + * Function: H5F_low_open + * + * Purpose: Opens a file of type TYPE with name NAME according to the + * field of bit flags FLAGS which are: + * + * H5F_ACC_WRITE: The file is open for read/write access. + * Without this bit set, the file would be open + * for read-only access. + * + * H5F_ACC_CREAT: The file is created if it doesn't already + * exist. On unix, the file permissions are set + * to 0666 modified by the umask. + * + * H5F_ACC_EXCL: This function will fail if the file already + * exists. + * + * H5F_ACC_TRUNC: Truncate the file to a zero-length file as it + * is opened. This allows existing files to be + * overwritten. + * + * Errors: + * IO CANTOPENFILE Open failed. + * + * Return: Success: Pointer to the new file descriptor. + * + * Failure: NULL + * + * Programmer: Robb Matzke + * Wednesday, October 22, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +H5F_low_t * +H5F_low_open (const H5F_low_class_t *type, const char *name, uintn flags) +{ + H5F_low_t *lf = NULL; + + FUNC_ENTER (H5F_low_open, NULL, NULL); + + assert (type && type->open); + assert (name && *name); + + if (NULL==(lf=(type->open)(name, flags))) { + HRETURN_ERROR (H5E_IO, H5E_CANTOPENFILE, NULL);/*open failed*/ + } + lf->type = type; + + FUNC_LEAVE (lf); +} + + + +/*------------------------------------------------------------------------- + * Function: H5F_low_close + * + * Purpose: Closes a low-level file. + * + * Errors: + * IO CLOSEERROR Close failed. + * + * Return: Success: NULL + * + * Failure: NULL + * + * Programmer: Robb Matzke + * Wednesday, October 22, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +H5F_low_t * +H5F_low_close (H5F_low_t *lf) +{ + FUNC_ENTER (H5F_low_close, NULL, NULL); + + if (lf && (lf->type->close)(lf)<0) { + HRETURN_ERROR (H5E_IO, H5E_CLOSEERROR, NULL); /*close failed*/ + H5MM_xfree (lf); + } + + FUNC_LEAVE (NULL); +} + + +/*------------------------------------------------------------------------- + * Function: H5F_low_read + * + * Purpose: Reads SIZE bytes of data beginning at address ADDR of the + * file LF and puts the result in BUF. + * + * Errors: + * IO READERROR Read failed. + * IO UNSUPPORTED No read method. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Wednesday, October 22, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5F_low_read (H5F_low_t *lf, haddr_t addr, size_t size, uint8 *buf) +{ + herr_t ret_value = FAIL; + + FUNC_ENTER (H5F_low_read, NULL, FAIL); + + assert (lf && lf->type); + assert (buf); + + if (lf->type->read) { + if ((ret_value = (lf->type->read)(lf, addr, size, buf))<0) { + HRETURN_ERROR (H5E_IO, H5E_READERROR, ret_value);/*read failed*/ + } + } else { + HRETURN_ERROR (H5E_IO, H5E_UNSUPPORTED, FAIL);/*no read method*/ + } + + FUNC_LEAVE (ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5F_low_write + * + * Purpose: Writes SIZE bytes of data from BUF into the file LF beginning + * at address ADDR of the file. + * + * Errors: + * IO UNSUPPORTED No write method. + * IO WRITEERROR Write failed. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Wednesday, October 22, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5F_low_write (H5F_low_t *lf, haddr_t addr, size_t size, const uint8 *buf) +{ + herr_t ret_value = FAIL; + + FUNC_ENTER (H5F_low_write, NULL, FAIL); + + assert (lf && lf->type); + assert (buf); + + if (lf->type->write) { + if ((ret_value = (lf->type->write)(lf, addr, size, buf))<0) { + HRETURN_ERROR (H5E_IO, H5E_WRITEERROR, ret_value);/*write failed*/ + } + } else { + HRETURN_ERROR (H5E_IO, H5E_UNSUPPORTED, FAIL);/*no write method*/ + } + + FUNC_LEAVE (ret_value); +} + + + +/*------------------------------------------------------------------------- + * Function: H5F_low_size + * + * Purpose: Returns the current size of the file in bytes. + * + * Errors: + * IO UNSUPPORTED No size method. + * + * Return: Success: Current size of file + * + * Failure: 0 + * + * Programmer: Robb Matzke + * Wednesday, October 22, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +size_t +H5F_low_size (H5F_low_t *lf) +{ + size_t size; + + FUNC_ENTER (H5F_low_size, NULL, 0); + + assert (lf && lf->type); + + if (lf->type->size) { + size = (lf->type->size)(lf); + } else { + HRETURN_ERROR (H5E_IO, H5E_UNSUPPORTED, 0);/*no size method*/ + } + + FUNC_LEAVE (size); +} + diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h index 0d0a65c..1a4d286 100644 --- a/src/H5Fprivate.h +++ b/src/H5Fprivate.h @@ -23,6 +23,16 @@ /* This is a near top-level header! Try not to include much! */ #include <H5private.h> +/* + * Feature: Define this constant to be non-zero if you want to enable code + * that minimizes the number of calls to lseek(). This has a huge + * performance benefit on some systems. Set this constant to zero + * on the compiler command line to disable that optimization. + */ +#ifndef H5F_OPT_SEEK +# define H5F_OPT_SEEK 1 +#endif + /* Maximum size of boot-block buffer */ #define H5F_BOOTBLOCK_SIZE 1024 @@ -42,120 +52,6 @@ #define H5F_ACC_EXCL 0x0004 /* Fail if file exists */ #define H5F_ACC_TRUNC 0x0008 /* Truncate existing file */ -/* - * Define the low-level file interface. - */ -#if FILELIB == POSIXBUFIO -typedef FILE *hdf_file_t; -# ifdef VMS -# define H5F_OPEN(p, a) (((a) & H5ACC_WRITE) ? \ - fopen ((p), "r+", "mbc=64") : \ - fopen ((p), "r", "mbc=64")) -# define H5F_CREATE(p) fopen ((p), "w+", "mbc=64") -# elif defined SUN && defined (__GNUC__) -# define H5F_OPEN(p, a) (((a) & H5ACC_WRITE) ? \ - fopen ((p), "r+") : \ - fopen ((p), "r")) -# define H5F_CREATE(p) fopen ((p), "w+") -# else -# define H5F_OPEN(p, a) (((a) & H5ACC_WRITE) ? \ - fopen ((p), "rb+") : \ - fopen((p), "rb")) -# define H5F_CREATE(p) fopen((p), "wb+") -# endif - -# define H5F_READ(f, b, n) (((size_t)(n) == (size_t)fread ((b), 1, \ - (size_t)(n), \ - (f))) ? \ - SUCCEED : FAIL) -# define H5F_WRITE(f, b, n) (((size_t)(n) == (size_t)fwrite ((b), 1, \ - (size_t)(n), \ - (f))) ? \ - SUCCEED : FAIL) -# define H5F_CLOSE(f) fclose (f) -# define H5F_FLUSH(f) (0==fflush (f) ? SUCCEED : FAIL) -# define H5F_SEEK(f,o) (0==fseek ((f), (long)(o), SEEK_SET) ? \ - SUCCEED : FAIL) -# define H5F_SEEK_CUR(f,o) (0==fseek ((f), (long)(o), SEEK_CUR) ? \ - SUCCEED : FAIL) -# define H5F_SEEKEND(f) (0==fseek ((f), (long)0, SEEK_END) ? \ - SUCCEED : FAIL) -# define H5F_TELL(f) ftell (f) -# define H5F_OPENERR(f) (!f) -# define H5F_INVALID_FILE ((FILE *)NULL) - - -#elif FILELIB == POSIXUNBUFIO -typedef int hdf_file_t; -# define H5F_OPEN(p, a) (((a) & H5ACC_WRITE) ? \ - open ((p), O_RDWR) : \ - open ((p), O_RDONLY)) -# define H5F_CREATE(p) open ((p), O_RDWR | O_CREAT | O_TRUNC, 0666) -# define H5F_CLOSE(f) close(f) -# define H5F_FLUSH(f) SUCCEED -# define H5F_READ(f, b, n) (((n)==read ((f), (char*)(b), (n))) ? \ - SUCCEED : FAIL) -# define H5F_WRITE(f, b, n) (((n)==write ((f), (char*)(b), (n))) ? \ - SUCCEED : FAIL) -# define H5F_SEEK(f, o) (lseek ((f), (off_t)(o), SEEK_SET)<0 ? \ - FAIL : SUCCEED) -# define H5F_SEEKEND(f) (lseek ((f), (off_t)0, SEEK_END)<0 ? \ - FAIL : SUCCEED) -# define H5F_TELL(f) lseek ((f), (off_t)0, SEEK_CUR) -# define H5F_OPENERR(f) ((f) < 0) -# define H5F_INVALID_FILE (-1) - - -#elif FILELIB == MACIO -typedef short hdf_file_t; -# define H5F_OPEN(x,y) mopen (x, y) -# define H5F_CREATE(name) mopen (name, H5ACC_CREATE) -# define H5F_CLOSE(x) mclose (x) -# define H5F_FLUSH(a) SUCCEED -# define H5F_READ(a,b,c) mread (a, (char*)b, (int32)c) -# define H5F_WRITE(a,b,c) mwrite (a, (char*)b, (int32)c) -# define H5F_SEEK(x,y) mlseek (x, (int32)y, 0) -# define H5F_SEEKEND(x) mlseek (x, 0L, 2) -# define H5F_TELL(x) mlseek (x, 0L, 1) -# define H5F_OPENERR(f) (f < 0) -# define H5F_INVALID_FILE (-1) - - -#elif FILELIB == WINNTIO -typedef HFILE hdf_file_t; -# define H5F_OPEN(p, a) (((a) & H5ACC_WRITE) ? \ - _lopen ((p), OF_READWRITE) : \ - _lopen ((p), OF_READ)) -# define H5F_CREATE(p) _lcreat ((p), 0) -# define H5F_READ(f, b, n) (((int32)(n) == _hread ((f), (b), (n))) ? \ - SUCCEED : FAIL) -# define H5F_WRITE(f, b, n) (((int32)(n) == _hwrite ((f), (b), (n))) ? \ - SUCCEED : FAIL) -# define H5F_CLOSE(f) (_lclose(f)==0 ? SUCCEED : FAIL) -# define H5F_FLUSH(f) 0 -# define H5F_SEEK(f, o) _llseek ((f), (long)(o), 0) -# define H5F_SEEKEND(f) _llseek ((f), (long)0, 2) -# define H5F_TELL(f) _llseek ((f), 0l, 1) -# define H5F_OPENERR(f) ((f) == (HFILE)HFILE_ERROR) -# define H5F_INVALID_FILE ((HFILE)HFILE_ERROR) - - -#elif FILELIB == PAGEBUFIO -# include "fmpio.h" -typedef MPFILE *hdf_file_t; -# define H5F_OPEN(p, a) MPopen ((p), (a)) -# define H5F_CREATE(p) MPopen ((p), H5ACC_CREATE) -# define H5F_CLOSE(f) MPclose (f) -# define H5F_FLUSH(f) MPflush (f) -# define H5F_READ(f, b, n) MPread ((f), (char *)(b), (n)) -# define H5F_WRITE(f, b, n) MPwrite ((f), (char *)(b), (n)) -# define H5F_SEEK(f, o) MPseek ((f), (off_t)(o), SEEK_SET) -# define H5F_SEEKEND(f) MPseek ((f), (off_t)0, SEEK_END) -# define H5F_TELL(f) MPseek ((f), (off_t)0, SEEK_CUR) -# define H5F_OPENERR(f) ((f) == (MPFILE *)NULL) -# define H5F_INVALID_FILE ((MPFILE *)NULL) - -#endif /* * Encode and decode macros for file meta-data. @@ -188,45 +84,30 @@ typedef MPFILE *hdf_file_t; *(p) = (uint8)(((i) >> 24) & 0xff); (p)++; \ } -# define INT64ENCODE(p, i) { \ - *(p) = (uint8)( (uint64)(i) & 0xff); (p)++; \ - *(p) = (uint8)(((uint64)(i) >> 8) & 0xff); (p)++; \ - *(p) = (uint8)(((uint64)(i) >> 16) & 0xff); (p)++; \ - *(p) = (uint8)(((uint64)(i) >> 24) & 0xff); (p)++; \ - if (sizeof(int64)>4) { \ - *(p) = (uint8)(((uint64)(i) >> 32) & 0xff); (p)++; \ - *(p) = (uint8)(((uint64)(i) >> 40) & 0xff); (p)++; \ - *(p) = (uint8)(((uint64)(i) >> 48) & 0xff); (p)++; \ - *(p) = (uint8)(((uint64)(i) >> 56) & 0xff); (p)++; \ - } else if ((i)<0) { \ - *(p)++ = 0xff; \ - *(p)++ = 0xff; \ - *(p)++ = 0xff; \ - *(p)++ = 0xff; \ - } else { \ - *(p)++ = 0x00; \ - *(p)++ = 0x00; \ - *(p)++ = 0x00; \ - *(p)++ = 0x00; \ +# define INT64ENCODE(p, n) { \ + int64 _n = (n); \ + intn _i; \ + uint8 *_p = (uint8*)(p); \ + for (_i=0; _i<sizeof(int64); _i++, _n>>=8) { \ + *_p++ = _n & 0xff; \ } \ + for (/*void*/; _i<8; _i++) { \ + *_p++ = (n)<0 ? 0xff : 0; \ + } \ + (p) = (uint8*)(p)+8; \ } -# define UINT64ENCODE(p, i) { \ - *(p) = (uint8)( (i) & 0xff); (p)++; \ - *(p) = (uint8)(((i) >> 8) & 0xff); (p)++; \ - *(p) = (uint8)(((i) >> 16) & 0xff); (p)++; \ - *(p) = (uint8)(((i) >> 24) & 0xff); (p)++; \ - if (sizeof(uint64)>4) { \ - *(p) = (uint8)(((i) >> 32) & 0xff); (p)++; \ - *(p) = (uint8)(((i) >> 40) & 0xff); (p)++; \ - *(p) = (uint8)(((i) >> 48) & 0xff); (p)++; \ - *(p) = (uint8)(((i) >> 56) & 0xff); (p)++; \ - } else { \ - *(p)++ = 0x00; \ - *(p)++ = 0x00; \ - *(p)++ = 0x00; \ - *(p)++ = 0x00; \ +# define UINT64ENCODE(p, n) { \ + uint64 _n = (n); \ + intn _i; \ + uint8 *_p = (uint8*)(p); \ + for (_i=0; _i<sizeof(uint64); _i++, _n>>=8) { \ + *_p++ = _n & 0xff; \ } \ + for (/*void*/; _i<8; _i++) { \ + *_p++ = 0; \ + } \ + (p) = (uint8*)(p)+8; \ } # define INT16DECODE(p, i) { \ @@ -253,34 +134,26 @@ typedef MPFILE *hdf_file_t; (i) |= ((uint32)(*(p) & 0xff) << 24); (p)++; \ } -# define INT64DECODE(p, i) { \ - (i) = ( *(p) & 0xff); (p)++; \ - (i) |= ((int64)(*(p) & 0xff) << 8); (p)++; \ - (i) |= ((int64)(*(p) & 0xff) << 16); (p)++; \ - (i) |= ((int64)(*(p) & 0xff) << 24); (p)++; \ - if (sizeof(int64)>4) { \ - (i) |= ((int64)(*(p) & 0xff) << 32); (p)++; \ - (i) |= ((int64)(*(p) & 0xff) << 40); (p)++; \ - (i) |= ((int64)(*(p) & 0xff) << 48); (p)++; \ - (i) |= ((int64)(*(p) & 0xff) << 56); (p)++; \ - } else { \ - (p) += 4; \ +# define INT64DECODE(p, n) { \ + /* WE DON'T CHECK FOR OVERFLOW! */ \ + int64 _n = 0; \ + intn _i; \ + uint8 *_p = (uint8*)(p)+8; \ + for (_i=0; _i<sizeof(int64); _i++, _n<<=8) { \ + _n |= *(--_p); \ } \ + (p) = (uint8*)(p)+8; \ } -# define UINT64DECODE(p, i) { \ - (i) = (uint64)(*(p) & 0xff); (p)++; \ - (i) |= ((uint64)(*(p) & 0xff) << 8); (p)++; \ - (i) |= ((uint64)(*(p) & 0xff) << 16); (p)++; \ - (i) |= ((uint64)(*(p) & 0xff) << 24); (p)++; \ - if (sizeof(uint64)>4) { \ - (i) |= ((uint64)(*(p) & 0xff) << 32); (p)++; \ - (i) |= ((uint64)(*(p) & 0xff) << 40); (p)++; \ - (i) |= ((uint64)(*(p) & 0xff) << 48); (p)++; \ - (i) |= ((uint64)(*(p) & 0xff) << 56); (p)++; \ - } else { \ - (p) += 4; \ +# define UINT64DECODE(p, n) { \ + /* WE DON'T CHECK FOR OVERFLOW! */ \ + uint64 _n = 0; \ + intn _i; \ + uint8 *_p = (uint8*)(p)+8; \ + for (_i=0; _i<sizeof(uint64); _i++, _n<<=8) { \ + _n |= *(--_p); \ } \ + (p) = (uint8*)(p)+8; \ } #else @@ -352,27 +225,62 @@ typedef struct H5F_search_t { } H5F_search_t; /* For determining what the last file operation was */ -typedef enum - { - OP_UNKNOWN = 0, /* Don't know what the last operation was (after fopen frex) */ - OP_SEEK, /* Last operation was a seek */ - OP_WRITE, /* Last operation was a write */ - OP_READ /* Last operation was a read */ - } -H5F_fileop_t; +typedef enum { + H5F_OP_UNKNOWN, /* Don't know what the last operation was */ + H5F_OP_SEEK, /* Last operation was a seek */ + H5F_OP_WRITE, /* Last operation was a write */ + H5F_OP_READ /* Last operation was a read */ +} H5F_fileop_t; + +/* + * Define the low-level file interface. + */ +typedef struct H5F_low_class_t { + struct H5F_low_t *(*open)(const char*, uintn); + herr_t (*close)(struct H5F_low_t*); + herr_t (*read)(struct H5F_low_t*, haddr_t, size_t, uint8*); + herr_t (*write)(struct H5F_low_t*, haddr_t, size_t, const uint8*); + herr_t (*flush)(struct H5F_low_t*); + size_t (*size)(struct H5F_low_t*); +} H5F_low_class_t; + +typedef struct H5F_low_t { + const H5F_low_class_t *type; /* What type of file is this? */ + union { + + /* Posix section 2 I/O */ + struct { + int fd; /* The unix file descriptor */ + H5F_fileop_t op; /* Previous file operation */ + haddr_t cur; /* Current file position */ + } sec2; + + /* Posix stdio */ + struct { + FILE *f; /* Posix stdio file */ + H5F_fileop_t op; /* Previous file operation */ + haddr_t cur; /* Current file position */ + } stdio; + + } u; +} H5F_low_t; + +/* What types of low-level files are there? */ +#ifndef H5F_LOW_DFLT +# define H5F_LOW_DFLT H5F_LOW_STDIO /* The default type */ +#endif +extern const H5F_low_class_t H5F_LOW_SEC2[]; /* Posix section 2 */ +extern const H5F_low_class_t H5F_LOW_STDIO[]; /* Posix stdio */ + /* * Define the structure to store the file information for HDF5 files. One of * these structures is allocated per file, not per H5Fopen(). */ typedef struct H5F_file_t { - /* Seek caching info */ - haddr_t f_cur_off; /* Current location in the file */ - H5F_fileop_t last_op; /* the last file operation performed */ - H5F_search_t key; /* The key for looking up files */ uintn flags; /* Access Permissions for file */ - hdf_file_t file_handle; /* File handle for actual I/O */ + H5F_low_t *file_handle; /* Lower level file handle for I/O */ uintn nrefs; /* Ref count for times file is opened */ uint32 consist_flags; /* File Consistency Flags */ haddr_t smallobj_off; /* Offset of small-obj heap within the file */ @@ -452,16 +360,33 @@ struct H5O_istore_t; /*forward decl for prototype arguments*/ /* Private functions, not part of the publicly documented API */ void H5F_encode_length_unusual(const H5F_t *f, uint8 **p, uint8 *l); void H5F_encode_offset_unusual(const H5F_t *f, uint8 **p, uint8 *o); -H5F_t *H5F_open (const char *name, uintn flags, +H5F_t *H5F_open (const H5F_low_class_t *type, const char *name, uintn flags, const file_create_temp_t *create_parms); herr_t H5F_close (H5F_t *f); -herr_t H5F_block_read (H5F_t *f, haddr_t addr, size_t size, void *buf); -herr_t H5F_block_write (H5F_t *f, haddr_t addr, size_t size, void *buf); -herr_t H5F_istore_read (H5F_t *f, struct H5O_istore_t *mesg, - size_t offset[], size_t size[], void *buf); -herr_t H5F_istore_write (H5F_t *f, struct H5O_istore_t *mesg, - size_t offset[], size_t size[], void *buf); herr_t H5F_debug (H5F_t *f, haddr_t addr, FILE *stream, intn indent, intn fwidth); +/* Functions that operate on indexed storage */ +herr_t H5F_istore_new (H5F_t *f, struct H5O_istore_t *istore, + uintn ndims, const size_t alignment[]); +herr_t H5F_istore_read (H5F_t *f, const struct H5O_istore_t *mesg, + const size_t offset[], const size_t size[], + void *buf); +herr_t H5F_istore_write (H5F_t *f, const struct H5O_istore_t *mesg, + const size_t offset[], const size_t size[], + void *buf); + +/* Functions that operate on contiguous storage wrt boot block */ +herr_t H5F_block_read (H5F_t *f, haddr_t addr, size_t size, void *buf); +herr_t H5F_block_write (H5F_t *f, haddr_t addr, size_t size, void *buf); + +/* Functions that operate directly on low-level files */ +H5F_low_t *H5F_low_open (const H5F_low_class_t *type, const char *name, + uintn flags); +H5F_low_t *H5F_low_close (H5F_low_t *lf); +size_t H5F_low_size (H5F_low_t *lf); +herr_t H5F_low_read (H5F_low_t *lf, haddr_t addr, size_t size, uint8 *buf); +herr_t H5F_low_write (H5F_low_t *lf, haddr_t addr, size_t size, + const uint8 *buf); + #endif diff --git a/src/H5Fsec2.c b/src/H5Fsec2.c new file mode 100644 index 0000000..f58725a --- /dev/null +++ b/src/H5Fsec2.c @@ -0,0 +1,314 @@ +/* + * Copyright (C) 1997 NCSA + * All rights reserved. + * + * Programmer: Robb Matzke <matzke@llnl.gov> + * Wednesday, October 22, 1997 + * + * Purpose: This is the Posix section-2 I/O subclass of H5Flow. + * + * Notes: This driver keeps track of its own file position in order to + * minimize the number of calls to lseek(). We assume that + * opening a file sets the current file position to the beginning + * and that read() and write() modify the file position as + * expected when they return successfully (unsuccessful return + * leaves the file position undefined). + */ +#include <H5private.h> +#include <H5Eprivate.h> +#include <H5Fprivate.h> +#include <H5MMprivate.h> + +#define PABLO_MASK H5F_sec2 +static hbool_t interface_initialize_g = FALSE; + +static H5F_low_t *H5F_sec2_open (const char *name, uintn flags); +static herr_t H5F_sec2_close (H5F_low_t *lf); +static herr_t H5F_sec2_read (H5F_low_t *lf, haddr_t addr, size_t size, + uint8 *buf); +static herr_t H5F_sec2_write (H5F_low_t *lf, haddr_t addr, size_t size, + const uint8 *buf); +static herr_t H5F_sec2_flush (H5F_low_t *lf); +static size_t H5F_sec2_size (H5F_low_t *lf); + + +const H5F_low_class_t H5F_LOW_SEC2[1] = {{ + H5F_sec2_open, /* open method */ + H5F_sec2_close, /* close method */ + H5F_sec2_read, /* read method */ + H5F_sec2_write, /* write method */ + H5F_sec2_flush, /* flush method */ + H5F_sec2_size, /* file size method */ +}}; + + + +/*------------------------------------------------------------------------- + * Function: H5F_sec2_open + * + * Purpose: Opens a file with name NAME. The FLAGS are a bit field with + * the possible values defined in H5F_low_open(). + * + * Errors: + * IO CANTOPENFILE Open failed. + * + * Return: Success: Low-level file pointer + * + * Failure: NULL + * + * Programmer: Robb Matzke + * Wednesday, October 22, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static H5F_low_t * +H5F_sec2_open (const char *name, uintn flags) +{ + uintn oflags; + H5F_low_t *lf = NULL; + int fd; + + FUNC_ENTER (H5F_sec2_open, NULL, NULL); + + oflags = (flags & H5F_ACC_WRITE) ? O_RDWR : O_RDONLY; + oflags |= (flags & H5F_ACC_CREAT) ? O_CREAT : 0; + oflags |= (flags & H5F_ACC_EXCL) ? O_EXCL : 0; + oflags |= (flags & H5F_ACC_TRUNC) ? O_TRUNC : 0; + + if ((fd=open (name, oflags, 0666))<0) { + HRETURN_ERROR (H5E_IO, H5E_CANTOPENFILE, NULL);/*open failed*/ + } + + lf = H5MM_xcalloc (1, sizeof(H5F_low_t)); + lf->u.sec2.fd = fd; + lf->u.sec2.op = H5F_OP_SEEK; + lf->u.sec2.cur = 0; + + FUNC_LEAVE (lf); +} + + + +/*------------------------------------------------------------------------- + * Function: H5F_sec2_close + * + * Purpose: Closes a file. + * + * Errors: + * IO CLOSEERROR Close failed. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Wednesday, October 22, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5F_sec2_close (H5F_low_t *lf) +{ + FUNC_ENTER (H5F_sec2_close, NULL, FAIL); + + if (close (lf->u.sec2.fd)<0) { + HRETURN_ERROR (H5E_IO, H5E_CLOSEERROR, FAIL); /*close failed*/ + } + lf->u.sec2.fd = -1; + + FUNC_LEAVE (SUCCEED); +} + + +/*------------------------------------------------------------------------- + * Function: H5F_sec2_read + * + * Purpose: Reads SIZE bytes beginning at address ADDR in file LF and + * places them in buffer BUF. Reading past the end of the + * file returns zeros instead of failing. + * + * Errors: + * IO READERROR Read failed. + * IO SEEKERROR Lseek failed. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Wednesday, October 22, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5F_sec2_read (H5F_low_t *lf, haddr_t addr, size_t size, uint8 *buf) +{ + ssize_t n; + + FUNC_ENTER (H5F_sec2_read, NULL, FAIL); + + /* + * Optimize seeking. If that optimization is disabled then alwasy call + * lseek(). + */ + if (!H5F_OPT_SEEK || + lf->u.sec2.op==H5F_OP_UNKNOWN || lf->u.sec2.cur!=addr) { + if (lseek (lf->u.sec2.fd, addr, SEEK_SET)<0) { + HRETURN_ERROR (H5E_IO, H5E_SEEKERROR, FAIL); /*lseek failed*/ + } + lf->u.sec2.cur = addr; + } + + /* + * Read the data. If a read error occurs then set the last file operation + * to UNKNOWN because the file position isn't guaranteed by Posix. + */ + if ((n=read (lf->u.sec2.fd, buf, size))<0) { + lf->u.sec2.op = H5F_OP_UNKNOWN; + HRETURN_ERROR (H5E_IO, H5E_READERROR, FAIL); /*read failed*/ + } else if (n<size) { + HDmemset (buf+n, 0, size-n); + } + + /* + * Update the file position with the number of bytes actually read. This + * might be different than the number requested. + */ + lf->u.sec2.op = H5F_OP_READ; + lf->u.sec2.cur = addr + n; + + FUNC_LEAVE (SUCCEED); +} + + + +/*------------------------------------------------------------------------- + * Function: H5F_sec2_write + * + * Purpose: Writes SIZE bytes from the beginning of BUF into file LF at + * file address ADDR. + * + * Errors: + * IO SEEKERROR Lseek failed. + * IO WRITEERROR Write failed. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Wednesday, October 22, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5F_sec2_write (H5F_low_t *lf, haddr_t addr, size_t size, const uint8 *buf) +{ + FUNC_ENTER (H5F_sec2_write, NULL, FAIL); + + /* + * Optimize seeking. If that optimization is disabled then always call + * lseek(). + */ + if (!H5F_OPT_SEEK || + lf->u.sec2.op==H5F_OP_UNKNOWN || lf->u.sec2.cur!=addr) { + if (lseek (lf->u.sec2.fd, addr, SEEK_SET)<0) { + HRETURN_ERROR (H5E_IO, H5E_SEEKERROR, FAIL); /*lseek failed*/ + } + lf->u.sec2.cur = addr; + } + + /* + * Read the data from the file. If the write failed then set the + * operation back to UNKNOWN since Posix doesn't gurantee its value. + */ + if (size != write (lf->u.sec2.fd, buf, size)) { + lf->u.sec2.op = H5F_OP_UNKNOWN; + HRETURN_ERROR (H5E_IO, H5E_WRITEERROR, FAIL); /*write failed*/ + } + + /* + * Update the file position. + */ + lf->u.sec2.op = H5F_OP_WRITE; + lf->u.sec2.cur = addr + size; + FUNC_LEAVE (SUCCEED); +} + + + +/*------------------------------------------------------------------------- + * Function: H5F_sec2_flush + * + * Purpose: Makes sure that all data is on disk. + * + * Errors: + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Wednesday, October 22, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5F_sec2_flush (H5F_low_t *lf) +{ + FUNC_ENTER (H5F_sec2_flush, NULL, FAIL); + + /* Not necessary with this driver */ + + FUNC_LEAVE (SUCCEED); +} + + +/*------------------------------------------------------------------------- + * Function: H5F_sec2_size + * + * Purpose: Returns the current size of the file in bytes. + * + * Bugs: There is no way to determine if this function failed. + * + * Errors: + * IO SEEKERROR Lseek failed. + * + * Return: Success: Size of file in bytes + * + * Failure: 0 + * + * Programmer: Robb Matzke + * Wednesday, October 22, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static size_t +H5F_sec2_size (H5F_low_t *lf) +{ + off_t size; + + FUNC_ENTER (H5F_sec2_size, NULL, 0); + + if ((size=lseek (lf->u.sec2.fd, 0, SEEK_END))<0) { + lf->u.sec2.op = H5F_OP_UNKNOWN; + HRETURN_ERROR (H5E_IO, H5E_SEEKERROR, 0); /*lseek failed*/ + } + + lf->u.sec2.op = H5F_OP_SEEK; + lf->u.sec2.cur = size; + + FUNC_LEAVE (size); +} diff --git a/src/H5Fstdio.c b/src/H5Fstdio.c new file mode 100644 index 0000000..d2b868d --- /dev/null +++ b/src/H5Fstdio.c @@ -0,0 +1,341 @@ +/* + * Copyright (C) 1997 NCSA + * All rights reserved. + * + * Programmer: Robb Matzke <matzke@llnl.gov> + * Wednesday, October 22, 1997 + * + * Purpose: This is the Posix stdio.h I/O subclass of H5Flow. + */ +#include <H5private.h> +#include <H5private.h> +#include <H5Eprivate.h> +#include <H5Fprivate.h> +#include <H5MMprivate.h> + +#define PABLO_MASK H5F_sec2 +static hbool_t interface_initialize_g = FALSE; + +static H5F_low_t *H5F_stdio_open (const char *name, uintn flags); +static herr_t H5F_stdio_close (H5F_low_t *lf); +static herr_t H5F_stdio_read (H5F_low_t *lf, haddr_t addr, size_t size, + uint8 *buf); +static herr_t H5F_stdio_write (H5F_low_t *lf, haddr_t addr, size_t size, + const uint8 *buf); +static herr_t H5F_stdio_flush (H5F_low_t *lf); +static size_t H5F_stdio_size (H5F_low_t *lf); + + +const H5F_low_class_t H5F_LOW_STDIO[1] = {{ + H5F_stdio_open, /* open method */ + H5F_stdio_close, /* close method */ + H5F_stdio_read, /* read method */ + H5F_stdio_write, /* write method */ + H5F_stdio_flush, /* flush method */ + H5F_stdio_size, /* file size method */ +}}; + + + +/*------------------------------------------------------------------------- + * Function: H5F_stdio_open + * + * Purpose: Opens a file with name NAME. The FLAGS are a bit field with + * the possible values defined in H5F_low_open(). + * + * Bugs: H5F_ACC_EXCL has a race condition. + * + * Errors: + * IO CANTOPENFILE File doesn't exist and CREAT wasn't + * specified. + * IO CANTOPENFILE Fopen failed. + * IO FILEEXISTS File exists but CREAT and EXCL were + * specified. + * + * Return: Success: Low-level file pointer + * + * Failure: NULL + * + * Programmer: Robb Matzke + * Wednesday, October 22, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static H5F_low_t * +H5F_stdio_open (const char *name, uintn flags) +{ + H5F_low_t *lf=NULL; + FILE *f=NULL; + + FUNC_ENTER (H5F_stdio_open, NULL, NULL); + + if (access (name, F_OK)<0) { + if ((flags & H5F_ACC_CREAT) && (flags & H5F_ACC_WRITE)) { + f = fopen (name, "wb+"); + } else { + /* File doesn't exist and CREAT wasn't specified */ + HRETURN_ERROR (H5E_IO, H5E_CANTOPENFILE, NULL); + } + + } else if ((flags & H5F_ACC_CREAT) && (flags & H5F_ACC_EXCL)) { + /* File exists but CREAT and EXCL were specified */ + HRETURN_ERROR (H5E_IO, H5E_FILEEXISTS, NULL); + + } else if (flags & H5F_ACC_WRITE) { + if (flags & H5F_ACC_TRUNC) f = fopen (name, "wb+"); + else f = fopen (name, "rb+"); + + } else { + f = fopen (name, "rb"); + } + if (!f) HRETURN_ERROR (H5E_IO, H5E_CANTOPENFILE, NULL); /*fopen failed*/ + + /* Build the return value */ + lf = H5MM_xcalloc (1, sizeof(H5F_low_t)); + lf->u.stdio.f = f; + lf->u.stdio.op = H5F_OP_SEEK; + lf->u.stdio.cur = 0; + + FUNC_LEAVE (lf); +} + + +/*------------------------------------------------------------------------- + * Function: H5F_stdio_close + * + * Purpose: Closes a file. + * + * Errors: + * IO CLOSEERROR Close failed. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Wednesday, October 22, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5F_stdio_close (H5F_low_t *lf) +{ + FUNC_ENTER (H5F_stdio_close, NULL, FAIL); + + if (fclose (lf->u.stdio.f)<0) { + HRETURN_ERROR (H5E_IO, H5E_CLOSEERROR, FAIL); /*close failed*/ + } + lf->u.stdio.f = NULL; + + FUNC_LEAVE (SUCCEED); +} + + +/*------------------------------------------------------------------------- + * Function: H5F_stdio_read + * + * Purpose: Reads SIZE bytes beginning at address ADDR in file LF and + * places them in buffer BUF. Reading past the end of the + * file returns zeros instead of failing. + * + * Errors: + * IO READERROR Fread failed. + * IO SEEKERROR Fseek failed. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Wednesday, October 22, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5F_stdio_read (H5F_low_t *lf, haddr_t addr, size_t size, uint8 *buf) +{ + size_t n; + + FUNC_ENTER (H5F_stdio_read, NULL, FAIL); + + /* + * Seek to the correct file position. + */ + if (!H5F_OPT_SEEK || + lf->u.stdio.op==H5F_OP_UNKNOWN || + lf->u.stdio.cur!=addr) { + if (fseek (lf->u.stdio.f, addr, SEEK_SET)<0) { + HRETURN_ERROR (H5E_IO, H5E_SEEKERROR, FAIL); /*fseek failed*/ + } + lf->u.stdio.cur = addr; + } + + /* + * Read the data. Since we're reading single-byte values, a partial read + * will advance the file position by N. If N is negative or an error + * occurs then the file position is undefined. + */ + n = fread (buf, 1, size, lf->u.stdio.f); + if (n<=0 && ferror (lf->u.stdio.f)) { + lf->u.stdio.op = H5F_OP_UNKNOWN; + HRETURN_ERROR (H5E_IO, H5E_READERROR, FAIL); /*fread failed*/ + } else if (n<size) { + HDmemset (buf+n, 0, size-n); + } + + /* + * Update the file position data. + */ + lf->u.stdio.op = H5F_OP_READ; + lf->u.stdio.cur = addr + n; + FUNC_LEAVE (SUCCEED); +} + + + +/*------------------------------------------------------------------------- + * Function: H5F_stdio_write + * + * Purpose: Writes SIZE bytes from the beginning of BUF into file LF at + * file address ADDR. + * + * Errors: + * IO SEEKERROR Fseek failed. + * IO WRITEERROR Fwrite failed. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Wednesday, October 22, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5F_stdio_write (H5F_low_t *lf, haddr_t addr, size_t size, const uint8 *buf) +{ + FUNC_ENTER (H5F_stdio_write, NULL, FAIL); + + /* + * Seek to the correct file position. + */ + if (!H5F_OPT_SEEK || + lf->u.stdio.op==H5F_OP_UNKNOWN || + lf->u.stdio.cur!=addr) { + if (fseek (lf->u.stdio.f, addr, SEEK_SET)<0) { + HRETURN_ERROR (H5E_IO, H5E_SEEKERROR, FAIL); /*fseek failed*/ + } + lf->u.stdio.cur = addr; + } + + /* + * Write the buffer. On successful return, the file position will be + * advanced by the number of bytes read. Otherwise nobody knows where it + * is. + */ + if (size != fwrite (buf, 1, size, lf->u.stdio.f)) { + lf->u.stdio.op = H5F_OP_UNKNOWN; + HRETURN_ERROR (H5E_IO, H5E_WRITEERROR, FAIL); /*fwrite failed*/ + } + + /* + * Update seek optimizing data. + */ + lf->u.stdio.op = H5F_OP_WRITE; + lf->u.stdio.cur = addr + size; + FUNC_LEAVE (SUCCEED); +} + + + +/*------------------------------------------------------------------------- + * Function: H5F_stdio_flush + * + * Purpose: Makes sure that all data is on disk. + * + * Errors: + * IO WRITEERROR Fflush failed. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Wednesday, October 22, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5F_stdio_flush (H5F_low_t *lf) +{ + FUNC_ENTER (H5F_stdio_flush, NULL, FAIL); + + /* + * What happens to the file position? Is it guaranteed to be the same + * after the fflush() as it was before? + */ + lf->u.stdio.op = H5F_OP_UNKNOWN; + + /* + * Flush + */ + if (fflush (lf->u.stdio.f)<0) { + HRETURN_ERROR (H5E_IO, H5E_WRITEERROR, FAIL); /*fflush failed*/ + } + + FUNC_LEAVE (SUCCEED); +} + + +/*------------------------------------------------------------------------- + * Function: H5F_stdio_size + * + * Purpose: Returns the current size of the file in bytes. + * + * Bugs: There is no way to determine if this function failed. + * + * Errors: + * IO SEEKERROR Fseek failed. + * + * Return: Success: Size of file in bytes + * + * Failure: 0 + * + * Programmer: Robb Matzke + * Wednesday, October 22, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static size_t +H5F_stdio_size (H5F_low_t *lf) +{ + off_t size; + + FUNC_ENTER (H5F_stdio_size, NULL, 0); + + /* Seek to the end and get the file offset */ + if (fseek (lf->u.stdio.f, 0, SEEK_END)<0) { + HRETURN_ERROR (H5E_IO, H5E_SEEKERROR, 0); /*fseek failed*/ + } + size = ftell (lf->u.stdio.f); + + /* Update seek opt data */ + lf->u.stdio.op = H5F_OP_SEEK; + lf->u.stdio.cur = size; + + FUNC_LEAVE (size); +} + @@ -519,7 +519,7 @@ H5H_insert (H5F_t *f, haddr_t addr, size_t buf_size, const void *buf) H5H_t *heap=NULL; H5H_free_t *fl=NULL, *max_fl=NULL; off_t offset = -1; - size_t need, old_size, need_more; + size_t old_size, need_more; #ifndef NDEBUG static nmessages = 0; #endif @@ -533,10 +533,6 @@ H5H_insert (H5F_t *f, haddr_t addr, size_t buf_size, const void *buf) assert (buf_size>0); assert (buf); - /* allocate aligned file memory */ - need = buf_size; - H5H_ALIGN (need); - if (NULL==(heap=H5AC_find (f, H5AC_HEAP, addr, NULL, NULL))) { HRETURN_ERROR (H5E_HEAP, H5E_CANTLOAD, FAIL); } @@ -547,12 +543,12 @@ H5H_insert (H5F_t *f, haddr_t addr, size_t buf_size, const void *buf) * leave zero or at least H5G_SIZEOF_FREE bytes left over. */ for (fl=heap->freelist; fl; fl=fl->next) { - if (fl->size>need && fl->size-need>=H5H_SIZEOF_FREE(f)) { + if (fl->size>buf_size && fl->size-buf_size>=H5H_SIZEOF_FREE(f)) { offset = fl->offset; - fl->offset += need; - fl->size -= need; + fl->offset += buf_size; + fl->size -= buf_size; break; - } else if (fl->size==need) { + } else if (fl->size==buf_size) { offset = fl->offset; fl = H5H_remove_free (heap, fl); break; @@ -570,15 +566,15 @@ H5H_insert (H5F_t *f, haddr_t addr, size_t buf_size, const void *buf) */ if (offset<0) { - need_more = MAX3 (need, heap->mem_alloc, H5H_SIZEOF_FREE(f)); + need_more = MAX3 (buf_size, heap->mem_alloc, H5H_SIZEOF_FREE(f)); if (max_fl && max_fl->offset+max_fl->size==heap->mem_alloc) { /* * Increase the size of the maximum free block. */ offset = max_fl->offset; - max_fl->offset += need; - max_fl->size += need_more - need; + max_fl->offset += buf_size; + max_fl->size += need_more - buf_size; if (max_fl->size < H5H_SIZEOF_FREE(f)) { #ifndef NDEBUG @@ -600,18 +596,18 @@ H5H_insert (H5F_t *f, haddr_t addr, size_t buf_size, const void *buf) * take some space out of it right away. */ offset = heap->mem_alloc; - if (need_more-need >= H5H_SIZEOF_FREE(f)) { + if (need_more-buf_size >= H5H_SIZEOF_FREE(f)) { fl = H5MM_xmalloc (sizeof(H5H_free_t)); - fl->offset = heap->mem_alloc + need; - fl->size = need_more - need; + fl->offset = heap->mem_alloc + buf_size; + fl->size = need_more - buf_size; fl->prev = NULL; fl->next = heap->freelist; if (heap->freelist) heap->freelist->prev = fl; heap->freelist = fl; #ifndef NDEBUG - } else if (need_more>need) { + } else if (need_more>buf_size) { fprintf (stderr, "H5H_insert: lost %d bytes at line %d\n", - need_more-need, __LINE__); + need_more-buf_size, __LINE__); if (0==nmessages++) { fprintf (stderr, "Messages from H5H_insert() will go away " "when assertions are turned off.\n"); diff --git a/src/H5Hprivate.h b/src/H5Hprivate.h index 1fa194b..151127a 100644 --- a/src/H5Hprivate.h +++ b/src/H5Hprivate.h @@ -24,7 +24,6 @@ #define H5H_MAGIC "HEAP" /*heap magic number */ #define H5H_SIZEOF_MAGIC 4 -#define H5H_ALIGN(X) ((X)=((X)+1) & ~0x01) #define H5H_SIZEOF_HDR(F) \ (H5H_SIZEOF_MAGIC + /*heap signature */ \ diff --git a/src/H5config.h.in b/src/H5config.h.in index 07a0615..d047ebf 100644 --- a/src/H5config.h.in +++ b/src/H5config.h.in @@ -20,10 +20,10 @@ #undef WORDS_BIGENDIAN /* Define if the __attribute__(()) extension is present */ -/* #define HAVE_ATTRIBUTE */ +#undef HAVE_ATTRIBUTE /* Define if the compiler understands the __FUNCTION__ keyword. */ -/* #define HAVE_FUNCTION */ +#undef HAVE_FUNCTION /* The number of bytes in a double. */ #undef SIZEOF_DOUBLE diff --git a/src/H5private.h b/src/H5private.h index 58db166..12d8a59 100644 --- a/src/H5private.h +++ b/src/H5private.h @@ -55,18 +55,6 @@ # include "ProcIDS.h" #endif -/* - * Low level I/O library - */ -#define POSIXBUFIO 0 -#define POSIXUNBUFIO 1 -#define MACIO 2 -#define WINNTIO 3 -#define PAGEBUFIO 4 -#ifndef FILELIB -# define FILELIB POSIXBUFIO -#endif - /* Does the compiler support the __attribute__(()) syntax? */ #ifndef HAVE_ATTRIBUTE # define __attribute__(X) /*void*/ diff --git a/src/Makefile.in b/src/Makefile.in index 8776376..b61b577 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -15,9 +15,10 @@ PROGS=debug # Source and object files for the library (lexicographically)... LIB_SRC=H5.c H5A.c H5AC.c H5B.c H5C.c H5D.c H5Dconv.c H5E.c H5F.c H5Fistore.c \ - H5G.c H5Gent.c H5Gnode.c H5Gshad.c H5Gstab.c H5H.c H5M.c H5MF.c \ - H5MM.c H5O.c H5Ocont.c H5Oistore.c H5Oname.c H5Onull.c H5Osdtyp.c \ - H5Osdim.c H5Ostab.c H5Ostdst.c H5P.c H5T.c H5V.c + H5Flow.c H5Fsec2.c H5Fstdio.c H5G.c H5Gent.c H5Gnode.c H5Gshad.c \ + H5Gstab.c H5H.c H5M.c H5MF.c H5MM.c H5O.c H5Ocont.c H5Oistore.c \ + H5Oname.c H5Onull.c H5Osdtyp.c H5Osdim.c H5Ostab.c H5Ostdst.c H5P.c \ + H5T.c H5V.c LIB_OBJ=$(LIB_SRC:.c=.o) diff --git a/test/istore.c b/test/istore.c index 9f6fa1f..e79696c 100644 --- a/test/istore.c +++ b/test/istore.c @@ -16,6 +16,9 @@ #define FILENAME "istore.h5" +#define TEST_SMALL 0x0001 +#define TEST_MEDIUM 0x0002 + #define AT() printf (" at %s:%d in %s()...\n", \ __FILE__, __LINE__, __FUNCTION__); @@ -82,6 +85,7 @@ new_object (H5F_t *f, const char *name, size_t ndims) { H5G_entry_t *handle = NULL; H5O_istore_t istore; + size_t alignment[H5O_ISTORE_NDIMS]; intn i; /* Create the object symbol table entry and header */ @@ -95,10 +99,8 @@ new_object (H5F_t *f, const char *name, size_t ndims) } /* Add the indexed-storage message */ - memset (&istore, 0, sizeof istore); - istore.ndims = ndims; - for (i=0; i<ndims; i++) istore.alignment[i] = 2; - + for (i=0; i<ndims; i++) alignment[i] = 2; + H5F_istore_new (f, &istore, ndims, alignment); if (H5O_modify (f, H5O_NO_ADDR, handle, H5O_ISTORE, H5O_NEW_MESG, &istore)<0) { printf ("*FAILED*\n"); @@ -156,7 +158,8 @@ test_create (H5F_t *f, const char *prefix) * Function: test_extend * * Purpose: Creates an empty object and then writes to it in such a way - * as to always extend the object's domain. + * as to always extend the object's domain without creating + * holes and without causing the object to become concave. * * Return: Success: SUCCEED * @@ -181,6 +184,7 @@ test_extend (H5F_t *f, const char *prefix, size_t max_corner[3]; size_t size[3]; size_t whole_size[3]; + size_t nelmts; H5O_istore_t istore; if (!nz) { @@ -245,16 +249,17 @@ test_extend (H5F_t *f, const char *prefix, if (0==ctr) { offset[0] = offset[1] = offset[2] = 0; size[0] = size[1] = size[2] = 1; + nelmts = 1; } else { - for (i=0; i<ndims; i++) { + for (i=0, nelmts=1; i<ndims; i++) { if (ctr % ndims == i) { offset[i] = max_corner[i]; - size[i] = 1; - if (offset[i]+size[i]>whole_size[i]) continue; + size[i] = MIN (1, whole_size[i]-offset[i]); } else { offset[i] = 0; size[i] = max_corner[i]; } + nelmts *= size[i]; } } @@ -266,11 +271,15 @@ test_extend (H5F_t *f, const char *prefix, printf ("), size=(%d", size[0]); if (ndims>1) printf (",%d", size[1]); if (ndims>2) printf (",%d", size[2]); - printf (")\n"); + printf ("), %d element%s", nelmts, 1==nelmts?"":"s"); + if (0==nelmts) printf (" *SKIPPED*"); + printf ("\n"); + fflush (stdout); #endif /* Fill the source array */ - memset (buf, 128+ctr, size[0]*size[1]*size[2]); + if (0==nelmts) continue; + memset (buf, 128+ctr, nelmts); /* Write to disk */ if (H5F_istore_write (f, &istore, offset, size, buf)<0) { @@ -283,7 +292,7 @@ test_extend (H5F_t *f, const char *prefix, } /* Read from disk */ - memset (check, 0xff, size[0]*size[1]*size[2]); + memset (check, 0xff, nelmts); if (H5F_istore_read (f, &istore, offset, size, check)<0) { puts ("*FAILED*"); if (!isatty (1)) { @@ -292,7 +301,7 @@ test_extend (H5F_t *f, const char *prefix, } goto error; } - if (memcmp (buf, check, size[0]*size[1]*size[2])) { + if (memcmp (buf, check, nelmts)) { puts ("*FAILED*"); if (!isatty (1)) { AT (); @@ -316,10 +325,6 @@ test_extend (H5F_t *f, const char *prefix, } } - /* Update the object header */ - H5O_modify (f, H5O_NO_ADDR, handle, H5O_ISTORE, 0, &istore); - - /* Now read the entire array back out and check it */ memset (buf, 0xff, nx*ny*nz); if (H5F_istore_read (f, &istore, H5V_ZERO, whole_size, buf)<0) { @@ -339,8 +344,8 @@ test_extend (H5F_t *f, const char *prefix, AT (); printf (" Check failed at i=%d", i); if (ndims>1) printf (", j=%d", j); - if (ndims>2) printf (", k=%d\n", k); - printf (" Check array is:\n"); + if (ndims>2) printf (", k=%d", k); + printf ("\n Check array is:\n"); print_array (whole, nx, ny, nz); printf (" Value read is:\n"); print_array (buf, nx, ny, nz); @@ -364,7 +369,115 @@ test_extend (H5F_t *f, const char *prefix, H5MM_xfree (whole); return FAIL; } - + + + +/*------------------------------------------------------------------------- + * Function: test_sparse + * + * Purpose: Creates a sparse matrix consisting of NBLOCKS randomly placed + * blocks each of size NX,NY,NZ. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Wednesday, October 22, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +test_sparse (H5F_t *f, const char *prefix, size_t nblocks, + size_t nx, size_t ny, size_t nz) +{ + intn ndims, ctr; + char dims[64], s[256], name[256]; + size_t offset[3], size[3]; + H5G_entry_t *handle = NULL; + H5O_istore_t istore; + uint8 *buf = NULL; + + if (!nz) { + if (!ny) { + ndims = 1; + ny = nz = 1; + sprintf (dims, "%d", nx); + } else { + ndims = 2; + nz = 1; + sprintf (dims, "%dx%d", nx, ny); + } + } else { + ndims = 3; + sprintf (dims, "%dx%dx%d", nx, ny, nz); + } + + sprintf (s, "Testing istore sparse: %s", dims); + printf ("%-70s", s); + fflush (stdout); + buf = H5MM_xmalloc (nx*ny*nz); + + /* Build the new empty object */ + sprintf (name, "%s_%s", prefix, dims); + if (NULL==(handle=new_object (f, name, ndims))) { + if (!isatty (1)) { + AT (); + printf (" Cannot create %d-d object `%s'\n", ndims, name); + } + goto error; + } + if (NULL==H5O_read (f, H5O_NO_ADDR, handle, H5O_ISTORE, 0, &istore)) { + puts ("*FAILED*"); + if (!isatty (1)) { + AT (); + printf (" Unable to read istore message\n"); + } + goto error; + } + + for (ctr=0; ctr<nblocks; ctr++) { + offset[0] = rand () % 1000000; + offset[1] = rand () % 1000000; + offset[2] = rand () % 1000000; + size[0] = nx; + size[1] = ny; + size[2] = nz; + memset (buf, 128+ctr, nx*ny*nz); + + /* write to disk */ + if (H5F_istore_write (f, &istore, offset, size, buf)<0) { + puts ("*FAILED*"); + if (!isatty (1)) { + AT (); + printf (" Write failed: ctr=%d\n", ctr); + printf (" offset=(%d", offset[0]); + if (ndims>1) printf (",%d", offset[1]); + if (ndims>2) printf (",%d", offset[2]); + printf ("), size=(%d", size[0]); + if (ndims>1) printf (",%d", size[1]); + if (ndims>2) printf (",%d", size[2]); + printf (")\n"); + } + goto error; + } + + /* We don't test reading yet.... */ + } + + + H5G_close (f, handle); + puts (" PASSED"); + H5MM_xfree (buf); + return SUCCEED; + + error: + H5MM_xfree (buf); + return FAIL; +} + /*------------------------------------------------------------------------- * Function: main @@ -383,37 +496,84 @@ test_extend (H5F_t *f, const char *prefix, *------------------------------------------------------------------------- */ int -main (void) +main (int argc, char *argv[]) { H5F_t *f; herr_t status; int nerrors = 0; + uintn size_of_test; + + /* Parse arguments or assume `small' */ + if (1==argc) { + size_of_test = TEST_SMALL; + } else { + intn i; + for (i=1,size_of_test=0; i<argc; i++) { + if (!strcmp (argv[i], "small")) { + size_of_test |= TEST_SMALL; + } else if (!strcmp (argv[i], "medium")) { + size_of_test |= TEST_MEDIUM; + } else { + printf ("unrecognized argument: %s\n", argv[i]); + exit (1); + } + } + } + printf ("Test sizes: "); + if (size_of_test & TEST_SMALL) printf (" SMALL"); + if (size_of_test & TEST_MEDIUM) printf (" MEDIUM"); + printf ("\n"); + /* Create the test file */ - if (NULL==(f=H5F_open (FILENAME, H5F_ACC_CREAT|H5F_ACC_WRITE|H5F_ACC_TRUNC, + if (NULL==(f=H5F_open (H5F_LOW_DFLT, FILENAME, + H5F_ACC_CREAT|H5F_ACC_WRITE|H5F_ACC_TRUNC, NULL))) { printf ("Cannot create file %s; test aborted\n", FILENAME); exit (1); } - /*---------------------- - * INDEXED STORAGE TESTS - *---------------------- + /* + * Creation test: Creates empty objects with various raw data sizes + * and alignments. */ - status = test_create (f, "test_create_1"); + status = test_create (f, "create"); nerrors += status<0 ? 1 : 0; - status = test_extend (f, "test_extend_1", 10, 0, 0); - nerrors += status<0 ? 1 : 0; - status = test_extend (f, "test_extend_1", 10, 10, 0); - nerrors += status<0 ? 1 : 0; - status = test_extend (f, "test_extend_1", 10, 10, 10); - nerrors += status<0 ? 1 : 0; - + if (size_of_test & TEST_SMALL) { + status = test_extend (f, "extend", 10, 0, 0); + nerrors += status<0 ? 1 : 0; + status = test_extend (f, "extend", 10, 10, 0); + nerrors += status<0 ? 1 : 0; + status = test_extend (f, "extend", 10, 10, 10); + nerrors += status<0 ? 1 : 0; + } + if (size_of_test & TEST_MEDIUM) { + status = test_extend (f, "extend", 10000, 0, 0); + nerrors += status<0 ? 1 : 0; + status = test_extend (f, "extend", 2500, 10, 0); + nerrors += status<0 ? 1 : 0; + status = test_extend (f, "extend", 10, 400, 10); + nerrors += status<0 ? 1 : 0; + } + if (size_of_test & TEST_SMALL) { + status = test_sparse (f, "sparse", 100, 5, 0, 0); + nerrors += status<0 ? 1 : 0; + status = test_sparse (f, "sparse", 100, 3, 4, 0); + nerrors += status<0 ? 1 : 0; + status = test_sparse (f, "sparse", 100, 2, 3, 4); + nerrors += status<0 ? 1 : 0; + } + if (size_of_test & TEST_MEDIUM) { + status = test_sparse (f, "sparse", 1000, 30, 0, 0); + nerrors += status<0 ? 1 : 0; + status = test_sparse (f, "sparse", 2000, 7, 3, 0); + nerrors += status<0 ? 1 : 0; + status = test_sparse (f, "sparse", 2000, 4, 2, 3); + nerrors += status<0 ? 1 : 0; + } - - /* Close the test file and exit */ H5F_close (f); if (nerrors) { |