summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2017-03-12 09:57:19 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2017-03-12 09:57:19 (GMT)
commitc4a36e0bb3b56e0c8397876be1c66fedb2f57d83 (patch)
treebafeb848fb17a45a11a75abbbc50778b52347e59 /src
parent36f06cab798cd45261988e2618018e0763f5e2fd (diff)
downloadhdf5-c4a36e0bb3b56e0c8397876be1c66fedb2f57d83.zip
hdf5-c4a36e0bb3b56e0c8397876be1c66fedb2f57d83.tar.gz
hdf5-c4a36e0bb3b56e0c8397876be1c66fedb2f57d83.tar.bz2
Minor cleanups and bring over "prefetched dirty" fixes for entries loaded from
a cache image.
Diffstat (limited to 'src')
-rw-r--r--src/H5AC.c9
-rw-r--r--src/H5ACdbg.c2
-rw-r--r--src/H5ACprivate.h2
-rw-r--r--src/H5C.c42
-rw-r--r--src/H5Cdbg.c106
-rw-r--r--src/H5Cimage.c2
-rw-r--r--src/H5Cpkg.h12
-rw-r--r--src/H5Cprivate.h58
-rw-r--r--src/H5Ctag.c2
9 files changed, 204 insertions, 31 deletions
diff --git a/src/H5AC.c b/src/H5AC.c
index ee68a6f..2fb7992 100644
--- a/src/H5AC.c
+++ b/src/H5AC.c
@@ -501,7 +501,7 @@ H5AC_create(const H5F_t *f, H5AC_cache_config_t *config_ptr, H5AC_cache_image_co
/* Turn on metadata cache logging, if being used */
if(H5F_USE_MDC_LOGGING(f)) {
if(H5C_set_up_logging(f->shared->cache, H5F_MDC_LOG_LOCATION(f), H5F_START_MDC_LOG_ON_ACCESS(f)) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "mdc logging setup failed")
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTINIT, FAIL, "mdc logging setup failed")
/* Write the log header regardless of current logging status */
if(H5AC__write_create_cache_log_msg(f->shared->cache) < 0)
@@ -510,9 +510,9 @@ H5AC_create(const H5F_t *f, H5AC_cache_config_t *config_ptr, H5AC_cache_image_co
/* Set the cache parameters */
if(H5AC_set_cache_auto_resize_config(f->shared->cache, config_ptr) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, "auto resize configuration failed")
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTSET, FAIL, "auto resize configuration failed")
- /* don't need to get the current H5C image config here since the
+ /* Don't need to get the current H5C image config here since the
* cache has just been created, and thus f->shared->cache->image_ctl
* must still set to its initial value (H5C__DEFAULT_CACHE_IMAGE_CTL).
* Note that this not true as soon as control returns to the application
@@ -522,9 +522,8 @@ H5AC_create(const H5F_t *f, H5AC_cache_config_t *config_ptr, H5AC_cache_image_co
int_ci_config.generate_image = image_config_ptr->generate_image;
int_ci_config.save_resize_status = image_config_ptr->save_resize_status;
int_ci_config.entry_ageout = image_config_ptr->entry_ageout;
-
if(H5C_set_cache_image_config(f, f->shared->cache, &int_ci_config) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, "auto resize configuration failed")
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTSET, FAIL, "auto resize configuration failed")
done:
#ifdef H5_HAVE_PARALLEL
diff --git a/src/H5ACdbg.c b/src/H5ACdbg.c
index 8ca5102..6073288 100644
--- a/src/H5ACdbg.c
+++ b/src/H5ACdbg.c
@@ -101,6 +101,7 @@ H5AC_stats(const H5F_t *f)
FUNC_LEAVE_NOAPI(SUCCEED)
} /* H5AC_stats() */
+#ifndef NDEBUG
/*-------------------------------------------------------------------------
* Function: H5AC_dump_cache
@@ -133,6 +134,7 @@ H5AC_dump_cache(const H5F_t *f)
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5AC_dump_cache() */
+#endif /* NDEBUG */
/*-------------------------------------------------------------------------
diff --git a/src/H5ACprivate.h b/src/H5ACprivate.h
index 1fe6456..1dc8270 100644
--- a/src/H5ACprivate.h
+++ b/src/H5ACprivate.h
@@ -482,8 +482,8 @@ H5_DLL herr_t H5AC_add_candidate(H5AC_t * cache_ptr, haddr_t addr);
/* Debugging functions */
H5_DLL herr_t H5AC_stats(const H5F_t *f);
-H5_DLL herr_t H5AC_dump_cache(const H5F_t *f);
#ifndef NDEBUG
+H5_DLL herr_t H5AC_dump_cache(const H5F_t *f);
H5_DLL herr_t H5AC_get_entry_ptr_from_addr(const H5F_t *f, haddr_t addr,
void **entry_ptr_ptr);
H5_DLL herr_t H5AC_flush_dependency_exists(H5F_t *f, haddr_t parent_addr,
diff --git a/src/H5C.c b/src/H5C.c
index cdf01b3..0eb9d9b 100644
--- a/src/H5C.c
+++ b/src/H5C.c
@@ -1459,6 +1459,7 @@ H5C_insert_entry(H5F_t * f,
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;
#endif /* NDEBUG */
@@ -4584,7 +4585,7 @@ H5C__autoadjust__ageout__evict_aged_out_entries(H5F_t * f,
( (entry_ptr->type)->id != H5AC_EPOCH_MARKER_ID ) &&
( bytes_evicted < eviction_size_limit ) )
{
- hbool_t corked = FALSE;
+ hbool_t skipping_entry = FALSE;
HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert( ! (entry_ptr->is_protected) );
@@ -4598,9 +4599,11 @@ H5C__autoadjust__ageout__evict_aged_out_entries(H5F_t * f,
prev_is_dirty = prev_ptr->is_dirty;
if(entry_ptr->is_dirty ) {
+ HDassert(!entry_ptr->prefetched_dirty);
+
/* dirty corked entry is skipped */
if(entry_ptr->tag_info && entry_ptr->tag_info->corked)
- corked = TRUE;
+ skipping_entry = TRUE;
else {
/* reset entries_removed_counter and
* last_entry_removed_ptr prior to the call to
@@ -4620,16 +4623,22 @@ H5C__autoadjust__ageout__evict_aged_out_entries(H5F_t * f,
restart_scan = TRUE;
} /* end else */
} /* end if */
- else {
+ else if(!entry_ptr->prefetched_dirty) {
bytes_evicted += entry_ptr->size;
if(H5C__flush_single_entry(f, dxpl_id, entry_ptr, H5C__FLUSH_INVALIDATE_FLAG | H5C__DEL_FROM_SLIST_ON_DESTROY_FLAG) < 0 )
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush entry")
- }
+ } /* end else-if */
+ else {
+ HDassert(!entry_ptr->is_dirty);
+ HDassert(entry_ptr->prefetched_dirty);
+
+ skipping_entry = TRUE;
+ } /* end else */
if(prev_ptr != NULL) {
- if(corked) /* dirty corked entry is skipped */
+ if(skipping_entry)
entry_ptr = prev_ptr;
else if(restart_scan || (prev_ptr->is_dirty != prev_is_dirty)
|| (prev_ptr->next != next_ptr)
@@ -4689,10 +4698,10 @@ H5C__autoadjust__ageout__evict_aged_out_entries(H5F_t * f,
prev_ptr = entry_ptr->prev;
- if(!(entry_ptr->is_dirty)) {
+ if(!(entry_ptr->is_dirty) && !(entry_ptr->prefetched_dirty))
if(H5C__flush_single_entry(f, dxpl_id, entry_ptr, H5C__FLUSH_INVALIDATE_FLAG | H5C__DEL_FROM_SLIST_ON_DESTROY_FLAG) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush clean entry")
- } /* end if */
+
/* just skip the entry if it is dirty, as we can't do
* anything with it now since we can't write.
*
@@ -6827,6 +6836,7 @@ H5C_load_entry(H5F_t * f,
entry->prefetched = FALSE;
entry->prefetch_type_id = 0;
entry->age = 0;
+ entry->prefetched_dirty = FALSE;
#ifndef NDEBUG /* debugging field */
entry->serialization_count = 0;
#endif /* NDEBUG */
@@ -6888,6 +6898,7 @@ H5C__make_space_in_cache(H5F_t *f, hid_t dxpl_id, size_t space_needed,
H5C_t * cache_ptr = f->shared->cache;
#if H5C_COLLECT_CACHE_STATS
int32_t clean_entries_skipped = 0;
+ int32_t dirty_pf_entries_skipped = 0;
int32_t total_entries_scanned = 0;
#endif /* H5C_COLLECT_CACHE_STATS */
uint32_t entries_examined = 0;
@@ -6956,7 +6967,8 @@ H5C__make_space_in_cache(H5F_t *f, hid_t dxpl_id, size_t space_needed,
didnt_flush_entry = TRUE;
} else if ( ( (entry_ptr->type)->id != H5AC_EPOCH_MARKER_ID ) &&
- ( ! entry_ptr->flush_in_progress ) ) {
+ ( ! entry_ptr->flush_in_progress ) &&
+ ( ! entry_ptr->prefetched_dirty ) ) {
didnt_flush_entry = FALSE;
@@ -7015,10 +7027,16 @@ H5C__make_space_in_cache(H5F_t *f, hid_t dxpl_id, size_t space_needed,
} else {
- /* Skip epoch markers and entries that are in the process
- * of being flushed.
+ /* Skip epoch markers, entries that are in the process
+ * of being flushed, and entries marked as prefetched_dirty
+ * (occurs in the R/O case only).
*/
didnt_flush_entry = TRUE;
+
+#if H5C_COLLECT_CACHE_STATS
+ if(entry_ptr->prefetched_dirty)
+ dirty_pf_entries_skipped++;
+#endif /* H5C_COLLECT_CACHE_STATS */
}
if ( prev_ptr != NULL ) {
@@ -7083,6 +7101,7 @@ H5C__make_space_in_cache(H5F_t *f, hid_t dxpl_id, size_t space_needed,
cache_ptr->calls_to_msic++;
cache_ptr->total_entries_skipped_in_msic += clean_entries_skipped;
+ cache_ptr->total_dirty_pf_entries_skipped_in_msic += dirty_pf_entries_skipped;
cache_ptr->total_entries_scanned_in_msic += total_entries_scanned;
if ( clean_entries_skipped > cache_ptr->max_entries_skipped_in_msic ) {
@@ -7090,6 +7109,9 @@ H5C__make_space_in_cache(H5F_t *f, hid_t dxpl_id, size_t space_needed,
cache_ptr->max_entries_skipped_in_msic = clean_entries_skipped;
}
+ if(dirty_pf_entries_skipped > cache_ptr->max_dirty_pf_entries_skipped_in_msic)
+ cache_ptr->max_dirty_pf_entries_skipped_in_msic = dirty_pf_entries_skipped;
+
if ( total_entries_scanned > cache_ptr->max_entries_scanned_in_msic ) {
cache_ptr->max_entries_scanned_in_msic = total_entries_scanned;
diff --git a/src/H5Cdbg.c b/src/H5Cdbg.c
index eb5f123..a955eaf 100644
--- a/src/H5Cdbg.c
+++ b/src/H5Cdbg.c
@@ -70,6 +70,7 @@
/*******************/
+#ifndef NDEBUG
/*-------------------------------------------------------------------------
* Function: H5C_dump_cache
@@ -175,6 +176,85 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5C_dump_cache() */
+#endif /* NDEBUG */
+
+#ifndef NDEBUG
+
+/*-------------------------------------------------------------------------
+ * Function: H5C_dump_cache_LRU
+ *
+ * Purpose: Print a summary of the contents of the metadata cache
+ * LRU for debugging purposes.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: John Mainzer
+ * 10/10/10
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5C_dump_cache_LRU(H5C_t *cache_ptr, const char *cache_name)
+{
+ H5C_cache_entry_t * entry_ptr;
+ int i = 0;
+
+ FUNC_ENTER_NOAPI_NOERR
+
+ /* Sanity check */
+ HDassert(cache_ptr != NULL);
+ HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
+ HDassert(cache_name != NULL );
+
+ HDfprintf(stdout, "\n\nDump of metadata cache LRU \"%s\"\n", cache_name);
+ HDfprintf(stdout, "LRU len = %d, LRU size = %d\n",
+ cache_ptr->LRU_list_len, (int)(cache_ptr->LRU_list_size));
+ HDfprintf(stdout, "index_size = %d, max_cache_size = %d, delta = %d\n\n",
+ (int)(cache_ptr->index_size), (int)(cache_ptr->max_cache_size),
+ (int)(cache_ptr->max_cache_size) - (int)(cache_ptr->index_size));
+
+ /* Print header */
+ HDfprintf(stdout, "Entry ");
+ HDfprintf(stdout, "| Address ");
+ HDfprintf(stdout, "| Tag ");
+ HDfprintf(stdout, "| Size ");
+ HDfprintf(stdout, "| Ring ");
+ HDfprintf(stdout, "| Type ");
+ HDfprintf(stdout, "| Dirty");
+ HDfprintf(stdout, "\n");
+
+ HDfprintf(stdout, "----------------------------------------------------------------------------------------------------------------\n");
+
+ entry_ptr = cache_ptr->LRU_head_ptr;
+ while(entry_ptr != NULL) {
+ HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+
+ /* Print entry */
+ HDfprintf(stdout, "%s%5d ", cache_ptr->prefix, i);
+ HDfprintf(stdout, " 0x%16llx ", (long long)(entry_ptr->addr));
+
+ if(NULL == entry_ptr->tag_info)
+ HDfprintf(stdout, " %16s ", "N/A");
+ else
+ HDfprintf(stdout, " 0x%16llx ",
+ (long long)(entry_ptr->tag_info->tag));
+
+ HDfprintf(stdout, " %5lld ", (long long)(entry_ptr->size));
+ HDfprintf(stdout, " %d ", (int)(entry_ptr->ring));
+ HDfprintf(stdout, " %2d %-32s ", (int)(entry_ptr->type->id),
+ (entry_ptr->type->name));
+ HDfprintf(stdout, " %d", (int)(entry_ptr->is_dirty));
+ HDfprintf(stdout, "\n");
+
+ i++;
+ entry_ptr = entry_ptr->next;
+ } /* end while */
+
+ HDfprintf(stdout, "----------------------------------------------------------------------------------------------------------------\n");
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5C_dump_cache_LRU() */
+#endif /* NDEBUG */
/*-------------------------------------------------------------------------
@@ -385,6 +465,7 @@ H5C_stats(H5C_t * cache_ptr,
double average_successful_search_depth = 0.0f;
double average_failed_search_depth = 0.0f;
double average_entries_skipped_per_calls_to_msic = 0.0f;
+ double average_dirty_pf_entries_skipped_per_call_to_msic = 0.0f;
double average_entries_scanned_per_calls_to_msic = 0.0f;
#endif /* H5C_COLLECT_CACHE_STATS */
herr_t ret_value = SUCCEED; /* Return value */
@@ -620,6 +701,17 @@ H5C_stats(H5C_t * cache_ptr,
(long)(cache_ptr->max_entries_skipped_in_msic));
if(cache_ptr->calls_to_msic > 0)
+ average_dirty_pf_entries_skipped_per_call_to_msic =
+ (((double)(cache_ptr->total_dirty_pf_entries_skipped_in_msic)) /
+ ((double)(cache_ptr->calls_to_msic)));
+
+ HDfprintf(stdout,
+ "%s MSIC: Average/max dirty pf entries skipped = %lf / %ld\n",
+ cache_ptr->prefix,
+ average_dirty_pf_entries_skipped_per_call_to_msic,
+ (long)(cache_ptr->max_dirty_pf_entries_skipped_in_msic));
+
+ if(cache_ptr->calls_to_msic > 0)
average_entries_scanned_per_calls_to_msic =
(((double)(cache_ptr->total_entries_scanned_in_msic)) /
((double)(cache_ptr->calls_to_msic)));
@@ -887,12 +979,14 @@ H5C_stats__reset(H5C_t H5_ATTR_UNUSED * cache_ptr)
cache_ptr->max_pel_len = 0;
cache_ptr->max_pel_size = (size_t)0;
- cache_ptr->calls_to_msic = 0;
- cache_ptr->total_entries_skipped_in_msic = 0;
- cache_ptr->total_entries_scanned_in_msic = 0;
- cache_ptr->max_entries_skipped_in_msic = 0;
- cache_ptr->max_entries_scanned_in_msic = 0;
- cache_ptr->entries_scanned_to_make_space = 0;
+ cache_ptr->calls_to_msic = 0;
+ cache_ptr->total_entries_skipped_in_msic = 0;
+ cache_ptr->total_dirty_pf_entries_skipped_in_msic = 0;
+ cache_ptr->total_entries_scanned_in_msic = 0;
+ cache_ptr->max_entries_skipped_in_msic = 0;
+ cache_ptr->max_dirty_pf_entries_skipped_in_msic = 0;
+ cache_ptr->max_entries_scanned_in_msic = 0;
+ cache_ptr->entries_scanned_to_make_space = 0;
cache_ptr->slist_scan_restarts = 0;
cache_ptr->LRU_scan_restarts = 0;
diff --git a/src/H5Cimage.c b/src/H5Cimage.c
index dcaf968..3a21137 100644
--- a/src/H5Cimage.c
+++ b/src/H5Cimage.c
@@ -636,6 +636,7 @@ H5C__deserialize_prefetched_entry(H5F_t *f, hid_t dxpl_id, H5C_t *cache_ptr,
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 /* debugging field */
ds_entry_ptr->serialization_count = 0;
#endif /* NDEBUG */
@@ -3317,6 +3318,7 @@ H5C__reconstruct_cache_entry(const H5F_t *f, H5C_t *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);
/* Sanity checks */
HDassert(pf_entry_ptr->size > 0 && pf_entry_ptr->size < H5C_MAX_ENTRY_SIZE);
diff --git a/src/H5Cpkg.h b/src/H5Cpkg.h
index 5b923e9..3ea5144 100644
--- a/src/H5Cpkg.h
+++ b/src/H5Cpkg.h
@@ -4500,12 +4500,22 @@ typedef struct H5C_tag_info_t {
* total_entries_skipped_in_msic: Number of clean entries skipped while
* enforcing the min_clean_fraction in H5C__make_space_in_cache().
*
+ * total_dirty_pf_entries_skipped_in_msic: Number of dirty prefetched entries
+ * skipped in H5C__make_space_in_cache(). Note that this can
+ * only occur when a file is opened R/O with a cache image
+ * containing dirty entries.
+ *
* total_entries_scanned_in_msic: Number of clean entries skipped while
* enforcing the min_clean_fraction in H5C__make_space_in_cache().
*
* max_entries_skipped_in_msic: Maximum number of clean entries skipped
* in any one call to H5C__make_space_in_cache().
*
+ * max_dirty_pf_entries_skipped_in_msic: Maximum number of dirty prefetched
+ * entries skipped in any one call to H5C__make_space_in_cache().
+ * Note that this can only occur when the file is opened
+ * R/O with a cache image containing dirty entries.
+ *
* max_entries_scanned_in_msic: Maximum number of entries scanned over
* in any one call to H5C__make_space_in_cache().
*
@@ -4822,8 +4832,10 @@ struct H5C_t {
/* Fields for tracking 'make space in cache' (msic) operations */
int64_t calls_to_msic;
int64_t total_entries_skipped_in_msic;
+ int64_t total_dirty_pf_entries_skipped_in_msic;
int64_t total_entries_scanned_in_msic;
int32_t max_entries_skipped_in_msic;
+ int32_t max_dirty_pf_entries_skipped_in_msic;
int32_t max_entries_scanned_in_msic;
int64_t entries_scanned_to_make_space;
diff --git a/src/H5Cprivate.h b/src/H5Cprivate.h
index 28eacf2..3408839 100644
--- a/src/H5Cprivate.h
+++ b/src/H5Cprivate.h
@@ -1066,9 +1066,9 @@ typedef int H5C_ring_t;
*
* is_read_only: Boolean flag that is only meaningful if is_protected is
* TRUE. In this circumstance, it indicates whether the
- * entry has been protected read only, or read/write.
+ * entry has been protected read-only, or read/write.
*
- * If the entry has been protected read only (i.e. is_protected
+ * If the entry has been protected read-only (i.e. is_protected
* and is_read_only are both TRUE), we allow the entry to be
* protected more than once.
*
@@ -1078,7 +1078,7 @@ typedef int H5C_ring_t;
* the entry is actually unprotected.
*
* ro_ref_count: Integer field used to maintain a count of the number of
- * outstanding read only protects on this entry. This field
+ * outstanding read-only protects on this entry. This field
* must be zero whenever either is_protected or is_read_only
* are TRUE.
*
@@ -1458,13 +1458,13 @@ typedef int H5C_ring_t;
* the load of a cache image block, although other scenarios
* are contemplated for the use of this feature. Note that
* unlike the usual prefetch situation, this means that a
- * pre fetched entry can be dirty, and/or can be a party to
+ * prefetched entry can be dirty, and/or can be a party to
* flush dependency relationship(s). This complicates matters
* somewhat.
*
- * The essential feature of a pre-fetched entry is that it
+ * The essential feature of a prefetched entry is that it
* consists only of a buffer containing the on disk image of
- * the entry. Thus it must be deserialized before it can
+ * the entry. Thus it must be deserialized before it can
* be passed back to the library on a protect call. This
* task is handled by H5C_deserialized_prefetched_entry().
* In essence, this routine calls the deserialize callback
@@ -1475,7 +1475,7 @@ typedef int H5C_ring_t;
*
* Further, if the prefetched entry is a flush dependency parent,
* all its flush dependency children (which must also be
- * pre-fetched entries), must be tranfered to the new cache
+ * prefetched entries), must be tranfered to the new cache
* entry returned by the deserailization callback.
*
* Finally, if the prefetched entry is a flush dependency child,
@@ -1511,6 +1511,46 @@ typedef int H5C_ring_t;
*
* This field must be zero if prefetched is FALSE.
*
+ * prefetched_dirty: Boolean field that must be set to FALSE unless the
+ * following conditions hold:
+ *
+ * 1) The file has been opened R/O.
+ *
+ * 2) The entry is either a prefetched entry, or was
+ * re-constructed from a prefetched entry.
+ *
+ * 3) The base prefetched entry was marked dirty.
+ *
+ * This field exists to solve the following problem with
+ * files containing cache images that are opened R/O.
+ *
+ * If the cache image contains a dirty entry, that entry
+ * must be marked clean when it is inserted into the cache
+ * in the read-only case, as otherwise the metadata cache
+ * will attempt to flush it on file close -- which is poor
+ * form in the read-only case.
+ *
+ * However, since the entry is marked clean, it is possible
+ * that the metadata cache will evict it if the size of the
+ * metadata in the file exceeds the size of the metadata cache,
+ * and the application visits much of this data.
+ *
+ * If this happens, and the metadata cache is then asked for
+ * this entry, it will attempt to read it from file, and will
+ * obtain either obsolete or invalid data depending on whether
+ * the entry has ever been written to it assigned location in
+ * the file.
+ *
+ * With this background, the purpose of this field should be
+ * obvious -- when set, it allows the eviction candidate
+ * selection code to skip over the entry, thus avoiding the
+ * issue.
+ *
+ * Since the issue only arises in the R/O case, there is
+ * no possible interaction with SWMR. There are also
+ * potential interactions with Evict On Close -- at present,
+ * we deal with this by disabling EOC in the R/O case.
+ *
* serialization_count: Integer field used to maintain a count of the
* number of times each entry is serialized during cache
* serialization. While no entry should be serialized more than
@@ -1627,6 +1667,7 @@ typedef struct H5C_cache_entry_t {
hbool_t prefetched;
int prefetch_type_id;
int32_t age;
+ hbool_t prefetched_dirty;
#ifndef NDEBUG /* debugging field */
int serialization_count;
@@ -2259,7 +2300,6 @@ H5_DLL herr_t H5C_set_trace_file_ptr(H5C_t *cache_ptr, FILE *trace_file_ptr);
H5_DLL herr_t H5C_stats(H5C_t *cache_ptr, const char *cache_name,
hbool_t display_detailed_stats);
H5_DLL void H5C_stats__reset(H5C_t *cache_ptr);
-H5_DLL herr_t H5C_dump_cache(H5C_t *cache_ptr, const char *cache_name);
H5_DLL herr_t H5C_unpin_entry(void *thing);
H5_DLL herr_t H5C_destroy_flush_dependency(void *parent_thing, void *child_thing);
H5_DLL herr_t H5C_unprotect(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *thing,
@@ -2289,6 +2329,8 @@ H5_DLL herr_t H5C_mark_entries_as_clean(H5F_t *f, hid_t dxpl_id, unsigned ce_arr
#endif /* H5_HAVE_PARALLEL */
#ifndef NDEBUG /* debugging functions */
+H5_DLL herr_t H5C_dump_cache(H5C_t *cache_ptr, const char *cache_name);
+H5_DLL herr_t H5C_dump_cache_LRU(H5C_t *cache_ptr, const char *cache_name);
H5_DLL hbool_t H5C_get_serialization_in_progress(const H5C_t *cache_ptr);
H5_DLL hbool_t H5C_cache_is_clean(const H5C_t *cache_ptr, H5C_ring_t inner_ring);
H5_DLL herr_t H5C_dump_cache_skip_list(H5C_t *cache_ptr, char *calling_fcn);
diff --git a/src/H5Ctag.c b/src/H5Ctag.c
index 157a838..a9bcca1 100644
--- a/src/H5Ctag.c
+++ b/src/H5Ctag.c
@@ -465,7 +465,7 @@ H5C__evict_tagged_entries_cb(H5C_cache_entry_t *entry, void *_ctx)
entry and we'll loop back around again (as evicting other
entries will hopefully unpin this entry) */
ctx->pinned_entries_need_evicted = TRUE;
- else {
+ else if(!entry->prefetched_dirty) {
/* Evict the Entry */
if(H5C__flush_single_entry(ctx->f, ctx->dxpl_id, entry, H5C__FLUSH_INVALIDATE_FLAG | H5C__FLUSH_CLEAR_ONLY_FLAG | H5C__DEL_FROM_SLIST_ON_DESTROY_FLAG) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, H5_ITER_ERROR, "Entry eviction failed.")