summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/H5A.c30
-rw-r--r--src/H5Aint.c10
-rw-r--r--src/H5Apkg.h26
-rw-r--r--src/H5Aprivate.h32
-rw-r--r--src/H5Bcache.c4
-rw-r--r--src/H5Dchunk.c2
-rw-r--r--src/H5Dcontig.c13
-rw-r--r--src/H5Dint.c4
-rw-r--r--src/H5Dio.c2
-rw-r--r--src/H5Dlayout.c22
-rw-r--r--src/H5Doh.c50
-rw-r--r--src/H5Dpkg.h1
-rw-r--r--src/H5E.c12
-rw-r--r--src/H5Edefin.h1
-rw-r--r--src/H5Einit.h5
-rw-r--r--src/H5Epubgen.h2
-rw-r--r--src/H5Eterm.h3
-rw-r--r--src/H5F.c323
-rw-r--r--src/H5FD.c82
-rw-r--r--src/H5FDcore.c303
-rw-r--r--src/H5FDfamily.c2
-rw-r--r--src/H5FDlog.c2
-rw-r--r--src/H5FDprivate.h26
-rw-r--r--src/H5FDpublic.h40
-rw-r--r--src/H5FDsec2.c2
-rw-r--r--src/H5FDstdio.c673
-rw-r--r--src/H5FSprivate.h2
-rw-r--r--src/H5FSsection.c2
-rw-r--r--src/H5Fmpi.c4
-rw-r--r--src/H5Fprivate.h5
-rw-r--r--src/H5Fpublic.h1
-rw-r--r--src/H5Gname.c11
-rw-r--r--src/H5Goh.c3
-rw-r--r--src/H5HF.c32
-rw-r--r--src/H5HFbtree2.c8
-rw-r--r--src/H5HFdbg.c195
-rw-r--r--src/H5HFhuge.c4
-rw-r--r--src/H5HFiblock.c146
-rw-r--r--src/H5HFpkg.h19
-rw-r--r--src/H5HFsection.c52
-rw-r--r--src/H5HFspace.c181
-rw-r--r--src/H5I.c147
-rw-r--r--src/H5Iprivate.h2
-rw-r--r--src/H5MF.c4
-rw-r--r--src/H5MFdbg.c4
-rw-r--r--src/H5O.c6
-rw-r--r--src/H5Oainfo.c14
-rw-r--r--src/H5Oattr.c1
-rw-r--r--src/H5Oattribute.c22
-rw-r--r--src/H5Ocopy.c813
-rw-r--r--src/H5Odtype.c38
-rw-r--r--src/H5Oefl.c8
-rw-r--r--src/H5Ofill.c2
-rw-r--r--src/H5Olayout.c8
-rw-r--r--src/H5Olinfo.c16
-rw-r--r--src/H5Olink.c16
-rw-r--r--src/H5Omessage.c6
-rw-r--r--src/H5Opkg.h15
-rw-r--r--src/H5Opline.c1
-rw-r--r--src/H5Oprivate.h22
-rw-r--r--src/H5Opublic.h11
-rw-r--r--src/H5Osdspace.c1
-rw-r--r--src/H5Oshared.c17
-rw-r--r--src/H5Oshared.h21
-rw-r--r--src/H5Ostab.c18
-rw-r--r--src/H5Pdcpl.c2
-rw-r--r--src/H5Pfapl.c500
-rw-r--r--src/H5Pint.c54
-rw-r--r--[-rwxr-xr-x]src/H5Pocpl.c0
-rw-r--r--[-rwxr-xr-x]src/H5Pocpypl.c447
-rw-r--r--src/H5Ppublic.h11
-rw-r--r--[-rwxr-xr-x]src/H5SM.c5
-rw-r--r--[-rwxr-xr-x]src/H5SMbtree2.c0
-rw-r--r--[-rwxr-xr-x]src/H5SMpkg.h0
-rw-r--r--[-rwxr-xr-x]src/H5SMprivate.h0
-rw-r--r--src/H5T.c3
-rw-r--r--src/H5Toh.c3
-rw-r--r--src/H5VL.c3
-rw-r--r--src/H5err.txt1
-rw-r--r--src/H5private.h2
-rw-r--r--src/H5public.h4
-rw-r--r--src/H5win32defs.h6
-rw-r--r--[-rwxr-xr-x]src/Makefile.am0
-rw-r--r--src/Makefile.in2
-rw-r--r--[-rwxr-xr-x]src/hdf5.lnt0
85 files changed, 3631 insertions, 962 deletions
diff --git a/src/H5A.c b/src/H5A.c
index c59e098..0ba7361 100644
--- a/src/H5A.c
+++ b/src/H5A.c
@@ -2566,6 +2566,36 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5A_type
+ *
+ * Purpose: Return the datatype for an attribute.
+ *
+ * Return: Success: Ptr to entry
+ * Failure: NULL
+ *
+ * Programmer: Neil Fortner
+ * Friday, November 11, 2011
+ *
+ *-------------------------------------------------------------------------
+ */
+H5T_t *
+H5A_type(const H5A_t *attr)
+{
+ H5T_t *ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI(NULL)
+
+ HDassert(attr);
+
+ /* Set return value */
+ ret_value = attr->shared->dt;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5A_type() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5Aexists
*
* Purpose: Checks if an attribute with a given name exists on an opened
diff --git a/src/H5Aint.c b/src/H5Aint.c
index 8475330..74c5590 100644
--- a/src/H5Aint.c
+++ b/src/H5Aint.c
@@ -795,6 +795,12 @@ H5A_set_version(const H5F_t *f, H5A_t *attr)
*
* Purpose: Copies a message from _MESG to _DEST in file
*
+ * Note that this function assumes that it is copying *all*
+ * the attributes in the object, specifically when it copies
+ * the creation order from source to destination. If this is
+ * to be used to copy only a single attribute, then the
+ * creation order must be handled differently. -NAF
+ *
* Return: Success: Ptr to _DEST
*
* Failure: NULL
@@ -849,6 +855,7 @@ H5A_attr_copy_file(const H5A_t *attr_src, H5F_t *file_dst, hbool_t *recompute_si
/* Copy attribute's name */
attr_dst->shared->name = H5MM_strdup(attr_src->shared->name);
HDassert(attr_dst->shared->name);
+ attr_dst->shared->encoding = attr_src->shared->encoding;
/* Copy attribute's datatype */
/* If source is named, we will keep dst as named, but we will not actually
@@ -1003,6 +1010,9 @@ H5A_attr_copy_file(const H5A_t *attr_src, H5F_t *file_dst, hbool_t *recompute_si
} /* end else */
} /* end if(attr_src->shared->data) */
+ /* Copy the creation order */
+ attr_dst->shared->crt_idx = attr_src->shared->crt_idx;
+
/* Recompute the version to encode the destination attribute */
if(H5A_set_version(file_dst, attr_dst) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, NULL, "unable to update attribute version")
diff --git a/src/H5Apkg.h b/src/H5Apkg.h
index e7732e2..5257171 100644
--- a/src/H5Apkg.h
+++ b/src/H5Apkg.h
@@ -158,29 +158,6 @@ typedef struct {
H5A_t **attrs; /* Pointer to array of attribute pointers */
} H5A_attr_table_t;
-/* Attribute iteration operator for internal library callbacks */
-typedef herr_t (*H5A_lib_iterate_t)(const H5A_t *attr, void *op_data);
-
-/* Describe kind of callback to make for each attribute */
-typedef enum H5A_attr_iter_op_type_t {
-#ifndef H5_NO_DEPRECATED_SYMBOLS
- H5A_ATTR_OP_APP, /* Application callback */
-#endif /* H5_NO_DEPRECATED_SYMBOLS */
- H5A_ATTR_OP_APP2, /* Revised application callback */
- H5A_ATTR_OP_LIB /* Library internal callback */
-} H5A_attr_iter_op_type_t;
-
-typedef struct H5A_attr_iter_op_t {
- H5A_attr_iter_op_type_t op_type;
- union {
-#ifndef H5_NO_DEPRECATED_SYMBOLS
- H5A_operator1_t app_op; /* Application callback for each attribute */
-#endif /* H5_NO_DEPRECATED_SYMBOLS */
- H5A_operator2_t app_op2; /* Revised application callback for each attribute */
- H5A_lib_iterate_t lib_op; /* Library internal callback for each attribute */
- } u;
-} H5A_attr_iter_op_t;
-
/*****************************/
/* Package Private Variables */
@@ -274,9 +251,6 @@ H5_DLL herr_t H5O_attr_write(const H5O_loc_t *loc, hid_t dxpl_id,
H5A_t *attr);
H5_DLL herr_t H5O_attr_rename(const H5O_loc_t *loc, hid_t dxpl_id,
const char *old_name, const char *new_name);
-H5_DLL herr_t H5O_attr_iterate(hid_t loc_id, hid_t dxpl_id, H5_index_t idx_type,
- H5_iter_order_t order, hsize_t skip, hsize_t *last_attr,
- const H5A_attr_iter_op_t *op, void *op_data);
H5_DLL herr_t H5O_attr_remove(const H5O_loc_t *loc, const char *name,
hid_t dxpl_id);
H5_DLL herr_t H5O_attr_remove_by_idx(const H5O_loc_t *loc, H5_index_t idx_type,
diff --git a/src/H5Aprivate.h b/src/H5Aprivate.h
index 18219e6..ac9f698 100644
--- a/src/H5Aprivate.h
+++ b/src/H5Aprivate.h
@@ -24,6 +24,8 @@
/* Private headers needed by this file */
#include "H5Gprivate.h" /* Groups */
+#include "H5Oprivate.h" /* Object headers */
+#include "H5Tprivate.h" /* Datatypes */
/**************************/
@@ -41,6 +43,29 @@
/* Forward references of package typedefs */
typedef struct H5A_t H5A_t;
+/* Attribute iteration operator for internal library callbacks */
+typedef herr_t (*H5A_lib_iterate_t)(const H5A_t *attr, void *op_data);
+
+/* Describe kind of callback to make for each attribute */
+typedef enum H5A_attr_iter_op_type_t {
+#ifndef H5_NO_DEPRECATED_SYMBOLS
+ H5A_ATTR_OP_APP, /* Application callback */
+#endif /* H5_NO_DEPRECATED_SYMBOLS */
+ H5A_ATTR_OP_APP2, /* Revised application callback */
+ H5A_ATTR_OP_LIB /* Library internal callback */
+} H5A_attr_iter_op_type_t;
+
+typedef struct H5A_attr_iter_op_t {
+ H5A_attr_iter_op_type_t op_type;
+ union {
+#ifndef H5_NO_DEPRECATED_SYMBOLS
+ H5A_operator1_t app_op; /* Application callback for each attribute */
+#endif /* H5_NO_DEPRECATED_SYMBOLS */
+ H5A_operator2_t app_op2; /* Revised application callback for each attribute */
+ H5A_lib_iterate_t lib_op; /* Library internal callback for each attribute */
+ } u;
+} H5A_attr_iter_op_t;
+
/*****************************/
/* Library-private Variables */
@@ -54,6 +79,13 @@ typedef struct H5A_t H5A_t;
/* General attribute routines */
H5_DLL struct H5O_loc_t *H5A_oloc(H5A_t *attr);
H5_DLL H5G_name_t *H5A_nameof(H5A_t *attr);
+H5_DLL H5T_t *H5A_type(const H5A_t *attr);
+H5_DLL herr_t H5O_attr_iterate_real(hid_t loc_id, const H5O_loc_t *loc,
+ hid_t dxpl_id, H5_index_t idx_type, H5_iter_order_t order, hsize_t skip,
+ hsize_t *last_attr, const H5A_attr_iter_op_t *attr_op, void *op_data);
+H5_DLL herr_t H5O_attr_iterate(hid_t loc_id, hid_t dxpl_id, H5_index_t idx_type,
+ H5_iter_order_t order, hsize_t skip, hsize_t *last_attr,
+ const H5A_attr_iter_op_t *op, void *op_data);
#endif /* _H5Aprivate_H */
diff --git a/src/H5Bcache.c b/src/H5Bcache.c
index c0fd121..68fb920 100644
--- a/src/H5Bcache.c
+++ b/src/H5Bcache.c
@@ -152,6 +152,10 @@ H5B_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
/* entries used */
UINT16DECODE(p, bt->nchildren);
+ /* Check if bt->nchildren is greater than two_k */
+ if(bt->nchildren > shared->two_k)
+ HGOTO_ERROR(H5E_BTREE, H5E_BADVALUE, NULL, "number of children is greater than maximum")
+
/* sibling pointers */
H5F_addr_decode(udata->f, (const uint8_t **)&p, &(bt->left));
H5F_addr_decode(udata->f, (const uint8_t **)&p, &(bt->right));
diff --git a/src/H5Dchunk.c b/src/H5Dchunk.c
index 46925a1..af888a9 100644
--- a/src/H5Dchunk.c
+++ b/src/H5Dchunk.c
@@ -974,7 +974,7 @@ H5D_free_chunk_info(void *item, void UNUSED *key, void UNUSED *opdata)
H5S_select_all(chunk_info->fspace, TRUE);
/* Close the chunk's memory dataspace, if it's not shared */
- if(!chunk_info->mspace_shared)
+ if(!chunk_info->mspace_shared && chunk_info->mspace)
(void)H5S_close(chunk_info->mspace);
/* Free the actual chunk info */
diff --git a/src/H5Dcontig.c b/src/H5Dcontig.c
index 674582d..c1ff68c 100644
--- a/src/H5Dcontig.c
+++ b/src/H5Dcontig.c
@@ -420,6 +420,7 @@ H5D_contig_construct(H5F_t *f, H5D_t *dset)
hsize_t nelmts; /* Number of elements in dataspace */
size_t dt_size; /* Size of datatype */
hsize_t tmp_size; /* Temporary holder for raw data size */
+ size_t tmp_sieve_buf_size; /* Temporary holder for sieve buffer size */
hsize_t dim[H5O_LAYOUT_NDIMS]; /* Current size of data in elements */
hsize_t max_dim[H5O_LAYOUT_NDIMS]; /* Maximum size of data in elements */
int ndims; /* Rank of dataspace */
@@ -464,8 +465,15 @@ H5D_contig_construct(H5F_t *f, H5D_t *dset)
/* Assign the dataset's contiguous storage size */
dset->shared->layout.storage.u.contig.size = tmp_size;
- /* Get the sieve buffer size for this dataset */
- dset->shared->cache.contig.sieve_buf_size = H5F_SIEVE_BUF_SIZE(f);
+ /* Get the sieve buffer size for the file */
+ tmp_sieve_buf_size = H5F_SIEVE_BUF_SIZE(f);
+
+ /* Adjust the sieve buffer size to the smaller one between the dataset size and the buffer size
+ * from the file access property. (SLU - 2012/3/30) */
+ if(tmp_size < tmp_sieve_buf_size)
+ dset->shared->cache.contig.sieve_buf_size = tmp_size;
+ else
+ dset->shared->cache.contig.sieve_buf_size = tmp_sieve_buf_size;
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -965,6 +973,7 @@ H5D_contig_writevv_sieve_cb(hsize_t dst_off, hsize_t src_off, size_t len,
/* Allocate room for the data sieve buffer */
if(NULL == (dset_contig->sieve_buf = H5FL_BLK_MALLOC(sieve_buf, dset_contig->sieve_buf_size)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "memory allocation failed")
+
#ifdef H5_CLEAR_MEMORY
if(dset_contig->sieve_size > len)
HDmemset(dset_contig->sieve_buf + len, 0, (dset_contig->sieve_size - len));
diff --git a/src/H5Dint.c b/src/H5Dint.c
index 31cd84b..e17c0f7 100644
--- a/src/H5Dint.c
+++ b/src/H5Dint.c
@@ -68,7 +68,6 @@ static herr_t H5D_init_space(H5F_t *file, const H5D_t *dset, const H5S_t *space)
static herr_t H5D_update_oh_info(H5F_t *file, hid_t dxpl_id, H5D_t *dset,
hid_t dapl_id);
static herr_t H5D_open_oid(H5D_t *dataset, hid_t dapl_id, hid_t dxpl_id);
-static herr_t H5D_flush_real(H5D_t *dataset, hid_t dxpl_id);
/*********************/
@@ -2440,7 +2439,8 @@ H5D_flush(const H5F_t *f, hid_t dxpl_id)
udata.dxpl_id = dxpl_id;
/* Iterate over all the open datasets */
- H5I_search(H5I_DATASET, H5D_flush_cb, &udata, FALSE);
+ if(H5I_iterate(H5I_DATASET, H5D_flush_cb, &udata, FALSE) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_BADITER, FAIL, "unable to flush cached dataset info")
done:
FUNC_LEAVE_NOAPI(ret_value)
diff --git a/src/H5Dio.c b/src/H5Dio.c
index 49a8f25..7a58c4a 100644
--- a/src/H5Dio.c
+++ b/src/H5Dio.c
@@ -362,6 +362,7 @@ H5D_read(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space,
|| dataset->shared->layout.type == H5D_COMPACT);
/* Call storage method's I/O initialization routine */
+ HDmemset(&fm, 0, sizeof(H5D_chunk_map_t));
if(io_info.layout_ops.io_init && (*io_info.layout_ops.io_init)(&io_info, &type_info, nelmts, file_space, mem_space, &fm) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't initialize I/O info")
io_op_init = TRUE;
@@ -585,6 +586,7 @@ H5D_write(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space,
#endif /*H5_HAVE_PARALLEL*/
/* Call storage method's I/O initialization routine */
+ HDmemset(&fm, 0, sizeof(H5D_chunk_map_t));
if(io_info.layout_ops.io_init && (*io_info.layout_ops.io_init)(&io_info, &type_info, nelmts, file_space, mem_space, &fm) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't initialize I/O info")
io_op_init = TRUE;
diff --git a/src/H5Dlayout.c b/src/H5Dlayout.c
index 7ec6404..53d49aa 100644
--- a/src/H5Dlayout.c
+++ b/src/H5Dlayout.c
@@ -384,6 +384,10 @@ H5D_layout_oh_read(H5D_t *dataset, hid_t dxpl_id, hid_t dapl_id, H5P_genplist_t
switch(dataset->shared->layout.type) {
case H5D_CONTIGUOUS:
+ {
+ hsize_t tmp_size; /* Temporary holder for raw data size */
+ size_t tmp_sieve_buf_size; /* Temporary holder for sieve buffer size */
+
/* Compute the size of the contiguous storage for versions of the
* layout message less than version 3 because versions 1 & 2 would
* truncate the dimension sizes to 32-bits of information. - QAK 5/26/04
@@ -392,7 +396,6 @@ H5D_layout_oh_read(H5D_t *dataset, hid_t dxpl_id, hid_t dapl_id, H5P_genplist_t
hssize_t snelmts; /* Temporary holder for number of elements in dataspace */
hsize_t nelmts; /* Number of elements in dataspace */
size_t dt_size; /* Size of datatype */
- hsize_t tmp_size; /* Temporary holder for raw data size */
/* Retrieve the number of elements in the dataspace */
if((snelmts = H5S_GET_EXTENT_NPOINTS(dataset->shared->space)) < 0)
@@ -412,10 +415,19 @@ H5D_layout_oh_read(H5D_t *dataset, hid_t dxpl_id, hid_t dapl_id, H5P_genplist_t
/* Assign the dataset's contiguous storage size */
dataset->shared->layout.storage.u.contig.size = tmp_size;
- } /* end if */
-
- /* Get the sieve buffer size for this dataset */
- dataset->shared->cache.contig.sieve_buf_size = H5F_SIEVE_BUF_SIZE(dataset->oloc.file);
+ } else
+ tmp_size = dataset->shared->layout.storage.u.contig.size;
+
+ /* Get the sieve buffer size for the file */
+ tmp_sieve_buf_size = H5F_SIEVE_BUF_SIZE(dataset->oloc.file);
+
+ /* Adjust the sieve buffer size to the smaller one between the dataset size and the buffer size
+ * from the file access property. (SLU - 2012/3/30) */
+ if(tmp_size < tmp_sieve_buf_size)
+ dataset->shared->cache.contig.sieve_buf_size = tmp_size;
+ else
+ dataset->shared->cache.contig.sieve_buf_size = tmp_sieve_buf_size;
+ }
break;
case H5D_CHUNKED:
diff --git a/src/H5Doh.c b/src/H5Doh.c
index 7a657ec..e6a715f 100644
--- a/src/H5Doh.c
+++ b/src/H5Doh.c
@@ -56,6 +56,8 @@ static H5O_loc_t *H5O_dset_get_oloc(hid_t obj_id);
static herr_t H5O_dset_bh_info(H5F_t *f, hid_t dxpl_id, H5O_t *oh,
H5_ih_info_t *bh_info);
+static herr_t H5O_dset_flush(H5G_loc_t *obj_loc, hid_t dxpl_id);
+
/*********************/
/* Package Variables */
@@ -81,7 +83,8 @@ const H5O_obj_class_t H5O_OBJ_DATASET[1] = {{
H5O_dset_open, /* open an object of this class */
H5O_dset_create, /* create an object of this class */
H5O_dset_get_oloc, /* get an object header location for an object */
- H5O_dset_bh_info /* get the index & heap info for an object */
+ H5O_dset_bh_info, /* get the index & heap info for an object */
+ H5O_dset_flush /* flush an opened object of this class */
}};
/* Declare a free list to manage the H5D_copy_file_ud_t struct */
@@ -431,3 +434,48 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_dset_bh_info() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_dset_flush
+ *
+ * Purpose: To flush any dataset information cached in memory
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Vailin Choi
+ * February 2012
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O_dset_flush(H5G_loc_t *obj_loc, hid_t dxpl_id)
+{
+ H5D_t *dset; /* Dataset opened */
+ H5O_type_t obj_type; /* Type of object at location */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ HDassert(obj_loc);
+ HDassert(obj_loc->oloc);
+
+ /* Check that the object found is the correct type */
+ if(H5O_obj_type(obj_loc->oloc, &obj_type, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get object type")
+
+ if(obj_type != H5O_TYPE_DATASET)
+ HGOTO_ERROR(H5E_DATASET, H5E_BADTYPE, FAIL, "not a dataset")
+
+ /* Open the dataset */
+ if(NULL == (dset = H5D_open(obj_loc, H5P_DATASET_ACCESS_DEFAULT, dxpl_id)))
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "unable to open dataset")
+
+ if(H5D_flush_real(dset, dxpl_id) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to flush cached dataset info")
+
+done:
+ if(dset && H5D_close(dset) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, NULL, "unable to release dataset")
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_dset_flush() */
diff --git a/src/H5Dpkg.h b/src/H5Dpkg.h
index 16de07f..40317f3 100644
--- a/src/H5Dpkg.h
+++ b/src/H5Dpkg.h
@@ -548,6 +548,7 @@ H5_DLL herr_t H5D_set_extent(H5D_t *dataset, const hsize_t *size, hid_t dxpl_id)
H5_DLL herr_t H5D_get_dxpl_cache(hid_t dxpl_id, H5D_dxpl_cache_t **cache);
H5_DLL herr_t H5D_flush_sieve_buf(H5D_t *dataset, hid_t dxpl_id);
H5_DLL herr_t H5D_mark(H5D_t *dataset, hid_t dxpl_id, unsigned flags);
+H5_DLL herr_t H5D_flush_real(H5D_t *dataset, hid_t dxpl_id);
/* Functions that perform direct serial I/O operations */
H5_DLL herr_t H5D_select_read(const H5D_io_info_t *io_info,
diff --git a/src/H5E.c b/src/H5E.c
index 4e14887..e74211e 100644
--- a/src/H5E.c
+++ b/src/H5E.c
@@ -107,7 +107,7 @@ static H5E_cls_t *H5E_register_class(const char *cls_name, const char *lib_name,
const char *version);
static herr_t H5E_unregister_class(H5E_cls_t *cls);
static ssize_t H5E_get_class_name(const H5E_cls_t *cls, char *name, size_t size);
-static int H5E_close_msg_cb(void *obj_ptr, hid_t obj_id, void *key);
+static int H5E_close_msg_cb(void *obj_ptr, hid_t obj_id, void *udata);
static herr_t H5E_close_msg(H5E_msg_t *err);
static H5E_msg_t *H5E_create_msg(H5E_cls_t *cls, H5E_type_t msg_type, const char *msg);
static H5E_t *H5E_get_current_stack(void);
@@ -543,8 +543,8 @@ H5E_unregister_class(H5E_cls_t *cls)
HDassert(cls);
/* Iterate over all the messages and delete those in this error class */
- /* (Ignore return value, since callback isn't designed to return a particular object) */
- (void)H5I_search(H5I_ERROR_MSG, H5E_close_msg_cb, cls, FALSE);
+ if(H5I_iterate(H5I_ERROR_MSG, H5E_close_msg_cb, cls, FALSE) < 0)
+ HGOTO_ERROR(H5E_ERROR, H5E_BADITER, FAIL, "unable to free all messages in this error class")
/* Free error class structure */
if(H5E_free_class(cls) < 0)
@@ -631,7 +631,7 @@ H5E_get_class_name(const H5E_cls_t *cls, char *name, size_t size)
/*-------------------------------------------------------------------------
* Function: H5E_close_msg_cb
*
- * Purpose: H5I_search callback function to close error messages in the
+ * Purpose: H5I_iterate callback function to close error messages in the
* error class.
*
* Return: Non-negative value on success/Negative on failure
@@ -642,10 +642,10 @@ H5E_get_class_name(const H5E_cls_t *cls, char *name, size_t size)
*-------------------------------------------------------------------------
*/
static int
-H5E_close_msg_cb(void *obj_ptr, hid_t obj_id, void *key)
+H5E_close_msg_cb(void *obj_ptr, hid_t obj_id, void *udata)
{
H5E_msg_t *err_msg = (H5E_msg_t*)obj_ptr;
- H5E_cls_t *cls = (H5E_cls_t*)key;
+ H5E_cls_t *cls = (H5E_cls_t*)udata;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT
diff --git a/src/H5Edefin.h b/src/H5Edefin.h
index 7fa8b12..27275a3 100644
--- a/src/H5Edefin.h
+++ b/src/H5Edefin.h
@@ -94,6 +94,7 @@ hid_t H5E_CANTRELEASE_g = FAIL; /* Unable to release object */
hid_t H5E_CANTGET_g = FAIL; /* Can't get value */
hid_t H5E_CANTSET_g = FAIL; /* Can't set value */
hid_t H5E_DUPCLASS_g = FAIL; /* Duplicate class name in parent class */
+hid_t H5E_SETDISALLOWED_g = FAIL; /* Disallowed operation */
/* Free space errors */
hid_t H5E_CANTMERGE_g = FAIL; /* Can't merge objects */
diff --git a/src/H5Einit.h b/src/H5Einit.h
index 7022297..99467ee 100644
--- a/src/H5Einit.h
+++ b/src/H5Einit.h
@@ -344,6 +344,11 @@ if((msg = H5E_create_msg(cls, H5E_MINOR, "Duplicate class name in parent class")
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
if((H5E_DUPCLASS_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
+assert(H5E_SETDISALLOWED_g==(-1));
+if((msg = H5E_create_msg(cls, H5E_MINOR, "Disallowed operation"))==NULL)
+ HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
+if((H5E_SETDISALLOWED_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
+ HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
/* Free space errors */
assert(H5E_CANTMERGE_g==(-1));
diff --git a/src/H5Epubgen.h b/src/H5Epubgen.h
index 12771b2..68c605c 100644
--- a/src/H5Epubgen.h
+++ b/src/H5Epubgen.h
@@ -157,9 +157,11 @@ H5_DLLVAR hid_t H5E_CANTRELEASE_g; /* Unable to release object */
#define H5E_CANTGET (H5OPEN H5E_CANTGET_g)
#define H5E_CANTSET (H5OPEN H5E_CANTSET_g)
#define H5E_DUPCLASS (H5OPEN H5E_DUPCLASS_g)
+#define H5E_SETDISALLOWED (H5OPEN H5E_SETDISALLOWED_g)
H5_DLLVAR hid_t H5E_CANTGET_g; /* Can't get value */
H5_DLLVAR hid_t H5E_CANTSET_g; /* Can't set value */
H5_DLLVAR hid_t H5E_DUPCLASS_g; /* Duplicate class name in parent class */
+H5_DLLVAR hid_t H5E_SETDISALLOWED_g; /* Disallowed operation */
/* Free space errors */
#define H5E_CANTMERGE (H5OPEN H5E_CANTMERGE_g)
diff --git a/src/H5Eterm.h b/src/H5Eterm.h
index 1860c19..28d822a 100644
--- a/src/H5Eterm.h
+++ b/src/H5Eterm.h
@@ -95,7 +95,8 @@ H5E_CANTRELEASE_g=
/* Property list errors */
H5E_CANTGET_g=
H5E_CANTSET_g=
-H5E_DUPCLASS_g=
+H5E_DUPCLASS_g=
+H5E_SETDISALLOWED_g=
/* Free space errors */
H5E_CANTMERGE_g=
diff --git a/src/H5F.c b/src/H5F.c
index 7c7db13..93d7cc6 100644
--- a/src/H5F.c
+++ b/src/H5F.c
@@ -53,7 +53,7 @@ typedef struct H5F_olist_t {
} H5F_olist_t;
/* PRIVATE PROTOTYPES */
-static size_t H5F_get_objects(const H5F_t *f, unsigned types, size_t max_objs, hid_t *obj_id_list, hbool_t app_ref);
+static herr_t H5F_get_objects(const H5F_t *f, unsigned types, size_t max_index, hid_t *obj_id_list, hbool_t app_ref, size_t *obj_id_count_ptr);
static int H5F_get_objects_cb(void *obj_ptr, hid_t obj_id, void *key);
static H5F_t *H5F_new(H5F_file_t *shared, hid_t fcpl_id, hid_t fapl_id,
H5FD_t *lf);
@@ -353,42 +353,38 @@ done:
*
* Programmer: Raymond Lu
* Wednesday, Dec 5, 2001
- * Modification:
- * Raymond Lu
- * 24 September 2008
- * Changed the return value to ssize_t to accommadate
- * potential large number of objects.
*
*-------------------------------------------------------------------------
*/
ssize_t
-H5Fget_obj_count(hid_t uid, unsigned types)
+H5Fget_obj_count(hid_t file_id, unsigned types)
{
- H5F_t *f = NULL; /* File to query */
- H5VL_id_wrapper_t *id_wrapper; /* user id structure */
- hid_t id;
- ssize_t ret_value; /* Return value */
+ H5F_t *f = NULL; /* File to query */
+ ssize_t ret_value; /* Return value */
+ size_t obj_count = 0; /* Number of opened objects */
FUNC_ENTER_API(FAIL)
- H5TRACE2("Zs", "iIu", uid, types);
+ H5TRACE2("Zs", "iIu", file_id, types);
- if (H5I_FILE_PUBLIC == H5I_get_type(uid)) {
- if(NULL == (id_wrapper = (H5VL_id_wrapper_t *)H5I_object(uid)))
+ if (H5I_FILE_PUBLIC == H5I_get_type(file_id)) {
+ H5VL_id_wrapper_t *id_wrapper; /* wrapper object */
+
+ if(NULL == (id_wrapper = (H5VL_id_wrapper_t *)H5I_object(file_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid user identifier")
- id = id_wrapper->obj_id;
- }
- else {
- id = uid;
+ file_id = id_wrapper->obj_id;
}
- if(id != (hid_t)H5F_OBJ_ALL &&
- (NULL == (f = (H5F_t *)H5I_object_verify(id, H5I_FILE))))
+ if(file_id != (hid_t)H5F_OBJ_ALL && (NULL == (f = (H5F_t *)H5I_object_verify(file_id, H5I_FILE))))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file id")
if(0 == (types & H5F_OBJ_ALL))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not an object type")
- /* H5F_get_obj_count doesn't fail */
- ret_value = (ssize_t)H5F_get_obj_count(f, types, TRUE);
+ /* Perform the query */
+ if(H5F_get_obj_count(f, types, TRUE, &obj_count) < 0)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_BADITER, FAIL, "H5F_get_obj_count failed")
+
+ /* Set the return value */
+ ret_value = (ssize_t)obj_count;
done:
FUNC_LEAVE_API(ret_value)
@@ -401,31 +397,30 @@ done:
* Purpose: Private function return the number of opened object IDs
* (files, datasets, groups, datatypes) in the same file.
*
- * Return: Non-negative on success; can't fail.
+ * Return: SUCCEED on success, FAIL on failure.
*
* Programmer: Raymond Lu
* Wednesday, Dec 5, 2001
*
- * Modification:
- * Raymond Lu
- * 24 September 2008
- * Changed the return value to size_t to accommadate
- * potential large number of objects.
- *
*-------------------------------------------------------------------------
*/
-size_t
-H5F_get_obj_count(const H5F_t *f, unsigned types, hbool_t app_ref)
+herr_t
+H5F_get_obj_count(const H5F_t *f, unsigned types, hbool_t app_ref, size_t *obj_id_count_ptr)
{
- size_t ret_value; /* Return value */
+ herr_t ret_value = SUCCEED;
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_NOAPI(FAIL)
- /* H5F_get_objects doesn't fail */
- ret_value = H5F_get_objects(f, types, 0, NULL, app_ref);
+ /* Sanity check */
+ HDassert(obj_id_count_ptr);
+
+ /* Perform the query */
+ if((ret_value = H5F_get_objects(f, types, 0, NULL, app_ref, obj_id_count_ptr)) < 0)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_BADITER, FAIL, "H5F_get_objects failed")
+done:
FUNC_LEAVE_NOAPI(ret_value)
-}
+} /* end H5F_get_obj_count() */
/*-------------------------------------------------------------------------
@@ -447,34 +442,36 @@ H5F_get_obj_count(const H5F_t *f, unsigned types, hbool_t app_ref)
*-------------------------------------------------------------------------
*/
ssize_t
-H5Fget_obj_ids(hid_t uid, unsigned types, size_t max_objs, hid_t *oid_list)
+H5Fget_obj_ids(hid_t file_id, unsigned types, size_t max_objs, hid_t *oid_list)
{
H5F_t *f = NULL; /* File to query */
- H5VL_id_wrapper_t *id_wrapper; /* user id structure */
- hid_t id;
+ size_t obj_id_count = 0; /* Number of open objects */
ssize_t ret_value; /* Return value */
FUNC_ENTER_API(FAIL)
- H5TRACE4("Zs", "iIuz*i", uid, types, max_objs, oid_list);
+ H5TRACE4("Zs", "iIuz*i", file_id, types, max_objs, oid_list);
- if (H5I_FILE_PUBLIC == H5I_get_type(uid)) {
- if(NULL == (id_wrapper = (H5VL_id_wrapper_t *)H5I_object(uid)))
+ if (H5I_FILE_PUBLIC == H5I_get_type(file_id)) {
+ H5VL_id_wrapper_t *id_wrapper; /* wrapper object */
+
+ if(NULL == (id_wrapper = (H5VL_id_wrapper_t *)H5I_object(file_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid user identifier")
- id = id_wrapper->obj_id;
- }
- else {
- id = uid;
+ file_id = id_wrapper->obj_id;
}
- if(id != (hid_t)H5F_OBJ_ALL &&
- (NULL == (f = (H5F_t *)H5I_object_verify(id, H5I_FILE))))
+ /* Check arguments */
+ if(file_id != (hid_t)H5F_OBJ_ALL && (NULL == (f = (H5F_t *)H5I_object_verify(file_id, H5I_FILE))))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file id")
if(0 == (types & H5F_OBJ_ALL))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not an object type")
HDassert(oid_list);
- /* H5F_get_objects doesn't fail */
- ret_value = (ssize_t)H5F_get_obj_ids(f, types, max_objs, oid_list, TRUE);
+ /* Perform the query */
+ if(H5F_get_obj_ids(f, types, max_objs, oid_list, TRUE, &obj_id_count) < 0)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_BADITER, FAIL, "H5F_get_obj_ids failed")
+
+ /* Set the return value */
+ ret_value = (ssize_t)obj_id_count;
if (H5VL_replace_with_uids (oid_list, ret_value) <= 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, FAIL, "can't get IDs")
@@ -494,26 +491,25 @@ done:
* Programmer: Raymond Lu
* Wednesday, Dec 5, 2001
*
- * Modification:
- * Raymond Lu
- * 24 September 2008
- * Changed the return value and MAX_OBJTS to size_t to accommadate
- * potential large number of objects.
- *
*-------------------------------------------------------------------------
*/
-size_t
-H5F_get_obj_ids(const H5F_t *f, unsigned types, size_t max_objs, hid_t *oid_list, hbool_t app_ref)
+herr_t
+H5F_get_obj_ids(const H5F_t *f, unsigned types, size_t max_objs, hid_t *oid_list, hbool_t app_ref, size_t *obj_id_count_ptr)
{
- size_t ret_value; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_NOAPI(FAIL)
- /* H5F_get_objects doesn't fail */
- ret_value = H5F_get_objects(f, types, max_objs, oid_list, app_ref);
+ /* Sanity check */
+ HDassert(obj_id_count_ptr);
+
+ /* Perform the query */
+ if((ret_value = H5F_get_objects(f, types, max_objs, oid_list, app_ref, obj_id_count_ptr)) < 0)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_BADITER, FAIL, "H5F_get_objects failed")
+done:
FUNC_LEAVE_NOAPI(ret_value)
-}
+} /* end H5F_get_obj_ids() */
/*---------------------------------------------------------------------------
@@ -529,14 +525,18 @@ H5F_get_obj_ids(const H5F_t *f, unsigned types, size_t max_objs, hid_t *oid_list
*
*---------------------------------------------------------------------------
*/
-static size_t
-H5F_get_objects(const H5F_t *f, unsigned types, size_t max_index, hid_t *obj_id_list, hbool_t app_ref)
+static herr_t
+H5F_get_objects(const H5F_t *f, unsigned types, size_t max_index, hid_t *obj_id_list, hbool_t app_ref, size_t *obj_id_count_ptr)
{
size_t obj_id_count=0; /* Number of open IDs */
H5F_olist_t olist; /* Structure to hold search results */
- size_t ret_value; /* Return value */
+ htri_t type_exists; /* Whether objects of a type are open */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_NOAPI_NOINIT
+
+ /* Sanity check */
+ HDassert(obj_id_count_ptr);
/* Set up search information */
olist.obj_id_list = (max_index==0 ? NULL : obj_id_list);
@@ -554,45 +554,50 @@ H5F_get_objects(const H5F_t *f, unsigned types, size_t max_index, hid_t *obj_id_
olist.file_info.ptr.shared = f ? f->shared : NULL;
} /* end else */
- /* Search through file IDs to count the number, and put their
- * IDs on the object list. H5I_search returns NULL if no object
- * is found, so don't return failure in this function. */
+ /* Iterate through file IDs to count the number, and put their
+ * IDs on the object list. */
if(types & H5F_OBJ_FILE) {
olist.obj_type = H5I_FILE;
- (void)H5I_search(H5I_FILE, H5F_get_objects_cb, &olist, app_ref);
+ if(H5I_iterate(H5I_FILE, H5F_get_objects_cb, &olist, app_ref) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "iteration failed(1)")
} /* end if */
/* Search through dataset IDs to count number of datasets, and put their
* IDs on the object list */
if(types & H5F_OBJ_DATASET) {
olist.obj_type = H5I_DATASET;
- (void)H5I_search(H5I_DATASET, H5F_get_objects_cb, &olist, app_ref);
- }
+ if(H5I_iterate(H5I_DATASET, H5F_get_objects_cb, &olist, app_ref) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "iteration failed(2)")
+ } /* end if */
/* Search through group IDs to count number of groups, and put their
* IDs on the object list */
if(types & H5F_OBJ_GROUP) {
olist.obj_type = H5I_GROUP;
- (void)H5I_search(H5I_GROUP, H5F_get_objects_cb, &olist, app_ref);
- }
+ if(H5I_iterate(H5I_GROUP, H5F_get_objects_cb, &olist, app_ref) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "iteration failed(3)")
+ } /* end if */
/* Search through datatype IDs to count number of named datatypes, and put their
* IDs on the object list */
if(types & H5F_OBJ_DATATYPE) {
olist.obj_type = H5I_DATATYPE;
- (void)H5I_search(H5I_DATATYPE, H5F_get_objects_cb, &olist, app_ref);
- }
+ if(H5I_iterate(H5I_DATATYPE, H5F_get_objects_cb, &olist, app_ref) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "iteration failed(4)")
+ } /* end if */
/* Search through attribute IDs to count number of attributes, and put their
* IDs on the object list */
if(types & H5F_OBJ_ATTR) {
olist.obj_type = H5I_ATTR;
- (void)H5I_search(H5I_ATTR, H5F_get_objects_cb, &olist, app_ref);
- }
+ if(H5I_iterate(H5I_ATTR, H5F_get_objects_cb, &olist, app_ref) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "iteration failed(5)")
+ } /* end if */
/* Set the number of objects currently open */
- ret_value = obj_id_count;
+ *obj_id_count_ptr = obj_id_count;
+done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5F_get_objects() */
@@ -610,8 +615,6 @@ H5F_get_objects(const H5F_t *f, unsigned types, size_t max_index, hid_t *obj_id_
* Programmer: Raymond Lu
* Wednesday, Dec 5, 2001
*
- * Modification:
- *
*-------------------------------------------------------------------------
*/
static int
@@ -643,8 +646,8 @@ H5F_get_objects_cb(void *obj_ptr, hid_t obj_id, void *key)
/* Check if we've filled up the array. Return TRUE only if
* we have filled up the array. Otherwise return FALSE(RET_VALUE is
- * preset to FALSE) because H5I_search needs the return value of FALSE
- * to continue searching. */
+ * preset to FALSE) because H5I_iterate needs the return value of
+ * FALSE to continue the iteration. */
if(olist->max_index>0 && olist->list_index>=olist->max_index)
HGOTO_DONE(TRUE) /* Indicate that the iterator should stop */
}
@@ -709,8 +712,8 @@ H5F_get_objects_cb(void *obj_ptr, hid_t obj_id, void *key)
/* Check if we've filled up the array. Return TRUE only if
* we have filled up the array. Otherwise return FALSE(RET_VALUE is
- * preset to FALSE) because H5I_search needs the return value of FALSE
- * to continue searching. */
+ * preset to FALSE) because H5I_iterate needs the return value of
+ * FALSE to continue iterating. */
if(olist->max_index>0 && olist->list_index>=olist->max_index)
HGOTO_DONE(TRUE) /* Indicate that the iterator should stop */
} /* end if */
@@ -1679,8 +1682,6 @@ done:
* Programmer: Quincey Koziol
* Tuesday, July 19, 2005
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
herr_t
@@ -1762,27 +1763,36 @@ H5F_try_close(H5F_t *f)
if(f->nopen_objs > 0) {
size_t obj_count; /* # of open objects */
hid_t objs[128]; /* Array of objects to close */
+ herr_t result; /* Local result from obj ID query */
size_t u; /* Local index variable */
/* Get the list of IDs of open dataset, group, & attribute objects */
- while((obj_count = H5F_get_obj_ids(f, H5F_OBJ_LOCAL|H5F_OBJ_DATASET|H5F_OBJ_GROUP|H5F_OBJ_ATTR, (int)(sizeof(objs)/sizeof(objs[0])), objs, FALSE)) != 0) {
+ while((result = H5F_get_obj_ids(f, H5F_OBJ_LOCAL | H5F_OBJ_DATASET | H5F_OBJ_GROUP | H5F_OBJ_ATTR, (int)(sizeof(objs) / sizeof(objs[0])), objs, FALSE, &obj_count)) <= 0
+ && obj_count != 0 ) {
+
/* Try to close all the open objects in this file */
for(u = 0; u < obj_count; u++)
if(H5I_dec_ref(objs[u]) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CLOSEERROR, FAIL, "can't close object")
} /* end while */
+ if(result < 0)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_BADITER, FAIL, "H5F_get_obj_ids failed(1)")
/* Get the list of IDs of open named datatype objects */
/* (Do this separately from the dataset & attribute IDs, because
* they could be using one of the named datatypes and then the
* open named datatype ID will get closed twice)
*/
- while((obj_count = H5F_get_obj_ids(f, H5F_OBJ_LOCAL|H5F_OBJ_DATATYPE, (int)(sizeof(objs)/sizeof(objs[0])), objs, FALSE)) != 0) {
+ while((result = H5F_get_obj_ids(f, H5F_OBJ_LOCAL | H5F_OBJ_DATATYPE, (int)(sizeof(objs) / sizeof(objs[0])), objs, FALSE, &obj_count)) <= 0
+ && obj_count != 0) {
+
/* Try to close all the open objects in this file */
for(u = 0; u < obj_count; u++)
if(H5I_dec_ref(objs[u]) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CLOSEERROR, FAIL, "can't close object")
} /* end while */
+ if(result < 0)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_BADITER, FAIL, "H5F_get_obj_ids failed(2)")
} /* end if */
} /* end if */
@@ -2427,6 +2437,139 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5Fget_file_image
+ *
+ * Purpose: If a buffer is provided (via the buf_ptr argument) and is
+ * big enough (size in buf_len argument), load *buf_ptr with
+ * an image of the open file whose ID is provided in the
+ * file_id parameter, and return the number of bytes copied
+ * to the buffer.
+ *
+ * If the buffer exists, but is too small to contain an image
+ * of the indicated file, return a negative number.
+ *
+ * Finally, if no buffer is provided, return the size of the
+ * buffer needed. This value is simply the eoa of the target
+ * file.
+ *
+ * Note that any user block is skipped.
+ *
+ * Also note that the function may not be used on files
+ * opened with either the split/multi file driver or the
+ * family file driver.
+ *
+ * In the former case, the sparse address space makes the
+ * get file image operation impractical, due to the size of
+ * the image typically required.
+ *
+ * In the case of the family file driver, the problem is
+ * the driver message in the super block, which will prevent
+ * the image being opened with any driver other than the
+ * family file driver -- which negates the purpose of the
+ * operation. This can be fixed, but no resources for
+ * this now.
+ *
+ * Return: Success: Bytes copied / number of bytes needed.
+ * Failure: negative value
+ *
+ * Programmer: John Mainzer
+ * 11/15/11
+ *
+ *-------------------------------------------------------------------------
+ */
+ssize_t
+H5Fget_file_image(hid_t file_id, void *buf_ptr, size_t buf_len)
+{
+ H5F_t *file; /* File object for file ID */
+ H5FD_t *fd_ptr; /* file driver */
+ haddr_t eoa; /* End of file address */
+ ssize_t ret_value; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE3("Zs", "i*xz", file_id, buf_ptr, buf_len);
+
+ /* Check args */
+ if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file ID")
+ if(!file || !file->shared || !file->shared->lf)
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "file_id yields invalid file pointer")
+ fd_ptr = file->shared->lf;
+ if(!fd_ptr->cls)
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "fd_ptr yields invalid class pointer")
+
+ /* the address space used by the split and multi file drivers is not
+ * a good fit for this call. Since the plan is to depreciate these
+ * drivers anyway, don't bother to do a "force fit".
+ *
+ * The following clause tests for the multi file driver, and fails
+ * if the supplied file has the multi file driver as its top level
+ * file driver. However, this test will not work if there is some
+ * other file driver sitting on top of the multi file driver.
+ *
+ * I'm not sure if this is possible at present, but in all likelyhood,
+ * it will become possible in the future. On the other hand, we may
+ * remove the split/multi file drivers before then.
+ *
+ * I am leaving this solution in for now, but we should review it,
+ * and improve the solution if necessary.
+ *
+ * JRM -- 11/11/22
+ */
+ if(HDstrcmp(fd_ptr->cls->name, "multi") == 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Not supported for multi file driver.")
+
+ /* While the family file driver is conceptually fully compatible
+ * with the get file image operation, it sets a file driver message
+ * in the super block that prevents the image being opened with any
+ * driver other than the family file driver. Needless to say, this
+ * rather defeats the purpose of the get file image operation.
+ *
+ * While this problem is quire solvable, the required time and
+ * resources are lacking at present. Hence, for now, we don't
+ * allow the get file image operation to be perfomed on files
+ * opened with the family file driver.
+ *
+ * Observe that the following test only looks at the top level
+ * driver, and fails if there is some other driver sitting on to
+ * of the family file driver.
+ *
+ * I don't think this can happen at present, but that may change
+ * in the future.
+ * JRM -- 12/21/11
+ */
+ if(HDstrcmp(fd_ptr->cls->name, "family") == 0)
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "Not supported for family file driver.")
+
+
+ /* Go get the actual file size */
+ if(HADDR_UNDEF == (eoa = H5FD_get_eoa(file->shared->lf, H5FD_MEM_DEFAULT)))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get file size")
+
+ /* set ret_value = to eoa -- will overwrite this if appropriate */
+ ret_value = (ssize_t)eoa;
+
+ /* test to see if a buffer was provided -- if not, we are done */
+ if(buf_ptr != NULL) {
+ size_t space_needed; /* size of file image */
+
+ /* Check for buffer too small */
+ if((haddr_t)buf_len < eoa)
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "supplied buffer too small")
+
+ space_needed = (size_t)eoa;
+
+ /* read in the file image */
+ /* (Note compensation for base address addition in internal routine) */
+ if(H5FD_read(fd_ptr, H5AC_ind_dxpl_id, H5FD_MEM_DEFAULT, 0, space_needed, buf_ptr) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_READERROR, FAIL, "file image read request failed")
+ } /* end if */
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* H5Fget_file_image() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5Fget_mdc_config
*
* Purpose: Retrieves the current automatic cache resize configuration
diff --git a/src/H5FD.c b/src/H5FD.c
index 66fa3b9..18b0eb6 100644
--- a/src/H5FD.c
+++ b/src/H5FD.c
@@ -70,6 +70,10 @@ static herr_t H5FD_pl_copy(void *(*copy_func)(const void *), size_t pl_size,
static herr_t H5FD_pl_close(hid_t driver_id, herr_t (*free_func)(void *),
void *pl);
static herr_t H5FD_free_cls(H5FD_class_t *cls);
+static herr_t H5FD_fapl_copy(hid_t driver_id, const void *fapl, void **copied_fapl);
+static herr_t H5FD_dxpl_copy(hid_t driver_id, const void *dxpl, void **copied_dxpl);
+static int H5FD_query(const H5FD_t *f, unsigned long *flags/*out*/);
+static int H5FD_driver_query(const H5FD_class_t *driver, unsigned long *flags/*out*/);
/*********************/
/* Package Variables */
@@ -750,17 +754,15 @@ done:
* Programmer: Robb Matzke
* Tuesday, August 3, 1999
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
-herr_t
+static herr_t
H5FD_fapl_copy(hid_t driver_id, const void *old_fapl, void **copied_fapl)
{
H5FD_class_t *driver;
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(FAIL)
+ FUNC_ENTER_NOAPI_NOINIT
/* Check args */
if(NULL == (driver = (H5FD_class_t *)H5I_object(driver_id)))
@@ -871,17 +873,15 @@ done:
* Programmer: Robb Matzke
* Tuesday, August 3, 1999
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
-herr_t
+static herr_t
H5FD_dxpl_copy(hid_t driver_id, const void *old_dxpl, void **copied_dxpl)
{
H5FD_class_t *driver;
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(FAIL)
+ FUNC_ENTER_NOAPI_NOINIT
/* Check args */
if(NULL == (driver = (H5FD_class_t *)H5I_object(driver_id)))
@@ -1039,6 +1039,8 @@ H5FD_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr)
H5FD_t *file = NULL; /* VFD file struct */
hid_t driver_id = -1; /* VFD ID */
H5P_genplist_t *plist; /* Property list pointer */
+ unsigned long driver_flags = 0; /* File-inspecific driver feature flags */
+ H5FD_file_image_info_t file_image_info; /* Initial file image */
H5FD_t *ret_value; /* Return value */
FUNC_ENTER_NOAPI(NULL)
@@ -1061,6 +1063,19 @@ H5FD_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr)
if(NULL == driver->open)
HGOTO_ERROR(H5E_VFL, H5E_UNSUPPORTED, NULL, "file driver has no `open' method")
+ /* Query driver flag */
+ H5FD_driver_query(driver, &driver_flags);
+
+ /* Get initial file image info */
+ if(H5P_get(plist, H5F_ACS_FILE_IMAGE_INFO_NAME, &file_image_info) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get file image info")
+
+ /* If an image is provided, make sure the driver supports this feature */
+ HDassert(((file_image_info.buffer != NULL) && (file_image_info.size > 0)) ||
+ ((file_image_info.buffer == NULL) && (file_image_info.size == 0)));
+ if((file_image_info.buffer != NULL) && !(driver_flags & H5FD_FEAT_ALLOW_FILE_IMAGE))
+ HGOTO_ERROR(H5E_VFL, H5E_UNSUPPORTED, NULL, "file image set, but not supported.")
+
/* Dispatch to file driver */
if(HADDR_UNDEF == maxaddr)
maxaddr = driver->maxaddr;
@@ -1318,19 +1333,17 @@ done:
* Programmer: Quincey Koziol
* Friday, August 25, 2000
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
-int
+static int
H5FD_query(const H5FD_t *f, unsigned long *flags/*out*/)
{
- int ret_value=0;
+ int ret_value = 0; /* Return value */
- FUNC_ENTER_NOAPI(FAIL)
+ FUNC_ENTER_NOAPI_NOINIT
- assert(f);
- assert(flags);
+ HDassert(f);
+ HDassert(flags);
/* Check for query driver and call it */
if(f->cls->query)
@@ -1340,7 +1353,44 @@ H5FD_query(const H5FD_t *f, unsigned long *flags/*out*/)
done:
FUNC_LEAVE_NOAPI(ret_value)
-}
+} /* end H5FD_query() */
+
+
+/*-------------------------------------------------------------------------
+* Function: H5FD_driver_query
+*
+* Purpose: Similar to H5FD_query(), but intended for cases when we don't
+* have a file available (e.g. before one is opened). Since we
+* can't use the file to get the driver, the driver is passed in
+* as a parameter.
+*
+* Return: Success: non-negative
+* Failure: negative
+*
+* Programmer: Jacob Gruber
+* Wednesday, August 17, 2011
+*
+*-------------------------------------------------------------------------
+*/
+static int
+H5FD_driver_query(const H5FD_class_t *driver, unsigned long *flags/*out*/)
+{
+ int ret_value = 0; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ HDassert(driver);
+ HDassert(flags);
+
+ /* Check for the driver to query and then query it */
+ if(driver->query)
+ ret_value = (driver->query)(NULL, flags);
+ else
+ *flags = 0;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD_driver_query() */
/*-------------------------------------------------------------------------
diff --git a/src/H5FDcore.c b/src/H5FDcore.c
index 940d4c7..1fef36c 100644
--- a/src/H5FDcore.c
+++ b/src/H5FDcore.c
@@ -101,6 +101,7 @@ typedef struct H5FD_core_t {
HANDLE hFile; /* Native windows file handle */
#endif /* H5_HAVE_WIN32_API */
hbool_t dirty; /*changes not saved? */
+ H5FD_file_image_callbacks_t fi_callbacks; /* file image callbacks */
} H5FD_core_t;
/* Driver-specific file access properties */
@@ -412,6 +413,7 @@ H5FD_core_open(const char *name, unsigned flags, hid_t fapl_id,
#endif
h5_stat_t sb;
int fd=-1;
+ H5FD_file_image_info_t file_image_info;
H5FD_t *ret_value;
FUNC_ENTER_NOAPI_NOINIT
@@ -434,10 +436,32 @@ H5FD_core_open(const char *name, unsigned flags, hid_t fapl_id,
if(H5F_ACC_CREAT & flags) o_flags |= O_CREAT;
if(H5F_ACC_EXCL & flags) o_flags |= O_EXCL;
+ /* Retrieve initial file image info */
+ if(H5P_get(plist, H5F_ACS_FILE_IMAGE_INFO_NAME, &file_image_info) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get initial file image info")
+
+ /* If the file image exists and this is an open, make sure the file doesn't exist */
+ HDassert(((file_image_info.buffer != NULL) && (file_image_info.size > 0)) ||
+ ((file_image_info.buffer == NULL) && (file_image_info.size == 0)));
+ if((file_image_info.buffer != NULL) && !(H5F_ACC_CREAT & flags)) {
+ if(HDopen(name, o_flags, 0666) >= 0)
+ HGOTO_ERROR(H5E_FILE, H5E_FILEEXISTS, NULL, "file already exists")
+
+ /* If backing store is requested, create and stat the file
+ * Note: We are forcing the O_CREAT flag here, even though this is
+ * technically an open.
+ */
+ if(fa->backing_store) {
+ if((fd = HDopen(name, o_flags | O_CREAT, 0666)) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to create file")
+ if(HDfstat(fd, &sb) < 0)
+ HSYS_GOTO_ERROR(H5E_FILE, H5E_BADFILE, NULL, "unable to fstat file")
+ } /* end if */
+ } /* end if */
/* Open backing store, and get stat() from file. The only case that backing
* store is off is when the backing_store flag is off and H5F_ACC_CREAT is
* on. */
- if(fa->backing_store || !(H5F_ACC_CREAT & flags)) {
+ else if(fa->backing_store || !(H5F_ACC_CREAT & flags)) {
if(fa && (fd = HDopen(name, o_flags, 0666)) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to open file")
if(HDfstat(fd, &sb) < 0)
@@ -460,6 +484,9 @@ H5FD_core_open(const char *name, unsigned flags, hid_t fapl_id,
/* If save data in backing store. */
file->backing_store = fa->backing_store;
+ /* Save file image callbacks */
+ file->fi_callbacks = file_image_info.callbacks;
+
if(fd >= 0) {
/* Retrieve information for determining uniqueness of file */
#ifdef H5_HAVE_WIN32_API
@@ -491,51 +518,70 @@ H5FD_core_open(const char *name, unsigned flags, hid_t fapl_id,
size_t size;
/* Retrieve file size */
- size = (size_t)sb.st_size;
+ if(file_image_info.buffer && file_image_info.size > 0)
+ size = file_image_info.size;
+ else
+ size = (size_t)sb.st_size;
/* Check if we should allocate the memory buffer and read in existing data */
if(size) {
- /* Allocate memory for the file's data */
- if(NULL == (file->mem = (unsigned char*)H5MM_malloc(size)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "unable to allocate memory block")
+ /* Allocate memory for the file's data, using the file image callback if available. */
+ if(file->fi_callbacks.image_malloc) {
+ if(NULL == (file->mem = (unsigned char*)file->fi_callbacks.image_malloc(size, H5FD_FILE_IMAGE_OP_FILE_OPEN, file->fi_callbacks.udata)))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, NULL, "image malloc callback failed")
+ } /* end if */
+ else {
+ if(NULL == (file->mem = (unsigned char*)H5MM_malloc(size)))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, NULL, "unable to allocate memory block")
+ } /* end else */
/* Set up data structures */
file->eof = size;
- /* Read in existing data, being careful of interrupted system calls,
- * partial results, and the end of the file.
- */
- while(size > 0) {
-
- h5_core_io_t bytes_in = 0; /* # of bytes to read */
- h5_core_io_ret_t bytes_read = -1; /* # of bytes actually read */
-
- /* Trying to read more bytes than the return type can handle is
- * undefined behavior in POSIX.
- */
- if(size > H5_CORE_MAX_IO_BYTES_g)
- bytes_in = H5_CORE_MAX_IO_BYTES_g;
- else
- bytes_in = (h5_core_io_t)size;
-
- do {
- bytes_read = HDread(file->fd, file->mem, bytes_in);
- } while(-1 == bytes_read && EINTR == errno);
-
- if(-1 == bytes_read) { /* error */
- int myerrno = errno;
- time_t mytime = HDtime(NULL);
- HDoff_t myoffset = HDlseek(file->fd, (HDoff_t)0, SEEK_CUR);
-
- HGOTO_ERROR(H5E_IO, H5E_READERROR, NULL, "file read failed: time = %s, filename = '%s', file descriptor = %d, errno = %d, error message = '%s', file->mem = %p, size = %lu, offset = %llu", HDctime(&mytime), file->name, file->fd, myerrno, HDstrerror(myerrno), file->mem, (unsigned long)size, (unsigned long long)myoffset);
+ /* If there is an initial file image, copy it, using the callback if possible */
+ if(file_image_info.buffer && file_image_info.size > 0) {
+ if(file->fi_callbacks.image_memcpy) {
+ if(file->mem != file->fi_callbacks.image_memcpy(file->mem, file_image_info.buffer, size, H5FD_FILE_IMAGE_OP_FILE_OPEN, file->fi_callbacks.udata))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTCOPY, NULL, "image_memcpy callback failed")
} /* end if */
-
- HDassert(bytes_read >= 0);
- HDassert((size_t)bytes_read <= size);
-
- size -= (size_t)bytes_read;
-
- } /* end while */
+ else
+ HDmemcpy(file->mem, file_image_info.buffer, size);
+ } /* end if */
+ /* Read in existing data from the file if there is no image */
+ else {
+ /* Read in existing data, being careful of interrupted system calls,
+ * partial results, and the end of the file.
+ */
+ while(size > 0) {
+ h5_core_io_t bytes_in = 0; /* # of bytes to read */
+ h5_core_io_ret_t bytes_read = -1; /* # of bytes actually read */
+
+ /* Trying to read more bytes than the return type can handle is
+ * undefined behavior in POSIX.
+ */
+ if(size > H5_CORE_MAX_IO_BYTES_g)
+ bytes_in = H5_CORE_MAX_IO_BYTES_g;
+ else
+ bytes_in = (h5_core_io_t)size;
+
+ do {
+ bytes_read = HDread(file->fd, file->mem, bytes_in);
+ } while(-1 == bytes_read && EINTR == errno);
+
+ if(-1 == bytes_read) { /* error */
+ int myerrno = errno;
+ time_t mytime = HDtime(NULL);
+ HDoff_t myoffset = HDlseek(file->fd, (HDoff_t)0, SEEK_CUR);
+
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, NULL, "file read failed: time = %s, filename = '%s', file descriptor = %d, errno = %d, error message = '%s', file->mem = %p, size = %lu, offset = %llu", HDctime(&mytime), file->name, file->fd, myerrno, HDstrerror(myerrno), file->mem, (unsigned long)size, (unsigned long long)myoffset);
+ } /* end if */
+
+ HDassert(bytes_read >= 0);
+ HDassert((size_t)bytes_read <= size);
+
+ size -= (size_t)bytes_read;
+ } /* end while */
+ } /* end else */
} /* end if */
} /* end if */
@@ -578,8 +624,15 @@ H5FD_core_close(H5FD_t *_file)
HDclose(file->fd);
if(file->name)
H5MM_xfree(file->name);
- if(file->mem)
- H5MM_xfree(file->mem);
+ if(file->mem) {
+ /* Use image callback if available */
+ if(file->fi_callbacks.image_free) {
+ if(file->fi_callbacks.image_free(file->mem, H5FD_FILE_IMAGE_OP_FILE_CLOSE, file->fi_callbacks.udata) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTFREE, FAIL, "image_free callback failed")
+ } /* end if */
+ else
+ H5MM_xfree(file->mem);
+ } /* end if */
HDmemset(file, 0, sizeof(H5FD_core_t));
H5MM_xfree(file);
@@ -700,9 +753,11 @@ H5FD_core_query(const H5FD_t * _file, unsigned long *flags /* out */)
*flags |= H5FD_FEAT_ACCUMULATE_METADATA; /* OK to accumulate metadata for faster writes */
*flags |= H5FD_FEAT_DATA_SIEVE; /* OK to perform data sieving for faster raw data reads & writes */
*flags |= H5FD_FEAT_AGGREGATE_SMALLDATA; /* OK to aggregate "small" raw data allocations */
+ *flags |= H5FD_FEAT_ALLOW_FILE_IMAGE; /* OK to use file image feature with this VFD */
+ *flags |= H5FD_FEAT_CAN_USE_FILE_IMAGE_CALLBACKS; /* OK to use file image callbacks with this VFD */
/* If the backing store is open, a POSIX file handle is available */
- if(file->fd >= 0 && file->backing_store)
+ if(file && file->fd >= 0 && file->backing_store)
*flags |= H5FD_FEAT_POSIX_COMPAT_HANDLE; /* VFD handle is POSIX I/O call compatible */
} /* end if */
@@ -976,9 +1031,16 @@ H5FD_core_write(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id, had
if((addr + size) % file->increment)
new_eof += file->increment;
- /* (Re)allocate memory for the file buffer */
- if(NULL == (x = (unsigned char *)H5MM_realloc(file->mem, new_eof)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate memory block of %llu bytes", (unsigned long long)new_eof)
+ /* (Re)allocate memory for the file buffer, using callbacks if available */
+ if(file->fi_callbacks.image_realloc) {
+ if(NULL == (x = (unsigned char *)file->fi_callbacks.image_realloc(file->mem, new_eof, H5FD_FILE_IMAGE_OP_FILE_RESIZE, file->fi_callbacks.udata)))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "unable to allocate memory block of %llu bytes with callback", (unsigned long long)new_eof)
+ } /* end if */
+ else {
+ if(NULL == (x = (unsigned char *)H5MM_realloc(file->mem, new_eof)))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "unable to allocate memory block of %llu bytes", (unsigned long long)new_eof)
+ } /* end else */
+
#ifdef H5_CLEAR_MEMORY
HDmemset(x + file->eof, 0, (size_t)(new_eof - file->eof));
#endif /* H5_CLEAR_MEMORY */
@@ -989,6 +1051,8 @@ HDmemset(x + file->eof, 0, (size_t)(new_eof - file->eof));
/* Write from BUF to memory */
HDmemcpy(file->mem + addr, buf, size);
+
+ /* Mark memory buffer as modified */
file->dirty = TRUE;
done:
@@ -1075,6 +1139,28 @@ done:
* Purpose: Makes sure that the true file size is the same (or larger)
* than the end-of-address.
*
+ * Addendum -- 12/2/11
+ * For file images opened with the core file driver, it is
+ * necessary that we avoid reallocating the core file driver's
+ * buffer uneccessarily.
+ *
+ * To this end, I have made the following functional changes
+ * to this function.
+ *
+ * If we are closing, and there is no backing store, this
+ * function becomes a no-op.
+ *
+ * If we are closing, and there is backing store, we set the
+ * eof to equal the eoa, and truncate the backing store to
+ * the new eof
+ *
+ * If we are not closing, we realloc the buffer to size equal
+ * to the smallest multiple of the allocation increment that
+ * equals or exceeds the eoa and set the eof accordingly.
+ * Note that we no longer truncate the backing store to the
+ * new eof if applicable.
+ * -- JRM
+ *
* Return: Success: Non-negative
* Failure: Negative
*
@@ -1085,7 +1171,7 @@ done:
*/
/* ARGSUSED */
static herr_t
-H5FD_core_truncate(H5FD_t *_file, hid_t UNUSED dxpl_id, hbool_t UNUSED closing)
+H5FD_core_truncate(H5FD_t *_file, hid_t UNUSED dxpl_id, hbool_t closing)
{
H5FD_core_t *file = (H5FD_core_t*)_file;
size_t new_eof; /* New size of memory buffer */
@@ -1095,78 +1181,83 @@ H5FD_core_truncate(H5FD_t *_file, hid_t UNUSED dxpl_id, hbool_t UNUSED closing)
HDassert(file);
- /* Determine new size of memory buffer */
- H5_ASSIGN_OVERFLOW(new_eof, file->increment * (file->eoa / file->increment), hsize_t, size_t);
- if(file->eoa % file->increment)
- new_eof += file->increment;
-
- /* Extend the file to make sure it's large enough */
- if(!H5F_addr_eq(file->eof, (haddr_t)new_eof)) {
- unsigned char *x; /* Pointer to new buffer for file data */
+ /* if we are closing and not using backing store, do nothing */
+ if(!closing || file->backing_store) {
+ if(closing) /* set eof to eoa */
+ new_eof = file->eoa;
+ else { /* set eof to smallest multiple of increment that exceeds eoa */
+ /* Determine new size of memory buffer */
+ H5_ASSIGN_OVERFLOW(new_eof, file->increment * (file->eoa / file->increment), hsize_t, size_t);
+ if(file->eoa % file->increment)
+ new_eof += file->increment;
+ } /* end else */
+
+ /* Extend the file to make sure it's large enough */
+ if(!H5F_addr_eq(file->eof, (haddr_t)new_eof)) {
+ unsigned char *x; /* Pointer to new buffer for file data */
+
+ /* (Re)allocate memory for the file buffer, using callback if available */
+ if(file->fi_callbacks.image_realloc) {
+ if(NULL == (x = (unsigned char *)file->fi_callbacks.image_realloc(file->mem, new_eof, H5FD_FILE_IMAGE_OP_FILE_RESIZE, file->fi_callbacks.udata)))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "unable to allocate memory block with callback")
+ } /* end if */
+ else {
+ if(NULL == (x = (unsigned char *)H5MM_realloc(file->mem, new_eof)))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "unable to allocate memory block")
+ } /* end else */
- /* (Re)allocate memory for the file buffer */
- if(NULL == (x = (unsigned char *)H5MM_realloc(file->mem, new_eof)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate memory block")
#ifdef H5_CLEAR_MEMORY
-if(file->eof < new_eof)
- HDmemset(x + file->eof, 0, (size_t)(new_eof - file->eof));
+ if(file->eof < new_eof)
+ HDmemset(x + file->eof, 0, (size_t)(new_eof - file->eof));
#endif /* H5_CLEAR_MEMORY */
- file->mem = x;
+ file->mem = x;
- /* Update backing store, if using it */
- if(file->fd >= 0 && file->backing_store) {
+ /* Update backing store, if using it and if closing */
+ if(closing && (file->fd >= 0) && file->backing_store) {
#ifdef H5_HAVE_WIN32_API
- LARGE_INTEGER li; /* 64-bit (union) integer for SetFilePointer() call */
- DWORD dwPtrLow; /* Low-order pointer bits from SetFilePointer()
- * Only used as an error code here.
- */
- DWORD dwError; /* DWORD error code from GetLastError() */
- BOOL bError; /* Boolean error flag */
-
- /* Windows uses this odd QuadPart union for 32/64-bit portability */
- li.QuadPart = (__int64)file->eoa;
-
- /* Extend the file to make sure it's large enough.
- *
- * Since INVALID_SET_FILE_POINTER can technically be a valid return value
- * from SetFilePointer(), we also need to check GetLastError().
- */
- dwPtrLow = SetFilePointer(file->hFile, li.LowPart, &li.HighPart, FILE_BEGIN);
- if(INVALID_SET_FILE_POINTER == dwPtrLow) {
- dwError = GetLastError();
- if(dwError != NO_ERROR )
- HGOTO_ERROR(H5E_FILE, H5E_FILEOPEN, FAIL, "unable to set file pointer")
- }
-
- bError = SetEndOfFile(file->hFile);
- if(0 == bError)
- HGOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to extend file properly")
+ LARGE_INTEGER li; /* 64-bit (union) integer for SetFilePointer() call */
+ DWORD dwPtrLow; /* Low-order pointer bits from SetFilePointer()
+ * Only used as an error code here.
+ */
+ DWORD dwError; /* DWORD error code from GetLastError() */
+ BOOL bError; /* Boolean error flag */
+
+ /* Windows uses this odd QuadPart union for 32/64-bit portability */
+ li.QuadPart = (__int64)file->eoa;
+
+ /* Extend the file to make sure it's large enough.
+ *
+ * Since INVALID_SET_FILE_POINTER can technically be a valid return value
+ * from SetFilePointer(), we also need to check GetLastError().
+ */
+ dwPtrLow = SetFilePointer(file->hFile, li.LowPart, &li.HighPart, FILE_BEGIN);
+ if(INVALID_SET_FILE_POINTER == dwPtrLow) {
+ dwError = GetLastError();
+ if(dwError != NO_ERROR )
+ HGOTO_ERROR(H5E_FILE, H5E_FILEOPEN, FAIL, "unable to set file pointer")
+ }
+
+ bError = SetEndOfFile(file->hFile);
+ if(0 == bError)
+ HGOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to extend file properly")
#else /* H5_HAVE_WIN32_API */
#ifdef H5_VMS
- /* Reset seek offset to the beginning of the file, so that the file isn't
- * re-extended later. This may happen on Open VMS. */
- if(-1 == HDlseek(file->fd, (HDoff_t)0, SEEK_SET))
- HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to seek to proper position")
-#endif
- if(-1 == HDftruncate(file->fd, (HDoff_t)file->eoa))
- HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to extend file properly")
+ /* Reset seek offset to the beginning of the file, so that the file isn't
+ * re-extended later. This may happen on Open VMS. */
+ if(-1 == HDlseek(file->fd, (HDoff_t)0, SEEK_SET))
+ HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to seek to proper position")
+#endif /* H5_VMS */
+ if(-1 == HDftruncate(file->fd, (HDoff_t)new_eof))
+ HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to extend file properly")
#endif /* H5_HAVE_WIN32_API */
+ } /* end if */
-#ifdef H5_VMS
- /* Reset seek offset to the beginning of the file, so that the file isn't
- * re-extended later. This may happen on Open VMS. */
- if(-1 == HDlseek(file->fd, 0, SEEK_SET))
- HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to seek to proper position")
-#endif
-
- if(-1 == HDftruncate(file->fd, (off_t)new_eof))
- HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to extend file properly")
+ /* Update the eof value */
+ file->eof = new_eof;
} /* end if */
-
- /* Update the eof value */
- file->eof = new_eof;
- } /* end if */
+ } /* end if(file->eof < file->eoa) */
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5FD_core_truncate() */
+
diff --git a/src/H5FDfamily.c b/src/H5FDfamily.c
index 17683ce..6f6d757 100644
--- a/src/H5FDfamily.c
+++ b/src/H5FDfamily.c
@@ -995,7 +995,7 @@ H5FD_family_query(const H5FD_t * _file, unsigned long *flags /* out */)
*flags |= H5FD_FEAT_AGGREGATE_SMALLDATA; /* OK to aggregate "small" raw data allocations */
/* Check for flags that are set by h5repart */
- if(file->repart_members)
+ if(file && file->repart_members)
*flags |= H5FD_FEAT_DIRTY_SBLK_LOAD; /* Mark the superblock dirty when it is loaded (so the family member sizes are rewritten) */
} /* end if */
diff --git a/src/H5FDlog.c b/src/H5FDlog.c
index cb5ce3c..0b5c677 100644
--- a/src/H5FDlog.c
+++ b/src/H5FDlog.c
@@ -918,7 +918,7 @@ H5FD_log_query(const H5FD_t *_file, unsigned long *flags /* out */)
*flags |= H5FD_FEAT_POSIX_COMPAT_HANDLE; /* VFD handle is POSIX I/O call compatible */
/* Check for flags that are set by h5repart */
- if(file->fam_to_sec2)
+ if(file && file->fam_to_sec2)
*flags |= H5FD_FEAT_IGNORE_DRVRINFO; /* Ignore the driver info when file is opened (which eliminates it) */
} /* end if */
diff --git a/src/H5FDprivate.h b/src/H5FDprivate.h
index 4f7d059..9c19562 100644
--- a/src/H5FDprivate.h
+++ b/src/H5FDprivate.h
@@ -52,6 +52,29 @@ typedef enum {
} H5FD_file_op_t;
+/* Define structure to hold initial file image and other relevant information */
+typedef struct {
+ void *buffer;
+ size_t size;
+ H5FD_file_image_callbacks_t callbacks;
+} H5FD_file_image_info_t;
+
+/* Define default file image info */
+#define H5FD_DEFAULT_FILE_IMAGE_INFO { \
+ /* file image buffer */ NULL, \
+ /* buffer size */ 0, \
+ { /* Callbacks */ \
+ /* image_malloc */ NULL, \
+ /* image_memcpy */ NULL, \
+ /* image_realloc */ NULL, \
+ /* image_free */ NULL, \
+ /* udata_copy */ NULL, \
+ /* udata_free */ NULL, \
+ /* udata */ NULL, \
+ } \
+}
+
+
/*****************************/
/* Library Private Variables */
/*****************************/
@@ -72,17 +95,14 @@ H5_DLL herr_t H5FD_sb_encode(H5FD_t *file, char *name/*out*/, uint8_t *buf);
H5_DLL herr_t H5FD_sb_decode(H5FD_t *file, const char *name, const uint8_t *buf);
H5_DLL void *H5FD_fapl_get(H5FD_t *file);
H5_DLL herr_t H5FD_fapl_open(struct H5P_genplist_t *plist, hid_t driver_id, const void *driver_info);
-H5_DLL herr_t H5FD_fapl_copy(hid_t driver_id, const void *fapl, void **copied_fapl);
H5_DLL herr_t H5FD_fapl_close(hid_t driver_id, void *fapl);
H5_DLL herr_t H5FD_dxpl_open(struct H5P_genplist_t *plist, hid_t driver_id, const void *driver_info);
-H5_DLL herr_t H5FD_dxpl_copy(hid_t driver_id, const void *dxpl, void **copied_dxpl);
H5_DLL herr_t H5FD_dxpl_close(hid_t driver_id, void *dxpl);
H5_DLL hid_t H5FD_register(const void *cls, size_t size, hbool_t app_ref);
H5_DLL H5FD_t *H5FD_open(const char *name, unsigned flags, hid_t fapl_id,
haddr_t maxaddr);
H5_DLL herr_t H5FD_close(H5FD_t *file);
H5_DLL int H5FD_cmp(const H5FD_t *f1, const H5FD_t *f2);
-H5_DLL int H5FD_query(const H5FD_t *f, unsigned long *flags/*out*/);
H5_DLL haddr_t H5FD_alloc(H5FD_t *file, hid_t dxpl_id, H5FD_mem_t type, struct H5F_t *f,
hsize_t size, haddr_t *align_addr, hsize_t *align_size);
H5_DLL herr_t H5FD_free(H5FD_t *file, hid_t dxpl_id, H5FD_mem_t type, struct H5F_t *f,
diff --git a/src/H5FDpublic.h b/src/H5FDpublic.h
index f495e2d..ab19c68 100644
--- a/src/H5FDpublic.h
+++ b/src/H5FDpublic.h
@@ -222,6 +222,19 @@ typedef enum H5F_mem_t H5FD_mem_t;
* instead of the default H5D_ALLOC_TIME_LATE
*/
#define H5FD_FEAT_ALLOCATE_EARLY 0x00000200
+ /*
+ * Defining the H5FD_FEAT_ALLOW_FILE_IMAGE for a VFL driver means that
+ * the driver is able to use a file image in the fapl as the initial
+ * contents of a file.
+ */
+#define H5FD_FEAT_ALLOW_FILE_IMAGE 0x00000400
+ /*
+ * Defining the H5FD_FEAT_CAN_USE_FILE_IMAGE_CALLBACKS for a VFL driver
+ * means that the driver is able to use callbacks to make a copy of the
+ * image to store in memory.
+ */
+#define H5FD_FEAT_CAN_USE_FILE_IMAGE_CALLBACKS 0x00000800
+
/* Forward declaration */
typedef struct H5FD_t H5FD_t;
@@ -291,6 +304,33 @@ struct H5FD_t {
hsize_t alignment; /* Allocation alignment */
};
+/* Define enum for the source of file image callbacks */
+typedef enum {
+ H5FD_FILE_IMAGE_OP_NO_OP,
+ H5FD_FILE_IMAGE_OP_PROPERTY_LIST_SET,
+ H5FD_FILE_IMAGE_OP_PROPERTY_LIST_COPY,
+ H5FD_FILE_IMAGE_OP_PROPERTY_LIST_GET,
+ H5FD_FILE_IMAGE_OP_PROPERTY_LIST_CLOSE,
+ H5FD_FILE_IMAGE_OP_FILE_OPEN,
+ H5FD_FILE_IMAGE_OP_FILE_RESIZE,
+ H5FD_FILE_IMAGE_OP_FILE_CLOSE,
+} H5FD_file_image_op_t;
+
+/* Define structure to hold file image callbacks */
+typedef struct {
+ void *(*image_malloc)(size_t size, H5FD_file_image_op_t file_image_op,
+ void *udata);
+ void *(*image_memcpy)(void *dest, const void *src, size_t size,
+ H5FD_file_image_op_t file_image_op, void *udata);
+ void *(*image_realloc)(void *ptr, size_t size,
+ H5FD_file_image_op_t file_image_op, void *udata);
+ herr_t (*image_free)(void *ptr, H5FD_file_image_op_t file_image_op,
+ void *udata);
+ void *(*udata_copy)(void *udata);
+ herr_t (*udata_free)(void *udata);
+ void *udata;
+} H5FD_file_image_callbacks_t;
+
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/src/H5FDsec2.c b/src/H5FDsec2.c
index 6d4a76a..4201e07 100644
--- a/src/H5FDsec2.c
+++ b/src/H5FDsec2.c
@@ -560,7 +560,7 @@ H5FD_sec2_query(const H5FD_t *_file, unsigned long *flags /* out */)
*flags |= H5FD_FEAT_POSIX_COMPAT_HANDLE; /* VFD handle is POSIX I/O call compatible */
/* Check for flags that are set by h5repart */
- if(file->fam_to_sec2)
+ if(file && file->fam_to_sec2)
*flags |= H5FD_FEAT_IGNORE_DRVRINFO; /* Ignore the driver info when file is opened (which eliminates it) */
} /* end if */
diff --git a/src/H5FDstdio.c b/src/H5FDstdio.c
index b67e01e..4733eba 100644
--- a/src/H5FDstdio.c
+++ b/src/H5FDstdio.c
@@ -13,37 +13,33 @@
* access to either file, you may request a copy from help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-/*
- * Programmer: Robb Matzke <matzke@llnl.gov>
- * Wednesday, October 22, 1997
- *
- * Purpose: This is the Posix stdio.h I/O subclass of H5Flow.
- * It also serves as an example of coding a simple file driver,
- * therefore, it should not use any non-public definitions.
+/* Programmer: Robb Matzke <matzke@llnl.gov>
+ * Wednesday, October 22, 1997
*
- * Notes: Ported to the new H5FD architecture on 10/18/99 - QAK
+ * Purpose: The C STDIO virtual file driver which only uses calls from stdio.h.
+ * This also serves as an example of coding a simple file driver,
+ * therefore, it should not use any non-public definitions.
*
+ * NOTE: This driver is not as well tested as the standard SEC2 driver
+ * and is not intended for production use!
*/
#include <assert.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
-/* Disable certain warnings in PC-Lint: */
-/*lint --emacro( {534, 830}, H5P_FILE_ACCESS) */
-/*lint --emacro( {534, 830}, H5F_ACC_RDWR, H5F_ACC_EXCL) */
-/*lint -esym( 534, H5Eclear2, H5Epush2) */
-
#include "hdf5.h"
-#ifdef H5_HAVE_STDIO_H
-#include <stdio.h>
-#endif
#ifdef H5_HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef H5_HAVE_WIN32_API
+/* The following two defines must be before any windows headers are included */
+#define WIN32_LEAN_AND_MEAN /* Exclude rarely-used stuff from Windows headers */
+#define NOGDI /* Exclude Graphic Display Interface macros */
+
#include <windows.h>
#include <io.h>
@@ -54,7 +50,6 @@
#endif
-
#ifdef MAX
#undef MAX
#endif /* MAX */
@@ -63,6 +58,9 @@
/* The driver identification number, initialized at runtime */
static hid_t H5FD_STDIO_g = 0;
+/* The maximum number of bytes which can be written in a single I/O operation */
+static size_t H5_STDIO_MAX_IO_BYTES_g = (size_t)-1;
+
/* File operations */
typedef enum {
H5FD_STDIO_OP_UNKNOWN=0,
@@ -71,55 +69,71 @@ typedef enum {
H5FD_STDIO_OP_SEEK=3
} H5FD_stdio_file_op;
-/*
- * The description of a file belonging to this driver. The `eoa' and `eof'
+/* The description of a file belonging to this driver. The 'eoa' and 'eof'
* determine the amount of hdf5 address space in use and the high-water mark
- * of the file (the current size of the underlying Unix file). The `pos'
+ * of the file (the current size of the underlying Unix file). The 'pos'
* value is used to eliminate file position updates when they would be a
* no-op. Unfortunately we've found systems that use separate file position
* indicators for reading and writing so the lseek can only be eliminated if
* the current operation is the same as the previous operation. When opening
- * a file the `eof' will be set to the current file size, `eoa' will be set
- * to zero, `pos' will be set to H5F_ADDR_UNDEF (as it is when an error
- * occurs), and `op' will be set to H5F_OP_UNKNOWN.
+ * a file the 'eof' will be set to the current file size, 'eoa' will be set
+ * to zero, 'pos' will be set to H5F_ADDR_UNDEF (as it is when an error
+ * occurs), and 'op' will be set to H5F_OP_UNKNOWN.
*/
typedef struct H5FD_stdio_t {
- H5FD_t pub; /*public stuff, must be first */
- FILE * fp; /*the file handle */
- haddr_t eoa; /*end of allocated region */
- haddr_t eof; /*end of file; current file size*/
- haddr_t pos; /*current file I/O position */
- H5FD_stdio_file_op op; /*last operation */
- unsigned write_access; /* Flag to indicate the file was opened with write access */
+ H5FD_t pub; /* public stuff, must be first */
+ FILE *fp; /* the file handle */
+ int fd; /* file descriptor (for truncate) */
+ haddr_t eoa; /* end of allocated region */
+ haddr_t eof; /* end of file; current file size */
+ haddr_t pos; /* current file I/O position */
+ unsigned write_access; /* Flag to indicate the file was opened with write access */
+ H5FD_stdio_file_op op; /* last operation */
#ifndef H5_HAVE_WIN32_API
- /*
- * On most systems the combination of device and i-node number uniquely
- * identify a file.
+ /* On most systems the combination of device and i-node number uniquely
+ * identify a file. Note that Cygwin, MinGW and other Windows POSIX
+ * environments have the stat function (which fakes inodes)
+ * and will use the 'device + inodes' scheme as opposed to the
+ * Windows code further below.
*/
- dev_t device; /*file device number */
- ino_t inode; /*file i-node number */
+ dev_t device; /* file device number */
+#ifdef H5_VMS
+ ino_t inode[3]; /* file i-node number */
#else
- /*
- * On H5_HAVE_WIN32_API the low-order word of a unique identifier associated with the
- * file and the volume serial number uniquely identify a file. This number
- * (which, both? -rpm) may change when the system is restarted or when the
- * file is opened. After a process opens a file, the identifier is
- * constant until the file is closed. An application can use this
- * identifier and the volume serial number to determine whether two
- * handles refer to the same file.
+ ino_t inode; /* file i-node number */
+#endif /* H5_VMS */
+#else
+ /* Files in windows are uniquely identified by the volume serial
+ * number and the file index (both low and high parts).
+ *
+ * There are caveats where these numbers can change, especially
+ * on FAT file systems. On NTFS, however, a file should keep
+ * those numbers the same until renamed or deleted (though you
+ * can use ReplaceFile() on NTFS to keep the numbers the same
+ * while renaming).
+ *
+ * See the MSDN "BY_HANDLE_FILE_INFORMATION Structure" entry for
+ * more information.
+ *
+ * http://msdn.microsoft.com/en-us/library/aa363788(v=VS.85).aspx
*/
- DWORD fileindexlo;
- DWORD fileindexhi;
-#endif
+ DWORD nFileIndexLow;
+ DWORD nFileIndexHigh;
+ DWORD dwVolumeSerialNumber;
+
+ HANDLE hFile; /* Native windows file handle */
+#endif /* H5_HAVE_WIN32_API */
} H5FD_stdio_t;
/* Use similar structure as in H5private.h by defining Windows stuff first. */
#ifdef H5_HAVE_WIN32_API
- # define file_fseek _fseeki64
- # define file_offset_t __int64
- # define file_ftruncate _chsize_s /* Supported in VS 2005 or newer */
- # define file_ftell _ftelli64
-#endif
+#ifndef H5_HAVE_MINGW
+ #define file_fseek _fseeki64
+ #define file_offset_t __int64
+ #define file_ftruncate _chsize_s /* Supported in VS 2005 or newer */
+ #define file_ftell _ftelli64
+#endif /* H5_HAVE_MINGW */
+#endif /* H5_HAVE_WIN32_API */
/* Use file_xxx to indicate these are local macros, avoiding confusing
* with the global HD_xxx macros.
@@ -128,20 +142,19 @@ typedef struct H5FD_stdio_t {
*/
#ifndef file_fseek
#ifdef H5_HAVE_FSEEKO64
- # define file_fseek fseeko64
- # define file_offset_t off64_t
- # define file_ftruncate ftruncate64
- # define file_ftell ftello64
+ #define file_fseek fseeko64
+ #define file_offset_t off64_t
+ #define file_ftruncate ftruncate64
+ #define file_ftell ftello64
#else
- # define file_fseek fseeko
- # define file_offset_t off_t
- # define file_ftruncate ftruncate
- # define file_ftell ftello
- #endif
-#endif
-
-/*
- * These macros check for overflow of various quantities. These macros
+ #define file_fseek fseeko
+ #define file_offset_t off_t
+ #define file_ftruncate ftruncate
+ #define file_ftell ftello
+ #endif /* H5_HAVE_FSEEKO64 */
+#endif /* file_fseek */
+
+/* These macros check for overflow of various quantities. These macros
* assume that file_offset_t is signed and haddr_t and size_t are unsigned.
*
* ADDR_OVERFLOW: Checks whether a file address of type `haddr_t'
@@ -182,38 +195,38 @@ static herr_t H5FD_stdio_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing);
static herr_t H5FD_stdio_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing);
static const H5FD_class_t H5FD_stdio_g = {
- "stdio", /*name */
- MAXADDR, /*maxaddr */
- H5F_CLOSE_WEAK, /* fc_degree */
- H5FD_stdio_term, /*terminate */
- NULL, /*sb_size */
- NULL, /*sb_encode */
- NULL, /*sb_decode */
- 0, /*fapl_size */
- NULL, /*fapl_get */
- NULL, /*fapl_copy */
- NULL, /*fapl_free */
- 0, /*dxpl_size */
- NULL, /*dxpl_copy */
- NULL, /*dxpl_free */
- H5FD_stdio_open, /*open */
- H5FD_stdio_close, /*close */
- H5FD_stdio_cmp, /*cmp */
- H5FD_stdio_query, /*query */
- NULL, /*get_type_map */
- H5FD_stdio_alloc, /*alloc */
- NULL, /*free */
- H5FD_stdio_get_eoa, /*get_eoa */
- H5FD_stdio_set_eoa, /*set_eoa */
- H5FD_stdio_get_eof, /*get_eof */
- H5FD_stdio_get_handle, /*get_handle */
- H5FD_stdio_read, /*read */
- H5FD_stdio_write, /*write */
- H5FD_stdio_flush, /*flush */
- H5FD_stdio_truncate, /*truncate */
- NULL, /*lock */
- NULL, /*unlock */
- H5FD_FLMAP_SINGLE /*fl_map */
+ "stdio", /* name */
+ MAXADDR, /* maxaddr */
+ H5F_CLOSE_WEAK, /* fc_degree */
+ H5FD_stdio_term, /* terminate */
+ NULL, /* sb_size */
+ NULL, /* sb_encode */
+ NULL, /* sb_decode */
+ 0, /* fapl_size */
+ NULL, /* fapl_get */
+ NULL, /* fapl_copy */
+ NULL, /* fapl_free */
+ 0, /* dxpl_size */
+ NULL, /* dxpl_copy */
+ NULL, /* dxpl_free */
+ H5FD_stdio_open, /* open */
+ H5FD_stdio_close, /* close */
+ H5FD_stdio_cmp, /* cmp */
+ H5FD_stdio_query, /* query */
+ NULL, /* get_type_map */
+ H5FD_stdio_alloc, /* alloc */
+ NULL, /* free */
+ H5FD_stdio_get_eoa, /* get_eoa */
+ H5FD_stdio_set_eoa, /* set_eoa */
+ H5FD_stdio_get_eof, /* get_eof */
+ H5FD_stdio_get_handle, /* get_handle */
+ H5FD_stdio_read, /* read */
+ H5FD_stdio_write, /* write */
+ H5FD_stdio_flush, /* flush */
+ H5FD_stdio_truncate, /* truncate */
+ NULL, /* lock */
+ NULL, /* unlock */
+ H5FD_FLMAP_SINGLE /* fl_map */
};
@@ -230,9 +243,6 @@ static const H5FD_class_t H5FD_stdio_g = {
* Programmer: Robb Matzke
* Thursday, July 29, 1999
*
- * Modifications:
- * Stolen from the sec2 driver - QAK, 10/18/99
- *
*-------------------------------------------------------------------------
*/
hid_t
@@ -243,8 +253,8 @@ H5FD_stdio_init(void)
if (H5I_VFL!=H5Iget_type(H5FD_STDIO_g))
H5FD_STDIO_g = H5FDregister(&H5FD_stdio_g);
- return(H5FD_STDIO_g);
-}
+ return H5FD_STDIO_g;
+} /* end H5FD_stdio_init() */
/*---------------------------------------------------------------------------
@@ -263,7 +273,7 @@ static herr_t
H5FD_stdio_term(void)
{
/* Reset VFL ID */
- H5FD_STDIO_g=0;
+ H5FD_STDIO_g = 0;
return 0;
} /* end H5FD_stdio_term() */
@@ -281,15 +291,12 @@ H5FD_stdio_term(void)
* Programmer: Robb Matzke
* Thursday, February 19, 1998
*
- * Modifications:
- * Stolen from the sec2 driver - QAK, 10/18/99
- *
*-------------------------------------------------------------------------
*/
herr_t
H5Pset_fapl_stdio(hid_t fapl_id)
{
- static const char *func="H5FDset_fapl_stdio"; /*for error reporting*/
+ static const char *func = "H5FDset_fapl_stdio"; /*for error reporting*/
/*NO TRACE*/
@@ -300,7 +307,7 @@ H5Pset_fapl_stdio(hid_t fapl_id)
H5Epush_ret(func, H5E_ERR_CLS, H5E_PLIST, H5E_BADTYPE, "not a file access property list", -1)
return H5Pset_driver(fapl_id, H5FD_STDIO, NULL);
-}
+} /* end H5Pset_fapl_stdio() */
/*-------------------------------------------------------------------------
@@ -308,50 +315,44 @@ H5Pset_fapl_stdio(hid_t fapl_id)
*
* Purpose: Create and/or opens a Standard C file as an HDF5 file.
*
- * Bugs: H5F_ACC_EXCL has a race condition. (? -QAK)
- *
* Errors:
- * IO CANTOPENFILE File doesn't exist and CREAT wasn't
- * specified.
- * IO CANTOPENFILE Fopen failed.
- * IO FILEEXISTS File exists but CREAT and EXCL were
- * specified.
+ * IO CANTOPENFILE File doesn't exist and CREAT wasn't
+ * specified.
+ * IO CANTOPENFILE fopen() failed.
+ * IO FILEEXISTS File exists but CREAT and EXCL were
+ * specified.
*
- * Return: Success: A pointer to a new file data structure. The
- * public fields will be initialized by the
- * caller, which is always H5FD_open().
+ * Return:
+ * Success: A pointer to a new file data structure. The
+ * public fields will be initialized by the
+ * caller, which is always H5FD_open().
*
- * Failure: NULL
+ * Failure: NULL
*
* Programmer: Robb Matzke
* Wednesday, October 22, 1997
*
- * Modifications:
- * Ported to VFL/H5FD layer - QAK, 10/18/99
- *
*-------------------------------------------------------------------------
*/
static H5FD_t *
H5FD_stdio_open( const char *name, unsigned flags, hid_t fapl_id,
haddr_t maxaddr)
{
- FILE *f = NULL;
- unsigned write_access=0; /* File opened with write access? */
- H5FD_stdio_t *file=NULL;
- static const char *func="H5FD_stdio_open"; /* Function Name for error reporting */
+ FILE *f = NULL;
+ unsigned write_access = 0; /* File opened with write access? */
+ H5FD_stdio_t *file = NULL;
+ static const char *func = "H5FD_stdio_open"; /* Function Name for error reporting */
#ifdef H5_HAVE_WIN32_API
- HFILE filehandle;
- struct _BY_HANDLE_FILE_INFORMATION fileinfo;
- int fd;
+ struct _BY_HANDLE_FILE_INFORMATION fileinfo;
#else /* H5_HAVE_WIN32_API */
- struct stat sb;
+ struct stat sb;
#endif /* H5_HAVE_WIN32_API */
/* Sanity check on file offsets */
- assert(sizeof(file_offset_t)>=sizeof(size_t));
+ assert(sizeof(file_offset_t) >= sizeof(size_t));
- /* Shut compiler up */
- fapl_id=fapl_id;
+ /* Quiet compiler */
+ fapl_id = fapl_id;
/* Clear the error stack */
H5Eclear2(H5E_DEFAULT);
@@ -359,15 +360,16 @@ H5FD_stdio_open( const char *name, unsigned flags, hid_t fapl_id,
/* Check arguments */
if (!name || !*name)
H5Epush_ret(func, H5E_ERR_CLS, H5E_ARGS, H5E_BADVALUE, "invalid file name", NULL)
- if (0==maxaddr || HADDR_UNDEF==maxaddr)
+ if (0 == maxaddr || HADDR_UNDEF == maxaddr)
H5Epush_ret(func, H5E_ERR_CLS, H5E_ARGS, H5E_BADRANGE, "bogus maxaddr", NULL)
if (ADDR_OVERFLOW(maxaddr))
H5Epush_ret(func, H5E_ERR_CLS, H5E_ARGS, H5E_OVERFLOW, "maxaddr too large", NULL)
+ /* Attempt to open/create the file */
if (access(name, F_OK) < 0) {
if ((flags & H5F_ACC_CREAT) && (flags & H5F_ACC_RDWR)) {
f = fopen(name, "wb+");
- write_access=1; /* Note the write access */
+ write_access = 1; /* Note the write access */
}
else
H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_CANTOPENFILE, "file doesn't exist and CREAT wasn't specified", NULL)
@@ -378,7 +380,7 @@ H5FD_stdio_open( const char *name, unsigned flags, hid_t fapl_id,
f = fopen(name, "wb+");
else
f = fopen(name, "rb+");
- write_access=1; /* Note the write access */
+ write_access = 1; /* Note the write access */
} else {
f = fopen(name, "rb");
}
@@ -393,30 +395,46 @@ H5FD_stdio_open( const char *name, unsigned flags, hid_t fapl_id,
file->fp = f;
file->op = H5FD_STDIO_OP_SEEK;
file->pos = HADDR_UNDEF;
- file->write_access=write_access; /* Note the write_access for later */
+ file->write_access = write_access; /* Note the write_access for later */
if(file_fseek(file->fp, (file_offset_t)0, SEEK_END) < 0) {
file->op = H5FD_STDIO_OP_UNKNOWN;
} else {
- file_offset_t x = file_ftell (file->fp);
- assert (x>=0);
+ file_offset_t x = file_ftell(file->fp);
+ assert (x >= 0);
file->eof = (haddr_t)x;
}
- /* The unique key */
+ /* Get the file descriptor (needed for truncate and some Windows information) */
+ file->fd = fileno(file->fp);
+ if(file->fd < 0)
+ H5Epush_ret(func, H5E_ERR_CLS, H5E_FILE, H5E_CANTOPENFILE, "unable to get file descriptor", NULL);
+
+
#ifdef H5_HAVE_WIN32_API
-/*#error "Needs correct fileindexhi & fileindexlo, code below is from sec2 driver"*/
- fd = _fileno(f);
- filehandle = _get_osfhandle(fd);
- (void)GetFileInformationByHandle((HANDLE)filehandle, &fileinfo);
- file->fileindexhi = fileinfo.nFileIndexHigh;
- file->fileindexlo = fileinfo.nFileIndexLow;
-#else
- fstat(fileno(file->fp), &sb);
+ file->hFile = (HANDLE)_get_osfhandle(file->fd);
+ if(INVALID_HANDLE_VALUE == file->hFile)
+ H5Epush_ret(func, H5E_ERR_CLS, H5E_FILE, H5E_CANTOPENFILE, "unable to get Windows file handle", NULL);
+
+ if(!GetFileInformationByHandle((HANDLE)file->hFile, &fileinfo))
+ H5Epush_ret(func, H5E_ERR_CLS, H5E_FILE, H5E_CANTOPENFILE, "unable to get Windows file desinformationcriptor", NULL);
+
+ file->nFileIndexHigh = fileinfo.nFileIndexHigh;
+ file->nFileIndexLow = fileinfo.nFileIndexLow;
+ file->dwVolumeSerialNumber = fileinfo.dwVolumeSerialNumber;
+#else /* H5_HAVE_WIN32_API */
+ fstat(file->fd, &sb);
file->device = sb.st_dev;
+#ifdef H5_VMS
+ file->inode[0] = sb.st_ino[0];
+ file->inode[1] = sb.st_ino[1];
+ file->inode[2] = sb.st_ino[2];
+#else /* H5_VMS */
file->inode = sb.st_ino;
-#endif
- return((H5FD_t*)file);
-} /* end H5FD_stdio_open() */
+#endif /* H5_VMS */
+#endif /* H5_HAVE_WIN32_API */
+
+ return (H5FD_t*)file;
+} /* end H5FD_stdio_open() */
/*-------------------------------------------------------------------------
@@ -432,16 +450,13 @@ H5FD_stdio_open( const char *name, unsigned flags, hid_t fapl_id,
* Programmer: Robb Matzke
* Wednesday, October 22, 1997
*
- * Modifications:
- * Ported to VFL/H5FD layer - QAK, 10/18/99
- *
*-------------------------------------------------------------------------
*/
static herr_t
H5FD_stdio_close(H5FD_t *_file)
{
H5FD_stdio_t *file = (H5FD_stdio_t*)_file;
- static const char *func="H5FD_stdio_close"; /* Function Name for error reporting */
+ static const char *func = "H5FD_stdio_close"; /* Function Name for error reporting */
/* Clear the error stack */
H5Eclear2(H5E_DEFAULT);
@@ -451,8 +466,8 @@ H5FD_stdio_close(H5FD_t *_file)
free(file);
- return(0);
-}
+ return 0;
+} /* end H5FD_stdio_close() */
/*-------------------------------------------------------------------------
@@ -461,17 +476,14 @@ H5FD_stdio_close(H5FD_t *_file)
* Purpose: Compares two files belonging to this driver using an
* arbitrary (but consistent) ordering.
*
- * Return: Success: A value like strcmp()
+ * Return:
+ * Success: A value like strcmp()
*
- * Failure: never fails (arguments were checked by the
- * caller).
+ * Failure: never fails (arguments were checked by the caller).
*
* Programmer: Robb Matzke
* Thursday, July 29, 1999
*
- * Modifications:
- * Stolen from the sec2 driver - QAK, 10/18/99
- *
*-------------------------------------------------------------------------
*/
static int
@@ -484,30 +496,37 @@ H5FD_stdio_cmp(const H5FD_t *_f1, const H5FD_t *_f2)
H5Eclear2(H5E_DEFAULT);
#ifdef H5_HAVE_WIN32_API
- if (f1->fileindexhi < f2->fileindexhi) return -1;
- if (f1->fileindexhi > f2->fileindexhi) return 1;
+ if(f1->dwVolumeSerialNumber < f2->dwVolumeSerialNumber) return -1;
+ if(f1->dwVolumeSerialNumber > f2->dwVolumeSerialNumber) return 1;
- if (f1->fileindexlo < f2->fileindexlo) return -1;
- if (f1->fileindexlo > f2->fileindexlo) return 1;
+ if(f1->nFileIndexHigh < f2->nFileIndexHigh) return -1;
+ if(f1->nFileIndexHigh > f2->nFileIndexHigh) return 1;
-#else
+ if(f1->nFileIndexLow < f2->nFileIndexLow) return -1;
+ if(f1->nFileIndexLow > f2->nFileIndexLow) return 1;
+#else /* H5_HAVE_WIN32_API */
#ifdef H5_DEV_T_IS_SCALAR
- if (f1->device < f2->device) return -1;
- if (f1->device > f2->device) return 1;
+ if(f1->device < f2->device) return -1;
+ if(f1->device > f2->device) return 1;
#else /* H5_DEV_T_IS_SCALAR */
/* If dev_t isn't a scalar value on this system, just use memcmp to
* determine if the values are the same or not. The actual return value
* shouldn't really matter...
*/
- if(memcmp(&(f1->device),&(f2->device),sizeof(dev_t))<0) return -1;
- if(memcmp(&(f1->device),&(f2->device),sizeof(dev_t))>0) return 1;
+ if(memcmp(&(f1->device),&(f2->device),sizeof(dev_t)) < 0) return -1;
+ if(memcmp(&(f1->device),&(f2->device),sizeof(dev_t)) > 0) return 1;
#endif /* H5_DEV_T_IS_SCALAR */
+#ifdef H5_VMS
+ if(memcmp(&(f1->inode), &(f2->inode), 3 * sizeof(ino_t)) < 0) return -1;
+ if(memcmp(&(f1->inode), &(f2->inode), 3 * sizeof(ino_t)) > 0) return 1;
+#else /* H5_VMS */
+ if(f1->inode < f2->inode) return -1;
+ if(f1->inode > f2->inode) return 1;
+#endif /* H5_VMS */
+#endif /* H5_HAVE_WIN32_API */
- if (f1->inode < f2->inode) return -1;
- if (f1->inode > f2->inode) return 1;
-#endif
return 0;
-}
+} /* H5FD_stdio_cmp() */
/*-------------------------------------------------------------------------
@@ -523,14 +542,12 @@ H5FD_stdio_cmp(const H5FD_t *_f1, const H5FD_t *_f2)
* Programmer: Quincey Koziol
* Friday, August 25, 2000
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
static herr_t
H5FD_stdio_query(const H5FD_t *_f, unsigned long *flags /* out */)
{
- /* Shut compiler up */
+ /* Quiet the compiler */
_f=_f;
/* Set the VFL feature flags that this driver supports */
@@ -542,37 +559,35 @@ H5FD_stdio_query(const H5FD_t *_f, unsigned long *flags /* out */)
*flags|=H5FD_FEAT_AGGREGATE_SMALLDATA; /* OK to aggregate "small" raw data allocations */
}
- return(0);
-}
+ return 0;
+} /* end H5FD_stdio_query() */
/*-------------------------------------------------------------------------
* Function: H5FD_stdio_alloc
*
- * Purpose: Allocates file memory. If fseeko isn't available, makes
+ * Purpose: Allocates file memory. If fseeko isn't available, makes
* sure the file size isn't bigger than 2GB because the
* parameter OFFSET of fseek is of the type LONG INT, limiting
* the file size to 2GB.
*
- * Return: Success: Address of new memory
+ * Return:
+ * Success: Address of new memory
*
- * Failure: HADDR_UNDEF
+ * Failure: HADDR_UNDEF
*
* Programmer: Raymond Lu
* 30 March 2007
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
static haddr_t
H5FD_stdio_alloc(H5FD_t *_file, H5FD_mem_t /*UNUSED*/ type, hid_t /*UNUSED*/ dxpl_id, hsize_t size)
{
- H5FD_stdio_t *file = (H5FD_stdio_t*)_file;
- haddr_t addr;
- haddr_t ret_value; /* Return value */
+ H5FD_stdio_t *file = (H5FD_stdio_t*)_file;
+ haddr_t addr;
- /* Shut compiler up */
+ /* Quiet compiler */
type = type;
dxpl_id = dxpl_id;
@@ -591,19 +606,16 @@ H5FD_stdio_alloc(H5FD_t *_file, H5FD_mem_t /*UNUSED*/ type, hid_t /*UNUSED*/ dxp
file->eoa = addr + size;
- /* Set return value */
- ret_value = addr;
-
- return(ret_value);
-} /* H5FD_stdio_alloc() */
+ return addr;
+} /* end H5FD_stdio_alloc() */
/*-------------------------------------------------------------------------
* Function: H5FD_stdio_get_eoa
*
* Purpose: Gets the end-of-address marker for the file. The EOA marker
- * is the first address past the last byte allocated in the
- * format address space.
+ * is the first address past the last byte allocated in the
+ * format address space.
*
* Return: Success: The end-of-address marker.
*
@@ -612,28 +624,21 @@ H5FD_stdio_alloc(H5FD_t *_file, H5FD_mem_t /*UNUSED*/ type, hid_t /*UNUSED*/ dxp
* Programmer: Robb Matzke
* Monday, August 2, 1999
*
- * Modifications:
- * Stolen from the sec2 driver - QAK, 10/18/99
- *
- * Raymond Lu
- * 21 Dec. 2006
- * Added the parameter TYPE. It's only used for MULTI driver.
- *
*-------------------------------------------------------------------------
*/
static haddr_t
-H5FD_stdio_get_eoa(const H5FD_t *_file, H5FD_mem_t /*unused*/ type)
+H5FD_stdio_get_eoa(const H5FD_t *_file, H5FD_mem_t /*UNUSED*/ type)
{
- const H5FD_stdio_t *file = (const H5FD_stdio_t *)_file;
+ const H5FD_stdio_t *file = (const H5FD_stdio_t *)_file;
/* Clear the error stack */
H5Eclear2(H5E_DEFAULT);
- /* Shut compiler up */
+ /* Quiet compiler */
type = type;
- return(file->eoa);
-}
+ return file->eoa;
+} /* end H5FD_stdio_get_eoa() */
/*-------------------------------------------------------------------------
@@ -645,33 +650,27 @@ H5FD_stdio_get_eoa(const H5FD_t *_file, H5FD_mem_t /*unused*/ type)
*
* Return: Success: 0
*
- * Failure: -1
+ * Failure: Does not fail
*
* Programmer: Robb Matzke
* Thursday, July 29, 1999
*
- * Modifications:
- * Stolen from the sec2 driver - QAK, 10/18/99
- *
- * Raymond Lu
- * 21 Dec. 2006
- * Added the parameter TYPE. It's only used for MULTI driver.
*-------------------------------------------------------------------------
*/
static herr_t
-H5FD_stdio_set_eoa(H5FD_t *_file, H5FD_mem_t /*unused*/ type, haddr_t addr)
+H5FD_stdio_set_eoa(H5FD_t *_file, H5FD_mem_t /*UNUSED*/ type, haddr_t addr)
{
H5FD_stdio_t *file = (H5FD_stdio_t*)_file;
/* Clear the error stack */
H5Eclear2(H5E_DEFAULT);
- /* Shut compiler up */
+ /* Quiet the compiler */
type = type;
file->eoa = addr;
- return(0);
+ return 0;
}
@@ -691,9 +690,6 @@ H5FD_stdio_set_eoa(H5FD_t *_file, H5FD_mem_t /*unused*/ type, haddr_t addr)
* Programmer: Robb Matzke
* Thursday, July 29, 1999
*
- * Modifications:
- * Stolen from the sec2 driver - QAK, 10/18/99
- *
*-------------------------------------------------------------------------
*/
static haddr_t
@@ -704,8 +700,8 @@ H5FD_stdio_get_eof(const H5FD_t *_file)
/* Clear the error stack */
H5Eclear2(H5E_DEFAULT);
- return(MAX(file->eof, file->eoa));
-}
+ return MAX(file->eof, file->eoa);
+} /* end H5FD_stdio_get_eof() */
/*-------------------------------------------------------------------------
@@ -718,64 +714,56 @@ H5FD_stdio_get_eof(const H5FD_t *_file)
* Programmer: Raymond Lu
* Sept. 16, 2002
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
static herr_t
H5FD_stdio_get_handle(H5FD_t *_file, hid_t fapl, void** file_handle)
{
H5FD_stdio_t *file = (H5FD_stdio_t *)_file;
- static const char *func="H5FD_stdio_get_handle"; /* Function Name for error reporting */
+ static const char *func = "H5FD_stdio_get_handle"; /* Function Name for error reporting */
- /* Shut compiler up */
- fapl=fapl;
+ /* Quiet the compiler */
+ fapl = fapl;
/* Clear the error stack */
H5Eclear2(H5E_DEFAULT);
*file_handle = &(file->fp);
- if(*file_handle==NULL)
+ if(*file_handle == NULL)
H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_WRITEERROR, "get handle failed", -1)
- return(0);
-}
+
+ return 0;
+} /* end H5FD_stdio_get_handle() */
/*-------------------------------------------------------------------------
- * Function: H5F_stdio_read
+ * Function: H5FD_stdio_read
*
* Purpose: Reads SIZE bytes beginning at address ADDR in file LF and
* places them in buffer BUF. Reading past the logical or
* physical end of file returns zeros instead of failing.
*
* Errors:
- * IO READERROR Fread failed.
- * IO SEEKERROR Fseek failed.
+ * IO READERROR fread failed.
+ * IO SEEKERROR fseek failed.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Robb Matzke
* Wednesday, October 22, 1997
*
- * Modifications:
- * June 2, 1998 Albert Cheng
- * Added xfer_mode argument
- *
- * Ported to VFL/H5FD layer - QAK, 10/18/99
- *
*-------------------------------------------------------------------------
*/
static herr_t
H5FD_stdio_read(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t size,
void *buf/*out*/)
{
- size_t n;
H5FD_stdio_t *file = (H5FD_stdio_t*)_file;
- static const char *func="H5FD_stdio_read"; /* Function Name for error reporting */
+ static const char *func = "H5FD_stdio_read"; /* Function Name for error reporting */
- /* Shut compiler up */
- type=type;
- dxpl_id=dxpl_id;
+ /* Quiet the compiler */
+ type = type;
+ dxpl_id = dxpl_id;
/* Clear the error stack */
H5Eclear2(H5E_DEFAULT);
@@ -790,16 +778,14 @@ H5FD_stdio_read(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, siz
/* Check easy cases */
if (0 == size)
- return(0);
+ return 0;
if ((haddr_t)addr >= file->eof) {
memset(buf, 0, size);
- return(0);
+ return 0;
}
- /*
- * Seek to the correct file position.
- */
- if (!(file->op == H5FD_STDIO_OP_READ || file->op==H5FD_STDIO_OP_SEEK) ||
+ /* Seek to the correct file position. */
+ if (!(file->op == H5FD_STDIO_OP_READ || file->op == H5FD_STDIO_OP_SEEK) ||
file->pos != addr) {
if (file_fseek(file->fp, (file_offset_t)addr, SEEK_SET) < 0) {
file->op = H5FD_STDIO_OP_UNKNOWN;
@@ -809,59 +795,70 @@ H5FD_stdio_read(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, siz
file->pos = addr;
}
- /*
- * Read zeros past the logical end of file (physical is handled below)
- */
+ /* Read zeros past the logical end of file (physical is handled below) */
if (addr + size > file->eof) {
size_t nbytes = (size_t) (addr + size - file->eof);
memset((unsigned char *)buf + size - nbytes, 0, nbytes);
size -= nbytes;
}
- /*
- * Read the data. Since we're reading single-byte values, a partial read
+ /* Read the data. Since we're reading single-byte values, a partial read
* will advance the file position by N. If N is zero or an error
* occurs then the file position is undefined.
*/
- n = fread(buf, (size_t)1, size, file->fp);
- if(n == 0 && ferror(file->fp)) {
- file->op = H5FD_STDIO_OP_UNKNOWN;
- file->pos = HADDR_UNDEF;
- H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_READERROR, "fread failed", -1)
- } else if (n < size) {
- memset((unsigned char *)buf + n, 0, (size - n));
- }
+ while(size > 0) {
- /*
- * Update the file position data.
- */
+ size_t bytes_in = 0; /* # of bytes to read */
+ size_t bytes_read = 0; /* # of bytes actually read */
+ size_t item_size = 1; /* size of items in bytes */
+
+ if(size > H5_STDIO_MAX_IO_BYTES_g)
+ bytes_in = H5_STDIO_MAX_IO_BYTES_g;
+ else
+ bytes_in = size;
+
+ bytes_read = fread(buf, item_size, bytes_in, file->fp);
+
+ if(0 == bytes_read && ferror(file->fp)) { /* error */
+ file->op = H5FD_STDIO_OP_UNKNOWN;
+ file->pos = HADDR_UNDEF;
+ H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_READERROR, "fread failed", -1)
+ } /* end if */
+
+ if(0 == bytes_read && feof(file->fp)) {
+ /* end of file but not end of format address space */
+ memset((unsigned char *)buf, 0, size);
+ break;
+ } /* end if */
+
+ size -= bytes_read;
+ addr += (haddr_t)bytes_read;
+ buf = (char *)buf + bytes_read;
+ } /* end while */
+
+ /* Update the file position data. */
file->op = H5FD_STDIO_OP_READ;
- file->pos = addr+n; /*checked for overflow above*/
- return(0);
+ file->pos = addr;
+
+ return 0;
}
/*-------------------------------------------------------------------------
- * Function: H5F_stdio_write
+ * Function: H5FD_stdio_write
*
* Purpose: Writes SIZE bytes from the beginning of BUF into file LF at
* file address ADDR.
*
* Errors:
- * IO SEEKERROR Fseek failed.
- * IO WRITEERROR Fwrite failed.
+ * IO SEEKERROR fseek failed.
+ * IO WRITEERROR fwrite failed.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Robb Matzke
* Wednesday, October 22, 1997
*
- * Modifications:
- * June 2, 1998 Albert Cheng
- * Added xfer_mode argument
- *
- * Ported to VFL/H5FD layer - QAK, 10/18/99
- *
*-------------------------------------------------------------------------
*/
static herr_t
@@ -869,26 +866,24 @@ H5FD_stdio_write(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr,
size_t size, const void *buf)
{
H5FD_stdio_t *file = (H5FD_stdio_t*)_file;
- static const char *func="H5FD_stdio_write"; /* Function Name for error reporting */
+ static const char *func = "H5FD_stdio_write"; /* Function Name for error reporting */
- /* Shut compiler up */
- dxpl_id=dxpl_id;
- type=type;
+ /* Quiet the compiler */
+ dxpl_id = dxpl_id;
+ type = type;
/* Clear the error stack */
H5Eclear2(H5E_DEFAULT);
/* Check for overflow conditions */
- if (HADDR_UNDEF==addr)
+ if (HADDR_UNDEF == addr)
H5Epush_ret (func, H5E_ERR_CLS, H5E_IO, H5E_OVERFLOW, "file address overflowed", -1)
if (REGION_OVERFLOW(addr, size))
H5Epush_ret (func, H5E_ERR_CLS, H5E_IO, H5E_OVERFLOW, "file address overflowed", -1)
- if (addr+size>file->eoa)
+ if (addr+size > file->eoa)
H5Epush_ret (func, H5E_ERR_CLS, H5E_IO, H5E_OVERFLOW, "file address overflowed", -1)
- /*
- * Seek to the correct file position.
- */
+ /* Seek to the correct file position. */
if ((file->op != H5FD_STDIO_OP_WRITE && file->op != H5FD_STDIO_OP_SEEK) ||
file->pos != addr) {
if (file_fseek(file->fp, (file_offset_t)addr, SEEK_SET) < 0) {
@@ -899,33 +894,51 @@ H5FD_stdio_write(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr,
file->pos = addr;
}
- /*
- * Write the buffer. On successful return, the file position will be
- * advanced by the number of bytes read. Otherwise nobody knows where it
- * is.
+ /* Write the buffer. On successful return, the file position will be
+ * advanced by the number of bytes read. On failure, the file position is
+ * undefined.
*/
- if(size != fwrite(buf, (size_t)1, size, file->fp)) {
- file->op = H5FD_STDIO_OP_UNKNOWN;
- file->pos = HADDR_UNDEF;
- H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_WRITEERROR, "fwrite failed", -1)
+ while(size > 0) {
+
+ size_t bytes_in = 0; /* # of bytes to write */
+ size_t bytes_wrote = 0; /* # of bytes written */
+ size_t item_size = 1; /* size of items in bytes */
+
+ if(size > H5_STDIO_MAX_IO_BYTES_g)
+ bytes_in = H5_STDIO_MAX_IO_BYTES_g;
+ else
+ bytes_in = size;
+
+ bytes_wrote = fwrite(buf, item_size, bytes_in, file->fp);
+
+ if(bytes_wrote != bytes_in || (0 == bytes_wrote && ferror(file->fp))) { /* error */
+ file->op = H5FD_STDIO_OP_UNKNOWN;
+ file->pos = HADDR_UNDEF;
+ H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_WRITEERROR, "fwrite failed", -1)
+ } /* end if */
+
+ assert(bytes_wrote > 0);
+ assert((size_t)bytes_wrote <= size);
+
+ size -= bytes_wrote;
+ addr += (haddr_t)bytes_wrote;
+ buf = (const char *)buf + bytes_wrote;
}
- /*
- * Update seek optimizing data.
- */
+ /* Update seek optimizing data. */
file->op = H5FD_STDIO_OP_WRITE;
- file->pos = addr + size;
+ file->pos = addr;
/* Update EOF if necessary */
- if (file->pos>file->eof)
+ if (file->pos > file->eof)
file->eof = file->pos;
- return(0);
+ return 0;
}
/*-------------------------------------------------------------------------
- * Function: H5F_stdio_flush
+ * Function: H5FD_stdio_flush
*
* Purpose: Makes sure that all data is on disk.
*
@@ -946,7 +959,7 @@ H5FD_stdio_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing)
H5FD_stdio_t *file = (H5FD_stdio_t*)_file;
static const char *func = "H5FD_stdio_flush"; /* Function Name for error reporting */
- /* Shut compiler up */
+ /* Quiet the compiler */
dxpl_id = dxpl_id;
/* Clear the error stack */
@@ -954,7 +967,6 @@ H5FD_stdio_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing)
/* Only try to flush the file if we have write access */
if(file->write_access) {
- /* Flush */
if(!closing) {
if(fflush(file->fp) < 0)
H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_WRITEERROR, "fflush failed", -1)
@@ -965,12 +977,12 @@ H5FD_stdio_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing)
} /* end if */
} /* end if */
- return(0);
+ return 0;
} /* end H5FD_stdio_flush() */
/*-------------------------------------------------------------------------
- * Function: H5F_stdio_truncate
+ * Function: H5FD_stdio_truncate
*
* Purpose: Makes sure that the true file size is the same (or larger)
* than the end-of-address.
@@ -984,9 +996,6 @@ H5FD_stdio_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing)
* Programmer: Quincey Koziol
* Thursday, January 31, 2008
*
- * Modifications:
- * Vailin Choi; June 2010
- * Fix for window failures manifested from tests in mf.c.
*-------------------------------------------------------------------------
*/
static herr_t
@@ -995,7 +1004,7 @@ H5FD_stdio_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing)
H5FD_stdio_t *file = (H5FD_stdio_t*)_file;
static const char *func = "H5FD_stdio_truncate"; /* Function Name for error reporting */
- /* Shut compiler up */
+ /* Quiet the compiler */
dxpl_id = dxpl_id;
closing = closing;
@@ -1006,30 +1015,42 @@ H5FD_stdio_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing)
if(file->write_access) {
/* Makes sure that the true file size is the same as the end-of-address. */
if(file->eoa != file->eof) {
- int fd = fileno(file->fp); /* File descriptor for HDF5 file */
#ifdef H5_HAVE_WIN32_API
- HFILE filehandle; /* Windows file handle */
- LARGE_INTEGER li; /* 64-bit integer for SetFilePointer() call */
+ LARGE_INTEGER li; /* 64-bit (union) integer for SetFilePointer() call */
+ DWORD dwPtrLow; /* Low-order pointer bits from SetFilePointer()
+ * Only used as an error code here.
+ */
+ DWORD dwError; /* DWORD error code from GetLastError() */
+ BOOL bError; /* Boolean error flag */
- /* Reset seek offset to beginning of file, so that file isn't re-extended later */
+ /* Reset seek offset to beginning of file, so that file isn't re-extended later */
rewind(file->fp);
- /* Map the posix file handle to a Windows file handle */
- filehandle = _get_osfhandle(fd);
-
- /* Translate 64-bit integers into form Windows wants */
- /* [This algorithm is from the Windows documentation for SetFilePointer()] */
- li.QuadPart = (LONGLONG)file->eoa;
- (void)SetFilePointer((HANDLE)filehandle, li.LowPart, &li.HighPart, FILE_BEGIN);
- if(SetEndOfFile((HANDLE)filehandle) == 0)
+ /* Windows uses this odd QuadPart union for 32/64-bit portability */
+ li.QuadPart = (__int64)file->eoa;
+
+ /* Extend the file to make sure it's large enough.
+ *
+ * Since INVALID_SET_FILE_POINTER can technically be a valid return value
+ * from SetFilePointer(), we also need to check GetLastError().
+ */
+ dwPtrLow = SetFilePointer(file->hFile, li.LowPart, &li.HighPart, FILE_BEGIN);
+ if(INVALID_SET_FILE_POINTER == dwPtrLow) {
+ dwError = GetLastError();
+ if(dwError != NO_ERROR )
+ H5Epush_ret(func, H5E_ERR_CLS, H5E_FILE, H5E_FILEOPEN, "unable to set file pointer", -1)
+ }
+
+ bError = SetEndOfFile(file->hFile);
+ if(0 == bError)
H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_SEEKERROR, "unable to truncate/extend file properly", -1)
#else /* H5_HAVE_WIN32_API */
/* Reset seek offset to beginning of file, so that file isn't re-extended later */
rewind(file->fp);
/* Truncate file to proper length */
- if(-1 == file_ftruncate(fd, (file_offset_t)file->eoa))
+ if(-1 == file_ftruncate(file->fd, (file_offset_t)file->eoa))
H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_SEEKERROR, "unable to truncate/extend file properly", -1)
#endif /* H5_HAVE_WIN32_API */
@@ -1044,10 +1065,10 @@ H5FD_stdio_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing)
else {
/* Double-check for problems */
if(file->eoa > file->eof)
- H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_TRUNCATED, "eoa>eof!", -1)
- } /* end else */
+ H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_TRUNCATED, "eoa > eof!", -1)
+ } /* end else */
- return(0);
+ return 0;
} /* end H5FD_stdio_truncate() */
diff --git a/src/H5FSprivate.h b/src/H5FSprivate.h
index ca7104c..f6a0034 100644
--- a/src/H5FSprivate.h
+++ b/src/H5FSprivate.h
@@ -155,7 +155,7 @@ typedef struct H5FS_stat_t {
} H5FS_stat_t;
/* Typedef for iteration operations */
-typedef herr_t (*H5FS_operator_t)(const H5FS_section_info_t *sect,
+typedef herr_t (*H5FS_operator_t)(H5FS_section_info_t *sect,
void *operator_data/*in,out*/);
diff --git a/src/H5FSsection.c b/src/H5FSsection.c
index 914fa58..0f126c2 100644
--- a/src/H5FSsection.c
+++ b/src/H5FSsection.c
@@ -2244,7 +2244,7 @@ H5FS_sect_assert(const H5FS_t *fspace)
hsize_t separate_obj; /* The number of separate objects managed */
FUNC_ENTER_NOAPI_NOINIT_NOERR
-#ifndef QAK
+#ifdef QAK
HDfprintf(stderr, "%s: fspace->tot_sect_count = %Hu\n", "H5FS_sect_assert", fspace->tot_sect_count);
#endif /* QAK */
diff --git a/src/H5Fmpi.c b/src/H5Fmpi.c
index 0f612be..966528a 100644
--- a/src/H5Fmpi.c
+++ b/src/H5Fmpi.c
@@ -202,7 +202,7 @@ H5Fset_mpi_atomicity(hid_t file_id, hbool_t flag)
herr_t ret_value = SUCCEED;
FUNC_ENTER_API(FAIL)
- H5TRACE2("e", "iMi", file_id, flag);
+ H5TRACE2("e", "ib", file_id, flag);
/* Check args */
if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
@@ -242,7 +242,7 @@ H5Fget_mpi_atomicity(hid_t file_id, hbool_t *flag)
herr_t ret_value = SUCCEED;
FUNC_ENTER_API(FAIL)
- H5TRACE2("e", "iMi", file_id, flag);
+ H5TRACE2("e", "i*b", file_id, flag);
/* Check args */
if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h
index 939bc3f..7e45cfa 100644
--- a/src/H5Fprivate.h
+++ b/src/H5Fprivate.h
@@ -417,6 +417,7 @@ typedef struct H5F_blk_aggr_t H5F_blk_aggr_t;
#define H5F_ACS_LATEST_FORMAT_NAME "latest_format" /* 'Use latest format version' flag */
#define H5F_ACS_WANT_POSIX_FD_NAME "want_posix_fd" /* Internal: query the file descriptor from the core VFD, instead of the memory address */
#define H5F_ACS_EFC_SIZE_NAME "efc_size" /* Size of external file cache */
+#define H5F_ACS_FILE_IMAGE_INFO_NAME "file_image_info" /* struct containing initial file image and callback info */
/* ======================== File Mount properties ====================*/
#define H5F_MNT_SYM_LOCAL_NAME "local" /* Whether absolute symlinks local to file. */
@@ -530,8 +531,8 @@ H5_DLL H5F_t *H5F_get_parent(const H5F_t *f);
H5_DLL unsigned H5F_get_nmounts(const H5F_t *f);
H5_DLL hid_t H5F_get_access_plist(H5F_t *f, hbool_t app_ref);
H5_DLL hid_t H5F_get_id(H5F_t *file, hbool_t app_ref);
-H5_DLL size_t H5F_get_obj_count(const H5F_t *f, unsigned types, hbool_t app_ref);
-H5_DLL size_t H5F_get_obj_ids(const H5F_t *f, unsigned types, size_t max_objs, hid_t *obj_id_list, hbool_t app_ref);
+H5_DLL herr_t H5F_get_obj_count(const H5F_t *f, unsigned types, hbool_t app_ref, size_t *obj_id_count_ptr);
+H5_DLL herr_t H5F_get_obj_ids(const H5F_t *f, unsigned types, size_t max_objs, hid_t *oid_list, hbool_t app_ref, size_t *obj_id_count_ptr);
H5_DLL struct H5VL_class_t *H5F_get_vol_cls(const H5F_t *f);
/* Functions than retrieve values set/cached from the superblock/FCPL */
diff --git a/src/H5Fpublic.h b/src/H5Fpublic.h
index d88538b..f32b3e0 100644
--- a/src/H5Fpublic.h
+++ b/src/H5Fpublic.h
@@ -192,6 +192,7 @@ H5_DLL herr_t H5Fmount(hid_t loc, const char *name, hid_t child, hid_t plist);
H5_DLL herr_t H5Funmount(hid_t loc, const char *name);
H5_DLL hssize_t H5Fget_freespace(hid_t file_id);
H5_DLL herr_t H5Fget_filesize(hid_t file_id, hsize_t *size);
+H5_DLL ssize_t H5Fget_file_image(hid_t file_id, void * buf_ptr, size_t buf_len);
H5_DLL herr_t H5Fget_mdc_config(hid_t file_id,
H5AC_cache_config_t * config_ptr);
H5_DLL herr_t H5Fset_mdc_config(hid_t file_id,
diff --git a/src/H5Gname.c b/src/H5Gname.c
index 62875dc..576d866 100644
--- a/src/H5Gname.c
+++ b/src/H5Gname.c
@@ -782,7 +782,7 @@ done:
/*-------------------------------------------------------------------------
* Function: H5G_name_replace_cb
*
- * Purpose: H5I_search callback function to replace group entry names
+ * Purpose: H5I_iterate callback function to replace group entry names
*
* Return: Success: 0, Failure: -1
*
@@ -1166,15 +1166,18 @@ H5G_name_replace(const H5O_link_t *lnk, H5G_names_op_t op, H5F_t *src_file,
/* Search through group IDs */
if(search_group)
- H5I_search(H5I_GROUP, H5G_name_replace_cb, &names, FALSE);
+ if(H5I_iterate(H5I_GROUP, H5G_name_replace_cb, &names, FALSE) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "can't iterate over groups")
/* Search through dataset IDs */
if(search_dataset)
- H5I_search(H5I_DATASET, H5G_name_replace_cb, &names, FALSE);
+ if(H5I_iterate(H5I_DATASET, H5G_name_replace_cb, &names, FALSE) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "can't iterate over datasets")
/* Search through datatype IDs */
if(search_datatype)
- H5I_search(H5I_DATATYPE, H5G_name_replace_cb, &names, FALSE);
+ if(H5I_iterate(H5I_DATATYPE, H5G_name_replace_cb, &names, FALSE) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "can't iterate over datatypes")
} /* end if */
} /* end if */
diff --git a/src/H5Goh.c b/src/H5Goh.c
index 194e3ec..c6115db 100644
--- a/src/H5Goh.c
+++ b/src/H5Goh.c
@@ -81,7 +81,8 @@ const H5O_obj_class_t H5O_OBJ_GROUP[1] = {{
H5O_group_open, /* open an object of this class */
H5O_group_create, /* create an object of this class */
H5O_group_get_oloc, /* get an object header location for an object */
- H5O_group_bh_info /* get the index & heap info for an object */
+ H5O_group_bh_info, /* get the index & heap info for an object */
+ NULL /* flush an opened object of this class */
}};
/* Declare the external free list to manage the H5O_ginfo_t struct */
diff --git a/src/H5HF.c b/src/H5HF.c
index 9c911fd..a9750c9 100644
--- a/src/H5HF.c
+++ b/src/H5HF.c
@@ -156,9 +156,6 @@ H5HF_create(H5F_t *f, hid_t dxpl_id, const H5HF_create_t *cparam)
H5HF_t *ret_value; /* Return value */
FUNC_ENTER_NOAPI(NULL)
-#ifdef QAK
-HDfprintf(stderr, "%s: Called\n", FUNC);
-#endif /* QAK */
/*
* Check arguments.
@@ -234,14 +231,8 @@ H5HF_open(H5F_t *f, hid_t dxpl_id, haddr_t fh_addr)
HDassert(H5F_addr_defined(fh_addr));
/* Load the heap header into memory */
-#ifdef QAK
-HDfprintf(stderr, "%s: fh_addr = %a\n", FUNC, fh_addr);
-#endif /* QAK */
if(NULL == (hdr = H5HF_hdr_protect(f, dxpl_id, fh_addr, H5AC_READ)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to protect fractal heap header")
-#ifdef QAK
-HDfprintf(stderr, "%s: hdr->rc = %u, hdr->fspace = %p\n", FUNC, hdr->rc, hdr->fspace);
-#endif /* QAK */
/* Check for pending heap deletion */
if(hdr->pending_delete)
@@ -361,9 +352,6 @@ H5HF_insert(H5HF_t *fh, hid_t dxpl_id, size_t size, const void *obj,
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
-#ifdef QAK
-HDfprintf(stderr, "%s: size = %Zu\n", FUNC, size);
-#endif /* QAK */
/* Sanity check */
HDassert(fh);
@@ -406,9 +394,6 @@ HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "'write once' managed blocks not su
} /* end else */
done:
-#ifdef QAK
-HDfprintf(stderr, "%s: Leaving, ret_value = %d\n", FUNC, ret_value);
-#endif /* QAK */
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HF_insert() */
@@ -580,9 +565,6 @@ H5HF_write(H5HF_t *fh, hid_t dxpl_id, void *_id, hbool_t UNUSED *id_changed,
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
-#ifdef QAK
-HDfprintf(stderr, "%s: Called\n", FUNC);
-#endif /* QAK */
/*
* Check arguments.
@@ -720,9 +702,6 @@ H5HF_remove(H5HF_t *fh, hid_t dxpl_id, const void *_id)
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
-#ifdef QAK
-HDfprintf(stderr, "%s: Called\n", FUNC);
-#endif /* QAK */
/*
* Check arguments.
@@ -814,17 +793,9 @@ H5HF_close(H5HF_t *fh, hid_t dxpl_id)
* a reference loop and the objects couldn't be removed from
* the metadata cache - QAK)
*/
-#ifdef QAK
-HDfprintf(stderr, "%s; fh->hdr->man_iter_off = %Hu\n", FUNC, fh->hdr->man_iter_off);
-HDfprintf(stderr, "%s; fh->hdr->man_size = %Hu\n", FUNC, fh->hdr->man_size);
-HDfprintf(stderr, "%s; fh->hdr->rc = %Zu\n", FUNC, fh->hdr->rc);
-#endif /* QAK */
if(H5HF_man_iter_ready(&fh->hdr->next_block))
if(H5HF_man_iter_reset(&fh->hdr->next_block) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't reset block iterator")
-#ifdef QAK
-HDfprintf(stderr, "%s; After iterator reset fh->hdr->rc = %Zu\n", FUNC, fh->hdr->rc);
-#endif /* QAK */
/* Shut down the huge object information */
/* (Can't put this in header "destroy" routine, because it has
@@ -900,9 +871,6 @@ H5HF_delete(H5F_t *f, hid_t dxpl_id, haddr_t fh_addr)
HDassert(H5F_addr_defined(fh_addr));
/* Lock the heap header into memory */
-#ifdef QAK
-HDfprintf(stderr, "%s: fh_addr = %a\n", FUNC, fh_addr);
-#endif /* QAK */
if(NULL == (hdr = H5HF_hdr_protect(f, dxpl_id, fh_addr, H5AC_WRITE)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap header")
diff --git a/src/H5HFbtree2.c b/src/H5HFbtree2.c
index 023344c..34b74d7 100644
--- a/src/H5HFbtree2.c
+++ b/src/H5HFbtree2.c
@@ -352,7 +352,7 @@ HDfprintf(stderr, "%s: nrecord = {%a, %Hu, %Hu}\n", "H5HF_huge_bt2_indir_found",
herr_t
H5HF_huge_bt2_indir_remove(const void *nrecord, void *_udata)
{
- H5HF_huge_remove_ud1_t *udata = (H5HF_huge_remove_ud1_t *)_udata; /* User callback data */
+ H5HF_huge_remove_ud_t *udata = (H5HF_huge_remove_ud_t *)_udata; /* User callback data */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT
@@ -570,7 +570,7 @@ HDfprintf(stderr, "%s: nrecord = {%a, %Hu, %x, %Hu, %Hu}\n", "H5HF_huge_bt2_filt
herr_t
H5HF_huge_bt2_filt_indir_remove(const void *nrecord, void *_udata)
{
- H5HF_huge_remove_ud1_t *udata = (H5HF_huge_remove_ud1_t *)_udata; /* User callback data */
+ H5HF_huge_remove_ud_t *udata = (H5HF_huge_remove_ud_t *)_udata; /* User callback data */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT
@@ -759,7 +759,7 @@ H5HF_huge_bt2_filt_indir_debug(FILE *stream, const H5F_t UNUSED *f, hid_t UNUSED
herr_t
H5HF_huge_bt2_dir_remove(const void *nrecord, void *_udata)
{
- H5HF_huge_remove_ud1_t *udata = (H5HF_huge_remove_ud1_t *)_udata; /* User callback data */
+ H5HF_huge_remove_ud_t *udata = (H5HF_huge_remove_ud_t *)_udata; /* User callback data */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT
@@ -984,7 +984,7 @@ HDfprintf(stderr, "%s: nrecord = {%a, %Hu, %x, %Hu}\n", "H5HF_huge_bt2_filt_dir_
herr_t
H5HF_huge_bt2_filt_dir_remove(const void *nrecord, void *_udata)
{
- H5HF_huge_remove_ud1_t *udata = (H5HF_huge_remove_ud1_t *)_udata; /* User callback data */
+ H5HF_huge_remove_ud_t *udata = (H5HF_huge_remove_ud_t *)_udata; /* User callback data */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT
diff --git a/src/H5HFdbg.c b/src/H5HFdbg.c
index 4289c02..caaedc7 100644
--- a/src/H5HFdbg.c
+++ b/src/H5HFdbg.c
@@ -172,39 +172,31 @@ H5HF_dtable_debug(H5HF_dtable_t *dtable, FILE *stream, int indent, int fwidth)
/*-------------------------------------------------------------------------
- * Function: H5HF_hdr_debug
+ * Function: H5HF_hdr_print
*
- * Purpose: Prints debugging info about a fractal heap header.
+ * Purpose: Prints info about a fractal heap header.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 24 2006
+ * koziol@hdfgroup.org
+ * Feb 23 2012
*
*-------------------------------------------------------------------------
*/
-herr_t
-H5HF_hdr_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, int fwidth)
+void
+H5HF_hdr_print(const H5HF_hdr_t *hdr, hid_t dxpl_id, hbool_t dump_internal, FILE *stream, int indent, int fwidth)
{
- H5HF_hdr_t *hdr = NULL; /* Fractal heap header info */
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(FAIL)
+ FUNC_ENTER_NOAPI_NOINIT
/*
* Check arguments.
*/
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
+ HDassert(hdr);
HDassert(stream);
HDassert(indent >= 0);
HDassert(fwidth >= 0);
- /* Load the fractal heap header */
- if(NULL == (hdr = H5HF_hdr_protect(f, dxpl_id, addr, H5AC_READ)))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap header")
-
/* Print opening message */
HDfprintf(stream, "%*sFractal Heap Header...\n", indent, "");
@@ -277,10 +269,66 @@ H5HF_hdr_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent,
"Filter mask for root direct block:",
hdr->pline_root_direct_filter_mask);
} /* end if */
- H5O_debug_id(H5O_PLINE_ID, f, dxpl_id, &(hdr->pline), stream,
+ H5O_debug_id(H5O_PLINE_ID, hdr->f, dxpl_id, &(hdr->pline), stream,
indent + 3, MAX(0, fwidth - 3));
} /* end if */
+ /* Print internal (runtime) information, if requested */
+ if(dump_internal) {
+ HDfprintf(stream, "%*sFractal Heap Header Internal Information:\n", indent, "");
+
+ /* Dump root iblock, if there is one */
+ HDfprintf(stream, "%*s%-*s %x\n", indent + 3, "", MAX(0, fwidth - 3),
+ "Root indirect block flags:",
+ hdr->root_iblock_flags);
+ HDfprintf(stream, "%*s%-*s %p\n", indent + 3, "", MAX(0, fwidth - 3),
+ "Root indirect block pointer:",
+ hdr->root_iblock);
+ if(hdr->root_iblock)
+ H5HF_iblock_print(hdr->root_iblock, dump_internal, stream, indent + 3, fwidth);
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI_VOID
+} /* end H5HF_hdr_print() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_hdr_debug
+ *
+ * Purpose: Prints debugging info about a fractal heap header.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Feb 24 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5HF_hdr_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, int fwidth)
+{
+ H5HF_hdr_t *hdr = NULL; /* Fractal heap header info */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(f);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(stream);
+ HDassert(indent >= 0);
+ HDassert(fwidth >= 0);
+
+ /* Load the fractal heap header */
+ if(NULL == (hdr = H5HF_hdr_protect(f, dxpl_id, addr, H5AC_READ)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap header")
+
+ /* Print the information about the heap's header */
+ H5HF_hdr_print(hdr, dxpl_id, FALSE, stream, indent, fwidth);
+
done:
if(hdr && H5AC_unprotect(f, dxpl_id, H5AC_FHEAP_HDR, addr, hdr, H5AC__NO_FLAGS_SET) < 0)
HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release fractal heap header")
@@ -303,9 +351,9 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5HF_dblock_debug_cb(const H5FS_section_info_t *_sect, void *_udata)
+H5HF_dblock_debug_cb(H5FS_section_info_t *_sect, void *_udata)
{
- const H5HF_free_section_t *sect = (const H5HF_free_section_t *)_sect; /* Section to dump info */
+ H5HF_free_section_t *sect = (H5HF_free_section_t *)_sect; /* Section to dump info */
H5HF_debug_iter_ud1_t *udata = (H5HF_debug_iter_ud1_t *)_udata; /* User data for callbacks */
haddr_t sect_start, sect_end; /* Section's beginning and ending offsets */
haddr_t dblock_start, dblock_end; /* Direct block's beginning and ending offsets */
@@ -501,51 +549,39 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5HF_iblock_debug
+ * Function: H5HF_iblock_print
*
* Purpose: Prints debugging info about a fractal heap indirect block.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Mar 7 2006
+ * koziol@hdfgroup.org
+ * Feb 23 2012
*
*-------------------------------------------------------------------------
*/
-herr_t
-H5HF_iblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream,
- int indent, int fwidth, haddr_t hdr_addr, unsigned nrows)
+void
+H5HF_iblock_print(const H5HF_indirect_t *iblock,
+ hbool_t dump_internal, FILE *stream, int indent, int fwidth)
{
- H5HF_hdr_t *hdr = NULL; /* Fractal heap header info */
- H5HF_indirect_t *iblock = NULL; /* Fractal heap direct block info */
- hbool_t did_protect; /* Whether we protected the indirect block or not */
+ const H5HF_hdr_t *hdr; /* Pointer to heap's header */
char temp_str[64]; /* Temporary string, for formatting */
size_t u, v; /* Local index variable */
- herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(FAIL)
+ FUNC_ENTER_NOAPI_NOINIT
/*
* Check arguments.
*/
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
+ HDassert(iblock);
+ HDassert(iblock->hdr);
HDassert(stream);
HDassert(indent >= 0);
HDassert(fwidth >= 0);
- HDassert(H5F_addr_defined(hdr_addr));
- HDassert(nrows > 0);
- /* Load the fractal heap header */
- if(NULL == (hdr = H5HF_hdr_protect(f, dxpl_id, hdr_addr, H5AC_READ)))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap header")
-
- /*
- * Load the heap indirect block
- */
- if(NULL == (iblock = H5HF_man_iblock_protect(hdr, dxpl_id, addr, nrows, NULL, 0, FALSE, H5AC_READ, &did_protect)))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load fractal heap indirect block")
+ /* Set up convenience variables */
+ hdr = iblock->hdr;
/* Print opening message */
HDfprintf(stream, "%*sFractal Heap Indirect Block...\n", indent, "");
@@ -623,6 +659,75 @@ H5HF_iblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream,
HDfprintf(stream, "%*s%-*s\n", indent + 3, "", MAX(0, fwidth - 3),
"<none>");
+ /* Print internal (runtime) information, if requested */
+ if(dump_internal) {
+ HDfprintf(stream, "%*sFractal Indirect Block Internal Information:\n", indent, "");
+
+ /* Print general information */
+ HDfprintf(stream, "%*s%-*s %Zu\n", indent + 3, "", MAX(0, fwidth - 3),
+ "Reference count:",
+ iblock->rc);
+
+ /* Print parent's information */
+ HDfprintf(stream, "%*s%-*s %p\n", indent + 3, "", MAX(0, fwidth - 3),
+ "Parent indirect block address:",
+ iblock->parent);
+ if(iblock->parent)
+ H5HF_iblock_print(iblock->parent, TRUE, stream, indent + 6, fwidth);
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI_VOID
+} /* end H5HF_iblock_print() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_iblock_debug
+ *
+ * Purpose: Prints debugging info about a fractal heap indirect block.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Mar 7 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5HF_iblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream,
+ int indent, int fwidth, haddr_t hdr_addr, unsigned nrows)
+{
+ H5HF_hdr_t *hdr = NULL; /* Fractal heap header info */
+ H5HF_indirect_t *iblock = NULL; /* Fractal heap direct block info */
+ hbool_t did_protect; /* Whether we protected the indirect block or not */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(f);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(stream);
+ HDassert(indent >= 0);
+ HDassert(fwidth >= 0);
+ HDassert(H5F_addr_defined(hdr_addr));
+ HDassert(nrows > 0);
+
+ /* Load the fractal heap header */
+ if(NULL == (hdr = H5HF_hdr_protect(f, dxpl_id, hdr_addr, H5AC_READ)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap header")
+
+ /*
+ * Load the heap indirect block
+ */
+ if(NULL == (iblock = H5HF_man_iblock_protect(hdr, dxpl_id, addr, nrows, NULL, 0, FALSE, H5AC_READ, &did_protect)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load fractal heap indirect block")
+
+ /* Print the information about the heap's indirect block */
+ H5HF_iblock_print(iblock, FALSE, stream, indent, fwidth);
+
done:
if(iblock && H5HF_man_iblock_unprotect(iblock, dxpl_id, H5AC__NO_FLAGS_SET, did_protect) < 0)
HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release fractal heap direct block")
@@ -647,9 +752,9 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5HF_sects_debug_cb(const H5FS_section_info_t *_sect, void *_udata)
+H5HF_sects_debug_cb(H5FS_section_info_t *_sect, void *_udata)
{
- const H5HF_free_section_t *sect = (const H5HF_free_section_t *)_sect; /* Section to dump info */
+ H5HF_free_section_t *sect = (H5HF_free_section_t *)_sect; /* Section to dump info */
H5HF_debug_iter_ud2_t *udata = (H5HF_debug_iter_ud2_t *)_udata; /* User data for callbacks */
herr_t ret_value = SUCCEED; /* Return value */
diff --git a/src/H5HFhuge.c b/src/H5HFhuge.c
index 3bbd137..6f0b48e 100644
--- a/src/H5HFhuge.c
+++ b/src/H5HFhuge.c
@@ -899,7 +899,7 @@ done:
herr_t
H5HF_huge_remove(H5HF_hdr_t *hdr, hid_t dxpl_id, const uint8_t *id)
{
- H5HF_huge_remove_ud1_t udata; /* User callback data for v2 B-tree remove call */
+ H5HF_huge_remove_ud_t udata; /* User callback data for v2 B-tree remove call */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT
@@ -1072,7 +1072,7 @@ done:
herr_t
H5HF_huge_delete(H5HF_hdr_t *hdr, hid_t dxpl_id)
{
- H5HF_huge_remove_ud1_t udata; /* User callback data for v2 B-tree remove call */
+ H5HF_huge_remove_ud_t udata; /* User callback data for v2 B-tree remove call */
H5B2_remove_t op; /* Callback for v2 B-tree removal */
herr_t ret_value = SUCCEED; /* Return value */
diff --git a/src/H5HFiblock.c b/src/H5HFiblock.c
index 6c19b4f..342e228 100644
--- a/src/H5HFiblock.c
+++ b/src/H5HFiblock.c
@@ -140,8 +140,17 @@ H5HF_iblock_pin(H5HF_indirect_t *iblock)
else {
/* Check for pinning the root indirect block */
if(iblock->block_off == 0) {
- HDassert(iblock->hdr->root_iblock == NULL);
- iblock->hdr->root_iblock = iblock;
+ /* Sanity check - shouldn't be recursively pinning root indirect block */
+ HDassert(0 == (iblock->hdr->root_iblock_flags & H5HF_ROOT_IBLOCK_PINNED));
+
+ /* Check if we should set the root iblock pointer */
+ if(0 == iblock->hdr->root_iblock_flags) {
+ HDassert(NULL == iblock->hdr->root_iblock);
+ iblock->hdr->root_iblock = iblock;
+ } /* end if */
+
+ /* Indicate that the root indirect block is pinned */
+ iblock->hdr->root_iblock_flags |= H5HF_ROOT_IBLOCK_PINNED;
} /* end if */
} /* end if */
@@ -192,12 +201,21 @@ H5HF_iblock_unpin(H5HF_indirect_t *iblock)
par_iblock->child_iblocks[indir_idx] = NULL;
} /* end if */
else {
- /* Check for unpinning the root indirect block */
+ /* Check for root indirect block */
if(iblock->block_off == 0) {
- HDassert(iblock->hdr->root_iblock);
- iblock->hdr->root_iblock = NULL;
+ /* Sanity check - shouldn't be recursively unpinning root indirect block */
+ HDassert(iblock->hdr->root_iblock_flags & H5HF_ROOT_IBLOCK_PINNED);
+
+ /* Check if we should reset the root iblock pointer */
+ if(H5HF_ROOT_IBLOCK_PINNED == iblock->hdr->root_iblock_flags) {
+ HDassert(NULL != iblock->hdr->root_iblock);
+ iblock->hdr->root_iblock = NULL;
+ } /* end if */
+
+ /* Indicate that the root indirect block is unpinned */
+ iblock->hdr->root_iblock_flags &= ~(H5HF_ROOT_IBLOCK_PINNED);
} /* end if */
- } /* end if */
+ } /* end else */
/* Mark block as evictable again */
if(H5AC_unpin_entry(iblock) < 0)
@@ -273,18 +291,23 @@ H5HF_iblock_decr(H5HF_indirect_t *iblock)
/* Mark block as evictable again when no child blocks depend on it */
if(iblock->rc == 0) {
- if(H5HF_iblock_unpin(iblock) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPIN, FAIL, "unable to unpin fractal heap indirect block")
+ H5HF_hdr_t *hdr; /* Fractal heap header */
+ haddr_t iblock_addr; /* Address of fractal heap */
+ hbool_t expunge_iblock = FALSE; /* Whether to expunge indirect block from heap */
+
+ /* Set up convenience variables */
+ hdr = iblock->hdr;
+ iblock_addr = iblock->addr;
if(iblock->nchildren == 0) {
/* Check for deleting root indirect block (and no root direct block) */
- if(iblock->block_off == 0 && iblock->hdr->man_dtable.curr_root_rows > 0) {
+ if(iblock->block_off == 0 && hdr->man_dtable.curr_root_rows > 0) {
/* Reset root pointer information */
- iblock->hdr->man_dtable.curr_root_rows = 0;
- iblock->hdr->man_dtable.table_addr = HADDR_UNDEF;
+ hdr->man_dtable.curr_root_rows = 0;
+ hdr->man_dtable.table_addr = HADDR_UNDEF;
/* Reset header information back to "empty heap" state */
- if(H5HF_hdr_empty(iblock->hdr) < 0)
+ if(H5HF_hdr_empty(hdr) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't make heap empty")
} /* end if */
@@ -297,8 +320,18 @@ H5HF_iblock_decr(H5HF_indirect_t *iblock)
iblock->par_entry = 0;
} /* end if */
+ /* Mark indirect block for removal from the metadata cache */
+ expunge_iblock = TRUE;
+ } /* end if */
+
+ /* Unpin the indirect block */
+ if(H5HF_iblock_unpin(iblock) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPIN, FAIL, "unable to unpin fractal heap indirect block")
+
+ /* Check for expunging the indirect block from the metadata cache */
+ if(expunge_iblock) {
/* Evict the indirect block from the metadata cache */
- if(H5AC_expunge_entry(iblock->hdr->f, H5AC_dxpl_id, H5AC_FHEAP_IBLOCK, iblock->addr, H5AC__FREE_FILE_SPACE_FLAG) < 0)
+ if(H5AC_expunge_entry(hdr->f, H5AC_dxpl_id, H5AC_FHEAP_IBLOCK, iblock_addr, H5AC__FREE_FILE_SPACE_FLAG) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTREMOVE, FAIL, "unable to remove indirect block from cache")
} /* end if */
} /* end if */
@@ -420,6 +453,10 @@ H5HF_man_iblock_root_create(H5HF_hdr_t *hdr, hid_t dxpl_id, size_t min_dblock_si
hdr->pline_root_direct_filter_mask = 0;
} /* end if */
+ /* Scan free space sections to set any 'parent' pointers to new indirect block */
+ if(H5HF_space_create_root(hdr, dxpl_id, iblock) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTSET, FAIL, "can't set free space section info to new root indirect block")
+
/* Unlock first (previously the root) direct block */
if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, hdr->man_dtable.table_addr, dblock, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap direct block")
@@ -859,6 +896,11 @@ H5HF_man_iblock_root_revert(H5HF_indirect_t *root_iblock, hid_t dxpl_id)
if(H5HF_hdr_adjust_heap(hdr, (hsize_t)hdr->man_dtable.cparam.start_block_size, (hssize_t)hdr->man_dtable.row_tot_dblock_free[0]) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTEXTEND, FAIL, "can't increase space to cover root direct block")
+ /* Scan free space sections to reset any 'parent' pointers */
+ if(H5HF_space_revert_root(hdr, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRESET, FAIL, "can't reset free space section info")
+
+
done:
if(dblock && H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, dblock_addr, dblock, H5AC__NO_FLAGS_SET) < 0)
HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap direct block")
@@ -1126,11 +1168,20 @@ H5HF_man_iblock_protect(H5HF_hdr_t *hdr, hid_t dxpl_id, haddr_t iblock_addr,
else {
/* Check for root indirect block */
if(H5F_addr_eq(iblock_addr, hdr->man_dtable.table_addr)) {
- /* Check for pointer to pinned indirect block in root */
- if(hdr->root_iblock)
+ /* Check for valid pointer to pinned indirect block in root */
+ if(H5HF_ROOT_IBLOCK_PINNED == hdr->root_iblock_flags) {
+ /* Sanity check */
+ HDassert(NULL != hdr->root_iblock);
+
+ /* Return the pointer to the pinned root indirect block */
iblock = hdr->root_iblock;
- else
+ } /* end if */
+ else {
+ /* Sanity check */
+ HDassert(NULL == hdr->root_iblock);
+
should_protect = TRUE;
+ } /* end else */
} /* end if */
else
should_protect = TRUE;
@@ -1158,6 +1209,21 @@ H5HF_man_iblock_protect(H5HF_hdr_t *hdr, hid_t dxpl_id, haddr_t iblock_addr,
/* Set the indirect block's address */
iblock->addr = iblock_addr;
+ /* Check for root indirect block */
+ if(iblock->block_off == 0) {
+ /* Sanity check - shouldn't be recursively protecting root indirect block */
+ HDassert(0 == (hdr->root_iblock_flags & H5HF_ROOT_IBLOCK_PROTECTED));
+
+ /* Check if we should set the root iblock pointer */
+ if(0 == hdr->root_iblock_flags) {
+ HDassert(NULL == hdr->root_iblock);
+ hdr->root_iblock = iblock;
+ } /* end if */
+
+ /* Indicate that the root indirect block is protected */
+ hdr->root_iblock_flags |= H5HF_ROOT_IBLOCK_PROTECTED;
+ } /* end if */
+
/* Indicate that the indirect block was protected */
*did_protect = TRUE;
} /* end if */
@@ -1202,6 +1268,21 @@ H5HF_man_iblock_unprotect(H5HF_indirect_t *iblock, hid_t dxpl_id,
/* Check if we previously protected this indirect block */
/* (as opposed to using an existing pointer to a pinned child indirect block) */
if(did_protect) {
+ /* Check for root indirect block */
+ if(iblock->block_off == 0) {
+ /* Sanity check - shouldn't be recursively unprotecting root indirect block */
+ HDassert(iblock->hdr->root_iblock_flags & H5HF_ROOT_IBLOCK_PROTECTED);
+
+ /* Check if we should reset the root iblock pointer */
+ if(H5HF_ROOT_IBLOCK_PROTECTED == iblock->hdr->root_iblock_flags) {
+ HDassert(NULL != iblock->hdr->root_iblock);
+ iblock->hdr->root_iblock = NULL;
+ } /* end if */
+
+ /* Indicate that the root indirect block is unprotected */
+ iblock->hdr->root_iblock_flags &= ~(H5HF_ROOT_IBLOCK_PROTECTED);
+ } /* end if */
+
/* Unprotect the indirect block */
if(H5AC_unprotect(iblock->hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock->addr, iblock, cache_flags) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block")
@@ -1215,7 +1296,7 @@ done:
/*-------------------------------------------------------------------------
* Function: H5HF_man_iblock_attach
*
- * Purpose: Attach a block to an indirect block
+ * Purpose: Attach a child block (direct or indirect) to an indirect block
*
* Return: SUCCEED/FAIL
*
@@ -1243,7 +1324,7 @@ H5HF_man_iblock_attach(H5HF_indirect_t *iblock, unsigned entry, haddr_t child_ad
if(H5HF_iblock_incr(iblock) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared indirect block")
- /* Point at the direct block */
+ /* Point at the child block */
iblock->ents[entry].addr = child_addr;
/* Check for I/O filters on this heap */
@@ -1280,7 +1361,7 @@ done:
/*-------------------------------------------------------------------------
* Function: H5HF_man_iblock_detach
*
- * Purpose: Detach a block from an indirect block
+ * Purpose: Detach a child block (direct or indirect) from an indirect block
*
* Return: SUCCEED/FAIL
*
@@ -1293,6 +1374,7 @@ done:
herr_t
H5HF_man_iblock_detach(H5HF_indirect_t *iblock, hid_t dxpl_id, unsigned entry)
{
+ unsigned row; /* Row for entry */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT
@@ -1306,16 +1388,14 @@ H5HF_man_iblock_detach(H5HF_indirect_t *iblock, hid_t dxpl_id, unsigned entry)
/* Reset address of entry */
iblock->ents[entry].addr = HADDR_UNDEF;
+ /* Compute row for entry */
+ row = entry / iblock->hdr->man_dtable.cparam.width;
+
/* Check for I/O filters on this heap */
if(iblock->hdr->filter_len > 0) {
- unsigned row; /* Row for entry */
-
/* Sanity check */
HDassert(iblock->filt_ents);
- /* Compute row for entry */
- row = entry / iblock->hdr->man_dtable.cparam.width;
-
/* If this is a direct block, reset its initial size */
if(row < iblock->hdr->man_dtable.max_direct_rows) {
iblock->filt_ents[entry].size = 0;
@@ -1323,6 +1403,24 @@ H5HF_man_iblock_detach(H5HF_indirect_t *iblock, hid_t dxpl_id, unsigned entry)
} /* end if */
} /* end if */
+ /* Check for indirect block being detached */
+ if(row >= iblock->hdr->man_dtable.max_direct_rows) {
+ unsigned indir_idx; /* Index in parent's child iblock pointer array */
+
+ /* Sanity check */
+ HDassert(iblock->child_iblocks);
+
+ /* Compute index in child iblock pointer array */
+ indir_idx = entry - (iblock->hdr->man_dtable.max_direct_rows
+ * iblock->hdr->man_dtable.cparam.width);
+
+ /* Sanity check */
+ HDassert(iblock->child_iblocks[indir_idx]);
+
+ /* Reset pointer to child indirect block in parent */
+ iblock->child_iblocks[indir_idx] = NULL;
+ } /* end if */
+
/* Decrement the # of child blocks */
/* (If the number of children drop to 0, the indirect block will be
* removed from the heap when its ref. count drops to zero and the
diff --git a/src/H5HFpkg.h b/src/H5HFpkg.h
index 2746302..498c45e 100644
--- a/src/H5HFpkg.h
+++ b/src/H5HFpkg.h
@@ -174,6 +174,11 @@
#define H5HF_OP_MODIFY 0x0001 /* Operation will modify object */
#define H5HF_OP_FLAGS (H5HF_OP_MODIFY) /* Bit-wise OR of all op flags */
+/* Flags for 'root_iblock_flags' field in header */
+#define H5HF_ROOT_IBLOCK_PINNED 0x01
+#define H5HF_ROOT_IBLOCK_PROTECTED 0x02
+
+
/****************************/
/* Package Private Typedefs */
/****************************/
@@ -342,7 +347,8 @@ typedef struct H5HF_hdr_t {
hbool_t pending_delete; /* Heap is pending deletion */
uint8_t sizeof_size; /* Size of file sizes */
uint8_t sizeof_addr; /* Size of file addresses */
- struct H5HF_indirect_t *root_iblock; /* Pointer to pinned root indirect block */
+ struct H5HF_indirect_t *root_iblock; /* Pointer to root indirect block */
+ unsigned root_iblock_flags; /* Flags to indicate whether root indirect block is pinned/protected */
H5FS_t *fspace; /* Free space list for objects in heap */
H5HF_block_iter_t next_block; /* Block iterator for searching for next block with space */
H5B2_t *huge_bt2; /* v2 B-tree handle for huge objects */
@@ -457,14 +463,14 @@ typedef struct H5HF_huge_bt2_filt_dir_rec_t {
typedef struct {
H5HF_hdr_t *hdr; /* Fractal heap header */
hid_t dxpl_id; /* DXPL ID for operation */
-} H5HF_sect_add_ud1_t;
+} H5HF_sect_add_ud_t;
/* User data for v2 B-tree 'remove' callback on 'huge' objects */
typedef struct {
H5HF_hdr_t *hdr; /* Fractal heap header (in) */
hid_t dxpl_id; /* DXPL ID for operation (in) */
hsize_t obj_len; /* Length of object removed (out) */
-} H5HF_huge_remove_ud1_t;
+} H5HF_huge_remove_ud_t;
/* User data for fractal heap header cache client callback */
typedef struct H5HF_hdr_cache_ud_t {
@@ -701,10 +707,14 @@ H5_DLL herr_t H5HF_tiny_op(H5HF_hdr_t *hdr, const uint8_t *id,
H5_DLL herr_t H5HF_tiny_remove(H5HF_hdr_t *fh, const uint8_t *id);
/* Debugging routines for dumping file structures */
+H5_DLL void H5HF_hdr_print(const H5HF_hdr_t *hdr, hid_t dxpl_id,
+ hbool_t dump_internal, FILE *stream, int indent, int fwidth);
H5_DLL herr_t H5HF_hdr_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr,
FILE *stream, int indent, int fwidth);
H5_DLL herr_t H5HF_dblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr,
FILE *stream, int indent, int fwidth, haddr_t hdr_addr, size_t nrec);
+H5_DLL void H5HF_iblock_print(const H5HF_indirect_t *iblock, hbool_t dump_internal,
+ FILE *stream, int indent, int fwidth);
H5_DLL herr_t H5HF_iblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr,
FILE *stream, int indent, int fwidth, haddr_t hdr_addr, unsigned nrows);
@@ -733,6 +743,9 @@ H5_DLL herr_t H5HF_space_add(H5HF_hdr_t *hdr, hid_t dxpl_id,
H5HF_free_section_t *node, unsigned flags);
H5_DLL htri_t H5HF_space_find(H5HF_hdr_t *hdr, hid_t dxpl_id, hsize_t request,
H5HF_free_section_t **node);
+H5_DLL herr_t H5HF_space_revert_root(const H5HF_hdr_t *hdr, hid_t dxpl_id);
+H5_DLL herr_t H5HF_space_create_root(const H5HF_hdr_t *hdr, hid_t dxpl_id,
+ H5HF_indirect_t *root_iblock);
H5_DLL herr_t H5HF_space_size(H5HF_hdr_t *hdr, hid_t dxpl_id, hsize_t *fs_size);
H5_DLL herr_t H5HF_space_remove(H5HF_hdr_t *hdr, hid_t dxpl_id,
H5HF_free_section_t *node);
diff --git a/src/H5HFsection.c b/src/H5HFsection.c
index 38d9381..87fa069 100644
--- a/src/H5HFsection.c
+++ b/src/H5HFsection.c
@@ -665,42 +665,6 @@ H5HF_sect_single_dblock_info(H5HF_hdr_t *hdr, hid_t dxpl_id,
HDassert(dblock_addr);
HDassert(dblock_size);
- /* Check for section in first direct block of heap */
- if(sect->sect_info.addr < hdr->man_dtable.cparam.start_block_size) {
- /* Check for heap changing from direct <-> indirect root (or vice versa)
- * while section was live.
- */
- if(sect->u.single.parent) {
- /* Check for heap converting from indirect root to direct root while section was live */
- if(hdr->man_dtable.curr_root_rows == 0) {
- /* Release hold on parent indirect block */
- if(H5HF_iblock_decr(sect->u.single.parent) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on section's indirect block")
-
- /* Reset parent information */
- sect->u.single.parent = NULL;
- sect->u.single.par_entry = 0;
- } /* end if */
- else {
- /* Check for heap converting from indirect to direct and back
- * to indirect again, which would indicate a different
- * indirect root block would be used for the parent of
- * this section and the actual root indirect block.
- */
- if(H5HF_sect_single_locate_parent(hdr, dxpl_id, TRUE, sect) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't get section's parent info")
- } /* end else */
- } /* end if */
- else {
- /* Check for heap converting from direct root to indirect root while section was live */
- if(hdr->man_dtable.curr_root_rows != 0) {
- /* Look up indirect block information for section */
- if(H5HF_sect_single_locate_parent(hdr, dxpl_id, FALSE, sect) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't get section's parent info")
- } /* end if */
- } /* end else */
- } /* end if */
-
/* Check for root direct block */
if(hdr->man_dtable.curr_root_rows == 0) {
/* Retrieve direct block info from heap header */
@@ -860,7 +824,7 @@ H5HF_sect_single_add(H5FS_section_info_t *_sect, unsigned *flags, void *_udata)
*/
if(!(*flags & H5FS_ADD_DESERIALIZING)) {
H5HF_free_section_t *sect = (H5HF_free_section_t *)_sect; /* Fractal heap free section */
- H5HF_sect_add_ud1_t *udata = (H5HF_sect_add_ud1_t *)_udata; /* User callback data */
+ H5HF_sect_add_ud_t *udata = (H5HF_sect_add_ud_t *)_udata; /* User callback data */
H5HF_hdr_t *hdr = udata->hdr; /* Fractal heap header */
hid_t dxpl_id = udata->dxpl_id; /* DXPL ID for operation */
@@ -992,7 +956,7 @@ H5HF_sect_single_merge(H5FS_section_info_t *_sect1, H5FS_section_info_t *_sect2,
{
H5HF_free_section_t *sect1 = (H5HF_free_section_t *)_sect1; /* Fractal heap free section */
H5HF_free_section_t *sect2 = (H5HF_free_section_t *)_sect2; /* Fractal heap free section */
- H5HF_sect_add_ud1_t *udata = (H5HF_sect_add_ud1_t *)_udata; /* User callback data */
+ H5HF_sect_add_ud_t *udata = (H5HF_sect_add_ud_t *)_udata; /* User callback data */
H5HF_hdr_t *hdr = udata->hdr; /* Fractal heap header */
hid_t dxpl_id = udata->dxpl_id; /* DXPL ID for operation */
herr_t ret_value = SUCCEED; /* Return value */
@@ -1050,7 +1014,7 @@ static htri_t
H5HF_sect_single_can_shrink(const H5FS_section_info_t *_sect, void *_udata)
{
const H5HF_free_section_t *sect = (const H5HF_free_section_t *)_sect; /* Fractal heap free section */
- H5HF_sect_add_ud1_t *udata = (H5HF_sect_add_ud1_t *)_udata; /* User callback data */
+ H5HF_sect_add_ud_t *udata = (H5HF_sect_add_ud_t *)_udata; /* User callback data */
H5HF_hdr_t *hdr = udata->hdr; /* Fractal heap header */
htri_t ret_value = FALSE; /* Return value */
@@ -1105,7 +1069,7 @@ static herr_t
H5HF_sect_single_shrink(H5FS_section_info_t **_sect, void UNUSED *_udata)
{
H5HF_free_section_t **sect = (H5HF_free_section_t **)_sect; /* Fractal heap free section */
- H5HF_sect_add_ud1_t *udata = (H5HF_sect_add_ud1_t *)_udata; /* User callback data */
+ H5HF_sect_add_ud_t *udata = (H5HF_sect_add_ud_t *)_udata; /* User callback data */
H5HF_hdr_t *hdr = udata->hdr; /* Fractal heap header */
hid_t dxpl_id = udata->dxpl_id; /* DXPL ID for operation */
H5HF_direct_t *dblock; /* Pointer to direct block for section */
@@ -1814,7 +1778,7 @@ H5HF_sect_row_merge(H5FS_section_info_t *_sect1, H5FS_section_info_t *_sect2,
{
H5HF_free_section_t *sect1 = (H5HF_free_section_t *)_sect1; /* Fractal heap free section */
H5HF_free_section_t *sect2 = (H5HF_free_section_t *)_sect2; /* Fractal heap free section */
- H5HF_sect_add_ud1_t *udata = (H5HF_sect_add_ud1_t *)_udata; /* User callback data */
+ H5HF_sect_add_ud_t *udata = (H5HF_sect_add_ud_t *)_udata; /* User callback data */
H5HF_hdr_t *hdr = udata->hdr; /* Fractal heap header */
hid_t dxpl_id = udata->dxpl_id; /* DXPL ID for operation */
herr_t ret_value = SUCCEED; /* Return value */
@@ -1881,7 +1845,7 @@ static htri_t
H5HF_sect_row_can_shrink(const H5FS_section_info_t *_sect, void UNUSED *_udata)
{
const H5HF_free_section_t *sect = (const H5HF_free_section_t *)_sect; /* Fractal heap free section */
- H5HF_sect_add_ud1_t *udata = (H5HF_sect_add_ud1_t *)_udata; /* User callback data */
+ H5HF_sect_add_ud_t *udata = (H5HF_sect_add_ud_t *)_udata; /* User callback data */
H5HF_hdr_t *hdr = udata->hdr; /* Fractal heap header */
htri_t ret_value = FALSE; /* Return value */
@@ -1919,7 +1883,7 @@ H5HF_sect_row_shrink(H5FS_section_info_t **_sect, void *_udata)
{
H5HF_free_section_t **sect = (H5HF_free_section_t **)_sect; /* Fractal heap free section */
H5HF_free_section_t *top_indir_sect; /* Top indirect section for row */
- H5HF_sect_add_ud1_t *udata = (H5HF_sect_add_ud1_t *)_udata; /* User callback data */
+ H5HF_sect_add_ud_t *udata = (H5HF_sect_add_ud_t *)_udata; /* User callback data */
H5HF_hdr_t *hdr = udata->hdr; /* Fractal heap header */
hid_t dxpl_id = udata->dxpl_id; /* DXPL ID for operation */
herr_t ret_value = SUCCEED; /* Return value */
@@ -2161,7 +2125,7 @@ H5HF_sect_indirect_iblock_off(const H5HF_free_section_t *sect)
*
* Purpose: Get the "top" indirect section
*
- * Return: Pointer to the top indirect sectin (can't fail)
+ * Return: Pointer to the top indirect section (can't fail)
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
diff --git a/src/H5HFspace.c b/src/H5HFspace.c
index cec9b3a..01330d3 100644
--- a/src/H5HFspace.c
+++ b/src/H5HFspace.c
@@ -168,7 +168,7 @@ herr_t
H5HF_space_add(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *node,
unsigned flags)
{
- H5HF_sect_add_ud1_t udata; /* User data for free space manager 'add' */
+ H5HF_sect_add_ud_t udata; /* User data for free space manager 'add' */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT
@@ -246,6 +246,185 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5HF_space_revert_root_cb
+ *
+ * Purpose: Callback routine from iterator, to reset 'parent' pointers in
+ * sections, when the heap is changing from having a root indirect
+ * block to a direct block.
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Feb 24 2012
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HF_space_revert_root_cb(H5FS_section_info_t *_sect, void UNUSED *_udata)
+{
+ H5HF_free_section_t *sect = (H5HF_free_section_t *)_sect; /* Section to dump info */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ /*
+ * Check arguments.
+ */
+ HDassert(sect);
+
+ /* Only modify "live" single blocks... */
+ if(sect->sect_info.type == H5HF_FSPACE_SECT_SINGLE && sect->sect_info.state == H5FS_SECT_LIVE) {
+ /* Release hold on previous indirect block (we must have one) */
+ HDassert(sect->u.single.parent);
+ if(H5HF_iblock_decr(sect->u.single.parent) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on section's indirect block")
+
+ /* Reset parent information */
+ sect->u.single.parent = NULL;
+ sect->u.single.par_entry = 0;
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF_space_revert_root_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_space_revert_root
+ *
+ * Purpose: Reset 'parent' pointers in sections, when the heap is
+ * changing from having a root indirect block to a direct block.
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Feb 23 2012
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5HF_space_revert_root(const H5HF_hdr_t *hdr, hid_t dxpl_id)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ /*
+ * Check arguments.
+ */
+ HDassert(hdr);
+
+ /* Only need to scan the sections if the free space has been initialized */
+ if(hdr->fspace) {
+ /* Iterate over all sections, reseting the parent pointers in 'single' sections */
+ if(H5FS_sect_iterate(hdr->f, dxpl_id, hdr->fspace, H5HF_space_revert_root_cb, NULL) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_BADITER, FAIL, "can't iterate over sections to reset parent pointers")
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF_space_revert_root() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_space_create_root_cb
+ *
+ * Purpose: Callback routine from iterator, to set 'parent' pointers in
+ * sections to newly created root indirect block, when the heap
+ * is changing from having a root direct block to an indirect block.
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Feb 24 2012
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HF_space_create_root_cb(H5FS_section_info_t *_sect, void *_udata)
+{
+ H5HF_free_section_t *sect = (H5HF_free_section_t *)_sect; /* Section to dump info */
+ H5HF_indirect_t *root_iblock = (H5HF_indirect_t *)_udata; /* User data for callback */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ /*
+ * Check arguments.
+ */
+ HDassert(sect);
+ HDassert(root_iblock);
+
+ /* Sanity check sections */
+ /* (If we are switching from a direct block for the root block of the heap, */
+ /* there should only be 'single' type sections. -QAK) */
+ HDassert(sect->sect_info.type == H5HF_FSPACE_SECT_SINGLE);
+
+ /* Increment ref. count on new root indirect block */
+ if(H5HF_iblock_incr(root_iblock) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on section's indirect block")
+
+ /* Set parent info ("live" section must _NOT_ have a parent right now) */
+ if(sect->sect_info.state == H5FS_SECT_SERIALIZED)
+ sect->sect_info.state = H5FS_SECT_LIVE; /* Mark "live" now */
+ else
+ HDassert(!sect->u.single.parent);
+ sect->u.single.parent = root_iblock;
+ sect->u.single.par_entry = 0;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF_space_create_root_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_space_create_root
+ *
+ * Purpose: Set 'parent' pointers in sections to new indirect block, when
+ * the heap is changing from having a root direct block to a
+ * indirect block.
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Feb 24 2012
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5HF_space_create_root(const H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_indirect_t *root_iblock)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ /*
+ * Check arguments.
+ */
+ HDassert(hdr);
+ HDassert(root_iblock);
+
+ /* Only need to scan the sections if the free space has been initialized */
+ if(hdr->fspace) {
+ /* Iterate over all sections, seting the parent pointers in 'single' sections to the new indirect block */
+ if(H5FS_sect_iterate(hdr->f, dxpl_id, hdr->fspace, H5HF_space_create_root_cb, root_iblock) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_BADITER, FAIL, "can't iterate over sections to set parent pointers")
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF_space_create_root() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5HF_space_size
*
* Purpose: Query the size of the heap's free space info on disk
diff --git a/src/H5I.c b/src/H5I.c
index 617b7a4..7b33533 100644
--- a/src/H5I.c
+++ b/src/H5I.c
@@ -109,6 +109,11 @@ typedef struct {
H5I_id_info_t **id_list; /*pointer to an array of ptrs to IDs */
} H5I_id_type_t;
+typedef struct {
+ H5I_search_func_t app_cb; /* Application's callback routine */
+ void *app_key; /* Application's "key" (user data) */
+ void *ret_obj; /* Object to return */
+} H5I_search_ud_t;
/*-------------------- Locally scoped variables -----------------------------*/
@@ -128,6 +133,7 @@ H5FL_DEFINE_STATIC(H5I_id_info_t);
/*--------------------- Local function prototypes ---------------------------*/
static H5I_id_info_t *H5I_find_id(hid_t id);
+static int H5I_search_cb(void *obj, hid_t id, void *udata);
#ifdef H5I_DEBUG_OUTPUT
static herr_t H5I_debug(H5I_type_t type);
#endif /* H5I_DEBUG_OUTPUT */
@@ -1921,6 +1927,40 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5I_search_cb
+ *
+ * Purpose: Callback routine for H5Isearch, when it calls H5I_iterate.
+ * Calls "user" callback search function, and then sets return
+ * value, based on the result of that callback.
+ *
+ * Return: Success: The first object in the type for which FUNC
+ * returns non-zero. NULL if FUNC returned zero
+ * for every object in the type.
+ * Failure: NULL
+ *
+ * Programmer: Quincey Koziol
+ * Friday, March 30, 2012
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+H5I_search_cb(void *obj, hid_t id, void *_udata)
+{
+ H5I_search_ud_t *udata = (H5I_search_ud_t *)_udata; /* User data for callback */
+ int ret_value; /* Callback return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ ret_value = (*udata->app_cb)(obj, id, udata->app_key);
+ if(ret_value > 0)
+ udata->ret_obj = obj;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5I_search_cb() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5Isearch
*
* Purpose: Apply function FUNC to each member of type TYPE and return a
@@ -1947,14 +1987,27 @@ done:
void *
H5Isearch(H5I_type_t type, H5I_search_func_t func, void *key)
{
- void * ret_value; /* Return value */
+ H5I_search_ud_t udata; /* Context for iteration */
+ void *ret_value; /* Return value */
FUNC_ENTER_API(NULL)
+ /* Check arguments */
if(H5I_IS_LIB_TYPE(type))
HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "cannot call public function on library type")
- ret_value = H5I_search(type, func, key, TRUE);
+ /* Set up udata struct */
+ udata.app_cb = func;
+ udata.app_key = key;
+ udata.ret_obj = NULL;
+
+ /* Note that H5I_iterate returns an error code. We ignore it
+ * here, as we can't do anything with it without revising the API.
+ */
+ H5I_iterate(type, H5I_search_cb, &udata, TRUE);
+
+ /* Set return value */
+ ret_value = udata.ret_obj;
done:
FUNC_LEAVE_API(ret_value)
@@ -1962,64 +2015,72 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5I_search
+ * Function: H5I_iterate
*
- * Purpose: Apply function FUNC to each member of type TYPE and return a
- * pointer to the first object for which FUNC returns non-zero.
- * The FUNC should take a pointer to the object and the KEY as
- * arguments and return non-zero to terminate the search (zero
- * to continue).
+ * Purpose: Apply function FUNC to each member of type TYPE (with
+ * non-zero application reference count if app_ref is TRUE).
+ * Stop if FUNC returns a non zero value (i.e. anything
+ * other than H5_ITER_CONT).
*
- * Limitation: Currently there is no way to start searching from where a
- * previous search left off.
+ * If FUNC returns a positive value (i.e. H5_ITER_STOP),
+ * return SUCCEED.
*
- * Return: Success: The first object in the type for which FUNC
- * returns non-zero. NULL if FUNC returned zero
- * for every object in the type.
- * Failure: NULL
+ * If FUNC returns a negative value (i.e. H5_ITER_ERROR),
+ * return FAIL.
+ *
+ * The FUNC should take a pointer to the object and the
+ * udata as arguments and return non-zero to terminate
+ * siteration, and zero to continue.
*
- * Programmer: Robb Matzke
- * Friday, February 19, 1999
+ * Limitation: Currently there is no way to start the iteration from
+ * where a previous iteration left off.
*
- * Modifications: Neil Fortner
- * Wednesday, October 1, 2008
- * Added app_ref parameter. When set to TRUE, the function will only
- * operate on ids that have a nonzero application reference count.
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: John Mainzer
+ * Monday, December 6, 2011
*
*-------------------------------------------------------------------------
*/
-void *
-H5I_search(H5I_type_t type, H5I_search_func_t func, void *key, hbool_t app_ref)
+herr_t
+H5I_iterate(H5I_type_t type, H5I_search_func_t func, void *udata, hbool_t app_ref)
{
- H5I_id_type_t *type_ptr; /*ptr to the type */
- void *ret_value = NULL; /*return value */
+ H5I_id_type_t *type_ptr; /*ptr to the type */
+ herr_t ret_value = SUCCEED; /*return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
- FUNC_ENTER_NOAPI(NULL
-)
/* Check arguments */
if(type <= H5I_BADID || type >= H5I_next_type)
- HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, NULL, "invalid type number")
+ HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number")
type_ptr = H5I_id_type_list_g[type];
- if(type_ptr == NULL || type_ptr->count <= 0)
- HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "invalid type")
-
- /* Only iterate through hash table if there are IDs in group */
- if(type_ptr->ids > 0) {
- H5I_id_info_t *id_ptr; /*ptr to the new ID */
- H5I_id_info_t *next_id; /*ptr to the next ID */
- unsigned i; /*counter */
+ /* Only iterate through hash table if it is initialized and there are IDs in group */
+ if(type_ptr && type_ptr->count > 0 && type_ptr->ids > 0) {
+ unsigned u; /* Counter */
/* Start at the beginning of the array */
- for(i = 0; i < type_ptr->hash_size; i++) {
- id_ptr = type_ptr->id_list[i];
+ for(u = 0; u < type_ptr->hash_size; u++) {
+ H5I_id_info_t *id_ptr; /* Ptr to the new ID */
+
+ id_ptr = type_ptr->id_list[u];
while(id_ptr) {
- next_id = id_ptr->next; /* Protect against ID being deleted in callback */
- /* (Casting away const OK -QAK) */
- if((!app_ref || id_ptr->app_count) && (*func)((void *)id_ptr->obj_ptr, id_ptr->id, key))
- /* (Casting away const OK -QAK) */
- HGOTO_DONE((void *)id_ptr->obj_ptr); /*found the item*/
+ H5I_id_info_t *next_id; /* Ptr to the next ID */
+
+ /* Protect against ID being deleted in callback */
+ next_id = id_ptr->next;
+ if((!app_ref) || (id_ptr->app_count > 0)) {
+ herr_t cb_ret_val; /* Callback return value */
+
+ /* (Casting away const OK) */
+ cb_ret_val = (*func)((void *)id_ptr->obj_ptr, id_ptr->id, udata);
+ if(cb_ret_val > 0)
+ HGOTO_DONE(SUCCEED) /* terminate iteration early */
+ else if(cb_ret_val < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "func failed")
+ } /* end if */
id_ptr = next_id;
} /* end while */
} /* end for */
@@ -2027,7 +2088,7 @@ H5I_search(H5I_type_t type, H5I_search_func_t func, void *key, hbool_t app_ref)
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5I_search() */
+} /* end H5I_iterate() */
/*-------------------------------------------------------------------------
diff --git a/src/H5Iprivate.h b/src/H5Iprivate.h
index 3a9e2db..ee938df 100644
--- a/src/H5Iprivate.h
+++ b/src/H5Iprivate.h
@@ -70,7 +70,7 @@ H5_DLL H5I_type_t H5I_get_type(hid_t id);
H5_DLL hid_t H5I_get_file_id(hid_t obj_id, hbool_t app_ref);
H5_DLL void *H5I_remove(hid_t id);
H5_DLL void *H5I_remove_verify(hid_t id, H5I_type_t id_type);
-H5_DLL void *H5I_search(H5I_type_t type, H5I_search_func_t func, void *key, hbool_t app_ref);
+H5_DLL herr_t H5I_iterate(H5I_type_t type, H5I_search_func_t func, void *udata, hbool_t app_ref);
H5_DLL int H5I_get_ref(hid_t id, hbool_t app_ref);
H5_DLL int H5I_inc_ref(hid_t id, hbool_t app_ref);
H5_DLL int H5I_dec_ref(hid_t id);
diff --git a/src/H5MF.c b/src/H5MF.c
index fce151e..f9ca256 100644
--- a/src/H5MF.c
+++ b/src/H5MF.c
@@ -1172,9 +1172,9 @@ HDfprintf(stderr, "%s: Leaving\n", FUNC);
*-------------------------------------------------------------------------
*/
static herr_t
-H5MF_sects_cb(const H5FS_section_info_t *_sect, void *_udata)
+H5MF_sects_cb(H5FS_section_info_t *_sect, void *_udata)
{
- const H5MF_free_section_t *sect = (const H5MF_free_section_t *)_sect;
+ H5MF_free_section_t *sect = (H5MF_free_section_t *)_sect;
H5MF_sect_iter_ud_t *udata = (H5MF_sect_iter_ud_t *)_udata;
FUNC_ENTER_NOAPI_NOINIT_NOERR
diff --git a/src/H5MFdbg.c b/src/H5MFdbg.c
index bdc811f..d6fc5ce 100644
--- a/src/H5MFdbg.c
+++ b/src/H5MFdbg.c
@@ -99,9 +99,9 @@ typedef struct {
*-------------------------------------------------------------------------
*/
static herr_t
-H5MF_sects_debug_cb(const H5FS_section_info_t *_sect, void *_udata)
+H5MF_sects_debug_cb(H5FS_section_info_t *_sect, void *_udata)
{
- const H5MF_free_section_t *sect = (const H5MF_free_section_t *)_sect; /* Section to dump info */
+ H5MF_free_section_t *sect = (H5MF_free_section_t *)_sect; /* Section to dump info */
H5MF_debug_iter_ud_t *udata = (H5MF_debug_iter_ud_t *)_udata; /* User data for callbacks */
herr_t ret_value = SUCCEED; /* Return value */
diff --git a/src/H5O.c b/src/H5O.c
index 82d9453..ec4cba9 100644
--- a/src/H5O.c
+++ b/src/H5O.c
@@ -79,12 +79,12 @@ typedef struct {
/********************/
static herr_t H5O_delete_oh(H5F_t *f, hid_t dxpl_id, H5O_t *oh);
-static const H5O_obj_class_t *H5O_obj_class(const H5O_loc_t *loc, hid_t dxpl_id);
static herr_t H5O_obj_type_real(H5O_t *oh, H5O_type_t *obj_type);
static herr_t H5O_visit(hid_t loc_id, const char *obj_name, H5_index_t idx_type,
H5_iter_order_t order, H5O_iterate_t op, void *op_data, hid_t lapl_id,
hid_t dxpl_id);
static herr_t H5O_get_hdr_info_real(const H5O_t *oh, H5O_hdr_info_t *hdr);
+static const H5O_obj_class_t *H5O_obj_class_real(H5O_t *oh);
/*********************/
@@ -2382,7 +2382,7 @@ H5O_obj_type_real(H5O_t *oh, H5O_type_t *obj_type)
*
*-------------------------------------------------------------------------
*/
-static const H5O_obj_class_t *
+const H5O_obj_class_t *
H5O_obj_class(const H5O_loc_t *loc, hid_t dxpl_id)
{
H5O_t *oh = NULL; /* Object header for location */
@@ -2419,7 +2419,7 @@ done:
*
*-------------------------------------------------------------------------
*/
-const H5O_obj_class_t *
+static const H5O_obj_class_t *
H5O_obj_class_real(H5O_t *oh)
{
size_t i; /* Local index variable */
diff --git a/src/H5Oainfo.c b/src/H5Oainfo.c
index ff4cc5d..b207ea2 100644
--- a/src/H5Oainfo.c
+++ b/src/H5Oainfo.c
@@ -46,11 +46,11 @@ static herr_t H5O_ainfo_delete(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
static herr_t H5O_ainfo_pre_copy_file(H5F_t *file_src, const void *mesg_src,
hbool_t *deleted, const H5O_copy_t *cpy_info, void *udata);
static void *H5O_ainfo_copy_file(H5F_t *file_src, void *mesg_src,
- H5F_t *file_dst, hbool_t *recompute_size, H5O_copy_t *cpy_info, void *udata,
- hid_t dxpl_id);
+ H5F_t *file_dst, hbool_t *recompute_size, unsigned *mesg_flags,
+ H5O_copy_t *cpy_info, void *udata, hid_t dxpl_id);
static herr_t H5O_ainfo_post_copy_file(const H5O_loc_t *src_oloc,
- const void *mesg_src, H5O_loc_t *dst_oloc, void *mesg_dst, hid_t dxpl_id,
- H5O_copy_t *cpy_info);
+ const void *mesg_src, H5O_loc_t *dst_oloc, void *mesg_dst,
+ unsigned *mesg_flags, hid_t dxpl_id, H5O_copy_t *cpy_info);
static herr_t H5O_ainfo_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg,
FILE * stream, int indent, int fwidth);
@@ -403,7 +403,8 @@ H5O_ainfo_pre_copy_file(H5F_t UNUSED *file_src, const void UNUSED *native_src,
*/
static void *
H5O_ainfo_copy_file(H5F_t *file_src, void *mesg_src, H5F_t *file_dst,
- hbool_t UNUSED *recompute_size, H5O_copy_t *cpy_info, void UNUSED *udata, hid_t dxpl_id)
+ hbool_t UNUSED *recompute_size, unsigned UNUSED *mesg_flags,
+ H5O_copy_t *cpy_info, void UNUSED *udata, hid_t dxpl_id)
{
H5O_ainfo_t *ainfo_src = (H5O_ainfo_t *)mesg_src;
H5O_ainfo_t *ainfo_dst = NULL;
@@ -468,7 +469,8 @@ done:
*/
static herr_t
H5O_ainfo_post_copy_file(const H5O_loc_t *src_oloc, const void *mesg_src,
- H5O_loc_t *dst_oloc, void *mesg_dst, hid_t dxpl_id, H5O_copy_t *cpy_info)
+ H5O_loc_t *dst_oloc, void *mesg_dst, unsigned UNUSED *mesg_flags,
+ hid_t dxpl_id, H5O_copy_t *cpy_info)
{
const H5O_ainfo_t *ainfo_src = (const H5O_ainfo_t *)mesg_src;
herr_t ret_value = SUCCEED; /* Return value */
diff --git a/src/H5Oattr.c b/src/H5Oattr.c
index 8cd243b..510d64f 100644
--- a/src/H5Oattr.c
+++ b/src/H5Oattr.c
@@ -61,6 +61,7 @@ static herr_t H5O_attr_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg,
#define H5O_SHARED_COPY_FILE_REAL H5O_attr_copy_file
#define H5O_SHARED_POST_COPY_FILE H5O_attr_shared_post_copy_file
#define H5O_SHARED_POST_COPY_FILE_REAL H5O_attr_post_copy_file
+#undef H5O_SHARED_POST_COPY_FILE_UPD
#define H5O_SHARED_DEBUG H5O_attr_shared_debug
#define H5O_SHARED_DEBUG_REAL H5O_attr_debug
#include "H5Oshared.h" /* Shared Object Header Message Callbacks */
diff --git a/src/H5Oattribute.c b/src/H5Oattribute.c
index fbfc140..30ec732 100644
--- a/src/H5Oattribute.c
+++ b/src/H5Oattribute.c
@@ -135,9 +135,6 @@ typedef struct {
/********************/
/* Local Prototypes */
/********************/
-static herr_t H5O_attr_iterate_real(hid_t loc_id, const H5O_loc_t *loc,
- hid_t dxpl_id, H5_index_t idx_type, H5_iter_order_t order, hsize_t skip,
- hsize_t *last_attr, const H5A_attr_iter_op_t *attr_op, void *op_data);
static htri_t H5O_attr_find_opened_attr(const H5O_loc_t *loc, H5A_t **attr,
const char* name_to_open);
@@ -437,8 +434,10 @@ H5O_attr_open_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/, unsigned sequence,
if(NULL == (udata->attr = H5A_copy(NULL, (H5A_t *)mesg->native)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, H5_ITER_ERROR, "unable to copy attribute")
- /* Assign [somewhat arbitrary] creation order value, for older versions of the format */
- if(oh->version == H5O_VERSION_1)
+ /* Assign [somewhat arbitrary] creation order value, for older versions
+ * of the format or if creation order is not tracked */
+ if(oh->version == H5O_VERSION_1
+ || !(oh->flags & H5O_HDR_ATTR_CRT_ORDER_TRACKED))
udata->attr->shared->crt_idx = sequence;
/* Stop iterating */
@@ -704,18 +703,23 @@ H5O_attr_find_opened_attr(const H5O_loc_t *loc, H5A_t **attr, const char* name_t
HGOTO_ERROR(H5E_ATTR, H5E_BADVALUE, FAIL, "can't get file serial number")
/* Count all opened attributes */
- num_open_attr = H5F_get_obj_count(loc->file, H5F_OBJ_ATTR | H5F_OBJ_LOCAL, FALSE);
+ if(H5F_get_obj_count(loc->file, H5F_OBJ_ATTR | H5F_OBJ_LOCAL, FALSE, &num_open_attr) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't count opened attributes")
/* Find out whether the attribute has been opened */
if(num_open_attr) {
+ size_t check_num_attr; /* Number of open attribute IDs */
size_t u; /* Local index variable */
/* Allocate space for the attribute ID list */
if(NULL == (attr_id_list = (hid_t *)H5MM_malloc(num_open_attr * sizeof(hid_t))))
- HGOTO_ERROR(H5E_ATTR, H5E_NOSPACE, FAIL, "unable to allocate memory for attribute ID list")
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, FAIL, "unable to allocate memory for attribute ID list")
/* Retrieve the IDs of all opened attributes */
- H5F_get_obj_ids(loc->file, H5F_OBJ_ATTR | H5F_OBJ_LOCAL, num_open_attr, attr_id_list, FALSE);
+ if(H5F_get_obj_ids(loc->file, H5F_OBJ_ATTR | H5F_OBJ_LOCAL, num_open_attr, attr_id_list, FALSE, &check_num_attr) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't get IDs of opened attributes")
+ if(check_num_attr != num_open_attr)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_BADITER, FAIL, "open attribute count mismatch")
/* Iterate over the attributes */
for(u = 0; u < num_open_attr; u++) {
@@ -1260,7 +1264,7 @@ done:
*
*-------------------------------------------------------------------------
*/
-static herr_t
+herr_t
H5O_attr_iterate_real(hid_t loc_id, const H5O_loc_t *loc, hid_t dxpl_id,
H5_index_t idx_type, H5_iter_order_t order, hsize_t skip,
hsize_t *last_attr, const H5A_attr_iter_op_t *attr_op, void *op_data)
diff --git a/src/H5Ocopy.c b/src/H5Ocopy.c
index dd649ff..7b812ec 100644
--- a/src/H5Ocopy.c
+++ b/src/H5Ocopy.c
@@ -34,10 +34,12 @@
/* Headers */
/***********/
#include "H5private.h" /* Generic Functions */
+#include "H5Aprivate.h" /* Attributes */
#include "H5Eprivate.h" /* Error handling */
#include "H5FLprivate.h" /* Free lists */
#include "H5Iprivate.h" /* IDs */
#include "H5HGprivate.h" /* Global Heaps */
+#include "H5FOprivate.h" /* File objects */
#include "H5Lprivate.h" /* Links */
#include "H5MFprivate.h" /* File memory management */
#include "H5MMprivate.h" /* Memory management */
@@ -54,6 +56,20 @@
/* Local Typedefs */
/******************/
+/* Key object for skiplist of committed datatypes */
+typedef struct H5O_copy_search_comm_dt_key_t {
+ H5T_t *dt; /* Datatype */
+ unsigned long fileno; /* File number */
+} H5O_copy_search_comm_dt_key_t;
+
+/* Callback struct for building a list of committed datatypes */
+typedef struct H5O_copy_search_comm_dt_ud_t {
+ H5SL_t *dst_dt_list; /* Skip list of committed datatypes */
+ H5G_loc_t *dst_root_loc; /* Starting location for iteration */
+ H5O_loc_t obj_oloc; /* Object location (for attribute iteration callback) */
+ hid_t dxpl_id; /* Dataset transfer property list id */
+} H5O_copy_search_comm_dt_ud_t;
+
/********************/
/* Package Typedefs */
@@ -65,14 +81,23 @@
/********************/
static herr_t H5O_copy_free_addrmap_cb(void *item, void *key, void *op_data);
-static herr_t H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */,
+static herr_t H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out*/,
hid_t dxpl_id, H5O_copy_t *cpy_info, H5O_type_t *obj_type, void **udata);
-static herr_t H5O_copy_header(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */,
- hid_t dxpl_id, unsigned cpy_option);
+static herr_t H5O_copy_header(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out*/,
+ hid_t dxpl_id, hid_t ocpypl_id);
static herr_t H5O_copy_obj(H5G_loc_t *src_loc, H5G_loc_t *dst_loc,
const char *dst_name, hid_t ocpypl_id, hid_t lcpl_id);
static herr_t H5O_copy_obj_by_ref(H5O_loc_t *src_oloc, hid_t dxpl_id,
H5O_loc_t *dst_oloc, H5G_loc_t *dst_root_loc, H5O_copy_t *cpy_info);
+static herr_t H5O_copy_free_comm_dt_cb(void *item, void *key, void *op_data);
+static int H5O_copy_comm_dt_cmp(const void *dt1, const void *dt2);
+static herr_t H5O_copy_search_comm_dt_cb(hid_t group, const char *name,
+ const H5L_info_t *linfo, void *udata);
+static htri_t H5O_copy_search_comm_dt(H5F_t *file_src, H5O_t *oh_src,
+ H5O_loc_t *oloc_dst/*in, out*/, hid_t dxpl_id, H5O_copy_t *cpy_info);
+static herr_t H5O_copy_insert_comm_dt(H5F_t *file_src, H5O_t *oh_src,
+ H5O_loc_t *oloc_dst, hid_t dxpl_id, H5O_copy_t *cpy_info);
+
/*********************/
/* Package Variables */
@@ -81,6 +106,12 @@ static herr_t H5O_copy_obj_by_ref(H5O_loc_t *src_oloc, hid_t dxpl_id,
/* Declare a free list to manage the H5O_addr_map_t struct */
H5FL_DEFINE(H5O_addr_map_t);
+/* Declare a free list to manage the H5O_copy_search_comm_dt_key_t struct */
+H5FL_DEFINE(H5O_copy_search_comm_dt_key_t);
+
+/* Declare a free list to manage haddr_t variables */
+H5FL_DEFINE(haddr_t);
+
/*****************************/
/* Library Private Variables */
@@ -281,11 +312,19 @@ done:
* Programmer: Peter Cao
* May 30, 2005
*
+ * Modifications:
+ * Vailin Choi; Feb 2012
+ * Bug fix for HDFFV-7853
+ * When the object is opened, call the object's flush class action
+ * to ensure that cached data is flushed so that H5Ocopy will get
+ * the correct data.
+ *
*-------------------------------------------------------------------------
*/
static herr_t
-H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */,
- hid_t dxpl_id, H5O_copy_t *cpy_info, H5O_type_t *obj_type, void **udata)
+H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out*/,
+ hid_t dxpl_id, H5O_copy_t *cpy_info, H5O_type_t *obj_type,
+ void **udata /*out*/)
{
H5O_addr_map_t *addr_map = NULL; /* Address mapping of object copied */
H5O_t *oh_src = NULL; /* Object header for source object */
@@ -316,19 +355,85 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */,
HDassert(oloc_dst->file);
HDassert(cpy_info);
+ /* Get pointer to object class for this object */
+ if((obj_class = H5O_obj_class(oloc_src, dxpl_id)) == NULL)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to determine object type")
+
+ /* Check if the object at the address is already open in the file */
+ if(H5FO_opened(oloc_src->file, oloc_src->addr) != NULL) {
+
+ H5G_loc_t tmp_loc; /* Location of object */
+ H5O_loc_t tmp_oloc; /* Location of object */
+ H5G_name_t tmp_path; /* Object's path */
+
+ tmp_loc.oloc = &tmp_oloc;
+ tmp_loc.path = &tmp_path;
+ tmp_oloc.file = oloc_src->file;
+ tmp_oloc.addr = oloc_src->addr;
+ tmp_oloc.holding_file = oloc_src->holding_file;
+ H5G_name_reset(tmp_loc.path);
+
+ /* Flush the object of this class */
+ if(obj_class->flush && obj_class->flush(&tmp_loc, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTFLUSH, FAIL, "unable to flush object")
+ }
+
/* Get source object header */
if(NULL == (oh_src = H5O_protect(oloc_src, dxpl_id, H5AC_READ)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
- /* Get pointer to object class for this object */
- if(NULL == (obj_class = H5O_obj_class_real(oh_src)))
- HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to determine object type")
-
/* Retrieve user data for particular type of object to copy */
if(obj_class->get_copy_file_udata &&
(NULL == (cpy_udata = (obj_class->get_copy_file_udata)())))
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to retrieve copy user data")
+ /* If we are merging committed datatypes, check for a match in the destination
+ * file now */
+ if(cpy_info->merge_comm_dt && obj_class->type == H5O_TYPE_NAMED_DATATYPE) {
+ unsigned long fileno_src; /* fileno for source file */
+ unsigned long fileno_dst; /* fileno for destination file */
+ htri_t merge; /* Whether we found a match in the destination file */
+
+ /* Check if the source and dest file are the same. If so, just return
+ * the source object address */
+ H5F_GET_FILENO(oloc_src->file, fileno_src);
+ H5F_GET_FILENO(oloc_dst->file, fileno_dst);
+ if(fileno_src == fileno_dst) {
+ merge = TRUE;
+ oloc_dst->addr = oloc_src->addr;
+ } /* end if */
+ else
+ /* Search for a matching committed datatype, building the list if
+ * necessary */
+ if((merge = H5O_copy_search_comm_dt(oloc_src->file, oh_src, oloc_dst, dxpl_id, cpy_info)) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't search for matching committed datatype")
+
+ if(merge) {
+ /* Found a match, add to skip list and exit */
+ /* Allocate space for the address mapping of the object copied */
+ if(NULL == (addr_map = H5FL_MALLOC(H5O_addr_map_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+
+ /* Insert the address mapping for the found object into the copied
+ * list */
+ addr_map->src_obj_pos.fileno = fileno_src;
+ addr_map->src_obj_pos.addr = oloc_src->addr;
+ addr_map->dst_addr = oloc_dst->addr;
+ addr_map->is_locked = TRUE; /* We've locked the object currently */
+ addr_map->inc_ref_count = 0; /* Start with no additional ref counts to add */
+ addr_map->obj_class = obj_class;
+ addr_map->udata = cpy_udata;
+
+ /* Insert into skip list */
+ if(H5SL_insert(cpy_info->map_list, addr_map, &(addr_map->src_obj_pos)) < 0) {
+ addr_map = H5FL_FREE(H5O_addr_map_t, addr_map);
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "can't insert object into skip list")
+ } /* end if */
+
+ HGOTO_DONE(SUCCEED)
+ } /* end if */
+ } /* end if */
+
/* Flush any dirty messages in source object header to update the header chunks */
if(H5O_flush_msgs(oloc_src->file, oh_src) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTFLUSH, FAIL, "unable to flush object header messages")
@@ -470,38 +575,33 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */,
/* copy this message into destination file */
if(copy_type->copy_file) {
- htri_t is_shared; /* Whether message is shared */
hbool_t recompute_size; /* Whether copy_file callback created a shared message */
+ unsigned mesg_flags; /* Message flags */
/* Decode the message if necessary. */
H5O_LOAD_NATIVE(oloc_src->file, dxpl_id, 0, oh_src, mesg_src, FAIL)
+ /* Get destination message flags, and unset shared and shareable
+ * flags. mesg_dst->flags will contain the original flags for now.
+ */
+ mesg_flags = (unsigned)mesg_dst->flags & ~H5O_MSG_FLAG_SHARED
+ & ~H5O_MSG_FLAG_SHAREABLE;
+
/* Copy the source message */
recompute_size = FALSE;
- if((mesg_dst->native = H5O_msg_copy_file(copy_type,
- oloc_src->file, mesg_src->native, oloc_dst->file,
- &recompute_size, cpy_info, cpy_udata, dxpl_id)) == NULL)
+ if((mesg_dst->native = H5O_msg_copy_file(copy_type, oloc_src->file,
+ mesg_src->native, oloc_dst->file, &recompute_size,
+ &mesg_flags, cpy_info, cpy_udata, dxpl_id)) == NULL)
HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object header message")
- /* Check if new message is shared */
- if((is_shared = H5O_msg_is_shared(copy_type->id, mesg_dst->native)) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to query message's shared status")
-
- /* In being copied, the message may have become shared or stopped
- * being shared, set/unset its sharing flag.
+ /* Check if the sharing state changed, and recompute the size if so
*/
- if(is_shared && !(mesg_dst->flags & H5O_MSG_FLAG_SHARED)) {
- mesg_dst->flags |= H5O_MSG_FLAG_SHARED;
-
- /* Recompute message size (mesg_dst->native is really shared) */
- recompute_size = TRUE;
- } /* end if */
- else if(!is_shared && (mesg_dst->flags & H5O_MSG_FLAG_SHARED)) {
- mesg_dst->flags &= ~H5O_MSG_FLAG_SHARED;
-
- /* Recompute message size (msg_dest->native is no longer shared) */
+ if(!(mesg_flags & H5O_MSG_FLAG_SHARED)
+ != !(mesg_dst->flags & H5O_MSG_FLAG_SHARED))
recompute_size = TRUE;
- } /* end if */
+
+ /* Set destination message flags */
+ mesg_dst->flags = (uint8_t)mesg_flags;
/* Recompute message's size */
/* (its sharing status or one of its components (for attributes)
@@ -671,6 +771,13 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */,
oloc_dst->addr = addr_new;
+ /* If we are merging committed datatypes and this is a committed datatype, insert
+ * the copied datatype into the list of committed datatypes in the target file.
+ */
+ if(cpy_info->merge_comm_dt && obj_class->type == H5O_TYPE_NAMED_DATATYPE)
+ if(H5O_copy_insert_comm_dt(oloc_src->file, oh_src, oloc_dst, dxpl_id, cpy_info) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't insert committed datatype into destination list")
+
/* Allocate space for the address mapping of the object copied */
if(NULL == (addr_map = H5FL_MALLOC(H5O_addr_map_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
@@ -686,8 +793,10 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */,
addr_map->udata = cpy_udata;
/* Insert into skip list */
- if(H5SL_insert(cpy_info->map_list, addr_map, &(addr_map->src_obj_pos)) < 0)
+ if(H5SL_insert(cpy_info->map_list, addr_map, &(addr_map->src_obj_pos)) < 0) {
+ addr_map = H5FL_FREE(H5O_addr_map_t, addr_map);
HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "can't insert object into skip list")
+ } /* end if */
/* "post copy" loop over messages, to fix up any messages which require a complete
* object header for destination object
@@ -716,17 +825,26 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */,
HDassert(copy_type);
if(copy_type->post_copy_file && mesg_src->native) {
+ unsigned mesg_flags; /* Message flags */
+
/* Sanity check destination message */
HDassert(mesg_dst->type == mesg_src->type);
HDassert(mesg_dst->native);
+ /* Get destination message flags. mesg_dst->flags will contain the
+ * original flags for now. */
+ mesg_flags = (unsigned)mesg_dst->flags;
+
/* the object header is needed in the post copy for shared message */
cpy_info->oh_dst = oh_dst;
/* Perform "post copy" operation on message */
if((copy_type->post_copy_file)(oloc_src, mesg_src->native, oloc_dst,
- mesg_dst->native, dxpl_id, cpy_info) < 0)
+ mesg_dst->native, &mesg_flags, dxpl_id, cpy_info) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to perform 'post copy' operation on message")
+
+ /* Verify that the flags did not change */
+ HDassert(mesg_flags == (unsigned) mesg_dst->flags);
} /* end if */
} /* end for */
@@ -797,9 +915,9 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5O_copy_header_map(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */,
+H5O_copy_header_map(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out*/,
hid_t dxpl_id, H5O_copy_t *cpy_info, hbool_t inc_depth,
- H5O_type_t *obj_type, void **udata)
+ H5O_type_t *obj_type, void **udata /*out*/)
{
H5O_addr_map_t *addr_map = NULL; /* Address mapping of object copied */
H5_obj_t src_obj_pos; /* Position of source object */
@@ -937,9 +1055,13 @@ H5O_copy_free_addrmap_cb(void *_item, void UNUSED *key, void UNUSED *op_data)
*/
static herr_t
H5O_copy_header(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */,
- hid_t dxpl_id, unsigned cpy_option)
+ hid_t dxpl_id, hid_t ocpypl_id)
{
H5O_copy_t cpy_info; /* Information for copying object */
+ H5P_genplist_t *ocpy_plist; /* Object copy property list created */
+ H5O_copy_dtype_merge_list_t *dt_list = NULL; /* List of datatype merge suggestions */
+ H5O_mcdt_cb_info_t cb_info; /* Callback info struct */
+ unsigned cpy_option = 0; /* Copy options */
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI_NOINIT
@@ -949,6 +1071,22 @@ H5O_copy_header(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */,
HDassert(H5F_addr_defined(oloc_src->addr));
HDassert(oloc_dst->file);
+ /* Get the copy property list */
+ if(NULL == (ocpy_plist = (H5P_genplist_t *)H5I_object(ocpypl_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
+
+ /* Retrieve the copy parameters */
+ if(H5P_get(ocpy_plist, H5O_CPY_OPTION_NAME, &cpy_option) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get object copy flag")
+
+ /* Retrieve the marge committed datatype list */
+ if(H5P_get(ocpy_plist, H5O_CPY_MERGE_COMM_DT_LIST_NAME, &dt_list) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get merge committed datatype list")
+
+ /* Get callback info */
+ if(H5P_get(ocpy_plist, H5O_CPY_MCDT_SEARCH_CB_NAME, &cb_info) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get callback info")
+
/* Convert copy flags into copy struct */
HDmemset(&cpy_info, 0, sizeof(H5O_copy_t));
if((cpy_option & H5O_COPY_SHALLOW_HIERARCHY_FLAG) > 0) {
@@ -968,9 +1106,18 @@ H5O_copy_header(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */,
cpy_info.copy_without_attr = TRUE;
if((cpy_option & H5O_COPY_PRESERVE_NULL_FLAG) > 0)
cpy_info.preserve_null = TRUE;
+ if((cpy_option & H5O_COPY_MERGE_COMMITTED_DTYPE_FLAG) > 0)
+ cpy_info.merge_comm_dt = TRUE;
+
+ /* Add dt_list to copy struct */
+ cpy_info.dst_dt_suggestion_list = dt_list;
+
+ /* Add set callback information */
+ cpy_info.mcdt_cb = cb_info.func;
+ cpy_info.mcdt_ud = cb_info.user_data;
/* Create a skip list to keep track of which objects are copied */
- if((cpy_info.map_list = H5SL_create(H5SL_TYPE_OBJ, NULL)) == NULL)
+ if(NULL == (cpy_info.map_list = H5SL_create(H5SL_TYPE_OBJ, NULL)))
HGOTO_ERROR(H5E_SLIST, H5E_CANTCREATE, FAIL, "cannot make skip list")
/* copy the object from the source file to the destination file */
@@ -980,6 +1127,8 @@ H5O_copy_header(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */,
done:
if(cpy_info.map_list)
H5SL_destroy(cpy_info.map_list, H5O_copy_free_addrmap_cb, NULL);
+ if(cpy_info.dst_dt_list)
+ H5SL_destroy(cpy_info.dst_dt_list, H5O_copy_free_comm_dt_cb, NULL);
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_copy_header() */
@@ -1001,14 +1150,12 @@ static herr_t
H5O_copy_obj(H5G_loc_t *src_loc, H5G_loc_t *dst_loc, const char *dst_name,
hid_t ocpypl_id, hid_t lcpl_id)
{
- H5P_genplist_t *ocpy_plist=NULL; /* Object copy property list created */
- hid_t dxpl_id=H5AC_dxpl_id;
H5G_name_t new_path; /* Copied object group hier. path */
H5O_loc_t new_oloc; /* Copied object object location */
H5G_loc_t new_loc; /* Group location of object copied */
H5F_t *cached_dst_file; /* Cached destination file */
- hbool_t entry_inserted=FALSE; /* Flag to indicate that the new entry was inserted into a group */
- unsigned cpy_option = 0; /* Copy options */
+ hbool_t entry_inserted = FALSE; /* Flag to indicate that the new entry was inserted into a group */
+ hid_t dxpl_id = H5AC_dxpl_id; /* DXPL for operation */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
@@ -1019,14 +1166,6 @@ H5O_copy_obj(H5G_loc_t *src_loc, H5G_loc_t *dst_loc, const char *dst_name,
HDassert(dst_loc->oloc->file);
HDassert(dst_name);
- /* Get the copy property list */
- if(NULL == (ocpy_plist = (H5P_genplist_t *)H5I_object(ocpypl_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
-
- /* Retrieve the copy parameters */
- if(H5P_get(ocpy_plist, H5O_CPY_OPTION_NAME, &cpy_option) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get object copy flag")
-
/* Set up copied object location to fill in */
new_loc.oloc = &new_oloc;
new_loc.path = &new_path;
@@ -1039,7 +1178,7 @@ H5O_copy_obj(H5G_loc_t *src_loc, H5G_loc_t *dst_loc, const char *dst_name,
cached_dst_file = dst_loc->oloc->file;
/* Copy the object from the source file to the destination file */
- if(H5O_copy_header(src_loc->oloc, &new_oloc, dxpl_id, cpy_option) < 0)
+ if(H5O_copy_header(src_loc->oloc, &new_oloc, dxpl_id, ocpypl_id) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object")
/* Patch dst_loc. Again, this can be removed once oloc's point to shared
@@ -1255,3 +1394,579 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_copy_expand_ref() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_copy_free_comm_dt_cb
+ *
+ * Purpose: Frees the merge committed dt skip list key and object.
+ *
+ * Return: SUCCEED (never fails)
+ *
+ * Programmer: Neil Fortner
+ * Oct 6 2011
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O_copy_free_comm_dt_cb(void *item, void *_key, void UNUSED *op_data)
+{
+ haddr_t *addr = (haddr_t *)item;
+ H5O_copy_search_comm_dt_key_t *key = (H5O_copy_search_comm_dt_key_t *)_key;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ HDassert(addr);
+ HDassert(key);
+ HDassert(key->dt);
+
+ key->dt = (H5T_t *)H5O_msg_free(H5O_DTYPE_ID, key->dt);
+ key = H5FL_FREE(H5O_copy_search_comm_dt_key_t, key);
+ addr = H5FL_FREE(haddr_t, addr);
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5O_copy_free_comm_dt_cb */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_copy_comm_dt_cmp
+ *
+ * Purpose: Skiplist callback used to compare 2 keys for the merge
+ * committed dt list. Mostly a wrapper for H5T_cmp.
+ *
+ * Return: 0 if key1 and key2 are equal.
+ * <0 if key1 is less than key2.
+ * >0 if key1 is greater than key2.
+ *
+ * Programmer: Neil Fortner
+ * Oct 6 2011
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+H5O_copy_comm_dt_cmp(const void *_key1, const void *_key2)
+{
+ const H5O_copy_search_comm_dt_key_t *key1 = (const H5O_copy_search_comm_dt_key_t *)_key1;
+ const H5O_copy_search_comm_dt_key_t *key2 = (const H5O_copy_search_comm_dt_key_t *)_key2;
+ int ret_value = 0;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ /* Check fileno. It is unlikely to be different so check if they are equal
+ * first so only one comparison needs to be made. */
+ if(key1->fileno != key2->fileno) {
+ if(key1->fileno < key2->fileno)
+ HGOTO_DONE(-1)
+ if(key1->fileno > key2->fileno)
+ HGOTO_DONE(1)
+ } /* end if */
+
+ ret_value = H5T_cmp(key1->dt, key2->dt, FALSE);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_copy_comm_dt_cmp */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_copy_search_comm_dt_attr_cb
+ *
+ * Purpose: Callback for H5O_attr_iterate_real from
+ * H5O_copy_search_comm_dt_check. Checks if the attribute's
+ * datatype is committed. If it is, adds it to the merge
+ * committed dt skiplist present in udata if it does not match
+ * any already present.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Neil Fortner
+ * Nov 3 2011
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O_copy_search_comm_dt_attr_cb(const H5A_t *attr, void *_udata)
+{
+ H5O_copy_search_comm_dt_ud_t *udata = (H5O_copy_search_comm_dt_ud_t *)_udata;
+ H5T_t *dt = NULL; /* Datatype */
+ H5O_copy_search_comm_dt_key_t *key = NULL; /* Skiplist key */
+ haddr_t *addr = NULL; /* Destination address */
+ hbool_t obj_inserted = FALSE; /* Object inserted into skip list */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ /* Sanity checks */
+ HDassert(attr);
+ HDassert(udata);
+ HDassert(udata->dst_dt_list);
+ HDassert(H5F_addr_defined(udata->obj_oloc.addr));
+
+ /* Get attribute datatype */
+ if(NULL == (dt = H5A_type(attr)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't get attribute datatype")
+
+ /* Check if the datatype is committed and search the skip list if so */
+ if(H5T_committed(dt)) {
+ /* Allocate key */
+ if(NULL == (key = H5FL_MALLOC(H5O_copy_search_comm_dt_key_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+
+ /* Copy datatype into key */
+ if(NULL == (key->dt = (H5T_t *)H5O_msg_copy(H5O_DTYPE_ID, dt, NULL)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to copy datatype message")
+
+ /* Get datatype object fileno */
+ H5F_GET_FILENO(udata->obj_oloc.file, key->fileno);
+
+ if(!H5SL_search(udata->dst_dt_list, key)) {
+ /* Allocate destination address */
+ if(NULL == (addr = H5FL_MALLOC(haddr_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+
+ /* Add the destination datatype to the skip list */
+ *addr = ((H5O_shared_t *)(key->dt))->u.loc.oh_addr;
+ if(H5SL_insert(udata->dst_dt_list, addr, key) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "can't insert object into skip list")
+ obj_inserted = TRUE;
+ } /* end if */
+ } /* end if */
+
+done:
+ /* Release resources */
+ if(!obj_inserted) {
+ if(key) {
+ if(key->dt)
+ key->dt = (H5T_t *)H5O_msg_free(H5O_DTYPE_ID, key->dt);
+ key = H5FL_FREE(H5O_copy_search_comm_dt_key_t, key);
+ } /* end if */
+ if(addr) {
+ HDassert(ret_value < 0);
+ addr = H5FL_FREE(haddr_t, addr);
+ } /* end if */
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_copy_search_comm_dt_attr_cb */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_copy_search_comm_dt_check
+ *
+ * Purpose: Check if the object at obj_oloc is or contains a reference
+ * to a committed datatype. If it does, adds it to the merge
+ * committed dt skiplist present in udata if it does not match
+ * any already present.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Neil Fortner
+ * Nov 3 2011
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O_copy_search_comm_dt_check(H5O_loc_t *obj_oloc,
+ H5O_copy_search_comm_dt_ud_t *udata)
+{
+ H5O_copy_search_comm_dt_key_t *key = NULL; /* Skiplist key */
+ haddr_t *addr = NULL; /* Destination address */
+ hbool_t obj_inserted = FALSE; /* Object inserted into skip list */
+ H5O_info_t oinfo; /* Object info */
+ H5A_attr_iter_op_t attr_op; /* Attribute iteration operator */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ /* Sanity checks */
+ HDassert(obj_oloc);
+ HDassert(udata);
+ HDassert(udata->dst_dt_list);
+ HDassert(udata->dst_root_loc);
+
+ /* Get the object's info */
+ if(H5O_get_info(obj_oloc, udata->dxpl_id, TRUE, &oinfo) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to get object info")
+
+ /* Check if the object is a datatype, a dataset using a committed
+ * datatype, or contains an attribute using a committed datatype */
+ if(oinfo.type == H5O_TYPE_NAMED_DATATYPE) {
+ /* Allocate key */
+ if(NULL == (key = H5FL_MALLOC(H5O_copy_search_comm_dt_key_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+
+ /* Read the destination datatype */
+ if(NULL == (key->dt = (H5T_t *)H5O_msg_read(obj_oloc, H5O_DTYPE_ID, NULL, udata->dxpl_id)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't read DTYPE message")
+
+ /* Get destination object fileno */
+ H5F_GET_FILENO(obj_oloc->file, key->fileno);
+
+ /* Check if the datatype is already present in the skip list */
+ if(!H5SL_search(udata->dst_dt_list, key)) {
+ /* Allocate destination address */
+ if(NULL == (addr = H5FL_MALLOC(haddr_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+
+ /* Add the destination datatype to the skip list */
+ *addr = obj_oloc->addr;
+ if(H5SL_insert(udata->dst_dt_list, addr, key) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "can't insert object into skip list")
+ obj_inserted = TRUE;
+ } /* end if */
+ } /* end if */
+ else if(oinfo.type == H5O_TYPE_DATASET) {
+ /* Allocate key */
+ if(NULL == (key = H5FL_MALLOC(H5O_copy_search_comm_dt_key_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+
+ /* Read the destination datatype */
+ if(NULL == (key->dt = (H5T_t *)H5O_msg_read(obj_oloc, H5O_DTYPE_ID, NULL, udata->dxpl_id)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't read DTYPE message")
+
+ /* Check if the datatype is committed and search the skip list if so
+ */
+ if(H5T_committed(key->dt)) {
+ /* Get datatype object fileno */
+ H5F_GET_FILENO(obj_oloc->file, key->fileno);
+
+ if(!H5SL_search(udata->dst_dt_list, key)) {
+ /* Allocate destination address */
+ if(NULL == (addr = H5FL_MALLOC(haddr_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+
+ /* Add the destination datatype to the skip list */
+ *addr = ((H5O_shared_t *)(key->dt))->u.loc.oh_addr;
+ if(H5SL_insert(udata->dst_dt_list, addr, key) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "can't insert object into skip list")
+ obj_inserted = TRUE;
+ } /* end if */
+ } /* end if */
+ } /* end else */
+
+ /* Search within attributes */
+ attr_op.op_type = H5A_ATTR_OP_LIB;
+ attr_op.u.lib_op = H5O_copy_search_comm_dt_attr_cb;
+ udata->obj_oloc.file = obj_oloc->file;
+ udata->obj_oloc.addr = obj_oloc->addr;
+ if(H5O_attr_iterate_real((hid_t)-1, obj_oloc, udata->dxpl_id, H5_INDEX_NAME, H5_ITER_NATIVE, 0, NULL, &attr_op, udata) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_BADITER, FAIL, "error iterating over attributes");
+
+done:
+ /* Release resources */
+ if(!obj_inserted) {
+ if(key) {
+ if(key->dt)
+ key->dt = (H5T_t *)H5O_msg_free(H5O_DTYPE_ID, key->dt);
+ key = H5FL_FREE(H5O_copy_search_comm_dt_key_t, key);
+ } /* end if */
+ if(addr) {
+ HDassert(ret_value < 0);
+ addr = H5FL_FREE(haddr_t, addr);
+ } /* end if */
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_copy_search_comm_dt_check */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_copy_search_comm_dt_cb
+ *
+ * Purpose: H5G_visit callback to add committed datatypes to the merge
+ * committed dt skiplist. Mostly a wrapper for
+ * H5O_copy_search_comm_dt_check.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Neil Fortner
+ * Oct 6 2011
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O_copy_search_comm_dt_cb(hid_t UNUSED group, const char *name,
+ const H5L_info_t *linfo, void *_udata)
+{
+ H5O_copy_search_comm_dt_ud_t *udata = (H5O_copy_search_comm_dt_ud_t *)_udata; /* Skip list of dtypes in dest file */
+ H5G_loc_t obj_loc; /* Location of object */
+ H5O_loc_t obj_oloc; /* Object's object location */
+ H5G_name_t obj_path; /* Object's group hier. path */
+ hbool_t obj_found = FALSE; /* Object at 'name' found */
+ herr_t ret_value = H5_ITER_CONT; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ /* Sanity checks */
+ HDassert(name);
+ HDassert(linfo);
+ HDassert(udata);
+ HDassert(udata->dst_dt_list);
+ HDassert(udata->dst_root_loc);
+
+ /* Check if this is a hard link */
+ if(linfo->type == H5L_TYPE_HARD) {
+ /* Set up opened group location to fill in */
+ obj_loc.oloc = &obj_oloc;
+ obj_loc.path = &obj_path;
+ H5G_loc_reset(&obj_loc);
+
+ /* Find the object */
+ if(H5G_loc_find(udata->dst_root_loc, name, &obj_loc/*out*/, H5P_LINK_ACCESS_DEFAULT, udata->dxpl_id) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, H5_ITER_ERROR, "object not found")
+ obj_found = TRUE;
+
+ /* Check object and add to skip list if appropriate */
+ if(H5O_copy_search_comm_dt_check(&obj_oloc, udata) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, H5_ITER_ERROR, "can't check object")
+ } /* end if */
+
+done:
+ /* Release resources */
+ if(obj_found && H5G_loc_free(&obj_loc) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, H5_ITER_ERROR, "can't free location")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_copy_search_comm_dt_cb */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_copy_search_comm_dt
+ *
+ * Purpose: Checks if the committed datatype present in oh_src matches any
+ * in the destination file, building the destination file
+ * skiplist as necessary.
+ *
+ * Return: TRUE if a match is found in the destination file
+ * - oloc_dst will contain the address
+ * FALSE if a match is not found
+ * Negative on failure
+ *
+ * Programmer: Neil Fortner
+ * Sep 27 2011
+ *
+ *-------------------------------------------------------------------------
+ */
+static htri_t
+H5O_copy_search_comm_dt(H5F_t *file_src, H5O_t *oh_src,
+ H5O_loc_t *oloc_dst/*in, out*/, hid_t dxpl_id, H5O_copy_t *cpy_info)
+{
+ H5O_copy_search_comm_dt_key_t *key = NULL; /* Skiplist key */
+ haddr_t *dst_addr; /* Destination datatype address */
+ H5G_loc_t dst_root_loc = {NULL, NULL}; /* Destination root group location */
+ H5O_copy_search_comm_dt_ud_t udata; /* Group iteration user data */
+ herr_t ret_value = FALSE; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ /* Sanity checks */
+ HDassert(oh_src);
+ HDassert(oloc_dst);
+ HDassert(oloc_dst->file);
+ HDassert(H5F_FILE_ID(oloc_dst->file) >= 0);
+ HDassert(cpy_info);
+
+ /* Allocate key */
+ if(NULL == (key = H5FL_MALLOC(H5O_copy_search_comm_dt_key_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+
+ /* Read the source datatype */
+ if(NULL == (key->dt = (H5T_t *)H5O_msg_read_oh(file_src, dxpl_id, oh_src, H5O_DTYPE_ID, NULL)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't read DTYPE message")
+
+ /* Get destination object fileno */
+ H5F_GET_FILENO(oloc_dst->file, key->fileno);
+
+ /* Check if the destination dtype list exists, create it if it does not */
+ if(!cpy_info->dst_dt_list) {
+ /* Create the skip list */
+ if(NULL == (cpy_info->dst_dt_list = H5SL_create(H5SL_TYPE_GENERIC, H5O_copy_comm_dt_cmp)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTCREATE, FAIL, "can't create skip list for committed datatypes")
+
+ /* Add suggested types to list, if they are present */
+ if(cpy_info->dst_dt_suggestion_list) {
+ H5O_copy_dtype_merge_list_t *suggestion = cpy_info->dst_dt_suggestion_list;
+ H5G_loc_t obj_loc; /* Location of object */
+ H5O_loc_t obj_oloc; /* Object's object location */
+ H5G_name_t obj_path; /* Object's group hier. path */
+
+ /* Set up the root group in the destination file */
+ if(NULL == (dst_root_loc.oloc = H5G_oloc(H5G_rootof(oloc_dst->file))))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get object location for root group")
+ if(NULL == (dst_root_loc.path = H5G_nameof(H5G_rootof(oloc_dst->file))))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get path for root group")
+
+ /* Set up opened group location to fill in */
+ obj_loc.oloc = &obj_oloc;
+ obj_loc.path = &obj_path;
+ H5G_loc_reset(&obj_loc);
+
+ /* Build udata */
+ udata.dst_dt_list = cpy_info->dst_dt_list;
+ udata.dst_root_loc = &dst_root_loc;
+ udata.obj_oloc.file = NULL;
+ udata.obj_oloc.addr = HADDR_UNDEF;
+ udata.dxpl_id = dxpl_id;
+
+ /* Walk through the list of datatype suggestions */
+ while(suggestion) {
+ /* Find the object */
+ if(H5G_loc_find(&dst_root_loc, suggestion->path, &obj_loc/*out*/, H5P_LINK_ACCESS_DEFAULT, dxpl_id) < 0)
+ /* Ignore errors - i.e. suggestions not present in
+ * destination file */
+ H5E_clear_stack(NULL);
+ else
+ /* Check object and add to skip list if appropriate */
+ if(H5O_copy_search_comm_dt_check(&obj_oloc, &udata) < 0) {
+ if(H5G_loc_free(&obj_loc) < 0)
+ HERROR(H5E_OHDR, H5E_CANTRELEASE, "can't free location");
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't check object")
+ } /* end if */
+
+ /* Free location */
+ if(H5G_loc_free(&obj_loc) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "can't free location");
+
+ /* Advance the suggestion pointer */
+ suggestion = suggestion->next;
+ } /* end while */
+ } /* end if */
+ }
+
+ if(!cpy_info->dst_dt_list_complete) {
+ /* Search for the type in the destination file, and return its address
+ * if found, but only if the list is populated with and only with
+ * suggested types. We will search complete lists later. */
+ if(cpy_info->dst_dt_suggestion_list
+ && NULL != (dst_addr = (haddr_t *)H5SL_search(
+ cpy_info->dst_dt_list, key))) {
+ oloc_dst->addr = *dst_addr;
+ ret_value = TRUE;
+ } /* end if */
+ else {
+ H5O_mcdt_search_ret_t search_cb_ret = H5O_MCDT_SEARCH_CONT;
+
+ /* Make callback to see if we should search destination file */
+ if(cpy_info->mcdt_cb)
+ if((search_cb_ret = cpy_info->mcdt_cb(cpy_info->mcdt_ud)) == H5O_MCDT_SEARCH_ERROR)
+ HGOTO_ERROR(H5E_OHDR, H5E_CALLBACK, FAIL, "callback returned error")
+
+ if(search_cb_ret == H5O_MCDT_SEARCH_CONT) {
+ /* Build the complete dst dt list */
+ /* Set up the root group in the destination file, if necessary */
+ if(!dst_root_loc.oloc) {
+ HDassert(!dst_root_loc.path);
+ if(NULL == (dst_root_loc.oloc = H5G_oloc(H5G_rootof(oloc_dst->file))))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get object location for root group")
+ if(NULL == (dst_root_loc.path = H5G_nameof(H5G_rootof(oloc_dst->file))))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get path for root group")
+ } /* end if */
+ else
+ HDassert(dst_root_loc.path);
+
+ /* Build udata. Note that this may be done twice in some cases, but
+ * it should be rare and should be cheaper on average than trying to
+ * keep track of whether it was done before. */
+ udata.dst_dt_list = cpy_info->dst_dt_list;
+ udata.dst_root_loc = &dst_root_loc;
+ udata.obj_oloc.file = NULL;
+ udata.obj_oloc.addr = HADDR_UNDEF;
+ udata.dxpl_id = dxpl_id;
+
+ /* Traverse the destination file, adding committed datatypes to the skip
+ * list */
+ if(H5G_visit(H5F_FILE_ID(oloc_dst->file), "/", H5_INDEX_NAME, H5_ITER_NATIVE, H5O_copy_search_comm_dt_cb, &udata, H5P_LINK_ACCESS_DEFAULT, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_BADITER, FAIL, "object visitation failed")
+ cpy_info->dst_dt_list_complete = TRUE;
+ } /* end if */
+ else
+ if(search_cb_ret != H5O_MCDT_SEARCH_STOP)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unknown return value for callback")
+ } /* end if */
+ } /* end if */
+
+ /* Search for the type in the destination file, and return its address if
+ * found, but only if the list is complete */
+ if(cpy_info->dst_dt_list_complete) {
+ if(NULL != (dst_addr = (haddr_t *)H5SL_search(cpy_info->dst_dt_list, key))) {
+ oloc_dst->addr = *dst_addr;
+ ret_value = TRUE;
+ } /* end if */
+ } /* end if */
+
+done:
+ if(key) {
+ if(key->dt)
+ key->dt = (H5T_t *)H5O_msg_free(H5O_DTYPE_ID, key->dt);
+ key = H5FL_FREE(H5O_copy_search_comm_dt_key_t, key);
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_copy_search_comm_dt */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_copy_insert_comm_dt
+ *
+ * Purpose: Insert the committed datatype at oloc_dst into the merge committed
+ * dt skiplist. The datatype must not be present already.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Neil Fortner
+ * Oct 6 2011
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O_copy_insert_comm_dt(H5F_t *file_src, H5O_t *oh_src, H5O_loc_t *oloc_dst,
+ hid_t dxpl_id, H5O_copy_t *cpy_info)
+{
+ H5O_copy_search_comm_dt_key_t *key = NULL; /* Skiplist key */
+ haddr_t *addr = NULL; /* Destination object address */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ /* Sanity checks */
+ HDassert(oh_src);
+ HDassert(oloc_dst);
+ HDassert(oloc_dst->file);
+ HDassert(oloc_dst->addr != HADDR_UNDEF);
+ HDassert(cpy_info);
+ HDassert(cpy_info->dst_dt_list);
+
+ /* Allocate key */
+ if(NULL == (key = H5FL_MALLOC(H5O_copy_search_comm_dt_key_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+
+ /* Read the datatype. Read from the source file because the destination
+ * object could be changed in the post-copy. */
+ if(NULL == (key->dt = (H5T_t *)H5O_msg_read_oh(file_src, dxpl_id, oh_src, H5O_DTYPE_ID, NULL)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't read DTYPE message")
+
+ /* Get destination object fileno */
+ H5F_GET_FILENO(oloc_dst->file, key->fileno);
+
+ /* Allocate destination address */
+ if(NULL == (addr = H5FL_MALLOC(haddr_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+
+ /* Add the destination datatype to the skip list */
+ *addr = oloc_dst->addr;
+ if(H5SL_insert(cpy_info->dst_dt_list, addr, key) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "can't insert object into skip list")
+
+done:
+ if(ret_value < 0) {
+ if(key) {
+ if(key->dt)
+ key->dt = (H5T_t *)H5O_msg_free(H5O_DTYPE_ID, key->dt);
+ key = H5FL_FREE(H5O_copy_search_comm_dt_key_t, key);
+ } /* end if */
+ if(addr)
+ addr = H5FL_FREE(haddr_t, addr);
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_copy_insert_comm_dt */
+
diff --git a/src/H5Odtype.c b/src/H5Odtype.c
index 9ccb51b..1b602c7 100644
--- a/src/H5Odtype.c
+++ b/src/H5Odtype.c
@@ -43,6 +43,9 @@ static herr_t H5O_dtype_pre_copy_file(H5F_t *file_src, const void *mesg_src,
static void *H5O_dtype_copy_file(H5F_t *file_src, const H5O_msg_class_t *mesg_type,
void *native_src, H5F_t *file_dst, hbool_t *recompute_size,
H5O_copy_t *cpy_info, void *udata, hid_t dxpl_id);
+static herr_t H5O_dtype_shared_post_copy_upd(const H5O_loc_t *src_oloc,
+ const void *mesg_src, H5O_loc_t *dst_oloc, void *mesg_dst, hid_t dxpl_id,
+ H5O_copy_t *cpy_info);
static herr_t H5O_dtype_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg,
FILE * stream, int indent, int fwidth);
@@ -63,6 +66,7 @@ static herr_t H5O_dtype_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg,
#define H5O_SHARED_COPY_FILE_REAL H5O_dtype_copy_file
#define H5O_SHARED_POST_COPY_FILE H5O_dtype_shared_post_copy_file
#undef H5O_SHARED_POST_COPY_FILE_REAL
+#define H5O_SHARED_POST_COPY_FILE_UPD H5O_dtype_shared_post_copy_upd
#define H5O_SHARED_DEBUG H5O_dtype_shared_debug
#define H5O_SHARED_DEBUG_REAL H5O_dtype_debug
#include "H5Oshared.h" /* Shared Object Header Message Callbacks */
@@ -1575,6 +1579,40 @@ done:
} /* end H5O_dtype_copy_file() */
+/*-------------------------------------------------------------------------
+ * Function: H5O_dtype_shared_post_copy_upd
+ *
+ * Purpose: Update a message after the shared message operations
+ * during the post-copy loop
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Neil Fortner
+ * November 8, 2011
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O_dtype_shared_post_copy_upd(const H5O_loc_t UNUSED *src_oloc,
+ const void UNUSED *mesg_src, H5O_loc_t UNUSED *dst_oloc, void *mesg_dst,
+ hid_t UNUSED dxpl_id, H5O_copy_t UNUSED *cpy_info)
+{
+ H5T_t *dt_dst = (H5T_t *)mesg_dst; /* Destination datatype */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ if(dt_dst->sh_loc.type == H5O_SHARE_TYPE_COMMITTED) {
+ HDassert(H5T_committed(dt_dst));
+ dt_dst->oloc.file = dt_dst->sh_loc.file;
+ dt_dst->oloc.addr = dt_dst->sh_loc.u.loc.oh_addr;
+ } /* end if */
+ else
+ HDassert(!H5T_committed(dt_dst));
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5O_dtype_shared_post_copy_upd */
+
+
/*--------------------------------------------------------------------------
NAME
H5O_dtype_debug
diff --git a/src/H5Oefl.c b/src/H5Oefl.c
index e4b21f0..3630cf4 100644
--- a/src/H5Oefl.c
+++ b/src/H5Oefl.c
@@ -36,8 +36,8 @@ static void *H5O_efl_copy(const void *_mesg, void *_dest);
static size_t H5O_efl_size(const H5F_t *f, hbool_t disable_shared, const void *_mesg);
static herr_t H5O_efl_reset(void *_mesg);
static void *H5O_efl_copy_file(H5F_t *file_src, void *mesg_src,
- H5F_t *file_dst, hbool_t *recompute_size, H5O_copy_t *cpy_info,
- void *udata, hid_t dxpl_id);
+ H5F_t *file_dst, hbool_t *recompute_size, unsigned *mesg_flags,
+ H5O_copy_t *cpy_info, void *udata, hid_t dxpl_id);
static herr_t H5O_efl_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE * stream,
int indent, int fwidth);
@@ -455,8 +455,8 @@ done:
*/
static void *
H5O_efl_copy_file(H5F_t UNUSED *file_src, void *mesg_src, H5F_t *file_dst,
- hbool_t UNUSED *recompute_size, H5O_copy_t UNUSED *cpy_info,
- void UNUSED *_udata, hid_t dxpl_id)
+ hbool_t UNUSED *recompute_size, unsigned UNUSED *mesg_flags,
+ H5O_copy_t UNUSED *cpy_info, void UNUSED *_udata, hid_t dxpl_id)
{
H5O_efl_t *efl_src = (H5O_efl_t *) mesg_src;
H5O_efl_t *efl_dst = NULL;
diff --git a/src/H5Ofill.c b/src/H5Ofill.c
index 9fa6108..f5569dc 100644
--- a/src/H5Ofill.c
+++ b/src/H5Ofill.c
@@ -63,6 +63,7 @@ static herr_t H5O_fill_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE *s
#undef H5O_SHARED_COPY_FILE_REAL
#define H5O_SHARED_POST_COPY_FILE H5O_fill_shared_post_copy_file
#undef H5O_SHARED_POST_COPY_FILE_REAL
+#undef H5O_SHARED_POST_COPY_FILE_UPD
#define H5O_SHARED_DEBUG H5O_fill_shared_debug
#define H5O_SHARED_DEBUG_REAL H5O_fill_debug
#include "H5Oshared.h" /* Shared Object Header Message Callbacks */
@@ -95,6 +96,7 @@ static herr_t H5O_fill_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE *s
#undef H5O_SHARED_POST_COPY_FILE
#define H5O_SHARED_POST_COPY_FILE H5O_fill_new_shared_post_copy_file
#undef H5O_SHARED_POST_COPY_FILE_REAL
+#undef H5O_SHARED_POST_COPY_FILE_UPD
#undef H5O_SHARED_DEBUG
#define H5O_SHARED_DEBUG H5O_fill_new_shared_debug
#undef H5O_SHARED_DEBUG_REAL
diff --git a/src/H5Olayout.c b/src/H5Olayout.c
index 1b17bff..e912d8c 100644
--- a/src/H5Olayout.c
+++ b/src/H5Olayout.c
@@ -46,8 +46,8 @@ static herr_t H5O_layout_free(void *_mesg);
static herr_t H5O_layout_delete(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
void *_mesg);
static void *H5O_layout_copy_file(H5F_t *file_src, void *mesg_src,
- H5F_t *file_dst, hbool_t *recompute_size, H5O_copy_t *cpy_info,
- void *udata, hid_t dxpl_id);
+ H5F_t *file_dst, hbool_t *recompute_size, unsigned *mesg_flags,
+ H5O_copy_t *cpy_info, void *udata, hid_t dxpl_id);
static herr_t H5O_layout_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE * stream,
int indent, int fwidth);
@@ -587,8 +587,8 @@ done:
*/
static void *
H5O_layout_copy_file(H5F_t *file_src, void *mesg_src, H5F_t *file_dst,
- hbool_t UNUSED *recompute_size, H5O_copy_t *cpy_info, void *_udata,
- hid_t dxpl_id)
+ hbool_t UNUSED *recompute_size, unsigned UNUSED *mesg_flags,
+ H5O_copy_t *cpy_info, void *_udata, hid_t dxpl_id)
{
H5D_copy_file_ud_t *udata = (H5D_copy_file_ud_t *)_udata; /* Dataset copying user data */
H5O_layout_t *layout_src = (H5O_layout_t *) mesg_src;
diff --git a/src/H5Olinfo.c b/src/H5Olinfo.c
index acdd1e1..e96483a 100644
--- a/src/H5Olinfo.c
+++ b/src/H5Olinfo.c
@@ -46,10 +46,11 @@ static herr_t H5O_linfo_free(void *_mesg);
static herr_t H5O_linfo_delete(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
void *_mesg);
static void *H5O_linfo_copy_file(H5F_t *file_src, void *native_src,
- H5F_t *file_dst, hbool_t *recompute_size, H5O_copy_t *cpy_info,
- void *udata, hid_t dxpl_id);
-static herr_t H5O_linfo_post_copy_file(const H5O_loc_t *parent_src_oloc, const void *mesg_src, H5O_loc_t *dst_oloc,
- void *mesg_dst, hid_t dxpl_id, H5O_copy_t *cpy_info);
+ H5F_t *file_dst, hbool_t *recompute_size, unsigned *mesg_flags,
+ H5O_copy_t *cpy_info, void *udata, hid_t dxpl_id);
+static herr_t H5O_linfo_post_copy_file(const H5O_loc_t *parent_src_oloc,
+ const void *mesg_src, H5O_loc_t *dst_oloc, void *mesg_dst,
+ unsigned *mesg_flags, hid_t dxpl_id, H5O_copy_t *cpy_info);
static herr_t H5O_linfo_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg,
FILE * stream, int indent, int fwidth);
@@ -379,8 +380,8 @@ done:
*/
static void *
H5O_linfo_copy_file(H5F_t UNUSED *file_src, void *native_src, H5F_t *file_dst,
- hbool_t UNUSED *recompute_size, H5O_copy_t *cpy_info, void *_udata,
- hid_t dxpl_id)
+ hbool_t UNUSED *recompute_size, unsigned UNUSED *mesg_flags,
+ H5O_copy_t *cpy_info, void *_udata, hid_t dxpl_id)
{
H5O_linfo_t *linfo_src = (H5O_linfo_t *) native_src;
H5O_linfo_t *linfo_dst = NULL;
@@ -501,7 +502,8 @@ done:
*/
static herr_t
H5O_linfo_post_copy_file(const H5O_loc_t *src_oloc, const void *mesg_src,
- H5O_loc_t *dst_oloc, void *mesg_dst, hid_t dxpl_id, H5O_copy_t *cpy_info)
+ H5O_loc_t *dst_oloc, void *mesg_dst, unsigned UNUSED *mesg_flags,
+ hid_t dxpl_id, H5O_copy_t *cpy_info)
{
const H5O_linfo_t *linfo_src = (const H5O_linfo_t *)mesg_src;
H5O_linfo_t *linfo_dst = (H5O_linfo_t *)mesg_dst;
diff --git a/src/H5Olink.c b/src/H5Olink.c
index a374807..12171b2 100644
--- a/src/H5Olink.c
+++ b/src/H5Olink.c
@@ -49,10 +49,11 @@ static herr_t H5O_link_free(void *_mesg);
static herr_t H5O_link_pre_copy_file(H5F_t *file_src, const void *mesg_src,
hbool_t *deleted, const H5O_copy_t *cpy_info, void *udata);
static void *H5O_link_copy_file(H5F_t *file_src, void *native_src,
- H5F_t *file_dst, hbool_t *recompute_size, H5O_copy_t *cpy_info, void *udata,
- hid_t dxpl_id);
-static herr_t H5O_link_post_copy_file(const H5O_loc_t *src_oloc, const void *mesg_src, H5O_loc_t *dst_oloc,
- void *mesg_dst, hid_t dxpl_id, H5O_copy_t *cpy_info);
+ H5F_t *file_dst, hbool_t *recompute_size, unsigned *mesg_flags,
+ H5O_copy_t *cpy_info, void *udata, hid_t dxpl_id);
+static herr_t H5O_link_post_copy_file(const H5O_loc_t *src_oloc,
+ const void *mesg_src, H5O_loc_t *dst_oloc, void *mesg_dst,
+ unsigned *mesg_flags, hid_t dxpl_id, H5O_copy_t *cpy_info);
static herr_t H5O_link_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg,
FILE * stream, int indent, int fwidth);
@@ -717,8 +718,8 @@ H5O_link_pre_copy_file(H5F_t UNUSED *file_src, const void UNUSED *native_src,
*/
static void *
H5O_link_copy_file(H5F_t UNUSED *file_src, void *native_src, H5F_t UNUSED *file_dst,
- hbool_t UNUSED *recompute_size, H5O_copy_t UNUSED *cpy_info, void UNUSED *udata,
- hid_t UNUSED dxpl_id)
+ hbool_t UNUSED *recompute_size, unsigned UNUSED *mesg_flags,
+ H5O_copy_t UNUSED *cpy_info, void UNUSED *udata, hid_t UNUSED dxpl_id)
{
H5O_link_t *link_src = (H5O_link_t *)native_src;
void *ret_value; /* Return value */
@@ -758,7 +759,8 @@ done:
*/
static herr_t
H5O_link_post_copy_file(const H5O_loc_t *src_oloc, const void *mesg_src,
- H5O_loc_t *dst_oloc, void *mesg_dst, hid_t dxpl_id, H5O_copy_t *cpy_info)
+ H5O_loc_t *dst_oloc, void *mesg_dst, unsigned UNUSED *mesg_flags,
+ hid_t dxpl_id, H5O_copy_t *cpy_info)
{
const H5O_link_t *link_src = (const H5O_link_t *)mesg_src;
H5O_link_t *link_dst = (H5O_link_t *)mesg_dst;
diff --git a/src/H5Omessage.c b/src/H5Omessage.c
index f12c835..c9a0997 100644
--- a/src/H5Omessage.c
+++ b/src/H5Omessage.c
@@ -1855,7 +1855,7 @@ done:
void *
H5O_msg_copy_file(const H5O_msg_class_t *type, H5F_t *file_src,
void *native_src, H5F_t *file_dst, hbool_t *recompute_size,
- H5O_copy_t *cpy_info, void *udata, hid_t dxpl_id)
+ unsigned *mesg_flags, H5O_copy_t *cpy_info, void *udata, hid_t dxpl_id)
{
void *ret_value;
@@ -1873,7 +1873,7 @@ H5O_msg_copy_file(const H5O_msg_class_t *type, H5F_t *file_src,
/* The copy_file callback will return an H5O_shared_t only if the message
* to be copied is a committed datatype.
*/
- if(NULL == (ret_value = (type->copy_file)(file_src, native_src, file_dst, recompute_size, cpy_info, udata, dxpl_id)))
+ if(NULL == (ret_value = (type->copy_file)(file_src, native_src, file_dst, recompute_size, mesg_flags, cpy_info, udata, dxpl_id)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, NULL, "unable to copy object header message to file")
done:
@@ -1986,7 +1986,7 @@ H5O_copy_mesg(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned idx,
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to copy message to object header")
/* Update the message flags */
- idx_msg->flags = mesg_flags;
+ idx_msg->flags = (uint8_t)mesg_flags;
/* Mark the message as modified */
idx_msg->dirty = TRUE;
diff --git a/src/H5Opkg.h b/src/H5Opkg.h
index a5d01bd..d4cc3fb 100644
--- a/src/H5Opkg.h
+++ b/src/H5Opkg.h
@@ -234,8 +234,8 @@ struct H5O_msg_class_t {
herr_t (*set_share)(void*, const H5O_shared_t*); /* Set shared information */
htri_t (*can_share)(const void *); /* Is message allowed to be shared? */
herr_t (*pre_copy_file)(H5F_t *, const void *, hbool_t *, const H5O_copy_t *, void *); /*"pre copy" action when copying native value to file */
- void *(*copy_file)(H5F_t *, void *, H5F_t *, hbool_t *, H5O_copy_t *, void *, hid_t); /*copy native value to file */
- herr_t (*post_copy_file)(const H5O_loc_t *, const void *, H5O_loc_t *, void *, hid_t, H5O_copy_t *); /*"post copy" action when copying native value to file */
+ void *(*copy_file)(H5F_t *, void *, H5F_t *, hbool_t *, unsigned *, H5O_copy_t *, void *, hid_t); /*copy native value to file */
+ herr_t (*post_copy_file)(const H5O_loc_t *, const void *, H5O_loc_t *, void *, unsigned *, hid_t, H5O_copy_t *); /*"post copy" action when copying native value to file */
herr_t (*get_crt_index)(const void *, H5O_msg_crt_idx_t *); /* Get message's creation index */
herr_t (*set_crt_index)(void *, H5O_msg_crt_idx_t); /* Set message's creation index */
herr_t (*debug)(H5F_t*, hid_t, const void*, FILE*, int, int);
@@ -325,6 +325,7 @@ typedef struct H5O_obj_class_t {
void *(*create)(H5F_t *, void *, H5G_loc_t *, hid_t ); /*create an object of this class */
H5O_loc_t *(*get_oloc)(hid_t ); /*get the object header location for an object */
herr_t (*bh_info)(H5F_t *f, hid_t dxpl_id, H5O_t *oh, H5_ih_info_t *bh_info); /*get the index & heap info for an object */
+ herr_t (*flush)(H5G_loc_t *loc, hid_t dxpl_id); /*flush an opened object of this class */
} H5O_obj_class_t;
/* Node in skip list to map addresses from one file to another during object header copy */
@@ -527,7 +528,7 @@ H5_DLL herr_t H5O_msg_flush(H5F_t *f, H5O_t *oh, H5O_mesg_t *mesg);
H5_DLL herr_t H5O_flush_msgs(H5F_t *f, H5O_t *oh);
H5_DLL hid_t H5O_open_by_loc(const H5G_loc_t *obj_loc, hid_t lapl_id, hid_t dxpl_id, hbool_t app_ref);
H5_DLL herr_t H5O_delete_mesg(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, H5O_mesg_t *mesg);
-H5_DLL const H5O_obj_class_t *H5O_obj_class_real(H5O_t *oh);
+H5_DLL const H5O_obj_class_t * H5O_obj_class(const H5O_loc_t *loc, hid_t dxpl_id);
H5_DLL int H5O_link_oh(H5F_t *f, int adjust, hid_t dxpl_id, H5O_t *oh, hbool_t *deleted);
H5_DLL herr_t H5O_inc_rc(H5O_t *oh);
H5_DLL herr_t H5O_dec_rc(H5O_t *oh);
@@ -549,7 +550,7 @@ H5_DLL herr_t H5O_msg_remove_real(H5F_t *f, H5O_t *oh, const H5O_msg_class_t *ty
int sequence, H5O_operator_t op, void *op_data, hbool_t adj_link, hid_t dxpl_id);
H5_DLL void *H5O_msg_copy_file(const H5O_msg_class_t *type, H5F_t *file_src,
void *mesg_src, H5F_t *file_dst, hbool_t *recompute_size,
- H5O_copy_t *cpy_info, void *udata, hid_t dxpl_id);
+ unsigned *mesg_flags, H5O_copy_t *cpy_info, void *udata, hid_t dxpl_id);
H5_DLL herr_t H5O_msg_iterate_real(H5F_t *f, H5O_t *oh, const H5O_msg_class_t *type,
const H5O_mesg_operator_t *op, void *op_data, hid_t dxpl_id);
@@ -586,10 +587,12 @@ H5_DLL herr_t H5O_shared_link(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
const H5O_msg_class_t *mesg_type, H5O_shared_t *sh_mesg);
H5_DLL herr_t H5O_shared_copy_file(H5F_t *file_src, H5F_t *file_dst,
const H5O_msg_class_t *mesg_type, const void *_native_src, void *_native_dst,
- hbool_t *recompute_size, H5O_copy_t *cpy_info, void *udata, hid_t dxpl_id);
+ hbool_t *recompute_size, unsigned *mesg_flags, H5O_copy_t *cpy_info,
+ void *udata, hid_t dxpl_id);
H5_DLL herr_t H5O_shared_post_copy_file (H5F_t *f,
const H5O_msg_class_t *mesg_type, const H5O_shared_t *shared_src,
- H5O_shared_t *shared_dst, hid_t dxpl_id, H5O_copy_t *cpy_info);
+ H5O_shared_t *shared_dst, unsigned *mesg_flags, hid_t dxpl_id,
+ H5O_copy_t *cpy_info);
H5_DLL herr_t H5O_shared_debug(const H5O_shared_t *mesg, FILE *stream,
int indent, int fwidth);
diff --git a/src/H5Opline.c b/src/H5Opline.c
index 89ce865..f626106 100644
--- a/src/H5Opline.c
+++ b/src/H5Opline.c
@@ -61,6 +61,7 @@ static herr_t H5O_pline_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg,
#undef H5O_SHARED_COPY_FILE_REAL
#define H5O_SHARED_POST_COPY_FILE H5O_pline_shared_post_copy_file
#undef H5O_SHARED_POST_COPY_FILE_REAL
+#undef H5O_SHARED_POST_COPY_FILE_UPD
#define H5O_SHARED_DEBUG H5O_pline_shared_debug
#define H5O_SHARED_DEBUG_REAL H5O_pline_debug
#include "H5Oshared.h" /* Shared Object Header Message Callbacks */
diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h
index 97bd9a7..8e2dfa4 100644
--- a/src/H5Oprivate.h
+++ b/src/H5Oprivate.h
@@ -99,7 +99,9 @@ typedef struct H5O_t H5O_t;
#endif /* H5O_ENABLE_BAD_MESG_COUNT */
/* ========= Object Copy properties ============ */
-#define H5O_CPY_OPTION_NAME "copy object" /* Copy options */
+#define H5O_CPY_OPTION_NAME "copy object" /* Copy options */
+#define H5O_CPY_MERGE_COMM_DT_LIST_NAME "merge committed dtype list" /* List of datatype paths to search in the dest file for merging */
+#define H5O_CPY_MCDT_SEARCH_CB_NAME "committed dtype list search" /* Callback function when the search for a matching committed datatype is complete */
/* If the module using this macro is allowed access to the private variables, access them directly */
#ifdef H5O_PACKAGE
@@ -133,6 +135,18 @@ typedef struct H5O_loc_t {
* its file's count of open objects. */
} H5O_loc_t;
+/* Typedef for linked list of datatype merge suggestions */
+typedef struct H5O_copy_dtype_merge_list_t {
+ char *path; /* Path to datatype in destination file */
+ struct H5O_copy_dtype_merge_list_t *next; /* Next object in list */
+} H5O_copy_dtype_merge_list_t;
+
+/* Structure for callback property before searching the global list of committed datatypes at destination */
+typedef struct H5O_mcdt_cb_info_t {
+ H5O_mcdt_search_cb_t func;
+ void *user_data;
+} H5O_mcdt_cb_info_t;
+
/* Settings/flags for copying an object */
typedef struct H5O_copy_t {
hbool_t copy_shallow; /* Flag to perform shallow hierarchy copy */
@@ -141,10 +155,16 @@ typedef struct H5O_copy_t {
hbool_t expand_ref; /* Flag to expand object references */
hbool_t copy_without_attr; /* Flag to not copy attributes */
hbool_t preserve_null; /* Flag to not delete NULL messages */
+ hbool_t merge_comm_dt; /* Flag to merge committed datatypes in dest file */
+ H5O_copy_dtype_merge_list_t *dst_dt_suggestion_list; /* Suggestions for merging committed datatypes */
int curr_depth; /* Current depth in hierarchy copied */
int max_depth; /* Maximum depth in hierarchy to copy */
H5SL_t *map_list; /* Skip list to hold address mappings */
+ H5SL_t *dst_dt_list; /* Skip list to hold committed datatypes in dest file */
+ hbool_t dst_dt_list_complete; /* Whether the destination datatype list is complete (i.e. not only populated with "suggestions" from H5Padd_merge_committed_dtype_path) */
H5O_t *oh_dst; /* The destination object header */
+ H5O_mcdt_search_cb_t mcdt_cb; /* The callback to invoke before searching the global list of committed datatypes at destination */
+ void *mcdt_ud; /* User data passed to callback */
} H5O_copy_t;
/* Header message IDs */
diff --git a/src/H5Opublic.h b/src/H5Opublic.h
index 2379d6b..a7d386a 100644
--- a/src/H5Opublic.h
+++ b/src/H5Opublic.h
@@ -43,7 +43,8 @@
#define H5O_COPY_EXPAND_REFERENCE_FLAG (0x0008u) /* Copy objects that are pointed by references */
#define H5O_COPY_WITHOUT_ATTR_FLAG (0x0010u) /* Copy object without copying attributes */
#define H5O_COPY_PRESERVE_NULL_FLAG (0x0020u) /* Copy NULL messages (empty space) */
-#define H5O_COPY_ALL (0x003Fu) /* All object copying flags (for internal checking) */
+#define H5O_COPY_MERGE_COMMITTED_DTYPE_FLAG (0x0040u) /* Merge committed datatypes in dest file */
+#define H5O_COPY_ALL (0x007Fu) /* All object copying flags (for internal checking) */
/* Flags for shared message indexes.
* Pass these flags in using the mesg_type_flags parameter in
@@ -131,6 +132,14 @@ typedef uint32_t H5O_msg_crt_idx_t;
typedef herr_t (*H5O_iterate_t)(hid_t obj, const char *name, const H5O_info_t *info,
void *op_data);
+typedef enum H5O_mcdt_search_ret_t {
+ H5O_MCDT_SEARCH_ERROR = -1, /* Abort H5Ocopy */
+ H5O_MCDT_SEARCH_CONT, /* Continue the global search of all committed datatypes in the destination file */
+ H5O_MCDT_SEARCH_STOP /* Stop the search, but continue copying. The committed datatype will be copied but not merged. */
+} H5O_mcdt_search_ret_t;
+
+/* Callback to invoke when completing the search for a matching committed datatype from the committed dtype list */
+typedef H5O_mcdt_search_ret_t (*H5O_mcdt_search_cb_t)(void *op_data);
/********************/
/* Public Variables */
diff --git a/src/H5Osdspace.c b/src/H5Osdspace.c
index 8ae73f7..905c4e9 100644
--- a/src/H5Osdspace.c
+++ b/src/H5Osdspace.c
@@ -55,6 +55,7 @@ static herr_t H5O_sdspace_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg,
#undef H5O_SHARED_COPY_FILE_REAL
#define H5O_SHARED_POST_COPY_FILE H5O_sdspace_shared_post_copy_file
#undef H5O_SHARED_POST_COPY_FILE_REAL
+#undef H5O_SHARED_POST_COPY_FILE_UPD
#define H5O_SHARED_DEBUG H5O_sdspace_shared_debug
#define H5O_SHARED_DEBUG_REAL H5O_sdspace_debug
#include "H5Oshared.h" /* Shared Object Header Message Callbacks */
diff --git a/src/H5Oshared.c b/src/H5Oshared.c
index 4cc30e8..c29e2c7 100644
--- a/src/H5Oshared.c
+++ b/src/H5Oshared.c
@@ -589,8 +589,8 @@ done:
herr_t
H5O_shared_copy_file(H5F_t *file_src, H5F_t *file_dst,
const H5O_msg_class_t *mesg_type, const void *_native_src, void *_native_dst,
- hbool_t UNUSED *recompute_size, H5O_copy_t *cpy_info, void UNUSED *udata,
- hid_t dxpl_id)
+ hbool_t UNUSED *recompute_size, unsigned *mesg_flags, H5O_copy_t *cpy_info,
+ void UNUSED *udata, hid_t dxpl_id)
{
const H5O_shared_t *shared_src = (const H5O_shared_t *)_native_src; /* Alias to shared info in native source */
H5O_shared_t *shared_dst = (H5O_shared_t *)_native_dst; /* Alias to shared info in native destination message */
@@ -621,16 +621,18 @@ H5O_shared_copy_file(H5F_t *file_src, H5F_t *file_dst,
/* Set copied metadata tag */
H5_BEGIN_TAG(dxpl_id, H5AC__COPIED_TAG, FAIL);
- if(H5SM_try_share(file_dst, dxpl_id, NULL, H5SM_DEFER, mesg_type->id, _native_dst, NULL) < 0)
+ if(H5SM_try_share(file_dst, dxpl_id, NULL, H5SM_DEFER, mesg_type->id, _native_dst, mesg_flags) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to determine if message should be shared")
/* Reset metadata tag */
H5_END_TAG(FAIL);
} /* end if */
- else
+ else {
/* Mark the message as committed - as it will be committed in post copy
*/
H5O_UPDATE_SHARED(shared_dst, H5O_SHARE_TYPE_COMMITTED, file_dst, mesg_type->id, 0, HADDR_UNDEF)
+ *mesg_flags |= H5O_MSG_FLAG_SHARED;
+ } /* end else */
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -657,8 +659,8 @@ done:
*/
herr_t
H5O_shared_post_copy_file(H5F_t *f, const H5O_msg_class_t *mesg_type,
- const H5O_shared_t *shared_src, H5O_shared_t *shared_dst, hid_t dxpl_id,
- H5O_copy_t *cpy_info)
+ const H5O_shared_t *shared_src, H5O_shared_t *shared_dst,
+ unsigned *mesg_flags, hid_t dxpl_id, H5O_copy_t *cpy_info)
{
herr_t ret_value = SUCCEED; /* Return value */
@@ -675,6 +677,7 @@ H5O_shared_post_copy_file(H5F_t *f, const H5O_msg_class_t *mesg_type,
H5O_loc_t src_oloc;
/* Copy the shared object from source to destination */
+ H5O_loc_reset(&dst_oloc);
dst_oloc.file = f;
src_oloc.file = shared_src->file;
src_oloc.addr = shared_src->u.loc.oh_addr;
@@ -688,7 +691,7 @@ H5O_shared_post_copy_file(H5F_t *f, const H5O_msg_class_t *mesg_type,
else
/* Share the message */
if(H5SM_try_share(f, dxpl_id, NULL, H5SM_WAS_DEFERRED, mesg_type->id,
- shared_dst, NULL) < 0)
+ shared_dst, mesg_flags) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "can't share message")
done:
diff --git a/src/H5Oshared.h b/src/H5Oshared.h
index ddacc25..3ec5709 100644
--- a/src/H5Oshared.h
+++ b/src/H5Oshared.h
@@ -320,7 +320,8 @@ done:
*/
static H5_inline void *
H5O_SHARED_COPY_FILE(H5F_t *file_src, void *_native_src, H5F_t *file_dst,
- hbool_t *recompute_size, H5O_copy_t *cpy_info, void *udata, hid_t dxpl_id)
+ hbool_t *recompute_size, unsigned *mesg_flags, H5O_copy_t *cpy_info,
+ void *udata, hid_t dxpl_id)
{
void *dst_mesg = NULL; /* Destination message */
void *ret_value; /* Return value */
@@ -348,8 +349,8 @@ H5O_SHARED_COPY_FILE(H5F_t *file_src, void *_native_src, H5F_t *file_dst,
HDmemset(dst_mesg, 0, sizeof(H5O_shared_t));
/* Handle sharing destination message */
- if(H5O_shared_copy_file(file_src, file_dst, H5O_SHARED_TYPE,
- _native_src, dst_mesg, recompute_size, cpy_info, udata, dxpl_id) < 0)
+ if(H5O_shared_copy_file(file_src, file_dst, H5O_SHARED_TYPE, _native_src,
+ dst_mesg, recompute_size, mesg_flags, cpy_info, udata, dxpl_id) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, NULL, "unable to determine if message should be shared")
/* Set return value */
@@ -383,7 +384,8 @@ done:
*/
static H5_inline herr_t
H5O_SHARED_POST_COPY_FILE(const H5O_loc_t *oloc_src, const void *mesg_src,
- H5O_loc_t *oloc_dst, void *mesg_dst, hid_t dxpl_id, H5O_copy_t *cpy_info)
+ H5O_loc_t *oloc_dst, void *mesg_dst, unsigned *mesg_flags, hid_t dxpl_id,
+ H5O_copy_t *cpy_info)
{
const H5O_shared_t *shared_src = (const H5O_shared_t *)mesg_src; /* Alias to shared info in native source */
H5O_shared_t *shared_dst = (H5O_shared_t *)mesg_dst; /* Alias to shared info in native destination */
@@ -405,7 +407,7 @@ H5O_SHARED_POST_COPY_FILE(const H5O_loc_t *oloc_src, const void *mesg_src,
#endif /* H5O_SHARED_POST_COPY_FILE */
#ifdef H5O_SHARED_POST_COPY_FILE_REAL
- /* Call native message's copy file callback to copy the message */
+ /* Call native message's post copy file callback to copy the message */
if(H5O_SHARED_POST_COPY_FILE_REAL(oloc_src, mesg_src, oloc_dst, mesg_dst, dxpl_id, cpy_info) <0 )
HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy native message to another file")
#endif /* H5O_SHARED_POST_COPY_FILE_REAL */
@@ -414,9 +416,16 @@ H5O_SHARED_POST_COPY_FILE(const H5O_loc_t *oloc_src, const void *mesg_src,
* production if the DEFER pass determined it will not be shared; debug mode
* verifies that it is indeed the case */
if(H5O_shared_post_copy_file(oloc_dst->file, H5O_SHARED_TYPE,
- shared_src, shared_dst, dxpl_id, cpy_info) < 0)
+ shared_src, shared_dst, mesg_flags, dxpl_id, cpy_info) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to fix shared message in post copy")
+#ifdef H5O_SHARED_POST_COPY_FILE_UPD
+ /* Call native message's post copy file update callback to update the
+ * message */
+ if(H5O_SHARED_POST_COPY_FILE_UPD(oloc_src, mesg_src, oloc_dst, mesg_dst, dxpl_id, cpy_info) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to update native message")
+#endif /* H5O_SHARED_POST_COPY_FILE_UPD */
+
/* Make sure that if the the source or destination is committed, both are
* committed */
HDassert((shared_src->type == H5O_SHARE_TYPE_COMMITTED)
diff --git a/src/H5Ostab.c b/src/H5Ostab.c
index 42cd92c..d5f5f86 100644
--- a/src/H5Ostab.c
+++ b/src/H5Ostab.c
@@ -44,10 +44,11 @@ static size_t H5O_stab_size(const H5F_t *f, hbool_t disable_shared, const void *
static herr_t H5O_stab_free(void *_mesg);
static herr_t H5O_stab_delete(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, void *_mesg);
static void *H5O_stab_copy_file(H5F_t *file_src, void *native_src,
- H5F_t *file_dst, hbool_t *recompute_size, H5O_copy_t *cpy_info, void *_udata,
- hid_t dxpl_id);
-static herr_t H5O_stab_post_copy_file(const H5O_loc_t *src_oloc, const void *mesg_src, H5O_loc_t *dst_oloc,
- void *mesg_dst, hid_t dxpl_id, H5O_copy_t *cpy_info);
+ H5F_t *file_dst, hbool_t *recompute_size, unsigned *mesg_flags,
+ H5O_copy_t *cpy_info, void *_udata, hid_t dxpl_id);
+static herr_t H5O_stab_post_copy_file(const H5O_loc_t *src_oloc,
+ const void *mesg_src, H5O_loc_t *dst_oloc, void *mesg_dst,
+ unsigned *mesg_flags, hid_t dxpl_id, H5O_copy_t *cpy_info);
static herr_t H5O_stab_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg,
FILE * stream, int indent, int fwidth);
@@ -307,8 +308,8 @@ done:
*/
static void *
H5O_stab_copy_file(H5F_t *file_src, void *native_src, H5F_t *file_dst,
- hbool_t UNUSED *recompute_size, H5O_copy_t UNUSED *cpy_info, void *_udata,
- hid_t dxpl_id)
+ hbool_t UNUSED *recompute_size, unsigned UNUSED *mesg_flags,
+ H5O_copy_t UNUSED *cpy_info, void *_udata, hid_t dxpl_id)
{
H5O_stab_t *stab_src = (H5O_stab_t *) native_src;
H5O_stab_t *stab_dst = NULL;
@@ -370,8 +371,9 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5O_stab_post_copy_file(const H5O_loc_t *src_oloc, const void *mesg_src, H5O_loc_t *dst_oloc,
- void *mesg_dst, hid_t dxpl_id, H5O_copy_t *cpy_info)
+H5O_stab_post_copy_file(const H5O_loc_t *src_oloc, const void *mesg_src,
+ H5O_loc_t *dst_oloc, void *mesg_dst, unsigned UNUSED *mesg_flags,
+ hid_t dxpl_id, H5O_copy_t *cpy_info)
{
const H5O_stab_t *stab_src = (const H5O_stab_t *)mesg_src;
H5O_stab_t *stab_dst = (H5O_stab_t *)mesg_dst;
diff --git a/src/H5Pdcpl.c b/src/H5Pdcpl.c
index f07aa87..0a41371 100644
--- a/src/H5Pdcpl.c
+++ b/src/H5Pdcpl.c
@@ -410,7 +410,7 @@ H5P_dcrt_layout_cmp(const void *_layout1, const void *_layout2, size_t UNUSED si
/* Sanity check */
HDassert(layout1);
- HDassert(layout1);
+ HDassert(layout2);
HDassert(size == sizeof(H5O_layout_t));
/* Check for different layout type */
diff --git a/src/H5Pfapl.c b/src/H5Pfapl.c
index c75cf61..2d46ec7 100644
--- a/src/H5Pfapl.c
+++ b/src/H5Pfapl.c
@@ -40,6 +40,7 @@
#include "H5FDprivate.h" /* File drivers */
#include "H5VLprivate.h" /* VOL plugins */
#include "H5Iprivate.h" /* IDs */
+#include "H5MMprivate.h" /* Memory Management */
#include "H5Ppkg.h" /* Property lists */
/* Includes needed to set as default file driver */
@@ -125,10 +126,18 @@
/* Definition for external file cache size */
#define H5F_ACS_EFC_SIZE_SIZE sizeof(unsigned)
#define H5F_ACS_EFC_SIZE_DEF 0
+
/* Definition for VOL plugin */
#define H5F_ACS_VOL_SIZE sizeof(void *)
#define H5F_ACS_VOL_DEF H5VL_NATIVE
+/* Definition of pointer to initial file image info */
+#define H5F_ACS_FILE_IMAGE_INFO_SIZE sizeof(H5FD_file_image_info_t)
+#define H5F_ACS_FILE_IMAGE_INFO_DEF H5FD_DEFAULT_FILE_IMAGE_INFO
+#define H5F_ACS_FILE_IMAGE_INFO_DEL H5P_file_image_info_del
+#define H5F_ACS_FILE_IMAGE_INFO_COPY H5P_file_image_info_copy
+#define H5F_ACS_FILE_IMAGE_INFO_CLOSE H5P_file_image_info_close
+
/******************/
/* Local Typedefs */
/******************/
@@ -154,6 +163,10 @@ static herr_t H5P_facc_reg_prop(H5P_genclass_t *pclass);
static herr_t H5P_facc_create(hid_t fapl_id, void *copy_data);
static herr_t H5P_facc_copy(hid_t new_plist_t, hid_t old_plist_t, void *copy_data);
+/* File image info property callbacks */
+static herr_t H5P_file_image_info_del(hid_t prop_id, const char *name, size_t size, void *value);
+static herr_t H5P_file_image_info_copy(const char *name, size_t size, void *value);
+static herr_t H5P_file_image_info_close(const char *name, size_t size, void *value);
/*********************/
/* Package Variables */
@@ -221,6 +234,7 @@ H5P_facc_reg_prop(H5P_genclass_t *pclass)
hbool_t want_posix_fd = H5F_ACS_WANT_POSIX_FD_DEF; /* Default setting for retrieving 'handle' from core VFD */
unsigned efc_size = H5F_ACS_EFC_SIZE_DEF; /* Default external file cache size */
H5VL_class_t *vol_cls = H5F_ACS_VOL_DEF; /* Default VOL plugin */
+ H5FD_file_image_info_t file_image_info = H5F_ACS_FILE_IMAGE_INFO_DEF; /* Default file image info and callbacks */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT
@@ -310,6 +324,10 @@ H5P_facc_reg_prop(H5P_genclass_t *pclass)
if(H5P_register_real(pclass, H5F_ACS_VOL_NAME, H5F_ACS_VOL_SIZE, &vol_cls, NULL, NULL, NULL, NULL, NULL, NULL, NULL) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
+ /* Register the initial file image info */
+ if(H5P_register_real(pclass, H5F_ACS_FILE_IMAGE_INFO_NAME, H5F_ACS_FILE_IMAGE_INFO_SIZE, &file_image_info, NULL, NULL, NULL, H5F_ACS_FILE_IMAGE_INFO_DEL, H5F_ACS_FILE_IMAGE_INFO_COPY, NULL, H5F_ACS_FILE_IMAGE_INFO_CLOSE) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
+
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5P_facc_reg_prop() */
@@ -2140,7 +2158,6 @@ done:
FUNC_LEAVE_API(ret_value)
} /* end H5Pget_elink_file_cache_size() */
-/* MSC Begin update */
/*-------------------------------------------------------------------------
* Function: H5P_set_vol
@@ -2184,3 +2201,484 @@ H5P_set_vol(H5P_genplist_t *plist, H5VL_class_t *vol_cls)
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5P_set_vol() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Pset_file_image
+ *
+ * Purpose: Sets the initial file image. Some file drivers can initialize
+ * the starting data in a file from a buffer.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Jacob Gruber
+ * Thurday, August 11, 2011
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Pset_file_image(hid_t fapl_id, void *buf_ptr, size_t buf_len)
+{
+ H5P_genplist_t *fapl; /* Property list pointer */
+ H5FD_file_image_info_t image_info; /* File image info */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE3("e", "i*xz", fapl_id, buf_ptr, buf_len);
+
+ /* validate parameters */
+ if(!(((buf_ptr == NULL) && (buf_len == 0)) || ((buf_ptr != NULL) && (buf_len > 0))))
+ HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "inconsistant buf_ptr and buf_len");
+
+ /* Get the plist structure */
+ if(NULL == (fapl = H5P_object_verify(fapl_id, H5P_FILE_ACCESS)))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
+
+ /* Get old image info */
+ if(H5P_get(fapl, H5F_ACS_FILE_IMAGE_INFO_NAME, &image_info) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get old file image pointer")
+
+ /* Release previous buffer, if it exists */
+ if(image_info.buffer != NULL) {
+ if(image_info.callbacks.image_free) {
+ if(SUCCEED != image_info.callbacks.image_free(image_info.buffer, H5FD_FILE_IMAGE_OP_PROPERTY_LIST_SET, image_info.callbacks.udata))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "image_free callback failed")
+ } /* end if */
+ else
+ H5MM_xfree(image_info.buffer);
+ } /* end if */
+
+ /* Update struct */
+ if(buf_ptr) {
+ /* Allocate memory */
+ if(image_info.callbacks.image_malloc) {
+ if(NULL == (image_info.buffer = image_info.callbacks.image_malloc(buf_len,
+ H5FD_FILE_IMAGE_OP_PROPERTY_LIST_SET, image_info.callbacks.udata)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "image malloc callback failed")
+ } /* end if */
+ else
+ if(NULL == (image_info.buffer = H5MM_malloc(buf_len)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate memory block")
+
+ /* Copy data */
+ if(image_info.callbacks.image_memcpy) {
+ if(image_info.buffer != image_info.callbacks.image_memcpy(image_info.buffer,
+ buf_ptr, buf_len, H5FD_FILE_IMAGE_OP_PROPERTY_LIST_SET,
+ image_info.callbacks.udata))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTCOPY, FAIL, "image_memcpy callback failed")
+ } /* end if */
+ else
+ HDmemcpy(image_info.buffer, buf_ptr, buf_len);
+ } /* end if */
+ else
+ image_info.buffer = NULL;
+
+ image_info.size = buf_len;
+
+ /* Set values */
+ if(H5P_set(fapl, H5F_ACS_FILE_IMAGE_INFO_NAME, &image_info) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set file image info")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Pset_file_image() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Pget_file_image
+ *
+ * Purpose: If the file image exists and buf_ptr_ptr is not NULL,
+ * allocate a buffer of the correct size, copy the image into
+ * the new buffer, and return the buffer to the caller in
+ * *buf_ptr_ptr. Do this using the file image callbacks
+ * if defined.
+ *
+ * NB: It is the responsibility of the caller to free the
+ * buffer whose address is returned in *buf_ptr_ptr. Do
+ * this using free if the file image callbacks are not
+ * defined, or with whatever method is appropriate if
+ * the callbacks are defined.
+ *
+ * If buf_ptr_ptr is not NULL, and no image exists, set
+ * *buf_ptr_ptr to NULL.
+ *
+ * If buf_len_ptr is not NULL, set *buf_len_ptr equal
+ * to the length of the file image if it exists, and
+ * to 0 if it does not.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Jacob Gruber
+ * Thurday, August 11, 2011
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Pget_file_image(hid_t fapl_id, void **buf_ptr_ptr, size_t *buf_len_ptr)
+{
+ H5P_genplist_t *fapl; /* Property list pointer */
+ H5FD_file_image_info_t image_info; /* File image info */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE3("e", "i**x*z", fapl_id, buf_ptr_ptr, buf_len_ptr);
+
+ /* Get the plist structure */
+ if(NULL == (fapl = H5P_object_verify(fapl_id, H5P_FILE_ACCESS)))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
+
+ /* Get values */
+ if(H5P_get(fapl, H5F_ACS_FILE_IMAGE_INFO_NAME, &image_info) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get file image info")
+
+ /* verify file image field consistancy */
+ HDassert(((image_info.buffer != NULL) && (image_info.size > 0)) ||
+ ((image_info.buffer == NULL) && (image_info.size == 0)));
+
+ /* Set output size */
+ if(buf_len_ptr != NULL)
+ *buf_len_ptr = image_info.size;
+
+ /* Duplicate the image if desired, using callbacks if available */
+ if(buf_ptr_ptr != NULL) {
+ void * copy_ptr = NULL; /* Copy of memory image */
+
+ if(image_info.buffer != NULL) {
+ /* Allocate memory */
+ if(image_info.callbacks.image_malloc) {
+ if(NULL == (copy_ptr = image_info.callbacks.image_malloc(image_info.size,
+ H5FD_FILE_IMAGE_OP_PROPERTY_LIST_GET, image_info.callbacks.udata)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "image malloc callback failed")
+ } /* end if */
+ else
+ if(NULL == (copy_ptr = H5MM_malloc(image_info.size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate copy")
+
+ /* Copy data */
+ if(image_info.callbacks.image_memcpy) {
+ if(copy_ptr != image_info.callbacks.image_memcpy(copy_ptr, image_info.buffer,
+ image_info.size, H5FD_FILE_IMAGE_OP_PROPERTY_LIST_GET,
+ image_info.callbacks.udata))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTCOPY, FAIL, "image_memcpy callback failed")
+ } /* end if */
+ else
+ HDmemcpy(copy_ptr, image_info.buffer, image_info.size);
+ } /* end if */
+
+ *buf_ptr_ptr = copy_ptr;
+ } /* end if */
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Pget_file_image */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Pset_file_image_callbacks
+ *
+ * Purpose: Sets the callbacks for file images. Some file drivers allow
+ * the use of user-defined callbacks for allocating, freeing and
+ * copying the drivers internal buffer, potentially allowing a
+ * clever user to do optimizations such as avoiding large mallocs
+ * and memcpys or to perform detailed logging.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Jacob Gruber
+ * Thurday, August 11, 2011
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Pset_file_image_callbacks(hid_t fapl_id, H5FD_file_image_callbacks_t *callbacks_ptr)
+{
+ H5P_genplist_t *fapl; /* Property list pointer */
+ H5FD_file_image_info_t info; /* File image info */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE2("e", "i*x", fapl_id, callbacks_ptr);
+
+ /* Get the plist structure */
+ if(NULL == (fapl = H5P_object_verify(fapl_id, H5P_FILE_ACCESS)))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
+
+ /* Get old info */
+ if(H5P_get(fapl, H5F_ACS_FILE_IMAGE_INFO_NAME, &info) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get old file image info")
+
+ /* verify file image field consistancy */
+ HDassert(((info.buffer != NULL) && (info.size > 0)) ||
+ ((info.buffer == NULL) && (info.size == 0)));
+
+ /* Make sure a file image hasn't already been set */
+ if(info.buffer != NULL || info.size > 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_SETDISALLOWED, FAIL, "setting callbacks when an image is already set is forbidden. It could cause memory leaks.")
+
+ /* verify that callbacks_ptr is not NULL */
+ if(NULL == callbacks_ptr)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "NULL callbacks_ptr")
+
+ /* Make sure udata callbacks are going to be set if udata is going to be set */
+ if(callbacks_ptr->udata)
+ if(callbacks_ptr->udata_copy == NULL || callbacks_ptr->udata_free == NULL)
+ HGOTO_ERROR(H5E_PLIST, H5E_SETDISALLOWED, FAIL, "udata callbacks must be set if udata is set")
+
+ /* Release old udata if it exists */
+ if(info.callbacks.udata != NULL) {
+ HDassert(info.callbacks.udata_free);
+ if(info.callbacks.udata_free(info.callbacks.udata) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "udata_free callback failed")
+ } /* end if */
+
+ /* Update struct */
+ info.callbacks = *callbacks_ptr;
+
+ if(callbacks_ptr->udata) {
+ HDassert(callbacks_ptr->udata_copy);
+ HDassert(callbacks_ptr->udata_free);
+ if((info.callbacks.udata = callbacks_ptr->udata_copy(callbacks_ptr->udata)) == NULL)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't copy the suppplied udata")
+ } /* end if */
+
+ /* Set values */
+ if(H5P_set(fapl, H5F_ACS_FILE_IMAGE_INFO_NAME, &info) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set file image info")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Pset_file_image_callbacks() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Pget_file_image_callbacks
+ *
+ * Purpose: Sets the callbacks for file images. Some file drivers allow
+ * the use of user-defined callbacks for allocating, freeing and
+ * copying the drivers internal buffer, potentially allowing a
+ * clever user to do optimizations such as avoiding large mallocs
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Jacob Gruber
+ * Thurday, August 11, 2011
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Pget_file_image_callbacks(hid_t fapl_id, H5FD_file_image_callbacks_t *callbacks_ptr)
+{
+ H5P_genplist_t *fapl; /* Property list pointer */
+ H5FD_file_image_info_t info; /* File image info */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE2("e", "i*x", fapl_id, callbacks_ptr);
+
+ /* Get the plist structure */
+ if(NULL == (fapl = H5P_object_verify(fapl_id, H5P_FILE_ACCESS)))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
+
+ /* Get old info */
+ if(H5P_get(fapl, H5F_ACS_FILE_IMAGE_INFO_NAME, &info) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get file image info")
+
+ /* verify file image field consistancy */
+ HDassert(((info.buffer != NULL) && (info.size > 0)) ||
+ ((info.buffer == NULL) && (info.size == 0)));
+
+ /* verify that callbacks_ptr is not NULL */
+ if(NULL == callbacks_ptr)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "NULL callbacks_ptr")
+
+ /* Transfer values to parameters */
+ *callbacks_ptr = info.callbacks;
+
+ /* Copy udata if it exists */
+ if(info.callbacks.udata != NULL) {
+ HDassert(info.callbacks.udata_copy);
+ if((callbacks_ptr->udata = info.callbacks.udata_copy(info.callbacks.udata)) == 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't copy udata")
+ } /* end if */
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Pget_file_image_callbacks() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5P_file_image_info_del
+ *
+ * Purpose: Delete callback for the file image info property, called
+ * when the property is deleted from the plist. The buffer
+ * and udata may need to be freed, possibly using their
+ * respective callbacks so the default free won't work.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Jacob Gruber
+ * Thurday, August 11, 2011
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5P_file_image_info_del(hid_t UNUSED prop_id, const char UNUSED *name, size_t UNUSED size, void *value)
+{
+ H5FD_file_image_info_t info; /* Image info struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ if(value) {
+ info = *(H5FD_file_image_info_t *)value;
+
+ /* verify file image field consistancy */
+ HDassert(((info.buffer != NULL) && (info.size > 0)) ||
+ ((info.buffer == NULL) && (info.size == 0)));
+
+ if(info.buffer && info.size > 0) {
+ /* Free buffer */
+ if(info.callbacks.image_free) {
+ if(info.callbacks.image_free(info.buffer, H5FD_FILE_IMAGE_OP_PROPERTY_LIST_CLOSE, info.callbacks.udata) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "image_free callback failed")
+ } /* end if */
+ else
+ free(info.buffer);
+ } /* end if */
+
+ /* Free udata if it exists */
+ if(info.callbacks.udata) {
+ if(NULL == info.callbacks.udata_free)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "udata_free not defined")
+
+ if(info.callbacks.udata_free(info.callbacks.udata) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "udata_free callback failed")
+ } /* end if */
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5P_file_image_info_del() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5P_file_image_info_copy
+ *
+ * Purpose: Copy callback for the file image info property. The buffer
+ * and udata may need to be copied, possibly using their
+ * respective callbacks so the default copy won't work.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Jacob Gruber
+ * Thurday, August 11, 2011
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5P_file_image_info_copy(const char UNUSED *name, size_t UNUSED size, void *value)
+{
+ H5FD_file_image_info_t *info; /* Image info struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ if(value) {
+ info = (H5FD_file_image_info_t *)value;
+
+ /* verify file image field consistancy */
+ HDassert(((info->buffer != NULL) && (info->size > 0)) ||
+ ((info->buffer == NULL) && (info->size == 0)));
+
+ if(info->buffer && info->size > 0) {
+ void *old_buffer; /* Pointer to old image buffer */
+
+ /* Store the old buffer */
+ old_buffer = info->buffer;
+
+ /* Allocate new buffer */
+ if(info->callbacks.image_malloc) {
+ if(NULL == (info->buffer = info->callbacks.image_malloc(info->size,
+ H5FD_FILE_IMAGE_OP_PROPERTY_LIST_COPY, info->callbacks.udata)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "image malloc callback failed")
+ } /* end if */
+ else {
+ if(NULL == (info->buffer = H5MM_malloc(info->size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate memory block")
+ } /* end else */
+
+ /* Copy data to new buffer */
+ if(info->callbacks.image_memcpy) {
+ if(info->buffer != info->callbacks.image_memcpy(info->buffer, old_buffer,
+ info->size, H5FD_FILE_IMAGE_OP_PROPERTY_LIST_COPY,
+ info->callbacks.udata))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTCOPY, FAIL, "image_memcpy callback failed")
+ } /* end if */
+ else
+ HDmemcpy(info->buffer, old_buffer, info->size);
+ } /* end if */
+ } /* end if */
+
+ /* Copy udata if it exists */
+ if(info->callbacks.udata) {
+ void *old_udata = info->callbacks.udata;
+
+ if(NULL == info->callbacks.udata_copy)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "udata_copy not defined")
+
+ info->callbacks.udata = info->callbacks.udata_copy(old_udata);
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5P_file_image_info_copy() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5P_file_image_info_close
+ *
+ * Purpose: Close callback for the file image info property. The buffer
+ * and udata may need to be freed, possibly using their
+ * respective callbacks so the standard free won't work.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Jacob Gruber
+ * Thurday, August 11, 2011
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5P_file_image_info_close(const char UNUSED *name, size_t UNUSED size, void *value)
+{
+ H5FD_file_image_info_t info; /* Image info struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ if(value) {
+ info = *(H5FD_file_image_info_t *)value;
+
+ if(info.buffer != NULL && info.size > 0) {
+ /* Free buffer */
+ if(info.callbacks.image_free) {
+ if(info.callbacks.image_free(info.buffer, H5FD_FILE_IMAGE_OP_PROPERTY_LIST_CLOSE,
+ info.callbacks.udata) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "image_free callback failed")
+ } /* end if */
+ else
+ H5MM_xfree(info.buffer);
+ } /* end if */
+ } /* end if */
+
+ /* Free udata if it exists */
+ if(info.callbacks.udata) {
+ if(NULL == info.callbacks.udata_free)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "udata_free not defined")
+ if(info.callbacks.udata_free(info.callbacks.udata) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "udata_free callback failed")
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5P_file_image_info_close() */
diff --git a/src/H5Pint.c b/src/H5Pint.c
index 08b8af6..46a06a0 100644
--- a/src/H5Pint.c
+++ b/src/H5Pint.c
@@ -51,6 +51,7 @@
typedef struct {
const H5P_genclass_t *parent; /* Pointer to parent class */
const char *name; /* Pointer to name to check */
+ H5P_genclass_t *new_class; /* Pointer to class during path traversal */
} H5P_check_class_t;
@@ -1358,11 +1359,11 @@ H5P_access_class(H5P_genclass_t *pclass, H5P_class_mod_t mod)
/*--------------------------------------------------------------------------
NAME
- H5P_check_class
+ H5P_open_class_path_cb
PURPOSE
Internal callback routine to check for duplicated names in parent class.
USAGE
- int H5P_check_class(obj, id, key)
+ int H5P_open_class_path_cb(obj, id, key)
H5P_genclass_t *obj; IN: Pointer to class
hid_t id; IN: ID of object being looked at
const void *key; IN: Pointer to information used to compare
@@ -1378,27 +1379,29 @@ H5P_access_class(H5P_genclass_t *pclass, H5P_class_mod_t mod)
REVISION LOG
--------------------------------------------------------------------------*/
static int
-H5P_check_class(void *_obj, hid_t UNUSED id, void *_key)
+H5P_open_class_path_cb(void *_obj, hid_t UNUSED id, void *_key)
{
- H5P_genclass_t *obj=(H5P_genclass_t *)_obj; /* Pointer to the class for this ID */
- const H5P_check_class_t *key=(const H5P_check_class_t *)_key; /* Pointer to key information for comparison */
- int ret_value=0; /* Return value */
+ H5P_genclass_t *obj = (H5P_genclass_t *)_obj; /* Pointer to the class for this ID */
+ H5P_check_class_t *key = (H5P_check_class_t *)_key; /* Pointer to key information for comparison */
+ int ret_value = 0; /* Return value */
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(obj);
- HDassert(H5I_GENPROP_CLS==H5I_get_type(id));
+ HDassert(H5I_GENPROP_CLS == H5I_get_type(id));
HDassert(key);
/* Check if the class object has the same parent as the new class */
- if(obj->parent==key->parent) {
+ if(obj->parent == key->parent) {
/* Check if they have the same name */
- if(HDstrcmp(obj->name,key->name)==0)
- ret_value=1; /* Indicate a match */
+ if(HDstrcmp(obj->name, key->name) == 0) {
+ key->new_class = obj;
+ ret_value = 1; /* Indicate a match */
+ } /* end if */
} /* end if */
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5P_check_class() */
+} /* end H5P_open_class_path_cb() */
/*--------------------------------------------------------------------------
@@ -4555,8 +4558,8 @@ H5P_open_class_path(const char *path)
char *curr_name; /* Pointer to current component of path name */
char *delimit; /* Pointer to path delimiter during traversal */
H5P_genclass_t *curr_class; /* Pointer to class during path traversal */
- H5P_genclass_t *ret_value; /* Return value */
H5P_check_class_t check_info; /* Structure to hold the information for checking duplicate names */
+ H5P_genclass_t *ret_value; /* Return value */
FUNC_ENTER_NOAPI_NOINIT
@@ -4569,20 +4572,24 @@ H5P_open_class_path(const char *path)
/* Find the generic property class with this full path */
curr_name = tmp_path;
curr_class = NULL;
- while((delimit=HDstrchr(curr_name,'/'))!=NULL) {
+ while(NULL != (delimit = HDstrchr(curr_name, '/'))) {
/* Change the delimiter to terminate the string */
- *delimit='\0';
+ *delimit = '\0';
/* Set up the search structure */
- check_info.parent=curr_class;
- check_info.name=curr_name;
+ check_info.parent = curr_class;
+ check_info.name = curr_name;
+ check_info.new_class = NULL;
/* Find the class with this name & parent by iterating over the open classes */
- if(NULL == (curr_class = (H5P_genclass_t *)H5I_search(H5I_GENPROP_CLS, H5P_check_class, &check_info, FALSE)))
- HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, NULL, "can't locate class")
+ if(H5I_iterate(H5I_GENPROP_CLS, H5P_open_class_path_cb, &check_info, FALSE) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_BADITER, NULL, "can't iterate over classes")
+ else if(NULL == check_info.new_class)
+ HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, NULL, "can't locate class")
/* Advance the pointer in the path to the start of the next component */
- curr_name=delimit+1;
+ curr_class = check_info.new_class;
+ curr_name = delimit + 1;
} /* end while */
/* Should be pointing to the last component in the path name now... */
@@ -4590,13 +4597,16 @@ H5P_open_class_path(const char *path)
/* Set up the search structure */
check_info.parent = curr_class;
check_info.name = curr_name;
+ check_info.new_class = NULL;
/* Find the class with this name & parent by iterating over the open classes */
- if(NULL == (curr_class = (H5P_genclass_t *)H5I_search(H5I_GENPROP_CLS, H5P_check_class, &check_info, FALSE)))
+ if(H5I_iterate(H5I_GENPROP_CLS, H5P_open_class_path_cb, &check_info, FALSE) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_BADITER, NULL, "can't iterate over classes")
+ else if(NULL == check_info.new_class)
HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, NULL, "can't locate class")
/* Copy it */
- if(NULL == (ret_value = H5P_copy_pclass(curr_class)))
+ if(NULL == (ret_value = H5P_copy_pclass(check_info.new_class)))
HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, NULL, "can't copy property class")
done:
@@ -4604,7 +4614,7 @@ done:
H5MM_xfree(tmp_path);
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5P_open_class_path() */
+} /* H5P_open_class_path() */
/*--------------------------------------------------------------------------
diff --git a/src/H5Pocpl.c b/src/H5Pocpl.c
index 217d0ba..217d0ba 100755..100644
--- a/src/H5Pocpl.c
+++ b/src/H5Pocpl.c
diff --git a/src/H5Pocpypl.c b/src/H5Pocpypl.c
index af50d80..23f8e4b 100755..100644
--- a/src/H5Pocpypl.c
+++ b/src/H5Pocpypl.c
@@ -35,7 +35,9 @@
/***********/
#include "H5private.h" /* Generic Functions */
#include "H5Eprivate.h" /* Error handling */
+#include "H5FLprivate.h" /* Free Lists */
#include "H5Iprivate.h" /* IDs */
+#include "H5MMprivate.h" /* Memory management */
#include "H5Ppkg.h" /* Property lists */
@@ -47,7 +49,13 @@
/* Definitions for copy options */
#define H5O_CPY_OPTION_SIZE sizeof(unsigned)
#define H5O_CPY_OPTION_DEF 0
-
+/* Definitions for merge committed dtype list */
+#define H5O_CPY_MERGE_COMM_DT_LIST_SIZE sizeof(char *)
+#define H5O_CPY_MERGE_COMM_DT_LIST_DEF NULL
+#define H5O_CPY_MERGE_COMM_DT_LIST_CMP H5P_ocpy_merge_comm_dt_list_cmp
+/* Definitions for callback function when completing the search for a matching committed datatype from the committed dtype list */
+#define H5O_CPY_MCDT_SEARCH_CB_SIZE sizeof(H5O_mcdt_cb_info_t)
+#define H5O_CPY_MCDT_SEARCH_CB_DEF {NULL,NULL}
/******************/
/* Local Typedefs */
@@ -63,8 +71,17 @@
/* Local Prototypes */
/********************/
+/* General routines */
+static H5O_copy_dtype_merge_list_t *H5P_free_merge_comm_dtype_list(H5O_copy_dtype_merge_list_t *dt_list);
+
/* Property class callbacks */
static herr_t H5P_ocpy_reg_prop(H5P_genclass_t *pclass);
+static herr_t H5P_ocpy_copy(hid_t dst_plist_id, hid_t src_plist_id,
+ void *copy_data);
+static herr_t H5P_ocpy_close(hid_t ocpypl_id, void *close_data);
+
+/* Property callbacks */
+static int H5P_ocpy_merge_comm_dt_list_cmp(const void *value1, const void *value2, size_t size);
/*********************/
@@ -80,9 +97,9 @@ const H5P_libclass_t H5P_CLS_OCPY[1] = {{
H5P_ocpy_reg_prop, /* Default property registration routine */
NULL, /* Class creation callback */
NULL, /* Class creation callback info */
- NULL, /* Class copy callback */
+ H5P_ocpy_copy, /* Class copy callback */
NULL, /* Class copy callback info */
- NULL, /* Class close callback */
+ H5P_ocpy_close, /* Class close callback */
NULL /* Class close callback info */
}};
@@ -96,6 +113,9 @@ const H5P_libclass_t H5P_CLS_OCPY[1] = {{
/* Local Variables */
/*******************/
+/* Declare a free list to manage the H5O_copy_dtype_merge_list_t struct */
+H5FL_DEFINE(H5O_copy_dtype_merge_list_t);
+
/*-------------------------------------------------------------------------
@@ -109,10 +129,12 @@ const H5P_libclass_t H5P_CLS_OCPY[1] = {{
* October 31, 2006
*-------------------------------------------------------------------------
*/
-herr_t
+static herr_t
H5P_ocpy_reg_prop(H5P_genclass_t *pclass)
{
unsigned ocpy_option = H5O_CPY_OPTION_DEF; /* Default object copy flags */
+ H5O_copy_dtype_merge_list_t *merge_comm_dtype_list = H5O_CPY_MERGE_COMM_DT_LIST_DEF; /* Default merge committed dtype list */
+ H5O_mcdt_cb_info_t mcdt_cb = H5O_CPY_MCDT_SEARCH_CB_DEF; /* Default callback before searching the global list of committed datatypes at destination */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
@@ -121,12 +143,222 @@ H5P_ocpy_reg_prop(H5P_genclass_t *pclass)
if(H5P_register_real(pclass, H5O_CPY_OPTION_NAME, H5O_CPY_OPTION_SIZE, &ocpy_option, NULL, NULL, NULL, NULL, NULL, NULL, NULL) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
+ /* Register merge named dtype list property */
+ if(H5P_register_real(pclass, H5O_CPY_MERGE_COMM_DT_LIST_NAME, H5O_CPY_MERGE_COMM_DT_LIST_SIZE, &merge_comm_dtype_list, NULL, NULL, NULL, NULL, NULL, H5O_CPY_MERGE_COMM_DT_LIST_CMP, NULL) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
+
+ /* Register property for callback when completing the search for a matching named datatype from the named dtype list */
+ if(H5P_register_real(pclass, H5O_CPY_MCDT_SEARCH_CB_NAME, H5O_CPY_MCDT_SEARCH_CB_SIZE, &mcdt_cb, NULL, NULL, NULL, NULL, NULL, NULL, NULL) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
+
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5P_ocpy_reg_prop() */
/*-------------------------------------------------------------------------
+ * Function: H5P_ocpy_copy
+ *
+ * Purpose: Callback routine which is called whenever any object
+ * copy property list is copied. This routine copies
+ * the properties from the old list to the new list.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Neil Fortner
+ * Friday, October 28, 2011
+ *
+ *-------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static herr_t
+H5P_ocpy_copy(hid_t dst_plist_id, hid_t src_plist_id, void UNUSED *copy_data)
+{
+ H5O_copy_dtype_merge_list_t *src_dt_list, *dst_dt_list = NULL; /* Source & destination merge named datatype lists */
+ H5O_copy_dtype_merge_list_t *dst_dt_list_tail = NULL, *tmp_dt_list = NULL; /* temporary merge named datatype lists */
+ H5P_genplist_t *src_plist; /* Pointer to source property list */
+ H5P_genplist_t *dst_plist; /* Pointer to destination property list */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ /* Verify property list IDs */
+ if(NULL == (dst_plist = (H5P_genplist_t *)H5I_object(dst_plist_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an object copy property list")
+ if(NULL == (src_plist = (H5P_genplist_t *)H5I_object(src_plist_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an object copy property list")
+
+ /* Get the merge committed dtype list property from the old property list */
+ if(H5P_get(src_plist, H5O_CPY_MERGE_COMM_DT_LIST_NAME, &src_dt_list) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get merge named dtype list")
+
+ /* Make copy of merge committed dtype list */
+ while(src_dt_list) {
+ /* Copy src_dt_list */
+ if(NULL == (tmp_dt_list = H5FL_CALLOC(H5O_copy_dtype_merge_list_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+ if(NULL == (tmp_dt_list->path = H5MM_strdup(src_dt_list->path)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+
+ /* Add copied node to dest dtype list */
+ if(dst_dt_list_tail) {
+ dst_dt_list_tail->next = tmp_dt_list;
+ dst_dt_list_tail = tmp_dt_list;
+ } /* end if */
+ else {
+ dst_dt_list = tmp_dt_list;
+ dst_dt_list_tail = tmp_dt_list;
+ } /* end else */
+ tmp_dt_list = NULL;
+
+ /* Advance src_dt_list pointer */
+ src_dt_list = src_dt_list->next;
+ } /* end while */
+
+ /* Set the merge named dtype list property for the destination property list
+ */
+ if(H5P_set(dst_plist, H5O_CPY_MERGE_COMM_DT_LIST_NAME, &dst_dt_list) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set merge committed dtype list")
+
+done:
+ if(ret_value < 0) {
+ dst_dt_list = H5P_free_merge_comm_dtype_list(dst_dt_list);
+ if(tmp_dt_list) {
+ tmp_dt_list->path = (char *)H5MM_xfree(tmp_dt_list->path);
+ tmp_dt_list = H5FL_FREE(H5O_copy_dtype_merge_list_t, tmp_dt_list);
+ } /* end if */
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5P_ocpy_copy() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5P_ocpy_close
+ *
+ * Purpose: Callback routine which is called whenever any object copy
+ * property list is closed. This routine performs any generic
+ * cleanup needed on the properties the library put into the
+ * list.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Neil Fortner
+ * Friday, October 28, 2011
+ *
+ *-------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static herr_t
+H5P_ocpy_close(hid_t ocpypl_id, void UNUSED *close_data)
+{
+ H5O_copy_dtype_merge_list_t *dt_list; /* Merge named datatype list */
+ H5P_genplist_t *plist; /* Property list */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ /* Check arguments */
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object(ocpypl_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an object copy property list")
+
+ /* Get the merge named dtype list property from the old property list */
+ if(H5P_get(plist, H5O_CPY_MERGE_COMM_DT_LIST_NAME, &dt_list) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get merge named dtype list")
+
+ /* Free the merge named dtype list */
+ dt_list = H5P_free_merge_comm_dtype_list(dt_list);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5P_ocpy_close() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5P_ocpy_merge_comm_dt_list_cmp
+ *
+ * Purpose: Callback routine which is called whenever the merge
+ * named dtype property in the object copy property list
+ * is compared.
+ *
+ * Return: positive if VALUE1 is greater than VALUE2, negative if
+ * VALUE2 is greater than VALUE1 and zero if VALUE1 and
+ * VALUE2 are equal.
+ *
+ * Programmer: Neil Fortner
+ * Friday, October 28, 2011
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+H5P_ocpy_merge_comm_dt_list_cmp(const void *_dt_list1, const void *_dt_list2,
+ size_t UNUSED size)
+{
+ const H5O_copy_dtype_merge_list_t *dt_list1 = *(H5O_copy_dtype_merge_list_t * const *)_dt_list1, /* Create local aliases for values */
+ *dt_list2 = *(H5O_copy_dtype_merge_list_t * const *)_dt_list2;
+ herr_t ret_value = 0; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ /* Sanity check */
+ HDassert(_dt_list1);
+ HDassert(_dt_list2);
+ HDassert(size == sizeof(H5O_copy_dtype_merge_list_t *));
+
+ /* Walk through the lists, comparing each path. For the lists to be the
+ * same, the paths must be in the same order. */
+ while(dt_list1 && dt_list2) {
+ /* Compare paths */
+ ret_value = HDstrcmp(dt_list1->path, dt_list2->path);
+ if(ret_value != 0) HGOTO_DONE(ret_value)
+
+ /* Advance to next node */
+ dt_list1 = dt_list1->next;
+ dt_list2 = dt_list2->next;
+ } /* end while */
+
+ /* Check if one list is longer than the other */
+ if(dt_list1) HGOTO_DONE(1)
+ if(dt_list2) HGOTO_DONE(-1)
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5P_ocpy_merge_comm_dt_list_cmp() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5P_free_merge_comm_dtype_list
+ *
+ * Purpose: Frees the provided merge named dtype list
+ *
+ * Return: NULL
+ *
+ * Programmer: Neil Fortner
+ * October 27, 2011
+ *-------------------------------------------------------------------------
+ */
+static H5O_copy_dtype_merge_list_t *
+H5P_free_merge_comm_dtype_list(H5O_copy_dtype_merge_list_t *dt_list)
+{
+ H5O_copy_dtype_merge_list_t *tmp_node;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ /* Free the list */
+ while(dt_list) {
+ tmp_node = dt_list->next;
+ (void)H5MM_xfree(dt_list->path);
+ (void)H5FL_FREE(H5O_copy_dtype_merge_list_t, dt_list);
+ dt_list = tmp_node;
+ } /* end while */
+
+ FUNC_LEAVE_NOAPI(NULL);
+} /* H5P_free_merge_comm_dtype_list */
+
+
+/*-------------------------------------------------------------------------
* Function: H5Pset_copy_object
*
* Purpose: Set properties when copying an object (group, dataset, and datatype)
@@ -207,3 +439,210 @@ done:
FUNC_LEAVE_API(ret_value)
} /* end H5Pget_copy_object() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5Padd_merge_committed_dtype_path
+ *
+ * Purpose: Adds path to the list of paths to search first in the
+ * target file when merging committed datatypes during H5Ocopy
+ * (i.e. when using the H5O_COPY_MERGE_COMMITTED_DTYPE_FLAG flag
+ * as set by H5Pset_copy_object). If the source named
+ * dataype is not found in the list of paths created by this
+ * function, the entire file will be searched.
+ *
+ * Usage: H5Padd_merge_committed_dtype_path(plist_id, path)
+ * hid_t plist_id; IN: Property list to copy object
+ * const char *path; IN: Path to add to list
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Neil Fortner
+ * October 27, 2011
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Padd_merge_committed_dtype_path(hid_t plist_id, const char *path)
+{
+ H5P_genplist_t *plist; /* Property list pointer */
+ H5O_copy_dtype_merge_list_t *old_list; /* Merge committed dtype list currently present */
+ H5O_copy_dtype_merge_list_t *new_obj = NULL; /* New object to add to list */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE2("e", "i*s", plist_id, path);
+
+ /* Check parameters */
+ if(!path)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no path specified")
+
+ /* Get the plist structure */
+ if(NULL == (plist = H5P_object_verify(plist_id, H5P_OBJECT_COPY)))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
+
+ /* Get dtype list */
+ if(H5P_get(plist, H5O_CPY_MERGE_COMM_DT_LIST_NAME, &old_list) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get merge named dtype list")
+
+ /* Add the new path to the list */
+ if(NULL == (new_obj = H5FL_CALLOC(H5O_copy_dtype_merge_list_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+ if(NULL == (new_obj->path = H5MM_strdup(path)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+ new_obj->next = old_list;
+
+ /* Update the list stored in the property list */
+ if(H5P_set(plist, H5O_CPY_MERGE_COMM_DT_LIST_NAME, &new_obj) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set merge named dtype list")
+
+done:
+ if(ret_value < 0)
+ if(new_obj) {
+ new_obj->path = (char *)H5MM_xfree(new_obj->path);
+ new_obj = H5FL_FREE(H5O_copy_dtype_merge_list_t, new_obj);
+ } /* end if */
+
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Padd_merge_committed_dtype_path() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Pfree_merge_committed_dtype_paths
+ *
+ * Purpose: Frees and clears the list of paths created by
+ * H5Padd_merge_committed_dtype_path. A new list may then be
+ * created by calling H5Padd_merge_committed_dtype_path again.
+ *
+ * Usage: H5Pfree_merge_committed_dtype_paths(plist_id)
+ * hid_t plist_id; IN: Property list to copy object
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Neil Fortner
+ * October 27, 2011
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Pfree_merge_committed_dtype_paths(hid_t plist_id)
+{
+ H5P_genplist_t *plist; /* Property list pointer */
+ H5O_copy_dtype_merge_list_t *dt_list; /* Merge committed dtype list currently present */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE1("e", "i", plist_id);
+
+ /* Get the plist structure */
+ if(NULL == (plist = H5P_object_verify(plist_id, H5P_OBJECT_COPY)))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
+
+ /* Get dtype list */
+ if(H5P_get(plist, H5O_CPY_MERGE_COMM_DT_LIST_NAME, &dt_list) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get merge committed dtype list")
+
+ /* Free dtype list */
+ dt_list = H5P_free_merge_comm_dtype_list(dt_list);
+
+ /* Update the list stored in the property list (to NULL) */
+ if(H5P_set(plist, H5O_CPY_MERGE_COMM_DT_LIST_NAME, &dt_list) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set merge committed dtype list")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Pfree_merge_committed_dtype_paths() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Pset_mcdt_search_cb
+ *
+ * Purpose: Set the callback function when a matching committed datatype is not found
+ * from the list of paths stored in the object copy property list.
+ * H5Ocopy will invoke this callback before searching all committed datatypes
+ * at destination.
+ *
+ * Usage: H5Pset_mcdt_search_cb(plist_id, H5O_mcdt_search_cb_t func, void *op_data)
+ * hid_t plist_id; IN: Property list to copy object
+ * H5O_mcdt_search_cb_t func; IN: The callback function
+ * void *op_data; IN: The user data
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Vailin Choi; November 28, 2011
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Pset_mcdt_search_cb(hid_t plist_id, H5O_mcdt_search_cb_t func, void *op_data)
+{
+ H5P_genplist_t *plist; /* Property list pointer */
+ H5O_mcdt_cb_info_t cb_info; /* Callback info struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE3("e", "ix*x", plist_id, func, op_data);
+
+ /* Check if the callback function is NULL and the user data is non-NULL.
+ * This is almost certainly an error as the user data will not be used. */
+ if(!func && op_data)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "callback is NULL while user data is not")
+
+ /* Get the plist structure */
+ if(NULL == (plist = H5P_object_verify(plist_id, H5P_OBJECT_COPY)))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
+
+ /* Populate the callback info struct */
+ cb_info.func = func;
+ cb_info.user_data = op_data;
+
+ /* Set callback info */
+ if(H5P_set(plist, H5O_CPY_MCDT_SEARCH_CB_NAME, &cb_info) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set callback info")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Pset_mcdt_search_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Pget_mcdt_search_cb
+ *
+ * Purpose: Retrieves the callback function and user data from the specified
+ * object copy property list.
+ *
+ * Usage: H5Pget_mcdt_search_cb(plist_id, H5O_mcdt_search_cb_t *func, void **op_data)
+ * hid_t plist_id; IN: Property list to copy object
+ * H5O_mcdt_search_cb_t *func; OUT: The callback function
+ * void **op_data; OUT: The user data
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Vailin Choi; November 29, 2011
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Pget_mcdt_search_cb(hid_t plist_id, H5O_mcdt_search_cb_t *func, void **op_data)
+{
+ H5P_genplist_t *plist; /* Property list pointer */
+ H5O_mcdt_cb_info_t cb_info; /* Callback info struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE3("e", "i*x**x", plist_id, func, op_data);
+
+ /* Get the plist structure */
+ if(NULL == (plist = H5P_object_verify(plist_id, H5P_OBJECT_COPY)))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
+
+ /* Get callback info */
+ if(H5P_get(plist, H5O_CPY_MCDT_SEARCH_CB_NAME, &cb_info) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get callback info")
+
+ if(func)
+ *func = cb_info.func;
+
+ if(op_data)
+ *op_data = cb_info.user_data;
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Pget_mcdt_search_cb() */
+
diff --git a/src/H5Ppublic.h b/src/H5Ppublic.h
index 4c812cc..6cba897 100644
--- a/src/H5Ppublic.h
+++ b/src/H5Ppublic.h
@@ -30,6 +30,7 @@
#include "H5FDpublic.h"
#include "H5Ipublic.h"
#include "H5Lpublic.h"
+#include "H5Opublic.h"
#include "H5MMpublic.h"
#include "H5Tpublic.h"
#include "H5Zpublic.h"
@@ -326,6 +327,12 @@ H5_DLL herr_t H5Pget_libver_bounds(hid_t plist_id, H5F_libver_t *low,
H5F_libver_t *high);
H5_DLL herr_t H5Pset_elink_file_cache_size(hid_t plist_id, unsigned efc_size);
H5_DLL herr_t H5Pget_elink_file_cache_size(hid_t plist_id, unsigned *efc_size);
+H5_DLL herr_t H5Pset_file_image(hid_t fapl_id, void *buf_ptr, size_t buf_len);
+H5_DLL herr_t H5Pget_file_image(hid_t fapl_id, void **buf_ptr_ptr, size_t *buf_len_ptr);
+H5_DLL herr_t H5Pset_file_image_callbacks(hid_t fapl_id,
+ H5FD_file_image_callbacks_t *callbacks_ptr);
+H5_DLL herr_t H5Pget_file_image_callbacks(hid_t fapl_id,
+ H5FD_file_image_callbacks_t *callbacks_ptr);
/* Dataset creation property list (DCPL) routines */
H5_DLL herr_t H5Pset_layout(hid_t plist_id, H5D_layout_t layout);
@@ -432,6 +439,10 @@ H5_DLL herr_t H5Pget_elink_cb(hid_t lapl_id, H5L_elink_traverse_t *func, void **
/* Object copy property list (OCPYPL) routines */
H5_DLL herr_t H5Pset_copy_object(hid_t plist_id, unsigned crt_intmd);
H5_DLL herr_t H5Pget_copy_object(hid_t plist_id, unsigned *crt_intmd /*out*/);
+H5_DLL herr_t H5Padd_merge_committed_dtype_path(hid_t plist_id, const char *path);
+H5_DLL herr_t H5Pfree_merge_committed_dtype_paths(hid_t plist_id);
+H5_DLL herr_t H5Pset_mcdt_search_cb(hid_t plist_id, H5O_mcdt_search_cb_t func, void *op_data);
+H5_DLL herr_t H5Pget_mcdt_search_cb(hid_t plist_id, H5O_mcdt_search_cb_t *func, void **op_data);
/* Symbols defined for compatibility with previous versions of the HDF5 API.
*
diff --git a/src/H5SM.c b/src/H5SM.c
index 8c00d34..62efb50 100755..100644
--- a/src/H5SM.c
+++ b/src/H5SM.c
@@ -1099,7 +1099,7 @@ H5SM_try_share(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, unsigned defer_flags,
/* Set flags if this message was "written" without error and wasn't a
* 'defer' attempt; it is now either fully shared or "shareable".
*/
- if(mesg_flags && !(defer_flags & H5SM_DEFER)) {
+ if(mesg_flags) {
if(((H5O_shared_t *)mesg)->type == H5O_SHARE_TYPE_HERE)
*mesg_flags |= H5O_MSG_FLAG_SHAREABLE;
else {
@@ -1109,7 +1109,8 @@ H5SM_try_share(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, unsigned defer_flags,
} /* end if */
done:
- HDassert(!ret_value || ((H5O_shared_t *)mesg)->type == H5O_SHARE_TYPE_HERE
+ HDassert((ret_value != TRUE)
+ || ((H5O_shared_t *)mesg)->type == H5O_SHARE_TYPE_HERE
|| ((H5O_shared_t *)mesg)->type == H5O_SHARE_TYPE_SOHM);
#ifndef NDEBUG
/* If we previously deferred this operation, make sure the saved message
diff --git a/src/H5SMbtree2.c b/src/H5SMbtree2.c
index daa1e4f..daa1e4f 100755..100644
--- a/src/H5SMbtree2.c
+++ b/src/H5SMbtree2.c
diff --git a/src/H5SMpkg.h b/src/H5SMpkg.h
index 68dc484..68dc484 100755..100644
--- a/src/H5SMpkg.h
+++ b/src/H5SMpkg.h
diff --git a/src/H5SMprivate.h b/src/H5SMprivate.h
index d072434..d072434 100755..100644
--- a/src/H5SMprivate.h
+++ b/src/H5SMprivate.h
diff --git a/src/H5T.c b/src/H5T.c
index 392228b..b27b152 100644
--- a/src/H5T.c
+++ b/src/H5T.c
@@ -1450,7 +1450,8 @@ H5T_term_interface(void)
H5T_g.asoft = 0;
/* Unlock all datatypes, then free them */
- H5I_search(H5I_DATATYPE, H5T_unlock_cb, NULL, FALSE);
+ /* note that we are ignoring the return value from H5I_iterate() */
+ H5I_iterate(H5I_DATATYPE, H5T_unlock_cb, NULL, FALSE);
H5I_dec_type_ref(H5I_DATATYPE);
/* Reset all the datatype IDs */
diff --git a/src/H5Toh.c b/src/H5Toh.c
index 5878075..be853f1 100644
--- a/src/H5Toh.c
+++ b/src/H5Toh.c
@@ -77,7 +77,8 @@ const H5O_obj_class_t H5O_OBJ_DATATYPE[1] = {{
H5O_dtype_open, /* open an object of this class */
H5O_dtype_create, /* create an object of this class */
H5O_dtype_get_oloc, /* get an object header location for an object */
- NULL /* get the index & heap info for an object */
+ NULL, /* get the index & heap info for an object */
+ NULL /* flush an opened object of this class */
}};
diff --git a/src/H5VL.c b/src/H5VL.c
index 293711f..f821463 100644
--- a/src/H5VL.c
+++ b/src/H5VL.c
@@ -1920,8 +1920,7 @@ H5VL_attr_create(hid_t uid, const char *name, hid_t acpl_id, hid_t aapl_id)
id_type = H5I_get_type(uid);
/* Check id */
if(H5I_FILE_PUBLIC != id_type && H5I_GROUP_PUBLIC != id_type &&
- H5I_DATASET_PUBLIC != id_type && H5I_DATATYPE_PUBLIC != id_type &&
- H5I_ATTR_PUBLIC != id_type)
+ H5I_DATASET_PUBLIC != id_type && H5I_DATATYPE_PUBLIC != id_type)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a user ID")
/* get the ID struct */
diff --git a/src/H5err.txt b/src/H5err.txt
index 71d27a6..b4cb28b 100644
--- a/src/H5err.txt
+++ b/src/H5err.txt
@@ -220,6 +220,7 @@ MINOR, DSPACE, H5E_CANTCOMPARE, Can't compare objects
MINOR, PLIST, H5E_CANTGET, Can't get value
MINOR, PLIST, H5E_CANTSET, Can't set value
MINOR, PLIST, H5E_DUPCLASS, Duplicate class name in parent class
+MINOR, PLIST, H5E_SETDISALLOWED, Disallowed operation
# Link errors
MINOR, LINK, H5E_TRAVERSE, Link traversal failure
diff --git a/src/H5private.h b/src/H5private.h
index 77ceaca..0bb8e3e 100644
--- a/src/H5private.h
+++ b/src/H5private.h
@@ -151,7 +151,9 @@
#ifdef H5_HAVE_WIN32_API
+/* The following two defines must be before any windows headers are included */
#define WIN32_LEAN_AND_MEAN /* Exclude rarely-used stuff from Windows headers */
+#define NOGDI /* Exclude Graphic Display Interface macros */
#ifdef H5_HAVE_WINSOCK_H
#include <winsock2.h>
diff --git a/src/H5public.h b/src/H5public.h
index 1f44ff3..e36c0eb 100644
--- a/src/H5public.h
+++ b/src/H5public.h
@@ -75,10 +75,10 @@ extern "C" {
/* Version numbers */
#define H5_VERS_MAJOR 1 /* For major interface/format changes */
#define H5_VERS_MINOR 9 /* For minor interface/format changes */
-#define H5_VERS_RELEASE 112 /* For tweaks, bug-fixes, or development */
+#define H5_VERS_RELEASE 114 /* For tweaks, bug-fixes, or development */
#define H5_VERS_SUBRELEASE "" /* For pre-releases like snap0 */
/* Empty string for real releases. */
-#define H5_VERS_INFO "HDF5 library version: 1.9.112" /* Full version string */
+#define H5_VERS_INFO "HDF5 library version: 1.9.114" /* Full version string */
#define H5check() H5check_version(H5_VERS_MAJOR,H5_VERS_MINOR, \
H5_VERS_RELEASE)
diff --git a/src/H5win32defs.h b/src/H5win32defs.h
index 5f886d1..e9b87625 100644
--- a/src/H5win32defs.h
+++ b/src/H5win32defs.h
@@ -33,9 +33,7 @@ typedef __int64 h5_stat_size_t;
#define HDdup(F) _dup(F)
#define HDfdopen(N,S) _fdopen(N,S)
#define HDfileno(F) _fileno(F)
-#define HDfseek(F,O,W) _fseeki64(F,O,W)
#define HDfstat(F,B) _fstati64(F,B)
-#define HDftruncate(F,L) _chsize_s(F,L)
#define HDisatty(F) _isatty(F)
#define HDgetcwd(S,Z) _getcwd(S,Z)
#define HDgetdcwd(D,S,Z) _getdcwd(D,S,Z)
@@ -91,4 +89,8 @@ struct timezone {
* type cannot be cast as a ulong like other systems. */
#define HDpthread_self_ulong() ((unsigned long)GetCurrentThreadId())
+#ifndef H5_HAVE_MINGW
+#define HDftruncate(F,L) _chsize_s(F,L)
+#define HDfseek(F,O,W) _fseeki64(F,O,W)
+#endif
#endif /* H5_HAVE_WIN32_API */
diff --git a/src/Makefile.am b/src/Makefile.am
index fad0241..fad0241 100755..100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
diff --git a/src/Makefile.in b/src/Makefile.in
index c9c1089..6efe7c4 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -485,7 +485,7 @@ CHECK_CLEANFILES = *.chkexe *.chklog *.clog
# Add libtool shared library version numbers to the HDF5 library
# See libtool versioning documentation online.
LT_VERS_INTERFACE = 6
-LT_VERS_REVISION = 102
+LT_VERS_REVISION = 104
LT_VERS_AGE = 0
H5detect_CFLAGS = -g $(AM_CFLAGS)
diff --git a/src/hdf5.lnt b/src/hdf5.lnt
index 1d02039..1d02039 100755..100644
--- a/src/hdf5.lnt
+++ b/src/hdf5.lnt