summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2017-01-29 07:21:22 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2017-01-29 07:21:22 (GMT)
commit3ad18072eba378ca1f598d33cc83587e8a76880f (patch)
tree63f600947a8d56c26a7b850ebb41fb8e688ecab9
parent1949d5756d424be0b23fc127fc99140374a7dd13 (diff)
downloadhdf5-3ad18072eba378ca1f598d33cc83587e8a76880f.zip
hdf5-3ad18072eba378ca1f598d33cc83587e8a76880f.tar.gz
hdf5-3ad18072eba378ca1f598d33cc83587e8a76880f.tar.bz2
Add missing files
-rw-r--r--src/H5Cimage.c4100
-rw-r--r--src/H5Cprefetched.c352
-rw-r--r--src/H5Ocache_image.c337
-rw-r--r--test/cache_image.c6490
-rw-r--r--test/genall5.c3893
-rw-r--r--test/genall5.h53
6 files changed, 15225 insertions, 0 deletions
diff --git a/src/H5Cimage.c b/src/H5Cimage.c
new file mode 100644
index 0000000..dec8283
--- /dev/null
+++ b/src/H5Cimage.c
@@ -0,0 +1,4100 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the files COPYING and Copyright.html. COPYING can be found at the root *
+ * of the source code distribution tree; Copyright.html can be found at the *
+ * root level of an installed copy of the electronic HDF5 document set and *
+ * is linked from the top-level documents page. It can also be found at *
+ * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: H5Cimage.c
+ * July 20, 2015
+ * John Mainzer
+ *
+ * Purpose: Functions in this file are specific to the implementation
+ * of the metadata cache image feature.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#include "H5Cmodule.h" /* This source code file is part of the H5C module */
+#define H5F_FRIEND /*suppress error about including H5Fpkg */
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#ifdef H5_HAVE_PARALLEL
+#define H5AC_FRIEND /*suppress error about including H5ACpkg */
+#include "H5ACpkg.h" /* Metadata cache */
+#endif /* H5_HAVE_PARALLEL */
+#include "H5Cpkg.h" /* Cache */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Fpkg.h" /* Files */
+#include "H5FDprivate.h" /* File drivers */
+#include "H5FLprivate.h" /* Free Lists */
+#include "H5MFprivate.h" /* File memory management */
+#include "H5MMprivate.h" /* Memory management */
+
+
+/****************/
+/* Local 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 */
+
+/* Cache image buffer components, on disk */
+#define H5C__MDCI_BLOCK_SIGNATURE "MDCI"
+#define H5C__MDCI_BLOCK_SIGNATURE_LEN 4
+#define H5C__MDCI_BLOCK_VERSION_0 0
+
+/* Metadata cache image header flags -- max 8 bits */
+#define H5C__MDCI_HEADER_HAVE_RESIZE_STATUS 0x01
+
+/* Metadata cache image entry flags -- max 8 bits */
+#define H5C__MDCI_ENTRY_DIRTY_FLAG 0x01
+#define H5C__MDCI_ENTRY_IN_LRU_FLAG 0x02
+#define H5C__MDCI_ENTRY_IS_FD_PARENT_FLAG 0x04
+#define H5C__MDCI_ENTRY_IS_FD_CHILD_FLAG 0x08
+
+/* Limits on flush dependency values, stored in 16-bit values on disk */
+#define H5C__MDCI_MAX_FD_CHILDREN USHRT_MAX
+#define H5C__MDCI_MAX_FD_PARENTS USHRT_MAX
+
+/* Values for image entry magic field */
+#define H5C_IMAGE_ENTRY_T_MAGIC 0x005CAC08
+#define H5C_IMAGE_ENTRY_T_BAD_MAGIC 0xBeefDead
+
+/* Maximum ring allowed in image */
+#define H5C_MAX_RING_IN_IMAGE 3
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+/* Helper routines */
+static size_t H5C__cache_image_block_entry_header_size(const H5F_t *f);
+static size_t H5C__cache_image_block_header_size(const H5F_t *f);
+static herr_t H5C__decode_cache_image_buffer(const H5F_t *f, H5C_t *cache_ptr);
+static herr_t H5C__decode_cache_image_header(const H5F_t *f,
+ H5C_t *cache_ptr, const uint8_t **buf);
+static herr_t H5C__decode_cache_image_entry(const H5F_t *f,
+ const H5C_t *cache_ptr, const uint8_t **buf, unsigned entry_num);
+static herr_t H5C__destroy_pf_entry_child_flush_deps(H5C_t *cache_ptr,
+ H5C_cache_entry_t *pf_entry_ptr, H5C_cache_entry_t **fd_children);
+static herr_t H5C__encode_cache_image_header(const H5F_t *f,
+ const H5C_t *cache_ptr, uint8_t **buf);
+static herr_t H5C__encode_cache_image_entry(H5F_t *f, H5C_t *cache_ptr,
+ uint8_t **buf, unsigned entry_num);
+static herr_t H5C__prep_for_file_close__compute_fd_heights(const H5C_t *cache_ptr);
+static void H5C__prep_for_file_close__compute_fd_heights_real(
+ H5C_cache_entry_t *entry_ptr, uint32_t fd_height);
+static herr_t H5C__prep_for_file_close__setup_image_entries_array(H5C_t *cache_ptr);
+static herr_t H5C__prep_for_file_close__scan_entries(const H5F_t *f,
+ H5C_t *cache_ptr);
+static herr_t H5C__reconstruct_cache_contents(H5F_t *f, hid_t dxpl_id,
+ H5C_t *cache_ptr);
+static H5C_cache_entry_t *H5C__reconstruct_cache_entry(H5C_t *cache_ptr,
+ unsigned index);
+static herr_t H5C__serialize_cache(H5F_t *f, hid_t dxpl_id);
+static herr_t H5C__serialize_ring(H5F_t *f, hid_t dxpl_id,
+ H5C_ring_t ring);
+static herr_t H5C__serialize_single_entry(H5F_t *f, hid_t dxpl_id,
+ H5C_t *cache_ptr, H5C_cache_entry_t *entry_ptr,
+ hbool_t *restart_list_scan_ptr);
+static herr_t H5C__write_cache_image_superblock_msg(H5F_t *f, hid_t dxpl_id,
+ hbool_t create);
+static herr_t H5C__read_cache_image(H5F_t * f, hid_t dxpl_id, const H5C_t *cache_ptr);
+static herr_t H5C__write_cache_image(H5F_t *f, hid_t dxpl_id, const H5C_t *cache_ptr);
+static herr_t H5C__construct_cache_image_buffer(H5F_t *f, H5C_t *cache_ptr);
+static herr_t H5C__free_image_entries_array(H5C_t *cache_ptr);
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+/* Declare a free list to manage H5C_cache_entry_t objects */
+H5FL_DEFINE(H5C_cache_entry_t);
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C_cache_image_status()
+ *
+ * Purpose: Examine the metadata cache associated with the supplied
+ * instance of H5F_t to determine whether the load of a
+ * cache image has either been queued ir executed, and if
+ * construction of a cache image has been requested.
+ *
+ * This done, it set *load_ci_ptr to TRUE if a cache image
+ * has either been loaded or a load has been requested, and
+ * to FALSE otherwise.
+ *
+ * Similarly, set *write_ci_ptr to TRUE if construction of
+ * a cache image has been requested, and to FALSE otherwise.
+ *
+ * Return: SUCCEED on success, and FAIL on failure.
+ *
+ * Programmer: John Mainzer
+ * 12/29/16
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5C_cache_image_status(H5F_t * f, hbool_t *load_ci_ptr, hbool_t *write_ci_ptr)
+{
+ H5C_t * cache_ptr;
+
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ /* Sanity checks */
+ HDassert(f);
+ HDassert(f->shared);
+ cache_ptr = f->shared->cache;
+ HDassert(cache_ptr);
+ HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
+ HDassert(load_ci_ptr);
+ HDassert(write_ci_ptr);
+
+ *load_ci_ptr = cache_ptr->load_image || cache_ptr->image_loaded;
+ *write_ci_ptr = cache_ptr->image_ctl.generate_image;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5C_cache_image_status() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__construct_cache_image_buffer()
+ *
+ * Purpose: Allocate a buffer of size cache_ptr->image_len, and
+ * load it with an image of the metadata cache image block.
+ *
+ * Note that by the time this function is called, the cache
+ * should have removed all entries from its data structures.
+ *
+ * Return: SUCCEED on success, and FAIL on failure.
+ *
+ * Programmer: John Mainzer
+ * 8/5/15
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__construct_cache_image_buffer(H5F_t * f, H5C_t *cache_ptr)
+{
+ uint8_t * p; /* Pointer into image buffer */
+ uint32_t chksum;
+ unsigned u; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(f);
+ HDassert(f->shared);
+ HDassert(cache_ptr == f->shared->cache);
+ HDassert(cache_ptr);
+ HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
+ HDassert(cache_ptr->close_warning_received);
+ HDassert(cache_ptr->image_ctl.generate_image);
+ HDassert(cache_ptr->num_entries_in_image > 0);
+ HDassert(cache_ptr->index_len == 0);
+ HDassert(cache_ptr->image_data_len > 0);
+ HDassert(cache_ptr->image_data_len <= cache_ptr->image_len);
+
+ /* Allocate the buffer in which to construct the cache image block */
+ if(NULL == (cache_ptr->image_buffer = H5MM_malloc(cache_ptr->image_len + 1)))
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, "memory allocation failed for cache image buffer")
+
+ /* Construct the cache image block header image */
+ p = (uint8_t *)cache_ptr->image_buffer;
+ if(H5C__encode_cache_image_header(f, cache_ptr, &p) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTENCODE, FAIL, "header image construction failed")
+ HDassert((size_t)(p - (uint8_t *)cache_ptr->image_buffer) < cache_ptr->image_data_len);
+
+ /* Construct the cache entry images */
+ for(u = 0; u < cache_ptr->num_entries_in_image; u++)
+ if(H5C__encode_cache_image_entry(f, cache_ptr, &p, u) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTENCODE, FAIL, "entry image construction failed")
+ HDassert((size_t)(p - (uint8_t *)cache_ptr->image_buffer) < cache_ptr->image_data_len);
+
+ /* Construct the adaptive resize status image -- not yet */
+
+ /* Compute the checksum and encode */
+ chksum = H5_checksum_metadata(cache_ptr->image_buffer, (size_t)(cache_ptr->image_data_len - H5F_SIZEOF_CHKSUM), 0);
+ UINT32ENCODE(p, chksum);
+ HDassert((size_t)(p - (uint8_t *)cache_ptr->image_buffer) == cache_ptr->image_data_len);
+ HDassert((size_t)(p - (uint8_t *)cache_ptr->image_buffer) <= cache_ptr->image_len);
+
+#ifndef NDEBUG
+ /* validate the metadata cache image we just constructed by decoding it
+ * and comparing the result with the original data.
+ */
+ {
+ uint32_t old_chksum;
+ const uint8_t * q;
+ H5C_t * fake_cache_ptr = NULL;
+ unsigned v;
+ herr_t status; /* Status from decoding */
+
+ fake_cache_ptr = (H5C_t *)H5MM_malloc(sizeof(H5C_t));
+ HDassert(fake_cache_ptr);
+ fake_cache_ptr->magic = H5C__H5C_T_MAGIC;
+
+ /* needed for sanity checks */
+ fake_cache_ptr->image_len = cache_ptr->image_len;
+ q = (const uint8_t *)cache_ptr->image_buffer;
+ status = H5C__decode_cache_image_header(f, fake_cache_ptr, &q);
+ HDassert(status >= 0);
+
+ HDassert(NULL != p);
+ HDassert(fake_cache_ptr->num_entries_in_image == cache_ptr->num_entries_in_image);
+
+ fake_cache_ptr->image_entries = (H5C_image_entry_t *)H5MM_malloc(sizeof(H5C_image_entry_t) *
+ (size_t)(fake_cache_ptr->num_entries_in_image + 1));
+ HDassert(fake_cache_ptr->image_entries);
+
+ for(u = 0; u < fake_cache_ptr->num_entries_in_image; u++) {
+ (fake_cache_ptr->image_entries)[u].magic = H5C_IMAGE_ENTRY_T_MAGIC;
+ (fake_cache_ptr->image_entries)[u].image_ptr = NULL;
+
+ /* touch up f->shared->cache to satisfy sanity checks... */
+ f->shared->cache = fake_cache_ptr;
+ status = H5C__decode_cache_image_entry(f, fake_cache_ptr, &q, u);
+ HDassert(status >= 0);
+
+ /* ...and then return f->shared->cache to its correct value */
+ f->shared->cache = cache_ptr;
+
+ /* verify expected contents */
+ HDassert((cache_ptr->image_entries)[u].addr == (fake_cache_ptr->image_entries)[u].addr);
+ HDassert((cache_ptr->image_entries)[u].size == (fake_cache_ptr->image_entries)[u].size);
+ HDassert((cache_ptr->image_entries)[u].type_id == (fake_cache_ptr->image_entries)[u].type_id);
+ HDassert((cache_ptr->image_entries)[u].lru_rank == (fake_cache_ptr->image_entries)[u].lru_rank);
+ HDassert((cache_ptr->image_entries)[u].is_dirty == (fake_cache_ptr->image_entries)[u].is_dirty);
+ /* don't check image_fd_height as it is not stored in
+ * the metadata cache image block.
+ */
+ HDassert((cache_ptr->image_entries)[u].fd_child_count == (fake_cache_ptr->image_entries)[u].fd_child_count);
+ HDassert((cache_ptr->image_entries)[u].fd_dirty_child_count == (fake_cache_ptr->image_entries)[u].fd_dirty_child_count);
+ HDassert((cache_ptr->image_entries)[u].fd_parent_count == (fake_cache_ptr->image_entries)[u].fd_parent_count);
+
+ for(v = 0; v < (cache_ptr->image_entries)[u].fd_parent_count; v++)
+ HDassert((cache_ptr->image_entries)[u].fd_parent_addrs[v] == (fake_cache_ptr->image_entries)[u].fd_parent_addrs[v]);
+
+ /* free the fd_parent_addrs array if it exists */
+ if((fake_cache_ptr->image_entries)[u].fd_parent_addrs) {
+ HDassert((fake_cache_ptr->image_entries)[u].fd_parent_count > 0);
+ (fake_cache_ptr->image_entries)[u].fd_parent_addrs = (haddr_t *)H5MM_xfree((fake_cache_ptr->image_entries)[u].fd_parent_addrs);
+ (fake_cache_ptr->image_entries)[u].fd_parent_count = 0;
+ } /* end if */
+ else
+ HDassert((fake_cache_ptr->image_entries)[u].fd_parent_count == 0);
+
+ HDassert((cache_ptr->image_entries)[u].image_ptr);
+ HDassert((fake_cache_ptr->image_entries)[u].image_ptr);
+ HDassert(!HDmemcmp((cache_ptr->image_entries)[u].image_ptr,
+ (fake_cache_ptr->image_entries)[u].image_ptr,
+ (cache_ptr->image_entries)[u].size));
+
+ (fake_cache_ptr->image_entries)[u].image_ptr = H5MM_xfree((fake_cache_ptr->image_entries)[u].image_ptr);
+ } /* end for */
+
+ HDassert((size_t)(q - (const uint8_t *)cache_ptr->image_buffer) == cache_ptr->image_data_len - H5F_SIZEOF_CHKSUM);
+
+ /* compute the checksum */
+ old_chksum = chksum;
+ chksum = H5_checksum_metadata(cache_ptr->image_buffer, (size_t)(cache_ptr->image_data_len - H5F_SIZEOF_CHKSUM), 0);
+ HDassert(chksum == old_chksum);
+
+ fake_cache_ptr->image_entries = (H5C_image_entry_t *)H5MM_xfree(fake_cache_ptr->image_entries);
+ fake_cache_ptr = (H5C_t *)H5MM_xfree(fake_cache_ptr);
+ } /* end block */
+#endif /* NDEBUG */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__construct_cache_image_buffer() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__generate_cache_image()
+ *
+ * Purpose: Generate the cache image and write it to the file, if
+ * directed.
+ *
+ * Return: SUCCEED on success, and FAIL on failure.
+ *
+ * Programmer: Quincey Koziol
+ * 1/26/17
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5C__generate_cache_image(H5F_t *f, hid_t dxpl_id, H5C_t *cache_ptr)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ /* Sanity checks */
+ HDassert(f);
+ HDassert(f->shared);
+ HDassert(cache_ptr == f->shared->cache);
+ HDassert(cache_ptr);
+ HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
+
+ /* Construct cache image */
+ if(H5C__construct_cache_image_buffer(f, cache_ptr) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't create metadata cache image")
+
+ /* Free image entries array */
+ if(H5C__free_image_entries_array(cache_ptr) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't free image entries array")
+
+ /* Write cache image block if so configured */
+ if(cache_ptr->image_ctl.flags & H5C_CI__GEN_MDC_IMAGE_BLK) {
+ if(H5C__write_cache_image(f, dxpl_id, cache_ptr) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't write metadata cache image block to file")
+
+ H5C__UPDATE_STATS_FOR_CACHE_IMAGE_CREATE(cache_ptr);
+ } /* end if */
+
+ /* Free cache image buffer */
+ HDassert(cache_ptr->image_buffer);
+ cache_ptr->image_buffer = H5MM_xfree(cache_ptr->image_buffer);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__generate_cache_image() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__deserialize_prefetched_entry()
+ *
+ * Purpose: Deserialize the supplied prefetched entry entry, and return
+ * a pointer to the deserialized entry in *entry_ptr_ptr.
+ * If successful, remove the prefetched entry from the cache,
+ * and free it. Insert the deserialized entry into the cache.
+ *
+ * Note that the on disk image of the entry is not freed --
+ * a pointer to it is stored in the deserialized entries'
+ * image_ptr field, and its image_up_to_date field is set to
+ * TRUE unless the entry is dirtied by the deserialize call.
+ *
+ * If the prefetched entry is a flush dependency child,
+ * destroy that flush dependency prior to calling the
+ * deserialize callback. If appropriate, the flush dependency
+ * relationship will be recreated by the cache client.
+ *
+ * If the prefetched entry is a flush dependency parent,
+ * destroy the flush dependency relationship with all its
+ * children. As all these children must be prefetched entries,
+ * recreate these flush dependency relationships with
+ * deserialized entry after it is inserted in the cache.
+ *
+ * Since deserializing a prefetched entry is semantically
+ * equivalent to a load, issue an entry loaded nofification
+ * if the notify callback is defined.
+ *
+ * Return: SUCCEED on success, and FAIL on failure.
+ *
+ * Note that *entry_ptr_ptr is undefined on failure.
+ *
+ * Programmer: John Mainzer, 8/10/15
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5C__deserialize_prefetched_entry(H5F_t *f, hid_t dxpl_id, H5C_t *cache_ptr,
+ H5C_cache_entry_t **entry_ptr_ptr, const H5C_class_t *type,
+ haddr_t addr, void *udata)
+{
+ hbool_t dirty = FALSE; /* Flag indicating whether thing was
+ * dirtied during deserialize
+ */
+ size_t len; /* Size of image in file */
+ void * thing = NULL; /* Pointer to thing loaded */
+ H5C_cache_entry_t * pf_entry_ptr; /* pointer to the prefetched entry */
+ /* supplied in *entry_ptr_ptr. */
+ H5C_cache_entry_t * ds_entry_ptr; /* Alias for thing loaded, as cache
+ * entry
+ */
+ H5C_cache_entry_t** fd_children = NULL; /* Pointer to a dynamically */
+ /* allocated array of pointers to */
+ /* the flush dependency children of */
+ /* the prefetched entry, or NULL if */
+ /* that array does not exist. */
+ unsigned flush_flags = (H5C__FLUSH_INVALIDATE_FLAG |
+ H5C__FLUSH_CLEAR_ONLY_FLAG);
+ int i;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ /* sanity checks */
+ HDassert(f);
+ HDassert(f->shared);
+ HDassert(f->shared->cache);
+ HDassert(f->shared->cache == cache_ptr);
+ HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
+ HDassert(entry_ptr_ptr);
+ HDassert(*entry_ptr_ptr);
+ pf_entry_ptr = *entry_ptr_ptr;
+ HDassert(pf_entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(pf_entry_ptr->type);
+ HDassert(pf_entry_ptr->type->id == H5AC_PREFETCHED_ENTRY_ID);
+ HDassert(pf_entry_ptr->prefetched);
+ HDassert(pf_entry_ptr->image_up_to_date);
+ HDassert(pf_entry_ptr->image_ptr);
+ HDassert(pf_entry_ptr->size > 0);
+ HDassert(pf_entry_ptr->addr == addr);
+ HDassert(type);
+ HDassert(type->id == pf_entry_ptr->prefetch_type_id);
+ HDassert(type->mem_type == cache_ptr->class_table_ptr[type->id]->mem_type);
+
+ /* verify absence of prohibited or unsupported type flag combinations */
+ HDassert(!(type->flags & H5C__CLASS_SKIP_READS));
+
+ /* Can't see how skip reads could be usefully combined with
+ * either the speculative read flag. Hence disallow.
+ */
+ HDassert(!((type->flags & H5C__CLASS_SKIP_READS) &&
+ (type->flags & H5C__CLASS_SPECULATIVE_LOAD_FLAG)));
+
+ HDassert(H5F_addr_defined(addr));
+ HDassert(type->get_initial_load_size);
+ HDassert(type->deserialize);
+
+ /* if *pf_entry_ptr is a flush dependency child, destroy all such
+ * relationships now. The client will restore the relationship(s) with
+ * the deserialized entry if appropriate.
+ */
+ for(i = (int)(pf_entry_ptr->fd_parent_count) - 1; i >= 0; i--) {
+ HDassert(pf_entry_ptr->flush_dep_parent);
+ HDassert(pf_entry_ptr->flush_dep_parent[i]);
+ HDassert(pf_entry_ptr->flush_dep_parent[i]->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(pf_entry_ptr->flush_dep_parent[i]->flush_dep_nchildren > 0);
+ HDassert(pf_entry_ptr->fd_parent_addrs);
+ HDassert(pf_entry_ptr->flush_dep_parent[i]->addr == pf_entry_ptr->fd_parent_addrs[i]);
+
+ if(H5C_destroy_flush_dependency(pf_entry_ptr->flush_dep_parent[i], pf_entry_ptr) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTUNDEPEND, FAIL, "can't destroy pf entry parent flush dependency")
+
+ pf_entry_ptr->fd_parent_addrs[i] = HADDR_UNDEF;
+ } /* end for */
+ HDassert(pf_entry_ptr->flush_dep_nparents == 0);
+
+ /* If *pf_entry_ptr is a flush dependency parent, destroy its flush
+ * dependency relationships with all its children (which must be
+ * prefetched entries as well).
+ *
+ * These flush dependency relationships will have to be restored
+ * after the deserialized entry is inserted into the cache in order
+ * to transfer these relationships to the new entry. Hence save the
+ * pointers to the flush dependency children of *pf_enty_ptr for later
+ * use.
+ */
+ if(pf_entry_ptr->fd_child_count > 0) {
+ if(NULL == (fd_children = (H5C_cache_entry_t **)H5MM_calloc(sizeof(H5C_cache_entry_t **) * (size_t)(pf_entry_ptr->fd_child_count + 1))))
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, "memory allocation failed for fd child ptr array")
+
+ if(H5C__destroy_pf_entry_child_flush_deps(cache_ptr, pf_entry_ptr, fd_children) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTUNDEPEND, FAIL, "can't destroy pf entry child flush dependency(s).")
+ } /* end if */
+
+ /* Since the size of the on disk image is known exactly, there is
+ * no need for either a call to the get_initial_load_size() callback,
+ * or retries if the H5C__CLASS_SPECULATIVE_LOAD_FLAG flag is set.
+ * Similarly, there is no need to clamp possible reads beyond
+ * EOF.
+ */
+ len = pf_entry_ptr->size;
+
+ /* Deserialize the prefetched on-disk image of the entry into the
+ * native memory form
+ */
+ if(NULL == (thing = type->deserialize(pf_entry_ptr->image_ptr, len, udata, &dirty)))
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTLOAD, FAIL, "Can't deserialize image")
+
+ ds_entry_ptr = (H5C_cache_entry_t *)thing;
+
+ /* In general, an entry should be clean just after it is loaded.
+ *
+ * However, when this code is used in the metadata cache, it is
+ * possible that object headers will be dirty at this point, as
+ * the deserialize function will alter object headers if necessary to
+ * fix an old bug.
+ *
+ * In the following assert:
+ *
+ * HDassert( ( dirty == FALSE ) || ( type->id == 5 || type->id == 6 ) );
+ *
+ * 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.
+ *
+ * Note that at present, dirty can't be set to true with prefetched
+ * entries. However this may change, so include this functionality
+ * against that posibility.
+ *
+ * Also, note that it is possible for a prefetched entry to be dirty --
+ * hence the value assigned to ds_entry_ptr->is_dirty below.
+ */
+
+ HDassert( ( dirty == FALSE ) || ( type->id == 5 || type->id == 6) );
+
+ ds_entry_ptr->magic = H5C__H5C_CACHE_ENTRY_T_MAGIC;
+ ds_entry_ptr->cache_ptr = f->shared->cache;
+ ds_entry_ptr->addr = addr;
+ ds_entry_ptr->size = len;
+ HDassert(ds_entry_ptr->size < H5C_MAX_ENTRY_SIZE);
+ ds_entry_ptr->image_ptr = pf_entry_ptr->image_ptr;
+ ds_entry_ptr->image_up_to_date = !dirty;
+ ds_entry_ptr->type = type;
+ ds_entry_ptr->is_dirty = dirty |
+ pf_entry_ptr->is_dirty;
+ ds_entry_ptr->dirtied = FALSE;
+ ds_entry_ptr->is_protected = FALSE;
+ ds_entry_ptr->is_read_only = FALSE;
+ ds_entry_ptr->ro_ref_count = 0;
+ ds_entry_ptr->is_pinned = FALSE;
+ ds_entry_ptr->in_slist = FALSE;
+ ds_entry_ptr->flush_marker = FALSE;
+#ifdef H5_HAVE_PARALLEL
+ ds_entry_ptr->clear_on_unprotect = FALSE;
+ ds_entry_ptr->flush_immediately = FALSE;
+ ds_entry_ptr->coll_access = FALSE;
+#endif /* H5_HAVE_PARALLEL */
+ ds_entry_ptr->flush_in_progress = FALSE;
+ ds_entry_ptr->destroy_in_progress = FALSE;
+
+ ds_entry_ptr->ring = pf_entry_ptr->ring;
+
+ /* Initialize flush dependency height fields */
+ ds_entry_ptr->flush_dep_parent = NULL;
+ ds_entry_ptr->flush_dep_nparents = 0;
+ ds_entry_ptr->flush_dep_parent_nalloc = 0;
+ ds_entry_ptr->flush_dep_nchildren = 0;
+ ds_entry_ptr->flush_dep_ndirty_children = 0;
+ ds_entry_ptr->flush_dep_nunser_children = 0;
+
+ /* Initialize fields supporting the hash table: */
+ ds_entry_ptr->ht_next = NULL;
+ ds_entry_ptr->ht_prev = NULL;
+ ds_entry_ptr->il_next = NULL;
+ ds_entry_ptr->il_prev = NULL;
+
+ /* Initialize fields supporting replacement policies: */
+ ds_entry_ptr->next = NULL;
+ ds_entry_ptr->prev = NULL;
+ ds_entry_ptr->aux_next = NULL;
+ ds_entry_ptr->aux_prev = NULL;
+#ifdef H5_HAVE_PARALLEL
+ pf_entry_ptr->coll_next = NULL;
+ pf_entry_ptr->coll_prev = NULL;
+#endif /* H5_HAVE_PARALLEL */
+
+ /* initialize cache image related fields */
+ ds_entry_ptr->include_in_image = FALSE;
+ ds_entry_ptr->lru_rank = 0;
+ ds_entry_ptr->image_dirty = FALSE;
+ ds_entry_ptr->fd_parent_count = 0;
+ ds_entry_ptr->fd_parent_addrs = NULL;
+ ds_entry_ptr->fd_child_count = pf_entry_ptr->fd_child_count;
+ ds_entry_ptr->fd_dirty_child_count = 0;
+ ds_entry_ptr->image_fd_height = 0;
+ ds_entry_ptr->prefetched = FALSE;
+ ds_entry_ptr->prefetch_type_id = 0;
+ ds_entry_ptr->age = 0;
+
+ H5C__RESET_CACHE_ENTRY_STATS(ds_entry_ptr);
+
+ /* Apply to to the newly deserialized entry */
+ if(H5C__tag_entry(cache_ptr, ds_entry_ptr, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTTAG, FAIL, "Cannot tag metadata entry")
+
+ /* We have successfully deserialized the prefetched entry.
+ *
+ * Before we return a pointer to the deserialized entry, we must remove
+ * the prefetched entry from the cache, discard it, and replace it with
+ * the deserialized entry. Note that we do not free the prefetched
+ * entries image, as that has been transferred to the deserialized
+ * entry.
+ *
+ * Also note that we have not yet restored any flush dependencies. This
+ * must wait until the deserialized entry is inserted in the cache.
+ *
+ * To delete the prefetched entry from the cache:
+ *
+ * 1) Set pf_entry_ptr->image_ptr to NULL. Since we have already
+ * transferred the buffer containing the image to *ds_entry_ptr,
+ * this is not a memory leak.
+ *
+ * 2) Call H5C__flush_single_entry() with the H5C__FLUSH_INVALIDATE_FLAG
+ * and H5C__FLUSH_CLEAR_ONLY_FLAG flags set.
+ */
+ pf_entry_ptr->image_ptr = NULL;
+ if ( pf_entry_ptr->is_dirty ) {
+ HDassert(pf_entry_ptr->in_slist);
+ flush_flags |= H5C__DEL_FROM_SLIST_ON_DESTROY_FLAG;
+ } /* end if */
+
+ if(H5C__flush_single_entry(f, dxpl_id, pf_entry_ptr, flush_flags) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTEXPUNGE, FAIL, "can't expunge prefetched entry")
+
+#ifndef NDEGUG /* verify deletion */
+ H5C__SEARCH_INDEX(cache_ptr, addr, pf_entry_ptr, FAIL);
+
+ HDassert(NULL == pf_entry_ptr);
+#endif /* NDEBUG */
+
+ /* Insert the deserialized entry into the cache. */
+ H5C__INSERT_IN_INDEX(cache_ptr, ds_entry_ptr, FAIL)
+
+ HDassert(!ds_entry_ptr->in_slist);
+
+ if(ds_entry_ptr->is_dirty)
+ H5C__INSERT_ENTRY_IN_SLIST(cache_ptr, ds_entry_ptr, FAIL)
+
+ H5C__UPDATE_RP_FOR_INSERTION(cache_ptr, ds_entry_ptr, FAIL)
+
+ /* Deserializing a prefetched entry is the conceptual equivalent of
+ * loading it from file. If the deserialized entry has a notify callback,
+ * send an "after load" notice now that the deserialized entry is fully
+ * integrated into the cache.
+ */
+ if(ds_entry_ptr->type->notify &&
+ (ds_entry_ptr->type->notify)(H5C_NOTIFY_ACTION_AFTER_LOAD, ds_entry_ptr) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, "can't notify client about entry loaded into cache")
+
+ /* restore flush dependencies with the flush dependency children of
+ * of the prefetched entry. Note that we must protect *ds_entry_ptr
+ * before the call to avoid triggering sanity check failures, and
+ * then unprotect it afterwards.
+ */
+ i = 0;
+ if(fd_children != NULL) {
+ int j;
+ hbool_t found;
+
+ H5C__UPDATE_RP_FOR_PROTECT(cache_ptr, ds_entry_ptr, FAIL)
+ ds_entry_ptr->is_protected = TRUE;
+ while(fd_children[i] != NULL) {
+ /* Sanity checks */
+ HDassert((fd_children[i])->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert((fd_children[i])->prefetched);
+ HDassert((fd_children[i])->fd_parent_count > 0);
+ HDassert((fd_children[i])->fd_parent_addrs);
+
+ j = 0;
+ found = FALSE;
+ while((j < (int)((fd_children[i])->fd_parent_count)) && (!found)) {
+ if((fd_children[i])->fd_parent_addrs[j] == ds_entry_ptr->addr)
+ found = TRUE;
+
+ j++;
+ } /* end while */
+ HDassert(found);
+
+ if(H5C_create_flush_dependency(ds_entry_ptr, fd_children[i]) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTDEPEND, FAIL, "Can't restore child flush dependency.")
+
+ i++;
+ } /* end while */
+
+ H5C__UPDATE_RP_FOR_UNPROTECT(cache_ptr, ds_entry_ptr, FAIL);
+
+ ds_entry_ptr->is_protected = FALSE;
+ } /* end if ( fd_children != NULL ) */
+ HDassert((unsigned)i == ds_entry_ptr->fd_child_count);
+
+ ds_entry_ptr->fd_child_count = 0;
+ H5C__UPDATE_STATS_FOR_PREFETCH_HIT(cache_ptr)
+
+ /* finally, pass ds_entry_ptr back to the caller */
+ *entry_ptr_ptr = ds_entry_ptr;
+
+done:
+ if(fd_children)
+ fd_children = (H5C_cache_entry_t **)H5MM_xfree((void *)fd_children);
+
+ /* Release resources on error */
+ if(FAIL == ret_value)
+ if(thing && type->free_icr(thing) < 0)
+ HDONE_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "free_icr callback failed")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__deserialize_prefetched_entry() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__free_image_entries_array
+ *
+ * Purpose: If the image entries array exists, free the image
+ * associated with each entry, and then free the image
+ * entries array proper.
+ *
+ * Note that by the time this function is called, the cache
+ * should have removed all entries from its data structures.
+ *
+ * Return: SUCCEED on success, and FAIL on failure.
+ *
+ * Programmer: John Mainzer
+ * 8/4/15
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__free_image_entries_array(H5C_t * cache_ptr)
+{
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Sanity checks */
+ HDassert(cache_ptr);
+ HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
+ HDassert(cache_ptr->close_warning_received);
+ HDassert(cache_ptr->image_ctl.generate_image);
+ HDassert(cache_ptr->index_len == 0);
+
+ /* Check for entries to free */
+ if(cache_ptr->image_entries != NULL) {
+ unsigned u; /* Local index variable */
+
+ for(u = 0; u < cache_ptr->num_entries_in_image; u++) {
+ H5C_image_entry_t *ie_ptr; /* Image entry to release */
+
+ /* Get pointer to image entry */
+ ie_ptr = &((cache_ptr->image_entries)[u]);
+
+ /* Sanity checks */
+ HDassert(ie_ptr);
+ HDassert(ie_ptr->magic == H5C_IMAGE_ENTRY_T_MAGIC);
+ HDassert(ie_ptr->image_ptr);
+
+ /* Free the parent addrs array if appropriate */
+ if(ie_ptr->fd_parent_addrs) {
+ HDassert(ie_ptr->fd_parent_count > 0);
+
+ ie_ptr->fd_parent_addrs = (haddr_t *)H5MM_xfree(ie_ptr->fd_parent_addrs);
+ } /* end if */
+ else
+ HDassert(ie_ptr->fd_parent_count == 0);
+
+ /* Free the image */
+ ie_ptr->image_ptr = H5MM_xfree(ie_ptr->image_ptr);
+
+ /* Set magic field to bad magic so we can detect freed entries */
+ ie_ptr->magic = H5C_IMAGE_ENTRY_T_BAD_MAGIC;
+ } /* end for */
+
+ /* Free the image entries array */
+ cache_ptr->image_entries = (H5C_image_entry_t *)H5MM_xfree(cache_ptr->image_entries);
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5C__free_image_entries_array() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C_get_cache_image_config
+ *
+ * Purpose: Copy the current configuration for cache image generation
+ * on file close into the instance of H5C_cache_image_ctl_t
+ * pointed to by config_ptr.
+ *
+ * Return: SUCCEED on success, and FAIL on failure.
+ *
+ * Programmer: John Mainzer
+ * 7/3/15
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5C_get_cache_image_config(const H5C_t * cache_ptr,
+ H5C_cache_image_ctl_t *config_ptr)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ if((cache_ptr == NULL) || (cache_ptr->magic != H5C__H5C_T_MAGIC))
+ HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "Bad cache_ptr on entry")
+ if(config_ptr == NULL)
+ HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "Bad config_ptr on entry")
+
+ *config_ptr = cache_ptr->image_ctl;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C_get_cache_image_config() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C_image_stats
+ *
+ * Purpose: Prints statistics specific to the cache image.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: John Mainzer
+ * 10/26/15
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+#if H5C_COLLECT_CACHE_STATS
+H5C_image_stats(H5C_t * cache_ptr, hbool_t print_header)
+#else /* H5C_COLLECT_CACHE_STATS */
+H5C_image_stats(H5C_t * cache_ptr, hbool_t H5_ATTR_UNUSED print_header)
+#endif /* H5C_COLLECT_CACHE_STATS */
+{
+#if H5C_COLLECT_CACHE_STATS
+ int i;
+ int64_t total_hits = 0;
+ int64_t total_misses = 0;
+ double hit_rate;
+ double prefetch_use_rate;
+#endif /* H5C_COLLECT_CACHE_STATS */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ if(!cache_ptr || cache_ptr->magic != H5C__H5C_T_MAGIC)
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Bad cache_ptr")
+
+#if H5C_COLLECT_CACHE_STATS
+ for(i = 0; i <= cache_ptr->max_type_id; i++) {
+ total_hits += cache_ptr->hits[i];
+ total_misses += cache_ptr->misses[i];
+ } /* end for */
+
+ if((total_hits > 0) || (total_misses > 0))
+ hit_rate = (double)100.0f * ((double)(total_hits)) / ((double)(total_hits + total_misses));
+ else
+ hit_rate = 0.0f;
+
+ if(cache_ptr->prefetches > 0)
+ prefetch_use_rate = (double)100.0f * ((double)(cache_ptr->prefetch_hits)) /
+ ((double)(cache_ptr->prefetches));
+ else
+ prefetch_use_rate = 0.0f;
+
+ if(print_header) {
+ HDfprintf(stdout,
+ "\nhit prefetches prefetch image pf hit\n");
+ HDfprintf(stdout,
+ "rate: total: dirty: hits: flshs: evct: size: rate:\n");
+ } /* end if */
+
+ HDfprintf(stdout,
+ "%3.1lf %5lld %5lld %5lld %5lld %5lld %5lld %3.1lf\n",
+ hit_rate,
+ (long long)(cache_ptr->prefetches),
+ (long long)(cache_ptr->dirty_prefetches),
+ (long long)(cache_ptr->prefetch_hits),
+ (long long)(cache_ptr->flushes[H5AC_PREFETCHED_ENTRY_ID]),
+ (long long)(cache_ptr->evictions[H5AC_PREFETCHED_ENTRY_ID]),
+ (long long)(cache_ptr->last_image_size),
+ prefetch_use_rate);
+#endif /* H5C_COLLECT_CACHE_STATS */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C_image_stats() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__read_cache_image
+ *
+ * Purpose: Load the metadata cache image from the specified location
+ * in the file, and return it in the supplied buffer.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: John Mainzer
+ * 8/16/15
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5C__read_cache_image(H5F_t *f, hid_t dxpl_id, const H5C_t *cache_ptr)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(f);
+ HDassert(cache_ptr);
+ HDassert(H5F_addr_defined(cache_ptr->image_addr));
+ HDassert(cache_ptr->image_len > 0);
+ HDassert(cache_ptr->image_buffer);
+
+#ifdef H5_HAVE_PARALLEL
+{
+ H5AC_aux_t *aux_ptr = (H5AC_aux_t *)cache_ptr->aux_ptr;
+ int mpi_result;
+
+ if((NULL == aux_ptr) || (aux_ptr->mpi_rank == 0)) {
+ HDassert((NULL == aux_ptr) || (aux_ptr->magic == H5AC__H5AC_AUX_T_MAGIC));
+#endif /* H5_HAVE_PARALLEL */
+
+ /* Read the buffer (if serial access, or rank 0 of parallel access) */
+ if(H5F_block_read(f, H5FD_MEM_SUPER, cache_ptr->image_addr, cache_ptr->image_len, dxpl_id, cache_ptr->image_buffer) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_READERROR, FAIL, "Can't read metadata cache image block")
+
+#ifdef H5_HAVE_PARALLEL
+ if(aux_ptr) {
+ /* Broadcast cache image */
+ if(MPI_SUCCESS != (mpi_result = MPI_Bcast(cache_ptr->image_buffer, (int)cache_ptr->image_len, MPI_BYTE, 0, aux_ptr->mpi_comm)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Bcast failed", mpi_result)
+ } /* end if */
+ } /* end if */
+ else if(aux_ptr) {
+ /* Retrieve the contents of the metadata cache image from process 0 */
+ if(MPI_SUCCESS != (mpi_result = MPI_Bcast(cache_ptr->image_buffer, (int)cache_ptr->image_len, MPI_BYTE, 0, aux_ptr->mpi_comm)))
+ HMPI_GOTO_ERROR(FAIL, "can't receive cache image MPI_Bcast", mpi_result)
+ } /* end else-if */
+} /* end block */
+#endif /* H5_HAVE_PARALLEL */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__read_cache_image() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__load_cache_image
+ *
+ * Purpose: Read the cache image superblock extension message and
+ * delete it if so directed.
+ *
+ * Then load the cache image block at the specified location,
+ * decode it, and insert its contents into the metadata
+ * cache.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: John Mainzer
+ * 7/6/15
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5C__load_cache_image(H5F_t *f, hid_t dxpl_id)
+{
+ H5C_t * cache_ptr;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ /* Sanity checks */
+ HDassert(f);
+ HDassert(f->shared);
+ cache_ptr = f->shared->cache;
+ HDassert(cache_ptr);
+ HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
+
+ /* If the image address is defined, load the image, decode it,
+ * and insert its contents into the metadata cache.
+ *
+ * Note that under normal operating conditions, it is an error if the
+ * image address is HADDR_UNDEF. However, to facilitate testing,
+ * we allow this special value of the image address which means that
+ * no image exists, and that the load operation should be skipped
+ * silently.
+ */
+ if(H5F_addr_defined(cache_ptr->image_addr)) {
+ /* Sanity checks */
+ HDassert(cache_ptr->image_len > 0);
+ HDassert(cache_ptr->image_buffer == NULL);
+
+ /* Allocate space for the image */
+ if(NULL == (cache_ptr->image_buffer = H5MM_malloc(cache_ptr->image_len + 1)))
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, "memory allocation failed for cache image buffer")
+
+ /* Load the image from file */
+ if(H5C__read_cache_image(f, dxpl_id, cache_ptr) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_READERROR, FAIL, "Can't read metadata cache image block")
+
+ /* Decode metadata cache image */
+ if(H5C__decode_cache_image_buffer(f, cache_ptr) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTDECODE, FAIL, "Can't decode metadata cache image block")
+
+ /* At this point, the image_data_len should be known */
+ HDassert(cache_ptr->image_data_len > 0);
+ HDassert(cache_ptr->image_data_len <= cache_ptr->image_len);
+
+ /* Insert image contents into cache */
+ if(H5C__reconstruct_cache_contents(f, dxpl_id, cache_ptr) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTDECODE, FAIL, "Can't reconstruct cache contents from image block")
+
+ /* Free the image buffer */
+ cache_ptr->image_buffer = H5MM_xfree(cache_ptr->image_buffer);
+
+ /* Update stats -- must do this now, as we are about
+ * to discard the size of the cache image.
+ */
+ H5C__UPDATE_STATS_FOR_CACHE_IMAGE_LOAD(cache_ptr)
+
+ /* Free the image entries array. Note that all on disk image
+ * image buffers and fd parent address arrays have been transferred
+ * to their respective prefetched entries so we can just free the
+ * array of H5C_image_entry_t.
+ */
+#ifndef NDEBUG
+ {
+ unsigned u;
+
+ for(u = 0; u < cache_ptr->num_entries_in_image; u++) {
+ H5C_image_entry_t * ie_ptr;
+
+ ie_ptr = &((cache_ptr->image_entries)[u]);
+
+ HDassert(ie_ptr);
+ HDassert(ie_ptr->magic == H5C_IMAGE_ENTRY_T_MAGIC);
+ HDassert(ie_ptr->fd_parent_addrs == NULL);
+ HDassert(ie_ptr->image_ptr == NULL);
+ } /* end for */
+ } /* end block */
+#endif /* NDEBUG */
+
+ cache_ptr->image_entries = (H5C_image_entry_t *)H5MM_xfree(cache_ptr->image_entries);
+ cache_ptr->num_entries_in_image = 0;
+
+ cache_ptr->image_loaded = TRUE;
+ } /* end if */
+
+ /* If directed, free the on disk metadata cache image */
+ if(cache_ptr->delete_image) {
+ if(H5F_super_ext_remove_msg(f, dxpl_id, H5O_MDCI_MSG_ID) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTREMOVE, FAIL, "can't remove metadata cache image message from superblock extension")
+
+ /* Reset image block values */
+ cache_ptr->image_len = 0;
+ cache_ptr->image_data_len = 0;
+ cache_ptr->image_addr = HADDR_UNDEF;
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__load_cache_image() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C_load_cache_image_on_next_protect()
+ *
+ * Purpose: Note the fact that a metadata cache image superblock
+ * extension message exists, along with the base address
+ * and length of the metadata cache image block.
+ *
+ * Once this notification is received the metadata cache
+ * image block must be read, decoded, and loaded into the
+ * cache on the next call to H5C_protect().
+ *
+ * Further, if the file is opened R/W, the metadata cache
+ * image superblock extension message must be deleted from
+ * the superblock extension and the image block freed
+ *
+ * Contrawise, if the file is openened R/O, the metadata
+ * cache image superblock extension message and image block
+ * must be left as is. Further, any dirty entries in the
+ * cache image block must be marked as clean to avoid
+ * attempts to write them on file close.
+ *
+ * Return: SUCCEED
+ *
+ * Programmer: John Mainzer
+ * 7/6/15
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5C_load_cache_image_on_next_protect(H5F_t *f, haddr_t addr, hsize_t len,
+ hbool_t rw)
+{
+ H5C_t *cache_ptr;
+
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ /* Sanity checks */
+ HDassert(f);
+ HDassert(f->shared);
+ cache_ptr = f->shared->cache;
+ HDassert(cache_ptr);
+ HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
+
+ /* Set information needed to load cache image */
+ cache_ptr->image_addr = addr,
+ cache_ptr->image_len = len;
+ cache_ptr->load_image = TRUE;
+ cache_ptr->delete_image = rw;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5C_load_cache_image_on_next_protect() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__image_entry_cmp
+ *
+ * Purpose: Comparison callback for qsort(3) on image entries.
+ * Entries are sorted first by flush dependency height,
+ * and then by LRU rank.
+ *
+ * Note: Entries with a _greater_ flush dependency height should
+ * be sorted earlier than entries with lower heights, since
+ * leafs in the flush dependency graph are at height 0, and their
+ * parents need to be earlier in the image, so that they can
+ * construct their flush dependencies when decoded.
+ *
+ * Return: An integer less than, equal to, or greater than zero if the
+ * first entry is considered to be respectively less than,
+ * equal to, or greater than the second.
+ *
+ * Programmer: Quincey Koziol
+ * 1/20/16
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+H5C__image_entry_cmp(const void *_entry1, const void *_entry2)
+{
+ const H5C_image_entry_t *entry1 = (const H5C_image_entry_t *)_entry1; /* Pointer to first image entry to compare */
+ const H5C_image_entry_t *entry2 = (const H5C_image_entry_t *)_entry2; /* Pointer to second image entry to compare */
+ int ret_value = 0; /* Return value */
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Sanity checks */
+ HDassert(entry1);
+ HDassert(entry2);
+
+ if(entry1->image_fd_height > entry2->image_fd_height)
+ ret_value = -1;
+ else if(entry1->image_fd_height < entry2->image_fd_height)
+ ret_value = 1;
+ else {
+ /* Sanity check */
+ HDassert(entry1->lru_rank >= -1);
+ HDassert(entry2->lru_rank >= -1);
+
+ if(entry1->lru_rank < entry2->lru_rank)
+ ret_value = -1;
+ else if(entry1->lru_rank > entry2->lru_rank)
+ ret_value = 1;
+ } /* end else */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__image_entry_cmp() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__prep_image_for_file_close
+ *
+ * Purpose: The objective of the call is to allow the metadata cache
+ * to do any preparatory work prior to generation of a
+ * cache image.
+ *
+ * In particular, the cache must
+ *
+ * 1) serialize all its entries,
+ *
+ * 2) compute the size of the metadata cache image,
+ *
+ * 3) allocate space for the metadata cache image, and
+ *
+ * 4) setup the metadata cache image superblock extension
+ * message with the address and size of the metadata
+ * cache image.
+ *
+ * The parallel case is complicated by the fact that
+ * while all metadata caches must contain the same set of
+ * dirty entries, there is no such requirement for clean
+ * entries or the order that entries appear in the LRU.
+ *
+ * Thus, there is no requirement that different processes
+ * will construct cache images of the same size.
+ *
+ * This is not a major issue as long as all processes include
+ * the same set of dirty entries in the cache -- as they
+ * currently do (note that this will change when we implement
+ * the ageout feature). Since only the process zero cache
+ * writes the cache image, all that is necessary is to
+ * broadcast the process zero cache size for use in the
+ * superblock extension messages and cache image block
+ * allocations.
+ *
+ * Note: At present, cache image is disabled in the
+ * parallel case as the new collective metadata write
+ * code must be modified to support cache image.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: John Mainzer
+ * 7/3/15
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5C__prep_image_for_file_close(H5F_t *f, hid_t dxpl_id)
+{
+ H5C_t * cache_ptr = NULL;
+ haddr_t eoa_frag_addr = HADDR_UNDEF;
+ hsize_t eoa_frag_size = 0;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ /* Sanity checks */
+ HDassert(f);
+ HDassert(f->shared);
+ HDassert(f->shared->cache);
+ cache_ptr = f->shared->cache;
+ HDassert(cache_ptr);
+ HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
+
+ /* Create the cache image super block extension message.
+ *
+ * Note that the base address and length of the metadata cache
+ * image are undefined at this point, and thus will have to be
+ * updated later.
+ *
+ * Create the super block extension message now so that space
+ * is allocated for it (if necessary) before we allocate space
+ * for the cache image block.
+ *
+ * To simplify testing, do this only if the
+ * H5C_CI__GEN_MDCI_SBE_MESG bit is set in
+ * cache_ptr->image_ctl.flags.
+ */
+ if(cache_ptr->image_ctl.flags & H5C_CI__GEN_MDCI_SBE_MESG)
+ if(H5C__write_cache_image_superblock_msg(f, dxpl_id, TRUE) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "creation of cache image SB mesg failed.")
+
+ /* Serialize the cache */
+ if(H5C__serialize_cache(f, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "serialization of the cache failed")
+
+ /* Scan the cache and record data needed to construct the
+ * cache image. In particular, for each entry we must record:
+ *
+ * 1) rank in LRU (if entry is in LRU)
+ *
+ * 2) Whether the entry is dirty prior to flush of
+ * cache just prior to close.
+ *
+ * 3) Addresses of flush dependency parents (if any).
+ *
+ * 4) Number of flush dependency children (if any).
+ *
+ * In passing, also compute the size of the metadata cache
+ * image. With the recent modifications of the free space
+ * manager code, this size should be correct.
+ */
+ if(H5C__prep_for_file_close__scan_entries(f, cache_ptr) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "H5C__prep_for_file_close__scan_entries failed")
+ HDassert(HADDR_UNDEF == cache_ptr->image_addr);
+
+#ifdef H5_HAVE_PARALLEL
+ /* In the parallel case, overwrite the image_len with the
+ * value computed by process 0.
+ */
+ if(cache_ptr->aux_ptr) { /* we have multiple processes */
+ int mpi_result;
+ unsigned p0_image_len;
+ H5AC_aux_t * aux_ptr;
+
+ aux_ptr = (H5AC_aux_t *)cache_ptr->aux_ptr;
+ if(aux_ptr->mpi_rank == 0) {
+ aux_ptr->p0_image_len = (unsigned)cache_ptr->image_data_len;
+ p0_image_len = aux_ptr->p0_image_len;
+
+ if(MPI_SUCCESS != (mpi_result = MPI_Bcast(&p0_image_len, 1, MPI_UNSIGNED, 0, aux_ptr->mpi_comm)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Bcast failed", mpi_result)
+
+ HDassert(p0_image_len == aux_ptr->p0_image_len);
+ } /* end if */
+ else {
+ if(MPI_SUCCESS != (mpi_result = MPI_Bcast(&p0_image_len, 1, MPI_UNSIGNED, 0, aux_ptr->mpi_comm)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Bcast failed", mpi_result)
+
+ aux_ptr->p0_image_len = p0_image_len;
+ } /* end else */
+
+ /* Allocate space for a cache image of size equal to that
+ * computed by the process 0. This may be different from
+ * cache_ptr->image_data_len if mpi_rank != 0. However, since
+ * cache image write is suppressed on all processes other than
+ * process 0, this doesn't matter.
+ *
+ * Note that we allocate the cache image directly from the file
+ * driver so as to avoid unsettling the free space managers.
+ */
+ if(HADDR_UNDEF == (cache_ptr->image_addr = H5FD_alloc(f->shared->lf, dxpl_id, H5FD_MEM_SUPER, f,
+ (hsize_t)p0_image_len, &eoa_frag_addr, &eoa_frag_size)))
+ HGOTO_ERROR(H5E_CACHE, H5E_NOSPACE, FAIL, "can't allocate file space for metadata cache image")
+ } /* end if */
+ else
+#endif /* H5_HAVE_PARALLEL */
+ /* Allocate the cache image block. Note that we allocate this
+ * this space directly from the file driver so as to avoid
+ * unsettling the free space managers.
+ */
+ if(HADDR_UNDEF == (cache_ptr->image_addr = H5FD_alloc(f->shared->lf, dxpl_id, H5FD_MEM_SUPER, f,
+ (hsize_t)(cache_ptr->image_data_len), &eoa_frag_addr, &eoa_frag_size)))
+ HGOTO_ERROR(H5E_CACHE, H5E_NOSPACE, FAIL, "can't allocate file space for metadata cache image")
+
+ /* For now, drop any fragment left over from the allocation of the
+ * image block on the ground. A fragment should only be returned
+ * if the underlying file alignment is greater than 1.
+ *
+ * Clean this up eventually by extending the size of the cache
+ * image block to the next alignement boundary, and then setting
+ * the image_data_len to the actual size of the cache_image.
+ *
+ * On the off chance that there is some other way to get a
+ * a fragment on a cache image allocation, leave the following
+ * assertion in the code so we will find out.
+ */
+ HDassert((eoa_frag_size == 0) || (f->shared->alignment != 1));
+
+ /* Eventually it will be possible for the length of the cache image
+ * block on file to be greater than the size of the data it
+ * contains. However, for now they must be the same. Set
+ * cache_ptr->image_len accordingly.
+ */
+ cache_ptr->image_len = cache_ptr->image_data_len;
+
+ /* update the metadata cache image superblock extension
+ * message with the new cache image block base address and
+ * length.
+ *
+ * to simplify testing, do this only if the
+ * H5C_CI__GEN_MDC_IMAGE_BLK bit is set in
+ * cache_ptr->image_ctl.flags.
+ */
+ if(cache_ptr->image_ctl.flags & H5C_CI__GEN_MDC_IMAGE_BLK)
+ if(H5C__write_cache_image_superblock_msg(f, dxpl_id, FALSE) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "update of cache image SB mesg failed.")
+
+ /* At this point:
+ *
+ * 1) space in the file for the metadata cache image
+ * is allocated,
+ *
+ * 2) the metadata cache image superblock extension
+ * message exists and (if so configured) contains
+ * the correct data,
+ *
+ * 3) All entries in the cache that will appear in the
+ * cache image are serialized with up to date images.
+ *
+ * Since we just updated the cache image message,
+ * the super block extension message is dirty. However,
+ * since the superblock and the superblock extension
+ * can't be included in the cache image, this is a non-
+ * issue.
+ *
+ * 4) All entries in the cache that will be include in
+ * the cache are marked as such, and we have a count
+ * of same.
+ *
+ * 5) Flush dependency heights are calculated for all
+ * entries that will be included in the cache image.
+ *
+ * If there are any entries to be included in the metadata cache
+ * image, allocate, populate, and sort the image_entries array.
+ *
+ * If the metadata cache image will be empty, delete the
+ * metadata cache image superblock extension message, set
+ * cache_ptr->image_ctl.generate_image to FALSE. This will
+ * allow the file close to continue normally without the
+ * unecessary generation of the metadata cache image.
+ */
+ if(cache_ptr->num_entries_in_image > 0) {
+ if(H5C__prep_for_file_close__setup_image_entries_array(cache_ptr) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTINIT, FAIL, "can't setup image entries array.")
+
+ /* Sort the entries */
+ HDqsort(cache_ptr->image_entries, (size_t)cache_ptr->num_entries_in_image,
+ sizeof(H5C_image_entry_t), H5C__image_entry_cmp);
+ } /* end if */
+ else { /* cancel creation of metadata cache iamge */
+ HDassert(cache_ptr->image_entries == NULL);
+
+ /* To avoid breaking the control flow tests, only delete
+ * the mdci superblock extension message if the
+ * H5C_CI__GEN_MDC_IMAGE_BLK flag is set in
+ * cache_ptr->image_ctl.flags.
+ */
+ if(cache_ptr->image_ctl.flags & H5C_CI__GEN_MDC_IMAGE_BLK)
+ if(H5F_super_ext_remove_msg(f, dxpl_id, H5O_MDCI_MSG_ID) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTREMOVE, FAIL, "can't remove MDC image msg from superblock ext.")
+
+ cache_ptr->image_ctl.generate_image = FALSE;
+ } /* end else */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__prep_image_for_file_close() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C_set_cache_image_config
+ *
+ * Purpose: If *config_ptr contains valid data, copy it into the
+ * image_ctl field of *cache_ptr. Make adjustments for
+ * changes in configuration as required.
+ *
+ * Fail if the new configuration is invalid.
+ *
+ * Return: SUCCEED on success, and FAIL on failure.
+ *
+ * Programmer: John Mainzer
+ * 7/3/15
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5C_set_cache_image_config(const H5F_t *f, H5C_t *cache_ptr,
+ H5C_cache_image_ctl_t *config_ptr)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity checks */
+ HDassert(f);
+ HDassert(f->shared);
+ HDassert(f->shared->cache == f->shared->cache);
+
+ /* Check arguments */
+ if((cache_ptr == NULL) || (cache_ptr->magic != H5C__H5C_T_MAGIC))
+ HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "Bad cache_ptr on entry")
+ if(config_ptr == NULL)
+ HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "NULL config_ptr on entry")
+ if(config_ptr->version != H5C__CURR_CACHE_IMAGE_CTL_VER)
+ HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "Unknown config version")
+
+ /* check general configuration section of the config: */
+ if(H5C_validate_cache_image_config(config_ptr) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid cache image configuration")
+
+ if(H5F_INTENT(f) & H5F_ACC_RDWR) /* file has been opened R/W */
+ cache_ptr->image_ctl = *config_ptr;
+ else { /* file opened R/O -- suppress cache image silently */
+ H5C_cache_image_ctl_t default_image_ctl = H5C__DEFAULT_CACHE_IMAGE_CTL;
+
+ cache_ptr->image_ctl = default_image_ctl;
+ HDassert(!(cache_ptr->image_ctl.generate_image));
+ } /* end else */
+
+#ifdef H5_HAVE_PARALLEL
+ /* the collective metadata write code is not currently compatible
+ * with cache image. Until this is fixed, suppress cache image silently
+ * if there is more than one process.
+ * JRM -- 11/8/16
+ */
+ if(cache_ptr->aux_ptr) {
+ H5C_cache_image_ctl_t default_image_ctl = H5C__DEFAULT_CACHE_IMAGE_CTL;
+
+ cache_ptr->image_ctl = default_image_ctl;
+ HDassert(!(cache_ptr->image_ctl.generate_image));
+ } /* end if */
+#endif /* H5_HAVE_PARALLEL */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C_set_cache_image_config() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C_validate_cache_image_config()
+ *
+ * Purpose: Run a sanity check on the provided instance of struct
+ * H5AC_cache_image_config_t.
+ *
+ * Do nothing and return SUCCEED if no errors are detected,
+ * and flag an error and return FAIL otherwise.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: John Mainzer
+ * 6/15/15
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5C_validate_cache_image_config(H5C_cache_image_ctl_t * ctl_ptr)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ if(ctl_ptr == NULL)
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "NULL ctl_ptr on entry")
+ if(ctl_ptr->version != H5C__CURR_CACHE_IMAGE_CTL_VER)
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Unknown cache image control version")
+
+ /* At present, we do not support inclusion of the adaptive resize
+ * configuration in the cache image. Thus the save_resize_status
+ * field must be FALSE.
+ */
+ if(ctl_ptr->save_resize_status != FALSE)
+ HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "unexpected value in save_resize_status field")
+
+ /* At present, we do not support prefetched entry ageouts. Thus
+ * the entry_ageout field must be set to
+ * H5AC__CACHE_IMAGE__ENTRY_AGEOUT__NONE.
+ */
+ if(ctl_ptr->entry_ageout != H5AC__CACHE_IMAGE__ENTRY_AGEOUT__NONE)
+ HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "unexpected value in entry_ageout field")
+
+ if((ctl_ptr->flags & ~H5C_CI__ALL_FLAGS) != 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "unknown flag set")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C_validate_cache_image_config() */
+
+
+/*************************************************************************/
+/**************************** Private Functions: *************************/
+/*************************************************************************/
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__cache_image_block_entry_header_size
+ *
+ * Purpose: Compute the size of the header of the metadata cache
+ * image block, and return the value.
+ *
+ * Return: Size of the header section of the metadata cache image
+ * block in bytes.
+ *
+ * Programmer: John Mainzer
+ * 7/27/15
+ *
+ *-------------------------------------------------------------------------
+ */
+static size_t
+H5C__cache_image_block_entry_header_size(const H5F_t * f)
+{
+ size_t ret_value = 0; /* Return value */
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Set return value */
+ ret_value = (size_t)( 1 + /* type */
+ 1 + /* flags */
+ 1 + /* ring */
+ 1 + /* age */
+ 2 + /* dependency child count */
+ 2 + /* dirty dep child count */
+ 2 + /* dependency parent count */
+ 4 + /* index in LRU */
+ H5F_SIZEOF_ADDR(f) + /* entry offset */
+ H5F_SIZEOF_SIZE(f) ); /* entry length */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__cache_image_block_entry_header_size() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__cache_image_block_header_size
+ *
+ * Purpose: Compute the size of the header of the metadata cache
+ * image block, and return the value.
+ *
+ * Return: Size of the header section of the metadata cache image
+ * block in bytes.
+ *
+ * Programmer: John Mainzer
+ * 7/27/15
+ *
+ *-------------------------------------------------------------------------
+ */
+static size_t
+H5C__cache_image_block_header_size(const H5F_t * f)
+{
+ size_t ret_value = 0; /* Return value */
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Set return value */
+ ret_value = (size_t)( 4 + /* signature */
+ 1 + /* version */
+ 1 + /* flags */
+ H5F_SIZEOF_SIZE(f) + /* image data length */
+ 4 ); /* num_entries */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__cache_image_block_header_size() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__decode_cache_image_buffer()
+ *
+ * Purpose: Allocate a suitably size array of instances of
+ * H5C_image_entry_t and and set cache_ptr->image_entries
+ * to point to this array. Set cache_ptr->num_entries_in_image
+ * equal to the number of entries in this array.
+ *
+ * Decode the contents of cache_ptr->image_buffer into the
+ * array.
+ *
+ * Return: SUCCEED on success, and FAIL on failure.
+ *
+ * Programmer: John Mainzer
+ * 8/9/15
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__decode_cache_image_buffer(const H5F_t *f, H5C_t *cache_ptr)
+{
+ uint32_t read_chksum;
+ uint32_t computed_chksum;
+ const uint8_t * p;
+ unsigned u; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(f);
+ HDassert(f->shared);
+ HDassert(cache_ptr == f->shared->cache);
+ HDassert(cache_ptr);
+ HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
+ HDassert(cache_ptr->image_buffer);
+ HDassert(cache_ptr->image_len > 0);
+ HDassert(cache_ptr->image_data_len == 0);
+ HDassert(cache_ptr->image_entries == NULL);
+ HDassert(cache_ptr->num_entries_in_image == 0);
+
+ /* Decode metadata cache image header */
+ p = (uint8_t *)cache_ptr->image_buffer;
+ if(H5C__decode_cache_image_header(f, cache_ptr, &p) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTDECODE, FAIL, "cache image header decode failed")
+ HDassert((size_t)(p - (uint8_t *)cache_ptr->image_buffer) < cache_ptr->image_len);
+
+ /* cache_ptr->image_data_len should be defined now */
+ HDassert(cache_ptr->image_data_len > 0);
+ HDassert(cache_ptr->image_data_len <= cache_ptr->image_len);
+
+ /* We should now have cache_ptr->num_entries_in_image -- allocate the
+ * image entries array.
+ */
+ HDassert(cache_ptr->num_entries_in_image > 0);
+ if(NULL == (cache_ptr->image_entries = (H5C_image_entry_t *)H5MM_malloc(sizeof(H5C_image_entry_t) * (size_t)(cache_ptr->num_entries_in_image + 1))))
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, "memory allocation failed image entries array")
+
+ /* Load the image entries */
+ for(u = 0; u < cache_ptr->num_entries_in_image; u++) {
+ (cache_ptr->image_entries)[u].magic = H5C_IMAGE_ENTRY_T_MAGIC;
+ (cache_ptr->image_entries)[u].image_fd_height = 0;
+ (cache_ptr->image_entries)[u].image_ptr = NULL;
+
+ if(H5C__decode_cache_image_entry(f, cache_ptr, &p, u) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTDECODE, FAIL, "entry image decode failed")
+ } /* end for */
+ HDassert((size_t)(p - (uint8_t *)cache_ptr->image_buffer) < cache_ptr->image_len);
+
+ /* (Load the adaptive cache resize status -- not yet) */
+
+ /* Verify the checksum */
+ UINT32DECODE(p, read_chksum);
+ HDassert((size_t)(p - (uint8_t *)cache_ptr->image_buffer) == cache_ptr->image_data_len);
+ HDassert((size_t)(p - (uint8_t *)cache_ptr->image_buffer) <= cache_ptr->image_len);
+ computed_chksum = H5_checksum_metadata(cache_ptr->image_buffer, (size_t)(cache_ptr->image_data_len - H5F_SIZEOF_CHKSUM), 0);
+ if(read_chksum != computed_chksum)
+ HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "bad checksum on metadata cache image block")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__decode_cache_image_buffer() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__decode_cache_image_header()
+ *
+ * Purpose: Decode the metadata cache image buffer header from the
+ * supplied buffer and load the data into the supplied instance
+ * of H5C_t. Advances the buffer pointer to the first byte
+ * after the header image, or unchanged on failure.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: John Mainzer
+ * 8/6/15
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__decode_cache_image_header(const H5F_t *f, H5C_t *cache_ptr,
+ const uint8_t **buf)
+{
+ uint8_t version;
+ uint8_t flags;
+ hbool_t have_resize_status = FALSE;
+ size_t actual_header_len;
+ size_t expected_header_len;
+ const uint8_t * p;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(cache_ptr);
+ HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
+ HDassert(buf);
+ HDassert(*buf);
+
+ /* Point to buffer to decode */
+ p = *buf;
+
+ /* Check signature */
+ if(HDmemcmp(p, H5C__MDCI_BLOCK_SIGNATURE, (size_t)H5C__MDCI_BLOCK_SIGNATURE_LEN))
+ HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "Bad metadata cache image header signature")
+ p += H5C__MDCI_BLOCK_SIGNATURE_LEN;
+
+ /* Check version */
+ version = *p++;
+ if(version != (uint8_t)H5C__MDCI_BLOCK_VERSION_0)
+ HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "Bad metadata cache image version")
+
+ /* Decode flags */
+ flags = *p++;
+ if(flags & H5C__MDCI_HEADER_HAVE_RESIZE_STATUS)
+ have_resize_status = TRUE;
+ if(have_resize_status)
+ HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "MDC resize status not yet supported")
+
+ /* Read image data length */
+ H5F_DECODE_LENGTH(f, p, cache_ptr->image_data_len);
+
+ /* For now -- will become <= eventually */
+ if(cache_ptr->image_data_len != cache_ptr->image_len)
+ HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "Bad metadata cache image data length")
+
+ /* Read num entries */
+ UINT32DECODE(p, cache_ptr->num_entries_in_image);
+ if(cache_ptr->num_entries_in_image == 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "Bad metadata cache entry count")
+
+ /* Verify expected length of header */
+ actual_header_len = (size_t)(p - *buf);
+ expected_header_len = H5C__cache_image_block_header_size(f);
+ if(actual_header_len != expected_header_len)
+ HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "Bad header image len.")
+
+ /* Update buffer pointer */
+ *buf = p;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__decode_cache_image_header() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__decode_cache_image_entry()
+ *
+ * Purpose: Decode the metadata cache image entry from the supplied
+ * buffer into the supplied instance of H5C_image_entry_t.
+ * This includes allocating a buffer for the entry image,
+ * loading it, and seting ie_ptr->image_ptr to point to
+ * the buffer.
+ *
+ * Advances the buffer pointer to the first byte
+ * after the entry, or unchanged on failure.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: John Mainzer
+ * 8/6/15
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__decode_cache_image_entry(const H5F_t *f, const H5C_t *cache_ptr,
+ const uint8_t **buf, unsigned entry_num)
+{
+ hbool_t is_dirty = FALSE;
+#ifndef NDEBUG /* only used in assertions */
+ hbool_t in_lru = FALSE;
+ hbool_t is_fd_parent = FALSE;
+ hbool_t is_fd_child = FALSE;
+#endif /* NDEBUG */ /* only used in assertions */
+ haddr_t addr;
+ hsize_t size = 0;
+ void * image_ptr;
+ uint8_t flags = 0;
+ uint8_t type_id;
+ uint8_t ring;
+ uint8_t age;
+ uint16_t fd_child_count;
+ uint16_t fd_dirty_child_count;
+ uint16_t fd_parent_count;
+ haddr_t * fd_parent_addrs = NULL;
+ int32_t lru_rank;
+ H5C_image_entry_t * ie_ptr = NULL;
+ const uint8_t * p;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(f);
+ HDassert(f->shared);
+ HDassert(cache_ptr == f->shared->cache);
+ HDassert(cache_ptr);
+ HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
+ HDassert(buf);
+ HDassert(*buf);
+ HDassert(entry_num < cache_ptr->num_entries_in_image);
+ ie_ptr = &((cache_ptr->image_entries)[entry_num]);
+ HDassert(ie_ptr);
+ HDassert(ie_ptr->magic == H5C_IMAGE_ENTRY_T_MAGIC);
+
+ /* Get pointer to buffer */
+ p = *buf;
+
+ /* Decode type id */
+ type_id = *p++;
+
+ /* Decode flags */
+ flags = *p++;
+ if(flags & H5C__MDCI_ENTRY_DIRTY_FLAG)
+ is_dirty = TRUE;
+#ifndef NDEBUG /* only used in assertions */
+ if(flags & H5C__MDCI_ENTRY_IN_LRU_FLAG)
+ in_lru = TRUE;
+ if(flags & H5C__MDCI_ENTRY_IS_FD_PARENT_FLAG)
+ is_fd_parent = TRUE;
+ if(flags & H5C__MDCI_ENTRY_IS_FD_CHILD_FLAG)
+ is_fd_child = TRUE;
+#endif /* NDEBUG */ /* only used in assertions */
+
+ /* Decode ring */
+ ring = *p++;
+ HDassert(ring > (uint8_t)(H5C_RING_UNDEFINED));
+ HDassert(ring < (uint8_t)(H5C_RING_NTYPES));
+
+ /* Decode age */
+ age = *p++;
+
+ /* Decode dependency child count */
+ UINT16DECODE(p, fd_child_count);
+ HDassert((is_fd_parent && fd_child_count > 0) || (!is_fd_parent && fd_child_count == 0));
+
+ /* Decode dirty dependency child count */
+ UINT16DECODE(p, fd_dirty_child_count);
+ if(fd_dirty_child_count > fd_child_count)
+ HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "invalid dirty flush dependency child count")
+
+ /* Decode dependency parent count */
+ UINT16DECODE(p, fd_parent_count);
+ HDassert((is_fd_child && fd_parent_count > 0) || (!is_fd_child && fd_parent_count == 0));
+
+ /* Decode index in LRU */
+ INT32DECODE(p, lru_rank);
+ HDassert((in_lru && lru_rank >= 0) || (!in_lru && lru_rank == -1));
+
+ /* Decode entry offset */
+ H5F_addr_decode(f, &p, &addr);
+ if(!H5F_addr_defined(addr))
+ HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "invalid entry offset")
+
+ /* Decode entry length */
+ H5F_DECODE_LENGTH(f, p, size);
+ if(size == 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "invalid entry size")
+
+ /* Verify expected length of entry image */
+ if((size_t)(p - *buf) != H5C__cache_image_block_entry_header_size(f))
+ HGOTO_ERROR(H5E_CACHE, H5E_BADSIZE, FAIL, "Bad entry image len")
+
+ /* If parent count greater than zero, allocate array for parent
+ * addresses, and decode addresses into the array.
+ */
+ if(fd_parent_count > 0) {
+ int i; /* Local index variable */
+
+ if(NULL == (fd_parent_addrs = (haddr_t *)H5MM_malloc((size_t)(fd_parent_count) * H5F_SIZEOF_ADDR(f))))
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, "memory allocation failed for fd parent addrs buffer")
+
+ for(i = 0; i < fd_parent_count; i++) {
+ H5F_addr_decode(f, &p, &(fd_parent_addrs[i]));
+ if(!H5F_addr_defined(fd_parent_addrs[i]))
+ HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "invalid flush dependency parent offset")
+ } /* end for */
+ } /* end if */
+
+ /* Allocate buffer for entry image */
+ if(NULL == (image_ptr = H5MM_malloc(size + H5C_IMAGE_EXTRA_SPACE)))
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, "memory allocation failed for on disk image buffer")
+
+#if H5C_DO_MEMORY_SANITY_CHECKS
+ HDmemcpy(((uint8_t *)image_ptr) + size, H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE);
+#endif /* H5C_DO_MEMORY_SANITY_CHECKS */
+
+ /* Copy the entry image from the cache image block */
+ HDmemcpy(image_ptr, p, size);
+ p += size;
+
+ /* Copy data into target */
+ ie_ptr->addr = addr;
+ ie_ptr->size = size;
+ ie_ptr->ring = (H5C_ring_t)ring;
+ ie_ptr->age = (int32_t)age;
+ ie_ptr->type_id = (int32_t)type_id;
+ ie_ptr->lru_rank = lru_rank;
+ ie_ptr->is_dirty = is_dirty;
+ ie_ptr->fd_child_count = (uint64_t)fd_child_count;
+ ie_ptr->fd_dirty_child_count = (uint64_t)fd_dirty_child_count;
+ ie_ptr->fd_parent_count = (uint64_t)fd_parent_count;
+ ie_ptr->fd_parent_addrs = fd_parent_addrs;
+ ie_ptr->image_ptr = image_ptr;
+
+ /* Update buffer pointer */
+ *buf = p;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__decode_cache_image_entry() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__destroy_pf_entry_child_flush_deps()
+ *
+ * Purpose: Destroy all flush dependencies in this the supplied
+ * prefetched entry is the parent. Note that the children
+ * in these flush dependencies must be prefetched entries as
+ * well.
+ *
+ * As this action is part of the process of transferring all
+ * such flush dependencies to the deserialized version of the
+ * prefetched entry, ensure that the data necessary to complete
+ * the transfer is retained.
+ *
+ * Note: The current implementation of this function is
+ * quite inefficient -- mostly due to the current
+ * implementation of flush dependencies. This should
+ * be fixed at some point.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: John Mainzer
+ * 8/11/15
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__destroy_pf_entry_child_flush_deps(H5C_t *cache_ptr,
+ H5C_cache_entry_t *pf_entry_ptr, H5C_cache_entry_t **fd_children)
+{
+ H5C_cache_entry_t * entry_ptr;
+ unsigned entries_visited = 0;
+ int fd_children_found = 0;
+ hbool_t found;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(cache_ptr);
+ HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
+ HDassert(pf_entry_ptr);
+ HDassert(pf_entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(pf_entry_ptr->type);
+ HDassert(pf_entry_ptr->type->id == H5AC_PREFETCHED_ENTRY_ID);
+ HDassert(pf_entry_ptr->prefetched);
+ HDassert(pf_entry_ptr->fd_child_count > 0);
+ HDassert(fd_children);
+
+ /* Scan each entry on the index list */
+ entry_ptr = cache_ptr->il_head;
+ while(entry_ptr != NULL) {
+ HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+
+ /* Here we look at entry_ptr->flush_dep_nparents and not
+ * entry_ptr->fd_parent_count as it is possible that some
+ * or all of the prefetched flush dependency child relationships
+ * have already been destroyed.
+ */
+ if(entry_ptr->prefetched && (entry_ptr->flush_dep_nparents > 0)) {
+ unsigned u; /* Local index variable */
+
+ /* Re-init */
+ u = 0;
+ found = FALSE;
+
+ /* Sanity checks */
+ HDassert(entry_ptr->type);
+ HDassert(entry_ptr->type->id == H5AC_PREFETCHED_ENTRY_ID);
+ HDassert(entry_ptr->fd_parent_count >= entry_ptr->flush_dep_nparents);
+ HDassert(entry_ptr->fd_parent_addrs);
+ HDassert(entry_ptr->flush_dep_parent);
+
+ /* Look for correct entry */
+ while(!found && (u < entry_ptr->fd_parent_count)) {
+ /* Sanity check entry */
+ HDassert(entry_ptr->flush_dep_parent[u]);
+ HDassert(entry_ptr->flush_dep_parent[u]->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+
+ /* Correct entry? */
+ if(pf_entry_ptr == entry_ptr->flush_dep_parent[u])
+ found = TRUE;
+
+ u++;
+ } /* end while */
+
+ if(found) {
+ HDassert(NULL == fd_children[fd_children_found]);
+
+ /* Remove flush dependency */
+ fd_children[fd_children_found] = entry_ptr;
+ fd_children_found++;
+ if(H5C_destroy_flush_dependency(pf_entry_ptr, entry_ptr) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTUNDEPEND, FAIL, "can't destroy pf entry child flush dependency")
+
+#ifndef NDEBUG
+ /* Sanity check -- verify that the address of the parent
+ * appears in entry_ptr->fd_parent_addrs. Must do a search,
+ * as with flush dependency creates and destroys,
+ * entry_ptr->fd_parent_addrs and entry_ptr->flush_dep_parent
+ * can list parents in different order.
+ */
+ found = FALSE;
+ u = 0;
+ while(!found && u < entry_ptr->fd_parent_count) {
+ if(pf_entry_ptr->addr == entry_ptr->fd_parent_addrs[u])
+ found = TRUE;
+ u++;
+ } /* end while */
+ HDassert(found);
+#endif /* NDEBUG */
+ } /* end if */
+ } /* end if */
+
+ entries_visited++;
+ entry_ptr = entry_ptr->il_next;
+ } /* end while */
+
+ /* Post-op sanity checks */
+ HDassert(NULL == fd_children[fd_children_found]);
+ HDassert((unsigned)fd_children_found == pf_entry_ptr->fd_child_count);
+ HDassert(entries_visited == cache_ptr->index_len);
+ HDassert(!pf_entry_ptr->is_pinned);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__destroy_pf_entry_child_flush_deps() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__encode_cache_image_header()
+ *
+ * Purpose: Encode the metadata cache image buffer header in the
+ * supplied buffer. Updates buffer pointer to the first byte
+ * after the header image in the buffer, or unchanged on failure.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: John Mainzer
+ * 8/6/15
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__encode_cache_image_header(const H5F_t *f, const H5C_t *cache_ptr,
+ uint8_t **buf)
+{
+ size_t actual_header_len;
+ size_t expected_header_len;
+ uint8_t flags = 0;
+ uint8_t * p; /* Pointer into cache image buffer */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(cache_ptr);
+ HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
+ HDassert(cache_ptr->close_warning_received);
+ HDassert(cache_ptr->image_ctl.generate_image);
+ HDassert(cache_ptr->index_len == 0);
+ HDassert(cache_ptr->image_data_len > 0);
+ HDassert(cache_ptr->image_data_len <= cache_ptr->image_len);
+ HDassert(buf);
+ HDassert(*buf);
+
+ /* Set pointer into buffer */
+ p = *buf;
+
+ /* write signature */
+ HDmemcpy(p, H5C__MDCI_BLOCK_SIGNATURE, (size_t)H5C__MDCI_BLOCK_SIGNATURE_LEN);
+ p += H5C__MDCI_BLOCK_SIGNATURE_LEN;
+
+ /* write version */
+ *p++ = (uint8_t)H5C__MDCI_BLOCK_VERSION_0;
+
+ /* setup and write flags */
+
+ /* at present we don't support saving resize status */
+ HDassert(!cache_ptr->image_ctl.save_resize_status);
+ if(cache_ptr->image_ctl.save_resize_status)
+ flags |= H5C__MDCI_HEADER_HAVE_RESIZE_STATUS;
+
+ *p++ = flags;
+
+ /* Encode image data length */
+ /* this must be true at present */
+ HDassert(cache_ptr->image_len == cache_ptr->image_data_len);
+ H5F_ENCODE_LENGTH(f, p, cache_ptr->image_data_len);
+
+ /* write num entries */
+ UINT32ENCODE(p, cache_ptr->num_entries_in_image);
+
+ /* verify expected length of header */
+ actual_header_len = (size_t)(p - *buf);
+ expected_header_len = H5C__cache_image_block_header_size(f);
+ if(actual_header_len != expected_header_len)
+ HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "Bad header image len")
+
+ /* Update buffer pointer */
+ *buf = p;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__encode_cache_image_header() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__encode_cache_image_entry()
+ *
+ * Purpose: Encode the metadata cache image buffer header in the
+ * supplied buffer. Updates buffer pointer to the first byte
+ * after the entry in the buffer, or unchanged on failure.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: John Mainzer
+ * 8/6/15
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__encode_cache_image_entry(H5F_t *f, H5C_t *cache_ptr, uint8_t **buf,
+ unsigned entry_num)
+{
+ H5C_image_entry_t * ie_ptr; /* Pointer to entry to encode */
+ uint8_t flags = 0; /* Flags for entry */
+ uint8_t * p; /* Pointer into cache image buffer */
+ unsigned u; /* Local index value */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(f);
+ HDassert(f->shared);
+ HDassert(cache_ptr == f->shared->cache);
+ HDassert(cache_ptr);
+ HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
+ HDassert(cache_ptr->close_warning_received);
+ HDassert(cache_ptr->image_ctl.generate_image);
+ HDassert(cache_ptr->index_len == 0);
+ HDassert(buf);
+ HDassert(*buf);
+ HDassert(entry_num < cache_ptr->num_entries_in_image);
+ ie_ptr = &((cache_ptr->image_entries)[entry_num]);
+ HDassert(ie_ptr->magic == H5C_IMAGE_ENTRY_T_MAGIC);
+
+ /* Get pointer to buffer to encode into */
+ p = *buf;
+
+ /* Encode type */
+ if((ie_ptr->type_id < 0) || (ie_ptr->type_id > 255))
+ HGOTO_ERROR(H5E_CACHE, H5E_BADRANGE, FAIL, "type_id out of range.")
+ *p++ = (uint8_t)(ie_ptr->type_id);
+
+ /* Compose and encode flags */
+ if(ie_ptr->is_dirty)
+ flags |= H5C__MDCI_ENTRY_DIRTY_FLAG;
+ if(ie_ptr->lru_rank > 0)
+ flags |= H5C__MDCI_ENTRY_IN_LRU_FLAG;
+ if(ie_ptr->fd_child_count > 0)
+ flags |= H5C__MDCI_ENTRY_IS_FD_PARENT_FLAG;
+ if(ie_ptr->fd_parent_count > 0)
+ flags |= H5C__MDCI_ENTRY_IS_FD_CHILD_FLAG;
+ *p++ = flags;
+
+ /* Encode ring */
+ *p++ = (uint8_t)(ie_ptr->ring);
+
+ /* Encode age */
+ *p++ = (uint8_t)(ie_ptr->age);
+
+ /* Validate and encode dependency child count */
+ if(ie_ptr->fd_child_count > H5C__MDCI_MAX_FD_CHILDREN)
+ HGOTO_ERROR(H5E_CACHE, H5E_BADRANGE, FAIL, "fd_child_count out of range")
+ UINT16ENCODE(p, (uint16_t)(ie_ptr->fd_child_count));
+
+ /* Validate and encode dirty dependency child count */
+ if(ie_ptr->fd_dirty_child_count > H5C__MDCI_MAX_FD_CHILDREN)
+ HGOTO_ERROR(H5E_CACHE, H5E_BADRANGE, FAIL, "fd_dirty_child_count out of range")
+ UINT16ENCODE(p, (uint16_t)(ie_ptr->fd_dirty_child_count));
+
+ /* Validate and encode dependency parent count */
+ if(ie_ptr->fd_parent_count > H5C__MDCI_MAX_FD_PARENTS)
+ HGOTO_ERROR(H5E_CACHE, H5E_BADRANGE, FAIL, "fd_parent_count out of rang.")
+ UINT16ENCODE(p, (uint16_t)(ie_ptr->fd_parent_count));
+
+ /* Encode index in LRU */
+ INT32ENCODE(p, ie_ptr->lru_rank);
+
+ /* Encode entry offset */
+ H5F_addr_encode(f, &p, ie_ptr->addr);
+
+ /* Encode entry length */
+ H5F_ENCODE_LENGTH(f, p, ie_ptr->size);
+
+ /* Verify expected length of entry image */
+ if((size_t)(p - *buf) != H5C__cache_image_block_entry_header_size(f))
+ HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "Bad entry image len")
+
+ /* Encode dependency parent offsets -- if any */
+ for(u = 0; u < ie_ptr->fd_parent_count; u++)
+ H5F_addr_encode(f, &p, ie_ptr->fd_parent_addrs[u]);
+
+ /* Copy entry image */
+ HDmemcpy(p, ie_ptr->image_ptr, ie_ptr->size);
+ p += ie_ptr->size;
+
+ /* Update buffer pointer */
+ *buf = p;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__encode_cache_image_entry() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__prep_for_file_close__compute_fd_heights
+ *
+ * Purpose: Recent modifications to flush dependency support in the
+ * metadata cache have removed the notion of flush dependency
+ * height. This is a problem for the cache image feature,
+ * as flush dependency height is used to order entries in the
+ * cache image so that flush dependency parents appear before
+ * flush dependency children. (Recall that the flush dependency
+ * height of an entry in a flush dependency relationship is the
+ * length of the longest path from the entry to a leaf entry --
+ * that is an entry with flush dependency parents, but no
+ * flush dependency children. With the introduction of the
+ * possibility of multiple flush dependency parents, we have
+ * a flush partial dependency latice, not a flush dependency
+ * tree. But since the partial latice is acyclic, the concept
+ * of flush dependency height still makes sense.
+ *
+ * The purpose of this function is to compute the flush
+ * dependency height of all entries that appear in the cache
+ * image.
+ *
+ * At present, entries are included or excluded from the
+ * cache image depending upon the ring in which they reside.
+ * Thus there is no chance that one side of a flush dependency
+ * will be in the cache image, and the other side not.
+ *
+ * However, once we start placing a limit on the size of the
+ * cache image, or start excluding prefetched entries from
+ * the cache image if they haven't been accessed in some
+ * number of file close / open cycles, this will no longer
+ * be the case.
+ *
+ * In particular, if a flush dependency child is dirty, and
+ * one of its flush dependency parents is dirty and not in
+ * the cache image, then the flush dependency child cannot
+ * be in the cache image without violating flush ordering.
+ *
+ * Observe that a clean flush dependency child can be either
+ * in or out of the cache image without effect on flush
+ * dependencies.
+ *
+ * Similarly, a flush dependency parent can always be part
+ * of a cache image, regardless of whether it is clean or
+ * dirty -- but remember that a flush dependency parent can
+ * also be a flush dependency child.
+ *
+ * Finally, note that for purposes of the cache image, flush
+ * dependency height ends when a flush dependecy relation
+ * passes off the cache image.
+ *
+ * On exit, the flush dependency height of each entry in the
+ * cache image should be calculated and stored in the cache
+ * entry. Entries will be removed from the cache image if
+ * necessary to maintain flush ordering.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: John Mainzer
+ * 9/6/16
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__prep_for_file_close__compute_fd_heights(const H5C_t *cache_ptr)
+{
+ H5C_cache_entry_t * entry_ptr;
+ H5C_cache_entry_t * parent_ptr;
+ unsigned entries_removed_from_image = 0;
+ unsigned external_parent_fd_refs_removed = 0;
+ unsigned external_child_fd_refs_removed = 0;
+ hbool_t done = FALSE;
+ unsigned u; /* Local index variable */
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* sanity checks */
+ HDassert(cache_ptr);
+ HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
+
+ /* Remove from the cache image all dirty entries that are
+ * flush dependency children of dirty entries that are not in the
+ * cache image. Must do this, as if we fail to do so, the parent
+ * will be written to file before the child. Since it is possible
+ * that the child will have dirty children of its own, this may take
+ * multiple passes through the index list.
+ */
+ done = FALSE;
+ while(!done) {
+ done = TRUE;
+ entry_ptr = cache_ptr->il_head;
+ while(entry_ptr != NULL) {
+ HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+
+ /* Should this entry be in the image */
+ if(entry_ptr->image_dirty && entry_ptr->include_in_image &&
+ (entry_ptr->fd_parent_count > 0)) {
+ HDassert(entry_ptr->flush_dep_parent != NULL);
+ for(u = 0; u < entry_ptr->flush_dep_nparents; u++ ) {
+ parent_ptr = entry_ptr->flush_dep_parent[u];
+
+ /* Sanity check parent */
+ HDassert(parent_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(entry_ptr->ring == parent_ptr->ring);
+
+ if(parent_ptr->is_dirty && !parent_ptr->include_in_image &&
+ entry_ptr->include_in_image) {
+
+ /* Must remove child from image -- only do this once */
+ entries_removed_from_image++;
+ entry_ptr->include_in_image = FALSE;
+ } /* end if */
+ } /* for */
+ } /* end if */
+
+ entry_ptr = entry_ptr->il_next;
+ } /* while ( entry_ptr != NULL ) */
+ } /* while ( ! done ) */
+
+ /* at present, entries are included in the cache image if they reside
+ * in a specified set of rings. Thus it should be impossible for
+ * entries_removed_from_image to be positive. Assert that this is
+ * so. Note that this will change when we start aging entries out
+ * of the cache image.
+ */
+ HDassert(entries_removed_from_image == 0);
+
+ /* Next, remove from entries in the cache image, references to
+ * flush dependency parents or children that are not in the cache image.
+ */
+ entry_ptr = cache_ptr->il_head;
+ while(entry_ptr != NULL) {
+ if(!entry_ptr->include_in_image && entry_ptr->flush_dep_nparents > 0) {
+ HDassert(entry_ptr->flush_dep_parent != NULL);
+
+ for(u = 0; u < entry_ptr->flush_dep_nparents; u++ ) {
+ parent_ptr = entry_ptr->flush_dep_parent[u];
+
+ /* Sanity check parent */
+ HDassert(parent_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(entry_ptr->ring == parent_ptr->ring);
+
+ if(parent_ptr->include_in_image) {
+ /* Must remove reference to child */
+ HDassert(parent_ptr->fd_child_count > 0);
+ parent_ptr->fd_child_count--;
+
+ if(entry_ptr->is_dirty) {
+ HDassert(parent_ptr->fd_dirty_child_count > 0);
+ parent_ptr->fd_dirty_child_count--;
+ } /* end if */
+
+ external_child_fd_refs_removed++;
+ } /* end if */
+ } /* for */
+ } /* end if */
+ else if(entry_ptr->include_in_image && entry_ptr->flush_dep_nparents > 0) {
+ /* Sanity checks */
+ HDassert(entry_ptr->flush_dep_parent != NULL);
+ HDassert(entry_ptr->flush_dep_nparents == entry_ptr->fd_parent_count);
+ HDassert(entry_ptr->fd_parent_addrs);
+
+ for(u = 0; u < entry_ptr->flush_dep_nparents; u++ ) {
+ parent_ptr = entry_ptr->flush_dep_parent[u];
+
+ /* Sanity check parent */
+ HDassert(parent_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(entry_ptr->ring == parent_ptr->ring);
+
+ if(!parent_ptr->include_in_image) {
+ /* Must remove reference to parent */
+ HDassert(entry_ptr->fd_parent_count > 0);
+ parent_ptr->fd_child_count--;
+
+ HDassert(parent_ptr->addr == entry_ptr->fd_parent_addrs[u]);
+
+ entry_ptr->fd_parent_addrs[u] = HADDR_UNDEF;
+ external_parent_fd_refs_removed++;
+ } /* end if */
+ } /* for */
+
+ /* Touch up fd_parent_addrs array if necessary */
+ if(entry_ptr->fd_parent_count == 0) {
+ H5MM_xfree(entry_ptr->fd_parent_addrs);
+ entry_ptr->fd_parent_addrs = NULL;
+ } /* end if */
+ else if(entry_ptr->flush_dep_nparents > entry_ptr->fd_parent_count) {
+ haddr_t * old_fd_parent_addrs = entry_ptr->fd_parent_addrs;
+ unsigned v;
+
+ if(NULL == (entry_ptr->fd_parent_addrs = (haddr_t *)H5MM_calloc(sizeof(haddr_t) * (size_t)(entry_ptr->fd_parent_addrs))))
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, "memory allocation failed for fd parent addr array")
+
+ v = 0;
+ for(u = 0; u < entry_ptr->flush_dep_nparents; u++) {
+ if(old_fd_parent_addrs[u] != HADDR_UNDEF) {
+ entry_ptr->fd_parent_addrs[v] = old_fd_parent_addrs[u];
+ v++;
+ } /* end if */
+ } /* end for */
+
+ HDassert(v == entry_ptr->fd_parent_count);
+ } /* end else-if */
+ } /* end else-if */
+
+ entry_ptr = entry_ptr->il_next;
+ } /* while (entry_ptr != NULL) */
+
+ /* At present, no extenal parent or child flush dependency links
+ * should exist -- hence the following assertions. This will change
+ * if we support ageout of entries in the cache image.
+ */
+ HDassert(external_child_fd_refs_removed == 0);
+ HDassert(external_parent_fd_refs_removed == 0);
+
+ /* At this point we should have removed all flush dependencies that
+ * cross cache image boundaries. Now compute the flush dependency
+ * heights for all entries in the image.
+ *
+ * Until I can think of a better way, do this via a depth first
+ * search implemented via a recursive function call.
+ *
+ * Note that entry_ptr->image_fd_height has already been initialized to 0
+ * for all entries that may appear in the cache image.
+ */
+ entry_ptr = cache_ptr->il_head;
+ while(entry_ptr != NULL ) {
+ if(entry_ptr->include_in_image && entry_ptr->fd_child_count == 0 &&
+ entry_ptr->fd_parent_count > 0) {
+ for(u = 0; u < entry_ptr->fd_parent_count; u++ ) {
+ parent_ptr = entry_ptr->flush_dep_parent[u];
+
+ HDassert(parent_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ if(parent_ptr->include_in_image && parent_ptr->image_fd_height <= 0)
+ H5C__prep_for_file_close__compute_fd_heights_real(parent_ptr, 1);
+ } /* end for */
+ } /* end if */
+
+ entry_ptr = entry_ptr->il_next;
+ } /* while (entry_ptr != NULL) */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__prep_for_file_close__compute_fd_heights() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__prep_for_file_close__compute_fd_heights_real
+ *
+ * Purpose: H5C__prep_for_file_close__compute_fd_heights() prepares
+ * for the computation of flush dependency heights of all
+ * entries in the cache image, this function actually does
+ * it.
+ *
+ * The basic observation behind this function is as follows:
+ *
+ * Suppose you have an entry E with a flush dependency
+ * height of X. Then the parents of E must all have
+ * flush dependency X + 1 or greater.
+ *
+ * Use this observation to compute flush dependency height
+ * of all entries in the cache image via the following
+ * recursive algorithm:
+ *
+ * 1) On entry, set the flush dependency height of the
+ * supplied cache entry to the supplied value.
+ *
+ * 2) Examine all the flush dependency parents of the
+ * supplied entry.
+ *
+ * If the parent is in the cache image, and has flush
+ * dependency height less than or equal to the flush
+ * dependency height of the current entry, call the
+ * recursive routine on the parent with flush dependency
+ * height equal to the flush dependency height of the
+ * child plus 1.
+ *
+ * Otherwise do nothing.
+ *
+ * Observe that if the flush dependency height of all entries
+ * in the image is initialized to zero, and if this recursive
+ * function is called with flush dependency height 0 on all
+ * entries in the cache image with FD parents in the image,
+ * but without FD children in the image, the correct flush
+ * dependency height should be set for all entries in the
+ * cache image.
+ *
+ * Return: void
+ *
+ * Programmer: John Mainzer
+ * 9/6/16
+ *
+ *-------------------------------------------------------------------------
+ */
+static void
+H5C__prep_for_file_close__compute_fd_heights_real(H5C_cache_entry_t *entry_ptr,
+ uint32_t fd_height)
+{
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Sanity checks */
+ HDassert(entry_ptr);
+ HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(entry_ptr->include_in_image);
+ HDassert((entry_ptr->image_fd_height == 0) || (entry_ptr->image_fd_height < fd_height));
+ HDassert(((fd_height == 0) && (entry_ptr->fd_child_count == 0)) || ((fd_height > 0) && (entry_ptr->fd_child_count > 0)));
+
+ entry_ptr->image_fd_height = fd_height;
+ if(entry_ptr->flush_dep_nparents > 0) {
+ unsigned u;
+
+ HDassert(entry_ptr->flush_dep_parent);
+ for(u = 0; u < entry_ptr->fd_parent_count; u++) {
+ H5C_cache_entry_t *parent_ptr;
+
+ parent_ptr = entry_ptr->flush_dep_parent[u];
+ HDassert(parent_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+
+ if(parent_ptr->include_in_image && parent_ptr->image_fd_height <= fd_height)
+ H5C__prep_for_file_close__compute_fd_heights_real(parent_ptr, fd_height + 1);
+ } /* end for */
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI_VOID
+} /* H5C__prep_for_file_close__compute_fd_heights_real() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__prep_for_file_close__setup_image_entries_array
+ *
+ * Purpose: Allocate space for the image_entries array, and load
+ * each instance of H5C_image_entry_t in the array with
+ * the data necessary to construct the metadata cache image.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: John Mainzer
+ * 8/4/15
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__prep_for_file_close__setup_image_entries_array(H5C_t *cache_ptr)
+{
+ H5C_cache_entry_t * entry_ptr;
+ H5C_image_entry_t * image_entries = NULL;
+ uint32_t entries_visited = 0;
+ unsigned u; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(cache_ptr);
+ HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
+ HDassert(cache_ptr->close_warning_received);
+ HDassert(cache_ptr->pl_len == 0);
+ HDassert(cache_ptr->num_entries_in_image > 0);
+ HDassert(cache_ptr->image_entries == NULL);
+
+ /* Allocate and initialize image_entries array */
+ if(NULL == (image_entries = (H5C_image_entry_t *)H5MM_malloc(sizeof(H5C_image_entry_t) * (size_t)(cache_ptr->num_entries_in_image + 1))))
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, "memory allocation failed for image_entries")
+
+ for(u = 0; u <= cache_ptr->num_entries_in_image; u++) {
+ image_entries[u].magic = H5C_IMAGE_ENTRY_T_MAGIC;
+ image_entries[u].addr = HADDR_UNDEF;
+ image_entries[u].size = 0;
+ image_entries[u].ring = H5C_RING_UNDEFINED;
+ image_entries[u].age = 0;
+ image_entries[u].type_id = -1;
+ image_entries[u].lru_rank = 0;
+ image_entries[u].is_dirty = FALSE;
+ image_entries[u].image_fd_height = 0;
+ image_entries[u].fd_parent_count = 0;
+ image_entries[u].fd_parent_addrs = NULL;
+ image_entries[u].fd_child_count = 0;
+ image_entries[u].fd_dirty_child_count = 0;
+ image_entries[u].image_ptr = NULL;
+ } /* end for */
+
+ /* Scan each entry on the index list and populate the image_entries array */
+ u = 0;
+ entry_ptr = cache_ptr->il_head;
+ while(entry_ptr != NULL) {
+ HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+
+ if(entry_ptr->include_in_image) {
+ /* Since we have already serialized the cache, the following
+ * should hold.
+ */
+ HDassert(entry_ptr->image_up_to_date);
+ HDassert(entry_ptr->image_ptr);
+ HDassert(entry_ptr->type);
+
+ image_entries[u].addr = entry_ptr->addr;
+ image_entries[u].size = entry_ptr->size;
+ image_entries[u].ring = entry_ptr->ring;
+
+ /* When a prefetched entry is included in the image, store
+ * its underlying type id in the image entry, not
+ * H5AC_PREFETCHED_ENTRY_ID. In passing, also increment
+ * the age (up to H5AC__CACHE_IMAGE__ENTRY_AGEOUT__MAX).
+ */
+ if(entry_ptr->type->id == H5AC_PREFETCHED_ENTRY_ID) {
+ image_entries[u].type_id = entry_ptr->prefetch_type_id;
+ image_entries[u].age = entry_ptr->age + 1;
+
+ if(image_entries[u].age > H5AC__CACHE_IMAGE__ENTRY_AGEOUT__MAX)
+ image_entries[u].age = H5AC__CACHE_IMAGE__ENTRY_AGEOUT__MAX;
+ } /* end if */
+ else {
+ image_entries[u].type_id = entry_ptr->type->id;
+ image_entries[u].age = 0;
+ } /* end else */
+
+ image_entries[u].lru_rank = entry_ptr->lru_rank;
+ image_entries[u].is_dirty = entry_ptr->is_dirty;
+ image_entries[u].image_fd_height = entry_ptr->image_fd_height;
+ image_entries[u].fd_parent_count = entry_ptr->fd_parent_count;
+ image_entries[u].fd_parent_addrs = entry_ptr->fd_parent_addrs;
+ image_entries[u].fd_child_count = entry_ptr->fd_child_count;
+ image_entries[u].fd_dirty_child_count =
+ entry_ptr->fd_dirty_child_count;
+ image_entries[u].image_ptr = entry_ptr->image_ptr;
+
+ /* Null out entry_ptr->fd_parent_addrs and set
+ * entry_ptr->fd_parent_count to zero so that ownership of the
+ * flush dependency parents address array is transferred to the
+ * image entry.
+ */
+ entry_ptr->fd_parent_count = 0;
+ entry_ptr->fd_parent_addrs = NULL;
+
+ u++;
+
+ HDassert(u <= cache_ptr->num_entries_in_image);
+ } /* end if */
+
+ entries_visited++;
+
+ entry_ptr = entry_ptr->il_next;
+ } /* end while */
+
+ /* Sanity checks */
+ HDassert(entries_visited == cache_ptr->index_len);
+ HDassert(u == cache_ptr->num_entries_in_image);
+
+ HDassert(image_entries[u].fd_parent_addrs == NULL);
+ HDassert(image_entries[u].image_ptr == NULL);
+
+ cache_ptr->image_entries = image_entries;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__prep_for_file_close__setup_image_entries_array() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__prep_for_file_close__scan_entries
+ *
+ * Purpose: Scan all entries in the metadata cache, and store all
+ * entry specific data required for construction of the
+ * metadata cache image block and likely to be discarded
+ * or modified during the cache flush on file close.
+ *
+ * In particular, make note of:
+ * entry rank in LRU
+ * whether the entry is dirty
+ * base address of entry flush dependency parent,
+ * if it exists.
+ * number of flush dependency children, if any.
+ *
+ * Also, determine which entries are to be included in the
+ * metadata cache image. At present, all entries other than
+ * the superblock, the superblock extension object header and
+ * its associated chunks (if any) are included.
+ *
+ * Finally, compute the size of the metadata cache image
+ * block.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: John Mainzer
+ * 7/21/15
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__prep_for_file_close__scan_entries(const H5F_t *f, H5C_t *cache_ptr)
+{
+ H5C_cache_entry_t * entry_ptr;
+ hbool_t include_in_image;
+ unsigned entries_visited = 0;
+ int lru_rank = 1;
+ uint32_t num_entries_tentatively_in_image = 0;
+ uint32_t num_entries_in_image = 0;
+ size_t image_len;
+ size_t entry_header_len;
+ size_t fd_parents_list_len;
+ int i;
+ unsigned j;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(f);
+ HDassert(f->shared);
+ HDassert(f->shared->sblock);
+ HDassert(cache_ptr);
+ HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
+ HDassert(cache_ptr->close_warning_received);
+ HDassert(cache_ptr->pl_len == 0);
+
+ /* Initialize image len to the size of the metadata cache image block
+ * header.
+ */
+ image_len = H5C__cache_image_block_header_size(f);
+ entry_header_len = H5C__cache_image_block_entry_header_size(f);
+
+ /* Scan each entry on the index list */
+ entry_ptr = cache_ptr->il_head;
+ while(entry_ptr != NULL) {
+ HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+
+ /* Since we have already serialized the cache, the following
+ * should hold.
+ */
+ HDassert(entry_ptr->image_up_to_date);
+ HDassert(entry_ptr->image_ptr);
+
+ /* Initially, we mark all entries in the rings included
+ * in the cache image as being included in the in the
+ * image. Depending on circumstances, we may exclude some
+ * of these entries later.
+ */
+ if(entry_ptr->ring > H5C_MAX_RING_IN_IMAGE)
+ include_in_image = FALSE;
+ else
+ include_in_image = TRUE;
+ entry_ptr->include_in_image = include_in_image;
+
+ if(include_in_image) {
+ entry_ptr->lru_rank = -1;
+ entry_ptr->image_dirty = entry_ptr->is_dirty;
+ entry_ptr->image_fd_height = 0; /* will compute this later */
+
+ /* Initially, include all flush dependency parents in the
+ * the list of flush dependencies to be stored in the
+ * image. We may remove some or all of these later.
+ */
+ if(entry_ptr->flush_dep_nparents > 0) {
+ /* The parents addresses array may already exist -- reallocate
+ * as needed.
+ */
+ if(entry_ptr->flush_dep_nparents == entry_ptr->fd_parent_count ) {
+ /* parent addresses array should already be allocated
+ * and of the correct size.
+ */
+ HDassert(entry_ptr->fd_parent_addrs);
+ } /* end if */
+ else if(entry_ptr->fd_parent_count > 0) {
+ HDassert(entry_ptr->fd_parent_addrs);
+ entry_ptr->fd_parent_addrs = (haddr_t *)H5MM_xfree(entry_ptr->fd_parent_addrs);
+ } /* end else-if */
+ else {
+ HDassert(entry_ptr->fd_parent_count == 0);
+ HDassert(entry_ptr->fd_parent_addrs == NULL);
+ } /* end else */
+
+ entry_ptr->fd_parent_count = entry_ptr->flush_dep_nparents;
+ if(NULL == entry_ptr->fd_parent_addrs)
+ if(NULL == (entry_ptr->fd_parent_addrs = (haddr_t *)H5MM_malloc(sizeof(haddr_t) * (size_t)(entry_ptr->fd_parent_count))))
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, "memory allocation failed for fd parent addrs buffer")
+
+ for(i = 0; i < (int)(entry_ptr->fd_parent_count); i++) {
+ entry_ptr->fd_parent_addrs[i] = entry_ptr->flush_dep_parent[i]->addr;
+ HDassert(H5F_addr_defined(entry_ptr->fd_parent_addrs[i]));
+ } /* end for */
+ } /* end if */
+ else if(entry_ptr->fd_parent_count > 0) {
+ HDassert(entry_ptr->fd_parent_addrs);
+ entry_ptr->fd_parent_addrs = (haddr_t *)H5MM_xfree(entry_ptr->fd_parent_addrs);
+ } /* end else-if */
+ else
+ HDassert(entry_ptr->fd_parent_addrs == NULL);
+
+ /* Initially, all flush dependency children are included int
+ * the count of flush dependency child relationships to be
+ * represented in the cache image. Some or all of these
+ * may be dropped from the image later.
+ */
+ if(entry_ptr->flush_dep_nchildren > 0) {
+ if(!entry_ptr->is_pinned)
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "encountered unpinned fd parent?!?")
+
+ entry_ptr->fd_child_count = entry_ptr->flush_dep_nchildren;
+ entry_ptr->fd_dirty_child_count = entry_ptr->flush_dep_ndirty_children;
+ } /* end if */
+
+ num_entries_tentatively_in_image++;
+ } /* end if */
+
+ entries_visited++;
+ entry_ptr = entry_ptr->il_next;
+ } /* end while */
+ HDassert(entries_visited == cache_ptr->index_len);
+
+ /* Now compute the flush dependency heights of all flush dependency
+ * relationships to be represented in the image.
+ *
+ * If all entries in the target rings are included in the
+ * image, the flush dependency heights are simply the heights
+ * of all flush dependencies in the target rings.
+ *
+ * However, if we restrict appearance in the cache image either
+ * by number of entries in the image, restrictions on the number
+ * of times a prefetched entry can appear in an image, or image
+ * size, it is possible that flush dependency parents or children
+ * of entries that are in the image may not be included in the
+ * the image. In this case, we must prune all flush dependency
+ * relationships that cross the image boundary, and all exclude
+ * from the image all dirty flush dependency children that have
+ * a dirty flush dependency parent that is not in the image.
+ * This is necessary to preserve the required flush ordering.
+ *
+ * These details are tended to by the following call to
+ * H5C__prep_for_file_close__compute_fd_heights(). Because the
+ * exact contents of the image cannot be known until after this
+ * call, computation of the image size is delayed.
+ */
+ if(H5C__prep_for_file_close__compute_fd_heights(cache_ptr) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "computation of flush dependency heights failed?!?")
+
+ /* At this point, all entries that will appear in the cache
+ * image should be marked correctly. Compute the size of the
+ * cache image.
+ */
+ entries_visited = 0;
+ entry_ptr = cache_ptr->il_head;
+ while(entry_ptr != NULL) {
+ HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+
+ if(entry_ptr->include_in_image) {
+ if(entry_ptr->fd_parent_count > 0)
+ fd_parents_list_len = (size_t)(H5F_SIZEOF_ADDR(f) * entry_ptr->fd_parent_count);
+ else
+ fd_parents_list_len = (size_t)0;
+
+ image_len += entry_header_len + fd_parents_list_len + entry_ptr->size;
+ num_entries_in_image++;
+ } /* end if */
+
+ entries_visited++;
+ entry_ptr = entry_ptr->il_next;
+ } /* end while */
+ HDassert(entries_visited == cache_ptr->index_len);
+ HDassert(num_entries_in_image <= num_entries_tentatively_in_image);
+
+ j = 0;
+ for(i = H5C_MAX_RING_IN_IMAGE + 1; i <= H5C_RING_SB; i++)
+ j += cache_ptr->index_ring_len[i];
+
+ /* This will change */
+ HDassert(entries_visited == (num_entries_tentatively_in_image + j));
+
+ cache_ptr->num_entries_in_image = num_entries_in_image;
+ entries_visited = 0;
+
+ /* Now scan the LRU list to set the lru_rank fields of all entries
+ * on the LRU.
+ *
+ * Note that we start with rank 1, and increment by 1 with each
+ * entry on the LRU.
+ *
+ * Note that manually pinned entryies will have lru_rank -1,
+ * and no flush dependency. Putting these entries at the head of
+ * the reconstructed LRU should be appropriate.
+ */
+ entry_ptr = cache_ptr->LRU_head_ptr;
+ while(entry_ptr != NULL) {
+ HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(entry_ptr->type != NULL);
+
+ /* to avoid confusion, don't set lru_rank on epoch markers.
+ * Note that we still increment the lru_rank, so that the holes
+ * in the sequence of entries on the LRU will indicate the
+ * locations of epoch markers (if any) when we reconstruct
+ * the LRU.
+ *
+ * Do not set lru_rank or increment lru_rank for entries
+ * that will not be included in the cache image.
+ */
+ if(entry_ptr->type->id == H5AC_EPOCH_MARKER_ID)
+ lru_rank++;
+ else if(entry_ptr->include_in_image) {
+ entry_ptr->lru_rank = lru_rank;
+ lru_rank++;
+ } /* end else-if */
+
+ entries_visited++;
+ entry_ptr = entry_ptr->next;
+ } /* end while */
+ HDassert(entries_visited == cache_ptr->LRU_list_len);
+
+ image_len += H5F_SIZEOF_CHKSUM;
+ cache_ptr->image_data_len = image_len;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__prep_for_file_close__scan_entries() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__reconstruct_cache_contents()
+ *
+ * Purpose: Scan the image_entries array, and create a prefetched
+ * cache entry for every entry in the array. Insert the
+ * prefetched entries in the index and the LRU, and
+ * reconstruct any flush dependencies. Order the entries
+ * in the LRU as indicated by the stored lru_ranks.
+ *
+ * Return: SUCCEED on success, and FAIL on failure.
+ *
+ * Programmer: John Mainzer
+ * 8/14/15
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__reconstruct_cache_contents(H5F_t *f, hid_t dxpl_id, H5C_t *cache_ptr)
+{
+ H5C_cache_entry_t * pf_entry_ptr; /* Pointer to prefetched entry */
+ H5C_cache_entry_t * parent_ptr; /* Pointer to parent of prefetched entry */
+ unsigned u, v; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(f);
+ HDassert(f->shared);
+ HDassert(cache_ptr == f->shared->cache);
+ HDassert(cache_ptr);
+ HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
+ HDassert(cache_ptr->image_buffer);
+ HDassert(cache_ptr->image_len > 0);
+ HDassert(cache_ptr->image_entries != NULL);
+ HDassert(cache_ptr->num_entries_in_image > 0);
+
+ /* Reconstruct entries in image */
+ for(u = 0; u < cache_ptr->num_entries_in_image; u++) {
+ /* Create the prefetched entry described by the ith
+ * entry in cache_ptr->image_entrise.
+ */
+ if(NULL == (pf_entry_ptr = H5C__reconstruct_cache_entry(cache_ptr, u)))
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "reconstruction of cache entry failed")
+
+ /* Note that we make no checks on available cache space before
+ * inserting the reconstructed entry into the metadata cache.
+ *
+ * This is OK since the cache must be almost empty at the beginning
+ * of the process, and since we check cache size at the end of the
+ * reconstruction process.
+ */
+
+ /* Insert the prefetched entry in the index */
+ H5C__INSERT_IN_INDEX(cache_ptr, pf_entry_ptr, FAIL)
+
+ /* If dirty, insert the entry into the slist. */
+ if(pf_entry_ptr->is_dirty)
+ H5C__INSERT_ENTRY_IN_SLIST(cache_ptr, pf_entry_ptr, FAIL)
+
+ /* Append the entry to the LRU */
+ H5C__UPDATE_RP_FOR_INSERT_APPEND(cache_ptr, pf_entry_ptr, FAIL)
+
+ H5C__UPDATE_STATS_FOR_PREFETCH(cache_ptr, pf_entry_ptr->is_dirty)
+
+ /* If the prefetched entry is the child in one or more flush
+ * dependency relationships, recreate those flush dependencies.
+ */
+ for(v = 0; v < pf_entry_ptr->fd_parent_count; v++) {
+ /* Sanity checks */
+ HDassert(pf_entry_ptr->fd_parent_addrs);
+ HDassert(H5F_addr_defined(pf_entry_ptr->fd_parent_addrs[v]));
+
+ /* Find the parent entry */
+ parent_ptr = NULL;
+ H5C__SEARCH_INDEX(cache_ptr, pf_entry_ptr->fd_parent_addrs[v], parent_ptr, FAIL)
+ if(parent_ptr == NULL)
+ HGOTO_ERROR(H5E_CACHE, H5E_NOTFOUND, FAIL, "fd parent not in cache?!?")
+
+ /* Sanity checks */
+ HDassert(parent_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(parent_ptr->addr == pf_entry_ptr->fd_parent_addrs[v]);
+ HDassert(parent_ptr->lru_rank == -1);
+
+ /* Must protect parent entry to set up a flush dependency.
+ * Do this now, and then uprotect when done.
+ */
+ H5C__UPDATE_RP_FOR_PROTECT(cache_ptr, parent_ptr, FAIL)
+ parent_ptr->is_protected = TRUE;
+
+ /* Setup the flush dependency */
+ if(H5C_create_flush_dependency(parent_ptr, pf_entry_ptr) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTDEPEND, FAIL, "Can't restore flush dependency")
+
+ /* And now unprotect */
+ H5C__UPDATE_RP_FOR_UNPROTECT(cache_ptr, parent_ptr, FAIL)
+ parent_ptr->is_protected = FALSE;
+ } /* end for */
+ } /* end for */
+
+#ifndef NDEBUG
+ /* Scan the image_entries array, and verify that each entry has
+ * the expected flush dependency status.
+ */
+ for(u = 0; u < cache_ptr->num_entries_in_image; u++) {
+ H5C_image_entry_t * ie_ptr;
+
+ ie_ptr = &(cache_ptr->image_entries[u]);
+ HDassert(ie_ptr->magic == H5C_IMAGE_ENTRY_T_MAGIC);
+
+ /* Find the prefetched entry */
+ pf_entry_ptr = NULL;
+ H5C__SEARCH_INDEX(cache_ptr, ie_ptr->addr, pf_entry_ptr, FAIL);
+
+ HDassert(pf_entry_ptr);
+ HDassert(pf_entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(pf_entry_ptr->prefetched);
+ HDassert(ie_ptr->fd_parent_count == pf_entry_ptr->fd_parent_count);
+ HDassert(pf_entry_ptr->fd_parent_count == pf_entry_ptr->flush_dep_nparents);
+ HDassert(ie_ptr->lru_rank == pf_entry_ptr->lru_rank);
+
+ for(v = 0; v < pf_entry_ptr->fd_parent_count; v++) {
+ parent_ptr = pf_entry_ptr->flush_dep_parent[v];
+ HDassert(parent_ptr);
+ HDassert(parent_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(pf_entry_ptr->fd_parent_addrs);
+ HDassert(pf_entry_ptr->fd_parent_addrs[v] == parent_ptr->addr);
+ HDassert(parent_ptr->flush_dep_nchildren > 0);
+ } /* end for */
+
+ HDassert(ie_ptr->fd_child_count == pf_entry_ptr->fd_child_count);
+ HDassert(pf_entry_ptr->fd_child_count == pf_entry_ptr->flush_dep_nchildren);
+ HDassert(pf_entry_ptr->fd_dirty_child_count == pf_entry_ptr->flush_dep_ndirty_children);
+ } /* end for */
+
+ /* Scan the LRU, and verify the expected ordering of the
+ * prefetched entries.
+ */
+ {
+ int lru_rank_holes = 0;
+ H5C_cache_entry_t *entry_ptr;
+ int i; /* Local index variable */
+
+ i = -1;
+ entry_ptr = cache_ptr->LRU_head_ptr;
+ while(entry_ptr != NULL) {
+ HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(entry_ptr->type != NULL);
+
+ if(entry_ptr->prefetched) {
+ HDassert(i <= entry_ptr->lru_rank);
+ HDassert((entry_ptr->lru_rank <= 2) ||
+ (entry_ptr->lru_rank == i + 1) ||
+ (entry_ptr->lru_rank == i + 2));
+
+ if((entry_ptr->lru_rank <= 2) && (entry_ptr->lru_rank == i + 2))
+ lru_rank_holes++;
+
+ i = entry_ptr->lru_rank;
+ } /* end if */
+
+ entry_ptr = entry_ptr->next;
+ } /* end while */
+
+ /* Holes of size 1 appear in the LRU ranking due to epoch
+ * markers. They are left in to allow re-insertion of the
+ * epoch markers on reconstruction of the cache -- thus
+ * the following sanity check will have to be revised when
+ * we add code to store and restore adaptive resize status.
+ */
+ HDassert(lru_rank_holes <= H5C__MAX_EPOCH_MARKERS);
+ } /* end block */
+#endif /* NDEBUG */
+
+ /* Check to see if the cache is oversize, and evict entries as
+ * necessary to remain within limits.
+ */
+ if(cache_ptr->index_size >= cache_ptr->max_cache_size) {
+ /* cache is oversized -- call H5C__make_space_in_cache() with zero
+ * space needed to repair the situation if possible.
+ */
+ hbool_t write_permitted = FALSE;
+
+ if(cache_ptr->check_write_permitted != NULL) {
+ if((cache_ptr->check_write_permitted)(f, &write_permitted) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTPROTECT, FAIL, "Can't get write_permitted")
+ } /* end if */
+ else
+ write_permitted = cache_ptr->write_permitted;
+
+ if(H5C__make_space_in_cache(f, dxpl_id, 0, write_permitted) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTPROTECT, FAIL, "H5C__make_space_in_cache failed")
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__reconstruct_cache_contents() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__reconstruct_cache_entry()
+ *
+ * Purpose: Allocate a prefetched metadata cache entry and initialize
+ * it from the indicated entry in the image_entries array.
+ *
+ * Return a pointer to the newly allocated cache entry,
+ * or NULL on failure.
+ *
+ * Return: Pointer to the new instance of H5C_cache_entry on success,
+ * or NULL on failure.
+ *
+ * Programmer: John Mainzer
+ * 8/14/15
+ *
+ *-------------------------------------------------------------------------
+ */
+static H5C_cache_entry_t *
+H5C__reconstruct_cache_entry(H5C_t *cache_ptr, unsigned index)
+{
+ H5C_cache_entry_t *pf_entry_ptr = NULL; /* Reconstructed cache entry */
+ H5C_image_entry_t *ie_ptr;
+ H5C_cache_entry_t *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(cache_ptr);
+ HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
+ HDassert(cache_ptr->image_entries != NULL);
+ HDassert(cache_ptr->num_entries_in_image > 0);
+ HDassert(index < cache_ptr->num_entries_in_image);
+ ie_ptr = &((cache_ptr->image_entries)[index]);
+ HDassert(ie_ptr->magic == H5C_IMAGE_ENTRY_T_MAGIC);
+ HDassert(H5F_addr_defined(ie_ptr->addr));
+ HDassert(ie_ptr->size > 0);
+ HDassert(ie_ptr->image_ptr);
+
+ /* Allocate space for the prefetched cache entry */
+ if(NULL == (pf_entry_ptr = H5FL_CALLOC(H5C_cache_entry_t)))
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, NULL, "memory allocation failed for prefetched cache entry")
+
+ /* Initialize the prefetched entry from the entry image */
+ /* (Only need to set non-zero/NULL/FALSE fields, due to calloc() above) */
+ pf_entry_ptr->magic = H5C__H5C_CACHE_ENTRY_T_MAGIC;
+ pf_entry_ptr->cache_ptr = cache_ptr;
+ pf_entry_ptr->addr = ie_ptr->addr;
+ pf_entry_ptr->size = ie_ptr->size;
+ pf_entry_ptr->ring = ie_ptr->ring;
+ pf_entry_ptr->age = ie_ptr->age;
+ pf_entry_ptr->image_ptr = ie_ptr->image_ptr;
+ pf_entry_ptr->image_up_to_date = TRUE;
+ pf_entry_ptr->type = H5AC_PREFETCHED_ENTRY;
+
+ /* Force dirty entries to clean if the file read only -- must do
+ * this as otherwise the cache will attempt to write them on file
+ * close. Since the file is R/O, the metadata cache image superblock
+ * extension message and the cache image block will not be removed.
+ * Hence no danger in this.
+ */
+ pf_entry_ptr->is_dirty = ie_ptr->is_dirty && cache_ptr->delete_image;
+
+ /* Initialize cache image related fields */
+ pf_entry_ptr->lru_rank = ie_ptr->lru_rank;
+ pf_entry_ptr->fd_parent_count = ie_ptr->fd_parent_count;
+ pf_entry_ptr->fd_parent_addrs = ie_ptr->fd_parent_addrs;
+ pf_entry_ptr->fd_child_count = ie_ptr->fd_child_count;
+ pf_entry_ptr->fd_dirty_child_count = ie_ptr->fd_dirty_child_count;
+ pf_entry_ptr->prefetched = TRUE;
+ pf_entry_ptr->prefetch_type_id = ie_ptr->type_id;
+ pf_entry_ptr->age = ie_ptr->age;
+
+ /* Array of addresses of flush dependency parents is now transferred to
+ * the prefetched entry. Thus set ie_ptr->fd_parent_addrs to NULL.
+ */
+ if(pf_entry_ptr->fd_parent_count > 0) {
+ HDassert(ie_ptr->fd_parent_addrs);
+ ie_ptr->fd_parent_addrs = NULL;
+ } /* end if */
+ else
+ HDassert(ie_ptr->fd_parent_addrs == NULL);
+
+ /* On disk image of entry is now transferred to the prefetched entry.
+ * Thus set ie_ptr->image_ptr to NULL.
+ */
+ ie_ptr->image_ptr = NULL;
+
+ /* Sanity checks */
+ HDassert(pf_entry_ptr->size > 0 && pf_entry_ptr->size < H5C_MAX_ENTRY_SIZE);
+
+ ret_value = pf_entry_ptr;
+
+done:
+ if(NULL == ret_value && pf_entry_ptr)
+ pf_entry_ptr = H5FL_FREE(H5C_cache_entry_t, pf_entry_ptr);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__reconstruct_cache_entry() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__serialize_cache
+ *
+ * Purpose: Serialize (i.e. construct an on disk image) for all entries
+ * in the metadata cache including clean entries.
+ *
+ * Note that flush dependencies and "flush me last" flags
+ * must be observed in the serialization process.
+ *
+ * Note also that entries may be loaded, flushed, evicted,
+ * expunged, relocated, resized, or removed from the cache
+ * during this process, just as these actions may occur during
+ * a regular flush.
+ *
+ * However, we are given that the cache will contain no protected
+ * entries on entry to this routine (although entries may be
+ * briefly protected and then unprotected during the serialize
+ * process).
+ *
+ * The objective of this routine is serialize all entries and
+ * to force all entries into their actual locations on disk.
+ *
+ * The initial need for this routine is to settle all entries
+ * in the cache prior to construction of the metadata cache
+ * image so that the size of the cache image can be calculated.
+ * However, I gather that other uses for the routine are
+ * under consideration.
+ *
+ * Return: Non-negative on success/Negative on failure or if there was
+ * a request to flush all items and something was protected.
+ *
+ * Programmer: John Mainzer
+ * 7/22/15
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__serialize_cache(H5F_t *f, hid_t dxpl_id)
+{
+#if H5C_DO_SANITY_CHECKS
+ int i;
+ uint32_t index_len = 0;
+ size_t index_size = (size_t)0;
+ size_t clean_index_size = (size_t)0;
+ size_t dirty_index_size = (size_t)0;
+ size_t slist_size = (size_t)0;
+ uint32_t slist_len = 0;
+#endif /* H5C_DO_SANITY_CHECKS */
+ H5C_ring_t ring;
+ H5C_t * cache_ptr;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(f);
+ HDassert(f->shared);
+ cache_ptr = f->shared->cache;
+ HDassert(cache_ptr);
+ HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
+ HDassert(cache_ptr->slist_ptr);
+
+#if H5C_DO_SANITY_CHECKS
+ HDassert(cache_ptr->index_ring_len[H5C_RING_UNDEFINED] == 0);
+ HDassert(cache_ptr->index_ring_size[H5C_RING_UNDEFINED] == (size_t)0);
+ HDassert(cache_ptr->clean_index_ring_size[H5C_RING_UNDEFINED] == (size_t)0);
+ HDassert(cache_ptr->dirty_index_ring_size[H5C_RING_UNDEFINED] == (size_t)0);
+ HDassert(cache_ptr->slist_ring_len[H5C_RING_UNDEFINED] == 0);
+ HDassert(cache_ptr->slist_ring_size[H5C_RING_UNDEFINED] == (size_t)0);
+
+ for(i = H5C_RING_USER; i < H5C_RING_NTYPES; i++) {
+ index_len += cache_ptr->index_ring_len[i];
+ index_size += cache_ptr->index_ring_size[i];
+ clean_index_size += cache_ptr->clean_index_ring_size[i];
+ dirty_index_size += cache_ptr->dirty_index_ring_size[i];
+
+ slist_len += cache_ptr->slist_ring_len[i];
+ slist_size += cache_ptr->slist_ring_size[i];
+ } /* end for */
+
+ HDassert(cache_ptr->index_len == index_len);
+ HDassert(cache_ptr->index_size == index_size);
+ HDassert(cache_ptr->clean_index_size == clean_index_size);
+ HDassert(cache_ptr->dirty_index_size == dirty_index_size);
+ HDassert(cache_ptr->slist_len == slist_len);
+ HDassert(cache_ptr->slist_size == slist_size);
+#endif /* H5C_DO_SANITY_CHECKS */
+
+#if H5C_DO_EXTREME_SANITY_CHECKS
+ if((H5C_validate_protected_entry_list(cache_ptr) < 0) ||
+ (H5C_validate_pinned_entry_list(cache_ptr) < 0) ||
+ (H5C_validate_lru_list(cache_ptr) < 0))
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "an extreme sanity check failed on entry.\n")
+#endif /* H5C_DO_EXTREME_SANITY_CHECKS */
+
+#ifndef NDEBUG
+ /* if this is a debug build, set the serialization_count field of
+ * each entry in the cache to zero before we start the serialization.
+ * This allows us to detect the case in which any entry is serialized
+ * more than once (a performance issues), and more importantly, the
+ * case is which any flush depencency parent is serializes more than
+ * once (a correctness issue).
+ */
+ {
+ H5C_cache_entry_t * scan_ptr = NULL;
+
+ scan_ptr = cache_ptr->il_head;
+ while(scan_ptr != NULL) {
+ HDassert(scan_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ scan_ptr->serialization_count = 0;
+ scan_ptr = scan_ptr->il_next;
+ } /* end while */
+ } /* end block */
+#endif /* NDEBUG */
+
+ /* set cache_ptr->serialization_in_progress to TRUE, and back
+ * to FALSE at the end of the function. Must maintain this flag
+ * to support H5C_get_serialization_in_progress(), which is in
+ * turn required to support sanity checking in some cache
+ * clients.
+ */
+ HDassert(!cache_ptr->serialization_in_progress);
+ cache_ptr->serialization_in_progress = TRUE;
+
+ /* Serialize each ring, starting from the outermost ring and
+ * working inward.
+ */
+ ring = H5C_RING_USER;
+ while(ring < H5C_RING_NTYPES) {
+ HDassert(cache_ptr->close_warning_received);
+ switch(ring) {
+ case H5C_RING_USER:
+ break;
+
+ case H5C_RING_RDFSM:
+ if(!cache_ptr->rdfsm_settled) {
+ hbool_t fsm_settled = FALSE; /* Whether the FSM was actually settled */
+
+ /* Settle raw data FSM */
+ if(H5MF_settle_raw_data_fsm(f, dxpl_id, &fsm_settled) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "RD FSM settle failed")
+
+ /* Only set the flag if the FSM was actually settled */
+ if(fsm_settled)
+ cache_ptr->rdfsm_settled = TRUE;
+ } /* end if */
+ break;
+
+ case H5C_RING_MDFSM:
+ if(!cache_ptr->mdfsm_settled) {
+ hbool_t fsm_settled = FALSE; /* Whether the FSM was actually settled */
+
+ /* Settle metadata FSM */
+ if(H5MF_settle_meta_data_fsm(f, dxpl_id, &fsm_settled) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "MD FSM settle failed")
+
+ /* Only set the flag if the FSM was actually settled */
+ if(fsm_settled)
+ cache_ptr->mdfsm_settled = TRUE;
+ } /* end if */
+ break;
+
+ case H5C_RING_SBE:
+ case H5C_RING_SB:
+ break;
+
+ default:
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Unknown ring?!?!")
+ break;
+ } /* end switch */
+
+ if(H5C__serialize_ring(f, dxpl_id, ring) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "serialize ring failed")
+
+ ring++;
+ } /* end while */
+
+#ifndef NDEBUG
+ /* Verify that no entry has been serialized more than once.
+ * FD parents with multiple serializations should have been caught
+ * elsewhere, so no specific check for them here.
+ */
+ {
+ H5C_cache_entry_t * scan_ptr = NULL;
+
+ scan_ptr = cache_ptr->il_head;
+ while(scan_ptr != NULL) {
+ HDassert(scan_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(scan_ptr->serialization_count <= 1);
+
+ scan_ptr = scan_ptr->il_next;
+ } /* end while */
+ } /* end block */
+#endif /* NDEBUG */
+
+done:
+ cache_ptr->serialization_in_progress = FALSE;
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__serialize_cache() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__serialize_ring
+ *
+ * Purpose: Serialize the entries contained in the specified cache and
+ * ring. All entries in rings outside the specified ring
+ * must have been serialized on entry.
+ *
+ * If the cache contains protected entries in the specified
+ * ring, the function will fail, as protected entries cannot
+ * be serialized. However all unprotected entries in the
+ * target ring should be serialized before the function
+ * returns failure.
+ *
+ * If flush dependencies appear in the target ring, the
+ * function makes repeated passes through the index list
+ * serializing entries in flush dependency order.
+ *
+ * All entries outside the H5C_RING_SBE are marked for
+ * inclusion in the cache image. Entries in H5C_RING_SBE
+ * and below are marked for exclusion from the image.
+ *
+ * Return: Non-negative on success/Negative on failure or if there was
+ * a request to flush all items and something was protected.
+ *
+ * Programmer: John Mainzer
+ * 9/11/15
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__serialize_ring(H5F_t *f, hid_t dxpl_id, H5C_ring_t ring)
+{
+ hbool_t done = FALSE;
+ hbool_t restart_list_scan = FALSE;
+ H5C_t * cache_ptr;
+ H5C_cache_entry_t * entry_ptr;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(f);
+ HDassert(f->shared);
+ cache_ptr = f->shared->cache;
+ HDassert(cache_ptr);
+ HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
+ HDassert(ring > H5C_RING_UNDEFINED);
+ HDassert(ring < H5C_RING_NTYPES);
+
+ HDassert(cache_ptr->serialization_in_progress);
+
+ /* The objective here is to serialize all entries in the cache ring
+ * in flush dependency order.
+ *
+ * The basic algorithm is to scan the cache index list looking for
+ * unserialized entries that are either not in a flush dependency
+ * relationship, or which have no unserialized children. Any such
+ * entry is serialized and its flush dependency parents (if any) are
+ * informed -- allowing them to decrement their userialized child counts.
+ *
+ * However, this algorithm is complicated by the ability
+ * of client serialization callbacks to perform operations on
+ * on the cache which can result in the insertion, deletion,
+ * relocation, resize, dirty, flush, eviction, or removal (via the
+ * take ownership flag) of entries. Changes in the flush dependency
+ * structure are also possible.
+ *
+ * On the other hand, the algorithm is simplified by the fact that
+ * we are serializing, not flushing. Thus, as long as all entries
+ * are serialized correctly, it doesn't matter if we have to go back
+ * and serialize an entry a second time.
+ *
+ * These possible actions result in the following modfications to
+ * tha basic algorithm:
+ *
+ * 1) In the event of an entry expunge, eviction or removal, we must
+ * restart the scan as it is possible that the next entry in our
+ * scan is no longer in the cache. Were we to examine this entry,
+ * we would be accessing deallocated memory.
+ *
+ * 2) A resize, dirty, or insertion of an entry may result in the
+ * the increment of a flush dependency parent's dirty and/or
+ * unserialized child count. In the context of serializing the
+ * the cache, this is a non-issue, as even if we have already
+ * serialized the parent, it will be marked dirty and its image
+ * marked out of date if appropriate when the child is serialized.
+ *
+ * However, this is a major issue for a flush, as were this to happen
+ * in a flush, it would violate the invarient that the flush dependency
+ * feature is intended to enforce. As the metadata cache has no
+ * control over the behavior of cache clients, it has no way of
+ * preventing this behaviour. However, it should detect it if at all
+ * possible.
+ *
+ * Do this by maintaining a count of the number of times each entry is
+ * serialized during a cache serialization. If any flush dependency
+ * parent is serialized more than once, throw an assertion failure.
+ *
+ * 3) An entry relocation will typically change the location of the
+ * entry in the index list. This shouldn't cause problems as we
+ * will scan the index list until we make a complete pass without
+ * finding anything to serialize -- making relocations of either
+ * the current or next entries irrelevant.
+ *
+ * Note that since a relocation may result in our skipping part of
+ * the index list, we must always do at least one more pass through
+ * the index list after an entry relocation.
+ *
+ * 4) Changes in the flush dependency structure are possible on
+ * entry insertion, load, expunge, evict, or remove. Destruction
+ * of a flush dependency has no effect, as it can only relax the
+ * flush dependencies. Creation of a flush dependency can create
+ * an unserialized child of a flush dependency parent where all
+ * flush dependency children were previously serialized. Should
+ * this child dirty the flush dependency parent when it is serialized,
+ * the parent will be re-serialized.
+ *
+ * Per the discussion of 2) above, this is a non issue for cache
+ * serialization, and a major problem for cache flush. Using the
+ * same detection mechanism, throw an assertion failure if this
+ * condition appears.
+ *
+ * Observe that either eviction or removal of entries as a result of
+ * a serialization is not a problem as long as the flush depencency
+ * tree does not change beyond the removal of a leaf.
+ */
+ while(!done) {
+ done = TRUE; /* set to FALSE if any activity in inner loop */
+ entry_ptr = cache_ptr->il_head;
+ while(entry_ptr != NULL) {
+ HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+
+ /* Verify that either the entry is already serialized, or
+ * that it is assigned to either the target or an inner
+ * ring.
+ */
+ HDassert((entry_ptr->ring >= ring) || (entry_ptr->image_up_to_date));
+
+ /* Skip flush me last entries or inner ring entries */
+ if(!entry_ptr->flush_me_last && entry_ptr->ring == ring) {
+
+ /* if we encounter an unserialized entry in the current
+ * ring that is not marked flush me last, we are not done.
+ */
+ if(!entry_ptr->image_up_to_date)
+ done = FALSE;
+
+ /* Serialize the entry if its image is not up to date
+ * and it has no unserialized flush dependency children.
+ */
+ if(!entry_ptr->image_up_to_date && entry_ptr->flush_dep_nunser_children == 0) {
+ HDassert(entry_ptr->serialization_count == 0);
+
+ /* Serialize the entry */
+ if(H5C__serialize_single_entry(f, dxpl_id, cache_ptr, entry_ptr, &restart_list_scan) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTSERIALIZE, FAIL, "entry serialization failed")
+
+ HDassert(entry_ptr->flush_dep_nunser_children == 0);
+ HDassert(entry_ptr->serialization_count == 0);
+
+#ifndef NDEBUG
+ entry_ptr->serialization_count++;
+#endif /* NDEBUG */
+ } /* end if */
+
+#if H5C_COLLECT_CACHE_STATS
+ if(restart_list_scan)
+ H5C__UPDATE_STATS_FOR_INDEX_SCAN_RESTART(cache_ptr);
+#endif /* H5C_COLLECT_CACHE_STATS */
+ } /* end if */
+
+ if(restart_list_scan) {
+ restart_list_scan = FALSE;
+ entry_ptr = cache_ptr->il_head;
+ } /* end if */
+ else
+ entry_ptr = entry_ptr->il_next;
+ } /* while ( entry_ptr != NULL ) */
+ } /* while ( ! done ) */
+
+
+ /* At this point, all entries not marked "flush me last" and in
+ * the current ring or outside it should be serialized and have up
+ * to date images. Scan the index list again to serialize the
+ * "flush me last" entries (if they are in the current ring) and to
+ * verify that all other entries have up to date images.
+ */
+ entry_ptr = cache_ptr->il_head;
+ while(entry_ptr != NULL) {
+ HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(entry_ptr->ring > H5C_RING_UNDEFINED);
+ HDassert(entry_ptr->ring < H5C_RING_NTYPES);
+ HDassert((entry_ptr->ring >= ring) || (entry_ptr->image_up_to_date));
+
+ if(entry_ptr->ring == ring) {
+ if(entry_ptr->flush_me_last) {
+ if(!entry_ptr->image_up_to_date) {
+ HDassert(entry_ptr->serialization_count == 0);
+ HDassert(entry_ptr->flush_dep_nunser_children == 0);
+
+ /* Serialize the entry */
+ if(H5C__serialize_single_entry(f, dxpl_id, cache_ptr, entry_ptr, &restart_list_scan) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTSERIALIZE, FAIL, "entry serialization failed")
+ else if(restart_list_scan)
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "flush_me_last entry serialization triggered restart")
+
+ HDassert(entry_ptr->flush_dep_nunser_children == 0);
+ HDassert(entry_ptr->serialization_count == 0);
+#ifndef NDEBUG
+ entry_ptr->serialization_count++;
+#endif /* NDEBUG */
+ } /* end if */
+ } /* end if */
+ else {
+ HDassert(entry_ptr->image_up_to_date);
+ HDassert(entry_ptr->serialization_count <= 1);
+ HDassert(entry_ptr->flush_dep_nunser_children == 0);
+ } /* end else */
+ } /* if ( entry_ptr->ring == ring ) */
+
+ entry_ptr = entry_ptr->il_next;
+ } /* while ( entry_ptr != NULL ) */
+
+done:
+ HDassert(cache_ptr->serialization_in_progress);
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__serialize_ring() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__serialize_single_entry
+ *
+ * Purpose: Serialize the cache entry pointed to by the entry_ptr
+ * parameter.
+ *
+ * Note: This routine is very similar to H5C__generate_image
+ * and changes to one should probably be reflected in the other.
+ * Ideally, one should be eliminated.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: John Mainzer, 7/24/15
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__serialize_single_entry(H5F_t *f, hid_t dxpl_id, H5C_t *cache_ptr,
+ H5C_cache_entry_t *entry_ptr, hbool_t *restart_list_scan_ptr)
+{
+ unsigned serialize_flags = H5C__SERIALIZE_NO_FLAGS_SET;
+ haddr_t new_addr = HADDR_UNDEF;
+ haddr_t old_addr = HADDR_UNDEF;
+ size_t new_len = 0;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(f);
+ HDassert(cache_ptr);
+ HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
+ HDassert(entry_ptr);
+ HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(!entry_ptr->prefetched);
+ HDassert(!entry_ptr->image_up_to_date);
+ HDassert(entry_ptr->is_dirty);
+ HDassert(!entry_ptr->is_protected);
+ HDassert(!entry_ptr->flush_in_progress);
+ HDassert(entry_ptr->type);
+ HDassert(restart_list_scan_ptr);
+ HDassert(*restart_list_scan_ptr == FALSE);
+
+ /* Set entry_ptr->flush_in_progress to TRUE so the the target entry
+ * will not be evicted out from under us. Must set it back to FALSE
+ * when we are done.
+ */
+ entry_ptr->flush_in_progress = TRUE;
+
+ /* Allocate buffer for the entry image if required. */
+ if(NULL == entry_ptr->image_ptr) {
+ HDassert(entry_ptr->size > 0);
+ if(NULL == (entry_ptr->image_ptr = H5MM_malloc(entry_ptr->size + H5C_IMAGE_EXTRA_SPACE)) )
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, "memory allocation failed for on disk image buffer")
+#if H5C_DO_MEMORY_SANITY_CHECKS
+ HDmemcpy(((uint8_t *)entry_ptr->image_ptr) + image_size, H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE);
+#endif /* H5C_DO_MEMORY_SANITY_CHECKS */
+ } /* end if */
+
+ /* Serialize the entry. Note that the entry need not be dirty. */
+
+ /* Reset cache_ptr->slist_changed so we can detect slist
+ * modifications in the pre_serialize call.
+ */
+ cache_ptr->slist_changed = FALSE;
+
+ /* Make note of the entry's current address */
+ old_addr = entry_ptr->addr;
+
+ /* Reset the counters so that we can detect insertions, loads,
+ * moves, and flush dependency height changes caused by the pre_serialize
+ * and serialize calls.
+ */
+ cache_ptr->entries_loaded_counter = 0;
+ cache_ptr->entries_inserted_counter = 0;
+ cache_ptr->entries_relocated_counter = 0;
+
+ /* Call client's pre-serialize callback, if there's one */
+ if(entry_ptr->type->pre_serialize &&
+ (entry_ptr->type->pre_serialize)(f, dxpl_id, (void *)entry_ptr, entry_ptr->addr, entry_ptr->size, &new_addr, &new_len, &serialize_flags) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to pre-serialize entry")
+
+ /* Check for any flags set in the pre-serialize callback */
+ if(serialize_flags != H5C__SERIALIZE_NO_FLAGS_SET) {
+
+ /* Check for unexpected flags from serialize callback */
+ if(serialize_flags & ~(H5C__SERIALIZE_RESIZED_FLAG | H5C__SERIALIZE_MOVED_FLAG))
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unknown serialize flag(s)")
+
+#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 process. Thus we can use this
+ * to detect the parallel case.
+ *
+ * This works for now, but if we start using the aux_ptr for
+ * other purposes, we will have to change this test accordingly.
+ *
+ * NB: While this test detects entryies that attempt
+ * to resize or move themselves during a flush
+ * in the parallel case, it will not detect an
+ * entry that dirties, resizes, and/or moves
+ * other entries during its flush.
+ *
+ * From what Quincey tells me, this test is
+ * sufficient for now, as any flush routine that
+ * does the latter will also do the former.
+ *
+ * If that ceases to be the case, further
+ * tests will be necessary.
+ */
+ if(cache_ptr->aux_ptr != NULL)
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "resize/move in serialize occured in parallel case.")
+#endif /* H5_HAVE_PARALLEL */
+
+ /* Resize the buffer if required */
+ if(serialize_flags & H5C__SERIALIZE_RESIZED_FLAG) {
+ /* Sanity check */
+ HDassert(new_len > 0);
+
+ /* Allocate a new image buffer */
+ if(NULL == (entry_ptr->image_ptr = H5MM_realloc(entry_ptr->image_ptr, new_len + H5C_IMAGE_EXTRA_SPACE)))
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, "memory allocation failed for on disk image buffer")
+#if H5C_DO_MEMORY_SANITY_CHECKS
+ HDmemcpy(((uint8_t *)entry_ptr->image_ptr) + new_len, H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE);
+#endif /* H5C_DO_MEMORY_SANITY_CHECKS */
+
+ /* Update the entry and the cache data structures for a resize. */
+ 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 serializing the cache. 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);
+
+ /* It should be in the skip list, update the skip list for the
+ * size change.
+ */
+ HDassert(entry_ptr->is_dirty);
+ HDassert(entry_ptr->in_slist);
+ H5C__UPDATE_SLIST_FOR_SIZE_CHANGE(cache_ptr, entry_ptr->size, new_len)
+
+ /* Finally, update the entry for its new size */
+ entry_ptr->size = new_len;
+ } /* end if */
+
+ /* If required, update the entry and the cache data structures
+ * for a move
+ */
+ if(serialize_flags & H5C__SERIALIZE_MOVED_FLAG) {
+ /* Since the entry has moved, it is probably no longer in
+ * the same place in its list. Thus at a minimum, we must set
+ * *restart_list_scan_ptr to TRUE.
+ */
+ *restart_list_scan_ptr = TRUE;
+
+ /* Update stats and the entries relocated counter */
+ H5C__UPDATE_STATS_FOR_MOVE(cache_ptr, entry_ptr)
+
+ /* We must update cache data structures for the change in address */
+ if(entry_ptr->addr == old_addr) {
+ /* Delete the entry from the hash table and the slist */
+ H5C__DELETE_FROM_INDEX(cache_ptr, entry_ptr, FAIL)
+ H5C__REMOVE_ENTRY_FROM_SLIST(cache_ptr, entry_ptr, FALSE)
+
+ /* Update the entry for its new address */
+ entry_ptr->addr = new_addr;
+
+ /* And then reinsert in the index and slist (if appropriate) */
+ H5C__INSERT_IN_INDEX(cache_ptr, entry_ptr, FAIL)
+ H5C__INSERT_ENTRY_IN_SLIST(cache_ptr, entry_ptr, FAIL)
+ } /* end if */
+ else /* Move is already done for us -- just do sanity checks */
+ HDassert(entry_ptr->addr == new_addr);
+ } /* end if */
+ } /* end if ( serialize_flags != H5C__SERIALIZE_NO_FLAGS_SET ) */
+
+ /* Reset cache_ptr->slist_changed so we can detect slist
+ * modifications in the serialize call.
+ */
+ cache_ptr->slist_changed = FALSE;
+
+ /* Serialize object into buffer */
+ if(entry_ptr->type->serialize(f, entry_ptr->image_ptr, entry_ptr->size, (void *)entry_ptr) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to serialize entry")
+#if H5C_DO_MEMORY_SANITY_CHECKS
+ HDassert(0 == HDmemcmp(((uint8_t *)entry_ptr->image_ptr) + image_len, H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE));
+#endif /* H5C_DO_MEMORY_SANITY_CHECKS */
+ entry_ptr->image_up_to_date = TRUE;
+
+ /* Propagate the fact that the entry is serialized up the
+ * flush dependency chain if appropriate. Since the image must
+ * have been out of date for this function to have been called
+ * (see assertion on entry), no need to check that -- only check
+ * for flush dependency parents.
+ */
+ HDassert(entry_ptr->flush_dep_nunser_children == 0);
+ if(entry_ptr->flush_dep_nparents > 0)
+ if(H5C__mark_flush_dep_serialized(entry_ptr) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, "Can't propagate flush dep serialized flag")
+
+ /* Reset the flush_in progress flag */
+ entry_ptr->flush_in_progress = FALSE;
+
+ /* Set *restart_fd_scan_ptr to TRUE if appropriate, and if we
+ * haven't already done so.
+ */
+ if(!(*restart_list_scan_ptr))
+ if((cache_ptr->entries_loaded_counter > 0) || (cache_ptr->entries_inserted_counter > 0) ||
+ (cache_ptr->entries_relocated_counter > 0))
+ *restart_list_scan_ptr = TRUE;
+
+done:
+ HDassert((ret_value != SUCCEED) || (!entry_ptr->flush_in_progress));
+ HDassert((ret_value != SUCCEED) || (entry_ptr->image_up_to_date));
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__serialize_single_entry() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__write_cache_image_superblock_msg
+ *
+ * Purpose: Write the cache image superblock extension message,
+ * creating if specified.
+ *
+ * In general, the size and location of the cache image block
+ * will be unknow at the time that the cache image superblock
+ * message is created. A subsequent call to this routine will
+ * be used to write the correct data.
+ *
+ * Return: Non-negative on success/Negative on failure.
+ *
+ * Programmer: John Mainzer, 7/4/15
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__write_cache_image_superblock_msg(H5F_t *f, hid_t dxpl_id, hbool_t create)
+{
+ H5C_t * cache_ptr;
+ H5O_mdci_t mdci_msg; /* metadata cache image message */
+ /* to insert in the superblock */
+ /* extension. */
+ unsigned mesg_flags = H5O_MSG_FLAG_FAIL_IF_UNKNOWN_ALWAYS;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(f);
+ HDassert(f->shared);
+ HDassert(f->shared->cache);
+ cache_ptr = f->shared->cache;
+ HDassert(cache_ptr);
+ HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
+ HDassert(cache_ptr->close_warning_received);
+
+ /* Write data into the metadata cache image superblock extension message.
+ * Note that this data will be bogus when we first create the message.
+ * We will overwrite this data later in a second call to this function.
+ */
+ mdci_msg.addr = cache_ptr->image_addr;
+#ifdef H5_HAVE_PARALLEL
+ if(cache_ptr->aux_ptr) { /* we have multiple processes */
+ H5AC_aux_t * aux_ptr;
+
+ aux_ptr = (H5AC_aux_t *)cache_ptr->aux_ptr;
+ HDassert(aux_ptr->magic == H5AC__H5AC_AUX_T_MAGIC);
+ mdci_msg.size = aux_ptr->p0_image_len;
+ } /* end if */
+ else
+#endif /* H5_HAVE_PARALLEL */
+ mdci_msg.size = cache_ptr->image_len;
+
+ /* Write metadata cache image message to superblock extension */
+ if(H5F_super_ext_write_msg(f, dxpl_id, H5O_MDCI_MSG_ID, &mdci_msg, create, mesg_flags) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_WRITEERROR, FAIL, "can't write metadata cache image message to superblock extension")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__write_cache_image_superblock_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__write_cache_image
+ *
+ * Purpose: Write the supplied metadata cache image to the specified
+ * location in file.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: John Mainzer
+ * 8/26/15
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__write_cache_image(H5F_t *f, hid_t dxpl_id, const H5C_t *cache_ptr)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(f);
+ HDassert(cache_ptr);
+ HDassert(H5F_addr_defined(cache_ptr->image_addr));
+ HDassert(cache_ptr->image_len > 0);
+ HDassert(cache_ptr->image_buffer);
+
+#ifdef H5_HAVE_PARALLEL
+{
+ H5AC_aux_t *aux_ptr = (H5AC_aux_t *)cache_ptr->aux_ptr;
+
+ if((NULL == aux_ptr) || (aux_ptr->mpi_rank == 0)) {
+ HDassert((NULL == aux_ptr) || (aux_ptr->magic == H5AC__H5AC_AUX_T_MAGIC));
+#endif /* H5_HAVE_PARALLEL */
+
+ /* Write the buffer (if serial access, or rank 0 for parallel access) */
+ if(H5F_block_write(f, H5FD_MEM_SUPER, cache_ptr->image_addr, cache_ptr->image_len, dxpl_id, cache_ptr->image_buffer) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't write metadata cache image block to file.")
+#ifdef H5_HAVE_PARALLEL
+ } /* end if */
+} /* end block */
+#endif /* H5_HAVE_PARALLEL */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__write_cache_image() */
+
diff --git a/src/H5Cprefetched.c b/src/H5Cprefetched.c
new file mode 100644
index 0000000..9b11006
--- /dev/null
+++ b/src/H5Cprefetched.c
@@ -0,0 +1,352 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the files COPYING and Copyright.html. COPYING can be found at the root *
+ * of the source code distribution tree; Copyright.html can be found at the *
+ * root level of an installed copy of the electronic HDF5 document set and *
+ * is linked from the top-level documents page. It can also be found at *
+ * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: H5Cprefetched.c
+ * December 28 2016
+ * Quincey Koziol
+ *
+ * Purpose: Metadata cache prefetched entry callbacks.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5ACprivate.h" /* Metadata cache */
+#include "H5FLprivate.h" /* Free Lists */
+#include "H5MMprivate.h" /* Memory management */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+/****************************************************************************
+ *
+ * Declarations for prefetched cache entry callbacks.
+ *
+ ****************************************************************************/
+static herr_t H5C__prefetched_entry_get_initial_load_size(void *udata_ptr,
+ size_t *image_len_ptr);
+static herr_t H5C__prefetched_entry_get_final_load_size(const void *image_ptr,
+ size_t image_len, void *udata_ptr, size_t *actual_len_ptr);
+static htri_t H5C__prefetched_entry_verify_chksum(const void *image_ptr,
+ size_t len, void *udata_ptr);
+static void * H5C__prefetched_entry_deserialize(const void *image_ptr,
+ size_t len, void *udata, hbool_t *dirty_ptr);
+static herr_t H5C__prefetched_entry_image_len(const void *thing,
+ size_t *image_len_ptr);
+static herr_t H5C__prefetched_entry_pre_serialize(H5F_t *f,
+ hid_t dxpl_id, void *thing, haddr_t addr, size_t len,
+ haddr_t *new_addr_ptr, size_t *new_len_ptr, unsigned *flags_ptr);
+static herr_t H5C__prefetched_entry_serialize(const H5F_t *f, void *image_ptr,
+ size_t len, void *thing);
+static herr_t H5C__prefetched_entry_notify(H5C_notify_action_t action,
+ void *thing);
+static herr_t H5C__prefetched_entry_free_icr(void *thing);
+static herr_t H5C__prefetched_entry_fsf_size(const void *thing,
+ size_t *fsf_size_ptr);
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+/* Declare external the free list for H5C_cache_entry_t's */
+H5FL_EXTERN(H5C_cache_entry_t);
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+
+const H5AC_class_t H5AC_PREFETCHED_ENTRY[1] = {{
+ /* id = */ H5AC_PREFETCHED_ENTRY_ID,
+ /* name = */ "prefetched entry",
+ /* mem_type = */ H5FD_MEM_DEFAULT, /* value doesn't matter */
+ /* flags = */ H5AC__CLASS_NO_FLAGS_SET,
+ /* get_initial_load_size = */ H5C__prefetched_entry_get_initial_load_size,
+ /* get_final_load_size = */ H5C__prefetched_entry_get_final_load_size,
+ /* verify_chksum = */ H5C__prefetched_entry_verify_chksum,
+ /* deserialize = */ H5C__prefetched_entry_deserialize,
+ /* image_len = */ H5C__prefetched_entry_image_len,
+ /* pre_serialize = */ H5C__prefetched_entry_pre_serialize,
+ /* serialize = */ H5C__prefetched_entry_serialize,
+ /* notify = */ H5C__prefetched_entry_notify,
+ /* free_icr = */ H5C__prefetched_entry_free_icr,
+ /* fsf_size = */ H5C__prefetched_entry_fsf_size,
+}};
+
+
+
+/***************************************************************************
+ * With two exceptions, these functions should never be called, and thus
+ * there is little point in documenting them separately as they all simply
+ * throw an error.
+ *
+ * See header comments for the two exceptions (free_icr and notify).
+ *
+ * JRM - 8/13/15
+ *
+ ***************************************************************************/
+
+static herr_t
+H5C__prefetched_entry_get_initial_load_size(void H5_ATTR_UNUSED *udata_ptr,
+ size_t H5_ATTR_UNUSED *image_len_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__prefetched_entry_get_initial_load_size() */
+
+static herr_t
+H5C__prefetched_entry_get_final_load_size(const void H5_ATTR_UNUSED *image_ptr,
+ size_t H5_ATTR_UNUSED image_len, void H5_ATTR_UNUSED *udata_ptr,
+ size_t H5_ATTR_UNUSED *actual_len_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__prefetched_entry_get_final_load_size() */
+
+static htri_t
+H5C__prefetched_entry_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 */
+
+ HERROR(H5E_CACHE, H5E_SYSTEM, "called unreachable fcn.");
+
+ FUNC_LEAVE_NOAPI(FAIL)
+} /* end H5C__prefetched_verify_chksum() */
+
+
+static void *
+H5C__prefetched_entry_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)
+{
+ 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(NULL)
+} /* end H5C__prefetched_entry_deserialize() */
+
+
+static herr_t
+H5C__prefetched_entry_image_len(const void H5_ATTR_UNUSED *thing,
+ size_t H5_ATTR_UNUSED *image_len_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__prefetched_entry_image_len() */
+
+
+static herr_t
+H5C__prefetched_entry_pre_serialize(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,
+ haddr_t H5_ATTR_UNUSED *new_addr_ptr,
+ size_t H5_ATTR_UNUSED *new_len_ptr,
+ unsigned H5_ATTR_UNUSED *flags_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__prefetched_entry_pre_serialize() */
+
+
+static herr_t
+H5C__prefetched_entry_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)
+{
+ 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__prefetched_entry_serialize() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__prefetched_entry_notify
+ *
+ * Purpose: On H5AC_NOTIFY_ACTION_BEFORE_EVICT, check to see if the
+ * target entry is a child in a flush dependency relationship.
+ * If it is, destroy that flush dependency relationship.
+ *
+ * Ignore on all other notifications.
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: John Mainzer
+ * 8/13/15
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__prefetched_entry_notify(H5C_notify_action_t action, void *_thing)
+{
+ H5C_cache_entry_t * entry_ptr = (H5C_cache_entry_t *)_thing;
+ unsigned u;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(entry_ptr);
+ HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(entry_ptr->prefetched);
+
+ switch(action) {
+ case H5C_NOTIFY_ACTION_AFTER_INSERT:
+ case H5C_NOTIFY_ACTION_AFTER_LOAD:
+ case H5C_NOTIFY_ACTION_AFTER_FLUSH:
+ case H5C_NOTIFY_ACTION_ENTRY_DIRTIED:
+ case H5C_NOTIFY_ACTION_ENTRY_CLEANED:
+ case H5C_NOTIFY_ACTION_CHILD_DIRTIED:
+ case H5C_NOTIFY_ACTION_CHILD_CLEANED:
+ case H5C_NOTIFY_ACTION_CHILD_UNSERIALIZED:
+ case H5C_NOTIFY_ACTION_CHILD_SERIALIZED:
+ /* do nothing */
+ break;
+
+ case H5C_NOTIFY_ACTION_BEFORE_EVICT:
+ for(u = 0; u < entry_ptr->flush_dep_nparents; u++) {
+ H5C_cache_entry_t * parent_ptr;
+
+ /* Sanity checks */
+ HDassert(entry_ptr->flush_dep_parent);
+ parent_ptr = entry_ptr->flush_dep_parent[u];
+ HDassert(parent_ptr);
+ HDassert(parent_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(parent_ptr->flush_dep_nchildren > 0);
+
+ /* Destroy flush dependency with flush dependency parent */
+ if(H5C_destroy_flush_dependency(parent_ptr, entry_ptr) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTUNDEPEND, FAIL, "unable to destroy prefetched entry flush dependency")
+
+ if(parent_ptr->prefetched) {
+ /* In prefetched entries, the fd_child_count field is
+ * used in sanity checks elsewhere. Thus update this
+ * field to reflect the destruction of the flush
+ * dependency relationship.
+ */
+ HDassert(parent_ptr->fd_child_count > 0);
+ (parent_ptr->fd_child_count)--;
+ } /* end if */
+ } /* end for */
+ break;
+
+ default:
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unknown action from metadata cache")
+ break;
+ } /* end switch */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5C__prefetched_entry_notify() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__prefetched_entry_free_icr
+ *
+ * Purpose: Free the in core representation of the prefetched entry.
+ * Verify that the image buffer associated with the entry
+ * has been either transferred or freed.
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: John Mainzer
+ * 8/13/15
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__prefetched_entry_free_icr(void *_thing)
+{
+ H5C_cache_entry_t *entry_ptr = (H5C_cache_entry_t *)_thing;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(entry_ptr);
+ HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC);
+ HDassert(entry_ptr->prefetched);
+
+ /* Release array for flush dependency parent addresses */
+ if(entry_ptr->fd_parent_addrs != NULL) {
+ HDassert(entry_ptr->fd_parent_count > 0);
+ entry_ptr->fd_parent_addrs = (haddr_t *)H5MM_xfree((void *)entry_ptr->fd_parent_addrs);
+ } /* end if */
+ else
+ HDassert(entry_ptr->fd_parent_count == 0);
+
+ if(entry_ptr->image_ptr != NULL)
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "prefetched entry image buffer still attatched?")
+
+ entry_ptr = H5FL_FREE(H5C_cache_entry_t, entry_ptr);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5C__prefetched_entry_free_icr() */
+
+
+static herr_t
+H5C__prefetched_entry_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__prefetched_entry_fsf_size() */
+
diff --git a/src/H5Ocache_image.c b/src/H5Ocache_image.c
new file mode 100644
index 0000000..65f6aa2
--- /dev/null
+++ b/src/H5Ocache_image.c
@@ -0,0 +1,337 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the files COPYING and Copyright.html. COPYING can be found at the root *
+ * of the source code distribution tree; Copyright.html can be found at the *
+ * root level of an installed copy of the electronic HDF5 document set and *
+ * is linked from the top-level documents page. It can also be found at *
+ * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: H5Ocache_image.c
+ * June 21, 2015
+ * John Mainzer
+ *
+ * Purpose: A message indicating that a metadata cache image block
+ * of the indicated length exists at the specified offset
+ * in the HDF5 file.
+ *
+ * The mdci_msg only appears in the superblock extension.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "H5Omodule.h" /* This source code file is part of the H5O module */
+
+
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5FLprivate.h" /* Free Lists */
+#include "H5Opkg.h" /* Object headers */
+#include "H5MFprivate.h" /* File space management */
+
+/* Callbacks for message class */
+static void *H5O__mdci_decode(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
+ unsigned mesg_flags, unsigned *ioflags, const uint8_t *p);
+static herr_t H5O__mdci_encode(H5F_t *f, hbool_t disable_shared,
+ uint8_t *p, const void *_mesg);
+static void *H5O__mdci_copy(const void *_mesg, void *_dest);
+static size_t H5O__mdci_size(const H5F_t *f, hbool_t disable_shared,
+ const void *_mesg);
+static herr_t H5O__mdci_free(void *mesg);
+static herr_t H5O__mdci_delete(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
+ void *_mesg);
+static herr_t H5O__mdci_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg,
+ FILE *stream, int indent, int fwidth);
+
+/* This message derives from H5O message class */
+const H5O_msg_class_t H5O_MSG_MDCI[1] = {{
+ H5O_MDCI_MSG_ID, /* message id number */
+ "mdci", /* message name for debugging */
+ sizeof(H5O_mdci_t), /* native message size */
+ 0, /* messages are sharable? */
+ H5O__mdci_decode, /* decode message */
+ H5O__mdci_encode, /* encode message */
+ H5O__mdci_copy, /* copy method */
+ H5O__mdci_size, /* size of mdc image message */
+ NULL, /* reset method */
+ H5O__mdci_free, /* free method */
+ H5O__mdci_delete, /* file delete method */
+ NULL, /* link method */
+ NULL, /* set share method */
+ NULL, /* can share method */
+ NULL, /* pre copy native value to file */
+ NULL, /* copy native value to file */
+ NULL, /* post copy native value to file */
+ NULL, /* get creation index */
+ NULL, /* set creation index */
+ H5O__mdci_debug /* debugging */
+}};
+
+/* Only one version of the metadata cache image message at present */
+#define H5O_MDCI_VERSION_0 0
+
+/* Declare the free list for H5O_mdci_t's */
+H5FL_DEFINE(H5O_mdci_t);
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O__mdci_decode
+ *
+ * Purpose: Decode a metadata cache image message and return a
+ * pointer to a newly allocated H5O_mdci_t struct.
+ *
+ * Return: Success: Ptr to new message in native struct.
+ * Failure: NULL
+ *
+ * Programmer: John Mainzer
+ * 6/22/15
+ *
+ *-------------------------------------------------------------------------
+ */
+static void *
+H5O__mdci_decode(H5F_t *f, hid_t H5_ATTR_UNUSED dxpl_id,
+ H5O_t H5_ATTR_UNUSED *open_oh, unsigned H5_ATTR_UNUSED mesg_flags,
+ unsigned H5_ATTR_UNUSED *ioflags, const uint8_t *p)
+{
+ H5O_mdci_t *mesg; /* Native message */
+ void *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity check */
+ HDassert(f);
+ HDassert(p);
+
+ /* Version of message */
+ if(*p++ != H5O_MDCI_VERSION_0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad version number for message")
+
+ /* Allocate space for message */
+ if(NULL == (mesg = (H5O_mdci_t *)H5FL_MALLOC(H5O_mdci_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for metadata cache image message")
+
+ /* Decode */
+ H5F_addr_decode(f, &p, &(mesg->addr));
+ H5F_DECODE_LENGTH(f, p, mesg->size);
+
+ /* Set return value */
+ ret_value = (void *)mesg;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O__mdci_decode() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O__mdci_encode
+ *
+ * Purpose: Encode metadata cache image message
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: John Mainzer
+ * 6/22/15
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O__mdci_encode(H5F_t *f, hbool_t H5_ATTR_UNUSED disable_shared,
+ uint8_t *p, const void *_mesg)
+{
+ const H5O_mdci_t *mesg = (const H5O_mdci_t *)_mesg;
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Sanity check */
+ HDassert(f);
+ HDassert(p);
+ HDassert(mesg);
+
+ /* encode */
+ *p++ = H5O_MDCI_VERSION_0;
+ H5F_addr_encode(f, &p, mesg->addr);
+ H5F_ENCODE_LENGTH(f, p, mesg->size);
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5O__mdci_encode() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O__mdci_copy
+ *
+ * Purpose: Copies a message from _MESG to _DEST, allocating _DEST if
+ * necessary.
+ *
+ * Return: Success: Ptr to _DEST
+ * Failure: NULL
+ *
+ * Programmer: John Mainzer
+ * 6/22/15
+ *
+ *-------------------------------------------------------------------------
+ */
+static void *
+H5O__mdci_copy(const void *_mesg, void *_dest)
+{
+ const H5O_mdci_t *mesg = (const H5O_mdci_t *)_mesg;
+ H5O_mdci_t *dest = (H5O_mdci_t *) _dest;
+ void *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* check args */
+ HDassert(mesg);
+ if(!dest && NULL == (dest = H5FL_MALLOC(H5O_mdci_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+
+ /* copy */
+ *dest = *mesg;
+
+ /* Set return value */
+ ret_value = dest;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_mdci__copy() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O__mdci_size
+ *
+ * Purpose: Returns the size of the raw message in bytes not counting
+ * the message type or size fields, but only the data fields.
+ * This function doesn't take into account alignment.
+ *
+ * Return: Success: Message data size in bytes without alignment.
+ *
+ * Failure: zero
+ *
+ * Programmer: John Mainzer
+ * 6/22/15
+ *
+ *-------------------------------------------------------------------------
+ */
+static size_t
+H5O__mdci_size(const H5F_t *f, hbool_t H5_ATTR_UNUSED disable_shared,
+ const void H5_ATTR_UNUSED *_mesg)
+{
+ size_t ret_value = 0; /* Return value */
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Set return value */
+ ret_value = (size_t)( 1 + /* Version number */
+ H5F_SIZEOF_ADDR(f) + /* addr of metadata cache */
+ /* image block */
+ H5F_SIZEOF_SIZE(f) ); /* length of metadata cache */
+ /* image block */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O__mdci_size() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O__mdci_free
+ *
+ * Purpose: Free the message
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: John Mainzer
+ * 6/22/15
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O__mdci_free(void *mesg)
+{
+ FUNC_ENTER_STATIC_NOERR
+
+ HDassert(mesg);
+
+ mesg = H5FL_FREE(H5O_mdci_t, mesg);
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5O__mdci_free() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O__mdci_delete
+ *
+ * Purpose: Free file space referenced by message
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Wednesday, March 19, 2003
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O__mdci_delete(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, void *_mesg)
+{
+ H5O_mdci_t *mesg = (H5O_mdci_t *)_mesg;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* check args */
+ HDassert(f);
+ HDassert(open_oh);
+ HDassert(mesg);
+
+ /* Free file space for cache image */
+ if(H5F_addr_defined(mesg->addr))
+ if(H5MF_xfree(f, H5FD_MEM_SUPER, dxpl_id, mesg->addr, mesg->size) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to free file space for cache image block")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O__mdci_delete() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O__mdci_debug
+ *
+ * Purpose: Prints debugging info.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: John Mainzer
+ * 6/22/15
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O__mdci_debug(H5F_t H5_ATTR_UNUSED *f, hid_t H5_ATTR_UNUSED dxpl_id,
+ const void *_mesg, FILE * stream, int indent, int fwidth)
+{
+ const H5O_mdci_t *mdci = (const H5O_mdci_t *) _mesg;
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* check args */
+ HDassert(f);
+ HDassert(mdci);
+ HDassert(stream);
+ HDassert(indent >= 0);
+ HDassert(fwidth >= 0);
+
+ HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth,
+ "Metadata Cache Image Block address:", mdci->addr);
+
+ HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth,
+ "Metadata Cache Image Block size in bytes:", mdci->size);
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5O__mdci_debug() */
+
diff --git a/test/cache_image.c b/test/cache_image.c
new file mode 100644
index 0000000..c91914d
--- /dev/null
+++ b/test/cache_image.c
@@ -0,0 +1,6490 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the files COPYING and Copyright.html. COPYING can be found at the root *
+ * of the source code distribution tree; Copyright.html can be found at the *
+ * root level of an installed copy of the electronic HDF5 document set and *
+ * is linked from the top-level documents page. It can also be found at *
+ * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/* Programmer: John Mainzer
+ * 7/13/15
+ *
+ * This file contains tests specific to the cache image
+ * feature implemented in H5C.c
+ */
+#include "cache_common.h"
+#include "genall5.h"
+
+/* global variable declarations: */
+
+
+const char *FILENAMES[] = {
+ "cache_image_test",
+ NULL
+};
+
+/* local utility function declarations */
+static void create_datasets(hid_t file_id, int min_dset, int max_dset);
+static void delete_datasets(hid_t file_id, int min_dset, int max_dset);
+static void open_hdf5_file(hbool_t create_file, hbool_t mdci_sbem_expected,
+ hbool_t read_only, hbool_t set_mdci_fapl, hbool_t config_fsm,
+ const char *hdf_file_name, unsigned cache_image_flags,
+ hid_t *file_id_ptr, H5F_t **file_ptr_ptr, H5C_t **cache_ptr_ptr);
+static void attempt_swmr_open_hdf5_file(hbool_t create_file,
+ hbool_t set_mdci_fapl, const char *hdf_file_name);
+static void verify_datasets(hid_t file_id, int min_dset, int max_dset);
+
+/* local test function declarations */
+static unsigned check_cache_image_ctl_flow_1(void);
+static unsigned check_cache_image_ctl_flow_2(void);
+static unsigned check_cache_image_ctl_flow_3(void);
+static unsigned check_cache_image_ctl_flow_4(void);
+static unsigned check_cache_image_ctl_flow_5(void);
+static unsigned check_cache_image_ctl_flow_6(void);
+
+static unsigned cache_image_smoke_check_1(void);
+static unsigned cache_image_smoke_check_2(void);
+static unsigned cache_image_smoke_check_3(void);
+static unsigned cache_image_smoke_check_4(void);
+static unsigned cache_image_smoke_check_5(void);
+static unsigned cache_image_smoke_check_6(void);
+
+static unsigned cache_image_api_error_check_1(void);
+static unsigned cache_image_api_error_check_2(void);
+static unsigned cache_image_api_error_check_3(void);
+
+
+/****************************************************************************/
+/***************************** Utility Functions ****************************/
+/****************************************************************************/
+
+/*-------------------------------------------------------------------------
+ * Function: create_datasets()
+ *
+ * Purpose: If pass is TRUE on entry, create the specified datasets
+ * in the indicated file.
+ *
+ * Datasets and their contents must be well known, as we
+ * will verify that they contain the expected data later.
+ *
+ * On failure, set pass to FALSE, and set failure_mssg
+ * to point to an appropriate failure message.
+ *
+ * Do nothing if pass is FALSE on entry.
+ *
+ * Return: void
+ *
+ * Programmer: John Mainzer
+ * 7/15/15
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#define CHUNK_SIZE 10
+#define DSET_SIZE (40 * CHUNK_SIZE)
+#define MAX_NUM_DSETS 256
+
+static void
+create_datasets(hid_t file_id, int min_dset, int max_dset)
+{
+ const char * fcn_name = "create_datasets()";
+ char dset_name[64];
+ hbool_t show_progress = FALSE;
+ hbool_t valid_chunk;
+ hbool_t verbose = FALSE;
+ int cp = 0;
+ int i, j, k, l, m;
+ int data_chunk[CHUNK_SIZE][CHUNK_SIZE];
+ herr_t status;
+ hid_t dataspace_id = -1;
+ hid_t filespace_ids[MAX_NUM_DSETS];
+ hid_t memspace_id = -1;
+ hid_t dataset_ids[MAX_NUM_DSETS];
+ hid_t properties = -1;
+ hsize_t dims[2];
+ hsize_t a_size[2];
+ hsize_t offset[2];
+ hsize_t chunk_size[2];
+
+ if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++);
+
+ HDassert(0 <= min_dset);
+ HDassert(min_dset <= max_dset);
+ HDassert(max_dset < MAX_NUM_DSETS);
+
+ /* create the datasets */
+
+ if ( pass ) {
+
+ i = min_dset;
+
+ while ( ( pass ) && ( i <= max_dset ) )
+ {
+ /* create a dataspace for the chunked dataset */
+ dims[0] = DSET_SIZE;
+ dims[1] = DSET_SIZE;
+ dataspace_id = H5Screate_simple(2, dims, NULL);
+
+ if ( dataspace_id < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Screate_simple() failed.";
+ }
+
+ /* set the dataset creation plist to specify that the raw data is
+ * to be partioned into 10X10 element chunks.
+ */
+
+ if ( pass ) {
+
+ chunk_size[0] = CHUNK_SIZE;
+ chunk_size[1] = CHUNK_SIZE;
+ properties = H5Pcreate(H5P_DATASET_CREATE);
+
+ if ( properties < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Pcreate() failed.";
+ }
+ }
+
+ if ( pass ) {
+
+ if ( H5Pset_chunk(properties, 2, chunk_size) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Pset_chunk() failed.";
+ }
+ }
+
+ /* create the dataset */
+ if ( pass ) {
+
+ sprintf(dset_name, "/dset%03d", i);
+ dataset_ids[i] = H5Dcreate2(file_id, dset_name, H5T_STD_I32BE,
+ dataspace_id, H5P_DEFAULT,
+ properties, H5P_DEFAULT);
+
+ if ( dataset_ids[i] < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Dcreate() failed.";
+ }
+ }
+
+ /* get the file space ID */
+ if ( pass ) {
+
+ filespace_ids[i] = H5Dget_space(dataset_ids[i]);
+
+ if ( filespace_ids[i] < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Dget_space() failed.";
+ }
+ }
+
+ i++;
+ }
+ }
+
+ if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++);
+
+ /* create the mem space to be used to read and write chunks */
+ if ( pass ) {
+
+ dims[0] = CHUNK_SIZE;
+ dims[1] = CHUNK_SIZE;
+ memspace_id = H5Screate_simple(2, dims, NULL);
+
+ if ( memspace_id < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Screate_simple() failed.";
+ }
+ }
+
+ if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++);
+
+ /* select in memory hyperslab */
+ if ( pass ) {
+
+ offset[0] = 0; /*offset of hyperslab in memory*/
+ offset[1] = 0;
+ a_size[0] = CHUNK_SIZE; /*size of hyperslab*/
+ a_size[1] = CHUNK_SIZE;
+ status = H5Sselect_hyperslab(memspace_id, H5S_SELECT_SET, offset, NULL,
+ a_size, NULL);
+
+ if ( status < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Sselect_hyperslab() failed.";
+ }
+ }
+
+ if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++);
+
+ /* initialize all datasets on a round robin basis */
+ i = 0;
+ while ( ( pass ) && ( i < DSET_SIZE ) )
+ {
+ j = 0;
+ while ( ( pass ) && ( j < DSET_SIZE ) )
+ {
+ m = min_dset;
+ while ( ( pass ) && ( m <= max_dset ) )
+ {
+ /* initialize the slab */
+ for ( k = 0; k < CHUNK_SIZE; k++ )
+ {
+ for ( l = 0; l < CHUNK_SIZE; l++ )
+ {
+ data_chunk[k][l] = (DSET_SIZE * DSET_SIZE * m) +
+ (DSET_SIZE * (i + k)) + j + l;
+ }
+ }
+
+ /* select on disk hyperslab */
+ offset[0] = (hsize_t)i; /*offset of hyperslab in file*/
+ offset[1] = (hsize_t)j;
+ a_size[0] = CHUNK_SIZE; /*size of hyperslab*/
+ a_size[1] = CHUNK_SIZE;
+ status = H5Sselect_hyperslab(filespace_ids[m], H5S_SELECT_SET,
+ offset, NULL, a_size, NULL);
+
+ if ( status < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "disk H5Sselect_hyperslab() failed.";
+ }
+
+ /* write the chunk to file */
+ status = H5Dwrite(dataset_ids[m], H5T_NATIVE_INT, memspace_id,
+ filespace_ids[m], H5P_DEFAULT, data_chunk);
+
+ if ( status < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Dwrite() failed.";
+ }
+ m++;
+ }
+ j += CHUNK_SIZE;
+ }
+
+ i += CHUNK_SIZE;
+ }
+
+ if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++);
+
+ /* read data from datasets and validate it */
+ i = 0;
+ while ( ( pass ) && ( i < DSET_SIZE ) )
+ {
+ j = 0;
+ while ( ( pass ) && ( j < DSET_SIZE ) )
+ {
+ m = min_dset;
+ while ( ( pass ) && ( m <= max_dset ) )
+ {
+
+ /* select on disk hyperslab */
+ offset[0] = (hsize_t)i; /* offset of hyperslab in file */
+ offset[1] = (hsize_t)j;
+ a_size[0] = CHUNK_SIZE; /* size of hyperslab */
+ a_size[1] = CHUNK_SIZE;
+ status = H5Sselect_hyperslab(filespace_ids[m], H5S_SELECT_SET,
+ offset, NULL, a_size, NULL);
+
+ if ( status < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "disk hyperslab create failed.";
+ }
+
+ /* read the chunk from file */
+ if ( pass ) {
+
+ status = H5Dread(dataset_ids[m], H5T_NATIVE_INT,
+ memspace_id, filespace_ids[m],
+ H5P_DEFAULT, data_chunk);
+
+ if ( status < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "disk hyperslab create failed.";
+ }
+ }
+
+ /* validate the slab */
+ if ( pass ) {
+
+ valid_chunk = TRUE;
+ for ( k = 0; k < CHUNK_SIZE; k++ )
+ {
+ for ( l = 0; l < CHUNK_SIZE; l++ )
+ {
+ if ( data_chunk[k][l]
+ !=
+ ((DSET_SIZE * DSET_SIZE * m) +
+ (DSET_SIZE * (i + k)) + j + l) ) {
+
+ valid_chunk = FALSE;
+
+ if ( verbose ) {
+
+ HDfprintf(stdout,
+ "data_chunk[%0d][%0d] = %0d, expect %0d.\n",
+ k, l, data_chunk[k][l],
+ ((DSET_SIZE * DSET_SIZE * m) +
+ (DSET_SIZE * (i + k)) + j + l));
+ HDfprintf(stdout,
+ "m = %d, i = %d, j = %d, k = %d, l = %d\n",
+ m, i, j, k, l);
+ }
+ }
+ }
+ }
+
+ if ( ! valid_chunk ) {
+
+ pass = FALSE;
+ failure_mssg = "slab validation failed.";
+
+ if ( verbose ) {
+
+ fprintf(stdout,
+ "Chunk (%0d, %0d) in /dset%03d is invalid.\n",
+ i, j, m);
+ }
+ }
+ }
+ m++;
+ }
+ j += CHUNK_SIZE;
+ }
+ i += CHUNK_SIZE;
+ }
+
+ if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++);
+
+ /* close the file spaces */
+ i = min_dset;
+ while ( ( pass ) && ( i <= max_dset ) )
+ {
+ if ( H5Sclose(filespace_ids[i]) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Sclose() failed.";
+ }
+ i++;
+ }
+
+
+ /* close the datasets */
+ i = min_dset;
+ while ( ( pass ) && ( i <= max_dset ) )
+ {
+ if ( H5Dclose(dataset_ids[i]) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Dclose() failed.";
+ }
+ i++;
+ }
+
+ /* close the mem space */
+ if ( pass ) {
+
+ if ( H5Sclose(memspace_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Sclose(memspace_id) failed.";
+ }
+ }
+
+ return;
+
+} /* create_datasets() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: delete_datasets()
+ *
+ * Purpose: If pass is TRUE on entry, verify and then delete the
+ * dataset(s) indicated by min_dset and max_dset in the
+ * indicated file.
+ *
+ * Datasets and their contents must be well know, as we
+ * will verify that they contain the expected data later.
+ *
+ * On failure, set pass to FALSE, and set failure_mssg
+ * to point to an appropriate failure message.
+ *
+ * Do nothing if pass is FALSE on entry.
+ *
+ * Return: void
+ *
+ * Programmer: John Mainzer
+ * 10/31/16
+ *
+ *-------------------------------------------------------------------------
+ */
+
+static void
+delete_datasets(hid_t file_id, int min_dset, int max_dset)
+{
+ const char * fcn_name = "delete_datasets()";
+ char dset_name[64];
+ hbool_t show_progress = FALSE;
+ int cp = 0;
+ int i;
+
+ if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++);
+
+ HDassert(0 <= min_dset);
+ HDassert(min_dset <= max_dset);
+ HDassert(max_dset < MAX_NUM_DSETS);
+
+ if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++);
+
+ /* first, verify the contents of the target dataset(s) */
+ verify_datasets(file_id, min_dset, max_dset);
+
+ if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++);
+
+ /* now delete the target datasets */
+ if ( pass ) {
+
+ i = min_dset;
+
+ while ( ( pass ) && ( i <= max_dset ) )
+ {
+ sprintf(dset_name, "/dset%03d", i);
+
+ if ( H5Ldelete(file_id, dset_name, H5P_DEFAULT) < 0) {
+
+ pass = FALSE;
+ failure_mssg = "H5Ldelete() failed.";
+ }
+
+ i++;
+ }
+ }
+
+ if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++);
+
+ return;
+
+} /* delete_datasets() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: open_hdf5_file()
+ *
+ * Purpose: If pass is true on entry, create or open the specified HDF5
+ * and test to see if it has a metadata cache image superblock
+ * extension message.
+ *
+ * Set pass to FALSE and issue a suitable failure
+ * message if either the file contains a metadata cache image
+ * superblock extension and mdci_sbem_expected is TRUE, or
+ * vise versa.
+ *
+ * If mdci_sbem_expected is TRUE, also verify that the metadata
+ * cache has been advised of this.
+ *
+ * If read_only is TRUE, open the file read only. Otherwise
+ * open the file read/write.
+ *
+ * If set_mdci_fapl is TRUE, set the metadata cache image
+ * FAPL entry when opening the file, and verify that the
+ * metadata cache is notified.
+ *
+ * If config_fsm is TRUE, setup the persistant free space
+ * manager. Note that this flag may only be set if
+ * create_file is also TRUE.
+ *
+ * Return pointers to the cache data structure and file data
+ * structures.
+ *
+ * On failure, set pass to FALSE, and set failure_mssg
+ * to point to an appropriate failure message.
+ *
+ * Do nothing if pass is FALSE on entry.
+ *
+ * Return: void
+ *
+ * Programmer: John Mainzer
+ * 7/14/15
+ *
+ *-------------------------------------------------------------------------
+ */
+
+static void
+open_hdf5_file(hbool_t create_file, hbool_t mdci_sbem_expected,
+ hbool_t read_only, hbool_t set_mdci_fapl, hbool_t config_fsm,
+ const char *hdf_file_name, unsigned cache_image_flags,
+ hid_t *file_id_ptr, H5F_t ** file_ptr_ptr, H5C_t ** cache_ptr_ptr)
+{
+ const char * fcn_name = "open_hdf5_file()";
+ hbool_t show_progress = FALSE;
+ hbool_t verbose = FALSE;
+ int cp = 0;
+ hid_t fapl_id = -1;
+ hid_t fcpl_id = -1;
+ hid_t file_id = -1;
+ herr_t result;
+ H5F_t * file_ptr = NULL;
+ H5C_t * cache_ptr = NULL;
+ H5C_cache_image_ctl_t image_ctl;
+ H5AC_cache_image_config_t cache_image_config = {
+ H5AC__CURR_CACHE_IMAGE_CONFIG_VERSION,
+ TRUE,
+ FALSE,
+ H5AC__CACHE_IMAGE__ENTRY_AGEOUT__NONE};
+
+ if ( pass )
+ {
+ /* opening the file both read only and with a cache image
+ * requested is a contradiction. We resolve it by ignoring
+ * the cache image request silently.
+ */
+ if ( ( create_file && mdci_sbem_expected ) ||
+ ( create_file && read_only ) ||
+ ( config_fsm && !create_file ) ||
+ ( hdf_file_name == NULL ) ||
+ ( ( set_mdci_fapl ) && ( cache_image_flags == 0 ) ) ||
+ ( ( set_mdci_fapl ) &&
+ ( (cache_image_flags & ~H5C_CI__ALL_FLAGS) != 0 ) ) ||
+ ( file_id_ptr == NULL ) ||
+ ( file_ptr_ptr == NULL ) ||
+ ( cache_ptr_ptr == NULL ) ) {
+
+ failure_mssg =
+ "Bad param(s) on entry to open_hdf5_file().\n";
+ pass = FALSE;
+ } else if ( verbose ) {
+
+ HDfprintf(stdout, "%s: HDF file name = \"%s\".\n",
+ fcn_name, hdf_file_name);
+ }
+ }
+
+ if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++);
+
+ /* create a file access propertly list. */
+ if ( pass ) {
+
+ fapl_id = H5Pcreate(H5P_FILE_ACCESS);
+
+ if ( fapl_id < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Pcreate() failed.\n";
+ }
+ }
+
+ if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++);
+
+ /* call H5Pset_libver_bounds() on the fapl_id */
+ if ( pass ) {
+
+ if ( H5Pset_libver_bounds(fapl_id, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Pset_libver_bounds() failed.\n";
+ }
+ }
+
+ if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++);
+
+ /* get metadata cache image config -- verify that it is the default */
+ if ( pass ) {
+
+ result = H5Pget_mdc_image_config(fapl_id, &cache_image_config);
+
+ if ( result < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Pget_mdc_image_config() failed.\n";
+ }
+
+ if ( ( cache_image_config.version !=
+ H5AC__CURR_CACHE_IMAGE_CONFIG_VERSION ) ||
+ ( cache_image_config.generate_image != FALSE ) ||
+ ( cache_image_config.save_resize_status != FALSE ) ||
+ ( cache_image_config.entry_ageout !=
+ H5AC__CACHE_IMAGE__ENTRY_AGEOUT__NONE ) ) {
+
+ pass = FALSE;
+ failure_mssg = "Unexpected default cache image config.\n";
+ }
+ }
+
+ if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++);
+
+ /* set metadata cache image fapl entry if indicated */
+ if ( ( pass ) && ( set_mdci_fapl ) ) {
+
+ /* set cache image config fields to taste */
+ cache_image_config.generate_image = TRUE;
+ cache_image_config.save_resize_status = FALSE;
+ cache_image_config.entry_ageout = H5AC__CACHE_IMAGE__ENTRY_AGEOUT__NONE;
+
+ result = H5Pset_mdc_image_config(fapl_id, &cache_image_config);
+
+ if ( result < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Pset_mdc_image_config() failed.\n";
+ }
+ }
+
+ if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++);
+
+ /* setup the persistant free space manager if indicated */
+ if ( ( pass ) && ( config_fsm ) ) {
+
+ fcpl_id = H5Pcreate(H5P_FILE_CREATE);
+
+ if ( fcpl_id <= 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Pcreate(H5P_FILE_CREATE) failed.";
+ }
+ }
+
+ if ( ( pass ) && ( config_fsm ) ) {
+
+ if ( H5Pset_file_space(fcpl_id, H5F_FILE_SPACE_ALL_PERSIST, 1) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Pset_file_space() failed.";
+ }
+ }
+
+ if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++);
+
+ /* open the file */
+ if ( pass ) {
+
+ if ( create_file ) {
+
+ if ( fcpl_id != -1 )
+
+ file_id = H5Fcreate(hdf_file_name, H5F_ACC_TRUNC, fcpl_id, fapl_id);
+ else
+
+ file_id = H5Fcreate(hdf_file_name, H5F_ACC_TRUNC, H5P_DEFAULT, fapl_id);
+
+ } else {
+
+ if ( read_only )
+
+ file_id = H5Fopen(hdf_file_name, H5F_ACC_RDONLY, fapl_id);
+
+ else
+
+ file_id = H5Fopen(hdf_file_name, H5F_ACC_RDWR, fapl_id);
+ }
+
+ if ( file_id < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fcreate() or H5Fopen() failed.\n";
+
+ } else {
+
+ file_ptr = (struct H5F_t *)H5I_object_verify(file_id, H5I_FILE);
+
+ if ( file_ptr == NULL ) {
+
+ pass = FALSE;
+ failure_mssg = "Can't get file_ptr.";
+
+ if ( verbose ) {
+ HDfprintf(stdout, "%s: Can't get file_ptr.\n", fcn_name);
+ }
+ }
+ }
+ }
+
+ if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++);
+
+ /* get a pointer to the files internal data structure and then
+ * to the cache structure
+ */
+ if ( pass ) {
+
+ if ( file_ptr->shared->cache == NULL ) {
+
+ pass = FALSE;
+ failure_mssg = "can't get cache pointer(1).\n";
+
+ } else {
+
+ cache_ptr = file_ptr->shared->cache;
+ }
+ }
+
+ if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++);
+
+ /* verify expected metadata cache status */
+
+ /* get the cache image control structure from the cache, and verify
+ * that it contains the expected values.
+ *
+ * Then set the flags in this structure to the specified value.
+ */
+ if ( pass ) {
+
+ if ( H5C_get_cache_image_config(cache_ptr, &image_ctl) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "error returned by H5C_get_cache_image_config().";
+ }
+ }
+
+ if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++);
+
+ if ( pass ) {
+
+ if ( set_mdci_fapl ) {
+
+ if ( read_only ) {
+
+ if ( ( image_ctl.version !=
+ H5AC__CURR_CACHE_IMAGE_CONFIG_VERSION ) ||
+ ( image_ctl.generate_image != FALSE ) ||
+ ( image_ctl.save_resize_status != FALSE ) ||
+ ( image_ctl.entry_ageout !=
+ H5AC__CACHE_IMAGE__ENTRY_AGEOUT__NONE ) ||
+ ( image_ctl.flags != H5C_CI__ALL_FLAGS ) ) {
+
+ pass = FALSE;
+ failure_mssg = "Unexpected image_ctl values(1).\n";
+ }
+ } else {
+
+ if ( ( image_ctl.version !=
+ H5AC__CURR_CACHE_IMAGE_CONFIG_VERSION ) ||
+ ( image_ctl.generate_image != TRUE ) ||
+ ( image_ctl.save_resize_status != FALSE ) ||
+ ( image_ctl.entry_ageout !=
+ H5AC__CACHE_IMAGE__ENTRY_AGEOUT__NONE ) ||
+ ( image_ctl.flags != H5C_CI__ALL_FLAGS ) ) {
+
+ pass = FALSE;
+ failure_mssg = "Unexpected image_ctl values(2).\n";
+ }
+ }
+ } else {
+
+ if ( ( image_ctl.version !=
+ H5AC__CURR_CACHE_IMAGE_CONFIG_VERSION ) ||
+ ( image_ctl.generate_image != FALSE ) ||
+ ( image_ctl.save_resize_status != FALSE ) ||
+ ( image_ctl.entry_ageout !=
+ H5AC__CACHE_IMAGE__ENTRY_AGEOUT__NONE ) ||
+ ( image_ctl.flags != H5C_CI__ALL_FLAGS ) ) {
+
+ pass = FALSE;
+ failure_mssg = "Unexpected image_ctl values(3).\n";
+ }
+ }
+ }
+
+ if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++);
+
+ if ( ( pass ) && ( set_mdci_fapl ) ) {
+
+ image_ctl.flags = cache_image_flags;
+
+ if ( H5C_set_cache_image_config(file_ptr, cache_ptr, &image_ctl) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "error returned by H5C_set_cache_image_config().";
+ }
+ }
+
+ if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++);
+
+ if ( pass ) {
+
+ if ( cache_ptr->close_warning_received == TRUE ) {
+
+ pass = FALSE;
+ failure_mssg = "Unexpected value of close_warning_received.\n";
+ }
+
+ if ( mdci_sbem_expected ) {
+
+ if ( read_only ) {
+
+ if ( ( cache_ptr->load_image != TRUE ) ||
+ ( cache_ptr->delete_image != FALSE ) ) {
+
+ pass = FALSE;
+ failure_mssg = "mdci sb extension message not present?\n";
+ }
+ } else {
+
+ if ( ( cache_ptr->load_image != TRUE ) ||
+ ( cache_ptr->delete_image != TRUE ) ) {
+
+ pass = FALSE;
+ failure_mssg = "mdci sb extension message not present?\n";
+ }
+ }
+ } else {
+
+ if ( ( cache_ptr->load_image == TRUE ) ||
+ ( cache_ptr->delete_image == TRUE ) ) {
+
+ pass = FALSE;
+ failure_mssg = "mdci sb extension message present?\n";
+ }
+ }
+ }
+
+ if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++);
+
+ if ( pass ) {
+
+ *file_id_ptr = file_id;
+ *file_ptr_ptr = file_ptr;
+ *cache_ptr_ptr = cache_ptr;
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d -- exiting.\n", fcn_name, cp++);
+
+ return;
+
+} /* open_hdf5_file() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: attempt_swmr_open_hdf5_file()
+ *
+ * Purpose: If pass is true on entry, attempt to create or open the
+ * specified HDF5 file with SWMR, and also with cache image
+ * creation if requested.
+ *
+ * In all cases, the attempted open or create should fail.
+ *
+ * Do nothing if pass is FALSE on entry.
+ *
+ * Return: void
+ *
+ * Programmer: John Mainzer
+ * 7/14/15
+ *
+ *-------------------------------------------------------------------------
+ */
+
+static void
+attempt_swmr_open_hdf5_file(const hbool_t create_file,
+ const hbool_t set_mdci_fapl,
+ const char * hdf_file_name)
+{
+ const char * fcn_name = "attempt_swmr_open_hdf5_file()";
+ hbool_t show_progress = FALSE;
+ int cp = 0;
+ hid_t fapl_id = -1;
+ hid_t file_id = -1;
+ herr_t result;
+ H5AC_cache_image_config_t cache_image_config = {
+ H5AC__CURR_CACHE_IMAGE_CONFIG_VERSION,
+ TRUE,
+ FALSE,
+ H5AC__CACHE_IMAGE__ENTRY_AGEOUT__NONE};
+
+ /* create a file access propertly list. */
+ if ( pass ) {
+
+ fapl_id = H5Pcreate(H5P_FILE_ACCESS);
+
+ if ( fapl_id < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Pcreate() failed.\n";
+ }
+ }
+
+ if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++);
+
+ /* call H5Pset_libver_bounds() on the fapl_id */
+ if ( pass ) {
+
+ if ( H5Pset_libver_bounds(fapl_id, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST)
+ < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Pset_libver_bounds() failed.\n";
+ }
+ }
+
+ if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++);
+
+ /* set metadata cache image fapl entry if indicated */
+ if ( ( pass ) && ( set_mdci_fapl ) ) {
+
+ /* set cache image config fields to taste */
+ cache_image_config.generate_image = TRUE;
+ cache_image_config.save_resize_status = FALSE;
+ cache_image_config.entry_ageout = H5AC__CACHE_IMAGE__ENTRY_AGEOUT__NONE;
+
+ result = H5Pset_mdc_image_config(fapl_id, &cache_image_config);
+
+ if ( result < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Pset_mdc_image_config() failed.\n";
+ }
+ }
+
+ if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++);
+
+ /* open the file */
+ if ( pass ) {
+
+ if ( create_file ) {
+
+ H5E_BEGIN_TRY {
+ file_id = H5Fcreate(hdf_file_name, H5F_ACC_TRUNC | H5F_ACC_SWMR_WRITE,
+ H5P_DEFAULT, fapl_id);
+ } H5E_END_TRY;
+ } else {
+
+ H5E_BEGIN_TRY {
+ file_id = H5Fopen(hdf_file_name, H5F_ACC_RDWR | H5F_ACC_SWMR_WRITE, fapl_id);
+ } H5E_END_TRY;
+ }
+
+ if ( file_id >= 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "SWMR H5Fcreate() or H5Fopen() succeeded.\n";
+
+ }
+ }
+
+ if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++);
+
+ return;
+
+} /* attempt_swmr_open_hdf5_file() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: verify_datasets()
+ *
+ * Purpose: If pass is TRUE on entry, verify that the datasets in the
+ * file exist and contain the expected data.
+ *
+ * Note that these datasets were created by
+ * create_datasets() above. Thus any changes in that
+ * function must be reflected in this function, and
+ * vise-versa.
+ *
+ * On failure, set pass to FALSE, and set failure_mssg
+ * to point to an appropriate failure message.
+ *
+ * Do nothing if pass is FALSE on entry.
+ *
+ * Return: void
+ *
+ * Programmer: John Mainzer
+ * 7/15/15
+ *
+ *-------------------------------------------------------------------------
+ */
+
+static void
+verify_datasets(hid_t file_id, int min_dset, int max_dset)
+{
+ const char * fcn_name = "verify_datasets()";
+ char dset_name[64];
+ hbool_t show_progress = FALSE;
+ hbool_t valid_chunk;
+ hbool_t verbose = FALSE;
+ int cp = 0;
+ int i, j, k, l, m;
+ int data_chunk[CHUNK_SIZE][CHUNK_SIZE];
+ herr_t status;
+ hid_t filespace_ids[MAX_NUM_DSETS];
+ hid_t memspace_id = -1;
+ hid_t dataset_ids[MAX_NUM_DSETS];
+ hsize_t dims[2];
+ hsize_t a_size[2];
+ hsize_t offset[2];
+
+ if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++);
+
+ HDassert(0 <= min_dset);
+ HDassert(min_dset <= max_dset);
+ HDassert(max_dset < MAX_NUM_DSETS);
+
+ /* open the datasets */
+
+ if ( pass ) {
+
+ i = min_dset;
+
+ while ( ( pass ) && ( i <= max_dset ) )
+ {
+ /* open the dataset */
+ if ( pass ) {
+
+ sprintf(dset_name, "/dset%03d", i);
+ dataset_ids[i] = H5Dopen2(file_id, dset_name, H5P_DEFAULT);
+
+ if ( dataset_ids[i] < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Dopen2() failed.";
+ }
+ }
+
+ /* get the file space ID */
+ if ( pass ) {
+
+ filespace_ids[i] = H5Dget_space(dataset_ids[i]);
+
+ if ( filespace_ids[i] < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Dget_space() failed.";
+ }
+ }
+
+ i++;
+ }
+ }
+
+ if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++);
+
+ /* create the mem space to be used to read and write chunks */
+ if ( pass ) {
+
+ dims[0] = CHUNK_SIZE;
+ dims[1] = CHUNK_SIZE;
+ memspace_id = H5Screate_simple(2, dims, NULL);
+
+ if ( memspace_id < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Screate_simple() failed.";
+ }
+ }
+
+ if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++);
+
+ /* select in memory hyperslab */
+ if ( pass ) {
+
+ offset[0] = 0; /*offset of hyperslab in memory*/
+ offset[1] = 0;
+ a_size[0] = CHUNK_SIZE; /*size of hyperslab*/
+ a_size[1] = CHUNK_SIZE;
+ status = H5Sselect_hyperslab(memspace_id, H5S_SELECT_SET, offset, NULL,
+ a_size, NULL);
+
+ if ( status < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Sselect_hyperslab() failed.";
+ }
+ }
+
+ if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++);
+
+
+ /* read data from datasets and validate it */
+ i = 0;
+ while ( ( pass ) && ( i < DSET_SIZE ) )
+ {
+ j = 0;
+ while ( ( pass ) && ( j < DSET_SIZE ) )
+ {
+ m = min_dset;
+ while ( ( pass ) && ( m <= max_dset ) )
+ {
+
+ /* select on disk hyperslab */
+ offset[0] = (hsize_t)i; /* offset of hyperslab in file */
+ offset[1] = (hsize_t)j;
+ a_size[0] = CHUNK_SIZE; /* size of hyperslab */
+ a_size[1] = CHUNK_SIZE;
+ status = H5Sselect_hyperslab(filespace_ids[m], H5S_SELECT_SET,
+ offset, NULL, a_size, NULL);
+
+ if ( status < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "disk hyperslab create failed.";
+ }
+
+ /* read the chunk from file */
+ if ( pass ) {
+
+ status = H5Dread(dataset_ids[m], H5T_NATIVE_INT,
+ memspace_id, filespace_ids[m],
+ H5P_DEFAULT, data_chunk);
+
+ if ( status < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "disk hyperslab create failed.";
+ }
+ }
+
+ /* validate the slab */
+ if ( pass ) {
+
+ valid_chunk = TRUE;
+ for ( k = 0; k < CHUNK_SIZE; k++ )
+ {
+ for ( l = 0; l < CHUNK_SIZE; l++ )
+ {
+ if ( data_chunk[k][l]
+ !=
+ ((DSET_SIZE * DSET_SIZE * m) +
+ (DSET_SIZE * (i + k)) + j + l) ) {
+
+ valid_chunk = FALSE;
+
+ if ( verbose ) {
+
+ HDfprintf(stdout,
+ "data_chunk[%0d][%0d] = %0d, expect %0d.\n",
+ k, l, data_chunk[k][l],
+ ((DSET_SIZE * DSET_SIZE * m) +
+ (DSET_SIZE * (i + k)) + j + l));
+ HDfprintf(stdout,
+ "m = %d, i = %d, j = %d, k = %d, l = %d\n",
+ m, i, j, k, l);
+ }
+ }
+ }
+ }
+
+ if ( ! valid_chunk ) {
+
+ pass = FALSE;
+ failure_mssg = "slab validation failed.";
+
+ if ( verbose ) {
+
+ fprintf(stdout,
+ "Chunk (%0d, %0d) in /dset%03d is invalid.\n",
+ i, j, m);
+ }
+ }
+ }
+ m++;
+ }
+ j += CHUNK_SIZE;
+ }
+ i += CHUNK_SIZE;
+ }
+
+ if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++);
+
+ /* close the file spaces */
+ i = min_dset;
+ while ( ( pass ) && ( i <= max_dset ) )
+ {
+ if ( H5Sclose(filespace_ids[i]) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Sclose() failed.";
+ }
+ i++;
+ }
+
+
+ /* close the datasets */
+ i = min_dset;
+ while ( ( pass ) && ( i <= max_dset ) )
+ {
+ if ( H5Dclose(dataset_ids[i]) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Dclose() failed.";
+ }
+ i++;
+ }
+
+ /* close the mem space */
+ if ( pass ) {
+
+ if ( H5Sclose(memspace_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Sclose(memspace_id) failed.";
+ }
+ }
+
+ return;
+
+} /* verify_datasets() */
+
+
+/****************************************************************************/
+/******************************* Test Functions *****************************/
+/****************************************************************************/
+
+/*-------------------------------------------------------------------------
+ * Function: check_cache_image_ctl_flow_1()
+ *
+ * Purpose: This test is one of a sequence of control flow tests intended
+ * to verify that control flow for the cache image feature works
+ * as expected.
+ *
+ * This test is an initial smoke check, so the sequence of
+ * operations is relatively simple. In particular, we are
+ * testing:
+ *
+ * i) Creation of file with cache image FAPL entry set
+ * and insertion of metadata cache image superblock
+ * message on file close.
+ *
+ * ii) Open of file with metadata cache image superblock
+ * message, transmission of message to metadata cache,
+ * and deletion of superblock message prior to close.
+ *
+ * Note that in all cases we are performing operations on the
+ * file. While this is the typical case, we must repeat this
+ * test without operations on the file.
+ *
+ * 1) Create a HDF5 file with the cache image FAPL entry.
+ *
+ * Verify that the cache is informed of the cache image
+ * FAPL entry.
+ *
+ * Set flags forcing creation of metadata cache image
+ * super block extension message only.
+ *
+ * 2) Create some datasets in the file.
+ *
+ * 3) Close the file.
+ *
+ * 4) Open the file.
+ *
+ * Verify that the metadata cache is instructed
+ * to load the metadata cache image, and that the
+ * supplied address and length are HADDR_UNDEF and
+ * zero respectively. Note that these values indicate
+ * that the metadata image block doesn't exist.
+ *
+ * 5) Open a dataset.
+ *
+ * Verify that the metadata cache image superblock
+ * extension message has been deleted.
+ *
+ * 6) Close the file.
+ *
+ * 7) Open the file.
+ *
+ * Verify that the file doesn't contain a metadata cache
+ * image superblock extension message.
+ *
+ * 8) Close the file.
+ *
+ * 9) Delete the file.
+ *
+ * Return: void
+ *
+ * Programmer: John Mainzer
+ * 7/15/15
+ *
+ *-------------------------------------------------------------------------
+ */
+
+static unsigned
+check_cache_image_ctl_flow_1(void)
+{
+ const char * fcn_name = "check_cache_image_ctl_flow_1()";
+ char filename[512];
+ hbool_t show_progress = FALSE;
+ hid_t file_id = -1;
+ H5F_t *file_ptr = NULL;
+ H5C_t *cache_ptr = NULL;
+ int cp = 0;
+
+ TESTING("metadata cache image control flow test 1");
+
+ pass = TRUE;
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* setup the file name */
+ if ( pass ) {
+
+ if ( h5_fixname(FILENAMES[0], H5P_DEFAULT, filename, sizeof(filename))
+ == NULL ) {
+
+ pass = FALSE;
+ failure_mssg = "h5_fixname() failed.\n";
+ }
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 1) Create a HDF5 file with the cache image FAPL entry.
+ *
+ * Verify that the cache is informed of the cache image FAPL entry.
+ *
+ * Set flags forcing creation of metadata cache image super block
+ * extension message only.
+ */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ TRUE,
+ /* mdci_sbem_expected */ FALSE,
+ /* read_only */ FALSE,
+ /* set_mdci_fapl */ TRUE,
+ /* config_fsm */ FALSE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ H5C_CI__GEN_MDCI_SBE_MESG,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 2) Create some datasets in the file. */
+
+ if ( pass ) {
+
+ create_datasets(file_id, 0, 5);
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 3) Close the file. */
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+
+ }
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 4) Open the file.
+ *
+ * Verify that the metadata cache is instructed to load the
+ * metadata cache image, and that the supplied address and length
+ * are HADDR_UNDEF and zero respectively. Note that these values
+ * indicate that the metadata image block doesn't exist.
+ */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ FALSE,
+ /* mdci_sbem_expected */ TRUE,
+ /* read_only */ FALSE,
+ /* set_mdci_fapl */ FALSE,
+ /* config_fsm */ FALSE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ 0,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 5) Open and close a dataset.
+ *
+ * Verify that the metadata cache image superblock
+ * extension message has been deleted.
+ */
+
+ if ( pass ) {
+
+ verify_datasets(file_id, 0, 5);
+ }
+
+ if ( pass ) {
+
+ /* think on how to verify that the superblock extension has been
+ * deleted, and if it is necessary to verify this directly.
+ */
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 6) Close the file. */
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+ }
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 7) Open the file.
+ *
+ * Verify that the file doesn't contain a metadata cache image
+ * superblock extension message.
+ */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ FALSE,
+ /* mdci_sbem_expected */ FALSE,
+ /* read_only */ FALSE,
+ /* set_mdci_fapl */ FALSE,
+ /* config_fsm */ FALSE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ 0,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 8) Close the file. */
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+ }
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 9) Delete the file */
+
+ if ( pass ) {
+
+ if ( HDremove(filename) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "HDremove() failed.\n";
+ }
+ }
+
+ if ( pass ) { PASSED(); } else { H5_FAILED(); }
+
+ if ( ! pass )
+ HDfprintf(stdout, "%s: failure_mssg = \"%s\".\n",
+ FUNC, failure_mssg);
+
+ return !pass;
+
+} /* check_cache_image_ctl_flow_1() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: check_cache_image_ctl_flow_2()
+ *
+ * Purpose: This test is one of a sequence of control flow tests intended
+ * to verify that control flow for the cache image feature works
+ * as expected.
+ *
+ * This test is an initial smoke check, so the sequence of
+ * operations is relatively simple. In particular, we are
+ * testing:
+ *
+ * i) Creation of file with cache image FAPL entry set
+ * and insertion of metadata cache image superblock
+ * message on file close.
+ *
+ * ii) Open of file with metadata cache image superblock
+ * message, transmission of message to metadata cache,
+ * and deletion of superblock message prior to close.
+ *
+ * Note that unlike the previous test, no operations are performed
+ * on the file. As a result of this, the metadata cache image
+ * message is not processed until the metadata cache receives
+ * the file close warning. (Under normal circumstances, it is
+ * processed as part of the first protect operation after the
+ * superblock is loaded.)
+ *
+ * In this particular test, we preform the following operations:
+ *
+ * 1) Create a HDF5 file with the cache image FAPL entry.
+ *
+ * Verify that the cache is informed of the cache image
+ * FAPL entry.
+ *
+ * Set flags forcing creation of metadata cache image
+ * super block extension message only.
+ *
+ * 2) Close the file.
+ *
+ * 3) Open the file.
+ *
+ * Verify that the metadata cache is instructed
+ * to load the metadata cache image, and that the
+ * supplied address and length are HADDR_UNDEF and
+ * zero respectively. Note that these values indicate
+ * that the metadata image block doesn't exist.
+ *
+ * 6) Close the file.
+ *
+ * 7) Open the file.
+ *
+ * Verify that the file doesn't contain a metadata cache
+ * image superblock extension message.
+ *
+ * 8) Close the file.
+ *
+ * 9) Delete the file.
+ *
+ * Return: void
+ *
+ * Programmer: John Mainzer
+ * 7/15/15
+ *
+ *-------------------------------------------------------------------------
+ */
+
+static unsigned
+check_cache_image_ctl_flow_2(void)
+{
+ const char * fcn_name = "check_cache_image_ctl_flow_2()";
+ char filename[512];
+ hbool_t show_progress = FALSE;
+ hid_t file_id = -1;
+ H5F_t *file_ptr = NULL;
+ H5C_t *cache_ptr = NULL;
+ int cp = 0;
+
+ TESTING("metadata cache image control flow test 2");
+
+ pass = TRUE;
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+ /* setup the file name */
+ if ( pass ) {
+
+ if ( h5_fixname(FILENAMES[0], H5P_DEFAULT, filename, sizeof(filename))
+ == NULL ) {
+
+ pass = FALSE;
+ failure_mssg = "h5_fixname() failed.\n";
+ }
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 1) Create a HDF5 file with the cache image FAPL entry.
+ *
+ * Verify that the cache is informed of the cache image FAPL entry.
+ *
+ * Set flags forcing creation of metadata cache image super block
+ * extension message only.
+ */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ TRUE,
+ /* mdci_sbem_expected */ FALSE,
+ /* read_only */ FALSE,
+ /* set_mdci_fapl */ TRUE,
+ /* config_fsm */ FALSE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ H5C_CI__GEN_MDCI_SBE_MESG,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 2) Close the file. */
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+
+ }
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 3) Open the file.
+ *
+ * Verify that the metadata cache is instructed to load the
+ * metadata cache image, and that the supplied address and length
+ * are HADDR_UNDEF and zero respectively. Note that these values
+ * indicate that the metadata image block doesn't exist.
+ */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ FALSE,
+ /* mdci_sbem_expected */ TRUE,
+ /* read_only */ FALSE,
+ /* set_mdci_fapl */ FALSE,
+ /* config_fsm */ FALSE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ 0,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 4) Close the file. */
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+ }
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 5) Open the file.
+ *
+ * Verify that the file doesn't contain a metadata cache image
+ * superblock extension message.
+ */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ FALSE,
+ /* mdci_sbem_expected */ FALSE,
+ /* read_only */ FALSE,
+ /* set_mdci_fapl */ FALSE,
+ /* config_fsm */ FALSE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ 0,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 6) Close the file. */
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+ }
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 7) Delete the file */
+
+ if ( pass ) {
+
+ if ( HDremove(filename) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "HDremove() failed.\n";
+ }
+ }
+
+ if ( pass ) { PASSED(); } else { H5_FAILED(); }
+
+ if ( ! pass )
+ HDfprintf(stdout, "%s: failure_mssg = \"%s\".\n",
+ FUNC, failure_mssg);
+
+ return !pass;
+
+} /* check_cache_image_ctl_flow_2() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: check_cache_image_ctl_flow_3()
+ *
+ * Purpose: This test is one of a sequence of control flow tests intended
+ * to verify that control flow for the cache image feature works
+ * as expected.
+ *
+ * The objectives of this test are to:
+ *
+ * i) Test operation of the metadata cache image FAPL
+ * entry set on open of an existing file. This
+ * should result in the insertion of a metadata
+ * cache image superblock message on file close.
+ *
+ * ii) Test operation of the metadata cache image super
+ * block extension message when it appears in a file
+ * that is opened READ ONLY.
+ *
+ * Note that in all cases we are performing operations on the
+ * file between file open and close. While this is the
+ * typical case, we must repeat this test without operations
+ * on the file.
+ *
+ * 1) Create a HDF5 file WITHOUT the cache image FAPL entry.
+ *
+ * Verify that the cache is NOT informed of the cache image
+ * FAPL entry.
+ *
+ * 2) Close the file.
+ *
+ * 3) Open the file WITH the cache image FAPL entry.
+ *
+ * Verify that the cache is informed of the cache image
+ * FAPL entry.
+ *
+ * Set flags forcing creation of metadata cache image
+ * super block extension message only.
+ *
+ * 4) Create some datasets.
+ *
+ * 5) Close the file.
+ *
+ * 6) Open the file READ ONLY.
+ *
+ * Verify that the metadata cache is instructed
+ * to load the metadata cache image, and that the
+ * supplied address and length are HADDR_UNDEF and
+ * zero respectively. Note that these values indicate
+ * that the metadata image block doesn't exist.
+ *
+ * 7) Verify the contents of the datasets.
+ *
+ * 8) Close the file.
+ *
+ * 9) Open the file READ/WRITE.
+ *
+ * Verify that the metadata cache is instructed
+ * to load the metadata cache image, and that the
+ * supplied address and length are HADDR_UNDEF and
+ * zero respectively. Note that these values indicate
+ * that the metadata image block doesn't exist.
+ *
+ * 10) Verify the contents of the datasets.
+ *
+ * 11) Close the file.
+ *
+ * 12) Open the file
+ *
+ * Verify that the file doesn't contain a metadata cache
+ * image superblock extension message.
+ *
+ * 13) Close the file.
+ *
+ * 14) Delete the file.
+ *
+ * Return: void
+ *
+ * Programmer: John Mainzer
+ * 7/16/15
+ *
+ *-------------------------------------------------------------------------
+ */
+
+static unsigned
+check_cache_image_ctl_flow_3(void)
+{
+ const char * fcn_name = "check_cache_image_ctl_flow_3()";
+ char filename[512];
+ hbool_t show_progress = FALSE;
+ hid_t file_id = -1;
+ H5F_t *file_ptr = NULL;
+ H5C_t *cache_ptr = NULL;
+ int cp = 0;
+
+ TESTING("metadata cache image control flow test 3");
+
+ pass = TRUE;
+
+ if ( show_progress ) /* 0 */
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+ /* setup the file name */
+ if ( pass ) {
+
+ if ( h5_fixname(FILENAMES[0], H5P_DEFAULT, filename, sizeof(filename))
+ == NULL ) {
+
+ pass = FALSE;
+ failure_mssg = "h5_fixname() failed.\n";
+ }
+ }
+
+ if ( show_progress ) /* 1 */
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+ /* 1) Create a HDF5 file WITHOUT the cache image FAPL entry.
+ *
+ * Verify that the cache is NOT informed of the cache image
+ * FAPL entry.
+ */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ TRUE,
+ /* mdci_sbem_expected */ FALSE,
+ /* read_only */ FALSE,
+ /* set_mdci_fapl */ FALSE,
+ /* config_fsm */ FALSE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ 0,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress ) /* 2 */
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 2) Close the file. */
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+ }
+ }
+
+ if ( show_progress ) /* 3 */
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 3) Open the file WITH the cache image FAPL entry.
+ *
+ * Verify that the cache is informed of the cache image FAPL entry.
+ *
+ * Set flags forcing creation of metadata cache image super block
+ * extension message only.
+ */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ FALSE,
+ /* mdci_sbem_expected */ FALSE,
+ /* read_only */ FALSE,
+ /* set_mdci_fapl */ TRUE,
+ /* config_fsm */ FALSE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ H5C_CI__GEN_MDCI_SBE_MESG,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress ) /* 4 */
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 4) Create some datasets. */
+
+ if ( pass ) {
+
+ create_datasets(file_id, 0, 5);
+ }
+
+ if ( show_progress ) /* 5 */
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 5) Close the file. */
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+ }
+ }
+
+ if ( show_progress ) /* 6 */
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 6) Open the file READ ONLY.
+ *
+ * Verify that the metadata cache is instructed
+ * to load the metadata cache image, and that the
+ * supplied address and length are HADDR_UNDEF and
+ * zero respectively. Note that these values indicate
+ * that the metadata image block doesn't exist.
+ */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ FALSE,
+ /* mdci_sbem_expected */ TRUE,
+ /* read_only */ TRUE,
+ /* set_mdci_fapl */ FALSE,
+ /* config_fsm */ FALSE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ 0,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress ) /* 7 */
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 7) Verify the contents of the datasets. */
+
+ if ( pass ) {
+
+ verify_datasets(file_id, 0, 5);
+ }
+
+ if ( show_progress ) /* 8 */
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 8) Close the file. */
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+ }
+ }
+
+ if ( show_progress ) /* 9 */
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 9) Open the file READ/WRITE.
+ *
+ * Verify that the metadata cache is instructed
+ * to load the metadata cache image, and that the
+ * supplied address and length are HADDR_UNDEF and
+ * zero respectively. Note that these values indicate
+ * that the metadata image block doesn't exist.
+ */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ FALSE,
+ /* mdci_sbem_expected */ TRUE,
+ /* read_only */ FALSE,
+ /* set_mdci_fapl */ FALSE,
+ /* config_fsm */ FALSE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ 0,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress ) /* 10 */
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 10) Verify the contents of the datasets. */
+
+ if ( pass ) {
+
+ verify_datasets(file_id, 0, 5);
+ }
+
+ if ( show_progress ) /* 11 */
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 11) Close the file. */
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+ }
+ }
+
+ if ( show_progress ) /* 12 */
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 12) Open the file
+ *
+ * Verify that the file doesn't contain a metadata cache
+ * image superblock extension message.
+ */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ FALSE,
+ /* mdci_sbem_expected */ FALSE,
+ /* read_only */ FALSE,
+ /* set_mdci_fapl */ FALSE,
+ /* config_fsm */ FALSE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ 0,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress ) /* 13 */
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 13) Close the file. */
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+ }
+ }
+
+ if ( show_progress ) /* 14 */
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 14) Delete the file. */
+
+ if ( pass ) {
+
+ if ( HDremove(filename) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "HDremove() failed.\n";
+ }
+ }
+
+
+ if ( pass ) { PASSED(); } else { H5_FAILED(); }
+
+ if ( ! pass )
+ HDfprintf(stdout, "%s: failure_mssg = \"%s\".\n",
+ FUNC, failure_mssg);
+
+ return !pass;
+
+} /* check_cache_image_ctl_flow_3() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: check_cache_image_ctl_flow_4()
+ *
+ * Purpose: This test is one of a sequence of control flow tests intended
+ * to verify that control flow for the cache image feature works
+ * as expected.
+ *
+ * The objectives of this test are to:
+ *
+ * i) Test operation of the metadata cache image FAPL
+ * entry set on open of an existing file. This
+ * should result in the insertion of a metadata
+ * cache image superblock message on file close.
+ *
+ * ii) Test operation of the metadata cache image super
+ * block extension message when it appears in a file
+ * that is opened READ ONLY.
+ *
+ * In this test we avoid all file access beyond file open
+ * and close.
+ *
+ * 1) Create a HDF5 file WITHOUT the cache image FAPL entry.
+ *
+ * Verify that the cache is NOT informed of the cache image
+ * FAPL entry.
+ *
+ * 2) Close the file.
+ *
+ * 3) Open the file WITH the cache image FAPL entry.
+ *
+ * Verify that the cache is informed of the cache image
+ * FAPL entry.
+ *
+ * Set flags forcing creation of metadata cache image
+ * super block extension message only.
+ *
+ * 4) Close the file.
+ *
+ * 5) Open the file READ ONLY.
+ *
+ * Verify that the metadata cache is instructed
+ * to load the metadata cache image, and that the
+ * supplied address and length are HADDR_UNDEF and
+ * zero respectively. Note that these values indicate
+ * that the metadata image block doesn't exist.
+ *
+ * 6) Close the file.
+ *
+ * 7) Open the file READ/WRITE.
+ *
+ * Verify that the metadata cache is instructed
+ * to load the metadata cache image, and that the
+ * supplied address and length are HADDR_UNDEF and
+ * zero respectively. Note that these values indicate
+ * that the metadata image block doesn't exist.
+ *
+ * 8) Close the file.
+ *
+ * 9) Open the file
+ *
+ * Verify that the file doesn't contain a metadata cache
+ * image superblock extension message.
+ *
+ * 10) Close the file.
+ *
+ * 11) Delete the file.
+ *
+ * Return: void
+ *
+ * Programmer: John Mainzer
+ * 7/16/15
+ *
+ *-------------------------------------------------------------------------
+ */
+
+static unsigned
+check_cache_image_ctl_flow_4(void)
+{
+ const char * fcn_name = "check_cache_image_ctl_flow_4()";
+ char filename[512];
+ hbool_t show_progress = FALSE;
+ hid_t file_id = -1;
+ H5F_t *file_ptr = NULL;
+ H5C_t *cache_ptr = NULL;
+ int cp = 0;
+
+ TESTING("metadata cache image control flow test 4");
+
+ pass = TRUE;
+
+ if ( show_progress ) /* 0 */
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+ /* setup the file name */
+ if ( pass ) {
+
+ if ( h5_fixname(FILENAMES[0], H5P_DEFAULT, filename, sizeof(filename))
+ == NULL ) {
+
+ pass = FALSE;
+ failure_mssg = "h5_fixname() failed.\n";
+ }
+ }
+
+ if ( show_progress ) /* 1 */
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+ /* 1) Create a HDF5 file WITHOUT the cache image FAPL entry.
+ *
+ * Verify that the cache is NOT informed of the cache image
+ * FAPL entry.
+ */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ TRUE,
+ /* mdci_sbem_expected */ FALSE,
+ /* read_only */ FALSE,
+ /* set_mdci_fapl */ FALSE,
+ /* config_fsm */ FALSE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ 0,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress ) /* 2 */
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 2) Close the file. */
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+ }
+ }
+
+ if ( show_progress ) /* 3 */
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 3) Open the file WITH the cache image FAPL entry.
+ *
+ * Verify that the cache is informed of the cache image FAPL entry.
+ *
+ * Set flags forcing creation of metadata cache image super block
+ * extension message only.
+ */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ FALSE,
+ /* mdci_sbem_expected */ FALSE,
+ /* read_only */ FALSE,
+ /* set_mdci_fapl */ TRUE,
+ /* config_fsm */ FALSE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ H5C_CI__GEN_MDCI_SBE_MESG,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress ) /* 4 */
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 4) Close the file. */
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+ }
+ }
+
+ if ( show_progress ) /* 5 */
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 5) Open the file READ ONLY.
+ *
+ * Verify that the metadata cache is instructed
+ * to load the metadata cache image, and that the
+ * supplied address and length are HADDR_UNDEF and
+ * zero respectively. Note that these values indicate
+ * that the metadata image block doesn't exist.
+ */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ FALSE,
+ /* mdci_sbem_expected */ TRUE,
+ /* read_only */ TRUE,
+ /* set_mdci_fapl */ FALSE,
+ /* config_fsm */ FALSE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ 0,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress ) /* 6 */
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 6) Close the file. */
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+ }
+ }
+
+ if ( show_progress ) /* 7 */
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 7) Open the file READ/WRITE.
+ *
+ * Verify that the metadata cache is instructed
+ * to load the metadata cache image, and that the
+ * supplied address and length are HADDR_UNDEF and
+ * zero respectively. Note that these values indicate
+ * that the metadata image block doesn't exist.
+ */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ FALSE,
+ /* mdci_sbem_expected */ TRUE,
+ /* read_only */ FALSE,
+ /* set_mdci_fapl */ FALSE,
+ /* config_fsm */ FALSE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ 0,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress ) /* 8 */
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 8) Close the file. */
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+ }
+ }
+
+ if ( show_progress ) /* 9 */
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 9) Open the file
+ *
+ * Verify that the file doesn't contain a metadata cache
+ * image superblock extension message.
+ */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ FALSE,
+ /* mdci_sbem_expected */ FALSE,
+ /* read_only */ FALSE,
+ /* set_mdci_fapl */ FALSE,
+ /* config_fsm */ FALSE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ 0,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress ) /* 10 */
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 10) Close the file. */
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+ }
+ }
+
+ if ( show_progress ) /* 11 */
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 11) Delete the file. */
+
+ if ( pass ) {
+
+ if ( HDremove(filename) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "HDremove() failed.\n";
+ }
+ }
+
+
+ if ( pass ) { PASSED(); } else { H5_FAILED(); }
+
+ if ( ! pass )
+ HDfprintf(stdout, "%s: failure_mssg = \"%s\".\n",
+ FUNC, failure_mssg);
+
+ return !pass;
+
+} /* check_cache_image_ctl_flow_4() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: check_cache_image_ctl_flow_5()
+ *
+ * Purpose: This test is one of a sequence of control flow tests intended
+ * to verify that control flow for the cache image feature works
+ * as expected.
+ *
+ * The objective of this test is verify correct control flow
+ * when a file with a metadata cache image superblock extension
+ * message is opened with the metadata cache image FAPL entry.
+ *
+ * Note that in all cases we are performing operations on the
+ * file between file open and close. While this is the
+ * typical case, we must repeat this test without operations
+ * on the file.
+ *
+ * 1) Create a HDF5 file with the cache image FAPL entry.
+ *
+ * Verify that the cache is informed of the cache image
+ * FAPL entry.
+ *
+ * Set flags forcing creation of metadata cache image
+ * super block extension message only.
+ *
+ * 2) Create some datasets.
+ *
+ * 3) Close the file.
+ *
+ * 4) Open the file WITH the cache image FAPL entry.
+ *
+ * Verify that the metadata cache is instructed
+ * to load the metadata cache image, and that the
+ * supplied address and length are HADDR_UNDEF and
+ * zero respectively. Note that these values indicate
+ * that the metadata image block doesn't exist.
+ *
+ * Verify that the cache is informed of the cache image
+ * FAPL entry.
+ *
+ * Set flags forcing creation of metadata cache image
+ * super block extension message only.
+ *
+ * 5) Verify the contents of the datasets.
+ *
+ * 6) Close the file.
+ *
+ * 7) Open the file.
+ *
+ * Verify that the metadata cache is instructed
+ * to load the metadata cache image, and that the
+ * supplied address and length are HADDR_UNDEF and
+ * zero respectively. Note that these values indicate
+ * that the metadata image block doesn't exist.
+ *
+ * 8) Verify the contents of the datasets.
+ *
+ * 9) Close the file.
+ *
+ * 10) Delete the file.
+ *
+ * Return: void
+ *
+ * Programmer: John Mainzer
+ * 7/17/15
+ *
+ *-------------------------------------------------------------------------
+ */
+
+static unsigned
+check_cache_image_ctl_flow_5(void)
+{
+ const char * fcn_name = "check_cache_image_ctl_flow_5()";
+ char filename[512];
+ hbool_t show_progress = FALSE;
+ hid_t file_id = -1;
+ H5F_t *file_ptr = NULL;
+ H5C_t *cache_ptr = NULL;
+ int cp = 0;
+
+ TESTING("metadata cache image control flow test 5");
+
+ pass = TRUE;
+
+ if ( show_progress ) /* 0 */
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+ /* setup the file name */
+ if ( pass ) {
+
+ if ( h5_fixname(FILENAMES[0], H5P_DEFAULT, filename, sizeof(filename))
+ == NULL ) {
+
+ pass = FALSE;
+ failure_mssg = "h5_fixname() failed.\n";
+ }
+ }
+
+ if ( show_progress ) /* 1 */
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 1) Create a HDF5 file with the cache image FAPL entry.
+ *
+ * Verify that the cache is informed of the cache image FAPL entry.
+ *
+ * Set flags forcing creation of metadata cache image
+ * super block extension message only.
+ */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ TRUE,
+ /* mdci_sbem_expected */ FALSE,
+ /* read_only */ FALSE,
+ /* set_mdci_fapl */ TRUE,
+ /* config_fsm */ FALSE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ H5C_CI__GEN_MDCI_SBE_MESG,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress ) /* 2 */
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 2) Create some datasets. */
+
+ if ( pass ) {
+
+ create_datasets(file_id, 0, 5);
+ }
+
+ if ( show_progress ) /* 3 */
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 3) Close the file. */
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+ }
+ }
+
+ if ( show_progress ) /* 4 */
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 4) Open the file WITH the cache image FAPL entry.
+ *
+ * Verify that the metadata cache is instructed
+ * to load the metadata cache image, and that the
+ * supplied address and length are HADDR_UNDEF and
+ * zero respectively. Note that these values indicate
+ * that the metadata image block doesn't exist.
+ *
+ * Verify that the cache is informed of the cache image
+ * FAPL entry.
+ *
+ * Set flags forcing creation of metadata cache image
+ * super block extension message only.
+ */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ FALSE,
+ /* mdci_sbem_expected */ TRUE,
+ /* read_only */ FALSE,
+ /* set_mdci_fapl */ TRUE,
+ /* config_fsm */ FALSE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ H5C_CI__GEN_MDCI_SBE_MESG,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress ) /* 5 */
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+ /* 5) Verify the contents of the datasets. */
+
+ if ( pass ) {
+
+ verify_datasets(file_id, 0, 5);
+ }
+
+ if ( show_progress ) /* 6 */
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 6) Close the file. */
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+ }
+ }
+
+ if ( show_progress ) /* 7 */
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 7) Open the file.
+ *
+ * Verify that the metadata cache is instructed
+ * to load the metadata cache image, and that the
+ * supplied address and length are HADDR_UNDEF and
+ * zero respectively. Note that these values indicate
+ * that the metadata image block doesn't exist.
+ */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ FALSE,
+ /* mdci_sbem_expected */ TRUE,
+ /* read_only */ FALSE,
+ /* set_mdci_fapl */ FALSE,
+ /* config_fsm */ FALSE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ 0,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress ) /* 8 */
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+ /* 8) Verify the contents of the datasets. */
+
+ if ( pass ) {
+
+ verify_datasets(file_id, 0, 5);
+ }
+
+ if ( show_progress ) /* 9 */
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 9) Close the file. */
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+ }
+ }
+
+ if ( show_progress ) /* 10 */
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 10) Delete the file. */
+
+ if ( pass ) {
+
+ if ( HDremove(filename) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "HDremove() failed.\n";
+ }
+ }
+
+
+ if ( pass ) { PASSED(); } else { H5_FAILED(); }
+
+ if ( ! pass )
+ HDfprintf(stdout, "%s: failure_mssg = \"%s\".\n",
+ FUNC, failure_mssg);
+
+ return !pass;
+
+} /* check_cache_image_ctl_flow_5() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: check_cache_image_ctl_flow_6()
+ *
+ * Purpose: This test is one of a sequence of control flow tests intended
+ * to verify that control flow for the cache image feature works
+ * as expected.
+ *
+ * The objective of this test is verify correct control flow
+ * when a file with a metadata cache image superblock extension
+ * message is opened with the metadata cache image FAPL entry.
+ *
+ * In this test we avoid all file activity other than open
+ * and close.
+ *
+ * 1) Create a HDF5 file with the cache image FAPL entry.
+ *
+ * Verify that the cache is informed of the cache image
+ * FAPL entry.
+ *
+ * Set flags forcing creation of metadata cache image
+ * super block extension message only.
+ *
+ * 2) Close the file.
+ *
+ * 3) Open the file WITH the cache image FAPL entry.
+ *
+ * Verify that the metadata cache is instructed
+ * to load the metadata cache image, and that the
+ * supplied address and length are HADDR_UNDEF and
+ * zero respectively. Note that these values indicate
+ * that the metadata image block doesn't exist.
+ *
+ * Verify that the cache is informed of the cache image
+ * FAPL entry.
+ *
+ * Set flags forcing creation of metadata cache image
+ * super block extension message only.
+ *
+ * 4) Close the file.
+ *
+ * 5) Open the file.
+ *
+ * Verify that the metadata cache is instructed
+ * to load the metadata cache image, and that the
+ * supplied address and length are HADDR_UNDEF and
+ * zero respectively. Note that these values indicate
+ * that the metadata image block doesn't exist.
+ *
+ * 6) Close the file.
+ *
+ * 7) Delete the file.
+ *
+ * Return: void
+ *
+ * Programmer: John Mainzer
+ * 7/17/15
+ *
+ *-------------------------------------------------------------------------
+ */
+
+static unsigned
+check_cache_image_ctl_flow_6(void)
+{
+ const char * fcn_name = "check_cache_image_ctl_flow_6()";
+ char filename[512];
+ hbool_t show_progress = FALSE;
+ hid_t file_id = -1;
+ H5F_t *file_ptr = NULL;
+ H5C_t *cache_ptr = NULL;
+ int cp = 0;
+
+ TESTING("metadata cache image control flow test 6");
+
+ pass = TRUE;
+
+ if ( show_progress ) /* 0 */
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+ /* setup the file name */
+ if ( pass ) {
+
+ if ( h5_fixname(FILENAMES[0], H5P_DEFAULT, filename, sizeof(filename))
+ == NULL ) {
+
+ pass = FALSE;
+ failure_mssg = "h5_fixname() failed.\n";
+ }
+ }
+
+ if ( show_progress ) /* 1 */
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 1) Create a HDF5 file with the cache image FAPL entry.
+ *
+ * Verify that the cache is informed of the cache image FAPL entry.
+ *
+ * Set flags forcing creation of metadata cache image
+ * super block extension message only.
+ */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ TRUE,
+ /* mdci_sbem_expected */ FALSE,
+ /* read_only */ FALSE,
+ /* set_mdci_fapl */ TRUE,
+ /* config_fsm */ FALSE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ H5C_CI__GEN_MDCI_SBE_MESG,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress ) /* 2 */
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 2) Close the file. */
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+ }
+ }
+
+ if ( show_progress ) /* 3 */
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 4) Open the file WITH the cache image FAPL entry.
+ *
+ * Verify that the metadata cache is instructed
+ * to load the metadata cache image, and that the
+ * supplied address and length are HADDR_UNDEF and
+ * zero respectively. Note that these values indicate
+ * that the metadata image block doesn't exist.
+ *
+ * Verify that the cache is informed of the cache image
+ * FAPL entry.
+ *
+ * Set flags forcing creation of metadata cache image
+ * super block extension message only.
+ */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ FALSE,
+ /* mdci_sbem_expected */ TRUE,
+ /* read_only */ FALSE,
+ /* set_mdci_fapl */ TRUE,
+ /* config_fsm */ FALSE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ H5C_CI__GEN_MDCI_SBE_MESG,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress ) /* 4 */
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 5) Close the file. */
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+ }
+ }
+
+ if ( show_progress ) /* 5 */
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 5) Open the file.
+ *
+ * Verify that the metadata cache is instructed
+ * to load the metadata cache image, and that the
+ * supplied address and length are HADDR_UNDEF and
+ * zero respectively. Note that these values indicate
+ * that the metadata image block doesn't exist.
+ */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ FALSE,
+ /* mdci_sbem_expected */ TRUE,
+ /* read_only */ FALSE,
+ /* set_mdci_fapl */ FALSE,
+ /* config_fsm */ FALSE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ 0,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress ) /* 6 */
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 6) Close the file. */
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+ }
+ }
+
+ if ( show_progress ) /* 7 */
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 7) Delete the file. */
+
+ if ( pass ) {
+
+ if ( HDremove(filename) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "HDremove() failed.\n";
+ }
+ }
+
+
+ if ( pass ) { PASSED(); } else { H5_FAILED(); }
+
+ if ( ! pass )
+ HDfprintf(stdout, "%s: failure_mssg = \"%s\".\n",
+ FUNC, failure_mssg);
+
+ return !pass;
+
+} /* check_cache_image_ctl_flow_6() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: cache_image_smoke_check_1()
+ *
+ * Purpose: This test is one of a sequence of tests intended
+ * to exercise the cache image feature verifying that it
+ * works more or less correctly in common cases.
+ *
+ * This test is an initial smoke check, so the sequence of
+ * operations is relatively simple. In particular, we are
+ * testing:
+ *
+ * i) Creation of file with metadata cache image
+ * superblock extension message and cache image
+ * block.
+ *
+ * ii) Open of file with metadata cache image superblock
+ * extension message and cache image block.
+ * Deserialization and removal of both, insertion
+ * of prefetched cache entries, and deserialization
+ * of prefetched cache entries as they are protected.
+ *
+ * iii) Subsequent write of file without metadata cache
+ * image.
+ *
+ * iv) Open and close of file with metadata cache image
+ * image requested, but with no operations on the
+ * file.
+ *
+ * To do this:
+ *
+ * 1) Create a HDF5 file with the cache image FAPL entry.
+ *
+ * Verify that the cache is informed of the cache image
+ * FAPL entry.
+ *
+ * Set all cache image flags, forcing full functionality.
+ *
+ * 2) Create some datasets in the file.
+ *
+ * 3) Close the file.
+ *
+ * 4) Open the file.
+ *
+ * Verify that the metadata cache is instructed
+ * to load the metadata cache image.
+ *
+ * 5) Open a dataset.
+ *
+ * Verify that it contains the expected data
+ *
+ * 6) Close the file.
+ *
+ * 7) Open the file.
+ *
+ * Verify that the file doesn't contain a metadata cache
+ * image superblock extension message.
+ *
+ * 8) Open a dataset.
+ *
+ * Verify that it contains the expected data.
+ *
+ * 9) Close the file.
+ *
+ * 10) Open the file with the cache image FAPL entry.
+ *
+ * Verify that the cache is informed of the cache image
+ * FAPL entry.
+ *
+ * Set all cache image flags, forcing full functionality.
+ *
+ * 11) Close the file. Since there has been no access to
+ * any entries that would be included in the cache image,
+ * there should be no cache image.
+ *
+ * 12) Open the file.
+ *
+ * Verify that the file doesn't contain a metadata cache
+ * image superblock extension message.
+ *
+ * 13) Open a dataset.
+ *
+ * Verify that it contains the expected data.
+ *
+ * 14) Close the file.
+ *
+ * 15) Delete the file.
+ *
+ * Return: void
+ *
+ * Programmer: John Mainzer
+ * 8/17/15
+ *
+ *-------------------------------------------------------------------------
+ */
+
+static unsigned
+cache_image_smoke_check_1(void)
+{
+ const char * fcn_name = "cache_image_smoke_check_1()";
+ char filename[512];
+ hbool_t show_progress = FALSE;
+ hid_t file_id = -1;
+ H5F_t *file_ptr = NULL;
+ H5C_t *cache_ptr = NULL;
+ int cp = 0;
+
+ TESTING("metadata cache image smoke check 1");
+
+ pass = TRUE;
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* setup the file name */
+ if ( pass ) {
+
+ if ( h5_fixname(FILENAMES[0], H5P_DEFAULT, filename, sizeof(filename))
+ == NULL ) {
+
+ pass = FALSE;
+ failure_mssg = "h5_fixname() failed.\n";
+ }
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 1) Create a HDF5 file with the cache image FAPL entry.
+ *
+ * Verify that the cache is informed of the cache image FAPL entry.
+ *
+ * Set flags forcing full function of the cache image feature.
+ */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ TRUE,
+ /* mdci_sbem_expected */ FALSE,
+ /* read_only */ FALSE,
+ /* set_mdci_fapl */ TRUE,
+ /* config_fsm */ FALSE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ H5C_CI__ALL_FLAGS,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 2) Create some datasets in the file. */
+
+ if ( pass ) {
+
+ create_datasets(file_id, 0, 5);
+ }
+
+#if H5C_COLLECT_CACHE_STATS
+ if ( pass ) {
+
+ if ( cache_ptr->images_loaded != 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "metadata cache image block loaded(1).";
+ }
+ }
+#endif /* H5C_COLLECT_CACHE_STATS */
+
+
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 3) Close the file. */
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+
+ }
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 4) Open the file.
+ *
+ * Verify that the metadata cache is instructed to load the
+ * metadata cache image, and that the supplied address and length
+ * are HADDR_UNDEF and zero respectively. Note that these values
+ * indicate that the metadata image block doesn't exist.
+ */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ FALSE,
+ /* mdci_sbem_expected */ TRUE,
+ /* read_only */ FALSE,
+ /* set_mdci_fapl */ FALSE,
+ /* config_fsm */ FALSE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ 0,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 5) Open and close a dataset.
+ *
+ * Verify that the metadata cache image superblock
+ * extension message has been deleted.
+ */
+
+ if ( pass ) {
+
+ verify_datasets(file_id, 0, 5);
+ }
+
+#if H5C_COLLECT_CACHE_STATS
+ if ( pass ) {
+
+ if ( cache_ptr->images_loaded != 1 ) {
+
+ pass = FALSE;
+ failure_mssg = "metadata cache image block not loaded(1).";
+ }
+ }
+#endif /* H5C_COLLECT_CACHE_STATS */
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 6) Close the file. */
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+ }
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 7) Open the file.
+ *
+ * Verify that the file doesn't contain a metadata cache image
+ * superblock extension message.
+ */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ FALSE,
+ /* mdci_sbem_expected */ FALSE,
+ /* read_only */ FALSE,
+ /* set_mdci_fapl */ FALSE,
+ /* config_fsm */ FALSE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ 0,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 8) Open and close a dataset.
+ *
+ * Verify that the metadata cache image superblock
+ * extension message has been deleted.
+ */
+
+ if ( pass ) {
+
+ verify_datasets(file_id, 0, 5);
+ }
+
+#if H5C_COLLECT_CACHE_STATS
+ if ( pass ) {
+
+ if ( cache_ptr->images_loaded != 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "metadata cache image block loaded(2).";
+ }
+ }
+#endif /* H5C_COLLECT_CACHE_STATS */
+
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 9) Close the file. */
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+ }
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 10) Open the file with the cache image FAPL entry.
+ *
+ * Verify that the cache is informed of the cache image
+ * FAPL entry.
+ */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ FALSE,
+ /* mdci_sbem_expected */ FALSE,
+ /* read_only */ FALSE,
+ /* set_mdci_fapl */ TRUE,
+ /* config_fsm */ FALSE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ H5C_CI__ALL_FLAGS,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 11) Close the file. Since there has been no access to
+ * any entries that would be included in the cache image,
+ * there should be no cache image.
+ */
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+ }
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 12) Open the file.
+ *
+ * Verify that the file doesn't contain a metadata cache
+ * image superblock extension message.
+ */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ FALSE,
+ /* mdci_sbem_expected */ FALSE,
+ /* read_only */ FALSE,
+ /* set_mdci_fapl */ FALSE,
+ /* config_fsm */ FALSE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ 0,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 13) Open a dataset.
+ *
+ * Verify that it contains the expected data.
+ */
+
+ if ( pass ) {
+
+ verify_datasets(file_id, 0, 5);
+ }
+
+#if H5C_COLLECT_CACHE_STATS
+ if ( pass ) {
+
+ if ( cache_ptr->images_loaded != 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "metadata cache image block loaded(3).";
+ }
+ }
+#endif /* H5C_COLLECT_CACHE_STATS */
+
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 14) Close the file. */
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+ }
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 15) Delete the file */
+
+ if ( pass ) {
+
+ if ( HDremove(filename) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "HDremove() failed.\n";
+ }
+ }
+
+ if ( pass ) { PASSED(); } else { H5_FAILED(); }
+
+ if ( ! pass )
+ HDfprintf(stdout, "%s: failure_mssg = \"%s\".\n",
+ FUNC, failure_mssg);
+
+ return !pass;
+
+} /* cache_image_smoke_check_1() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: cache_image_smoke_check_2()
+ *
+ * Purpose: This test is one of a sequence of tests intended
+ * to exercise the cache image feature verifying that it
+ * works more or less correctly in common cases.
+ *
+ * This test is an initial smoke check, so the sequence of
+ * operations is relatively simple. In particular, we are
+ * testing:
+ *
+ * i) Creation of file with metadata cache image
+ * superblock extension message and cache image
+ * block.
+ *
+ * ii) Open of file with metadata cache image superblock
+ * extension message and cache image block. Write
+ * of prefetched entries to file on file close.
+ *
+ * To do this:
+ *
+ * 1) Create a HDF5 file with the cache image FAPL entry.
+ *
+ * Verify that the cache is informed of the cache image
+ * FAPL entry.
+ *
+ * Set all cache image flags, forcing full functionality.
+ *
+ * 2) Create some datasets in the file.
+ *
+ * 3) Close the file.
+ *
+ * 4) Open the file.
+ *
+ * 5) Close the file.
+ *
+ * 6) Open the file.
+ *
+ * Verify that the file doesn't contain a metadata cache
+ * image superblock extension message.
+ *
+ * 7) Open a dataset.
+ *
+ * Verify that it contains the expected data.
+ *
+ * 8) Close the file.
+ *
+ * 9) Delete the file.
+ *
+ * Return: void
+ *
+ * Programmer: John Mainzer
+ * 8/18/15
+ *
+ *-------------------------------------------------------------------------
+ */
+
+static unsigned
+cache_image_smoke_check_2(void)
+{
+ const char * fcn_name = "cache_image_smoke_check_2()";
+ char filename[512];
+ hbool_t show_progress = FALSE;
+ hid_t file_id = -1;
+ H5F_t *file_ptr = NULL;
+ H5C_t *cache_ptr = NULL;
+ int cp = 0;
+
+ TESTING("metadata cache image smoke check 2");
+
+ pass = TRUE;
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* setup the file name */
+ if ( pass ) {
+
+ if ( h5_fixname(FILENAMES[0], H5P_DEFAULT, filename, sizeof(filename))
+ == NULL ) {
+
+ pass = FALSE;
+ failure_mssg = "h5_fixname() failed.\n";
+ }
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 1) Create a HDF5 file with the cache image FAPL entry.
+ *
+ * Verify that the cache is informed of the cache image FAPL entry.
+ *
+ * Set flags forcing full function of the cache image feature.
+ */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ TRUE,
+ /* mdci_sbem_expected */ FALSE,
+ /* read_only */ FALSE,
+ /* set_mdci_fapl */ TRUE,
+ /* config_fsm */ TRUE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ H5C_CI__ALL_FLAGS,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 2) Create some datasets in the file. */
+
+ if ( pass ) {
+
+ create_datasets(file_id, 0, 5);
+ }
+
+#if H5C_COLLECT_CACHE_STATS
+ if ( pass ) {
+
+ if ( cache_ptr->images_loaded != 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "metadata cache image block loaded(1).";
+ }
+ }
+#endif /* H5C_COLLECT_CACHE_STATS */
+
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 3) Close the file. */
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+
+ }
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 4) Open the file.
+ *
+ * Verify that the metadata cache is instructed to load the
+ * metadata cache image.
+ */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ FALSE,
+ /* mdci_sbem_expected */ TRUE,
+ /* read_only */ FALSE,
+ /* set_mdci_fapl */ FALSE,
+ /* config_fsm */ FALSE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ 0,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ /* can't verify that metadata cache image has been loaded directly,
+ * as in this cache, the load will not happen until close, and thus
+ * the images_created stat will not be readily available as it is
+ * incremented just before the cache is shut down.
+ */
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 5) Close the file. */
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+ }
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 6) Open the file.
+ *
+ * Verify that the file doesn't contain a metadata cache image
+ * superblock extension message.
+ */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ FALSE,
+ /* mdci_sbem_expected */ FALSE,
+ /* read_only */ FALSE,
+ /* set_mdci_fapl */ FALSE,
+ /* config_fsm */ FALSE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ 0,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 7) Open and close a dataset.
+ *
+ * Verify that the metadata cache image superblock
+ * extension message has been deleted.
+ */
+
+ if ( pass ) {
+
+ verify_datasets(file_id, 0, 5);
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 8) Close the file. */
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+ }
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 9) Delete the file */
+
+ if ( pass ) {
+
+ if ( HDremove(filename) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "HDremove() failed.\n";
+ }
+ }
+
+ if ( pass ) { PASSED(); } else { H5_FAILED(); }
+
+ if ( ! pass )
+ HDfprintf(stdout, "%s: failure_mssg = \"%s\".\n",
+ FUNC, failure_mssg);
+
+ return !pass;
+
+} /* cache_image_smoke_check_2() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: cache_image_smoke_check_3()
+ *
+ * Purpose: This test is one of a sequence of tests intended
+ * to exercise the cache image feature verifying that it
+ * works more or less correctly in common cases.
+ *
+ * This test is an initial smoke check, so the sequence of
+ * operations is relatively simple. In particular, we are
+ * testing:
+ *
+ * i) Creation of file with metadata cache image
+ * superblock extension message and cache image
+ * block.
+ *
+ * ii) Read only open and close of file with metadata
+ * cache image superblock extension message and
+ * cache image block.
+ *
+ * iii) Subsequent R/W open and close of file with metadata
+ * cache image superblock extension message and
+ * cache image block.
+ *
+ * To do this:
+ *
+ * 1) Create a HDF5 file with the cache image FAPL entry.
+ *
+ * Verify that the cache is informed of the cache image
+ * FAPL entry.
+ *
+ * Set all cache image flags, forcing full functionality.
+ *
+ * 2) Create some datasets in the file.
+ *
+ * 3) Close the file.
+ *
+ * 4) Open the file read only.
+ *
+ * Verify that the file contains a metadata cache
+ * image superblock extension message.
+ *
+ * 5 Open a dataset.
+ *
+ * Verify that it contains the expected data.
+ *
+ * 6) Close the file.
+ *
+ * 7) Open the file.
+ *
+ * Verify that the file contains a metadata cache
+ * image superblock extension message.
+ *
+ * 8 Open a dataset.
+ *
+ * Verify that it contains the expected data.
+ *
+ * 9) Close the file.
+ *
+ * 10) Open the file.
+ *
+ * Verify that the file doesn't contain a metadata cache
+ * image superblock extension message.
+ *
+ * 11) Open a dataset.
+ *
+ * Verify that it contains the expected data.
+ *
+ * 12) Close the file.
+ *
+ * 13) Delete the file.
+ *
+ * Return: void
+ *
+ * Programmer: John Mainzer
+ * 8/18/15
+ *
+ *-------------------------------------------------------------------------
+ */
+
+static unsigned
+cache_image_smoke_check_3(void)
+{
+ const char * fcn_name = "cache_image_smoke_check_3()";
+ char filename[512];
+ hbool_t show_progress = FALSE;
+ hid_t file_id = -1;
+ H5F_t *file_ptr = NULL;
+ H5C_t *cache_ptr = NULL;
+ int cp = 0;
+
+ TESTING("metadata cache image smoke check 3");
+
+ pass = TRUE;
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* setup the file name */
+ if ( pass ) {
+
+ if ( h5_fixname(FILENAMES[0], H5P_DEFAULT, filename, sizeof(filename))
+ == NULL ) {
+
+ pass = FALSE;
+ failure_mssg = "h5_fixname() failed.\n";
+ }
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 1) Create a HDF5 file with the cache image FAPL entry.
+ *
+ * Verify that the cache is informed of the cache image FAPL entry.
+ *
+ * Set flags forcing full function of the cache image feature.
+ */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ TRUE,
+ /* mdci_sbem_expected */ FALSE,
+ /* read_only */ FALSE,
+ /* set_mdci_fapl */ TRUE,
+ /* config_fsm */ TRUE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ H5C_CI__ALL_FLAGS,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 2) Create some datasets in the file. */
+
+ if ( pass ) {
+
+ create_datasets(file_id, 0, 5);
+ }
+
+#if H5C_COLLECT_CACHE_STATS
+ if ( pass ) {
+
+ if ( cache_ptr->images_loaded != 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "metadata cache image block loaded(1).";
+ }
+ }
+#endif /* H5C_COLLECT_CACHE_STATS */
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 3) Close the file. */
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+
+ }
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 4) Open the file read only.
+ *
+ * Verify that the metadata cache is instructed to load the
+ * metadata cache image.
+ */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ FALSE,
+ /* mdci_sbem_expected */ TRUE,
+ /* read_only */ TRUE,
+ /* set_mdci_fapl */ FALSE,
+ /* config_fsm */ FALSE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ 0,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 5) Open and close a dataset.
+ *
+ * Verify that the metadata cache image superblock
+ * extension message has been deleted.
+ */
+
+ if ( pass ) {
+
+ verify_datasets(file_id, 0, 5);
+ }
+
+#if H5C_COLLECT_CACHE_STATS
+ if ( pass ) {
+
+ if ( cache_ptr->images_loaded == 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "metadata cache image block not loaded(1).";
+ }
+ }
+#endif /* H5C_COLLECT_CACHE_STATS */
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 6) Close the file. */
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+ }
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 7) Open the file.
+ *
+ * Verify that the file contains a metadata cache image
+ * superblock extension message.
+ */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ FALSE,
+ /* mdci_sbem_expected */ TRUE,
+ /* read_only */ FALSE,
+ /* set_mdci_fapl */ FALSE,
+ /* config_fsm */ FALSE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ 0,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 8) Open and close a dataset.
+ *
+ * Verify that the metadata cache image superblock
+ * extension message has been deleted.
+ */
+
+ if ( pass ) {
+
+ verify_datasets(file_id, 0, 5);
+ }
+
+#if H5C_COLLECT_CACHE_STATS
+ if ( pass ) {
+
+ if ( cache_ptr->images_loaded == 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "metadata cache image block not loaded(2).";
+ }
+ }
+#endif /* H5C_COLLECT_CACHE_STATS */
+
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 9) Close the file. */
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+ }
+ }
+
+
+ /* 10) Open the file.
+ *
+ * Verify that the file doesn't contain a metadata cache image
+ * superblock extension message.
+ */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ FALSE,
+ /* mdci_sbem_expected */ FALSE,
+ /* read_only */ FALSE,
+ /* set_mdci_fapl */ FALSE,
+ /* config_fsm */ FALSE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ 0,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 11) Open and close a dataset.
+ *
+ * Verify that the metadata cache image superblock
+ * extension message has been deleted.
+ */
+
+ if ( pass ) {
+
+ verify_datasets(file_id, 0, 5);
+ }
+
+#if H5C_COLLECT_CACHE_STATS
+ if ( pass ) {
+
+ if ( cache_ptr->images_loaded != 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "metadata cache image block loaded(2).";
+ }
+ }
+#endif /* H5C_COLLECT_CACHE_STATS */
+
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 12) Close the file. */
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+ }
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 13) Delete the file */
+
+ if ( pass ) {
+
+ if ( HDremove(filename) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "HDremove() failed.\n";
+ }
+ }
+
+ if ( pass ) { PASSED(); } else { H5_FAILED(); }
+
+ if ( ! pass )
+ HDfprintf(stdout, "%s: failure_mssg = \"%s\".\n",
+ FUNC, failure_mssg);
+
+ return !pass;
+
+} /* cache_image_smoke_check_3() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: cache_image_smoke_check_4()
+ *
+ * Purpose: This test attempts to mimic the typical "poor man's
+ * parallel use case in which the file is passed between
+ * processes, each of which open the file, write some data,
+ * close the file, and then pass control on to the next
+ * process.
+ *
+ * In this case, we only write one dataset per process.
+ *
+ * Cycle of operation
+ *
+ * 1) Create a HDF5 file with the cache image FAPL entry.
+ *
+ * Verify that the cache is informed of the cache image
+ * FAPL entry.
+ *
+ * Set all cache image flags, forcing full functionality.
+ *
+ * 2) Create and write a dataset in the file.
+ *
+ * 3) Close the file.
+ *
+ * 4) Open the file with the cache image FAPL entry.
+ *
+ * Verify that the file contains a metadata cache
+ * image superblock extension message.
+ *
+ * 5 Create and write a new dataset
+ *
+ * 6) Close the file.
+ *
+ * If sufficient datasets have been created, continue to
+ * 7). Otherwise goto 4)
+ *
+ * 7) Open the file.
+ *
+ * Verify that the file contains a metadata cache
+ * image superblock extension message.
+ *
+ * 8) Open all datasets that have been created, and
+ * verify that they contain the expected data.
+ *
+ * 9) Close the file.
+ *
+ * 10) Open the file.
+ *
+ * Verify that the file doesn't contain a metadata cache
+ * image superblock extension message.
+ *
+ * 11) Open all datasets that have been created, and
+ * verify that they contain the expected data.
+ *
+ * Verify that it contains the expected data.
+ *
+ * 12) Close the file.
+ *
+ * 13) Delete the file.
+ *
+ * Return: void
+ *
+ * Programmer: John Mainzer
+ * 8/18/15
+ *
+ *-------------------------------------------------------------------------
+ */
+
+static unsigned
+cache_image_smoke_check_4(void)
+{
+ const char * fcn_name = "cache_image_smoke_check_4()";
+ char filename[512];
+ hbool_t show_progress = FALSE;
+ hid_t file_id = -1;
+ H5F_t *file_ptr = NULL;
+ H5C_t *cache_ptr = NULL;
+ int cp = 0;
+ int min_dset = 0;
+ int max_dset = 0;
+
+ TESTING("metadata cache image smoke check 4");
+
+ pass = TRUE;
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* setup the file name */
+ if ( pass ) {
+
+ if ( h5_fixname(FILENAMES[0], H5P_DEFAULT, filename, sizeof(filename))
+ == NULL ) {
+
+ pass = FALSE;
+ failure_mssg = "h5_fixname() failed.\n";
+ }
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 1) Create a HDF5 file with the cache image FAPL entry.
+ *
+ * Verify that the cache is informed of the cache image FAPL entry.
+ *
+ * Set flags forcing full function of the cache image feature.
+ */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ TRUE,
+ /* mdci_sbem_expected */ FALSE,
+ /* read_only */ FALSE,
+ /* set_mdci_fapl */ TRUE,
+ /* config_fsm */ TRUE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ H5C_CI__ALL_FLAGS,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 2) Create a dataset in the file. */
+
+ if ( pass ) {
+
+ create_datasets(file_id, min_dset++, max_dset++);
+ }
+
+#if H5C_COLLECT_CACHE_STATS
+ if ( pass ) {
+
+ if ( cache_ptr->images_loaded != 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "metadata cache image block loaded(1).";
+ }
+ }
+#endif /* H5C_COLLECT_CACHE_STATS */
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 3) Close the file. */
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+
+ }
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+ while ( ( pass ) && ( max_dset < MAX_NUM_DSETS ) )
+ {
+
+ /* 4) Open the file.
+ *
+ * Verify that the metadata cache is instructed to load the
+ * metadata cache image.
+ */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ FALSE,
+ /* mdci_sbem_expected */ TRUE,
+ /* read_only */ FALSE,
+ /* set_mdci_fapl */ TRUE,
+ /* config_fsm */ FALSE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ H5C_CI__ALL_FLAGS,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s:L1 cp = %d, max_dset = %d, pass = %d.\n",
+ fcn_name, cp, max_dset, pass);
+
+
+ /* 5) Create a dataset in the file. */
+
+ if ( pass ) {
+
+ create_datasets(file_id, min_dset++, max_dset++);
+ }
+
+#if H5C_COLLECT_CACHE_STATS
+ if ( pass ) {
+
+ if ( cache_ptr->images_loaded == 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "metadata cache image block not loaded(1).";
+ }
+ }
+#endif /* H5C_COLLECT_CACHE_STATS */
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s:L2 cp = %d, max_dset = %d, pass = %d.\n",
+ fcn_name, cp + 1, max_dset, pass);
+
+
+ /* 6) Close the file. */
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+
+ }
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s:L3 cp = %d, max_dset = %d, pass = %d.\n",
+ fcn_name, cp + 2, max_dset, pass);
+ } /* end while */
+ cp += 3;
+
+
+ /* 7) Open the file.
+ *
+ * Verify that the file contains a metadata cache image
+ * superblock extension message.
+ */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ FALSE,
+ /* mdci_sbem_expected */ TRUE,
+ /* read_only */ FALSE,
+ /* set_mdci_fapl */ FALSE,
+ /* config_fsm */ FALSE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ 0,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 8) Open and close all datasets.
+ *
+ * Verify that the metadata cache image superblock
+ * extension message has been deleted.
+ */
+
+ if ( pass ) {
+
+ verify_datasets(file_id, 0, max_dset - 1);
+ }
+
+#if H5C_COLLECT_CACHE_STATS
+ if ( pass ) {
+
+ if ( cache_ptr->images_loaded == 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "metadata cache image block not loaded(2).";
+ }
+ }
+#endif /* H5C_COLLECT_CACHE_STATS */
+
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 9) Close the file. */
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+ }
+ }
+
+
+ /* 10) Open the file.
+ *
+ * Verify that the file doesn't contain a metadata cache image
+ * superblock extension message.
+ */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ FALSE,
+ /* mdci_sbem_expected */ FALSE,
+ /* read_only */ FALSE,
+ /* set_mdci_fapl */ FALSE,
+ /* config_fsm */ FALSE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ 0,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 11) Open and close all datasets.
+ *
+ * Verify that the metadata cache image superblock
+ * extension message has been deleted.
+ */
+
+ if ( pass ) {
+
+ verify_datasets(file_id, 0, max_dset - 1);
+ }
+
+#if H5C_COLLECT_CACHE_STATS
+ if ( pass ) {
+
+ if ( cache_ptr->images_loaded != 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "metadata cache image block loaded(2).";
+ }
+ }
+#endif /* H5C_COLLECT_CACHE_STATS */
+
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 12) Close the file. */
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+ }
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 13) Delete the file */
+
+ if ( pass ) {
+
+ if ( HDremove(filename) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "HDremove() failed.\n";
+ }
+ }
+
+ if ( pass ) { PASSED(); } else { H5_FAILED(); }
+
+ if ( ! pass )
+ HDfprintf(stdout, "%s: failure_mssg = \"%s\".\n",
+ FUNC, failure_mssg);
+
+ return !pass;
+
+} /* cache_image_smoke_check_4() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: cache_image_smoke_check_5()
+ *
+ * Purpose: This test attempts to mimic the typical "poor man's
+ * parallel use case in which the file is passed between
+ * processes, each of which open the file, write some data,
+ * close the file, and then pass control on to the next
+ * process.
+ *
+ * In this case, we create one group for each process, and
+ * populate it with a "zoo" of HDF5 objects selected to
+ * (ideally) exercise all HDF5 on disk data structures.
+ *
+ * Cycle of operation
+ *
+ * 1) Create a HDF5 file with the cache image FAPL entry.
+ *
+ * Verify that the cache is informed of the cache image
+ * FAPL entry.
+ *
+ * Set all cache image flags, forcing full functionality.
+ *
+ * 2) Create a process specific group.
+ *
+ * 3) Construct a "zoo" in the above group, and validate it.
+ *
+ * 4) Close the file.
+ *
+ * 5) Open the file with the cache image FAPL entry.
+ *
+ * Verify that the file contains a metadata cache
+ * image superblock extension message.
+ *
+ * 6) Validate the "zoo" created in the previous file open.
+ *
+ * 7) Create a process specific group for this file open
+ *
+ * 8) Construct a "zoo" in the above group, and validate it.
+ *
+ * 9) Close the file.
+ *
+ * If sufficient zoos have been created, continue to
+ * 10). Otherwise goto 5)
+ *
+ * 10) Open the file.
+ *
+ * Verify that the file contains a metadata cache
+ * image superblock extension message.
+ *
+ * 11) Validate all the zoos.
+ *
+ * 12) Close the file.
+ *
+ * 13) Open the file.
+ *
+ * Verify that the file doesn't contain a metadata cache
+ * image superblock extension message.
+ *
+ * 14) Validate all the zoos.
+ *
+ * 15) Close the file.
+ *
+ * 16) Delete the file.
+ *
+ * Return: void
+ *
+ * Programmer: John Mainzer
+ * 9/15/15
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#define MAX_NUM_GROUPS 128
+
+static unsigned
+cache_image_smoke_check_5(void)
+{
+ const char * fcn_name = "cache_image_smoke_check_5()";
+ char filename[512];
+ char process_group_name[512];
+ hbool_t show_progress = FALSE;
+ hid_t file_id = -1;
+ hid_t proc_gid = -1;
+ H5F_t *file_ptr = NULL;
+ H5C_t *cache_ptr = NULL;
+ int cp = 0;
+ int i;
+ int min_group = 0;
+ int max_group = 0;
+
+ TESTING("metadata cache image smoke check 5");
+
+ pass = TRUE;
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* setup the file name */
+ if ( pass ) {
+
+ if ( h5_fixname(FILENAMES[0], H5P_DEFAULT, filename, sizeof(filename))
+ == NULL ) {
+
+ pass = FALSE;
+ failure_mssg = "h5_fixname() failed.\n";
+ }
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 1) Create a HDF5 file with the cache image FAPL entry.
+ *
+ * Verify that the cache is informed of the cache image FAPL entry.
+ *
+ * Set flags forcing full function of the cache image feature.
+ */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ TRUE,
+ /* mdci_sbem_expected */ FALSE,
+ /* read_only */ FALSE,
+ /* set_mdci_fapl */ TRUE,
+ /* config_fsm */ TRUE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ H5C_CI__ALL_FLAGS,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 2) Create a process specific group. */
+ if ( pass ) {
+
+ sprintf(process_group_name, "/process_%d", min_group);
+
+ proc_gid = H5Gcreate2(file_id, process_group_name, H5P_DEFAULT,
+ H5P_DEFAULT, H5P_DEFAULT);
+
+ if ( proc_gid < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Gcreate2() failed (1).\n";
+ }
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 3) Construct a "zoo" in the above group, and validate it. */
+ if ( pass )
+ create_zoo(file_id, process_group_name, min_group);
+
+#if H5C_COLLECT_CACHE_STATS
+ if ( pass ) {
+
+ if ( cache_ptr->images_loaded != 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "metadata cache image block loaded(1).";
+ }
+ }
+#endif /* H5C_COLLECT_CACHE_STATS */
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 4) Close the file. */
+
+ if ( pass ) {
+
+ if ( H5Gclose(proc_gid) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Gclose(proc_gid) failed. (1)";
+ }
+ }
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+
+ }
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+ while ( ( pass ) && ( max_group < MAX_NUM_GROUPS ) )
+ {
+
+ /* 5) Open the file.
+ *
+ * Verify that the metadata cache is instructed to load the
+ * metadata cache image.
+ */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ FALSE,
+ /* mdci_sbem_expected */ TRUE,
+ /* read_only */ FALSE,
+ /* set_mdci_fapl */ TRUE,
+ /* config_fsm */ FALSE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ H5C_CI__ALL_FLAGS,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s:L1 cp = %d, max_group = %d, pass = %d.\n",
+ fcn_name, cp, max_group, pass);
+
+
+ /* 6) Validate the "zoo" created in the previous file open. */
+ if ( pass )
+ validate_zoo(file_id, process_group_name, max_group);
+
+#if H5C_COLLECT_CACHE_STATS
+ if ( pass ) {
+
+ if ( cache_ptr->images_loaded == 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "metadata cache image block not loaded(1).";
+ }
+ }
+#endif /* H5C_COLLECT_CACHE_STATS */
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s:L2 cp = %d, max_group = %d, pass = %d.\n",
+ fcn_name, cp + 1, max_group, pass);
+
+
+ /* 7) Create a process specific group for this file open */
+ if ( pass ) {
+
+ max_group++;
+ sprintf(process_group_name, "/process_%d", max_group);
+
+ proc_gid = H5Gcreate2(file_id, process_group_name, H5P_DEFAULT,
+ H5P_DEFAULT, H5P_DEFAULT);
+
+ if ( proc_gid < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Gcreate2() failed (2).\n";
+ }
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s:L3 cp = %d, max_group = %d, pass = %d.\n",
+ fcn_name, cp + 2, max_group, pass);
+
+
+ /* 8) Construct a "zoo" in the above group, and validate it. */
+ if ( pass )
+ create_zoo(file_id, process_group_name, max_group);
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s:L4 cp = %d, max_group = %d, pass = %d.\n",
+ fcn_name, cp + 3, max_group, pass);
+
+
+ /* 9) Close the file. */
+
+ if ( pass ) {
+
+ if ( H5Gclose(proc_gid) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Gclose(process_gid) failed. (2)";
+ }
+ }
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+
+ }
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s:L5 cp = %d, max_group = %d, pass = %d.\n",
+ fcn_name, cp + 4, max_group, pass);
+ } /* end while */
+ cp += 5;
+
+
+
+ /* 10) Open the file.
+ *
+ * Verify that the file contains a metadata cache image
+ * superblock extension message.
+ */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ FALSE,
+ /* mdci_sbem_expected */ TRUE,
+ /* read_only */ FALSE,
+ /* set_mdci_fapl */ FALSE,
+ /* config_fsm */ FALSE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ 0,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 11) Validate all the zoos. */
+ i = min_group;
+ while ( ( pass ) && ( i <= max_group ) ) {
+
+ sprintf(process_group_name, "/process_%d", i);
+ validate_zoo(file_id, process_group_name, i++);
+ }
+
+#if H5C_COLLECT_CACHE_STATS
+ if ( pass ) {
+
+ if ( cache_ptr->images_loaded == 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "metadata cache image block not loaded(2).";
+ }
+ }
+#endif /* H5C_COLLECT_CACHE_STATS */
+
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 12) Close the file. */
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+ }
+ }
+
+
+ /* 13) Open the file.
+ *
+ * Verify that the file doesn't contain a metadata cache image
+ * superblock extension message.
+ */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ FALSE,
+ /* mdci_sbem_expected */ FALSE,
+ /* read_only */ FALSE,
+ /* set_mdci_fapl */ FALSE,
+ /* config_fsm */ FALSE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ 0,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 14) Validate all the zoos.
+ *
+ * Verify that the metadata cache image superblock
+ * extension message has been deleted.
+ */
+ i = min_group;
+ while ( ( pass ) && ( i <= max_group ) ) {
+
+ sprintf(process_group_name, "/process_%d", i);
+ validate_zoo(file_id, process_group_name, i++);
+ }
+
+#if H5C_COLLECT_CACHE_STATS
+ if ( pass ) {
+
+ if ( cache_ptr->images_loaded != 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "metadata cache image block loaded(2).";
+ }
+ }
+#endif /* H5C_COLLECT_CACHE_STATS */
+
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 15) Close the file. */
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+ }
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 16) Delete the file */
+
+ if ( pass ) {
+
+ if ( HDremove(filename) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "HDremove() failed.\n";
+ }
+ }
+
+
+ if ( pass ) { PASSED(); } else { H5_FAILED(); }
+
+ if ( ! pass )
+ HDfprintf(stdout, "%s: failure_mssg = \"%s\".\n",
+ FUNC, failure_mssg);
+
+ return !pass;
+
+} /* cache_image_smoke_check_5() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: cache_image_smoke_check_6()
+ *
+ * Purpose: As the free space manager metadata is now included in the
+ * cache image, a smoke check to verify generally correct
+ * behaviour of the persistent free space managers seems
+ * prudent.
+ *
+ * The basic idea of this test is to construct a long
+ * sequence of dataset creations and deletions, all separated
+ * by file open/close cycles with cache image enabled. If the
+ * perisistant free space managers are performing as expected,
+ * the size of the file should stabilize.
+ *
+ * To implement this, proceed as outlined in the cycle of
+ * operation below:
+ *
+ * Cycle of operation
+ *
+ * 1) Create a HDF5 file with the cache image FAPL entry.
+ *
+ * Verify that the cache is informed of the cache image
+ * FAPL entry.
+ *
+ * Set all cache image flags, forcing full functionality.
+ *
+ * 2) Create and write a dataset in the file.
+ *
+ * 3) Close the file.
+ *
+ * 4) Open the file with the cache image FAPL entry.
+ *
+ * Verify that the file contains a metadata cache
+ * image superblock extension message.
+ *
+ * 5) Create and write a new dataset.
+ *
+ * 6) Verify and delete the old dataset.
+ *
+ * 7) Close the file.
+ *
+ * If sufficient datasets have been created, and then
+ * deleteded continue to 8). Otherwise goto 4)
+ *
+ * 8) Open the file.
+ *
+ * Verify that the file contains a metadata cache
+ * image superblock extension message.
+ *
+ * 9) Verify the last dataset created.
+ *
+ * 10) Close the file.
+ *
+ * 11) Open the file.
+ *
+ * 12) Verify and delete the last dataset.
+ *
+ * Verify that a metadata cache image is not loaded.
+ *
+ * 13) Close the file.
+ *
+ * 14) Get the size of the file. Verify that it is less
+ * than 1 KB. Without deletions and persistant free
+ * space managers, size size is about 167 MB, so this
+ * is sufficient to verify that the persistant free
+ * space managers are more or less doing their job.
+ *
+ * 15) Delete the file.
+ *
+ * Return: void
+ *
+ * Programmer: John Mainzer
+ * 10/31/16
+ *
+ *-------------------------------------------------------------------------
+ */
+
+static unsigned
+cache_image_smoke_check_6(void)
+{
+ const char * fcn_name = "cache_image_smoke_check_6()";
+ char filename[512];
+ hbool_t show_progress = FALSE;
+ hid_t file_id = -1;
+ H5F_t *file_ptr = NULL;
+ H5C_t *cache_ptr = NULL;
+ h5_stat_size_t file_size;
+ int cp = 0;
+ int min_dset = 0;
+ int max_dset = 0;
+
+ TESTING("metadata cache image smoke check 6");
+
+ pass = TRUE;
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* setup the file name */
+ if ( pass ) {
+
+ if ( h5_fixname(FILENAMES[0], H5P_DEFAULT, filename, sizeof(filename))
+ == NULL ) {
+
+ pass = FALSE;
+ failure_mssg = "h5_fixname() failed.\n";
+ }
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 1) Create a HDF5 file with the cache image FAPL entry.
+ *
+ * Verify that the cache is informed of the cache image FAPL entry.
+ *
+ * Set flags forcing full function of the cache image feature.
+ */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ TRUE,
+ /* mdci_sbem_expected */ FALSE,
+ /* read_only */ FALSE,
+ /* set_mdci_fapl */ TRUE,
+ /* config_fsm */ TRUE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ H5C_CI__ALL_FLAGS,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 2) Create a dataset in the file. */
+
+ if ( pass ) {
+
+ create_datasets(file_id, min_dset++, max_dset++);
+ }
+
+#if H5C_COLLECT_CACHE_STATS
+ if ( pass ) {
+
+ if ( cache_ptr->images_loaded != 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "metadata cache image block loaded(1).";
+ }
+ }
+#endif /* H5C_COLLECT_CACHE_STATS */
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 3) Close the file. */
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+
+ }
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+ while ( ( pass ) && ( max_dset < MAX_NUM_DSETS ) )
+ {
+
+ /* 4) Open the file.
+ *
+ * Verify that the metadata cache is instructed to load the
+ * metadata cache image.
+ */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ FALSE,
+ /* mdci_sbem_expected */ TRUE,
+ /* read_only */ FALSE,
+ /* set_mdci_fapl */ TRUE,
+ /* config_fsm */ FALSE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ H5C_CI__ALL_FLAGS,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s:L1 cp = %d, max_dset = %d, pass = %d.\n",
+ fcn_name, cp, max_dset, pass);
+
+
+ /* 5) Create a dataset in the file. */
+
+ if ( pass ) {
+
+ create_datasets(file_id, min_dset++, max_dset++);
+ }
+
+#if H5C_COLLECT_CACHE_STATS
+ if ( pass ) {
+
+ if ( cache_ptr->images_loaded == 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "metadata cache image block not loaded(1).";
+ }
+ }
+#endif /* H5C_COLLECT_CACHE_STATS */
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s:L2 cp = %d, max_dset = %d, pass = %d.\n",
+ fcn_name, cp + 1, max_dset, pass);
+
+
+ /* 6) Verify and delete the old dataset. */
+ if ( pass ) {
+
+ delete_datasets(file_id, min_dset - 2, max_dset - 2);
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s:L3 cp = %d, max_dset = %d, pass = %d.\n",
+ fcn_name, cp + 2, max_dset, pass);
+
+
+ /* 7) Close the file. */
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+
+ }
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s:L4 cp = %d, max_dset = %d, pass = %d.\n",
+ fcn_name, cp + 3, max_dset, pass);
+ } /* end while */
+ cp += 4;
+
+
+ /* 8) Open the file.
+ *
+ * Verify that the file contains a metadata cache image
+ * superblock extension message.
+ */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ FALSE,
+ /* mdci_sbem_expected */ TRUE,
+ /* read_only */ FALSE,
+ /* set_mdci_fapl */ FALSE,
+ /* config_fsm */ FALSE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ 0,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 9) Verify the last dataset created. */
+
+ if ( pass ) {
+
+ verify_datasets(file_id, min_dset - 1, max_dset - 1);
+ }
+
+#if H5C_COLLECT_CACHE_STATS
+ if ( pass ) {
+
+ if ( cache_ptr->images_loaded == 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "metadata cache image block not loaded(2).";
+ }
+ }
+#endif /* H5C_COLLECT_CACHE_STATS */
+
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 10) Close the file. */
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+ }
+ }
+
+
+ /* 11) Open the file.
+ *
+ * Verify that the file doesn't contain a metadata cache image
+ * superblock extension message.
+ */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ FALSE,
+ /* mdci_sbem_expected */ FALSE,
+ /* read_only */ FALSE,
+ /* set_mdci_fapl */ FALSE,
+ /* config_fsm */ FALSE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ 0,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 12) Verify and delete the last dataset.
+ *
+ * Verify that a metadata cache image is not loaded.
+ */
+
+ if ( pass ) {
+
+ delete_datasets(file_id, min_dset - 1, max_dset - 1);
+ }
+
+#if H5C_COLLECT_CACHE_STATS
+ if ( pass ) {
+
+ if ( cache_ptr->images_loaded != 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "metadata cache image block loaded(2).";
+ }
+ }
+#endif /* H5C_COLLECT_CACHE_STATS */
+
+
+
+ /* 13) Close the file. */
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+ }
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 14) Get the size of the file. Verify that it is less
+ * than 1 KB. Without deletions and persistant free
+ * space managers, size size is about 167 MB, so this
+ * is sufficient to verify that the persistant free
+ * space managers are more or less doing their job.
+ */
+ if((file_size = h5_get_file_size(filename, H5P_DEFAULT)) < 0) {
+
+ pass = FALSE;
+ failure_mssg = "h5_get_file_size() failed.\n";
+
+ } else if ( file_size > 1024 ) {
+
+ pass = FALSE;
+ failure_mssg = "unexpectedly large file size.\n";
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 15) Delete the file */
+ if ( pass ) {
+
+ if ( HDremove(filename) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "HDremove() failed.\n";
+ }
+ }
+
+
+ if ( pass ) { PASSED(); } else { H5_FAILED(); }
+
+ if ( ! pass )
+ HDfprintf(stdout, "%s: failure_mssg = \"%s\".\n",
+ FUNC, failure_mssg);
+
+ return !pass;
+
+} /* cache_image_smoke_check_6() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: cache_image_api_error_check_1()
+ *
+ * Purpose: This test is one of a sequence of tests intended
+ * to verify correct management of API errors.
+ *
+ * The object of this test is to verify that a file without
+ * a pre-existing cache image that is opened both read only
+ * and with a cache image requested is handle correctly
+ * (the cache image request should be ignored silently).
+ *
+ * The test is set up as follows:
+ *
+ * 1) Create a HDF5 file.
+ *
+ * 2) Create some datasets in the file.
+ *
+ * 3) Close the file.
+ *
+ * 4) Open the file read only with a cache image FAPL entry
+ * requested.
+ *
+ * 5) Open a dataset.
+ *
+ * Verify that it contains the expected data
+ *
+ * Verify that the cache image was not loaded.
+ *
+ * 6) Close the file.
+ *
+ * 7) Open the file read only.
+ *
+ * 8) Open a dataset.
+ *
+ * Verify that it contains the expected data.
+ *
+ * Verify that the cache image was not loaded.
+ *
+ * 9) Close the file.
+ *
+ * 10) Open the file read write.
+ *
+ * 11) Open a dataset.
+ *
+ * Verify that it contains the expected data.
+ *
+ * 12) Close the file.
+ *
+ * 13) Delete the file.
+ *
+ * Return: void
+ *
+ * Programmer: John Mainzer
+ * 9/25/15
+ *
+ *-------------------------------------------------------------------------
+ */
+
+static unsigned
+cache_image_api_error_check_1(void)
+{
+ const char * fcn_name = "cache_image_api_error_check_1()";
+ char filename[512];
+ hbool_t show_progress = FALSE;
+ hid_t file_id = -1;
+ H5F_t *file_ptr = NULL;
+ H5C_t *cache_ptr = NULL;
+ int cp = 0;
+
+ TESTING("metadata cache image api error check 1");
+
+ pass = TRUE;
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* setup the file name */
+ if ( pass ) {
+
+ if ( h5_fixname(FILENAMES[0], H5P_DEFAULT, filename, sizeof(filename))
+ == NULL ) {
+
+ pass = FALSE;
+ failure_mssg = "h5_fixname() failed.\n";
+ }
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 1) Create a HDF5 file. */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ TRUE,
+ /* mdci_sbem_expected */ FALSE,
+ /* read_only */ FALSE,
+ /* set_mdci_fapl */ FALSE,
+ /* config_fsm */ TRUE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ 0,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 2) Create some datasets in the file. */
+
+ if ( pass ) {
+
+ create_datasets(file_id, 0, 5);
+ }
+
+#if H5C_COLLECT_CACHE_STATS
+ if ( pass ) {
+
+ if ( cache_ptr->images_loaded != 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "metadata cache image block loaded(1).";
+ }
+ }
+#endif /* H5C_COLLECT_CACHE_STATS */
+
+
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 3) Close the file. */
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+
+ }
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 4) Open the file read only with a cache image FAPL entry requested. */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ FALSE,
+ /* mdci_sbem_expected */ FALSE,
+ /* read_only */ TRUE,
+ /* set_mdci_fapl */ TRUE,
+ /* config_fsm */ FALSE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ H5C_CI__ALL_FLAGS,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 5) Open and close a dataset.
+ *
+ * Verify that it contains the expected data.
+ *
+ * Verify that the cache image was not loaded.
+ */
+
+ if ( pass ) {
+
+ verify_datasets(file_id, 0, 5);
+ }
+
+#if H5C_COLLECT_CACHE_STATS
+ if ( pass ) {
+
+ if ( cache_ptr->images_loaded != 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "metadata cache image block loaded(2).";
+ }
+ }
+#endif /* H5C_COLLECT_CACHE_STATS */
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 6) Close the file. */
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+ }
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 7) Open the file read only. */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ FALSE,
+ /* mdci_sbem_expected */ FALSE,
+ /* read_only */ TRUE,
+ /* set_mdci_fapl */ FALSE,
+ /* config_fsm */ FALSE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ 0,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 8) Open and close a dataset.
+ *
+ * Verify that it contains the expected data.
+ *
+ * Verify that the cache image was not loaded.
+ */
+
+ if ( pass ) {
+
+ verify_datasets(file_id, 0, 5);
+ }
+
+#if H5C_COLLECT_CACHE_STATS
+ if ( pass ) {
+
+ if ( cache_ptr->images_loaded != 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "metadata cache image block loaded(3).";
+ }
+ }
+#endif /* H5C_COLLECT_CACHE_STATS */
+
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 9) Close the file. */
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+ }
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 10) Open the file read / write. */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ FALSE,
+ /* mdci_sbem_expected */ FALSE,
+ /* read_only */ FALSE,
+ /* set_mdci_fapl */ FALSE,
+ /* config_fsm */ FALSE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ H5C_CI__ALL_FLAGS,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+ /* 11) Open and close a dataset.
+ *
+ * Verify that it contains the expected data.
+ *
+ * Verify that the cache image was not loaded.
+ */
+
+ if ( pass ) {
+
+ verify_datasets(file_id, 0, 5);
+ }
+
+#if H5C_COLLECT_CACHE_STATS
+ if ( pass ) {
+
+ if ( cache_ptr->images_loaded != 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "metadata cache image block loaded(4).";
+ }
+ }
+#endif /* H5C_COLLECT_CACHE_STATS */
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 12) Close the file. */
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+ }
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 13) Delete the file */
+
+ if ( pass ) {
+
+ if ( HDremove(filename) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "HDremove() failed.\n";
+ }
+ }
+
+ if ( pass ) { PASSED(); } else { H5_FAILED(); }
+
+ if ( ! pass )
+ HDfprintf(stdout, "%s: failure_mssg = \"%s\".\n",
+ FUNC, failure_mssg);
+
+ return !pass;
+
+} /* cache_image_api_error_check_1() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: cache_image_api_error_check_2()
+ *
+ * Purpose: This test is one of a sequence of tests intended
+ * to verify correct management of API errors.
+ *
+ * The object of this test is to verify that a file with
+ * a pre-existing cache image that is opened both read only
+ * and with a cache image requested is handled correctly
+ * (the cache image request should be ignored silently).
+ *
+ * The test is set up as follows:
+ *
+ * 1) Create a HDF5 file with a cache image requested..
+ *
+ * 2) Create some datasets in the file.
+ *
+ * 3) Close the file.
+ *
+ * 4) Open the file read only with a cache image FAPL entry
+ * requested.
+ *
+ * 5) Open a dataset.
+ *
+ * Verify that it contains the expected data
+ *
+ * Verify that the cache image was loaded.
+ *
+ * 6) Close the file.
+ *
+ * 7) Open the file read only.
+ *
+ * 8) Open a dataset.
+ *
+ * Verify that it contains the expected data.
+ *
+ * Verify that the cache image was loaded.
+ *
+ * 9) Close the file.
+ *
+ * 10) Open the file read write.
+ *
+ * 11) Open a dataset.
+ *
+ * Verify that it contains the expected data.
+ *
+ * Verify that the cache image was loaded.
+ *
+ * 12) Close the file.
+ *
+ * 13) Open the file read write.
+ *
+ * 14) Open a dataset.
+ *
+ * Verify that it contains the expected data.
+ *
+ * Verify that the cache image was NOT loaded.
+ *
+ * 15) Close the file.
+ *
+ * 16) Delete the file.
+ *
+ * Return: void
+ *
+ * Programmer: John Mainzer
+ * 9/25/15
+ *
+ *-------------------------------------------------------------------------
+ */
+
+static unsigned
+cache_image_api_error_check_2(void)
+{
+ const char * fcn_name = "cache_image_api_error_check_2()";
+ char filename[512];
+ hbool_t show_progress = FALSE;
+ hid_t file_id = -1;
+ H5F_t *file_ptr = NULL;
+ H5C_t *cache_ptr = NULL;
+ int cp = 0;
+
+ TESTING("metadata cache image api error check 2");
+
+ pass = TRUE;
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* setup the file name */
+ if ( pass ) {
+
+ if ( h5_fixname(FILENAMES[0], H5P_DEFAULT, filename, sizeof(filename))
+ == NULL ) {
+
+ pass = FALSE;
+ failure_mssg = "h5_fixname() failed.\n";
+ }
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 1) Create a HDF5 file with a cache image requested. */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ TRUE,
+ /* mdci_sbem_expected */ FALSE,
+ /* read_only */ FALSE,
+ /* set_mdci_fapl */ TRUE,
+ /* config_fsm */ TRUE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ H5C_CI__ALL_FLAGS,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 2) Create some datasets in the file. */
+
+ if ( pass ) {
+
+ create_datasets(file_id, 0, 5);
+ }
+
+#if H5C_COLLECT_CACHE_STATS
+ if ( pass ) {
+
+ if ( cache_ptr->images_loaded != 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "metadata cache image block loaded(1).";
+ }
+ }
+#endif /* H5C_COLLECT_CACHE_STATS */
+
+
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 3) Close the file. */
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+
+ }
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 4) Open the file read only with a cache image FAPL entry requested. */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ FALSE,
+ /* mdci_sbem_expected */ TRUE,
+ /* read_only */ TRUE,
+ /* set_mdci_fapl */ TRUE,
+ /* config_fsm */ FALSE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ H5C_CI__ALL_FLAGS,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 5) Open and close a dataset.
+ *
+ * Verify that it contains the expected data.
+ *
+ * Verify that the cache image was loaded.
+ */
+
+ if ( pass ) {
+
+ verify_datasets(file_id, 0, 5);
+ }
+
+#if H5C_COLLECT_CACHE_STATS
+ if ( pass ) {
+
+ if ( cache_ptr->images_loaded != 1 ) {
+
+ pass = FALSE;
+ failure_mssg = "metadata cache image block was not loaded(1).";
+ }
+ }
+#endif /* H5C_COLLECT_CACHE_STATS */
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 6) Close the file. */
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+ }
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 7) Open the file read only. */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ FALSE,
+ /* mdci_sbem_expected */ TRUE,
+ /* read_only */ TRUE,
+ /* set_mdci_fapl */ FALSE,
+ /* config_fsm */ FALSE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ 0,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 8) Open and close a dataset.
+ *
+ * Verify that it contains the expected data.
+ *
+ * Verify that the cache image was loaded.
+ */
+
+ if ( pass ) {
+
+ verify_datasets(file_id, 0, 5);
+ }
+
+#if H5C_COLLECT_CACHE_STATS
+ if ( pass ) {
+
+ if ( cache_ptr->images_loaded != 1 ) {
+
+ pass = FALSE;
+ failure_mssg = "metadata cache image block was not loaded(2).";
+ }
+ }
+#endif /* H5C_COLLECT_CACHE_STATS */
+
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 9) Close the file. */
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+ }
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 10) Open the file read / write. */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ FALSE,
+ /* mdci_sbem_expected */ TRUE,
+ /* read_only */ FALSE,
+ /* set_mdci_fapl */ FALSE,
+ /* config_fsm */ FALSE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ H5C_CI__ALL_FLAGS,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+ /* 11) Open and close a dataset.
+ *
+ * Verify that it contains the expected data.
+ *
+ * Verify that the cache image was loaded.
+ */
+
+ if ( pass ) {
+
+ verify_datasets(file_id, 0, 5);
+ }
+
+#if H5C_COLLECT_CACHE_STATS
+ if ( pass ) {
+
+ if ( cache_ptr->images_loaded != 1 ) {
+
+ pass = FALSE;
+ failure_mssg = "metadata cache image block was not loaded(3).";
+ }
+ }
+#endif /* H5C_COLLECT_CACHE_STATS */
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 12) Close the file. */
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+ }
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 13) Open the file read / write. */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ FALSE,
+ /* mdci_sbem_expected */ FALSE,
+ /* read_only */ FALSE,
+ /* set_mdci_fapl */ FALSE,
+ /* config_fsm */ FALSE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ H5C_CI__ALL_FLAGS,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+ /* 14) Open and close a dataset.
+ *
+ * Verify that it contains the expected data.
+ *
+ * Verify that the cache image was not loaded.
+ */
+
+ if ( pass ) {
+
+ verify_datasets(file_id, 0, 5);
+ }
+
+#if H5C_COLLECT_CACHE_STATS
+ if ( pass ) {
+
+ if ( cache_ptr->images_loaded != 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "metadata cache image block was loaded(2).";
+ }
+ }
+#endif /* H5C_COLLECT_CACHE_STATS */
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 15) Close the file. */
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+ }
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 13) Delete the file */
+
+ if ( pass ) {
+
+ if ( HDremove(filename) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "HDremove() failed.\n";
+ }
+ }
+
+ if ( pass ) { PASSED(); } else { H5_FAILED(); }
+
+ if ( ! pass )
+ HDfprintf(stdout, "%s: failure_mssg = \"%s\".\n",
+ FUNC, failure_mssg);
+
+ return !pass;
+
+} /* cache_image_api_error_check_2() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: cache_image_api_error_check_3()
+ *
+ * Purpose: This test is one of a sequence of tests intended
+ * to verify correct management of API errors.
+ *
+ * At present, SWMR and cache image may not be active
+ * at the same time. The purpose of this test is to
+ * verify that attempts to run SWMR and cache image
+ * at the same time will fail.
+ *
+ * The test is set up as follows:
+ *
+ * 1) Create a HDF5 file with a cache image requested..
+ *
+ * 2) Try to start SWMR write -- should fail.
+ *
+ * 3) Discard the file if necessary
+ *
+ * 4) Attempt to create a HDF5 file with SWMR write
+ * access and cache image requested -- should fail.
+ *
+ * 5) Discard the file if necessary
+ *
+ * 6) Create a HDF5 file with a cache image requested.
+ *
+ * 7) Create some datasets in the file.
+ *
+ * 8) Close the file.
+ *
+ * 9) Attempt to open the file with SWMR write access --
+ * should fail.
+ *
+ * 10) Discard the file if necessary.
+ *
+ * Return: void
+ *
+ * Programmer: John Mainzer
+ * 12/29/16
+ *
+ *-------------------------------------------------------------------------
+ */
+
+static unsigned
+cache_image_api_error_check_3(void)
+{
+ const char * fcn_name = "cache_image_api_error_check_3()";
+ char filename[512];
+ hbool_t show_progress = FALSE;
+ hid_t file_id = -1;
+ H5F_t *file_ptr = NULL;
+ H5C_t *cache_ptr = NULL;
+ int cp = 0;
+
+ TESTING("metadata cache image api error check 3");
+
+ pass = TRUE;
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* setup the file name */
+ if ( pass ) {
+
+ if ( h5_fixname(FILENAMES[0], H5P_DEFAULT, filename, sizeof(filename))
+ == NULL ) {
+
+ pass = FALSE;
+ failure_mssg = "h5_fixname() failed.\n";
+ }
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 1) Create a HDF5 file with a cache image requested. */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ TRUE,
+ /* mdci_sbem_expected */ FALSE,
+ /* read_only */ FALSE,
+ /* set_mdci_fapl */ TRUE,
+ /* config_fsm */ TRUE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ H5C_CI__ALL_FLAGS,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 2) Try to start SWMR write -- should fail. */
+
+ if ( pass ) {
+
+ H5E_BEGIN_TRY {
+ if ( H5Fstart_swmr_write(file_id) == SUCCEED ) {
+
+ pass = FALSE;
+ failure_mssg = "metadata cache image block loaded(1).";
+ }
+ } H5E_END_TRY;
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 3) Discard the file if necessary */
+
+ if ( pass ) {
+
+ if ( HDremove(filename) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "HDremove() failed.\n";
+ }
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 4) Attempt to create a HDF5 file with SWMR write
+ * access and cache image requested -- should fail.
+ */
+
+ attempt_swmr_open_hdf5_file(/* create_file */ TRUE,
+ /* set_mdci_fapl */ TRUE,
+ /* hdf_file_name */ filename);
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 5) Discard the file if necessary */
+
+ if ( pass ) {
+
+ /* file probably doesn't exist, so don't
+ * error check the remove call.
+ */
+ HDremove(filename);
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 6) Create a HDF5 file with a cache image requested. */
+
+ if ( pass ) {
+
+ open_hdf5_file(/* create_file */ TRUE,
+ /* mdci_sbem_expected */ FALSE,
+ /* read_only */ FALSE,
+ /* set_mdci_fapl */ TRUE,
+ /* config_fsm */ TRUE,
+ /* hdf_file_name */ filename,
+ /* cache_image_flags */ H5C_CI__ALL_FLAGS,
+ /* file_id_ptr */ &file_id,
+ /* file_ptr_ptr */ &file_ptr,
+ /* cache_ptr_ptr */ &cache_ptr);
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 7) Create some datasets in the file. */
+
+ if ( pass ) {
+
+ create_datasets(file_id, 0, 5);
+ }
+
+#if H5C_COLLECT_CACHE_STATS
+ if ( pass ) {
+
+ if ( cache_ptr->images_loaded != 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "metadata cache image block loaded(1).";
+ }
+ }
+#endif /* H5C_COLLECT_CACHE_STATS */
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 8) Close the file. */
+
+ if ( pass ) {
+
+ if ( H5Fclose(file_id) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "H5Fclose() failed.\n";
+
+ }
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 9) Attempt to open the file with SWMR write access -- should fail. */
+
+ attempt_swmr_open_hdf5_file(/* create_file */ FALSE,
+ /* set_mdci_fapl */ TRUE,
+ /* hdf_file_name */ filename);
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ /* 10) Discard the file if necessary. */
+
+ if ( pass ) {
+
+ if ( HDremove(filename) < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "HDremove() failed.\n";
+ }
+ }
+
+ if ( show_progress )
+ HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass);
+
+
+ if ( pass ) { PASSED(); } else { H5_FAILED(); }
+
+ if ( ! pass )
+ HDfprintf(stdout, "%s: failure_mssg = \"%s\".\n",
+ FUNC, failure_mssg);
+
+ return !pass;
+
+} /* cache_image_api_error_check_3() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: main
+ *
+ * Purpose: Run tests on the cache code contained in H5C.c
+ *
+ * Return: Success:
+ *
+ * Failure:
+ *
+ * Programmer: John Mainzer
+ * 6/24/04
+ *
+ *-------------------------------------------------------------------------
+ */
+int
+main(void)
+{
+ unsigned nerrs = 0;
+ int express_test;
+
+ H5open();
+
+ express_test = GetTestExpress();
+
+ printf("=========================================\n");
+ printf("Cache image tests\n");
+ printf(" express_test = %d\n", express_test);
+ printf("=========================================\n");
+
+ nerrs += check_cache_image_ctl_flow_1();
+ nerrs += check_cache_image_ctl_flow_2();
+ nerrs += check_cache_image_ctl_flow_3();
+ nerrs += check_cache_image_ctl_flow_4();
+ nerrs += check_cache_image_ctl_flow_5();
+ nerrs += check_cache_image_ctl_flow_6();
+
+ nerrs += cache_image_smoke_check_1();
+ nerrs += cache_image_smoke_check_2();
+ nerrs += cache_image_smoke_check_3();
+ nerrs += cache_image_smoke_check_4();
+ nerrs += cache_image_smoke_check_5();
+ nerrs += cache_image_smoke_check_6();
+
+ nerrs += cache_image_api_error_check_1();
+ nerrs += cache_image_api_error_check_2();
+ nerrs += cache_image_api_error_check_3();
+
+ return(nerrs > 0);
+
+} /* main() */
+
+
diff --git a/test/genall5.c b/test/genall5.c
new file mode 100644
index 0000000..1d92e96
--- /dev/null
+++ b/test/genall5.c
@@ -0,0 +1,3893 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the files COPYING and Copyright.html. COPYING can be found at the root *
+ * of the source code distribution tree; Copyright.html can be found at the *
+ * root level of an installed copy of the electronic HDF5 document set and *
+ * is linked from the top-level documents page. It can also be found at *
+ * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/* Programmer: John Mainzer
+ * 9/23/15
+ *
+ * This file contains a heavily edited and functionaly reduce
+ * version of the test code first written by Quincey in a file
+ * of the same name.
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include "hdf5.h"
+#include "cache_common.h"
+#include "genall5.h"
+
+#define DSET_DIMS (1024 * 1024)
+#define DSET_SMALL_DIMS (64 * 1024)
+#define DSET_CHUNK_DIMS 1024
+#define DSET_COMPACT_DIMS 4096
+
+
+/*-------------------------------------------------------------------------
+ * Function: ns_grp_0
+ *
+ * Purpose: Create an empty "new style" group at the specified location
+ * in the specified file.
+ *
+ * If pass is false on entry, do nothing.
+ *
+ * If an error is detected, set pass to FALSE, and set
+ * failure_mssg to point to an appropriate error message.
+ *
+ * Return: void
+ *
+ * Programmer: John Mainzer
+ * 9/14/15
+ *
+ *-------------------------------------------------------------------------
+ */
+
+void
+ns_grp_0(hid_t fid, const char *group_name)
+{
+ hid_t gid = -1;
+ hid_t gcpl = -1;
+ herr_t ret;
+
+ if ( pass ) {
+
+ gcpl = H5Pcreate(H5P_GROUP_CREATE);
+
+ if ( gcpl <= 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "ns_grp_0: H5Pcreate() failed";
+ }
+ assert(gcpl > 0);
+ }
+
+ if ( pass ) {
+
+ ret = H5Pset_link_creation_order(gcpl, H5P_CRT_ORDER_TRACKED);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "ns_grp_0: H5Pset_link_creation_order() failed";
+ }
+ assert(ret >= 0);
+ }
+
+ if ( pass ) {
+
+ gid = H5Gcreate2(fid, group_name, H5P_DEFAULT, gcpl, H5P_DEFAULT);
+
+ if ( gid <= 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "ns_grp_0: H5Gcreate2() failed";
+ }
+ assert(gid > 0);
+ }
+
+ if ( pass ) {
+
+ ret = H5Pclose(gcpl);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "ns_grp_0: H5Pclose(gcpl) failed";
+ }
+ assert(ret >= 0);
+ }
+
+ if ( pass ) {
+
+ ret = H5Gclose(gid);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "ns_grp_0: H5Gclose(gid) failed";
+ }
+ assert(ret >= 0);
+ }
+
+ return;
+
+} /* ns_grp_0 */
+
+
+/*-------------------------------------------------------------------------
+ * Function: vrfy_ns_grp_0
+ *
+ * Purpose: verify an empty "new style" group at the specified location
+ * in the specified file.
+ *
+ * If pass is false on entry, do nothing.
+ *
+ * If an error is detected, set pass to FALSE, and set
+ * failure_mssg to point to an appropriate error message.
+ *
+ * Return: void
+ *
+ * Programmer: John Mainzer
+ * 9/14/15
+ *
+ *-------------------------------------------------------------------------
+ */
+
+void vrfy_ns_grp_0(hid_t fid, const char *group_name)
+{
+ hid_t gid = -1;
+ hid_t gcpl = -1;
+ H5G_info_t grp_info;
+ unsigned crt_order_flags = 0;
+ herr_t ret;
+
+ if ( pass ) {
+
+ gid = H5Gopen2(fid, group_name, H5P_DEFAULT);
+
+ if ( gid <= 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ns_grp_0: H5Gopen2() failed";
+ }
+ HDassert(gid > 0);
+ }
+
+ if ( pass ) {
+
+ gcpl = H5Gget_create_plist(gid);
+
+ if ( gcpl <= 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ns_grp_0: H5Gget_create_plist() failed";
+ }
+ HDassert(gcpl > 0);
+ }
+
+ if ( pass ) {
+
+ ret = H5Pget_link_creation_order(gcpl, &crt_order_flags);
+
+ if ( gcpl <= 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ns_grp_0: H5Pget_link_creation_order() failed";
+ }
+ else if ( H5P_CRT_ORDER_TRACKED != crt_order_flags ) {
+
+ pass = FALSE;
+ failure_mssg =
+ "vrfy_ns_grp_0: H5P_CRT_ORDER_TRACKED != crt_order_flags";
+ }
+ HDassert(ret >= 0);
+ HDassert(H5P_CRT_ORDER_TRACKED == crt_order_flags);
+ }
+
+ if ( pass ) {
+
+ ret = H5Pclose(gcpl);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ns_grp_0: H5Pclose() failed";
+ }
+ HDassert(ret >= 0);
+ }
+
+ if ( pass ) {
+
+ memset(&grp_info, 0, sizeof(grp_info));
+ ret = H5Gget_info(gid, &grp_info);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ns_grp_0: H5Gget_info() failed";
+ }
+ else if ( H5G_STORAGE_TYPE_COMPACT != grp_info.storage_type ) {
+
+ pass = FALSE;
+ failure_mssg =
+ "vrfy_ns_grp_0: H5G_STORAGE_TYPE_COMPACT != grp_info.storage_type";
+ }
+ else if ( 0 != grp_info.nlinks ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ns_grp_0: 0 != grp_info.nlinks";
+ }
+ else if ( 0 != grp_info.max_corder ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ns_grp_0: 0 != grp_info.max_corder";
+ }
+ else if ( FALSE != grp_info.mounted ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ns_grp_0: FALSE != grp_info.mounted";
+ }
+
+ HDassert(ret >= 0);
+ HDassert(H5G_STORAGE_TYPE_COMPACT == grp_info.storage_type);
+ HDassert(0 == grp_info.nlinks);
+ HDassert(0 == grp_info.max_corder);
+ HDassert(false == grp_info.mounted);
+ }
+
+ if ( pass ) {
+
+ ret = H5Gclose(gid);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ns_grp_0: H5Gclose() failed";
+ }
+ HDassert(ret >= 0);
+ }
+
+ return;
+
+} /* vrfy_ns_grp_0() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: ns_grp_c
+ *
+ * Purpose: Create a compact "new style" group, with 'nlinks'
+ * soft/hard/external links in it in the specified file.
+ *
+ * If pass is false on entry, do nothing.
+ *
+ * If an error is detected, set pass to FALSE, and set
+ * failure_mssg to point to an appropriate error message.
+ *
+ * Return: void
+ *
+ * Programmer: John Mainzer
+ * 9/14/15
+ *
+ *-------------------------------------------------------------------------
+ */
+
+void
+ns_grp_c(hid_t fid, const char *group_name, unsigned nlinks)
+{
+ hid_t gid = -1;
+ hid_t gcpl = -1;
+ unsigned max_compact;
+ unsigned u;
+ herr_t ret;
+
+ if ( pass ) {
+
+ gcpl = H5Pcreate(H5P_GROUP_CREATE);
+
+ if ( gcpl <= 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "ns_grp_c: H5Pcreate(H5P_GROUP_CREATE) failed";
+ }
+ HDassert(gcpl > 0);
+ }
+
+ if ( pass ) {
+
+ ret = H5Pset_link_creation_order(gcpl, H5P_CRT_ORDER_TRACKED);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "ns_grp_c: H5Pset_link_creation_order() failed";
+ }
+ HDassert(ret >= 0);
+ }
+
+ if ( pass ) {
+
+ gid = H5Gcreate2(fid, group_name, H5P_DEFAULT, gcpl, H5P_DEFAULT);
+
+ if ( gid <= 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "ns_grp_c: H5Gcreate2() failed";
+ }
+ HDassert(gid > 0);
+ }
+
+ if ( pass ) {
+
+ max_compact = 0;
+ ret = H5Pget_link_phase_change(gcpl, &max_compact, NULL);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "ns_grp_c: H5Pget_link_phase_change() failed";
+ }
+ else if ( nlinks <= 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "ns_grp_c: nlinks <= 0";
+ }
+ else if ( nlinks >= max_compact ) {
+
+ pass = FALSE;
+ failure_mssg = "ns_grp_c: nlinks >= max_compact";
+ }
+
+ HDassert(ret >= 0);
+ HDassert(nlinks > 0);
+ HDassert(nlinks < max_compact);
+ }
+
+ u = 0;
+ while ( ( pass ) && ( u < nlinks ) ) {
+
+ char linkname[16];
+
+ sprintf(linkname, "%u", u);
+
+ if(0 == (u % 3)) {
+
+ ret = H5Lcreate_soft(group_name, gid, linkname, H5P_DEFAULT,
+ H5P_DEFAULT);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "ns_grp_c: H5Lcreate_soft() failed";
+ }
+ HDassert(ret >= 0);
+ } /* end if */
+ else if(1 == (u % 3)) {
+
+ ret = H5Lcreate_hard(fid, "/", gid, linkname, H5P_DEFAULT,
+ H5P_DEFAULT);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "ns_grp_c: H5Lcreate_hard() failed";
+ }
+ HDassert(ret >= 0);
+ } /* end else-if */
+ else {
+
+ HDassert(2 == (u % 3));
+ ret = H5Lcreate_external("external.h5", "/ext", gid, linkname,
+ H5P_DEFAULT, H5P_DEFAULT);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "ns_grp_c: H5Lcreate_external() failed";
+ }
+ HDassert(ret >= 0);
+ } /* end else */
+
+ u++;
+
+ } /* end while() */
+
+ if ( pass ) {
+
+ ret = H5Pclose(gcpl);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "ns_grp_c: H5Pclose(gcpl) failed";
+ }
+ HDassert(ret >= 0);
+ }
+
+ if ( pass ) {
+
+ ret = H5Gclose(gid);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "ns_grp_c: H5Gclose(gid) failed";
+ }
+ HDassert(ret >= 0);
+ }
+
+ return;
+
+} /* ns_grp_c() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: vrfy_ns_grp_c
+ *
+ * Purpose: Verify a compact "new style" group, with 'nlinks'
+ * soft/hard/external links in it in the specified file.
+ *
+ * If pass is false on entry, do nothing.
+ *
+ * If an error is detected, set pass to FALSE, and set
+ * failure_mssg to point to an appropriate error message.
+ *
+ * Return: void
+ *
+ * Programmer: John Mainzer
+ * 9/14/15
+ *
+ *-------------------------------------------------------------------------
+ */
+
+void
+vrfy_ns_grp_c(hid_t fid, const char *group_name, unsigned nlinks)
+{
+ hid_t gid = -1;
+ hid_t gcpl = -1;
+ H5G_info_t grp_info;
+ unsigned crt_order_flags = 0;
+ unsigned u;
+ herr_t ret;
+
+ if ( pass ) {
+
+ gid = H5Gopen2(fid, group_name, H5P_DEFAULT);
+
+ if ( gid <= 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ns_grp_c: H5Gopen2() failed";
+ }
+ HDassert(gid > 0);
+ }
+
+ if ( pass ) {
+
+ gcpl = H5Gget_create_plist(gid);
+
+ if ( gcpl <= 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ns_grp_c: H5Gget_create_plist(gid) failed";
+ }
+ assert(gcpl > 0);
+ }
+
+ if ( pass ) {
+
+ ret = H5Pget_link_creation_order(gcpl, &crt_order_flags);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ns_grp_c: H5Pget_link_creation_order() failed";
+ }
+ else if ( H5P_CRT_ORDER_TRACKED != crt_order_flags ) {
+
+ pass = FALSE;
+ failure_mssg =
+ "vrfy_ns_grp_c: H5P_CRT_ORDER_TRACKED != crt_order_flags";
+ }
+ HDassert(ret >= 0);
+ HDassert(H5P_CRT_ORDER_TRACKED == crt_order_flags);
+ }
+
+ if ( pass ) {
+
+ ret = H5Pclose(gcpl);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ns_grp_c: H5Pclose() failed";
+ }
+ HDassert(ret >= 0);
+ }
+
+ if ( pass ) {
+
+ memset(&grp_info, 0, sizeof(grp_info));
+ ret = H5Gget_info(gid, &grp_info);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ns_grp_c: H5Gget_info() failed";
+ }
+ else if ( H5G_STORAGE_TYPE_COMPACT != grp_info.storage_type ) {
+
+ pass = FALSE;
+ failure_mssg =
+ "vrfy_ns_grp_c: H5G_STORAGE_TYPE_COMPACT != grp_info.storage_type";
+ }
+ else if ( nlinks != grp_info.nlinks ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ns_grp_c: nlinks != grp_info.nlinks";
+ }
+ else if ( nlinks != grp_info.max_corder ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ns_grp_c: nlinks != grp_info.max_corder";
+ }
+ else if ( FALSE != grp_info.mounted ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ns_grp_c: FALSE != grp_info.mounted";
+ }
+
+ HDassert(ret >= 0);
+ HDassert(H5G_STORAGE_TYPE_COMPACT == grp_info.storage_type);
+ HDassert(nlinks == grp_info.nlinks);
+ HDassert(nlinks == grp_info.max_corder);
+ HDassert(false == grp_info.mounted);
+ }
+
+ u = 0;
+ while ( ( pass ) && ( u < nlinks ) ) {
+
+ H5L_info_t lnk_info;
+ char linkname[16];
+ htri_t link_exists;
+
+ sprintf(linkname, "%u", u);
+ link_exists = H5Lexists(gid, linkname, H5P_DEFAULT);
+
+ if ( link_exists < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ns_grp_c: H5Lexists() failed";
+ }
+ HDassert(link_exists >= 0);
+
+ memset(&lnk_info, 0, sizeof(grp_info));
+ ret = H5Lget_info(gid, linkname, &lnk_info, H5P_DEFAULT);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ns_grp_c: H5Lget_info() failed";
+ }
+ else if ( TRUE != lnk_info.corder_valid ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ns_grp_c: TRUE != lnk_info.corder_valid";
+ }
+ else if ( u != lnk_info.corder ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ns_grp_c: u != lnk_info.corder";
+ }
+ else if ( H5T_CSET_ASCII != lnk_info.cset ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ns_grp_c: H5T_CSET_ASCII != lnk_info.cset";
+ }
+ HDassert(ret >= 0);
+ HDassert(true == lnk_info.corder_valid);
+ HDassert(u == lnk_info.corder);
+ HDassert(H5T_CSET_ASCII == lnk_info.cset);
+
+ if ( 0 == (u % 3) ) {
+
+ char *slinkval;
+
+ if ( H5L_TYPE_SOFT != lnk_info.type ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ns_grp_c: H5L_TYPE_SOFT != lnk_info.type";
+ }
+ else if ( (strlen(group_name) + 1) != lnk_info.u.val_size ) {
+
+ pass = FALSE;
+ failure_mssg =
+ "vrfy_ns_grp_c: (strlen(group_name) + 1) != lnk_info.u.val_size";
+ }
+ HDassert(H5L_TYPE_SOFT == lnk_info.type);
+ HDassert((strlen(group_name) + 1) == lnk_info.u.val_size);
+
+ slinkval = (char *)malloc(lnk_info.u.val_size);
+
+ if ( ! slinkval ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ns_grp_c: malloc of slinkval failed";
+ }
+ HDassert(slinkval);
+
+ ret = H5Lget_val(gid, linkname, slinkval, lnk_info.u.val_size,
+ H5P_DEFAULT);
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ns_grp_c: H5Lget_val() failed";
+ }
+ else if ( 0 != strcmp(slinkval, group_name) ) {
+
+ pass = FALSE;
+ failure_mssg =
+ "vrfy_ns_grp_c: 0 != strcmp(slinkval, group_name)";
+ }
+ HDassert(ret >= 0);
+ HDassert(0 == strcmp(slinkval, group_name));
+
+ free(slinkval);
+ } /* end if */
+ else if(1 == (u % 3)) {
+
+ H5O_info_t root_oinfo;
+
+ if ( H5L_TYPE_HARD != lnk_info.type ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ns_grp_c: H5L_TYPE_HARD != lnk_info.type";
+ }
+ HDassert(H5L_TYPE_HARD == lnk_info.type);
+
+ memset(&root_oinfo, 0, sizeof(root_oinfo));
+ ret = H5Oget_info(fid, &root_oinfo);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ns_grp_c: H5Oget_info() failed.";
+ }
+ else if ( root_oinfo.addr != lnk_info.u.address ) {
+
+ pass = FALSE;
+ failure_mssg =
+ "vrfy_ns_grp_c: root_oinfo.addr != lnk_info.u.address";
+ }
+ HDassert(ret >= 0);
+ HDassert(root_oinfo.addr == lnk_info.u.address);
+ } /* end else-if */
+ else {
+ void *elinkval;
+ const char *file = NULL;
+ const char *path = NULL;
+
+ HDassert(2 == (u % 3));
+
+ if ( H5L_TYPE_EXTERNAL != lnk_info.type ) {
+
+ pass = FALSE;
+ failure_mssg =
+ "vrfy_ns_grp_c: H5L_TYPE_EXTERNAL != lnk_info.type";
+ }
+ HDassert(H5L_TYPE_EXTERNAL == lnk_info.type);
+
+ elinkval = malloc(lnk_info.u.val_size);
+
+ if ( ! elinkval ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ns_grp_c: malloc of elinkval failed.";
+ }
+ HDassert(elinkval);
+
+ ret = H5Lget_val(gid, linkname, elinkval, lnk_info.u.val_size,
+ H5P_DEFAULT);
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ns_grp_c: H5Lget_val() failed.";
+ }
+ HDassert(ret >= 0);
+
+ ret = H5Lunpack_elink_val(elinkval, lnk_info.u.val_size,
+ NULL, &file, &path);
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ns_grp_c: H5Lunpack_elink_val() failed.";
+ }
+ else if ( 0 != strcmp(file, "external.h5") ) {
+
+ pass = FALSE;
+ failure_mssg =
+ "vrfy_ns_grp_c: 0 != strcmp(file, \"external.h5\")";
+ }
+ else if ( 0 != strcmp(path, "/ext") ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ns_grp_c: 0 != strcmp(path, \"/ext\")";
+ }
+ HDassert(ret >= 0);
+ HDassert(0 == strcmp(file, "external.h5"));
+ HDassert(0 == strcmp(path, "/ext"));
+
+ free(elinkval);
+ } /* end else */
+
+ u++;
+
+ } /* end while */
+
+ if ( pass ) {
+
+ ret = H5Gclose(gid);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ns_grp_c: H5Gclose() failed.";
+ }
+ assert(ret >= 0);
+ }
+
+ return;
+
+} /* vrfy_ns_grp_c() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: ns_grp_d
+ *
+ * Purpose: Create a dense "new style" group, with 'nlinks'
+ * (soft/hard/external) links in it in the specified file.
+ *
+ * If pass is false on entry, do nothing.
+ *
+ * If an error is detected, set pass to FALSE, and set
+ * failure_mssg to point to an appropriate error message.
+ *
+ * Return: void
+ *
+ * Programmer: John Mainzer
+ * 9/14/15
+ *
+ *-------------------------------------------------------------------------
+ */
+
+void
+ns_grp_d(hid_t fid, const char *group_name, unsigned nlinks)
+{
+ hid_t gid = -1;
+ hid_t gcpl = -1;
+ unsigned max_compact;
+ unsigned u;
+ herr_t ret;
+
+ if ( pass ) {
+
+ gcpl = H5Pcreate(H5P_GROUP_CREATE);
+
+ if ( gcpl <= 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "ns_grp_d: H5Pcreate() failed.";
+ }
+ HDassert(gcpl > 0);
+ }
+
+ if ( pass ) {
+
+ ret = H5Pset_link_creation_order(gcpl, H5P_CRT_ORDER_TRACKED);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "ns_grp_d: H5Pset_link_creation_order() failed.";
+ }
+ HDassert(ret >= 0);
+ }
+
+ if ( pass ) {
+
+ gid = H5Gcreate2(fid, group_name, H5P_DEFAULT, gcpl, H5P_DEFAULT);
+
+ if ( gid <= 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "ns_grp_d: H5Gcreate2() failed.";
+ }
+ HDassert(gid > 0);
+ }
+
+ if ( pass ) {
+
+ max_compact = 0;
+ ret = H5Pget_link_phase_change(gcpl, &max_compact, NULL);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "ns_grp_d: H5Pget_link_phase_change() failed.";
+ }
+ else if ( nlinks <= max_compact ) {
+
+ pass = FALSE;
+ failure_mssg = "ns_grp_d: nlinks <= max_compact";
+ }
+ HDassert(ret >= 0);
+ HDassert(nlinks > max_compact);
+ }
+
+ u = 0;
+ while ( ( pass ) && ( u < nlinks ) ) {
+
+ char linkname[16];
+
+ sprintf(linkname, "%u", u);
+
+ if(0 == (u % 3)) {
+
+ ret = H5Lcreate_soft(group_name, gid, linkname,
+ H5P_DEFAULT, H5P_DEFAULT);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "ns_grp_d: H5Lcreate_soft() failed.";
+ }
+ HDassert(ret >= 0);
+ } /* end if */
+ else if(1 == (u % 3)) {
+
+ ret = H5Lcreate_hard(fid, "/", gid, linkname,
+ H5P_DEFAULT, H5P_DEFAULT);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "ns_grp_d: H5Lcreate_hard() failed.";
+ }
+ HDassert(ret >= 0);
+ } /* end else-if */
+ else {
+
+ HDassert(2 == (u % 3));
+
+ ret = H5Lcreate_external("external.h5", "/ext", gid, linkname,
+ H5P_DEFAULT, H5P_DEFAULT);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "ns_grp_d: H5Lcreate_external() failed.";
+ }
+ HDassert(ret >= 0);
+ } /* end else */
+
+ u++;
+
+ } /* end while */
+
+ if ( pass ) {
+
+ ret = H5Pclose(gcpl);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "ns_grp_d: H5Pclose() failed.";
+ }
+ HDassert(ret >= 0);
+ }
+
+ if ( pass ) {
+
+ ret = H5Gclose(gid);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "ns_grp_d: H5Gclose() failed.";
+ }
+ HDassert(ret >= 0);
+ }
+
+ return;
+
+} /* ns_grp_d() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: vrfy_ns_grp_d
+ *
+ * Purpose: Verify a dense "new style" group, with 'nlinks'
+ * soft/hard/external links in it in the specified file.
+ *
+ * If pass is false on entry, do nothing.
+ *
+ * If an error is detected, set pass to FALSE, and set
+ * failure_mssg to point to an appropriate error message.
+ *
+ * Return: void
+ *
+ * Programmer: John Mainzer
+ * 9/14/15
+ *
+ *-------------------------------------------------------------------------
+ */
+
+
+void
+vrfy_ns_grp_d(hid_t fid, const char *group_name, unsigned nlinks)
+{
+ hid_t gid = -1;
+ hid_t gcpl = -1;
+ H5G_info_t grp_info;
+ unsigned crt_order_flags = 0;
+ unsigned u;
+ herr_t ret;
+
+ if ( pass ) {
+
+ gid = H5Gopen2(fid, group_name, H5P_DEFAULT);
+
+ if ( gid <= 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ns_grp_d: H5Gopen2() failed.";
+ }
+ HDassert(gid > 0);
+ }
+
+ if ( pass ) {
+
+ gcpl = H5Gget_create_plist(gid);
+
+ if ( gcpl <= 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ns_grp_d: H5Gget_create_plist() failed.";
+ }
+ assert(gcpl > 0);
+ }
+
+ if ( pass ) {
+
+ ret = H5Pget_link_creation_order(gcpl, &crt_order_flags);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg =
+ "vrfy_ns_grp_d: H5Pget_link_creation_order() failed.";
+ }
+ else if ( H5P_CRT_ORDER_TRACKED != crt_order_flags ) {
+
+ pass = FALSE;
+ failure_mssg =
+ "vrfy_ns_grp_d: H5P_CRT_ORDER_TRACKED != crt_order_flags";
+ }
+ HDassert(ret >= 0);
+ HDassert(H5P_CRT_ORDER_TRACKED == crt_order_flags);
+ }
+
+ if ( pass ) {
+
+ ret = H5Pclose(gcpl);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ns_grp_d: H5Pclose() failed.";
+ }
+ HDassert(ret >= 0);
+ }
+
+ if ( pass ) {
+
+ memset(&grp_info, 0, sizeof(grp_info));
+ ret = H5Gget_info(gid, &grp_info);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ns_grp_d: H5Gget_info() failed.";
+ }
+ else if ( H5G_STORAGE_TYPE_DENSE != grp_info.storage_type ) {
+
+ pass = FALSE;
+ failure_mssg =
+ "vrfy_ns_grp_d: H5G_STORAGE_TYPE_DENSE != grp_info.storage_type";
+ }
+ else if ( nlinks != grp_info.nlinks ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ns_grp_d: nlinks != grp_info.nlinks";
+ }
+ else if ( nlinks != grp_info.max_corder ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ns_grp_d: nlinks != grp_info.max_corder";
+ }
+ else if ( FALSE != grp_info.mounted ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ns_grp_d: FALSE != grp_info.mounted";
+ }
+ HDassert(ret >= 0);
+ HDassert(H5G_STORAGE_TYPE_DENSE == grp_info.storage_type);
+ HDassert(nlinks == grp_info.nlinks);
+ HDassert(nlinks == grp_info.max_corder);
+ HDassert(false == grp_info.mounted);
+ }
+
+ u = 0;
+ while ( ( pass ) && ( u < nlinks ) ) {
+
+ H5L_info_t lnk_info;
+ char linkname[16];
+ htri_t link_exists;
+
+ sprintf(linkname, "%u", u);
+ link_exists = H5Lexists(gid, linkname, H5P_DEFAULT);
+
+ if ( link_exists < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ns_grp_d: H5Lexists() failed.";
+ }
+ HDassert(link_exists >= 0);
+
+ memset(&lnk_info, 0, sizeof(grp_info));
+ ret = H5Lget_info(gid, linkname, &lnk_info, H5P_DEFAULT);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ns_grp_d: H5Lget_info() failed.";
+ }
+ else if ( TRUE != lnk_info.corder_valid ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ns_grp_d: TRUE != lnk_info.corder_valid";
+ }
+ else if ( u != lnk_info.corder ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ns_grp_d: u != lnk_info.corder";
+ }
+ else if ( H5T_CSET_ASCII != lnk_info.cset ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ns_grp_d: H5T_CSET_ASCII != lnk_info.cset";
+ }
+ HDassert(ret >= 0);
+ HDassert(true == lnk_info.corder_valid);
+ HDassert(u == lnk_info.corder);
+ HDassert(H5T_CSET_ASCII == lnk_info.cset);
+
+ if(0 == (u % 3)) {
+ char *slinkval;
+
+ if ( H5L_TYPE_SOFT != lnk_info.type ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ns_grp_d: H5L_TYPE_SOFT != lnk_info.type";
+ }
+ else if ( (strlen(group_name) + 1) != lnk_info.u.val_size ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ns_grp_d: H5L_TYPE_SOFT != lnk_info.type";
+ }
+ HDassert(H5L_TYPE_SOFT == lnk_info.type);
+ HDassert((strlen(group_name) + 1) == lnk_info.u.val_size);
+
+ slinkval = (char *)malloc(lnk_info.u.val_size);
+
+ if ( ! slinkval ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ns_grp_d: malloc of slinkval failed";
+ }
+ HDassert(slinkval);
+
+ ret = H5Lget_val(gid, linkname, slinkval, lnk_info.u.val_size,
+ H5P_DEFAULT);
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ns_grp_d: H5Lget_val() failed";
+ }
+ else if ( 0 != strcmp(slinkval, group_name) ) {
+
+ pass = FALSE;
+ failure_mssg =
+ "vrfy_ns_grp_d: 0 != strcmp(slinkval, group_name)";
+ }
+ HDassert(ret >= 0);
+ HDassert(0 == strcmp(slinkval, group_name));
+
+ free(slinkval);
+ } /* end if */
+ else if(1 == (u % 3)) {
+ H5O_info_t root_oinfo;
+
+ if ( H5L_TYPE_HARD != lnk_info.type ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ns_grp_d: H5L_TYPE_HARD != lnk_info.type";
+ }
+ HDassert(H5L_TYPE_HARD == lnk_info.type);
+
+ memset(&root_oinfo, 0, sizeof(root_oinfo));
+ ret = H5Oget_info(fid, &root_oinfo);
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ns_grp_d: H5Oget_info() failed.";
+ }
+ else if ( root_oinfo.addr != lnk_info.u.address ) {
+
+ pass = FALSE;
+ failure_mssg =
+ "vrfy_ns_grp_d: root_oinfo.addr != lnk_info.u.address";
+ }
+ HDassert(ret >= 0);
+ HDassert(root_oinfo.addr == lnk_info.u.address);
+ } /* end else-if */
+ else {
+ void *elinkval;
+ const char *file = NULL;
+ const char *path = NULL;
+
+ HDassert(2 == (u % 3));
+
+ if ( H5L_TYPE_EXTERNAL != lnk_info.type ) {
+
+ pass = FALSE;
+ failure_mssg =
+ "vrfy_ns_grp_d: H5L_TYPE_EXTERNAL != lnk_info.type";
+ }
+ HDassert(H5L_TYPE_EXTERNAL == lnk_info.type);
+
+ elinkval = malloc(lnk_info.u.val_size);
+
+ if ( ! elinkval ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ns_grp_d: malloc of elinkval failed.";
+ }
+ HDassert(elinkval);
+
+ ret = H5Lget_val(gid, linkname, elinkval, lnk_info.u.val_size,
+ H5P_DEFAULT);
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ns_grp_d: H5Lget_val failed.";
+ }
+ HDassert(ret >= 0);
+
+ ret = H5Lunpack_elink_val(elinkval, lnk_info.u.val_size, NULL,
+ &file, &path);
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ns_grp_d: H5Lunpack_elink_val failed.";
+ }
+ else if ( 0 != strcmp(file, "external.h5") ) {
+
+ pass = FALSE;
+ failure_mssg =
+ "vrfy_ns_grp_d: 0 != strcmp(file, \"external.h5\").";
+ }
+ else if ( 0 != strcmp(path, "/ext") ) {
+
+ pass = FALSE;
+ failure_mssg =
+ "vrfy_ns_grp_d: 0 != strcmp(path, \"/ext\")";
+ }
+ HDassert(ret >= 0);
+ HDassert(0 == strcmp(file, "external.h5"));
+ HDassert(0 == strcmp(path, "/ext"));
+
+ free(elinkval);
+
+ } /* end else */
+
+ u++;
+
+ } /* end while() */
+
+ if ( pass ) {
+
+ ret = H5Gclose(gid);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ns_grp_d: H5Gclose() failed.";
+ }
+ HDassert(ret >= 0);
+ }
+
+ return;
+
+} /* vrfy_ns_grp_d() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: os_grp_0
+ *
+ * Purpose: Create an empty "old style" group.
+ *
+ * If pass is false on entry, do nothing.
+ *
+ * If an error is detected, set pass to FALSE, and set
+ * failure_mssg to point to an appropriate error message.
+ *
+ * Return: void
+ *
+ * Programmer: John Mainzer
+ * 9/14/15
+ *
+ *-------------------------------------------------------------------------
+ */
+
+void
+os_grp_0(hid_t fid, const char *group_name)
+{
+ hid_t gid = -1;
+ herr_t ret;
+
+ if ( pass ) { /* turn file format latest off */
+
+ ret = H5Fset_latest_format(fid, FALSE);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "os_grp_0: H5Fset_latest_format() failed(1).";
+ }
+ HDassert(ret >= 0);
+ }
+
+ if ( pass ) {
+
+ gid = H5Gcreate2(fid, group_name, H5P_DEFAULT, H5P_DEFAULT,
+ H5P_DEFAULT);
+ if ( gid <= 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "os_grp_0: H5Gcreate2() failed.";
+ }
+ HDassert(gid > 0);
+ }
+
+ if ( pass ) {
+
+ ret = H5Gclose(gid);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "os_grp_0: H5Gclose() failed.";
+ }
+ HDassert(ret >= 0);
+ }
+
+ if ( pass ) { /* turn file format latest on */
+
+ ret = H5Fset_latest_format(fid, TRUE);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "os_grp_0: H5Fset_latest_format() failed(2).";
+ }
+ HDassert(ret >= 0);
+ }
+
+ return;
+
+} /* os_grp_0() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: vrfy_os_grp_0
+ *
+ * Purpose: Validate an empty "old style" group.
+ *
+ * If pass is false on entry, do nothing.
+ *
+ * If an error is detected, set pass to FALSE, and set
+ * failure_mssg to point to an appropriate error message.
+ *
+ * Return: void
+ *
+ * Programmer: John Mainzer
+ * 9/14/15
+ *
+ *-------------------------------------------------------------------------
+ */
+
+void
+vrfy_os_grp_0(hid_t fid, const char *group_name)
+{
+ hid_t gid = -1;
+ hid_t gcpl = -1;
+ H5G_info_t grp_info;
+ unsigned crt_order_flags = 0;
+ herr_t ret;
+
+ if ( pass ) {
+
+ gid = H5Gopen2(fid, group_name, H5P_DEFAULT);
+
+ if ( gid <= 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_os_grp_0: H5Gopen2() failed.";
+ }
+ HDassert(gid > 0);
+ }
+
+ if ( pass ) {
+
+ gcpl = H5Gget_create_plist(gid);
+
+ if ( gcpl <= 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_os_grp_0: H5Gget_create_plist() failed.";
+ }
+ HDassert(gcpl > 0);
+ }
+
+ if ( pass ) {
+
+ ret = H5Pget_link_creation_order(gcpl, &crt_order_flags);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_os_grp_0: H5Pget_link_creation_order() failed";
+ }
+ else if ( 0 != crt_order_flags ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_os_grp_0: 0 != crt_order_flags";
+ }
+ HDassert(ret >= 0);
+ HDassert(0 == crt_order_flags);
+ }
+
+ if ( pass ) {
+
+ ret = H5Pclose(gcpl);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_os_grp_0: H5Pclose() failed.";
+ }
+ HDassert(ret >= 0);
+ }
+
+ if ( pass ) {
+
+ memset(&grp_info, 0, sizeof(grp_info));
+ ret = H5Gget_info(gid, &grp_info);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_os_grp_0: H5Gget_info() failed.";
+ }
+ else if ( H5G_STORAGE_TYPE_SYMBOL_TABLE != grp_info.storage_type ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_os_grp_0: H5G_STORAGE_TYPE_SYMBOL_TABLE != grp_info.storage_type";
+ }
+ else if ( 0 != grp_info.nlinks ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_os_grp_0: 0 != grp_info.nlinks";
+ }
+ else if ( 0 != grp_info.max_corder ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_os_grp_0: 0 != grp_info.max_corder";
+ }
+ else if ( FALSE != grp_info.mounted ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_os_grp_0: FALSE != grp_info.mounted";
+ }
+ HDassert(ret >= 0);
+ HDassert(H5G_STORAGE_TYPE_SYMBOL_TABLE == grp_info.storage_type);
+ HDassert(0 == grp_info.nlinks);
+ HDassert(0 == grp_info.max_corder);
+ HDassert(false == grp_info.mounted);
+ }
+
+ if ( pass ) {
+
+ ret = H5Gclose(gid);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_os_grp_0: H5Gclose() failed.";
+ }
+ HDassert(ret >= 0);
+ }
+
+ return;
+
+} /* vrfy_os_grp_0() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: os_grp_n
+ *
+ * Purpose: Create an "old style" group, with 'nlinks' soft/hard
+ * links in it.
+ *
+ * If pass is false on entry, do nothing.
+ *
+ * If an error is detected, set pass to FALSE, and set
+ * failure_mssg to point to an appropriate error message.
+ *
+ * Return: void
+ *
+ * Programmer: John Mainzer
+ * 9/14/15
+ *
+ *-------------------------------------------------------------------------
+ */
+
+void
+os_grp_n(hid_t fid, const char *group_name, int proc_num, unsigned nlinks)
+{
+ hid_t gid = -1;
+ unsigned u;
+ herr_t ret;
+
+ if ( pass ) { /* turn file format latest off */
+
+ ret = H5Fset_latest_format(fid, FALSE);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "os_grp_n: H5Fset_latest_format() failed(1).";
+ }
+ HDassert(ret >= 0);
+ }
+
+ if ( pass ) {
+
+ gid = H5Gcreate2(fid, group_name, H5P_DEFAULT, H5P_DEFAULT,
+ H5P_DEFAULT);
+ if ( gid <= 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "os_grp_n: H5Gcreate2() failed.";
+ }
+ HDassert(gid > 0);
+ }
+
+ HDassert(nlinks > 0);
+
+ u = 0;
+ while ( ( pass ) && ( u < nlinks ) ) {
+
+ char linkname[32];
+
+ sprintf(linkname, "ln%d_%u", proc_num, u);
+
+ if(0 == (u % 2)) {
+
+ ret = H5Lcreate_soft(group_name, gid, linkname, H5P_DEFAULT,
+ H5P_DEFAULT);
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "os_grp_n: H5Lcreate_soft() failed.";
+ }
+ HDassert(ret >= 0);
+ } /* end if */
+ else {
+
+ HDassert(1 == (u % 2));
+
+ ret = H5Lcreate_hard(fid, "/", gid, linkname, H5P_DEFAULT,
+ H5P_DEFAULT);
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "os_grp_n: H5Lcreate_hard() failed.";
+ }
+ HDassert(ret >= 0);
+ } /* end else */
+
+ u++;
+
+ } /* end while */
+
+ if ( pass ) {
+
+ ret = H5Gclose(gid);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "os_grp_n: H5Gclose() failed.";
+ }
+ assert(ret >= 0);
+ }
+
+ if ( pass ) { /* turn file format latest on */
+
+ ret = H5Fset_latest_format(fid, TRUE);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "os_grp_n: H5Fset_latest_format() failed(2).";
+ }
+ HDassert(ret >= 0);
+ }
+
+ return;
+} /* os_grp_n() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: vrfy_os_grp_n
+ *
+ * Purpose: Validate an "old style" group with 'nlinks' soft/hard
+ * links in it.
+ *
+ * If pass is false on entry, do nothing.
+ *
+ * If an error is detected, set pass to FALSE, and set
+ * failure_mssg to point to an appropriate error message.
+ *
+ * Return: void
+ *
+ * Programmer: John Mainzer
+ * 9/14/15
+ *
+ *-------------------------------------------------------------------------
+ */
+void
+vrfy_os_grp_n(hid_t fid, const char *group_name, int proc_num, unsigned nlinks)
+{
+ hid_t gid = -1;
+ hid_t gcpl = -1;
+ H5G_info_t grp_info;
+ unsigned crt_order_flags = 0;
+ unsigned u;
+ herr_t ret;
+
+ if ( pass ) {
+
+ gid = H5Gopen2(fid, group_name, H5P_DEFAULT);
+
+ if ( gid <= 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_os_grp_n: H5Gopen2() failed";
+ }
+ HDassert(gid > 0);
+ }
+
+ if ( pass ) {
+
+ gcpl = H5Gget_create_plist(gid);
+
+ if ( gcpl <= 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_os_grp_n: H5Gget_create_plist() failed";
+ }
+ HDassert(gcpl > 0);
+ }
+
+ if ( pass ) {
+
+ ret = H5Pget_link_creation_order(gcpl, &crt_order_flags);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_os_grp_n: H5Pget_link_creation_order";
+ }
+ else if ( 0 != crt_order_flags ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_os_grp_n: 0 != crt_order_flags";
+ }
+ HDassert(ret >= 0);
+ HDassert(0 == crt_order_flags);
+ }
+
+ if ( pass ) {
+
+ ret = H5Pclose(gcpl);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_os_grp_n: H5Pclose() failed";
+ }
+ HDassert(ret >= 0);
+ }
+
+ if ( pass ) {
+
+ memset(&grp_info, 0, sizeof(grp_info));
+
+ ret = H5Gget_info(gid, &grp_info);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_os_grp_n: H5Gget_info() failed";
+ }
+ else if ( H5G_STORAGE_TYPE_SYMBOL_TABLE != grp_info.storage_type ) {
+
+ pass = FALSE;
+ failure_mssg =
+ "vrfy_os_grp_n: H5G_STORAGE_TYPE_SYMBOL_TABLE != grp_info.storage_type";
+ }
+ else if ( nlinks != grp_info.nlinks ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_os_grp_n: nlinks != grp_info.nlinks";
+ }
+ else if ( 0 != grp_info.max_corder ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_os_grp_n: 0 != grp_info.max_corder";
+ }
+ else if ( FALSE != grp_info.mounted ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_os_grp_n: FALSE != grp_info.mounted";
+ }
+ HDassert(ret >= 0);
+ HDassert(H5G_STORAGE_TYPE_SYMBOL_TABLE == grp_info.storage_type);
+ HDassert(nlinks == grp_info.nlinks);
+ HDassert(0 == grp_info.max_corder);
+ HDassert(false == grp_info.mounted);
+ }
+
+ u = 0;
+ while ( ( pass ) && ( u < nlinks ) ) {
+
+ H5L_info_t lnk_info;
+ char linkname[32];
+ htri_t link_exists;
+
+ sprintf(linkname, "ln%d_%u", proc_num, u);
+ link_exists = H5Lexists(gid, linkname, H5P_DEFAULT);
+
+ if ( link_exists < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_os_grp_n: H5Lexists() failed";
+ }
+ HDassert(link_exists >= 0);
+
+ memset(&lnk_info, 0, sizeof(grp_info));
+ ret = H5Lget_info(gid, linkname, &lnk_info, H5P_DEFAULT);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_os_grp_n: H5Lget_info() failed";
+ }
+ else if ( FALSE != lnk_info.corder_valid ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_os_grp_n: FALSE != lnk_info.corder_valid";
+ }
+ else if ( H5T_CSET_ASCII != lnk_info.cset ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_os_grp_n: H5T_CSET_ASCII != lnk_info.cset";
+ }
+ HDassert(ret >= 0);
+ HDassert(false == lnk_info.corder_valid);
+ HDassert(H5T_CSET_ASCII == lnk_info.cset);
+
+ if(0 == (u % 2)) {
+ char *slinkval;
+
+ if ( H5L_TYPE_SOFT != lnk_info.type ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_os_grp_n: H5L_TYPE_SOFT != lnk_info.type";
+ }
+ else if ( (strlen(group_name) + 1) != lnk_info.u.val_size ) {
+
+ pass = FALSE;
+ failure_mssg =
+ "vrfy_os_grp_n: (strlen(group_name) + 1) != lnk_info.u.val_size";
+ }
+ HDassert(H5L_TYPE_SOFT == lnk_info.type);
+ HDassert((strlen(group_name) + 1) == lnk_info.u.val_size);
+
+ slinkval = (char *)malloc(lnk_info.u.val_size);
+
+ if ( ! slinkval ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_os_grp_n: malloc of slinkval failed";
+ }
+ HDassert(slinkval);
+
+ ret = H5Lget_val(gid, linkname, slinkval, lnk_info.u.val_size,
+ H5P_DEFAULT);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_os_grp_n: H5Lget_val() failed";
+ }
+ else if ( 0 != strcmp(slinkval, group_name) ) {
+
+ pass = FALSE;
+ failure_mssg =
+ "vrfy_os_grp_n: 0 != strcmp(slinkval, group_name)";
+ }
+ HDassert(ret >= 0);
+ HDassert(0 == strcmp(slinkval, group_name));
+
+ free(slinkval);
+ } /* end if */
+ else {
+ H5O_info_t root_oinfo;
+
+ HDassert(1 == (u % 2));
+
+ if ( H5L_TYPE_HARD != lnk_info.type ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_os_grp_n: H5L_TYPE_HARD != lnk_info.type";
+ }
+ HDassert(H5L_TYPE_HARD == lnk_info.type);
+
+ memset(&root_oinfo, 0, sizeof(root_oinfo));
+ ret = H5Oget_info(fid, &root_oinfo);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_os_grp_n: H5Oget_info() failed.";
+ }
+ else if ( root_oinfo.addr != lnk_info.u.address ) {
+
+ pass = FALSE;
+ failure_mssg =
+ "vrfy_os_grp_n: root_oinfo.addr != lnk_info.u.address";
+ }
+ HDassert(ret >= 0);
+ HDassert(root_oinfo.addr == lnk_info.u.address);
+ } /* end else */
+
+ u++;
+
+ } /* end while */
+
+ if ( pass ) {
+
+ ret = H5Gclose(gid);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_os_grp_n: H5Gclose() failed.";
+ }
+ HDassert(ret >= 0);
+ }
+
+ return;
+
+} /* vrfy_os_grp_n() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: ds_ctg_i
+ *
+ * Purpose: Create a contiguous dataset w/int datatype. Write data
+ * to the data set or not as indicated by the write_data
+ * parameter.
+ *
+ * If pass is false on entry, do nothing.
+ *
+ * If an error is detected, set pass to FALSE, and set
+ * failure_mssg to point to an appropriate error message.
+ *
+ * Return: void
+ *
+ * Programmer: John Mainzer
+ * 9/14/15
+ *
+ *-------------------------------------------------------------------------
+ */
+void
+ds_ctg_i(hid_t fid, const char *dset_name, hbool_t write_data)
+{
+ int *wdata = NULL;
+ unsigned u;
+ hid_t dsid = -1;
+ hid_t sid = -1;
+ hsize_t dims[1] = {DSET_DIMS};
+ herr_t ret;
+
+ if ( pass ) {
+
+ sid = H5Screate_simple(1, dims, NULL);
+
+ if ( sid <= 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "ds_ctg_i: H5Screate_simple() failed";
+ }
+ HDassert(sid > 0);
+ }
+
+ if ( pass ) {
+
+ dsid = H5Dcreate2(fid, dset_name, H5T_NATIVE_INT, sid, H5P_DEFAULT,
+ H5P_DEFAULT, H5P_DEFAULT);
+
+ if ( dsid <= 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "ds_ctg_i: H5Dcreate2() failed";
+ }
+ HDassert(dsid > 0);
+ }
+
+ if ( pass ) {
+
+ ret = H5Sclose(sid);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "ds_ctg_i: H5Sclose() failed";
+ }
+ HDassert(ret >= 0);
+ }
+
+ if ( ( pass ) && ( write_data ) ) {
+
+ wdata = (int *)malloc(sizeof(int) * DSET_DIMS);
+
+ if ( ! wdata ) {
+
+ pass = FALSE;
+ failure_mssg = "ds_ctg_i: malloc of wdata failed.";
+ }
+ HDassert(wdata);
+ }
+
+ if ( ( pass ) && ( write_data ) ) {
+
+ for(u = 0; u < DSET_DIMS; u++)
+
+ wdata[u] = (int)u;
+
+ ret = H5Dwrite(dsid, H5T_NATIVE_INT, H5S_ALL, H5S_ALL,
+ H5P_DEFAULT, wdata);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "ds_ctg_i: H5Dwrite() failed.";
+ }
+ HDassert(ret >= 0);
+
+ free(wdata);
+ }
+
+ if ( pass ) {
+
+ ret = H5Dclose(dsid);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "ds_ctg_i: H5Dclose() failed";
+ }
+ HDassert(ret >= 0);
+ }
+
+ return;
+
+} /* ds_ctg_i */
+
+
+/*-------------------------------------------------------------------------
+ * Function: vrfy_ds_ctg_i
+ *
+ * Purpose: Validate a contiguous datasets w/int datatypes. Validate
+ * data if indicated via the write_data parameter.
+ *
+ * If pass is false on entry, do nothing.
+ *
+ * If an error is detected, set pass to FALSE, and set
+ * failure_mssg to point to an appropriate error message.
+ *
+ * Return: void
+ *
+ * Programmer: John Mainzer
+ * 9/14/15
+ *
+ *-------------------------------------------------------------------------
+ */
+void
+vrfy_ds_ctg_i(hid_t fid, const char *dset_name, hbool_t write_data)
+{
+ int *rdata = NULL;
+ unsigned u;
+ hid_t dsid = -1;
+ hid_t sid = -1;
+ hid_t tid = -1;
+ hid_t dcpl = -1;
+ H5D_space_status_t allocation;
+ H5D_layout_t layout;
+ int ndims;
+ hsize_t dims[1], max_dims[1];
+ htri_t type_equal;
+ herr_t ret;
+
+ if ( pass ) {
+
+ dsid = H5Dopen2(fid, dset_name, H5P_DEFAULT);
+
+ if ( dsid <= 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_ctg_i: H5Dopen2() failed.";
+ }
+ HDassert(dsid > 0);
+ }
+
+ if ( pass ) {
+
+ sid = H5Dget_space(dsid);
+
+ if ( sid <= 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_ctg_i: H5Dget_space() failed.";
+ }
+ HDassert(sid > 0);
+ }
+
+ if ( pass ) {
+
+ ndims = H5Sget_simple_extent_ndims(sid);
+
+ if ( 1 != ndims ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_ctg_i: 1 != ndims";
+ }
+ HDassert(1 == ndims);
+ }
+
+ if ( pass ) {
+
+ ret = H5Sget_simple_extent_dims(sid, dims, max_dims);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_ctg_i: H5Sget_simple_extent_dims() failed";
+ }
+ else if ( DSET_DIMS != dims[0] ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_ctg_i: DSET_DIMS != dims[0]";
+ }
+ else if ( DSET_DIMS != max_dims[0] ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_ctg_i: DSET_DIMS != max_dims[0]";
+ }
+ HDassert(ret >= 0);
+ HDassert(DSET_DIMS == dims[0]);
+ HDassert(DSET_DIMS == max_dims[0]);
+ }
+
+ if ( pass ) {
+
+ ret = H5Sclose(sid);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_ctg_i: H5Sclose() failed.";
+ }
+ HDassert(ret >= 0);
+ }
+
+ if ( pass ) {
+
+ tid = H5Dget_type(dsid);
+
+ if ( tid <= 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_ctg_i: H5Dget_type() failed.";
+ }
+ HDassert(tid > 0);
+ }
+
+ if ( pass ) {
+
+ type_equal = H5Tequal(tid, H5T_NATIVE_INT);
+
+ if ( 1 != type_equal ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_ctg_i: type not H5T_NATIVE_INT";
+ }
+ HDassert(1 == type_equal);
+ }
+
+ if ( pass ) {
+
+ ret = H5Tclose(tid);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_ctg_i: H5Tclose() failed.";
+ }
+ assert(ret >= 0);
+ }
+
+ if ( pass ) {
+
+ ret = H5Dget_space_status(dsid, &allocation);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_ctg_i: H5Dget_space_status() failed.";
+ }
+ else if ( write_data && ( allocation != H5D_SPACE_STATUS_ALLOCATED ) ) {
+
+ pass = FALSE;
+ failure_mssg =
+ "vrfy_ds_ctg_i: write_data && allocation != H5D_SPACE_STATUS_ALLOCATED";
+ }
+ else if ( !write_data &&
+ ( allocation != H5D_SPACE_STATUS_NOT_ALLOCATED ) ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_ctg_i: !write_data && allocation != H5D_SPACE_STATUS_NOT_ALLOCATED";
+ }
+ HDassert(ret >= 0);
+ HDassert((write_data && allocation == H5D_SPACE_STATUS_ALLOCATED) ||
+ (!write_data && allocation == H5D_SPACE_STATUS_NOT_ALLOCATED));
+ }
+
+ if ( pass ) {
+
+ dcpl = H5Dget_create_plist(dsid);
+
+ if ( dcpl <= 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_ctg_i: H5Dget_create_plist() failed.";
+ }
+ HDassert(dcpl > 0);
+ }
+
+ if ( pass ) {
+
+ layout = H5Pget_layout(dcpl);
+
+ if ( H5D_CONTIGUOUS != layout ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_ctg_i: H5D_CONTIGUOUS != layout";
+ }
+ HDassert(H5D_CONTIGUOUS == layout);
+ }
+
+ if ( pass ) {
+
+ ret = H5Pclose(dcpl);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_ctg_i: H5Pclose() failed.";
+ }
+ HDassert(ret >= 0);
+ }
+
+ if ( ( pass ) && ( write_data ) ) {
+
+ rdata = (int *)malloc(sizeof(int) * DSET_DIMS);
+
+ if ( ! rdata ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_ctg_i: malloc of rdata failed.";
+ }
+ HDassert(rdata);
+ }
+
+ if ( ( pass ) && ( write_data ) ) {
+
+ ret = H5Dread(dsid, H5T_NATIVE_INT, H5S_ALL, H5S_ALL,
+ H5P_DEFAULT, rdata);
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_ctg_i: H5Dread() failed.";
+ }
+ HDassert(ret >= 0);
+ }
+
+ if ( ( pass ) && ( write_data ) ) {
+
+ for(u = 0; u < DSET_DIMS; u++) {
+
+ if ( (int)u != rdata[u] ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_ctg_i: u != rdata[u].";
+ break;
+ }
+ HDassert((int)u == rdata[u]);
+ }
+
+ free(rdata);
+ } /* end if */
+
+ if ( pass ) {
+
+ ret = H5Dclose(dsid);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_ctg_i: H5Dclose() failed";
+ }
+ HDassert(ret >= 0);
+ }
+
+ return;
+
+} /* vrfy_ds_ctg_i() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: ds_chk_i
+ *
+ * Purpose: Create a chunked dataset w/int datatype. Write data
+ * to the data set or not as indicated by the write_data
+ * parameter.
+ *
+ * If pass is false on entry, do nothing.
+ *
+ * If an error is detected, set pass to FALSE, and set
+ * failure_mssg to point to an appropriate error message.
+ *
+ * Return: void
+ *
+ * Programmer: John Mainzer
+ * 9/14/15
+ *
+ *-------------------------------------------------------------------------
+ */
+void
+ds_chk_i(hid_t fid, const char *dset_name, hbool_t write_data)
+{
+ int *wdata = NULL;
+ unsigned u;
+ hid_t dsid = -1;
+ hid_t dcpl = -1;
+ hid_t sid = -1;
+ hsize_t dims[1] = {DSET_DIMS};
+ hsize_t chunk_dims[1] = {DSET_CHUNK_DIMS};
+ herr_t ret;
+
+ if ( pass ) {
+
+ sid = H5Screate_simple(1, dims, NULL);
+
+ if ( sid <= 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "ds_chk_i: H5Screate_simple() failed.";
+ }
+ HDassert(sid > 0);
+ }
+
+ if ( pass ) {
+
+ dcpl = H5Pcreate(H5P_DATASET_CREATE);
+
+ if ( dcpl <= 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "ds_chk_i: H5Pcreate() failed.";
+ }
+ HDassert(dcpl > 0);
+ }
+
+ if ( pass ) {
+
+ ret = H5Pset_chunk(dcpl, 1, chunk_dims);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "ds_chk_i: H5Pset_chunk() failed.";
+ }
+ HDassert(ret >= 0);
+ }
+
+ if ( pass ) {
+
+ dsid = H5Dcreate2(fid, dset_name, H5T_NATIVE_INT, sid,
+ H5P_DEFAULT, dcpl, H5P_DEFAULT);
+
+ if ( dsid <= 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "ds_chk_i: H5Dcreate2() failed";
+ }
+ HDassert(dsid > 0);
+ }
+
+ if ( pass ) {
+
+ ret = H5Pclose(dcpl);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "ds_chk_i: H5Pclose() failed.";
+ }
+ HDassert(ret >= 0);
+ }
+
+ if ( pass ) {
+
+ ret = H5Sclose(sid);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "ds_chk_i: H5Sclose() failed.";
+ }
+ HDassert(ret >= 0);
+ }
+
+ if ( ( pass ) && ( write_data ) ) {
+
+ wdata = (int *)malloc(sizeof(int) * DSET_DIMS);
+
+ if ( ! wdata ) {
+
+ pass = FALSE;
+ failure_mssg = "ds_chk_i: malloc of wdata failed.";
+ }
+ HDassert(wdata);
+ }
+
+ if ( ( pass ) && ( write_data ) ) {
+
+ for(u = 0; u < DSET_DIMS; u++)
+ wdata[u] = (int)u;
+
+ ret = H5Dwrite(dsid, H5T_NATIVE_INT, H5S_ALL, H5S_ALL,
+ H5P_DEFAULT, wdata);
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "ds_chk_i: H5Dwrite() failed.";
+ }
+ HDassert(ret >= 0);
+
+ free(wdata);
+ } /* end if */
+
+ if ( pass ) {
+
+ ret = H5Dclose(dsid);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "ds_chk_i: H5Dclose() failed.";
+ }
+ HDassert(ret >= 0);
+ }
+
+ return;
+
+} /* ds_chk_i */
+
+
+/*-------------------------------------------------------------------------
+ * Function: vrfy_ds_chk_i
+ *
+ * Purpose: Validate a chunked datasets w/int datatypes. Validate
+ * data if indicated via the write_data parameter.
+ *
+ * If pass is false on entry, do nothing.
+ *
+ * If an error is detected, set pass to FALSE, and set
+ * failure_mssg to point to an appropriate error message.
+ *
+ * Return: void
+ *
+ * Programmer: John Mainzer
+ * 9/14/15
+ *
+ *-------------------------------------------------------------------------
+ */
+void
+vrfy_ds_chk_i(hid_t fid, const char *dset_name, hbool_t write_data)
+{
+ int *rdata = NULL;
+ unsigned u;
+ hid_t dsid = -1;
+ hid_t sid = -1;
+ hid_t tid = -1;
+ hid_t dcpl = -1;
+ H5D_space_status_t allocation;
+ H5D_layout_t layout;
+ int ndims;
+ hsize_t dims[1], max_dims[1], chunk_dims[1];
+ htri_t type_equal;
+ herr_t ret;
+
+ if ( pass ) {
+
+ dsid = H5Dopen2(fid, dset_name, H5P_DEFAULT);
+
+ if ( dsid <= 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_chk_i: H5Dopen2() failed.";
+ }
+ HDassert(dsid > 0);
+ }
+
+ if ( pass ) {
+
+ sid = H5Dget_space(dsid);
+
+ if ( sid <= 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_chk_i: H5Dget_space() failed.";
+ }
+ HDassert(sid > 0);
+ }
+
+ if ( pass ) {
+
+ ndims = H5Sget_simple_extent_ndims(sid);
+
+ if ( 1 != ndims ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_chk_i: 1 != ndims";
+ }
+ HDassert(1 == ndims);
+ }
+
+ if ( pass ) {
+
+ ret = H5Sget_simple_extent_dims(sid, dims, max_dims);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_chk_i: H5Sget_simple_extent_dims() failed";
+ }
+ else if ( DSET_DIMS != dims[0] ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_chk_i: DSET_DIMS != dims[0]";
+ }
+ else if ( DSET_DIMS != max_dims[0] ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_chk_i: DSET_DIMS != max_dims[0]";
+ }
+ HDassert(ret >= 0);
+ HDassert(DSET_DIMS == dims[0]);
+ HDassert(DSET_DIMS == max_dims[0]);
+ }
+
+ if ( pass ) {
+
+ ret = H5Sclose(sid);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_chk_i: H5Sclose() failed.";
+ }
+ HDassert(ret >= 0);
+ }
+
+ if ( pass ) {
+
+ tid = H5Dget_type(dsid);
+
+ if ( tid <= 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_chk_i: H5Dget_type() failed.";
+ }
+ HDassert(tid > 0);
+ }
+
+ if ( pass ) {
+
+ type_equal = H5Tequal(tid, H5T_NATIVE_INT);
+
+ if ( 1 != type_equal ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_chk_i: tid != H5T_NATIVE_INT";
+ }
+ HDassert(1 == type_equal);
+ }
+
+ if ( pass ) {
+
+ ret = H5Tclose(tid);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_chk_i: H5Tclose() failed.";
+ }
+ HDassert(ret >= 0);
+ }
+
+ if ( pass ) {
+
+ ret = H5Dget_space_status(dsid, &allocation);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_chk_i: H5Dget_space_status() failed.";
+ }
+ else if ( write_data && ( allocation != H5D_SPACE_STATUS_ALLOCATED ) ) {
+
+ pass = FALSE;
+ failure_mssg =
+ "vrfy_ds_chk_i: write_data && allocation != H5D_SPACE_STATUS_ALLOCATED";
+ }
+ else if ( !write_data &&
+ ( allocation != H5D_SPACE_STATUS_NOT_ALLOCATED ) ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_chk_i: !write_data && allocation != H5D_SPACE_STATUS_NOT_ALLOCATED";
+ }
+ HDassert(ret >= 0);
+ HDassert((write_data && allocation == H5D_SPACE_STATUS_ALLOCATED) ||
+ (!write_data && allocation == H5D_SPACE_STATUS_NOT_ALLOCATED));
+ }
+
+ if ( pass ) {
+
+ dcpl = H5Dget_create_plist(dsid);
+
+ if ( dcpl <= 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_chk_i: H5Dget_create_plist() failed.";
+ }
+ HDassert(dcpl > 0);
+ }
+
+ if ( pass ) {
+
+ layout = H5Pget_layout(dcpl);
+
+ if ( H5D_CHUNKED != layout ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_chk_i: H5D_CHUNKED != layout";
+ }
+ HDassert(H5D_CHUNKED == layout);
+ }
+
+ if ( pass ) {
+
+ ret = H5Pget_chunk(dcpl, 1, chunk_dims);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_chk_i: H5Pget_chunk";
+ }
+ else if ( DSET_CHUNK_DIMS != chunk_dims[0] ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_chk_i: ";
+ }
+ HDassert(ret >= 0);
+ HDassert(DSET_CHUNK_DIMS == chunk_dims[0]);
+ }
+
+ if ( pass ) {
+
+ ret = H5Pclose(dcpl);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_chk_i: H5Pclose() failed.";
+ }
+ HDassert(ret >= 0);
+ }
+
+ if ( ( pass ) && ( write_data ) ) {
+
+ rdata = (int *)malloc(sizeof(int) * DSET_DIMS);
+
+ if ( ! rdata ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_chk_i: malloc of rdata failed.";
+ }
+ HDassert(rdata);
+ }
+
+ if ( ( pass ) && ( write_data ) ) {
+
+ ret = H5Dread(dsid, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT,
+ rdata);
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_chk_i: H5Dread() failed.";
+ }
+ HDassert(ret >= 0);
+ }
+
+ if ( ( pass ) && ( write_data ) ) {
+
+ for(u = 0; u < DSET_DIMS; u++) {
+
+ if ( (int)u != rdata[u] ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_chk_i: u != rdata[u]";
+ break;
+ }
+ HDassert((int)u == rdata[u]);
+ }
+
+ free(rdata);
+ } /* end if */
+
+
+ if ( pass ) {
+
+ ret = H5Dclose(dsid);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_chk_i: H5Dclose() failed.";
+ }
+ HDassert(ret >= 0);
+ }
+
+ return;
+
+} /* vrfy_ds_chk_i() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: ds_cpt_i
+ *
+ * Purpose: Create a compact dataset w/int datatype. Write data
+ * to the data set or not as indicated by the write_data
+ * parameter.
+ *
+ * If pass is false on entry, do nothing.
+ *
+ * If an error is detected, set pass to FALSE, and set
+ * failure_mssg to point to an appropriate error message.
+ *
+ * Return: void
+ *
+ * Programmer: John Mainzer
+ * 9/14/15
+ *
+ *-------------------------------------------------------------------------
+ */
+void
+ds_cpt_i(hid_t fid, const char *dset_name, hbool_t write_data)
+{
+ int *wdata = NULL;
+ unsigned u;
+ hid_t dsid = -1;
+ hid_t dcpl = -1;
+ hid_t sid = -1;
+ hsize_t dims[1] = {DSET_COMPACT_DIMS};
+ herr_t ret;
+
+ if ( pass ) {
+
+ sid = H5Screate_simple(1, dims, NULL);
+
+ if ( sid <= 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "ds_cpt_i: H5Screate_simple() failed.";
+ }
+ HDassert(sid > 0);
+ }
+
+ if ( pass ) {
+
+ dcpl = H5Pcreate(H5P_DATASET_CREATE);
+
+ if ( dcpl <= 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "ds_cpt_i: H5Pcreate() failed.";
+ }
+ HDassert(dcpl > 0);
+ }
+
+ if ( pass ) {
+
+ ret = H5Pset_layout(dcpl, H5D_COMPACT);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "ds_cpt_i: H5Pset_layout() failed.";
+ }
+ HDassert(ret >= 0);
+ }
+
+ if ( pass ) {
+
+ dsid = H5Dcreate2(fid, dset_name, H5T_NATIVE_INT, sid,
+ H5P_DEFAULT, dcpl, H5P_DEFAULT);
+
+ if ( dsid <= 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "ds_cpt_i: H5Dcreate2() failed.";
+ }
+ HDassert(dsid > 0);
+ }
+
+ if ( pass ) {
+
+ ret = H5Pclose(dcpl);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "ds_cpt_i: H5Pclose() failed.";
+ }
+ HDassert(ret >= 0);
+ }
+
+ if ( pass ) {
+
+ ret = H5Sclose(sid);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "ds_cpt_i: H5Sclose() failed.";
+ }
+ HDassert(ret >= 0);
+ }
+
+ if ( ( pass ) && ( write_data ) ) {
+
+ wdata = (int *)malloc(sizeof(int) * DSET_COMPACT_DIMS);
+
+ if ( ! wdata ) {
+
+ pass = FALSE;
+ failure_mssg = "ds_cpt_i: malloc of wdata failed.";
+ }
+ HDassert(wdata);
+ }
+
+ if ( ( pass ) && ( write_data ) ) {
+
+ for(u = 0; u < DSET_COMPACT_DIMS; u++)
+ wdata[u] = (int)u;
+
+ ret = H5Dwrite(dsid, H5T_NATIVE_INT, H5S_ALL, H5S_ALL,
+ H5P_DEFAULT, wdata);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "ds_cpt_i: H5Dwrite() failed.";
+ }
+ HDassert(ret >= 0);
+
+ free(wdata);
+ } /* end if */
+
+ if ( pass ) {
+
+ ret = H5Dclose(dsid);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "ds_cpt_i: H5Dclose() failed.";
+ }
+ HDassert(ret >= 0);
+ }
+
+ return;
+
+} /* ds_cpt_i() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: vrfy_ds_cpt_i
+ *
+ * Purpose: Validate a compact datasets w/int datatypes. Validate
+ * data if indicated via the write_data parameter.
+ *
+ * If pass is false on entry, do nothing.
+ *
+ * If an error is detected, set pass to FALSE, and set
+ * failure_mssg to point to an appropriate error message.
+ *
+ * Return: void
+ *
+ * Programmer: John Mainzer
+ * 9/14/15
+ *
+ *-------------------------------------------------------------------------
+ */
+void
+vrfy_ds_cpt_i(hid_t fid, const char *dset_name, hbool_t write_data)
+{
+ int *rdata = NULL;
+ unsigned u;
+ hid_t dsid = -1;
+ hid_t sid = -1;
+ hid_t tid = -1;
+ hid_t dcpl = -1;
+ H5D_space_status_t allocation;
+ H5D_layout_t layout;
+ int ndims;
+ hsize_t dims[1], max_dims[1];
+ htri_t type_equal;
+ herr_t ret;
+
+ if ( pass ) {
+
+ dsid = H5Dopen2(fid, dset_name, H5P_DEFAULT);
+
+ if ( dsid <= 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_cpt_i: H5Dopen2() failed.";
+ }
+ HDassert(dsid > 0);
+ }
+
+ if ( pass ) {
+
+ sid = H5Dget_space(dsid);
+
+ if ( sid <= 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_cpt_i: H5Dget_space() failed.";
+ }
+ HDassert(sid > 0);
+ }
+
+ if ( pass ) {
+
+ ndims = H5Sget_simple_extent_ndims(sid);
+
+ if ( 1 != ndims ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_cpt_i: 1 != ndims";
+ }
+ HDassert(1 == ndims);
+ }
+
+ if ( pass ) {
+
+ ret = H5Sget_simple_extent_dims(sid, dims, max_dims);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_cpt_i: H5Sget_simple_extent_dims() failed";
+ }
+ else if ( DSET_COMPACT_DIMS != dims[0] ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_cpt_i: DSET_COMPACT_DIMS != dims[0]";
+ }
+ else if ( DSET_COMPACT_DIMS != max_dims[0] ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_cpt_i: DSET_COMPACT_DIMS != max_dims[0]";
+ }
+ HDassert(ret >= 0);
+ HDassert(DSET_COMPACT_DIMS == dims[0]);
+ HDassert(DSET_COMPACT_DIMS == max_dims[0]);
+ }
+
+ if ( pass ) {
+
+ ret = H5Sclose(sid);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_cpt_i: H5Sclose() failed.";
+ }
+ HDassert(ret >= 0);
+ }
+
+ if ( pass ) {
+
+ tid = H5Dget_type(dsid);
+
+ if ( tid <= 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_cpt_i: H5Dget_type() failed.";
+ }
+ HDassert(tid > 0);
+ }
+
+ if ( pass ) {
+
+ type_equal = H5Tequal(tid, H5T_NATIVE_INT);
+
+ if ( 1 != type_equal ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_cpt_i: type != H5T_NATIVE_INT";
+ }
+ HDassert(1 == type_equal);
+ }
+
+ if ( pass ) {
+
+ ret = H5Tclose(tid);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_cpt_i: H5Tclose() failed.";
+ }
+ HDassert(ret >= 0);
+ }
+
+ if ( pass ) {
+
+ ret = H5Dget_space_status(dsid, &allocation);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_cpt_i: H5Dget_space_status() failed.";
+ }
+ else if ( H5D_SPACE_STATUS_ALLOCATED != allocation ) {
+
+ pass = FALSE;
+ failure_mssg =
+ "vrfy_ds_cpt_i: H5D_SPACE_STATUS_ALLOCATED != allocation";
+ }
+ HDassert(ret >= 0);
+ HDassert(H5D_SPACE_STATUS_ALLOCATED == allocation);
+ }
+
+ if ( pass ) {
+
+ dcpl = H5Dget_create_plist(dsid);
+
+ if ( dcpl <= 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_cpt_i: H5Dget_create_plist() failed.";
+ }
+ HDassert(dcpl > 0);
+ }
+
+ if ( pass ) {
+
+ layout = H5Pget_layout(dcpl);
+
+ if ( H5D_COMPACT != layout ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_cpt_i: H5D_COMPACT != layout";
+ }
+ HDassert(H5D_COMPACT == layout);
+ }
+
+ if ( pass ) {
+
+ ret = H5Pclose(dcpl);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_cpt_i: H5Pclose() failed.";
+ }
+ HDassert(ret >= 0);
+ }
+
+ if ( ( pass ) && ( write_data ) ) {
+
+ rdata = (int *)malloc(sizeof(int) * DSET_COMPACT_DIMS);
+
+ if ( ! rdata ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_cpt_i: malloc of rdata failed.";
+ }
+ HDassert(rdata);
+ }
+
+ if ( ( pass ) && ( write_data ) ) {
+
+ ret = H5Dread(dsid, H5T_NATIVE_INT, H5S_ALL, H5S_ALL,
+ H5P_DEFAULT, rdata);
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_cpt_i: H5Dread() failed.";
+ }
+ HDassert(ret >= 0);
+ }
+
+ if ( ( pass ) && ( write_data ) ) {
+
+ for(u = 0; u < DSET_COMPACT_DIMS; u++) {
+
+ if ( (int)u != rdata[u] ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_cpt_i: (int)u != rdata[u]";
+ break;
+ }
+ HDassert((int)u == rdata[u]);
+ }
+
+ free(rdata);
+ } /* end if */
+
+ if ( pass ) {
+
+ ret = H5Dclose(dsid);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_cpt_i: H5Dclose() failed.";
+ }
+ HDassert(ret >= 0);
+ }
+
+ return;
+
+} /* vrfy_ds_cpt_i() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: ds_ctg_v
+ *
+ * Purpose: Create a contiguous dataset w/variable-length datatype.
+ * Write data to the data set or not as indicated by the
+ * write_data parameter.
+ *
+ * If pass is false on entry, do nothing.
+ *
+ * If an error is detected, set pass to FALSE, and set
+ * failure_mssg to point to an appropriate error message.
+ *
+ * Return: void
+ *
+ * Programmer: John Mainzer
+ * 9/14/15
+ *
+ *-------------------------------------------------------------------------
+ */
+void
+ds_ctg_v(hid_t fid, const char *dset_name, hbool_t write_data)
+{
+ hid_t dsid = -1;
+ hid_t sid = -1;
+ hid_t tid = -1;
+ hsize_t dims[1] = {DSET_SMALL_DIMS};
+ herr_t ret;
+ hvl_t *wdata = NULL;
+ unsigned u;
+
+ if ( pass ) {
+
+ sid = H5Screate_simple(1, dims, NULL);
+
+ if ( sid <= 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "ds_ctg_v: H5Screate_simple";
+ }
+ HDassert(sid > 0);
+ }
+
+ if ( pass ) {
+
+ tid = H5Tvlen_create(H5T_NATIVE_INT);
+
+ if ( tid <= 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "ds_ctg_v: H5Tvlen_create() failed.";
+ }
+ HDassert(tid > 0);
+ }
+
+ if ( pass ) {
+
+ dsid = H5Dcreate2(fid, dset_name, tid, sid, H5P_DEFAULT,
+ H5P_DEFAULT, H5P_DEFAULT);
+
+ if ( dsid <= 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "ds_ctg_v: H5Dcreate2() failed.";
+ }
+ HDassert(dsid > 0);
+ }
+
+ if ( ( pass ) && ( write_data ) ) {
+
+ wdata = (hvl_t *)malloc(sizeof(hvl_t) * DSET_SMALL_DIMS);
+
+ if ( ! wdata ) {
+
+ pass = FALSE;
+ failure_mssg = "ds_ctg_v: malloc of wdata failed.";
+ }
+ HDassert(wdata);
+ }
+
+ if ( ( pass ) && ( write_data ) ) {
+
+ for(u = 0; u < DSET_SMALL_DIMS; u++) {
+
+ int *tdata;
+ unsigned len;
+ unsigned v;
+
+ len = (u % 10) + 1;
+ tdata = (int *)malloc(sizeof(int) * len);
+
+ if ( !tdata ) {
+
+ pass = FALSE;
+ failure_mssg = "ds_ctg_v: malloc of tdata failed.";
+ break;
+ }
+ HDassert(tdata);
+
+ for(v = 0; v < len; v++)
+ tdata[v] = (int)(u + v);
+
+ wdata[u].len = len;
+ wdata[u].p = tdata;
+ } /* end for */
+ }
+
+ if ( ( pass ) && ( write_data ) ) {
+
+ ret = H5Dwrite(dsid, tid, H5S_ALL, H5S_ALL, H5P_DEFAULT, wdata);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "ds_ctg_v: H5Dwrite() failed.";
+ }
+ HDassert(ret >= 0);
+ }
+
+ if ( ( pass ) && ( write_data ) ) {
+
+ ret = H5Dvlen_reclaim(tid, sid, H5P_DEFAULT, wdata);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "ds_ctg_v: H5Dvlen_reclaim() failed.";
+ }
+ HDassert(ret >= 0);
+
+ free(wdata);
+
+ } /* end if */
+
+ if ( pass ) {
+
+ ret = H5Sclose(sid);
+
+ if ( sid < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "ds_ctg_v: H5Sclose() failed.";
+ }
+ HDassert(ret >= 0);
+ }
+
+ if ( pass ) {
+
+ ret = H5Tclose(tid);
+
+ if ( tid < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "ds_ctg_v: H5Tclose() failed.";
+ }
+ HDassert(ret >= 0);
+ }
+
+ if ( pass ) {
+
+ ret = H5Dclose(dsid);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "ds_ctg_v: H5Dclose() failed.";
+ }
+ HDassert(ret >= 0);
+ }
+
+ return;
+
+} /* ds_ctg_v() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: vrfy_ds_ctg_v
+ *
+ * Purpose: Validate a contiguous datasets w/variable-length datatypes.
+ * Validate data if indicated via the write_data parameter.
+ *
+ * If pass is false on entry, do nothing.
+ *
+ * If an error is detected, set pass to FALSE, and set
+ * failure_mssg to point to an appropriate error message.
+ *
+ * Return: void
+ *
+ * Programmer: John Mainzer
+ * 9/14/15
+ *
+ *-------------------------------------------------------------------------
+ */
+void
+vrfy_ds_ctg_v(hid_t fid, const char *dset_name, hbool_t write_data)
+{
+ hid_t dsid = -1;
+ hid_t sid = -1;
+ hid_t tid = -1;
+ hid_t tmp_tid = -1;
+ hid_t dcpl = -1;
+ H5D_space_status_t allocation;
+ H5D_layout_t layout;
+ int ndims;
+ hsize_t dims[1], max_dims[1];
+ htri_t type_equal;
+ hvl_t *rdata = NULL;
+ unsigned u;
+ herr_t ret;
+
+ if ( pass ) {
+
+ dsid = H5Dopen2(fid, dset_name, H5P_DEFAULT);
+
+ if ( dsid <= 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_ctg_v: H5Dopen2() failed.";
+ }
+ HDassert(dsid > 0);
+ }
+
+ if ( pass ) {
+
+ sid = H5Dget_space(dsid);
+
+ if ( sid <= 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_ctg_v: H5Dget_space() failed";
+ }
+ HDassert(sid > 0);
+ }
+
+ if ( pass ) {
+
+ ndims = H5Sget_simple_extent_ndims(sid);
+
+ if ( 1 != ndims ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_ctg_v: 1 != ndims";
+ }
+ HDassert(1 == ndims);
+ }
+
+ if ( pass ) {
+
+ ret = H5Sget_simple_extent_dims(sid, dims, max_dims);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_ctg_v: H5Sget_simple_extent_dims() failed.";
+ }
+ else if ( DSET_SMALL_DIMS != dims[0] ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_ctg_v: DSET_SMALL_DIMS != dims[0]";
+ }
+ else if ( DSET_SMALL_DIMS != max_dims[0] ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_ctg_v: DSET_SMALL_DIMS != max_dims[0]";
+ }
+ HDassert(ret >= 0);
+ HDassert(DSET_SMALL_DIMS == dims[0]);
+ HDassert(DSET_SMALL_DIMS == max_dims[0]);
+ }
+
+ if ( pass ) {
+
+ tid = H5Dget_type(dsid);
+
+ if ( tid <= 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_ctg_v: H5Dget_type() failed.";
+ }
+ HDassert(tid > 0);
+ }
+
+ if ( pass ) {
+
+ tmp_tid = H5Tvlen_create(H5T_NATIVE_INT);
+
+ if ( tmp_tid <= 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_ctg_v: H5Tvlen_create() failed.";
+ }
+ HDassert(tmp_tid > 0);
+ }
+
+ if ( pass ) {
+
+ type_equal = H5Tequal(tid, tmp_tid);
+
+ if ( 1 != type_equal ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_ctg_v: type != vlen H5T_NATIVE_INT";
+ }
+ HDassert(1 == type_equal);
+ }
+
+ if ( pass ) {
+
+ ret = H5Tclose(tmp_tid);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_ctg_v: H5Tclose() failed.";
+ }
+ HDassert(ret >= 0);
+ }
+
+ if ( pass ) {
+
+ ret = H5Dget_space_status(dsid, &allocation);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_ctg_v: H5Dget_space_status() failed";
+ }
+ else if ( write_data && (allocation != H5D_SPACE_STATUS_ALLOCATED) ) {
+
+ pass = FALSE;
+ failure_mssg =
+ "vrfy_ds_ctg_v: write_data && allocation != H5D_SPACE_STATUS_ALLOCATED";
+ }
+ else if ( !write_data &&
+ ( allocation != H5D_SPACE_STATUS_NOT_ALLOCATED ) ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_ctg_v: !write_data && allocation != H5D_SPACE_STATUS_NOT_ALLOCATED";
+ }
+ HDassert(ret >= 0);
+ HDassert((write_data && allocation == H5D_SPACE_STATUS_ALLOCATED) ||
+ (!write_data && allocation == H5D_SPACE_STATUS_NOT_ALLOCATED));
+ }
+
+ if ( pass ) {
+
+ dcpl = H5Dget_create_plist(dsid);
+
+ if ( dcpl <= 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_ctg_v: H5Dget_create_plist() failed.";
+ }
+ HDassert(dcpl > 0);
+ }
+
+ if ( pass ) {
+
+ layout = H5Pget_layout(dcpl);
+
+ if ( H5D_CONTIGUOUS != layout ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_ctg_v: H5D_CONTIGUOUS != layout";
+ }
+ HDassert(H5D_CONTIGUOUS == layout);
+ }
+
+ if ( pass ) {
+
+ ret = H5Pclose(dcpl);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_ctg_v: H5Pclose() failed.";
+ }
+ HDassert(ret >= 0);
+ }
+
+ if ( ( pass ) && ( write_data ) ) {
+
+ rdata = (hvl_t *)malloc(sizeof(hvl_t) * DSET_SMALL_DIMS);
+
+ if ( !rdata ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_ctg_v: malloc of rdata failed.";
+ }
+ HDassert(rdata);
+ }
+
+ if ( ( pass ) && ( write_data ) ) {
+
+ ret = H5Dread(dsid, tid, H5S_ALL, H5S_ALL, H5P_DEFAULT, rdata);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_ctg_v: H5Dread() failed.";
+ }
+ HDassert(ret >= 0);
+ }
+
+ if ( ( pass ) && ( write_data ) ) {
+
+ for(u = 0; u < DSET_SMALL_DIMS; u++) {
+ unsigned len;
+ unsigned v;
+
+ len = (unsigned)rdata[u].len;
+ for(v = 0; v < len; v++) {
+ int *tdata = (int *)rdata[u].p;
+
+ if ( !tdata ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_ctg_v: !tdata";
+ break;
+ }
+ else if ( (int)(u + v) != tdata[v] ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_ctg_v: (int)(u + v) != tdata[v]";
+ break;
+ }
+ HDassert(tdata);
+ HDassert((int)(u + v) == tdata[v]);
+ } /* end for */
+ } /* end for */
+ }
+
+ if ( ( pass ) && ( write_data ) ) {
+
+ ret = H5Dvlen_reclaim(tid, sid, H5P_DEFAULT, rdata);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_ctg_v: H5Dvlen_reclaim() failed.";
+ }
+ HDassert(ret >= 0);
+
+ free(rdata);
+ } /* end if */
+
+ if ( pass ) {
+
+ ret = H5Sclose(sid);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_ctg_v: H5Sclose() failed.";
+ }
+ HDassert(ret >= 0);
+ }
+
+ if ( pass ) {
+
+ ret = H5Tclose(tid);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_ctg_v: H5Tclose() failed.";
+ }
+ HDassert(ret >= 0);
+ }
+
+ if ( pass ) {
+
+ ret = H5Dclose(dsid);
+
+ if ( ret < 0 ) {
+
+ pass = FALSE;
+ failure_mssg = "vrfy_ds_ctg_v: H5Dclose() failed.";
+ }
+ HDassert(ret >= 0);
+ }
+
+ return;
+
+} /* vrfy_ds_ctg_v() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: create_zoo
+ *
+ * Purpose: Given the path to a group, construct a variety of HDF5
+ * data sets, groups, and other objects selected so as to
+ * include instances of all on disk data structures used
+ * in the HDF5 library.
+ *
+ * If pass is false on entry, do nothing.
+ *
+ * If an error is detected, set pass to FALSE, and set
+ * failure_mssg to point to an appropriate error message.
+ *
+ * This function was initially created to assist in testing
+ * the cache image feature of the metadata cache. Thus, it
+ * only concerns itself with the version 2 superblock, and
+ * on disk structures that can occur with this version of
+ * the superblock.
+ *
+ * Note the associated validate_zoo() function.
+ *
+ * Return: void
+ *
+ * Programmer: John Mainzer
+ * 9/14/15
+ *
+ *-------------------------------------------------------------------------
+ */
+
+void
+create_zoo(hid_t fid, const char *base_path, int proc_num)
+{
+ char full_path[1024];
+
+ HDassert(base_path);
+
+ /* Add & verify an empty "new style" group */
+ if ( pass ) {
+ sprintf(full_path, "%s/A", base_path);
+ HDassert(strlen(full_path) < 1024);
+ ns_grp_0(fid, full_path);
+ }
+
+ if ( pass ) {
+ sprintf(full_path, "%s/A", base_path);
+ HDassert(strlen(full_path) < 1024);
+ vrfy_ns_grp_0(fid, full_path);
+ }
+
+ /* Add & verify a compact "new style" group (3 link messages) */
+ if ( pass ) {
+ sprintf(full_path, "%s/B", base_path);
+ HDassert(strlen(full_path) < 1024);
+ ns_grp_c(fid, full_path, 3);
+ }
+
+ if ( pass ) {
+ sprintf(full_path, "%s/B", base_path);
+ HDassert(strlen(full_path) < 1024);
+ vrfy_ns_grp_c(fid, full_path, 3);
+ }
+
+ /* Add & verify a dense "new style" group (w/300 links, in v2 B-tree &
+ * fractal heap)
+ */
+ if ( pass ) {
+ sprintf(full_path, "%s/C", base_path);
+ HDassert(strlen(full_path) < 1024);
+ ns_grp_d(fid, full_path, 300);
+ }
+
+ if ( pass ) {
+ sprintf(full_path, "%s/C", base_path);
+ HDassert(strlen(full_path) < 1024);
+ vrfy_ns_grp_d(fid, full_path, 300);
+ }
+
+ /* Add & verify an empty "old style" group to file */
+ if ( pass ) {
+ sprintf(full_path, "%s/D", base_path);
+ HDassert(strlen(full_path) < 1024);
+ os_grp_0(fid, full_path);
+ }
+
+ if ( pass ) {
+ sprintf(full_path, "%s/D", base_path);
+ HDassert(strlen(full_path) < 1024);
+ vrfy_os_grp_0(fid, full_path);
+ }
+
+ /* Add & verify an "old style" group (w/300 links, in v1 B-tree &
+ * local heap) to file
+ */
+ if ( pass ) {
+ sprintf(full_path, "%s/E", base_path);
+ HDassert(strlen(full_path) < 1024);
+ os_grp_n(fid, full_path, proc_num, 300);
+ }
+
+ if ( pass ) {
+ sprintf(full_path, "%s/E", base_path);
+ HDassert(strlen(full_path) < 1024);
+ vrfy_os_grp_n(fid, full_path, proc_num, 300);
+ }
+
+ /* Add & verify a contiguous dataset w/integer datatype (but no data)
+ * to file
+ */
+ if ( pass ) {
+ sprintf(full_path, "%s/F", base_path);
+ HDassert(strlen(full_path) < 1024);
+ ds_ctg_i(fid, full_path, FALSE);
+ }
+
+ if ( pass ) {
+ sprintf(full_path, "%s/F", base_path);
+ HDassert(strlen(full_path) < 1024);
+ vrfy_ds_ctg_i(fid, full_path, FALSE);
+ }
+
+ /* Add & verify a contiguous dataset w/integer datatype (with data)
+ * to file
+ */
+ if ( pass ) {
+ sprintf(full_path, "%s/G", base_path);
+ HDassert(strlen(full_path) < 1024);
+ ds_ctg_i(fid, full_path, TRUE);
+ }
+
+ if ( pass ) {
+ sprintf(full_path, "%s/G", base_path);
+ HDassert(strlen(full_path) < 1024);
+ vrfy_ds_ctg_i(fid, full_path, TRUE);
+ }
+
+ /* Add & verify a chunked dataset w/integer datatype (but no data)
+ * to file
+ */
+ if ( pass ) {
+ sprintf(full_path, "%s/H", base_path);
+ HDassert(strlen(full_path) < 1024);
+ ds_chk_i(fid, full_path, FALSE);
+ }
+
+ if ( pass ) {
+ sprintf(full_path, "%s/H", base_path);
+ HDassert(strlen(full_path) < 1024);
+ vrfy_ds_chk_i(fid, full_path, FALSE);
+ }
+
+ /* Add & verify a chunked dataset w/integer datatype (and data)
+ * to file
+ */
+ if ( pass ) {
+ sprintf(full_path, "%s/I", base_path);
+ HDassert(strlen(full_path) < 1024);
+ ds_chk_i(fid, full_path, TRUE);
+ }
+
+ if ( pass ) {
+ sprintf(full_path, "%s/I", base_path);
+ HDassert(strlen(full_path) < 1024);
+ vrfy_ds_chk_i(fid, full_path, TRUE);
+ }
+
+ /* Add & verify a compact dataset w/integer datatype (but no data)
+ * to file
+ */
+ if ( pass ) {
+ sprintf(full_path, "%s/J", base_path);
+ HDassert(strlen(full_path) < 1024);
+ ds_cpt_i(fid, full_path, FALSE);
+ }
+
+ if ( pass ) {
+ sprintf(full_path, "%s/J", base_path);
+ HDassert(strlen(full_path) < 1024);
+ vrfy_ds_cpt_i(fid, full_path, FALSE);
+ }
+
+ /* Add & verify a compact dataset w/integer datatype (and data)
+ * to file
+ */
+ if ( pass ) {
+ sprintf(full_path, "%s/K", base_path);
+ HDassert(strlen(full_path) < 1024);
+ ds_cpt_i(fid, full_path, TRUE);
+ }
+
+ if ( pass ) {
+ sprintf(full_path, "%s/K", base_path);
+ HDassert(strlen(full_path) < 1024);
+ vrfy_ds_cpt_i(fid, full_path, TRUE);
+ }
+
+ /* Add & verify a contiguous dataset w/variable-length datatype
+ * (but no data) to file
+ */
+ if ( pass ) {
+ sprintf(full_path, "%s/L", base_path);
+ HDassert(strlen(full_path) < 1024);
+ ds_ctg_v(fid, full_path, FALSE);
+ }
+
+ if ( pass ) {
+ sprintf(full_path, "%s/L", base_path);
+ HDassert(strlen(full_path) < 1024);
+ vrfy_ds_ctg_v(fid, full_path, FALSE);
+ }
+
+ /* Add & verify a contiguous dataset w/variable-length datatype
+ * (and data) to file
+ */
+ if ( pass ) {
+ sprintf(full_path, "%s/M", base_path);
+ HDassert(strlen(full_path) < 1024);
+ ds_ctg_v(fid, full_path, TRUE);
+ }
+
+ if ( pass ) {
+ sprintf(full_path, "%s/M", base_path);
+ HDassert(strlen(full_path) < 1024);
+ vrfy_ds_ctg_v(fid, full_path, TRUE);
+ }
+
+ return;
+
+} /* create_zoo() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: validate_zoo
+ *
+ * Purpose: Given the path to a group in which a "zoo" has been
+ * constructed, validate the objects in the "zoo".
+ *
+ * If pass is false on entry, do nothing.
+ *
+ * If an error is detected, set pass to FALSE, and set
+ * failure_mssg to point to an appropriate error message.
+ *
+ * This function was initially created to assist in testing
+ * the cache image feature of the metadata cache. Thus, it
+ * only concerns itself with the version 2 superblock, and
+ * on disk structures that can occur with this version of
+ * the superblock.
+ *
+ * Note the associated validate_zoo() function.
+ *
+ * Return: void
+ *
+ * Programmer: John Mainzer
+ * 9/14/15
+ *
+ *-------------------------------------------------------------------------
+ */
+
+void
+validate_zoo(hid_t fid, const char *base_path, int proc_num)
+{
+ char full_path[1024];
+
+ HDassert(base_path);
+
+ /* validate an empty "new style" group */
+ if ( pass ) {
+ sprintf(full_path, "%s/A", base_path);
+ HDassert(strlen(full_path) < 1024);
+ vrfy_ns_grp_0(fid, full_path);
+ }
+
+ /* validate a compact "new style" group (3 link messages) */
+ if ( pass ) {
+ sprintf(full_path, "%s/B", base_path);
+ HDassert(strlen(full_path) < 1024);
+ vrfy_ns_grp_c(fid, full_path, 3);
+ }
+
+ /* validate a dense "new style" group (w/300 links, in v2 B-tree &
+ * fractal heap)
+ */
+ if ( pass ) {
+ sprintf(full_path, "%s/C", base_path);
+ HDassert(strlen(full_path) < 1024);
+ vrfy_ns_grp_d(fid, full_path, 300);
+ }
+
+ /* validate an empty "old style" group in file */
+ if ( pass ) {
+ sprintf(full_path, "%s/D", base_path);
+ HDassert(strlen(full_path) < 1024);
+ vrfy_os_grp_0(fid, full_path);
+ }
+
+ /* validate an "old style" group (w/300 links, in v1 B-tree &
+ * local heap)
+ */
+ if ( pass ) {
+ sprintf(full_path, "%s/E", base_path);
+ HDassert(strlen(full_path) < 1024);
+ vrfy_os_grp_n(fid, full_path, proc_num, 300);
+ }
+
+ /* validate a contiguous dataset w/integer datatype (but no data)
+ * in file.
+ */
+ if ( pass ) {
+ sprintf(full_path, "%s/F", base_path);
+ HDassert(strlen(full_path) < 1024);
+ vrfy_ds_ctg_i(fid, full_path, FALSE);
+ }
+
+ /* validate a contiguous dataset w/integer datatype (with data)
+ * in file.
+ */
+ if ( pass ) {
+ sprintf(full_path, "%s/G", base_path);
+ HDassert(strlen(full_path) < 1024);
+ vrfy_ds_ctg_i(fid, full_path, TRUE);
+ }
+
+ /* validate a chunked dataset w/integer datatype (but no data)
+ * in file
+ */
+ if ( pass ) {
+ sprintf(full_path, "%s/H", base_path);
+ HDassert(strlen(full_path) < 1024);
+ vrfy_ds_chk_i(fid, full_path, FALSE);
+ }
+
+ /* validate a chunked dataset w/integer datatype (and data)
+ * in file
+ */
+ if ( pass ) {
+ sprintf(full_path, "%s/I", base_path);
+ HDassert(strlen(full_path) < 1024);
+ vrfy_ds_chk_i(fid, full_path, TRUE);
+ }
+
+ /* Validate a compact dataset w/integer datatype (but no data)
+ * in file
+ */
+ if ( pass ) {
+ sprintf(full_path, "%s/J", base_path);
+ HDassert(strlen(full_path) < 1024);
+ vrfy_ds_cpt_i(fid, full_path, FALSE);
+ }
+
+ /* validate a compact dataset w/integer datatype (and data)
+ * in file
+ */
+ if ( pass ) {
+ sprintf(full_path, "%s/K", base_path);
+ HDassert(strlen(full_path) < 1024);
+ vrfy_ds_cpt_i(fid, full_path, TRUE);
+ }
+
+ /* validate a contiguous dataset w/variable-length datatype
+ * (but no data) to file
+ */
+ if ( pass ) {
+ sprintf(full_path, "%s/L", base_path);
+ HDassert(strlen(full_path) < 1024);
+ vrfy_ds_ctg_v(fid, full_path, FALSE);
+ }
+
+ /* validate a contiguous dataset w/variable-length datatype
+ * (and data) to file
+ */
+ if ( pass ) {
+ sprintf(full_path, "%s/M", base_path);
+ HDassert(strlen(full_path) < 1024);
+ vrfy_ds_ctg_v(fid, full_path, TRUE);
+ }
+
+ return;
+
+} /* validate_zoo() */
+
diff --git a/test/genall5.h b/test/genall5.h
new file mode 100644
index 0000000..70b5a6f
--- /dev/null
+++ b/test/genall5.h
@@ -0,0 +1,53 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the files COPYING and Copyright.html. COPYING can be found at the root *
+ * of the source code distribution tree; Copyright.html can be found at the *
+ * root level of an installed copy of the electronic HDF5 document set and *
+ * is linked from the top-level documents page. It can also be found at *
+ * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/* Programmer: John Mainzer
+ * 9/4/15
+ *
+ * This file contains declarations of all functions defined
+ * in genall5.c
+ */
+
+void create_zoo(hid_t fid, const char *base_path, int proc_num);
+void validate_zoo(hid_t fid, const char *base_path, int proc_num);
+
+void ns_grp_0(hid_t fid, const char *group_name);
+void vrfy_ns_grp_0(hid_t fid, const char *group_name);
+
+void ns_grp_c(hid_t fid, const char *group_name, unsigned nlinks);
+void vrfy_ns_grp_c(hid_t fid, const char *group_name, unsigned nlinks);
+
+void ns_grp_d(hid_t fid, const char *group_name, unsigned nlinks);
+void vrfy_ns_grp_d(hid_t fid, const char *group_name, unsigned nlinks);
+
+void os_grp_0(hid_t fid, const char *group_name);
+void vrfy_os_grp_0(hid_t fid, const char *group_name);
+
+void os_grp_n(hid_t fid, const char *group_name, int proc_num, unsigned nlinks);
+void vrfy_os_grp_n(hid_t fid, const char *group_name, int proc_num,
+ unsigned nlinks);
+
+void ds_ctg_i(hid_t fid, const char *dset_name, hbool_t write_data);
+void vrfy_ds_ctg_i(hid_t fid, const char *dset_name, hbool_t write_data);
+
+void ds_chk_i(hid_t fid, const char *dset_name, hbool_t write_data);
+void vrfy_ds_chk_i(hid_t fid, const char *dset_name, hbool_t write_data);
+
+void ds_cpt_i(hid_t fid, const char *dset_name, hbool_t write_data);
+void vrfy_ds_cpt_i(hid_t fid, const char *dset_name, hbool_t write_data);
+
+void ds_ctg_v(hid_t fid, const char *dset_name, hbool_t write_data);
+void vrfy_ds_ctg_v(hid_t fid, const char *dset_name, hbool_t write_data);
+