summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjhendersonHDF <jhenderson@hdfgroup.org>2023-10-24 02:08:06 (GMT)
committerGitHub <noreply@github.com>2023-10-24 02:08:06 (GMT)
commit8cff88c5073b0bbd66c5876e0ce3da16214af39c (patch)
treef1dd8065cc17fbbb749b1c30e5d91e9fe6dbd998
parentaf49eb5b8647e8d9ffb527fd533def0910eb535c (diff)
downloadhdf5-8cff88c5073b0bbd66c5876e0ce3da16214af39c.zip
hdf5-8cff88c5073b0bbd66c5876e0ce3da16214af39c.tar.gz
hdf5-8cff88c5073b0bbd66c5876e0ce3da16214af39c.tar.bz2
Fix some issues with collective metadata reads for chunked datasets (#3716)
Add functions/callbacks for explicit control over chunk index open/close Add functions/callbacks to check if chunk index is open or not so that it can be opened if necessary before temporarily disabling collective metadata reads in the library Add functions/callbacks for requesting loading of additional chunk index metadata beyond the chunk index itself
-rw-r--r--release_docs/RELEASE.txt40
-rw-r--r--src/H5Dbtree.c442
-rw-r--r--src/H5Dbtree2.c467
-rw-r--r--src/H5Dchunk.c63
-rw-r--r--src/H5Dearray.c271
-rw-r--r--src/H5Dfarray.c234
-rw-r--r--src/H5Dmpio.c40
-rw-r--r--src/H5Dnone.c170
-rw-r--r--src/H5Dpkg.h21
-rw-r--r--src/H5Dsingle.c168
10 files changed, 1292 insertions, 624 deletions
diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt
index e5d53e4..e5cb097 100644
--- a/release_docs/RELEASE.txt
+++ b/release_docs/RELEASE.txt
@@ -392,6 +392,46 @@ Bug Fixes since HDF5-1.14.0 release
===================================
Library
-------
+ - Fixed some issues with chunk index metadata not getting read
+ collectively when collective metadata reads are enabled
+
+ When looking up dataset chunks during I/O, the parallel library
+ temporarily disables collective metadata reads since it's generally
+ unlikely that the application will read the same chunks from all
+ MPI ranks. Leaving collective metadata reads enabled during
+ chunk lookups can lead to hangs or other bad behavior depending
+ on the chunk indexing structure used for the dataset in question.
+ However, due to the way that dataset chunk index metadata was
+ previously loaded in a deferred manner, this could mean that
+ the metadata for the main chunk index structure or its
+ accompanying pieces of metadata (e.g., fixed array data blocks)
+ could end up being read independently if these chunk lookup
+ operations are the first chunk index-related operation that
+ occurs on a dataset. This behavior is generally observed when
+ opening a dataset for which the metadata isn't in the metadata
+ cache yet and then immediately performing I/O on that dataset.
+ This behavior is not generally observed when creating a dataset
+ and then performing I/O on it, as the relevant metadata will
+ usually be in the metadata cache as a side effect of creating
+ the chunk index structures during dataset creation.
+
+ This issue has been fixed by adding callbacks to the different
+ chunk indexing structure classes that allow more explicit control
+ over when chunk index metadata gets loaded. When collective
+ metadata reads are enabled, the necessary index metadata will now
+ get loaded collectively by all MPI ranks at the start of dataset
+ I/O to ensure that the ranks don't unintentionally read this
+ metadata independently further on. These changes fix collective
+ loading of the main chunk index structure, as well as v2 B-tree
+ root nodes, extensible array index blocks and fixed array data
+ blocks. There are still pieces of metadata that cannot currently
+ be loaded collectively, however, such as extensible array data
+ blocks, data block pages and super blocks, as well as fixed array
+ data block pages. These pieces of metadata are not necessarily
+ read in by all MPI ranks since this depends on which chunks the
+ ranks have selected in the dataset. Therefore, reading of these
+ pieces of metadata remains an independent operation.
+
- Fixed potential hangs in parallel library during collective I/O with
independent metadata writes
diff --git a/src/H5Dbtree.c b/src/H5Dbtree.c
index d79f7d0..4f8a867 100644
--- a/src/H5Dbtree.c
+++ b/src/H5Dbtree.c
@@ -24,30 +24,32 @@
/***********/
/* Headers */
/***********/
-#include "H5private.h" /* Generic Functions */
-#include "H5Bprivate.h" /* B-link trees */
-#include "H5Dpkg.h" /* Datasets */
-#include "H5Eprivate.h" /* Error handling */
-#include "H5Fprivate.h" /* Files */
-#include "H5FDprivate.h" /* File drivers */
+#include "H5private.h" /* Generic Functions */
+#include "H5Bprivate.h" /* B-link trees */
+#include "H5Dpkg.h" /* Datasets */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Fprivate.h" /* Files */
+#include "H5FDprivate.h" /* File drivers */
#include "H5FLprivate.h" /* Free Lists */
-#include "H5Iprivate.h" /* IDs */
-#include "H5MFprivate.h" /* File space management */
-#include "H5MMprivate.h" /* Memory management */
-#include "H5Oprivate.h" /* Object headers */
+#include "H5Iprivate.h" /* IDs */
+#include "H5MFprivate.h" /* File space management */
+#include "H5MMprivate.h" /* Memory management */
+#include "H5Oprivate.h" /* Object headers */
#include "H5Sprivate.h" /* Dataspaces */
-#include "H5VMprivate.h" /* Vector and array functions */
+#include "H5VMprivate.h" /* Vector and array functions */
/****************/
/* Local Macros */
/****************/
+#define H5D_BTREE_IDX_IS_OPEN(idx_info) (NULL != (idx_info)->storage->u.btree.shared)
+
/******************/
/* Local Typedefs */
/******************/
/*
- * B-tree key. A key contains the minimum logical N-dimensional coordinates and
+ * B-tree key. A key contains the minimum logical N-dimensional coordinates and
* the logical size of the chunk to which this key refers. The
* fastest-varying dimension is assumed to reference individual bytes of the
* array, so a 100-element 1-d array of 4-byte integers would really be a 2-d
@@ -61,9 +63,9 @@
* The chunk's file address is part of the B-tree and not part of the key.
*/
typedef struct H5D_btree_key_t {
- hsize_t scaled[H5O_LAYOUT_NDIMS]; /*logical offset to start*/
- uint32_t nbytes; /*size of stored data */
- unsigned filter_mask; /*excluded filters */
+ hsize_t scaled[H5O_LAYOUT_NDIMS]; /*logical offset to start */
+ uint32_t nbytes; /*size of stored data */
+ unsigned filter_mask; /*excluded filters */
} H5D_btree_key_t;
/* B-tree callback info for iteration over chunks */
@@ -111,10 +113,14 @@ static herr_t H5D__btree_debug_key(FILE *stream, int indent, int fwidth, const v
static herr_t H5D__btree_idx_init(const H5D_chk_idx_info_t *idx_info, const H5S_t *space,
haddr_t dset_ohdr_addr);
static herr_t H5D__btree_idx_create(const H5D_chk_idx_info_t *idx_info);
+static herr_t H5D__btree_idx_open(const H5D_chk_idx_info_t *idx_info);
+static herr_t H5D__btree_idx_close(const H5D_chk_idx_info_t *idx_info);
+static herr_t H5D__btree_idx_is_open(const H5D_chk_idx_info_t *idx_info, bool *is_open);
static bool H5D__btree_idx_is_space_alloc(const H5O_storage_chunk_t *storage);
static herr_t H5D__btree_idx_insert(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata,
const H5D_t *dset);
static herr_t H5D__btree_idx_get_addr(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata);
+static herr_t H5D__btree_idx_load_metadata(const H5D_chk_idx_info_t *idx_info);
static int H5D__btree_idx_iterate(const H5D_chk_idx_info_t *idx_info, H5D_chunk_cb_func_t chunk_cb,
void *chunk_udata);
static herr_t H5D__btree_idx_remove(const H5D_chk_idx_info_t *idx_info, H5D_chunk_common_ud_t *udata);
@@ -137,9 +143,13 @@ const H5D_chunk_ops_t H5D_COPS_BTREE[1] = {{
false, /* v1 B-tree indices does not support SWMR access */
H5D__btree_idx_init, /* insert */
H5D__btree_idx_create, /* create */
+ H5D__btree_idx_open, /* open */
+ H5D__btree_idx_close, /* close */
+ H5D__btree_idx_is_open, /* is_open */
H5D__btree_idx_is_space_alloc, /* is_space_alloc */
H5D__btree_idx_insert, /* insert */
H5D__btree_idx_get_addr, /* get_addr */
+ H5D__btree_idx_load_metadata, /* load_metadata */
NULL, /* resize */
H5D__btree_idx_iterate, /* iterate */
H5D__btree_idx_remove, /* remove */
@@ -158,21 +168,21 @@ const H5D_chunk_ops_t H5D_COPS_BTREE[1] = {{
/* inherits B-tree like properties from H5B */
static H5B_class_t H5B_BTREE[1] = {{
- H5B_CHUNK_ID, /*id */
- sizeof(H5D_btree_key_t), /*sizeof_nkey */
- H5D__btree_get_shared, /*get_shared */
- H5D__btree_new_node, /*new */
- H5D__btree_cmp2, /*cmp2 */
- H5D__btree_cmp3, /*cmp3 */
- H5D__btree_found, /*found */
- H5D__btree_insert, /*insert */
- false, /*follow min branch? */
- false, /*follow max branch? */
- H5B_LEFT, /*critical key */
- H5D__btree_remove, /*remove */
- H5D__btree_decode_key, /*decode */
- H5D__btree_encode_key, /*encode */
- H5D__btree_debug_key /*debug */
+ H5B_CHUNK_ID, /* id */
+ sizeof(H5D_btree_key_t), /* sizeof_nkey */
+ H5D__btree_get_shared, /* get_shared */
+ H5D__btree_new_node, /* new */
+ H5D__btree_cmp2, /* cmp2 */
+ H5D__btree_cmp3, /* cmp3 */
+ H5D__btree_found, /* found */
+ H5D__btree_insert, /* insert */
+ false, /* follow min branch? */
+ false, /* follow max branch? */
+ H5B_LEFT, /* critical key */
+ H5D__btree_remove, /* remove */
+ H5D__btree_decode_key, /* decode */
+ H5D__btree_encode_key, /* encode */
+ H5D__btree_debug_key /* debug */
}};
/*******************/
@@ -183,13 +193,13 @@ static H5B_class_t H5B_BTREE[1] = {{
H5FL_DEFINE_STATIC(H5O_layout_chunk_t);
/*-------------------------------------------------------------------------
- * Function: H5D__btree_get_shared
+ * Function: H5D__btree_get_shared
*
- * Purpose: Returns the shared B-tree info for the specified UDATA.
+ * Purpose: Returns the shared B-tree info for the specified UDATA.
*
- * Return: Success: Pointer to the raw B-tree page for this dataset
+ * Return: Success: Pointer to the raw B-tree page for this dataset
*
- * Failure: Can't fail
+ * Failure: Can't fail
*
*-------------------------------------------------------------------------
*/
@@ -210,17 +220,17 @@ H5D__btree_get_shared(const H5F_t H5_ATTR_UNUSED *f, const void *_udata)
} /* end H5D__btree_get_shared() */
/*-------------------------------------------------------------------------
- * Function: H5D__btree_new_node
+ * Function: H5D__btree_new_node
*
- * Purpose: Adds a new entry to an i-storage B-tree. We can assume that
- * the domain represented by UDATA doesn't intersect the domain
- * already represented by the B-tree.
+ * Purpose: Adds a new entry to an i-storage B-tree. We can assume
+ * that the domain represented by UDATA doesn't intersect the
+ * domain already represented by the B-tree.
*
- * Return: Success: Non-negative. The address of leaf is returned
- * through the ADDR argument. It is also added
- * to the UDATA.
+ * Return: Success: Non-negative. The address of leaf is returned
+ * through the ADDR argument. It is also added
+ * to the UDATA.
*
- * Failure: Negative
+ * Failure: Negative
*
*-------------------------------------------------------------------------
*/
@@ -275,18 +285,18 @@ H5D__btree_new_node(H5F_t H5_ATTR_NDEBUG_UNUSED *f, H5B_ins_t op, void *_lt_key,
} /* end H5D__btree_new_node() */
/*-------------------------------------------------------------------------
- * Function: H5D__btree_cmp2
+ * Function: H5D__btree_cmp2
*
- * Purpose: Compares two keys sort of like strcmp(). The UDATA pointer
- * is only to supply extra information not carried in the keys
- * (in this case, the dimensionality) and is not compared
- * against the keys.
+ * Purpose: Compares two keys sort of like strcmp(). The UDATA pointer
+ * is only to supply extra information not carried in the keys
+ * (in this case, the dimensionality) and is not compared
+ * against the keys.
*
- * Return: Success: -1 if LT_KEY is less than RT_KEY;
- * 1 if LT_KEY is greater than RT_KEY;
- * 0 if LT_KEY and RT_KEY are equal.
+ * Return: Success: -1 if LT_KEY is less than RT_KEY;
+ * 1 if LT_KEY is greater than RT_KEY;
+ * 0 if LT_KEY and RT_KEY are equal.
*
- * Failure: FAIL (same as LT_KEY<RT_KEY)
+ * Failure: FAIL (same as LT_KEY < RT_KEY)
*
*-------------------------------------------------------------------------
*/
@@ -312,26 +322,26 @@ H5D__btree_cmp2(void *_lt_key, void *_udata, void *_rt_key)
} /* end H5D__btree_cmp2() */
/*-------------------------------------------------------------------------
- * Function: H5D__btree_cmp3
+ * Function: H5D__btree_cmp3
*
- * Purpose: Compare the requested datum UDATA with the left and right
- * keys of the B-tree.
+ * Purpose: Compare the requested datum UDATA with the left and right
+ * keys of the B-tree.
*
- * Return: Success: negative if the min_corner of UDATA is less
- * than the min_corner of LT_KEY.
+ * Return: Success: negative if the min_corner of UDATA is less
+ * than the min_corner of LT_KEY.
*
- * positive if the min_corner of UDATA is
- * greater than or equal the min_corner of
- * RT_KEY.
+ * positive if the min_corner of UDATA is
+ * greater than or equal the min_corner of
+ * RT_KEY.
*
- * zero otherwise. The min_corner of UDATA is
- * not necessarily contained within the address
- * space represented by LT_KEY, but a key that
- * would describe the UDATA min_corner address
- * would fall lexicographically between LT_KEY
- * and RT_KEY.
+ * zero otherwise. The min_corner of UDATA is
+ * not necessarily contained within the address
+ * space represented by LT_KEY, but a key that
+ * would describe the UDATA min_corner address
+ * would fall lexicographically between LT_KEY
+ * and RT_KEY.
*
- * Failure: FAIL (same as UDATA < LT_KEY)
+ * Failure: FAIL (same as UDATA < LT_KEY)
*
*-------------------------------------------------------------------------
*/
@@ -375,23 +385,24 @@ H5D__btree_cmp3(void *_lt_key, void *_udata, void *_rt_key)
} /* end H5D__btree_cmp3() */
/*-------------------------------------------------------------------------
- * Function: H5D__btree_found
- *
- * Purpose: This function is called when the B-tree search engine has
- * found the leaf entry that points to a chunk of storage that
- * contains the beginning of the logical address space
- * represented by UDATA. The LT_KEY is the left key (the one
- * that describes the chunk) and RT_KEY is the right key (the
- * one that describes the next or last chunk).
- *
- * Note: It's possible that the chunk isn't really found. For
- * instance, in a sparse dataset the requested chunk might fall
- * between two stored chunks in which case this function is
- * called with the maximum stored chunk indices less than the
- * requested chunk indices.
- *
- * Return: Non-negative on success with information about the
- * chunk returned through the UDATA argument, if *FOUND is true.
+ * Function: H5D__btree_found
+ *
+ * Purpose: This function is called when the B-tree search engine has
+ * found the leaf entry that points to a chunk of storage that
+ * contains the beginning of the logical address space
+ * represented by UDATA. The LT_KEY is the left key (the one
+ * that describes the chunk) and RT_KEY is the right key (the
+ * one that describes the next or last chunk).
+ *
+ * Note: It's possible that the chunk isn't really found. For
+ * instance, in a sparse dataset the requested chunk might fall
+ * between two stored chunks in which case this function is
+ * called with the maximum stored chunk indices less than the
+ * requested chunk indices.
+ *
+ * Return: Non-negative on success with information about the
+ * chunk returned through the UDATA argument, if *FOUND is
+ * true.
* Negative on failure.
*
*-------------------------------------------------------------------------
@@ -432,14 +443,14 @@ done:
} /* end H5D__btree_found() */
/*-------------------------------------------------------------------------
- * Function: H5D__chunk_disjoint
+ * Function: H5D__chunk_disjoint
*
- * Purpose: Determines if two chunks are disjoint.
+ * Purpose: Determines if two chunks are disjoint.
*
- * Return: Success: false if they are not disjoint.
- * true if they are disjoint.
+ * Return: Success: false if they are not disjoint.
+ * true if they are disjoint.
*
- * Note: Assumes that the chunk offsets are scaled coordinates
+ * Note: Assumes that the chunk offsets are scaled coordinates
*
*-------------------------------------------------------------------------
*/
@@ -466,27 +477,27 @@ done:
} /* end H5D__chunk_disjoint() */
/*-------------------------------------------------------------------------
- * Function: H5D__btree_insert
+ * Function: H5D__btree_insert
*
- * Purpose: This function is called when the B-tree insert engine finds
- * the node to use to insert new data. The UDATA argument
- * points to a struct that describes the logical addresses being
- * added to the file. This function allocates space for the
- * data and returns information through UDATA describing a
- * file chunk to receive (part of) the data.
+ * Purpose: This function is called when the B-tree insert engine finds
+ * the node to use to insert new data. The UDATA argument
+ * points to a struct that describes the logical addresses being
+ * added to the file. This function allocates space for the
+ * data and returns information through UDATA describing a
+ * file chunk to receive (part of) the data.
*
- * The LT_KEY is always the key describing the chunk of file
- * memory at address ADDR. On entry, UDATA describes the logical
- * addresses for which storage is being requested (through the
- * `offset' and `size' fields). On return, UDATA describes the
- * logical addresses contained in a chunk on disk.
+ * The LT_KEY is always the key describing the chunk of file
+ * memory at address ADDR. On entry, UDATA describes the logical
+ * addresses for which storage is being requested (through the
+ * `offset' and `size' fields). On return, UDATA describes the
+ * logical addresses contained in a chunk on disk.
*
- * Return: Success: An insertion command for the caller, one of
- * the H5B_INS_* constants. The address of the
- * new chunk is returned through the NEW_NODE
- * argument.
+ * Return: Success: An insertion command for the caller, one of
+ * the H5B_INS_* constants. The address of the
+ * new chunk is returned through the NEW_NODE
+ * argument.
*
- * Failure: H5B_INS_ERROR
+ * Failure: H5B_INS_ERROR
*
*-------------------------------------------------------------------------
*/
@@ -567,11 +578,11 @@ done:
} /* end H5D__btree_insert() */
/*-------------------------------------------------------------------------
- * Function: H5D__btree_remove
+ * Function: H5D__btree_remove
*
- * Purpose: Removes chunks that are no longer necessary in the B-tree.
+ * Purpose: Removes chunks that are no longer necessary in the B-tree.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
@@ -645,11 +656,11 @@ done:
} /* end H5D__btree_decode_key() */
/*-------------------------------------------------------------------------
- * Function: H5D__btree_encode_key
+ * Function: H5D__btree_encode_key
*
- * Purpose: Encode a key from native format to raw format.
+ * Purpose: Encode a key from native format to raw format.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
@@ -684,11 +695,11 @@ H5D__btree_encode_key(const H5B_shared_t *shared, uint8_t *raw, const void *_key
} /* end H5D__btree_encode_key() */
/*-------------------------------------------------------------------------
- * Function: H5D__btree_debug_key
+ * Function: H5D__btree_debug_key
*
- * Purpose: Prints a key.
+ * Purpose: Prints a key.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
@@ -714,11 +725,11 @@ H5D__btree_debug_key(FILE *stream, int indent, int fwidth, const void *_key, con
} /* end H5D__btree_debug_key() */
/*-------------------------------------------------------------------------
- * Function: H5D__btree_shared_free
+ * Function: H5D__btree_shared_free
*
- * Purpose: Free "local" B-tree shared info
+ * Purpose: Free "local" B-tree shared info
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
@@ -742,11 +753,11 @@ done:
} /* end H5D__btree_shared_free() */
/*-------------------------------------------------------------------------
- * Function: H5D__btree_shared_create
+ * Function: H5D__btree_shared_create
*
- * Purpose: Create & initialize B-tree shared info
+ * Purpose: Create & initialize B-tree shared info
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
@@ -788,11 +799,11 @@ done:
} /* end H5D__btree_shared_create() */
/*-------------------------------------------------------------------------
- * Function: H5D__btree_idx_init
+ * Function: H5D__btree_idx_init
*
- * Purpose: Initialize the indexing information for a dataset.
+ * Purpose: Initialize the indexing information for a dataset.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
@@ -823,17 +834,18 @@ done:
} /* end H5D__btree_idx_init() */
/*-------------------------------------------------------------------------
- * Function: H5D__btree_idx_create
+ * Function: H5D__btree_idx_create
*
- * Purpose: Creates a new indexed-storage B-tree and initializes the
- * layout struct with information about the storage. The
- * struct should be immediately written to the object header.
+ * Purpose: Creates a new indexed-storage B-tree and initializes the
+ * layout struct with information about the storage. The
+ * struct should be immediately written to the object header.
*
- * This function must be called before passing LAYOUT to any of
- * the other indexed storage functions!
+ * This function must be called before passing LAYOUT to any
+ * of the other indexed storage functions!
*
- * Return: Non-negative on success (with the LAYOUT argument initialized
- * and ready to write to an object header). Negative on failure.
+ * Return: Non-negative on success (with the LAYOUT argument
+ * initialized and ready to write to an object header).
+ * Negative on failure.
*
*-------------------------------------------------------------------------
*/
@@ -866,11 +878,73 @@ done:
} /* end H5D__btree_idx_create() */
/*-------------------------------------------------------------------------
- * Function: H5D__btree_idx_is_space_alloc
+ * Function: H5D__btree_idx_open
+ *
+ * Purpose: Opens an existing B-tree. Currently a no-op.
+ *
+ * Return: SUCCEED (can't fail)
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D__btree_idx_open(const H5D_chk_idx_info_t H5_ATTR_UNUSED *idx_info)
+{
+ FUNC_ENTER_PACKAGE_NOERR
+
+ /* NO OP */
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5D__btree_idx_open() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5D__btree_idx_close
*
- * Purpose: Query if space is allocated for index method
+ * Purpose: Closes an existing B-tree. Currently a no-op.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: SUCCEED (can't fail)
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D__btree_idx_close(const H5D_chk_idx_info_t H5_ATTR_UNUSED *idx_info)
+{
+ FUNC_ENTER_PACKAGE_NOERR
+
+ /* NO OP */
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5D__btree_idx_close() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5D__btree_idx_is_open
+ *
+ * Purpose: Query if the index is opened or not
+ *
+ * Return: SUCCEED (can't fail)
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D__btree_idx_is_open(const H5D_chk_idx_info_t *idx_info, bool *is_open)
+{
+ FUNC_ENTER_PACKAGE_NOERR
+
+ assert(idx_info);
+ assert(idx_info->storage);
+ assert(H5D_CHUNK_IDX_BTREE == idx_info->storage->idx_type);
+ assert(is_open);
+
+ *is_open = H5D_BTREE_IDX_IS_OPEN(idx_info);
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5D__btree_idx_is_open() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5D__btree_idx_is_space_alloc
+ *
+ * Purpose: Query if space is allocated for index method
+ *
+ * Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
@@ -886,11 +960,11 @@ H5D__btree_idx_is_space_alloc(const H5O_storage_chunk_t *storage)
} /* end H5D__btree_idx_is_space_alloc() */
/*-------------------------------------------------------------------------
- * Function: H5D__btree_idx_insert
+ * Function: H5D__btree_idx_insert
*
- * Purpose: Insert chunk entry into the indexing structure.
+ * Purpose: Insert chunk entry into the indexing structure.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
@@ -922,13 +996,13 @@ done:
} /* H5D__btree_idx_insert() */
/*-------------------------------------------------------------------------
- * Function: H5D__btree_idx_get_addr
+ * Function: H5D__btree_idx_get_addr
*
- * Purpose: Get the file address of a chunk if file space has been
- * assigned. Save the retrieved information in the udata
- * supplied.
+ * Purpose: Get the file address of a chunk if file space has been
+ * assigned. Save the retrieved information in the udata
+ * supplied.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
@@ -959,14 +1033,34 @@ done:
} /* H5D__btree_idx_get_addr() */
/*-------------------------------------------------------------------------
- * Function: H5D__btree_idx_iterate_cb
+ * Function: H5D__btree_idx_load_metadata
+ *
+ * Purpose: Load additional chunk index metadata beyond the chunk index
+ * itself. Currently a no-op.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D__btree_idx_load_metadata(const H5D_chk_idx_info_t H5_ATTR_UNUSED *idx_info)
+{
+ FUNC_ENTER_PACKAGE_NOERR
+
+ /* NO OP */
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5D__btree_idx_load_metadata() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5D__btree_idx_iterate_cb
*
- * Purpose: Translate the B-tree specific chunk record into a generic
+ * Purpose: Translate the B-tree specific chunk record into a generic
* form and make the callback to the generic chunk callback
* routine.
*
- * Return: Success: Non-negative
- * Failure: Negative
+ * Return: Success: Non-negative
+ * Failure: Negative
*
*-------------------------------------------------------------------------
*/
@@ -1001,12 +1095,12 @@ H5D__btree_idx_iterate_cb(H5F_t H5_ATTR_UNUSED *f, const void *_lt_key, haddr_t
} /* H5D__btree_idx_iterate_cb() */
/*-------------------------------------------------------------------------
- * Function: H5D__btree_idx_iterate
+ * Function: H5D__btree_idx_iterate
*
- * Purpose: Iterate over the chunks in an index, making a callback
+ * Purpose: Iterate over the chunks in an index, making a callback
* for each one.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
@@ -1043,11 +1137,11 @@ H5D__btree_idx_iterate(const H5D_chk_idx_info_t *idx_info, H5D_chunk_cb_func_t c
} /* end H5D__btree_idx_iterate() */
/*-------------------------------------------------------------------------
- * Function: H5D__btree_idx_remove
+ * Function: H5D__btree_idx_remove
*
- * Purpose: Remove chunk from index.
+ * Purpose: Remove chunk from index.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
@@ -1077,13 +1171,13 @@ done:
} /* H5D__btree_idx_remove() */
/*-------------------------------------------------------------------------
- * Function: H5D__btree_idx_delete
+ * Function: H5D__btree_idx_delete
*
- * Purpose: Delete index and raw data storage for entire dataset
+ * Purpose: Delete index and raw data storage for entire dataset
* (i.e. all chunks)
*
- * Return: Success: Non-negative
- * Failure: negative
+ * Return: Success: Non-negative
+ * Failure: negative
*
*-------------------------------------------------------------------------
*/
@@ -1134,11 +1228,11 @@ done:
} /* end H5D__btree_idx_delete() */
/*-------------------------------------------------------------------------
- * Function: H5D__btree_idx_copy_setup
+ * Function: H5D__btree_idx_copy_setup
*
- * Purpose: Set up any necessary information for copying chunks
+ * Purpose: Set up any necessary information for copying chunks
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
@@ -1178,11 +1272,11 @@ done:
} /* end H5D__btree_idx_copy_setup() */
/*-------------------------------------------------------------------------
- * Function: H5D__btree_idx_copy_shutdown
+ * Function: H5D__btree_idx_copy_shutdown
*
- * Purpose: Shutdown any information from copying chunks
+ * Purpose: Shutdown any information from copying chunks
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
@@ -1250,11 +1344,11 @@ done:
} /* end H5D__btree_idx_size() */
/*-------------------------------------------------------------------------
- * Function: H5D__btree_idx_reset
+ * Function: H5D__btree_idx_reset
*
- * Purpose: Reset indexing information.
+ * Purpose: Reset indexing information.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
@@ -1274,11 +1368,11 @@ H5D__btree_idx_reset(H5O_storage_chunk_t *storage, bool reset_addr)
} /* end H5D__btree_idx_reset() */
/*-------------------------------------------------------------------------
- * Function: H5D__btree_idx_dump
+ * Function: H5D__btree_idx_dump
*
- * Purpose: Dump indexing information to a stream.
+ * Purpose: Dump indexing information to a stream.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
@@ -1296,11 +1390,11 @@ H5D__btree_idx_dump(const H5O_storage_chunk_t *storage, FILE *stream)
} /* end H5D__btree_idx_dump() */
/*-------------------------------------------------------------------------
- * Function: H5D__btree_idx_dest
+ * Function: H5D__btree_idx_dest
*
- * Purpose: Release indexing information in memory.
+ * Purpose: Release indexing information in memory.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
@@ -1328,11 +1422,11 @@ done:
} /* end H5D__btree_idx_dest() */
/*-------------------------------------------------------------------------
- * Function: H5D_btree_debug
+ * Function: H5D_btree_debug
*
- * Purpose: Debugs a B-tree node for indexed raw data storage.
+ * Purpose: Debugs a B-tree node for indexed raw data storage.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
diff --git a/src/H5Dbtree2.c b/src/H5Dbtree2.c
index 4da9555..7a26b6d 100644
--- a/src/H5Dbtree2.c
+++ b/src/H5Dbtree2.c
@@ -27,16 +27,18 @@
/* Headers */
/***********/
#include "H5private.h" /* Generic Functions */
-#include "H5Dpkg.h" /* Datasets */
+#include "H5Dpkg.h" /* Datasets */
#include "H5FLprivate.h" /* Free Lists */
#include "H5MFprivate.h" /* File space management */
-#include "H5MMprivate.h" /* Memory management */
-#include "H5VMprivate.h" /* Vector and array functions */
+#include "H5MMprivate.h" /* Memory management */
+#include "H5VMprivate.h" /* Vector and array functions */
/****************/
/* Local Macros */
/****************/
+#define H5D_BT2_IDX_IS_OPEN(idx_info) (NULL != (idx_info)->storage->u.btree2.bt2)
+
/******************/
/* Local Typedefs */
/******************/
@@ -92,7 +94,6 @@ static herr_t H5D__bt2_filt_debug(FILE *stream, int indent, int fwidth, const vo
const void *u_ctx);
/* Helper routine */
-static herr_t H5D__bt2_idx_open(const H5D_chk_idx_info_t *idx_info);
static herr_t H5D__btree2_idx_depend(const H5D_chk_idx_info_t *idx_info);
/* Callback for H5B2_iterate() which is called in H5D__bt2_idx_iterate() */
@@ -114,10 +115,14 @@ static herr_t H5D__bt2_mod_cb(void *_record, void *_op_data, bool *changed);
static herr_t H5D__bt2_idx_init(const H5D_chk_idx_info_t *idx_info, const H5S_t *space,
haddr_t dset_ohdr_addr);
static herr_t H5D__bt2_idx_create(const H5D_chk_idx_info_t *idx_info);
+static herr_t H5D__bt2_idx_open(const H5D_chk_idx_info_t *idx_info);
+static herr_t H5D__bt2_idx_close(const H5D_chk_idx_info_t *idx_info);
+static herr_t H5D__bt2_idx_is_open(const H5D_chk_idx_info_t *idx_info, bool *is_open);
static bool H5D__bt2_idx_is_space_alloc(const H5O_storage_chunk_t *storage);
static herr_t H5D__bt2_idx_insert(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata,
const H5D_t *dset);
static herr_t H5D__bt2_idx_get_addr(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata);
+static herr_t H5D__bt2_idx_load_metadata(const H5D_chk_idx_info_t *idx_info);
static int H5D__bt2_idx_iterate(const H5D_chk_idx_info_t *idx_info, H5D_chunk_cb_func_t chunk_cb,
void *chunk_udata);
static herr_t H5D__bt2_idx_remove(const H5D_chk_idx_info_t *idx_info, H5D_chunk_common_ud_t *udata);
@@ -139,9 +144,13 @@ const H5D_chunk_ops_t H5D_COPS_BT2[1] = {{
true, /* Fixed array indices support SWMR access */
H5D__bt2_idx_init, /* init */
H5D__bt2_idx_create, /* create */
+ H5D__bt2_idx_open, /* open */
+ H5D__bt2_idx_close, /* close */
+ H5D__bt2_idx_is_open, /* is_open */
H5D__bt2_idx_is_space_alloc, /* is_space_alloc */
H5D__bt2_idx_insert, /* insert */
H5D__bt2_idx_get_addr, /* get_addr */
+ H5D__bt2_idx_load_metadata, /* load_metadata */
NULL, /* resize */
H5D__bt2_idx_iterate, /* iterate */
H5D__bt2_idx_remove, /* remove */
@@ -203,8 +212,8 @@ H5FL_ARR_DEFINE_STATIC(uint32_t, H5O_LAYOUT_NDIMS);
*
* Purpose: Create client callback context
*
- * Return: Success: non-NULL
- * Failure: NULL
+ * Return: Success: non-NULL
+ * Failure: NULL
*
*-------------------------------------------------------------------------
*/
@@ -258,8 +267,8 @@ done:
*
* Purpose: Destroy client callback context
*
- * Return: Success: non-negative
- * Failure: negative
+ * Return: Success: non-negative
+ * Failure: negative
*
*-------------------------------------------------------------------------
*/
@@ -286,10 +295,10 @@ H5D__bt2_dst_context(void *_ctx)
* Function: H5D__bt2_store
*
* Purpose: Store native information into record for v2 B-tree
- * (non-filtered)
+ * (non-filtered)
*
- * Return: Success: non-negative
- * Failure: negative
+ * Return: Success: non-negative
+ * Failure: negative
*
*-------------------------------------------------------------------------
*/
@@ -308,8 +317,8 @@ H5D__bt2_store(void *record, const void *_udata)
/*-------------------------------------------------------------------------
* Function: H5D__bt2_compare
*
- * Purpose: Compare two native information records, according to some key
- * (non-filtered)
+ * Purpose: Compare two native information records, according to some
+ * key (non-filtered)
*
* Return: <0 if rec1 < rec2
* =0 if rec1 == rec2
@@ -341,10 +350,10 @@ H5D__bt2_compare(const void *_udata, const void *_rec2, int *result)
* Function: H5D__bt2_unfilt_encode
*
* Purpose: Encode native information into raw form for storing on disk
- * (non-filtered)
+ * (non-filtered)
*
- * Return: Success: non-negative
- * Failure: negative
+ * Return: Success: non-negative
+ * Failure: negative
*
*-------------------------------------------------------------------------
*/
@@ -373,10 +382,10 @@ H5D__bt2_unfilt_encode(uint8_t *raw, const void *_record, void *_ctx)
* Function: H5D__bt2_unfilt_decode
*
* Purpose: Decode raw disk form of record into native form
- * (non-filtered)
+ * (non-filtered)
*
- * Return: Success: non-negative
- * Failure: negative
+ * Return: Success: non-negative
+ * Failure: negative
*
*-------------------------------------------------------------------------
*/
@@ -403,12 +412,12 @@ H5D__bt2_unfilt_decode(const uint8_t *raw, void *_record, void *_ctx)
} /* H5D__bt2_unfilt_decode() */
/*-------------------------------------------------------------------------
- * Function: H5D__bt2_unfilt_debug
+ * Function: H5D__bt2_unfilt_debug
*
- * Purpose: Debug native form of record (non-filtered)
+ * Purpose: Debug native form of record (non-filtered)
*
- * Return: Success: non-negative
- * Failure: negative
+ * Return: Success: non-negative
+ * Failure: negative
*
*-------------------------------------------------------------------------
*/
@@ -440,10 +449,10 @@ H5D__bt2_unfilt_debug(FILE *stream, int indent, int fwidth, const void *_record,
* Function: H5D__bt2_filt_encode
*
* Purpose: Encode native information into raw form for storing on disk
- * (filtered)
+ * (filtered)
*
- * Return: Success: non-negative
- * Failure: negative
+ * Return: Success: non-negative
+ * Failure: negative
*
*-------------------------------------------------------------------------
*/
@@ -473,13 +482,13 @@ H5D__bt2_filt_encode(uint8_t *raw, const void *_record, void *_ctx)
} /* H5D__bt2_filt_encode() */
/*-------------------------------------------------------------------------
- * Function: H5D__bt2_filt_decode
+ * Function: H5D__bt2_filt_decode
*
- * Purpose: Decode raw disk form of record into native form
- * (filtered)
+ * Purpose: Decode raw disk form of record into native form
+ * (filtered)
*
- * Return: Success: non-negative
- * Failure: negative
+ * Return: Success: non-negative
+ * Failure: negative
*
*-------------------------------------------------------------------------
*/
@@ -511,12 +520,12 @@ H5D__bt2_filt_decode(const uint8_t *raw, void *_record, void *_ctx)
} /* H5D__bt2_filt_decode() */
/*-------------------------------------------------------------------------
- * Function: H5D__bt2_filt_debug
+ * Function: H5D__bt2_filt_debug
*
- * Purpose: Debug native form of record (filtered)
+ * Purpose: Debug native form of record (filtered)
*
- * Return: Success: non-negative
- * Failure: negative
+ * Return: Success: non-negative
+ * Failure: negative
*
*-------------------------------------------------------------------------
*/
@@ -570,13 +579,13 @@ H5D__bt2_idx_init(const H5D_chk_idx_info_t H5_ATTR_UNUSED *idx_info, const H5S_t
} /* end H5D__bt2_idx_init() */
/*-------------------------------------------------------------------------
- * Function: H5D__btree2_idx_depend
+ * Function: H5D__btree2_idx_depend
*
- * Purpose: Create flush dependency between v2 B-tree and dataset's
+ * Purpose: Create flush dependency between v2 B-tree and dataset's
* object header.
*
- * Return: Success: non-negative
- * Failure: negative
+ * Return: Success: non-negative
+ * Failure: negative
*
*-------------------------------------------------------------------------
*/
@@ -629,63 +638,9 @@ done:
} /* end H5D__btree2_idx_depend() */
/*-------------------------------------------------------------------------
- * Function: H5D__bt2_idx_open()
- *
- * Purpose: Opens an existing v2 B-tree.
- *
- * Note: This information is passively initialized from each index
- * operation callback because those abstract chunk index operations
- * are designed to work with the v2 B-tree chunk indices also,
- * which don't require an 'open' for the data structure.
+ * Function: H5D__bt2_idx_create
*
- * Return: Success: non-negative
- * Failure: negative
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5D__bt2_idx_open(const H5D_chk_idx_info_t *idx_info)
-{
- H5D_bt2_ctx_ud_t u_ctx; /* user data for creating context */
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_PACKAGE
-
- /* Check args */
- assert(idx_info);
- assert(idx_info->f);
- assert(idx_info->pline);
- assert(idx_info->layout);
- assert(H5D_CHUNK_IDX_BT2 == idx_info->layout->idx_type);
- assert(idx_info->storage);
- assert(H5_addr_defined(idx_info->storage->idx_addr));
- assert(NULL == idx_info->storage->u.btree2.bt2);
-
- /* Set up the user data */
- u_ctx.f = idx_info->f;
- u_ctx.ndims = idx_info->layout->ndims - 1;
- u_ctx.chunk_size = idx_info->layout->size;
- u_ctx.dim = idx_info->layout->dim;
-
- /* Open v2 B-tree for the chunk index */
- if (NULL ==
- (idx_info->storage->u.btree2.bt2 = H5B2_open(idx_info->f, idx_info->storage->idx_addr, &u_ctx)))
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't open v2 B-tree for tracking chunked dataset");
-
- /* Check for SWMR writes to the file */
- if (H5F_INTENT(idx_info->f) & H5F_ACC_SWMR_WRITE)
- if (H5D__btree2_idx_depend(idx_info) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTDEPEND, FAIL,
- "unable to create flush dependency on object header");
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D__bt2_idx_open() */
-
-/*-------------------------------------------------------------------------
- * Function: H5D__bt2_idx_create
- *
- * Purpose: Create the v2 B-tree for tracking dataset chunks
+ * Purpose: Create the v2 B-tree for tracking dataset chunks
*
* Return: SUCCEED/FAIL
*
@@ -758,11 +713,120 @@ done:
} /* end H5D__bt2_idx_create() */
/*-------------------------------------------------------------------------
- * Function: H5D__bt2_idx_is_space_alloc
+ * Function: H5D__bt2_idx_open()
+ *
+ * Purpose: Opens an existing v2 B-tree.
*
- * Purpose: Query if space is allocated for index method
+ * Note: This information is passively initialized from each index
+ * operation callback because those abstract chunk index
+ * operations are designed to work with the v2 B-tree chunk
+ * indices also, which don't require an 'open' for the data
+ * structure.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D__bt2_idx_open(const H5D_chk_idx_info_t *idx_info)
+{
+ H5D_bt2_ctx_ud_t u_ctx; /* user data for creating context */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ /* Check args */
+ assert(idx_info);
+ assert(idx_info->f);
+ assert(idx_info->pline);
+ assert(idx_info->layout);
+ assert(H5D_CHUNK_IDX_BT2 == idx_info->layout->idx_type);
+ assert(idx_info->storage);
+ assert(H5_addr_defined(idx_info->storage->idx_addr));
+ assert(NULL == idx_info->storage->u.btree2.bt2);
+
+ /* Set up the user data */
+ u_ctx.f = idx_info->f;
+ u_ctx.ndims = idx_info->layout->ndims - 1;
+ u_ctx.chunk_size = idx_info->layout->size;
+ u_ctx.dim = idx_info->layout->dim;
+
+ /* Open v2 B-tree for the chunk index */
+ if (NULL ==
+ (idx_info->storage->u.btree2.bt2 = H5B2_open(idx_info->f, idx_info->storage->idx_addr, &u_ctx)))
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't open v2 B-tree for tracking chunked dataset");
+
+ /* Check for SWMR writes to the file */
+ if (H5F_INTENT(idx_info->f) & H5F_ACC_SWMR_WRITE)
+ if (H5D__btree2_idx_depend(idx_info) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTDEPEND, FAIL,
+ "unable to create flush dependency on object header");
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D__bt2_idx_open() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5D__bt2_idx_close()
+ *
+ * Purpose: Closes an existing v2 B-tree.
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D__bt2_idx_close(const H5D_chk_idx_info_t *idx_info)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ assert(idx_info);
+ assert(idx_info->storage);
+ assert(H5D_CHUNK_IDX_BT2 == idx_info->storage->idx_type);
+ assert(idx_info->storage->u.btree2.bt2);
+
+ if (H5B2_close(idx_info->storage->u.btree2.bt2) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "unable to close v2 B-tree");
+ idx_info->storage->u.btree2.bt2 = NULL;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D__bt2_idx_close() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5D__bt2_idx_is_open
+ *
+ * Purpose: Query if the index is opened or not
+ *
+ * Return: SUCCEED (can't fail)
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D__bt2_idx_is_open(const H5D_chk_idx_info_t *idx_info, bool *is_open)
+{
+ FUNC_ENTER_PACKAGE_NOERR
+
+ assert(idx_info);
+ assert(idx_info->storage);
+ assert(H5D_CHUNK_IDX_BT2 == idx_info->storage->idx_type);
+ assert(is_open);
+
+ *is_open = H5D_BT2_IDX_IS_OPEN(idx_info);
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5D__bt2_idx_is_open() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5D__bt2_idx_is_space_alloc
+ *
+ * Purpose: Query if space is allocated for index method
+ *
+ * Return: true/false
*
*-------------------------------------------------------------------------
*/
@@ -778,14 +842,14 @@ H5D__bt2_idx_is_space_alloc(const H5O_storage_chunk_t *storage)
} /* end H5D__bt2_idx_is_space_alloc() */
/*-------------------------------------------------------------------------
- * Function: H5D__bt2_mod_cb
+ * Function: H5D__bt2_mod_cb
*
- * Purpose: Modify record for dataset chunk when it is found in a v2 B-tree.
- * This is the callback for H5B2_update() which is called in
- * H5D__bt2_idx_insert().
+ * Purpose: Modify record for dataset chunk when it is found in a v2
+ * B-tree. This is the callback for H5B2_update() which is
+ * called in H5D__bt2_idx_insert().
*
- * Return: Success: non-negative
- * Failure: negative
+ * Return: Success: non-negative
+ * Failure: negative
*
*-------------------------------------------------------------------------
*/
@@ -817,18 +881,21 @@ H5D__bt2_mod_cb(void *_record, void *_op_data, bool *changed)
} /* end H5D__bt2_mod_cb() */
/*-------------------------------------------------------------------------
- * Function: H5D__bt2_idx_insert
+ * Function: H5D__bt2_idx_insert
+ *
+ * Purpose: Insert chunk address into the indexing structure.
+ * A non-filtered chunk:
+ * Should not exist
+ * Allocate the chunk and pass chunk address back up
+ * A filtered chunk:
+ * If it was not found, create the chunk and pass chunk
+ * address back up
+ * If it was found but its size changed, reallocate the chunk
+ * and pass chunk address back up
+ * If it was found but its size was the same, pass chunk
+ * address back up
*
- * Purpose: Insert chunk address into the indexing structure.
- * A non-filtered chunk:
- * Should not exist
- * Allocate the chunk and pass chunk address back up
- * A filtered chunk:
- * If it was not found, create the chunk and pass chunk address back up
- * If it was found but its size changed, reallocate the chunk and pass chunk address back up
- * If it was found but its size was the same, pass chunk address back up
- *
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
@@ -854,7 +921,7 @@ H5D__bt2_idx_insert(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata,
assert(H5_addr_defined(udata->chunk_block.offset));
/* Check if the v2 B-tree is open yet */
- if (NULL == idx_info->storage->u.btree2.bt2) {
+ if (!H5D_BT2_IDX_IS_OPEN(idx_info)) {
/* Open existing v2 B-tree */
if (H5D__bt2_idx_open(idx_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "can't open v2 B-tree");
@@ -889,14 +956,14 @@ done:
} /* H5D__bt2_idx_insert() */
/*-------------------------------------------------------------------------
- * Function: H5D__bt2_found_cb
+ * Function: H5D__bt2_found_cb
*
- * Purpose: Retrieve record for dataset chunk when it is found in a v2 B-tree.
- * This is the callback for H5B2_find() which is called in
- * H5D__bt2_idx_get_addr() and H5D__bt2_idx_insert().
+ * Purpose: Retrieve record for dataset chunk when it is found in a v2
+ * B-tree. This is the callback for H5B2_find() which is called
+ * in H5D__bt2_idx_get_addr() and H5D__bt2_idx_insert().
*
- * Return: Success: non-negative
- * Failure: negative
+ * Return: Success: non-negative
+ * Failure: negative
*
*-------------------------------------------------------------------------
*/
@@ -911,13 +978,13 @@ H5D__bt2_found_cb(const void *nrecord, void *op_data)
} /* H5D__bt2_found_cb() */
/*-------------------------------------------------------------------------
- * Function: H5D__bt2_idx_get_addr
+ * Function: H5D__bt2_idx_get_addr
*
- * Purpose: Get the file address of a chunk if file space has been
- * assigned. Save the retrieved information in the udata
- * supplied.
+ * Purpose: Get the file address of a chunk if file space has been
+ * assigned. Save the retrieved information in the udata
+ * supplied.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
@@ -944,7 +1011,7 @@ H5D__bt2_idx_get_addr(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata)
assert(udata);
/* Check if the v2 B-tree is open yet */
- if (NULL == idx_info->storage->u.btree2.bt2) {
+ if (!H5D_BT2_IDX_IS_OPEN(idx_info)) {
/* Open existing v2 B-tree */
if (H5D__bt2_idx_open(idx_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "can't open v2 B-tree");
@@ -1003,16 +1070,59 @@ done:
} /* H5D__bt2_idx_get_addr() */
/*-------------------------------------------------------------------------
- * Function: H5D__bt2_idx_iterate_cb
+ * Function: H5D__bt2_idx_load_metadata
+ *
+ * Purpose: Load additional chunk index metadata beyond the chunk index
+ * itself.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D__bt2_idx_load_metadata(const H5D_chk_idx_info_t H5_ATTR_UNUSED *idx_info)
+{
+ H5D_chunk_ud_t chunk_ud;
+ hsize_t scaled[H5O_LAYOUT_NDIMS] = {0};
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_PACKAGE
+
+ /*
+ * After opening a dataset that uses a v2 Btree, the root
+ * node will generally not be read in until an element is
+ * looked up for the first time. Since there isn't currently
+ * a good way of controlling that explicitly, perform a fake
+ * lookup of a chunk to cause it to be read in.
+ */
+ chunk_ud.common.layout = idx_info->layout;
+ chunk_ud.common.storage = idx_info->storage;
+ chunk_ud.common.scaled = scaled;
+
+ chunk_ud.chunk_block.offset = HADDR_UNDEF;
+ chunk_ud.chunk_block.length = 0;
+ chunk_ud.filter_mask = 0;
+ chunk_ud.new_unfilt_chunk = false;
+ chunk_ud.idx_hint = UINT_MAX;
+
+ if (H5D__bt2_idx_get_addr(idx_info, &chunk_ud) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't load v2 B-tree root node");
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5D__bt2_idx_load_metadata() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5D__bt2_idx_iterate_cb
*
- * Purpose: Translate the B-tree specific chunk record into a generic
+ * Purpose: Translate the B-tree specific chunk record into a generic
* form and make the callback to the generic chunk callback
* routine.
- * This is the callback for H5B2_iterate() which is called in
- * H5D__bt2_idx_iterate().
+ * This is the callback for H5B2_iterate() which is called in
+ * H5D__bt2_idx_iterate().
*
- * Return: Success: Non-negative
- * Failure: Negative
+ * Return: Success: Non-negative
+ * Failure: Negative
*
*-------------------------------------------------------------------------
*/
@@ -1033,12 +1143,12 @@ H5D__bt2_idx_iterate_cb(const void *_record, void *_udata)
} /* H5D__bt2_idx_iterate_cb() */
/*-------------------------------------------------------------------------
- * Function: H5D__bt2_idx_iterate
+ * Function: H5D__bt2_idx_iterate
*
- * Purpose: Iterate over the chunks in an index, making a callback
+ * Purpose: Iterate over the chunks in an index, making a callback
* for each one.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
@@ -1062,7 +1172,7 @@ H5D__bt2_idx_iterate(const H5D_chk_idx_info_t *idx_info, H5D_chunk_cb_func_t chu
assert(chunk_udata);
/* Check if the v2 B-tree is open yet */
- if (NULL == idx_info->storage->u.btree2.bt2) {
+ if (!H5D_BT2_IDX_IS_OPEN(idx_info)) {
/* Open existing v2 B-tree */
if (H5D__bt2_idx_open(idx_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "can't open v2 B-tree");
@@ -1087,15 +1197,16 @@ done:
} /* end H5D__bt2_idx_iterate() */
/*-------------------------------------------------------------------------
- * Function: H5D__bt2_remove_cb()
+ * Function: H5D__bt2_remove_cb()
*
- * Purpose: Free space for 'dataset chunk' object as v2 B-tree
- * is being deleted or v2 B-tree node is removed.
- * This is the callback for H5B2_remove() and H5B2_delete() which
- * which are called in H5D__bt2_idx_remove() and H5D__bt2_idx_delete().
+ * Purpose: Free space for 'dataset chunk' object as v2 B-tree
+ * is being deleted or v2 B-tree node is removed.
+ * This is the callback for H5B2_remove() and H5B2_delete()
+ * which are called in H5D__bt2_idx_remove() and
+ * H5D__bt2_idx_delete().
*
- * Return: Success: non-negative
- * Failure: negative
+ * Return: Success: non-negative
+ * Failure: negative
*
*-------------------------------------------------------------------------
*/
@@ -1121,11 +1232,11 @@ done:
} /* H5D__bt2_remove_cb() */
/*-------------------------------------------------------------------------
- * Function: H5D__bt2_idx_remove
+ * Function: H5D__bt2_idx_remove
*
- * Purpose: Remove chunk from index.
+ * Purpose: Remove chunk from index.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
@@ -1149,7 +1260,7 @@ H5D__bt2_idx_remove(const H5D_chk_idx_info_t *idx_info, H5D_chunk_common_ud_t *u
assert(udata);
/* Check if the v2 B-tree is open yet */
- if (NULL == idx_info->storage->u.btree2.bt2) {
+ if (!H5D_BT2_IDX_IS_OPEN(idx_info)) {
/* Open existing v2 B-tree */
if (H5D__bt2_idx_open(idx_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "can't open v2 B-tree");
@@ -1180,13 +1291,13 @@ done:
} /* H5D__bt2_idx_remove() */
/*-------------------------------------------------------------------------
- * Function: H5D__bt2_idx_delete
+ * Function: H5D__bt2_idx_delete
*
- * Purpose: Delete index and raw data storage for entire dataset
+ * Purpose: Delete index and raw data storage for entire dataset
* (i.e. all chunks)
*
- * Return: Success: Non-negative
- * Failure: negative
+ * Return: Success: Non-negative
+ * Failure: negative
*
*-------------------------------------------------------------------------
*/
@@ -1233,11 +1344,11 @@ done:
} /* end H5D__bt2_idx_delete() */
/*-------------------------------------------------------------------------
- * Function: H5D__bt2_idx_copy_setup
+ * Function: H5D__bt2_idx_copy_setup
*
- * Purpose: Set up any necessary information for copying chunks
+ * Purpose: Set up any necessary information for copying chunks
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
@@ -1264,7 +1375,7 @@ H5D__bt2_idx_copy_setup(const H5D_chk_idx_info_t *idx_info_src, const H5D_chk_id
assert(!H5_addr_defined(idx_info_dst->storage->idx_addr));
/* Check if the source v2 B-tree is open yet */
- if (NULL == idx_info_src->storage->u.btree2.bt2)
+ if (!H5D_BT2_IDX_IS_OPEN(idx_info_src))
if (H5D__bt2_idx_open(idx_info_src) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "can't open v2 B-tree");
@@ -1284,11 +1395,11 @@ done:
} /* end H5D__bt2_idx_copy_setup() */
/*-------------------------------------------------------------------------
- * Function: H5D__bt2_idx_copy_shutdown
+ * Function: H5D__bt2_idx_copy_shutdown
*
- * Purpose: Shutdown any information from copying chunks
+ * Purpose: Shutdown any information from copying chunks
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
@@ -1324,8 +1435,8 @@ done:
*
* Purpose: Retrieve the amount of index storage for chunked dataset
*
- * Return: Success: Non-negative
- * Failure: negative
+ * Return: Success: Non-negative
+ * Failure: negative
*
*-------------------------------------------------------------------------
*/
@@ -1355,23 +1466,23 @@ H5D__bt2_idx_size(const H5D_chk_idx_info_t *idx_info, hsize_t *index_size)
/* Get v2 B-tree size for indexing chunked dataset */
if (H5B2_size(bt2_cdset, index_size) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't retrieve v2 B-tree storage info for chunked dataset");
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL,
+ "can't retrieve v2 B-tree storage info for chunked dataset");
done:
/* Close v2 B-tree index */
- if (bt2_cdset && H5B2_close(bt2_cdset) < 0)
- HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "can't close v2 B-tree for tracking chunked dataset");
- idx_info->storage->u.btree2.bt2 = NULL;
+ if (H5D__bt2_idx_close(idx_info) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "can't close v2 B-tree for tracking chunked dataset");
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D__bt2_idx_size() */
/*-------------------------------------------------------------------------
- * Function: H5D__bt2_idx_reset
+ * Function: H5D__bt2_idx_reset
*
- * Purpose: Reset indexing information.
+ * Purpose: Reset indexing information.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
@@ -1392,11 +1503,11 @@ H5D__bt2_idx_reset(H5O_storage_chunk_t *storage, bool reset_addr)
} /* end H5D__bt2_idx_reset() */
/*-------------------------------------------------------------------------
- * Function: H5D__bt2_idx_dump
+ * Function: H5D__bt2_idx_dump
*
- * Purpose: Dump indexing information to a stream.
+ * Purpose: Dump indexing information to a stream.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
@@ -1415,11 +1526,11 @@ H5D__bt2_idx_dump(const H5O_storage_chunk_t *storage, FILE *stream)
} /* end H5D__bt2_idx_dump() */
/*-------------------------------------------------------------------------
- * Function: H5D__bt2_idx_dest
+ * Function: H5D__bt2_idx_dest
*
- * Purpose: Release indexing information in memory.
+ * Purpose: Release indexing information in memory.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
@@ -1436,16 +1547,14 @@ H5D__bt2_idx_dest(const H5D_chk_idx_info_t *idx_info)
assert(idx_info->storage);
/* Check if the v2-btree is open */
- if (idx_info->storage->u.btree2.bt2) {
-
+ if (H5D_BT2_IDX_IS_OPEN(idx_info)) {
/* Patch the top level file pointer contained in bt2 if needed */
if (H5B2_patch_file(idx_info->storage->u.btree2.bt2, idx_info->f) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "can't patch v2 B-tree file pointer");
/* Close v2 B-tree */
- if (H5B2_close(idx_info->storage->u.btree2.bt2) < 0)
+ if (H5D__bt2_idx_close(idx_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "can't close v2 B-tree");
- idx_info->storage->u.btree2.bt2 = NULL;
} /* end if */
done:
diff --git a/src/H5Dchunk.c b/src/H5Dchunk.c
index 9f4bd90..41d774d 100644
--- a/src/H5Dchunk.c
+++ b/src/H5Dchunk.c
@@ -1124,18 +1124,33 @@ H5D__chunk_io_init(H5D_io_info_t *io_info, H5D_dset_io_info_t *dinfo)
if (H5F_SHARED_HAS_FEATURE(io_info->f_sh, H5FD_FEAT_HAS_MPI) &&
H5F_shared_get_coll_metadata_reads(io_info->f_sh) &&
H5D__chunk_is_space_alloc(&dataset->shared->layout.storage)) {
- H5D_chunk_ud_t udata;
- hsize_t scaled[H5O_LAYOUT_NDIMS] = {0};
+ H5O_storage_chunk_t *sc = &(dataset->shared->layout.storage.u.chunk);
+ H5D_chk_idx_info_t idx_info;
+ bool index_is_open;
+
+ idx_info.f = dataset->oloc.file;
+ idx_info.pline = &dataset->shared->dcpl_cache.pline;
+ idx_info.layout = &dataset->shared->layout.u.chunk;
+ idx_info.storage = sc;
+
+ assert(sc && sc->ops && sc->ops->is_open);
+ if (sc->ops->is_open(&idx_info, &index_is_open) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to check if dataset chunk index is open");
+
+ if (!index_is_open) {
+ assert(sc->ops->open);
+ if (sc->ops->open(&idx_info) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to open dataset chunk index");
+ }
/*
- * TODO: Until the dataset chunk index callback structure has
- * callbacks for checking if an index is opened and also for
- * directly opening the index, the following fake chunk lookup
- * serves the purpose of forcing a chunk index open operation
- * on all ranks
+ * Load any other chunk index metadata that we can,
+ * such as fixed array data blocks, while we know all
+ * MPI ranks will do so with collective metadata reads
+ * enabled
*/
- if (H5D__chunk_lookup(dataset, scaled, &udata) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to collectively open dataset chunk index");
+ if (sc->ops->load_metadata && sc->ops->load_metadata(&idx_info) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to load additional chunk index metadata");
}
#endif
@@ -3827,15 +3842,29 @@ H5D__chunk_lookup(const H5D_t *dset, const hsize_t *scaled, H5D_chunk_ud_t *udat
idx_info.storage = sc;
#ifdef H5_HAVE_PARALLEL
- /* Disable collective metadata read for chunk indexes as it is
- * highly unlikely that users would read the same chunks from all
- * processes.
- */
if (H5F_HAS_FEATURE(idx_info.f, H5FD_FEAT_HAS_MPI)) {
- md_reads_file_flag = H5P_FORCE_FALSE;
- md_reads_context_flag = false;
- H5F_set_coll_metadata_reads(idx_info.f, &md_reads_file_flag, &md_reads_context_flag);
- restore_md_reads_state = true;
+ /* Disable collective metadata read for chunk indexes as it is
+ * highly unlikely that users would read the same chunks from all
+ * processes.
+ */
+ if (H5F_get_coll_metadata_reads(idx_info.f)) {
+#ifndef NDEBUG
+ bool index_is_open;
+
+ /*
+ * The dataset's chunk index should be open at this point.
+ * Otherwise, we will end up reading it in independently,
+ * which may not be desired.
+ */
+ sc->ops->is_open(&idx_info, &index_is_open);
+ assert(index_is_open);
+#endif
+
+ md_reads_file_flag = H5P_FORCE_FALSE;
+ md_reads_context_flag = false;
+ H5F_set_coll_metadata_reads(idx_info.f, &md_reads_file_flag, &md_reads_context_flag);
+ restore_md_reads_state = true;
+ }
}
#endif /* H5_HAVE_PARALLEL */
diff --git a/src/H5Dearray.c b/src/H5Dearray.c
index c713b6f..965eaac 100644
--- a/src/H5Dearray.c
+++ b/src/H5Dearray.c
@@ -26,19 +26,21 @@
/***********/
/* Headers */
/***********/
-#include "H5private.h" /* Generic Functions */
-#include "H5Dpkg.h" /* Datasets */
-#include "H5Eprivate.h" /* Error handling */
-#include "H5EAprivate.h" /* Extensible arrays */
+#include "H5private.h" /* Generic Functions */
+#include "H5Dpkg.h" /* Datasets */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5EAprivate.h" /* Extensible arrays */
#include "H5FLprivate.h" /* Free Lists */
-#include "H5MFprivate.h" /* File space management */
-#include "H5MMprivate.h" /* Memory management */
-#include "H5VMprivate.h" /* Vector functions */
+#include "H5MFprivate.h" /* File space management */
+#include "H5MMprivate.h" /* Memory management */
+#include "H5VMprivate.h" /* Vector functions */
/****************/
/* Local Macros */
/****************/
+#define H5D_EARRAY_IDX_IS_OPEN(idx_info) (NULL != (idx_info)->storage->u.earray.ea)
+
/* Value to fill unset array elements with */
#define H5D_EARRAY_FILL HADDR_UNDEF
#define H5D_EARRAY_FILT_FILL \
@@ -106,10 +108,14 @@ static herr_t H5D__earray_filt_debug(FILE *stream, int indent, int fwidth, hsize
static herr_t H5D__earray_idx_init(const H5D_chk_idx_info_t *idx_info, const H5S_t *space,
haddr_t dset_ohdr_addr);
static herr_t H5D__earray_idx_create(const H5D_chk_idx_info_t *idx_info);
+static herr_t H5D__earray_idx_open(const H5D_chk_idx_info_t *idx_info);
+static herr_t H5D__earray_idx_close(const H5D_chk_idx_info_t *idx_info);
+static herr_t H5D__earray_idx_is_open(const H5D_chk_idx_info_t *idx_info, bool *is_open);
static bool H5D__earray_idx_is_space_alloc(const H5O_storage_chunk_t *storage);
static herr_t H5D__earray_idx_insert(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata,
const H5D_t *dset);
static herr_t H5D__earray_idx_get_addr(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata);
+static herr_t H5D__earray_idx_load_metadata(const H5D_chk_idx_info_t *idx_info);
static herr_t H5D__earray_idx_resize(H5O_layout_chunk_t *layout);
static int H5D__earray_idx_iterate(const H5D_chk_idx_info_t *idx_info, H5D_chunk_cb_func_t chunk_cb,
void *chunk_udata);
@@ -125,7 +131,6 @@ static herr_t H5D__earray_idx_dump(const H5O_storage_chunk_t *storage, FILE *str
static herr_t H5D__earray_idx_dest(const H5D_chk_idx_info_t *idx_info);
/* Generic extensible array routines */
-static herr_t H5D__earray_idx_open(const H5D_chk_idx_info_t *idx_info);
static herr_t H5D__earray_idx_depend(const H5D_chk_idx_info_t *idx_info);
/*********************/
@@ -137,9 +142,13 @@ const H5D_chunk_ops_t H5D_COPS_EARRAY[1] = {{
true, /* Extensible array indices support SWMR access */
H5D__earray_idx_init, /* init */
H5D__earray_idx_create, /* create */
+ H5D__earray_idx_open, /* open */
+ H5D__earray_idx_close, /* close */
+ H5D__earray_idx_is_open, /* is_open */
H5D__earray_idx_is_space_alloc, /* is_space_alloc */
H5D__earray_idx_insert, /* insert */
H5D__earray_idx_get_addr, /* get_addr */
+ H5D__earray_idx_load_metadata, /* load_metadata */
H5D__earray_idx_resize, /* resize */
H5D__earray_idx_iterate, /* iterate */
H5D__earray_idx_remove, /* remove */
@@ -270,10 +279,10 @@ H5D__earray_dst_context(void *_ctx)
/*-------------------------------------------------------------------------
* Function: H5D__earray_fill
*
- * Purpose: Fill "missing elements" in block of elements
+ * Purpose: Fill "missing elements" in block of elements
*
- * Return: Success: non-negative
- * Failure: negative
+ * Return: Success: non-negative
+ * Failure: negative
*
*-------------------------------------------------------------------------
*/
@@ -706,59 +715,6 @@ done:
} /* end H5D__earray_idx_depend() */
/*-------------------------------------------------------------------------
- * Function: H5D__earray_idx_open
- *
- * Purpose: Opens an existing extensible array.
- *
- * Note: This information is passively initialized from each index
- * operation callback because those abstract chunk index operations
- * are designed to work with the v1 B-tree chunk indices also,
- * which don't require an 'open' for the data structure.
- *
- * Return: Success: non-negative
- * Failure: negative
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5D__earray_idx_open(const H5D_chk_idx_info_t *idx_info)
-{
- H5D_earray_ctx_ud_t udata; /* User data for extensible array open call */
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_PACKAGE
-
- /* Check args */
- assert(idx_info);
- assert(idx_info->f);
- assert(idx_info->pline);
- assert(idx_info->layout);
- assert(H5D_CHUNK_IDX_EARRAY == idx_info->layout->idx_type);
- assert(idx_info->storage);
- assert(H5D_CHUNK_IDX_EARRAY == idx_info->storage->idx_type);
- assert(H5_addr_defined(idx_info->storage->idx_addr));
- assert(NULL == idx_info->storage->u.earray.ea);
-
- /* Set up the user data */
- udata.f = idx_info->f;
- udata.chunk_size = idx_info->layout->size;
-
- /* Open the extensible array for the chunk index */
- if (NULL ==
- (idx_info->storage->u.earray.ea = H5EA_open(idx_info->f, idx_info->storage->idx_addr, &udata)))
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't open extensible array");
-
- /* Check for SWMR writes to the file */
- if (H5F_INTENT(idx_info->f) & H5F_ACC_SWMR_WRITE)
- if (H5D__earray_idx_depend(idx_info) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTDEPEND, FAIL,
- "unable to create flush dependency on object header");
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D__earray_idx_open() */
-
-/*-------------------------------------------------------------------------
* Function: H5D__earray_idx_init
*
* Purpose: Initialize the indexing information for a dataset.
@@ -906,11 +862,119 @@ done:
} /* end H5D__earray_idx_create() */
/*-------------------------------------------------------------------------
+ * Function: H5D__earray_idx_open
+ *
+ * Purpose: Opens an existing extensible array.
+ *
+ * Note: This information is passively initialized from each index
+ * operation callback because those abstract chunk index
+ * operations are designed to work with the v1 B-tree chunk
+ * indices also, which don't require an 'open' for the data
+ * structure.
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D__earray_idx_open(const H5D_chk_idx_info_t *idx_info)
+{
+ H5D_earray_ctx_ud_t udata; /* User data for extensible array open call */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ /* Check args */
+ assert(idx_info);
+ assert(idx_info->f);
+ assert(idx_info->pline);
+ assert(idx_info->layout);
+ assert(H5D_CHUNK_IDX_EARRAY == idx_info->layout->idx_type);
+ assert(idx_info->storage);
+ assert(H5D_CHUNK_IDX_EARRAY == idx_info->storage->idx_type);
+ assert(H5_addr_defined(idx_info->storage->idx_addr));
+ assert(NULL == idx_info->storage->u.earray.ea);
+
+ /* Set up the user data */
+ udata.f = idx_info->f;
+ udata.chunk_size = idx_info->layout->size;
+
+ /* Open the extensible array for the chunk index */
+ if (NULL ==
+ (idx_info->storage->u.earray.ea = H5EA_open(idx_info->f, idx_info->storage->idx_addr, &udata)))
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't open extensible array");
+
+ /* Check for SWMR writes to the file */
+ if (H5F_INTENT(idx_info->f) & H5F_ACC_SWMR_WRITE)
+ if (H5D__earray_idx_depend(idx_info) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTDEPEND, FAIL,
+ "unable to create flush dependency on object header");
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D__earray_idx_open() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5D__earray_idx_close
+ *
+ * Purpose: Closes an existing extensible array.
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D__earray_idx_close(const H5D_chk_idx_info_t *idx_info)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ assert(idx_info);
+ assert(idx_info->storage);
+ assert(H5D_CHUNK_IDX_EARRAY == idx_info->storage->idx_type);
+ assert(idx_info->storage->u.earray.ea);
+
+ if (H5EA_close(idx_info->storage->u.earray.ea) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "unable to close extensible array");
+ idx_info->storage->u.earray.ea = NULL;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D__earray_idx_close() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5D__earray_idx_is_open
+ *
+ * Purpose: Query if the index is opened or not
+ *
+ * Return: SUCCEED (can't fail)
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D__earray_idx_is_open(const H5D_chk_idx_info_t *idx_info, bool *is_open)
+{
+ FUNC_ENTER_PACKAGE_NOERR
+
+ assert(idx_info);
+ assert(idx_info->storage);
+ assert(H5D_CHUNK_IDX_EARRAY == idx_info->storage->idx_type);
+ assert(is_open);
+
+ *is_open = H5D_EARRAY_IDX_IS_OPEN(idx_info);
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5D__earray_idx_is_open() */
+
+/*-------------------------------------------------------------------------
* Function: H5D__earray_idx_is_space_alloc
*
* Purpose: Query if space is allocated for index method
*
- * Return: Non-negative on success/Negative on failure
+ * Return: true/false
*
*-------------------------------------------------------------------------
*/
@@ -953,7 +1017,7 @@ H5D__earray_idx_insert(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata
assert(udata);
/* Check if the extensible array is open yet */
- if (NULL == idx_info->storage->u.earray.ea) {
+ if (!H5D_EARRAY_IDX_IS_OPEN(idx_info)) {
/* Open the extensible array in file */
if (H5D__earray_idx_open(idx_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "can't open extensible array");
@@ -1021,7 +1085,7 @@ H5D__earray_idx_get_addr(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *uda
assert(udata);
/* Check if the extensible array is open yet */
- if (NULL == idx_info->storage->u.earray.ea) {
+ if (!H5D_EARRAY_IDX_IS_OPEN(idx_info)) {
/* Open the extensible array in file */
if (H5D__earray_idx_open(idx_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "can't open extensible array");
@@ -1087,6 +1151,51 @@ done:
} /* H5D__earray_idx_get_addr() */
/*-------------------------------------------------------------------------
+ * Function: H5D__earray_idx_load_metadata
+ *
+ * Purpose: Load additional chunk index metadata beyond the chunk index
+ * itself.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D__earray_idx_load_metadata(const H5D_chk_idx_info_t *idx_info)
+{
+ H5D_chunk_ud_t chunk_ud;
+ hsize_t scaled[H5O_LAYOUT_NDIMS] = {0};
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_PACKAGE
+
+ /*
+ * After opening a dataset that uses an extensible array,
+ * the extensible array header index block will generally
+ * not be read in until an element is looked up for the
+ * first time. Since there isn't currently a good way of
+ * controlling that explicitly, perform a fake lookup of
+ * a chunk to cause it to be read in or created if it
+ * doesn't exist yet.
+ */
+ chunk_ud.common.layout = idx_info->layout;
+ chunk_ud.common.storage = idx_info->storage;
+ chunk_ud.common.scaled = scaled;
+
+ chunk_ud.chunk_block.offset = HADDR_UNDEF;
+ chunk_ud.chunk_block.length = 0;
+ chunk_ud.filter_mask = 0;
+ chunk_ud.new_unfilt_chunk = false;
+ chunk_ud.idx_hint = UINT_MAX;
+
+ if (H5D__earray_idx_get_addr(idx_info, &chunk_ud) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't load extensible array header index block");
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5D__earray_idx_load_metadata() */
+
+/*-------------------------------------------------------------------------
* Function: H5D__earray_idx_resize
*
* Purpose: Calculate/setup the swizzled down chunk array, used for chunk
@@ -1195,10 +1304,6 @@ H5D__earray_idx_iterate_cb(hsize_t H5_ATTR_UNUSED idx, const void *_elmt, void *
* Purpose: Iterate over the chunks in an index, making a callback
* for each one.
*
- * Note: This implementation is slow, particularly for sparse
- * extensible arrays, replace it with call to H5EA_iterate()
- * when that's available.
- *
* Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
@@ -1223,10 +1328,10 @@ H5D__earray_idx_iterate(const H5D_chk_idx_info_t *idx_info, H5D_chunk_cb_func_t
assert(chunk_udata);
/* Check if the extensible array is open yet */
- if (NULL == idx_info->storage->u.earray.ea) {
+ if (!H5D_EARRAY_IDX_IS_OPEN(idx_info)) {
/* Open the extensible array in file */
if (H5D__earray_idx_open(idx_info) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "can't open extensible array");
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, H5_ITER_ERROR, "can't open extensible array");
}
else /* Patch the top level file pointer contained in ea if needed */
H5EA_patch_file(idx_info->storage->u.earray.ea, idx_info->f);
@@ -1236,7 +1341,7 @@ H5D__earray_idx_iterate(const H5D_chk_idx_info_t *idx_info, H5D_chunk_cb_func_t
/* Get the extensible array statistics */
if (H5EA_get_stats(ea, &ea_stat) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't query extensible array statistics");
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, H5_ITER_ERROR, "can't query extensible array statistics");
if (ea_stat.stored.max_idx_set > 0) {
H5D_earray_it_ud_t udata; /* User data for iteration callback */
@@ -1291,7 +1396,7 @@ H5D__earray_idx_remove(const H5D_chk_idx_info_t *idx_info, H5D_chunk_common_ud_t
assert(udata);
/* Check if the extensible array is open yet */
- if (NULL == idx_info->storage->u.earray.ea) {
+ if (!H5D_EARRAY_IDX_IS_OPEN(idx_info)) {
/* Open the extensible array in file */
if (H5D__earray_idx_open(idx_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "can't open extensible array");
@@ -1444,9 +1549,8 @@ H5D__earray_idx_delete(const H5D_chk_idx_info_t *idx_info)
HGOTO_ERROR(H5E_DATASET, H5E_BADITER, FAIL, "unable to iterate over chunk addresses");
/* Close extensible array */
- if (H5EA_close(idx_info->storage->u.earray.ea) < 0)
+ if (H5D__earray_idx_close(idx_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "unable to close extensible array");
- idx_info->storage->u.earray.ea = NULL;
/* Set up the context user data */
ctx_udata.f = idx_info->f;
@@ -1494,7 +1598,7 @@ H5D__earray_idx_copy_setup(const H5D_chk_idx_info_t *idx_info_src, const H5D_chk
assert(!H5_addr_defined(idx_info_dst->storage->idx_addr));
/* Check if the source extensible array is open yet */
- if (NULL == idx_info_src->storage->u.earray.ea)
+ if (!H5D_EARRAY_IDX_IS_OPEN(idx_info_src))
/* Open the extensible array in file */
if (H5D__earray_idx_open(idx_info_src) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "can't open extensible array");
@@ -1593,9 +1697,8 @@ H5D__earray_idx_size(const H5D_chk_idx_info_t *idx_info, hsize_t *index_size)
done:
if (idx_info->storage->u.earray.ea) {
- if (H5EA_close(idx_info->storage->u.earray.ea) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "unable to close extensible array");
- idx_info->storage->u.earray.ea = NULL;
+ if (H5D__earray_idx_close(idx_info) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "unable to close extensible array");
} /* end if */
FUNC_LEAVE_NOAPI(ret_value)
@@ -1673,16 +1776,14 @@ H5D__earray_idx_dest(const H5D_chk_idx_info_t *idx_info)
assert(idx_info->storage);
/* Check if the extensible array is open */
- if (idx_info->storage->u.earray.ea) {
-
+ if (H5D_EARRAY_IDX_IS_OPEN(idx_info)) {
/* Patch the top level file pointer contained in ea if needed */
if (H5EA_patch_file(idx_info->storage->u.earray.ea, idx_info->f) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "can't patch earray file pointer");
/* Close extensible array */
- if (H5EA_close(idx_info->storage->u.earray.ea) < 0)
+ if (H5D__earray_idx_close(idx_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "unable to close extensible array");
- idx_info->storage->u.earray.ea = NULL;
} /* end if */
done:
diff --git a/src/H5Dfarray.c b/src/H5Dfarray.c
index 450d466..8d06de4 100644
--- a/src/H5Dfarray.c
+++ b/src/H5Dfarray.c
@@ -37,6 +37,8 @@
/* Local Macros */
/****************/
+#define H5D_FARRAY_IDX_IS_OPEN(idx_info) (NULL != (idx_info)->storage->u.btree2.bt2)
+
/* Value to fill unset array elements with */
#define H5D_FARRAY_FILL HADDR_UNDEF
#define H5D_FARRAY_FILT_FILL \
@@ -105,10 +107,14 @@ static herr_t H5D__farray_filt_debug(FILE *stream, int indent, int fwidth, hsize
static herr_t H5D__farray_idx_init(const H5D_chk_idx_info_t *idx_info, const H5S_t *space,
haddr_t dset_ohdr_addr);
static herr_t H5D__farray_idx_create(const H5D_chk_idx_info_t *idx_info);
+static herr_t H5D__farray_idx_open(const H5D_chk_idx_info_t *idx_info);
+static herr_t H5D__farray_idx_close(const H5D_chk_idx_info_t *idx_info);
+static herr_t H5D__farray_idx_is_open(const H5D_chk_idx_info_t *idx_info, bool *is_open);
static bool H5D__farray_idx_is_space_alloc(const H5O_storage_chunk_t *storage);
static herr_t H5D__farray_idx_insert(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata,
const H5D_t *dset);
static herr_t H5D__farray_idx_get_addr(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata);
+static herr_t H5D__farray_idx_load_metadata(const H5D_chk_idx_info_t *idx_info);
static int H5D__farray_idx_iterate(const H5D_chk_idx_info_t *idx_info, H5D_chunk_cb_func_t chunk_cb,
void *chunk_udata);
static herr_t H5D__farray_idx_remove(const H5D_chk_idx_info_t *idx_info, H5D_chunk_common_ud_t *udata);
@@ -123,7 +129,6 @@ static herr_t H5D__farray_idx_dump(const H5O_storage_chunk_t *storage, FILE *str
static herr_t H5D__farray_idx_dest(const H5D_chk_idx_info_t *idx_info);
/* Generic fixed array routines */
-static herr_t H5D__farray_idx_open(const H5D_chk_idx_info_t *idx_info);
static herr_t H5D__farray_idx_depend(const H5D_chk_idx_info_t *idx_info);
/*********************/
@@ -135,9 +140,13 @@ const H5D_chunk_ops_t H5D_COPS_FARRAY[1] = {{
true, /* Fixed array indices support SWMR access */
H5D__farray_idx_init, /* init */
H5D__farray_idx_create, /* create */
+ H5D__farray_idx_open, /* open */
+ H5D__farray_idx_close, /* close */
+ H5D__farray_idx_is_open, /* is_open */
H5D__farray_idx_is_space_alloc, /* is_space_alloc */
H5D__farray_idx_insert, /* insert */
H5D__farray_idx_get_addr, /* get_addr */
+ H5D__farray_idx_load_metadata, /* load_metadata */
NULL, /* resize */
H5D__farray_idx_iterate, /* iterate */
H5D__farray_idx_remove, /* remove */
@@ -727,55 +736,6 @@ H5D__farray_idx_init(const H5D_chk_idx_info_t *idx_info, const H5S_t H5_ATTR_UNU
} /* end H5D__farray_idx_init() */
/*-------------------------------------------------------------------------
- * Function: H5D__farray_idx_open
- *
- * Purpose: Opens an existing fixed array and initializes
- * the layout struct with information about the storage.
- *
- * Return: Success: non-negative
- * Failure: negative
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5D__farray_idx_open(const H5D_chk_idx_info_t *idx_info)
-{
- H5D_farray_ctx_ud_t udata; /* User data for fixed array open call */
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_PACKAGE
-
- /* Check args */
- assert(idx_info);
- assert(idx_info->f);
- assert(idx_info->pline);
- assert(idx_info->layout);
- assert(H5D_CHUNK_IDX_FARRAY == idx_info->layout->idx_type);
- assert(idx_info->storage);
- assert(H5D_CHUNK_IDX_FARRAY == idx_info->storage->idx_type);
- assert(H5_addr_defined(idx_info->storage->idx_addr));
- assert(NULL == idx_info->storage->u.farray.fa);
-
- /* Set up the user data */
- udata.f = idx_info->f;
- udata.chunk_size = idx_info->layout->size;
-
- /* Open the fixed array for the chunk index */
- if (NULL ==
- (idx_info->storage->u.farray.fa = H5FA_open(idx_info->f, idx_info->storage->idx_addr, &udata)))
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't open fixed array");
-
- /* Check for SWMR writes to the file */
- if (H5F_INTENT(idx_info->f) & H5F_ACC_SWMR_WRITE)
- if (H5D__farray_idx_depend(idx_info) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTDEPEND, FAIL,
- "unable to create flush dependency on object header");
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D__farray_idx_open() */
-
-/*-------------------------------------------------------------------------
* Function: H5D__farray_idx_create
*
* Purpose: Creates a new indexed-storage fixed array and initializes
@@ -854,11 +814,114 @@ done:
} /* end H5D__farray_idx_create() */
/*-------------------------------------------------------------------------
+ * Function: H5D__farray_idx_open
+ *
+ * Purpose: Opens an existing fixed array and initializes
+ * the layout struct with information about the storage.
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D__farray_idx_open(const H5D_chk_idx_info_t *idx_info)
+{
+ H5D_farray_ctx_ud_t udata; /* User data for fixed array open call */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ /* Check args */
+ assert(idx_info);
+ assert(idx_info->f);
+ assert(idx_info->pline);
+ assert(idx_info->layout);
+ assert(H5D_CHUNK_IDX_FARRAY == idx_info->layout->idx_type);
+ assert(idx_info->storage);
+ assert(H5D_CHUNK_IDX_FARRAY == idx_info->storage->idx_type);
+ assert(H5_addr_defined(idx_info->storage->idx_addr));
+ assert(NULL == idx_info->storage->u.farray.fa);
+
+ /* Set up the user data */
+ udata.f = idx_info->f;
+ udata.chunk_size = idx_info->layout->size;
+
+ /* Open the fixed array for the chunk index */
+ if (NULL ==
+ (idx_info->storage->u.farray.fa = H5FA_open(idx_info->f, idx_info->storage->idx_addr, &udata)))
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't open fixed array");
+
+ /* Check for SWMR writes to the file */
+ if (H5F_INTENT(idx_info->f) & H5F_ACC_SWMR_WRITE)
+ if (H5D__farray_idx_depend(idx_info) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTDEPEND, FAIL,
+ "unable to create flush dependency on object header");
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D__farray_idx_open() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5D__farray_idx_close
+ *
+ * Purpose: Closes an existing fixed array.
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D__farray_idx_close(const H5D_chk_idx_info_t *idx_info)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ assert(idx_info);
+ assert(idx_info->storage);
+ assert(H5D_CHUNK_IDX_FARRAY == idx_info->storage->idx_type);
+ assert(idx_info->storage->u.farray.fa);
+
+ if (H5FA_close(idx_info->storage->u.farray.fa) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "unable to close fixed array");
+ idx_info->storage->u.farray.fa = NULL;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D__farray_idx_close() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5D__farray_idx_is_open
+ *
+ * Purpose: Query if the index is opened or not
+ *
+ * Return: SUCCEED (can't fail)
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D__farray_idx_is_open(const H5D_chk_idx_info_t *idx_info, bool *is_open)
+{
+ FUNC_ENTER_PACKAGE_NOERR
+
+ assert(idx_info);
+ assert(idx_info->storage);
+ assert(H5D_CHUNK_IDX_FARRAY == idx_info->storage->idx_type);
+ assert(is_open);
+
+ *is_open = H5D_FARRAY_IDX_IS_OPEN(idx_info);
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5D__farray_idx_is_open() */
+
+/*-------------------------------------------------------------------------
* Function: H5D__farray_idx_is_space_alloc
*
* Purpose: Query if space is allocated for index method
*
- * Return: Non-negative on success/Negative on failure
+ * Return: true/false
*
*-------------------------------------------------------------------------
*/
@@ -901,7 +964,7 @@ H5D__farray_idx_insert(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata
assert(udata);
/* Check if the fixed array is open yet */
- if (NULL == idx_info->storage->u.farray.fa) {
+ if (!H5D_FARRAY_IDX_IS_OPEN(idx_info)) {
/* Open the fixed array in file */
if (H5D__farray_idx_open(idx_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "can't open fixed array");
@@ -969,7 +1032,7 @@ H5D__farray_idx_get_addr(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *uda
assert(udata);
/* Check if the fixed array is open yet */
- if (NULL == idx_info->storage->u.farray.fa) {
+ if (!H5D_FARRAY_IDX_IS_OPEN(idx_info)) {
/* Open the fixed array in file */
if (H5D__farray_idx_open(idx_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "can't open fixed array");
@@ -1017,6 +1080,50 @@ done:
} /* H5D__farray_idx_get_addr() */
/*-------------------------------------------------------------------------
+ * Function: H5D__farray_idx_load_metadata
+ *
+ * Purpose: Load additional chunk index metadata beyond the chunk index
+ * itself.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D__farray_idx_load_metadata(const H5D_chk_idx_info_t *idx_info)
+{
+ H5D_chunk_ud_t chunk_ud;
+ hsize_t scaled[H5O_LAYOUT_NDIMS] = {0};
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_PACKAGE
+
+ /*
+ * After opening a dataset that uses a fixed array, the
+ * fixed array data block will generally not be read in
+ * until an element is looked up for the first time. Since
+ * there isn't currently a good way of controlling that
+ * explicitly, perform a fake lookup of a chunk to cause
+ * it to be read in.
+ */
+ chunk_ud.common.layout = idx_info->layout;
+ chunk_ud.common.storage = idx_info->storage;
+ chunk_ud.common.scaled = scaled;
+
+ chunk_ud.chunk_block.offset = HADDR_UNDEF;
+ chunk_ud.chunk_block.length = 0;
+ chunk_ud.filter_mask = 0;
+ chunk_ud.new_unfilt_chunk = false;
+ chunk_ud.idx_hint = UINT_MAX;
+
+ if (H5D__farray_idx_get_addr(idx_info, &chunk_ud) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't load fixed array data block");
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5D__farray_idx_load_metadata() */
+
+/*-------------------------------------------------------------------------
* Function: H5D__farray_idx_iterate_cb
*
* Purpose: Callback routine for fixed array element iteration.
@@ -1102,7 +1209,7 @@ H5D__farray_idx_iterate(const H5D_chk_idx_info_t *idx_info, H5D_chunk_cb_func_t
assert(chunk_udata);
/* Check if the fixed array is open yet */
- if (NULL == idx_info->storage->u.farray.fa) {
+ if (!H5D_FARRAY_IDX_IS_OPEN(idx_info)) {
/* Open the fixed array in file */
if (H5D__farray_idx_open(idx_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "can't open fixed array");
@@ -1171,7 +1278,7 @@ H5D__farray_idx_remove(const H5D_chk_idx_info_t *idx_info, H5D_chunk_common_ud_t
assert(udata);
/* Check if the fixed array is open yet */
- if (NULL == idx_info->storage->u.farray.fa) {
+ if (!H5D_FARRAY_IDX_IS_OPEN(idx_info)) {
/* Open the fixed array in file */
if (H5D__farray_idx_open(idx_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "can't open fixed array");
@@ -1302,9 +1409,8 @@ H5D__farray_idx_delete(const H5D_chk_idx_info_t *idx_info)
HGOTO_ERROR(H5E_DATASET, H5E_BADITER, FAIL, "unable to iterate over chunk addresses");
/* Close fixed array */
- if (H5FA_close(idx_info->storage->u.farray.fa) < 0)
+ if (H5D__farray_idx_close(idx_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "unable to close fixed array");
- idx_info->storage->u.farray.fa = NULL;
/* Set up the user data */
ctx_udata.f = idx_info->f;
@@ -1352,10 +1458,11 @@ H5D__farray_idx_copy_setup(const H5D_chk_idx_info_t *idx_info_src, const H5D_chk
assert(!H5_addr_defined(idx_info_dst->storage->idx_addr));
/* Check if the source fixed array is open yet */
- if (NULL == idx_info_src->storage->u.farray.fa)
+ if (!H5D_FARRAY_IDX_IS_OPEN(idx_info_src)) {
/* Open the fixed array in file */
if (H5D__farray_idx_open(idx_info_src) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "can't open fixed array");
+ }
/* Set copied metadata tag */
H5_BEGIN_TAG(H5AC__COPIED_TAG)
@@ -1450,9 +1557,8 @@ H5D__farray_idx_size(const H5D_chk_idx_info_t *idx_info, hsize_t *index_size)
done:
if (idx_info->storage->u.farray.fa) {
- if (H5FA_close(idx_info->storage->u.farray.fa) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "unable to close fixed array");
- idx_info->storage->u.farray.fa = NULL;
+ if (H5D__farray_idx_close(idx_info) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "unable to close fixed array");
} /* end if */
FUNC_LEAVE_NOAPI(ret_value)
@@ -1528,16 +1634,14 @@ H5D__farray_idx_dest(const H5D_chk_idx_info_t *idx_info)
assert(idx_info->storage);
/* Check if the fixed array is open */
- if (idx_info->storage->u.farray.fa) {
-
+ if (H5D_FARRAY_IDX_IS_OPEN(idx_info)) {
/* Patch the top level file pointer contained in fa if needed */
if (H5FA_patch_file(idx_info->storage->u.farray.fa, idx_info->f) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "can't patch fixed array file pointer");
/* Close fixed array */
- if (H5FA_close(idx_info->storage->u.farray.fa) < 0)
+ if (H5D__farray_idx_close(idx_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "unable to close fixed array");
- idx_info->storage->u.farray.fa = NULL;
} /* end if */
done:
diff --git a/src/H5Dmpio.c b/src/H5Dmpio.c
index 0ef6542..16243fa 100644
--- a/src/H5Dmpio.c
+++ b/src/H5Dmpio.c
@@ -3024,6 +3024,26 @@ H5D__obtain_mpio_mode(H5D_io_info_t *io_info, H5D_dset_io_info_t *di, uint8_t as
* metadata reads are enabled.
*/
if (H5F_get_coll_metadata_reads(di->dset->oloc.file)) {
+#ifndef NDEBUG
+ {
+ H5D_chk_idx_info_t idx_info;
+ bool index_is_open;
+
+ idx_info.f = di->dset->oloc.file;
+ idx_info.pline = &di->dset->shared->dcpl_cache.pline;
+ idx_info.layout = &di->dset->shared->layout.u.chunk;
+ idx_info.storage = &di->dset->shared->layout.storage.u.chunk;
+
+ /*
+ * The dataset's chunk index should be open at this point.
+ * Otherwise, we will end up reading it in independently,
+ * which may not be desired.
+ */
+ idx_info.storage->ops->is_open(&idx_info, &index_is_open);
+ assert(index_is_open);
+ }
+#endif
+
md_reads_file_flag = H5P_FORCE_FALSE;
md_reads_context_flag = false;
H5F_set_coll_metadata_reads(di->dset->oloc.file, &md_reads_file_flag, &md_reads_context_flag);
@@ -3446,26 +3466,6 @@ H5D__mpio_collective_filtered_chunk_io_setup(const H5D_io_info_t *io_info, const
chunk_node = H5SL_next(chunk_node);
}
}
- else if (H5F_get_coll_metadata_reads(di[dset_idx].dset->oloc.file)) {
- hsize_t scaled[H5O_LAYOUT_NDIMS] = {0};
-
- /*
- * If this rank has no selection in the dataset and collective
- * metadata reads are enabled, do a fake lookup of a chunk to
- * ensure that this rank has the chunk index opened. Otherwise,
- * only the ranks that had a selection will have opened the
- * chunk index and they will have done so independently. Therefore,
- * when ranks with no selection participate in later collective
- * metadata reads, they will try to open the chunk index collectively
- * and issues will occur since other ranks won't participate.
- *
- * In the future, we should consider having a chunk index "open"
- * callback that can be used to ensure collectivity between ranks
- * in a more natural way, but this hack should suffice for now.
- */
- if (H5D__chunk_lookup(di[dset_idx].dset, scaled, &udata) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error looking up chunk address");
- }
/* Reset metadata tagging */
H5AC_tag(prev_tag, NULL);
diff --git a/src/H5Dnone.c b/src/H5Dnone.c
index 472a221..d4eb918 100644
--- a/src/H5Dnone.c
+++ b/src/H5Dnone.c
@@ -14,9 +14,9 @@
* Purpose: Implicit (Non Index) chunked I/O functions.
*
* This is used when the dataset is:
- * - extendible but with fixed max. dims
- * - with early allocation
- * - without filter
+ * - extendible but with fixed max. dims
+ * - with early allocation
+ * - without filter
*
* The chunk coordinate is mapped into the actual disk addresses
* for the chunk without indexing.
@@ -31,12 +31,12 @@
/***********/
/* Headers */
/***********/
-#include "H5private.h" /* Generic Functions */
-#include "H5Dpkg.h" /* Datasets */
-#include "H5Eprivate.h" /* Error handling */
+#include "H5private.h" /* Generic Functions */
+#include "H5Dpkg.h" /* Datasets */
+#include "H5Eprivate.h" /* Error handling */
#include "H5FLprivate.h" /* Free Lists */
-#include "H5MFprivate.h" /* File space management */
-#include "H5VMprivate.h" /* Vector functions */
+#include "H5MFprivate.h" /* File space management */
+#include "H5VMprivate.h" /* Vector functions */
/****************/
/* Local Macros */
@@ -52,8 +52,12 @@
/* Non Index chunking I/O ops */
static herr_t H5D__none_idx_create(const H5D_chk_idx_info_t *idx_info);
+static herr_t H5D__none_idx_open(const H5D_chk_idx_info_t *idx_info);
+static herr_t H5D__none_idx_close(const H5D_chk_idx_info_t *idx_info);
+static herr_t H5D__none_idx_is_open(const H5D_chk_idx_info_t *idx_info, bool *is_open);
static bool H5D__none_idx_is_space_alloc(const H5O_storage_chunk_t *storage);
static herr_t H5D__none_idx_get_addr(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata);
+static herr_t H5D__none_idx_load_metadata(const H5D_chk_idx_info_t *idx_info);
static int H5D__none_idx_iterate(const H5D_chk_idx_info_t *idx_info, H5D_chunk_cb_func_t chunk_cb,
void *chunk_udata);
static herr_t H5D__none_idx_remove(const H5D_chk_idx_info_t *idx_info, H5D_chunk_common_ud_t *udata);
@@ -73,9 +77,13 @@ const H5D_chunk_ops_t H5D_COPS_NONE[1] = {{
false, /* Non-indexed chunking don't current support SWMR access */
NULL, /* init */
H5D__none_idx_create, /* create */
+ H5D__none_idx_open, /* open */
+ H5D__none_idx_close, /* close */
+ H5D__none_idx_is_open, /* is_open */
H5D__none_idx_is_space_alloc, /* is_space_alloc */
NULL, /* insert */
H5D__none_idx_get_addr, /* get_addr */
+ H5D__none_idx_load_metadata, /* load_metadata */
NULL, /* resize */
H5D__none_idx_iterate, /* iterate */
H5D__none_idx_remove, /* remove */
@@ -97,12 +105,12 @@ const H5D_chunk_ops_t H5D_COPS_NONE[1] = {{
/*******************/
/*-------------------------------------------------------------------------
- * Function: H5D__none_idx_create
+ * Function: H5D__none_idx_create
*
- * Purpose: Allocate memory for the maximum # of chunks in the dataset.
+ * Purpose: Allocate memory for the maximum # of chunks in the dataset.
*
- * Return: Non-negative on success
- * Negative on failure.
+ * Return: Non-negative on success
+ * Negative on failure.
*
*-------------------------------------------------------------------------
*/
@@ -141,11 +149,73 @@ done:
} /* end H5D__none_idx_create() */
/*-------------------------------------------------------------------------
- * Function: H5D__none_idx_is_space_alloc
+ * Function: H5D__none_idx_open
*
- * Purpose: Query if space for the dataset chunks is allocated
+ * Purpose: Opens an existing "none" index. Currently a no-op.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: SUCCEED (can't fail)
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D__none_idx_open(const H5D_chk_idx_info_t H5_ATTR_UNUSED *idx_info)
+{
+ FUNC_ENTER_PACKAGE_NOERR
+
+ /* NO OP */
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5D__none_idx_open() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5D__none_idx_close
+ *
+ * Purpose: Closes an existing "none" index. Currently a no-op.
+ *
+ * Return: SUCCEED (can't fail)
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D__none_idx_close(const H5D_chk_idx_info_t H5_ATTR_UNUSED *idx_info)
+{
+ FUNC_ENTER_PACKAGE_NOERR
+
+ /* NO OP */
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5D__none_idx_close() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5D__none_idx_is_open
+ *
+ * Purpose: Query if the index is opened or not
+ *
+ * Return: SUCCEED (can't fail)
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D__none_idx_is_open(const H5D_chk_idx_info_t H5_ATTR_NDEBUG_UNUSED *idx_info, bool *is_open)
+{
+ FUNC_ENTER_PACKAGE_NOERR
+
+ assert(idx_info);
+ assert(idx_info->storage);
+ assert(H5D_CHUNK_IDX_NONE == idx_info->storage->idx_type);
+ assert(is_open);
+
+ *is_open = true;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5D__none_idx_is_open() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5D__none_idx_is_space_alloc
+ *
+ * Purpose: Query if space for the dataset chunks is allocated
+ *
+ * Return: true/false
*
*-------------------------------------------------------------------------
*/
@@ -161,12 +231,12 @@ H5D__none_idx_is_space_alloc(const H5O_storage_chunk_t *storage)
} /* end H5D__none_idx_is_space_alloc() */
/*-------------------------------------------------------------------------
- * Function: H5D__none_idx_get_addr
+ * Function: H5D__none_idx_get_addr
*
- * Purpose: Get the file address of a chunk.
- * Save the retrieved information in the udata supplied.
+ * Purpose: Get the file address of a chunk.
+ * Save the retrieved information in the udata supplied.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
@@ -200,12 +270,32 @@ H5D__none_idx_get_addr(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata
} /* H5D__none_idx_get_addr() */
/*-------------------------------------------------------------------------
- * Function: H5D__none_idx_iterate
+ * Function: H5D__none_idx_load_metadata
+ *
+ * Purpose: Load additional chunk index metadata beyond the chunk index
+ * itself. Currently a no-op.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D__none_idx_load_metadata(const H5D_chk_idx_info_t H5_ATTR_UNUSED *idx_info)
+{
+ FUNC_ENTER_PACKAGE_NOERR
+
+ /* NO OP */
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5D__none_idx_load_metadata() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5D__none_idx_iterate
*
- * Purpose: Iterate over the chunks in an index, making a callback
+ * Purpose: Iterate over the chunks in an index, making a callback
* for each one.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
@@ -275,13 +365,13 @@ done:
} /* end H5D__none_idx_iterate() */
/*-------------------------------------------------------------------------
- * Function: H5D__none_idx_remove
+ * Function: H5D__none_idx_remove
*
- * Purpose: Remove chunk from index.
+ * Purpose: Remove chunk from index.
*
- * Note: Chunks can't be removed (or added) to datasets with this
- * form of index - all the space for all the chunks is always
- * allocated in the file.
+ * Note: Chunks can't be removed (or added) to datasets with this
+ * form of index - all the space for all the chunks is always
+ * allocated in the file.
*
* Return: Non-negative on success/Negative on failure
*
@@ -299,12 +389,12 @@ H5D__none_idx_remove(const H5D_chk_idx_info_t H5_ATTR_UNUSED *idx_info,
} /* H5D__none_idx_remove() */
/*-------------------------------------------------------------------------
- * Function: H5D__none_idx_delete
+ * Function: H5D__none_idx_delete
*
- * Purpose: Delete raw data storage for entire dataset (i.e. all chunks)
+ * Purpose: Delete raw data storage for entire dataset (i.e. all chunks)
*
- * Return: Success: Non-negative
- * Failure: negative
+ * Return: Success: Non-negative
+ * Failure: negative
*
*-------------------------------------------------------------------------
*/
@@ -337,11 +427,11 @@ done:
} /* end H5D__none_idx_delete() */
/*-------------------------------------------------------------------------
- * Function: H5D__none_idx_copy_setup
+ * Function: H5D__none_idx_copy_setup
*
- * Purpose: Set up any necessary information for copying chunks
+ * Purpose: Set up any necessary information for copying chunks
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
@@ -407,11 +497,11 @@ H5D__none_idx_size(const H5D_chk_idx_info_t H5_ATTR_UNUSED *idx_info, hsize_t *i
} /* end H5D__none_idx_size() */
/*-------------------------------------------------------------------------
- * Function: H5D__none_idx_reset
+ * Function: H5D__none_idx_reset
*
- * Purpose: Reset indexing information.
+ * Purpose: Reset indexing information.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
@@ -431,11 +521,11 @@ H5D__none_idx_reset(H5O_storage_chunk_t *storage, bool reset_addr)
} /* end H5D__none_idx_reset() */
/*-------------------------------------------------------------------------
- * Function: H5D__none_idx_dump
+ * Function: H5D__none_idx_dump
*
- * Purpose: Dump
+ * Purpose: Dump
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
diff --git a/src/H5Dpkg.h b/src/H5Dpkg.h
index 82fec0e..a3695ae 100644
--- a/src/H5Dpkg.h
+++ b/src/H5Dpkg.h
@@ -393,10 +393,14 @@ typedef int (*H5D_chunk_cb_func_t)(const H5D_chunk_rec_t *chunk_rec, void *udata
typedef herr_t (*H5D_chunk_init_func_t)(const H5D_chk_idx_info_t *idx_info, const H5S_t *space,
haddr_t dset_ohdr_addr);
typedef herr_t (*H5D_chunk_create_func_t)(const H5D_chk_idx_info_t *idx_info);
+typedef herr_t (*H5D_chunk_open_func_t)(const H5D_chk_idx_info_t *idx_info);
+typedef herr_t (*H5D_chunk_close_func_t)(const H5D_chk_idx_info_t *idx_info);
+typedef herr_t (*H5D_chunk_is_open_func_t)(const H5D_chk_idx_info_t *idx_info, bool *is_open);
typedef bool (*H5D_chunk_is_space_alloc_func_t)(const H5O_storage_chunk_t *storage);
typedef herr_t (*H5D_chunk_insert_func_t)(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata,
const H5D_t *dset);
typedef herr_t (*H5D_chunk_get_addr_func_t)(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata);
+typedef herr_t (*H5D_chunk_load_metadata_func_t)(const H5D_chk_idx_info_t *idx_info);
typedef herr_t (*H5D_chunk_resize_func_t)(H5O_layout_chunk_t *layout);
typedef int (*H5D_chunk_iterate_func_t)(const H5D_chk_idx_info_t *idx_info, H5D_chunk_cb_func_t chunk_cb,
void *chunk_udata);
@@ -413,13 +417,18 @@ typedef herr_t (*H5D_chunk_dest_func_t)(const H5D_chk_idx_info_t *idx_info);
/* Typedef for grouping chunk I/O routines */
typedef struct H5D_chunk_ops_t {
- bool can_swim; /* Flag to indicate that the index supports SWMR access */
- H5D_chunk_init_func_t init; /* Routine to initialize indexing information in memory */
- H5D_chunk_create_func_t create; /* Routine to create chunk index */
+ bool can_swim; /* Flag to indicate that the index supports SWMR access */
+ H5D_chunk_init_func_t init; /* Routine to initialize indexing information in memory */
+ H5D_chunk_create_func_t create; /* Routine to create chunk index */
+ H5D_chunk_open_func_t open; /* Routine to open chunk index */
+ H5D_chunk_close_func_t close; /* Routine to close chunk index */
+ H5D_chunk_is_open_func_t is_open; /* Query routine to determine if index is open or not */
H5D_chunk_is_space_alloc_func_t
- is_space_alloc; /* Query routine to determine if storage/index is allocated */
- H5D_chunk_insert_func_t insert; /* Routine to insert a chunk into an index */
- H5D_chunk_get_addr_func_t get_addr; /* Routine to retrieve address of chunk in file */
+ is_space_alloc; /* Query routine to determine if storage/index is allocated */
+ H5D_chunk_insert_func_t insert; /* Routine to insert a chunk into an index */
+ H5D_chunk_get_addr_func_t get_addr; /* Routine to retrieve address of chunk in file */
+ H5D_chunk_load_metadata_func_t
+ load_metadata; /* Routine to load additional chunk index metadata, such as fixed array data blocks */
H5D_chunk_resize_func_t resize; /* Routine to update chunk index info after resizing dataset */
H5D_chunk_iterate_func_t iterate; /* Routine to iterate over chunks */
H5D_chunk_remove_func_t remove; /* Routine to remove a chunk from an index */
diff --git a/src/H5Dsingle.c b/src/H5Dsingle.c
index 9cb18d3..dd9f235 100644
--- a/src/H5Dsingle.c
+++ b/src/H5Dsingle.c
@@ -27,12 +27,12 @@
/***********/
/* Headers */
/***********/
-#include "H5private.h" /* Generic Functions */
-#include "H5Dpkg.h" /* Datasets */
-#include "H5Eprivate.h" /* Error handling */
+#include "H5private.h" /* Generic Functions */
+#include "H5Dpkg.h" /* Datasets */
+#include "H5Eprivate.h" /* Error handling */
#include "H5FLprivate.h" /* Free Lists */
-#include "H5MFprivate.h" /* File space management */
-#include "H5VMprivate.h" /* Vector functions */
+#include "H5MFprivate.h" /* File space management */
+#include "H5VMprivate.h" /* Vector functions */
/****************/
/* Local Macros */
@@ -50,10 +50,14 @@
static herr_t H5D__single_idx_init(const H5D_chk_idx_info_t *idx_info, const H5S_t *space,
haddr_t dset_ohdr_addr);
static herr_t H5D__single_idx_create(const H5D_chk_idx_info_t *idx_info);
+static herr_t H5D__single_idx_open(const H5D_chk_idx_info_t *idx_info);
+static herr_t H5D__single_idx_close(const H5D_chk_idx_info_t *idx_info);
+static herr_t H5D__single_idx_is_open(const H5D_chk_idx_info_t *idx_info, bool *is_open);
static bool H5D__single_idx_is_space_alloc(const H5O_storage_chunk_t *storage);
static herr_t H5D__single_idx_insert(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata,
const H5D_t *dset);
static herr_t H5D__single_idx_get_addr(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata);
+static herr_t H5D__single_idx_load_metadata(const H5D_chk_idx_info_t *idx_info);
static int H5D__single_idx_iterate(const H5D_chk_idx_info_t *idx_info, H5D_chunk_cb_func_t chunk_cb,
void *chunk_udata);
static herr_t H5D__single_idx_remove(const H5D_chk_idx_info_t *idx_info, H5D_chunk_common_ud_t *udata);
@@ -73,9 +77,13 @@ const H5D_chunk_ops_t H5D_COPS_SINGLE[1] = {{
false, /* Single Chunk indexing doesn't current support SWMR access */
H5D__single_idx_init, /* init */
H5D__single_idx_create, /* create */
+ H5D__single_idx_open, /* open */
+ H5D__single_idx_close, /* close */
+ H5D__single_idx_is_open, /* is_open */
H5D__single_idx_is_space_alloc, /* is_space_alloc */
H5D__single_idx_insert, /* insert */
H5D__single_idx_get_addr, /* get_addr */
+ H5D__single_idx_load_metadata, /* load_metadata */
NULL, /* resize */
H5D__single_idx_iterate, /* iterate */
H5D__single_idx_remove, /* remove */
@@ -133,12 +141,12 @@ H5D__single_idx_init(const H5D_chk_idx_info_t *idx_info, const H5S_t H5_ATTR_UNU
} /* end H5D__single_idx_init() */
/*-------------------------------------------------------------------------
- * Function: H5D__single_idx_create
+ * Function: H5D__single_idx_create
*
- * Purpose: Set up Single Chunk Index: filtered or non-filtered
+ * Purpose: Set up Single Chunk Index: filtered or non-filtered
*
- * Return: Non-negative on success
- * Negative on failure.
+ * Return: Non-negative on success
+ * Negative on failure.
*
*-------------------------------------------------------------------------
*/
@@ -166,11 +174,73 @@ H5D__single_idx_create(const H5D_chk_idx_info_t *idx_info)
} /* end H5D__single_idx_create() */
/*-------------------------------------------------------------------------
- * Function: H5D__single_idx_is_space_alloc
+ * Function: H5D__single_idx_open
*
- * Purpose: Query if space is allocated for the single chunk
+ * Purpose: Opens an existing "single" index. Currently a no-op.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: SUCCEED (can't fail)
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D__single_idx_open(const H5D_chk_idx_info_t H5_ATTR_UNUSED *idx_info)
+{
+ FUNC_ENTER_PACKAGE_NOERR
+
+ /* NO OP */
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5D__single_idx_open() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5D__single_idx_close
+ *
+ * Purpose: Closes an existing "single" index. Currently a no-op.
+ *
+ * Return: SUCCEED (can't fail)
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D__single_idx_close(const H5D_chk_idx_info_t H5_ATTR_UNUSED *idx_info)
+{
+ FUNC_ENTER_PACKAGE_NOERR
+
+ /* NO OP */
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5D__single_idx_close() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5D__single_idx_is_open
+ *
+ * Purpose: Query if the index is opened or not
+ *
+ * Return: SUCCEED (can't fail)
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D__single_idx_is_open(const H5D_chk_idx_info_t H5_ATTR_NDEBUG_UNUSED *idx_info, bool *is_open)
+{
+ FUNC_ENTER_PACKAGE_NOERR
+
+ assert(idx_info);
+ assert(idx_info->storage);
+ assert(H5D_CHUNK_IDX_SINGLE == idx_info->storage->idx_type);
+ assert(is_open);
+
+ *is_open = true;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5D__single_idx_is_open() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5D__single_idx_is_space_alloc
+ *
+ * Purpose: Query if space is allocated for the single chunk
+ *
+ * Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
@@ -186,11 +256,11 @@ H5D__single_idx_is_space_alloc(const H5O_storage_chunk_t *storage)
} /* end H5D__single_idx_is_space_alloc() */
/*-------------------------------------------------------------------------
- * Function: H5D__single_idx_insert
+ * Function: H5D__single_idx_insert
*
- * Purpose: Allocate space for the single chunk
+ * Purpose: Allocate space for the single chunk
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
@@ -231,12 +301,12 @@ done:
} /* H5D__single_idx_insert() */
/*-------------------------------------------------------------------------
- * Function: H5D__single_idx_get_addr
+ * Function: H5D__single_idx_get_addr
*
- * Purpose: Get the file address of a chunk.
- * Save the retrieved information in the udata supplied.
+ * Purpose: Get the file address of a chunk.
+ * Save the retrieved information in the udata supplied.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
@@ -271,11 +341,31 @@ H5D__single_idx_get_addr(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *uda
} /* H5D__single_idx_get_addr() */
/*-------------------------------------------------------------------------
- * Function: H5D__single_idx_iterate
+ * Function: H5D__single_idx_load_metadata
+ *
+ * Purpose: Load additional chunk index metadata beyond the chunk index
+ * itself. Currently a no-op.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D__single_idx_load_metadata(const H5D_chk_idx_info_t H5_ATTR_UNUSED *idx_info)
+{
+ FUNC_ENTER_PACKAGE_NOERR
+
+ /* NO OP */
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5D__single_idx_load_metadata() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5D__single_idx_iterate
*
- * Purpose: Make callback for the single chunk
+ * Purpose: Make callback for the single chunk
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
@@ -318,11 +408,11 @@ H5D__single_idx_iterate(const H5D_chk_idx_info_t *idx_info, H5D_chunk_cb_func_t
} /* end H5D__single_idx_iterate() */
/*-------------------------------------------------------------------------
- * Function: H5D__single_idx_remove
+ * Function: H5D__single_idx_remove
*
- * Purpose: Remove the single chunk
+ * Purpose: Remove the single chunk
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
@@ -357,12 +447,13 @@ done:
} /* H5D__single_idx_remove() */
/*-------------------------------------------------------------------------
- * Function: H5D__single_idx_delete
+ * Function: H5D__single_idx_delete
*
- * Purpose: Delete raw data storage for entire dataset (i.e. the only chunk)
+ * Purpose: Delete raw data storage for entire dataset (i.e. the only
+ * chunk)
*
- * Return: Success: Non-negative
- * Failure: negative
+ * Return: Success: Non-negative
+ * Failure: negative
*
*-------------------------------------------------------------------------
*/
@@ -389,11 +480,12 @@ H5D__single_idx_delete(const H5D_chk_idx_info_t *idx_info)
} /* end H5D__single_idx_delete() */
/*-------------------------------------------------------------------------
- * Function: H5D__single_idx_copy_setup
+ * Function: H5D__single_idx_copy_setup
*
- * Purpose: Set up any necessary information for copying the single chunk
+ * Purpose: Set up any necessary information for copying the single
+ * chunk
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
@@ -457,11 +549,11 @@ H5D__single_idx_size(const H5D_chk_idx_info_t H5_ATTR_UNUSED *idx_info, hsize_t
} /* end H5D__single_idx_size() */
/*-------------------------------------------------------------------------
- * Function: H5D__single_idx_reset
+ * Function: H5D__single_idx_reset
*
- * Purpose: Reset indexing information.
+ * Purpose: Reset indexing information.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
@@ -481,11 +573,11 @@ H5D__single_idx_reset(H5O_storage_chunk_t *storage, bool reset_addr)
} /* end H5D__single_idx_reset() */
/*-------------------------------------------------------------------------
- * Function: H5D__single_idx_dump
+ * Function: H5D__single_idx_dump
*
- * Purpose: Dump the address of the single chunk
+ * Purpose: Dump the address of the single chunk
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/