summaryrefslogtreecommitdiffstats
path: root/src/H5C.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5C.c')
-rw-r--r--src/H5C.c1044
1 files changed, 858 insertions, 186 deletions
diff --git a/src/H5C.c b/src/H5C.c
index 52c8dfa..bd2d2e2 100644
--- a/src/H5C.c
+++ b/src/H5C.c
@@ -322,14 +322,21 @@ H5C_create(size_t max_cache_size,
cache_ptr->slist_ring_size[i] = (size_t)0;
} /* end for */
- for(i = 0; i < H5C__HASH_TABLE_LEN; i++)
+ for(i = 0; i < H5C__HASH_TABLE_LEN; i++) {
(cache_ptr->index)[i] = NULL;
+ }
cache_ptr->il_len = 0;
cache_ptr->il_size = (size_t)0;
cache_ptr->il_head = NULL;
cache_ptr->il_tail = NULL;
+ /* Fields supporting VFD SWMR */
+ cache_ptr->vfd_swmr_reader = FALSE;
+ for(i = 0; i < H5C__PAGE_HASH_TABLE_LEN; i++) {
+ (cache_ptr->page_index)[i] = NULL;
+ }
+
/* Tagging Field Initializations */
cache_ptr->ignore_tags = FALSE;
@@ -735,8 +742,9 @@ herr_t
H5C_prep_for_file_close(H5F_t *f)
{
H5C_t * cache_ptr;
- hbool_t image_generated = FALSE; /* Whether a cache image was generated */
- herr_t ret_value = SUCCEED; /* Return value */
+ hbool_t image_generated = FALSE; /* Whether a cache image was */
+ /* generated */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
@@ -914,6 +922,358 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5C_evict_or_refresh_all_entries_in_page
+ *
+ * Purpose: When a file is opened in VFD SWMR reader mode, we must be
+ * able to ensure that the metadata cache contains no stale
+ * entries at the end of each tick.
+ *
+ * To do this, we must identify pages that have changed in
+ * the last tick, and either evict, or refresh all modified
+ * entries in the modified pages. If an evicted entry is
+ * needed subsequently, it must be reloaded, almost always
+ * from the metadata file.
+ *
+ * This function performs this function of a given page buffer
+ * page.
+ *
+ * This is done by mapping the supplied page to associated
+ * hash bucket in the page_index, and then scanning the
+ * contents of the bucket for entries residing in the
+ * target page.
+ *
+ * For each such entry, we test to see if it is pinned.
+ * If it is not, we simply evict it.
+ *
+ * Pinned entries may in turn be divided into tagged and
+ * un-tagged entries.
+ *
+ * For pinned tagged entries, it would be best if we could
+ * simply tell the associated cache client to refresh it.
+ * However, until we have that facility, we look up its tag,
+ * and evict all entries associated with that on disk object.
+ *
+ * For pinned, un-tagged entries (i.e. super block, global
+ * heaps, etc. we must instruct the client to refresh the
+ * entry. Fortunately, this is only necessary for the
+ * super block in the initial VFD SWMR implementation.
+ *
+ * Note that there is also the possibility that while the
+ * page was modified, one or more metadata entries in
+ * that page were not. Eventually we should write code
+ * to detect this -- but not for the prototype.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: John Mainzer -- 12/16/18
+ *
+ * Changes: None.
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5C_evict_or_refresh_all_entries_in_page(H5F_t * f, uint64_t page,
+ uint64_t tick)
+{
+ int i;
+ size_t image_len;
+ size_t original_image_len;
+ void * image_ptr = NULL;
+ void * new_image_ptr = NULL;
+ unsigned flush_flags = (H5C__FLUSH_INVALIDATE_FLAG |
+ H5C__FLUSH_CLEAR_ONLY_FLAG);
+ haddr_t tag;
+ H5PB_t * pb_ptr = NULL;
+ H5C_t * cache_ptr = NULL;
+ H5C_cache_entry_t * entry_ptr;
+ H5C_cache_entry_t * follow_ptr = NULL;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity check */
+ HDassert(f);
+ HDassert(f->shared);
+
+ cache_ptr = f->shared->cache;
+
+ HDassert(cache_ptr);
+ HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
+ HDassert(cache_ptr->vfd_swmr_reader);
+
+ /* since file must be opened R/O for a VFD SWMR reader, the skip
+ * list must be empty. Verify this.
+ */
+ HDassert(cache_ptr->slist_len == 0);
+
+ pb_ptr = f->shared->pb_ptr;
+
+ HDassert(pb_ptr);
+ HDassert(pb_ptr->magic == H5PB__H5PB_T_MAGIC);
+
+ i = H5C__PI_HASH_FCN(page);
+
+ entry_ptr = (cache_ptr->page_index)[i];
+
+ while (entry_ptr) {
+
+ HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+
+ if ( entry_ptr->page == page ) {
+
+ HDassert(entry_ptr->addr >= (haddr_t)(page * pb_ptr->page_size));
+ HDassert(entry_ptr->addr < (haddr_t)((page+1) * pb_ptr->page_size));
+
+ /* since end of tick occurs only on API call entry in
+ * the VFD SWMR reader case, the entry must not be protected.
+ *
+ * since the VFD SWMR reader must have opened the file R/O,
+ * the entry must be clean.
+ */
+ HDassert(!(entry_ptr->is_protected));
+ HDassert(!(entry_ptr->is_dirty));
+
+ /* we must evict the entry, as page has been modified, and
+ * thus the entry may be out of date.
+ *
+ * Note that we should eventually modify this code to be more
+ * intelligent, and only evict entries if they have in fact changed.
+ * However, no time for that in the first cut.
+ */
+ if ( entry_ptr->is_pinned ) {
+
+ if ( entry_ptr->tag_info ) {
+
+ tag = entry_ptr->tag_info->tag;
+
+ HDassert(!(entry_ptr->tag_info->corked));
+
+ /* passing TRUE for the match_global parameter. Look
+ * into this and verify that it is the right thing to
+ * do.
+ */
+ if ( H5C_evict_tagged_entries(f, tag, TRUE) < 0 )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTEXPUNGE, FAIL, \
+ "can't evict pinned and tagged entries")
+
+ /* *entry_ptr should be evicted -- set entry_ptr to NULL */
+ entry_ptr = NULL;
+
+ } else if ( entry_ptr->type->refresh ) {
+ /* If the entry is pinned and not tagged, it is a global
+ * object such as the super block, persistant free
+ * space manager, or a global heap.
+ *
+ * In this case, we must either refresh the entry,
+ * or verify that it has not changed, and that no
+ * action is required.
+ *
+ * For the initial prototype, we avoid global heaps,
+ * and claim that we need not concern ourselves with
+ * free space managers, since the VFD SWMR reader opens
+ * the file R/O.
+ */
+
+ /* 1) Get the on disk size of the entry. Since the
+ * the entry is already loaded, we can use the
+ * size listed in the entry.
+ *
+ * This will almost always be correct, but we
+ * allow a second try as it is possible that the
+ * version of the entry may change on the writer.
+ */
+ image_len = entry_ptr->size;
+ original_image_len = image_len;
+
+ /* 2) Allocate and read the buffer.
+ *
+ * Note that this will be satisfied from the metadata
+ * file via the VFD SWMR reade VFD.
+ *
+ * For this reason, we don't nead to check for reads
+ * past the EOA. Torn reads and checksums are also
+ * not an issue, since pages in the metadata file
+ * are checksumed and re-tried if necessary in the
+ * VFD SWMR reader VFD.
+ */
+ if ( NULL == (image_ptr = (uint8_t *)
+ H5MM_malloc(image_len + H5C_IMAGE_EXTRA_SPACE)) )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, \
+ "memory allocation failed for image buffer")
+
+#if H5C_DO_MEMORY_SANITY_CHECKS
+ HDmemcpy(image_ptr + image_len, H5C_IMAGE_SANITY_VALUE,
+ H5C_IMAGE_EXTRA_SPACE);
+#endif /* H5C_DO_MEMORY_SANITY_CHECKS */
+
+ if ( H5F_block_read(f, entry_ptr->type->mem_type,
+ entry_ptr->addr,
+ image_len, image_ptr) < 0 )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_READERROR, FAIL, \
+ "Can't read image (1)")
+
+ /* 3) Call the refresh callback. If it doesn't
+ * request a different image size, goto 6)
+ */
+ if ( entry_ptr->type->refresh(f, (void *)entry_ptr,
+ image_ptr, &image_len) < 0 )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTLOAD, FAIL, \
+ "Can't refresh entry (1)")
+
+ if ( image_len != original_image_len ) {
+
+ /* 4) If image_len has changed, re-allocate and re-read
+ * the image.
+ *
+ * Note: Generate a log entry in this case
+ */
+
+ if ( NULL == (new_image_ptr = H5MM_realloc(image_ptr,
+ image_len + H5C_IMAGE_EXTRA_SPACE)) )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, \
+ "re-alloc of image buffer failed.")
+
+ image_ptr = new_image_ptr;
+
+#if H5C_DO_MEMORY_SANITY_CHECKS
+ HDmemcpy(image_ptr + image_len, H5C_IMAGE_SANITY_VALUE,
+ H5C_IMAGE_EXTRA_SPACE);
+#endif /* H5C_DO_MEMORY_SANITY_CHECKS */
+
+ if ( H5F_block_read(f, entry_ptr->type->mem_type,
+ entry_ptr->addr,
+ image_len, image_ptr) < 0 )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_READERROR, FAIL, \
+ "Can't read image (2)")
+
+ /* 5) Call the refresh callback again. Requesting
+ * a different buffer size again is an error.
+ */
+ original_image_len = image_len;
+ if ( entry_ptr->type->refresh(f, (void *)entry_ptr,
+ image_ptr,
+ &image_len) < 0 )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTLOAD, FAIL, \
+ "Can't refresh entry (2)")
+
+ if ( image_len != original_image_len )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "2nd refresh call changed image_len.")
+ }
+
+ /* 6) Mark the entry as having been looked at this
+ * this tick to accooadate later sanity chackes.
+ */
+ entry_ptr->refreshed_in_tick = tick;
+
+ /* 7) Free the old image if it exists, and replace
+ * it with the new image.
+ */
+ if ( entry_ptr->image_ptr ) {
+
+ entry_ptr->image_ptr = H5MM_xfree(entry_ptr->image_ptr);
+ }
+ entry_ptr->image_ptr = image_ptr;
+
+ /* 8) Since *entry_ptr has been refreshed and not
+ * evicted, we can leave entry_ptr defined, and
+ * and continue the scan of the bucket from
+ * that point.
+ */
+
+ } else {
+
+ /* The entry is pinned, is not tagged, and has no
+ * callback.
+ *
+ * This should be un-reachable. If it is reached, we
+ * probably have another refresh callback to write.
+ */
+ HDassert(FALSE);
+ }
+ } else { /* simply evict the entry */
+
+ /* since the entry is clean, it must not be on the
+ * skip list -- thus no need for the
+ * H5C__DEL_FROM_SLIST_ON_DESTROY_FLAG.
+ */
+ if ( H5C__flush_single_entry(f, entry_ptr, flush_flags) < 0 )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTEXPUNGE, FAIL, \
+ "can't evict unpinned entry")
+
+ /* *entry_ptr should be evicted -- set entry_ptr to NULL */
+ entry_ptr = NULL;
+ }
+
+ /* If entry_ptr is NULL, it was evicted, and we must continue
+ * the scan from follow_ptr, or start at the head of the
+ * bucket list it follow_ptr is NULL as well.
+ *
+ * If follow_ptr isn't NULL, set entry_ptr to follow_ptr->pi_next.
+ * Otherwise, set entry_ptr to point to the first item in the hash
+ * bucket.
+ */
+ if ( entry_ptr ) {
+
+ /* *entry_ptr was refreshed, not evicted. Continue the
+ * the scan from that point, and update follow_ptr.
+ */
+ follow_ptr = entry_ptr;
+ entry_ptr = entry_ptr->pi_next;
+
+ } else if ( follow_ptr ) {
+
+ /* *entry_ptr was evicted. Since follow_ptr is not NULL,
+ * we can continue the scan from that point.
+ */
+ entry_ptr = follow_ptr->pi_next;
+
+ } else {
+
+ /* follow_ptr is null as well, so we have to re-start
+ * the scan from the head of the page index bucket list.
+ */
+
+ entry_ptr = (cache_ptr->page_index)[i];
+ }
+ } else {
+
+ /* entry belongs to another page -- skip it and go on. */
+ follow_ptr = entry_ptr;
+ entry_ptr = entry_ptr->pi_next;
+ }
+ } /* end while */
+
+ /* at this point, all entries residing in the target page should have
+ * been either evicted or refreshed -- verify this.
+ */
+ entry_ptr = (cache_ptr->page_index)[i];
+
+ while (entry_ptr) {
+
+ HDassert((entry_ptr->page != page) ||
+ (entry_ptr->refreshed_in_tick == tick));;
+
+ entry_ptr = entry_ptr->pi_next;
+ }
+
+done:
+
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* H5C_evict_or_refresh_all_entries_in_page() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5C_expunge_entry
*
* Purpose: Use this function to tell the cache to expunge an entry
@@ -932,7 +1292,8 @@ H5C_expunge_entry(H5F_t *f, const H5C_class_t *type, haddr_t addr, unsigned flag
{
H5C_t * cache_ptr;
H5C_cache_entry_t * entry_ptr = NULL;
- unsigned flush_flags = (H5C__FLUSH_INVALIDATE_FLAG | H5C__FLUSH_CLEAR_ONLY_FLAG);
+ unsigned flush_flags = (H5C__FLUSH_INVALIDATE_FLAG |
+ H5C__FLUSH_CLEAR_ONLY_FLAG);
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
@@ -1246,7 +1607,8 @@ H5C_insert_entry(H5F_t * f,
hbool_t insert_pinned;
hbool_t flush_last;
#ifdef H5_HAVE_PARALLEL
- hbool_t coll_access = FALSE; /* whether access to the cache entry is done collectively */
+ hbool_t coll_access = FALSE; /* whether access to the cache */
+ /* entry is done collectively */
#endif /* H5_HAVE_PARALLEL */
hbool_t set_flush_marker;
hbool_t write_permitted = TRUE;
@@ -1265,6 +1627,14 @@ H5C_insert_entry(H5F_t * f,
HDassert( cache_ptr );
HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC );
+
+ /* if this is a VFD SWMR reader, verify that the page buffer is
+ * configured.
+ */
+ HDassert( ( ! cache_ptr->vfd_swmr_reader ) ||
+ ( ( f->shared->pb_ptr ) &&
+ ( f->shared->pb_ptr->magic == H5PB__H5PB_T_MAGIC ) ) );
+
HDassert( type );
HDassert( type->mem_type == cache_ptr->class_table_ptr[type->id]->mem_type );
HDassert( type->image_len );
@@ -1297,9 +1667,13 @@ H5C_insert_entry(H5F_t * f,
if(test_entry_ptr != NULL) {
if(test_entry_ptr == entry_ptr)
+
HGOTO_ERROR(H5E_CACHE, H5E_CANTINS, FAIL, "entry already in cache")
+
else
- HGOTO_ERROR(H5E_CACHE, H5E_CANTINS, FAIL, "duplicate entry in cache")
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTINS, FAIL, \
+ "duplicate entry in cache")
} /* end if */
entry_ptr->magic = H5C__H5C_CACHE_ENTRY_T_MAGIC;
@@ -1369,25 +1743,39 @@ H5C_insert_entry(H5F_t * f,
#endif /* H5_HAVE_PARALLEL */
/* initialize cache image related fields */
- entry_ptr->include_in_image = FALSE;
- entry_ptr->lru_rank = 0;
- entry_ptr->image_dirty = FALSE;
- entry_ptr->fd_parent_count = 0;
- entry_ptr->fd_parent_addrs = NULL;
- entry_ptr->fd_child_count = 0;
- entry_ptr->fd_dirty_child_count = 0;
- entry_ptr->image_fd_height = 0;
- entry_ptr->prefetched = FALSE;
- entry_ptr->prefetch_type_id = 0;
- entry_ptr->age = 0;
- entry_ptr->prefetched_dirty = FALSE;
+ entry_ptr->include_in_image = FALSE;
+ entry_ptr->lru_rank = 0;
+ entry_ptr->image_dirty = FALSE;
+ entry_ptr->fd_parent_count = 0;
+ entry_ptr->fd_parent_addrs = NULL;
+ entry_ptr->fd_child_count = 0;
+ entry_ptr->fd_dirty_child_count = 0;
+ entry_ptr->image_fd_height = 0;
+ entry_ptr->prefetched = FALSE;
+ entry_ptr->prefetch_type_id = 0;
+ entry_ptr->age = 0;
+ entry_ptr->prefetched_dirty = FALSE;
#ifndef NDEBUG /* debugging field */
- entry_ptr->serialization_count = 0;
+ entry_ptr->serialization_count = 0;
#endif /* NDEBUG */
- entry_ptr->tl_next = NULL;
- entry_ptr->tl_prev = NULL;
- entry_ptr->tag_info = NULL;
+ /* initialize tag list fields */
+ entry_ptr->tl_next = NULL;
+ entry_ptr->tl_prev = NULL;
+ entry_ptr->tag_info = NULL;
+
+ /* initialize fields supporting VFD SWMR */
+ if ( cache_ptr->vfd_swmr_reader ) {
+
+ entry_ptr->page = (addr / f->shared->pb_ptr->page_size);
+
+ } else {
+
+ entry_ptr->page = 0;
+ }
+ entry_ptr->refreshed_in_tick = 0;
+ entry_ptr->pi_next = NULL;
+ entry_ptr->pi_prev = NULL;
/* Apply tag to newly inserted entry */
if(H5C__tag_entry(cache_ptr, entry_ptr) < 0)
@@ -1396,36 +1784,60 @@ H5C_insert_entry(H5F_t * f,
H5C__RESET_CACHE_ENTRY_STATS(entry_ptr)
- if(cache_ptr->flash_size_increase_possible &&
- (entry_ptr->size > cache_ptr->flash_size_increase_threshold))
- if(H5C__flash_increase_cache_size(cache_ptr, 0, entry_ptr->size) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTINS, FAIL, "H5C__flash_increase_cache_size failed")
+ if ( cache_ptr->flash_size_increase_possible &&
+ ( entry_ptr->size > cache_ptr->flash_size_increase_threshold ) ) {
+
+ if ( H5C__flash_increase_cache_size(cache_ptr, 0, entry_ptr->size) < 0 )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTINS, FAIL, \
+ "H5C__flash_increase_cache_size failed")
+ }
+
+ if(cache_ptr->index_size >= cache_ptr->max_cache_size) {
- if(cache_ptr->index_size >= cache_ptr->max_cache_size)
empty_space = 0;
- else
+
+ } else {
+
empty_space = cache_ptr->max_cache_size - cache_ptr->index_size;
+ }
- if(cache_ptr->evictions_enabled &&
- (((cache_ptr->index_size + entry_ptr->size) > cache_ptr->max_cache_size)
+ if ( ( cache_ptr->evictions_enabled ) &&
+ ( ( (cache_ptr->index_size + entry_ptr->size) >
+ cache_ptr->max_cache_size
+ )
||
- (((empty_space + cache_ptr->clean_index_size) < cache_ptr->min_clean_size)))) {
+ ( (empty_space + cache_ptr->clean_index_size) <
+ cache_ptr->min_clean_size
+ )
+ )
+ ) {
size_t space_needed;
- if(empty_space <= entry_ptr->size)
+ if ( empty_space <= entry_ptr->size ) {
+
cache_ptr->cache_full = TRUE;
+ }
+
+ if ( cache_ptr->check_write_permitted != NULL ) {
+
+ if ( ( cache_ptr->check_write_permitted)(f, &write_permitted) < 0 )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTINS, FAIL, \
+ "Can't get write_permitted")
+
+ } else {
- if(cache_ptr->check_write_permitted != NULL) {
- if((cache_ptr->check_write_permitted)(f, &write_permitted) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTINS, FAIL, "Can't get write_permitted")
- } /* end if */
- else
write_permitted = cache_ptr->write_permitted;
+ }
HDassert(entry_ptr->size <= H5C_MAX_ENTRY_SIZE);
space_needed = entry_ptr->size;
- if(space_needed > cache_ptr->max_cache_size)
+
+ if ( space_needed > cache_ptr->max_cache_size ) {
+
space_needed = cache_ptr->max_cache_size;
+ }
/* Note that space_needed is just the amount of space that
* needed to insert the new entry without exceeding the cache
@@ -1452,8 +1864,10 @@ H5C_insert_entry(H5F_t * f,
* no point in worrying about the third.
*/
- if(H5C__make_space_in_cache(f, space_needed, write_permitted) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTINS, FAIL, "H5C__make_space_in_cache failed")
+ if ( H5C__make_space_in_cache(f, space_needed, write_permitted) < 0 )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTINS, FAIL, \
+ "H5C__make_space_in_cache failed")
} /* end if */
H5C__INSERT_IN_INDEX(cache_ptr, entry_ptr, FAIL)
@@ -1468,42 +1882,63 @@ H5C_insert_entry(H5F_t * f,
if((H5C_validate_protected_entry_list(cache_ptr) < 0) ||
(H5C_validate_pinned_entry_list(cache_ptr) < 0) ||
(H5C_validate_lru_list(cache_ptr) < 0))
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "an extreme sanity check failed just before done")
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "an extreme sanity check failed just before done")
#endif /* H5C_DO_EXTREME_SANITY_CHECKS */
/* If the entry's type has a 'notify' callback send a 'after insertion'
* notice now that the entry is fully integrated into the cache.
*/
- if(entry_ptr->type->notify &&
- (entry_ptr->type->notify)(H5C_NOTIFY_ACTION_AFTER_INSERT, entry_ptr) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, "can't notify client about entry inserted into cache")
+ if ( ( entry_ptr->type->notify ) &&
+ ( (entry_ptr->type->notify)(H5C_NOTIFY_ACTION_AFTER_INSERT,
+ entry_ptr) < 0 ) )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, \
+ "can't notify client about entry inserted into cache")
H5C__UPDATE_STATS_FOR_INSERTION(cache_ptr, entry_ptr)
#ifdef H5_HAVE_PARALLEL
if(H5F_HAS_FEATURE(f, H5FD_FEAT_HAS_MPI)) {
+
coll_access = (H5P_USER_TRUE == f->coll_md_read ? TRUE : FALSE);
- /* If not explicitly disabled, get the cmdr setting from the API context */
- if(!coll_access && H5P_FORCE_FALSE != f->coll_md_read)
+ /* If not explicitly disabled, get the cmdr setting from the
+ * API context
+ */
+ if(!coll_access && H5P_FORCE_FALSE != f->coll_md_read) {
+
coll_access = H5CX_get_coll_metadata_read();
+ }
} /* end if */
entry_ptr->coll_access = coll_access;
+
if(coll_access) {
H5C__INSERT_IN_COLL_LIST(cache_ptr, entry_ptr, FAIL)
- /* Make sure the size of the collective entries in the cache remain in check */
+ /* Make sure the size of the collective entries in the cache
+ * remain in check
+ */
if(H5P_USER_TRUE == f->coll_md_read) {
- if(cache_ptr->max_cache_size * 80 < cache_ptr->coll_list_size * 100) {
+
+ if ( cache_ptr->max_cache_size * 80 <
+ cache_ptr->coll_list_size * 100) {
+
if(H5C_clear_coll_entries(cache_ptr, TRUE) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "can't clear collective metadata entries")
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \
+ "can't clear collective metadata entries")
} /* end if */
} /* end if */
else {
- if(cache_ptr->max_cache_size * 40 < cache_ptr->coll_list_size * 100) {
+ if ( cache_ptr->max_cache_size * 40 <
+ cache_ptr->coll_list_size * 100) {
+
if(H5C_clear_coll_entries(cache_ptr, TRUE) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "can't clear collective metadata entries")
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \
+ "can't clear collective metadata entries")
} /* end if */
} /* end else */
} /* end if */
@@ -1514,14 +1949,17 @@ done:
if((H5C_validate_protected_entry_list(cache_ptr) < 0) ||
(H5C_validate_pinned_entry_list(cache_ptr) < 0) ||
(H5C_validate_lru_list(cache_ptr) < 0))
- HDONE_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "an extreme sanity check failed on exit")
+ HDONE_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "an extreme sanity check failed on exit")
#endif /* H5C_DO_EXTREME_SANITY_CHECKS */
if(ret_value < 0 && entry_tagged)
if(H5C__untag_entry(cache_ptr, entry_ptr) < 0)
- HDONE_ERROR(H5E_CACHE, H5E_CANTREMOVE, FAIL, "can't remove entry from tag list")
+ HDONE_ERROR(H5E_CACHE, H5E_CANTREMOVE, FAIL, \
+ "can't remove entry from tag list")
FUNC_LEAVE_NOAPI(ret_value)
+
} /* H5C_insert_entry() */
@@ -1817,39 +2255,68 @@ done:
* Programmer: John Mainzer
* 6/2/04
*
+ * Changes: Added code to update cache entry page field required
+ * by VFD SWMR. To do this, we need the page size used
+ * by the page buffer. The simple way to do this was to
+ * replace the cache_ptr parameter with a pointer to the
+ * H5F_t, and then lookup the cache_ptr and pb_ptr as
+ * required.
+ * JRM -- 12/13/18
+ *
*-------------------------------------------------------------------------
*/
herr_t
-H5C_move_entry(H5C_t * cache_ptr,
- const H5C_class_t * type,
- haddr_t old_addr,
- haddr_t new_addr)
+H5C_move_entry(H5F_t * f,
+ const H5C_class_t * type,
+ haddr_t old_addr,
+ haddr_t new_addr)
{
+ H5C_t * cache_ptr = NULL;
H5C_cache_entry_t * entry_ptr = NULL;
H5C_cache_entry_t * test_entry_ptr = NULL;
- herr_t ret_value = SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
+ /* sanity checks */
+ HDassert(f);
+ HDassert(f->shared);
+
+ cache_ptr = f->shared->cache;
+
HDassert(cache_ptr);
HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
+
+ /* if this is a VFD SWMR reader, verify that the page buffer is
+ * configured.
+ */
+ HDassert(( ! cache_ptr->vfd_swmr_reader ) ||
+ ( ( f->shared->pb_ptr ) &&
+ ( f->shared->pb_ptr->magic == H5PB__H5PB_T_MAGIC ) ));
+
+
+
HDassert(type);
HDassert(H5F_addr_defined(old_addr));
HDassert(H5F_addr_defined(new_addr));
HDassert(H5F_addr_ne(old_addr, new_addr));
#if H5C_DO_EXTREME_SANITY_CHECKS
- if((H5C_validate_protected_entry_list(cache_ptr) < 0) ||
- (H5C_validate_pinned_entry_list(cache_ptr) < 0) ||
- (H5C_validate_lru_list(cache_ptr) < 0))
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "an extreme sanity check failed on entry")
+ if ( ( H5C_validate_protected_entry_list(cache_ptr) < 0 ) ||
+ ( H5C_validate_pinned_entry_list(cache_ptr) < 0 ) ||
+ ( H5C_validate_lru_list(cache_ptr) < 0 ) )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "an extreme sanity check failed on entry")
#endif /* H5C_DO_EXTREME_SANITY_CHECKS */
H5C__SEARCH_INDEX(cache_ptr, old_addr, entry_ptr, FAIL)
- if(entry_ptr == NULL || entry_ptr->type != type)
+ if ( ( entry_ptr == NULL ) || ( entry_ptr->type != type ) ) {
+
/* the old item doesn't exist in the cache, so we are done. */
HGOTO_DONE(SUCCEED)
+ }
HDassert(entry_ptr->addr == old_addr);
HDassert(entry_ptr->type == type);
@@ -1858,16 +2325,21 @@ H5C_move_entry(H5C_t * cache_ptr,
/* (Moving a R/O entry would mark it dirty, which shouldn't
* happen. QAK - 2016/12/02)
*/
- if(entry_ptr->is_read_only)
+ if ( entry_ptr->is_read_only )
HGOTO_ERROR(H5E_CACHE, H5E_CANTMOVE, FAIL, "can't move R/O entry")
H5C__SEARCH_INDEX(cache_ptr, new_addr, test_entry_ptr, FAIL)
- if(test_entry_ptr != NULL) { /* we are hosed */
- if(test_entry_ptr->type == type)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTMOVE, FAIL, "target already moved & reinserted???")
+ if ( test_entry_ptr != NULL ) { /* we are hosed */
+
+ if ( test_entry_ptr->type == type )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTMOVE, FAIL, \
+ "target already moved & reinserted???")
else
- HGOTO_ERROR(H5E_CACHE, H5E_CANTMOVE, FAIL, "new address already in use?")
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTMOVE, FAIL, \
+ "new address already in use?")
} /* end if */
/* If we get this far we have work to do. Remove *entry_ptr from
@@ -1885,10 +2357,12 @@ H5C_move_entry(H5C_t * cache_ptr,
* change the addr. If the entry is only in the process of being flushed,
* don't mark it as dirty either, lest we confuse the flush call back.
*/
- if(!entry_ptr->destroy_in_progress) {
+ if ( ! entry_ptr->destroy_in_progress ) {
+
H5C__DELETE_FROM_INDEX(cache_ptr, entry_ptr, FAIL)
- if(entry_ptr->in_slist) {
+ if ( entry_ptr->in_slist ) {
+
HDassert(cache_ptr->slist_ptr);
H5C__REMOVE_ENTRY_FROM_SLIST(cache_ptr, entry_ptr, FALSE)
} /* end if */
@@ -1896,8 +2370,18 @@ H5C_move_entry(H5C_t * cache_ptr,
entry_ptr->addr = new_addr;
- if(!entry_ptr->destroy_in_progress) {
- hbool_t was_dirty; /* Whether the entry was previously dirty */
+ /* update the page in which the entry resides if the file is opened
+ * as a VFD SWMR reader.
+ */
+ if ( cache_ptr->vfd_swmr_reader ) {
+
+ entry_ptr->page = (new_addr / f->shared->pb_ptr->page_size);
+
+ }
+
+ if ( ! entry_ptr->destroy_in_progress ) {
+
+ hbool_t was_dirty; /* Whether the entry was previously dirty */
/* Remember previous dirty status */
was_dirty = entry_ptr->is_dirty;
@@ -1906,11 +2390,17 @@ H5C_move_entry(H5C_t * cache_ptr,
entry_ptr->is_dirty = TRUE;
/* This shouldn't be needed, but it keeps the test code happy */
- if(entry_ptr->image_up_to_date) {
+ if ( entry_ptr->image_up_to_date ) {
+
entry_ptr->image_up_to_date = FALSE;
- if(entry_ptr->flush_dep_nparents > 0)
- if(H5C__mark_flush_dep_unserialized(entry_ptr) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, "Can't propagate serialization status to fd parents")
+
+ if ( entry_ptr->flush_dep_nparents > 0 ) {
+
+ if ( H5C__mark_flush_dep_unserialized(entry_ptr) < 0 )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, \
+ "Can't propagate serialization status to fd parents")
+ }
} /* end if */
/* Modify cache data structures */
@@ -1918,23 +2408,35 @@ H5C_move_entry(H5C_t * cache_ptr,
H5C__INSERT_ENTRY_IN_SLIST(cache_ptr, entry_ptr, FAIL)
/* Skip some actions if we're in the middle of flushing the entry */
- if(!entry_ptr->flush_in_progress) {
+ if ( !entry_ptr->flush_in_progress ) {
+
/* Update the replacement policy for the entry */
H5C__UPDATE_RP_FOR_MOVE(cache_ptr, entry_ptr, was_dirty, FAIL)
/* Check for entry changing status and do notifications, etc. */
if(!was_dirty) {
- /* If the entry's type has a 'notify' callback send a 'entry dirtied'
- * notice now that the entry is fully integrated into the cache.
+
+ /* If the entry's type has a 'notify' callback send a 'entry
+ * dirtied' notice now that the entry is fully integrated
+ * into the cache.
*/
- if(entry_ptr->type->notify &&
- (entry_ptr->type->notify)(H5C_NOTIFY_ACTION_ENTRY_DIRTIED, entry_ptr) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, "can't notify client about entry dirty flag set")
+ if ( ( entry_ptr->type->notify ) &&
+ ( (entry_ptr->type->notify)
+ (H5C_NOTIFY_ACTION_ENTRY_DIRTIED, entry_ptr) < 0 ) )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, \
+ "can't notify client about entry dirty flag set")
+
+ /* Propagate the dirty flag up the flush dependency chain
+ * if appropriate
+ */
+ if ( entry_ptr->flush_dep_nparents > 0 ) {
+
+ if ( H5C__mark_flush_dep_dirty(entry_ptr) < 0 )
- /* Propagate the dirty flag up the flush dependency chain if appropriate */
- if(entry_ptr->flush_dep_nparents > 0)
- if(H5C__mark_flush_dep_dirty(entry_ptr) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTMARKDIRTY, FAIL, "Can't propagate flush dep dirty flag")
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTMARKDIRTY, FAIL, \
+ "Can't propagate flush dep dirty flag")
+ }
} /* end if */
} /* end if */
} /* end if */
@@ -1942,14 +2444,18 @@ H5C_move_entry(H5C_t * cache_ptr,
H5C__UPDATE_STATS_FOR_MOVE(cache_ptr, entry_ptr)
done:
+
#if H5C_DO_EXTREME_SANITY_CHECKS
- if((H5C_validate_protected_entry_list(cache_ptr) < 0) ||
- (H5C_validate_pinned_entry_list(cache_ptr) < 0) ||
- (H5C_validate_lru_list(cache_ptr) < 0))
- HDONE_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "an extreme sanity check failed on exit")
+ if ( ( H5C_validate_protected_entry_list(cache_ptr) < 0 ) ||
+ ( H5C_validate_pinned_entry_list(cache_ptr) < 0 ) ||
+ ( H5C_validate_lru_list(cache_ptr) < 0 ) )
+
+ HDONE_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "an extreme sanity check failed on exit")
#endif /* H5C_DO_EXTREME_SANITY_CHECKS */
FUNC_LEAVE_NOAPI(ret_value)
+
} /* H5C_move_entry() */
@@ -6522,17 +7028,19 @@ H5C_load_entry(H5F_t * f,
haddr_t addr,
void * udata)
{
- hbool_t dirty = FALSE; /* Flag indicating whether thing was dirtied during deserialize */
- uint8_t * image = NULL; /* Buffer for disk image */
- void * thing = NULL; /* Pointer to thing loaded */
- H5C_cache_entry_t *entry = NULL; /* Alias for thing loaded, as cache entry */
- size_t len; /* Size of image in file */
+ hbool_t dirty = FALSE; /* Flag indicating whether thing */
+ /* was dirtied during deserialize */
+ uint8_t * image = NULL; /* Buffer for disk image */
+ void * thing = NULL; /* Pointer to thing loaded */
+ H5C_cache_entry_t *entry = NULL; /* Alias for thing loaded, as */
+ /* cache entry */
+ size_t len; /* Size of image in file */
#ifdef H5_HAVE_PARALLEL
- int mpi_rank = 0; /* MPI process rank */
- MPI_Comm comm = MPI_COMM_NULL; /* File MPI Communicator */
- int mpi_code; /* MPI error code */
+ int mpi_rank = 0; /* MPI process rank */
+ MPI_Comm comm = MPI_COMM_NULL; /* File MPI Communicator */
+ int mpi_code; /* MPI error code */
#endif /* H5_HAVE_PARALLEL */
- void * ret_value = NULL; /* Return value */
+ void * ret_value = NULL; /* Return value */
FUNC_ENTER_NOAPI_NOINIT
@@ -6540,13 +7048,28 @@ H5C_load_entry(H5F_t * f,
HDassert(f);
HDassert(f->shared);
HDassert(f->shared->cache);
+ HDassert(f->shared->cache->magic == H5C__H5C_T_MAGIC );
+
+ /* if this is a VFD SWMR reader, verify that the page buffer is
+ * configured.
+ */
+ HDassert( ( ! f->shared->cache->vfd_swmr_reader ) ||
+ ( ( f->shared->pb_ptr ) &&
+ ( f->shared->pb_ptr->magic == H5PB__H5PB_T_MAGIC ) ) );
+
HDassert(type);
HDassert(H5F_addr_defined(addr));
HDassert(type->get_initial_load_size);
- if(type->flags & H5C__CLASS_SPECULATIVE_LOAD_FLAG)
+
+ if ( type->flags & H5C__CLASS_SPECULATIVE_LOAD_FLAG ) {
+
HDassert(type->get_final_load_size);
- else
+
+ } else {
+
HDassert(NULL == type->get_final_load_size);
+ }
+
HDassert(type->deserialize);
/* Can't see how skip reads could be usefully combined with
@@ -6555,41 +7078,61 @@ H5C_load_entry(H5F_t * f,
HDassert(!((type->flags & H5C__CLASS_SKIP_READS) &&
(type->flags & H5C__CLASS_SPECULATIVE_LOAD_FLAG)));
- /* Call the get_initial_load_size callback, to retrieve the initial size of image */
- if(type->get_initial_load_size(udata, &len) < 0)
+ /* Call the get_initial_load_size callback, to retrieve the initial
+ * size of image
+ */
+ if ( type->get_initial_load_size(udata, &len) < 0 )
+
HGOTO_ERROR(H5E_CACHE, H5E_CANTGET, NULL, "can't retrieve image size")
+
HDassert(len > 0);
/* Check for possible speculative read off the end of the file */
- if(type->flags & H5C__CLASS_SPECULATIVE_LOAD_FLAG)
- if(H5C__verify_len_eoa(f, type, addr, &len, FALSE) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, NULL, "invalid len with respect to EOA")
+ if ( type->flags & H5C__CLASS_SPECULATIVE_LOAD_FLAG ) {
+
+ if ( H5C__verify_len_eoa(f, type, addr, &len, FALSE) < 0 )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, NULL, \
+ "invalid len with respect to EOA")
+ }
/* Allocate the buffer for reading the on-disk entry image */
- if(NULL == (image = (uint8_t *)H5MM_malloc(len + H5C_IMAGE_EXTRA_SPACE)))
- HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, NULL, "memory allocation failed for on disk image buffer")
+ if ( NULL == (image = (uint8_t *)H5MM_malloc(len + 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
HDmemcpy(image + len, H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE);
#endif /* H5C_DO_MEMORY_SANITY_CHECKS */
#ifdef H5_HAVE_PARALLEL
- if(H5F_HAS_FEATURE(f, H5FD_FEAT_HAS_MPI)) {
- if((mpi_rank = H5F_mpi_get_rank(f)) < 0)
+ if ( H5F_HAS_FEATURE(f, H5FD_FEAT_HAS_MPI) ) {
+
+ if ( (mpi_rank = H5F_mpi_get_rank(f)) < 0 )
+
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "Can't get MPI rank")
- if((comm = H5F_mpi_get_comm(f)) == MPI_COMM_NULL)
+
+ if ( (comm = H5F_mpi_get_comm(f)) == MPI_COMM_NULL )
+
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "get_comm request failed")
+
} /* end if */
#endif /* H5_HAVE_PARALLEL */
/* Get the on-disk entry image */
- if(0 == (type->flags & H5C__CLASS_SKIP_READS)) {
- unsigned tries, max_tries; /* The # of read attempts */
- unsigned retries; /* The # of retries */
- htri_t chk_ret; /* return from verify_chksum callback */
- size_t actual_len = len; /* The actual length, after speculative reads have been resolved */
- uint64_t nanosec = 1; /* # of nanoseconds to sleep between retries */
- void *new_image; /* Pointer to image */
- hbool_t len_changed = TRUE; /* Whether to re-check speculative entries */
+ if ( 0 == (type->flags & H5C__CLASS_SKIP_READS) ) {
+
+ unsigned tries, max_tries; /* The # of read attempts */
+ unsigned retries; /* The # of retries */
+ htri_t chk_ret; /* return from verify_chksum callback */
+ size_t actual_len = len; /* The actual length, after speculative */
+ /* reads have been resolved */
+ uint64_t nanosec = 1; /* # of nanoseconds to sleep between */
+ /* retries */
+ void *new_image; /* Pointer to image */
+ hbool_t len_changed = TRUE; /* Whether to re-check speculative */
+ /* entries */
/* Get the # of read attempts */
max_tries = tries = H5F_GET_READ_ATTEMPTS(f);
@@ -6602,31 +7145,44 @@ H5C_load_entry(H5F_t * f,
* --perform checksum verification
*/
do {
- if(actual_len != len) {
- if(NULL == (new_image = H5MM_realloc(image, len + H5C_IMAGE_EXTRA_SPACE)))
- HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, NULL, "image null after H5MM_realloc()")
+ if ( actual_len != len ) {
+
+ if ( NULL == (new_image = H5MM_realloc(image,
+ len + H5C_IMAGE_EXTRA_SPACE)) )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, NULL, \
+ "image null after H5MM_realloc()")
+
image = (uint8_t *)new_image;
+
#if H5C_DO_MEMORY_SANITY_CHECKS
- HDmemcpy(image + len, H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE);
+ HDmemcpy(image + len, H5C_IMAGE_SANITY_VALUE,
+ H5C_IMAGE_EXTRA_SPACE);
#endif /* H5C_DO_MEMORY_SANITY_CHECKS */
} /* end if */
#ifdef H5_HAVE_PARALLEL
- if(!coll_access || 0 == mpi_rank) {
+ if ( !coll_access || 0 == mpi_rank ) {
#endif /* H5_HAVE_PARALLEL */
- if(H5F_block_read(f, type->mem_type, addr, len, image) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_READERROR, NULL, "Can't read image*")
+
+ if ( H5F_block_read(f, type->mem_type, addr, len, image) < 0 )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_READERROR, NULL, \
+ "Can't read image*")
#ifdef H5_HAVE_PARALLEL
} /* end if */
/* if the collective metadata read optimization is turned on,
* bcast the metadata read from process 0 to all ranks in the file
* communicator
*/
- if(coll_access) {
+ if ( coll_access ) {
+
int buf_size;
H5_CHECKED_ASSIGN(buf_size, int, len, size_t);
- if(MPI_SUCCESS != (mpi_code = MPI_Bcast(image, buf_size, MPI_BYTE, 0, comm)))
+ if ( MPI_SUCCESS !=
+ (mpi_code = MPI_Bcast(image, buf_size, MPI_BYTE, 0, comm)))
+
HMPI_GOTO_ERROR(NULL, "MPI_Bcast failed", mpi_code)
} /* end if */
#endif /* H5_HAVE_PARALLEL */
@@ -6634,46 +7190,77 @@ H5C_load_entry(H5F_t * f,
/* If the entry could be read speculatively and the length is still
* changing, check for updating the actual size
*/
- if((type->flags & H5C__CLASS_SPECULATIVE_LOAD_FLAG) && len_changed) {
+ if( ( type->flags & H5C__CLASS_SPECULATIVE_LOAD_FLAG ) &&
+ ( len_changed ) ) {
+
/* Retrieve the actual length */
actual_len = len;
- if(type->get_final_load_size(image, len, udata, &actual_len) < 0)
- continue; /* Transfer control to while() and count towards retries */
+ if ( type->get_final_load_size(image, len, udata,
+ &actual_len) < 0 ) {
+
+ /* Transfer control to while() and count towards retries */
+ continue;
+ }
/* Check for the length changing */
- if(actual_len != len) {
- /* Verify that the length isn't past the EOA for the file */
- if(H5C__verify_len_eoa(f, type, addr, &actual_len, TRUE) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, NULL, "actual_len exceeds EOA")
+ if ( actual_len != len ) {
+
+ /* Verify that the length isn't past the EOA for
+ * the file
+ */
+ if ( H5C__verify_len_eoa(f, type, addr,
+ &actual_len, TRUE) < 0)
+
+ HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, NULL, \
+ "actual_len exceeds EOA")
/* Expand buffer to new size */
- if(NULL == (new_image = H5MM_realloc(image, actual_len + H5C_IMAGE_EXTRA_SPACE)))
- HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, NULL, "image null after H5MM_realloc()")
+ if ( NULL ==
+ (new_image = H5MM_realloc(image,
+ actual_len + H5C_IMAGE_EXTRA_SPACE)))
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, NULL, \
+ "image null after H5MM_realloc()")
+
image = (uint8_t *)new_image;
+
#if H5C_DO_MEMORY_SANITY_CHECKS
- HDmemcpy(image + actual_len, H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE);
+ HDmemcpy(image + actual_len, H5C_IMAGE_SANITY_VALUE,
+ H5C_IMAGE_EXTRA_SPACE);
#endif /* H5C_DO_MEMORY_SANITY_CHECKS */
- if(actual_len > len) {
+ if ( actual_len > len ) {
#ifdef H5_HAVE_PARALLEL
- if(!coll_access || 0 == mpi_rank) {
+ if ( !coll_access || 0 == mpi_rank ) {
#endif /* H5_HAVE_PARALLEL */
- /* If the thing's image needs to be bigger for a speculatively
- * loaded thing, go get the on-disk image again (the extra portion).
+ /* If the thing's image needs to be bigger for
+ * a speculatively loaded thing, go get the
+ * on-disk image again (the extra portion).
*/
- if(H5F_block_read(f, type->mem_type, addr + len, actual_len - len, image + len) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTLOAD, NULL, "can't read image")
+ if ( H5F_block_read(f, type->mem_type, addr + len,
+ actual_len - len, image + len) < 0)
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTLOAD, NULL, \
+ "can't read image")
#ifdef H5_HAVE_PARALLEL
}
- /* If the collective metadata read optimization is turned on,
- * Bcast the metadata read from process 0 to all ranks in the file
- * communicator */
- if(coll_access) {
+ /* If the collective metadata read optimization is
+ * turned on, Bcast the metadata read from process
+ * 0 to all ranks in the file communicator
+ */
+ if ( coll_access ) {
+
int buf_size;
- H5_CHECKED_ASSIGN(buf_size, int, actual_len - len, size_t);
- if(MPI_SUCCESS != (mpi_code = MPI_Bcast(image + len, buf_size, MPI_BYTE, 0, comm)))
- HMPI_GOTO_ERROR(NULL, "MPI_Bcast failed", mpi_code)
+ H5_CHECKED_ASSIGN(buf_size, int, actual_len - len, \
+ size_t);
+
+ if ( MPI_SUCCESS !=
+ (mpi_code = MPI_Bcast(image + len, buf_size,
+ MPI_BYTE, 0, comm)) )
+
+ HMPI_GOTO_ERROR(NULL, "MPI_Bcast failed", \
+ mpi_code)
} /* end if */
#endif /* H5_HAVE_PARALLEL */
} /* end if */
@@ -6694,28 +7281,39 @@ H5C_load_entry(H5F_t * f,
break;
/* Verify the checksum for the metadata image */
- if((chk_ret = type->verify_chksum(image, actual_len, udata)) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTGET, NULL, "failure from verify_chksum callback")
+ if ( (chk_ret = type->verify_chksum(image, actual_len, udata)) < 0)
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTGET, NULL, \
+ "failure from verify_chksum callback")
+
if(chk_ret == TRUE)
break;
/* Sleep for some time */
H5_nanosleep(nanosec);
nanosec *= 2; /* Double the sleep time next time */
+
} while(--tries);
/* Check for too many tries */
if(tries == 0)
- HGOTO_ERROR(H5E_CACHE, H5E_READERROR, NULL, "incorrect metadatda checksum after all read attempts")
+ HGOTO_ERROR(H5E_CACHE, H5E_READERROR, NULL, \
+ "incorrect metadatda checksum after all read attempts")
/* Calculate and track the # of retries */
retries = max_tries - tries;
- if(retries) /* Does not track 0 retry */
- if(H5F_track_metadata_read_retries(f, (unsigned)type->mem_type, retries) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, NULL, "cannot track read tries = %u ", retries)
+ if ( retries ) { /* Does not track 0 retry */
+
+ if ( H5F_track_metadata_read_retries(f, (unsigned)type->mem_type,
+ retries) < 0)
+
+ HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, NULL, \
+ "cannot track read tries = %u ", retries)
+ }
/* Set the final length (in case it wasn't set earlier) */
len = actual_len;
+
} /* end if !H5C__CLASS_SKIP_READS */
/* Deserialize the on-disk image into the native memory form */
@@ -6753,7 +7351,7 @@ H5C_load_entry(H5F_t * f,
entry->image_ptr = image;
entry->image_up_to_date = !dirty;
entry->type = type;
- entry->is_dirty = dirty;
+ entry->is_dirty = dirty;
entry->dirtied = FALSE;
entry->is_protected = FALSE;
entry->is_read_only = FALSE;
@@ -6813,9 +7411,23 @@ H5C_load_entry(H5F_t * f,
entry->serialization_count = 0;
#endif /* NDEBUG */
- entry->tl_next = NULL;
- entry->tl_prev = NULL;
- entry->tag_info = NULL;
+ /* initialize tag list fields */
+ entry->tl_next = NULL;
+ entry->tl_prev = NULL;
+ entry->tag_info = NULL;
+
+ /* initialize fields supporting VFD SWMR */
+ if ( f->shared->cache->vfd_swmr_reader ) {
+
+ entry->page = (addr / f->shared->pb_ptr->page_size);
+
+ } else {
+
+ entry->page = 0;
+ }
+ entry->refreshed_in_tick = 0;
+ entry->pi_next = NULL;
+ entry->pi_prev = NULL;
H5C__RESET_CACHE_ENTRY_STATS(entry);
@@ -8517,6 +9129,11 @@ done:
* Programmer: Mohamad Chaarawi
* 2/10/16
*
+ * Changes: Added code to update the page field in the VFD SWMR reader
+ * case.
+ *
+ * JRM -- 12/14/18
+ *
*-------------------------------------------------------------------------
*/
herr_t
@@ -8534,6 +9151,14 @@ H5C__generate_image(H5F_t *f, H5C_t *cache_ptr, H5C_cache_entry_t *entry_ptr)
HDassert(f);
HDassert(cache_ptr);
HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
+
+ /* if this is a VFD SWMR reader, verify that the page buffer is
+ * configured.
+ */
+ HDassert( ( ! cache_ptr->vfd_swmr_reader ) ||
+ ( ( f->shared->pb_ptr ) &&
+ ( f->shared->pb_ptr->magic == H5PB__H5PB_T_MAGIC ) ) );
+
HDassert(entry_ptr);
HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(!entry_ptr->image_up_to_date);
@@ -8545,16 +9170,24 @@ H5C__generate_image(H5F_t *f, H5C_t *cache_ptr, H5C_cache_entry_t *entry_ptr)
old_addr = entry_ptr->addr;
/* Call client's pre-serialize callback, if there's one */
- if(entry_ptr->type->pre_serialize &&
- (entry_ptr->type->pre_serialize)(f, (void *)entry_ptr,
- entry_ptr->addr, entry_ptr->size, &new_addr, &new_len, &serialize_flags) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to pre-serialize entry")
+ if ( ( entry_ptr->type->pre_serialize ) &&
+ ( (entry_ptr->type->pre_serialize)(f, (void *)entry_ptr,
+ entry_ptr->addr, entry_ptr->size,
+ &new_addr, &new_len,
+ &serialize_flags) < 0 ) )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \
+ "unable to pre-serialize entry")
/* Check for any flags set in the pre-serialize callback */
- if(serialize_flags != H5C__SERIALIZE_NO_FLAGS_SET) {
+ if ( serialize_flags != H5C__SERIALIZE_NO_FLAGS_SET ) {
+
/* Check for unexpected flags from serialize callback */
- if(serialize_flags & ~(H5C__SERIALIZE_RESIZED_FLAG | H5C__SERIALIZE_MOVED_FLAG))
- HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unknown serialize flag(s)")
+ if ( serialize_flags & ~(H5C__SERIALIZE_RESIZED_FLAG |
+ H5C__SERIALIZE_MOVED_FLAG) )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \
+ "unknown serialize flag(s)")
#ifdef H5_HAVE_PARALLEL
/* In the parallel case, resizes and moves in
@@ -8583,28 +9216,40 @@ H5C__generate_image(H5F_t *f, H5C_t *cache_ptr, H5C_cache_entry_t *entry_ptr)
* If that ceases to be the case, further
* tests will be necessary.
*/
- if(cache_ptr->aux_ptr != NULL)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "resize/move in serialize occurred in parallel case")
+ if ( cache_ptr->aux_ptr != NULL )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "resize/move in serialize occurred in parallel case")
#endif
/* If required, resize the buffer and update the entry and the cache
- * data structures */
- if(serialize_flags & H5C__SERIALIZE_RESIZED_FLAG) {
+ * data structures
+ */
+ if ( serialize_flags & H5C__SERIALIZE_RESIZED_FLAG ) {
+
/* Sanity check */
HDassert(new_len > 0);
/* Allocate a new image buffer */
- if(NULL == (entry_ptr->image_ptr = H5MM_realloc(entry_ptr->image_ptr, new_len + H5C_IMAGE_EXTRA_SPACE)))
- HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, "memory allocation failed for on disk image buffer")
+ if ( NULL == (entry_ptr->image_ptr =
+ H5MM_realloc(entry_ptr->image_ptr,
+ new_len + 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
- HDmemcpy(((uint8_t *)entry_ptr->image_ptr) + new_len, H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE);
+ HDmemcpy(((uint8_t *)entry_ptr->image_ptr) + new_len, \
+ H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE);
#endif /* H5C_DO_MEMORY_SANITY_CHECKS */
/* Update statistics for resizing the entry */
- H5C__UPDATE_STATS_FOR_ENTRY_SIZE_CHANGE(cache_ptr, entry_ptr, new_len);
+ H5C__UPDATE_STATS_FOR_ENTRY_SIZE_CHANGE(cache_ptr, entry_ptr, \
+ new_len);
/* Update the hash table for the size change */
- H5C__UPDATE_INDEX_FOR_SIZE_CHANGE(cache_ptr, entry_ptr->size, new_len, entry_ptr, !(entry_ptr->is_dirty));
+ H5C__UPDATE_INDEX_FOR_SIZE_CHANGE(cache_ptr, entry_ptr->size, \
+ new_len, entry_ptr, !(entry_ptr->is_dirty));
/* The entry can't be protected since we are in the process of
* flushing it. Thus we must update the replacement policy data
@@ -8619,21 +9264,25 @@ H5C__generate_image(H5F_t *f, H5C_t *cache_ptr, H5C_cache_entry_t *entry_ptr)
*/
HDassert(entry_ptr->is_dirty);
HDassert(entry_ptr->in_slist);
- H5C__UPDATE_SLIST_FOR_SIZE_CHANGE(cache_ptr, entry_ptr->size, new_len);
+ H5C__UPDATE_SLIST_FOR_SIZE_CHANGE(cache_ptr, entry_ptr->size, \
+ new_len);
/* Finally, update the entry for its new size */
entry_ptr->size = new_len;
+
} /* end if */
/* If required, udate the entry and the cache data structures
* for a move
*/
- if(serialize_flags & H5C__SERIALIZE_MOVED_FLAG) {
+ if ( serialize_flags & H5C__SERIALIZE_MOVED_FLAG ) {
+
/* Update stats and entries relocated counter */
H5C__UPDATE_STATS_FOR_MOVE(cache_ptr, entry_ptr)
/* We must update cache data structures for the change in address */
if(entry_ptr->addr == old_addr) {
+
/* Delete the entry from the hash table and the slist */
H5C__DELETE_FROM_INDEX(cache_ptr, entry_ptr, FAIL);
H5C__REMOVE_ENTRY_FROM_SLIST(cache_ptr, entry_ptr, FALSE);
@@ -8641,21 +9290,37 @@ H5C__generate_image(H5F_t *f, H5C_t *cache_ptr, H5C_cache_entry_t *entry_ptr)
/* Update the entry for its new address */
entry_ptr->addr = new_addr;
+ /* In the VFD SWMR reader case, update the entry page field */
+ if ( cache_ptr->vfd_swmr_reader ) {
+
+ entry_ptr->page = (new_addr / f->shared->pb_ptr->page_size);
+ }
+
/* And then reinsert in the index and slist */
H5C__INSERT_IN_INDEX(cache_ptr, entry_ptr, FAIL);
H5C__INSERT_ENTRY_IN_SLIST(cache_ptr, entry_ptr, FAIL);
- } /* end if */
- else /* move is already done for us -- just do sanity checks */
+
+ } else { /* move is already done for us -- just do sanity checks */
+
HDassert(entry_ptr->addr == new_addr);
+ HDassert(( ! cache_ptr->vfd_swmr_reader ) ||
+ ( entry_ptr->page ==
+ (entry_ptr->addr / f->shared->pb_ptr->page_size) ));
+ }
} /* end if */
} /* end if(serialize_flags != H5C__SERIALIZE_NO_FLAGS_SET) */
/* Serialize object into buffer */
- if(entry_ptr->type->serialize(f, entry_ptr->image_ptr, entry_ptr->size, (void *)entry_ptr) < 0)
+ if ( entry_ptr->type->serialize(f, entry_ptr->image_ptr, entry_ptr->size,
+ (void *)entry_ptr) < 0)
+
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to serialize entry")
+
#if H5C_DO_MEMORY_SANITY_CHECKS
- HDassert(0 == HDmemcmp(((uint8_t *)entry_ptr->image_ptr) + entry_ptr->size, H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE));
+ HDassert(0 == HDmemcmp(((uint8_t *)entry_ptr->image_ptr) + entry_ptr->size,
+ H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE));
#endif /* H5C_DO_MEMORY_SANITY_CHECKS */
+
entry_ptr->image_up_to_date = TRUE;
/* Propagate the fact that the entry is serialized up the
@@ -8665,12 +9330,19 @@ H5C__generate_image(H5F_t *f, H5C_t *cache_ptr, H5C_cache_entry_t *entry_ptr)
* for flush dependency parents.
*/
HDassert(entry_ptr->flush_dep_nunser_children == 0);
- if(entry_ptr->flush_dep_nparents > 0)
- if(H5C__mark_flush_dep_serialized(entry_ptr) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, "Can't propagate serialization status to fd parents")
+
+ if ( entry_ptr->flush_dep_nparents > 0 ) {
+
+ if ( H5C__mark_flush_dep_serialized(entry_ptr) < 0 )
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, \
+ "Can't propagate serialization status to fd parents")
+ }
done:
+
FUNC_LEAVE_NOAPI(ret_value)
+
} /* H5C__generate_image */