diff options
author | Robb Matzke <matzke@llnl.gov> | 1998-04-03 21:11:05 (GMT) |
---|---|---|
committer | Robb Matzke <matzke@llnl.gov> | 1998-04-03 21:11:05 (GMT) |
commit | 92571bbe1d77c74ddefeeba6ac0b2097593c058d (patch) | |
tree | 610c3a65c2d3fa5dabfda39635770029bb734646 /src | |
parent | a780cdd178f849afbc8cbb24e416eef733cbc9f2 (diff) | |
download | hdf5-92571bbe1d77c74ddefeeba6ac0b2097593c058d.zip hdf5-92571bbe1d77c74ddefeeba6ac0b2097593c058d.tar.gz hdf5-92571bbe1d77c74ddefeeba6ac0b2097593c058d.tar.bz2 |
[svn-r336] Changes since 19980402
----------------------
./MANIFEST
./test/Makefile.in
./test/shtype.c [NEW]
Added some tests for shared data types.
./configure.in
Removed MF and HL from the default debug list since. MF
because it hasn't been implemented yet and HL because it
produces lots of annoying messages about adjusting the size of
local heaps.
./src/H5F.c
./src/H5T.c
./src/H5Tprivate.h
Fixed a bug with opening the same file twice. The first close
on the file_id incorrectly closed shared data structs.
Closing a file now correctly unshares data types that might be
pointing into that file.
./src/H5T.c
./src/H5Tpublic.h
Added an H5Tis_shared(). The caller supplies a file and a
data type and the function returns true if the data type is
currently marked for sharing in that file.
./src/H5AC.c
./src/H5F.c
./src/H5HL.c
./src/H5HG.c
./src/H5MF.c
./src/H5O.c
We now detect errors sooner when writing to a read-only
file. In the past, the error might not show up until the
cached item was flushed, and it was sometimes possible to not
even get an error!
./src/H5I.c
./src/H5Iprivate.h
If the search function fails then H5I_search() returns
failure. Also, the first argument for the search function
isn't const anymore because we might want the search to have
side effects (like calling H5T_unshare() for all shared data
types whose file just closed).
Diffstat (limited to 'src')
-rw-r--r-- | src/H5AC.c | 2 | ||||
-rw-r--r-- | src/H5F.c | 71 | ||||
-rw-r--r-- | src/H5HG.c | 13 | ||||
-rw-r--r-- | src/H5HL.c | 14 | ||||
-rw-r--r-- | src/H5I.c | 7 | ||||
-rw-r--r-- | src/H5Iprivate.h | 2 | ||||
-rw-r--r-- | src/H5MF.c | 5 | ||||
-rw-r--r-- | src/H5O.c | 12 | ||||
-rw-r--r-- | src/H5T.c | 92 | ||||
-rw-r--r-- | src/H5Tprivate.h | 1 | ||||
-rw-r--r-- | src/H5Tpublic.h | 1 |
11 files changed, 191 insertions, 29 deletions
@@ -399,7 +399,7 @@ H5AC_flush(H5F_t *f, const H5AC_class_t *type, const haddr_t *addr, if (status < 0) { map = H5MM_xfree(map); HRETURN_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, - "can't flush cache"); + "unable to flush cache"); } cache->diagnostics[slot->type->id].nflushes++; if (destroy) @@ -44,6 +44,7 @@ static char RcsId[] = "@(#)$Revision$"; #include <H5Gprivate.h> /*symbol tables */ #include <H5MMprivate.h> /*core memory management */ #include <H5Pprivate.h> /*property lists */ +#include <H5Tprivate.h> /*data types */ #include <ctype.h> #include <sys/types.h> @@ -97,7 +98,7 @@ static void H5F_term_interface(void); /* PRIVATE PROTOTYPES */ static H5F_t *H5F_new(H5F_file_t *shared); -static H5F_t *H5F_dest(H5F_t *f); +static herr_t H5F_dest(H5F_t *f); static herr_t H5F_flush(H5F_t *f, hbool_t invalidate); static herr_t H5F_locate_signature(H5F_low_t *f_handle, const H5F_access_t *access_parms, @@ -342,7 +343,7 @@ H5Fget_access_template (hid_t file_id) keys. --------------------------------------------------------------------------*/ static intn -H5F_compare_files(const void * _obj, const void * _key) +H5F_compare_files(void * _obj, const void * _key) { const H5F_t *obj = (const H5F_t *) _obj; const H5F_search_t *key = (const H5F_search_t *) _key; @@ -510,16 +511,14 @@ H5F_new(H5F_file_t *shared) /*------------------------------------------------------------------------- * Function: H5F_dest * - * Purpose: Destroys a file structure. This function does not flush - * the cache or anything else; it only frees memory associated - * with the file struct. The shared info for the file is freed + * Purpose: Destroys a file structure. This function flushes the cache + * but doesn't do any other cleanup other than freeing memory + * for the file struct. The shared info for the file is freed * only when its reference count reaches zero. * - * Errors: - * - * Return: Success: NULL + * Return: Success: SUCCEED * - * Failure: NULL + * Failure: FAIL * * Programmer: Robb Matzke * matzke@llnl.gov @@ -529,22 +528,28 @@ H5F_new(H5F_file_t *shared) * *------------------------------------------------------------------------- */ -static H5F_t * +static herr_t H5F_dest(H5F_t *f) { - FUNC_ENTER(H5F_dest, NULL); + herr_t ret_value = SUCCEED; + + FUNC_ENTER(H5F_dest, FAIL); if (f) { if (0 == --(f->shared->nrefs)) { /* Do not close the root group since we didn't count it */ - H5AC_dest(f); + if (H5AC_dest(f)) { + HERROR (H5E_FILE, H5E_CANTINIT, "problems closing file"); + ret_value = FAIL; /*but keep going*/ + } f->shared = H5MM_xfree(f->shared); } f->name = H5MM_xfree(f->name); H5MM_xfree(f); } - FUNC_LEAVE(NULL); + FUNC_LEAVE(ret_value); } + /*------------------------------------------------------------------------- * Function: H5F_open @@ -1242,7 +1247,7 @@ H5F_flush(H5F_t *f, hbool_t 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"); + HRETURN_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush cache"); } /* encode the file boot block */ @@ -1312,8 +1317,9 @@ H5F_close(H5F_t *f) while (H5G_pop(f)>=0) /*void*/; /* Flush the boot block and caches */ - if (H5F_flush(f, TRUE) < 0) { - HRETURN_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "can't flush cache"); + if (H5F_flush(f, FALSE) < 0) { + HRETURN_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, + "unable to flush cache"); } /* @@ -1336,14 +1342,31 @@ H5F_close(H5F_t *f) fprintf(stderr, "H5F: H5F_close: operation completed\n"); #endif } + + /* Invalidate shared data types since they depend on the H5F_t pointer */ + H5I_search (H5_DATATYPE, H5T_invalidate_cb, f); - /* Dump debugging info */ - if (f->intent & H5F_ACC_DEBUG) H5AC_debug(f); + /* + * If this is the last reference to the shared part of the file then + * close it also. + */ + if (1==f->shared->nrefs) { + /* Flush again just to be safe, but this time clean up the cache */ + if (H5F_flush (f, TRUE)<0) { + HRETURN_ERROR (H5E_CACHE, H5E_CANTFLUSH, FAIL, + "unable to flush cache"); + } - /* Close files and release resources */ - H5F_low_close(f->shared->lf, &(f->shared->access_parms)); - f = H5F_dest(f); + /* Dump debugging info */ + if (f->intent & H5F_ACC_DEBUG) H5AC_debug(f); + /* Close files and release resources */ + H5F_low_close(f->shared->lf, &(f->shared->access_parms)); + } + if (H5F_dest(f)<0) { + HRETURN_ERROR (H5E_FILE, H5E_CANTINIT, FAIL, + "problems closing file"); + } FUNC_LEAVE(SUCCEED); } @@ -1400,8 +1423,10 @@ H5Fclose(hid_t fid) * Decrement reference count on atom. When it reaches zero the file will * be closed. */ - H5I_dec_ref (fid); - + if (H5I_dec_ref (fid)<0) { + HGOTO_ERROR (H5E_ATOM, H5E_CANTINIT, FAIL, "problems closing file"); + } + done: FUNC_LEAVE(ret_value < 0 ? FAIL : SUCCEED); } @@ -488,6 +488,11 @@ H5HG_insert (H5F_t *f, size_t size, void *obj, H5HG_t *hobj/*out*/) assert (0==size || obj); assert (hobj); + if (0==(f->intent & H5F_ACC_RDWR)) { + HRETURN_ERROR (H5E_HEAP, H5E_WRITEERROR, FAIL, + "no write intent on file"); + } + /* Find a large enough collection on the CWFS list */ need = size + H5HG_SIZEOF_OBJHDR (f); for (cwfsno=0; cwfsno<f->shared->ncwfs; cwfsno++) { @@ -692,6 +697,10 @@ H5HG_link (H5F_t *f, H5HG_t *hobj, intn adjust) /* Check args */ assert (f); assert (hobj); + if (0==(f->intent & H5F_ACC_RDWR)) { + HRETURN_ERROR (H5E_HEAP, H5E_WRITEERROR, FAIL, + "no write intent on file"); + } /* Load the heap */ if (NULL==(heap=H5AC_find (f, H5AC_GHEAP, &(hobj->addr), NULL, NULL))) { @@ -743,6 +752,10 @@ H5HG_remove (H5F_t *f, H5HG_t *hobj) /* Check args */ assert (f); assert (hobj); + if (0==(f->intent & H5F_ACC_RDWR)) { + HRETURN_ERROR (H5E_HEAP, H5E_WRITEERROR, FAIL, + "no write intent on file"); + } /* Load the heap */ if (NULL==(heap=H5AC_find (f, H5AC_GHEAP, &(hobj->addr), NULL, NULL))) { @@ -537,6 +537,10 @@ H5HL_insert(H5F_t *f, const haddr_t *addr, size_t buf_size, const void *buf) assert(addr && H5F_addr_defined(addr)); assert(buf_size > 0); assert(buf); + if (0==(f->intent & H5F_ACC_RDWR)) { + HRETURN_ERROR (H5E_HEAP, H5E_WRITEERROR, (size_t)(-1), + "no write intent on file"); + } if (NULL == (heap = H5AC_find(f, H5AC_LHEAP, addr, NULL, NULL))) { HRETURN_ERROR(H5E_HEAP, H5E_CANTLOAD, (size_t)(-1), @@ -686,6 +690,10 @@ H5HL_write(H5F_t *f, const haddr_t *addr, size_t offset, size_t size, assert(addr && H5F_addr_defined(addr)); assert(buf); assert (offset==H5HL_ALIGN (offset)); + if (0==(f->intent & H5F_ACC_RDWR)) { + HRETURN_ERROR (H5E_HEAP, H5E_WRITEERROR, FAIL, + "no write intent on file"); + } if (NULL == (heap = H5AC_find(f, H5AC_LHEAP, addr, NULL, NULL))) { HRETURN_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, @@ -741,8 +749,12 @@ H5HL_remove(H5F_t *f, const haddr_t *addr, size_t offset, size_t size) assert(addr && H5F_addr_defined(addr)); assert(size > 0); assert (offset==H5HL_ALIGN (offset)); - size = H5HL_ALIGN (size); + if (0==(f->intent & H5F_ACC_RDWR)) { + HRETURN_ERROR (H5E_HEAP, H5E_WRITEERROR, FAIL, + "no write intent on file"); + } + size = H5HL_ALIGN (size); if (NULL == (heap = H5AC_find(f, H5AC_LHEAP, addr, NULL, NULL))) { HRETURN_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load heap"); @@ -640,7 +640,12 @@ H5I_dec_ref(hid_t id) * call the user's 'free' function for the atom's information, * otherwise just leak memory. */ - if (grp_ptr->free_func) (grp_ptr->free_func)(obj); + if (grp_ptr->free_func) { + if ((grp_ptr->free_func)(obj)<0) { + HRETURN_ERROR (H5E_ATOM, H5E_CANTINIT, FAIL, + "unable to free atom"); + } + } } ret_value = SUCCEED; } diff --git a/src/H5Iprivate.h b/src/H5Iprivate.h index c339390..45f9e85 100644 --- a/src/H5Iprivate.h +++ b/src/H5Iprivate.h @@ -89,7 +89,7 @@ typedef struct { } H5I_id_group_t; /* Type of the function to compare objects & keys */ -typedef intn (*H5I_search_func_t) (const void * obj, const void * key); +typedef intn (*H5I_search_func_t) (void * obj, const void * key); /* Private Functions in H5I.c */ intn H5I_init_group (H5I_group_t grp, intn hash_size, uintn reserved, @@ -63,6 +63,11 @@ H5MF_alloc(H5F_t *f, intn op, size_t size, haddr_t *addr /*out */ ) assert(size > 0); assert(addr); + /* Fail if we don't have write access */ + if (0==(f->intent & H5F_ACC_RDWR)) { + HRETURN_ERROR (H5E_RESOURCE, H5E_CANTINIT, FAIL, "file is read-only"); + } + /* * Eventually we'll maintain a free list(s) and try to satisfy requests * from there. But for now we just allocate more memory from the end of @@ -694,6 +694,10 @@ H5O_link(H5G_entry_t *ent, intn adjust) assert(ent); assert(ent->file); assert(H5F_addr_defined(&(ent->header))); + if (0==(ent->file->intent & H5F_ACC_RDWR)) { + HGOTO_ERROR (H5E_OHDR, H5E_WRITEERROR, FAIL, + "no write intent on file"); + } /* get header */ if (NULL == (oh = H5AC_protect(ent->file, H5AC_OHDR, &(ent->header), @@ -967,6 +971,10 @@ H5O_modify(H5G_entry_t *ent, const H5O_class_t *type, intn overwrite, assert(type); assert(mesg); assert (0==(flags & ~H5O_FLAG_BITS)); + if (0==(ent->file->intent & H5F_ACC_RDWR)) { + HGOTO_ERROR (H5E_OHDR, H5E_WRITEERROR, FAIL, + "no write intent on file"); + } if (NULL == (oh = H5AC_protect(ent->file, H5AC_OHDR, &(ent->header), NULL, NULL))) { @@ -1102,6 +1110,10 @@ H5O_remove(H5G_entry_t *ent, const H5O_class_t *type, intn sequence) assert(ent->file); assert(H5F_addr_defined(&(ent->header))); assert(type); + if (0==(ent->file->intent & H5F_ACC_RDWR)) { + HRETURN_ERROR (H5E_HEAP, H5E_WRITEERROR, FAIL, + "no write intent on file"); + } /* load the object header */ if (NULL == (oh = H5AC_protect(ent->file, H5AC_OHDR, &(ent->header), @@ -12,8 +12,9 @@ static char RcsId[] = "@(#)$Revision$"; #define H5T_PACKAGE /*suppress error about including H5Tpkg */ #include <H5private.h> /*generic functions */ -#include <H5Iprivate.h> /*ID functions */ -#include <H5Eprivate.h> /*error handling */ +#include <H5Iprivate.h> /*ID functions */ +#include <H5Eprivate.h> /*error handling */ +#include <H5Gprivate.h> /*groups */ #include <H5HGprivate.h> /*global heap */ #include <H5MMprivate.h> /*memory management */ #include <H5Sprivate.h> /*data space */ @@ -2206,6 +2207,50 @@ H5Tshare (hid_t loc_id, hid_t type_id) /*------------------------------------------------------------------------- + * Function: H5Tis_shared + * + * Purpose: Determines if a data type is shared in the specified file. + * The TYPE_ID is the type in question and LOC_ID is a file id + * or group id (a group id is used only to identify the file). + * + * Return: Success: TRUE or FALSE + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Friday, April 3, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +hbool_t +H5Tis_shared (hid_t loc_id, hid_t type_id) +{ + H5G_t *loc = NULL; + H5T_t *dt = NULL; + hbool_t ret_value = FAIL; + + FUNC_ENTER (H5Tis_shared, FAIL); + + /* Check arguments */ + if (NULL==(loc=H5G_loc (loc_id))) { + HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a location"); + } + if (H5_DATATYPE!=H5I_group (type_id) || + NULL==(dt=H5I_object (type_id))) { + HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); + } + + /* Is it sharable */ + ret_value = (H5HG_defined (&(dt->sh_heap)) && + dt->sh_file->shared==H5G_fileof(loc)->shared) ? TRUE : FALSE; + + FUNC_LEAVE (ret_value); +} + + +/*------------------------------------------------------------------------- * Function: H5Tregister_hard * * Purpose: Register a hard conversion function for a data type @@ -2771,6 +2816,49 @@ H5T_unshare (H5T_t *dt) /*------------------------------------------------------------------------- + * Function: H5T_invalidate_cb + * + * Purpose: This is a callback function for H5I_search(). When a file is + * closed we scan through the data type list and invalidate + * shared info for all types that have sharing enabled for the + * specified file. This insures that we don't having dangling + * pointers from data types to files. We have to do this with + * data types but not datasets because a dataset_id always + * corresponds to an open object header which prevents the file + * from closing in the first place, but a data type can exist + * independent of a file and doesn't have an object header. + * + * Return: Success: 0, this function never returns a non-zero + * value because that would terminate + * H5I_search(). + * + * Failure: 0 + * + * Programmer: Robb Matzke + * Friday, April 3, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +intn +H5T_invalidate_cb (void *obj, const void *call_data) +{ + H5T_t *dt = (H5T_t *)obj; + const H5F_t *f = (const H5F_t*)call_data; /*used only for comparison*/ + + FUNC_ENTER (H5T_invalidate, 0); + + if (H5HG_defined (&(dt->sh_heap)) && dt->sh_file->shared==f->shared) { + H5T_unshare (dt); + H5E_clear (); + } + + FUNC_LEAVE (0); +} + + +/*------------------------------------------------------------------------- * Function: H5T_is_atomic * * Purpose: Determines if a data type is an atomic type. diff --git a/src/H5Tprivate.h b/src/H5Tprivate.h index 27d27f3..ea80fcb 100644 --- a/src/H5Tprivate.h +++ b/src/H5Tprivate.h @@ -34,6 +34,7 @@ H5T_t *H5T_copy (const H5T_t *old_dt); herr_t H5T_close (H5T_t *dt); herr_t H5T_share (H5F_t *f, H5T_t *dt); herr_t H5T_unshare (H5T_t *dt); +intn H5T_invalidate_cb (void *obj, const void *call_data); size_t H5T_get_size (const H5T_t *dt); intn H5T_cmp (const H5T_t *dt1, const H5T_t *dt2); hbool_t H5T_is_atomic (const H5T_t *dt); diff --git a/src/H5Tpublic.h b/src/H5Tpublic.h index f362cdf..60a0311 100644 --- a/src/H5Tpublic.h +++ b/src/H5Tpublic.h @@ -185,6 +185,7 @@ herr_t H5Tclose (hid_t type_id); hbool_t H5Tequal (hid_t type1_id, hid_t type2_id); herr_t H5Tlock (hid_t type_id); herr_t H5Tshare (hid_t location_id, hid_t type_id); +hbool_t H5Tis_shared (hid_t location_id, hid_t type_id); /* Operations defined on compound data types */ herr_t H5Tinsert (hid_t parent_id, const char *name, off_t offset, |