diff options
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, |