diff options
Diffstat (limited to 'src/H5Cprivate.h')
-rw-r--r-- | src/H5Cprivate.h | 476 |
1 files changed, 471 insertions, 5 deletions
diff --git a/src/H5Cprivate.h b/src/H5Cprivate.h index 654ce35..47573f9 100644 --- a/src/H5Cprivate.h +++ b/src/H5Cprivate.h @@ -114,6 +114,7 @@ /* Cache configuration versions */ #define H5C__CURR_AUTO_SIZE_CTL_VER 1 #define H5C__CURR_AUTO_RESIZE_RPT_FCN_VER 1 +#define H5C__CURR_CACHE_IMAGE_CTL_VER 1 /* Default configuration settings */ #define H5C__DEF_AR_UPPER_THRESHHOLD 0.9999f @@ -994,16 +995,16 @@ typedef int H5C_ring_t; * just before the entry is freed. * * This is necessary, as the LRU list can be changed out - * from under H5C_make_space_in_cache() by the serialize + * from under H5C__make_space_in_cache() by the serialize * callback which may change the size of an existing entry, * and/or load a new entry while serializing the target entry. * * This in turn can cause a recursive call to - * H5C_make_space_in_cache() which may either flush or evict + * H5C__make_space_in_cache() which may either flush or evict * the next entry that the first invocation of that function * was about to examine. * - * The magic field allows H5C_make_space_in_cache() to + * The magic field allows H5C__make_space_in_cache() to * detect this case, and re-start its scan from the bottom * of the LRU when this situation occurs. * @@ -1338,6 +1339,187 @@ typedef int H5C_ring_t; * In either case, when there is no previous item, it should * be NULL. * + * Fields supporting the cache image feature: + * + * The following fields are used to store data about the entry which must + * be stored in the cache image block, but which will typically be either + * lost or heavily altered in the process of serializing the cache and + * preparing its contents to be copied into the cache image block. + * + * Some fields are also used in loading the contents of the metadata cache + * image back into the cache, and in managing such entries until they are + * either protected by the library (at which point they become regular + * entries) or are evicted. See discussion of the prefetched field for + * further details. + * + * include_in_image: Boolean flag indicating whether this entry should + * be included in the metadata cache image. This field should + * always be false prior to the H5C_prep_for_file_close() call. + * During that call, it should be set to TRUE for all entries + * that are to be included in the metadata cache image. At + * present, only the superblock, the superblock extension + * object header and its chunks (if any) are omitted from + * the image. + * + * lru_rank: Rank of the entry in the LRU just prior to file close. + * + * Note that the first entry on the LRU has lru_rank 1, + * and that entries not on the LRU at that time will have + * either lru_rank -1 (if pinned) or 0 (if loaded during + * the process of flushing the cache. + * + * image_dirty: Boolean flag indicating whether the entry should be marked + * as dirty in the metadata cache image. The flag is set to + * TRUE iff the entry is dirty when H5C_prep_for_file_close() + * is called. + * + * fd_parent_count: If the entry is a child in one or more flush dependency + * relationships, this field contains the number of flush + * dependency parents. + * + * In all other cases, the field is set to zero. + * + * Note that while this count is initially taken from the + * flush dependency fields above, if the entry is in the + * cache image (i.e. include_in_image is TRUE), any parents + * that are not in the image are removed from this count and + * from the fd_parent_addrs array below. + * + * Finally observe that if the entry is dirty and in the + * cache image, and its parent is dirty and not in the cache + * image, then the entry must be removed from the cache image + * to avoid violating the flush dependency flush ordering. + * + * fd_parent_addrs: If the entry is a child in one or more flush dependency + * relationship when H5C_prep_for_file_close() is called, this + * field must contain a pointer to an array of size + * fd_parent_count containing the on disk addresses of the + * parent. + * + * In all other cases, the field is set to NULL. + * + * Note that while this list of addresses is initially taken + * from the flush dependency fields above, if the entry is in the + * cache image (i.e. include_in_image is TRUE), any parents + * that are not in the image are removed from this list, and + * and from the fd_parent_count above. + * + * Finally observe that if the entry is dirty and in the + * cache image, and its parent is dirty and not in the cache + * image, then the entry must be removed from the cache image + * to avoid violating the flush dependency flush ordering. + * + * fd_child_count: If the entry is a parent in a flush dependency + * relationship, this field contains the number of flush + * dependency children. + * + * In all other cases, the field is set to zero. + * + * Note that while this count is initially taken from the + * flush dependency fields above, if the entry is in the + * cache image (i.e. include_in_image is TRUE), any children + * that are not in the image are removed from this count. + * + * fd_dirty_child_count: If the entry is a parent in a flush dependency + * relationship, this field contains the number of dirty flush + * dependency children. + * + * In all other cases, the field is set to zero. + * + * Note that while this count is initially taken from the + * flush dependency fields above, if the entry is in the + * cache image (i.e. include_in_image is TRUE), any dirty + * children that are not in the image are removed from this + * count. + * + * image_fd_height: Flush dependency height of the entry in the cache image. + * + * The flush dependency height of any entry involved in a + * flush dependency relationship is defined to be the + * longest flush dependency path from that entry to an entry + * with no flush depenency children. + * + * Since the image_fd_height is used to order entries in the + * cache image so that fd parents preceed fd children, for + * purposes of this field, and entry is at flush dependency + * level 0 if it either has no children, or if all of its + * children are not in the cache image. + * + * Note that if a child in a flush dependency relationship is + * dirty and in the cache image, and its parent is dirty and + * not in the cache image, then the child must be excluded + * from the cache image to maintain flush ordering. + * + * prefetched: Boolean flag indicating that the on disk image of the entry + * has been loaded into the cache prior any request for the + * entry by the rest of the library. + * + * As of this writing (8/10/15), this can only happen through + * the load of a cache image block, although other scenarios + * are contemplated for the use of this feature. Note that + * unlike the usual prefetch situation, this means that a + * pre fetched entry can be dirty, and/or can be a party to + * flush dependency relationship(s). This complicates matters + * somewhat. + * + * The essential feature of a pre-fetched entry is that it + * consists only of a buffer containing the on disk image of + * the entry. Thus it must be deserialized before it can + * be passed back to the library on a protect call. This + * task is handled by H5C_deserialized_prefetched_entry(). + * In essence, this routine calls the deserialize callback + * provided in the protect call with the on disk image, + * deletes the prefetched entry from the cache, and replaces + * it with the deserialized entry returned by the deserialize + * callback. + * + * Further, if the prefetched entry is a flush dependency parent, + * all its flush dependency children (which must also be + * pre-fetched entries), must be tranfered to the new cache + * entry returned by the deserailization callback. + * + * Finally, if the prefetched entry is a flush dependency child, + * this flush dependency must be destroyed prior to the + * deserialize call. + * + * In addition to the above special processing on the first + * protect call on a prefetched entry (after which is no longer + * a prefetched entry), prefetched entries also require special + * tretment on flush and evict. + * + * On flush, a dirty prefetched entry must simply be written + * to disk and marked clean without any call to any client + * callback. + * + * On eviction, if a prefetched entry is a flush dependency + * child, that flush dependency relationship must be destroyed + * just prior to the eviction. If the flush dependency code + * is working properly, it should be impossible for any entry + * that is a flush dependency parent to be evicted. + * + * prefetch_type_id: Integer field containing the type ID of the prefetched + * entry. This ID must match the ID of the type provided in any + * protect call on the prefetched entry. + * + * The value of this field is undefined in prefetched is FALSE. + * + * age: Number of times a prefetched entry has appeared in + * subsequent cache images. The field exists to allow + * imposition of a limit on how many times a prefetched + * entry can appear in subsequent cache images without being + * converted to a regular entry. + * + * This field must be zero if prefetched is FALSE. + * + * serialization_count: Integer field used to maintain a count of the + * number of times each entry is serialized during cache + * serialization. While no entry should be serialized more than + * once in any serialization call, throw an assertion if any + * flush depencency parent is serialized more than once during + * a single cache serialization. + * + * This is a debugging field, and thus is maintained only if + * NDEBUG is undefined. * * Fields supporting tagged entries: * @@ -1433,6 +1615,23 @@ typedef struct H5C_cache_entry_t { struct H5C_cache_entry_t *coll_prev; #endif /* H5_HAVE_PARALLEL */ + /* fields supporting cache image */ + hbool_t include_in_image; + int32_t lru_rank; + hbool_t image_dirty; + uint64_t fd_parent_count; + haddr_t *fd_parent_addrs; + uint64_t fd_child_count; + uint64_t fd_dirty_child_count; + uint32_t image_fd_height; + hbool_t prefetched; + int prefetch_type_id; + int32_t age; + +#ifndef NDEBUG /* debugging field */ + int serialization_count; +#endif /* NDEBUG */ + /* fields supporting tag lists */ struct H5C_cache_entry_t *tl_next; struct H5C_cache_entry_t *tl_prev; @@ -1447,6 +1646,168 @@ typedef struct H5C_cache_entry_t { #endif /* H5C_COLLECT_CACHE_ENTRY_STATS */ } H5C_cache_entry_t; + +/**************************************************************************** + * + * structure H5C_image_entry_t + * + * Instances of the H5C_image_entry_t structure are used to store data on + * metadata cache entries used in the construction of the metadata cache + * image block. In essence this structure is a greatly simplified version + * of H5C_cache_entry_t. + * + * The fields of this structure are discussed individually below: + * + * JRM - 8/5/15 + * + * magic: Unsigned 32 bit integer that must always be set to + * H5C__H5C_IMAGE_ENTRY_T_MAGIC when the entry is valid. + * The field must be set to H5C__H5C_IMAGE__ENTRY_T_BAD_MAGIC + * just before the entry is freed. + * + * addr: Base address of the cache entry on disk. + * + * size: Length of the cache entry on disk in bytes. + * + * ring: Instance of H5C_ring_t indicating the flush ordering ring + * to which this entry is assigned. + * + * age: Number of times this prefetech entry has appeared in + * the current sequence of cache images. This field is + * initialized to 0 if the instance of H5C_image_entry_t + * is constructed from a regular entry. + * + * If the instance is constructed from a prefetched entry + * currently residing in the metadata cache, the field is + * set to 1 + the age of the prefetched entry, or to + * H5AC__CACHE_IMAGE__ENTRY_AGEOUT__MAX if that sum exceeds + * H5AC__CACHE_IMAGE__ENTRY_AGEOUT__MAX. + * + * type_id: Integer field containing the type ID of the entry. + * + * lru_rank: Rank of the entry in the LRU just prior to file close. + * + * Note that the first entry on the LRU has lru_rank 1, + * and that entries not on the LRU at that time will have + * either lru_rank -1 (if pinned) or 0 (if loaded during + * the process of flushing the cache. + * + * is_dirty: Boolean flag indicating whether the contents of the cache + * entry has been modified since the last time it was written + * to disk as a regular piece of metadata. + * + * image_fd_height: Flush dependency height of the entry in the cache image. + * + * The flush dependency height of any entry involved in a + * flush dependency relationship is defined to be the + * longest flush dependency path from that entry to an entry + * with no flush depenency children. + * + * Since the image_fd_height is used to order entries in the + * cache image so that fd parents preceed fd children, for + * purposes of this field, an entry is at flush dependency + * level 0 if it either has no children, or if all of its + * children are not in the cache image. + * + * Note that if a child in a flush dependency relationship is + * dirty and in the cache image, and its parent is dirty and + * not in the cache image, then the child must be excluded + * from the cache image to maintain flush ordering. + * + * fd_parent_count: If the entry is a child in one or more flush dependency + * relationships, this field contains the number of flush + * dependency parents. + * + * In all other cases, the field is set to zero. + * + * Note that while this count is initially taken from the + * flush dependency fields in the associated instance of + * H5C_cache_entry_t, if the entry is in the cache image + * (i.e. include_in_image is TRUE), any parents that are + * not in the image are removed from this count and + * from the fd_parent_addrs array below. + * + * Finally observe that if the entry is dirty and in the + * cache image, and its parent is dirty and not in the cache + * image, then the entry must be removed from the cache image + * to avoid violating the flush dependency flush ordering. + * This should have happened before the construction of + * the instance of H5C_image_entry_t. + * + * fd_parent_addrs: If the entry is a child in one or more flush dependency + * relationship when H5C_prep_for_file_close() is called, this + * field must contain a pointer to an array of size + * fd_parent_count containing the on disk addresses of the + * parents. + * + * In all other cases, the field is set to NULL. + * + * Note that while this list of addresses is initially taken + * from the flush dependency fields in the associated instance of + * H5C_cache_entry_t, if the entry is in the cache image + * (i.e. include_in_image is TRUE), any parents that are not + * in the image are removed from this list, and from the + * fd_parent_count above. + * + * Finally observe that if the entry is dirty and in the + * cache image, and its parent is dirty and not in the cache + * image, then the entry must be removed from the cache image + * to avoid violating the flush dependency flush ordering. + * This should have happened before the construction of + * the instance of H5C_image_entry_t. + * + * fd_child_count: If the entry is a parent in a flush dependency + * relationship, this field contains the number of flush + * dependency children. + * + * In all other cases, the field is set to zero. + * + * Note that while this count is initially taken from the + * flush dependency fields in the associated instance of + * H5C_cache_entry_t, if the entry is in the cache image + * (i.e. include_in_image is TRUE), any children + * that are not in the image are removed from this count. + * + * fd_dirty_child_count: If the entry is a parent in a flush dependency + * relationship, this field contains the number of dirty flush + * dependency children. + * + * In all other cases, the field is set to zero. + * + * Note that while this count is initially taken from the + * flush dependency fields in the associated instance of + * H5C_cache_entry_t, if the entry is in the cache image + * (i.e. include_in_image is TRUE), any dirty children + * that are not in the image are removed from this count. + * + * image_ptr: Pointer to void. When not NULL, this field points to a + * dynamically allocated block of size bytes in which the + * on disk image of the metadata cache entry is stored. + * + * If the entry is dirty, the pre-serialize and serialize + * callbacks must be used to update this image before it is + * written to disk + * + * + ****************************************************************************/ + +typedef struct H5C_image_entry_t { + uint32_t magic; + haddr_t addr; + size_t size; + H5C_ring_t ring; + int32_t age; + int32_t type_id; + int32_t lru_rank; + hbool_t is_dirty; + unsigned image_fd_height; + uint64_t fd_parent_count; + haddr_t *fd_parent_addrs; + uint64_t fd_child_count; + uint64_t fd_dirty_child_count; + void *image_ptr; +} H5C_image_entry_t; + /**************************************************************************** * * structure H5C_auto_size_ctl_t @@ -1736,12 +2097,98 @@ typedef struct H5C_auto_size_ctl_t { double empty_reserve; } H5C_auto_size_ctl_t; +/**************************************************************************** + * + * structure H5C_cache_image_ctl_t + * + * Instances of H5C_image_ctl_t are used to get and set the control + * fields for generation of a metadata cache image on file close. + * + * At present control of construction of a cache image is via a FAPL + * property at file open / create. + * + * The fields of the structure are discussed individually below: + * + * version: Integer field containing the version number of this version + * of the H5C_image_ctl_t structure. Any instance of + * H5C_image_ctl_t passed to the cache must have a known + * version number, or an error will be flagged. + * + * generate_image: Boolean flag indicating whether a cache image should + * be created on file close. + * + * save_resize_status: Boolean flag indicating whether the cache image + * should include the adaptive cache resize configuration and status. + * Note that this field is ignored at present. + * + * entry_ageout: Integer field indicating the maximum number of + * times a prefetched entry can appear in subsequent cache images. + * This field exists to allow the user to avoid the buildup of + * infrequently used entries in long sequences of cache images. + * + * The value of this field must lie in the range + * H5AC__CACHE_IMAGE__ENTRY_AGEOUT__NONE (-1) to + * H5AC__CACHE_IMAGE__ENTRY_AGEOUT__MAX (100). + * + * H5AC__CACHE_IMAGE__ENTRY_AGEOUT__NONE means that no limit + * is imposed on number of times a prefeteched entry can appear + * in subsequent cache images. + * + * A value of 0 prevents prefetched entries from being included + * in cache images. + * + * Positive integers restrict prefetched entries to the specified + * number of appearances. + * + * Note that the number of subsequent cache images that a prefetched + * entry has appeared in is tracked in an 8 bit field. Thus, while + * H5AC__CACHE_IMAGE__ENTRY_AGEOUT__MAX can be increased from its + * current value, any value in excess of 255 will be the functional + * equivalent of H5AC__CACHE_IMAGE__ENTRY_AGEOUT__NONE. + * + * flags: Unsigned integer containing flags controling which aspects of the + * cache image functinality is actually executed. The primary impetus + * behind this field is to allow developement of tests for partial + * implementations that will require little if any modification to run + * with the full implementation. In normal operation, all flags should + * be set. + * + ****************************************************************************/ + +#define H5C_CI__GEN_MDCI_SBE_MESG ((unsigned)0x0001) +#define H5C_CI__GEN_MDC_IMAGE_BLK ((unsigned)0x0002) +#define H5C_CI__SUPRESS_ENTRY_WRITES ((unsigned)0x0004) +#define H5C_CI__WRITE_CACHE_IMAGE ((unsigned)0x0008) + +/* This #define must set all defined H5C_CI flags. It is + * used in the default value for instances of H5C_cache_image_ctl_t. + * This value will only be modified in test code. + */ +#define H5C_CI__ALL_FLAGS ((unsigned)0x000F) + +#define H5C__DEFAULT_CACHE_IMAGE_CTL \ +{ \ + /* version = */ H5C__CURR_CACHE_IMAGE_CTL_VER, \ + /* generate_image = */ FALSE, \ + /* save_resize_status = */ FALSE, \ + /* entry_ageout = */ H5AC__CACHE_IMAGE__ENTRY_AGEOUT__NONE, \ + /* flags = */ H5C_CI__ALL_FLAGS \ +} + +typedef struct H5C_cache_image_ctl_t { + int32_t version; + hbool_t generate_image; + hbool_t save_resize_status; + int32_t entry_ageout; + unsigned flags; +} H5C_cache_image_ctl_t; + /***************************************/ /* Library-private Function Prototypes */ /***************************************/ H5_DLL H5C_t *H5C_create(size_t max_cache_size, size_t min_clean_size, - int max_type_id, const char *(*type_name_table_ptr), + int max_type_id, const H5C_class_t * const *class_table_ptr, H5C_write_permitted_func_t check_write_permitted, hbool_t write_permitted, H5C_log_flush_func_t log_flush, void *aux_ptr); H5_DLL herr_t H5C_set_up_logging(H5C_t *cache_ptr, const char log_location[], hbool_t start_immediately); @@ -1770,9 +2217,11 @@ herr_t H5C_verify_tag(int id, haddr_t tag); H5_DLL herr_t H5C_flush_to_min_clean(H5F_t *f, hid_t dxpl_id); H5_DLL herr_t H5C_get_cache_auto_resize_config(const H5C_t *cache_ptr, H5C_auto_size_ctl_t *config_ptr); +H5_DLL herr_t H5C_get_cache_image_config(const H5C_t * cache_ptr, + H5C_cache_image_ctl_t *config_ptr); H5_DLL herr_t H5C_get_cache_size(H5C_t *cache_ptr, size_t *max_size_ptr, size_t *min_clean_size_ptr, size_t *cur_size_ptr, - int32_t *cur_num_entries_ptr); + uint32_t *cur_num_entries_ptr); H5_DLL herr_t H5C_get_cache_hit_rate(H5C_t *cache_ptr, double *hit_rate_ptr); H5_DLL herr_t H5C_get_entry_status(const H5F_t *f, haddr_t addr, size_t *size_ptr, hbool_t *in_cache_ptr, hbool_t *is_dirty_ptr, @@ -1783,8 +2232,11 @@ H5_DLL herr_t H5C_get_evictions_enabled(const H5C_t *cache_ptr, hbool_t *evictio H5_DLL void * H5C_get_aux_ptr(const H5C_t *cache_ptr); H5_DLL FILE *H5C_get_trace_file_ptr(const H5C_t *cache_ptr); H5_DLL FILE *H5C_get_trace_file_ptr_from_entry(const H5C_cache_entry_t *entry_ptr); +H5_DLL herr_t H5C_image_stats(H5C_t * cache_ptr, hbool_t print_header); H5_DLL herr_t H5C_insert_entry(H5F_t *f, hid_t dxpl_id, const H5C_class_t *type, haddr_t addr, void *thing, unsigned int flags); +H5_DLL herr_t H5C_load_cache_image_on_next_protect(H5F_t *f, haddr_t addr, + hsize_t len, hbool_t rw); H5_DLL herr_t H5C_mark_entry_dirty(void *thing); H5_DLL herr_t H5C_mark_entry_clean(void *thing); H5_DLL herr_t H5C_mark_entry_unserialized(void *thing); @@ -1799,6 +2251,8 @@ H5_DLL void * H5C_protect(H5F_t *f, hid_t dxpl_id, const H5C_class_t *type, H5_DLL herr_t H5C_reset_cache_hit_rate_stats(H5C_t *cache_ptr); H5_DLL herr_t H5C_resize_entry(void *thing, size_t new_size); H5_DLL herr_t H5C_set_cache_auto_resize_config(H5C_t *cache_ptr, H5C_auto_size_ctl_t *config_ptr); +H5_DLL herr_t H5C_set_cache_image_config(const H5F_t *f, H5C_t *cache_ptr, + H5C_cache_image_ctl_t *config_ptr); H5_DLL herr_t H5C_set_evictions_enabled(H5C_t *cache_ptr, hbool_t evictions_enabled); H5_DLL herr_t H5C_set_prefix(H5C_t *cache_ptr, char *prefix); H5_DLL herr_t H5C_set_trace_file_ptr(H5C_t *cache_ptr, FILE *trace_file_ptr); @@ -1810,6 +2264,7 @@ H5_DLL herr_t H5C_unpin_entry(void *thing); H5_DLL herr_t H5C_destroy_flush_dependency(void *parent_thing, void *child_thing); H5_DLL herr_t H5C_unprotect(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *thing, unsigned int flags); +H5_DLL herr_t H5C_validate_cache_image_config(H5C_cache_image_ctl_t * ctl_ptr); H5_DLL herr_t H5C_validate_resize_config(H5C_auto_size_ctl_t *config_ptr, unsigned int tests); H5_DLL herr_t H5C_ignore_tags(H5C_t *cache_ptr); @@ -1819,6 +2274,8 @@ H5_DLL herr_t H5C_cork(H5C_t *cache_ptr, haddr_t obj_addr, unsigned action, hboo H5_DLL herr_t H5C_get_entry_ring(const H5F_t *f, haddr_t addr, H5C_ring_t *ring); H5_DLL herr_t H5C_unsettle_entry_ring(void *thing); H5_DLL herr_t H5C_remove_entry(void *thing); +H5_DLL herr_t H5C_cache_image_status(H5F_t * f, hbool_t *load_ci_ptr, + hbool_t *write_ci_ptr); #ifdef H5_HAVE_PARALLEL H5_DLL herr_t H5C_apply_candidate_list(H5F_t *f, hid_t dxpl_id, @@ -1832,7 +2289,16 @@ H5_DLL herr_t H5C_mark_entries_as_clean(H5F_t *f, hid_t dxpl_id, int32_t ce_arra #endif /* H5_HAVE_PARALLEL */ #ifndef NDEBUG /* debugging functions */ +H5_DLL hbool_t H5C_get_serialization_in_progress(const H5C_t *cache_ptr); H5_DLL hbool_t H5C_cache_is_clean(const H5C_t *cache_ptr, H5C_ring_t inner_ring); +H5_DLL herr_t H5C_get_entry_ptr_from_addr(H5C_t *cache_ptr, haddr_t addr, + void **entry_ptr_ptr); +H5_DLL herr_t H5C_flush_dependency_exists(H5C_t *cache_ptr, haddr_t parent_addr, + haddr_t child_addr, hbool_t *fd_exists_ptr); +H5_DLL herr_t H5C_verify_entry_type(H5C_t *cache_ptr, haddr_t addr, + const H5C_class_t *expected_type, hbool_t *in_cache_ptr, + hbool_t *type_ok_ptr); +H5_DLL herr_t H5C_validate_index_list(H5C_t *cache_ptr); #endif /* NDEBUG */ #endif /* !_H5Cprivate_H */ |