#include "H5Cmodule.h"
#define H5F_FRIEND
#include "H5private.h"
#ifdef H5_HAVE_PARALLEL
#define H5AC_FRIEND
#include "H5ACpkg.h"
#endif
#include "H5Cpkg.h"
#include "H5Eprivate.h"
#include "H5Fpkg.h"
#include "H5FDprivate.h"
#include "H5FLprivate.h"
#include "H5MFprivate.h"
#include "H5MMprivate.h"
#if H5C_DO_MEMORY_SANITY_CHECKS
#define H5C_IMAGE_EXTRA_SPACE 8
#define H5C_IMAGE_SANITY_VALUE "DeadBeef"
#else
#define H5C_IMAGE_EXTRA_SPACE 0
#endif
#define H5C__MDCI_BLOCK_SIGNATURE "MDCI"
#define H5C__MDCI_BLOCK_SIGNATURE_LEN 4
#define H5C__MDCI_BLOCK_VERSION_0 0
#define H5C__MDCI_HEADER_HAVE_RESIZE_STATUS 0x01
#define H5C__MDCI_ENTRY_DIRTY_FLAG 0x01
#define H5C__MDCI_ENTRY_IN_LRU_FLAG 0x02
#define H5C__MDCI_ENTRY_IS_FD_PARENT_FLAG 0x04
#define H5C__MDCI_ENTRY_IS_FD_CHILD_FLAG 0x08
#define H5C__MDCI_MAX_FD_CHILDREN USHRT_MAX
#define H5C__MDCI_MAX_FD_PARENTS USHRT_MAX
#define H5C_IMAGE_ENTRY_T_MAGIC 0x005CAC08
#define H5C_IMAGE_ENTRY_T_BAD_MAGIC 0xBeefDead
#define H5C_MAX_RING_IN_IMAGE H5C_RING_MDFSM
static size_t H5C__cache_image_block_entry_header_size(const H5F_t *f);
static size_t H5C__cache_image_block_header_size(const H5F_t *f);
static herr_t H5C__decode_cache_image_header(const H5F_t *f,
H5C_t *cache_ptr, const uint8_t **buf);
#ifndef NDEBUG
static herr_t H5C__decode_cache_image_entry(const H5F_t *f,
const H5C_t *cache_ptr, const uint8_t **buf, unsigned entry_num);
#endif
static herr_t H5C__destroy_pf_entry_child_flush_deps(H5C_t *cache_ptr,
H5C_cache_entry_t *pf_entry_ptr, H5C_cache_entry_t **fd_children);
static herr_t H5C__encode_cache_image_header(const H5F_t *f,
const H5C_t *cache_ptr, uint8_t **buf);
static herr_t H5C__encode_cache_image_entry(H5F_t *f, H5C_t *cache_ptr,
uint8_t **buf, unsigned entry_num);
static herr_t H5C__prep_for_file_close__compute_fd_heights(const H5C_t *cache_ptr);
static void H5C__prep_for_file_close__compute_fd_heights_real(
H5C_cache_entry_t *entry_ptr, uint32_t fd_height);
static herr_t H5C__prep_for_file_close__setup_image_entries_array(H5C_t *cache_ptr);
static herr_t H5C__prep_for_file_close__scan_entries(const H5F_t *f,
H5C_t *cache_ptr);
static herr_t H5C__reconstruct_cache_contents(H5F_t *f, H5C_t *cache_ptr);
static H5C_cache_entry_t *H5C__reconstruct_cache_entry(const H5F_t *f,
H5C_t *cache_ptr, const uint8_t **buf);
static herr_t H5C__write_cache_image_superblock_msg(H5F_t *f, hbool_t create);
static herr_t H5C__read_cache_image(H5F_t * f, H5C_t *cache_ptr);
static herr_t H5C__write_cache_image(H5F_t *f, const H5C_t *cache_ptr);
static herr_t H5C__construct_cache_image_buffer(H5F_t *f, H5C_t *cache_ptr);
static herr_t H5C__free_image_entries_array(H5C_t *cache_ptr);
H5FL_DEFINE(H5C_cache_entry_t);
hbool_t
H5C_cache_image_pending(const H5C_t *cache_ptr)
{
hbool_t ret_value = TRUE;
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(cache_ptr);
HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
ret_value = (cache_ptr->load_image && !cache_ptr->image_loaded);
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5C_cache_image_status(H5F_t * f, hbool_t *load_ci_ptr, hbool_t *write_ci_ptr)
{
H5C_t * cache_ptr;
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(f);
HDassert(f->shared);
cache_ptr = f->shared->cache;
HDassert(cache_ptr);
HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
HDassert(load_ci_ptr);
HDassert(write_ci_ptr);
*load_ci_ptr = cache_ptr->load_image || cache_ptr->image_loaded;
*write_ci_ptr = cache_ptr->image_ctl.generate_image;
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5C__construct_cache_image_buffer(H5F_t * f, H5C_t *cache_ptr)
{
uint8_t * p;
uint32_t chksum;
unsigned u;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(f);
HDassert(f->shared);
HDassert(cache_ptr == f->shared->cache);
HDassert(cache_ptr);
HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
HDassert(cache_ptr->close_warning_received);
HDassert(cache_ptr->image_ctl.generate_image);
HDassert(cache_ptr->num_entries_in_image > 0);
HDassert(cache_ptr->index_len == 0);
HDassert(cache_ptr->image_data_len > 0);
HDassert(cache_ptr->image_data_len <= cache_ptr->image_len);
if(NULL == (cache_ptr->image_buffer = H5MM_malloc(cache_ptr->image_len + 1)))
HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, "memory allocation failed for cache image buffer")
p = (uint8_t *)cache_ptr->image_buffer;
if(H5C__encode_cache_image_header(f, cache_ptr, &p) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTENCODE, FAIL, "header image construction failed")
HDassert((size_t)(p - (uint8_t *)cache_ptr->image_buffer) < cache_ptr->image_data_len);
for(u = 0; u < cache_ptr->num_entries_in_image; u++)
if(H5C__encode_cache_image_entry(f, cache_ptr, &p, u) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTENCODE, FAIL, "entry image construction failed")
HDassert((size_t)(p - (uint8_t *)cache_ptr->image_buffer) < cache_ptr->image_data_len);
chksum = H5_checksum_metadata(cache_ptr->image_buffer, (size_t)(cache_ptr->image_data_len - H5F_SIZEOF_CHKSUM), 0);
UINT32ENCODE(p, chksum);
HDassert((size_t)(p - (uint8_t *)cache_ptr->image_buffer) == cache_ptr->image_data_len);
HDassert((size_t)(p - (uint8_t *)cache_ptr->image_buffer) <= cache_ptr->image_len);
#ifndef NDEBUG
{
uint32_t old_chksum;
const uint8_t * q;
H5C_t * fake_cache_ptr = NULL;
unsigned v;
herr_t status;
fake_cache_ptr = (H5C_t *)H5MM_malloc(sizeof(H5C_t));
HDassert(fake_cache_ptr);
fake_cache_ptr->magic = H5C__H5C_T_MAGIC;
fake_cache_ptr->image_len = cache_ptr->image_len;
q = (const uint8_t *)cache_ptr->image_buffer;
status = H5C__decode_cache_image_header(f, fake_cache_ptr, &q);
HDassert(status >= 0);
HDassert(NULL != p);
HDassert(fake_cache_ptr->num_entries_in_image == cache_ptr->num_entries_in_image);
fake_cache_ptr->image_entries = (H5C_image_entry_t *)H5MM_malloc(sizeof(H5C_image_entry_t) *
(size_t)(fake_cache_ptr->num_entries_in_image + 1));
HDassert(fake_cache_ptr->image_entries);
for(u = 0; u < fake_cache_ptr->num_entries_in_image; u++) {
(fake_cache_ptr->image_entries)[u].magic = H5C_IMAGE_ENTRY_T_MAGIC;
(fake_cache_ptr->image_entries)[u].image_ptr = NULL;
f->shared->cache = fake_cache_ptr;
status = H5C__decode_cache_image_entry(f, fake_cache_ptr, &q, u);
HDassert(status >= 0);
f->shared->cache = cache_ptr;
HDassert((cache_ptr->image_entries)[u].addr == (fake_cache_ptr->image_entries)[u].addr);
HDassert((cache_ptr->image_entries)[u].size == (fake_cache_ptr->image_entries)[u].size);
HDassert((cache_ptr->image_entries)[u].type_id == (fake_cache_ptr->image_entries)[u].type_id);
HDassert((cache_ptr->image_entries)[u].lru_rank == (fake_cache_ptr->image_entries)[u].lru_rank);
HDassert((cache_ptr->image_entries)[u].is_dirty == (fake_cache_ptr->image_entries)[u].is_dirty);
HDassert((cache_ptr->image_entries)[u].fd_child_count == (fake_cache_ptr->image_entries)[u].fd_child_count);
HDassert((cache_ptr->image_entries)[u].fd_dirty_child_count == (fake_cache_ptr->image_entries)[u].fd_dirty_child_count);
HDassert((cache_ptr->image_entries)[u].fd_parent_count == (fake_cache_ptr->image_entries)[u].fd_parent_count);
for(v = 0; v < (cache_ptr->image_entries)[u].fd_parent_count; v++)
HDassert((cache_ptr->image_entries)[u].fd_parent_addrs[v] == (fake_cache_ptr->image_entries)[u].fd_parent_addrs[v]);
if((fake_cache_ptr->image_entries)[u].fd_parent_addrs) {
HDassert((fake_cache_ptr->image_entries)[u].fd_parent_count > 0);
(fake_cache_ptr->image_entries)[u].fd_parent_addrs = (haddr_t *)H5MM_xfree((fake_cache_ptr->image_entries)[u].fd_parent_addrs);
(fake_cache_ptr->image_entries)[u].fd_parent_count = 0;
}
else
HDassert((fake_cache_ptr->image_entries)[u].fd_parent_count == 0);
HDassert((cache_ptr->image_entries)[u].image_ptr);
HDassert((fake_cache_ptr->image_entries)[u].image_ptr);
HDassert(!HDmemcmp((cache_ptr->image_entries)[u].image_ptr,
(fake_cache_ptr->image_entries)[u].image_ptr,
(cache_ptr->image_entries)[u].size));
(fake_cache_ptr->image_entries)[u].image_ptr = H5MM_xfree((fake_cache_ptr->image_entries)[u].image_ptr);
}
HDassert((size_t)(q - (const uint8_t *)cache_ptr->image_buffer) == cache_ptr->image_data_len - H5F_SIZEOF_CHKSUM);
old_chksum = chksum;
chksum = H5_checksum_metadata(cache_ptr->image_buffer, (size_t)(cache_ptr->image_data_len - H5F_SIZEOF_CHKSUM), 0);
HDassert(chksum == old_chksum);
fake_cache_ptr->image_entries = (H5C_image_entry_t *)H5MM_xfree(fake_cache_ptr->image_entries);
fake_cache_ptr = (H5C_t *)H5MM_xfree(fake_cache_ptr);
}
#endif
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5C__generate_cache_image(H5F_t *f, H5C_t *cache_ptr)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(f);
HDassert(f->shared);
HDassert(cache_ptr == f->shared->cache);
HDassert(cache_ptr);
HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
if(H5C__construct_cache_image_buffer(f, cache_ptr) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't create metadata cache image")
if(H5C__free_image_entries_array(cache_ptr) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't free image entries array")
if(cache_ptr->image_ctl.flags & H5C_CI__GEN_MDC_IMAGE_BLK) {
if(H5C__write_cache_image(f, cache_ptr) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't write metadata cache image block to file")
H5C__UPDATE_STATS_FOR_CACHE_IMAGE_CREATE(cache_ptr);
}
HDassert(cache_ptr->image_buffer);
cache_ptr->image_buffer = H5MM_xfree(cache_ptr->image_buffer);
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5C__deserialize_prefetched_entry(H5F_t *f, H5C_t *cache_ptr,
H5C_cache_entry_t **entry_ptr_ptr, const H5C_class_t *type,
haddr_t addr, void *udata)
{
hbool_t dirty = FALSE;
size_t len;
void * thing = NULL;
H5C_cache_entry_t * pf_entry_ptr;
H5C_cache_entry_t * ds_entry_ptr;
H5C_cache_entry_t** fd_children = NULL;
unsigned flush_flags = (H5C__FLUSH_INVALIDATE_FLAG |
H5C__FLUSH_CLEAR_ONLY_FLAG);
int i;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(f);
HDassert(f->shared);
HDassert(f->shared->cache);
HDassert(f->shared->cache == cache_ptr);
HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
HDassert(entry_ptr_ptr);
HDassert(*entry_ptr_ptr);
pf_entry_ptr = *entry_ptr_ptr;
HDassert(pf_entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(pf_entry_ptr->type);
HDassert(pf_entry_ptr->type->id == H5AC_PREFETCHED_ENTRY_ID);
HDassert(pf_entry_ptr->prefetched);
HDassert(pf_entry_ptr->image_up_to_date);
HDassert(pf_entry_ptr->image_ptr);
HDassert(pf_entry_ptr->size > 0);
HDassert(pf_entry_ptr->addr == addr);
HDassert(type);
HDassert(type->id == pf_entry_ptr->prefetch_type_id);
HDassert(type->mem_type == cache_ptr->class_table_ptr[type->id]->mem_type);
HDassert(!(type->flags & H5C__CLASS_SKIP_READS));
HDassert(!((type->flags & H5C__CLASS_SKIP_READS) &&
(type->flags & H5C__CLASS_SPECULATIVE_LOAD_FLAG)));
HDassert(H5F_addr_defined(addr));
HDassert(type->get_initial_load_size);
HDassert(type->deserialize);
HDassert(pf_entry_ptr->fd_parent_count == pf_entry_ptr->flush_dep_nparents);
for(i = (int)(pf_entry_ptr->fd_parent_count) - 1; i >= 0; i--) {
HDassert(pf_entry_ptr->flush_dep_parent);
HDassert(pf_entry_ptr->flush_dep_parent[i]);
HDassert(pf_entry_ptr->flush_dep_parent[i]->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(pf_entry_ptr->flush_dep_parent[i]->flush_dep_nchildren > 0);
HDassert(pf_entry_ptr->fd_parent_addrs);
HDassert(pf_entry_ptr->flush_dep_parent[i]->addr == pf_entry_ptr->fd_parent_addrs[i]);
if(H5C_destroy_flush_dependency(pf_entry_ptr->flush_dep_parent[i], pf_entry_ptr) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTUNDEPEND, FAIL, "can't destroy pf entry parent flush dependency")
pf_entry_ptr->fd_parent_addrs[i] = HADDR_UNDEF;
}
HDassert(pf_entry_ptr->flush_dep_nparents == 0);
if(pf_entry_ptr->fd_child_count > 0) {
if(NULL == (fd_children = (H5C_cache_entry_t **)H5MM_calloc(sizeof(H5C_cache_entry_t **) * (size_t)(pf_entry_ptr->fd_child_count + 1))))
HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, "memory allocation failed for fd child ptr array")
if(H5C__destroy_pf_entry_child_flush_deps(cache_ptr, pf_entry_ptr, fd_children) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTUNDEPEND, FAIL, "can't destroy pf entry child flush dependency(s).")
}
len = pf_entry_ptr->size;
if(NULL == (thing = type->deserialize(pf_entry_ptr->image_ptr, len, udata, &dirty)))
HGOTO_ERROR(H5E_CACHE, H5E_CANTLOAD, FAIL, "Can't deserialize image")
ds_entry_ptr = (H5C_cache_entry_t *)thing;
HDassert( ( dirty == FALSE ) || ( type->id == 5 || type->id == 6) );
ds_entry_ptr->magic = H5C__H5C_CACHE_ENTRY_T_MAGIC;
ds_entry_ptr->cache_ptr = f->shared->cache;
ds_entry_ptr->addr = addr;
ds_entry_ptr->size = len;
HDassert(ds_entry_ptr->size < H5C_MAX_ENTRY_SIZE);
ds_entry_ptr->image_ptr = pf_entry_ptr->image_ptr;
ds_entry_ptr->image_up_to_date = !dirty;
ds_entry_ptr->type = type;
ds_entry_ptr->is_dirty = dirty | pf_entry_ptr->is_dirty;
ds_entry_ptr->dirtied = FALSE;
ds_entry_ptr->is_protected = FALSE;
ds_entry_ptr->is_read_only = FALSE;
ds_entry_ptr->ro_ref_count = 0;
ds_entry_ptr->is_pinned = FALSE;
ds_entry_ptr->in_slist = FALSE;
ds_entry_ptr->flush_marker = FALSE;
#ifdef H5_HAVE_PARALLEL
ds_entry_ptr->clear_on_unprotect = FALSE;
ds_entry_ptr->flush_immediately = FALSE;
ds_entry_ptr->coll_access = FALSE;
#endif
ds_entry_ptr->flush_in_progress = FALSE;
ds_entry_ptr->destroy_in_progress = FALSE;
ds_entry_ptr->ring = pf_entry_ptr->ring;
ds_entry_ptr->flush_dep_parent = NULL;
ds_entry_ptr->flush_dep_nparents = 0;
ds_entry_ptr->flush_dep_parent_nalloc = 0;
ds_entry_ptr->flush_dep_nchildren = 0;
ds_entry_ptr->flush_dep_ndirty_children = 0;
ds_entry_ptr->flush_dep_nunser_children = 0;
ds_entry_ptr->ht_next = NULL;
ds_entry_ptr->ht_prev = NULL;
ds_entry_ptr->il_next = NULL;
ds_entry_ptr->il_prev = NULL;
ds_entry_ptr->next = NULL;
ds_entry_ptr->prev = NULL;
#if H5C_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS
ds_entry_ptr->aux_next = NULL;
ds_entry_ptr->aux_prev = NULL;
#endif
#ifdef H5_HAVE_PARALLEL
pf_entry_ptr->coll_next = NULL;
pf_entry_ptr->coll_prev = NULL;
#endif
ds_entry_ptr->include_in_image = FALSE;
ds_entry_ptr->lru_rank = 0;
ds_entry_ptr->image_dirty = FALSE;
ds_entry_ptr->fd_parent_count = 0;
ds_entry_ptr->fd_parent_addrs = NULL;
ds_entry_ptr->fd_child_count = pf_entry_ptr->fd_child_count;
ds_entry_ptr->fd_dirty_child_count = 0;
ds_entry_ptr->image_fd_height = 0;
ds_entry_ptr->prefetched = FALSE;
ds_entry_ptr->prefetch_type_id = 0;
ds_entry_ptr->age = 0;
ds_entry_ptr->prefetched_dirty = pf_entry_ptr->prefetched_dirty;
#ifndef NDEBUG
ds_entry_ptr->serialization_count = 0;
#endif
H5C__RESET_CACHE_ENTRY_STATS(ds_entry_ptr);
if(H5C__tag_entry(cache_ptr, ds_entry_ptr) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTTAG, FAIL, "Cannot tag metadata entry")
pf_entry_ptr->image_ptr = NULL;
if ( pf_entry_ptr->is_dirty ) {
HDassert(((cache_ptr->slist_enabled) && (pf_entry_ptr->in_slist)) || \
((!cache_ptr->slist_enabled) && (!pf_entry_ptr->in_slist)));
flush_flags |= H5C__DEL_FROM_SLIST_ON_DESTROY_FLAG;
}
if(H5C__flush_single_entry(f, pf_entry_ptr, flush_flags) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTEXPUNGE, FAIL, "can't expunge prefetched entry")
#ifndef NDEGUG
H5C__SEARCH_INDEX(cache_ptr, addr, pf_entry_ptr, FAIL);
HDassert(NULL == pf_entry_ptr);
#endif
H5C__INSERT_IN_INDEX(cache_ptr, ds_entry_ptr, FAIL)
HDassert(!ds_entry_ptr->in_slist);
if(ds_entry_ptr->is_dirty)
H5C__INSERT_ENTRY_IN_SLIST(cache_ptr, ds_entry_ptr, FAIL)
H5C__UPDATE_RP_FOR_INSERTION(cache_ptr, ds_entry_ptr, FAIL)
if(ds_entry_ptr->type->notify &&
(ds_entry_ptr->type->notify)(H5C_NOTIFY_ACTION_AFTER_LOAD, ds_entry_ptr) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, "can't notify client about entry loaded into cache")
i = 0;
if(fd_children != NULL) {
H5C__UPDATE_RP_FOR_PROTECT(cache_ptr, ds_entry_ptr, FAIL)
ds_entry_ptr->is_protected = TRUE;
while(fd_children[i] != NULL) {
HDassert((fd_children[i])->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert((fd_children[i])->prefetched);
HDassert((fd_children[i])->fd_parent_count > 0);
HDassert((fd_children[i])->fd_parent_addrs);
#ifndef NDEBUG
{
int j;
hbool_t found;
j = 0;
found = FALSE;
while((j < (int)((fd_children[i])->fd_parent_count)) && (!found)) {
if((fd_children[i])->fd_parent_addrs[j] == ds_entry_ptr->addr)
found = TRUE;
j++;
}
HDassert(found);
}
#endif
if(H5C_create_flush_dependency(ds_entry_ptr, fd_children[i]) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTDEPEND, FAIL, "Can't restore child flush dependency")
i++;
}
H5C__UPDATE_RP_FOR_UNPROTECT(cache_ptr, ds_entry_ptr, FAIL);
ds_entry_ptr->is_protected = FALSE;
}
HDassert((unsigned)i == ds_entry_ptr->fd_child_count);
ds_entry_ptr->fd_child_count = 0;
H5C__UPDATE_STATS_FOR_PREFETCH_HIT(cache_ptr)
*entry_ptr_ptr = ds_entry_ptr;
done:
if(fd_children)
fd_children = (H5C_cache_entry_t **)H5MM_xfree((void *)fd_children);
if(FAIL == ret_value)
if(thing && type->free_icr(thing) < 0)
HDONE_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "free_icr callback failed")
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5C__free_image_entries_array(H5C_t * cache_ptr)
{
FUNC_ENTER_STATIC_NOERR
HDassert(cache_ptr);
HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
HDassert(cache_ptr->close_warning_received);
HDassert(cache_ptr->image_ctl.generate_image);
HDassert(cache_ptr->index_len == 0);
if(cache_ptr->image_entries != NULL) {
unsigned u;
for(u = 0; u < cache_ptr->num_entries_in_image; u++) {
H5C_image_entry_t *ie_ptr;
ie_ptr = &((cache_ptr->image_entries)[u]);
HDassert(ie_ptr);
HDassert(ie_ptr->magic == H5C_IMAGE_ENTRY_T_MAGIC);
HDassert(ie_ptr->image_ptr);
if(ie_ptr->fd_parent_addrs) {
HDassert(ie_ptr->fd_parent_count > 0);
ie_ptr->fd_parent_addrs = (haddr_t *)H5MM_xfree(ie_ptr->fd_parent_addrs);
}
else
HDassert(ie_ptr->fd_parent_count == 0);
ie_ptr->image_ptr = H5MM_xfree(ie_ptr->image_ptr);
ie_ptr->magic = H5C_IMAGE_ENTRY_T_BAD_MAGIC;
}
cache_ptr->image_entries = (H5C_image_entry_t *)H5MM_xfree(cache_ptr->image_entries);
}
FUNC_LEAVE_NOAPI(SUCCEED)
}
herr_t
H5C_force_cache_image_load(H5F_t *f)
{
H5C_t *cache_ptr;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(f);
HDassert(f->shared);
cache_ptr = f->shared->cache;
HDassert(cache_ptr);
HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
HDassert(cache_ptr->load_image);
if(cache_ptr->load_image) {
cache_ptr->load_image = FALSE;
if(H5C__load_cache_image(f) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTLOAD, FAIL, "can't load cache image")
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5C_get_cache_image_config(const H5C_t * cache_ptr,
H5C_cache_image_ctl_t *config_ptr)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
if((cache_ptr == NULL) || (cache_ptr->magic != H5C__H5C_T_MAGIC))
HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "Bad cache_ptr on entry")
if(config_ptr == NULL)
HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "Bad config_ptr on entry")
*config_ptr = cache_ptr->image_ctl;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
#if H5C_COLLECT_CACHE_STATS
H5C_image_stats(H5C_t * cache_ptr, hbool_t print_header)
#else
H5C_image_stats(H5C_t * cache_ptr, hbool_t H5_ATTR_UNUSED print_header)
#endif
{
#if H5C_COLLECT_CACHE_STATS
int i;
int64_t total_hits = 0;
int64_t total_misses = 0;
double hit_rate;
double prefetch_use_rate;
#endif
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
if(!cache_ptr || cache_ptr->magic != H5C__H5C_T_MAGIC)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Bad cache_ptr")
#if H5C_COLLECT_CACHE_STATS
for(i = 0; i <= cache_ptr->max_type_id; i++) {
total_hits += cache_ptr->hits[i];
total_misses += cache_ptr->misses[i];
}
if((total_hits > 0) || (total_misses > 0))
hit_rate = (double)100.0f * ((double)(total_hits)) / ((double)(total_hits + total_misses));
else
hit_rate = 0.0f;
if(cache_ptr->prefetches > 0)
prefetch_use_rate = (double)100.0f * ((double)(cache_ptr->prefetch_hits)) /
((double)(cache_ptr->prefetches));
else
prefetch_use_rate = 0.0f;
if(print_header) {
HDfprintf(stdout,
"\nhit prefetches prefetch image pf hit\n");
HDfprintf(stdout,
"rate: total: dirty: hits: flshs: evct: size: rate:\n");
}
HDfprintf(stdout,
"%3.1lf %5lld %5lld %5lld %5lld %5lld %5lld %3.1lf\n",
hit_rate,
(long long)(cache_ptr->prefetches),
(long long)(cache_ptr->dirty_prefetches),
(long long)(cache_ptr->prefetch_hits),
(long long)(cache_ptr->flushes[H5AC_PREFETCHED_ENTRY_ID]),
(long long)(cache_ptr->evictions[H5AC_PREFETCHED_ENTRY_ID]),
(long long)(cache_ptr->last_image_size),
prefetch_use_rate);
#endif
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5C__read_cache_image(H5F_t *f, H5C_t *cache_ptr)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(f);
HDassert(cache_ptr);
HDassert(H5F_addr_defined(cache_ptr->image_addr));
HDassert(cache_ptr->image_len > 0);
HDassert(cache_ptr->image_buffer);
#ifdef H5_HAVE_PARALLEL
{
H5AC_aux_t *aux_ptr = (H5AC_aux_t *)cache_ptr->aux_ptr;
int mpi_result;
if ( ( NULL == aux_ptr ) || ( aux_ptr->mpi_rank == 0 ) ) {
HDassert((NULL == aux_ptr) ||
(aux_ptr->magic == H5AC__H5AC_AUX_T_MAGIC));
#endif
if(H5F_block_read(f, H5FD_MEM_SUPER, cache_ptr->image_addr,
cache_ptr->image_len, cache_ptr->image_buffer) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_READERROR, FAIL, "Can't read metadata cache image block")
H5C__UPDATE_STATS_FOR_CACHE_IMAGE_READ(cache_ptr)
#ifdef H5_HAVE_PARALLEL
if ( aux_ptr ) {
if ( MPI_SUCCESS !=
(mpi_result = MPI_Bcast(cache_ptr->image_buffer,
(int)cache_ptr->image_len, MPI_BYTE,
0, aux_ptr->mpi_comm)) )
HMPI_GOTO_ERROR(FAIL, "MPI_Bcast failed", mpi_result)
}
}
else if ( aux_ptr ) {
if ( MPI_SUCCESS !=
(mpi_result = MPI_Bcast(cache_ptr->image_buffer,
(int)cache_ptr->image_len, MPI_BYTE,
0, aux_ptr->mpi_comm)) )
HMPI_GOTO_ERROR(FAIL, "can't receive cache image MPI_Bcast", \
mpi_result)
}
}
#endif
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5C__load_cache_image(H5F_t *f)
{
H5C_t * cache_ptr;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(f);
HDassert(f->shared);
cache_ptr = f->shared->cache;
HDassert(cache_ptr);
HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
if(H5F_addr_defined(cache_ptr->image_addr)) {
HDassert(cache_ptr->image_len > 0);
HDassert(cache_ptr->image_buffer == NULL);
if(NULL == (cache_ptr->image_buffer = H5MM_malloc(cache_ptr->image_len + 1)))
HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, "memory allocation failed for cache image buffer")
if(H5C__read_cache_image(f, cache_ptr) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_READERROR, FAIL, "Can't read metadata cache image block")
if(H5C__reconstruct_cache_contents(f, cache_ptr) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTDECODE, FAIL, "Can't reconstruct cache contents from image block")
cache_ptr->image_buffer = H5MM_xfree(cache_ptr->image_buffer);
H5C__UPDATE_STATS_FOR_CACHE_IMAGE_LOAD(cache_ptr)
cache_ptr->image_loaded = TRUE;
}
if(cache_ptr->delete_image) {
if(H5F__super_ext_remove_msg(f, H5O_MDCI_MSG_ID) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTREMOVE, FAIL, "can't remove metadata cache image message from superblock extension")
cache_ptr->image_len = 0;
cache_ptr->image_data_len = 0;
cache_ptr->image_addr = HADDR_UNDEF;
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5C_load_cache_image_on_next_protect(H5F_t *f, haddr_t addr, hsize_t len,
hbool_t rw)
{
H5C_t *cache_ptr;
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(f);
HDassert(f->shared);
cache_ptr = f->shared->cache;
HDassert(cache_ptr);
HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
cache_ptr->image_addr = addr,
cache_ptr->image_len = len;
cache_ptr->load_image = TRUE;
cache_ptr->delete_image = rw;
FUNC_LEAVE_NOAPI(SUCCEED)
}
static int
H5C__image_entry_cmp(const void *_entry1, const void *_entry2)
{
const H5C_image_entry_t *entry1 = (const H5C_image_entry_t *)_entry1;
const H5C_image_entry_t *entry2 = (const H5C_image_entry_t *)_entry2;
int ret_value = 0;
FUNC_ENTER_STATIC_NOERR
HDassert(entry1);
HDassert(entry2);
if(entry1->image_fd_height > entry2->image_fd_height)
ret_value = -1;
else if(entry1->image_fd_height < entry2->image_fd_height)
ret_value = 1;
else {
HDassert(entry1->lru_rank >= -1);
HDassert(entry2->lru_rank >= -1);
if(entry1->lru_rank < entry2->lru_rank)
ret_value = -1;
else if(entry1->lru_rank > entry2->lru_rank)
ret_value = 1;
}
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5C__prep_image_for_file_close(H5F_t *f, hbool_t *image_generated)
{
H5C_t * cache_ptr = NULL;
haddr_t eoa_frag_addr = HADDR_UNDEF;
hsize_t eoa_frag_size = 0;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(f);
HDassert(f->shared);
HDassert(f->shared->cache);
cache_ptr = f->shared->cache;
HDassert(cache_ptr);
HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
HDassert(image_generated);
if(cache_ptr->load_image) {
cache_ptr->load_image = FALSE;
if(H5C__load_cache_image(f) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTLOAD, FAIL, "can't load cache image")
}
if((NULL == f->shared->sblock) ||
(f->shared->sblock->super_vers < HDF5_SUPERBLOCK_VERSION_2) ||
(f->shared->high_bound < H5F_LIBVER_V110)) {
H5C_cache_image_ctl_t default_image_ctl = H5C__DEFAULT_CACHE_IMAGE_CTL;
cache_ptr->image_ctl = default_image_ctl;
HDassert(!(cache_ptr->image_ctl.generate_image));
}
if(cache_ptr->image_ctl.generate_image) {
if(cache_ptr->image_ctl.flags & H5C_CI__GEN_MDCI_SBE_MESG)
if(H5C__write_cache_image_superblock_msg(f, TRUE) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "creation of cache image SB mesg failed.")
if(H5C__serialize_cache(f) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "serialization of the cache failed")
if(H5C__prep_for_file_close__scan_entries(f, cache_ptr) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "H5C__prep_for_file_close__scan_entries failed")
HDassert(HADDR_UNDEF == cache_ptr->image_addr);
#ifdef H5_HAVE_PARALLEL
if(cache_ptr->aux_ptr) {
int mpi_result;
unsigned p0_image_len;
H5AC_aux_t * aux_ptr;
aux_ptr = (H5AC_aux_t *)cache_ptr->aux_ptr;
if(aux_ptr->mpi_rank == 0) {
aux_ptr->p0_image_len = (unsigned)cache_ptr->image_data_len;
p0_image_len = aux_ptr->p0_image_len;
if(MPI_SUCCESS != (mpi_result = MPI_Bcast(&p0_image_len, 1, MPI_UNSIGNED, 0, aux_ptr->mpi_comm)))
HMPI_GOTO_ERROR(FAIL, "MPI_Bcast failed", mpi_result)
HDassert(p0_image_len == aux_ptr->p0_image_len);
}
else {
if(MPI_SUCCESS != (mpi_result = MPI_Bcast(&p0_image_len, 1, MPI_UNSIGNED, 0, aux_ptr->mpi_comm)))
HMPI_GOTO_ERROR(FAIL, "MPI_Bcast failed", mpi_result)
aux_ptr->p0_image_len = p0_image_len;
}
if(HADDR_UNDEF == (cache_ptr->image_addr = H5FD_alloc(f->shared->lf, H5FD_MEM_SUPER, f,
(hsize_t)p0_image_len, &eoa_frag_addr, &eoa_frag_size)))
HGOTO_ERROR(H5E_CACHE, H5E_NOSPACE, FAIL, "can't allocate file space for metadata cache image")
}
else
#endif
if(HADDR_UNDEF == (cache_ptr->image_addr = H5FD_alloc(f->shared->lf, H5FD_MEM_SUPER, f,
(hsize_t)(cache_ptr->image_data_len), &eoa_frag_addr, &eoa_frag_size)))
HGOTO_ERROR(H5E_CACHE, H5E_NOSPACE, FAIL, "can't allocate file space for metadata cache image")
HDassert(HADDR_UNDEF == f->shared->eoa_post_mdci_fsalloc);
if(HADDR_UNDEF == (f->shared->eoa_post_mdci_fsalloc = H5FD_get_eoa(f->shared->lf, H5FD_MEM_DEFAULT)) )
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get file size")
HDassert((eoa_frag_size == 0) || (f->shared->alignment != 1));
cache_ptr->image_len = cache_ptr->image_data_len;
if(cache_ptr->image_ctl.flags & H5C_CI__GEN_MDC_IMAGE_BLK)
if(H5C__write_cache_image_superblock_msg(f, FALSE) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "update of cache image SB mesg failed")
if(cache_ptr->num_entries_in_image > 0) {
if(H5C__prep_for_file_close__setup_image_entries_array(cache_ptr) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTINIT, FAIL, "can't setup image entries array.")
HDqsort(cache_ptr->image_entries, (size_t)cache_ptr->num_entries_in_image,
sizeof(H5C_image_entry_t), H5C__image_entry_cmp);
}
else {
HDassert(cache_ptr->image_entries == NULL);
if(cache_ptr->image_ctl.flags & H5C_CI__GEN_MDC_IMAGE_BLK)
if(H5F__super_ext_remove_msg(f, H5O_MDCI_MSG_ID) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTREMOVE, FAIL, "can't remove MDC image msg from superblock ext")
cache_ptr->image_ctl.generate_image = FALSE;
}
*image_generated = TRUE;
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5C_set_cache_image_config(const H5F_t *f, H5C_t *cache_ptr,
H5C_cache_image_ctl_t *config_ptr)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(f);
HDassert(f->shared);
HDassert(f->shared->cache == f->shared->cache);
if((cache_ptr == NULL) || (cache_ptr->magic != H5C__H5C_T_MAGIC))
HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "Bad cache_ptr on entry")
if(H5C_validate_cache_image_config(config_ptr) < 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid cache image configuration")
#ifdef H5_HAVE_PARALLEL
if(cache_ptr->aux_ptr) {
H5C_cache_image_ctl_t default_image_ctl = H5C__DEFAULT_CACHE_IMAGE_CTL;
cache_ptr->image_ctl = default_image_ctl;
HDassert(!(cache_ptr->image_ctl.generate_image));
}
else {
#endif
if(H5F_INTENT(f) & H5F_ACC_RDWR)
cache_ptr->image_ctl = *config_ptr;
else {
H5C_cache_image_ctl_t default_image_ctl = H5C__DEFAULT_CACHE_IMAGE_CTL;
cache_ptr->image_ctl = default_image_ctl;
HDassert(!(cache_ptr->image_ctl.generate_image));
}
#ifdef H5_HAVE_PARALLEL
}
#endif
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5C_validate_cache_image_config(H5C_cache_image_ctl_t * ctl_ptr)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
if(ctl_ptr == NULL)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "NULL ctl_ptr on entry")
if(ctl_ptr->version != H5C__CURR_CACHE_IMAGE_CTL_VER)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Unknown cache image control version")
if(ctl_ptr->save_resize_status != FALSE)
HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "unexpected value in save_resize_status field")
if(ctl_ptr->entry_ageout != H5AC__CACHE_IMAGE__ENTRY_AGEOUT__NONE)
HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "unexpected value in entry_ageout field")
if((ctl_ptr->flags & ~H5C_CI__ALL_FLAGS) != 0)
HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "unknown flag set")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static size_t
H5C__cache_image_block_entry_header_size(const H5F_t * f)
{
size_t ret_value = 0;
FUNC_ENTER_STATIC_NOERR
ret_value = (size_t)( 1 +
1 +
1 +
1 +
2 +
2 +
2 +
4 +
H5F_SIZEOF_ADDR(f) +
H5F_SIZEOF_SIZE(f) );
FUNC_LEAVE_NOAPI(ret_value)
}
static size_t
H5C__cache_image_block_header_size(const H5F_t * f)
{
size_t ret_value = 0;
FUNC_ENTER_STATIC_NOERR
ret_value = (size_t)( 4 +
1 +
1 +
H5F_SIZEOF_SIZE(f) +
4 );
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5C__decode_cache_image_header(const H5F_t *f, H5C_t *cache_ptr,
const uint8_t **buf)
{
uint8_t version;
uint8_t flags;
hbool_t have_resize_status = FALSE;
size_t actual_header_len;
size_t expected_header_len;
const uint8_t * p;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(cache_ptr);
HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
HDassert(buf);
HDassert(*buf);
p = *buf;
if(HDmemcmp(p, H5C__MDCI_BLOCK_SIGNATURE, (size_t)H5C__MDCI_BLOCK_SIGNATURE_LEN))
HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "Bad metadata cache image header signature")
p += H5C__MDCI_BLOCK_SIGNATURE_LEN;
version = *p++;
if(version != (uint8_t)H5C__MDCI_BLOCK_VERSION_0)
HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "Bad metadata cache image version")
flags = *p++;
if(flags & H5C__MDCI_HEADER_HAVE_RESIZE_STATUS)
have_resize_status = TRUE;
if(have_resize_status)
HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "MDC resize status not yet supported")
H5F_DECODE_LENGTH(f, p, cache_ptr->image_data_len);
if(cache_ptr->image_data_len != cache_ptr->image_len)
HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "Bad metadata cache image data length")
UINT32DECODE(p, cache_ptr->num_entries_in_image);
if(cache_ptr->num_entries_in_image == 0)
HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "Bad metadata cache entry count")
actual_header_len = (size_t)(p - *buf);
expected_header_len = H5C__cache_image_block_header_size(f);
if(actual_header_len != expected_header_len)
HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "Bad header image len")
*buf = p;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
#ifndef NDEBUG
static herr_t
H5C__decode_cache_image_entry(const H5F_t *f, const H5C_t *cache_ptr,
const uint8_t **buf, unsigned entry_num)
{
hbool_t is_dirty = FALSE;
hbool_t in_lru = FALSE;
hbool_t is_fd_parent = FALSE;
hbool_t is_fd_child = FALSE;
haddr_t addr;
hsize_t size = 0;
void * image_ptr;
uint8_t flags = 0;
uint8_t type_id;
uint8_t ring;
uint8_t age;
uint16_t fd_child_count;
uint16_t fd_dirty_child_count;
uint16_t fd_parent_count;
haddr_t * fd_parent_addrs = NULL;
int32_t lru_rank;
H5C_image_entry_t * ie_ptr = NULL;
const uint8_t * p;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(f);
HDassert(f->shared);
HDassert(cache_ptr == f->shared->cache);
HDassert(cache_ptr);
HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
HDassert(buf);
HDassert(*buf);
HDassert(entry_num < cache_ptr->num_entries_in_image);
ie_ptr = &((cache_ptr->image_entries)[entry_num]);
HDassert(ie_ptr);
HDassert(ie_ptr->magic == H5C_IMAGE_ENTRY_T_MAGIC);
p = *buf;
type_id = *p++;
flags = *p++;
if(flags & H5C__MDCI_ENTRY_DIRTY_FLAG)
is_dirty = TRUE;
if(flags & H5C__MDCI_ENTRY_IN_LRU_FLAG)
in_lru = TRUE;
if(flags & H5C__MDCI_ENTRY_IS_FD_PARENT_FLAG)
is_fd_parent = TRUE;
if(flags & H5C__MDCI_ENTRY_IS_FD_CHILD_FLAG)
is_fd_child = TRUE;
ring = *p++;
HDassert(ring > (uint8_t)(H5C_RING_UNDEFINED));
HDassert(ring < (uint8_t)(H5C_RING_NTYPES));
age = *p++;
UINT16DECODE(p, fd_child_count);
HDassert((is_fd_parent && fd_child_count > 0) || (!is_fd_parent && fd_child_count == 0));
UINT16DECODE(p, fd_dirty_child_count);
if(fd_dirty_child_count > fd_child_count)
HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "invalid dirty flush dependency child count")
UINT16DECODE(p, fd_parent_count);
HDassert((is_fd_child && fd_parent_count > 0) || (!is_fd_child && fd_parent_count == 0));
INT32DECODE(p, lru_rank);
HDassert((in_lru && lru_rank >= 0) || (!in_lru && lru_rank == -1));
H5F_addr_decode(f, &p, &addr);
if(!H5F_addr_defined(addr))
HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "invalid entry offset")
H5F_DECODE_LENGTH(f, p, size);
if(size == 0)
HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "invalid entry size")
if((size_t)(p - *buf) != H5C__cache_image_block_entry_header_size(f))
HGOTO_ERROR(H5E_CACHE, H5E_BADSIZE, FAIL, "Bad entry image len")
if(fd_parent_count > 0) {
int i;
if(NULL == (fd_parent_addrs = (haddr_t *)H5MM_malloc((size_t)(fd_parent_count) * H5F_SIZEOF_ADDR(f))))
HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, "memory allocation failed for fd parent addrs buffer")
for(i = 0; i < fd_parent_count; i++) {
H5F_addr_decode(f, &p, &(fd_parent_addrs[i]));
if(!H5F_addr_defined(fd_parent_addrs[i]))
HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "invalid flush dependency parent offset")
}
}
if(NULL == (image_ptr = H5MM_malloc(size + H5C_IMAGE_EXTRA_SPACE)))
HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, "memory allocation failed for on disk image buffer")
#if H5C_DO_MEMORY_SANITY_CHECKS
H5MM_memcpy(((uint8_t *)image_ptr) + size, H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE);
#endif
H5MM_memcpy(image_ptr, p, size);
p += size;
ie_ptr->addr = addr;
ie_ptr->size = size;
ie_ptr->ring = (H5C_ring_t)ring;
ie_ptr->age = (int32_t)age;
ie_ptr->type_id = (int32_t)type_id;
ie_ptr->lru_rank = lru_rank;
ie_ptr->is_dirty = is_dirty;
ie_ptr->fd_child_count = (uint64_t)fd_child_count;
ie_ptr->fd_dirty_child_count = (uint64_t)fd_dirty_child_count;
ie_ptr->fd_parent_count = (uint64_t)fd_parent_count;
ie_ptr->fd_parent_addrs = fd_parent_addrs;
ie_ptr->image_ptr = image_ptr;
*buf = p;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
#endif
static herr_t
H5C__destroy_pf_entry_child_flush_deps(H5C_t *cache_ptr,
H5C_cache_entry_t *pf_entry_ptr, H5C_cache_entry_t **fd_children)
{
H5C_cache_entry_t * entry_ptr;
unsigned entries_visited = 0;
int fd_children_found = 0;
hbool_t found;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(cache_ptr);
HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
HDassert(pf_entry_ptr);
HDassert(pf_entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(pf_entry_ptr->type);
HDassert(pf_entry_ptr->type->id == H5AC_PREFETCHED_ENTRY_ID);
HDassert(pf_entry_ptr->prefetched);
HDassert(pf_entry_ptr->fd_child_count > 0);
HDassert(fd_children);
entry_ptr = cache_ptr->il_head;
while(entry_ptr != NULL) {
HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
if(entry_ptr->prefetched && (entry_ptr->flush_dep_nparents > 0)) {
unsigned u;
u = 0;
found = FALSE;
HDassert(entry_ptr->type);
HDassert(entry_ptr->type->id == H5AC_PREFETCHED_ENTRY_ID);
HDassert(entry_ptr->fd_parent_count >= entry_ptr->flush_dep_nparents);
HDassert(entry_ptr->fd_parent_addrs);
HDassert(entry_ptr->flush_dep_parent);
while(!found && (u < entry_ptr->fd_parent_count)) {
HDassert(entry_ptr->flush_dep_parent[u]);
HDassert(entry_ptr->flush_dep_parent[u]->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
if(pf_entry_ptr == entry_ptr->flush_dep_parent[u])
found = TRUE;
u++;
}
if(found) {
HDassert(NULL == fd_children[fd_children_found]);
fd_children[fd_children_found] = entry_ptr;
fd_children_found++;
if(H5C_destroy_flush_dependency(pf_entry_ptr, entry_ptr) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTUNDEPEND, FAIL, "can't destroy pf entry child flush dependency")
#ifndef NDEBUG
found = FALSE;
u = 0;
while(!found && u < entry_ptr->fd_parent_count) {
if(pf_entry_ptr->addr == entry_ptr->fd_parent_addrs[u])
found = TRUE;
u++;
}
HDassert(found);
#endif
}
}
entries_visited++;
entry_ptr = entry_ptr->il_next;
}
HDassert(NULL == fd_children[fd_children_found]);
HDassert((unsigned)fd_children_found == pf_entry_ptr->fd_child_count);
HDassert(entries_visited == cache_ptr->index_len);
HDassert(!pf_entry_ptr->is_pinned);
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5C__encode_cache_image_header(const H5F_t *f, const H5C_t *cache_ptr,
uint8_t **buf)
{
size_t actual_header_len;
size_t expected_header_len;
uint8_t flags = 0;
uint8_t * p;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(cache_ptr);
HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
HDassert(cache_ptr->close_warning_received);
HDassert(cache_ptr->image_ctl.generate_image);
HDassert(cache_ptr->index_len == 0);
HDassert(cache_ptr->image_data_len > 0);
HDassert(cache_ptr->image_data_len <= cache_ptr->image_len);
HDassert(buf);
HDassert(*buf);
p = *buf;
H5MM_memcpy(p, H5C__MDCI_BLOCK_SIGNATURE, (size_t)H5C__MDCI_BLOCK_SIGNATURE_LEN);
p += H5C__MDCI_BLOCK_SIGNATURE_LEN;
*p++ = (uint8_t)H5C__MDCI_BLOCK_VERSION_0;
HDassert(!cache_ptr->image_ctl.save_resize_status);
if(cache_ptr->image_ctl.save_resize_status)
flags |= H5C__MDCI_HEADER_HAVE_RESIZE_STATUS;
*p++ = flags;
HDassert(cache_ptr->image_len == cache_ptr->image_data_len);
H5F_ENCODE_LENGTH(f, p, cache_ptr->image_data_len);
UINT32ENCODE(p, cache_ptr->num_entries_in_image);
actual_header_len = (size_t)(p - *buf);
expected_header_len = H5C__cache_image_block_header_size(f);
if(actual_header_len != expected_header_len)
HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "Bad header image len")
*buf = p;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5C__encode_cache_image_entry(H5F_t *f, H5C_t *cache_ptr, uint8_t **buf,
unsigned entry_num)
{
H5C_image_entry_t * ie_ptr;
uint8_t flags = 0;
uint8_t * p;
unsigned u;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(f);
HDassert(f->shared);
HDassert(cache_ptr == f->shared->cache);
HDassert(cache_ptr);
HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
HDassert(cache_ptr->close_warning_received);
HDassert(cache_ptr->image_ctl.generate_image);
HDassert(cache_ptr->index_len == 0);
HDassert(buf);
HDassert(*buf);
HDassert(entry_num < cache_ptr->num_entries_in_image);
ie_ptr = &((cache_ptr->image_entries)[entry_num]);
HDassert(ie_ptr->magic == H5C_IMAGE_ENTRY_T_MAGIC);
p = *buf;
if((ie_ptr->type_id < 0) || (ie_ptr->type_id > 255))
HGOTO_ERROR(H5E_CACHE, H5E_BADRANGE, FAIL, "type_id out of range.")
*p++ = (uint8_t)(ie_ptr->type_id);
if(ie_ptr->is_dirty)
flags |= H5C__MDCI_ENTRY_DIRTY_FLAG;
if(ie_ptr->lru_rank > 0)
flags |= H5C__MDCI_ENTRY_IN_LRU_FLAG;
if(ie_ptr->fd_child_count > 0)
flags |= H5C__MDCI_ENTRY_IS_FD_PARENT_FLAG;
if(ie_ptr->fd_parent_count > 0)
flags |= H5C__MDCI_ENTRY_IS_FD_CHILD_FLAG;
*p++ = flags;
*p++ = (uint8_t)(ie_ptr->ring);
*p++ = (uint8_t)(ie_ptr->age);
if(ie_ptr->fd_child_count > H5C__MDCI_MAX_FD_CHILDREN)
HGOTO_ERROR(H5E_CACHE, H5E_BADRANGE, FAIL, "fd_child_count out of range")
UINT16ENCODE(p, (uint16_t)(ie_ptr->fd_child_count));
if(ie_ptr->fd_dirty_child_count > H5C__MDCI_MAX_FD_CHILDREN)
HGOTO_ERROR(H5E_CACHE, H5E_BADRANGE, FAIL, "fd_dirty_child_count out of range")
UINT16ENCODE(p, (uint16_t)(ie_ptr->fd_dirty_child_count));
if(ie_ptr->fd_parent_count > H5C__MDCI_MAX_FD_PARENTS)
HGOTO_ERROR(H5E_CACHE, H5E_BADRANGE, FAIL, "fd_parent_count out of range")
UINT16ENCODE(p, (uint16_t)(ie_ptr->fd_parent_count));
INT32ENCODE(p, ie_ptr->lru_rank);
H5F_addr_encode(f, &p, ie_ptr->addr);
H5F_ENCODE_LENGTH(f, p, ie_ptr->size);
if((size_t)(p - *buf) != H5C__cache_image_block_entry_header_size(f))
HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "Bad entry image len")
for(u = 0; u < ie_ptr->fd_parent_count; u++)
H5F_addr_encode(f, &p, ie_ptr->fd_parent_addrs[u]);
H5MM_memcpy(p, ie_ptr->image_ptr, ie_ptr->size);
p += ie_ptr->size;
*buf = p;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5C__prep_for_file_close__compute_fd_heights(const H5C_t *cache_ptr)
{
H5C_cache_entry_t * entry_ptr;
H5C_cache_entry_t * parent_ptr;
unsigned entries_removed_from_image = 0;
unsigned external_parent_fd_refs_removed = 0;
unsigned external_child_fd_refs_removed = 0;
hbool_t done = FALSE;
unsigned u;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(cache_ptr);
HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
done = FALSE;
while(!done) {
done = TRUE;
entry_ptr = cache_ptr->il_head;
while(entry_ptr != NULL) {
HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
if(entry_ptr->image_dirty && entry_ptr->include_in_image &&
(entry_ptr->fd_parent_count > 0)) {
HDassert(entry_ptr->flush_dep_parent != NULL);
for(u = 0; u < entry_ptr->flush_dep_nparents; u++ ) {
parent_ptr = entry_ptr->flush_dep_parent[u];
HDassert(parent_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(entry_ptr->ring == parent_ptr->ring);
if(parent_ptr->is_dirty && !parent_ptr->include_in_image &&
entry_ptr->include_in_image) {
entries_removed_from_image++;
entry_ptr->include_in_image = FALSE;
}
}
}
entry_ptr = entry_ptr->il_next;
}
}
HDassert(entries_removed_from_image == 0);
entry_ptr = cache_ptr->il_head;
while(entry_ptr != NULL) {
if(!entry_ptr->include_in_image && entry_ptr->flush_dep_nparents > 0) {
HDassert(entry_ptr->flush_dep_parent != NULL);
for(u = 0; u < entry_ptr->flush_dep_nparents; u++ ) {
parent_ptr = entry_ptr->flush_dep_parent[u];
HDassert(parent_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(entry_ptr->ring == parent_ptr->ring);
if(parent_ptr->include_in_image) {
HDassert(parent_ptr->fd_child_count > 0);
parent_ptr->fd_child_count--;
if(entry_ptr->is_dirty) {
HDassert(parent_ptr->fd_dirty_child_count > 0);
parent_ptr->fd_dirty_child_count--;
}
external_child_fd_refs_removed++;
}
}
}
else if(entry_ptr->include_in_image && entry_ptr->flush_dep_nparents > 0) {
HDassert(entry_ptr->flush_dep_parent != NULL);
HDassert(entry_ptr->flush_dep_nparents == entry_ptr->fd_parent_count);
HDassert(entry_ptr->fd_parent_addrs);
for(u = 0; u < entry_ptr->flush_dep_nparents; u++ ) {
parent_ptr = entry_ptr->flush_dep_parent[u];
HDassert(parent_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(entry_ptr->ring == parent_ptr->ring);
if(!parent_ptr->include_in_image) {
HDassert(entry_ptr->fd_parent_count > 0);
parent_ptr->fd_child_count--;
HDassert(parent_ptr->addr == entry_ptr->fd_parent_addrs[u]);
entry_ptr->fd_parent_addrs[u] = HADDR_UNDEF;
external_parent_fd_refs_removed++;
}
}
if(entry_ptr->fd_parent_count == 0) {
H5MM_xfree(entry_ptr->fd_parent_addrs);
entry_ptr->fd_parent_addrs = NULL;
}
else if(entry_ptr->flush_dep_nparents > entry_ptr->fd_parent_count) {
haddr_t * old_fd_parent_addrs = entry_ptr->fd_parent_addrs;
unsigned v;
if(NULL == (entry_ptr->fd_parent_addrs = (haddr_t *)H5MM_calloc(sizeof(haddr_t) * (size_t)(entry_ptr->fd_parent_addrs))))
HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, "memory allocation failed for fd parent addr array")
v = 0;
for(u = 0; u < entry_ptr->flush_dep_nparents; u++) {
if(old_fd_parent_addrs[u] != HADDR_UNDEF) {
entry_ptr->fd_parent_addrs[v] = old_fd_parent_addrs[u];
v++;
}
}
HDassert(v == entry_ptr->fd_parent_count);
}
}
entry_ptr = entry_ptr->il_next;
}
HDassert(external_child_fd_refs_removed == 0);
HDassert(external_parent_fd_refs_removed == 0);
entry_ptr = cache_ptr->il_head;
while(entry_ptr != NULL) {
if(entry_ptr->include_in_image && entry_ptr->fd_child_count == 0 &&
entry_ptr->fd_parent_count > 0) {
for(u = 0; u < entry_ptr->fd_parent_count; u++) {
parent_ptr = entry_ptr->flush_dep_parent[u];
HDassert(parent_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
if(parent_ptr->include_in_image && parent_ptr->image_fd_height <= 0)
H5C__prep_for_file_close__compute_fd_heights_real(parent_ptr, 1);
}
}
entry_ptr = entry_ptr->il_next;
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static void
H5C__prep_for_file_close__compute_fd_heights_real(H5C_cache_entry_t *entry_ptr,
uint32_t fd_height)
{
FUNC_ENTER_STATIC_NOERR
HDassert(entry_ptr);
HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(entry_ptr->include_in_image);
HDassert((entry_ptr->image_fd_height == 0) || (entry_ptr->image_fd_height < fd_height));
HDassert(((fd_height == 0) && (entry_ptr->fd_child_count == 0)) || ((fd_height > 0) && (entry_ptr->fd_child_count > 0)));
entry_ptr->image_fd_height = fd_height;
if(entry_ptr->flush_dep_nparents > 0) {
unsigned u;
HDassert(entry_ptr->flush_dep_parent);
for(u = 0; u < entry_ptr->fd_parent_count; u++) {
H5C_cache_entry_t *parent_ptr;
parent_ptr = entry_ptr->flush_dep_parent[u];
HDassert(parent_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
if(parent_ptr->include_in_image && parent_ptr->image_fd_height <= fd_height)
H5C__prep_for_file_close__compute_fd_heights_real(parent_ptr, fd_height + 1);
}
}
FUNC_LEAVE_NOAPI_VOID
}
static herr_t
H5C__prep_for_file_close__setup_image_entries_array(H5C_t *cache_ptr)
{
H5C_cache_entry_t * entry_ptr;
H5C_image_entry_t * image_entries = NULL;
uint32_t entries_visited = 0;
unsigned u;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(cache_ptr);
HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
HDassert(cache_ptr->close_warning_received);
HDassert(cache_ptr->pl_len == 0);
HDassert(cache_ptr->num_entries_in_image > 0);
HDassert(cache_ptr->image_entries == NULL);
if(NULL == (image_entries = (H5C_image_entry_t *)H5MM_calloc(sizeof(H5C_image_entry_t) * (size_t)(cache_ptr->num_entries_in_image + 1))))
HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, "memory allocation failed for image_entries")
for(u = 0; u <= cache_ptr->num_entries_in_image; u++) {
image_entries[u].magic = H5C_IMAGE_ENTRY_T_MAGIC;
image_entries[u].addr = HADDR_UNDEF;
image_entries[u].ring = H5C_RING_UNDEFINED;
image_entries[u].type_id = -1;
}
u = 0;
entry_ptr = cache_ptr->il_head;
while(entry_ptr != NULL) {
HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
if(entry_ptr->include_in_image) {
HDassert(entry_ptr->image_up_to_date);
HDassert(entry_ptr->image_ptr);
HDassert(entry_ptr->type);
image_entries[u].addr = entry_ptr->addr;
image_entries[u].size = entry_ptr->size;
image_entries[u].ring = entry_ptr->ring;
if(entry_ptr->type->id == H5AC_PREFETCHED_ENTRY_ID) {
image_entries[u].type_id = entry_ptr->prefetch_type_id;
image_entries[u].age = entry_ptr->age + 1;
if(image_entries[u].age > H5AC__CACHE_IMAGE__ENTRY_AGEOUT__MAX)
image_entries[u].age = H5AC__CACHE_IMAGE__ENTRY_AGEOUT__MAX;
}
else {
image_entries[u].type_id = entry_ptr->type->id;
image_entries[u].age = 0;
}
image_entries[u].lru_rank = entry_ptr->lru_rank;
image_entries[u].is_dirty = entry_ptr->is_dirty;
image_entries[u].image_fd_height = entry_ptr->image_fd_height;
image_entries[u].fd_parent_count = entry_ptr->fd_parent_count;
image_entries[u].fd_parent_addrs = entry_ptr->fd_parent_addrs;
image_entries[u].fd_child_count = entry_ptr->fd_child_count;
image_entries[u].fd_dirty_child_count =
entry_ptr->fd_dirty_child_count;
image_entries[u].image_ptr = entry_ptr->image_ptr;
entry_ptr->fd_parent_count = 0;
entry_ptr->fd_parent_addrs = NULL;
u++;
HDassert(u <= cache_ptr->num_entries_in_image);
}
entries_visited++;
entry_ptr = entry_ptr->il_next;
}
HDassert(entries_visited == cache_ptr->index_len);
HDassert(u == cache_ptr->num_entries_in_image);
HDassert(image_entries[u].fd_parent_addrs == NULL);
HDassert(image_entries[u].image_ptr == NULL);
cache_ptr->image_entries = image_entries;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5C__prep_for_file_close__scan_entries(const H5F_t *f, H5C_t *cache_ptr)
{
H5C_cache_entry_t * entry_ptr;
hbool_t include_in_image;
unsigned entries_visited = 0;
int lru_rank = 1;
uint32_t num_entries_tentatively_in_image = 0;
uint32_t num_entries_in_image = 0;
size_t image_len;
size_t entry_header_len;
size_t fd_parents_list_len;
int i;
unsigned j;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(f);
HDassert(f->shared);
HDassert(f->shared->sblock);
HDassert(cache_ptr);
HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
HDassert(cache_ptr->close_warning_received);
HDassert(cache_ptr->pl_len == 0);
image_len = H5C__cache_image_block_header_size(f);
entry_header_len = H5C__cache_image_block_entry_header_size(f);
entry_ptr = cache_ptr->il_head;
while(entry_ptr != NULL) {
HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(entry_ptr->image_up_to_date);
HDassert(entry_ptr->image_ptr);
if(entry_ptr->ring > H5C_MAX_RING_IN_IMAGE)
include_in_image = FALSE;
else
include_in_image = TRUE;
entry_ptr->include_in_image = include_in_image;
if(include_in_image) {
entry_ptr->lru_rank = -1;
entry_ptr->image_dirty = entry_ptr->is_dirty;
entry_ptr->image_fd_height = 0;
if(entry_ptr->flush_dep_nparents > 0) {
if(entry_ptr->flush_dep_nparents == entry_ptr->fd_parent_count ) {
HDassert(entry_ptr->fd_parent_addrs);
}
else if(entry_ptr->fd_parent_count > 0) {
HDassert(entry_ptr->fd_parent_addrs);
entry_ptr->fd_parent_addrs = (haddr_t *)H5MM_xfree(entry_ptr->fd_parent_addrs);
}
else {
HDassert(entry_ptr->fd_parent_count == 0);
HDassert(entry_ptr->fd_parent_addrs == NULL);
}
entry_ptr->fd_parent_count = entry_ptr->flush_dep_nparents;
if(NULL == entry_ptr->fd_parent_addrs)
if(NULL == (entry_ptr->fd_parent_addrs = (haddr_t *)H5MM_malloc(sizeof(haddr_t) * (size_t)(entry_ptr->fd_parent_count))))
HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, "memory allocation failed for fd parent addrs buffer")
for(i = 0; i < (int)(entry_ptr->fd_parent_count); i++) {
entry_ptr->fd_parent_addrs[i] = entry_ptr->flush_dep_parent[i]->addr;
HDassert(H5F_addr_defined(entry_ptr->fd_parent_addrs[i]));
}
}
else if(entry_ptr->fd_parent_count > 0) {
HDassert(entry_ptr->fd_parent_addrs);
entry_ptr->fd_parent_addrs = (haddr_t *)H5MM_xfree(entry_ptr->fd_parent_addrs);
}
else
HDassert(entry_ptr->fd_parent_addrs == NULL);
if(entry_ptr->flush_dep_nchildren > 0) {
if(!entry_ptr->is_pinned)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "encountered unpinned fd parent?!?")
entry_ptr->fd_child_count = entry_ptr->flush_dep_nchildren;
entry_ptr->fd_dirty_child_count = entry_ptr->flush_dep_ndirty_children;
}
num_entries_tentatively_in_image++;
}
entries_visited++;
entry_ptr = entry_ptr->il_next;
}
HDassert(entries_visited == cache_ptr->index_len);
if(H5C__prep_for_file_close__compute_fd_heights(cache_ptr) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "computation of flush dependency heights failed?!?")
entries_visited = 0;
entry_ptr = cache_ptr->il_head;
while(entry_ptr != NULL) {
HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
if(entry_ptr->include_in_image) {
if(entry_ptr->fd_parent_count > 0)
fd_parents_list_len = (size_t)(H5F_SIZEOF_ADDR(f) * entry_ptr->fd_parent_count);
else
fd_parents_list_len = (size_t)0;
image_len += entry_header_len + fd_parents_list_len + entry_ptr->size;
num_entries_in_image++;
}
entries_visited++;
entry_ptr = entry_ptr->il_next;
}
HDassert(entries_visited == cache_ptr->index_len);
HDassert(num_entries_in_image <= num_entries_tentatively_in_image);
j = 0;
for(i = H5C_MAX_RING_IN_IMAGE + 1; i <= H5C_RING_SB; i++)
j += cache_ptr->index_ring_len[i];
HDassert(entries_visited == (num_entries_tentatively_in_image + j));
cache_ptr->num_entries_in_image = num_entries_in_image;
entries_visited = 0;
entry_ptr = cache_ptr->LRU_head_ptr;
while(entry_ptr != NULL) {
HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(entry_ptr->type != NULL);
if(entry_ptr->type->id == H5AC_EPOCH_MARKER_ID)
lru_rank++;
else if(entry_ptr->include_in_image) {
entry_ptr->lru_rank = lru_rank;
lru_rank++;
}
entries_visited++;
entry_ptr = entry_ptr->next;
}
HDassert(entries_visited == cache_ptr->LRU_list_len);
image_len += H5F_SIZEOF_CHKSUM;
cache_ptr->image_data_len = image_len;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5C__reconstruct_cache_contents(H5F_t *f, H5C_t *cache_ptr)
{
H5C_cache_entry_t * pf_entry_ptr;
H5C_cache_entry_t * parent_ptr;
const uint8_t * p;
unsigned u, v;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(f);
HDassert(f->shared);
HDassert(cache_ptr == f->shared->cache);
HDassert(cache_ptr);
HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
HDassert(cache_ptr->image_buffer);
HDassert(cache_ptr->image_len > 0);
p = (uint8_t *)cache_ptr->image_buffer;
if(H5C__decode_cache_image_header(f, cache_ptr, &p) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTDECODE, FAIL, "cache image header decode failed")
HDassert((size_t)(p - (uint8_t *)cache_ptr->image_buffer) < cache_ptr->image_len);
HDassert(cache_ptr->image_data_len > 0);
HDassert(cache_ptr->image_data_len <= cache_ptr->image_len);
HDassert(cache_ptr->num_entries_in_image > 0);
for(u = 0; u < cache_ptr->num_entries_in_image; u++) {
if(NULL == (pf_entry_ptr = H5C__reconstruct_cache_entry(f, cache_ptr, &p)))
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "reconstruction of cache entry failed")
H5C__INSERT_IN_INDEX(cache_ptr, pf_entry_ptr, FAIL)
if(pf_entry_ptr->is_dirty)
H5C__INSERT_ENTRY_IN_SLIST(cache_ptr, pf_entry_ptr, FAIL)
H5C__UPDATE_RP_FOR_INSERT_APPEND(cache_ptr, pf_entry_ptr, FAIL)
H5C__UPDATE_STATS_FOR_PREFETCH(cache_ptr, pf_entry_ptr->is_dirty)
for(v = 0; v < pf_entry_ptr->fd_parent_count; v++) {
HDassert(pf_entry_ptr->fd_parent_addrs);
HDassert(H5F_addr_defined(pf_entry_ptr->fd_parent_addrs[v]));
parent_ptr = NULL;
H5C__SEARCH_INDEX(cache_ptr, pf_entry_ptr->fd_parent_addrs[v], parent_ptr, FAIL)
if(parent_ptr == NULL)
HGOTO_ERROR(H5E_CACHE, H5E_NOTFOUND, FAIL, "fd parent not in cache?!?")
HDassert(parent_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(parent_ptr->addr == pf_entry_ptr->fd_parent_addrs[v]);
HDassert(parent_ptr->lru_rank == -1);
H5C__UPDATE_RP_FOR_PROTECT(cache_ptr, parent_ptr, FAIL)
parent_ptr->is_protected = TRUE;
if(H5C_create_flush_dependency(parent_ptr, pf_entry_ptr) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTDEPEND, FAIL, "Can't restore flush dependency")
H5C__UPDATE_RP_FOR_UNPROTECT(cache_ptr, parent_ptr, FAIL)
parent_ptr->is_protected = FALSE;
}
}
#ifndef NDEBUG
pf_entry_ptr = cache_ptr->il_head;
while(pf_entry_ptr != NULL) {
HDassert(pf_entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert((pf_entry_ptr->prefetched && pf_entry_ptr->type == H5AC_PREFETCHED_ENTRY)
|| (!pf_entry_ptr->prefetched && pf_entry_ptr->type != H5AC_PREFETCHED_ENTRY));
if(pf_entry_ptr->type == H5AC_PREFETCHED_ENTRY)
HDassert(pf_entry_ptr->fd_parent_count == pf_entry_ptr->flush_dep_nparents);
for(v = 0; v < pf_entry_ptr->fd_parent_count; v++) {
parent_ptr = pf_entry_ptr->flush_dep_parent[v];
HDassert(parent_ptr);
HDassert(parent_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(pf_entry_ptr->fd_parent_addrs);
HDassert(pf_entry_ptr->fd_parent_addrs[v] == parent_ptr->addr);
HDassert(parent_ptr->flush_dep_nchildren > 0);
}
if(pf_entry_ptr->type == H5AC_PREFETCHED_ENTRY) {
HDassert(pf_entry_ptr->fd_child_count == pf_entry_ptr->flush_dep_nchildren);
HDassert(pf_entry_ptr->fd_dirty_child_count == pf_entry_ptr->flush_dep_ndirty_children);
}
pf_entry_ptr = pf_entry_ptr->il_next;
}
{
int lru_rank_holes = 0;
H5C_cache_entry_t *entry_ptr;
int i;
i = -1;
entry_ptr = cache_ptr->LRU_head_ptr;
while(entry_ptr != NULL) {
HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(entry_ptr->type != NULL);
if ( entry_ptr->prefetched ) {
HDassert(entry_ptr->lru_rank != 0);
HDassert((entry_ptr->lru_rank == -1) ||
(entry_ptr->lru_rank > i));
if ( ( entry_ptr->lru_rank > 1 ) &&
( entry_ptr->lru_rank > i + 1 ) )
lru_rank_holes += entry_ptr->lru_rank - (i + 1);
i = entry_ptr->lru_rank;
}
entry_ptr = entry_ptr->next;
}
HDassert(lru_rank_holes <= H5C__MAX_EPOCH_MARKERS);
}
#endif
if(cache_ptr->index_size >= cache_ptr->max_cache_size) {
hbool_t write_permitted = FALSE;
if(cache_ptr->check_write_permitted != NULL) {
if((cache_ptr->check_write_permitted)(f, &write_permitted) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTPROTECT, FAIL, "Can't get write_permitted")
}
else
write_permitted = cache_ptr->write_permitted;
if(H5C__make_space_in_cache(f, 0, write_permitted) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTPROTECT, FAIL, "H5C__make_space_in_cache failed")
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static H5C_cache_entry_t *
H5C__reconstruct_cache_entry(const H5F_t *f, H5C_t *cache_ptr,
const uint8_t **buf)
{
H5C_cache_entry_t *pf_entry_ptr = NULL;
uint8_t flags = 0;
hbool_t is_dirty = FALSE;
#ifndef NDEBUG
hbool_t in_lru = FALSE;
hbool_t is_fd_parent = FALSE;
hbool_t is_fd_child = FALSE;
#endif
const uint8_t * p;
hbool_t file_is_rw;
H5C_cache_entry_t *ret_value = NULL;
FUNC_ENTER_STATIC
HDassert(cache_ptr);
HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
HDassert(cache_ptr->num_entries_in_image > 0);
HDassert(buf && *buf);
file_is_rw = cache_ptr->delete_image;
if(NULL == (pf_entry_ptr = H5FL_CALLOC(H5C_cache_entry_t)))
HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, NULL, "memory allocation failed for prefetched cache entry")
p = *buf;
pf_entry_ptr->prefetch_type_id = *p++;
flags = *p++;
if(flags & H5C__MDCI_ENTRY_DIRTY_FLAG)
is_dirty = TRUE;
#ifndef NDEBUG
if(flags & H5C__MDCI_ENTRY_IN_LRU_FLAG)
in_lru = TRUE;
if(flags & H5C__MDCI_ENTRY_IS_FD_PARENT_FLAG)
is_fd_parent = TRUE;
if(flags & H5C__MDCI_ENTRY_IS_FD_CHILD_FLAG)
is_fd_child = TRUE;
#endif
pf_entry_ptr->is_dirty = (is_dirty && file_is_rw);
pf_entry_ptr->ring = *p++;
HDassert(pf_entry_ptr->ring > (uint8_t)(H5C_RING_UNDEFINED));
HDassert(pf_entry_ptr->ring < (uint8_t)(H5C_RING_NTYPES));
pf_entry_ptr->age = *p++;
UINT16DECODE(p, pf_entry_ptr->fd_child_count);
HDassert((is_fd_parent && pf_entry_ptr->fd_child_count > 0) || (!is_fd_parent && pf_entry_ptr->fd_child_count == 0));
UINT16DECODE(p, pf_entry_ptr->fd_dirty_child_count);
if(!file_is_rw)
pf_entry_ptr->fd_dirty_child_count = 0;
if(pf_entry_ptr->fd_dirty_child_count > pf_entry_ptr->fd_child_count)
HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, NULL, "invalid dirty flush dependency child count")
UINT16DECODE(p, pf_entry_ptr->fd_parent_count);
HDassert((is_fd_child && pf_entry_ptr->fd_parent_count > 0) || (!is_fd_child && pf_entry_ptr->fd_parent_count == 0));
INT32DECODE(p, pf_entry_ptr->lru_rank);
HDassert((in_lru && pf_entry_ptr->lru_rank >= 0) || (!in_lru && pf_entry_ptr->lru_rank == -1));
H5F_addr_decode(f, &p, &pf_entry_ptr->addr);
if(!H5F_addr_defined(pf_entry_ptr->addr))
HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, NULL, "invalid entry offset")
H5F_DECODE_LENGTH(f, p, pf_entry_ptr->size);
if(pf_entry_ptr->size == 0)
HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, NULL, "invalid entry size")
if((size_t)(p - *buf) != H5C__cache_image_block_entry_header_size(f))
HGOTO_ERROR(H5E_CACHE, H5E_BADSIZE, NULL, "Bad entry image len")
if(pf_entry_ptr->fd_parent_count > 0) {
unsigned u;
if(NULL == (pf_entry_ptr->fd_parent_addrs = (haddr_t *)H5MM_malloc((size_t)(pf_entry_ptr->fd_parent_count) * H5F_SIZEOF_ADDR(f))))
HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, NULL, "memory allocation failed for fd parent addrs buffer")
for(u = 0; u < pf_entry_ptr->fd_parent_count; u++) {
H5F_addr_decode(f, &p, &(pf_entry_ptr->fd_parent_addrs[u]));
if(!H5F_addr_defined(pf_entry_ptr->fd_parent_addrs[u]))
HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, NULL, "invalid flush dependency parent offset")
}
}
if(NULL == (pf_entry_ptr->image_ptr = H5MM_malloc(pf_entry_ptr->size + H5C_IMAGE_EXTRA_SPACE)))
HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, NULL, "memory allocation failed for on disk image buffer")
#if H5C_DO_MEMORY_SANITY_CHECKS
H5MM_memcpy(((uint8_t *)pf_entry_ptr->image_ptr) + size, H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE);
#endif
H5MM_memcpy(pf_entry_ptr->image_ptr, p, pf_entry_ptr->size);
p += pf_entry_ptr->size;
pf_entry_ptr->magic = H5C__H5C_CACHE_ENTRY_T_MAGIC;
pf_entry_ptr->cache_ptr = cache_ptr;
pf_entry_ptr->image_up_to_date = TRUE;
pf_entry_ptr->type = H5AC_PREFETCHED_ENTRY;
pf_entry_ptr->prefetched = TRUE;
pf_entry_ptr->prefetched_dirty = is_dirty && (!file_is_rw);
HDassert(pf_entry_ptr->size > 0 && pf_entry_ptr->size < H5C_MAX_ENTRY_SIZE);
*buf = p;
ret_value = pf_entry_ptr;
done:
if(NULL == ret_value && pf_entry_ptr)
pf_entry_ptr = H5FL_FREE(H5C_cache_entry_t, pf_entry_ptr);
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5C__write_cache_image_superblock_msg(H5F_t *f, hbool_t create)
{
H5C_t * cache_ptr;
H5O_mdci_t mdci_msg;
unsigned mesg_flags = H5O_MSG_FLAG_FAIL_IF_UNKNOWN_ALWAYS;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(f);
HDassert(f->shared);
HDassert(f->shared->cache);
cache_ptr = f->shared->cache;
HDassert(cache_ptr);
HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
HDassert(cache_ptr->close_warning_received);
mdci_msg.addr = cache_ptr->image_addr;
#ifdef H5_HAVE_PARALLEL
if(cache_ptr->aux_ptr) {
H5AC_aux_t * aux_ptr;
aux_ptr = (H5AC_aux_t *)cache_ptr->aux_ptr;
HDassert(aux_ptr->magic == H5AC__H5AC_AUX_T_MAGIC);
mdci_msg.size = aux_ptr->p0_image_len;
}
else
#endif
mdci_msg.size = cache_ptr->image_len;
if(H5F__super_ext_write_msg(f, H5O_MDCI_MSG_ID, &mdci_msg, create, mesg_flags) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_WRITEERROR, FAIL, "can't write metadata cache image message to superblock extension")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5C__write_cache_image(H5F_t *f, const H5C_t *cache_ptr)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(f);
HDassert(cache_ptr);
HDassert(H5F_addr_defined(cache_ptr->image_addr));
HDassert(cache_ptr->image_len > 0);
HDassert(cache_ptr->image_buffer);
#ifdef H5_HAVE_PARALLEL
{
H5AC_aux_t *aux_ptr = (H5AC_aux_t *)cache_ptr->aux_ptr;
if((NULL == aux_ptr) || (aux_ptr->mpi_rank == 0)) {
HDassert((NULL == aux_ptr) || (aux_ptr->magic == H5AC__H5AC_AUX_T_MAGIC));
#endif
if(H5F_block_write(f, H5FD_MEM_SUPER, cache_ptr->image_addr, cache_ptr->image_len, cache_ptr->image_buffer) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "can't write metadata cache image block to file")
#ifdef H5_HAVE_PARALLEL
}
}
#endif
done:
FUNC_LEAVE_NOAPI(ret_value)
}