From c54ea2b9783c89554ab84cd48b5a6c689afe5e33 Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Sun, 13 Apr 2003 23:21:18 -0500 Subject: [svn-r6646] Purpose: Code cleanup, bug fix & new feature. Description: Moved some "package-scope" information out of the private header file and into the code module. (code cleanup). Fixed a few places where the "destroy but don't flush" code wasn't working correctly, which mostly affects the FPH5 effort. (bug fix). Added the ability to "unprotect" a metadata object and delete it at the same time. (new feature). Platforms tested: FreeBSD 4.8 (sleipnir) w/C++ Linux 2.4 (burrwhite) w/FORTRAN Solaris 2.7 (arabica) w/FORTRAN IRIX64 6.5 (modi4) w/parallel & FORTRAN (h5committest not run due to my ongoing difficulties with C++ on burrwhite). --- src/H5AC.c | 277 ++++++++++++++++++++++++++++++++++-------------------- src/H5ACprivate.h | 73 +++++--------- 2 files changed, 199 insertions(+), 151 deletions(-) diff --git a/src/H5AC.c b/src/H5AC.c index 1ab8ba6..ffdad6e 100644 --- a/src/H5AC.c +++ b/src/H5AC.c @@ -54,9 +54,6 @@ #include "H5FDmpio.h" #include "H5FDmpiposix.h" -/* - * Private file-scope variables. - */ #define PABLO_MASK H5AC_mask /* Interface initialization */ @@ -64,6 +61,55 @@ static int interface_initialize_g = 0; #define INTERFACE_INIT H5AC_init_interface static herr_t H5AC_init_interface(void); +/* + * Private macros + */ + +/* Hash an address in the file to an offset in the cache */ +#define H5AC_HASH_DIVISOR 8 /* Attempt to spread out the hashing */ + /* This should be the same size as the alignment of */ + /* of the smallest file format object written to the file. */ +#define H5AC_HASH(F,ADDR) H5F_addr_hash((ADDR/H5AC_HASH_DIVISOR),(F)->shared->cache->nslots) + +/* + * Private typedefs & structs + */ + +#ifdef H5AC_DEBUG +typedef struct H5AC_prot_t { + int nprots; /*number of things protected */ + int aprots; /*nelmts of `prot' array */ + H5AC_info_t **slot; /*array of pointers to protected things */ +} H5AC_prot_t; +#endif /* H5AC_DEBUG */ + +struct H5AC_t { + unsigned nslots; /*number of cache slots */ + H5AC_info_t **slot; /*the cache slots, an array of pointers to the cached objects */ + H5AC_info_t **dslot; /*"held object" cache slots, an array of pointers to dirty cached objects */ +#ifdef H5AC_DEBUG + H5AC_prot_t *prot; /*the protected slots */ +#endif /* H5AC_DEBUG */ + int nprots; /*number of protected objects */ +#ifdef H5AC_DEBUG + struct { + unsigned nhits; /*number of cache hits */ + unsigned nmisses; /*number of cache misses */ + unsigned ninits; /*number of cache inits */ + unsigned nflushes; /*number of flushes to disk */ +#ifdef H5_HAVE_PARALLEL + unsigned ndestroys; /*number of cache destroys */ + unsigned nholds; /*number of cache holds */ + unsigned nrestores; /*number of cache restores */ +#endif /* H5_HAVE_PARALLEL */ + } diagnostics[H5AC_NTYPES]; /*diagnostics for each type of object*/ +#endif /* H5AC_DEBUG */ +}; + +/* + * Private file-scope variables. + */ + /* Default dataset transfer property list for metadata I/O calls */ /* (Collective set, "block before metadata write" set and "library internal" set) */ /* (Global variable definition, declaration is in H5ACprivate.h also) */ @@ -717,11 +763,11 @@ H5AC_flush(H5F_t *f, hid_t dxpl_id, const H5AC_class_t *type, haddr_t addr, unsi { unsigned i; herr_t status; - H5AC_flush_func_t flush=NULL; + H5AC_flush_func_t flush=NULL; /* 'flush' callback for an object */ H5AC_info_t **info; int *map = NULL; - hbool_t destroy=(flags&H5F_FLUSH_INVALIDATE)>0; - hbool_t clear_only=(flags&H5F_FLUSH_CLEAR_ONLY)>0; + hbool_t destroy=(flags&H5F_FLUSH_INVALIDATE)>0; /* Flag for destroying objects */ + hbool_t clear_only=(flags&H5F_FLUSH_CLEAR_ONLY)>0; /* Flag for only clearing objects */ unsigned nslots; H5AC_t *cache; herr_t ret_value=SUCCEED; /* Return value */ @@ -828,12 +874,15 @@ H5AC_flush(H5F_t *f, hid_t dxpl_id, const H5AC_class_t *type, haddr_t addr, unsi H5AC_subid_t type_id=(*info)->type->id; /* Remember this for later */ #endif /* H5AC_DEBUG */ - flush = (*info)->type->flush; - /* Clear the dirty flag only, if requested */ - if(clear_only) - (*info)->dirty=0; + if(clear_only) { + /* Call the callback routine to clear all dirty flags for object */ + if(((*info)->type->clear)(*info)<0) + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to clear cache"); + } /* end if */ else { + flush = (*info)->type->flush; + /* Only block for all the processes on the first piece of metadata */ if(first_flush && (*info)->dirty) { status = (flush)(f, dxpl_id, destroy, (*info)->addr, (*info)); @@ -844,7 +893,7 @@ H5AC_flush(H5F_t *f, hid_t dxpl_id, const H5AC_class_t *type, haddr_t addr, unsi if (status < 0) HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush cache"); #ifdef H5AC_DEBUG - cache->diagnostics[type_id].nflushes++; + cache->diagnostics[type_id].nflushes++; #endif /* H5AC_DEBUG */ } /* end else */ @@ -925,8 +974,11 @@ H5AC_flush(H5F_t *f, hid_t dxpl_id, const H5AC_class_t *type, haddr_t addr, unsi */ /* Clear the dirty flag only, if requested */ - if(clear_only) - (*info)->dirty=0; + if(clear_only) { + /* Call the callback routine to clear all dirty flags for object */ + if(((*info)->type->clear)(*info)<0) + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to clear cache"); + } /* end if */ else { flush = (*info)->type->flush; if((flush)(f, dxpl_id, destroy, (*info)->addr, (*info)) < 0) @@ -1528,6 +1580,8 @@ done: * H5AC_protect(). The TYPE and ADDR arguments should be the * same as the corresponding call to H5AC_protect() and the * THING argument should be the value returned by H5AC_protect(). + * If the DELETED flag is set, then this object has been deleted + * from the file and should not be returned to the cache. * * If H5AC_DEBUG is defined then this function fails * if the TYPE and ADDR arguments are not what was used when the @@ -1542,10 +1596,13 @@ done: * Modifications: * Robb Matzke, 1999-07-27 * The ADDR argument is passed by value. + * + * Quincey Koziol, 2003-03-19 + * Added "deleted" argument *------------------------------------------------------------------------- */ herr_t -H5AC_unprotect(H5F_t *f, hid_t dxpl_id, const H5AC_class_t *type, haddr_t addr, void *thing) +H5AC_unprotect(H5F_t *f, hid_t dxpl_id, const H5AC_class_t *type, haddr_t addr, void *thing, hbool_t deleted) { unsigned idx; H5AC_flush_func_t flush; @@ -1568,125 +1625,139 @@ H5AC_unprotect(H5F_t *f, hid_t dxpl_id, const H5AC_class_t *type, haddr_t addr, cache = f->shared->cache; info = cache->slot + idx; +#ifdef H5AC_DEBUG + /* + * Remove the object's protect data to indicate that it is no longer + * protected. + */ + { + H5AC_prot_t *prot = NULL; + int found, i; + + prot = cache->prot + idx; + for (i = 0, found = FALSE; i < prot->nprots && !found; i++) { + if (H5F_addr_eq(addr, prot->slot[i]->addr)) { + assert(prot->slot[i]->type == type); + HDmemmove(prot->slot + i, prot->slot + i + 1, + ((prot->nprots - i) - 1) * sizeof(H5AC_info_t *)); + prot->nprots -= 1; + found = TRUE; + } + } + assert(found); + } +#endif /* H5AC_DEBUG */ + + /* Don't restore deleted objects to the cache */ + if(!deleted) { #ifdef H5_HAVE_PARALLEL - /* If MPIO, MPIPOSIX, or FPHDF5 is used, do special parallel I/O actions */ - if(IS_H5FD_MPIO(f) || IS_H5FD_MPIPOSIX(f) || IS_H5FD_FPHDF5(f)) { - H5AC_info_t **dinfo; - H5AC_subid_t type_id; - H5P_genplist_t *dxpl; /* Dataset transfer property list */ - H5FD_mpio_xfer_t xfer_mode; /* I/O transfer mode property value */ + /* If MPIO, MPIPOSIX, or FPHDF5 is used, do special parallel I/O actions */ + if(IS_H5FD_MPIO(f) || IS_H5FD_MPIPOSIX(f) || IS_H5FD_FPHDF5(f)) { + H5AC_info_t **dinfo; + H5AC_subid_t type_id; + H5P_genplist_t *dxpl; /* Dataset transfer property list */ + H5FD_mpio_xfer_t xfer_mode; /* I/O transfer mode property value */ - /* Get the dataset transfer property list */ - if (NULL == (dxpl = H5I_object(dxpl_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset creation property list"); + /* Get the dataset transfer property list */ + if (NULL == (dxpl = H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset creation property list"); - /* Get the transfer mode property */ - if(H5P_get(dxpl, H5D_XFER_IO_XFER_MODE_NAME, &xfer_mode) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't retrieve xfer mode"); + /* Get the transfer mode property */ + if(H5P_get(dxpl, H5D_XFER_IO_XFER_MODE_NAME, &xfer_mode) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't retrieve xfer mode"); - /* Get pointer to 'held' information */ - dinfo = cache->dslot + idx; + /* Get pointer to 'held' information */ + dinfo = cache->dslot + idx; - /* Sanity check transfer mode */ - if(xfer_mode==H5FD_MPIO_COLLECTIVE) { - /* Check for dirty metadata */ - if(*dinfo) { - H5AC_dest_func_t dest; + /* Sanity check transfer mode */ + if(xfer_mode==H5FD_MPIO_COLLECTIVE) { + /* Check for dirty metadata */ + if(*dinfo) { + H5AC_dest_func_t dest; - /* Various sanity checks */ - assert((*dinfo)->dirty); - assert((*info)!=NULL); - assert((*info)->dirty==0); + /* Various sanity checks */ + assert((*dinfo)->dirty); + assert((*info)!=NULL); + assert((*info)->dirty==0); - type_id=(*info)->type->id; /* Remember this for later */ + type_id=(*info)->type->id; /* Remember this for later */ - /* Destroy 'current' information */ - dest = (*info)->type->dest; - if ((dest)(f, (*info))<0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTFREE, FAIL, "unable to free cached object"); + /* Destroy 'current' information */ + dest = (*info)->type->dest; + if ((dest)(f, (*info))<0) + HGOTO_ERROR(H5E_CACHE, H5E_CANTFREE, FAIL, "unable to free cached object"); - /* Restore 'held' information back to 'current' information */ - (*info)=(*dinfo); + /* Restore 'held' information back to 'current' information */ + (*info)=(*dinfo); - /* Clear 'held' information */ - (*dinfo)=NULL; + /* Clear 'held' information */ + (*dinfo)=NULL; #ifdef H5AC_DEBUG - cache->diagnostics[type_id].nrestores++; + cache->diagnostics[type_id].nrestores++; #endif /* H5AC_DEBUG */ + } /* end if */ } /* end if */ - } /* end if */ - else { - /* Sanity check */ - assert((*dinfo)==NULL); - assert(xfer_mode==H5FD_MPIO_INDEPENDENT); + else { + /* Sanity check */ + assert((*dinfo)==NULL); + assert(xfer_mode==H5FD_MPIO_INDEPENDENT); - /* Make certain there will be no write of dirty metadata */ - if((*info) && (*info)->dirty) { - /* Sanity check new item */ - assert(((H5AC_info_t*)thing)->dirty==0); + /* Make certain there will be no write of dirty metadata */ + if((*info) && (*info)->dirty) { + /* Sanity check new item */ + assert(((H5AC_info_t*)thing)->dirty==0); - /* 'Hold' the current metadata for later */ - (*dinfo)=(*info); + /* 'Hold' the current metadata for later */ + (*dinfo)=(*info); - /* Reset the 'current' metadata, so it doesn't get flushed */ - (*info)=NULL; + /* Reset the 'current' metadata, so it doesn't get flushed */ + (*info)=NULL; #ifdef H5AC_DEBUG - cache->diagnostics[(*dinfo)->type->id].nholds++; + cache->diagnostics[(*dinfo)->type->id].nholds++; #endif /* H5AC_DEBUG */ - } /* end if */ - } /* end else */ - } /* end if */ + } /* end if */ + } /* end else */ + } /* end if */ #endif /* H5_HAVE_PARALLEL */ - /* - * Flush any object already in the cache at that location. It had - * better not be another copy of the protected object. - */ - if (*info) { + /* + * Flush any object already in the cache at that location. It had + * better not be another copy of the protected object. + */ + if (*info) { #ifdef H5AC_DEBUG - H5AC_subid_t type_id=(*info)->type->id; /* Remember this for later */ + H5AC_subid_t type_id=(*info)->type->id; /* Remember this for later */ #endif /* H5AC_DEBUG */ - assert(H5F_addr_ne((*info)->addr, addr)); - flush = (*info)->type->flush; - if ((flush)(f, dxpl_id, TRUE, (*info)->addr, (*info)) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush object"); + assert(H5F_addr_ne((*info)->addr, addr)); + flush = (*info)->type->flush; + if ((flush)(f, dxpl_id, TRUE, (*info)->addr, (*info)) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush object"); #ifdef H5AC_DEBUG - cache->diagnostics[type_id].nflushes++; + cache->diagnostics[type_id].nflushes++; #endif /* H5AC_DEBUG */ - } + } -#ifdef H5AC_DEBUG - /* - * Remove the object's protect data to indicate that it is no longer - * protected. - */ - { - H5AC_prot_t *prot = NULL; - int found, i; + /* + * Insert the object back into the cache; it is no longer protected. + */ + (*info)=thing; + (*info)->type = type; + (*info)->addr = addr; + } /* end if */ + else { + /* Mark the thing as clean (prerequite for destroy routine) */ + if((type->clear)(thing)<0) + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to clear object"); - prot = cache->prot + idx; - for (i = 0, found = FALSE; i < prot->nprots && !found; i++) { - if (H5F_addr_eq(addr, prot->slot[i]->addr)) { - assert(prot->slot[i]->type == type); - HDmemmove(prot->slot + i, prot->slot + i + 1, - ((prot->nprots - i) - 1) * sizeof(H5AC_info_t *)); - prot->nprots -= 1; - found = TRUE; - } - } - assert(found); - } -#endif /* H5AC_DEBUG */ + /* Destroy previously cached thing */ + if ((type->dest)(f, thing)<0) + HGOTO_ERROR(H5E_CACHE, H5E_CANTFREE, FAIL, "unable to free object"); + } /* end else */ - /* - * Insert the object back into the cache; it is no longer protected. - */ - (*info)=thing; - (*info)->type = type; - (*info)->addr = addr; + /* Decrement the number of protected items outstanding */ cache->nprots -= 1; done: diff --git a/src/H5ACprivate.h b/src/H5ACprivate.h index d1edf7c..06e3a27 100644 --- a/src/H5ACprivate.h +++ b/src/H5ACprivate.h @@ -45,16 +45,6 @@ # undef H5AC_DEBUG #endif -/* Dataset transfer property list for flush calls */ -/* (Collective set, "block before metadata write" set and "library internal" set) */ -/* (Global variable declaration, definition is in H5AC.c) */ -extern hid_t H5AC_dxpl_id; - -/* Dataset transfer property list for independent metadata I/O calls */ -/* (just "library internal" set - i.e. independent transfer mode) */ -/* (Global variable declaration, definition is in H5AC.c) */ -extern hid_t H5AC_ind_dxpl_id; - /* * Class methods pertaining to caching. Each type of cached object will * have a constant variable with permanent life-span that describes how @@ -68,7 +58,12 @@ extern hid_t H5AC_ind_dxpl_id; * wise for the data structure to include dirty flags to * indicate whether it really needs to be written. This * function is also responsible for freeing memory allocated - * by the LOAD method if the DEST argument is non-zero. + * by the LOAD method if the DEST argument is non-zero (by + * calling the DEST method). + * + * DEST: Just frees memory allocated by the LOAD method. + * + * CLEAR: Just marks object as non-dirty. */ typedef enum H5AC_subid_t { H5AC_BT_ID = 0, /*B-tree nodes */ @@ -82,12 +77,14 @@ typedef enum H5AC_subid_t { typedef void *(*H5AC_load_func_t)(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *udata1, void *udata2); typedef herr_t (*H5AC_flush_func_t)(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr, void *thing); typedef herr_t (*H5AC_dest_func_t)(H5F_t *f, void *thing); +typedef herr_t (*H5AC_clear_func_t)(void *thing); typedef struct H5AC_class_t { H5AC_subid_t id; - H5AC_load_func_t load; - H5AC_flush_func_t flush; + H5AC_load_func_t load; + H5AC_flush_func_t flush; H5AC_dest_func_t dest; + H5AC_clear_func_t clear; } H5AC_class_t; /* @@ -96,10 +93,6 @@ typedef struct H5AC_class_t { * own cache, an array of slots. */ #define H5AC_NSLOTS 10330 /* The library "likes" this number... */ -#define H5AC_HASH_DIVISOR 8 /* Attempt to spread out the hashing */ - /* This should be the same size as the alignment of */ - /* of the smallest file format object written to the file. */ -#define H5AC_HASH(F,ADDR) H5F_addr_hash((ADDR/H5AC_HASH_DIVISOR),(F)->shared->cache->nslots) typedef struct H5AC_info_t { const H5AC_class_t *type; /*type of object stored here */ @@ -108,37 +101,11 @@ typedef struct H5AC_info_t { } H5AC_info_t; typedef H5AC_info_t *H5AC_info_ptr_t; /* Typedef for free lists */ -#ifdef H5AC_DEBUG -typedef struct H5AC_prot_t { - int nprots; /*number of things protected */ - int aprots; /*nelmts of `prot' array */ - H5AC_info_t **slot; /*array of pointers to protected things */ -} H5AC_prot_t; -#endif /* H5AC_DEBUG */ - -typedef struct H5AC_t { - unsigned nslots; /*number of cache slots */ - H5AC_info_t **slot; /*the cache slots, an array of pointers to the cached objects */ - H5AC_info_t **dslot; /*"held object" cache slots, an array of pointers to dirty cached objects */ -#ifdef H5AC_DEBUG - H5AC_prot_t *prot; /*the protected slots */ -#endif /* H5AC_DEBUG */ - int nprots; /*number of protected objects */ -#ifdef H5AC_DEBUG - struct { - unsigned nhits; /*number of cache hits */ - unsigned nmisses; /*number of cache misses */ - unsigned ninits; /*number of cache inits */ - unsigned nflushes; /*number of flushes to disk */ -#ifdef H5_HAVE_PARALLEL - unsigned ndestroys; /*number of cache destroys */ - unsigned nholds; /*number of cache holds */ - unsigned nrestores; /*number of cache restores */ -#endif /* H5_HAVE_PARALLEL */ - } diagnostics[H5AC_NTYPES]; /*diagnostics for each type of object*/ -#endif /* H5AC_DEBUG */ -} H5AC_t; +/* Typedef for metadata cache (defined in H5AC.c) */ +typedef struct H5AC_t H5AC_t; +/* Metadata specific properties for FAPL */ +/* (Only used for parallel I/O) */ #ifdef H5_HAVE_PARALLEL /* Definitions for "block before metadata write" property */ #define H5AC_BLOCK_BEFORE_META_WRITE_NAME "H5AC_block_before_meta_write" @@ -151,6 +118,16 @@ typedef struct H5AC_t { #define H5AC_LIBRARY_INTERNAL_DEF 0 #endif /* H5_HAVE_PARALLEL */ +/* Dataset transfer property list for flush calls */ +/* (Collective set, "block before metadata write" set and "library internal" set) */ +/* (Global variable declaration, definition is in H5AC.c) */ +extern hid_t H5AC_dxpl_id; + +/* Dataset transfer property list for independent metadata I/O calls */ +/* (just "library internal" set - i.e. independent transfer mode) */ +/* (Global variable declaration, definition is in H5AC.c) */ +extern hid_t H5AC_ind_dxpl_id; + /* * Library prototypes. */ @@ -161,7 +138,7 @@ H5_DLL herr_t H5AC_set(H5F_t *f, hid_t dxpl_id, const H5AC_class_t *type, haddr_ H5_DLL void *H5AC_protect(H5F_t *f, hid_t dxpl_id, const H5AC_class_t *type, haddr_t addr, const void *udata1, void *udata2); H5_DLL herr_t H5AC_unprotect(H5F_t *f, hid_t dxpl_id, const H5AC_class_t *type, haddr_t addr, - void *thing); + void *thing, hbool_t deleted); H5_DLL void *H5AC_find(H5F_t *f, hid_t dxpl_id, const H5AC_class_t *type, haddr_t addr, const void *udata1, void *udata2); H5_DLL herr_t H5AC_flush(H5F_t *f, hid_t dxpl_id, const H5AC_class_t *type, haddr_t addr, -- cgit v0.12