summaryrefslogtreecommitdiffstats
path: root/src/H5F.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5F.c')
-rw-r--r--src/H5F.c1120
1 files changed, 679 insertions, 441 deletions
diff --git a/src/H5F.c b/src/H5F.c
index d2979fa..8b66d9b 100644
--- a/src/H5F.c
+++ b/src/H5F.c
@@ -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);
}