@@ -63,6 +63,9 @@ static herr_t H5C__pin_entry_from_client(H5C_t *cache_ptr, H5C_cache_entry_t *en
6363static herr_t H5C__unpin_entry_real (H5C_t * cache_ptr , H5C_cache_entry_t * entry_ptr , bool update_rp );
6464static herr_t H5C__unpin_entry_from_client (H5C_t * cache_ptr , H5C_cache_entry_t * entry_ptr , bool update_rp );
6565static herr_t H5C__generate_image (H5F_t * f , H5C_t * cache_ptr , H5C_cache_entry_t * entry_ptr );
66+ static herr_t H5C__discard_single_entry (H5F_t * f , H5C_t * cache_ptr , H5C_cache_entry_t * entry_ptr ,
67+ bool destroy_entry , bool free_file_space ,
68+ bool suppress_image_entry_frees );
6669static herr_t H5C__verify_len_eoa (H5F_t * f , const H5C_class_t * type , haddr_t addr , size_t * len , bool actual );
6770static void * H5C__load_entry (H5F_t * f ,
6871#ifdef H5_HAVE_PARALLEL
@@ -753,118 +756,13 @@ H5C__flush_single_entry(H5F_t *f, H5C_cache_entry_t *entry_ptr, unsigned flags)
753756 * Now discard the entry if appropriate.
754757 */
755758 if (destroy ) {
756- /* Sanity check */
757- assert (0 == entry_ptr -> flush_dep_nparents );
758-
759- /* if both suppress_image_entry_frees and entry_ptr->include_in_image
760- * are true, simply set entry_ptr->image_ptr to NULL, as we have
761- * another pointer to the buffer in an instance of H5C_image_entry_t
762- * in cache_ptr->image_entries.
763- *
764- * Otherwise, free the buffer if it exists.
765- */
766- if (suppress_image_entry_frees && entry_ptr -> include_in_image )
767- entry_ptr -> image_ptr = NULL ;
768- else if (entry_ptr -> image_ptr != NULL )
769- entry_ptr -> image_ptr = H5MM_xfree (entry_ptr -> image_ptr );
770-
771- /* If the entry is not a prefetched entry, verify that the flush
772- * dependency parents addresses array has been transferred.
773- *
774- * If the entry is prefetched, the free_isr routine will dispose of
775- * the flush dependency parents addresses array if necessary.
776- */
777- if (!entry_ptr -> prefetched ) {
778- assert (0 == entry_ptr -> fd_parent_count );
779- assert (NULL == entry_ptr -> fd_parent_addrs );
780- } /* end if */
781-
782- /* Check whether we should free the space in the file that
783- * the entry occupies
784- */
785- if (free_file_space ) {
786- hsize_t fsf_size ;
787-
788- /* Sanity checks */
789- assert (H5_addr_defined (entry_ptr -> addr ));
790- assert (!H5F_IS_TMP_ADDR (f , entry_ptr -> addr ));
791- #ifndef NDEBUG
792- {
793- size_t curr_len ;
794-
795- /* Get the actual image size for the thing again */
796- entry_ptr -> type -> image_len ((void * )entry_ptr , & curr_len );
797- assert (curr_len == entry_ptr -> size );
798- }
799- #endif
800-
801- /* If the file space free size callback is defined, use
802- * it to get the size of the block of file space to free.
803- * Otherwise use entry_ptr->size.
804- */
805- if (entry_ptr -> type -> fsf_size ) {
806- if ((entry_ptr -> type -> fsf_size )((void * )entry_ptr , & fsf_size ) < 0 )
807- HGOTO_ERROR (H5E_CACHE , H5E_CANTFREE , FAIL , "unable to get file space free size" );
808- } /* end if */
809- else /* no file space free size callback -- use entry size */
810- fsf_size = entry_ptr -> size ;
811-
812- /* Release the space on disk */
813- if (H5MF_xfree (f , entry_ptr -> type -> mem_type , entry_ptr -> addr , fsf_size ) < 0 )
814- HGOTO_ERROR (H5E_CACHE , H5E_CANTFREE , FAIL , "unable to free file space for cache entry" );
815- } /* end if ( free_file_space ) */
816-
817- /* Reset the pointer to the cache the entry is within. -QAK */
818- entry_ptr -> cache_ptr = NULL ;
819-
820- /* increment entries_removed_counter and set
821- * last_entry_removed_ptr. As we are likely abuut to
822- * free the entry, recall that last_entry_removed_ptr
823- * must NEVER be dereferenced.
824- *
825- * Recall that these fields are maintained to allow functions
826- * that perform scans of lists of entries to detect the
827- * unexpected removal of entries (via expunge, eviction,
828- * or take ownership at present), so that they can re-start
829- * their scans if necessary.
830- *
831- * Also check if the entry we are watching for removal is being
832- * removed (usually the 'next' entry for an iteration) and reset
833- * it to indicate that it was removed.
834- */
835- cache_ptr -> entries_removed_counter ++ ;
836- cache_ptr -> last_entry_removed_ptr = entry_ptr ;
837-
838- if (entry_ptr == cache_ptr -> entry_watched_for_removal )
839- cache_ptr -> entry_watched_for_removal = NULL ;
840-
841- /* Check for actually destroying the entry in memory */
842- /* (As opposed to taking ownership of it) */
843- if (destroy_entry ) {
844- if (entry_ptr -> is_dirty ) {
845- /* Reset dirty flag */
846- entry_ptr -> is_dirty = false;
847-
848- /* If the entry's type has a 'notify' callback send a
849- * 'entry cleaned' notice now that the entry is fully
850- * integrated into the cache.
851- */
852- if (entry_ptr -> type -> notify &&
853- (entry_ptr -> type -> notify )(H5C_NOTIFY_ACTION_ENTRY_CLEANED , entry_ptr ) < 0 )
854- HGOTO_ERROR (H5E_CACHE , H5E_CANTNOTIFY , FAIL ,
855- "can't notify client about entry dirty flag cleared" );
856- } /* end if */
857-
858- /* verify that the image has been freed */
859- assert (entry_ptr -> image_ptr == NULL );
759+ /* Make sure one of either `destroy_entry` or `take_ownership` are true */
760+ assert (destroy_entry != take_ownership );
860761
861- if (entry_ptr -> type -> free_icr ((void * )entry_ptr ) < 0 )
862- HGOTO_ERROR (H5E_CACHE , H5E_CANTFLUSH , FAIL , "free_icr callback failed" );
863- } /* end if */
864- else {
865- assert (take_ownership );
866- } /* end else */
867- } /* if (destroy) */
762+ if (H5C__discard_single_entry (f , cache_ptr , entry_ptr , destroy_entry , free_file_space ,
763+ suppress_image_entry_frees ) < 0 )
764+ HGOTO_ERROR (H5E_CACHE , H5E_CANTFREE , FAIL , "can't discard cache entry" );
765+ }
868766
869767 /* Check if we have to update the page buffer with cleared entries
870768 * so it doesn't go out of date
@@ -891,6 +789,145 @@ H5C__flush_single_entry(H5F_t *f, H5C_cache_entry_t *entry_ptr, unsigned flags)
891789 FUNC_LEAVE_NOAPI (ret_value )
892790} /* H5C__flush_single_entry() */
893791
792+ /*-------------------------------------------------------------------------
793+ * Function: H5C__discard_single_entry
794+ *
795+ * Purpose: Helper routine to discard a cache entry, freeing as much
796+ * of the relevant file space and data structures as possible
797+ * along the way.
798+ *
799+ * Return: FAIL if error is detected, SUCCEED otherwise.
800+ *
801+ *-------------------------------------------------------------------------
802+ */
803+ static herr_t
804+ H5C__discard_single_entry (H5F_t * f , H5C_t * cache_ptr , H5C_cache_entry_t * entry_ptr , bool destroy_entry ,
805+ bool free_file_space , bool suppress_image_entry_frees )
806+ {
807+ herr_t ret_value = SUCCEED ;
808+
809+ FUNC_ENTER_PACKAGE
810+
811+ assert (f );
812+ assert (cache_ptr );
813+ assert (entry_ptr );
814+
815+ /* Sanity check */
816+ assert (0 == entry_ptr -> flush_dep_nparents );
817+
818+ /* if both suppress_image_entry_frees and entry_ptr->include_in_image
819+ * are true, simply set entry_ptr->image_ptr to NULL, as we have
820+ * another pointer to the buffer in an instance of H5C_image_entry_t
821+ * in cache_ptr->image_entries.
822+ *
823+ * Otherwise, free the buffer if it exists.
824+ */
825+ if (suppress_image_entry_frees && entry_ptr -> include_in_image )
826+ entry_ptr -> image_ptr = NULL ;
827+ else if (entry_ptr -> image_ptr != NULL )
828+ entry_ptr -> image_ptr = H5MM_xfree (entry_ptr -> image_ptr );
829+
830+ /* If the entry is not a prefetched entry, verify that the flush
831+ * dependency parents addresses array has been transferred.
832+ *
833+ * If the entry is prefetched, the free_isr routine will dispose of
834+ * the flush dependency parents addresses array if necessary.
835+ */
836+ if (!entry_ptr -> prefetched ) {
837+ assert (0 == entry_ptr -> fd_parent_count );
838+ assert (NULL == entry_ptr -> fd_parent_addrs );
839+ } /* end if */
840+
841+ /* Check whether we should free the space in the file that
842+ * the entry occupies
843+ */
844+ if (free_file_space ) {
845+ hsize_t fsf_size ;
846+
847+ /* Sanity checks */
848+ assert (H5_addr_defined (entry_ptr -> addr ));
849+ assert (!H5F_IS_TMP_ADDR (f , entry_ptr -> addr ));
850+ #ifndef NDEBUG
851+ {
852+ size_t curr_len ;
853+
854+ /* Get the actual image size for the thing again */
855+ entry_ptr -> type -> image_len ((void * )entry_ptr , & curr_len );
856+ assert (curr_len == entry_ptr -> size );
857+ }
858+ #endif
859+
860+ /* If the file space free size callback is defined, use
861+ * it to get the size of the block of file space to free.
862+ * Otherwise use entry_ptr->size.
863+ */
864+ if (entry_ptr -> type -> fsf_size ) {
865+ if ((entry_ptr -> type -> fsf_size )((void * )entry_ptr , & fsf_size ) < 0 )
866+ /* Note error but keep going */
867+ HDONE_ERROR (H5E_CACHE , H5E_CANTFREE , FAIL , "unable to get file space free size" );
868+ } /* end if */
869+ else /* no file space free size callback -- use entry size */
870+ fsf_size = entry_ptr -> size ;
871+
872+ /* Release the space on disk */
873+ if ((ret_value >= 0 ) && H5MF_xfree (f , entry_ptr -> type -> mem_type , entry_ptr -> addr , fsf_size ) < 0 )
874+ /* Note error but keep going */
875+ HDONE_ERROR (H5E_CACHE , H5E_CANTFREE , FAIL , "unable to free file space for cache entry" );
876+ } /* end if ( free_file_space ) */
877+
878+ /* Reset the pointer to the cache the entry is within. -QAK */
879+ entry_ptr -> cache_ptr = NULL ;
880+
881+ /* increment entries_removed_counter and set
882+ * last_entry_removed_ptr. As we are likely about to
883+ * free the entry, recall that last_entry_removed_ptr
884+ * must NEVER be dereferenced.
885+ *
886+ * Recall that these fields are maintained to allow functions
887+ * that perform scans of lists of entries to detect the
888+ * unexpected removal of entries (via expunge, eviction,
889+ * or take ownership at present), so that they can re-start
890+ * their scans if necessary.
891+ *
892+ * Also check if the entry we are watching for removal is being
893+ * removed (usually the 'next' entry for an iteration) and reset
894+ * it to indicate that it was removed.
895+ */
896+ cache_ptr -> entries_removed_counter ++ ;
897+ cache_ptr -> last_entry_removed_ptr = entry_ptr ;
898+
899+ if (entry_ptr == cache_ptr -> entry_watched_for_removal )
900+ cache_ptr -> entry_watched_for_removal = NULL ;
901+
902+ /* Check for actually destroying the entry in memory */
903+ /* (As opposed to taking ownership of it) */
904+ if (destroy_entry ) {
905+ if (entry_ptr -> is_dirty ) {
906+ /* Reset dirty flag */
907+ entry_ptr -> is_dirty = false;
908+
909+ /* If the entry's type has a 'notify' callback send a
910+ * 'entry cleaned' notice now that the entry is fully
911+ * integrated into the cache.
912+ */
913+ if (entry_ptr -> type -> notify &&
914+ (entry_ptr -> type -> notify )(H5C_NOTIFY_ACTION_ENTRY_CLEANED , entry_ptr ) < 0 )
915+ /* Note error but keep going */
916+ HDONE_ERROR (H5E_CACHE , H5E_CANTNOTIFY , FAIL ,
917+ "can't notify client about entry dirty flag cleared" );
918+ } /* end if */
919+
920+ /* verify that the image has been freed */
921+ assert (entry_ptr -> image_ptr == NULL );
922+
923+ if (entry_ptr -> type -> free_icr ((void * )entry_ptr ) < 0 )
924+ /* Note error but keep going */
925+ HDONE_ERROR (H5E_CACHE , H5E_CANTFLUSH , FAIL , "free_icr callback failed" );
926+ } /* end if */
927+
928+ FUNC_LEAVE_NOAPI (ret_value )
929+ } /* end H5C__discard_single_entry() */
930+
894931/*-------------------------------------------------------------------------
895932 * Function: H5C__verify_len_eoa
896933 *
0 commit comments