From 1071d8bf73bc9f069b9d939d882aa27e2334f94a Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Fri, 25 Nov 2016 16:07:23 -0600 Subject: Add a flag for H5C__flush_single_entry() to allow the parallel code to request that images for entries be generated, even when not writing the entry from an MPI rank. --- src/H5C.c | 58 ++++++++++++++++++++++++++++++-------------------------- src/H5Cmpio.c | 42 ++++++++++++++++++++++++++++++---------- src/H5Cprivate.h | 2 ++ 3 files changed, 65 insertions(+), 37 deletions(-) diff --git a/src/H5C.c b/src/H5C.c index 147489b..31f887d 100644 --- a/src/H5C.c +++ b/src/H5C.c @@ -5739,6 +5739,7 @@ H5C__flush_single_entry(const H5F_t *f, hid_t dxpl_id, H5C_cache_entry_t *entry_ hbool_t during_flush; /* external flag */ hbool_t write_entry; /* internal flag */ hbool_t destroy_entry; /* internal flag */ + hbool_t generate_image; /* internal flag */ hbool_t was_dirty; haddr_t entry_addr = HADDR_UNDEF; herr_t ret_value = SUCCEED; /* Return value */ @@ -5759,6 +5760,7 @@ H5C__flush_single_entry(const H5F_t *f, hid_t dxpl_id, H5C_cache_entry_t *entry_ take_ownership = ((flags & H5C__TAKE_OWNERSHIP_FLAG) != 0); del_from_slist_on_destroy = ((flags & H5C__DEL_FROM_SLIST_ON_DESTROY_FLAG) != 0); during_flush = ((flags & H5C__DURING_FLUSH_FLAG) != 0); + generate_image = ((flags & H5C__GENERATE_IMAGE_FLAG) != 0); /* Set the flag for destroying the entry, based on the 'take ownership' * and 'destroy' flags @@ -5818,29 +5820,13 @@ H5C__flush_single_entry(const H5F_t *f, hid_t dxpl_id, H5C_cache_entry_t *entry_ entry_ptr->flush_in_progress = TRUE; entry_ptr->flush_marker = FALSE; - /* serialize the entry if necessary, and then write it to disk. */ - if(write_entry) { - - /* The entry is dirty, and we are doing either a flush, - * or a flush destroy. In either case, serialize the - * entry and write it to disk. - * - * Note that this may cause the entry to be re-sized and/or - * moved in the cache. - * - * As we will not update the metadata cache's data structures - * until we we finish the write, we must touch up these - * data structures for size and location changes even if we - * are about to delete the entry from the cache (i.e. on a - * flush destroy). - */ + /* The entry is dirty, and we are doing a flush, a flush destroy or have + * been requested to generate an image. In those cases, serialize the + * entry. + */ + if(write_entry || generate_image) { HDassert(entry_ptr->is_dirty); -#if H5C_DO_SANITY_CHECKS - if(cache_ptr->check_write_permitted && !(cache_ptr->write_permitted)) - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Write when writes are always forbidden!?!?!") -#endif /* H5C_DO_SANITY_CHECKS */ - if(NULL == entry_ptr->image_ptr) { if(NULL == (entry_ptr->image_ptr = H5MM_malloc(entry_ptr->size + H5C_IMAGE_EXTRA_SPACE))) HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, "memory allocation failed for on disk image buffer") @@ -5854,13 +5840,22 @@ H5C__flush_single_entry(const H5F_t *f, hid_t dxpl_id, H5C_cache_entry_t *entry_ if(H5C__generate_image(f, cache_ptr, entry_ptr, dxpl_id) < 0) HGOTO_ERROR(H5E_CACHE, H5E_CANTGET, FAIL, "can't generate entry's image") } /* end if ( ! (entry_ptr->image_up_to_date) ) */ + } /* end if */ + + /* Finally, write the image to disk. + * + * Note that if the H5AC__CLASS_SKIP_WRITES flag is set in the + * in the entry's type, we silently skip the write. This + * flag should only be used in test code. + */ + if(write_entry) { + HDassert(entry_ptr->is_dirty); + +#if H5C_DO_SANITY_CHECKS + if(cache_ptr->check_write_permitted && !(cache_ptr->write_permitted)) + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Write when writes are always forbidden!?!?!") +#endif /* H5C_DO_SANITY_CHECKS */ - /* Finally, write the image to disk. - * - * Note that if the H5AC__CLASS_SKIP_WRITES flag is set in the - * in the entry's type, we silently skip the write. This - * flag should only be used in test code. - */ if(((entry_ptr->type->flags) & H5C__CLASS_SKIP_WRITES) == 0) { #ifdef H5_HAVE_PARALLEL if(collective_write_list) { @@ -7600,6 +7595,15 @@ H5C__assert_flush_dep_nocycle(const H5C_cache_entry_t * entry, * * Purpose: Serialize an entry and generate its image. * + * Note: This may cause the entry to be re-sized and/or moved in + * the cache. + * + * As we will not update the metadata cache's data structures + * until we we finish the write, we must touch up these + * data structures for size and location changes even if we + * are about to delete the entry from the cache (i.e. on a + * flush destroy). + * * Return: Non-negative on success/Negative on failure * * Programmer: Mohamad Chaarawi diff --git a/src/H5Cmpio.c b/src/H5Cmpio.c index 8a28f88..72de4d0 100644 --- a/src/H5Cmpio.c +++ b/src/H5Cmpio.c @@ -454,13 +454,37 @@ H5C_apply_candidate_list(H5F_t * f, (long long)clear_ptr->addr); #endif /* H5C_APPLY_CANDIDATE_LIST__DEBUG */ - /* No need to check for the next entry in the scan being - * removed from the cache, as this call to H5C__flush_single_entry() - * will not call either the pre_serialize or serialize callbacks. + /* reset entries_removed_counter and + * last_entry_removed_ptr prior to the call to + * H5C__flush_single_entry() so that we can spot + * unexpected removals of entries from the cache, + * and set the restart_scan flag if proceeding + * would be likely to cause us to scan an entry + * that is no longer in the cache. + * + * Note that as of this writing (April 2015) this + * case cannot occur in the parallel case. However + * Quincey is making noises about changing this, hence + * the insertion of this test. + * + * Note also that there is no test code to verify + * that this code actually works (although similar code + * in the serial version exists and is tested). + * + * Implementing a test will likely require implementing + * flush op like facilities in the parallel tests. At + * a guess this will not be terribly painful, but it + * will take a bit of time. */ + cache_ptr->entries_removed_counter = 0; + cache_ptr->last_entry_removed_ptr = NULL; - if(H5C__flush_single_entry(f, dxpl_id, clear_ptr, H5C__FLUSH_CLEAR_ONLY_FLAG | H5C__DEL_FROM_SLIST_ON_DESTROY_FLAG, NULL) < 0) + if(H5C__flush_single_entry(f, dxpl_id, clear_ptr, H5C__FLUSH_CLEAR_ONLY_FLAG | H5C__GENERATE_IMAGE_FLAG | H5C__DEL_FROM_SLIST_ON_DESTROY_FLAG, NULL) < 0) HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't clear entry.") + + if((cache_ptr->entries_removed_counter > 1) || + (cache_ptr->last_entry_removed_ptr == entry_ptr)) + restart_scan = TRUE; } /* end if */ /* Else, if this process needs to flush this entry. */ @@ -508,11 +532,9 @@ H5C_apply_candidate_list(H5F_t * f, if(H5C__flush_single_entry(f, dxpl_id, flush_ptr, H5C__DEL_FROM_SLIST_ON_DESTROY_FLAG, collective_write_list) < 0) HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't flush entry.") - if ( ( cache_ptr->entries_removed_counter > 1 ) || - ( cache_ptr->last_entry_removed_ptr == entry_ptr ) ) - + if((cache_ptr->entries_removed_counter > 1) || + (cache_ptr->last_entry_removed_ptr == entry_ptr)) restart_scan = TRUE; - } /* end else-if */ /* Otherwise, no action to be taken on this entry. Grab the next. */ @@ -663,7 +685,7 @@ H5C_apply_candidate_list(H5F_t * f, (long long)clear_ptr->addr); #endif /* H5C_APPLY_CANDIDATE_LIST__DEBUG */ - if(H5C__flush_single_entry(f, dxpl_id, clear_ptr, H5C__FLUSH_CLEAR_ONLY_FLAG | H5C__DEL_FROM_SLIST_ON_DESTROY_FLAG, NULL) < 0) + if(H5C__flush_single_entry(f, dxpl_id, clear_ptr, H5C__FLUSH_CLEAR_ONLY_FLAG | H5C__GENERATE_IMAGE_FLAG | H5C__DEL_FROM_SLIST_ON_DESTROY_FLAG, NULL) < 0) HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't clear entry.") } /* end else-if */ @@ -714,7 +736,7 @@ H5C_apply_candidate_list(H5F_t * f, if (delayed_ptr) { if (delayed_ptr->clear_on_unprotect) { - if(H5C__flush_single_entry(f, dxpl_id, delayed_ptr, H5C__FLUSH_CLEAR_ONLY_FLAG, NULL) < 0) + if(H5C__flush_single_entry(f, dxpl_id, delayed_ptr, H5C__FLUSH_CLEAR_ONLY_FLAG | H5C__GENERATE_IMAGE_FLAG, NULL) < 0) HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't flush entry.") entry_ptr->clear_on_unprotect = FALSE; diff --git a/src/H5Cprivate.h b/src/H5Cprivate.h index c03e2e7..923083f 100644 --- a/src/H5Cprivate.h +++ b/src/H5Cprivate.h @@ -183,6 +183,7 @@ * H5C__FLUSH_MARKED_ENTRIES_FLAG * H5C__TAKE_OWNERSHIP_FLAG * H5C__DEL_FROM_SLIST_ON_DESTROY_FLAG + * H5C__GENERATE_IMAGE_FLAG */ #define H5C__NO_FLAGS_SET 0x00000 #define H5C__SET_FLUSH_MARKER_FLAG 0x00001 @@ -202,6 +203,7 @@ #define H5C__EVICT_ALLOW_LAST_PINS_FLAG 0x04000 #define H5C__DEL_FROM_SLIST_ON_DESTROY_FLAG 0x08000 #define H5C__DURING_FLUSH_FLAG 0x10000 /* Set when the entire cache is being flushed */ +#define H5C__GENERATE_IMAGE_FLAG 0x20000 /* Set during parallel I/O */ /* Debugging/sanity checking/statistics settings */ #ifndef NDEBUG -- cgit v0.12