diff options
Diffstat (limited to 'src/H5F.c')
-rw-r--r-- | src/H5F.c | 1120 |
1 files changed, 679 insertions, 441 deletions
@@ -46,6 +46,10 @@ static char RcsId[] = "@(#)$Revision$"; #include <H5Mprivate.h> /*meta data */ #include <H5MMprivate.h> /*core memory management */ +#include <sys/types.h> +#include <sys/stat.h> + + #define PABLO_MASK H5F_mask /*--------------------- Locally scoped variables -----------------------------*/ @@ -55,9 +59,10 @@ static intn interface_initialize_g = FALSE; /*--------------------- Local function prototypes ----------------------------*/ static herr_t H5F_init_interface(void); -static hdf5_file_t *H5F_new (void); -static hdf5_file_t *H5F_dest (hdf5_file_t *f); -static herr_t H5F_flush (hdf5_file_t *f, hbool_t invalidate); +static H5F_t *H5F_new (H5F_file_t *shared); +static H5F_t *H5F_dest (H5F_t *f); +static herr_t H5F_flush (H5F_t *f, hbool_t invalidate); +static herr_t H5F_close (H5F_t *f); /*-------------------------------------------------------------------------- NAME @@ -118,7 +123,7 @@ void H5F_term_interface (void) H5F_encode_length_unusual -- encode an unusual length size USAGE void H5F_encode_length_unusual(f, p, l) - const hdf5_file_t *f; IN: pointer to the file record + const H5F_t *f; IN: pointer to the file record uint8 **p; IN: pointer to buffer pointer to encode length in uint8 *l; IN: pointer to length to encode @@ -129,15 +134,18 @@ void H5F_term_interface (void) DESCRIPTION Encode non-standard (i.e. not 2, 4 or 8-byte) lengths in file meta-data. --------------------------------------------------------------------------*/ -void H5F_encode_length_unusual(const hdf5_file_t *f, uint8 **p, uint8 *l) +void H5F_encode_length_unusual(const H5F_t *f, uint8 **p, uint8 *l) { intn i = H5F_SIZEOF_SIZE (f); -/* For non-little-endian platforms, encode each byte in memory backwards */ -#if ((DF_MT&0xFFF0)!=0x4440) +#ifdef WORDS_BIGENDIAN + /* + * For non-little-endian platforms, encode each byte in memory backwards. + */ for(; i>=0; i--,(*p)++) *(*p)=*(l+i); -#else /* platform has little-endian integers */ +#else + /* platform has little-endian integers */ for(; i>=0; i--,(*p)++) *(*p)=*l; #endif @@ -159,7 +167,7 @@ done: H5F_encode_offset_unusual -- encode an unusual offset size USAGE void H5F_encode_offset_unusual(f, p, o) - const hdf5_file_t *f; IN: pointer to the file record + const H5F_t *f; IN: pointer to the file record uint8 **p; IN: pointer to buffer pointer to encode offset in uint8 *o; IN: pointer to offset to encode @@ -170,15 +178,18 @@ ERRORS DESCRIPTION Encode non-standard (i.e. not 2, 4 or 8-byte) offsets in file meta-data. --------------------------------------------------------------------------*/ -void H5F_encode_offset_unusual(const hdf5_file_t *f, uint8 **p, uint8 *o) +void H5F_encode_offset_unusual(const H5F_t *f, uint8 **p, uint8 *o) { intn i = H5F_SIZEOF_OFFSET(f); -/* For non-little-endian platforms, encode each byte in memory backwards */ -#if ((DF_MT&0xFFF0)!=0x4440) +#ifdef WORDS_BIGENDIAN + /* + * For non-little-endian platforms, encode each byte in memory backwards. + */ for(; i>=0; i--,(*p)++) *(*p)=*(o+i); -#else /* platform has little-endian integers */ +#else + /* platform has little-endian integers */ for(; i>=0; i--,(*p)++) *(*p)=*o; #endif @@ -198,11 +209,11 @@ done: /*-------------------------------------------------------------------------- NAME - H5F_compare_filename -- compare file objects for the atom API + H5F_compare_files -- compare file objects for the atom API USAGE intn HPcompare_filename(obj, key) const VOIDP obj; IN: pointer to the file record - const VOIDP key; IN: pointer to the name of file + const VOIDP key; IN: pointer to the search key ERRORS @@ -210,21 +221,22 @@ done: TRUE if the key matches the obj, FALSE otherwise DESCRIPTION Look inside the file record for the atom API and compare the the - filenames. + keys. --------------------------------------------------------------------------*/ -intn -H5F_compare_filename (const VOIDP _obj, const VOIDP _key) +static intn +H5F_compare_files (const VOIDP _obj, const VOIDP _key) { - const hdf5_file_t *obj = (const hdf5_file_t *)_obj; - const char *key = (const char *)_key; + const H5F_t *obj = (const H5F_t *)_obj; + const H5F_search_t *key = (const H5F_search_t *)_key; int ret_value = FALSE; - FUNC_ENTER (H5F_compare_filename, NULL, FALSE); + FUNC_ENTER (H5F_compare_files, NULL, FALSE); - ret_value = !HDstrcmp (obj->filename, key); + ret_value = (obj->shared->key.dev == key->dev && + obj->shared->key.ino == key->ino); FUNC_LEAVE (ret_value); -} /* H5F_compare_filename */ +} /*-------------------------------------------------------------------------- NAME @@ -251,7 +263,7 @@ H5F_compare_filename (const VOIDP _obj, const VOIDP _key) --------------------------------------------------------------------------*/ hid_t H5Fget_create_template(hid_t fid) { - hdf5_file_t *file=NULL; /* file struct for file to close */ + H5F_t *file=NULL; /* file struct for file to close */ hid_t ret_value = FAIL; FUNC_ENTER(H5Fget_create_template, H5F_init_interface, FAIL); @@ -267,7 +279,7 @@ hid_t H5Fget_create_template(hid_t fid) if((ret_value=H5Mcreate(fid,H5_TEMPLATE,NULL))==FAIL) HGOTO_ERROR(H5E_FUNC, H5E_CANTCREATE, FAIL); /*can't create template*/ - if(H5C_init(ret_value,&(file->file_create_parms))==FAIL) + if(H5C_init(ret_value,&(file->shared->file_create_parms))==FAIL) HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL); /*can't init template*/ done: @@ -351,22 +363,13 @@ hbool_t H5Fis_hdf5(const char *filename) else curr_off*=2; } /* end while */ - H5F_CLOSE(f_handle); /* close the file we opened */ -done: - if(ret_value == BFAIL) - { /* Error condition cleanup */ - - /* Check if we left a dangling file handle */ - if(f_handle!=H5F_INVALID_FILE) - H5F_CLOSE(f_handle); /* close the file we opened */ - - } /* end if */ - - /* Normal function cleanup */ + done: + if(f_handle!=H5F_INVALID_FILE) + H5F_CLOSE(f_handle); /* close the file we opened */ FUNC_LEAVE(ret_value); -} /* end H5Fis_hdf5() */ +} /*------------------------------------------------------------------------- @@ -374,7 +377,9 @@ done: * * Purpose: Creates a new file object and initializes it. The * H5Fopen and H5Fcreate functions then fill in various - * fields. + * fields. If SHARED is a non-null pointer then the shared info + * to which it points has the reference count incremented. + * Otherwise a new, empty shared info struct is created. * * Errors: * @@ -390,22 +395,33 @@ done: * *------------------------------------------------------------------------- */ -static hdf5_file_t * -H5F_new (void) +static H5F_t * +H5F_new (H5F_file_t *shared) { - hdf5_file_t *f = H5MM_xcalloc (1, sizeof(hdf5_file_t)); + H5F_t *f = NULL; + FUNC_ENTER (H5F_new, H5F_init_interface, NULL); - /* Create a main cache */ - H5AC_new (f, H5AC_NSLOTS); + f = H5MM_xcalloc (1, sizeof(H5F_t)); + f->shared = shared; + + if (!f->shared) { + f->shared = H5MM_xcalloc (1, sizeof(H5F_file_t)); - /* Create the shadow hash table */ - f->nshadows = H5G_NSHADOWS; - f->shadow = H5MM_xcalloc (f->nshadows, sizeof(struct H5G_hash_t*)); + /* Create a main cache */ + H5AC_new (f, H5AC_NSLOTS); - /* Create a root symbol slot */ - f->root_sym = H5G_ent_calloc (); - - return f; + /* Create the shadow hash table */ + f->shared->nshadows = H5G_NSHADOWS; + f->shared->shadow = H5MM_xcalloc (f->shared->nshadows, + sizeof(struct H5G_hash_t*)); + + /* Create a root symbol slot */ + f->shared->root_sym = H5G_ent_calloc (); + } + + f->shared->nrefs++; + + FUNC_LEAVE (f); } @@ -414,7 +430,8 @@ H5F_new (void) * * Purpose: Destroys a file structure. This function does not flush * the cache or anything else; it only frees memory associated - * with the file struct. + * with the file struct. The shared info for the file is freed + * only when its reference count reaches zero. * * Errors: * @@ -430,19 +447,384 @@ H5F_new (void) * *------------------------------------------------------------------------- */ -static hdf5_file_t * -H5F_dest (hdf5_file_t *f) +static H5F_t * +H5F_dest (H5F_t *f) { + FUNC_ENTER (H5F_dest, H5F_init_interface, NULL); + if (f) { - H5AC_dest (f); - f->dir = H5MM_xfree (f->dir); - f->filename = H5MM_xfree (f->filename); - f->root_sym = H5MM_xfree (f->root_sym); - f->nshadows = 0; - f->shadow = H5MM_xfree (f->shadow); + if (0 == --(f->shared->nrefs)) { + H5AC_dest (f); + f->shared->root_sym = H5MM_xfree (f->shared->root_sym); + f->shared->nshadows = 0; + f->shared->shadow = H5MM_xfree (f->shared->shadow); + f->shared = H5MM_xfree (f->shared); + } + f->name = H5MM_xfree (f->name); H5MM_xfree (f); } - return NULL; + + FUNC_LEAVE (NULL); +} + + + +/*------------------------------------------------------------------------- + * Function: H5F_open + * + * Purpose: Opens (or creates) a file. This function understands the + * following flags which are similar in nature to the Posix + * open(2) flags. + * + * H5F_ACC_WRITE: Open with read/write access. If the file is + * currently open for read-only access then it + * will be reopened. Absence of this flag + * implies read-only access. + * + * H5F_ACC_CREAT: Create a new file if it doesn't exist yet. + * The permissions are 0666 bit-wise AND with + * the current umask. H5F_ACC_WRITE must also + * be specified. + * + * H5F_ACC_EXCL: This flag causes H5F_open() to fail if the + * file already exists. + * + * H5F_ACC_TRUNC: The file is truncated and a new HDF5 boot + * block is written. This operation will fail + * if the file is already open. + * + * Unlinking the file name from the directory hierarchy while + * the file is opened causes the file to continue to exist but + * one will not be able to upgrade the file from read-only + * access to read-write access by reopening it. Disk resources + * for the file are released when all handles to the file are + * closed. NOTE: This paragraph probably only applies to Unix; + * deleting the file name in other OS's has undefined results. + * + * Errors: + * FILE BADVALUE Can't create file without write + * intent. + * FILE BADVALUE Can't truncate without write intent. + * FILE CANTCREATE Can't create file. + * FILE CANTCREATE Can't stat file. + * FILE CANTCREATE Can't truncate file. + * FILE CANTINIT Can't write file boot block. + * FILE CANTINIT Cannot determine file size. + * FILE CANTOPENFILE Bad boot block version number. + * FILE CANTOPENFILE Bad free space version number. + * FILE CANTOPENFILE Bad length size. + * FILE CANTOPENFILE Bad object dir version number. + * FILE CANTOPENFILE Bad offset size. + * FILE CANTOPENFILE Bad shared header version number. + * FILE CANTOPENFILE Bad small object heap version number. + * FILE CANTOPENFILE Bad symbol table internal node 1/2 + * rank. + * FILE CANTOPENFILE Bad symbol table leaf node 1/2 rank. + * FILE CANTOPENFILE Can't read root symbol entry. + * FILE CANTOPENFILE Cannot open existing file. + * FILE CANTOPENFILE File cannot be reopened with write + * access. + * FILE CANTOPENFILE File does not exist. + * FILE FILEEXISTS File already exists - CREAT EXCL + * failed. + * FILE FILEOPEN File already open - TRUNC failed. + * FILE NOTHDF5 Can't read boot block. + * FILE READERROR File is not readable. + * FILE WRITEERROR File is not writable. + * + * Return: Success: Ptr to the file pointer. + * + * Failure: NULL + * + * Programmer: Robb Matzke + * Tuesday, September 23, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static H5F_t * +H5F_open (const char *name, uintn flags, + const file_create_temp_t *create_parms) +{ + H5F_t *f = NULL; /*return value */ + H5F_t *ret_value = NULL; /*a copy of `f' */ + 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 */ + 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 */ + size_t fixed_size = 24; /*size of fixed part of boot blk*/ + size_t variable_size; /*variable part of boot block */ + intn i; + file_create_temp_t *cp=NULL; /*file creation parameters */ + + FUNC_ENTER (H5F_open, H5F_init_interface, NULL); + + assert (name && *name); + + /* + * Does the file exist? If so, get the device and i-node values so we can + * compare them with other files already open. On Unix (and other systems + * with hard or soft links) it doesn't work to compare files based only on + * their full path name. + */ + file_exists = (stat (name, &sb)>=0); + + /* + * Open the low-level file (if necessary) and create an H5F_t struct that + * points to an H5F_file_t struct. + */ + if (file_exists) { + if (flags & H5F_ACC_EXCL) { + /* File already exists - CREAT EXCL failed */ + HRETURN_ERROR (H5E_FILE, H5E_FILEEXISTS, NULL); + } + if (access (name, R_OK)<0) { + /* File is not readable */ + HRETURN_ERROR (H5E_FILE, H5E_READERROR, NULL); + } + if ((flags & H5F_ACC_WRITE) && access (name, W_OK)<0) { + /* File is not writable */ + HRETURN_ERROR (H5E_FILE, H5E_WRITEERROR, NULL); + } + + search.dev = sb.st_dev; + search.ino = sb.st_ino; + if ((old=H5Asearch_atom (H5_FILE, H5F_compare_files, &search))) { + if (flags & H5F_ACC_TRUNC) { + /* File already open - TRUNC failed */ + HRETURN_ERROR (H5E_FILE, H5E_FILEOPEN, NULL); + } + if ((flags & H5F_ACC_WRITE) && + 0==(old->shared->flags & H5F_ACC_WRITE)) { + if (H5F_INVALID_FILE==(fd = H5F_OPEN (name, H5ACC_WRITE))) { + /* File cannot be reopened with write access */ + HRETURN_ERROR (H5E_FILE, H5E_CANTOPENFILE, NULL); + } + H5F_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*/ + } + f = H5F_new (old->shared); + + } else if (flags & H5F_ACC_TRUNC) { + /* Truncate existing file */ + if (0==(flags & H5F_ACC_WRITE)) { + /* Can't truncate without write intent */ + HRETURN_ERROR (H5E_FILE, H5E_BADVALUE, NULL); + } + if (H5F_INVALID_FILE==(fd=H5F_CREATE (name))) { + /* Can't truncate file */ + HRETURN_ERROR (H5E_FILE, H5E_CANTCREATE, NULL); + } + f = H5F_new (NULL); + f->shared->key.dev = sb.st_dev; + f->shared->key.ino = sb.st_ino; + f->shared->flags = flags; + f->shared->file_handle = fd; + empty_file = TRUE; + + } else { + fd = H5F_OPEN (name, (flags & H5F_ACC_WRITE)?H5ACC_WRITE : 0); + if (H5F_INVALID_FILE==fd) { + /* Cannot open existing file */ + HRETURN_ERROR (H5E_FILE, H5E_CANTOPENFILE, NULL); + } + f = H5F_new (NULL); + f->shared->key = search; + f->shared->flags = flags; + f->shared->file_handle = fd; + } + + } else if (flags & H5F_ACC_CREAT) { + if (0==(flags & H5F_ACC_WRITE)) { + /* Can't create file without write intent */ + HRETURN_ERROR (H5E_FILE, H5E_BADVALUE, NULL); + } + if (H5F_INVALID_FILE==(fd=H5F_CREATE (name))) { + /* Can't create file */ + HRETURN_ERROR (H5E_FILE, H5E_CANTCREATE, NULL); + } + if (stat (name, &sb)<0) { + /* Can't stat file */ + HRETURN_ERROR (H5E_FILE, H5E_CANTCREATE, NULL); + } + f = H5F_new (NULL); + f->shared->key.dev = sb.st_dev; + f->shared->key.ino = sb.st_ino; + f->shared->flags = flags; + f->shared->file_handle = fd; + empty_file = TRUE; + + } else { + /* File does not exist */ + HRETURN_ERROR (H5E_FILE, H5E_CANTOPENFILE, NULL); + } + assert (f); + + /* + * The intent at the top level file struct are not necessarily the same as + * the flags at the bottom. The top level describes how the file can be + * accessed through the HDF5 library. The bottom level describes how the + * file can be accessed through the C library. + */ + f->intent = flags; + f->name = H5MM_xstrdup (name); + + /* + * Update the file creation parameters with default values if this is the + * first time this file is opened. + */ + if (1==f->shared->nrefs) { + HDmemcpy (&(f->shared->file_create_parms), + create_parms, + sizeof(file_create_temp_t)); + } + cp = &(f->shared->file_create_parms); + + /* + * Read or write the file boot block. + */ + if (empty_file) { + /* For new files we must write the boot block. */ + f->shared->consist_flags = 0x03; + if (H5F_flush (f, FALSE)<0) { + /* Can't write file boot block */ + HGOTO_ERROR (H5E_FILE, H5E_CANTINIT, NULL); + } + } else if (1==f->shared->nrefs) { + /* For existing files we must read the boot block. */ + assert (fixed_size <= sizeof buf); + for (i=8; i<32*sizeof(haddr_t); i++) { + cp->userblock_size = (8==i ? 0 : 1<<i); + + /* Read the fixed size part of the boot block */ + if (H5F_block_read (f, 0, fixed_size, buf)<0) { + /*can't read boot block*/ + HGOTO_ERROR (H5E_FILE, H5E_NOTHDF5, NULL); + } + + /* + * Decode the fixed size part of the boot block. For each of the + * version parameters, check that the library is able to handle that + * version. + */ + p = buf; + if (HDmemcmp (p, H5F_SIGNATURE, H5F_SIGNATURE_LEN)) continue; + p += H5F_SIGNATURE_LEN; + + cp->bootblock_ver = *p++; + if (cp->bootblock_ver != HDF5_BOOTBLOCK_VERSION) { + /* Bad boot block version number */ + HGOTO_ERROR (H5E_FILE, H5E_CANTOPENFILE, NULL); + } + + cp->smallobject_ver = *p++; + if (cp->smallobject_ver != HDF5_SMALLOBJECT_VERSION) { + /* Bad small object heap version number */ + HGOTO_ERROR (H5E_FILE, H5E_CANTOPENFILE, NULL); + } + + cp->freespace_ver = *p++; + if (cp->freespace_ver != HDF5_FREESPACE_VERSION) { + /* Bad free space version number */ + HGOTO_ERROR (H5E_FILE, H5E_CANTOPENFILE, NULL); + } + + cp->objectdir_ver = *p++; + if (cp->objectdir_ver != HDF5_OBJECTDIR_VERSION) { + /* Bad object dir version number */ + HGOTO_ERROR (H5E_FILE, H5E_CANTOPENFILE, NULL); + } + + cp->sharedheader_ver = *p++; + if (cp->sharedheader_ver != HDF5_SHAREDHEADER_VERSION) { + /* Bad shared header version number */ + HGOTO_ERROR (H5E_FILE, H5E_CANTOPENFILE, NULL); + } + + cp->offset_size = *p++; + if (cp->offset_size!=2 && + cp->offset_size!=4 && + cp->offset_size!=8) { + /* Bad offset size */ + HGOTO_ERROR (H5E_FILE, H5E_CANTOPENFILE, NULL); + } + + cp->length_size = *p++; + if (cp->length_size!=2 && + cp->length_size!=4 && + cp->length_size!=8) { + /* Bad length size */ + HGOTO_ERROR (H5E_FILE, H5E_CANTOPENFILE, NULL); + } + + /* Reserved byte */ + p++; + + UINT16DECODE (p, cp->sym_leaf_k); + if (cp->sym_leaf_k<1) { + /* Bad symbol table leaf node 1/2 rank */ + HGOTO_ERROR (H5E_FILE, H5E_CANTOPENFILE, NULL); + } + + UINT16DECODE (p, cp->btree_k[H5B_SNODE_ID]); + if (cp->btree_k[H5B_SNODE_ID]<1) { + /* Bad symbol table internal node 1/2 rank */ + HGOTO_ERROR (H5E_FILE, H5E_CANTOPENFILE, NULL); + } + + UINT32DECODE (p, f->shared->consist_flags); + /* nothing to check for consistency flags */ + + assert (p-buf == fixed_size); + + /* Read the variable length part of the boot block... */ + variable_size = H5F_SIZEOF_OFFSET (f) + /*global small obj heap*/ + H5F_SIZEOF_OFFSET (f) + /*global free list addr*/ + H5F_SIZEOF_SIZE (f) + /*logical file size*/ + H5G_SIZEOF_ENTRY (f); + assert (variable_size <= sizeof buf); + if (H5F_block_read (f, fixed_size, variable_size, buf)<0) { + /*can't read boot block*/ + HGOTO_ERROR (H5E_FILE, H5E_NOTHDF5, NULL); + } + + p = buf; + H5F_decode_offset (f, p, f->shared->smallobj_off); + H5F_decode_offset (f, p, f->shared->freespace_off); + H5F_decode_length (f, p, f->shared->logical_len); + if (H5G_ent_decode (f, &p, f->shared->root_sym)<0) { + /*can't read root symbol entry*/ + HGOTO_ERROR (H5E_FILE, H5E_CANTOPENFILE, NULL); + } + break; + } + } + + /* 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); + + + + /* Success! */ + ret_value = f; + + done: + if (!ret_value) { + if (f) H5F_dest (f); + if (H5F_INVALID_FILE!=fd) H5F_CLOSE (fd); + } + + FUNC_LEAVE (ret_value); } /*-------------------------------------------------------------------------- @@ -462,16 +844,9 @@ H5F_dest (hdf5_file_t *f) ERRORS ARGS BADVALUE Invalid file name. ARGS BADVALUE Invalid flags. - ATOM BADATOM Can't atomize template. ATOM BADATOM Can't unatomize template. ATOM CANTREGISTER Can't atomize file. - FILE CANTCREATE Unable to create the file due to low level create - failure. - FILE FILEEXISTS File already exists but overwrite permission - was not given. - FILE FILEOPEN File already open. - IO CANTINIT Can't write file boot block. - RESOURCE NOSPACE H5F_new() failed. + FILE CANTOPENFILE Can't create file. RETURNS Returns file ID on success, FAIL on failure @@ -483,8 +858,9 @@ H5F_dest (hdf5_file_t *f) may be combined with the "||" (logical OR operator) to change the behavior of the file open call. The flags currently defined: - H5ACC_OVERWRITE - Truncate file, if it already exists. The file will - be truncated, erasing all data previously stored in the file. + H5ACC_OVERWRITE - Truncate file, if it already exists. The file + will be truncated, erasing all data previously stored in the + file. The more complex behaviors of a file's creation and access are controlled through the file-creation and file-access templates. The value of 0 for a template value indicates that the library should use the default @@ -499,104 +875,62 @@ H5F_dest (hdf5_file_t *f) Robb Matzke, 29 Aug 1997 Moved creation of the boot block to H5F_flush(). + + Robb Matzke, 23 Sep 1997 + Most of the work is now done by H5F_open() since H5Fcreate() and H5Fopen() + originally contained almost identical code. --------------------------------------------------------------------------*/ -hid_t H5Fcreate(const char *filename, uintn flags, hid_t create_temp, hid_t access_temp) +hid_t H5Fcreate(const char *filename, uintn flags, hid_t create_temp, + hid_t access_temp) { - hdf5_file_t *new_file=NULL; /* file struct for new file */ - hdf_file_t f_handle=H5F_INVALID_FILE; /* file handle */ - const file_create_temp_t *f_create_parms; /* pointer to the parameters to use when creating the file */ - intn file_exists=0; /* flag to indicate that file exists already */ - hid_t ret_value = FAIL; + H5F_t *new_file=NULL; /* file struct for new file */ + const file_create_temp_t *create_parms; /* pointer to the parameters to + * use when creating the file + */ + hid_t ret_value = FAIL; FUNC_ENTER(H5Fcreate, H5F_init_interface, FAIL); - - /* Clear errors and check args and all the boring stuff. */ H5ECLEAR; - if(filename==NULL) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL); /*invalid file name*/ - if((flags&~H5ACC_OVERWRITE)!=0) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL); /*invalid flags*/ - - /* See if this file is already open */ - if(H5Asearch_atom(H5_FILE,H5F_compare_filename,(const VOIDP)filename)!=NULL) - HGOTO_ERROR(H5E_FILE, H5E_FILEOPEN, FAIL); /*file already open*/ - - /* Check if the file already exists */ - f_handle=H5F_OPEN(filename,0); - if(!H5F_OPENERR(f_handle)) - { - file_exists=1; /* set the flag to indicate that the file already exists */ - H5F_CLOSE(f_handle); /* close the file we opened */ - f_handle=H5F_INVALID_FILE; - } /* end if */ - - if((flags&H5ACC_OVERWRITE)==0 && file_exists) { - /* File already exists but overwrite permission was not given */ - HGOTO_ERROR(H5E_FILE, H5E_FILEEXISTS, FAIL); - } - - /* OK to create/overwrite the file */ - f_handle=H5F_CREATE(filename); - if(H5F_OPENERR(f_handle)) { - /* Unable to create the file due to low level create failure */ - HGOTO_ERROR(H5E_FILE, H5E_CANTCREATE, FAIL); - } - - /* Create the file node */ - if (NULL==(new_file=H5F_new())) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL); /*H5F_new() failed*/ - - /* Set the non-zero elements of the file structure */ - new_file->dir=HDgetcwd(NULL,0); /* get the directory we just created the file within */ - new_file->filename=HDstrdup(filename); /* make a copy of the filename */ - new_file->acc_perm=H5ACC_WRITE; /* all new files we create have write permission */ - new_file->file_handle=f_handle; /* keep the file handle we just opened */ - new_file->ref_count=1; /* only 1 fid handed out so far */ - new_file->consist_flags=0x03; /* Set file-consistency flags: write-access and "file is consistent" */ - new_file->smallobj_off=0; /* Set the offset of the small-object heap */ - new_file->freespace_off=0; /* Set the offset of the free-space info */ - /* Get the file-creation template & record it */ - if(create_temp==0) - create_temp=H5C_get_default_atom(H5_TEMPLATE); - if((f_create_parms=H5Aatom_object(create_temp))==NULL) - HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL); /*can't atomize template*/ - HDmemcpy(&new_file->file_create_parms,f_create_parms,sizeof(file_create_temp_t)); + /* Check/fix arguments */ + if (!filename || !*filename) + HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL); /*invalid file name*/ + if (flags & ~H5ACC_OVERWRITE) + HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL); /*invalid flags*/ + flags = (H5F_ACC_WRITE | H5F_ACC_CREAT) | + (H5ACC_OVERWRITE==flags ? H5F_ACC_TRUNC : H5F_ACC_EXCL); + if (0==create_temp) + create_temp = H5C_get_default_atom (H5_TEMPLATE); + if (NULL==(create_parms=H5Aatom_object(create_temp))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL); /*can't unatomize template*/ #ifdef LATER - /* Get the file-access template & record it */ - if(access_temp==0) - access_temp=H5CPget_default_atom(H5_TEMPLATE); - if((f_access_parms=H5Aatom_object(access_temp))==NULL) + if (0==access_temp) + access_temp = H5CPget_default_atom(H5_TEMPLATE); + if (NULL==(access_parms=H5Aatom_object(access_temp))) HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL); /*can't unatomize template*/ - HDmemcpy(&new_file->file_access_parms,f_access_parms,sizeof(file_access_temp_t)); -#endif /* LATER */ - - /* Flush the file signature and boot block */ - if (H5F_flush (new_file, FALSE)<0) { - HGOTO_ERROR (H5E_IO, H5E_CANTINIT, FAIL); /*can't write file boot block*/ +#endif + + /* + * Create a new file or truncate an existing file. + */ + if (NULL==(new_file = H5F_open (filename, flags, create_parms))) { + HGOTO_ERROR (H5E_FILE, H5E_CANTOPENFILE, FAIL); /*can't create file */ } /* Get an atom for the file */ - if((ret_value=H5Aregister_atom(H5_FILE, new_file))==FAIL) + if ((ret_value=H5Aregister_atom (H5_FILE, new_file))<0) HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL); /*can't atomize file*/ -done: - if(ret_value == FAIL) - { /* Error condition cleanup */ - - /* Check if we left a dangling file handle */ - if(f_handle!=H5F_INVALID_FILE) - H5F_CLOSE(f_handle); /* close the file we opened */ - - /* Check if we left a dangling file struct */ - if (new_file) - H5F_dest (new_file); + done: + if (ret_value<0 && new_file) { + /* Error condition cleanup */ + H5F_close (new_file); } /* Normal function cleanup */ FUNC_LEAVE(ret_value); -} /* end H5Fcreate() */ +} /*-------------------------------------------------------------------------- @@ -614,29 +948,18 @@ done: ERRORS ARGS BADRANGE Invalid file name. - ATOM BADATOM Can't atomize template. ATOM BADATOM Can't unatomize template. ATOM CANTREGISTER Can't atomize file. - ATOM CANTREGISTER Can't register new_file atom. - FILE CANTOPEN File doesn't exist. - FILE NOTHDF5 Not an HDF5 file. - FILE NOTHDF5 The file exists but doesn't appear to be an - HDF5 file. - IO READERROR Can't decode root symbol table entry. - IO READERROR Read boot block failed. - IO READERROR Read boot block signature failed. - IO READERROR Seek to boot block failed. - IO SEEKERROR Seek failed. - RESOURCE NOSPACE H5F_new() failed. + FILE CANTOPENFILE Cant open file. RETURNS Returns file ID on success, FAIL on failure DESCRIPTION This is the primary function for accessing existing HDF5 files. The - flags parameter determines whether writing to an existing file will be allowed - or not. All flags may be combined with the "||" (logical OR operator) to - change the behavior of the file open call. + flags parameter determines whether writing to an existing file will be + allowed or not. All flags may be combined with the "||" (logical OR + operator) to change the behavior of the file open call. The flags currently defined: H5ACC_WRITE - Allow writing to the file. The more complex behaviors of a file's access are controlled through @@ -646,168 +969,147 @@ done: Robb Matzke, 18 Jul 1997 File struct creation and destruction is through H5F_new() H5F_dest(). Reading the root symbol table entry is done with H5G_decode(). + + Robb Matzke, 23 Sep 1997 + Most of the work is now done by H5F_open() since H5Fcreate() and H5Fopen() + originally contained almost identical code. --------------------------------------------------------------------------*/ hid_t H5Fopen(const char *filename, uintn flags, hid_t access_temp) { - hdf5_file_t *new_file=NULL; /* file struct for new file */ - hdf_file_t f_handle=H5F_INVALID_FILE; /* file handle */ - hid_t create_temp; /* file-creation template ID */ - const file_create_temp_t *f_create_parms; /* pointer to the parameters to use when creating the file */ - uint8 temp_buf[2048], *p; /* temporary buffer for encoding header */ - 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 */ - hid_t ret_value = FAIL; - size_t variable_size; /*size of the variable part of the bb */ + H5F_t *new_file=NULL; /* file struct for new file */ + hid_t create_temp; /* file-creation template ID */ + const file_create_temp_t *f_create_parms; /* pointer to the parameters + * to use when creating the + * file + */ + hid_t ret_value = FAIL; FUNC_ENTER(H5Fopen, H5F_init_interface, FAIL); - - /* Clear errors and check args and all the boring stuff. */ H5ECLEAR; - if(filename==NULL) - HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL);/*invalid file name*/ - - /* See if this file is already open */ - new_file=H5Asearch_atom(H5_FILE,H5F_compare_filename,(const VOIDP)filename); - /* If the file is already open, check the access permissions and go ahead with it */ - if(new_file!=NULL && new_file->acc_perm==flags) - { - /* Get an atom for the file */ - new_file->ref_count++; /* increment the reference count for the file */ - if((ret_value=H5Aregister_atom(H5_FILE, new_file))==FAIL) { - /* Can't register new_file atom */ - HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL); - } - HGOTO_DONE(ret_value); - } /* end if */ - - /* - * If the file exists but has different permissions or if it's a new file, - * start a new file handle for it, etc. - */ - if(H5Fis_hdf5(filename)==BFALSE) { - /* The file exists but doesn't appear to be an HDF5 file */ - HGOTO_ERROR(H5E_FILE, H5E_NOTHDF5, FAIL); - } + /* Check/fix arguments. */ + if (!filename || !*filename) + HGOTO_ERROR (H5E_ARGS, H5E_BADRANGE, FAIL);/*invalid file name*/ + flags = flags & H5ACC_WRITE ? H5F_ACC_WRITE : 0; - /* Check if the file already exists */ - f_handle=H5F_OPEN(filename,flags); - if(H5F_OPENERR(f_handle)) - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL);/*file doesn't exist*/ - - /* Create the file node */ - if (NULL==(new_file=H5F_new())) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL);/*H5F_new() failed*/ - - /* Set the non-zero elements of the file structure */ - new_file->dir=HDgetcwd(NULL,0); /* get the directory we just created the file within */ - new_file->filename=HDstrdup(filename); /* make a copy of the filename */ - new_file->acc_perm=flags; /* set the access permissions */ - new_file->file_handle=f_handle; /* keep the file handle we just opened */ - new_file->ref_count=1; /* only 1 fid handed out so far */ - create_temp=H5C_get_default_atom(H5_TEMPLATE); - if((f_create_parms=H5Aatom_object(create_temp))==NULL) - HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL);/*can't unatomize template*/ - HDmemcpy(&new_file->file_create_parms,f_create_parms,sizeof(file_create_temp_t)); + create_temp = H5C_get_default_atom (H5_TEMPLATE); + if (NULL==(f_create_parms=H5Aatom_object(create_temp))) + HGOTO_ERROR (H5E_ATOM, H5E_BADATOM, FAIL);/*can't unatomize template*/ #ifdef LATER - if(access_temp<=0) - access_temp=H5CPget_default_atom(H5_TEMPLATE); - if((f_access_parms=H5Aatom_object(access_temp))==NULL) - HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL);/*can't atomize template*/ - HDmemcpy(&new_file->file_access_parms,f_access_parms,sizeof(file_access_temp_t)); -#endif /* LATER */ - - /* Read the basic skeleton of the file */ - - /* Seek to the correct offset to read in the file signature & boot-block */ - /* Get the length of the file */ - if(H5F_SEEKEND(new_file->file_handle)==FAIL) - HGOTO_ERROR(H5E_IO, H5E_SEEKERROR, BFAIL);/*seek failed*/ - file_len=H5F_TELL(new_file->file_handle); + if (access_temp<=0) + access_temp = H5CPget_default_atom (H5_TEMPLATE); + if (NULL==(f_access_parms=H5Aatom_object (access_temp))) + HGOTO_ERROR (H5E_ATOM, H5E_BADATOM, FAIL);/*can't unatomize template*/ +#endif - /* Check the offsets where the file signature is possible */ - while(curr_off<file_len) - { - if(H5F_SEEK(new_file->file_handle,curr_off)==FAIL) { - /*seek to boot block failed*/ - HGOTO_ERROR(H5E_IO, H5E_READERROR, BFAIL); - } - if(H5F_READ(new_file->file_handle,temp_buf, H5F_SIGNATURE_LEN)==FAIL) { - /*read boot block signature failed*/ - HGOTO_ERROR(H5E_IO, H5E_READERROR, BFAIL); - } - if(HDmemcmp(temp_buf,H5F_SIGNATURE,H5F_SIGNATURE_LEN)==0) - { - new_file->file_create_parms.userblock_size=curr_off; - break; - } /* end if */ - if(curr_off==0) - curr_off=512; - else - curr_off*=2; - } /* end while */ - if(curr_off>file_len) /* Why didn't H5Fis_hdf5 catch this? */ - HGOTO_ERROR(H5E_FILE, H5E_NOTHDF5, FAIL); /*not an HDF5 file*/ - - /* Read in the fixed-size part of the boot-block */ - if(H5F_READ(new_file->file_handle,temp_buf,16)==FAIL) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL); /*read boot block failed*/ - - /* Decode fixed-size part of the boot block */ - p=temp_buf; - new_file->file_create_parms.bootblock_ver=*p++; /* Decode Boot-block version # */ - new_file->file_create_parms.smallobject_ver=*p++; /* Decode Small-Object Heap version # */ - new_file->file_create_parms.freespace_ver=*p++; /* Decode Free-Space Info version # */ - new_file->file_create_parms.objectdir_ver=*p++; /* Decode Object Directory Format version # */ - new_file->file_create_parms.sharedheader_ver=*p++; /* Decode Shared-Header Info version # */ - new_file->file_create_parms.offset_size=*p++; /* Decode the number of bytes for the offset */ - new_file->file_create_parms.length_size=*p++; /* Decode the number of bytes for the length */ - p++; /* Decode the reserved byte :-) */ - UINT16DECODE (p, new_file->file_create_parms.sym_leaf_k); /*stab leaf 1/2 rank*/ - UINT16DECODE (p, new_file->file_create_parms.btree_k[H5B_SNODE_ID]); /*stab internal 1/2 rank*/ - UINT32DECODE(p,new_file->consist_flags); /* Decode File-Consistancy flags */ - - /* Read the variable-size part of the boot-block */ - variable_size = H5F_SIZEOF_OFFSET(new_file) + /*offset of global small-object heap*/ - H5F_SIZEOF_OFFSET(new_file) + /*offset of global free list*/ - H5F_SIZEOF_SIZE(new_file) + /*logical size of HDF5 file*/ - H5G_SIZEOF_ENTRY(new_file); /*root symbol table entry*/ - if (H5F_READ(new_file->file_handle, temp_buf, variable_size)<0) - HGOTO_ERROR (H5E_IO, H5E_READERROR, FAIL); /*read boot block failed*/ - - /* Decode the variable-size part of the boot block */ - p = temp_buf; - H5F_decode_offset(new_file,p,new_file->smallobj_off); /* Decode offset of global small-object heap */ - H5F_decode_offset(new_file,p,new_file->freespace_off); /* Decode offset of global free-space heap */ - H5F_decode_length(new_file,p,new_file->logical_len); /* Decode logical length of file */ - - /* Decode the root symbol table entry */ - if (H5G_ent_decode (new_file, &p, new_file->root_sym)<0) { - /*can't decode root symbol table entry */ - HGOTO_ERROR (H5E_IO, H5E_READERROR, FAIL); + /* Open the file */ + if (NULL==(new_file=H5F_open (filename, flags, f_create_parms))) { + HGOTO_ERROR (H5E_FILE, H5E_CANTOPENFILE, FAIL); /*cant open file*/ } /* Get an atom for the file */ - if((ret_value=H5Aregister_atom(H5_FILE, new_file))==FAIL) + if ((ret_value = H5Aregister_atom (H5_FILE, new_file))<0) HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL);/*can't atomize file*/ -done: - if(ret_value == FAIL) - { /* Error condition cleanup */ - - /* Check if we left a dangling file handle */ - if(f_handle!=H5F_INVALID_FILE) - H5F_CLOSE(f_handle); /* close the file we opened */ - - /* Check if we left a dangling file struct */ - if(new_file) HDfree(new_file); + done: + if (ret_value<0 && new_file) { + H5F_close (new_file); } /* Normal function cleanup */ FUNC_LEAVE(ret_value); -} /* end H5Fopen() */ +} + + +/*------------------------------------------------------------------------- + * Function: H5F_flush + * + * Purpose: Flushes (and optionally invalidates) cached data plus the + * file boot block. If the logical file size field is zero + * then it is updated to be the length of the boot block. + * + * Errors: + * CACHE CANTFLUSH Can't flush cache. + * IO WRITEERROR Can't write header. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * -2 if the there are open objects and + * INVALIDATE was non-zero. + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Aug 29 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5F_flush (H5F_t *f, hbool_t invalidate) +{ + uint8 buf[2048], *p=buf; + herr_t shadow_flush; + + FUNC_ENTER (H5F_flush, H5F_init_interface, FAIL); + + /* + * Nothing to do if the file is read only. This determination is made at + * the shared open(2) flags level, implying that opening a file twice, + * once for read-only and once for read-write, and then calling + * H5F_flush() with the read-only handle, still causes data to be flushed. + */ + if (0==(H5F_ACC_WRITE & f->shared->flags)) HRETURN (SUCCEED); + + /* + * Flush all open object info. If this fails just remember it and return + * failure at the end. At least that way we get a consistent file. + */ + shadow_flush = H5G_shadow_flush (f, invalidate); + + /* flush (and invalidate) the entire cache */ + if (H5AC_flush (f, NULL, 0, invalidate)<0) { + HRETURN_ERROR (H5E_CACHE, H5E_CANTFLUSH, FAIL); /*can't flush cache*/ + } + + /* encode the file boot block */ + HDmemcpy (p, H5F_SIGNATURE, H5F_SIGNATURE_LEN); + p += H5F_SIGNATURE_LEN; + + *p++ = f->shared->file_create_parms.bootblock_ver; + *p++ = f->shared->file_create_parms.smallobject_ver; + *p++ = f->shared->file_create_parms.freespace_ver; + *p++ = f->shared->file_create_parms.objectdir_ver; + *p++ = f->shared->file_create_parms.sharedheader_ver; + *p++ = H5F_SIZEOF_OFFSET (f); + *p++ = H5F_SIZEOF_SIZE (f); + *p++ = 0; /*reserved*/ + UINT16ENCODE (p, f->shared->file_create_parms.sym_leaf_k); + UINT16ENCODE (p, f->shared->file_create_parms.btree_k[H5B_SNODE_ID]); + UINT32ENCODE (p, f->shared->consist_flags); + H5F_encode_offset (f, p, f->shared->smallobj_off); + H5F_encode_offset (f, p, f->shared->freespace_off); + H5F_encode_length (f, p, f->shared->logical_len); + H5G_ent_encode (f, &p, f->shared->root_sym); + + /* write the boot block to disk */ + if (H5F_block_write (f, 0, p-buf, buf)<0) { + HRETURN_ERROR (H5E_IO, H5E_WRITEERROR, FAIL); /*can't write header*/ + } + + /* update file length if necessary */ + if (f->shared->logical_len<=0) f->shared->logical_len = p-buf; + + /* Did shadow flush fail above? */ + if (shadow_flush<0) { + HRETURN_ERROR (H5E_CACHE, H5E_CANTFLUSH, -2);/*object are still open*/ + } + + FUNC_LEAVE (SUCCEED); +} /*-------------------------------------------------------------------------- NAME @@ -840,7 +1142,7 @@ done: herr_t H5Fflush (hid_t fid, hbool_t invalidate) { - hdf5_file_t *file = NULL; + H5F_t *file = NULL; FUNC_ENTER (H5Fflush, H5F_init_interface, FAIL); H5ECLEAR; @@ -863,86 +1165,44 @@ H5Fflush (hid_t fid, hbool_t invalidate) /*------------------------------------------------------------------------- - * Function: H5F_flush - * - * Purpose: Flushes (and optionally invalidates) cached data plus the - * file boot block. If the logical file size field is zero - * then it is updated to be the length of the boot block. + * Function: H5F_close * - * Errors: - * CACHE CANTFLUSH Can't flush cache. - * IO WRITEERROR Can't write header. + * Purpose: Closes an open HDF5 file. * * Return: Success: SUCCEED * - * Failure: FAIL - * -2 if the there are open objects and - * INVALIDATE was non-zero. + * Failure: FAIL, or -2 if the failure is due to objects + * still being open. * * Programmer: Robb Matzke - * robb@maya.nuance.com - * Aug 29 1997 + * Tuesday, September 23, 1997 * * Modifications: * *------------------------------------------------------------------------- */ static herr_t -H5F_flush (hdf5_file_t *f, hbool_t invalidate) +H5F_close (H5F_t *f) { - uint8 buf[2048], *p=buf; - herr_t shadow_flush; - - FUNC_ENTER (H5F_flush, H5F_init_interface, FAIL); - - /* nothing to do if the file is read only */ - if (0==(H5ACC_WRITE & f->acc_perm)) HRETURN (SUCCEED); - - /* - * Flush all open object info. If this fails just remember it and return - * failure at the end. At least that way we get a consistent file. - */ - shadow_flush = H5G_shadow_flush (f, invalidate); - - /* flush (and invalidate) the entire cache */ - if (H5AC_flush (f, NULL, 0, invalidate)<0) { - HRETURN_ERROR (H5E_CACHE, H5E_CANTFLUSH, FAIL); /*can't flush cache*/ - } + herr_t ret_value = FAIL; - /* encode the file boot block */ - HDmemcpy (p, H5F_SIGNATURE, H5F_SIGNATURE_LEN); - p += H5F_SIGNATURE_LEN; + FUNC_ENTER (H5F_close, H5F_init_interface, FAIL); - *p++ = f->file_create_parms.bootblock_ver; - *p++ = f->file_create_parms.smallobject_ver; - *p++ = f->file_create_parms.freespace_ver; - *p++ = f->file_create_parms.objectdir_ver; - *p++ = f->file_create_parms.sharedheader_ver; - *p++ = H5F_SIZEOF_OFFSET (f); - *p++ = H5F_SIZEOF_SIZE (f); - *p++ = 0; /*reserved*/ - UINT16ENCODE (p, f->file_create_parms.sym_leaf_k); - UINT16ENCODE (p, f->file_create_parms.btree_k[H5B_SNODE_ID]); - UINT32ENCODE (p, f->consist_flags); - H5F_encode_offset (f, p, f->smallobj_off); - H5F_encode_offset (f, p, f->freespace_off); - H5F_encode_length (f, p, f->logical_len); - H5G_ent_encode (f, &p, f->root_sym); - - /* write the boot block to disk */ - if (H5F_block_write (f, 0, p-buf, buf)<0) { - HRETURN_ERROR (H5E_IO, H5E_WRITEERROR, FAIL); /*can't write header*/ + if (-2==(ret_value=H5F_flush (f, TRUE))) { + /*objects are still open, but don't fail yet*/ + } else if (ret_value<0) { + /*can't flush cache*/ + HRETURN_ERROR (H5E_CACHE, H5E_CANTFLUSH, FAIL); } + H5F_CLOSE(f->shared->file_handle); + H5F_dest (f); - /* update file length if necessary */ - if (f->logical_len<=0) f->logical_len = p-buf; - - /* Did shadow flush fail above? */ - if (shadow_flush<0) { - HRETURN_ERROR (H5E_CACHE, H5E_CANTFLUSH, -2);/*object are still open*/ + /* Did the H5F_flush() fail because of open objects? */ + if (ret_value<0) { + HRETURN_ERROR (H5E_SYM, H5E_CANTFLUSH, ret_value); } - - FUNC_LEAVE (SUCCEED); + + FUNC_LEAVE (ret_value); } /*-------------------------------------------------------------------------- @@ -980,52 +1240,29 @@ H5F_flush (hdf5_file_t *f, hbool_t invalidate) --------------------------------------------------------------------------*/ herr_t H5Fclose(hid_t fid) { - hdf5_file_t *file=NULL; /* file struct for file to close */ - herr_t ret_value = SUCCEED; + H5F_t *file=NULL; /* file struct for file to close */ + herr_t ret_value = SUCCEED; FUNC_ENTER(H5Fclose, H5F_init_interface, FAIL); - - /* Clear errors and check args and all the boring stuff. */ H5ECLEAR; - if(H5Aatom_group(fid)!=H5_FILE) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL);/*not a file atom*/ - /* Get the file handle to close */ - if((file=H5Aatom_object(fid))==NULL) - HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL);/*can't unatomize file*/ + /* Check/fix arguments. */ + if (H5_FILE!=H5Aatom_group (fid)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL);/*not a file atom*/ + if (NULL==(file=H5Aatom_object (fid))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL);/*can't unatomize file*/ - /* Decrement the ref. count and recycle the file structure */ - if((--file->ref_count)==0) - { - if(file->file_handle!=H5F_INVALID_FILE) { - if (-2==(ret_value=H5F_flush (file, TRUE))) { - /*objects are still open*/ - } else if (ret_value<0) { - /*can't flush cache*/ - HGOTO_ERROR (H5E_CACHE, H5E_CANTFLUSH, FAIL); - } - H5F_CLOSE(file->file_handle); - } - H5F_dest (file); - if(H5Aremove_atom(fid)==NULL) { - HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL);/*can't remove atom*/ - } - } /* end if */ + /* Close the file */ + ret_value = H5F_close (file); + + /* Remove the file atom */ + if (NULL==H5Aremove_atom(fid)) { + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL);/*can't remove atom*/ + } - /* Did the H5F_flush() fail because of open objects? */ - if (ret_value<0) { - HGOTO_ERROR (H5E_SYM, H5E_CANTFLUSH, FAIL); - } - done: - if(ret_value == FAIL) - { /* Error condition cleanup */ - - } /* end if */ - - /* Normal function cleanup */ - FUNC_LEAVE(ret_value); -} /* end H5Fclose() */ + FUNC_LEAVE (ret_value<0?FAIL:SUCCEED); +} /*------------------------------------------------------------------------- @@ -1051,18 +1288,18 @@ done: *------------------------------------------------------------------------- */ herr_t -H5F_block_read (hdf5_file_t *f, haddr_t addr, size_t size, void *buf) +H5F_block_read (H5F_t *f, haddr_t addr, size_t size, void *buf) { FUNC_ENTER (H5F_block_read, H5F_init_interface, FAIL); if (0==size) return 0; - addr += f->file_create_parms.userblock_size; + addr += f->shared->file_create_parms.userblock_size; - if (H5F_SEEK (f->file_handle, addr)<0) { + if (H5F_SEEK (f->shared->file_handle, addr)<0) { /* low-level seek failure */ HRETURN_ERROR (H5E_IO, H5E_SEEKERROR, FAIL); } - if (H5F_READ (f->file_handle, buf, size)<0) { + if (H5F_READ (f->shared->file_handle, buf, size)<0) { /* low-level read failure */ HRETURN_ERROR (H5E_IO, H5E_READERROR, FAIL); } @@ -1080,6 +1317,7 @@ H5F_block_read (hdf5_file_t *f, haddr_t addr, size_t size, void *buf) * Errors: * IO SEEKERROR Low-level seek failure. * IO WRITEERROR Low-level write failure. + * IO WRITEERROR No write intent. * * Return: Success: SUCCEED * @@ -1094,18 +1332,22 @@ H5F_block_read (hdf5_file_t *f, haddr_t addr, size_t size, void *buf) *------------------------------------------------------------------------- */ herr_t -H5F_block_write (hdf5_file_t *f, haddr_t addr, size_t size, void *buf) +H5F_block_write (H5F_t *f, haddr_t addr, size_t size, void *buf) { FUNC_ENTER (H5F_block_write, H5F_init_interface, FAIL); if (0==size) return 0; - addr += f->file_create_parms.userblock_size; + addr += f->shared->file_create_parms.userblock_size; - if (H5F_SEEK (f->file_handle, addr)<0) { + if (0==(f->intent & H5F_ACC_WRITE)) { + /* no write intent */ + HRETURN_ERROR (H5E_IO, H5E_WRITEERROR, FAIL); + } + if (H5F_SEEK (f->shared->file_handle, addr)<0) { /* low-level seek failure */ HRETURN_ERROR (H5E_IO, H5E_SEEKERROR, FAIL); } - if (H5F_WRITE (f->file_handle, buf, size)<0) { + if (H5F_WRITE (f->shared->file_handle, buf, size)<0) { /* low-level write failure */ HRETURN_ERROR (H5E_IO, H5E_WRITEERROR, FAIL); } @@ -1136,8 +1378,7 @@ H5F_block_write (hdf5_file_t *f, haddr_t addr, size_t size, void *buf) *------------------------------------------------------------------------- */ herr_t -H5F_debug (hdf5_file_t *f, haddr_t addr, FILE *stream, intn indent, - intn fwidth) +H5F_debug (H5F_t *f, haddr_t addr, FILE *stream, intn indent, intn fwidth) { FUNC_ENTER (H5F_debug, H5F_init_interface, FAIL); @@ -1152,62 +1393,59 @@ H5F_debug (hdf5_file_t *f, haddr_t addr, FILE *stream, intn indent, fprintf (stream, "%*sFile Boot Block...\n", indent, ""); fprintf (stream, "%*s%-*s %s\n", indent, "", fwidth, - "Directory:", - f->dir); - fprintf (stream, "%*s%-*s %s\n", indent, "", fwidth, "File name:", - f->filename); + f->name); fprintf (stream, "%*s%-*s 0x%08x\n", indent, "", fwidth, - "Permissions", - (unsigned)(f->acc_perm)); + "Flags", + (unsigned)(f->shared->flags)); fprintf (stream, "%*s%-*s %u\n", indent, "", fwidth, "Reference count:", - (unsigned)(f->ref_count)); + (unsigned)(f->shared->nrefs)); fprintf (stream, "%*s%-*s 0x%08lx\n", indent, "", fwidth, "Consistency flags:", - (unsigned long)(f->consist_flags)); + (unsigned long)(f->shared->consist_flags)); fprintf (stream, "%*s%-*s %ld\n", indent, "", fwidth, "Small object heap address:", - (long)(f->smallobj_off)); + (long)(f->shared->smallobj_off)); fprintf (stream, "%*s%-*s %ld\n", indent, "", fwidth, "Free list address:", - (long)(f->freespace_off)); + (long)(f->shared->freespace_off)); fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth, "Logical file length:", - (unsigned long)(f->logical_len)); + (unsigned long)(f->shared->logical_len)); fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth, "Size of user block:", - (unsigned long)(f->file_create_parms.userblock_size)); + (unsigned long)(f->shared->file_create_parms.userblock_size)); fprintf (stream, "%*s%-*s %u\n", indent, "", fwidth, "Size of file size_t type:", - (unsigned)(f->file_create_parms.offset_size)); + (unsigned)(f->shared->file_create_parms.offset_size)); fprintf (stream, "%*s%-*s %u\n", indent, "", fwidth, "Size of file off_t type:", - (unsigned)(f->file_create_parms.length_size)); + (unsigned)(f->shared->file_create_parms.length_size)); fprintf (stream, "%*s%-*s %u\n", indent, "", fwidth, "Symbol table leaf node 1/2 rank:", - (unsigned)(f->file_create_parms.sym_leaf_k)); + (unsigned)(f->shared->file_create_parms.sym_leaf_k)); fprintf (stream, "%*s%-*s %u\n", indent, "", fwidth, "Symbol table internal node 1/2 rank:", - (unsigned)(f->file_create_parms.btree_k[H5B_SNODE_ID])); + (unsigned)(f->shared->file_create_parms.btree_k[H5B_SNODE_ID])); fprintf (stream, "%*s%-*s %u\n", indent, "", fwidth, "Boot block version number:", - (unsigned)(f->file_create_parms.bootblock_ver)); + (unsigned)(f->shared->file_create_parms.bootblock_ver)); fprintf (stream, "%*s%-*s %u\n", indent, "", fwidth, "Small object heap version number:", - (unsigned)(f->file_create_parms.smallobject_ver)); + (unsigned)(f->shared->file_create_parms.smallobject_ver)); fprintf (stream, "%*s%-*s %u\n", indent, "", fwidth, "Free list version number:", - (unsigned)(f->file_create_parms.freespace_ver)); + (unsigned)(f->shared->file_create_parms.freespace_ver)); fprintf (stream, "%*s%-*s %u\n", indent, "", fwidth, "Object directory version number:", - (unsigned)(f->file_create_parms.objectdir_ver)); + (unsigned)(f->shared->file_create_parms.objectdir_ver)); fprintf (stream, "%*s%-*s %u\n", indent, "", fwidth, "Shared header version number:", - (unsigned)(f->file_create_parms.sharedheader_ver)); + (unsigned)(f->shared->file_create_parms.sharedheader_ver)); fprintf (stream, "%*sRoot symbol table entry:\n", indent, ""); - H5G_ent_debug (f, f->root_sym, stream, indent+3, MAX(0, fwidth-3)); + H5G_ent_debug (f, f->shared->root_sym, stream, indent+3, MAX(0, fwidth-3)); FUNC_LEAVE (SUCCEED); } |