summaryrefslogtreecommitdiffstats
path: root/src/H5AC.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5AC.c')
-rw-r--r--src/H5AC.c1561
1 files changed, 458 insertions, 1103 deletions
diff --git a/src/H5AC.c b/src/H5AC.c
index 4fe9e73..dced1ab 100644
--- a/src/H5AC.c
+++ b/src/H5AC.c
@@ -31,6 +31,14 @@
* Quincey Koziol, 22 Apr 2000
* Turned on "H5AC_SORT_BY_ADDR"
*
+ * John Mainzer, 5/19/04
+ * Complete redesign and rewrite. See the header comments for
+ * H5AC_t for an overview of what is going on.
+ *
+ * John Mainzer, 6/4/04
+ * Factored the new cache code into a separate file (H5C.c) to
+ * facilitate re-use. Re-worked this file again to use H5C.
+ *
*-------------------------------------------------------------------------
*/
@@ -46,9 +54,7 @@
#include "H5Eprivate.h" /* Error handling */
#include "H5Fpkg.h" /* Files */
#include "H5FDprivate.h" /* File drivers */
-#include "H5FLprivate.h" /* Free Lists */
#include "H5Iprivate.h" /* IDs */
-#include "H5MMprivate.h" /* Memory management */
#include "H5Pprivate.h" /* Property lists */
/* Interface initialization */
@@ -57,51 +63,6 @@ static int interface_initialize_g = 0;
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.
*/
@@ -120,21 +81,14 @@ static hid_t H5AC_noblock_dxpl_id=(-1);
/* (Global variable definition, declaration is in H5ACprivate.h also) */
hid_t H5AC_ind_dxpl_id=(-1);
-static H5AC_t *current_cache_g = NULL; /*for sorting */
-
-/* Declare a free list to manage the H5AC_t struct */
-H5FL_DEFINE_STATIC(H5AC_t);
-/* Declare a PQ free list to manage the cache mapping array information */
-H5FL_SEQ_DEFINE_STATIC(int);
-
-/* Declare a PQ free list to manage the cache slot array information */
-H5FL_SEQ_DEFINE_STATIC(H5AC_info_ptr_t);
+/*
+ * Private file-scope function declarations:
+ */
-#ifdef H5AC_DEBUG
-/* Declare a PQ free list to manage the protected slot array information */
-H5FL_SEQ_DEFINE_STATIC(H5AC_prot_t);
-#endif /* H5AC_DEBUG */
+static herr_t H5AC_check_if_write_permitted(H5F_t *f,
+ hid_t dxpl_id,
+ hbool_t * write_permitted_ptr);
/*-------------------------------------------------------------------------
@@ -158,11 +112,11 @@ H5AC_init(void)
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5AC_init, FAIL);
+ FUNC_ENTER_NOAPI(H5AC_init, FAIL)
/* FUNC_ENTER() does all the work */
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -315,10 +269,10 @@ H5AC_term_interface(void)
n = 1; /* H5I */
/* Close H5AC dxpl */
- if (H5Pclose(H5AC_dxpl_id) < 0 ||
- H5Pclose(H5AC_noblock_dxpl_id) < 0 ||
- H5Pclose(H5AC_ind_dxpl_id) < 0)
- H5E_clear(); /*ignore the error*/
+ if (H5I_dec_ref(H5AC_dxpl_id) < 0 ||
+ H5I_dec_ref(H5AC_noblock_dxpl_id) < 0 ||
+ H5I_dec_ref(H5AC_ind_dxpl_id) < 0)
+ H5E_clear(); /*ignore error*/
else {
/* Reset static IDs */
H5AC_dxpl_id=(-1);
@@ -363,52 +317,82 @@ H5AC_term_interface(void)
*
* Modifications:
*
+ * Complete re-design and re-write to support the re-designed
+ * metadata cache.
+ *
+ * At present, the size_hint is ignored, and the
+ * max_cache_size and min_clean_size fields are hard
+ * coded. This should be fixed, but a parameter
+ * list change will be required, so I will leave it
+ * for now.
+ *
+ * Since no-one seems to care, the function now returns
+ * one on success.
+ * JRM - 4/28/04
+ *
+ * Reworked the function again after abstracting its guts to
+ * the similar function in H5C.c. The function is now a
+ * wrapper for H5C_create().
+ * JRM - 6/4/04
*-------------------------------------------------------------------------
*/
+
+const char * H5AC_entry_type_names[H5AC_NTYPES] =
+{
+ "B-tree nodes",
+ "symbol table nodes",
+ "local heaps",
+ "global heaps",
+ "object headers"
+};
+
int
-H5AC_create(H5F_t *f, int size_hint)
+H5AC_create(const H5F_t *f, int UNUSED size_hint)
{
- H5AC_t *cache = NULL;
- int ret_value; /* Return value */
+ H5AC_t *cache = NULL;
+ int ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5AC_create, FAIL);
+ FUNC_ENTER_NOAPI(H5AC_create, FAIL)
- assert(f);
- assert(NULL == f->shared->cache);
- if (size_hint < 1) size_hint = H5AC_NSLOTS;
-
- if (NULL==(f->shared->cache = cache = H5FL_CALLOC(H5AC_t)))
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed");
- cache->nslots = size_hint;
- if (NULL==( cache->slot = H5FL_SEQ_CALLOC(H5AC_info_ptr_t,cache->nslots)))
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed");
- if (NULL==( cache->dslot = H5FL_SEQ_CALLOC(H5AC_info_ptr_t,cache->nslots)))
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed");
-#ifdef H5AC_DEBUG
- if ((cache->prot = H5FL_SEQ_CALLOC(H5AC_prot_t,cache->nslots))==NULL)
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed");
-#endif /* H5AC_DEBUG */
+ HDassert(f);
+ HDassert(NULL == f->shared->cache);
- /* Set return value */
- ret_value=size_hint;
+ /* this is test code that should be removed when we start passing
+ * in proper size hints.
+ * -- JRM
+ */
+ cache = H5C_create(H5C__DEFAULT_MAX_CACHE_SIZE,
+ H5C__DEFAULT_MIN_CLEAN_SIZE,
+ (H5AC_NTYPES - 1),
+ (const char **)H5AC_entry_type_names,
+ H5AC_check_if_write_permitted);
+
+ if ( NULL == cache ) {
+
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+
+ } else {
+
+ f->shared->cache = cache;
+
+ }
done:
- if(ret_value<0) {
- if(cache!=NULL) {
- if(cache->dslot !=NULL)
- cache->dslot = H5FL_SEQ_FREE (H5AC_info_ptr_t,cache->dslot);
- if(cache->slot !=NULL)
- cache->slot = H5FL_SEQ_FREE (H5AC_info_ptr_t,cache->slot);
-#ifdef H5AC_DEBUG
- if(cache->prot !=NULL)
- cache->prot = H5FL_SEQ_FREE (H5AC_prot_t,cache->prot);
-#endif /* H5AC_DEBUG */
- f->shared->cache = H5FL_FREE (H5AC_t,f->shared->cache);
+
+ if ( ret_value < 0 ) {
+
+ if ( cache != NULL ) {
+
+ H5C_dest_empty(cache);
+ f->shared->cache = NULL;
+
} /* end if */
+
} /* end if */
- FUNC_LEAVE_NOAPI(ret_value);
-}
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* H5AC_create() */
/*-------------------------------------------------------------------------
@@ -426,6 +410,15 @@ done:
*
* Modifications:
*
+ * Complete re-design and re-write to support the re-designed
+ * metadata cache.
+ * JRM - 5/12/04
+ *
+ * Abstracted the guts of the function to H5C_dest() in H5C.c,
+ * and then re-wrote the function as a wrapper for H5C_dest().
+ *
+ * JRM - 6/7/04
+ *
*-------------------------------------------------------------------------
*/
herr_t
@@ -434,92 +427,59 @@ H5AC_dest(H5F_t *f, hid_t dxpl_id)
H5AC_t *cache = NULL;
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5AC_dest, FAIL);
+ FUNC_ENTER_NOAPI(H5AC_dest, FAIL)
assert(f);
assert(f->shared->cache);
cache = f->shared->cache;
- if (H5AC_flush(f, dxpl_id, NULL, HADDR_UNDEF, H5F_FLUSH_INVALIDATE) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush cache");
+ f->shared->cache = NULL;
-#ifdef H5AC_DEBUG
- {
- unsigned i;
- for (i=0; i<cache->nslots; i++) {
- cache->prot[i].slot = H5MM_xfree(cache->prot[i].slot);
- cache->prot[i].aprots = 0;
- cache->prot[i].nprots = 0;
- }
- cache->prot = H5FL_SEQ_FREE(H5AC_prot_t,cache->prot);
- }
-#endif
+ if ( H5C_dest(f, dxpl_id, H5AC_noblock_dxpl_id, cache) < 0 ) {
- cache->dslot = H5FL_SEQ_FREE(H5AC_info_ptr_t,cache->dslot);
- cache->slot = H5FL_SEQ_FREE(H5AC_info_ptr_t,cache->slot);
- cache->nslots = 0;
- f->shared->cache = cache = H5FL_FREE(H5AC_t,cache);
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFREE, FAIL, "can't destroy cache")
+ }
done:
- FUNC_LEAVE_NOAPI(ret_value);
-}
-
-/*-------------------------------------------------------------------------
- * Function: H5AC_compare
- *
- * Purpose: Compare two hash entries by address. Unused entries are
- * all equal to one another and greater than all used entries.
- *
- * Return: Success: -1, 0, 1
- *
- * Failure: never fails
- *
- * Programmer: Robb Matzke
- * matzke@llnl.gov
- * Aug 12 1997
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static int
-H5AC_compare(const void *_a, const void *_b)
-{
- int a = *((const int *) _a);
- int b = *((const int *) _b);
- int ret_value=0;
- H5AC_info_t *slot_a;
- H5AC_info_t *slot_b;
-
- /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5AC_compare);
-
- assert(current_cache_g);
-
- /* Create aliases for slots */
- slot_a=current_cache_g->slot[a];
- slot_b=current_cache_g->slot[b];
-
- assert(slot_a);
- assert(slot_b);
- assert(slot_a->type);
- assert(slot_b->type);
-
- if (slot_a->addr < slot_b->addr) {
- ret_value=(-1);
- } else if (slot_a->addr > slot_b->addr) {
- ret_value=1;
- }
+ FUNC_LEAVE_NOAPI(ret_value)
- FUNC_LEAVE_NOAPI(ret_value);
-}
+} /* H5AC_dest() */
/*-------------------------------------------------------------------------
* Function: H5AC_flush
*
- * Purpose: Flushes (and destroys if DESTROY is non-zero) the specified
+ * Purpose: Flush (and possibly destroy) the metadata cache associated
+ * with the specified file.
+ *
+ * This is a re-write of an earlier version of the function
+ * which was reputedly capable of flushing (and destroying
+ * if requested) individual entries, individual entries if
+ * they match the supplied type, all entries of a given type,
+ * as well as all entries in the cache.
+ *
+ * As only this last capability is actually used at present,
+ * I have not implemented the other capabilities in this
+ * version of the function.
+ *
+ * The type and addr parameters are retained to avoid source
+ * code changed, but values other than NULL and HADDR_UNDEF
+ * respectively are errors. If all goes well, they should
+ * be removed, and the function renamed to something more
+ * descriptive -- perhaps H5AC_flush_cache.
+ *
+ * If the cache contains protected entries, the function will
+ * fail, as protected entries cannot be flushed. However
+ * all unprotected entries should be flushed before the
+ * function returns failure.
+ *
+ * For historical purposes, the original version of the
+ * purpose section is reproduced below:
+ *
+ * ============ Original Version of "Purpose:" ============
+ *
+ * Flushes (and destroys if DESTROY is non-zero) the specified
* entry from the cache. If the entry TYPE is CACHE_FREE and
* ADDR is HADDR_UNDEF then all types of entries are
* flushed. If TYPE is CACHE_FREE and ADDR is defined then
@@ -540,258 +500,43 @@ H5AC_compare(const void *_a, const void *_b)
* Modifications:
* Robb Matzke, 1999-07-27
* The ADDR argument is passed by value.
+ *
+ * Complete re-write. See above for details. -- JRM 5/11/04
+ *
+ * Abstracted the guts of the function to H5C_dest() in H5C.c,
+ * and then re-wrote the function as a wrapper for H5C_dest().
+ *
+ * JRM - 6/7/04
+ *
*-------------------------------------------------------------------------
*/
herr_t
-H5AC_flush(H5F_t *f, hid_t dxpl_id, const H5AC_class_t *type, haddr_t addr, unsigned flags)
+H5AC_flush(H5F_t *f, hid_t dxpl_id, unsigned flags)
{
- unsigned i;
- herr_t status;
- 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; /* 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 status;
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5AC_flush, FAIL);
+ FUNC_ENTER_NOAPI(H5AC_flush, FAIL)
- assert(f);
- assert(f->shared->cache);
+ HDassert(f);
+ HDassert(f->shared->cache);
- /* Get local copy of this information */
- cache = f->shared->cache;
-
- if (!H5F_addr_defined(addr)) {
- unsigned first_flush=1; /* Indicate if this is the first flush */
+ status = H5C_flush_cache(f,
+ dxpl_id,
+ H5AC_noblock_dxpl_id,
+ f->shared->cache,
+ flags);
- /*
- * Sort the cache entries by address since flushing them in
- * ascending order by address is much more efficient.
- */
- if (NULL==(map=H5FL_SEQ_MALLOC(int,cache->nslots)))
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed");
-#ifdef H5_HAVE_PARALLEL
- /* If MPIO, MPIPOSIX, or FPHDF5 is used, do special parallel I/O actions */
- if(IS_H5FD_MPI(f)) {
- H5AC_info_t **dinfo;
-#ifdef H5AC_DEBUG
- H5AC_subid_t type_id;
-#endif /* H5AC_DEBUG */
-#ifndef NDEBUG
- 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 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");
-
- /* Sanity check transfer mode */
- assert(xfer_mode==H5FD_MPIO_COLLECTIVE);
-#endif /* NDEBUG */
-
- /* Create the mapping */
- for (i = nslots = 0; i < cache->nslots; i++) {
- info = cache->slot + i;
- dinfo = cache->dslot + i;
-
- /* Move dirty metadata from 'held' slots into 'regular' slots */
- if((*dinfo)!=NULL) {
- H5AC_dest_func_t dest;
-
- /* Various sanity checks */
- assert((*dinfo)->is_dirty);
- assert((*info)!=NULL);
- assert((*info)->is_dirty==0);
-
-#ifdef H5AC_DEBUG
- type_id=(*info)->type->id; /* Remember this for later */
-#endif /* H5AC_DEBUG */
-
- /* 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);
-
- /* Clear 'held' information */
- (*dinfo)=NULL;
-
-#ifdef H5AC_DEBUG
- cache->diagnostics[type_id].nrestores++;
-#endif /* H5AC_DEBUG */
- } /* end if */
- if ((*info))
- map[nslots++] = i;
- } /* end for */
- } /* end if */
- else {
-#endif /* H5_HAVE_PARALLEL */
- for (i = nslots = 0; i < cache->nslots; i++) {
- if (cache->slot[i]!=NULL)
- map[nslots++] = i;
- }
-#ifdef H5_HAVE_PARALLEL
- } /* end else */
-#endif /* H5_HAVE_PARALLEL */
- assert(NULL == current_cache_g);
- current_cache_g = cache;
- HDqsort(map, nslots, sizeof(int), H5AC_compare);
- current_cache_g = NULL;
-#ifndef NDEBUG
- for (i = 1; i < nslots; i++)
- assert(H5F_addr_lt(cache->slot[map[i - 1]]->addr, cache->slot[map[i]]->addr));
-#endif
-
- /*
- * Look at all cache entries.
- */
- for (i = 0; i < nslots; i++) {
- info = cache->slot + map[i];
- assert(*info);
- if (!type || type == (*info)->type) {
-#ifdef H5AC_DEBUG
- H5AC_subid_t type_id=(*info)->type->id; /* Remember this for later */
-#endif /* H5AC_DEBUG */
-
- /* Clear the dirty flag only, if requested */
- 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)->is_dirty) {
- status = (flush)(f, dxpl_id, destroy, (*info)->addr, (*info));
- first_flush=0;
- } /* end if */
- else
- status = (flush)(f, H5AC_noblock_dxpl_id, destroy, (*info)->addr, (*info));
- if (status < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush cache");
-#ifdef H5AC_DEBUG
- cache->diagnostics[type_id].nflushes++;
-#endif /* H5AC_DEBUG */
- } /* end else */
-
- /* Destroy entry also, if asked */
- if (destroy)
- (*info)= NULL;
- }
- }
-
- /*
- * If there are protected object then fail. However, everything
- * else should have been flushed.
- */
- if (cache->nprots > 0)
- HGOTO_ERROR(H5E_CACHE, H5E_PROTECT, FAIL, "cache has protected items");
- } else {
- i = H5AC_HASH(f, addr);
- info = cache->slot + i;
-#ifdef H5_HAVE_PARALLEL
- /* If MPIO, MPIPOSIX, or FPHDF5 is used, do special parallel I/O actions */
- if(IS_H5FD_MPI(f)) {
- H5AC_info_t **dinfo;
-#ifdef H5AC_DEBUG
- H5AC_subid_t type_id;
-#endif /* H5AC_DEBUG */
-#ifndef NDEBUG
- 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 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");
-
- /* Sanity check transfer mode */
- assert(xfer_mode==H5FD_MPIO_COLLECTIVE);
-#endif /* NDEBUG */
-
- dinfo = cache->dslot + i;
-
- /* Restore dirty metadata from 'held' slot to 'current' slot */
- if((*dinfo)!=NULL) {
- H5AC_dest_func_t dest;
-
- /* Various sanity checks */
- assert((*dinfo)->is_dirty);
- assert((*info)!=NULL);
- assert((*info)->is_dirty==0);
-
-#ifdef H5AC_DEBUG
- type_id=(*info)->type->id; /* Remember this for later */
-#endif /* H5AC_DEBUG */
-
- /* 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);
-
- /* Clear 'held' information */
- (*dinfo)=NULL;
-
-#ifdef H5AC_DEBUG
- cache->diagnostics[type_id].nrestores++;
-#endif /* H5AC_DEBUG */
- } /* end if */
- } /* end if */
-#endif /* H5_HAVE_PARALLEL */
- if ((*info) && (!type || (*info)->type == type) &&
- H5F_addr_eq((*info)->addr, addr)) {
-#ifdef H5AC_DEBUG
- H5AC_subid_t type_id=(*info)->type->id; /* Remember this for later */
-#endif /* H5AC_DEBUG */
-
- /*
- * Flush just this entry.
- */
-
- /* Clear the dirty flag only, if requested */
- 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)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush object");
-#ifdef H5AC_DEBUG
- cache->diagnostics[type_id].nflushes++;
-#endif /* H5AC_DEBUG */
- } /* end else */
+ if ( status < 0 ) {
- /* Destroy entry also, if asked */
- if (destroy)
- (*info)= NULL;
- } /* end if */
- } /* end else */
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't flush entry.")
+ }
done:
- if(map!=NULL)
- map = H5FL_SEQ_FREE(int,map);
- FUNC_LEAVE_NOAPI(ret_value);
-}
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* H5AC_flush() */
/*-------------------------------------------------------------------------
@@ -813,143 +558,69 @@ done:
* Modifications:
* Robb Matzke, 1999-07-27
* The ADDR argument is passed by value.
+ *
+ * Bill Wendling, 2003-09-16
+ * Added automatic "flush" if the FPHDF5 driver is being
+ * used. This'll write the metadata to the SAP where other,
+ * lesser processes can grab it.
+ *
+ * JRM - 5/13/04
+ * Complete re-write for the new metadata cache. The new
+ * code is functionally almost identical to the old, although
+ * the sanity check for a protected entry is now an assert
+ * at the beginning of the function.
+ *
+ * JRM - 6/7/04
+ * Abstracted the guts of the function to H5C_insert_entry()
+ * in H5C.c, and then re-wrote the function as a wrapper for
+ * H5C_insert_entry().
+ *
*-------------------------------------------------------------------------
*/
herr_t
H5AC_set(H5F_t *f, hid_t dxpl_id, const H5AC_class_t *type, haddr_t addr, void *thing)
{
- unsigned idx;
- H5AC_flush_func_t flush;
- H5AC_info_t **info;
- H5AC_t *cache;
+ herr_t result;
+ H5AC_info_t *info;
+ H5AC_t *cache;
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5AC_set, FAIL);
+ FUNC_ENTER_NOAPI(H5AC_set, FAIL)
- assert(f);
- assert(f->shared->cache);
- assert(type);
- assert(type->flush);
- assert(H5F_addr_defined(addr));
- assert(thing);
+ HDassert(f);
+ HDassert(f->shared->cache);
+ HDassert(type);
+ HDassert(type->flush);
+ HDassert(type->size);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(thing);
/* Get local copy of this information */
- idx = H5AC_HASH(f, addr);
cache = f->shared->cache;
- info = cache->slot + idx;
-
-#ifdef H5AC_DEBUG
- {
- H5AC_prot_t *prot = NULL;
- int i;
+ info = (H5AC_info_t *)thing;
- prot = cache->prot + idx;
- for (i = 0; i < prot->nprots; i++)
- assert(H5F_addr_ne(addr, prot->slot[i]->addr));
- }
-#endif
+ info->addr = addr;
+ info->type = type;
+ info->is_protected = FALSE;
-#ifdef H5_HAVE_PARALLEL
- /* If MPIO, MPIPOSIX, or FPHDF5 is used, do special parallel I/O actions */
- if(IS_H5FD_MPI(f)) {
- H5AC_info_t **dinfo;
-#ifdef H5AC_DEBUG
- H5AC_subid_t type_id;
-#endif /* H5AC_DEBUG */
- H5P_genplist_t *dxpl; /* Dataset transfer property list */
- H5FD_mpio_xfer_t xfer_mode; /* I/O transfer mode property value */
+ result = H5C_insert_entry(f,
+ dxpl_id,
+ H5AC_noblock_dxpl_id,
+ cache,
+ type,
+ addr,
+ thing);
- /* 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");
+ if ( result < 0 ) {
- /* 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;
-
- /* 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)->is_dirty);
- assert((*info)!=NULL);
- assert((*info)->is_dirty==0);
-
-#ifdef H5AC_DEBUG
- type_id=(*info)->type->id; /* Remember this for later */
-#endif /* H5AC_DEBUG */
-
- /* 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);
-
- /* Clear 'held' information */
- (*dinfo)=NULL;
-
-#ifdef H5AC_DEBUG
- cache->diagnostics[type_id].nrestores++;
-#endif /* H5AC_DEBUG */
- } /* end if */
- } /* end if */
- 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)->is_dirty) {
- /* Sanity check new item */
- assert(((H5AC_info_t*)thing)->is_dirty==0);
-
- /* 'Hold' the current metadata for later */
- (*dinfo)=(*info);
-
- /* Reset the 'current' metadata, so it doesn't get flushed */
- (*info)=NULL;
-
-#ifdef H5AC_DEBUG
- cache->diagnostics[(*dinfo)->type->id].nholds++;
-#endif /* H5AC_DEBUG */
- } /* end if */
- } /* end else */
- } /* end if */
-#endif /* H5_HAVE_PARALLEL */
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTLOAD, FAIL, "H5C_insert_entry() failed")
+ }
- /* Flush any object already in cache slot */
- if ((*info)) {
-#ifdef H5AC_DEBUG
- H5AC_subid_t type_id=(*info)->type->id; /* Remember this for later */
-#endif /* H5AC_DEBUG */
-
- 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++;
-#endif /* H5AC_DEBUG */
- } /* end if */
+done:
- /* Cache this item */
- (*info)=thing;
- (*info)->type = type;
- (*info)->addr = addr;
-#ifdef H5AC_DEBUG
- cache->diagnostics[type->id].ninits++;
-#endif /* H5AC_DEBUG */
+ FUNC_LEAVE_NOAPI(ret_value)
-done:
- FUNC_LEAVE_NOAPI(ret_value);
-}
+} /* H5AC_set() */
/*-------------------------------------------------------------------------
@@ -971,205 +642,74 @@ done:
* Modifications:
* Robb Matzke, 1999-07-27
* The OLD_ADDR and NEW_ADDR arguments are passed by value.
+ *
+ * JRM 5/17/04
+ * Complete rewrite for the new meta-data cache.
+ *
+ * JRM - 6/7/04
+ * Abstracted the guts of the function to H5C_rename_entry()
+ * in H5C.c, and then re-wrote the function as a wrapper for
+ * H5C_rename_entry().
+ *
*-------------------------------------------------------------------------
*/
herr_t
-H5AC_rename(H5F_t *f, hid_t dxpl_id, const H5AC_class_t *type, haddr_t old_addr,
+H5AC_rename(H5F_t *f, hid_t UNUSED dxpl_id, const H5AC_class_t *type, haddr_t old_addr,
haddr_t new_addr)
{
- unsigned old_idx, new_idx;
- H5AC_flush_func_t flush;
- H5AC_t *cache;
- H5AC_info_t **new_info = NULL;
- H5AC_info_t **old_info = NULL;
+ herr_t result;
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5AC_rename, FAIL);
-
- assert(f);
- assert(f->shared->cache);
- assert(type);
-
- /* Get local copy of this information */
- old_idx = H5AC_HASH(f, old_addr);
- new_idx = H5AC_HASH(f, new_addr);
- cache = f->shared->cache;
- new_info = cache->slot + new_idx;
- old_info = cache->slot + old_idx;
-
-#ifdef H5AC_DEBUG
- {
- H5AC_prot_t *prot = NULL;
- int i;
-
- prot = cache->prot + old_idx;
- for (i = 0; i < prot->nprots; i++)
- assert(H5F_addr_ne(old_addr, prot->slot[i]->addr));
- prot = cache->prot + new_idx;
- for (i = 0; i < prot->nprots; i++)
- assert(H5F_addr_ne(new_addr, prot->slot[i]->addr));
- }
-#endif
+ FUNC_ENTER_NOAPI(H5AC_rename, FAIL)
- /*
- * We don't need to do anything if the object isn't cached or if the
- * new hash value is the same as the old one.
- */
- if (H5F_addr_ne((*old_info)->addr, old_addr) || (*old_info)->type!=type)
- HGOTO_DONE(SUCCEED);
- if (old_idx == new_idx) {
- (*old_info)->addr = new_addr;
- HGOTO_DONE(SUCCEED);
- }
+ HDassert(f);
+ HDassert(f->shared->cache);
+ HDassert(type);
+ HDassert(H5F_addr_defined(old_addr));
+ HDassert(H5F_addr_defined(new_addr));
+ HDassert(H5F_addr_ne(old_addr, new_addr));
-#ifdef H5_HAVE_PARALLEL
- /* If MPIO, MPIPOSIX, or FPHDF5 is used, do special parallel I/O actions */
- if(IS_H5FD_MPI(f)) {
- H5AC_info_t **new_dinfo;
-#ifdef H5AC_DEBUG
- H5AC_subid_t type_id;
-#endif /* H5AC_DEBUG */
- H5P_genplist_t *dxpl; /* Dataset transfer property list */
- H5FD_mpio_xfer_t xfer_mode; /* I/O transfer mode property value */
+ result = H5C_rename_entry(f,
+ f->shared->cache,
+ type,
+ old_addr,
+ new_addr);
- /* 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");
+ if ( result < 0 ) {
- /* 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 new 'held' information */
- new_dinfo = cache->dslot + new_idx;
-
- /* Sanity check transfer mode */
- if(xfer_mode==H5FD_MPIO_COLLECTIVE) {
- /* Check for dirty metadata */
- if(*new_dinfo) {
- H5AC_dest_func_t dest;
-
- /* Various sanity checks */
- assert((*new_dinfo)->is_dirty);
- assert((*new_info)!=NULL);
- assert((*new_info)->is_dirty==0);
-
-#ifdef H5AC_DEBUG
- type_id=(*new_info)->type->id; /* Remember this for later */
-#endif /* H5AC_DEBUG */
-
- /* Destroy 'current' information */
- dest = (*new_info)->type->dest;
- if ((dest)(f, (*new_info))<0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTFREE, FAIL, "unable to free cached object");
-
- /* Restore 'held' information back to 'current' information */
- (*new_info)=(*new_dinfo);
-
- /* Clear 'held' information */
- (*new_dinfo)=NULL;
-
-#ifdef H5AC_DEBUG
- cache->diagnostics[type_id].nrestores++;
-#endif /* H5AC_DEBUG */
- } /* end if */
- } /* end if */
- else {
- /* Sanity check that there will be no write of dirty metadata */
- assert((*new_dinfo)==NULL);
- assert(xfer_mode==H5FD_MPIO_INDEPENDENT);
-
- /* Make certain there will be no write of dirty metadata */
- if((*new_info) && (*new_info)->is_dirty) {
- /* Sanity check that we won't put two pieces of dirty metadata in same cache location */
- assert((*old_info)->is_dirty==0);
-
- /* 'Hold' the current metadata for later */
- (*new_dinfo)=(*new_info);
-
- /* Reset the 'current' metadata, so it doesn't get flushed */
- (*new_info)=NULL;
-
-#ifdef H5AC_DEBUG
- cache->diagnostics[(*new_dinfo)->type->id].nholds++;
-#endif /* H5AC_DEBUG */
- } /* end if */
- } /* end else */
- } /* end if */
-#endif /* H5_HAVE_PARALLEL */
-
- /*
- * Free the item from the destination cache line.
- */
- if (*new_info) {
-#ifdef H5AC_DEBUG
- H5AC_subid_t type_id=(*new_info)->type->id; /* Remember this for later */
-#endif /* H5AC_DEBUG */
-
- flush = (*new_info)->type->flush;
- if ( (flush)(f, dxpl_id, TRUE, (*new_info)->addr, (*new_info)) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush object");
-#ifdef H5AC_DEBUG
- cache->diagnostics[type_id].nflushes++;
-#endif /* H5AC_DEBUG */
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTLOAD, FAIL, \
+ "H5C_rename_entry() failed.")
}
- /*
- * Move the source to the destination (it might not be cached)
- */
- (*new_info)= (*old_info);
- (*new_info)->addr = new_addr;
-
-#ifdef H5_HAVE_PARALLEL
- /* If MPIO, MPIPOSIX, or FPHDF5 is used, do special parallel I/O actions */
- if(IS_H5FD_MPI(f)) {
- H5AC_info_t **old_dinfo;
-#ifdef H5AC_DEBUG
- H5AC_subid_t type_id;
-#endif /* H5AC_DEBUG */
-
- /* Get pointer to new 'held' information */
- old_dinfo = cache->dslot + old_idx;
-
- /* Check for 'held' metadata in old location & restore it, if so */
- if(*old_dinfo) {
- /* Sanity check */
- assert((*old_dinfo)->is_dirty);
-
-#ifdef H5AC_DEBUG
- type_id=(*old_info)->type->id; /* Remember this for later */
-#endif /* H5AC_DEBUG */
-
- /* Restore 'held' information back to 'current' information */
- (*old_info)=(*old_dinfo);
-
- /* Clear 'held' information */
- (*old_dinfo)=NULL;
-
-#ifdef H5AC_DEBUG
- cache->diagnostics[type_id].nrestores++;
-#endif /* H5AC_DEBUG */
- } /* end if */
- else
- (*old_info)= NULL;
- } /* end if */
- else {
-#endif /* H5_HAVE_PARALLEL */
+done:
- (*old_info)= NULL;
-#ifdef H5_HAVE_PARALLEL
- } /* end else */
-#endif /* H5_HAVE_PARALLEL */
+ FUNC_LEAVE_NOAPI(ret_value)
-done:
- FUNC_LEAVE_NOAPI(ret_value);
-}
+} /* H5AC_rename() */
/*-------------------------------------------------------------------------
* Function: H5AC_protect
*
- * Purpose: Similar to H5AC_find() except the object is removed from
+ * Purpose: If the target entry is not in the cache, load it. If
+ * necessary, attempt to evict one or more entries to keep
+ * the cache within its maximum size.
+ *
+ * Mark the target entry as protected, and return its address
+ * to the caller. The caller must call H5AC_unprotect() when
+ * finished with the entry.
+ *
+ * While it is protected, the entry may not be either evicted
+ * or flushed -- nor may it be accessed by another call to
+ * H5AC_protect. Any attempt to do so will result in a failure.
+ *
+ * This comment is a re-write of the original Purpose: section.
+ * For historical interest, the original version is reproduced
+ * below:
+ *
+ * Original Purpose section:
+ *
+ * Similar to H5AC_find() except the object is removed from
* the cache and given to the caller, preventing other parts
* of the program from modifying the protected object or
* preempting it from the cache.
@@ -1191,6 +731,20 @@ done:
* Modifications:
* Robb Matzke, 1999-07-27
* The ADDR argument is passed by value.
+ *
+ * Bill Wendling, 2003-09-10
+ * Added parameter to indicate whether this is a READ or
+ * WRITE type of protect.
+ *
+ * JRM -- 5/17/04
+ * Complete re-write for the new client cache. See revised
+ * Purpose section above.
+ *
+ * JRM - 6/7/04
+ * Abstracted the guts of the function to H5C_protect()
+ * in H5C.c, and then re-wrote the function as a wrapper for
+ * H5C_protect().
+ *
*-------------------------------------------------------------------------
*/
void *
@@ -1204,190 +758,68 @@ H5AC_protect(H5F_t *f,
UNUSED
rw)
{
- int idx;
- void *thing=NULL;
- H5AC_t *cache;
- H5AC_info_t **info;
- void *ret_value; /* Return value */
-
-#ifdef H5AC_DEBUG
- H5AC_prot_t *prot = NULL;
- static int ncalls = 0;
-
- if (0 == ncalls++) {
- if (H5DEBUG(AC)) {
- fprintf(H5DEBUG(AC), "H5AC: debugging cache (expensive)\n");
- }
- }
-#endif
+ void * thing = NULL;
+ void * ret_value; /* Return value */
- FUNC_ENTER_NOAPI(H5AC_protect, NULL);
+ FUNC_ENTER_NOAPI(H5AC_protect, NULL)
/* check args */
- assert(f);
- assert(f->shared->cache);
- assert(type);
- assert(type->load);
- assert(type->flush);
- assert(H5F_addr_defined(addr));
-
- /* Get local copy of this information */
- idx = H5AC_HASH(f, addr);
- cache = f->shared->cache;
- info = cache->slot + idx;
-#ifdef H5AC_DEBUG
- prot = cache->prot + idx;
-#endif /* H5AC_DEBUG */
-
-#ifdef H5_HAVE_PARALLEL
- /* If MPIO, MPIPOSIX, or FPHDF5 is used, do special parallel I/O actions */
- if(IS_H5FD_MPI(f)) {
- H5AC_info_t **dinfo;
-
- /* Get pointer to new 'held' information */
- dinfo = cache->dslot + idx;
-
- /* Check for 'held' metadata in location & handle it */
- if(*dinfo) {
- /* Sanity checks */
- assert((*dinfo)->is_dirty);
- assert((*info));
- assert((*info)->is_dirty==0);
- assert((*dinfo)->addr!=(*info)->addr);
-
- /* Is 'held' metadata the metadata we are looking for? */
- if (H5F_addr_eq((*dinfo)->addr, addr)
-#ifdef H5AC_DEBUG
- && (*dinfo)->type==type
-#endif /* H5AC_DEBUG */
- ) {
-#ifndef H5AC_DEBUG
- /* Sanity check that the object in the cache is the correct type */
- assert((*dinfo)->type==type);
-#endif /* H5AC_DEBUG */
- /*
- * The object is already cached; simply remove it from the cache.
- */
- thing = (*dinfo);
- (*dinfo)->type = NULL;
- (*dinfo)->addr = HADDR_UNDEF;
- (*dinfo)= NULL;
-#ifdef H5AC_DEBUG
- cache->diagnostics[(*dinfo)->type->id].nhits++;
-#endif /* H5AC_DEBUG */
- } /* end if */
- /* 'held' metadata isn't what we are looking for, but check for 'current' metadata */
- else {
- if(H5F_addr_eq((*info)->addr, addr)
-#ifdef H5AC_DEBUG
- && (*info)->type==type
-#endif /* H5AC_DEBUG */
- ) {
-#ifndef H5AC_DEBUG
- /* Sanity check that the object in the cache is the correct type */
- assert((*info)->type==type);
-#endif /* H5AC_DEBUG */
- /*
- * The object is already cached; remove it from the cache.
- * and bring the 'held' object into the 'regular' information
- */
- thing = (*info);
- (*info)->type = NULL;
- (*info)->addr = HADDR_UNDEF;
- (*info)= (*dinfo);
- (*dinfo)= NULL;
-#ifdef H5AC_DEBUG
- cache->diagnostics[(*info)->type->id].nhits++;
-#endif /* H5AC_DEBUG */
- } /* end if */
- } /* end else */
- } /* end if */
- } /* end if */
-
- /* Check if we've already found the object to protect */
- if(thing==NULL) {
-#endif /* H5_HAVE_PARALLEL */
- if ((*info) && H5F_addr_eq(addr,(*info)->addr)
-#ifdef H5AC_DEBUG
- && (*info)->type==type
-#endif /* H5AC_DEBUG */
- ) {
-#ifndef H5AC_DEBUG
- /* Sanity check that the object in the cache is the correct type */
- assert((*info)->type==type);
-#endif /* H5AC_DEBUG */
-
- /*
- * The object is already cached; simply remove it from the cache.
- */
- thing = (*info);
-#ifdef H5AC_DEBUG
- cache->diagnostics[(*info)->type->id].nhits++;
-#endif /* H5AC_DEBUG */
- (*info)->type = NULL;
- (*info)->addr = HADDR_UNDEF;
- (*info)= NULL;
- } else {
-#ifdef H5AC_DEBUG
- /*
- * Check that the requested thing isn't protected, for protected things
- * can only be modified through the pointer already handed out by the
- * H5AC_protect() function.
- */
- int i;
-
- for (i = 0; i < prot->nprots; i++)
- assert(H5F_addr_ne(addr, prot->slot[i]->addr));
-#endif /* H5AC_DEBUG */
-
- /*
- * Load a new thing. If it can't be loaded, then return an error
- * without preempting anything.
- */
- if (NULL == (thing = (type->load)(f, dxpl_id, addr, udata1, udata2)))
- HGOTO_ERROR(H5E_CACHE, H5E_CANTLOAD, NULL, "unable to load object");
-#ifdef H5AC_DEBUG
- cache->diagnostics[type->id].nmisses++;
-#endif /* H5AC_DEBUG */
- }
-#ifdef H5_HAVE_PARALLEL
- } /* end if */
-#endif /* H5_HAVE_PARALLEL */
-
-#ifdef H5AC_DEBUG
- /*
- * Add the protected object to the protect debugging fields of the
- * cache.
- */
- if (prot->nprots >= prot->aprots) {
- size_t na = prot->aprots + 10;
- H5AC_info_t **x = H5MM_realloc(prot->slot, na * sizeof(H5AC_info_t *));
-
- if (NULL==x)
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
- prot->aprots = (int)na;
- prot->slot = x;
+ HDassert(f);
+ HDassert(f->shared->cache);
+ HDassert(type);
+ HDassert(type->flush);
+ HDassert(type->load);
+ HDassert(H5F_addr_defined(addr));
+
+
+ thing = H5C_protect(f,
+ dxpl_id,
+ H5AC_noblock_dxpl_id,
+ f->shared->cache,
+ type,
+ addr,
+ udata1,
+ udata2);
+
+ if ( thing == NULL ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_PROTECT, NULL, "H5C_protect() failed.")
}
- prot->slot[prot->nprots]= thing;
- prot->slot[prot->nprots]->type = type;
- prot->slot[prot->nprots]->addr = addr;
- prot->nprots += 1;
-#endif /* H5AC_DEBUG */
-
- cache->nprots += 1;
/* Set return value */
- ret_value=thing;
+ ret_value = thing;
done:
- FUNC_LEAVE_NOAPI(ret_value);
-}
+
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* H5AC_protect() */
/*-------------------------------------------------------------------------
* Function: H5AC_unprotect
*
- * Purpose: This function should be called to undo the effect of
+ * Purpose: Undo an H5AC_protect() call -- specifically, mark the
+ * entry as unprotected, remove it from the protected list,
+ * and give it back to the replacement policy.
+ *
+ * The TYPE and ADDR arguments must be the same as those in
+ * the corresponding call to H5AC_protect() and the THING
+ * argument must be the value returned by that call to
+ * H5AC_protect().
+ *
+ * If the deleted flag is TRUE, simply remove the target entry
+ * from the cache, clear it, and free it without writing it to
+ * disk.
+ *
+ * This verion of the function is a complete re-write to
+ * use the new metadata cache. While there isn't all that
+ * much difference between the old and new Purpose sections,
+ * the original version is given below.
+ *
+ * Original purpose section:
+ *
+ * This function should be called to undo the effect of
* 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().
@@ -1405,265 +837,188 @@ done:
* Sep 2 1997
*
* Modifications:
- * Robb Matzke, 1999-07-27
+ * Robb Matzke, 1999-07-27
* The ADDR argument is passed by value.
*
- * Quincey Koziol, 2003-03-19
+ * Quincey Koziol, 2003-03-19
* Added "deleted" argument
+ *
+ * Bill Wendling, 2003-09-18
+ * If this is an FPHDF5 driver and the data is dirty,
+ * perform a "flush" that writes the data to the SAP.
+ *
+ * John Mainzer 5/19/04
+ * Complete re-write for the new metadata cache.
+ *
+ * JRM - 6/7/04
+ * Abstracted the guts of the function to H5C_unprotect()
+ * in H5C.c, and then re-wrote the function as a wrapper for
+ * H5C_unprotect().
+ *
*-------------------------------------------------------------------------
*/
herr_t
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;
- H5AC_t *cache;
- H5AC_info_t **info;
+ herr_t result;
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5AC_unprotect, FAIL);
-
- /* check args */
- assert(f);
- assert(f->shared->cache);
- assert(type);
- assert(type->flush);
- assert(H5F_addr_defined(addr));
- assert(thing);
-
- /* Get local copy of this information */
- idx = H5AC_HASH(f, 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);
+ FUNC_ENTER_NOAPI(H5AC_unprotect, FAIL)
+
+ HDassert(f);
+ HDassert(f->shared->cache);
+ HDassert(type);
+ HDassert(type->clear);
+ HDassert(type->flush);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(thing);
+ HDassert( ((H5AC_info_t *)thing)->addr == addr );
+ HDassert( ((H5AC_info_t *)thing)->type == type );
+
+ result = H5C_unprotect(f,
+ dxpl_id,
+ H5AC_noblock_dxpl_id,
+ f->shared->cache,
+ type,
+ addr,
+ thing,
+ deleted);
+
+ if ( result < 0 ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_NOTCACHED, FAIL, \
+ "H5C_unprotect() failed.")
}
-#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_MPI(f)) {
- H5AC_info_t **dinfo;
-#ifdef H5AC_DEBUG
- H5AC_subid_t type_id;
-#endif /* H5AC_DEBUG */
- 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 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;
-
- /* 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)->is_dirty);
- assert((*info)!=NULL);
- assert((*info)->is_dirty==0);
-
-#ifdef H5AC_DEBUG
- type_id=(*info)->type->id; /* Remember this for later */
-#endif /* H5AC_DEBUG */
-
- /* 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);
-
- /* Clear 'held' information */
- (*dinfo)=NULL;
-
-#ifdef H5AC_DEBUG
- cache->diagnostics[type_id].nrestores++;
-#endif /* H5AC_DEBUG */
- } /* end if */
- } /* end if */
- 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)->is_dirty) {
- /* Sanity check new item */
- assert(((H5AC_info_t*)thing)->is_dirty==0);
+done:
- /* 'Hold' the current metadata for later */
- (*dinfo)=(*info);
+ FUNC_LEAVE_NOAPI(ret_value)
- /* Reset the 'current' metadata, so it doesn't get flushed */
- (*info)=NULL;
+} /* H5AC_unprotect() */
-#ifdef H5AC_DEBUG
- cache->diagnostics[(*dinfo)->type->id].nholds++;
-#endif /* H5AC_DEBUG */
- } /* 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) {
-#ifdef H5AC_DEBUG
- 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");
-#ifdef H5AC_DEBUG
- cache->diagnostics[type_id].nflushes++;
-#endif /* H5AC_DEBUG */
- }
+
+/*-------------------------------------------------------------------------
+ * Function: H5AC_stats
+ *
+ * Purpose: Prints statistics about the cache.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Robb Matzke
+ * Thursday, October 30, 1997
+ *
+ * Modifications:
+ * John Mainzer 5/19/04
+ * Re-write to support the new metadata cache.
+ *
+ * JRM - 6/7/04
+ * Abstracted the guts of the function to H5C_stats()
+ * in H5C.c, and then re-wrote the function as a wrapper for
+ * H5C_stats().
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5AC_stats(H5F_t UNUSED *f)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
- /*
- * 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");
+ FUNC_ENTER_NOAPI(H5AC_stats, FAIL)
- /* Destroy previously cached thing */
- if ((type->dest)(f, thing)<0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTFREE, FAIL, "unable to free object");
- } /* end else */
+ HDassert(f);
+ HDassert(f->shared->cache);
- /* Decrement the number of protected items outstanding */
- cache->nprots -= 1;
+ H5C_stats(f->shared->cache, f->name, FALSE); /* at present, this can't fail */
done:
- FUNC_LEAVE_NOAPI(ret_value);
-}
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* H5AC_stats() */
+/*************************************************************************/
+/**************************** Private Functions: *************************/
+/*************************************************************************/
+
/*-------------------------------------------------------------------------
- * Function: H5AC_debug
*
- * Purpose: Prints debugging info about the cache.
+ * Function: H5AC_check_if_write_permitted
*
- * Return: Non-negative on success/Negative on failure
+ * Purpose: Determine if a write is permitted under the current
+ * circumstances, and set *write_permitted_ptr accordingly.
+ * As a general rule it is, but when we are running in parallel
+ * mode with collective I/O, we must ensure that a read cannot
+ * cause a write.
*
- * Programmer: Robb Matzke
- * Thursday, October 30, 1997
+ * In the event of failure, the value of *write_permitted_ptr
+ * is undefined.
+ *
+ * Return: Non-negative on success/Negative on failure.
+ *
+ * Programmer: John Mainzer, 5/15/04
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
-herr_t
-H5AC_debug(H5F_t UNUSED *f)
+
+#ifdef H5_HAVE_PARALLEL
+static herr_t
+H5AC_check_if_write_permitted(H5F_t *f,
+ hid_t dxpl_id,
+ hbool_t * write_permitted_ptr)
+#else /* H5_HAVE_PARALLEL */
+static herr_t
+H5AC_check_if_write_permitted(H5F_t UNUSED * f,
+ hid_t UNUSED dxpl_id,
+ hbool_t * write_permitted_ptr)
+#endif /* H5_HAVE_PARALLEL */
{
-#ifdef H5AC_DEBUG
- H5AC_subid_t i;
- char s[32], ascii[32];
- H5AC_t *cache = f->shared->cache;
- double miss_rate;
-#endif /* H5AC_DEBUG */
- herr_t ret_value=SUCCEED; /* Return value */
+ hbool_t write_permitted = TRUE;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5AC_check_if_write_permitted, FAIL)
+
+#ifdef H5_HAVE_PARALLEL
+
+ if ( IS_H5FD_MPI(f) ) {
+
+ 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")
+
+ }
- FUNC_ENTER_NOAPI(H5AC_debug, FAIL);
-
-#ifdef H5AC_DEBUG
- if (H5DEBUG(AC)) {
- fprintf(H5DEBUG(AC), "H5AC: meta data cache statistics for file %s\n",
- f->name);
- fprintf(H5DEBUG(AC), " %-18s %8s %8s %8s %8s+%-8s\n",
- "Layer", "Hits", "Misses", "MissRate", "Inits", "Flushes");
- fprintf(H5DEBUG(AC), " %-18s %8s %8s %8s %8s-%-8s\n",
- "-----", "----", "------", "--------", "-----", "-------");
-
- for (i = H5AC_BT_ID; i < H5AC_NTYPES; i++) {
-
- switch (i) {
- case H5AC_BT_ID:
- HDstrcpy(s, "B-tree nodes");
- break;
- case H5AC_SNODE_ID:
- HDstrcpy(s, "symbol table nodes");
- break;
- case H5AC_LHEAP_ID:
- HDstrcpy (s, "local heaps");
- break;
- case H5AC_GHEAP_ID:
- HDstrcpy (s, "global heaps");
- break;
- case H5AC_OHDR_ID:
- HDstrcpy(s, "object headers");
- break;
- default:
- sprintf(s, "unknown id %d", i);
- }
-
- if (cache->diagnostics[i].nhits>0 ||
- cache->diagnostics[i].nmisses>0) {
- miss_rate = 100.0 * cache->diagnostics[i].nmisses /
- (cache->diagnostics[i].nhits+
- cache->diagnostics[i].nmisses);
- } else {
- miss_rate = 0.0;
- }
-
- if (miss_rate > 100) {
- sprintf(ascii, "%7d%%", (int) (miss_rate + 0.5));
- } else {
- sprintf(ascii, "%7.2f%%", miss_rate);
- }
- fprintf(H5DEBUG(AC), " %-18s %8u %8u %7s %8u%+-9ld\n", s,
- cache->diagnostics[i].nhits,
- cache->diagnostics[i].nmisses,
- ascii,
- cache->diagnostics[i].ninits,
- ((long)(cache->diagnostics[i].nflushes) -
- (long)(cache->diagnostics[i].ninits)));
- }
+ /* 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")
+
+ }
+
+ if ( xfer_mode == H5FD_MPIO_INDEPENDENT ) {
+
+ write_permitted = FALSE;
+
+ } else {
+
+ HDassert(xfer_mode == H5FD_MPIO_COLLECTIVE );
+
+ }
}
-#endif /* H5AC_DEBUG */
+
+#endif /* H5_HAVE_PARALLEL */
+
+ *write_permitted_ptr = write_permitted;
done:
- FUNC_LEAVE_NOAPI(ret_value);
-}
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* H5AC_check_if_write_permitted() */