summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/H5AC.c105
-rw-r--r--src/H5AClog.c8
-rw-r--r--src/H5ACpkg.h8
-rw-r--r--src/H5ACprivate.h119
-rw-r--r--src/H5B.c34
-rw-r--r--src/H5B2.c23
-rw-r--r--src/H5B2cache.c1372
-rw-r--r--src/H5B2dbg.c13
-rw-r--r--src/H5B2int.c148
-rw-r--r--src/H5B2pkg.h5
-rw-r--r--src/H5B2test.c4
-rw-r--r--src/H5Bcache.c373
-rw-r--r--src/H5Bdbg.c6
-rw-r--r--src/H5C.c3783
-rw-r--r--src/H5Cpkg.h270
-rw-r--r--src/H5Cprivate.h1213
-rw-r--r--src/H5Dlayout.c2
-rw-r--r--src/H5EA.c28
-rw-r--r--src/H5EAcache.c2264
-rw-r--r--src/H5EAdbg.c14
-rw-r--r--src/H5EAdblkpage.c8
-rw-r--r--src/H5EAdblock.c10
-rw-r--r--src/H5EAhdr.c13
-rw-r--r--src/H5EAiblock.c10
-rw-r--r--src/H5EApkg.h23
-rw-r--r--src/H5EAsblock.c11
-rw-r--r--src/H5FA.c18
-rw-r--r--src/H5FAcache.c1299
-rw-r--r--src/H5FAdbg.c10
-rw-r--r--src/H5FAdblkpage.c8
-rw-r--r--src/H5FAdblock.c10
-rw-r--r--src/H5FAhdr.c13
-rw-r--r--src/H5FApkg.h15
-rw-r--r--src/H5FDfamily.c2
-rw-r--r--src/H5FDpublic.h6
-rw-r--r--src/H5FS.c27
-rw-r--r--src/H5FScache.c1535
-rw-r--r--src/H5FSdbg.c4
-rw-r--r--src/H5FSpkg.h4
-rw-r--r--src/H5FSsection.c33
-rw-r--r--src/H5Fint.c8
-rw-r--r--src/H5Fio.c8
-rw-r--r--src/H5Fpkg.h57
-rw-r--r--src/H5Fsuper.c495
-rw-r--r--src/H5Fsuper_cache.c1585
-rw-r--r--src/H5Gcache.c412
-rw-r--r--src/H5Gent.c2
-rw-r--r--src/H5Gnode.c24
-rw-r--r--src/H5Gstab.c22
-rw-r--r--src/H5Gtest.c6
-rw-r--r--src/H5HF.c8
-rw-r--r--src/H5HFcache.c2911
-rw-r--r--src/H5HFdbg.c12
-rw-r--r--src/H5HFdblock.c27
-rw-r--r--src/H5HFhdr.c11
-rw-r--r--src/H5HFiblock.c38
-rw-r--r--src/H5HFiter.c2
-rw-r--r--src/H5HFman.c20
-rw-r--r--src/H5HFpkg.h43
-rw-r--r--src/H5HFsection.c12
-rw-r--r--src/H5HG.c17
-rw-r--r--src/H5HGcache.c534
-rw-r--r--src/H5HGdbg.c2
-rw-r--r--src/H5HGpkg.h2
-rw-r--r--src/H5HL.c25
-rw-r--r--src/H5HLcache.c907
-rw-r--r--src/H5HLdbg.c2
-rw-r--r--src/H5HLpkg.h12
-rw-r--r--src/H5HLprivate.h2
-rw-r--r--src/H5O.c41
-rw-r--r--src/H5Oattribute.c10
-rw-r--r--src/H5Ocache.c1243
-rw-r--r--src/H5Ochunk.c6
-rw-r--r--src/H5Ocopy.c2
-rw-r--r--src/H5Odbg.c2
-rw-r--r--src/H5Oefl.c6
-rw-r--r--src/H5Oflush.c2
-rw-r--r--src/H5Omessage.c14
-rw-r--r--src/H5Opkg.h8
-rw-r--r--src/H5Oprivate.h4
-rw-r--r--src/H5Oproxy.c301
-rw-r--r--src/H5Otest.c14
-rw-r--r--src/H5SM.c30
-rw-r--r--src/H5SMcache.c858
-rw-r--r--src/H5SMtest.c2
85 files changed, 13765 insertions, 8835 deletions
diff --git a/src/H5AC.c b/src/H5AC.c
index 3662905..843022d 100644
--- a/src/H5AC.c
+++ b/src/H5AC.c
@@ -128,8 +128,7 @@ static herr_t H5AC__receive_haddr_list(MPI_Comm mpi_comm, int *num_entries_ptr,
haddr_t **haddr_buf_ptr_ptr);
static herr_t H5AC__receive_candidate_list(const H5AC_t *cache_ptr,
int *num_entries_ptr, haddr_t **haddr_buf_ptr_ptr);
-static herr_t H5AC__receive_and_apply_clean_list(H5F_t *f, hid_t primary_dxpl_id,
- hid_t secondary_dxpl_id);
+static herr_t H5AC__receive_and_apply_clean_list(H5F_t *f, hid_t dxpl_id);
static herr_t H5AC__tidy_cache_0_lists(H5AC_t *cache_ptr, int num_candidates,
haddr_t *candidates_list_ptr);
static herr_t H5AC__rsp__dist_md_write__flush(H5F_t *f, hid_t dxpl_id);
@@ -202,11 +201,11 @@ static const char * H5AC_entry_type_names[H5AC_NTYPES] =
"extensible array super blocks",
"extensible array data blocks",
"extensible array data block pages",
- "chunk proxy",
"fixed array headers",
"fixed array data block",
"fixed array data block pages",
"superblock",
+ "driver info",
"test entry" /* for testing only -- not used for actual files */
};
@@ -593,7 +592,7 @@ H5AC_dest(H5F_t *f, hid_t dxpl_id)
#endif /* H5_HAVE_PARALLEL */
/* Destroy the cache */
- if(H5C_dest(f, dxpl_id, H5AC_dxpl_id) < 0)
+ if(H5C_dest(f, dxpl_id) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTFREE, FAIL, "can't destroy cache")
f->shared->cache = NULL;
@@ -646,7 +645,7 @@ H5AC_evict(H5F_t *f, hid_t dxpl_id)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "unable to get logging status")
/* Evict all entries in the cache except the pinned superblock entry */
- if(H5C_evict(f, dxpl_id, H5AC_dxpl_id) < 0)
+ if(H5C_evict(f, dxpl_id) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTFREE, FAIL, "can't evict cache")
done:
@@ -693,8 +692,7 @@ H5AC_expunge_entry(H5F_t *f, hid_t dxpl_id, const H5AC_class_t *type,
HDassert(f->shared);
HDassert(f->shared->cache);
HDassert(type);
- HDassert(type->clear);
- HDassert(type->dest);
+ HDassert(type->serialize);
HDassert(H5F_addr_defined(addr));
/* Check if log messages are being emitted */
@@ -714,7 +712,7 @@ H5AC_expunge_entry(H5F_t *f, hid_t dxpl_id, const H5AC_class_t *type,
}
#endif /* H5AC__TRACE_FILE_ENABLED */
- if(H5C_expunge_entry(f, dxpl_id, H5AC_dxpl_id, type, addr, flags) < 0)
+ if(H5C_expunge_entry(f, dxpl_id, type, addr, flags) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTEXPUNGE, FAIL, "H5C_expunge_entry() failed.")
done:
@@ -792,7 +790,7 @@ H5AC_flush(H5F_t *f, hid_t dxpl_id)
/* Flush the cache */
/* (Again, in parallel - writes out the superblock) */
- if(H5C_flush_cache(f, dxpl_id, H5AC_dxpl_id, H5AC__NO_FLAGS_SET) < 0)
+ if(H5C_flush_cache(f, dxpl_id, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't flush cache.")
done:
@@ -911,8 +909,7 @@ H5AC_insert_entry(H5F_t *f, hid_t dxpl_id, const H5AC_class_t *type, haddr_t add
HDassert(f->shared);
HDassert(f->shared->cache);
HDassert(type);
- HDassert(type->flush);
- HDassert(type->size);
+ HDassert(type->serialize);
HDassert(H5F_addr_defined(addr));
HDassert(thing);
@@ -951,7 +948,7 @@ H5AC_insert_entry(H5F_t *f, hid_t dxpl_id, const H5AC_class_t *type, haddr_t add
#endif /* H5AC_DO_TAGGING_SANITY_CHECKS */
/* Insert entry into metadata cache */
- if(H5C_insert_entry(f, dxpl_id, H5AC_dxpl_id, type, addr, thing, flags) < 0)
+ if(H5C_insert_entry(f, dxpl_id, type, addr, thing, flags) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTINS, FAIL, "H5C_insert_entry() failed")
#if H5AC__TRACE_FILE_ENABLED
@@ -1318,7 +1315,7 @@ done:
*/
void *
H5AC_protect(H5F_t *f, hid_t dxpl_id, const H5AC_class_t *type, haddr_t addr,
- void *udata, H5AC_protect_t rw)
+ void *udata, unsigned flags)
{
#if H5AC__TRACE_FILE_ENABLED
char trace[128] = "";
@@ -1338,16 +1335,27 @@ H5AC_protect(H5F_t *f, hid_t dxpl_id, const H5AC_class_t *type, haddr_t addr,
HDassert(f->shared);
HDassert(f->shared->cache);
HDassert(type);
- HDassert(type->flush);
- HDassert(type->load);
+ HDassert(type->serialize);
HDassert(H5F_addr_defined(addr));
/* Check if log messages are being emitted */
if(H5C_get_logging_status(f->shared->cache, &log_enabled, &curr_logging) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, NULL, "unable to get logging status")
+ /* Check for unexpected flags -- H5C__FLUSH_COLLECTIVELY_FLAG
+ * only permitted in the parallel case.
+ */
+#ifdef H5_HAVE_PARALLEL
+ HDassert(0 == (flags & (unsigned)(~(H5C__READ_ONLY_FLAG | \
+ H5C__FLUSH_LAST_FLAG | \
+ H5C__FLUSH_COLLECTIVELY_FLAG))));
+#else /* H5_HAVE_PARALLEL */
+ HDassert(0 == (flags & (unsigned)(~(H5C__READ_ONLY_FLAG | \
+ H5C__FLUSH_LAST_FLAG))));
+#endif /* H5_HAVE_PARALLEL */
+
/* Check for invalid access request */
- if(0 == (H5F_INTENT(f) & H5F_ACC_RDWR) && rw == H5AC_WRITE)
+ if((0 == (H5F_INTENT(f) & H5F_ACC_RDWR)) && (0 == (flags & H5C__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, NULL, "no write intent on file")
/* FIXME: (temporary)
@@ -1359,36 +1367,21 @@ H5AC_protect(H5F_t *f, hid_t dxpl_id, const H5AC_class_t *type, haddr_t addr,
HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, NULL, "can't protect/write version 1 B-tree nodes under SWMR writes")
#if H5AC__TRACE_FILE_ENABLED
- /* For the protect call, only the addr and type id is really necessary
- * in the trace file. Include the size of the entry protected as a
- * sanity check. Also indicate whether the call was successful to
- * catch occult errors.
+ /* For the protect call, only the addr, size, type id, and flags are
+ * necessary in the trace file. Also indicate whether the call was
+ * successful to catch occult errors.
*/
- if(NULL != (trace_file_ptr = H5C_get_trace_file_ptr(cache_ptr))) {
- const char * rw_string;
-
- if (rw == H5AC_WRITE )
- rw_string = "H5AC_WRITE";
- else if (rw == H5AC_READ )
- rw_string = "H5AC_READ";
- else
- rw_string = "???";
-
- sprintf(trace, "%s 0x%lx %d %s", FUNC, (unsigned long)addr,
- (int)(type->id), rw_string);
- }
+ if(NULL != (trace_file_ptr = H5C_get_trace_file_ptr(cache_ptr)))
+ sprintf(trace, "%s 0x%lx %d 0x%x", FUNC, (unsigned long)addr,
+ (int)(type->id), flags);
#endif /* H5AC__TRACE_FILE_ENABLED */
- if ( rw == H5AC_READ )
- protect_flags |= H5C__READ_ONLY_FLAG;
-
#if H5AC_DO_TAGGING_SANITY_CHECKS
if (!f->shared->cache->ignore_tags && (H5AC_verify_tag(dxpl_id, type) < 0))
HGOTO_ERROR(H5E_CACHE, H5E_CANTTAG, NULL, "Bad tag value")
#endif /* H5AC_DO_TAGGING_SANITY_CHECKS */
- if(NULL == (thing = H5C_protect(f, dxpl_id, H5AC_dxpl_id, type, addr, udata, protect_flags)))
-
+ if(NULL == (thing = H5C_protect(f, dxpl_id, type, addr, udata, flags)))
HGOTO_ERROR(H5E_CACHE, H5E_CANTPROTECT, NULL, "H5C_protect() failed.")
#if H5AC__TRACE_FILE_ENABLED
@@ -1411,7 +1404,7 @@ done:
herr_t fake_ret_value = (NULL == ret_value) ? FAIL : SUCCEED;
if(H5AC__write_protect_entry_log_msg(f->shared->cache, (H5AC_info_t *)thing,
- rw, fake_ret_value) < 0)
+ flags, fake_ret_value) < 0)
HDONE_ERROR(H5E_CACHE, H5E_SYSTEM, NULL, "unable to emit log message")
}
@@ -1694,8 +1687,8 @@ H5AC_unprotect(H5F_t *f, hid_t dxpl_id, const H5AC_class_t *type, haddr_t addr,
HDassert(f->shared);
HDassert(f->shared->cache);
HDassert(type);
- HDassert(type->clear);
- HDassert(type->flush);
+ HDassert(type->deserialize);
+ HDassert(type->image_len);
HDassert(H5F_addr_defined(addr));
HDassert(thing);
HDassert( ((H5AC_info_t *)thing)->addr == addr );
@@ -1722,9 +1715,11 @@ H5AC_unprotect(H5F_t *f, hid_t dxpl_id, const H5AC_class_t *type, haddr_t addr,
* the entry.
*/
if(dirtied && !deleted) {
+ hbool_t curr_compressed = FALSE; /* dummy for call */
size_t curr_size = 0;
+ size_t curr_compressed_size = 0; /* dummy for call */
- if((type->size)(f, thing, &curr_size) < 0)
+ if((type->image_len)(thing, &curr_size, &curr_compressed, &curr_compressed_size) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTGETSIZE, FAIL, "Can't get size of thing")
if(((H5AC_info_t *)thing)->size != curr_size)
@@ -1743,7 +1738,7 @@ H5AC_unprotect(H5F_t *f, hid_t dxpl_id, const H5AC_class_t *type, haddr_t addr,
} /* end if */
#endif /* H5_HAVE_PARALLEL */
- if(H5C_unprotect(f, dxpl_id, H5AC_dxpl_id, type, addr, thing, flags) < 0)
+ if(H5C_unprotect(f, dxpl_id, type, addr, thing, flags) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, "H5C_unprotect() failed.")
#ifdef H5_HAVE_PARALLEL
@@ -3699,7 +3694,7 @@ H5AC__propagate_and_apply_candidate_list(H5F_t *f, hid_t dxpl_id)
aux_ptr->write_permitted = TRUE;
/* Apply the candidate list */
- result = H5C_apply_candidate_list(f, dxpl_id, dxpl_id, cache_ptr, num_candidates,
+ result = H5C_apply_candidate_list(f, dxpl_id, cache_ptr, num_candidates,
candidates_list_ptr, aux_ptr->mpi_rank, aux_ptr->mpi_size);
/* Disable writes again */
@@ -3843,7 +3838,7 @@ H5AC__propagate_flushed_and_still_clean_entries_list(H5F_t *f, hid_t dxpl_id)
HDassert(H5SL_count(aux_ptr->c_slist_ptr) == 0);
} /* end if */
else {
- if(H5AC__receive_and_apply_clean_list(f, dxpl_id, H5AC_dxpl_id) < 0)
+ if(H5AC__receive_and_apply_clean_list(f, dxpl_id) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Can't receive and/or process clean slist broadcast.")
} /* end else */
@@ -3947,7 +3942,7 @@ done:
*/
#ifdef H5_HAVE_PARALLEL
static herr_t
-H5AC__receive_and_apply_clean_list(H5F_t *f, hid_t primary_dxpl_id, hid_t secondary_dxpl_id)
+H5AC__receive_and_apply_clean_list(H5F_t *f, hid_t dxpl_id)
{
H5AC_t * cache_ptr;
H5AC_aux_t * aux_ptr;
@@ -3973,7 +3968,7 @@ H5AC__receive_and_apply_clean_list(H5F_t *f, hid_t primary_dxpl_id, hid_t second
if(num_entries > 0)
/* mark the indicated entries as clean */
- if(H5C_mark_entries_as_clean(f, primary_dxpl_id, secondary_dxpl_id, (int32_t)num_entries, haddr_buf_ptr) < 0)
+ if(H5C_mark_entries_as_clean(f, dxpl_id, (int32_t)num_entries, haddr_buf_ptr) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Can't mark entries clean.")
/* if it is defined, call the sync point done callback. Note
@@ -4140,7 +4135,7 @@ H5AC__rsp__dist_md_write__flush(H5F_t *f, hid_t dxpl_id)
aux_ptr->write_permitted = TRUE;
/* Apply the candidate list */
- result = H5C_apply_candidate_list(f, dxpl_id, dxpl_id, cache_ptr, num_entries,
+ result = H5C_apply_candidate_list(f, dxpl_id, cache_ptr, num_entries,
haddr_buf_ptr, aux_ptr->mpi_rank, aux_ptr->mpi_size);
/* Disable writes again */
@@ -4353,7 +4348,7 @@ H5AC__rsp__p0_only__flush(H5F_t *f, hid_t dxpl_id)
aux_ptr->write_permitted = TRUE;
/* Flush the cache */
- result = H5C_flush_cache(f, dxpl_id, dxpl_id, H5AC__NO_FLAGS_SET);
+ result = H5C_flush_cache(f, dxpl_id, H5AC__NO_FLAGS_SET);
/* Disable writes again */
aux_ptr->write_permitted = FALSE;
@@ -4477,7 +4472,7 @@ H5AC__rsp__p0_only__flush_to_min_clean(H5F_t *f, hid_t dxpl_id)
aux_ptr->write_permitted = TRUE;
/* Flush the cache */
- result = H5C_flush_to_min_clean(f, dxpl_id, H5AC_dxpl_id);
+ result = H5C_flush_to_min_clean(f, dxpl_id);
/* Disable writes again */
aux_ptr->write_permitted = FALSE;
@@ -4905,7 +4900,7 @@ H5AC_flush_tagged_metadata(H5F_t * f, haddr_t metadata_tag, hid_t dxpl_id)
HDassert(f->shared);
/* Call cache level function to flush metadata entries with specified tag */
- if(H5C_flush_tagged_entries(f, dxpl_id, H5AC_dxpl_id, metadata_tag)<0)
+ if(H5C_flush_tagged_entries(f, dxpl_id, metadata_tag)<0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Cannot flush metadata")
done:
@@ -4941,7 +4936,7 @@ H5AC_evict_tagged_metadata(H5F_t * f, haddr_t metadata_tag, hid_t dxpl_id)
HDassert(f->shared);
/* Call cache level function to evict metadata entries with specified tag */
- if(H5C_evict_tagged_entries(f, dxpl_id, H5AC_dxpl_id, metadata_tag)<0)
+ if(H5C_evict_tagged_entries(f, dxpl_id, metadata_tag)<0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Cannot evict metadata")
done:
@@ -5032,11 +5027,11 @@ H5AC_verify_tag(hid_t dxpl_id, const H5AC_class_t * type)
* constraints are met. */
/* Superblock */
- if(type->id == H5AC_SUPERBLOCK_ID) {
+ if(type->id == H5AC_SUPERBLOCK_ID || type->id == H5AC_DRVRINFO_ID) {
if(tag.value != H5AC__SUPERBLOCK_TAG)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTTAG, FAIL, "superblock not tagged with H5AC__SUPERBLOCK_TAG")
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTTAG, FAIL, "superblock/driver-info not tagged with H5AC__SUPERBLOCK_TAG")
if(tag.globality != H5C_GLOBALITY_MAJOR)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTTAG, FAIL, "superblock globality not marked with H5C_GLOBALITY_MAJOR")
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTTAG, FAIL, "superblock/driver-info globality not marked with H5C_GLOBALITY_MAJOR")
}
else {
if(tag.value == H5AC__SUPERBLOCK_TAG)
diff --git a/src/H5AClog.c b/src/H5AClog.c
index 1461738..fc96f9a 100644
--- a/src/H5AClog.c
+++ b/src/H5AClog.c
@@ -596,7 +596,7 @@ done:
herr_t
H5AC__write_protect_entry_log_msg(const H5AC_t *cache,
const H5AC_info_t *entry,
- H5AC_protect_t rw,
+ unsigned flags,
herr_t fxn_ret_value)
{
char msg[MSG_SIZE];
@@ -610,12 +610,10 @@ H5AC__write_protect_entry_log_msg(const H5AC_t *cache,
HDassert(cache->magic == H5C__H5C_T_MAGIC);
HDassert(entry);
- if(H5AC_READ == rw)
+ if(H5AC__READ_ONLY_FLAG == flags)
HDstrcpy(rw_s, "READ");
- else if(H5AC_WRITE == rw)
+ else
HDstrcpy(rw_s, "WRITE");
- else
- HDstrcpy(rw_s, "UNKNOWN");
/* Create the log message string */
HDsnprintf(msg, MSG_SIZE,
diff --git a/src/H5ACpkg.h b/src/H5ACpkg.h
index e1c2693..3afce99 100644
--- a/src/H5ACpkg.h
+++ b/src/H5ACpkg.h
@@ -391,6 +391,12 @@ typedef struct H5AC_aux_t
haddr_t * written_entries_tbl);
} H5AC_aux_t; /* struct H5AC_aux_t */
+/* Package scoped functions */
+H5_DLL herr_t H5AC_set_sync_point_done_callback(H5C_t *cache_ptr,
+ void (*sync_point_done)(int num_writes, haddr_t *written_entries_tbl));
+H5_DLL herr_t H5AC_set_write_done_callback(H5C_t * cache_ptr,
+ void (* write_done)(void));
+
#endif /* H5_HAVE_PARALLEL */
/******************************/
@@ -431,7 +437,7 @@ H5_DLL herr_t H5AC__write_create_fd_log_msg(const H5AC_t *cache,
herr_t fxn_ret_value);
H5_DLL herr_t H5AC__write_protect_entry_log_msg(const H5AC_t *cache,
const H5AC_info_t *entry,
- H5AC_protect_t rw,
+ unsigned flags,
herr_t fxn_ret_value);
H5_DLL herr_t H5AC__write_resize_entry_log_msg(const H5AC_t *cache,
const H5AC_info_t *entry,
diff --git a/src/H5ACprivate.h b/src/H5ACprivate.h
index 81f0dad..18794a0 100644
--- a/src/H5ACprivate.h
+++ b/src/H5ACprivate.h
@@ -76,11 +76,11 @@ typedef enum {
H5AC_EARRAY_SBLOCK_ID, /* (20) extensible array super block */
H5AC_EARRAY_DBLOCK_ID, /* (21) extensible array data block */
H5AC_EARRAY_DBLK_PAGE_ID, /* (22) extensible array data block page */
- H5AC_CHUNK_PROXY_ID, /* (23) chunk proxy */
- H5AC_FARRAY_HDR_ID, /* (24) fixed array header */
- H5AC_FARRAY_DBLOCK_ID, /* (25) fixed array data block */
- H5AC_FARRAY_DBLK_PAGE_ID, /* (26) fixed array data block page */
- H5AC_SUPERBLOCK_ID, /* (27) file superblock */
+ H5AC_FARRAY_HDR_ID, /* (23) fixed array header */
+ H5AC_FARRAY_DBLOCK_ID, /* (24) fixed array data block */
+ H5AC_FARRAY_DBLK_PAGE_ID, /* (25) fixed array data block page */
+ H5AC_SUPERBLOCK_ID, /* (26) file superblock */
+ H5AC_DRVRINFO_ID, /* (27) driver info block (supplements superblock)*/
H5AC_TEST_ID, /* (28) test entry -- not used for actual files */
H5AC_NTYPES /* Number of types, must be last */
} H5AC_type_t;
@@ -93,6 +93,17 @@ typedef enum {
* times for debugging purposes.
*
* Hence the following, somewhat odd set of #defines.
+ *
+ * NOTE: test/cache plays games with the f->shared->cache, and thus
+ * setting H5AC_DUMP_STATS_ON_CLOSE will generate constant,
+ * irrelevant data when run with that test program. See
+ * comments on setup_cache() / takedown_cache() in test/cache_common.c.
+ * for details.
+ *
+ * If you need to dump stats at file close in test/cache.c,
+ * use the dump_stats parameter to takedown_cache(), or call
+ * H5C_stats() directly.
+ * JRM -- 4/12/15
*/
#if H5C_COLLECT_CACHE_STATS
@@ -121,33 +132,12 @@ typedef enum {
/*
* Class methods pertaining to caching. Each type of cached object will
* have a constant variable with permanent life-span that describes how
- * to cache the object. That variable will be of type H5AC_class_t and
- * have the following required fields...
- *
- * LOAD: Loads an object from disk to memory. The function
- * should allocate some data structure and return it.
- *
- * FLUSH: Writes some data structure back to disk. It would be
- * wise for the data structure to include dirty flags to
- * indicate whether it really needs to be written. This
- * function is also responsible for freeing memory allocated
- * by the LOAD method if the DEST argument is non-zero (by
- * calling the DEST method).
- *
- * DEST: Just frees memory allocated by the LOAD method.
- *
- * CLEAR: Just marks object as non-dirty.
- *
- * NOTIFY: Notify client that an action on an entry has taken/will take
- * place
- *
- * SIZE: Report the size (on disk) of the specified cache object.
- * Note that the space allocated on disk may not be contiguous.
+ * to cache the object.
*/
-#define H5AC_CALLBACK__NO_FLAGS_SET H5C_CALLBACK__NO_FLAGS_SET
-#define H5AC_CALLBACK__SIZE_CHANGED_FLAG H5C_CALLBACK__SIZE_CHANGED_FLAG
-#define H5AC_CALLBACK__MOVED_FLAG H5C_CALLBACK__MOVED_FLAG
+#define H5AC__SERIALIZE_RESIZED_FLAG H5C__SERIALIZE_RESIZED_FLAG
+#define H5AC__SERIALIZE_MOVED_FLAG H5C__SERIALIZE_MOVED_FLAG
+#define H5AC__SERIALIZE_COMPRESSED_FLAG H5C__SERIALIZE_COMPRESSED_FLAG
/* Cork actions: cork/uncork/get cork status of an object */
@@ -158,50 +148,40 @@ typedef enum {
/* Aliases for 'notify action' type & values */
typedef H5C_notify_action_t H5AC_notify_action_t;
#define H5AC_NOTIFY_ACTION_AFTER_INSERT H5C_NOTIFY_ACTION_AFTER_INSERT
+#define H5AC_NOTIFY_ACTION_AFTER_LOAD H5C_NOTIFY_ACTION_AFTER_LOAD
+#define H5AC_NOTIFY_ACTION_AFTER_FLUSH H5C_NOTIFY_ACTION_AFTER_FLUSH
#define H5AC_NOTIFY_ACTION_BEFORE_EVICT H5C_NOTIFY_ACTION_BEFORE_EVICT
-typedef H5C_load_func_t H5AC_load_func_t;
-typedef H5C_flush_func_t H5AC_flush_func_t;
-typedef H5C_dest_func_t H5AC_dest_func_t;
-typedef H5C_clear_func_t H5AC_clear_func_t;
-typedef H5C_notify_func_t H5AC_notify_func_t;
-typedef H5C_size_func_t H5AC_size_func_t;
+#define H5AC__CLASS_NO_FLAGS_SET H5C__CLASS_NO_FLAGS_SET
+#define H5AC__CLASS_SPECULATIVE_LOAD_FLAG H5C__CLASS_SPECULATIVE_LOAD_FLAG
+#define H5AC__CLASS_COMPRESSED_FLAG H5C__CLASS_COMPRESSED_FLAG
-typedef H5C_class_t H5AC_class_t;
+/* The following flags should only appear in test code */
+/* The H5AC__CLASS_SKIP_READS & H5AC__CLASS_SKIP_WRITES flags are used in H5Oproxy.c */
+#define H5AC__CLASS_NO_IO_FLAG H5C__CLASS_NO_IO_FLAG
+#define H5AC__CLASS_SKIP_READS H5C__CLASS_SKIP_READS
+#define H5AC__CLASS_SKIP_WRITES H5C__CLASS_SKIP_WRITES
+typedef H5C_get_load_size_func_t H5AC_get_load_size_func_t;
+typedef H5C_verify_chksum_func_t H5AC_verify_chksum_func_t;
+typedef H5C_deserialize_func_t H5AC_deserialize_func_t;
+typedef H5C_image_len_func_t H5AC_image_len_func_t;
-/* The H5AC_NSLOTS #define is now obsolete, as the metadata cache no longer
- * uses slots. However I am leaving it in for now to avoid modifying the
- * interface between the metadata cache and the rest of HDF. It should
- * be removed when we get to dealing with the size_hint parameter in
- * H5AC_create().
- * JRM - 5/20/04
- *
- * Old comment on H5AC_NSLOTS follows:
- *
- * A cache has a certain number of entries. Objects are mapped into a
- * cache entry by hashing the object's file address. Each file has its
- * own cache, an array of slots.
- */
-#define H5AC_NSLOTS 10330 /* The library "likes" this number... */
-
-
-typedef H5C_cache_entry_t H5AC_info_t;
+#define H5AC__SERIALIZE_NO_FLAGS_SET H5C__SERIALIZE_NO_FLAGS_SET
+#define H5AC__SERIALIZE_RESIZED_FLAG H5C__SERIALIZE_RESIZED_FLAG
+#define H5AC__SERIALIZE_MOVED_FLAG H5C__SERIALIZE_MOVED_FLAG
+typedef H5C_pre_serialize_func_t H5AC_pre_serialize_func_t;
+typedef H5C_serialize_func_t H5AC_serialize_func_t;
+typedef H5C_notify_func_t H5AC_notify_func_t;
+typedef H5C_free_icr_func_t H5AC_free_icr_func_t;
+typedef H5C_clear_func_t H5AC_clear_func_t;
+typedef H5C_get_fsf_size_t H5AC_get_fsf_size_t;
-/*===----------------------------------------------------------------------===
- * Protect Types
- *===----------------------------------------------------------------------===
- *
- * These are for the wrapper functions to H5AC_protect. They specify what
- * type of operation you're planning on doing to the metadata. The
- * Flexible Parallel HDF5 locking can then act accordingly.
- */
+typedef H5C_class_t H5AC_class_t;
-typedef enum H5AC_protect_t {
- H5AC_WRITE, /* Protect object for writing */
- H5AC_READ /* Protect object for reading */
-} H5AC_protect_t;
+/* Cache entry info */
+typedef H5C_cache_entry_t H5AC_info_t;
/* Typedef for metadata cache (defined in H5Cpkg.h) */
@@ -327,6 +307,7 @@ H5_DLLVAR hid_t H5AC_ind_dxpl_id;
#define H5AC__FLUSH_CLEAR_ONLY_FLAG H5C__FLUSH_CLEAR_ONLY_FLAG
#define H5AC__FLUSH_MARKED_ENTRIES_FLAG H5C__FLUSH_MARKED_ENTRIES_FLAG
#define H5AC__FLUSH_IGNORE_PROTECTED_FLAG H5C__FLUSH_IGNORE_PROTECTED_FLAG
+#define H5AC__READ_ONLY_FLAG H5C__READ_ONLY_FLAG
#define H5AC__FREE_FILE_SPACE_FLAG H5C__FREE_FILE_SPACE_FLAG
#define H5AC__TAKE_OWNERSHIP_FLAG H5C__TAKE_OWNERSHIP_FLAG
#define H5AC__FLUSH_LAST_FLAG H5C__FLUSH_LAST_FLAG
@@ -358,7 +339,7 @@ H5_DLL herr_t H5AC_insert_entry(H5F_t *f, hid_t dxpl_id, const H5AC_class_t *typ
H5_DLL herr_t H5AC_pin_protected_entry(void *thing);
H5_DLL herr_t H5AC_create_flush_dependency(void *parent_thing, void *child_thing);
H5_DLL void * H5AC_protect(H5F_t *f, hid_t dxpl_id, const H5AC_class_t *type,
- haddr_t addr, void *udata, H5AC_protect_t rw);
+ haddr_t addr, void *udata, unsigned flags);
H5_DLL herr_t H5AC_resize_entry(void *thing, size_t new_size);
H5_DLL herr_t H5AC_unpin_entry(void *thing);
H5_DLL herr_t H5AC_destroy_flush_dependency(void *parent_thing, void *child_thing);
@@ -372,10 +353,6 @@ H5_DLL herr_t H5AC_dest(H5F_t *f, hid_t dxpl_id);
H5_DLL herr_t H5AC_evict(H5F_t *f, hid_t dxpl_id);
H5_DLL herr_t H5AC_expunge_entry(H5F_t *f, hid_t dxpl_id,
const H5AC_class_t *type, haddr_t addr, unsigned flags);
-H5_DLL herr_t H5AC_set_sync_point_done_callback(H5C_t *cache_ptr,
- void (*sync_point_done)(int num_writes, haddr_t *written_entries_tbl));
-H5_DLL herr_t H5AC_set_write_done_callback(H5C_t * cache_ptr,
- void (* write_done)(void));
H5_DLL herr_t H5AC_get_cache_auto_resize_config(const H5AC_t * cache_ptr,
H5AC_cache_config_t *config_ptr);
H5_DLL herr_t H5AC_get_cache_size(H5AC_t *cache_ptr, size_t *max_size_ptr,
diff --git a/src/H5B.c b/src/H5B.c
index dd5c384..8c6ee28 100644
--- a/src/H5B.c
+++ b/src/H5B.c
@@ -335,7 +335,7 @@ H5B_find(H5F_t *f, hid_t dxpl_id, const H5B_class_t *type, haddr_t addr, void *u
cache_udata.f = f;
cache_udata.type = type;
cache_udata.rc_shared = rc_shared;
- if(NULL == (bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, addr, &cache_udata, H5AC_READ)))
+ if(NULL == (bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, addr, &cache_udata, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree node")
rt = bt->nchildren;
@@ -485,7 +485,7 @@ H5B__split(H5F_t *f, hid_t dxpl_id, H5B_ins_ud_t *bt_ud, unsigned idx,
cache_udata.type = shared->type;
cache_udata.parent = bt_ud->bt->parent;
cache_udata.rc_shared = bt_ud->bt->rc_shared;
- if(NULL == (split_bt_ud->bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, split_bt_ud->addr, &cache_udata, H5AC_WRITE)))
+ if(NULL == (split_bt_ud->bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, split_bt_ud->addr, &cache_udata, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree")
split_bt_ud->bt->level = bt_ud->bt->level;
@@ -518,7 +518,7 @@ H5B__split(H5F_t *f, hid_t dxpl_id, H5B_ins_ud_t *bt_ud, unsigned idx,
if(H5F_addr_defined(bt_ud->bt->right)) {
H5B_t *tmp_bt;
- if(NULL == (tmp_bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, bt_ud->bt->right, &cache_udata, H5AC_WRITE)))
+ if(NULL == (tmp_bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, bt_ud->bt->right, &cache_udata, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load right sibling")
tmp_bt->left = split_bt_ud->addr;
@@ -598,7 +598,7 @@ H5B_insert(H5F_t *f, hid_t dxpl_id, const H5B_class_t *type, haddr_t addr, void
cache_udata.type = type;
cache_udata.rc_shared = rc_shared;
bt_ud.addr = addr;
- if(NULL == (bt_ud.bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, addr, &cache_udata, H5AC_WRITE)))
+ if(NULL == (bt_ud.bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, addr, &cache_udata, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to locate root of B-tree")
/* Insert the object */
@@ -910,7 +910,7 @@ H5B__insert_helper(H5F_t *f, hid_t dxpl_id, H5B_ins_ud_t *bt_ud,
* Follow the minimum branch out of this node to a subtree.
*/
child_bt_ud.addr = bt->child[idx];
- if(NULL == (child_bt_ud.bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, child_bt_ud.addr, &cache_udata, H5AC_WRITE)))
+ if(NULL == (child_bt_ud.bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, child_bt_ud.addr, &cache_udata, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, H5B_INS_ERROR, "unable to load node")
if((int)(my_ins = H5B__insert_helper(f, dxpl_id, &child_bt_ud, type,
@@ -956,7 +956,7 @@ H5B__insert_helper(H5F_t *f, hid_t dxpl_id, H5B_ins_ud_t *bt_ud,
*/
idx = bt->nchildren - 1;
child_bt_ud.addr = bt->child[idx];
- if(NULL == (child_bt_ud.bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, child_bt_ud.addr, &cache_udata, H5AC_WRITE)))
+ if(NULL == (child_bt_ud.bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, child_bt_ud.addr, &cache_udata, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, H5B_INS_ERROR, "unable to load node")
if((int)(my_ins = H5B__insert_helper(f, dxpl_id, &child_bt_ud, type,
@@ -1011,7 +1011,7 @@ H5B__insert_helper(H5F_t *f, hid_t dxpl_id, H5B_ins_ud_t *bt_ud,
*/
HDassert(idx < bt->nchildren);
child_bt_ud.addr = bt->child[idx];
- if(NULL == (child_bt_ud.bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, child_bt_ud.addr, &cache_udata, H5AC_WRITE)))
+ if(NULL == (child_bt_ud.bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, child_bt_ud.addr, &cache_udata, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, H5B_INS_ERROR, "unable to load node")
if((int)(my_ins = H5B__insert_helper(f, dxpl_id, &child_bt_ud, type,
@@ -1177,7 +1177,7 @@ H5B__iterate_helper(H5F_t *f, hid_t dxpl_id, const H5B_class_t *type, haddr_t ad
cache_udata.f = f;
cache_udata.type = type;
cache_udata.rc_shared = rc_shared;
- if(NULL == (bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, addr, &cache_udata, H5AC_READ)))
+ if(NULL == (bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, addr, &cache_udata, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, H5_ITER_ERROR, "unable to load B-tree node")
/* Iterate over node's children */
@@ -1299,7 +1299,7 @@ H5B__remove_helper(H5F_t *f, hid_t dxpl_id, haddr_t addr, const H5B_class_t *typ
cache_udata.f = f;
cache_udata.type = type;
cache_udata.rc_shared = rc_shared;
- if(NULL == (bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, addr, &cache_udata, H5AC_WRITE)))
+ if(NULL == (bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, addr, &cache_udata, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, H5B_INS_ERROR, "unable to load B-tree node")
rt = bt->nchildren;
@@ -1399,7 +1399,7 @@ H5B__remove_helper(H5F_t *f, hid_t dxpl_id, haddr_t addr, const H5B_class_t *typ
* "critical" for any child in its node to maintain this
* consistency (and avoid breaking key/child consistency) */
if(H5F_addr_defined(bt->left)) {
- if(NULL == (sibling = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, bt->left, &cache_udata, H5AC_WRITE)))
+ if(NULL == (sibling = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, bt->left, &cache_udata, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, H5B_INS_ERROR, "unable to load node from tree")
/* Copy right-most key from deleted node to right-most key
@@ -1416,7 +1416,7 @@ H5B__remove_helper(H5F_t *f, hid_t dxpl_id, haddr_t addr, const H5B_class_t *typ
sibling = NULL; /* Make certain future references will be caught */
} /* end if */
if(H5F_addr_defined(bt->right)) {
- if(NULL == (sibling = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, bt->right, &cache_udata, H5AC_WRITE)))
+ if(NULL == (sibling = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, bt->right, &cache_udata, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, H5B_INS_ERROR, "unable to unlink node from tree")
/* Copy left-most key from deleted node to left-most key in
@@ -1536,7 +1536,7 @@ H5B__remove_helper(H5F_t *f, hid_t dxpl_id, haddr_t addr, const H5B_class_t *typ
HDassert(level > 0);
/* Update the rightmost key in the left sibling */
- if(NULL == (sibling = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, bt->left, &cache_udata, H5AC_WRITE)))
+ if(NULL == (sibling = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, bt->left, &cache_udata, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, H5B_INS_ERROR, "unable to protect node")
HDmemcpy(H5B_NKEY(sibling, shared, sibling->nchildren),
@@ -1551,7 +1551,7 @@ H5B__remove_helper(H5F_t *f, hid_t dxpl_id, haddr_t addr, const H5B_class_t *typ
HDassert(level > 0);
/* Update the lefttmost key in the right sibling */
- if(NULL == (sibling = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, bt->right, &cache_udata, H5AC_WRITE)))
+ if(NULL == (sibling = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, bt->right, &cache_udata, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, H5B_INS_ERROR, "unable to protect node")
HDmemcpy(H5B_NKEY(sibling, shared, 0),
@@ -1659,7 +1659,7 @@ H5B_delete(H5F_t *f, hid_t dxpl_id, const H5B_class_t *type, haddr_t addr, void
cache_udata.f = f;
cache_udata.type = type;
cache_udata.rc_shared = rc_shared;
- if(NULL == (bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, addr, &cache_udata, H5AC_WRITE)))
+ if(NULL == (bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, addr, &cache_udata, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree node")
/* Iterate over all children in tree, deleting them */
@@ -1921,7 +1921,7 @@ H5B__get_info_helper(H5F_t *f, hid_t dxpl_id, const H5B_class_t *type, haddr_t a
cache_udata.f = f;
cache_udata.type = type;
cache_udata.rc_shared = rc_shared;
- if(NULL == (bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, addr, &cache_udata, H5AC_READ)))
+ if(NULL == (bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, addr, &cache_udata, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree node")
/* Cache information from this node */
@@ -1945,7 +1945,7 @@ H5B__get_info_helper(H5F_t *f, hid_t dxpl_id, const H5B_class_t *type, haddr_t a
while(H5F_addr_defined(next_addr)) {
/* Protect the next node to the right */
addr = next_addr;
- if(NULL == (bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, addr, &cache_udata, H5AC_READ)))
+ if(NULL == (bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, addr, &cache_udata, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "B-tree node")
/* Cache information from this node */
@@ -2074,7 +2074,7 @@ H5B_valid(H5F_t *f, hid_t dxpl_id, const H5B_class_t *type, haddr_t addr,
cache_udata.type = type;
cache_udata.parent = parent;
cache_udata.rc_shared = rc_shared;
- if(NULL == (bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, addr, &cache_udata, H5AC_READ)))
+ if(NULL == (bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, addr, &cache_udata, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree node")
done:
diff --git a/src/H5B2.c b/src/H5B2.c
index d7684a9..8e6aba3 100644
--- a/src/H5B2.c
+++ b/src/H5B2.c
@@ -161,8 +161,9 @@ H5B2_create(H5F_t *f, hid_t dxpl_id, const H5B2_create_t *cparam,
/* Look up the B-tree header */
cache_udata.f = f;
cache_udata.parent = parent;
+ cache_udata.addr = hdr_addr;
cache_udata.ctx_udata = ctx_udata;
- if(NULL == (hdr = (H5B2_hdr_t *)H5AC_protect(f, dxpl_id, H5AC_BT2_HDR, hdr_addr, &cache_udata, H5AC_WRITE)))
+ if(NULL == (hdr = (H5B2_hdr_t *)H5AC_protect(f, dxpl_id, H5AC_BT2_HDR, hdr_addr, &cache_udata, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, NULL, "unable to load B-tree header")
/* Point v2 B-tree wrapper at header and bump it's ref count */
@@ -222,8 +223,9 @@ H5B2_open(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *ctx_udata, void *parent)
/* Look up the B-tree header */
cache_udata.f = f;
cache_udata.parent = parent;
+ cache_udata.addr = addr;
cache_udata.ctx_udata = ctx_udata;
- if(NULL == (hdr = (H5B2_hdr_t *)H5AC_protect(f, dxpl_id, H5AC_BT2_HDR, addr, &cache_udata, H5AC_READ)))
+ if(NULL == (hdr = (H5B2_hdr_t *)H5AC_protect(f, dxpl_id, H5AC_BT2_HDR, addr, &cache_udata, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, NULL, "unable to load B-tree header")
/* Check for pending heap deletion */
@@ -491,7 +493,7 @@ H5B2_find(H5B2_t *bt2, hid_t dxpl_id, void *udata, H5B2_found_t op,
H5B2_node_ptr_t next_node_ptr; /* Node pointer info for next node */
/* Lock B-tree current node */
- if(NULL == (internal = H5B2__protect_internal(hdr, dxpl_id, curr_node_ptr.addr, parent, curr_node_ptr.node_nrec, depth, H5AC_READ)))
+ if(NULL == (internal = H5B2__protect_internal(hdr, dxpl_id, curr_node_ptr.addr, parent, curr_node_ptr.node_nrec, depth, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
/* Unpin parent if necessary */
@@ -565,7 +567,7 @@ H5B2_find(H5B2_t *bt2, hid_t dxpl_id, void *udata, H5B2_found_t op,
H5B2_leaf_t *leaf; /* Pointer to leaf node in B-tree */
/* Lock B-tree leaf node */
- if(NULL == (leaf = H5B2__protect_leaf(hdr, dxpl_id, curr_node_ptr.addr, parent, curr_node_ptr.node_nrec, H5AC_READ)))
+ if(NULL == (leaf = H5B2__protect_leaf(hdr, dxpl_id, curr_node_ptr.addr, parent, curr_node_ptr.node_nrec, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
/* Unpin parent if necessary */
@@ -703,7 +705,7 @@ H5B2_index(H5B2_t *bt2, hid_t dxpl_id, H5_iter_order_t order, hsize_t idx,
unsigned u; /* Local index variable */
/* Lock B-tree current node */
- if(NULL == (internal = H5B2__protect_internal(hdr, dxpl_id, curr_node_ptr.addr, parent, curr_node_ptr.node_nrec, depth, H5AC_READ)))
+ if(NULL == (internal = H5B2__protect_internal(hdr, dxpl_id, curr_node_ptr.addr, parent, curr_node_ptr.node_nrec, depth, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
/* Unpin parent if necessary */
@@ -790,7 +792,7 @@ H5B2_index(H5B2_t *bt2, hid_t dxpl_id, H5_iter_order_t order, hsize_t idx,
H5B2_leaf_t *leaf; /* Pointer to leaf node in B-tree */
/* Lock B-tree leaf node */
- if(NULL == (leaf = H5B2__protect_leaf(hdr, dxpl_id, curr_node_ptr.addr, parent, curr_node_ptr.node_nrec, H5AC_READ)))
+ if(NULL == (leaf = H5B2__protect_leaf(hdr, dxpl_id, curr_node_ptr.addr, parent, curr_node_ptr.node_nrec, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
/* Unpin parent if necessary */
@@ -1152,7 +1154,7 @@ H5B2_modify(H5B2_t *bt2, hid_t dxpl_id, void *udata, H5B2_modify_t op,
H5B2_node_ptr_t next_node_ptr; /* Node pointer info for next node */
/* Lock B-tree current node */
- if(NULL == (internal = H5B2__protect_internal(hdr, dxpl_id, curr_node_ptr.addr, parent, curr_node_ptr.node_nrec, depth, H5AC_WRITE)))
+ if(NULL == (internal = H5B2__protect_internal(hdr, dxpl_id, curr_node_ptr.addr, parent, curr_node_ptr.node_nrec, depth, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
/* Unpin parent if necessary */
@@ -1235,7 +1237,7 @@ H5B2_modify(H5B2_t *bt2, hid_t dxpl_id, void *udata, H5B2_modify_t op,
hbool_t changed = FALSE;/* Whether the 'modify' callback changed the record */
/* Lock B-tree leaf node */
- if(NULL == (leaf = H5B2__protect_leaf(hdr, dxpl_id, curr_node_ptr.addr, parent, curr_node_ptr.node_nrec, H5AC_WRITE)))
+ if(NULL == (leaf = H5B2__protect_leaf(hdr, dxpl_id, curr_node_ptr.addr, parent, curr_node_ptr.node_nrec, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
/* Unpin parent if necessary */
@@ -1382,7 +1384,7 @@ H5B2_close(H5B2_t *bt2, hid_t dxpl_id)
/* Lock the v2 B-tree header into memory */
/* (OK to pass in NULL for callback context, since we know the header must be in the cache) */
- if(NULL == (hdr = (H5B2_hdr_t *)H5AC_protect(bt2->f, dxpl_id, H5AC_BT2_HDR, bt2_addr, NULL, H5AC_WRITE)))
+ if(NULL == (hdr = (H5B2_hdr_t *)H5AC_protect(bt2->f, dxpl_id, H5AC_BT2_HDR, bt2_addr, NULL, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect v2 B-tree header")
/* Set the shared v2 B-tree header's file context for this operation */
@@ -1459,8 +1461,9 @@ HDfprintf(stderr, "%s: addr = %a\n", FUNC, addr);
#endif /* QAK */
cache_udata.f = f;
cache_udata.parent = parent;
+ cache_udata.addr = addr;
cache_udata.ctx_udata = ctx_udata;
- if(NULL == (hdr = (H5B2_hdr_t *)H5AC_protect(f, dxpl_id, H5AC_BT2_HDR, addr, &cache_udata, H5AC_WRITE)))
+ if(NULL == (hdr = (H5B2_hdr_t *)H5AC_protect(f, dxpl_id, H5AC_BT2_HDR, addr, &cache_udata, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect v2 B-tree header")
/* Remember the callback & context for later */
diff --git a/src/H5B2cache.c b/src/H5B2cache.c
index 8e5554a..87daebb 100644
--- a/src/H5B2cache.c
+++ b/src/H5B2cache.c
@@ -37,7 +37,6 @@
#include "H5private.h" /* Generic Functions */
#include "H5B2pkg.h" /* v2 B-trees */
#include "H5Eprivate.h" /* Error handling */
-#include "H5MFprivate.h" /* File memory management */
#include "H5WBprivate.h" /* Wrapped Buffers */
@@ -50,9 +49,6 @@
#define H5B2_INT_VERSION 0 /* Internal node */
#define H5B2_LEAF_VERSION 0 /* Leaf node */
-/* Size of stack buffer for serialized headers */
-#define H5B2_HDR_BUF_SIZE 128
-
/******************/
/* Local Typedefs */
@@ -69,25 +65,44 @@
/********************/
/* Metadata cache callbacks */
-static H5B2_hdr_t *H5B2__cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata);
-static herr_t H5B2__cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5B2_hdr_t *hdr, unsigned H5_ATTR_UNUSED * flags_ptr);
-static herr_t H5B2__cache_hdr_dest(H5F_t *f, H5B2_hdr_t *hdr);
-static herr_t H5B2__cache_hdr_clear(H5F_t *f, H5B2_hdr_t *hdr, hbool_t destroy);
-static herr_t H5B2__cache_hdr_notify(H5AC_notify_action_t action, H5B2_hdr_t *hdr);
-static herr_t H5B2__cache_hdr_size(const H5F_t *f, const H5B2_hdr_t *hdr, size_t *size_ptr);
-static H5B2_internal_t *H5B2__cache_internal_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata);
-static herr_t H5B2__cache_internal_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5B2_internal_t *i, unsigned H5_ATTR_UNUSED * flags_ptr);
-static herr_t H5B2__cache_internal_dest(H5F_t *f, H5B2_internal_t *internal);
-static herr_t H5B2__cache_internal_clear(H5F_t *f, H5B2_internal_t *i, hbool_t destroy);
-static herr_t H5B2__cache_internal_notify(H5AC_notify_action_t action, H5B2_internal_t *internal);
-static herr_t H5B2__cache_internal_size(const H5F_t *f, const H5B2_internal_t *i, size_t *size_ptr);
-static H5B2_leaf_t *H5B2__cache_leaf_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata);
-static herr_t H5B2__cache_leaf_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5B2_leaf_t *l, unsigned H5_ATTR_UNUSED * flags_ptr);
-static herr_t H5B2__cache_leaf_dest(H5F_t *f, H5B2_leaf_t *leaf);
-static herr_t H5B2__cache_leaf_clear(H5F_t *f, H5B2_leaf_t *l, hbool_t destroy);
-static herr_t H5B2__cache_leaf_notify(H5AC_notify_action_t action, H5B2_leaf_t *leaf);
-static herr_t H5B2__cache_leaf_size(const H5F_t *f, const H5B2_leaf_t *l, size_t *size_ptr);
-
+static herr_t H5B2__cache_hdr_get_load_size(const void *image_ptr, void *udata,
+ size_t *image_len, size_t *actual_len,
+ hbool_t *compressed_ptr, size_t *compressed_image_len_ptr);
+static htri_t H5B2__cache_hdr_verify_chksum(const void *image_ptr, size_t len, void *udata);
+static void *H5B2__cache_hdr_deserialize(const void *image, size_t len,
+ void *udata, hbool_t *dirty);
+static herr_t H5B2__cache_hdr_image_len(const void *thing, size_t *image_len,
+ hbool_t *compressed_ptr, size_t *compressed_image_len_ptr);
+static herr_t H5B2__cache_hdr_serialize(const H5F_t *f, void *image, size_t len,
+ void *thing);
+static herr_t H5B2__cache_hdr_notify(H5AC_notify_action_t action, void *thing);
+static herr_t H5B2__cache_hdr_free_icr(void *thing);
+
+static herr_t H5B2__cache_int_get_load_size(const void *image_ptr, void *udata,
+ size_t *image_len, size_t *actual_len,
+ hbool_t *compressed_ptr, size_t *compressed_image_len_ptr);
+static htri_t H5B2__cache_int_verify_chksum(const void *image_ptr, size_t len, void *udata);
+static void *H5B2__cache_int_deserialize(const void *image, size_t len,
+ void *udata, hbool_t *dirty);
+static herr_t H5B2__cache_int_image_len(const void *thing, size_t *image_len,
+ hbool_t *compressed_ptr, size_t *compressed_image_len_ptr);
+static herr_t H5B2__cache_int_serialize(const H5F_t *f, void *image, size_t len,
+ void *thing);
+static herr_t H5B2__cache_int_notify(H5AC_notify_action_t action, void *thing);
+static herr_t H5B2__cache_int_free_icr(void *thing);
+
+static herr_t H5B2__cache_leaf_get_load_size(const void * mage_ptr, void *udata,
+ size_t *image_len, size_t *actual_len,
+ hbool_t *compressed_ptr, size_t *compressed_image_len_ptr);
+static htri_t H5B2__cache_leaf_verify_chksum(const void *image_ptr, size_t len, void *udata);
+static void *H5B2__cache_leaf_deserialize(const void *image, size_t len,
+ void *udata, hbool_t *dirty);
+static herr_t H5B2__cache_leaf_image_len(const void *thing, size_t *image_len,
+ hbool_t *compressed_ptr, size_t *compressed_image_len_ptr);
+static herr_t H5B2__cache_leaf_serialize(const H5F_t *f, void *image, size_t len,
+ void *thing);
+static herr_t H5B2__cache_leaf_notify(H5AC_notify_action_t action, void *thing);
+static herr_t H5B2__cache_leaf_free_icr(void *thing);
/*********************/
/* Package Variables */
@@ -95,35 +110,56 @@ static herr_t H5B2__cache_leaf_size(const H5F_t *f, const H5B2_leaf_t *l, size_t
/* H5B2 inherits cache-like properties from H5AC */
const H5AC_class_t H5AC_BT2_HDR[1] = {{
- H5AC_BT2_HDR_ID,
- (H5AC_load_func_t)H5B2__cache_hdr_load,
- (H5AC_flush_func_t)H5B2__cache_hdr_flush,
- (H5AC_dest_func_t)H5B2__cache_hdr_dest,
- (H5AC_clear_func_t)H5B2__cache_hdr_clear,
- (H5AC_notify_func_t)H5B2__cache_hdr_notify,
- (H5AC_size_func_t)H5B2__cache_hdr_size,
+ H5AC_BT2_HDR_ID, /* Metadata client ID */
+ "v2 B-tree header", /* Metadata client name (for debugging) */
+ H5FD_MEM_BTREE, /* File space memory type for client */
+ H5AC__CLASS_NO_FLAGS_SET, /* Client class behavior flags */
+ H5B2__cache_hdr_get_load_size, /* 'get_load_size' callback */
+ H5B2__cache_hdr_verify_chksum,
+ H5B2__cache_hdr_deserialize, /* 'deserialize' callback */
+ H5B2__cache_hdr_image_len, /* 'image_len' callback */
+ NULL, /* 'pre_serialize' callback */
+ H5B2__cache_hdr_serialize, /* 'serialize' callback */
+ H5B2__cache_hdr_notify, /* 'notify' callback */
+ H5B2__cache_hdr_free_icr, /* 'free_icr' callback */
+ NULL, /* 'clear' callback */
+ NULL, /* 'fsf_size' callback */
}};
/* H5B2 inherits cache-like properties from H5AC */
const H5AC_class_t H5AC_BT2_INT[1] = {{
- H5AC_BT2_INT_ID,
- (H5AC_load_func_t)H5B2__cache_internal_load,
- (H5AC_flush_func_t)H5B2__cache_internal_flush,
- (H5AC_dest_func_t)H5B2__cache_internal_dest,
- (H5AC_clear_func_t)H5B2__cache_internal_clear,
- (H5AC_notify_func_t)H5B2__cache_internal_notify,
- (H5AC_size_func_t)H5B2__cache_internal_size,
+ H5AC_BT2_INT_ID, /* Metadata client ID */
+ "v2 B-tree internal node", /* Metadata client name (for debugging) */
+ H5FD_MEM_BTREE, /* File space memory type for client */
+ H5AC__CLASS_NO_FLAGS_SET, /* Client class behavior flags */
+ H5B2__cache_int_get_load_size, /* 'get_load_size' callback */
+ H5B2__cache_int_verify_chksum, /* 'verify_chksum' callback */
+ H5B2__cache_int_deserialize, /* 'deserialize' callback */
+ H5B2__cache_int_image_len, /* 'image_len' callback */
+ NULL, /* 'pre_serialize' callback */
+ H5B2__cache_int_serialize, /* 'serialize' callback */
+ H5B2__cache_int_notify, /* 'notify' callback */
+ H5B2__cache_int_free_icr, /* 'free_icr' callback */
+ NULL, /* 'clear' callback */
+ NULL, /* 'fsf_size' callback */
}};
/* H5B2 inherits cache-like properties from H5AC */
const H5AC_class_t H5AC_BT2_LEAF[1] = {{
- H5AC_BT2_LEAF_ID,
- (H5AC_load_func_t)H5B2__cache_leaf_load,
- (H5AC_flush_func_t)H5B2__cache_leaf_flush,
- (H5AC_dest_func_t)H5B2__cache_leaf_dest,
- (H5AC_clear_func_t)H5B2__cache_leaf_clear,
- (H5AC_notify_func_t)H5B2__cache_leaf_notify,
- (H5AC_size_func_t)H5B2__cache_leaf_size,
+ H5AC_BT2_LEAF_ID, /* Metadata client ID */
+ "v2 B-tree leaf node", /* Metadata client name (for debugging) */
+ H5FD_MEM_BTREE, /* File space memory type for client */
+ H5AC__CLASS_NO_FLAGS_SET, /* Client class behavior flags */
+ H5B2__cache_leaf_get_load_size, /* 'get_load_size' callback */
+ H5B2__cache_leaf_verify_chksum, /* 'verify_chksum' callback */
+ H5B2__cache_leaf_deserialize, /* 'deserialize' callback */
+ H5B2__cache_leaf_image_len, /* 'image_len' callback */
+ NULL, /* 'pre_serialize' callback */
+ H5B2__cache_leaf_serialize, /* 'serialize' callback */
+ H5B2__cache_leaf_notify, /* 'notify' callback */
+ H5B2__cache_leaf_free_icr, /* 'free_icr' callback */
+ NULL, /* 'clear' callback */
+ NULL, /* 'fsf_size' callback */
}};
@@ -139,7 +175,82 @@ const H5AC_class_t H5AC_BT2_LEAF[1] = {{
/*-------------------------------------------------------------------------
- * Function: H5B2__cache_hdr_load
+ * Function: H5B2__cache_hdr_get_load_size
+ *
+ * Purpose: Compute the size of the data structure on disk.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * May 18, 2010
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5B2__cache_hdr_get_load_size(const void *_image, void *_udata, size_t *image_len, size_t *actual_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr)
+{
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ H5B2_hdr_cache_ud_t *udata = (H5B2_hdr_cache_ud_t *)_udata; /* User data for callback */
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Check arguments */
+ HDassert(udata);
+ HDassert(udata->f);
+ HDassert(image_len);
+
+ if(image == NULL) {
+ /* Set the image length size */
+ *image_len = H5B2_HEADER_SIZE_FILE(udata->f);
+ } else {
+ HDassert(actual_len);
+ HDassert(*actual_len == *actual_len);
+ }
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5B2__cache_hdr_get_load_size() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B2__cache_hdr_verify_chksum
+ *
+ * Purpose: Verify the computed checksum of the data structure is the
+ * same as the stored chksum.
+ *
+ * Return: Success: TRUE/FALSE
+ * Failure: Negative
+ *
+ * Programmer: Vailin Choi; Aug 2015
+ *
+ *-------------------------------------------------------------------------
+ */
+static htri_t
+H5B2__cache_hdr_verify_chksum(const void *_image, size_t len, void H5_ATTR_UNUSED *_udata)
+{
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ uint32_t stored_chksum; /* Stored metadata checksum value */
+ uint32_t computed_chksum; /* Computed metadata checksum value */
+ htri_t ret_value = TRUE; /* Return value */
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Check arguments */
+ HDassert(image);
+
+ /* Get stored and computed checksums */
+ H5F_get_checksums(image, len, &stored_chksum, &computed_chksum);
+
+ if(stored_chksum != computed_chksum)
+ ret_value = FALSE;
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5B2__cache_hdr_verify_chksum() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B2__cache_hdr_deserialize
*
* Purpose: Loads a B-tree header from the disk.
*
@@ -152,82 +263,68 @@ const H5AC_class_t H5AC_BT2_LEAF[1] = {{
*
*-------------------------------------------------------------------------
*/
-static H5B2_hdr_t *
-H5B2__cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
+static void *
+H5B2__cache_hdr_deserialize(const void *_image, size_t H5_ATTR_UNUSED len,
+ void *_udata, hbool_t H5_ATTR_UNUSED *dirty)
{
H5B2_hdr_t *hdr = NULL; /* B-tree header */
H5B2_hdr_cache_ud_t *udata = (H5B2_hdr_cache_ud_t *)_udata;
H5B2_create_t cparam; /* B-tree creation parameters */
H5B2_subid_t id; /* ID of B-tree class, as found in file */
uint16_t depth; /* Depth of B-tree */
- H5WB_t *wb = NULL; /* Wrapped buffer for header data */
- uint8_t hdr_buf[H5B2_HDR_BUF_SIZE]; /* Buffer for header */
- uint8_t *buf; /* Pointer to header buffer */
- const uint8_t *p; /* Pointer into raw data buffer */
+ uint32_t stored_chksum; /* Stored metadata checksum value */
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
H5B2_hdr_t *ret_value; /* Return value */
FUNC_ENTER_STATIC
/* Check arguments */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
+ HDassert(image);
HDassert(udata);
/* Allocate new B-tree header and reset cache info */
if(NULL == (hdr = H5B2__hdr_alloc(udata->f)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTALLOC, NULL, "allocation failed for B-tree header")
- /* Wrap the local buffer for serialized header info */
- if(NULL == (wb = H5WB_wrap(hdr_buf, sizeof(hdr_buf))))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, NULL, "can't wrap buffer")
-
- /* Get a pointer to a buffer that's large enough for header */
- if(NULL == (buf = (uint8_t *)H5WB_actual(wb, hdr->hdr_size)))
- HGOTO_ERROR(H5E_BTREE, H5E_NOSPACE, NULL, "can't get actual buffer")
-
- /* Read and validate header from disk */
- if(H5F_read_check_metadata(f, dxpl_id, H5FD_MEM_BTREE, H5AC_BT2_HDR_ID, addr, hdr->hdr_size, hdr->hdr_size, buf) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_BADVALUE, NULL, "incorrect metadata checksum for v2 B-tree header")
-
- /* Get temporary pointer to serialized header */
- p = buf;
-
/* Magic number */
- if(HDmemcmp(p, H5B2_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC))
+ if(HDmemcmp(image, H5B2_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC))
HGOTO_ERROR(H5E_BTREE, H5E_BADVALUE, NULL, "wrong B-tree header signature")
- p += H5_SIZEOF_MAGIC;
+ image += H5_SIZEOF_MAGIC;
/* Version */
- if(*p++ != H5B2_HDR_VERSION)
+ if(*image++ != H5B2_HDR_VERSION)
HGOTO_ERROR(H5E_BTREE, H5E_BADRANGE, NULL, "wrong B-tree header version")
/* B-tree class */
- id = (H5B2_subid_t)*p++;
+ id = (H5B2_subid_t)*image++;
if(id >= H5B2_NUM_BTREE_ID)
HGOTO_ERROR(H5E_BTREE, H5E_BADTYPE, NULL, "incorrect B-tree type")
/* Node size (in bytes) */
- UINT32DECODE(p, cparam.node_size);
+ UINT32DECODE(image, cparam.node_size);
/* Raw key size (in bytes) */
- UINT16DECODE(p, cparam.rrec_size);
+ UINT16DECODE(image, cparam.rrec_size);
/* Depth of tree */
- UINT16DECODE(p, depth);
+ UINT16DECODE(image, depth);
/* Split & merge %s */
- cparam.split_percent = *p++;
- cparam.merge_percent = *p++;
+ cparam.split_percent = *image++;
+ cparam.merge_percent = *image++;
/* Root node pointer */
- H5F_addr_decode(udata->f, (const uint8_t **)&p, &(hdr->root.addr));
- UINT16DECODE(p, hdr->root.node_nrec);
- H5F_DECODE_LENGTH(udata->f, p, hdr->root.all_nrec);
+ H5F_addr_decode(udata->f, (const uint8_t **)&image, &(hdr->root.addr));
+ UINT16DECODE(image, hdr->root.node_nrec);
+ H5F_DECODE_LENGTH(udata->f, image, hdr->root.all_nrec);
+
+ /* checksum verification already done in verify_chksum cb */
- /* Already decoded and compared stored checksum earlier, when reading */
+ /* Metadata checksum */
+ UINT32DECODE(image, stored_chksum);
/* Sanity check */
- HDassert((size_t)(p - (const uint8_t *)buf) == (hdr->hdr_size - H5_SIZEOF_CHKSUM));
+ HDassert((size_t)(image - (const uint8_t *)_image) == hdr->hdr_size);
/* Initialize B-tree header info */
cparam.cls = H5B2_client_class_g[id];
@@ -235,152 +332,59 @@ H5B2__cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, NULL, "can't initialize B-tree header info")
/* Set the B-tree header's address */
- hdr->addr = addr;
+ hdr->addr = udata->addr;
+
+ /* Sanity check */
+ HDassert((size_t)(image - (const uint8_t *)_image) <= len);
/* Set return value */
ret_value = hdr;
done:
- /* Release resources */
- if(wb && H5WB_unwrap(wb) < 0)
- HDONE_ERROR(H5E_BTREE, H5E_CLOSEERROR, NULL, "can't close wrapped buffer")
if(!ret_value && hdr)
if(H5B2__hdr_free(hdr) < 0)
HDONE_ERROR(H5E_BTREE, H5E_CANTRELEASE, NULL, "can't release v2 B-tree header")
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5B2__cache_hdr_load() */ /*lint !e818 Can't make udata a pointer to const */
+} /* end H5B2__cache_hdr_deserialize() */
/*-------------------------------------------------------------------------
- * Function: H5B2__cache_hdr_flush
+ * Function: H5B2__cache_hdr_image_len
*
- * Purpose: Flushes a dirty B-tree header to disk.
+ * Purpose: Compute the size of the data structure on disk.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 1 2005
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * May 20, 2010
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5B2__cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr,
- H5B2_hdr_t *hdr, unsigned H5_ATTR_UNUSED * flags_ptr)
+H5B2__cache_hdr_image_len(const void *_thing, size_t *image_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr)
{
- H5WB_t *wb = NULL; /* Wrapped buffer for header data */
- uint8_t hdr_buf[H5B2_HDR_BUF_SIZE]; /* Buffer for header */
- herr_t ret_value = SUCCEED; /* Return value */
+ const H5B2_hdr_t *hdr = (const H5B2_hdr_t *)_thing; /* Pointer to the B-tree header */
- FUNC_ENTER_STATIC
+ FUNC_ENTER_STATIC_NOERR
/* Check arguments */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
HDassert(hdr);
+ HDassert(image_len);
- if(hdr->cache_info.is_dirty) {
- uint8_t *buf; /* Pointer to header buffer */
- uint8_t *p; /* Pointer into raw data buffer */
- uint32_t metadata_chksum; /* Computed metadata checksum value */
-
- /* Set the B-tree header's file context for this operation */
- hdr->f = f;
-
- /* Wrap the local buffer for serialized header info */
- if(NULL == (wb = H5WB_wrap(hdr_buf, sizeof(hdr_buf))))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "can't wrap buffer")
-
- /* Get a pointer to a buffer that's large enough for header */
- if(NULL == (buf = (uint8_t *)H5WB_actual(wb, hdr->hdr_size)))
- HGOTO_ERROR(H5E_BTREE, H5E_NOSPACE, FAIL, "can't get actual buffer")
-
- /* Get temporary pointer to serialized header */
- p = buf;
-
- /* Magic number */
- HDmemcpy(p, H5B2_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC);
- p += H5_SIZEOF_MAGIC;
-
- /* Version # */
- *p++ = H5B2_HDR_VERSION;
-
- /* B-tree type */
- *p++ = hdr->cls->id;
-
- /* Node size (in bytes) */
- UINT32ENCODE(p, hdr->node_size);
-
- /* Raw key size (in bytes) */
- UINT16ENCODE(p, hdr->rrec_size);
-
- /* Depth of tree */
- UINT16ENCODE(p, hdr->depth);
-
- /* Split & merge %s */
- H5_CHECK_OVERFLOW(hdr->split_percent, /* From: */ unsigned, /* To: */ uint8_t);
- *p++ = (uint8_t)hdr->split_percent;
- H5_CHECK_OVERFLOW(hdr->merge_percent, /* From: */ unsigned, /* To: */ uint8_t);
- *p++ = (uint8_t)hdr->merge_percent;
-
- /* Root node pointer */
- H5F_addr_encode(f, &p, hdr->root.addr);
- UINT16ENCODE(p, hdr->root.node_nrec);
- H5F_ENCODE_LENGTH(f, p, hdr->root.all_nrec);
-
- /* Compute metadata checksum */
- metadata_chksum = H5_checksum_metadata(buf, (hdr->hdr_size - H5B2_SIZEOF_CHKSUM), 0);
-
- /* Metadata checksum */
- UINT32ENCODE(p, metadata_chksum);
+ /* Set the image length size */
+ *image_len = hdr->hdr_size;
- /* Write the B-tree header. */
- HDassert((size_t)(p - buf) == hdr->hdr_size);
- if(H5F_block_write(f, H5FD_MEM_BTREE, addr, hdr->hdr_size, dxpl_id, buf) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTFLUSH, FAIL, "unable to save B-tree header to disk")
-
- hdr->cache_info.is_dirty = FALSE;
-
- /* Clear shadowed node lists, as the header has been flushed and all
- * nodes must be shadowed again (if doing SWMR writes). Note that this
- * algorithm does one extra iteration at the end, as the last node's
- * shadowed_next pointer points to itself. */
- while(hdr->shadowed_internal) {
- H5B2_internal_t *next = hdr->shadowed_internal->shadowed_next;
-
- HDassert(!hdr->shadowed_internal->cache_info.is_dirty);
- hdr->shadowed_internal->shadowed_next = NULL;
- hdr->shadowed_internal->shadowed_prev = NULL;
- hdr->shadowed_internal = next;
- } /* end while */
- while(hdr->shadowed_leaf) {
- H5B2_leaf_t *next = hdr->shadowed_leaf->shadowed_next;
-
- HDassert(!hdr->shadowed_leaf->cache_info.is_dirty);
- hdr->shadowed_leaf->shadowed_next = NULL;
- hdr->shadowed_leaf->shadowed_prev = NULL;
- hdr->shadowed_leaf = next;
- } /* end while */
- } /* end if */
-
- if(destroy)
- if(H5B2__cache_hdr_dest(f, hdr) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to destroy B-tree header")
-
-done:
- /* Release resources */
- if(wb && H5WB_unwrap(wb) < 0)
- HDONE_ERROR(H5E_BTREE, H5E_CLOSEERROR, FAIL, "can't close wrapped buffer")
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5B2__cache_hdr_flush() */
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5B2__cache_hdr_image_len() */
/*-------------------------------------------------------------------------
- * Function: H5B2__cache_hdr_dest
+ * Function: H5B2__cache_hdr_serialize
*
- * Purpose: Destroys a B-tree header in memory.
+ * Purpose: Flushes a dirty B-tree header to disk.
*
* Return: Non-negative on success/Negative on failure
*
@@ -391,71 +395,82 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5B2__cache_hdr_dest(H5F_t *f, H5B2_hdr_t *hdr)
+H5B2__cache_hdr_serialize(const H5F_t *f, void *_image, size_t H5_ATTR_UNUSED len,
+ void *_thing)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ H5B2_hdr_t *hdr = (H5B2_hdr_t *)_thing; /* Pointer to the B-tree header */
+ uint8_t *image = (uint8_t *)_image; /* Pointer into raw data buffer */
+ uint32_t metadata_chksum; /* Computed metadata checksum value */
- FUNC_ENTER_STATIC
+ FUNC_ENTER_STATIC_NOERR
- /* Check arguments */
+ /* check arguments */
+ HDassert(f);
+ HDassert(image);
HDassert(hdr);
- HDassert(hdr->rc == 0);
- /* If we're going to free the space on disk, the address must be valid */
- HDassert(!hdr->cache_info.free_file_space_on_destroy || H5F_addr_defined(hdr->cache_info.addr));
+ /* Magic number */
+ HDmemcpy(image, H5B2_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ image += H5_SIZEOF_MAGIC;
- /* Check for freeing file space for B-tree header */
- if(hdr->cache_info.free_file_space_on_destroy) {
- /* Release the space on disk */
- /* (XXX: Nasty usage of internal DXPL value! -QAK) */
- if(H5MF_xfree(f, H5FD_MEM_BTREE, H5AC_dxpl_id, hdr->cache_info.addr, (hsize_t)hdr->hdr_size) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free v2 B-tree header")
- } /* end if */
+ /* Version # */
+ *image++ = H5B2_HDR_VERSION;
- /* Release B-tree header info */
- if(H5B2__hdr_free(hdr) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free v2 B-tree header info")
+ /* B-tree type */
+ *image++ = hdr->cls->id;
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5B2__cache_hdr_dest() */
+ /* Node size (in bytes) */
+ UINT32ENCODE(image, hdr->node_size);
-
-/*-------------------------------------------------------------------------
- * Function: H5B2__cache_hdr_clear
- *
- * Purpose: Mark a B-tree header in memory as non-dirty.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 1 2005
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5B2__cache_hdr_clear(H5F_t *f, H5B2_hdr_t *hdr, hbool_t destroy)
-{
- herr_t ret_value = SUCCEED; /* Return value */
+ /* Raw key size (in bytes) */
+ UINT16ENCODE(image, hdr->rrec_size);
- FUNC_ENTER_STATIC
+ /* Depth of tree */
+ UINT16ENCODE(image, hdr->depth);
- /*
- * Check arguments.
- */
- HDassert(hdr);
+ /* Split & merge %s */
+ H5_CHECK_OVERFLOW(hdr->split_percent, /* From: */ unsigned, /* To: */ uint8_t);
+ *image++ = (uint8_t)hdr->split_percent;
+ H5_CHECK_OVERFLOW(hdr->merge_percent, /* From: */ unsigned, /* To: */ uint8_t);
+ *image++ = (uint8_t)hdr->merge_percent;
- /* Reset the dirty flag. */
- hdr->cache_info.is_dirty = FALSE;
+ /* Root node pointer */
+ H5F_addr_encode(f, &image, hdr->root.addr);
+ UINT16ENCODE(image, hdr->root.node_nrec);
+ H5F_ENCODE_LENGTH(f, image, hdr->root.all_nrec);
- if(destroy)
- if(H5B2__cache_hdr_dest(f, hdr) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to destroy B-tree header")
+ /* Compute metadata checksum */
+ metadata_chksum = H5_checksum_metadata(_image, (hdr->hdr_size - H5B2_SIZEOF_CHKSUM), 0);
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5B2__cache_hdr_clear() */
+ /* Metadata checksum */
+ UINT32ENCODE(image, metadata_chksum);
+
+ /* Sanity check */
+ HDassert((size_t)(image - (uint8_t *)_image) <= len);
+
+ /* Clear shadowed node lists, as the header has been flushed and all
+ * nodes must be shadowed again (if doing SWMR writes). Note that this
+ * algorithm does one extra iteration at the end, as the last node's
+ * shadowed_next pointer points to itself. */
+ while(hdr->shadowed_internal) {
+ H5B2_internal_t *next = hdr->shadowed_internal->shadowed_next;
+
+ HDassert(!hdr->shadowed_internal->cache_info.is_dirty);
+ hdr->shadowed_internal->shadowed_next = NULL;
+ hdr->shadowed_internal->shadowed_prev = NULL;
+ hdr->shadowed_internal = next;
+ } /* end while */
+ while(hdr->shadowed_leaf) {
+ H5B2_leaf_t *next = hdr->shadowed_leaf->shadowed_next;
+
+ HDassert(!hdr->shadowed_leaf->cache_info.is_dirty);
+ hdr->shadowed_leaf->shadowed_next = NULL;
+ hdr->shadowed_leaf->shadowed_prev = NULL;
+ hdr->shadowed_leaf = next;
+ } /* end while */
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5B2__cache_hdr_serialize() */
/*-------------------------------------------------------------------------
@@ -472,9 +487,10 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5B2__cache_hdr_notify(H5AC_notify_action_t action, H5B2_hdr_t *hdr)
+H5B2__cache_hdr_notify(H5AC_notify_action_t action, void *_thing)
{
- herr_t ret_value = SUCCEED;
+ H5B2_hdr_t *hdr = (H5B2_hdr_t *)_thing;
+ herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
@@ -488,14 +504,21 @@ H5B2__cache_hdr_notify(H5AC_notify_action_t action, H5B2_hdr_t *hdr)
HDassert(hdr->parent);
switch(action) {
case H5AC_NOTIFY_ACTION_AFTER_INSERT:
+ case H5AC_NOTIFY_ACTION_AFTER_LOAD:
/* Create flush dependency on parent */
if(H5B2__create_flush_depend((H5AC_info_t *)hdr->parent, (H5AC_info_t *)hdr) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTDEPEND, FAIL, "unable to create flush dependency")
break;
+ case H5AC_NOTIFY_ACTION_AFTER_FLUSH:
+ /* do nothing */
+ break;
+
case H5AC_NOTIFY_ACTION_BEFORE_EVICT:
- /* Nothing to do */
- break;
+ /* Destroy flush dependency on parent */
+ if(H5B2__destroy_flush_depend((H5AC_info_t *)hdr->parent, (H5AC_info_t *)hdr) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNDEPEND, FAIL, "unable to destroy flush dependency")
+ break;
default:
#ifdef NDEBUG
@@ -512,41 +535,122 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5B2__cache_hdr_size
+ * Function: H5B2__cache_hdr_free_icr
+ *
+ * Purpose: Destroy/release an "in core representation" of a data
+ * structure
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Mike McGreevy
+ * mcgreevy@hdfgroup.org
+ * June 18, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5B2__cache_hdr_free_icr(void *thing)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check arguments */
+ HDassert(thing);
+
+ /* Destroy v2 B-tree header */
+ if(H5B2__hdr_free((H5B2_hdr_t *)thing) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free v2 B-tree header")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5B2__cache_hdr_free_icr() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B2__cache_int_get_load_size
*
- * Purpose: Compute the size in bytes of a B-tree header
- * on disk, and return it in *size_ptr. On failure,
- * the value of *size_ptr is undefined.
+ * Purpose: Compute the size of the data structure on disk.
*
- * Return: SUCCEED (Can't fail)
+ * Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
* koziol@hdfgroup.org
- * Feb 1 2005
+ * May 18, 2010
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5B2__cache_hdr_size(const H5F_t H5_ATTR_UNUSED *f, const H5B2_hdr_t *hdr, size_t *size_ptr)
+H5B2__cache_int_get_load_size(const void *_image, void *_udata, size_t *image_len, size_t *actual_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr)
{
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ H5B2_internal_cache_ud_t *udata = (H5B2_internal_cache_ud_t *)_udata; /* User data for callback */
+
+ FUNC_ENTER_STATIC_NOERR
/* Check arguments */
- HDassert(f);
- HDassert(hdr);
- HDassert(size_ptr);
+ HDassert(udata);
+ HDassert(udata->hdr);
+ HDassert(image_len);
- /* Set size value */
- *size_ptr = hdr->hdr_size;
+ if(image == NULL) {
+ /* Set the image length size */
+ *image_len = udata->hdr->node_size;
+ } else {
+ HDassert(actual_len);
+ HDassert(*actual_len == *image_len);
+ }
FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5B2__cache_hdr_size() */
+} /* end H5B2__cache_int_get_load_size() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5B2__cache_int_verify_chksum
+ *
+ * Purpose: Verify the computed checksum of the data structure is the
+ * same as the stored chksum.
+ *
+ * Return: Success: TRUE/FALSE
+ * Failure: Negative
+ *
+ * Programmer: Vailin Choi; Aug 2015
+ *
+ *-------------------------------------------------------------------------
+ */
+static htri_t
+H5B2__cache_int_verify_chksum(const void *_image, size_t H5_ATTR_UNUSED len, void *_udata)
+{
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ H5B2_internal_cache_ud_t *udata = (H5B2_internal_cache_ud_t *)_udata; /* Pointer to user data */
+ size_t chk_size; /* Exact size of the node with checksum at the end */
+ uint32_t stored_chksum; /* Stored metadata checksum value */
+ uint32_t computed_chksum; /* Computed metadata checksum value */
+ htri_t ret_value = TRUE; /* Return value */
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Check arguments */
+ HDassert(image);
+ HDassert(udata);
+
+ /* Internal node prefix header + records + child pointer triplets: size with checksum at the end */
+ chk_size = H5B2_INT_PREFIX_SIZE + (udata->nrec * udata->hdr->rrec_size) + ((size_t)(udata->nrec + 1) * H5B2_INT_POINTER_SIZE(udata->hdr, udata->depth));
+
+ /* Get stored and computed checksums */
+ H5F_get_checksums(image, chk_size, &stored_chksum, &computed_chksum);
+
+ if(stored_chksum != computed_chksum)
+ ret_value = FALSE;
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5B2__cache_int_verify_chksum() */
/*-------------------------------------------------------------------------
- * Function: H5B2__cache_internal_load
+ * Function: H5B2__cache_int_deserialize
*
- * Purpose: Loads a B-tree internal node from the disk.
+ * Purpose: Deserialize a B-tree internal node from the disk.
*
* Return: Success: Pointer to a new B-tree internal node.
* Failure: NULL
@@ -557,23 +661,23 @@ H5B2__cache_hdr_size(const H5F_t H5_ATTR_UNUSED *f, const H5B2_hdr_t *hdr, size_
*
*-------------------------------------------------------------------------
*/
-static H5B2_internal_t *
-H5B2__cache_internal_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
+static void *
+H5B2__cache_int_deserialize(const void *_image, size_t H5_ATTR_UNUSED len,
+ void *_udata, hbool_t H5_ATTR_UNUSED *dirty)
{
H5B2_internal_cache_ud_t *udata = (H5B2_internal_cache_ud_t *)_udata; /* Pointer to user data */
H5B2_internal_t *internal = NULL; /* Internal node read */
- const uint8_t *p; /* Pointer into raw data buffer */
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
uint8_t *native; /* Pointer to native record info */
H5B2_node_ptr_t *int_node_ptr; /* Pointer to node pointer info */
+ uint32_t stored_chksum; /* Stored metadata checksum value */
unsigned u; /* Local index variable */
- size_t chk_size; /* Exact size of the node with checksum at the end */
H5B2_internal_t *ret_value; /* Return value */
FUNC_ENTER_STATIC
/* Check arguments */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
+ HDassert(image);
HDassert(udata);
/* Allocate new internal node and reset cache info */
@@ -581,9 +685,6 @@ H5B2__cache_internal_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
HDmemset(&internal->cache_info, 0, sizeof(H5AC_info_t));
- /* Set the B-tree header's file context for this operation */
- udata->hdr->f = f;
-
/* Increment ref. count on B-tree header */
if(H5B2__hdr_incr(udata->hdr) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTINC, NULL, "can't increment ref. count on B-tree header")
@@ -594,25 +695,17 @@ H5B2__cache_internal_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
internal->shadowed_next = NULL;
internal->shadowed_prev = NULL;
- /* Internal node prefix header + records + child pointer triplets: size with checksum at the end */
- chk_size = H5B2_INT_PREFIX_SIZE + (udata->nrec * udata->hdr->rrec_size) + ((size_t)(udata->nrec + 1) * H5B2_INT_POINTER_SIZE(udata->hdr, udata->depth));
- /* Read and validate internal node from disk */
- if(H5F_read_check_metadata(f, dxpl_id, H5FD_MEM_BTREE, H5AC_BT2_INT_ID, addr, (size_t)udata->hdr->node_size, chk_size, udata->hdr->page) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_BADVALUE, NULL, "incorrect metadata checksum for v2 internal node")
-
- p = udata->hdr->page;
-
/* Magic number */
- if(HDmemcmp(p, H5B2_INT_MAGIC, (size_t)H5_SIZEOF_MAGIC))
+ if(HDmemcmp(image, H5B2_INT_MAGIC, (size_t)H5_SIZEOF_MAGIC))
HGOTO_ERROR(H5E_BTREE, H5E_BADVALUE, NULL, "wrong B-tree internal node signature")
- p += H5_SIZEOF_MAGIC;
+ image += H5_SIZEOF_MAGIC;
/* Version */
- if(*p++ != H5B2_INT_VERSION)
+ if(*image++ != H5B2_INT_VERSION)
HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, NULL, "wrong B-tree internal node version")
/* B-tree type */
- if(*p++ != (uint8_t)udata->hdr->cls->id)
+ if(*image++ != (uint8_t)udata->hdr->cls->id)
HGOTO_ERROR(H5E_BTREE, H5E_BADTYPE, NULL, "incorrect B-tree type")
/* Allocate space for the native keys in memory */
@@ -631,11 +724,11 @@ H5B2__cache_internal_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
native = internal->int_native;
for(u = 0; u < internal->nrec; u++) {
/* Decode record */
- if((udata->hdr->cls->decode)(p, native, udata->hdr->cb_ctx) < 0)
+ if((udata->hdr->cls->decode)(image, native, udata->hdr->cb_ctx) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTDECODE, NULL, "unable to decode B-tree record")
/* Move to next record */
- p += udata->hdr->rrec_size;
+ image += udata->hdr->rrec_size;
native += udata->hdr->cls->nrec_size;
} /* end for */
@@ -643,10 +736,10 @@ H5B2__cache_internal_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
int_node_ptr = internal->node_ptrs;
for(u = 0; u < (unsigned)(internal->nrec + 1); u++) {
/* Decode node pointer */
- H5F_addr_decode(udata->f, (const uint8_t **)&p, &(int_node_ptr->addr));
- UINT64DECODE_VAR(p, int_node_ptr->node_nrec, udata->hdr->max_nrec_size);
+ H5F_addr_decode(udata->f, (const uint8_t **)&image, &(int_node_ptr->addr));
+ UINT64DECODE_VAR(image, int_node_ptr->node_nrec, udata->hdr->max_nrec_size);
if(udata->depth > 1)
- UINT64DECODE_VAR(p, int_node_ptr->all_nrec, udata->hdr->node_info[udata->depth - 1].cum_max_nrec_size)
+ UINT64DECODE_VAR(image, int_node_ptr->all_nrec, udata->hdr->node_info[udata->depth - 1].cum_max_nrec_size)
else
int_node_ptr->all_nrec = int_node_ptr->node_nrec;
@@ -654,10 +747,13 @@ H5B2__cache_internal_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
int_node_ptr++;
} /* end for */
- /* Already decoded and compared stored checksum earlier, when reading */
+ /* checksum verification already done in verify_chksum cb */
+
+ /* Metadata checksum */
+ UINT32DECODE(image, stored_chksum);
/* Sanity check parsing */
- HDassert((size_t)(p - (const uint8_t *)udata->hdr->page) <= (udata->hdr->node_size - H5_SIZEOF_CHKSUM));
+ HDassert((size_t)(image - (const uint8_t *)_image) <= len);
/* Set return value */
ret_value = internal;
@@ -668,214 +764,127 @@ done:
HDONE_ERROR(H5E_BTREE, H5E_CANTFREE, NULL, "unable to destroy B-tree internal node")
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5B2__cache_internal_load() */ /*lint !e818 Can't make udata a pointer to const */
+} /* H5B2__cache_int_deserialize() */
/*-------------------------------------------------------------------------
- * Function: H5B2__cache_internal_flush
+ * Function: H5B2__cache_int_image_len
*
- * Purpose: Flushes a dirty B-tree internal node to disk.
+ * Purpose: Compute the size of the data structure on disk.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 3 2005
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * May 20, 2010
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5B2__cache_internal_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5B2_internal_t *internal, unsigned H5_ATTR_UNUSED * flags_ptr)
+H5B2__cache_int_image_len(const void *_thing, size_t *image_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ const H5B2_internal_t *internal = (const H5B2_internal_t *)_thing; /* Pointer to the B-tree internal node */
- FUNC_ENTER_STATIC
+ FUNC_ENTER_STATIC_NOERR
/* Check arguments */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
HDassert(internal);
HDassert(internal->hdr);
+ HDassert(image_len);
- if(internal->cache_info.is_dirty) {
- uint8_t *p; /* Pointer into raw data buffer */
- uint8_t *native; /* Pointer to native record info */
- H5B2_node_ptr_t *int_node_ptr; /* Pointer to node pointer info */
- uint32_t metadata_chksum; /* Computed metadata checksum value */
- unsigned u; /* Local index variable */
-
- /* Set the B-tree header's file context for this operation */
- internal->hdr->f = f;
-
- p = internal->hdr->page;
-
- /* Magic number */
- HDmemcpy(p, H5B2_INT_MAGIC, (size_t)H5_SIZEOF_MAGIC);
- p += H5_SIZEOF_MAGIC;
-
- /* Version # */
- *p++ = H5B2_INT_VERSION;
-
- /* B-tree type */
- *p++ = internal->hdr->cls->id;
- HDassert((size_t)(p - internal->hdr->page) == (H5B2_INT_PREFIX_SIZE - H5B2_SIZEOF_CHKSUM));
-
- /* Serialize records for internal node */
- native = internal->int_native;
- for(u = 0; u < internal->nrec; u++) {
- /* Encode record */
- if((internal->hdr->cls->encode)(p, native, internal->hdr->cb_ctx) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTENCODE, FAIL, "unable to encode B-tree record")
-
- /* Move to next record */
- p += internal->hdr->rrec_size;
- native += internal->hdr->cls->nrec_size;
- } /* end for */
-
- /* Serialize node pointers for internal node */
- int_node_ptr = internal->node_ptrs;
- for(u = 0; u < (unsigned)(internal->nrec + 1); u++) {
- /* Encode node pointer */
- H5F_addr_encode(f, &p, int_node_ptr->addr);
- UINT64ENCODE_VAR(p, int_node_ptr->node_nrec, internal->hdr->max_nrec_size);
- if(internal->depth > 1)
- UINT64ENCODE_VAR(p, int_node_ptr->all_nrec, internal->hdr->node_info[internal->depth - 1].cum_max_nrec_size);
-
- /* Move to next node pointer */
- int_node_ptr++;
- } /* end for */
-
- /* Compute metadata checksum */
- metadata_chksum = H5_checksum_metadata(internal->hdr->page, (size_t)(p - internal->hdr->page), 0);
-
- /* Metadata checksum */
- UINT32ENCODE(p, metadata_chksum);
-
- /* Write the B-tree internal node */
- HDassert((size_t)(p - internal->hdr->page) <= internal->hdr->node_size);
- if(H5F_block_write(f, H5FD_MEM_BTREE, addr, (size_t)internal->hdr->node_size, dxpl_id, internal->hdr->page) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTFLUSH, FAIL, "unable to save B-tree internal node to disk")
-
- internal->cache_info.is_dirty = FALSE;
- } /* end if */
-
- if(destroy)
- if(H5B2__cache_internal_dest(f, internal) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to destroy B-tree internal node")
+ /* Set the image length size */
+ *image_len = internal->hdr->node_size;
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5B2__cache_internal_flush() */
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5B2__cache_int_image_len() */
/*-------------------------------------------------------------------------
- * Function: H5B2__cache_internal_dest
+ * Function: H5B2__cache_int_serialize
*
- * Purpose: Destroys a B-tree internal node in memory.
+ * Purpose: Serializes a B-tree internal node for writing to disk.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
- * Feb 2 2005
+ * Feb 3 2005
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5B2__cache_internal_dest(H5F_t *f, H5B2_internal_t *internal)
+H5B2__cache_int_serialize(const H5F_t *f, void *_image, size_t H5_ATTR_UNUSED len,
+ void *_thing)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ H5B2_internal_t *internal = (H5B2_internal_t *)_thing; /* Pointer to the B-tree internal node */
+ uint8_t *image = (uint8_t *)_image; /* Pointer into raw data buffer */
+ uint8_t *native; /* Pointer to native record info */
+ H5B2_node_ptr_t *int_node_ptr; /* Pointer to node pointer info */
+ uint32_t metadata_chksum; /* Computed metadata checksum value */
+ unsigned u; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_STATIC
- /* Check arguments */
+ /* check arguments */
HDassert(f);
+ HDassert(image);
HDassert(internal);
HDassert(internal->hdr);
- /* If we're going to free the space on disk, the address must be valid */
- HDassert(!internal->cache_info.free_file_space_on_destroy || H5F_addr_defined(internal->cache_info.addr));
-
- /* Unlink from shadowed list */
- if(internal->shadowed_next) {
- if(internal->shadowed_next != internal) {
- internal->shadowed_next->shadowed_prev = internal->shadowed_prev;
-
- if(internal->shadowed_prev)
- internal->shadowed_prev->shadowed_next = internal->shadowed_next;
- else {
- HDassert(internal->hdr->shadowed_internal = internal);
-
- internal->hdr->shadowed_internal = internal->shadowed_next;
- } /* end else */
- } /* end if */
- else {
- if(internal->shadowed_prev)
- internal->shadowed_prev->shadowed_next = internal->shadowed_prev;
- else {
- HDassert(internal->hdr->shadowed_internal = internal);
+ /* Magic number */
+ HDmemcpy(image, H5B2_INT_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ image += H5_SIZEOF_MAGIC;
- internal->hdr->shadowed_internal = NULL;
- } /* end else */
- } /* end else */
- } /* end if */
+ /* Version # */
+ *image++ = H5B2_INT_VERSION;
- /* Check for freeing file space for B-tree internal node */
- if(internal->cache_info.free_file_space_on_destroy) {
- /* Release the space on disk */
- /* (XXX: Nasty usage of internal DXPL value! -QAK) */
- if(H5MF_xfree(f, H5FD_MEM_BTREE, H5AC_dxpl_id, internal->cache_info.addr, (hsize_t)internal->hdr->node_size) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free v2 B-tree internal node")
- } /* end if */
+ /* B-tree type */
+ *image++ = internal->hdr->cls->id;
+ HDassert((size_t)(image - (uint8_t *)_image) == (H5B2_INT_PREFIX_SIZE - H5B2_SIZEOF_CHKSUM));
- /* Release v2 b-tree internal node */
- if(H5B2__internal_free(internal) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to release v2 B-tree internal node")
+ /* Serialize records for internal node */
+ native = internal->int_native;
+ for(u = 0; u < internal->nrec; u++) {
+ /* Encode record */
+ if((internal->hdr->cls->encode)(image, native, internal->hdr->cb_ctx) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTENCODE, FAIL, "unable to encode B-tree record")
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5B2__cache_internal_dest() */
+ /* Move to next record */
+ image += internal->hdr->rrec_size;
+ native += internal->hdr->cls->nrec_size;
+ } /* end for */
-
-/*-------------------------------------------------------------------------
- * Function: H5B2__cache_internal_clear
- *
- * Purpose: Mark a B-tree internal node in memory as non-dirty.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 2 2005
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5B2__cache_internal_clear(H5F_t *f, H5B2_internal_t *internal, hbool_t destroy)
-{
- herr_t ret_value = SUCCEED;
+ /* Serialize node pointers for internal node */
+ int_node_ptr = internal->node_ptrs;
+ for(u = 0; u < (unsigned)(internal->nrec + 1); u++) {
+ /* Encode node pointer */
+ H5F_addr_encode(f, &image, int_node_ptr->addr);
+ UINT64ENCODE_VAR(image, int_node_ptr->node_nrec, internal->hdr->max_nrec_size);
+ if(internal->depth > 1)
+ UINT64ENCODE_VAR(image, int_node_ptr->all_nrec, internal->hdr->node_info[internal->depth - 1].cum_max_nrec_size);
- FUNC_ENTER_STATIC
+ /* Move to next node pointer */
+ int_node_ptr++;
+ } /* end for */
- /*
- * Check arguments.
- */
- HDassert(internal);
+ /* Compute metadata checksum */
+ metadata_chksum = H5_checksum_metadata(_image, (size_t)(image - (uint8_t *)_image), 0);
- /* Reset the dirty flag. */
- internal->cache_info.is_dirty = FALSE;
+ /* Metadata checksum */
+ UINT32ENCODE(image, metadata_chksum);
- if(destroy)
- if(H5B2__cache_internal_dest(f, internal) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to destroy B-tree internal node")
+ /* Sanity check */
+ HDassert((size_t)(image - (uint8_t *)_image) <= len);
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5B2__cache_internal_clear() */
+} /* H5B2__cache_int_serialize() */
/*-------------------------------------------------------------------------
- * Function: H5B2__cache_internal_notify
+ * Function: H5B2__cache_int_notify
*
* Purpose: Handle cache action notifications
*
@@ -888,9 +897,10 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5B2__cache_internal_notify(H5AC_notify_action_t action, H5B2_internal_t *internal)
+H5B2__cache_int_notify(H5AC_notify_action_t action, void *_thing)
{
- herr_t ret_value = SUCCEED;
+ H5B2_internal_t *internal = (H5B2_internal_t *)_thing;
+ herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI_NOINIT
@@ -904,13 +914,21 @@ H5B2__cache_internal_notify(H5AC_notify_action_t action, H5B2_internal_t *intern
HDassert(internal->parent);
switch(action) {
case H5AC_NOTIFY_ACTION_AFTER_INSERT:
+ case H5AC_NOTIFY_ACTION_AFTER_LOAD:
/* Create flush dependency on parent */
if(H5B2__create_flush_depend((H5AC_info_t *)internal->parent, (H5AC_info_t *)internal) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTDEPEND, FAIL, "unable to create flush dependency")
break;
+ case H5AC_NOTIFY_ACTION_AFTER_FLUSH:
+ /* do nothing */
+ break;
+
case H5AC_NOTIFY_ACTION_BEFORE_EVICT:
- /* Nothing to do */
+ /* Destroy flush dependency on parent */
+ if(H5B2__destroy_flush_depend((H5AC_info_t *)internal->parent, (H5AC_info_t *)internal) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNDEPEND, FAIL, "unable to destroy flush dependency")
+
break;
default:
@@ -924,45 +942,153 @@ H5B2__cache_internal_notify(H5AC_notify_action_t action, H5B2_internal_t *intern
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5B2__cache_internal_notify() */
+} /* end H5B2__cache_int_notify() */
/*-------------------------------------------------------------------------
- * Function: H5B2__cache_internal_size
+ * Function: H5B2__cache_int_free_icr
*
- * Purpose: Compute the size in bytes of a B-tree internal node
- * on disk, and return it in *size_ptr. On failure,
- * the value of *size_ptr is undefined.
+ * Purpose: Destroy/release an "in core representation" of a data
+ * structure
*
* Return: Non-negative on success/Negative on failure
*
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 2 2005
+ * Programmer: Mike McGreevy
+ * mcgreevy@hdfgroup.org
+ * June 18, 2008
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5B2__cache_internal_size(const H5F_t H5_ATTR_UNUSED *f, const H5B2_internal_t *internal, size_t *size_ptr)
+H5B2__cache_int_free_icr(void *_thing)
{
- FUNC_ENTER_STATIC_NOERR
+ H5B2_internal_t *internal = (H5B2_internal_t *)_thing;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
/* Check arguments */
HDassert(internal);
HDassert(internal->hdr);
- HDassert(size_ptr);
- /* Set size value */
- *size_ptr = internal->hdr->node_size;
+ /* Unlink from shadowed list */
+ if(internal->shadowed_next) {
+ if(internal->shadowed_next != internal) {
+ internal->shadowed_next->shadowed_prev = internal->shadowed_prev;
+
+ if(internal->shadowed_prev)
+ internal->shadowed_prev->shadowed_next = internal->shadowed_next;
+ else {
+ HDassert(internal->hdr->shadowed_internal = internal);
+
+ internal->hdr->shadowed_internal = internal->shadowed_next;
+ } /* end else */
+ } /* end if */
+ else {
+ if(internal->shadowed_prev)
+ internal->shadowed_prev->shadowed_next = internal->shadowed_prev;
+ else {
+ HDassert(internal->hdr->shadowed_internal = internal);
+
+ internal->hdr->shadowed_internal = NULL;
+ } /* end else */
+ } /* end else */
+ } /* end if */
+
+ /* Release v2 B-tree internal node */
+ if(H5B2__internal_free(internal) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to release v2 B-tree internal node")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5B2__cache_int_free_icr() */
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B2__cache_leaf_get_load_size
+ *
+ * Purpose: Compute the size of the data structure on disk.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * May 18, 2010
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5B2__cache_leaf_get_load_size(const void *_image, void *_udata, size_t *image_len, size_t *actual_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr)
+{
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ H5B2_leaf_cache_ud_t *udata = (H5B2_leaf_cache_ud_t *)_udata; /* User data for callback */
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Check arguments */
+ HDassert(udata);
+ HDassert(udata->hdr);
+ HDassert(image_len);
+
+ if(image == NULL) {
+ /* Set the image length size */
+ *image_len = udata->hdr->node_size;
+ } else {
+ HDassert(actual_len);
+ HDassert(*actual_len == *image_len);
+ }
FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5B2__cache_internal_size() */
+} /* end H5B2__cache_leaf_get_load_size() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5B2__cache_leaf_verify_chksum
+ *
+ * Purpose: Verify the computed checksum of the data structure is the
+ * same as the stored chksum.
+ *
+ * Return: Success: TRUE/FALSE
+ * Failure: Negative
+ *
+ * Programmer: Vailin Choi; Aug 2015
+ *
+ *-------------------------------------------------------------------------
+ */
+static htri_t
+H5B2__cache_leaf_verify_chksum(const void *_image, size_t H5_ATTR_UNUSED len, void *_udata)
+{
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ H5B2_internal_cache_ud_t *udata = (H5B2_internal_cache_ud_t *)_udata; /* Pointer to user data */
+ size_t chk_size; /* Exact size of the node with checksum at the end */
+ uint32_t stored_chksum; /* Stored metadata checksum value */
+ uint32_t computed_chksum; /* Computed metadata checksum value */
+ htri_t ret_value = TRUE; /* Return value */
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Check arguments */
+ HDassert(image);
+ HDassert(udata);
+
+ /* Leaf node prefix header + records: size with checksum at the end */
+ chk_size = H5B2_LEAF_PREFIX_SIZE + (udata->nrec * udata->hdr->rrec_size);
+
+ /* Get stored and computed checksums */
+ H5F_get_checksums(image, chk_size, &stored_chksum, &computed_chksum);
+
+ if(stored_chksum != computed_chksum)
+ ret_value = FALSE;
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5B2__cache_leaf_verify_chksum() */
/*-------------------------------------------------------------------------
- * Function: H5B2__cache_leaf_load
+ * Function: H5B2__cache_leaf_deserialize
*
- * Purpose: Loads a B-tree leaf from the disk.
+ * Purpose: Deserialize a B-tree leaf from the disk.
*
* Return: Success: Pointer to a new B-tree leaf node.
* Failure: NULL
@@ -973,22 +1099,22 @@ H5B2__cache_internal_size(const H5F_t H5_ATTR_UNUSED *f, const H5B2_internal_t *
*
*-------------------------------------------------------------------------
*/
-static H5B2_leaf_t *
-H5B2__cache_leaf_load(H5F_t H5_ATTR_UNUSED *f, hid_t dxpl_id, haddr_t addr, void *_udata)
+static void *
+H5B2__cache_leaf_deserialize(const void *_image, size_t H5_ATTR_UNUSED len,
+ void *_udata, hbool_t H5_ATTR_UNUSED *dirty)
{
H5B2_leaf_cache_ud_t *udata = (H5B2_leaf_cache_ud_t *)_udata;
H5B2_leaf_t *leaf = NULL; /* Pointer to lead node loaded */
- const uint8_t *p; /* Pointer into raw data buffer */
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
uint8_t *native; /* Pointer to native keys */
+ uint32_t stored_chksum; /* Stored metadata checksum value */
unsigned u; /* Local index variable */
- size_t chk_size; /* Exact size of the node with checksum at the end */
H5B2_leaf_t *ret_value; /* Return value */
FUNC_ENTER_STATIC
/* Check arguments */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
+ HDassert(image);
HDassert(udata);
/* Allocate new leaf node and reset cache info */
@@ -996,9 +1122,6 @@ H5B2__cache_leaf_load(H5F_t H5_ATTR_UNUSED *f, hid_t dxpl_id, haddr_t addr, void
HGOTO_ERROR(H5E_BTREE, H5E_CANTALLOC, NULL, "memory allocation failed")
HDmemset(&leaf->cache_info, 0, sizeof(H5AC_info_t));
- /* Set the B-tree header's file context for this operation */
- udata->hdr->f = udata->f;
-
/* Increment ref. count on B-tree header */
if(H5B2__hdr_incr(udata->hdr) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTINC, NULL, "can't increment ref. count on B-tree header")
@@ -1009,26 +1132,17 @@ H5B2__cache_leaf_load(H5F_t H5_ATTR_UNUSED *f, hid_t dxpl_id, haddr_t addr, void
leaf->shadowed_next = NULL;
leaf->shadowed_prev = NULL;
- /* Leaf node prefix header + records: size with checksum at the end */
- chk_size = H5B2_LEAF_PREFIX_SIZE + (udata->nrec * udata->hdr->rrec_size);
-
- /* Read and validate leaf node from disk */
- if(H5F_read_check_metadata(f, dxpl_id, H5FD_MEM_BTREE, H5AC_BT2_LEAF_ID, addr, (size_t)udata->hdr->node_size, chk_size, udata->hdr->page) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_BADVALUE, NULL, "incorrect metadata checksum for v2 leaf node")
-
- p = udata->hdr->page;
-
/* Magic number */
- if(HDmemcmp(p, H5B2_LEAF_MAGIC, (size_t)H5_SIZEOF_MAGIC))
+ if(HDmemcmp(image, H5B2_LEAF_MAGIC, (size_t)H5_SIZEOF_MAGIC))
HGOTO_ERROR(H5E_BTREE, H5E_BADVALUE, NULL, "wrong B-tree leaf node signature")
- p += H5_SIZEOF_MAGIC;
+ image += H5_SIZEOF_MAGIC;
/* Version */
- if(*p++ != H5B2_LEAF_VERSION)
+ if(*image++ != H5B2_LEAF_VERSION)
HGOTO_ERROR(H5E_BTREE, H5E_BADRANGE, NULL, "wrong B-tree leaf node version")
/* B-tree type */
- if(*p++ != (uint8_t)udata->hdr->cls->id)
+ if(*image++ != (uint8_t)udata->hdr->cls->id)
HGOTO_ERROR(H5E_BTREE, H5E_BADTYPE, NULL, "incorrect B-tree type")
/* Allocate space for the native keys in memory */
@@ -1042,18 +1156,24 @@ H5B2__cache_leaf_load(H5F_t H5_ATTR_UNUSED *f, hid_t dxpl_id, haddr_t addr, void
native = leaf->leaf_native;
for(u = 0; u < leaf->nrec; u++) {
/* Decode record */
- if((udata->hdr->cls->decode)(p, native, udata->hdr->cb_ctx) < 0)
+ if((udata->hdr->cls->decode)(image, native, udata->hdr->cb_ctx) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTENCODE, NULL, "unable to decode B-tree record")
/* Move to next record */
- p += udata->hdr->rrec_size;
+ image += udata->hdr->rrec_size;
native += udata->hdr->cls->nrec_size;
} /* end for */
- /* Already decoded and compared stored checksum earlier, when reading */
+ /* checksum verification already done in verify_chksum cb */
+
+ /* Metadata checksum */
+ UINT32DECODE(image, stored_chksum);
/* Sanity check parsing */
- HDassert((size_t)(p - (const uint8_t *)udata->hdr->page) <= (udata->hdr->node_size - H5_SIZEOF_CHKSUM));
+ HDassert((size_t)(image - (const uint8_t *)_image) <= udata->hdr->node_size);
+
+ /* Sanity check */
+ HDassert((size_t)(image - (const uint8_t *)_image) <= len);
/* Set return value */
ret_value = leaf;
@@ -1064,96 +1184,46 @@ done:
HDONE_ERROR(H5E_BTREE, H5E_CANTFREE, NULL, "unable to destroy B-tree leaf node")
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5B2__cache_leaf_load() */ /*lint !e818 Can't make udata a pointer to const */
+} /* H5B2__cache_leaf_deserialize() */
/*-------------------------------------------------------------------------
- * Function: H5B2__cache_leaf_flush
+ * Function: H5B2__cache_leaf_image_len
*
- * Purpose: Flushes a dirty B-tree leaf node to disk.
+ * Purpose: Compute the size of the data structure on disk.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 2 2005
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * May 20, 2010
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5B2__cache_leaf_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5B2_leaf_t *leaf, unsigned H5_ATTR_UNUSED * flags_ptr)
+H5B2__cache_leaf_image_len(const void *_thing, size_t *image_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ const H5B2_leaf_t *leaf = (const H5B2_leaf_t *)_thing; /* Pointer to the B-tree leaf node */
- FUNC_ENTER_STATIC
+ FUNC_ENTER_STATIC_NOERR
/* Check arguments */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
HDassert(leaf);
HDassert(leaf->hdr);
+ HDassert(image_len);
- if(leaf->cache_info.is_dirty) {
- uint8_t *p; /* Pointer into raw data buffer */
- uint8_t *native; /* Pointer to native keys */
- uint32_t metadata_chksum; /* Computed metadata checksum value */
- unsigned u; /* Local index variable */
-
- /* Set the B-tree header's file context for this operation */
- leaf->hdr->f = f;
-
- p = leaf->hdr->page;
-
- /* magic number */
- HDmemcpy(p, H5B2_LEAF_MAGIC, (size_t)H5_SIZEOF_MAGIC);
- p += H5_SIZEOF_MAGIC;
-
- /* version # */
- *p++ = H5B2_LEAF_VERSION;
-
- /* b-tree type */
- *p++ = leaf->hdr->cls->id;
- HDassert((size_t)(p - leaf->hdr->page) == (H5B2_LEAF_PREFIX_SIZE - H5B2_SIZEOF_CHKSUM));
-
- /* Serialize records for leaf node */
- native = leaf->leaf_native;
- for(u = 0; u < leaf->nrec; u++) {
- /* Encode record */
- if((leaf->hdr->cls->encode)(p, native, leaf->hdr->cb_ctx) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTENCODE, FAIL, "unable to encode B-tree record")
-
- /* Move to next record */
- p += leaf->hdr->rrec_size;
- native += leaf->hdr->cls->nrec_size;
- } /* end for */
-
- /* Compute metadata checksum */
- metadata_chksum = H5_checksum_metadata(leaf->hdr->page, (size_t)(p - leaf->hdr->page), 0);
+ /* Set the image length size */
+ *image_len = leaf->hdr->node_size;
- /* Metadata checksum */
- UINT32ENCODE(p, metadata_chksum);
-
- /* Write the B-tree leaf node */
- HDassert((size_t)(p - leaf->hdr->page) <= leaf->hdr->node_size);
- if(H5F_block_write(f, H5FD_MEM_BTREE, addr, (size_t)leaf->hdr->node_size, dxpl_id, leaf->hdr->page) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTFLUSH, FAIL, "unable to save B-tree leaf node to disk")
-
- leaf->cache_info.is_dirty = FALSE;
- } /* end if */
-
- if(destroy)
- if(H5B2__cache_leaf_dest(f, leaf) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to destroy B-tree leaf node")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5B2__cache_leaf_flush() */
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5B2__cache_leaf_image_len() */
/*-------------------------------------------------------------------------
- * Function: H5B2__cache_leaf_dest
+ * Function: H5B2__cache_leaf_serialize
*
- * Purpose: Destroys a B-tree leaf node in memory.
+ * Purpose: Serializes a B-tree leaf node for writing to disk.
*
* Return: Non-negative on success/Negative on failure
*
@@ -1164,96 +1234,59 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5B2__cache_leaf_dest(H5F_t *f, H5B2_leaf_t *leaf)
+H5B2__cache_leaf_serialize(const H5F_t *f, void *_image, size_t H5_ATTR_UNUSED len,
+ void *_thing)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ H5B2_leaf_t *leaf = (H5B2_leaf_t *)_thing; /* Pointer to the B-tree leaf node */
+ uint8_t *image = (uint8_t *)_image; /* Pointer into raw data buffer */
+ uint8_t *native; /* Pointer to native keys */
+ uint32_t metadata_chksum; /* Computed metadata checksum value */
+ unsigned u; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_STATIC
- /* Check arguments */
+ /* check arguments */
HDassert(f);
+ HDassert(image);
HDassert(leaf);
HDassert(leaf->hdr);
- /* If we're going to free the space on disk, the address must be valid */
- HDassert(!leaf->cache_info.free_file_space_on_destroy || H5F_addr_defined(leaf->cache_info.addr));
-
- /* Unlink from shadowed list */
- if(leaf->shadowed_next) {
- if(leaf->shadowed_next != leaf) {
- leaf->shadowed_next->shadowed_prev = leaf->shadowed_prev;
-
- if(leaf->shadowed_prev)
- leaf->shadowed_prev->shadowed_next = leaf->shadowed_next;
- else {
- HDassert(leaf->hdr->shadowed_leaf = leaf);
-
- leaf->hdr->shadowed_leaf = leaf->shadowed_next;
- } /* end else */
- } /* end if */
- else {
- if(leaf->shadowed_prev)
- leaf->shadowed_prev->shadowed_next = leaf->shadowed_prev;
- else {
- HDassert(leaf->hdr->shadowed_leaf = leaf);
-
- leaf->hdr->shadowed_leaf = NULL;
- } /* end else */
- } /* end else */
- } /* end if */
+ /* magic number */
+ HDmemcpy(image, H5B2_LEAF_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ image += H5_SIZEOF_MAGIC;
- /* Check for freeing file space for B-tree leaf node */
- if(leaf->cache_info.free_file_space_on_destroy) {
- /* Release the space on disk */
- /* (XXX: Nasty usage of internal DXPL value! -QAK) */
- if(H5MF_xfree(f, H5FD_MEM_BTREE, H5AC_dxpl_id, leaf->cache_info.addr, (hsize_t)leaf->hdr->node_size) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free v2 B-tree leaf node")
- } /* end if */
+ /* version # */
+ *image++ = H5B2_LEAF_VERSION;
- /* Destroy v2 b-tree leaf node */
- if(H5B2__leaf_free(leaf) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to destroy B-tree leaf node")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5B2__cache_leaf_dest() */
+ /* B-tree type */
+ *image++ = leaf->hdr->cls->id;
+ HDassert((size_t)(image - (uint8_t *)_image) == (H5B2_LEAF_PREFIX_SIZE - H5B2_SIZEOF_CHKSUM));
-
-/*-------------------------------------------------------------------------
- * Function: H5B2__cache_leaf_clear
- *
- * Purpose: Mark a B-tree leaf node in memory as non-dirty.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 2 2005
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5B2__cache_leaf_clear(H5F_t *f, H5B2_leaf_t *leaf, hbool_t destroy)
-{
- herr_t ret_value = SUCCEED;
+ /* Serialize records for leaf node */
+ native = leaf->leaf_native;
+ for(u = 0; u < leaf->nrec; u++) {
+ /* Encode record */
+ if((leaf->hdr->cls->encode)(image, native, leaf->hdr->cb_ctx) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTENCODE, FAIL, "unable to encode B-tree record")
- FUNC_ENTER_STATIC
+ /* Move to next record */
+ image += leaf->hdr->rrec_size;
+ native += leaf->hdr->cls->nrec_size;
+ } /* end for */
- /*
- * Check arguments.
- */
- HDassert(leaf);
+ /* Compute metadata checksum */
+ metadata_chksum = H5_checksum_metadata(_image, (size_t)((const uint8_t *)image - (const uint8_t *)_image), 0);
- /* Reset the dirty flag. */
- leaf->cache_info.is_dirty = FALSE;
+ /* Metadata checksum */
+ UINT32ENCODE(image, metadata_chksum);
- if(destroy)
- if(H5B2__cache_leaf_dest(f, leaf) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to destroy B-tree leaf node")
+ /* Sanity check */
+ HDassert((size_t)(image - (uint8_t *)_image) <= len);
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5B2__cache_leaf_clear() */
+} /* H5B2__cache_leaf_serialize() */
/*-------------------------------------------------------------------------
@@ -1270,8 +1303,9 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5B2__cache_leaf_notify(H5AC_notify_action_t action, H5B2_leaf_t *leaf)
+H5B2__cache_leaf_notify(H5AC_notify_action_t action, void *_thing)
{
+ H5B2_leaf_t *leaf = (H5B2_leaf_t *)_thing;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI_NOINIT
@@ -1286,13 +1320,20 @@ H5B2__cache_leaf_notify(H5AC_notify_action_t action, H5B2_leaf_t *leaf)
HDassert(leaf->parent);
switch(action) {
case H5AC_NOTIFY_ACTION_AFTER_INSERT:
+ case H5AC_NOTIFY_ACTION_AFTER_LOAD:
/* Create flush dependency on parent */
if(H5B2__create_flush_depend((H5AC_info_t *)leaf->parent, (H5AC_info_t *)leaf) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTDEPEND, FAIL, "unable to create flush dependency")
break;
+ case H5AC_NOTIFY_ACTION_AFTER_FLUSH:
+ /* do nothing */
+ break;
+
case H5AC_NOTIFY_ACTION_BEFORE_EVICT:
- /* Nothing to do */
+ /* Destroy flush dependency on parent */
+ if(H5B2__destroy_flush_depend((H5AC_info_t *)leaf->parent, (H5AC_info_t *)leaf) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNDEPEND, FAIL, "unable to destroy flush dependency")
break;
default:
@@ -1310,33 +1351,60 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5B2__cache_leaf_size
+ * Function: H5B2__cache_leaf_free_icr
*
- * Purpose: Compute the size in bytes of a B-tree leaf node
- * on disk, and return it in *size_ptr. On failure,
- * the value of *size_ptr is undefined.
+ * Purpose: Destroy/release an "in core representation" of a data
+ * structure
*
* Return: Non-negative on success/Negative on failure
*
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 2 2005
+ * Programmer: Mike McGreevy
+ * mcgreevy@hdfgroup.org
+ * June 18, 2008
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5B2__cache_leaf_size(const H5F_t H5_ATTR_UNUSED *f, const H5B2_leaf_t *leaf, size_t *size_ptr)
+H5B2__cache_leaf_free_icr(void *_thing)
{
- FUNC_ENTER_STATIC_NOERR
+ H5B2_leaf_t *leaf = (H5B2_leaf_t *)_thing;
+ herr_t ret_value = SUCCEED; /* Return value */
- /* check arguments */
+ FUNC_ENTER_STATIC
+
+ /* Check arguments */
HDassert(leaf);
HDassert(leaf->hdr);
- HDassert(size_ptr);
- /* Set size value */
- *size_ptr = leaf->hdr->node_size;
+ /* Unlink from shadowed list */
+ if(leaf->shadowed_next) {
+ if(leaf->shadowed_next != leaf) {
+ leaf->shadowed_next->shadowed_prev = leaf->shadowed_prev;
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5B2__cache_leaf_size() */
+ if(leaf->shadowed_prev)
+ leaf->shadowed_prev->shadowed_next = leaf->shadowed_next;
+ else {
+ HDassert(leaf->hdr->shadowed_leaf = leaf);
+
+ leaf->hdr->shadowed_leaf = leaf->shadowed_next;
+ } /* end else */
+ } /* end if */
+ else {
+ if(leaf->shadowed_prev)
+ leaf->shadowed_prev->shadowed_next = leaf->shadowed_prev;
+ else {
+ HDassert(leaf->hdr->shadowed_leaf = leaf);
+
+ leaf->hdr->shadowed_leaf = NULL;
+ } /* end else */
+ } /* end else */
+ } /* end if */
+
+ /* Destroy v2 B-tree leaf node */
+ if(H5B2__leaf_free(leaf) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to destroy B-tree leaf node")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5B2__cache_leaf_free_icr() */
diff --git a/src/H5B2dbg.c b/src/H5B2dbg.c
index 19bd2cd..20c0a5f 100644
--- a/src/H5B2dbg.c
+++ b/src/H5B2dbg.c
@@ -123,9 +123,10 @@ H5B2__hdr_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent,
* Load the B-tree header.
*/
cache_udata.f = f;
+ cache_udata.addr = addr;
cache_udata.ctx_udata = dbg_ctx;
cache_udata.parent = NULL;
- if(NULL == (hdr = (H5B2_hdr_t *)H5AC_protect(f, dxpl_id, H5AC_BT2_HDR, addr, &cache_udata, H5AC_READ)))
+ if(NULL == (hdr = (H5B2_hdr_t *)H5AC_protect(f, dxpl_id, H5AC_BT2_HDR, addr, &cache_udata, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, FAIL, "unable to load B-tree header")
/* Set file pointer for this B-tree operation */
@@ -242,9 +243,10 @@ H5B2__int_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent,
* Load the B-tree header.
*/
cache_udata.f = f;
+ cache_udata.addr = hdr_addr;
cache_udata.ctx_udata = dbg_ctx;
cache_udata.parent = NULL;
- if(NULL == (hdr = (H5B2_hdr_t *)H5AC_protect(f, dxpl_id, H5AC_BT2_HDR, hdr_addr, &cache_udata, H5AC_READ)))
+ if(NULL == (hdr = (H5B2_hdr_t *)H5AC_protect(f, dxpl_id, H5AC_BT2_HDR, hdr_addr, &cache_udata, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, FAIL, "unable to load B-tree header")
/* Set file pointer for this B-tree operation */
@@ -255,7 +257,7 @@ H5B2__int_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent,
*/
H5_CHECK_OVERFLOW(nrec, unsigned, uint16_t);
H5_CHECK_OVERFLOW(depth, unsigned, uint16_t);
- if(NULL == (internal = H5B2__protect_internal(hdr, dxpl_id, addr, NULL, (uint16_t)nrec, (uint16_t)depth, H5AC_READ)))
+ if(NULL == (internal = H5B2__protect_internal(hdr, dxpl_id, addr, NULL, (uint16_t)nrec, (uint16_t)depth, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, FAIL, "unable to load B-tree internal node")
/* Print opening message */
@@ -377,9 +379,10 @@ H5B2__leaf_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent
* Load the B-tree header.
*/
cache_udata.f = f;
+ cache_udata.addr = hdr_addr;
cache_udata.ctx_udata = dbg_ctx;
cache_udata.parent = NULL;
- if(NULL == (hdr = (H5B2_hdr_t *)H5AC_protect(f, dxpl_id, H5AC_BT2_HDR, hdr_addr, &cache_udata, H5AC_READ)))
+ if(NULL == (hdr = (H5B2_hdr_t *)H5AC_protect(f, dxpl_id, H5AC_BT2_HDR, hdr_addr, &cache_udata, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree header")
/* Set file pointer for this B-tree operation */
@@ -389,7 +392,7 @@ H5B2__leaf_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent
* Load the B-tree leaf node
*/
H5_CHECK_OVERFLOW(nrec, unsigned, uint16_t);
- if(NULL == (leaf = H5B2__protect_leaf(hdr, dxpl_id, addr, NULL, (uint16_t)nrec, H5AC_READ)))
+ if(NULL == (leaf = H5B2__protect_leaf(hdr, dxpl_id, addr, NULL, (uint16_t)nrec, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
/* Print opening message */
diff --git a/src/H5B2int.c b/src/H5B2int.c
index daf5003..7f53264 100644
--- a/src/H5B2int.c
+++ b/src/H5B2int.c
@@ -223,9 +223,9 @@ H5B2__split1(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth,
right_addr = internal->node_ptrs[idx + 1].addr;
/* Protect both leaves */
- if(NULL == (left_int = H5B2__protect_internal(hdr, dxpl_id, left_addr, internal, internal->node_ptrs[idx].node_nrec, (uint16_t)(depth - 1), H5AC_WRITE)))
+ if(NULL == (left_int = H5B2__protect_internal(hdr, dxpl_id, left_addr, internal, internal->node_ptrs[idx].node_nrec, (uint16_t)(depth - 1), H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
- if(NULL == (right_int = H5B2__protect_internal(hdr, dxpl_id, right_addr, internal, internal->node_ptrs[idx + 1].node_nrec, (uint16_t)(depth - 1), H5AC_WRITE)))
+ if(NULL == (right_int = H5B2__protect_internal(hdr, dxpl_id, right_addr, internal, internal->node_ptrs[idx + 1].node_nrec, (uint16_t)(depth - 1), H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
/* Shadow the left node if doing SWMR writes */
@@ -259,9 +259,9 @@ H5B2__split1(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth,
right_addr = internal->node_ptrs[idx + 1].addr;
/* Protect both leaves */
- if(NULL == (left_leaf = H5B2__protect_leaf(hdr, dxpl_id, left_addr, internal, internal->node_ptrs[idx].node_nrec, H5AC_WRITE)))
+ if(NULL == (left_leaf = H5B2__protect_leaf(hdr, dxpl_id, left_addr, internal, internal->node_ptrs[idx].node_nrec, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
- if(NULL == (right_leaf = H5B2__protect_leaf(hdr, dxpl_id, right_addr, internal, internal->node_ptrs[idx + 1].node_nrec, H5AC_WRITE)))
+ if(NULL == (right_leaf = H5B2__protect_leaf(hdr, dxpl_id, right_addr, internal, internal->node_ptrs[idx + 1].node_nrec, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
/* Shadow the left node if doing SWMR writes */
@@ -356,7 +356,7 @@ H5B2__split1(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth,
H5B2_internal_t *grandchild_int = NULL;
/* Protect grandchild */
- if(NULL == (grandchild_int = H5B2__protect_internal(hdr, dxpl_id, grandchild_addr, right_child, right_node_ptrs[u].node_nrec, (depth - 2), H5AC_WRITE)))
+ if(NULL == (grandchild_int = H5B2__protect_internal(hdr, dxpl_id, grandchild_addr, right_child, right_node_ptrs[u].node_nrec, (depth - 2), H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
grandchild_class = H5AC_BT2_INT;
grandchild = grandchild_int;
@@ -372,7 +372,7 @@ H5B2__split1(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth,
H5B2_leaf_t *grandchild_leaf = NULL;
/* Protect grandchild */
- if(NULL == (grandchild_leaf = H5B2__protect_leaf(hdr, dxpl_id, grandchild_addr, right_child, right_node_ptrs[u].node_nrec, H5AC_WRITE)))
+ if(NULL == (grandchild_leaf = H5B2__protect_leaf(hdr, dxpl_id, grandchild_addr, right_child, right_node_ptrs[u].node_nrec, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
grandchild_class = H5AC_BT2_LEAF;
grandchild = grandchild_leaf;
@@ -494,7 +494,7 @@ H5B2__split_root(H5B2_hdr_t *hdr, hid_t dxpl_id)
HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "unable to create new internal node")
/* Protect new root node */
- if(NULL == (new_root = H5B2__protect_internal(hdr, dxpl_id, hdr->root.addr, hdr, hdr->root.node_nrec, hdr->depth, H5AC_WRITE)))
+ if(NULL == (new_root = H5B2__protect_internal(hdr, dxpl_id, hdr->root.addr, hdr, hdr->root.node_nrec, hdr->depth, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
/* Set first node pointer in root node to old root node pointer info */
@@ -562,9 +562,9 @@ H5B2__redistribute2(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth,
right_addr = internal->node_ptrs[idx + 1].addr;
/* Lock left & right B-tree child nodes */
- if(NULL == (left_internal = H5B2__protect_internal(hdr, dxpl_id, left_addr, internal, internal->node_ptrs[idx].node_nrec, (uint16_t)(depth - 1), H5AC_WRITE)))
+ if(NULL == (left_internal = H5B2__protect_internal(hdr, dxpl_id, left_addr, internal, internal->node_ptrs[idx].node_nrec, (uint16_t)(depth - 1), H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
- if(NULL == (right_internal = H5B2__protect_internal(hdr, dxpl_id, right_addr, internal, internal->node_ptrs[idx + 1].node_nrec, (uint16_t)(depth - 1), H5AC_WRITE)))
+ if(NULL == (right_internal = H5B2__protect_internal(hdr, dxpl_id, right_addr, internal, internal->node_ptrs[idx + 1].node_nrec, (uint16_t)(depth - 1), H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
/* Shadow both nodes if doing SWMR writes */
@@ -597,9 +597,9 @@ H5B2__redistribute2(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth,
right_addr = internal->node_ptrs[idx + 1].addr;
/* Lock left & right B-tree child nodes */
- if(NULL == (left_leaf = H5B2__protect_leaf(hdr, dxpl_id, left_addr, internal, internal->node_ptrs[idx].node_nrec, H5AC_WRITE)))
+ if(NULL == (left_leaf = H5B2__protect_leaf(hdr, dxpl_id, left_addr, internal, internal->node_ptrs[idx].node_nrec, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
- if(NULL == (right_leaf = H5B2__protect_leaf(hdr, dxpl_id, right_addr, internal, internal->node_ptrs[idx + 1].node_nrec, H5AC_WRITE)))
+ if(NULL == (right_leaf = H5B2__protect_leaf(hdr, dxpl_id, right_addr, internal, internal->node_ptrs[idx + 1].node_nrec, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
/* Shadow both nodes if doing SWMR writes */
@@ -684,7 +684,7 @@ H5B2__redistribute2(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth,
H5B2_internal_t *grandchild_int = NULL;
/* Protect grandchild */
- if(NULL == (grandchild_int = H5B2__protect_internal(hdr, dxpl_id, grandchild_addr, left_child, left_node_ptrs[u].node_nrec, (depth - 2), H5AC_WRITE)))
+ if(NULL == (grandchild_int = H5B2__protect_internal(hdr, dxpl_id, grandchild_addr, left_child, left_node_ptrs[u].node_nrec, (depth - 2), H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
grandchild_class = H5AC_BT2_INT;
grandchild = grandchild_int;
@@ -700,7 +700,7 @@ H5B2__redistribute2(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth,
H5B2_leaf_t *grandchild_leaf = NULL;
/* Protect grandchild */
- if(NULL == (grandchild_leaf = H5B2__protect_leaf(hdr, dxpl_id, grandchild_addr, left_child, left_node_ptrs[u].node_nrec, H5AC_WRITE)))
+ if(NULL == (grandchild_leaf = H5B2__protect_leaf(hdr, dxpl_id, grandchild_addr, left_child, left_node_ptrs[u].node_nrec, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
grandchild_class = H5AC_BT2_LEAF;
grandchild = grandchild_leaf;
@@ -791,7 +791,7 @@ H5B2__redistribute2(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth,
H5B2_internal_t *grandchild_int = NULL;
/* Protect grandchild */
- if(NULL == (grandchild_int = H5B2__protect_internal(hdr, dxpl_id, grandchild_addr, right_child, right_node_ptrs[u].node_nrec, (depth - 2), H5AC_WRITE)))
+ if(NULL == (grandchild_int = H5B2__protect_internal(hdr, dxpl_id, grandchild_addr, right_child, right_node_ptrs[u].node_nrec, (depth - 2), H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
grandchild_class = H5AC_BT2_INT;
grandchild = grandchild_int;
@@ -807,7 +807,7 @@ H5B2__redistribute2(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth,
H5B2_leaf_t *grandchild_leaf = NULL;
/* Protect grandchild */
- if(NULL == (grandchild_leaf = H5B2__protect_leaf(hdr, dxpl_id, grandchild_addr, right_child, right_node_ptrs[u].node_nrec, H5AC_WRITE)))
+ if(NULL == (grandchild_leaf = H5B2__protect_leaf(hdr, dxpl_id, grandchild_addr, right_child, right_node_ptrs[u].node_nrec, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
grandchild_class = H5AC_BT2_LEAF;
grandchild = grandchild_leaf;
@@ -952,11 +952,11 @@ H5B2__redistribute3(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth,
right_addr = internal->node_ptrs[idx + 1].addr;
/* Lock B-tree child nodes */
- if(NULL == (left_internal = H5B2__protect_internal(hdr, dxpl_id, left_addr, internal, internal->node_ptrs[idx - 1].node_nrec, (uint16_t)(depth - 1), H5AC_WRITE)))
+ if(NULL == (left_internal = H5B2__protect_internal(hdr, dxpl_id, left_addr, internal, internal->node_ptrs[idx - 1].node_nrec, (uint16_t)(depth - 1), H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
- if(NULL == (middle_internal = H5B2__protect_internal(hdr, dxpl_id, middle_addr, internal, internal->node_ptrs[idx].node_nrec, (uint16_t)(depth - 1), H5AC_WRITE)))
+ if(NULL == (middle_internal = H5B2__protect_internal(hdr, dxpl_id, middle_addr, internal, internal->node_ptrs[idx].node_nrec, (uint16_t)(depth - 1), H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
- if(NULL == (right_internal = H5B2__protect_internal(hdr, dxpl_id, right_addr, internal, internal->node_ptrs[idx + 1].node_nrec, (uint16_t)(depth - 1), H5AC_WRITE)))
+ if(NULL == (right_internal = H5B2__protect_internal(hdr, dxpl_id, right_addr, internal, internal->node_ptrs[idx + 1].node_nrec, (uint16_t)(depth - 1), H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
/* Shadow all nodes if doing SWMR writes */
@@ -998,11 +998,11 @@ H5B2__redistribute3(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth,
right_addr = internal->node_ptrs[idx + 1].addr;
/* Lock B-tree child nodes */
- if(NULL == (left_leaf = H5B2__protect_leaf(hdr, dxpl_id, left_addr, internal, internal->node_ptrs[idx - 1].node_nrec, H5AC_WRITE)))
+ if(NULL == (left_leaf = H5B2__protect_leaf(hdr, dxpl_id, left_addr, internal, internal->node_ptrs[idx - 1].node_nrec, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
- if(NULL == (middle_leaf = H5B2__protect_leaf(hdr, dxpl_id, middle_addr, internal, internal->node_ptrs[idx].node_nrec, H5AC_WRITE)))
+ if(NULL == (middle_leaf = H5B2__protect_leaf(hdr, dxpl_id, middle_addr, internal, internal->node_ptrs[idx].node_nrec, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
- if(NULL == (right_leaf = H5B2__protect_leaf(hdr, dxpl_id, right_addr, internal, internal->node_ptrs[idx + 1].node_nrec, H5AC_WRITE)))
+ if(NULL == (right_leaf = H5B2__protect_leaf(hdr, dxpl_id, right_addr, internal, internal->node_ptrs[idx + 1].node_nrec, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
/* Shadow all nodes if doing SWMR writes */
@@ -1096,7 +1096,7 @@ H5B2__redistribute3(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth,
H5B2_internal_t *grandchild_int = NULL;
/* Protect grandchild */
- if(NULL == (grandchild_int = H5B2__protect_internal(hdr, dxpl_id, grandchild_addr, left_child, left_node_ptrs[u].node_nrec, (depth - 2), H5AC_WRITE)))
+ if(NULL == (grandchild_int = H5B2__protect_internal(hdr, dxpl_id, grandchild_addr, left_child, left_node_ptrs[u].node_nrec, (depth - 2), H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
grandchild_class = H5AC_BT2_INT;
grandchild = grandchild_int;
@@ -1112,7 +1112,7 @@ H5B2__redistribute3(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth,
H5B2_leaf_t *grandchild_leaf = NULL;
/* Protect grandchild */
- if(NULL == (grandchild_leaf = H5B2__protect_leaf(hdr, dxpl_id, grandchild_addr, left_child, left_node_ptrs[u].node_nrec, H5AC_WRITE)))
+ if(NULL == (grandchild_leaf = H5B2__protect_leaf(hdr, dxpl_id, grandchild_addr, left_child, left_node_ptrs[u].node_nrec, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
grandchild_class = H5AC_BT2_LEAF;
grandchild = grandchild_leaf;
@@ -1197,7 +1197,7 @@ H5B2__redistribute3(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth,
H5B2_internal_t *grandchild_int = NULL;
/* Protect grandchild */
- if(NULL == (grandchild_int = H5B2__protect_internal(hdr, dxpl_id, grandchild_addr, right_child, right_node_ptrs[u].node_nrec, (depth - 2), H5AC_WRITE)))
+ if(NULL == (grandchild_int = H5B2__protect_internal(hdr, dxpl_id, grandchild_addr, right_child, right_node_ptrs[u].node_nrec, (depth - 2), H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
grandchild_class = H5AC_BT2_INT;
grandchild = grandchild_int;
@@ -1213,7 +1213,7 @@ H5B2__redistribute3(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth,
H5B2_leaf_t *grandchild_leaf = NULL;
/* Protect grandchild */
- if(NULL == (grandchild_leaf = H5B2__protect_leaf(hdr, dxpl_id, grandchild_addr, right_child, right_node_ptrs[u].node_nrec, H5AC_WRITE)))
+ if(NULL == (grandchild_leaf = H5B2__protect_leaf(hdr, dxpl_id, grandchild_addr, right_child, right_node_ptrs[u].node_nrec, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
grandchild_class = H5AC_BT2_LEAF;
grandchild = grandchild_leaf;
@@ -1298,7 +1298,7 @@ H5B2__redistribute3(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth,
H5B2_internal_t *grandchild_int = NULL;
/* Protect grandchild */
- if(NULL == (grandchild_int = H5B2__protect_internal(hdr, dxpl_id, grandchild_addr, middle_child, middle_node_ptrs[u].node_nrec, (depth - 2), H5AC_WRITE)))
+ if(NULL == (grandchild_int = H5B2__protect_internal(hdr, dxpl_id, grandchild_addr, middle_child, middle_node_ptrs[u].node_nrec, (depth - 2), H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
grandchild_class = H5AC_BT2_INT;
grandchild = grandchild_int;
@@ -1314,7 +1314,7 @@ H5B2__redistribute3(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth,
H5B2_leaf_t *grandchild_leaf = NULL;
/* Protect grandchild */
- if(NULL == (grandchild_leaf = H5B2__protect_leaf(hdr, dxpl_id, grandchild_addr, middle_child, middle_node_ptrs[u].node_nrec, H5AC_WRITE)))
+ if(NULL == (grandchild_leaf = H5B2__protect_leaf(hdr, dxpl_id, grandchild_addr, middle_child, middle_node_ptrs[u].node_nrec, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
grandchild_class = H5AC_BT2_LEAF;
grandchild = grandchild_leaf;
@@ -1398,7 +1398,7 @@ H5B2__redistribute3(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth,
H5B2_internal_t *grandchild_int = NULL;
/* Protect grandchild */
- if(NULL == (grandchild_int = H5B2__protect_internal(hdr, dxpl_id, grandchild_addr, middle_child, middle_node_ptrs[u].node_nrec, (depth - 2), H5AC_WRITE)))
+ if(NULL == (grandchild_int = H5B2__protect_internal(hdr, dxpl_id, grandchild_addr, middle_child, middle_node_ptrs[u].node_nrec, (depth - 2), H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
grandchild_class = H5AC_BT2_INT;
grandchild = grandchild_int;
@@ -1414,7 +1414,7 @@ H5B2__redistribute3(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth,
H5B2_leaf_t *grandchild_leaf = NULL;
/* Protect grandchild */
- if(NULL == (grandchild_leaf = H5B2__protect_leaf(hdr, dxpl_id, grandchild_addr, middle_child, middle_node_ptrs[u].node_nrec, H5AC_WRITE)))
+ if(NULL == (grandchild_leaf = H5B2__protect_leaf(hdr, dxpl_id, grandchild_addr, middle_child, middle_node_ptrs[u].node_nrec, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
grandchild_class = H5AC_BT2_LEAF;
grandchild = grandchild_leaf;
@@ -1601,9 +1601,9 @@ H5B2__merge2(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth,
right_addr = internal->node_ptrs[idx + 1].addr;
/* Lock left & right B-tree child nodes */
- if(NULL == (left_internal = H5B2__protect_internal(hdr, dxpl_id, left_addr, internal, internal->node_ptrs[idx].node_nrec, (uint16_t)(depth - 1), H5AC_WRITE)))
+ if(NULL == (left_internal = H5B2__protect_internal(hdr, dxpl_id, left_addr, internal, internal->node_ptrs[idx].node_nrec, (uint16_t)(depth - 1), H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
- if(NULL == (right_internal = H5B2__protect_internal(hdr, dxpl_id, right_addr, internal, internal->node_ptrs[idx + 1].node_nrec, (uint16_t)(depth - 1), H5AC_WRITE)))
+ if(NULL == (right_internal = H5B2__protect_internal(hdr, dxpl_id, right_addr, internal, internal->node_ptrs[idx + 1].node_nrec, (uint16_t)(depth - 1), H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
/* Shadow the left node if doing SWMR writes */
@@ -1633,9 +1633,9 @@ H5B2__merge2(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth,
right_addr = internal->node_ptrs[idx + 1].addr;
/* Lock left & right B-tree child nodes */
- if(NULL == (left_leaf = H5B2__protect_leaf(hdr, dxpl_id, left_addr, internal, internal->node_ptrs[idx].node_nrec, H5AC_WRITE)))
+ if(NULL == (left_leaf = H5B2__protect_leaf(hdr, dxpl_id, left_addr, internal, internal->node_ptrs[idx].node_nrec, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
- if(NULL == (right_leaf = H5B2__protect_leaf(hdr, dxpl_id, right_addr, internal, internal->node_ptrs[idx + 1].node_nrec, H5AC_WRITE)))
+ if(NULL == (right_leaf = H5B2__protect_leaf(hdr, dxpl_id, right_addr, internal, internal->node_ptrs[idx + 1].node_nrec, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
/* Shadow the left node if doing SWMR writes */
@@ -1680,7 +1680,7 @@ H5B2__merge2(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth,
H5B2_internal_t *grandchild_int = NULL;
/* Protect grandchild */
- if(NULL == (grandchild_int = H5B2__protect_internal(hdr, dxpl_id, grandchild_addr, left_child, left_node_ptrs[u].node_nrec, (depth - 2), H5AC_WRITE)))
+ if(NULL == (grandchild_int = H5B2__protect_internal(hdr, dxpl_id, grandchild_addr, left_child, left_node_ptrs[u].node_nrec, (depth - 2), H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
grandchild_class = H5AC_BT2_INT;
grandchild = grandchild_int;
@@ -1696,7 +1696,7 @@ H5B2__merge2(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth,
H5B2_leaf_t *grandchild_leaf = NULL;
/* Protect grandchild */
- if(NULL == (grandchild_leaf = H5B2__protect_leaf(hdr, dxpl_id, grandchild_addr, left_child, left_node_ptrs[u].node_nrec, H5AC_WRITE)))
+ if(NULL == (grandchild_leaf = H5B2__protect_leaf(hdr, dxpl_id, grandchild_addr, left_child, left_node_ptrs[u].node_nrec, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
grandchild_class = H5AC_BT2_LEAF;
grandchild = grandchild_leaf;
@@ -1849,11 +1849,11 @@ H5B2__merge3(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth,
right_addr = internal->node_ptrs[idx + 1].addr;
/* Lock B-tree child nodes */
- if(NULL == (left_internal = H5B2__protect_internal(hdr, dxpl_id, left_addr, internal, internal->node_ptrs[idx - 1].node_nrec, (uint16_t)(depth - 1), H5AC_WRITE)))
+ if(NULL == (left_internal = H5B2__protect_internal(hdr, dxpl_id, left_addr, internal, internal->node_ptrs[idx - 1].node_nrec, (uint16_t)(depth - 1), H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
- if(NULL == (middle_internal = H5B2__protect_internal(hdr, dxpl_id, middle_addr, internal, internal->node_ptrs[idx].node_nrec, (uint16_t)(depth - 1), H5AC_WRITE)))
+ if(NULL == (middle_internal = H5B2__protect_internal(hdr, dxpl_id, middle_addr, internal, internal->node_ptrs[idx].node_nrec, (uint16_t)(depth - 1), H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
- if(NULL == (right_internal = H5B2__protect_internal(hdr, dxpl_id, right_addr, internal, internal->node_ptrs[idx + 1].node_nrec, (uint16_t)(depth - 1), H5AC_WRITE)))
+ if(NULL == (right_internal = H5B2__protect_internal(hdr, dxpl_id, right_addr, internal, internal->node_ptrs[idx + 1].node_nrec, (uint16_t)(depth - 1), H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
/* Shadow left and middle nodes if doing SWMR writes */
@@ -1892,11 +1892,11 @@ H5B2__merge3(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth,
right_addr = internal->node_ptrs[idx + 1].addr;
/* Lock B-tree child nodes */
- if(NULL == (left_leaf = H5B2__protect_leaf(hdr, dxpl_id, left_addr, internal, internal->node_ptrs[idx - 1].node_nrec, H5AC_WRITE)))
+ if(NULL == (left_leaf = H5B2__protect_leaf(hdr, dxpl_id, left_addr, internal, internal->node_ptrs[idx - 1].node_nrec, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
- if(NULL == (middle_leaf = H5B2__protect_leaf(hdr, dxpl_id, middle_addr, internal, internal->node_ptrs[idx].node_nrec, H5AC_WRITE)))
+ if(NULL == (middle_leaf = H5B2__protect_leaf(hdr, dxpl_id, middle_addr, internal, internal->node_ptrs[idx].node_nrec, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
- if(NULL == (right_leaf = H5B2__protect_leaf(hdr, dxpl_id, right_addr, internal, internal->node_ptrs[idx + 1].node_nrec, H5AC_WRITE)))
+ if(NULL == (right_leaf = H5B2__protect_leaf(hdr, dxpl_id, right_addr, internal, internal->node_ptrs[idx + 1].node_nrec, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
/* Shadow left and middle nodes if doing SWMR writes */
@@ -1969,7 +1969,7 @@ H5B2__merge3(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth,
H5B2_internal_t *grandchild_int = NULL;
/* Protect grandchild */
- if(NULL == (grandchild_int = H5B2__protect_internal(hdr, dxpl_id, grandchild_addr, left_child, left_node_ptrs[u].node_nrec, (depth - 2), H5AC_WRITE)))
+ if(NULL == (grandchild_int = H5B2__protect_internal(hdr, dxpl_id, grandchild_addr, left_child, left_node_ptrs[u].node_nrec, (depth - 2), H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
grandchild_class = H5AC_BT2_INT;
grandchild = grandchild_int;
@@ -1985,7 +1985,7 @@ H5B2__merge3(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth,
H5B2_leaf_t *grandchild_leaf = NULL;
/* Protect grandchild */
- if(NULL == (grandchild_leaf = H5B2__protect_leaf(hdr, dxpl_id, grandchild_addr, left_child, left_node_ptrs[u].node_nrec, H5AC_WRITE)))
+ if(NULL == (grandchild_leaf = H5B2__protect_leaf(hdr, dxpl_id, grandchild_addr, left_child, left_node_ptrs[u].node_nrec, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
grandchild_class = H5AC_BT2_LEAF;
grandchild = grandchild_leaf;
@@ -2050,7 +2050,7 @@ H5B2__merge3(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth,
H5B2_internal_t *grandchild_int = NULL;
/* Protect grandchild */
- if(NULL == (grandchild_int = H5B2__protect_internal(hdr, dxpl_id, grandchild_addr, middle_child, middle_node_ptrs[u].node_nrec, (depth - 2), H5AC_WRITE)))
+ if(NULL == (grandchild_int = H5B2__protect_internal(hdr, dxpl_id, grandchild_addr, middle_child, middle_node_ptrs[u].node_nrec, (depth - 2), H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
grandchild_class = H5AC_BT2_INT;
grandchild = grandchild_int;
@@ -2066,7 +2066,7 @@ H5B2__merge3(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth,
H5B2_leaf_t *grandchild_leaf = NULL;
/* Protect grandchild */
- if(NULL == (grandchild_leaf = H5B2__protect_leaf(hdr, dxpl_id, grandchild_addr, middle_child, middle_node_ptrs[u].node_nrec, H5AC_WRITE)))
+ if(NULL == (grandchild_leaf = H5B2__protect_leaf(hdr, dxpl_id, grandchild_addr, middle_child, middle_node_ptrs[u].node_nrec, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
grandchild_class = H5AC_BT2_LEAF;
grandchild = grandchild_leaf;
@@ -2209,7 +2209,7 @@ H5B2__swap_leaf(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth,
child_addr = internal->node_ptrs[idx].addr;
/* Lock B-tree child nodes */
- if(NULL == (child_internal = H5B2__protect_internal(hdr, dxpl_id, child_addr, internal, internal->node_ptrs[idx].node_nrec, (depth - 1), H5AC_WRITE)))
+ if(NULL == (child_internal = H5B2__protect_internal(hdr, dxpl_id, child_addr, internal, internal->node_ptrs[idx].node_nrec, (uint16_t)(depth - 1), H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
/* More setup for accessing child node information */
@@ -2224,7 +2224,7 @@ H5B2__swap_leaf(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth,
child_addr = internal->node_ptrs[idx].addr;
/* Lock B-tree child node */
- if(NULL == (child_leaf = H5B2__protect_leaf(hdr, dxpl_id, child_addr, internal, internal->node_ptrs[idx].node_nrec, H5AC_WRITE)))
+ if(NULL == (child_leaf = H5B2__protect_leaf(hdr, dxpl_id, child_addr, internal, internal->node_ptrs[idx].node_nrec, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
/* More setup for accessing child node information */
@@ -2287,7 +2287,7 @@ H5B2__insert_leaf(H5B2_hdr_t *hdr, hid_t dxpl_id, H5B2_node_ptr_t *curr_node_ptr
HDassert(H5F_addr_defined(curr_node_ptr->addr));
/* Lock current B-tree node */
- if(NULL == (leaf = H5B2__protect_leaf(hdr, dxpl_id, curr_node_ptr->addr, parent, curr_node_ptr->node_nrec, H5AC_WRITE)))
+ if(NULL == (leaf = H5B2__protect_leaf(hdr, dxpl_id, curr_node_ptr->addr, parent, curr_node_ptr->node_nrec, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
/* Shadow the node if doing SWMR writes */
@@ -2391,7 +2391,7 @@ H5B2__insert_internal(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth,
HDassert(H5F_addr_defined(curr_node_ptr->addr));
/* Lock current B-tree node */
- if(NULL == (internal = H5B2__protect_internal(hdr, dxpl_id, curr_node_ptr->addr, parent, curr_node_ptr->node_nrec, depth, H5AC_WRITE)))
+ if(NULL == (internal = H5B2__protect_internal(hdr, dxpl_id, curr_node_ptr->addr, parent, curr_node_ptr->node_nrec, depth, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
/* Shadow the node if doing SWMR writes */
@@ -2599,8 +2599,8 @@ done:
*-------------------------------------------------------------------------
*/
H5B2_leaf_t *
-H5B2__protect_leaf(H5B2_hdr_t *hdr, hid_t dxpl_id, haddr_t addr, void *parent,
- uint16_t nrec, H5AC_protect_t rw)
+H5B2__protect_leaf(H5B2_hdr_t *hdr, hid_t dxpl_id, haddr_t addr, void *parent,
+ uint16_t nrec, unsigned flags)
{
H5B2_leaf_cache_ud_t udata; /* User-data for callback */
H5B2_leaf_t *ret_value; /* Return value */
@@ -2611,6 +2611,9 @@ H5B2__protect_leaf(H5B2_hdr_t *hdr, hid_t dxpl_id, haddr_t addr, void *parent,
HDassert(hdr);
HDassert(H5F_addr_defined(addr));
+ /* only H5AC__READ_ONLY_FLAG may appear in flags */
+ HDassert((flags & (unsigned)(~H5AC__READ_ONLY_FLAG)) == 0);
+
/* Set up user data for callback */
udata.f = hdr->f;
udata.hdr = hdr;
@@ -2618,7 +2621,7 @@ H5B2__protect_leaf(H5B2_hdr_t *hdr, hid_t dxpl_id, haddr_t addr, void *parent,
H5_CHECKED_ASSIGN(udata.nrec, uint16_t, nrec, unsigned)
/* Protect the leaf node */
- if(NULL == (ret_value = (H5B2_leaf_t *)H5AC_protect(hdr->f, dxpl_id, H5AC_BT2_LEAF, addr, &udata, rw)))
+ if(NULL == (ret_value = (H5B2_leaf_t *)H5AC_protect(hdr->f, dxpl_id, H5AC_BT2_LEAF, addr, &udata, flags)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, NULL, "unable to protect B-tree leaf node")
done:
@@ -2727,7 +2730,7 @@ done:
*/
H5B2_internal_t *
H5B2__protect_internal(H5B2_hdr_t *hdr, hid_t dxpl_id, haddr_t addr,
- void *parent, uint16_t nrec, uint16_t depth, H5AC_protect_t rw)
+ void *parent, uint16_t nrec, uint16_t depth, unsigned flags)
{
H5B2_internal_cache_ud_t udata; /* User data to pass through to cache 'deserialize' callback */
H5B2_internal_t *ret_value; /* Return value */
@@ -2739,6 +2742,9 @@ H5B2__protect_internal(H5B2_hdr_t *hdr, hid_t dxpl_id, haddr_t addr,
HDassert(H5F_addr_defined(addr));
HDassert(depth > 0);
+ /* only H5AC__READ_ONLY_FLAG may appear in flags */
+ HDassert((flags & (unsigned)(~H5AC__READ_ONLY_FLAG)) == 0);
+
/* Set up user data for callback */
udata.f = hdr->f;
udata.hdr = hdr;
@@ -2747,7 +2753,7 @@ H5B2__protect_internal(H5B2_hdr_t *hdr, hid_t dxpl_id, haddr_t addr,
udata.depth = depth;
/* Protect the internal node */
- if(NULL == (ret_value = (H5B2_internal_t *)H5AC_protect(hdr->f, dxpl_id, H5AC_BT2_INT, addr, &udata, rw)))
+ if(NULL == (ret_value = (H5B2_internal_t *)H5AC_protect(hdr->f, dxpl_id, H5AC_BT2_INT, addr, &udata, flags)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, NULL, "unable to protect B-tree internal node")
done:
@@ -2798,7 +2804,7 @@ H5B2__iterate_node(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth,
H5B2_internal_t *internal; /* Pointer to internal node */
/* Lock the current B-tree node */
- if(NULL == (internal = H5B2__protect_internal(hdr, dxpl_id, curr_node->addr, parent, curr_node->node_nrec, depth, H5AC_READ)))
+ if(NULL == (internal = H5B2__protect_internal(hdr, dxpl_id, curr_node->addr, parent, curr_node->node_nrec, depth, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
/* Set up information about current node */
@@ -2817,7 +2823,7 @@ H5B2__iterate_node(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth,
H5B2_leaf_t *leaf; /* Pointer to leaf node */
/* Lock the current B-tree node */
- if(NULL == (leaf = H5B2__protect_leaf(hdr, dxpl_id, curr_node->addr, parent, curr_node->node_nrec, H5AC_READ)))
+ if(NULL == (leaf = H5B2__protect_leaf(hdr, dxpl_id, curr_node->addr, parent, curr_node->node_nrec, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
/* Set up information about current node */
@@ -2909,7 +2915,7 @@ H5B2__remove_leaf(H5B2_hdr_t *hdr, hid_t dxpl_id, H5B2_node_ptr_t *curr_node_ptr
/* Lock current B-tree node */
leaf_addr = curr_node_ptr->addr;
- if(NULL == (leaf = H5B2__protect_leaf(hdr, dxpl_id, leaf_addr, parent, curr_node_ptr->node_nrec, H5AC_WRITE)))
+ if(NULL == (leaf = H5B2__protect_leaf(hdr, dxpl_id, leaf_addr, parent, curr_node_ptr->node_nrec, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
/* Sanity check number of records */
@@ -3029,7 +3035,7 @@ H5B2__remove_internal(H5B2_hdr_t *hdr, hid_t dxpl_id, hbool_t *depth_decreased,
/* Lock current B-tree node */
internal_addr = curr_node_ptr->addr;
- if(NULL == (internal = H5B2__protect_internal(hdr, dxpl_id, internal_addr, parent_cache_info, curr_node_ptr->node_nrec, depth, H5AC_WRITE)))
+ if(NULL == (internal = H5B2__protect_internal(hdr, dxpl_id, internal_addr, parent_cache_info, curr_node_ptr->node_nrec, depth, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
/* Determine the correct number of records to merge at */
@@ -3063,7 +3069,7 @@ H5B2__remove_internal(H5B2_hdr_t *hdr, hid_t dxpl_id, hbool_t *depth_decreased,
H5B2_internal_t *new_root_int = NULL;
/* Protect new root */
- if(NULL == (new_root_int = H5B2__protect_internal(hdr, dxpl_id, curr_node_ptr->addr, hdr, curr_node_ptr->node_nrec, (depth - 1), H5AC_WRITE)))
+ if(NULL == (new_root_int = H5B2__protect_internal(hdr, dxpl_id, curr_node_ptr->addr, hdr, curr_node_ptr->node_nrec, (depth - 1), H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
new_root_class = H5AC_BT2_INT;
new_root = new_root_int;
@@ -3079,7 +3085,7 @@ H5B2__remove_internal(H5B2_hdr_t *hdr, hid_t dxpl_id, hbool_t *depth_decreased,
H5B2_leaf_t *new_root_leaf = NULL;
/* Protect new root */
- if(NULL == (new_root_leaf = H5B2__protect_leaf(hdr, dxpl_id, curr_node_ptr->addr, hdr, curr_node_ptr->node_nrec, H5AC_WRITE)))
+ if(NULL == (new_root_leaf = H5B2__protect_leaf(hdr, dxpl_id, curr_node_ptr->addr, hdr, curr_node_ptr->node_nrec, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
new_root_class = H5AC_BT2_LEAF;
new_root = new_root_leaf;
@@ -3312,7 +3318,7 @@ H5B2__remove_leaf_by_idx(H5B2_hdr_t *hdr, hid_t dxpl_id,
/* Lock B-tree leaf node */
leaf_addr = curr_node_ptr->addr;
- if(NULL == (leaf = H5B2__protect_leaf(hdr, dxpl_id, leaf_addr, parent, curr_node_ptr->node_nrec, H5AC_WRITE)))
+ if(NULL == (leaf = H5B2__protect_leaf(hdr, dxpl_id, leaf_addr, parent, curr_node_ptr->node_nrec, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
/* Sanity check number of records */
@@ -3431,7 +3437,7 @@ H5B2__remove_internal_by_idx(H5B2_hdr_t *hdr, hid_t dxpl_id,
/* Lock current B-tree node */
internal_addr = curr_node_ptr->addr;
- if(NULL == (internal = H5B2__protect_internal(hdr, dxpl_id, internal_addr, parent_cache_info, curr_node_ptr->node_nrec, depth, H5AC_WRITE)))
+ if(NULL == (internal = H5B2__protect_internal(hdr, dxpl_id, internal_addr, parent_cache_info, curr_node_ptr->node_nrec, depth, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
HDassert(internal->nrec == curr_node_ptr->node_nrec);
HDassert(depth == hdr->depth || internal->nrec > 1);
@@ -3468,7 +3474,7 @@ H5B2__remove_internal_by_idx(H5B2_hdr_t *hdr, hid_t dxpl_id,
H5B2_internal_t *new_root_int = NULL;
/* Protect new root */
- if(NULL == (new_root_int = H5B2__protect_internal(hdr, dxpl_id, curr_node_ptr->addr, hdr, curr_node_ptr->node_nrec, (depth - 1), H5AC_WRITE)))
+ if(NULL == (new_root_int = H5B2__protect_internal(hdr, dxpl_id, curr_node_ptr->addr, hdr, curr_node_ptr->node_nrec, (depth - 1), H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
new_root_class = H5AC_BT2_INT;
new_root = new_root_int;
@@ -3484,7 +3490,7 @@ H5B2__remove_internal_by_idx(H5B2_hdr_t *hdr, hid_t dxpl_id,
H5B2_leaf_t *new_root_leaf = NULL;
/* Protect new root */
- if(NULL == (new_root_leaf = H5B2__protect_leaf(hdr, dxpl_id, curr_node_ptr->addr, hdr, curr_node_ptr->node_nrec, H5AC_WRITE)))
+ if(NULL == (new_root_leaf = H5B2__protect_leaf(hdr, dxpl_id, curr_node_ptr->addr, hdr, curr_node_ptr->node_nrec, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
new_root_class = H5AC_BT2_LEAF;
new_root = new_root_leaf;
@@ -3781,7 +3787,7 @@ H5B2__neighbor_leaf(H5B2_hdr_t *hdr, hid_t dxpl_id, H5B2_node_ptr_t *curr_node_p
HDassert(op);
/* Lock current B-tree node */
- if(NULL == (leaf = H5B2__protect_leaf(hdr, dxpl_id, curr_node_ptr->addr, parent, curr_node_ptr->node_nrec, H5AC_READ)))
+ if(NULL == (leaf = H5B2__protect_leaf(hdr, dxpl_id, curr_node_ptr->addr, parent, curr_node_ptr->node_nrec, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
/* Locate node pointer for child */
@@ -3868,7 +3874,7 @@ H5B2__neighbor_internal(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth,
HDassert(op);
/* Lock current B-tree node */
- if(NULL == (internal = H5B2__protect_internal(hdr, dxpl_id, curr_node_ptr->addr, parent, curr_node_ptr->node_nrec, depth, H5AC_READ)))
+ if(NULL == (internal = H5B2__protect_internal(hdr, dxpl_id, curr_node_ptr->addr, parent, curr_node_ptr->node_nrec, depth, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
/* Locate node pointer for child */
@@ -3942,7 +3948,7 @@ H5B2__delete_node(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth,
unsigned u; /* Local index */
/* Lock the current B-tree node */
- if(NULL == (internal = H5B2__protect_internal(hdr, dxpl_id, curr_node->addr, parent, curr_node->node_nrec, depth, H5AC_WRITE)))
+ if(NULL == (internal = H5B2__protect_internal(hdr, dxpl_id, curr_node->addr, parent, curr_node->node_nrec, depth, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
/* Set up information about current node */
@@ -3959,7 +3965,7 @@ H5B2__delete_node(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth,
H5B2_leaf_t *leaf; /* Pointer to leaf node */
/* Lock the current B-tree node */
- if(NULL == (leaf = H5B2__protect_leaf(hdr, dxpl_id, curr_node->addr, parent, curr_node->node_nrec, H5AC_WRITE)))
+ if(NULL == (leaf = H5B2__protect_leaf(hdr, dxpl_id, curr_node->addr, parent, curr_node->node_nrec, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
/* Set up information about current node */
@@ -4018,7 +4024,7 @@ H5B2__node_size(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth,
HDassert(depth > 0);
/* Lock the current B-tree node */
- if(NULL == (internal = H5B2__protect_internal(hdr, dxpl_id, curr_node->addr, parent, curr_node->node_nrec, depth, H5AC_READ)))
+ if(NULL == (internal = H5B2__protect_internal(hdr, dxpl_id, curr_node->addr, parent, curr_node->node_nrec, depth, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
/* Recursively descend into child nodes, if we are above the "twig" level in the B-tree */
@@ -4203,7 +4209,7 @@ H5B2_shadow_internal(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
/* Re-protect node at new address. Should have the same location in
* memory. */
- if(*internal != H5B2__protect_internal(hdr, dxpl_id, curr_node_ptr->addr, (*internal)->parent, curr_node_ptr->node_nrec, depth, H5AC_WRITE))
+ if(*internal != H5B2__protect_internal(hdr, dxpl_id, curr_node_ptr->addr, (*internal)->parent, curr_node_ptr->node_nrec, depth, H5AC__NO_FLAGS_SET))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
node_protected = TRUE;
@@ -4303,7 +4309,7 @@ H5B2_shadow_leaf(H5B2_hdr_t *hdr, hid_t dxpl_id,
/* Re-protect node at new address. Should have the same location in
* memory. */
- if(*leaf != H5B2__protect_leaf(hdr, dxpl_id, curr_node_ptr->addr, (*leaf)->parent, curr_node_ptr->node_nrec, H5AC_WRITE))
+ if(*leaf != H5B2__protect_leaf(hdr, dxpl_id, curr_node_ptr->addr, (*leaf)->parent, curr_node_ptr->node_nrec, H5AC__NO_FLAGS_SET))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
node_protected = TRUE;
diff --git a/src/H5B2pkg.h b/src/H5B2pkg.h
index 9c5c693..9702ae0 100644
--- a/src/H5B2pkg.h
+++ b/src/H5B2pkg.h
@@ -242,6 +242,7 @@ typedef enum H5B2_nodepos_t {
typedef struct H5B2_hdr_cache_ud_t {
H5F_t *f; /* File that v2 b-tree header is within */
void *parent; /* Flush dependency parent */
+ haddr_t addr; /* Address of B-tree header in the file */
void *ctx_udata; /* User-data for protecting */
} H5B2_hdr_cache_ud_t;
@@ -324,11 +325,11 @@ H5_DLL herr_t H5B2__hdr_delete(H5B2_hdr_t *hdr, hid_t dxpl_id);
/* Routines for operating on leaf nodes */
H5B2_leaf_t *H5B2__protect_leaf(H5B2_hdr_t *hdr, hid_t dxpl_id, haddr_t addr,
- void *parent, uint16_t nrec, H5AC_protect_t rw);
+ void *parent, uint16_t nrec, unsigned flags);
/* Routines for operating on internal nodes */
H5_DLL H5B2_internal_t *H5B2__protect_internal(H5B2_hdr_t *hdr, hid_t dxpl_id,
- haddr_t addr, void *parent, uint16_t nrec, uint16_t depth, H5AC_protect_t rw);
+ haddr_t addr, void *parent, uint16_t nrec, uint16_t depth, unsigned flags);
/* Routines for allocating nodes */
H5_DLL herr_t H5B2__split_root(H5B2_hdr_t *hdr, hid_t dxpl_id);
diff --git a/src/H5B2test.c b/src/H5B2test.c
index 45b53a6..5890fb8 100644
--- a/src/H5B2test.c
+++ b/src/H5B2test.c
@@ -435,7 +435,7 @@ H5B2_get_node_info_test(H5B2_t *bt2, hid_t dxpl_id, void *udata,
H5B2_node_ptr_t next_node_ptr; /* Node pointer info for next node */
/* Lock B-tree current node */
- if(NULL == (internal = H5B2__protect_internal(hdr, dxpl_id, curr_node_ptr.addr, parent, curr_node_ptr.node_nrec, depth, H5AC_READ)))
+ if(NULL == (internal = H5B2__protect_internal(hdr, dxpl_id, curr_node_ptr.addr, parent, curr_node_ptr.node_nrec, depth, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
/* Unpin parent if necessary */
@@ -486,7 +486,7 @@ H5B2_get_node_info_test(H5B2_t *bt2, hid_t dxpl_id, void *udata,
H5B2_leaf_t *leaf; /* Pointer to leaf node in B-tree */
/* Lock B-tree leaf node */
- if(NULL == (leaf = H5B2__protect_leaf(hdr, dxpl_id, curr_node_ptr.addr, parent, curr_node_ptr.node_nrec, H5AC_READ)))
+ if(NULL == (leaf = H5B2__protect_leaf(hdr, dxpl_id, curr_node_ptr.addr, parent, curr_node_ptr.node_nrec, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
/* Unpin parent if necessary */
diff --git a/src/H5Bcache.c b/src/H5Bcache.c
index 923880f..2a188f8 100644
--- a/src/H5Bcache.c
+++ b/src/H5Bcache.c
@@ -37,7 +37,6 @@
#include "H5private.h" /* Generic Functions */
#include "H5Bpkg.h" /* B-link trees */
#include "H5Eprivate.h" /* Error handling */
-#include "H5MFprivate.h" /* File memory management */
/****************/
@@ -55,11 +54,15 @@
/********************/
/* Metadata cache callbacks */
-static H5B_t *H5B__load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata);
-static herr_t H5B__flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5B_t *b, unsigned H5_ATTR_UNUSED * flags_ptr);
-static herr_t H5B__dest(H5F_t *f, H5B_t *bt);
-static herr_t H5B__clear(H5F_t *f, H5B_t *b, hbool_t destroy);
-static herr_t H5B__compute_size(const H5F_t *f, const H5B_t *bt, size_t *size_ptr);
+static herr_t H5B__get_load_size(const void *image, void *udata, size_t *image_len, size_t *actual_len,
+ hbool_t *compressed_ptr, size_t *compressed_image_len_ptr);
+static void *H5B__deserialize(const void *image, size_t len, void *udata,
+ hbool_t *dirty);
+static herr_t H5B__image_len(const void *thing, size_t *image_len,
+ hbool_t *compressed_ptr, size_t *compressed_image_len_ptr);
+static herr_t H5B__serialize(const H5F_t *f, void *image, size_t len,
+ void *thing);
+static herr_t H5B__free_icr(void *thing);
/*********************/
@@ -68,13 +71,20 @@ static herr_t H5B__compute_size(const H5F_t *f, const H5B_t *bt, size_t *size_pt
/* H5B inherits cache-like properties from H5AC */
const H5AC_class_t H5AC_BT[1] = {{
- H5AC_BT_ID,
- (H5AC_load_func_t)H5B__load,
- (H5AC_flush_func_t)H5B__flush,
- (H5AC_dest_func_t)H5B__dest,
- (H5AC_clear_func_t)H5B__clear,
- (H5AC_notify_func_t)NULL,
- (H5AC_size_func_t)H5B__compute_size,
+ H5AC_BT_ID, /* Metadata client ID */
+ "v1 B-tree", /* Metadata client name (for debugging) */
+ H5FD_MEM_BTREE, /* File space memory type for client */
+ H5AC__CLASS_NO_FLAGS_SET, /* Client class behavior flags */
+ H5B__get_load_size, /* 'get_load_size' callback */
+ NULL, /* 'verify_chksum' callback */
+ H5B__deserialize, /* 'deserialize' callback */
+ H5B__image_len, /* 'image_len' callback */
+ NULL, /* 'pre_serialize' callback */
+ H5B__serialize, /* 'serialize' callback */
+ NULL, /* 'notify' callback */
+ H5B__free_icr, /* 'free_icr' callback */
+ NULL, /* 'clear" callback */
+ NULL, /* 'fsf_size' callback */
}};
/*******************/
@@ -84,35 +94,78 @@ const H5AC_class_t H5AC_BT[1] = {{
/*-------------------------------------------------------------------------
- * Function: H5B__load
+ * Function: H5B__get_load_size
*
- * Purpose: Loads a B-tree node from the disk.
+ * Purpose: Compute the size of the data structure on disk.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * May 18, 2010
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5B__get_load_size(const void *_image, void *_udata, size_t *image_len, size_t *actual_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr)
+{
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into image buffer */
+ H5B_cache_ud_t *udata = (H5B_cache_ud_t *)_udata; /* User data for callback */
+ H5B_shared_t *shared; /* Pointer to shared B-tree info */
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Check arguments */
+ HDassert(udata);
+ HDassert(image_len);
+
+ if(image == NULL) {
+ /* Get shared info for B-tree */
+ shared = (H5B_shared_t *)H5UC_GET_OBJ(udata->rc_shared);
+ HDassert(shared);
+
+ /* Set the image length size */
+ *image_len = shared->sizeof_rnode;
+ } else {
+ HDassert(actual_len);
+ HDassert(*actual_len == *image_len);
+ }
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5B__get_load_size() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B__deserialize
+ *
+ * Purpose: Deserialize the data structure from disk.
*
* Return: Success: Pointer to a new B-tree node.
* Failure: NULL
*
- * Programmer: Robb Matzke
- * matzke@llnl.gov
- * Jun 23 1997
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Mar 24, 2008
*
*-------------------------------------------------------------------------
*/
-static H5B_t *
-H5B__load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
+static void *
+H5B__deserialize(const void *_image, size_t H5_ATTR_UNUSED len, void *_udata,
+ hbool_t H5_ATTR_UNUSED *dirty)
{
H5B_t *bt = NULL; /* Pointer to the deserialized B-tree node */
H5B_cache_ud_t *udata = (H5B_cache_ud_t *)_udata; /* User data for callback */
H5B_shared_t *shared; /* Pointer to shared B-tree info */
- const uint8_t *p; /* Pointer into raw data buffer */
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into image buffer */
uint8_t *native; /* Pointer to native keys */
unsigned u; /* Local index variable */
H5B_t *ret_value; /* Return value */
FUNC_ENTER_STATIC
- /* Check arguments */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
+ /* check arguments */
+ HDassert(image);
HDassert(udata);
/* Allocate the B-tree node in memory */
@@ -134,53 +187,50 @@ H5B__load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
if(NULL == (bt->child = H5FL_SEQ_MALLOC(haddr_t, (size_t)shared->two_k)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTALLOC, NULL, "can't allocate buffer for child addresses")
- if(H5F_block_read(f, H5FD_MEM_BTREE, addr, shared->sizeof_rnode, dxpl_id, shared->page) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_READERROR, NULL, "can't read B-tree node")
-
- /* Set the pointer into the raw data buffer */
- p = shared->page;
-
/* magic number */
- if(HDmemcmp(p, H5B_MAGIC, (size_t)H5_SIZEOF_MAGIC))
+ if(HDmemcmp(image, H5B_MAGIC, (size_t)H5_SIZEOF_MAGIC))
HGOTO_ERROR(H5E_BTREE, H5E_BADVALUE, NULL, "wrong B-tree signature")
- p += 4;
+ image += H5_SIZEOF_MAGIC;
/* node type and level */
- if(*p++ != (uint8_t)udata->type->id)
+ if(*image++ != (uint8_t)udata->type->id)
HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, NULL, "incorrect B-tree node type")
- bt->level = *p++;
+ bt->level = *image++;
/* entries used */
- UINT16DECODE(p, bt->nchildren);
+ UINT16DECODE(image, bt->nchildren);
/* Check if bt->nchildren is greater than two_k */
if(bt->nchildren > shared->two_k)
HGOTO_ERROR(H5E_BTREE, H5E_BADVALUE, NULL, "number of children is greater than maximum")
/* sibling pointers */
- H5F_addr_decode(udata->f, (const uint8_t **)&p, &(bt->left));
- H5F_addr_decode(udata->f, (const uint8_t **)&p, &(bt->right));
+ H5F_addr_decode(udata->f, (const uint8_t **)&image, &(bt->left));
+ H5F_addr_decode(udata->f, (const uint8_t **)&image, &(bt->right));
/* the child/key pairs */
native = bt->native;
for(u = 0; u < bt->nchildren; u++) {
/* Decode native key value */
- if((udata->type->decode)(shared, p, native) < 0)
+ if((udata->type->decode)(shared, image, native) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTDECODE, NULL, "unable to decode key")
- p += shared->sizeof_rkey;
+ image += shared->sizeof_rkey;
native += udata->type->sizeof_nkey;
/* Decode address value */
- H5F_addr_decode(udata->f, (const uint8_t **)&p, bt->child + u);
+ H5F_addr_decode(udata->f, (const uint8_t **)&image, bt->child + u);
} /* end for */
/* Decode final key */
if(bt->nchildren > 0) {
/* Decode native key value */
- if((udata->type->decode)(shared, p, native) < 0)
+ if((udata->type->decode)(shared, image, native) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTDECODE, NULL, "unable to decode key")
} /* end if */
+ /* Sanity check */
+ HDassert((size_t)((const uint8_t *)image - (const uint8_t *)_image) <= len);
+
/* Set return value */
ret_value = bt;
@@ -190,223 +240,150 @@ done:
HDONE_ERROR(H5E_BTREE, H5E_CANTFREE, NULL, "unable to destroy B-tree node")
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5B__load() */ /*lint !e818 Can't make udata a pointer to const */
+} /* end H5B__deserialize() */
/*-------------------------------------------------------------------------
- * Function: H5B__flush
+ * Function: H5B__image_len
*
- * Purpose: Flushes a dirty B-tree node to disk.
+ * Purpose: Compute the size of the data structure on disk.
*
* Return: Non-negative on success/Negative on failure
*
- * Programmer: Robb Matzke
- * matzke@llnl.gov
- * Jun 23 1997
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * May 20, 2010
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5B__flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5B_t *bt, unsigned H5_ATTR_UNUSED * flags_ptr)
+H5B__image_len(const void *_thing, size_t *image_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr)
{
+ const H5B_t *bt = (const H5B_t *)_thing; /* Pointer to the B-tree node */
H5B_shared_t *shared; /* Pointer to shared B-tree info */
- herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_STATIC
+ FUNC_ENTER_STATIC_NOERR
- /* check arguments */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
+ /* Check arguments */
HDassert(bt);
+ HDassert(image_len);
+
+ /* Get shared info for B-tree */
shared = (H5B_shared_t *)H5UC_GET_OBJ(bt->rc_shared);
HDassert(shared);
- HDassert(shared->type);
- HDassert(shared->type->encode);
-
- if(bt->cache_info.is_dirty) {
- uint8_t *p; /* Pointer into raw data buffer */
- uint8_t *native; /* Pointer to native keys */
- unsigned u; /* Local index variable */
-
- p = shared->page;
-
- /* magic number */
- HDmemcpy(p, H5B_MAGIC, (size_t)H5_SIZEOF_MAGIC);
- p += 4;
-
- /* node type and level */
- *p++ = (uint8_t)shared->type->id;
- H5_CHECK_OVERFLOW(bt->level, unsigned, uint8_t);
- *p++ = (uint8_t)bt->level;
-
- /* entries used */
- UINT16ENCODE(p, bt->nchildren);
-
- /* sibling pointers */
- H5F_addr_encode(f, &p, bt->left);
- H5F_addr_encode(f, &p, bt->right);
-
- /* child keys and pointers */
- native = bt->native;
- for(u = 0; u < bt->nchildren; ++u) {
- /* encode the key */
- if(shared->type->encode(shared, p, native) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTENCODE, FAIL, "unable to encode B-tree key")
- p += shared->sizeof_rkey;
- native += shared->type->sizeof_nkey;
-
- /* encode the child address */
- H5F_addr_encode(f, &p, bt->child[u]);
- } /* end for */
- if(bt->nchildren > 0) {
- /* Encode the final key */
- if(shared->type->encode(shared, p, native) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTENCODE, FAIL, "unable to encode B-tree key")
- } /* end if */
-
- /*
- * Write the disk page. We always write the header, but we don't
- * bother writing data for the child entries that don't exist or
- * for the final unchanged children.
- */
- if(H5F_block_write(f, H5FD_MEM_BTREE, addr, shared->sizeof_rnode, dxpl_id, shared->page) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTFLUSH, FAIL, "unable to save B-tree node to disk")
-
- bt->cache_info.is_dirty = FALSE;
- } /* end if */
- if(destroy)
- if(H5B__dest(f, bt) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to destroy B-tree node")
+ /* Set the image length size */
+ *image_len = shared->sizeof_rnode;
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5B__flush() */
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5B__image_len() */
/*-------------------------------------------------------------------------
- * Function: H5B__dest
+ * Function: H5B__serialize
*
- * Purpose: Destroys a B-tree node in memory.
+ * Purpose: Serialize the data structure for writing to disk.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Jan 15 2003
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Mar 24, 2008
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5B__dest(H5F_t *f, H5B_t *bt)
+H5B__serialize(const H5F_t *f, void *_image, size_t H5_ATTR_UNUSED len,
+ void *_thing)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ H5B_t *bt = (H5B_t *)_thing; /* Pointer to the B-tree node */
+ H5B_shared_t *shared; /* Pointer to shared B-tree info */
+ uint8_t *image = (uint8_t *)_image; /* Pointer into image buffer */
+ uint8_t *native; /* Pointer to native keys */
+ unsigned u; /* Local index counter */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_STATIC
- /*
- * Check arguments.
- */
- HDassert(f);
+ /* check arguments */
+ HDassert(image);
HDassert(bt);
HDassert(bt->rc_shared);
+ shared = (H5B_shared_t *)H5UC_GET_OBJ(bt->rc_shared);
+ HDassert(shared);
+ HDassert(shared->type);
+ HDassert(shared->type->encode);
- /* If we're going to free the space on disk, the address must be valid */
- HDassert(!bt->cache_info.free_file_space_on_destroy || H5F_addr_defined(bt->cache_info.addr));
+ /* magic number */
+ HDmemcpy(image, H5B_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ image += 4;
- /* Check for freeing file space for B-tree node */
- if(bt->cache_info.free_file_space_on_destroy) {
- H5B_shared_t *shared; /* Pointer to shared B-tree info */
+ /* node type and level */
+ *image++ = (uint8_t)shared->type->id;
+ H5_CHECK_OVERFLOW(bt->level, unsigned, uint8_t);
+ *image++ = (uint8_t)bt->level;
- /* Get the pointer to the shared B-tree info */
- shared = (H5B_shared_t *)H5UC_GET_OBJ(bt->rc_shared);
- HDassert(shared);
+ /* entries used */
+ UINT16ENCODE(image, bt->nchildren);
- /* Release the space on disk */
- /* (XXX: Nasty usage of internal DXPL value! -QAK) */
- if(H5MF_xfree(f, H5FD_MEM_BTREE, H5AC_dxpl_id, bt->cache_info.addr, (hsize_t)shared->sizeof_rnode) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free B-tree node")
+ /* sibling pointers */
+ H5F_addr_encode(f, &image, bt->left);
+ H5F_addr_encode(f, &image, bt->right);
+
+ /* child keys and pointers */
+ native = bt->native;
+ for(u = 0; u < bt->nchildren; ++u) {
+ /* encode the key */
+ if(shared->type->encode(shared, image, native) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTENCODE, FAIL, "unable to encode B-tree key")
+ image += shared->sizeof_rkey;
+ native += shared->type->sizeof_nkey;
+
+ /* encode the child address */
+ H5F_addr_encode(f, &image, bt->child[u]);
+ } /* end for */
+ if(bt->nchildren > 0) {
+ /* Encode the final key */
+ if(shared->type->encode(shared, image, native) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTENCODE, FAIL, "unable to encode B-tree key")
} /* end if */
- /* Destroy B-tree node */
- if(H5B__node_dest(bt) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to destroy B-tree node")
+ /* Sanity check */
+ HDassert((size_t)((const uint8_t *)image - (const uint8_t *)_image) <= len);
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5B__dest() */
+} /* end H5B__serialize() */
/*-------------------------------------------------------------------------
- * Function: H5B__clear
+ * Function: H5B__free_icr
*
- * Purpose: Mark a B-tree node in memory as non-dirty.
+ * Purpose: Destroy/release an "in core representation" of a data structure
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Mar 20 2003
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Mar 26, 2008
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5B__clear(H5F_t *f, H5B_t *bt, hbool_t destroy)
+H5B__free_icr(void *thing)
{
- herr_t ret_value = SUCCEED;
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_STATIC
- /*
- * Check arguments.
- */
- HDassert(bt);
-
- /* Reset the dirty flag. */
- bt->cache_info.is_dirty = FALSE;
+ /* Check arguments */
+ HDassert(thing);
- if(destroy)
- if(H5B__dest(f, bt) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to destroy B-tree node")
+ /* Destroy B-tree node */
+ if(H5B__node_dest((H5B_t *)thing) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to destroy B-tree node")
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5B__clear() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5B__compute_size
- *
- * Purpose: Compute the size in bytes of the specified instance of
- * H5B_t on disk, and return it in *len_ptr. On failure,
- * the value of *len_ptr is undefined.
- *
- * Return: SUCCEED (Can't fail)
- *
- * Programmer: John Mainzer
- * 5/13/04
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5B__compute_size(const H5F_t H5_ATTR_UNUSED *f, const H5B_t *bt, size_t *size_ptr)
-{
- H5B_shared_t *shared; /* Pointer to shared B-tree info */
-
- FUNC_ENTER_NOAPI_NOINIT_NOERR
-
- /* check arguments */
- HDassert(f);
- HDassert(bt);
- HDassert(bt->rc_shared);
- shared = (H5B_shared_t *)H5UC_GET_OBJ(bt->rc_shared);
- HDassert(shared);
- HDassert(shared->type);
- HDassert(size_ptr);
-
- /* Set size value */
- *size_ptr = shared->sizeof_rnode;
-
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5B__compute_size() */
-
+} /* end H5B__free_icr() */
diff --git a/src/H5Bdbg.c b/src/H5Bdbg.c
index 276156e..34e8465 100644
--- a/src/H5Bdbg.c
+++ b/src/H5Bdbg.c
@@ -93,7 +93,7 @@ H5B_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, int f
cache_udata.type = type;
cache_udata.rc_shared = rc_shared;
cache_udata.parent = NULL;
- if(NULL == (bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, addr, &cache_udata, H5AC_READ)))
+ if(NULL == (bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, addr, &cache_udata, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree node")
/*
@@ -210,7 +210,7 @@ H5B__assert(H5F_t *f, hid_t dxpl_id, haddr_t addr, const H5B_class_t *type, void
cache_udata.f = f;
cache_udata.type = type;
cache_udata.rc_shared = rc_shared;
- bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, addr, &cache_udata, H5AC_READ);
+ bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, addr, &cache_udata, H5AC__READ_ONLY_FLAG);
HDassert(bt);
shared = (H5B_shared_t *)H5UC_GET_OBJ(bt->rc_shared);
HDassert(shared);
@@ -231,7 +231,7 @@ H5B__assert(H5F_t *f, hid_t dxpl_id, haddr_t addr, const H5B_class_t *type, void
* test.
*/
for(ncell = 0; cur; ncell++) {
- bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, cur->addr, &cache_udata, H5AC_READ);
+ bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, cur->addr, &cache_udata, H5AC__READ_ONLY_FLAG);
HDassert(bt);
/* Check node header */
diff --git a/src/H5C.c b/src/H5C.c
index f1a51f1..66aaae0 100644
--- a/src/H5C.c
+++ b/src/H5C.c
@@ -86,12 +86,23 @@
#include "H5FDprivate.h" /* File drivers */
#include "H5FLprivate.h" /* Free Lists */
#include "H5Iprivate.h" /* IDs */
+#include "H5MFprivate.h" /* File memory management */
#include "H5MMprivate.h" /* Memory management */
#include "H5Pprivate.h" /* Property lists */
#include "H5SLprivate.h" /* Skip lists */
/*
+ * Private macros.
+ */
+#if H5C_DO_MEMORY_SANITY_CHECKS
+#define H5C_IMAGE_EXTRA_SPACE 8
+#define H5C_IMAGE_SANITY_VALUE "DeadBeef"
+#else /* H5C_DO_MEMORY_SANITY_CHECKS */
+#define H5C_IMAGE_EXTRA_SPACE 0
+#endif /* H5C_DO_MEMORY_SANITY_CHECKS */
+
+/*
* Private file-scope variables.
*/
@@ -110,27 +121,21 @@ H5FL_DEFINE_STATIC(haddr_t);
*/
static herr_t H5C__auto_adjust_cache_size(H5F_t * f,
- hid_t primary_dxpl_id,
- hid_t secondary_dxpl_id,
- hbool_t write_permitted,
- hbool_t * first_flush_ptr);
+ hid_t dxpl_id,
+ hbool_t write_permitted);
static herr_t H5C__autoadjust__ageout(H5F_t * f,
+ hid_t dxpl_id,
double hit_rate,
enum H5C_resize_status * status_ptr,
size_t * new_max_cache_size_ptr,
- hid_t primary_dxpl_id,
- hid_t secondary_dxpl_id,
- hbool_t write_permitted,
- hbool_t * first_flush_ptr);
+ hbool_t write_permitted);
static herr_t H5C__autoadjust__ageout__cycle_epoch_marker(H5C_t * cache_ptr);
static herr_t H5C__autoadjust__ageout__evict_aged_out_entries(H5F_t * f,
- hid_t primary_dxpl_id,
- hid_t secondary_dxpl_id,
- hbool_t write_permitted,
- hbool_t * first_flush_ptr);
+ hid_t dxpl_id,
+ hbool_t write_permitted);
static herr_t H5C__autoadjust__ageout__insert_new_marker(H5C_t * cache_ptr);
@@ -142,19 +147,16 @@ static herr_t H5C__flash_increase_cache_size(H5C_t * cache_ptr,
size_t old_entry_size,
size_t new_entry_size);
-static herr_t H5C_flush_single_entry(H5F_t * f,
- hid_t primary_dxpl_id,
- hid_t secondary_dxpl_id,
- const H5C_class_t * type_ptr,
- haddr_t addr,
- unsigned flags,
- hbool_t * first_flush_ptr,
- hbool_t del_entry_from_slist_on_destroy);
+static herr_t H5C_flush_single_entry(const H5F_t * f,
+ hid_t dxpl_id,
+ haddr_t addr,
+ unsigned flags,
+ hbool_t del_entry_from_slist_on_destroy,
+ int64_t *entry_size_change_ptr);
-static herr_t H5C_flush_invalidate_cache(H5F_t * f,
- hid_t primary_dxpl_id,
- hid_t secondary_dxpl_id,
- unsigned flags);
+static herr_t H5C_flush_invalidate_cache(const H5F_t * f,
+ hid_t dxpl_id,
+ unsigned flags);
static void * H5C_load_entry(H5F_t * f,
hid_t dxpl_id,
@@ -163,37 +165,41 @@ static void * H5C_load_entry(H5F_t * f,
void * udata);
static herr_t H5C_make_space_in_cache(H5F_t * f,
- hid_t primary_dxpl_id,
- hid_t secondary_dxpl_id,
- size_t space_needed,
- hbool_t write_permitted,
- hbool_t * first_flush_ptr);
+ hid_t dxpl_id,
+ size_t space_needed,
+ hbool_t write_permitted);
static herr_t H5C_tag_entry(H5C_t * cache_ptr,
H5C_cache_entry_t * entry_ptr,
hid_t dxpl_id);
-static herr_t H5C_mark_tagged_entries(H5C_t * cache_ptr,
+static herr_t H5C_mark_tagged_entries(H5C_t * cache_ptr,
haddr_t tag,
hbool_t mark_clean);
-static herr_t H5C_mark_tagged_entries_cork(H5C_t *cache_ptr,
- haddr_t obj_addr,
- hbool_t val);
-static herr_t H5C_flush_marked_entries(H5F_t * f,
- hid_t primary_dxpl_id,
- hid_t secondary_dxpl_id,
- H5C_t * cache_ptr);
+static herr_t H5C_mark_tagged_entries_cork(H5C_t *cache_ptr,
+ haddr_t obj_addr,
+ hbool_t val);
-static herr_t H5C_evict_marked_entries(H5F_t * f,
- hid_t primary_dxpl_id,
- hid_t secondary_dxpl_id,
+static herr_t H5C_flush_marked_entries(H5F_t * f,
+ hid_t dxpl_id,
H5C_t * cache_ptr);
static herr_t H5C__mark_flush_dep_dirty(H5C_cache_entry_t * entry);
static herr_t H5C__mark_flush_dep_clean(H5C_cache_entry_t * entry);
+static herr_t H5C_verify_len_eoa (H5F_t *f,
+ const H5C_class_t * type,
+ haddr_t addr,
+ size_t *len,
+ htri_t actual);
+
+#if H5C_DO_SLIST_SANITY_CHECKS
+static hbool_t H5C_entry_in_skip_list(H5C_t * cache_ptr,
+ H5C_cache_entry_t *target_ptr);
+#endif /* H5C_DO_SLIST_SANITY_CHECKS */
+
#if H5C_DO_EXTREME_SANITY_CHECKS
static herr_t H5C_validate_lru_list(H5C_t * cache_ptr);
static herr_t H5C_validate_pinned_entry_list(H5C_t * cache_ptr);
@@ -223,25 +229,61 @@ static void H5C__assert_flush_dep_nocycle(H5C_cache_entry_t * entry,
#define H5C__EPOCH_MARKER_TYPE H5C__MAX_NUM_TYPE_IDS
-static void *H5C_epoch_marker_load(H5F_t *f, hid_t dxpl_id, haddr_t addr,
- void *udata);
-static herr_t H5C_epoch_marker_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest,
- haddr_t addr, void *thing,
- unsigned *flags_ptr);
-static herr_t H5C_epoch_marker_dest(H5F_t *f, void *thing);
-static herr_t H5C_epoch_marker_clear(H5F_t *f, void *thing, hbool_t dest);
-static herr_t H5C_epoch_marker_notify(H5C_notify_action_t action, void *thing);
-static herr_t H5C_epoch_marker_size(const H5F_t *f, const void *thing, size_t *size_ptr);
+static herr_t H5C__epoch_marker_get_load_size(const void *image_ptr,
+ const void *udata_ptr,
+ size_t *image_len_ptr,
+ size_t *actual_len,
+ hbool_t *compressed_ptr,
+ size_t *compressed_len_ptr);
+static htri_t H5C__epoch_marker_verify_chksum(const void *image_ptr,
+ size_t len,
+ void *udata_ptr);
+static void * H5C__epoch_marker_deserialize(const void * image_ptr,
+ size_t len,
+ void * udata,
+ hbool_t * dirty_ptr);
+static herr_t H5C__epoch_marker_image_len(const void * thing,
+ size_t *image_len_ptr,
+ hbool_t *compressed_ptr,
+ size_t *compressed_len_ptr);
+static herr_t H5C__epoch_marker_pre_serialize(const H5F_t *f,
+ hid_t dxpl_id,
+ void * thing,
+ haddr_t addr,
+ size_t len,
+ size_t compressed_len,
+ haddr_t * new_addr_ptr,
+ size_t * new_len_ptr,
+ size_t * new_compressed_len_ptr,
+ unsigned * flags_ptr);
+static herr_t H5C__epoch_marker_serialize(const H5F_t *f,
+ void * image_ptr,
+ size_t len,
+ void * thing);
+static herr_t H5C__epoch_marker_notify(H5C_notify_action_t action, void *thing);
+static herr_t H5C__epoch_marker_free_icr(void * thing);
+
+static herr_t H5C__epoch_marker_clear(const H5F_t *f, void * thing,
+ hbool_t about_to_destroy);
+static herr_t H5C__epoch_marker_fsf_size(const void H5_ATTR_UNUSED * thing,
+ size_t H5_ATTR_UNUSED * fsf_size_ptr);
const H5C_class_t epoch_marker_class =
{
- /* id = */ H5C__EPOCH_MARKER_TYPE,
- /* load = */ &H5C_epoch_marker_load,
- /* flush = */ &H5C_epoch_marker_flush,
- /* dest = */ &H5C_epoch_marker_dest,
- /* clear = */ &H5C_epoch_marker_clear,
- /* notify = */&H5C_epoch_marker_notify,
- /* size = */ &H5C_epoch_marker_size
+ /* id = */ H5C__EPOCH_MARKER_TYPE,
+ /* name = */ "epoch marker",
+ /* mem_type = */ H5FD_MEM_DEFAULT, /* value doesn't matter */
+ /* flags = */ H5AC__CLASS_NO_FLAGS_SET,
+ /* get_load_size = */ H5C__epoch_marker_get_load_size,
+ /* verify_chksum = */ H5C__epoch_marker_verify_chksum,
+ /* deserialize = */ H5C__epoch_marker_deserialize,
+ /* image_len = */ H5C__epoch_marker_image_len,
+ /* pre_serialize = */ H5C__epoch_marker_pre_serialize,
+ /* serialize = */ H5C__epoch_marker_serialize,
+ /* notify = */ H5C__epoch_marker_notify,
+ /* free_icr = */ H5C__epoch_marker_free_icr,
+ /* clear = */ H5C__epoch_marker_clear,
+ /* fsf_size = */ H5C__epoch_marker_fsf_size,
};
@@ -254,107 +296,127 @@ const H5C_class_t epoch_marker_class =
* JRM - 11/16/04
*
***************************************************************************/
-
-static void *
-H5C_epoch_marker_load(H5F_t H5_ATTR_UNUSED * f,
- hid_t H5_ATTR_UNUSED dxpl_id,
- haddr_t H5_ATTR_UNUSED addr,
- void H5_ATTR_UNUSED * udata)
+static herr_t
+H5C__epoch_marker_get_load_size(const void H5_ATTR_UNUSED *image_ptr, const void H5_ATTR_UNUSED *udata_ptr,
+ size_t H5_ATTR_UNUSED *image_len_ptr, size_t H5_ATTR_UNUSED *actual_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_len_ptr)
{
- void * ret_value = NULL; /* Return value */
+ FUNC_ENTER_STATIC_NOERR /* Yes, even though this pushes an error on the stack */
- FUNC_ENTER_NOAPI_NOINIT
+ HERROR(H5E_CACHE, H5E_SYSTEM, "called unreachable fcn.");
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, NULL, "called unreachable fcn.")
+ FUNC_LEAVE_NOAPI(FAIL)
+} /* end H5C__epoch_marker_get_load_size() */
-done:
+
+static htri_t
+H5C__epoch_marker_verify_chksum(const void H5_ATTR_UNUSED *image_ptr, size_t H5_ATTR_UNUSED len,
+ void H5_ATTR_UNUSED *udata_ptr)
+{
+ FUNC_ENTER_STATIC_NOERR /* Yes, even though this pushes an error on the stack */
- FUNC_LEAVE_NOAPI(ret_value)
-}
+ HERROR(H5E_CACHE, H5E_SYSTEM, "called unreachable fcn.");
+ FUNC_LEAVE_NOAPI(FALSE)
+} /* end H5C__epoch_marker_verify_chksum() */
-static herr_t
-H5C_epoch_marker_flush(H5F_t H5_ATTR_UNUSED *f,
- hid_t H5_ATTR_UNUSED dxpl_id,
- hbool_t H5_ATTR_UNUSED dest,
- haddr_t H5_ATTR_UNUSED addr,
- void H5_ATTR_UNUSED *thing,
- unsigned H5_ATTR_UNUSED * flags_ptr)
+static void *
+H5C__epoch_marker_deserialize(const void H5_ATTR_UNUSED * image_ptr, size_t H5_ATTR_UNUSED len,
+ void H5_ATTR_UNUSED * udata, hbool_t H5_ATTR_UNUSED * dirty_ptr)
{
- herr_t ret_value = FAIL; /* Return value */
+ FUNC_ENTER_STATIC_NOERR /* Yes, even though this pushes an error on the stack */
- FUNC_ENTER_NOAPI_NOINIT
+ HERROR(H5E_CACHE, H5E_SYSTEM, "called unreachable fcn.");
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "called unreachable fcn.")
+ FUNC_LEAVE_NOAPI(NULL)
+} /* end H5C__epoch_marker_deserialize() */
-done:
+
+static herr_t
+H5C__epoch_marker_image_len(const void H5_ATTR_UNUSED *thing,
+ size_t H5_ATTR_UNUSED *image_len_ptr, hbool_t H5_ATTR_UNUSED *compressed_ptr,
+ size_t H5_ATTR_UNUSED *compressed_len_ptr)
+{
+ FUNC_ENTER_STATIC_NOERR /* Yes, even though this pushes an error on the stack */
- FUNC_LEAVE_NOAPI(ret_value)
-}
+ HERROR(H5E_CACHE, H5E_SYSTEM, "called unreachable fcn.");
+ FUNC_LEAVE_NOAPI(FAIL)
+} /* end H5C__epoch_marker_image_len() */
static herr_t
-H5C_epoch_marker_dest(H5F_t H5_ATTR_UNUSED * f,
- void H5_ATTR_UNUSED * thing)
+H5C__epoch_marker_pre_serialize(const H5F_t H5_ATTR_UNUSED *f, hid_t H5_ATTR_UNUSED dxpl_id,
+ void H5_ATTR_UNUSED *thing, haddr_t H5_ATTR_UNUSED addr, size_t H5_ATTR_UNUSED len,
+ size_t H5_ATTR_UNUSED compressed_len, haddr_t H5_ATTR_UNUSED *new_addr_ptr,
+ size_t H5_ATTR_UNUSED *new_len_ptr, size_t H5_ATTR_UNUSED *new_compressed_len_ptr,
+ unsigned H5_ATTR_UNUSED *flags_ptr)
{
- herr_t ret_value = FAIL; /* Return value */
+ FUNC_ENTER_STATIC_NOERR /* Yes, even though this pushes an error on the stack */
- FUNC_ENTER_NOAPI_NOINIT
-
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "called unreachable fcn.")
-
-done:
+ HERROR(H5E_CACHE, H5E_SYSTEM, "called unreachable fcn.");
- FUNC_LEAVE_NOAPI(ret_value)
-}
+ FUNC_LEAVE_NOAPI(FAIL)
+} /* end H5C__epoch_marker_pre_serialize() */
+
static herr_t
-H5C_epoch_marker_clear(H5F_t H5_ATTR_UNUSED * f,
- void H5_ATTR_UNUSED * thing,
- hbool_t H5_ATTR_UNUSED dest)
+H5C__epoch_marker_serialize(const H5F_t H5_ATTR_UNUSED *f, void H5_ATTR_UNUSED *image_ptr,
+ size_t H5_ATTR_UNUSED len, void H5_ATTR_UNUSED *thing)
{
- herr_t ret_value = FAIL; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT
-
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "called unreachable fcn.")
+ FUNC_ENTER_STATIC_NOERR /* Yes, even though this pushes an error on the stack */
-done:
+ HERROR(H5E_CACHE, H5E_SYSTEM, "called unreachable fcn.");
- FUNC_LEAVE_NOAPI(ret_value)
-}
+ FUNC_LEAVE_NOAPI(FAIL)
+} /* end H5C__epoch_marker_serialize() */
+
static herr_t
-H5C_epoch_marker_notify(H5C_notify_action_t H5_ATTR_UNUSED action,
+H5C__epoch_marker_notify(H5C_notify_action_t H5_ATTR_UNUSED action,
void H5_ATTR_UNUSED * thing)
{
- herr_t ret_value = FAIL; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC_NOERR /* Yes, even though this pushes an error on the stack */
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "called unreachable fcn.")
+ HERROR(H5E_CACHE, H5E_SYSTEM, "called unreachable fcn.");
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-}
+ FUNC_LEAVE_NOAPI(FAIL)
+} /* end H5C__epoch_marker_notify() */
+
static herr_t
-H5C_epoch_marker_size(const H5F_t H5_ATTR_UNUSED * f,
- const void H5_ATTR_UNUSED * thing,
- size_t H5_ATTR_UNUSED * size_ptr)
+H5C__epoch_marker_free_icr(void H5_ATTR_UNUSED * thing)
{
- herr_t ret_value = FAIL; /* Return value */
+ FUNC_ENTER_STATIC_NOERR /* Yes, even though this pushes an error on the stack */
- FUNC_ENTER_NOAPI_NOINIT
+ HERROR(H5E_CACHE, H5E_SYSTEM, "called unreachable fcn.");
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "called unreachable fcn.")
+ FUNC_LEAVE_NOAPI(FAIL)
+} /* end H5C__epoch_marker_free_icr() */
-done:
+
+static herr_t
+H5C__epoch_marker_clear(const H5F_t H5_ATTR_UNUSED *f, void H5_ATTR_UNUSED * thing, hbool_t H5_ATTR_UNUSED about_to_destroy)
+{
+ FUNC_ENTER_STATIC_NOERR /* Yes, even though this pushes an error on the stack */
+
+ HERROR(H5E_CACHE, H5E_SYSTEM, "called unreachable fcn.");
+
+ FUNC_LEAVE_NOAPI(FAIL)
+} /* end H5C__epoch_marker_clear() */
+
+
+static herr_t
+H5C__epoch_marker_fsf_size(const void H5_ATTR_UNUSED * thing, size_t H5_ATTR_UNUSED *fsf_size_ptr)
+{
+ FUNC_ENTER_STATIC_NOERR /* Yes, even though this pushes an error on the stack */
+
+ HERROR(H5E_CACHE, H5E_SYSTEM, "called unreachable fcn.");
+
+ FUNC_LEAVE_NOAPI(FAIL)
+} /* end H5C__epoch_marker_fsf_size() */
- FUNC_LEAVE_NOAPI(ret_value)
-}
/*-------------------------------------------------------------------------
@@ -438,21 +500,46 @@ done:
* Programmer: John Mainzer
* 3/17/10
*
+ * Changes: Ported code to detect next entry status changes as the
+ * the result of a flush from the serial code in the scan of
+ * the LRU. Also added code to detect and adapt to the
+ * removal from the cache of the next entry in the scan of
+ * the LRU.
+ *
+ * Note that at present, all of these changes should not
+ * be required as the operations on entries as they are
+ * flushed that can cause these condiditions are not premitted
+ * in the parallel case. However, Quincey indicates that
+ * this may change, and thus has requested the modification.
+ *
+ * Note the assert(FALSE) in the if statement whose body
+ * restarts the scan of the LRU. As the body of the if
+ * statement should be unreachable, it should never be
+ * triggered until the constraints on the parallel case
+ * are relaxed. Please remove the assertion at that time.
+ *
+ * Also added warning on the Pinned Entry List scan, as it
+ * is potentially subject to the same issue. As there is
+ * no cognate of this scan in the serial code, I don't have
+ * a fix to port to it.
+ *
+ * JRM -- 4/10/19
+ *
*-------------------------------------------------------------------------
*/
#ifdef H5_HAVE_PARALLEL
#define H5C_APPLY_CANDIDATE_LIST__DEBUG 0
herr_t
H5C_apply_candidate_list(H5F_t * f,
- hid_t primary_dxpl_id,
- hid_t secondary_dxpl_id,
+ hid_t dxpl_id,
H5C_t * cache_ptr,
int num_candidates,
haddr_t * candidates_list_ptr,
int mpi_rank,
int mpi_size)
{
- hbool_t first_flush = FALSE;
+ hbool_t restart_scan;
+ hbool_t prev_is_dirty;
int i;
int m;
int n;
@@ -472,6 +559,7 @@ H5C_apply_candidate_list(H5F_t * f,
int * candidate_assignment_table = NULL;
haddr_t addr;
H5C_cache_entry_t * clear_ptr = NULL;
+ H5C_cache_entry_t * next_ptr = NULL;
H5C_cache_entry_t * entry_ptr = NULL;
H5C_cache_entry_t * flush_ptr = NULL;
H5C_cache_entry_t * delayed_ptr = NULL;
@@ -649,16 +737,29 @@ H5C_apply_candidate_list(H5F_t * f,
* should be reworked to account for additional cases.
* ===================================================================== */
+ HDassert(entries_to_flush >= 0);
+
+ restart_scan = FALSE;
entries_examined = 0;
initial_list_len = cache_ptr->LRU_list_len;
entry_ptr = cache_ptr->LRU_tail_ptr;
/* Examine each entry in the LRU list */
- while((entry_ptr != NULL) && (entries_examined <= initial_list_len) &&
- ((entries_cleared + entries_flushed) < num_candidates)) {
+ while ( ( entry_ptr != NULL )
+ &&
+ ( entries_examined <= (entries_to_flush + 1) * initial_list_len )
+ &&
+ ( (entries_cleared + entries_flushed) < num_candidates ) ) {
+
+ if ( entry_ptr->prev != NULL )
+ prev_is_dirty = entry_ptr->prev->is_dirty;
/* If this process needs to clear this entry. */
if(entry_ptr->clear_on_unprotect) {
+
+ HDassert(entry_ptr->is_dirty);
+
+ next_ptr = entry_ptr->next;
entry_ptr->clear_on_unprotect = FALSE;
clear_ptr = entry_ptr;
entry_ptr = entry_ptr->prev;
@@ -669,20 +770,26 @@ H5C_apply_candidate_list(H5F_t * f,
(long long)clear_ptr->addr);
#endif /* H5C_APPLY_CANDIDATE_LIST__DEBUG */
+ /* No need to check for the next entry in the scan being
+ * removed from the cache, as this call to H5C_flush_single_entry()
+ * will not call either the pre_serialize or serialize callbacks.
+ */
+
if(H5C_flush_single_entry(f,
- primary_dxpl_id,
- secondary_dxpl_id,
- clear_ptr->type,
+ dxpl_id,
clear_ptr->addr,
H5C__FLUSH_CLEAR_ONLY_FLAG,
- &first_flush,
- TRUE) < 0)
+ TRUE,
+ NULL) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Can't clear entry.")
} /* end if */
/* Else, if this process needs to flush this entry. */
else if (entry_ptr->flush_immediately) {
+ HDassert(entry_ptr->is_dirty);
+
+ next_ptr = entry_ptr->next;
entry_ptr->flush_immediately = FALSE;
flush_ptr = entry_ptr;
entry_ptr = entry_ptr->prev;
@@ -693,22 +800,94 @@ H5C_apply_candidate_list(H5F_t * f,
(long long)flush_ptr->addr);
#endif /* H5C_APPLY_CANDIDATE_LIST__DEBUG */
+ /* reset entries_removed_counter and
+ * last_entry_removed_ptr prior to the call to
+ * H5C_flush_single_entry() so that we can spot
+ * unexpected removals of entries from the cache,
+ * and set the restart_scan flag if proceeding
+ * would be likely to cause us to scan an entry
+ * that is no longer in the cache.
+ *
+ * Note that as of this writing (April 2015) this
+ * case cannot occur in the parallel case. However
+ * Quincey is making noises about changing this, hence
+ * the insertion of this test.
+ *
+ * Note also that there is no test code to verify
+ * that this code actually works (although similar code
+ * in the serial version exists and is tested).
+ *
+ * Implementing a test will likely require implementing
+ * flush op like facilities in the parallel tests. At
+ * a guess this will not be terribly painful, but it
+ * will take a bit of time.
+ */
+ cache_ptr->entries_removed_counter = 0;
+ cache_ptr->last_entry_removed_ptr = NULL;
+
if(H5C_flush_single_entry(f,
- primary_dxpl_id,
- secondary_dxpl_id,
- flush_ptr->type,
+ dxpl_id,
flush_ptr->addr,
H5C__NO_FLAGS_SET,
- &first_flush,
- TRUE) < 0)
+ TRUE,
+ NULL) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Can't flush entry.")
+
+ if ( ( cache_ptr->entries_removed_counter > 1 ) ||
+ ( cache_ptr->last_entry_removed_ptr == entry_ptr ) )
+
+ restart_scan = TRUE;
+
} /* end else-if */
/* Otherwise, no action to be taken on this entry. Grab the next. */
else {
entry_ptr = entry_ptr->prev;
+
+ if ( entry_ptr != NULL )
+ next_ptr = entry_ptr->next;
+
} /* end else */
+ if ( ( entry_ptr != NULL )
+ &&
+ ( ( restart_scan )
+ ||
+ ( entry_ptr->is_dirty != prev_is_dirty )
+ ||
+ ( entry_ptr->next != next_ptr )
+ ||
+ ( entry_ptr->is_protected )
+ ||
+ ( entry_ptr->is_pinned )
+ )
+ ) {
+
+ /* something has happened to the LRU -- start over
+ * from the tail.
+ *
+ * Recall that this code should be un-reachable at present,
+ * as all the operations by entries on flush that could cause
+ * it to be reachable are disallowed in the parallel case at
+ * present. Hence the following assertion which should be
+ * removed if the above changes.
+ */
+
+ HDassert( ! restart_scan );
+ HDassert( entry_ptr->is_dirty == prev_is_dirty );
+ HDassert( entry_ptr->next == next_ptr );
+ HDassert( ! entry_ptr->is_protected );
+ HDassert( ! entry_ptr->is_pinned );
+
+ HDassert(FALSE); /* see comment above */
+
+ restart_scan = FALSE;
+ entry_ptr = cache_ptr->LRU_tail_ptr;
+/*
+ H5C__UPDATE_STATS_FOR_LRU_SCAN_RESTART(cache_ptr)
+*/
+ }
+
entries_examined++;
} /* end while */
@@ -720,6 +899,30 @@ H5C_apply_candidate_list(H5F_t * f,
/* It is also possible that some of the cleared entries are on the
* pinned list. Must scan that also.
+ *
+ * WARNING:
+ *
+ * As we now allow unpinning, and removal of other entries as a side
+ * effect of flushing an entry, it is possible that the next entry
+ * in a PEL scan could either be no longer pinned, or no longer in
+ * the cache by the time we get to it.
+ *
+ * At present, this is not possible in this case, as we disallow such
+ * operations in the parallel version of the library. However, Quincey
+ * has been making noises about relaxing this. If and when he does,
+ * we have a potential problem here.
+ *
+ * The same issue exists in the serial cache, and there are tests
+ * to detect this problem when it occurs, and adjust to it. As seen
+ * above in the LRU scan, I have ported such tests to the parallel
+ * code where a close cognate exists in the serial code.
+ *
+ * I haven't done so here, as there are no PEL scans where the problem
+ * can occur in the serial code. Needless to say, this will have to
+ * be repaired if the constraints on pre_serialize and serialize
+ * callbacks are relaxed in the parallel version of the metadata cache.
+ *
+ * JRM -- 4/1/15
*/
#if H5C_APPLY_CANDIDATE_LIST__DEBUG
@@ -787,14 +990,12 @@ H5C_apply_candidate_list(H5F_t * f,
#endif /* H5C_APPLY_CANDIDATE_LIST__DEBUG */
if(H5C_flush_single_entry(f,
- primary_dxpl_id,
- secondary_dxpl_id,
- clear_ptr->type,
- clear_ptr->addr,
- H5C__FLUSH_CLEAR_ONLY_FLAG,
- &first_flush,
- TRUE) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Can't clear entry.")
+ dxpl_id,
+ clear_ptr->addr,
+ H5C__FLUSH_CLEAR_ONLY_FLAG,
+ TRUE,
+ NULL) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Can't clear entry.")
} /* end else-if */
/* Else, if this process needs to independently flush this entry. */
@@ -810,14 +1011,12 @@ H5C_apply_candidate_list(H5F_t * f,
#endif /* H5C_APPLY_CANDIDATE_LIST__DEBUG */
if(H5C_flush_single_entry(f,
- primary_dxpl_id,
- secondary_dxpl_id,
- flush_ptr->type,
- flush_ptr->addr,
- H5C__NO_FLAGS_SET,
- &first_flush,
- TRUE) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Can't flush entry.")
+ dxpl_id,
+ flush_ptr->addr,
+ H5C__NO_FLAGS_SET,
+ TRUE,
+ NULL) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Can't clear entry.")
} /* end else-if */
} /* end if */
@@ -858,13 +1057,11 @@ H5C_apply_candidate_list(H5F_t * f,
} /* end if */
if(H5C_flush_single_entry(f,
- primary_dxpl_id,
- secondary_dxpl_id,
- delayed_ptr->type,
+ dxpl_id,
delayed_ptr->addr,
H5C__NO_FLAGS_SET,
- &first_flush,
- TRUE) < 0)
+ TRUE,
+ NULL) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL,
"Can't flush entry collectively.")
@@ -1208,6 +1405,9 @@ H5C_create(size_t max_cache_size,
/* Tagging Field Initializations */
cache_ptr->ignore_tags = FALSE;
+ cache_ptr->slist_changed = FALSE;
+ cache_ptr->slist_change_in_pre_serialize = FALSE;
+ cache_ptr->slist_change_in_serialize = FALSE;
cache_ptr->slist_len = 0;
cache_ptr->slist_size = (size_t)0;
@@ -1221,6 +1421,9 @@ H5C_create(size_t max_cache_size,
(cache_ptr->index)[i] = NULL;
}
+ cache_ptr->entries_removed_counter = 0;
+ cache_ptr->last_entry_removed_ptr = NULL;
+
cache_ptr->pl_len = 0;
cache_ptr->pl_size = (size_t)0;
cache_ptr->pl_head_ptr = NULL;
@@ -1295,11 +1498,8 @@ H5C_create(size_t max_cache_size,
/* Set non-zero/FALSE/NULL fields for epoch markers */
for ( i = 0; i < H5C__MAX_EPOCH_MARKERS; i++ )
{
- (cache_ptr->epoch_marker_active)[i] = FALSE;
-#ifndef NDEBUG
((cache_ptr->epoch_markers)[i]).magic =
H5C__H5C_CACHE_ENTRY_T_MAGIC;
-#endif /* NDEBUG */
((cache_ptr->epoch_markers)[i]).addr = (haddr_t)i;
((cache_ptr->epoch_markers)[i]).type = &epoch_marker_class;
}
@@ -1586,9 +1786,7 @@ H5C_free_cork_list_cb(void *_item, void H5_ATTR_UNUSED *key, void H5_ATTR_UNUSED
*-------------------------------------------------------------------------
*/
herr_t
-H5C_dest(H5F_t * f,
- hid_t primary_dxpl_id,
- hid_t secondary_dxpl_id)
+H5C_dest(H5F_t * f, hid_t dxpl_id)
{
H5C_t * cache_ptr = f->shared->cache;
herr_t ret_value = SUCCEED; /* Return value */
@@ -1600,8 +1798,7 @@ H5C_dest(H5F_t * f,
HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
/* Flush and invalidate all cache entries */
- if(H5C_flush_invalidate_cache(f, primary_dxpl_id, secondary_dxpl_id,
- H5C__NO_FLAGS_SET) < 0 )
+ if(H5C_flush_invalidate_cache(f, dxpl_id, H5C__NO_FLAGS_SET) < 0 )
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush cache")
if(cache_ptr->slist_ptr != NULL) {
@@ -1631,7 +1828,9 @@ H5C_dest(H5F_t * f,
#endif /* H5C_DO_SANITY_CHECKS */
#endif /* NDEBUG */
+#ifndef NDEBUG
cache_ptr->magic = 0;
+#endif /* NDEBUG */
cache_ptr = H5FL_FREE(H5C_t, cache_ptr);
@@ -1652,9 +1851,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5C_evict(H5F_t * f,
- hid_t primary_dxpl_id,
- hid_t secondary_dxpl_id)
+H5C_evict(H5F_t * f, hid_t dxpl_id)
{
H5C_t *cache_ptr = f->shared->cache;
herr_t ret_value = SUCCEED; /* Return value */
@@ -1666,8 +1863,7 @@ H5C_evict(H5F_t * f,
HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
/* Flush and invalidate all cache entries except the pinned entries */
- if(H5C_flush_invalidate_cache(f, primary_dxpl_id, secondary_dxpl_id,
- H5C__EVICT_ALLOW_LAST_PINS_FLAG) < 0 )
+ if(H5C_flush_invalidate_cache(f, dxpl_id, H5C__EVICT_ALLOW_LAST_PINS_FLAG) < 0 )
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to evict entries in the cache")
done:
@@ -1690,17 +1886,16 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5C_expunge_entry(H5F_t * f,
- hid_t primary_dxpl_id,
- hid_t secondary_dxpl_id,
- const H5C_class_t * type,
- haddr_t addr,
- unsigned flags)
+H5C_expunge_entry(H5F_t *f, hid_t dxpl_id, const H5C_class_t *type,
+ haddr_t addr, unsigned flags)
{
H5C_t * cache_ptr;
- herr_t result;
- hbool_t first_flush = TRUE;
H5C_cache_entry_t * entry_ptr = NULL;
+ unsigned flush_flags = (H5C__FLUSH_INVALIDATE_FLAG | H5C__FLUSH_CLEAR_ONLY_FLAG);
+#if H5C_DO_SANITY_CHECKS
+ hbool_t entry_was_dirty;
+ hsize_t entry_size;
+#endif /* H5C_DO_SANITY_CHECKS */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
@@ -1711,8 +1906,6 @@ H5C_expunge_entry(H5F_t * f,
HDassert(cache_ptr);
HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
HDassert(type);
- HDassert(type->clear);
- HDassert(type->dest);
HDassert(H5F_addr_defined(addr));
#if H5C_DO_EXTREME_SANITY_CHECKS
@@ -1736,27 +1929,34 @@ H5C_expunge_entry(H5F_t * f,
if(entry_ptr->is_pinned)
HGOTO_ERROR(H5E_CACHE, H5E_CANTEXPUNGE, FAIL, "Target entry is pinned.")
- /* Pass along 'free file space' flag to cache client */
- entry_ptr->free_file_space_on_destroy = ( (flags & H5C__FREE_FILE_SPACE_FLAG) != 0 );
-
/* If we get this far, call H5C_flush_single_entry() with the
* H5C__FLUSH_INVALIDATE_FLAG and the H5C__FLUSH_CLEAR_ONLY_FLAG.
* This will clear the entry, and then delete it from the cache.
*/
- result = H5C_flush_single_entry(f,
- primary_dxpl_id,
- secondary_dxpl_id,
- entry_ptr->type,
- entry_ptr->addr,
- H5C__FLUSH_INVALIDATE_FLAG | H5C__FLUSH_CLEAR_ONLY_FLAG,
- &first_flush,
- TRUE);
- if ( result < 0 ) {
+ /* Pass along 'free file space' flag to cache client. */
+ flush_flags |= (flags & H5C__FREE_FILE_SPACE_FLAG);
+
+#if H5C_DO_SANITY_CHECKS
+ entry_was_dirty = entry_ptr->is_dirty;
+ entry_size = entry_ptr->size;
+#endif /* H5C_DO_EXTREME_SANITY_CHECKS */
- HGOTO_ERROR(H5E_CACHE, H5E_CANTEXPUNGE, FAIL, \
- "H5C_flush_single_entry() failed.")
+ if(H5C_flush_single_entry(f, dxpl_id, entry_ptr->addr, flush_flags, TRUE, NULL) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTEXPUNGE, FAIL, "H5C_flush_single_entry() failed.")
+
+#if H5C_DO_SANITY_CHECKS
+ if ( entry_was_dirty )
+ {
+ /* we have just removed an entry from the skip list. Thus
+ * we must touch up cache_ptr->slist_len_increase and
+ * cache_ptr->slist_size_increase to keep from skewing
+ * the sanity checks on flushes.
+ */
+ cache_ptr->slist_len_increase -= 1;
+ cache_ptr->slist_size_increase -= (int64_t)(entry_size);
}
+#endif /* H5C_DO_SANITY_CHECKS */
done:
#if H5C_DO_EXTREME_SANITY_CHECKS
@@ -1793,10 +1993,24 @@ done:
* Programmer: John Mainzer
* 6/2/04
*
+ * Changes: Modified function to test for slist chamges in
+ * pre_serialize and serialize callbacks, and re-start
+ * scans through the slist when such changes occur.
+ *
+ * This has been a potential problem for some time,
+ * and there has been code in this function to deal
+ * with elements of this issue. However the shift
+ * to the V3 cache in combination with the activities
+ * of some of the cache clients (in particular the
+ * free space manager and the fractal heap) have
+ * made this re-work necessary.
+ *
+ * JRM -- 12/13/14
+ *
*-------------------------------------------------------------------------
*/
herr_t
-H5C_flush_cache(H5F_t *f, hid_t primary_dxpl_id, hid_t secondary_dxpl_id, unsigned flags)
+H5C_flush_cache(H5F_t *f, hid_t dxpl_id, unsigned flags)
{
H5C_t * cache_ptr = f->shared->cache;
herr_t status;
@@ -1804,9 +2018,9 @@ H5C_flush_cache(H5F_t *f, hid_t primary_dxpl_id, hid_t secondary_dxpl_id, unsign
hbool_t destroy;
hbool_t flushed_entries_last_pass;
hbool_t flush_marked_entries;
- hbool_t first_flush = TRUE;
hbool_t ignore_protected;
hbool_t tried_to_flush_protected_entry = FALSE;
+ hbool_t restart_slist_scan;
int32_t protected_entries = 0;
H5SL_node_t * node_ptr = NULL;
H5C_cache_entry_t * entry_ptr = NULL;
@@ -1816,6 +2030,10 @@ H5C_flush_cache(H5F_t *f, hid_t primary_dxpl_id, hid_t secondary_dxpl_id, unsign
int64_t flushed_entries_size = 0;
int64_t initial_slist_len = 0;
size_t initial_slist_size = 0;
+ int64_t entry_size_change;
+ int64_t * entry_size_change_ptr = &entry_size_change;
+#else /* H5C_DO_SANITY_CHECKS */
+ int64_t * entry_size_change_ptr = NULL;
#endif /* H5C_DO_SANITY_CHECKS */
FUNC_ENTER_NOAPI(FAIL)
@@ -1852,10 +2070,7 @@ H5C_flush_cache(H5F_t *f, hid_t primary_dxpl_id, hid_t secondary_dxpl_id, unsign
if ( destroy ) {
- status = H5C_flush_invalidate_cache(f,
- primary_dxpl_id,
- secondary_dxpl_id,
- flags);
+ status = H5C_flush_invalidate_cache(f, dxpl_id, flags);
if ( status < 0 ) {
@@ -1874,23 +2089,23 @@ H5C_flush_cache(H5F_t *f, hid_t primary_dxpl_id, hid_t secondary_dxpl_id, unsign
flushed_entries_last_pass = TRUE;
+ /* set the cache_ptr->slist_change_in_pre_serialize and
+ * cache_ptr->slist_change_in_serialize to false.
+ *
+ * These flags are set to TRUE by H5C_flush_single_entry if the
+ * slist is modified by a pre_serialize or serialize call respectively.
+ * H5C_flush_cache uses these flags to detect any modifications
+ * to the slist that might corrupt the scan of the slist -- and
+ * restart the scan in this event.
+ */
+ cache_ptr->slist_change_in_pre_serialize = FALSE;
+ cache_ptr->slist_change_in_serialize = FALSE;
+
while ( ( cache_ptr->slist_len != 0 ) &&
( protected_entries == 0 ) &&
( flushed_entries_last_pass ) )
{
- flushed_entries_last_pass = FALSE;
-
- /* Start at beginning of skip list each time */
- node_ptr = H5SL_first(cache_ptr->slist_ptr);
- HDassert( node_ptr != NULL );
-
- /* Get cache entry for this node */
- next_entry_ptr = (H5C_cache_entry_t *)H5SL_item(node_ptr);
- if ( NULL == next_entry_ptr )
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "next_entry_ptr == NULL ?!?!")
- HDassert( next_entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC );
- HDassert( next_entry_ptr->is_dirty );
- HDassert( next_entry_ptr->in_slist );
+ flushed_entries_last_pass = FALSE;
#if H5C_DO_SANITY_CHECKS
/* For sanity checking, try to verify that the skip list has
@@ -1900,9 +2115,11 @@ H5C_flush_cache(H5F_t *f, hid_t primary_dxpl_id, hid_t secondary_dxpl_id, unsign
* Doing this get a bit tricky, as depending on flags, we may
* or may not flush all the entries in the slist.
*
- * To make things more entertaining, with the advent of the
- * fractal heap, the entry flush callback can cause entries
- * to be dirtied, resized, and/or moved.
+ * To make things more entertaining, with the advent of the
+ * fractal heap, the entry serialize callback can cause entries
+ * to be dirtied, resized, and/or moved. Also, the
+ * pre_serialize callback can result in an entry being
+ * removed from the cache via the take ownership flag.
*
* To deal with this, we first make note of the initial
* skip list length and size:
@@ -1917,7 +2134,8 @@ H5C_flush_cache(H5F_t *f, hid_t primary_dxpl_id, hid_t secondary_dxpl_id, unsign
flushed_entries_size = 0;
/* As mentioned above, there is the possibility that
- * entries will be dirtied, resized, and/or flushed during
+ * entries will be dirtied, resized, flushed, or removed
+ * from the cache via the take ownership flag during
* our pass through the skip list. To capture the number
* of entries added, and the skip list size delta,
* zero the slist_len_increase and slist_size_increase of
@@ -1934,53 +2152,57 @@ H5C_flush_cache(H5F_t *f, hid_t primary_dxpl_id, hid_t secondary_dxpl_id, unsign
*/
#endif /* H5C_DO_SANITY_CHECKS */
- while ( node_ptr != NULL )
+ restart_slist_scan = TRUE;
+
+ while ( ( restart_slist_scan ) || ( node_ptr != NULL ) )
{
- entry_ptr = next_entry_ptr;
+ if ( restart_slist_scan )
+ {
+ restart_slist_scan = FALSE;
- /* With the advent of the fractal heap, it is possible
- * that the flush callback will dirty and/or resize
- * other entries in the cache. In particular, while
- * Quincey has promised me that this will never happen,
- * it is possible that the flush callback for an
- * entry may protect an entry that is not in the cache,
- * perhaps causing the cache to flush and possibly
- * evict the entry associated with node_ptr to make
- * space for the new entry.
- *
- * Thus we do a bit of extra sanity checking on entry_ptr,
- * and break out of this scan of the skip list if we
- * detect minor problems. We have a bit of leaway on the
- * number of passes though the skip list, so this shouldn't
- * be an issue in the flush in and of itself, as it should
- * be all but impossible for this to happen more than once
- * in any flush.
- *
- * Observe that that breaking out of the scan early
- * shouldn't break the sanity checks just after the end
- * of this while loop.
- *
- * If an entry has merely been marked clean and removed from
- * the s-list, we simply break out of the scan.
- *
- * If the entry has been evicted, we flag an error and
- * exit.
- */
-#ifndef NDEBUG
- if ( entry_ptr->magic != H5C__H5C_CACHE_ENTRY_T_MAGIC ) {
+ /* Start at beginning of skip list */
+ node_ptr = H5SL_first(cache_ptr->slist_ptr);
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "entry_ptr->magic is invalid ?!?!")
+ if ( node_ptr == NULL )
+ {
+ /* the slist is empty -- break out of inner loop */
+ break;
+ }
+ HDassert( node_ptr != NULL );
- } else
-#endif /* NDEBUG */
- if ( ( ! entry_ptr->is_dirty ) ||
- ( ! entry_ptr->in_slist ) ) {
+ /* Get cache entry for this node */
+ next_entry_ptr = (H5C_cache_entry_t *)H5SL_item(node_ptr);
- /* the s-list has been modified out from under us.
- * break out of the loop.
- */
- goto end_of_inner_loop;;
- }
+ if(NULL == next_entry_ptr)
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "next_entry_ptr == NULL ?!?!")
+
+ HDassert( next_entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC );
+ HDassert( next_entry_ptr->is_dirty );
+ HDassert( next_entry_ptr->in_slist );
+ }
+
+ entry_ptr = next_entry_ptr;
+
+ /* With the advent of the fractal heap, the free space
+ * manager, and the version 3 cache, it is possible
+ * that the pre-serialize or serialize callback will
+ * dirty, resize, or take ownership of other entries
+ * in the cache.
+ *
+ * To deal with this, I have inserted code to detect any
+ * change in the skip list not directly under the control
+ * of this function. If such modifications are detected,
+ * we must re-start the scan of the skip list to avoid
+ * the possibility that the target of the next_entry_ptr
+ * may have been flushed or deleted from the cache.
+ *
+ * To verify that all such possibilities have been dealt
+ * with, we do a bit of extra sanity checking on
+ * entry_ptr.
+ */
+ HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(entry_ptr->in_slist);
+ HDassert(entry_ptr->is_dirty);
/* increment node pointer now, before we delete its target
* from the slist.
@@ -1994,6 +2216,7 @@ H5C_flush_cache(H5F_t *f, hid_t primary_dxpl_id, hid_t secondary_dxpl_id, unsign
HDassert( next_entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC );
HDassert( next_entry_ptr->is_dirty );
HDassert( next_entry_ptr->in_slist );
+ HDassert( entry_ptr != next_entry_ptr );
} else {
next_entry_ptr = NULL;
}
@@ -2013,11 +2236,10 @@ H5C_flush_cache(H5F_t *f, hid_t primary_dxpl_id, hid_t secondary_dxpl_id, unsign
( entry_ptr->flush_dep_ndirty_children == 0 ) ) ) ) {
if ( entry_ptr->is_protected ) {
-
- /* we probably have major problems -- but lets flush
- * everything we can before we decide whether to flag
- * an error.
- */
+ /* we probably have major problems -- but lets
+ * flush everything we can before we decide
+ * whether to flag an error.
+ */
tried_to_flush_protected_entry = TRUE;
protected_entries++;
@@ -2025,15 +2247,14 @@ H5C_flush_cache(H5F_t *f, hid_t primary_dxpl_id, hid_t secondary_dxpl_id, unsign
#if H5C_DO_SANITY_CHECKS
flushed_entries_count++;
flushed_entries_size += (int64_t)entry_ptr->size;
+ entry_size_change = 0;
#endif /* H5C_DO_SANITY_CHECKS */
status = H5C_flush_single_entry(f,
- primary_dxpl_id,
- secondary_dxpl_id,
- NULL,
- entry_ptr->addr,
- flags,
- &first_flush,
- FALSE);
+ dxpl_id,
+ entry_ptr->addr,
+ flags,
+ FALSE,
+ entry_size_change_ptr);
if ( status < 0 ) {
/* This shouldn't happen -- if it does, we are toast
@@ -2042,21 +2263,45 @@ H5C_flush_cache(H5F_t *f, hid_t primary_dxpl_id, hid_t secondary_dxpl_id, unsign
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \
"dirty pinned entry flush failed.")
} /* end if */
+#if H5C_DO_SANITY_CHECKS
+ /* it is possible that the entry size changed
+ * during flush -- update flushed_entries_size
+ * to account for this.
+ */
+ flushed_entries_size += entry_size_change;
+#endif /* H5C_DO_SANITY_CHECKS */
+
+ if ((cache_ptr->slist_change_in_serialize) ||
+ (cache_ptr->slist_change_in_pre_serialize))
+ {
+ /* The slist has been modified by something
+ * other than the simple removal of the
+ * of the flushed entry after the flush.
+ *
+ * This has the potential to corrupt the
+ * scan through the slist, so restart it.
+ */
+ restart_slist_scan = TRUE;
+ cache_ptr->slist_change_in_pre_serialize = FALSE;
+ cache_ptr->slist_change_in_serialize = FALSE;
+
+ H5C__UPDATE_STATS_FOR_SLIST_SCAN_RESTART(cache_ptr)
+ }
+
flushed_entries_last_pass = TRUE;
} /* end if */
else {
#if H5C_DO_SANITY_CHECKS
flushed_entries_count++;
flushed_entries_size += (int64_t)entry_ptr->size;
+ entry_size_change = 0;
#endif /* H5C_DO_SANITY_CHECKS */
status = H5C_flush_single_entry(f,
- primary_dxpl_id,
- secondary_dxpl_id,
- NULL,
- entry_ptr->addr,
- flags,
- &first_flush,
- FALSE);
+ dxpl_id,
+ entry_ptr->addr,
+ flags,
+ FALSE,
+ entry_size_change_ptr);
if ( status < 0 ) {
/* This shouldn't happen -- if it does, we are
@@ -2065,14 +2310,36 @@ H5C_flush_cache(H5F_t *f, hid_t primary_dxpl_id, hid_t secondary_dxpl_id, unsign
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \
"Can't flush entry.")
}
- flushed_entries_last_pass = TRUE;
+
+#if H5C_DO_SANITY_CHECKS
+ /* it is possible that the entry size changed
+ * during flush -- update flushed_entries_size
+ * to account for this.
+ */
+ flushed_entries_size += entry_size_change;
+#endif /* H5C_DO_SANITY_CHECKS */
+ if ((cache_ptr->slist_change_in_serialize) ||
+ (cache_ptr->slist_change_in_pre_serialize))
+ {
+ /* The slist has been modified by something
+ * other than the simple removal of the
+ * of the flushed entry after the flush.
+ *
+ * This has the potential to corrupt the
+ * scan through the slist, so restart it.
+ */
+ restart_slist_scan = TRUE;
+ cache_ptr->slist_change_in_pre_serialize = FALSE;
+ cache_ptr->slist_change_in_serialize = FALSE;
+
+ H5C__UPDATE_STATS_FOR_SLIST_SCAN_RESTART(cache_ptr)
+ }
+
+ flushed_entries_last_pass = TRUE;
} /* end else */
} /* end if */
- } /* while ( node_ptr != NULL ) */
-/* Note the extra ; is necessary so the label is not at the end of the compound
- * statement (the while loop), which is illegal */
-end_of_inner_loop:;
-
+ } /* while ( ( restart_slist_scan ) || ( node_ptr != NULL ) ) */
+
#if H5C_DO_SANITY_CHECKS
/* Verify that the slist size and length are as expected. */
@@ -2140,12 +2407,10 @@ done:
*/
herr_t
H5C_flush_to_min_clean(H5F_t * f,
- hid_t primary_dxpl_id,
- hid_t secondary_dxpl_id)
+ hid_t dxpl_id)
{
H5C_t * cache_ptr;
herr_t result;
- hbool_t first_flush = TRUE;
hbool_t write_permitted;
#if 0 /* modified code -- commented out for now */
int i;
@@ -2188,11 +2453,9 @@ H5C_flush_to_min_clean(H5F_t * f,
}
#if 1 /* original code */
result = H5C_make_space_in_cache(f,
- primary_dxpl_id,
- secondary_dxpl_id,
+ dxpl_id,
(size_t)0,
- write_permitted,
- &first_flush);
+ write_permitted);
if ( result < 0 ) {
@@ -3008,8 +3271,7 @@ done:
*/
herr_t
H5C_insert_entry(H5F_t * f,
- hid_t primary_dxpl_id,
- hid_t secondary_dxpl_id,
+ hid_t dxpl_id,
const H5C_class_t * type,
haddr_t addr,
void * thing,
@@ -3017,7 +3279,6 @@ H5C_insert_entry(H5F_t * f,
{
H5C_t * cache_ptr;
herr_t result;
- hbool_t first_flush = TRUE;
hbool_t insert_pinned;
hbool_t flush_last;
#ifdef H5_HAVE_PARALLEL
@@ -3040,8 +3301,6 @@ H5C_insert_entry(H5F_t * f,
HDassert( cache_ptr );
HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC );
HDassert( type );
- HDassert( type->flush );
- HDassert( type->size );
HDassert( H5F_addr_defined(addr) );
HDassert( thing );
@@ -3080,15 +3339,16 @@ H5C_insert_entry(H5F_t * f,
HGOTO_ERROR(H5E_CACHE, H5E_CANTINS, FAIL, "duplicate entry in cache.")
} /* end if */
-#ifndef NDEBUG
entry_ptr->magic = H5C__H5C_CACHE_ENTRY_T_MAGIC;
-#endif /* NDEBUG */
entry_ptr->cache_ptr = cache_ptr;
entry_ptr->addr = addr;
entry_ptr->type = type;
+ entry_ptr->image_ptr = NULL;
+ entry_ptr->image_up_to_date = FALSE;
+
/* Apply tag to newly inserted entry */
- if(H5C_tag_entry(cache_ptr, entry_ptr, primary_dxpl_id) < 0)
+ if(H5C_tag_entry(cache_ptr, entry_ptr, dxpl_id) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTTAG, FAIL, "Cannot tag entry")
/* Set the entry's cork status */
@@ -3113,10 +3373,27 @@ H5C_insert_entry(H5F_t * f,
/* not protected, so can't be dirtied */
entry_ptr->dirtied = FALSE;
- /* Retrieve the size of the thing */
- if((type->size)(f, thing, &(entry_ptr->size)) < 0)
+ /* Retrieve the size of the thing. Set the compressed field to FALSE
+ * and the compressed_size field to zero first, as they may not be
+ * initialized by the image_len call.
+ */
+ entry_ptr->compressed = FALSE;
+ entry_ptr->compressed_size = 0;
+ if((type->image_len)(thing, &(entry_ptr->size), &(entry_ptr->compressed),
+ &(entry_ptr->compressed_size)) < 0)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGETSIZE, FAIL, "Can't get size of thing")
HDassert(entry_ptr->size > 0 && entry_ptr->size < H5C_MAX_ENTRY_SIZE);
+ HDassert(((type->flags & H5C__CLASS_COMPRESSED_FLAG) != 0) ||
+ (entry_ptr->compressed == FALSE));
+
+ /* entry has just been inserted -- thus compressed size cannot have
+ * been computed yet. Thus if entry_ptr->compressed is TRUE,
+ * entry_ptr->size must equal entry_ptr->compressed_size.
+ */
+ HDassert((entry_ptr->compressed == FALSE) ||
+ (entry_ptr->size == entry_ptr->compressed_size));
+ HDassert((entry_ptr->compressed == TRUE) ||
+ (entry_ptr->compressed_size == 0));
entry_ptr->in_slist = FALSE;
@@ -3127,7 +3404,6 @@ H5C_insert_entry(H5F_t * f,
entry_ptr->flush_in_progress = FALSE;
entry_ptr->destroy_in_progress = FALSE;
- entry_ptr->free_file_space_on_destroy = FALSE;
/* Initialize flush dependency height fields */
entry_ptr->flush_dep_parent = NULL;
@@ -3227,11 +3503,9 @@ H5C_insert_entry(H5F_t * f,
*/
result = H5C_make_space_in_cache(f,
- primary_dxpl_id,
- secondary_dxpl_id,
+ dxpl_id,
space_needed,
- write_permitted,
- &first_flush);
+ write_permitted);
if ( result < 0 ) {
@@ -3323,18 +3597,39 @@ done:
* Programmer: John Mainzer
* 7/5/05
*
+ * Changes: Tidied up code, removeing some old commented out
+ * code that had been left in pending success of the
+ * new version.
+ *
+ * Note that unlike H5C_apply_candidate_list(),
+ * H5C_mark_entries_as_clean() makes all its calls to
+ * H6C_flush_single_entry() with the
+ * H5C__FLUSH_CLEAR_ONLY_FLAG set. As a result,
+ * the pre_serialize() and serialize calls are not made.
+ *
+ * This then implies that (assuming such actions were
+ * permitted in the parallel case) no loads, dirties,
+ * resizes, or removals of other entries can occur as
+ * a side effect of the flush. Hence, there is no need
+ * for the checks for entry removal / status change
+ * that I ported to H5C_apply_candidate_list().
+ *
+ * However, if (in addition to allowing such operations
+ * in the parallel case), we allow such operations outside
+ * of the pre_serialize / serialize routines, this may
+ * cease to be the case -- requiring a review of this
+ * function.
+ *
*-------------------------------------------------------------------------
*/
#ifdef H5_HAVE_PARALLEL
herr_t
H5C_mark_entries_as_clean(H5F_t * f,
- hid_t primary_dxpl_id,
- hid_t secondary_dxpl_id,
+ hid_t dxpl_id,
int32_t ce_array_len,
haddr_t * ce_array_ptr)
{
H5C_t * cache_ptr;
- hbool_t first_flush = TRUE;
int entries_cleared;
int entries_examined;
int i;
@@ -3428,27 +3723,9 @@ H5C_mark_entries_as_clean(H5F_t * f,
#endif /* H5C_DO_SANITY_CHECKS */
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
"Listed entry not dirty?!?!?.")
-#if 0 /* original code */
- } else if ( entry_ptr->is_protected ) {
-
- entry_ptr->clear_on_unprotect = TRUE;
} else {
- if ( H5C_flush_single_entry(f,
- primary_dxpl_id,
- secondary_dxpl_id,
- entry_ptr->type,
- addr,
- H5C__FLUSH_CLEAR_ONLY_FLAG,
- &first_flush,
- TRUE) < 0 ) {
-
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Can't clear entry.")
- }
- }
-#else /* modified code */
- } else {
/* Mark the entry to be cleared on unprotect. We will
* scan the LRU list shortly, and clear all those entries
* not currently protected.
@@ -3469,13 +3746,32 @@ H5C_mark_entries_as_clean(H5F_t * f,
}
#endif /* H5C_DO_SANITY_CHECKS */
}
-#endif /* end modified code */
}
-#if 1 /* modified code */
+
/* Scan through the LRU list from back to front, and flush the
* entries whose clear_on_unprotect flags are set. Observe that
* any protected entries will not be on the LRU, and therefore
* will not be flushed at this time.
+ *
+ * Note that unlike H5C_apply_candidate_list(),
+ * H5C_mark_entries_as_clean() makes all its calls to
+ * H6C_flush_single_entry() with the H5C__FLUSH_CLEAR_ONLY_FLAG
+ * set. As a result, the pre_serialize() and serialize calls are
+ * not made.
+ *
+ * This then implies that (assuming such actions were
+ * permitted in the parallel case) no loads, dirties,
+ * resizes, or removals of other entries can occur as
+ * a side effect of the flush. Hence, there is no need
+ * for the checks for entry removal / status change
+ * that I ported to H5C_apply_candidate_list().
+ *
+ * However, if (in addition to allowing such operations
+ * in the parallel case), we allow such operations outside
+ * of the pre_serialize / serialize routines, this may
+ * cease to be the case -- requiring a review of this
+ * point.
+ * JRM -- 4/7/15
*/
entries_cleared = 0;
@@ -3495,13 +3791,11 @@ H5C_mark_entries_as_clean(H5F_t * f,
entries_cleared++;
if ( H5C_flush_single_entry(f,
- primary_dxpl_id,
- secondary_dxpl_id,
- clear_ptr->type,
+ dxpl_id,
clear_ptr->addr,
H5C__FLUSH_CLEAR_ONLY_FLAG,
- &first_flush,
- TRUE) < 0 ) {
+ TRUE,
+ NULL) < 0 ) {
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Can't clear entry.")
}
@@ -3532,13 +3826,11 @@ H5C_mark_entries_as_clean(H5F_t * f,
entries_cleared++;
if ( H5C_flush_single_entry(f,
- primary_dxpl_id,
- secondary_dxpl_id,
- clear_ptr->type,
+ dxpl_id,
clear_ptr->addr,
H5C__FLUSH_CLEAR_ONLY_FLAG,
- &first_flush,
- TRUE) < 0 ) {
+ TRUE,
+ NULL) < 0 ) {
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Can't clear entry.")
}
@@ -3569,7 +3861,6 @@ H5C_mark_entries_as_clean(H5F_t * f,
}
HDassert( (entries_cleared + i) == ce_array_len );
#endif /* H5C_DO_SANITY_CHECKS */
-#endif /* modified code */
done:
@@ -3645,6 +3936,7 @@ H5C_mark_entry_dirty(void *thing)
/* mark the entry as dirty if it isn't already */
entry_ptr->is_dirty = TRUE;
+ entry_ptr->image_up_to_date = FALSE;
/* Propagate the dirty flag up the flush dependency chain if appropriate
*/
@@ -3701,7 +3993,7 @@ H5C_move_entry(H5C_t * cache_ptr,
haddr_t old_addr,
haddr_t new_addr)
{
- hbool_t was_dirty;
+ hbool_t was_dirty;
H5C_cache_entry_t * entry_ptr = NULL;
H5C_cache_entry_t * test_entry_ptr = NULL;
#if H5C_DO_SANITY_CHECKS
@@ -3801,10 +4093,12 @@ H5C_move_entry(H5C_t * cache_ptr,
if ( ! ( entry_ptr->destroy_in_progress ) ) {
was_dirty = entry_ptr->is_dirty;
+ entry_ptr->is_dirty = TRUE;
- if ( ! ( entry_ptr->flush_in_progress ) ) {
+ /* This shouldn't be needed, but it keeps the test code happy */
+ entry_ptr->image_up_to_date = FALSE;
- entry_ptr->is_dirty = TRUE;
+ if ( ! ( entry_ptr->flush_in_progress ) ) {
/* Propagate the dirty flag up the flush dependency chain if
* appropriate */
@@ -3824,29 +4118,26 @@ H5C_move_entry(H5C_t * cache_ptr,
H5C__INSERT_IN_INDEX(cache_ptr, entry_ptr, FAIL)
- if ( ! ( entry_ptr->flush_in_progress ) ) {
-
- H5C__INSERT_ENTRY_IN_SLIST(cache_ptr, entry_ptr, FAIL)
+ H5C__INSERT_ENTRY_IN_SLIST(cache_ptr, entry_ptr, FAIL)
#if H5C_DO_SANITY_CHECKS
- if ( removed_entry_from_slist ) {
+ if ( removed_entry_from_slist ) {
- /* we just removed the entry from the slist. Thus we
- * must touch up cache_ptr->slist_len_increase and
- * cache_ptr->slist_size_increase to keep from skewing
- * the sanity checks.
- */
- HDassert( cache_ptr->slist_len_increase > 1 );
- HDassert( cache_ptr->slist_size_increase >
- (int64_t)(entry_ptr->size) );
-
- cache_ptr->slist_len_increase -= 1;
- cache_ptr->slist_size_increase -= (int64_t)(entry_ptr->size);
- }
+ /* we just removed the entry from the slist. Thus we
+ * must touch up cache_ptr->slist_len_increase and
+ * cache_ptr->slist_size_increase to keep from skewing
+ * the sanity checks.
+ */
+ cache_ptr->slist_len_increase -= 1;
+ cache_ptr->slist_size_increase -= (int64_t)(entry_ptr->size);
+ }
#endif /* H5C_DO_SANITY_CHECKS */
+ if ( ! ( entry_ptr->flush_in_progress ) ) {
+
+ /* skip the update if a flush is in progress */
H5C__UPDATE_RP_FOR_MOVE(cache_ptr, entry_ptr, was_dirty, FAIL)
}
}
@@ -3926,6 +4217,11 @@ H5C_resize_entry(void *thing, size_t new_size)
/* mark the entry as dirty if it isn't already */
entry_ptr->is_dirty = TRUE;
+ entry_ptr->image_up_to_date = FALSE;
+
+ /* Release the current image */
+ if( entry_ptr->image_ptr )
+ entry_ptr->image_ptr = H5MM_xfree(entry_ptr->image_ptr);
/* Propagate the dirty flag up the flush dependency chain if
* appropriate */
@@ -4148,18 +4444,6 @@ done:
* or flushed -- nor may it be accessed by another call to
* H5C_protect. Any attempt to do so will result in a failure.
*
- * The primary_dxpl_id and secondary_dxpl_id parameters
- * specify the dxpl_ids used on the first write occasioned
- * by the insertion (primary_dxpl_id), and on all subsequent
- * writes (secondary_dxpl_id). This is useful in the
- * metadata cache, but may not be needed elsewhere. If so,
- * just use the same dxpl_id for both parameters.
- *
- * All reads are performed with the primary_dxpl_id.
- *
- * Similarly, the primary_dxpl_id is passed to the
- * check_write_permitted function if it is called.
- *
* Return: Success: Ptr to the desired entry
* Failure: NULL
*
@@ -4181,12 +4465,21 @@ done:
* entries long before we actually have to evict something
* to make space.
*
+ * JRM -- 9/1/14
+ * Replace the old rw parameter with the flags parameter.
+ * This allows H5C_protect to accept flags other than
+ * H5C__READ_ONLY_FLAG.
+ *
+ * Added support for the H5C__FLUSH_LAST_FLAG and
+ * H5C__FLUSH_COLLECTIVELY_FLAG flags. At present, these
+ * flags are only applied if the entry is not in cache, and
+ * is loaded into the cache as a result of this call.
+ *
*-------------------------------------------------------------------------
*/
void *
H5C_protect(H5F_t * f,
- hid_t primary_dxpl_id,
- hid_t secondary_dxpl_id,
+ hid_t dxpl_id,
const H5C_class_t * type,
haddr_t addr,
void * udata,
@@ -4194,9 +4487,12 @@ H5C_protect(H5F_t * f,
{
H5C_t * cache_ptr;
hbool_t hit;
- hbool_t first_flush;
hbool_t have_write_permitted = FALSE;
hbool_t read_only = FALSE;
+ hbool_t flush_last;
+#ifdef H5_HAVE_PARALLEL
+ hbool_t flush_collectively;
+#endif /* H5_HAVE_PARALLEL */
hbool_t write_permitted;
herr_t result;
size_t empty_space;
@@ -4215,8 +4511,6 @@ H5C_protect(H5F_t * f,
HDassert( cache_ptr );
HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC );
HDassert( type );
- HDassert( type->flush );
- HDassert( type->load );
HDassert( H5F_addr_defined(addr) );
#if H5C_DO_EXTREME_SANITY_CHECKS
@@ -4230,6 +4524,10 @@ H5C_protect(H5F_t * f,
#endif /* H5C_DO_EXTREME_SANITY_CHECKS */
read_only = ( (flags & H5C__READ_ONLY_FLAG) != 0 );
+ flush_last = ( (flags & H5C__FLUSH_LAST_FLAG) != 0 );
+#ifdef H5_HAVE_PARALLEL
+ flush_collectively = ( (flags & H5C__FLUSH_COLLECTIVELY_FLAG) != 0 );
+#endif /* H5_HAVE_PARALLEL */
/* first check to see if the target is in cache */
H5C__SEARCH_INDEX(cache_ptr, addr, entry_ptr, NULL)
@@ -4249,17 +4547,17 @@ H5C_protect(H5F_t * f,
hit = FALSE;
- thing = H5C_load_entry(f, primary_dxpl_id, type, addr, udata);
+ thing = H5C_load_entry(f, dxpl_id, type, addr, udata);
if ( thing == NULL ) {
HGOTO_ERROR(H5E_CACHE, H5E_CANTLOAD, NULL, "can't load entry")
- }
+ }
entry_ptr = (H5C_cache_entry_t *)thing;
/* Apply tag to newly protected entry */
- if(H5C_tag_entry(cache_ptr, entry_ptr, primary_dxpl_id) < 0)
+ if(H5C_tag_entry(cache_ptr, entry_ptr, dxpl_id) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTTAG, NULL, "Cannot tag entry")
/* Set the entry's cork status */
@@ -4318,7 +4616,6 @@ H5C_protect(H5F_t * f,
have_write_permitted = TRUE;
- first_flush = TRUE;
}
} else {
@@ -4326,7 +4623,6 @@ H5C_protect(H5F_t * f,
have_write_permitted = TRUE;
- first_flush = TRUE;
}
HDassert( entry_ptr->size <= H5C_MAX_ENTRY_SIZE );
@@ -4367,10 +4663,10 @@ H5C_protect(H5F_t * f,
* see no point in worrying about the fourth.
*/
- result = H5C_make_space_in_cache(f, primary_dxpl_id,
- secondary_dxpl_id,
- space_needed, write_permitted,
- &first_flush);
+ result = H5C_make_space_in_cache(f,
+ dxpl_id,
+ space_needed,
+ write_permitted);
if ( result < 0 ) {
@@ -4384,7 +4680,24 @@ H5C_protect(H5F_t * f,
*
* This is no longer true -- due to a bug fix, we may modify
* data on load to repair a file.
+ *
+ * *******************************************
+ *
+ * Set the flush_last (and possibly flush_collectively) fields
+ * of the newly loaded entry before inserting it into the
+ * index. Must do this, as the index tracked the number of
+ * entries with the flush_last field set, but assumes that
+ * the field will not change after insertion into the index.
+ *
+ * Note that this means that the H5C__FLUSH_LAST_FLAG and
+ * H5C__FLUSH_COLLECTIVELY_FLAG flags are ignored if the
+ * entry is already in cache.
*/
+ entry_ptr->flush_me_last = flush_last;
+#ifdef H5_HAVE_PARALLEL
+ entry_ptr->flush_me_collectively = flush_collectively;
+#endif
+
H5C__INSERT_IN_INDEX(cache_ptr, entry_ptr, NULL)
if ( ( entry_ptr->is_dirty ) && ( ! (entry_ptr->in_slist) ) ) {
@@ -4398,6 +4711,13 @@ H5C_protect(H5F_t * f,
* code. If we do this often enough, we may want to optimize this.
*/
H5C__UPDATE_RP_FOR_INSERTION(cache_ptr, entry_ptr, NULL)
+
+ /* If the entry's type has a 'notify' callback send a 'after load'
+ * notice now that the entry is fully integrated into the cache.
+ */
+ if(entry_ptr->type->notify &&
+ (entry_ptr->type->notify)(H5C_NOTIFY_ACTION_AFTER_LOAD, entry_ptr) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, NULL, "can't notify client about entry inserted into cache")
}
HDassert( entry_ptr->addr == addr );
@@ -4458,7 +4778,6 @@ H5C_protect(H5F_t * f,
have_write_permitted = TRUE;
- first_flush = TRUE;
}
} else {
@@ -4466,7 +4785,6 @@ H5C_protect(H5F_t * f,
have_write_permitted = TRUE;
- first_flush = TRUE;
}
}
@@ -4475,10 +4793,8 @@ H5C_protect(H5F_t * f,
(cache_ptr->resize_ctl).epoch_length ) ) {
result = H5C__auto_adjust_cache_size(f,
- primary_dxpl_id,
- secondary_dxpl_id,
- write_permitted,
- &first_flush);
+ dxpl_id,
+ write_permitted);
if ( result != SUCCEED ) {
HGOTO_ERROR(H5E_CACHE, H5E_CANTPROTECT, NULL, \
@@ -4512,10 +4828,10 @@ H5C_protect(H5F_t * f,
if(cache_ptr->index_size > cache_ptr->max_cache_size)
cache_ptr->cache_full = TRUE;
- result = H5C_make_space_in_cache(f, primary_dxpl_id,
- secondary_dxpl_id,
- (size_t)0, write_permitted,
- &first_flush);
+ result = H5C_make_space_in_cache(f,
+ dxpl_id,
+ (size_t)0,
+ write_permitted);
if ( result < 0 ) {
@@ -4526,14 +4842,16 @@ H5C_protect(H5F_t * f,
}
}
+#ifdef ASK
/* If we loaded the entry and the entry's type has a 'notify' callback, send
* a 'after insertion' notice now that the entry is fully integrated into
* the cache and protected. We must wait until it is protected so it is not
* evicted during the notify callback.
*/
if(!hit && entry_ptr->type->notify &&
- (entry_ptr->type->notify)(H5C_NOTIFY_ACTION_AFTER_INSERT, entry_ptr) < 0)
+ (entry_ptr->type->notify)(H5C_NOTIFY_ACTION_AFTER_LOAD, entry_ptr) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, NULL, "can't notify client about entry inserted into cache")
+#endif
done:
@@ -5060,6 +5378,10 @@ done:
* total_entries_skipped_in_msic, total_entries_scanned_in_msic,
* and max_entries_skipped_in_msic fields.
*
+ * JRM -- 4/11/15
+ * Added code displaying the new slist_scan_restarts,
+ * LRU_scan_restarts, and hash_bucket_scan_restarts fields;
+ *
*-------------------------------------------------------------------------
*/
herr_t
@@ -5083,6 +5405,7 @@ H5C_stats(H5C_t * cache_ptr,
int64_t total_clears = 0;
int64_t total_flushes = 0;
int64_t total_evictions = 0;
+ int64_t total_take_ownerships = 0;
int64_t total_moves = 0;
int64_t total_entry_flush_moves = 0;
int64_t total_cache_flush_moves = 0;
@@ -5111,6 +5434,8 @@ H5C_stats(H5C_t * cache_ptr,
FUNC_ENTER_NOAPI(FAIL)
+ HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC );
+
/* This would normally be an assert, but we need to use an HGOTO_ERROR
* call to shut up the compiler.
*/
@@ -5137,6 +5462,7 @@ H5C_stats(H5C_t * cache_ptr,
total_clears += cache_ptr->clears[i];
total_flushes += cache_ptr->flushes[i];
total_evictions += cache_ptr->evictions[i];
+ total_take_ownerships += cache_ptr->take_ownerships[i];
total_moves += cache_ptr->moves[i];
total_entry_flush_moves += cache_ptr->entry_flush_moves[i];
total_cache_flush_moves += cache_ptr->cache_flush_moves[i];
@@ -5288,11 +5614,16 @@ H5C_stats(H5C_t * cache_ptr,
(long)max_read_protects);
HDfprintf(stdout,
- "%s Total clears / flushes / evictions = %ld / %ld / %ld\n",
+ "%s Total clears / flushes = %ld / %ld\n",
cache_ptr->prefix,
(long)total_clears,
- (long)total_flushes,
- (long)total_evictions);
+ (long)total_flushes);
+
+ HDfprintf(stdout,
+ "%s Total evictions / take ownerships = %ld / %ld\n",
+ cache_ptr->prefix,
+ (long)total_evictions,
+ (long)total_take_ownerships);
HDfprintf(stdout,
"%s Total insertions(pinned) / moves = %ld(%ld) / %ld\n",
@@ -5364,6 +5695,13 @@ H5C_stats(H5C_t * cache_ptr,
(long long)(cache_ptr->total_entries_scanned_in_msic -
cache_ptr->entries_scanned_to_make_space));
+ HDfprintf(stdout,
+ "%s slist/LRU/hash bkt scan restarts = %lld / %lld / %lld.\n",
+ cache_ptr->prefix,
+ (long long)(cache_ptr->slist_scan_restarts),
+ (long long)(cache_ptr->LRU_scan_restarts),
+ (long long)(cache_ptr->hash_bucket_scan_restarts));
+
#if H5C_COLLECT_CACHE_ENTRY_STATS
HDfprintf(stdout, "%s aggregate max / min accesses = %d / %d\n",
@@ -5417,11 +5755,16 @@ H5C_stats(H5C_t * cache_ptr,
(int)(cache_ptr->max_read_protects[i]));
HDfprintf(stdout,
- "%s clears / flushes / evictions = %ld / %ld / %ld\n",
+ "%s clears / flushes = %ld / %ld\n",
cache_ptr->prefix,
(long)(cache_ptr->clears[i]),
- (long)(cache_ptr->flushes[i]),
- (long)(cache_ptr->evictions[i]));
+ (long)(cache_ptr->flushes[i]));
+
+ HDfprintf(stdout,
+ "%s evictions / take ownerships = %ld / %ld\n",
+ cache_ptr->prefix,
+ (long)(cache_ptr->evictions[i]),
+ (long)(cache_ptr->take_ownerships[i]));
HDfprintf(stdout,
"%s insertions(pinned) / moves = %ld(%ld) / %ld\n",
@@ -5516,6 +5859,11 @@ done:
* total_entries_skipped_in_msic, total_entries_scanned_in_msic,
* and max_entries_skipped_in_msic fields.
*
+ * JRM 4/11/15
+ * Added code to initialize the new slist_scan_restarts,
+ * LRU_scan_restarts, hash_bucket_scan_restarts, and
+ * take_ownerships fields.
+ *
*-------------------------------------------------------------------------
*/
void
@@ -5549,6 +5897,7 @@ H5C_stats__reset(H5C_t H5_ATTR_UNUSED * cache_ptr)
cache_ptr->clears[i] = 0;
cache_ptr->flushes[i] = 0;
cache_ptr->evictions[i] = 0;
+ cache_ptr->take_ownerships[i] = 0;
cache_ptr->moves[i] = 0;
cache_ptr->entry_flush_moves[i] = 0;
cache_ptr->cache_flush_moves[i] = 0;
@@ -5591,6 +5940,10 @@ H5C_stats__reset(H5C_t H5_ATTR_UNUSED * cache_ptr)
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;
+ cache_ptr->hash_bucket_scan_restarts = 0;
+
#if H5C_COLLECT_CACHE_ENTRY_STATS
for ( i = 0; i <= cache_ptr->max_type_id; i++ )
@@ -5745,6 +6098,107 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5C_dump_cache_skip_list
+ *
+ * Purpose: Debugging routine that prints a summary of the contents of
+ * the skip list used by the metadata cache metadata cache to
+ * maintain an address sorted list of dirty entries.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: John Mainzer
+ * 11/15/14
+ *
+ *-------------------------------------------------------------------------
+ */
+#if 0 /* debugging routine */
+herr_t
+H5C_dump_cache_skip_list(H5C_t * cache_ptr, char * calling_fcn)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+ int i;
+ H5C_cache_entry_t * entry_ptr = NULL;
+ H5SL_node_t * node_ptr = NULL;
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ HDassert(cache_ptr != NULL);
+ HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
+ HDassert(calling_fcn != NULL);
+
+ HDfprintf(stdout, "\n\nDumping metadata cache skip list from %s.\n",
+ calling_fcn);
+ HDfprintf(stdout, " slist len = %d.\n", cache_ptr->slist_len);
+ HDfprintf(stdout, " slist size = %lld.\n",
+ (long long)(cache_ptr->slist_size));
+
+ if ( cache_ptr->slist_len > 0 )
+ {
+ /* If we get this far, all entries in the cache are listed in the
+ * skip list -- scan the skip list generating the desired output.
+ */
+
+ HDfprintf(stdout,
+ "Num: Addr: Len: Prot/Pind: Dirty: Type:\n");
+
+ i = 0;
+
+ node_ptr = H5SL_first(cache_ptr->slist_ptr);
+
+ if ( node_ptr != NULL ) {
+
+ entry_ptr = (H5C_cache_entry_t *)H5SL_item(node_ptr);
+
+ } else {
+
+ entry_ptr = NULL;
+ }
+
+ while ( entry_ptr != NULL ) {
+
+ HDassert( entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC );
+
+ HDfprintf(stdout,
+ "%s%d 0x%016llx %4lld %d/%d %d %s\n",
+ cache_ptr->prefix, i,
+ (long long)(entry_ptr->addr),
+ (long long)(entry_ptr->size),
+ (int)(entry_ptr->is_protected),
+ (int)(entry_ptr->is_pinned),
+ (int)(entry_ptr->is_dirty),
+ entry_ptr->type->name);
+
+ HDfprintf(stdout, " node_ptr = 0x%llx, item = 0x%llx\n",
+ (unsigned long long)node_ptr,
+ (unsigned long long)H5SL_item(node_ptr));
+
+ /* increment node_ptr before we delete its target */
+ node_ptr = H5SL_next(node_ptr);
+
+ if ( node_ptr != NULL ) {
+
+ entry_ptr = (H5C_cache_entry_t *)H5SL_item(node_ptr);
+
+ } else {
+
+ entry_ptr = NULL;
+ }
+
+ i++;
+ }
+ }
+
+ HDfprintf(stdout, "\n\n");
+
+done:
+
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* H5C_dump_cache_skip_list() */
+#endif /* debugging routine */
+
+
+/*-------------------------------------------------------------------------
* Function: H5C_unpin_entry_from_client()
*
* Purpose: Internal routine to unpin a cache entry from a client action.
@@ -5900,8 +6354,7 @@ done:
*/
herr_t
H5C_unprotect(H5F_t * f,
- hid_t primary_dxpl_id,
- hid_t secondary_dxpl_id,
+ hid_t dxpl_id,
const H5C_class_t * type,
haddr_t addr,
void * thing,
@@ -5941,8 +6394,6 @@ H5C_unprotect(H5F_t * f,
HDassert( cache_ptr );
HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC );
HDassert( type );
- HDassert( type->clear );
- HDassert( type->flush );
HDassert( H5F_addr_defined(addr) );
HDassert( thing );
HDassert( ! ( pin_entry && unpin_entry ) );
@@ -6041,6 +6492,19 @@ H5C_unprotect(H5F_t * f,
/* Mark the entry as dirty if appropriate */
entry_ptr->is_dirty = (entry_ptr->is_dirty || dirtied);
+ /* the image_up_to_date field was introduced to support
+ * journaling. Until we re-introduce journaling, this
+ * field should be equal to !entry_ptr->is_dirty.
+ *
+ * When journaling is re-enabled it should be set
+ * to FALSE if dirtied is TRUE.
+ */
+#if 1 /* JRM */
+ entry_ptr->image_up_to_date = FALSE;
+#else /* JRM */
+ entry_ptr->image_up_to_date = !entry_ptr->is_dirty;
+#endif /* JRM */
+
/* Update index for newly dirtied entry */
if(was_clean && entry_ptr->is_dirty) {
@@ -6109,13 +6573,6 @@ H5C_unprotect(H5F_t * f,
* JRM - 5/19/04
*/
if ( deleted ) {
-
- /* the following first flush flag will never be used as we are
- * calling H5C_flush_single_entry with both the
- * H5C__FLUSH_CLEAR_ONLY_FLAG and H5C__FLUSH_INVALIDATE_FLAG flags.
- * However, it is needed for the function call.
- */
- hbool_t dummy_first_flush = TRUE;
unsigned flush_flags = (H5C__FLUSH_CLEAR_ONLY_FLAG |
H5C__FLUSH_INVALIDATE_FLAG);
@@ -6137,36 +6594,40 @@ H5C_unprotect(H5F_t * f,
"hash table contains multiple entries for addr?!?.")
}
- /* Pass along 'free file space' flag to cache client */
-
- entry_ptr->free_file_space_on_destroy = free_file_space;
+ /* Set the 'free file space' flag for the flush, if needed */
+ if(free_file_space)
+ flush_flags |= H5C__FREE_FILE_SPACE_FLAG;
/* Set the "take ownership" flag for the flush, if needed */
if(take_ownership)
flush_flags |= H5C__TAKE_OWNERSHIP_FLAG;
if ( H5C_flush_single_entry(f,
- primary_dxpl_id,
- secondary_dxpl_id,
- type,
+ dxpl_id,
addr,
flush_flags,
- &dummy_first_flush,
- TRUE) < 0 ) {
+ TRUE,
+ NULL) < 0 ) {
HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, "Can't flush.")
}
+
+#if H5C_DO_SANITY_CHECKS
+ if ( ( take_ownership ) && ( ! was_clean ) )
+ {
+ /* we have just removed an entry from the skip list. Thus
+ * we must touch up cache_ptr->slist_len_increase and
+ * cache_ptr->slist_size_increase to keep from skewing
+ * the sanity checks on flushes.
+ */
+ cache_ptr->slist_len_increase -= 1;
+ cache_ptr->slist_size_increase -= (int64_t)(entry_ptr->size);
+ }
+#endif /* H5C_DO_SANITY_CHECKS */
}
#ifdef H5_HAVE_PARALLEL
else if ( clear_entry ) {
- /* the following first flush flag will never be used as we are
- * calling H5C_flush_single_entry with the
- * H5C__FLUSH_CLEAR_ONLY_FLAG flag. However, it is needed for
- * the function call.
- */
- hbool_t dummy_first_flush = TRUE;
-
/* verify that the target entry is in the cache. */
H5C__SEARCH_INDEX(cache_ptr, addr, test_entry_ptr, FAIL)
@@ -6183,13 +6644,11 @@ H5C_unprotect(H5F_t * f,
}
if ( H5C_flush_single_entry(f,
- primary_dxpl_id,
- secondary_dxpl_id,
- type,
+ dxpl_id,
addr,
H5C__FLUSH_CLEAR_ONLY_FLAG,
- &dummy_first_flush,
- TRUE) < 0 ) {
+ TRUE,
+ NULL) < 0 ) {
HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, "Can't clear.")
}
@@ -6746,10 +7205,8 @@ done:
*/
static herr_t
H5C__auto_adjust_cache_size(H5F_t * f,
- hid_t primary_dxpl_id,
- hid_t secondary_dxpl_id,
- hbool_t write_permitted,
- hbool_t * first_flush_ptr)
+ hid_t dxpl_id,
+ hbool_t write_permitted)
{
H5C_t * cache_ptr = f->shared->cache;
herr_t result;
@@ -6950,13 +7407,11 @@ H5C__auto_adjust_cache_size(H5F_t * f,
} else {
result = H5C__autoadjust__ageout(f,
+ dxpl_id,
hit_rate,
&status,
&new_max_cache_size,
- primary_dxpl_id,
- secondary_dxpl_id,
- write_permitted,
- first_flush_ptr);
+ write_permitted);
if ( result != SUCCEED ) {
@@ -7099,13 +7554,11 @@ done:
*/
static herr_t
H5C__autoadjust__ageout(H5F_t * f,
+ hid_t dxpl_id,
double hit_rate,
enum H5C_resize_status * status_ptr,
size_t * new_max_cache_size_ptr,
- hid_t primary_dxpl_id,
- hid_t secondary_dxpl_id,
- hbool_t write_permitted,
- hbool_t * first_flush_ptr)
+ hbool_t write_permitted)
{
H5C_t * cache_ptr = f->shared->cache;
herr_t result;
@@ -7146,8 +7599,7 @@ H5C__autoadjust__ageout(H5F_t * f,
if ( cache_ptr->max_cache_size > (cache_ptr->resize_ctl).min_size ){
/* evict aged out cache entries if appropriate... */
- if(H5C__autoadjust__ageout__evict_aged_out_entries(f, primary_dxpl_id,
- secondary_dxpl_id, write_permitted, first_flush_ptr) < 0)
+ if(H5C__autoadjust__ageout__evict_aged_out_entries(f, dxpl_id, write_permitted) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "error flushing aged out entries.")
/* ... and then reduce cache size if appropriate */
@@ -7344,20 +7796,32 @@ done:
*
* Programmer: John Mainzer, 11/22/04
*
+ * Changes: Modified function to detect deletions of entries
+ * during a scan of the LRU, and where appropriate,
+ * restart the scan to avoid proceeding with a next
+ * entry that is no longer in the cache.
+ *
+ * Note the absence of checks after flushes of clean
+ * entries. As a second entry can only be removed by
+ * by a call to the pre_serialize or serialize callback
+ * of the first, and as these callbacks will not be called
+ * on clean entries, no checks are needed.
+ *
+ * JRM -- 4/6/15
+ *
*-------------------------------------------------------------------------
*/
static herr_t
H5C__autoadjust__ageout__evict_aged_out_entries(H5F_t * f,
- hid_t primary_dxpl_id,
- hid_t secondary_dxpl_id,
- hbool_t write_permitted,
- hbool_t * first_flush_ptr)
+ hid_t dxpl_id,
+ hbool_t write_permitted)
{
H5C_t * cache_ptr = f->shared->cache;
herr_t result;
size_t eviction_size_limit;
size_t bytes_evicted = 0;
hbool_t prev_is_dirty = FALSE;
+ hbool_t restart_scan;
H5C_cache_entry_t * entry_ptr;
H5C_cache_entry_t * next_ptr;
H5C_cache_entry_t * prev_ptr;
@@ -7386,6 +7850,7 @@ H5C__autoadjust__ageout__evict_aged_out_entries(H5F_t * f,
if ( write_permitted ) {
+ restart_scan = FALSE;
entry_ptr = cache_ptr->LRU_tail_ptr;
while ( ( entry_ptr != NULL ) &&
@@ -7393,7 +7858,11 @@ H5C__autoadjust__ageout__evict_aged_out_entries(H5F_t * f,
( bytes_evicted < eviction_size_limit ) )
{
hbool_t corked = FALSE;
+
+ HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert( ! (entry_ptr->is_protected) );
+ HDassert( ! (entry_ptr->is_read_only) );
+ HDassert( (entry_ptr->ro_ref_count) == 0 );
next_ptr = entry_ptr->next;
prev_ptr = entry_ptr->prev;
@@ -7409,26 +7878,39 @@ H5C__autoadjust__ageout__evict_aged_out_entries(H5F_t * f,
result = TRUE;
} else if ( entry_ptr->is_dirty ) {
+ /* reset entries_removed_counter and
+ * last_entry_removed_ptr prior to the call to
+ * H5C_flush_single_entry() so that we can spot
+ * unexpected removals of entries from the cache,
+ * and set the restart_scan flag if proceeding
+ * would be likely to cause us to scan an entry
+ * that is no longer in the cache.
+ */
+ cache_ptr->entries_removed_counter = 0;
+ cache_ptr->last_entry_removed_ptr = NULL;
+
result = H5C_flush_single_entry(f,
- primary_dxpl_id,
- secondary_dxpl_id,
- entry_ptr->type,
+ dxpl_id,
entry_ptr->addr,
H5C__NO_FLAGS_SET,
- first_flush_ptr,
- FALSE);
+ FALSE,
+ NULL);
+
+ if ( ( cache_ptr->entries_removed_counter > 1 ) ||
+ ( cache_ptr->last_entry_removed_ptr == prev_ptr ) )
+
+ restart_scan = TRUE;
+
} else {
bytes_evicted += entry_ptr->size;
result = H5C_flush_single_entry(f,
- primary_dxpl_id,
- secondary_dxpl_id,
- entry_ptr->type,
+ dxpl_id,
entry_ptr->addr,
H5C__FLUSH_INVALIDATE_FLAG,
- first_flush_ptr,
- TRUE);
+ TRUE,
+ NULL);
}
if ( result < 0 ) {
@@ -7438,32 +7920,28 @@ H5C__autoadjust__ageout__evict_aged_out_entries(H5F_t * f,
}
if ( prev_ptr != NULL ) {
-#ifndef NDEBUG
- if ( prev_ptr->magic != H5C__H5C_CACHE_ENTRY_T_MAGIC ) {
-
- /* something horrible has happened to *prev_ptr --
- * scream and die.
- */
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
- "*prev_ptr corrupt")
- }
-#endif /* NDEBUG */
if(corked) { /* dirty corked entry is skipped */
entry_ptr = prev_ptr;
- } else if ( ( prev_ptr->is_dirty != prev_is_dirty )
- ||
- ( prev_ptr->next != next_ptr )
- ||
- ( prev_ptr->is_protected )
- ||
- ( prev_ptr->is_pinned ) ) {
+
+ } else if ( ( restart_scan )
+ ||
+ ( prev_ptr->is_dirty != prev_is_dirty )
+ ||
+ ( prev_ptr->next != next_ptr )
+ ||
+ ( prev_ptr->is_protected )
+ ||
+ ( prev_ptr->is_pinned ) ) {
/* something has happened to the LRU -- start over
* from the tail.
*/
+ restart_scan = FALSE;
entry_ptr = cache_ptr->LRU_tail_ptr;
+ H5C__UPDATE_STATS_FOR_LRU_SCAN_RESTART(cache_ptr)
+
} else {
entry_ptr = prev_ptr;
@@ -7522,13 +8000,11 @@ H5C__autoadjust__ageout__evict_aged_out_entries(H5F_t * f,
if ( ! (entry_ptr->is_dirty) ) {
result = H5C_flush_single_entry(f,
- primary_dxpl_id,
- secondary_dxpl_id,
- entry_ptr->type,
+ dxpl_id,
entry_ptr->addr,
H5C__FLUSH_INVALIDATE_FLAG,
- first_flush_ptr,
- TRUE);
+ TRUE,
+ NULL);
if ( result < 0 ) {
@@ -7538,6 +8014,10 @@ H5C__autoadjust__ageout__evict_aged_out_entries(H5F_t * f,
}
/* just skip the entry if it is dirty, as we can't do
* anything with it now since we can't write.
+ *
+ * Since all entries are clean, serialize() will not be called,
+ * and thus we needn't test to see if the LRU has been changed
+ * out from under us.
*/
entry_ptr = prev_ptr;
@@ -8001,17 +8481,45 @@ done:
* Programmer: John Mainzer
* 3/24/065
*
+ * Changes: Modified function to test for slist chamges in
+ * pre_serialize and serialize callbacks, and re-start
+ * scans through the slist when such changes occur.
+ *
+ * This has been a potential problem for some time,
+ * and there has been code in this function to deal
+ * with elements of this issue. However the shift
+ * to the V3 cache in combination with the activities
+ * of some of the cache clients (in particular the
+ * free space manager and the fractal heap) have
+ * made this re-work necessary in H5C_flush_cache.
+ *
+ * At present, this issue doesn't seem to be causing problems
+ * in H5C_flush_invalidate_cache(). However, it seems
+ * prudent to port the H5C_flush_cache changes to this
+ * function as well.
+ *
+ * JRM -- 12/14/14
+ *
+ * Added code to track entry size change during flush single
+ * entry. This didn't used to be a problem, as the entry
+ * was largely removed from the cache data structures before
+ * the flush proper. However, re-entrant calls to the cache
+ * in the parallel case required a re-factoring of the
+ * H5C_flush_single_entry() function to keep entries fully
+ * in the cache until after the pre-serialize and serialize
+ * calls.
+ * JRM -- 12/25/14
+ *
*-------------------------------------------------------------------------
*/
static herr_t
-H5C_flush_invalidate_cache(H5F_t * f,
- hid_t primary_dxpl_id,
- hid_t secondary_dxpl_id,
+H5C_flush_invalidate_cache(const H5F_t * f,
+ hid_t dxpl_id,
unsigned flags)
{
H5C_t * cache_ptr = f->shared->cache;
herr_t status;
- hbool_t first_flush = TRUE;
+ hbool_t restart_slist_scan;
int32_t protected_entries = 0;
int32_t i;
int32_t cur_pel_len;
@@ -8022,10 +8530,14 @@ H5C_flush_invalidate_cache(H5F_t * f,
H5C_cache_entry_t * entry_ptr = NULL;
H5C_cache_entry_t * next_entry_ptr = NULL;
#if H5C_DO_SANITY_CHECKS
- int64_t actual_slist_len = 0;
+ int64_t flushed_slist_len = 0;
int64_t initial_slist_len = 0;
- size_t actual_slist_size = 0;
+ int64_t flushed_slist_size = 0;
size_t initial_slist_size = 0;
+ int64_t entry_size_change;
+ int64_t * entry_size_change_ptr = &entry_size_change;
+#else /* H5C_DO_SANITY_CHECKS */
+ int64_t * entry_size_change_ptr = NULL;
#endif /* H5C_DO_SANITY_CHECKS */
herr_t ret_value = SUCCEED;
@@ -8096,27 +8608,6 @@ H5C_flush_invalidate_cache(H5F_t * f,
* that the slist will not be empty after we finish the scan.
*/
- if ( cache_ptr->slist_len == 0 ) {
-
- node_ptr = NULL;
- HDassert( cache_ptr->slist_size == 0 );
-
- } else {
-
- /* Start at beginning of skip list each time */
- node_ptr = H5SL_first(cache_ptr->slist_ptr);
- HDassert( node_ptr != NULL );
-
- /* Get cache entry for this node */
- next_entry_ptr = (H5C_cache_entry_t *)H5SL_item(node_ptr);
- if ( NULL == next_entry_ptr )
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "next_entry_ptr == NULL ?!?!")
- HDassert( next_entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC );
- HDassert( next_entry_ptr->is_dirty );
- HDassert( next_entry_ptr->in_slist );
- }
-
-
#if H5C_DO_SANITY_CHECKS
/* Depending on circumstances, H5C_flush_single_entry() will
* remove dirty entries from the slist as it flushes them.
@@ -8137,63 +8628,78 @@ H5C_flush_invalidate_cache(H5F_t * f,
cache_ptr->slist_len_increase = 0;
cache_ptr->slist_size_increase = 0;
- /* Finally, reset the actual_slist_len and actual_slist_size
+ /* Finally, reset the flushed_slist_len and flushed_slist_size
* fields to zero, as these fields are used to accumulate
* the slist lenght and size that we see as we scan through
* the slist.
*/
- actual_slist_len = 0;
- actual_slist_size = 0;
+ flushed_slist_len = 0;
+ flushed_slist_size = 0;
#endif /* H5C_DO_SANITY_CHECKS */
- while ( node_ptr != NULL )
+ /* set the cache_ptr->slist_change_in_pre_serialize and
+ * cache_ptr->slist_change_in_serialize to false.
+ *
+ * These flags are set to TRUE by H5C_flush_single_entry if the
+ * slist is modified by a pre_serialize or serialize call
+ * respectively.
+ *
+ * H5C_flush_invalidate_cache() uses these flags to detect any
+ * modifications to the slist that might corrupt the scan of
+ * the slist -- and restart the scan in this event.
+ */
+ cache_ptr->slist_change_in_pre_serialize = FALSE;
+ cache_ptr->slist_change_in_serialize = FALSE;
+
+ /* this done, start the scan of the slist */
+
+ restart_slist_scan = TRUE;
+
+ while ( ( restart_slist_scan ) || ( node_ptr != NULL ) )
{
- entry_ptr = next_entry_ptr;
-
- /* With the advent of the fractal heap, it is possible
- * that the flush callback will dirty and/or resize
- * other entries in the cache. In particular, while
- * Quincey has promised me that this will never happen,
- * it is possible that the flush callback for an
- * entry may protect an entry that is not in the cache,
- * perhaps causing the cache to flush and possibly
- * evict the entry associated with node_ptr to make
- * space for the new entry.
- *
- * Thus we do a bit of extra sanity checking on entry_ptr,
- * and break out of this scan of the skip list if we
- * detect major problems. We have a bit of leaway on the
- * number of passes though the skip list, so this shouldn't
- * be an issue in the flush in and of itself, as it should
- * be all but impossible for this to happen more than once
- * in any flush.
- *
- * Observe that that breaking out of the scan early
- * shouldn't break the sanity checks just after the end
- * of this while loop.
- *
- * If an entry has merely been marked clean and removed from
- * the s-list, we simply break out of the scan.
- *
- * If the entry has been evicted, we flag an error and
- * exit.
- */
-#ifndef NDEBUG
- if ( entry_ptr->magic != H5C__H5C_CACHE_ENTRY_T_MAGIC ) {
+ if ( restart_slist_scan )
+ {
+ restart_slist_scan = FALSE;
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "entry_ptr->magic is invalid ?!?!")
+ /* Start at beginning of skip list */
+ node_ptr = H5SL_first(cache_ptr->slist_ptr);
- } else
-#endif /* NDEBUG */
- if ( ( ! entry_ptr->is_dirty ) ||
- ( ! entry_ptr->in_slist ) ) {
+ if ( node_ptr == NULL )
+ {
+ /* the slist is empty -- break out of inner loop */
+ break;
+ }
+ HDassert( node_ptr != NULL );
- /* the s-list has been modified out from under us.
- * break out of the loop.
- */
- goto end_of_inner_loop;;
+ /* Get cache entry for this node */
+ next_entry_ptr = (H5C_cache_entry_t *)H5SL_item(node_ptr);
+
+ if(NULL == next_entry_ptr)
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "next_entry_ptr == NULL ?!?!")
+
+ HDassert( next_entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC );
+ HDassert( next_entry_ptr->is_dirty );
+ HDassert( next_entry_ptr->in_slist );
}
+ entry_ptr = next_entry_ptr;
+
+ /* It is possible that entries will be dirtied, resized,
+ * flushed, or removed from the cache via the take ownership
+ * flag as the result of pre_serialize or serialized callbacks.
+ *
+ * This in turn can corrupt the scan through the slist.
+ *
+ * We test for slist modifications in the pre_serialize
+ * and serialize callbacks, and restart the scan of the
+ * slist if we find them. However, best we do some extra
+ * sanity checking just in case.
+ */
+
+ HDassert( entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC );
+ HDassert( entry_ptr->in_slist );
+ HDassert( entry_ptr->is_dirty );
+
/* increment node pointer now, before we delete its target
* from the slist.
*/
@@ -8206,6 +8712,7 @@ H5C_flush_invalidate_cache(H5F_t * f,
HDassert( next_entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC );
HDassert( next_entry_ptr->is_dirty );
HDassert( next_entry_ptr->in_slist );
+ HDassert( entry_ptr != next_entry_ptr );
} else {
next_entry_ptr = NULL;
}
@@ -8230,21 +8737,6 @@ H5C_flush_invalidate_cache(H5F_t * f,
cache_ptr->slist_len ) ) ) &&
( entry_ptr->flush_dep_nchildren == 0 ) ) {
-#if H5C_DO_SANITY_CHECKS
- /* update actual_slist_len & actual_slist_size before
- * the flush. Note that the entry will be removed
- * from the slist after the flush, and thus may be
- * resized by the flush callback. This is OK, as
- * we will catch the size delta in
- * cache_ptr->slist_size_increase.
- *
- * Note that we include pinned entries in this count, even
- * though we will not actually flush them.
- */
- actual_slist_len++;
- actual_slist_size += entry_ptr->size;
-#endif /* H5C_DO_SANITY_CHECKS */
-
if ( entry_ptr->is_protected ) {
/* we have major problems -- but lets flush
@@ -8254,14 +8746,26 @@ H5C_flush_invalidate_cache(H5F_t * f,
} else if ( entry_ptr->is_pinned ) {
+#if H5C_DO_SANITY_CHECKS
+ /* update flushed_slist_len & flushed_slist_size
+ * before the flush. Note that the entry will
+ * be removed from the slist after the flush,
+ * and thus may be resized by the flush callback.
+ * This is OK, as we will catch the size delta in
+ * cache_ptr->slist_size_increase.
+ *
+ */
+ flushed_slist_len++;
+ flushed_slist_size += (int64_t)entry_ptr->size;
+ entry_size_change = 0;
+#endif /* H5C_DO_SANITY_CHECKS */
+
status = H5C_flush_single_entry(f,
- primary_dxpl_id,
- secondary_dxpl_id,
- NULL,
- entry_ptr->addr,
- H5C__NO_FLAGS_SET,
- &first_flush,
- FALSE);
+ dxpl_id,
+ entry_ptr->addr,
+ H5C__NO_FLAGS_SET,
+ FALSE,
+ entry_size_change_ptr);
if ( status < 0 ) {
/* This shouldn't happen -- if it does, we are toast
@@ -8271,17 +8775,52 @@ H5C_flush_invalidate_cache(H5F_t * f,
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \
"dirty pinned entry flush failed.")
} /* end if */
+
+#if H5C_DO_SANITY_CHECKS
+ /* entry size may have changed during the flush.
+ * Update flushed_slist_size to account for this.
+ */
+ flushed_slist_size += entry_size_change;
+#endif /* H5C_DO_SANITY_CHECKS */
+
+ if ( ( cache_ptr->slist_change_in_serialize ) ||
+ ( cache_ptr->slist_change_in_pre_serialize ) )
+ {
+ /* The slist has been modified by something
+ * other than the simple removal of the
+ * of the flushed entry after the flush.
+ *
+ * This has the potential to corrupt the
+ * scan through the slist, so restart it.
+ */
+ restart_slist_scan = TRUE;
+ cache_ptr->slist_change_in_pre_serialize = FALSE;
+ cache_ptr->slist_change_in_serialize = FALSE;
+ H5C__UPDATE_STATS_FOR_SLIST_SCAN_RESTART(cache_ptr);
+ }
} /* end if */
else {
+#if H5C_DO_SANITY_CHECKS
+ /* update flushed_slist_len & flushed_slist_size
+ * before the flush. Note that the entry will
+ * be removed from the slist after the flush,
+ * and thus may be resized by the flush callback.
+ * This is OK, as we will catch the size delta in
+ * cache_ptr->slist_size_increase.
+ *
+ */
+ flushed_slist_len++;
+ flushed_slist_size += (int64_t)entry_ptr->size;
+ entry_size_change = 0;
+#endif /* H5C_DO_SANITY_CHECKS */
+
status = H5C_flush_single_entry(f,
- primary_dxpl_id,
- secondary_dxpl_id,
- NULL,
+ dxpl_id,
entry_ptr->addr,
(cooked_flags | H5C__FLUSH_INVALIDATE_FLAG),
- &first_flush,
- TRUE);
+ TRUE,
+ entry_size_change_ptr);
if ( status < 0 ) {
/* This shouldn't happen -- if it does, we are toast so
@@ -8291,6 +8830,30 @@ H5C_flush_invalidate_cache(H5F_t * f,
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \
"dirty entry flush destroy failed.")
} /* end if */
+
+#if H5C_DO_SANITY_CHECKS
+ /* entry size may have changed during the flush.
+ * Update flushed_slist_size to account for this.
+ */
+ flushed_slist_size += entry_size_change;
+#endif /* H5C_DO_SANITY_CHECKS */
+
+ if ((cache_ptr->slist_change_in_serialize) ||
+ (cache_ptr->slist_change_in_pre_serialize))
+ {
+ /* The slist has been modified by something
+ * other than the simple removal of the
+ * of the flushed entry after the flush.
+ *
+ * This has the potential to corrupt the
+ * scan through the slist, so restart it.
+ */
+ restart_slist_scan = TRUE;
+ cache_ptr->slist_change_in_pre_serialize = FALSE;
+ cache_ptr->slist_change_in_serialize = FALSE;
+ H5C__UPDATE_STATS_FOR_SLIST_SCAN_RESTART(cache_ptr)
+ }
+
} /* end else */
} /* end if */
} /* end while loop scanning skip list */
@@ -8307,11 +8870,10 @@ H5C_flush_invalidate_cache(H5F_t * f,
if ( node_ptr == NULL ) {
- HDassert( (actual_slist_len + cache_ptr->slist_len) ==
+ HDassert( (flushed_slist_len + cache_ptr->slist_len) ==
(initial_slist_len + cache_ptr->slist_len_increase) );
- HDassert( (actual_slist_size + cache_ptr->slist_size) ==
- (initial_slist_size +
- (size_t)(cache_ptr->slist_size_increase)) );
+ HDassert( (flushed_slist_size + (int64_t)cache_ptr->slist_size) ==
+ ((int64_t)initial_slist_size + cache_ptr->slist_size_increase) );
}
#endif /* H5C_DO_SANITY_CHECKS */
@@ -8333,9 +8895,7 @@ H5C_flush_invalidate_cache(H5F_t * f,
while ( next_entry_ptr != NULL )
{
entry_ptr = next_entry_ptr;
-#ifndef NDEBUG
HDassert( entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC );
-#endif /* NDEBUG */
next_entry_ptr = entry_ptr->ht_next;
HDassert ( ( next_entry_ptr == NULL ) ||
@@ -8359,15 +8919,39 @@ H5C_flush_invalidate_cache(H5F_t * f,
HDassert( !(entry_ptr->is_dirty) );
}
} else if ( ! ( entry_ptr->is_pinned ) ) {
+ /* if *entry_ptr is dirty, it is possible
+ * that one or more other entries may be
+ * either removed from the cache, loaded
+ * into the cache, or moved to a new location
+ * in the file as a side effect of the flush.
+ *
+ * If this happens, and one of the target
+ * entries happens to be the next entry in
+ * the hash bucket, we could find ourselves
+ * either find ourselves either scanning a
+ * non-existant entry, scanning through a
+ * different bucket, or skipping an entry.
+ *
+ * Neither of these are good, so restart the
+ * the scan at the head of the hash bucket
+ * after the flush if *entry_ptr was dirty,
+ * on the off chance that the next entry was
+ * a target.
+ *
+ * This is not as inefficient at it might seem,
+ * as hash buckets typically have at most two
+ * or three entries.
+ */
+ hbool_t entry_was_dirty;
+
+ entry_was_dirty = entry_ptr->is_dirty;
status = H5C_flush_single_entry(f,
- primary_dxpl_id,
- secondary_dxpl_id,
- NULL,
+ dxpl_id,
entry_ptr->addr,
(cooked_flags | H5C__FLUSH_INVALIDATE_FLAG),
- &first_flush,
- TRUE);
+ TRUE,
+ NULL);
if ( status < 0 ) {
/* This shouldn't happen -- if it does, we are toast so
@@ -8377,6 +8961,17 @@ H5C_flush_invalidate_cache(H5F_t * f,
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \
"Entry flush destroy failed.")
}
+
+ if ( entry_was_dirty ) {
+
+ /* update stats for hash bucket scan
+ * restart here.
+ * -- JRM
+ */
+ next_entry_ptr = cache_ptr->index[i];
+ H5C__UPDATE_STATS_FOR_HASH_BUCKET_SCAN_RESTART(cache_ptr)
+ }
+
} /* end if */
} /* end if */
/* We can't do anything if the entry is pinned. The
@@ -8387,7 +8982,7 @@ H5C_flush_invalidate_cache(H5F_t * f,
* of pinned entries from pass to pass. If it stops
* shrinking before it hits zero, we scream and die.
*/
- /* if the flush function on the entry we last evicted
+ /* if the serialize function on the entry we last evicted
* loaded an entry into cache (as Quincey has promised me
* it never will), and if the cache was full, it is
* possible that *next_entry_ptr was flushed or evicted.
@@ -8396,8 +8991,13 @@ H5C_flush_invalidate_cache(H5F_t * f,
* test is triggred, we are accessing a deallocated piece
* of dynamically allocated memory, so we just scream and
* die.
+ *
+ * Update: The code to restart the scan after flushes
+ * of dirty entries should make it impossible
+ * to satisfy the following test. Leave it in
+ * in case I am wrong.
+ * -- JRM
*/
-#ifndef NDEBUG
if ( ( next_entry_ptr != NULL ) &&
( next_entry_ptr->magic !=
H5C__H5C_CACHE_ENTRY_T_MAGIC ) ) {
@@ -8408,10 +9008,8 @@ H5C_flush_invalidate_cache(H5F_t * f,
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
"next_entry_ptr->magic is invalid?!?!?.")
}
-#endif /* NDEBUG */
} /* end while loop scanning hash table bin */
} /* end for loop scanning hash table */
-end_of_inner_loop:
old_pel_len = cur_pel_len;
cur_pel_len = cache_ptr->pel_len;
@@ -8490,22 +9088,9 @@ done:
* Attempts to flush a protected entry will result in an
* error.
*
- * *first_flush_ptr should be true if only one
- * flush is contemplated before the next load, or if this
- * is the first of a sequence of flushes that will be
- * completed before the next load. *first_flush_ptr is set
- * to false if a flush actually takes place, and should be
- * left false until the end of the sequence.
- *
- * The primary_dxpl_id is used if *first_flush_ptr is TRUE
- * on entry, and a flush actually takes place. The
- * secondary_dxpl_id is used in any subsequent flush where
- * *first_flush_ptr is FALSE on entry.
- *
* If the H5C__FLUSH_INVALIDATE_FLAG flag is set, the entry will
- * be cleared and not flushed -- in the case *first_flush_ptr,
- * primary_dxpl_id, and secondary_dxpl_id are all irrelevent,
- * and the call can't be part of a sequence of flushes.
+ * be cleared and not flushed, and the call can't be part of a
+ * sequence of flushes.
*
* If the caller knows the address of the skip list node at
* which the target entry resides, it can avoid a lookup
@@ -8522,26 +9107,57 @@ done:
*
* Programmer: John Mainzer, 5/5/04
*
+ * Changes: Refactored function to remove the type_ptr parameter.
+ *
+ * JRM -- 8/7/14
+ *
+ * Added code to check for slist changes in pre_serialize and
+ * serialize calls, and set
+ * cache_ptr->slist_change_in_pre_serialize and
+ * cache_ptr->slist_change_in_serialize as appropriate.
+ *
+ * JRM -- 12/13/14
+ *
+ * Refactored function to delay all modifications of the
+ * metadata cache data structures until after any calls
+ * to the pre-serialize or serialize callbacks.
+ *
+ * Need to do this, as some pre-serialize or serialize
+ * calls result in calls to the metadata cache and
+ * modifications to its data structures. Thus, at the
+ * time of any such call, the target entry flags and
+ * the metadata cache must all be consistant.
+ *
+ * Also added the entry_size_change_ptr parameter, which
+ * allows the function to report back any change in the size
+ * of the entry during the flush. Such size changes may
+ * occur during the pre-serialize callback.
+ *
+ * JRM -- 12/24/14
+ *
*-------------------------------------------------------------------------
*/
static herr_t
-H5C_flush_single_entry(H5F_t * f,
- hid_t primary_dxpl_id,
- hid_t secondary_dxpl_id,
- const H5C_class_t * type_ptr,
- haddr_t addr,
- unsigned flags,
- hbool_t * first_flush_ptr,
- hbool_t del_entry_from_slist_on_destroy)
+H5C_flush_single_entry(const H5F_t * f,
+ hid_t dxpl_id,
+ haddr_t addr,
+ unsigned flags,
+ hbool_t del_entry_from_slist_on_destroy,
+ int64_t * entry_size_change_ptr)
{
H5C_t * cache_ptr = f->shared->cache;
hbool_t destroy; /* external flag */
hbool_t clear_only; /* external flag */
+ hbool_t free_file_space; /* external flag */
hbool_t take_ownership; /* external flag */
+ hbool_t write_entry; /* internal flag */
+ hbool_t destroy_entry; /* internal flag */
hbool_t was_dirty;
- hbool_t destroy_entry;
herr_t status;
- unsigned flush_flags = H5C_CALLBACK__NO_FLAGS_SET;
+ haddr_t new_addr = HADDR_UNDEF;
+ haddr_t old_addr = HADDR_UNDEF;
+ size_t new_len = 0;
+ size_t new_compressed_len = 0;
H5C_cache_entry_t * entry_ptr = NULL;
herr_t ret_value = SUCCEED; /* Return value */
@@ -8551,11 +9167,15 @@ H5C_flush_single_entry(H5F_t * f,
HDassert( cache_ptr );
HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC );
HDassert( H5F_addr_defined(addr) );
- HDassert( first_flush_ptr );
+
+ /* If defined, initialize *entry_size_change_ptr to 0 */
+ if(entry_size_change_ptr != NULL)
+ *entry_size_change_ptr = 0;
/* setup external flags from the flags parameter */
destroy = ((flags & H5C__FLUSH_INVALIDATE_FLAG) != 0);
clear_only = ((flags & H5C__FLUSH_CLEAR_ONLY_FLAG) != 0);
+ free_file_space = ((flags & H5C__FREE_FILE_SPACE_FLAG) != 0);
take_ownership = ((flags & H5C__TAKE_OWNERSHIP_FLAG) != 0);
/* Set the flag for destroying the entry, based on the 'take ownership'
@@ -8569,6 +9189,14 @@ H5C_flush_single_entry(H5F_t * f,
/* attempt to find the target entry in the hash table */
H5C__SEARCH_INDEX(cache_ptr, addr, entry_ptr, FAIL)
+ /* we will write the entry to disk if it exists, is dirty, and if the
+ * clear only flag is not set.
+ */
+ if ( ( entry_ptr != NULL ) && ( entry_ptr->is_dirty ) && ( ! clear_only ) )
+ write_entry = TRUE;
+ else
+ write_entry = FALSE;
+
/* run initial sanity checks */
#if H5C_DO_SANITY_CHECKS
if ( entry_ptr != NULL ) {
@@ -8577,6 +9205,8 @@ H5C_flush_single_entry(H5F_t * f,
if ( entry_ptr->in_slist ) {
+ HDassert(entry_ptr->is_dirty);
+
if ( ( ( entry_ptr->flush_marker ) && ( ! entry_ptr->is_dirty ) ) ||
( entry_ptr->addr != addr ) ) {
@@ -8585,6 +9215,10 @@ H5C_flush_single_entry(H5F_t * f,
}
} else {
+ HDassert(!entry_ptr->is_dirty);
+ HDassert(!entry_ptr->flush_marker);
+ HDassert(entry_ptr->addr == addr);
+
if ( ( entry_ptr->is_dirty ) ||
( entry_ptr->flush_marker ) ||
( entry_ptr->addr != addr ) ) {
@@ -8598,22 +9232,32 @@ H5C_flush_single_entry(H5F_t * f,
if ( ( entry_ptr != NULL ) && ( entry_ptr->is_protected ) )
{
+ HDassert(!entry_ptr->is_protected);
/* Attempt to flush a protected entry -- scream and die. */
HGOTO_ERROR(H5E_CACHE, H5E_PROTECT, FAIL, \
"Attempt to flush a protected entry.")
}
- if ( ( entry_ptr != NULL ) &&
- ( ( type_ptr == NULL ) || ( type_ptr->id == entry_ptr->type->id ) ) )
+ /* if the entry exists, set entry_ptr->flush_in_progress = TRUE
+ * and set entry_ptr->flush_marker = FALSE
+ *
+ * in the parallel case, do some sanity checking in passing.
+ */
+ if ( entry_ptr != NULL )
{
/* we have work to do */
+ HDassert(entry_ptr->type);
+
+ was_dirty = entry_ptr->is_dirty; /* needed later for logging */
/* We will set flush_in_progress back to FALSE at the end if the
* entry still exists at that point.
*/
entry_ptr->flush_in_progress = TRUE;
+ entry_ptr->flush_marker = FALSE;
+
#ifdef H5_HAVE_PARALLEL
#ifndef NDEBUG
/* If MPI based VFD is used, do special parallel I/O sanity checks.
@@ -8627,7 +9271,7 @@ H5C_flush_single_entry(H5F_t * f,
unsigned coll_meta; /* Collective metadata write flag */
/* Get the dataset transfer property list */
- if(NULL == (dxpl = H5I_object(primary_dxpl_id)))
+ if(NULL == (dxpl = H5I_object(dxpl_id)))
HGOTO_ERROR(H5E_CACHE, H5E_BADTYPE, FAIL, "not a dataset transfer property list")
/* Get the collective metadata write property */
@@ -8639,174 +9283,112 @@ H5C_flush_single_entry(H5F_t * f,
} /* end if */
#endif /* NDEBUG */
#endif /* H5_HAVE_PARALLEL */
+ }
- was_dirty = entry_ptr->is_dirty;
-
- entry_ptr->flush_marker = FALSE;
-
- if ( clear_only ) {
- H5C__UPDATE_STATS_FOR_CLEAR(cache_ptr, entry_ptr)
- } else {
- H5C__UPDATE_STATS_FOR_FLUSH(cache_ptr, entry_ptr)
- }
-
- if ( destroy ) {
- H5C__UPDATE_STATS_FOR_EVICTION(cache_ptr, entry_ptr)
- }
+ if ( ( entry_ptr != NULL ) && ( write_entry ) )
+ {
+ /* serialize the entry if necessary, and then write it to disk. */
- /* If the entry's type has a 'notify' callback and the entry is about
- * to be removed from the cache, send a 'before eviction' notice while
- * the entry is still fully integrated in the cache.
- */
- if(destroy) {
- if(entry_ptr->type->notify &&
- (entry_ptr->type->notify)(H5C_NOTIFY_ACTION_BEFORE_EVICT, entry_ptr) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, "can't notify client about entry to evict")
- } /* end if */
+ unsigned serialize_flags = H5C__SERIALIZE_NO_FLAGS_SET;
- /* Always remove the entry from the hash table on a destroy. On a
- * flush with destroy, it is cheaper to discard the skip list all at
- * once rather than remove the entries one by one, so we only delete
- * from the slist only if requested.
- *
- * We must do deletions now as the callback routines will free the
- * entry if destroy is true.
+ /* The entry is dirty, and we are doing either a flush,
+ * or a flush destroy. In either case, serialize the
+ * entry and write it to disk.
*
- * Note that it is possible that the entry will be moved during
- * its call to flush. This will upset H5C_move_entry() if we
- * don't tell it that it doesn't have to worry about updating the
- * index and SLIST. Use the destroy_in_progress field for this
- * purpose.
- */
- if ( destroy ) {
-
- entry_ptr->destroy_in_progress = TRUE;
-
- H5C__DELETE_FROM_INDEX(cache_ptr, entry_ptr)
-
- if ( ( entry_ptr->in_slist ) &&
- ( del_entry_from_slist_on_destroy ) ) {
-
- H5C__REMOVE_ENTRY_FROM_SLIST(cache_ptr, entry_ptr)
- }
- }
-
- /* Update the replacement policy for the flush or eviction.
- * Again, do this now so we don't have to reference freed
- * memory in the destroy case.
+ * Note that this may cause the entry to be re-sized and/or
+ * moved in the cache.
+ *
+ * As we will not update the metadata cache's data structures
+ * until we we finish the write, we must touch up these
+ * data structures for size and location changes even if we
+ * are about to delete the entry from the cache (i.e. on a
+ * flush destroy).
*/
- if ( destroy ) { /* AKA eviction */
-
- H5C__UPDATE_RP_FOR_EVICTION(cache_ptr, entry_ptr, FAIL)
-
- } else {
-
- H5C__UPDATE_RP_FOR_FLUSH(cache_ptr, entry_ptr, FAIL)
- }
-
- /* Destroy parent flush dependencies and free flush dependency parent
- * array, if necessary */
- if ( destroy ) {
- HDassert( entry_ptr->flush_dep_nchildren == 0 );
-
- if ( entry_ptr->flush_dep_parent_nalloc > 0 ) {
+ HDassert(entry_ptr->is_dirty);
- while ( entry_ptr->flush_dep_nparents > 0 ) {
+#if H5C_DO_SANITY_CHECKS
+ if ( ( cache_ptr->check_write_permitted == NULL ) &&
+ ( !(cache_ptr->write_permitted) ) )
- /* Since the flush_dep_parent array willbe resized every
- * a flush dependency is destroyed, we do not have to
- * iterate over all indices. Instead, always destroy the
- * last dependency so we can skip the memmove() in
- * H5C_destroy_flush_dependency(). */
- if ( H5C_destroy_flush_dependency(entry_ptr->flush_dep_parent[entry_ptr->flush_dep_nparents - 1],
- entry_ptr) < 0 ) {
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "Write when writes are always forbidden!?!?!")
+#endif /* H5C_DO_SANITY_CHECKS */
- HGOTO_ERROR(H5E_CACHE, H5E_CANTUNDEPEND, FAIL, \
- "Can't remove flush dependency")
- }
- }
+ if ( NULL == entry_ptr->image_ptr )
+ {
+ size_t image_size;
- /* H5C_destroy_flush_dependency should have freed the parent
- * array when it became empty */
- HDassert( ! (entry_ptr->flush_dep_parent) );
- HDassert( entry_ptr->flush_dep_parent_nalloc == 0 );
- }
- }
+ if ( entry_ptr->compressed )
+ image_size = entry_ptr->compressed_size;
+ else
+ image_size = entry_ptr->size;
- /* Clear the dirty flag only, if requested */
- if ( clear_only ) {
+ HDassert(image_size > 0);
- if ( destroy ) {
-#ifndef NDEBUG
- /* we are about to call the clear callback with the
- * destroy flag set -- this will result in *entry_ptr
- * being freed. Set the magic field to bad magic
- * so we can detect a freed cache entry if we see
- * one.
- */
- entry_ptr->magic = H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC;
-#endif /* NDEBUG */
- entry_ptr->cache_ptr = NULL;
- }
- /* Call the callback routine to clear all dirty flags for object */
- if ( (entry_ptr->type->clear)(f, entry_ptr, destroy_entry) < 0 ) {
+ entry_ptr->image_ptr =
+ H5MM_malloc(image_size + H5C_IMAGE_EXTRA_SPACE);
- HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "can't clear entry")
+ if ( NULL == entry_ptr->image_ptr)
+ {
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, \
+ "memory allocation failed for on disk image buffer")
}
- } else {
+#if H5C_DO_MEMORY_SANITY_CHECKS
-#if H5C_DO_SANITY_CHECKS
- if ( ( entry_ptr->is_dirty ) &&
- ( cache_ptr->check_write_permitted == NULL ) &&
- ( ! (cache_ptr->write_permitted) ) )
+ HDmemcpy(((uint8_t *)entry_ptr->image_ptr) + image_size,
+ H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE);
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
- "Write when writes are always forbidden!?!?!")
-#endif /* H5C_DO_SANITY_CHECKS */
+#endif /* H5C_DO_MEMORY_SANITY_CHECKS */
- if ( destroy ) {
-#ifndef NDEBUG
- /* we are about to call the flush callback with the
- * destroy flag set -- this will result in *entry_ptr
- * being freed. Set the magic field to bad magic
- * so we can detect a freed cache entry if we see
- * one.
- */
- entry_ptr->magic = H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC;
-#endif /* NDEBUG */
- entry_ptr->cache_ptr = NULL;
- }
+ } /* end if */
- /* Only block for all the processes on the first piece of metadata
+ if ( ! (entry_ptr->image_up_to_date) )
+ {
+ /* reset cache_ptr->slist_changed so we can detect slist
+ * modifications in the pre_serialize call.
*/
-
- if ( *first_flush_ptr && entry_ptr->is_dirty ) {
-
- status = (entry_ptr->type->flush)(f, primary_dxpl_id, destroy_entry,
- entry_ptr->addr, entry_ptr,
- &flush_flags);
- *first_flush_ptr = FALSE;
-
- } else {
-
- status = (entry_ptr->type->flush)(f, secondary_dxpl_id,
- destroy_entry, entry_ptr->addr,
- entry_ptr, &flush_flags);
- }
-
- if ( status < 0 ) {
-
+ cache_ptr->slist_changed = FALSE;
+
+ /* make note of the entry's current address */
+ old_addr = entry_ptr->addr;
+
+ /* Call client's pre-serialize callback, if there's one */
+ if ( ( entry_ptr->type->pre_serialize != NULL ) &&
+ ( (entry_ptr->type->pre_serialize)(f, dxpl_id,
+ (void *)entry_ptr,
+ entry_ptr->addr,
+ entry_ptr->size,
+ entry_ptr->compressed_size,
+ &new_addr, &new_len,
+ &new_compressed_len,
+ &serialize_flags) < 0 ) )
+ {
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \
- "unable to flush entry")
+ "unable to pre-serialize entry")
}
-#ifdef H5_HAVE_PARALLEL
- if ( flush_flags != H5C_CALLBACK__NO_FLAGS_SET ) {
+ /* set cache_ptr->slist_change_in_pre_serialize if the
+ * slist was modified.
+ */
+ if ( cache_ptr->slist_changed )
+ cache_ptr->slist_change_in_pre_serialize = TRUE;
- /* In the parallel case, flush operations can
- * cause problems. If they occur, scream and
- * die.
+ /* Check for any flags set in the pre-serialize callback */
+ 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 |
+ H5C__SERIALIZE_COMPRESSED_FLAG))
+ {
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \
+ "unknown serialize flag(s)")
+ }
+#ifdef H5_HAVE_PARALLEL
+ /* In the parallel case, resizes and moves in
+ * the serialize operation can cause problems.
+ * If they occur, scream and die.
*
* At present, in the parallel case, the aux_ptr
* will only be set if there is more than one
@@ -8833,106 +9415,387 @@ H5C_flush_single_entry(H5F_t * f,
if ( cache_ptr->aux_ptr != NULL )
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
- "resize/move in serialize occured in parallel case.")
+ "resize/move in serialize occured in parallel case.")
+#endif /* H5_HAVE_PARALLEL */
+
+ /* Resize the buffer if required */
+ if ( ( ( ! entry_ptr->compressed ) &&
+ ( serialize_flags & H5C__SERIALIZE_RESIZED_FLAG ) ) ||
+ ( ( entry_ptr->compressed ) &&
+ ( serialize_flags & H5C__SERIALIZE_COMPRESSED_FLAG ) ) )
+ {
+ size_t new_image_size;
+
+ if ( entry_ptr->compressed )
+ new_image_size = new_compressed_len;
+ else
+ new_image_size = new_len;
+
+ HDassert(new_image_size > 0);
+
+ /* Release the current image */
+ if ( entry_ptr->image_ptr )
+ {
+ entry_ptr->image_ptr = H5MM_xfree(entry_ptr->image_ptr);
+ }
+
+ /* Allocate a new image buffer */
+ entry_ptr->image_ptr =
+ H5MM_malloc(new_image_size + H5C_IMAGE_EXTRA_SPACE);
+
+ if ( NULL == entry_ptr->image_ptr )
+ {
+ 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_image_size,
+ H5C_IMAGE_SANITY_VALUE,
+ H5C_IMAGE_EXTRA_SPACE);
+
+#endif /* H5C_DO_MEMORY_SANITY_CHECKS */
+
+ } /* end if */
+
+ /* If required, update the entry and the cache data structures
+ * for a resize.
+ */
+ if ( serialize_flags & H5C__SERIALIZE_RESIZED_FLAG ) {
+
+ 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));
+
+ /* The entry can't be protected since we are
+ * in the process of flushing it. Thus we must
+ * update the replacement policy data
+ * structures for the size change. The macro
+ * deals with the pinned case.
+ */
+ H5C__UPDATE_RP_FOR_SIZE_CHANGE(cache_ptr, entry_ptr, new_len);
+
+ /* as we haven't updated the cache data structures for
+ * for the flush or flush destroy yet, the entry should
+ * be in the slist. Thus update it for the size change.
+ */
+ HDassert(entry_ptr->in_slist);
+ H5C__UPDATE_SLIST_FOR_SIZE_CHANGE(cache_ptr, entry_ptr->size, \
+ new_len)
+
+ /* if defined, update *entry_size_change_ptr for the
+ * change in entry size.
+ */
+ if(entry_size_change_ptr != NULL)
+ *entry_size_change_ptr = (int64_t)new_len - (int64_t)(entry_ptr->size);
+
+ /* 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 H5C_DO_SANITY_CHECKS
+ int64_t saved_slist_len_increase;
+ int64_t saved_slist_size_increase;
+#endif /* H5C_DO_SANITY_CHECKS */
+
+ H5C__UPDATE_STATS_FOR_MOVE(cache_ptr, entry_ptr)
+
+ if ( entry_ptr->addr == old_addr )
+ {
+ /* we must update cache data structures for the
+ * change in address.
+ */
+
+ /* delete the entry from the hash table and the slist */
+ H5C__DELETE_FROM_INDEX(cache_ptr, entry_ptr)
+ H5C__REMOVE_ENTRY_FROM_SLIST(cache_ptr, entry_ptr)
+
+ /* update the entry for its new address */
+ entry_ptr->addr = new_addr;
+
+ /* and then reinsert in the index and slist */
+ H5C__INSERT_IN_INDEX(cache_ptr, entry_ptr, FAIL)
+
+#if H5C_DO_SANITY_CHECKS
+ /* save cache_ptr->slist_len_increase and
+ * cache_ptr->slist_size_increase before the
+ * reinsertion into the slist, and restore
+ * them afterwards to avoid skewing our sanity
+ * checking.
+ */
+ saved_slist_len_increase = cache_ptr->slist_len_increase;
+ saved_slist_size_increase = cache_ptr->slist_size_increase;
+#endif /* H5C_DO_SANITY_CHECKS */
+
+ H5C__INSERT_ENTRY_IN_SLIST(cache_ptr, entry_ptr, FAIL)
+
+#if H5C_DO_SANITY_CHECKS
+ cache_ptr->slist_len_increase = saved_slist_len_increase;
+ cache_ptr->slist_size_increase = saved_slist_size_increase;
+#endif /* H5C_DO_SANITY_CHECKS */
+ }
+ else /* move is alread done for us -- just do sanity checks */
+ {
+ HDassert(entry_ptr->addr == new_addr);
+ }
+ } /* end if */
+
+ if ( serialize_flags & H5C__SERIALIZE_COMPRESSED_FLAG ) {
+ /* just save the new compressed entry size in
+ * entry_ptr->compressed_size. We don't need to
+ * do more, as compressed size is only used for I/O.
+ */
+ HDassert(entry_ptr->compressed);
+ entry_ptr->compressed_size = new_compressed_len;
+ }
+ } /* end if ( serialize_flags != H5C__SERIALIZE_NO_FLAGS_SET ) */
+
+ /* Serialize object into buffer */
+ {
+ size_t image_len;
+
+ if ( entry_ptr->compressed )
+ image_len = entry_ptr->compressed_size;
+ else
+ image_len = entry_ptr->size;
+
+ /* reset cache_ptr->slist_changed so we can detect slist
+ * modifications in the serialize call.
+ */
+ cache_ptr->slist_changed = FALSE;
+
+
+ if ( entry_ptr->type->serialize(f, entry_ptr->image_ptr,
+ image_len,
+ (void *)entry_ptr) < 0 )
+ {
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \
+ "unable to serialize entry")
+ }
+
+ /* set cache_ptr->slist_change_in_serialize if the
+ * slist was modified.
+ */
+ if ( cache_ptr->slist_changed )
+ cache_ptr->slist_change_in_pre_serialize = TRUE;
+#if H5C_DO_MEMORY_SANITY_CHECKS
+
+ HDassert(0 == HDmemcmp(((uint8_t *)entry_ptr->image_ptr) +
+ image_len,
+ H5C_IMAGE_SANITY_VALUE,
+ H5C_IMAGE_EXTRA_SPACE));
+
+#endif /* H5C_DO_MEMORY_SANITY_CHECKS */
+
+ entry_ptr->image_up_to_date = TRUE;
+ }
+ } /* end if ( ! (entry_ptr->image_up_to_date) ) */
+
+ /* Finally, write the image to disk.
+ *
+ * Note that if either the H5C__CLASS_NO_IO_FLAG or the
+ * the H5AC__CLASS_SKIP_WRITES flag is set in the
+ * in the entry's type, we silently skip the write. This
+ * flag should only be used in test code.
+ */
+ if ( ( ((entry_ptr->type->flags) & H5C__CLASS_NO_IO_FLAG) == 0 ) &&
+ ( ((entry_ptr->type->flags) & H5C__CLASS_SKIP_WRITES) == 0 ) )
+ {
+ /* If compression is not enabled, the size of the entry on
+ * disk is entry_prt->size. However if entry_ptr->compressed
+ * is TRUE, the on disk size is entry_ptr->compressed_size.
+ */
+ size_t image_size;
+
+ if ( entry_ptr->compressed )
+ image_size = entry_ptr->compressed_size;
+ else
+ image_size = entry_ptr->size;
+
+ if ( ( H5F_block_write(f, entry_ptr->type->mem_type,
+ entry_ptr->addr,
+ image_size, dxpl_id,
+ entry_ptr->image_ptr) < 0 ) )
+ {
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \
+ "Can't write image to file.")
}
-#endif /* H5_HAVE_PARALLEL */
}
- if ( ( ! destroy ) && ( entry_ptr->in_slist ) ) {
+ /* if the entry has a notify callback, notify it that we have
+ * just flushed the entry.
+ */
- H5C__REMOVE_ENTRY_FROM_SLIST(cache_ptr, entry_ptr)
+ if ( ( entry_ptr->type->notify ) &&
+ ( (entry_ptr->type->notify)(H5C_NOTIFY_ACTION_AFTER_FLUSH,
+ entry_ptr) < 0 ) )
+ {
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, \
+ "can't notify client of entry flush")
+ }
+ } /* if ( ( entry_ptr != NULL ) && ( write_entry ) ) */
+
+
+ /* At this point, all pre-serialize and serialize calls have been
+ * made if it was appropriate to make them. Similarly, the entry
+ * has been written to disk if desired.
+ *
+ * Thus it is now safe to update the cache data structures for the
+ * flush.
+ */
+
+ if ( entry_ptr != NULL )
+ {
+ /* start by updating the statistics */
+
+ if ( clear_only ) {
+
+ /* only log a clear if the entry was dirty */
+ if ( was_dirty ) {
+
+ H5C__UPDATE_STATS_FOR_CLEAR(cache_ptr, entry_ptr)
+ }
+ } else if ( write_entry ) {
+
+ HDassert( was_dirty );
+
+ /* only log a flush if we actually wrote to disk */
+ H5C__UPDATE_STATS_FOR_FLUSH(cache_ptr, entry_ptr)
}
- if ( ( ! destroy ) && ( was_dirty ) ) {
+ if ( destroy )
+ {
+ if ( take_ownership )
+ {
+ HDassert(!destroy_entry);
+ }
+ else
+ {
+ HDassert(destroy_entry);
+ }
- H5C__UPDATE_INDEX_FOR_ENTRY_CLEAN(cache_ptr, entry_ptr);
+ H5C__UPDATE_STATS_FOR_EVICTION(cache_ptr, entry_ptr, \
+ take_ownership)
}
- if ( ! destroy ) { /* i.e. if the entry still exists */
+ /* If the entry's type has a 'notify' callback and the entry is about
+ * to be removed from the cache, send a 'before eviction' notice while
+ * the entry is still fully integrated in the cache.
+ */
+ if ( destroy ) {
- HDassert( !(entry_ptr->is_dirty) );
- HDassert( !(entry_ptr->flush_marker) );
- HDassert( !(entry_ptr->in_slist) );
- HDassert( !(entry_ptr->is_protected) );
- HDassert( !(entry_ptr->is_read_only) );
- HDassert( (entry_ptr->ro_ref_count) == 0 );
+ if ( ( entry_ptr->type->notify ) &&
+ ( (entry_ptr->type->notify)(H5C_NOTIFY_ACTION_BEFORE_EVICT,
+ entry_ptr) < 0 ) )
+ {
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, \
+ "can't notify client about entry to evict")
+ }
+ } /* end if */
- if ( (flush_flags & H5C_CALLBACK__SIZE_CHANGED_FLAG) != 0 ) {
- /* The entry size changed as a result of the flush.
- *
- * Most likely, the entry was compressed, and the
- * new version is of a different size than the old.
- *
- * In any case, we must update entry and cache size
- * accordingly.
- */
- size_t new_size;
+ /* Update the cache internal data structures. */
+ if ( destroy )
+ {
+ /* Update the cache internal data structures as appropriate
+ * for a destroy. Specifically:
+ *
+ * 1) Delete it from the index
+ *
+ * 2) Delete it from the skip list if requested.
+ *
+ * 3) Update the replacement policy for eviction
+ *
+ * Finally, if the destroy_entry flag is set, discard the
+ * entry.
+ */
- if ( (entry_ptr->type->size)(f, (void *)entry_ptr, &new_size)
- < 0 ) {
+ H5C__DELETE_FROM_INDEX(cache_ptr, entry_ptr)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGETSIZE, FAIL, \
- "Can't get entry size after flush")
- }
+ if ( ( entry_ptr->in_slist ) &&
+ ( del_entry_from_slist_on_destroy ) ) {
- if ( new_size != entry_ptr->size ) {
+ H5C__REMOVE_ENTRY_FROM_SLIST(cache_ptr, entry_ptr)
+ }
- HDassert( entry_ptr->size < H5C_MAX_ENTRY_SIZE );
+ H5C__UPDATE_RP_FOR_EVICTION(cache_ptr, entry_ptr, FAIL)
- /* update the hash table for the size change
- * We pass TRUE as the was_clean parameter, as we
- * have already updated the clean and dirty index
- * size fields for the fact that the entry has
- * been flushed. (See above call to
- * H5C__UPDATE_INDEX_FOR_ENTRY_CLEAN()).
- */
- H5C__UPDATE_INDEX_FOR_SIZE_CHANGE((cache_ptr), \
- (entry_ptr->size), \
- (new_size), \
- (entry_ptr), \
- (TRUE))
-
- /* The entry can't be protected since we just flushed it.
- * Thus we must update the replacement policy data
- * structures for the size change. The macro deals
- * with the pinned case.
- */
- H5C__UPDATE_RP_FOR_SIZE_CHANGE(cache_ptr, entry_ptr, \
- new_size)
+ /* Destroy parent flush dependencies and free flush dependency parent
+ * array, if necessary */
+ HDassert( entry_ptr->flush_dep_nchildren == 0 );
+ if ( entry_ptr->flush_dep_parent_nalloc > 0 ) {
- /* The entry can't be in the slist, so no need to update
- * the slist for the size change.
- */
+ while ( entry_ptr->flush_dep_nparents > 0 ) {
- /* update stats for the size change */
- H5C__UPDATE_STATS_FOR_ENTRY_SIZE_CHANGE(cache_ptr, \
- entry_ptr, \
- new_size)
+ /* Since the flush_dep_parent array willbe resized every
+ * a flush dependency is destroyed, we do not have to
+ * iterate over all indices. Instead, always destroy the
+ * last dependency so we can skip the memmove() in
+ * H5C_destroy_flush_dependency(). */
+ if ( H5C_destroy_flush_dependency(entry_ptr->flush_dep_parent[entry_ptr->flush_dep_nparents - 1],
+ entry_ptr) < 0 ) {
- /* finally, update the entry size proper */
- entry_ptr->size = new_size;
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTUNDEPEND, FAIL, \
+ "Can't remove flush dependency")
+ }
}
+
+ /* H5C_destroy_flush_dependency should have freed the parent
+ * array when it became empty */
+ HDassert( ! (entry_ptr->flush_dep_parent) );
+ HDassert( entry_ptr->flush_dep_parent_nalloc == 0 );
}
+ }
+ else
+ {
+ HDassert(clear_only || write_entry);
+ HDassert(entry_ptr->is_dirty);
+ HDassert(entry_ptr->in_slist);
+
+ /* We are either doing a flush or a clear.
+ *
+ * A clear and a flush are the same from the point of
+ * view of the replacement policy and the slist.
+ * Hence no differentiation between them.
+ *
+ * JRM -- 7/7/07
+ */
- if ( (flush_flags & H5C_CALLBACK__MOVED_FLAG) != 0 ) {
+ H5C__UPDATE_RP_FOR_FLUSH(cache_ptr, entry_ptr, FAIL)
+
+ H5C__REMOVE_ENTRY_FROM_SLIST(cache_ptr, entry_ptr)
- /* The entry was moved as the result of the flush.
- *
- * Most likely, the entry was compressed, and the
- * new version is larger than the old and thus had
- * to be relocated.
- *
- * At preset, all processing for this case is
- * handled elsewhere. But lets keep the if statement
- * around just in case.
- */
+ /* mark the entry as clean and update the index for
+ * entry clean. Also, call the clear callback
+ * if defined.
+ */
+
+ entry_ptr->is_dirty = FALSE;
+
+ H5C__UPDATE_INDEX_FOR_ENTRY_CLEAN(cache_ptr, entry_ptr);
+
+ if ( ( entry_ptr->type->clear != NULL ) &&
+ ( (entry_ptr->type->clear)(f, (void *)entry_ptr, FALSE) ) )
+ {
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \
+ "unable to clear entry")
}
- /* Propagate the clean flag up the flush dependency chain if
+ /* Propagate the clean flag up the flush dependency chain if
* appropriate */
if ( was_dirty ) {
@@ -8948,9 +9811,159 @@ H5C_flush_single_entry(H5F_t * f,
}
}
- entry_ptr->flush_in_progress = FALSE;
}
+ /* reset the flush_in progress flag */
+
+ entry_ptr->flush_in_progress = FALSE;
+
+ } /* end if */
+
+
+ /* Internal cache data structures should now be up to date, and
+ * consistant with the status of the entry.
+ *
+ * Now discard the entry if appropriate.
+ */
+ if ( entry_ptr != NULL )
+ {
+ if ( destroy )
+ {
+ /* start by freeing the buffer for the on disk image */
+ if(entry_ptr->image_ptr != NULL)
+ entry_ptr->image_ptr = H5MM_xfree(entry_ptr->image_ptr);
+
+ /* Check whether we should free the space in the file that
+ * the entry occupies
+ */
+ if ( free_file_space )
+ {
+
+ size_t fsf_size;
+
+ /* Sanity checks */
+ HDassert(H5F_addr_defined(entry_ptr->addr));
+ HDassert(!H5F_IS_TMP_ADDR(f, entry_ptr->addr));
+#ifndef NDEBUG
+{
+ hbool_t curr_compressed = FALSE;
+ size_t curr_len;
+ size_t curr_compressed_len = 0;
+
+ /* Get the actual image size for the thing again */
+ entry_ptr->type->image_len((void *)entry_ptr, &curr_len, &curr_compressed, &curr_compressed_len);
+ HDassert(curr_len == entry_ptr->size);
+ HDassert(curr_compressed == entry_ptr->compressed);
+ HDassert(curr_compressed_len == entry_ptr->compressed_size);
+}
+#endif /* NDEBUG */
+
+ /* if the file space free size callback is defined, use
+ * it to get the size of the block of file space to free.
+ * Otherwise use entry_ptr->compressed_size if
+ * entry_ptr->compressed == TRUE, and entry_ptr->size
+ * if entry_ptr->compressed == FALSE.
+ */
+ if ( entry_ptr->type->fsf_size )
+ {
+ if ( (entry_ptr->type->fsf_size)((void *)entry_ptr,
+ &fsf_size) < 0 )
+ {
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFREE, FAIL, \
+ "unable to get file space free size")
+ }
+ }
+ else if ( entry_ptr->compressed ) /* use compressed size */
+ {
+ fsf_size = entry_ptr->compressed_size;
+ }
+ else /* no file space free size callback -- use entry size */
+ {
+ fsf_size = entry_ptr->size;
+ }
+
+ /* Release the space on disk */
+ if ( H5MF_xfree(f, entry_ptr->type->mem_type, dxpl_id,
+ entry_ptr->addr, (hsize_t)fsf_size) < 0)
+ {
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFREE, FAIL, \
+ "unable to free file space for cache entry")
+ }
+ } /* end if ( free_file_space ) */
+
+
+ /* Reset the pointer to the cache the entry is within. -QAK */
+ entry_ptr->cache_ptr = NULL;
+
+ /* increment entries_removed_counter and set
+ * last_entry_removed_ptr. As we are likely abuut to
+ * free the entry, recall that last_entry_removed_ptr
+ * must NEVER be dereferenced.
+ *
+ * Recall that these fields are maintained to allow functions
+ * that perform scans of lists of entries to detect the
+ * unexpected removal of entries (via expunge, eviction,
+ * or take ownership at present), so that they can re-start
+ * their scans if necessary.
+ */
+ cache_ptr->last_entry_removed_ptr++;
+ cache_ptr->last_entry_removed_ptr = entry_ptr;
+
+ /* Check for actually destroying the entry in memory */
+ /* (As opposed to taking ownership of it) */
+ if ( destroy_entry )
+ {
+ /* if the entry is dirty and it has a clear callback,
+ * call this callback now. Since this callback exists,
+ * it follows tht the client maintains its own dirty bits,
+ * which must be cleared before the entry is freed to avoid
+ * sanity check failures. Also clear the dirty flag for
+ * the same reason.
+ */
+
+ if ( entry_ptr->is_dirty ) {
+
+ entry_ptr->is_dirty = FALSE;
+
+ if ( ( entry_ptr->type->clear != NULL ) &&
+ ( (entry_ptr->type->clear)(f, (void *)entry_ptr, TRUE) ) )
+ {
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \
+ "unable to clear entry")
+ }
+ }
+
+ /* we are about to discard the in core representation --
+ * set the magic field to bad magic so we can detect a
+ * freed entry if we see one.
+ */
+ entry_ptr->magic = H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC;
+
+
+ /* verify that the image has been freed */
+ HDassert( entry_ptr->image_ptr == NULL );
+
+ if ( entry_ptr->type->free_icr((void *)entry_ptr) < 0 )
+ {
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \
+ "free_icr callback failed.")
+ }
+ }
+ else
+ {
+ HDassert(take_ownership);
+
+ /* client is taking ownership of the entry.
+ * set bad magic here too so the cache will choke
+ * unless the entry is re-inserted properly
+ */
+ entry_ptr->magic = H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC;
+ }
+ } /* if ( destroy ) */
+ }
+
+ if ( entry_ptr != NULL )
+ {
if ( cache_ptr->log_flush ) {
status = (cache_ptr->log_flush)(cache_ptr, addr, was_dirty, flags);
@@ -8964,14 +9977,94 @@ H5C_flush_single_entry(H5F_t * f,
}
done:
- HDassert( ( destroy ) ||
+
+ HDassert( ( ret_value != SUCCEED ) || ( destroy_entry ) ||
( ( entry_ptr ) && ( ! entry_ptr->flush_in_progress ) ) );
+
+ HDassert( ( ret_value != SUCCEED ) || ( destroy_entry ) ||
+ ( take_ownership ) ||
+ ( ( entry_ptr ) && ( ! entry_ptr->is_dirty ) ) );
+
FUNC_LEAVE_NOAPI(ret_value)
} /* H5C_flush_single_entry() */
/*-------------------------------------------------------------------------
*
+ * Function: H5C_verify_len_eoa
+ *
+ * Purpose: Verify that 'len' does not exceed eoa when 'actual' is
+ * false i.e. 'len" is the initial speculative length from
+ * get_load_size callback with null image pointer.
+ * If exceed, adjust 'len' accordingly.
+ *
+ * Verify that 'len' should not exceed eoa when 'actual' is
+ * true i.e. 'len' is the actual length from get_load_size
+ * callback with non-null image pointer.
+ * If exceed, return error.
+ *
+ * The coding is copied and moved from H5C_load_entry().
+ *
+ * Return: FAIL if error is detected, SUCCEED otherwise.
+ *
+ * Programmer:
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C_verify_len_eoa (H5F_t * f,
+ const H5C_class_t * type,
+ haddr_t addr,
+ size_t *len,
+ htri_t actual)
+{
+ haddr_t eoa; /* End-of-allocation in the file */
+ H5FD_mem_t cooked_type;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ /* if type == H5FD_MEM_GHEAP, H5F_block_read() forces
+ * type to H5FD_MEM_DRAW via its call to H5F__accum_read().
+ * Thus we do the same for purposes of computing the eoa
+ * for sanity checks.
+ */
+ cooked_type = (type->mem_type == H5FD_MEM_GHEAP) ? H5FD_MEM_DRAW : type->mem_type;
+
+ /* Get the file's end-of-allocation value */
+ eoa = H5F_get_eoa(f, cooked_type);
+
+ HDassert(H5F_addr_defined(eoa));
+
+ /* Check for bad address in general */
+ if ( H5F_addr_gt(addr, eoa) )
+ HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "address of object past end of allocation")
+
+ /* Check if the amount of data to read will be past the eoa */
+ if( H5F_addr_gt((addr + *len), eoa) ) {
+
+ if(actual)
+ HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "actual len exceeds EOA.")
+ else
+ /* Trim down the length of the metadata */
+ /* Note that for some cache clients, this will cause an
+ * assertion failure. JRM -- 8/29/14
+ */
+ *len = (size_t)(eoa - addr);
+ }
+
+ if ( *len <= 0 )
+ HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "len not positive after adjustment for EOA.")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* H5C_verify_len_eoa() */
+
+
+
+/*-------------------------------------------------------------------------
+ *
* Function: H5C_load_entry
*
* Purpose: Attempt to load the entry at the specified disk address
@@ -8995,8 +10088,19 @@ H5C_load_entry(H5F_t * f,
haddr_t addr,
void * udata)
{
+ hbool_t dirty = FALSE; /* Flag indicating whether thing was dirtied during deserialize */
+ hbool_t compressed = FALSE; /* flag indicating whether thing */
+ /* will be run through filters on */
+ /* on read and write. Usually FALSE */
+ /* set to true if appropriate. */
+ size_t compressed_size = 0; /* entry compressed size if */
+ /* known -- otherwise uncompressed. */
+ /* Zero indicates compression not */
+ /* enabled. */
+ void * image = NULL; /* Buffer for disk image */
void * thing = NULL; /* Pointer to thing loaded */
H5C_cache_entry_t * entry; /* Alias for thing loaded, as cache entry */
+ size_t len; /* Size of image in file */
void * ret_value; /* Return value */
FUNC_ENTER_NOAPI_NOINIT
@@ -9005,14 +10109,223 @@ H5C_load_entry(H5F_t * f,
HDassert(f->shared);
HDassert(f->shared->cache);
HDassert(type);
- HDassert(type->load);
- HDassert(type->size);
+
+ /* verify absence of prohibited or unsupported type flag combinations */
+ HDassert(!(type->flags & H5C__CLASS_NO_IO_FLAG));
+
+ /* for now, we do not combine the speculative load and compressed flags */
+ HDassert(!((type->flags & H5C__CLASS_SPECULATIVE_LOAD_FLAG) &&
+ (type->flags & H5C__CLASS_COMPRESSED_FLAG)));
+
+ /* Can't see how skip reads could be usefully combined with
+ * either the speculative read or compressed flags. Hence disallow.
+ */
+ HDassert(!((type->flags & H5C__CLASS_SKIP_READS) &&
+ (type->flags & H5C__CLASS_SPECULATIVE_LOAD_FLAG)));
+ HDassert(!((type->flags & H5C__CLASS_SKIP_READS) &&
+ (type->flags & H5C__CLASS_COMPRESSED_FLAG)));
+
HDassert(H5F_addr_defined(addr));
+ HDassert(type->get_load_size);
+ HDassert(type->deserialize);
+
+ /* Call the get_load_size callback, to retrieve the initial
+ * size of image
+ */
+ if(type->get_load_size(NULL, udata, &len, NULL, NULL, NULL) < 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) {
+
+/* Quincey has added patches for eoa calculations -- leave the original
+ * code around until we see the effect of these patches.
+ * JRM -- 1/1/15
+ */
+#if 0 /* original code */ /* JRM */
+ /* the original version of this code has several problems:
+ *
+ * First, the sblock is not available until the sblock
+ * has been read in, which causes a seg fault. This is
+ * dealt with easily enough by testing to see if
+ * f->shared->sblock is NULL, and calling H5FD_get_base_addr()
+ * to obtain the base addr when it is.
+ *
+ * The second issue is more subtle. H5F_get_eoa() calls
+ * H5FD_get_eoa(). However, this function returns the EOA as
+ * a relative address -- i.e. relative to the base address.
+ * This means that the base addr + addr < eoa sanity check will
+ * fail whenever the super block is not at address 0 when
+ * reading in the first chunk of the super block.
+ *
+ * To address these issues, I have rewritten the code to
+ * simply verify that the address plus length is less than
+ * the eoa. I think this is sufficient, but further testing
+ * should tell me if it isn't.
+ * JRM -- 8/29/14
+ */
+ haddr_t eoa; /* End-of-allocation in the file */
+ haddr_t base_addr; /* Base address of file data */
+
+ /* Get the file's end-of-allocation value */
+ eoa = H5F_get_eoa(f, type->mem_type);
+ HDassert(H5F_addr_defined(eoa));
+
+ /* Get the file's base address */
+ if ( f->shared->sblock )
+
+ base_addr = H5F_BASE_ADDR(f);
+
+ else { /* sblock not loaded yet -- use file driver info */
+
+ HDassert(f->shared->lf);
+ base_addr = H5FD_get_base_addr(f->shared->lf);
+
+ }
+ HDassert(H5F_addr_defined(base_addr));
+
+ /* Check for bad address in general */
+ if((addr + base_addr) > eoa)
+ HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, NULL, \
+ "address of object past end of allocation")
+
+ /* Check if the amount of data to read will be past the eoa */
+ if((addr + base_addr + len) > eoa)
+ /* Trim down the length of the metadata */
+ len = (size_t)(eoa - (addr + base_addr));
+
+#else /* modified code */ /* JRM */
+
+ if(H5C_verify_len_eoa(f, type, addr, &len, FALSE) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, NULL, "invalid len with respect to EOA.")
+
+#endif /* modified code */ /* JRM */
+ }
+ /* Allocate the buffer for reading the on-disk entry image */
+ if(NULL == (image = 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(((uint8_t *)image) + len, H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE);
+#endif /* H5C_DO_MEMORY_SANITY_CHECKS */
+
+ /* 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;
+ void *new_image; /* Pointer to image */
+
+ /* Get the # of read attempts */
+ max_tries = tries = H5F_GET_READ_ATTEMPTS(f);
+
+ /*
+ * This do/while loop performs the following till the metadata checksum is correct or the
+ * file's allowed read attempts are reached.
+ * --read the metadata
+ * --determine the actual size of the metadata
+ * --perform checksum verification
+ */
+ do {
+ compressed = FALSE;
+ compressed_size = 0;
+
+ 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 = new_image;
+ }
+
+ if(H5F_block_read(f, type->mem_type, addr, len, dxpl_id, image) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_READERROR, NULL, "Can't read image*")
+
+ actual_len = len;
+
+ if(type->get_load_size(image, udata, &len, &actual_len, &compressed, &compressed_size) < 0)
+ continue; /* Transfer control to while() and count towards retries */
+
+ HDassert(((type->flags & H5C__CLASS_COMPRESSED_FLAG) != 0) ||
+ ((compressed == FALSE) && (compressed_size == 0)));
+ HDassert((compressed == TRUE) || (compressed_size == 0));
+
+ if(actual_len != len) {
+
+ if(type->flags & H5C__CLASS_COMPRESSED_FLAG) {
+ /* if actual_len != len, then compression must be enabled on the entry.
+ * In this case, the get_load_size callback should have set compressed to TRUE,
+ * compressed_size to the compressed size (which must equal to len),
+ * and actual_len to the uncompressed size of the entry,
+ * We can't verify the uncompressed size, but we can verify the rest
+ * with the following assertions.
+ */
+ HDassert(compressed);
+ HDassert(compressed_size == len);
+ } else if(type->flags & H5C__CLASS_SPECULATIVE_LOAD_FLAG) {
+
+ size_t temp_len = actual_len;
+
+ /* compressed must be FALSE, and compressed_size
+ * must be zero.
+ */
+ HDassert(!compressed);
+ HDassert(compressed_size == 0);
+
+ if(H5C_verify_len_eoa(f, type, addr, &temp_len, TRUE) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, NULL, "actual_len exceeds EOA.")
+ HDassert(temp_len == actual_len);
- if(NULL == (thing = (type->load)(f, dxpl_id, addr, udata)))
+ 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 = new_image;
+#if H5C_DO_MEMORY_SANITY_CHECKS
- HGOTO_ERROR(H5E_CACHE, H5E_CANTLOAD, NULL, "unable to load entry")
+ HDmemcpy(((uint8_t *)image) + actual_len, H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE);
+
+#endif /* H5C_DO_MEMORY_SANITY_CHECKS */
+ /* 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(actual_len > len) {
+
+ if(H5F_block_read(f, type->mem_type, addr+len, actual_len-len, dxpl_id, image+len) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTLOAD, NULL, "Can't read image")
+ }
+ } else { /* throw an error */
+ HGOTO_ERROR(H5E_CACHE, H5E_UNSUPPORTED, NULL,
+ "size of non-speculative, non-compressed object changed")
+ }
+ } /* end if (actual_len != len) */
+
+ if(type->verify_chksum == NULL)
+ break;
+
+ if((chk_ret = type->verify_chksum(image, actual_len, udata)) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_NOSPACE, NULL, "Failure from verify_chksum callback")
+ if(chk_ret == TRUE)
+ break;
+ } while(--tries);
+
+ /* Check for too many tries */
+ if(tries == 0)
+ 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)
+ }
+ len = actual_len;
+ } /* end if !H5C__CLASS_SKIP_READS */
+ /* Deserialize the on-disk image into the native memory form */
+ if(NULL == (thing = type->deserialize(image, len, udata, &dirty)))
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTLOAD, NULL, "Can't deserialize image")
entry = (H5C_cache_entry_t *)thing;
@@ -9020,35 +10333,39 @@ H5C_load_entry(H5F_t * f,
*
* However, when this code is used in the metadata cache, it is
* possible that object headers will be dirty at this point, as
- * the load function will alter object headers if necessary to
+ * the deserialize function will alter object headers if necessary to
* fix an old bug.
*
- * To support this bug fix, I have replace the old assert:
- *
- * HDassert( entry->is_dirty == FALSE );
- *
- * with:
+ * In the following assert:
*
- * HDassert( ( entry->is_dirty == FALSE ) || ( type->id == 5 ) );
+ * HDassert( ( dirty == FALSE ) || ( type->id == 5 || type->id == 6 ) );
*
- * Note that type id 5 is associated with object headers in the metadata
- * cache.
+ * note that type ids 5 & 6 are associated with object headers in the
+ * metadata cache.
*
* When we get to using H5C for other purposes, we may wish to
* tighten up the assert so that the loophole only applies to the
* metadata cache.
*/
- HDassert( ( entry->is_dirty == FALSE ) || ( type->id == 5 ) );
-#ifndef NDEBUG
+ HDassert( ( dirty == FALSE ) || ( type->id == 5 || type->id == 6) );
+
entry->magic = H5C__H5C_CACHE_ENTRY_T_MAGIC;
-#endif /* NDEBUG */
entry->cache_ptr = f->shared->cache;
entry->addr = addr;
+ entry->size = len;
+ HDassert(entry->size < H5C_MAX_ENTRY_SIZE);
+ entry->compressed = compressed;
+ entry->compressed_size = compressed_size;
+ entry->image_ptr = image;
+ entry->image_up_to_date = TRUE;
entry->type = type;
+ entry->is_dirty = dirty;
+ entry->dirtied = FALSE;
entry->is_protected = FALSE;
entry->is_read_only = FALSE;
entry->ro_ref_count = 0;
+ entry->is_pinned = FALSE;
entry->in_slist = FALSE;
entry->flush_marker = FALSE;
#ifdef H5_HAVE_PARALLEL
@@ -9057,13 +10374,6 @@ H5C_load_entry(H5F_t * f,
#endif /* H5_HAVE_PARALLEL */
entry->flush_in_progress = FALSE;
entry->destroy_in_progress = FALSE;
- entry->free_file_space_on_destroy = FALSE;
-
- if((type->size)(f, thing, &(entry->size)) < 0)
-
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGETSIZE, NULL, "Can't get size of thing")
-
- HDassert( entry->size < H5C_MAX_ENTRY_SIZE );
/* Initialize flush dependency height fields */
entry->flush_dep_parent = NULL;
@@ -9085,6 +10395,18 @@ H5C_load_entry(H5F_t * f,
ret_value = thing;
done:
+ /* Cleanup on error */
+ if(NULL == ret_value) {
+
+ /* Release resources */
+ if ( thing && type->free_icr(thing) < 0 )
+
+ HDONE_ERROR(H5E_CACHE, H5E_CANTFLUSH, NULL, \
+ "free_icr callback failed")
+
+ if(image)
+ image = H5MM_xfree(image);
+ } /* end if */
FUNC_LEAVE_NOAPI(ret_value)
} /* H5C_load_entry() */
@@ -9123,36 +10445,45 @@ done:
*
* Programmer: John Mainzer, 5/14/04
*
- * JRM -- 11/13/08
- * Modified function to always observe the min_clean_size
- * whether we are maintaining the clean and dirt LRU lists
- * or not. To do this, we had to add the new clean_index_size
- * and dirty_index_size fields to H5C_t, and supporting code
- * as needed throughout the cache.
+ * Changes: Modified function to skip over entries with the
+ * flush_in_progress flag set. If this is not done,
+ * an infinite recursion is possible if the cache is
+ * full, and the pre-serialize or serialize routine
+ * attempts to load another entry.
*
- * The purpose of this modification is to avoid "metadata
- * blizzards" in the write only case. In such instances,
- * the cache was allowed to fill with dirty metadata. When
- * we finally needed to evict an entry to make space, we had
- * to flush out a whole cache full of metadata -- which has
- * interesting performance effects. We hope to avoid (or
- * perhaps more accurately hide) this effect by maintaining
- * the min_clean_size, which should force us to start flushing
- * entries long before we actually have to evict something
- * to make space.
+ * This error was exposed by a re-factor of the
+ * H5C_flush_single_entry() routine. However, it was
+ * a potential bug from the moment that entries were
+ * allowed to load other entries on flush.
+ *
+ * In passing, note that the primary and secondary dxpls
+ * mentioned in the comment above have been replaced by
+ * a single dxpl at some point, and thus the discussion
+ * above is somewhat obsolete. Date of this change is
+ * unkown.
+ *
+ * JRM -- 12/26/14
+ *
+ * Modified function to detect deletions of entries
+ * during a scan of the LRU, and where appropriate,
+ * restart the scan to avoid proceeding with a next
+ * entry that is no longer in the cache.
+ *
+ * Note the absence of checks after flushes of clean
+ * entries. As a second entry can only be removed by
+ * by a call to the pre_serialize or serialize callback
+ * of the first, and as these callbacks will not be called
+ * on clean entries, no checks are needed.
+ *
+ * JRM -- 4/6/15
*
- * MAM -- 01/06/09
- * Added code to maintain clean_entries_skipped and total_entries
- * scanned statistics.
*-------------------------------------------------------------------------
*/
static herr_t
-H5C_make_space_in_cache(H5F_t * f,
- hid_t primary_dxpl_id,
- hid_t secondary_dxpl_id,
- size_t space_needed,
- hbool_t write_permitted,
- hbool_t * first_flush_ptr)
+H5C_make_space_in_cache(H5F_t * f,
+ hid_t dxpl_id,
+ size_t space_needed,
+ hbool_t write_permitted)
{
H5C_t * cache_ptr = f->shared->cache;
herr_t result;
@@ -9165,6 +10496,7 @@ H5C_make_space_in_cache(H5F_t * f,
size_t empty_space;
hbool_t prev_is_dirty = FALSE;
hbool_t didnt_flush_entry = FALSE;
+ hbool_t restart_scan;
H5C_cache_entry_t * entry_ptr;
H5C_cache_entry_t * prev_ptr;
H5C_cache_entry_t * next_ptr;
@@ -9176,13 +10508,12 @@ H5C_make_space_in_cache(H5F_t * f,
HDassert( f );
HDassert( cache_ptr );
HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC );
- HDassert( first_flush_ptr != NULL );
- HDassert( ( *first_flush_ptr == TRUE ) || ( *first_flush_ptr == FALSE ) );
HDassert( cache_ptr->index_size ==
(cache_ptr->clean_index_size + cache_ptr->dirty_index_size) );
if ( write_permitted ) {
+ restart_scan = FALSE;
initial_list_len = cache_ptr->LRU_list_len;
entry_ptr = cache_ptr->LRU_tail_ptr;
@@ -9213,6 +10544,7 @@ H5C_make_space_in_cache(H5F_t * f,
( entry_ptr != NULL )
)
{
+ HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert( !(entry_ptr->is_protected) );
HDassert( ! (entry_ptr->is_read_only) );
HDassert( (entry_ptr->ro_ref_count) == 0 );
@@ -9234,7 +10566,8 @@ H5C_make_space_in_cache(H5F_t * f,
didnt_flush_entry = TRUE;
result = SUCCEED;
- } else if ( (entry_ptr->type)->id != H5C__EPOCH_MARKER_TYPE) {
+ } else if ( ( (entry_ptr->type)->id != H5C__EPOCH_MARKER_TYPE ) &&
+ ( ! entry_ptr->flush_in_progress ) ) {
didnt_flush_entry = FALSE;
@@ -9249,14 +10582,29 @@ H5C_make_space_in_cache(H5F_t * f,
}
#endif /* H5C_COLLECT_CACHE_STATS */
+ /* reset entries_removed_counter and
+ * last_entry_removed_ptr prior to the call to
+ * H5C_flush_single_entry() so that we can spot
+ * unexpected removals of entries from the cache,
+ * and set the restart_scan flag if proceeding
+ * would be likely to cause us to scan an entry
+ * that is no longer in the cache.
+ */
+ cache_ptr->entries_removed_counter = 0;
+ cache_ptr->last_entry_removed_ptr = NULL;
+
result = H5C_flush_single_entry(f,
- primary_dxpl_id,
- secondary_dxpl_id,
- entry_ptr->type,
+ dxpl_id,
entry_ptr->addr,
H5C__NO_FLAGS_SET,
- first_flush_ptr,
- FALSE);
+ FALSE,
+ NULL);
+
+ if ( ( cache_ptr->entries_removed_counter > 1 ) ||
+ ( cache_ptr->last_entry_removed_ptr == prev_ptr ) )
+
+ restart_scan = TRUE;
+
} else if ( (cache_ptr->index_size + space_needed)
>
cache_ptr->max_cache_size ) {
@@ -9265,13 +10613,11 @@ H5C_make_space_in_cache(H5F_t * f,
#endif /* H5C_COLLECT_CACHE_STATS */
result = H5C_flush_single_entry(f,
- primary_dxpl_id,
- secondary_dxpl_id,
- entry_ptr->type,
+ dxpl_id,
entry_ptr->addr,
H5C__FLUSH_INVALIDATE_FLAG,
- first_flush_ptr,
- TRUE);
+ TRUE,
+ NULL);
} else {
/* We have enough space so don't flush clean entry.
@@ -9292,7 +10638,8 @@ H5C_make_space_in_cache(H5F_t * f,
} else {
- /* Skip epoch markers. Set result to SUCCEED to avoid
+ /* Skip epoch markers and entries that are in the process
+ * of being flushed. Set result to SUCCEED to avoid
* triggering the error code below.
*/
didnt_flush_entry = TRUE;
@@ -9306,26 +10653,20 @@ H5C_make_space_in_cache(H5F_t * f,
}
if ( prev_ptr != NULL ) {
-#ifndef NDEBUG
- if ( prev_ptr->magic != H5C__H5C_CACHE_ENTRY_T_MAGIC ) {
-
- /* something horrible has happened to *prev_ptr --
- * scream and die.
- */
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
- "*prev_ptr corrupt 1")
- }
-#endif /* NDEBUG */
if ( didnt_flush_entry ) {
- /* epoch markers don't get flushed, so the sanity checks
- * on normal entries will fail -- thus just set entry_ptr
- * to prev_ptr and go on.
- */
+ /* epoch markers don't get flushed, and we don't touch
+ * entries that are in the process of being flushed.
+ * Hence no need for sanity checks, as we haven't
+ * flushed anything. Thus just set entry_ptr to prev_ptr
+ * and go on.
+ */
entry_ptr = prev_ptr;
- } else if ( ( prev_ptr->is_dirty != prev_is_dirty )
+ } else if ( ( restart_scan )
+ ||
+ ( prev_ptr->is_dirty != prev_is_dirty )
||
( prev_ptr->next != next_ptr )
||
@@ -9336,7 +10677,9 @@ H5C_make_space_in_cache(H5F_t * f,
/* something has happened to the LRU -- start over
* from the tail.
*/
+ restart_scan = FALSE;
entry_ptr = cache_ptr->LRU_tail_ptr;
+ H5C__UPDATE_STATS_FOR_LRU_SCAN_RESTART(cache_ptr)
} else {
@@ -9426,13 +10769,11 @@ H5C_make_space_in_cache(H5F_t * f,
prev_ptr = entry_ptr->aux_prev;
result = H5C_flush_single_entry(f,
- primary_dxpl_id,
- secondary_dxpl_id,
- entry_ptr->type,
+ dxpl_id,
entry_ptr->addr,
H5C__FLUSH_INVALIDATE_FLAG,
- first_flush_ptr,
- TRUE);
+ TRUE,
+ NULL);
if ( result < 0 ) {
@@ -9440,9 +10781,15 @@ H5C_make_space_in_cache(H5F_t * f,
"unable to flush entry")
}
+ /* we are scanning the clean LRU, so the serialize function
+ * will not be called on any entry -- thus there is no
+ * concern about the list being modified out from under
+ * this function.
+ */
+
entry_ptr = prev_ptr;
entries_examined++;
- }
+ }
}
done:
@@ -9489,90 +10836,90 @@ H5C_validate_lru_list(H5C_t * cache_ptr)
HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC );
if ( ( ( cache_ptr->LRU_head_ptr == NULL )
- ||
- ( cache_ptr->LRU_tail_ptr == NULL )
- )
- &&
- ( cache_ptr->LRU_head_ptr != cache_ptr->LRU_tail_ptr )
+ ||
+ ( cache_ptr->LRU_tail_ptr == NULL )
+ )
+ &&
+ ( cache_ptr->LRU_head_ptr != cache_ptr->LRU_tail_ptr )
) {
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 1 failed")
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 1 failed")
}
if ( ( cache_ptr->LRU_list_len < 0 ) || ( cache_ptr->LRU_list_size < 0 ) ) {
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 2 failed")
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 2 failed")
}
if ( ( cache_ptr->LRU_list_len == 1 )
- &&
- ( ( cache_ptr->LRU_head_ptr != cache_ptr->LRU_tail_ptr )
- ||
- ( cache_ptr->LRU_head_ptr == NULL )
- ||
- ( cache_ptr->LRU_head_ptr->size != cache_ptr->LRU_list_size )
- )
+ &&
+ ( ( cache_ptr->LRU_head_ptr != cache_ptr->LRU_tail_ptr )
+ ||
+ ( cache_ptr->LRU_head_ptr == NULL )
+ ||
+ ( cache_ptr->LRU_head_ptr->size != cache_ptr->LRU_list_size )
+ )
) {
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 3 failed")
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 3 failed")
}
if ( ( cache_ptr->LRU_list_len >= 1 )
- &&
- ( ( cache_ptr->LRU_head_ptr == NULL )
- ||
- ( cache_ptr->LRU_head_ptr->prev != NULL )
- ||
- ( cache_ptr->LRU_tail_ptr == NULL )
- ||
- ( cache_ptr->LRU_tail_ptr->next != NULL )
- )
+ &&
+ ( ( cache_ptr->LRU_head_ptr == NULL )
+ ||
+ ( cache_ptr->LRU_head_ptr->prev != NULL )
+ ||
+ ( cache_ptr->LRU_tail_ptr == NULL )
+ ||
+ ( cache_ptr->LRU_tail_ptr->next != NULL )
+ )
) {
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 4 failed")
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 4 failed")
}
entry_ptr = cache_ptr->LRU_head_ptr;
while ( entry_ptr != NULL )
{
- if ( ( entry_ptr != cache_ptr->LRU_head_ptr ) &&
- ( ( entry_ptr->prev == NULL ) ||
- ( entry_ptr->prev->next != entry_ptr ) ) ) {
+ if ( ( entry_ptr != cache_ptr->LRU_head_ptr ) &&
+ ( ( entry_ptr->prev == NULL ) ||
+ ( entry_ptr->prev->next != entry_ptr ) ) ) {
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 5 failed")
- }
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 5 failed")
+ }
- if ( ( entry_ptr != cache_ptr->LRU_tail_ptr ) &&
- ( ( entry_ptr->next == NULL ) ||
- ( entry_ptr->next->prev != entry_ptr ) ) ) {
+ if ( ( entry_ptr != cache_ptr->LRU_tail_ptr ) &&
+ ( ( entry_ptr->next == NULL ) ||
+ ( entry_ptr->next->prev != entry_ptr ) ) ) {
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 6 failed")
- }
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 6 failed")
+ }
- if ( ( entry_ptr->is_pinned ) ||
- ( entry_ptr->pinned_from_client ) ||
- ( entry_ptr->pinned_from_cache ) ) {
+ if ( ( entry_ptr->is_pinned ) ||
+ ( entry_ptr->pinned_from_client ) ||
+ ( entry_ptr->pinned_from_cache ) ) {
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 7 failed")
- }
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 7 failed")
+ }
- len++;
- size += entry_ptr->size;
- entry_ptr = entry_ptr->next;
+ len++;
+ size += entry_ptr->size;
+ entry_ptr = entry_ptr->next;
}
if ( ( cache_ptr->LRU_list_len != len ) ||
- ( cache_ptr->LRU_list_size != size ) ) {
+ ( cache_ptr->LRU_list_size != size ) ) {
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 8 failed")
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 8 failed")
}
done:
if ( ret_value != SUCCEED ) {
- HDassert(0);
+ HDassert(0);
}
FUNC_LEAVE_NOAPI(ret_value)
@@ -9619,94 +10966,94 @@ H5C_validate_pinned_entry_list(H5C_t * cache_ptr)
HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC );
if ( ( ( cache_ptr->pel_head_ptr == NULL )
- ||
- ( cache_ptr->pel_tail_ptr == NULL )
- )
- &&
- ( cache_ptr->pel_head_ptr != cache_ptr->pel_tail_ptr )
+ ||
+ ( cache_ptr->pel_tail_ptr == NULL )
+ )
+ &&
+ ( cache_ptr->pel_head_ptr != cache_ptr->pel_tail_ptr )
) {
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 1 failed")
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 1 failed")
}
if ( ( cache_ptr->pel_len < 0 ) || ( cache_ptr->pel_size < 0 ) ) {
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 2 failed")
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 2 failed")
}
if ( ( cache_ptr->pel_len == 1 )
- &&
- ( ( cache_ptr->pel_head_ptr != cache_ptr->pel_tail_ptr )
- ||
- ( cache_ptr->pel_head_ptr == NULL )
- ||
- ( cache_ptr->pel_head_ptr->size != cache_ptr->pel_size )
- )
+ &&
+ ( ( cache_ptr->pel_head_ptr != cache_ptr->pel_tail_ptr )
+ ||
+ ( cache_ptr->pel_head_ptr == NULL )
+ ||
+ ( cache_ptr->pel_head_ptr->size != cache_ptr->pel_size )
+ )
) {
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 3 failed")
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 3 failed")
}
if ( ( cache_ptr->pel_len >= 1 )
- &&
- ( ( cache_ptr->pel_head_ptr == NULL )
- ||
- ( cache_ptr->pel_head_ptr->prev != NULL )
- ||
- ( cache_ptr->pel_tail_ptr == NULL )
- ||
- ( cache_ptr->pel_tail_ptr->next != NULL )
- )
+ &&
+ ( ( cache_ptr->pel_head_ptr == NULL )
+ ||
+ ( cache_ptr->pel_head_ptr->prev != NULL )
+ ||
+ ( cache_ptr->pel_tail_ptr == NULL )
+ ||
+ ( cache_ptr->pel_tail_ptr->next != NULL )
+ )
) {
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 4 failed")
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 4 failed")
}
entry_ptr = cache_ptr->pel_head_ptr;
while ( entry_ptr != NULL )
{
- if ( ( entry_ptr != cache_ptr->pel_head_ptr ) &&
- ( ( entry_ptr->prev == NULL ) ||
- ( entry_ptr->prev->next != entry_ptr ) ) ) {
+ if ( ( entry_ptr != cache_ptr->pel_head_ptr ) &&
+ ( ( entry_ptr->prev == NULL ) ||
+ ( entry_ptr->prev->next != entry_ptr ) ) ) {
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 5 failed")
- }
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 5 failed")
+ }
- if ( ( entry_ptr != cache_ptr->pel_tail_ptr ) &&
- ( ( entry_ptr->next == NULL ) ||
- ( entry_ptr->next->prev != entry_ptr ) ) ) {
+ if ( ( entry_ptr != cache_ptr->pel_tail_ptr ) &&
+ ( ( entry_ptr->next == NULL ) ||
+ ( entry_ptr->next->prev != entry_ptr ) ) ) {
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 6 failed")
- }
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 6 failed")
+ }
- if ( ! entry_ptr->is_pinned ) {
+ if ( ! entry_ptr->is_pinned ) {
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 7 failed")
- }
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 7 failed")
+ }
- if ( ! ( ( entry_ptr->pinned_from_client ) ||
- ( entry_ptr->pinned_from_cache ) ) ) {
+ if ( ! ( ( entry_ptr->pinned_from_client ) ||
+ ( entry_ptr->pinned_from_cache ) ) ) {
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 8 failed")
- }
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 8 failed")
+ }
- len++;
- size += entry_ptr->size;
- entry_ptr = entry_ptr->next;
+ len++;
+ size += entry_ptr->size;
+ entry_ptr = entry_ptr->next;
}
if ( ( cache_ptr->pel_len != len ) ||
- ( cache_ptr->pel_size != size ) ) {
+ ( cache_ptr->pel_size != size ) ) {
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 9 failed")
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 9 failed")
}
done:
if ( ret_value != SUCCEED ) {
- HDassert(0);
+ HDassert(0);
}
FUNC_LEAVE_NOAPI(ret_value)
@@ -9753,94 +11100,94 @@ H5C_validate_protected_entry_list(H5C_t * cache_ptr)
HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC );
if ( ( ( cache_ptr->pl_head_ptr == NULL )
- ||
- ( cache_ptr->pl_tail_ptr == NULL )
- )
- &&
- ( cache_ptr->pl_head_ptr != cache_ptr->pl_tail_ptr )
+ ||
+ ( cache_ptr->pl_tail_ptr == NULL )
+ )
+ &&
+ ( cache_ptr->pl_head_ptr != cache_ptr->pl_tail_ptr )
) {
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 1 failed")
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 1 failed")
}
if ( ( cache_ptr->pl_len < 0 ) || ( cache_ptr->pl_size < 0 ) ) {
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 2 failed")
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 2 failed")
}
if ( ( cache_ptr->pl_len == 1 )
- &&
- ( ( cache_ptr->pl_head_ptr != cache_ptr->pl_tail_ptr )
- ||
- ( cache_ptr->pl_head_ptr == NULL )
- ||
- ( cache_ptr->pl_head_ptr->size != cache_ptr->pl_size )
- )
+ &&
+ ( ( cache_ptr->pl_head_ptr != cache_ptr->pl_tail_ptr )
+ ||
+ ( cache_ptr->pl_head_ptr == NULL )
+ ||
+ ( cache_ptr->pl_head_ptr->size != cache_ptr->pl_size )
+ )
) {
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 3 failed")
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 3 failed")
}
if ( ( cache_ptr->pl_len >= 1 )
- &&
- ( ( cache_ptr->pl_head_ptr == NULL )
- ||
- ( cache_ptr->pl_head_ptr->prev != NULL )
- ||
- ( cache_ptr->pl_tail_ptr == NULL )
- ||
- ( cache_ptr->pl_tail_ptr->next != NULL )
- )
+ &&
+ ( ( cache_ptr->pl_head_ptr == NULL )
+ ||
+ ( cache_ptr->pl_head_ptr->prev != NULL )
+ ||
+ ( cache_ptr->pl_tail_ptr == NULL )
+ ||
+ ( cache_ptr->pl_tail_ptr->next != NULL )
+ )
) {
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 4 failed")
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 4 failed")
}
entry_ptr = cache_ptr->pl_head_ptr;
while ( entry_ptr != NULL )
{
- if ( ( entry_ptr != cache_ptr->pl_head_ptr ) &&
- ( ( entry_ptr->prev == NULL ) ||
- ( entry_ptr->prev->next != entry_ptr ) ) ) {
+ if ( ( entry_ptr != cache_ptr->pl_head_ptr ) &&
+ ( ( entry_ptr->prev == NULL ) ||
+ ( entry_ptr->prev->next != entry_ptr ) ) ) {
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 5 failed")
- }
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 5 failed")
+ }
- if ( ( entry_ptr != cache_ptr->pl_tail_ptr ) &&
- ( ( entry_ptr->next == NULL ) ||
- ( entry_ptr->next->prev != entry_ptr ) ) ) {
+ if ( ( entry_ptr != cache_ptr->pl_tail_ptr ) &&
+ ( ( entry_ptr->next == NULL ) ||
+ ( entry_ptr->next->prev != entry_ptr ) ) ) {
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 6 failed")
- }
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 6 failed")
+ }
- if ( ! entry_ptr->is_protected ) {
+ if ( ! entry_ptr->is_protected ) {
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 7 failed")
- }
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 7 failed")
+ }
- if ( ( entry_ptr->is_read_only ) &&
- ( entry_ptr->ro_ref_count <= 0 ) ) {
+ if ( ( entry_ptr->is_read_only ) &&
+ ( entry_ptr->ro_ref_count <= 0 ) ) {
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 8 failed")
- }
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 8 failed")
+ }
- len++;
- size += entry_ptr->size;
- entry_ptr = entry_ptr->next;
+ len++;
+ size += entry_ptr->size;
+ entry_ptr = entry_ptr->next;
}
if ( ( cache_ptr->pl_len != len ) ||
- ( cache_ptr->pl_size != size ) ) {
+ ( cache_ptr->pl_size != size ) ) {
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 9 failed")
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 9 failed")
}
done:
if ( ret_value != SUCCEED ) {
- HDassert(0);
+ HDassert(0);
}
FUNC_LEAVE_NOAPI(ret_value)
@@ -9852,6 +11199,66 @@ done:
/*-------------------------------------------------------------------------
*
+ * Function: H5C_entry_in_skip_list
+ *
+ * Purpose: Debugging function that scans skip list to see if it
+ * is in present. We need this, as it is possible for
+ * an entry to be in the skip list twice.
+ *
+ * Return: FALSE if the entry is not in the skip list, and TRUE
+ * if it is.
+ *
+ * Programmer: John Mainzer, 11/1/14
+ *
+ * Changes:
+ *
+ * None.
+ *
+ *-------------------------------------------------------------------------
+ */
+#if H5C_DO_SLIST_SANITY_CHECKS
+
+static hbool_t
+H5C_entry_in_skip_list(H5C_t * cache_ptr, H5C_cache_entry_t *target_ptr)
+{
+ hbool_t in_slist = FALSE;
+ H5SL_node_t * node_ptr = NULL;
+ H5C_cache_entry_t * entry_ptr = NULL;
+
+ HDassert( cache_ptr );
+ HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC );
+ HDassert( cache_ptr->slist_ptr );
+
+ node_ptr = H5SL_first(cache_ptr->slist_ptr);
+
+ while ( ( node_ptr != NULL ) && ( ! in_slist ) )
+ {
+ entry_ptr = (H5C_cache_entry_t *)H5SL_item(node_ptr);
+
+ HDassert( entry_ptr );
+ HDassert( entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC );
+ HDassert( entry_ptr->is_dirty );
+ HDassert( entry_ptr->in_slist );
+
+ if ( entry_ptr == target_ptr ) {
+
+ in_slist = TRUE;
+
+ } else {
+
+ node_ptr = H5SL_next(node_ptr);
+ }
+ }
+
+ return(in_slist);
+
+} /* H5C_entry_in_skip_list() */
+
+#endif /* H5C_DO_SLIST_SANITY_CHECKS */
+
+
+/*-------------------------------------------------------------------------
+ *
* Function: H5C_get_entry_ptr_from_addr()
*
* Purpose: Debugging function that attempts to look up an entry in the
@@ -9893,7 +11300,7 @@ done:
#ifndef NDEBUG
herr_t
H5C_get_entry_ptr_from_addr(const H5F_t *f,
- haddr_t addr,
+ haddr_t addr,
void ** entry_ptr_ptr)
{
H5C_t * cache_ptr;
@@ -9917,21 +11324,21 @@ H5C_get_entry_ptr_from_addr(const H5F_t *f,
*/
if ( ( cache_ptr == NULL ) || ( cache_ptr->magic != H5C__H5C_T_MAGIC ) ) {
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Bad cache_ptr on entry.")
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Bad cache_ptr on entry.")
}
H5C__SEARCH_INDEX(cache_ptr, addr, entry_ptr, FAIL)
if ( entry_ptr == NULL ) {
- /* the entry doesn't exist in the cache -- report this
- * and quit.
- */
- *entry_ptr_ptr = NULL;
+ /* the entry doesn't exist in the cache -- report this
+ * and quit.
+ */
+ *entry_ptr_ptr = NULL;
} else {
- *entry_ptr_ptr = entry_ptr;
+ *entry_ptr_ptr = entry_ptr;
/* increment call counter */
(cache_ptr->get_entry_ptr_from_addr_counter)++;
@@ -9978,10 +11385,10 @@ done:
#ifndef NDEBUG
herr_t
H5C_verify_entry_type(const H5F_t *f,
- haddr_t addr,
- const H5C_class_t * expected_type,
- hbool_t * in_cache_ptr,
- hbool_t * type_ok_ptr)
+ haddr_t addr,
+ const H5C_class_t * expected_type,
+ hbool_t * in_cache_ptr,
+ hbool_t * type_ok_ptr)
{
H5C_t * cache_ptr;
H5C_cache_entry_t * entry_ptr = NULL;
@@ -10005,21 +11412,21 @@ H5C_verify_entry_type(const H5F_t *f,
*/
if ( ( cache_ptr == NULL ) || ( cache_ptr->magic != H5C__H5C_T_MAGIC ) ) {
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Bad cache_ptr on entry.")
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Bad cache_ptr on entry.")
}
H5C__SEARCH_INDEX(cache_ptr, addr, entry_ptr, FAIL)
if ( entry_ptr == NULL ) {
- /* the entry doesn't exist in the cache -- report this
- * and quit.
- */
- *in_cache_ptr = FALSE;
+ /* the entry doesn't exist in the cache -- report this
+ * and quit.
+ */
+ *in_cache_ptr = FALSE;
} else {
- *in_cache_ptr = TRUE;
+ *in_cache_ptr = TRUE;
*type_ok_ptr = (expected_type == entry_ptr->type);
}
@@ -10104,11 +11511,11 @@ H5C_tag_entry(H5C_t * cache_ptr, H5C_cache_entry_t * entry_ptr, hid_t dxpl_id)
/* Get the dataset transfer property list */
if(NULL == (dxpl = (H5P_genplist_t *)H5I_object_verify(dxpl_id, H5I_GENPROP_LST)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
/* Get the tag from the DXPL */
if((H5P_get(dxpl, "H5C_tag", &tag)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to query property value")
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to query property value")
/* Apply the tag to the entry */
entry_ptr->tag = tag.value;
@@ -10120,7 +11527,6 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5C_tag_entry */
-
/*-------------------------------------------------------------------------
*
* Function: H5C_evict_tagged_entries
@@ -10135,7 +11541,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5C_evict_tagged_entries(H5F_t * f, hid_t primary_dxpl_id, hid_t secondary_dxpl_id, haddr_t tag)
+H5C_evict_tagged_entries(H5F_t * f, hid_t dxpl_id, haddr_t tag)
{
/* Variable Declarations */
herr_t status;
@@ -10144,9 +11550,7 @@ H5C_evict_tagged_entries(H5F_t * f, hid_t primary_dxpl_id, hid_t secondary_dxpl_
int i;
hbool_t evicted_entries_last_pass;
hbool_t pinned_entries_need_evicted;
- hbool_t first_flush = TRUE;
-
- H5C_t *cache_ptr = NULL;
+ H5C_t *cache_ptr = NULL;
herr_t ret_value = SUCCEED;
/* Function Enter Macro */
@@ -10165,66 +11569,64 @@ H5C_evict_tagged_entries(H5F_t * f, hid_t primary_dxpl_id, hid_t secondary_dxpl_
/* Start evicting entries */
do {
- /* Reset pinned/evicted trackers */
- pinned_entries_need_evicted = FALSE;
- evicted_entries_last_pass = FALSE;
+ /* Reset pinned/evicted trackers */
+ pinned_entries_need_evicted = FALSE;
+ evicted_entries_last_pass = FALSE;
- /* Iterate through entries in the index. */
- for (i = 0; i < H5C__HASH_TABLE_LEN; i++) {
+ /* Iterate through entries in the index. */
+ for (i = 0; i < H5C__HASH_TABLE_LEN; i++) {
- next_entry_ptr = cache_ptr->index[i];
+ next_entry_ptr = cache_ptr->index[i];
- while ( next_entry_ptr != NULL ) {
+ while ( next_entry_ptr != NULL ) {
- entry_ptr = next_entry_ptr;
- next_entry_ptr = entry_ptr->ht_next;
+ entry_ptr = next_entry_ptr;
+ next_entry_ptr = entry_ptr->ht_next;
if(( entry_ptr->tag == tag ) ||
( entry_ptr->globality == H5C_GLOBALITY_MAJOR)) {
- /* This entry will need to be evicted */
-
- if ( entry_ptr->is_protected ) {
- HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Cannot evict protected entry");
- } else if (entry_ptr->is_dirty) {
- HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Cannot evict dirty entry");
- } else if (entry_ptr->is_pinned) {
-
- /* Can't evict at this time, but let's note that we hit a pinned
- entry and we'll loop back around again (as evicting other
- entries will hopefully unpin this entry) */
+ /* This entry will need to be evicted */
+
+ if ( entry_ptr->is_protected ) {
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Cannot evict protected entry");
+ } else if (entry_ptr->is_dirty) {
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Cannot evict dirty entry");
+ } else if (entry_ptr->is_pinned) {
+
+ /* Can't evict at this time, but let's note that we hit a pinned
+ entry and we'll loop back around again (as evicting other
+ entries will hopefully unpin this entry) */
- pinned_entries_need_evicted = TRUE;
+ pinned_entries_need_evicted = TRUE;
- } else {
+ } else {
- /* Evict the Entry */
+ /* Evict the Entry */
- status = H5C_flush_single_entry(f,
- primary_dxpl_id,
- secondary_dxpl_id,
- entry_ptr->type,
- entry_ptr->addr,
- H5C__FLUSH_INVALIDATE_FLAG | H5C__FLUSH_CLEAR_ONLY_FLAG,
- &first_flush,
- TRUE);
+ status = H5C_flush_single_entry(f,
+ dxpl_id,
+ entry_ptr->addr,
+ H5C__FLUSH_INVALIDATE_FLAG | H5C__FLUSH_CLEAR_ONLY_FLAG,
+ TRUE,
+ NULL);
- if ( status < 0 ) {
+ if ( status < 0 ) {
- HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \
- "Entry eviction failed.")
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \
+ "Entry eviction failed.")
- }
+ }
- evicted_entries_last_pass = TRUE;
+ evicted_entries_last_pass = TRUE;
- } /* end if */
+ } /* end if */
- } /* end if */
+ } /* end if */
- } /* end while */
+ } /* end while */
- } /* end for */
+ } /* end for */
/* Keep doing this until we have stopped evicted entries */
} while ((evicted_entries_last_pass == TRUE));
@@ -10232,7 +11634,7 @@ H5C_evict_tagged_entries(H5F_t * f, hid_t primary_dxpl_id, hid_t secondary_dxpl_
/* If we stop evicting entries and pinned entries still need evicted,
then we have a problem. */
if (pinned_entries_need_evicted) {
- HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Pinned entries still need evicted?!");
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Pinned entries still need evicted?!");
} /* end if */
done:
@@ -10275,26 +11677,26 @@ H5C_mark_tagged_entries(H5C_t * cache_ptr, haddr_t tag, hbool_t mark_clean)
* when flushing based on tag value */
for(u = 0; u < H5C__HASH_TABLE_LEN; u++) {
- entry_ptr = cache_ptr->index[u];
+ entry_ptr = cache_ptr->index[u];
- while ( entry_ptr != NULL ) {
+ while ( entry_ptr != NULL ) {
- if (( entry_ptr->tag == tag ) ||
- ( entry_ptr->globality == H5C_GLOBALITY_MAJOR)) {
+ if (( entry_ptr->tag == tag ) ||
+ ( entry_ptr->globality == H5C_GLOBALITY_MAJOR)) {
- /* We only want to set the flush marker on entries that
- * actually need flushed (i.e., dirty ones), unless
- * we've specified otherwise with the mark_clean flag */
- if (entry_ptr->is_dirty || mark_clean) {
+ /* We only want to set the flush marker on entries that
+ * actually need flushed (i.e., dirty ones), unless
+ * we've specified otherwise with the mark_clean flag */
+ if (entry_ptr->is_dirty || mark_clean) {
- entry_ptr->flush_marker = TRUE;
+ entry_ptr->flush_marker = TRUE;
- } /* end if */
+ } /* end if */
- } /* end if */
+ } /* end if */
- entry_ptr = entry_ptr->ht_next;
- } /* end while */
+ entry_ptr = entry_ptr->ht_next;
+ } /* end while */
} /* for */
FUNC_LEAVE_NOAPI(SUCCEED)
@@ -10315,7 +11717,7 @@ H5C_mark_tagged_entries(H5C_t * cache_ptr, haddr_t tag, hbool_t mark_clean)
*-------------------------------------------------------------------------
*/
static herr_t
-H5C_flush_marked_entries(H5F_t * f, hid_t primary_dxpl_id, hid_t secondary_dxpl_id, H5C_t * cache_ptr)
+H5C_flush_marked_entries(H5F_t * f, hid_t dxpl_id, H5C_t * cache_ptr)
{
herr_t ret_value = SUCCEED;
@@ -10326,9 +11728,8 @@ H5C_flush_marked_entries(H5F_t * f, hid_t primary_dxpl_id, hid_t secondary_dxpl_
HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
/* Flush all marked entries */
- if(H5C_flush_cache(f, primary_dxpl_id, secondary_dxpl_id,
- H5C__FLUSH_MARKED_ENTRIES_FLAG | H5C__FLUSH_IGNORE_PROTECTED_FLAG) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't flush cache")
+ if(H5C_flush_cache(f, dxpl_id, H5C__FLUSH_MARKED_ENTRIES_FLAG | H5C__FLUSH_IGNORE_PROTECTED_FLAG) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't flush cache")
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -10349,7 +11750,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5C_flush_tagged_entries(H5F_t * f, hid_t primary_dxpl_id, hid_t secondary_dxpl_id, haddr_t tag)
+H5C_flush_tagged_entries(H5F_t * f, hid_t dxpl_id, haddr_t tag)
{
/* Variable Declarations */
H5C_t *cache_ptr = NULL;
@@ -10367,11 +11768,11 @@ H5C_flush_tagged_entries(H5F_t * f, hid_t primary_dxpl_id, hid_t secondary_dxpl_
/* Mark all entries with specified tag */
if((result = H5C_mark_tagged_entries(cache_ptr, tag, FALSE)) < 0 )
- HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't mark tagged entries")
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't mark tagged entries")
/* Flush all marked entries */
- if(H5C_flush_marked_entries(f, primary_dxpl_id, secondary_dxpl_id, cache_ptr) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't flush marked entries")
+ if(H5C_flush_marked_entries(f, dxpl_id, cache_ptr) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't flush marked entries")
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -10403,15 +11804,14 @@ H5C_retag_entries(H5C_t * cache_ptr, haddr_t src_tag, haddr_t dest_tag)
/* Iterate through entries, retagging those with the src_tag tag */
for(u = 0; u < H5C__HASH_TABLE_LEN; u++) {
- entry_ptr = cache_ptr->index[u];
- while(entry_ptr != NULL) {
- if(cache_ptr->index[u] != NULL) {
- if((cache_ptr->index[u])->tag == src_tag) {
- (cache_ptr->index[u])->tag = dest_tag;
- }
- } /* end if */
- entry_ptr = entry_ptr->ht_next;
- } /* end while */
+ entry_ptr = cache_ptr->index[u];
+ while(entry_ptr != NULL) {
+ if(cache_ptr->index[u] != NULL)
+ if((cache_ptr->index[u])->tag == src_tag) {
+ (cache_ptr->index[u])->tag = dest_tag;
+ }
+ entry_ptr = entry_ptr->ht_next;
+ } /* end while */
} /* end for */
FUNC_LEAVE_NOAPI_VOID
@@ -10500,7 +11900,7 @@ H5C_cork(H5C_t * cache_ptr, haddr_t obj_addr, unsigned action, hbool_t *corked)
default: /* should be unreachable */
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Unknown cork action")
- break;
+ break;
} /* end switch */
if(action != H5C__GET_CORKED)
@@ -10545,15 +11945,15 @@ H5C_mark_tagged_entries_cork(H5C_t *cache_ptr, haddr_t obj_addr, hbool_t val)
/* and set the entry's "corked" field to "val" */
for(u = 0; u < H5C__HASH_TABLE_LEN; u++) {
- entry_ptr = cache_ptr->index[u];
+ entry_ptr = cache_ptr->index[u];
- while(entry_ptr != NULL) {
+ while(entry_ptr != NULL) {
- if(entry_ptr->tag == obj_addr)
+ if(entry_ptr->tag == obj_addr)
entry_ptr->is_corked = val;
- entry_ptr = entry_ptr->ht_next;
- } /* end while */
+ entry_ptr = entry_ptr->ht_next;
+ } /* end while */
} /* end for */
FUNC_LEAVE_NOAPI(SUCCEED)
@@ -10586,22 +11986,22 @@ H5C__mark_flush_dep_dirty(H5C_cache_entry_t * entry)
/* Sanity checks */
HDassert(entry);
HDassert((entry->is_dirty && entry->flush_dep_ndirty_children == 0)
- || (!entry->is_dirty && entry->flush_dep_ndirty_children == 1));
+ || (!entry->is_dirty && entry->flush_dep_ndirty_children == 1));
/* Iterate over the parent entries, if any */
for(i=0; i<entry->flush_dep_nparents; i++) {
- /* Sanity check */
- HDassert(entry->flush_dep_parent[i]->flush_dep_ndirty_children
- < entry->flush_dep_parent[i]->flush_dep_nchildren);
-
- /* Adjust the parent's number of dirty children */
- entry->flush_dep_parent[i]->flush_dep_ndirty_children++;
-
- /* Propagate the flush dep dirty flag up the chain if necessary */
- if(!entry->flush_dep_parent[i]->is_dirty
- && entry->flush_dep_parent[i]->flush_dep_ndirty_children == 1)
- if(H5C__mark_flush_dep_dirty(entry->flush_dep_parent[i]) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTMARKDIRTY, FAIL, "can't propagate flush dep dirty flag")
+ /* Sanity check */
+ HDassert(entry->flush_dep_parent[i]->flush_dep_ndirty_children
+ < entry->flush_dep_parent[i]->flush_dep_nchildren);
+
+ /* Adjust the parent's number of dirty children */
+ entry->flush_dep_parent[i]->flush_dep_ndirty_children++;
+
+ /* Propagate the flush dep dirty flag up the chain if necessary */
+ if(!entry->flush_dep_parent[i]->is_dirty
+ && entry->flush_dep_parent[i]->flush_dep_ndirty_children == 1)
+ if(H5C__mark_flush_dep_dirty(entry->flush_dep_parent[i]) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTMARKDIRTY, FAIL, "can't propagate flush dep dirty flag")
} /* end for */
done:
@@ -10638,17 +12038,17 @@ H5C__mark_flush_dep_clean(H5C_cache_entry_t * entry)
/* Iterate over the parent entries, if any */
for(i=0; i<entry->flush_dep_nparents; i++) {
- /* Sanity check */
- HDassert(entry->flush_dep_parent[i]->flush_dep_ndirty_children > 0);
+ /* Sanity check */
+ HDassert(entry->flush_dep_parent[i]->flush_dep_ndirty_children > 0);
- /* Adjust the parent's number of dirty children */
- entry->flush_dep_parent[i]->flush_dep_ndirty_children--;
+ /* Adjust the parent's number of dirty children */
+ entry->flush_dep_parent[i]->flush_dep_ndirty_children--;
- /* Propagate the flush dep clean flag up the chain if necessary */
- if(!entry->flush_dep_parent[i]->is_dirty
- && entry->flush_dep_parent[i]->flush_dep_ndirty_children == 0)
- if(H5C__mark_flush_dep_clean(entry->flush_dep_parent[i]) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTMARKDIRTY, FAIL, "can't propagate flush dep clean flag")
+ /* Propagate the flush dep clean flag up the chain if necessary */
+ if(!entry->flush_dep_parent[i]->is_dirty
+ && entry->flush_dep_parent[i]->flush_dep_ndirty_children == 0)
+ if(H5C__mark_flush_dep_clean(entry->flush_dep_parent[i]) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTMARKDIRTY, FAIL, "can't propagate flush dep clean flag")
} /* end for */
done:
@@ -10689,9 +12089,8 @@ H5C__assert_flush_dep_nocycle(H5C_cache_entry_t * entry,
/* Iterate over entry's parents (if any) */
for(i=0; i<entry->flush_dep_nparents; i++)
- H5C__assert_flush_dep_nocycle(entry->flush_dep_parent[i], base_entry);
+ H5C__assert_flush_dep_nocycle(entry->flush_dep_parent[i], base_entry);
FUNC_LEAVE_NOAPI_VOID
} /* H5C__assert_flush_dep_nocycle() */
#endif /* NDEBUG */
-
diff --git a/src/H5Cpkg.h b/src/H5Cpkg.h
index 61c0539..c8a5a7c 100644
--- a/src/H5Cpkg.h
+++ b/src/H5Cpkg.h
@@ -564,6 +564,15 @@ if ( ( (entry_ptr) == NULL ) || \
#define H5C__UPDATE_STATS_FOR_UNPIN(cache_ptr, entry_ptr) \
((cache_ptr)->unpins)[(entry_ptr)->type->id]++;
+#define H5C__UPDATE_STATS_FOR_SLIST_SCAN_RESTART(cache_ptr) \
+ ((cache_ptr)->slist_scan_restarts)++;
+
+#define H5C__UPDATE_STATS_FOR_LRU_SCAN_RESTART(cache_ptr) \
+ ((cache_ptr)->LRU_scan_restarts)++;
+
+#define H5C__UPDATE_STATS_FOR_HASH_BUCKET_SCAN_RESTART(cache_ptr) \
+ ((cache_ptr)->hash_bucket_scan_restarts)++;
+
#if H5C_COLLECT_CACHE_ENTRY_STATS
#define H5C__RESET_CACHE_ENTRY_STATS(entry_ptr) \
@@ -590,9 +599,12 @@ if ( ( (entry_ptr) == NULL ) || \
((entry_ptr)->flushes)++; \
}
-#define H5C__UPDATE_STATS_FOR_EVICTION(cache_ptr, entry_ptr) \
-{ \
- (((cache_ptr)->evictions)[(entry_ptr)->type->id])++; \
+#define H5C__UPDATE_STATS_FOR_EVICTION(cache_ptr, entry_ptr, take_ownership) \
+{ \
+ if ( take_ownership ) \
+ (((cache_ptr)->take_ownerships)[(entry_ptr)->type->id])++; \
+ else \
+ (((cache_ptr)->evictions)[(entry_ptr)->type->id])++; \
if ( (entry_ptr)->accesses > \
((cache_ptr)->max_accesses)[(entry_ptr)->type->id] ) \
((cache_ptr)->max_accesses)[(entry_ptr)->type->id] = \
@@ -700,8 +712,13 @@ if ( ( (entry_ptr) == NULL ) || \
(((cache_ptr)->pinned_flushes)[(entry_ptr)->type->id])++; \
}
-#define H5C__UPDATE_STATS_FOR_EVICTION(cache_ptr, entry_ptr) \
- (((cache_ptr)->evictions)[(entry_ptr)->type->id])++;
+#define H5C__UPDATE_STATS_FOR_EVICTION(cache_ptr, entry_ptr, take_ownership) \
+{ \
+ if ( take_ownership ) \
+ (((cache_ptr)->take_ownerships)[(entry_ptr)->type->id])++; \
+ else \
+ (((cache_ptr)->evictions)[(entry_ptr)->type->id])++; \
+}
#define H5C__UPDATE_STATS_FOR_INSERTION(cache_ptr, entry_ptr) \
{ \
@@ -771,10 +788,13 @@ if ( ( (entry_ptr) == NULL ) || \
#define H5C__UPDATE_STATS_FOR_INSERTION(cache_ptr, entry_ptr)
#define H5C__UPDATE_STATS_FOR_CLEAR(cache_ptr, entry_ptr)
#define H5C__UPDATE_STATS_FOR_FLUSH(cache_ptr, entry_ptr)
-#define H5C__UPDATE_STATS_FOR_EVICTION(cache_ptr, entry_ptr)
+#define H5C__UPDATE_STATS_FOR_EVICTION(cache_ptr, entry_ptr, take_ownership)
#define H5C__UPDATE_STATS_FOR_PROTECT(cache_ptr, entry_ptr, hit)
#define H5C__UPDATE_STATS_FOR_PIN(cache_ptr, entry_ptr)
#define H5C__UPDATE_STATS_FOR_UNPIN(cache_ptr, entry_ptr)
+#define H5C__UPDATE_STATS_FOR_SLIST_SCAN_RESTART(cache_ptr)
+#define H5C__UPDATE_STATS_FOR_LRU_SCAN_RESTART(cache_ptr)
+#define H5C__UPDATE_STATS_FOR_HASH_BUCKET_SCAN_RESTART(cache_ptr)
#endif /* H5C_COLLECT_CACHE_STATS */
@@ -819,11 +839,25 @@ if ( ( (cache_ptr) == NULL ) || \
( H5C__HASH_FCN((entry_ptr)->addr) >= H5C__HASH_TABLE_LEN ) || \
( (cache_ptr)->index_size != \
((cache_ptr)->clean_index_size + \
- (cache_ptr)->dirty_index_size) ) ) { \
+ (cache_ptr)->dirty_index_size) ) || \
+ ( (cache_ptr)->index_size < ((cache_ptr)->clean_index_size) ) || \
+ ( (cache_ptr)->index_size < ((cache_ptr)->dirty_index_size) ) ) { \
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, fail_val, \
"Pre HT insert SC failed") \
}
+#define H5C__POST_HT_INSERT_SC(cache_ptr, fail_val) \
+if ( ( (cache_ptr) == NULL ) || \
+ ( (cache_ptr)->magic != H5C__H5C_T_MAGIC ) || \
+ ( (cache_ptr)->index_size != \
+ ((cache_ptr)->clean_index_size + \
+ (cache_ptr)->dirty_index_size) ) || \
+ ( (cache_ptr)->index_size < ((cache_ptr)->clean_index_size) ) || \
+ ( (cache_ptr)->index_size < ((cache_ptr)->dirty_index_size) ) ) { \
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, fail_val, \
+ "Post HT insert SC failed") \
+}
+
#define H5C__PRE_HT_REMOVE_SC(cache_ptr, entry_ptr) \
if ( ( (cache_ptr) == NULL ) || \
( (cache_ptr)->magic != H5C__H5C_T_MAGIC ) || \
@@ -844,10 +878,28 @@ if ( ( (cache_ptr) == NULL ) || \
( (entry_ptr)->ht_prev != NULL ) ) || \
( (cache_ptr)->index_size != \
((cache_ptr)->clean_index_size + \
- (cache_ptr)->dirty_index_size) ) ) { \
+ (cache_ptr)->dirty_index_size) ) || \
+ ( (cache_ptr)->index_size < ((cache_ptr)->clean_index_size) ) || \
+ ( (cache_ptr)->index_size < ((cache_ptr)->dirty_index_size) ) ) { \
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Pre HT remove SC failed") \
}
+#define H5C__POST_HT_REMOVE_SC(cache_ptr, entry_ptr) \
+if ( ( (cache_ptr) == NULL ) || \
+ ( (cache_ptr)->magic != H5C__H5C_T_MAGIC ) || \
+ ( (entry_ptr) == NULL ) || \
+ ( ! H5F_addr_defined((entry_ptr)->addr) ) || \
+ ( (entry_ptr)->size <= 0 ) || \
+ ( (entry_ptr)->ht_prev != NULL ) || \
+ ( (entry_ptr)->ht_prev != NULL ) || \
+ ( (cache_ptr)->index_size != \
+ ((cache_ptr)->clean_index_size + \
+ (cache_ptr)->dirty_index_size) ) || \
+ ( (cache_ptr)->index_size < ((cache_ptr)->clean_index_size) ) || \
+ ( (cache_ptr)->index_size < ((cache_ptr)->dirty_index_size) ) ) { \
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Post HT remove SC failed") \
+}
+
/* (Keep in sync w/H5C_TEST__PRE_HT_SEARCH_SC macro in test/cache_common.h -QAK) */
#define H5C__PRE_HT_SEARCH_SC(cache_ptr, Addr, fail_val) \
if ( ( (cache_ptr) == NULL ) || \
@@ -906,6 +958,8 @@ if ( ( (cache_ptr) == NULL ) || \
( (cache_ptr)->index_size != \
((cache_ptr)->clean_index_size + \
(cache_ptr)->dirty_index_size) ) || \
+ ( (cache_ptr)->index_size < ((cache_ptr)->clean_index_size) ) || \
+ ( (cache_ptr)->index_size < ((cache_ptr)->dirty_index_size) ) || \
( ( !( was_clean ) || \
( (cache_ptr)->clean_index_size < (old_size) ) ) && \
( ( (was_clean) ) || \
@@ -924,6 +978,8 @@ if ( ( (cache_ptr) == NULL ) || \
( (cache_ptr)->index_size != \
((cache_ptr)->clean_index_size + \
(cache_ptr)->dirty_index_size) ) || \
+ ( (cache_ptr)->index_size < ((cache_ptr)->clean_index_size) ) || \
+ ( (cache_ptr)->index_size < ((cache_ptr)->dirty_index_size) ) || \
( ( !((entry_ptr)->is_dirty ) || \
( (cache_ptr)->dirty_index_size < (new_size) ) ) && \
( ( ((entry_ptr)->is_dirty) ) || \
@@ -944,7 +1000,9 @@ if ( \
( (cache_ptr)->index_size < (entry_ptr)->size ) || \
( (cache_ptr)->dirty_index_size < (entry_ptr)->size ) || \
( (cache_ptr)->index_size != \
- ((cache_ptr)->clean_index_size + (cache_ptr)->dirty_index_size) ) ) { \
+ ((cache_ptr)->clean_index_size + (cache_ptr)->dirty_index_size) ) || \
+ ( (cache_ptr)->index_size < ((cache_ptr)->clean_index_size) ) || \
+ ( (cache_ptr)->index_size < ((cache_ptr)->dirty_index_size) ) ) { \
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
"Pre HT update for entry clean SC failed") \
}
@@ -959,21 +1017,27 @@ if ( \
( (cache_ptr)->index_size < (entry_ptr)->size ) || \
( (cache_ptr)->clean_index_size < (entry_ptr)->size ) || \
( (cache_ptr)->index_size != \
- ((cache_ptr)->clean_index_size + (cache_ptr)->dirty_index_size) ) ) { \
+ ((cache_ptr)->clean_index_size + (cache_ptr)->dirty_index_size) ) || \
+ ( (cache_ptr)->index_size < ((cache_ptr)->clean_index_size) ) || \
+ ( (cache_ptr)->index_size < ((cache_ptr)->dirty_index_size) ) ) { \
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
"Pre HT update for entry dirty SC failed") \
}
#define H5C__POST_HT_UPDATE_FOR_ENTRY_CLEAN_SC(cache_ptr, entry_ptr) \
-if ( (cache_ptr)->index_size != \
- ((cache_ptr)->clean_index_size + (cache_ptr)->dirty_index_size) ) { \
+if ( ( (cache_ptr)->index_size != \
+ ((cache_ptr)->clean_index_size + (cache_ptr)->dirty_index_size) ) || \
+ ( (cache_ptr)->index_size < ((cache_ptr)->clean_index_size) ) || \
+ ( (cache_ptr)->index_size < ((cache_ptr)->dirty_index_size) ) ) { \
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
"Post HT update for entry clean SC failed") \
}
#define H5C__POST_HT_UPDATE_FOR_ENTRY_DIRTY_SC(cache_ptr, entry_ptr) \
-if ( (cache_ptr)->index_size != \
- ((cache_ptr)->clean_index_size + (cache_ptr)->dirty_index_size) ) { \
+if ( ( (cache_ptr)->index_size != \
+ ((cache_ptr)->clean_index_size + (cache_ptr)->dirty_index_size) ) || \
+ ( (cache_ptr)->index_size < ((cache_ptr)->clean_index_size) ) || \
+ ( (cache_ptr)->index_size < ((cache_ptr)->dirty_index_size) ) ) { \
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
"Post HT update for entry dirty SC failed") \
}
@@ -981,7 +1045,9 @@ if ( (cache_ptr)->index_size != \
#else /* H5C_DO_SANITY_CHECKS */
#define H5C__PRE_HT_INSERT_SC(cache_ptr, entry_ptr, fail_val)
+#define H5C__POST_HT_INSERT_SC(cache_ptr, fail_val)
#define H5C__PRE_HT_REMOVE_SC(cache_ptr, entry_ptr)
+#define H5C__POST_HT_REMOVE_SC(cache_ptr, entry_ptr)
#define H5C__PRE_HT_SEARCH_SC(cache_ptr, Addr, fail_val)
#define H5C__POST_SUC_HT_SEARCH_SC(cache_ptr, entry_ptr, Addr, k, fail_val)
#define H5C__POST_HT_SHIFT_TO_FRONT(cache_ptr, entry_ptr, k, fail_val)
@@ -1017,9 +1083,10 @@ if ( (cache_ptr)->index_size != \
(cache_ptr)->clean_index_size += (entry_ptr)->size; \
if ((entry_ptr)->flush_me_last) { \
(cache_ptr)->num_last_entries++; \
- HDassert((cache_ptr)->num_last_entries == 1); \
+ HDassert((cache_ptr)->num_last_entries <= 2); \
} \
H5C__UPDATE_STATS_FOR_HT_INSERTION(cache_ptr) \
+ H5C__POST_HT_INSERT_SC(cache_ptr, fail_val) \
}
#define H5C__DELETE_FROM_INDEX(cache_ptr, entry_ptr) \
@@ -1043,9 +1110,10 @@ if ( (cache_ptr)->index_size != \
(cache_ptr)->clean_index_size -= (entry_ptr)->size; \
if ((entry_ptr)->flush_me_last) { \
(cache_ptr)->num_last_entries--; \
- HDassert((cache_ptr)->num_last_entries == 0); \
+ HDassert((cache_ptr)->num_last_entries <= 1); \
} \
H5C__UPDATE_STATS_FOR_HT_DELETION(cache_ptr) \
+ H5C__POST_HT_REMOVE_SC(cache_ptr, entry_ptr) \
}
#define H5C__SEARCH_INDEX(cache_ptr, Addr, entry_ptr, fail_val) \
@@ -1196,9 +1264,20 @@ if ( (cache_ptr)->index_size != \
* able to dirty, resize and/or move entries during the
* flush.
*
+ * JRM -- 12/13/14
+ * Added code to set cache_ptr->slist_changed to TRUE
+ * when an entry is inserted in the slist.
+ *
*-------------------------------------------------------------------------
*/
+#if H5C_DO_SLIST_SANITY_CHECKS
+#define ENTRY_IN_SLIST(cache_ptr, entry_ptr) \
+ H5C_entry_in_skip_list((cache_ptr), (entry_ptr))
+#else /* H5C_DO_SLIST_SANITY_CHECKS */
+#define ENTRY_IN_SLIST(cache_ptr, entry_ptr) FALSE
+#endif /* H5C_DO_SLIST_SANITY_CHECKS */
+
#if H5C_DO_SANITY_CHECKS
#define H5C__INSERT_ENTRY_IN_SLIST(cache_ptr, entry_ptr, fail_val) \
@@ -1209,12 +1288,14 @@ if ( (cache_ptr)->index_size != \
HDassert( (entry_ptr)->size > 0 ); \
HDassert( H5F_addr_defined((entry_ptr)->addr) ); \
HDassert( !((entry_ptr)->in_slist) ); \
+ HDassert( !ENTRY_IN_SLIST((cache_ptr), (entry_ptr)) ); \
\
if(H5SL_insert((cache_ptr)->slist_ptr, entry_ptr, &(entry_ptr)->addr) < 0) \
HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, (fail_val), \
"Can't insert entry in skip list") \
\
(entry_ptr)->in_slist = TRUE; \
+ (cache_ptr)->slist_changed = TRUE; \
(cache_ptr)->slist_len++; \
(cache_ptr)->slist_size += (entry_ptr)->size; \
(cache_ptr)->slist_len_increase++; \
@@ -1235,12 +1316,14 @@ if ( (cache_ptr)->index_size != \
HDassert( (entry_ptr)->size > 0 ); \
HDassert( H5F_addr_defined((entry_ptr)->addr) ); \
HDassert( !((entry_ptr)->in_slist) ); \
+ HDassert( !ENTRY_IN_SLIST((cache_ptr), (entry_ptr)) ); \
\
if(H5SL_insert((cache_ptr)->slist_ptr, entry_ptr, &(entry_ptr)->addr) < 0) \
HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, (fail_val), \
"Can't insert entry in skip list") \
\
(entry_ptr)->in_slist = TRUE; \
+ (cache_ptr)->slist_changed = TRUE; \
(cache_ptr)->slist_len++; \
(cache_ptr)->slist_size += (entry_ptr)->size; \
\
@@ -1281,6 +1364,10 @@ if ( (cache_ptr)->index_size != \
* Updated sanity checks for the new is_read_only and
* ro_ref_count fields in H5C_cache_entry_t.
*
+ * JRM -- 12/13/14
+ * Added code to set cache_ptr->slist_changed to TRUE
+ * when an entry is removed from the slist.
+ *
*-------------------------------------------------------------------------
*/
@@ -1302,6 +1389,7 @@ if ( (cache_ptr)->index_size != \
"Can't delete entry from skip list.") \
\
HDassert( (cache_ptr)->slist_len > 0 ); \
+ (cache_ptr)->slist_changed = TRUE; \
(cache_ptr)->slist_len--; \
HDassert( (cache_ptr)->slist_size >= (entry_ptr)->size ); \
(cache_ptr)->slist_size -= (entry_ptr)->size; \
@@ -1332,6 +1420,11 @@ if ( (cache_ptr)->index_size != \
* able to dirty, resize and/or move entries during the
* flush.
*
+ * JRM -- 12/13/14
+ * Note that we do not set cache_ptr->slist_changed to TRUE
+ * in this case, as the structure of the slist is not
+ * modified.
+ *
*-------------------------------------------------------------------------
*/
@@ -2720,6 +2813,10 @@ if ( (cache_ptr)->index_size != \
* the max_cache_size limit until the next time the cache
* attempts to load or insert an entry.
*
+ * d) When the evictions_enabled field is false (see below),
+ * the cache size will increase without limit until the
+ * field is set to true.
+ *
* min_clean_size: Nominal minimum number of clean bytes in the cache.
* The cache attempts to maintain this number of bytes of
* clean data so as to avoid case b) above. Again, this is
@@ -2770,7 +2867,7 @@ if ( (cache_ptr)->index_size != \
* This value should not be mistaken for footprint of the
* cache in memory. The average cache entry is small, and
* the cache has a considerable overhead. Multiplying the
- * index_size by two should yield a conservative estimate
+ * index_size by three should yield a conservative estimate
* of the cache's memory footprint.
*
* clean_index_size: Number of bytes of clean entries currently stored in
@@ -2781,12 +2878,7 @@ if ( (cache_ptr)->index_size != \
*
* WARNING:
*
- * 1) The clean_index_size field is not maintained by the
- * index macros, as the hash table doesn't care whether
- * the entry is clean or dirty. Instead the field is
- * maintained in the H5C__UPDATE_RP macros.
- *
- * 2) The value of the clean_index_size must not be mistaken
+ * The value of the clean_index_size must not be mistaken
* for the current clean size of the cache. Rather, the
* clean size of the cache is the current value of
* clean_index_size plus the amount of empty space (if any)
@@ -2798,13 +2890,6 @@ if ( (cache_ptr)->index_size != \
* Thus we should have the invariant that clean_index_size +
* dirty_index_size == index_size.
*
- * WARNING:
- *
- * 1) The dirty_index_size field is not maintained by the
- * index macros, as the hash table doesn't care whether
- * the entry is clean or dirty. Instead the field is
- * maintained in the H5C__UPDATE_RP macros.
- *
* index: Array of pointer to H5C_cache_entry_t of size
* H5C__HASH_TABLE_LEN. At present, this value is a power
* of two, not the usual prime number.
@@ -2820,6 +2905,37 @@ if ( (cache_ptr)->index_size != \
* changing the H5C__HASH_FCN macro and the deletion of the
* H5C__HASH_MASK #define. No other changes should be required.
*
+ * With the addition of the take ownership flag, it is possible that
+ * an entry may be removed from the cache as the result of the flush of
+ * a second entry. In general, this causes little trouble, but it is
+ * possible that the entry removed may be the next entry in the scan of
+ * a list. In this case, we must be able to detect the fact that the
+ * entry has been removed, so that the scan doesn't attempt to proceed with
+ * an entry that is no longer in the cache.
+ *
+ * The following fields are maintained to facilitate this.
+ *
+ * entries_removed_counter: Counter that is incremented each time an
+ * entry is removed from the cache by any means (eviction,
+ * expungement, or take ownership at this point in time).
+ * Functions that perform scans on lists may set this field
+ * to zero prior to calling H5C_flush_single_entry().
+ * Unexpected changes to the counter indicate that an entry
+ * was removed from the cache as a side effect of the flush.
+ *
+ * last_entry_removed_ptr: Pointer to the instance of H5C_cache_entry_t
+ * which contained the last entry to be removed from the cache,
+ * or NULL if there either is no such entry, or if a function
+ * performing a scan of a list has set this field to NULL prior
+ * to calling H5C_flush_single_entry().
+ *
+ * WARNING!!! This field must NEVER be dereferenced. It is
+ * maintained to allow functions that perform scans of lists
+ * to compare this pointer with their pointers to next, thus
+ * allowing them to avoid unnecessary restarts of scans if the
+ * pointers don't match, and if entries_removed_counter is
+ * one.
+ *
*
* With the addition of cache entry tagging, it is possible that
* an entry may be inserted into the cache without a tag during testing
@@ -2839,6 +2955,21 @@ if ( (cache_ptr)->index_size != \
* are flushed. (this has been changed -- dirty entries are now removed from
* the skip list as they are flushed. JRM - 10/25/05)
*
+ * slist_changed: Boolean flag used to indicate whether the contents of
+ * the slist has changed since the last time this flag was
+ * reset. This is used in the cache flush code to detect
+ * conditions in which pre-serialize or serialize callbacks
+ * have modified the slist -- which obliges us to restart
+ * the scan of the slist from the beginning.
+ *
+ * slist_change_in_pre_serialize: Boolean flag used to indicate that
+ * a pre_serialize call has modified the slist since the
+ * last time this flag was reset.
+ *
+ * slist_change_in_serialize: Boolean flag used to indicate that
+ * a serialize call has modified the slist since the
+ * last time this flag was reset.
+ *
* slist_len: Number of entries currently in the skip list
* used to maintain a sorted list of dirty entries in the
* cache.
@@ -2869,6 +3000,11 @@ if ( (cache_ptr)->index_size != \
* explicit tests for that case should be added when said
* HDasserts are removed.
*
+ * Update: There are now two possible last entries
+ * (superblock and file driver info message). This
+ * number will probably increase as we add superblock
+ * messages. JRM -- 11/18/14
+ *
* With the addition of the fractal heap, the cache must now deal with
* the case in which entries may be dirtied, moved, or have their sizes
* changed during a flush. To allow sanity checks in this situation, the
@@ -2877,10 +3013,11 @@ if ( (cache_ptr)->index_size != \
*
* slist_len_increase: Number of entries that have been added to the
* slist since the last time this field was set to zero.
+ * Note that this value can be negative.
*
* slist_size_increase: Total size of all entries that have been added
* to the slist since the last time this field was set to
- * zero.
+ * zero. Note that this value can be negative.
*
* cork_list_ptr: A skip list to track object addresses that are corked.
* When an entry is inserted or protected in the cache,
@@ -2924,9 +3061,9 @@ if ( (cache_ptr)->index_size != \
* replacement policy code).
*
* 2) A pinned entry can be accessed or modified at any time.
- * Therefore, the cache must check with the entry owner
- * before flushing it. If permission is denied, the
- * cache just skips the entry in the flush.
+ * This places an additional burden on the associated pre-serialize
+ * and serialize callbacks, which must ensure the the entry is in
+ * a consistant state before creating an image of it.
*
* 3) A pinned entry can be marked as dirty (and possibly
* change size) while it is unprotected.
@@ -2984,7 +3121,8 @@ if ( (cache_ptr)->index_size != \
* be collective and the other processes will not know to participate.
*
* To deal with this issue, I have modified the usual LRU policy by adding
- * clean and dirty LRU lists to the usual LRU list.
+ * clean and dirty LRU lists to the usual LRU list. In general, these
+ * lists are only exist in parallel builds.
*
* The clean LRU list is simply the regular LRU list with all dirty cache
* entries removed.
@@ -3001,7 +3139,7 @@ if ( (cache_ptr)->index_size != \
*
* Even if we start with a completely clean cache, a sequence of protects
* without unprotects can empty the clean LRU list. In this case, the
- * cache must grow temporarily. At the next write, we will attempt to
+ * cache must grow temporarily. At the next sync point, we will attempt to
* evict enough entries to reduce index_size to less than max_cache_size.
* While this will usually be possible, all bets are off if enough entries
* are protected.
@@ -3011,14 +3149,14 @@ if ( (cache_ptr)->index_size != \
*
* LRU_list_len: Number of cache entries currently on the LRU list.
*
- * Observe that LRU_list_len + pl_len must always equal
- * index_len.
+ * Observe that LRU_list_len + pl_len + pel_len must always
+ * equal index_len.
*
* LRU_list_size: Number of bytes of cache entries currently residing on the
* LRU list.
*
- * Observe that LRU_list_size + pl_size must always equal
- * index_size.
+ * Observe that LRU_list_size + pl_size + pel_size must always
+ * equal index_size.
*
* LRU_head_ptr: Pointer to the head of the doubly linked LRU list. Cache
* entries on this list are linked by their next and prev fields.
@@ -3263,6 +3401,11 @@ if ( (cache_ptr)->index_size != \
* equal to the array index has been evicted from the cache in
* the current epoch.
*
+ * take_ownerships: Array of int64 of length H5C__MAX_NUM_TYPE_IDS + 1. The
+ * cells are used to record the number of times an entry with
+ * type id equal to the array index has been removed from the
+ * cache via the H5C__TAKE_OWNERSHIP_FLAG in the current epoch.
+ *
* moves: Array of int64 of length H5C__MAX_NUM_TYPE_IDS + 1. The cells
* are used to record the number of times an entry with type
* id equal to the array index has been moved in the current
@@ -3271,7 +3414,7 @@ if ( (cache_ptr)->index_size != \
* entry_flush_moves: Array of int64 of length H5C__MAX_NUM_TYPE_IDS + 1.
* The cells are used to record the number of times an entry
* with type id equal to the array index has been moved
- * during its flush callback in the current epoch.
+ * during its pre-serialize callback in the current epoch.
*
* cache_flush_moves: Array of int64 of length H5C__MAX_NUM_TYPE_IDS + 1.
* The cells are used to record the number of times an entry
@@ -3316,7 +3459,8 @@ if ( (cache_ptr)->index_size != \
* entry_flush_size_changes: Array of int64 of length
* H5C__MAX_NUM_TYPE_IDS + 1. The cells are used to record
* the number of times an entry with type id equal to the
- * array index has changed size while in its flush callback.
+ * array index has changed size while in its pre-serialize
+ * callback.
*
* cache_flush_size_changes: Array of int64 of length
* H5C__MAX_NUM_TYPE_IDS + 1. The cells are used to record
@@ -3389,7 +3533,33 @@ if ( (cache_ptr)->index_size != \
*
* entries_scanned_to_make_space: Number of entries scanned only when looking
* for entries to evict in order to make space in cache.
-
+ *
+ *
+ * As entries are now capable of moving, loading, dirtying, and deleting
+ * other entries in their pre_serialize and serialize callbacks, it has
+ * been necessary to insert code to restart scans of lists so as to avoid
+ * improper behavior if the next entry in the list is the target of one on
+ * these operations.
+ *
+ * The following fields are use to count such occurances. They are used
+ * both in tests (to verify that the scan has been restarted), and to
+ * obtain estimates of how frequently these restarts occur.
+ *
+ * slist_scan_restarts: Number of times a scan of the slist (that contains
+ * calls to H5C_flush_single_entry()) has been restarted to
+ * avoid potential issues with change of status of the next
+ * entry in the scan.
+ *
+ * LRU_scan_restarts: Number of times a scan of the LRU list (that contains
+ * calls to H5C_flush_single_entry()) has been restarted to
+ * avoid potential issues with change of status of the next
+ * entry in the scan.
+ *
+ * hash_bucket_scan_restarts: Number of times a scan of a hash bucket list
+ * (that contains calls to H5C_flush_single_entry()) has been
+ * restarted to avoid potential issues with change of status
+ * of the next entry in the scan.
+ *
* The remaining stats are collected only when both H5C_COLLECT_CACHE_STATS
* and H5C_COLLECT_CACHE_ENTRY_STATS are true.
*
@@ -3460,9 +3630,17 @@ struct H5C_t {
size_t dirty_index_size;
H5C_cache_entry_t * (index[H5C__HASH_TABLE_LEN]);
+ /* Fields to detect entries removed during scans */
+ int64_t entries_removed_counter;
+ H5C_cache_entry_t * last_entry_removed_ptr;
+
/* Field to disable tag validation */
hbool_t ignore_tags;
+ /* Fields for maintaining list of in-order entries, for flushing */
+ hbool_t slist_changed;
+ hbool_t slist_change_in_pre_serialize;
+ hbool_t slist_change_in_serialize;
int32_t slist_len;
size_t slist_size;
H5SL_t * slist_ptr;
@@ -3539,6 +3717,7 @@ struct H5C_t {
int64_t clears[H5C__MAX_NUM_TYPE_IDS + 1];
int64_t flushes[H5C__MAX_NUM_TYPE_IDS + 1];
int64_t evictions[H5C__MAX_NUM_TYPE_IDS + 1];
+ int64_t take_ownerships[H5C__MAX_NUM_TYPE_IDS + 1];
int64_t moves[H5C__MAX_NUM_TYPE_IDS + 1];
int64_t entry_flush_moves[H5C__MAX_NUM_TYPE_IDS + 1];
int64_t cache_flush_moves[H5C__MAX_NUM_TYPE_IDS + 1];
@@ -3583,6 +3762,11 @@ struct H5C_t {
int32_t max_entries_skipped_in_msic;
int32_t max_entries_scanned_in_msic;
int64_t entries_scanned_to_make_space;
+
+ /* Fields for tracking skip list scan restarts */
+ int64_t slist_scan_restarts;
+ int64_t LRU_scan_restarts;
+ int64_t hash_bucket_scan_restarts;
#if H5C_COLLECT_CACHE_ENTRY_STATS
int32_t max_accesses[H5C__MAX_NUM_TYPE_IDS + 1];
diff --git a/src/H5Cprivate.h b/src/H5Cprivate.h
index 902e635..4a3bf25 100644
--- a/src/H5Cprivate.h
+++ b/src/H5Cprivate.h
@@ -40,9 +40,30 @@
/* Library Private Macros */
/**************************/
-#define H5C_DO_SANITY_CHECKS 0
+#ifndef NDEBUG
+#define H5C_DO_SANITY_CHECKS 1
+#define H5C_DO_SLIST_SANITY_CHECKS 0
#define H5C_DO_TAGGING_SANITY_CHECKS 1
#define H5C_DO_EXTREME_SANITY_CHECKS 0
+#else /* NDEBUG */
+/* With rare execptions, the following defines should be set
+ * to 0 if NDEBUG is defined
+ */
+#define H5C_DO_SANITY_CHECKS 0
+#define H5C_DO_SLIST_SANITY_CHECKS 0
+#define H5C_DO_TAGGING_SANITY_CHECKS 0
+#define H5C_DO_EXTREME_SANITY_CHECKS 0
+#endif /* NDEBUG */
+
+/* Note: The memory sanity checks aren't going to work until I/O filters are
+ * changed to call a particular alloc/free routine for their buffers,
+ * because the H5AC__SERIALIZE_RESIZED_FLAG set by the fractal heap
+ * direct block serialize callback calls H5Z_pipeline(). When the I/O
+ * filters are changed, then we should implement "cache image alloc/free"
+ * routines that the fractal heap direct block (and global heap) serialize
+ * calls can use when resizing (and re-allocating) their image in the
+ * cache. -QAK */
+#define H5C_DO_MEMORY_SANITY_CHECKS 0
/* This sanity checking constant was picked out of the air. Increase
* or decrease it if appropriate. Its purposes is to detect corrupt
@@ -53,9 +74,15 @@
#define H5C_MAX_ENTRY_SIZE ((size_t)(32 * 1024 * 1024))
/* H5C_COLLECT_CACHE_STATS controls overall collection of statistics
- * on cache activity. In general, this #define should be set to 0.
+ * on cache activity. In general, this #define should be set to 1 in
+ * debug mode, and 0 in production mode..
*/
+
+#ifndef NDEBUG
+#define H5C_COLLECT_CACHE_STATS 1
+#else /* NDEBUG */
#define H5C_COLLECT_CACHE_STATS 0
+#endif /* NDEBUG */
/* H5C_COLLECT_CACHE_ENTRY_STATS controls collection of statistics
* in individual cache entries.
@@ -82,10 +109,21 @@
#define H5C_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS 0
#endif /* H5_HAVE_PARALLEL */
-/* Flags returned from the 'flush' callback */
-#define H5C_CALLBACK__NO_FLAGS_SET 0x0
-#define H5C_CALLBACK__SIZE_CHANGED_FLAG 0x1
-#define H5C_CALLBACK__MOVED_FLAG 0x2
+/* Flags for cache client class behavior */
+#define H5C__CLASS_NO_FLAGS_SET ((unsigned)0x0)
+#define H5C__CLASS_SPECULATIVE_LOAD_FLAG ((unsigned)0x1)
+#define H5C__CLASS_COMPRESSED_FLAG ((unsigned)0x2)
+/* The following flags may only appear in test code */
+/* The H5C__CLASS_SKIP_READS & H5C__CLASS_SKIP_WRITES flags are used in H5Oproxy.c */
+#define H5C__CLASS_NO_IO_FLAG ((unsigned)0x4)
+#define H5C__CLASS_SKIP_READS ((unsigned)0x8)
+#define H5C__CLASS_SKIP_WRITES ((unsigned)0x10)
+
+/* Flags for pre-serialize callback */
+#define H5C__SERIALIZE_NO_FLAGS_SET ((unsigned)0)
+#define H5C__SERIALIZE_RESIZED_FLAG ((unsigned)0x1)
+#define H5C__SERIALIZE_MOVED_FLAG ((unsigned)0x2)
+#define H5C__SERIALIZE_COMPRESSED_FLAG ((unsigned)0x4)
/* Upper and lower limits on cache size. These limits are picked
* out of a hat -- you should be able to change them as necessary.
@@ -104,11 +142,9 @@
#define H5C__DEFAULT_MAX_CACHE_SIZE ((size_t)(4 * 1024 * 1024))
#define H5C__DEFAULT_MIN_CLEAN_SIZE ((size_t)(2 * 1024 * 1024))
-#ifndef NDEBUG
/* Values for cache entry magic field */
#define H5C__H5C_CACHE_ENTRY_T_MAGIC 0x005CAC0A
#define H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC 0xDeadBeef
-#endif /* NDEBUG */
/* Cache configuration validation definitions */
#define H5C_RESIZE_CFG__VALIDATE_GENERAL 0x1
@@ -161,9 +197,13 @@
* These flags apply to H5C_insert_entry():
* H5C__SET_FLUSH_MARKER_FLAG
* H5C__PIN_ENTRY_FLAG
+ * H5C__FLUSH_LAST_FLAG ; super block only
+ * H5C__FLUSH_COLLECTIVELY_FLAG ; super block only
*
* These flags apply to H5C_protect()
* H5C__READ_ONLY_FLAG
+ * H5C__FLUSH_LAST_FLAG ; super block only
+ * H5C__FLUSH_COLLECTIVELY_FLAG ; super block only
*
* These flags apply to H5C_unprotect():
* H5C__SET_FLUSH_MARKER_FLAG
@@ -238,64 +278,928 @@ typedef enum {
} H5C_tag_globality_t;
/*
- * Class methods pertaining to caching. Each type of cached object will
- * have a constant variable with permanent life-span that describes how
- * to cache the object. That variable will be of type H5C_class_t and
- * have the following required fields...
*
- * LOAD: Loads an object from disk to memory. The function
- * should allocate some data structure and return it.
+ * Struct H5C_class_t
+ *
+ * Instances of H5C_class_t are used to specify the callback functions
+ * used by the metadata cache for each class of metadata cache entry.
+ * The fields of the structure are discussed below:
+ *
+ * id: Integer field containing the unique ID of the class of metadata
+ * cache entries.
+ *
+ * name: Pointer to a string containing the name of the class of metadata
+ * cache entries.
+ *
+ * mem_type: Instance of H5FD_mem_t, that is used to supply the
+ * mem type passed into H5F_block_read().
+ *
+ * flags: Flags indicating class-specific behavior.
+ *
+ * Whoever created the flags field neglected to document the meanings
+ * of the flags he created. Hence the following discussion of the
+ * H5C__CLASS_SPECULATIVE_LOAD_FLAG and (to a lesser extent)
+ * H5C__CLASS_COMPRESSED_FLAG should be viewed with suspicion,
+ * as the meanings are divined from the source code, and thus may be
+ * inaccurate. Please correct any errors you find.
+ *
+ * Possible flags are:
+ *
+ * H5C__CLASS_NO_FLAGS_SET: No special processing.
+ *
+ * H5C__CLASS_SPECULATIVE_LOAD_FLAG: This flag appears to be used
+ * only in H5C_load_entry(). When it is set, entries are
+ * permitted to change their sizes on the first attempt
+ * to load.
+ *
+ * If the new size is larger than the old, the read buffer
+ * is reallocated to the new size, loaded from file, and the
+ * deserialize routine is called a second time on the
+ * new buffer. The entry returned by the first call to
+ * the deserialize routine is discarded (via the free_icr
+ * call) after the new size is retrieved (via the image_len
+ * call). Note that the new size is used as the size of the
+ * entry in the cache.
+ *
+ * If the new size is smaller than the old, no new loads
+ * or desearializes are performed, but the new size becomes
+ * the size of the entry in the cache.
+ *
+ * When this flag is set, an attempt to read past the
+ * end of file is pemitted. In this case, if the size
+ * returned get_load_size callback would result in a
+ * read past the end of file, the size is trunkated to
+ * avoid this, and processing proceeds as normal.
+ *
+ * H5C__CLASS_COMPRESSED_FLAG: This flags indicates that the entry
+ * may be compressed -- i.e. its on disk image is run through
+ * filters on the way to and from disk. Thus the uncompressed
+ * (or unfiltered) size of the entry may be different from the
+ * size of the entry in file.
+ *
+ * This has the following implications:
+ *
+ * On load, uncompressed size and load size may be different.
+ * Presumably, load size will be smaller than uncompressed
+ * size, but there is no requirement for this in the code
+ * (but note that I have inserted an assertion to this effect,
+ * which has not been triggered to date).
+ *
+ * On insertion, compressed (AKA filtered, AKA on disk) size
+ * is unknown, as the entry has yet to be run through filters.
+ * Compressed size is computed whenever the entry is
+ * written (or the image is updated -- not relevant until
+ * journaling is brought back).
+ *
+ * On dirty (of a clean entry), compressed (AKA filtered,
+ * AKA on disk) size becomes unknown. Thus, compressed size
+ * must be computed by the pre-serialize callback before the
+ * entry may be written.
+ *
+ * Once the compressed size becomes unknown, it remains so
+ * until the on disk image is constructed.
+ *
+ * Observe that the cache needs to know the size of the entry
+ * for space allocation purposes. Since the compressed size
+ * can change or become unknown, it uses the uncompressed
+ * size which may change, but which should always be known.
+ * The compressed size is used only for journaling and disk I/O.
+ *
+ * While there is no logical reason why they could not be
+ * combined, due to absence of need and for simplicity of code,
+ * the cache does not permit both the the
+ * H5C__CLASS_COMPRESSED_FLAG and the
+ * H5C__CLASS_SPECULATIVE_LOAD_FLAG to be set in the same
+ * instance of H5C_class_t.
+ *
+ * The following flags may only appear in test code.
+ *
+ * H5C__CLASS_NO_IO_FLAG: This flag is intended only for use in test
+ * code. When it is set, any attempt to load an entry of
+ * the type with this flag set will trigger an assertion
+ * failure, and any flush of an entry with this flag set
+ * will not result in any write to file.
+ *
+ * H5C__CLASS_SKIP_READS: This flags is intended only for use in test
+ * code. When it is set, reads on load will be skipped,
+ * and an uninitialize buffer will be passed to the
+ * deserialize function.
+ * This flag is used in H5Oproxy.c because this client does not
+ * exist on disk. See description in that file.
+ *
+ * H5C__CLASS_SKIP_WRITES: This flags is intended only for use in test
+ * code. When it is set, writes of buffers prepared by the
+ * serialize callback will be skipped.
+ * This flag is used in H5Oproxy.c because this client does not
+ * exist on disk. See description in that file.
+ *
+ * GET_LOAD_SIZE: Pointer to the 'get load size' function.
+ *
+ * This function determines the size of a metadata cache entry based
+ * on the parameter "image":
+ * (a) When the piece of metadata has not been read, "image" is null.
+ * This function determines the size based on the information in the
+ * parameter "udata" or an initial speculative guess. The size is
+ * returned in the parameter "image_len_ptr".
+ * (b) When the piece of metadata has been read, "image" is non-null.
+ * This function might deserialize the needed metadata information
+ * to determine the actual size. The size is returned in the
+ * parameter "actual_len_ptr". The calculation of actual size is
+ * needed for checksum verification.
+ *
+ * For an entry with H5C__CLASS_NO_FLAGS_SET:
+ * This function computes either one of the following:
+ * (1) When "image" is null, it returns in "image_len_ptr"
+ * the on disk size of the entry.
+ * (2) When "image" is non-null, it does nothing.
+ * The values stored in "image_len_ptr" and "actual_len_ptr"
+ * should be the same.
+ *
+ * For an entry with H5C__CLASS_SPECULATIVE_LOAD_FLAG:
+ * This function computes either one of the following:
+ * (1) When "image" is null, it returns in "image_len_ptr"
+ * the initial guess of the entry's on disk size.
+ * (2) When "image" is non-null, it returns in "actual_len_ptr"
+ * the actual size of the entry on disk by
+ * deserializing the needed metadata information.
+ *
+ * For an entry with H5C__CLASS_COMPRESSED_FLAG:
+ * This function computes either one of the following:
+ * (1) When "image" is null, it returns in "image_len_ptr"
+ * the entry's on disk size:
+ * --for a filtered entry: the compressed size
+ * --for a non-filtered entry: the uncompressed size
+ * (2) When "image" is non-null, it returns in "actual_len_ptr:
+ * --for a filtered entry: the de-compressed size based on
+ * "udata" information
+ * --for a non-filtered entry: the uncompressed size
+ *
+ * The typedef for the get_load_size callback is as follows:
+ *
+ * typedef herr_t (*H5C_get_load_size_func_t)(const void *image_ptr,
+ * void *udata_ptr,
+ * size_t *image_len_ptr,
+ * size_t *actual_len_ptr,
+ * size_t *compressed_ptr,
+ * size_t *compressed_image_len_ptr);
+ *
+ * The parameters of the get_load_size callback are as follows:
+ *
+ * image_ptr: Pointer to a buffer containing the metadata read in.
+ *
+ * udata_ptr: Pointer to user data provided in the protect call, which
+ * will also be passed through to the deserialize callback.
+ *
+ * image_len_ptr: Pointer to the location in which the length in bytes
+ * of the in file image to be deserialized is to be returned.
+ *
+ * This value is used by the cache to determine the size of
+ * the disk image for the metadata, in order to read the disk
+ * image from the file.
+ *
+ * actual_len_ptr: Pointer to the location containing the actual length
+ * of the metadata entry on disk.
+ *
+ * compressed_ptr: See description in image_len callback.
+ *
+ * compressed_image_len_ptr: See description in image_len callback.
+ *
+ * Processing in the get_load_size function should proceed as follows:
+ *
+ * If successful, the function will place the length in either the
+ * *image_len_ptr or *actual_le_ptr associated with supplied user data
+ * and then return SUCCEED.
+ *
+ * On failure, the function must return FAIL and push error information
+ * onto the error stack with the error API routines, without modifying
+ * the value pointed to by image_len_ptr or actual_len_ptr.
+ *
+ *
+ * VERIFY_CHKSUM: Pointer to the verify_chksum function.
+ *
+ * This function verifies the checksum computed for the metadata is
+ * the same as the checksum stored in the metadata.
+ *
+ * It computes the checksum based on the metadata stored in the
+ * parameter "image_ptr" and the actual length of the metadata in the
+ * parameter "len" which is obtained from the "get_load_size" callback.
+ *
+ * For a filtered metadata entry with H5C__CLASS_COMPRESSED_FLAG,
+ * "len" is the decompressed size. This function will decompress
+ * the metadata and compute the checksum for the metadata with
+ * length "len".
+ *
+ * The typedef for the verify_chksum callback is as follows:
+ *
+ * typedef htri_t (*H5C_verify_chksum_func_t)(const void *image_ptr,
+ * size_t len,
+ * void *udata_ptr);
+ *
+ * The parameters of the verify_chksum callback are as follows:
+ *
+ * image_ptr: Pointer to a buffer containing the metadata read in.
+ *
+ * len: The actual length of the metadata.
+ *
+ * udata_ptr: Pointer to user data.
+ *
+ *
+ * DESERIALIZE: Pointer to the deserialize function.
*
- * FLUSH: Writes some data structure back to disk. It would be
- * wise for the data structure to include dirty flags to
- * indicate whether it really needs to be written. This
- * function is also responsible for freeing memory allocated
- * by the LOAD method if the DEST argument is non-zero (by
- * calling the DEST method).
+ * This function must be able to read a buffer containing the on disk
+ * image of a metadata cache entry, allocate and load the equivalent
+ * in core representation, and return a pointer to that representation.
*
- * DEST: Just frees memory allocated by the LOAD method.
+ * The typedef for the deserialize callback is as follows:
*
- * CLEAR: Just marks object as non-dirty.
+ * typedef void *(*H5C_deserialize_func_t)(const void * image_ptr,
+ * size_t len,
+ * void * udata_ptr,
+ * boolean * dirty_ptr);
*
- * NOTIFY: Notify client that an action on an entry has taken/will take
- * place
+ * The parameters of the deserialize callback are as follows:
*
- * SIZE: Report the size (on disk) of the specified cache object.
- * Note that the space allocated on disk may not be contiguous.
- */
+ * image_ptr: Pointer to a buffer of length len containing the
+ * contents of the file starting at addr and continuing
+ * for len bytes.
+ *
+ * len: Length in bytes of the in file image to be deserialized.
+ *
+ * This parameter is supplied mainly for sanity checking.
+ * Sanity checks should be performed when compiled in debug
+ * mode, but the parameter may be unused when compiled in
+ * production mode.
+ *
+ * udata_ptr: Pointer to user data provided in the protect call, which
+ * must be passed through to the deserialize callback.
+ *
+ * dirty_ptr: Pointer to boolean which the deserialize function
+ * must use to mark the entry dirty if it has to modify
+ * the entry to clean up file corruption left over from
+ * an old bug in the HDF5 library.
+ *
+ * Processing in the deserialize function should proceed as follows:
+ *
+ * NOTE: With the modification to get_load_size callback (see above
+ * description) to compute the actual length of a metadata entry for
+ * checksum verification, the value in the parameter "len" will be the
+ * actual length of the metadata and a subsequent call to image_len
+ * callback is not needed.
+ *
+ * If the image contains valid data, and is of the correct length,
+ * the deserialize function must allocate space for an in core
+ * representation of that data, load the contents of the image into
+ * the space allocated for the in core representation, and return
+ * a pointer to the in core representation. Observe that an
+ * instance of H5C_cache_entry_t must be the first item in this
+ * representation. The cache will initialize it after the callback
+ * returns.
+ *
+ * Note that the structure of the in core representation is otherwise
+ * up to the cache client. All that is required is that the pointer
+ * returned be sufficient for the clients purposes when it is returned
+ * on a protect call.
+ *
+ * If the deserialize function has to clean up file corruption
+ * left over from an old bug in the HDF5 library, it must set
+ * *dirty_ptr to TRUE. If it doesn't, no action is needed as
+ * *dirty_ptr will be set to FALSE before the deserialize call.
+ *
+ * If the operation fails for any reason (i.e. bad data in buffer, bad
+ * buffer length, malloc failure, etc.) the function must return NULL and
+ * push error information on the error stack with the error API routines.
+ *
+ * Exceptions to the above:
+ *
+ * If the H5C__CLASS_SPECULATIVE_LOAD_FLAG is set, the buffer supplied
+ * to the function need not be currect on the first invocation of the
+ * callback in any single attempt to load the entry.
+ *
+ * In this case, if the buffer is larger than necessary, the function
+ * should load the entry as described above and not flag an error due
+ * to the oversized buffer. The cache will correct its mis-apprehension
+ * of the entry size with a subsequent call to the image_len callback.
+ *
+ * If the buffer is too small, and this is the first deserialize call
+ * in the entry load operation, the function should not flag an error.
+ * Instead, it must compute the correct size of the entry, allocate an
+ * in core representation and initialize it to the extent that an
+ * immediate call to the image len callback will return the correct
+ * image size.
+ *
+ * In this case, when the deserialize callback returns, the cache will
+ * call the image length callback, realize that the supplied buffer was
+ * too small, discard the returned in core representation, allocate
+ * and load a new buffer of the correct size from file, and then call
+ * the deserialize callback again.
+ *
+ * If the H5C__CLASS_COMPRESSED_FLAG is set, exceptions are as per the
+ * H5C__CLASS_SPECULATIVE_LOAD_FLAG, save that only oversized buffers
+ * are permitted.
+ *
+ *
+ * IMAGE_LEN: Pointer to the image length callback.
+
+ * NOTE: With the modification to the get_load_size callback (see above
+ * description) due to checksum verification, the image_len callback
+ * is mainly used for newly inserted entries and assert verification.
+ *
+ * This callback exists primarily to support
+ * H5C__CLASS_SPECULATIVE_LOAD_FLAG and H5C__CLASS_COMPRESSED_FLAG
+ * discussed above, although it is also used to obtain the size of
+ * newly inserted entries.
+ *
+ * In the case of the H5C__CLASS_SPECULATIVE_LOAD_FLAG, it is used to
+ * allow the client to change the size of an entry in the deserialize
+ * callback.
+ *
+ * For the H5C__CLASS_COMPRESSED_FLAG, it is used to allow the client
+ * to indicate whether the entry is compressed (i.e. whether entries
+ * are run through filters) and if so, to report both the uncompressed
+ * and the compressed entry size (i.e. the actual on disk size after
+ * the entry has been run through filters) if that value is known.
+ *
+ * The callback is also used in H5C_insert_entry() to obtain the
+ * size of the newly inserted entry.
+ *
+ * The typedef for the image_len callback is as follows:
+ *
+ * typedef herr_t (*H5C_image_len_func_t)(void *thing,
+ * size_t *image_len_ptr,
+ * hbool_t *compressed_ptr,
+ * size_t *compressed_image_len_ptr);
+ *
+ * The parameters of the image_len callback are as follows:
+ *
+ * thing: Pointer to the in core representation of the entry.
+ *
+ * image_len_ptr: Pointer to size_t in which the callback will return
+ * the length (in bytes) of the cache entry.
+ *
+ * If the H5C__CLASS_COMPRESSED_FLAG is not set in the
+ * associated instance of H5C_class_t, or if the flag is
+ * set, and the callback sets *compressed_ptr to FALSE,
+ * this size is the actual size of the entry on disk.
+ *
+ * Otherwise, this size is the uncompressed size of the
+ * entry -- which the cache will use for all purposes OTHER
+ * than journal writes and disk I/O.
+ *
+ * compressed_ptr: Pointer to a boolean flag indicating whether
+ * the cache entry will be compressed / uncompressed on
+ * disk writes / reads.
+ *
+ * If the H5C__CLASS_COMPRESSED_FLAG is not set in the
+ * associated instance of H5C_class_t, *compressed_ptr
+ * must be set to FALSE.
+ *
+ * If the H5C__CLASS_COMPRESSED_FLAG is set in the
+ * associated instance of H5C_class_t, and filters are
+ * not enabled, *compressed_ptr must be set to FALSE.
+ *
+ * If the H5C__CLASS_COMPRESSED_FLAG is set in the
+ * associated instance of H5C_class_t, and filters are
+ * enabled, the callback must set *compressed_ptr to TRUE.
+ *
+ * Note that *compressed_ptr will always be set to FALSE
+ * by the caller prior to invocation of the callback. Thus
+ * callbacks for clients that don't set the
+ * H5C__CLASS_COMPRESSED_FLAG can ignore this parameter.
+ *
+ * compressed_image_len_ptr: Pointer to size_t in which the callback
+ * may return the length (in bytes) of the compressed on
+ * disk image of the entry, or the uncompressed size if the
+ * compressed size has not yet been calculated.
+ *
+ * Since computing the compressed image len is expensive,
+ * the callback should only report the most recently computed
+ * value -- which will typically be incorrect if the entry
+ * is dirty.
+ *
+ * If *compressed_ptr is set to FALSE, *compressed_image_len_ptr
+ * should be set to zero. However, as *compressed_image_len_ptr
+ * will be initialize to zero prior to the call, the callback
+ * need not modify it if the H5C__CLASS_COMPRESSED_FLAG is
+ * not set.
+ *
+ * If the H5C__CLASS_COMPRESSED_FLAG is not set in the associated
+ * instance of H5C_class_t, processing in the image_len function
+ * should proceed as follows:
+ *
+ * If successful, the function will place the length of the on disk
+ * image associated with the in core representation provided in the
+ * thing parameter in *image_len_ptr, and then return SUCCEED. Since
+ * *compressed_ptr and *compressed_image_len_ptr will be initialized to
+ * FALSE and zero respectively before the call, the callback need not
+ * modify these values, and may declare the associated parameters as
+ * UNUSED.
+ *
+ * If the H5C__CLASS_COMPRESSED_FLAG is set in the associated
+ * instance of H5C_class_t, processing in the image_len function
+ * should proceed as follows:
+ *
+ * If successful, the function will place the uncompressed length of
+ * the on disk image associated with the in core representation
+ * provided in the thing parameter in *image_len_ptr. If filters
+ * are not enabled for the entry, it will set *compressed_ptr to FALSE,
+ * and *compressed_image_len_ptr to zero. If filters are enabled,
+ * it will set *compressed_ptr to TRUE. In this case, it must set
+ * *compressed_image_len_ptr equal to the last computed compressed
+ * if the compressed size, or to the uncompressed size if that value
+ * is yet to be computed. In all cases, it will return SUCCEED if
+ * successful.
+ *
+ * In either case, if the function fails, it must return FAIL and
+ * push error information onto the error stack with the error API
+ * routines, and return without modifying the values pointed to by
+ * the image_len_ptr, compressed_ptr, and compressed_image_len_ptr
+ * parameters.
+ *
+ * PRE_SERIALIZE: Pointer to the pre-serialize callback.
+ *
+ * The pre-serialize callback is invoked by the metadata cache before
+ * it needs a current on-disk image of the metadata entry for purposes
+ * either constructing a journal or flushing the entry to disk.
+ *
+ * If the client needs to change the address or compressed or
+ * uncompressed length of the entry prior to flush, the pre-serialize
+ * callback is responsible for these actions, so that the actual
+ * serialize callback (described below) is only responsible for
+ * serializing the data structure, not moving it on disk or resizing it.
+ *
+ * In addition, the client may use the pre-serialize callback to
+ * ensure that the entry is ready to be flushed -- in particular,
+ * if the entry contains references to other entries that are in
+ * temporary file space, the pre-serialize callback must move those
+ * entries into real file space so that the serialzed entry will
+ * contain no invalid data.
+ *
+ * One would think that the base address and length of
+ * the length of the entry's image on disk would be well known.
+ * However, that need not be the case as free space section info
+ * entries will change size (and possibly location) depending on the
+ * number of blocks of free space being manages, and fractal heap
+ * direct blocks can change compressed size (and possibly location)
+ * on serialization if compression is enabled. Similarly, it may
+ * be necessary to move entries from temporary to real file space.
+ *
+ * The pre-serialize callback must report any such changes to the
+ * cache, which must then update its internal structures as needed.
+ *
+ * The typedef for the pre-serialize callback is as follows:
+ *
+ * typedef herr_t (*H5C_pre_serialize_func_t)(const H5F_t *f,
+ * hid_t dxpl_id,
+ * void * thing,
+ * haddr_t addr,
+ * size_t len,
+ * size_t compressed_len,
+ * haddr_t * new_addr_ptr,
+ * size_t * new_len_ptr,
+ * size_t * new_compressed_len_ptr,
+ * unsigned * flags_ptr);
+ *
+ * The parameters of the pre-serialize callback are as follows:
+ *
+ * f: File pointer -- needed if other metadata cache entries
+ * must be modified in the process of serializing the
+ * target entry.
+ *
+ * dxpl_id: dxpl_id passed with the file pointer to the cache, and
+ * passed on to the callback. Necessary as some callbacks
+ * revise the size and location of the target entry, or
+ * possibly other entries on pre-serialize.
+ *
+ * thing: Pointer to void containing the address of the in core
+ * representation of the target metadata cache entry.
+ * This is the same pointer returned by a protect of the
+ * addr and len given above.
+ *
+ * addr: Base address in file of the entry to be serialized.
+ *
+ * This parameter is supplied mainly for sanity checking.
+ * Sanity checks should be performed when compiled in debug
+ * mode, but the parameter may be unused when compiled in
+ * production mode.
+ *
+ * len: Length in bytes of the in file image of the entry to be
+ * serialized. Also the size the image passed to the
+ * serialize callback (discussed below) unless either that
+ * value is altered by this function, or the entry will be
+ * compressed. In the latter case, the compressed size
+ * of the entry will be reported in *new_compressed_len_ptr.
+ *
+ * This parameter is supplied mainly for sanity checking.
+ * Sanity checks should be performed when compiled in debug
+ * mode, but the parameter may be unused when compiled in
+ * production mode.
+ *
+ * compressed_len: If the entry is to be compressed (i.e. run through
+ * filters) prior to flush, Length in bytes of the last know
+ * compressed size of the entry -- or the uncompressed size
+ * if no such value exists (i.e. the entry has been inserted,
+ * but never flushed). This parameter should be set to zero
+ * in all other cases.
+ *
+ * This parameter is supplied mainly for sanity checking.
+ * Sanity checks should be performed when compiled in debug
+ * mode, but the parameter may be unused when compiled in
+ * production mode.
+ *
+ * new_addr_ptr: Pointer to haddr_t. If the entry is moved by
+ * the serialize function, the new on disk base address must
+ * be stored in *new_addr_ptr, and the appropriate flag set
+ * in *flags_ptr.
+ *
+ * If the entry is not moved by the serialize function,
+ * *new_addr_ptr is undefined on pre-serialize callback
+ * return.
+ *
+ * new_len_ptr: Pointer to size_t. If the entry is resized by the
+ * serialize function, the new length of the on disk image
+ * must be stored in *new_len_ptr, and the appropriate flag set
+ * in *flags_ptr.
+ *
+ * If the entry is not resized by the pre-serialize function,
+ * *new_len_ptr is undefined on pre-serialize callback
+ * return.
+ *
+ * new_compressed_len_ptr: Pointer to size_t. If the image will be
+ * compressed (i.e. run through filters) prior to being
+ * written to disk, the compressed size (in bytes) of the
+ * on disk image must be stored in *new_compressed_len_ptr,
+ * and the appropriate flag set in *flags_ptr.
+ *
+ * flags_ptr: Pointer to an unsigned integer used to return flags
+ * indicating whether the preserialize function resized or moved
+ * the entry, or computed its compressed size. If the entry was
+ * neither resized or moved, nor will be compressed,
+ * the serialize function must set *flags_ptr to zero.
+ * H5C__SERIALIZE_RESIZED_FLAG, H5C__SERIALIZE_MOVED_FLAG
+ * and H5C__SERIALIZE_COMPRESSED_FLAG must be set to indicate
+ * a resize, a move, or compression respectively.
+ *
+ * If the H5C__SERIALIZE_RESIZED_FLAG is set, the new length
+ * must be stored in *new_len_ptr.
+ *
+ * If the H5C__SERIALIZE_MOVED_FLAG flag is set, the
+ * new image base address must be stored in *new_addr_ptr.
+ *
+ * If the H5C__SERIALIZE_COMPRESSED_FLAG is set, the
+ * compressed size of the new image must be stored in
+ * *new_compressed_len_ptr.
+ *
+ * Processing in the pre-serialize function should proceed as follows:
+ *
+ * The pre-serialize function must examine the in core representation
+ * indicated by the thing parameter, if the pre-serialize function does
+ * not need to change the size or location of the on-disk image, or
+ * compute its compress size, it must set *flags_ptr to zero.
+ *
+ * If the (uncompressed) size of the on-disk image must be changed,
+ * the pre-serialize function must load the length of the new image
+ * into *new_len_ptr, and set the H5C__SERIALIZE_RESIZED_FLAG in
+ * *flags_ptr.
+ *
+ * If the base address of the on disk image must be changed, the
+ * pre-serialize function must set *new_addr_ptr to the new base address,
+ * and set the H5C__SERIALIZE_MOVED_FLAG in *flags_ptr.
+ *
+ * If the H5C__CLASS_COMPRESSED_FLAG is set in the assocated instance
+ * of H5C_class_t, and filters (i.e. compression) are enabled, the
+ * pre-serialize function must compute the compressed size of the
+ * on disk image, and if it has changed, load this value into
+ * *new_compressed_len_ptr, and set H5C__SERIALIZE_COMPRESSED_FLAG in
+ * *flags_ptr.
+ *
+ * Note that to do this, the preserialize function will typically have
+ * to serialize the entry, and run it through the filters to obtain
+ * the compressed size. For efficiency, the compressed image may
+ * be stored to be copied into the supplied buffer by the
+ * serialize callback. Needless to say this is awkward. We may
+ * want to re-work the API for cache clients to simplify this.
+ *
+ * In addition, the pre-serialize callback may perform any other
+ * processing required before the entry is written to disk
+ *
+ * If it is successful, the function must return SUCCEED.
+ *
+ * If it fails for any reason, the function must return FAIL and
+ * push error information on the error stack with the error API
+ * routines.
+ *
+ *
+ * SERIALIZE: Pointer to the serialize callback.
+ *
+ * The serialize callback is invoked by the metadata cache whenever
+ * it needs a current on disk image of the metadata entry for purposes
+ * either constructing a journal entry or flushing the entry to disk.
+ *
+ * At this point, the base address and length of the entry's image on
+ * disk must be well known and not change during the serialization
+ * process.
+ *
+ * While any size and/or location changes must have been handled
+ * by a pre-serialize call, the client may elect to handle any other
+ * changes to the entry required to place it in correct form for
+ * writing to disk in this call.
+ *
+ * The typedef for the serialize callback is as follows:
+ *
+ * typedef herr_t (*H5C_serialize_func_t)(const H5F_t *f,
+ * void * image_ptr,
+ * size_t len,
+ * void * thing);
+ *
+ * The parameters of the serialize callback are as follows:
+ *
+ * f: File pointer -- needed if other metadata cache entries
+ * must be modified in the process of serializing the
+ * target entry.
+ *
+ * image_ptr: Pointer to a buffer of length len bytes into which a
+ * serialized image of the target metadata cache entry is
+ * to be written.
+ *
+ * Note that this buffer will not in general be initialized
+ * to any particular value. Thus the serialize function may
+ * not assume any initial value and must set each byte in
+ * the buffer.
+ *
+ * len: Length in bytes of the in file image of the entry to be
+ * serialized. Also the size of *image_ptr (below). If
+ * compression is not enabled, this value is simply the
+ * uncompressed size of the entry's image on disk. If
+ * compression is enabled, this value is the size of the
+ * compressed image.
+ *
+ * This parameter is supplied mainly for sanity checking.
+ * Sanity checks should be performed when compiled in debug
+ * mode, but the parameter may be unused when compiled in
+ * production mode.
+ *
+ * thing: Pointer to void containing the address of the in core
+ * representation of the target metadata cache entry.
+ * This is the same pointer returned by a protect of the
+ * addr and len given above.
+ *
+ * Processing in the serialize function should proceed as follows:
+ *
+ * If there are any remaining changes to the entry required before
+ * write to disk, they must be dealt with first.
+ *
+ * The serialize function must then examine the in core
+ * representation indicated by the thing parameter, and write a
+ * serialized (and possibly compressed) image of its contents into
+ * the provided buffer.
+ *
+ * If it is successful, the function must return SUCCEED.
+ *
+ * If it fails for any reason, the function must return FAIL and
+ * push error information on the error stack with the error API
+ * routines.
+ *
+ *
+ * NOTIFY: Pointer to the notify callback.
+ *
+ * The notify callback is invoked by the metadata cache when a cache
+ * action on an entry has taken/will take place and the client indicates
+ * it wishes to be notified about the action.
+ *
+ * The typedef for the notify callback is as follows:
+ *
+ * typedef herr_t (*H5C_notify_func_t)(H5C_notify_action_t action,
+ * void *thing);
+ *
+ * The parameters of the notify callback are as follows:
+ *
+ * action: An enum indicating the metadata cache action that has taken/
+ * will take place.
+ *
+ * thing: Pointer to void containing the address of the in core
+ * representation of the target metadata cache entry. This
+ * is the same pointer that would be returned by a protect
+ * of the addr and len of the entry.
+ *
+ * Processing in the notify function should proceed as follows:
+ *
+ * The notify function may perform any action it would like, including
+ * metadata cache calls.
+ *
+ * If the function is successful, it must return SUCCEED.
+ *
+ * If it fails for any reason, the function must return FAIL and
+ * push error information on the error stack with the error API
+ * routines.
+ *
+ *
+ * FREE_ICR: Pointer to the free ICR callback.
+ *
+ * The free ICR callback is invoked by the metadata cache when it
+ * wishes to evict an entry, and needs the client to free the memory
+ * allocated for the in core representation.
+ *
+ * The typedef for the free ICR callback is as follows:
+ *
+ * typedef herr_t (*H5C_free_icr_func_t)(void * thing));
+ *
+ * The parameters of the free ICR callback are as follows:
+ *
+ * thing: Pointer to void containing the address of the in core
+ * representation of the target metadata cache entry. This
+ * is the same pointer that would be returned by a protect
+ * of the addr and len of the entry.
+ *
+ * Processing in the free ICR function should proceed as follows:
+ *
+ * The free ICR function must free all memory allocated to the
+ * in core representation.
+ *
+ * If the function is successful, it must return SUCCEED.
+ *
+ * If it fails for any reason, the function must return FAIL and
+ * push error information on the error stack with the error API
+ * routines.
+ *
+ * At least when compiled with debug, it would be useful if the
+ * free ICR call would fail if the in core representation has been
+ * modified since the last serialize of clear callback.
+ *
+ * CLEAR: Pointer to the clear callback.
+ *
+ * In principle, there should be no need for the clear callback,
+ * as the dirty flag should be maintained by the metadata cache.
+ *.
+ * However, some clients maintain dirty bits on internal data,
+ * and we need some way of keeping these dirty bits in sync with
+ * those maintained by the metadata cache. This callback exists
+ * to serve this purpose. If defined, it is called whenever the
+ * cache marks dirty entry clean, or when the cache is about to
+ * discard a dirty entry without writing it to disk (This
+ * happens as the result of an unprotect call with the
+ * H5AC__DELETED_FLAG set, and the H5C__TAKE_OWNERSHIP_FLAG not
+ * set.)
+ *
+ * Arguably, this functionality should be in the NOTIFY callback.
+ * However, this callback is specific to only a few clients, and
+ * it will be called relatively frequently. Hence it is made its
+ * own callback to minimize overhead.
+ *
+ * The typedef for the clear callback is as follows:
+ *
+ * typedef herr_t (*H5C_clear_func_t)(const H5F_t *f,
+ * void * thing,
+ * hbool_t about_to_destroy);
+ *
+ * The parameters of the clear callback are as follows:
+ *
+ * f: File pointer.
+ *
+ * thing: Pointer to void containing the address of the in core
+ * representation of the target metadata cache entry. This
+ * is the same pointer that would be returned by a protect()
+ * call of the associated addr and len.
+ *
+ * about_to_destroy: Boolean flag used to indicate whether the
+ * metadata cache is about to destroy the target metadata
+ * cache entry. The callback may use this flag to omit
+ * operations that are irrelevant it the entry is about
+ * to be destroyed.
+ *
+ * Processing in the clear function should proceed as follows:
+ *
+ * Reset all internal dirty bits in the target metadata cache entry.
+ *
+ * If the about_to_destroy flag is TRUE, the clear function may
+ * ommit any dirty bit that will not trigger a sanity check failure
+ * or otherwise cause problems in the subsequent free icr call.
+ * In particular, the call must ensure that the free icr call will
+ * not fail due to changes prior to this call, and after the
+ * last serialize or clear call.
+ *
+ * If the function is successful, it must return SUCCEED.
+ *
+ * If it fails for any reason, the function must return FAIL and
+ * push error information on the error stack with the error API
+ * routines.
+ *
+ * GET_FSF_SIZE: Pointer to the get file space free size callback.
+ *
+ * In principle, there is no need for the get file space free size
+ * callback. However, as an optimization, it is sometimes convenient
+ * to allocate and free file space for a number of cache entries
+ * simultaneously in a single contiguous block of file space.
+ *
+ * File space allocation is done by the client, so the metadata cache
+ * need not be involved. However, since the metadata cache typically
+ * handles file space release when an entry is destroyed, some
+ * adjustment on the part of the metadata cache is required for this
+ * operation.
+ *
+ * The get file space free size callback exists to support this
+ * operation.
+ *
+ * If a group of cache entries that were allocated as a group are to
+ * be discarded and their file space released, the type of the first
+ * (i.e. lowest address) entry in the group must implement the
+ * get free file space size callback.
+ *
+ * To free the file space of all entries in the group in a single
+ * operation, first expunge all entries other than the first without
+ * the free file space flag.
+ *
+ * Then, to complete the operation, unprotect or expunge the first
+ * entry in the block with the free file space flag set. Since
+ * the get free file space callback is implemented, the metadata
+ * cache will use this callback to get the size of the block to be
+ * freed, instead of using the size of the entry as is done otherwise.
+ *
+ * At present this callback is used only by the H5FA and H5EA dblock
+ * and dblock page client classes.
+ *
+ * The typedef for the clear callback is as follows:
+ *
+ * typedef herr_t (*H5C_get_fsf_size_t)(const void * thing,
+ * size_t *fsf_size_ptr);
+ *
+ * The parameters of the clear callback are as follows:
+ *
+ * thing: Pointer to void containing the address of the in core
+ * representation of the target metadata cache entry. This
+ * is the same pointer that would be returned by a protect()
+ * call of the associated addr and len.
+ *
+ * fs_size_ptr: Pointer to size_t in which the callback will return
+ * the size of the piece of file space to be freed. Note
+ * that the space to be freed is presumed to have the same
+ * base address as the cache entry.
+ *
+ * The function simply returns the size of the block of file space
+ * to be freed in *fsf_size_ptr.
+ *
+ * If the function is successful, it must return SUCCEED.
+ *
+ * If it fails for any reason, the function must return FAIL and
+ * push error information on the error stack with the error API
+ * routines.
+ *
+ ***************************************************************************/
/* Actions that can be reported to 'notify' client callback */
typedef enum H5C_notify_action_t {
- H5C_NOTIFY_ACTION_AFTER_INSERT, /* Entry has been added to the cache */
- /* (could be loaded from file with
- * 'protect' call, or inserted
- * with 'set' call)
+ H5C_NOTIFY_ACTION_AFTER_INSERT, /* Entry has been added to the cache
+ * via the insert call
+ */
+ H5C_NOTIFY_ACTION_AFTER_LOAD, /* Entry has been loaded into the
+ * from file via the protect call
+ */
+ H5C_NOTIFY_ACTION_AFTER_FLUSH, /* Entry has just been flushed to
+ * file.
+ */
+ H5C_NOTIFY_ACTION_BEFORE_EVICT /* Entry is about to be evicted
+ * from cache.
*/
- H5C_NOTIFY_ACTION_BEFORE_EVICT /* Entry is about to be evicted from cache */
} H5C_notify_action_t;
/* Cache client callback function pointers */
-typedef void *(*H5C_load_func_t)(H5F_t *f, hid_t dxpl_id, haddr_t addr,
- void *udata);
-typedef herr_t (*H5C_flush_func_t)(H5F_t *f, hid_t dxpl_id, hbool_t dest,
- haddr_t addr, void *thing, unsigned *flags_ptr);
-typedef herr_t (*H5C_dest_func_t)(H5F_t *f, void *thing);
-typedef herr_t (*H5C_clear_func_t)(H5F_t *f, void *thing, hbool_t dest);
+typedef herr_t (*H5C_get_load_size_func_t)(const void *image_ptr, void *udata_ptr,
+ size_t *image_len_ptr, size_t *actual_len_ptr,
+ hbool_t *compressed_ptr, size_t *compressed_image_len_ptr);
+typedef htri_t (*H5C_verify_chksum_func_t)(const void *image_ptr, size_t len, void *udata_ptr);
+typedef void *(*H5C_deserialize_func_t)(const void *image_ptr,
+ size_t len, void *udata_ptr, hbool_t *dirty_ptr);
+typedef herr_t (*H5C_image_len_func_t)(const void *thing,
+ size_t *image_len_ptr, hbool_t *compressed_ptr, size_t *compressed_image_len_ptr);
+typedef herr_t (*H5C_pre_serialize_func_t)(const H5F_t *f, hid_t dxpl_id,
+ void *thing, haddr_t addr, size_t len, size_t compressed_len,
+ haddr_t *new_addr_ptr, size_t *new_len_ptr, size_t *new_compressed_len_ptr,
+ unsigned *flags_ptr);
+typedef herr_t (*H5C_serialize_func_t)(const H5F_t *f, void *image_ptr,
+ size_t len, void *thing);
typedef herr_t (*H5C_notify_func_t)(H5C_notify_action_t action, void *thing);
-typedef herr_t (*H5C_size_func_t)(const H5F_t *f, const void *thing,
- size_t *size_ptr);
+typedef herr_t (*H5C_free_icr_func_t)(void *thing);
+typedef herr_t (*H5C_clear_func_t)(const H5F_t *f, void * thing,
+ hbool_t about_to_destroy);
+typedef herr_t (*H5C_get_fsf_size_t)(const void * thing, size_t *fsf_size_ptr);
/* Metadata cache client class definition */
typedef struct H5C_class_t {
- int id;
- H5C_load_func_t load;
- H5C_flush_func_t flush;
- H5C_dest_func_t dest;
- H5C_clear_func_t clear;
- H5C_notify_func_t notify;
- H5C_size_func_t size;
+ int id;
+ const char * name;
+ H5FD_mem_t mem_type;
+ unsigned flags;
+ H5C_get_load_size_func_t get_load_size;
+ H5C_verify_chksum_func_t verify_chksum;
+ H5C_deserialize_func_t deserialize;
+ H5C_image_len_func_t image_len;
+ H5C_pre_serialize_func_t pre_serialize;
+ H5C_serialize_func_t serialize;
+ H5C_notify_func_t notify;
+ H5C_free_icr_func_t free_icr;
+ H5C_clear_func_t clear;
+ H5C_get_fsf_size_t fsf_size;
} H5C_class_t;
/* Type defintions of callback functions used by the cache as a whole */
@@ -328,7 +1232,7 @@ typedef herr_t (*H5C_log_flush_func_t)(H5C_t *cache_ptr, haddr_t addr,
* just before the entry is freed.
*
* This is necessary, as the LRU list can be changed out
- * from under H5C_make_space_in_cache() by the flush
+ * from under H5C_make_space_in_cache() by the serialize
* callback which may change the size of an existing entry,
* and/or load a new entry while serializing the target entry.
*
@@ -341,18 +1245,66 @@ typedef herr_t (*H5C_log_flush_func_t)(H5C_t *cache_ptr, haddr_t addr,
* detect this case, and re-start its scan from the bottom
* of the LRU when this situation occurs.
*
- * This field is only compiled in debug mode.
+ * cache_ptr: Pointer to the cache that this entry is contained within.
*
* addr: Base address of the cache entry on disk.
*
- * size: Length of the cache entry on disk. Note that unlike normal
- * caches, the entries in this cache are of variable length.
- * The entries should never overlap, and when we do writebacks,
- * we will want to writeback adjacent entries where possible.
+ * size: Length of the cache entry on disk in bytes(exception: if
+ * the entry is compressed on disk, this field contains the
+ * uncompressed size of the entry -- see discussion of
+ * compressed entries below). Note that unlike normal
+ * caches, the entries in this cache are of arbitrary size.
+ *
+ * With the exception of compressed entries, the file space
+ * allocations for cache entries implied by the addr and size
+ * fields must be disjoint. For compressed entries,
+ * the size field contains the uncompressed size -- thus in
+ * in this case, substitution of compressed size for size
+ * must result in disjoint file space allocations. However,
+ * as discussed below, the compressed size may not be know.
+ *
+ * Any entry whose associated instance of H5C_class_t has the
+ * H5C__CLASS_COMPRESSED_FLAG set may be compressed. When
+ * an entry is compressed (that is, when filters are enabled
+ * on it), the compressed flag (see below) must be set, and
+ * the compressed size (if known), must be stored in
+ * the compressed_size field.
+ *
+ * Since the compressed size will be unknown unless the
+ * entry is clean, or has an up to date image (see the
+ * image_ptr and image_up_to_date fields below), we use the
+ * uncompressed size for all purposes other than disk I/O.
+ *
+ * compressed: Boolean flag that is set iff the instance of H5C_class_t
+ * associated with the entry has the H5C__CLASS_COMPRESSED_FLAG
+ * set, and filters are enabled on the entry.
+ *
+ * compressed_size: If compressed is TRUE, this field contains the actual
+ * compressed size of the entry in bytes, which is also its
+ * true size on disk -- or the uncompressed size if the
+ * compressed size is unknown (i.e. the entry has been
+ * inserted in the cache, but it has not been compressed yet).
+ * Note that this value will usually be incorrect if the
+ * entry is dirty.
+ *
+ * Since this value is frequently out of date and expensive to
+ * compute, it is used only for disk I/O. The uncompressed
+ * size of the entry (stored in the size field above) is used
+ * for all other purposes (i.e. computing the sum of the sizes
+ * of all entries in the cache, etc.).
+ *
+ * If compressed is FALSE, this field should contain 0.
*
- * NB: At present, entries need not be contiguous on disk. Until
- * we fix this, we can't do much with writing back adjacent
- * entries.
+ * image_ptr: Pointer to void. When not NULL, this field points to a
+ * dynamically allocated block of size bytes in which the
+ * on disk image of the metadata cache entry is stored.
+ *
+ * If the entry is dirty, the pre-serialize and serialize
+ * callbacks must be used to update this image before it is
+ * written to disk
+ *
+ * image_up_to_date: Boolean flag that is set to TRUE when *image_ptr
+ * is up to date, and set to false when the entry is dirtied.
*
* type: Pointer to the instance of H5C_class_t containing pointers
* to the methods for cache entries of the current type. This
@@ -385,6 +1337,9 @@ typedef herr_t (*H5C_log_flush_func_t)(H5C_t *cache_ptr, haddr_t addr,
* modules using the cache. These still clear the
* is_dirty field as before. -- JRM 7/5/05
*
+ * Update: Management of the is_dirty field is now entirely
+ * in the cache. -- JRM 7/5/07
+ *
* dirtied: Boolean flag used to indicate that the entry has been
* dirtied while protected.
*
@@ -441,9 +1396,10 @@ typedef herr_t (*H5C_log_flush_func_t)(H5C_t *cache_ptr, haddr_t addr,
* policy code (LRU at present).
*
* 2) A pinned entry can be accessed or modified at any time.
- * Therefore, the cache must check with the entry owner
- * before flushing it. If permission is denied, the
- * cache does not flush the entry.
+ * This places an extra burden on the pre-serialize and
+ * serialize callbacks, which must ensure that a pinned
+ * entry is consistant and ready to write to disk before
+ * generating an image.
*
* 3) A pinned entry can be marked as dirty (and possibly
* change size) while it is unprotected.
@@ -485,6 +1441,11 @@ typedef herr_t (*H5C_log_flush_func_t)(H5C_t *cache_ptr, haddr_t addr,
* will need to be expanded and tested appropriately if that
* functionality is desired.
*
+ * Update: There are now two possible last entries
+ * (superblock and file driver info message). This
+ * number will probably increase as we add superblock
+ * messages. JRM -- 11/18/14
+ *
* clear_on_unprotect: Boolean flag used only in PHDF5. When H5C is used
* to implement the metadata cache In the parallel case, only
* the cache with mpi rank 0 is allowed to actually write to
@@ -512,11 +1473,6 @@ typedef herr_t (*H5C_log_flush_func_t)(H5C_t *cache_ptr, haddr_t addr,
* destroy_in_progress: Boolean flag that is set to true iff the entry
* is in the process of being flushed and destroyed.
*
- * free_file_space_on_destroy: Boolean flag that is set to true iff the entry
- * is in the process of being flushed and destroyed and the file
- * space used by the object should be freed by the cache client's
- * 'dest' callback routine.
- *
*
* Fields supporting the 'flush dependency' feature:
*
@@ -596,63 +1552,43 @@ typedef herr_t (*H5C_log_flush_func_t)(H5C_t *cache_ptr, haddr_t addr,
* The use of the replacement policy fields under the Modified LRU policy
* is discussed below:
*
- * next: Next pointer in either the LRU or the protected list,
- * depending on the current value of protected. If there
- * is no next entry on the list, this field should be set
- * to NULL.
+ * next: Next pointer in either the LRU, the protected list, or
+ * the pinned list depending on the current values of
+ * is_protected and is_pinned. If there is no next entry
+ * on the list, this field should be set to NULL.
*
- * prev: Prev pointer in either the LRU or the protected list,
- * depending on the current value of protected. If there
- * is no previous entry on the list, this field should be
- * set to NULL.
+ * prev: Prev pointer in either the LRU, the protected list,
+ * or the pinned list depending on the current values of
+ * is_protected and is_pinned. If there is no previous
+ * entry on the list, this field should be set to NULL.
*
* aux_next: Next pointer on either the clean or dirty LRU lists.
- * This entry should be NULL when protected is true. When
- * protected is false, and dirty is true, it should point
- * to the next item on the dirty LRU list. When protected
- * is false, and dirty is false, it should point to the
- * next item on the clean LRU list. In either case, when
- * there is no next item, it should be NULL.
+ * This entry should be NULL when either is_protected or
+ * is_pinned is true.
+ *
+ * When is_protected and is_pinned are false, and is_dirty is
+ * true, it should point to the next item on the dirty LRU
+ * list.
+ *
+ * When is_protected and is_pinned are false, and is_dirty is
+ * false, it should point to the next item on the clean LRU
+ * list. In either case, when there is no next item, it
+ * should be NULL.
*
* aux_prev: Previous pointer on either the clean or dirty LRU lists.
- * This entry should be NULL when protected is true. When
- * protected is false, and dirty is true, it should point
- * to the previous item on the dirty LRU list. When protected
- * is false, and dirty is false, it should point to the
- * previous item on the clean LRU list. In either case, when
- * there is no previous item, it should be NULL.
- *
- *
- * Fields supporting metadata journaling:
- *
- * last_trans: unit64_t containing the ID of the last transaction in
- * which this entry was dirtied. If journaling is disabled,
- * or if the entry has never been dirtied in a transaction,
- * this field should be set to zero. Once we notice that
- * the specified transaction has made it to disk, we will
- * reset this field to zero as well.
- *
- * We must maintain this field, as to avoid messages from
- * the future, we must not flush a dirty entry to disk
- * until the last transaction in which it was dirtied
- * has made it to disk in the journal file.
- *
- * trans_next: Next pointer in the entries modified in the current
- * transaction list. This field should always be null
- * unless journaling is enabled, the entry is dirty,
- * and last_trans field contains the current transaction
- * number. Even if all these conditions are fulfilled,
- * the field will still be NULL if this is the last
- * entry on the list.
- *
- * trans_prev: Previous pointer in the entries modified in the current
- * transaction list. This field should always be null
- * unless journaling is enabled, the entry is dirty,
- * and last_trans field contains the current transaction
- * number. Even if all these conditions are fulfilled,
- * the field will still be NULL if this is the first
- * entry on the list.
+ * This entry should be NULL when either is_protected or
+ * is_pinned is true.
+ *
+ * When is_protected and is_pinned are false, and is_dirty is
+ * true, it should point to the previous item on the dirty
+ * LRU list.
+ *
+ * When is_protected and is_pinned are false, and is_dirty
+ * is false, it should point to the previous item on the
+ * clean LRU list.
*
+ * In either case, when there is no previous item, it should
+ * be NULL.
*
* Cache entry stats collection fields:
*
@@ -674,12 +1610,14 @@ typedef herr_t (*H5C_log_flush_func_t)(H5C_t *cache_ptr, haddr_t addr,
*
****************************************************************************/
typedef struct H5C_cache_entry_t {
-#ifndef NDEBUG
uint32_t magic;
-#endif /* NDEBUG */
H5C_t * cache_ptr;
haddr_t addr;
size_t size;
+ hbool_t compressed;
+ size_t compressed_size;
+ void * image_ptr;
+ hbool_t image_up_to_date;
const H5C_class_t * type;
haddr_t tag;
int globality;
@@ -700,7 +1638,6 @@ typedef struct H5C_cache_entry_t {
#endif /* H5_HAVE_PARALLEL */
hbool_t flush_in_progress;
hbool_t destroy_in_progress;
- hbool_t free_file_space_on_destroy;
/* fields supporting the 'flush dependency' feature: */
struct H5C_cache_entry_t ** flush_dep_parent;
@@ -1039,15 +1976,15 @@ H5_DLL void H5C_def_auto_resize_rpt_fcn(H5C_t *cache_ptr, int32_t version,
double hit_rate, enum H5C_resize_status status,
size_t old_max_cache_size, size_t new_max_cache_size,
size_t old_min_clean_size, size_t new_min_clean_size);
-H5_DLL herr_t H5C_dest(H5F_t *f, hid_t primary_dxpl_id, hid_t secondary_dxpl_id);
-H5_DLL herr_t H5C_evict(H5F_t * f, hid_t primary_dxpl_id, hid_t secondary_dxpl_id);
-H5_DLL herr_t H5C_expunge_entry(H5F_t *f, hid_t primary_dxpl_id, hid_t secondary_dxpl_id,
- const H5C_class_t *type, haddr_t addr, unsigned flags);
-H5_DLL herr_t H5C_flush_cache(H5F_t *f, hid_t primary_dxpl_id, hid_t secondary_dxpl_id,
- unsigned flags);
-H5_DLL herr_t H5C_flush_tagged_entries(H5F_t * f, hid_t primary_dxpl_id, hid_t secondary_dxpl_id, haddr_t tag);
-H5_DLL herr_t H5C_evict_tagged_entries(H5F_t * f, hid_t primary_dxpl_id, hid_t secondary_dxpl_id, haddr_t tag);
-H5_DLL herr_t H5C_flush_to_min_clean(H5F_t *f, hid_t primary_dxpl_id, hid_t secondary_dxpl_id);
+H5_DLL herr_t H5C_dest(H5F_t *f, hid_t dxpl_id);
+H5_DLL herr_t H5C_evict(H5F_t *f, hid_t dxpl_id);
+H5_DLL herr_t H5C_expunge_entry(H5F_t *f, hid_t dxpl_id, const H5C_class_t *type, haddr_t addr, unsigned flags);
+
+
+H5_DLL herr_t H5C_flush_cache(H5F_t *f, hid_t dxpl_id, unsigned flags);
+H5_DLL herr_t H5C_flush_tagged_entries(H5F_t * f, hid_t dxpl_id, haddr_t tag);
+H5_DLL herr_t H5C_evict_tagged_entries(H5F_t * f, hid_t dxpl_id, haddr_t tag);
+H5_DLL herr_t H5C_flush_to_min_clean(H5F_t *f, hid_t dxpl_id);
H5_DLL herr_t H5C_get_cache_auto_resize_config(const H5C_t *cache_ptr,
H5C_auto_size_ctl_t *config_ptr);
H5_DLL herr_t H5C_get_cache_size(H5C_t *cache_ptr, size_t *max_size_ptr,
@@ -1061,17 +1998,17 @@ H5_DLL herr_t H5C_get_entry_status(const H5F_t *f, haddr_t addr,
H5_DLL herr_t H5C_get_evictions_enabled(const H5C_t *cache_ptr, hbool_t *evictions_enabled_ptr);
H5_DLL FILE *H5C_get_trace_file_ptr(const H5C_t *cache_ptr);
H5_DLL FILE *H5C_get_trace_file_ptr_from_entry(const H5C_cache_entry_t *entry_ptr);
-H5_DLL herr_t H5C_insert_entry(H5F_t *f, hid_t primary_dxpl_id, hid_t secondary_dxpl_id,
- const H5C_class_t *type, haddr_t addr, void *thing, unsigned int flags);
-H5_DLL herr_t H5C_mark_entries_as_clean(H5F_t *f, hid_t primary_dxpl_id,
- hid_t secondary_dxpl_id, int32_t ce_array_len, haddr_t *ce_array_ptr);
+H5_DLL herr_t H5C_insert_entry(H5F_t *f, hid_t dxpl_id, const H5C_class_t *type,
+ haddr_t addr, void *thing, unsigned int flags);
+H5_DLL herr_t H5C_mark_entries_as_clean(H5F_t *f, hid_t dxpl_id, int32_t ce_array_len,
+ haddr_t *ce_array_ptr);
H5_DLL herr_t H5C_mark_entry_dirty(void *thing);
H5_DLL herr_t H5C_move_entry(H5C_t *cache_ptr, const H5C_class_t *type,
haddr_t old_addr, haddr_t new_addr);
H5_DLL herr_t H5C_pin_protected_entry(void *thing);
H5_DLL herr_t H5C_create_flush_dependency(void *parent_thing, void *child_thing);
-H5_DLL void * H5C_protect(H5F_t *f, hid_t primary_dxpl_id, hid_t secondary_dxpl_id,
- const H5C_class_t *type, haddr_t addr, void *udata, unsigned flags);
+H5_DLL void * H5C_protect(H5F_t *f, hid_t dxpl_id, const H5C_class_t *type,
+ haddr_t addr, void *udata, unsigned flags);
H5_DLL herr_t H5C_reset_cache_hit_rate_stats(H5C_t *cache_ptr);
H5_DLL herr_t H5C_resize_entry(void *thing, size_t new_size);
H5_DLL herr_t H5C_set_cache_auto_resize_config(H5C_t *cache_ptr, H5C_auto_size_ctl_t *config_ptr);
@@ -1085,8 +2022,8 @@ 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 primary_dxpl_id, hid_t secondary_dxpl_id,
- const H5C_class_t *type, haddr_t addr, void *thing, unsigned int flags);
+H5_DLL herr_t H5C_unprotect(H5F_t *f, hid_t dxpl_id, const H5C_class_t *type,
+ haddr_t addr, void *thing, unsigned int flags);
H5_DLL herr_t H5C_validate_resize_config(H5C_auto_size_ctl_t *config_ptr,
unsigned int tests);
H5_DLL herr_t H5C_ignore_tags(H5C_t *cache_ptr);
@@ -1094,9 +2031,9 @@ H5_DLL void H5C_retag_entries(H5C_t * cache_ptr, haddr_t src_tag, haddr_t dest_t
H5_DLL herr_t H5C_cork(H5C_t *cache_ptr, haddr_t obj_addr, unsigned action, hbool_t *corked);
#ifdef H5_HAVE_PARALLEL
-H5_DLL herr_t H5C_apply_candidate_list(H5F_t *f, hid_t primary_dxpl_id,
- hid_t secondary_dxpl_id, H5C_t *cache_ptr, int num_candidates,
- haddr_t *candidates_list_ptr, int mpi_rank, int mpi_size);
+H5_DLL herr_t H5C_apply_candidate_list(H5F_t *f, hid_t dxpl_id,
+ H5C_t *cache_ptr, int num_candidates, haddr_t *candidates_list_ptr,
+ int mpi_rank, int mpi_size);
H5_DLL herr_t H5C_construct_candidate_list__clean_cache(H5C_t *cache_ptr);
H5_DLL herr_t H5C_construct_candidate_list__min_clean(H5C_t *cache_ptr);
#endif /* H5_HAVE_PARALLEL */
diff --git a/src/H5Dlayout.c b/src/H5Dlayout.c
index c0cde78..d9a8845 100644
--- a/src/H5Dlayout.c
+++ b/src/H5Dlayout.c
@@ -479,7 +479,7 @@ H5D__layout_oh_create(H5F_t *file, hid_t dxpl_id, H5O_t *oh, H5D_t *dset,
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create EFL file name heap")
/* Pin the heap down in memory */
- if(NULL == (heap = H5HL_protect(file, dxpl_id, efl->heap_addr, H5AC_WRITE)))
+ if(NULL == (heap = H5HL_protect(file, dxpl_id, efl->heap_addr, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTPROTECT, FAIL, "unable to protect EFL file name heap")
/* Insert "empty" name first */
diff --git a/src/H5EA.c b/src/H5EA.c
index 4a1365a..134f559 100644
--- a/src/H5EA.c
+++ b/src/H5EA.c
@@ -152,7 +152,7 @@ HDfprintf(stderr, "%s: Called\n", FUNC);
H5E_THROW(H5E_CANTALLOC, "memory allocation failed for extensible array info")
/* Lock the array header into memory */
- if(NULL == (hdr = H5EA__hdr_protect(f, dxpl_id, ea_addr, ctx_udata, H5AC_WRITE)))
+ if(NULL == (hdr = H5EA__hdr_protect(f, dxpl_id, ea_addr, ctx_udata, H5AC__NO_FLAGS_SET)))
H5E_THROW(H5E_CANTPROTECT, "unable to load extensible array header")
/* Point extensible array wrapper at header and bump it's ref count */
@@ -213,7 +213,7 @@ H5EA_open(H5F_t *f, hid_t dxpl_id, haddr_t ea_addr, void *ctx_udata))
#ifdef QAK
HDfprintf(stderr, "%s: ea_addr = %a\n", FUNC, ea_addr);
#endif /* QAK */
- if(NULL == (hdr = H5EA__hdr_protect(f, dxpl_id, ea_addr, ctx_udata, H5AC_READ)))
+ if(NULL == (hdr = H5EA__hdr_protect(f, dxpl_id, ea_addr, ctx_udata, H5AC__READ_ONLY_FLAG)))
H5E_THROW(H5E_CANTPROTECT, "unable to load extensible array header, address = %llu", (unsigned long long)ea_addr)
/* Check for pending array deletion */
@@ -337,7 +337,7 @@ END_FUNC(PRIV) /* end H5EA_get_addr() */
*/
BEGIN_FUNC(STATIC, ERR,
herr_t, SUCCEED, FAIL,
-H5EA__lookup_elmt(const H5EA_t *ea, hid_t dxpl_id, hsize_t idx, H5AC_protect_t thing_acc,
+H5EA__lookup_elmt(const H5EA_t *ea, hid_t dxpl_id, hsize_t idx, unsigned thing_acc,
void **thing, uint8_t **thing_elmt_buf, hsize_t *thing_elmt_idx,
H5EA__unprotect_func_t *thing_unprot_func))
@@ -366,6 +366,9 @@ HDfprintf(stderr, "%s: Index %Hu\n", FUNC, idx);
HDassert(thing_elmt_buf);
HDassert(thing_unprot_func);
+ /* only the H5AC__READ_ONLY_FLAG may be set in thing_acc */
+ HDassert((thing_acc & (unsigned)(~H5AC__READ_ONLY_FLAG)) == 0);
+
/* Set the shared array header's file context for this operation */
hdr->f = ea->f;
@@ -381,7 +384,7 @@ HDfprintf(stderr, "%s: Index %Hu\n", FUNC, idx);
HDfprintf(stderr, "%s: Index block address not defined!\n", FUNC, idx);
#endif /* QAK */
/* Check if we are allowed to create the thing */
- if(H5AC_WRITE == thing_acc) {
+ if(0 == (thing_acc & H5AC__READ_ONLY_FLAG)) { /* i.e. r/w access */
/* Create the index block */
hdr->idx_blk_addr = H5EA__iblock_create(hdr, dxpl_id, &stats_changed);
if(!H5F_addr_defined(hdr->idx_blk_addr))
@@ -439,7 +442,7 @@ HDfprintf(stderr, "%s: dblk_idx = %u, iblock->ndblk_addrs = %Zu\n", FUNC, dblk_i
/* Check if the data block has been allocated on disk yet */
if(!H5F_addr_defined(iblock->dblk_addrs[dblk_idx])) {
/* Check if we are allowed to create the thing */
- if(H5AC_WRITE == thing_acc) {
+ if(0 == (thing_acc & H5AC__READ_ONLY_FLAG)) { /* i.e. r/w access */
haddr_t dblk_addr; /* Address of data block created */
hsize_t dblk_off; /* Offset of data block in array */
@@ -479,7 +482,7 @@ HDfprintf(stderr, "%s: dblk_idx = %u, iblock->ndblk_addrs = %Zu\n", FUNC, dblk_i
/* Check if the super block has been allocated on disk yet */
if(!H5F_addr_defined(iblock->sblk_addrs[sblk_off])) {
/* Check if we are allowed to create the thing */
- if(H5AC_WRITE == thing_acc) {
+ if(0 == (thing_acc & H5AC__READ_ONLY_FLAG)) { /* i.e. r/w access */
haddr_t sblk_addr; /* Address of data block created */
/* Create super block */
@@ -512,7 +515,7 @@ HDfprintf(stderr, "%s: dblk_idx = %u, sblock->ndblks = %Zu\n", FUNC, dblk_idx, s
/* Check if the data block has been allocated on disk yet */
if(!H5F_addr_defined(sblock->dblk_addrs[dblk_idx])) {
/* Check if we are allowed to create the thing */
- if(H5AC_WRITE == thing_acc) {
+ if(0 == (thing_acc & H5AC__READ_ONLY_FLAG)) { /* i.e. r/w access */
haddr_t dblk_addr; /* Address of data block created */
hsize_t dblk_off; /* Offset of data block in array */
@@ -572,7 +575,7 @@ HDfprintf(stderr, "%s: sblock->dblk_page_size = %Zu\n", FUNC, sblock->dblk_page_
/* Check if page has been initialized yet */
if(!H5VM_bit_get(sblock->page_init, page_init_idx)) {
/* Check if we are allowed to create the thing */
- if(H5AC_WRITE == thing_acc) {
+ if(0 == (thing_acc & H5AC__READ_ONLY_FLAG)) { /* i.e. r/w access */
/* Create the data block page */
if(H5EA__dblk_page_create(hdr, dxpl_id, sblock, dblk_page_addr) < 0)
H5E_THROW(H5E_CANTCREATE, "unable to create data block page")
@@ -681,7 +684,7 @@ HDfprintf(stderr, "%s: Index %Hu\n", FUNC, idx);
hdr->f = ea->f;
/* Look up the array metadata containing the element we want to set */
- if(H5EA__lookup_elmt(ea, dxpl_id, idx, H5AC_WRITE, &thing, &thing_elmt_buf, &thing_elmt_idx, &thing_unprot_func) < 0)
+ if(H5EA__lookup_elmt(ea, dxpl_id, idx, H5AC__NO_FLAGS_SET, &thing, &thing_elmt_buf, &thing_elmt_idx, &thing_unprot_func) < 0)
H5E_THROW(H5E_CANTPROTECT, "unable to protect array metadata")
/* Sanity check */
@@ -766,7 +769,7 @@ HDfprintf(stderr, "%s: Index block address is: %a\n", FUNC, hdr->idx_blk_addr);
hdr->f = ea->f;
/* Look up the array metadata containing the element we want to set */
- if(H5EA__lookup_elmt(ea, dxpl_id, idx, H5AC_READ, &thing, &thing_elmt_buf, &thing_elmt_idx, &thing_unprot_func) < 0)
+ if(H5EA__lookup_elmt(ea, dxpl_id, idx, H5AC__READ_ONLY_FLAG, &thing, &thing_elmt_buf, &thing_elmt_idx, &thing_unprot_func) < 0)
H5E_THROW(H5E_CANTPROTECT, "unable to protect array metadata")
/* Check if the thing holding the element has been created yet */
@@ -873,7 +876,6 @@ CATCH
END_FUNC(PRIV) /* end H5EA_undepend() */
-
/*-------------------------------------------------------------------------
* Function: H5EA_close
@@ -943,7 +945,7 @@ HDfprintf(stderr, "%s: Called\n", FUNC);
/* Lock the array header into memory */
/* (OK to pass in NULL for callback context, since we know the header must be in the cache) */
- if(NULL == (hdr = H5EA__hdr_protect(ea->f, dxpl_id, ea_addr, NULL, H5AC_WRITE)))
+ if(NULL == (hdr = H5EA__hdr_protect(ea->f, dxpl_id, ea_addr, NULL, H5AC__NO_FLAGS_SET)))
H5E_THROW(H5E_CANTLOAD, "unable to load extensible array header")
/* Set the shared array header's file context for this operation */
@@ -1007,7 +1009,7 @@ H5EA_delete(H5F_t *f, hid_t dxpl_id, haddr_t ea_addr, void *ctx_udata))
#ifdef QAK
HDfprintf(stderr, "%s: ea_addr = %a\n", FUNC, ea_addr);
#endif /* QAK */
- if(NULL == (hdr = H5EA__hdr_protect(f, dxpl_id, ea_addr, ctx_udata, H5AC_WRITE)))
+ if(NULL == (hdr = H5EA__hdr_protect(f, dxpl_id, ea_addr, ctx_udata, H5AC__NO_FLAGS_SET)))
H5E_THROW(H5E_CANTPROTECT, "unable to protect extensible array header, address = %llu", (unsigned long long)ea_addr)
/* Check for files using shared array header */
diff --git a/src/H5EAcache.c b/src/H5EAcache.c
index 3363701..ba7ee5d 100644
--- a/src/H5EAcache.c
+++ b/src/H5EAcache.c
@@ -57,13 +57,6 @@
#define H5EA_SBLOCK_VERSION 0 /* Super block */
#define H5EA_DBLOCK_VERSION 0 /* Data block */
-/* Size of stack buffer for serialization buffers */
-#define H5EA_HDR_BUF_SIZE 512
-#define H5EA_IBLOCK_BUF_SIZE 512
-#define H5EA_SBLOCK_BUF_SIZE 512
-#define H5EA_DBLOCK_BUF_SIZE 512
-#define H5EA_DBLK_PAGE_BUF_SIZE 512
-
/******************/
/* Local Typedefs */
@@ -80,35 +73,74 @@
/********************/
/* Metadata cache (H5AC) callbacks */
-static H5EA_hdr_t *H5EA__cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata);
-static herr_t H5EA__cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5EA_hdr_t *hdr, unsigned * flags_ptr);
-static herr_t H5EA__cache_hdr_clear(H5F_t *f, H5EA_hdr_t *hdr, hbool_t destroy);
-static herr_t H5EA__cache_hdr_size(const H5F_t *f, const H5EA_hdr_t *hdr, size_t *size_ptr);
-static herr_t H5EA__cache_hdr_dest(H5F_t *f, H5EA_hdr_t *hdr);
-static H5EA_iblock_t *H5EA__cache_iblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata);
-static herr_t H5EA__cache_iblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5EA_iblock_t *iblock, unsigned * flags_ptr);
-static herr_t H5EA__cache_iblock_clear(H5F_t *f, H5EA_iblock_t *iblock, hbool_t destroy);
-static herr_t H5EA__cache_iblock_notify(H5AC_notify_action_t action, H5EA_iblock_t *iblock);
-static herr_t H5EA__cache_iblock_size(const H5F_t *f, const H5EA_iblock_t *iblock, size_t *size_ptr);
-static herr_t H5EA__cache_iblock_dest(H5F_t *f, H5EA_iblock_t *iblock);
-static H5EA_sblock_t *H5EA__cache_sblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata);
-static herr_t H5EA__cache_sblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5EA_sblock_t *sblock, unsigned * flags_ptr);
-static herr_t H5EA__cache_sblock_clear(H5F_t *f, H5EA_sblock_t *sblock, hbool_t destroy);
-static herr_t H5EA__cache_sblock_size(const H5F_t *f, const H5EA_sblock_t *sblock, size_t *size_ptr);
-static herr_t H5EA__cache_sblock_notify(H5AC_notify_action_t action, H5EA_sblock_t *sblock);
-static herr_t H5EA__cache_sblock_dest(H5F_t *f, H5EA_sblock_t *sblock);
-static H5EA_dblock_t *H5EA__cache_dblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata);
-static herr_t H5EA__cache_dblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5EA_dblock_t *dblock, unsigned * flags_ptr);
-static herr_t H5EA__cache_dblock_clear(H5F_t *f, H5EA_dblock_t *dblock, hbool_t destroy);
-static herr_t H5EA__cache_dblock_size(const H5F_t *f, const H5EA_dblock_t *dblock, size_t *size_ptr);
-static herr_t H5EA__cache_dblock_notify(H5AC_notify_action_t action, H5EA_dblock_t *dblock);
-static herr_t H5EA__cache_dblock_dest(H5F_t *f, H5EA_dblock_t *dblock);
-static H5EA_dblk_page_t *H5EA__cache_dblk_page_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata);
-static herr_t H5EA__cache_dblk_page_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5EA_dblk_page_t *dblk_page, unsigned * flags_ptr);
-static herr_t H5EA__cache_dblk_page_clear(H5F_t *f, H5EA_dblk_page_t *dblk_page, hbool_t destroy);
-static herr_t H5EA__cache_dblk_page_size(const H5F_t *f, const H5EA_dblk_page_t *dblk_page, size_t *size_ptr);
-static herr_t H5EA__cache_dblk_page_notify(H5AC_notify_action_t action, H5EA_dblk_page_t *dblk_page);
-static herr_t H5EA__cache_dblk_page_dest(H5F_t *f, H5EA_dblk_page_t *dblk_page);
+static herr_t H5EA__cache_hdr_get_load_size(const void *image, void *udata,
+ size_t *image_len, size_t *actual_len,
+ hbool_t *compressed_ptr, size_t *compressed_image_len_ptr);
+static htri_t H5EA__cache_hdr_verify_chksum(const void *image_ptr, size_t len, void *udata_ptr);
+static void *H5EA__cache_hdr_deserialize(const void *image, size_t len,
+ void *udata, hbool_t *dirty);
+static herr_t H5EA__cache_hdr_image_len(const void *thing, size_t *image_len,
+ hbool_t *compressed_ptr, size_t *compressed_image_len_ptr);
+static herr_t H5EA__cache_hdr_serialize(const H5F_t *f, void *image, size_t len,
+ void *thing);
+static herr_t H5EA__cache_hdr_free_icr(void *thing);
+
+static herr_t H5EA__cache_iblock_get_load_size(const void *image, void *udata,
+ size_t *image_len, size_t *actual_len,
+ hbool_t *compressed_ptr, size_t *compressed_image_len_ptr);
+static htri_t H5EA__cache_iblock_verify_chksum(const void *image_ptr, size_t len, void *udata_ptr);
+static void *H5EA__cache_iblock_deserialize(const void *image, size_t len,
+ void *udata, hbool_t *dirty);
+static herr_t H5EA__cache_iblock_image_len(const void *thing,
+ size_t *image_len, hbool_t *compressed_ptr,
+ size_t *compressed_image_len_ptr);
+static herr_t H5EA__cache_iblock_serialize(const H5F_t *f, void *image, size_t len,
+ void *thing);
+static herr_t H5EA__cache_iblock_notify(H5AC_notify_action_t action, void *thing);
+static herr_t H5EA__cache_iblock_free_icr(void *thing);
+
+static herr_t H5EA__cache_sblock_get_load_size(const void *image, void *udata,
+ size_t *image_len, size_t *actual_len,
+ hbool_t *compressed_ptr, size_t *compressed_image_len_ptr);
+static htri_t H5EA__cache_sblock_verify_chksum(const void *image_ptr, size_t len, void *udata_ptr);
+static void *H5EA__cache_sblock_deserialize(const void *image, size_t len,
+ void *udata, hbool_t *dirty);
+static herr_t H5EA__cache_sblock_image_len(const void *thing,
+ size_t *image_len, hbool_t *compressed_ptr,
+ size_t *compressed_image_len_ptr);
+static herr_t H5EA__cache_sblock_serialize(const H5F_t *f, void *image, size_t len,
+ void *thing);
+static herr_t H5EA__cache_sblock_notify(H5AC_notify_action_t action, void *thing);
+static herr_t H5EA__cache_sblock_free_icr(void *thing);
+
+static herr_t H5EA__cache_dblock_get_load_size(const void *image, void *udata,
+ size_t *image_len, size_t *actual_len,
+ hbool_t *compressed_ptr, size_t *compressed_image_len_ptr);
+static htri_t H5EA__cache_dblock_verify_chksum(const void *image_ptr, size_t len, void *udata_ptr);
+static void *H5EA__cache_dblock_deserialize(const void *image, size_t len,
+ void *udata, hbool_t *dirty);
+static herr_t H5EA__cache_dblock_image_len(const void *thing,
+ size_t *image_len, hbool_t *compressed_ptr,
+ size_t *compressed_image_len_ptr);
+static herr_t H5EA__cache_dblock_serialize(const H5F_t *f, void *image, size_t len,
+ void *thing);
+static herr_t H5EA__cache_dblock_notify(H5AC_notify_action_t action, void *thing);
+static herr_t H5EA__cache_dblock_free_icr(void *thing);
+static herr_t H5EA__cache_dblock_fsf_size(const void *thing, size_t *fsf_size);
+
+static herr_t H5EA__cache_dblk_page_get_load_size(const void *image, void *udata,
+ size_t *image_len, size_t *actual_len,
+ hbool_t *compressed_ptr, size_t *compressed_image_len_ptr);
+static htri_t H5EA__cache_dblk_page_verify_chksum(const void *image_ptr, size_t len, void *udata_ptr);
+static void *H5EA__cache_dblk_page_deserialize(const void *image, size_t len,
+ void *udata, hbool_t *dirty);
+static herr_t H5EA__cache_dblk_page_image_len(const void *thing,
+ size_t *image_len, hbool_t *compressed_ptr,
+ size_t *compressed_image_len_ptr);
+static herr_t H5EA__cache_dblk_page_serialize(const H5F_t *f, void *image, size_t len,
+ void *thing);
+static herr_t H5EA__cache_dblk_page_notify(H5AC_notify_action_t action, void *thing);
+static herr_t H5EA__cache_dblk_page_free_icr(void *thing);
/*********************/
@@ -117,57 +149,92 @@ static herr_t H5EA__cache_dblk_page_dest(H5F_t *f, H5EA_dblk_page_t *dblk_page);
/* H5EA header inherits cache-like properties from H5AC */
const H5AC_class_t H5AC_EARRAY_HDR[1] = {{
- H5AC_EARRAY_HDR_ID,
- (H5AC_load_func_t)H5EA__cache_hdr_load,
- (H5AC_flush_func_t)H5EA__cache_hdr_flush,
- (H5AC_dest_func_t)H5EA__cache_hdr_dest,
- (H5AC_clear_func_t)H5EA__cache_hdr_clear,
- (H5AC_notify_func_t)NULL,
- (H5AC_size_func_t)H5EA__cache_hdr_size,
+ H5AC_EARRAY_HDR_ID, /* Metadata client ID */
+ "Extensible Array Header", /* Metadata client name (for debugging) */
+ H5FD_MEM_EARRAY_HDR, /* File space memory type for client */
+ H5AC__CLASS_NO_FLAGS_SET, /* Client class behavior flags */
+ H5EA__cache_hdr_get_load_size, /* 'get_load_size' callback */
+ H5EA__cache_hdr_verify_chksum, /* 'verify_chksum' callback */
+ H5EA__cache_hdr_deserialize, /* 'deserialize' callback */
+ H5EA__cache_hdr_image_len, /* 'image_len' callback */
+ NULL, /* 'pre_serialize' callback */
+ H5EA__cache_hdr_serialize, /* 'serialize' callback */
+ NULL, /* 'notify' callback */
+ H5EA__cache_hdr_free_icr, /* 'free_icr' callback */
+ NULL, /* 'clear' callback */
+ NULL, /* 'fsf_size' callback */
}};
/* H5EA index block inherits cache-like properties from H5AC */
const H5AC_class_t H5AC_EARRAY_IBLOCK[1] = {{
- H5AC_EARRAY_IBLOCK_ID,
- (H5AC_load_func_t)H5EA__cache_iblock_load,
- (H5AC_flush_func_t)H5EA__cache_iblock_flush,
- (H5AC_dest_func_t)H5EA__cache_iblock_dest,
- (H5AC_clear_func_t)H5EA__cache_iblock_clear,
- (H5AC_notify_func_t)H5EA__cache_iblock_notify,
- (H5AC_size_func_t)H5EA__cache_iblock_size,
+ H5AC_EARRAY_IBLOCK_ID, /* Metadata client ID */
+ "Extensible Array Index Block", /* Metadata client name (for debugging) */
+ H5FD_MEM_EARRAY_IBLOCK, /* File space memory type for client */
+ H5AC__CLASS_NO_FLAGS_SET, /* Client class behavior flags */
+ H5EA__cache_iblock_get_load_size, /* 'get_load_size' callback */
+ H5EA__cache_iblock_verify_chksum, /* 'verify_chksum' callback */
+ H5EA__cache_iblock_deserialize, /* 'deserialize' callback */
+ H5EA__cache_iblock_image_len, /* 'image_len' callback */
+ NULL, /* 'pre_serialize' callback */
+ H5EA__cache_iblock_serialize, /* 'serialize' callback */
+ H5EA__cache_iblock_notify, /* 'notify' callback */
+ H5EA__cache_iblock_free_icr, /* 'free_icr' callback */
+ NULL, /* 'clear' callback */
+ NULL, /* 'fsf_size' callback */
}};
/* H5EA super block inherits cache-like properties from H5AC */
const H5AC_class_t H5AC_EARRAY_SBLOCK[1] = {{
- H5AC_EARRAY_SBLOCK_ID,
- (H5AC_load_func_t)H5EA__cache_sblock_load,
- (H5AC_flush_func_t)H5EA__cache_sblock_flush,
- (H5AC_dest_func_t)H5EA__cache_sblock_dest,
- (H5AC_clear_func_t)H5EA__cache_sblock_clear,
- (H5AC_notify_func_t)H5EA__cache_sblock_notify,
- (H5AC_size_func_t)H5EA__cache_sblock_size,
+ H5AC_EARRAY_SBLOCK_ID, /* Metadata client ID */
+ "Extensible Array Super Block", /* Metadata client name (for debugging) */
+ H5FD_MEM_EARRAY_SBLOCK, /* File space memory type for client */
+ H5AC__CLASS_NO_FLAGS_SET, /* Client class behavior flags */
+ H5EA__cache_sblock_get_load_size, /* 'get_load_size' callback */
+ H5EA__cache_sblock_verify_chksum, /* 'verify_chksum' callback */
+ H5EA__cache_sblock_deserialize, /* 'deserialize' callback */
+ H5EA__cache_sblock_image_len, /* 'image_len' callback */
+ NULL, /* 'pre_serialize' callback */
+ H5EA__cache_sblock_serialize, /* 'serialize' callback */
+ H5EA__cache_sblock_notify, /* 'notify' callback */
+ H5EA__cache_sblock_free_icr, /* 'free_icr' callback */
+ NULL, /* 'clear' callback */
+ NULL, /* 'fsf_size' callback */
}};
/* H5EA data block inherits cache-like properties from H5AC */
const H5AC_class_t H5AC_EARRAY_DBLOCK[1] = {{
- H5AC_EARRAY_DBLOCK_ID,
- (H5AC_load_func_t)H5EA__cache_dblock_load,
- (H5AC_flush_func_t)H5EA__cache_dblock_flush,
- (H5AC_dest_func_t)H5EA__cache_dblock_dest,
- (H5AC_clear_func_t)H5EA__cache_dblock_clear,
- (H5AC_notify_func_t)H5EA__cache_dblock_notify,
- (H5AC_size_func_t)H5EA__cache_dblock_size,
+ H5AC_EARRAY_DBLOCK_ID, /* Metadata client ID */
+ "Extensible Array Data Block", /* Metadata client name (for debugging) */
+ H5FD_MEM_EARRAY_DBLOCK, /* File space memory type for client */
+ H5AC__CLASS_NO_FLAGS_SET, /* Client class behavior flags */
+ H5EA__cache_dblock_get_load_size, /* 'get_load_size' callback */
+ H5EA__cache_dblock_verify_chksum, /* 'verify_chksum' callback */
+ H5EA__cache_dblock_deserialize, /* 'deserialize' callback */
+ H5EA__cache_dblock_image_len, /* 'image_len' callback */
+ NULL, /* 'pre_serialize' callback */
+ H5EA__cache_dblock_serialize, /* 'serialize' callback */
+ H5EA__cache_dblock_notify, /* 'notify' callback */
+ H5EA__cache_dblock_free_icr, /* 'free_icr' callback */
+ NULL, /* 'clear' callback */
+ H5EA__cache_dblock_fsf_size, /* 'fsf_size' callback */
}};
/* H5EA data block page inherits cache-like properties from H5AC */
const H5AC_class_t H5AC_EARRAY_DBLK_PAGE[1] = {{
- H5AC_EARRAY_DBLK_PAGE_ID,
- (H5AC_load_func_t)H5EA__cache_dblk_page_load,
- (H5AC_flush_func_t)H5EA__cache_dblk_page_flush,
- (H5AC_dest_func_t)H5EA__cache_dblk_page_dest,
- (H5AC_clear_func_t)H5EA__cache_dblk_page_clear,
- (H5AC_notify_func_t)H5EA__cache_dblk_page_notify,
- (H5AC_size_func_t)H5EA__cache_dblk_page_size,
+ H5AC_EARRAY_DBLK_PAGE_ID, /* Metadata client ID */
+ "Extensible Array Data Block Page", /* Metadata client name (for debugging) */
+ H5FD_MEM_EARRAY_DBLK_PAGE, /* File space memory type for client */
+ H5AC__CLASS_NO_FLAGS_SET, /* Client class behavior flags */
+ H5EA__cache_dblk_page_get_load_size, /* 'get_load_size' callback */
+ H5EA__cache_dblk_page_verify_chksum, /* 'verify_chksum' callback */
+ H5EA__cache_dblk_page_deserialize, /* 'deserialize' callback */
+ H5EA__cache_dblk_page_image_len, /* 'image_len' callback */
+ NULL, /* 'pre_serialize' callback */
+ H5EA__cache_dblk_page_serialize, /* 'serialize' callback */
+ H5EA__cache_dblk_page_notify, /* 'notify' callback */
+ H5EA__cache_dblk_page_free_icr, /* 'free_icr' callback */
+ NULL, /* 'clear' callback */
+ NULL, /* 'fsf_size' callback */
}};
@@ -183,95 +250,150 @@ const H5AC_class_t H5AC_EARRAY_DBLK_PAGE[1] = {{
/*-------------------------------------------------------------------------
- * Function: H5EA__cache_hdr_load
+ * Function: H5EA__cache_hdr_get_load_size
+ *
+ * Purpose: Compute the size of the data structure on disk.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * July 16, 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(STATIC, NOERR,
+herr_t, SUCCEED, -,
+H5EA__cache_hdr_get_load_size(const void *_image, void *_udata, size_t *image_len, size_t *actual_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr))
+
+ /* Local variables */
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ H5EA_hdr_cache_ud_t *udata = (H5EA_hdr_cache_ud_t *)_udata; /* User data for callback */
+
+ /* Check arguments */
+ HDassert(udata);
+ HDassert(udata->f);
+ HDassert(image_len);
+
+ if(image == NULL) {
+ /* Set the image length size */
+ *image_len = (size_t)H5EA_HEADER_SIZE_FILE(udata->f);
+ } else {
+ HDassert(actual_len);
+ HDassert(*actual_len == *image_len);
+ }
+
+END_FUNC(STATIC) /* end H5EA__cache_hdr_get_load_size() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__cache_hdr_verify_chksum
+ *
+ * Purpose: Verify the computed checksum of the data structure is the
+ * same as the stored chksum.
*
- * Purpose: Loads an extensible array header from the disk.
+ * Return: Success: TRUE/FALSE
+ * Failure: Negative
*
- * Return: Success: Pointer to a new extensible array
+ * Programmer: Vailin Choi; Aug 2015
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(STATIC, NOERR,
+htri_t, TRUE, -,
+H5EA__cache_hdr_verify_chksum(const void *_image, size_t len, void H5_ATTR_UNUSED *_udata))
+
+ /* Local variables */
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ uint32_t stored_chksum; /* Stored metadata checksum value */
+ uint32_t computed_chksum; /* Computed metadata checksum value */
+
+ /* Check arguments */
+ HDassert(image);
+
+ /* Get stored and computed checksums */
+ H5F_get_checksums(image, len, &stored_chksum, &computed_chksum);
+
+ if(stored_chksum != computed_chksum)
+ ret_value = FALSE;
+
+END_FUNC(STATIC) /* end H5EA__cache_hdr_verify_chksum() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__cache_hdr_deserialize
+ *
+ * Purpose: Loads a data structure from the disk.
+ *
+ * Return: Success: Pointer to a new B-tree.
* Failure: NULL
*
* Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * Aug 26 2008
+ * koziol@hdfgroup.org
+ * July 16, 2013
*
*-------------------------------------------------------------------------
*/
BEGIN_FUNC(STATIC, ERR,
-H5EA_hdr_t *, NULL, NULL,
-H5EA__cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata))
+void *, NULL, NULL,
+H5EA__cache_hdr_deserialize(const void *_image, size_t len, void *_udata,
+ hbool_t H5_ATTR_UNUSED *dirty))
/* Local variables */
H5EA_cls_id_t id; /* ID of extensible array class, as found in file */
H5EA_hdr_t *hdr = NULL; /* Extensible array info */
- size_t size; /* Header size */
- H5WB_t *wb = NULL; /* Wrapped buffer for header data */
- uint8_t hdr_buf[H5EA_HDR_BUF_SIZE]; /* Buffer for header */
- uint8_t *buf; /* Pointer to header buffer */
- const uint8_t *p; /* Pointer into raw data buffer */
+ H5EA_hdr_cache_ud_t *udata = (H5EA_hdr_cache_ud_t *)_udata;
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ uint32_t stored_chksum; /* Stored metadata checksum value */
/* Check arguments */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
+ HDassert(image);
+ HDassert(udata);
+ HDassert(udata->f);
+ HDassert(H5F_addr_defined(udata->addr));
/* Allocate space for the extensible array data structure */
- if(NULL == (hdr = H5EA__hdr_alloc(f)))
+ if(NULL == (hdr = H5EA__hdr_alloc(udata->f)))
H5E_THROW(H5E_CANTALLOC, "memory allocation failed for extensible array shared header")
/* Set the extensible array header's address */
- hdr->addr = addr;
-
- /* Wrap the local buffer for serialized info */
- if(NULL == (wb = H5WB_wrap(hdr_buf, sizeof(hdr_buf))))
- H5E_THROW(H5E_CANTINIT, "can't wrap buffer")
-
- /* Compute the 'base' size of the extensible array header on disk */
- size = H5EA_HEADER_SIZE_HDR(hdr);
-
- /* Get a pointer to a buffer that's large enough for serialized header */
- if(NULL == (buf = (uint8_t *)H5WB_actual(wb, size)))
- H5E_THROW(H5E_CANTGET, "can't get actual buffer")
-
- /* Read and validate header from disk */
- if(H5F_read_check_metadata(f, dxpl_id, H5FD_MEM_EARRAY_HDR, H5AC_EARRAY_HDR_ID, addr, size, size, buf) < 0)
- H5E_THROW(H5E_BADVALUE, "incorrect metadata checksum for extensible array header")
-
- /* Get temporary pointer to serialized header */
- p = buf;
+ hdr->addr = udata->addr;
/* Magic number */
- if(HDmemcmp(p, H5EA_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC))
+ if(HDmemcmp(image, H5EA_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC))
H5E_THROW(H5E_BADVALUE, "wrong extensible array header signature")
- p += H5_SIZEOF_MAGIC;
+ image += H5_SIZEOF_MAGIC;
/* Version */
- if(*p++ != H5EA_HDR_VERSION)
+ if(*image++ != H5EA_HDR_VERSION)
H5E_THROW(H5E_VERSION, "wrong extensible array header version")
/* Extensible array class */
- id = (H5EA_cls_id_t)*p++;
+ id = (H5EA_cls_id_t)*image++;
if(id >= H5EA_NUM_CLS_ID)
H5E_THROW(H5E_BADTYPE, "incorrect extensible array class")
hdr->cparam.cls = H5EA_client_class_g[id];
/* General array creation/configuration information */
- hdr->cparam.raw_elmt_size = *p++; /* Element size in file (in bytes) */
- hdr->cparam.max_nelmts_bits = *p++; /* Log2(Max. # of elements in array) - i.e. # of bits needed to store max. # of elements */
- hdr->cparam.idx_blk_elmts = *p++; /* # of elements to store in index block */
- hdr->cparam.data_blk_min_elmts = *p++; /* Min. # of elements per data block */
- hdr->cparam.sup_blk_min_data_ptrs = *p++; /* Min. # of data block pointers for a super block */
- hdr->cparam.max_dblk_page_nelmts_bits = *p++; /* Log2(Max. # of elements in data block page) - i.e. # of bits needed to store max. # of elements in data block page */
+ hdr->cparam.raw_elmt_size = *image++; /* Element size in file (in bytes) */
+ hdr->cparam.max_nelmts_bits = *image++; /* Log2(Max. # of elements in array) - i.e. # of bits needed to store max. # of elements */
+ hdr->cparam.idx_blk_elmts = *image++; /* # of elements to store in index block */
+ hdr->cparam.data_blk_min_elmts = *image++; /* Min. # of elements per data block */
+ hdr->cparam.sup_blk_min_data_ptrs = *image++; /* Min. # of data block pointers for a super block */
+ hdr->cparam.max_dblk_page_nelmts_bits = *image++; /* Log2(Max. # of elements in data block page) - i.e. # of bits needed to store max. # of elements in data block page */
/* Array statistics */
- hdr->stats.computed.hdr_size = size; /* Size of header in file */
- H5F_DECODE_LENGTH(f, p, hdr->stats.stored.nsuper_blks); /* Number of super blocks created */
- H5F_DECODE_LENGTH(f, p, hdr->stats.stored.super_blk_size); /* Size of super blocks created */
- H5F_DECODE_LENGTH(f, p, hdr->stats.stored.ndata_blks); /* Number of data blocks created */
- H5F_DECODE_LENGTH(f, p, hdr->stats.stored.data_blk_size); /* Size of data blocks created */
- H5F_DECODE_LENGTH(f, p, hdr->stats.stored.max_idx_set); /* Max. index set (+1) */
- H5F_DECODE_LENGTH(f, p, hdr->stats.stored.nelmts); /* Number of elements 'realized' */
+ hdr->stats.computed.hdr_size = len; /* Size of header in file */
+ H5F_DECODE_LENGTH(udata->f, image, hdr->stats.stored.nsuper_blks); /* Number of super blocks created */
+ H5F_DECODE_LENGTH(udata->f, image, hdr->stats.stored.super_blk_size); /* Size of super blocks created */
+ H5F_DECODE_LENGTH(udata->f, image, hdr->stats.stored.ndata_blks); /* Number of data blocks created */
+ H5F_DECODE_LENGTH(udata->f, image, hdr->stats.stored.data_blk_size); /* Size of data blocks created */
+ H5F_DECODE_LENGTH(udata->f, image, hdr->stats.stored.max_idx_set); /* Max. index set (+1) */
+ H5F_DECODE_LENGTH(udata->f, image, hdr->stats.stored.nelmts); /* Number of elements 'realized' */
/* Internal information */
- H5F_addr_decode(f, &p, &hdr->idx_blk_addr); /* Address of index block */
+ H5F_addr_decode(udata->f, &image, &hdr->idx_blk_addr); /* Address of index block */
/* Index block statistics */
if(H5F_addr_defined(hdr->idx_blk_addr)) {
@@ -296,17 +418,20 @@ H5EA__cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata))
/* Sanity check */
/* (allow for checksum not decoded yet) */
- HDassert((size_t)(p - buf) == (size - H5EA_SIZEOF_CHKSUM));
+ HDassert((size_t)(image - (const uint8_t *)_image) == (len - H5EA_SIZEOF_CHKSUM));
- /* Already decoded and compared stored checksum earlier, when reading */
+ /* checksum verification already done in verify_chksum cb */
+
+ /* Metadata checksum */
+ UINT32DECODE(image, stored_chksum);
/* Sanity check */
- HDassert((size_t)(p - buf) == (size - H5_SIZEOF_CHKSUM));
+ HDassert((size_t)(image - (const uint8_t *)_image) == len);
/* Finish initializing extensible array header */
- if(H5EA__hdr_init(hdr, udata) < 0)
+ if(H5EA__hdr_init(hdr, udata->ctx_udata) < 0)
H5E_THROW(H5E_CANTINIT, "initialization failed for extensible array header")
- HDassert(hdr->size == size);
+ HDassert(hdr->size == len);
/* Set return value */
ret_value = hdr;
@@ -314,261 +439,251 @@ H5EA__cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata))
CATCH
/* Release resources */
- if(wb && H5WB_unwrap(wb) < 0)
- H5E_THROW(H5E_CLOSEERROR, "can't close wrapped buffer")
if(!ret_value)
if(hdr && H5EA__hdr_dest(hdr) < 0)
H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array header")
-END_FUNC(STATIC) /* end H5EA__cache_hdr_load() */
+END_FUNC(STATIC) /* end H5EA__cache_hdr_deserialize() */
/*-------------------------------------------------------------------------
- * Function: H5EA__cache_hdr_flush
+ * Function: H5EA__cache_hdr_image_len
*
- * Purpose: Flushes a dirty extensible array header to disk.
+ * Purpose: Compute the size of the data structure on disk.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * Aug 26 2008
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * July 16, 2013
*
*-------------------------------------------------------------------------
*/
-BEGIN_FUNC(STATIC, ERR,
-herr_t, SUCCEED, FAIL,
-H5EA__cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr,
- H5EA_hdr_t *hdr, unsigned H5_ATTR_UNUSED * flags_ptr))
+BEGIN_FUNC(STATIC, NOERR,
+herr_t, SUCCEED, -,
+H5EA__cache_hdr_image_len(const void *_thing, size_t *image_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr))
- H5WB_t *wb = NULL; /* Wrapped buffer for header data */
- uint8_t hdr_buf[H5EA_HDR_BUF_SIZE]; /* Buffer for header */
+ /* Local variables */
+ const H5EA_hdr_t *hdr = (const H5EA_hdr_t *)_thing; /* Pointer to the object */
- /* check arguments */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
+ /* Check arguments */
HDassert(hdr);
+ HDassert(image_len);
- if(hdr->cache_info.is_dirty) {
- uint8_t *buf; /* Temporary raw data buffer */
- uint8_t *p; /* Pointer into raw data buffer */
- size_t size; /* Header size on disk */
- uint32_t metadata_chksum; /* Computed metadata checksum value */
-
- /* Wrap the local buffer for serialized header info */
- if(NULL == (wb = H5WB_wrap(hdr_buf, sizeof(hdr_buf))))
- H5E_THROW(H5E_CANTINIT, "can't wrap buffer")
-
- /* Compute the size of the array header on disk */
- size = hdr->size;
+ /* Set the image length size */
+ *image_len = hdr->size;
- /* Get a pointer to a buffer that's large enough for serialized header */
- if(NULL == (buf = (uint8_t *)H5WB_actual(wb, size)))
- H5E_THROW(H5E_CANTGET, "can't get actual buffer")
+END_FUNC(STATIC) /* end H5EA__cache_hdr_image_len() */
- /* Get temporary pointer to serialized header */
- p = buf;
-
- /* Magic number */
- HDmemcpy(p, H5EA_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC);
- p += H5_SIZEOF_MAGIC;
-
- /* Version # */
- *p++ = H5EA_HDR_VERSION;
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__cache_hdr_serialize
+ *
+ * Purpose: Flushes a dirty object to disk.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * July 16, 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(STATIC, NOERR,
+herr_t, SUCCEED, -,
+H5EA__cache_hdr_serialize(const H5F_t *f, void *_image, size_t H5_ATTR_UNUSED len,
+ void *_thing))
- /* Extensible array type */
- *p++ = hdr->cparam.cls->id;
+ /* Local variables */
+ H5EA_hdr_t *hdr = (H5EA_hdr_t *)_thing; /* Pointer to the extensible array header */
+ uint8_t *image = (uint8_t *)_image; /* Pointer into raw data buffer */
+ uint32_t metadata_chksum; /* Computed metadata checksum value */
- /* General array creation/configuration information */
- *p++ = hdr->cparam.raw_elmt_size; /* Element size in file (in bytes) */
- *p++ = hdr->cparam.max_nelmts_bits; /* Log2(Max. # of elements in array) - i.e. # of bits needed to store max. # of elements */
- *p++ = hdr->cparam.idx_blk_elmts; /* # of elements to store in index block */
- *p++ = hdr->cparam.data_blk_min_elmts; /* Min. # of elements per data block */
- *p++ = hdr->cparam.sup_blk_min_data_ptrs; /* Min. # of data block pointers for a super block */
- *p++ = hdr->cparam.max_dblk_page_nelmts_bits; /* Log2(Max. # of elements in data block page) - i.e. # of bits needed to store max. # of elements in data block page */
+ /* check arguments */
+ HDassert(f);
+ HDassert(image);
+ HDassert(hdr);
- /* Array statistics */
- H5F_ENCODE_LENGTH(f, p, hdr->stats.stored.nsuper_blks); /* Number of super blocks created */
- H5F_ENCODE_LENGTH(f, p, hdr->stats.stored.super_blk_size); /* Size of super blocks created */
- H5F_ENCODE_LENGTH(f, p, hdr->stats.stored.ndata_blks); /* Number of data blocks created */
- H5F_ENCODE_LENGTH(f, p, hdr->stats.stored.data_blk_size); /* Size of data blocks created */
- H5F_ENCODE_LENGTH(f, p, hdr->stats.stored.max_idx_set); /* Max. index set (+1) */
- H5F_ENCODE_LENGTH(f, p, hdr->stats.stored.nelmts); /* Number of elements 'realized' */
+ /* Magic number */
+ HDmemcpy(image, H5EA_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ image += H5_SIZEOF_MAGIC;
- /* Internal information */
- H5F_addr_encode(f, &p, hdr->idx_blk_addr); /* Address of index block */
+ /* Version # */
+ *image++ = H5EA_HDR_VERSION;
- /* Compute metadata checksum */
- metadata_chksum = H5_checksum_metadata(buf, (size_t)(p - buf), 0);
+ /* Extensible array type */
+ *image++ = hdr->cparam.cls->id;
- /* Metadata checksum */
- UINT32ENCODE(p, metadata_chksum);
+ /* General array creation/configuration information */
+ *image++ = hdr->cparam.raw_elmt_size; /* Element size in file (in bytes) */
+ *image++ = hdr->cparam.max_nelmts_bits; /* Log2(Max. # of elements in array) - i.e. # of bits needed to store max. # of elements */
+ *image++ = hdr->cparam.idx_blk_elmts; /* # of elements to store in index block */
+ *image++ = hdr->cparam.data_blk_min_elmts; /* Min. # of elements per data block */
+ *image++ = hdr->cparam.sup_blk_min_data_ptrs; /* Min. # of data block pointers for a super block */
+ *image++ = hdr->cparam.max_dblk_page_nelmts_bits; /* Log2(Max. # of elements in data block page) - i.e. # of bits needed to store max. # of elements in data block page */
- /* Write the array header. */
- HDassert((size_t)(p - buf) == size);
- if(H5F_block_write(f, H5FD_MEM_EARRAY_HDR, addr, size, dxpl_id, buf) < 0)
- H5E_THROW(H5E_WRITEERROR, "unable to save extensible array header to disk")
+ /* Array statistics */
+ H5F_ENCODE_LENGTH(f, image, hdr->stats.stored.nsuper_blks); /* Number of super blocks created */
+ H5F_ENCODE_LENGTH(f, image, hdr->stats.stored.super_blk_size); /* Size of super blocks created */
+ H5F_ENCODE_LENGTH(f, image, hdr->stats.stored.ndata_blks); /* Number of data blocks created */
+ H5F_ENCODE_LENGTH(f, image, hdr->stats.stored.data_blk_size); /* Size of data blocks created */
+ H5F_ENCODE_LENGTH(f, image, hdr->stats.stored.max_idx_set); /* Max. index set (+1) */
+ H5F_ENCODE_LENGTH(f, image, hdr->stats.stored.nelmts); /* Number of elements 'realized' */
- hdr->cache_info.is_dirty = FALSE;
- } /* end if */
+ /* Internal information */
+ H5F_addr_encode(f, &image, hdr->idx_blk_addr); /* Address of index block */
- if(destroy)
- if(H5EA__cache_hdr_dest(f, hdr) < 0)
- H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array header")
+ /* Compute metadata checksum */
+ metadata_chksum = H5_checksum_metadata(_image, (size_t)(image - (uint8_t *)_image), 0);
-CATCH
+ /* Metadata checksum */
+ UINT32ENCODE(image, metadata_chksum);
- /* Release resources */
- if(wb && H5WB_unwrap(wb) < 0)
- H5E_THROW(H5E_CLOSEERROR, "can't close wrapped buffer")
+ /* Sanity check */
+ HDassert((size_t)(image - (uint8_t *)_image) <= len);
-END_FUNC(STATIC) /* end H5EA__cache_hdr_flush() */
+END_FUNC(STATIC) /* end H5EA__cache_hdr_serialize() */
/*-------------------------------------------------------------------------
- * Function: H5EA__cache_hdr_clear
+ * Function: H5EA__cache_hdr_free_icr
*
- * Purpose: Mark a extensible array header in memory as non-dirty.
+ * Purpose: Destroy/release an "in core representation" of a data
+ * structure
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * Aug 26 2008
+ * koziol@hdfgroup.org
+ * July 16, 2013
*
*-------------------------------------------------------------------------
*/
BEGIN_FUNC(STATIC, ERR,
herr_t, SUCCEED, FAIL,
-H5EA__cache_hdr_clear(H5F_t *f, H5EA_hdr_t *hdr, hbool_t destroy))
+H5EA__cache_hdr_free_icr(void *thing))
- /* Sanity check */
- HDassert(hdr);
-
- /* Reset the dirty flag. */
- hdr->cache_info.is_dirty = FALSE;
+ /* Check arguments */
+ HDassert(thing);
- if(destroy)
- if(H5EA__cache_hdr_dest(f, hdr) < 0)
- H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array header")
+ /* Release the extensible array header */
+ if(H5EA__hdr_dest((H5EA_hdr_t *)thing) < 0)
+ H5E_THROW(H5E_CANTFREE, "can't free extensible array header")
CATCH
-END_FUNC(STATIC) /* end H5EA__cache_hdr_clear() */
+END_FUNC(STATIC) /* end H5EA__cache_hdr_free_icr() */
/*-------------------------------------------------------------------------
- * Function: H5EA__cache_hdr_size
+ * Function: H5EA__cache_iblock_get_load_size
*
- * Purpose: Compute the size in bytes of a extensible array header
- * on disk, and return it in *size_ptr. On failure,
- * the value of *size_ptr is undefined.
+ * Purpose: Compute the size of the data structure on disk.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * Aug 26 2008
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * July 17, 2013
*
*-------------------------------------------------------------------------
*/
-/* ARGSUSED */
BEGIN_FUNC(STATIC, NOERR,
herr_t, SUCCEED, -,
-H5EA__cache_hdr_size(const H5F_t H5_ATTR_UNUSED *f, const H5EA_hdr_t *hdr,
- size_t *size_ptr))
+H5EA__cache_iblock_get_load_size(const void *_image, void *_udata, size_t *image_len, size_t *actual_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr))
- /* Sanity check */
- HDassert(f);
+ /* Local variables */
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ H5EA_hdr_t *hdr = (H5EA_hdr_t *)_udata; /* User data for callback */
+ H5EA_iblock_t iblock; /* Fake index block for computing size */
+
+ /* Check arguments */
HDassert(hdr);
- HDassert(size_ptr);
+ HDassert(image_len);
- /* Set size value */
- *size_ptr = hdr->size;
+ if(image == NULL) {
+ /* Set up fake index block for computing size on disk */
+ HDmemset(&iblock, 0, sizeof(iblock));
+ iblock.hdr = (H5EA_hdr_t *)hdr; /* Casting away 'const' OK - QAK */
+ iblock.nsblks = H5EA_SBLK_FIRST_IDX(hdr->cparam.sup_blk_min_data_ptrs);
+ iblock.ndblk_addrs = 2 * ((size_t)hdr->cparam.sup_blk_min_data_ptrs - 1);
+ iblock.nsblk_addrs = hdr->nsblks - iblock.nsblks;
-END_FUNC(STATIC) /* end H5EA__cache_hdr_size() */
+ /* Set the image length size */
+ *image_len = (size_t)H5EA_IBLOCK_SIZE(&iblock);
+ } else {
+ HDassert(actual_len);
+ HDassert(*actual_len == *image_len);
+ }
+
+END_FUNC(STATIC) /* end H5EA__cache_iblock_get_load_size() */
/*-------------------------------------------------------------------------
- * Function: H5EA__cache_hdr_dest
+ * Function: H5EA__cache_iblock_verify_chksum
*
- * Purpose: Destroys an extensible array header in memory.
+ * Purpose: Verify the computed checksum of the data structure is the
+ * same as the stored chksum.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Success: TRUE/FALSE
+ * Failure: Negative
*
- * Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * Aug 26 2008
+ * Programmer: Vailin Choi; Aug 2015
*
*-------------------------------------------------------------------------
*/
-/* ARGSUSED */
-BEGIN_FUNC(STATIC, ERR,
-herr_t, SUCCEED, FAIL,
-H5EA__cache_hdr_dest(H5F_t *f, H5EA_hdr_t *hdr))
-
- /* Check arguments */
- HDassert(f);
- HDassert(hdr);
-
- /* Verify that header is clean */
- HDassert(hdr->cache_info.is_dirty == FALSE);
+BEGIN_FUNC(STATIC, NOERR,
+htri_t, TRUE, -,
+H5EA__cache_iblock_verify_chksum(const void *_image, size_t len, void H5_ATTR_UNUSED *_udata))
- /* If we're going to free the space on disk, the address must be valid */
- HDassert(!hdr->cache_info.free_file_space_on_destroy || H5F_addr_defined(hdr->cache_info.addr));
+ /* Local variables */
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ uint32_t stored_chksum; /* Stored metadata checksum value */
+ uint32_t computed_chksum; /* Computed metadata checksum value */
- /* Check for freeing file space for extensible array header */
- if(hdr->cache_info.free_file_space_on_destroy) {
- /* Sanity check address */
- HDassert(H5F_addr_eq(hdr->addr, hdr->cache_info.addr));
+ /* Check arguments */
+ HDassert(image);
- /* Release the space on disk */
- /* (XXX: Nasty usage of internal DXPL value! -QAK) */
- if(H5MF_xfree(f, H5FD_MEM_EARRAY_HDR, H5AC_dxpl_id, hdr->cache_info.addr, (hsize_t)hdr->size) < 0)
- H5E_THROW(H5E_CANTFREE, "unable to free extensible array header")
- } /* end if */
+ /* Get stored and computed checksums */
+ H5F_get_checksums(image, len, &stored_chksum, &computed_chksum);
- /* Release the extensible array header */
- if(H5EA__hdr_dest(hdr) < 0)
- H5E_THROW(H5E_CANTFREE, "can't free extensible array header")
-
-CATCH
+ if(stored_chksum != computed_chksum)
+ ret_value = FALSE;
-END_FUNC(STATIC) /* end H5EA__cache_hdr_dest() */
+END_FUNC(STATIC) /* end H5EA__cache_iblock_verify_chksum() */
/*-------------------------------------------------------------------------
- * Function: H5EA__cache_iblock_load
+ * Function: H5EA__cache_iblock_deserialize
*
- * Purpose: Loads an extensible array index block from the disk.
+ * Purpose: Loads a data structure from the disk.
*
- * Return: Success: Pointer to a new extensible array index block
+ * Return: Success: Pointer to a new B-tree.
* Failure: NULL
*
* Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * Sep 9 2008
+ * koziol@hdfgroup.org
+ * July 17, 2013
*
*-------------------------------------------------------------------------
*/
BEGIN_FUNC(STATIC, ERR,
-H5EA_iblock_t *, NULL, NULL,
-H5EA__cache_iblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata))
+void *, NULL, NULL,
+H5EA__cache_iblock_deserialize(const void *_image, size_t len,
+ void *_udata, hbool_t H5_ATTR_UNUSED *dirty))
/* Local variables */
- H5EA_hdr_t *hdr = (H5EA_hdr_t *)_udata; /* Shared extensible array information */
H5EA_iblock_t *iblock = NULL; /* Index block info */
- size_t size; /* Index block size */
- H5WB_t *wb = NULL; /* Wrapped buffer for index block data */
- uint8_t iblock_buf[H5EA_IBLOCK_BUF_SIZE]; /* Buffer for index block */
- uint8_t *buf; /* Pointer to index block buffer */
- const uint8_t *p; /* Pointer into raw data buffer */
+ H5EA_hdr_t *hdr = (H5EA_hdr_t *)_udata; /* User data for callback */
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ uint32_t stored_chksum; /* Stored metadata checksum value */
haddr_t arr_addr; /* Address of array header in the file */
size_t u; /* Local index variable */
- /* Sanity check */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
+ /* Check arguments */
+ HDassert(image);
HDassert(hdr);
/* Allocate the extensible array index block */
@@ -576,41 +691,23 @@ H5EA__cache_iblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata))
H5E_THROW(H5E_CANTALLOC, "memory allocation failed for extensible array index block")
/* Set the extensible array index block's address */
- iblock->addr = addr;
-
- /* Wrap the local buffer for serialized info */
- if(NULL == (wb = H5WB_wrap(iblock_buf, sizeof(iblock_buf))))
- H5E_THROW(H5E_CANTINIT, "can't wrap buffer")
-
- /* Compute the size of the extensible array index block on disk */
- size = H5EA_IBLOCK_SIZE(iblock);
-
- /* Get a pointer to a buffer that's large enough for serialized info */
- if(NULL == (buf = (uint8_t *)H5WB_actual(wb, size)))
- H5E_THROW(H5E_CANTGET, "can't get actual buffer")
-
- /* Read and validate index block from disk */
- if(H5F_read_check_metadata(f, dxpl_id, H5FD_MEM_EARRAY_IBLOCK, H5AC_EARRAY_IBLOCK_ID, addr, size, size, buf) < 0)
- H5E_THROW(H5E_BADVALUE, "incorrect metadata checksum for extensible array index block")
-
- /* Get temporary pointer to serialized header */
- p = buf;
+ iblock->addr = hdr->idx_blk_addr;
/* Magic number */
- if(HDmemcmp(p, H5EA_IBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC))
+ if(HDmemcmp(image, H5EA_IBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC))
H5E_THROW(H5E_BADVALUE, "wrong extensible array index block signature")
- p += H5_SIZEOF_MAGIC;
+ image += H5_SIZEOF_MAGIC;
/* Version */
- if(*p++ != H5EA_IBLOCK_VERSION)
+ if(*image++ != H5EA_IBLOCK_VERSION)
H5E_THROW(H5E_VERSION, "wrong extensible array index block version")
/* Extensible array type */
- if(*p++ != (uint8_t)hdr->cparam.cls->id)
+ if(*image++ != (uint8_t)hdr->cparam.cls->id)
H5E_THROW(H5E_BADTYPE, "incorrect extensible array class")
/* Address of header for array that owns this block (just for file integrity checks) */
- H5F_addr_decode(f, &p, &arr_addr);
+ H5F_addr_decode(hdr->f, &image, &arr_addr);
if(H5F_addr_ne(arr_addr, hdr->addr))
H5E_THROW(H5E_BADVALUE, "wrong extensible array header address")
@@ -619,36 +716,39 @@ H5EA__cache_iblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata))
/* Decode elements in index block */
if(hdr->cparam.idx_blk_elmts > 0) {
/* Convert from raw elements on disk into native elements in memory */
- if((hdr->cparam.cls->decode)(p, iblock->elmts, (size_t)hdr->cparam.idx_blk_elmts, hdr->cb_ctx) < 0)
+ if((hdr->cparam.cls->decode)(image, iblock->elmts, (size_t)hdr->cparam.idx_blk_elmts, hdr->cb_ctx) < 0)
H5E_THROW(H5E_CANTDECODE, "can't decode extensible array index elements")
- p += (hdr->cparam.idx_blk_elmts * hdr->cparam.raw_elmt_size);
+ image += (hdr->cparam.idx_blk_elmts * hdr->cparam.raw_elmt_size);
} /* end if */
/* Decode data block addresses in index block */
if(iblock->ndblk_addrs > 0) {
/* Decode addresses of data blocks in index block */
for(u = 0; u < iblock->ndblk_addrs; u++)
- H5F_addr_decode(f, &p, &iblock->dblk_addrs[u]);
+ H5F_addr_decode(hdr->f, &image, &iblock->dblk_addrs[u]);
} /* end if */
/* Decode super block addresses in index block */
if(iblock->nsblk_addrs > 0) {
/* Decode addresses of super blocks in index block */
for(u = 0; u < iblock->nsblk_addrs; u++)
- H5F_addr_decode(f, &p, &iblock->sblk_addrs[u]);
+ H5F_addr_decode(hdr->f, &image, &iblock->sblk_addrs[u]);
} /* end if */
/* Sanity check */
/* (allow for checksum not decoded yet) */
- HDassert((size_t)(p - buf) == (size - H5EA_SIZEOF_CHKSUM));
+ HDassert((size_t)(image - (const uint8_t *)_image) == (len - H5EA_SIZEOF_CHKSUM));
/* Save the index block's size */
- iblock->size = size;
+ iblock->size = len;
+
+ /* checksum verification already done in verify_chksum cb */
- /* Already decoded and compared stored checksum earlier, when reading */
+ /* Metadata checksum */
+ UINT32DECODE(image, stored_chksum);
/* Sanity check */
- HDassert((size_t)(p - buf) == (iblock->size - H5_SIZEOF_CHKSUM));
+ HDassert((size_t)(image - (const uint8_t *)_image) == iblock->size);
/* Set return value */
ret_value = iblock;
@@ -656,161 +756,128 @@ H5EA__cache_iblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata))
CATCH
/* Release resources */
- if(wb && H5WB_unwrap(wb) < 0)
- H5E_THROW(H5E_CLOSEERROR, "can't close wrapped buffer")
if(!ret_value)
if(iblock && H5EA__iblock_dest(iblock) < 0)
H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array index block")
-END_FUNC(STATIC) /* end H5EA__cache_iblock_load() */
+END_FUNC(STATIC) /* end H5EA__cache_iblock_deserialize() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__cache_iblock_image_len
+ *
+ * Purpose: Compute the size of the data structure on disk.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * July 17, 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(STATIC, NOERR,
+herr_t, SUCCEED, -,
+H5EA__cache_iblock_image_len(const void *_thing, size_t *image_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr))
+
+ /* Local variables */
+ const H5EA_iblock_t *iblock = (const H5EA_iblock_t *)_thing; /* Pointer to the object */
+
+ /* Check arguments */
+ HDassert(iblock);
+ HDassert(image_len);
+
+ /* Set the image length size */
+ *image_len = iblock->size;
+
+END_FUNC(STATIC) /* end H5EA__cache_iblock_image_len() */
/*-------------------------------------------------------------------------
- * Function: H5EA__cache_iblock_flush
+ * Function: H5EA__cache_iblock_serialize
*
- * Purpose: Flushes a dirty extensible array index block to disk.
+ * Purpose: Flushes a dirty object to disk.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * Sep 9 2008
+ * koziol@hdfgroup.org
+ * July 17, 2013
*
*-------------------------------------------------------------------------
*/
BEGIN_FUNC(STATIC, ERR,
herr_t, SUCCEED, FAIL,
-H5EA__cache_iblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr,
- H5EA_iblock_t *iblock, unsigned H5_ATTR_UNUSED * flags_ptr))
+H5EA__cache_iblock_serialize(const H5F_t *f, void *_image, size_t H5_ATTR_UNUSED len,
+ void *_thing))
/* Local variables */
- H5WB_t *wb = NULL; /* Wrapped buffer for serializing data */
- uint8_t ser_buf[H5EA_IBLOCK_BUF_SIZE]; /* Serialization buffer */
+ H5EA_iblock_t *iblock = (H5EA_iblock_t *)_thing; /* Pointer to the object to serialize */
+ uint8_t *image = (uint8_t *)_image; /* Pointer into raw data buffer */
+ uint32_t metadata_chksum; /* Computed metadata checksum value */
- /* Sanity check */
+ /* check arguments */
HDassert(f);
- HDassert(H5F_addr_defined(addr));
+ HDassert(image);
HDassert(iblock);
HDassert(iblock->hdr);
- if(iblock->cache_info.is_dirty) {
- uint8_t *buf; /* Temporary raw data buffer */
- uint8_t *p; /* Pointer into raw data buffer */
- size_t size; /* Index block size on disk */
- uint32_t metadata_chksum; /* Computed metadata checksum value */
-
- /* Wrap the local buffer for serialized info */
- if(NULL == (wb = H5WB_wrap(ser_buf, sizeof(ser_buf))))
- H5E_THROW(H5E_CANTINIT, "can't wrap buffer")
-
- /* Compute the size of the index block on disk */
- size = iblock->size;
-
- /* Get a pointer to a buffer that's large enough for serialized info */
- if(NULL == (buf = (uint8_t *)H5WB_actual(wb, size)))
- H5E_THROW(H5E_CANTGET, "can't get actual buffer")
-
- /* Get temporary pointer to serialized info */
- p = buf;
-
- /* Magic number */
- HDmemcpy(p, H5EA_IBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC);
- p += H5_SIZEOF_MAGIC;
-
- /* Version # */
- *p++ = H5EA_IBLOCK_VERSION;
-
- /* Extensible array type */
- *p++ = iblock->hdr->cparam.cls->id;
+ /* Get temporary pointer to serialized info */
- /* Address of array header for array which owns this block */
- H5F_addr_encode(f, &p, iblock->hdr->addr);
-
- /* Internal information */
-
- /* Encode elements in index block */
- if(iblock->hdr->cparam.idx_blk_elmts > 0) {
- /* Convert from native elements in memory into raw elements on disk */
- if((iblock->hdr->cparam.cls->encode)(p, iblock->elmts, (size_t)iblock->hdr->cparam.idx_blk_elmts, iblock->hdr->cb_ctx) < 0)
- H5E_THROW(H5E_CANTENCODE, "can't encode extensible array index elements")
- p += (iblock->hdr->cparam.idx_blk_elmts * iblock->hdr->cparam.raw_elmt_size);
- } /* end if */
-
- /* Encode data block addresses in index block */
- if(iblock->ndblk_addrs > 0) {
- size_t u; /* Local index variable */
+ /* Magic number */
+ HDmemcpy(image, H5EA_IBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ image += H5_SIZEOF_MAGIC;
- /* Encode addresses of data blocks in index block */
- for(u = 0; u < iblock->ndblk_addrs; u++)
- H5F_addr_encode(f, &p, iblock->dblk_addrs[u]);
- } /* end if */
+ /* Version # */
+ *image++ = H5EA_IBLOCK_VERSION;
- /* Encode data block addresses in index block */
- if(iblock->nsblk_addrs > 0) {
- size_t u; /* Local index variable */
+ /* Extensible array type */
+ *image++ = iblock->hdr->cparam.cls->id;
- /* Encode addresses of super blocks in index block */
- for(u = 0; u < iblock->nsblk_addrs; u++)
- H5F_addr_encode(f, &p, iblock->sblk_addrs[u]);
- } /* end if */
+ /* Address of array header for array which owns this block */
+ H5F_addr_encode(f, &image, iblock->hdr->addr);
- /* Compute metadata checksum */
- metadata_chksum = H5_checksum_metadata(buf, (size_t)(p - buf), 0);
+ /* Internal information */
- /* Metadata checksum */
- UINT32ENCODE(p, metadata_chksum);
+ /* Encode elements in index block */
+ if(iblock->hdr->cparam.idx_blk_elmts > 0) {
+ /* Convert from native elements in memory into raw elements on disk */
+ if((iblock->hdr->cparam.cls->encode)(image, iblock->elmts, (size_t)iblock->hdr->cparam.idx_blk_elmts, iblock->hdr->cb_ctx) < 0)
+ H5E_THROW(H5E_CANTENCODE, "can't encode extensible array index elements")
+ image += (iblock->hdr->cparam.idx_blk_elmts * iblock->hdr->cparam.raw_elmt_size);
+ } /* end if */
- /* Write the index block */
- HDassert((size_t)(p - buf) == size);
- if(H5F_block_write(f, H5FD_MEM_EARRAY_IBLOCK, addr, size, dxpl_id, buf) < 0)
- H5E_THROW(H5E_WRITEERROR, "unable to save extensible array index block to disk")
+ /* Encode data block addresses in index block */
+ if(iblock->ndblk_addrs > 0) {
+ size_t u; /* Local index variable */
- iblock->cache_info.is_dirty = FALSE;
+ /* Encode addresses of data blocks in index block */
+ for(u = 0; u < iblock->ndblk_addrs; u++)
+ H5F_addr_encode(f, &image, iblock->dblk_addrs[u]);
} /* end if */
- if(destroy)
- if(H5EA__cache_iblock_dest(f, iblock) < 0)
- H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array index block")
-
-CATCH
+ /* Encode data block addresses in index block */
+ if(iblock->nsblk_addrs > 0) {
+ size_t u; /* Local index variable */
- /* Release resources */
- if(wb && H5WB_unwrap(wb) < 0)
- H5E_THROW(H5E_CLOSEERROR, "can't close wrapped buffer")
+ /* Encode addresses of super blocks in index block */
+ for(u = 0; u < iblock->nsblk_addrs; u++)
+ H5F_addr_encode(f, &image, iblock->sblk_addrs[u]);
+ } /* end if */
-END_FUNC(STATIC) /* end H5EA__cache_iblock_flush() */
+ /* Compute metadata checksum */
+ metadata_chksum = H5_checksum_metadata(_image, (size_t)(image - (uint8_t *)_image), 0);
-
-/*-------------------------------------------------------------------------
- * Function: H5EA__cache_iblock_clear
- *
- * Purpose: Mark a extensible array index block in memory as non-dirty.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * Sept 9 2008
- *
- *-------------------------------------------------------------------------
- */
-BEGIN_FUNC(STATIC, ERR,
-herr_t, SUCCEED, FAIL,
-H5EA__cache_iblock_clear(H5F_t *f, H5EA_iblock_t *iblock, hbool_t destroy))
+ /* Metadata checksum */
+ UINT32ENCODE(image, metadata_chksum);
/* Sanity check */
- HDassert(iblock);
-
- /* Reset the dirty flag */
- iblock->cache_info.is_dirty = FALSE;
-
- if(destroy)
- if(H5EA__cache_iblock_dest(f, iblock) < 0)
- H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array index block")
+ HDassert((size_t)(image - (uint8_t *)_image) <= len);
CATCH
-END_FUNC(STATIC) /* end H5EA__cache_iblock_clear() */
+END_FUNC(STATIC) /* end H5EA__cache_iblock_serialize() */
/*-------------------------------------------------------------------------
@@ -822,13 +889,16 @@ END_FUNC(STATIC) /* end H5EA__cache_iblock_clear() */
*
* Programmer: Quincey Koziol
* koziol@hdfgroup.org
- * Mar 31 2009
+ * July 17, 2013
*
*-------------------------------------------------------------------------
*/
BEGIN_FUNC(STATIC, ERR,
herr_t, SUCCEED, FAIL,
-H5EA__cache_iblock_notify(H5AC_notify_action_t action, H5EA_iblock_t *iblock))
+H5EA__cache_iblock_notify(H5AC_notify_action_t action, void *_thing))
+
+ /* Local variables */
+ H5EA_iblock_t *iblock = (H5EA_iblock_t *)_thing; /* Pointer to the object */
/* Sanity check */
HDassert(iblock);
@@ -838,14 +908,21 @@ H5EA__cache_iblock_notify(H5AC_notify_action_t action, H5EA_iblock_t *iblock))
/* Determine which action to take */
switch(action) {
case H5AC_NOTIFY_ACTION_AFTER_INSERT:
+ case H5AC_NOTIFY_ACTION_AFTER_LOAD:
/* Create flush dependency on extensible array header */
if(H5EA__create_flush_depend((H5AC_info_t *)iblock->hdr, (H5AC_info_t *)iblock) < 0)
H5E_THROW(H5E_CANTDEPEND, "unable to create flush dependency between index block and header, address = %llu", (unsigned long long)iblock->addr)
break;
- case H5AC_NOTIFY_ACTION_BEFORE_EVICT:
- /* Nothing to do */
- break;
+ case H5AC_NOTIFY_ACTION_AFTER_FLUSH:
+ /* do nothing */
+ break;
+
+ case H5AC_NOTIFY_ACTION_BEFORE_EVICT:
+ /* Destroy flush dependency on extensible array header */
+ if(H5EA__destroy_flush_depend((H5AC_info_t *)iblock->hdr, (H5AC_info_t *)iblock) < 0)
+ H5E_THROW(H5E_CANTUNDEPEND, "unable to destroy flush dependency between index block and header, address = %llu", (unsigned long long)iblock->addr)
+ break;
default:
#ifdef NDEBUG
@@ -862,163 +939,196 @@ END_FUNC(STATIC) /* end H5EA__cache_iblock_notify() */
/*-------------------------------------------------------------------------
- * Function: H5EA__cache_iblock_size
+ * Function: H5EA__cache_iblock_free_icr
*
- * Purpose: Compute the size in bytes of a extensible array index block
- * on disk, and return it in *size_ptr. On failure,
- * the value of *size_ptr is undefined.
+ * Purpose: Destroy/release an "in core representation" of a data
+ * structure
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * Sept 9 2008
+ * koziol@hdfgroup.org
+ * July 17, 2013
*
*-------------------------------------------------------------------------
*/
-/* ARGSUSED */
-BEGIN_FUNC(STATIC, NOERR,
-herr_t, SUCCEED, -,
-H5EA__cache_iblock_size(const H5F_t H5_ATTR_UNUSED *f, const H5EA_iblock_t *iblock,
- size_t *size_ptr))
+BEGIN_FUNC(STATIC, ERR,
+herr_t, SUCCEED, FAIL,
+H5EA__cache_iblock_free_icr(void *thing))
- /* Sanity check */
- HDassert(f);
- HDassert(iblock);
- HDassert(size_ptr);
+ /* Check arguments */
+ HDassert(thing);
- /* Set size value */
- *size_ptr = iblock->size;
+ /* Release the extensible array index block */
+ if(H5EA__iblock_dest((H5EA_iblock_t *)thing) < 0)
+ H5E_THROW(H5E_CANTFREE, "can't free extensible array index block")
-END_FUNC(STATIC) /* end H5EA__cache_iblock_size() */
+CATCH
+
+END_FUNC(STATIC) /* end H5EA__cache_iblock_free_icr() */
/*-------------------------------------------------------------------------
- * Function: H5EA__cache_iblock_dest
+ * Function: H5EA__cache_sblock_get_load_size
*
- * Purpose: Destroys an extensible array index block in memory.
+ * Purpose: Compute the size of the data structure on disk.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * Sep 9 2008
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * July 17, 2013
*
*-------------------------------------------------------------------------
*/
-BEGIN_FUNC(STATIC, ERR,
-herr_t, SUCCEED, FAIL,
-H5EA__cache_iblock_dest(H5F_t *f, H5EA_iblock_t *iblock))
+BEGIN_FUNC(STATIC, NOERR,
+herr_t, SUCCEED, -,
+H5EA__cache_sblock_get_load_size(const void *_image, void *_udata,
+ size_t *image_len, size_t *actual_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr))
- /* Sanity check */
- HDassert(f);
- HDassert(iblock);
+ /* Local variables */
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ H5EA_sblock_cache_ud_t *udata = (H5EA_sblock_cache_ud_t *)_udata; /* User data */
+ H5EA_sblock_t sblock; /* Fake super block for computing size */
- /* Verify that index block is clean */
- HDassert(iblock->cache_info.is_dirty == FALSE);
+ /* Check arguments */
+ HDassert(udata);
+ HDassert(udata->hdr);
+ HDassert(udata->sblk_idx > 0);
+ HDassert(H5F_addr_defined(udata->sblk_addr));
+ HDassert(image_len);
+
+ if(image == NULL) {
+ /* Set up fake super block for computing size on disk */
+ /* (Note: extracted from H5EA__sblock_alloc) */
+ HDmemset(&sblock, 0, sizeof(sblock));
+ sblock.hdr = udata->hdr;
+ sblock.ndblks = udata->hdr->sblk_info[udata->sblk_idx].ndblks;
+ sblock.dblk_nelmts = udata->hdr->sblk_info[udata->sblk_idx].dblk_nelmts;
+
+ /* Check if # of elements in data blocks requires paging */
+ if(sblock.dblk_nelmts > udata->hdr->dblk_page_nelmts) {
+ /* Compute # of pages in each data block from this super block */
+ sblock.dblk_npages = sblock.dblk_nelmts / udata->hdr->dblk_page_nelmts;
+
+ /* Sanity check that we have at least 2 pages in data block */
+ HDassert(sblock.dblk_npages > 1);
+
+ /* Sanity check for integer truncation */
+ HDassert((sblock.dblk_npages * udata->hdr->dblk_page_nelmts) == sblock.dblk_nelmts);
+
+ /* Compute size of buffer for each data block's 'page init' bitmask */
+ sblock.dblk_page_init_size = ((sblock.dblk_npages) + 7) / 8;
+ HDassert(sblock.dblk_page_init_size > 0);
+ } /* end if */
+
+ /* Set the image length size */
+ *image_len = (size_t)H5EA_SBLOCK_SIZE(&sblock);
+
+ } else {
+ HDassert(actual_len);
+ HDassert(*actual_len == *image_len);
+ }
+
+END_FUNC(STATIC) /* end H5EA__cache_sblock_get_load_size() */
- /* If we're going to free the space on disk, the address must be valid */
- HDassert(!iblock->cache_info.free_file_space_on_destroy || H5F_addr_defined(iblock->cache_info.addr));
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__cache_sblock_verify_chksum
+ *
+ * Purpose: Verify the computed checksum of the data structure is the
+ * same as the stored chksum.
+ *
+ * Return: Success: TRUE/FALSE
+ * Failure: Negative
+ *
+ * Programmer: Vailin Choi; Aug 2015
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(STATIC, NOERR,
+htri_t, TRUE, -,
+H5EA__cache_sblock_verify_chksum(const void *_image, size_t len, void H5_ATTR_UNUSED *_udata))
- /* Check for freeing file space for extensible array index block */
- if(iblock->cache_info.free_file_space_on_destroy) {
- /* Sanity check address */
- HDassert(H5F_addr_eq(iblock->addr, iblock->cache_info.addr));
+ /* Local variables */
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ uint32_t stored_chksum; /* Stored metadata checksum value */
+ uint32_t computed_chksum; /* Computed metadata checksum value */
- /* Release the space on disk */
- /* (XXX: Nasty usage of internal DXPL value! -QAK) */
- if(H5MF_xfree(f, H5FD_MEM_EARRAY_IBLOCK, H5AC_dxpl_id, iblock->cache_info.addr, (hsize_t)iblock->size) < 0)
- H5E_THROW(H5E_CANTFREE, "unable to free extensible array index block")
- } /* end if */
+ /* Check arguments */
+ HDassert(image);
- /* Release the index block */
- if(H5EA__iblock_dest(iblock) < 0)
- H5E_THROW(H5E_CANTFREE, "can't free extensible array index block")
+ /* Get stored and computed checksums */
+ H5F_get_checksums(image, len, &stored_chksum, &computed_chksum);
-CATCH
+ if(stored_chksum != computed_chksum)
+ ret_value = FALSE;
-END_FUNC(STATIC) /* end H5EA__cache_iblock_dest() */
+END_FUNC(STATIC) /* end H5EA__cache_sblock_verify_chksum() */
/*-------------------------------------------------------------------------
- * Function: H5EA__cache_sblock_load
+ * Function: H5EA__cache_sblock_deserialize
*
- * Purpose: Loads an extensible array super block from the disk.
+ * Purpose: Loads a data structure from the disk.
*
- * Return: Success: Pointer to a new extensible array super block
+ * Return: Success: Pointer to a new B-tree.
* Failure: NULL
*
* Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * Sep 30 2008
+ * koziol@hdfgroup.org
+ * July 17, 2013
*
*-------------------------------------------------------------------------
*/
BEGIN_FUNC(STATIC, ERR,
-H5EA_sblock_t *, NULL, NULL,
-H5EA__cache_sblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata))
+void *, NULL, NULL,
+H5EA__cache_sblock_deserialize(const void *_image, size_t len,
+ void *_udata, hbool_t H5_ATTR_UNUSED *dirty))
/* Local variables */
H5EA_sblock_t *sblock = NULL; /* Super block info */
- H5EA_sblock_cache_ud_t *udata = (H5EA_sblock_cache_ud_t *)_udata; /* User data for loading super block */
- size_t size; /* Super block size */
- H5WB_t *wb = NULL; /* Wrapped buffer for super block data */
- uint8_t sblock_buf[H5EA_IBLOCK_BUF_SIZE]; /* Buffer for super block */
- uint8_t *buf; /* Pointer to super block buffer */
- const uint8_t *p; /* Pointer into raw data buffer */
+ H5EA_sblock_cache_ud_t *udata = (H5EA_sblock_cache_ud_t *)_udata; /* User data */
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ uint32_t stored_chksum; /* Stored metadata checksum value */
haddr_t arr_addr; /* Address of array header in the file */
size_t u; /* Local index variable */
/* Sanity check */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
- HDassert(udata && udata->hdr && udata->parent && udata->sblk_idx > 0);
+ HDassert(udata);
+ HDassert(udata->hdr);
+ HDassert(udata->parent);
+ HDassert(udata->sblk_idx > 0);
+ HDassert(H5F_addr_defined(udata->sblk_addr));
/* Allocate the extensible array super block */
if(NULL == (sblock = H5EA__sblock_alloc(udata->hdr, udata->parent, udata->sblk_idx)))
H5E_THROW(H5E_CANTALLOC, "memory allocation failed for extensible array super block")
/* Set the extensible array super block's address */
- sblock->addr = addr;
-
- /* Wrap the local buffer for serialized info */
- if(NULL == (wb = H5WB_wrap(sblock_buf, sizeof(sblock_buf))))
- H5E_THROW(H5E_CANTINIT, "can't wrap buffer")
-
- /* Compute the size of the extensible array super block on disk */
- size = H5EA_SBLOCK_SIZE(sblock);
-
- /* Get a pointer to a buffer that's large enough for serialized info */
- if(NULL == (buf = (uint8_t *)H5WB_actual(wb, size)))
- H5E_THROW(H5E_CANTGET, "can't get actual buffer")
-
- /* Read and validate super block from disk */
- if(H5F_read_check_metadata(f, dxpl_id, H5FD_MEM_EARRAY_SBLOCK, H5AC_EARRAY_SBLOCK_ID, addr, size, size, buf) < 0)
- H5E_THROW(H5E_BADVALUE, "incorrect metadata checksum for extensible array super block")
-
- /* Get temporary pointer to serialized header */
- p = buf;
+ sblock->addr = udata->sblk_addr;
/* Magic number */
- if(HDmemcmp(p, H5EA_SBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC))
+ if(HDmemcmp(image, H5EA_SBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC))
H5E_THROW(H5E_BADVALUE, "wrong extensible array super block signature")
- p += H5_SIZEOF_MAGIC;
+ image += H5_SIZEOF_MAGIC;
/* Version */
- if(*p++ != H5EA_SBLOCK_VERSION)
+ if(*image++ != H5EA_SBLOCK_VERSION)
H5E_THROW(H5E_VERSION, "wrong extensible array super block version")
/* Extensible array type */
- if(*p++ != (uint8_t)udata->hdr->cparam.cls->id)
+ if(*image++ != (uint8_t)udata->hdr->cparam.cls->id)
H5E_THROW(H5E_BADTYPE, "incorrect extensible array class")
/* Address of header for array that owns this block (just for file integrity checks) */
- H5F_addr_decode(f, &p, &arr_addr);
+ H5F_addr_decode(udata->hdr->f, &image, &arr_addr);
if(H5F_addr_ne(arr_addr, udata->hdr->addr))
H5E_THROW(H5E_BADVALUE, "wrong extensible array header address")
/* Offset of block within the array's address space */
- UINT64DECODE_VAR(p, sblock->block_off, udata->hdr->arr_off_size);
+ UINT64DECODE_VAR(image, sblock->block_off, udata->hdr->arr_off_size);
/* Internal information */
@@ -1027,25 +1137,28 @@ H5EA__cache_sblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata))
size_t tot_page_init_size = sblock->ndblks * sblock->dblk_page_init_size; /* Compute total size of 'page init' buffer */
/* Retrieve the 'page init' bitmasks */
- HDmemcpy(sblock->page_init, p, tot_page_init_size);
- p += tot_page_init_size;
+ HDmemcpy(sblock->page_init, image, tot_page_init_size);
+ image += tot_page_init_size;
} /* end if */
/* Decode data block addresses */
for(u = 0; u < sblock->ndblks; u++)
- H5F_addr_decode(f, &p, &sblock->dblk_addrs[u]);
+ H5F_addr_decode(udata->hdr->f, &image, &sblock->dblk_addrs[u]);
/* Sanity check */
/* (allow for checksum not decoded yet) */
- HDassert((size_t)(p - buf) == (size - H5EA_SIZEOF_CHKSUM));
+ HDassert((size_t)(image - (const uint8_t *)_image) == (len - H5EA_SIZEOF_CHKSUM));
/* Save the super block's size */
- sblock->size = size;
+ sblock->size = len;
- /* Already decoded and compared stored checksum earlier, when reading */
+ /* checksum verification already done in verify_chksum cb */
+
+ /* Metadata checksum */
+ UINT32DECODE(image, stored_chksum);
/* Sanity check */
- HDassert((size_t)(p - buf) == (sblock->size - H5_SIZEOF_CHKSUM));
+ HDassert((size_t)(image - (const uint8_t *)_image) == sblock->size);
/* Set return value */
ret_value = sblock;
@@ -1053,183 +1166,115 @@ H5EA__cache_sblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata))
CATCH
/* Release resources */
- if(wb && H5WB_unwrap(wb) < 0)
- H5E_THROW(H5E_CLOSEERROR, "can't close wrapped buffer")
if(!ret_value)
if(sblock && H5EA__sblock_dest(sblock) < 0)
H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array super block")
-END_FUNC(STATIC) /* end H5EA__cache_sblock_load() */
+END_FUNC(STATIC) /* end H5EA__cache_sblock_deserialize() */
/*-------------------------------------------------------------------------
- * Function: H5EA__cache_sblock_flush
+ * Function: H5EA__cache_sblock_image_len
*
- * Purpose: Flushes a dirty extensible array super block to disk.
+ * Purpose: Compute the size of the data structure on disk.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * Sep 30 2008
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * July 17, 2013
*
*-------------------------------------------------------------------------
*/
-BEGIN_FUNC(STATIC, ERR,
-herr_t, SUCCEED, FAIL,
-H5EA__cache_sblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr,
- H5EA_sblock_t *sblock, unsigned H5_ATTR_UNUSED * flags_ptr))
+BEGIN_FUNC(STATIC, NOERR,
+herr_t, SUCCEED, -,
+H5EA__cache_sblock_image_len(const void *_thing, size_t *image_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr))
/* Local variables */
- H5WB_t *wb = NULL; /* Wrapped buffer for serializing data */
- uint8_t ser_buf[H5EA_SBLOCK_BUF_SIZE]; /* Serialization buffer */
+ const H5EA_sblock_t *sblock = (const H5EA_sblock_t *)_thing; /* Pointer to the object */
- /* Sanity check */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
+ /* Check arguments */
HDassert(sblock);
- HDassert(sblock->hdr);
-
- if(sblock->cache_info.is_dirty) {
- uint8_t *buf; /* Temporary raw data buffer */
- uint8_t *p; /* Pointer into raw data buffer */
- size_t size; /* Index block size on disk */
- uint32_t metadata_chksum; /* Computed metadata checksum value */
- size_t u; /* Local index variable */
-
- /* Wrap the local buffer for serialized info */
- if(NULL == (wb = H5WB_wrap(ser_buf, sizeof(ser_buf))))
- H5E_THROW(H5E_CANTINIT, "can't wrap buffer")
+ HDassert(image_len);
- /* Compute the size of the super block on disk */
- size = sblock->size;
+ /* Set the image length size */
+ *image_len = sblock->size;
- /* Get a pointer to a buffer that's large enough for serialized info */
- if(NULL == (buf = (uint8_t *)H5WB_actual(wb, size)))
- H5E_THROW(H5E_CANTGET, "can't get actual buffer")
-
- /* Get temporary pointer to serialized info */
- p = buf;
-
- /* Magic number */
- HDmemcpy(p, H5EA_SBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC);
- p += H5_SIZEOF_MAGIC;
-
- /* Version # */
- *p++ = H5EA_SBLOCK_VERSION;
-
- /* Extensible array type */
- *p++ = sblock->hdr->cparam.cls->id;
-
- /* Address of array header for array which owns this block */
- H5F_addr_encode(f, &p, sblock->hdr->addr);
-
- /* Offset of block in array */
- UINT64ENCODE_VAR(p, sblock->block_off, sblock->hdr->arr_off_size);
-
- /* Internal information */
-
- /* Check for 'page init' bitmasks for this super block */
- if(sblock->dblk_npages > 0) {
- size_t tot_page_init_size = sblock->ndblks * sblock->dblk_page_init_size; /* Compute total size of 'page init' buffer */
-
- /* Store the 'page init' bitmasks */
- HDmemcpy(p, sblock->page_init, tot_page_init_size);
- p += tot_page_init_size;
- } /* end if */
-
- /* Encode addresses of data blocks in super block */
- for(u = 0; u < sblock->ndblks; u++)
- H5F_addr_encode(f, &p, sblock->dblk_addrs[u]);
-
- /* Compute metadata checksum */
- metadata_chksum = H5_checksum_metadata(buf, (size_t)(p - buf), 0);
-
- /* Metadata checksum */
- UINT32ENCODE(p, metadata_chksum);
-
- /* Write the super block */
- HDassert((size_t)(p - buf) == size);
- if(H5F_block_write(f, H5FD_MEM_EARRAY_SBLOCK, addr, size, dxpl_id, buf) < 0)
- H5E_THROW(H5E_WRITEERROR, "unable to save extensible array super block to disk")
-
- sblock->cache_info.is_dirty = FALSE;
- } /* end if */
-
- if(destroy)
- if(H5EA__cache_sblock_dest(f, sblock) < 0)
- H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array super block")
-
-CATCH
-
- /* Release resources */
- if(wb && H5WB_unwrap(wb) < 0)
- H5E_THROW(H5E_CLOSEERROR, "can't close wrapped buffer")
-
-END_FUNC(STATIC) /* end H5EA__cache_sblock_flush() */
+END_FUNC(STATIC) /* end H5EA__cache_sblock_image_len() */
/*-------------------------------------------------------------------------
- * Function: H5EA__cache_sblock_clear
+ * Function: H5EA__cache_sblock_serialize
*
- * Purpose: Mark a extensible array super block in memory as non-dirty.
+ * Purpose: Flushes a dirty object to disk.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * Sept 30 2008
+ * koziol@hdfgroup.org
+ * July 17, 2013
*
*-------------------------------------------------------------------------
*/
-BEGIN_FUNC(STATIC, ERR,
-herr_t, SUCCEED, FAIL,
-H5EA__cache_sblock_clear(H5F_t *f, H5EA_sblock_t *sblock, hbool_t destroy))
+BEGIN_FUNC(STATIC, NOERR,
+herr_t, SUCCEED, -,
+H5EA__cache_sblock_serialize(const H5F_t *f, void *_image, size_t H5_ATTR_UNUSED len,
+ void *_thing))
- /* Sanity check */
+ /* Local variables */
+ H5EA_sblock_t *sblock = (H5EA_sblock_t *)_thing; /* Pointer to the object to serialize */
+ uint8_t *image = (uint8_t *)_image; /* Pointer into raw data buffer */
+ uint32_t metadata_chksum; /* Computed metadata checksum value */
+ size_t u; /* Local index variable */
+
+ /* check arguments */
+ HDassert(f);
+ HDassert(image);
HDassert(sblock);
+ HDassert(sblock->hdr);
- /* Reset the dirty flag */
- sblock->cache_info.is_dirty = FALSE;
+ /* Magic number */
+ HDmemcpy(image, H5EA_SBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ image += H5_SIZEOF_MAGIC;
- if(destroy)
- if(H5EA__cache_sblock_dest(f, sblock) < 0)
- H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array super block")
+ /* Version # */
+ *image++ = H5EA_SBLOCK_VERSION;
-CATCH
+ /* Extensible array type */
+ *image++ = sblock->hdr->cparam.cls->id;
-END_FUNC(STATIC) /* end H5EA__cache_sblock_clear() */
+ /* Address of array header for array which owns this block */
+ H5F_addr_encode(f, &image, sblock->hdr->addr);
-
-/*-------------------------------------------------------------------------
- * Function: H5EA__cache_sblock_size
- *
- * Purpose: Compute the size in bytes of a extensible array super block
- * on disk, and return it in *size_ptr. On failure,
- * the value of *size_ptr is undefined.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * Sept 30 2008
- *
- *-------------------------------------------------------------------------
- */
-/* ARGSUSED */
-BEGIN_FUNC(STATIC, NOERR,
-herr_t, SUCCEED, -,
-H5EA__cache_sblock_size(const H5F_t H5_ATTR_UNUSED *f, const H5EA_sblock_t *sblock,
- size_t *size_ptr))
+ /* Offset of block in array */
+ UINT64ENCODE_VAR(image, sblock->block_off, sblock->hdr->arr_off_size);
- /* Sanity check */
- HDassert(sblock);
- HDassert(size_ptr);
+ /* Internal information */
- /* Set size value */
- *size_ptr = sblock->size;
+ /* Check for 'page init' bitmasks for this super block */
+ if(sblock->dblk_npages > 0) {
+ size_t tot_page_init_size = sblock->ndblks * sblock->dblk_page_init_size; /* Compute total size of 'page init' buffer */
+
+ /* Store the 'page init' bitmasks */
+ HDmemcpy(image, sblock->page_init, tot_page_init_size);
+ image += tot_page_init_size;
+ } /* end if */
+
+ /* Encode addresses of data blocks in super block */
+ for(u = 0; u < sblock->ndblks; u++)
+ H5F_addr_encode(f, &image, sblock->dblk_addrs[u]);
+
+ /* Compute metadata checksum */
+ metadata_chksum = H5_checksum_metadata(_image, (size_t)(image - (uint8_t *)_image), 0);
+
+ /* Metadata checksum */
+ UINT32ENCODE(image, metadata_chksum);
+
+ /* Sanity check */
+ HDassert((size_t)(image - (uint8_t *)_image) <= len);
-END_FUNC(STATIC) /* end H5EA__cache_sblock_size() */
+END_FUNC(STATIC) /* end H5EA__cache_sblock_serialize() */
/*-------------------------------------------------------------------------
@@ -1247,7 +1292,10 @@ END_FUNC(STATIC) /* end H5EA__cache_sblock_size() */
*/
BEGIN_FUNC(STATIC, ERR,
herr_t, SUCCEED, FAIL,
-H5EA__cache_sblock_notify(H5AC_notify_action_t action, H5EA_sblock_t *sblock))
+H5EA__cache_sblock_notify(H5AC_notify_action_t action, void *_thing))
+
+ /* Local variables */
+ H5EA_sblock_t *sblock = (H5EA_sblock_t *)_thing; /* Pointer to the object */
/* Sanity check */
HDassert(sblock);
@@ -1257,14 +1305,21 @@ H5EA__cache_sblock_notify(H5AC_notify_action_t action, H5EA_sblock_t *sblock))
/* Determine which action to take */
switch(action) {
case H5AC_NOTIFY_ACTION_AFTER_INSERT:
+ case H5AC_NOTIFY_ACTION_AFTER_LOAD:
/* Create flush dependency on index block */
if(H5EA__create_flush_depend((H5AC_info_t *)sblock->parent, (H5AC_info_t *)sblock) < 0)
H5E_THROW(H5E_CANTDEPEND, "unable to create flush dependency between super block and index block, address = %llu", (unsigned long long)sblock->addr)
break;
- case H5AC_NOTIFY_ACTION_BEFORE_EVICT:
- /* Nothing to do */
- break;
+ case H5AC_NOTIFY_ACTION_AFTER_FLUSH:
+ /* do nothing */
+ break;
+
+ case H5AC_NOTIFY_ACTION_BEFORE_EVICT:
+ /* Destroy flush dependency on index block */
+ if(H5EA__destroy_flush_depend((H5AC_info_t *)sblock->parent, (H5AC_info_t *)sblock) < 0)
+ H5E_THROW(H5E_CANTUNDEPEND, "unable to destroy flush dependency between super block and index block, address = %llu", (unsigned long long)sblock->addr)
+ break;
default:
#ifdef NDEBUG
@@ -1281,133 +1336,198 @@ END_FUNC(STATIC) /* end H5EA__cache_sblock_notify() */
/*-------------------------------------------------------------------------
- * Function: H5EA__cache_sblock_dest
+ * Function: H5EA__cache_sblock_free_icr
*
- * Purpose: Destroys an extensible array super block in memory.
+ * Purpose: Destroy/release an "in core representation" of a data
+ * structure
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * Sep 30 2008
+ * koziol@hdfgroup.org
+ * July 17, 2013
*
*-------------------------------------------------------------------------
*/
BEGIN_FUNC(STATIC, ERR,
herr_t, SUCCEED, FAIL,
-H5EA__cache_sblock_dest(H5F_t *f, H5EA_sblock_t *sblock))
+H5EA__cache_sblock_free_icr(void *thing))
- /* Sanity check */
- HDassert(f);
- HDassert(sblock);
+ /* Check arguments */
+ HDassert(thing);
- /* Verify that super block is clean */
- HDassert(sblock->cache_info.is_dirty == FALSE);
+ /* Release the extensible array super block */
+ if(H5EA__sblock_dest((H5EA_sblock_t *)thing) < 0)
+ H5E_THROW(H5E_CANTFREE, "can't free extensible array super block")
- /* If we're going to free the space on disk, the address must be valid */
- HDassert(!sblock->cache_info.free_file_space_on_destroy || H5F_addr_defined(sblock->cache_info.addr));
+CATCH
- /* Check for freeing file space for extensible array super block */
- if(sblock->cache_info.free_file_space_on_destroy) {
- /* Sanity check address */
- HDassert(H5F_addr_eq(sblock->addr, sblock->cache_info.addr));
+END_FUNC(STATIC) /* end H5EA__cache_sblock_free_icr() */
- /* Release the space on disk */
- /* (XXX: Nasty usage of internal DXPL value! -QAK) */
- if(H5MF_xfree(f, H5FD_MEM_EARRAY_SBLOCK, H5AC_dxpl_id, sblock->cache_info.addr, (hsize_t)sblock->size) < 0)
- H5E_THROW(H5E_CANTFREE, "unable to free extensible array super block")
- } /* end if */
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__cache_dblock_get_load_size
+ *
+ * Purpose: Compute the size of the data structure on disk.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * July 17, 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(STATIC, NOERR,
+herr_t, SUCCEED, -,
+H5EA__cache_dblock_get_load_size(const void *_image, void *_udata,
+ size_t *image_len, size_t *actual_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr))
- /* Release the super block */
- if(H5EA__sblock_dest(sblock) < 0)
- H5E_THROW(H5E_CANTFREE, "can't free extensible array super block")
+ /* Local variables */
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ H5EA_dblock_cache_ud_t *udata = (H5EA_dblock_cache_ud_t *)_udata; /* User data */
+ H5EA_dblock_t dblock; /* Fake data block for computing size */
-CATCH
+ /* Check arguments */
+ HDassert(udata);
+ HDassert(udata->hdr);
+ HDassert(udata->nelmts > 0);
+ HDassert(image_len);
+
+ if(image == NULL) {
+ /* Set up fake data block for computing size on disk */
+ /* (Note: extracted from H5EA__dblock_alloc) */
+ HDmemset(&dblock, 0, sizeof(dblock));
+
+ /* need to set:
+ *
+ * dblock.hdr
+ * dblock.npages
+ * dblock.nelmts
+ *
+ * before we invoke either H5EA_DBLOCK_PREFIX_SIZE() or
+ * H5EA_DBLOCK_SIZE().
+ */
+ dblock.hdr = udata->hdr;
+ dblock.nelmts = udata->nelmts;
+
+ if(udata->nelmts > udata->hdr->dblk_page_nelmts) {
+ /* Set the # of pages in the direct block */
+ dblock.npages = udata->nelmts / udata->hdr->dblk_page_nelmts;
+ HDassert(udata->nelmts==(dblock.npages * udata->hdr->dblk_page_nelmts));
+ } /* end if */
+
+ /* Set the image length size */
+ if(!dblock.npages)
+ *image_len = H5EA_DBLOCK_SIZE(&dblock);
+ else
+ *image_len = H5EA_DBLOCK_PREFIX_SIZE(&dblock);
+ } else {
+ HDassert(actual_len);
+ HDassert(*actual_len == *image_len);
+ }
+
+END_FUNC(STATIC) /* end H5EA__cache_dblock_get_load_size() */
-END_FUNC(STATIC) /* end H5EA__cache_sblock_dest() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__cache_dblock_verify_chksum
+ *
+ * Purpose: Verify the computed checksum of the data structure is the
+ * same as the stored chksum.
+ *
+ * Return: Success: TRUE/FALSE
+ * Failure: Negative
+ *
+ * Programmer: Vailin Choi; Aug 2015
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(STATIC, NOERR,
+htri_t, TRUE, -,
+H5EA__cache_dblock_verify_chksum(const void *_image, size_t len, void H5_ATTR_UNUSED *_udata))
+
+ /* Local variables */
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ uint32_t stored_chksum; /* Stored metadata checksum value */
+ uint32_t computed_chksum; /* Computed metadata checksum value */
+
+ /* Check arguments */
+ HDassert(image);
+
+ /* Get stored and computed checksums */
+ H5F_get_checksums(image, len, &stored_chksum, &computed_chksum);
+
+ if(stored_chksum != computed_chksum)
+ ret_value = FALSE;
+
+END_FUNC(STATIC) /* end H5EA__cache_sblock_verify_chksum() */
/*-------------------------------------------------------------------------
- * Function: H5EA__cache_dblock_load
+ * Function: H5EA__cache_dblock_deserialize
*
- * Purpose: Loads an extensible array data block from the disk.
+ * Purpose: Loads a data structure from the disk.
*
- * Return: Success: Pointer to a new extensible array data block
+ * Return: Success: Pointer to a new B-tree.
* Failure: NULL
*
* Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * Sep 16 2008
+ * koziol@hdfgroup.org
+ * July 17, 2013
*
*-------------------------------------------------------------------------
*/
BEGIN_FUNC(STATIC, ERR,
-H5EA_dblock_t *, NULL, NULL,
-H5EA__cache_dblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata))
+void *, NULL, NULL,
+H5EA__cache_dblock_deserialize(const void *_image, size_t len,
+ void *_udata, hbool_t H5_ATTR_UNUSED *dirty))
/* Local variables */
H5EA_dblock_t *dblock = NULL; /* Data block info */
- H5EA_dblock_cache_ud_t *udata = (H5EA_dblock_cache_ud_t *)_udata; /* User data for loading data block */
- size_t size; /* Data block size */
- H5WB_t *wb = NULL; /* Wrapped buffer for data block data */
- uint8_t dblock_buf[H5EA_DBLOCK_BUF_SIZE]; /* Buffer for data block */
- uint8_t *buf; /* Pointer to data block buffer */
- const uint8_t *p; /* Pointer into raw data buffer */
+ H5EA_dblock_cache_ud_t *udata = (H5EA_dblock_cache_ud_t *)_udata; /* User data */
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ uint32_t stored_chksum; /* Stored metadata checksum value */
haddr_t arr_addr; /* Address of array header in the file */
- /* Sanity check */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
- HDassert(udata && udata->hdr && udata->parent && udata->nelmts > 0);
+ /* Check arguments */
+ HDassert(udata);
+ HDassert(udata->hdr);
+ HDassert(udata->parent);
+ HDassert(udata->nelmts > 0);
+ HDassert(H5F_addr_defined(udata->dblk_addr));
/* Allocate the extensible array data block */
if(NULL == (dblock = H5EA__dblock_alloc(udata->hdr, udata->parent, udata->nelmts)))
H5E_THROW(H5E_CANTALLOC, "memory allocation failed for extensible array data block")
- /* Set the extensible array data block's information */
- dblock->addr = addr;
-
- /* Wrap the local buffer for serialized info */
- if(NULL == (wb = H5WB_wrap(dblock_buf, sizeof(dblock_buf))))
- H5E_THROW(H5E_CANTINIT, "can't wrap buffer")
-
- /* Compute the size of the extensible array data block on disk */
- if(!dblock->npages)
- size = H5EA_DBLOCK_SIZE(dblock);
- else
- size = H5EA_DBLOCK_PREFIX_SIZE(dblock);
+ HDassert(((!dblock->npages) && (len == H5EA_DBLOCK_SIZE(dblock))) ||
+ (len == H5EA_DBLOCK_PREFIX_SIZE(dblock)));
- /* Get a pointer to a buffer that's large enough for serialized info */
- if(NULL == (buf = (uint8_t *)H5WB_actual(wb, size)))
- H5E_THROW(H5E_CANTGET, "can't get actual buffer")
-
- /* Read and validate data block from disk */
- if(H5F_read_check_metadata(f, dxpl_id, H5FD_MEM_EARRAY_DBLOCK, H5AC_EARRAY_DBLOCK_ID, addr, size, size, buf) < 0)
- H5E_THROW(H5E_BADVALUE, "incorrect metadata checksum for extensible data block")
-
- /* Get temporary pointer to serialized header */
- p = buf;
+ /* Set the extensible array data block's information */
+ dblock->addr = udata->dblk_addr;
/* Magic number */
- if(HDmemcmp(p, H5EA_DBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC))
+ if(HDmemcmp(image, H5EA_DBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC))
H5E_THROW(H5E_BADVALUE, "wrong extensible array data block signature")
- p += H5_SIZEOF_MAGIC;
+ image += H5_SIZEOF_MAGIC;
/* Version */
- if(*p++ != H5EA_DBLOCK_VERSION)
+ if(*image++ != H5EA_DBLOCK_VERSION)
H5E_THROW(H5E_VERSION, "wrong extensible array data block version")
/* Extensible array type */
- if(*p++ != (uint8_t)udata->hdr->cparam.cls->id)
+ if(*image++ != (uint8_t)udata->hdr->cparam.cls->id)
H5E_THROW(H5E_BADTYPE, "incorrect extensible array class")
/* Address of header for array that owns this block (just for file integrity checks) */
- H5F_addr_decode(f, &p, &arr_addr);
+ H5F_addr_decode(udata->hdr->f, &image, &arr_addr);
if(H5F_addr_ne(arr_addr, udata->hdr->addr))
H5E_THROW(H5E_BADVALUE, "wrong extensible array header address")
/* Offset of block within the array's address space */
- UINT64DECODE_VAR(p, dblock->block_off, udata->hdr->arr_off_size);
+ UINT64DECODE_VAR(image, dblock->block_off, udata->hdr->arr_off_size);
/* Internal information */
@@ -1415,22 +1535,26 @@ H5EA__cache_dblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata))
if(!dblock->npages) {
/* Decode elements in data block */
/* Convert from raw elements on disk into native elements in memory */
- if((udata->hdr->cparam.cls->decode)(p, dblock->elmts, udata->nelmts, udata->hdr->cb_ctx) < 0)
+ if((udata->hdr->cparam.cls->decode)(image, dblock->elmts, udata->nelmts, udata->hdr->cb_ctx) < 0)
H5E_THROW(H5E_CANTDECODE, "can't decode extensible array data elements")
- p += (udata->nelmts * udata->hdr->cparam.raw_elmt_size);
+ image += (udata->nelmts * udata->hdr->cparam.raw_elmt_size);
} /* end if */
/* Sanity check */
/* (allow for checksum not decoded yet) */
- HDassert((size_t)(p - buf) == (size - H5EA_SIZEOF_CHKSUM));
+ HDassert((size_t)(image - (const uint8_t *)_image) == (len - H5EA_SIZEOF_CHKSUM));
/* Set the data block's size */
+ /* (Note: This is not the same as the image length, for paged data blocks) */
dblock->size = H5EA_DBLOCK_SIZE(dblock);
- /* Already decoded and compared stored checksum earlier, when reading */
+ /* checksum verification already done in verify_chksum cb */
+
+ /* Metadata checksum */
+ UINT32DECODE(image, stored_chksum);
/* Sanity check */
- HDassert((size_t)(p - buf) == (size - H5_SIZEOF_CHKSUM));
+ HDassert((size_t)(image - (const uint8_t *)_image) == len);
/* Set return value */
ret_value = dblock;
@@ -1438,151 +1562,116 @@ H5EA__cache_dblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata))
CATCH
/* Release resources */
- if(wb && H5WB_unwrap(wb) < 0)
- H5E_THROW(H5E_CLOSEERROR, "can't close wrapped buffer")
if(!ret_value)
if(dblock && H5EA__dblock_dest(dblock) < 0)
H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array data block")
-END_FUNC(STATIC) /* end H5EA__cache_dblock_load() */
+END_FUNC(STATIC) /* end H5EA__cache_dblock_deserialize() */
/*-------------------------------------------------------------------------
- * Function: H5EA__cache_dblock_flush
+ * Function: H5EA__cache_dblock_image_len
*
- * Purpose: Flushes a dirty extensible array data block to disk.
+ * Purpose: Compute the size of the data structure on disk.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * Sep 18 2008
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * July 17, 2013
*
*-------------------------------------------------------------------------
*/
-BEGIN_FUNC(STATIC, ERR,
-herr_t, SUCCEED, FAIL,
-H5EA__cache_dblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr,
- H5EA_dblock_t *dblock, unsigned H5_ATTR_UNUSED * flags_ptr))
+BEGIN_FUNC(STATIC, NOERR,
+herr_t, SUCCEED, -,
+H5EA__cache_dblock_image_len(const void *_thing, size_t *image_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr))
/* Local variables */
- H5WB_t *wb = NULL; /* Wrapped buffer for serializing data */
- uint8_t ser_buf[H5EA_DBLOCK_BUF_SIZE]; /* Serialization buffer */
+ const H5EA_dblock_t *dblock = (const H5EA_dblock_t *)_thing; /* Pointer to the object */
- /* Sanity check */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
+ /* Check arguments */
HDassert(dblock);
- HDassert(dblock->hdr);
-
- if(dblock->cache_info.is_dirty) {
- uint8_t *buf; /* Temporary raw data buffer */
- uint8_t *p; /* Pointer into raw data buffer */
- size_t size; /* Index block size on disk */
- uint32_t metadata_chksum; /* Computed metadata checksum value */
-
- /* Wrap the local buffer for serialized info */
- if(NULL == (wb = H5WB_wrap(ser_buf, sizeof(ser_buf))))
- H5E_THROW(H5E_CANTINIT, "can't wrap buffer")
-
- /* Compute the size of the data block on disk */
- if(!dblock->npages)
- size = dblock->size;
- else
- size = H5EA_DBLOCK_PREFIX_SIZE(dblock);
-
- /* Get a pointer to a buffer that's large enough for serialized info */
- if(NULL == (buf = (uint8_t *)H5WB_actual(wb, size)))
- H5E_THROW(H5E_CANTGET, "can't get actual buffer")
-
- /* Get temporary pointer to serialized info */
- p = buf;
-
- /* Magic number */
- HDmemcpy(p, H5EA_DBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC);
- p += H5_SIZEOF_MAGIC;
-
- /* Version # */
- *p++ = H5EA_DBLOCK_VERSION;
-
- /* Extensible array type */
- *p++ = dblock->hdr->cparam.cls->id;
+ HDassert(image_len);
- /* Address of array header for array which owns this block */
- H5F_addr_encode(f, &p, dblock->hdr->addr);
-
- /* Offset of block in array */
- UINT64ENCODE_VAR(p, dblock->block_off, dblock->hdr->arr_off_size);
-
- /* Internal information */
-
- /* Only encode elements if the data block is not paged */
- if(!dblock->npages) {
- /* Encode elements in data block */
-
- /* Convert from native elements in memory into raw elements on disk */
- if((dblock->hdr->cparam.cls->encode)(p, dblock->elmts, dblock->nelmts, dblock->hdr->cb_ctx) < 0)
- H5E_THROW(H5E_CANTENCODE, "can't encode extensible array data elements")
- p += (dblock->nelmts * dblock->hdr->cparam.raw_elmt_size);
- } /* end if */
-
- /* Compute metadata checksum */
- metadata_chksum = H5_checksum_metadata(buf, (size_t)(p - buf), 0);
-
- /* Metadata checksum */
- UINT32ENCODE(p, metadata_chksum);
-
- /* Write the data block */
- HDassert((size_t)(p - buf) == size);
- if(H5F_block_write(f, H5FD_MEM_EARRAY_DBLOCK, addr, size, dxpl_id, buf) < 0)
- H5E_THROW(H5E_WRITEERROR, "unable to save extensible array data block to disk")
-
- dblock->cache_info.is_dirty = FALSE;
- } /* end if */
-
- if(destroy)
- if(H5EA__cache_dblock_dest(f, dblock) < 0)
- H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array data block")
-
-CATCH
-
- /* Release resources */
- if(wb && H5WB_unwrap(wb) < 0)
- H5E_THROW(H5E_CLOSEERROR, "can't close wrapped buffer")
+ /* Set the image length size */
+ if(!dblock->npages)
+ *image_len = dblock->size;
+ else
+ *image_len = (size_t)H5EA_DBLOCK_PREFIX_SIZE(dblock);
-END_FUNC(STATIC) /* end H5EA__cache_dblock_flush() */
+END_FUNC(STATIC) /* end H5EA__cache_dblock_image_len() */
/*-------------------------------------------------------------------------
- * Function: H5EA__cache_dblock_clear
+ * Function: H5EA__cache_dblock_serialize
*
- * Purpose: Mark a extensible array data block in memory as non-dirty.
+ * Purpose: Flushes a dirty object to disk.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * Sept 18 2008
+ * koziol@hdfgroup.org
+ * July 17, 2013
*
*-------------------------------------------------------------------------
*/
BEGIN_FUNC(STATIC, ERR,
herr_t, SUCCEED, FAIL,
-H5EA__cache_dblock_clear(H5F_t *f, H5EA_dblock_t *dblock, hbool_t destroy))
+H5EA__cache_dblock_serialize(const H5F_t *f, void *_image, size_t H5_ATTR_UNUSED len,
+ void *_thing))
- /* Sanity check */
+ /* Local variables */
+ H5EA_dblock_t *dblock = (H5EA_dblock_t *)_thing; /* Pointer to the object to serialize */
+ uint8_t *image = (uint8_t *)_image; /* Pointer into raw data buffer */
+ uint32_t metadata_chksum; /* Computed metadata checksum value */
+
+ /* check arguments */
+ HDassert(f);
+ HDassert(image);
HDassert(dblock);
+ HDassert(dblock->hdr);
+
+ /* Magic number */
+ HDmemcpy(image, H5EA_DBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ image += H5_SIZEOF_MAGIC;
- /* Reset the dirty flag */
- dblock->cache_info.is_dirty = FALSE;
+ /* Version # */
+ *image++ = H5EA_DBLOCK_VERSION;
- if(destroy)
- if(H5EA__cache_dblock_dest(f, dblock) < 0)
- H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array data block")
+ /* Extensible array type */
+ *image++ = dblock->hdr->cparam.cls->id;
+
+ /* Address of array header for array which owns this block */
+ H5F_addr_encode(f, &image, dblock->hdr->addr);
+
+ /* Offset of block in array */
+ UINT64ENCODE_VAR(image, dblock->block_off, dblock->hdr->arr_off_size);
+
+ /* Internal information */
+
+ /* Only encode elements if the data block is not paged */
+ if(!dblock->npages) {
+ /* Encode elements in data block */
+
+ /* Convert from native elements in memory into raw elements on disk */
+ if((dblock->hdr->cparam.cls->encode)(image, dblock->elmts, dblock->nelmts, dblock->hdr->cb_ctx) < 0)
+ H5E_THROW(H5E_CANTENCODE, "can't encode extensible array data elements")
+ image += (dblock->nelmts * dblock->hdr->cparam.raw_elmt_size);
+ } /* end if */
+
+ /* Compute metadata checksum */
+ metadata_chksum = H5_checksum_metadata(_image, (size_t)(image - (uint8_t *)_image), 0);
+
+ /* Metadata checksum */
+ UINT32ENCODE(image, metadata_chksum);
+
+ /* Sanity check */
+ HDassert((size_t)(image - (uint8_t *)_image) <= len);
CATCH
-END_FUNC(STATIC) /* end H5EA__cache_dblock_clear() */
+END_FUNC(STATIC) /* end H5EA__cache_dblock_serialize() */
/*-------------------------------------------------------------------------
@@ -1600,9 +1689,12 @@ END_FUNC(STATIC) /* end H5EA__cache_dblock_clear() */
*/
BEGIN_FUNC(STATIC, ERR,
herr_t, SUCCEED, FAIL,
-H5EA__cache_dblock_notify(H5AC_notify_action_t action, H5EA_dblock_t *dblock))
+H5EA__cache_dblock_notify(H5AC_notify_action_t action, void *_thing))
- /* Sanity check */
+ /* Local variables */
+ H5EA_dblock_t *dblock = (H5EA_dblock_t *)_thing; /* Pointer to the object */
+
+ /* Check arguments */
HDassert(dblock);
/* Check if the file was opened with SWMR-write access */
@@ -1610,14 +1702,21 @@ H5EA__cache_dblock_notify(H5AC_notify_action_t action, H5EA_dblock_t *dblock))
/* Determine which action to take */
switch(action) {
case H5AC_NOTIFY_ACTION_AFTER_INSERT:
+ case H5AC_NOTIFY_ACTION_AFTER_LOAD:
/* Create flush dependency on parent */
if(H5EA__create_flush_depend((H5AC_info_t *)dblock->parent, (H5AC_info_t *)dblock) < 0)
H5E_THROW(H5E_CANTDEPEND, "unable to create flush dependency between data block and parent, address = %llu", (unsigned long long)dblock->addr)
break;
- case H5AC_NOTIFY_ACTION_BEFORE_EVICT:
- /* Nothing to do */
- break;
+ case H5AC_NOTIFY_ACTION_AFTER_FLUSH:
+ /* do nothing */
+ break;
+
+ case H5AC_NOTIFY_ACTION_BEFORE_EVICT:
+ /* Destroy flush dependency on parent */
+ if(H5EA__destroy_flush_depend((H5AC_info_t *)dblock->parent, (H5AC_info_t *)dblock) < 0)
+ H5E_THROW(H5E_CANTUNDEPEND, "unable to destroy flush dependency between data block and parent, address = %llu", (unsigned long long)dblock->addr)
+ break;
default:
#ifdef NDEBUG
@@ -1634,165 +1733,214 @@ END_FUNC(STATIC) /* end H5EA__cache_dblock_notify() */
/*-------------------------------------------------------------------------
- * Function: H5EA__cache_dblock_size
+ * Function: H5EA__cache_dblock_free_icr
*
- * Purpose: Compute the size in bytes of a extensible array data block
- * on disk, and return it in *size_ptr. On failure,
- * the value of *size_ptr is undefined.
+ * Purpose: Destroy/release an "in core representation" of a data
+ * structure
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * Sept 18 2008
+ * koziol@hdfgroup.org
+ * July 17, 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(STATIC, ERR,
+herr_t, SUCCEED, FAIL,
+H5EA__cache_dblock_free_icr(void *thing))
+
+ /* Check arguments */
+ HDassert(thing);
+
+ /* Release the extensible array data block */
+ if(H5EA__dblock_dest((H5EA_dblock_t *)thing) < 0)
+ H5E_THROW(H5E_CANTFREE, "can't free extensible array data block")
+
+CATCH
+
+END_FUNC(STATIC) /* end H5EA__cache_dblock_free_icr() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__cache_dblock_fsf_size
+ *
+ * Purpose: Tell the metadata cache the actual amount of file space
+ * to free when a dblock entry is destroyed with the free
+ * file space block set.
+ *
+ * This function is needed when the data block is paged, as
+ * the datablock header and all its pages are allocted as a
+ * single contiguous chunk of file space, and must be
+ * deallocated the same way.
+ *
+ * The size of the chunk of memory in which the dblock
+ * header and all its pages is stored in the size field,
+ * so we simply pass that value back to the cache.
+ *
+ * If the datablock is not paged, then the size field of
+ * the cache_info contains the correct size. However this
+ * value will be the same as the size field, so we return
+ * the contents of the size field to the cache in this case
+ * as well.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: John Mainzer
+ * 12/5/14
*
*-------------------------------------------------------------------------
*/
-/* ARGSUSED */
BEGIN_FUNC(STATIC, NOERR,
herr_t, SUCCEED, -,
-H5EA__cache_dblock_size(const H5F_t H5_ATTR_UNUSED *f, const H5EA_dblock_t *dblock,
- size_t *size_ptr))
+H5EA__cache_dblock_fsf_size(const void *_thing, size_t *fsf_size))
- /* Sanity check */
- HDassert(f);
+ /* Local variables */
+ const H5EA_dblock_t *dblock = (const H5EA_dblock_t *)_thing; /* Pointer to the object */
+
+ /* Check arguments */
HDassert(dblock);
- HDassert(size_ptr);
+ HDassert(dblock->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(dblock->cache_info.type == H5AC_EARRAY_DBLOCK);
+ HDassert(fsf_size);
- /* Set size value */
- if(!dblock->npages)
- *size_ptr = dblock->size;
- else
- *size_ptr = H5EA_DBLOCK_PREFIX_SIZE(dblock);
+ *fsf_size = dblock->size;
-END_FUNC(STATIC) /* end H5EA__cache_dblock_size() */
+END_FUNC(STATIC) /* end H5EA__cache_dblock_fsf_size() */
/*-------------------------------------------------------------------------
- * Function: H5EA__cache_dblock_dest
+ * Function: H5EA__cache_dblk_page_get_load_size
*
- * Purpose: Destroys an extensible array data block in memory.
+ * Purpose: Compute the size of the data structure on disk.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * Sep 18 2008
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * July 17, 2013
*
*-------------------------------------------------------------------------
*/
-/* ARGSUSED */
-BEGIN_FUNC(STATIC, ERR,
-herr_t, SUCCEED, FAIL,
-H5EA__cache_dblock_dest(H5F_t *f, H5EA_dblock_t *dblock))
+BEGIN_FUNC(STATIC, NOERR,
+herr_t, SUCCEED, -,
+H5EA__cache_dblk_page_get_load_size(const void *_image, void *_udata,
+ size_t *image_len, size_t *actual_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr))
- /* Sanity check */
- HDassert(f);
- HDassert(dblock);
+ /* Local variables */
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ H5EA_dblk_page_cache_ud_t *udata = (H5EA_dblk_page_cache_ud_t *)_udata; /* User data */
- /* Verify that data block is clean */
- HDassert(dblock->cache_info.is_dirty == FALSE);
+ /* Check arguments */
+ HDassert(udata);
+ HDassert(udata->hdr);
+ HDassert(image_len);
- /* If we're going to free the space on disk, the address must be valid */
- HDassert(!dblock->cache_info.free_file_space_on_destroy || H5F_addr_defined(dblock->cache_info.addr));
+ if(image == NULL)
+ *image_len = (size_t)H5EA_DBLK_PAGE_SIZE(udata->hdr);
+ else {
+ HDassert(actual_len);
+ HDassert(*actual_len == *image_len);
+ }
- /* Check for freeing file space for extensible array data block */
- if(dblock->cache_info.free_file_space_on_destroy) {
- /* Sanity check address */
- HDassert(H5F_addr_eq(dblock->addr, dblock->cache_info.addr));
+END_FUNC(STATIC) /* end H5EA__cache_dblk_page_get_load_size() */
- /* Release the space on disk */
- /* (Includes space for pages!) */
- /* (XXX: Nasty usage of internal DXPL value! -QAK) */
- if(H5MF_xfree(f, H5FD_MEM_EARRAY_DBLOCK, H5AC_dxpl_id, dblock->cache_info.addr, (hsize_t)dblock->size) < 0)
- H5E_THROW(H5E_CANTFREE, "unable to free extensible array data block")
- } /* end if */
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__cache_dblk_page_verify_chksum
+ *
+ * Purpose: Verify the computed checksum of the data structure is the
+ * same as the stored chksum.
+ *
+ * Return: Success: TRUE/FALSE
+ * Failure: Negative
+ *
+ * Programmer: Vailin Choi; Aug 2015
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(STATIC, NOERR,
+htri_t, TRUE, -,
+H5EA__cache_dblk_page_verify_chksum(const void *_image, size_t len, void H5_ATTR_UNUSED *_udata))
- /* Release the data block */
- if(H5EA__dblock_dest(dblock) < 0)
- H5E_THROW(H5E_CANTFREE, "can't free extensible array data block")
+ /* Local variables */
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ uint32_t stored_chksum; /* Stored metadata checksum value */
+ uint32_t computed_chksum; /* Computed metadata checksum value */
-CATCH
+ /* Check arguments */
+ HDassert(image);
+
+ /* Get stored and computed checksums */
+ H5F_get_checksums(image, len, &stored_chksum, &computed_chksum);
-END_FUNC(STATIC) /* end H5EA__cache_dblock_dest() */
+ if(stored_chksum != computed_chksum)
+ ret_value = FALSE;
+
+END_FUNC(STATIC) /* end H5EA__cache_dblk_page_verify_chksum() */
/*-------------------------------------------------------------------------
- * Function: H5EA__cache_dblk_page_load
+ * Function: H5EA__cache_dblk_page_deserialize
*
- * Purpose: Loads an extensible array data block page from the disk.
+ * Purpose: Loads a data structure from the disk.
*
- * Return: Success: Pointer to a new extensible array data block page
+ * Return: Success: Pointer to a new B-tree.
* Failure: NULL
*
* Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * Nov 20 2008
+ * koziol@hdfgroup.org
+ * July 17, 2013
*
*-------------------------------------------------------------------------
*/
BEGIN_FUNC(STATIC, ERR,
-H5EA_dblk_page_t *, NULL, NULL,
-H5EA__cache_dblk_page_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata))
+void *, NULL, NULL,
+H5EA__cache_dblk_page_deserialize(const void *_image, size_t len,
+ void *_udata, hbool_t H5_ATTR_UNUSED *dirty))
/* Local variables */
H5EA_dblk_page_t *dblk_page = NULL; /* Data block page info */
H5EA_dblk_page_cache_ud_t *udata = (H5EA_dblk_page_cache_ud_t *)_udata; /* User data for loading data block page */
- size_t size; /* Data block page size */
- H5WB_t *wb = NULL; /* Wrapped buffer for data block page data */
- uint8_t dblk_page_buf[H5EA_DBLK_PAGE_BUF_SIZE]; /* Buffer for data block page */
- uint8_t *buf; /* Pointer to data block page buffer */
- const uint8_t *p; /* Pointer into raw data buffer */
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ uint32_t stored_chksum; /* Stored metadata checksum value */
/* Sanity check */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
- HDassert(udata && udata->hdr && udata->parent);
+ HDassert(udata);
+ HDassert(udata->hdr);
+ HDassert(udata->parent);
+ HDassert(H5F_addr_defined(udata->dblk_page_addr));
/* Allocate the extensible array data block page */
if(NULL == (dblk_page = H5EA__dblk_page_alloc(udata->hdr, udata->parent)))
H5E_THROW(H5E_CANTALLOC, "memory allocation failed for extensible array data block page")
- /* Set the extensible array data block's information */
- dblk_page->addr = addr;
-
- /* Wrap the local buffer for serialized info */
- if(NULL == (wb = H5WB_wrap(dblk_page_buf, sizeof(dblk_page_buf))))
- H5E_THROW(H5E_CANTINIT, "can't wrap buffer")
-
- /* Compute the size of the extensible array data block page on disk */
- size = H5EA_DBLK_PAGE_SIZE(udata->hdr);
-
- /* Get a pointer to a buffer that's large enough for serialized info */
- if(NULL == (buf = (uint8_t *)H5WB_actual(wb, size)))
- H5E_THROW(H5E_CANTGET, "can't get actual buffer")
-
- /* Read and validate data block page from disk */
- if(H5F_read_check_metadata(f, dxpl_id, H5FD_MEM_EARRAY_DBLK_PAGE, H5AC_EARRAY_DBLK_PAGE_ID, addr, size, size, buf) < 0)
- H5E_THROW(H5E_BADVALUE, "incorrect metadata checksum for extensible array data block page")
-
- /* Get temporary pointer to serialized header */
- p = buf;
+ /* Set the extensible array data block page's information */
+ dblk_page->addr = udata->dblk_page_addr;
/* Internal information */
/* Decode elements in data block page */
/* Convert from raw elements on disk into native elements in memory */
- if((udata->hdr->cparam.cls->decode)(p, dblk_page->elmts, udata->hdr->dblk_page_nelmts, udata->hdr->cb_ctx) < 0)
+ if((udata->hdr->cparam.cls->decode)(image, dblk_page->elmts, udata->hdr->dblk_page_nelmts, udata->hdr->cb_ctx) < 0)
H5E_THROW(H5E_CANTDECODE, "can't decode extensible array data elements")
- p += (udata->hdr->dblk_page_nelmts * udata->hdr->cparam.raw_elmt_size);
+ image += (udata->hdr->dblk_page_nelmts * udata->hdr->cparam.raw_elmt_size);
/* Sanity check */
/* (allow for checksum not decoded yet) */
- HDassert((size_t)(p - buf) == (size - H5EA_SIZEOF_CHKSUM));
+ HDassert((size_t)(image - (const uint8_t *)_image) == (len - H5EA_SIZEOF_CHKSUM));
/* Set the data block page's size */
- dblk_page->size = size;
+ dblk_page->size = len;
- /* Already decoded and compared stored checksum earlier, when reading */
+ /* checksum verification already done in verify_chksum cb */
+
+ /* Metadata checksum */
+ UINT32DECODE(image, stored_chksum);
/* Sanity check */
- HDassert((size_t)(p - buf) == (dblk_page->size - H5_SIZEOF_CHKSUM));
+ HDassert((size_t)(image - (const uint8_t *)_image) == dblk_page->size);
/* Set return value */
ret_value = dblk_page;
@@ -1800,129 +1948,94 @@ H5EA__cache_dblk_page_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata))
CATCH
/* Release resources */
- if(wb && H5WB_unwrap(wb) < 0)
- H5E_THROW(H5E_CLOSEERROR, "can't close wrapped buffer")
if(!ret_value)
if(dblk_page && H5EA__dblk_page_dest(dblk_page) < 0)
H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array data block page")
-END_FUNC(STATIC) /* end H5EA__cache_dblk_page_load() */
+END_FUNC(STATIC) /* end H5EA__cache_dblk_page_deserialize() */
/*-------------------------------------------------------------------------
- * Function: H5EA__cache_dblk_page_flush
+ * Function: H5EA__cache_dblk_page_image_len
*
- * Purpose: Flushes a dirty extensible array data block page to disk.
+ * Purpose: Compute the size of the data structure on disk.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * Nov 20 2008
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * July 17, 2013
*
*-------------------------------------------------------------------------
*/
-BEGIN_FUNC(STATIC, ERR,
-herr_t, SUCCEED, FAIL,
-H5EA__cache_dblk_page_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr,
- H5EA_dblk_page_t *dblk_page, unsigned H5_ATTR_UNUSED * flags_ptr))
+BEGIN_FUNC(STATIC, NOERR,
+herr_t, SUCCEED, -,
+H5EA__cache_dblk_page_image_len(const void *_thing, size_t *image_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr))
/* Local variables */
- H5WB_t *wb = NULL; /* Wrapped buffer for serializing data */
- uint8_t ser_buf[H5EA_DBLK_PAGE_BUF_SIZE]; /* Serialization buffer */
+ const H5EA_dblk_page_t *dblk_page = (const H5EA_dblk_page_t *)_thing; /* Pointer to the object */
- /* Sanity check */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
+ /* Check arguments */
HDassert(dblk_page);
- HDassert(dblk_page->hdr);
-
- if(dblk_page->cache_info.is_dirty) {
- uint8_t *buf; /* Temporary raw data buffer */
- uint8_t *p; /* Pointer into raw data buffer */
- size_t size; /* Index block size on disk */
- uint32_t metadata_chksum; /* Computed metadata checksum value */
-
- /* Wrap the local buffer for serialized info */
- if(NULL == (wb = H5WB_wrap(ser_buf, sizeof(ser_buf))))
- H5E_THROW(H5E_CANTINIT, "can't wrap buffer")
-
- /* Compute the size of the data block on disk */
- size = dblk_page->size;
-
- /* Get a pointer to a buffer that's large enough for serialized info */
- if(NULL == (buf = (uint8_t *)H5WB_actual(wb, size)))
- H5E_THROW(H5E_CANTGET, "can't get actual buffer")
-
- /* Get temporary pointer to serialized info */
- p = buf;
-
- /* Internal information */
-
- /* Encode elements in data block page */
-
- /* Convert from native elements in memory into raw elements on disk */
- if((dblk_page->hdr->cparam.cls->encode)(p, dblk_page->elmts, dblk_page->hdr->dblk_page_nelmts, dblk_page->hdr->cb_ctx) < 0)
- H5E_THROW(H5E_CANTENCODE, "can't encode extensible array data elements")
- p += (dblk_page->hdr->dblk_page_nelmts * dblk_page->hdr->cparam.raw_elmt_size);
-
- /* Compute metadata checksum */
- metadata_chksum = H5_checksum_metadata(buf, (size_t)(p - buf), 0);
+ HDassert(image_len);
- /* Metadata checksum */
- UINT32ENCODE(p, metadata_chksum);
+ /* Set the image length size */
+ *image_len = dblk_page->size;
- /* Write the data block */
- HDassert((size_t)(p - buf) == size);
- if(H5F_block_write(f, H5FD_MEM_EARRAY_DBLK_PAGE, addr, size, dxpl_id, buf) < 0)
- H5E_THROW(H5E_WRITEERROR, "unable to save extensible array data block page to disk")
-
- dblk_page->cache_info.is_dirty = FALSE;
- } /* end if */
-
- if(destroy)
- if(H5EA__cache_dblk_page_dest(f, dblk_page) < 0)
- H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array data block page")
-
-CATCH
-
- /* Release resources */
- if(wb && H5WB_unwrap(wb) < 0)
- H5E_THROW(H5E_CLOSEERROR, "can't close wrapped buffer")
-
-END_FUNC(STATIC) /* end H5EA__cache_dblk_page_flush() */
+END_FUNC(STATIC) /* end H5EA__cache_dblk_page_image_len() */
/*-------------------------------------------------------------------------
- * Function: H5EA__cache_dblk_page_clear
+ * Function: H5EA__cache_dblk_page_serialize
*
- * Purpose: Mark a extensible array data block page in memory as non-dirty.
+ * Purpose: Flushes a dirty object to disk.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * Nov 20 2008
+ * koziol@hdfgroup.org
+ * July 17, 2013
*
*-------------------------------------------------------------------------
*/
BEGIN_FUNC(STATIC, ERR,
herr_t, SUCCEED, FAIL,
-H5EA__cache_dblk_page_clear(H5F_t *f, H5EA_dblk_page_t *dblk_page, hbool_t destroy))
+H5EA__cache_dblk_page_serialize(const H5F_t *f, void *_image, size_t H5_ATTR_UNUSED len,
+ void *_thing))
- /* Sanity check */
+ /* Local variables */
+ H5EA_dblk_page_t *dblk_page = (H5EA_dblk_page_t *)_thing; /* Pointer to the object to serialize */
+ uint8_t *image = (uint8_t *)_image; /* Pointer into raw data buffer */
+ uint32_t metadata_chksum; /* Computed metadata checksum value */
+
+ /* Check arguments */
+ HDassert(f);
+ HDassert(image);
HDassert(dblk_page);
+ HDassert(dblk_page->hdr);
- /* Reset the dirty flag */
- dblk_page->cache_info.is_dirty = FALSE;
+ /* Internal information */
- if(destroy)
- if(H5EA__cache_dblk_page_dest(f, dblk_page) < 0)
- H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array data block page")
+ /* Encode elements in data block page */
+
+ /* Convert from native elements in memory into raw elements on disk */
+ if((dblk_page->hdr->cparam.cls->encode)(image, dblk_page->elmts, dblk_page->hdr->dblk_page_nelmts, dblk_page->hdr->cb_ctx) < 0)
+ H5E_THROW(H5E_CANTENCODE, "can't encode extensible array data elements")
+ image += (dblk_page->hdr->dblk_page_nelmts * dblk_page->hdr->cparam.raw_elmt_size);
+
+ /* Compute metadata checksum */
+ metadata_chksum = H5_checksum_metadata(_image, (size_t)(image - (uint8_t *)_image), 0);
+
+ /* Metadata checksum */
+ UINT32ENCODE(image, metadata_chksum);
+
+ /* Sanity check */
+ HDassert((size_t)(image - (uint8_t *)_image) <= len);
CATCH
-END_FUNC(STATIC) /* end H5EA__cache_dblk_page_clear() */
+END_FUNC(STATIC) /* end H5EA__cache_dblk_page_serialize() */
/*-------------------------------------------------------------------------
@@ -1940,7 +2053,10 @@ END_FUNC(STATIC) /* end H5EA__cache_dblk_page_clear() */
*/
BEGIN_FUNC(STATIC, ERR,
herr_t, SUCCEED, FAIL,
-H5EA__cache_dblk_page_notify(H5AC_notify_action_t action, H5EA_dblk_page_t *dblk_page))
+H5EA__cache_dblk_page_notify(H5AC_notify_action_t action, void *_thing))
+
+ /* Local variables */
+ H5EA_dblk_page_t *dblk_page = (H5EA_dblk_page_t *)_thing; /* Pointer to the object */
/* Sanity check */
HDassert(dblk_page);
@@ -1950,14 +2066,21 @@ H5EA__cache_dblk_page_notify(H5AC_notify_action_t action, H5EA_dblk_page_t *dblk
/* Determine which action to take */
switch(action) {
case H5AC_NOTIFY_ACTION_AFTER_INSERT:
+ case H5AC_NOTIFY_ACTION_AFTER_LOAD:
/* Create flush dependency on parent */
if(H5EA__create_flush_depend((H5AC_info_t *)dblk_page->parent, (H5AC_info_t *)dblk_page) < 0)
H5E_THROW(H5E_CANTDEPEND, "unable to create flush dependency between data block page and parent, address = %llu", (unsigned long long)dblk_page->addr)
break;
- case H5AC_NOTIFY_ACTION_BEFORE_EVICT:
- /* Nothing to do */
- break;
+ case H5AC_NOTIFY_ACTION_AFTER_FLUSH:
+ /* do nothing */
+ break;
+
+ case H5AC_NOTIFY_ACTION_BEFORE_EVICT:
+ /* Destroy flush dependency on parent */
+ if(H5EA__destroy_flush_depend((H5AC_info_t *)dblk_page->parent, (H5AC_info_t *)dblk_page) < 0)
+ H5E_THROW(H5E_CANTUNDEPEND, "unable to destroy flush dependency between data block page and parent, address = %llu", (unsigned long long)dblk_page->addr)
+ break;
default:
#ifdef NDEBUG
@@ -1974,70 +2097,31 @@ END_FUNC(STATIC) /* end H5EA__cache_dblk_page_notify() */
/*-------------------------------------------------------------------------
- * Function: H5EA__cache_dblk_page_size
- *
- * Purpose: Compute the size in bytes of a extensible array data block page
- * on disk, and return it in *size_ptr. On failure,
- * the value of *size_ptr is undefined.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * Nov 20 2008
- *
- *-------------------------------------------------------------------------
- */
-/* ARGSUSED */
-BEGIN_FUNC(STATIC, NOERR,
-herr_t, SUCCEED, -,
-H5EA__cache_dblk_page_size(const H5F_t H5_ATTR_UNUSED *f, const H5EA_dblk_page_t *dblk_page,
- size_t *size_ptr))
-
- /* Sanity check */
- HDassert(f);
- HDassert(dblk_page);
- HDassert(size_ptr);
-
- /* Set size value */
- *size_ptr = dblk_page->size;
-
-END_FUNC(STATIC) /* end H5EA__cache_dblk_page_size() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5EA__cache_dblk_page_dest
- *
- * Purpose: Destroys an extensible array data block page in memory.
+ * Function: H5EA__cache_dblk_page_free_icr
*
- * Note: Does _not_ free the space for the page on disk, that is
- * handled through the data block that "owns" the page.
+ * Purpose: Destroy/release an "in core representation" of a data
+ * structure
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * Nov 20 2008
+ * koziol@hdfgroup.org
+ * July 17, 2013
*
*-------------------------------------------------------------------------
*/
-/* ARGSUSED */
BEGIN_FUNC(STATIC, ERR,
herr_t, SUCCEED, FAIL,
-H5EA__cache_dblk_page_dest(H5F_t H5_ATTR_UNUSED *f, H5EA_dblk_page_t *dblk_page))
+H5EA__cache_dblk_page_free_icr(void *thing))
- /* Sanity check */
- HDassert(f);
- HDassert(dblk_page);
-
- /* Verify that data block page is clean */
- HDassert(dblk_page->cache_info.is_dirty == FALSE);
+ /* Check arguments */
+ HDassert(thing);
- /* Release the data block page */
- if(H5EA__dblk_page_dest(dblk_page) < 0)
+ /* Release the extensible array data block page */
+ if(H5EA__dblk_page_dest((H5EA_dblk_page_t *)thing) < 0)
H5E_THROW(H5E_CANTFREE, "can't free extensible array data block page")
CATCH
-END_FUNC(STATIC) /* end H5EA__cache_dblk_page_dest() */
+END_FUNC(STATIC) /* end H5EA__cache_dblk_page_free_icr() */
diff --git a/src/H5EAdbg.c b/src/H5EAdbg.c
index ff55722..9c3ce6d 100644
--- a/src/H5EAdbg.c
+++ b/src/H5EAdbg.c
@@ -119,7 +119,7 @@ H5EA__hdr_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent,
} /* end if */
/* Load the extensible array header */
- if(NULL == (hdr = H5EA__hdr_protect(f, dxpl_id, addr, dbg_ctx, H5AC_READ)))
+ if(NULL == (hdr = H5EA__hdr_protect(f, dxpl_id, addr, dbg_ctx, H5AC__READ_ONLY_FLAG)))
H5E_THROW(H5E_CANTPROTECT, "unable to load extensible array header")
/* Print opening message */
@@ -218,14 +218,14 @@ H5EA__iblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t H5_ATTR_UNUSED addr, FILE *s
} /* end if */
/* Load the extensible array header */
- if(NULL == (hdr = H5EA__hdr_protect(f, dxpl_id, hdr_addr, dbg_ctx, H5AC_READ)))
+ if(NULL == (hdr = H5EA__hdr_protect(f, dxpl_id, hdr_addr, dbg_ctx, H5AC__READ_ONLY_FLAG)))
H5E_THROW(H5E_CANTPROTECT, "unable to load extensible array header")
/* Sanity check */
HDassert(H5F_addr_eq(hdr->idx_blk_addr, addr));
/* Protect index block */
- if(NULL == (iblock = H5EA__iblock_protect(hdr, dxpl_id, H5AC_READ)))
+ if(NULL == (iblock = H5EA__iblock_protect(hdr, dxpl_id, H5AC__READ_ONLY_FLAG)))
H5E_THROW(H5E_CANTPROTECT, "unable to protect extensible array index block, address = %llu", (unsigned long long)hdr->idx_blk_addr)
/* Print opening message */
@@ -343,12 +343,12 @@ H5EA__sblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int inde
} /* end if */
/* Load the extensible array header */
- if(NULL == (hdr = H5EA__hdr_protect(f, dxpl_id, hdr_addr, dbg_ctx, H5AC_READ)))
+ if(NULL == (hdr = H5EA__hdr_protect(f, dxpl_id, hdr_addr, dbg_ctx, H5AC__READ_ONLY_FLAG)))
H5E_THROW(H5E_CANTPROTECT, "unable to load extensible array header")
/* Protect super block */
/* (Note: setting parent of super block to 'hdr' for this operation should be OK -QAK) */
- if(NULL == (sblock = H5EA__sblock_protect(hdr, dxpl_id, (H5EA_iblock_t *)hdr, addr, sblk_idx, H5AC_READ)))
+ if(NULL == (sblock = H5EA__sblock_protect(hdr, dxpl_id, (H5EA_iblock_t *)hdr, addr, sblk_idx, H5AC__READ_ONLY_FLAG)))
H5E_THROW(H5E_CANTPROTECT, "unable to protect extensible array super block, address = %llu", (unsigned long long)addr)
/* Print opening message */
@@ -437,12 +437,12 @@ H5EA__dblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int inde
} /* end if */
/* Load the extensible array header */
- if(NULL == (hdr = H5EA__hdr_protect(f, dxpl_id, hdr_addr, dbg_ctx, H5AC_READ)))
+ if(NULL == (hdr = H5EA__hdr_protect(f, dxpl_id, hdr_addr, dbg_ctx, H5AC__READ_ONLY_FLAG)))
H5E_THROW(H5E_CANTPROTECT, "unable to load extensible array header")
/* Protect data block */
/* (Note: setting parent of data block to 'hdr' for this operation should be OK -QAK) */
- if(NULL == (dblock = H5EA__dblock_protect(hdr, dxpl_id, hdr, addr, dblk_nelmts, H5AC_READ)))
+ if(NULL == (dblock = H5EA__dblock_protect(hdr, dxpl_id, hdr, addr, dblk_nelmts, H5AC__READ_ONLY_FLAG)))
H5E_THROW(H5E_CANTPROTECT, "unable to protect extensible array data block, address = %llu", (unsigned long long)addr)
/* Print opening message */
diff --git a/src/H5EAdblkpage.c b/src/H5EAdblkpage.c
index 37fd68b..5d188c2 100644
--- a/src/H5EAdblkpage.c
+++ b/src/H5EAdblkpage.c
@@ -210,7 +210,7 @@ END_FUNC(PKG) /* end H5EA__dblk_page_create() */
BEGIN_FUNC(PKG, ERR,
H5EA_dblk_page_t *, NULL, NULL,
H5EA__dblk_page_protect(H5EA_hdr_t *hdr, hid_t dxpl_id, H5EA_sblock_t *parent,
- haddr_t dblk_page_addr, H5AC_protect_t rw))
+ haddr_t dblk_page_addr, unsigned flags))
/* Local variables */
H5EA_dblk_page_cache_ud_t udata; /* Information needed for loading data block page */
@@ -223,12 +223,16 @@ HDfprintf(stderr, "%s: Called\n", FUNC);
HDassert(hdr);
HDassert(H5F_addr_defined(dblk_page_addr));
+ /* only the H5AC__READ_ONLY_FLAG may be set */
+ HDassert((flags & (unsigned)(~H5AC__READ_ONLY_FLAG)) == 0);
+
/* Set up user data */
udata.hdr = hdr;
udata.parent = parent;
+ udata.dblk_page_addr = dblk_page_addr;
/* Protect the data block page */
- if(NULL == (ret_value = (H5EA_dblk_page_t *)H5AC_protect(hdr->f, dxpl_id, H5AC_EARRAY_DBLK_PAGE, dblk_page_addr, &udata, rw)))
+ if(NULL == (ret_value = (H5EA_dblk_page_t *)H5AC_protect(hdr->f, dxpl_id, H5AC_EARRAY_DBLK_PAGE, dblk_page_addr, &udata, flags)))
H5E_THROW(H5E_CANTPROTECT, "unable to protect extensible array data block page, address = %llu", (unsigned long long)dblk_page_addr)
CATCH
diff --git a/src/H5EAdblock.c b/src/H5EAdblock.c
index dd1e7b0..24be87a 100644
--- a/src/H5EAdblock.c
+++ b/src/H5EAdblock.c
@@ -304,7 +304,7 @@ END_FUNC(PKG) /* end H5EA__dblock_sblk_idx() */
BEGIN_FUNC(PKG, ERR,
H5EA_dblock_t *, NULL, NULL,
H5EA__dblock_protect(H5EA_hdr_t *hdr, hid_t dxpl_id, void *parent,
- haddr_t dblk_addr, size_t dblk_nelmts, H5AC_protect_t rw))
+ haddr_t dblk_addr, size_t dblk_nelmts, unsigned flags))
/* Local variables */
H5EA_dblock_cache_ud_t udata; /* Information needed for loading data block */
@@ -318,13 +318,17 @@ HDfprintf(stderr, "%s: Called\n", FUNC);
HDassert(H5F_addr_defined(dblk_addr));
HDassert(dblk_nelmts);
+ /* only the H5AC__READ_ONLY_FLAG may be set */
+ HDassert((flags & (unsigned)(~H5AC__READ_ONLY_FLAG)) == 0);
+
/* Set up user data */
udata.hdr = hdr;
udata.parent = parent;
udata.nelmts = dblk_nelmts;
+ udata.dblk_addr = dblk_addr;
/* Protect the data block */
- if(NULL == (ret_value = (H5EA_dblock_t *)H5AC_protect(hdr->f, dxpl_id, H5AC_EARRAY_DBLOCK, dblk_addr, &udata, rw)))
+ if(NULL == (ret_value = (H5EA_dblock_t *)H5AC_protect(hdr->f, dxpl_id, H5AC_EARRAY_DBLOCK, dblk_addr, &udata, flags)))
H5E_THROW(H5E_CANTPROTECT, "unable to protect extensible array data block, address = %llu", (unsigned long long)dblk_addr)
CATCH
@@ -399,7 +403,7 @@ HDfprintf(stderr, "%s: Called\n", FUNC);
HDassert(dblk_nelmts > 0);
/* Protect data block */
- if(NULL == (dblock = H5EA__dblock_protect(hdr, dxpl_id, parent, dblk_addr, dblk_nelmts, H5AC_WRITE)))
+ if(NULL == (dblock = H5EA__dblock_protect(hdr, dxpl_id, parent, dblk_addr, dblk_nelmts, H5AC__NO_FLAGS_SET)))
H5E_THROW(H5E_CANTPROTECT, "unable to protect extensible array data block, address = %llu", (unsigned long long)dblk_addr)
/* Check if this is a paged data block */
diff --git a/src/H5EAhdr.c b/src/H5EAhdr.c
index 0b8f4bf..e82ad7f 100644
--- a/src/H5EAhdr.c
+++ b/src/H5EAhdr.c
@@ -628,16 +628,25 @@ END_FUNC(PKG) /* end H5EA__hdr_modified() */
BEGIN_FUNC(PKG, ERR,
H5EA_hdr_t *, NULL, NULL,
H5EA__hdr_protect(H5F_t *f, hid_t dxpl_id, haddr_t ea_addr, void *ctx_udata,
- H5AC_protect_t rw))
+ unsigned flags))
/* Local variables */
+ H5EA_hdr_cache_ud_t udata; /* User data for cache callbacks */
/* Sanity check */
HDassert(f);
HDassert(H5F_addr_defined(ea_addr));
+ /* only the H5AC__READ_ONLY_FLAG may appear in flags */
+ HDassert((flags & (unsigned)(~H5AC__READ_ONLY_FLAG)) == 0);
+
+ /* Set up user data for cache callbacks */
+ udata.f = f;
+ udata.addr = ea_addr;
+ udata.ctx_udata = ctx_udata;
+
/* Protect the header */
- if(NULL == (ret_value = (H5EA_hdr_t *)H5AC_protect(f, dxpl_id, H5AC_EARRAY_HDR, ea_addr, ctx_udata, rw)))
+ if(NULL == (ret_value = (H5EA_hdr_t *)H5AC_protect(f, dxpl_id, H5AC_EARRAY_HDR, ea_addr, &udata, flags)))
H5E_THROW(H5E_CANTPROTECT, "unable to protect extensible array header, address = %llu", (unsigned long long)ea_addr)
CATCH
diff --git a/src/H5EAiblock.c b/src/H5EAiblock.c
index 3c2894a..364b443 100644
--- a/src/H5EAiblock.c
+++ b/src/H5EAiblock.c
@@ -279,7 +279,7 @@ END_FUNC(PKG) /* end H5EA__iblock_create() */
*/
BEGIN_FUNC(PKG, ERR,
H5EA_iblock_t *, NULL, NULL,
-H5EA__iblock_protect(H5EA_hdr_t *hdr, hid_t dxpl_id, H5AC_protect_t rw))
+H5EA__iblock_protect(H5EA_hdr_t *hdr, hid_t dxpl_id, unsigned flags))
#ifdef QAK
HDfprintf(stderr, "%s: Called\n", FUNC);
@@ -288,8 +288,11 @@ HDfprintf(stderr, "%s: Called\n", FUNC);
/* Sanity check */
HDassert(hdr);
+ /* only the H5AC__READ_ONLY_FLAG may be set */
+ HDassert((flags & (unsigned)(~H5AC__READ_ONLY_FLAG)) == 0);
+
/* Protect the index block */
- if(NULL == (ret_value = (H5EA_iblock_t *)H5AC_protect(hdr->f, dxpl_id, H5AC_EARRAY_IBLOCK, hdr->idx_blk_addr, hdr, rw)))
+ if(NULL == (ret_value = (H5EA_iblock_t *)H5AC_protect(hdr->f, dxpl_id, H5AC_EARRAY_IBLOCK, hdr->idx_blk_addr, hdr, flags)))
H5E_THROW(H5E_CANTPROTECT, "unable to protect extensible array index block, address = %llu", (unsigned long long)hdr->idx_blk_addr)
CATCH
@@ -361,7 +364,7 @@ HDfprintf(stderr, "%s: Called\n", FUNC);
HDassert(H5F_addr_defined(hdr->idx_blk_addr));
/* Protect index block */
- if(NULL == (iblock = H5EA__iblock_protect(hdr, dxpl_id, H5AC_WRITE)))
+ if(NULL == (iblock = H5EA__iblock_protect(hdr, dxpl_id, H5AC__NO_FLAGS_SET)))
H5E_THROW(H5E_CANTPROTECT, "unable to protect extensible array index block, address = %llu", (unsigned long long)hdr->idx_blk_addr)
/* Check for index block having data block pointers */
@@ -436,7 +439,6 @@ H5EA__iblock_dest(H5EA_iblock_t *iblock))
/* Sanity check */
HDassert(iblock);
- HDassert(iblock->rc == 0);
/* Check if shared header field has been initialized */
if(iblock->hdr) {
diff --git a/src/H5EApkg.h b/src/H5EApkg.h
index 4df40f6..993a9e1 100644
--- a/src/H5EApkg.h
+++ b/src/H5EApkg.h
@@ -230,7 +230,6 @@ typedef struct H5EA_iblock_t {
haddr_t *sblk_addrs; /* Buffer for addresses of super blocks in index block */
/* Internal array information (not stored) */
- size_t rc; /* Reference count of objects using this block */
H5EA_hdr_t *hdr; /* Shared array header info */
haddr_t addr; /* Address of this index block on disk */
size_t size; /* Size of index block on disk */
@@ -252,7 +251,6 @@ typedef struct H5EA_sblock_t {
uint8_t *page_init; /* Bitmap of whether a data block page is initialized */
/* Internal array information (not stored) */
- size_t rc; /* Reference count of objects using this block */
H5EA_hdr_t *hdr; /* Shared array header info */
H5EA_iblock_t *parent; /* Parent object for super block (index block) */
haddr_t addr; /* Address of this index block on disk */
@@ -313,11 +311,19 @@ struct H5EA_t {
/* Metadata cache callback user data types */
+/* Info needed for loading header */
+typedef struct H5EA_hdr_cache_ud_t {
+ H5F_t *f; /* Pointer to file for extensible array */
+ haddr_t addr; /* Address of header on disk */
+ void *ctx_udata; /* User context for class */
+} H5EA_hdr_cache_ud_t;
+
/* Info needed for loading super block */
typedef struct H5EA_sblock_cache_ud_t {
H5EA_hdr_t *hdr; /* Shared extensible array information */
H5EA_iblock_t *parent; /* Pointer to parent object for super block (index block) */
unsigned sblk_idx; /* Index of super block */
+ haddr_t sblk_addr; /* Address of super block */
} H5EA_sblock_cache_ud_t;
/* Info needed for loading data block */
@@ -325,12 +331,14 @@ typedef struct H5EA_dblock_cache_ud_t {
H5EA_hdr_t *hdr; /* Shared extensible array information */
void *parent; /* Pointer to parent object for data block (index or super block) */
size_t nelmts; /* Number of elements in data block */
+ haddr_t dblk_addr; /* Address of data block */
} H5EA_dblock_cache_ud_t;
/* Info needed for loading data block page */
typedef struct H5EA_dblk_page_cache_ud_t {
H5EA_hdr_t *hdr; /* Shared extensible array information */
H5EA_sblock_t *parent; /* Pointer to parent object for data block page (super block) */
+ haddr_t dblk_page_addr; /* Address of data block page */
} H5EA_dblk_page_cache_ud_t;
#ifdef H5EA_TESTING
@@ -389,7 +397,7 @@ H5_DLL herr_t H5EA__hdr_fuse_incr(H5EA_hdr_t *hdr);
H5_DLL size_t H5EA__hdr_fuse_decr(H5EA_hdr_t *hdr);
H5_DLL herr_t H5EA__hdr_modified(H5EA_hdr_t *hdr);
H5_DLL H5EA_hdr_t *H5EA__hdr_protect(H5F_t *f, hid_t dxpl_id, haddr_t ea_addr,
- void *ctx_udata, H5AC_protect_t rw);
+ void *ctx_udata, unsigned flags);
H5_DLL herr_t H5EA__hdr_unprotect(H5EA_hdr_t *hdr, hid_t dxpl_id, unsigned cache_flags);
H5_DLL herr_t H5EA__hdr_delete(H5EA_hdr_t *hdr, hid_t dxpl_id);
H5_DLL herr_t H5EA__hdr_dest(H5EA_hdr_t *hdr);
@@ -399,7 +407,7 @@ H5_DLL H5EA_iblock_t *H5EA__iblock_alloc(H5EA_hdr_t *hdr);
H5_DLL haddr_t H5EA__iblock_create(H5EA_hdr_t *hdr, hid_t dxpl_id,
hbool_t *stats_changed);
H5_DLL H5EA_iblock_t *H5EA__iblock_protect(H5EA_hdr_t *hdr, hid_t dxpl_id,
- H5AC_protect_t rw);
+ unsigned flags);
H5_DLL herr_t H5EA__iblock_unprotect(H5EA_iblock_t *iblock, hid_t dxpl_id,
unsigned cache_flags);
H5_DLL herr_t H5EA__iblock_delete(H5EA_hdr_t *hdr, hid_t dxpl_id);
@@ -411,7 +419,8 @@ H5_DLL H5EA_sblock_t *H5EA__sblock_alloc(H5EA_hdr_t *hdr, H5EA_iblock_t *parent,
H5_DLL haddr_t H5EA__sblock_create(H5EA_hdr_t *hdr, hid_t dxpl_id,
H5EA_iblock_t *parent, hbool_t *stats_changed, unsigned sblk_idx);
H5_DLL H5EA_sblock_t *H5EA__sblock_protect(H5EA_hdr_t *hdr, hid_t dxpl_id,
- H5EA_iblock_t *parent, haddr_t sblk_addr, unsigned sblk_idx, H5AC_protect_t rw);
+ H5EA_iblock_t *parent, haddr_t sblk_addr, unsigned sblk_idx,
+ unsigned flags);
H5_DLL herr_t H5EA__sblock_unprotect(H5EA_sblock_t *sblock, hid_t dxpl_id,
unsigned cache_flags);
H5_DLL herr_t H5EA__sblock_delete(H5EA_hdr_t *hdr, hid_t dxpl_id,
@@ -425,7 +434,7 @@ H5_DLL haddr_t H5EA__dblock_create(H5EA_hdr_t *hdr, hid_t dxpl_id, void *parent,
hbool_t *stats_changed, hsize_t dblk_off, size_t nelmts);
H5_DLL unsigned H5EA__dblock_sblk_idx(const H5EA_hdr_t *hdr, hsize_t idx);
H5_DLL H5EA_dblock_t *H5EA__dblock_protect(H5EA_hdr_t *hdr, hid_t dxpl_id,
- void *parent, haddr_t dblk_addr, size_t dblk_nelmts, H5AC_protect_t rw);
+ void *parent, haddr_t dblk_addr, size_t dblk_nelmts, unsigned flags);
H5_DLL herr_t H5EA__dblock_unprotect(H5EA_dblock_t *dblock, hid_t dxpl_id,
unsigned cache_flags);
H5_DLL herr_t H5EA__dblock_delete(H5EA_hdr_t *hdr, hid_t dxpl_id, void *parent,
@@ -437,7 +446,7 @@ H5_DLL H5EA_dblk_page_t *H5EA__dblk_page_alloc(H5EA_hdr_t *hdr, H5EA_sblock_t *p
H5_DLL herr_t H5EA__dblk_page_create(H5EA_hdr_t *hdr, hid_t dxpl_id,
H5EA_sblock_t *parent, haddr_t addr);
H5_DLL H5EA_dblk_page_t *H5EA__dblk_page_protect(H5EA_hdr_t *hdr, hid_t dxpl_id,
- H5EA_sblock_t *parent, haddr_t dblk_page_addr, H5AC_protect_t rw);
+ H5EA_sblock_t *parent, haddr_t dblk_page_addr, unsigned flags);
H5_DLL herr_t H5EA__dblk_page_unprotect(H5EA_dblk_page_t *dblk_page,
hid_t dxpl_id, unsigned cache_flags);
H5_DLL herr_t H5EA__dblk_page_dest(H5EA_dblk_page_t *dblk_page);
diff --git a/src/H5EAsblock.c b/src/H5EAsblock.c
index 1cc8bd9..33f34c9 100644
--- a/src/H5EAsblock.c
+++ b/src/H5EAsblock.c
@@ -276,7 +276,7 @@ END_FUNC(PKG) /* end H5EA__sblock_create() */
BEGIN_FUNC(PKG, ERR,
H5EA_sblock_t *, NULL, NULL,
H5EA__sblock_protect(H5EA_hdr_t *hdr, hid_t dxpl_id, H5EA_iblock_t *parent,
- haddr_t sblk_addr, unsigned sblk_idx, H5AC_protect_t rw))
+ haddr_t sblk_addr, unsigned sblk_idx, unsigned flags))
/* Local variables */
H5EA_sblock_cache_ud_t udata; /* Information needed for loading super block */
@@ -290,13 +290,17 @@ HDfprintf(stderr, "%s: Called\n", FUNC);
HDassert(hdr);
HDassert(H5F_addr_defined(sblk_addr));
+ /* only the H5AC__READ_ONLY_FLAG may be set */
+ HDassert((flags & (unsigned)(~H5AC__READ_ONLY_FLAG)) == 0);
+
/* Set up user data */
udata.hdr = hdr;
udata.parent = parent;
udata.sblk_idx = sblk_idx;
+ udata.sblk_addr = sblk_addr;
/* Protect the super block */
- if(NULL == (ret_value = (H5EA_sblock_t *)H5AC_protect(hdr->f, dxpl_id, H5AC_EARRAY_SBLOCK, sblk_addr, &udata, rw)))
+ if(NULL == (ret_value = (H5EA_sblock_t *)H5AC_protect(hdr->f, dxpl_id, H5AC_EARRAY_SBLOCK, sblk_addr, &udata, flags)))
H5E_THROW(H5E_CANTPROTECT, "unable to protect extensible array super block, address = %llu", (unsigned long long)sblk_addr)
CATCH
@@ -370,7 +374,7 @@ HDfprintf(stderr, "%s: Called\n", FUNC);
HDassert(H5F_addr_defined(sblk_addr));
/* Protect super block */
- if(NULL == (sblock = H5EA__sblock_protect(hdr, dxpl_id, parent, sblk_addr, sblk_idx, H5AC_WRITE)))
+ if(NULL == (sblock = H5EA__sblock_protect(hdr, dxpl_id, parent, sblk_addr, sblk_idx, H5AC__NO_FLAGS_SET)))
H5E_THROW(H5E_CANTPROTECT, "unable to protect extensible array super block, address = %llu", (unsigned long long)sblk_addr)
/* Iterate over data blocks */
@@ -412,7 +416,6 @@ H5EA__sblock_dest(H5EA_sblock_t *sblock))
/* Sanity check */
HDassert(sblock);
- HDassert(sblock->rc == 0);
#ifdef QAK
HDfprintf(stderr, "%s: sblock->hdr->dblk_page_nelmts = %Zu, sblock->ndblks = %Zu, sblock->dblk_nelmts = %Zu\n", FUNC, sblock->hdr->dblk_page_nelmts, sblock->ndblks, sblock->dblk_nelmts);
#endif /* QAK */
diff --git a/src/H5FA.c b/src/H5FA.c
index 3120588..bd4a162 100644
--- a/src/H5FA.c
+++ b/src/H5FA.c
@@ -143,7 +143,7 @@ HDfprintf(stderr, "%s: Called\n", FUNC);
H5E_THROW(H5E_CANTALLOC, "memory allocation failed for fixed array info")
/* Lock the array header into memory */
- if(NULL == (hdr = H5FA__hdr_protect(f, dxpl_id, fa_addr, ctx_udata, H5AC_WRITE)))
+ if(NULL == (hdr = H5FA__hdr_protect(f, dxpl_id, fa_addr, ctx_udata, H5AC__NO_FLAGS_SET)))
H5E_THROW(H5E_CANTPROTECT, "unable to load fixed array header")
/* Point fixed array wrapper at header and bump it's ref count */
@@ -203,7 +203,7 @@ H5FA_open(H5F_t *f, hid_t dxpl_id, haddr_t fa_addr, void *ctx_udata))
#ifdef H5FA_DEBUG
HDfprintf(stderr, "%s: fa_addr = %a\n", FUNC, fa_addr);
#endif /* H5FA_DEBUG */
- if(NULL == (hdr = H5FA__hdr_protect(f, dxpl_id, fa_addr, ctx_udata, H5AC_READ)))
+ if(NULL == (hdr = H5FA__hdr_protect(f, dxpl_id, fa_addr, ctx_udata, H5AC__READ_ONLY_FLAG)))
H5E_THROW(H5E_CANTPROTECT, "unable to load fixed array header, address = %llu", (unsigned long long)fa_addr)
/* Check for pending array deletion */
@@ -361,7 +361,7 @@ HDfprintf(stderr, "%s: fixed array data block address not defined!\n", FUNC, idx
HDassert(idx < hdr->cparam.nelmts);
/* Protect data block */
- if(NULL == (dblock = H5FA__dblock_protect(hdr, dxpl_id, hdr->dblk_addr, H5AC_WRITE)))
+ if(NULL == (dblock = H5FA__dblock_protect(hdr, dxpl_id, hdr->dblk_addr, H5AC__NO_FLAGS_SET)))
H5E_THROW(H5E_CANTPROTECT, "unable to protect fixed array data block, address = %llu", (unsigned long long)hdr->dblk_addr)
/* Check for paging data block */
@@ -402,8 +402,8 @@ HDfprintf(stderr, "%s: fixed array data block address not defined!\n", FUNC, idx
} /* end if */
/* Protect the data block page */
- if(NULL == (dblk_page = H5FA__dblk_page_protect(hdr, dxpl_id, dblk_page_addr, dblk_page_nelmts, H5AC_WRITE)))
- H5E_THROW(H5E_CANTPROTECT, "unable to protect fixed array data block page, address = %llu", (unsigned long long)dblk_page_addr)
+ if(NULL == (dblk_page = H5FA__dblk_page_protect(hdr, dxpl_id, dblk_page_addr, dblk_page_nelmts, H5AC__NO_FLAGS_SET)))
+ H5E_THROW(H5E_CANTPROTECT, "unable to protect fixed array data block page, address = %llu", (unsigned long long)dblk_page_addr)
/* Set the element in the data block page */
HDmemcpy(((uint8_t *)dblk_page->elmts) + (hdr->cparam.cls->nat_elmt_size * elmt_idx), elmt, hdr->cparam.cls->nat_elmt_size);
@@ -469,7 +469,7 @@ HDfprintf(stderr, "%s: Index %Hu\n", FUNC, idx);
else {
/* Get the data block */
HDassert(H5F_addr_defined(hdr->dblk_addr));
- if(NULL == (dblock = H5FA__dblock_protect(hdr, dxpl_id, hdr->dblk_addr, H5AC_READ)))
+ if(NULL == (dblock = H5FA__dblock_protect(hdr, dxpl_id, hdr->dblk_addr, H5AC__READ_ONLY_FLAG)))
H5E_THROW(H5E_CANTPROTECT, "unable to protect fixed array data block, address = %llu", (unsigned long long)hdr->dblk_addr)
/* Check for paged data block */
@@ -509,7 +509,7 @@ HDfprintf(stderr, "%s: Index %Hu\n", FUNC, idx);
dblk_page_nelmts = dblock->dblk_page_nelmts;
/* Protect the data block page */
- if(NULL == (dblk_page = H5FA__dblk_page_protect(hdr, dxpl_id, dblk_page_addr, dblk_page_nelmts, H5AC_READ)))
+ if(NULL == (dblk_page = H5FA__dblk_page_protect(hdr, dxpl_id, dblk_page_addr, dblk_page_nelmts, H5AC__READ_ONLY_FLAG)))
H5E_THROW(H5E_CANTPROTECT, "unable to protect fixed array data block page, address = %llu", (unsigned long long)dblk_page_addr)
/* Retrieve element from data block */
@@ -594,7 +594,7 @@ HDfprintf(stderr, "%s: Called\n", FUNC);
/* Lock the array header into memory */
/* (OK to pass in NULL for callback context, since we know the header must be in the cache) */
- if(NULL == (hdr = H5FA__hdr_protect(fa->f, dxpl_id, fa_addr, NULL, H5AC_WRITE)))
+ if(NULL == (hdr = H5FA__hdr_protect(fa->f, dxpl_id, fa_addr, NULL, H5AC__NO_FLAGS_SET)))
H5E_THROW(H5E_CANTLOAD, "unable to load fixed array header")
/* Set the shared array header's file context for this operation */
@@ -657,7 +657,7 @@ H5FA_delete(H5F_t *f, hid_t dxpl_id, haddr_t fa_addr, void *ctx_udata))
#ifdef H5FA_DEBUG
HDfprintf(stderr, "%s: fa_addr = %a\n", FUNC, fa_addr);
#endif /* H5FA_DEBUG */
- if(NULL == (hdr = H5FA__hdr_protect(f, dxpl_id, fa_addr, ctx_udata, H5AC_WRITE)))
+ if(NULL == (hdr = H5FA__hdr_protect(f, dxpl_id, fa_addr, ctx_udata, H5AC__NO_FLAGS_SET)))
H5E_THROW(H5E_CANTPROTECT, "unable to protect fixed array header, address = %llu", (unsigned long long)fa_addr)
/* Check for files using shared array header */
diff --git a/src/H5FAcache.c b/src/H5FAcache.c
index bbfd94e..64d5e60 100644
--- a/src/H5FAcache.c
+++ b/src/H5FAcache.c
@@ -55,11 +55,6 @@
#define H5FA_HDR_VERSION 0 /* Header */
#define H5FA_DBLOCK_VERSION 0 /* Data block */
-/* Size of stack buffer for serialization buffers */
-#define H5FA_HDR_BUF_SIZE 512
-#define H5FA_DBLOCK_BUF_SIZE 512
-#define H5FA_DBLK_PAGE_BUF_SIZE 512
-
/******************/
/* Local Typedefs */
@@ -76,24 +71,45 @@
/********************/
/* Metadata cache (H5AC) callbacks */
-static H5FA_hdr_t *H5FA__cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata);
-static herr_t H5FA__cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5FA_hdr_t *hdr, unsigned * flags_ptr);
-static herr_t H5FA__cache_hdr_dest(H5F_t *f, H5FA_hdr_t *hdr);
-static herr_t H5FA__cache_hdr_clear(H5F_t *f, H5FA_hdr_t *hdr, hbool_t destroy);
-static herr_t H5FA__cache_hdr_size(const H5F_t *f, const H5FA_hdr_t *hdr, size_t *size_ptr);
-
-static H5FA_dblock_t *H5FA__cache_dblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata);
-static herr_t H5FA__cache_dblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5FA_dblock_t *dblock, unsigned * flags_ptr);
-static herr_t H5FA__cache_dblock_dest(H5F_t *f, H5FA_dblock_t *dblock);
-static herr_t H5FA__cache_dblock_clear(H5F_t *f, H5FA_dblock_t *dblock, hbool_t destroy);
-static herr_t H5FA__cache_dblock_notify(H5AC_notify_action_t action, H5FA_dblock_t *dblock);
-static herr_t H5FA__cache_dblock_size(const H5F_t *f, const H5FA_dblock_t *dblock, size_t *size_ptr);
-
-static H5FA_dblk_page_t *H5FA__cache_dblk_page_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata);
-static herr_t H5FA__cache_dblk_page_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5FA_dblk_page_t *dblk_page, unsigned * flags_ptr);
-static herr_t H5FA__cache_dblk_page_dest(H5F_t *f, H5FA_dblk_page_t *dblk_page);
-static herr_t H5FA__cache_dblk_page_clear(H5F_t *f, H5FA_dblk_page_t *dblk_page, hbool_t destroy);
-static herr_t H5FA__cache_dblk_page_size(const H5F_t *f, const H5FA_dblk_page_t *dblk_page, size_t *size_ptr);
+static herr_t H5FA__cache_hdr_get_load_size(const void *image_ptr, void *udata,
+ size_t *image_len, size_t *actual_len,
+ hbool_t *compressed_ptr, size_t *compressed_image_len_ptr);
+static htri_t H5FA__cache_hdr_verify_chksum(const void *image_ptr, size_t len, void *udata_ptr);
+static void *H5FA__cache_hdr_deserialize(const void *image, size_t len,
+ void *udata, hbool_t *dirty);
+static herr_t H5FA__cache_hdr_image_len(const void *thing, size_t *image_len,
+ hbool_t *compressed_ptr, size_t *compressed_image_len_ptr);
+static herr_t H5FA__cache_hdr_serialize(const H5F_t *f, void *image, size_t len,
+ void *thing);
+static herr_t H5FA__cache_hdr_free_icr(void *thing);
+
+static herr_t H5FA__cache_dblock_get_load_size(const void *image_ptr, void *udata,
+ size_t *image_len, size_t *actual_len,
+ hbool_t *compressed_ptr, size_t *compressed_image_len_ptr);
+static htri_t H5FA__cache_dblock_verify_chksum(const void *image_ptr, size_t len, void *udata_ptr);
+static void *H5FA__cache_dblock_deserialize(const void *image, size_t len,
+ void *udata, hbool_t *dirty);
+static herr_t H5FA__cache_dblock_image_len(const void *thing,
+ size_t *image_len, hbool_t *compressed_ptr,
+ size_t *compressed_image_len_ptr);
+static herr_t H5FA__cache_dblock_serialize(const H5F_t *f, void *image, size_t len,
+ void *thing);
+static herr_t H5FA__cache_dblock_notify(H5AC_notify_action_t action, void *thing);
+static herr_t H5FA__cache_dblock_free_icr(void *thing);
+static herr_t H5FA__cache_dblock_fsf_size(const void *thing, size_t *fsf_size);
+
+static herr_t H5FA__cache_dblk_page_get_load_size(const void *image_ptr, void *udata,
+ size_t *image_len, size_t *actual_len,
+ hbool_t *compressed_ptr, size_t *compressed_image_len_ptr);
+static htri_t H5FA__cache_dblk_page_verify_chksum(const void *image_ptr, size_t len, void *udata_ptr);
+static void *H5FA__cache_dblk_page_deserialize(const void *image, size_t len,
+ void *udata, hbool_t *dirty);
+static herr_t H5FA__cache_dblk_page_image_len(const void *thing,
+ size_t *image_len, hbool_t *compressed_ptr,
+ size_t *compressed_image_len_ptr);
+static herr_t H5FA__cache_dblk_page_serialize(const H5F_t *f, void *image, size_t len,
+ void *thing);
+static herr_t H5FA__cache_dblk_page_free_icr(void *thing);
/*********************/
@@ -102,36 +118,56 @@ static herr_t H5FA__cache_dblk_page_size(const H5F_t *f, const H5FA_dblk_page_t
/* H5FA header inherits cache-like properties from H5AC */
const H5AC_class_t H5AC_FARRAY_HDR[1] = {{
- H5AC_FARRAY_HDR_ID,
- (H5AC_load_func_t)H5FA__cache_hdr_load,
- (H5AC_flush_func_t)H5FA__cache_hdr_flush,
- (H5AC_dest_func_t)H5FA__cache_hdr_dest,
- (H5AC_clear_func_t)H5FA__cache_hdr_clear,
- (H5AC_notify_func_t)NULL,
- (H5AC_size_func_t)H5FA__cache_hdr_size,
+ H5AC_FARRAY_HDR_ID, /* Metadata client ID */
+ "Fixed-array Header", /* Metadata client name (for debugging) */
+ H5FD_MEM_FARRAY_HDR, /* File space memory type for client */
+ H5AC__CLASS_NO_FLAGS_SET, /* Client class behavior flags */
+ H5FA__cache_hdr_get_load_size, /* 'get_load_size' callback */
+ H5FA__cache_hdr_verify_chksum, /* 'verify_chksum' callback */
+ H5FA__cache_hdr_deserialize, /* 'deserialize' callback */
+ H5FA__cache_hdr_image_len, /* 'image_len' callback */
+ NULL, /* 'pre_serialize' callback */
+ H5FA__cache_hdr_serialize, /* 'serialize' callback */
+ NULL, /* 'notify' callback */
+ H5FA__cache_hdr_free_icr, /* 'free_icr' callback */
+ NULL, /* 'clear' callback */
+ NULL, /* 'fsf_size' callback */
}};
-
/* H5FA data block inherits cache-like properties from H5AC */
const H5AC_class_t H5AC_FARRAY_DBLOCK[1] = {{
- H5AC_FARRAY_DBLOCK_ID,
- (H5AC_load_func_t)H5FA__cache_dblock_load,
- (H5AC_flush_func_t)H5FA__cache_dblock_flush,
- (H5AC_dest_func_t)H5FA__cache_dblock_dest,
- (H5AC_clear_func_t)H5FA__cache_dblock_clear,
- (H5AC_notify_func_t)H5FA__cache_dblock_notify,
- (H5AC_size_func_t)H5FA__cache_dblock_size,
+ H5AC_FARRAY_DBLOCK_ID, /* Metadata client ID */
+ "Fixed Array Data Block", /* Metadata client name (for debugging) */
+ H5FD_MEM_FARRAY_DBLOCK, /* File space memory type for client */
+ H5AC__CLASS_NO_FLAGS_SET, /* Client class behavior flags */
+ H5FA__cache_dblock_get_load_size, /* 'get_load_size' callback */
+ H5FA__cache_dblock_verify_chksum, /* 'verify_chksum' callback */
+ H5FA__cache_dblock_deserialize, /* 'deserialize' callback */
+ H5FA__cache_dblock_image_len, /* 'image_len' callback */
+ NULL, /* 'pre_serialize' callback */
+ H5FA__cache_dblock_serialize, /* 'serialize' callback */
+ H5FA__cache_dblock_notify, /* 'notify' callback */
+ H5FA__cache_dblock_free_icr, /* 'free_icr' callback */
+ NULL, /* 'clear' callback */
+ H5FA__cache_dblock_fsf_size, /* 'fsf_size' callback */
}};
/* H5FA data block page inherits cache-like properties from H5AC */
const H5AC_class_t H5AC_FARRAY_DBLK_PAGE[1] = {{
- H5AC_FARRAY_DBLK_PAGE_ID,
- (H5AC_load_func_t)H5FA__cache_dblk_page_load,
- (H5AC_flush_func_t)H5FA__cache_dblk_page_flush,
- (H5AC_dest_func_t)H5FA__cache_dblk_page_dest,
- (H5AC_clear_func_t)H5FA__cache_dblk_page_clear,
- (H5AC_notify_func_t)NULL,
- (H5AC_size_func_t)H5FA__cache_dblk_page_size,
+ H5AC_FARRAY_DBLK_PAGE_ID, /* Metadata client ID */
+ "Fixed Array Data Block Page", /* Metadata client name (for debugging) */
+ H5FD_MEM_FARRAY_DBLK_PAGE, /* File space memory type for client */
+ H5AC__CLASS_NO_FLAGS_SET, /* Client class behavior flags */
+ H5FA__cache_dblk_page_get_load_size, /* 'get_load_size' callback */
+ H5FA__cache_dblk_page_verify_chksum, /* 'verify_chksum' callback */
+ H5FA__cache_dblk_page_deserialize, /* 'deserialize' callback */
+ H5FA__cache_dblk_page_image_len, /* 'image_len' callback */
+ NULL, /* 'pre_serialize' callback */
+ H5FA__cache_dblk_page_serialize, /* 'serialize' callback */
+ NULL, /* 'notify' callback */
+ H5FA__cache_dblk_page_free_icr, /* 'free_icr' callback */
+ NULL, /* 'clear' callback */
+ NULL, /* 'fsf_size' callback */
}};
@@ -147,87 +183,142 @@ const H5AC_class_t H5AC_FARRAY_DBLK_PAGE[1] = {{
/*-------------------------------------------------------------------------
- * Function: H5FA__cache_hdr_load
+ * Function: H5FA__cache_hdr_get_load_size
*
- * Purpose: Loads a fixed array header from the disk.
+ * Purpose: Compute the size of the data structure on disk.
*
- * Return: Success: Pointer to a new fixed array
- * Failure: NULL
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Vailin Choi
- * Thursday, April 30, 2009
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * July 31, 2013
*
*-------------------------------------------------------------------------
*/
-BEGIN_FUNC(STATIC, ERR,
-H5FA_hdr_t *, NULL, NULL,
-H5FA__cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata))
+BEGIN_FUNC(STATIC, NOERR,
+herr_t, SUCCEED, -,
+H5FA__cache_hdr_get_load_size(const void *_image, void *_udata,
+ size_t *image_len, size_t *actual_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr))
/* Local variables */
- H5FA_cls_id_t id; /* ID of fixed array class, as found in file */
- H5FA_hdr_t *hdr = NULL; /* Fixed array info */
- size_t size; /* Header size */
- H5WB_t *wb = NULL; /* Wrapped buffer for header data */
- uint8_t hdr_buf[H5FA_HDR_BUF_SIZE]; /* Buffer for header */
- uint8_t *buf; /* Pointer to header buffer */
- const uint8_t *p; /* Pointer into raw data buffer */
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ H5FA_hdr_cache_ud_t *udata = (H5FA_hdr_cache_ud_t *)_udata; /* User data for callback */
/* Check arguments */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
+ HDassert(udata);
+ HDassert(udata->f);
+ HDassert(image_len);
- /* Allocate space for the fixed array data structure */
- if(NULL == (hdr = H5FA__hdr_alloc(f)))
- H5E_THROW(H5E_CANTALLOC, "memory allocation failed for fixed array shared header")
+ if(image == NULL) {
+ /* Set the image length size */
+ *image_len = (size_t)H5FA_HEADER_SIZE_FILE(udata->f);
+ } else {
+ HDassert(actual_len);
+ HDassert(*actual_len == *image_len);
+ }
- /* Set the fixed array header's address */
- hdr->addr = addr;
+END_FUNC(STATIC) /* end H5FA__cache_hdr_get_load_size() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FA__cache_hdr_verify_chksum
+ *
+ * Purpose: Verify the computed checksum of the data structure is the
+ * same as the stored chksum.
+ *
+ * Return: Success: TRUE/FALSE
+ * Failure: Negative
+ *
+ * Programmer: Vailin Choi; Aug 2015
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(STATIC, NOERR,
+htri_t, TRUE, -,
+H5FA__cache_hdr_verify_chksum(const void *_image, size_t len, void H5_ATTR_UNUSED *_udata))
+
+ /* Local variables */
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ uint32_t stored_chksum; /* Stored metadata checksum value */
+ uint32_t computed_chksum; /* Computed metadata checksum value */
- /* Wrap the local buffer for serialized info */
- if(NULL == (wb = H5WB_wrap(hdr_buf, sizeof(hdr_buf))))
- H5E_THROW(H5E_CANTINIT, "can't wrap buffer")
+ /* Check arguments */
+ HDassert(image);
- /* Compute the 'base' size of the fixed array header on disk */
- size = H5FA_HEADER_SIZE_HDR(hdr);
+ /* Get stored and computed checksums */
+ H5F_get_checksums(image, len, &stored_chksum, &computed_chksum);
- /* Get a pointer to a buffer that's large enough for serialized header */
- if(NULL == (buf = (uint8_t *)H5WB_actual(wb, size)))
- H5E_THROW(H5E_CANTGET, "can't get actual buffer")
+ if(stored_chksum != computed_chksum)
+ ret_value = FALSE;
- /* Read and vaildate header from disk */
- if(H5F_read_check_metadata(f, dxpl_id, H5FD_MEM_FARRAY_HDR, H5AC_FARRAY_HDR_ID, addr, size, size, buf) < 0)
- H5E_THROW(H5E_BADVALUE, "incorrect metadata checksum for fixed array header")
+END_FUNC(STATIC) /* end H5FA__cache_hdr_verify_chksum() */
- /* Get temporary pointer to serialized header */
- p = buf;
+
+/*-------------------------------------------------------------------------
+ * Function: H5FA__cache_hdr_deserialize
+ *
+ * Purpose: Loads a data structure from the disk.
+ *
+ * Return: Success: Pointer to a new Fixed array
+ * Failure: NULL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * August 12, 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(STATIC, ERR,
+void *, NULL, NULL,
+H5FA__cache_hdr_deserialize(const void *_image, size_t len,
+ void *_udata, hbool_t H5_ATTR_UNUSED *dirty))
+
+ /* Local variables */
+ H5FA_cls_id_t id; /* ID of fixed array class, as found in file */
+ H5FA_hdr_t *hdr = NULL; /* Fixed array info */
+ H5FA_hdr_cache_ud_t *udata = (H5FA_hdr_cache_ud_t *)_udata;
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ uint32_t stored_chksum; /* Stored metadata checksum value */
+
+ /* Check arguments */
+ HDassert(udata);
+ HDassert(udata->f);
+ HDassert(H5F_addr_defined(udata->addr));
+
+ /* Allocate space for the fixed array data structure */
+ if(NULL == (hdr = H5FA__hdr_alloc(udata->f)))
+ H5E_THROW(H5E_CANTALLOC, "memory allocation failed for fixed array shared header")
+
+ /* Set the fixed array header's address */
+ hdr->addr = udata->addr;
/* Magic number */
- if(HDmemcmp(p, H5FA_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC))
+ if(HDmemcmp(image, H5FA_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC))
H5E_THROW(H5E_BADVALUE, "wrong fixed array header signature")
- p += H5_SIZEOF_MAGIC;
+ image += H5_SIZEOF_MAGIC;
/* Version */
- if(*p++ != H5FA_HDR_VERSION)
+ if(*image++ != H5FA_HDR_VERSION)
H5E_THROW(H5E_VERSION, "wrong fixed array header version")
/* Fixed array class */
- id = (H5FA_cls_id_t)*p++;
+ id = (H5FA_cls_id_t)*image++;
if(id >= H5FA_NUM_CLS_ID)
H5E_THROW(H5E_BADTYPE, "incorrect fixed array class")
hdr->cparam.cls = H5FA_client_class_g[id];
/* General array creation/configuration information */
- hdr->cparam.raw_elmt_size = *p++; /* Element size in file (in bytes) */
- hdr->cparam.max_dblk_page_nelmts_bits = *p++; /* Log2(Max. # of elements in data block page) -
- * i.e. # of bits needed to store max. # of
- * elements in data block page.
- */
+ hdr->cparam.raw_elmt_size = *image++; /* Element size in file (in bytes) */
+ hdr->cparam.max_dblk_page_nelmts_bits = *image++; /* Log2(Max. # of elements in data block page) -
+ i.e. # of bits needed to store max. # of
+ elements in data block page. */
/* Array statistics */
- H5F_DECODE_LENGTH(f, p, hdr->cparam.nelmts); /* Number of elements */
+ H5F_DECODE_LENGTH(udata->f, image, hdr->cparam.nelmts); /* Number of elements */
/* Internal information */
- H5F_addr_decode(f, &p, &hdr->dblk_addr); /* Address of index block */
+ H5F_addr_decode(udata->f, &image, &hdr->dblk_addr); /* Address of index block */
/* Check for data block */
if(H5F_addr_defined(hdr->dblk_addr)) {
@@ -250,17 +341,20 @@ H5FA__cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata))
/* Sanity check */
/* (allow for checksum not decoded yet) */
- HDassert((size_t)(p - buf) == (size - H5FA_SIZEOF_CHKSUM));
+ HDassert((size_t)(image - (const uint8_t *)_image) == (len - H5FA_SIZEOF_CHKSUM));
- /* Already decoded and compared stored checksum earlier, when reading */
+ /* checksum verification already done in verify_chksum cb */
+
+ /* Metadata checksum */
+ UINT32DECODE(image, stored_chksum);
/* Sanity check */
- HDassert((size_t)(p - buf) == (size - H5_SIZEOF_CHKSUM));
+ HDassert((size_t)(image - (const uint8_t *)_image) == len);
/* Finish initializing fixed array header */
- if(H5FA__hdr_init(hdr, udata) < 0)
+ if(H5FA__hdr_init(hdr, udata->ctx_udata) < 0)
H5E_THROW(H5E_CANTINIT, "initialization failed for fixed array header")
- HDassert(hdr->size == size);
+ HDassert(hdr->size == len);
/* Set return value */
ret_value = hdr;
@@ -268,521 +362,439 @@ H5FA__cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata))
CATCH
/* Release resources */
- if(wb && H5WB_unwrap(wb) < 0)
- H5E_THROW(H5E_CLOSEERROR, "can't close wrapped buffer")
if(!ret_value)
if(hdr && H5FA__hdr_dest(hdr) < 0)
H5E_THROW(H5E_CANTFREE, "unable to destroy fixed array header")
-END_FUNC(STATIC) /* end H5FA__cache_hdr_load() */
+END_FUNC(STATIC) /* end H5FA__cache_hdr_deserialize() */
/*-------------------------------------------------------------------------
- * Function: H5FA__cache_hdr_flush
+ * Function: H5FA__cache_hdr_image_len
*
- * Purpose: Flushes a dirty fixed array header to disk.
+ * Purpose: Compute the size of the data structure on disk.
*
- * Return: SUCCEED/FAIL
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Vailin Choi
- * Thursday, April 30, 2009
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * August 12, 2013
*
*-------------------------------------------------------------------------
*/
-BEGIN_FUNC(STATIC, ERR,
-herr_t, SUCCEED, FAIL,
-H5FA__cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr,
- H5FA_hdr_t *hdr, unsigned H5_ATTR_UNUSED * flags_ptr))
+BEGIN_FUNC(STATIC, NOERR,
+herr_t, SUCCEED, -,
+H5FA__cache_hdr_image_len(const void *_thing, size_t *image_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr))
- H5WB_t *wb = NULL; /* Wrapped buffer for header data */
- uint8_t hdr_buf[H5FA_HDR_BUF_SIZE]; /* Buffer for header */
+ /* Local variables */
+ const H5FA_hdr_t *hdr = (const H5FA_hdr_t *)_thing; /* Pointer to the object */
- /* check arguments */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
+ /* Check arguments */
HDassert(hdr);
+ HDassert(image_len);
- if(hdr->cache_info.is_dirty) {
- uint8_t *buf; /* Temporary raw data buffer */
- uint8_t *p; /* Pointer into raw data buffer */
- size_t size; /* Header size on disk */
- uint32_t metadata_chksum; /* Computed metadata checksum value */
-
- /* Wrap the local buffer for serialized header info */
- if(NULL == (wb = H5WB_wrap(hdr_buf, sizeof(hdr_buf))))
- H5E_THROW(H5E_CANTINIT, "can't wrap buffer")
-
- /* Compute the size of the array header on disk */
- size = hdr->size;
-
- /* Get a pointer to a buffer that's large enough for serialized header */
- if(NULL == (buf = (uint8_t *)H5WB_actual(wb, size)))
- H5E_THROW(H5E_CANTGET, "can't get actual buffer")
+ /* Set the image length size */
+ *image_len = hdr->size;
- /* Get temporary pointer to serialized header */
- p = buf;
+END_FUNC(STATIC) /* end H5FA__cache_hdr_image_len() */
- /* Magic number */
- HDmemcpy(p, H5FA_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC);
- p += H5_SIZEOF_MAGIC;
-
- /* Version # */
- *p++ = H5FA_HDR_VERSION;
+
+/*-------------------------------------------------------------------------
+ * Function: H5FA__cache_hdr_serialize
+ *
+ * Purpose: Flushes a dirty object to disk.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * August 12, 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(STATIC, NOERR,
+herr_t, SUCCEED, -,
+H5FA__cache_hdr_serialize(const H5F_t *f, void *_image, size_t H5_ATTR_UNUSED len,
+ void *_thing))
- /* Fixed array type */
- *p++ = hdr->cparam.cls->id;
+ /* Local variables */
+ H5FA_hdr_t *hdr = (H5FA_hdr_t *)_thing; /* Pointer to the fixed array header */
+ uint8_t *image = (uint8_t *)_image; /* Pointer into raw data buffer */
+ uint32_t metadata_chksum; /* Computed metadata checksum value */
- /* General array creation/configuration information */
- *p++ = hdr->cparam.raw_elmt_size; /* Element size in file (in bytes) */
- *p++ = hdr->cparam.max_dblk_page_nelmts_bits; /* Log2(Max. # of elements in data block page) - i.e. # of bits needed to store max. # of elements in data block page */
+ /* check arguments */
+ HDassert(f);
+ HDassert(image);
+ HDassert(hdr);
- /* Array statistics */
- H5F_ENCODE_LENGTH(f, p, hdr->stats.nelmts); /* Number of elements for the fixed array */
+ /* Magic number */
+ HDmemcpy(image, H5FA_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ image += H5_SIZEOF_MAGIC;
- /* Internal information */
- H5F_addr_encode(f, &p, hdr->dblk_addr); /* Address of fixed array data block */
+ /* Version # */
+ *image++ = H5FA_HDR_VERSION;
- /* Compute metadata checksum */
- metadata_chksum = H5_checksum_metadata(buf, (size_t)(p - buf), 0);
+ /* Fixed array type */
+ *image++ = hdr->cparam.cls->id;
- /* Metadata checksum */
- UINT32ENCODE(p, metadata_chksum);
+ /* General array creation/configuration information */
+ *image++ = hdr->cparam.raw_elmt_size; /* Element size in file (in bytes) */
+ *image++ = hdr->cparam.max_dblk_page_nelmts_bits; /* Log2(Max. # of elements in data block page) - i.e. # of bits needed to store max. # of elements in data block page */
- /* Write the array header. */
- HDassert((size_t)(p - buf) == size);
- if(H5F_block_write(f, H5FD_MEM_FARRAY_HDR, addr, size, dxpl_id, buf) < 0)
- H5E_THROW(H5E_WRITEERROR, "unable to save fixed array header to disk")
+ /* Array statistics */
+ H5F_ENCODE_LENGTH(f, image, hdr->stats.nelmts); /* Number of elements for the fixed array */
- hdr->cache_info.is_dirty = FALSE;
- } /* end if */
+ /* Internal information */
+ H5F_addr_encode(f, &image, hdr->dblk_addr); /* Address of fixed array data block */
- if(destroy)
- if(H5FA__cache_hdr_dest(f, hdr) < 0)
- H5E_THROW(H5E_CANTFREE, "unable to destroy fixed array header")
+ /* Compute metadata checksum */
+ metadata_chksum = H5_checksum_metadata(_image, (size_t)(image - (uint8_t *)_image), 0);
-CATCH
+ /* Metadata checksum */
+ UINT32ENCODE(image, metadata_chksum);
- /* Release resources */
- if(wb && H5WB_unwrap(wb) < 0)
- H5E_THROW(H5E_CLOSEERROR, "can't close wrapped buffer")
+ /* Sanity check */
+ HDassert((size_t)(image - (uint8_t *)_image) <= len);
-END_FUNC(STATIC) /* end H5FA__cache_hdr_flush() */
+END_FUNC(STATIC) /* end H5FA__cache_hdr_serialize() */
/*-------------------------------------------------------------------------
- * Function: H5FA__cache_hdr_dest
+ * Function: H5FA__cache_hdr_free_icr
*
- * Purpose: Destroys a fixed array header in memory.
+ * Purpose: Destroy/release an "in core representation" of a data
+ * structure
*
* Return: SUCCEED/FAIL
*
- * Programmer: Vailin Choi
- * Thursday, April 30, 2009
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * August 12, 2013
*
*-------------------------------------------------------------------------
*/
/* ARGSUSED */
BEGIN_FUNC(STATIC, ERR,
herr_t, SUCCEED, FAIL,
-H5FA__cache_hdr_dest(H5F_t *f, H5FA_hdr_t *hdr))
+H5FA__cache_hdr_free_icr(void *thing))
/* Check arguments */
- HDassert(f);
- HDassert(hdr);
-
- /* Verify that header is clean */
- HDassert(hdr->cache_info.is_dirty == FALSE);
-
- /* If we're going to free the space on disk, the address must be valid */
- HDassert(!hdr->cache_info.free_file_space_on_destroy || H5F_addr_defined(hdr->cache_info.addr));
-
- /* Check for freeing file space for fixed array header */
- if(hdr->cache_info.free_file_space_on_destroy) {
- /* Sanity check address */
- HDassert(H5F_addr_eq(hdr->addr, hdr->cache_info.addr));
+ HDassert(thing);
- /* Release the space on disk */
- /* (XXX: Nasty usage of internal DXPL value! -QAK) */
- if(H5MF_xfree(f, H5FD_MEM_FARRAY_HDR, H5AC_dxpl_id, hdr->cache_info.addr, (hsize_t)hdr->size) < 0)
- H5E_THROW(H5E_CANTFREE, "unable to free fixed array header")
- } /* end if */
-
- /* Release the fixed array header */
- if(H5FA__hdr_dest(hdr) < 0)
+ /* Release the extensible array header */
+ if(H5FA__hdr_dest((H5FA_hdr_t *)thing) < 0)
H5E_THROW(H5E_CANTFREE, "can't free fixed array header")
CATCH
-END_FUNC(STATIC) /* end H5FA__cache_hdr_dest() */
+END_FUNC(STATIC) /* end H5FA__cache_hdr_free_icr() */
/*-------------------------------------------------------------------------
- * Function: H5FA__cache_hdr_clear
+ * Function: H5FA__cache_dblock_get_load_size
*
- * Purpose: Mark a fixed array header in memory as non-dirty.
+ * Purpose: Compute the size of the data structure on disk.
*
- * Return: SUCCEED/FAIL
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Vailin Choi
- * Thursday, April 30, 2009
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * August 12, 2013
*
*-------------------------------------------------------------------------
*/
-BEGIN_FUNC(STATIC, ERR,
-herr_t, SUCCEED, FAIL,
-H5FA__cache_hdr_clear(H5F_t *f, H5FA_hdr_t *hdr, hbool_t destroy))
-
- /* Sanity check */
- HDassert(hdr);
-
- /* Reset the dirty flag. */
- hdr->cache_info.is_dirty = FALSE;
-
- if(destroy)
- if(H5FA__cache_hdr_dest(f, hdr) < 0)
- H5E_THROW(H5E_CANTFREE, "unable to destroy fixed array header")
+BEGIN_FUNC(STATIC, NOERR,
+herr_t, SUCCEED, -,
+H5FA__cache_dblock_get_load_size(const void *_image, void *_udata,
+ size_t *image_len, size_t *actual_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr))
-CATCH
+ /* Local variables */
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ H5FA_dblock_cache_ud_t *udata = (H5FA_dblock_cache_ud_t *)_udata; /* User data */
+ H5FA_dblock_t dblock; /* Fake data block for computing size */
+ size_t dblk_page_nelmts; /* # of elements per data block page */
-END_FUNC(STATIC) /* end H5FA__cache_hdr_clear() */
+ /* Check arguments */
+ HDassert(udata);
+ HDassert(udata->hdr);
+ HDassert(image_len);
+
+ if(image == NULL) {
+
+ /* Set up fake data block for computing size on disk */
+ /* (Note: extracted from H5FA__dblock_alloc) */
+ HDmemset(&dblock, 0, sizeof(dblock));
+
+ /* Set up fake data block for computing size on disk
+ *
+ * need: dblock->hdr
+ * dblock->npages
+ * dblock->dblk_page_init_size
+ */
+
+ dblock.hdr = udata->hdr;
+ dblk_page_nelmts = (size_t)1 << udata->hdr->cparam.max_dblk_page_nelmts_bits;
+ if(udata->hdr->cparam.nelmts > dblk_page_nelmts) {
+ dblock.npages = (size_t)(((udata->hdr->cparam.nelmts + dblk_page_nelmts) - 1) / dblk_page_nelmts);
+ dblock.dblk_page_init_size = (dblock.npages + 7) / 8;
+ } /* end if */
+
+ /* Set the image length size */
+ if(!dblock.npages)
+ *image_len = (size_t)H5FA_DBLOCK_SIZE(&dblock);
+ else
+ *image_len = (size_t)H5FA_DBLOCK_PREFIX_SIZE(&dblock);
+ } else {
+ HDassert(actual_len);
+ HDassert(*actual_len == *image_len);
+ }
+
+END_FUNC(STATIC) /* end H5FA__cache_dblock_get_load_size() */
/*-------------------------------------------------------------------------
- * Function: H5FA__cache_hdr_size
+ * Function: H5FA__cache_dblock_verify_chksum
*
- * Purpose: Compute the size in bytes of a fixed array header
- * on disk, and return it in *size_ptr. On failure,
- * the value of *size_ptr is undefined.
+ * Purpose: Verify the computed checksum of the data structure is the
+ * same as the stored chksum.
*
- * Return: SUCCEED/FAIL
+ * Return: Success: TRUE/FALSE
+ * Failure: Negative
*
- * Programmer: Vailin Choi
- * Thursday, April 30, 2009
+ * Programmer: Vailin Choi; Aug 2015
*
*-------------------------------------------------------------------------
*/
-/* ARGSUSED */
BEGIN_FUNC(STATIC, NOERR,
-herr_t, SUCCEED, -,
-H5FA__cache_hdr_size(const H5F_t H5_ATTR_UNUSED *f, const H5FA_hdr_t *hdr,
- size_t *size_ptr))
+htri_t, TRUE, -,
+H5FA__cache_dblock_verify_chksum(const void *_image, size_t len, void H5_ATTR_UNUSED *_udata))
- /* Sanity check */
- HDassert(f);
- HDassert(hdr);
- HDassert(size_ptr);
+ /* Local variables */
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ uint32_t stored_chksum; /* Stored metadata checksum value */
+ uint32_t computed_chksum; /* Computed metadata checksum value */
+
+ /* Check arguments */
+ HDassert(image);
+
+ /* Get stored and computed checksums */
+ H5F_get_checksums(image, len, &stored_chksum, &computed_chksum);
- /* Set size value */
- *size_ptr = hdr->size;
+ if(stored_chksum != computed_chksum)
+ ret_value = FALSE;
-END_FUNC(STATIC) /* end H5FA__cache_hdr_size() */
+END_FUNC(STATIC) /* end H5FA__cache_dblock_verify_chksum() */
/*-------------------------------------------------------------------------
- * Function: H5FA__cache_dblock_load
+ * Function: H5FA__cache_dblock_deserialize
*
- * Purpose: Loads a fixed array data block from the disk.
+ * Purpose: Loads a data structure from the disk.
*
- * Return: Success: Pointer to a new fixed array data block
- * Failure: NULL
+ * Return: Success: Pointer to a new B-tree.
+ * Failure: NULL
*
- * Programmer: Vailin Choi
- * Thursday, April 30, 2009
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * August 14, 2013
*
*-------------------------------------------------------------------------
*/
BEGIN_FUNC(STATIC, ERR,
-H5FA_dblock_t *, NULL, NULL,
-H5FA__cache_dblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata))
+void *, NULL, NULL,
+H5FA__cache_dblock_deserialize(const void *_image, size_t len,
+ void *_udata, hbool_t H5_ATTR_UNUSED *dirty))
/* Local variables */
H5FA_dblock_t *dblock = NULL; /* Data block info */
H5FA_dblock_cache_ud_t *udata = (H5FA_dblock_cache_ud_t *)_udata; /* User data for loading data block */
- size_t size; /* Data block size */
- H5WB_t *wb = NULL; /* Wrapped buffer for data block data */
- uint8_t dblock_buf[H5FA_DBLOCK_BUF_SIZE]; /* Buffer for data block */
- uint8_t *buf; /* Pointer to data block buffer */
- const uint8_t *p; /* Pointer into raw data buffer */
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ uint32_t stored_chksum; /* Stored metadata checksum value */
haddr_t arr_addr; /* Address of array header in the file */
/* Sanity check */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
- HDassert(udata && udata->hdr);
+ HDassert(udata);
+ HDassert(udata->hdr);
/* Allocate the fixed array data block */
if(NULL == (dblock = H5FA__dblock_alloc(udata->hdr)))
H5E_THROW(H5E_CANTALLOC, "memory allocation failed for fixed array data block")
- /* Set the fixed array data block's information */
- dblock->addr = addr;
-
- /* Wrap the local buffer for serialized info */
- if(NULL == (wb = H5WB_wrap(dblock_buf, sizeof(dblock_buf))))
- H5E_THROW(H5E_CANTINIT, "can't wrap buffer")
-
- /* Compute the size of the fixed array data block on disk */
- if(!dblock->npages)
- size = (size_t)H5FA_DBLOCK_SIZE(dblock);
- else
- size = H5FA_DBLOCK_PREFIX_SIZE(dblock);
+ HDassert(((!dblock->npages) && (len == (size_t)H5FA_DBLOCK_SIZE(dblock)))
+ || (len == (size_t)H5FA_DBLOCK_PREFIX_SIZE(dblock)));
- /* Get a pointer to a buffer that's large enough for serialized info */
- if(NULL == (buf = (uint8_t *)H5WB_actual(wb, size)))
- H5E_THROW(H5E_CANTGET, "can't get actual buffer")
-
- /* Read and validate data block from disk */
- if(H5F_read_check_metadata(f, dxpl_id, H5FD_MEM_FARRAY_DBLOCK, H5AC_FARRAY_DBLOCK_ID, addr, size, size, buf) < 0)
- H5E_THROW(H5E_BADVALUE, "incorrect metadata checksum for fixed array data block")
-
- /* Get temporary pointer to serialized header */
- p = buf;
+ /* Set the fixed array data block's information */
+ dblock->addr = udata->dblk_addr;
/* Magic number */
- if(HDmemcmp(p, H5FA_DBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC))
+ if(HDmemcmp(image, H5FA_DBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC))
H5E_THROW(H5E_BADVALUE, "wrong fixed array data block signature")
- p += H5_SIZEOF_MAGIC;
+ image += H5_SIZEOF_MAGIC;
/* Version */
- if(*p++ != H5FA_DBLOCK_VERSION)
+ if(*image++ != H5FA_DBLOCK_VERSION)
H5E_THROW(H5E_VERSION, "wrong fixed array data block version")
/* Fixed array type */
- if(*p++ != (uint8_t)udata->hdr->cparam.cls->id)
+ if(*image++ != (uint8_t)udata->hdr->cparam.cls->id)
H5E_THROW(H5E_BADTYPE, "incorrect fixed array class")
/* Address of header for array that owns this block (just for file integrity checks) */
- H5F_addr_decode(f, &p, &arr_addr);
+ H5F_addr_decode(udata->hdr->f, &image, &arr_addr);
if(H5F_addr_ne(arr_addr, udata->hdr->addr))
H5E_THROW(H5E_BADVALUE, "wrong fixed array header address")
/* Page initialization flags */
if(dblock->npages > 0) {
- HDmemcpy(dblock->dblk_page_init, p, dblock->dblk_page_init_size);
- p += dblock->dblk_page_init_size;
+ HDmemcpy(dblock->dblk_page_init, image, dblock->dblk_page_init_size);
+ image += dblock->dblk_page_init_size;
} /* end if */
/* Only decode elements if the data block is not paged */
if(!dblock->npages) {
/* Decode elements in data block */
/* Convert from raw elements on disk into native elements in memory */
- if((udata->hdr->cparam.cls->decode)(p, dblock->elmts, (size_t)udata->hdr->stats.nelmts, udata->hdr->cb_ctx) < 0)
+ if((udata->hdr->cparam.cls->decode)(image, dblock->elmts, (size_t)udata->hdr->cparam.nelmts, udata->hdr->cb_ctx) < 0)
H5E_THROW(H5E_CANTDECODE, "can't decode fixed array data elements")
- p += (udata->hdr->stats.nelmts * udata->hdr->cparam.raw_elmt_size);
+ image += (udata->hdr->cparam.nelmts * udata->hdr->cparam.raw_elmt_size);
} /* end if */
/* Sanity check */
/* (allow for checksum not decoded yet) */
- HDassert((size_t)(p - buf) == (size - H5FA_SIZEOF_CHKSUM));
+ HDassert((size_t)(image - (const uint8_t *)_image) == (len - H5FA_SIZEOF_CHKSUM));
/* Set the data block's size */
dblock->size = H5FA_DBLOCK_SIZE(dblock);
- /* Already decoded and compared stored checksum earlier, when reading */
+ /* checksum verification already done in verify_chksum cb */
+
+ /* Metadata checksum */
+ UINT32DECODE(image, stored_chksum);
/* Sanity check */
- HDassert((size_t)(p - buf) == (size - H5_SIZEOF_CHKSUM));
+ HDassert((size_t)(image - (const uint8_t *)_image) == len);
/* Set return value */
ret_value = dblock;
CATCH
- /* Release resources */
- if(wb && H5WB_unwrap(wb) < 0)
- H5E_THROW(H5E_CLOSEERROR, "can't close wrapped buffer")
if(!ret_value)
if(dblock && H5FA__dblock_dest(dblock) < 0)
H5E_THROW(H5E_CANTFREE, "unable to destroy fixed array data block")
-END_FUNC(STATIC) /* end H5FA__cache_dblock_load() */
+END_FUNC(STATIC) /* end H5FA__cache_dblock_deserialize() */
/*-------------------------------------------------------------------------
- * Function: H5FA__cache_dblock_flush
+ * Function: H5FA__cache_dblock_image_len
*
- * Purpose: Flushes a dirty fixed array data block to disk.
+ * Purpose: Compute the size of the data structure on disk.
*
- * Return: SUCCEED/FAIL
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Vailin Choi
- * Thursday, April 30, 2009
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * August 14, 2013
*
*-------------------------------------------------------------------------
*/
-BEGIN_FUNC(STATIC, ERR,
-herr_t, SUCCEED, FAIL,
-H5FA__cache_dblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr,
- H5FA_dblock_t *dblock, unsigned H5_ATTR_UNUSED * flags_ptr))
+BEGIN_FUNC(STATIC, NOERR,
+herr_t, SUCCEED, -,
+H5FA__cache_dblock_image_len(const void *_thing, size_t *image_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr))
/* Local variables */
- H5WB_t *wb = NULL; /* Wrapped buffer for serializing data */
- uint8_t ser_buf[H5FA_DBLOCK_BUF_SIZE]; /* Serialization buffer */
+ const H5FA_dblock_t *dblock = (const H5FA_dblock_t *)_thing; /* Pointer to the object */
- /* Sanity check */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
+ /* Check arguments */
HDassert(dblock);
- HDassert(dblock->hdr);
-
- if(dblock->cache_info.is_dirty) {
- uint8_t *buf; /* Temporary raw data buffer */
- uint8_t *p; /* Pointer into raw data buffer */
- size_t size; /* Index block size on disk */
- uint32_t metadata_chksum; /* Computed metadata checksum value */
-
- /* Wrap the local buffer for serialized info */
- if(NULL == (wb = H5WB_wrap(ser_buf, sizeof(ser_buf))))
- H5E_THROW(H5E_CANTINIT, "can't wrap buffer")
-
- /* Compute the size of the data block on disk */
- if(!dblock->npages)
- size = (size_t)dblock->size;
- else
- size = H5FA_DBLOCK_PREFIX_SIZE(dblock);
-
- /* Get a pointer to a buffer that's large enough for serialized info */
- if(NULL == (buf = (uint8_t *)H5WB_actual(wb, size)))
- H5E_THROW(H5E_CANTGET, "can't get actual buffer")
-
- /* Get temporary pointer to serialized info */
- p = buf;
-
- /* Magic number */
- HDmemcpy(p, H5FA_DBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC);
- p += H5_SIZEOF_MAGIC;
-
- /* Version # */
- *p++ = H5FA_DBLOCK_VERSION;
-
- /* Fixed array type */
- *p++ = dblock->hdr->cparam.cls->id;
-
- /* Address of array header for array which owns this block */
- H5F_addr_encode(f, &p, dblock->hdr->addr);
-
- /* Page init flags */
- if(dblock->npages > 0) {
- /* Store the 'page init' bitmasks */
- HDmemcpy(p, dblock->dblk_page_init, dblock->dblk_page_init_size);
- p += dblock->dblk_page_init_size;
- } /* end if */
-
- /* Only encode elements if the data block is not paged */
- if(!dblock->npages) {
- /* Encode elements in data block */
-
- /* Convert from native elements in memory into raw elements on disk */
- H5_CHECK_OVERFLOW(dblock->hdr->cparam.nelmts, /* From: */hsize_t, /* To: */size_t);
- if((dblock->hdr->cparam.cls->encode)(p, dblock->elmts, (size_t)dblock->hdr->cparam.nelmts, dblock->hdr->cb_ctx) < 0)
- H5E_THROW(H5E_CANTENCODE, "can't encode fixed array data elements")
- p += (dblock->hdr->cparam.nelmts * dblock->hdr->cparam.raw_elmt_size);
- } /* end if */
-
- /* Compute metadata checksum */
- metadata_chksum = H5_checksum_metadata(buf, (size_t)(p - buf), 0);
-
- /* Metadata checksum */
- UINT32ENCODE(p, metadata_chksum);
-
- /* Write the data block */
- HDassert((size_t)(p - buf) == size);
- if(H5F_block_write(f, H5FD_MEM_FARRAY_DBLOCK, addr, size, dxpl_id, buf) < 0)
- H5E_THROW(H5E_WRITEERROR, "unable to save fixed array data block to disk")
+ HDassert(image_len);
- dblock->cache_info.is_dirty = FALSE;
- } /* end if */
-
- if(destroy)
- if(H5FA__cache_dblock_dest(f, dblock) < 0)
- H5E_THROW(H5E_CANTFREE, "unable to destroy fixed array data block")
-
-CATCH
-
- /* Release resources */
- if(wb && H5WB_unwrap(wb) < 0)
- H5E_THROW(H5E_CLOSEERROR, "can't close wrapped buffer")
+ /* Set the image length size */
+ if(!dblock->npages)
+ *image_len = (size_t)dblock->size;
+ else
+ *image_len = H5FA_DBLOCK_PREFIX_SIZE(dblock);
-END_FUNC(STATIC) /* end H5FA__cache_dblock_flush() */
+END_FUNC(STATIC) /* end H5FA__cache_dblock_image_len() */
/*-------------------------------------------------------------------------
- * Function: H5FA__cache_dblock_dest
+ * Function: H5FA__cache_dblock_serialize
*
- * Purpose: Destroys a fixed array data block in memory.
+ * Purpose: Flushes a dirty object to disk.
*
- * Return: SUCCEED/FAIL
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Vailin Choi
- * Thursday, April 30, 2009
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * August 14, 2013
*
*-------------------------------------------------------------------------
*/
-/* ARGSUSED */
BEGIN_FUNC(STATIC, ERR,
herr_t, SUCCEED, FAIL,
-H5FA__cache_dblock_dest(H5F_t *f, H5FA_dblock_t *dblock))
+H5FA__cache_dblock_serialize(const H5F_t *f, void *_image, size_t H5_ATTR_UNUSED len,
+ void *_thing))
- /* Sanity check */
+ /* Local variables */
+ H5FA_dblock_t *dblock = (H5FA_dblock_t *)_thing; /* Pointer to the object to serialize */
+ uint8_t *image = (uint8_t *)_image; /* Pointer into raw data buffer */
+ uint32_t metadata_chksum; /* Computed metadata checksum value */
+
+ /* Check arguments */
HDassert(f);
+ HDassert(image);
HDassert(dblock);
+ HDassert(dblock->hdr);
- /* Verify that data block is clean */
- HDassert(dblock->cache_info.is_dirty == FALSE);
+ /* Magic number */
+ HDmemcpy(image, H5FA_DBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ image += H5_SIZEOF_MAGIC;
- /* If we're going to free the space on disk, the address must be valid */
- HDassert(!dblock->cache_info.free_file_space_on_destroy || H5F_addr_defined(dblock->cache_info.addr));
+ /* Version # */
+ *image++ = H5FA_DBLOCK_VERSION;
- /* Check for freeing file space for fixed array data block */
- if(dblock->cache_info.free_file_space_on_destroy) {
- /* Sanity check address */
- HDassert(H5F_addr_eq(dblock->addr, dblock->cache_info.addr));
+ /* Fixed array type */
+ *image++ = dblock->hdr->cparam.cls->id;
- /* Release the space on disk */
- /* (Includes space for pages!) */
- /* (XXX: Nasty usage of internal DXPL value! -QAK) */
- if(H5MF_xfree(f, H5FD_MEM_FARRAY_DBLOCK, H5AC_dxpl_id, dblock->cache_info.addr, (hsize_t)dblock->size) < 0)
- H5E_THROW(H5E_CANTFREE, "unable to free fixed array data block")
+ /* Address of array header for array which owns this block */
+ H5F_addr_encode(f, &image, dblock->hdr->addr);
+
+ /* Page init flags */
+ if(dblock->npages > 0) {
+ /* Store the 'page init' bitmasks */
+ HDmemcpy(image, dblock->dblk_page_init, dblock->dblk_page_init_size);
+ image += dblock->dblk_page_init_size;
} /* end if */
- /* Release the data block */
- if(H5FA__dblock_dest(dblock) < 0)
- H5E_THROW(H5E_CANTFREE, "can't free fixed array data block")
+ /* Only encode elements if the data block is not paged */
+ if(!dblock->npages) {
+ /* Encode elements in data block */
-CATCH
+ /* Convert from native elements in memory into raw elements on disk */
+ H5_CHECK_OVERFLOW(dblock->hdr->cparam.nelmts, /* From: */hsize_t, /* To: */size_t);
+ if((dblock->hdr->cparam.cls->encode)(image, dblock->elmts, (size_t)dblock->hdr->cparam.nelmts, dblock->hdr->cb_ctx) < 0)
+ H5E_THROW(H5E_CANTENCODE, "can't encode fixed array data elements")
+ image += (dblock->hdr->cparam.nelmts * dblock->hdr->cparam.raw_elmt_size);
+ } /* end if */
-END_FUNC(STATIC) /* end H5FA__cache_dblock_dest() */
+ /* Compute metadata checksum */
+ metadata_chksum = H5_checksum_metadata(_image, (size_t)(image - (uint8_t *)_image), 0);
-
-/*-------------------------------------------------------------------------
- * Function: H5FA__cache_dblock_clear
- *
- * Purpose: Mark a fixed array data block in memory as non-dirty.
- *
- * Return: SUCCEED/FAIL
- *
- * Programmer: Vailin Choi
- * Thursday, April 30, 2009
- *
- *-------------------------------------------------------------------------
- */
-BEGIN_FUNC(STATIC, ERR,
-herr_t, SUCCEED, FAIL,
-H5FA__cache_dblock_clear(H5F_t *f, H5FA_dblock_t *dblock, hbool_t destroy))
+ /* Metadata checksum */
+ UINT32ENCODE(image, metadata_chksum);
/* Sanity check */
- HDassert(dblock);
-
- /* Reset the dirty flag */
- dblock->cache_info.is_dirty = FALSE;
-
- if(destroy)
- if(H5FA__cache_dblock_dest(f, dblock) < 0)
- H5E_THROW(H5E_CANTFREE, "unable to destroy fixed array data block")
+ HDassert((size_t)(image - (uint8_t *)_image) <= len);
CATCH
-END_FUNC(STATIC) /* end H5FA__cache_dblock_clear() */
+END_FUNC(STATIC) /* end H5FA__cache_dblock_serialize() */
+
/*-------------------------------------------------------------------------
@@ -799,7 +811,10 @@ END_FUNC(STATIC) /* end H5FA__cache_dblock_clear() */
*/
BEGIN_FUNC(STATIC, ERR,
herr_t, SUCCEED, FAIL,
-H5FA__cache_dblock_notify(H5AC_notify_action_t action, H5FA_dblock_t *dblock))
+H5FA__cache_dblock_notify(H5AC_notify_action_t action, void *_thing))
+
+ /* Local variables */
+ H5FA_dblock_t *dblock = (H5FA_dblock_t *)_thing;
/* Sanity check */
HDassert(dblock);
@@ -809,13 +824,21 @@ H5FA__cache_dblock_notify(H5AC_notify_action_t action, H5FA_dblock_t *dblock))
/* Determine which action to take */
switch(action) {
case H5AC_NOTIFY_ACTION_AFTER_INSERT:
- /* Create flush dependency on extensible array header */
+ case H5AC_NOTIFY_ACTION_AFTER_LOAD:
+ /* Create flush dependency on parent */
if(H5FA__create_flush_depend((H5AC_info_t *)dblock->hdr, (H5AC_info_t *)dblock) < 0)
H5E_THROW(H5E_CANTDEPEND, "unable to create flush dependency between data block and header, address = %llu", (unsigned long long)dblock->addr)
break;
+ case H5AC_NOTIFY_ACTION_AFTER_FLUSH:
+ /* do nothing */
+ break;
+
case H5AC_NOTIFY_ACTION_BEFORE_EVICT:
- /* Nothing to do */
+ /* Destroy flush dependency on parent */
+ if(H5FA__destroy_flush_depend((H5AC_info_t *)dblock->hdr, (H5AC_info_t *)dblock) < 0)
+ H5E_THROW(H5E_CANTUNDEPEND, "unable to destroy flush dependency")
+
break;
default:
@@ -831,115 +854,220 @@ CATCH
END_FUNC(STATIC) /* end H5FA__cache_dblock_notify() */
+
/*-------------------------------------------------------------------------
- * Function: H5FA__cache_dblock_size
+ * Function: H5FA__cache_dblock_free_icr
*
- * Purpose: Compute the size in bytes of a fixed array data block
- * on disk, and return it in *size_ptr.
+ * Purpose: Destroy/release an "in core representation" of a data
+ * structure
*
- * Return: SUCCEED (Can't fail)
+ * Return: SUCCEED/FAIL
*
- * Programmer: Vailin Choi
- * Thursday, April 30, 2009
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * August 14, 2013
*
*-------------------------------------------------------------------------
*/
/* ARGSUSED */
+BEGIN_FUNC(STATIC, ERR,
+herr_t, SUCCEED, FAIL,
+H5FA__cache_dblock_free_icr(void *_thing))
+
+ H5FA_dblock_t *dblock = (H5FA_dblock_t *)_thing; /* Pointer to the object */
+
+ /* Check arguments */
+ HDassert(dblock);
+
+ /* Release the fixed array data block */
+ if(H5FA__dblock_dest(dblock) < 0)
+ H5E_THROW(H5E_CANTFREE, "can't free fixed array data block")
+
+CATCH
+
+END_FUNC(STATIC) /* end H5FA__cache_dblock_free_icr() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FA__cache_dblock_fsf_size
+ *
+ * Purpose: Tell the metadata cache the actual amount of file space
+ * to free when a dblock entry is destroyed with the free
+ * file space block set.
+ *
+ * This function is needed when the data block is paged, as
+ * the datablock header and all its pages are allocted as a
+ * single contiguous chunk of file space, and must be
+ * deallocated the same way.
+ *
+ * The size of the chunk of memory in which the dblock
+ * header and all its pages is stored in the size field,
+ * so we simply pass that value back to the cache.
+ *
+ * If the datablock is not paged, then the size field of
+ * the cache_info contains the correct size. However this
+ * value will be the same as the size field, so we return
+ * the contents of the size field to the cache in this case
+ * as well.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: John Mainzer
+ * 12/5/14
+ *
+ *-------------------------------------------------------------------------
+ */
BEGIN_FUNC(STATIC, NOERR,
herr_t, SUCCEED, -,
-H5FA__cache_dblock_size(const H5F_t H5_ATTR_UNUSED *f, const H5FA_dblock_t *dblock,
- size_t *size_ptr))
+H5FA__cache_dblock_fsf_size(const void *_thing, size_t *fsf_size))
- /* Sanity check */
- HDassert(f);
+ const H5FA_dblock_t *dblock = (const H5FA_dblock_t *)_thing; /* Pointer to the object */
+
+ /* Check arguments */
HDassert(dblock);
- HDassert(size_ptr);
+ HDassert(dblock->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(dblock->cache_info.type == H5AC_FARRAY_DBLOCK);
+ HDassert(fsf_size);
- /* Set size value */
- if(!dblock->npages)
- *size_ptr = (size_t)dblock->size;
- else
- *size_ptr = H5FA_DBLOCK_PREFIX_SIZE(dblock);
+ *fsf_size = dblock->size;
-END_FUNC(STATIC) /* end H5FA__cache_dblock_size() */
+END_FUNC(STATIC) /* end H5FA__cache_dblock_fsf_size() */
/*-------------------------------------------------------------------------
- * Function: H5FA__cache_dblk_page_load
+ * Function: H5FA__cache_dblk_page_get_load_size
*
- * Purpose: Loads a fixed array data block page from the disk.
+ * Purpose: Compute the size of the data structure on disk.
*
- * Return: Success: Pointer to a new fixed array data block page
- * Failure: NULL
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Vailin Choi
- * Thursday, April 30, 2009
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * August 14, 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(STATIC, NOERR,
+herr_t, SUCCEED, -,
+H5FA__cache_dblk_page_get_load_size(const void *_image, void *_udata,
+ size_t *image_len, size_t *actual_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr))
+
+ /* Local variables */
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ H5FA_dblk_page_cache_ud_t *udata = (H5FA_dblk_page_cache_ud_t *)_udata; /* User data */
+
+ /* Check arguments */
+ HDassert(udata);
+ HDassert(udata->hdr);
+ HDassert(udata->nelmts > 0);
+ HDassert(image_len);
+
+ if(image == NULL)
+ *image_len = (size_t)H5FA_DBLK_PAGE_SIZE(udata->hdr, udata->nelmts);
+ else {
+ HDassert(actual_len);
+ HDassert(*actual_len == *image_len);
+ }
+
+END_FUNC(STATIC) /* end H5FA__cache_dblk_page_get_load_size() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FA__cache_dblk_page_verify_chksum
+ *
+ * Purpose: Verify the computed checksum of the data structure is the
+ * same as the stored chksum.
+ *
+ * Return: Success: TRUE/FALSE
+ * Failure: Negative
+ *
+ * Programmer: Vailin Choi; Aug 2015
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(STATIC, NOERR,
+htri_t, TRUE, -,
+H5FA__cache_dblk_page_verify_chksum(const void *_image, size_t len, void H5_ATTR_UNUSED *_udata))
+
+ /* Local variables */
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ uint32_t stored_chksum; /* Stored metadata checksum value */
+ uint32_t computed_chksum; /* Computed metadata checksum value */
+
+ /* Check arguments */
+ HDassert(image);
+
+ /* Get stored and computed checksums */
+ H5F_get_checksums(image, len, &stored_chksum, &computed_chksum);
+
+ if(stored_chksum != computed_chksum)
+ ret_value = FALSE;
+
+END_FUNC(STATIC) /* end H5FA__cache_dblk_page_verify_chksum() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FA__cache_dblk_page_deserialize
+ *
+ * Purpose: Loads a data structure from the disk.
+ *
+ * Return: Success: Pointer to a new B-tree.
+ * Failure: NULL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * August 14, 2013
*
*-------------------------------------------------------------------------
*/
BEGIN_FUNC(STATIC, ERR,
-H5FA_dblk_page_t *, NULL, NULL,
-H5FA__cache_dblk_page_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata))
+void *, NULL, NULL,
+H5FA__cache_dblk_page_deserialize(const void *_image, size_t len,
+ void *_udata, hbool_t H5_ATTR_UNUSED *dirty))
/* Local variables */
H5FA_dblk_page_t *dblk_page = NULL; /* Data block page info */
H5FA_dblk_page_cache_ud_t *udata = (H5FA_dblk_page_cache_ud_t *)_udata; /* User data for loading data block page */
- size_t size; /* Data block page size */
- H5WB_t *wb = NULL; /* Wrapped buffer for data block page data */
- uint8_t dblk_page_buf[H5FA_DBLK_PAGE_BUF_SIZE]; /* Buffer for data block page */
- uint8_t *buf; /* Pointer to data block page buffer */
- const uint8_t *p; /* Pointer into raw data buffer */
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ uint32_t stored_chksum; /* Stored metadata checksum value */
/* Sanity check */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
- HDassert(udata && udata->hdr && udata->nelmts > 0);
+ HDassert(udata);
+ HDassert(udata->hdr);
+ HDassert(udata->nelmts > 0);
+ HDassert(H5F_addr_defined(udata->dblk_page_addr));
/* Allocate the fixed array data block page */
if(NULL == (dblk_page = H5FA__dblk_page_alloc(udata->hdr, udata->nelmts)))
H5E_THROW(H5E_CANTALLOC, "memory allocation failed for fixed array data block page")
/* Set the fixed array data block's information */
- dblk_page->addr = addr;
-
- /* Wrap the local buffer for serialized info */
- if(NULL == (wb = H5WB_wrap(dblk_page_buf, sizeof(dblk_page_buf))))
- H5E_THROW(H5E_CANTINIT, "can't wrap buffer")
-
- /* Compute the size of the fixed array data block page on disk */
- size = H5FA_DBLK_PAGE_SIZE(udata->hdr, udata->nelmts);
-
- /* Get a pointer to a buffer that's large enough for serialized info */
- if(NULL == (buf = (uint8_t *)H5WB_actual(wb, size)))
- H5E_THROW(H5E_CANTGET, "can't get actual buffer")
-
- /* Read and validate data block page from disk */
- if(H5F_read_check_metadata(f, dxpl_id, H5FD_MEM_FARRAY_DBLK_PAGE, H5AC_FARRAY_DBLK_PAGE_ID, addr, size, size, buf) < 0)
- H5E_THROW(H5E_BADVALUE, "incorrect metadata checksum for fixed array data block page")
-
- /* Get temporary pointer to serialized header */
- p = buf;
+ dblk_page->addr = udata->dblk_page_addr;
/* Internal information */
/* Decode elements in data block page */
/* Convert from raw elements on disk into native elements in memory */
- if((udata->hdr->cparam.cls->decode)(p, dblk_page->elmts, udata->nelmts, udata->hdr->cb_ctx) < 0)
+ if((udata->hdr->cparam.cls->decode)(image, dblk_page->elmts, udata->nelmts, udata->hdr->cb_ctx) < 0)
H5E_THROW(H5E_CANTDECODE, "can't decode fixed array data elements")
- p += (udata->nelmts * udata->hdr->cparam.raw_elmt_size);
+ image += (udata->nelmts * udata->hdr->cparam.raw_elmt_size);
/* Sanity check */
/* (allow for checksum not decoded yet) */
- HDassert((size_t)(p - buf) == (size - H5FA_SIZEOF_CHKSUM));
+ HDassert((size_t)(image - (const uint8_t *)_image) == (len - H5FA_SIZEOF_CHKSUM));
/* Set the data block page's size */
- dblk_page->size = size;
+ dblk_page->size = len;
- /* Already decoded and compared stored checksum earlier, when reading */
+ /* checksum verification already done in verify_chksum cb */
+
+ /* Metadata checksum */
+ UINT32DECODE(image, stored_chksum);
/* Sanity check */
- HDassert((size_t)(p - buf) == (dblk_page->size - H5_SIZEOF_CHKSUM));
+ HDassert((size_t)(image - (const uint8_t *)_image) == dblk_page->size);
/* Set return value */
ret_value = dblk_page;
@@ -947,191 +1075,120 @@ H5FA__cache_dblk_page_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata))
CATCH
/* Release resources */
- if(wb && H5WB_unwrap(wb) < 0)
- H5E_THROW(H5E_CLOSEERROR, "can't close wrapped buffer")
if(!ret_value)
if(dblk_page && H5FA__dblk_page_dest(dblk_page) < 0)
H5E_THROW(H5E_CANTFREE, "unable to destroy fixed array data block page")
-END_FUNC(STATIC) /* end H5FA__cache_dblk_page_load() */
+END_FUNC(STATIC) /* end H5FA__cache_dblk_page_deserialize() */
/*-------------------------------------------------------------------------
- * Function: H5FA__cache_dblk_page_flush
+ * Function: H5FA__cache_dblk_page_image_len
*
- * Purpose: Flushes a dirty fixed array data block page to disk.
+ * Purpose: Compute the size of the data structure on disk.
*
- * Return: SUCCEED/FAIL
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Vailin Choi
- * Thursday, April 30, 2009
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * August 14, 2013
*
*-------------------------------------------------------------------------
*/
-BEGIN_FUNC(STATIC, ERR,
-herr_t, SUCCEED, FAIL,
-H5FA__cache_dblk_page_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr,
- H5FA_dblk_page_t *dblk_page, unsigned H5_ATTR_UNUSED * flags_ptr))
+BEGIN_FUNC(STATIC, NOERR,
+herr_t, SUCCEED, -,
+H5FA__cache_dblk_page_image_len(const void *_thing, size_t *image_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr))
/* Local variables */
- H5WB_t *wb = NULL; /* Wrapped buffer for serializing data */
- uint8_t ser_buf[H5FA_DBLK_PAGE_BUF_SIZE]; /* Serialization buffer */
+ const H5FA_dblk_page_t *dblk_page = (const H5FA_dblk_page_t *)_thing; /* Pointer to the object */
- /* Sanity check */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
+ /* Check arguments */
HDassert(dblk_page);
- HDassert(dblk_page->hdr);
-
- if(dblk_page->cache_info.is_dirty) {
- uint8_t *buf; /* Temporary raw data buffer */
- uint8_t *p; /* Pointer into raw data buffer */
- size_t size; /* Index block size on disk */
- uint32_t metadata_chksum; /* Computed metadata checksum value */
-
- /* Wrap the local buffer for serialized info */
- if(NULL == (wb = H5WB_wrap(ser_buf, sizeof(ser_buf))))
- H5E_THROW(H5E_CANTINIT, "can't wrap buffer")
-
- /* Compute the size of the data block on disk */
- size = dblk_page->size;
-
- /* Get a pointer to a buffer that's large enough for serialized info */
- if(NULL == (buf = (uint8_t *)H5WB_actual(wb, size)))
- H5E_THROW(H5E_CANTGET, "can't get actual buffer")
-
- /* Get temporary pointer to serialized info */
- p = buf;
-
- /* Internal information */
-
- /* Encode elements in data block page */
-
- /* Convert from native elements in memory into raw elements on disk */
- if((dblk_page->hdr->cparam.cls->encode)(p, dblk_page->elmts, dblk_page->nelmts, dblk_page->hdr->cb_ctx) < 0)
- H5E_THROW(H5E_CANTENCODE, "can't encode fixed array data elements")
- p += (dblk_page->nelmts * dblk_page->hdr->cparam.raw_elmt_size);
-
- /* Compute metadata checksum */
- metadata_chksum = H5_checksum_metadata(buf, (size_t)(p - buf), 0);
-
- /* Metadata checksum */
- UINT32ENCODE(p, metadata_chksum);
-
- /* Write the data block */
- HDassert((size_t)(p - buf) == size);
- if(H5F_block_write(f, H5FD_MEM_FARRAY_DBLK_PAGE, addr, size, dxpl_id, buf) < 0)
- H5E_THROW(H5E_WRITEERROR, "unable to save fixed array data block page to disk")
-
- dblk_page->cache_info.is_dirty = FALSE;
- } /* end if */
+ HDassert(image_len);
- if(destroy)
- if(H5FA__cache_dblk_page_dest(f, dblk_page) < 0)
- H5E_THROW(H5E_CANTFREE, "unable to destroy fixed array data block page")
-
-CATCH
+ /* Set the image length size */
+ *image_len = dblk_page->size;
- /* Release resources */
- if(wb && H5WB_unwrap(wb) < 0)
- H5E_THROW(H5E_CLOSEERROR, "can't close wrapped buffer")
-
-END_FUNC(STATIC) /* end H5FA__cache_dblk_page_flush() */
+END_FUNC(STATIC) /* end H5FA__cache_dblk_page_image_len() */
/*-------------------------------------------------------------------------
- * Function: H5FA__cache_dblk_page_dest
+ * Function: H5FA__cache_dblk_page_serialize
*
- * Purpose: Destroys a fixed array data block page in memory.
+ * Purpose: Flushes a dirty object to disk.
*
- * Note: Does _not_ free the space for the page on disk, that is
- * handled through the data block that "owns" the page.
- *
- * Return: SUCCEED/FAIL
- *
- * Programmer: Vailin Choi
- * Thursday, April 30, 2009
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * August 14, 2013
*
*-------------------------------------------------------------------------
*/
/* ARGSUSED */
BEGIN_FUNC(STATIC, ERR,
herr_t, SUCCEED, FAIL,
-H5FA__cache_dblk_page_dest(H5F_t H5_ATTR_UNUSED *f, H5FA_dblk_page_t *dblk_page))
+H5FA__cache_dblk_page_serialize(const H5F_t *f, void *_image, size_t H5_ATTR_UNUSED len,
+ void *_thing))
+
+ /* Local variables */
+ H5FA_dblk_page_t *dblk_page = (H5FA_dblk_page_t *)_thing; /* Pointer to the object to serialize */
+ uint8_t *image = (uint8_t *)_image; /* Pointer into raw data buffer */
+ uint32_t metadata_chksum; /* Computed metadata checksum value */
/* Sanity check */
HDassert(f);
+ HDassert(image);
HDassert(dblk_page);
+ HDassert(dblk_page->hdr);
- /* Verify that data block page is clean */
- HDassert(dblk_page->cache_info.is_dirty == FALSE);
+ /* Internal information */
- /* Release the data block page */
- if(H5FA__dblk_page_dest(dblk_page) < 0)
- H5E_THROW(H5E_CANTFREE, "can't free fixed array data block page")
+ /* Encode elements in data block page */
-CATCH
+ /* Convert from native elements in memory into raw elements on disk */
+ if((dblk_page->hdr->cparam.cls->encode)(image, dblk_page->elmts, dblk_page->nelmts, dblk_page->hdr->cb_ctx) < 0)
+ H5E_THROW(H5E_CANTENCODE, "can't encode fixed array data elements")
+ image += (dblk_page->nelmts * dblk_page->hdr->cparam.raw_elmt_size);
-END_FUNC(STATIC) /* end H5FA__cache_dblk_page_dest() */
+ /* Compute metadata checksum */
+ metadata_chksum = H5_checksum_metadata(_image, (size_t)(image - (uint8_t *)_image), 0);
-
-/*-------------------------------------------------------------------------
- * Function: H5FA__cache_dblk_page_clear
- *
- * Purpose: Mark a fixed array data block page in memory as non-dirty.
- *
- * Return: SUCCEED/FAIL
- *
- * Programmer: Vailin Choi
- * Thursday, April 30, 2009
- *
- *-------------------------------------------------------------------------
- */
-BEGIN_FUNC(STATIC, ERR,
-herr_t, SUCCEED, FAIL,
-H5FA__cache_dblk_page_clear(H5F_t *f, H5FA_dblk_page_t *dblk_page, hbool_t destroy))
+ /* Metadata checksum */
+ UINT32ENCODE(image, metadata_chksum);
/* Sanity check */
- HDassert(dblk_page);
-
- /* Reset the dirty flag */
- dblk_page->cache_info.is_dirty = FALSE;
-
- if(destroy)
- if(H5FA__cache_dblk_page_dest(f, dblk_page) < 0)
- H5E_THROW(H5E_CANTFREE, "unable to destroy fixed array data block page")
+ HDassert((size_t)(image - (uint8_t *)_image) <= len);
CATCH
-END_FUNC(STATIC) /* end H5FA__cache_dblk_page_clear() */
+END_FUNC(STATIC) /* end H5FA__cache_dblk_page_serialize() */
/*-------------------------------------------------------------------------
- * Function: H5FA__cache_dblk_page_size
+ * Function: H5FA__cache_dblk_page_free_icr
*
- * Purpose: Compute the size in bytes of a fixed array data block page
- * on disk, and return it in *size_ptr. On failure,
- * the value of *size_ptr is undefined.
+ * Purpose: Destroy/release an "in core representation" of a data
+ * structure
*
- * Return: SUCCEED (Can't fail)
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Vailin Choi
- * Thursday, April 30, 2009
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * August 14, 2013
*
*-------------------------------------------------------------------------
*/
-/* ARGSUSED */
-BEGIN_FUNC(STATIC, NOERR,
-herr_t, SUCCEED, -,
-H5FA__cache_dblk_page_size(const H5F_t H5_ATTR_UNUSED *f, const H5FA_dblk_page_t *dblk_page,
- size_t *size_ptr))
+BEGIN_FUNC(STATIC, ERR,
+herr_t, SUCCEED, FAIL,
+H5FA__cache_dblk_page_free_icr(void *thing))
- /* Sanity check */
- HDassert(f);
- HDassert(dblk_page);
- HDassert(size_ptr);
+ /* Check arguments */
+ HDassert(thing);
- /* Set size value */
- *size_ptr = dblk_page->size;
+ /* Release the fixed array data block page */
+ if(H5FA__dblk_page_dest((H5FA_dblk_page_t *)thing) < 0)
+ H5E_THROW(H5E_CANTFREE, "can't free fixed array data block page")
+
+CATCH
-END_FUNC(STATIC) /* end H5FA__cache_dblk_page_size() */
+END_FUNC(STATIC) /* end H5FA__cache_dblk_page_free_icr() */
diff --git a/src/H5FAdbg.c b/src/H5FAdbg.c
index 281efdd..1d1e569 100644
--- a/src/H5FAdbg.c
+++ b/src/H5FAdbg.c
@@ -117,7 +117,7 @@ H5FA__hdr_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent,
} /* end if */
/* Load the fixed array header */
- if(NULL == (hdr = H5FA__hdr_protect(f, dxpl_id, addr, dbg_ctx, H5AC_READ)))
+ if(NULL == (hdr = H5FA__hdr_protect(f, dxpl_id, addr, dbg_ctx, H5AC__READ_ONLY_FLAG)))
H5E_THROW(H5E_CANTPROTECT, "unable to load fixed array header")
/* Print opening message */
@@ -198,11 +198,11 @@ H5FA__dblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int inde
} /* end if */
/* Load the fixed array header */
- if(NULL == (hdr = H5FA__hdr_protect(f, dxpl_id, hdr_addr, dbg_ctx, H5AC_READ)))
+ if(NULL == (hdr = H5FA__hdr_protect(f, dxpl_id, hdr_addr, dbg_ctx, H5AC__READ_ONLY_FLAG)))
H5E_THROW(H5E_CANTPROTECT, "unable to load fixed array header")
/* Protect data block */
- if(NULL == (dblock = H5FA__dblock_protect(hdr, dxpl_id, addr, H5AC_READ)))
+ if(NULL == (dblock = H5FA__dblock_protect(hdr, dxpl_id, addr, H5AC__READ_ONLY_FLAG)))
H5E_THROW(H5E_CANTPROTECT, "unable to protect fixed array data block, address = %llu", (unsigned long long)addr)
/* Print opening message */
@@ -246,8 +246,8 @@ H5FA__dblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int inde
if(((page_idx + 1) == dblock->npages) && (nelmts_left = hdr->cparam.nelmts % dblock->dblk_page_nelmts))
dblk_page_nelmts = (size_t)nelmts_left;
- if(NULL == (dblk_page = H5FA__dblk_page_protect(hdr, dxpl_id, dblk_page_addr, dblk_page_nelmts, H5AC_READ)))
- H5E_THROW(H5E_CANTPROTECT, "unable to protect fixed array data block page, address = %llu", (unsigned long long)dblk_page_addr)
+ if(NULL == (dblk_page = H5FA__dblk_page_protect(hdr, dxpl_id, dblk_page_addr, dblk_page_nelmts, H5AC__READ_ONLY_FLAG)))
+ H5E_THROW(H5E_CANTPROTECT, "unable to protect fixed array data block page, address = %llu", (unsigned long long)dblk_page_addr)
HDfprintf(stream, "%*sElements in page %Zu:\n", indent, "", page_idx);
for(u = 0; u < dblk_page_nelmts; u++) {
diff --git a/src/H5FAdblkpage.c b/src/H5FAdblkpage.c
index aaedb96..4337504 100644
--- a/src/H5FAdblkpage.c
+++ b/src/H5FAdblkpage.c
@@ -207,7 +207,7 @@ END_FUNC(PKG) /* end H5FA__dblk_page_create() */
BEGIN_FUNC(PKG, ERR,
H5FA_dblk_page_t *, NULL, NULL,
H5FA__dblk_page_protect(H5FA_hdr_t *hdr, hid_t dxpl_id, haddr_t dblk_page_addr,
- size_t dblk_page_nelmts, H5AC_protect_t rw))
+ size_t dblk_page_nelmts, unsigned flags))
/* Local variables */
H5FA_dblk_page_cache_ud_t udata; /* Information needed for loading data block page */
@@ -220,12 +220,16 @@ HDfprintf(stderr, "%s: Called\n", FUNC);
HDassert(hdr);
HDassert(H5F_addr_defined(dblk_page_addr));
+ /* only the H5AC__READ_ONLY_FLAG is permitted */
+ HDassert((flags & (unsigned)(~H5AC__READ_ONLY_FLAG)) == 0);
+
/* Set up user data */
udata.hdr = hdr;
udata.nelmts = dblk_page_nelmts;
+ udata.dblk_page_addr = dblk_page_addr;
/* Protect the data block page */
- if(NULL == (ret_value = (H5FA_dblk_page_t *)H5AC_protect(hdr->f, dxpl_id, H5AC_FARRAY_DBLK_PAGE, dblk_page_addr, &udata, rw)))
+ if(NULL == (ret_value = (H5FA_dblk_page_t *)H5AC_protect(hdr->f, dxpl_id, H5AC_FARRAY_DBLK_PAGE, dblk_page_addr, &udata, flags)))
H5E_THROW(H5E_CANTPROTECT, "unable to protect fixed array data block page, address = %llu", (unsigned long long)dblk_page_addr)
CATCH
diff --git a/src/H5FAdblock.c b/src/H5FAdblock.c
index 73838a1..9336a85 100644
--- a/src/H5FAdblock.c
+++ b/src/H5FAdblock.c
@@ -263,7 +263,7 @@ END_FUNC(PKG) /* end H5FA__dblock_create() */
BEGIN_FUNC(PKG, ERR,
H5FA_dblock_t *, NULL, NULL,
H5FA__dblock_protect(H5FA_hdr_t *hdr, hid_t dxpl_id, haddr_t dblk_addr,
- H5AC_protect_t rw))
+ unsigned flags))
/* Local variables */
H5FA_dblock_cache_ud_t udata; /* Information needed for loading data block */
@@ -276,11 +276,15 @@ HDfprintf(stderr, "%s: Called\n", FUNC);
HDassert(hdr);
HDassert(H5F_addr_defined(dblk_addr));
+ /* only the H5AC__READ_ONLY_FLAG flag is permitted */
+ HDassert((flags & (unsigned)(~H5AC__READ_ONLY_FLAG)) == 0);
+
/* Set up user data */
udata.hdr = hdr;
+ udata.dblk_addr = dblk_addr;
/* Protect the data block */
- if(NULL == (ret_value = (H5FA_dblock_t *)H5AC_protect(hdr->f, dxpl_id, H5AC_FARRAY_DBLOCK, dblk_addr, &udata, rw)))
+ if(NULL == (ret_value = (H5FA_dblock_t *)H5AC_protect(hdr->f, dxpl_id, H5AC_FARRAY_DBLOCK, dblk_addr, &udata, flags)))
H5E_THROW(H5E_CANTPROTECT, "unable to protect fixed array data block, address = %llu", (unsigned long long)dblk_addr)
CATCH
@@ -350,7 +354,7 @@ HDfprintf(stderr, "%s: Called\n", FUNC);
HDassert(H5F_addr_defined(dblk_addr));
/* Protect data block */
- if(NULL == (dblock = H5FA__dblock_protect(hdr, dxpl_id, dblk_addr, H5AC_WRITE)))
+ if(NULL == (dblock = H5FA__dblock_protect(hdr, dxpl_id, dblk_addr, H5AC__NO_FLAGS_SET)))
H5E_THROW(H5E_CANTPROTECT, "unable to protect fixed array data block, address = %llu", (unsigned long long)dblk_addr)
/* Check if data block is paged */
diff --git a/src/H5FAhdr.c b/src/H5FAhdr.c
index 2827fd7..79fe72a 100644
--- a/src/H5FAhdr.c
+++ b/src/H5FAhdr.c
@@ -409,16 +409,25 @@ END_FUNC(PKG) /* end H5FA__hdr_modified() */
BEGIN_FUNC(PKG, ERR,
H5FA_hdr_t *, NULL, NULL,
H5FA__hdr_protect(H5F_t *f, hid_t dxpl_id, haddr_t fa_addr, void *ctx_udata,
- H5AC_protect_t rw))
+ unsigned flags))
/* Local variables */
+ H5FA_hdr_cache_ud_t udata; /* User data for cache callbacks */
/* Sanity check */
HDassert(f);
HDassert(H5F_addr_defined(fa_addr));
+ /* only the H5AC__READ_ONLY_FLAG is permitted */
+ HDassert((flags & (unsigned)(~H5AC__READ_ONLY_FLAG)) == 0);
+
+ /* Set up user data for cache callbacks */
+ udata.f = f;
+ udata.addr = fa_addr;
+ udata.ctx_udata = ctx_udata;
+
/* Protect the header */
- if(NULL == (ret_value = (H5FA_hdr_t *)H5AC_protect(f, dxpl_id, H5AC_FARRAY_HDR, fa_addr, ctx_udata, rw)))
+ if(NULL == (ret_value = (H5FA_hdr_t *)H5AC_protect(f, dxpl_id, H5AC_FARRAY_HDR, fa_addr, &udata, flags)))
H5E_THROW(H5E_CANTPROTECT, "unable to protect fixed array header, address = %llu", (unsigned long long)fa_addr)
CATCH
diff --git a/src/H5FApkg.h b/src/H5FApkg.h
index e57b23a..77276cf 100644
--- a/src/H5FApkg.h
+++ b/src/H5FApkg.h
@@ -207,15 +207,24 @@ struct H5FA_t {
/* Metadata cache callback user data types */
+/* Info needed for loading header */
+typedef struct H5FA_hdr_cache_ud_t {
+ H5F_t *f; /* Pointer to file for fixed array */
+ haddr_t addr; /* Address of header on disk */
+ void *ctx_udata; /* User context for class */
+} H5FA_hdr_cache_ud_t;
+
/* Info needed for loading data block */
typedef struct H5FA_dblock_cache_ud_t {
H5FA_hdr_t *hdr; /* Shared fixed array information */
+ haddr_t dblk_addr; /* Address of data block on disk */
} H5FA_dblock_cache_ud_t;
/* Info needed for loading data block page */
typedef struct H5FA_dblk_page_cache_ud_t {
H5FA_hdr_t *hdr; /* Shared fixed array information */
size_t nelmts; /* Number of elements in data block page */
+ haddr_t dblk_page_addr; /* Address of data block page on disk */
} H5FA_dblk_page_cache_ud_t;
@@ -261,7 +270,7 @@ H5_DLL herr_t H5FA__hdr_fuse_incr(H5FA_hdr_t *hdr);
H5_DLL size_t H5FA__hdr_fuse_decr(H5FA_hdr_t *hdr);
H5_DLL herr_t H5FA__hdr_modified(H5FA_hdr_t *hdr);
H5_DLL H5FA_hdr_t *H5FA__hdr_protect(H5F_t *f, hid_t dxpl_id, haddr_t fa_addr,
- void *ctx_udata, H5AC_protect_t rw);
+ void *ctx_udata, unsigned flags);
H5_DLL herr_t H5FA__hdr_unprotect(H5FA_hdr_t *hdr, hid_t dxpl_id, unsigned cache_flags);
H5_DLL herr_t H5FA__hdr_delete(H5FA_hdr_t *hdr, hid_t dxpl_id);
H5_DLL herr_t H5FA__hdr_dest(H5FA_hdr_t *hdr);
@@ -271,7 +280,7 @@ H5_DLL H5FA_dblock_t *H5FA__dblock_alloc(H5FA_hdr_t *hdr);
H5_DLL haddr_t H5FA__dblock_create(H5FA_hdr_t *hdr, hid_t dxpl_id, hbool_t *hdr_dirty);
H5_DLL unsigned H5FA__dblock_sblk_idx(const H5FA_hdr_t *hdr, hsize_t idx);
H5_DLL H5FA_dblock_t *H5FA__dblock_protect(H5FA_hdr_t *hdr, hid_t dxpl_id,
- haddr_t dblk_addr, H5AC_protect_t rw);
+ haddr_t dblk_addr, unsigned flags);
H5_DLL herr_t H5FA__dblock_unprotect(H5FA_dblock_t *dblock, hid_t dxpl_id,
unsigned cache_flags);
H5_DLL herr_t H5FA__dblock_delete(H5FA_hdr_t *hdr, hid_t dxpl_id,
@@ -283,7 +292,7 @@ H5_DLL herr_t H5FA__dblk_page_create(H5FA_hdr_t *hdr, hid_t dxpl_id,
haddr_t addr, size_t nelmts);
H5_DLL H5FA_dblk_page_t *H5FA__dblk_page_alloc(H5FA_hdr_t *hdr, size_t nelmts);
H5_DLL H5FA_dblk_page_t *H5FA__dblk_page_protect(H5FA_hdr_t *hdr, hid_t dxpl_id,
- haddr_t dblk_page_addr, size_t dblk_page_nelmts, H5AC_protect_t rw);
+ haddr_t dblk_page_addr, size_t dblk_page_nelmts, unsigned flags);
H5_DLL herr_t H5FA__dblk_page_unprotect(H5FA_dblk_page_t *dblk_page,
hid_t dxpl_id, unsigned cache_flags);
H5_DLL herr_t H5FA__dblk_page_dest(H5FA_dblk_page_t *dblk_page);
diff --git a/src/H5FDfamily.c b/src/H5FDfamily.c
index 51a1b67..0ead309 100644
--- a/src/H5FDfamily.c
+++ b/src/H5FDfamily.c
@@ -907,7 +907,7 @@ H5FD_family_query(const H5FD_t * _file, unsigned long *flags /* out */)
/* Check for flags that are set by h5repart */
if(file && file->repart_members)
- *flags |= H5FD_FEAT_DIRTY_SBLK_LOAD; /* Mark the superblock dirty when it is loaded (so the family member sizes are rewritten) */
+ *flags |= H5FD_FEAT_DIRTY_DRVRINFO_LOAD; /* Mark the superblock dirty when it is loaded (so the family member sizes are rewritten) */
} /* end if */
FUNC_LEAVE_NOAPI(SUCCEED)
diff --git a/src/H5FDpublic.h b/src/H5FDpublic.h
index 92df63f..cabca06 100644
--- a/src/H5FDpublic.h
+++ b/src/H5FDpublic.h
@@ -198,12 +198,12 @@ typedef enum H5F_mem_t H5FD_mem_t;
*/
#define H5FD_FEAT_IGNORE_DRVRINFO 0x00000020
/*
- * Defining H5FD_FEAT_DIRTY_SBLK_LOAD for a VFL driver means that
- * the library will mark the superblock dirty when the file is opened
+ * Defining the H5FD_FEAT_DIRTY_DRVRINFO_LOAD for a VFL driver means that
+ * the library will mark the driver info dirty when the file is opened
* R/W. This will cause the driver info to be re-encoded when the file
* is flushed/closed.
*/
-#define H5FD_FEAT_DIRTY_SBLK_LOAD 0x00000040
+#define H5FD_FEAT_DIRTY_DRVRINFO_LOAD 0x00000040
/*
* Defining H5FD_FEAT_POSIX_COMPAT_HANDLE for a VFL driver means that
* the handle for the VFD (returned with the 'get_handle' callback) is
diff --git a/src/H5FS.c b/src/H5FS.c
index efe2091..7f437dd 100644
--- a/src/H5FS.c
+++ b/src/H5FS.c
@@ -206,7 +206,7 @@ HDfprintf(stderr, "%s: Opening free space manager, fs_addr = %a, nclasses = %Zu\
cache_udata.addr = fs_addr;
/* Protect the free space header */
- if(NULL == (fspace = (H5FS_t *)H5AC_protect(f, dxpl_id, H5AC_FSPACE_HDR, fs_addr, &cache_udata, H5AC_READ)))
+ if(NULL == (fspace = (H5FS_t *)H5AC_protect(f, dxpl_id, H5AC_FSPACE_HDR, fs_addr, &cache_udata, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_FSPACE, H5E_CANTPROTECT, NULL, "unable to load free space header")
#ifdef H5FS_DEBUG
HDfprintf(stderr, "%s: fspace->sect_addr = %a\n", FUNC, fspace->sect_addr);
@@ -317,7 +317,7 @@ HDfprintf(stderr, "%s: Deleting free space manager, fs_addr = %a\n", FUNC, fs_ad
#endif /* H5FS_DEBUG */
/* Protect the free space header */
- if(NULL == (fspace = (H5FS_t *)H5AC_protect(f, dxpl_id, H5AC_FSPACE_HDR, fs_addr, &cache_udata, H5AC_WRITE)))
+ if(NULL == (fspace = (H5FS_t *)H5AC_protect(f, dxpl_id, H5AC_FSPACE_HDR, fs_addr, &cache_udata, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_FSPACE, H5E_CANTPROTECT, FAIL, "unable to protect free space header")
/* Sanity check */
@@ -349,8 +349,19 @@ HDfprintf(stderr, "%s: Expunging free space section info from cache\n", FUNC);
#endif /* H5FS_DEBUG */
/* Evict the free space section info from the metadata cache */
/* (Free file space) */
- if(H5AC_expunge_entry(f, dxpl_id, H5AC_FSPACE_SINFO, fspace->sect_addr, H5AC__FREE_FILE_SPACE_FLAG) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTREMOVE, FAIL, "unable to remove free space section info from cache")
+ {
+ unsigned cache_flags = H5AC__NO_FLAGS_SET;
+
+ /* if the indirect block is in real file space, tell
+ * the cache to free its file space.
+ */
+ if (!H5F_IS_TMP_ADDR(f, fspace->sect_addr))
+ cache_flags |= H5AC__FREE_FILE_SPACE_FLAG;
+
+ if(H5AC_expunge_entry(f, dxpl_id, H5AC_FSPACE_SINFO, fspace->sect_addr, cache_flags) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTREMOVE, FAIL, "unable to remove free space section info from cache")
+ }
+
#ifdef H5FS_DEBUG
HDfprintf(stderr, "%s: Done expunging free space section info from cache\n", FUNC);
#endif /* H5FS_DEBUG */
@@ -923,8 +934,8 @@ H5FS_free(H5F_t *f, H5FS_t *fspace, hid_t dxpl_id)
cache_udata.f = f;
cache_udata.dxpl_id = dxpl_id;
cache_udata.fspace = fspace;
- if(NULL == (fspace->sinfo = (H5FS_sinfo_t *)H5AC_protect(f, dxpl_id, H5AC_FSPACE_SINFO, fspace->sect_addr, &cache_udata, H5AC_READ)))
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTPROTECT, FAIL, "unable to protect free space section info")
+ if(NULL == (fspace->sinfo = (H5FS_sinfo_t *)H5AC_protect(f, dxpl_id, H5AC_FSPACE_SINFO, fspace->sect_addr, &cache_udata, H5AC__READ_ONLY_FLAG)))
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTPROTECT, FAIL, "unable to protect free space section info")
/* Unload and release ownership of the free-space manager section info */
if(H5AC_unprotect(f, dxpl_id, H5AC_FSPACE_SINFO, fspace->sect_addr, fspace->sinfo, cache_flags) < 0)
@@ -964,8 +975,8 @@ H5FS_free(H5F_t *f, H5FS_t *fspace, hid_t dxpl_id)
cache_udata.nclasses = 0;
cache_udata.classes = NULL;
cache_udata.cls_init_udata = NULL;
- if(NULL == (fspace = (H5FS_t *)H5AC_protect(f, dxpl_id, H5AC_FSPACE_HDR, fspace->addr, &cache_udata, H5AC_READ)))
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTPROTECT, FAIL, "unable to protect free space section info")
+ if(NULL == (fspace = (H5FS_t *)H5AC_protect(f, dxpl_id, H5AC_FSPACE_HDR, fspace->addr, &cache_udata, H5AC__READ_ONLY_FLAG)))
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTPROTECT, FAIL, "unable to protect free space section info")
/* Unpin the free-space manager header */
if(H5AC_unpin_entry(fspace) < 0)
diff --git a/src/H5FScache.c b/src/H5FScache.c
index f68bf0f..93d7ed3 100644
--- a/src/H5FScache.c
+++ b/src/H5FScache.c
@@ -49,9 +49,6 @@
#define H5FS_HDR_VERSION 0 /* Header */
#define H5FS_SINFO_VERSION 0 /* Serialized sections */
-/* Size of stack buffer for serialized headers */
-#define H5FS_HDR_BUF_SIZE 256
-
/******************/
/* Local Typedefs */
@@ -60,7 +57,7 @@
/* User data for skip list iterator callback for iterating over section size nodes when syncing */
typedef struct {
H5FS_sinfo_t *sinfo; /* Free space section info */
- uint8_t **p; /* Pointer to address of buffer pointer to serialize with */
+ uint8_t **image; /* Pointer to address of buffer pointer to serialize with */
unsigned sect_cnt_size; /* # of bytes to encode section size counts in */
} H5FS_iter_ud_t;
@@ -75,22 +72,42 @@ typedef struct {
/********************/
/* Section info routines */
-static herr_t H5FS_sinfo_serialize_sect_cb(void *_item, void H5_ATTR_UNUSED *key, void *_udata);
-static herr_t H5FS_sinfo_serialize_node_cb(void *_item, void H5_ATTR_UNUSED *key, void *_udata);
+static herr_t H5FS__sinfo_serialize_sect_cb(void *_item, void H5_ATTR_UNUSED *key, void *_udata);
+static herr_t H5FS__sinfo_serialize_node_cb(void *_item, void H5_ATTR_UNUSED *key, void *_udata);
/* Metadata cache callbacks */
-static H5FS_t *H5FS_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata);
-static herr_t H5FS_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5FS_t *fspace, unsigned H5_ATTR_UNUSED * flags_ptr);
-static herr_t H5FS_cache_hdr_dest(H5F_t *f, H5FS_t *fspace);
-static herr_t H5FS_cache_hdr_clear(H5F_t *f, H5FS_t *fspace, hbool_t destroy);
-static herr_t H5FS_cache_hdr_size(const H5F_t *f, const H5FS_t *fspace, size_t *size_ptr);
-
-static H5FS_sinfo_t *H5FS_cache_sinfo_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata);
-static herr_t H5FS_cache_sinfo_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5FS_sinfo_t *sinfo, unsigned H5_ATTR_UNUSED * flags_ptr);
-static herr_t H5FS_cache_sinfo_dest(H5F_t *f, H5FS_sinfo_t *sinfo);
-static herr_t H5FS_cache_sinfo_clear(H5F_t *f, H5FS_sinfo_t *sinfo, hbool_t destroy);
-static herr_t H5FS_cache_sinfo_notify(H5AC_notify_action_t action, H5FS_sinfo_t *sinfo);
-static herr_t H5FS_cache_sinfo_size(const H5F_t *f, const H5FS_sinfo_t *sinfo, size_t *size_ptr);
+static herr_t H5FS__cache_hdr_get_load_size(const void *image_ptr, void *udata,
+ size_t *image_len, size_t *actual_len,
+ hbool_t *compressed_ptr, size_t *compressed_image_len_ptr);
+static htri_t H5FS__cache_hdr_verify_chksum(const void *image_ptr, size_t len, void *udata_ptr);
+static void *H5FS__cache_hdr_deserialize(const void *image, size_t len,
+ void *udata, hbool_t *dirty);
+static herr_t H5FS__cache_hdr_image_len(const void *thing, size_t *image_len,
+ hbool_t *compressed_ptr, size_t *compressed_image_len_ptr);
+static herr_t H5FS__cache_hdr_pre_serialize(const H5F_t *f, hid_t dxpl_id,
+ void *thing, haddr_t addr, size_t len, size_t compressed_len,
+ haddr_t *new_addr, size_t *new_len, size_t *new_compressed_len,
+ unsigned *flags);
+static herr_t H5FS__cache_hdr_serialize(const H5F_t *f, void *image,
+ size_t len, void *thing);
+static herr_t H5FS__cache_hdr_free_icr(void *thing);
+
+static herr_t H5FS__cache_sinfo_get_load_size(const void *image_ptr, void *udata,
+ size_t *image_len, size_t *actual_len,
+ hbool_t *compressed_ptr, size_t *compressed_image_len_ptr);
+static htri_t H5FS__cache_sinfo_verify_chksum(const void *image_ptr, size_t len, void *udata_ptr);
+static void *H5FS__cache_sinfo_deserialize(const void *image, size_t len,
+ void *udata, hbool_t *dirty);
+static herr_t H5FS__cache_sinfo_image_len(const void *thing, size_t *image_len,
+ hbool_t *compressed_ptr, size_t *compressed_image_len_ptr);
+static herr_t H5FS__cache_sinfo_pre_serialize(const H5F_t *f, hid_t dxpl_id,
+ void *thing, haddr_t addr, size_t len, size_t compressed_len,
+ haddr_t *new_addr, size_t *new_len, size_t *new_compressed_len,
+ unsigned *flags);
+static herr_t H5FS__cache_sinfo_serialize(const H5F_t *f, void *image,
+ size_t len, void *thing);
+static herr_t H5FS__cache_sinfo_notify(H5AC_notify_action_t action, void *thing);
+static herr_t H5FS__cache_sinfo_free_icr(void *thing);
/*********************/
@@ -99,24 +116,38 @@ static herr_t H5FS_cache_sinfo_size(const H5F_t *f, const H5FS_sinfo_t *sinfo, s
/* H5FS header inherits cache-like properties from H5AC */
const H5AC_class_t H5AC_FSPACE_HDR[1] = {{
- H5AC_FSPACE_HDR_ID,
- (H5AC_load_func_t)H5FS_cache_hdr_load,
- (H5AC_flush_func_t)H5FS_cache_hdr_flush,
- (H5AC_dest_func_t)H5FS_cache_hdr_dest,
- (H5AC_clear_func_t)H5FS_cache_hdr_clear,
- (H5AC_notify_func_t)NULL,
- (H5AC_size_func_t)H5FS_cache_hdr_size,
+ H5AC_FSPACE_HDR_ID, /* Metadata client ID */
+ "Free Space Header", /* Metadata client name (for debugging) */
+ H5FD_MEM_FSPACE_HDR, /* File space memory type for client */
+ H5AC__CLASS_NO_FLAGS_SET, /* Client class behavior flags */
+ H5FS__cache_hdr_get_load_size, /* 'get_load_size' callback */
+ H5FS__cache_hdr_verify_chksum, /* 'verify_chksum' callback */
+ H5FS__cache_hdr_deserialize, /* 'deserialize' callback */
+ H5FS__cache_hdr_image_len, /* 'image_len' callback */
+ H5FS__cache_hdr_pre_serialize, /* 'pre_serialize' callback */
+ H5FS__cache_hdr_serialize, /* 'serialize' callback */
+ NULL, /* 'notify' callback */
+ H5FS__cache_hdr_free_icr, /* 'free_icr' callback */
+ NULL, /* 'clear' callback */
+ NULL, /* 'fsf_size' callback */
}};
-/* H5FS serialized sections inherit cache-like properties from H5AC */
+/* H5FS section info inherits cache-like properties from H5AC */
const H5AC_class_t H5AC_FSPACE_SINFO[1] = {{
- H5AC_FSPACE_SINFO_ID,
- (H5AC_load_func_t)H5FS_cache_sinfo_load,
- (H5AC_flush_func_t)H5FS_cache_sinfo_flush,
- (H5AC_dest_func_t)H5FS_cache_sinfo_dest,
- (H5AC_clear_func_t)H5FS_cache_sinfo_clear,
- (H5AC_notify_func_t)H5FS_cache_sinfo_notify,
- (H5AC_size_func_t)H5FS_cache_sinfo_size,
+ H5AC_FSPACE_SINFO_ID, /* Metadata client ID */
+ "Free Space Section Info", /* Metadata client name (for debugging) */
+ H5FD_MEM_FSPACE_SINFO, /* File space memory type for client */
+ H5AC__CLASS_NO_FLAGS_SET, /* Client class behavior flags */
+ H5FS__cache_sinfo_get_load_size, /* 'get_load_size' callback */
+ H5FS__cache_sinfo_verify_chksum, /* 'verify_chksum' callback */
+ H5FS__cache_sinfo_deserialize, /* 'deserialize' callback */
+ H5FS__cache_sinfo_image_len, /* 'image_len' callback */
+ H5FS__cache_sinfo_pre_serialize, /* 'pre_serialize' callback */
+ H5FS__cache_sinfo_serialize, /* 'serialize' callback */
+ H5FS__cache_sinfo_notify, /* 'notify' callback */
+ H5FS__cache_sinfo_free_icr, /* 'free_icr' callback */
+ NULL, /* 'clear' callback */
+ NULL, /* 'fsf_size' callback */
}};
@@ -129,41 +160,117 @@ const H5AC_class_t H5AC_FSPACE_SINFO[1] = {{
/* Local Variables */
/*******************/
-/* Declare a free list to manage free space section data to/from disk */
-H5FL_BLK_DEFINE_STATIC(sect_block);
-
/*-------------------------------------------------------------------------
- * Function: H5FS_cache_hdr_load
+ * Function: H5FS__cache_hdr_get_load_size
*
- * Purpose: Loads a free space manager header from the disk.
+ * Purpose: Compute the size of the data structure on disk.
*
- * Return: Success: Pointer to a new free space header
- * Failure: NULL
+ * Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
- * May 2 2006
+ * koziol@hdfgroup.org
+ * August 14, 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FS__cache_hdr_get_load_size(const void *_image, void *_udata, size_t *image_len, size_t *actual_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr)
+{
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ H5FS_hdr_cache_ud_t *udata = (H5FS_hdr_cache_ud_t *)_udata; /* User-data for metadata cache callback */
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Check arguments */
+ HDassert(udata);
+ HDassert(udata->f);
+ HDassert(image_len);
+
+ if(image == NULL) {
+ /* Set the image length size */
+ *image_len = (size_t)H5FS_HEADER_SIZE(udata->f);
+ } else {
+ HDassert(actual_len);
+ HDassert(*actual_len == *image_len);
+ }
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5FS__cache_hdr_get_load_size() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FS__cache_hdr_verify_chksum
+ *
+ * Purpose: Verify the computed checksum of the data structure is the
+ * same as the stored chksum.
+ *
+ * Return: Success: TRUE/FALSE
+ * Failure: Negative
+ *
+ * Programmer: Vailin Choi; Aug 2015
+ *
+ *-------------------------------------------------------------------------
+ */
+htri_t
+H5FS__cache_hdr_verify_chksum(const void *_image, size_t len, void H5_ATTR_UNUSED *_udata)
+{
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ uint32_t stored_chksum; /* Stored metadata checksum value */
+ uint32_t computed_chksum; /* Computed metadata checksum value */
+ htri_t ret_value = TRUE; /* Return value */
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Check arguments */
+ HDassert(image);
+
+ /* Get stored and computed checksums */
+ H5F_get_checksums(image, len, &stored_chksum, &computed_chksum);
+
+ if(stored_chksum != computed_chksum)
+ ret_value = FALSE;
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FS__cache_hdr_verify_chksum() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FS__cache_hdr_deserialize
+ *
+ * Purpose: Given a buffer containing the on disk image of the free space
+ * manager section info, allocate an instance of H5FS_t, load
+ * it with the data contained in the image, and return a pointer
+ * to the new instance.
+ *
+ * Return: Success: Pointer to new object
+ * Failure: NULL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * August 18 2013
*
*-------------------------------------------------------------------------
*/
-static H5FS_t *
-H5FS_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
+static void *
+H5FS__cache_hdr_deserialize(const void *_image, size_t len, void *_udata,
+ hbool_t H5_ATTR_UNUSED *dirty)
{
- H5FS_t *fspace = NULL; /* Free space header info */
- H5FS_hdr_cache_ud_t *udata = (H5FS_hdr_cache_ud_t *)_udata; /* user data for callback */
- H5WB_t *wb = NULL; /* Wrapped buffer for header data */
- uint8_t hdr_buf[H5FS_HDR_BUF_SIZE]; /* Buffer for header */
- uint8_t *hdr; /* Pointer to header buffer */
- const uint8_t *p; /* Pointer into raw data buffer */
+ H5FS_t *fspace = NULL; /* Free space header info */
+ H5FS_hdr_cache_ud_t *udata = (H5FS_hdr_cache_ud_t *)_udata; /* User data for callback */
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ uint32_t stored_chksum; /* Stored metadata checksum value */
unsigned nclasses; /* Number of section classes */
H5FS_t *ret_value; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
/* Check arguments */
- HDassert(f);
+ HDassert(image);
HDassert(udata);
+ HDassert(udata->f);
/* Allocate a new free space manager */
if(NULL == (fspace = H5FS__new(udata->f, udata->nclasses, udata->classes, udata->cls_init_udata)))
@@ -172,423 +279,676 @@ H5FS_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
/* Set free space manager's internal information */
fspace->addr = udata->addr;
- /* Wrap the local buffer for serialized header info */
- if(NULL == (wb = H5WB_wrap(hdr_buf, sizeof(hdr_buf))))
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTINIT, NULL, "can't wrap buffer")
-
- /* Get a pointer to a buffer that's large enough for header */
- if(NULL == (hdr = (uint8_t *)H5WB_actual(wb, fspace->hdr_size)))
- HGOTO_ERROR(H5E_FSPACE, H5E_NOSPACE, NULL, "can't get actual buffer")
-
- /* Read and validate header from disk */
- if(H5F_read_check_metadata(f, dxpl_id, H5FD_MEM_FSPACE_HDR, H5AC_FSPACE_HDR_ID, addr, fspace->hdr_size, fspace->hdr_size, hdr) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_BADVALUE, NULL, "incorrect metadata checksum for free space header")
-
- p = hdr;
-
/* Magic number */
- if(HDmemcmp(p, H5FS_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC))
+ if(HDmemcmp(image, H5FS_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC))
HGOTO_ERROR(H5E_FSPACE, H5E_CANTLOAD, NULL, "wrong free space header signature")
- p += H5_SIZEOF_MAGIC;
+ image += H5_SIZEOF_MAGIC;
/* Version */
- if(*p++ != H5FS_HDR_VERSION)
+ if(*image++ != H5FS_HDR_VERSION)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTLOAD, NULL, "wrong free space header version")
/* Client ID */
- fspace->client = (H5FS_client_t)*p++;
+ fspace->client = (H5FS_client_t)*image++;
if(fspace->client >= H5FS_NUM_CLIENT_ID)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTLOAD, NULL, "unknown client ID in free space header")
/* Total space tracked */
- H5F_DECODE_LENGTH(udata->f, p, fspace->tot_space);
+ H5F_DECODE_LENGTH(udata->f, image, fspace->tot_space);
/* Total # of free space sections tracked */
- H5F_DECODE_LENGTH(udata->f, p, fspace->tot_sect_count);
+ H5F_DECODE_LENGTH(udata->f, image, fspace->tot_sect_count);
/* # of serializable free space sections tracked */
- H5F_DECODE_LENGTH(udata->f, p, fspace->serial_sect_count);
+ H5F_DECODE_LENGTH(udata->f, image, fspace->serial_sect_count);
/* # of ghost free space sections tracked */
- H5F_DECODE_LENGTH(udata->f, p, fspace->ghost_sect_count);
+ H5F_DECODE_LENGTH(udata->f, image, fspace->ghost_sect_count);
/* # of section classes */
/* (only check if we actually have some classes) */
- UINT16DECODE(p, nclasses);
+ UINT16DECODE(image, nclasses);
if(fspace->nclasses > 0 && fspace->nclasses != nclasses)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTLOAD, NULL, "section class count mismatch")
/* Shrink percent */
- UINT16DECODE(p, fspace->shrink_percent);
+ UINT16DECODE(image, fspace->shrink_percent);
/* Expand percent */
- UINT16DECODE(p, fspace->expand_percent);
+ UINT16DECODE(image, fspace->expand_percent);
- /* Size of address space free space sections are within (log2 of actual value) */
- UINT16DECODE(p, fspace->max_sect_addr);
+ /* Size of address space free space sections are within
+ * (log2 of actual value)
+ */
+ UINT16DECODE(image, fspace->max_sect_addr);
/* Max. size of section to track */
- H5F_DECODE_LENGTH(udata->f, p, fspace->max_sect_size);
+ H5F_DECODE_LENGTH(udata->f, image, fspace->max_sect_size);
/* Address of serialized free space sections */
- H5F_addr_decode(udata->f, &p, &fspace->sect_addr);
+ H5F_addr_decode(udata->f, &image, &fspace->sect_addr);
/* Size of serialized free space sections */
- H5F_DECODE_LENGTH(udata->f, p, fspace->sect_size);
+ H5F_DECODE_LENGTH(udata->f, image, fspace->sect_size);
/* Allocated size of serialized free space sections */
- H5F_DECODE_LENGTH(udata->f, p, fspace->alloc_sect_size);
+ H5F_DECODE_LENGTH(udata->f, image, fspace->alloc_sect_size);
+
+ /* checksum verification already done in verify_chksum cb */
- /* Already decoded and compared stored checksum earlier, when reading */
+ /* Metadata checksum */
+ UINT32DECODE(image, stored_chksum);
/* Sanity check */
- HDassert((size_t)(p - (const uint8_t *)hdr) == (fspace->hdr_size - H5_SIZEOF_CHKSUM));
+ HDassert((size_t)(image - (const uint8_t *)_image) <= len);
/* Set return value */
ret_value = fspace;
done:
/* Release resources */
- if(wb && H5WB_unwrap(wb) < 0)
- HDONE_ERROR(H5E_FSPACE, H5E_CLOSEERROR, NULL, "can't close wrapped buffer")
if(!ret_value && fspace)
if(H5FS__hdr_dest(fspace) < 0)
HDONE_ERROR(H5E_FSPACE, H5E_CANTFREE, NULL, "unable to destroy free space header")
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5FS_cache_hdr_load() */ /*lint !e818 Can't make udata a pointer to const */
+} /* end H5FS__cache_hdr_deserialize() */
/*-------------------------------------------------------------------------
- * Function: H5FS_cache_hdr_flush
+ * Function: H5FS__cache_hdr_image_len
*
- * Purpose: Flushes a dirty free space header to disk.
+ * Purpose: Compute the size of the data structure on disk and return
+ * it in *image_len.
*
- * Return: SUCCEED/FAIL
+ * Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
- * May 2 2006
+ * koziol@hdfgroup.org
+ * August 14, 2013
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5FS_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5FS_t *fspace, unsigned H5_ATTR_UNUSED * flags_ptr)
+H5FS__cache_hdr_image_len(const void *_thing, size_t *image_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr)
{
- H5WB_t *wb = NULL; /* Wrapped buffer for header data */
- uint8_t hdr_buf[H5FS_HDR_BUF_SIZE]; /* Buffer for header */
- herr_t ret_value = SUCCEED; /* Return value */
+ const H5FS_t *fspace = (const H5FS_t *)_thing; /* Pointer to the object */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Check arguments */
+ HDassert(fspace);
+ HDassert(fspace->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(fspace->cache_info.type == H5AC_FSPACE_HDR);
+ HDassert(image_len);
+
+ /* Set the image length size */
+ *image_len = fspace->hdr_size;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5FS__cache_hdr_image_len() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FS__cache_hdf_pre_serialize
+ *
+ * Purpose: The free space manager header contains the address, size, and
+ * allocation size of the free space manager section info. However,
+ * since it is possible for the section info to either not be allocated
+ * at all, or be allocated in temporary (AKA imaginary) files space,
+ * it is possible for the above mentioned fields to contain giberish
+ * when the free space manager header is serialized.
+ *
+ * This function exists to prevent this problem. It does so by
+ * forcing allocation of real file space for the section information.
+ *
+ * Note that in the Version 2 cache, this problem was dealt with by
+ * simply flushing the section info before flushing the header. This
+ * was possible, since the clients handled file I/O directly. As
+ * this responsibility has moved to the cache in Version 3, this
+ * solution is no longer directly applicable.
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: John Mainzer
+ * 6/21/14
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FS__cache_hdr_pre_serialize(const H5F_t *f, hid_t dxpl_id, void *_thing,
+ haddr_t addr, size_t H5_ATTR_UNUSED len, size_t H5_ATTR_UNUSED compressed_len,
+ haddr_t *new_addr, size_t *new_len, size_t H5_ATTR_UNUSED *new_compressed_len,
+ unsigned *flags)
+{
+ H5FS_t *fspace = (H5FS_t *)_thing; /* Pointer to the object */
+ herr_t ret_value = SUCCEED; /* Return value */
- /* check arguments */
+ FUNC_ENTER_STATIC_TAG(dxpl_id, H5AC__FREESPACE_TAG, FAIL)
+
+ /* Sanity check */
HDassert(f);
- HDassert(H5F_addr_defined(addr));
HDassert(fspace);
- HDassert(H5F_addr_defined(fspace->addr));
+ HDassert(fspace->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(fspace->cache_info.type == H5AC_FSPACE_HDR);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(new_addr);
+ HDassert(new_len);
+ HDassert(flags);
- /* Check if the header "owns" the section info */
if(fspace->sinfo) {
- /* Sanity check - should not be trying to destroy header if it still
- * "owns" section info
+ /* This implies that the header "owns" the section info.
+ *
+ * Unfortunately, the comments in the code are not clear as to
+ * what this means, but from reviewing the code (most particularly
+ * H5FS_close(), H5FS_sinfo_lock, and H5FS_sinfo_unlock()), I
+ * gather that it means that the header is maintaining a pointer to
+ * an instance of H5FS_sinfo_t in which free space data is
+ * maintained, and either:
+ *
+ * 1) The instance of H5FS_sinfo_t is not in the metadata cache.
+ *
+ * This will be TRUE iff H5F_addr_defined(fspace->sect_addr)
+ * is FALSE, and fspace->sinfo is not NULL. This is sometimes
+ * referred to as "floating" section info in the comments.
+ *
+ * If the section info structure contains free space data
+ * that must be placed on disk eventually, then
+ *
+ * fspace->serial_sect_count > 0
+ *
+ * and
+ *
+ * H5F_addr_defined(fspace->addr)
+ *
+ * will both be TRUE. If this contition does not hold, then
+ * either the free space info is not persistant
+ * (!H5F_addr_defined(fspace->addr)???) or the section info
+ * contains no free space data that must be written to file
+ * ( fspace->serial_sect_count == 0 ).
+ *
+ * 2) The instance of H5FS_sinfo_t is in the metadata cache with
+ * address in temporary file space (AKA imaginary file space).
+ * The entry may or may not be protected, and if protected, it
+ * may be protected either RW or RO (as indicated by
+ * fspace->sinfo_protected and fspace->sinfo_accmod).
+ *
+ * 3) The instance of H5FS_sinfo_t is in the metadata cache with
+ * address in real file space. As in case 2) above, the entry
+ * may or may not be protected, and if protected, it
+ * may be protected either RW or RO (as indicated by
+ * fspace->sinfo_protected and fspace->sinfo_accmod).
+ *
+ * Observe that fspace->serial_sect_count > 0 must be TRUE in
+ * cases 2) and 3), as the section info should not be stored on
+ * disk if it doesn't exist. Similarly, since the section info
+ * will not be stored to disk unless the header is,
+ * H5F_addr_defined(fspace->addr) must hold as well.
+ *
+ * As the objective is to touch up the free space manager header
+ * so that it contains sensical data on the size and location of
+ * the section information, we have to handle each of the above
+ * cases differently.
+ *
+ * Case 1) If either fspace->serial_sect_count == 0 or
+ * ! H5F_addr_defined(fspace->addr) do nothing as either
+ * the free space manager data is not persistant, or the
+ * section info is empty.
+ *
+ * Otherwise, allocate space for the section info in real
+ * file space, insert the section info at this location, and
+ * set fspace->sect_addr, fspace->sect_size, and
+ * fspace->alloc_sect_size to reflect the new location
+ * of the section info. Note that it is not necessary to
+ * force a write of the section info.
+ *
+ * Case 2) Allocate space for the section info in real file space,
+ * and tell the metadata cache to relocate the entry.
+ * Update fspace->sect_addr, fspace->sect_size, and
+ * fspace->alloc_sect_size to reflect the new location.
+ *
+ * Case 3) Nothing to be done in this case, although it is useful
+ * to perform sanity checks.
+ *
+ * Note that while we may alter the contents of the free space
+ * header in cases 1) and 2), there is no need to mark the header
+ * as dirty, as the metadata cache would not be attempting to
+ * serialize the header if it though it was clean.
*/
- HDassert(!destroy);
-
- /* Check if the section info is dirty */
- if(fspace->sinfo->dirty) {
- if(fspace->serial_sect_count > 0) {
- /* Check if we need to allocate space for section info */
- if(H5F_IS_TMP_ADDR(f, fspace->sect_addr) || !H5F_addr_defined(fspace->sect_addr)) {
- /* Sanity check */
- HDassert(fspace->sect_size > 0);
-
- /* Allocate space for the section info in file */
- if(HADDR_UNDEF == (fspace->sect_addr = H5MF_alloc(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, fspace->sect_size)))
- HGOTO_ERROR(H5E_FSPACE, H5E_NOSPACE, FAIL, "file allocation failed for free space sections")
- fspace->alloc_sect_size = (size_t)fspace->sect_size;
-
- /* Mark header dirty */
- /* (don't use cache API, since we're in a callback) */
- fspace->cache_info.is_dirty = TRUE;
- } /* end if */
-
- /* Write section info to file */
- if(H5FS_cache_sinfo_flush(f, dxpl_id, FALSE, fspace->sect_addr, fspace->sinfo, NULL) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTFLUSH, FAIL, "unable to save free space section info to disk")
+ if(fspace->serial_sect_count > 0 && H5F_addr_defined(fspace->addr)) {
+ /* Sanity check */
+ HDassert(fspace->sect_size > 0);
+
+ if(!H5F_addr_defined(fspace->sect_addr)) { /* case 1 */
+ /* allocate file space for the section info, and insert it
+ * into the metadata cache.
+ */
+ if(HADDR_UNDEF == (fspace->sect_addr = H5MF_alloc((H5F_t *)f, H5FD_MEM_FSPACE_SINFO, dxpl_id, fspace->sect_size)))
+ HGOTO_ERROR(H5E_FSPACE, H5E_NOSPACE, FAIL, "file allocation failed for free space sections")
+
+ fspace->alloc_sect_size = (size_t)fspace->sect_size;
+ if(H5AC_insert_entry((H5F_t *)f, dxpl_id, H5AC_FSPACE_SINFO, fspace->sect_addr, fspace->sinfo, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTINIT, FAIL, "can't add free space sections to cache")
+
+ HDassert(fspace->sinfo->cache_info.size == fspace->alloc_sect_size);
+
+ /* the metadata cache is now managing the section info,
+ * so set fspace->sinfo to NULL.
+ */
+ fspace->sinfo = NULL;
} /* end if */
-
- /* Mark section info clean */
- fspace->sinfo->dirty = FALSE;
- } /* end if */
+ else if(H5F_IS_TMP_ADDR(f, fspace->sect_addr)) { /* case 2 */
+ haddr_t new_sect_addr;
+
+ /* move the section info from temporary (AKA imaginary) file
+ * space to real file space.
+ */
+
+ /* if my reading of the code is correct, this should always
+ * be the case. If not, we will have to add code to resize
+ * file space allocation for section info as well as moving it.
+ */
+ HDassert(fspace->sect_size > 0);
+ HDassert(fspace->alloc_sect_size == (size_t)fspace->sect_size);
+
+ /* Allocate space for the section info in file */
+ if(HADDR_UNDEF == (new_sect_addr = H5MF_alloc((H5F_t *)f, H5FD_MEM_FSPACE_SINFO, dxpl_id, fspace->sect_size)))
+ HGOTO_ERROR(H5E_FSPACE, H5E_NOSPACE, FAIL, "file allocation failed for free space sections")
+
+ fspace->alloc_sect_size = (size_t)fspace->sect_size;
+ HDassert(fspace->sinfo->cache_info.size == fspace->alloc_sect_size);
+
+ /* Let the metadata cache know the section info moved */
+ if(H5AC_move_entry((H5F_t *)f, H5AC_FSPACE_SINFO, fspace->sect_addr, new_sect_addr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTMOVE, FAIL, "unable to move section info")
+
+ fspace->sect_addr = new_sect_addr;
+ } /* end else-if */
+ else { /* case 3 -- nothing to do but sanity checking */
+ /* if my reading of the code is correct, this should always
+ * be the case. If not, we will have to add code to resize
+ * file space allocation for section info.
+ */
+ HDassert(fspace->sect_size > 0);
+ HDassert(fspace->alloc_sect_size == (size_t)fspace->sect_size);
+ } /* end else */
+ } /* end else */
+ else {
+ /* for one reason or another (see comment above) there should
+ * not be any file space allocated for the section info.
+ */
+ HDassert(!H5F_addr_defined(fspace->sect_addr));
+ } /* end else */
} /* end if */
- else if(fspace->serial_sect_count > 0)
- /* Sanity check that section info has address */
- HDassert(H5F_addr_defined(fspace->sect_addr));
+ else if(H5F_addr_defined(fspace->sect_addr)) {
+ /* Here the metadata cache is managing the section info.
+ *
+ * Do some sanity checks, and then test to see if the section
+ * info is in real file space. If it isn't relocate it into
+ * real file space lest the header be written to file with
+ * a nonsense section info address.
+ */
+ HDassert(fspace->serial_sect_count > 0);
+ HDassert(fspace->sect_size > 0);
+ HDassert(fspace->alloc_sect_size == (size_t)fspace->sect_size);
+
+ if(H5F_IS_TMP_ADDR(f, fspace->sect_addr)) {
+ unsigned sect_status = 0;
+ haddr_t new_sect_addr;
+
+ /* we have work to do -- must relocate section info into
+ * real file space.
+ *
+ * Since the section info address is in temporary space (AKA
+ * imaginary space), it follows that the entry must be in
+ * cache. Further, since fspace->sinfo is NULL, it must be
+ * unprotected and un-pinned. Start by verifying this.
+ */
+ if(H5AC_get_entry_status(f, fspace->sect_addr, &sect_status) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTGET, FAIL, "can't get section info status")
+
+ HDassert(sect_status & H5AC_ES__IN_CACHE);
+ HDassert((sect_status & H5AC_ES__IS_PROTECTED) == 0);
+ HDassert((sect_status & H5AC_ES__IS_PINNED) == 0);
- if(fspace->cache_info.is_dirty) {
- uint8_t *hdr; /* Pointer to header buffer */
- uint8_t *p; /* Pointer into raw data buffer */
- uint32_t metadata_chksum; /* Computed metadata checksum value */
+ /* Allocate space for the section info in file */
+ if(HADDR_UNDEF == (new_sect_addr = H5MF_alloc((H5F_t *)f, H5FD_MEM_FSPACE_SINFO, dxpl_id, fspace->sect_size)))
+ HGOTO_ERROR(H5E_FSPACE, H5E_NOSPACE, FAIL, "file allocation failed for free space sections")
- /* Wrap the local buffer for serialized header info */
- if(NULL == (wb = H5WB_wrap(hdr_buf, sizeof(hdr_buf))))
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTINIT, FAIL, "can't wrap buffer")
+ fspace->alloc_sect_size = (size_t)fspace->sect_size;
- /* Get a pointer to a buffer that's large enough for header */
- if(NULL == (hdr = (uint8_t *)H5WB_actual(wb, fspace->hdr_size)))
- HGOTO_ERROR(H5E_FSPACE, H5E_NOSPACE, FAIL, "can't get actual buffer")
+ /* Sanity check */
+ HDassert(!H5F_addr_eq(fspace->sect_addr, new_sect_addr));
- /* Get temporary pointer to header */
- p = hdr;
+ /* Let the metadata cache know the section info moved */
+ if(H5AC_move_entry((H5F_t *)f, H5AC_FSPACE_SINFO, fspace->sect_addr, new_sect_addr) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTMOVE, FAIL, "unable to move section info")
- /* Magic number */
- HDmemcpy(p, H5FS_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC);
- p += H5_SIZEOF_MAGIC;
+ /* Update the internal address for the section info */
+ fspace->sect_addr = new_sect_addr;
- /* Version # */
- *p++ = H5FS_HDR_VERSION;
+ /* No need to mark the header dirty, as we are about to
+ * serialize it.
+ */
+ } /* end if */
+ } /* end else-if */
+ else { /* there is no section info at present */
+ /* do some sanity checks */
+ HDassert(fspace->serial_sect_count == 0);
+ HDassert(fspace->tot_sect_count == fspace->ghost_sect_count);
+ } /* end else */
- /* Client ID */
- *p++ = fspace->client;
+ /* what ever happened above, set *flags to 0 */
+ *flags = 0;
- /* Total space tracked */
- H5F_ENCODE_LENGTH(f, p, fspace->tot_space);
+done:
+ FUNC_LEAVE_NOAPI_TAG(ret_value, FAIL)
+} /* end H5FS__cache_hdr_pre_serialize() */
- /* Total # of free space sections tracked */
- H5F_ENCODE_LENGTH(f, p, fspace->tot_sect_count);
+
+/*-------------------------------------------------------------------------
+ * Function: H5FS__cache_hdr_serialize
+ *
+ * Purpose: Given an instance of H5FS_t and a suitably sized buffer,
+ * serialize the contents of the instance of H5FS_t and write
+ * its contents to the buffer. This buffer will be used to
+ * write the image of the instance to file.
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: John Mainzer
+ * 6/21/14
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FS__cache_hdr_serialize(const H5F_t *f, void *_image, size_t len,
+ void *_thing)
+{
+ H5FS_t *fspace = (H5FS_t *)_thing; /* Pointer to the object */
+ uint8_t *image = (uint8_t *)_image; /* Pointer into raw data buffer */
+ uint32_t metadata_chksum; /* Computed metadata checksum value */
+ herr_t ret_value = SUCCEED; /* Return value */
- /* # of serializable free space sections tracked */
- H5F_ENCODE_LENGTH(f, p, fspace->serial_sect_count);
+ FUNC_ENTER_STATIC_NOERR
- /* # of ghost free space sections tracked */
- H5F_ENCODE_LENGTH(f, p, fspace->ghost_sect_count);
+ /* Check arguments */
+ HDassert(f);
+ HDassert(image);
+ HDassert(fspace);
+ HDassert(fspace->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(fspace->cache_info.type == H5AC_FSPACE_HDR);
+ HDassert(fspace->hdr_size == len);
+
+ /* The section information does not always exits, and if it does,
+ * it is not always in the cache. To make matters more interesting,
+ * even if it is in the cache, it may not be in real file space.
+ *
+ * The pre-serialize function should have moved the section info
+ * into real file space if necessary before this function was called.
+ * The following asserts are a cursory check on this.
+ */
+ HDassert((! H5F_addr_defined(fspace->sect_addr)) || (! H5F_IS_TMP_ADDR(f, fspace->sect_addr)));
+ HDassert((! H5F_addr_defined(fspace->sect_addr)) ||
+ ((fspace->serial_sect_count > 0) &&
+ (fspace->sect_size > 0) &&
+ (fspace->alloc_sect_size == (size_t)fspace->sect_size)));
- /* # of section classes */
- UINT16ENCODE(p, fspace->nclasses);
+ /* Magic number */
+ HDmemcpy(image, H5FS_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ image += H5_SIZEOF_MAGIC;
- /* Shrink percent */
- UINT16ENCODE(p, fspace->shrink_percent);
+ /* Version # */
+ *image++ = H5FS_HDR_VERSION;
- /* Expand percent */
- UINT16ENCODE(p, fspace->expand_percent);
+ /* Client ID */
+ *image++ = fspace->client;
- /* Size of address space free space sections are within (log2 of actual value) */
- UINT16ENCODE(p, fspace->max_sect_addr);
+ /* Total space tracked */
+ H5F_ENCODE_LENGTH(f, image, fspace->tot_space);
- /* Max. size of section to track */
- H5F_ENCODE_LENGTH(f, p, fspace->max_sect_size);
+ /* Total # of free space sections tracked */
+ H5F_ENCODE_LENGTH(f, image, fspace->tot_sect_count);
- /* Address of serialized free space sections */
- H5F_addr_encode(f, &p, fspace->sect_addr);
+ /* # of serializable free space sections tracked */
+ H5F_ENCODE_LENGTH(f, image, fspace->serial_sect_count);
- /* Size of serialized free space sections */
- H5F_ENCODE_LENGTH(f, p, fspace->sect_size);
+ /* # of ghost free space sections tracked */
+ H5F_ENCODE_LENGTH(f, image, fspace->ghost_sect_count);
- /* Allocated size of serialized free space sections */
- H5F_ENCODE_LENGTH(f, p, fspace->alloc_sect_size);
+ /* # of section classes */
+ UINT16ENCODE(image, fspace->nclasses);
- /* Compute checksum */
- metadata_chksum = H5_checksum_metadata(hdr, (size_t)(p - (uint8_t *)hdr), 0);
+ /* Shrink percent */
+ UINT16ENCODE(image, fspace->shrink_percent);
- /* Metadata checksum */
- UINT32ENCODE(p, metadata_chksum);
+ /* Expand percent */
+ UINT16ENCODE(image, fspace->expand_percent);
- /* Write the free space header. */
- HDassert((size_t)(p - hdr) == fspace->hdr_size);
- if(H5F_block_write(f, H5FD_MEM_FSPACE_HDR, addr, fspace->hdr_size, dxpl_id, hdr) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTFLUSH, FAIL, "unable to save free space header to disk")
+ /* Size of address space free space sections are within (log2 of
+ * actual value)
+ */
+ UINT16ENCODE(image, fspace->max_sect_addr);
- fspace->cache_info.is_dirty = FALSE;
- } /* end if */
+ /* Max. size of section to track */
+ H5F_ENCODE_LENGTH(f, image, fspace->max_sect_size);
- if(destroy)
- if(H5FS_cache_hdr_dest(f, fspace) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to destroy free space header")
+ /* Address of serialized free space sections */
+ H5F_addr_encode(f, &image, fspace->sect_addr);
-done:
- /* Release resources */
- if(wb && H5WB_unwrap(wb) < 0)
- HDONE_ERROR(H5E_FSPACE, H5E_CLOSEERROR, FAIL, "can't close wrapped buffer")
+ /* Size of serialized free space sections */
+ H5F_ENCODE_LENGTH(f, image, fspace->sect_size);
+
+ /* Allocated size of serialized free space sections */
+ H5F_ENCODE_LENGTH(f, image, fspace->alloc_sect_size);
+
+ /* Compute checksum */
+ metadata_chksum = H5_checksum_metadata((uint8_t *)_image, (size_t)(image - (uint8_t *)_image), 0);
+
+ /* Metadata checksum */
+ UINT32ENCODE(image, metadata_chksum);
+
+ /* sanity checks */
+ HDassert((size_t)(image - (uint8_t *)_image) == fspace->hdr_size);
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5FS_cache_hdr_flush() */
+} /* H5FS__cache_hdr_serialize() */
+
+/***************************************/
+/* no H5FS__cache_hdr_notify() function */
+/***************************************/
/*-------------------------------------------------------------------------
- * Function: H5FS_cache_hdr_dest
+ * Function: H5FS__cache_hdr_free_icr
*
- * Purpose: Destroys a free space header in memory.
+ * Purpose: Destroys a free space header in memory.
*
- * Return: SUCCEED/FAIL
+ * Note: The metadata cache sets the object's cache_info.magic to
+ * H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC before calling a free_icr
+ * callback (checked in assert).
*
- * Programmer: Quincey Koziol
- * May 2 2006
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * May 2 2006
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5FS_cache_hdr_dest(H5F_t *f, H5FS_t *fspace)
+H5FS__cache_hdr_free_icr(void *_thing)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ H5FS_t *fspace = (H5FS_t *)_thing; /* Pointer to the object */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
- /* Check arguments */
+ /* Sanity checks */
HDassert(fspace);
+ HDassert(fspace->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC);
+ HDassert(fspace->cache_info.type == H5AC_FSPACE_HDR);
/* We should not still be holding on to the free space section info */
HDassert(!fspace->sinfo);
- /* If we're going to free the space on disk, the address must be valid */
- HDassert(!fspace->cache_info.free_file_space_on_destroy || H5F_addr_defined(fspace->cache_info.addr));
-
- /* Check for freeing file space for free space header */
- if(fspace->cache_info.free_file_space_on_destroy) {
- /* Sanity check */
- HDassert(H5F_addr_defined(fspace->addr));
-
- /* Release the space on disk */
- /* (XXX: Nasty usage of internal DXPL value! -QAK) */
- if(H5MF_xfree(f, H5FD_MEM_FSPACE_HDR, H5AC_dxpl_id, fspace->cache_info.addr, (hsize_t)fspace->hdr_size) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to free free space header")
- } /* end if */
-
/* Destroy free space header */
if(H5FS__hdr_dest(fspace) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to destroy free space header")
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5FS_cache_hdr_dest() */
+} /* end H5FS__cache_hdr_free_icr() */
+
+/********************************************************/
+/* metadata cache callback definitions for section info */
+/********************************************************/
/*-------------------------------------------------------------------------
- * Function: H5FS_cache_hdr_clear
+ * Function: H5FS__cache_sinfo_get_load_size()
*
- * Purpose: Mark a free space header in memory as non-dirty.
+ * Purpose: Compute the size of the on disk image of the free space
+ * manager section info, and place this value in *image_len.
*
- * Return: SUCCEED/FAIL
+ * Return: Success: SUCCEED
+ * Failure: FAIL
*
- * Programmer: Quincey Koziol
- * May 2 2006
+ * Programmer: John Mainzer
+ * 7/7/14
*
*-------------------------------------------------------------------------
*/
-static herr_t
-H5FS_cache_hdr_clear(H5F_t *f, H5FS_t *fspace, hbool_t destroy)
+static herr_t
+H5FS__cache_sinfo_get_load_size(const void *_image, void *_udata, size_t *image_len, size_t *actual_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ const H5FS_t *fspace; /* free space manager */
+ H5FS_sinfo_cache_ud_t *udata = (H5FS_sinfo_cache_ud_t *)_udata; /* User data for callback */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC_NOERR
- /*
- * Check arguments.
- */
+ /* Sanity checks */
+ HDassert(udata);
+ fspace = udata->fspace;
HDassert(fspace);
+ HDassert(fspace->sect_size > 0);
+ HDassert(image_len);
- /* Reset the dirty flag. */
- fspace->cache_info.is_dirty = FALSE;
-
- if(destroy)
- if(H5FS_cache_hdr_dest(f, fspace) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to destroy free space header")
+ if(image == NULL)
+ *image_len = (size_t)(fspace->sect_size);
+ else {
+ HDassert(actual_len);
+ HDassert(*actual_len == *image_len);
+ }
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5FS_cache_hdr_clear() */
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5FS__cache_sinfo_get_load_size() */
/*-------------------------------------------------------------------------
- * Function: H5FS_cache_hdr_size
+ * Function: H5FS__cache_sinfo_verify_chksum
*
- * Purpose: Compute the size in bytes of a free space header
- * on disk, and return it in *size_ptr.
+ * Purpose: Verify the computed checksum of the data structure is the
+ * same as the stored chksum.
*
- * Return: SUCCEED (Can't fail)
+ * Return: Success: TRUE/FALSE
+ * Failure: Negative
*
- * Programmer: Quincey Koziol
- * May 2 2006
+ * Programmer: Vailin Choi; Aug 2015
*
*-------------------------------------------------------------------------
*/
-static herr_t
-H5FS_cache_hdr_size(const H5F_t H5_ATTR_UNUSED *f, const H5FS_t *fspace, size_t *size_ptr)
+htri_t
+H5FS__cache_sinfo_verify_chksum(const void *_image, size_t len, void H5_ATTR_UNUSED *_udata)
{
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ uint32_t stored_chksum; /* Stored metadata checksum value */
+ uint32_t computed_chksum; /* Computed metadata checksum value */
+ htri_t ret_value = TRUE; /* Return value */
- /* check arguments */
- HDassert(f);
- HDassert(fspace);
- HDassert(size_ptr);
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Check arguments */
+ HDassert(image);
- /* Set size value */
- *size_ptr = fspace->hdr_size;
+ /* Get stored and computed checksums */
+ H5F_get_checksums(image, len, &stored_chksum, &computed_chksum);
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5FS_cache_hdr_size() */
+ if(stored_chksum != computed_chksum)
+ ret_value = FALSE;
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FS__cache_sinfo_verify_chksum() */
/*-------------------------------------------------------------------------
- * Function: H5FS_cache_sinfo_load
+ * Function: H5FS__cache_sinfo_deserialize
*
- * Purpose: Loads free space sections from the disk.
+ * Purpose: Given a buffer containing the on disk image of the free space
+ * manager section info, allocate an instance of H5FS_sinfo_t, load
+ * it with the data contained in the image, and return a pointer to
+ * the new instance.
*
- * Return: Success: Pointer to a new free space section info
- * Failure: NULL
+ * Return: Success: Pointer to in core representation
+ * Failure: NULL
*
- * Programmer: Quincey Koziol
- * July 31 2006
+ * Programmer: John Mainzer
+ * 7/7/14
*
*-------------------------------------------------------------------------
*/
-static H5FS_sinfo_t *
-H5FS_cache_sinfo_load(H5F_t *f, hid_t dxpl_id, haddr_t H5_ATTR_UNUSED addr, void *_udata)
+static void *
+H5FS__cache_sinfo_deserialize(const void *_image, size_t len, void *_udata,
+ hbool_t *dirty)
{
- H5FS_sinfo_t *sinfo = NULL; /* Free space section info */
- H5FS_sinfo_cache_ud_t *udata = (H5FS_sinfo_cache_ud_t *)_udata; /* user data for callback */
- haddr_t fs_addr; /* Free space header address */
- size_t old_sect_size; /* Old section size */
- uint8_t *buf = NULL; /* Temporary buffer */
- const uint8_t *p; /* Pointer into raw data buffer */
- H5FS_sinfo_t *ret_value; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT
-
- /* Check arguments */
- HDassert(f);
+ H5FS_sinfo_cache_ud_t *udata = (H5FS_sinfo_cache_ud_t *)_udata; /* User data for callback */
+ H5FS_t *fspace; /* free space manager */
+ H5FS_sinfo_t *sinfo = NULL; /* Free space section info */
+ haddr_t fs_addr; /* Free space header address */
+ size_t old_sect_size; /* Old section size */
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ uint32_t stored_chksum; /* Stored metadata checksum */
+ void * ret_value; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(image);
HDassert(udata);
+ fspace = udata->fspace;
+ HDassert(fspace);
+ HDassert(fspace->sect_size == len);
+ HDassert(dirty);
/* Allocate a new free space section info */
- if(NULL == (sinfo = H5FS_sinfo_new(udata->f, udata->fspace)))
+ if(NULL == (sinfo = H5FS_sinfo_new(udata->f, fspace)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
- /* Allocate space for the buffer to serialize the sections into */
+ /* initialize old_sect_size */
H5_CHECKED_ASSIGN(old_sect_size, size_t, udata->fspace->sect_size, hsize_t);
- if(NULL == (buf = H5FL_BLK_MALLOC(sect_block, (size_t)udata->fspace->sect_size)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
-
- /* Read and validate free space sections from disk */
- if(H5F_read_check_metadata(f, dxpl_id, H5FD_MEM_FSPACE_SINFO, H5AC_FSPACE_SINFO_ID, udata->fspace->sect_addr, (size_t)udata->fspace->sect_size, (size_t)udata->fspace->sect_size, buf) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_BADVALUE, NULL, "incorrect metadata checksum for free space sections")
-
- /* Deserialize free sections from buffer available */
- p = buf;
/* Magic number */
- if(HDmemcmp(p, H5FS_SINFO_MAGIC, (size_t)H5_SIZEOF_MAGIC))
+ if(HDmemcmp(image, H5FS_SINFO_MAGIC, (size_t)H5_SIZEOF_MAGIC))
HGOTO_ERROR(H5E_FSPACE, H5E_CANTLOAD, NULL, "wrong free space sections signature")
- p += H5_SIZEOF_MAGIC;
+ image += H5_SIZEOF_MAGIC;
/* Version */
- if(*p++ != H5FS_SINFO_VERSION)
+ if(*image++ != H5FS_SINFO_VERSION)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTLOAD, NULL, "wrong free space sections version")
/* Address of free space header for these sections */
- H5F_addr_decode(udata->f, &p, &fs_addr);
+ H5F_addr_decode(udata->f, &image, &fs_addr);
if(H5F_addr_ne(fs_addr, udata->fspace->addr))
HGOTO_ERROR(H5E_FSPACE, H5E_CANTLOAD, NULL, "incorrect header address for free space sections")
/* Check for any serialized sections */
- if(udata->fspace->serial_sect_count > 0) {
+ if(fspace->serial_sect_count > 0) {
hsize_t old_tot_sect_count; /* Total section count from header */
hsize_t old_serial_sect_count; /* Total serializable section count from header */
hsize_t old_ghost_sect_count; /* Total ghost section count from header */
@@ -599,27 +959,27 @@ H5FS_cache_sinfo_load(H5F_t *f, hid_t dxpl_id, haddr_t H5_ATTR_UNUSED addr, void
sect_cnt_size = H5VM_limit_enc_size((uint64_t)udata->fspace->serial_sect_count);
/* Reset the section count, the "add" routine will update it */
- old_tot_sect_count = udata->fspace->tot_sect_count;
- old_serial_sect_count = udata->fspace->serial_sect_count;
- old_ghost_sect_count = udata->fspace->ghost_sect_count;
- old_tot_space = udata->fspace->tot_space;
- udata->fspace->tot_sect_count = 0;
- udata->fspace->serial_sect_count = 0;
- udata->fspace->ghost_sect_count = 0;
- udata->fspace->tot_space = 0;
-
- /* Walk through the buffer, deserializing sections */
+ old_tot_sect_count = fspace->tot_sect_count;
+ old_serial_sect_count = fspace->serial_sect_count;
+ old_ghost_sect_count = fspace->ghost_sect_count;
+ old_tot_space = fspace->tot_space;
+ fspace->tot_sect_count = 0;
+ fspace->serial_sect_count = 0;
+ fspace->ghost_sect_count = 0;
+ fspace->tot_space = 0;
+
+ /* Walk through the image, deserializing sections */
do {
hsize_t sect_size; /* Current section size */
size_t node_count; /* # of sections of this size */
size_t u; /* Local index variable */
/* The number of sections of this node's size */
- UINT64DECODE_VAR(p, node_count, sect_cnt_size);
+ UINT64DECODE_VAR(image, node_count, sect_cnt_size);
HDassert(node_count);
/* The size of the sections for this node */
- UINT64DECODE_VAR(p, sect_size, sinfo->sect_len_size);
+ UINT64DECODE_VAR(image, sect_size, sinfo->sect_len_size);
HDassert(sect_size);
/* Loop over nodes of this size */
@@ -630,435 +990,466 @@ H5FS_cache_sinfo_load(H5F_t *f, hid_t dxpl_id, haddr_t H5_ATTR_UNUSED addr, void
unsigned des_flags; /* Flags from deserialize callback */
/* The address of the section */
- UINT64DECODE_VAR(p, sect_addr, sinfo->sect_off_size);
+ UINT64DECODE_VAR(image, sect_addr, sinfo->sect_off_size);
/* The type of this section */
- sect_type = *p++;
+ sect_type = *image++;
/* Call 'deserialize' callback for this section */
des_flags = 0;
HDassert(udata->fspace->sect_cls[sect_type].deserialize);
- if(NULL == (new_sect = (*udata->fspace->sect_cls[sect_type].deserialize)(&udata->fspace->sect_cls[sect_type], udata->dxpl_id, p, sect_addr, sect_size, &des_flags)))
+ if(NULL == (new_sect = (*fspace->sect_cls[sect_type].deserialize) (&fspace->sect_cls[sect_type], udata->dxpl_id, image, sect_addr, sect_size, &des_flags)))
HGOTO_ERROR(H5E_FSPACE, H5E_CANTDECODE, NULL, "can't deserialize section")
- /* Update offset in serialization buffer */
- p += udata->fspace->sect_cls[sect_type].serial_size;
+ /* Update offset in serialization image */
+ image += udata->fspace->sect_cls[sect_type].serial_size;
/* Insert section in free space manager, unless requested not to */
if(!(des_flags & H5FS_DESERIALIZE_NO_ADD))
if(H5FS_sect_add(udata->f, udata->dxpl_id, udata->fspace, new_sect, H5FS_ADD_DESERIALIZING, NULL) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, NULL, "can't add section to free space manager")
} /* end for */
- } while(p < ((buf + old_sect_size) - H5FS_SIZEOF_CHKSUM));
+ } while(image < (((const uint8_t *)_image + old_sect_size) - H5FS_SIZEOF_CHKSUM));
/* Sanity check */
- HDassert((size_t)(p - buf) == (old_sect_size - H5FS_SIZEOF_CHKSUM));
- HDassert(old_sect_size == udata->fspace->sect_size);
- HDassert(old_tot_sect_count == udata->fspace->tot_sect_count);
- HDassert(old_serial_sect_count == udata->fspace->serial_sect_count);
- HDassert(old_ghost_sect_count == udata->fspace->ghost_sect_count);
- HDassert(old_tot_space == udata->fspace->tot_space);
+ HDassert((size_t)(image - (const uint8_t *)_image) == (old_sect_size - H5FS_SIZEOF_CHKSUM));
+ HDassert(old_sect_size == fspace->sect_size);
+ HDassert(old_tot_sect_count == fspace->tot_sect_count);
+ HDassert(old_serial_sect_count == fspace->serial_sect_count);
+ HDassert(old_ghost_sect_count == fspace->ghost_sect_count);
+ HDassert(old_tot_space == fspace->tot_space);
} /* end if */
- /* Already decoded and compared stored checksum earlier, when reading */
+ /* checksum verification already done in verify_chksum cb */
+
+ /* Metadata checksum */
+ UINT32DECODE(image, stored_chksum);
/* Sanity check */
- HDassert((size_t)(p - (const uint8_t *)buf) == (old_sect_size - H5_SIZEOF_CHKSUM));
+ HDassert((size_t)(image - (const uint8_t *)_image) == old_sect_size);
/* Set return value */
ret_value = sinfo;
done:
- if(buf)
- buf = H5FL_BLK_FREE(sect_block, buf);
if(!ret_value && sinfo)
if(H5FS_sinfo_dest(sinfo) < 0)
HDONE_ERROR(H5E_FSPACE, H5E_CANTFREE, NULL, "unable to destroy free space info")
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5FS_cache_sinfo_load() */ /*lint !e818 Can't make udata a pointer to const */
+} /* end H5FS__cache_sinfo_deserialize() */
/*-------------------------------------------------------------------------
- * Function: H5FS_sinfo_serialize_sect_cb
+ * Function: H5FS__cache_sinfo_image_len
*
- * Purpose: Skip list iterator callback to serialize free space sections
- * of a particular size
+ * Purpose: Compute the size of the data structure on disk and return
+ * it in *image_len.
*
- * Return: SUCCEED/FAIL
+ * Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
- * Monday, May 8, 2006
+ * koziol@hdfgroup.org
+ * August 14, 2013
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5FS_sinfo_serialize_sect_cb(void *_item, void H5_ATTR_UNUSED *key, void *_udata)
+H5FS__cache_sinfo_image_len(const void *_thing, size_t *image_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr)
{
- H5FS_section_class_t *sect_cls; /* Class of section */
- H5FS_section_info_t *sect= (H5FS_section_info_t *)_item; /* Free space section to work on */
- H5FS_iter_ud_t *udata = (H5FS_iter_ud_t *)_udata; /* Callback info */
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT
+ const H5FS_sinfo_t *sinfo = (const H5FS_sinfo_t *)_thing; /* Pointer to the object */
+ const H5FS_t *fspace; /* Free space header */
- /* Check arguments. */
- HDassert(sect);
- HDassert(udata->sinfo);
- HDassert(udata->p);
-
- /* Get section's class */
- sect_cls = &udata->sinfo->fspace->sect_cls[sect->type];
+ FUNC_ENTER_STATIC_NOERR
- /* Check if this section should be serialized (i.e. is not a ghost section) */
- if(!(sect_cls->flags & H5FS_CLS_GHOST_OBJ)) {
- /* The address of the section */
- UINT64ENCODE_VAR(*udata->p, sect->addr, udata->sinfo->sect_off_size);
-
- /* The type of this section */
- *(*udata->p)++ = (uint8_t)sect->type;
-
- /* Call 'serialize' callback for this section */
- if(sect_cls->serialize) {
- if((*sect_cls->serialize)(sect_cls, sect, *udata->p) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTSERIALIZE, FAIL, "can't syncronize section")
+ /* Sanity checks */
+ HDassert(sinfo);
+ HDassert(sinfo->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(sinfo->cache_info.type == H5AC_FSPACE_SINFO);
+ fspace = sinfo->fspace;
+ HDassert(fspace);
+ HDassert(fspace->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(fspace->cache_info.type == H5AC_FSPACE_HDR);
+ HDassert(image_len);
- /* Update offset in serialization buffer */
- (*udata->p) += sect_cls->serial_size;
- } /* end if */
- else
- HDassert(sect_cls->serial_size == 0);
- } /* end if */
+ /* Set the image length size */
+ H5_CHECKED_ASSIGN(*image_len, size_t, sinfo->fspace->alloc_sect_size, hsize_t);
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5FS_sinfo_serialize_sect_cb() */
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5FS__cache_sinfo_image_len() */
/*-------------------------------------------------------------------------
- * Function: H5FS_sinfo_serialize_node_cb
+ * Function: H5FS__cache_sinfo_pre_serialize
*
- * Purpose: Skip list iterator callback to serialize free space sections
- * in a bin
+ * Purpose: The objective of this function is to test to see if file space
+ * for the section info is located in temporary (AKA imaginary) file
+ * space. If it is, relocate file space for the section info to
+ * regular file space.
*
- * Return: SUCCEED/FAIL
+ * Return: Success: SUCCEED
+ * Failure: FAIL
*
- * Programmer: Quincey Koziol
- * Monday, May 8, 2006
+ * Programmer: John Mainzer
+ * 7/7/14
*
*-------------------------------------------------------------------------
*/
-static herr_t
-H5FS_sinfo_serialize_node_cb(void *_item, void H5_ATTR_UNUSED *key, void *_udata)
+static herr_t
+H5FS__cache_sinfo_pre_serialize(const H5F_t *f, hid_t dxpl_id, void *_thing,
+ haddr_t addr, size_t len, size_t H5_ATTR_UNUSED compressed_len, haddr_t *new_addr,
+ size_t *new_len, size_t H5_ATTR_UNUSED *new_compressed_len, unsigned *flags)
{
- H5FS_node_t *fspace_node = (H5FS_node_t *)_item; /* Free space size node to work on */
- H5FS_iter_ud_t *udata = (H5FS_iter_ud_t *)_udata; /* Callback info */
- herr_t ret_value = SUCCEED; /* Return value */
+ H5FS_sinfo_t *sinfo = (H5FS_sinfo_t *)_thing; /* Pointer to the object */
+ H5FS_t *fspace; /* Free space header */
+ haddr_t sinfo_addr; /* Address for section info */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
- /* Check arguments. */
- HDassert(fspace_node);
- HDassert(udata->sinfo);
- HDassert(udata->p);
+ /* Sanity checks */
+ HDassert(f);
+ HDassert(sinfo);
+ HDassert(sinfo->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(sinfo->cache_info.type == H5AC_FSPACE_SINFO);
+ fspace = sinfo->fspace;
+ HDassert(fspace->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(fspace->cache_info.type == H5AC_FSPACE_HDR);
+ HDassert(fspace->cache_info.is_pinned);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(H5F_addr_eq(fspace->sect_addr, addr));
+ HDassert(fspace->sect_size == len);
+ HDassert(new_addr);
+ HDassert(new_len);
+ HDassert(flags);
- /* Check if this node has any serializable sections */
- if(fspace_node->serial_count > 0) {
- /* The number of serializable sections of this node's size */
- UINT64ENCODE_VAR(*udata->p, fspace_node->serial_count, udata->sect_cnt_size);
+ /* we shouldn't be called if the section info is empty */
+ HDassert(fspace->serial_sect_count > 0);
- /* The size of the sections for this node */
- UINT64ENCODE_VAR(*udata->p, fspace_node->sect_size, udata->sinfo->sect_len_size);
+ sinfo_addr = addr; /* this will change if we relocate the section data */
- /* Iterate through all the sections of this size */
- HDassert(fspace_node->sect_list);
- if(H5SL_iterate(fspace_node->sect_list, H5FS_sinfo_serialize_sect_cb, udata) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_BADITER, FAIL, "can't iterate over section nodes")
+ /* Check for section info at temporary address */
+ if(H5F_IS_TMP_ADDR(f, fspace->sect_addr)) {
+ /* Sanity check */
+ HDassert(fspace->sect_size > 0);
+ HDassert(H5F_addr_eq(fspace->sect_addr, addr));
+
+ /* Allocate space for the section info in file */
+ if(HADDR_UNDEF == (sinfo_addr = H5MF_alloc((H5F_t *)f, H5FD_MEM_FSPACE_SINFO, dxpl_id, fspace->sect_size)))
+ HGOTO_ERROR(H5E_FSPACE, H5E_NOSPACE, FAIL, "file allocation failed for free space sections")
+
+ fspace->alloc_sect_size = (size_t)fspace->sect_size;
+
+ /* Sanity check */
+ HDassert(!H5F_addr_eq(sinfo->fspace->sect_addr, sinfo_addr));
+
+ /* Let the metadata cache know the section info moved */
+ if(H5AC_move_entry((H5F_t *)f, H5AC_FSPACE_SINFO, sinfo->fspace->sect_addr, sinfo_addr) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTMOVE, FAIL, "unable to move section info")
+
+ /* Update the internal address for the section info */
+ sinfo->fspace->sect_addr = sinfo_addr;
+
+ /* Mark free space header as dirty */
+ if(H5AC_mark_entry_dirty(fspace) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space header as dirty")
+ } /* end if */
+
+ if(!H5F_addr_eq(addr, sinfo_addr)) {
+ *new_addr = sinfo_addr;
+ *flags = H5C__SERIALIZE_MOVED_FLAG;
} /* end if */
+ else
+ *flags = 0;
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5FS_sinfo_serialize_node_cb() */
+} /* end H5FS__cache_sinfo_pre_serialize() */
/*-------------------------------------------------------------------------
- * Function: H5FS_cache_sinfo_flush
+ * Function: H5FS__cache_sinfo_serialize
*
- * Purpose: Flushes a dirty free space section info to disk.
+ * Purpose: Given an instance of H5FS_sinfo_t and a suitably sized buffer,
+ * serialize the contents of the instance of H5FS_sinfo_t and write
+ * its contents to the buffer. This buffer will be used to write
+ * the image of the instance to file.
*
- * Return: SUCCEED/FAIL
+ * Return: Success: SUCCEED
+ * Failure: FAIL
*
- * Programmer: Quincey Koziol
- * July 31 2006
+ * Programmer: John Mainzer
+ * 6/21/14
*
*-------------------------------------------------------------------------
*/
-static herr_t
-H5FS_cache_sinfo_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5FS_sinfo_t *sinfo, unsigned H5_ATTR_UNUSED * flags_ptr)
+static herr_t
+H5FS__cache_sinfo_serialize(const H5F_t *f, void *_image, size_t len,
+ void *_thing)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ H5FS_sinfo_t *sinfo = (H5FS_sinfo_t *)_thing; /* Pointer to the object */
+ H5FS_t *fspace; /* Free space header */
+ H5FS_iter_ud_t udata; /* User data for callbacks */
+ uint8_t *image = (uint8_t *)_image; /* Pointer into raw data buffer */
+ uint32_t metadata_chksum; /* Computed metadata checksum value */
+ unsigned bin; /* Current bin we are on */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
- /* check arguments */
+ /* Sanity checks */
HDassert(f);
- HDassert(H5F_addr_defined(addr));
+ HDassert(image);
HDassert(sinfo);
- HDassert(sinfo->fspace);
- HDassert(sinfo->fspace->sect_cls);
-
- if(sinfo->cache_info.is_dirty || sinfo->dirty) {
- H5FS_iter_ud_t udata; /* User data for callbacks */
- uint8_t *buf = NULL; /* Temporary raw data buffer */
- uint8_t *p; /* Pointer into raw data buffer */
- uint32_t metadata_chksum; /* Computed metadata checksum value */
- unsigned bin; /* Current bin we are on */
-
- /* Sanity check address */
- if(H5F_addr_ne(addr, sinfo->fspace->sect_addr))
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTLOAD, FAIL, "incorrect address for free space sections")
+ HDassert(sinfo->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(sinfo->cache_info.type == H5AC_FSPACE_SINFO);
+ fspace = sinfo->fspace;
+ HDassert(fspace->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(fspace->cache_info.type == H5AC_FSPACE_HDR);
+ HDassert(fspace->cache_info.is_pinned);
+ HDassert(fspace->sect_size == len);
+ HDassert(fspace->sect_cls);
- /* Allocate temporary buffer */
- if((buf = H5FL_BLK_MALLOC(sect_block, (size_t)sinfo->fspace->sect_size)) == NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
-
- p = buf;
-
- /* Magic number */
- HDmemcpy(p, H5FS_SINFO_MAGIC, (size_t)H5_SIZEOF_MAGIC);
- p += H5_SIZEOF_MAGIC;
-
- /* Version # */
- *p++ = H5FS_SINFO_VERSION;
-
- /* Address of free space header for these sections */
- H5F_addr_encode(f, &p, sinfo->fspace->addr);
-
- /* Set up user data for iterator */
- udata.sinfo = sinfo;
- udata.p = &p;
- udata.sect_cnt_size = H5VM_limit_enc_size((uint64_t)sinfo->fspace->serial_sect_count);
-
- /* Iterate over all the bins */
- for(bin = 0; bin < sinfo->nbins; bin++)
- /* Check if there are any sections in this bin */
- if(sinfo->bins[bin].bin_list)
- /* Iterate over list of section size nodes for bin */
- if(H5SL_iterate(sinfo->bins[bin].bin_list, H5FS_sinfo_serialize_node_cb, &udata) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_BADITER, FAIL, "can't iterate over section size nodes")
-
- /* Compute checksum */
- metadata_chksum = H5_checksum_metadata(buf, (size_t)(p - buf), 0);
-
- /* Metadata checksum */
- UINT32ENCODE(p, metadata_chksum);
-
- /* Sanity check */
- HDassert((size_t)(p - buf) == sinfo->fspace->sect_size);
- HDassert(sinfo->fspace->sect_size <= sinfo->fspace->alloc_sect_size);
-
- /* Check for section info at temporary address */
- if(H5F_IS_TMP_ADDR(f, sinfo->fspace->sect_addr)) {
- /* Sanity check */
- HDassert(sinfo->fspace->sect_size > 0);
- HDassert(H5F_addr_eq(sinfo->fspace->sect_addr, addr));
-
- /* Allocate space for the section info in file */
- if(HADDR_UNDEF == (addr = H5MF_alloc(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, sinfo->fspace->sect_size)))
- HGOTO_ERROR(H5E_FSPACE, H5E_NOSPACE, FAIL, "file allocation failed for free space sections")
- sinfo->fspace->alloc_sect_size = (size_t)sinfo->fspace->sect_size;
+ /* Magic number */
+ HDmemcpy(image, H5FS_SINFO_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ image += H5_SIZEOF_MAGIC;
- /* Sanity check */
- HDassert(!H5F_addr_eq(sinfo->fspace->sect_addr, addr));
+ /* Version # */
+ *image++ = H5FS_SINFO_VERSION;
- /* Let the metadata cache know the section info moved */
- if(H5AC_move_entry(f, H5AC_FSPACE_SINFO, sinfo->fspace->sect_addr, addr) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTMOVE, FAIL, "unable to move indirect block")
+ /* Address of free space header for these sections */
+ H5F_addr_encode(f, &image, sinfo->fspace->addr);
- /* Update the internal address for the section info */
- sinfo->fspace->sect_addr = addr;
+ /* Set up user data for iterator */
+ udata.sinfo = sinfo;
+ udata.image = &image;
+ udata.sect_cnt_size = H5VM_limit_enc_size((uint64_t)sinfo->fspace->serial_sect_count);
- /* Mark free space header as dirty */
- if(H5AC_mark_entry_dirty(sinfo->fspace) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space header as dirty")
- } /* end if */
+ /* Iterate over all the bins */
+ for(bin = 0; bin < sinfo->nbins; bin++)
+ /* Check if there are any sections in this bin */
+ if(sinfo->bins[bin].bin_list)
+ /* Iterate over list of section size nodes for bin */
+ if(H5SL_iterate(sinfo->bins[bin].bin_list, H5FS__sinfo_serialize_node_cb, &udata) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_BADITER, FAIL, "can't iterate over section size nodes")
- /* Write buffer to disk */
- if(H5F_block_write(f, H5FD_MEM_FSPACE_SINFO, sinfo->fspace->sect_addr, (size_t)sinfo->fspace->sect_size, dxpl_id, buf) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTFLUSH, FAIL, "unable to save free space sections to disk")
- buf = H5FL_BLK_FREE(sect_block, buf);
+ /* Compute checksum */
+ metadata_chksum = H5_checksum_metadata(_image, (size_t)(image - (uint8_t *)_image), 0);
- sinfo->cache_info.is_dirty = FALSE;
- sinfo->dirty = FALSE;
- } /* end if */
+ /* Metadata checksum */
+ UINT32ENCODE(image, metadata_chksum);
- if(destroy)
- if(H5FS_cache_sinfo_dest(f, sinfo) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to destroy free space section info")
+ /* Sanity check */
+ HDassert((size_t)(image - (uint8_t *)_image) == sinfo->fspace->sect_size);
+ HDassert(sinfo->fspace->sect_size <= sinfo->fspace->alloc_sect_size);
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5FS_cache_sinfo_flush() */
+} /* end H5FS__cache_sinfo_serialize() */
/*-------------------------------------------------------------------------
- * Function: H5FS_cache_sinfo_dest
+ * Function: H5FS__cache_sinfo_notify
*
- * Purpose: Destroys a free space section info in memory.
+ * Purpose: Handle cache action notifications
*
* Return: SUCCEED/FAIL
*
- * Programmer: Quincey Koziol
- * July 31 2006
+ * Programmer: Dana Robinson
+ * Fall 2012
*
*-------------------------------------------------------------------------
*/
-static herr_t
-H5FS_cache_sinfo_dest(H5F_t *f, H5FS_sinfo_t *sinfo)
+herr_t
+H5FS__cache_sinfo_notify(H5AC_notify_action_t action, void *_thing)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ H5FS_sinfo_t *sinfo = (H5FS_sinfo_t *)_thing;
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT
-
- /* Check arguments */
+
+ /* Sanity check */
HDassert(sinfo);
- /* If we're going to free the space on disk, the address must be valid */
- HDassert(!sinfo->cache_info.free_file_space_on_destroy || H5F_addr_defined(sinfo->cache_info.addr));
+ /* Check if the file was opened with SWMR-write access */
+ if(sinfo->fspace->swmr_write) {
+ /* Determine which action to take */
+ switch(action) {
+ case H5AC_NOTIFY_ACTION_AFTER_INSERT:
+ case H5AC_NOTIFY_ACTION_AFTER_LOAD:
+ /* Create flush dependency on parent */
+ if(H5FS__create_flush_depend((H5AC_info_t *)sinfo->fspace, (H5AC_info_t *)sinfo) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTDEPEND, FAIL, "unable to create flush dependency between data block and header, address = %llu", (unsigned long long)sinfo->fspace->sect_addr)
+ break;
- /* Check for freeing file space for free space section info */
- if(sinfo->cache_info.free_file_space_on_destroy) {
- /* Sanity check */
- HDassert(sinfo->fspace->alloc_sect_size > 0);
+ case H5AC_NOTIFY_ACTION_AFTER_FLUSH:
+ /* do nothing */
+ break;
- /* Release the space on disk */
- /* (XXX: Nasty usage of internal DXPL value! -QAK) */
- if(!H5F_IS_TMP_ADDR(f, sinfo->cache_info.addr))
- if(H5MF_xfree(f, H5FD_MEM_FSPACE_SINFO, H5AC_dxpl_id, sinfo->cache_info.addr, (hsize_t)sinfo->fspace->alloc_sect_size) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to free free space section info")
- } /* end if */
+ case H5AC_NOTIFY_ACTION_BEFORE_EVICT:
+ /* Destroy flush dependency on parent */
+ if(H5FS__destroy_flush_depend((H5AC_info_t *)sinfo->fspace, (H5AC_info_t *)sinfo) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTUNDEPEND, FAIL, "unable to destroy flush dependency")
+ break;
- /* Destroy free space info */
- if(H5FS_sinfo_dest(sinfo) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to destroy free space info")
+ default:
+#ifdef NDEBUG
+ HGOTO_ERROR(H5E_FSPACE, H5E_BADVALUE, FAIL, "unknown action from metadata cache")
+#else /* NDEBUG */
+ HDassert(0 && "Unknown action?!?");
+#endif /* NDEBUG */
+ } /* end switch */
+ } /* end if */
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5FS_cache_sinfo_dest() */
+} /* end H5FS__cache_sinfo_notify() */
/*-------------------------------------------------------------------------
- * Function: H5FS_cache_sinfo_clear
+ * Function: H5FS__cache_sinfo_free_icr
*
- * Purpose: Mark a free space section info in memory as non-dirty.
+ * Purpose: Free the memory used for the in core representation of the
+ * free space manager section info.
*
- * Return: SUCCEED/FAIL
+ * Note: The metadata cache sets the object's cache_info.magic to
+ * H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC before calling a free_icr
+ * callback (checked in assert).
*
- * Programmer: Quincey Koziol
- * July 31 2006
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: John Mainzer
+ * 6/21/14
*
*-------------------------------------------------------------------------
*/
-static herr_t
-H5FS_cache_sinfo_clear(H5F_t *f, H5FS_sinfo_t *sinfo, hbool_t destroy)
+static herr_t
+H5FS__cache_sinfo_free_icr(void *_thing)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ H5FS_sinfo_t *sinfo = (H5FS_sinfo_t *)_thing; /* Pointer to the object */
+ H5FS_t *fspace; /* Free space header */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
- /*
- * Check arguments.
- */
+ /* Sanity checks */
HDassert(sinfo);
+ HDassert(sinfo->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC);
+ HDassert(sinfo->cache_info.type == H5AC_FSPACE_SINFO);
+ fspace = sinfo->fspace;
+ HDassert(fspace->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(fspace->cache_info.type == H5AC_FSPACE_HDR);
+ HDassert(fspace->cache_info.is_pinned);
- /* Reset the dirty flag. */
- sinfo->cache_info.is_dirty = FALSE;
-
- if(destroy)
- if(H5FS_cache_sinfo_dest(f, sinfo) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to destroy free space section info")
+ /* Destroy free space info */
+ if(H5FS_sinfo_dest(sinfo) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to destroy free space info")
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5FS_cache_sinfo_clear() */
+} /* end H5FS__cache_sinfo_free_icr() */
/*-------------------------------------------------------------------------
- * Function: H5FS_cache_sinfo_notify
+ * Function: H5FS__sinfo_serialize_sect_cb
*
- * Purpose: Handle cache action notifications
+ * Purpose: Skip list iterator callback to serialize free space sections
+ * of a particular size
*
- * Return: SUCCEED/FAIL
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Dana Robinson
- * Fall 2012
+ * Programmer: Quincey Koziol
+ * Monday, May 8, 2006
*
*-------------------------------------------------------------------------
*/
-herr_t
-H5FS_cache_sinfo_notify(H5AC_notify_action_t action, H5FS_sinfo_t *sinfo)
+static herr_t
+H5FS__sinfo_serialize_sect_cb(void *_item, void H5_ATTR_UNUSED *key, void *_udata)
{
+ H5FS_section_class_t *sect_cls; /* Class of section */
+ H5FS_section_info_t *sect= (H5FS_section_info_t *)_item; /* Free space section to work on */
+ H5FS_iter_ud_t *udata = (H5FS_iter_ud_t *)_udata; /* Callback info */
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
-
- /* Sanity check */
- HDassert(sinfo);
+ FUNC_ENTER_STATIC
- /* Check if the file was opened with SWMR-write access */
- if(sinfo->fspace->swmr_write) {
- /* Determine which action to take */
- switch(action) {
- case H5AC_NOTIFY_ACTION_AFTER_INSERT:
- /* Create flush dependency on extensible array header */
- if(H5FS__create_flush_depend((H5AC_info_t *)sinfo->fspace, (H5AC_info_t *)sinfo) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTDEPEND, FAIL, "unable to create flush dependency between data block and header, address = %llu", (unsigned long long)sinfo->fspace->sect_addr)
- break;
+ /* Check arguments. */
+ HDassert(sect);
+ HDassert(udata->sinfo);
+ HDassert(udata->image);
- case H5AC_NOTIFY_ACTION_BEFORE_EVICT:
- /* Nothing to do */
- break;
+ /* Get section's class */
+ sect_cls = &udata->sinfo->fspace->sect_cls[sect->type];
- default:
-#ifdef NDEBUG
- HGOTO_ERROR(H5E_FSPACE, H5E_BADVALUE, FAIL, "unknown action from metadata cache")
-#else /* NDEBUG */
- HDassert(0 && "Unknown action?!?");
-#endif /* NDEBUG */
- } /* end switch */
+ /* Check if this section should be serialized (i.e. is not a ghost section) */
+ if(!(sect_cls->flags & H5FS_CLS_GHOST_OBJ)) {
+ /* The address of the section */
+ UINT64ENCODE_VAR(*udata->image, sect->addr, udata->sinfo->sect_off_size);
+
+ /* The type of this section */
+ *(*udata->image)++ = (uint8_t)sect->type;
+
+ /* Call 'serialize' callback for this section */
+ if(sect_cls->serialize) {
+ if((*sect_cls->serialize)(sect_cls, sect, *udata->image) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTSERIALIZE, FAIL, "can't syncronize section")
+
+ /* Update offset in serialization buffer */
+ (*udata->image) += sect_cls->serial_size;
+ } /* end if */
+ else
+ HDassert(sect_cls->serial_size == 0);
} /* end if */
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5FS_cache_sinfo_notify() */
+} /* H5FS__sinfo_serialize_sect_cb() */
/*-------------------------------------------------------------------------
- * Function: H5FS_cache_sinfo_size
+ * Function: H5FS__sinfo_serialize_node_cb
*
- * Purpose: Compute the size in bytes of a free space section info
- * on disk, and return it in *size_ptr.
+ * Purpose: Skip list iterator callback to serialize free space sections
+ * in a bin
*
- * Return: SUCCEED (Can't fail)
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Quincey Koziol
- * July 31 2006
+ * Programmer: Quincey Koziol
+ * Monday, May 8, 2006
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5FS_cache_sinfo_size(const H5F_t H5_ATTR_UNUSED *f, const H5FS_sinfo_t *sinfo, size_t *size_ptr)
+H5FS__sinfo_serialize_node_cb(void *_item, void H5_ATTR_UNUSED *key, void *_udata)
{
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ H5FS_node_t *fspace_node = (H5FS_node_t *)_item; /* Free space size node to work on */
+ H5FS_iter_ud_t *udata = (H5FS_iter_ud_t *)_udata; /* Callback info */
+ herr_t ret_value = SUCCEED; /* Return value */
- /* check arguments */
- HDassert(sinfo);
- HDassert(size_ptr);
+ FUNC_ENTER_STATIC
- /* Set size value */
- H5_CHECKED_ASSIGN(*size_ptr, size_t, sinfo->fspace->alloc_sect_size, hsize_t);
+ /* Check arguments. */
+ HDassert(fspace_node);
+ HDassert(udata->sinfo);
+ HDassert(udata->image);
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5FS_cache_sinfo_size() */
+ /* Check if this node has any serializable sections */
+ if(fspace_node->serial_count > 0) {
+ /* The number of serializable sections of this node's size */
+ UINT64ENCODE_VAR(*udata->image, fspace_node->serial_count, udata->sect_cnt_size);
+
+ /* The size of the sections for this node */
+ UINT64ENCODE_VAR(*udata->image, fspace_node->sect_size, udata->sinfo->sect_len_size);
+ /* Iterate through all the sections of this size */
+ HDassert(fspace_node->sect_list);
+ if(H5SL_iterate(fspace_node->sect_list, H5FS__sinfo_serialize_sect_cb, udata) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_BADITER, FAIL, "can't iterate over section nodes")
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5FS__sinfo_serialize_node_cb() */
diff --git a/src/H5FSdbg.c b/src/H5FSdbg.c
index 11a2232..4599b52 100644
--- a/src/H5FSdbg.c
+++ b/src/H5FSdbg.c
@@ -116,7 +116,7 @@ H5FS_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, int
/*
* Load the free space header.
*/
- if(NULL == (fspace = (H5FS_t *)H5AC_protect(f, dxpl_id, H5AC_FSPACE_HDR, addr, &cache_udata, H5AC_READ)))
+ if(NULL == (fspace = (H5FS_t *)H5AC_protect(f, dxpl_id, H5AC_FSPACE_HDR, addr, &cache_udata, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_FSPACE, H5E_CANTLOAD, FAIL, "unable to load free space header")
/* Print opening message */
@@ -256,7 +256,7 @@ H5FS_sects_debug(H5F_t *f, hid_t dxpl_id, haddr_t H5_ATTR_UNUSED addr, FILE *str
/*
* Load the free space header.
*/
- if(NULL == (fspace = (H5FS_t *)H5AC_protect(f, dxpl_id, H5AC_FSPACE_HDR, fs_addr, &cache_udata, H5AC_READ)))
+ if(NULL == (fspace = (H5FS_t *)H5AC_protect(f, dxpl_id, H5AC_FSPACE_HDR, fs_addr, &cache_udata, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_FSPACE, H5E_CANTLOAD, FAIL, "unable to load free space header")
/* Retrieve the client id */
diff --git a/src/H5FSpkg.h b/src/H5FSpkg.h
index 70c83f0..62da2e3 100644
--- a/src/H5FSpkg.h
+++ b/src/H5FSpkg.h
@@ -183,7 +183,9 @@ struct H5FS_t {
unsigned sinfo_lock_count; /* # of times the section info has been locked */
hbool_t sinfo_protected; /* Whether the section info was protected when locked */
hbool_t sinfo_modified; /* Whether the section info has been modified while locked */
- H5AC_protect_t sinfo_accmode; /* Access mode for protecting the section info */
+ unsigned sinfo_accmode; /* Access mode for protecting the section info */
+ /* must be either H5C__NO_FLAGS_SET (i.e r/w) */
+ /* or H5AC__READ_ONLY_FLAG (i.e. r/o). */
size_t max_cls_serial_size; /* Max. additional size of serialized form of section */
hsize_t threshold; /* Threshold for alignment */
hsize_t alignment; /* Alignment */
diff --git a/src/H5FSsection.c b/src/H5FSsection.c
index 5bd4d95..7fb1944 100644
--- a/src/H5FSsection.c
+++ b/src/H5FSsection.c
@@ -203,7 +203,7 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5FS_sinfo_lock(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5AC_protect_t accmode)
+H5FS_sinfo_lock(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, unsigned accmode)
{
H5FS_sinfo_cache_ud_t cache_udata; /* User-data for cache callback */
herr_t ret_value = SUCCEED; /* Return value */
@@ -219,14 +219,21 @@ HDfprintf(stderr, "%s: fspace->alloc_sect_size = %Hu, fspace->sect_size = %Hu\n"
HDassert(f);
HDassert(fspace);
+ /* only H5AC__READ_ONLY_FLAG may appear in accmode */
+ HDassert((accmode & (unsigned)(~H5AC__READ_ONLY_FLAG)) == 0);
+
/* If the free space header doesn't already "own" the section info, load
* section info or create it
*/
if(fspace->sinfo) {
/* Check if the section info was protected & we want a different access mode */
+
+ /* only H5AC__READ_ONLY_FLAG may appear in fspace->sinfo_accmode */
+ HDassert(((fspace->sinfo_accmode) & (unsigned)(~H5AC__READ_ONLY_FLAG)) == 0);
+
if(fspace->sinfo_protected && accmode != fspace->sinfo_accmode) {
/* Check if we need to switch from read-only access to read-write */
- if(H5AC_WRITE == accmode) {
+ if(0 == (accmode & (unsigned)(~H5AC__READ_ONLY_FLAG))) {
/* Unprotect the read-only section info */
if(H5AC_unprotect(f, dxpl_id, H5AC_FSPACE_SINFO, fspace->sect_addr, fspace->sinfo, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTUNPROTECT, FAIL, "unable to release free space section info")
@@ -235,11 +242,11 @@ HDfprintf(stderr, "%s: fspace->alloc_sect_size = %Hu, fspace->sect_size = %Hu\n"
cache_udata.f = f;
cache_udata.dxpl_id = dxpl_id;
cache_udata.fspace = fspace;
- if(NULL == (fspace->sinfo = (H5FS_sinfo_t *)H5AC_protect(f, dxpl_id, H5AC_FSPACE_SINFO, fspace->sect_addr, &cache_udata, H5AC_WRITE)))
+ if(NULL == (fspace->sinfo = (H5FS_sinfo_t *)H5AC_protect(f, dxpl_id, H5AC_FSPACE_SINFO, fspace->sect_addr, &cache_udata, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_FSPACE, H5E_CANTPROTECT, FAIL, "unable to load free space sections")
/* Switch the access mode we have */
- fspace->sinfo_accmode = H5AC_WRITE;
+ fspace->sinfo_accmode = H5AC__NO_FLAGS_SET;
} /* end if */
} /* end if */
} /* end if */
@@ -329,7 +336,7 @@ HDfprintf(stderr, "%s: fspace->alloc_sect_size = %Hu, fspace->sect_size = %Hu\n"
/* Check if we modified any section */
if(modified) {
/* Check if the section info was protected with a different access mode */
- if(fspace->sinfo_protected && fspace->sinfo_accmode != H5AC_WRITE)
+ if(fspace->sinfo_protected && (0 != ((fspace->sinfo_accmode) & H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_FSPACE, H5E_CANTDIRTY, FAIL, "attempt to modify read-only section info")
/* If we modified the section info, mark it dirty */
@@ -903,7 +910,7 @@ H5FS_sect_remove(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
HDassert(sect);
/* Get a pointer to the section info */
- if(H5FS_sinfo_lock(f, dxpl_id, fspace, H5AC_WRITE) < 0)
+ if(H5FS_sinfo_lock(f, dxpl_id, fspace, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTGET, FAIL, "can't get section info")
sinfo_valid = TRUE;
@@ -1369,7 +1376,7 @@ HDfprintf(stderr, "%s: *sect = {%a, %Hu, %u, %s}\n", FUNC, sect->addr, sect->siz
HDassert(sect->size);
/* Get a pointer to the section info */
- if(H5FS_sinfo_lock(f, dxpl_id, fspace, H5AC_WRITE) < 0)
+ if(H5FS_sinfo_lock(f, dxpl_id, fspace, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTGET, FAIL, "can't get section info")
sinfo_valid = TRUE;
@@ -1466,7 +1473,7 @@ HDfprintf(stderr, "%s: fspace->ghost_sect_count = %Hu\n", FUNC, fspace->ghost_se
H5FS_section_info_t *sect; /* Temporary free space section */
/* Get a pointer to the section info */
- if(H5FS_sinfo_lock(f, dxpl_id, fspace, H5AC_WRITE) < 0)
+ if(H5FS_sinfo_lock(f, dxpl_id, fspace, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTGET, FAIL, "can't get section info")
sinfo_valid = TRUE;
@@ -1586,7 +1593,7 @@ H5FS_sect_try_merge(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5FS_section_info_t
HDassert(sect->size);
/* Get a pointer to the section info */
- if(H5FS_sinfo_lock(f, dxpl_id, fspace, H5AC_WRITE) < 0)
+ if(H5FS_sinfo_lock(f, dxpl_id, fspace, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTGET, FAIL, "can't get section info")
sinfo_valid = TRUE;
saved_fs_size = sect->size;
@@ -1809,7 +1816,7 @@ HDfprintf(stderr, "%s: fspace->ghost_sect_count = %Hu\n", FUNC, fspace->ghost_se
#endif /* QAK */
if(fspace->tot_sect_count > 0) {
/* Get a pointer to the section info */
- if(H5FS_sinfo_lock(f, dxpl_id, fspace, H5AC_WRITE) < 0)
+ if(H5FS_sinfo_lock(f, dxpl_id, fspace, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTGET, FAIL, "can't get section info")
sinfo_valid = TRUE;
@@ -1951,7 +1958,7 @@ HDfprintf(stderr, "%s: fspace->tot_sect_count = %Hu\n", FUNC, fspace->tot_sect_c
unsigned bin; /* Current bin we are on */
/* Get a pointer to the section info */
- if(H5FS_sinfo_lock(f, dxpl_id, fspace, H5AC_READ) < 0)
+ if(H5FS_sinfo_lock(f, dxpl_id, fspace, H5AC__READ_ONLY_FLAG) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTGET, FAIL, "can't get section info")
sinfo_valid = TRUE;
@@ -2040,7 +2047,7 @@ H5FS_sect_change_class(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
HDassert(new_class < fspace->nclasses);
/* Get a pointer to the section info */
- if(H5FS_sinfo_lock(f, dxpl_id, fspace, H5AC_WRITE) < 0)
+ if(H5FS_sinfo_lock(f, dxpl_id, fspace, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTGET, FAIL, "can't get section info")
sinfo_valid = TRUE;
@@ -2353,7 +2360,7 @@ H5FS_sect_try_shrink_eoa(const H5F_t *f, hid_t dxpl_id, const H5FS_t *fspace, vo
/* Check arguments. */
HDassert(fspace);
- if(H5FS_sinfo_lock(f, dxpl_id, fspace, H5AC_WRITE) < 0)
+ if(H5FS_sinfo_lock(f, dxpl_id, fspace, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTGET, FAIL, "can't get section info")
sinfo_valid = TRUE;
diff --git a/src/H5Fint.c b/src/H5Fint.c
index 61c0eee..3410036 100644
--- a/src/H5Fint.c
+++ b/src/H5Fint.c
@@ -886,6 +886,14 @@ H5F_dest(H5F_t *f, hid_t dxpl_id, hbool_t flush)
}
} /* end if */
+ /* if it exists, unpin the driver information block cache entry,
+ * since we're about to destroy the cache
+ */
+ if(f->shared->drvinfo)
+ if(H5AC_unpin_entry(f->shared->drvinfo) < 0)
+ /* Push error, but keep going*/
+ HDONE_ERROR(H5E_FSPACE, H5E_CANTUNPIN, FAIL, "unable to unpin drvinfo")
+
/* Unpin the superblock, since we're about to destroy the cache */
if(H5AC_unpin_entry(f->shared->sblock) < 0)
/* Push error, but keep going*/
diff --git a/src/H5Fio.c b/src/H5Fio.c
index fafe5e8..b7e925e 100644
--- a/src/H5Fio.c
+++ b/src/H5Fio.c
@@ -209,9 +209,10 @@ H5F_flush_tagged_metadata(H5F_t * f, haddr_t tag, hid_t dxpl_id)
if(NULL == (fio_info.dxpl = (H5P_genplist_t *)H5I_object(dxpl_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get property list")
- /* Flush out the metadata accumulator */
- if(H5F__accum_flush(&fio_info) < 0)
- HGOTO_ERROR(H5E_IO, H5E_CANTFLUSH, FAIL, "unable to flush metadata accumulator")
+
+ /* Flush and reset the accumulator */
+ if(H5F__accum_reset(&fio_info, TRUE) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_CANTRESET, FAIL, "can't reset accumulator")
/* Flush file buffers to disk. */
if(H5FD_flush(f->shared->lf, dxpl_id, FALSE) < 0)
@@ -414,4 +415,3 @@ H5F_read_check_metadata(H5F_t *f, hid_t dxpl_id, H5FD_mem_t type,
done:
FUNC_LEAVE_NOAPI(ret_value);
} /* end H5F_read_check_metadata */
-
diff --git a/src/H5Fpkg.h b/src/H5Fpkg.h
index d2c43b5..18bc7ef 100644
--- a/src/H5Fpkg.h
+++ b/src/H5Fpkg.h
@@ -83,6 +83,21 @@
#define H5F_SUPERBLOCK_FIXED_SIZE ( H5F_SIGNATURE_LEN \
+ 1) /* superblock version */
+/* The H5F_SUPERBLOCK_MINIMAL_VARLEN_SIZE is the minimal amount of super block
+ * variable length data guarnateed to load the sizeof offsets and the sizeof
+ * lengths fields in all versions of the superblock.
+ *
+ * This is necessary in the V3 cache, as on the initial load, we need to
+ * get enough of the superblock to determine its version and size so that
+ * the metadata cache can load the correct amount of data from file to
+ * allow the second deserialization attempt to succeed.
+ *
+ * The value selected will have to be revisited for each new version
+ * of the super block. Note that the current value is one byte larger
+ * than it needs to be.
+ */
+#define H5F_SUPERBLOCK_MINIMAL_VARLEN_SIZE 7
+
/* Macros for computing variable-size superblock size */
#define H5F_SUPERBLOCK_VARLEN_SIZE_COMMON \
(2 /* freespace, and root group versions */ \
@@ -115,14 +130,14 @@
+ (sizeof_addr) /* EOF address */ \
+ (sizeof_addr) /* root group object header address */ \
+ H5F_SIZEOF_CHKSUM) /* superblock checksum (keep this last) */
-#define H5F_SUPERBLOCK_VARLEN_SIZE(v, f) ( \
- (v == 0 ? H5F_SUPERBLOCK_VARLEN_SIZE_V0(H5F_SIZEOF_ADDR(f), H5F_SIZEOF_SIZE(f)) : 0) \
- + (v == 1 ? H5F_SUPERBLOCK_VARLEN_SIZE_V1(H5F_SIZEOF_ADDR(f), H5F_SIZEOF_SIZE(f)) : 0) \
- + (v == 2 ? H5F_SUPERBLOCK_VARLEN_SIZE_V2(H5F_SIZEOF_ADDR(f)) : 0))
+#define H5F_SUPERBLOCK_VARLEN_SIZE(v, sizeof_addr, sizeof_size) ( \
+ (v == 0 ? H5F_SUPERBLOCK_VARLEN_SIZE_V0(sizeof_addr, sizeof_size) : 0) \
+ + (v == 1 ? H5F_SUPERBLOCK_VARLEN_SIZE_V1(sizeof_addr, sizeof_size) : 0) \
+ + (v == 2 ? H5F_SUPERBLOCK_VARLEN_SIZE_V2(sizeof_addr) : 0))
/* Total size of superblock, depends on superblock version */
-#define H5F_SUPERBLOCK_SIZE(v, f) ( H5F_SUPERBLOCK_FIXED_SIZE \
- + H5F_SUPERBLOCK_VARLEN_SIZE(v, f))
+#define H5F_SUPERBLOCK_SIZE(s) ( H5F_SUPERBLOCK_FIXED_SIZE \
+ + H5F_SUPERBLOCK_VARLEN_SIZE((s)->super_vers, (s)->sizeof_addr, (s)->sizeof_size))
/* For superblock version 0 & 1:
Offset to the file consistency flags (status_flags) in the superblock (excluding H5F_SUPERBLOCK_FIXED_SIZE) */
@@ -156,6 +171,26 @@ typedef struct H5F_super_ud_t {
* H5Fefc.c) */
typedef struct H5F_efc_t H5F_efc_t;
+/* Structure for passing 'user data' to superblock cache callbacks */
+typedef struct H5F_superblock_cache_ud_t {
+/* IN: */
+ H5F_t *f; /* Pointer to file */
+ hbool_t ignore_drvrinfo; /* Indicate if the driver info should be ignored */
+/* OUT: */
+ unsigned sym_leaf_k; /* Symbol table leaf node's 'K' value */
+ unsigned btree_k[H5B_NUM_BTREE_ID]; /* B-tree key values for each type */
+ haddr_t stored_eof; /* End-of-file in file */
+ hbool_t drvrinfo_removed; /* Indicate if the driver info was removed */
+ unsigned super_vers; /* Superblock version obtained in get_load_size callback.
+ * It will be used later in verify_chksum callback
+ */
+} H5F_superblock_cache_ud_t;
+
+typedef struct H5F_drvrinfo_cache_ud_t {
+ H5F_t *f; /* Pointer to file */
+ haddr_t driver_addr; /* address of driver info block */
+} H5F_drvrinfo_cache_ud_t;
+
/* Structure for metadata & "small [raw] data" block aggregation fields */
struct H5F_blk_aggr_t {
unsigned long feature_flag; /* Feature flag type */
@@ -205,6 +240,8 @@ typedef struct H5F_mtab_t {
typedef struct H5F_super_t {
H5AC_info_t cache_info; /* Cache entry information structure */
unsigned super_vers; /* Superblock version */
+ uint8_t sizeof_addr; /* Size of addresses in file */
+ uint8_t sizeof_size; /* Size of offsets in file */
uint8_t status_flags; /* File status flags */
unsigned sym_leaf_k; /* Size of leaves in symbol tables */
unsigned btree_k[H5B_NUM_BTREE_ID]; /* B-tree key values for each type */
@@ -226,6 +263,13 @@ typedef struct H5F_super_t {
struct H5F_file_t {
H5FD_t *lf; /* Lower level file handle for I/O */
H5F_super_t *sblock; /* Pointer to (pinned) superblock for file */
+ H5O_drvinfo_t *drvinfo; /* Pointer to the (pinned) driver info
+ * cache entry. This field is only defined
+ * for older versions of the super block,
+ * and then only when a driver information
+ * block is present. At all other times
+ * it should be NULL.
+ */
unsigned nrefs; /* Ref count for times file is opened */
unsigned flags; /* Access Permissions for file */
H5F_mtab_t mtab; /* File mount table */
@@ -322,6 +366,7 @@ H5FL_EXTERN(H5F_t);
H5FL_EXTERN(H5F_file_t);
H5_DLLVAR const H5AC_class_t H5AC_SUPERBLOCK[1];
+H5_DLLVAR const H5AC_class_t H5AC_DRVRINFO[1];
/******************************/
diff --git a/src/H5Fsuper.c b/src/H5Fsuper.c
index d5e378e..2ef6964 100644
--- a/src/H5Fsuper.c
+++ b/src/H5Fsuper.c
@@ -258,17 +258,20 @@ H5F__super_read(H5F_t *f, hid_t dxpl_id, hbool_t initial_read)
{
H5P_genplist_t *dxpl; /* DXPL object */
H5F_super_t * sblock = NULL; /* Superblock structure */
+ H5F_superblock_cache_ud_t udata; /* User data for cache callbacks */
+ H5P_genplist_t *c_plist; /* File creation property list */
unsigned sblock_flags = H5AC__NO_FLAGS_SET; /* flags used in superblock unprotect call */
- haddr_t super_addr; /* Absolute address of superblock */
- H5AC_protect_t rw; /* read/write permissions for file */
- H5F_super_ud_t udata; /* User data passed to sblock protect */
- herr_t ret_value = SUCCEED; /* return value */
+ haddr_t super_addr; /* Absolute address of superblock */
+ haddr_t eof; /* End of file address */
+ unsigned rw_flags; /* Read/write permissions for file */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE_TAG(dxpl_id, H5AC__SUPERBLOCK_TAG, FAIL)
- udata.dirtied = FALSE; /* Boolean (dirtied or not ) for sblock protect call */
- udata.initial_read = initial_read; /* Indicate superblock read for initial file open: */
- /* whether to skip the check for truncated file in H5F_sblock_load() */
+ /* initialize the drvinfo to NULL -- we will overwrite this if there
+ * is a driver information block
+ */
+ f->shared->drvinfo = NULL;
/* Get the DXPL plist object for DXPL ID */
if(NULL == (dxpl = (H5P_genplist_t *)H5I_object(dxpl_id)))
@@ -288,23 +291,374 @@ H5F__super_read(H5F_t *f, hid_t dxpl_id, hbool_t initial_read)
} /* end if */
/* Determine file intent for superblock protect */
- if(H5F_INTENT(f) & H5F_ACC_RDWR)
- rw = H5AC_WRITE;
- else
- rw = H5AC_READ;
+
+ /* Must tell cache at protect time that the super block is to be
+ * flushed last (and collectively in the parallel case).
+ */
+ rw_flags = H5AC__FLUSH_LAST_FLAG;
+#ifdef H5_HAVE_PARALLEL
+ rw_flags |= H5C__FLUSH_COLLECTIVELY_FLAG;
+#endif /* H5_HAVE_PARALLEL */
+ if(!(H5F_INTENT(f) & H5F_ACC_RDWR))
+ rw_flags |= H5AC__READ_ONLY_FLAG;
+
+ /* Get the shared file creation property list */
+ if(NULL == (c_plist = (H5P_genplist_t *)H5I_object(f->shared->fcpl_id)))
+ HGOTO_ERROR(H5E_FILE, H5E_BADTYPE, FAIL, "can't get property list")
+
+ /* Make certain we can read the fixed-size portion of the superblock */
+ if(H5F__set_eoa(f, H5FD_MEM_SUPER,
+ (haddr_t)(H5F_SUPERBLOCK_FIXED_SIZE + H5F_SUPERBLOCK_MINIMAL_VARLEN_SIZE)) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "set end of space allocation request failed")
+
+ /* Set up the user data for cache callbacks */
+ udata.f = f;
+ udata.ignore_drvrinfo = H5F_HAS_FEATURE(f, H5FD_FEAT_IGNORE_DRVRINFO);
+ udata.sym_leaf_k = 0;
+ if(H5P_get(c_plist, H5F_CRT_BTREE_RANK_NAME, udata.btree_k) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get rank for btree internal nodes")
+ udata.stored_eof = HADDR_UNDEF;
+ udata.drvrinfo_removed = FALSE;
/* Look up the superblock */
- if(NULL == (sblock = (H5F_super_t *)H5AC_protect(f, dxpl_id, H5AC_SUPERBLOCK, (haddr_t)0, &udata, rw)))
+ if(NULL == (sblock = (H5F_super_t *)H5AC_protect(f, dxpl_id, H5AC_SUPERBLOCK, (haddr_t)0, &udata, rw_flags)))
HGOTO_ERROR(H5E_FILE, H5E_CANTPROTECT, FAIL, "unable to load superblock")
- /* Mark the superblock dirty if it was modified during loading or VFD indicated to do so */
- if((H5AC_WRITE == rw) && (udata.dirtied || H5F_HAS_FEATURE(f, H5FD_FEAT_DIRTY_SBLK_LOAD)))
- sblock_flags |= H5AC__DIRTIED_FLAG;
-
/* Pin the superblock in the cache */
if(H5AC_pin_protected_entry(sblock) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTPIN, FAIL, "unable to pin superblock")
+ /* Mark the superblock dirty if it was modified during loading */
+ if(((rw_flags & H5AC__READ_ONLY_FLAG) == 0) && udata.ignore_drvrinfo && udata.drvrinfo_removed) {
+ HDassert(sblock->super_vers < HDF5_SUPERBLOCK_VERSION_2);
+ sblock_flags |= H5AC__DIRTIED_FLAG;
+ } /* end if */
+
+ /* The superblock must be flushed last (and collectively in parallel) */
+ sblock_flags |= H5AC__FLUSH_LAST_FLAG;
+#ifdef H5_HAVE_PARALLEL
+ sblock_flags |= H5AC__FLUSH_COLLECTIVELY_FLAG;
+#endif /* H5_HAVE_PARALLEL */
+
+ /* Check if superblock address is different from base address and adjust
+ * base address and "end of address" address if so.
+ */
+ if(!H5F_addr_eq(super_addr, sblock->base_addr)) {
+ /* Check if the superblock moved earlier in the file */
+ if(H5F_addr_lt(super_addr, sblock->base_addr))
+ udata.stored_eof -= (sblock->base_addr - super_addr);
+ else
+ /* The superblock moved later in the file */
+ udata.stored_eof += (super_addr - sblock->base_addr);
+
+ /* Adjust base address for offsets of the HDF5 data in the file */
+ sblock->base_addr = super_addr;
+
+ /* Set the base address for the file in the VFD now */
+ if(H5F__set_base_addr(f, sblock->base_addr) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "failed to set base address for file driver")
+
+ /* Indicate that the superblock should be marked dirty */
+ if((rw_flags & H5AC__READ_ONLY_FLAG) == 0)
+ sblock_flags |= H5AC__DIRTIED_FLAG;
+ } /* end if */
+
+ /* Set information in the file's creation property list */
+ if(H5P_set(c_plist, H5F_CRT_SUPER_VERS_NAME, &sblock->super_vers) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "unable to set superblock version")
+ if(H5P_set(c_plist, H5F_CRT_ADDR_BYTE_NUM_NAME, &sblock->sizeof_addr) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "unable to set byte number in an address")
+ if(H5P_set(c_plist, H5F_CRT_OBJ_BYTE_NUM_NAME, &sblock->sizeof_size) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "unable to set byte number for object size")
+
+ /* Handle the B-tree 'K' values */
+ if(sblock->super_vers < HDF5_SUPERBLOCK_VERSION_2) {
+ /* Sanity check */
+ HDassert(udata.sym_leaf_k != 0);
+
+ /* Set the symbol table internal node 'K' value */
+ if(H5P_set(c_plist, H5F_CRT_SYM_LEAF_NAME, &udata.sym_leaf_k) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "unable to set rank for symbol table leaf nodes")
+ sblock->sym_leaf_k = udata.sym_leaf_k;
+
+ /* Set the B-tree internal node values, etc */
+ if(H5P_set(c_plist, H5F_CRT_BTREE_RANK_NAME, udata.btree_k) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "unable to set rank for btree internal nodes")
+ HDmemcpy(sblock->btree_k, udata.btree_k, sizeof(unsigned) * (size_t)H5B_NUM_BTREE_ID);
+ } /* end if */
+ else {
+ /* Get the (default) B-tree internal node values, etc */
+ /* (Note: these may be reset in a superblock extension) */
+ if(H5P_get(c_plist, H5F_CRT_BTREE_RANK_NAME, sblock->btree_k) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get rank for btree internal nodes")
+ if(H5P_get(c_plist, H5F_CRT_SYM_LEAF_NAME, &sblock->sym_leaf_k) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get rank for btree internal nodes")
+ } /* end else */
+
+ /*
+ * The user-defined data is the area of the file before the base
+ * address.
+ */
+ if(H5P_set(c_plist, H5F_CRT_USER_BLOCK_NAME, &sblock->base_addr) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "unable to set userblock size")
+
+ /*
+ * Make sure that the data is not truncated. One case where this is
+ * possible is if the first file of a family of files was opened
+ * individually.
+ */
+ /* (This check can be skipped when the file is opened for SWMR read,
+ * as the file can appear truncated if only part of it has been
+ * been flushed to disk by the single writer process.)
+ */
+ /* Can skip this test when it is not the initial file open--
+ * H5F_super_read() call from H5F_evict_tagged_metadata() for
+ * refreshing object.
+ * When flushing file buffers and fractal heap is involved,
+ * the library will allocate actual space for tmp addresses
+ * via the file layer. The aggregator allocates a block,
+ * thus the eoa might be greater than eof.
+ * Note: the aggregator is changed again after being reset
+ * earlier before H5AC_flush due to allocation of tmp addresses.
+ */
+ if (!(H5F_INTENT(f) & H5F_ACC_SWMR_READ) && initial_read) {
+ if(HADDR_UNDEF == (eof = H5FD_get_eof(f->shared->lf, H5FD_MEM_DEFAULT)))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to determine file size")
+
+ /* (Account for the stored EOA being absolute offset -QAK) */
+ if((eof + sblock->base_addr) < udata.stored_eof)
+ HGOTO_ERROR(H5E_FILE, H5E_TRUNCATED, FAIL, "truncated file: eof = %llu, sblock->base_addr = %llu, stored_eof = %llu", (unsigned long long)eof, (unsigned long long)sblock->base_addr, (unsigned long long)udata.stored_eof)
+ } /* end if */
+
+ /*
+ * Tell the file driver how much address space has already been
+ * allocated so that it knows how to allocate additional memory.
+ */
+
+ /* Decode the optional driver information block */
+ if(H5F_addr_defined(sblock->driver_addr)) {
+ H5O_drvinfo_t *drvinfo; /* Driver info */
+ H5F_drvrinfo_cache_ud_t drvrinfo_udata; /* User data for metadata callbacks */
+ unsigned drvinfo_flags = H5AC__NO_FLAGS_SET; /* Flags used in driver info block unprotect call */
+
+ /* Sanity check - driver info block should only be defined for
+ * superblock version < 2.
+ */
+ HDassert(sblock->super_vers < HDF5_SUPERBLOCK_VERSION_2);
+
+ /* Set up user data */
+ drvrinfo_udata.f = f;
+ drvrinfo_udata.driver_addr = sblock->driver_addr;
+
+ /* extend EOA so we can read at least the fixed sized
+ * portion of the driver info block
+ */
+ if(H5FD_set_eoa(f->shared->lf, H5FD_MEM_SUPER, sblock->driver_addr + H5F_DRVINFOBLOCK_HDR_SIZE) < 0) /* will extend eoa later if required */
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, \
+ "set end of space allocation request failed")
+
+ /* Look up the driver info block */
+ if(NULL == (drvinfo = (H5O_drvinfo_t *)H5AC_protect(f, dxpl_id, H5AC_DRVRINFO, sblock->driver_addr, &drvrinfo_udata, rw_flags)))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTPROTECT, FAIL, "unable to load driver info block")
+
+ /* Loading the driver info block is enough to set up the right info */
+
+ /* Check if we need to rewrite the driver info block info */
+ if ( ( (rw_flags & H5AC__READ_ONLY_FLAG) == 0 ) &&
+ ( H5F_HAS_FEATURE(f, H5FD_FEAT_DIRTY_DRVRINFO_LOAD) ) ) {
+
+ drvinfo_flags |= H5AC__DIRTIED_FLAG;
+ } /* end if */
+
+ /* set the pin entry flag so that the driver information block
+ * cache entry will be pinned in the cache.
+ */
+ drvinfo_flags |= H5AC__PIN_ENTRY_FLAG;
+
+ /* Release the driver info block */
+ if(H5AC_unprotect(f, dxpl_id, H5AC_DRVRINFO, sblock->driver_addr, drvinfo, drvinfo_flags) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTUNPROTECT, FAIL, "unable to release driver info block")
+
+ /* save a pointer to the driver information cache entry */
+ f->shared->drvinfo = drvinfo;
+ } /* end if */
+
+ /* (Account for the stored EOA being absolute offset -NAF) */
+ if(H5F__set_eoa(f, H5FD_MEM_SUPER, udata.stored_eof - sblock->base_addr) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "unable to set end-of-address marker for file")
+
+ /* Decode the optional superblock extension info */
+ if(H5F_addr_defined(sblock->ext_addr)) {
+ H5O_loc_t ext_loc; /* "Object location" for superblock extension */
+ H5O_btreek_t btreek; /* v1 B-tree 'K' value message from superblock extension */
+ H5O_drvinfo_t drvinfo; /* Driver info message from superblock extension */
+ size_t u; /* Local index variable */
+ htri_t status; /* Status for message existing */
+
+ /* Sanity check - superblock extension should only be defined for
+ * superblock version >= 2.
+ */
+ HDassert(sblock->super_vers >= HDF5_SUPERBLOCK_VERSION_2);
+
+ /* Check for superblock extension being located "outside" the stored
+ * 'eoa' value, which can occur with the split/multi VFD.
+ */
+ if(H5F_addr_gt(sblock->ext_addr, udata.stored_eof)) {
+ /* Set the 'eoa' for the object header memory type large enough
+ * to give some room for a reasonably sized superblock extension.
+ * (This is _rather_ a kludge -QAK)
+ */
+ if(H5F__set_eoa(f, H5FD_MEM_OHDR, (haddr_t)(sblock->ext_addr + 1024)) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "unable to set end-of-address marker for file")
+ } /* end if */
+
+ /* Open the superblock extension */
+ if(H5F_super_ext_open(f, sblock->ext_addr, &ext_loc) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENOBJ, FAIL, "unable to open file's superblock extension")
+
+ /* Check for the extension having a 'driver info' message */
+ if((status = H5O_msg_exists(&ext_loc, H5O_DRVINFO_ID, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_EXISTS, FAIL, "unable to read object header")
+ if(status) {
+ /* Check for ignoring the driver info for this file */
+ if(!udata.ignore_drvrinfo) {
+
+ /* Retrieve the 'driver info' structure */
+ if(NULL == H5O_msg_read(&ext_loc, H5O_DRVINFO_ID, &drvinfo, dxpl_id))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "driver info message not present")
+
+ /* Validate and decode driver information */
+ if(H5FD_sb_load(f->shared->lf, drvinfo.name, drvinfo.buf) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTDECODE, FAIL, "unable to decode driver information")
+
+ /* Reset driver info message */
+ H5O_msg_reset(H5O_DRVINFO_ID, &drvinfo);
+ } /* end else */
+ } /* end if */
+
+ /* Read in the shared OH message information if there is any */
+ if(H5SM_get_info(&ext_loc, c_plist, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to read SOHM table information")
+
+ /* Check for the extension having a 'v1 B-tree "K"' message */
+ if((status = H5O_msg_exists(&ext_loc, H5O_BTREEK_ID, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_EXISTS, FAIL, "unable to read object header")
+ if(status) {
+ /* Retrieve the 'v1 B-tree "K"' structure */
+ if(NULL == H5O_msg_read(&ext_loc, H5O_BTREEK_ID, &btreek, dxpl_id))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "v1 B-tree 'K' info message not present")
+
+ /* Set non-default v1 B-tree 'K' value info from file */
+ sblock->btree_k[H5B_CHUNK_ID] = btreek.btree_k[H5B_CHUNK_ID];
+ sblock->btree_k[H5B_SNODE_ID] = btreek.btree_k[H5B_SNODE_ID];
+ sblock->sym_leaf_k = btreek.sym_leaf_k;
+
+ /* Set non-default v1 B-tree 'K' values in the property list */
+ if(H5P_set(c_plist, H5F_CRT_BTREE_RANK_NAME, btreek.btree_k) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "unable to set rank for btree internal nodes")
+ if(H5P_set(c_plist, H5F_CRT_SYM_LEAF_NAME, &btreek.sym_leaf_k) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "unable to set rank for symbol table leaf nodes")
+ } /* end if */
+
+ /* Check for the extension having a 'free-space manager info' message */
+ if((status = H5O_msg_exists(&ext_loc, H5O_FSINFO_ID, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_EXISTS, FAIL, "unable to read object header")
+ if(status) {
+ H5O_fsinfo_t fsinfo; /* Free-space manager info message from superblock extension */
+
+ /* Retrieve the 'free-space manager info' structure */
+ if(NULL == H5O_msg_read(&ext_loc, H5O_FSINFO_ID, &fsinfo, dxpl_id))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get free-space manager info message")
+
+ /* Check for non-default info */
+ if(f->shared->fs_strategy != fsinfo.strategy) {
+ f->shared->fs_strategy = fsinfo.strategy;
+
+ /* Set non-default strategy in the property list */
+ if(H5P_set(c_plist, H5F_CRT_FILE_SPACE_STRATEGY_NAME, &fsinfo.strategy) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "unable to set file space strategy")
+ } /* end if */
+ if(f->shared->fs_threshold != fsinfo.threshold) {
+ f->shared->fs_threshold = fsinfo.threshold;
+
+ /* Set non-default threshold in the property list */
+ if(H5P_set(c_plist, H5F_CRT_FREE_SPACE_THRESHOLD_NAME, &fsinfo.threshold) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "unable to set file space strategy")
+ } /* end if */
+
+ /* Set free-space manager addresses */
+ f->shared->fs_addr[0] = HADDR_UNDEF;
+ for(u = 1; u < NELMTS(f->shared->fs_addr); u++)
+ f->shared->fs_addr[u] = fsinfo.fs_addr[u-1];
+ } /* end if */
+
+ /* Close superblock extension */
+ if(H5F_super_ext_close(f, &ext_loc, dxpl_id, FALSE) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "unable to close file's superblock extension")
+ } /* end if */
+
+ /* Update the driver info if VFD indicated to do so */
+ /* (NOTE: only for later versions of superblock, earlier versions are handled
+ * earlier in this routine.
+ */
+ if(((rw_flags & H5AC__READ_ONLY_FLAG) == 0) &&
+ sblock->super_vers >= HDF5_SUPERBLOCK_VERSION_2 &&
+ H5F_addr_defined(sblock->ext_addr)) {
+ /* Check for modifying the driver info when opening the file */
+ if(H5F_HAS_FEATURE(f, H5FD_FEAT_DIRTY_DRVRINFO_LOAD)) {
+ size_t driver_size; /* Size of driver info block (bytes) */
+
+ /* Check for driver info message */
+ H5_CHECKED_ASSIGN(driver_size, size_t, H5FD_sb_size(f->shared->lf), hsize_t);
+ if(driver_size > 0) {
+ H5O_drvinfo_t drvinfo; /* Driver info */
+ uint8_t dbuf[H5F_MAX_DRVINFOBLOCK_SIZE]; /* Driver info block encoding buffer */
+
+ /* Sanity check */
+ HDassert(driver_size <= H5F_MAX_DRVINFOBLOCK_SIZE);
+
+ /* Encode driver-specific data */
+ if(H5FD_sb_encode(f->shared->lf, drvinfo.name, dbuf) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to encode driver information")
+
+ /* Set the driver info information for the superblock extension */
+ drvinfo.len = driver_size;
+ drvinfo.buf = dbuf;
+
+ /* Write driver info information to the superblock extension */
+
+#if 1 /* bug fix test code -- tidy this up if all goes well */ /* JRM */
+ /* KLUGE ALERT!!
+ *
+ * H5F_super_ext_write_msg() expects f->shared->sblock to
+ * be set -- verify that it is NULL, and then set it.
+ * Set it back to NULL when we are done.
+ */
+ HDassert(f->shared->sblock == NULL);
+ f->shared->sblock = sblock;
+#endif /* JRM */
+
+ if(H5F_super_ext_write_msg(f, dxpl_id, &drvinfo, H5O_DRVINFO_ID, FALSE) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_WRITEERROR, FAIL, "error in writing message to superblock extension")
+
+#if 1 /* bug fix test code -- tidy this up if all goes well */ /* JRM */
+ f->shared->sblock = NULL;
+#endif /* JRM */
+
+ } /* end if */
+ } /* end if */
+ /* Check for eliminating the driver info block */
+ else if(H5F_HAS_FEATURE(f, H5FD_FEAT_IGNORE_DRVRINFO)) {
+ /* Remove the driver info message from the superblock extension */
+ if(H5F_super_ext_remove_msg(f, dxpl_id, H5O_DRVINFO_ID) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "error in removing message from superblock extension")
+
+ /* Check if the superblock extension was removed */
+ if(!H5F_addr_defined(sblock->ext_addr))
+ sblock_flags |= H5AC__DIRTIED_FLAG;
+ } /* end if */
+ } /* end if */
+
/* Set the pointer to the pinned superblock */
f->shared->sblock = sblock;
@@ -313,6 +667,32 @@ done:
if(sblock && H5AC_unprotect(f, dxpl_id, H5AC_SUPERBLOCK, (haddr_t)0, sblock, sblock_flags) < 0)
HDONE_ERROR(H5E_FILE, H5E_CANTUNPROTECT, FAIL, "unable to close superblock")
+ /* If we have failed, make sure no entries are left in the
+ * metadata cache, so that it can be shut down and discarded.
+ */
+ if(ret_value < 0) {
+ /* Unpin and discard drvinfo cache entry */
+ if(f->shared->drvinfo) {
+ if(H5AC_unpin_entry(f->shared->drvinfo) < 0)
+ HDONE_ERROR(H5E_FILE, H5E_CANTUNPIN, FAIL, "unable to unpin driver info")
+
+ /* Evict the driver info block from the cache */
+ if(H5AC_expunge_entry(f, dxpl_id, H5AC_DRVRINFO, sblock->driver_addr, H5AC__NO_FLAGS_SET) < 0)
+ HDONE_ERROR(H5E_FILE, H5E_CANTEXPUNGE, FAIL, "unable to expunge driver info block")
+ } /* end if */
+
+ /* Unpin & discard superblock */
+ if(sblock) {
+ /* Unpin superblock in cache */
+ if(H5AC_unpin_entry(sblock) < 0)
+ HDONE_ERROR(H5E_FILE, H5E_CANTUNPIN, FAIL, "unable to unpin superblock")
+
+ /* Evict the superblock from the cache */
+ if(H5AC_expunge_entry(f, dxpl_id, H5AC_SUPERBLOCK, (haddr_t)0, H5AC__NO_FLAGS_SET) < 0)
+ HDONE_ERROR(H5E_FILE, H5E_CANTEXPUNGE, FAIL, "unable to expunge superblock")
+ } /* end if */
+ } /* end if */
+
FUNC_LEAVE_NOAPI_TAG(ret_value, FAIL)
} /* end H5F__super_read() */
@@ -338,6 +718,8 @@ H5F__super_init(H5F_t *f, hid_t dxpl_id)
{
H5F_super_t *sblock = NULL; /* Superblock cache structure */
hbool_t sblock_in_cache = FALSE; /* Whether the superblock has been inserted into the metadata cache */
+ H5O_drvinfo_t *drvinfo = NULL; /* Driver info */
+ hbool_t drvinfo_in_cache = FALSE; /* Whether the driver info block has been inserted into the metadata cache */
H5P_genplist_t *plist; /* File creation property list */
hsize_t userblock_size; /* Size of userblock, in bytes */
hsize_t superblock_size; /* Size of superblock, in bytes */
@@ -431,11 +813,13 @@ H5F__super_init(H5F_t *f, hid_t dxpl_id)
if(H5F__set_base_addr(f, sblock->base_addr) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "failed to set base address for file driver")
- /* Save a local copy of the superblock version number */
+ /* Save a local copy of the superblock version number, size of addresses & offsets */
sblock->super_vers = super_vers;
+ sblock->sizeof_addr = f->shared->sizeof_addr;
+ sblock->sizeof_size = f->shared->sizeof_size;
/* Compute the size of the superblock */
- superblock_size = (hsize_t)H5F_SUPERBLOCK_SIZE(super_vers, f);
+ superblock_size = (hsize_t)H5F_SUPERBLOCK_SIZE(sblock);
/* Compute the size of the driver information block */
H5_CHECKED_ASSIGN(driver_size, size_t, H5FD_sb_size(f->shared->lf), hsize_t);
@@ -450,10 +834,10 @@ H5F__super_init(H5F_t *f, hid_t dxpl_id)
} /* end if */
/*
- * Allocate space for the userblock, superblock & driver info blocks.
- * We do it with one allocation request because the userblock and
- * superblock need to be at the beginning of the file and only the first
- * allocation request is required to return memory at format address zero.
+ * Allocate space for the superblock & driver info block.
+ * We do it with one allocation request because the superblock needs to be
+ * at the beginning of the file and only the first allocation request is
+ * required to return memory at format address zero.
*/
if(super_vers < HDF5_SUPERBLOCK_VERSION_2)
superblock_size += driver_size;
@@ -470,6 +854,9 @@ H5F__super_init(H5F_t *f, hid_t dxpl_id)
/* Keep a copy of the superblock info */
f->shared->sblock = sblock;
+ /* set the drvinfo filed to NULL -- will overwrite this later if needed */
+ f->shared->drvinfo = NULL;
+
/*
* Determine if we will need a superblock extension
*/
@@ -543,20 +930,20 @@ H5F__super_init(H5F_t *f, hid_t dxpl_id)
/* Check for driver info to store */
if(driver_size > 0) {
- H5O_drvinfo_t drvinfo; /* Driver info */
+ H5O_drvinfo_t t_drvinfo; /* Driver info */
uint8_t dbuf[H5F_MAX_DRVINFOBLOCK_SIZE]; /* Driver info block encoding buffer */
/* Sanity check */
HDassert(driver_size <= H5F_MAX_DRVINFOBLOCK_SIZE);
/* Encode driver-specific data */
- if(H5FD_sb_encode(f->shared->lf, drvinfo.name, dbuf) < 0)
+ if(H5FD_sb_encode(f->shared->lf, t_drvinfo.name, dbuf) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to encode driver information")
/* Write driver info information to the superblock extension */
- drvinfo.len = driver_size;
- drvinfo.buf = dbuf;
- if(H5O_msg_create(&ext_loc, H5O_DRVINFO_ID, H5O_MSG_FLAG_DONTSHARE, H5O_UPDATE_TIME, &drvinfo, dxpl_id) < 0)
+ t_drvinfo.len = driver_size;
+ t_drvinfo.buf = dbuf;
+ if(H5O_msg_create(&ext_loc, H5O_DRVINFO_ID, H5O_MSG_FLAG_DONTSHARE, H5O_UPDATE_TIME, &t_drvinfo, dxpl_id) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to update driver info header message")
} /* end if */
@@ -576,6 +963,33 @@ H5F__super_init(H5F_t *f, hid_t dxpl_id)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to update free-space info header message")
} /* end if */
} /* end if */
+ else {
+ /* Check for creating an "old-style" driver info block */
+ if(driver_size > 0) {
+ /* Sanity check */
+ HDassert(H5F_addr_defined(sblock->driver_addr));
+
+ /* Allocate space for the driver info */
+ if(NULL == (drvinfo = (H5O_drvinfo_t *)H5MM_calloc(sizeof(H5O_drvinfo_t))))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "memory allocation failed for driver info message")
+
+ /* Set up driver info message */
+ /* (NOTE: All the actual information (name & driver information) is
+ * actually based on the VFD info in the file handle and
+ * will be encoded by the VFD's 'encode' callback, so it
+ * doesn't need to be set here. -QAK, 7/20/2013
+ */
+ H5_CHECKED_ASSIGN(drvinfo->len, size_t, H5FD_sb_size(f->shared->lf), hsize_t);
+
+ /* Insert driver info block into cache */
+ if(H5AC_insert_entry(f, dxpl_id, H5AC_DRVRINFO, sblock->driver_addr, drvinfo, H5AC__PIN_ENTRY_FLAG | H5AC__FLUSH_LAST_FLAG | H5AC__FLUSH_COLLECTIVELY_FLAG) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINS, FAIL, "can't add driver info block to cache")
+ drvinfo_in_cache = TRUE;
+ f->shared->drvinfo = drvinfo;
+ } /* end if */
+ else
+ HDassert(!H5F_addr_defined(sblock->driver_addr));
+ } /* end if */
done:
/* Close superblock extension, if it was created */
@@ -584,6 +998,23 @@ done:
/* Cleanup on failure */
if(ret_value < 0) {
+ /* Check if the driver info block has been allocated yet */
+ if(drvinfo) {
+ /* Check if we've cached it already */
+ if(drvinfo_in_cache) {
+ /* Unpin drvinfo in cache */
+ if(H5AC_unpin_entry(drvinfo) < 0)
+ HDONE_ERROR(H5E_FILE, H5E_CANTUNPIN, FAIL, "unable to unpin driver info")
+
+ /* Evict the driver info block from the cache */
+ if(H5AC_expunge_entry(f, dxpl_id, H5AC_DRVRINFO, sblock->driver_addr, H5AC__NO_FLAGS_SET) < 0)
+ HDONE_ERROR(H5E_FILE, H5E_CANTEXPUNGE, FAIL, "unable to expunge driver info block")
+ } /* end if */
+ else
+ /* Free driver info block */
+ H5MM_xfree(drvinfo);
+ } /* end if */
+
/* Check if the superblock has been allocated yet */
if(sblock) {
/* Check if we've cached it already */
@@ -639,6 +1070,14 @@ H5F_super_dirty(H5F_t *f)
if(H5AC_mark_entry_dirty(f->shared->sblock) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTMARKDIRTY, FAIL, "unable to mark superblock as dirty")
+ /* if the driver information block exists, mark it dirty as well
+ * so that the change in eoa will be reflected there as well if
+ * appropriate.
+ */
+ if ( f->shared->drvinfo )
+ if(H5AC_mark_entry_dirty(f->shared->drvinfo) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTMARKDIRTY, FAIL, "unable to mark drvinfo as dirty")
+
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5F_super_dirty() */
@@ -702,7 +1141,7 @@ H5F__super_size(H5F_t *f, hid_t dxpl_id, hsize_t *super_size, hsize_t *super_ext
/* Set the superblock size */
if(super_size)
- *super_size = (hsize_t)H5F_SUPERBLOCK_SIZE(f->shared->sblock->super_vers, f);
+ *super_size = (hsize_t)H5F_SUPERBLOCK_SIZE(f->shared->sblock);
/* Set the superblock extension size */
if(super_ext_size) {
diff --git a/src/H5Fsuper_cache.c b/src/H5Fsuper_cache.c
index ad0bdae..525597b 100644
--- a/src/H5Fsuper_cache.c
+++ b/src/H5Fsuper_cache.c
@@ -51,9 +51,6 @@
/* Local Macros */
/****************/
-/* Maximum size of super-block buffers */
-#define H5F_MAX_SUPERBLOCK_SIZE 134
-
/******************/
/* Local Typedefs */
@@ -70,28 +67,77 @@
/********************/
/* Metadata cache (H5AC) callbacks */
-static H5F_super_t *H5F_sblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata);
-static herr_t H5F_sblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5F_super_t *sblock);
-static herr_t H5F_sblock_dest(H5F_t *f, H5F_super_t * sblock);
-static herr_t H5F_sblock_clear(H5F_t *f, H5F_super_t *sblock, hbool_t destroy);
-static herr_t H5F_sblock_size(const H5F_t *f, const H5F_super_t *sblock, size_t *size_ptr);
+static herr_t H5F__cache_superblock_get_load_size(const void *image_ptr, void *udata,
+ size_t *image_len, size_t *actual_len,
+ hbool_t *compressed_ptr, size_t *compressed_image_len_ptr);
+static htri_t H5F__cache_superblock_verify_chksum(const void *image_ptr, size_t len, void *udata_ptr);
+static void *H5F__cache_superblock_deserialize(const void *image, size_t len,
+ void *udata, hbool_t *dirty);
+static herr_t H5F__cache_superblock_image_len(const void *thing,
+ size_t *image_len, hbool_t *compressed_ptr,
+ size_t *compressed_image_len_ptr);
+static herr_t H5F__cache_superblock_pre_serialize(const H5F_t *f,
+ hid_t dxpl_id, void *thing, haddr_t addr, size_t len,
+ size_t compressed_len, haddr_t *new_addr, size_t *new_len,
+ size_t *new_compressed_len, unsigned *flags);
+static herr_t H5F__cache_superblock_serialize(const H5F_t *f, void *image, size_t len,
+ void *thing);
+static herr_t H5F__cache_superblock_free_icr(void *thing);
+
+static herr_t H5F__cache_drvrinfo_get_load_size(const void *image_ptr, void *udata,
+ size_t *image_len, size_t *actual_len,
+ hbool_t *compressed_ptr, size_t *compressed_image_len_ptr);
+static void *H5F__cache_drvrinfo_deserialize(const void *image, size_t len,
+ void *udata, hbool_t *dirty);
+static herr_t H5F__cache_drvrinfo_image_len(const void *thing,
+ size_t *image_len, hbool_t *compressed_ptr,
+ size_t *compressed_image_len_ptr);
+static herr_t H5F__cache_drvrinfo_serialize(const H5F_t *f, void *image, size_t len,
+ void *thing);
+static herr_t H5F__cache_drvrinfo_free_icr(void *thing);
/*********************/
/* Package Variables */
/*********************/
-/* H5F inherits cache-like properties from H5AC */
+/* H5F superblock inherits cache-like properties from H5AC */
const H5AC_class_t H5AC_SUPERBLOCK[1] = {{
- H5AC_SUPERBLOCK_ID,
- (H5AC_load_func_t)H5F_sblock_load,
- (H5AC_flush_func_t)H5F_sblock_flush,
- (H5AC_dest_func_t)H5F_sblock_dest,
- (H5AC_clear_func_t)H5F_sblock_clear,
- (H5AC_notify_func_t)NULL,
- (H5AC_size_func_t)H5F_sblock_size,
+ H5AC_SUPERBLOCK_ID, /* Metadata client ID */
+ "Superblock", /* Metadata client name (for debugging) */
+ H5FD_MEM_SUPER, /* File space memory type for client */
+ H5AC__CLASS_SPECULATIVE_LOAD_FLAG, /* Client class behavior flags */
+ H5F__cache_superblock_get_load_size,/* 'get_load_size' callback */
+ H5F__cache_superblock_verify_chksum, /* 'verify_chksum' callback */
+ H5F__cache_superblock_deserialize, /* 'deserialize' callback */
+ H5F__cache_superblock_image_len, /* 'image_len' callback */
+ H5F__cache_superblock_pre_serialize,/* 'pre_serialize' callback */
+ H5F__cache_superblock_serialize, /* 'serialize' callback */
+ NULL, /* 'notify' callback */
+ H5F__cache_superblock_free_icr, /* 'free_icr' callback */
+ NULL, /* 'clear' callback */
+ NULL, /* 'fsf_size' callback */
+}};
+
+/* H5F driver info block inherits cache-like properties from H5AC */
+const H5AC_class_t H5AC_DRVRINFO[1] = {{
+ H5AC_DRVRINFO_ID, /* Metadata client ID */
+ "Driver info block", /* Metadata client name (for debugging) */
+ H5FD_MEM_SUPER, /* File space memory type for client */
+ H5AC__CLASS_SPECULATIVE_LOAD_FLAG, /* Client class behavior flags */
+ H5F__cache_drvrinfo_get_load_size, /* 'get_load_size' callback */
+ NULL, /* 'verify_chksum' callback */
+ H5F__cache_drvrinfo_deserialize, /* 'deserialize' callback */
+ H5F__cache_drvrinfo_image_len, /* 'image_len' callback */
+ NULL, /* 'pre_serialize' callback */
+ H5F__cache_drvrinfo_serialize, /* 'serialize' callback */
+ NULL, /* 'notify' callback */
+ H5F__cache_drvrinfo_free_icr, /* 'free_icr' callback */
+ NULL, /* 'clear' callback */
+ NULL, /* 'fsf_size' callback */
}};
+
/*****************************/
/* Library Private Variables */
/*****************************/
@@ -107,583 +153,565 @@ H5FL_EXTERN(H5F_super_t);
/*-------------------------------------------------------------------------
- * Function: H5F_sblock_load
+ * Function: H5F__cache_superblock_get_load_size
*
- * Purpose: Loads the superblock from the file, and deserializes
- * its information into the H5F_super_t structure.
+ * Purpose: Compute the size of the data structure on disk.
*
- * Return: Success: SUCCEED
- * Failure: NULL
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Mike McGreevy
- * mamcgree@hdfgroup.org
- * April 8, 2009
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * July 17, 2013
*
*-------------------------------------------------------------------------
*/
-static H5F_super_t *
-H5F_sblock_load(H5F_t *f, hid_t dxpl_id, haddr_t H5_ATTR_UNUSED addr, void *_udata)
+static herr_t
+H5F__cache_superblock_get_load_size(const void *_image, void *_udata, size_t *image_len, size_t *actual_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr)
{
- H5F_super_t *sblock = NULL; /* File's superblock */
- haddr_t base_addr = HADDR_UNDEF; /* Base address of file */
- uint8_t sbuf[H5F_MAX_SUPERBLOCK_SIZE]; /* Buffer for superblock */
- H5P_genplist_t *dxpl; /* DXPL object */
- H5P_genplist_t *c_plist; /* File creation property list */
- H5F_file_t *shared; /* shared part of `file' */
- H5FD_t *lf; /* file driver part of `shared' */
- haddr_t stored_eof; /* stored end-of-file address in file */
- haddr_t eof; /* end of file address */
- uint8_t sizeof_addr; /* Size of offsets in the file (in bytes) */
- uint8_t sizeof_size; /* Size of lengths in the file (in bytes) */
- const size_t fixed_size = H5F_SUPERBLOCK_FIXED_SIZE; /*fixed sizeof superblock */
- size_t variable_size; /*variable sizeof superblock */
- uint8_t *p; /* Temporary pointer into encoding buffer */
- unsigned super_vers; /* Superblock version */
- H5F_super_ud_t *udata = (H5F_super_ud_t *)_udata;
- unsigned tries, max_tries; /* The # of read attempts to try */
- unsigned retries; /* The # of retries */
- uint32_t computed_chksum; /* Computed checksum */
- uint32_t stored_chksum; /* Checksum read from file */
- H5F_super_t *ret_value; /* Return value */
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ H5F_superblock_cache_ud_t *udata = (H5F_superblock_cache_ud_t *)_udata; /* User data */
+ unsigned super_vers; /* Superblock version */
+ uint8_t sizeof_addr; /* Size of offsets in the file (in bytes) */
+ uint8_t sizeof_size; /* Size of lengths in the file (in bytes) */
+ size_t variable_size; /* Variable size of superblock */
+ htri_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
/* Check arguments */
- HDassert(f);
- HDassert(H5F_addr_eq(addr, 0));
+ HDassert(image_len);
+
+ if(image == NULL) {
+ HDassert(actual_len == NULL);
+
+ /* Set the initial image length size */
+ *image_len = H5F_SUPERBLOCK_FIXED_SIZE + /* Fixed size of superblock */
+ H5F_SUPERBLOCK_MINIMAL_VARLEN_SIZE;
+ } else { /* compute actual_len */
+ HDassert(udata);
+ HDassert(udata->f);
+ HDassert(actual_len);
+ HDassert(*actual_len == *image_len);
+
+ image += H5F_SIGNATURE_LEN;
+
+ /* Superblock version */
+ super_vers = *image++;
+ if(super_vers > HDF5_SUPERBLOCK_VERSION_LATEST)
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "bad superblock version number")
+
+ /* Save the version to be used in verify_chksum callback */
+ udata->super_vers = super_vers;
+
+ /* Sanity check */
+ HDassert(((size_t)(image - (const uint8_t *)_image)) == H5F_SUPERBLOCK_FIXED_SIZE);
+ HDassert(*image_len >= H5F_SUPERBLOCK_FIXED_SIZE + 6);
+
+ /* Determine the size of addresses & size of offsets, for computing the
+ * variable-sized portion of the superblock.
+ */
+ if(super_vers < HDF5_SUPERBLOCK_VERSION_2) {
+ sizeof_addr = image[4];
+ sizeof_size = image[5];
+ } /* end if */
+ else {
+ sizeof_addr = image[0];
+ sizeof_size = image[1];
+ } /* end else */
+ if(sizeof_addr != 2 && sizeof_addr != 4 &&
+ sizeof_addr != 8 && sizeof_addr != 16 && sizeof_addr != 32)
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "bad byte number in an address")
+ if(sizeof_size != 2 && sizeof_size != 4 &&
+ sizeof_size != 8 && sizeof_size != 16 && sizeof_size != 32)
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "bad byte number for object size")
+
+ /* Determine the size of the variable-length part of the superblock */
+ variable_size = (size_t)H5F_SUPERBLOCK_VARLEN_SIZE(super_vers, sizeof_addr, sizeof_size);
+ HDassert(variable_size > 0);
+
+ /* Handle metadata cache retry for variable-sized portion of the superblock */
+ if(*image_len != (H5F_SUPERBLOCK_FIXED_SIZE + variable_size)) {
+
+ /* Sanity check */
+ HDassert(*image_len == (H5F_SUPERBLOCK_FIXED_SIZE + H5F_SUPERBLOCK_MINIMAL_VARLEN_SIZE));
+
+ /* Make certain we can read the variabled-sized portion of the superblock */
+ if(H5F__set_eoa(udata->f, H5FD_MEM_SUPER, (haddr_t)(H5F_SUPERBLOCK_FIXED_SIZE + variable_size)) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "set end of space allocation request failed")
+
+ *actual_len = H5F_SUPERBLOCK_FIXED_SIZE + variable_size;
+
+ } /* end if */
+ }
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F__cache_superblock_get_load_size() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F__cache_superblock_verify_chksum
+ *
+ * Purpose: Verify the computed checksum of the data structure is the
+ * same as the stored chksum.
+ *
+ * Return: Success: TRUE/FALSE
+ * Failure: Negative
+ *
+ * Programmer: Vailin Choi; Aug 2015
+ *
+ *-------------------------------------------------------------------------
+ */
+static htri_t
+H5F__cache_superblock_verify_chksum(const void *_image, size_t len, void *_udata)
+{
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ H5F_superblock_cache_ud_t *udata = (H5F_superblock_cache_ud_t *)_udata; /* User data */
+ uint32_t stored_chksum; /* Stored metadata checksum value */
+ uint32_t computed_chksum; /* Computed metadata checksum value */
+ htri_t ret_value = TRUE; /* Return value */
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Check arguments */
+ HDassert(image);
HDassert(udata);
- /* Short cuts */
- shared = f->shared;
- lf = shared->lf;
+ /* No checksum for version 0 & 1 */
+ if(udata->super_vers >= HDF5_SUPERBLOCK_VERSION_2) {
- /* Get the shared file creation property list */
- if(NULL == (c_plist = (H5P_genplist_t *)H5I_object(shared->fcpl_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "can't get property list")
+ /* Get stored and computed checksums */
+ H5F_get_checksums(image, len, &stored_chksum, &computed_chksum);
- /* Get the base address for the file in the VFD */
- if(HADDR_UNDEF == (base_addr = H5FD_get_base_addr(lf)))
- HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "failed to get base address for file driver")
+ if(stored_chksum != computed_chksum)
+ ret_value = FALSE;
+ }
- /* Allocate space for the superblock */
- if(NULL == (sblock = H5FL_CALLOC(H5F_super_t)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F__cache_superblock_verify_chksum() */
- /* The superblock must be flushed last (and collectively in parallel) */
- sblock->cache_info.flush_me_last = TRUE;
-#ifdef H5_HAVE_PARALLEL
- sblock->cache_info.flush_me_collectively = TRUE;
-#endif
+
+/*-------------------------------------------------------------------------
+ * Function: H5F__cache_superblock_deserialize
+ *
+ * Purpose: Loads an object from the disk.
+ *
+ * Return: Success: Pointer to new object
+ * Failure: NULL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * July 18 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+static void *
+H5F__cache_superblock_deserialize(const void *_image, size_t len, void *_udata,
+ hbool_t H5_ATTR_UNUSED *dirty)
+{
+ H5F_super_t *sblock = NULL; /* File's superblock */
+ H5F_superblock_cache_ud_t *udata = (H5F_superblock_cache_ud_t *)_udata; /* User data */
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ size_t variable_size; /* Variable size of superblock */
+ unsigned super_vers; /* Superblock version */
+ uint8_t sizeof_addr; /* Size of offsets in the file (in bytes) */
+ uint8_t sizeof_size; /* Size of lengths in the file (in bytes) */
+ H5F_super_t *ret_value; /* Return value */
- /* Get the DXPL plist object for DXPL ID */
- if(NULL == (dxpl = (H5P_genplist_t *)H5I_object(dxpl_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "can't get property list")
+ FUNC_ENTER_STATIC
- H5_CHECK_OVERFLOW(fixed_size, size_t, haddr_t);
+ /* Check arguments */
+ HDassert(image);
+ HDassert(udata);
+ HDassert(udata->f);
- /* Get the # of read attempts */
- tries = max_tries = H5F_GET_READ_ATTEMPTS(f);
- retries = 0;
- do {
- /* Read fixed-size portion of the superblock */
- p = sbuf;
- if(H5FD_set_eoa(lf, H5FD_MEM_SUPER, (haddr_t)fixed_size) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "set end of space allocation request failed")
- if(H5FD_read(lf, dxpl, H5FD_MEM_SUPER, (haddr_t)0, fixed_size, p) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_READERROR, NULL, "unable to read superblock")
+ /* Allocate space for the superblock */
+ if(NULL == (sblock = H5FL_CALLOC(H5F_super_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
- /* Skip over signature (already checked when locating the superblock) */
- p += H5F_SIGNATURE_LEN;
+ image += H5F_SIGNATURE_LEN;
- /* Superblock version */
- super_vers = *p++;
- if(super_vers > HDF5_SUPERBLOCK_VERSION_LATEST)
- HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad superblock version number")
- if(H5P_set(c_plist, H5F_CRT_SUPER_VERS_NAME, &super_vers) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, NULL, "unable to set superblock version")
+ /* Superblock version */
+ super_vers = *image++;
+ if(super_vers > HDF5_SUPERBLOCK_VERSION_LATEST)
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad superblock version number")
- /* Record the superblock version */
- sblock->super_vers = super_vers;
+ /* Record the superblock version */
+ sblock->super_vers = super_vers;
- /* Sanity check */
- HDassert(((size_t)(p - sbuf)) == fixed_size);
+ /* Sanity check */
+ HDassert(((size_t)(image - (const uint8_t *)_image)) == H5F_SUPERBLOCK_FIXED_SIZE);
+ HDassert(len >= H5F_SUPERBLOCK_FIXED_SIZE + 6);
- /* Determine the size of the variable-length part of the superblock */
- variable_size = (size_t)H5F_SUPERBLOCK_VARLEN_SIZE(super_vers, f);
- HDassert(variable_size > 0);
- HDassert(fixed_size + variable_size <= sizeof(sbuf));
-
- /* Read in variable-sized portion of superblock */
- if(H5FD_set_eoa(lf, H5FD_MEM_SUPER, (haddr_t)(fixed_size + variable_size)) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "set end of space allocation request failed")
- if(H5FD_read(lf, dxpl, H5FD_MEM_SUPER, (haddr_t)fixed_size, variable_size, p) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to read superblock")
-
- /* No checksum for version 0 & 1 */
- if(super_vers < HDF5_SUPERBLOCK_VERSION_2)
- break;
-
- /* Decode size of file addresses at this point to get the correct H5F_SIZEOF_ADDR(f) for checksum */
- sizeof_addr = *p++;
- if(sizeof_addr == 2 || sizeof_addr == 4 ||
- sizeof_addr == 8 || sizeof_addr == 16 || sizeof_addr == 32) {
-
- if(H5P_set(c_plist, H5F_CRT_ADDR_BYTE_NUM_NAME, &sizeof_addr) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, NULL, "unable to set byte number in an address")
- shared->sizeof_addr = sizeof_addr; /* Keep a local copy also */
-
- /* Retrieve stored and computed checksum */
- H5F_get_checksums(sbuf, fixed_size + H5F_SUPERBLOCK_VARLEN_SIZE(super_vers, f), &stored_chksum, &computed_chksum);
-
- /* Verify correct checksum */
- if(stored_chksum == computed_chksum)
- break;
- } /* end if */
- } while (--tries);
+ /* Determine the size of addresses & size of offsets, for computing the
+ * variable-sized portion of the superblock.
+ */
+ if(super_vers < HDF5_SUPERBLOCK_VERSION_2) {
+ sizeof_addr = image[4];
+ sizeof_size = image[5];
+ } /* end if */
+ else {
+ sizeof_addr = image[0];
+ sizeof_size = image[1];
+ } /* end else */
+ if(sizeof_addr != 2 && sizeof_addr != 4 &&
+ sizeof_addr != 8 && sizeof_addr != 16 && sizeof_addr != 32)
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad byte number in an address")
+ if(sizeof_size != 2 && sizeof_size != 4 &&
+ sizeof_size != 8 && sizeof_size != 16 && sizeof_size != 32)
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad byte number for object size")
+ sblock->sizeof_addr = sizeof_addr;
+ sblock->sizeof_size = sizeof_size;
- if(tries == 0)
- /* After all tries (for SWMR access) or after 1 try (for non-SWMR) */
- HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "bad checksum or bad byte value in superblock")
+ /* Determine the size of the variable-length part of the superblock */
+ variable_size = (size_t)H5F_SUPERBLOCK_VARLEN_SIZE(super_vers, sizeof_addr, sizeof_size);
+ HDassert(variable_size > 0);
- retries += (max_tries - tries);
- if(retries) /* Does not track 0 retry */
- if(H5F_track_metadata_read_retries(f, H5AC_SUPERBLOCK_ID, retries) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "cannot track read retries = %u ", retries)
+ HDassert(len == (H5F_SUPERBLOCK_FIXED_SIZE + variable_size));
/* Check for older version of superblock format */
if(super_vers < HDF5_SUPERBLOCK_VERSION_2) {
- uint32_t status_flags; /* File status flags */
- unsigned btree_k[H5B_NUM_BTREE_ID]; /* B-tree internal node 'K' values */
- unsigned sym_leaf_k; /* Symbol table leaf node's 'K' value */
-
- /* Freespace version (hard-wired) */
- if(HDF5_FREESPACE_VERSION != *p++)
- HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad free space version number")
-
- /* Root group version number (hard-wired) */
- if(HDF5_OBJECTDIR_VERSION != *p++)
- HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad object directory version number")
-
- /* Skip over reserved byte */
- p++;
-
- /* Shared header version number (hard-wired) */
- if(HDF5_SHAREDHEADER_VERSION != *p++)
- HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad shared-header format version number")
-
- /* Size of file addresses */
- sizeof_addr = *p++;
- if(sizeof_addr != 2 && sizeof_addr != 4 &&
- sizeof_addr != 8 && sizeof_addr != 16 && sizeof_addr != 32)
- HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad byte number in an address")
- if(H5P_set(c_plist, H5F_CRT_ADDR_BYTE_NUM_NAME, &sizeof_addr) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, NULL, "unable to set byte number in an address")
- shared->sizeof_addr = sizeof_addr; /* Keep a local copy also */
-
- /* Size of file sizes */
- sizeof_size = *p++;
- if(sizeof_size != 2 && sizeof_size != 4 &&
- sizeof_size != 8 && sizeof_size != 16 && sizeof_size != 32)
- HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad byte number for object size")
- if(H5P_set(c_plist, H5F_CRT_OBJ_BYTE_NUM_NAME, &sizeof_size) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, NULL, "unable to set byte number for object size")
- shared->sizeof_size = sizeof_size; /* Keep a local copy also */
-
- /* Skip over reserved byte */
- p++;
-
- /* Various B-tree sizes */
- UINT16DECODE(p, sym_leaf_k);
- if(sym_leaf_k == 0)
- HGOTO_ERROR(H5E_FILE, H5E_BADRANGE, NULL, "bad symbol table leaf node 1/2 rank")
- if(H5P_set(c_plist, H5F_CRT_SYM_LEAF_NAME, &sym_leaf_k) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, NULL, "unable to set rank for symbol table leaf nodes")
- sblock->sym_leaf_k = sym_leaf_k; /* Keep a local copy also */
+ uint32_t status_flags; /* File status flags */
+ unsigned sym_leaf_k; /* Symbol table leaf node's 'K' value */
+ unsigned snode_btree_k; /* B-tree symbol table internal node 'K' value */
+ unsigned chunk_btree_k; /* B-tree chunk internal node 'K' value */
+
+ /* Freespace version (hard-wired) */
+ if(HDF5_FREESPACE_VERSION != *image++)
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad free space version number")
+
+ /* Root group version number (hard-wired) */
+ if(HDF5_OBJECTDIR_VERSION != *image++)
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad object directory version number")
+
+ /* Skip over reserved byte */
+ image++;
+
+ /* Shared header version number (hard-wired) */
+ if(HDF5_SHAREDHEADER_VERSION != *image++)
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad shared-header format version number")
+
+ /* Size of file addresses */
+ sizeof_addr = *image++;
+ if(sizeof_addr != 2 && sizeof_addr != 4 &&
+ sizeof_addr != 8 && sizeof_addr != 16 && sizeof_addr != 32)
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad byte number in an address")
+ sblock->sizeof_addr = sizeof_addr;
+ udata->f->shared->sizeof_addr = sizeof_addr; /* Keep a local copy also */
+
+ /* Size of file sizes */
+ sizeof_size = *image++;
+ if(sizeof_size != 2 && sizeof_size != 4 &&
+ sizeof_size != 8 && sizeof_size != 16 && sizeof_size != 32)
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad byte number for object size")
+ sblock->sizeof_size = sizeof_size;
+ udata->f->shared->sizeof_size = sizeof_size; /* Keep a local copy also */
+
+ /* Skip over reserved byte */
+ image++;
+
+ /* Various B-tree sizes */
+ UINT16DECODE(image, sym_leaf_k);
+ if(sym_leaf_k == 0)
+ HGOTO_ERROR(H5E_FILE, H5E_BADRANGE, NULL, "bad symbol table leaf node 1/2 rank")
+ udata->sym_leaf_k = sym_leaf_k; /* Keep a local copy also */
/* Need 'get' call to set other array values */
- if(H5P_get(c_plist, H5F_CRT_BTREE_RANK_NAME, btree_k) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "unable to get rank for btree internal nodes")
- UINT16DECODE(p, btree_k[H5B_SNODE_ID]);
- if(btree_k[H5B_SNODE_ID] == 0)
- HGOTO_ERROR(H5E_FILE, H5E_BADRANGE, NULL, "bad 1/2 rank for btree internal nodes")
- /*
+ UINT16DECODE(image, snode_btree_k);
+ if(snode_btree_k == 0)
+ HGOTO_ERROR(H5E_FILE, H5E_BADRANGE, NULL, "bad 1/2 rank for btree internal nodes")
+ udata->btree_k[H5B_SNODE_ID] = snode_btree_k;
+
+ /*
* Delay setting the value in the property list until we've checked
* for the indexed storage B-tree internal 'K' value later.
*/
/* File status flags (not really used yet) */
- UINT32DECODE(p, status_flags);
+ UINT32DECODE(image, status_flags);
HDassert(status_flags <= 255);
sblock->status_flags = (uint8_t)status_flags;
if(sblock->status_flags & ~H5F_SUPER_ALL_FLAGS)
- HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad flag value for superblock")
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad flag value for superblock")
- /*
+ /*
* If the superblock version # is greater than 0, read in the indexed
* storage B-tree internal 'K' value
*/
if(super_vers > HDF5_SUPERBLOCK_VERSION_DEF) {
- UINT16DECODE(p, btree_k[H5B_CHUNK_ID]);
- /* Reserved bytes are present only in version 1 */
- if(super_vers == HDF5_SUPERBLOCK_VERSION_1)
- p += 2; /* reserved */
- } /* end if */
- else
- btree_k[H5B_CHUNK_ID] = HDF5_BTREE_CHUNK_IK_DEF;
+ UINT16DECODE(image, chunk_btree_k);
- /* Set the B-tree internal node values, etc */
- if(H5P_set(c_plist, H5F_CRT_BTREE_RANK_NAME, btree_k) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, NULL, "unable to set rank for btree internal nodes")
- HDmemcpy(sblock->btree_k, btree_k, sizeof(unsigned) * (size_t)H5B_NUM_BTREE_ID); /* Keep a local copy also */
+ /* Reserved bytes are present only in version 1 */
+ if(super_vers == HDF5_SUPERBLOCK_VERSION_1)
+ image += 2; /* reserved */
+ } /* end if */
+ else
+ chunk_btree_k = HDF5_BTREE_CHUNK_IK_DEF;
+ udata->btree_k[H5B_CHUNK_ID] = chunk_btree_k;
- /* Remainder of "variable-sized" portion of superblock */
- H5F_addr_decode(f, (const uint8_t **)&p, &sblock->base_addr/*out*/);
- H5F_addr_decode(f, (const uint8_t **)&p, &sblock->ext_addr/*out*/);
- H5F_addr_decode(f, (const uint8_t **)&p, &stored_eof/*out*/);
- H5F_addr_decode(f, (const uint8_t **)&p, &sblock->driver_addr/*out*/);
+ /* Remainder of "variable-sized" portion of superblock */
+ H5F_addr_decode(udata->f, (const uint8_t **)&image, &sblock->base_addr/*out*/);
+ H5F_addr_decode(udata->f, (const uint8_t **)&image, &sblock->ext_addr/*out*/);
+ H5F_addr_decode(udata->f, (const uint8_t **)&image, &udata->stored_eof/*out*/);
+ H5F_addr_decode(udata->f, (const uint8_t **)&image, &sblock->driver_addr/*out*/);
- /* Allocate space for the root group symbol table entry */
- HDassert(!sblock->root_ent);
- if(NULL == (sblock->root_ent = (H5G_entry_t *)H5MM_calloc(sizeof(H5G_entry_t))))
- HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, NULL, "can't allocate space for root group symbol table entry")
+ /* Allocate space for the root group symbol table entry */
+ HDassert(!sblock->root_ent);
+ if(NULL == (sblock->root_ent = (H5G_entry_t *)H5MM_calloc(sizeof(H5G_entry_t))))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, NULL, "can't allocate space for root group symbol table entry")
- /* decode the root group symbol table entry */
- if(H5G_ent_decode(f, (const uint8_t **)&p, sblock->root_ent) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTDECODE, NULL, "can't decode root group symbol table entry")
+ /* decode the root group symbol table entry */
+ if(H5G_ent_decode(udata->f, (const uint8_t **)&image, sblock->root_ent) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTDECODE, NULL, "can't decode root group symbol table entry")
- /* Set the root group address to the correct value */
- sblock->root_addr = sblock->root_ent->header;
+ /* Set the root group address to the correct value */
+ sblock->root_addr = sblock->root_ent->header;
- /*
- * Check if superblock address is different from base address and
- * adjust base address and "end of address" address if so.
- */
- if(!H5F_addr_eq(base_addr, sblock->base_addr)) {
- /* Check if the superblock moved earlier in the file */
- if(H5F_addr_lt(base_addr, sblock->base_addr))
- stored_eof -= (sblock->base_addr - base_addr);
- else
- /* The superblock moved later in the file */
- stored_eof += (base_addr - sblock->base_addr);
-
- /* Adjust base address for offsets of the HDF5 data in the file */
- sblock->base_addr = base_addr;
-
- /* Set the base address for the file in the VFD now */
- if(H5FD_set_base_addr(lf, sblock->base_addr) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTSET, NULL, "failed to set base address for file driver")
-
- /* Indicate that the superblock should be marked dirty */
- udata->dirtied = TRUE;
- } /* end if */
-
- /* This step is for h5repart tool only. If user wants to change file driver
+ /* This step is for h5repart tool only. If user wants to change file driver
* from family to sec2 while using h5repart, set the driver address to
* undefined to let the library ignore the family driver information saved
* in the superblock.
*/
- if(H5F_HAS_FEATURE(f, H5FD_FEAT_IGNORE_DRVRINFO)) {
- /* Eliminate the driver info */
- sblock->driver_addr = HADDR_UNDEF;
+ if(udata->ignore_drvrinfo && H5F_addr_defined(sblock->driver_addr)) {
+ /* Eliminate the driver info */
+ sblock->driver_addr = HADDR_UNDEF;
+ udata->drvrinfo_removed = TRUE;
+ } /* end if */
- /* Indicate that the superblock should be marked dirty */
- udata->dirtied = TRUE;
- } /* end if */
+ /* NOTE: Driver info block is decoded separately, later */
- /* Decode the optional driver information block */
- if(H5F_addr_defined(sblock->driver_addr)) {
- uint8_t dbuf[H5F_MAX_DRVINFOBLOCK_SIZE]; /* Buffer for driver info block */
- char drv_name[9]; /* Name of driver */
- unsigned drv_vers; /* Version of driver info block */
- size_t drv_variable_size; /* Size of variable-length portion of driver info block, in bytes */
-
- /* Read in fixed-sized portion of driver info block */
- p = dbuf;
- if(H5FD_set_eoa(lf, H5FD_MEM_SUPER, sblock->driver_addr + H5F_DRVINFOBLOCK_HDR_SIZE) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "set end of space allocation request failed")
- if(H5FD_read(lf, dxpl, H5FD_MEM_SUPER, sblock->driver_addr, (size_t)H5F_DRVINFOBLOCK_HDR_SIZE, p) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to read driver information block")
-
- /* Version number */
- drv_vers = *p++;
- if(drv_vers != HDF5_DRIVERINFO_VERSION_0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "bad driver information block version number")
-
- p += 3; /* reserved bytes */
-
- /* Driver info size */
- UINT32DECODE(p, drv_variable_size);
-
- /* Sanity check */
- HDassert(H5F_DRVINFOBLOCK_HDR_SIZE + drv_variable_size <= sizeof(dbuf));
-
- /* Driver name and/or version */
- HDstrncpy(drv_name, (const char *)p, (size_t)8);
- drv_name[8] = '\0';
- p += 8; /* advance past name/version */
-
- /* Read in variable-sized portion of driver info block */
- if(H5FD_set_eoa(lf, H5FD_MEM_SUPER, sblock->driver_addr + H5F_DRVINFOBLOCK_HDR_SIZE + drv_variable_size) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "set end of space allocation request failed")
- if(H5FD_read(lf, dxpl, H5FD_MEM_SUPER, sblock->driver_addr + H5F_DRVINFOBLOCK_HDR_SIZE, drv_variable_size, p) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to read file driver information")
-
- /* Decode driver information */
- if(H5FD_sb_load(lf, drv_name, p) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to decode driver information")
- } /* end if */
} /* end if */
else {
+ uint32_t read_chksum; /* Checksum read from file */
+
+ /* Size of file addresses */
+ sizeof_addr = *image++;
+ if(sizeof_addr != 2 && sizeof_addr != 4 &&
+ sizeof_addr != 8 && sizeof_addr != 16 && sizeof_addr != 32)
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad byte number in an address")
+ sblock->sizeof_addr = sizeof_addr;
+ udata->f->shared->sizeof_addr = sizeof_addr; /* Keep a local copy also */
+
+ /* Size of file sizes */
+ sizeof_size = *image++;
+ if(sizeof_size != 2 && sizeof_size != 4 &&
+ sizeof_size != 8 && sizeof_size != 16 && sizeof_size != 32)
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad byte number for object size")
+ sblock->sizeof_size = sizeof_size;
+ udata->f->shared->sizeof_size = sizeof_size; /* Keep a local copy also */
+
+ /* File status flags (not really used yet) */
+ sblock->status_flags = *image++;
+ if(sblock->status_flags & ~H5F_SUPER_ALL_FLAGS)
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad flag value for superblock")
+
+ /* Base, superblock extension, end of file & root group object header addresses */
+ H5F_addr_decode(udata->f, (const uint8_t **)&image, &sblock->base_addr/*out*/);
+ H5F_addr_decode(udata->f, (const uint8_t **)&image, &sblock->ext_addr/*out*/);
+ H5F_addr_decode(udata->f, (const uint8_t **)&image, &udata->stored_eof/*out*/);
+ H5F_addr_decode(udata->f, (const uint8_t **)&image, &sblock->root_addr/*out*/);
+
+ /* checksum verification already done in verify_chksum cb */
+
+ /* Decode checksum */
+ UINT32DECODE(image, read_chksum);
+
+ /* The Driver Information Block may not appear with the version
+ * 2 super block. Thus we set the driver_addr field of the in
+ * core representation of the super block HADDR_UNDEF to prevent
+ * any attempt to load the Driver Information Block.
+ */
+ sblock->driver_addr = HADDR_UNDEF;
+ } /* end else */
- /* Already decoded sizeof_addr (and set property) when validating checksum earlier */
+ /* Sanity check */
+ HDassert((size_t)(image - (const uint8_t *)_image) <= len);
- /* Size of file sizes */
- sizeof_size = *p++;
- if(sizeof_size != 2 && sizeof_size != 4 &&
- sizeof_size != 8 && sizeof_size != 16 && sizeof_size != 32)
- HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad byte number for object size")
- if(H5P_set(c_plist, H5F_CRT_OBJ_BYTE_NUM_NAME, &sizeof_size) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, NULL, "unable to set byte number for object size")
- shared->sizeof_size = sizeof_size; /* Keep a local copy also */
+ /* Set return value */
+ ret_value = sblock;
- /* File status flags (not really used yet) */
- sblock->status_flags = *p++;
- if(sblock->status_flags & ~H5F_SUPER_ALL_FLAGS)
- HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad flag value for superblock")
+done:
+ /* Release the [possibly partially initialized] superblock on error */
+ if(!ret_value && sblock)
+ if(H5F__super_free(sblock) < 0)
+ HDONE_ERROR(H5E_FILE, H5E_CANTFREE, NULL, "unable to destroy superblock data")
- /* Base, superblock extension, end of file & root group object header addresses */
- H5F_addr_decode(f, (const uint8_t **)&p, &sblock->base_addr/*out*/);
- H5F_addr_decode(f, (const uint8_t **)&p, &sblock->ext_addr/*out*/);
- H5F_addr_decode(f, (const uint8_t **)&p, &stored_eof/*out*/);
- H5F_addr_decode(f, (const uint8_t **)&p, &sblock->root_addr/*out*/);
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F__cache_superblock_deserialize() */
- /* Already decoded and compared stored checksum earlier, when reading */
+
+/*-------------------------------------------------------------------------
+ * Function: H5F__cache_superblock_image_len
+ *
+ * Purpose: Compute the size of the data structure on disk.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * July 19, 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5F__cache_superblock_image_len(const void *_thing, size_t *image_len, hbool_t *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr)
+{
+ const H5F_super_t *sblock = (const H5F_super_t *)_thing; /* Pointer to the object */
- /*
- * Check if superblock address is different from base address and
- * adjust base address and "end of address" address if so.
- */
- if(!H5F_addr_eq(base_addr, sblock->base_addr)) {
- /* Check if the superblock moved earlier in the file */
- if(H5F_addr_lt(base_addr, sblock->base_addr))
- stored_eof -= (sblock->base_addr - base_addr);
- else
- /* The superblock moved later in the file */
- stored_eof += (base_addr - sblock->base_addr);
-
- /* Adjust base address for offsets of the HDF5 data in the file */
- sblock->base_addr = base_addr;
-
- /* Set the base address for the file in the VFD now */
- if(H5FD_set_base_addr(lf, sblock->base_addr) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTSET, NULL, "failed to set base address for file driver")
-
- /* Indicate that the superblock should be marked dirty */
- udata->dirtied = TRUE;
- } /* end if */
+ FUNC_ENTER_STATIC_NOERR
- /* Get the B-tree internal node values, etc */
- if(H5P_get(c_plist, H5F_CRT_BTREE_RANK_NAME, sblock->btree_k) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "unable to get rank for btree internal nodes")
- if(H5P_get(c_plist, H5F_CRT_SYM_LEAF_NAME, &sblock->sym_leaf_k) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "unable to get rank for btree internal nodes")
- } /* end else */
+ /* Check arguments */
+ HDassert(sblock);
+ HDassert(sblock->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(sblock->cache_info.type == H5AC_SUPERBLOCK);
+ HDassert(image_len);
+ HDassert(compressed_ptr);
- /*
- * The user-defined data is the area of the file before the base
- * address.
- */
- if(H5P_set(c_plist, H5F_CRT_USER_BLOCK_NAME, &sblock->base_addr) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, NULL, "unable to set userblock size")
+ /* Set the image length size */
+ *image_len = (size_t)H5F_SUPERBLOCK_SIZE(sblock);
- /*
- * Make sure that the data is not truncated. One case where this is
- * possible is if the first file of a family of files was opened
- * individually.
- */
- /* (This check can be skipped when the file is opened for SWMR read,
- * as the file can appear truncated if only part of it has been
- * been flushed to disk by the single writer process.)
- */
- /* Can skip this test when it is not the initial file open--
- * H5F_super_read() call from H5F_evict_tagged_metadata() for
- * refreshing object.
- * When flushing file buffers and fractal heap is involved,
- * the library will allocate actual space for tmp addresses
- * via the file layer. The aggregator allocates a block,
- * thus the eoa might be greater than eof.
- * Note: the aggregator is changed again after being reset
- * earlier before H5AC_flush due to allocation of tmp addresses.
- */
- if (!(H5F_INTENT(f) & H5F_ACC_SWMR_READ) && udata->initial_read) {
- if(HADDR_UNDEF == (eof = H5FD_get_eof(lf, H5FD_MEM_DEFAULT)))
- HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to determine file size")
+ /* Set *compressed_ptr to FALSE unconditionally */
+ *compressed_ptr;
- /* (Account for the stored EOA being absolute offset -QAK) */
- if((eof + sblock->base_addr) < stored_eof)
- HGOTO_ERROR(H5E_FILE, H5E_TRUNCATED, NULL, "truncated file: eof = %llu, sblock->base_addr = %llu, stored_eof = %llu", (unsigned long long)eof, (unsigned long long)sblock->base_addr, (unsigned long long)stored_eof)
- } /* end if */
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5F__cache_superblock_image_len() */
- /*
- * Tell the file driver how much address space has already been
- * allocated so that it knows how to allocate additional memory.
- */
- /* (Account for the stored EOA being absolute offset -NAF) */
- if(H5FD_set_eoa(lf, H5FD_MEM_SUPER, stored_eof - sblock->base_addr) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to set end-of-address marker for file")
-
- /* Read the file's superblock extension, if there is one. */
- if(H5F_addr_defined(sblock->ext_addr)) {
- H5O_loc_t ext_loc; /* "Object location" for superblock extension */
- H5O_btreek_t btreek; /* v1 B-tree 'K' value message from superblock extension */
- H5O_drvinfo_t drvinfo; /* Driver info message from superblock extension */
- size_t u; /* Local index variable */
- htri_t status; /* Status for message existing */
-
- /* Sanity check - superblock extension should only be defined for
- * superblock version >= 2.
- */
- HDassert(super_vers >= HDF5_SUPERBLOCK_VERSION_2);
+
+/*-------------------------------------------------------------------------
+ * Function: H5FS__cache_hdf_pre_serialize
+ *
+ * Purpose: The current use of this function is a cludge to repair an
+ * oversight in the conversion of the superblock code to use the
+ * version 3 cache.
+ *
+ * In the V2 metadata cache callbacks, the superblock dirver info
+ * message was updated in the flush routine. Note that this
+ * operation only applies to version 2 or later superblocks.
+ *
+ * Somehow, this functionality was lost in the conversion to use
+ * the V3 cache, causing failures with the multi file driver
+ * (and possibly the family file driver as well).
+ *
+ * Performing this operation is impossible in the current
+ * serialize routine, as the dxpl_id is not available. While
+ * I am pretty sure that this is not the correct place for this
+ * functionality, as I can see it causing problems with both
+ * journaling and possibly parallel HDF5 as well, I am placing
+ * code for the necessary update in the pre_serialize call for
+ * now for testing purposes. We will almost certainly want to
+ * change this.
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: John Mainzer
+ * 10/82/14
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5F__cache_superblock_pre_serialize(const H5F_t *f, hid_t dxpl_id,
+ void *_thing, haddr_t H5_ATTR_UNUSED addr, size_t H5_ATTR_UNUSED len,
+ size_t H5_ATTR_UNUSED compressed_len, haddr_t H5_ATTR_UNUSED *new_addr,
+ size_t H5_ATTR_UNUSED *new_len, size_t H5_ATTR_UNUSED *new_compressed_len,
+ unsigned H5_ATTR_UNUSED *flags)
+{
+ H5F_super_t *sblock = (H5F_super_t *)_thing; /* Pointer to the super block */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
- /* Check for superblock extension being located "outside" the stored
- * 'eoa' value, which can occur with the split/multi VFD.
+ /* Sanity check */
+ HDassert(f);
+ HDassert(sblock);
+ HDassert(sblock->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(sblock->cache_info.type == H5AC_SUPERBLOCK);
+ HDassert(flags);
+
+ if(sblock->super_vers >= HDF5_SUPERBLOCK_VERSION_2) {
+ /* WARNING: This code almost certainly doesn't belong here. Must
+ * discuss with Quincey where to put it. Note issues
+ * for journaling and possibly parallel.
+ *
+ * -- JRM
*/
- if(H5F_addr_gt(sblock->ext_addr, stored_eof)) {
- /* Set the 'eoa' for the object header memory type large enough
- * to give some room for a reasonably sized superblock extension.
- * (This is _rather_ a kludge -QAK)
- */
- if(H5FD_set_eoa(lf, H5FD_MEM_OHDR, (haddr_t)(sblock->ext_addr + 1024)) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to set end-of-address marker for file")
- } /* end if */
+ /* Update the driver information message in the superblock extension
+ * if appropriate.
+ */
+ if(H5F_addr_defined(sblock->ext_addr)) {
+ size_t driver_size; /* Size of driver info block (bytes)*/
+ H5O_loc_t ext_loc; /* "Object location" for superblock extension */
- /* Open the superblock extension */
- if(H5F_super_ext_open(f, sblock->ext_addr, &ext_loc) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTOPENOBJ, NULL, "unable to open file's superblock extension")
+ HDassert(sblock->super_vers >= HDF5_SUPERBLOCK_VERSION_2);
+
+ /* Open the superblock extension's object header */
+ if(H5F_super_ext_open((H5F_t *)f, sblock->ext_addr, &ext_loc) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENOBJ, FAIL, "unable to open file's superblock extension")
- /* Check for the extension having a 'driver info' message */
- if((status = H5O_msg_exists(&ext_loc, H5O_DRVINFO_ID, dxpl_id)) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "unable to read object header")
- if(status) {
/* Check for ignoring the driver info for this file */
- if(H5F_HAS_FEATURE(f, H5FD_FEAT_IGNORE_DRVRINFO)) {
- /* Indicate that the superblock should be marked dirty */
- udata->dirtied = TRUE;
- } /* end if */
- else {
- /* Retrieve the 'driver info' structure */
- if(NULL == H5O_msg_read(&ext_loc, H5O_DRVINFO_ID, &drvinfo, dxpl_id))
- HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "driver info message not present")
-
- /* Decode driver information */
- if(H5FD_sb_load(lf, drvinfo.name, drvinfo.buf) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to decode driver information")
-
- /* Reset driver info message */
- H5O_msg_reset(H5O_DRVINFO_ID, &drvinfo);
- } /* end else */
- } /* end if */
+ if(!H5F_HAS_FEATURE(f, H5FD_FEAT_IGNORE_DRVRINFO)) {
+ /* Check for driver info message */
+ H5_CHECKED_ASSIGN(driver_size, size_t, H5FD_sb_size(f->shared->lf), hsize_t);
+ if(driver_size > 0) {
+ H5O_drvinfo_t drvinfo; /* Driver info */
+ uint8_t dbuf[H5F_MAX_DRVINFOBLOCK_SIZE]; /* Driver info block encoding buffer */
- /* Read in the shared OH message information if there is any */
- if(H5SM_get_info(&ext_loc, c_plist, dxpl_id) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to read SOHM table information")
-
- /* Check for the extension having a 'v1 B-tree "K"' message */
- if((status = H5O_msg_exists(&ext_loc, H5O_BTREEK_ID, dxpl_id)) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "unable to read object header")
- if(status) {
- /* Retrieve the 'v1 B-tree "K"' structure */
- if(NULL == H5O_msg_read(&ext_loc, H5O_BTREEK_ID, &btreek, dxpl_id))
- HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "v1 B-tree 'K' info message not present")
-
- /* Set non-default v1 B-tree 'K' value info from file */
- sblock->btree_k[H5B_CHUNK_ID] = btreek.btree_k[H5B_CHUNK_ID];
- sblock->btree_k[H5B_SNODE_ID] = btreek.btree_k[H5B_SNODE_ID];
- sblock->sym_leaf_k = btreek.sym_leaf_k;
-
- /* Set non-default v1 B-tree 'K' values in the property list */
- if(H5P_set(c_plist, H5F_CRT_BTREE_RANK_NAME, btreek.btree_k) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, NULL, "unable to set rank for btree internal nodes")
- if(H5P_set(c_plist, H5F_CRT_SYM_LEAF_NAME, &btreek.sym_leaf_k) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, NULL, "unable to set rank for symbol table leaf nodes")
- } /* end if */
+ /* Sanity check */
+ HDassert(driver_size <= H5F_MAX_DRVINFOBLOCK_SIZE);
- /* Check for the extension having a 'free-space manager info' message */
- if((status = H5O_msg_exists(&ext_loc, H5O_FSINFO_ID, dxpl_id)) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "unable to check object header")
- if(status) {
- H5O_fsinfo_t fsinfo; /* Free-space manager info message from superblock extension */
-
- /* Retrieve the 'free-space manager info' structure */
- if(NULL == H5O_msg_read(&ext_loc, H5O_FSINFO_ID, &fsinfo, dxpl_id))
- HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, NULL, "unable to get free-space manager info message")
-
- if(shared->fs_strategy != fsinfo.strategy) {
- shared->fs_strategy = fsinfo.strategy;
-
- /* Set non-default strategy in the property list */
- if(H5P_set(c_plist, H5F_CRT_FILE_SPACE_STRATEGY_NAME, &fsinfo.strategy) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTSET, NULL, "unable to set file space strategy")
- } /* end if */
- if(shared->fs_threshold != fsinfo.threshold) {
- shared->fs_threshold = fsinfo.threshold;
-
- /* Set non-default threshold in the property list */
- if(H5P_set(c_plist, H5F_CRT_FREE_SPACE_THRESHOLD_NAME, &fsinfo.threshold) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTSET, NULL, "unable to set file space strategy")
- } /* end if */
-
- /* set free-space manager addresses */
- shared->fs_addr[0] = HADDR_UNDEF;
- for(u = 1; u < NELMTS(f->shared->fs_addr); u++)
- shared->fs_addr[u] = fsinfo.fs_addr[u-1];
- } /* end if */
+ /* Encode driver-specific data */
+ if(H5FD_sb_encode(f->shared->lf, drvinfo.name, dbuf) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to encode driver information")
- /* Close superblock extension */
- if(H5F_super_ext_close(f, &ext_loc, dxpl_id, FALSE) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTRELEASE, NULL, "unable to close file's superblock extension")
- } /* end if */
+ /* Write driver info information to the superblock extension */
+ drvinfo.len = driver_size;
+ drvinfo.buf = dbuf;
+ if(H5O_msg_write(&ext_loc, H5O_DRVINFO_ID, H5O_MSG_FLAG_DONTSHARE, H5O_UPDATE_TIME, &drvinfo, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_WRITEERROR, FAIL, "unable to update driver info header message")
+ } /* end if */
+ } /* end if */
- /* Set return value */
- ret_value = sblock;
+ /* Close the superblock extension object header */
+ if(H5F_super_ext_close((H5F_t *)f, &ext_loc, dxpl_id, FALSE) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "unable to close file's superblock extension")
+ } /* end if */
+ } /* end if */
done:
- /* Release the [possibly partially initialized] superblock on errors */
- if(!ret_value && sblock)
- if(H5F__super_free(sblock) < 0)
- HDONE_ERROR(H5E_FILE, H5E_CANTFREE, NULL, "unable to destroy superblock data")
-
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5F_sblock_load() */
+} /* end H5FS_cache_superblock_pre_serialize() */
/*-------------------------------------------------------------------------
- * Function: H5F_sblock_flush
+ * Function: H5F__cache_superblock_serialize
*
- * Purpose: Flushes the superblock.
+ * Purpose: Flushes a dirty object to disk.
*
- * Return: Success: SUCCEED
- * Failure: NULL
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Mike McGreevy
- * mamcgree@hdfgroup.org
- * April 8, 2009
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * July 19 2013
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5F_sblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t H5_ATTR_UNUSED addr,
- H5F_super_t *sblock)
+H5F__cache_superblock_serialize(const H5F_t *f, void *_image, size_t H5_ATTR_UNUSED len,
+ void *_thing)
{
- herr_t ret_value = SUCCEED;
+ H5F_super_t *sblock = (H5F_super_t *)_thing; /* Pointer to the object */
+ uint8_t *image = (uint8_t *)_image; /* Pointer into raw data buffer */
+ haddr_t rel_eof; /* Relative EOF for file */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
- /* check arguments */
+ /* Sanity check */
HDassert(f);
- HDassert(H5F_addr_eq(addr, 0));
+ HDassert(image);
HDassert(sblock);
-
+
/* Assert that the superblock is marked as being flushed last (and
collectively in parallel) */
/* (We'll rely on the cache to make sure it actually *is* flushed
@@ -693,301 +721,434 @@ H5F_sblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t H5_ATTR_UNUSE
HDassert(sblock->cache_info.flush_me_collectively);
#endif
- if(sblock->cache_info.is_dirty) {
- H5P_genplist_t *dxpl; /* DXPL object */
- uint8_t buf[H5F_MAX_SUPERBLOCK_SIZE + H5F_MAX_DRVINFOBLOCK_SIZE]; /* Superblock & driver info blockencoding buffer */
- uint8_t *p; /* Ptr into encoding buffer */
- haddr_t rel_eof; /* Relative EOF for file */
- size_t superblock_size; /* Size of superblock, in bytes */
- size_t driver_size; /* Size of driver info block (bytes)*/
-
- /* Encode the common portion of the file superblock for all versions */
- p = buf;
- HDmemcpy(p, H5F_SIGNATURE, (size_t)H5F_SIGNATURE_LEN);
- p += H5F_SIGNATURE_LEN;
- *p++ = (uint8_t)sblock->super_vers;
-
- /* Check for older version of superblock format */
- if(sblock->super_vers < HDF5_SUPERBLOCK_VERSION_2) {
- *p++ = (uint8_t)HDF5_FREESPACE_VERSION; /* (hard-wired) */
- *p++ = (uint8_t)HDF5_OBJECTDIR_VERSION; /* (hard-wired) */
- *p++ = 0; /* reserved*/
-
- *p++ = (uint8_t)HDF5_SHAREDHEADER_VERSION; /* (hard-wired) */
- *p++ = (uint8_t)H5F_SIZEOF_ADDR(f);
- *p++ = (uint8_t)H5F_SIZEOF_SIZE(f);
- *p++ = 0; /* reserved */
-
- UINT16ENCODE(p, sblock->sym_leaf_k);
- UINT16ENCODE(p, sblock->btree_k[H5B_SNODE_ID]);
- UINT32ENCODE(p, (uint32_t)sblock->status_flags);
-
- /*
- * Versions of the superblock >0 have the indexed storage B-tree
- * internal 'K' value stored
- */
- if(sblock->super_vers > HDF5_SUPERBLOCK_VERSION_DEF) {
- UINT16ENCODE(p, sblock->btree_k[H5B_CHUNK_ID]);
- *p++ = 0; /*reserved */
- *p++ = 0; /*reserved */
- } /* end if */
-
- /* Encode the base address */
- H5F_addr_encode(f, &p, sblock->base_addr);
-
- /* Encode the address of global free-space index */
- H5F_addr_encode(f, &p, sblock->ext_addr);
-
- /* Encode the end-of-file address. Note that at this point in time,
- * the EOF value itself may not be reflective of the file's size, as
- * we will eventually truncate the file to match the EOA value. As
- * such, use the EOA value in its place, knowing that the current EOF
- * value will ultimately match it. */
- if ((rel_eof = H5FD_get_eoa(f->shared->lf, H5FD_MEM_SUPER)) == HADDR_UNDEF)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "driver get_eoa request failed")
- H5F_addr_encode(f, &p, (rel_eof + sblock->base_addr));
-
- /* Encode the driver informaton block address */
- H5F_addr_encode(f, &p, sblock->driver_addr);
-
- /* Encode the root group object entry, including the cached stab info */
- if(H5G_ent_encode(f, &p, sblock->root_ent) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTENCODE, FAIL, "can't encode root group symbol table entry")
-
- /* Encode the driver information block. */
- H5_CHECKED_ASSIGN(driver_size, size_t, H5FD_sb_size(f->shared->lf), hsize_t);
-
- /* Checking whether driver block address is defined here is to handle backward
- * compatibility. If the file was created with v1.6 library or earlier and no
- * driver info block was written in the superblock, we don't write it either even
- * though there's some driver info. Otherwise, the driver block extended will
- * overwrite the (meta)data right after the superblock. This situation happens to
- * the family driver particularly. SLU - 2009/3/24
- */
- if(driver_size > 0 && H5F_addr_defined(sblock->driver_addr)) {
- char driver_name[9]; /* Name of driver, for driver info block */
- uint8_t *dbuf = p; /* Pointer to beginning of driver info */
-
- /* Encode the driver information block */
- *p++ = HDF5_DRIVERINFO_VERSION_0; /* Version */
- *p++ = 0; /* reserved */
- *p++ = 0; /* reserved */
- *p++ = 0; /* reserved */
-
- /* Driver info size, excluding header */
- UINT32ENCODE(p, driver_size);
-
- /* Encode driver-specific data */
- if(H5FD_sb_encode(f->shared->lf, driver_name, dbuf + H5F_DRVINFOBLOCK_HDR_SIZE) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to encode driver information")
-
- /* Store driver name (set in 'H5FD_sb_encode' call above) */
- HDmemcpy(p, driver_name, (size_t)8);
-
- /* Advance buffer pointer past name & variable-sized portion of driver info */
- /* (for later use in computing the superblock size) */
- p += 8 + driver_size;
- } /* end if */
- } /* end if */
- else {
- uint32_t chksum; /* Checksum temporary variable */
- H5O_loc_t *root_oloc; /* Pointer to root group's object location */
-
- /* Size of file addresses & offsets, and status flags */
- *p++ = (uint8_t)H5F_SIZEOF_ADDR(f);
- *p++ = (uint8_t)H5F_SIZEOF_SIZE(f);
- *p++ = sblock->status_flags;
+ /* Encode the common portion of the file superblock for all versions */
+ HDmemcpy(image, H5F_SIGNATURE, (size_t)H5F_SIGNATURE_LEN);
+ image += H5F_SIGNATURE_LEN;
+ *image++ = (uint8_t)sblock->super_vers;
- /* Encode the base address */
- H5F_addr_encode(f, &p, sblock->base_addr);
-
- /* Encode the address of the superblock extension */
- H5F_addr_encode(f, &p, sblock->ext_addr);
-
- /* At this point in time, the EOF value itself may
- * not be reflective of the file's size, since we'll eventually
- * truncate it to match the EOA value. As such, use the EOA value
- * in its place, knowing that the current EOF value will
- * ultimately match it. */
- if ((rel_eof = H5FD_get_eoa(f->shared->lf, H5FD_MEM_SUPER)) == HADDR_UNDEF)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "driver get_eoa request failed")
- H5F_addr_encode(f, &p, (rel_eof + sblock->base_addr));
+ /* Check for older version of superblock format */
+ if(sblock->super_vers < HDF5_SUPERBLOCK_VERSION_2) {
+ *image++ = (uint8_t)HDF5_FREESPACE_VERSION; /* (hard-wired) */
+ *image++ = (uint8_t)HDF5_OBJECTDIR_VERSION; /* (hard-wired) */
+ *image++ = 0; /* reserved*/
- /* Retrieve information for root group */
- if(NULL == (root_oloc = H5G_oloc(f->shared->root_grp)))
- HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to retrieve root group information")
+ *image++ = (uint8_t)HDF5_SHAREDHEADER_VERSION; /* (hard-wired) */
+ *image++ = sblock->sizeof_addr;
+ *image++ = sblock->sizeof_size;
+ *image++ = 0; /* reserved */
- /* Encode address of root group's object header */
- H5F_addr_encode(f, &p, root_oloc->addr);
+ UINT16ENCODE(image, sblock->sym_leaf_k);
+ UINT16ENCODE(image, sblock->btree_k[H5B_SNODE_ID]);
+ UINT32ENCODE(image, (uint32_t)sblock->status_flags);
- /* Compute superblock checksum */
- chksum = H5_checksum_metadata(buf, ((size_t)H5F_SUPERBLOCK_SIZE(sblock->super_vers, f) - H5F_SIZEOF_CHKSUM), 0);
+ /*
+ * Versions of the superblock >0 have the indexed storage B-tree
+ * internal 'K' value stored
+ */
+ if(sblock->super_vers > HDF5_SUPERBLOCK_VERSION_DEF) {
+ UINT16ENCODE(image, sblock->btree_k[H5B_CHUNK_ID]);
+ *image++ = 0; /*reserved */
+ *image++ = 0; /*reserved */
+ } /* end if */
- /* Superblock checksum */
- UINT32ENCODE(p, chksum);
+ /* Encode the base address */
+ H5F_addr_encode(f, &image, sblock->base_addr);
- /* Sanity check */
- HDassert((size_t)(p - buf) == (size_t)H5F_SUPERBLOCK_SIZE(sblock->super_vers, f));
- } /* end else */
+ /* Encode the address of global free-space index */
+ H5F_addr_encode(f, &image, sblock->ext_addr);
- /* Retrieve the total size of the superblock info */
- H5_CHECKED_ASSIGN(superblock_size, size_t, (p - buf), ptrdiff_t);
+ /* Encode the end-of-file address. Note that at this point in time,
+ * the EOF value itself may not be reflective of the file's size, as
+ * we will eventually truncate the file to match the EOA value. As
+ * such, use the EOA value in its place, knowing that the current EOF
+ * value will ultimately match it. */
+ if ((rel_eof = H5FD_get_eoa(f->shared->lf, H5FD_MEM_SUPER)) == HADDR_UNDEF)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "driver get_eoa request failed")
+ H5F_addr_encode(f, &image, (rel_eof + sblock->base_addr));
- /* Double check we didn't overrun the block (unlikely) */
- HDassert(superblock_size <= sizeof(buf));
+ /* Encode the driver informaton block address */
+ H5F_addr_encode(f, &image, sblock->driver_addr);
- /* Get the DXPL plist object for DXPL ID */
- if(NULL == (dxpl = (H5P_genplist_t *)H5I_object(dxpl_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get property list")
+ /* Encode the root group object entry, including the cached stab info */
+ if(H5G_ent_encode(f, &image, sblock->root_ent) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTENCODE, FAIL, "can't encode root group symbol table entry")
- /* Write superblock */
- /* (always at relative address 0) */
- if(H5FD_write(f->shared->lf, dxpl, H5FD_MEM_SUPER, (haddr_t)0, superblock_size, buf) < 0)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to write superblock")
+ /* NOTE: Driver info block is handled separately */
- /* Check for newer version of superblock format & superblock extension */
- if(sblock->super_vers >= HDF5_SUPERBLOCK_VERSION_2 && H5F_addr_defined(sblock->ext_addr)) {
- H5O_loc_t ext_loc; /* "Object location" for superblock extension */
+ } /* end if */
+ else { /* sblock->super_vers >= HDF5_SUPERBLOCK_VERSION_2 */
+ uint32_t chksum; /* Checksum temporary variable */
+ H5O_loc_t *root_oloc; /* Pointer to root group's object location */
- /* Open the superblock extension's object header */
- if(H5F_super_ext_open(f, sblock->ext_addr, &ext_loc) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTOPENOBJ, FAIL, "unable to open file's superblock extension")
+ /* Size of file addresses & offsets, and status flags */
+ *image++ = sblock->sizeof_addr;
+ *image++ = sblock->sizeof_size;
+ *image++ = sblock->status_flags;
- /* Check for ignoring the driver info for this file */
- if(!H5F_HAS_FEATURE(f, H5FD_FEAT_IGNORE_DRVRINFO)) {
- /* Check for driver info message */
- H5_CHECKED_ASSIGN(driver_size, size_t, H5FD_sb_size(f->shared->lf), hsize_t);
- if(driver_size > 0) {
- H5O_drvinfo_t drvinfo; /* Driver info */
- uint8_t dbuf[H5F_MAX_DRVINFOBLOCK_SIZE]; /* Driver info block encoding buffer */
+ /* Encode the base address */
+ H5F_addr_encode(f, &image, sblock->base_addr);
- /* Sanity check */
- HDassert(driver_size <= H5F_MAX_DRVINFOBLOCK_SIZE);
+ /* Encode the address of the superblock extension */
+ H5F_addr_encode(f, &image, sblock->ext_addr);
- /* Encode driver-specific data */
- if(H5FD_sb_encode(f->shared->lf, drvinfo.name, dbuf) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to encode driver information")
+ /* At this point in time, the EOF value itself may
+ * not be reflective of the file's size, since we'll eventually
+ * truncate it to match the EOA value. As such, use the EOA value
+ * in its place, knowing that the current EOF value will
+ * ultimately match it. */
+ if ((rel_eof = H5FD_get_eoa(f->shared->lf, H5FD_MEM_SUPER)) == HADDR_UNDEF)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "driver get_eoa request failed")
+ H5F_addr_encode(f, &image, (rel_eof + sblock->base_addr));
- /* Write driver info information to the superblock extension */
- drvinfo.len = driver_size;
- drvinfo.buf = dbuf;
- if(H5O_msg_write(&ext_loc, H5O_DRVINFO_ID, H5O_MSG_FLAG_DONTSHARE, H5O_UPDATE_TIME, &drvinfo, dxpl_id) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_WRITEERROR, FAIL, "unable to update driver info header message")
+ /* Retrieve information for root group */
+ if(NULL == (root_oloc = H5G_oloc(f->shared->root_grp)))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to retrieve root group information")
- } /* end if */
+ /* Encode address of root group's object header */
+ H5F_addr_encode(f, &image, root_oloc->addr);
- } /* end if */
+ /* Compute superblock checksum */
+ chksum = H5_checksum_metadata(_image, ((size_t)H5F_SUPERBLOCK_SIZE(sblock) - H5F_SIZEOF_CHKSUM), 0);
- /* Close the superblock extension object header */
- if(H5F_super_ext_close(f, &ext_loc, dxpl_id, FALSE) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "unable to close file's superblock extension")
- } /* end if */
+ /* Superblock checksum */
+ UINT32ENCODE(image, chksum);
- /* Reset the dirty flag. */
- sblock->cache_info.is_dirty = FALSE;
- } /* end if */
+ /* Sanity check */
+ HDassert((size_t)(image - (uint8_t *)_image) == (size_t)H5F_SUPERBLOCK_SIZE(sblock));
+ } /* end else */
- if(destroy)
- if(H5F_sblock_dest(f, sblock) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CLOSEERROR, FAIL, "can't close superblock")
+ /* Sanity check */
+ HDassert((size_t)(image - (uint8_t *)_image) <= len);
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5F_sblock_flush() */
+} /* H5F__cache_superblock_serialize() */
/*-------------------------------------------------------------------------
- * Function: H5F_sblock_dest
+ * Function: H5F__cache_superblock_free_icr
*
- * Purpose: Frees memory used by the superblock.
+ * Purpose: Destroy/release an "in core representation" of a data
+ * structure
*
- * Return: Non-negative on success/Negative on failure
+ * Note: The metadata cache sets the object's cache_info.magic to
+ * H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC before calling a free_icr
+ * callback (checked in assert).
+ *
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Mike McGreevy
- * April 8, 2009
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * July 20, 2013
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5F_sblock_dest(H5F_t H5_ATTR_UNUSED *f, H5F_super_t* sblock)
+H5F__cache_superblock_free_icr(void *_thing)
{
+ H5F_super_t *sblock = (H5F_super_t *)_thing; /* Pointer to the object */
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
/* Sanity check */
HDassert(sblock);
+ HDassert(sblock->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC);
+ HDassert(sblock->cache_info.type == H5AC_SUPERBLOCK);
- /* Free superblock */
+ /* Destroy superblock */
if(H5F__super_free(sblock) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTFREE, FAIL, "unable to destroy superblock")
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free superblock")
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5F_sblock_dest() */
+} /* H5F__cache_superblock_free_icr() */
/*-------------------------------------------------------------------------
- * Function: H5F_sblock_clear
+ * Function: H5F__cache_drvrinfo_get_load_size
*
- * Purpose: Mark the superblock as no longer being dirty.
+ * Purpose: Compute the size of the data structure on disk.
*
* Return: Non-negative on success/Negative on failure
*
- * Programmer: Mike McGreevy
- * April 8, 2009
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * July 20, 2013
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5F_sblock_clear(H5F_t *f, H5F_super_t *sblock, hbool_t destroy)
+H5F__cache_drvrinfo_get_load_size(const void *_image, void *_udata, size_t *image_len, size_t *actual_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ H5F_drvrinfo_cache_ud_t *udata = (H5F_drvrinfo_cache_ud_t *)_udata; /* User data */
+ unsigned drv_vers; /* Version of driver info block */
+ size_t drvinfo_len; /* Length of encoded buffer */
+ htri_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
- /*
- * Check arguments.
- */
- HDassert(sblock);
+ /* Check arguments */
+ HDassert(image_len);
+
+ if(image == NULL) {
+ HDassert(actual_len == NULL);
+
+ /* Set the initial image length size */
+ *image_len = H5F_DRVINFOBLOCK_HDR_SIZE; /* Fixed size portion of driver info block */
+
+ } else { /* compute actual_len */
+
+ HDassert(udata);
+ HDassert(udata->f);
+ HDassert(actual_len);
+ HDassert(*actual_len == *image_len);
+
+ /* Version number */
+ drv_vers = *image++;
+ if(drv_vers != HDF5_DRIVERINFO_VERSION_0)
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "bad driver information block version number")
+
+ image += 3; /* reserved bytes */
- /* Reset the dirty flag. */
- sblock->cache_info.is_dirty = FALSE;
+ /* Driver info size */
+ UINT32DECODE(image, drvinfo_len);
- if(destroy)
- if(H5F_sblock_dest(f, sblock) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTFREE, FAIL, "unable to delete superblock")
+ /* Handle metadata cache retry for variable-sized portion of the driver info block */
+ if(*image_len != (H5F_DRVINFOBLOCK_HDR_SIZE + drvinfo_len)) {
+ /* Sanity check */
+ HDassert(*image_len == H5F_DRVINFOBLOCK_HDR_SIZE);
+
+ /* extend the eoa if required so that we can read the complete driver info block */
+ {
+ haddr_t eoa;
+ haddr_t min_eoa;
+
+ /* get current eoa... */
+ if ((eoa = H5FD_get_eoa(udata->f->shared->lf, H5FD_MEM_SUPER)) == HADDR_UNDEF)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "driver get_eoa request failed")
+
+ /* ... if it is too small, extend it. */
+ min_eoa = udata->driver_addr + H5F_DRVINFOBLOCK_HDR_SIZE + drvinfo_len;
+
+ if ( H5F_addr_gt(min_eoa, eoa) )
+ if(H5FD_set_eoa(udata->f->shared->lf, H5FD_MEM_SUPER, min_eoa) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, \
+ "set end of space allocation request failed")
+ }
+ *actual_len = H5F_DRVINFOBLOCK_HDR_SIZE + drvinfo_len;
+ }
+ } /* compute actual_len */
done:
+
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5F_sblock_clear() */
+} /* end H5F__cache_drvrinfo_get_load_size() */
/*-------------------------------------------------------------------------
- * Function: H5F_sblock_size
+ * Function: H5F__cache_drvrinfo_deserialize
*
- * Purpose: Returns the size of the superblock encoded on disk.
+ * Purpose: Loads an object from the disk.
+ *
+ * Return: Success: Pointer to a new B-tree.
+ * Failure: NULL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * July 20 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+static void *
+H5F__cache_drvrinfo_deserialize(const void *_image, size_t len, void *_udata,
+ hbool_t H5_ATTR_UNUSED *dirty)
+{
+ H5O_drvinfo_t *drvinfo = NULL; /* Driver info */
+ H5F_drvrinfo_cache_ud_t *udata = (H5F_drvrinfo_cache_ud_t *)_udata; /* User data */
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ char drv_name[9]; /* Name of driver */
+ unsigned drv_vers; /* Version of driver info block */
+ H5O_drvinfo_t *ret_value; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity check */
+ HDassert(image);
+ HDassert(len >= H5F_DRVINFOBLOCK_HDR_SIZE);
+ HDassert(udata);
+ HDassert(udata->f);
+
+ /* Allocate space for the driver info */
+ if(NULL == (drvinfo = (H5O_drvinfo_t *)H5MM_calloc(sizeof(H5O_drvinfo_t))))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, NULL, "memory allocation failed for driver info message")
+
+ /* Version number */
+ drv_vers = *image++;
+ if(drv_vers != HDF5_DRIVERINFO_VERSION_0)
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad driver information block version number")
+
+ image += 3; /* reserved bytes */
+
+ /* Driver info size */
+ UINT32DECODE(image, drvinfo->len);
+
+ /* Driver name and/or version */
+ HDstrncpy(drv_name, (const char *)image, (size_t)8);
+ drv_name[8] = '\0';
+ image += 8; /* advance past name/version */
+
+ HDassert(len == (H5F_DRVINFOBLOCK_HDR_SIZE + drvinfo->len));
+
+ /* Validate and decode driver information */
+ if(H5FD_sb_load(udata->f->shared->lf, drv_name, image) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTDECODE, NULL, "unable to decode driver information")
+
+ /* Sanity check */
+ HDassert((size_t)(image - (const uint8_t *)_image) <= len);
+
+ /* Set return value */
+ ret_value = drvinfo;
+
+done:
+ /* Release the [possibly partially initialized] driver info message on error */
+ if(!ret_value && drvinfo)
+ H5MM_xfree(drvinfo);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F__cache_drvrinfo_deserialize() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F__cache_drvrinfo_image_len
+ *
+ * Purpose: Compute the size of the data structure on disk.
*
* Return: Non-negative on success/Negative on failure
*
- * Programmer: Mike McGreevy
- * April 8, 2009
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * July 20, 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5F__cache_drvrinfo_image_len(const void *_thing, size_t *image_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr)
+{
+ const H5O_drvinfo_t *drvinfo = (const H5O_drvinfo_t *)_thing; /* Pointer to the object */
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Check arguments */
+ HDassert(drvinfo);
+ HDassert(drvinfo->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(drvinfo->cache_info.type == H5AC_DRVRINFO);
+ HDassert(image_len);
+ HDassert(compressed_ptr);
+
+ /* Set the image length size */
+ *image_len = (size_t)(H5F_DRVINFOBLOCK_HDR_SIZE + /* Fixed-size portion of driver info block */
+ drvinfo->len); /* Variable-size portion of driver info block */
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5F__cache_drvrinfo_image_len() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F__cache_drvrinfo_serialize
+ *
+ * Purpose: Flushes a dirty object to disk.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * July 20 2013
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5F_sblock_size(const H5F_t *f, const H5F_super_t *sblock, size_t *size_ptr)
+H5F__cache_drvrinfo_serialize(const H5F_t *f, void *_image, size_t len,
+ void *_thing)
{
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ H5O_drvinfo_t *drvinfo = (H5O_drvinfo_t *)_thing; /* Pointer to the object */
+ uint8_t *image = (uint8_t *)_image; /* Pointer into raw data buffer */
+ uint8_t *dbuf; /* Pointer to beginning of driver info */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
/* check arguments */
HDassert(f);
- HDassert(sblock);
- HDassert(size_ptr);
+ HDassert(image);
+ HDassert(drvinfo);
+ HDassert(drvinfo->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(drvinfo->cache_info.type == H5AC_DRVRINFO);
+ HDassert(len == (size_t)(H5F_DRVINFOBLOCK_HDR_SIZE + drvinfo->len));
+
+ /* Save pointer to beginning of driver info */
+ dbuf = image;
+
+ /* Encode the driver information block */
+ *image++ = HDF5_DRIVERINFO_VERSION_0; /* Version */
+ *image++ = 0; /* reserved */
+ *image++ = 0; /* reserved */
+ *image++ = 0; /* reserved */
+
+ /* Driver info size, excluding header */
+ UINT32ENCODE(image, drvinfo->len);
+
+ /* Encode driver-specific data */
+ if(H5FD_sb_encode(f->shared->lf, (char *)image, dbuf + H5F_DRVINFOBLOCK_HDR_SIZE) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to encode driver information")
+
+ /* Advance buffer pointer past name & variable-sized portion of driver info */
+ image += 8 + drvinfo->len;
+
+ /* Sanity check */
+ HDassert((size_t)(image - (uint8_t *)_image) <= len);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5F__cache_drvrinfo_serialize() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F__cache_drvrinfo_free_icr
+ *
+ * Purpose: Destroy/release an "in core representation" of a data
+ * structure
+ *
+ * Note: The metadata cache sets the object's cache_info.magic to
+ * H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC before calling a free_icr
+ * callback (checked in assert).
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * July 20, 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5F__cache_drvrinfo_free_icr(void *_thing)
+{
+ H5O_drvinfo_t *drvinfo = (H5O_drvinfo_t *)_thing; /* Pointer to the object */
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Check arguments */
+ HDassert(drvinfo);
+ HDassert(drvinfo->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC);
+ HDassert(drvinfo->cache_info.type == H5AC_DRVRINFO);
- /* Set size value */
- *size_ptr = (size_t)H5F_SUPERBLOCK_SIZE(sblock->super_vers, f);
+ /* Destroy driver info message */
+ H5MM_xfree(drvinfo);
FUNC_LEAVE_NOAPI(SUCCEED)
-} /* end H5F_sblock_size() */
+} /* H5F__cache_drvrinfo_free_icr() */
diff --git a/src/H5Gcache.c b/src/H5Gcache.c
index bedceb6..4ab5217 100644
--- a/src/H5Gcache.c
+++ b/src/H5Gcache.c
@@ -46,7 +46,6 @@
/****************/
#define H5G_NODE_VERS 1 /* Symbol table node version number */
-#define H5G_NODE_BUF_SIZE 512 /* Size of stack buffer for serialized nodes */
/******************/
@@ -64,12 +63,16 @@
/********************/
/* Metadata cache (H5AC) callbacks */
-static H5G_node_t *H5G_node_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata);
-static herr_t H5G_node_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr,
- H5G_node_t *sym, unsigned *flags_ptr);
-static herr_t H5G_node_dest(H5F_t *f, H5G_node_t *sym);
-static herr_t H5G_node_clear(H5F_t *f, H5G_node_t *sym, hbool_t destroy);
-static herr_t H5G_node_size(const H5F_t *f, const H5G_node_t *sym, size_t *size_ptr);
+static herr_t H5G__cache_node_get_load_size(const void *image, void *udata,
+ size_t *image_len, size_t *actual_len,
+ hbool_t *compressed_ptr, size_t *compressed_image_len_ptr);
+static void *H5G__cache_node_deserialize(const void *image, size_t len,
+ void *udata, hbool_t *dirty);
+static herr_t H5G__cache_node_image_len(const void *thing, size_t *image_len,
+ hbool_t *compressed_ptr, size_t *compressed_image_len_ptr);
+static herr_t H5G__cache_node_serialize(const H5F_t *f, void *image,
+ size_t len, void *thing);
+static herr_t H5G__cache_node_free_icr(void *thing);
/*********************/
@@ -88,13 +91,20 @@ static herr_t H5G_node_size(const H5F_t *f, const H5G_node_t *sym, size_t *size_
/* Symbol table nodes inherit cache-like properties from H5AC */
const H5AC_class_t H5AC_SNODE[1] = {{
- H5AC_SNODE_ID,
- (H5AC_load_func_t)H5G_node_load,
- (H5AC_flush_func_t)H5G_node_flush,
- (H5AC_dest_func_t)H5G_node_dest,
- (H5AC_clear_func_t)H5G_node_clear,
- (H5AC_notify_func_t)NULL,
- (H5AC_size_func_t)H5G_node_size,
+ H5AC_SNODE_ID, /* Metadata client ID */
+ "Symbol table node", /* Metadata client name (for debugging) */
+ H5FD_MEM_BTREE, /* File space memory type for client */
+ H5AC__CLASS_NO_FLAGS_SET, /* Client class behavior flags */
+ H5G__cache_node_get_load_size, /* 'get_load_size' callback */
+ NULL, /* 'verify_chksum' callback */
+ H5G__cache_node_deserialize, /* 'deserialize' callback */
+ H5G__cache_node_image_len, /* 'image_len' callback */
+ NULL, /* 'pre_serialize' callback */
+ H5G__cache_node_serialize, /* 'serialize' callback */
+ NULL, /* 'notify' callback */
+ H5G__cache_node_free_icr, /* 'free_icr' callback */
+ NULL, /* 'clear' callback */
+ NULL, /* 'fsf_size' callback */
}};
@@ -106,42 +116,89 @@ H5FL_SEQ_EXTERN(H5G_entry_t);
/*-------------------------------------------------------------------------
- * Function: H5G_node_load
+ * Function: H5G__cache_node_get_load_size()
*
- * Purpose: Loads a symbol table node from the file.
+ * Purpose: Determine the size of the on disk image of the node, and
+ * return this value in *image_len.
*
- * Return: Success: Ptr to the new table.
+ * Note that this computation requires access to the file pointer,
+ * which is not provided in the parameter list for this callback.
+ * Finesse this issue by passing in the file pointer twice to the
+ * H5AC_protect() call -- once as the file pointer proper, and
+ * again as the user data.
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
*
- * Failure: NULL
- *
- * Programmer: Robb Matzke
- * matzke@llnl.gov
- * Jun 23 1997
+ * Programmer: John Mainzer
+ * 7/21/14
*
*-------------------------------------------------------------------------
*/
-static H5G_node_t *
-H5G_node_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata)
+static herr_t
+H5G__cache_node_get_load_size(const void *_image, void *_udata, size_t *image_len, size_t *actual_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr)
{
- H5G_node_t *sym = NULL;
- H5WB_t *wb = NULL; /* Wrapped buffer for node data */
- uint8_t node_buf[H5G_NODE_BUF_SIZE]; /* Buffer for node */
- uint8_t *node; /* Pointer to node buffer */
- const uint8_t *p;
- H5G_node_t *ret_value; /*for error handling */
-
- FUNC_ENTER_NOAPI_NOINIT
-
- /*
- * Check arguments.
- */
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer to image to deserialize */
+ H5F_t *f = (H5F_t *)_udata; /* User data for callback */
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Sanity checks */
HDassert(f);
- HDassert(H5F_addr_defined(addr));
- HDassert(udata);
+ HDassert(image_len);
+
+ if(image == NULL) {
+ /* report image length */
+ *image_len = (size_t)(H5G_NODE_SIZE(f));
+ } else {
+ HDassert(actual_len);
+ HDassert(*image_len == *actual_len);
+ }
- /*
- * Initialize variables.
- */
+ /* Nothing to do for non-NULL image : no need to compute actual_len */
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5G__cache_node_get_load_size() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G__cache_node_deserialize
+ *
+ * Purpose: Given a buffer containing the on disk image of a symbol table
+ * node, allocate an instance of H5G_node_t, load the contence of the
+ * image into it, and return a pointer to the instance.
+ *
+ * Note that deserializing the image requires access to the file
+ * pointer, which is not included in the parameter list for this
+ * callback. Finesse this issue by passing in the file pointer
+ * twice to the H5AC_protect() call -- once as the file pointer
+ * proper, and again as the user data
+ *
+ * Return: Success: Pointer to in core representation
+ * Failure: NULL
+ *
+ * Programmer: John Mainzer
+ * 6/21/14
+ *
+ *-------------------------------------------------------------------------
+ */
+static void *
+H5G__cache_node_deserialize(const void *_image, size_t len, void *_udata,
+ hbool_t H5_ATTR_UNUSED *dirty)
+{
+ H5F_t *f = (H5F_t *)_udata; /* User data for callback */
+ H5G_node_t *sym = NULL; /* Symbol table node created */
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer to image to deserialize */
+ void * ret_value; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(image);
+ HDassert(len > 0);
+ HDassert(f);
+ HDassert(dirty);
/* Allocate symbol table data structures */
if(NULL == (sym = H5FL_CALLOC(H5G_node_t)))
@@ -150,262 +207,175 @@ H5G_node_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata)
if(NULL == (sym->entry = H5FL_SEQ_CALLOC(H5G_entry_t, (size_t)(2 * H5F_SYM_LEAF_K(f)))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
- /* Wrap the local buffer for serialized node info */
- if(NULL == (wb = H5WB_wrap(node_buf, sizeof(node_buf))))
- HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "can't wrap buffer")
-
- /* Get a pointer to a buffer that's large enough for node */
- if(NULL == (node = (uint8_t *)H5WB_actual(wb, sym->node_size)))
- HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, NULL, "can't get actual buffer")
-
- /* Read the serialized symbol table node. */
- if(H5F_block_read(f, H5FD_MEM_BTREE, addr, sym->node_size, dxpl_id, node) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_READERROR, NULL, "unable to read symbol table node")
-
- /* Get temporary pointer to serialized node */
- p = node;
-
/* magic */
- if(HDmemcmp(p, H5G_NODE_MAGIC, (size_t)H5_SIZEOF_MAGIC))
- HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, NULL, "bad symbol table node signature")
- p += H5_SIZEOF_MAGIC;
+ if(HDmemcmp(image, H5G_NODE_MAGIC, (size_t)H5_SIZEOF_MAGIC))
+ HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, NULL, "bad symbol table node signature")
+ image += H5_SIZEOF_MAGIC;
/* version */
- if(H5G_NODE_VERS != *p++)
- HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, NULL, "bad symbol table node version")
+ if(H5G_NODE_VERS != *image++)
+ HGOTO_ERROR(H5E_SYM, H5E_VERSION, NULL, "bad symbol table node version")
/* reserved */
- p++;
+ image++;
/* number of symbols */
- UINT16DECODE(p, sym->nsyms);
+ UINT16DECODE(image, sym->nsyms);
/* entries */
- if(H5G__ent_decode_vec(f, &p, sym->entry, sym->nsyms) < 0)
+ if(H5G__ent_decode_vec(f, &image, sym->entry, sym->nsyms) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, NULL, "unable to decode symbol table entries")
/* Set return value */
ret_value = sym;
done:
- /* Release resources */
- if(wb && H5WB_unwrap(wb) < 0)
- HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, NULL, "can't close wrapped buffer")
if(!ret_value)
if(sym && H5G__node_free(sym) < 0)
HDONE_ERROR(H5E_SYM, H5E_CANTFREE, NULL, "unable to destroy symbol table node")
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5G_node_load() */
+} /* end H5G__cache_node_deserialize() */
/*-------------------------------------------------------------------------
- * Function: H5G_node_flush
+ * Function: H5G__cache_node_image_len
*
- * Purpose: Flush a symbol table node to disk.
+ * Purpose: Compute the size of the data structure on disk and return
+ * it in *image_len.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Success: SUCCEED
+ * Failure: FAIL
*
- * Programmer: Robb Matzke
- * matzke@llnl.gov
- * Jun 23 1997
+ * Programmer: John Mainzer
+ * 6/21/14
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5G_node_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5G_node_t *sym, unsigned H5_ATTR_UNUSED * flags_ptr)
+H5G__cache_node_image_len(const void *_thing, size_t *image_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr)
{
- H5WB_t *wb = NULL; /* Wrapped buffer for node data */
- uint8_t node_buf[H5G_NODE_BUF_SIZE]; /* Buffer for node */
- herr_t ret_value = SUCCEED; /* Return value */
+ const H5G_node_t *sym = (const H5G_node_t *)_thing; /* Pointer to object */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC_NOERR
- /*
- * Check arguments.
- */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
+ /* Sanity checks */
HDassert(sym);
+ HDassert(sym->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(sym->cache_info.type == H5AC_SNODE);
+ HDassert(image_len);
- /*
- * Write the symbol node to disk.
- */
- if(sym->cache_info.is_dirty) {
- uint8_t *node; /* Pointer to node buffer */
- uint8_t *p; /* Pointer into raw data buffer */
-
- /* Wrap the local buffer for serialized node info */
- if(NULL == (wb = H5WB_wrap(node_buf, sizeof(node_buf))))
- HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't wrap buffer")
-
- /* Get a pointer to a buffer that's large enough for node */
- if(NULL == (node = (uint8_t *)H5WB_actual(wb, sym->node_size)))
- HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't get actual buffer")
-
- /* Get temporary pointer to serialized symbol table node */
- p = node;
-
- /* magic number */
- HDmemcpy(p, H5G_NODE_MAGIC, (size_t)H5_SIZEOF_MAGIC);
- p += H5_SIZEOF_MAGIC;
-
- /* version number */
- *p++ = H5G_NODE_VERS;
-
- /* reserved */
- *p++ = 0;
-
- /* number of symbols */
- UINT16ENCODE(p, sym->nsyms);
-
- /* entries */
- if(H5G__ent_encode_vec(f, &p, sym->entry, sym->nsyms) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTENCODE, FAIL, "can't serialize")
- HDmemset(p, 0, sym->node_size - (size_t)(p - node));
-
- /* Write the serialized symbol table node. */
- if(H5F_block_write(f, H5FD_MEM_BTREE, addr, sym->node_size, dxpl_id, node) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_WRITEERROR, FAIL, "unable to write symbol table node to the file")
+ *image_len = sym->node_size;
- /* Reset the node's dirty flag */
- sym->cache_info.is_dirty = FALSE;
- } /* end if */
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5G__cache_node_image_len() */
- /*
- * Destroy the symbol node? This might happen if the node is being
- * preempted from the cache.
- */
- if(destroy)
- if(H5G_node_dest(f, sym) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to destroy symbol table node")
-done:
- /* Release resources */
- if(wb && H5WB_unwrap(wb) < 0)
- HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "can't close wrapped buffer")
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5G_node_flush() */
+/*************************************/
+/* no H5G__cache_node_pre_serialize() */
+/*************************************/
/*-------------------------------------------------------------------------
- * Function: H5G_node_dest
+ * Function: H5G__cache_node_serialize
*
- * Purpose: Destroy a symbol table node in memory.
+ * Purpose: Given a correctly sized buffer and an instace of H5G_node_t,
+ * serialize the contents of the instance of H5G_node_t, and write
+ * this data into the supplied buffer. This buffer will be written
+ * to disk.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Success: SUCCEED
+ * Failure: FAIL
*
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Jan 15 2003
+ * Programmer: John Mainzer
+ * 7/21/14
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5G_node_dest(H5F_t *f, H5G_node_t *sym)
+H5G__cache_node_serialize(const H5F_t *f, void *_image, size_t len,
+ void *_thing)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ H5G_node_t *sym = (H5G_node_t *)_thing; /* Pointer to object */
+ uint8_t *image = (uint8_t *)_image; /* Pointer into raw data buffer */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
- /*
- * Check arguments.
- */
+ /* Sanity checks */
HDassert(f);
+ HDassert(image);
HDassert(sym);
+ HDassert(sym->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(sym->cache_info.type == H5AC_SNODE);
+ HDassert(len == sym->node_size);
- /* Verify that node is clean */
- HDassert(sym->cache_info.is_dirty == FALSE);
+ /* magic number */
+ HDmemcpy(image, H5G_NODE_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ image += H5_SIZEOF_MAGIC;
- /* If we're going to free the space on disk, the address must be valid */
- HDassert(!sym->cache_info.free_file_space_on_destroy || H5F_addr_defined(sym->cache_info.addr));
+ /* version number */
+ *image++ = H5G_NODE_VERS;
- /* Check for freeing file space for symbol table node */
- if(sym->cache_info.free_file_space_on_destroy) {
- /* Release the space on disk */
- /* (XXX: Nasty usage of internal DXPL value! -QAK) */
- if(H5MF_xfree(f, H5FD_MEM_BTREE, H5AC_dxpl_id, sym->cache_info.addr, (hsize_t)sym->node_size) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to free symbol table node")
- } /* end if */
+ /* reserved */
+ *image++ = 0;
- /* Destroy symbol table node */
- if(H5G__node_free(sym) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to destroy symbol table node")
+ /* number of symbols */
+ UINT16ENCODE(image, sym->nsyms);
+
+ /* entries */
+ if(H5G__ent_encode_vec(f, &image, sym->entry, sym->nsyms) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTENCODE, FAIL, "can't serialize")
+
+ /* Clear rest of symbol table node */
+ HDmemset(image, 0, sym->node_size - (size_t)(image - (uint8_t *)_image));
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5G_node_dest() */
+} /* end H5G__cache_node_serialize() */
+
+
+/***************************************/
+/* no H5G__cache_node_notify() function */
+/***************************************/
/*-------------------------------------------------------------------------
- * Function: H5G_node_clear
+ * Function: H5G__cache_node_free_icr
*
- * Purpose: Mark a symbol table node in memory as non-dirty.
+ * Purpose: Destroys a symbol table node in memory.
*
- * Return: Non-negative on success/Negative on failure
+ * Note: The metadata cache sets the object's cache_info.magic to
+ * H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC before calling a free_icr
+ * callback (checked in assert).
*
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Mar 20 2003
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: John Mainzer
+ * 6/21/14
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5G_node_clear(H5F_t *f, H5G_node_t *sym, hbool_t destroy)
+H5G__cache_node_free_icr(void *_thing)
{
- herr_t ret_value = SUCCEED;
+ H5G_node_t *sym = (H5G_node_t *)_thing; /* Pointer to the object */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
- /*
- * Check arguments.
- */
+ /* Sanity checks */
HDassert(sym);
+ HDassert(sym->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC);
+ HDassert(sym->cache_info.type == H5AC_SNODE);
- /* Reset the node's dirty flag */
- sym->cache_info.is_dirty = FALSE;
-
- /*
- * Destroy the symbol node? This might happen if the node is being
- * preempted from the cache.
- */
- if(destroy)
- if(H5G_node_dest(f, sym) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to destroy symbol table node")
+ /* Destroy symbol table node */
+ if(H5G__node_free(sym) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to destroy symbol table node")
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5G_node_clear() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5G_node_size
- *
- * Purpose: Compute the size in bytes of the specified instance of
- * H5G_node_t on disk, and return it in *size_ptr. On failure
- * the value of size_ptr is undefined.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: John Mainzer
- * 5/13/04
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5G_node_size(const H5F_t H5_ATTR_UNUSED *f, const H5G_node_t *sym, size_t *size_ptr)
-{
- FUNC_ENTER_NOAPI_NOINIT_NOERR
-
- /*
- * Check arguments.
- */
- HDassert(f);
- HDassert(size_ptr);
-
- *size_ptr = sym->node_size;
-
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5G_node_size() */
+} /* end H5G__cache_node_free_icr() */
diff --git a/src/H5Gent.c b/src/H5Gent.c
index 86af500..2959a53 100644
--- a/src/H5Gent.c
+++ b/src/H5Gent.c
@@ -460,7 +460,7 @@ H5G__ent_convert(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, const char *name,
targ_oloc.addr = lnk->u.hard.addr;
/* Get the object header */
- if(NULL == (oh = H5O_protect(&targ_oloc, dxpl_id, H5AC_READ)))
+ if(NULL == (oh = H5O_protect(&targ_oloc, dxpl_id, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_SYM, H5E_CANTPROTECT, FAIL, "unable to protect target object header")
/* Check if a symbol table message exists */
diff --git a/src/H5Gnode.c b/src/H5Gnode.c
index dc954ca..9c4c962 100644
--- a/src/H5Gnode.c
+++ b/src/H5Gnode.c
@@ -541,7 +541,7 @@ H5G_node_found(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void H5_ATTR_UNUSED
/*
* Load the symbol table node for exclusive access.
*/
- if(NULL == (sn = (H5G_node_t *)H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, f, H5AC_READ)))
+ if(NULL == (sn = (H5G_node_t *)H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, f, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, FAIL, "unable to protect symbol table node")
/* Get base address of heap */
@@ -647,7 +647,7 @@ H5G_node_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr,
/*
* Load the symbol node.
*/
- if(NULL == (sn = (H5G_node_t *)H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, f, H5AC_WRITE)))
+ if(NULL == (sn = (H5G_node_t *)H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, f, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5B_INS_ERROR, "unable to protect symbol table node")
/* Get base address of heap */
@@ -691,7 +691,7 @@ H5G_node_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr,
if(H5G_node_create(f, dxpl_id, H5B_INS_FIRST, NULL, NULL, NULL, new_node_p/*out*/) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, H5B_INS_ERROR, "unable to split symbol table node")
- if(NULL == (snrt = (H5G_node_t *)H5AC_protect(f, dxpl_id, H5AC_SNODE, *new_node_p, f, H5AC_WRITE)))
+ if(NULL == (snrt = (H5G_node_t *)H5AC_protect(f, dxpl_id, H5AC_SNODE, *new_node_p, f, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5B_INS_ERROR, "unable to split symbol table node")
HDmemcpy(snrt->entry, sn->entry + H5F_SYM_LEAF_K(f),
@@ -808,7 +808,7 @@ H5G_node_remove(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key/*in,out*/,
HDassert(udata && udata->common.heap);
/* Load the symbol table */
- if(NULL == (sn = (H5G_node_t *)H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, f, H5AC_WRITE)))
+ if(NULL == (sn = (H5G_node_t *)H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, f, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5B_INS_ERROR, "unable to protect symbol table node")
/* "Normal" removal of a single entry from the symbol table node */
@@ -1001,7 +1001,7 @@ H5G__node_iterate(H5F_t *f, hid_t dxpl_id, const void H5_ATTR_UNUSED *_lt_key, h
HDassert(udata && udata->heap);
/* Protect the symbol table node & local heap while we iterate over entries */
- if(NULL == (sn = (H5G_node_t *)H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, f, H5AC_READ)))
+ if(NULL == (sn = (H5G_node_t *)H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, f, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5_ITER_ERROR, "unable to load symbol table node")
/*
@@ -1078,7 +1078,7 @@ H5G__node_sumup(H5F_t *f, hid_t dxpl_id, const void H5_ATTR_UNUSED *_lt_key, had
HDassert(num_objs);
/* Find the object node and add the number of symbol entries. */
- if(NULL == (sn = (H5G_node_t *)H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, f, H5AC_READ)))
+ if(NULL == (sn = (H5G_node_t *)H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, f, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5_ITER_ERROR, "unable to load symbol table node")
*num_objs += sn->nsyms;
@@ -1123,7 +1123,7 @@ H5G__node_by_idx(H5F_t *f, hid_t dxpl_id, const void H5_ATTR_UNUSED *_lt_key, ha
HDassert(udata);
/* Get a pointer to the symbol table node */
- if(NULL == (sn = (H5G_node_t *)H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, f, H5AC_READ)))
+ if(NULL == (sn = (H5G_node_t *)H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, f, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5_ITER_ERROR, "unable to load symbol table node");
/* Find the node, locate the object symbol table entry and retrieve the name */
@@ -1261,11 +1261,11 @@ H5G__node_copy(H5F_t *f, hid_t dxpl_id, const void H5_ATTR_UNUSED *_lt_key, hadd
HDassert(udata);
/* load the symbol table into memory from the source file */
- if(NULL == (sn = (H5G_node_t *)H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, f, H5AC_READ)))
+ if(NULL == (sn = (H5G_node_t *)H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, f, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5_ITER_ERROR, "unable to load symbol table node")
/* get the base address of the heap */
- if(NULL == (heap = H5HL_protect(f, dxpl_id, udata->src_heap_addr, H5AC_READ)))
+ if(NULL == (heap = H5HL_protect(f, dxpl_id, udata->src_heap_addr, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, H5_ITER_ERROR, "unable to protect symbol name")
/* copy object in this node one by one */
@@ -1420,7 +1420,7 @@ H5G__node_build_table(H5F_t *f, hid_t dxpl_id, const void H5_ATTR_UNUSED *_lt_ke
* Save information about the symbol table node since we can't lock it
* because we're about to call an application function.
*/
- if(NULL == (sn = (H5G_node_t *)H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, f, H5AC_READ)))
+ if(NULL == (sn = (H5G_node_t *)H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, f, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5_ITER_ERROR, "unable to load symbol table node")
/* Check if the link table needs to be extended */
@@ -1527,14 +1527,14 @@ H5G_node_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE * stream, int indent,
/* Pin the heap down in memory */
if(heap_addr > 0 && H5F_addr_defined(heap_addr))
- if(NULL == (heap = H5HL_protect(f, dxpl_id, heap_addr, H5AC_READ)))
+ if(NULL == (heap = H5HL_protect(f, dxpl_id, heap_addr, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, FAIL, "unable to protect symbol table heap")
/*
* If we couldn't load the symbol table node, then try loading the
* B-tree node.
*/
- if(NULL == (sn = (H5G_node_t *)H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, f, H5AC_READ))) {
+ if(NULL == (sn = (H5G_node_t *)H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, f, H5AC__READ_ONLY_FLAG))) {
H5G_bt_common_t udata; /*data to pass through B-tree */
H5E_clear_stack(NULL); /* discard that error */
diff --git a/src/H5Gstab.c b/src/H5Gstab.c
index 6c7e828..a5c5d3e 100644
--- a/src/H5Gstab.c
+++ b/src/H5Gstab.c
@@ -160,7 +160,7 @@ H5G__stab_create_components(H5F_t *f, H5O_stab_t *stab, size_t size_hint, hid_t
HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create heap")
/* Pin the heap down in memory */
- if(NULL == (heap = H5HL_protect(f, dxpl_id, stab->heap_addr, H5AC_WRITE)))
+ if(NULL == (heap = H5HL_protect(f, dxpl_id, stab->heap_addr, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to protect symbol table heap")
/* Insert name into the heap */
@@ -276,7 +276,7 @@ H5G__stab_insert_real(H5F_t *f, const H5O_stab_t *stab, const char *name,
HDassert(obj_lnk);
/* Pin the heap down in memory */
- if(NULL == (heap = H5HL_protect(f, dxpl_id, stab->heap_addr, H5AC_WRITE)))
+ if(NULL == (heap = H5HL_protect(f, dxpl_id, stab->heap_addr, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to protect symbol table heap")
/* Initialize data to pass through B-tree */
@@ -373,7 +373,7 @@ H5G__stab_remove(const H5O_loc_t *loc, hid_t dxpl_id, H5RS_str_t *grp_full_path_
HGOTO_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "not a symbol table")
/* Pin the heap down in memory */
- if(NULL == (heap = H5HL_protect(loc->file, dxpl_id, stab.heap_addr, H5AC_WRITE)))
+ if(NULL == (heap = H5HL_protect(loc->file, dxpl_id, stab.heap_addr, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to protect symbol table heap")
/* Initialize data to pass through B-tree */
@@ -431,7 +431,7 @@ H5G__stab_remove_by_idx(const H5O_loc_t *grp_oloc, hid_t dxpl_id, H5RS_str_t *gr
HGOTO_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "not a symbol table")
/* Pin the heap down in memory */
- if(NULL == (heap = H5HL_protect(grp_oloc->file, dxpl_id, stab.heap_addr, H5AC_WRITE)))
+ if(NULL == (heap = H5HL_protect(grp_oloc->file, dxpl_id, stab.heap_addr, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to protect symbol table heap")
/* Initialize data to pass through B-tree */
@@ -485,7 +485,7 @@ H5G__stab_delete(H5F_t *f, hid_t dxpl_id, const H5O_stab_t *stab)
HDassert(H5F_addr_defined(stab->heap_addr));
/* Pin the heap down in memory */
- if(NULL == (heap = H5HL_protect(f, dxpl_id, stab->heap_addr, H5AC_WRITE)))
+ if(NULL == (heap = H5HL_protect(f, dxpl_id, stab->heap_addr, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to protect symbol table heap")
/* Set up user data for B-tree deletion */
@@ -546,7 +546,7 @@ H5G__stab_iterate(const H5O_loc_t *oloc, hid_t dxpl_id, H5_iter_order_t order,
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to determine local heap address")
/* Pin the heap down in memory */
- if(NULL == (heap = H5HL_protect(oloc->file, dxpl_id, stab.heap_addr, H5AC_READ)))
+ if(NULL == (heap = H5HL_protect(oloc->file, dxpl_id, stab.heap_addr, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to protect symbol table heap")
/* Check on iteration order */
@@ -766,7 +766,7 @@ H5G__stab_get_name_by_idx(const H5O_loc_t *oloc, H5_iter_order_t order, hsize_t
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to determine local heap address")
/* Pin the heap down in memory */
- if(NULL == (heap = H5HL_protect(oloc->file, dxpl_id, stab.heap_addr, H5AC_READ)))
+ if(NULL == (heap = H5HL_protect(oloc->file, dxpl_id, stab.heap_addr, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to protect symbol table heap")
/* Remap index for decreasing iteration order */
@@ -888,7 +888,7 @@ H5G__stab_lookup(const H5O_loc_t *grp_oloc, const char *name, H5O_link_t *lnk,
HGOTO_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "can't read message")
/* Pin the heap down in memory */
- if(NULL == (heap = H5HL_protect(grp_oloc->file, dxpl_id, stab.heap_addr, H5AC_READ)))
+ if(NULL == (heap = H5HL_protect(grp_oloc->file, dxpl_id, stab.heap_addr, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to protect symbol table heap")
/* Set up user data to pass to 'find' operation callback */
@@ -989,7 +989,7 @@ H5G__stab_lookup_by_idx(const H5O_loc_t *grp_oloc, H5_iter_order_t order, hsize_
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to determine local heap address")
/* Pin the heap down in memory */
- if(NULL == (heap = H5HL_protect(grp_oloc->file, dxpl_id, stab.heap_addr, H5AC_READ)))
+ if(NULL == (heap = H5HL_protect(grp_oloc->file, dxpl_id, stab.heap_addr, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to protect symbol table heap")
/* Remap index for decreasing iteration order */
@@ -1081,10 +1081,10 @@ H5G__stab_valid(H5O_loc_t *grp_oloc, hid_t dxpl_id, H5O_stab_t *alt_stab)
} /* end if */
/* Check if the symbol table message's heap address is valid */
- if(NULL == (heap = H5HL_protect(grp_oloc->file, dxpl_id, stab.heap_addr, H5AC_READ))) {
+ if(NULL == (heap = H5HL_protect(grp_oloc->file, dxpl_id, stab.heap_addr, H5AC__READ_ONLY_FLAG))) {
/* Address is invalid, try the heap address in the alternate symbol
* table message */
- if(!alt_stab || NULL == (heap = H5HL_protect(grp_oloc->file, dxpl_id, alt_stab->heap_addr, H5AC_READ)))
+ if(!alt_stab || NULL == (heap = H5HL_protect(grp_oloc->file, dxpl_id, alt_stab->heap_addr, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "unable to locate heap")
else {
/* The alternate symbol table's heap address is valid. Adjust the
diff --git a/src/H5Gtest.c b/src/H5Gtest.c
index 981946d..412389b 100644
--- a/src/H5Gtest.c
+++ b/src/H5Gtest.c
@@ -637,7 +637,7 @@ H5G__verify_cached_stab_test(H5O_loc_t *grp_oloc, H5G_entry_t *ent)
HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "b-tree address is invalid")
/* Verify that the heap address is valid */
- if(NULL == (heap = H5HL_protect(grp_oloc->file, dxpl_id, stab.heap_addr, H5AC_READ)))
+ if(NULL == (heap = H5HL_protect(grp_oloc->file, dxpl_id, stab.heap_addr, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "heap address is invalid")
done:
@@ -686,7 +686,7 @@ H5G_verify_cached_stabs_test_cb(H5F_t *f, hid_t dxpl_id,
HDassert(H5F_addr_defined(addr));
/* Load the node */
- if(NULL == (sn = (H5G_node_t *)H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, f, H5AC_READ)))
+ if(NULL == (sn = (H5G_node_t *)H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, f, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5_ITER_ERROR, "unable to load symbol table node")
/* Check each target object to see if its stab message (if present) matches
@@ -701,7 +701,7 @@ H5G_verify_cached_stabs_test_cb(H5F_t *f, hid_t dxpl_id,
targ_oloc.addr = sn->entry[i].header;
/* Load target object header */
- if(NULL == (targ_oh = H5O_protect(&targ_oloc, dxpl_id, H5AC_READ)))
+ if(NULL == (targ_oh = H5O_protect(&targ_oloc, dxpl_id, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_SYM, H5E_CANTPROTECT, H5_ITER_ERROR, "unable to protect target object header")
/* Check if a symbol table message exists */
diff --git a/src/H5HF.c b/src/H5HF.c
index 3f1f37f..b2d7a34 100644
--- a/src/H5HF.c
+++ b/src/H5HF.c
@@ -172,7 +172,7 @@ H5HF_create(H5F_t *f, hid_t dxpl_id, const H5HF_create_t *cparam)
HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, NULL, "memory allocation failed for fractal heap info")
/* Lock the heap header into memory */
- if(NULL == (hdr = H5HF_hdr_protect(f, dxpl_id, fh_addr, H5AC_WRITE)))
+ if(NULL == (hdr = H5HF_hdr_protect(f, dxpl_id, fh_addr, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to protect fractal heap header")
/* Point fractal heap wrapper at header and bump it's ref count */
@@ -231,7 +231,7 @@ H5HF_open(H5F_t *f, hid_t dxpl_id, haddr_t fh_addr)
HDassert(H5F_addr_defined(fh_addr));
/* Load the heap header into memory */
- if(NULL == (hdr = H5HF_hdr_protect(f, dxpl_id, fh_addr, H5AC_READ)))
+ if(NULL == (hdr = H5HF_hdr_protect(f, dxpl_id, fh_addr, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to protect fractal heap header")
/* Check for pending heap deletion */
@@ -821,7 +821,7 @@ H5HF_close(H5HF_t *fh, hid_t dxpl_id)
H5HF_hdr_t *hdr; /* Another pointer to fractal heap header */
/* Lock the heap header into memory */
- if(NULL == (hdr = H5HF_hdr_protect(fh->f, dxpl_id, heap_addr, H5AC_WRITE)))
+ if(NULL == (hdr = H5HF_hdr_protect(fh->f, dxpl_id, heap_addr, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap header")
/* Delete heap, starting with header (unprotects header) */
@@ -865,7 +865,7 @@ H5HF_delete(H5F_t *f, hid_t dxpl_id, haddr_t fh_addr)
HDassert(H5F_addr_defined(fh_addr));
/* Lock the heap header into memory */
- if(NULL == (hdr = H5HF_hdr_protect(f, dxpl_id, fh_addr, H5AC_WRITE)))
+ if(NULL == (hdr = H5HF_hdr_protect(f, dxpl_id, fh_addr, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap header")
/* Check for files using shared heap header */
diff --git a/src/H5HFcache.c b/src/H5HFcache.c
index 4b02e06..7171da9 100644
--- a/src/H5HFcache.c
+++ b/src/H5HFcache.c
@@ -1,4 +1,4 @@
-/* / * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* Copyright by the Board of Trustees of the University of Illinois. *
* All rights reserved. *
@@ -53,20 +53,6 @@
#define H5HF_DBLOCK_VERSION 0 /* Direct block */
#define H5HF_IBLOCK_VERSION 0 /* Indirect block */
-/* Size of stack buffer for serialized headers */
-#define H5HF_HDR_BUF_SIZE 512
-
-/* Size of stack buffer for serialized indirect blocks */
-#define H5HF_IBLOCK_BUF_SIZE 4096
-
-/* Size of minimum header to decode for determining the full header size */
-#define H5HF_MIN_HEADER_SIZE ( \
- H5_SIZEOF_MAGIC + /* Signature */ \
- 1 + /* Version */ \
- 2 + /* Heap ID len */ \
- 2 /* I/O filters' encoded len */ \
- )
-
/******************/
/* Local Typedefs */
@@ -87,24 +73,57 @@ static herr_t H5HF__dtable_encode(H5F_t *f, uint8_t **pp, const H5HF_dtable_t *d
static herr_t H5HF__dtable_decode(H5F_t *f, const uint8_t **pp, H5HF_dtable_t *dtable);
/* Metadata cache (H5AC) callbacks */
-static H5HF_hdr_t *H5HF_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata);
-static herr_t H5HF_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HF_hdr_t *hdr, unsigned H5_ATTR_UNUSED * flags_ptr);
-static herr_t H5HF_cache_hdr_dest(H5F_t *f, H5HF_hdr_t *hdr);
-static herr_t H5HF_cache_hdr_clear(H5F_t *f, H5HF_hdr_t *hdr, hbool_t destroy);
-static herr_t H5HF_cache_hdr_size(const H5F_t *f, const H5HF_hdr_t *hdr, size_t *size_ptr);
-static H5HF_indirect_t *H5HF_cache_iblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata);
-static herr_t H5HF_cache_iblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HF_indirect_t *iblock, unsigned H5_ATTR_UNUSED * flags_ptr);
-static herr_t H5HF_cache_iblock_dest(H5F_t *f, H5HF_indirect_t *iblock);
-static herr_t H5HF_cache_iblock_clear(H5F_t *f, H5HF_indirect_t *iblock, hbool_t destroy);
-static herr_t H5HF_cache_iblock_notify(H5C_notify_action_t action, H5HF_indirect_t *iblock);
-static herr_t H5HF_cache_iblock_size(const H5F_t *f, const H5HF_indirect_t *iblock, size_t *size_ptr);
-static H5HF_direct_t *H5HF_cache_dblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata);
-static herr_t H5HF_cache_dblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HF_direct_t *dblock, unsigned H5_ATTR_UNUSED * flags_ptr);
-static herr_t H5HF_cache_dblock_dest(H5F_t *f, H5HF_direct_t *dblock);
-static herr_t H5HF_cache_dblock_clear(H5F_t *f, H5HF_direct_t *dblock, hbool_t destroy);
-static herr_t H5HF_cache_dblock_notify(H5C_notify_action_t action, H5HF_direct_t *dblock);
-static herr_t H5HF_cache_dblock_size(const H5F_t *f, const H5HF_direct_t *dblock, size_t *size_ptr);
-
+static herr_t H5HF__cache_hdr_get_load_size(const void *image_ptr, void *udata,
+ size_t *image_len, size_t *actual_len,
+ hbool_t *compressed_ptr, size_t *compressed_image_len_ptr);
+static htri_t H5HF__cache_hdr_verify_chksum(const void *image_ptr, size_t len, void *udata_ptr);
+static void *H5HF__cache_hdr_deserialize(const void *image, size_t len,
+ void *udata, hbool_t *dirty);
+static herr_t H5HF__cache_hdr_image_len(const void *thing, size_t *image_len,
+ hbool_t *compressed_ptr, size_t *compressed_image_len_ptr);
+static herr_t H5HF__cache_hdr_pre_serialize(const H5F_t *f, hid_t dxpl_id,
+ void *thing, haddr_t addr, size_t len, size_t compressed_len,
+ haddr_t *new_addr, size_t *new_len, size_t *new_compressed_len,
+ unsigned *flags);
+static herr_t H5HF__cache_hdr_serialize(const H5F_t *f, void *image,
+ size_t len, void *thing);
+static herr_t H5HF__cache_hdr_free_icr(void *thing);
+
+static herr_t H5HF__cache_iblock_get_load_size(const void *image_ptr, void *udata,
+ size_t *image_len, size_t *actual_len,
+ hbool_t *compressed_ptr, size_t *compressed_image_len_ptr);
+static htri_t H5HF__cache_iblock_verify_chksum(const void *image_ptr, size_t len, void *udata_ptr);
+static void *H5HF__cache_iblock_deserialize(const void *image, size_t len,
+ void *udata, hbool_t *dirty);
+static herr_t H5HF__cache_iblock_image_len(const void *thing,
+ size_t *image_len, hbool_t *compressed_ptr,
+ size_t *compressed_image_len_ptr);
+static herr_t H5HF__cache_iblock_pre_serialize(const H5F_t *f, hid_t dxpl_id,
+ void *thing, haddr_t addr, size_t len, size_t compressed_len,
+ haddr_t *new_addr, size_t *new_len, size_t *new_compressed_len,
+ unsigned *flags);
+static herr_t H5HF__cache_iblock_serialize(const H5F_t *f, void *image,
+ size_t len, void *thing);
+static herr_t H5HF__cache_iblock_notify(H5C_notify_action_t action, void *thing);
+static herr_t H5HF__cache_iblock_free_icr(void *thing);
+
+static herr_t H5HF__cache_dblock_get_load_size(const void *image_ptr, void *udata,
+ size_t *image_len, size_t *actual_len,
+ hbool_t *compressed_ptr, size_t *compressed_image_len_ptr);
+static htri_t H5HF__cache_dblock_verify_chksum(const void *image_ptr, size_t len, void *udata_ptr);
+static void *H5HF__cache_dblock_deserialize(const void *image, size_t len,
+ void *udata, hbool_t *dirty);
+static herr_t H5HF__cache_dblock_image_len(const void *thing,
+ size_t *image_len, hbool_t *compressed_ptr,
+ size_t *compressed_image_len_ptr);
+static herr_t H5HF__cache_dblock_pre_serialize(const H5F_t *f, hid_t dxpl_id,
+ void *thing, haddr_t addr, size_t len, size_t compressed_len,
+ haddr_t *new_addr, size_t *new_len, size_t *new_compressed_len,
+ unsigned *flags);
+static herr_t H5HF__cache_dblock_serialize(const H5F_t *f, void *image,
+ size_t len, void *thing);
+static herr_t H5HF__cache_dblock_notify(H5C_notify_action_t action, void *thing);
+static herr_t H5HF__cache_dblock_free_icr(void *thing);
/* Debugging Function Prototypes */
#ifndef NDEBUG
@@ -125,35 +144,56 @@ static herr_t H5HF__cache_verify_descendant_iblocks_clean(H5F_t *f, hid_t dxpl_i
/* H5HF header inherits cache-like properties from H5AC */
const H5AC_class_t H5AC_FHEAP_HDR[1] = {{
- H5AC_FHEAP_HDR_ID,
- (H5AC_load_func_t)H5HF_cache_hdr_load,
- (H5AC_flush_func_t)H5HF_cache_hdr_flush,
- (H5AC_dest_func_t)H5HF_cache_hdr_dest,
- (H5AC_clear_func_t)H5HF_cache_hdr_clear,
- (H5AC_notify_func_t)NULL,
- (H5AC_size_func_t)H5HF_cache_hdr_size,
+ H5AC_FHEAP_HDR_ID, /* Metadata client ID */
+ "fractal heap header", /* Metadata client name (for debugging) */
+ H5FD_MEM_FHEAP_HDR, /* File space memory type for client */
+ H5AC__CLASS_SPECULATIVE_LOAD_FLAG, /* Client class behavior flags */
+ H5HF__cache_hdr_get_load_size, /* 'get_load_size' callback */
+ H5HF__cache_hdr_verify_chksum, /* 'verify_chksum' callback */
+ H5HF__cache_hdr_deserialize, /* 'deserialize' callback */
+ H5HF__cache_hdr_image_len, /* 'image_len' callback */
+ H5HF__cache_hdr_pre_serialize, /* 'pre_serialize' callback */
+ H5HF__cache_hdr_serialize, /* 'serialize' callback */
+ NULL, /* 'notify' callback */
+ H5HF__cache_hdr_free_icr, /* 'free_icr' callback */
+ NULL, /* 'clear' callback */
+ NULL, /* 'fsf_size' callback */
}};
/* H5HF indirect block inherits cache-like properties from H5AC */
const H5AC_class_t H5AC_FHEAP_IBLOCK[1] = {{
- H5AC_FHEAP_IBLOCK_ID,
- (H5AC_load_func_t)H5HF_cache_iblock_load,
- (H5AC_flush_func_t)H5HF_cache_iblock_flush,
- (H5AC_dest_func_t)H5HF_cache_iblock_dest,
- (H5AC_clear_func_t)H5HF_cache_iblock_clear,
- (H5AC_notify_func_t)H5HF_cache_iblock_notify,
- (H5AC_size_func_t)H5HF_cache_iblock_size,
+ H5AC_FHEAP_IBLOCK_ID, /* Metadata client ID */
+ "fractal heap indirect block", /* Metadata client name (for debugging) */
+ H5FD_MEM_FHEAP_IBLOCK, /* File space memory type for client */
+ H5AC__CLASS_NO_FLAGS_SET, /* Client class behavior flags */
+ H5HF__cache_iblock_get_load_size, /* 'get_load_size' callback */
+ H5HF__cache_iblock_verify_chksum, /* 'verify_chksum' callback */
+ H5HF__cache_iblock_deserialize, /* 'deserialize' callback */
+ H5HF__cache_iblock_image_len, /* 'image_len' callback */
+ H5HF__cache_iblock_pre_serialize, /* 'pre_serialize' callback */
+ H5HF__cache_iblock_serialize, /* 'serialize' callback */
+ H5HF__cache_iblock_notify, /* 'notify' callback */
+ H5HF__cache_iblock_free_icr, /* 'free_icr' callback */
+ NULL, /* 'clear' callback */
+ NULL, /* 'fsf_size' callback */
}};
/* H5HF direct block inherits cache-like properties from H5AC */
const H5AC_class_t H5AC_FHEAP_DBLOCK[1] = {{
- H5AC_FHEAP_DBLOCK_ID,
- (H5AC_load_func_t)H5HF_cache_dblock_load,
- (H5AC_flush_func_t)H5HF_cache_dblock_flush,
- (H5AC_dest_func_t)H5HF_cache_dblock_dest,
- (H5AC_clear_func_t)H5HF_cache_dblock_clear,
- (H5AC_notify_func_t)H5HF_cache_dblock_notify,
- (H5AC_size_func_t)H5HF_cache_dblock_size,
+ H5AC_FHEAP_DBLOCK_ID, /* Metadata client ID */
+ "fractal heap direct block", /* Metadata client name (for debugging) */
+ H5FD_MEM_FHEAP_DBLOCK, /* File space memory type for client */
+ H5C__CLASS_COMPRESSED_FLAG, /* Client class behavior flags */
+ H5HF__cache_dblock_get_load_size, /* 'get_load_size' callback */
+ H5HF__cache_dblock_verify_chksum, /* 'verify_chksum' callback */
+ H5HF__cache_dblock_deserialize, /* 'deserialize' callback */
+ H5HF__cache_dblock_image_len, /* 'image_len' callback */
+ H5HF__cache_dblock_pre_serialize, /* 'pre_serialize' callback */
+ H5HF__cache_dblock_serialize, /* 'serialize' callback */
+ H5HF__cache_dblock_notify, /* 'notify' callback */
+ H5HF__cache_dblock_free_icr, /* 'free_icr' callback */
+ NULL, /* 'clear' callback */
+ NULL, /* 'fsf_size' callback */
}};
@@ -272,174 +312,294 @@ H5HF__dtable_encode(H5F_t *f, uint8_t **pp, const H5HF_dtable_t *dtable)
/*-------------------------------------------------------------------------
- * Function: H5HF_cache_hdr_load
+ * Function: H5HF__cache_hdr_get_load_size()
*
- * Purpose: Loads a fractal heap header from the disk.
+ * Purpose: Determine the size of the fractal heap header on disk,
+ * and set *image_len to this value.
*
- * Return: Success: Pointer to a new fractal heap
+ * This code is based on the old H5HF_cache_hdr_load() routine
+ * that was used with the version 2 metadata cache. Note the
+ * use of a dummy header to compute the on disk size of the header.
+ *
+ * Note also that the value returned by this function presumes that
+ * there is no I/O filtering data in the header. If there is, the
+ * size reported will be too small, and H5C_load_entry()
+ * will have to make two tries to load the fractal heap header.
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: John Mainzer
+ * 6/21/14
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HF__cache_hdr_get_load_size(const void *_image, void *_udata, size_t *image_len, size_t *actual_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr)
+{
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ H5HF_hdr_cache_ud_t *udata = (H5HF_hdr_cache_ud_t *)_udata; /* pointer to user data */
+ H5HF_hdr_t dummy_hdr; /* dummy header -- to compute size */
+ unsigned id_len; /* Size of heap IDs (in bytes) */
+ unsigned filter_len; /* Size of I/O filter information (in bytes) */
+ size_t filter_info_size; /* Size of filter information */
+ htri_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Sanity checks */
+ HDassert(udata);
+ HDassert(image_len);
+
+ if(image == NULL) {
+ /* Set the internal parameters for the heap */
+ dummy_hdr.f = udata->f;
+ dummy_hdr.sizeof_size = H5F_SIZEOF_SIZE(udata->f);
+ dummy_hdr.sizeof_addr = H5F_SIZEOF_ADDR(udata->f);
+
+ /* Compute the 'base' size of the fractal heap header on disk */
+ *image_len = (size_t)H5HF_HEADER_SIZE(&dummy_hdr);
+
+ } else { /* compute actual_len */
+
+ HDassert(actual_len);
+ HDassert(*actual_len == *image_len);
+
+ /* Magic number */
+ if(HDmemcmp(image, H5HF_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC))
+ HGOTO_DONE(FAIL)
+ image += H5_SIZEOF_MAGIC;
+
+ /* Version */
+ if(*image++ != H5HF_HDR_VERSION)
+ HGOTO_DONE(FAIL)
+
+ /* General heap information */
+ UINT16DECODE(image, id_len); /* Heap ID length */
+ UINT16DECODE(image, filter_len); /* I/O filters' encoded length */
+
+ if(filter_len > 0) {
+
+ /* Compute the size of the extra filter information */
+ filter_info_size = (size_t)(H5F_SIZEOF_SIZE(udata->f) /* Size of size for filtered root direct block */
+ + (unsigned)4 /* Size of filter mask for filtered root direct block */
+ + filter_len); /* Size of encoded I/O filter info */
+
+ /* Compute the heap header's size */
+ *actual_len += filter_info_size;
+ }
+
+ } /* compute actual_len */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF__cache_hdr_get_load_size() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF__cache_hdr_verify_chksum
+ *
+ * Purpose: Verify the computed checksum of the data structure is the
+ * same as the stored chksum.
+ *
+ * Return: Success: TRUE/FALSE
+ * Failure: Negative
+ *
+ * Programmer: Vailin Choi; Aug 2015
+ *
+ *-------------------------------------------------------------------------
+ */
+static htri_t
+H5HF__cache_hdr_verify_chksum(const void *_image, size_t len, void H5_ATTR_UNUSED *_udata)
+{
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ uint32_t stored_chksum; /* Stored metadata checksum value */
+ uint32_t computed_chksum; /* Computed metadata checksum value */
+ htri_t ret_value = TRUE; /* Return value */
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Check arguments */
+ HDassert(image);
+
+ /* Get stored and computed checksums */
+ H5F_get_checksums(image, len, &stored_chksum, &computed_chksum);
+
+ if(stored_chksum != computed_chksum)
+ ret_value = FALSE;
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF__cache_hdr_verify_chksum() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF__cache_hdr_deserialize
+ *
+ * Purpose: Given a buffer containing an on disk image of a fractal heap
+ * header block, allocate an instance of H5HF_hdr_t, load the contents
+ * of the buffer into into the new instance of H5HF_hdr_t, and then
+ * return a pointer to the new instance.
+ *
+ * Since H5HF__cache_hdr_get_load_size() reports header on disk size
+ * base on the assumption that the header contains no I/O filtering
+ * data, it is possible that the provided image will be too small.
+ *
+ * In this case, we DO NOT flag an error when this is discovered.
+ * Instead, we make note of the correct image size, and report
+ * success.
+ *
+ * Since H5HF__cache_hdr_image_len() callback is defined,
+ * H5C_load_entry() will call H5HF__cache_hdr_image_len() and
+ * obtain the correct image length.
+ *
+ * Since the H5AC__CLASS_SPECULATIVE_LOAD_FLAG is set,
+ * H5C_load_entry() will load an image of the correct size, and
+ * then call this function again to deserialize it. Before doing
+ * so, it will also call H5HF__cache_hdr_free_icr() to discard the
+ * result of the first deserialize call.
+ *
+ * Note that the v2 B-tree and free space manager associated
+ * with the fractal heap (roots stored in the huge_bt2 and fspace
+ * fields respectively) are not loaded at this time. As best I can
+ * tell from reviewing the code, they are loaded or created when
+ * they are accessed.
+ *
+ * Return: Success: Pointer to in core representation
* Failure: NULL
*
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 24 2006
+ * Programmer: John Mainzer
+ * 6/21/14
*
*-------------------------------------------------------------------------
*/
-static H5HF_hdr_t *
-H5HF_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
+static void *
+H5HF__cache_hdr_deserialize(const void *_image, size_t len, void *_udata,
+ hbool_t H5_ATTR_UNUSED *dirty)
{
- H5HF_hdr_t *hdr = NULL; /* Fractal heap info */
- H5HF_hdr_cache_ud_t *udata = (H5HF_hdr_cache_ud_t *)_udata;
- size_t min_size; /* Header size */
- H5WB_t *wb = NULL; /* Wrapped buffer for header data */
- uint8_t hdr_buf[H5HF_HDR_BUF_SIZE]; /* Buffer for header */
- uint8_t *buf; /* Pointer to header buffer */
- size_t buf_size; /* Current size of temporary buffer */
- const uint8_t *p; /* Pointer into raw data buffer */
+ H5HF_hdr_t *hdr = NULL; /* Fractal heap info */
+ H5HF_hdr_cache_ud_t *udata = (H5HF_hdr_cache_ud_t *)_udata; /* User data for callback */
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into into supplied image */
+ size_t size; /* Header size */
uint32_t stored_chksum; /* Stored metadata checksum value */
- uint32_t computed_chksum; /* Computed metadata checksum value */
- unsigned tries, max_tries; /* The # of read attempts */
- unsigned retries; /* The # of retries */
uint8_t heap_flags; /* Status flags for heap */
- H5HF_hdr_t *ret_value; /* Return value */
+ void * ret_value; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
- /* Check arguments */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
+ /* Sanity checks */
+ HDassert(image);
+ HDassert(len > 0);
HDassert(udata);
+ HDassert(dirty);
/* Allocate space for the fractal heap data structure */
if(NULL == (hdr = H5HF_hdr_alloc(udata->f)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
- /* Wrap the local buffer for serialized header info */
- if(NULL == (wb = H5WB_wrap(hdr_buf, sizeof(hdr_buf))))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, NULL, "can't wrap buffer")
-
- /* Compute the minimum size of the fractal heap header to determine filter info */
- min_size = (size_t)H5HF_MIN_HEADER_SIZE;
-
- /* Get a pointer to a buffer that's large enough for serialized header */
- if(NULL == (buf = (uint8_t *)H5WB_actual(wb, min_size)))
- HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, NULL, "can't get actual buffer")
- buf_size = min_size;
-
- /* Get the # of read attempts */
- tries = max_tries = H5F_GET_READ_ATTEMPTS(udata->f);
- retries = 0;
- do {
- /* Read minimum header from disk */
- if(H5F_block_read(udata->f, H5FD_MEM_FHEAP_HDR, addr, min_size, dxpl_id, buf) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_READERROR, NULL, "can't read fractal heap header")
-
- /* Get temporary pointer to serialized header */
- p = buf;
-
- /* Magic number */
- if(HDmemcmp(p, H5HF_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC))
- continue; /* Transfer control to while() and count this as a bad read, not an error */
- p += H5_SIZEOF_MAGIC;
-
- /* Version */
- if(*p++ != H5HF_HDR_VERSION)
- continue; /* Transfer control to while() and count this as a bad read, not an error */
-
- /* General heap information */
- UINT16DECODE(p, hdr->id_len); /* Heap ID length */
- UINT16DECODE(p, hdr->filter_len); /* I/O filters' encoded length */
-
- /* Fixed-size header length */
- hdr->heap_size = (size_t)H5HF_HEADER_SIZE(hdr);
-
- /* Check for I/O filter information to decode */
- if(hdr->filter_len > 0)
- /* Add the variable-len I/O filter information */
- hdr->heap_size += (size_t)(hdr->sizeof_size /* Size of size for filtered root direct block */
- + (unsigned)4 /* Size of filter mask for filtered root direct block */
- + hdr->filter_len); /* Size of encoded I/O filter info */
-
- /* Check if we need to resize the buffer */
- if(hdr->heap_size > buf_size) {
- /* Re-size current buffer */
- if(NULL == (buf = (uint8_t *)H5WB_actual(wb, hdr->heap_size)))
- HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, NULL, "can't get actual buffer")
- buf_size = hdr->heap_size;
- } /* end if */
-
- /* Read the whole header, possibly with filter info */
- /* (Can't use H5F_read_check_metadata() since the length from the
- * minimum-sized header info might be incorrect. -QAK)
- */
- if(H5F_block_read(udata->f, H5FD_MEM_FHEAP_HDR, addr, hdr->heap_size, dxpl_id, buf) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_READERROR, NULL, "can't read remainder of fractal heap header")
-
- /* Retrieve stored and computed checksums */
- H5F_get_checksums(buf, hdr->heap_size, &stored_chksum, &computed_chksum);
+ /* Compute the 'base' size of the fractal heap header on disk */
+ size = (size_t)H5HF_HEADER_SIZE(hdr);
- /* Verify checksum */
- if(stored_chksum == computed_chksum)
- break;
- } while (--tries);
+ /* the size we have just calculated presumes that there is no I/O
+ * filter information in the header. If there is no filter information,
+ * the deserialize operation should succeed.
+ *
+ * If there is filter information, the first attempt to deserialize
+ * the header will reveal this. In this case, we will be unable to
+ * deserialize the header as the supplied image will be too small.
+ * However, we will make note of the correct size and report success
+ * anyway.
+ *
+ * When H5C_load_entry() calls H5HF__cache_hdr_image_len(), we will report
+ * the correct size. Since the H5C__CLASS_SPECULATIVE_LOAD_FLAG is set,
+ * this will prompt H5C_load_entry() to load the correct size image,
+ * discard the result of the first attempt at deserialization, and
+ * call this routine a second time to deserialize the correct size
+ * buffer.
+ */
+ HDassert(size <= len);
- if(tries == 0)
- HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, NULL, "incorrect metadata checksum after all tries (%u) for fractal heap header", max_tries)
+ /* Magic number */
+ if(HDmemcmp(image, H5HF_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC))
+ HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, NULL, "wrong fractal heap header signature")
+ image += H5_SIZEOF_MAGIC;
- /* Calculate and track the # of retry */
- retries += (max_tries - tries);
- if(retries) /* Does not track 0 retry */
- if(H5F_track_metadata_read_retries(udata->f, H5AC_FHEAP_HDR_ID, retries) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "cannot track read tries = %u ", retries)
+ /* Version */
+ if(*image++ != H5HF_HDR_VERSION)
+ HGOTO_ERROR(H5E_HEAP, H5E_VERSION, NULL, "wrong fractal heap header version")
- /* Reset pointer into [possibly] re-sized buffer */
- /* (Skip over information decoded earlier) */
- p = buf + min_size;
+ /* General heap information */
+ UINT16DECODE(image, hdr->id_len); /* Heap ID length */
+ UINT16DECODE(image, hdr->filter_len); /* I/O filters' encoded length */
/* Heap status flags */
/* (bit 0: "huge" object IDs have wrapped) */
/* (bit 1: checksum direct blocks) */
- heap_flags = *p++;
+ heap_flags = *image++;
hdr->huge_ids_wrapped = heap_flags & H5HF_HDR_FLAGS_HUGE_ID_WRAPPED;
hdr->checksum_dblocks = heap_flags & H5HF_HDR_FLAGS_CHECKSUM_DBLOCKS;
/* "Huge" object information */
- UINT32DECODE(p, hdr->max_man_size); /* Max. size of "managed" objects */
- H5F_DECODE_LENGTH(udata->f, p, hdr->huge_next_id); /* Next ID to use for "huge" object */
- H5F_addr_decode(udata->f, &p, &hdr->huge_bt2_addr); /* Address of "huge" object tracker B-tree */
+ UINT32DECODE(image, hdr->max_man_size); /* Max. size of "managed" objects */
+ H5F_DECODE_LENGTH(udata->f, image, hdr->huge_next_id); /* Next ID to use for "huge" object */
+ H5F_addr_decode(udata->f, &image, &hdr->huge_bt2_addr); /* Address of "huge" object tracker B-tree */
/* "Managed" object free space information */
- H5F_DECODE_LENGTH(udata->f, p, hdr->total_man_free); /* Internal free space in managed direct blocks */
- H5F_addr_decode(udata->f, &p, &hdr->fs_addr); /* Address of free section header */
+ H5F_DECODE_LENGTH(udata->f, image, hdr->total_man_free); /* Internal free space in managed direct blocks */
+ H5F_addr_decode(udata->f, &image, &hdr->fs_addr); /* Address of free section header */
/* Heap statistics */
- H5F_DECODE_LENGTH(udata->f, p, hdr->man_size);
- H5F_DECODE_LENGTH(udata->f, p, hdr->man_alloc_size);
- H5F_DECODE_LENGTH(udata->f, p, hdr->man_iter_off);
- H5F_DECODE_LENGTH(udata->f, p, hdr->man_nobjs);
- H5F_DECODE_LENGTH(udata->f, p, hdr->huge_size);
- H5F_DECODE_LENGTH(udata->f, p, hdr->huge_nobjs);
- H5F_DECODE_LENGTH(udata->f, p, hdr->tiny_size);
- H5F_DECODE_LENGTH(udata->f, p, hdr->tiny_nobjs);
+ H5F_DECODE_LENGTH(udata->f, image, hdr->man_size);
+ H5F_DECODE_LENGTH(udata->f, image, hdr->man_alloc_size);
+ H5F_DECODE_LENGTH(udata->f, image, hdr->man_iter_off);
+ H5F_DECODE_LENGTH(udata->f, image, hdr->man_nobjs);
+ H5F_DECODE_LENGTH(udata->f, image, hdr->huge_size);
+ H5F_DECODE_LENGTH(udata->f, image, hdr->huge_nobjs);
+ H5F_DECODE_LENGTH(udata->f, image, hdr->tiny_size);
+ H5F_DECODE_LENGTH(udata->f, image, hdr->tiny_nobjs);
/* Managed objects' doubling-table info */
- if(H5HF__dtable_decode(udata->f, &p, &(hdr->man_dtable)) < 0)
+ if(H5HF__dtable_decode(hdr->f, &image, &(hdr->man_dtable)) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTENCODE, NULL, "unable to encode managed obj. doubling table info")
+ /* Sanity check */
+ /* (allow for checksum not decoded yet) */
+ HDassert((size_t)(image - (const uint8_t *)_image) == (size - H5HF_SIZEOF_CHKSUM));
+
/* Check for I/O filter information to decode */
if(hdr->filter_len > 0) {
+ size_t filter_info_size; /* Size of filter information */
H5O_pline_t *pline; /* Pipeline information from the header on disk */
+ /* Compute the size of the extra filter information */
+ filter_info_size = (size_t)(hdr->sizeof_size /* Size of size for filtered root direct block */
+ + (unsigned)4 /* Size of filter mask for filtered root direct block */
+ + hdr->filter_len); /* Size of encoded I/O filter info */
+
+ /* Compute the heap header's size */
+ hdr->heap_size = size + filter_info_size;
+
+ if(size == len)
+ /* we were supplied with too small a buffer -- goto done
+ * and let H5C_load_entry() retry with a larger buffer
+ */
+ HGOTO_DONE((void *)hdr)
+
+ else
+ if((size + filter_info_size) != len)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "bad image len")
+
/* Decode the size of a filtered root direct block */
- H5F_DECODE_LENGTH(udata->f, p, hdr->pline_root_direct_size);
+ H5F_DECODE_LENGTH(udata->f, image, hdr->pline_root_direct_size);
/* Decode the filter mask for a filtered root direct block */
- UINT32DECODE(p, hdr->pline_root_direct_filter_mask);
+ UINT32DECODE(image, hdr->pline_root_direct_filter_mask);
/* Decode I/O filter information */
- if(NULL == (pline = (H5O_pline_t *)H5O_msg_decode(udata->f, udata->dxpl_id, NULL, H5O_PLINE_ID, p)))
+ if(NULL == (pline = (H5O_pline_t *)H5O_msg_decode(hdr->f, udata->dxpl_id, NULL, H5O_PLINE_ID, image)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTDECODE, NULL, "can't decode I/O pipeline filters")
- p += hdr->filter_len;
+
+ image += hdr->filter_len;
/* Copy the information into the header's I/O pipeline structure */
if(NULL == H5O_msg_copy(H5O_PLINE_ID, pline, &(hdr->pline)))
@@ -448,354 +608,441 @@ H5HF_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
/* Release the space allocated for the I/O pipeline filters */
H5O_msg_free(H5O_PLINE_ID, pline);
} /* end if */
+ else
+ /* Set the heap header's size */
+ hdr->heap_size = size;
+
+ /* checksum verification already done in verify_chksum cb */
- /* Already decoded and compared stored checksum earlier, when reading */
+ /* Metadata checksum */
+ UINT32DECODE(image, stored_chksum);
/* Sanity check */
- HDassert((size_t)(p - (const uint8_t *)buf) == (hdr->heap_size - H5_SIZEOF_CHKSUM));
+ HDassert((size_t)(image - (const uint8_t *)_image) == hdr->heap_size);
/* Finish initialization of heap header */
if(H5HF_hdr_finish_init(hdr) < 0)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, NULL, "can't finish initializing shared fractal heap header")
/* Set return value */
- ret_value = hdr;
+ ret_value = (void *)hdr;
done:
- /* Release resources */
- if(wb && H5WB_unwrap(wb) < 0)
- HDONE_ERROR(H5E_HEAP, H5E_CLOSEERROR, NULL, "can't close wrapped buffer")
if(!ret_value && hdr)
if(H5HF_hdr_free(hdr) < 0)
HDONE_ERROR(H5E_HEAP, H5E_CANTRELEASE, NULL, "unable to release fractal heap header")
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5HF_cache_hdr_load() */ /*lint !e818 Can't make udata a pointer to const */
+} /* end H5HF__cache_hdr_deserialize() */
/*-------------------------------------------------------------------------
- * Function: H5HF_cache_hdr_flush
+ * Function: H5HF__cache_hdr_image_len
*
- * Purpose: Flushes a dirty fractal heap header to disk.
+ * Purpose: Return the actual size of the fractal heap header on
+ * disk image.
*
- * Return: Non-negative on success/Negative on failure
+ * If the header contains filter information, this size will be
+ * larger than the value returned by H5HF__cache_hdr_get_load_size().
*
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 24 2006
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: John Mainzer
+ * 6/21/14
*
*-------------------------------------------------------------------------
*/
-static herr_t
-H5HF_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HF_hdr_t *hdr, unsigned H5_ATTR_UNUSED * flags_ptr)
+static herr_t
+H5HF__cache_hdr_image_len(const void *_thing, size_t *image_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr)
{
- H5WB_t *wb = NULL; /* Wrapped buffer for header data */
- uint8_t hdr_buf[H5HF_HDR_BUF_SIZE]; /* Buffer for header */
- herr_t ret_value = SUCCEED; /* Return value */
+ const H5HF_hdr_t *hdr = (const H5HF_hdr_t *)_thing; /* Fractal heap info */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC_NOERR
- /* check arguments */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
+ /* Sanity checks */
HDassert(hdr);
+ HDassert(hdr->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(hdr->cache_info.type == H5AC_FHEAP_HDR);
+ HDassert(image_len);
- if(hdr->cache_info.is_dirty) {
- uint8_t *buf; /* Temporary raw data buffer */
- uint8_t *p; /* Pointer into raw data buffer */
- size_t size; /* Header size on disk */
- uint8_t heap_flags; /* Status flags for heap */
- uint32_t metadata_chksum; /* Computed metadata checksum value */
-
-#ifndef NDEBUG
-{
- /* Verify that flush dependencies are working correctly. Do this
- * by verifying that either:
- *
- * 1) the header has a root iblock, and that the root iblock and all
- * of its children are clean, or
- *
- * 2) The header has a root dblock, which is clean, or
- *
- * 3) The heap is empty, and thus the header has neither a root
- * iblock no a root dblock. In this case, the flush ordering
- * constraint is met by default.
- *
- * Do this with a call to H5HF__cache_verify_hdr_descendants_clean().
- */
- hbool_t descendants_clean = TRUE;
+ *image_len = hdr->heap_size;
- if(H5HF__cache_verify_hdr_descendants_clean(f, dxpl_id, hdr, &descendants_clean) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_SYSTEM, FAIL, "can't verify hdr descendants clean.")
- HDassert(descendants_clean);
-}
-#endif /* NDEBUG */
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5HF__cache_hdr_image_len() */
- /* Set the shared heap header's file context for this operation */
- hdr->f = f;
-
- /* Wrap the local buffer for serialized header info */
- if(NULL == (wb = H5WB_wrap(hdr_buf, sizeof(hdr_buf))))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't wrap buffer")
-
- /* Compute the size of the heap header on disk */
- size = hdr->heap_size;
-
- /* Get a pointer to a buffer that's large enough for serialized header */
- if(NULL == (buf = (uint8_t *)H5WB_actual(wb, size)))
- HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "can't get actual buffer")
-
- /* Get temporary pointer to serialized header */
- p = buf;
-
- /* Magic number */
- HDmemcpy(p, H5HF_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC);
- p += H5_SIZEOF_MAGIC;
-
- /* Version # */
- *p++ = H5HF_HDR_VERSION;
-
- /* General heap information */
- UINT16ENCODE(p, hdr->id_len); /* Heap ID length */
- UINT16ENCODE(p, hdr->filter_len); /* I/O filters' encoded length */
-
- /* Heap status flags */
- /* (bit 0: "huge" object IDs have wrapped) */
- /* (bit 1: checksum direct blocks) */
- heap_flags = 0;
- heap_flags = (uint8_t)(heap_flags | (hdr->huge_ids_wrapped ? H5HF_HDR_FLAGS_HUGE_ID_WRAPPED : 0));
- heap_flags = (uint8_t)(heap_flags | (hdr->checksum_dblocks ? H5HF_HDR_FLAGS_CHECKSUM_DBLOCKS : 0));
- *p++ = heap_flags;
-
- /* "Huge" object information */
- UINT32ENCODE(p, hdr->max_man_size); /* Max. size of "managed" objects */
- H5F_ENCODE_LENGTH(f, p, hdr->huge_next_id); /* Next ID to use for "huge" object */
- H5F_addr_encode(f, &p, hdr->huge_bt2_addr); /* Address of "huge" object tracker B-tree */
-
- /* "Managed" object free space information */
- H5F_ENCODE_LENGTH(f, p, hdr->total_man_free); /* Internal free space in managed direct blocks */
- H5F_addr_encode(f, &p, hdr->fs_addr); /* Address of free section header */
-
- /* Heap statistics */
- H5F_ENCODE_LENGTH(f, p, hdr->man_size);
- H5F_ENCODE_LENGTH(f, p, hdr->man_alloc_size);
- H5F_ENCODE_LENGTH(f, p, hdr->man_iter_off);
- H5F_ENCODE_LENGTH(f, p, hdr->man_nobjs);
- H5F_ENCODE_LENGTH(f, p, hdr->huge_size);
- H5F_ENCODE_LENGTH(f, p, hdr->huge_nobjs);
- H5F_ENCODE_LENGTH(f, p, hdr->tiny_size);
- H5F_ENCODE_LENGTH(f, p, hdr->tiny_nobjs);
-
- /* Managed objects' doubling-table info */
- if(H5HF__dtable_encode(hdr->f, &p, &(hdr->man_dtable)) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTENCODE, FAIL, "unable to encode managed obj. doubling table info")
-
- /* Check for I/O filter information to encode */
- if(hdr->filter_len > 0) {
- /* Encode the size of a filtered root direct block */
- H5F_ENCODE_LENGTH(f, p, hdr->pline_root_direct_size);
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF__cache_hdr_pre_serialize
+ *
+ * Purpose: As best I can tell, fractal heap header blocks are always
+ * allocated in real file space. Thus this routine simply verifies
+ * this, verifies that the len parameter contains the expected
+ * value, and returns an error if either of these checks fail.
+ *
+ * When compiled in debug mode, the function also verifies that all
+ * indirect and direct blocks that are children of the header are
+ * either clean, or not in the metadata cache.
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: John Mainzer
+ * 6/21/14
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HF__cache_hdr_pre_serialize(const H5F_t *f, hid_t dxpl_id, void *_thing,
+ haddr_t addr, size_t len, size_t H5_ATTR_UNUSED compressed_len,
+ haddr_t H5_ATTR_UNUSED *new_addr, size_t H5_ATTR_UNUSED *new_len,
+ size_t H5_ATTR_UNUSED *new_compressed_len, unsigned *flags)
+{
+ H5HF_hdr_t *hdr = (H5HF_hdr_t *)_thing; /* Fractal heap info */
+ herr_t ret_value = SUCCEED; /* Return value */
- /* Encode the filter mask for a filtered root direct block */
- UINT32ENCODE(p, hdr->pline_root_direct_filter_mask);
+ FUNC_ENTER_STATIC
- /* Encode I/O filter information */
- if(H5O_msg_encode(hdr->f, H5O_PLINE_ID, FALSE, p, &(hdr->pline)) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTENCODE, FAIL, "can't encode I/O pipeline fiters")
- p += hdr->filter_len;
- } /* end if */
+ /* Sanity checks */
+ HDassert(f);
+ HDassert(hdr);
+ HDassert(hdr->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(hdr->cache_info.type == H5AC_FHEAP_HDR);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(addr == hdr->heap_addr);
+ HDassert(new_addr);
+ HDassert(new_len);
+ HDassert(flags);
- /* Compute metadata checksum */
- metadata_chksum = H5_checksum_metadata(buf, (size_t)(p - buf), 0);
+#ifndef NDEBUG
+{
+ hbool_t descendants_clean = TRUE;
- /* Metadata checksum */
- UINT32ENCODE(p, metadata_chksum);
+ /* Verify that flush dependencies are working correctly. Do this
+ * by verifying that either:
+ *
+ * 1) the header has a root iblock, and that the root iblock and all
+ * of its children are clean, or
+ *
+ * 2) The header has a root dblock, which is clean, or
+ *
+ * 3) The heap is empty, and thus the header has neither a root
+ * iblock no a root dblock. In this case, the flush ordering
+ * constraint is met by default.
+ *
+ * Do this with a call to H5HF__cache_verify_hdr_descendants_clean().
+ */
+ if(H5HF__cache_verify_hdr_descendants_clean((H5F_t *)f, dxpl_id, hdr, &descendants_clean) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_SYSTEM, FAIL, "can't verify hdr descendants clean.")
+ HDassert(descendants_clean);
+}
+#endif /* NDEBUG */
- /* Write the heap header. */
- HDassert((size_t)(p - buf) == size);
- if(H5F_block_write(f, H5FD_MEM_FHEAP_HDR, addr, size, dxpl_id, buf) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFLUSH, FAIL, "unable to save fractal heap header to disk")
+ if(H5F_IS_TMP_ADDR(f, addr))
+ HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "addr in temporary space?!?.");
- hdr->cache_info.is_dirty = FALSE;
- } /* end if */
+ if(len != hdr->heap_size)
+ HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "unexpected image len.");
- if(destroy)
- if(H5HF_cache_hdr_dest(f, hdr) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy fractal heap header")
+ *flags = 0;
done:
- /* Release resources */
- if(wb && H5WB_unwrap(wb) < 0)
- HDONE_ERROR(H5E_HEAP, H5E_CLOSEERROR, FAIL, "can't close wrapped buffer")
-
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5HF_cache_hdr_flush() */
+} /* end H5HF__cache_hdr_pre_serialize() */
/*-------------------------------------------------------------------------
- * Function: H5HF_cache_hdr_dest
+ * Function: H5HF__cache_hdr_serialize
*
- * Purpose: Destroys a fractal heap header in memory.
+ * Purpose: Construct the on disk image of the header, and place it in
+ * the buffer pointed to by image. Return SUCCEED on success,
+ * and FAIL on failure.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Success: SUCCEED
+ * Failure: FAIL
*
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 24 2006
+ * Programmer: John Mainzer
+ * 6/21/14
*
*-------------------------------------------------------------------------
*/
-static herr_t
-H5HF_cache_hdr_dest(H5F_t *f, H5HF_hdr_t *hdr)
+static herr_t
+H5HF__cache_hdr_serialize(const H5F_t *f, void *_image, size_t len,
+ void *_thing)
{
+ H5HF_hdr_t *hdr = (H5HF_hdr_t *)_thing; /* Fractal heap info */
+ uint8_t *image = (uint8_t *)_image; /* Pointer into raw data buffer */
+ uint8_t heap_flags; /* Status flags for heap */
+ uint32_t metadata_chksum; /* Computed metadata checksum value */
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
- /*
- * Check arguments.
- */
+ /* Sanity checks */
+ HDassert(f);
+ HDassert(image);
HDassert(hdr);
- HDassert(hdr->rc == 0);
+ HDassert(hdr->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(hdr->cache_info.type == H5AC_FHEAP_HDR);
+ HDassert(len == hdr->heap_size);
+
+ /* Set the shared heap header's file context for this operation */
+ hdr->f = f;
+
+ /* Magic number */
+ HDmemcpy(image, H5HF_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ image += H5_SIZEOF_MAGIC;
- /* If we're going to free the space on disk, the address must be valid */
- HDassert(!hdr->cache_info.free_file_space_on_destroy || H5F_addr_defined(hdr->cache_info.addr));
+ /* Version # */
+ *image++ = H5HF_HDR_VERSION;
- /* Check for freeing file space for heap header */
- if(hdr->cache_info.free_file_space_on_destroy) {
- /* Release the space on disk */
- /* (XXX: Nasty usage of internal DXPL value! -QAK) */
- if(H5MF_xfree(f, H5FD_MEM_FHEAP_HDR, H5AC_dxpl_id, hdr->cache_info.addr, (hsize_t)hdr->heap_size) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap header")
+ /* General heap information */
+ UINT16ENCODE(image, hdr->id_len); /* Heap ID length */
+ UINT16ENCODE(image, hdr->filter_len); /* I/O filters' encoded length */
+
+ /* Heap status flags */
+ /* (bit 0: "huge" object IDs have wrapped) */
+ /* (bit 1: checksum direct blocks) */
+ heap_flags = 0;
+ heap_flags = (uint8_t)(heap_flags | (hdr->huge_ids_wrapped ? H5HF_HDR_FLAGS_HUGE_ID_WRAPPED : 0));
+ heap_flags = (uint8_t)(heap_flags | (hdr->checksum_dblocks ? H5HF_HDR_FLAGS_CHECKSUM_DBLOCKS : 0));
+ *image++ = heap_flags;
+
+ /* "Huge" object information */
+ UINT32ENCODE(image, hdr->max_man_size); /* Max. size of "managed" objects */
+ H5F_ENCODE_LENGTH(f, image, hdr->huge_next_id); /* Next ID to use for "huge" object */
+ H5F_addr_encode(f, &image, hdr->huge_bt2_addr); /* Address of "huge" object tracker B-tree */
+
+ /* "Managed" object free space information */
+ H5F_ENCODE_LENGTH(f, image, hdr->total_man_free); /* Internal free space in managed direct blocks */
+ H5F_addr_encode(f, &image, hdr->fs_addr); /* Address of free section header */
+
+ /* Heap statistics */
+ H5F_ENCODE_LENGTH(f, image, hdr->man_size);
+ H5F_ENCODE_LENGTH(f, image, hdr->man_alloc_size);
+ H5F_ENCODE_LENGTH(f, image, hdr->man_iter_off);
+ H5F_ENCODE_LENGTH(f, image, hdr->man_nobjs);
+ H5F_ENCODE_LENGTH(f, image, hdr->huge_size);
+ H5F_ENCODE_LENGTH(f, image, hdr->huge_nobjs);
+ H5F_ENCODE_LENGTH(f, image, hdr->tiny_size);
+ H5F_ENCODE_LENGTH(f, image, hdr->tiny_nobjs);
+
+ /* Managed objects' doubling-table info */
+ if(H5HF__dtable_encode(hdr->f, &image, &(hdr->man_dtable)) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTENCODE, FAIL, "unable to encode managed obj. doubling table info")
+
+ /* Check for I/O filter information to encode */
+ if(hdr->filter_len > 0) {
+ /* Encode the size of a filtered root direct block */
+ H5F_ENCODE_LENGTH(f, image, hdr->pline_root_direct_size);
+
+ /* Encode the filter mask for a filtered root direct block */
+ UINT32ENCODE(image, hdr->pline_root_direct_filter_mask);
+
+ /* Encode I/O filter information */
+ if(H5O_msg_encode(hdr->f, H5O_PLINE_ID, FALSE, image, &(hdr->pline)) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTENCODE, FAIL, "can't encode I/O pipeline fiters")
+ image += hdr->filter_len;
} /* end if */
- /* Free the shared info itself */
- if(H5HF_hdr_free(hdr) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "unable to release fractal heap header")
+ /* Compute metadata checksum */
+ metadata_chksum = H5_checksum_metadata(_image, (size_t)(image - (uint8_t *)_image), 0);
+
+ /* Metadata checksum */
+ UINT32ENCODE(image, metadata_chksum);
+
+ /* sanity check */
+ HDassert((size_t)(image - (uint8_t *)_image) == len);
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5HF_cache_hdr_dest() */
+} /* end H5HF__cache_hdr_serialize() */
+
+/***************************************/
+/* no H5HF__cache_hdr_notify() function */
+/***************************************/
/*-------------------------------------------------------------------------
- * Function: H5HF_cache_hdr_clear
+ * Function: H5HF__cache_hdr_free_icr
*
- * Purpose: Mark a fractal heap header in memory as non-dirty.
+ * Purpose: Free the in core representation of the fractal heap header.
*
- * Return: Non-negative on success/Negative on failure
+ * This routine frees just the header itself, not the
+ * associated version 2 B-Tree, the associated Free Space Manager,
+ * nor the indirect/direct block tree that is rooted in the header.
*
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 24 2006
+ * This routine also does not free the file space that may
+ * be allocated to the header.
+ *
+ * Note: The metadata cache sets the object's cache_info.magic to
+ * H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC before calling a free_icr
+ * callback (checked in assert).
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: John Mainzer
+ * 6/21/14
*
*-------------------------------------------------------------------------
*/
-static herr_t
-H5HF_cache_hdr_clear(H5F_t *f, H5HF_hdr_t *hdr, hbool_t destroy)
+static herr_t
+H5HF__cache_hdr_free_icr(void *_thing)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ H5HF_hdr_t *hdr = (H5HF_hdr_t *)_thing; /* Fractal heap info */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
- /*
- * Check arguments.
- */
+ /* Sanity checks */
HDassert(hdr);
+ HDassert(hdr->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC);
+ HDassert(hdr->cache_info.type == H5AC_FHEAP_HDR);
+ HDassert(hdr->rc == 0);
- /* Reset the dirty flag. */
- hdr->cache_info.is_dirty = FALSE;
-
- if(destroy)
- if(H5HF_cache_hdr_dest(f, hdr) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy fractal heap header")
+ if(H5HF_hdr_free(hdr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "unable to release fractal heap header")
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5HF_cache_hdr_clear() */
+} /* end H5HF__cache_hdr_free_icr() */
+
+/***********************************************************/
+/* metadata cache callback definitions for indirect blocks */
+/***********************************************************/
/*-------------------------------------------------------------------------
- * Function: H5HF_cache_hdr_size
+ * Function: H5HF__cache_iblock_get_load_size()
*
- * Purpose: Compute the size in bytes of a fractal heap header
- * on disk, and return it in *size_ptr. On failure,
- * the value of *size_ptr is undefined.
+ * Purpose: Compute the size of the on disk image of the indirect
+ * block, and place this value in *image_len.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Success: SUCCEED
+ * Failure: FAIL
*
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 24 2006
+ * Programmer: John Mainzer
+ * 6/21/14
*
*-------------------------------------------------------------------------
*/
-static herr_t
-H5HF_cache_hdr_size(const H5F_t H5_ATTR_UNUSED *f, const H5HF_hdr_t *hdr, size_t *size_ptr)
+static herr_t
+H5HF__cache_iblock_get_load_size(const void *_image, void *_udata, size_t *image_len, size_t *actual_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr)
{
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ H5HF_iblock_cache_ud_t *udata = (H5HF_iblock_cache_ud_t *)_udata; /* User data for callback */
- /* Check arguments */
- HDassert(f);
- HDassert(hdr);
- HDassert(size_ptr);
+ FUNC_ENTER_STATIC_NOERR
- /* Set size value */
- *size_ptr = hdr->heap_size;
+ /* Sanity checks */
+ HDassert(udata);
+ HDassert(udata->par_info);
+ HDassert(udata->par_info->hdr);
+ HDassert(image_len);
+
+ if(image == NULL)
+ *image_len = (size_t)H5HF_MAN_INDIRECT_SIZE(udata->par_info->hdr, *udata->nrows);
+ else {
+ HDassert(actual_len);
+ HDassert(*actual_len == *image_len);
+ }
FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5HF_cache_hdr_size() */
+} /* end H5HF__cache_iblock_get_load_size() */
/***********************************************************/
/* metadata cache callback definitions for indirect blocks */
/***********************************************************/
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF__cache_iblock_verify_chksum
+ *
+ * Purpose: Verify the computed checksum of the data structure is the
+ * same as the stored chksum.
+ *
+ * Return: Success: TRUE/FALSE
+ * Failure: Negative
+ *
+ * Programmer: Vailin Choi; Aug 2015
+ *
+ *-------------------------------------------------------------------------
+ */
+static htri_t
+H5HF__cache_iblock_verify_chksum(const void *_image, size_t len, void H5_ATTR_UNUSED *_udata)
+{
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ uint32_t stored_chksum; /* Stored metadata checksum value */
+ uint32_t computed_chksum; /* Computed metadata checksum value */
+ htri_t ret_value = TRUE; /* Return value */
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Check arguments */
+ HDassert(image);
+
+ /* Get stored and computed checksums */
+ H5F_get_checksums(image, len, &stored_chksum, &computed_chksum);
+
+ if(stored_chksum != computed_chksum)
+ ret_value = FALSE;
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF__cache_iblock_verify_chksum() */
+
/*-------------------------------------------------------------------------
- * Function: H5HF_cache_iblock_load
+ * Function: H5HF__cache_iblock_deserialize
*
- * Purpose: Loads a fractal heap indirect block from the disk.
+ * Purpose: Given a buffer containing the on disk image of the indirect
+ * block, allocate an instance of H5HF_indirect_t, load the data
+ * in the buffer into this new instance, and return a pointer to
+ * it.
*
- * Return: Success: Pointer to a new fractal heap indirect block
+ * As best I can tell, the size of the indirect block image is fully
+ * know before the image is loaded, so this function should succeed
+ * unless the image is corrupt or memory allocation fails.
*
+ * Return: Success: Pointer to in core representation
* Failure: NULL
*
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 27 2006
+ * Programmer: John Mainzer
+ * 6/21/14
*
*-------------------------------------------------------------------------
*/
-static H5HF_indirect_t *
-H5HF_cache_iblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
+static void *
+H5HF__cache_iblock_deserialize(const void *_image, size_t len, void *_udata,
+ hbool_t H5_ATTR_UNUSED *dirty)
{
H5HF_hdr_t *hdr; /* Shared fractal heap information */
- H5HF_iblock_cache_ud_t *udata = (H5HF_iblock_cache_ud_t *)_udata; /* user data for callback */
- H5HF_indirect_t *iblock = NULL; /* Indirect block info */
- H5WB_t *wb = NULL; /* Wrapped buffer for indirect block data */
- uint8_t iblock_buf[H5HF_IBLOCK_BUF_SIZE]; /* Buffer for indirect block */
- uint8_t *buf; /* Temporary buffer */
- const uint8_t *p; /* Pointer into raw data buffer */
+ H5HF_iblock_cache_ud_t *udata = (H5HF_iblock_cache_ud_t *)_udata; /* User data for callback */
+ H5HF_indirect_t *iblock = NULL; /* Indirect block info */
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
haddr_t heap_addr; /* Address of heap header in the file */
+ uint32_t stored_chksum; /* Stored metadata checksum value */
unsigned u; /* Local index variable */
- H5HF_indirect_t *ret_value; /* Return value */
+ void * ret_value; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
- /* Check arguments */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
+ /* Sanity checks */
+ HDassert(image);
HDassert(udata);
-
- /* Allocate space for the fractal heap indirect block */
- if(NULL == (iblock = H5FL_CALLOC(H5HF_indirect_t)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
-
- /* Get the pointer to the shared heap header */
+ HDassert(dirty);
hdr = udata->par_info->hdr;
+ HDassert(hdr->f);
/* Set the shared heap header's file context for this operation */
hdr->f = udata->f;
+ /* Allocate space for the fractal heap indirect block */
+ if(NULL == (iblock = H5FL_CALLOC(H5HF_indirect_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+
/* Share common heap information */
iblock->hdr = hdr;
if(H5HF_hdr_incr(hdr) < 0)
@@ -806,35 +1053,23 @@ H5HF_cache_iblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
iblock->nrows = *udata->nrows;
iblock->nchildren = 0;
- /* Wrap the local buffer for serialized indirect block */
- if(NULL == (wb = H5WB_wrap(iblock_buf, sizeof(iblock_buf))))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, NULL, "can't wrap buffer")
-
/* Compute size of indirect block */
iblock->size = H5HF_MAN_INDIRECT_SIZE(hdr, iblock->nrows);
- /* Get a pointer to a buffer that's large enough for serialized indirect block */
- if(NULL == (buf = (uint8_t *)H5WB_actual(wb, iblock->size)))
- HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, NULL, "can't get actual buffer")
-
- /* Read and validate indirect block from disk */
- if(H5F_read_check_metadata(f, dxpl_id, H5FD_MEM_FHEAP_IBLOCK, H5AC_FHEAP_IBLOCK_ID, addr, iblock->size, iblock->size, buf) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, NULL, "incorrect metadata checksum for fractal heap indirect block")
-
- /* Get temporary pointer to serialized indirect block */
- p = buf;
+ /* sanity check */
+ HDassert(iblock->size == len);
/* Magic number */
- if(HDmemcmp(p, H5HF_IBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "wrong fractal heap indirect block signature")
- p += H5_SIZEOF_MAGIC;
+ if(HDmemcmp(image, H5HF_IBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC))
+ HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, NULL, "wrong fractal heap indirect block signature")
+ image += H5_SIZEOF_MAGIC;
/* Version */
- if(*p++ != H5HF_IBLOCK_VERSION)
+ if(*image++ != H5HF_IBLOCK_VERSION)
HGOTO_ERROR(H5E_HEAP, H5E_VERSION, NULL, "wrong fractal heap direct block version")
/* Address of heap that owns this block */
- H5F_addr_decode(udata->f, &p, &heap_addr);
+ H5F_addr_decode(udata->f, &image, &heap_addr);
if(H5F_addr_ne(heap_addr, hdr->heap_addr))
HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "incorrect heap header address for direct block")
@@ -859,7 +1094,7 @@ H5HF_cache_iblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
} /* end else */
/* Offset of heap within the heap's address space */
- UINT64DECODE_VAR(p, iblock->block_off, hdr->heap_off_size);
+ UINT64DECODE_VAR(image, iblock->block_off, hdr->heap_off_size);
/* Allocate & decode child block entry tables */
HDassert(iblock->nrows > 0);
@@ -881,7 +1116,7 @@ H5HF_cache_iblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
for(u = 0; u < (iblock->nrows * hdr->man_dtable.cparam.width); u++) {
/* Decode child block address */
- H5F_addr_decode(udata->f, &p, &(iblock->ents[u].addr));
+ H5F_addr_decode(udata->f, &image, &(iblock->ents[u].addr));
/* Check for heap with I/O filters */
if(hdr->filter_len > 0) {
@@ -891,7 +1126,7 @@ H5HF_cache_iblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
/* Decode extra information for direct blocks */
if(u < (hdr->man_dtable.max_direct_rows * hdr->man_dtable.cparam.width)) {
/* Size of filtered direct block */
- H5F_DECODE_LENGTH(udata->f, p, iblock->filt_ents[u].size);
+ H5F_DECODE_LENGTH(udata->f, image, iblock->filt_ents[u].size);
/* Sanity check */
/* (either both the address & size are defined or both are
@@ -901,7 +1136,7 @@ H5HF_cache_iblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
|| (!H5F_addr_defined(iblock->ents[u].addr) && iblock->filt_ents[u].size == 0));
/* I/O filter mask for filtered direct block */
- UINT32DECODE(p, iblock->filt_ents[u].filter_mask);
+ UINT32DECODE(image, iblock->filt_ents[u].filter_mask);
} /* end if */
} /* end if */
@@ -915,14 +1150,17 @@ H5HF_cache_iblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
/* Sanity check */
HDassert(iblock->nchildren); /* indirect blocks w/no children should have been deleted */
- /* Already decoded and compared stored checksum earlier, when reading */
+ /* checksum verification already done by verify_chksum cb */
+
+ /* Metadata checksum */
+ UINT32DECODE(image, stored_chksum);
/* Sanity check */
- HDassert((size_t)(p - (const uint8_t *)buf) == (iblock->size - H5_SIZEOF_CHKSUM));
+ HDassert((size_t)(image - (const uint8_t *)_image) == iblock->size);
/* Check if we have any indirect block children */
if(iblock->nrows > hdr->man_dtable.max_direct_rows) {
- unsigned indir_rows; /* Number of indirect rows in this indirect block */
+ unsigned indir_rows;/* Number of indirect rows in this indirect block */
/* Compute the number of indirect rows for this indirect block */
indir_rows = iblock->nrows - hdr->man_dtable.max_direct_rows;
@@ -935,343 +1173,323 @@ H5HF_cache_iblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
iblock->child_iblocks = NULL;
/* Set return value */
- ret_value = iblock;
+ ret_value = (void *)iblock;
done:
- /* Release resources */
- if(wb && H5WB_unwrap(wb) < 0)
- HDONE_ERROR(H5E_HEAP, H5E_CLOSEERROR, NULL, "can't close wrapped buffer")
if(!ret_value && iblock)
if(H5HF_man_iblock_dest(iblock) < 0)
HDONE_ERROR(H5E_HEAP, H5E_CANTFREE, NULL, "unable to destroy fractal heap indirect block")
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5HF_cache_iblock_load() */
+} /* end H5HF__cache_iblock_deserialize() */
/*-------------------------------------------------------------------------
- * Function: H5HF_cache_iblock_flush
+ * Function: H5HF__cache_iblock_image_len
*
- * Purpose: Flushes a dirty fractal heap indirect block to disk.
+ * Purpose: Return the size of the on disk image of the iblock.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Success: SUCCEED
+ * Failure: FAIL
*
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Mar 6 2006
+ * Programmer: John Mainzer
+ * 6/21/14
*
*-------------------------------------------------------------------------
*/
-static herr_t
-H5HF_cache_iblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HF_indirect_t *iblock, unsigned H5_ATTR_UNUSED * flags_ptr)
+static herr_t
+H5HF__cache_iblock_image_len(const void *_thing, size_t *image_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr)
{
- H5WB_t *wb = NULL; /* Wrapped buffer for indirect block data */
- uint8_t iblock_buf[H5HF_IBLOCK_BUF_SIZE]; /* Buffer for indirect block */
- herr_t ret_value = SUCCEED; /* Return value */
+ const H5HF_indirect_t *iblock = (const H5HF_indirect_t *)_thing; /* Indirect block info */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC_NOERR
- /* check arguments */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
+ /* Sanity checks */
HDassert(iblock);
+ HDassert(iblock->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(iblock->cache_info.type == H5AC_FHEAP_IBLOCK);
+ HDassert(image_len);
- if(iblock->cache_info.is_dirty) {
- H5HF_hdr_t *hdr; /* Shared fractal heap information */
- uint8_t *buf; /* Temporary buffer */
- uint8_t *p; /* Pointer into raw data buffer */
-#ifndef NDEBUG
- unsigned nchildren = 0; /* Track # of children */
- unsigned max_child = 0; /* Track max. child entry used */
-#endif /* NDEBUG */
- uint32_t metadata_chksum; /* Computed metadata checksum value */
- size_t u; /* Local index variable */
-
-#ifndef NDEBUG
-{
- /* Verify that flush dependencies are working correctly. Do this
- * by verifying that all children of this iblock are clean.
- */
- hbool_t descendants_clean = TRUE;
- unsigned iblock_status;
-
- if(H5AC_get_entry_status(f, iblock->addr, &iblock_status) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't get iblock status")
-
- /* since the current iblock is the guest of honor in a flush, we know
- * that it is locked into the cache for the duration of the call. Hence
- * there is no need to check to see if it is pinned or protected, or to
- * protect it if it is not.
- */
- if(H5HF__cache_verify_iblock_descendants_clean(f, dxpl_id, iblock, &iblock_status, &descendants_clean) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_SYSTEM, FAIL, "can't verify descendants clean.")
-
- HDassert(descendants_clean);
-}
-#endif /* NDEBUG */
-
- /* Get the pointer to the shared heap header */
- hdr = iblock->hdr;
-
- /* Set the shared heap header's file context for this operation */
- hdr->f = f;
-
- /* Wrap the local buffer for serialized indirect block */
- if(NULL == (wb = H5WB_wrap(iblock_buf, sizeof(iblock_buf))))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't wrap buffer")
-
- /* Get a pointer to a buffer that's large enough for serialized indirect block */
- if(NULL == (buf = (uint8_t *)H5WB_actual(wb, iblock->size)))
- HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "can't get actual buffer")
-
- /* Get temporary pointer to buffer for serialized indirect block */
- p = buf;
-
- /* Magic number */
- HDmemcpy(p, H5HF_IBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC);
- p += H5_SIZEOF_MAGIC;
-
- /* Version # */
- *p++ = H5HF_IBLOCK_VERSION;
-
- /* Address of heap header for heap which owns this block */
- H5F_addr_encode(f, &p, hdr->heap_addr);
-
- /* Offset of block in heap */
- UINT64ENCODE_VAR(p, iblock->block_off, hdr->heap_off_size);
-
- /* Encode indirect block-specific fields */
- for(u = 0; u < (iblock->nrows * hdr->man_dtable.cparam.width); u++) {
- /* Encode child block address */
- H5F_addr_encode(f, &p, iblock->ents[u].addr);
+ *image_len = iblock->size;
- /* Check for heap with I/O filters */
- if(hdr->filter_len > 0) {
- /* Sanity check */
- HDassert(iblock->filt_ents);
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5HF__cache_iblock_image_len() */
- /* Encode extra information for direct blocks */
- if(u < (hdr->man_dtable.max_direct_rows * hdr->man_dtable.cparam.width)) {
- /* Sanity check */
- /* (either both the address & size are defined or both are
- * not defined)
- */
- HDassert((H5F_addr_defined(iblock->ents[u].addr) && iblock->filt_ents[u].size)
- || (!H5F_addr_defined(iblock->ents[u].addr) && iblock->filt_ents[u].size == 0));
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF__cache_iblock_pre_serialize
+ *
+ * Purpose: The primary objective of this function is to determine if the
+ * indirect block is currently allocated in temporary file space,
+ * and if so, to move it to real file space before the entry is
+ * serialized.
+ *
+ * In debug compiles, this function also verifies that all children
+ * of this indirect block are either clean or are not in cache.
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: John Mainzer
+ * 6/21/14
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HF__cache_iblock_pre_serialize(const H5F_t *f, hid_t dxpl_id, void *_thing,
+ haddr_t addr, size_t H5_ATTR_UNUSED len, size_t H5_ATTR_UNUSED compressed_len,
+ haddr_t *new_addr, size_t H5_ATTR_UNUSED *new_len,
+ size_t H5_ATTR_UNUSED *new_compressed_len, unsigned *flags)
+{
+ H5HF_hdr_t *hdr; /* Shared fractal heap information */
+ H5HF_indirect_t *iblock = (H5HF_indirect_t *)_thing; /* Indirect block info */
+ herr_t ret_value = SUCCEED; /* Return value */
- /* Size of filtered direct block */
- H5F_ENCODE_LENGTH(f, p, iblock->filt_ents[u].size);
+ FUNC_ENTER_STATIC
- /* I/O filter mask for filtered direct block */
- UINT32ENCODE(p, iblock->filt_ents[u].filter_mask);
- } /* end if */
- } /* end if */
+ /* Sanity checks */
+ HDassert(f);
+ HDassert(iblock);
+ HDassert(iblock->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(iblock->cache_info.type == H5AC_FHEAP_IBLOCK);
+ HDassert(iblock->cache_info.size == iblock->size);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(H5F_addr_eq(iblock->addr, addr));
+ HDassert(new_addr);
+ HDassert(new_len);
+ HDassert(flags);
+ hdr = iblock->hdr;
+ HDassert(hdr);
+ HDassert(hdr->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(hdr->cache_info.type == H5AC_FHEAP_HDR);
#ifndef NDEBUG
- /* Count child blocks */
- if(H5F_addr_defined(iblock->ents[u].addr)) {
- nchildren++;
- if(u > max_child)
- max_child = u;
- } /* end if */
-#endif /* NDEBUG */
- } /* end for */
-
- /* Compute checksum */
- metadata_chksum = H5_checksum_metadata(buf, (size_t)(p - buf), 0);
+{
+ hbool_t descendants_clean = TRUE;
+ unsigned iblock_status = 0;
- /* Metadata checksum */
- UINT32ENCODE(p, metadata_chksum);
+ /* verify that flush dependencies are working correctly. Do this
+ * by verifying that all children of this iblock are clean.
+ */
+ if(H5AC_get_entry_status(f, iblock->addr, &iblock_status) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't get iblock status")
- /* Sanity check */
- HDassert((size_t)(p - buf) == iblock->size);
-#ifndef NDEBUG
- HDassert(nchildren == iblock->nchildren);
- HDassert(max_child == iblock->max_child);
+ /* since the current iblock is the guest of honor in a flush, we know
+ * that it is locked into the cache for the duration of the call. Hence
+ * there is no need to check to see if it is pinned or protected, or to
+ * protect it if it is not.
+ */
+ if(H5HF__cache_verify_iblock_descendants_clean((H5F_t *)f, dxpl_id, iblock, &iblock_status, &descendants_clean) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_SYSTEM, FAIL, "can't verify descendants clean.")
+ HDassert(descendants_clean);
+}
#endif /* NDEBUG */
- /* Check for needing to re-allocate indirect block from 'temp.' to 'normal' file space */
- if(H5F_IS_TMP_ADDR(f, addr)) {
- /* Sanity check */
- HDassert(H5F_addr_eq(iblock->addr, addr));
+ /* Check to see if we must re-allocate the iblock from temporary to
+ * normal (AKA real) file space.
+ */
+ if(H5F_IS_TMP_ADDR(f, addr)) {
+ haddr_t iblock_addr;
- /* Allocate 'normal' space for the new indirect block on disk */
- if(HADDR_UNDEF == (addr = H5MF_alloc(f, H5FD_MEM_FHEAP_IBLOCK, dxpl_id, (hsize_t)iblock->size)))
- HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap indirect block")
+ /* Allocate 'normal' space for the new indirect block on disk */
+ if(HADDR_UNDEF == (iblock_addr = H5MF_alloc((H5F_t *)f, H5FD_MEM_FHEAP_IBLOCK, dxpl_id, (hsize_t)iblock->size)))
+ HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap indirect block")
- /* Sanity check */
- HDassert(!H5F_addr_eq(iblock->addr, addr));
+ /* Sanity check */
+ HDassert(!H5F_addr_eq(iblock->addr, iblock_addr));
- /* Let the metadata cache know the block moved */
- if(H5AC_move_entry(f, H5AC_FHEAP_IBLOCK, iblock->addr, addr) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTMOVE, FAIL, "unable to move indirect block")
+ /* Let the metadata cache know the block moved */
+ if(H5AC_move_entry((H5F_t *)f, H5AC_FHEAP_IBLOCK, iblock->addr, iblock_addr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTMOVE, FAIL, "unable to move indirect block")
- /* Update the internal address for the block */
- iblock->addr = addr;
+ /* Update the internal address for the block */
+ iblock->addr = iblock_addr;
- /* Check for root indirect block */
- if(NULL == iblock->parent) {
- /* Update information about indirect block's location */
- hdr->man_dtable.table_addr = addr;
+ /* Check for root indirect block */
+ if(NULL == iblock->parent) {
+ /* Update information about indirect block's location */
+ hdr->man_dtable.table_addr = iblock_addr;
- /* Mark that heap header was modified */
- if(H5HF_hdr_dirty(hdr) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty")
- } /* end if */
- else {
- H5HF_indirect_t *par_iblock; /* Parent indirect block */
- unsigned par_entry; /* Entry in parent indirect block */
+ /* Mark that heap header was modified */
+ if(H5HF_hdr_dirty(hdr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty")
+ } /* end if */
+ else {
+ H5HF_indirect_t *par_iblock; /* Parent indirect block */
+ unsigned par_entry; /* Entry in parent indirect block */
- /* Get parent information */
- par_iblock = iblock->parent;
- par_entry = iblock->par_entry;
+ /* Get parent information */
+ par_iblock = iblock->parent;
+ par_entry = iblock->par_entry;
- /* Update information about indirect block's location */
- par_iblock->ents[par_entry].addr = addr;
+ /* Update information about indirect block's location */
+ par_iblock->ents[par_entry].addr = iblock_addr;
- /* Mark that parent was modified */
- if(H5HF_iblock_dirty(par_iblock) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty")
- } /* end if */
+ /* Mark that parent was modified */
+ if(H5HF_iblock_dirty(par_iblock) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty")
} /* end if */
- /* Indirect block must be in 'normal' file space now */
- HDassert(!H5F_IS_TMP_ADDR(f, addr));
-
- /* Write the indirect block */
- if(H5F_block_write(f, H5FD_MEM_FHEAP_IBLOCK, addr, iblock->size, dxpl_id, buf) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFLUSH, FAIL, "unable to save fractal heap indirect block to disk")
-
- /* Reset dirty flags */
- iblock->cache_info.is_dirty = FALSE;
+ *new_addr = iblock_addr;
+ *flags = H5C__SERIALIZE_MOVED_FLAG;
} /* end if */
-
- if(destroy)
- if(H5HF_cache_iblock_dest(f, iblock) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy fractal heap indirect block")
+ else
+ *flags = 0;
done:
- /* Release resources */
- if(wb && H5WB_unwrap(wb) < 0)
- HDONE_ERROR(H5E_HEAP, H5E_CLOSEERROR, FAIL, "can't close wrapped buffer")
-
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5HF_cache_iblock_flush() */
+} /* end H5HF__cache_iblock_pre_serialize() */
/*-------------------------------------------------------------------------
- * Function: H5HF_cache_iblock_dest
+ * Function: H5HF__cache_iblock_serialize
*
- * Purpose: Destroys a fractal heap indirect block in memory.
+ * Purpose: Given a pointer to an iblock, and a pointer to a buffer of
+ * the appropriate size, write the contents of the iblock to the
+ * buffer in format appropriate for writing to disk.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Success: SUCCEED
+ * Failure: FAIL
*
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Mar 6 2006
+ * Programmer: John Mainzer
+ * 6/21/14
*
*-------------------------------------------------------------------------
*/
-static herr_t
-H5HF_cache_iblock_dest(H5F_t *f, H5HF_indirect_t *iblock)
+static herr_t
+H5HF__cache_iblock_serialize(const H5F_t *f, void *_image, size_t len,
+ void *_thing)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ H5HF_hdr_t *hdr; /* Shared fractal heap information */
+ H5HF_indirect_t *iblock = (H5HF_indirect_t *)_thing; /* Indirect block info */
+ uint8_t *image = (uint8_t *)_image; /* Pointer into raw data buffer */
+#ifndef NDEBUG
+ unsigned nchildren = 0; /* Track # of children */
+ size_t max_child = 0; /* Track max. child entry used */
+#endif /* NDEBUG */
+ uint32_t metadata_chksum; /* Computed metadata checksum value */
+ size_t u; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC_NOERR
- /*
- * Check arguments.
- */
+ /* Sanity checks */
+ HDassert(f);
+ HDassert(image);
HDassert(iblock);
- HDassert(iblock->rc == 0);
- HDassert(iblock->hdr);
+ HDassert(iblock->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(iblock->cache_info.type == H5AC_FHEAP_IBLOCK);
+ HDassert(iblock->cache_info.size == iblock->size);
+ HDassert(len == iblock->size);
- /* If we're going to free the space on disk, the address must be valid */
- HDassert(!iblock->cache_info.free_file_space_on_destroy || H5F_addr_defined(iblock->cache_info.addr));
-
- /* Check for freeing file space for indirect block */
- if(iblock->cache_info.free_file_space_on_destroy) {
- /* Check if the indirect block is NOT currently allocated in temp. file space */
- /* (temp. file space does not need to be freed) */
- if(!H5F_IS_TMP_ADDR(f, iblock->cache_info.addr)) {
- /* Release the space on disk */
- /* (XXX: Nasty usage of internal DXPL value! -QAK) */
- if(H5MF_xfree(f, H5FD_MEM_FHEAP_IBLOCK, H5AC_dxpl_id, iblock->cache_info.addr, (hsize_t)iblock->size) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap indirect block")
- } /* end if */
- } /* end if */
+ /* Indirect block must be in 'normal' file space */
+ HDassert(!H5F_IS_TMP_ADDR(f, iblock->addr));
+ HDassert(H5F_addr_eq(iblock->addr, iblock->cache_info.addr));
- /* Destroy fractal heap indirect block */
- if(H5HF_man_iblock_dest(iblock) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy fractal heap indirect block")
+ /* Get the pointer to the shared heap header */
+ hdr = iblock->hdr;
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5HF_cache_iblock_dest() */
+ /* Set the shared heap header's file context for this operation */
+ hdr->f = f;
-
-/*-------------------------------------------------------------------------
- * Function: H5HF_cache_iblock_clear
- *
- * Purpose: Mark a fractal heap indirect block in memory as non-dirty.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Mar 6 2006
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5HF_cache_iblock_clear(H5F_t *f, H5HF_indirect_t *iblock, hbool_t destroy)
-{
- herr_t ret_value = SUCCEED; /* Return value */
+ /* Magic number */
+ HDmemcpy(image, H5HF_IBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ image += H5_SIZEOF_MAGIC;
- FUNC_ENTER_NOAPI_NOINIT
+ /* Version # */
+ *image++ = H5HF_IBLOCK_VERSION;
- /*
- * Check arguments.
- */
- HDassert(iblock);
+ /* Address of heap header for heap which owns this block */
+ H5F_addr_encode(f, &image, hdr->heap_addr);
- /* Reset the dirty flag. */
- iblock->cache_info.is_dirty = FALSE;
+ /* Offset of block in heap */
+ UINT64ENCODE_VAR(image, iblock->block_off, hdr->heap_off_size);
- if(destroy)
- if(H5HF_cache_iblock_dest(f, iblock) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy fractal heap indirect block")
+ /* Encode indirect block-specific fields */
+ for(u = 0; u < (iblock->nrows * hdr->man_dtable.cparam.width); u++) {
+ /* Encode child block address */
+ H5F_addr_encode(f, &image, iblock->ents[u].addr);
+
+ /* Check for heap with I/O filters */
+ if(hdr->filter_len > 0) {
+ /* Sanity check */
+ HDassert(iblock->filt_ents);
+
+ /* Encode extra information for direct blocks */
+ if(u < (hdr->man_dtable.max_direct_rows * hdr->man_dtable.cparam.width)) {
+ /* Sanity check */
+ /* (either both the address & size are defined or both are
+ * not defined)
+ */
+ HDassert((H5F_addr_defined(iblock->ents[u].addr) && iblock->filt_ents[u].size)
+ || (!H5F_addr_defined(iblock->ents[u].addr) && iblock->filt_ents[u].size == 0));
+
+ /* Size of filtered direct block */
+ H5F_ENCODE_LENGTH(f, image, iblock->filt_ents[u].size);
+
+ /* I/O filter mask for filtered direct block */
+ UINT32ENCODE(image, iblock->filt_ents[u].filter_mask);
+ } /* end if */
+ } /* end if */
+
+#ifndef NDEBUG
+ /* Count child blocks */
+ if(H5F_addr_defined(iblock->ents[u].addr)) {
+ nchildren++;
+ if(u > max_child)
+ max_child = u;
+ } /* end if */
+#endif /* NDEBUG */
+ } /* end for */
+
+ /* Compute checksum */
+ metadata_chksum = H5_checksum_metadata((uint8_t *)_image, (size_t)(image - (uint8_t *)_image), 0);
+
+ /* Metadata checksum */
+ UINT32ENCODE(image, metadata_chksum);
+
+ /* Sanity checks */
+ HDassert((size_t)(image - (uint8_t *)_image) == iblock->size);
+#ifndef NDEBUG
+ HDassert(nchildren == iblock->nchildren);
+ HDassert(max_child == iblock->max_child);
+#endif /* NDEBUG */
-done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5HF_cache_iblock_clear() */
+} /* end H5HF__cache_iblock_serialize() */
/*-------------------------------------------------------------------------
- * Function: H5HF_cache_iblock_notify
+ * Function: H5HF__cache_iblock_notify
*
- * Purpose: Setup / takedown flush dependencies as indirect blocks
+ * Purpose: This function is used to create and destroy flush dependency
+ * relationships between iblocks and their parents as indirect blocks
* are loaded / inserted and evicted from the metadata cache.
*
- * Return: Non-negative on success/Negative on failure
+ * In general, the parent will be another iblock, but it may be the
+ * header if the iblock in question is the root iblock.
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
*
* Programmer: John Mainzer
- * 5/17/14
+ * 6/21/14
*
*-------------------------------------------------------------------------
*/
-static herr_t
-H5HF_cache_iblock_notify(H5C_notify_action_t action, H5HF_indirect_t *iblock)
+static herr_t
+H5HF__cache_iblock_notify(H5C_notify_action_t action, void *_thing)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ H5HF_indirect_t *iblock = (H5HF_indirect_t *)_thing; /* Indirect block info */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
- /*
- * Check arguments.
- */
+ /* Sanity checks */
HDassert(iblock);
HDassert(iblock->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(iblock->cache_info.type == H5AC_FHEAP_IBLOCK);
HDassert(iblock->hdr);
if(action == H5AC_NOTIFY_ACTION_BEFORE_EVICT)
@@ -1316,6 +1534,7 @@ H5HF_cache_iblock_notify(H5C_notify_action_t action, H5HF_indirect_t *iblock)
switch(action) {
case H5AC_NOTIFY_ACTION_AFTER_INSERT:
+ case H5AC_NOTIFY_ACTION_AFTER_LOAD:
if(iblock->parent) { /* this is a child iblock */
/* create flush dependency with parent iblock */
if(H5AC_create_flush_dependency(iblock->parent, iblock) < 0)
@@ -1328,6 +1547,10 @@ H5HF_cache_iblock_notify(H5C_notify_action_t action, H5HF_indirect_t *iblock)
} /* end else */
break;
+ case H5AC_NOTIFY_ACTION_AFTER_FLUSH:
+ /* do nothing */
+ break;
+
case H5AC_NOTIFY_ACTION_BEFORE_EVICT:
if(iblock->fd_parent) { /* this is a child iblock */
/* destroy flush dependency with parent iblock */
@@ -1348,95 +1571,324 @@ H5HF_cache_iblock_notify(H5C_notify_action_t action, H5HF_indirect_t *iblock)
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5HF_cache_iblock_notify() */
+} /* end H5HF__cache_iblock_notify() */
/*-------------------------------------------------------------------------
- * Function: H5HF_cache_iblock_size
+ * Function: H5HF__cache_iblock_free_icr
*
- * Purpose: Compute the size in bytes of a fractal heap indirect block
- * on disk, and return it in *size_ptr. On failure,
- * the value of *size_ptr is undefined.
+ * Purpose: Unlink the supplied instance of H5HF_indirect_t from the
+ * fractal heap and free its memory.
*
- * Return: Non-negative on success/Negative on failure
+ * Note: The metadata cache sets the object's cache_info.magic to
+ * H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC before calling a free_icr
+ * callback (checked in assert).
*
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Mar 6 2006
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: John Mainzer
+ * 6/21/14
*
*-------------------------------------------------------------------------
*/
-static herr_t
-H5HF_cache_iblock_size(const H5F_t H5_ATTR_UNUSED *f, const H5HF_indirect_t *iblock, size_t *size_ptr)
+static herr_t
+H5HF__cache_iblock_free_icr(void *thing)
{
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ H5HF_indirect_t *iblock = (H5HF_indirect_t *)thing; /* Fractal heap indirect block to free */
+ herr_t ret_value = SUCCEED; /* Return value */
- /* Check arguments */
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
HDassert(iblock);
- HDassert(size_ptr);
+ HDassert(iblock->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC);
+ HDassert(iblock->cache_info.type == H5AC_FHEAP_IBLOCK);
+ HDassert(iblock->rc == 0);
+ HDassert(iblock->hdr);
- /* Set size value */
- *size_ptr = iblock->size;
+ /* Destroy fractal heap indirect block */
+ if(H5HF_man_iblock_dest(iblock) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy fractal heap indirect block")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF__cache_iblock_free_icr() */
+/*********************************************************/
+/* metadata cache callback definitions for direct blocks */
+/*********************************************************/
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF__cache_dblock_get_load_size()
+ *
+ * Purpose: Determine the size of the direct block on disk image, and
+ * return it in *image_len.
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: John Mainzer
+ * 6/21/14
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HF__cache_dblock_get_load_size(const void *_image, void *_udata, size_t *image_len, size_t *actual_len,
+ hbool_t *compressed_ptr, size_t *compressed_image_len_ptr)
+{
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ const H5HF_dblock_cache_ud_t *udata = (const H5HF_dblock_cache_ud_t *)_udata; /* User data for callback */
+ const H5HF_parent_t *par_info; /* Pointer to parent information */
+ const H5HF_hdr_t *hdr; /* Shared fractal heap information */
+ size_t compressed_size=0;
+ hbool_t compressed;
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Sanity checks */
+ HDassert(udata);
+ HDassert(image_len);
+ par_info = (const H5HF_parent_t *)(&(udata->par_info));
+ HDassert(par_info);
+ hdr = par_info->hdr;
+ HDassert(hdr);
+ HDassert(hdr->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(hdr->cache_info.type == H5AC_FHEAP_HDR);
+
+ if(hdr->filter_len > 0) {
+
+ /* Check for root direct block */
+ if(par_info->iblock == NULL) {
+ /* filtered direct block */
+ compressed_size = hdr->pline_root_direct_size;
+ } /* end if */
+ else {
+ /* filtered direct block */
+ compressed_size = par_info->iblock->filt_ents[par_info->entry].size;
+ } /* end else */
+ }
+
+ if(image == NULL) {
+
+ /* depend on I/O filters on this heap */
+ *image_len = (hdr->filter_len > 0) ? compressed_size:udata->dblock_size;
+
+ } else {
+
+ HDassert(actual_len);
+ HDassert(*actual_len == *image_len);
+ HDassert(compressed_ptr);
+ HDassert(compressed_image_len_ptr);
+
+ if(hdr->filter_len > 0) {
+ HDassert(*image_len == compressed_size);
+ compressed = TRUE;
+ } else {
+ HDassert(*image_len == udata->dblock_size);
+ compressed = FALSE;
+ compressed_size = 0;
+ }
+
+ /* decompressed size */
+ *actual_len = udata->dblock_size;
+ *compressed_ptr = compressed;
+ *compressed_image_len_ptr = compressed_size;
+ }
+
FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5HF_cache_iblock_size() */
+} /* end H5HF__cache_dblock_get_load_size() */
/*********************************************************/
/* metadata cache callback definitions for direct blocks */
/*********************************************************/
+/*-------------------------------------------------------------------------
+ * Function: H5HF__cache_dblock_verify_chksum
+ *
+ * Purpose: Verify the computed checksum of the data structure is the
+ * same as the stored chksum.
+ *
+ * Return: Success: TRUE/FALSE
+ * Failure: Negative
+ *
+ * Programmer: Vailin Choi; Aug 2015
+ *
+ *-------------------------------------------------------------------------
+ */
+static htri_t
+H5HF__cache_dblock_verify_chksum(const void *_image, size_t len, void *_udata)
+{
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ H5HF_dblock_cache_ud_t *udata = (H5HF_dblock_cache_ud_t *)_udata; /* User data for callback */
+ void *read_buf = NULL; /* Pointer to buffer to read in */
+ size_t read_size; /* Size of filtered direct block to read */
+ H5HF_hdr_t *hdr; /* Shared fractal heap information */
+ H5HF_parent_t *par_info; /* Pointer to parent information */
+ uint32_t stored_chksum; /* Stored metadata checksum value */
+ uint32_t t_chksum; /* Computed metadata checksum value */
+ uint32_t computed_chksum; /* Computed metadata checksum value */
+ size_t chk_size; /* The size for validating checksum */
+ uint8_t *chk_p; /* Pointer to the area for validating checksum */
+ htri_t ret_value = TRUE; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(image);
+ HDassert(udata);
+ par_info = (H5HF_parent_t *)(&(udata->par_info));
+ HDassert(par_info);
+ hdr = par_info->hdr;
+ HDassert(hdr);
+
+ /* len is the decompressed size of the direct block */
+
+ udata->decompressed = FALSE;
+ udata->dblk = NULL;
+
+ /* Get out if data block is not checksummed */
+ if(!(hdr->checksum_dblocks))
+ HGOTO_DONE(TRUE);
+
+ /* Determine the size on disk */
+ if(hdr->filter_len > 0) {
+
+ /* Check for root direct block */
+ if(par_info->iblock == NULL) {
+ /* Set up parameters to read filtered direct block */
+ read_size = hdr->pline_root_direct_size;
+ } /* end if */
+ else {
+ /* Set up parameters to read filtered direct block */
+ read_size = par_info->iblock->filt_ents[par_info->entry].size;
+ } /* end else */
+ } else
+ read_size = len;
+
+ /* Allocate buffer to perform I/O filtering on and copy image into
+ * it. Must do this as H5Z_pipeline() may re-sized the buffer
+ * provided to it.
+ */
+ if(NULL == (read_buf = H5MM_malloc(read_size)))
+ HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "memory allocation failed for pipeline buffer")
+
+ if(hdr->filter_len > 0) {
+ size_t nbytes; /* Number of bytes used in buffer, after applying reverse filters */
+ unsigned filter_mask; /* Excluded filters for direct block */
+ H5Z_cb_t filter_cb = {NULL, NULL}; /* Filter callback structure */
+
+ /* Push direct block data through I/O filter pipeline */
+ nbytes = read_size;
+ filter_mask = udata->filter_mask;
+ HDmemcpy(read_buf, image, read_size);
+
+ if(H5Z_pipeline(&(hdr->pline), H5Z_FLAG_REVERSE, &filter_mask, H5Z_ENABLE_EDC, filter_cb, &nbytes, &read_size, &read_buf) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFILTER, FAIL, "output pipeline failed")
+
+ /* Sanity check */
+ HDassert(nbytes == len);
+ udata->decompressed = TRUE;
+
+ } else
+ HDmemcpy(read_buf, image, read_size);
+
+ /* Decode checksum */
+ chk_size = (size_t)(H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr) - H5HF_SIZEOF_CHKSUM);
+ chk_p = (uint8_t *)read_buf + chk_size;
+
+ /* Metadata checksum */
+ UINT32DECODE(chk_p, stored_chksum);
+
+ chk_p -= H5HF_SIZEOF_CHKSUM;
+
+ /* Reset checksum field, for computing the checksum */
+ /* (Casting away const OK - QAK) */
+ HDmemset(chk_p, 0, (size_t)H5HF_SIZEOF_CHKSUM);
+
+ /* Compute checksum on entire direct block */
+ computed_chksum = H5_checksum_metadata(read_buf, len, 0);
+
+ /* Restore the checksum */
+ UINT32ENCODE(chk_p, stored_chksum)
+
+ /* Verify checksum */
+ if(stored_chksum != computed_chksum)
+ HGOTO_DONE(FALSE);
+
+ /* Save the decompressed data to be used later in deserialize callback */
+ if(hdr->filter_len > 0) {
+
+ HDassert(udata->decompressed);
+ HDassert(len == udata->dblock_size);
+ /* Allocate block buffer */
+ if(NULL == (udata->dblk = H5FL_BLK_MALLOC(direct_block, (size_t)len)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+
+ /* Copy un-filtered data into block's buffer */
+ HDmemcpy(udata->dblk, read_buf, len);
+ }
+
+done:
+ /* Release the read buffer */
+ if(read_buf)
+ H5MM_xfree(read_buf);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF__cache_dblock_verify_chksum() */
+
/*-------------------------------------------------------------------------
- * Function: H5HF_cache_dblock_load
+ * Function: H5HF__cache_dblock_deserialize
*
- * Purpose: Loads a fractal heap direct block from the disk.
+ * Purpose: Given a buffer containing the on disk image of a direct
+ * block, allocate an instance of H5HF_direct_t, load the data
+ * in the buffer into this new instance, and return a pointer to
+ * it.
*
- * Return: Success: Pointer to a new fractal heap direct block
+ * As best I can tell, the size of the direct block image is fully
+ * know before the image is loaded, so this function should succeed
+ * unless the image is corrupt or memory allocation fails.
*
+ * Return: Success: Pointer to in core representation
* Failure: NULL
*
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 27 2006
+ * Programmer: John Mainzer
+ * 6/21/14
*
*-------------------------------------------------------------------------
*/
-static H5HF_direct_t *
-H5HF_cache_dblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
+static void *
+H5HF__cache_dblock_deserialize(const void *_image, size_t len, void *_udata,
+ hbool_t H5_ATTR_UNUSED *dirty)
{
H5HF_hdr_t *hdr; /* Shared fractal heap information */
H5HF_dblock_cache_ud_t *udata = (H5HF_dblock_cache_ud_t *)_udata; /* User data for callback */
H5HF_parent_t *par_info; /* Pointer to parent information */
- H5HF_direct_t *dblock = NULL; /* Direct block info */
- const uint8_t *p; /* Pointer into raw data buffer */
+ H5HF_direct_t *dblock = NULL; /* Direct block info */
+ const uint8_t *image; /* Pointer into raw data buffer */
haddr_t heap_addr; /* Address of heap header in the file */
- uint32_t computed_chksum; /* Computed metadata checksum value */
- uint32_t stored_chksum; /* Metadata checksum value */
- unsigned tries, max_tries; /* The # of read attempts */
- unsigned retries; /* The # of retries */
- size_t chk_size; /* The size for validating checksum */
- uint8_t *chk_p; /* Pointer to the area for validating checksum */
- size_t read_size; /* Size of filtered direct block to read */
- H5HF_direct_t *ret_value; /* Return value */
+ void * ret_value; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
- /* Check arguments */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
- HDassert(udata != NULL);
- HDassert(udata->f != NULL);
- HDassert(udata->dblock_size > 0);
+ /* Sanity checks */
+ HDassert(_image);
+ HDassert(udata);
+ par_info = (H5HF_parent_t *)(&(udata->par_info));
+ HDassert(par_info);
+ hdr = par_info->hdr;
+ HDassert(hdr);
+ HDassert(hdr->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(hdr->cache_info.type == H5AC_FHEAP_HDR);
+ HDassert(dirty);
/* Allocate space for the fractal heap direct block */
if(NULL == (dblock = H5FL_MALLOC(H5HF_direct_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
HDmemset(&dblock->cache_info, 0, sizeof(H5AC_info_t));
- /* Get the pointer to the shared heap header */
- par_info = (H5HF_parent_t *)(&(udata->par_info));
- hdr = par_info->hdr;
-
/* Set the shared heap header's file context for this operation */
hdr->f = udata->f;
@@ -1449,46 +1901,54 @@ H5HF_cache_dblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
dblock->size = udata->dblock_size;
dblock->file_size = 0;
- /* Allocate block buffer */
-/* XXX: Change to using free-list factories */
- if(NULL == (dblock->blk = H5FL_BLK_MALLOC(direct_block, (size_t)dblock->size)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
-
- /* Determine read_size for filter buffer */
+ /* initialize fields used in serialization */
+ dblock->write_buf = NULL;
+ dblock->write_size = 0;
+
+ if(udata->dblk && udata->decompressed) {
+ /* direct block is already decompressed in verify_chksum callback */
+ HDassert(hdr->filter_len > 0);
+ HDassert(len == dblock->size);
+ dblock->blk = udata->dblk;
+ } else {
+ HDassert(udata->dblk == NULL);
+ HDassert(!udata->decompressed);
+
+ /* Allocate block buffer */
+ /* XXX: Change to using free-list factories */
+ if(NULL == (dblock->blk = H5FL_BLK_MALLOC(direct_block, (size_t)dblock->size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+ }
+
+ /* Check for I/O filters on this heap */
if(hdr->filter_len > 0) {
- /* Check for root direct block */
- if(par_info->iblock == NULL) {
- /* Sanity check */
- HDassert(H5F_addr_eq(hdr->man_dtable.table_addr, addr));
-
- /* Set up parameters to read filtered direct block */
- read_size = hdr->pline_root_direct_size;
- } /* end if */
- else {
- /* Sanity check */
- HDassert(H5F_addr_eq(par_info->iblock->ents[par_info->entry].addr, addr));
-
- /* Set up parameters to read filtered direct block */
- read_size = par_info->iblock->filt_ents[par_info->entry].size;
- } /* end else */
- } /* end if */
-
- tries = max_tries = H5F_GET_READ_ATTEMPTS(f);
- do {
- /* Check for I/O filters on this heap */
- if(hdr->filter_len > 0) {
- H5Z_cb_t filter_cb = {NULL, NULL}; /* Filter callback structure */
- size_t nbytes; /* Number of bytes used in buffer, after applying reverse filters */
- void *read_buf; /* Pointer to buffer to read in */
- unsigned filter_mask; /* Excluded filters for direct block */
+ H5Z_cb_t filter_cb = {NULL, NULL}; /* Filter callback structure */
+ size_t nbytes; /* Number of bytes used in buffer, after applying reverse filters */
+ void *read_buf; /* Pointer to buffer to read in */
+ size_t read_size; /* Size of filtered direct block to read */
+ unsigned filter_mask; /* Excluded filters for direct block */
+
+ if(!udata->decompressed) {
+ HDassert(udata->dblk == NULL);
+
+ /* Check for root direct block */
+ if(par_info->iblock == NULL) {
+ /* Set up parameters to read filtered direct block */
+ read_size = hdr->pline_root_direct_size;
+ } /* end if */
+ else {
+ /* Set up parameters to read filtered direct block */
+ read_size = par_info->iblock->filt_ents[par_info->entry].size;
+ } /* end else */
+ HDassert(len == read_size);
- /* Allocate buffer to perform I/O filtering on */
+ /* Allocate buffer to perform I/O filtering on and copy image into
+ * it. Must do this as H5Z_pipeline() may re-sized the buffer
+ * provided to it.
+ */
if(NULL == (read_buf = H5MM_malloc(read_size)))
HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, NULL, "memory allocation failed for pipeline buffer")
-
- /* Read filtered direct block from disk */
- if(H5F_block_read(f, H5FD_MEM_FHEAP_DBLOCK, addr, read_size, dxpl_id, read_buf) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_READERROR, NULL, "can't read fractal heap direct block")
+ HDmemcpy(read_buf, _image, len);
/* Push direct block data through I/O filter pipeline */
nbytes = read_size;
@@ -1504,62 +1964,28 @@ H5HF_cache_dblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
/* Release the read buffer */
H5MM_xfree(read_buf);
- } /* end if */
- else {
- /* Read direct block from disk */
- if(H5F_block_read(f, H5FD_MEM_FHEAP_DBLOCK, addr, dblock->size, dxpl_id, dblock->blk) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_READERROR, NULL, "can't read fractal heap direct block")
- } /* end else */
-
- /* Get out if data block is not checksummed */
- if(!(hdr->checksum_dblocks))
- break;
-
- /* Decode checksum on direct block, if requested */
- chk_size = (size_t)(H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr) - H5HF_SIZEOF_CHKSUM);
- chk_p = dblock->blk + chk_size;
-
- /* Metadata checksum */
- UINT32DECODE(chk_p, stored_chksum);
-
- chk_p -= H5HF_SIZEOF_CHKSUM;
-
- /* Reset checksum field, for computing the checksum */
- /* (Casting away const OK - QAK) */
- HDmemset(chk_p, 0, (size_t)H5HF_SIZEOF_CHKSUM);
-
- /* Compute checksum on entire direct block */
- computed_chksum = H5_checksum_metadata(dblock->blk, dblock->size, 0);
-
- /* Verify checksum */
- if(stored_chksum == computed_chksum)
- break;
-
- } while (--tries);
-
- if(tries == 0)
- HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, NULL, "incorrect metadata checksum after all tries (%u) for fractal heap direct block", max_tries)
-
- /* Calculate and track the # of retries */
- retries = max_tries - tries;
- if(retries) /* Does not track 0 retry */
- if(H5F_track_metadata_read_retries(f, H5AC_FHEAP_DBLOCK_ID, retries) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, NULL, "cannot track read retries = %u ", retries)
+ }
+ } /* end if */
+ else {
+ /* copy image to dblock->blk */
+ HDassert(dblock->size == len);
+ HDmemcpy(dblock->blk, _image, dblock->size);
+ } /* end else */
/* Start decoding direct block */
- p = dblock->blk;
+ image = dblock->blk;
/* Magic number */
- if(HDmemcmp(p, H5HF_DBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "wrong fractal heap direct block signature")
- p += H5_SIZEOF_MAGIC;
+ if(HDmemcmp(image, H5HF_DBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC))
+ HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, NULL, "wrong fractal heap direct block signature")
+ image += H5_SIZEOF_MAGIC;
/* Version */
- if(*p++ != H5HF_DBLOCK_VERSION)
+ if(*image++ != H5HF_DBLOCK_VERSION)
HGOTO_ERROR(H5E_HEAP, H5E_VERSION, NULL, "wrong fractal heap direct block version")
/* Address of heap that owns this block (just for file integrity checks) */
- H5F_addr_decode(udata->f, &p, &heap_addr);
+ H5F_addr_decode(udata->f, &image, &heap_addr);
if(H5F_addr_ne(heap_addr, hdr->heap_addr))
HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "incorrect heap header address for direct block")
@@ -1574,17 +2000,24 @@ H5HF_cache_dblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
} /* end if */
/* Offset of heap within the heap's address space */
- UINT64DECODE_VAR(p, dblock->block_off, hdr->heap_off_size);
+ UINT64DECODE_VAR(image, dblock->block_off, hdr->heap_off_size);
+
+ /* Decode checksum on direct block, if requested */
+ if(hdr->checksum_dblocks) {
+ uint32_t stored_chksum; /* Metadata checksum value */
- /* Advance past optional checksum on direct block, it was verified earlier */
- if(hdr->checksum_dblocks)
- p += H5HF_SIZEOF_CHKSUM;
+ /* checksum verification already done in verify_chksum cb */
+
+ /* Metadata checksum */
+ UINT32DECODE(image, stored_chksum);
+
+ } /* end if */
/* Sanity check */
- HDassert((size_t)(p - dblock->blk) == (size_t)H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr));
+ HDassert((size_t)(image - dblock->blk) == (size_t)H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr));
/* Set return value */
- ret_value = dblock;
+ ret_value = (void *)dblock;
done:
if(!ret_value && dblock)
@@ -1592,402 +2025,646 @@ done:
HDONE_ERROR(H5E_HEAP, H5E_CANTFREE, NULL, "unable to destroy fractal heap direct block")
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5HF_cache_dblock_load() */
+} /* end H5HF__cache_dblock_deserialize() */
/*-------------------------------------------------------------------------
- * Function: H5HF_cache_dblock_flush
+ * Function: H5HF__cache_dblock_image_len
*
- * Purpose: Flushes a dirty fractal heap direct block to disk.
+ * Purpose: Report the actual size of the direct block image on disk.
+ * Note that this value will probably be incorrect if compression
+ * is enabled and the entry is dirty.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Success: SUCCEED
+ * Failure: FAIL
*
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 27 2006
+ * Programmer: John Mainzer
+ * 6/21/14
*
*-------------------------------------------------------------------------
*/
-static herr_t
-H5HF_cache_dblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HF_direct_t *dblock, unsigned H5_ATTR_UNUSED * flags_ptr)
+static herr_t
+H5HF__cache_dblock_image_len(const void *_thing, size_t *image_len, hbool_t *compressed_ptr, size_t *compressed_image_len_ptr)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ const H5HF_direct_t *dblock = (const H5HF_direct_t *)_thing; /* Direct block info */
+ const H5HF_indirect_t *par_iblock; /* Parent iblock */
+ const H5HF_hdr_t *hdr; /* Shared fractal heap information */
+ hbool_t compressed;
+ size_t size;
+ size_t compressed_size;
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC_NOERR
- /* check arguments */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
+ /* Sanity checks */
HDassert(dblock);
+ HDassert(dblock->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(dblock->cache_info.type == H5AC_FHEAP_DBLOCK);
+ HDassert(image_len);
+ HDassert(compressed_ptr);
+ HDassert(compressed_image_len_ptr);
- if(dblock->cache_info.is_dirty) {
- H5HF_hdr_t *hdr; /* Shared fractal heap information */
- hbool_t at_tmp_addr = H5F_IS_TMP_ADDR(f, addr); /* Flag to indicate direct block is at temporary address */
- void *write_buf; /* Pointer to buffer to write out */
- size_t write_size; /* Size of buffer to write out */
- uint8_t *p; /* Pointer into raw data buffer */
+ /* Set up convenience variables */
+ hdr = dblock->hdr;
+ par_iblock = dblock->parent;
- /* Get the pointer to the shared heap header */
- hdr = dblock->hdr;
+ /* Check for I/O filters on this heap */
+ if(hdr->filter_len > 0) {
- /* Set the shared heap header's file context for this operation */
- hdr->f = f;
+ /* Filters are enabled, so set compressed to TRUE, and set
+ * size equal to the uncompressed size of the direct block.
+ * If the data is available, set compressed_size to the compressed
+ * size of the direct block -- otherwise set it equal to the
+ * uncompressed size.
+ *
+ * We have three possible scenarios here.
+ *
+ * First, the block may never have been flushed. In this
+ * case, both dblock->file_size and the size stored in the
+ * parent (either the header or the parent iblock) will all
+ * be zero. In this case, return the uncompressed size
+ * stored in dblock->size as the compressed size.
+ *
+ * Second, the block may have just been serialized, in which
+ * case, dblock->file_size should be zero, and the correct
+ * on disk size should be stored in the parent (again, either
+ * the header or the parent iblock as case may be).
+ *
+ * Third, we may be in the process of discarding this
+ * dblock without writing it. In this case, dblock->file_size
+ * should be non-zero and have the correct size. Note that
+ * in this case, the direct block will have been detached,
+ * and thus looking up the parent will likely return incorrect
+ * data.
+ */
+ size = dblock->size;
+ compressed = TRUE;
+ compressed_size = dblock->size; /* will overwrite if compressed
+ * size is available.
+ */
+
+ if(dblock->file_size != 0)
+ compressed_size = dblock->file_size;
+ else {
+ if(par_iblock) {
+ unsigned par_entry; /* Entry in parent indirect block */
- HDassert(dblock->blk);
- p = dblock->blk;
+ par_entry = dblock->par_entry;
+ compressed_size = par_iblock->filt_ents[par_entry].size;
- /* Magic number */
- HDmemcpy(p, H5HF_DBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC);
- p += H5_SIZEOF_MAGIC;
+ } /* end if */
+ else {
+ compressed_size = hdr->pline_root_direct_size;
+ }
- /* Version # */
- *p++ = H5HF_DBLOCK_VERSION;
+ if(compressed_size == 0)
+ compressed_size = dblock->size;
- /* Address of heap header for heap which owns this block */
- H5F_addr_encode(f, &p, hdr->heap_addr);
+ } /* end else */
+ } /* end if */
+ else {
+ size = dblock->size;
+ compressed = FALSE;
+ compressed_size = 0; /* a convenient, invalid value */
+ }
- /* Offset of block in heap */
- UINT64ENCODE_VAR(p, dblock->block_off, hdr->heap_off_size);
+ HDassert(size > 0);
- /* Metadata checksum */
- if(hdr->checksum_dblocks) {
- uint32_t metadata_chksum; /* Computed metadata checksum value */
+ *image_len = size;
+ *compressed_ptr = compressed;
+ *compressed_image_len_ptr = compressed_size;
- /* Clear the checksum field, to compute the checksum */
- HDmemset(p, 0, (size_t)H5HF_SIZEOF_CHKSUM);
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5HF__cache_dblock_image_len() */
- /* Compute checksum on entire direct block */
- metadata_chksum = H5_checksum_metadata(dblock->blk, dblock->size, 0);
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF__cache_dblock_pre_serialize
+ *
+ * Purpose: In principle, the purpose of this function is to determine
+ * the size and location of the disk image of the target direct
+ * block. In this case, the uncompressed size of the block is
+ * fixed, but sined the H5C__CLASS_COMPRESSED_FLAG is set,
+ * we may need to compute and report the compressed size.
+ *
+ * This is a bit sticky in the case of a direct block when I/O
+ * filters are enabled, as the size of the compressed version
+ * of the on disk image is not known until the direct block has
+ * been run through the filters. Further, the location of the
+ * on disk image may change if the compressed size of the image
+ * changes as well.
+ *
+ * To complicate matters further, the direct block may have been
+ * initially allocated in temporary (AKA imaginary) file space.
+ * In this case, we must relocate the direct block's on disk
+ * image to real file space regardless of whether it has changed
+ * size.
+ *
+ * One simplifying factor is the direct block's "blk" field,
+ * which contains a pointer to a buffer which (with the exception
+ * of a small header) contains the on disk image in uncompressed
+ * form.
+ *
+ * To square this particular circle, this function does
+ * everything the serialize function usually does, with the
+ * exception of copying the image into the image buffer provided
+ * to the serialize function by the metadata cache. The data to
+ * copy is provided to the serialize function in a buffer pointed
+ * to by the write_buf field.
+ *
+ * If I/O filters are enabled, on exit,
+ * H5HF__cache_dblock_pre_serialize() sets the write_buf field to
+ * point to a buffer containing the filtered image of the direct
+ * block. The serialize function should free this block, and set
+ * the write_buf field to NULL after copying it into the image
+ * buffer provided by the metadata cache.
+ *
+ * If I/O filters are not enabled, this function prepares
+ * the buffer pointed to by the blk field for copying to the
+ * image buffer provided by the metadata cache, and sets the
+ * write_buf field equal to the blk field. In this case, the
+ * serialize function should simply set the write_buf field to
+ * NULL after copying the direct block image into the image
+ * buffer.
+ *
+ * In both of the above cases, the length of the buffer pointed
+ * to by write_buf is provided in the write_len field. This
+ * field must contain 0 on entry to this function, and should
+ * be set back to 0 at the end of the serialize function.
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: John Mainzer
+ * 6/21/14
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HF__cache_dblock_pre_serialize(const H5F_t *f, hid_t dxpl_id, void *_thing,
+ haddr_t addr, size_t len, size_t compressed_len, haddr_t *new_addr,
+ size_t H5_ATTR_UNUSED *new_len, size_t *new_compressed_len, unsigned *flags)
+{
+ hbool_t at_tmp_addr; /* Flag to indicate direct block is */
+ /* at temporary address */
+ haddr_t dblock_addr;
+ H5HF_hdr_t *hdr; /* Shared fractal heap information */
+ H5HF_direct_t *dblock = (H5HF_direct_t *)_thing; /* Direct block info */
+ H5HF_indirect_t *par_iblock; /* Parent indirect block */
+ unsigned par_entry; /* Entry in parent indirect block */
+ void *write_buf; /* Pointer to buffer to write out */
+ size_t write_size; /* Size of buffer to write out */
+ uint8_t *image; /* Pointer into raw data buffer */
+ unsigned dblock_flags = 0;
+ herr_t ret_value = SUCCEED; /* Return value */
- /* Metadata checksum */
- UINT32ENCODE(p, metadata_chksum);
- } /* end if */
+ FUNC_ENTER_STATIC
- /* Sanity check */
- HDassert((size_t)(p - dblock->blk) == (size_t)H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr));
+ /* Sanity checks */
+ HDassert(f);
+ HDassert(dblock);
+ HDassert(dblock->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(dblock->cache_info.type == H5AC_FHEAP_DBLOCK);
+ HDassert(dblock->write_buf == NULL);
+ HDassert(dblock->write_size == 0);
+ HDassert(dblock->cache_info.size == len);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(len == dblock->size);
+ HDassert(new_addr);
+ HDassert(new_compressed_len);
+ HDassert(flags);
- /* Check for I/O filters on this heap */
- if(hdr->filter_len > 0) {
- H5Z_cb_t filter_cb = {NULL, NULL}; /* Filter callback structure */
- size_t nbytes; /* Number of bytes used */
- unsigned filter_mask = 0; /* Filter mask for block */
+ /* Set up local variables */
+ hdr = dblock->hdr;
+ dblock_addr = addr; /* will update dblock_addr if we move the block */
- /* Allocate buffer to perform I/O filtering on */
- write_size = dblock->size;
- if(NULL == (write_buf = H5MM_malloc(write_size)))
- HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "memory allocation failed for pipeline buffer")
- HDmemcpy(write_buf, dblock->blk, write_size);
+ /* dblock->size must match dblock->cache_info.size */
+ HDassert(dblock->cache_info.size == dblock->size);
- /* Push direct block data through I/O filter pipeline */
- nbytes = write_size;
- if(H5Z_pipeline(&(hdr->pline), 0, &filter_mask, H5Z_ENABLE_EDC, filter_cb, &nbytes, &write_size, &write_buf) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "output pipeline failed")
+ /* Set the shared heap header's file context for this operation */
+ hdr->f = (H5F_t *)f;
- /* Use the compressed number of bytes as the size to write */
- write_size = nbytes;
+ HDassert(hdr);
+ HDassert(hdr->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(hdr->cache_info.type == H5AC_FHEAP_HDR);
- /* Check for root direct block */
- if(dblock->parent == NULL) {
- hbool_t hdr_changed = FALSE; /* Whether the header information changed */
+ if(dblock->parent) {
+ /* this is the common case, in which the direct block is the child
+ * of an indirect block. Set up the convenience variables we will
+ * need if the address and/or compressed size of the on disk image
+ * of the direct block changes, and do some sanity checking in
+ * passing.
+ */
+ par_iblock = dblock->parent;
+ par_entry = dblock->par_entry;
- /* Sanity check */
- HDassert(H5F_addr_eq(hdr->man_dtable.table_addr, addr));
- HDassert(hdr->pline_root_direct_size > 0);
+ HDassert(par_iblock->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(par_iblock->cache_info.type == H5AC_FHEAP_IBLOCK);
+ HDassert(H5F_addr_eq(par_iblock->ents[par_entry].addr, addr));
+ } /* end if */
+ else {
+ /* the direct block is a root direct block -- just set par_iblock
+ * to NULL, as the field will not be used.
+ */
+ par_iblock = NULL;
+ } /* end else */
- /* Check if the filter mask changed */
- if(hdr->pline_root_direct_filter_mask != filter_mask) {
- hdr->pline_root_direct_filter_mask = filter_mask;
- hdr_changed = TRUE;
- } /* end if */
+ at_tmp_addr = H5F_IS_TMP_ADDR(f, addr);
- /* Check if we need to re-size the block on disk */
- if(hdr->pline_root_direct_size != write_size || at_tmp_addr) {
- /* Check if the direct block is NOT currently allocated in temp. file space */
- /* (temp. file space does not need to be freed) */
- if(!at_tmp_addr) {
- /* Release direct block's current disk space */
- if(H5MF_xfree(f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, addr, (hsize_t)hdr->pline_root_direct_size) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap direct block")
- } /* end if */
+ /* Begin by preping the direct block to be written to disk. Do
+ * this by writing the correct magic number, the dblock version,
+ * the address of the header, the offset of the block in the heap,
+ * and the checksum at the beginning of the block.
+ */
- /* Allocate space for the compressed direct block */
- if(HADDR_UNDEF == (addr = H5MF_alloc(f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, (hsize_t)write_size)))
- HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap direct block")
+ HDassert(dblock->blk);
+ image = dblock->blk;
- /* Let the metadata cache know, if the block moved */
- if(!H5F_addr_eq(hdr->man_dtable.table_addr, addr))
- if(H5AC_move_entry(f, H5AC_FHEAP_DBLOCK, hdr->man_dtable.table_addr, addr) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTMOVE, FAIL, "unable to move direct block")
+ /* Magic number */
+ HDmemcpy(image, H5HF_DBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ image += H5_SIZEOF_MAGIC;
- /* Update information about compressed direct block's location & size */
- hdr->man_dtable.table_addr = addr;
- hdr->pline_root_direct_size = write_size;
+ /* Version # */
+ *image++ = H5HF_DBLOCK_VERSION;
- /* Note that heap header was modified */
- hdr_changed = TRUE;
- } /* end if */
+ /* Address of heap header for heap which owns this block */
+ H5F_addr_encode(f, &image, hdr->heap_addr);
- /* Check if heap header was modified */
- if(hdr_changed)
- if(H5HF_hdr_dirty(hdr) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty")
- } /* end if */
- else {
- hbool_t par_changed = FALSE; /* Whether the parent's information changed */
- H5HF_indirect_t *par_iblock; /* Parent indirect block */
- unsigned par_entry; /* Entry in parent indirect block */
+ /* Offset of block in heap */
+ UINT64ENCODE_VAR(image, dblock->block_off, hdr->heap_off_size);
- /* Get parent information */
- par_iblock = dblock->parent;
- par_entry = dblock->par_entry;
+ /* Metadata checksum */
+ if(hdr->checksum_dblocks) {
+ uint32_t metadata_chksum; /* Computed metadata checksum value */
- /* Sanity check */
- HDassert(H5F_addr_eq(par_iblock->ents[par_entry].addr, addr));
- HDassert(par_iblock->filt_ents[par_entry].size > 0);
+ /* Clear the checksum field, to compute the checksum */
+ HDmemset(image, 0, (size_t)H5HF_SIZEOF_CHKSUM);
- /* Check if the filter mask changed */
- if(par_iblock->filt_ents[par_entry].filter_mask != filter_mask) {
- par_iblock->filt_ents[par_entry].filter_mask = filter_mask;
- par_changed = TRUE;
- } /* end if */
+ /* Compute checksum on entire direct block */
+ metadata_chksum = H5_checksum_metadata(dblock->blk, dblock->size, 0);
- /* Check if we need to re-size the block on disk */
- if(par_iblock->filt_ents[par_entry].size != write_size || at_tmp_addr) {
- /* Check if the direct block is NOT currently allocated in temp. file space */
- /* (temp. file space does not need to be freed) */
- if(!at_tmp_addr) {
- /* Release direct block's current disk space */
- if(H5MF_xfree(f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, addr, (hsize_t)par_iblock->filt_ents[par_entry].size) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap direct block")
- } /* end if */
+ /* Metadata checksum */
+ UINT32ENCODE(image, metadata_chksum);
+ } /* end if */
- /* Allocate space for the compressed direct block */
- if(HADDR_UNDEF == (addr = H5MF_alloc(f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, (hsize_t)write_size)))
- HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap direct block")
+ /* at this point, dblock->blk should point to an uncompressed image of
+ * the direct block. If I/O filters are not enabled, this image should
+ * be ready to hand off to the metadata cache.
+ */
- /* Let the metadata cache know, if the block moved */
- if(!H5F_addr_eq(par_iblock->ents[par_entry].addr, addr))
- if(H5AC_move_entry(f, H5AC_FHEAP_DBLOCK, par_iblock->ents[par_entry].addr, addr) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTMOVE, FAIL, "unable to move direct block")
+ /* Sanity check */
+ HDassert((size_t)(image - dblock->blk) == (size_t)H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr));
- /* Update information about compressed direct block's location & size */
- par_iblock->ents[par_entry].addr = addr;
- par_iblock->filt_ents[par_entry].size = write_size;
+ /* If I/O filters are enabled on this heap, we must run the direct block
+ * image through the filters to obtain the image that we will hand off
+ * to the metadata cache.
+ */
- /* Note that parent was modified */
- par_changed = TRUE;
- } /* end if */
+ /* Check for I/O filters on this heap */
+ if(hdr->filter_len > 0) {
+ H5Z_cb_t filter_cb = {NULL, NULL}; /* Filter callback structure */
+ size_t nbytes; /* Number of bytes used */
+ unsigned filter_mask = 0; /* Filter mask for block */
+
+ /* Allocate buffer to perform I/O filtering on */
+ write_size = dblock->size;
+
+ if(NULL == (write_buf = H5MM_malloc(write_size)))
+ HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "memory allocation failed for pipeline buffer")
+ HDmemcpy(write_buf, dblock->blk, write_size);
+
+ /* Push direct block data through I/O filter pipeline */
+ nbytes = write_size;
+ if(H5Z_pipeline(&(hdr->pline), 0, &filter_mask, H5Z_ENABLE_EDC, filter_cb, &nbytes, &write_size, &write_buf) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "output pipeline failed")
+
+ /* Use the compressed number of bytes as the size to write */
+ write_size = nbytes;
+
+ /* If the size and/or location of the on disk image of the
+ * direct block changes, we must touch up its parent to reflect
+ * these changes. Do this differently depending on whether the
+ * direct block's parent is an indirect block or (rarely) the
+ * fractal heap header. In this case, the direct block is known
+ * as a root direct block.
+ */
- /* Check if parent was modified */
- if(par_changed)
- if(H5HF_iblock_dirty(par_iblock) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty")
- } /* end else */
- } /* end if */
- else {
- write_buf = dblock->blk;
- write_size = dblock->size;
+ /* Check for root direct block */
+ if(dblock->parent == NULL) {
+ hbool_t hdr_changed = FALSE; /* Whether the header info changed */
- /* Check for needing to re-allocate direct block from 'temp.' to 'normal' file space */
- if(at_tmp_addr) {
- /* Check for root direct block */
- if(NULL == dblock->parent) {
- /* Sanity check */
- HDassert(H5F_addr_eq(hdr->man_dtable.table_addr, addr));
+ /* Sanity check */
+ HDassert(H5F_addr_eq(hdr->man_dtable.table_addr, addr));
+ HDassert(hdr->pline_root_direct_size > 0);
- /* Allocate 'normal' space for the direct block */
- if(HADDR_UNDEF == (addr = H5MF_alloc(f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, (hsize_t)write_size)))
- HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap direct block")
+ /* Check if the filter mask changed */
+ if(hdr->pline_root_direct_filter_mask != filter_mask) {
+ hdr->pline_root_direct_filter_mask = filter_mask;
+ hdr_changed = TRUE;
+ } /* end if */
+
+ /* verify that the cache's last record of the compressed
+ * size matches the heap's last record. This value will
+ * likely change shortly.
+ */
+ HDassert(compressed_len == hdr->pline_root_direct_size);
+
+ /* Check if we need to re-size the block on disk */
+ if(hdr->pline_root_direct_size != write_size || at_tmp_addr) {
+ /* Check if the direct block is NOT currently allocated
+ * in temp. file space
+ *
+ * (temp. file space does not need to be freed)
+ */
+ if(!at_tmp_addr) {
+ /* Release direct block's current disk space */
+ if(H5MF_xfree(f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, addr, (hsize_t)hdr->pline_root_direct_size) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap direct block")
+ } /* end if */
- /* Sanity check */
- HDassert(!H5F_addr_eq(hdr->man_dtable.table_addr, addr));
+ /* Allocate space for the compressed direct block */
+ if(HADDR_UNDEF == (dblock_addr = H5MF_alloc((H5F_t *)f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, (hsize_t)write_size)))
+ HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap direct block")
- /* Let the metadata cache know the block moved */
- if(H5AC_move_entry(f, H5AC_FHEAP_DBLOCK, hdr->man_dtable.table_addr, addr) < 0)
+ /* Let the metadata cache know, if the block moved */
+ if(!H5F_addr_eq(hdr->man_dtable.table_addr, dblock_addr))
+ if(H5AC_move_entry((H5F_t *)f, H5AC_FHEAP_DBLOCK, hdr->man_dtable.table_addr, dblock_addr) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTMOVE, FAIL, "unable to move direct block")
- /* Update information about direct block's location */
- hdr->man_dtable.table_addr = addr;
+ /* Update information about compressed direct block's
+ * location & size
+ */
+ HDassert(hdr->man_dtable.table_addr == addr);
+ HDassert(hdr->pline_root_direct_size == compressed_len);
+ hdr->man_dtable.table_addr = dblock_addr;
+ hdr->pline_root_direct_size = write_size;
- /* Mark that heap header was modified */
- if(H5HF_hdr_dirty(hdr) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty")
- } /* end if */
- else {
- H5HF_indirect_t *par_iblock; /* Parent indirect block */
- unsigned par_entry; /* Entry in parent indirect block */
+ /* Note that heap header was modified */
+ hdr_changed = TRUE;
+ } /* end if */
+
+ /* Check if heap header was modified */
+ if(hdr_changed)
+ if(H5HF_hdr_dirty(hdr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty")
+ } /* end if */
+ else { /* the direct block's parent is an indirect block */
+ hbool_t par_changed = FALSE; /* Whether the parent's infochanged */
+
+ /* Sanity check */
+ HDassert(par_iblock);
+ HDassert(par_iblock->filt_ents[par_entry].size > 0);
- /* Get parent information */
- par_iblock = dblock->parent;
- par_entry = dblock->par_entry;
+ /* Check if the filter mask changed */
+ if(par_iblock->filt_ents[par_entry].filter_mask != filter_mask) {
+ par_iblock->filt_ents[par_entry].filter_mask = filter_mask;
+ par_changed = TRUE;
+ } /* end if */
- /* Sanity check */
- HDassert(H5F_addr_eq(par_iblock->ents[par_entry].addr, addr));
+ /* verify that the cache's last record of the compressed
+ * size matches the heap's last record. This value will
+ * likely change shortly.
+ */
+ HDassert(compressed_len == par_iblock->filt_ents[par_entry].size);
- /* Allocate 'normal' space for the direct block */
- if(HADDR_UNDEF == (addr = H5MF_alloc(f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, (hsize_t)write_size)))
- HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap direct block")
+ /* Check if we need to re-size the block on disk */
+ if(par_iblock->filt_ents[par_entry].size != write_size || at_tmp_addr) {
+ /* Check if the direct block is NOT currently allocated
+ * in temp. file space
+ *
+ * (temp. file space does not need to be freed)
+ */
+ if(!at_tmp_addr) {
+ /* Release direct block's current disk space */
+ if(H5MF_xfree(f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, addr, (hsize_t)par_iblock->filt_ents[par_entry].size) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap direct block")
+ } /* end if */
- /* Sanity check */
- HDassert(!H5F_addr_eq(par_iblock->ents[par_entry].addr, addr));
+ /* Allocate space for the compressed direct block */
+ if(HADDR_UNDEF == (dblock_addr = H5MF_alloc((H5F_t *)f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, (hsize_t)write_size)))
+ HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap direct block")
- /* Let the metadata cache know the block moved */
- if(H5AC_move_entry(f, H5AC_FHEAP_DBLOCK, par_iblock->ents[par_entry].addr, addr) < 0)
+ /* Let the metadata cache know, if the block moved */
+ if(!H5F_addr_eq(par_iblock->ents[par_entry].addr, dblock_addr))
+ if(H5AC_move_entry((H5F_t *)f, H5AC_FHEAP_DBLOCK, par_iblock->ents[par_entry].addr, dblock_addr) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTMOVE, FAIL, "unable to move direct block")
- /* Update information about direct block's location */
- par_iblock->ents[par_entry].addr = addr;
+ /* Update information about compressed direct block's
+ * location & size
+ */
+ HDassert(par_iblock->ents[par_entry].addr == addr);
+ HDassert(par_iblock->filt_ents[par_entry].size == compressed_len);
+ par_iblock->ents[par_entry].addr = dblock_addr;
+ par_iblock->filt_ents[par_entry].size = write_size;
- /* Mark that parent was modified */
- if(H5HF_iblock_dirty(par_iblock) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty")
- } /* end else */
+ /* Note that parent was modified */
+ par_changed = TRUE;
} /* end if */
+
+ /* Check if parent was modified */
+ if(par_changed)
+ if(H5HF_iblock_dirty(par_iblock) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty")
} /* end else */
+ } /* end if */
+ else {
+ /* I/O filters are not enabled -- thus all we need to do is check to
+ * see if the direct block is in temporary (AKA imaginary) file
+ * space, and move it to real file space if it is.
+ *
+ * As in the I/O filters case above, we will have to touch up the
+ * direct blocks parent if the direct block is relocated.
+ *
+ * Recall that temporary file space need not be freed, which
+ * simplifies matters slightly.
+ */
+ write_buf = dblock->blk;
+ write_size = dblock->size;
- /* Direct block must be in 'normal' file space now */
- HDassert(!H5F_IS_TMP_ADDR(f, addr));
+ /* Check to see if we must re-allocate direct block from 'temp.'
+ * to 'normal' file space
+ */
+ if(at_tmp_addr) {
+ /* Check for root direct block */
+ if(NULL == dblock->parent) {
+ /* Sanity check */
+ HDassert(H5F_addr_eq(hdr->man_dtable.table_addr, addr));
- /* Write the direct block */
- if(H5F_block_write(f, H5FD_MEM_FHEAP_DBLOCK, addr, write_size, dxpl_id, write_buf) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFLUSH, FAIL, "unable to save fractal heap direct block to disk")
+ /* Allocate 'normal' space for the direct block */
+ if(HADDR_UNDEF == (dblock_addr = H5MF_alloc((H5F_t *)f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, (hsize_t)write_size)))
+ HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap direct block")
- /* Release the write buffer, if it was allocated */
- if(write_buf != dblock->blk)
- H5MM_xfree(write_buf);
+ /* Sanity check */
+ HDassert(!H5F_addr_eq(hdr->man_dtable.table_addr, dblock_addr));
- dblock->cache_info.is_dirty = FALSE;
- } /* end if */
+ /* Let the metadata cache know the block moved */
+ if(H5AC_move_entry((H5F_t *)f, H5AC_FHEAP_DBLOCK, hdr->man_dtable.table_addr, dblock_addr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTMOVE, FAIL, "unable to move direct block")
- if(destroy)
- if(H5HF_cache_dblock_dest(f, dblock) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy fractal heap direct block")
+ /* Update information about direct block's location */
+ hdr->man_dtable.table_addr = dblock_addr;
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5HF_cache_dblock_flush() */
+ /* Mark that heap header was modified */
+ if(H5HF_hdr_dirty(hdr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty")
+ } /* end if */
+ else { /* the direct block's parent is an indirect block */
+ /* Sanity check */
+ HDassert(par_iblock);
+ HDassert(H5F_addr_eq(par_iblock->ents[par_entry].addr, addr));
-
-/*-------------------------------------------------------------------------
- * Function: H5HF_cache_dblock_dest
- *
- * Purpose: Destroys a fractal heap direct block in memory.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 27 2006
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5HF_cache_dblock_dest(H5F_t *f, H5HF_direct_t *dblock)
-{
- herr_t ret_value = SUCCEED; /* Return value */
+ /* Allocate 'normal' space for the direct block */
+ if(HADDR_UNDEF == (dblock_addr = H5MF_alloc((H5F_t *)f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, (hsize_t)write_size)))
+ HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap direct block")
- FUNC_ENTER_NOAPI_NOINIT
+ /* Sanity check */
+ HDassert(!H5F_addr_eq(par_iblock->ents[par_entry].addr, dblock_addr));
- /*
- * Check arguments.
- */
- HDassert(dblock);
+ /* Let the metadata cache know the block moved */
+ if(H5AC_move_entry((H5F_t *)f, H5AC_FHEAP_DBLOCK, par_iblock->ents[par_entry].addr, dblock_addr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTMOVE, FAIL, "unable to move direct block")
- /* If we're going to free the space on disk, the address must be valid */
- HDassert(!dblock->cache_info.free_file_space_on_destroy || H5F_addr_defined(dblock->cache_info.addr));
+ /* Update information about direct block's location */
+ par_iblock->ents[par_entry].addr = dblock_addr;
- /* Check for freeing file space for direct block */
- if(dblock->cache_info.free_file_space_on_destroy) {
- /* Sanity check */
- HDassert(dblock->file_size > 0);
-
- /* Check if the direct block is NOT currently allocated in temp. file space */
- /* (temp. file space does not need to be freed) */
- if(!H5F_IS_TMP_ADDR(f, dblock->cache_info.addr)) {
- /* Release the space on disk */
- /* (XXX: Nasty usage of internal DXPL value! -QAK) */
- if(H5MF_xfree(f, H5FD_MEM_FHEAP_DBLOCK, H5AC_dxpl_id, dblock->cache_info.addr, dblock->file_size) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap direct block")
+ /* Mark that parent was modified */
+ if(H5HF_iblock_dirty(par_iblock) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty")
+ } /* end else */
} /* end if */
+ } /* end else */
+
+ /* At this point, write_buf points to a buffer containing the image
+ * of the direct block that is ready to copy into the image buffer,
+ * and write_size contains the length of this buffer.
+ *
+ * Also, if image size or address has changed, the direct block's
+ * parent has been modified to reflect the change.
+ *
+ * Now, make note of the pointer and length of the above buffer for
+ * use by the serialize function.
+ */
+ dblock->write_buf = (uint8_t *)write_buf;
+ dblock->write_size = write_size;
+
+ /* finally, pass data back to the metadata cache as appropriate */
+ if(!H5F_addr_eq(addr, dblock_addr)) {
+ dblock_flags |= H5C__SERIALIZE_MOVED_FLAG;
+ *new_addr = dblock_addr;
} /* end if */
- /* Destroy fractal heap direct block */
- if(H5HF_man_dblock_dest(dblock) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy fractal heap direct block")
+ if((hdr->filter_len > 0) && (compressed_len != write_size)) {
+ dblock_flags |= H5C__SERIALIZE_COMPRESSED_FLAG;
+ *new_compressed_len = write_size;
+ } /* end if */
+
+ *flags = dblock_flags;
+
+ /* final sanity check */
+ HDassert(dblock->write_buf);
+ HDassert(dblock->write_size > 0);
done:
+ /* discard the write buf if we have an error */
+ if(write_buf && (write_buf != dblock->blk) && (dblock->write_buf == NULL))
+ H5MM_xfree(write_buf);
+
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5HF_cache_dblock_dest() */
+} /* end H5HF__cache_dblock_pre_serialize() */
/*-------------------------------------------------------------------------
- * Function: H5HF_cache_dblock_clear
+ * Function: H5HF__cache_dblock_serialize
*
- * Purpose: Mark a fractal heap direct block in memory as non-dirty.
+ * Purpose: In principle, this function is supposed to construct the on
+ * disk image of the direct block, and place that image in the
+ * image buffer provided by the metadata cache.
*
- * Return: Non-negative on success/Negative on failure
+ * However, since there are cases in which the pre_serialize
+ * function has to construct the on disk image to determine its size
+ * and address, this function simply copies the image prepared by
+ * the pre-serialize function into the supplied image buffer, and
+ * discards a buffer if necessary.
*
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 27 2006
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: John Mainzer
+ * 6/21/14
*
*-------------------------------------------------------------------------
*/
-static herr_t
-H5HF_cache_dblock_clear(H5F_t *f, H5HF_direct_t *dblock, hbool_t destroy)
+static herr_t
+H5HF__cache_dblock_serialize(const H5F_t *f, void *image, size_t len,
+ void *_thing)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ H5HF_direct_t *dblock = (H5HF_direct_t *)_thing; /* Direct block info */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC_NOERR
- /*
- * Check arguments.
- */
+ /* Sanity checks */
+ HDassert(f);
+ HDassert(image);
+ HDassert(len > 0);
HDassert(dblock);
+ HDassert(dblock->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(dblock->cache_info.type == H5AC_FHEAP_DBLOCK);
+ HDassert((dblock->blk != dblock->write_buf) || (dblock->cache_info.size == dblock->size));
+ HDassert(dblock->write_buf);
+ HDassert(dblock->write_size > 0);
+ HDassert((dblock->blk != dblock->write_buf) || (dblock->write_size == dblock->size));
+ HDassert(dblock->write_size == len);
+
+ /* Copy the image from *(dblock->write_buf) to *image */
+ HDmemcpy(image, dblock->write_buf, dblock->write_size);
+
+ /* Free *(dblock->write_buf) if it was allocated by the
+ * pre-serialize function
+ */
+ if(dblock->write_buf != dblock->blk)
+ H5MM_xfree(dblock->write_buf);
- /* Reset the dirty flag. */
- dblock->cache_info.is_dirty = FALSE;
-
- if(destroy)
- if(H5HF_cache_dblock_dest(f, dblock) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy fractal heap direct block")
+ /* Reset the write_buf and write_size fields */
+ dblock->write_buf = NULL;
+ dblock->write_size = 0;
-done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5HF_cache_dblock_clear() */
+} /* end H5HF__cache_dblock_serialize() */
/*-------------------------------------------------------------------------
- * Function: H5HF_cache_dblock_notify
+ * Function: H5HF__cache_dblock_notify
*
* Purpose: Setup / takedown flush dependencies as direct blocks
* are loaded / inserted and evicted from the metadata cache.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Success: SUCCEED
+ * Failure: FAIL
*
* Programmer: John Mainzer
- * 5/17/14
+ * 6/21/14
*
*-------------------------------------------------------------------------
*/
-static herr_t
-H5HF_cache_dblock_notify(H5C_notify_action_t action, H5HF_direct_t *dblock)
+static herr_t
+H5HF__cache_dblock_notify(H5C_notify_action_t action, void *_thing)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ H5HF_direct_t *dblock = (H5HF_direct_t *)_thing; /* Fractal heap direct block */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
- /*
- * Check arguments.
- */
+ /* Sanity checks */
HDassert(dblock);
HDassert(dblock->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(dblock->cache_info.type == H5AC_FHEAP_DBLOCK);
HDassert(dblock->hdr);
HDassert((dblock->fd_parent) ||
((dblock->hdr->man_dtable.curr_root_rows == 0) && (dblock->block_off == (hsize_t)0)));
switch(action) {
case H5AC_NOTIFY_ACTION_AFTER_INSERT:
+ case H5AC_NOTIFY_ACTION_AFTER_LOAD:
HDassert(dblock->parent == dblock->fd_parent);
if(dblock->parent) { /* this is a leaf dblock */
/* create flush dependency with parent iblock */
@@ -2001,6 +2678,10 @@ H5HF_cache_dblock_notify(H5C_notify_action_t action, H5HF_direct_t *dblock)
} /* end else */
break;
+ case H5AC_NOTIFY_ACTION_AFTER_FLUSH:
+ /* do nothing */
+ break;
+
case H5AC_NOTIFY_ACTION_BEFORE_EVICT:
HDassert((dblock->parent == dblock->fd_parent) ||
((NULL == dblock->parent) && (dblock->fd_parent)));
@@ -2023,39 +2704,47 @@ H5HF_cache_dblock_notify(H5C_notify_action_t action, H5HF_direct_t *dblock)
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5HF_cache_dblock_notify() */
+} /* end H5HF__cache_dblock_notify() */
/*-------------------------------------------------------------------------
- * Function: H5HF_cache_dblock_size
+ * Function: H5HF__cache_dblock_free_icr
*
- * Purpose: Compute the size in bytes of a fractal heap direct block
- * on disk, and return it in *size_ptr. On failure,
- * the value of *size_ptr is undefined.
+ * Purpose: Free the in core memory allocated to the supplied direct
+ * block.
*
- * Return: Non-negative on success/Negative on failure
+ * Note: The metadata cache sets the object's cache_info.magic to
+ * H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC before calling a free_icr
+ * callback (checked in assert).
*
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 24 2006
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: John Mainzer
+ * 6/21/14
*
*-------------------------------------------------------------------------
*/
-static herr_t
-H5HF_cache_dblock_size(const H5F_t H5_ATTR_UNUSED *f, const H5HF_direct_t *dblock, size_t *size_ptr)
+static herr_t
+H5HF__cache_dblock_free_icr(void *_thing)
{
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ H5HF_direct_t *dblock = (H5HF_direct_t *)_thing; /* Fractal heap direct block */
+ herr_t ret_value = SUCCEED; /* Return value */
- /* check arguments */
- HDassert(dblock);
- HDassert(size_ptr);
+ FUNC_ENTER_STATIC
- /* Set size value */
- *size_ptr = dblock->size;
+ /* Sanity checks */
+ HDassert(dblock);
+ HDassert(dblock->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC);
+ HDassert(dblock->cache_info.type == H5AC_FHEAP_DBLOCK);
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5HF_cache_dblock_size() */
+ /* Destroy fractal heap direct block */
+ if(H5HF_man_dblock_dest(dblock) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy fractal heap direct block")
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF__cache_dblock_free_icr() */
/*------------------------------------------------------------------------
@@ -2181,7 +2870,7 @@ H5HF__cache_verify_hdr_descendants_clean(H5F_t *f, hid_t dxpl_id,
* in this case, since we know that the entry is in cache,
* we can pass NULL udata.
*/
- if(NULL == (root_iblock = (H5HF_indirect_t *)H5AC_protect(f, dxpl_id, H5AC_FHEAP_IBLOCK, root_iblock_addr, NULL, H5AC_READ)))
+ if(NULL == (root_iblock = (H5HF_indirect_t *)H5AC_protect(f, dxpl_id, H5AC_FHEAP_IBLOCK, root_iblock_addr, NULL, H5C__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "H5AC_protect() faild.")
unprotect_root_iblock = TRUE;
} /* end if */
@@ -2242,7 +2931,7 @@ H5HF__cache_verify_hdr_descendants_clean(H5F_t *f, hid_t dxpl_id,
* in this case, since we know that the entry is in cache,
* we can pass NULL udata.
*/
- if(NULL == (iblock = (H5HF_indirect_t *)H5AC_protect(f, dxpl_id, H5AC_FHEAP_IBLOCK, root_iblock_addr, NULL, H5AC_READ)))
+ if(NULL == (iblock = (H5HF_indirect_t *)H5AC_protect(f, dxpl_id, H5AC_FHEAP_IBLOCK, root_iblock_addr, NULL, H5C__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "H5AC_protect() faild.")
unprotect_root_iblock = TRUE;
HDassert(iblock == root_iblock);
@@ -2632,7 +3321,7 @@ H5HF__cache_verify_descendant_iblocks_clean(H5F_t *f, hid_t dxpl_id,
/* in this case, since we know that the */
/* entry is in cache, we can pass NULL udata */
- if(NULL == (child_iblock = (H5HF_indirect_t *) H5AC_protect(f, dxpl_id, H5AC_FHEAP_IBLOCK, child_iblock_addr, NULL, H5AC_READ)))
+ if(NULL == (child_iblock = (H5HF_indirect_t *) H5AC_protect(f, dxpl_id, H5AC_FHEAP_IBLOCK, child_iblock_addr, NULL, H5C__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "H5AC_protect() faild.")
unprotect_child_iblock = TRUE;
} /* end if */
diff --git a/src/H5HFdbg.c b/src/H5HFdbg.c
index 8620f6f..5183b67 100644
--- a/src/H5HFdbg.c
+++ b/src/H5HFdbg.c
@@ -323,7 +323,7 @@ H5HF_hdr_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent,
HDassert(fwidth >= 0);
/* Load the fractal heap header */
- if(NULL == (hdr = H5HF_hdr_protect(f, dxpl_id, addr, H5AC_READ)))
+ if(NULL == (hdr = H5HF_hdr_protect(f, dxpl_id, addr, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap header")
/* Print the information about the heap's header */
@@ -459,13 +459,13 @@ H5HF_dblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream,
HDassert(block_size > 0);
/* Load the fractal heap header */
- if(NULL == (hdr = H5HF_hdr_protect(f, dxpl_id, hdr_addr, H5AC_READ)))
+ if(NULL == (hdr = H5HF_hdr_protect(f, dxpl_id, hdr_addr, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap header")
/*
* Load the heap direct block
*/
- if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, addr, block_size, NULL, 0, H5AC_READ)))
+ if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, addr, block_size, NULL, 0, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load fractal heap direct block")
/* Print opening message */
@@ -716,13 +716,13 @@ H5HF_iblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream,
HDassert(nrows > 0);
/* Load the fractal heap header */
- if(NULL == (hdr = H5HF_hdr_protect(f, dxpl_id, hdr_addr, H5AC_READ)))
+ if(NULL == (hdr = H5HF_hdr_protect(f, dxpl_id, hdr_addr, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap header")
/*
* Load the heap indirect block
*/
- if(NULL == (iblock = H5HF_man_iblock_protect(hdr, dxpl_id, addr, nrows, NULL, 0, FALSE, H5AC_READ, &did_protect)))
+ if(NULL == (iblock = H5HF_man_iblock_protect(hdr, dxpl_id, addr, nrows, NULL, 0, FALSE, H5AC__READ_ONLY_FLAG, &did_protect)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load fractal heap indirect block")
/* Print the information about the heap's indirect block */
@@ -825,7 +825,7 @@ H5HF_sects_debug(H5F_t *f, hid_t dxpl_id, haddr_t fh_addr,
HDassert(fwidth >= 0);
/* Load the fractal heap header */
- if(NULL == (hdr = H5HF_hdr_protect(f, dxpl_id, fh_addr, H5AC_READ)))
+ if(NULL == (hdr = H5HF_hdr_protect(f, dxpl_id, fh_addr, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap header")
/* Initialize the free space information for the heap */
diff --git a/src/H5HFdblock.c b/src/H5HFdblock.c
index 3a54bb9..0d5172c 100644
--- a/src/H5HFdblock.c
+++ b/src/H5HFdblock.c
@@ -149,6 +149,9 @@ H5HF_man_dblock_create(hid_t dxpl_id, H5HF_hdr_t *hdr, H5HF_indirect_t *par_iblo
HDmemset(dblock->blk, 0, dblock->size);
#endif /* H5_CLEAR_MEMORY */
+ dblock->write_buf = NULL;
+ dblock->write_size = 0;
+
/* Allocate [temporary] space for the direct block on disk */
if(H5F_USE_TMP_SPACE(hdr->f)) {
if(HADDR_UNDEF == (dblock_addr = H5MF_alloc_tmp(hdr->f, (hsize_t)dblock->size)))
@@ -308,9 +311,13 @@ H5HF_man_dblock_destroy(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_direct_t *dblock,
} /* end if */
} /* end else */
- /* Indicate that the indirect block should be deleted & file space freed */
+ /* Indicate that the indirect block should be deleted */
dblock->file_size = dblock_size;
- cache_flags |= H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG;
+ cache_flags |= H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG;
+
+ /* If the dblock is in real file space, also tell the cache to free its file space */
+ if (!H5F_IS_TMP_ADDR(hdr->f, dblock_addr))
+ cache_flags |= H5AC__FREE_FILE_SPACE_FLAG;
done:
/* Unprotect the indirect block, with appropriate flags */
@@ -436,7 +443,7 @@ done:
H5HF_direct_t *
H5HF_man_dblock_protect(H5HF_hdr_t *hdr, hid_t dxpl_id, haddr_t dblock_addr,
size_t dblock_size, H5HF_indirect_t *par_iblock, unsigned par_entry,
- H5AC_protect_t rw)
+ unsigned flags)
{
H5HF_direct_t *dblock; /* Direct block from cache */
H5HF_dblock_cache_ud_t udata; /* parent and other infor for deserializing direct block */
@@ -451,6 +458,9 @@ H5HF_man_dblock_protect(H5HF_hdr_t *hdr, hid_t dxpl_id, haddr_t dblock_addr,
HDassert(H5F_addr_defined(dblock_addr));
HDassert(dblock_size > 0);
+ /* only H5AC__READ_ONLY_FLAG may appear in flags */
+ HDassert((flags & (~H5AC__READ_ONLY_FLAG)) == 0);
+
/* Set up parent info */
udata.par_info.hdr = hdr;
udata.par_info.iblock = par_iblock;
@@ -485,7 +495,7 @@ H5HF_man_dblock_protect(H5HF_hdr_t *hdr, hid_t dxpl_id, haddr_t dblock_addr,
} /* end else */
/* Protect the direct block */
- if(NULL == (dblock = (H5HF_direct_t *)H5AC_protect(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, dblock_addr, &udata, rw)))
+ if(NULL == (dblock = (H5HF_direct_t *)H5AC_protect(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, dblock_addr, &udata, flags)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to protect fractal heap direct block")
/* Set the return value */
@@ -512,7 +522,7 @@ done:
herr_t
H5HF_man_dblock_locate(H5HF_hdr_t *hdr, hid_t dxpl_id, hsize_t obj_off,
H5HF_indirect_t **ret_iblock, unsigned *ret_entry, hbool_t *ret_did_protect,
- H5AC_protect_t rw)
+ unsigned flags)
{
haddr_t iblock_addr; /* Indirect block's address */
H5HF_indirect_t *iblock; /* Pointer to indirect block */
@@ -531,6 +541,9 @@ H5HF_man_dblock_locate(H5HF_hdr_t *hdr, hid_t dxpl_id, hsize_t obj_off,
HDassert(ret_iblock);
HDassert(ret_did_protect);
+ /* only H5AC__READ_ONLY_FLAG may appear in flags */
+ HDassert((flags & (~H5AC__READ_ONLY_FLAG)) == 0);
+
/* Look up row & column for object */
if(H5HF_dtable_lookup(&hdr->man_dtable, obj_off, &row, &col) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTCOMPUTE, FAIL, "can't compute row & column of object")
@@ -539,7 +552,7 @@ H5HF_man_dblock_locate(H5HF_hdr_t *hdr, hid_t dxpl_id, hsize_t obj_off,
iblock_addr = hdr->man_dtable.table_addr;
/* Lock root indirect block */
- if(NULL == (iblock = H5HF_man_iblock_protect(hdr, dxpl_id, iblock_addr, hdr->man_dtable.curr_root_rows, NULL, 0, FALSE, rw, &did_protect)))
+ if(NULL == (iblock = H5HF_man_iblock_protect(hdr, dxpl_id, iblock_addr, hdr->man_dtable.curr_root_rows, NULL, 0, FALSE, flags, &did_protect)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block")
/* Check for indirect block row */
@@ -569,7 +582,7 @@ H5HF_man_dblock_locate(H5HF_hdr_t *hdr, hid_t dxpl_id, hsize_t obj_off,
} /* end if */
/* Lock child indirect block */
- if(NULL == (new_iblock = H5HF_man_iblock_protect(hdr, dxpl_id, iblock_addr, nrows, iblock, entry, FALSE, rw, &new_did_protect)))
+ if(NULL == (new_iblock = H5HF_man_iblock_protect(hdr, dxpl_id, iblock_addr, nrows, iblock, entry, FALSE, flags, &new_did_protect)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block")
/* Release the current indirect block */
diff --git a/src/H5HFhdr.c b/src/H5HFhdr.c
index bfc8fc6..814d524 100644
--- a/src/H5HFhdr.c
+++ b/src/H5HFhdr.c
@@ -530,7 +530,7 @@ done:
*-------------------------------------------------------------------------
*/
H5HF_hdr_t *
-H5HF_hdr_protect(H5F_t *f, hid_t dxpl_id, haddr_t addr, H5AC_protect_t rw)
+H5HF_hdr_protect(H5F_t *f, hid_t dxpl_id, haddr_t addr, unsigned flags)
{
H5HF_hdr_cache_ud_t cache_udata; /* User-data for callback */
H5HF_hdr_t *hdr; /* Fractal heap header */
@@ -542,12 +542,15 @@ H5HF_hdr_protect(H5F_t *f, hid_t dxpl_id, haddr_t addr, H5AC_protect_t rw)
HDassert(f);
HDassert(H5F_addr_defined(addr));
+ /* only H5AC__READ_ONLY_FLAG may appear in flags */
+ HDassert((flags & (unsigned)(~H5AC__READ_ONLY_FLAG)) == 0);
+
/* Set up userdata for protect call */
cache_udata.f = f;
cache_udata.dxpl_id = dxpl_id;
/* Lock the heap header into memory */
- if(NULL == (hdr = (H5HF_hdr_t *)H5AC_protect(f, dxpl_id, H5AC_FHEAP_HDR, addr, &cache_udata, rw)))
+ if(NULL == (hdr = (H5HF_hdr_t *)H5AC_protect(f, dxpl_id, H5AC_FHEAP_HDR, addr, &cache_udata, flags)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to protect fractal heap header")
/* Set the header's address */
@@ -1110,7 +1113,7 @@ H5HF_hdr_update_iter(H5HF_hdr_t *hdr, hid_t dxpl_id, size_t min_dblock_size)
HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't allocate fractal heap indirect block")
/* Lock new indirect block */
- if(NULL == (new_iblock = H5HF_man_iblock_protect(hdr, dxpl_id, new_iblock_addr, child_nrows, iblock, next_entry, FALSE, H5AC_WRITE, &did_protect)))
+ if(NULL == (new_iblock = H5HF_man_iblock_protect(hdr, dxpl_id, new_iblock_addr, child_nrows, iblock, next_entry, FALSE, H5AC__NO_FLAGS_SET, &did_protect)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block")
/* Move iterator down one level (pins indirect block) */
@@ -1304,7 +1307,7 @@ H5HF_hdr_reverse_iter(H5HF_hdr_t *hdr, hid_t dxpl_id, haddr_t dblock_addr)
child_nrows = H5HF_dtable_size_to_rows(&hdr->man_dtable, hdr->man_dtable.row_block_size[row]);
/* Lock child indirect block */
- if(NULL == (child_iblock = H5HF_man_iblock_protect(hdr, dxpl_id, iblock->ents[curr_entry].addr, child_nrows, iblock, curr_entry, FALSE, H5AC_WRITE, &did_protect)))
+ if(NULL == (child_iblock = H5HF_man_iblock_protect(hdr, dxpl_id, iblock->ents[curr_entry].addr, child_nrows, iblock, curr_entry, FALSE, H5AC__NO_FLAGS_SET, &did_protect)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block")
/* Set the current location of the iterator */
diff --git a/src/H5HFiblock.c b/src/H5HFiblock.c
index 4473803..547aaf0 100644
--- a/src/H5HFiblock.c
+++ b/src/H5HFiblock.c
@@ -330,8 +330,15 @@ H5HF_iblock_decr(H5HF_indirect_t *iblock)
/* Check for expunging the indirect block from the metadata cache */
if(expunge_iblock) {
- /* Evict the indirect block from the metadata cache */
- if(H5AC_expunge_entry(hdr->f, H5AC_dxpl_id, H5AC_FHEAP_IBLOCK, iblock_addr, H5AC__FREE_FILE_SPACE_FLAG) < 0)
+ unsigned cache_flags = H5AC__NO_FLAGS_SET;
+
+ /* if the indirect block is in real file space, tell
+ * the cache to free its file space.
+ */
+ if (!H5F_IS_TMP_ADDR(hdr->f, iblock_addr))
+ cache_flags |= H5AC__FREE_FILE_SPACE_FLAG;
+
+ if(H5AC_expunge_entry(hdr->f, H5AC_dxpl_id, H5AC_FHEAP_IBLOCK, iblock_addr, cache_flags) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTREMOVE, FAIL, "unable to remove indirect block from cache")
} /* end if */
} /* end if */
@@ -424,7 +431,7 @@ H5HF_man_iblock_root_create(H5HF_hdr_t *hdr, hid_t dxpl_id, size_t min_dblock_si
/* Move current direct block (used as root) into new indirect block */
/* Lock new indirect block */
- if(NULL == (iblock = H5HF_man_iblock_protect(hdr, dxpl_id, iblock_addr, nrows, NULL, 0, FALSE, H5AC_WRITE, &did_protect)))
+ if(NULL == (iblock = H5HF_man_iblock_protect(hdr, dxpl_id, iblock_addr, nrows, NULL, 0, FALSE, H5AC__NO_FLAGS_SET, &did_protect)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block")
/* Check if there's already a direct block as root) */
@@ -433,7 +440,7 @@ H5HF_man_iblock_root_create(H5HF_hdr_t *hdr, hid_t dxpl_id, size_t min_dblock_si
H5HF_direct_t *dblock; /* Pointer to direct block to query */
/* Lock first (root) direct block */
- if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, hdr->man_dtable.table_addr, hdr->man_dtable.cparam.start_block_size, NULL, 0, H5AC_WRITE)))
+ if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, hdr->man_dtable.table_addr, hdr->man_dtable.cparam.start_block_size, NULL, 0, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap direct block")
/* Attach direct block to new root indirect block */
@@ -879,7 +886,7 @@ H5HF_man_iblock_root_revert(H5HF_indirect_t *root_iblock, hid_t dxpl_id)
dblock_size = hdr->man_dtable.cparam.start_block_size;
/* Get pointer to last direct block */
- if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, dblock_addr, dblock_size, root_iblock, 0, H5AC_WRITE)))
+ if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, dblock_addr, dblock_size, root_iblock, 0, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap direct block")
HDassert(dblock->parent == root_iblock);
HDassert(dblock->par_entry == 0);
@@ -1159,7 +1166,7 @@ done:
H5HF_indirect_t *
H5HF_man_iblock_protect(H5HF_hdr_t *hdr, hid_t dxpl_id, haddr_t iblock_addr,
unsigned iblock_nrows, H5HF_indirect_t *par_iblock, unsigned par_entry,
- hbool_t must_protect, H5AC_protect_t rw, hbool_t *did_protect)
+ hbool_t must_protect, unsigned flags, hbool_t *did_protect)
{
H5HF_parent_t par_info; /* Parent info for loading block */
H5HF_indirect_t *iblock = NULL; /* Indirect block from cache */
@@ -1176,6 +1183,9 @@ H5HF_man_iblock_protect(H5HF_hdr_t *hdr, hid_t dxpl_id, haddr_t iblock_addr,
HDassert(iblock_nrows > 0);
HDassert(did_protect);
+ /* only H5AC__READ_ONLY_FLAG may appear in flags */
+ HDassert((flags & (unsigned)(~H5AC__READ_ONLY_FLAG)) == 0);
+
/* Check if we are allowed to use existing pinned iblock pointer */
if(!must_protect) {
/* Check for this block already being pinned */
@@ -1235,7 +1245,7 @@ H5HF_man_iblock_protect(H5HF_hdr_t *hdr, hid_t dxpl_id, haddr_t iblock_addr,
cache_udata.nrows = &iblock_nrows;
/* Protect the indirect block */
- if(NULL == (iblock = (H5HF_indirect_t *)H5AC_protect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock_addr, &cache_udata, rw)))
+ if(NULL == (iblock = (H5HF_indirect_t *)H5AC_protect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock_addr, &cache_udata, flags)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to protect fractal heap indirect block")
/* Set the indirect block's address */
@@ -1579,7 +1589,7 @@ H5HF_man_iblock_delete(H5HF_hdr_t *hdr, hid_t dxpl_id, haddr_t iblock_addr,
HDassert(iblock_nrows > 0);
/* Lock indirect block */
- if(NULL == (iblock = H5HF_man_iblock_protect(hdr, dxpl_id, iblock_addr, iblock_nrows, par_iblock, par_entry, TRUE, H5AC_WRITE, &did_protect)))
+ if(NULL == (iblock = H5HF_man_iblock_protect(hdr, dxpl_id, iblock_addr, iblock_nrows, par_iblock, par_entry, TRUE, H5AC__NO_FLAGS_SET, &did_protect)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block")
HDassert(iblock->nchildren > 0);
HDassert(did_protect == TRUE);
@@ -1637,8 +1647,14 @@ H5HF_man_iblock_delete(H5HF_hdr_t *hdr, hid_t dxpl_id, haddr_t iblock_addr,
}
#endif /* NDEBUG */
- /* Indicate that the indirect block should be deleted & file space freed */
- cache_flags |= H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG;
+ /* Indicate that the indirect block should be deleted */
+ cache_flags |= H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG;
+
+ /* If the indirect block is in real file space, tell
+ * the cache to free its file space as well.
+ */
+ if (!H5F_IS_TMP_ADDR(hdr->f, iblock_addr))
+ cache_flags |= H5AC__FREE_FILE_SPACE_FLAG;
done:
/* Unprotect the indirect block, with appropriate flags */
@@ -1680,7 +1696,7 @@ H5HF_man_iblock_size(H5F_t *f, hid_t dxpl_id, H5HF_hdr_t *hdr, haddr_t iblock_ad
HDassert(heap_size);
/* Protect the indirect block */
- if(NULL == (iblock = H5HF_man_iblock_protect(hdr, dxpl_id, iblock_addr, nrows, par_iblock, par_entry, FALSE, H5AC_READ, &did_protect)))
+ if(NULL == (iblock = H5HF_man_iblock_protect(hdr, dxpl_id, iblock_addr, nrows, par_iblock, par_entry, FALSE, H5AC__READ_ONLY_FLAG, &did_protect)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load fractal heap indirect block")
/* Accumulate size of this indirect block */
diff --git a/src/H5HFiter.c b/src/H5HFiter.c
index 137d0ee..262a9ee 100644
--- a/src/H5HFiter.c
+++ b/src/H5HFiter.c
@@ -217,7 +217,7 @@ H5HF_man_iter_start_offset(H5HF_hdr_t *hdr, hid_t dxpl_id,
} /* end else */
/* Load indirect block for this context location */
- if(NULL == (iblock = H5HF_man_iblock_protect(hdr, dxpl_id, iblock_addr, iblock_nrows, iblock_parent, iblock_par_entry, FALSE, H5AC_WRITE, &did_protect)))
+ if(NULL == (iblock = H5HF_man_iblock_protect(hdr, dxpl_id, iblock_addr, iblock_nrows, iblock_parent, iblock_par_entry, FALSE, H5AC__NO_FLAGS_SET, &did_protect)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block")
/* Make indirect block the context for the current location */
diff --git a/src/H5HFman.c b/src/H5HFman.c
index 58dab10..5f95a91 100644
--- a/src/H5HFman.c
+++ b/src/H5HFman.c
@@ -161,7 +161,7 @@ H5HF_man_insert(H5HF_hdr_t *hdr, hid_t dxpl_id, size_t obj_size, const void *obj
HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't retrieve direct block information")
/* Lock direct block */
- if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, dblock_addr, dblock_size, sec_node->u.single.parent, sec_node->u.single.par_entry, H5AC_WRITE)))
+ if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, dblock_addr, dblock_size, sec_node->u.single.parent, sec_node->u.single.par_entry, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to load fractal heap direct block")
/* Insert object into block */
@@ -274,7 +274,11 @@ H5HF_man_op_real(H5HF_hdr_t *hdr, hid_t dxpl_id, const uint8_t *id,
H5HF_operator_t op, void *op_data, unsigned op_flags)
{
H5HF_direct_t *dblock = NULL; /* Pointer to direct block to query */
- H5AC_protect_t dblock_access; /* Access method for direct block */
+ unsigned dblock_access_flags; /* Access method for direct block */
+ /* must equal either
+ * H5AC__NO_FLAGS_SET or
+ * H5AC__READ_ONLY_FLAG
+ */
haddr_t dblock_addr; /* Direct block address */
size_t dblock_size; /* Direct block size */
unsigned dblock_cache_flags; /* Flags for unprotecting direct block */
@@ -298,11 +302,11 @@ H5HF_man_op_real(H5HF_hdr_t *hdr, hid_t dxpl_id, const uint8_t *id,
/* Check pipeline */
H5HF_MAN_WRITE_CHECK_PLINE(hdr)
- dblock_access = H5AC_WRITE;
+ dblock_access_flags = H5AC__NO_FLAGS_SET;
dblock_cache_flags = H5AC__DIRTIED_FLAG;
} /* end if */
else {
- dblock_access = H5AC_READ;
+ dblock_access_flags = H5AC__READ_ONLY_FLAG;
dblock_cache_flags = H5AC__NO_FLAGS_SET;
} /* end else */
@@ -332,7 +336,7 @@ H5HF_man_op_real(H5HF_hdr_t *hdr, hid_t dxpl_id, const uint8_t *id,
dblock_size = hdr->man_dtable.cparam.start_block_size;
/* Lock direct block */
- if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, dblock_addr, dblock_size, NULL, 0, dblock_access)))
+ if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, dblock_addr, dblock_size, NULL, 0, dblock_access_flags)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap direct block")
} /* end if */
else {
@@ -341,7 +345,7 @@ H5HF_man_op_real(H5HF_hdr_t *hdr, hid_t dxpl_id, const uint8_t *id,
unsigned entry; /* Entry of block */
/* Look up indirect block containing direct block */
- if(H5HF_man_dblock_locate(hdr, dxpl_id, obj_off, &iblock, &entry, &did_protect, H5AC_READ) < 0)
+ if(H5HF_man_dblock_locate(hdr, dxpl_id, obj_off, &iblock, &entry, &did_protect, H5AC__READ_ONLY_FLAG) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTCOMPUTE, FAIL, "can't compute row & column of section")
/* Set direct block info */
@@ -359,7 +363,7 @@ H5HF_man_op_real(H5HF_hdr_t *hdr, hid_t dxpl_id, const uint8_t *id,
} /* end if */
/* Lock direct block */
- if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, dblock_addr, dblock_size, iblock, entry, dblock_access))) {
+ if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, dblock_addr, dblock_size, iblock, entry, dblock_access_flags))) {
/* Unlock indirect block */
if(H5HF_man_iblock_unprotect(iblock, dxpl_id, H5AC__NO_FLAGS_SET, did_protect) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block")
@@ -578,7 +582,7 @@ H5HF_man_remove(H5HF_hdr_t *hdr, hid_t dxpl_id, const uint8_t *id)
} /* end if */
else {
/* Look up indirect block containing direct block */
- if(H5HF_man_dblock_locate(hdr, dxpl_id, obj_off, &iblock, &dblock_entry, &did_protect, H5AC_WRITE) < 0)
+ if(H5HF_man_dblock_locate(hdr, dxpl_id, obj_off, &iblock, &dblock_entry, &did_protect, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTCOMPUTE, FAIL, "can't compute row & column of section")
/* Check for offset of invalid direct block */
diff --git a/src/H5HFpkg.h b/src/H5HFpkg.h
index b0eba2f..cb5488b 100644
--- a/src/H5HFpkg.h
+++ b/src/H5HFpkg.h
@@ -341,7 +341,7 @@ typedef struct H5HF_hdr_t {
size_t rc; /* Reference count of heap's components using heap header */
haddr_t heap_addr; /* Address of heap header in the file */
size_t heap_size; /* Size of heap header in the file */
- H5AC_protect_t mode; /* Access mode for heap */
+ unsigned mode; /* Access mode for heap */
H5F_t *f; /* Pointer to file for heap */
size_t file_rc; /* Reference count of files using heap header */
hbool_t pending_delete; /* Heap is pending deletion */
@@ -425,6 +425,31 @@ typedef struct H5HF_direct_t {
size_t size; /* Size of direct block */
hsize_t file_size; /* Size of direct block in file (only valid when block's space is being freed) */
uint8_t *blk; /* Pointer to buffer containing block data */
+ uint8_t *write_buf; /* Pointer to buffer containing the block data */
+ /* in form ready to copy to the metadata */
+ /* cache's image buffer. */
+ /* */
+ /* This field is used by */
+ /* H5HF_cache_dblock_pre_serialize() to pass */
+ /* the serialized image of the direct block to */
+ /* H5HF_cache_dblock_serialize(). It should */
+ /* NULL at all other times. */
+ /* */
+ /* If I/O filters are enabled, the pre- */
+ /* the pre-serialize function will allocate */
+ /* a buffer, copy the filtered version of the */
+ /* direct block image into it, and place the */
+ /* base address of the buffer in this field. */
+ /* The serialize function must discard this */
+ /* buffer after it copies the contents into */
+ /* the image buffer provided by the metadata */
+ /* cache. */
+ /* */
+ /* If I/O filters are not enabled, the */
+ /* write_buf field is simply set equal to the */
+ /* blk field by the pre-serialize function, */
+ /* and back to NULL by the serialize function. */
+ size_t write_size; /* size of the buffer pointed to by write_buf. */
/* Stored values */
hsize_t block_off; /* Offset of the block within the heap's address space */
@@ -520,6 +545,14 @@ typedef struct H5HF_dblock_cache_ud_t {
* calls to it.
*/
unsigned filter_mask; /* Excluded filters for direct block */
+ uint8_t *dblk; /* Pointer to the buffer containing the decompressed
+ * direct block data obtained in verify_chksum callback.
+ * It will be used later in deserialize callback.
+ */
+ htri_t decompressed; /* Indicate that the direct block has been
+ * decompressed in verify_chksum callback.
+ * It will be used later in deserialize callback.
+ */
} H5HF_dblock_cache_ud_t;
@@ -604,7 +637,7 @@ H5_DLL hsize_t H5HF_dtable_span_size(const H5HF_dtable_t *dtable, unsigned start
H5_DLL H5HF_hdr_t * H5HF_hdr_alloc(H5F_t *f);
H5_DLL haddr_t H5HF_hdr_create(H5F_t *f, hid_t dxpl_id, const H5HF_create_t *cparam);
H5_DLL H5HF_hdr_t *H5HF_hdr_protect(H5F_t *f, hid_t dxpl_id, haddr_t addr,
- H5AC_protect_t rw);
+ unsigned flags);
H5_DLL herr_t H5HF_hdr_finish_init_phase1(H5HF_hdr_t *hdr);
H5_DLL herr_t H5HF_hdr_finish_init_phase2(H5HF_hdr_t *hdr);
H5_DLL herr_t H5HF_hdr_finish_init(H5HF_hdr_t *hdr);
@@ -645,7 +678,7 @@ H5_DLL herr_t H5HF_man_iblock_create(H5HF_hdr_t *hdr, hid_t dxpl_id,
H5_DLL H5HF_indirect_t *H5HF_man_iblock_protect(H5HF_hdr_t *hdr, hid_t dxpl_id,
haddr_t iblock_addr, unsigned iblock_nrows,
H5HF_indirect_t *par_iblock, unsigned par_entry, hbool_t must_protect,
- H5AC_protect_t rw, hbool_t *did_protect);
+ unsigned flags, hbool_t *did_protect);
H5_DLL herr_t H5HF_man_iblock_unprotect(H5HF_indirect_t *iblock, hid_t dxpl_id,
unsigned cache_flags, hbool_t did_protect);
H5_DLL herr_t H5HF_man_iblock_attach(H5HF_indirect_t *iblock, unsigned entry,
@@ -671,10 +704,10 @@ H5_DLL herr_t H5HF_man_dblock_destroy(H5HF_hdr_t *hdr, hid_t dxpl_id,
H5_DLL H5HF_direct_t *H5HF_man_dblock_protect(H5HF_hdr_t *hdr, hid_t dxpl_id,
haddr_t dblock_addr, size_t dblock_size,
H5HF_indirect_t *par_iblock, unsigned par_entry,
- H5AC_protect_t rw);
+ unsigned flags);
H5_DLL herr_t H5HF_man_dblock_locate(H5HF_hdr_t *hdr, hid_t dxpl_id,
hsize_t obj_off, H5HF_indirect_t **par_iblock,
- unsigned *par_entry, hbool_t *par_did_protect, H5AC_protect_t rw);
+ unsigned *par_entry, hbool_t *par_did_protect, unsigned flags);
H5_DLL herr_t H5HF_man_dblock_delete(H5F_t *f, hid_t dxpl_id, haddr_t dblock_addr,
hsize_t dblock_size);
H5_DLL herr_t H5HF_man_dblock_dest(H5HF_direct_t *dblock);
diff --git a/src/H5HFsection.c b/src/H5HFsection.c
index 7f960d4..6da456b 100644
--- a/src/H5HFsection.c
+++ b/src/H5HFsection.c
@@ -555,7 +555,7 @@ H5HF_sect_single_locate_parent(H5HF_hdr_t *hdr, hid_t dxpl_id, hbool_t refresh,
HDassert(sect);
/* Look up indirect block containing direct blocks for range */
- if(H5HF_man_dblock_locate(hdr, dxpl_id, sect->sect_info.addr, &sec_iblock, &sec_entry, &did_protect, H5AC_READ) < 0)
+ if(H5HF_man_dblock_locate(hdr, dxpl_id, sect->sect_info.addr, &sec_iblock, &sec_entry, &did_protect, H5AC__READ_ONLY_FLAG) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTCOMPUTE, FAIL, "can't compute row & column of section")
/* Increment reference count on indirect block that free section is in */
@@ -776,7 +776,7 @@ H5HF_sect_single_full_dblock(H5HF_hdr_t *hdr, hid_t dxpl_id,
hdr->man_dtable.curr_root_rows > 0) {
H5HF_direct_t *dblock; /* Pointer to direct block for section */
- if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, dblock_addr, dblock_size, sect->u.single.parent, sect->u.single.par_entry, H5AC_WRITE)))
+ if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, dblock_addr, dblock_size, sect->u.single.parent, sect->u.single.par_entry, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to load fractal heap direct block")
HDassert(H5F_addr_eq(dblock->block_off + dblock_overhead, sect->sect_info.addr));
@@ -1094,7 +1094,7 @@ H5HF_sect_single_shrink(H5FS_section_info_t **_sect, void H5_ATTR_UNUSED *_udata
/* (should be a root direct block) */
HDassert(dblock_addr == hdr->man_dtable.table_addr);
if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, dblock_addr,
- dblock_size, (*sect)->u.single.parent, (*sect)->u.single.par_entry, H5AC_WRITE)))
+ dblock_size, (*sect)->u.single.parent, (*sect)->u.single.par_entry, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to load fractal heap direct block")
HDassert(H5F_addr_eq(dblock->block_off + dblock_size, (*sect)->sect_info.addr + (*sect)->sect_info.size));
@@ -1221,7 +1221,7 @@ H5HF_sect_single_valid(const H5FS_section_class_t H5_ATTR_UNUSED *cls, const H5F
H5HF_direct_t *dblock; /* Direct block for section */
/* Protect the direct block for the section */
- dblock = H5HF_man_dblock_protect(iblock->hdr, H5AC_dxpl_id, dblock_addr, dblock_size, iblock, sect->u.single.par_entry, H5AC_READ);
+ dblock = H5HF_man_dblock_protect(iblock->hdr, H5AC_dxpl_id, dblock_addr, dblock_size, iblock, sect->u.single.par_entry, H5AC__READ_ONLY_FLAG);
HDassert(dblock);
/* Sanity check settings for section */
@@ -2536,7 +2536,7 @@ H5HF_sect_indirect_init_rows(H5HF_hdr_t *hdr, hid_t dxpl_id,
/* If the child indirect block's address is defined, protect it */
if(H5F_addr_defined(child_iblock_addr)) {
- if(NULL == (child_iblock = H5HF_man_iblock_protect(hdr, dxpl_id, child_iblock_addr, child_nrows, sect->u.indirect.u.iblock, curr_entry, FALSE, H5AC_WRITE, &did_protect)))
+ if(NULL == (child_iblock = H5HF_man_iblock_protect(hdr, dxpl_id, child_iblock_addr, child_nrows, sect->u.indirect.u.iblock, curr_entry, FALSE, H5AC__NO_FLAGS_SET, &did_protect)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block")
} /* end if */
else
@@ -2771,7 +2771,7 @@ H5HF_sect_indirect_revive_row(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_
HDassert(sect->sect_info.state == H5FS_SECT_SERIALIZED);
/* Look up indirect block containing indirect blocks for section */
- if(H5HF_man_dblock_locate(hdr, dxpl_id, sect->sect_info.addr, &sec_iblock, NULL, &did_protect, H5AC_READ) < 0)
+ if(H5HF_man_dblock_locate(hdr, dxpl_id, sect->sect_info.addr, &sec_iblock, NULL, &did_protect, H5AC__READ_ONLY_FLAG) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTCOMPUTE, FAIL, "can't compute row & column of section")
/* Increment reference count on indirect block that free section is in */
diff --git a/src/H5HG.c b/src/H5HG.c
index 7127a72..80298d7 100644
--- a/src/H5HG.c
+++ b/src/H5HG.c
@@ -246,7 +246,7 @@ done:
*-------------------------------------------------------------------------
*/
H5HG_heap_t *
-H5HG_protect(H5F_t *f, hid_t dxpl_id, haddr_t addr, H5AC_protect_t rw)
+H5HG_protect(H5F_t *f, hid_t dxpl_id, haddr_t addr, unsigned flags)
{
H5HG_heap_t *heap; /* Global heap */
H5HG_heap_t *ret_value; /* Return value */
@@ -257,8 +257,11 @@ H5HG_protect(H5F_t *f, hid_t dxpl_id, haddr_t addr, H5AC_protect_t rw)
HDassert(f);
HDassert(H5F_addr_defined(addr));
+ /* only H5AC__READ_ONLY_FLAG may appear in flags */
+ HDassert((flags & (unsigned)(~H5AC__READ_ONLY_FLAG)) == 0);
+
/* Lock the heap into memory */
- if(NULL == (heap = (H5HG_heap_t *)H5AC_protect(f, dxpl_id, H5AC_GHEAP, addr, f, rw)))
+ if(NULL == (heap = (H5HG_heap_t *)H5AC_protect(f, dxpl_id, H5AC_GHEAP, addr, f, flags)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to protect global heap")
/* Set the heap's address */
@@ -440,7 +443,7 @@ H5HG_extend(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t need)
HDassert(H5F_addr_defined(addr));
/* Protect the heap */
- if(NULL == (heap = H5HG_protect(f, dxpl_id, addr, H5AC_WRITE)))
+ if(NULL == (heap = H5HG_protect(f, dxpl_id, addr, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect global heap")
/* Re-allocate the heap information in memory */
@@ -554,7 +557,7 @@ H5HG_insert(H5F_t *f, hid_t dxpl_id, size_t size, void *obj, H5HG_t *hobj/*out*/
} /* end if */
HDassert(H5F_addr_defined(addr));
- if(NULL == (heap = H5HG_protect(f, dxpl_id, addr, H5AC_WRITE)))
+ if(NULL == (heap = H5HG_protect(f, dxpl_id, addr, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect global heap")
/* Split the free space to make room for the new object */
@@ -618,7 +621,7 @@ H5HG_read(H5F_t *f, hid_t dxpl_id, H5HG_t *hobj, void *object/*out*/,
HDassert(hobj);
/* Load the heap */
- if(NULL == (heap = H5HG_protect(f, dxpl_id, hobj->addr, H5AC_READ)))
+ if(NULL == (heap = H5HG_protect(f, dxpl_id, hobj->addr, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to protect global heap")
HDassert(hobj->idx < heap->nused);
@@ -692,7 +695,7 @@ H5HG_link(H5F_t *f, hid_t dxpl_id, const H5HG_t *hobj, int adjust)
HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "no write intent on file")
/* Load the heap */
- if(NULL == (heap = H5HG_protect(f, dxpl_id, hobj->addr, H5AC_WRITE)))
+ if(NULL == (heap = H5HG_protect(f, dxpl_id, hobj->addr, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect global heap")
if(adjust != 0) {
@@ -755,7 +758,7 @@ H5HG_remove (H5F_t *f, hid_t dxpl_id, H5HG_t *hobj)
HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "no write intent on file")
/* Load the heap */
- if(NULL == (heap = H5HG_protect(f, dxpl_id, hobj->addr, H5AC_WRITE)))
+ if(NULL == (heap = H5HG_protect(f, dxpl_id, hobj->addr, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect global heap")
HDassert(hobj->idx < heap->nused);
diff --git a/src/H5HGcache.c b/src/H5HGcache.c
index aac73ed..c5d5517 100644
--- a/src/H5HGcache.c
+++ b/src/H5HGcache.c
@@ -62,12 +62,16 @@
/********************/
/* Metadata cache callbacks */
-static H5HG_heap_t *H5HG_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata);
-static herr_t H5HG_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr,
- H5HG_heap_t *heap, unsigned H5_ATTR_UNUSED * flags_ptr);
-static herr_t H5HG_dest(H5F_t *f, H5HG_heap_t *heap);
-static herr_t H5HG_clear(H5F_t *f, H5HG_heap_t *heap, hbool_t destroy);
-static herr_t H5HG_size(const H5F_t *f, const H5HG_heap_t *heap, size_t *size_ptr);
+static herr_t H5HG__cache_heap_get_load_size(const void *_image, void *udata,
+ size_t *image_len, size_t *actual_len,
+ hbool_t *compressed_ptr, size_t *compressed_image_len_ptr);
+static void *H5HG__cache_heap_deserialize(const void *image, size_t len,
+ void *udata, hbool_t *dirty);
+static herr_t H5HG__cache_heap_image_len(const void *thing, size_t *image_len,
+ hbool_t *compressed_ptr, size_t *compressed_image_len_ptr);
+static herr_t H5HG__cache_heap_serialize(const H5F_t *f, void *image,
+ size_t len, void *thing);
+static herr_t H5HG__cache_heap_free_icr(void *thing);
/*********************/
@@ -76,13 +80,20 @@ static herr_t H5HG_size(const H5F_t *f, const H5HG_heap_t *heap, size_t *size_pt
/* H5HG inherits cache-like properties from H5AC */
const H5AC_class_t H5AC_GHEAP[1] = {{
- H5AC_GHEAP_ID,
- (H5AC_load_func_t)H5HG_load,
- (H5AC_flush_func_t)H5HG_flush,
- (H5AC_dest_func_t)H5HG_dest,
- (H5AC_clear_func_t)H5HG_clear,
- (H5AC_notify_func_t)NULL,
- (H5AC_size_func_t)H5HG_size,
+ H5AC_GHEAP_ID, /* Metadata client ID */
+ "global heap", /* Metadata client name (for debugging) */
+ H5FD_MEM_GHEAP, /* File space memory type for client */
+ H5AC__CLASS_SPECULATIVE_LOAD_FLAG, /* Client class behavior flags */
+ H5HG__cache_heap_get_load_size, /* 'get_load_size' callback */
+ NULL, /* 'verify_chksum' callback */
+ H5HG__cache_heap_deserialize, /* 'deserialize' callback */
+ H5HG__cache_heap_image_len, /* 'image_len' callback */
+ NULL, /* 'pre_serialize' callback */
+ H5HG__cache_heap_serialize, /* 'serialize' callback */
+ NULL, /* 'notify' callback */
+ H5HG__cache_heap_free_icr, /* 'free_icr' callback */
+ NULL, /* 'clear' callback */
+ NULL, /* 'fsf_size' callback */
}};
@@ -98,162 +109,237 @@ const H5AC_class_t H5AC_GHEAP[1] = {{
/*-------------------------------------------------------------------------
- * Function: H5HG_load
+ * Function: H5HG__cache_heap_get_load_size()
*
- * Purpose: Loads a global heap collection from disk.
+ * Purpose: Return the initial speculative read size to the metadata
+ * cache. This size will be used in the initial attempt to read
+ * the global heap. If this read is too small, the cache will
+ * try again with the correct value obtained from
+ * H5HG__cache_heap_image_len().
*
- * Return: Success: Ptr to a global heap collection.
+ * Return: Success: SUCCEED
+ * Failure: FAIL
*
- * Failure: NULL
+ * Programmer: John Mainzer
+ * 7/27/14
*
- * Programmer: Robb Matzke
- * Friday, March 27, 1998
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HG__cache_heap_get_load_size(const void *_image, void *_udata, size_t *image_len, size_t *actual_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr)
+{
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ H5F_t *f = (H5F_t *)_udata; /* File pointer -- obtained from user data */
+ size_t heap_size; /* Total size of collection */
+ htri_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ HDassert(image_len);
+
+ if(image == NULL) {
+ *image_len = (size_t)H5HG_MINSIZE;
+
+ } else { /* compute actual_len */
+ HDassert(f);
+ HDassert(actual_len);
+ HDassert(*actual_len == *image_len);
+
+ /* Magic number */
+ if(HDmemcmp(image, H5HG_MAGIC, (size_t)H5_SIZEOF_MAGIC))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "bad global heap collection signature")
+ image += H5_SIZEOF_MAGIC;
+
+ /* Version */
+ if(H5HG_VERSION != *image++)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "wrong version number in global heap")
+
+ /* Reserved */
+ image += 3;
+
+ /* Size */
+ H5F_DECODE_LENGTH(f, image, heap_size);
+ HDassert(heap_size >= H5HG_MINSIZE);
+ HDassert(*image_len == H5HG_MINSIZE);
+
+ *actual_len = heap_size;
+ }
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HG__cache_heap_get_load_size() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HG__cache_heap_deserialize
+ *
+ * Purpose: Given a buffer containing the on disk image of the global
+ * heap, deserialize it, load its contents into a newly allocated
+ * instance of H5HG_heap_t, and return a pointer to the new instance.
+ *
+ * Note that this heap client uses speculative reads. If the supplied
+ * buffer is too small, we simply make note of the correct size, and
+ * wait for the metadata cache to try again.
+ *
+ * Return: Success: Pointer to in core representation
+ * Failure: NULL
+ *
+ * Programmer: John Mainzer
+ * 7/27/14
*
*-------------------------------------------------------------------------
*/
-static H5HG_heap_t *
-H5HG_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata)
+static void *
+H5HG__cache_heap_deserialize(const void *_image, size_t len, void *_udata,
+ hbool_t H5_ATTR_UNUSED *dirty)
{
- H5HG_heap_t *heap = NULL;
- uint8_t *p;
- size_t nalloc, need;
- size_t max_idx = 0; /* The maximum index seen */
- H5HG_heap_t *ret_value = NULL; /* Return value */
+ H5F_t *f = (H5F_t *)_udata; /* File pointer -- obtained from user data */
+ H5HG_heap_t *heap = NULL; /* New global heap */
+ uint8_t *image; /* Pointer to image to decode */
+ void *ret_value; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
- /* check arguments */
+ /* Sanity checks */
+ HDassert(_image);
+ HDassert(len >= (size_t)H5HG_MINSIZE);
HDassert(f);
- HDassert(H5F_addr_defined(addr));
- HDassert(udata);
+ HDassert(dirty);
- /* Read the initial 4k page */
+ /* Allocate a new global heap */
if(NULL == (heap = H5FL_CALLOC(H5HG_heap_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
heap->shared = H5F_SHARED(f);
- if(NULL == (heap->chunk = H5FL_BLK_MALLOC(gheap_chunk, (size_t)H5HG_MINSIZE)))
+ if(NULL == (heap->chunk = H5FL_BLK_MALLOC(gheap_chunk, len)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
- if(H5F_block_read(f, H5FD_MEM_GHEAP, addr, (size_t)H5HG_MINSIZE, dxpl_id, heap->chunk) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_READERROR, NULL, "unable to read global heap collection")
- p = heap->chunk;
+
+ /* copy the image buffer into the newly allocate chunk */
+ HDmemcpy(heap->chunk, _image, len);
+
+ image = heap->chunk;
/* Magic number */
- if(HDmemcmp(p, H5HG_MAGIC, (size_t)H5_SIZEOF_MAGIC))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "bad global heap collection signature")
- p += H5_SIZEOF_MAGIC;
+ if(HDmemcmp(image, H5HG_MAGIC, (size_t)H5_SIZEOF_MAGIC))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "bad global heap collection signature")
+ image += H5_SIZEOF_MAGIC;
/* Version */
- if(H5HG_VERSION != *p++)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "wrong version number in global heap")
+ if(H5HG_VERSION != *image++)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "wrong version number in global heap")
/* Reserved */
- p += 3;
+ image += 3;
/* Size */
- H5F_DECODE_LENGTH(f, p, heap->size);
+ H5F_DECODE_LENGTH(f, image, heap->size);
HDassert(heap->size >= H5HG_MINSIZE);
-
- /*
- * If we didn't read enough in the first try, then read the rest of the
- * collection now.
- */
- if(heap->size > H5HG_MINSIZE) {
- haddr_t next_addr = addr + (hsize_t)H5HG_MINSIZE;
-
- if(NULL == (heap->chunk = H5FL_BLK_REALLOC(gheap_chunk, heap->chunk, heap->size)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
- if(H5F_block_read(f, H5FD_MEM_GHEAP, next_addr, (heap->size - H5HG_MINSIZE), dxpl_id, heap->chunk + H5HG_MINSIZE) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_READERROR, NULL, "unable to read global heap collection")
- } /* end if */
-
- /* Decode each object */
- p = heap->chunk + H5HG_SIZEOF_HDR(f);
- nalloc = H5HG_NOBJS(f, heap->size);
-
- /* Calloc the obj array because the file format spec makes no guarantee
- * about the order of the objects, and unused slots must be set to zero.
- */
- if(NULL == (heap->obj = H5FL_SEQ_CALLOC(H5HG_obj_t, nalloc)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
-
- heap->nalloc = nalloc;
- while(p < (heap->chunk + heap->size)) {
- if((p + H5HG_SIZEOF_OBJHDR(f)) > (heap->chunk + heap->size)) {
- /*
- * The last bit of space is too tiny for an object header, so we
- * assume that it's free space.
- */
- HDassert(NULL == heap->obj[0].begin);
- heap->obj[0].size = (size_t)(((const uint8_t *)heap->chunk + heap->size) - p);
- heap->obj[0].begin = p;
- p += heap->obj[0].size;
- } /* end if */
- else {
- unsigned idx;
- uint8_t *begin = p;
-
- UINT16DECODE(p, idx);
-
- /* Check if we need more room to store heap objects */
- if(idx >= heap->nalloc) {
- size_t new_alloc; /* New allocation number */
- H5HG_obj_t *new_obj; /* New array of object descriptions */
-
- /* Determine the new number of objects to index */
- new_alloc = MAX(heap->nalloc * 2, (idx + 1));
- HDassert(idx < new_alloc);
-
- /* Reallocate array of objects */
- if(NULL == (new_obj = H5FL_SEQ_REALLOC(H5HG_obj_t, heap->obj, new_alloc)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
-
- /* Clear newly allocated space */
- HDmemset(&new_obj[heap->nalloc], 0, (new_alloc - heap->nalloc) * sizeof(heap->obj[0]));
-
- /* Update heap information */
- heap->nalloc = new_alloc;
- heap->obj = new_obj;
- HDassert(heap->nalloc > heap->nused);
+ HDassert((len == H5HG_MINSIZE) /* first try */ ||
+ ((len == heap->size) && (len > H5HG_MINSIZE))); /* second try */
+
+ if(len == heap->size) { /* proceed with the deserialize */
+ size_t max_idx = 0;
+ size_t nalloc;
+
+ /* Decode each object */
+ image = heap->chunk + H5HG_SIZEOF_HDR(f);
+ nalloc = H5HG_NOBJS(f, heap->size);
+
+ /* Calloc the obj array because the file format spec makes no guarantee
+ * about the order of the objects, and unused slots must be set to zero.
+ */
+ if(NULL == (heap->obj = H5FL_SEQ_CALLOC(H5HG_obj_t, nalloc)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+ heap->nalloc = nalloc;
+
+ while(image < (heap->chunk + heap->size)) {
+ if((image + H5HG_SIZEOF_OBJHDR(f)) > (heap->chunk + heap->size)) {
+ /*
+ * The last bit of space is too tiny for an object header, so
+ * we assume that it's free space.
+ */
+ HDassert(NULL == heap->obj[0].begin);
+ heap->obj[0].size = (size_t)(((const uint8_t *)heap->chunk + heap->size) - image);
+ heap->obj[0].begin = image;
+ image += heap->obj[0].size;
} /* end if */
-
- UINT16DECODE(p, heap->obj[idx].nrefs);
- p += 4; /*reserved*/
- H5F_DECODE_LENGTH(f, p, heap->obj[idx].size);
- heap->obj[idx].begin = begin;
-
- /*
- * The total storage size includes the size of the object header
- * and is zero padded so the next object header is properly
- * aligned. The entire obj array was calloc'ed, so no need to zero
- * the space here. The last bit of space is the free space object
- * whose size is never padded and already includes the object
- * header.
- */
- if(idx > 0) {
- need = H5HG_SIZEOF_OBJHDR(f) + H5HG_ALIGN(heap->obj[idx].size);
-
- if(idx > max_idx)
- max_idx = idx;
- } /* end if */
- else
- need = heap->obj[idx].size;
- p = begin + need;
- } /* end else */
- } /* end while */
- HDassert(p == heap->chunk + heap->size);
- HDassert(H5HG_ISALIGNED(heap->obj[0].size));
-
- /* Set the next index value to use */
- if(max_idx > 0)
- heap->nused = max_idx + 1;
+ else {
+ size_t need;
+ unsigned idx;
+ uint8_t *begin = image;
+
+ UINT16DECODE(image, idx);
+
+ /* Check if we need more room to store heap objects */
+ if(idx >= heap->nalloc) {
+ size_t new_alloc; /* New allocation number */
+ H5HG_obj_t *new_obj; /* New array of object descriptions */
+
+ /* Determine the new number of objects to index */
+ new_alloc = MAX(heap->nalloc * 2, (idx + 1));
+ HDassert(idx < new_alloc);
+
+ /* Reallocate array of objects */
+ if(NULL == (new_obj = H5FL_SEQ_REALLOC(H5HG_obj_t, heap->obj, new_alloc)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+
+ /* Clear newly allocated space */
+ HDmemset(&new_obj[heap->nalloc], 0, (new_alloc - heap->nalloc) * sizeof(heap->obj[0]));
+
+ /* Update heap information */
+ heap->nalloc = new_alloc;
+ heap->obj = new_obj;
+ HDassert(heap->nalloc > heap->nused);
+ } /* end if */
+
+ UINT16DECODE(image, heap->obj[idx].nrefs);
+ image += 4; /*reserved*/
+ H5F_DECODE_LENGTH(f, image, heap->obj[idx].size);
+ heap->obj[idx].begin = begin;
+
+ /*
+ * The total storage size includes the size of the object
+ * header and is zero padded so the next object header is
+ * properly aligned. The entire obj array was calloc'ed,
+ * so no need to zero the space here. The last bit of space
+ * is the free space object whose size is never padded and
+ * already includes the object header.
+ */
+ if(idx > 0) {
+ need = H5HG_SIZEOF_OBJHDR(f) + H5HG_ALIGN(heap->obj[idx].size);
+ if(idx > max_idx)
+ max_idx = idx;
+ } /* end if */
+ else
+ need = heap->obj[idx].size;
+
+ image = begin + need;
+ } /* end else */
+ } /* end while */
+
+ HDassert(image == heap->chunk + heap->size);
+ HDassert(H5HG_ISALIGNED(heap->obj[0].size));
+
+ /* Set the next index value to use */
+ if(max_idx > 0)
+ heap->nused = max_idx + 1;
+ else
+ heap->nused = 1;
+
+ HDassert(max_idx < heap->nused);
+
+ /* Add the new heap to the CWFS list for the file */
+ if(H5F_cwfs_add(f, heap) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, NULL, "unable to add global heap collection to file's CWFS")
+ } /* end if ( len == heap->size ) */
else
- heap->nused = 1;
-
- HDassert(max_idx < heap->nused);
-
- /* Add the new heap to the CWFS list for the file */
- if(H5F_cwfs_add(f, heap) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, NULL, "unable to add global heap collection to file's CWFS")
+ /* if len is less than heap size, then the initial speculative
+ * read was too small. In this case we return without reporting
+ * failure. H5C_load_entry() will call H5HG__cache_heap_image_len()
+ * to get the actual read size, and then repeat the read with the
+ * correct size, and call this function a second time.
+ */
+ HDassert(len < heap->size);
ret_value = heap;
@@ -263,154 +349,126 @@ done:
HDONE_ERROR(H5E_HEAP, H5E_CANTFREE, NULL, "unable to destroy global heap collection")
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5HG_load() */
+} /* end H5HG__cache_heap_deserialize() */
/*-------------------------------------------------------------------------
- * Function: H5HG_flush
+ * Function: H5HG__cache_heap_image_len
*
- * Purpose: Flushes a global heap collection from memory to disk if it's
- * dirty. Optionally deletes teh heap from memory.
+ * Purpose: Return the on disk image size of the global heap to the
+ * metadata cache via the image_len.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Success: SUCCEED
+ * Failure: FAIL
*
- * Programmer: Robb Matzke
- * Friday, March 27, 1998
+ * Programmer: John Mainzer
+ * 7/27/14
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5HG_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HG_heap_t *heap, unsigned H5_ATTR_UNUSED * flags_ptr)
+H5HG__cache_heap_image_len(const void *_thing, size_t *image_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ const H5HG_heap_t *heap = (const H5HG_heap_t *)_thing;
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC_NOERR
- /* Check arguments */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
- HDassert(H5F_addr_eq(addr, heap->addr));
+ /* Sanity checks */
HDassert(heap);
+ HDassert(heap->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(heap->cache_info.type == H5AC_GHEAP);
+ HDassert(heap->size >= H5HG_MINSIZE);
+ HDassert(image_len);
- if(heap->cache_info.is_dirty) {
- if(H5F_block_write(f, H5FD_MEM_GHEAP, addr, heap->size, dxpl_id, heap->chunk) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write global heap collection to file")
- heap->cache_info.is_dirty = FALSE;
- } /* end if */
+ *image_len = heap->size;
- if(destroy)
- if(H5HG_dest(f, heap) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy global heap collection")
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5HG__cache_heap_image_len() */
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5HG_flush() */
+/**************************************/
+/* no H5HG_cache_heap_pre_serialize() */
+/**************************************/
/*-------------------------------------------------------------------------
- * Function: H5HG_dest
+ * Function: H5HG__cache_heap_serialize
+ *
+ * Purpose: Given an appropriately sized buffer and an instance of
+ * H5HG_heap_t, serialize the global heap for writing to file,
+ * and copy the serialized verion into the buffer.
*
- * Purpose: Destroys a global heap collection in memory
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Success: SUCCEED
+ * Failure: FAIL
*
- * Programmer: Quincey Koziol
- * Wednesday, January 15, 2003
+ * Programmer: John Mainzer
+ * 7/27/14
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5HG_dest(H5F_t *f, H5HG_heap_t *heap)
+H5HG__cache_heap_serialize(const H5F_t *f, void *image, size_t len,
+ void *_thing)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ H5HG_heap_t *heap = (H5HG_heap_t *)_thing;
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC_NOERR
- /* Check arguments */
+ HDassert(f);
+ HDassert(image);
HDassert(heap);
+ HDassert(heap->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(heap->cache_info.type == H5AC_GHEAP);
+ HDassert(heap->size == len);
+ HDassert(heap->chunk);
- /* Verify that node is clean */
- HDassert(heap->cache_info.is_dirty == FALSE);
-
- /* If we're going to free the space on disk, the address must be valid */
- HDassert(!heap->cache_info.free_file_space_on_destroy || H5F_addr_defined(heap->cache_info.addr));
+ /* copy the image into the buffer */
+ HDmemcpy(image, heap->chunk, len);
- /* Check for freeing file space for globalheap */
- if(heap->cache_info.free_file_space_on_destroy) {
- /* Release the space on disk */
- /* (XXX: Nasty usage of internal DXPL value! -QAK) */
- if(H5MF_xfree(f, H5FD_MEM_GHEAP, H5AC_dxpl_id, heap->cache_info.addr, (hsize_t)heap->size) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free global heap")
- } /* end if */
-
- /* Destroy global heap collection */
- if(H5HG_free(heap) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy global heap collection")
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5HG__cache_heap_serialize() */
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5HG_dest() */
+/****************************************/
+/* no H5HG_cache_heap_notify() function */
+/****************************************/
/*-------------------------------------------------------------------------
- * Function: H5HG_clear
+ * Function: H5HG__cache_heap_free_icr
+ *
+ * Purpose: Free the in memory representation of the supplied global heap.
*
- * Purpose: Mark a global heap in memory as non-dirty.
+ * Note: The metadata cache sets the object's cache_info.magic to
+ * H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC before calling a free_icr
+ * callback (checked in assert).
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Success: SUCCEED
+ * Failure: FAIL
*
- * Programmer: Quincey Koziol
- * Thursday, March 20, 2003
+ * Programmer: John Mainzer
+ * 7/27/14
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5HG_clear(H5F_t *f, H5HG_heap_t *heap, hbool_t destroy)
+H5HG__cache_heap_free_icr(void *_thing)
{
+ H5HG_heap_t *heap = (H5HG_heap_t *)_thing;
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
/* Sanity checks */
HDassert(heap);
+ HDassert(heap->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC);
+ HDassert(heap->cache_info.type == H5AC_GHEAP);
- /* Mark heap as clean */
- heap->cache_info.is_dirty = FALSE;
-
- if(destroy)
- if(H5HG_dest(f, heap) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy global heap collection")
+ /* Destroy global heap collection */
+ if(H5HG_free(heap) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy global heap collection")
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5HG_clear() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5HG_size
- *
- * Purpose: Compute the size in bytes of the specified instance of
- * H5HG_heap_t on disk, and return it in *len_ptr. On failure,
- * the value of *len_ptr is undefined.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: John Mainzer
- * 5/13/04
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5HG_size(const H5F_t H5_ATTR_UNUSED *f, const H5HG_heap_t *heap, size_t *size_ptr)
-{
- FUNC_ENTER_NOAPI_NOINIT_NOERR
-
- /* Check arguments */
- HDassert(heap);
- HDassert(size_ptr);
-
- *size_ptr = heap->size;
-
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5HG_size() */
+} /* end H5HG__cache_heap_free_icr() */
diff --git a/src/H5HGdbg.c b/src/H5HGdbg.c
index 16d8c49..c79aac8 100644
--- a/src/H5HGdbg.c
+++ b/src/H5HGdbg.c
@@ -103,7 +103,7 @@ H5HG_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent,
HDassert(indent >= 0);
HDassert(fwidth >= 0);
- if(NULL == (h = H5HG_protect(f, dxpl_id, addr, H5AC_READ)))
+ if(NULL == (h = H5HG_protect(f, dxpl_id, addr, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect global heap collection");
HDfprintf(stream, "%*sGlobal Heap Collection...\n", indent, "");
diff --git a/src/H5HGpkg.h b/src/H5HGpkg.h
index c1ce954..5d00cbd 100644
--- a/src/H5HGpkg.h
+++ b/src/H5HGpkg.h
@@ -143,7 +143,7 @@ struct H5HG_heap_t {
/* Package Private Prototypes */
/******************************/
H5_DLL herr_t H5HG_free(H5HG_heap_t *heap);
-H5_DLL H5HG_heap_t *H5HG_protect(H5F_t *f, hid_t dxpl_id, haddr_t addr, H5AC_protect_t rw);
+H5_DLL H5HG_heap_t *H5HG_protect(H5F_t *f, hid_t dxpl_id, haddr_t addr, unsigned flags);
#endif /* _H5HGpkg_H */
diff --git a/src/H5HL.c b/src/H5HL.c
index 704bd6c..3a04a79 100644
--- a/src/H5HL.c
+++ b/src/H5HL.c
@@ -322,7 +322,7 @@ END_FUNC(STATIC) /* H5HL__minimize_heap_space() */
*/
BEGIN_FUNC(PRIV, ERR,
H5HL_t *, NULL, NULL,
-H5HL_protect(H5F_t *f, hid_t dxpl_id, haddr_t addr, H5AC_protect_t rw))
+H5HL_protect(H5F_t *f, hid_t dxpl_id, haddr_t addr, unsigned flags))
H5HL_cache_prfx_ud_t prfx_udata; /* User data for protecting local heap prefix */
H5HL_prfx_t *prfx = NULL; /* Local heap prefix */
@@ -335,14 +335,19 @@ H5HL_protect(H5F_t *f, hid_t dxpl_id, haddr_t addr, H5AC_protect_t rw))
HDassert(f);
HDassert(H5F_addr_defined(addr));
+ /* only the H5AC__READ_ONLY_FLAG may appear in flags */
+ HDassert((flags & (unsigned)(~H5AC__READ_ONLY_FLAG)) == 0);
+
/* Construct the user data for protect callback */
+ prfx_udata.made_attempt = FALSE;
prfx_udata.sizeof_size = H5F_SIZEOF_SIZE(f);
prfx_udata.sizeof_addr = H5F_SIZEOF_ADDR(f);
prfx_udata.prfx_addr = addr;
prfx_udata.sizeof_prfx = H5HL_SIZEOF_HDR(f);
+ prfx_udata.loaded = FALSE;
/* Protect the local heap prefix */
- if(NULL == (prfx = (H5HL_prfx_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP_PRFX, addr, &prfx_udata, rw)))
+ if(NULL == (prfx = (H5HL_prfx_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP_PRFX, addr, &prfx_udata, flags)))
H5E_THROW(H5E_CANTPROTECT, "unable to load heap prefix");
/* Get the pointer to the heap */
@@ -364,7 +369,7 @@ H5HL_protect(H5F_t *f, hid_t dxpl_id, haddr_t addr, H5AC_protect_t rw))
dblk_udata.loaded = FALSE;
/* Protect the local heap data block */
- if(NULL == (dblk = (H5HL_dblk_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP_DBLK, heap->dblk_addr, &dblk_udata, rw)))
+ if(NULL == (dblk = (H5HL_dblk_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP_DBLK, heap->dblk_addr, &dblk_udata, flags)))
H5E_THROW(H5E_CANTPROTECT, "unable to load heap data block");
/* Pin the prefix, if the data block was loaded from file */
@@ -924,13 +929,15 @@ H5HL_delete(H5F_t *f, hid_t dxpl_id, haddr_t addr))
HDassert(H5F_addr_defined(addr));
/* Construct the user data for protect callback */
+ prfx_udata.made_attempt = FALSE;
prfx_udata.sizeof_size = H5F_SIZEOF_SIZE(f);
prfx_udata.sizeof_addr = H5F_SIZEOF_ADDR(f);
prfx_udata.prfx_addr = addr;
prfx_udata.sizeof_prfx = H5HL_SIZEOF_HDR(f);
+ prfx_udata.loaded = FALSE;
/* Protect the local heap prefix */
- if(NULL == (prfx = (H5HL_prfx_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP_PRFX, addr, &prfx_udata, H5AC_WRITE)))
+ if(NULL == (prfx = (H5HL_prfx_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP_PRFX, addr, &prfx_udata, H5AC__NO_FLAGS_SET)))
H5E_THROW(H5E_CANTPROTECT, "unable to load heap prefix");
/* Get the pointer to the heap */
@@ -945,7 +952,7 @@ H5HL_delete(H5F_t *f, hid_t dxpl_id, haddr_t addr))
dblk_udata.loaded = FALSE;
/* Protect the local heap data block */
- if(NULL == (dblk = (H5HL_dblk_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP_DBLK, heap->dblk_addr, &dblk_udata, H5AC_WRITE)))
+ if(NULL == (dblk = (H5HL_dblk_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP_DBLK, heap->dblk_addr, &dblk_udata, H5AC__NO_FLAGS_SET)))
H5E_THROW(H5E_CANTPROTECT, "unable to load heap data block");
/* Pin the prefix, if the data block was loaded from file */
@@ -996,13 +1003,15 @@ H5HL_get_size(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t *size))
HDassert(size);
/* Construct the user data for protect callback */
+ prfx_udata.made_attempt = FALSE;
prfx_udata.sizeof_size = H5F_SIZEOF_SIZE(f);
prfx_udata.sizeof_addr = H5F_SIZEOF_ADDR(f);
prfx_udata.prfx_addr = addr;
prfx_udata.sizeof_prfx = H5HL_SIZEOF_HDR(f);
+ prfx_udata.loaded = FALSE;
/* Protect the local heap prefix */
- if(NULL == (prfx = (H5HL_prfx_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP_PRFX, addr, &prfx_udata, H5AC_READ)))
+ if(NULL == (prfx = (H5HL_prfx_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP_PRFX, addr, &prfx_udata, H5AC__READ_ONLY_FLAG)))
H5E_THROW(H5E_CANTPROTECT, "unable to load heap prefix");
/* Get the pointer to the heap */
@@ -1045,13 +1054,15 @@ H5HL_heapsize(H5F_t *f, hid_t dxpl_id, haddr_t addr, hsize_t *heap_size))
HDassert(heap_size);
/* Construct the user data for protect callback */
+ prfx_udata.made_attempt = FALSE;
prfx_udata.sizeof_size = H5F_SIZEOF_SIZE(f);
prfx_udata.sizeof_addr = H5F_SIZEOF_ADDR(f);
prfx_udata.prfx_addr = addr;
prfx_udata.sizeof_prfx = H5HL_SIZEOF_HDR(f);
+ prfx_udata.loaded = FALSE;
/* Protect the local heap prefix */
- if(NULL == (prfx = (H5HL_prfx_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP_PRFX, addr, &prfx_udata, H5AC_READ)))
+ if(NULL == (prfx = (H5HL_prfx_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP_PRFX, addr, &prfx_udata, H5AC__READ_ONLY_FLAG)))
H5E_THROW(H5E_CANTPROTECT, "unable to load heap prefix");
/* Get the pointer to the heap */
diff --git a/src/H5HLcache.c b/src/H5HLcache.c
index 74d414a..e3c8ded 100644
--- a/src/H5HLcache.c
+++ b/src/H5HLcache.c
@@ -71,21 +71,31 @@
/* Metadata cache callbacks */
/* Local heap prefix */
-static H5HL_prfx_t *H5HL__prefix_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata);
-static herr_t H5HL__prefix_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr,
- H5HL_prfx_t *prfx, unsigned *flags_ptr);
-static herr_t H5HL__prefix_dest(H5F_t *f, H5HL_prfx_t *prfx);
-static herr_t H5HL__prefix_clear(H5F_t *f, H5HL_prfx_t *prfx, hbool_t destroy);
-static herr_t H5HL__prefix_size(const H5F_t *f, H5HL_prfx_t *prfx, size_t *size_ptr);
+static herr_t H5HL__cache_prefix_get_load_size(const void *_image, void *udata,
+ size_t *image_len, size_t *actual_len,
+ hbool_t *compressed_ptr, size_t *compressed_image_len_ptr);
+static void *H5HL__cache_prefix_deserialize(const void *image, size_t len,
+ void *udata, hbool_t *dirty);
+static herr_t H5HL__cache_prefix_image_len(const void *thing,
+ size_t *image_len, hbool_t *compressed_ptr,
+ size_t *compressed_image_len_ptr);
+static herr_t H5HL__cache_prefix_serialize(const H5F_t *f, void *image,
+ size_t len, void *thing);
+static herr_t H5HL__cache_prefix_free_icr(void *thing);
/* Local heap data block */
-static H5HL_dblk_t *H5HL__datablock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata);
-static herr_t H5HL__datablock_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr,
- H5HL_dblk_t *dblk, unsigned *flags_ptr);
-static herr_t H5HL__datablock_dest(H5F_t *f, H5HL_dblk_t *dblk);
-static herr_t H5HL__datablock_clear(H5F_t *f, H5HL_dblk_t *dblk, hbool_t destroy);
-static herr_t H5HL__datablock_notify(H5AC_notify_action_t action, H5HL_dblk_t *dblk);
-static herr_t H5HL__datablock_size(const H5F_t *f, H5HL_dblk_t *dblk, size_t *size_ptr);
+static herr_t H5HL__cache_datablock_get_load_size(const void *_image, void *udata,
+ size_t *image_len, size_t *actual_len,
+ hbool_t *compressed_ptr, size_t *compressed_image_len_ptr);
+static void *H5HL__cache_datablock_deserialize(const void *image, size_t len,
+ void *udata, hbool_t *dirty);
+static herr_t H5HL__cache_datablock_image_len(const void *thing,
+ size_t *image_len, hbool_t *compressed_ptr,
+ size_t *compressed_image_len_ptr);
+static herr_t H5HL__cache_datablock_serialize(const H5F_t *f, void *image,
+ size_t len, void *thing);
+static herr_t H5HL__cache_datablock_notify(H5AC_notify_action_t action, void *thing);
+static herr_t H5HL__cache_datablock_free_icr(void *thing);
/* Free list de/serialization */
static herr_t H5HL__fl_deserialize(H5HL_t *heap);
@@ -97,23 +107,37 @@ static void H5HL__fl_serialize(const H5HL_t *heap);
/* H5HL inherits cache-like properties from H5AC */
const H5AC_class_t H5AC_LHEAP_PRFX[1] = {{
- H5AC_LHEAP_PRFX_ID,
- (H5AC_load_func_t) H5HL__prefix_load,
- (H5AC_flush_func_t) H5HL__prefix_flush,
- (H5AC_dest_func_t) H5HL__prefix_dest,
- (H5AC_clear_func_t) H5HL__prefix_clear,
- (H5AC_notify_func_t) NULL,
- (H5AC_size_func_t) H5HL__prefix_size,
+ H5AC_LHEAP_PRFX_ID, /* Metadata client ID */
+ "local heap prefix", /* Metadata client name (for debugging) */
+ H5FD_MEM_LHEAP, /* File space memory type for client */
+ H5AC__CLASS_SPECULATIVE_LOAD_FLAG, /* Client class behavior flags */
+ H5HL__cache_prefix_get_load_size, /* 'get_load_size' callback */
+ NULL, /* 'verify_chksum' callback */
+ H5HL__cache_prefix_deserialize, /* 'deserialize' callback */
+ H5HL__cache_prefix_image_len, /* 'image_len' callback */
+ NULL, /* 'pre_serialize' callback */
+ H5HL__cache_prefix_serialize, /* 'serialize' callback */
+ NULL, /* 'notify' callback */
+ H5HL__cache_prefix_free_icr, /* 'free_icr' callback */
+ NULL, /* 'clear' callback */
+ NULL, /* 'fsf_size' callback */
}};
const H5AC_class_t H5AC_LHEAP_DBLK[1] = {{
- H5AC_LHEAP_DBLK_ID,
- (H5AC_load_func_t) H5HL__datablock_load,
- (H5AC_flush_func_t) H5HL__datablock_flush,
- (H5AC_dest_func_t) H5HL__datablock_dest,
- (H5AC_clear_func_t) H5HL__datablock_clear,
- (H5AC_notify_func_t) H5HL__datablock_notify,
- (H5AC_size_func_t) H5HL__datablock_size,
+ H5AC_LHEAP_DBLK_ID, /* Metadata client ID */
+ "local heap datablock", /* Metadata client name (for debugging) */
+ H5FD_MEM_LHEAP, /* File space memory type for client */
+ H5AC__CLASS_NO_FLAGS_SET, /* Client class behavior flags */
+ H5HL__cache_datablock_get_load_size,/* 'get_load_size' callback */
+ NULL, /* 'verify_chksum' callback */
+ H5HL__cache_datablock_deserialize, /* 'deserialize' callback */
+ H5HL__cache_datablock_image_len, /* 'image_len' callback */
+ NULL, /* 'pre_serialize' callback */
+ H5HL__cache_datablock_serialize, /* 'serialize' callback */
+ H5HL__cache_datablock_notify, /* 'notify' callback */
+ H5HL__cache_datablock_free_icr, /* 'free_icr' callback */
+ NULL, /* 'clear' callback */
+ NULL, /* 'fsf_size' callback */
}};
@@ -153,7 +177,7 @@ H5HL__fl_deserialize(H5HL_t *heap))
/* Build free list */
free_block = heap->free_block;
while(H5HL_FREE_NULL != free_block) {
- const uint8_t *p; /* Pointer into image buffer */
+ const uint8_t *image; /* Pointer into image buffer */
/* Sanity check */
if(free_block >= heap->dblk_size)
@@ -167,13 +191,13 @@ H5HL__fl_deserialize(H5HL_t *heap))
fl->next = NULL;
/* Decode offset of next free block */
- p = heap->dblk_image + free_block;
- H5F_DECODE_LENGTH_LEN(p, free_block, heap->sizeof_size);
+ image = heap->dblk_image + free_block;
+ H5F_DECODE_LENGTH_LEN(image, free_block, heap->sizeof_size);
if(0 == free_block)
H5E_THROW(H5E_BADVALUE, "free block size is zero?");
/* Decode length of this free block */
- H5F_DECODE_LENGTH_LEN(p, fl->size, heap->sizeof_size);
+ H5F_DECODE_LENGTH_LEN(image, fl->size, heap->sizeof_size);
if((fl->offset + fl->size) > heap->dblk_size)
H5E_THROW(H5E_BADRANGE, "bad heap free list");
@@ -217,105 +241,180 @@ H5HL__fl_serialize(const H5HL_t *heap))
/* Serialize the free list into the heap data's image */
for(fl = heap->freelist; fl; fl = fl->next) {
- uint8_t *p; /* Pointer into raw data buffer */
+ uint8_t *image; /* Pointer into raw data buffer */
HDassert(fl->offset == H5HL_ALIGN(fl->offset));
- p = heap->dblk_image + fl->offset;
+ image = heap->dblk_image + fl->offset;
if(fl->next)
- H5F_ENCODE_LENGTH_LEN(p, fl->next->offset, heap->sizeof_size)
+ H5F_ENCODE_LENGTH_LEN(image, fl->next->offset, heap->sizeof_size)
else
- H5F_ENCODE_LENGTH_LEN(p, H5HL_FREE_NULL, heap->sizeof_size)
+ H5F_ENCODE_LENGTH_LEN(image, H5HL_FREE_NULL, heap->sizeof_size)
- H5F_ENCODE_LENGTH_LEN(p, fl->size, heap->sizeof_size)
+ H5F_ENCODE_LENGTH_LEN(image, fl->size, heap->sizeof_size)
} /* end for */
END_FUNC_VOID(STATIC) /* end H5HL__fl_serialize() */
/*-------------------------------------------------------------------------
- * Function: H5HL__prefix_load
+ * Function: H5HL__cache_prefix_get_load_size()
*
- * Purpose: Loads a local heap prefix from disk.
+ * Purpose: Return the size of the buffer the metadata cache should
+ * load from file and pass to the deserialize routine.
*
- * Return: Success: Pointer to a local heap prefix structure.
- * Failure: NULL
+ * The version 2 metadata cache callbacks included a test to
+ * ensure that the read did not pass the end of file, but this
+ * functionality has been moved to H5C_load_entry(). Thus
+ * all this function does is set *image_len equal to
+ * H5HL_SPEC_READ_SIZE, leaving it to the metadata cache to
+ * reduce the size of the read if appropriate.
*
- * Programmer: Robb Matzke
- * Jul 17 1997
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: John Mainzer
+ * 6/21/14
*
*-------------------------------------------------------------------------
*/
-BEGIN_FUNC(STATIC, ERR,
-H5HL_prfx_t *, NULL, NULL,
-H5HL__prefix_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata))
-
- H5HL_t *heap = NULL; /* Local heap */
- H5HL_prfx_t *prfx = NULL; /* Heap prefix deserialized */
- H5HL_cache_prfx_ud_t *udata = (H5HL_cache_prfx_ud_t *)_udata; /* User data for callback */
- uint8_t buf[H5HL_SPEC_READ_SIZE]; /* Buffer for decoding */
- size_t spec_read_size; /* Size of buffer to speculatively read in */
- const uint8_t *p; /* Pointer into decoding buffer */
- haddr_t eoa; /* Relative end of file address */
- hsize_t min; /* temp min value to avoid macro nesting */
+static herr_t
+H5HL__cache_prefix_get_load_size(const void *_image, void *_udata, size_t *image_len, size_t *actual_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr)
+{
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ H5HL_cache_prfx_ud_t *udata = (H5HL_cache_prfx_ud_t *)_udata; /* User data for callback */
+ H5HL_t heap; /* Local heap */
+ htri_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
- /* check arguments */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
HDassert(udata);
- HDassert(udata->sizeof_size > 0);
- HDassert(udata->sizeof_addr > 0);
- HDassert(udata->sizeof_prfx > 0);
- HDassert(udata->sizeof_prfx <= sizeof(buf));
+ HDassert(image_len);
+
+ if(image == NULL)
+ *image_len = H5HL_SPEC_READ_SIZE;
+
+ else { /* compute actual_len */
+
+ HDassert(actual_len);
+ HDassert(*actual_len == *image_len);
+
+ /* Check magic number */
+ if(HDmemcmp(image, H5HL_MAGIC, (size_t)H5_SIZEOF_MAGIC))
+ HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "bad local heap signature")
+ image += H5_SIZEOF_MAGIC;
+
+ /* Version */
+ if(H5HL_VERSION != *image++)
+ HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "wrong version number in local heap")
+
+ /* Reserved */
+ image += 3;
+
+ /* Store the prefix's address & length */
+ heap.prfx_addr = udata->prfx_addr; /* NEED */
+ heap.prfx_size = udata->sizeof_prfx; /* NEED */
+
+ /* Heap data size */
+ H5F_DECODE_LENGTH_LEN(image, heap.dblk_size, udata->sizeof_size); /* NEED */
+
+ /* Free list head */
+ H5F_DECODE_LENGTH_LEN(image, heap.free_block, udata->sizeof_size);
+ if(heap.free_block != H5HL_FREE_NULL && heap.free_block >= heap.dblk_size)
+ HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "bad heap free list");
+
+ /* Heap data address */
+ H5F_addr_decode_len(udata->sizeof_addr, &image, &(heap.dblk_addr)); /* NEED */
+
+ *actual_len = heap.prfx_size;
+
+ /* Check if heap block exists */
+ if(heap.dblk_size) {
+ /* Check if heap data block is contiguous with header */
+ if(H5F_addr_eq((heap.prfx_addr + heap.prfx_size), heap.dblk_addr)) {
+ /* Note that the heap should be a single object in the cache */
+ *actual_len += heap.dblk_size;
+ }
+ } /* end if */
+ } /* end compute actual_len */
- /* Make certain we don't speculatively read off the end of the file */
- if(HADDR_UNDEF == (eoa = H5F_get_eoa(f, H5FD_MEM_LHEAP)))
- H5E_THROW(H5E_CANTGET, "unable to determine file size");
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HL__cache_prefix_get_load_size() */
- /* Compute the size of the speculative local heap prefix buffer */
- min = MIN(eoa - addr, H5HL_SPEC_READ_SIZE);
- H5_CHECKED_ASSIGN(spec_read_size, size_t, min, hsize_t);
- HDassert(spec_read_size >= udata->sizeof_prfx);
+
+/*-------------------------------------------------------------------------
+ * Function: H5HL__cache_prefix_deserialize
+ *
+ * Purpose: Given a buffer containing the on disk image of the local
+ * heap prefix, deserialize it, load its contents into a newly allocated
+ * instance of H5HL_prfx_t, and return a pointer to the new instance.
+ *
+ * Return: Success: Pointer to in core representation
+ * Failure: NULL
+ *
+ * Programmer: John Mainzer
+ * 6/21/14
+ *
+ *-------------------------------------------------------------------------
+ */
+static void *
+H5HL__cache_prefix_deserialize(const void *_image, size_t len, void *_udata,
+ hbool_t H5_ATTR_UNUSED *dirty)
+{
+ H5HL_t *heap = NULL; /* Local heap */
+ H5HL_prfx_t *prfx = NULL; /* Heap prefix deserialized */
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into decoding buffer */
+ H5HL_cache_prfx_ud_t *udata = (H5HL_cache_prfx_ud_t *)_udata; /* User data for callback */
+ void *ret_value; /* Return value */
+
+ FUNC_ENTER_STATIC
- /* Attempt to speculatively read both local heap prefix and heap data */
- if(FAIL == H5F_block_read(f, H5FD_MEM_LHEAP, addr, spec_read_size, dxpl_id, buf))
- H5E_THROW(H5E_READERROR, "unable to read local heap prefix");
- p = buf;
+ /* Check arguments */
+ HDassert(image);
+ HDassert(len > 0);
+ HDassert(udata);
+ HDassert(udata->sizeof_size > 0);
+ HDassert(udata->sizeof_addr > 0);
+ HDassert(udata->sizeof_prfx > 0);
+ HDassert(H5F_addr_defined(udata->prfx_addr));
+ HDassert(dirty);
/* Check magic number */
- if(HDmemcmp(p, H5HL_MAGIC, (size_t)H5_SIZEOF_MAGIC))
- H5E_THROW(H5E_BADVALUE, "bad local heap signature");
- p += H5_SIZEOF_MAGIC;
+ if(HDmemcmp(image, H5HL_MAGIC, (size_t)H5_SIZEOF_MAGIC))
+ HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, NULL, "bad local heap signature")
+ image += H5_SIZEOF_MAGIC;
/* Version */
- if(H5HL_VERSION != *p++)
- H5E_THROW(H5E_BADVALUE, "wrong version number in local heap");
+ if(H5HL_VERSION != *image++)
+ HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, NULL, "wrong version number in local heap")
/* Reserved */
- p += 3;
-
+ image += 3;
+
/* Allocate space in memory for the heap */
if(NULL == (heap = H5HL__new(udata->sizeof_size, udata->sizeof_addr, udata->sizeof_prfx)))
- H5E_THROW(H5E_CANTALLOC, "can't allocate local heap structure");
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, NULL, "can't allocate local heap structure");
/* Allocate the heap prefix */
if(NULL == (prfx = H5HL__prfx_new(heap)))
- H5E_THROW(H5E_CANTALLOC, "can't allocate local heap prefix");
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, NULL, "can't allocate local heap prefix");
/* Store the prefix's address & length */
heap->prfx_addr = udata->prfx_addr;
heap->prfx_size = udata->sizeof_prfx;
/* Heap data size */
- H5F_DECODE_LENGTH_LEN(p, heap->dblk_size, udata->sizeof_size);
+ H5F_DECODE_LENGTH_LEN(image, heap->dblk_size, udata->sizeof_size);
/* Free list head */
- H5F_DECODE_LENGTH_LEN(p, heap->free_block, udata->sizeof_size);
+ H5F_DECODE_LENGTH_LEN(image, heap->free_block, udata->sizeof_size);
if(heap->free_block != H5HL_FREE_NULL && heap->free_block >= heap->dblk_size)
- H5E_THROW(H5E_BADVALUE, "bad heap free list");
+ HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, NULL, "bad heap free list");
/* Heap data address */
- H5F_addr_decode_len(udata->sizeof_addr, &p, &(heap->dblk_addr));
+ H5F_addr_decode_len(udata->sizeof_addr, &image, &(heap->dblk_addr));
/* Check if heap block exists */
if(heap->dblk_size) {
@@ -324,318 +423,345 @@ H5HL__prefix_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata))
/* Note that the heap should be a single object in the cache */
heap->single_cache_obj = TRUE;
- /* Allocate space for the heap data image */
- if(NULL == (heap->dblk_image = H5FL_BLK_MALLOC(lheap_chunk, heap->dblk_size)))
- H5E_THROW(H5E_CANTALLOC, "memory allocation failed");
+ /* Check if the current buffer from the speculative read
+ * already has the heap data
+ */
+ if(len >= (heap->prfx_size + heap->dblk_size)) {
+ /* Allocate space for the heap data image */
+ if(NULL == (heap->dblk_image = H5FL_BLK_MALLOC(lheap_chunk, heap->dblk_size)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, NULL, "memory allocation failed")
- /* Check if the current buffer from the speculative read already has the heap data */
- if(spec_read_size >= (heap->prfx_size + heap->dblk_size)) {
- /* Set p to the start of the data block. This is necessary
+ /* Set image to the start of the data block. This is necessary
* because there may be a gap between the used portion of the
* prefix and the data block due to alignment constraints. */
- p = buf + heap->prfx_size;
+ image = ((const uint8_t *)_image) + heap->prfx_size;
/* Copy the heap data from the speculative read buffer */
- HDmemcpy(heap->dblk_image, p, heap->dblk_size);
+ HDmemcpy(heap->dblk_image, image, heap->dblk_size);
+
+ /* Build free list */
+ if(H5HL__fl_deserialize(heap) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, NULL, "can't initialize free list")
} /* end if */
else {
- /* Read the local heap data block directly into buffer */
- if(FAIL == H5F_block_read(f, H5FD_MEM_LHEAP, heap->dblk_addr, heap->dblk_size, dxpl_id, heap->dblk_image))
- H5E_THROW(H5E_READERROR, "unable to read heap data");
- } /* end else */
-
- /* Build free list */
- if(FAIL == H5HL__fl_deserialize(heap))
- H5E_THROW(H5E_CANTINIT, "can't initialize free list");
+ /* the supplied buffer is too small -- We have already made note
+ * of the correct size, so simply return success. H5C_load_entry()
+ * will notice the size discrepency, and re-try the load.
+ */
+
+ /* Make certain that this is the first try ... */
+ HDassert(!udata->made_attempt);
+
+ /* ... and mark the udata so that we know that we have used up
+ * our first try.
+ */
+ udata->made_attempt = TRUE;
+ } /* end else */
} /* end if */
- else
- /* Note that the heap should _NOT_ be a single object in the cache */
+ else {
+ /* Note that the heap should _NOT_ be a single
+ * object in the cache
+ */
heap->single_cache_obj = FALSE;
+
+ } /* end else */
} /* end if */
+ /* Set flag to indicate prefix from loaded from file */
+ udata->loaded = TRUE;
+
/* Set return value */
ret_value = prfx;
-CATCH
+done:
/* Release the [possibly partially initialized] local heap on errors */
if(!ret_value) {
if(prfx) {
if(FAIL == H5HL__prfx_dest(prfx))
- H5E_THROW(H5E_CANTRELEASE, "unable to destroy local heap prefix");
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, NULL, "unable to destroy local heap prefix");
} /* end if */
else {
if(heap && FAIL == H5HL__dest(heap))
- H5E_THROW(H5E_CANTRELEASE, "unable to destroy local heap");
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, NULL, "unable to destroy local heap");
} /* end else */
} /* end if */
-END_FUNC(STATIC) /* end H5HL__prefix_load() */
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HL__cache_prefix_deserialize() */
/*-------------------------------------------------------------------------
- * Function: H5HL__prefix_flush
+ * Function: H5HL__cache_prefix_image_len
*
- * Purpose: Flushes a heap from memory to disk if it's dirty. Optionally
- * deletes the heap from memory.
+ * Purpose: Return the on disk image size of a local heap prefix to the
+ * metadata cache via the image_len.
*
- * Return: SUCCEED/FAIL
+ * Return: Success: SUCCEED
+ * Failure: FAIL
*
- * Programmer: Robb Matzke
- * Jul 17 1997
+ * Programmer: John Mainzer
+ * 6/21/14
*
*-------------------------------------------------------------------------
*/
-BEGIN_FUNC(STATIC, ERR,
-herr_t, SUCCEED, FAIL,
-H5HL__prefix_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr,
- H5HL_prfx_t *prfx, unsigned H5_ATTR_UNUSED *flags_ptr))
+static herr_t
+H5HL__cache_prefix_image_len(const void *_thing, size_t *image_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr)
+{
+ const H5HL_prfx_t *prfx = (const H5HL_prfx_t *)_thing; /* Pointer to local heap prefix to query */
- H5WB_t *wb = NULL; /* Wrapped buffer for heap data */
- uint8_t heap_buf[H5HL_SPEC_READ_SIZE]; /* Buffer for heap */
+ FUNC_ENTER_STATIC_NOERR
- /* check arguments */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
+ /* Check arguments */
HDassert(prfx);
+ HDassert(prfx->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(prfx->cache_info.type == H5AC_LHEAP_PRFX);
+ HDassert(image_len);
- if(prfx->cache_info.is_dirty) {
- H5HL_t *heap = prfx->heap; /* Pointer to the local heap */
- uint8_t *buf; /* Pointer to heap buffer */
- size_t buf_size; /* Size of buffer for encoding & writing heap info */
- uint8_t *p; /* Pointer into raw data buffer */
-
- /* Wrap the local buffer for serialized heap info */
- if(NULL == (wb = H5WB_wrap(heap_buf, sizeof(heap_buf))))
- H5E_THROW(H5E_CANTINIT, "can't wrap buffer");
-
-
- /* Compute the size of the buffer to encode & write */
- buf_size = heap->prfx_size;
- if(heap->single_cache_obj)
- buf_size += heap->dblk_size;
-
- /* Get a pointer to a buffer that's large enough for serialized heap */
- if(NULL == (buf = (uint8_t *)H5WB_actual(wb, buf_size)))
- H5E_THROW(H5E_NOSPACE, "can't get actual buffer");
-
- /* Update the free block value from the free list */
- heap->free_block = heap->freelist ? heap->freelist->offset : H5HL_FREE_NULL;
-
- /* Serialize the heap prefix */
- p = buf;
- HDmemcpy(p, H5HL_MAGIC, (size_t)H5_SIZEOF_MAGIC);
- p += H5_SIZEOF_MAGIC;
- *p++ = H5HL_VERSION;
- *p++ = 0; /*reserved*/
- *p++ = 0; /*reserved*/
- *p++ = 0; /*reserved*/
- H5F_ENCODE_LENGTH_LEN(p, heap->dblk_size, heap->sizeof_size);
- H5F_ENCODE_LENGTH_LEN(p, heap->free_block, heap->sizeof_size);
- H5F_addr_encode_len(heap->sizeof_addr, &p, heap->dblk_addr);
-
- /* Check if the local heap is a single object in cache */
- if(heap->single_cache_obj) {
- if((size_t)(p - buf) < heap->prfx_size) {
- size_t gap; /* Size of gap between prefix and data block */
-
- /* Set p to the start of the data block. This is necessary because
- * there may be a gap between the used portion of the prefix and the
- * data block due to alignment constraints. */
- gap = heap->prfx_size - (size_t)(p - buf);
- HDmemset(p, 0, gap);
- p += gap;
- } /* end if */
-
- /* Serialize the free list into the heap data's image */
- H5HL__fl_serialize(heap);
+ /* Set the prefix's size */
+ *image_len = prfx->heap->prfx_size;
- /* Copy the heap data block into the cache image */
- HDmemcpy(p, heap->dblk_image, heap->dblk_size);
- } /* end if */
-
- /* Write the prefix [and possibly the data block] to the file */
- if(FAIL == H5F_block_write(f, H5FD_MEM_LHEAP, addr, buf_size, dxpl_id, buf))
- H5E_THROW(H5E_WRITEERROR, "unable to write heap header and data to file");
-
- prfx->cache_info.is_dirty = FALSE;
- } /* end if */
-
- /* Should we destroy the memory version? */
- if(destroy)
- if(FAIL == H5HL__prefix_dest(f, prfx))
- H5E_THROW(H5E_CANTFREE, "unable to destroy local heap prefix");
+ /* If the heap is stored as a single object, add in the
+ * data block size also
+ */
+ if(prfx->heap->single_cache_obj)
+ *image_len += prfx->heap->dblk_size;
-CATCH
- /* Release resources */
- if(wb && FAIL == H5WB_unwrap(wb))
- H5E_THROW(H5E_CLOSEERROR, "can't close wrapped buffer");
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5HL__cache_prefix_image_len() */
-END_FUNC(STATIC) /* end H5HL__prefix_flush() */
+/****************************************/
+/* no H5HL_cache_prefix_pre_serialize() */
+/****************************************/
/*-------------------------------------------------------------------------
- * Function: H5HL__prefix_dest
+ * Function: H5HL__cache_prefix_serialize
*
- * Purpose: Destroys a heap prefix in memory.
+ * Purpose: Given a pointer to an instance of H5HL_prfx_t and an
+ * appropriately sized buffer, serialize the contents of the
+ * instance for writing to disk, and copy the serialized data
+ * into the buffer.
*
- * Return: SUCCEED/FAIL
+ * Return: Success: SUCCEED
+ * Failure: FAIL
*
- * Programmer: Quincey Koziol
- * Jan 15 2003
+ * Programmer: John Mainzer
+ * 7/21/14
*
*-------------------------------------------------------------------------
*/
-BEGIN_FUNC(STATIC, ERR,
-herr_t, SUCCEED, FAIL,
-H5HL__prefix_dest(H5F_t *f, H5HL_prfx_t *prfx))
+static herr_t
+H5HL__cache_prefix_serialize(const H5F_t *f, void *_image, size_t len,
+ void *_thing)
+{
+ H5HL_prfx_t *prfx = (H5HL_prfx_t *)_thing; /* Pointer to local heap prefix to query */
+ H5HL_t *heap; /* Pointer to the local heap */
+ uint8_t *image = (uint8_t *)_image; /* Pointer into image buffer */
+ size_t buf_size; /* expected size of the image buffer */
- /* check arguments */
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Check arguments */
+ HDassert(f);
+ HDassert(image);
HDassert(prfx);
- HDassert(prfx->heap);
+ HDassert(prfx->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(prfx->cache_info.type == H5AC_LHEAP_PRFX);
HDassert(H5F_addr_eq(prfx->cache_info.addr, prfx->heap->prfx_addr));
+ HDassert(prfx->heap);
- /* Verify that entry is clean */
- HDassert(prfx->cache_info.is_dirty == FALSE);
-
- /* If we're going to free the space on disk, the address must be valid */
- HDassert(!prfx->cache_info.free_file_space_on_destroy || H5F_addr_defined(prfx->cache_info.addr));
+ /* Get the pointer to the heap */
+ heap = prfx->heap;
+ HDassert(heap);
- /* Check for freeing file space for local heap prefix */
- if(prfx->cache_info.free_file_space_on_destroy) {
- hsize_t free_size; /* Size of region to free in file */
+ /* Compute the buffer size */
+ buf_size = heap->prfx_size;
+ if(heap->single_cache_obj)
+ buf_size += heap->dblk_size;
+ HDassert(len == buf_size);
+
+ /* Update the free block value from the free list */
+ heap->free_block = heap->freelist ? heap->freelist->offset : H5HL_FREE_NULL;
+
+ /* Serialize the heap prefix */
+ HDmemcpy(image, H5HL_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ image += H5_SIZEOF_MAGIC;
+ *image++ = H5HL_VERSION;
+ *image++ = 0; /*reserved*/
+ *image++ = 0; /*reserved*/
+ *image++ = 0; /*reserved*/
+ H5F_ENCODE_LENGTH_LEN(image, heap->dblk_size, heap->sizeof_size);
+ H5F_ENCODE_LENGTH_LEN(image, heap->free_block, heap->sizeof_size);
+ H5F_addr_encode_len(heap->sizeof_addr, &image, heap->dblk_addr);
+
+ /* Check if the local heap is a single object in cache */
+ if(heap->single_cache_obj) {
+ if((size_t)(image - (uint8_t *)_image) < heap->prfx_size) {
+ size_t gap; /* Size of gap between prefix and data block */
+
+ /* Set image to the start of the data block. This is necessary
+ * because there may be a gap between the used portion of
+ * the prefix and the data block due to alignment constraints.
+ */
+ gap = heap->prfx_size - (size_t)(image - (uint8_t *)_image);
+ HDmemset(image, 0, gap);
+ image += gap;
+ } /* end if */
- /* Compute size to free for later */
- free_size = prfx->heap->prfx_size;
- if(prfx->heap->single_cache_obj)
- free_size += prfx->heap->dblk_size;
+ /* Serialize the free list into the heap data's image */
+ H5HL__fl_serialize(heap);
- /* Free the local heap prefix [and possible the data block] on disk */
- /* (XXX: Nasty usage of internal DXPL value! -QAK) */
- if(FAIL == H5MF_xfree(f, H5FD_MEM_LHEAP, H5AC_dxpl_id, prfx->cache_info.addr, free_size))
- H5E_THROW(H5E_CANTFREE, "unable to free local heap prefix");
+ /* Copy the heap data block into the cache image */
+ HDmemcpy(image, heap->dblk_image, heap->dblk_size);
} /* end if */
- /* Destroy local heap prefix */
- if(FAIL == H5HL__prfx_dest(prfx))
- H5E_THROW(H5E_CANTRELEASE, "can't destroy local heap prefix");
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5HL__cache_prefix_serialize() */
-CATCH
- /* No special processing on errors */
-
-END_FUNC(STATIC) /* end H5HL__prefix_dest() */
+/******************************************/
+/* no H5HL_cache_prefix_notify() function */
+/******************************************/
/*-------------------------------------------------------------------------
- * Function: H5HL__prefix_clear
+ * Function: H5HL__cache_prefix_free_icr
*
- * Purpose: Mark a local heap prefix in memory as non-dirty.
+ * Purpose: Free the supplied in core representation of a local heap
+ * prefix.
*
- * Return: SUCCEED/FAIL
+ * Note that this function handles the partially initialize prefix
+ * from a failed speculative load attempt. See comments below for
+ * details.
*
- * Programmer: Quincey Koziol
- * Mar 20 2003
+ * Note: The metadata cache sets the object's cache_info.magic to
+ * H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC before calling a free_icr
+ * callback (checked in assert).
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: John Mainzer
+ * 6/21/14
*
*-------------------------------------------------------------------------
*/
-BEGIN_FUNC(STATIC, ERR,
-herr_t, SUCCEED, FAIL,
-H5HL__prefix_clear(H5F_t H5_ATTR_UNUSED *f, H5HL_prfx_t *prfx, hbool_t destroy))
+static herr_t
+H5HL__cache_prefix_free_icr(void *_thing)
+{
+ H5HL_prfx_t *prfx = (H5HL_prfx_t *)_thing; /* Pointer to local heap prefix to query */
+ herr_t ret_value = SUCCEED; /* Return value */
- /* check arguments */
- HDassert(prfx);
+ FUNC_ENTER_STATIC
- /* Mark heap prefix as clean */
- prfx->cache_info.is_dirty = FALSE;
+ /* Check arguments */
+ HDassert(prfx);
+ HDassert(prfx->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC);
+ HDassert(prfx->cache_info.type == H5AC_LHEAP_PRFX);
+ HDassert(H5F_addr_eq(prfx->cache_info.addr, prfx->heap->prfx_addr));
- if(destroy)
- if(FAIL == H5HL__prefix_dest(f, prfx))
- H5E_THROW(H5E_CANTFREE, "unable to destroy local heap prefix");
-
-CATCH
- /* No special processing on errors */
+ /* Destroy local heap prefix */
+ if(H5HL__prfx_dest(prfx) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't destroy local heap prefix")
-END_FUNC(STATIC) /* end H5HL__prefix_clear() */
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HL__cache_prefix_free_icr() */
/*-------------------------------------------------------------------------
- * Function: H5HL__prefix_size
+ * Function: H5HL__cache_datablock_get_load_size()
*
- * Purpose: Compute the size in bytes of the heap prefix on disk,
- * and return it in *len_ptr. On failure, the value of *len_ptr
- * is undefined.
+ * Purpose: Tell the metadata cache how large a buffer to read from
+ * file when loading a datablock. In this case, we simply lookup
+ * the correct value in the user data, and return it in *image_len.
*
- * Return: SUCCEED (Can't fail)
+ * Return: Success: SUCCEED
+ * Failure: FAIL
*
* Programmer: John Mainzer
- * 5/13/04
+ * 6/21/14
*
*-------------------------------------------------------------------------
*/
-BEGIN_FUNC(STATIC, NOERR,
-herr_t, SUCCEED, -,
-H5HL__prefix_size(const H5F_t H5_ATTR_UNUSED *f, H5HL_prfx_t *prfx, size_t *size_ptr))
+static herr_t
+H5HL__cache_datablock_get_load_size(const void *_image, void *_udata,
+ size_t *image_len, size_t *actual_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr)
+{
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into image buffer */
+ H5HL_cache_dblk_ud_t *udata = (H5HL_cache_dblk_ud_t *)_udata; /* User data for callback */
- /* check arguments */
- HDassert(prfx);
- HDassert(prfx->heap);
- HDassert(size_ptr);
+ FUNC_ENTER_STATIC_NOERR
- /* Calculate size of prefix in cache */
- *size_ptr = prfx->heap->prfx_size;
+ /* Check arguments */
+ HDassert(udata);
+ HDassert(udata->heap);
+ HDassert(udata->heap->dblk_size > 0);
+ HDassert(image_len);
- /* If the heap is stored as a single object, add in the data block size also */
- if(prfx->heap->single_cache_obj)
- *size_ptr += prfx->heap->dblk_size;
+ if(image == NULL)
+ *image_len = udata->heap->dblk_size;
+ else {
+ HDassert(actual_len);
+ HDassert(*actual_len == *image_len);
+ }
-END_FUNC(STATIC) /* H5HL__prefix_size() */
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5HL__cache_datablock_get_load_size() */
/*-------------------------------------------------------------------------
- * Function: H5HL__datablock_load
+ * Function: H5HL__cache_datablock_deserialize
*
- * Purpose: Loads a local heap data block from disk.
+ * Purpose: Given a buffer containing the on disk image of a local
+ * heap data block, deserialize it, load its contents into a newly allocated
+ * instance of H5HL_dblk_t, and return a pointer to the new instance.
*
- * Return: Success: Pointer to a local heap data block memory data
- * structure.
- * Failure: NULL
+ * Return: Success: Pointer to in core representation
+ * Failure: NULL
*
- * Programmer: Quincey Koziol
- * Jan 5 2010
+ * Programmer: John Mainzer
+ * 6/21/14
*
*-------------------------------------------------------------------------
*/
-BEGIN_FUNC(STATIC, ERR,
-H5HL_dblk_t *, NULL, NULL,
-H5HL__datablock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata))
+static void *
+H5HL__cache_datablock_deserialize(const void *image, size_t len, void *_udata,
+ hbool_t H5_ATTR_UNUSED *dirty)
+{
+ H5HL_dblk_t *dblk = NULL; /* Local heap data block deserialized */
+ H5HL_cache_dblk_ud_t *udata = (H5HL_cache_dblk_ud_t *)_udata; /* User data for callback */
+ void * ret_value; /* Return value */
- H5HL_dblk_t *dblk = NULL; /* Local heap data block deserialized */
- H5HL_cache_dblk_ud_t *udata = (H5HL_cache_dblk_ud_t *)_udata; /* User data for callback */
+ FUNC_ENTER_STATIC
/* Check arguments */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
+ HDassert(image);
+ HDassert(len > 0);
HDassert(udata);
HDassert(udata->heap);
+ HDassert(udata->heap->dblk_size == len);
HDassert(!udata->heap->single_cache_obj);
HDassert(NULL == udata->heap->dblk);
+ HDassert(dirty);
/* Allocate space in memory for the heap data block */
if(NULL == (dblk = H5HL__dblk_new(udata->heap)))
- H5E_THROW(H5E_CANTALLOC, "memory allocation failed");
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, NULL, "memory allocation failed");
/* Check for heap still retaining image */
if(NULL == udata->heap->dblk_image) {
/* Allocate space for the heap data image */
if(NULL == (udata->heap->dblk_image = H5FL_BLK_MALLOC(lheap_chunk, udata->heap->dblk_size)))
- H5E_THROW(H5E_CANTALLOC, "can't allocate data block image buffer");
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, NULL, "can't allocate data block image buffer");
- /* Read local heap data block */
- if(FAIL == H5F_block_read(f, H5FD_MEM_LHEAP, udata->heap->dblk_addr, udata->heap->dblk_size, dxpl_id, udata->heap->dblk_image))
- H5E_THROW(H5E_READERROR, "unable to read local heap data block");
+ /* copy the datablock from the read buffer */
+ HDmemcpy(udata->heap->dblk_image, image, len);
/* Build free list */
if(FAIL == H5HL__fl_deserialize(udata->heap))
- H5E_THROW(H5E_CANTINIT, "can't initialize free list");
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, NULL, "can't initialize free list");
} /* end if */
/* Set flag to indicate data block from loaded from file */
@@ -644,146 +770,104 @@ H5HL__datablock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata))
/* Set return value */
ret_value = dblk;
-CATCH
+done:
/* Release the [possibly partially initialized] local heap on errors */
if(!ret_value && dblk)
if(FAIL == H5HL__dblk_dest(dblk))
- H5E_THROW(H5E_CANTRELEASE, "unable to destroy local heap data block");
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, NULL, "unable to destroy local heap data block");
-END_FUNC(STATIC) /* end H5HL__datablock_load() */
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HL__cache_datablock_deserialize() */
/*-------------------------------------------------------------------------
- * Function: H5HL__datablock_flush
+ * Function: H5HL__cache_datablock_image_len
*
- * Purpose: Flushes a heap's data block from memory to disk if it's dirty.
- * Optionally deletes the heap data block from memory.
+ * Purpose: Return the size of the on disk image of the datablock.
*
- * Return: SUCCEED/FAIL
+ * Return: Success: SUCCEED
+ * Failure: FAIL
*
- * Programmer: Robb Matzke
- * Jul 17 1997
+ * Programmer: John Mainzer
+ * 6/21/14
*
*-------------------------------------------------------------------------
*/
-BEGIN_FUNC(STATIC, ERR,
-herr_t, SUCCEED, FAIL,
-H5HL__datablock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr,
- H5HL_dblk_t *dblk, unsigned H5_ATTR_UNUSED * flags_ptr))
+static herr_t
+H5HL__cache_datablock_image_len(const void *_thing, size_t *image_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr)
+{
+ const H5HL_dblk_t *dblk = (const H5HL_dblk_t *)_thing; /* Pointer to the local heap data block */
- /* check arguments */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
- HDassert(dblk);
- HDassert(dblk->heap);
- HDassert(!dblk->heap->single_cache_obj);
-
- if(dblk->cache_info.is_dirty) {
- H5HL_t *heap = dblk->heap; /* Pointer to the local heap */
-
- /* Update the free block value from the free list */
- heap->free_block = heap->freelist ? heap->freelist->offset : H5HL_FREE_NULL;
-
- /* Serialize the free list into the heap data's image */
- H5HL__fl_serialize(heap);
-
- /* Write the data block to the file */
- if(FAIL == H5F_block_write(f, H5FD_MEM_LHEAP, heap->dblk_addr, heap->dblk_size, dxpl_id, heap->dblk_image))
- H5E_THROW(H5E_WRITEERROR, "unable to write heap data block to file");
-
- dblk->cache_info.is_dirty = FALSE;
- } /* end if */
-
- /* Should we destroy the memory version? */
- if(destroy)
- if(FAIL == H5HL__datablock_dest(f, dblk))
- H5E_THROW(H5E_CANTFREE, "unable to destroy local heap data block");
-
-CATCH
- /* No special processing on errors */
-
-END_FUNC(STATIC) /* end H5HL__datablock_flush() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5HL__datablock_dest
- *
- * Purpose: Destroys a local heap data block in memory.
- *
- * Return: SUCCEED/FAIL
- *
- * Programmer: Quincey Koziol
- * Jan 15 2003
- *
- *-------------------------------------------------------------------------
- */
-BEGIN_FUNC(STATIC, ERR,
-herr_t, SUCCEED, FAIL,
-H5HL__datablock_dest(H5F_t *f, H5HL_dblk_t *dblk))
+ FUNC_ENTER_STATIC_NOERR
/* Check arguments */
HDassert(dblk);
+ HDassert(dblk->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(dblk->cache_info.type == H5AC_LHEAP_DBLK);
HDassert(dblk->heap);
- HDassert(!dblk->heap->single_cache_obj);
- HDassert(H5F_addr_eq(dblk->cache_info.addr, dblk->heap->dblk_addr));
+ HDassert(dblk->heap->dblk_size > 0);
+ HDassert(image_len);
- /* Verify that entry is clean */
- HDassert(dblk->cache_info.is_dirty == FALSE);
+ *image_len = dblk->heap->dblk_size;
- /* If we're going to free the space on disk, the address must be valid */
- HDassert(!dblk->cache_info.free_file_space_on_destroy || H5F_addr_defined(dblk->cache_info.addr));
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5HL__cache_datablock_image_len() */
- /* Check for freeing file space for local heap data block */
- if(dblk->cache_info.free_file_space_on_destroy) {
- /* Free the local heap data block on disk */
- /* (XXX: Nasty usage of internal DXPL value! -QAK) */
- if(FAIL == H5MF_xfree(f, H5FD_MEM_LHEAP, H5AC_dxpl_id, dblk->cache_info.addr, (hsize_t)dblk->heap->dblk_size))
- H5E_THROW(H5E_CANTFREE, "unable to free local heap data block");
- } /* end if */
-
- /* Destroy local heap data block */
- if(FAIL == H5HL__dblk_dest(dblk))
- H5E_THROW(H5E_CANTRELEASE, "can't destroy local heap data block");
-
-CATCH
- /* No special processing on errors */
-
-END_FUNC(STATIC) /* end H5HL__datablock_dest() */
+/*******************************************/
+/* no H5HL_cache_datablock_pre_serialize() */
+/*******************************************/
/*-------------------------------------------------------------------------
- * Function: H5HL__datablock_clear
+ * Function: H5HL__cache_datablock_serialize
*
- * Purpose: Mark a local heap data block in memory as non-dirty.
+ * Purpose: Serialize the supplied datablock, and copy the serialized
+ * image into the supplied image buffer.
*
- * Return: SUCCEED/FAIL
+ * Return: Success: SUCCEED
+ * Failure: FAIL
*
- * Programmer: Quincey Koziol
- * Mar 20 2003
+ * Programmer: John Mainzer
+ * 6/21/14
*
*-------------------------------------------------------------------------
*/
-BEGIN_FUNC(STATIC, ERR,
-herr_t, SUCCEED, FAIL,
-H5HL__datablock_clear(H5F_t *f, H5HL_dblk_t *dblk, hbool_t destroy))
+static herr_t
+H5HL__cache_datablock_serialize(const H5F_t *f, void *image, size_t len,
+ void *_thing)
+{
+ H5HL_t *heap; /* Pointer to the local heap */
+ H5HL_dblk_t *dblk = (H5HL_dblk_t *)_thing; /* Pointer to the local heap data block */
+
+ FUNC_ENTER_STATIC_NOERR
/* Check arguments */
+ HDassert(f);
+ HDassert(image);
HDassert(dblk);
+ HDassert(dblk->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(dblk->cache_info.type == H5AC_LHEAP_DBLK);
+ HDassert(dblk->heap);
+ heap = dblk->heap;
+ HDassert(heap->dblk_size == len);
+ HDassert(!heap->single_cache_obj);
- /* Mark local heap data block as clean */
- dblk->cache_info.is_dirty = FALSE;
+ /* Update the free block value from the free list */
+ heap->free_block = heap->freelist ? heap->freelist->offset : H5HL_FREE_NULL;
- if(destroy)
- if(FAIL == H5HL__datablock_dest(f, dblk))
- H5E_THROW(H5E_CANTFREE, "unable to destroy local heap data block");
+ /* Serialize the free list into the heap data's image */
+ H5HL__fl_serialize(heap);
-CATCH
+ /* Copy the heap's data block into the cache's image */
+ HDmemcpy(image, heap->dblk_image, heap->dblk_size);
-END_FUNC(STATIC) /* end H5HL__datablock_clear() */
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5HL__cache_datablock_serialize() */
/*-------------------------------------------------------------------------
- * Function: H5HL__datablock_notify
+ * Function: H5HL__cache_datablock_notify
*
* Purpose: Handle cache action notifications
*
@@ -796,8 +880,11 @@ END_FUNC(STATIC) /* end H5HL__datablock_clear() */
*/
BEGIN_FUNC(STATIC, ERR,
herr_t, SUCCEED, FAIL,
-H5HL__datablock_notify(H5AC_notify_action_t action, H5HL_dblk_t *dblk))
+H5HL__cache_datablock_notify(H5AC_notify_action_t action, void *_thing))
+ /* Local variables */
+ H5HL_dblk_t *dblk = (H5HL_dblk_t *)_thing;
+
/* Sanity check */
HDassert(dblk);
@@ -806,13 +893,20 @@ H5HL__datablock_notify(H5AC_notify_action_t action, H5HL_dblk_t *dblk))
/* Determine which action to take */
switch(action) {
case H5AC_NOTIFY_ACTION_AFTER_INSERT:
+ case H5AC_NOTIFY_ACTION_AFTER_LOAD:
/* Create flush dependency on parent */
if(FAIL == H5HL__create_flush_depend((H5AC_info_t *)dblk->heap->prfx, (H5AC_info_t *)dblk))
H5E_THROW(H5E_CANTDEPEND, "unable to create flush dependency between data block and parent, address = %llu", (unsigned long long)dblk->heap->dblk_addr);
break;
+ case H5AC_NOTIFY_ACTION_AFTER_FLUSH:
+ /* do nothing */
+ break;
+
case H5AC_NOTIFY_ACTION_BEFORE_EVICT:
- /* Nothing to do */
+ /* Destroy flush dependency on parent */
+ if(H5HL__destroy_flush_depend((H5AC_info_t *)dblk->heap->prfx, (H5AC_info_t *)dblk) < 0)
+ H5E_THROW(H5E_CANTUNDEPEND, "unable to destroy flush dependency")
break;
default:
@@ -827,34 +921,43 @@ H5HL__datablock_notify(H5AC_notify_action_t action, H5HL_dblk_t *dblk))
CATCH
/* No special processing on errors */
-END_FUNC(STATIC) /* end H5HL__datablock_notify() */
+END_FUNC(STATIC) /* end H5HL__cache_datablock_notify() */
/*-------------------------------------------------------------------------
- * Function: H5HL__datablock_size
+ * Function: H5HL__cache_datablock_free_icr
+ *
+ * Purpose: Free the in memory representation of the supplied local heap data block.
*
- * Purpose: Compute the size in bytes of the local heap data block on disk,
- * and return it in *len_ptr. On failure, the value of *len_ptr
- * is undefined.
+ * Note: The metadata cache sets the object's cache_info.magic to
+ * H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC before calling a free_icr
+ * callback (checked in assert).
*
- * Return: SUCCEED (Can't fail)
+ * Return: Success: SUCCEED
+ * Failure: FAIL
*
* Programmer: John Mainzer
- * 5/13/04
+ * 6/21/14
*
*-------------------------------------------------------------------------
*/
-BEGIN_FUNC(STATIC, NOERR,
-herr_t, SUCCEED, -,
-H5HL__datablock_size(const H5F_t H5_ATTR_UNUSED *f, H5HL_dblk_t *dblk, size_t *size_ptr))
+static herr_t
+H5HL__cache_datablock_free_icr(void *_thing)
+{
+ H5HL_dblk_t *dblk = (H5HL_dblk_t *)_thing; /* Pointer to the local heap data block */
+ herr_t ret_value = SUCCEED; /* Return value */
- /* check arguments */
- HDassert(dblk);
- HDassert(dblk->heap);
- HDassert(size_ptr);
+ FUNC_ENTER_STATIC
- /* Set size of data block in cache */
- *size_ptr = dblk->heap->dblk_size;
+ /* Check arguments */
+ HDassert(dblk);
+ HDassert(dblk->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC);
+ HDassert(dblk->cache_info.type == H5AC_LHEAP_DBLK);
-END_FUNC(STATIC) /* H5HL__datablock_size() */
+ /* Destroy the data block */
+ if(H5HL__dblk_dest(dblk) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy local heap data block")
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HL__cache_datablock_free_icr() */
diff --git a/src/H5HLdbg.c b/src/H5HLdbg.c
index e481b20..f94b0cc 100644
--- a/src/H5HLdbg.c
+++ b/src/H5HLdbg.c
@@ -57,7 +57,7 @@ H5HL_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE * stream, int indent, int
HDassert(indent >= 0);
HDassert(fwidth >= 0);
- if(NULL == (h = (H5HL_t *)H5HL_protect(f, dxpl_id, addr, H5AC_READ)))
+ if(NULL == (h = (H5HL_t *)H5HL_protect(f, dxpl_id, addr, H5AC__READ_ONLY_FLAG)))
H5E_THROW(H5E_CANTPROTECT, "unable to load/protect local heap");
HDfprintf(stream, "%*sLocal Heap...\n", indent, "");
diff --git a/src/H5HLpkg.h b/src/H5HLpkg.h
index 2670b18..77d6255 100644
--- a/src/H5HLpkg.h
+++ b/src/H5HLpkg.h
@@ -133,12 +133,16 @@ struct H5HL_prfx_t {
/* Callback information for loading local heap prefix from disk */
typedef struct H5HL_cache_prfx_ud_t {
/* Downwards */
- size_t sizeof_size; /* Size of file sizes */
- size_t sizeof_addr; /* Size of file addresses */
- haddr_t prfx_addr; /* Address of prefix */
- size_t sizeof_prfx; /* Size of heap prefix */
+ hbool_t made_attempt; /* Whether the deserialize routine */
+ /* was already attempted */
+ size_t sizeof_size; /* Size of file sizes */
+ size_t sizeof_addr; /* Size of file addresses */
+ haddr_t prfx_addr; /* Address of prefix */
+ size_t sizeof_prfx; /* Size of heap prefix */
/* Upwards */
+ hbool_t loaded; /* Whether prefix was loaded */
+ /* from file */
} H5HL_cache_prfx_ud_t;
/* Callback information for loading local heap data block from disk */
diff --git a/src/H5HLprivate.h b/src/H5HLprivate.h
index 7ca54b0..92ad9bc 100644
--- a/src/H5HLprivate.h
+++ b/src/H5HLprivate.h
@@ -65,7 +65,7 @@ H5_DLL herr_t H5HL_heapsize(H5F_t *f, hid_t dxpl_id, haddr_t addr, hsize_t *heap
H5_DLL size_t H5HL_insert(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t size,
const void *buf);
H5_DLL void *H5HL_offset_into(const H5HL_t *heap, size_t offset);
-H5_DLL H5HL_t *H5HL_protect(H5F_t *f, hid_t dxpl_id, haddr_t addr, H5AC_protect_t rw);
+H5_DLL H5HL_t *H5HL_protect(H5F_t *f, hid_t dxpl_id, haddr_t addr, unsigned flags);
H5_DLL herr_t H5HL_remove(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t offset,
size_t size);
H5_DLL herr_t H5HL_unprotect(H5HL_t *heap);
diff --git a/src/H5O.c b/src/H5O.c
index e1b4793..c79914a 100644
--- a/src/H5O.c
+++ b/src/H5O.c
@@ -1772,7 +1772,7 @@ done:
*-------------------------------------------------------------------------
*/
H5O_t *
-H5O_protect(const H5O_loc_t *loc, hid_t dxpl_id, H5AC_protect_t prot)
+H5O_protect(const H5O_loc_t *loc, hid_t dxpl_id, unsigned prot_flags)
{
H5O_t *oh = NULL; /* Object header protected */
H5O_cache_ud_t udata; /* User data for protecting object header */
@@ -1786,13 +1786,16 @@ H5O_protect(const H5O_loc_t *loc, hid_t dxpl_id, H5AC_protect_t prot)
HDassert(loc);
HDassert(loc->file);
+ /* prot_flags may only contain the H5AC__READ_ONLY_FLAG */
+ HDassert((prot_flags & (unsigned)(~H5AC__READ_ONLY_FLAG)) == 0);
+
/* Check for valid address */
if(!H5F_addr_defined(loc->addr))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "address undefined")
/* Check for write access on the file */
file_intent = H5F_INTENT(loc->file);
- if((prot == H5AC_WRITE) && (0 == (file_intent & H5F_ACC_RDWR)))
+ if((0 == (prot_flags & H5AC__READ_ONLY_FLAG)) && (0 == (file_intent & H5F_ACC_RDWR)))
HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "no write intent on file")
/* Construct the user data for protect callback */
@@ -1808,7 +1811,7 @@ H5O_protect(const H5O_loc_t *loc, hid_t dxpl_id, H5AC_protect_t prot)
udata.common.addr = loc->addr;
/* Lock the object header into the cache */
- if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, &udata, prot)))
+ if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, &udata, prot_flags)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, NULL, "unable to load object header")
/* Check if there are any continuation messages to process */
@@ -1845,7 +1848,7 @@ H5O_protect(const H5O_loc_t *loc, hid_t dxpl_id, H5AC_protect_t prot)
/* (which adds to the object header) */
chk_udata.common.addr = cont_msg_info.msgs[curr_msg].addr;
chk_udata.size = cont_msg_info.msgs[curr_msg].size;
- if(NULL == (chk_proxy = (H5O_chunk_proxy_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR_CHK, cont_msg_info.msgs[curr_msg].addr, &chk_udata, prot)))
+ if(NULL == (chk_proxy = (H5O_chunk_proxy_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR_CHK, cont_msg_info.msgs[curr_msg].addr, &chk_udata, prot_flags)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, NULL, "unable to load object header chunk")
/* Sanity check */
@@ -1889,7 +1892,7 @@ H5O_protect(const H5O_loc_t *loc, hid_t dxpl_id, H5AC_protect_t prot)
/* (object header will have been marked dirty during protect, if we
* have write access -QAK)
*/
- if(prot != H5AC_WRITE)
+ if((prot_flags & H5AC__READ_ONLY_FLAG) != 0)
oh->prefix_modified = TRUE;
#ifndef NDEBUG
else {
@@ -1907,7 +1910,7 @@ H5O_protect(const H5O_loc_t *loc, hid_t dxpl_id, H5AC_protect_t prot)
} /* end if */
/* Check for any messages that were modified while being read in */
- if(udata.common.mesgs_modified && prot != H5AC_WRITE)
+ if(udata.common.mesgs_modified && (0 == (prot_flags & H5AC__READ_ONLY_FLAG)))
oh->mesgs_modified = TRUE;
/* Reset the field that contained chunk 0's size during speculative load */
@@ -1917,7 +1920,7 @@ H5O_protect(const H5O_loc_t *loc, hid_t dxpl_id, H5AC_protect_t prot)
/* Take care of loose ends for modifications made while bringing in the
* object header & chunks.
*/
- if(prot == H5AC_WRITE) {
+ if(0 == (prot_flags & H5AC__READ_ONLY_FLAG)) {
/* Check for the object header prefix being modified somehow */
/* (usually through updating the # of object header messages) */
if(oh->prefix_modified) {
@@ -2003,7 +2006,7 @@ H5O_pin(const H5O_loc_t *loc, hid_t dxpl_id)
HDassert(loc);
/* Get header */
- if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_WRITE)))
+ if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, NULL, "unable to protect object header")
/* Increment the reference count on the object header */
@@ -2216,7 +2219,7 @@ H5O_touch(const H5O_loc_t *loc, hbool_t force, hid_t dxpl_id)
HDassert(loc);
/* Get the object header */
- if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_WRITE)))
+ if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
/* Create/Update the modification time message */
@@ -2333,7 +2336,7 @@ H5O_delete(H5F_t *f, hid_t dxpl_id, haddr_t addr)
loc.holding_file = FALSE;
/* Get the object header information */
- if(NULL == (oh = H5O_protect(&loc, dxpl_id, H5AC_WRITE)))
+ if(NULL == (oh = H5O_protect(&loc, dxpl_id, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
/* Delete object */
@@ -2425,7 +2428,7 @@ H5O_obj_type(const H5O_loc_t *loc, H5O_type_t *obj_type, hid_t dxpl_id)
FUNC_ENTER_NOAPI_TAG(dxpl_id, loc->addr, FAIL)
/* Load the object header */
- if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_READ)))
+ if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
/* Retrieve the type of the object */
@@ -2503,7 +2506,7 @@ H5O_obj_class(const H5O_loc_t *loc, hid_t dxpl_id)
FUNC_ENTER_NOAPI_NOINIT_TAG(dxpl_id, loc->addr, NULL)
/* Load the object header */
- if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_READ)))
+ if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, NULL, "unable to load object header")
/* Test whether entry qualifies as a particular type of object */
@@ -2800,7 +2803,7 @@ H5O_get_hdr_info(const H5O_loc_t *loc, hid_t dxpl_id, H5O_hdr_info_t *hdr)
HDmemset(hdr, 0, sizeof(*hdr));
/* Get the object header */
- if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_READ)))
+ if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header")
/* Get the information for the object header */
@@ -2924,7 +2927,7 @@ H5O_get_info(const H5O_loc_t *loc, hid_t dxpl_id, hbool_t want_ih_info,
HDassert(oinfo);
/* Get the object header */
- if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_READ)))
+ if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
/* Reset the object info structure */
@@ -3045,7 +3048,7 @@ H5O_get_create_plist(const H5O_loc_t *loc, hid_t dxpl_id, H5P_genplist_t *oc_pli
HDassert(oc_plist);
/* Get the object header */
- if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_READ)))
+ if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
/* Set property values, if they were used for the object */
@@ -3100,7 +3103,7 @@ H5O_get_nlinks(const H5O_loc_t *loc, hid_t dxpl_id, hsize_t *nlinks)
HDassert(nlinks);
/* Get the object header */
- if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_READ)))
+ if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
/* Retrieve the # of link messages seen when the object header was loaded */
@@ -3217,7 +3220,7 @@ H5O_get_rc_and_type(const H5O_loc_t *loc, hid_t dxpl_id, unsigned *rc, H5O_type_
HDassert(loc);
/* Get the object header */
- if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_READ)))
+ if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
/* Set the object's reference count */
@@ -3590,7 +3593,7 @@ H5O_dec_rc_by_loc(const H5O_loc_t *loc, hid_t dxpl_id)
HDassert(loc);
/* Get header */
- if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_READ)))
+ if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to protect object header")
/* Decrement the reference count on the object header */
@@ -3694,7 +3697,7 @@ H5O_pin_flush_dep_proxy(H5O_loc_t *loc, hid_t dxpl_id)
HDassert(loc);
/* Get header */
- if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_READ)))
+ if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, NULL, "unable to protect object header")
/* Pin object header proxy */
diff --git a/src/H5Oattribute.c b/src/H5Oattribute.c
index f7910f5..79ec506 100644
--- a/src/H5Oattribute.c
+++ b/src/H5Oattribute.c
@@ -493,7 +493,7 @@ H5O_attr_open_by_name(const H5O_loc_t *loc, const char *name, hid_t dxpl_id)
HDassert(name);
/* Protect the object header to iterate over */
- if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_READ)))
+ if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTPROTECT, NULL, "unable to load object header")
/* Check for attribute info stored */
@@ -650,7 +650,7 @@ H5O_attr_open_by_idx(const H5O_loc_t *loc, H5_index_t idx_type,
HGOTO_ERROR(H5E_ATTR, H5E_BADITER, NULL, "can't locate attribute")
/* Protect the object header to iterate over */
- if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_READ)))
+ if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTPROTECT, NULL, "unable to load object header")
/* Find out whether it has already been opened. If it has, close the object
@@ -1311,7 +1311,7 @@ H5O_attr_iterate_real(hid_t loc_id, const H5O_loc_t *loc, hid_t dxpl_id,
HDassert(attr_op);
/* Protect the object header to iterate over */
- if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_READ)))
+ if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTPROTECT, FAIL, "unable to load object header")
/* Check for attribute info stored */
@@ -1910,7 +1910,7 @@ H5O_attr_exists(const H5O_loc_t *loc, const char *name, hid_t dxpl_id)
HDassert(name);
/* Protect the object header to iterate over */
- if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_READ)))
+ if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTPROTECT, FAIL, "unable to load object header")
/* Check for attribute info stored */
@@ -2081,7 +2081,7 @@ H5O_attr_count(const H5O_loc_t *loc, hid_t dxpl_id)
HDassert(loc);
/* Protect the object header to iterate over */
- if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_READ)))
+ if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTPROTECT, FAIL, "unable to load object header")
/* Retrieve # of attributes on object */
diff --git a/src/H5Ocache.c b/src/H5Ocache.c
index 8653817..c7632bd 100644
--- a/src/H5Ocache.c
+++ b/src/H5Ocache.c
@@ -53,11 +53,6 @@
* size to save the extra I/O operations) */
#define H5O_SPEC_READ_SIZE 512
-/* Set the estimated size of the chunk to read */
-/* (Avoids an allocation, if we estimate correctly) */
-#define H5O_EST_CHUNK_SIZE 512
-
-
/******************/
/* Local Typedefs */
@@ -74,18 +69,32 @@
/********************/
/* Metadata cache callbacks */
-static H5O_t *H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata);
-static herr_t H5O_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5O_t *oh, unsigned H5_ATTR_UNUSED * flags_ptr);
-static herr_t H5O_dest(H5F_t *f, H5O_t *oh);
-static herr_t H5O_clear(H5F_t *f, H5O_t *oh, hbool_t destroy);
-static herr_t H5O_size(const H5F_t *f, const H5O_t *oh, size_t *size_ptr);
-
-static H5O_chunk_proxy_t *H5O_cache_chk_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata);
-static herr_t H5O_cache_chk_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5O_chunk_proxy_t *chk_proxy, unsigned H5_ATTR_UNUSED * flags_ptr);
-static herr_t H5O_cache_chk_dest(H5F_t *f, H5O_chunk_proxy_t *chk_proxy);
-static herr_t H5O_cache_chk_clear(H5F_t *f, H5O_chunk_proxy_t *chk_proxy, hbool_t destroy);
-static herr_t H5O_cache_chk_notify(H5AC_notify_action_t action, H5O_chunk_proxy_t *chk_proxy);
-static herr_t H5O_cache_chk_size(const H5F_t *f, const H5O_chunk_proxy_t *chk_proxy, size_t *size_ptr);
+static herr_t H5O__cache_get_load_size(const void *image_ptr, void *udata,
+ size_t *image_len, size_t *actual_len,
+ hbool_t *compressed_ptr, size_t *compressed_image_len_ptr);
+static htri_t H5O__cache_verify_chksum(const void *image_ptr, size_t len, void *udata_ptr);
+static void *H5O__cache_deserialize(const void *image, size_t len,
+ void *udata, hbool_t *dirty);
+static herr_t H5O__cache_image_len(const void *thing, size_t *image_len,
+ hbool_t *compressed_ptr, size_t *compressed_image_len_ptr);
+static herr_t H5O__cache_serialize(const H5F_t *f, void *image, size_t len,
+ void *thing);
+static herr_t H5O__cache_free_icr(void *thing);
+static herr_t H5O__cache_clear(const H5F_t *f, void *thing, hbool_t about_to_destroy);
+
+static herr_t H5O__cache_chk_get_load_size(const void *image_ptr, void *udata,
+ size_t *image_len, size_t *actual_len,
+ hbool_t *compressed_ptr, size_t *compressed_image_len_ptr);
+static htri_t H5O__cache_chk_verify_chksum(const void *image_ptr, size_t len, void *udata_ptr);
+static void *H5O__cache_chk_deserialize(const void *image, size_t len,
+ void *udata, hbool_t *dirty);
+static herr_t H5O__cache_chk_image_len(const void *thing, size_t *image_len,
+ hbool_t *compressed_ptr, size_t *compressed_image_len_ptr);
+static herr_t H5O__cache_chk_serialize(const H5F_t *f, void *image, size_t len,
+ void *thing);
+static herr_t H5O__cache_chk_notify(H5AC_notify_action_t action, void *_thing);
+static herr_t H5O__cache_chk_free_icr(void *thing);
+static herr_t H5O__cache_chk_clear(const H5F_t *f, void *thing, hbool_t about_to_destroy);
/* Chunk proxy routines */
static herr_t H5O__chunk_proxy_dest(H5O_chunk_proxy_t *chunk_proxy);
@@ -107,24 +116,38 @@ static herr_t H5O_decode_prefix(H5F_t *f, H5O_t *oh, const uint8_t *buf, void *_
/* H5O object header prefix inherits cache-like properties from H5AC */
const H5AC_class_t H5AC_OHDR[1] = {{
- H5AC_OHDR_ID,
- (H5AC_load_func_t)H5O_load,
- (H5AC_flush_func_t)H5O_flush,
- (H5AC_dest_func_t)H5O_dest,
- (H5AC_clear_func_t)H5O_clear,
- (H5AC_notify_func_t)NULL,
- (H5AC_size_func_t)H5O_size,
+ H5AC_OHDR_ID, /* Metadata client ID */
+ "object header", /* Metadata client name (for debugging) */
+ H5FD_MEM_OHDR, /* File space memory type for client */
+ H5AC__CLASS_SPECULATIVE_LOAD_FLAG, /* Client class behavior flags */
+ H5O__cache_get_load_size, /* 'get_load_size' callback */
+ H5O__cache_verify_chksum, /* 'verify_chksum' callback */
+ H5O__cache_deserialize, /* 'deserialize' callback */
+ H5O__cache_image_len, /* 'image_len' callback */
+ NULL, /* 'pre_serialize' callback */
+ H5O__cache_serialize, /* 'serialize' callback */
+ NULL, /* 'notify' callback */
+ H5O__cache_free_icr, /* 'free_icr' callback */
+ H5O__cache_clear, /* 'clear' callback */
+ NULL, /* 'fsf_size' callback */
}};
/* H5O object header chunk inherits cache-like properties from H5AC */
const H5AC_class_t H5AC_OHDR_CHK[1] = {{
- H5AC_OHDR_CHK_ID,
- (H5AC_load_func_t)H5O_cache_chk_load,
- (H5AC_flush_func_t)H5O_cache_chk_flush,
- (H5AC_dest_func_t)H5O_cache_chk_dest,
- (H5AC_clear_func_t)H5O_cache_chk_clear,
- (H5AC_notify_func_t)H5O_cache_chk_notify,
- (H5AC_size_func_t)H5O_cache_chk_size,
+ H5AC_OHDR_CHK_ID, /* Metadata client ID */
+ "object header continuation chunk", /* Metadata client name (for debugging) */
+ H5FD_MEM_OHDR, /* File space memory type for client */
+ H5AC__CLASS_NO_FLAGS_SET, /* Client class behavior flags */
+ H5O__cache_chk_get_load_size, /* 'get_load_size' callback */
+ H5O__cache_chk_verify_chksum, /* 'verify_chksum' callback */
+ H5O__cache_chk_deserialize, /* 'deserialize' callback */
+ H5O__cache_chk_image_len, /* 'image_len' callback */
+ NULL, /* 'pre_serialize' callback */
+ H5O__cache_chk_serialize, /* 'serialize' callback */
+ H5O__cache_chk_notify, /* 'notify' callback */
+ H5O__cache_chk_free_icr, /* 'free_icr' callback */
+ H5O__cache_chk_clear, /* 'clear' callback */
+ NULL, /* 'fsf_size' callback */
}};
/* Declare external the free list for H5O_unknown_t's */
@@ -151,11 +174,11 @@ H5FL_SEQ_DEFINE(H5O_cont_t);
* Function: H5O_decode_prefix
*
* Purpose: To decode the object header prefix.
- * The coding is extracted fromt H5O_load() to this routine.
+ * The coding is extracted fromt H5O__cache_deserialize() to this routine.
*
* Return: Non-negative on success/Negative on failure
*
- * Programmer: Vailin Choi; June 2013
+ * Programmer: Vailin Choi; Aug 2015
*
*-------------------------------------------------------------------------
*/
@@ -291,155 +314,177 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5O_load
+ * Function: H5O__cache_get_load_size()
+ *
+ * Purpose: Tell the metadata cache how much data to read from file in
+ * the first speculative read for the object header. Note that we do
+ * not have to be concerned about reading past the end of file, as the
+ * cache will clamp the read to avoid this if needed.
*
- * Purpose: Loads an object header from disk.
+ * Return: Success: SUCCEED
+ * Failure: FAIL
*
- * Return: Success: Pointer to the new object header.
+ * Programmer: John Mainzer
+ * 7/28/14
*
- * Failure: NULL
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O__cache_get_load_size(const void *_image, void *_udata, size_t *image_len, size_t *actual_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr)
+{
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ H5O_cache_ud_t *udata = (H5O_cache_ud_t *)_udata; /* User data for callback */
+ H5O_t oh; /* Object header read in */
+ htri_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Check arguments */
+ HDassert(image_len);
+
+ if(image == NULL)
+ *image_len = H5O_SPEC_READ_SIZE;
+
+ else { /* compute actual_len */
+ HDassert(udata);
+ HDassert(actual_len);
+ HDassert(*actual_len == *image_len);
+
+ /* Decode header prefix */
+ if(H5O_decode_prefix(udata->common.f, &oh, image, udata) < 0)
+ HGOTO_DONE(FAIL)
+
+ /* Save the version to be used in verify_chksum callback */
+ udata->version = oh.version;
+ *actual_len = oh.chunk0_size + (size_t)H5O_SIZEOF_HDR(&oh);
+ }
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O__cache_get_load_size() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O__cache_verify_chksum
*
- * Programmer: Robb Matzke
- * matzke@llnl.gov
- * Aug 5 1997
+ * Purpose: Verify the computed checksum of the data structure is the
+ * same as the stored chksum.
+ *
+ * Return: Success: TRUE/FALSE
+ * Failure: Negative
+ *
+ * Programmer: Vailin Choi; Aug 2015
*
- * Modifications:
- * Vailin Choi; June 2013
- * This is a fix for SWMR:
- * When reading a block that is > spec_read_size, read the whole block in
- * again and possibly decode the header.
- * Move the coding for decoding the object header prefix to another routine
- * H5O_decode_prefix().
*-------------------------------------------------------------------------
*/
-static H5O_t *
-H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
+static htri_t
+H5O__cache_verify_chksum(const void *_image, size_t len, void *_udata)
{
- H5O_t *oh = NULL; /* Object header read in */
- H5O_cache_ud_t *udata = (H5O_cache_ud_t *)_udata; /* User data for callback */
- uint8_t read_buf[H5O_SPEC_READ_SIZE]; /* Buffer for speculative read */
- uint8_t *buf = NULL; /* Buffer to decode */
- size_t spec_read_size; /* Size of buffer to speculatively read in */
- size_t buf_size; /* Size of prefix+chunk #0 buffer */
- haddr_t eoa; /* Relative end of file address */
- unsigned tries, max_tries; /* The # of read attempts */
- unsigned retries; /* The # of retries */
- unsigned fixed_tries; /* The # of read attempts for prefix */
- uint32_t stored_chksum; /* Stored metadata checksum value */
- uint32_t computed_chksum;/* Computed metadata checksum value */
- H5O_t *ret_value; /* Return value */
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ H5O_cache_ud_t *udata = (H5O_cache_ud_t *)_udata; /* User data for callback */
+ uint32_t stored_chksum; /* Stored metadata checksum value */
+ uint32_t computed_chksum; /* Computed metadata checksum value */
+ htri_t ret_value = TRUE; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC_NOERR
/* Check arguments */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
+ HDassert(image);
HDassert(udata);
- HDassert(udata->common.f);
- HDassert(udata->common.cont_msg_info);
- /* Make certain we don't speculatively read off the end of the file */
- if(HADDR_UNDEF == (eoa = H5F_get_eoa(f, H5FD_MEM_OHDR)))
- HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, NULL, "unable to determine file size")
+ /* There is no checksum for version 1 */
+ if(udata->version != H5O_VERSION_1) {
+
+ /* Get stored and computed checksums */
+ H5F_get_checksums(image, len, &stored_chksum, &computed_chksum);
+
+ if(stored_chksum != computed_chksum)
+ ret_value = FALSE;
+ }
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O__cache_verify_chksum() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O__cache_deserialize
+ *
+ * Purpose: Attempt to deserialize the object header contained in the
+ * supplied buffer, load the data into an instance of H5O_t, and
+ * return a pointer to the new instance.
+ *
+ * Note that the object header is read with with a speculative read.
+ * If the initial read is too small, make note of this fact and return
+ * without error. H5C_load_entry() will note the size discrepency
+ * and retry the deserialize operation with the correct size read.
+ *
+ * Return: Success: Pointer to in core representation
+ * Failure: NULL
+ *
+ * Programmer: John Mainzer
+ * 7/28/14
+ *
+ *-------------------------------------------------------------------------
+ */
+static void *
+H5O__cache_deserialize(const void *_image, size_t len, void *_udata,
+ hbool_t *dirty)
+{
+ H5O_t *oh = NULL; /* Object header read in */
+ H5O_cache_ud_t *udata = (H5O_cache_ud_t *)_udata; /* User data for callback */
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into buffer to decode */
+ size_t buf_size; /* Size of prefix+chunk #0 buffer */
+ void * ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_STATIC
- /* Compute the size of the speculative object header buffer */
- H5_CHECKED_ASSIGN(spec_read_size, size_t, MIN(eoa - addr, H5O_SPEC_READ_SIZE), hsize_t);
+ /* Check arguments */
+ HDassert(image);
+ HDassert(len > 0);
+ HDassert(udata);
+ HDassert(udata->common.f);
+ HDassert(udata->common.cont_msg_info);
+ HDassert(dirty);
/* Allocate space for the object header data structure */
if(NULL == (oh = H5FL_CALLOC(H5O_t)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
-
- /* Get the # of read attempts */
- tries = max_tries = H5F_GET_READ_ATTEMPTS(f);
- do {
- fixed_tries = max_tries;
- do {
- /* Attempt to speculatively read both object header prefix and first chunk */
- if(H5F_block_read(f, H5FD_MEM_OHDR, addr, spec_read_size, dxpl_id, read_buf) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_READERROR, NULL, "unable to read object header")
-
- /* Decode header prefix */
- if(H5O_decode_prefix(f, oh, read_buf, udata) >= 0)
- break;
- } while (--fixed_tries);
-
- if(fixed_tries == 0)
- /* After all tries (for SWMR access) or after 1 try (for non-SWMR) */
- HGOTO_ERROR(H5E_OHDR, H5E_READERROR, NULL, "bad object header prefix after all tries")
-
- /* Compute the size of the buffer required */
- buf_size = oh->chunk0_size + (size_t)H5O_SIZEOF_HDR(oh);
-
- /* Check if the speculative read was large enough to parse the first chunk */
- if(spec_read_size < buf_size) {
- /* Allocate space for a buffer that's large enough for serialized header */
- if(NULL == (buf = (uint8_t *)H5MM_malloc(buf_size)))
- HGOTO_ERROR(H5E_OHDR, H5E_CANTALLOC, NULL, "can't get actual buffer")
-
- /* SWMR access */
- if(H5F_INTENT(f) & (H5F_ACC_SWMR_READ | H5F_ACC_SWMR_WRITE)) {
- /* Read the chunk that is bigger than the speculative read size */
- if(H5F_block_read(f, H5FD_MEM_OHDR, addr, buf_size, dxpl_id, buf) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_READERROR, NULL, "unable to read object header")
-
- /* See if the data read now is the same as what is read initially */
- if(HDmemcmp(buf, read_buf, spec_read_size)) {
- HDmemset(oh, 0, sizeof(*oh));
-
- /* Decode the prefix again */
- if(H5O_decode_prefix(f, oh, buf, udata) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "can't decode object header prefix")
- } /* end if */
- } /* end if */
- else {
- /* Copy existing raw data into new buffer */
- HDmemcpy(buf, read_buf, spec_read_size);
-
- /* Read rest of the raw data */
- if(H5F_block_read(f, H5FD_MEM_OHDR, (addr + spec_read_size), (buf_size - spec_read_size), dxpl_id, (buf + spec_read_size)) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_READERROR, NULL, "unable to read object header data")
- } /* end else */
- } else
- buf = read_buf;
-
- /* There is no checksum for version 1 */
- if(oh->version == H5O_VERSION_1)
- break;
-
- /* For version 2: retrieve the stored checksum and compute the checksum */
- H5F_get_checksums(buf, buf_size, &stored_chksum, &computed_chksum);
-
- /* Verify checksums */
- if(stored_chksum == computed_chksum)
- break;
- } while (--tries);
-
- if(tries == 0)
- HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "incorrect metadata checksum for object header chunk after all read tries (%u) for %u bytes", max_tries, buf_size)
-
- /* Calculate and track the # of retries */
- retries = max_tries - tries;
- if(retries) /* Does not track 0 retry */
- if(H5F_track_metadata_read_retries(f, H5AC_OHDR_ID, retries) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "cannot track read retries = %u ", retries)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
/* File-specific, non-stored information */
oh->sizeof_size = H5F_SIZEOF_SIZE(udata->common.f);
oh->sizeof_addr = H5F_SIZEOF_ADDR(udata->common.f);
+
+ /* Decode header prefix */
+ if(H5O_decode_prefix(udata->common.f, oh, image, udata) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "can't deserialize object header prefix")
+
+ /* Compute the size of the buffer used */
+ buf_size = oh->chunk0_size + (size_t)H5O_SIZEOF_HDR(oh);
+
oh->swmr_write = !!(H5F_INTENT(udata->common.f) & H5F_ACC_SWMR_WRITE);
/* Create object header proxy if doing SWMR writes */
HDassert(!oh->proxy_present);
- if(H5F_INTENT(f) & H5F_ACC_SWMR_WRITE) {
- if(H5O_proxy_create(f, dxpl_id, oh) < 0)
+ if(H5F_INTENT(udata->common.f) & H5F_ACC_SWMR_WRITE) {
+ if(H5O_proxy_create(udata->common.f, udata->common.dxpl_id, oh) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTCREATE, NULL, "can't create object header proxy")
} /* end if */
else
oh->proxy_addr = HADDR_UNDEF;
- /* Parse the first chunk */
- if(H5O__chunk_deserialize(oh, udata->common.addr, oh->chunk0_size, buf, &(udata->common), &oh->cache_info.is_dirty) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "can't deserialize first object header chunk")
+ /* Check to see if the buffer provided is large enough to contain both
+ * the prefix and the first chunk. If it isn't, make note of the desired
+ * size, but otherwise do nothing. H5C_load_entry() will notice the
+ * discrepency, load the correct size buffer, and retry the deserialize.
+ */
+ if(len >= buf_size) {
+ /* Parse the first chunk */
+ if(H5O__chunk_deserialize(oh, udata->common.addr, oh->chunk0_size, (const uint8_t *)_image, &(udata->common), dirty) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "can't deserialize first object header chunk")
+ } /* end if */
+ else
+ HDassert(!udata->made_attempt);
/* Note that we've loaded the object header from the file */
udata->made_attempt = TRUE;
@@ -448,202 +493,234 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
ret_value = oh;
done:
- /* Release resources */
- if(buf && buf != read_buf)
- H5MM_free(buf);
-
/* Release the [possibly partially initialized] object header on errors */
if(!ret_value && oh)
if(H5O_free(oh) < 0)
HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, NULL, "unable to destroy object header data")
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5O_load() */
+} /* end H5O__cache_deserialize() */
/*-------------------------------------------------------------------------
- * Function: H5O_flush
+ * Function: H5O__cache_image_len
*
- * Purpose: Flushes (and destroys) an object header.
+ * Purpose: Compute the size in bytes of the specified instance of
+ * H5O_t on disk, and return it in *image_len. On failure,
+ * the value of *image_len is undefined.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Success: SUCCEED
+ * Failure: FAIL
*
- * Programmer: Robb Matzke
- * matzke@llnl.gov
- * Aug 5 1997
+ * Programmer: John Mainzer
+ * 7/28/14
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5O_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t H5_ATTR_UNUSED addr, H5O_t *oh, unsigned H5_ATTR_UNUSED * flags_ptr)
+H5O__cache_image_len(const void *_thing, size_t *image_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ const H5O_t *oh = (const H5O_t *)_thing; /* Object header to query */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC_NOERR
/* Check arguments */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
HDassert(oh);
+ HDassert(oh->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(oh->cache_info.type == H5AC_OHDR);
+ HDassert(image_len);
+
+ /* Report the object header's prefix+first chunk length */
+ if(oh->chunk0_size)
+ *image_len = (size_t)H5O_SIZEOF_HDR(oh) + oh->chunk0_size;
+ else
+ *image_len = oh->chunk[0].size;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5O__cache_image_len() */
+
+/********************************/
+/* no H5O_cache_pre_serialize() */
+/********************************/
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O__cache_serialize
+ *
+ * Purpose: Serialize the contents of the supplied object header, and
+ * load this data into the supplied buffer.
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: John Mainzer
+ * 7/28/14
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O__cache_serialize(const H5F_t *f, void *image, size_t len, void *_thing)
+{
+ H5O_t *oh = (H5O_t *)_thing; /* Object header to encode */
+ uint8_t *chunk_image; /* Pointer to object header prefix buffer */
+ herr_t ret_value = SUCCEED; /* Return value */
- /* flush */
- if(oh->cache_info.is_dirty) {
- uint8_t *p; /* Pointer to object header prefix buffer */
+ FUNC_ENTER_STATIC
+ /* Check arguments */
+ HDassert(f);
+ HDassert(image);
+ HDassert(oh);
+ HDassert(oh->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(oh->cache_info.type == H5AC_OHDR);
+ HDassert(oh->chunk[0].size == len);
#ifdef H5O_DEBUG
-H5O_assert(oh);
+ H5O_assert(oh);
#endif /* H5O_DEBUG */
- /* Point to raw data 'image' for first chunk, which has room for the prefix */
- p = oh->chunk[0].image;
-
- /* Later versions of object header prefix have different format and
- * also require that chunk 0 always be updated, since the checksum
- * on the entire block of memory needs to be updated if anything is
- * modified */
- if(oh->version > H5O_VERSION_1) {
- uint64_t chunk0_size; /* Size of chunk 0's data */
+ /* Point to raw data 'image' for first chunk, which
+ * has room for the prefix
+ */
+ chunk_image = oh->chunk[0].image;
- HDassert(oh->chunk[0].size >= (size_t)H5O_SIZEOF_HDR(oh));
- chunk0_size = oh->chunk[0].size - (size_t)H5O_SIZEOF_HDR(oh);
+ /* Later versions of object header prefix have different format and
+ * also require that chunk 0 always be updated, since the checksum
+ * on the entire block of memory needs to be updated if anything is
+ * modified
+ */
+ if(oh->version > H5O_VERSION_1) {
+ uint64_t chunk0_size; /* Size of chunk 0's data */
- /* Verify magic number */
- HDassert(!HDmemcmp(p, H5O_HDR_MAGIC, H5_SIZEOF_MAGIC));
- p += H5_SIZEOF_MAGIC;
+ HDassert(oh->chunk[0].size >= (size_t)H5O_SIZEOF_HDR(oh));
+ chunk0_size = oh->chunk[0].size - (size_t)H5O_SIZEOF_HDR(oh);
- /* Version */
- *p++ = oh->version;
+ /* Verify magic number */
+ HDassert(!HDmemcmp(chunk_image, H5O_HDR_MAGIC, H5_SIZEOF_MAGIC));
+ chunk_image += H5_SIZEOF_MAGIC;
- /* Flags */
- *p++ = oh->flags;
+ /* Version */
+ *chunk_image++ = oh->version;
- /* Time fields */
- if(oh->flags & H5O_HDR_STORE_TIMES) {
- UINT32ENCODE(p, oh->atime);
- UINT32ENCODE(p, oh->mtime);
- UINT32ENCODE(p, oh->ctime);
- UINT32ENCODE(p, oh->btime);
- } /* end if */
+ /* Flags */
+ *chunk_image++ = oh->flags;
- /* Attribute fields */
- if(oh->flags & H5O_HDR_ATTR_STORE_PHASE_CHANGE) {
- UINT16ENCODE(p, oh->max_compact);
- UINT16ENCODE(p, oh->min_dense);
- } /* end if */
+ /* Time fields */
+ if(oh->flags & H5O_HDR_STORE_TIMES) {
+ UINT32ENCODE(chunk_image, oh->atime);
+ UINT32ENCODE(chunk_image, oh->mtime);
+ UINT32ENCODE(chunk_image, oh->ctime);
+ UINT32ENCODE(chunk_image, oh->btime);
+ } /* end if */
- /* First chunk size */
- switch(oh->flags & H5O_HDR_CHUNK0_SIZE) {
- case 0: /* 1 byte size */
- HDassert(chunk0_size < 256);
- *p++ = (uint8_t)chunk0_size;
- break;
-
- case 1: /* 2 byte size */
- HDassert(chunk0_size < 65536);
- UINT16ENCODE(p, chunk0_size);
- break;
-
- case 2: /* 4 byte size */
- /* use <= 2**32 -1 to stay within 4 bytes integer range */
- HDassert(chunk0_size <= 4294967295UL);
- UINT32ENCODE(p, chunk0_size);
- break;
-
- case 3: /* 8 byte size */
- UINT64ENCODE(p, chunk0_size);
- break;
-
- default:
- HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "bad size for chunk 0")
- } /* end switch */
+ /* Attribute fields */
+ if(oh->flags & H5O_HDR_ATTR_STORE_PHASE_CHANGE) {
+ UINT16ENCODE(chunk_image, oh->max_compact);
+ UINT16ENCODE(chunk_image, oh->min_dense);
} /* end if */
- else {
- /* Version */
- *p++ = oh->version;
- /* Reserved */
- *p++ = 0;
+ /* First chunk size */
+ switch(oh->flags & H5O_HDR_CHUNK0_SIZE) {
+ case 0: /* 1 byte size */
+ HDassert(chunk0_size < 256);
+ *chunk_image++ = (uint8_t)chunk0_size;
+ break;
+
+ case 1: /* 2 byte size */
+ HDassert(chunk0_size < 65536);
+ UINT16ENCODE(chunk_image, chunk0_size);
+ break;
+
+ case 2: /* 4 byte size */
+ /* use <= 2**32 -1 to stay within 4 bytes integer range */
+ HDassert(chunk0_size <= 4294967295UL);
+ UINT32ENCODE(chunk_image, chunk0_size);
+ break;
+
+ case 3: /* 8 byte size */
+ UINT64ENCODE(chunk_image, chunk0_size);
+ break;
+
+ default:
+ HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "bad size for chunk 0")
+ } /* end switch */
+ } /* end if */
+ else {
+ /* Version */
+ *chunk_image++ = oh->version;
+
+ /* Reserved */
+ *chunk_image++ = 0;
- /* Number of messages */
+ /* Number of messages */
#ifdef H5O_ENABLE_BAD_MESG_COUNT
- if(oh->store_bad_mesg_count)
- UINT16ENCODE(p, (oh->nmesgs - 1))
- else
+ if(oh->store_bad_mesg_count)
+ UINT16ENCODE(chunk_image, (oh->nmesgs - 1))
+ else
#endif /* H5O_ENABLE_BAD_MESG_COUNT */
- UINT16ENCODE(p, oh->nmesgs);
+ UINT16ENCODE(chunk_image, oh->nmesgs);
- /* Link count */
- UINT32ENCODE(p, oh->nlink);
+ /* Link count */
+ UINT32ENCODE(chunk_image, oh->nlink);
- /* First chunk size */
- UINT32ENCODE(p, (oh->chunk[0].size - (size_t)H5O_SIZEOF_HDR(oh)));
+ /* First chunk size */
+ UINT32ENCODE(chunk_image, (oh->chunk[0].size - (size_t)H5O_SIZEOF_HDR(oh)));
- /* Zero to alignment */
- HDmemset(p, 0, (size_t)(H5O_SIZEOF_HDR(oh) - 12));
- p += (size_t)(H5O_SIZEOF_HDR(oh) - 12);
- } /* end else */
- HDassert((size_t)(p - oh->chunk[0].image) == (size_t)(H5O_SIZEOF_HDR(oh) - H5O_SIZEOF_CHKSUM_OH(oh)));
+ /* Zero to alignment */
+ HDmemset(chunk_image, 0, (size_t)(H5O_SIZEOF_HDR(oh) - 12));
+ chunk_image += (size_t)(H5O_SIZEOF_HDR(oh) - 12);
+ } /* end else */
- /* Serialize messages for this chunk */
- if(H5O__chunk_serialize(f, oh, (unsigned)0) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTSERIALIZE, FAIL, "unable to serialize first object header chunk")
+ HDassert((size_t)(chunk_image - oh->chunk[0].image) == (size_t)(H5O_SIZEOF_HDR(oh) - H5O_SIZEOF_CHKSUM_OH(oh)));
- /* Write the chunk out */
- HDassert(H5F_addr_defined(oh->chunk[0].addr));
- if(H5F_block_write(f, H5FD_MEM_OHDR, oh->chunk[0].addr, oh->chunk[0].size, dxpl_id, oh->chunk[0].image) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to write object header chunk to disk")
+ /* Serialize messages for this chunk */
+ if(H5O__chunk_serialize(f, oh, (unsigned)0) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTSERIALIZE, FAIL, "unable to serialize first object header chunk")
- /* Mark object header as clean now */
- oh->cache_info.is_dirty = FALSE;
- } /* end if */
-
- /* Destroy the object header, if requested */
- if(destroy)
- if(H5O_dest(f, oh) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to destroy object header data")
+ /* copy the chunk into the image -- this is potentially expensive.
+ * Can we rework things so that the object header and the cache
+ * share a buffer?
+ */
+ HDmemcpy(image, oh->chunk[0].image, len);
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5O_flush() */
+} /* end H5O__cache_serialize() */
+
+/**********************************/
+/* no H5O_cache_notify() function */
+/**********************************/
/*-------------------------------------------------------------------------
- * Function: H5O_dest
+ * Function: H5O__cache_free_icr
*
- * Purpose: Destroys an object header.
+ * Purpose: Free the in core representation of the supplied object header.
*
- * Return: Non-negative on success/Negative on failure
+ * Note: The metadata cache sets the object's cache_info.magic to
+ * H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC before calling a free_icr
+ * callback (checked in assert).
*
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Jan 15 2003
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: John Mainzer
+ * 7/28/14
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5O_dest(H5F_t *f, H5O_t *oh)
-{
- herr_t ret_value = SUCCEED; /* Return value */
+H5O__cache_free_icr(void *_thing)
+{
+ H5O_t *oh = (H5O_t *)_thing; /* Object header to destroy */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
/* Check arguments */
HDassert(oh);
- HDassert(oh->rc == 0);
-
- /* Verify that node is clean */
- HDassert(!oh->cache_info.is_dirty);
-
- /* If we're going to free the space on disk, the address must be valid */
- HDassert(!oh->cache_info.free_file_space_on_destroy || H5F_addr_defined(oh->cache_info.addr));
-
- /* Check for releasing file space for object header */
- if(oh->chunk && oh->cache_info.free_file_space_on_destroy) {
- /* Free main (first) object header "chunk" */
- /* (XXX: Nasty usage of internal DXPL value! -QAK) */
- if(H5MF_xfree(f, H5FD_MEM_OHDR, H5AC_dxpl_id, oh->chunk[0].addr, (hsize_t)oh->chunk[0].size) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to free object header")
- } /* end if */
+ HDassert(oh->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC);
+ HDassert(oh->cache_info.type == H5AC_OHDR);
/* Destroy object header */
if(H5O_free(oh) < 0)
@@ -651,178 +728,191 @@ H5O_dest(H5F_t *f, H5O_t *oh)
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5O_dest() */
+} /* end H5O__cache_free_icr() */
/*-------------------------------------------------------------------------
- * Function: H5O_clear
+ * Function: H5O__cache_clear
*
- * Purpose: Mark a object header in memory as non-dirty.
+ * Purpose: Clear all dirty bits associated with this cache entry.
*
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Mar 20 2003
+ * This is ncessary as the object header cache client maintains
+ * its own dirty bits on individual messages. These dirty bits
+ * used to be cleared by the old V2 metadata cache flush callback,
+ * but now the metadata cache must clear them explicitly, as
+ * the serialize callback does not imply that the data has been
+ * written to disk.
*
- * Changes: In the parallel case, there is the possibility that the
- * the object header may be flushed by different processes
- * over the life of the computation. Thus we must ensure
- * that the chunk images are up to date before we mark the
- * messages clean -- as otherwise we may overwrite valid
- * data with a blank section of a chunk image.
+ * This callback is also necessary for the parallel case.
*
- * To deal with this, I have added code to call
- * H5O_chunk_serialize() for all chunks before we
- * mark all messages as clean if we are not destroying the
- * object. Do this in the parallel case only, as the problem
- * can only occur in this context.
+ * Return: Success: SUCCEED
+ * Failure: FAIL
*
- * JRM -- 10/12/10
+ * Programmer: John Mainzer
+ * 9/22/14
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5O_clear(H5F_t *f, H5O_t *oh, hbool_t destroy)
-{
- unsigned u; /* Local index variable */
- herr_t ret_value = SUCCEED;
+H5O__cache_clear(const H5F_t *f, void *_thing, hbool_t about_to_destroy)
+{
+ H5O_t *oh = (H5O_t *)_thing; /* Object header to reset */
+ unsigned u; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
/* Check arguments */
HDassert(oh);
+ HDassert(oh->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(oh->cache_info.type == H5AC_OHDR);
#ifdef H5_HAVE_PARALLEL
- if ( ( oh->cache_info.is_dirty ) && ( ! destroy ) ) {
-
- size_t i;
-
- /* scan through all chunks associated with the object header,
- * and cause them to update their images for all entries currently
- * marked dirty. Must do this in the parallel case, as it is possible
- * that this processor may clear this object header several times
- * before flushing it -- thus causing undefined sections of the image
- * to be written to disk overwriting valid data.
+ if((oh->nchunks > 0) && (!about_to_destroy)) {
+ /* Scan through chunk 0 (the chunk stored contiguously with this
+ * object header) and cause it to update its image of all entries
+ * currently marked dirty. Must do this in the parallel case, as
+ * it is possible that this processor may clear this object header
+ * several times before flushing it -- thus causing undefined
+ * sections of the image to be written to disk overwriting valid data.
*/
-
- for ( i = 0; i < oh->nchunks; i++ ) {
-
- if(H5O__chunk_serialize(f, oh, i) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTSERIALIZE, FAIL, "unable to serialize object header chunk")
- }
- }
+ if(H5O__chunk_serialize(f, oh, 0) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTSERIALIZE, FAIL, "unable to serialize object header chunk")
+ } /* end if */
#endif /* H5_HAVE_PARALLEL */
/* Mark messages stored with the object header (i.e. messages in chunk 0) as clean */
for(u = 0; u < oh->nmesgs; u++)
- oh->mesg[u].dirty = FALSE;
+ if(oh->mesg[u].chunkno == 0)
+ oh->mesg[u].dirty = FALSE;
#ifndef NDEBUG
/* Reset the number of messages dirtied by decoding */
oh->ndecode_dirtied = 0;
#endif /* NDEBUG */
- /* Mark whole header as clean */
- oh->cache_info.is_dirty = FALSE;
-
- if(destroy)
- if(H5O_dest(f, oh) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to destroy object header data")
-
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5O_clear() */
+} /* end H5O__cache_clear() */
/*-------------------------------------------------------------------------
- * Function: H5O_size
+ * Function: H5O__cache_chk_get_load_size()
*
- * Purpose: Compute the size in bytes of the specified instance of
- * H5O_t on disk, and return it in *len_ptr. On failure,
- * the value of *len_ptr is undefined.
+ * Purpose: Tell the metadata cache how large the on disk image of the
+ * chunk proxy is, so it can load the image into a buffer for the
+ * deserialize call. In this case, we simply look up the size in
+ * the user data, and return it in *image_len,
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Success: SUCCEED
+ * Failure: FAIL
*
- * Programmer: John Mainzer
- * 5/13/04
+ * Programmer: John Mainzer
+ * 7/28/14
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5O_size(const H5F_t H5_ATTR_UNUSED *f, const H5O_t *oh, size_t *size_ptr)
+H5O__cache_chk_get_load_size(const void *_image, void *_udata,
+ size_t *image_len, size_t *actual_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr)
{
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ const H5O_chk_cache_ud_t *udata = (const H5O_chk_cache_ud_t *)_udata; /* User data for callback */
- /* check args */
- HDassert(oh);
- HDassert(size_ptr);
+ FUNC_ENTER_STATIC_NOERR
- /* Report the object header's prefix+first chunk length */
- if(oh->chunk0_size)
- *size_ptr = (size_t)H5O_SIZEOF_HDR(oh) + oh->chunk0_size;
- else
- *size_ptr = oh->chunk[0].size;
+ /* Check arguments */
+ HDassert(udata);
+ HDassert(udata->oh);
+ HDassert(image_len);
+
+ if(image == NULL)
+ *image_len = udata->size;
+ else {
+ HDassert(actual_len);
+ HDassert(*actual_len == *image_len);
+ }
FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5O_size() */
+} /* end H5O__cache_chk_get_load_size() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5B2__cache_chk_verify_chksum
+ *
+ * Purpose: Verify the computed checksum of the data structure is the
+ * same as the stored chksum.
+ *
+ * Return: Success: TRUE/FALSE
+ * Failure: Negative
+ *
+ * Programmer: Vailin Choi; Aug 2015
+ *
+ *-------------------------------------------------------------------------
+ */
+static htri_t
+H5O__cache_chk_verify_chksum(const void *_image, size_t len, void *_udata)
+{
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ H5O_chk_cache_ud_t *udata = (H5O_chk_cache_ud_t *)_udata; /* User data for callback */
+ uint32_t stored_chksum; /* Stored metadata checksum value */
+ uint32_t computed_chksum; /* Computed metadata checksum value */
+ htri_t ret_value = TRUE; /* Return value */
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Check arguments */
+ HDassert(image);
+
+ /* There is no checksum for version 1 */
+ if(udata->oh->version != H5O_VERSION_1) {
+
+ /* Get stored and computed checksums */
+ H5F_get_checksums(image, len, &stored_chksum, &computed_chksum);
+
+ if(stored_chksum != computed_chksum)
+ ret_value = FALSE;
+ }
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O__cache_chk_verify_chksum() */
/*-------------------------------------------------------------------------
- * Function: H5O_cache_chk_load
+ * Function: H5O__cache_chk_deserialize
*
- * Purpose: Loads an object header continuation chunk from disk.
+ * Purpose: Attempt to deserialize the object header continuation chunk
+ * contained in the supplied buffer, load the data into an instance
+ * of H5O_chunk_proxy_t, and return a pointer to the new instance.
*
- * Return: Success: Pointer to the new object header chunk proxy.
- * Failure: NULL
+ * Return: Success: Pointer to in core representation
+ * Failure: NULL
*
- * Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * Jul 12 2008
+ * Programmer: John Mainzer
+ * 7/28/14
*
*-------------------------------------------------------------------------
*/
-static H5O_chunk_proxy_t *
-H5O_cache_chk_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
+static void *
+H5O__cache_chk_deserialize(const void *image, size_t len, void *_udata,
+ hbool_t *dirty)
{
- H5O_chunk_proxy_t *chk_proxy = NULL; /* Chunk proxy object */
- H5O_chk_cache_ud_t *udata = (H5O_chk_cache_ud_t *)_udata; /* User data for callback */
- H5WB_t *wb = NULL; /* Wrapped buffer for prefix data */
- uint8_t chunk_buf[H5O_EST_CHUNK_SIZE]; /* Buffer for estimated chunk size */
- uint8_t *buf; /* Buffer to decode */
- H5O_chunk_proxy_t *ret_value; /* Return value */
+ H5O_chunk_proxy_t *chk_proxy = NULL; /* Chunk proxy object */
+ H5O_chk_cache_ud_t *udata = (H5O_chk_cache_ud_t *)_udata; /* User data for callback */
+ void * ret_value; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
/* Check arguments */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
+ HDassert(image);
+ HDassert(len > 0);
HDassert(udata);
HDassert(udata->oh);
+ HDassert(dirty);
/* Allocate space for the object header data structure */
- if(NULL == (chk_proxy = H5FL_CALLOC(H5O_chunk_proxy_t)))
- HGOTO_ERROR(H5E_OHDR, H5E_CANTALLOC, NULL, "memory allocation failed")
-
- /* Wrap the local buffer for serialized header info */
- if(NULL == (wb = H5WB_wrap(chunk_buf, sizeof(chunk_buf))))
- HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "can't wrap buffer")
-
- /* Get a pointer to a buffer that's large enough for serialized header */
- if(NULL == (buf = (uint8_t *)H5WB_actual(wb, udata->size)))
- HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, NULL, "can't get actual buffer")
-
- /* Read rest of the raw data */
- if(udata->oh->version == H5O_VERSION_2 && udata->decoding) {
- /* Read and validate object header continuation chunk */
- if(H5F_read_check_metadata(f, dxpl_id, H5FD_MEM_OHDR, H5AC_OHDR_CHK_ID, addr, udata->size, udata->size, buf) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "incorrect metadata checksum for object header continuation chunk")
- } /* end if */
- else {
- /* Read the header object continuation chunk */
- if(H5F_block_read(f, H5FD_MEM_OHDR, addr, udata->size, dxpl_id, buf) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_READERROR, NULL, "unable to read object header continuation chunk")
- } /* end else */
+ if(NULL == (chk_proxy = H5FL_CALLOC(H5O_chunk_proxy_t)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTALLOC, NULL, "memory allocation failed")
/* Check if we are still decoding the object header */
/* (as opposed to bringing a piece of it back from the file) */
@@ -832,7 +922,7 @@ H5O_cache_chk_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
HDassert(udata->common.cont_msg_info);
/* Parse the chunk */
- if(H5O__chunk_deserialize(udata->oh, udata->common.addr, udata->size, buf, &(udata->common), &chk_proxy->cache_info.is_dirty) < 0)
+ if(H5O__chunk_deserialize(udata->oh, udata->common.addr, udata->size, (const uint8_t *)image, &(udata->common), dirty) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "can't deserialize object header chunk")
/* Set the fields for the chunk proxy */
@@ -850,7 +940,7 @@ H5O_cache_chk_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
/* Sanity check that the chunk representation we have in memory is
* the same as the one being brought in from disk.
*/
- HDassert(0 == HDmemcmp(buf, chk_proxy->oh->chunk[chk_proxy->chunkno].image, chk_proxy->oh->chunk[chk_proxy->chunkno].size));
+ HDassert(0 == HDmemcmp(image, chk_proxy->oh->chunk[chk_proxy->chunkno].image, chk_proxy->oh->chunk[chk_proxy->chunkno].size));
} /* end else */
/* Increment reference count of object header */
@@ -861,186 +951,98 @@ H5O_cache_chk_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
ret_value = chk_proxy;
done:
- /* Release resources */
- if(wb && H5WB_unwrap(wb) < 0)
- HDONE_ERROR(H5E_OHDR, H5E_CLOSEERROR, NULL, "can't close wrapped buffer")
-
- /* Release the [possibly partially initialized] object header on errors */
- if(!ret_value && chk_proxy)
- if(H5O__chunk_proxy_dest(chk_proxy) < 0)
- HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, NULL, "unable to destroy object header chunk proxy")
-
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5O_cache_chk_load() */
+} /* end H5O__cache_chk_deserialize() */
/*-------------------------------------------------------------------------
- * Function: H5O_cache_chk_flush
+ * Function: H5O__cache_chk_image_len
*
- * Purpose: Flushes (and destroys) an object header continuation chunk.
+ * Purpose: Return the on disk image size of a object header chunk to the
+ * metadata cache via the image_len.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Success: SUCCEED
+ * Failure: FAIL
*
- * Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * Jul 12 2008
+ * Programmer: John Mainzer
+ * 7/28/14
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5O_cache_chk_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr,
- H5O_chunk_proxy_t *chk_proxy, unsigned H5_ATTR_UNUSED * flags_ptr)
+H5O__cache_chk_image_len(const void *_thing, size_t *image_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ const H5O_chunk_proxy_t * chk_proxy = (const H5O_chunk_proxy_t *)_thing; /* Chunk proxy to query */
- FUNC_ENTER_NOAPI_NOINIT
-
- /* flush */
- if(chk_proxy->cache_info.is_dirty) {
- /* Serialize messages for this chunk */
- if(H5O__chunk_serialize(f, chk_proxy->oh, chk_proxy->chunkno) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTSERIALIZE, FAIL, "unable to serialize object header continuation chunk")
-
- /* Write the chunk out */
- HDassert(H5F_addr_defined(chk_proxy->oh->chunk[chk_proxy->chunkno].addr));
- HDassert(H5F_addr_eq(addr, chk_proxy->oh->chunk[chk_proxy->chunkno].addr));
- if(H5F_block_write(f, H5FD_MEM_OHDR, addr, chk_proxy->oh->chunk[chk_proxy->chunkno].size, dxpl_id, chk_proxy->oh->chunk[chk_proxy->chunkno].image) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to write object header continuation chunk to disk")
-
- /* Mark object header as clean now */
- chk_proxy->cache_info.is_dirty = FALSE;
- } /* end if */
-
- /* Destroy the object header, if requested */
- if(destroy)
- if(H5O_cache_chk_dest(f, chk_proxy) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to destroy object header continuation chunk data")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5O_cache_chk_flush() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5O_cache_chk_dest
- *
- * Purpose: Destroys an object header continuation chunk.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * July 12, 2008
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5O_cache_chk_dest(H5F_t *f, H5O_chunk_proxy_t *chk_proxy)
-{
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC_NOERR
/* Check arguments */
HDassert(chk_proxy);
- HDassert(chk_proxy->chunkno > 0);
-
- /* Verify that node is clean */
- HDassert(chk_proxy->cache_info.is_dirty == FALSE);
-
- /* If we're going to free the space on disk, the address must be valid */
- HDassert(!chk_proxy->cache_info.free_file_space_on_destroy || H5F_addr_defined(chk_proxy->cache_info.addr));
+ HDassert(chk_proxy->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(chk_proxy->cache_info.type == H5AC_OHDR_CHK);
+ HDassert(chk_proxy->oh);
+ HDassert(image_len);
- /* Check for releasing file space for object header */
- if(chk_proxy->cache_info.free_file_space_on_destroy) {
- /* Release the space on disk */
- /* (XXX: Nasty usage of internal DXPL value! -QAK) */
- if(H5MF_xfree(f, H5FD_MEM_OHDR, H5AC_dxpl_id, chk_proxy->oh->chunk[chk_proxy->chunkno].addr, (hsize_t)chk_proxy->oh->chunk[chk_proxy->chunkno].size) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to free object header continuation chunk")
- } /* end if */
+ *image_len = chk_proxy->oh->chunk[chk_proxy->chunkno].size;
- /* Destroy object header chunk proxy */
- if(H5O__chunk_proxy_dest(chk_proxy) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "unable to destroy object header chunk proxy")
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5O__cache_chk_image_len() */
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5O_cache_chk_dest() */
+/************************************/
+/* no H5O_cache_chk_pre_serialize() */
+/************************************/
/*-------------------------------------------------------------------------
- * Function: H5O_cache_chk_clear
- *
- * Purpose: Mark a object header continuation chunk in memory as non-dirty.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * July 12, 2008
- *
- * Changes: In the parallel case, there is the possibility that the
- * the object header chunk may be flushed by different
- * processes over the life of the computation. Thus we must
- * ensure that the chunk image is up to date before we mark its
- * messages clean -- as otherwise we may overwrite valid
- * data with a blank section of a chunk image.
+ * Function: H5O__cache_chk_serialize
*
- * To deal with this, I have added code to call
- * H5O_chunk_serialize() for this chunk before we
- * mark all messages as clean if we are not destroying the
- * chunk.
+ * Purpose: Given a pointer to an instance of an object header chunk and an
+ * appropriately sized buffer, serialize the contents of the
+ * instance for writing to disk, and copy the serialized data
+ * into the buffer.
*
- * Do this in the parallel case only, as the problem
- * can only occur in this context.
+ * Return: Success: SUCCEED
+ * Failure: FAIL
*
- * Note that at present at least, it seems that this fix
- * is not necessary, as we don't seem to be able to
- * generate a dirty chunk without creating a dirty object
- * header. However, the object header code will be changing
- * a lot in the near future, so I'll leave this fix in
- * for now, unless Quincey requests otherwise.
- *
- * JRM -- 10/12/10
+ * Programmer: John Mainzer
+ * 7/28/14
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5O_cache_chk_clear(H5F_t *f, H5O_chunk_proxy_t *chk_proxy, hbool_t destroy)
+H5O__cache_chk_serialize(const H5F_t *f, void *image, size_t len, void *_thing)
{
- unsigned u; /* Local index variable */
- herr_t ret_value = SUCCEED;
+ H5O_chunk_proxy_t * chk_proxy = (H5O_chunk_proxy_t *)_thing; /* Object header chunk to serialize */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
/* Check arguments */
+ HDassert(f);
+ HDassert(image);
HDassert(chk_proxy);
+ HDassert(chk_proxy->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(chk_proxy->cache_info.type == H5AC_OHDR_CHK);
+ HDassert(chk_proxy->oh);
+ HDassert(chk_proxy->oh->chunk[chk_proxy->chunkno].size == len);
-#ifdef H5_HAVE_PARALLEL
- if((chk_proxy->oh->cache_info.is_dirty) && (!destroy))
- if(H5O__chunk_serialize(f, chk_proxy->oh, chk_proxy->chunkno) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTSERIALIZE, FAIL, "unable to serialize object header chunk")
-#endif /* H5_HAVE_PARALLEL */
-
- /* Mark messages in chunk as clean */
- for(u = 0; u < chk_proxy->oh->nmesgs; u++)
- if(chk_proxy->oh->mesg[u].chunkno == chk_proxy->chunkno)
- chk_proxy->oh->mesg[u].dirty = FALSE;
-
- /* Mark as clean */
- chk_proxy->cache_info.is_dirty = FALSE;
+ /* Serialize messages for this chunk */
+ if(H5O__chunk_serialize(f, chk_proxy->oh, chk_proxy->chunkno) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTSERIALIZE, FAIL, "unable to serialize object header continuation chunk")
- if(destroy)
- if(H5O_cache_chk_dest(f, chk_proxy) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to destroy object header continuation chunk data")
+ /* copy the chunk into the image -- this is potentially expensive.
+ * Can we rework things so that the chunk and the cache share a buffer?
+ */
+ HDmemcpy(image, chk_proxy->oh->chunk[chk_proxy->chunkno].image, len);
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5O_cache_chk_clear() */
+} /* end H5O__cache_chk_serialize() */
/*-------------------------------------------------------------------------
- * Function: H5O_cache_chk_notify
+ * Function: H5O__cache_chk_notify
*
* Purpose: Handle cache action notifications
*
@@ -1052,8 +1054,9 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5O_cache_chk_notify(H5AC_notify_action_t action, H5O_chunk_proxy_t *chk_proxy)
+H5O__cache_chk_notify(H5AC_notify_action_t action, void *_thing)
{
+ H5O_chunk_proxy_t *chk_proxy = (H5O_chunk_proxy_t *)_thing;
void *parent = NULL; /* Chunk containing continuation message that points to this chunk */
H5O_chunk_proxy_t *cont_chk_proxy = NULL; /* Proxy for chunk containing continuation message that points to this chunk, if not chunk 0 */
herr_t ret_value = SUCCEED; /* Return value */
@@ -1069,6 +1072,7 @@ H5O_cache_chk_notify(H5AC_notify_action_t action, H5O_chunk_proxy_t *chk_proxy)
if(chk_proxy->oh->swmr_write) {
switch(action) {
case H5AC_NOTIFY_ACTION_AFTER_INSERT:
+ case H5AC_NOTIFY_ACTION_AFTER_LOAD:
/* Add flush dependency from chunk containing the continuation message
* that points to this chunk (either oh or another chunk proxy object)
*/
@@ -1088,8 +1092,12 @@ H5O_cache_chk_notify(H5AC_notify_action_t action, H5O_chunk_proxy_t *chk_proxy)
if(H5O_proxy_depend(chk_proxy->f, H5AC_ind_dxpl_id, chk_proxy->oh, chk_proxy) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTDEPEND, FAIL, "can't create flush dependency on object header proxy")
+ case H5AC_NOTIFY_ACTION_AFTER_FLUSH:
+ /* do nothing */
+ break;
+
case H5AC_NOTIFY_ACTION_BEFORE_EVICT:
- /* Nothing to do */
+ /* Nothing to do */
break;
default:
@@ -1107,38 +1115,105 @@ done:
HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to unprotect object header chunk")
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5O_cache_chk_notify() */
+} /* end H5O__cache_chk_notify() */
/*-------------------------------------------------------------------------
- * Function: H5O_cache_chk_size
+ * Function: H5O__cache_chk_free_icr
*
- * Purpose: Compute the size in bytes of the specified instance of
- * an object header continuation chunk on disk, and return it in
- * *len_ptr. On failure, the value of *len_ptr is undefined.
+ * Purpose: Free the in core memory associated with the supplied object
+ * header continuation chunk.
*
- * Return: Non-negative on success/Negative on failure
+ * Note: The metadata cache sets the object's cache_info.magic to
+ * H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC before calling a free_icr
+ * callback (checked in assert).
*
- * Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * July 12, 2008
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: John Mainzer
+ * 7/28/14
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5O_cache_chk_size(const H5F_t H5_ATTR_UNUSED *f, const H5O_chunk_proxy_t *chk_proxy, size_t *size_ptr)
+H5O__cache_chk_free_icr(void *_thing)
{
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ H5O_chunk_proxy_t * chk_proxy = (H5O_chunk_proxy_t *)_thing; /* Object header chunk proxy to release */
+ herr_t ret_value = SUCCEED; /* Return value */
- /* check args */
+ FUNC_ENTER_STATIC
+
+ /* Check arguments */
HDassert(chk_proxy);
- HDassert(size_ptr);
+ HDassert(chk_proxy->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC);
+ HDassert(chk_proxy->cache_info.type == H5AC_OHDR_CHK);
- /* Report the object header continuation chunk's length */
- *size_ptr = chk_proxy->oh->chunk[chk_proxy->chunkno].size;
+ /* Destroy object header chunk proxy */
+ if(H5O__chunk_proxy_dest(chk_proxy) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "unable to destroy object header chunk proxy")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O__cache_chk_free_icr() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O__cache_chk_clear
+ *
+ * Purpose: Clear all dirty bits associated with this cache entry.
+ *
+ * This is ncessary as the object header cache client maintains
+ * its own dirty bits on individual messages. These dirty bits
+ * used to be cleared by the old V2 metadata cache flush callback,
+ * but now the metadata cache must clear them explicitly, as
+ * the serialize callback does not imply that the data has been
+ * written to disk.
+ *
+ * This callback is also necessary for the parallel case.
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: John Mainzer
+ * 9/22/14
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O__cache_chk_clear(const H5F_t *f, void *_thing, hbool_t about_to_destroy)
+{
+ H5O_chunk_proxy_t *chk_proxy = (H5O_chunk_proxy_t *)_thing; /* Object header chunk to reset */
+ H5O_t *oh; /* Object header for chunk */
+ unsigned u; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check arguments */
+ HDassert(chk_proxy);
+ HDassert(chk_proxy->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(chk_proxy->cache_info.type == H5AC_OHDR_CHK);
+ oh = chk_proxy->oh;
+ HDassert(oh);
+ HDassert(oh->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(oh->cache_info.type == H5AC_OHDR);
+
+#ifdef H5_HAVE_PARALLEL
+ if((chk_proxy->oh->cache_info.is_dirty) && (!about_to_destroy))
+ if(H5O__chunk_serialize(f, chk_proxy->oh, chk_proxy->chunkno) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTSERIALIZE, FAIL, "unable to serialize object header chunk")
+#endif /* H5_HAVE_PARALLEL */
+
+ /* Mark messages in chunk as clean */
+ for(u = 0; u < chk_proxy->oh->nmesgs; u++)
+ if(chk_proxy->oh->mesg[u].chunkno == chk_proxy->chunkno)
+ chk_proxy->oh->mesg[u].dirty = FALSE;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O__cache_chk_clear() */
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5O_cache_chk_size() */
/*-------------------------------------------------------------------------
@@ -1208,7 +1283,7 @@ static herr_t
H5O__chunk_deserialize(H5O_t *oh, haddr_t addr, size_t len, const uint8_t *image,
H5O_common_cache_ud_t *udata, hbool_t *dirty)
{
- const uint8_t *p; /* Pointer into buffer to decode */
+ const uint8_t *chunk_image; /* Pointer into buffer to decode */
uint8_t *eom_ptr; /* Pointer to end of messages for a chunk */
size_t curmesg; /* Current message being decoded in object header */
unsigned merged_null_msgs = 0; /* Number of null messages merged together */
@@ -1257,18 +1332,18 @@ H5O__chunk_deserialize(H5O_t *oh, haddr_t addr, size_t len, const uint8_t *image
HDmemcpy(oh->chunk[chunkno].image, image, oh->chunk[chunkno].size);
/* Point into chunk image to decode */
- p = oh->chunk[chunkno].image;
+ chunk_image = oh->chunk[chunkno].image;
/* Handle chunk 0 as special case */
if(chunkno == 0)
/* Skip over [already decoded] prefix */
- p += (size_t)(H5O_SIZEOF_HDR(oh) - H5O_SIZEOF_CHKSUM_OH(oh));
+ chunk_image += (size_t)(H5O_SIZEOF_HDR(oh) - H5O_SIZEOF_CHKSUM_OH(oh));
/* Check for magic # on chunks > 0 in later versions of the format */
else if(chunkno > 0 && oh->version > H5O_VERSION_1) {
/* Magic number */
- if(HDmemcmp(p, H5O_CHK_MAGIC, (size_t)H5_SIZEOF_MAGIC))
+ if(HDmemcmp(chunk_image, H5O_CHK_MAGIC, (size_t)H5_SIZEOF_MAGIC))
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "wrong object header chunk signature")
- p += H5_SIZEOF_MAGIC;
+ chunk_image += H5_SIZEOF_MAGIC;
} /* end if */
/* Save # of messages already inspected */
@@ -1279,7 +1354,7 @@ H5O__chunk_deserialize(H5O_t *oh, haddr_t addr, size_t len, const uint8_t *image
#ifndef NDEBUG
nullcnt = 0;
#endif /* NDEBUG */
- while(p < eom_ptr) {
+ while(chunk_image < eom_ptr) {
size_t mesgno; /* Current message to operate on */
size_t mesg_size; /* Size of message read in */
unsigned id; /* ID (type) of current message */
@@ -1290,20 +1365,20 @@ H5O__chunk_deserialize(H5O_t *oh, haddr_t addr, size_t len, const uint8_t *image
/* Version # */
if(oh->version == H5O_VERSION_1)
- UINT16DECODE(p, id)
+ UINT16DECODE(chunk_image, id)
else
- id = *p++;
+ id = *chunk_image++;
/* Check for unknown message ID getting encoded in file */
if(id == H5O_UNKNOWN_ID)
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "'unknown' message ID encoded in file?!?")
/* Message size */
- UINT16DECODE(p, mesg_size);
+ UINT16DECODE(chunk_image, mesg_size);
HDassert(mesg_size == H5O_ALIGN_OH(oh, mesg_size));
/* Message flags */
- flags = *p++;
+ flags = *chunk_image++;
if(flags & ~H5O_MSG_FLAG_BITS)
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unknown flag for message")
if((flags & H5O_MSG_FLAG_SHARED) && (flags & H5O_MSG_FLAG_DONTSHARE))
@@ -1315,17 +1390,17 @@ H5O__chunk_deserialize(H5O_t *oh, haddr_t addr, size_t len, const uint8_t *image
/* Reserved bytes/creation index */
if(oh->version == H5O_VERSION_1)
- p += 3; /*reserved*/
+ chunk_image += 3; /*reserved*/
else {
/* Only decode creation index if they are being tracked */
if(oh->flags & H5O_HDR_ATTR_CRT_ORDER_TRACKED)
- UINT16DECODE(p, crt_idx);
+ UINT16DECODE(chunk_image, crt_idx);
} /* end else */
/* Try to detect invalidly formatted object header message that
* extends past end of chunk.
*/
- if(p + mesg_size > eom_ptr)
+ if(chunk_image + mesg_size > eom_ptr)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "corrupt object header")
#ifndef NDEBUG
@@ -1361,7 +1436,7 @@ H5O__chunk_deserialize(H5O_t *oh, haddr_t addr, size_t len, const uint8_t *image
oh->mesg[mesgno].flags = flags;
oh->mesg[mesgno].crt_idx = crt_idx;
oh->mesg[mesgno].native = NULL;
- oh->mesg[mesgno].raw = (uint8_t *)p; /* Casting away const OK - QAK */
+ oh->mesg[mesgno].raw = (uint8_t *)chunk_image; /* Casting away const OK - QAK */
oh->mesg[mesgno].raw_size = mesg_size;
oh->mesg[mesgno].chunkno = chunkno;
@@ -1417,10 +1492,10 @@ H5O__chunk_deserialize(H5O_t *oh, haddr_t addr, size_t len, const uint8_t *image
} /* end else */
/* Advance decode pointer past message */
- p += mesg_size;
+ chunk_image += mesg_size;
/* Check for 'gap' at end of chunk */
- if((eom_ptr - p) > 0 && (eom_ptr - p) < H5O_SIZEOF_MSGHDR_OH(oh)) {
+ if((eom_ptr - chunk_image) > 0 && (eom_ptr - chunk_image) < H5O_SIZEOF_MSGHDR_OH(oh)) {
/* Gaps can only occur in later versions of the format */
HDassert(oh->version > H5O_VERSION_1);
@@ -1428,31 +1503,26 @@ H5O__chunk_deserialize(H5O_t *oh, haddr_t addr, size_t len, const uint8_t *image
HDassert(nullcnt == 0);
/* Set gap information for chunk */
- oh->chunk[chunkno].gap = (size_t)(eom_ptr - p);
+ oh->chunk[chunkno].gap = (size_t)(eom_ptr - chunk_image);
/* Increment location in chunk */
- p += oh->chunk[chunkno].gap;
+ chunk_image += oh->chunk[chunkno].gap;
} /* end if */
} /* end while */
/* Check for correct checksum on chunks, in later versions of the format */
if(oh->version > H5O_VERSION_1) {
uint32_t stored_chksum; /* Checksum from file */
- uint32_t computed_chksum; /* Checksum computed in memory */
- /* Metadata checksum */
- UINT32DECODE(p, stored_chksum);
+ /* checksum verification already done in verify_chksum cb */
- /* Compute checksum on chunk */
- computed_chksum = H5_checksum_metadata(oh->chunk[chunkno].image, (oh->chunk[chunkno].size - H5O_SIZEOF_CHKSUM), 0);
+ /* Metadata checksum */
+ UINT32DECODE(chunk_image, stored_chksum);
- /* Verify checksum */
- if(stored_chksum != computed_chksum)
- HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "incorrect metadata checksum for object header chunk")
} /* end if */
/* Sanity check */
- HDassert(p == oh->chunk[chunkno].image + oh->chunk[chunkno].size);
+ HDassert(chunk_image == oh->chunk[chunkno].image + oh->chunk[chunkno].size);
/* Do some inspection/interpretation of new messages from this chunk */
/* (detect continuation messages, ref. count messages, etc.) */
@@ -1574,7 +1644,7 @@ H5O__chunk_serialize(const H5F_t *f, H5O_t *oh, unsigned chunkno)
/* Extra work, for later versions of the format */
if(oh->version > H5O_VERSION_1) {
uint32_t metadata_chksum; /* Computed metadata checksum value */
- uint8_t *p; /* Pointer into object header chunk */
+ uint8_t *chunk_image; /* Pointer into object header chunk */
/* Check for gap in chunk & zero it out */
if(oh->chunk[chunkno].gap)
@@ -1585,8 +1655,8 @@ H5O__chunk_serialize(const H5F_t *f, H5O_t *oh, unsigned chunkno)
metadata_chksum = H5_checksum_metadata(oh->chunk[chunkno].image, (oh->chunk[chunkno].size - H5O_SIZEOF_CHKSUM), 0);
/* Metadata checksum */
- p = oh->chunk[chunkno].image + (oh->chunk[chunkno].size - H5O_SIZEOF_CHKSUM);
- UINT32ENCODE(p, metadata_chksum);
+ chunk_image = oh->chunk[chunkno].image + (oh->chunk[chunkno].size - H5O_SIZEOF_CHKSUM);
+ UINT32ENCODE(chunk_image, metadata_chksum);
} /* end if */
done:
@@ -1627,5 +1697,4 @@ H5O__chunk_proxy_dest(H5O_chunk_proxy_t *chk_proxy)
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5O_chunk_proxy_dest() */
-
+} /* H5O__chunk_proxy_dest() */
diff --git a/src/H5Ochunk.c b/src/H5Ochunk.c
index 8b380b2..2d025e7 100644
--- a/src/H5Ochunk.c
+++ b/src/H5Ochunk.c
@@ -189,7 +189,7 @@ H5O_chunk_protect(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned idx)
chk_udata.size = oh->chunk[idx].size;
/* Get the chunk proxy */
- if(NULL == (chk_proxy = (H5O_chunk_proxy_t *)H5AC_protect(f, dxpl_id, H5AC_OHDR_CHK, oh->chunk[idx].addr, &chk_udata, H5AC_WRITE)))
+ if(NULL == (chk_proxy = (H5O_chunk_proxy_t *)H5AC_protect(f, dxpl_id, H5AC_OHDR_CHK, oh->chunk[idx].addr, &chk_udata, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, NULL, "unable to load object header chunk")
/* Sanity check */
@@ -342,7 +342,7 @@ H5O_chunk_update_idx(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned idx)
chk_udata.size = oh->chunk[idx].size;
/* Get the chunk proxy */
- if(NULL == (chk_proxy = (H5O_chunk_proxy_t *)H5AC_protect(f, dxpl_id, H5AC_OHDR_CHK, oh->chunk[idx].addr, &chk_udata, H5AC_WRITE)))
+ if(NULL == (chk_proxy = (H5O_chunk_proxy_t *)H5AC_protect(f, dxpl_id, H5AC_OHDR_CHK, oh->chunk[idx].addr, &chk_udata, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header chunk")
/* Update index for chunk proxy in cache */
@@ -395,7 +395,7 @@ H5O_chunk_delete(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned idx)
chk_udata.size = oh->chunk[idx].size;
/* Get the chunk proxy */
- if(NULL == (chk_proxy = (H5O_chunk_proxy_t *)H5AC_protect(f, dxpl_id, H5AC_OHDR_CHK, oh->chunk[idx].addr, &chk_udata, H5AC_WRITE)))
+ if(NULL == (chk_proxy = (H5O_chunk_proxy_t *)H5AC_protect(f, dxpl_id, H5AC_OHDR_CHK, oh->chunk[idx].addr, &chk_udata, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header chunk")
/* Sanity check */
diff --git a/src/H5Ocopy.c b/src/H5Ocopy.c
index 1c8c301..a315842 100644
--- a/src/H5Ocopy.c
+++ b/src/H5Ocopy.c
@@ -392,7 +392,7 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out*/,
}
/* Get source object header */
- if(NULL == (oh_src = H5O_protect(oloc_src, dxpl_id, H5AC_READ)))
+ if(NULL == (oh_src = H5O_protect(oloc_src, dxpl_id, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
/* Retrieve user data for particular type of object to copy */
diff --git a/src/H5Odbg.c b/src/H5Odbg.c
index 0531a90..0388cd5 100644
--- a/src/H5Odbg.c
+++ b/src/H5Odbg.c
@@ -566,7 +566,7 @@ H5O_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, int f
loc.addr = addr;
loc.holding_file = FALSE;
- if(NULL == (oh = H5O_protect(&loc, dxpl_id, H5AC_READ)))
+ if(NULL == (oh = H5O_protect(&loc, dxpl_id, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
/* debug */
diff --git a/src/H5Oefl.c b/src/H5Oefl.c
index aa2b847..7337c75 100644
--- a/src/H5Oefl.c
+++ b/src/H5Oefl.c
@@ -128,7 +128,7 @@ H5O_efl_decode(H5F_t *f, hid_t dxpl_id, H5O_t H5_ATTR_UNUSED *open_oh,
#ifndef NDEBUG
HDassert(H5F_addr_defined(mesg->heap_addr));
- if(NULL == (heap = H5HL_protect(f, dxpl_id, mesg->heap_addr, H5AC_READ)))
+ if(NULL == (heap = H5HL_protect(f, dxpl_id, mesg->heap_addr, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, NULL, "unable to read protect link value")
s = (const char *)H5HL_offset_into(heap, 0);
@@ -145,7 +145,7 @@ H5O_efl_decode(H5F_t *f, hid_t dxpl_id, H5O_t H5_ATTR_UNUSED *open_oh,
if(NULL == mesg->slot)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
- if(NULL == (heap = H5HL_protect(f, dxpl_id, mesg->heap_addr, H5AC_READ)))
+ if(NULL == (heap = H5HL_protect(f, dxpl_id, mesg->heap_addr, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, NULL, "unable to read protect link value")
for(u = 0; u < mesg->nused; u++) {
/* Name */
@@ -487,7 +487,7 @@ H5O_efl_copy_file(H5F_t H5_ATTR_UNUSED *file_src, void *mesg_src, H5F_t *file_ds
HGOTO_ERROR(H5E_EFL, H5E_CANTINIT, NULL, "can't create heap")
/* Pin the heap down in memory */
- if(NULL == (heap = H5HL_protect(file_dst, dxpl_id, efl_dst->heap_addr, H5AC_WRITE)))
+ if(NULL == (heap = H5HL_protect(file_dst, dxpl_id, efl_dst->heap_addr, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_EFL, H5E_PROTECT, NULL, "unable to protect EFL file name heap")
/* Insert "empty" name first */
diff --git a/src/H5Oflush.c b/src/H5Oflush.c
index ee2996e..b051b6a 100644
--- a/src/H5Oflush.c
+++ b/src/H5Oflush.c
@@ -159,7 +159,7 @@ H5O_oh_tag(const H5O_loc_t *oloc, hid_t dxpl_id, haddr_t *tag)
HDassert(oloc);
/* Get object header for object */
- if(NULL == (oh = H5O_protect(oloc, dxpl_id, H5AC_READ)))
+ if(NULL == (oh = H5O_protect(oloc, dxpl_id, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to protect object's object header")
/* Get object header's address (i.e. the tag value for this object) */
diff --git a/src/H5Omessage.c b/src/H5Omessage.c
index d361194..c2756ea 100644
--- a/src/H5Omessage.c
+++ b/src/H5Omessage.c
@@ -476,7 +476,7 @@ H5O_msg_read(const H5O_loc_t *loc, unsigned type_id, void *mesg,
HDassert(type_id < NELMTS(H5O_msg_class_g));
/* Get the object header */
- if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_READ)))
+ if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, NULL, "unable to protect object header")
/* Call the "real" read routine */
@@ -802,7 +802,7 @@ H5O_msg_count(const H5O_loc_t *loc, unsigned type_id, hid_t dxpl_id)
HDassert(type);
/* Load the object header */
- if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_READ)))
+ if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to protect object header")
/* Count the messages of the correct type */
@@ -884,7 +884,7 @@ H5O_msg_exists(const H5O_loc_t *loc, unsigned type_id, hid_t dxpl_id)
HDassert(type_id < NELMTS(H5O_msg_class_g));
/* Load the object header */
- if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_READ)))
+ if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to protect object header")
/* Call the "real" exists routine */
@@ -1224,7 +1224,7 @@ H5O_msg_iterate(const H5O_loc_t *loc, unsigned type_id,
HDassert(op);
/* Protect the object header to iterate over */
- if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_READ)))
+ if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to protect object header")
/* Call the "real" iterate routine */
@@ -2289,7 +2289,7 @@ H5O_msg_get_chunkno(const H5O_loc_t *loc, unsigned type_id, hid_t dxpl_id)
HDassert(type);
/* Get the object header */
- if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_READ)))
+ if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to protect object header")
/* Locate message of correct type */
@@ -2344,7 +2344,7 @@ H5O_msg_lock(const H5O_loc_t *loc, unsigned type_id, hid_t dxpl_id)
HDassert(type);
/* Get the object header */
- if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_READ)))
+ if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to protect object header")
/* Locate message of correct type */
@@ -2402,7 +2402,7 @@ H5O_msg_unlock(const H5O_loc_t *loc, unsigned type_id, hid_t dxpl_id)
HDassert(type);
/* Get the object header */
- if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_READ)))
+ if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to protect object header")
/* Locate message of correct type */
diff --git a/src/H5Opkg.h b/src/H5Opkg.h
index e6b7c03..af9c320 100644
--- a/src/H5Opkg.h
+++ b/src/H5Opkg.h
@@ -365,6 +365,9 @@ typedef struct H5O_common_cache_ud_t {
typedef struct H5O_cache_ud_t {
hbool_t made_attempt; /* Whether the deserialize routine was already attempted */
unsigned v1_pfx_nmesgs; /* Number of messages from v1 prefix header */
+ uint8_t version; /* Version number obtained in get_load_size callback.
+ * It will be used later in verify_chksum callback
+ */
H5O_common_cache_ud_t common; /* Common object header cache callback info */
} H5O_cache_ud_t;
@@ -396,6 +399,11 @@ struct H5O_proxy_t {
H5O_t *oh; /* Object header */
};
+/* Callback information for loading object header proxy */
+typedef struct H5O_proxy_cache_ud_t {
+ H5F_t *f; /* Pointer to file for object header/chunk */
+ H5O_t *oh; /* Object header for this chunk */
+} H5O_proxy_cache_ud_t;
/* H5O object header inherits cache-like properties from H5AC */
H5_DLLVAR const H5AC_class_t H5AC_OHDR[1];
diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h
index 1d79ab5..3fb1295 100644
--- a/src/H5Oprivate.h
+++ b/src/H5Oprivate.h
@@ -659,6 +659,8 @@ typedef struct H5O_btreek_t {
* (Data structure in memory)
*/
typedef struct H5O_drvinfo_t {
+/* Information for H5AC cache functions, _must_ be first field in structure */
+ H5AC_info_t cache_info;
char name[9]; /* Driver name */
size_t len; /* Length of encoded buffer */
uint8_t *buf; /* Buffer for encoded info */
@@ -754,7 +756,7 @@ H5_DLL herr_t H5O_create(H5F_t *f, hid_t dxpl_id, size_t size_hint,
H5_DLL herr_t H5O_open(H5O_loc_t *loc);
H5_DLL herr_t H5O_close(H5O_loc_t *loc);
H5_DLL int H5O_link(const H5O_loc_t *loc, int adjust, hid_t dxpl_id);
-H5_DLL H5O_t *H5O_protect(const H5O_loc_t *loc, hid_t dxpl_id, H5AC_protect_t prot);
+H5_DLL H5O_t *H5O_protect(const H5O_loc_t *loc, hid_t dxpl_id, unsigned prot_flags);
H5_DLL H5O_t *H5O_pin(const H5O_loc_t *loc, hid_t dxpl_id);
H5_DLL herr_t H5O_unpin(H5O_t *oh);
H5_DLL herr_t H5O_dec_rc_by_loc(const H5O_loc_t *loc, hid_t dxpl_id);
diff --git a/src/H5Oproxy.c b/src/H5Oproxy.c
index 9e38524..3675ba3 100644
--- a/src/H5Oproxy.c
+++ b/src/H5Oproxy.c
@@ -71,32 +71,36 @@
/********************/
/* Metadata cache (H5AC) callbacks */
-static H5O_proxy_t *H5O_cache_proxy_load(H5F_t *f, hid_t dxpl_id, haddr_t addr,
- void *udata);
-static herr_t H5O_cache_proxy_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy,
- haddr_t addr, H5O_proxy_t *proxy, unsigned *flags_ptr);
-static herr_t H5O_cache_proxy_dest(H5F_t *f, H5O_proxy_t *proxy);
-static herr_t H5O_cache_proxy_clear(H5F_t *f, H5O_proxy_t *proxy,
- hbool_t destroy);
-static herr_t H5O_cache_proxy_notify(H5AC_notify_action_t action,
- H5O_proxy_t *proxy);
-static herr_t H5O_cache_proxy_size(const H5F_t *f, const H5O_proxy_t *proxy,
- size_t *size_ptr);
+static herr_t H5O__cache_proxy_get_load_size(const void *image, const void *udata,
+ size_t *image_len, size_t *actual_len);
+static void *H5O__cache_proxy_deserialize(const void *image, size_t len, void *udata, hbool_t *dirty);
+static herr_t H5O__cache_proxy_image_len(const void *thing, size_t *image_len, hbool_t *compressed_ptr,
+ size_t *compressed_image_len_ptr);
+static herr_t H5O__cache_proxy_serialize(const H5F_t *f, void *image, size_t len, void *thing);
+static herr_t H5O__cache_proxy_notify(H5AC_notify_action_t action, void *thing);
+static herr_t H5O__cache_proxy_free_icr(void *thing);
+static herr_t H5O__cache_proxy_dest(H5O_proxy_t *proxy);
/*********************/
/* Package Variables */
/*********************/
-/* H5O proxy inherits cache-like properties from H5AC */
const H5AC_class_t H5AC_OHDR_PROXY[1] = {{
- H5AC_OHDR_PROXY_ID,
- (H5AC_load_func_t)H5O_cache_proxy_load,
- (H5AC_flush_func_t)H5O_cache_proxy_flush,
- (H5AC_dest_func_t)H5O_cache_proxy_dest,
- (H5AC_clear_func_t)H5O_cache_proxy_clear,
- (H5AC_notify_func_t)H5O_cache_proxy_notify,
- (H5AC_size_func_t)H5O_cache_proxy_size,
+ H5AC_OHDR_PROXY_ID, /* Metadata client ID */
+ "Object header proxy", /* Metadata client name (for debugging) */
+ H5FD_MEM_OHDR, /* File space memory type for client */
+ H5AC__CLASS_SKIP_READS|H5AC__CLASS_SKIP_WRITES, /* Client class behavior flags */
+ H5O__cache_proxy_get_load_size, /* 'get_load_size' callback */
+ NULL, /* 'verify_chksum' callback */
+ H5O__cache_proxy_deserialize, /* 'deserialize' callback */
+ H5O__cache_proxy_image_len, /* 'image_len' callback */
+ NULL, /* 'pre_serialize' callback */
+ H5O__cache_proxy_serialize, /* 'serialize' callback */
+ H5O__cache_proxy_notify, /* 'notify' callback */
+ H5O__cache_proxy_free_icr, /* 'free_icr' callback */
+ NULL, /* 'clear' callback */
+ NULL, /* 'fsf_size' callback */
}};
@@ -115,170 +119,166 @@ H5FL_DEFINE_STATIC(H5O_proxy_t);
/*-------------------------------------------------------------------------
- * Function: H5O_cache_proxy_load
+ * Function: H5O__cache_proxy_get_load_size
*
- * Purpose: Creates an object header proxy and creates flush
- * dependencies from all object header chunks on this proxy.
+ * Purpose: Compute the size of the data structure on disk.
*
- * Return: Success: Pointer to a new object header proxy
- * Failure: NULL
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Neil Fortner
- * Mar 15 2012
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * May 18, 2010
*
*-------------------------------------------------------------------------
*/
-static H5O_proxy_t *
-H5O_cache_proxy_load(H5F_t *f, hid_t H5_ATTR_UNUSED dxpl_id, haddr_t addr, void *udata)
+static herr_t
+H5O__cache_proxy_get_load_size(const void *_image, const void H5_ATTR_UNUSED *_udata,
+ size_t *image_len, size_t H5_ATTR_UNUSED *actual_len)
{
- H5O_t *oh = (H5O_t *)udata; /* Parent object header */
- H5O_proxy_t *proxy = NULL; /* Object header proxy */
- H5O_proxy_t *ret_value; /* Return value */
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC_NOERR
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
- HDassert(udata);
- HDassert(oh->proxy_addr == addr);
+ /* Check arguments */
+ HDassert(image_len);
- /* Create object header proxy object & initialize fields */
- if(NULL == (proxy = H5FL_CALLOC(H5O_proxy_t)))
- HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, NULL, "can't allocate object header proxy")
- proxy->f = f;
- proxy->oh = oh;
+ if(image == NULL) {
+ /* Set the image length size */
+ /* Object header proxies are represented as 1 byte in cache */
+ /* (would be 0 bytes, but cache won't allow it currently. See
+ * H5D_cache_proxy_size) */
+ *image_len = 1;
+ }
+ /* Nothing to do for non-NULL image: no need to compute actual_len */
- /* Set return value */
- ret_value = proxy;
- proxy = NULL;
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5O_cache_proxy_load() */
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5O__cache_proxy_get_load_size() */
/*-------------------------------------------------------------------------
- * Function: H5O_cache_proxy_flush
+ * Function: H5O__cache_proxy_deserialize
*
- * Purpose: Flush callback for object header proxies. Does nothing
- * except destroy the object if requested.
+ * Purpose: Creates an object header proxy and creates flush
+ * dependencies from all object header chunks on this proxy.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Success: Pointer to a new object header proxy
+ * Failure: NULL
*
* Programmer: Neil Fortner
* Mar 15 2012
*
*-------------------------------------------------------------------------
*/
-static herr_t
-H5O_cache_proxy_flush(H5F_t *f, hid_t H5_ATTR_UNUSED dxpl_id, hbool_t destroy,
- haddr_t addr, H5O_proxy_t *proxy, unsigned H5_ATTR_UNUSED *flags_ptr)
+static void *
+H5O__cache_proxy_deserialize(const void H5_ATTR_UNUSED *_image, size_t H5_ATTR_UNUSED len, void *_udata,
+ hbool_t H5_ATTR_UNUSED *dirty)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ H5O_proxy_t *proxy = NULL; /* Object header proxy */
+ H5O_proxy_cache_ud_t *udata = (H5O_proxy_cache_ud_t *)_udata; /* User data for callback */
+ H5O_proxy_t *ret_value; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
/* check arguments */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
- HDassert(proxy);
+ HDassert(udata);
- /* The dirty flag should not be set */
- HDassert(!proxy->cache_info.is_dirty);
+ /* Create object header proxy object & initialize fields */
+ if(NULL == (proxy = H5FL_MALLOC(H5O_proxy_t)))
+ HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, NULL, "can't allocate object header proxy")
+ HDmemset(&proxy->cache_info, 0, sizeof(H5AC_info_t));
- if(destroy)
- if(H5O_cache_proxy_dest(f, proxy) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to destroy object header proxy")
+ proxy->f = udata->f;
+ proxy->oh = udata->oh;
+
+ /* Set return value */
+ ret_value = proxy;
done:
+ if(!ret_value && proxy)
+ if(H5O__cache_proxy_dest(proxy) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_CANTFREE, NULL, "unable to destroy object header proxy")
+
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5O_cache_proxy_flush() */
+} /* end H5O__cache_proxy_deserialize() */
/*-------------------------------------------------------------------------
- * Function: H5O_cache_proxy_dest
+ * Function: H5B2__cache_hdr_image_len
*
- * Purpose: Destroys an object header proxy in memory.
+ * Purpose: Compute the size of the data structure on disk.
*
* Return: Non-negative on success/Negative on failure
*
- * Programmer: Neil Fortner
- * Mar 15 2012
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * May 20, 2010
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5O_cache_proxy_dest(H5F_t H5_ATTR_UNUSED *f, H5O_proxy_t *proxy)
+H5O__cache_proxy_image_len(const void H5_ATTR_UNUSED *_thing, size_t *image_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ FUNC_ENTER_STATIC_NOERR
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ /* Check arguments */
+ HDassert(image_len);
- HDassert(proxy);
- HDassert(proxy->oh);
-
- /* Free the object header proxy object */
- proxy = H5FL_FREE(H5O_proxy_t, proxy);
+ /* Set the image length size */
+ /* Object header proxies are represented as 1 byte in cache */
+ /* (would be 0 bytes, but cache won't allow it currently. See
+ * H5D_cache_proxy_size) */
+ *image_len = 1;
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5O_cache_proxy_dest() */
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5O__cache_proxy_image_len() */
/*-------------------------------------------------------------------------
- * Function: H5O_cache_proxy_clear
+ * Function: H5O__cache_proxy_serialize
*
- * Purpose: Clear callback for object header proxies. Does nothing
- * except destroy the object if requested.
+ * Purpose: A no-op
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Neil Fortner
- * Mar 15 2012
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Feb 2 2005
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5O_cache_proxy_clear(H5F_t *f, H5O_proxy_t *proxy, hbool_t destroy)
+H5O__cache_proxy_serialize(const H5F_t H5_ATTR_UNUSED *f, void H5_ATTR_UNUSED *_image, size_t H5_ATTR_UNUSED len,
+ void H5_ATTR_UNUSED *_thing)
{
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT
-
- /*
- * Check arguments.
- */
- HDassert(proxy);
+ FUNC_ENTER_STATIC_NOERR
- /* The dirty flag should not be set */
- HDassert(!proxy->cache_info.is_dirty);
+ /* A no-op */
- if(destroy)
- if(H5O_cache_proxy_dest(f, proxy) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to destroy object header proxy")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5O_cache_proxy_clear() */
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5O__cache_proxy_serialize() */
/*-------------------------------------------------------------------------
- * Function: H5O_cache_proxy_notify
+ * Function: H5O__cache_proxy_notify
*
* Purpose: Handle cache action notifications
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Neil Fortner
- * Mar 20 2012
+ * nfortne2@hdfgroup.org
+ * Apr 25 2012
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5O_cache_proxy_notify(H5AC_notify_action_t action, H5O_proxy_t *proxy)
+H5O__cache_proxy_notify(H5AC_notify_action_t action, void *_thing)
{
- H5O_chunk_proxy_t *chk_proxy = NULL; /* Object header chunk proxy */
- unsigned i; /* Local index variable */
- herr_t ret_value = SUCCEED; /* Return value */
+ H5O_proxy_t *proxy = (H5O_proxy_t *)_thing;
+ H5O_chunk_proxy_t *chk_proxy = NULL; /* Object header chunk proxy */
+ unsigned i; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT
@@ -292,14 +292,16 @@ H5O_cache_proxy_notify(H5AC_notify_action_t action, H5O_proxy_t *proxy)
switch(action) {
case H5AC_NOTIFY_ACTION_AFTER_INSERT:
+ case H5AC_NOTIFY_ACTION_AFTER_LOAD:
/* Create flush dependency on object header chunk 0 */
if(H5AC_create_flush_dependency(proxy->oh, proxy) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTDEPEND, FAIL, "unable to create flush dependency")
/* Create flush dependencies on all other object header chunks */
- for(i=1; i<proxy->oh->nchunks; i++) {
+ for(i = 1; i < proxy->oh->nchunks; i++) {
if(NULL == (chk_proxy = H5O_chunk_protect(proxy->f, H5AC_ind_dxpl_id, proxy->oh, i)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header chunk")
+/* same as before, but looks backward...need to check into that..(proxy, chk_proxy) */
if(H5AC_create_flush_dependency(chk_proxy, proxy) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTDEPEND, FAIL, "unable to create flush dependency")
if(H5O_chunk_unprotect(proxy->f, H5AC_ind_dxpl_id, chk_proxy, FALSE) < 0)
@@ -312,6 +314,10 @@ H5O_cache_proxy_notify(H5AC_notify_action_t action, H5O_proxy_t *proxy)
break;
+ case H5AC_NOTIFY_ACTION_AFTER_FLUSH:
+ /* do nothing */
+ break;
+
case H5AC_NOTIFY_ACTION_BEFORE_EVICT:
/* Mark proxy as not present on the object header */
proxy->oh->proxy_present = FALSE;
@@ -334,16 +340,17 @@ done:
} /* end if */
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5O_cache_proxy_notify() */
+
+} /* end H5O__cache_proxy_notify() */
/*-------------------------------------------------------------------------
- * Function: H5O_cache_proxy_size
+ * Function: H5O__cache_proxy_free_icr
*
- * Purpose: Compute the size in bytes of an object header proxy
- * on disk, and return it in *size_ptr.
+ * Purpose: Destroy/release an "in core representation" of a data
+ * structure
*
- * Return: 0 (never fails)
+ * Return: Non-negative on success/Negative on failure
*
* Programmer: Neil Fortner
* Mar 15 2012
@@ -351,21 +358,48 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5O_cache_proxy_size(const H5F_t H5_ATTR_UNUSED *f,
- const H5O_proxy_t H5_ATTR_UNUSED *proxy, size_t *size_ptr)
+H5O__cache_proxy_free_icr(void *_thing)
{
+ H5O_proxy_t *proxy = (H5O_proxy_t *)_thing;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ if(H5O__cache_proxy_dest(proxy) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to destroy object header proxy")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5O__cache_proxy_free_icr() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_cache_proxy_dest
+ *
+ * Purpose: Destroys an object header proxy in memory.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Neil Fortner
+ * Mar 15 2012
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O__cache_proxy_dest(H5O_proxy_t *proxy)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
FUNC_ENTER_NOAPI_NOINIT_NOERR
- /* check arguments */
- HDassert(size_ptr);
+ HDassert(proxy);
+ HDassert(proxy->oh);
- /* Object header proxies are represented as 1 byte in cache */
- /* (would be 0 bytes, but cache won't allow it currently. See
- * H5D_cache_proxy_size) */
- *size_ptr = 1;
+ /* Free the object header proxy object */
+ proxy = H5FL_FREE(H5O_proxy_t, proxy);
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5O_cache_proxy_size() */
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O__cache_proxy_dest() */
/*-------------------------------------------------------------------------
@@ -425,6 +459,7 @@ H5O_proxy_t *
H5O_proxy_pin(H5F_t *f, hid_t dxpl_id, H5O_t *oh)
{
H5O_proxy_t *proxy = NULL; /* Object header proxy */
+ H5O_proxy_cache_ud_t udata; /* User-data for callback */
H5O_proxy_t *ret_value = NULL; /* Return value */
FUNC_ENTER_NOAPI_NOINIT
@@ -433,8 +468,10 @@ H5O_proxy_pin(H5F_t *f, hid_t dxpl_id, H5O_t *oh)
HDassert(oh);
HDassert(H5F_addr_defined(oh->proxy_addr));
+ udata.f = f;
+ udata.oh = oh;
/* Protect the object header proxy */
- if(NULL == (proxy = (H5O_proxy_t *)H5AC_protect(f, dxpl_id, H5AC_OHDR_PROXY, oh->proxy_addr, oh, H5AC_READ)))
+ if(NULL == (proxy = (H5O_proxy_t *)H5AC_protect(f, dxpl_id, H5AC_OHDR_PROXY, oh->proxy_addr, &udata, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, NULL, "unable to protect object header proxy");
/* Unprotect the object header proxy and pin it */
@@ -503,6 +540,7 @@ herr_t
H5O_proxy_depend(H5F_t *f, hid_t dxpl_id, H5O_t *oh, void *parent)
{
H5O_proxy_t *proxy = NULL; /* Object header proxy */
+ H5O_proxy_cache_ud_t udata; /* User-data for callback */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT
@@ -512,8 +550,10 @@ H5O_proxy_depend(H5F_t *f, hid_t dxpl_id, H5O_t *oh, void *parent)
HDassert(H5F_addr_defined(oh->proxy_addr));
HDassert(parent);
+ udata.f = f;
+ udata.oh = oh;
/* Protect the object header proxy */
- if(NULL == (proxy = (H5O_proxy_t *)H5AC_protect(f, dxpl_id, H5AC_OHDR_PROXY, oh->proxy_addr, oh, H5AC_READ)))
+ if(NULL == (proxy = (H5O_proxy_t *)H5AC_protect(f, dxpl_id, H5AC_OHDR_PROXY, oh->proxy_addr, &udata, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to protect object header proxy");
/* Add the flush dependency on the parent object */
@@ -553,6 +593,7 @@ herr_t
H5O_proxy_undepend(H5F_t *f, hid_t dxpl_id, H5O_t *oh, void *parent)
{
H5O_proxy_t *proxy = NULL; /* Object header proxy */
+ H5O_proxy_cache_ud_t udata; /* User-data for callback */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT
@@ -562,8 +603,10 @@ H5O_proxy_undepend(H5F_t *f, hid_t dxpl_id, H5O_t *oh, void *parent)
HDassert(H5F_addr_defined(oh->proxy_addr));
HDassert(parent);
+ udata.f = f;
+ udata.oh = oh;
/* Protect the object header proxy */
- if(NULL == (proxy = (H5O_proxy_t *)H5AC_protect(f, dxpl_id, H5AC_OHDR_PROXY, oh->proxy_addr, oh, H5AC_READ)))
+ if(NULL == (proxy = (H5O_proxy_t *)H5AC_protect(f, dxpl_id, H5AC_OHDR_PROXY, oh->proxy_addr, &udata, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to protect object header proxy");
/* Add the flush dependency on the parent object */
diff --git a/src/H5Otest.c b/src/H5Otest.c
index 9c1b9d8..66fd092 100644
--- a/src/H5Otest.c
+++ b/src/H5Otest.c
@@ -108,7 +108,7 @@ H5O_is_attr_dense_test(hid_t oid)
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "object not found")
/* Get the object header */
- if(NULL == (oh = H5O_protect(loc, H5AC_ind_dxpl_id, H5AC_READ)))
+ if(NULL == (oh = H5O_protect(loc, H5AC_ind_dxpl_id, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
/* Check for attribute info stored */
@@ -174,7 +174,7 @@ H5O_is_attr_empty_test(hid_t oid)
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "object not found")
/* Get the object header */
- if(NULL == (oh = H5O_protect(loc, H5AC_ind_dxpl_id, H5AC_READ)))
+ if(NULL == (oh = H5O_protect(loc, H5AC_ind_dxpl_id, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
/* Check for attribute info stored */
@@ -276,7 +276,7 @@ H5O_num_attrs_test(hid_t oid, hsize_t *nattrs)
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "object not found")
/* Get the object header */
- if(NULL == (oh = H5O_protect(loc, H5AC_ind_dxpl_id, H5AC_READ)))
+ if(NULL == (oh = H5O_protect(loc, H5AC_ind_dxpl_id, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
/* Check for attribute info stored */
@@ -380,7 +380,7 @@ H5O_attr_dense_info_test(hid_t oid, hsize_t *name_count, hsize_t *corder_count)
H5_BEGIN_TAG(H5AC_ind_dxpl_id, loc->addr, FAIL);
/* Get the object header */
- if(NULL == (oh = H5O_protect(loc, H5AC_ind_dxpl_id, H5AC_READ)))
+ if(NULL == (oh = H5O_protect(loc, H5AC_ind_dxpl_id, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR_TAG(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
/* Check for attribute info stored */
@@ -479,7 +479,7 @@ H5O_check_msg_marked_test(hid_t oid, hbool_t flag_val)
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "object not found")
/* Get the object header */
- if(NULL == (oh = H5O_protect(loc, H5AC_ind_dxpl_id, H5AC_READ)))
+ if(NULL == (oh = H5O_protect(loc, H5AC_ind_dxpl_id, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
/* Locate "unknown" message */
@@ -538,7 +538,7 @@ H5O_expunge_chunks_test(const H5O_loc_t *loc, hid_t dxpl_id)
FUNC_ENTER_NOAPI(FAIL)
/* Get the object header */
- if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_WRITE)))
+ if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to protect object header")
/* Safety check */
@@ -598,7 +598,7 @@ H5O_get_rc(const H5O_loc_t *loc, hid_t dxpl_id, unsigned *rc)
HDassert(rc);
/* Get the object header */
- if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_READ)))
+ if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to protect object header")
/* Save the refcount for the object header */
diff --git a/src/H5SM.c b/src/H5SM.c
index 5a73bf3..730f4b1 100644
--- a/src/H5SM.c
+++ b/src/H5SM.c
@@ -358,7 +358,7 @@ H5SM_type_shared(H5F_t *f, unsigned type_id, hid_t dxpl_id)
/* Set up user data for callback */
cache_udata.f = f;
- if(NULL == (table = (H5SM_master_table_t *)H5AC_protect(f, dxpl_id, H5AC_SOHM_TABLE, H5F_SOHM_ADDR(f), &cache_udata, H5AC_READ)))
+ if(NULL == (table = (H5SM_master_table_t *)H5AC_protect(f, dxpl_id, H5AC_SOHM_TABLE, H5F_SOHM_ADDR(f), &cache_udata, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTPROTECT, FAIL, "unable to load SOHM master table")
} /* end if */
else
@@ -412,7 +412,7 @@ H5SM_get_fheap_addr(H5F_t *f, hid_t dxpl_id, unsigned type_id, haddr_t *fheap_ad
cache_udata.f = f;
/* Look up the master SOHM table */
- if(NULL == (table = (H5SM_master_table_t *)H5AC_protect(f, dxpl_id, H5AC_SOHM_TABLE, H5F_SOHM_ADDR(f), &cache_udata, H5AC_READ)))
+ if(NULL == (table = (H5SM_master_table_t *)H5AC_protect(f, dxpl_id, H5AC_SOHM_TABLE, H5F_SOHM_ADDR(f), &cache_udata, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTPROTECT, FAIL, "unable to load SOHM master table")
/* Look up index for message type */
@@ -831,7 +831,7 @@ H5SM_convert_btree_to_list(H5F_t * f, H5SM_index_header_t * header, hid_t dxpl_i
cache_udata.header = header;
/* Protect the SOHM list */
- if(NULL == (list = (H5SM_list_t *)H5AC_protect(f, dxpl_id, H5AC_SOHM_LIST, header->index_addr, &cache_udata, H5AC_WRITE)))
+ if(NULL == (list = (H5SM_list_t *)H5AC_protect(f, dxpl_id, H5AC_SOHM_LIST, header->index_addr, &cache_udata, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTPROTECT, FAIL, "unable to load SOHM list index")
/* Delete the B-tree and have messages copy themselves to the
@@ -939,7 +939,7 @@ H5SM_can_share(H5F_t *f, hid_t dxpl_id, H5SM_master_table_t *table,
/* Set up user data for callback */
cache_udata.f = f;
- if(NULL == (my_table = (H5SM_master_table_t *)H5AC_protect(f, dxpl_id, H5AC_SOHM_TABLE, H5F_SOHM_ADDR(f), &cache_udata, H5AC_READ)))
+ if(NULL == (my_table = (H5SM_master_table_t *)H5AC_protect(f, dxpl_id, H5AC_SOHM_TABLE, H5F_SOHM_ADDR(f), &cache_udata, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTPROTECT, FAIL, "unable to load SOHM master table")
} /* end if */
@@ -1071,7 +1071,7 @@ H5SM_try_share(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, unsigned defer_flags,
cache_udata.f = f;
/* Look up the master SOHM table */
- if(NULL == (table = (H5SM_master_table_t *)H5AC_protect(f, dxpl_id, H5AC_SOHM_TABLE, H5F_SOHM_ADDR(f), &cache_udata, H5AC_WRITE)))
+ if(NULL == (table = (H5SM_master_table_t *)H5AC_protect(f, dxpl_id, H5AC_SOHM_TABLE, H5F_SOHM_ADDR(f), &cache_udata, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTPROTECT, FAIL, "unable to load SOHM master table")
/* "complex" sharing checks */
@@ -1277,7 +1277,7 @@ H5SM_write_mesg(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
cache_udata.header = header;
/* The index is a list; get it from the cache */
- if(NULL == (list = (H5SM_list_t *)H5AC_protect(f, dxpl_id, H5AC_SOHM_LIST, header->index_addr, &cache_udata, defer ? H5AC_READ : H5AC_WRITE)))
+ if(NULL == (list = (H5SM_list_t *)H5AC_protect(f, dxpl_id, H5AC_SOHM_LIST, header->index_addr, &cache_udata, defer ? H5AC__READ_ONLY_FLAG : H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTPROTECT, FAIL, "unable to load SOHM index")
/* See if the message is already in the index and get its location.
@@ -1530,7 +1530,7 @@ H5SM_delete(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, H5O_shared_t *sh_mesg)
cache_udata.f = f;
/* Look up the master SOHM table */
- if(NULL == (table = (H5SM_master_table_t *)H5AC_protect(f, dxpl_id, H5AC_SOHM_TABLE, H5F_SOHM_ADDR(f), &cache_udata, H5AC_WRITE)))
+ if(NULL == (table = (H5SM_master_table_t *)H5AC_protect(f, dxpl_id, H5AC_SOHM_TABLE, H5F_SOHM_ADDR(f), &cache_udata, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTPROTECT, FAIL, "unable to load SOHM master table")
/* Find the correct index and try to delete from it */
@@ -1799,7 +1799,7 @@ H5SM_delete_from_index(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
cache_udata.header = header;
/* If the index is stored as a list, get it from the cache */
- if(NULL == (list = (H5SM_list_t *)H5AC_protect(f, dxpl_id, H5AC_SOHM_LIST, header->index_addr, &cache_udata, H5AC_WRITE)))
+ if(NULL == (list = (H5SM_list_t *)H5AC_protect(f, dxpl_id, H5AC_SOHM_LIST, header->index_addr, &cache_udata, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTPROTECT, FAIL, "unable to load SOHM index")
/* Find the message in the list */
@@ -1970,7 +1970,7 @@ H5SM_get_info(const H5O_loc_t *ext_loc, H5P_genplist_t *fc_plist, hid_t dxpl_id)
cache_udata.f = f;
/* Read the rest of the SOHM table information from the cache */
- if(NULL == (table = (H5SM_master_table_t *)H5AC_protect(f, dxpl_id, H5AC_SOHM_TABLE, H5F_SOHM_ADDR(f), &cache_udata, H5AC_READ)))
+ if(NULL == (table = (H5SM_master_table_t *)H5AC_protect(f, dxpl_id, H5AC_SOHM_TABLE, H5F_SOHM_ADDR(f), &cache_udata, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTPROTECT, FAIL, "unable to load SOHM master table")
/* Get index conversion limits */
@@ -2133,7 +2133,7 @@ H5SM_get_refcount(H5F_t *f, hid_t dxpl_id, unsigned type_id,
tbl_cache_udata.f = f;
/* Look up the master SOHM table */
- if(NULL == (table = (H5SM_master_table_t *)H5AC_protect(f, dxpl_id, H5AC_SOHM_TABLE, H5F_SOHM_ADDR(f), &tbl_cache_udata, H5AC_READ)))
+ if(NULL == (table = (H5SM_master_table_t *)H5AC_protect(f, dxpl_id, H5AC_SOHM_TABLE, H5F_SOHM_ADDR(f), &tbl_cache_udata, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTPROTECT, FAIL, "unable to load SOHM master table")
/* Find the correct index and find the message in it */
@@ -2172,7 +2172,7 @@ H5SM_get_refcount(H5F_t *f, hid_t dxpl_id, unsigned type_id,
lst_cache_udata.header = header;
/* If the index is stored as a list, get it from the cache */
- if(NULL == (list = (H5SM_list_t *)H5AC_protect(f, dxpl_id, H5AC_SOHM_LIST, header->index_addr, &lst_cache_udata, H5AC_READ)))
+ if(NULL == (list = (H5SM_list_t *)H5AC_protect(f, dxpl_id, H5AC_SOHM_LIST, header->index_addr, &lst_cache_udata, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTPROTECT, FAIL, "unable to load SOHM index")
/* Find the message in the list */
@@ -2375,7 +2375,7 @@ H5SM_read_mesg(H5F_t *f, const H5SM_sohm_t *mesg, H5HF_t *fheap,
HGOTO_ERROR(H5E_SOHM, H5E_CANTLOAD, FAIL, "unable to open object header")
/* Load the object header from the cache */
- if(NULL == (oh = H5O_protect(&oloc, dxpl_id, H5AC_READ)))
+ if(NULL == (oh = H5O_protect(&oloc, dxpl_id, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTPROTECT, FAIL, "unable to load object header")
} /* end if */
else
@@ -2530,7 +2530,7 @@ H5SM_table_debug(H5F_t *f, hid_t dxpl_id, haddr_t table_addr,
cache_udata.f = f;
/* Look up the master SOHM table */
- if(NULL == (table = (H5SM_master_table_t *)H5AC_protect(f, dxpl_id, H5AC_SOHM_TABLE, table_addr, &cache_udata, H5AC_READ)))
+ if(NULL == (table = (H5SM_master_table_t *)H5AC_protect(f, dxpl_id, H5AC_SOHM_TABLE, table_addr, &cache_udata, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTPROTECT, FAIL, "unable to load SOHM master table")
HDfprintf(stream, "%*sShared Message Master Table...\n", indent, "");
@@ -2616,7 +2616,7 @@ H5SM_list_debug(H5F_t *f, hid_t dxpl_id, haddr_t list_addr,
cache_udata.header = &header;
/* Get the list from the cache */
- if(NULL == (list = (H5SM_list_t *)H5AC_protect(f, dxpl_id, H5AC_SOHM_LIST, list_addr, &cache_udata, H5AC_READ)))
+ if(NULL == (list = (H5SM_list_t *)H5AC_protect(f, dxpl_id, H5AC_SOHM_LIST, list_addr, &cache_udata, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTPROTECT, FAIL, "unable to load SOHM index")
HDfprintf(stream, "%*sShared Message List Index...\n", indent, "");
@@ -2693,7 +2693,7 @@ H5SM_ih_size(H5F_t *f, hid_t dxpl_id, hsize_t *hdr_size, H5_ih_info_t *ih_info)
cache_udata.f = f;
/* Look up the master SOHM table */
- if(NULL == (table = (H5SM_master_table_t *)H5AC_protect(f, dxpl_id, H5AC_SOHM_TABLE, H5F_SOHM_ADDR(f), &cache_udata, H5AC_READ)))
+ if(NULL == (table = (H5SM_master_table_t *)H5AC_protect(f, dxpl_id, H5AC_SOHM_TABLE, H5F_SOHM_ADDR(f), &cache_udata, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTPROTECT, FAIL, "unable to load SOHM master table")
/* Get SOHM header size */
diff --git a/src/H5SMcache.c b/src/H5SMcache.c
index 0a8921a..54c2b41 100644
--- a/src/H5SMcache.c
+++ b/src/H5SMcache.c
@@ -47,12 +47,6 @@
/* Local Macros */
/****************/
-/* Size of stack buffer for serialized tables */
-#define H5SM_TBL_BUF_SIZE 1024
-
-/* Size of stack buffer for serialized list indices */
-#define H5SM_LST_BUF_SIZE 1024
-
/******************/
/* Local Typedefs */
@@ -64,16 +58,29 @@
/********************/
/* Metadata cache (H5AC) callbacks */
-static H5SM_master_table_t *H5SM_table_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata);
-static herr_t H5SM_table_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5SM_master_table_t *table);
-static herr_t H5SM_table_dest(H5F_t *f, H5SM_master_table_t* table);
-static herr_t H5SM_table_clear(H5F_t *f, H5SM_master_table_t *table, hbool_t destroy);
-static herr_t H5SM_table_size(const H5F_t *f, const H5SM_master_table_t *table, size_t *size_ptr);
-static H5SM_list_t *H5SM_list_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata);
-static herr_t H5SM_list_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5SM_list_t *list);
-static herr_t H5SM_list_dest(H5F_t *f, H5SM_list_t* list);
-static herr_t H5SM_list_clear(H5F_t *f, H5SM_list_t *list, hbool_t destroy);
-static herr_t H5SM_list_size(const H5F_t *f, const H5SM_list_t H5_ATTR_UNUSED *list, size_t *size_ptr);
+static herr_t H5SM__cache_table_get_load_size(const void *image_ptr, void *udata,
+ size_t *image_len, size_t *actual_len,
+ hbool_t *compressed_ptr, size_t *compressed_image_len_ptr);
+static htri_t H5SM__cache_table_verify_chksum(const void *image_ptr, size_t len, void *udata_ptr);
+static void *H5SM__cache_table_deserialize(const void *image, size_t len,
+ void *udata, hbool_t *dirty);
+static herr_t H5SM__cache_table_image_len(const void *thing, size_t *image_len,
+ hbool_t *compressed_ptr, size_t *compressed_image_len_ptr);
+static herr_t H5SM__cache_table_serialize(const H5F_t *f, void *image,
+ size_t len, void *thing);
+static herr_t H5SM__cache_table_free_icr(void *thing);
+
+static herr_t H5SM__cache_list_get_load_size(const void *image_ptr, void *udata,
+ size_t *image_len, size_t *actual_len,
+ hbool_t *compressed_ptr, size_t *compressed_image_len_ptr);
+static htri_t H5SM__cache_list_verify_chksum(const void *image_ptr, size_t len, void *udata_ptr);
+static void *H5SM__cache_list_deserialize(const void *image, size_t len,
+ void *udata, hbool_t *dirty);
+static herr_t H5SM__cache_list_image_len(const void *thing, size_t *image_len,
+ hbool_t *compressed_ptr, size_t *compressed_image_len_ptr);
+static herr_t H5SM__cache_list_serialize(const H5F_t *f, void *image,
+ size_t len, void *thing);
+static herr_t H5SM__cache_list_free_icr(void *thing);
/*********************/
@@ -82,23 +89,37 @@ static herr_t H5SM_list_size(const H5F_t *f, const H5SM_list_t H5_ATTR_UNUSED *l
/* H5SM inherits cache-like properties from H5AC */
const H5AC_class_t H5AC_SOHM_TABLE[1] = {{
- H5AC_SOHM_TABLE_ID,
- (H5AC_load_func_t)H5SM_table_load,
- (H5AC_flush_func_t)H5SM_table_flush,
- (H5AC_dest_func_t)H5SM_table_dest,
- (H5AC_clear_func_t)H5SM_table_clear,
- (H5AC_notify_func_t)NULL,
- (H5AC_size_func_t)H5SM_table_size,
+ H5AC_SOHM_TABLE_ID, /* Metadata client ID */
+ "shared message table", /* Metadata client name (for debugging) */
+ H5FD_MEM_SOHM_TABLE, /* File space memory type for client */
+ H5AC__CLASS_NO_FLAGS_SET, /* Client class behavior flags */
+ H5SM__cache_table_get_load_size, /* 'get_load_size' callback */
+ H5SM__cache_table_verify_chksum, /* 'verify_chksum' callback */
+ H5SM__cache_table_deserialize, /* 'deserialize' callback */
+ H5SM__cache_table_image_len, /* 'image_len' callback */
+ NULL, /* 'pre_serialize' callback */
+ H5SM__cache_table_serialize, /* 'serialize' callback */
+ NULL, /* 'notify' callback */
+ H5SM__cache_table_free_icr, /* 'free_icr' callback */
+ NULL, /* 'clear' callback */
+ NULL, /* 'fsf_size' callback */
}};
const H5AC_class_t H5AC_SOHM_LIST[1] = {{
- H5AC_SOHM_LIST_ID,
- (H5AC_load_func_t)H5SM_list_load,
- (H5AC_flush_func_t)H5SM_list_flush,
- (H5AC_dest_func_t)H5SM_list_dest,
- (H5AC_clear_func_t)H5SM_list_clear,
- (H5AC_notify_func_t)NULL,
- (H5AC_size_func_t)H5SM_list_size,
+ H5AC_SOHM_LIST_ID, /* Metadata client ID */
+ "shared message list", /* Metadata client name (for debugging) */
+ H5FD_MEM_SOHM_TABLE, /* File space memory type for client */
+ H5AC__CLASS_NO_FLAGS_SET, /* Client class behavior flags */
+ H5SM__cache_list_get_load_size, /* 'get_load_size' callback */
+ H5SM__cache_list_verify_chksum, /* 'verify_chksum' callback */
+ H5SM__cache_list_deserialize, /* 'deserialize' callback */
+ H5SM__cache_list_image_len, /* 'image_len' callback */
+ NULL, /* 'pre_serialize' callback */
+ H5SM__cache_list_serialize, /* 'serialize' callback */
+ NULL, /* 'notify' callback */
+ H5SM__cache_list_free_icr, /* 'free_icr' callback */
+ NULL, /* 'clear' callback */
+ NULL, /* 'fsf_size' callback */
}};
@@ -114,30 +135,119 @@ const H5AC_class_t H5AC_SOHM_LIST[1] = {{
/*-------------------------------------------------------------------------
- * Function: H5SM_table_load
+ * Function: H5SM__cache_table_get_load_size()
+ *
+ * Purpose: Return the size of the master table of Shared Object Header
+ * Message indexes on disk. As this cache client doesn't use
+ * speculative reads, this value should be accurate.
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: John Mainzer
+ * 7/28/14
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5SM__cache_table_get_load_size(const void *_image, void *_udata,
+ size_t *image_len, size_t *actual_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr)
+{
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ const H5SM_table_cache_ud_t *udata = (const H5SM_table_cache_ud_t *)_udata; /* User data for callback */
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Check arguments */
+ HDassert(udata);
+ HDassert(udata->f);
+ HDassert(image_len);
+
+ if(image == NULL)
+ *image_len = H5SM_TABLE_SIZE(udata->f);
+ else {
+ HDassert(actual_len);
+ HDassert(*actual_len == *image_len);
+ }
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5SM__cache_table_get_load_size() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5SM__cache_table_verify_chksum
+ *
+ * Purpose: Verify the computed checksum of the data structure is the
+ * same as the stored chksum.
+ *
+ * Return: Success: TRUE/FALSE
+ * Failure: Negative
+ *
+ * Programmer: Vailin Choi; Aug 2015
+ *
+ *-------------------------------------------------------------------------
+ */
+htri_t
+H5SM__cache_table_verify_chksum(const void *_image, size_t len, void H5_ATTR_UNUSED *_udata)
+{
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ uint32_t stored_chksum; /* Stored metadata checksum value */
+ uint32_t computed_chksum; /* Computed metadata checksum value */
+ htri_t ret_value = TRUE; /* Return value */
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Check arguments */
+ HDassert(image);
+
+ /* Get stored and computed checksums */
+ H5F_get_checksums(image, len, &stored_chksum, &computed_chksum);
+
+ if(stored_chksum != computed_chksum)
+ ret_value = FALSE;
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5SM__cache_table_verify_chksum() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5SM__cache_table_deserialize
*
- * Purpose: Loads the master table of Shared Object Header Message
- * indexes.
+ * Purpose: Given a buffer containing the on disk representation of the
+ * master table of Shared Object Header Message indexes, deserialize
+ * the table, copy the contents into a newly allocated instance of
+ * H5SM_master_table_t, and return a pointer to the new instance.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Success: Pointer to in core representation
+ * Failure: NULL
*
- * Programmer: James Laird
- * November 6, 2006
+ * Programmer: John Mainzer
+ * 7/28/14
*
*-------------------------------------------------------------------------
*/
-static H5SM_master_table_t *
-H5SM_table_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void H5_ATTR_UNUSED *udata)
+static void *
+H5SM__cache_table_deserialize(const void *_image, size_t len, void *_udata,
+ hbool_t H5_ATTR_UNUSED *dirty)
{
- H5SM_master_table_t *table = NULL;
- H5WB_t *wb = NULL; /* Wrapped buffer for table data */
- uint8_t tbl_buf[H5SM_TBL_BUF_SIZE]; /* Buffer for table */
- uint8_t *buf; /* Reading buffer */
- const uint8_t *p; /* Pointer into input buffer */
- size_t u; /* Counter variable for index headers */
- H5SM_master_table_t *ret_value;
+ H5F_t *f; /* File pointer -- from user data */
+ H5SM_master_table_t *table = NULL; /* Shared message table that we deserializing */
+ H5SM_table_cache_ud_t *udata = (H5SM_table_cache_ud_t *)_udata; /* Pointer to user data */
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into input buffer */
+ uint32_t stored_chksum; /* Stored metadata checksum value */
+ size_t u; /* Counter variable for index headers */
+ void * ret_value; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
+
+ /* Check arguments */
+ HDassert(image);
+ HDassert(len > 0);
+ HDassert(udata);
+ HDassert(udata->f);
+ f = udata->f;
+ HDassert(dirty);
/* Verify that we're reading version 0 of the table; this is the only
* version defined so far.
@@ -150,35 +260,18 @@ H5SM_table_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void H5_ATTR_UNUSED *udat
/* Read number of indexes and version from file superblock */
table->num_indexes = H5F_SOHM_NINDEXES(f);
-
- HDassert(addr == H5F_SOHM_ADDR(f));
- HDassert(addr != HADDR_UNDEF);
HDassert(table->num_indexes > 0);
- /* Wrap the local buffer for serialized table info */
- if(NULL == (wb = H5WB_wrap(tbl_buf, sizeof(tbl_buf))))
- HGOTO_ERROR(H5E_SOHM, H5E_CANTINIT, NULL, "can't wrap buffer")
-
/* Compute the size of the SOHM table header on disk. This is the "table"
* itself plus each index within the table
*/
table->table_size = H5SM_TABLE_SIZE(f);
-
- /* Get a pointer to a buffer that's large enough for serialized table */
- if(NULL == (buf = (uint8_t *)H5WB_actual(wb, table->table_size)))
- HGOTO_ERROR(H5E_SOHM, H5E_NOSPACE, NULL, "can't get actual buffer")
-
- /* Read and validate shared message table from disk */
- if(H5F_read_check_metadata(f, dxpl_id, H5FD_MEM_SOHM_TABLE, H5AC_SOHM_TABLE_ID, addr, table->table_size, table->table_size, buf) < 0)
- HGOTO_ERROR(H5E_SOHM, H5E_BADVALUE, NULL, "incorrect metadata checksum for shared message table")
-
- /* Get temporary pointer to serialized table */
- p = buf;
+ HDassert(table->table_size == len);
/* Check magic number */
- if(HDmemcmp(p, H5SM_TABLE_MAGIC, (size_t)H5_SIZEOF_MAGIC))
- HGOTO_ERROR(H5E_SOHM, H5E_CANTLOAD, NULL, "bad SOHM table signature")
- p += H5_SIZEOF_MAGIC;
+ if(HDmemcmp(image, H5SM_TABLE_MAGIC, (size_t)H5_SIZEOF_MAGIC))
+ HGOTO_ERROR(H5E_SOHM, H5E_CANTLOAD, NULL, "bad SOHM table signature")
+ image += H5_SIZEOF_MAGIC;
/* Allocate space for the index headers in memory*/
if(NULL == (table->indexes = (H5SM_index_header_t *)H5FL_ARR_MALLOC(H5SM_index_header_t, (size_t)table->num_indexes)))
@@ -187,187 +280,213 @@ H5SM_table_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void H5_ATTR_UNUSED *udat
/* Read in the index headers */
for(u = 0; u < table->num_indexes; ++u) {
/* Verify correct version of index list */
- if(H5SM_LIST_VERSION != *p++)
+ if(H5SM_LIST_VERSION != *image++)
HGOTO_ERROR(H5E_SOHM, H5E_VERSION, NULL, "bad shared message list version number")
/* Type of the index (list or B-tree) */
- table->indexes[u].index_type= (H5SM_index_type_t)*p++;
+ table->indexes[u].index_type= (H5SM_index_type_t)*image++;
/* Type of messages in the index */
- UINT16DECODE(p, table->indexes[u].mesg_types);
+ UINT16DECODE(image, table->indexes[u].mesg_types);
/* Minimum size of message to share */
- UINT32DECODE(p, table->indexes[u].min_mesg_size);
+ UINT32DECODE(image, table->indexes[u].min_mesg_size);
/* List cutoff; fewer than this number and index becomes a list */
- UINT16DECODE(p, table->indexes[u].list_max);
+ UINT16DECODE(image, table->indexes[u].list_max);
/* B-tree cutoff; more than this number and index becomes a B-tree */
- UINT16DECODE(p, table->indexes[u].btree_min);
+ UINT16DECODE(image, table->indexes[u].btree_min);
/* Number of messages shared */
- UINT16DECODE(p, table->indexes[u].num_messages);
+ UINT16DECODE(image, table->indexes[u].num_messages);
/* Address of the actual index */
- H5F_addr_decode(f, &p, &(table->indexes[u].index_addr));
+ H5F_addr_decode(f, &image, &(table->indexes[u].index_addr));
/* Address of the index's heap */
- H5F_addr_decode(f, &p, &(table->indexes[u].heap_addr));
+ H5F_addr_decode(f, &image, &(table->indexes[u].heap_addr));
/* Compute the size of a list index for this SOHM index */
table->indexes[u].list_size = H5SM_LIST_SIZE(f, table->indexes[u].list_max);
+ table->indexes[u].list_size = H5SM_LIST_SIZE(f, table->indexes[u].list_max);
} /* end for */
- /* Already decoded and compared stored checksum earlier, when reading */
+ /* checksum verification already done in verify_chksum cb */
+
+ /* Read in checksum */
+ UINT32DECODE(image, stored_chksum);
/* Sanity check */
- HDassert((size_t)(p - (const uint8_t *)buf) == (table->table_size - H5_SIZEOF_CHKSUM));
+ HDassert((size_t)(image - (const uint8_t *)_image) == table->table_size);
/* Set return value */
ret_value = table;
done:
- /* Release resources */
- if(wb && H5WB_unwrap(wb) < 0)
- HDONE_ERROR(H5E_SOHM, H5E_CLOSEERROR, NULL, "can't close wrapped buffer")
if(!ret_value && table)
if(H5SM_table_free(table) < 0)
HDONE_ERROR(H5E_SOHM, H5E_CANTFREE, NULL, "unable to destroy sohm table")
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5SM_table_load() */
+} /* end H5SM__cache_table_deserialize() */
/*-------------------------------------------------------------------------
- * Function: H5SM_table_flush
+ * Function: H5SM__cache_table_image_len
*
- * Purpose: Flushes (and destroys) the table of Shared Object Header
- * Message indexes.
+ * Purpose: Compute the size in bytes of the specified instance of
+ * H5SM_master_table_t on disk, and return it in *image_len.
+ * On failure, the value of *image_len is undefined.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Success: SUCCEED
+ * Failure: FAIL
*
- * Programmer: James Laird
- * November 6, 2006
+ * Programmer: John Mainzer
+ * 7/28/14
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5SM_table_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5SM_master_table_t *table)
+H5SM__cache_table_image_len(const void *_thing, size_t *image_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr)
{
- H5WB_t *wb = NULL; /* Wrapped buffer for table data */
- uint8_t tbl_buf[H5SM_TBL_BUF_SIZE]; /* Buffer for table */
- herr_t ret_value = SUCCEED; /* Return value */
+ const H5SM_master_table_t *table = (const H5SM_master_table_t *)_thing; /* Shared message table to query */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC_NOERR
- /* check arguments */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
+ /* Check arguments */
HDassert(table);
+ HDassert(table->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(table->cache_info.type == H5AC_SOHM_TABLE);
+ HDassert(image_len);
- if(table->cache_info.is_dirty) {
- uint8_t *buf; /* Temporary buffer */
- uint8_t *p; /* Pointer into raw data buffer */
- uint32_t computed_chksum; /* Computed metadata checksum value */
- size_t u; /* Counter variable */
+ *image_len = table->table_size;
- /* Verify that we're writing version 0 of the table; this is the only
- * version defined so far.
- */
- HDassert(H5F_SOHM_VERS(f) == HDF5_SHAREDHEADER_VERSION);
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5SM__cache_table_image_len() */
- /* Wrap the local buffer for serialized header info */
- if(NULL == (wb = H5WB_wrap(tbl_buf, sizeof(tbl_buf))))
- HGOTO_ERROR(H5E_SOHM, H5E_CANTINIT, FAIL, "can't wrap buffer")
+/***************************************/
+/* no H5SM_cache_table_pre_serialize() */
+/***************************************/
- /* Get a pointer to a buffer that's large enough for serialized table */
- if(NULL == (buf = (uint8_t *)H5WB_actual(wb, table->table_size)))
- HGOTO_ERROR(H5E_SOHM, H5E_NOSPACE, FAIL, "can't get actual buffer")
+
+/*-------------------------------------------------------------------------
+ * Function: H5SM__cache_table_serialize
+ *
+ * Purpose: Serialize the contents of the supplied shared message table, and
+ * load this data into the supplied buffer.
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: John Mainzer
+ * 7/28/14
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5SM__cache_table_serialize(const H5F_t *f, void *_image, size_t len,
+ void *_thing)
+{
+ H5SM_master_table_t *table = (H5SM_master_table_t *)_thing; /* Shared message table to encode */
+ uint8_t *image = (uint8_t *)_image; /* Pointer into raw data buffer */
+ uint32_t computed_chksum; /* Computed metadata checksum value */
+ size_t u; /* Counter variable */
- /* Get temporary pointer to buffer for serialized table */
- p = buf;
+ FUNC_ENTER_STATIC_NOERR
- /* Encode magic number */
- HDmemcpy(p, H5SM_TABLE_MAGIC, (size_t)H5_SIZEOF_MAGIC);
- p += H5_SIZEOF_MAGIC;
+ /* Check arguments */
+ HDassert(f);
+ HDassert(image);
+ HDassert(table);
+ HDassert(table->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(table->cache_info.type == H5AC_SOHM_TABLE);
+ HDassert(table->table_size == len);
- /* Encode each index header */
- for(u = 0; u < table->num_indexes; ++u) {
- /* Version for this list */
- *p++ = H5SM_LIST_VERSION;
+ /* Verify that we're writing version 0 of the table; this is the only
+ * version defined so far.
+ */
+ HDassert(H5F_SOHM_VERS(f) == HDF5_SHAREDHEADER_VERSION);
- /* Is message index a list or a B-tree? */
- *p++ = table->indexes[u].index_type;
+ /* Encode magic number */
+ HDmemcpy(image, H5SM_TABLE_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ image += H5_SIZEOF_MAGIC;
- /* Type of messages in the index */
- UINT16ENCODE(p, table->indexes[u].mesg_types);
+ /* Encode each index header */
+ for(u = 0; u < table->num_indexes; ++u) {
+ /* Version for this list */
+ *image++ = H5SM_LIST_VERSION;
- /* Minimum size of message to share */
- UINT32ENCODE(p, table->indexes[u].min_mesg_size);
+ /* Is message index a list or a B-tree? */
+ *image++ = table->indexes[u].index_type;
- /* List cutoff; fewer than this number and index becomes a list */
- UINT16ENCODE(p, table->indexes[u].list_max);
+ /* Type of messages in the index */
+ UINT16ENCODE(image, table->indexes[u].mesg_types);
- /* B-tree cutoff; more than this number and index becomes a B-tree */
- UINT16ENCODE(p, table->indexes[u].btree_min);
+ /* Minimum size of message to share */
+ UINT32ENCODE(image, table->indexes[u].min_mesg_size);
- /* Number of messages shared */
- UINT16ENCODE(p, table->indexes[u].num_messages);
+ /* List cutoff; fewer than this number and index becomes a list */
+ UINT16ENCODE(image, table->indexes[u].list_max);
- /* Address of the actual index */
- H5F_addr_encode(f, &p, table->indexes[u].index_addr);
+ /* B-tree cutoff; more than this number and index becomes a B-tree */
+ UINT16ENCODE(image, table->indexes[u].btree_min);
- /* Address of the index's heap */
- H5F_addr_encode(f, &p, table->indexes[u].heap_addr);
- } /* end for */
+ /* Number of messages shared */
+ UINT16ENCODE(image, table->indexes[u].num_messages);
- /* Compute checksum on buffer */
- computed_chksum = H5_checksum_metadata(buf, (table->table_size - H5SM_SIZEOF_CHECKSUM), 0);
- UINT32ENCODE(p, computed_chksum);
+ /* Address of the actual index */
+ H5F_addr_encode(f, &image, table->indexes[u].index_addr);
- /* Write the table to disk */
- HDassert((size_t)(p - buf) == table->table_size);
- if(H5F_block_write(f, H5FD_MEM_SOHM_TABLE, addr, table->table_size, dxpl_id, buf) < 0)
- HGOTO_ERROR(H5E_SOHM, H5E_CANTFLUSH, FAIL, "unable to save sohm table to disk")
+ /* Address of the index's heap */
+ H5F_addr_encode(f, &image, table->indexes[u].heap_addr);
+ } /* end for */
- table->cache_info.is_dirty = FALSE;
- } /* end if */
+ /* Compute checksum on buffer */
+ computed_chksum = H5_checksum_metadata(_image, (table->table_size - H5SM_SIZEOF_CHECKSUM), 0);
+ UINT32ENCODE(image, computed_chksum);
- if(destroy)
- if(H5SM_table_dest(f, table) < 0)
- HGOTO_ERROR(H5E_SOHM, H5E_CANTFREE, FAIL, "unable to destroy sohm table")
+ /* sanity check */
+ HDassert((size_t)(image - ((uint8_t *)_image)) == table->table_size);
-done:
- /* Release resources */
- if(wb && H5WB_unwrap(wb) < 0)
- HDONE_ERROR(H5E_SOHM, H5E_CLOSEERROR, FAIL, "can't close wrapped buffer")
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5SM__cache_table_serialize() */
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5SM_table_flush() */
+/*****************************************/
+/* no H5SM_cache_table_notify() function */
+/*****************************************/
/*-------------------------------------------------------------------------
- * Function: H5SM_table_dest
+ * Function: H5SM__cache_table_free_icr
+ *
+ * Purpose: Free memory used by the SOHM table.
*
- * Purpose: Frees memory used by the SOHM table.
+ * Note: The metadata cache sets the object's cache_info.magic to
+ * H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC before calling a free_icr
+ * callback (checked in assert).
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Success: SUCCEED
+ * Failure: FAIL
*
- * Programmer: James Laird
- * November 6, 2006
+ * Programmer: John Mainzer
+ * 7/28/14
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5SM_table_dest(H5F_t H5_ATTR_UNUSED *f, H5SM_master_table_t* table)
+H5SM__cache_table_free_icr(void *_thing)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ H5SM_master_table_t *table = (H5SM_master_table_t *)_thing; /* Shared message table to release */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
/* Check arguments */
HDassert(table);
- HDassert(table->indexes);
+ HDassert(table->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC);
+ HDassert(table->cache_info.type == H5AC_SOHM_TABLE);
/* Destroy Shared Object Header Message table */
if(H5SM_table_free(table) < 0)
@@ -375,104 +494,129 @@ H5SM_table_dest(H5F_t H5_ATTR_UNUSED *f, H5SM_master_table_t* table)
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5SM_table_dest() */
+} /* end H5SM_cache_table_free_icr() */
/*-------------------------------------------------------------------------
- * Function: H5SM_table_clear
+ * Function: H5SM__cache_list_get_load_size()
*
- * Purpose: Mark this table as no longer being dirty.
+ * Purpose: Return the on disk size of list of SOHM messages. In this case,
+ * we simply look up the size in the user data, and return that value
+ * in *image_len.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Success: SUCCEED
+ * Failure: FAIL
*
- * Programmer: James Laird
- * November 6, 2006
+ * Programmer: John Mainzer
+ * 7/28/14
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5SM_table_clear(H5F_t *f, H5SM_master_table_t *table, hbool_t destroy)
+H5SM__cache_list_get_load_size(const void *_image, void *_udata,
+ size_t *image_len, size_t *actual_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ const H5SM_list_cache_ud_t *udata = (const H5SM_list_cache_ud_t *)_udata; /* User data for callback */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC_NOERR
- /*
- * Check arguments.
- */
- HDassert(table);
-
- /* Reset the dirty flag. */
- table->cache_info.is_dirty = FALSE;
+ /* Check arguments */
+ HDassert(udata);
+ HDassert(udata->header);
+ HDassert(udata->header->list_size > 0);
+ HDassert(image_len);
- if(destroy)
- if(H5SM_table_dest(f, table) < 0)
- HGOTO_ERROR(H5E_SOHM, H5E_CANTFREE, FAIL, "unable to delete SOHM master table")
+ if(image == NULL)
+ *image_len = udata->header->list_size;
+ else {
+ HDassert(actual_len);
+ HDassert(*actual_len == *image_len);
+ }
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5SM_table_clear() */
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5SM__cache_list_get_load_size() */
/*-------------------------------------------------------------------------
- * Function: H5SM_table_size
+ * Function: H5SM__cache_list_verify_chksum
*
- * Purpose: Returns the size of the table encoded on disk.
+ * Purpose: Verify the computed checksum of the data structure is the
+ * same as the stored chksum.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Success: TRUE/FALSE
+ * Failure: Negative
*
- * Programmer: James Laird
- * November 6, 2006
+ * Programmer: Vailin Choi; Aug 2015
*
*-------------------------------------------------------------------------
*/
-static herr_t
-H5SM_table_size(const H5F_t H5_ATTR_UNUSED *f, const H5SM_master_table_t *table, size_t *size_ptr)
+htri_t
+H5SM__cache_list_verify_chksum(const void *_image, size_t H5_ATTR_UNUSED len, void *_udata)
{
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ H5SM_list_cache_ud_t *udata = (H5SM_list_cache_ud_t *)_udata; /* User data for callback */
+ size_t chk_size; /* Exact size of the node with checksum at the end */
+ uint32_t stored_chksum; /* Stored metadata checksum value */
+ uint32_t computed_chksum; /* Computed metadata checksum value */
+ htri_t ret_value = TRUE; /* Return value */
+
+ FUNC_ENTER_STATIC_NOERR
/* Check arguments */
- HDassert(f);
- HDassert(table);
- HDassert(size_ptr);
+ HDassert(image);
+ HDassert(udata);
- /* Set size value */
- *size_ptr = table->table_size;
+ /* Exact size with checksum at the end */
+ chk_size = H5SM_LIST_SIZE(udata->f, udata->header->num_messages);
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* end H5SM_table_size() */
+ /* Get stored and computed checksums */
+ H5F_get_checksums(image, chk_size, &stored_chksum, &computed_chksum);
+
+ if(stored_chksum != computed_chksum)
+ ret_value = FALSE;
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5SM__cache_list_verify_chksum() */
/*-------------------------------------------------------------------------
- * Function: H5SM_list_load
+ * Function: H5SM__cache_list_deserialize
*
- * Purpose: Loads a list of SOHM messages.
+ * Purpose: Given a buffer containing the on disk image of a list of
+ * SOHM message, deserialize the list, load it into a newly allocated
+ * instance of H5SM_list_t, and return a pointer to same.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Success: Pointer to in core representation
+ * Failure: NULL
*
- * Programmer: James Laird
- * November 6, 2006
+ * Programmer: John Mainzer
+ * 7/28/14
*
*-------------------------------------------------------------------------
*/
-static H5SM_list_t *
-H5SM_list_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
+static void *
+H5SM__cache_list_deserialize(const void *_image, size_t len, void *_udata,
+ hbool_t H5_ATTR_UNUSED *dirty)
{
- H5SM_list_t *list; /* The SOHM list being read in */
- H5SM_list_cache_ud_t *udata = (H5SM_list_cache_ud_t *)_udata; /* User data for callback */
- H5SM_bt2_ctx_t ctx; /* Message encoding context */
- H5WB_t *wb = NULL; /* Wrapped buffer for list index data */
- uint8_t lst_buf[H5SM_LST_BUF_SIZE]; /* Buffer for list index */
- uint8_t *buf; /* Reading buffer */
- uint8_t *p; /* Pointer into input buffer */
- size_t u; /* Counter variable for messages in list */
- size_t chk_size; /* Exact size with checksum at the end */
- H5SM_list_t *ret_value; /* Return value */
+ H5SM_list_t *list = NULL; /* The SOHM list being read in */
+ H5SM_list_cache_ud_t *udata = (H5SM_list_cache_ud_t *)_udata; /* User data for callback */
+ H5SM_bt2_ctx_t ctx; /* Message encoding context */
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into input buffer */
+ uint32_t stored_chksum; /* Stored metadata checksum value */
+ size_t u; /* Counter variable for messages in list */
+ void * ret_value; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
/* Check arguments */
+ HDassert(image);
+ HDassert(len > 0);
+ HDassert(udata);
HDassert(udata->header);
+ HDassert(udata->header->list_size == len);
+ HDassert(dirty);
/* Allocate space for the SOHM list data structure */
if(NULL == (list = H5FL_MALLOC(H5SM_list_t)))
@@ -484,41 +628,27 @@ H5SM_list_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
HGOTO_ERROR(H5E_SOHM, H5E_NOSPACE, NULL, "file allocation failed for SOHM list")
list->header = udata->header;
- /* Wrap the local buffer for serialized list index info */
- if(NULL == (wb = H5WB_wrap(lst_buf, sizeof(lst_buf))))
- HGOTO_ERROR(H5E_SOHM, H5E_CANTINIT, NULL, "can't wrap buffer")
-
- /* Get a pointer to a buffer that's large enough for serialized list index */
- if(NULL == (buf = (uint8_t *)H5WB_actual(wb, udata->header->list_size)))
- HGOTO_ERROR(H5E_SOHM, H5E_NOSPACE, NULL, "can't get actual buffer")
-
- /* Exact size with checksum at the end */
- chk_size = H5SM_LIST_SIZE(udata->f, udata->header->num_messages);
-
- /* Read and validate shared message list from disk */
- if(H5F_read_check_metadata(f, dxpl_id, H5FD_MEM_SOHM_INDEX, H5AC_SOHM_LIST_ID, addr, udata->header->list_size, chk_size, buf) < 0)
- HGOTO_ERROR(H5E_SOHM, H5E_BADVALUE, NULL, "incorrect metadata checksum for shared message list")
-
- /* Get temporary pointer to serialized list index */
- p = buf;
-
/* Check magic number */
- if(HDmemcmp(p, H5SM_LIST_MAGIC, (size_t)H5_SIZEOF_MAGIC))
+ if(HDmemcmp(image, H5SM_LIST_MAGIC, (size_t)H5_SIZEOF_MAGIC))
HGOTO_ERROR(H5E_SOHM, H5E_CANTLOAD, NULL, "bad SOHM list signature")
- p += H5_SIZEOF_MAGIC;
+ image += H5_SIZEOF_MAGIC;
/* Read messages into the list array */
ctx.sizeof_addr = H5F_SIZEOF_ADDR(udata->f);
for(u = 0; u < udata->header->num_messages; u++) {
- if(H5SM_message_decode(p, &(list->messages[u]), &ctx) < 0)
+ if(H5SM_message_decode(image, &(list->messages[u]), &ctx) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTLOAD, NULL, "can't decode shared message")
- p += H5SM_SOHM_ENTRY_SIZE(udata->f);
+
+ image += H5SM_SOHM_ENTRY_SIZE(udata->f);
} /* end for */
- /* Already decoded and compared stored checksum earlier, when reading */
+ /* checksum verification already done in verify_chksum cb */
+
+ /* Read in checksum */
+ UINT32DECODE(image, stored_chksum);
/* Sanity check */
- HDassert((size_t)(p - buf) <= (udata->header->list_size - H5_SIZEOF_CHKSUM));
+ HDassert((size_t)(image - (const uint8_t *)_image) <= udata->header->list_size);
/* Initialize the rest of the array */
for(u = udata->header->num_messages; u < udata->header->list_max; u++)
@@ -528,9 +658,6 @@ H5SM_list_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
ret_value = list;
done:
- /* Release resources */
- if(wb && H5WB_unwrap(wb) < 0)
- HDONE_ERROR(H5E_SOHM, H5E_CLOSEERROR, NULL, "can't close wrapped buffer")
if(!ret_value && list) {
if(list->messages)
list->messages = H5FL_ARR_FREE(H5SM_sohm_t, list->messages);
@@ -538,205 +665,158 @@ done:
} /* end if */
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5SM_list_load() */
+} /* end H5SM__cache_list_deserialize() */
/*-------------------------------------------------------------------------
- * Function: H5SM_list_flush
+ * Function: H5SM__cache_list_image_len
*
- * Purpose: Flush this list index.
+ * Purpose: Get the size of the shared message list on disk.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Success: SUCCEED
+ * Failure: FAIL
*
- * Programmer: James Laird
- * November 6, 2006
+ * Programmer: John Mainzer
+ * 7/28/14
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5SM_list_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5SM_list_t *list)
+H5SM__cache_list_image_len(const void *_thing, size_t *image_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr)
{
- H5WB_t *wb = NULL; /* Wrapped buffer for list index data */
- uint8_t lst_buf[H5SM_LST_BUF_SIZE]; /* Buffer for list index */
- herr_t ret_value = SUCCEED; /* Return value */
+ const H5SM_list_t *list = (const H5SM_list_t *)_thing; /* Shared message list to query */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC_NOERR
- /* check arguments */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
+ /* Check arguments */
HDassert(list);
+ HDassert(list->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(list->cache_info.type == H5AC_SOHM_LIST);
HDassert(list->header);
+ HDassert(image_len);
- if(list->cache_info.is_dirty) {
- H5SM_bt2_ctx_t ctx; /* Message encoding context */
- uint8_t *buf; /* Temporary buffer */
- uint8_t *p; /* Pointer into raw data buffer */
- uint32_t computed_chksum; /* Computed metadata checksum value */
- size_t mesgs_written; /* Number of messages written to list */
- size_t u; /* Local index variable */
-
- /* Wrap the local buffer for serialized list index info */
- if(NULL == (wb = H5WB_wrap(lst_buf, sizeof(lst_buf))))
- HGOTO_ERROR(H5E_SOHM, H5E_CANTINIT, FAIL, "can't wrap buffer")
-
- /* Get a pointer to a buffer that's large enough for serialized list index */
- if(NULL == (buf = (uint8_t *)H5WB_actual(wb, list->header->list_size)))
- HGOTO_ERROR(H5E_SOHM, H5E_NOSPACE, FAIL, "can't get actual buffer")
-
- /* Get temporary pointer to buffer for serialized list index */
- p = buf;
-
- /* Encode magic number */
- HDmemcpy(p, H5SM_LIST_MAGIC, (size_t)H5_SIZEOF_MAGIC);
- p += H5_SIZEOF_MAGIC;
-
- /* Write messages from the messages array to disk */
- mesgs_written = 0;
- ctx.sizeof_addr = H5F_SIZEOF_ADDR(f);
- for(u = 0; u < list->header->list_max && mesgs_written < list->header->num_messages; u++) {
- if(list->messages[u].location != H5SM_NO_LOC) {
- if(H5SM_message_encode(p, &(list->messages[u]), &ctx) < 0)
- HGOTO_ERROR(H5E_SOHM, H5E_CANTFLUSH, FAIL, "unable to write shared message to disk")
-
- p += H5SM_SOHM_ENTRY_SIZE(f);
- ++mesgs_written;
- } /* end if */
- } /* end for */
- HDassert(mesgs_written == list->header->num_messages);
-
- /* Compute checksum on buffer */
- computed_chksum = H5_checksum_metadata(buf, (size_t)(p - buf), 0);
- UINT32ENCODE(p, computed_chksum);
-#ifdef H5_CLEAR_MEMORY
-HDmemset(p, 0, (list->header->list_size - (size_t)(p - buf)));
-#endif /* H5_CLEAR_MEMORY */
+ *image_len = list->header->list_size;
- /* Write the list to disk */
- HDassert((size_t)(p - buf) <= list->header->list_size);
- if(H5F_block_write(f, H5FD_MEM_SOHM_INDEX, addr, list->header->list_size, dxpl_id, buf) < 0)
- HGOTO_ERROR(H5E_SOHM, H5E_CANTFLUSH, FAIL, "unable to save sohm table to disk")
-
- list->cache_info.is_dirty = FALSE;
- } /* end if */
-
- if(destroy)
- if(H5SM_list_dest(f, list) < 0)
- HGOTO_ERROR(H5E_SOHM, H5E_CANTFREE, FAIL, "unable to destroy list")
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5SM__cache_list_image_len() */
-done:
- /* Release resources */
- if(wb && H5WB_unwrap(wb) < 0)
- HDONE_ERROR(H5E_SOHM, H5E_CLOSEERROR, FAIL, "can't close wrapped buffer")
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5SM_list_flush() */
+/**************************************/
+/* no H5SM_cache_list_pre_serialize() */
+/**************************************/
/*-------------------------------------------------------------------------
- * Function: H5SM_list_dest
+ * Function: H5SM__cache_list_serialize
*
- * Purpose: Frees all memory used by the list.
+ * Purpose: Serialize the contents of the supplied shared message list, and
+ * load this data into the supplied buffer.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Success: SUCCEED
+ * Failure: FAIL
*
- * Programmer: James Laird
- * November 6, 2006
+ * Programmer: John Mainzer
+ * 7/28/14
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5SM_list_dest(H5F_t *f, H5SM_list_t* list)
+H5SM__cache_list_serialize(const H5F_t *f, void *_image, size_t len,
+ void *_thing)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ H5SM_list_t *list = (H5SM_list_t *)_thing ; /* Instance being serialized */
+ H5SM_bt2_ctx_t ctx; /* Message encoding context */
+ uint8_t *image = (uint8_t *)_image; /* Pointer into raw data buffer */
+ uint32_t computed_chksum; /* Computed metadata checksum value */
+ size_t mesgs_serialized; /* Number of messages serialized */
+ size_t u; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
- /* Sanity check */
+ /* Check arguments */
+ HDassert(f);
+ HDassert(image);
HDassert(list);
+ HDassert(list->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(list->cache_info.type == H5AC_SOHM_LIST);
HDassert(list->header);
- HDassert(list->messages);
+ HDassert(list->header->list_size == len);
+
+ /* Encode magic number */
+ HDmemcpy(image, H5SM_LIST_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ image += H5_SIZEOF_MAGIC;
+
+ /* serialize messages from the messages array */
+ mesgs_serialized = 0;
+ ctx.sizeof_addr = H5F_SIZEOF_ADDR(f);
+ for(u = 0; ((u < list->header->list_max) && (mesgs_serialized < list->header->num_messages)); u++) {
+ if(list->messages[u].location != H5SM_NO_LOC) {
+ if(H5SM_message_encode(image, &(list->messages[u]), &ctx) < 0)
+ HGOTO_ERROR(H5E_SOHM, H5E_CANTFLUSH, FAIL, "unable to serialize shared message")
+
+ image += H5SM_SOHM_ENTRY_SIZE(f);
+ ++mesgs_serialized;
+ } /* end if */
+ } /* end for */
- /* If we're going to free the space on disk, the address must be valid */
- HDassert(!list->cache_info.free_file_space_on_destroy || H5F_addr_defined(list->cache_info.addr));
+ HDassert(mesgs_serialized == list->header->num_messages);
- /* Check for freeing file space for shared message index list */
- if(list->cache_info.free_file_space_on_destroy) {
- /* Release the space on disk */
- /* (XXX: Nasty usage of internal DXPL value! -QAK) */
- if(H5MF_xfree(f, H5FD_MEM_SOHM_INDEX, H5AC_dxpl_id, list->cache_info.addr, (hsize_t)list->header->list_size) < 0)
- HGOTO_ERROR(H5E_SOHM, H5E_NOSPACE, FAIL, "unable to free shared message list")
- } /* end if */
+ /* Compute checksum on buffer */
+ computed_chksum = H5_checksum_metadata(_image, (size_t)(image - (uint8_t *)_image), 0);
+ UINT32ENCODE(image, computed_chksum);
- /* Destroy Shared Object Header Message list */
- if(H5SM_list_free(list) < 0)
- HGOTO_ERROR(H5E_SOHM, H5E_CANTRELEASE, FAIL, "unable to free shared message list")
+#ifdef H5_CLEAR_MEMORY
+ HDmemset(image, 0, (list->header->list_size - (size_t)(image - (uint8_t *)_image)));
+#endif /* H5_CLEAR_MEMORY */
+
+ /* sanity check */
+ HDassert((size_t)(image - (uint8_t *)_image) <= list->header->list_size);
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5SM_list_dest() */
+} /* end H5SM__cache_list_serialize() */
+
+/****************************************/
+/* no H5SM_cache_list_notify() function */
+/****************************************/
/*-------------------------------------------------------------------------
- * Function: H5SM_list_clear
+ * Function: H5SM__cache_list_free_icr
+ *
+ * Purpose: Free all memory used by the list.
*
- * Purpose: Marks a list as not dirty.
+ * Note: The metadata cache sets the object's cache_info.magic to
+ * H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC before calling a free_icr
+ * callback (checked in assert).
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Success: SUCCEED
+ * Failure: FAIL
*
- * Programmer: James Laird
- * November 6, 2006
+ * Programmer: John Mainzer
+ * 7/28/14
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5SM_list_clear(H5F_t *f, H5SM_list_t *list, hbool_t destroy)
+H5SM__cache_list_free_icr(void *_thing)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ H5SM_list_t *list = (H5SM_list_t *)_thing; /* Shared message list to release */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
/* Check arguments */
HDassert(list);
+ HDassert(list->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC);
+ HDassert(list->cache_info.type == H5AC_SOHM_LIST);
- /* Reset the dirty flag. */
- list->cache_info.is_dirty = FALSE;
-
- if(destroy)
- if(H5SM_list_dest(f, list) < 0)
- HGOTO_ERROR(H5E_SOHM, H5E_CANTFREE, FAIL, "unable to destroy SOHM list")
+ /* Destroy Shared Object Header Message list */
+ if(H5SM_list_free(list) < 0)
+ HGOTO_ERROR(H5E_SOHM, H5E_CANTRELEASE, FAIL, "unable to free shared message list")
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end of H5SM_list_clear() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5SM_list_size
- *
- * Purpose: Gets the size of a list on disk.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: James Laird
- * November 6, 2006
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5SM_list_size(const H5F_t H5_ATTR_UNUSED *f, const H5SM_list_t *list, size_t *size_ptr)
-{
- FUNC_ENTER_NOAPI_NOINIT_NOERR
-
- /* check arguments */
- HDassert(f);
- HDassert(list);
- HDassert(list->header);
- HDassert(size_ptr);
-
- /* Set size value */
- *size_ptr = list->header->list_size;
-
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* end H5SM_list_size() */
+} /* end H5O_cache_list_free_icr() */
diff --git a/src/H5SMtest.c b/src/H5SMtest.c
index 12ed766..c4e02bc 100644
--- a/src/H5SMtest.c
+++ b/src/H5SMtest.c
@@ -98,7 +98,7 @@ H5SM_get_mesg_count_test(H5F_t *f, hid_t dxpl_id, unsigned type_id,
cache_udata.f = f;
/* Look up the master SOHM table */
- if(NULL == (table = (H5SM_master_table_t *)H5AC_protect(f, dxpl_id, H5AC_SOHM_TABLE, H5F_SOHM_ADDR(f), &cache_udata, H5AC_READ)))
+ if(NULL == (table = (H5SM_master_table_t *)H5AC_protect(f, dxpl_id, H5AC_SOHM_TABLE, H5F_SOHM_ADDR(f), &cache_udata, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTPROTECT, FAIL, "unable to load SOHM master table")
/* Find the correct index for this message type */