summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorScot Breitenfeld <brtnfld@hdfgroup.org>2008-04-30 19:51:13 (GMT)
committerScot Breitenfeld <brtnfld@hdfgroup.org>2008-04-30 19:51:13 (GMT)
commitaec106e324ce20e5efb725c25a6a333c7970127b (patch)
tree234df369115a46b08037c5f385061cf58823e497 /src
parent5773fd34bc5adf59b4530d95ac9f0c0585902803 (diff)
downloadhdf5-aec106e324ce20e5efb725c25a6a333c7970127b.zip
hdf5-aec106e324ce20e5efb725c25a6a333c7970127b.tar.gz
hdf5-aec106e324ce20e5efb725c25a6a333c7970127b.tar.bz2
[svn-r14903] Undoing change committed in r14902.
Diffstat (limited to 'src')
-rw-r--r--src/H5Adeprec.c2
-rw-r--r--src/H5B2int.c6
-rw-r--r--src/H5D.c4
-rw-r--r--src/H5Dchunk.c1515
-rw-r--r--src/H5Dcompact.c91
-rw-r--r--src/H5Dcontig.c434
-rw-r--r--src/H5Ddeprec.c2
-rw-r--r--src/H5Defl.c196
-rw-r--r--src/H5Dfill.c12
-rw-r--r--src/H5Dint.c269
-rw-r--r--src/H5Dio.c3217
-rw-r--r--src/H5Distore.c409
-rw-r--r--src/H5Dmpio.c2658
-rw-r--r--src/H5Doh.c2
-rw-r--r--src/H5Dpkg.h338
-rw-r--r--src/H5Dprivate.h22
-rw-r--r--src/H5Dscatgath.c899
-rw-r--r--src/H5Dselect.c466
-rw-r--r--src/H5F.c41
-rw-r--r--src/H5FDmpi.h4
-rw-r--r--src/H5FDmpio.c188
-rw-r--r--src/H5FScache.c4
-rw-r--r--src/H5FSsection.c4
-rw-r--r--src/H5Fpkg.h1
-rw-r--r--src/H5Fprivate.h3
-rw-r--r--src/H5HFhdr.c2
-rw-r--r--src/H5HFiblock.c10
-rw-r--r--src/H5HFpkg.h2
-rw-r--r--src/H5HFstat.c9
-rw-r--r--src/H5Lexternal.c200
-rw-r--r--src/H5Odtype.c19
-rw-r--r--src/H5Pdxpl.c6
-rw-r--r--src/H5S.c273
-rw-r--r--src/H5Smpio.c14
-rw-r--r--src/H5Sprivate.h28
-rw-r--r--src/H5T.c2
-rw-r--r--src/H5Tconv.c6
-rw-r--r--src/H5Tprivate.h2
-rw-r--r--src/H5Vprivate.h20
-rw-r--r--src/H5config.h.in3
-rw-r--r--src/H5private.h44
-rw-r--r--src/H5public.h6
-rw-r--r--src/H5system.c98
-rwxr-xr-xsrc/Makefile.am4
-rw-r--r--src/Makefile.in35
45 files changed, 5634 insertions, 5936 deletions
diff --git a/src/H5Adeprec.c b/src/H5Adeprec.c
index 9f888c8..85cef2f 100644
--- a/src/H5Adeprec.c
+++ b/src/H5Adeprec.c
@@ -312,6 +312,8 @@ H5Aget_num_attrs(hid_t loc_id)
H5TRACE1("Is", "i", loc_id);
/* check arguments */
+ if(H5I_BADID == H5I_get_type(loc_id))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "bad location ID")
if(H5I_FILE == H5I_get_type(loc_id) || H5I_ATTR == H5I_get_type(loc_id))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "location is not valid for an attribute")
if(NULL == (obj = H5I_object(loc_id)))
diff --git a/src/H5B2int.c b/src/H5B2int.c
index 2625c63..eae1291 100644
--- a/src/H5B2int.c
+++ b/src/H5B2int.c
@@ -203,7 +203,7 @@ HDmemset(shared->page, 0, shared->node_size);
/* Compute size to store # of records in each node */
/* (uses leaf # of records because its the largest) */
- shared->max_nrec_size = (H5V_log2_gen((uint64_t)shared->node_info[0].max_nrec) + 7) / 8;
+ shared->max_nrec_size = H5V_limit_enc_size((uint64_t)shared->node_info[0].max_nrec);
HDassert(shared->max_nrec_size <= H5B2_SIZEOF_RECORDS_PER_NODE);
/* Initialize internal node info */
@@ -217,7 +217,7 @@ HDmemset(shared->page, 0, shared->node_size);
shared->node_info[u].cum_max_nrec = ((shared->node_info[u].max_nrec + 1) *
shared->node_info[u - 1].cum_max_nrec) + shared->node_info[u].max_nrec;
- shared->node_info[u].cum_max_nrec_size = (H5V_log2_gen((uint64_t)shared->node_info[u].cum_max_nrec) + 7) / 8;
+ shared->node_info[u].cum_max_nrec_size = H5V_limit_enc_size((uint64_t)shared->node_info[u].cum_max_nrec);
if((shared->node_info[u].nat_rec_fac = H5FL_fac_init(shared->type->nrec_size * shared->node_info[u].max_nrec)) == NULL)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't create node native key block factory")
@@ -576,7 +576,7 @@ H5B2_split_root(H5F_t *f, hid_t dxpl_id, H5B2_t *bt2, unsigned *bt2_flags_ptr)
shared->node_info[shared->depth].merge_nrec = (shared->node_info[shared->depth].max_nrec * shared->merge_percent) / 100;
shared->node_info[shared->depth].cum_max_nrec = ((shared->node_info[shared->depth].max_nrec + 1) *
shared->node_info[shared->depth - 1].cum_max_nrec) + shared->node_info[shared->depth].max_nrec;
- shared->node_info[shared->depth].cum_max_nrec_size = (H5V_log2_gen((uint64_t)shared->node_info[shared->depth].cum_max_nrec) + 7) / 8;
+ shared->node_info[shared->depth].cum_max_nrec_size = H5V_limit_enc_size((uint64_t)shared->node_info[shared->depth].cum_max_nrec);
if((shared->node_info[shared->depth].nat_rec_fac = H5FL_fac_init(shared->type->nrec_size * shared->node_info[shared->depth].max_nrec)) == NULL)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't create node native key block factory")
if((shared->node_info[shared->depth].node_ptr_fac = H5FL_fac_init(sizeof(H5B2_node_ptr_t) * (shared->node_info[shared->depth].max_nrec + 1))) == NULL)
diff --git a/src/H5D.c b/src/H5D.c
index 7153ea5..7fd03b3 100644
--- a/src/H5D.c
+++ b/src/H5D.c
@@ -625,7 +625,7 @@ H5Dget_create_plist(hid_t dset_id)
H5I_dec_ref(src_id);
H5I_dec_ref(dst_id);
if(bkg_buf)
- H5FL_BLK_FREE(type_conv, bkg_buf);
+ (void)H5FL_BLK_FREE(type_conv, bkg_buf);
HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "datatype conversion failed")
} /* end if */
@@ -633,7 +633,7 @@ H5Dget_create_plist(hid_t dset_id)
H5I_dec_ref(src_id);
H5I_dec_ref(dst_id);
if(bkg_buf)
- H5FL_BLK_FREE(type_conv, bkg_buf);
+ (void)H5FL_BLK_FREE(type_conv, bkg_buf);
} /* end if */
} /* end if */
diff --git a/src/H5Dchunk.c b/src/H5Dchunk.c
new file mode 100644
index 0000000..baaa5f1
--- /dev/null
+++ b/src/H5Dchunk.c
@@ -0,0 +1,1515 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the files COPYING and Copyright.html. COPYING can be found at the root *
+ * of the source code distribution tree; Copyright.html can be found at the *
+ * root level of an installed copy of the electronic HDF5 document set and *
+ * is linked from the top-level documents page. It can also be found at *
+ * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#define H5D_PACKAGE /*suppress error about including H5Dpkg */
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Dpkg.h" /* Dataset functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5FLprivate.h" /* Free Lists */
+#include "H5Iprivate.h" /* IDs */
+#ifdef H5_HAVE_PARALLEL
+#include "H5MMprivate.h" /* Memory management */
+#endif /* H5_HAVE_PARALLEL */
+#include "H5Vprivate.h" /* Vector and array functions */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+/* Default skip list height for storing list of chunks */
+#define H5D_DEFAULT_SKIPLIST_HEIGHT 8
+
+/* Macros for iterating over chunks to operate on */
+#define H5D_CHUNK_GET_FIRST_NODE(map) (map->use_single ? (H5SL_node_t *)(1) : H5SL_first(map->sel_chunks))
+#define H5D_CHUNK_GET_NODE_INFO(map, node) (map->use_single ? map->single_chunk_info : (H5D_chunk_info_t *)H5SL_item(node))
+#define H5D_CHUNK_GET_NEXT_NODE(map, node) (map->use_single ? (H5SL_node_t *)NULL : H5SL_next(node))
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+/* Chunked layout operation callbacks */
+static herr_t H5D_chunk_io_init(const H5D_io_info_t *io_info,
+ const H5D_type_info_t *type_info, hsize_t nelmts, const H5S_t *file_space,
+ const H5S_t *mem_space, H5D_chunk_map_t *fm);
+static herr_t H5D_chunk_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
+ hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space,
+ H5D_chunk_map_t *fm);
+static herr_t H5D_chunk_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
+ hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space,
+ H5D_chunk_map_t *fm);
+static herr_t H5D_chunk_io_term(const H5D_chunk_map_t *fm);
+
+/* "Null" layout operation callbacks */
+static ssize_t H5D_null_readvv(const H5D_io_info_t *io_info,
+ size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_len_arr[], hsize_t dset_offset_arr[],
+ size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[]);
+
+/* Helper routines */
+static herr_t H5D_free_chunk_info(void *item, void *key, void *opdata);
+static herr_t H5D_create_chunk_map_single(H5D_chunk_map_t *fm,
+ const H5D_io_info_t *io_info);
+static herr_t H5D_create_chunk_file_map_hyper(H5D_chunk_map_t *fm,
+ const H5D_io_info_t *io_info);
+static herr_t H5D_create_chunk_mem_map_hyper(const H5D_chunk_map_t *fm);
+static herr_t H5D_chunk_file_cb(void *elem, hid_t type_id, unsigned ndims,
+ const hsize_t *coords, void *fm);
+static herr_t H5D_chunk_mem_cb(void *elem, hid_t type_id, unsigned ndims,
+ const hsize_t *coords, void *fm);
+
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+/* Compact storage layout I/O ops */
+const H5D_layout_ops_t H5D_LOPS_CHUNK[1] = {{
+ H5D_chunk_io_init,
+ H5D_chunk_read,
+ H5D_chunk_write,
+#ifdef H5_HAVE_PARALLEL
+ H5D_chunk_collective_read,
+ H5D_chunk_collective_write,
+#endif /* H5_HAVE_PARALLEL */
+ NULL,
+ NULL,
+ H5D_chunk_io_term
+}};
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+/* "null" storage layout I/O ops */
+const H5D_layout_ops_t H5D_LOPS_NULL[1] = {{
+ NULL,
+ NULL,
+ NULL,
+#ifdef H5_HAVE_PARALLEL
+ NULL,
+ NULL,
+#endif /* H5_HAVE_PARALLEL */
+ H5D_null_readvv,
+ NULL,
+ NULL
+}};
+
+/* Declare a free list to manage the H5D_chunk_info_t struct */
+H5FL_DEFINE(H5D_chunk_info_t);
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_chunk_io_init
+ *
+ * Purpose: Performs initialization before any sort of I/O on the raw data
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, March 20, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_chunk_io_init(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
+ hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space,
+ H5D_chunk_map_t *fm)
+{
+ H5D_t *dataset = io_info->dset; /* Local pointer to dataset info */
+ const H5T_t *mem_type = type_info->mem_type; /* Local pointer to memory datatype */
+ H5S_t *tmp_mspace = NULL; /* Temporary memory dataspace */
+ hssize_t old_offset[H5O_LAYOUT_NDIMS]; /* Old selection offset */
+ htri_t file_space_normalized = FALSE; /* File dataspace was normalized */
+ hid_t f_tid = (-1); /* Temporary copy of file datatype for iteration */
+ hbool_t iter_init = FALSE; /* Selection iteration info has been initialized */
+ unsigned f_ndims; /* The number of dimensions of the file's dataspace */
+ int sm_ndims; /* The number of dimensions of the memory buffer's dataspace (signed) */
+ H5SL_node_t *curr_node; /* Current node in skip list */
+ H5S_sel_type fsel_type; /* Selection type on disk */
+ char bogus; /* "bogus" buffer to pass to selection iterator */
+ unsigned u; /* Local index variable */
+ hbool_t sel_hyper_flag;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_chunk_io_init)
+
+ /* Get layout for dataset */
+ fm->layout = &(dataset->shared->layout);
+ fm->nelmts = nelmts;
+
+ /* Check if the memory space is scalar & make equivalent memory space */
+ if((sm_ndims = H5S_GET_EXTENT_NDIMS(mem_space)) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get dimension number")
+ /* Set the number of dimensions for the memory dataspace */
+ H5_ASSIGN_OVERFLOW(fm->m_ndims, sm_ndims, int, unsigned);
+
+ /* Get dim number and dimensionality for each dataspace */
+ fm->f_ndims = f_ndims = dataset->shared->layout.u.chunk.ndims - 1;
+ if(H5S_get_simple_extent_dims(file_space, fm->f_dims, NULL) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get dimensionality")
+
+ /* Normalize hyperslab selections by adjusting them by the offset */
+ /* (It might be worthwhile to normalize both the file and memory dataspaces
+ * before any (contiguous, chunked, etc) file I/O operation, in order to
+ * speed up hyperslab calculations by removing the extra checks and/or
+ * additions involving the offset and the hyperslab selection -QAK)
+ */
+ if((file_space_normalized = H5S_hyper_normalize_offset((H5S_t *)file_space, old_offset)) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_BADSELECT, FAIL, "unable to normalize dataspace by offset")
+
+ /* Decide the number of chunks in each dimension*/
+ for(u=0; u<f_ndims; u++) {
+ /* Keep the size of the chunk dimensions as hsize_t for various routines */
+ fm->chunk_dim[u]=fm->layout->u.chunk.dim[u];
+
+ /* Round up to the next integer # of chunks, to accomodate partial chunks */
+ fm->chunks[u] = ((fm->f_dims[u]+dataset->shared->layout.u.chunk.dim[u])-1) / dataset->shared->layout.u.chunk.dim[u];
+ } /* end for */
+
+ /* Compute the "down" size of 'chunks' information */
+ if(H5V_array_down(f_ndims,fm->chunks,fm->down_chunks) < 0)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_BADVALUE, FAIL, "can't compute 'down' sizes")
+
+#ifdef H5_HAVE_PARALLEL
+ /* Calculate total chunk in file map*/
+ fm->select_chunk = NULL;
+ fm->total_chunks = 1;
+ for(u = 0; u < fm->f_ndims; u++)
+ fm->total_chunks = fm->total_chunks * fm->chunks[u];
+ if(io_info->using_mpi_vfd) {
+ H5_CHECK_OVERFLOW(fm->total_chunks, hsize_t, size_t);
+ if(NULL == (fm->select_chunk = (H5D_chunk_info_t **)H5MM_calloc((size_t)fm->total_chunks * sizeof(H5D_chunk_info_t *))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate chunk info")
+ } /* end if */
+#endif /* H5_HAVE_PARALLEL */
+
+
+ /* Initialize "last chunk" information */
+ fm->last_index = (hsize_t)-1;
+ fm->last_chunk_info = NULL;
+
+ /* Point at the dataspaces */
+ fm->file_space = file_space;
+ fm->mem_space = mem_space;
+
+ /* Special case for only one element in selection */
+ /* (usually appending a record) */
+ if(nelmts == 1
+#ifdef H5_HAVE_PARALLEL
+ && !(io_info->using_mpi_vfd)
+#endif /* H5_HAVE_PARALLEL */
+ ) {
+ /* Initialize skip list for chunk selections */
+ fm->sel_chunks = NULL;
+ fm->use_single = TRUE;
+
+ /* Initialize single chunk dataspace */
+ if(NULL == dataset->shared->cache.chunk.single_space) {
+ /* Make a copy of the dataspace for the dataset */
+ if((dataset->shared->cache.chunk.single_space = H5S_copy(file_space, TRUE, FALSE)) == NULL)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy file space")
+
+ /* Resize chunk's dataspace dimensions to size of chunk */
+ if(H5S_set_extent_real(dataset->shared->cache.chunk.single_space, fm->chunk_dim) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "can't adjust chunk dimensions")
+
+ /* Set the single chunk dataspace to 'all' selection */
+ if(H5S_select_all(dataset->shared->cache.chunk.single_space, TRUE) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTSELECT, FAIL, "unable to set all selection")
+ } /* end if */
+ fm->single_space = dataset->shared->cache.chunk.single_space;
+ HDassert(fm->single_space);
+
+ /* Allocate the single chunk information */
+ if(NULL == dataset->shared->cache.chunk.single_chunk_info) {
+ if(NULL == (dataset->shared->cache.chunk.single_chunk_info = H5FL_MALLOC(H5D_chunk_info_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate chunk info")
+ } /* end if */
+ fm->single_chunk_info = dataset->shared->cache.chunk.single_chunk_info;
+ HDassert(fm->single_chunk_info);
+
+ /* Reset chunk template information */
+ fm->mchunk_tmpl = NULL;
+
+ /* Set up chunk mapping for single element */
+ if(H5D_create_chunk_map_single(fm, io_info) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create chunk selections for single element")
+ } /* end if */
+ else {
+ /* Initialize skip list for chunk selections */
+ if(NULL == dataset->shared->cache.chunk.sel_chunks) {
+ if(NULL == (dataset->shared->cache.chunk.sel_chunks = H5SL_create(H5SL_TYPE_HSIZE, 0.5, (size_t)H5D_DEFAULT_SKIPLIST_HEIGHT)))
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTCREATE, FAIL, "can't create skip list for chunk selections")
+ } /* end if */
+ fm->sel_chunks = dataset->shared->cache.chunk.sel_chunks;
+ HDassert(fm->sel_chunks);
+
+ /* We are not using single element mode */
+ fm->use_single = FALSE;
+
+ /* Get type of selection on disk & in memory */
+ if((fsel_type = H5S_GET_SELECT_TYPE(file_space)) < H5S_SEL_NONE)
+ HGOTO_ERROR(H5E_DATASET, H5E_BADSELECT, FAIL, "unable to get type of selection")
+ if((fm->msel_type = H5S_GET_SELECT_TYPE(mem_space)) < H5S_SEL_NONE)
+ HGOTO_ERROR(H5E_DATASET, H5E_BADSELECT, FAIL, "unable to get type of selection")
+
+ /* If the selection is NONE or POINTS, set the flag to FALSE */
+ if(fsel_type == H5S_SEL_POINTS || fsel_type == H5S_SEL_NONE)
+ sel_hyper_flag = FALSE;
+ else
+ sel_hyper_flag = TRUE;
+
+ /* Check if file selection is a not a hyperslab selection */
+ if(sel_hyper_flag) {
+ /* Build the file selection for each chunk */
+ if(H5D_create_chunk_file_map_hyper(fm, io_info) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create file chunk selections")
+
+ /* Clean file chunks' hyperslab span "scratch" information */
+ curr_node = H5SL_first(fm->sel_chunks);
+ while(curr_node) {
+ H5D_chunk_info_t *chunk_info; /* Pointer chunk information */
+
+ /* Get pointer to chunk's information */
+ chunk_info = (H5D_chunk_info_t *)H5SL_item(curr_node);
+ HDassert(chunk_info);
+
+ /* Clean hyperslab span's "scratch" information */
+ if(H5S_hyper_reset_scratch(chunk_info->fspace) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "unable to reset span scratch info")
+
+ /* Get the next chunk node in the skip list */
+ curr_node = H5SL_next(curr_node);
+ } /* end while */
+ } /* end if */
+ else {
+ /* Create temporary datatypes for selection iteration */
+ if((f_tid = H5I_register(H5I_DATATYPE, H5T_copy(dataset->shared->type, H5T_COPY_ALL))) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register file datatype")
+
+ /* Spaces might not be the same shape, iterate over the file selection directly */
+ if(H5S_select_iterate(&bogus, f_tid, file_space, H5D_chunk_file_cb, fm) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create file chunk selections")
+
+ /* Reset "last chunk" info */
+ fm->last_index = (hsize_t)-1;
+ fm->last_chunk_info = NULL;
+ } /* end else */
+
+ /* Build the memory selection for each chunk */
+ if(sel_hyper_flag && H5S_select_shape_same(file_space, mem_space) == TRUE) {
+ /* Reset chunk template information */
+ fm->mchunk_tmpl = NULL;
+
+ /* If the selections are the same shape, use the file chunk information
+ * to generate the memory chunk information quickly.
+ */
+ if(H5D_create_chunk_mem_map_hyper(fm) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create memory chunk selections")
+ } /* end if */
+ else {
+ size_t elmt_size; /* Memory datatype size */
+
+ /* Make a copy of equivalent memory space */
+ if((tmp_mspace = H5S_copy(mem_space, TRUE, FALSE)) == NULL)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy memory space")
+
+ /* De-select the mem space copy */
+ if(H5S_select_none(tmp_mspace) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to de-select memory space")
+
+ /* Save chunk template information */
+ fm->mchunk_tmpl = tmp_mspace;
+
+ /* Create temporary datatypes for selection iteration */
+ if(f_tid < 0) {
+ if((f_tid = H5I_register(H5I_DATATYPE, H5T_copy(dataset->shared->type, H5T_COPY_ALL))) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register file datatype")
+ } /* end if */
+
+ /* Create selection iterator for memory selection */
+ if(0 == (elmt_size = H5T_get_size(mem_type)))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_BADSIZE, FAIL, "datatype size invalid")
+ if(H5S_select_iter_init(&(fm->mem_iter), mem_space, elmt_size) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator")
+ iter_init = TRUE; /* Selection iteration info has been initialized */
+
+ /* Spaces aren't the same shape, iterate over the memory selection directly */
+ if(H5S_select_iterate(&bogus, f_tid, file_space, H5D_chunk_mem_cb, fm) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create memory chunk selections")
+
+ /* Clean up hyperslab stuff, if necessary */
+ if(fm->msel_type != H5S_SEL_POINTS) {
+ /* Clean memory chunks' hyperslab span "scratch" information */
+ curr_node = H5SL_first(fm->sel_chunks);
+ while(curr_node) {
+ H5D_chunk_info_t *chunk_info; /* Pointer chunk information */
+
+ /* Get pointer to chunk's information */
+ chunk_info = (H5D_chunk_info_t *)H5SL_item(curr_node);
+ HDassert(chunk_info);
+
+ /* Clean hyperslab span's "scratch" information */
+ if(H5S_hyper_reset_scratch(chunk_info->mspace) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "unable to reset span scratch info")
+
+ /* Get the next chunk node in the skip list */
+ curr_node = H5SL_next(curr_node);
+ } /* end while */
+ } /* end if */
+ } /* end else */
+ } /* end else */
+
+done:
+ /* Release the [potentially partially built] chunk mapping information if an error occurs */
+ if(ret_value < 0) {
+ if(tmp_mspace && !fm->mchunk_tmpl) {
+ if(H5S_close(tmp_mspace) < 0)
+ HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "can't release memory chunk dataspace template")
+ } /* end if */
+
+ if(H5D_chunk_io_term(fm) < 0)
+ HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release chunk mapping")
+ } /* end if */
+
+ /* Reset the global dataspace info */
+ fm->file_space = NULL;
+ fm->mem_space = NULL;
+
+ if(iter_init) {
+ if(H5S_SELECT_ITER_RELEASE(&(fm->mem_iter)) < 0)
+ HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator")
+ } /* end if */
+ if(f_tid!=(-1)) {
+ if(H5I_dec_ref(f_tid) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't decrement temporary datatype ID")
+ } /* end if */
+ if(file_space_normalized) {
+ if(H5S_hyper_denormalize_offset((H5S_t *)file_space, old_offset) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_BADSELECT, FAIL, "unable to normalize dataspace by offset")
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_chunk_io_init() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5D_free_chunk_info
+ PURPOSE
+ Internal routine to destroy a chunk info node
+ USAGE
+ void H5D_free_chunk_info(chunk_info)
+ void *chunk_info; IN: Pointer to chunk info to destroy
+ RETURNS
+ No return value
+ DESCRIPTION
+ Releases all the memory for a chunk info node. Called by H5SL_free
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+static herr_t
+H5D_free_chunk_info(void *item, void UNUSED *key, void UNUSED *opdata)
+{
+ H5D_chunk_info_t *chunk_info = (H5D_chunk_info_t *)item;
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_free_chunk_info)
+
+ HDassert(chunk_info);
+
+ /* Close the chunk's file dataspace, if it's not shared */
+ if(!chunk_info->fspace_shared)
+ (void)H5S_close(chunk_info->fspace);
+ else
+ H5S_select_all(chunk_info->fspace, TRUE);
+
+ /* Close the chunk's memory dataspace, if it's not shared */
+ if(!chunk_info->mspace_shared)
+ (void)H5S_close(chunk_info->mspace);
+
+ /* Free the actual chunk info */
+ H5FL_FREE(H5D_chunk_info_t, chunk_info);
+
+ FUNC_LEAVE_NOAPI(0)
+} /* H5D_free_chunk_info() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_create_chunk_map_single
+ *
+ * Purpose: Create chunk selections when appending a single record
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, November 20, 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_create_chunk_map_single(H5D_chunk_map_t *fm, const H5D_io_info_t
+#ifndef H5_HAVE_PARALLEL
+ UNUSED
+#endif /* H5_HAVE_PARALLEL */
+ *io_info)
+{
+ H5D_chunk_info_t *chunk_info; /* Chunk information to insert into skip list */
+ hsize_t sel_start[H5O_LAYOUT_NDIMS]; /* Offset of low bound of file selection */
+ hsize_t sel_end[H5O_LAYOUT_NDIMS]; /* Offset of high bound of file selection */
+ unsigned u; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_create_chunk_map_single)
+
+ /* Sanity check */
+ HDassert(fm->f_ndims > 0);
+
+ /* Get coordinate for selection */
+ if(H5S_SELECT_BOUNDS(fm->file_space, sel_start, sel_end) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get file selection bound info")
+
+ /* Initialize the 'single chunk' file & memory chunk information */
+ chunk_info = fm->single_chunk_info;
+ chunk_info->chunk_points = 1;
+
+ /* Set chunk location & hyperslab size */
+ for(u = 0; u < fm->f_ndims; u++) {
+ HDassert(sel_start[u] == sel_end[u]);
+ chunk_info->coords[u] = (sel_start[u] / fm->layout->u.chunk.dim[u]) * fm->layout->u.chunk.dim[u];
+ } /* end for */
+ chunk_info->coords[fm->f_ndims] = 0;
+
+ /* Calculate the index of this chunk */
+ if(H5V_chunk_index(fm->f_ndims, chunk_info->coords, fm->layout->u.chunk.dim, fm->down_chunks, &chunk_info->index) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "can't get chunk index")
+
+ /* Copy selection for file's dataspace into chunk dataspace */
+ if(H5S_select_copy(fm->single_space, fm->file_space, FALSE) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy file selection")
+
+ /* Move selection back to have correct offset in chunk */
+ if(H5S_SELECT_ADJUST_U(fm->single_space, chunk_info->coords) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't adjust chunk selection")
+
+#ifdef H5_HAVE_PARALLEL
+ /* store chunk selection information */
+ if(io_info->using_mpi_vfd)
+ fm->select_chunk[chunk_info->index] = chunk_info;
+#endif /* H5_HAVE_PARALLEL */
+
+ /* Set the file dataspace for the chunk to the shared 'single' dataspace */
+ chunk_info->fspace = fm->single_space;
+
+ /* Indicate that the chunk's file dataspace is shared */
+ chunk_info->fspace_shared = TRUE;
+
+ /* Just point at the memory dataspace & selection */
+ /* (Casting away const OK -QAK) */
+ chunk_info->mspace = (H5S_t *)fm->mem_space;
+
+ /* Indicate that the chunk's memory dataspace is shared */
+ chunk_info->mspace_shared = TRUE;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_create_chunk_map_single() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_create_chunk_file_map_hyper
+ *
+ * Purpose: Create all chunk selections in file.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, May 29, 2003
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_create_chunk_file_map_hyper(H5D_chunk_map_t *fm, const H5D_io_info_t
+#ifndef H5_HAVE_PARALLEL
+ UNUSED
+#endif /* H5_HAVE_PARALLEL */
+ *io_info)
+{
+ hsize_t sel_start[H5O_LAYOUT_NDIMS]; /* Offset of low bound of file selection */
+ hsize_t sel_end[H5O_LAYOUT_NDIMS]; /* Offset of high bound of file selection */
+ hsize_t sel_points; /* Number of elements in file selection */
+ hsize_t start_coords[H5O_LAYOUT_NDIMS]; /* Starting coordinates of selection */
+ hsize_t coords[H5O_LAYOUT_NDIMS]; /* Current coordinates of chunk */
+ hsize_t end[H5O_LAYOUT_NDIMS]; /* Current coordinates of chunk */
+ hsize_t chunk_index; /* Index of chunk */
+ int curr_dim; /* Current dimension to increment */
+ unsigned u; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_create_chunk_file_map_hyper)
+
+ /* Sanity check */
+ assert(fm->f_ndims>0);
+
+ /* Get number of elements selected in file */
+ sel_points = fm->nelmts;
+
+ /* Get bounding box for selection (to reduce the number of chunks to iterate over) */
+ if(H5S_SELECT_BOUNDS(fm->file_space, sel_start, sel_end) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get file selection bound info")
+
+ /* Set initial chunk location & hyperslab size */
+
+ for(u=0; u<fm->f_ndims; u++) {
+ start_coords[u]=(sel_start[u]/fm->layout->u.chunk.dim[u])*fm->layout->u.chunk.dim[u];
+ coords[u]=start_coords[u];
+ end[u]=(coords[u]+fm->chunk_dim[u])-1;
+ } /* end for */
+
+
+ /* Calculate the index of this chunk */
+ if(H5V_chunk_index(fm->f_ndims,coords,fm->layout->u.chunk.dim,fm->down_chunks,&chunk_index) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "can't get chunk index")
+
+ /* Iterate through each chunk in the dataset */
+ while(sel_points) {
+ /* Check for intersection of temporary chunk and file selection */
+ /* (Casting away const OK - QAK) */
+ if(H5S_hyper_intersect_block((H5S_t *)fm->file_space,coords,end)==TRUE) {
+ H5S_t *tmp_fchunk; /* Temporary file dataspace */
+ H5D_chunk_info_t *new_chunk_info; /* chunk information to insert into skip list */
+ hssize_t schunk_points; /* Number of elements in chunk selection */
+
+ /* Create "temporary" chunk for selection operations (copy file space) */
+ if((tmp_fchunk = H5S_copy(fm->file_space, TRUE, FALSE)) == NULL)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy memory space")
+
+ /* Make certain selections are stored in span tree form (not "optimized hyperslab" or "all") */
+ if(H5S_hyper_convert(tmp_fchunk) < 0) {
+ (void)H5S_close(tmp_fchunk);
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to convert selection to span trees")
+ } /* end if */
+
+ /* "AND" temporary chunk and current chunk */
+ if(H5S_select_hyperslab(tmp_fchunk,H5S_SELECT_AND,coords,NULL,fm->chunk_dim,NULL) < 0) {
+ (void)H5S_close(tmp_fchunk);
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't create chunk selection")
+ } /* end if */
+
+ /* Resize chunk's dataspace dimensions to size of chunk */
+ if(H5S_set_extent_real(tmp_fchunk,fm->chunk_dim) < 0) {
+ (void)H5S_close(tmp_fchunk);
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't adjust chunk dimensions")
+ } /* end if */
+
+ /* Move selection back to have correct offset in chunk */
+ if(H5S_SELECT_ADJUST_U(tmp_fchunk, coords) < 0) {
+ (void)H5S_close(tmp_fchunk);
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't adjust chunk selection")
+ } /* end if */
+
+ /* Add temporary chunk to the list of chunks */
+
+ /* Allocate the file & memory chunk information */
+ if (NULL==(new_chunk_info = H5FL_MALLOC (H5D_chunk_info_t))) {
+ (void)H5S_close(tmp_fchunk);
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate chunk info")
+ } /* end if */
+
+ /* Initialize the chunk information */
+
+ /* Set the chunk index */
+ new_chunk_info->index=chunk_index;
+
+#ifdef H5_HAVE_PARALLEL
+ /* store chunk selection information */
+ if(io_info->using_mpi_vfd)
+ fm->select_chunk[chunk_index] = new_chunk_info;
+#endif /* H5_HAVE_PARALLEL */
+
+ /* Set the file chunk dataspace */
+ new_chunk_info->fspace = tmp_fchunk;
+ new_chunk_info->fspace_shared = FALSE;
+
+ /* Set the memory chunk dataspace */
+ new_chunk_info->mspace=NULL;
+ new_chunk_info->mspace_shared = FALSE;
+
+ /* Copy the chunk's coordinates */
+ for(u=0; u<fm->f_ndims; u++)
+ new_chunk_info->coords[u]=coords[u];
+ new_chunk_info->coords[fm->f_ndims]=0;
+
+ /* Insert the new chunk into the skip list */
+ if(H5SL_insert(fm->sel_chunks,new_chunk_info,&new_chunk_info->index) < 0) {
+ H5D_free_chunk_info(new_chunk_info,NULL,NULL);
+ HGOTO_ERROR(H5E_DATASPACE,H5E_CANTINSERT,FAIL,"can't insert chunk into skip list")
+ } /* end if */
+
+ /* Get number of elements selected in chunk */
+ if((schunk_points=H5S_GET_SELECT_NPOINTS(tmp_fchunk)) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get file selection # of elements")
+ H5_ASSIGN_OVERFLOW(new_chunk_info->chunk_points,schunk_points,hssize_t,size_t);
+
+ /* Decrement # of points left in file selection */
+ sel_points-=(hsize_t)schunk_points;
+
+ /* Leave if we are done */
+ if(sel_points==0)
+ HGOTO_DONE(SUCCEED)
+ assert(sel_points>0);
+ } /* end if */
+
+ /* Increment chunk index */
+ chunk_index++;
+
+ /* Set current increment dimension */
+ curr_dim=(int)fm->f_ndims-1;
+
+ /* Increment chunk location in fastest changing dimension */
+ H5_CHECK_OVERFLOW(fm->chunk_dim[curr_dim],hsize_t,hssize_t);
+ coords[curr_dim]+=fm->chunk_dim[curr_dim];
+ end[curr_dim]+=fm->chunk_dim[curr_dim];
+
+ /* Bring chunk location back into bounds, if necessary */
+ if(coords[curr_dim]>sel_end[curr_dim]) {
+ do {
+ /* Reset current dimension's location to 0 */
+ coords[curr_dim]=start_coords[curr_dim]; /*lint !e771 The start_coords will always be initialized */
+ end[curr_dim]=(coords[curr_dim]+(hssize_t)fm->chunk_dim[curr_dim])-1;
+
+ /* Decrement current dimension */
+ curr_dim--;
+
+ /* Increment chunk location in current dimension */
+ coords[curr_dim]+=fm->chunk_dim[curr_dim];
+ end[curr_dim]=(coords[curr_dim]+fm->chunk_dim[curr_dim])-1;
+ } while(coords[curr_dim]>sel_end[curr_dim]);
+
+ /* Re-Calculate the index of this chunk */
+ if(H5V_chunk_index(fm->f_ndims,coords,fm->layout->u.chunk.dim,fm->down_chunks,&chunk_index) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "can't get chunk index")
+ } /* end if */
+ } /* end while */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_create_chunk_file_map_hyper() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_create_chunk_mem_map_hyper
+ *
+ * Purpose: Create all chunk selections in memory by copying the file
+ * chunk selections and adjusting their offsets to be correct
+ * for the memory.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, May 29, 2003
+ *
+ * Assumptions: That the file and memory selections are the same shape.
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_create_chunk_mem_map_hyper(const H5D_chunk_map_t *fm)
+{
+ H5SL_node_t *curr_node; /* Current node in skip list */
+ hsize_t file_sel_start[H5O_LAYOUT_NDIMS]; /* Offset of low bound of file selection */
+ hsize_t file_sel_end[H5O_LAYOUT_NDIMS]; /* Offset of high bound of file selection */
+ hsize_t mem_sel_start[H5O_LAYOUT_NDIMS]; /* Offset of low bound of file selection */
+ hsize_t mem_sel_end[H5O_LAYOUT_NDIMS]; /* Offset of high bound of file selection */
+ hssize_t adjust[H5O_LAYOUT_NDIMS]; /* Adjustment to make to all file chunks */
+ hssize_t chunk_adjust[H5O_LAYOUT_NDIMS]; /* Adjustment to make to a particular chunk */
+ unsigned u; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_create_chunk_mem_map_hyper)
+
+ /* Sanity check */
+ assert(fm->f_ndims>0);
+
+ /* Check for all I/O going to a single chunk */
+ if(H5SL_count(fm->sel_chunks)==1) {
+ H5D_chunk_info_t *chunk_info; /* Pointer to chunk information */
+
+ /* Get the node */
+ curr_node=H5SL_first(fm->sel_chunks);
+
+ /* Get pointer to chunk's information */
+ chunk_info = (H5D_chunk_info_t *)H5SL_item(curr_node);
+ assert(chunk_info);
+
+ /* Just point at the memory dataspace & selection */
+ /* (Casting away const OK -QAK) */
+ chunk_info->mspace=(H5S_t *)fm->mem_space;
+
+ /* Indicate that the chunk's memory space is shared */
+ chunk_info->mspace_shared = TRUE;
+ } /* end if */
+ else {
+ /* Get bounding box for file selection */
+ if(H5S_SELECT_BOUNDS(fm->file_space, file_sel_start, file_sel_end) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get file selection bound info")
+
+ /* Get bounding box for memory selection */
+ if(H5S_SELECT_BOUNDS(fm->mem_space, mem_sel_start, mem_sel_end) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get file selection bound info")
+
+ /* Calculate the adjustment for memory selection from file selection */
+ assert(fm->m_ndims==fm->f_ndims);
+ for(u=0; u<fm->f_ndims; u++) {
+ H5_CHECK_OVERFLOW(file_sel_start[u],hsize_t,hssize_t);
+ H5_CHECK_OVERFLOW(mem_sel_start[u],hsize_t,hssize_t);
+ adjust[u]=(hssize_t)file_sel_start[u]-(hssize_t)mem_sel_start[u];
+ } /* end for */
+
+ /* Iterate over each chunk in the chunk list */
+ curr_node=H5SL_first(fm->sel_chunks);
+ while(curr_node) {
+ H5D_chunk_info_t *chunk_info; /* Pointer to chunk information */
+
+ /* Get pointer to chunk's information */
+ chunk_info = (H5D_chunk_info_t *)H5SL_item(curr_node);
+ assert(chunk_info);
+
+ /* Copy the information */
+
+ /* Copy the memory dataspace */
+ if((chunk_info->mspace = H5S_copy(fm->mem_space, TRUE, FALSE)) == NULL)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy memory space")
+
+ /* Release the current selection */
+ if(H5S_SELECT_RELEASE(chunk_info->mspace) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection")
+
+ /* Copy the file chunk's selection */
+ if(H5S_select_copy(chunk_info->mspace,chunk_info->fspace,FALSE) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy selection")
+
+ /* Compensate for the chunk offset */
+ for(u=0; u<fm->f_ndims; u++) {
+ H5_CHECK_OVERFLOW(chunk_info->coords[u],hsize_t,hssize_t);
+ chunk_adjust[u]=adjust[u]-(hssize_t)chunk_info->coords[u]; /*lint !e771 The adjust array will always be initialized */
+ } /* end for */
+
+ /* Adjust the selection */
+ if(H5S_hyper_adjust_s(chunk_info->mspace,chunk_adjust) < 0) /*lint !e772 The chunk_adjust array will always be initialized */
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't adjust chunk selection")
+
+ /* Get the next chunk node in the skip list */
+ curr_node=H5SL_next(curr_node);
+ } /* end while */
+ } /* end else */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_create_chunk_mem_map_hyper() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_chunk_file_cb
+ *
+ * Purpose: Callback routine for file selection iterator. Used when
+ * creating selections in file for each point selected.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Wednesday, July 23, 2003
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_chunk_file_cb(void UNUSED *elem, hid_t UNUSED type_id, unsigned ndims, const hsize_t *coords, void *_fm)
+{
+ H5D_chunk_map_t *fm = (H5D_chunk_map_t *)_fm; /* File<->memory chunk mapping info */
+ H5D_chunk_info_t *chunk_info; /* Chunk information for current chunk */
+ hsize_t coords_in_chunk[H5O_LAYOUT_NDIMS]; /* Coordinates of element in chunk */
+ hsize_t chunk_index; /* Chunk index */
+ unsigned u; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_chunk_file_cb)
+
+ /* Calculate the index of this chunk */
+ if(H5V_chunk_index(ndims,coords,fm->layout->u.chunk.dim,fm->down_chunks,&chunk_index) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "can't get chunk index")
+
+ /* Find correct chunk in file & memory skip list */
+ if(chunk_index==fm->last_index) {
+ /* If the chunk index is the same as the last chunk index we used,
+ * get the cached info to operate on.
+ */
+ chunk_info=fm->last_chunk_info;
+ } /* end if */
+ else {
+ /* If the chunk index is not the same as the last chunk index we used,
+ * find the chunk in the skip list.
+ */
+ /* Get the chunk node from the skip list */
+ if(NULL == (chunk_info = (H5D_chunk_info_t *)H5SL_search(fm->sel_chunks, &chunk_index))) {
+ H5S_t *fspace; /* Memory chunk's dataspace */
+
+ /* Allocate the file & memory chunk information */
+ if (NULL==(chunk_info = H5FL_MALLOC (H5D_chunk_info_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate chunk info")
+
+ /* Initialize the chunk information */
+
+ /* Set the chunk index */
+ chunk_info->index=chunk_index;
+
+ /* Create a dataspace for the chunk */
+ if((fspace = H5S_create_simple(fm->f_ndims,fm->chunk_dim,NULL))==NULL) {
+ H5FL_FREE(H5D_chunk_info_t,chunk_info);
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "unable to create dataspace for chunk")
+ } /* end if */
+
+ /* De-select the chunk space */
+ if(H5S_select_none(fspace) < 0) {
+ (void)H5S_close(fspace);
+ H5FL_FREE(H5D_chunk_info_t,chunk_info);
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to de-select dataspace")
+ } /* end if */
+
+ /* Set the file chunk dataspace */
+ chunk_info->fspace = fspace;
+ chunk_info->fspace_shared = FALSE;
+
+ /* Set the memory chunk dataspace */
+ chunk_info->mspace=NULL;
+ chunk_info->mspace_shared = FALSE;
+
+ /* Set the number of selected elements in chunk to zero */
+ chunk_info->chunk_points=0;
+
+ /* Compute the chunk's coordinates */
+ for(u=0; u<fm->f_ndims; u++) {
+ H5_CHECK_OVERFLOW(fm->layout->u.chunk.dim[u],hsize_t,hssize_t);
+ chunk_info->coords[u]=(coords[u]/(hssize_t)fm->layout->u.chunk.dim[u])*(hssize_t)fm->layout->u.chunk.dim[u];
+ } /* end for */
+ chunk_info->coords[fm->f_ndims]=0;
+
+ /* Insert the new chunk into the skip list */
+ if(H5SL_insert(fm->sel_chunks,chunk_info,&chunk_info->index) < 0) {
+ H5D_free_chunk_info(chunk_info,NULL,NULL);
+ HGOTO_ERROR(H5E_DATASPACE,H5E_CANTINSERT,FAIL,"can't insert chunk into skip list")
+ } /* end if */
+ } /* end if */
+
+ /* Update the "last chunk seen" information */
+ fm->last_index=chunk_index;
+ fm->last_chunk_info=chunk_info;
+ } /* end else */
+
+ /* Get the coordinates of the element in the chunk */
+ for(u=0; u<fm->f_ndims; u++)
+ coords_in_chunk[u]=coords[u]%fm->layout->u.chunk.dim[u];
+
+ /* Add point to file selection for chunk */
+ if(H5S_select_elements(chunk_info->fspace, H5S_SELECT_APPEND, (size_t)1, coords_in_chunk) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "unable to select element")
+
+ /* Increment the number of elemented selected in chunk */
+ chunk_info->chunk_points++;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_chunk_file_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_chunk_mem_cb
+ *
+ * Purpose: Callback routine for file selection iterator. Used when
+ * creating selections in memory for each chunk.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Raymond Lu
+ * Thursday, April 10, 2003
+ *
+ *-------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static herr_t
+H5D_chunk_mem_cb(void UNUSED *elem, hid_t UNUSED type_id, unsigned ndims, const hsize_t *coords, void *_fm)
+{
+ H5D_chunk_map_t *fm = (H5D_chunk_map_t *)_fm; /* File<->memory chunk mapping info */
+ H5D_chunk_info_t *chunk_info; /* Chunk information for current chunk */
+ hsize_t coords_in_mem[H5O_LAYOUT_NDIMS]; /* Coordinates of element in memory */
+ hsize_t chunk_index; /* Chunk index */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_chunk_mem_cb)
+
+ /* Calculate the index of this chunk */
+ if(H5V_chunk_index(ndims,coords,fm->layout->u.chunk.dim,fm->down_chunks,&chunk_index) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "can't get chunk index")
+
+ /* Find correct chunk in file & memory skip list */
+ if(chunk_index==fm->last_index) {
+ /* If the chunk index is the same as the last chunk index we used,
+ * get the cached spaces to operate on.
+ */
+ chunk_info=fm->last_chunk_info;
+ } /* end if */
+ else {
+ /* If the chunk index is not the same as the last chunk index we used,
+ * find the chunk in the skip list.
+ */
+ /* Get the chunk node from the skip list */
+ if(NULL == (chunk_info = (H5D_chunk_info_t *)H5SL_search(fm->sel_chunks, &chunk_index)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_NOTFOUND, FAIL, "can't locate chunk in skip list")
+
+ /* Check if the chunk already has a memory space */
+ if(chunk_info->mspace==NULL) {
+ /* Copy the template memory chunk dataspace */
+ if((chunk_info->mspace = H5S_copy(fm->mchunk_tmpl, FALSE, FALSE)) == NULL)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy file space")
+ } /* end else */
+
+ /* Update the "last chunk seen" information */
+ fm->last_index=chunk_index;
+ fm->last_chunk_info=chunk_info;
+ } /* end else */
+
+ /* Get coordinates of selection iterator for memory */
+ if(H5S_SELECT_ITER_COORDS(&fm->mem_iter,coords_in_mem) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get iterator coordinates")
+
+ /* Add point to memory selection for chunk */
+ if(fm->msel_type==H5S_SEL_POINTS) {
+ if(H5S_select_elements(chunk_info->mspace, H5S_SELECT_APPEND, (size_t)1, coords_in_mem) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "unable to select element")
+ } /* end if */
+ else {
+ if(H5S_hyper_add_span_element(chunk_info->mspace, fm->m_ndims, coords_in_mem) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "unable to select element")
+ } /* end else */
+
+ /* Move memory selection iterator to next element in selection */
+ if(H5S_SELECT_ITER_NEXT(&fm->mem_iter, (size_t)1) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTNEXT, FAIL, "unable to move to next iterator location")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_chunk_mem_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_chunk_cacheable
+ *
+ * Purpose: A small internal function to if it's possible to load the
+ * chunk into cache.
+ *
+ * Return: TRUE or FALSE
+ *
+ * Programmer: Raymond Lu
+ * 17 July 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+hbool_t
+H5D_chunk_cacheable(const H5D_io_info_t *io_info, haddr_t caddr)
+{
+ const H5D_t *dataset = io_info->dset;
+ hbool_t ret_value;
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_chunk_cacheable)
+
+ HDassert(io_info);
+ HDassert(dataset);
+
+ /* Must bring the whole chunk in if there are any filters */
+ if(dataset->shared->dcpl_cache.pline.nused > 0)
+ ret_value = TRUE;
+ else
+#ifdef H5_HAVE_PARALLEL
+ /* If MPI based VFD is used and the file is opened for write access, must
+ * bypass the chunk-cache scheme because other MPI processes could
+ * be writing to other elements in the same chunk. Do a direct
+ * write-through of only the elements requested.
+ */
+ if(io_info->using_mpi_vfd && (H5F_ACC_RDWR & H5F_INTENT(dataset->oloc.file)))
+ ret_value = FALSE;
+ else
+#endif /* H5_HAVE_PARALLEL */
+ /* If the chunk is too large to keep in the cache and if the address
+ * for the chunk has been defined, then don't load the chunk into the
+ * cache, just write the data to it directly.
+ */
+ if(dataset->shared->layout.u.chunk.size > dataset->shared->cache.chunk.nbytes
+ && H5F_addr_defined(caddr))
+ ret_value = FALSE;
+ else
+ ret_value = TRUE;
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_chunk_cacheable() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_chunk_in_cache
+ *
+ * Purpose: Check if a chunk is in the cache.
+ *
+ * Return: TRUE or FALSE
+ *
+ * Programmer: Quincey Koziol
+ * 1 April 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static hbool_t
+H5D_chunk_in_cache(const H5D_io_info_t *io_info)
+{
+ H5D_rdcc_t *rdcc = &(io_info->dset->shared->cache.chunk);/*raw data chunk cache*/
+ hbool_t found = FALSE; /*already in cache? */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_chunk_in_cache)
+
+ HDassert(io_info);
+
+ /* Check if the chunk is in the cache (but hasn't been written to disk yet) */
+ if(rdcc->nslots > 0) {
+ unsigned idx = H5D_CHUNK_HASH(io_info->dset->shared, io_info->store->chunk.index); /* Cache entry index */
+ H5D_rdcc_ent_t *ent = rdcc->slot[idx]; /* Cache entry */
+
+ /* Potential match... */
+ if(ent) {
+ size_t u; /* Local index variable */
+
+ for(u = 0, found = TRUE; u < io_info->dset->shared->layout.u.chunk.ndims; u++) {
+ if(io_info->store->chunk.offset[u] != ent->offset[u]) {
+ found = FALSE;
+ break;
+ } /* end if */
+ } /* end for */
+ } /* end if */
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(found)
+} /* end H5D_chunk_in_cache() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_chunk_read
+ *
+ * Purpose: Read from a chunked dataset.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Raymond Lu
+ * Thursday, April 10, 2003
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_chunk_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
+ hsize_t UNUSED nelmts, const H5S_t UNUSED *file_space, const H5S_t UNUSED *mem_space,
+ H5D_chunk_map_t *fm)
+{
+ H5SL_node_t *chunk_node; /* Current node in chunk skip list */
+ H5D_io_info_t nul_io_info; /* "null" I/O info object */
+ H5D_io_info_t ctg_io_info; /* Contiguous I/O info object */
+ H5D_storage_t ctg_store; /* Chunk storage information as contiguous dataset */
+ H5D_io_info_t cpt_io_info; /* Compact I/O info object */
+ H5D_storage_t cpt_store; /* Chunk storage information as compact dataset */
+ hbool_t cpt_dirty; /* Temporary placeholder for compact storage "dirty" flag */
+ size_t src_accessed_bytes = 0; /* Total accessed size in a chunk */
+ hbool_t skip_missing_chunks = FALSE; /* Whether to skip missing chunks */
+ unsigned idx_hint = 0; /* Cache index hint */
+ herr_t ret_value = SUCCEED; /*return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_chunk_read)
+
+ /* Sanity check */
+ HDassert(io_info);
+ HDassert(io_info->u.rbuf);
+ HDassert(type_info);
+ HDassert(fm);
+
+ /* Set up "null" I/O info object */
+ HDmemcpy(&nul_io_info, io_info, sizeof(nul_io_info));
+ nul_io_info.layout_ops = *H5D_LOPS_NULL;
+
+ /* Set up contiguous I/O info object */
+ HDmemcpy(&ctg_io_info, io_info, sizeof(ctg_io_info));
+ ctg_io_info.store = &ctg_store;
+ ctg_io_info.layout_ops = *H5D_LOPS_CONTIG;
+
+ /* Initialize temporary contiguous storage info */
+ ctg_store.contig.dset_size = (hsize_t)io_info->dset->shared->layout.u.chunk.size;
+
+ /* Set up compact I/O info object */
+ HDmemcpy(&cpt_io_info, io_info, sizeof(cpt_io_info));
+ cpt_io_info.store = &cpt_store;
+ cpt_io_info.layout_ops = *H5D_LOPS_COMPACT;
+
+ /* Initialize temporary compact storage info */
+ cpt_store.compact.dirty = &cpt_dirty;
+
+ {
+ const H5O_fill_t *fill = &(io_info->dset->shared->dcpl_cache.fill); /* Fill value info */
+ H5D_fill_value_t fill_status; /* Fill value status */
+
+ /* Check the fill value status */
+ if(H5P_is_fill_value_defined(fill, &fill_status) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't tell if fill value defined")
+
+ /* If we are never to return fill values, or if we would return them
+ * but they aren't set, set the flag to skip missing chunks.
+ */
+ if(fill->fill_time == H5D_FILL_TIME_NEVER ||
+ (fill->fill_time == H5D_FILL_TIME_IFSET && fill_status != H5D_FILL_VALUE_USER_DEFINED))
+ skip_missing_chunks = TRUE;
+ }
+
+ /* Iterate through nodes in chunk skip list */
+ chunk_node = H5D_CHUNK_GET_FIRST_NODE(fm);
+ while(chunk_node) {
+ H5D_chunk_info_t *chunk_info; /* Chunk information */
+ H5D_io_info_t *chk_io_info; /* Pointer to I/O info object for this chunk */
+ void *chunk; /* Pointer to locked chunk buffer */
+ haddr_t chunk_addr; /* Chunk address on disk */
+ H5D_istore_ud1_t udata; /* B-tree pass-through */
+
+ /* Get the actual chunk information from the skip list node */
+ chunk_info = H5D_CHUNK_GET_NODE_INFO(fm, chunk_node);
+
+ /* Pass in chunk's coordinates in a union. */
+ io_info->store->chunk.offset = chunk_info->coords;
+ io_info->store->chunk.index = chunk_info->index;
+
+ /* Get the address of the chunk in the file */
+ chunk_addr = H5D_istore_get_addr(io_info, &udata);
+
+ /* Check for non-existant chunk & skip it if appropriate */
+ if(!H5F_addr_defined(chunk_addr) && !H5D_chunk_in_cache(io_info)
+ && skip_missing_chunks) {
+ /* No chunk cached */
+ chunk = NULL;
+
+ /* Point I/O info at "null" I/O info for this chunk */
+ chk_io_info = &nul_io_info;
+ } /* end if */
+ else {
+ /* Load the chunk into cache and lock it. */
+ if(H5D_chunk_cacheable(io_info, chunk_addr)) {
+ /* Compute # of bytes accessed in chunk */
+ src_accessed_bytes = chunk_info->chunk_points * type_info->src_type_size;
+
+ /* Lock the chunk into the cache */
+ if(NULL == (chunk = H5D_istore_lock(io_info, &udata, FALSE, &idx_hint)))
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to read raw data chunk")
+
+ /* Set up the storage buffer information for this chunk */
+ cpt_store.compact.buf = chunk;
+
+ /* Point I/O info at contiguous I/O info for this chunk */
+ chk_io_info = &cpt_io_info;
+ } /* end if */
+ else {
+ /* Sanity check */
+ HDassert(H5F_addr_defined(chunk_addr));
+
+ /* Set up the storage address information for this chunk */
+ ctg_store.contig.dset_addr = chunk_addr;
+
+ /* No chunk cached */
+ chunk = NULL;
+
+ /* Point I/O info at temporary I/O info for this chunk */
+ chk_io_info = &ctg_io_info;
+ } /* end else */
+ } /* end else */
+
+ /* Perform the actual read operation */
+ if((io_info->io_ops.single_read)(chk_io_info, type_info,
+ (hsize_t)chunk_info->chunk_points, chunk_info->fspace, chunk_info->mspace) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "chunked read failed")
+
+ /* Release the cache lock on the chunk. */
+ if(chunk && H5D_istore_unlock(io_info, FALSE, idx_hint, chunk, src_accessed_bytes) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to unlock raw data chunk")
+
+ /* Advance to next chunk in list */
+ chunk_node = H5D_CHUNK_GET_NEXT_NODE(fm, chunk_node);
+ } /* end while */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5D_chunk_read() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_chunk_write
+ *
+ * Purpose: Writes to a chunked dataset.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Raymond Lu
+ * Thursday, April 10, 2003
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_chunk_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
+ hsize_t UNUSED nelmts, const H5S_t UNUSED *file_space, const H5S_t UNUSED *mem_space,
+ H5D_chunk_map_t *fm)
+{
+ H5SL_node_t *chunk_node; /* Current node in chunk skip list */
+ H5D_io_info_t ctg_io_info; /* Contiguous I/O info object */
+ H5D_storage_t ctg_store; /* Chunk storage information as contiguous dataset */
+ H5D_io_info_t cpt_io_info; /* Compact I/O info object */
+ H5D_storage_t cpt_store; /* Chunk storage information as compact dataset */
+ hbool_t cpt_dirty; /* Temporary placeholder for compact storage "dirty" flag */
+ size_t dst_accessed_bytes = 0; /* Total accessed size in a chunk */
+ unsigned idx_hint = 0; /* Cache index hint */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_chunk_write)
+
+ /* Sanity check */
+ HDassert(io_info);
+ HDassert(io_info->u.wbuf);
+ HDassert(type_info);
+ HDassert(fm);
+
+ /* Set up contiguous I/O info object */
+ HDmemcpy(&ctg_io_info, io_info, sizeof(ctg_io_info));
+ ctg_io_info.store = &ctg_store;
+ ctg_io_info.layout_ops = *H5D_LOPS_CONTIG;
+
+ /* Initialize temporary contiguous storage info */
+ ctg_store.contig.dset_size = (hsize_t)io_info->dset->shared->layout.u.chunk.size;
+
+ /* Set up compact I/O info object */
+ HDmemcpy(&cpt_io_info, io_info, sizeof(cpt_io_info));
+ cpt_io_info.store = &cpt_store;
+ cpt_io_info.layout_ops = *H5D_LOPS_COMPACT;
+
+ /* Initialize temporary compact storage info */
+ cpt_store.compact.dirty = &cpt_dirty;
+
+ /* Iterate through nodes in chunk skip list */
+ chunk_node = H5D_CHUNK_GET_FIRST_NODE(fm);
+ while(chunk_node) {
+ H5D_chunk_info_t *chunk_info; /* Chunk information */
+ H5D_io_info_t *chk_io_info; /* Pointer to I/O info object for this chunk */
+ void *chunk; /* Pointer to locked chunk buffer */
+ haddr_t chunk_addr; /* Chunk address on disk */
+ H5D_istore_ud1_t udata; /* B-tree pass-through */
+
+ /* Get the actual chunk information from the skip list node */
+ chunk_info = H5D_CHUNK_GET_NODE_INFO(fm, chunk_node);
+
+ /* Pass in chunk's coordinates in a union. */
+ io_info->store->chunk.offset = chunk_info->coords;
+ io_info->store->chunk.index = chunk_info->index;
+
+ /* Load the chunk into cache. But if the whole chunk is written,
+ * simply allocate space instead of load the chunk. */
+ chunk_addr = H5D_istore_get_addr(io_info, &udata);
+ if(H5D_chunk_cacheable(io_info, chunk_addr)) {
+ hbool_t entire_chunk = TRUE; /* Whether whole chunk is selected */
+
+ /* Compute # of bytes accessed in chunk */
+ dst_accessed_bytes = chunk_info->chunk_points * type_info->dst_type_size;
+
+ /* Determine if we will access all the data in the chunk */
+ if(dst_accessed_bytes != ctg_store.contig.dset_size ||
+ (chunk_info->chunk_points * type_info->src_type_size) != ctg_store.contig.dset_size)
+ entire_chunk = FALSE;
+
+ /* Lock the chunk into the cache */
+ if(NULL == (chunk = H5D_istore_lock(io_info, &udata, entire_chunk, &idx_hint)))
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to read raw data chunk")
+
+ /* Set up the storage buffer information for this chunk */
+ cpt_store.compact.buf = chunk;
+
+ /* Point I/O info at main I/O info for this chunk */
+ chk_io_info = &cpt_io_info;
+ } /* end if */
+ else {
+ /* Sanity check */
+ HDassert(H5F_addr_defined(chunk_addr));
+
+ /* Set up the storage address information for this chunk */
+ ctg_store.contig.dset_addr = chunk_addr;
+
+ /* No chunk cached */
+ chunk = NULL;
+
+ /* Point I/O info at temporary I/O info for this chunk */
+ chk_io_info = &ctg_io_info;
+ } /* end else */
+
+ /* Perform the actual write operation */
+ if((io_info->io_ops.single_write)(chk_io_info, type_info,
+ (hsize_t)chunk_info->chunk_points, chunk_info->fspace, chunk_info->mspace) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "chunked write failed")
+
+ /* Release the cache lock on the chunk. */
+ if(chunk && H5D_istore_unlock(io_info, TRUE, idx_hint, chunk, dst_accessed_bytes) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to unlock raw data chunk")
+
+ /* Advance to next chunk in list */
+ chunk_node = H5D_CHUNK_GET_NEXT_NODE(fm, chunk_node);
+ } /* end while */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5D_chunk_write() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_chunk_io_term
+ *
+ * Purpose: Destroy I/O operation information.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Saturday, May 17, 2003
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_chunk_io_term(const H5D_chunk_map_t *fm)
+{
+ herr_t ret_value = SUCCEED; /*return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_chunk_io_term)
+
+ /* Single element I/O vs. multiple element I/O cleanup */
+ if(fm->use_single) {
+ /* Sanity checks */
+ HDassert(fm->sel_chunks == NULL);
+ HDassert(fm->single_chunk_info);
+ HDassert(fm->single_chunk_info->fspace_shared);
+ HDassert(fm->single_chunk_info->mspace_shared);
+
+ /* Reset the selection for the single element I/O */
+ H5S_select_all(fm->single_space, TRUE);
+ } /* end if */
+ else {
+ /* Release the nodes on the list of selected chunks */
+ if(fm->sel_chunks)
+ if(H5SL_free(fm->sel_chunks, H5D_free_chunk_info, NULL) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTNEXT, FAIL, "can't iterate over chunks")
+ } /* end else */
+
+ /* Free the memory chunk dataspace template */
+ if(fm->mchunk_tmpl)
+ if(H5S_close(fm->mchunk_tmpl) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "can't release memory chunk dataspace template")
+#ifdef H5_HAVE_PARALLEL
+ if(fm->select_chunk)
+ H5MM_xfree(fm->select_chunk);
+#endif /* H5_HAVE_PARALLEL */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_chunk_io_term() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_null_readvv
+ *
+ * Purpose: Performs "no-op" I/O operation, advancing through two I/O
+ * vectors, until one runs out.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, April 1, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static ssize_t
+H5D_null_readvv(const H5D_io_info_t UNUSED *io_info,
+ size_t chunk_max_nseq, size_t *chunk_curr_seq, size_t chunk_len_arr[], hsize_t chunk_offset_arr[],
+ size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[])
+{
+ size_t u, v; /* Local index variables */
+ size_t size; /* Size of sequence in bytes */
+ ssize_t bytes_processed = 0; /* Eventual return value */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_null_readvv)
+
+ /* Check args */
+ HDassert(chunk_len_arr);
+ HDassert(chunk_offset_arr);
+ HDassert(mem_len_arr);
+ HDassert(mem_offset_arr);
+
+ /* Work through all the sequences */
+ for(u = *mem_curr_seq, v = *chunk_curr_seq; u < mem_max_nseq && v < chunk_max_nseq; ) {
+ /* Choose smallest buffer to write */
+ if(chunk_len_arr[v] < mem_len_arr[u])
+ size = chunk_len_arr[v];
+ else
+ size = mem_len_arr[u];
+
+ /* Update source information */
+ chunk_len_arr[v] -= size;
+ chunk_offset_arr[v] += size;
+ if(chunk_len_arr[v] == 0)
+ v++;
+
+ /* Update destination information */
+ mem_len_arr[u] -= size;
+ mem_offset_arr[u] += size;
+ if(mem_len_arr[u] == 0)
+ u++;
+
+ /* Increment number of bytes copied */
+ bytes_processed += (ssize_t)size;
+ } /* end for */
+
+ /* Update current sequence vectors */
+ *mem_curr_seq = u;
+ *chunk_curr_seq = v;
+
+ FUNC_LEAVE_NOAPI(bytes_processed)
+} /* H5D_null_readvv() */
+
diff --git a/src/H5Dcompact.c b/src/H5Dcompact.c
index 2e4d3f7..c3abab6 100644
--- a/src/H5Dcompact.c
+++ b/src/H5Dcompact.c
@@ -41,22 +41,52 @@
#include "H5Oprivate.h" /* Object headers */
#include "H5Vprivate.h" /* Vector and array functions */
+
/****************/
/* Local Macros */
/****************/
+
/******************/
/* Local Typedefs */
/******************/
+
/********************/
/* Local Prototypes */
/********************/
+/* Layout operation callbacks */
+static herr_t H5D_compact_io_init(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
+ hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space,
+ H5D_chunk_map_t *cm);
+static ssize_t H5D_compact_readvv(const H5D_io_info_t *io_info,
+ size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_size_arr[], hsize_t dset_offset_arr[],
+ size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_size_arr[], hsize_t mem_offset_arr[]);
+static ssize_t H5D_compact_writevv(const H5D_io_info_t *io_info,
+ size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_size_arr[], hsize_t dset_offset_arr[],
+ size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_size_arr[], hsize_t mem_offset_arr[]);
+
+
/*********************/
/* Package Variables */
/*********************/
+/* Compact storage layout I/O ops */
+const H5D_layout_ops_t H5D_LOPS_COMPACT[1] = {{
+ H5D_compact_io_init,
+ H5D_contig_read,
+ H5D_contig_write,
+#ifdef H5_HAVE_PARALLEL
+ NULL,
+ NULL,
+#endif /* H5_HAVE_PARALLEL */
+ H5D_compact_readvv,
+ H5D_compact_writevv,
+ NULL
+}};
+
+
/*******************/
/* Local Variables */
/*******************/
@@ -64,6 +94,7 @@
/* Declare extern the free list to manage blocks of type conversion data */
H5FL_BLK_EXTERN(type_conv);
+
/*-------------------------------------------------------------------------
* Function: H5D_compact_fill
@@ -118,6 +149,32 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5D_compact_io_init
+ *
+ * Purpose: Performs initialization before any sort of I/O on the raw data
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, March 20, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_compact_io_init(const H5D_io_info_t *io_info, const H5D_type_info_t UNUSED *type_info,
+ hsize_t UNUSED nelmts, const H5S_t UNUSED *file_space, const H5S_t UNUSED *mem_space,
+ H5D_chunk_map_t UNUSED *cm)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_compact_io_init)
+
+ io_info->store->compact.buf = io_info->dset->shared->layout.u.compact.buf;
+ io_info->store->compact.dirty = &io_info->dset->shared->layout.u.compact.dirty;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5D_compact_io_init() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5D_compact_readvv
*
* Purpose: Reads some data vectors from a dataset into a buffer.
@@ -135,20 +192,19 @@ done:
*
*-------------------------------------------------------------------------
*/
-ssize_t
+static ssize_t
H5D_compact_readvv(const H5D_io_info_t *io_info,
size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_size_arr[], hsize_t dset_offset_arr[],
- size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_size_arr[], hsize_t mem_offset_arr[],
- haddr_t UNUSED addr, void UNUSED *pointer/*in*/, void *buf)
+ size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_size_arr[], hsize_t mem_offset_arr[])
{
- ssize_t ret_value; /* Return value */
+ ssize_t ret_value; /* Return value */
- FUNC_ENTER_NOAPI(H5D_compact_readvv, FAIL)
+ FUNC_ENTER_NOAPI_NOINIT(H5D_compact_readvv)
- assert(io_info->dset);
+ HDassert(io_info);
/* Use the vectorized memory copy routine to do actual work */
- if((ret_value=H5V_memcpyvv(buf,mem_max_nseq,mem_curr_seq,mem_size_arr,mem_offset_arr,io_info->dset->shared->layout.u.compact.buf,dset_max_nseq,dset_curr_seq,dset_size_arr,dset_offset_arr))<0)
+ if((ret_value = H5V_memcpyvv(io_info->u.rbuf, mem_max_nseq, mem_curr_seq, mem_size_arr, mem_offset_arr, io_info->store->compact.buf, dset_max_nseq, dset_curr_seq, dset_size_arr, dset_offset_arr)) < 0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "vectorized memcpy failed")
done:
@@ -177,24 +233,23 @@ done:
*
*-------------------------------------------------------------------------
*/
-ssize_t
+static ssize_t
H5D_compact_writevv(const H5D_io_info_t *io_info,
size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_size_arr[], hsize_t dset_offset_arr[],
- size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_size_arr[], hsize_t mem_offset_arr[],
- haddr_t UNUSED addr, void UNUSED *pointer/*in*/, const void *buf)
+ size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_size_arr[], hsize_t mem_offset_arr[])
{
- ssize_t ret_value; /* Return value */
+ ssize_t ret_value; /* Return value */
- FUNC_ENTER_NOAPI(H5D_compact_writevv, FAIL)
+ FUNC_ENTER_NOAPI_NOINIT(H5D_compact_writevv)
- assert(io_info->dset);
+ HDassert(io_info);
/* Use the vectorized memory copy routine to do actual work */
- if((ret_value=H5V_memcpyvv(io_info->dset->shared->layout.u.compact.buf,dset_max_nseq,dset_curr_seq,dset_size_arr,dset_offset_arr,buf,mem_max_nseq,mem_curr_seq,mem_size_arr,mem_offset_arr))<0)
+ if((ret_value = H5V_memcpyvv(io_info->store->compact.buf, dset_max_nseq, dset_curr_seq, dset_size_arr, dset_offset_arr, io_info->u.wbuf, mem_max_nseq, mem_curr_seq, mem_size_arr, mem_offset_arr)) < 0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "vectorized memcpy failed")
/* Mark the compact dataset's buffer as dirty */
- io_info->dset->shared->layout.u.compact.dirty = TRUE;
+ *io_info->store->compact.dirty = TRUE;
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -371,11 +426,11 @@ done:
if(H5I_dec_ref(tid_mem) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't decrement temporary datatype ID")
if(buf)
- H5FL_BLK_FREE(type_conv, buf);
+ (void)H5FL_BLK_FREE(type_conv, buf);
if(reclaim_buf)
- H5FL_BLK_FREE(type_conv, reclaim_buf);
+ (void)H5FL_BLK_FREE(type_conv, reclaim_buf);
if(bkg)
- H5FL_BLK_FREE(type_conv, bkg);
+ (void)H5FL_BLK_FREE(type_conv, bkg);
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D_compact_copy() */
diff --git a/src/H5Dcontig.c b/src/H5Dcontig.c
index bdb8294..1a3fda5 100644
--- a/src/H5Dcontig.c
+++ b/src/H5Dcontig.c
@@ -45,24 +45,50 @@
#include "H5Pprivate.h" /* Property lists */
#include "H5Vprivate.h" /* Vector and array functions */
+
/****************/
/* Local Macros */
/****************/
+
/******************/
/* Local Typedefs */
/******************/
+
/********************/
/* Local Prototypes */
/********************/
-static herr_t H5D_contig_write(H5D_t *dset, const H5D_dxpl_cache_t *dxpl_cache,
- hid_t dxpl_id, const H5D_storage_t *store, hsize_t offset, size_t size, const void *buf);
+
+/* Layout operation callbacks */
+static herr_t H5D_contig_io_init(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
+ hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space,
+ H5D_chunk_map_t *cm);
+
+/* Helper routines */
+static herr_t H5D_contig_write_one(H5D_io_info_t *io_info, hsize_t offset,
+ size_t size);
+
/*********************/
/* Package Variables */
/*********************/
+/* Contiguous storage layout I/O ops */
+const H5D_layout_ops_t H5D_LOPS_CONTIG[1] = {{
+ H5D_contig_io_init,
+ H5D_contig_read,
+ H5D_contig_write,
+#ifdef H5_HAVE_PARALLEL
+ H5D_contig_collective_read,
+ H5D_contig_collective_write,
+#endif /* H5_HAVE_PARALLEL */
+ H5D_contig_readvv,
+ H5D_contig_writevv,
+ NULL
+}};
+
+
/*******************/
/* Local Variables */
/*******************/
@@ -73,6 +99,7 @@ H5FL_BLK_DEFINE(sieve_buf);
/* Declare extern the free list to manage blocks of type conversion data */
H5FL_BLK_EXTERN(type_conv);
+
/*-------------------------------------------------------------------------
* Function: H5D_contig_create
@@ -121,7 +148,8 @@ done:
herr_t
H5D_contig_fill(H5D_t *dset, hid_t dxpl_id)
{
- H5D_storage_t store; /* Union of storage info for dataset */
+ H5D_io_info_t ioinfo; /* Dataset I/O info */
+ H5D_storage_t store; /* Union of storage info for dataset */
H5D_dxpl_cache_t _dxpl_cache; /* Data transfer property cache buffer */
H5D_dxpl_cache_t *dxpl_cache = &_dxpl_cache; /* Data transfer property cache */
hssize_t snpoints; /* Number of points in space (for error checking) */
@@ -198,6 +226,9 @@ H5D_contig_fill(H5D_t *dset, hid_t dxpl_id)
/* Start at the beginning of the dataset */
offset = 0;
+ /* Simple setup for dataset I/O info struct */
+ H5D_BUILD_IO_INFO_WRT(&ioinfo, dset, dxpl_cache, my_dxpl_id, &store, fb_info.fill_buf);
+
/*
* Fill the entire current extent with the fill value. We can do
* this quite efficiently by making sure we copy the fill value
@@ -225,7 +256,7 @@ H5D_contig_fill(H5D_t *dset, hid_t dxpl_id)
/* Write the chunks out from only one process */
/* !! Use the internal "independent" DXPL!! -QAK */
if(H5_PAR_META_WRITE == mpi_rank)
- if(H5D_contig_write(dset, dxpl_cache, my_dxpl_id, &store, offset, size, fb_info.fill_buf) < 0)
+ if(H5D_contig_write_one(&ioinfo, offset, size) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to write fill value to dataset")
/* Indicate that blocks are being written */
@@ -234,7 +265,7 @@ H5D_contig_fill(H5D_t *dset, hid_t dxpl_id)
else {
#endif /* H5_HAVE_PARALLEL */
H5_CHECK_OVERFLOW(size, size_t, hsize_t);
- if(H5D_contig_write(dset, dxpl_cache, my_dxpl_id, &store, offset, size, fb_info.fill_buf) < 0)
+ if(H5D_contig_write_one(&ioinfo, offset, size) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to write fill value to dataset")
#ifdef H5_HAVE_PARALLEL
} /* end else */
@@ -324,8 +355,108 @@ H5D_contig_get_addr(const H5D_t *dset)
/*-------------------------------------------------------------------------
+ * Function: H5D_contig_io_init
+ *
+ * Purpose: Performs initialization before any sort of I/O on the raw data
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, March 20, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_contig_io_init(const H5D_io_info_t *io_info, const H5D_type_info_t UNUSED *type_info,
+ hsize_t UNUSED nelmts, const H5S_t UNUSED *file_space, const H5S_t UNUSED *mem_space,
+ H5D_chunk_map_t UNUSED *cm)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_contig_io_init)
+
+ io_info->store->contig.dset_addr = io_info->dset->shared->layout.u.contig.addr;
+ io_info->store->contig.dset_size = io_info->dset->shared->layout.u.contig.size;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5D_contig_io_init() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_contig_read
+ *
+ * Purpose: Read from a contiguous dataset.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Raymond Lu
+ * Thursday, April 10, 2003
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5D_contig_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
+ hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space,
+ H5D_chunk_map_t UNUSED *fm)
+{
+ herr_t ret_value = SUCCEED; /*return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_contig_read)
+
+ /* Sanity check */
+ HDassert(io_info);
+ HDassert(io_info->u.rbuf);
+ HDassert(type_info);
+ HDassert(mem_space);
+ HDassert(file_space);
+
+ /* Read data */
+ if((io_info->io_ops.single_read)(io_info, type_info, nelmts, file_space, mem_space) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "contiguous read failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_contig_read() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5D_contig_write
*
+ * Purpose: Write to a contiguous dataset.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Raymond Lu
+ * Thursday, April 10, 2003
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5D_contig_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
+ hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space,
+ H5D_chunk_map_t UNUSED *fm)
+{
+ herr_t ret_value = SUCCEED; /*return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_contig_write)
+
+ /* Sanity check */
+ HDassert(io_info);
+ HDassert(io_info->u.wbuf);
+ HDassert(type_info);
+ HDassert(mem_space);
+ HDassert(file_space);
+
+ /* Write data */
+ if((io_info->io_ops.single_write)(io_info, type_info, nelmts, file_space, mem_space) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "contiguous write failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_contig_write() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_contig_write_one
+ *
* Purpose: Writes some data from a dataset into a buffer.
* The data is contiguous. The address is relative to the base
* address for the file.
@@ -338,34 +469,27 @@ H5D_contig_get_addr(const H5D_t *dset)
*-------------------------------------------------------------------------
*/
static herr_t
-H5D_contig_write(H5D_t *dset, const H5D_dxpl_cache_t *dxpl_cache,
- hid_t dxpl_id, const H5D_storage_t *store,
- hsize_t offset, size_t size, const void *buf)
+H5D_contig_write_one(H5D_io_info_t *io_info, hsize_t offset, size_t size)
{
- H5D_io_info_t io_info; /* Dataset I/O info */
- hsize_t dset_off=offset; /* Offset in dataset */
- size_t dset_len=size; /* Length in dataset */
- size_t dset_curr_seq=0; /* "Current sequence" in dataset */
- hsize_t mem_off=0; /* Offset in memory */
- size_t mem_len=size; /* Length in memory */
- size_t mem_curr_seq=0; /* "Current sequence" in memory */
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5D_contig_write, FAIL)
-
- assert (dset);
- assert (dxpl_cache);
- assert (store);
- assert (buf);
-
- H5D_BUILD_IO_INFO(&io_info,dset,dxpl_cache,dxpl_id,store);
- if(H5D_contig_writevv(&io_info, (size_t)1, &dset_curr_seq, &dset_len, &dset_off,
- (size_t)1, &mem_curr_seq, &mem_len, &mem_off, (haddr_t)0, NULL, buf) < 0)
+ hsize_t dset_off = offset; /* Offset in dataset */
+ size_t dset_len = size; /* Length in dataset */
+ size_t dset_curr_seq = 0; /* "Current sequence" in dataset */
+ hsize_t mem_off = 0; /* Offset in memory */
+ size_t mem_len = size; /* Length in memory */
+ size_t mem_curr_seq = 0; /* "Current sequence" in memory */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_contig_write_one)
+
+ HDassert(io_info);
+
+ if(H5D_contig_writevv(io_info, (size_t)1, &dset_curr_seq, &dset_len, &dset_off,
+ (size_t)1, &mem_curr_seq, &mem_len, &mem_off) < 0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "vector write failed")
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_contig_write() */
+} /* end H5D_contig_write_one() */
/*-------------------------------------------------------------------------
@@ -389,67 +513,76 @@ done:
ssize_t
H5D_contig_readvv(const H5D_io_info_t *io_info,
size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_len_arr[], hsize_t dset_offset_arr[],
- size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[],
- haddr_t UNUSED address, void UNUSED *pointer, void *_buf)
+ size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[])
{
H5F_t *file = io_info->dset->oloc.file; /* File for dataset */
- H5D_rdcdc_t *dset_contig=&(io_info->dset->shared->cache.contig); /* Cached information about contiguous data */
- const H5D_contig_storage_t *store_contig=&(io_info->store->contig); /* Contiguous storage info for this I/O operation */
- unsigned char *buf=(unsigned char *)_buf; /* Pointer to buffer to fill */
+ H5D_rdcdc_t *dset_contig = &(io_info->dset->shared->cache.contig); /* Cached information about contiguous data */
+ const H5D_contig_storage_t *store_contig = &(io_info->store->contig); /* Contiguous storage info for this I/O operation */
+ unsigned char *buf = (unsigned char *)io_info->u.rbuf; /* Pointer to buffer to fill */
haddr_t addr; /* Actual address to read */
- size_t total_size=0; /* Total size of sequence in bytes */
+ size_t total_size = 0; /* Total size of sequence in bytes */
size_t size; /* Size of sequence in bytes */
size_t u; /* Counting variable */
size_t v; /* Counting variable */
ssize_t ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5D_contig_readvv, FAIL)
+#ifdef QAK
+HDfprintf(stderr, "%s: dset_max_nseq = %Zu\n", FUNC, dset_max_nseq);
+HDfprintf(stderr, "%s: mem_max_nseq = %Zu\n", FUNC, mem_max_nseq);
+HDfprintf(stderr, "%s: *dset_curr_seq= %Zu\n", FUNC, *dset_curr_seq);
+HDfprintf(stderr, "%s: *mem_curr_seq= %Zu\n", FUNC, *mem_curr_seq);
+for(u = 0; u < dset_max_nseq; u++)
+ HDfprintf(stderr, "%s: dset_len_arr[%Zu] = %Zu, dset_offset_arr[%Zu] = %Hu\n", FUNC, u, dset_len_arr[u], u, dset_offset_arr[u]);
+for(u = 0; u < mem_max_nseq; u++)
+ HDfprintf(stderr, "%s: mem_len_arr[%Zu] = %Zu, mem_offset_arr[%Zu] = %Hu\n", FUNC, u, mem_len_arr[u], u, mem_offset_arr[u]);
+#endif /* QAK */
/* Check args */
- assert(io_info);
- assert(io_info->dset);
- assert(io_info->store);
- assert(buf);
+ HDassert(io_info);
+ HDassert(io_info->dset);
+ HDassert(io_info->store);
+ HDassert(buf);
/* Check if data sieving is enabled */
- if(H5F_HAS_FEATURE(file,H5FD_FEAT_DATA_SIEVE)) {
- haddr_t sieve_start=HADDR_UNDEF, sieve_end=HADDR_UNDEF; /* Start & end locations of sieve buffer */
+ if(H5F_HAS_FEATURE(file, H5FD_FEAT_DATA_SIEVE)) {
+ haddr_t sieve_start = HADDR_UNDEF, sieve_end = HADDR_UNDEF; /* Start & end locations of sieve buffer */
haddr_t contig_end; /* End locations of block to write */
- size_t sieve_size=(size_t)-1; /* size of sieve buffer */
+ size_t sieve_size = (size_t)-1; /* size of sieve buffer */
haddr_t abs_eoa; /* Absolute end of file address */
haddr_t rel_eoa; /* Relative end of file address */
hsize_t max_data; /* Actual maximum size of data to cache */
/* Set offsets in sequence lists */
- u=*dset_curr_seq;
- v=*mem_curr_seq;
+ u = *dset_curr_seq;
+ v = *mem_curr_seq;
/* Stash local copies of these value */
- if(dset_contig->sieve_buf!=NULL) {
- sieve_start=dset_contig->sieve_loc;
- sieve_size=dset_contig->sieve_size;
- sieve_end=sieve_start+sieve_size;
+ if(dset_contig->sieve_buf != NULL) {
+ sieve_start = dset_contig->sieve_loc;
+ sieve_size = dset_contig->sieve_size;
+ sieve_end = sieve_start+sieve_size;
} /* end if */
/* Works through sequences as fast as possible */
- for(; u<dset_max_nseq && v<mem_max_nseq; ) {
+ for(; u < dset_max_nseq && v < mem_max_nseq; ) {
/* Choose smallest buffer to write */
- if(mem_len_arr[v]<dset_len_arr[u])
- size=mem_len_arr[v];
+ if(mem_len_arr[v] < dset_len_arr[u])
+ size = mem_len_arr[v];
else
- size=dset_len_arr[u];
+ size = dset_len_arr[u];
/* Compute offset on disk */
- addr=store_contig->dset_addr+dset_offset_arr[u];
+ addr = store_contig->dset_addr + dset_offset_arr[u];
/* Compute offset in memory */
- buf = (unsigned char *)_buf + mem_offset_arr[v];
+ buf = (unsigned char *)io_info->u.rbuf + mem_offset_arr[v];
/* Check if the sieve buffer is allocated yet */
- if(dset_contig->sieve_buf==NULL) {
+ if(dset_contig->sieve_buf == NULL) {
/* Check if we can actually hold the I/O request in the sieve buffer */
if(size>dset_contig->sieve_buf_size) {
- if (H5F_block_read(file, H5FD_MEM_DRAW, addr, size, io_info->dxpl_id, buf)<0)
+ if(H5F_block_read(file, H5FD_MEM_DRAW, addr, size, io_info->dxpl_id, buf) < 0)
HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed")
} /* end if */
else {
@@ -465,40 +598,40 @@ H5D_contig_readvv(const H5D_io_info_t *io_info,
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to determine file size")
/* Adjust absolute EOA address to relative EOA address */
- rel_eoa=abs_eoa-H5F_get_base_addr(file);
+ rel_eoa = abs_eoa - H5F_get_base_addr(file);
/* Set up the buffer parameters */
- max_data=store_contig->dset_size-dset_offset_arr[u];
+ max_data = store_contig->dset_size-dset_offset_arr[u];
/* Compute the size of the sieve buffer */
- H5_ASSIGN_OVERFLOW(dset_contig->sieve_size,MIN3(rel_eoa-dset_contig->sieve_loc,max_data,dset_contig->sieve_buf_size),hsize_t,size_t);
+ H5_ASSIGN_OVERFLOW(dset_contig->sieve_size, MIN3(rel_eoa-dset_contig->sieve_loc, max_data, dset_contig->sieve_buf_size), hsize_t, size_t);
/* Read the new sieve buffer */
- if (H5F_block_read(file, H5FD_MEM_DRAW, dset_contig->sieve_loc, dset_contig->sieve_size, io_info->dxpl_id, dset_contig->sieve_buf)<0)
+ if(H5F_block_read(file, H5FD_MEM_DRAW, dset_contig->sieve_loc, dset_contig->sieve_size, io_info->dxpl_id, dset_contig->sieve_buf) < 0)
HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed")
/* Grab the data out of the buffer (must be first piece of data in buffer ) */
- HDmemcpy(buf,dset_contig->sieve_buf,size);
+ HDmemcpy(buf, dset_contig->sieve_buf, size);
/* Reset sieve buffer dirty flag */
- dset_contig->sieve_dirty=0;
+ dset_contig->sieve_dirty = 0;
/* Stash local copies of these value */
- sieve_start=dset_contig->sieve_loc;
- sieve_size=dset_contig->sieve_size;
- sieve_end=sieve_start+sieve_size;
+ sieve_start = dset_contig->sieve_loc;
+ sieve_size = dset_contig->sieve_size;
+ sieve_end = sieve_start+sieve_size;
} /* end else */
} /* end if */
else {
/* Compute end of sequence to retrieve */
- contig_end=addr+size-1;
+ contig_end = addr + size - 1;
/* If entire read is within the sieve buffer, read it from the buffer */
if(addr>=sieve_start && contig_end<sieve_end) {
unsigned char *base_sieve_buf=dset_contig->sieve_buf+(addr-sieve_start);
/* Grab the data out of the buffer */
- HDmemcpy(buf,base_sieve_buf,size);
+ HDmemcpy(buf, base_sieve_buf, size);
} /* end if */
/* Entire request is not within this data sieve buffer */
else {
@@ -510,16 +643,16 @@ H5D_contig_readvv(const H5D_io_info_t *io_info,
/* Flush the sieve buffer, if it's dirty */
if(dset_contig->sieve_dirty) {
/* Write to file */
- if (H5F_block_write(file, H5FD_MEM_DRAW, sieve_start, sieve_size, io_info->dxpl_id, dset_contig->sieve_buf)<0)
+ if(H5F_block_write(file, H5FD_MEM_DRAW, sieve_start, sieve_size, io_info->dxpl_id, dset_contig->sieve_buf) < 0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed")
/* Reset sieve buffer dirty flag */
- dset_contig->sieve_dirty=0;
+ dset_contig->sieve_dirty = 0;
} /* end if */
} /* end if */
/* Read directly into the user's buffer */
- if (H5F_block_read(file, H5FD_MEM_DRAW, addr, size, io_info->dxpl_id, buf)<0)
+ if(H5F_block_read(file, H5FD_MEM_DRAW, addr, size, io_info->dxpl_id, buf) < 0)
HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed")
} /* end if */
/* Element size fits within the buffer size */
@@ -561,72 +694,72 @@ H5D_contig_readvv(const H5D_io_info_t *io_info,
HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed")
/* Grab the data out of the buffer (must be first piece of data in buffer ) */
- HDmemcpy(buf,dset_contig->sieve_buf,size);
+ HDmemcpy(buf, dset_contig->sieve_buf, size);
/* Reset sieve buffer dirty flag */
- dset_contig->sieve_dirty=0;
+ dset_contig->sieve_dirty = 0;
} /* end else */
} /* end else */
} /* end else */
/* Update memory information */
- mem_len_arr[v]-=size;
- mem_offset_arr[v]+=size;
- if(mem_len_arr[v]==0)
+ mem_len_arr[v] -= size;
+ mem_offset_arr[v] += size;
+ if(mem_len_arr[v] == 0)
v++;
/* Update file information */
- dset_len_arr[u]-=size;
- dset_offset_arr[u]+=size;
- if(dset_len_arr[u]==0)
+ dset_len_arr[u] -= size;
+ dset_offset_arr[u] += size;
+ if(dset_len_arr[u] == 0)
u++;
/* Increment number of bytes copied */
- total_size+=size;
+ total_size += size;
} /* end for */
} /* end if */
else {
/* Work through all the sequences */
- for(u=*dset_curr_seq, v=*mem_curr_seq; u<dset_max_nseq && v<mem_max_nseq; ) {
+ for(u = *dset_curr_seq, v = *mem_curr_seq; u < dset_max_nseq && v < mem_max_nseq; ) {
/* Choose smallest buffer to write */
- if(mem_len_arr[v]<dset_len_arr[u])
- size=mem_len_arr[v];
+ if(mem_len_arr[v] < dset_len_arr[u])
+ size = mem_len_arr[v];
else
- size=dset_len_arr[u];
+ size = dset_len_arr[u];
/* Compute offset on disk */
- addr=store_contig->dset_addr+dset_offset_arr[u];
+ addr = store_contig->dset_addr + dset_offset_arr[u];
/* Compute offset in memory */
- buf = (unsigned char *)_buf + mem_offset_arr[v];
+ buf = (unsigned char *)io_info->u.rbuf + mem_offset_arr[v];
/* Write data */
- if (H5F_block_read(file, H5FD_MEM_DRAW, addr, size, io_info->dxpl_id, buf)<0)
+ if(H5F_block_read(file, H5FD_MEM_DRAW, addr, size, io_info->dxpl_id, buf) < 0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed")
/* Update memory information */
- mem_len_arr[v]-=size;
- mem_offset_arr[v]+=size;
- if(mem_len_arr[v]==0)
+ mem_len_arr[v] -= size;
+ mem_offset_arr[v] += size;
+ if(mem_len_arr[v] == 0)
v++;
/* Update file information */
- dset_len_arr[u]-=size;
- dset_offset_arr[u]+=size;
- if(dset_len_arr[u]==0)
+ dset_len_arr[u] -= size;
+ dset_offset_arr[u] += size;
+ if(dset_len_arr[u] == 0)
u++;
/* Increment number of bytes copied */
- total_size+=size;
+ total_size += size;
} /* end for */
} /* end else */
/* Update current sequence vectors */
- *dset_curr_seq=u;
- *mem_curr_seq=v;
+ *dset_curr_seq = u;
+ *mem_curr_seq = v;
/* Set return value */
- H5_ASSIGN_OVERFLOW(ret_value,total_size,size_t,ssize_t);
+ H5_ASSIGN_OVERFLOW(ret_value, total_size, size_t, ssize_t);
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -654,15 +787,14 @@ done:
ssize_t
H5D_contig_writevv(const H5D_io_info_t *io_info,
size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_len_arr[], hsize_t dset_offset_arr[],
- size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[],
- haddr_t UNUSED address, void UNUSED *pointer, const void *_buf)
+ size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[])
{
H5F_t *file = io_info->dset->oloc.file; /* File for dataset */
- H5D_rdcdc_t *dset_contig=&(io_info->dset->shared->cache.contig); /* Cached information about contiguous data */
- const H5D_contig_storage_t *store_contig=&(io_info->store->contig); /* Contiguous storage info for this I/O operation */
- const unsigned char *buf=(const unsigned char *)_buf; /* Pointer to buffer to fill */
+ H5D_rdcdc_t *dset_contig = &(io_info->dset->shared->cache.contig); /* Cached information about contiguous data */
+ const H5D_contig_storage_t *store_contig = &(io_info->store->contig); /* Contiguous storage info for this I/O operation */
+ const unsigned char *buf = (const unsigned char *)io_info->u.wbuf; /* Pointer to buffer to fill */
haddr_t addr; /* Actual address to read */
- size_t total_size=0; /* Size of sequence in bytes */
+ size_t total_size = 0; /* Size of sequence in bytes */
size_t size; /* Size of sequence in bytes */
size_t u; /* Counting variable */
size_t v; /* Counting variable */
@@ -671,10 +803,10 @@ H5D_contig_writevv(const H5D_io_info_t *io_info,
FUNC_ENTER_NOAPI(H5D_contig_writevv, FAIL)
/* Check args */
- assert(io_info);
- assert(io_info->dset);
- assert(io_info->store);
- assert(buf);
+ HDassert(io_info);
+ HDassert(io_info->dset);
+ HDassert(io_info->store);
+ HDassert(buf);
/* Check if data sieving is enabled */
if(H5F_HAS_FEATURE(file,H5FD_FEAT_DATA_SIEVE)) {
@@ -708,18 +840,18 @@ H5D_contig_writevv(const H5D_io_info_t *io_info,
addr=store_contig->dset_addr+dset_offset_arr[u];
/* Compute offset in memory */
- buf = (const unsigned char *)_buf + mem_offset_arr[v];
+ buf = (const unsigned char *)io_info->u.wbuf + mem_offset_arr[v];
/* No data sieve buffer yet, go allocate one */
if(dset_contig->sieve_buf==NULL) {
/* Check if we can actually hold the I/O request in the sieve buffer */
if(size>dset_contig->sieve_buf_size) {
- if (H5F_block_write(file, H5FD_MEM_DRAW, addr, size, io_info->dxpl_id, buf)<0)
+ if(H5F_block_write(file, H5FD_MEM_DRAW, addr, size, io_info->dxpl_id, buf) < 0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed")
} /* end if */
else {
/* Allocate room for the data sieve buffer */
- if (NULL==(dset_contig->sieve_buf=H5FL_BLK_MALLOC(sieve_buf,dset_contig->sieve_buf_size)))
+ if(NULL == (dset_contig->sieve_buf = H5FL_BLK_MALLOC(sieve_buf, dset_contig->sieve_buf_size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
#ifdef H5_CLEAR_MEMORY
if(dset_contig->sieve_size > size)
@@ -750,15 +882,15 @@ if(dset_contig->sieve_size > size)
} /* end if */
/* Grab the data out of the buffer (must be first piece of data in buffer ) */
- HDmemcpy(dset_contig->sieve_buf,buf,size);
+ HDmemcpy(dset_contig->sieve_buf, buf, size);
/* Set sieve buffer dirty flag */
- dset_contig->sieve_dirty=1;
+ dset_contig->sieve_dirty = 1;
/* Stash local copies of these values */
- sieve_start=dset_contig->sieve_loc;
- sieve_size=dset_contig->sieve_size;
- sieve_end=sieve_start+sieve_size;
+ sieve_start = dset_contig->sieve_loc;
+ sieve_size = dset_contig->sieve_size;
+ sieve_end = sieve_start + sieve_size;
} /* end else */
} /* end if */
else {
@@ -767,13 +899,13 @@ if(dset_contig->sieve_size > size)
/* If entire write is within the sieve buffer, write it to the buffer */
if(addr>=sieve_start && contig_end<sieve_end) {
- unsigned char *base_sieve_buf=dset_contig->sieve_buf+(addr-sieve_start);
+ unsigned char *base_sieve_buf = dset_contig->sieve_buf + (addr - sieve_start);
/* Put the data into the sieve buffer */
- HDmemcpy(base_sieve_buf,buf,size);
+ HDmemcpy(base_sieve_buf, buf, size);
/* Set sieve buffer dirty flag */
- dset_contig->sieve_dirty=1;
+ dset_contig->sieve_dirty = 1;
} /* end if */
/* Entire request is not within this data sieve buffer */
else {
@@ -798,7 +930,7 @@ if(dset_contig->sieve_size > size)
} /* end if */
/* Write directly from the user's buffer */
- if (H5F_block_write(file, H5FD_MEM_DRAW, addr, size, io_info->dxpl_id, buf)<0)
+ if(H5F_block_write(file, H5FD_MEM_DRAW, addr, size, io_info->dxpl_id, buf) < 0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed")
} /* end if */
/* Element size fits within the buffer size */
@@ -808,30 +940,30 @@ if(dset_contig->sieve_size > size)
(size+sieve_size)<=dset_contig->sieve_buf_size &&
dset_contig->sieve_dirty) {
/* Prepend to existing sieve buffer */
- if((addr+size)==sieve_start) {
+ if((addr + size) == sieve_start) {
/* Move existing sieve information to correct location */
- HDmemmove(dset_contig->sieve_buf+size,dset_contig->sieve_buf,dset_contig->sieve_size);
+ HDmemmove(dset_contig->sieve_buf + size, dset_contig->sieve_buf, dset_contig->sieve_size);
/* Copy in new information (must be first in sieve buffer) */
- HDmemcpy(dset_contig->sieve_buf,buf,size);
+ HDmemcpy(dset_contig->sieve_buf, buf, size);
/* Adjust sieve location */
- dset_contig->sieve_loc=addr;
+ dset_contig->sieve_loc = addr;
} /* end if */
/* Append to existing sieve buffer */
else {
/* Copy in new information */
- HDmemcpy(dset_contig->sieve_buf+sieve_size,buf,size);
+ HDmemcpy(dset_contig->sieve_buf + sieve_size, buf, size);
} /* end else */
/* Adjust sieve size */
dset_contig->sieve_size += size;
/* Update local copies of sieve information */
- sieve_start=dset_contig->sieve_loc;
- sieve_size=dset_contig->sieve_size;
- sieve_end=sieve_start+sieve_size;
+ sieve_start = dset_contig->sieve_loc;
+ sieve_size = dset_contig->sieve_size;
+ sieve_end = sieve_start + sieve_size;
} /* end if */
/* Can't add the new data onto the existing sieve buffer */
else {
@@ -875,73 +1007,73 @@ if(dset_contig->sieve_size > size)
} /* end if */
/* Grab the data out of the buffer (must be first piece of data in buffer ) */
- HDmemcpy(dset_contig->sieve_buf,buf,size);
+ HDmemcpy(dset_contig->sieve_buf, buf, size);
/* Set sieve buffer dirty flag */
- dset_contig->sieve_dirty=1;
+ dset_contig->sieve_dirty = 1;
} /* end else */
} /* end else */
} /* end else */
} /* end else */
/* Update memory information */
- mem_len_arr[v]-=size;
- mem_offset_arr[v]+=size;
- if(mem_len_arr[v]==0)
+ mem_len_arr[v] -= size;
+ mem_offset_arr[v] += size;
+ if(mem_len_arr[v] == 0)
v++;
/* Update file information */
- dset_len_arr[u]-=size;
- dset_offset_arr[u]+=size;
- if(dset_len_arr[u]==0)
+ dset_len_arr[u] -= size;
+ dset_offset_arr[u] += size;
+ if(dset_len_arr[u] == 0)
u++;
/* Increment number of bytes copied */
- total_size+=size;
+ total_size += size;
} /* end for */
} /* end if */
else {
/* Work through all the sequences */
- for(u=*dset_curr_seq, v=*mem_curr_seq; u<dset_max_nseq && v<mem_max_nseq; ) {
+ for(u = *dset_curr_seq, v = *mem_curr_seq; u < dset_max_nseq && v < mem_max_nseq; ) {
/* Choose smallest buffer to write */
- if(mem_len_arr[v]<dset_len_arr[u])
- size=mem_len_arr[v];
+ if(mem_len_arr[v] < dset_len_arr[u])
+ size = mem_len_arr[v];
else
- size=dset_len_arr[u];
+ size = dset_len_arr[u];
/* Compute offset on disk */
- addr=store_contig->dset_addr+dset_offset_arr[u];
+ addr = store_contig->dset_addr + dset_offset_arr[u];
/* Compute offset in memory */
- buf = (const unsigned char *)_buf + mem_offset_arr[v];
+ buf = (const unsigned char *)io_info->u.wbuf + mem_offset_arr[v];
/* Write data */
- if (H5F_block_write(file, H5FD_MEM_DRAW, addr, size, io_info->dxpl_id, buf)<0)
+ if(H5F_block_write(file, H5FD_MEM_DRAW, addr, size, io_info->dxpl_id, buf) < 0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed")
/* Update memory information */
- mem_len_arr[v]-=size;
- mem_offset_arr[v]+=size;
- if(mem_len_arr[v]==0)
+ mem_len_arr[v] -= size;
+ mem_offset_arr[v] += size;
+ if(mem_len_arr[v] == 0)
v++;
/* Update file information */
- dset_len_arr[u]-=size;
- dset_offset_arr[u]+=size;
- if(dset_len_arr[u]==0)
+ dset_len_arr[u] -= size;
+ dset_offset_arr[u] += size;
+ if(dset_len_arr[u] == 0)
u++;
/* Increment number of bytes copied */
- total_size+=size;
+ total_size += size;
} /* end for */
} /* end else */
/* Update current sequence vectors */
- *dset_curr_seq=u;
- *mem_curr_seq=v;
+ *dset_curr_seq = u;
+ *mem_curr_seq = v;
/* Set return value */
- H5_ASSIGN_OVERFLOW(ret_value,total_size,size_t,ssize_t);
+ H5_ASSIGN_OVERFLOW(ret_value, total_size, size_t, ssize_t);
done:
FUNC_LEAVE_NOAPI(ret_value)
diff --git a/src/H5Ddeprec.c b/src/H5Ddeprec.c
index 8f8aa50..fd1d2e8 100644
--- a/src/H5Ddeprec.c
+++ b/src/H5Ddeprec.c
@@ -156,7 +156,7 @@ H5Dcreate1(hid_t loc_id, const char *name, hid_t type_id, hid_t space_id,
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name")
if(H5I_DATATYPE != H5I_get_type(type_id))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype ID")
- if(NULL == (space = H5I_object_verify(space_id,H5I_DATASPACE)))
+ if(NULL == (space = (const H5S_t *)H5I_object_verify(space_id,H5I_DATASPACE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace ID")
if(H5P_DEFAULT == dcpl_id)
dcpl_id = H5P_DATASET_CREATE_DEFAULT;
diff --git a/src/H5Defl.c b/src/H5Defl.c
index c8d1098..7dac29b 100644
--- a/src/H5Defl.c
+++ b/src/H5Defl.c
@@ -33,30 +33,88 @@
#include "H5Eprivate.h" /* Error handling */
#include "H5Fprivate.h" /* Files */
+
/****************/
/* Local Macros */
/****************/
+
/******************/
/* Local Typedefs */
/******************/
+
/********************/
/* Local Prototypes */
/********************/
-static herr_t H5D_efl_read (const H5O_efl_t *efl, haddr_t addr, size_t size,
+
+/* Layout operation callbacks */
+static herr_t H5D_efl_io_init(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
+ hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space,
+ H5D_chunk_map_t *cm);
+static ssize_t H5D_efl_readvv(const H5D_io_info_t *io_info,
+ size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_len_arr[], hsize_t dset_offset_arr[],
+ size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[]);
+static ssize_t H5D_efl_writevv(const H5D_io_info_t *io_info,
+ size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_len_arr[], hsize_t dset_offset_arr[],
+ size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[]);
+
+/* Helper routines */
+static herr_t H5D_efl_read(const H5O_efl_t *efl, haddr_t addr, size_t size,
uint8_t *buf);
static herr_t H5D_efl_write(const H5O_efl_t *efl, haddr_t addr, size_t size,
const uint8_t *buf);
+
/*********************/
/* Package Variables */
/*********************/
+/* External File List (EFL) storage layout I/O ops */
+const H5D_layout_ops_t H5D_LOPS_EFL[1] = {{
+ H5D_efl_io_init,
+ H5D_contig_read,
+ H5D_contig_write,
+#ifdef H5_HAVE_PARALLEL
+ NULL,
+ NULL,
+#endif /* H5_HAVE_PARALLEL */
+ H5D_efl_readvv,
+ H5D_efl_writevv,
+ NULL
+}};
+
+
/*******************/
/* Local Variables */
/*******************/
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_efl_io_init
+ *
+ * Purpose: Performs initialization before any sort of I/O on the raw data
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, March 20, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_efl_io_init(const H5D_io_info_t *io_info, const H5D_type_info_t UNUSED *type_info,
+ hsize_t UNUSED nelmts, const H5S_t UNUSED *file_space, const H5S_t UNUSED *mem_space,
+ H5D_chunk_map_t UNUSED *cm)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_efl_io_init)
+
+ HDmemcpy(&io_info->store->efl, &(io_info->dset->shared->dcpl_cache.efl), sizeof(H5O_efl_t));
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5D_efl_io_init() */
+
/*-------------------------------------------------------------------------
* Function: H5D_efl_read
@@ -77,26 +135,26 @@ static herr_t H5D_efl_write(const H5O_efl_t *efl, haddr_t addr, size_t size,
*-------------------------------------------------------------------------
*/
static herr_t
-H5D_efl_read (const H5O_efl_t *efl, haddr_t addr, size_t size, uint8_t *buf)
+H5D_efl_read(const H5O_efl_t *efl, haddr_t addr, size_t size, uint8_t *buf)
{
- int fd=-1;
+ int fd = -1;
size_t to_read;
#ifndef NDEBUG
hsize_t tempto_read;
#endif /* NDEBUG */
- hsize_t skip=0;
+ hsize_t skip = 0;
haddr_t cur;
ssize_t n;
size_t u; /* Local index variable */
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5D_efl_read)
/* Check args */
- assert (efl && efl->nused>0);
- assert (H5F_addr_defined (addr));
- assert (size < SIZET_MAX);
- assert (buf || 0==size);
+ HDassert(efl && efl->nused>0);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(size < SIZET_MAX);
+ HDassert(buf || 0 == size);
/* Find the first efl member from which to read */
for (u=0, cur=0; u<efl->nused; u++) {
@@ -109,7 +167,7 @@ H5D_efl_read (const H5O_efl_t *efl, haddr_t addr, size_t size, uint8_t *buf)
/* Read the data */
while (size) {
- assert(buf);
+ HDassert(buf);
if (u>=efl->nused)
HGOTO_ERROR (H5E_EFL, H5E_OVERFLOW, FAIL, "read past logical end of file")
if (H5F_OVERFLOW_HSIZET2OFFT (efl->slot[u].offset+skip))
@@ -165,25 +223,25 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5D_efl_write (const H5O_efl_t *efl, haddr_t addr, size_t size, const uint8_t *buf)
+H5D_efl_write(const H5O_efl_t *efl, haddr_t addr, size_t size, const uint8_t *buf)
{
- int fd=-1;
+ int fd = -1;
size_t to_write;
#ifndef NDEBUG
hsize_t tempto_write;
#endif /* NDEBUG */
haddr_t cur;
- hsize_t skip=0;
+ hsize_t skip = 0;
size_t u; /* Local index variable */
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5D_efl_write)
/* Check args */
- assert (efl && efl->nused>0);
- assert (H5F_addr_defined (addr));
- assert (size < SIZET_MAX);
- assert (buf || 0==size);
+ HDassert(efl && efl->nused>0);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(size < SIZET_MAX);
+ HDassert(buf || 0 == size);
/* Find the first efl member in which to write */
for (u=0, cur=0; u<efl->nused; u++) {
@@ -248,71 +306,68 @@ done:
* Programmer: Quincey Koziol
* Wednesday, May 7, 2003
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
-ssize_t
+static ssize_t
H5D_efl_readvv(const H5D_io_info_t *io_info,
size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_len_arr[], hsize_t dset_offset_arr[],
- size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[],
- haddr_t UNUSED address, void UNUSED *pointer/*in*/, void *_buf)
+ size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[])
{
- const H5O_efl_t *efl=&(io_info->store->efl); /* Pointer to efl info */
+ const H5O_efl_t *efl = &(io_info->store->efl); /* Pointer to efl info */
unsigned char *buf; /* Pointer to buffer to write */
haddr_t addr; /* Actual address to read */
- size_t total_size=0; /* Total size of sequence in bytes */
+ size_t total_size = 0; /* Total size of sequence in bytes */
size_t size; /* Size of sequence in bytes */
size_t u; /* Counting variable */
size_t v; /* Counting variable */
ssize_t ret_value; /* Return value */
- FUNC_ENTER_NOAPI(H5D_efl_readvv, FAIL)
+ FUNC_ENTER_NOAPI_NOINIT(H5D_efl_readvv)
/* Check args */
- assert (efl && efl->nused>0);
- assert (_buf);
+ HDassert(efl && efl->nused > 0);
+ HDassert(io_info->u.rbuf);
/* Work through all the sequences */
- for(u=*dset_curr_seq, v=*mem_curr_seq; u<dset_max_nseq && v<mem_max_nseq; ) {
+ for(u = *dset_curr_seq, v = *mem_curr_seq; u < dset_max_nseq && v < mem_max_nseq; ) {
/* Choose smallest buffer to write */
- if(mem_len_arr[v]<dset_len_arr[u])
- size=mem_len_arr[v];
+ if(mem_len_arr[v] < dset_len_arr[u])
+ size = mem_len_arr[v];
else
- size=dset_len_arr[u];
+ size = dset_len_arr[u];
/* Compute offset on disk */
- addr=dset_offset_arr[u];
+ addr = dset_offset_arr[u];
/* Compute offset in memory */
- buf = (unsigned char *)_buf + mem_offset_arr[v];
+ buf = (unsigned char *)io_info->u.rbuf + mem_offset_arr[v];
/* Read data */
- if (H5D_efl_read(efl, addr, size, buf)<0)
+ if(H5D_efl_read(efl, addr, size, buf) < 0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed")
/* Update memory information */
- mem_len_arr[v]-=size;
- mem_offset_arr[v]+=size;
- if(mem_len_arr[v]==0)
+ mem_len_arr[v] -= size;
+ mem_offset_arr[v] += size;
+ if(mem_len_arr[v] == 0)
v++;
/* Update file information */
- dset_len_arr[u]-=size;
- dset_offset_arr[u]+=size;
- if(dset_len_arr[u]==0)
+ dset_len_arr[u] -= size;
+ dset_offset_arr[u] += size;
+ if(dset_len_arr[u] == 0)
u++;
/* Increment number of bytes copied */
- total_size+=size;
+ total_size += size;
} /* end for */
/* Update current sequence vectors */
- *dset_curr_seq=u;
- *mem_curr_seq=v;
+ *dset_curr_seq = u;
+ *mem_curr_seq = v;
/* Set return value */
- H5_ASSIGN_OVERFLOW(ret_value,total_size,size_t,ssize_t);
+ H5_ASSIGN_OVERFLOW(ret_value, total_size, size_t, ssize_t);
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -332,71 +387,68 @@ done:
* Programmer: Quincey Koziol
* Friday, May 2, 2003
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
-ssize_t
+static ssize_t
H5D_efl_writevv(const H5D_io_info_t *io_info,
size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_len_arr[], hsize_t dset_offset_arr[],
- size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[],
- haddr_t UNUSED address, void UNUSED *pointer/*in*/, const void *_buf)
+ size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[])
{
- const H5O_efl_t *efl=&(io_info->store->efl); /* Pointer to efl info */
+ const H5O_efl_t *efl = &(io_info->store->efl); /* Pointer to efl info */
const unsigned char *buf; /* Pointer to buffer to write */
haddr_t addr; /* Actual address to read */
- size_t total_size=0; /* Total size of sequence in bytes */
+ size_t total_size = 0; /* Total size of sequence in bytes */
size_t size; /* Size of sequence in bytes */
size_t u; /* Counting variable */
size_t v; /* Counting variable */
ssize_t ret_value; /* Return value */
- FUNC_ENTER_NOAPI(H5D_efl_writevv, FAIL)
+ FUNC_ENTER_NOAPI_NOINIT(H5D_efl_writevv)
/* Check args */
- assert (efl && efl->nused>0);
- assert (_buf);
+ HDassert(efl && efl->nused > 0);
+ HDassert(io_info->u.wbuf);
/* Work through all the sequences */
- for(u=*dset_curr_seq, v=*mem_curr_seq; u<dset_max_nseq && v<mem_max_nseq; ) {
+ for(u = *dset_curr_seq, v = *mem_curr_seq; u < dset_max_nseq && v < mem_max_nseq; ) {
/* Choose smallest buffer to write */
- if(mem_len_arr[v]<dset_len_arr[u])
- size=mem_len_arr[v];
+ if(mem_len_arr[v] < dset_len_arr[u])
+ size = mem_len_arr[v];
else
- size=dset_len_arr[u];
+ size = dset_len_arr[u];
/* Compute offset on disk */
- addr=dset_offset_arr[u];
+ addr = dset_offset_arr[u];
/* Compute offset in memory */
- buf = (const unsigned char *)_buf + mem_offset_arr[v];
+ buf = (const unsigned char *)io_info->u.wbuf + mem_offset_arr[v];
/* Write data */
- if (H5D_efl_write(efl, addr, size, buf)<0)
+ if(H5D_efl_write(efl, addr, size, buf) < 0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed")
/* Update memory information */
- mem_len_arr[v]-=size;
- mem_offset_arr[v]+=size;
- if(mem_len_arr[v]==0)
+ mem_len_arr[v] -= size;
+ mem_offset_arr[v] += size;
+ if(mem_len_arr[v] == 0)
v++;
/* Update file information */
- dset_len_arr[u]-=size;
- dset_offset_arr[u]+=size;
- if(dset_len_arr[u]==0)
+ dset_len_arr[u] -= size;
+ dset_offset_arr[u] += size;
+ if(dset_len_arr[u] == 0)
u++;
/* Increment number of bytes copied */
- total_size+=size;
+ total_size += size;
} /* end for */
/* Update current sequence vectors */
- *dset_curr_seq=u;
- *mem_curr_seq=v;
+ *dset_curr_seq = u;
+ *mem_curr_seq = v;
/* Set return value */
- H5_ASSIGN_OVERFLOW(ret_value,total_size,size_t,ssize_t);
+ H5_ASSIGN_OVERFLOW(ret_value, total_size, size_t, ssize_t);
done:
FUNC_LEAVE_NOAPI(ret_value)
diff --git a/src/H5Dfill.c b/src/H5Dfill.c
index bfb4354..4879f4d 100644
--- a/src/H5Dfill.c
+++ b/src/H5Dfill.c
@@ -275,7 +275,7 @@ H5D_fill(const void *fill, const H5T_t *fill_type, void *buf,
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize memory selection information")
/* Scatter the data into memory */
- if(H5D_select_mscat(tmp_buf, space, &mem_iter, (size_t)nelmts, dxpl_cache, buf/*out*/) < 0) {
+ if(H5D_scatter_mem(tmp_buf, space, &mem_iter, (size_t)nelmts, dxpl_cache, buf/*out*/) < 0) {
H5S_SELECT_ITER_RELEASE(&mem_iter);
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "scatter failed")
} /* end if */
@@ -337,13 +337,13 @@ done:
if(dst_id != (-1) && H5I_dec_ref(dst_id) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't decrement temporary datatype ID")
if(tmp_buf)
- H5FL_BLK_FREE(type_conv, tmp_buf);
+ (void)H5FL_BLK_FREE(type_conv, tmp_buf);
if(elem_wb && H5WB_unwrap(elem_wb) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close wrapped buffer")
if(bkg_elem_wb && H5WB_unwrap(bkg_elem_wb) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close wrapped buffer")
if(bkg_buf)
- H5FL_BLK_FREE(type_conv, bkg_buf);
+ (void)H5FL_BLK_FREE(type_conv, bkg_buf);
FUNC_LEAVE_NOAPI(ret_value)
} /* H5D_fill() */
@@ -636,9 +636,9 @@ H5D_fill_release(H5D_fill_buf_info_t *fb_info)
fb_info->fill_free_func(fb_info->fill_buf, fb_info->fill_free_info);
else {
if(fb_info->fill->buf)
- H5FL_BLK_FREE(non_zero_fill, fb_info->fill_buf);
+ (void)H5FL_BLK_FREE(non_zero_fill, fb_info->fill_buf);
else
- H5FL_BLK_FREE(zero_fill, fb_info->fill_buf);
+ (void)H5FL_BLK_FREE(zero_fill, fb_info->fill_buf);
} /* end else */
fb_info->fill_buf = NULL;
} /* end if */
@@ -677,7 +677,7 @@ H5D_fill_term(H5D_fill_buf_info_t *fb_info)
else if(fb_info->mem_type)
H5T_close(fb_info->mem_type);
if(fb_info->bkg_buf)
- H5FL_BLK_FREE(type_conv, fb_info->bkg_buf);
+ (void)H5FL_BLK_FREE(type_conv, fb_info->bkg_buf);
} /* end if */
FUNC_LEAVE_NOAPI(SUCCEED)
diff --git a/src/H5Dint.c b/src/H5Dint.c
index a5ea398..acb95d2 100644
--- a/src/H5Dint.c
+++ b/src/H5Dint.c
@@ -59,10 +59,12 @@ typedef struct {
/* General stuff */
static herr_t H5D_init_storage(H5D_t *dataset, hbool_t full_overwrite, hid_t dxpl_id);
+static herr_t H5D_get_dxpl_cache_real(hid_t dxpl_id, H5D_dxpl_cache_t *cache);
static H5D_shared_t *H5D_new(hid_t dcpl_id, hbool_t creating, hbool_t vl_type);
static herr_t H5D_init_type(H5F_t *file, const H5D_t *dset, hid_t type_id,
const H5T_t *type);
static herr_t H5D_init_space(H5F_t *file, const H5D_t *dset, const H5S_t *space);
+static herr_t H5D_set_io_ops(H5D_t *dataset);
static herr_t H5D_update_oh_info(H5F_t *file, hid_t dxpl_id, H5D_t *dset);
static herr_t H5D_open_oid(H5D_t *dataset, hid_t dxpl_id);
static herr_t H5D_flush_real(H5D_t *dataset, hid_t dxpl_id, unsigned flags);
@@ -250,6 +252,133 @@ H5D_term_interface(void)
} /* end H5D_term_interface() */
+/*--------------------------------------------------------------------------
+ NAME
+ H5D_get_dxpl_cache_real
+ PURPOSE
+ Get all the values for the DXPL cache.
+ USAGE
+ herr_t H5D_get_dxpl_cache_real(dxpl_id, cache)
+ hid_t dxpl_id; IN: DXPL to query
+ H5D_dxpl_cache_t *cache;IN/OUT: DXPL cache to fill with values
+ RETURNS
+ Non-negative on success/Negative on failure.
+ DESCRIPTION
+ Query all the values from a DXPL that are needed by internal routines
+ within the library.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+static herr_t
+H5D_get_dxpl_cache_real(hid_t dxpl_id, H5D_dxpl_cache_t *cache)
+{
+ H5P_genplist_t *dx_plist; /* Data transfer property list */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_get_dxpl_cache_real)
+
+ /* Check args */
+ HDassert(cache);
+
+ /* Get the dataset transfer property list */
+ if(NULL == (dx_plist = (H5P_genplist_t *)H5I_object(dxpl_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset transfer property list")
+
+ /* Get maximum temporary buffer size */
+ if(H5P_get(dx_plist, H5D_XFER_MAX_TEMP_BUF_NAME, &cache->max_temp_buf) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "Can't retrieve maximum temporary buffer size")
+
+ /* Get temporary buffer pointer */
+ if(H5P_get(dx_plist, H5D_XFER_TCONV_BUF_NAME, &cache->tconv_buf) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "Can't retrieve temporary buffer pointer")
+
+ /* Get background buffer pointer */
+ if(H5P_get(dx_plist, H5D_XFER_BKGR_BUF_NAME, &cache->bkgr_buf) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "Can't retrieve background buffer pointer")
+
+ /* Get background buffer type */
+ if(H5P_get(dx_plist, H5D_XFER_BKGR_BUF_TYPE_NAME, &cache->bkgr_buf_type) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "Can't retrieve background buffer type")
+
+ /* Get B-tree split ratios */
+ if(H5P_get(dx_plist, H5D_XFER_BTREE_SPLIT_RATIO_NAME, &cache->btree_split_ratio) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "Can't retrieve B-tree split ratios")
+
+ /* Get I/O vector size */
+ if(H5P_get(dx_plist, H5D_XFER_HYPER_VECTOR_SIZE_NAME, &cache->vec_size) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "Can't retrieve I/O vector size")
+
+#ifdef H5_HAVE_PARALLEL
+ /* Collect Parallel I/O information for possible later use */
+ if(H5P_get(dx_plist, H5D_XFER_IO_XFER_MODE_NAME, &cache->xfer_mode) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "Can't retrieve parallel transfer method")
+ if(H5P_get(dx_plist, H5D_XFER_MPIO_COLLECTIVE_OPT_NAME, &cache->coll_opt_mode) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "Can't retrieve collective transfer option")
+#endif /* H5_HAVE_PARALLEL */
+
+ /* Get error detection properties */
+ if(H5P_get(dx_plist, H5D_XFER_EDC_NAME, &cache->err_detect) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "Can't retrieve error detection info")
+
+ /* Get filter callback function */
+ if(H5P_get(dx_plist, H5D_XFER_FILTER_CB_NAME, &cache->filter_cb) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "Can't retrieve filter callback function")
+
+ /* Get the data transform property */
+ if(H5P_get(dx_plist, H5D_XFER_XFORM_NAME, &cache->data_xform_prop) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "Can't retrieve data transform info")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5D_get_dxpl_cache_real() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5D_get_dxpl_cache
+ PURPOSE
+ Get all the values for the DXPL cache.
+ USAGE
+ herr_t H5D_get_dxpl_cache(dxpl_id, cache)
+ hid_t dxpl_id; IN: DXPL to query
+ H5D_dxpl_cache_t *cache;IN/OUT: DXPL cache to fill with values
+ RETURNS
+ Non-negative on success/Negative on failure.
+ DESCRIPTION
+ Query all the values from a DXPL that are needed by internal routines
+ within the library.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ The CACHE pointer should point at already allocated memory to place
+ non-default property list info. If a default property list is used, the
+ CACHE pointer will be changed to point at the default information.
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+herr_t
+H5D_get_dxpl_cache(hid_t dxpl_id, H5D_dxpl_cache_t **cache)
+{
+ herr_t ret_value=SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5D_get_dxpl_cache,FAIL)
+
+ /* Check args */
+ assert(cache);
+
+ /* Check for the default DXPL */
+ if(dxpl_id==H5P_DATASET_XFER_DEFAULT)
+ *cache=&H5D_def_dxpl_cache;
+ else
+ if(H5D_get_dxpl_cache_real(dxpl_id,*cache) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "Can't retrieve DXPL values")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5D_get_dxpl_cache() */
+
+
/*-------------------------------------------------------------------------
* Function: H5D_create_named
*
@@ -556,6 +685,54 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5D_set_io_ops
+ *
+ * Purpose: Set the I/O operation function pointers for a dataset
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, March 20, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_set_io_ops(H5D_t *dataset)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_set_io_ops)
+
+ /* check args */
+ HDassert(dataset);
+
+ /* Set the I/O functions for each layout type */
+ switch(dataset->shared->layout.type) {
+ case H5D_CONTIGUOUS:
+ if(dataset->shared->dcpl_cache.efl.nused > 0)
+ dataset->shared->layout_ops = H5D_LOPS_EFL;
+ else
+ dataset->shared->layout_ops = H5D_LOPS_CONTIG;
+ break;
+
+ case H5D_CHUNKED:
+ dataset->shared->layout_ops = H5D_LOPS_CHUNK;
+ break;
+
+ case H5D_COMPACT:
+ dataset->shared->layout_ops = H5D_LOPS_COMPACT;
+ break;
+
+ default:
+ HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unknown storage method")
+ } /* end switch */ /*lint !e788 All appropriate cases are covered */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_set_io_ops() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5D_update_oh_info
*
* Purpose: Create and fill object header for dataset
@@ -979,18 +1156,10 @@ H5D_create(H5F_t *file, hid_t type_id, const H5S_t *space, hid_t dcpl_id,
} else if(max_points * H5T_get_size(type) > max_storage) {
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "data space size exceeds external storage size")
}
-
- /* Set the I/O functions for this layout type */
- new_dset->shared->io_ops.readvv = H5D_efl_readvv;
- new_dset->shared->io_ops.writevv = H5D_efl_writevv;
} /* end if */
else {
if(ndims > 0 && max_dim[0] > dim[0])
HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, NULL, "extendible contiguous non-external dataset")
-
- /* Set the I/O functions for this layout type */
- new_dset->shared->io_ops.readvv = H5D_contig_readvv;
- new_dset->shared->io_ops.writevv = H5D_contig_writevv;
} /* end else */
/* Compute the total size of a chunk */
@@ -1042,10 +1211,6 @@ H5D_create(H5F_t *file, hid_t type_id, const H5S_t *space, hid_t dcpl_id,
for(u = 1, new_dset->shared->layout.u.chunk.size = new_dset->shared->layout.u.chunk.dim[0]; u < new_dset->shared->layout.u.chunk.ndims; u++)
new_dset->shared->layout.u.chunk.size *= new_dset->shared->layout.u.chunk.dim[u];
- /* Set the I/O functions for this layout type */
- new_dset->shared->io_ops.readvv = H5D_istore_readvv;
- new_dset->shared->io_ops.writevv = H5D_istore_writevv;
-
/* Initialize the chunk cache for the dataset */
if(H5D_istore_init(file, new_dset) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "can't initialize chunk cache")
@@ -1073,10 +1238,6 @@ H5D_create(H5F_t *file, hid_t type_id, const H5S_t *space, hid_t dcpl_id,
comp_data_size = H5O_MESG_MAX_SIZE - H5O_layout_meta_size(file, &(new_dset->shared->layout));
if(new_dset->shared->layout.u.compact.size > comp_data_size)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "compact dataset size is bigger than header message maximum size")
-
- /* Set the I/O functions for this layout type */
- new_dset->shared->io_ops.readvv = H5D_compact_readvv;
- new_dset->shared->io_ops.writevv = H5D_compact_writevv;
} /* end case */
break;
@@ -1084,6 +1245,10 @@ H5D_create(H5F_t *file, hid_t type_id, const H5S_t *space, hid_t dcpl_id,
HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, NULL, "not implemented yet")
} /* end switch */ /*lint !e788 All appropriate cases are covered */
+ /* Set the dataset's I/O operations */
+ if(H5D_set_io_ops(new_dset) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to initialize I/O operations")
+
/* Update the dataset's object header info. */
if(H5D_update_oh_info(file, dxpl_id, new_dset) != SUCCEED)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "can't update the metadata cache")
@@ -1252,9 +1417,9 @@ static herr_t
H5D_open_oid(H5D_t *dataset, hid_t dxpl_id)
{
H5P_genplist_t *plist; /* Property list */
- H5O_pline_t *pline; /* I/O pipeline information */
H5O_fill_t *fill_prop; /* Pointer to dataset's fill value info */
unsigned alloc_time_state; /* Allocation time state */
+ htri_t msg_exists; /* Whether a particular type of message exists */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5D_open_oid)
@@ -1285,13 +1450,17 @@ H5D_open_oid(H5D_t *dataset, hid_t dxpl_id)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get dataset creation property list")
/* Get the optional filters message */
- pline = &dataset->shared->dcpl_cache.pline;
- if(NULL != H5O_msg_read(&(dataset->oloc), H5O_PLINE_ID, pline, dxpl_id)) {
- if(H5P_set(plist, H5D_CRT_DATA_PIPELINE_NAME, pline) < 0)
+ if((msg_exists = H5O_msg_exists(&(dataset->oloc), H5O_PLINE_ID, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't check if message exists")
+ if(msg_exists) {
+ /* Retrieve the I/O pipeline message */
+ if(NULL == H5O_msg_read(&(dataset->oloc), H5O_PLINE_ID, &dataset->shared->dcpl_cache.pline, dxpl_id))
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't retrieve message")
+
+ /* Set the I/O pipeline info in the property list */
+ if(H5P_set(plist, H5D_CRT_DATA_PIPELINE_NAME, &dataset->shared->dcpl_cache.pline) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set pipeline")
} /* end if */
- else
- H5E_clear_stack(NULL);
/*
* Get the raw data layout info. It's actually stored in two locations:
@@ -1316,10 +1485,6 @@ H5D_open_oid(H5D_t *dataset, hid_t dxpl_id)
H5_ASSIGN_OVERFLOW(dataset->shared->layout.u.contig.size, tmp_size, hssize_t, hsize_t);
} /* end if */
- /* Set the I/O functions for this layout type */
- dataset->shared->io_ops.readvv = H5D_contig_readvv;
- dataset->shared->io_ops.writevv = H5D_contig_writevv;
-
/* Get the sieve buffer size for this dataset */
dataset->shared->cache.contig.sieve_buf_size = H5F_SIEVE_BUF_SIZE(dataset->oloc.file);
break;
@@ -1344,33 +1509,34 @@ H5D_open_oid(H5D_t *dataset, hid_t dxpl_id)
if(H5D_istore_init(dataset->oloc.file, dataset) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't initialize chunk cache")
}
-
- /* Set the I/O functions for this layout type */
- dataset->shared->io_ops.readvv = H5D_istore_readvv;
- dataset->shared->io_ops.writevv = H5D_istore_writevv;
break;
case H5D_COMPACT:
- /* Set the I/O functions for this layout type */
- dataset->shared->io_ops.readvv = H5D_compact_readvv;
- dataset->shared->io_ops.writevv = H5D_compact_writevv;
break;
default:
- HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "not implemented yet")
+ HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unknown storage method")
} /* end switch */ /*lint !e788 All appropriate cases are covered */
/* Point at dataset's copy, to cache it for later */
fill_prop = &dataset->shared->dcpl_cache.fill;
/* Try to get the new fill value message from the object header */
- if(NULL == H5O_msg_read(&(dataset->oloc), H5O_FILL_NEW_ID, fill_prop, dxpl_id)) {
- H5E_clear_stack(NULL);
-
+ if((msg_exists = H5O_msg_exists(&(dataset->oloc), H5O_FILL_NEW_ID, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't check if message exists")
+ if(msg_exists) {
+ if(NULL == H5O_msg_read(&(dataset->oloc), H5O_FILL_NEW_ID, fill_prop, dxpl_id))
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't retrieve message")
+ } /* end if */
+ else {
/* For backward compatibility, try to retrieve the old fill value message */
- if(NULL == H5O_msg_read(&(dataset->oloc), H5O_FILL_ID, fill_prop, dxpl_id)) {
- H5E_clear_stack(NULL);
-
+ if((msg_exists = H5O_msg_exists(&(dataset->oloc), H5O_FILL_ID, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't check if message exists")
+ if(msg_exists) {
+ if(NULL == H5O_msg_read(&(dataset->oloc), H5O_FILL_ID, fill_prop, dxpl_id))
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't retrieve message")
+ } /* end if */
+ else {
/* Set the space allocation time appropriately, based on the type of dataset storage */
switch(dataset->shared->layout.type) {
case H5D_COMPACT:
@@ -1388,7 +1554,7 @@ H5D_open_oid(H5D_t *dataset, hid_t dxpl_id)
default:
HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "not implemented yet")
} /* end switch */ /*lint !e788 All appropriate cases are covered */
- } /* end if */
+ } /* end else */
/* If "old" fill value size is 0 (undefined), map it to -1 */
if(fill_prop->size == 0)
@@ -1412,18 +1578,23 @@ H5D_open_oid(H5D_t *dataset, hid_t dxpl_id)
* also undefined when space allocate time is H5D_ALLOC_TIME_LATE. */
if((dataset->shared->layout.type == H5D_CONTIGUOUS && !H5F_addr_defined(dataset->shared->layout.u.contig.addr))
|| (dataset->shared->layout.type == H5D_CHUNKED && !H5F_addr_defined(dataset->shared->layout.u.chunk.addr))) {
- if(NULL != H5O_msg_read(&(dataset->oloc), H5O_EFL_ID, &dataset->shared->dcpl_cache.efl, dxpl_id)) {
+ if((msg_exists = H5O_msg_exists(&(dataset->oloc), H5O_EFL_ID, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't check if message exists")
+ if(msg_exists) {
+ /* Retrieve the EFL message */
+ if(NULL == H5O_msg_read(&(dataset->oloc), H5O_EFL_ID, &dataset->shared->dcpl_cache.efl, dxpl_id))
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't retrieve message")
+
+ /* Set the EFL info in the property list */
if(H5P_set(plist, H5D_CRT_EXT_FILE_LIST_NAME, &dataset->shared->dcpl_cache.efl) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set external file list")
-
- /* Override the I/O functions for this layout type */
- dataset->shared->io_ops.readvv = H5D_efl_readvv;
- dataset->shared->io_ops.writevv = H5D_efl_writevv;
} /* end if */
- else
- H5E_clear_stack(NULL);
} /* end if */
+ /* Set the dataset's I/O operations */
+ if(H5D_set_io_ops(dataset) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize I/O operations")
+
/*
* Make sure all storage is properly initialized.
* This is important only for parallel I/O where the space must
@@ -2334,7 +2505,7 @@ H5D_set_extent(H5D_t *dset, const hsize_t *size, hid_t dxpl_id)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't fill dxpl cache")
/* Construct dataset I/O info */
- H5D_BUILD_IO_INFO(&io_info, dset, dxpl_cache, dxpl_id, NULL);
+ H5D_BUILD_IO_INFO_RD(&io_info, dset, dxpl_cache, dxpl_id, NULL, NULL);
/* Remove excess chunks */
if(H5D_istore_prune_by_extent(&io_info, curr_dims) < 0)
diff --git a/src/H5Dio.c b/src/H5Dio.c
index 8576464..17bab19 100644
--- a/src/H5Dio.c
+++ b/src/H5Dio.c
@@ -28,27 +28,17 @@
#include "H5Eprivate.h" /* Error handling */
#include "H5FLprivate.h" /* Free Lists */
#include "H5Iprivate.h" /* IDs */
-#include "H5MMprivate.h" /* Memory management */
-#include "H5Sprivate.h" /* Dataspace functions */
-#include "H5SLprivate.h" /* Skip lists */
-#include "H5Vprivate.h" /* Vector and array functions */
#ifdef H5_HAVE_PARALLEL
/* Remove this if H5R_DATASET_REGION is no longer used in this file */
-# include "H5Rpublic.h"
+#include "H5Rpublic.h"
#endif /*H5_HAVE_PARALLEL*/
+
/****************/
/* Local Macros */
/****************/
-#define H5D_DEFAULT_SKIPLIST_HEIGHT 8
-
-/* Macros for iterating over chunks to operate on */
-#define H5D_CHUNK_GET_FIRST_NODE(map) (map.use_single ? (H5SL_node_t *)(1) : H5SL_first(map.sel_chunks))
-#define H5D_CHUNK_GET_NODE_INFO(map, node) (map.use_single ? map.single_chunk_info : (H5D_chunk_info_t *)H5SL_item(node))
-#define H5D_CHUNK_GET_NEXT_NODE(map, node) (map.use_single ? (H5SL_node_t *)NULL : H5SL_next(node))
-
/******************/
/* Local Typedefs */
@@ -59,64 +49,36 @@
/* Local Prototypes */
/********************/
+/* Internal I/O routines */
static herr_t H5D_read(H5D_t *dataset, hid_t mem_type_id,
- const H5S_t *mem_space, const H5S_t *file_space,
- hid_t dset_xfer_plist, void *buf/*out*/);
+ const H5S_t *mem_space, const H5S_t *file_space, hid_t dset_xfer_plist,
+ void *buf/*out*/);
static herr_t H5D_write(H5D_t *dataset, hid_t mem_type_id,
- const H5S_t *mem_space, const H5S_t *file_space,
- hid_t dset_xfer_plist, const void *buf);
-static herr_t H5D_contig_read(H5D_io_info_t *io_info, hsize_t nelmts,
- const H5T_t *mem_type, const H5S_t *mem_space,
- const H5S_t *file_space, H5T_path_t *tpath,
- hid_t src_id, hid_t dst_id, void *buf/*out*/);
-static herr_t H5D_contig_write(H5D_io_info_t *io_info, hsize_t nelmts,
- const H5T_t *mem_type, const H5S_t *mem_space,
- const H5S_t *file_space, H5T_path_t *tpath,
- hid_t src_id, hid_t dst_id, const void *buf);
-static herr_t H5D_chunk_read(H5D_io_info_t *io_info, hsize_t nelmts,
- const H5T_t *mem_type, const H5S_t *mem_space,
- const H5S_t *file_space, H5T_path_t *tpath,
- hid_t src_id, hid_t dst_id, void *buf/*out*/);
-static herr_t H5D_chunk_write(H5D_io_info_t *io_info, hsize_t nelmts,
- const H5T_t *mem_type, const H5S_t *mem_space,
- const H5S_t *file_space, H5T_path_t *tpath,
- hid_t src_id, hid_t dst_id, const void *buf);
-static herr_t H5D_compound_opt_read(size_t nelmts, const H5S_t *mem_space,
- H5S_sel_iter_t *iter, const H5D_dxpl_cache_t *dxpl_cache,
- hid_t src_id, hid_t dst_id, H5T_subset_t subset, void *data_buf,
- void *user_buf/*out*/);
-static herr_t H5D_compound_opt_write(size_t nelmts, hid_t src_id, hid_t dst_id,
- void *data_buf);
+ const H5S_t *mem_space, const H5S_t *file_space, hid_t dset_xfer_plist,
+ const void *buf);
+/* Setup/teardown routines */
+static herr_t H5D_ioinfo_init(H5D_t *dset, const H5D_dxpl_cache_t *dxpl_cache,
+ hid_t dxpl_id, const H5D_type_info_t *type_info, H5D_storage_t *store,
+ H5D_io_info_t *io_info);
+static herr_t H5D_typeinfo_init(const H5D_t *dset, const H5D_dxpl_cache_t *dxpl_cache,
+ hid_t dxpl_id, hid_t mem_type_id, hbool_t do_write,
+ H5D_type_info_t *type_info);
#ifdef H5_HAVE_PARALLEL
+static herr_t H5D_ioinfo_adjust(H5D_io_info_t *io_info, const H5D_t *dset,
+ const H5D_dxpl_cache_t *dxpl_cache, hid_t dxpl_id,
+ const H5S_t *file_space, const H5S_t *mem_space,
+ const H5D_type_info_t *type_info, const H5D_chunk_map_t *fm);
static herr_t H5D_ioinfo_term(H5D_io_info_t *io_info);
#endif /* H5_HAVE_PARALLEL */
+static herr_t H5D_typeinfo_term(const H5D_type_info_t *type_info);
-/* I/O info operations */
-static herr_t H5D_ioinfo_init(H5D_t *dset, const H5D_dxpl_cache_t *dxpl_cache,
- hid_t dxpl_id, const H5S_t *mem_space, const H5S_t *file_space,
- H5T_path_t *tpath, H5D_io_info_t *io_info);
-
-/* Chunk operations */
-static herr_t H5D_create_chunk_map(H5D_chunk_map_t *fm, const H5D_io_info_t *io_info,
- hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space,
- const H5T_t *mem_type);
-static herr_t H5D_destroy_chunk_map(const H5D_chunk_map_t *fm);
-static herr_t H5D_free_chunk_info(void *item, void *key, void *opdata);
-static herr_t H5D_create_chunk_map_single(H5D_chunk_map_t *fm,
- const H5D_io_info_t *io_info);
-static herr_t H5D_create_chunk_file_map_hyper(H5D_chunk_map_t *fm,
- const H5D_io_info_t *io_info);
-static herr_t H5D_create_chunk_mem_map_hyper(const H5D_chunk_map_t *fm);
-static herr_t H5D_chunk_file_cb(void *elem, hid_t type_id, unsigned ndims,
- const hsize_t *coords, void *fm);
-static herr_t H5D_chunk_mem_cb(void *elem, hid_t type_id, unsigned ndims,
- const hsize_t *coords, void *fm);
/*********************/
/* Package Variables */
/*********************/
+
/*******************/
/* Local Variables */
/*******************/
@@ -124,142 +86,6 @@ static herr_t H5D_chunk_mem_cb(void *elem, hid_t type_id, unsigned ndims,
/* Declare a free list to manage blocks of type conversion data */
H5FL_BLK_DEFINE(type_conv);
-/* Declare a free list to manage the H5D_chunk_info_t struct */
-H5FL_DEFINE(H5D_chunk_info_t);
-
-/* Declare a free list to manage sequences of size_t */
-H5FL_SEQ_DEFINE_STATIC(size_t);
-
-/* Declare a free list to manage sequences of hsize_t */
-H5FL_SEQ_DEFINE_STATIC(hsize_t);
-
-
-
-/*--------------------------------------------------------------------------
- NAME
- H5D_get_dxpl_cache_real
- PURPOSE
- Get all the values for the DXPL cache.
- USAGE
- herr_t H5D_get_dxpl_cache_real(dxpl_id, cache)
- hid_t dxpl_id; IN: DXPL to query
- H5D_dxpl_cache_t *cache;IN/OUT: DXPL cache to fill with values
- RETURNS
- Non-negative on success/Negative on failure.
- DESCRIPTION
- Query all the values from a DXPL that are needed by internal routines
- within the library.
- GLOBAL VARIABLES
- COMMENTS, BUGS, ASSUMPTIONS
- EXAMPLES
- REVISION LOG
---------------------------------------------------------------------------*/
-herr_t
-H5D_get_dxpl_cache_real(hid_t dxpl_id, H5D_dxpl_cache_t *cache)
-{
- H5P_genplist_t *dx_plist; /* Data transfer property list */
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5D_get_dxpl_cache_real,FAIL)
-
- /* Check args */
- assert(cache);
-
- /* Get the dataset transfer property list */
- if (NULL == (dx_plist = (H5P_genplist_t *)H5I_object(dxpl_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset transfer property list")
-
- /* Get maximum temporary buffer size */
- if(H5P_get(dx_plist, H5D_XFER_MAX_TEMP_BUF_NAME, &cache->max_temp_buf) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "Can't retrieve maximum temporary buffer size")
-
- /* Get temporary buffer pointer */
- if(H5P_get(dx_plist, H5D_XFER_TCONV_BUF_NAME, &cache->tconv_buf) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "Can't retrieve temporary buffer pointer")
-
- /* Get background buffer pointer */
- if(H5P_get(dx_plist, H5D_XFER_BKGR_BUF_NAME, &cache->bkgr_buf) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "Can't retrieve background buffer pointer")
-
- /* Get background buffer type */
- if(H5P_get(dx_plist, H5D_XFER_BKGR_BUF_TYPE_NAME, &cache->bkgr_buf_type) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "Can't retrieve background buffer type")
-
- /* Get B-tree split ratios */
- if(H5P_get(dx_plist, H5D_XFER_BTREE_SPLIT_RATIO_NAME, &cache->btree_split_ratio) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "Can't retrieve B-tree split ratios")
-
- /* Get I/O vector size */
- if(H5P_get(dx_plist, H5D_XFER_HYPER_VECTOR_SIZE_NAME, &cache->vec_size) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "Can't retrieve I/O vector size")
-
-#ifdef H5_HAVE_PARALLEL
- /* Collect Parallel I/O information for possible later use */
- if(H5P_get(dx_plist, H5D_XFER_IO_XFER_MODE_NAME, &cache->xfer_mode) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "Can't retrieve parallel transfer method")
- if(H5P_get(dx_plist, H5D_XFER_IO_XFER_OPT_MODE_NAME, &cache->xfer_opt_mode) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "Can't retrieve parallel transfer method")
-#endif /*H5_HAVE_PARALLEL*/
-
- /* Get error detection properties */
- if(H5P_get(dx_plist, H5D_XFER_EDC_NAME, &cache->err_detect) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "Can't retrieve error detection info")
-
- /* Get filter callback function */
- if(H5P_get(dx_plist, H5D_XFER_FILTER_CB_NAME, &cache->filter_cb) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "Can't retrieve filter callback function")
-
- /* Get the data transform property */
- if(H5P_get(dx_plist, H5D_XFER_XFORM_NAME, &cache->data_xform_prop) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "Can't retrieve data transform info")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5D_get_dxpl_cache_real() */
-
-
-/*--------------------------------------------------------------------------
- NAME
- H5D_get_dxpl_cache
- PURPOSE
- Get all the values for the DXPL cache.
- USAGE
- herr_t H5D_get_dxpl_cache(dxpl_id, cache)
- hid_t dxpl_id; IN: DXPL to query
- H5D_dxpl_cache_t *cache;IN/OUT: DXPL cache to fill with values
- RETURNS
- Non-negative on success/Negative on failure.
- DESCRIPTION
- Query all the values from a DXPL that are needed by internal routines
- within the library.
- GLOBAL VARIABLES
- COMMENTS, BUGS, ASSUMPTIONS
- The CACHE pointer should point at already allocated memory to place
- non-default property list info. If a default property list is used, the
- CACHE pointer will be changed to point at the default information.
- EXAMPLES
- REVISION LOG
---------------------------------------------------------------------------*/
-herr_t
-H5D_get_dxpl_cache(hid_t dxpl_id, H5D_dxpl_cache_t **cache)
-{
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5D_get_dxpl_cache,FAIL)
-
- /* Check args */
- assert(cache);
-
- /* Check for the default DXPL */
- if(dxpl_id==H5P_DATASET_XFER_DEFAULT)
- *cache=&H5D_def_dxpl_cache;
- else
- if(H5D_get_dxpl_cache_real(dxpl_id,*cache) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "Can't retrieve DXPL values")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5D_get_dxpl_cache() */
/*-------------------------------------------------------------------------
@@ -300,7 +126,7 @@ H5Dread(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id,
const H5S_t *mem_space = NULL;
const H5S_t *file_space = NULL;
char fake_char;
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(H5Dread, FAIL)
H5TRACE6("e", "iiiiix", dset_id, mem_type_id, mem_space_id, file_space_id,
@@ -316,7 +142,7 @@ H5Dread(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id,
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space")
/* Check for valid selection */
- if(H5S_SELECT_VALID(mem_space)!=TRUE)
+ if(H5S_SELECT_VALID(mem_space) != TRUE)
HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "selection+offset not within extent")
} /* end if */
if(H5S_ALL != file_space_id) {
@@ -324,33 +150,33 @@ H5Dread(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id,
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space")
/* Check for valid selection */
- if(H5S_SELECT_VALID(file_space)!=TRUE)
+ if(H5S_SELECT_VALID(file_space) != TRUE)
HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "selection+offset not within extent")
- }
+ } /* end if */
/* Get the default dataset transfer property list if the user didn't provide one */
if (H5P_DEFAULT == plist_id)
plist_id= H5P_DATASET_XFER_DEFAULT;
else
- if (TRUE!=H5P_isa_class(plist_id,H5P_DATASET_XFER))
+ if(TRUE != H5P_isa_class(plist_id, H5P_DATASET_XFER))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not xfer parms")
- if (!buf && H5S_GET_SELECT_NPOINTS(file_space)!=0)
+ if(!buf && H5S_GET_SELECT_NPOINTS(file_space) != 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no output buffer")
/* If the buffer is nil, and 0 element is selected, make a fake buffer.
* This is for some MPI package like ChaMPIon on NCSA's tungsten which
* doesn't support this feature.
*/
- if (!buf)
+ if(!buf)
buf = &fake_char;
/* read raw data */
- if (H5D_read(dset, mem_type_id, mem_space, file_space, plist_id, buf/*out*/) < 0)
+ if(H5D_read(dset, mem_type_id, mem_space, file_space, plist_id, buf/*out*/) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't read data")
done:
FUNC_LEAVE_API(ret_value)
-}
+} /* end H5Dread() */
/*-------------------------------------------------------------------------
@@ -392,7 +218,7 @@ H5Dwrite(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id,
const H5S_t *mem_space = NULL;
const H5S_t *file_space = NULL;
char fake_char;
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(H5Dwrite, FAIL)
H5TRACE6("e", "iiiii*x", dset_id, mem_type_id, mem_space_id, file_space_id,
@@ -408,7 +234,7 @@ H5Dwrite(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id,
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space")
/* Check for valid selection */
- if (H5S_SELECT_VALID(mem_space)!=TRUE)
+ if(H5S_SELECT_VALID(mem_space) != TRUE)
HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "memory selection+offset not within extent")
} /* end if */
if(H5S_ALL != file_space_id) {
@@ -416,7 +242,7 @@ H5Dwrite(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id,
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space")
/* Check for valid selection */
- if(H5S_SELECT_VALID(file_space)!=TRUE)
+ if(H5S_SELECT_VALID(file_space) != TRUE)
HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "file selection+offset not within extent")
} /* end if */
@@ -424,16 +250,16 @@ H5Dwrite(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id,
if(H5P_DEFAULT == plist_id)
plist_id= H5P_DATASET_XFER_DEFAULT;
else
- if(TRUE!=H5P_isa_class(plist_id,H5P_DATASET_XFER))
+ if(TRUE != H5P_isa_class(plist_id, H5P_DATASET_XFER))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not xfer parms")
- if(!buf && H5S_GET_SELECT_NPOINTS(file_space)!=0)
+ if(!buf && H5S_GET_SELECT_NPOINTS(file_space) != 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no output buffer")
/* If the buffer is nil, and 0 element is selected, make a fake buffer.
* This is for some MPI package like ChaMPIon on NCSA's tungsten which
* doesn't support this feature.
*/
- if (!buf)
+ if(!buf)
buf = &fake_char;
/* write raw data */
@@ -442,7 +268,7 @@ H5Dwrite(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id,
done:
FUNC_LEAVE_API(ret_value)
-}
+} /* end H5Dwrite() */
/*-------------------------------------------------------------------------
@@ -462,16 +288,18 @@ static herr_t
H5D_read(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space,
const H5S_t *file_space, hid_t dxpl_id, void *buf/*out*/)
{
+ H5D_chunk_map_t fm; /* Chunk file<->memory mapping */
+ H5D_io_info_t io_info; /* Dataset I/O info */
+ H5D_type_info_t type_info; /* Datatype info for operation */
+ H5D_storage_t store; /*union of EFL and chunk pointer in file space */
hssize_t snelmts; /*total number of elmts (signed) */
hsize_t nelmts; /*total number of elmts */
- H5T_path_t *tpath = NULL; /*type conversion info */
- const H5T_t *mem_type = NULL; /* Memory datatype */
- H5D_io_info_t io_info; /* Dataset I/O info */
#ifdef H5_HAVE_PARALLEL
hbool_t io_info_init = FALSE; /* Whether the I/O info has been initialized */
#endif /*H5_HAVE_PARALLEL*/
+ hbool_t io_op_init = FALSE; /* Whether the I/O op has been initialized */
H5D_dxpl_cache_t _dxpl_cache; /* Data transfer property cache buffer */
- H5D_dxpl_cache_t *dxpl_cache=&_dxpl_cache; /* Data transfer property cache */
+ H5D_dxpl_cache_t *dxpl_cache = &_dxpl_cache; /* Data transfer property cache */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5D_read)
@@ -479,10 +307,6 @@ H5D_read(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space,
/* check args */
HDassert(dataset && dataset->oloc.file);
- /* Get memory datatype */
- if(NULL == (mem_type = (const H5T_t *)H5I_object_verify(mem_type_id, H5I_DATATYPE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
-
if(!file_space)
file_space = dataset->shared->space;
if(!mem_space)
@@ -492,23 +316,27 @@ H5D_read(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space,
H5_ASSIGN_OVERFLOW(nelmts,snelmts,hssize_t,hsize_t);
/* Fill the DXPL cache values for later use */
- if(H5D_get_dxpl_cache(dxpl_id,&dxpl_cache) < 0)
+ if(H5D_get_dxpl_cache(dxpl_id, &dxpl_cache) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't fill dxpl cache")
+ /* Set up datatype info for operation */
+ if(H5D_typeinfo_init(dataset, dxpl_cache, dxpl_id, mem_type_id, FALSE, &type_info) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to set up type info")
+
#ifdef H5_HAVE_PARALLEL
/* Collective access is not permissible without a MPI based VFD */
- if (dxpl_cache->xfer_mode==H5FD_MPIO_COLLECTIVE && !IS_H5FD_MPI(dataset->oloc.file))
+ if(dxpl_cache->xfer_mode == H5FD_MPIO_COLLECTIVE && !IS_H5FD_MPI(dataset->oloc.file))
HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "collective access for MPI-based drivers only")
#endif /*H5_HAVE_PARALLEL*/
/* Make certain that the number of elements in each selection is the same */
- if (nelmts!=(hsize_t)H5S_GET_SELECT_NPOINTS(file_space))
+ if(nelmts != (hsize_t)H5S_GET_SELECT_NPOINTS(file_space))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "src and dest data spaces have different sizes")
/* Make sure that both selections have their extents set */
- if( !(H5S_has_extent(file_space)) )
+ if(!(H5S_has_extent(file_space)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "file dataspace does not have extent set")
- if( !(H5S_has_extent(mem_space)) )
+ if(!(H5S_has_extent(mem_space)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "memory dataspace does not have extent set")
/* Retrieve dataset properties */
@@ -539,49 +367,56 @@ H5D_read(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space,
HGOTO_DONE(SUCCEED)
/* Go fill the user's selection with the dataset's fill value */
- if(H5D_fill(dataset->shared->dcpl_cache.fill.buf, dataset->shared->type, buf, mem_type, mem_space, dxpl_id) < 0)
+ if(H5D_fill(dataset->shared->dcpl_cache.fill.buf, dataset->shared->type, buf, type_info.mem_type, mem_space, dxpl_id) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "filling buf failed")
else
HGOTO_DONE(SUCCEED)
} /* end if */
- /*
- * Locate the type conversion function and data space conversion
- * functions, and set up the element numbering information. If a data
- * type conversion is necessary then register datatype atoms. Data type
- * conversion is necessary if the user has set the `need_bkg' to a high
- * enough value in xfer_parms since turning off datatype conversion also
- * turns off background preservation.
- */
- if (NULL==(tpath=H5T_path_find(dataset->shared->type, mem_type, NULL, NULL, dxpl_id, FALSE)))
- HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dest datatype")
-
/* Set up I/O operation */
- if(H5D_ioinfo_init(dataset,dxpl_cache,dxpl_id,mem_space,file_space,tpath,&io_info) < 0)
+ io_info.op_type = H5D_IO_OP_READ;
+ io_info.u.rbuf = buf;
+ if(H5D_ioinfo_init(dataset, dxpl_cache, dxpl_id, &type_info, &store, &io_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unable to set up I/O operation")
#ifdef H5_HAVE_PARALLEL
io_info_init = TRUE;
#endif /*H5_HAVE_PARALLEL*/
- /* Determine correct I/O routine to invoke */
- if(dataset->shared->layout.type!=H5D_CHUNKED) {
- if(H5D_contig_read(&io_info, nelmts, mem_type, mem_space, file_space, tpath,
- dataset->shared->type_id, mem_type_id, buf) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't read data")
- } /* end if */
- else {
- if(H5D_chunk_read(&io_info, nelmts, mem_type, mem_space, file_space, tpath,
- dataset->shared->type_id, mem_type_id, buf) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't read data")
- } /* end else */
+ /* Sanity check that space is allocated, if there are elements */
+ if(nelmts > 0)
+ HDassert(((dataset->shared->layout.type == H5D_CONTIGUOUS && H5F_addr_defined(dataset->shared->layout.u.contig.addr))
+ || (dataset->shared->layout.type == H5D_CHUNKED && H5F_addr_defined(dataset->shared->layout.u.chunk.addr)))
+ || dataset->shared->dcpl_cache.efl.nused > 0
+ || dataset->shared->layout.type == H5D_COMPACT);
+
+ /* Call storage method's I/O initialization routine */
+ if(io_info.layout_ops.init && (*io_info.layout_ops.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;
+
+#ifdef H5_HAVE_PARALLEL
+ /* Adjust I/O info for any parallel I/O */
+ if(H5D_ioinfo_adjust(&io_info, dataset, dxpl_cache, dxpl_id, file_space, mem_space, &type_info, &fm) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to adjust I/O info for parallel I/O")
+#endif /*H5_HAVE_PARALLEL*/
+
+ /* Invoke correct "high level" I/O routine */
+ if((*io_info.io_ops.multi_read)(&io_info, &type_info, nelmts, file_space, mem_space, &fm) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't read data")
done:
+ /* Shut down the I/O op information */
+ if(io_op_init && io_info.layout_ops.term && (*io_info.layout_ops.term)(&fm) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "unable to shut down I/O op info")
#ifdef H5_HAVE_PARALLEL
/* Shut down io_info struct */
- if (io_info_init)
+ if(io_info_init)
if(H5D_ioinfo_term(&io_info) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "can't shut down io_info")
#endif /*H5_HAVE_PARALLEL*/
+ /* Shut down datatype info for operation */
+ if(H5D_typeinfo_term(&type_info) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "unable to shut down type info")
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D_read() */
@@ -604,16 +439,18 @@ static herr_t
H5D_write(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space,
const H5S_t *file_space, hid_t dxpl_id, const void *buf)
{
+ H5D_chunk_map_t fm; /* Chunk file<->memory mapping */
+ H5D_io_info_t io_info; /* Dataset I/O info */
+ H5D_type_info_t type_info; /* Datatype info for operation */
+ H5D_storage_t store; /*union of EFL and chunk pointer in file space */
hssize_t snelmts; /*total number of elmts (signed) */
hsize_t nelmts; /*total number of elmts */
- H5T_path_t *tpath = NULL; /*type conversion info */
- const H5T_t *mem_type = NULL; /* Memory datatype */
- H5D_io_info_t io_info; /* Dataset I/O info */
#ifdef H5_HAVE_PARALLEL
hbool_t io_info_init = FALSE; /* Whether the I/O info has been initialized */
#endif /*H5_HAVE_PARALLEL*/
+ hbool_t io_op_init = FALSE; /* Whether the I/O op has been initialized */
H5D_dxpl_cache_t _dxpl_cache; /* Data transfer property cache buffer */
- H5D_dxpl_cache_t *dxpl_cache=&_dxpl_cache; /* Data transfer property cache */
+ H5D_dxpl_cache_t *dxpl_cache = &_dxpl_cache; /* Data transfer property cache */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5D_write)
@@ -621,33 +458,33 @@ H5D_write(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space,
/* check args */
HDassert(dataset && dataset->oloc.file);
- /* Get the memory datatype */
- if(NULL == (mem_type = (const H5T_t *)H5I_object_verify(mem_type_id, H5I_DATATYPE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
-
/* All filters in the DCPL must have encoding enabled. */
if(!dataset->shared->checked_filters) {
- if(H5Z_can_apply(dataset->shared->dcpl_id, dataset->shared->type_id) <0)
+ if(H5Z_can_apply(dataset->shared->dcpl_id, dataset->shared->type_id) < 0)
HGOTO_ERROR(H5E_PLINE, H5E_CANAPPLY, FAIL, "can't apply filters")
dataset->shared->checked_filters = TRUE;
} /* end if */
/* Check if we are allowed to write to this file */
- if(0==(H5F_get_intent(dataset->oloc.file) & H5F_ACC_RDWR))
+ if(0 == (H5F_INTENT(dataset->oloc.file) & H5F_ACC_RDWR))
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "no write intent on file")
/* Fill the DXPL cache values for later use */
- if(H5D_get_dxpl_cache(dxpl_id,&dxpl_cache) < 0)
+ if(H5D_get_dxpl_cache(dxpl_id, &dxpl_cache) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't fill dxpl cache")
+ /* Set up datatype info for operation */
+ if(H5D_typeinfo_init(dataset, dxpl_cache, dxpl_id, mem_type_id, TRUE, &type_info) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to set up type info")
+
/* Various MPI based checks */
#ifdef H5_HAVE_PARALLEL
if(IS_H5FD_MPI(dataset->oloc.file)) {
/* If MPI based VFD is used, no VL datatype support yet. */
/* This is because they use the global heap in the file and we don't */
/* support parallel access of that yet */
- if(H5T_detect_class(mem_type, H5T_VLEN)>0)
+ if(H5T_detect_class(type_info.mem_type, H5T_VLEN) > 0)
HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "Parallel IO does not support writing VL datatypes yet")
/* If MPI based VFD is used, no VL datatype support yet. */
@@ -656,42 +493,48 @@ H5D_write(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space,
/* We should really use H5T_detect_class() here, but it will be difficult
* to detect the type of the reference if it is nested... -QAK
*/
- if (H5T_get_class(mem_type, TRUE)==H5T_REFERENCE &&
- H5T_get_ref_type(mem_type)==H5R_DATASET_REGION)
+ if(H5T_get_class(type_info.mem_type, TRUE) == H5T_REFERENCE &&
+ H5T_get_ref_type(type_info.mem_type) == H5R_DATASET_REGION)
HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "Parallel IO does not support writing region reference datatypes yet")
+
+ /* Can't write to chunked datasets with filters, in parallel */
+ if(dataset->shared->layout.type == H5D_CHUNKED &&
+ dataset->shared->dcpl_cache.pline.nused > 0)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "cannot write to chunked storage with filters in parallel")
} /* end if */
else {
/* Collective access is not permissible without a MPI based VFD */
- if (dxpl_cache->xfer_mode==H5FD_MPIO_COLLECTIVE)
+ if(dxpl_cache->xfer_mode == H5FD_MPIO_COLLECTIVE)
HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "collective access for MPI-based driver only")
} /* end else */
#endif /*H5_HAVE_PARALLEL*/
- if (!file_space)
+ /* Initialize dataspace information */
+ if(!file_space)
file_space = dataset->shared->space;
- if (!mem_space)
+ if(!mem_space)
mem_space = file_space;
if((snelmts = H5S_GET_SELECT_NPOINTS(mem_space)) < 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "src dataspace has invalid selection")
- H5_ASSIGN_OVERFLOW(nelmts,snelmts,hssize_t,hsize_t);
+ H5_ASSIGN_OVERFLOW(nelmts, snelmts, hssize_t, hsize_t);
/* Make certain that the number of elements in each selection is the same */
- if (nelmts!=(hsize_t)H5S_GET_SELECT_NPOINTS(file_space))
+ if(nelmts != (hsize_t)H5S_GET_SELECT_NPOINTS(file_space))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "src and dest data spaces have different sizes")
/* Make sure that both selections have their extents set */
- if( !(H5S_has_extent(file_space)) )
+ if(!(H5S_has_extent(file_space)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "file dataspace does not have extent set")
- if( !(H5S_has_extent(mem_space)) )
+ if(!(H5S_has_extent(mem_space)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "memory dataspace does not have extent set")
/* Retrieve dataset properties */
/* <none needed currently> */
/* Allocate data space and initialize it if it hasn't been. */
- if(nelmts > 0 && dataset->shared->dcpl_cache.efl.nused==0 &&
- ((dataset->shared->layout.type==H5D_CONTIGUOUS && !H5F_addr_defined(dataset->shared->layout.u.contig.addr))
- || (dataset->shared->layout.type==H5D_CHUNKED && !H5F_addr_defined(dataset->shared->layout.u.chunk.addr)))) {
+ if(nelmts > 0 && dataset->shared->dcpl_cache.efl.nused == 0 &&
+ ((dataset->shared->layout.type == H5D_CONTIGUOUS && !H5F_addr_defined(dataset->shared->layout.u.contig.addr))
+ || (dataset->shared->layout.type == H5D_CHUNKED && !H5F_addr_defined(dataset->shared->layout.u.chunk.addr)))) {
hssize_t file_nelmts; /* Number of elements in file dataset's dataspace */
hbool_t full_overwrite; /* Whether we are over-writing all the elements */
@@ -703,42 +546,36 @@ H5D_write(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space,
if(H5T_detect_class(dataset->shared->type, H5T_VLEN))
full_overwrite = FALSE;
else
- full_overwrite = (hsize_t)file_nelmts==nelmts ? TRUE : FALSE;
+ full_overwrite = (hsize_t)file_nelmts == nelmts ? TRUE : FALSE;
/* Allocate storage */
if(H5D_alloc_storage(dataset->oloc.file, dxpl_id, dataset, H5D_ALLOC_WRITE, full_overwrite) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize storage")
} /* end if */
- /*
- * Locate the type conversion function and data space conversion
- * functions, and set up the element numbering information. If a data
- * type conversion is necessary then register datatype atoms. Data type
- * conversion is necessary if the user has set the `need_bkg' to a high
- * enough value in xfer_parms since turning off datatype conversion also
- * turns off background preservation.
- */
- if (NULL==(tpath=H5T_path_find(mem_type, dataset->shared->type, NULL, NULL, dxpl_id, FALSE)))
- HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dest datatype")
-
/* Set up I/O operation */
- if(H5D_ioinfo_init(dataset,dxpl_cache,dxpl_id,mem_space,file_space,tpath,&io_info) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unable to set up I/O operation")
+ io_info.op_type = H5D_IO_OP_WRITE;
+ io_info.u.wbuf = buf;
+ if(H5D_ioinfo_init(dataset, dxpl_cache, dxpl_id, &type_info, &store, &io_info) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to set up I/O operation")
#ifdef H5_HAVE_PARALLEL
io_info_init = TRUE;
#endif /*H5_HAVE_PARALLEL*/
- /* Determine correct I/O routine to invoke */
- if(dataset->shared->layout.type!=H5D_CHUNKED) {
- if(H5D_contig_write(&io_info, nelmts, mem_type, mem_space, file_space, tpath,
- mem_type_id, dataset->shared->type_id, buf) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't write data")
- } /* end if */
- else {
- if(H5D_chunk_write(&io_info, nelmts, mem_type, mem_space, file_space, tpath,
- mem_type_id, dataset->shared->type_id, buf) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't write data")
- } /* end else */
+ /* Call storage method's I/O initialization routine */
+ if(io_info.layout_ops.init && (*io_info.layout_ops.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;
+
+#ifdef H5_HAVE_PARALLEL
+ /* Adjust I/O info for any parallel I/O */
+ if(H5D_ioinfo_adjust(&io_info, dataset, dxpl_cache, dxpl_id, file_space, mem_space, &type_info, &fm) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to adjust I/O info for parallel I/O")
+#endif /*H5_HAVE_PARALLEL*/
+
+ /* Invoke correct "high level" I/O routine */
+ if((*io_info.io_ops.multi_write)(&io_info, &type_info, nelmts, file_space, mem_space, &fm) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't write data")
#ifdef OLD_WAY
/*
@@ -756,2667 +593,325 @@ H5D_write(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space,
#endif /* OLD_WAY */
done:
+ /* Shut down the I/O op information */
+ if(io_op_init && io_info.layout_ops.term && (*io_info.layout_ops.term)(&fm) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "unable to shut down I/O op info")
#ifdef H5_HAVE_PARALLEL
/* Shut down io_info struct */
- if (io_info_init)
- if(H5D_ioinfo_term(&io_info) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "can't shut down io_info")
+ if(io_info_init && H5D_ioinfo_term(&io_info) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "can't shut down io_info")
#endif /*H5_HAVE_PARALLEL*/
+ /* Shut down datatype info for operation */
+ if(H5D_typeinfo_term(&type_info) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "unable to shut down type info")
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D_write() */
/*-------------------------------------------------------------------------
- * Function: H5D_contig_read
+ * Function: H5D_ioinfo_init
*
- * Purpose: Read from a contiguous dataset.
+ * Purpose: Routine for determining correct I/O operations for
+ * each I/O action.
*
* Return: Non-negative on success/Negative on failure
*
- * Programmer: Raymond Lu
- * Thursday, April 10, 2003
+ * Programmer: Quincey Koziol
+ * Thursday, September 30, 2004
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5D_contig_read(H5D_io_info_t *io_info, hsize_t nelmts,
- const H5T_t *mem_type, const H5S_t *mem_space,
- const H5S_t *file_space, H5T_path_t *tpath,
- hid_t src_id, hid_t dst_id, void *buf/*out*/)
+H5D_ioinfo_init(H5D_t *dset, const H5D_dxpl_cache_t *dxpl_cache, hid_t dxpl_id,
+ const H5D_type_info_t *type_info, H5D_storage_t *store, H5D_io_info_t *io_info)
{
- H5D_t *dataset=io_info->dset; /* Local pointer to dataset info */
- const H5D_dxpl_cache_t *dxpl_cache=io_info->dxpl_cache; /* Local pointer to dataset transfer info */
- herr_t status; /*function return status*/
-#ifdef H5S_DEBUG
- H5_timer_t timer;
-#endif
- size_t src_type_size; /*size of source type */
- size_t dst_type_size; /*size of destination type*/
- size_t max_type_size; /* Size of largest source/destination type */
- size_t target_size; /*desired buffer size */
- size_t request_nelmts; /*requested strip mine */
- H5S_sel_iter_t mem_iter; /*memory selection iteration info*/
- hbool_t mem_iter_init=0; /*memory selection iteration info has been initialized */
- H5S_sel_iter_t bkg_iter; /*background iteration info*/
- hbool_t bkg_iter_init=0; /*background iteration info has been initialized */
- H5S_sel_iter_t file_iter; /*file selection iteration info*/
- hbool_t file_iter_init=0; /*file selection iteration info has been initialized */
- H5T_bkg_t need_bkg; /*type of background buf*/
- uint8_t *tconv_buf = NULL; /*datatype conv buffer */
- uint8_t *bkg_buf = NULL; /*background buffer */
- hsize_t smine_start; /*strip mine start loc */
- size_t n, smine_nelmts; /*elements per strip */
- H5D_storage_t store; /*union of storage info for dataset */
-
-
- herr_t ret_value = SUCCEED; /*return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5D_contig_read)
-
- assert (buf);
-
- /* Initialize storage info for this dataset */
- if (dataset->shared->dcpl_cache.efl.nused > 0)
- HDmemcpy(&store.efl, &(dataset->shared->dcpl_cache.efl), sizeof(H5O_efl_t));
- else {
- store.contig.dset_addr = dataset->shared->layout.u.contig.addr;
- store.contig.dset_size = dataset->shared->layout.u.contig.size;
- } /* end if */
-
- /* Set dataset storage for I/O info */
- io_info->store=&store;
-
- /*
- * If there is no type conversion then read directly into the
- * application's buffer. This saves at least one mem-to-mem copy.
- */
- if ( H5Z_xform_noop(dxpl_cache->data_xform_prop) && H5T_path_noop(tpath)) {
-#ifdef H5S_DEBUG
- H5_timer_begin(&timer);
-#endif
- /* Sanity check dataset, then read it */
- assert(((dataset->shared->layout.type == H5D_CONTIGUOUS && H5F_addr_defined(dataset->shared->layout.u.contig.addr))
- || (dataset->shared->layout.type == H5D_CHUNKED && H5F_addr_defined(dataset->shared->layout.u.chunk.addr)))
- || dataset->shared->dcpl_cache.efl.nused > 0 || 0 == nelmts
- || dataset->shared->layout.type==H5D_COMPACT);
- H5_CHECK_OVERFLOW(nelmts,hsize_t,size_t);
-
-#ifdef H5_HAVE_PARALLEL
- if(io_info->dxpl_cache->xfer_mode == H5FD_MPIO_COLLECTIVE) {
- if(H5D_contig_collective_io(io_info,file_space,mem_space,buf,FALSE) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "contiguous read failed in collective mode");
- }
- else
-#endif
- {
- if((io_info->ops.read)(io_info, (size_t)nelmts,
- H5T_get_size(dataset->shared->type), file_space, mem_space,
- (haddr_t)0, NULL, buf/*out*/) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "contiguous read failed ");
- }
-
-#ifdef H5S_DEBUG
- H5_timer_end(&(io_info->stats->stats[1].read_timer), &timer);
- io_info->stats->stats[1].read_nbytes += nelmts * H5T_get_size(dataset->shared->type);
- io_info->stats->stats[1].read_ncalls++;
-#endif
-
- /* direct xfer accomplished successfully */
- HGOTO_DONE(SUCCEED)
- } /* end if */
-
- /*
- * This is the general case (type conversion, usually).
- */
- if(nelmts==0)
- HGOTO_DONE(SUCCEED)
-
- /* Compute element sizes and other parameters */
- src_type_size = H5T_get_size(dataset->shared->type);
- dst_type_size = H5T_get_size(mem_type);
- max_type_size = MAX(src_type_size, dst_type_size);
- target_size = dxpl_cache->max_temp_buf;
- /* XXX: This could cause a problem if the user sets their buffer size
- * to the same size as the default, and then the dataset elements are
- * too large for the buffer... - QAK
- */
- if(target_size == H5D_TEMP_BUF_SIZE) {
- /* If the buffer is too small to hold even one element, make it bigger */
- if(target_size<max_type_size)
- target_size = max_type_size;
- /* If the buffer is too large to hold all the elements, make it smaller */
- else if(target_size>(nelmts*max_type_size))
- target_size=(size_t)(nelmts*max_type_size);
- } /* end if */
- request_nelmts = target_size / max_type_size;
-
- /* Sanity check elements in temporary buffer */
- if (request_nelmts==0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "temporary buffer max size is too small")
-
- /* Figure out the strip mine size. */
- if (H5S_select_iter_init(&file_iter, file_space, src_type_size) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize file selection information")
- file_iter_init=1; /*file selection iteration info has been initialized */
- if (H5S_select_iter_init(&mem_iter, mem_space, dst_type_size) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize memory selection information")
- mem_iter_init=1; /*file selection iteration info has been initialized */
- if (H5S_select_iter_init(&bkg_iter, mem_space, dst_type_size) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize background selection information")
- bkg_iter_init=1; /*file selection iteration info has been initialized */
-
- /*
- * Get a temporary buffer for type conversion unless the app has already
- * supplied one through the xfer properties. Instead of allocating a
- * buffer which is the exact size, we allocate the target size. The
- * malloc() is usually less resource-intensive if we allocate/free the
- * same size over and over.
- */
- if (H5T_path_bkg(tpath)) {
- H5T_bkg_t path_bkg; /* Type conversion's background info */
-
- /* Retrieve the bkgr buffer property */
- need_bkg=dxpl_cache->bkgr_buf_type;
- path_bkg = H5T_path_bkg(tpath);
- need_bkg = MAX(path_bkg, need_bkg);
- } else {
- need_bkg = H5T_BKG_NO; /*never needed even if app says yes*/
- } /* end else */
- if(NULL == (tconv_buf = (uint8_t *)dxpl_cache->tconv_buf)) {
- /* Allocate temporary buffer */
- if(NULL == (tconv_buf = H5FL_BLK_MALLOC(type_conv, target_size)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for type conversion")
- } /* end if */
- if(need_bkg && NULL == (bkg_buf = (uint8_t *)dxpl_cache->bkgr_buf)) {
- /* Allocate background buffer */
- /* (Need calloc()-like call since memory needs to be initialized) */
- if(NULL == (bkg_buf = H5FL_BLK_CALLOC(type_conv, (request_nelmts * dst_type_size))))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for background conversion")
- } /* end if */
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_ioinfo_init)
- /* Start strip mining... */
- for (smine_start=0; smine_start<nelmts; smine_start+=smine_nelmts) {
- /* Go figure out how many elements to read from the file */
- assert(H5S_SELECT_ITER_NELMTS(&file_iter)==(nelmts-smine_start));
- smine_nelmts = (size_t)MIN(request_nelmts, (nelmts-smine_start));
+ /* check args */
+ HDassert(dset);
+ HDassert(dset->oloc.file);
+ HDassert(type_info);
+ HDassert(type_info->tpath);
+ HDassert(io_info);
- /*
- * Gather the data from disk into the datatype conversion
- * buffer. Also gather data from application to background buffer
- * if necessary.
- */
-#ifdef H5S_DEBUG
- H5_timer_begin(&timer);
-#endif
- /* Sanity check that space is allocated, then read data from it */
- HDassert(((dataset->shared->layout.type == H5D_CONTIGUOUS && H5F_addr_defined(dataset->shared->layout.u.contig.addr))
- || (dataset->shared->layout.type == H5D_CHUNKED && H5F_addr_defined(dataset->shared->layout.u.chunk.addr)))
- || dataset->shared->dcpl_cache.efl.nused > 0 ||
- dataset->shared->layout.type == H5D_COMPACT);
- n = H5D_select_fgath(io_info, file_space, &file_iter, smine_nelmts, (haddr_t)0, NULL, tconv_buf/*out*/);
-
-#ifdef H5S_DEBUG
- H5_timer_end(&(io_info->stats->stats[1].gath_timer), &timer);
- io_info->stats->stats[1].gath_nbytes += n * src_type_size;
- io_info->stats->stats[1].gath_ncalls++;
-#endif
- if (n!=smine_nelmts)
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "file gather failed")
-
- /* If the source and destination are compound types and subset of each other
- * and no conversion is needed, copy the data directly into user's buffer and
- * bypass the rest of steps. This optimization is for Chicago company */
- if(H5T_SUBSET_SRC==H5T_path_compound_subset(tpath)) {
- if(H5D_compound_opt_read(smine_nelmts, mem_space, &mem_iter, dxpl_cache,
- src_id, dst_id, H5T_SUBSET_SRC, tconv_buf, buf /*out*/)<0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "datatype conversion failed")
-
- continue;
- } else if(H5T_SUBSET_DST==H5T_path_compound_subset(tpath)) {
- if(H5D_compound_opt_read(smine_nelmts, mem_space, &mem_iter, dxpl_cache,
- src_id, dst_id, H5T_SUBSET_DST, tconv_buf, buf /*out*/)<0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "datatype conversion failed")
-
- continue;
- }
-
- if (H5T_BKG_YES==need_bkg) {
-#ifdef H5S_DEBUG
- H5_timer_begin(&timer);
-#endif
- n = H5D_select_mgath(buf, mem_space, &bkg_iter,
- smine_nelmts, dxpl_cache, bkg_buf/*out*/);
-#ifdef H5S_DEBUG
- H5_timer_end(&(io_info->stats->stats[1].bkg_timer), &timer);
- io_info->stats->stats[1].bkg_nbytes += n * dst_type_size;
- io_info->stats->stats[1].bkg_ncalls++;
-#endif
- if (n!=smine_nelmts)
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "mem gather failed")
- } /* end if */
+ /* Set up "normal" I/O fields */
+ io_info->dset = dset;
+ io_info->dxpl_cache = dxpl_cache;
+ io_info->dxpl_id = dxpl_id;
+ io_info->store = store;
- /*
- * Perform datatype conversion.
- */
- if (H5T_convert(tpath, src_id, dst_id, smine_nelmts, (size_t)0, (size_t)0, tconv_buf, bkg_buf, io_info->dxpl_id) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "datatype conversion failed")
+ /* Set I/O operations to initial values */
+ io_info->layout_ops = *dset->shared->layout_ops;
- /* Do the data transform after the conversion (since we're using type mem_type) */
- if(!H5Z_xform_noop(dxpl_cache->data_xform_prop))
- if( H5Z_xform_eval(dxpl_cache->data_xform_prop, tconv_buf, smine_nelmts, mem_type) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Error performing data transform")
+ /* Set the "high-level" I/O operations for the dataset */
+ io_info->io_ops.multi_read = dset->shared->layout_ops->ser_read;
+ io_info->io_ops.multi_write = dset->shared->layout_ops->ser_write;
+ /* Set the I/O operations for reading/writing single blocks on disk */
+ if(type_info->is_xform_noop && type_info->is_conv_noop) {
/*
- * Scatter the data into memory.
+ * If there is no data transform or type conversion then read directly into
+ * the application's buffer. This saves at least one mem-to-mem copy.
*/
-#ifdef H5S_DEBUG
- H5_timer_begin(&timer);
-#endif
- status = H5D_select_mscat(tconv_buf, mem_space,
- &mem_iter, smine_nelmts, dxpl_cache, buf/*out*/);
-#ifdef H5S_DEBUG
- H5_timer_end(&(io_info->stats->stats[1].scat_timer), &timer);
- io_info->stats->stats[1].scat_nbytes += smine_nelmts * dst_type_size;
- io_info->stats->stats[1].scat_ncalls++;
-#endif
- if (status<0)
- HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "scatter failed")
- } /* end for */
-
-done:
- /* Release selection iterators */
- if(file_iter_init) {
- if(H5S_SELECT_ITER_RELEASE(&file_iter) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
+ io_info->io_ops.single_read = H5D_select_read;
+ io_info->io_ops.single_write = H5D_select_write;
} /* end if */
- if(mem_iter_init) {
- if(H5S_SELECT_ITER_RELEASE(&mem_iter) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
- } /* end if */
- if(bkg_iter_init) {
- if(H5S_SELECT_ITER_RELEASE(&bkg_iter) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
- } /* end if */
-
- if (tconv_buf && NULL==dxpl_cache->tconv_buf)
- (void)H5FL_BLK_FREE(type_conv,tconv_buf);
- if (bkg_buf && NULL==dxpl_cache->bkgr_buf)
- (void)H5FL_BLK_FREE(type_conv,bkg_buf);
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_contig_read() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_contig_write
- *
- * Purpose: Write to a contiguous dataset.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Raymond Lu
- * Thursday, April 10, 2003
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5D_contig_write(H5D_io_info_t *io_info, hsize_t nelmts,
- const H5T_t *mem_type, const H5S_t *mem_space,
- const H5S_t *file_space, H5T_path_t *tpath,
- hid_t src_id, hid_t dst_id, const void *buf)
-{
- H5D_t *dataset=io_info->dset; /* Local pointer to dataset info */
- const H5D_dxpl_cache_t *dxpl_cache=io_info->dxpl_cache; /* Local pointer to dataset transfer info */
- herr_t status; /*function return status*/
-#ifdef H5S_DEBUG
- H5_timer_t timer;
-#endif
- size_t src_type_size; /*size of source type */
- size_t dst_type_size; /*size of destination type*/
- size_t max_type_size; /* Size of largest source/destination type */
- size_t target_size; /*desired buffer size */
- size_t request_nelmts; /*requested strip mine */
- H5S_sel_iter_t mem_iter; /*memory selection iteration info*/
- hbool_t mem_iter_init=0; /*memory selection iteration info has been initialized */
- H5S_sel_iter_t bkg_iter; /*background iteration info*/
- hbool_t bkg_iter_init=0; /*background iteration info has been initialized */
- H5S_sel_iter_t file_iter; /*file selection iteration info*/
- hbool_t file_iter_init=0; /*file selection iteration info has been initialized */
- H5T_bkg_t need_bkg; /*type of background buf*/
- uint8_t *tconv_buf = NULL; /*datatype conv buffer */
- uint8_t *bkg_buf = NULL; /*background buffer */
- hsize_t smine_start; /*strip mine start loc */
- size_t n, smine_nelmts; /*elements per strip */
- H5D_storage_t store; /*union of storage info for dataset */
-
- herr_t ret_value = SUCCEED; /*return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5D_contig_write)
-
- assert (buf);
-
- /* Initialize storage info for this dataset */
- if(dataset->shared->dcpl_cache.efl.nused > 0)
- HDmemcpy(&store.efl, &(dataset->shared->dcpl_cache.efl), sizeof(H5O_efl_t));
else {
- store.contig.dset_addr = dataset->shared->layout.u.contig.addr;
- store.contig.dset_size = dataset->shared->layout.u.contig.size;
- } /* end if */
-
- /* Set dataset storage for I/O info */
- io_info->store = &store;
-
- /*
- * If there is no type conversion then write directly from the
- * application's buffer. This saves at least one mem-to-mem copy.
- */
- if(H5Z_xform_noop(dxpl_cache->data_xform_prop) && H5T_path_noop(tpath)) {
-#ifdef H5S_DEBUG
- H5_timer_begin(&timer);
-#endif
- H5_CHECK_OVERFLOW(nelmts,hsize_t,size_t);
-#ifdef H5_HAVE_PARALLEL
- if(io_info->dxpl_cache->xfer_mode == H5FD_MPIO_COLLECTIVE) {
- if(H5D_contig_collective_io(io_info, file_space, mem_space, buf, TRUE) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "contiguous write failed in collective mode")
- }
- else
-#endif
- {
- if((io_info->ops.write)(io_info, (size_t)nelmts,
- H5T_get_size(dataset->shared->type), file_space, mem_space,
- (haddr_t)0, NULL, buf/*out*/) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "contiguous write failed ")
- }
-
-#ifdef H5S_DEBUG
- H5_timer_end(&(io_info->stats->stats[0].write_timer), &timer);
- io_info->stats->stats[0].write_nbytes += nelmts * H5T_get_size(mem_type);
- io_info->stats->stats[0].write_ncalls++;
-#endif
-
- /* direct xfer accomplished successfully */
- HGOTO_DONE(SUCCEED)
- } /* end if */
-
- /*
- * This is the general case.
- */
- if(nelmts==0)
- HGOTO_DONE(SUCCEED)
-
- /* Compute element sizes and other parameters */
- src_type_size = H5T_get_size(mem_type);
- dst_type_size = H5T_get_size(dataset->shared->type);
- max_type_size = MAX(src_type_size, dst_type_size);
- target_size = dxpl_cache->max_temp_buf;
- /* XXX: This could cause a problem if the user sets their buffer size
- * to the same size as the default, and then the dataset elements are
- * too large for the buffer... - QAK
- */
- if(target_size == H5D_TEMP_BUF_SIZE) {
- /* If the buffer is too small to hold even one element, make it bigger */
- if(target_size<max_type_size)
- target_size = max_type_size;
- /* If the buffer is too large to hold all the elements, make it smaller */
- else if(target_size>(nelmts*max_type_size))
- target_size=(size_t)(nelmts*max_type_size);
- } /* end if */
- request_nelmts = target_size / max_type_size;
-
- /* Sanity check elements in temporary buffer */
- if (request_nelmts==0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "temporary buffer max size is too small")
-
- /* Figure out the strip mine size. */
- if (H5S_select_iter_init(&file_iter, file_space, dst_type_size) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize file selection information")
- file_iter_init=1; /*file selection iteration info has been initialized */
- if (H5S_select_iter_init(&mem_iter, mem_space, src_type_size) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize memory selection information")
- mem_iter_init=1; /*file selection iteration info has been initialized */
- if (H5S_select_iter_init(&bkg_iter, file_space, dst_type_size) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize background selection information")
- bkg_iter_init=1; /*file selection iteration info has been initialized */
-
- /*
- * Get a temporary buffer for type conversion unless the app has already
- * supplied one through the xfer properties. Instead of allocating a
- * buffer which is the exact size, we allocate the target size. The
- * malloc() is usually less resource-intensive if we allocate/free the
- * same size over and over.
- */
- if(H5T_detect_class(dataset->shared->type, H5T_VLEN)) {
- /* Old data is retrieved into background buffer for VL datatype. The
- * data is used later for freeing heap objects. */
- need_bkg = H5T_BKG_YES;
- } else if (H5T_path_bkg(tpath)) {
- H5T_bkg_t path_bkg; /* Type conversion's background info */
-
- /* Retrieve the bkgr buffer property */
- need_bkg=dxpl_cache->bkgr_buf_type;
- path_bkg = H5T_path_bkg(tpath);
- need_bkg = MAX (path_bkg, need_bkg);
- } else {
- need_bkg = H5T_BKG_NO; /*never needed even if app says yes*/
- } /* end else */
- if(NULL == (tconv_buf = (uint8_t *)dxpl_cache->tconv_buf)) {
- /* Allocate temporary buffer */
- if(NULL == (tconv_buf = H5FL_BLK_MALLOC(type_conv, target_size)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for type conversion")
- } /* end if */
- if(need_bkg && NULL == (bkg_buf = (uint8_t *)dxpl_cache->bkgr_buf)) {
- /* Allocate background buffer */
- /* (Don't need calloc()-like call since file data is already initialized) */
- if(NULL == (bkg_buf = H5FL_BLK_MALLOC(type_conv, (request_nelmts * dst_type_size))))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for background conversion")
- } /* end if */
-
- /* Start strip mining... */
- for (smine_start=0; smine_start<nelmts; smine_start+=smine_nelmts) {
- /* Go figure out how many elements to read from the file */
- assert(H5S_SELECT_ITER_NELMTS(&file_iter)==(nelmts-smine_start));
- smine_nelmts = (size_t)MIN(request_nelmts, (nelmts-smine_start));
-
- /*
- * Gather data from application buffer into the datatype conversion
- * buffer. Also gather data from the file into the background buffer
- * if necessary.
- */
-#ifdef H5S_DEBUG
- H5_timer_begin(&timer);
-#endif
- n = H5D_select_mgath(buf, mem_space, &mem_iter,
- smine_nelmts, dxpl_cache, tconv_buf/*out*/);
-#ifdef H5S_DEBUG
- H5_timer_end(&(io_info->stats->stats[0].gath_timer), &timer);
- io_info->stats->stats[0].gath_nbytes += n * src_type_size;
- io_info->stats->stats[0].gath_ncalls++;
-#endif
- if (n!=smine_nelmts)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "mem gather failed")
-
- /* If the source and destination are compound types and the destination is
- * is a subset of the source and no conversion is needed, copy the data
- * directly into user's buffer and bypass the rest of steps. If the source
- * is a subset of the destination, the optimization is done in conversion
- * function H5T_conv_struct_opt to protect the background data. This
- * optimization is for Chicago company */
- if(H5T_SUBSET_DST==H5T_path_compound_subset(tpath)) {
- if(H5D_compound_opt_write(smine_nelmts, src_id, dst_id, tconv_buf)<0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "datatype conversion failed")
- } else {
- if (H5T_BKG_YES==need_bkg) {
-#ifdef H5S_DEBUG
- H5_timer_begin(&timer);
-#endif
- n = H5D_select_fgath(io_info, file_space, &bkg_iter, smine_nelmts,
- (haddr_t)0, NULL, bkg_buf/*out*/);
-
-#ifdef H5S_DEBUG
- H5_timer_end(&(io_info->stats->stats[0].bkg_timer), &timer);
- io_info->stats->stats[0].bkg_nbytes += n * dst_type_size;
- io_info->stats->stats[0].bkg_ncalls++;
-#endif
- if (n!=smine_nelmts)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file gather failed")
- } /* end if */
-
- /*
- * Perform datatype conversion.
- */
- if(H5T_convert(tpath, src_id, dst_id, smine_nelmts, (size_t)0, (size_t)0, tconv_buf, bkg_buf, io_info->dxpl_id) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "datatype conversion failed")
-
- /* Do the data transform after the type conversion (since we're using dataset->shared->type). */
- if(!H5Z_xform_noop(dxpl_cache->data_xform_prop))
- if( H5Z_xform_eval(dxpl_cache->data_xform_prop, tconv_buf, smine_nelmts, dataset->shared->type) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Error performing data transform")
- }
-
/*
- * Scatter the data out to the file.
+ * This is the general case (type conversion, usually).
*/
-#ifdef H5S_DEBUG
- H5_timer_begin(&timer);
-#endif
- status = H5D_select_fscat(io_info, file_space, &file_iter, smine_nelmts,
- (haddr_t)0, NULL, tconv_buf);
-#ifdef H5S_DEBUG
- H5_timer_end(&(io_info->stats->stats[0].scat_timer), &timer);
- io_info->stats->stats[0].scat_nbytes += smine_nelmts * dst_type_size;
- io_info->stats->stats[0].scat_ncalls++;
-#endif
- if (status<0)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "scatter failed")
- } /* end for */
-
-done:
- /* Release selection iterators */
- if(file_iter_init) {
- if(H5S_SELECT_ITER_RELEASE(&file_iter) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
- } /* end if */
- if(mem_iter_init) {
- if(H5S_SELECT_ITER_RELEASE(&mem_iter) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
- } /* end if */
- if(bkg_iter_init) {
- if(H5S_SELECT_ITER_RELEASE(&bkg_iter) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
- } /* end if */
-
- if (tconv_buf && NULL==dxpl_cache->tconv_buf)
- (void)H5FL_BLK_FREE(type_conv,tconv_buf);
- if (bkg_buf && NULL==dxpl_cache->bkgr_buf)
- (void)H5FL_BLK_FREE(type_conv,bkg_buf);
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_contig_write() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_chunk_read
- *
- * Purpose: Read from a chunked dataset.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Raymond Lu
- * Thursday, April 10, 2003
- *
- * Modification:
- * Raymond Lu
- * 20 July 2007
- * Moved H5D_istore_lock and H5D_istore_unlock to this level
- * from H5D_istore_readvv to avoid frequent lock and unlock
- * and to improve performance.
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5D_chunk_read(H5D_io_info_t *io_info, hsize_t nelmts,
- const H5T_t *mem_type, const H5S_t *mem_space,
- const H5S_t *file_space, H5T_path_t *tpath,
- hid_t src_id, hid_t dst_id, void *buf/*out*/)
-{
- H5D_t *dataset=io_info->dset; /* Local pointer to dataset info */
- const H5D_dxpl_cache_t *dxpl_cache=io_info->dxpl_cache; /* Local pointer to dataset transfer info */
- H5D_chunk_map_t fm; /* File<->memory mapping */
- H5SL_node_t *chunk_node; /* Current node in chunk skip list */
- herr_t status; /*function return status*/
-#ifdef H5S_DEBUG
- H5_timer_t timer;
-#endif
- size_t src_type_size; /*size of source type */
- size_t dst_type_size; /*size of destination type*/
- size_t max_type_size; /* Size of largest source/destination type */
- size_t target_size; /*desired buffer size */
- size_t request_nelmts; /*requested strip mine */
- hsize_t smine_start; /*strip mine start loc */
- size_t n, smine_nelmts; /*elements per strip */
- size_t accessed_bytes = 0; /*total accessed size in a chunk */
- H5S_sel_iter_t mem_iter; /*memory selection iteration info*/
- hbool_t mem_iter_init = FALSE; /*memory selection iteration info has been initialized */
- H5S_sel_iter_t bkg_iter; /*background iteration info*/
- hbool_t bkg_iter_init = FALSE; /*background iteration info has been initialized */
- H5S_sel_iter_t file_iter; /*file selection iteration info*/
- hbool_t file_iter_init = FALSE; /*file selection iteration info has been initialized */
- H5T_bkg_t need_bkg; /*type of background buf*/
- uint8_t *tconv_buf = NULL; /*datatype conv buffer */
- uint8_t *bkg_buf = NULL; /*background buffer */
- H5D_storage_t store; /*union of EFL and chunk pointer in file space */
- void *chunk = NULL;
- haddr_t chunk_addr; /* Chunk address on disk */
- H5D_istore_ud1_t udata; /*B-tree pass-through */
- unsigned idx_hint=0; /* Cache index hint */
- herr_t ret_value = SUCCEED; /*return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5D_chunk_read)
-
- assert (buf);
-
- /* Map elements between file and memory for each chunk*/
- if(H5D_create_chunk_map(&fm, io_info, nelmts, file_space, mem_space, mem_type) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't build chunk mapping")
-
- /* Set dataset storage for I/O info */
- io_info->store=&store;
-
- /* Compute element sizes */
- src_type_size = H5T_get_size(dataset->shared->type);
- dst_type_size = H5T_get_size(mem_type);
- max_type_size = MAX(src_type_size, dst_type_size);
-
- /*
- * If there is no type conversion then read directly into the
- * application's buffer. This saves at least one mem-to-mem copy.
- */
- if ( H5Z_xform_noop(dxpl_cache->data_xform_prop) && H5T_path_noop(tpath)) {
-#ifdef H5S_DEBUG
- H5_timer_begin(&timer);
-#endif
- /* Sanity check dataset, then read it */
- HDassert(((dataset->shared->layout.type == H5D_CONTIGUOUS && H5F_addr_defined(dataset->shared->layout.u.contig.addr))
- || (dataset->shared->layout.type == H5D_CHUNKED && H5F_addr_defined(dataset->shared->layout.u.chunk.addr)))
- || dataset->shared->dcpl_cache.efl.nused > 0 || 0 == nelmts
- || dataset->shared->layout.type == H5D_COMPACT);
-
-#ifdef H5_HAVE_PARALLEL
- /* Check whether the collective mode can be turned off globally*/
-#ifndef H5_MPI_SPECIAL_COLLECTIVE_IO_WORKS
- if(io_info->dxpl_cache->xfer_mode == H5FD_MPIO_COLLECTIVE) {
- if(H5D_mpio_chunk_adjust_iomode(io_info ,&fm))
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't adjust collective I/O")
- }
-#endif /* H5_MPI_SPECIAL_COLLECTIVE_IO_WORKS */
- /* Temporarily shut down collective IO for chunking */
- if(io_info->dxpl_cache->xfer_mode == H5FD_MPIO_COLLECTIVE) {
- if(H5D_chunk_collective_io(io_info, &fm, buf, FALSE) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "chunked read failed in collective mode")
- }
- else {/* sequential or independent read */
-#endif
- /* Get first node in chunk skip list */
- chunk_node = H5D_CHUNK_GET_FIRST_NODE(fm);
-
- while(chunk_node) {
- H5D_chunk_info_t *chunk_info; /* chunk information */
-
- /* Get the actual chunk information from the skip list node */
- chunk_info = H5D_CHUNK_GET_NODE_INFO(fm, chunk_node);
-
- /* Pass in chunk's coordinates in a union. */
- store.chunk.offset = chunk_info->coords;
- store.chunk.index = chunk_info->index;
-
- /* Load the chunk into cache and lock it. */
- chunk_addr = H5D_istore_get_addr(io_info, &udata);
- if(H5D_istore_if_load(io_info, chunk_addr)) {
- if(NULL == (chunk = H5D_istore_lock(io_info, &udata, FALSE, &idx_hint)))
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to read raw data chunk")
- } else
- chunk = NULL;
-
- /* Perform the actual read operation */
- if((io_info->ops.read)(io_info, chunk_info->chunk_points,
- src_type_size, chunk_info->fspace,
- chunk_info->mspace, chunk_addr, chunk, buf) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, " chunked read failed")
-
- /* Release the cache lock on the chunk. */
- if(chunk) {
- accessed_bytes = chunk_info->chunk_points * src_type_size;
- if(H5D_istore_unlock(io_info, FALSE, idx_hint, chunk, accessed_bytes) < 0)
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to unlock raw data chunk")
- } /* end if */
-
- /* Advance to next chunk in list */
- chunk_node = H5D_CHUNK_GET_NEXT_NODE(fm, chunk_node);
- } /* end while */
-#ifdef H5_HAVE_PARALLEL
- }
-#endif
-
-
-#ifdef H5S_DEBUG
- H5_timer_end(&(io_info->stats->stats[1].read_timer), &timer);
- io_info->stats->stats[1].read_nbytes += nelmts * src_type_size;
- io_info->stats->stats[1].read_ncalls++;
-#endif
-
- /* direct xfer accomplished successfully */
- HGOTO_DONE(SUCCEED)
- } /* end if */
-
- /*
- * This is the general case (type conversion, usually).
- */
- if(nelmts==0)
- HGOTO_DONE(SUCCEED)
-
- /* Compute buffer sizes and other parameters */
- target_size = dxpl_cache->max_temp_buf;
- /* XXX: This could cause a problem if the user sets their buffer size
- * to the same size as the default, and then the dataset elements are
- * too large for the buffer... - QAK
- */
- if(target_size == H5D_TEMP_BUF_SIZE) {
- /* If the buffer is too small to hold even one element, make it bigger */
- if(target_size<max_type_size)
- target_size = max_type_size;
- /* If the buffer is too large to hold all the elements, make it smaller */
- else if(target_size>(nelmts*max_type_size))
- target_size=(size_t)(nelmts*max_type_size);
- } /* end if */
- request_nelmts = target_size / max_type_size;
-
- /* Sanity check elements in temporary buffer */
- if (request_nelmts==0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "temporary buffer max size is too small")
-
- /*
- * Get a temporary buffer for type conversion unless the app has already
- * supplied one through the xfer properties. Instead of allocating a
- * buffer which is the exact size, we allocate the target size. The
- * malloc() is usually less resource-intensive if we allocate/free the
- * same size over and over.
- */
- if (H5T_path_bkg(tpath)) {
- H5T_bkg_t path_bkg; /* Type conversion's background info */
-
- /* Retrieve the bkgr buffer property */
- need_bkg=dxpl_cache->bkgr_buf_type;
- path_bkg = H5T_path_bkg(tpath);
- need_bkg = MAX(path_bkg, need_bkg);
- } else {
- need_bkg = H5T_BKG_NO; /*never needed even if app says yes*/
+ io_info->io_ops.single_read = H5D_scatgath_read;
+ io_info->io_ops.single_write = H5D_scatgath_write;
} /* end else */
- if(NULL == (tconv_buf = (uint8_t *)dxpl_cache->tconv_buf)) {
- /* Allocate temporary buffer */
- if(NULL == (tconv_buf = H5FL_BLK_MALLOC(type_conv, target_size)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for type conversion")
- } /* end if */
- if(need_bkg && NULL == (bkg_buf = (uint8_t *)dxpl_cache->bkgr_buf)) {
- /* Allocate background buffer */
- /* (Need calloc()-like call since memory needs to be initialized) */
- if(NULL == (bkg_buf = H5FL_BLK_CALLOC(type_conv, (request_nelmts * dst_type_size))))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for background conversion")
- } /* end if */
-
- /* Loop over all the chunks, performing I/O on each */
-
- /* Get first node in chunk skip list */
- chunk_node = H5D_CHUNK_GET_FIRST_NODE(fm);
-
- /* Iterate through chunks to be operated on */
- while(chunk_node) {
- H5D_chunk_info_t *chunk_info; /* chunk information */
-
- /* Get the actual chunk information from the skip list nodes */
- chunk_info = H5D_CHUNK_GET_NODE_INFO(fm, chunk_node);
-
- /* initialize selection iterator */
- if (H5S_select_iter_init(&file_iter, chunk_info->fspace, src_type_size) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize file selection information")
- file_iter_init = TRUE; /*file selection iteration info has been initialized */
- if (H5S_select_iter_init(&mem_iter, chunk_info->mspace, dst_type_size) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize memory selection information")
- mem_iter_init = TRUE; /*file selection iteration info has been initialized */
- if (H5S_select_iter_init(&bkg_iter, chunk_info->mspace, dst_type_size) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize background selection information")
- bkg_iter_init = TRUE; /*file selection iteration info has been initialized */
-
- /* Pass in chunk's coordinates in a union*/
- store.chunk.offset = chunk_info->coords;
- store.chunk.index = chunk_info->index;
-
- /* Load the chunk into cache and lock it. */
- chunk_addr = H5D_istore_get_addr(io_info, &udata);
-
- if(H5D_istore_if_load(io_info, chunk_addr)) {
- if(NULL == (chunk = H5D_istore_lock(io_info, &udata, FALSE, &idx_hint)))
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to read raw data chunk")
- } else
- chunk = NULL;
-
- for(smine_start=0; smine_start<chunk_info->chunk_points; smine_start+=smine_nelmts) {
- /* Go figure out how many elements to read from the file */
- assert(H5S_SELECT_ITER_NELMTS(&file_iter)==(chunk_info->chunk_points-smine_start));
- smine_nelmts = (size_t)MIN(request_nelmts, (chunk_info->chunk_points-smine_start));
-
- /*
- * Gather the data from disk into the datatype conversion
- * buffer. Also gather data from application to background buffer
- * if necessary.
- */
-#ifdef H5S_DEBUG
- H5_timer_begin(&timer);
-#endif
- /* Sanity check that space is allocated, then read data from it */
- HDassert(((dataset->shared->layout.type == H5D_CONTIGUOUS && H5F_addr_defined(dataset->shared->layout.u.contig.addr))
- || (dataset->shared->layout.type == H5D_CHUNKED && H5F_addr_defined(dataset->shared->layout.u.chunk.addr)))
- || dataset->shared->dcpl_cache.efl.nused > 0 || dataset->shared->layout.type == H5D_COMPACT);
-
- if(chunk) {
- n = H5D_select_mgath(chunk, chunk_info->fspace, &file_iter,
- smine_nelmts, dxpl_cache, tconv_buf/*out*/);
- } else {
- n = H5D_select_fgath(io_info, chunk_info->fspace, &file_iter, smine_nelmts,
- chunk_addr, NULL, tconv_buf/*out*/);
- }
-
-#ifdef H5S_DEBUG
- H5_timer_end(&(io_info->stats->stats[1].gath_timer), &timer);
- io_info->stats->stats[1].gath_nbytes += n * src_type_size;
- io_info->stats->stats[1].gath_ncalls++;
-#endif
- if(n != smine_nelmts)
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "file gather failed")
-
- /* If the source and destination are compound types and subset of each other
- * and no conversion is needed, copy the data directly into user's buffer and
- * bypass the rest of steps. This optimization is for Chicago company */
- if(H5T_SUBSET_SRC==H5T_path_compound_subset(tpath)) {
- if(H5D_compound_opt_read(smine_nelmts, chunk_info->mspace, &mem_iter, dxpl_cache,
- src_id, dst_id, H5T_SUBSET_SRC, tconv_buf, buf /*out*/)<0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "datatype conversion failed")
-
- continue;
- } else if(H5T_SUBSET_DST==H5T_path_compound_subset(tpath)) {
- if(H5D_compound_opt_read(smine_nelmts, chunk_info->mspace, &mem_iter, dxpl_cache,
- src_id, dst_id, H5T_SUBSET_DST, tconv_buf, buf /*out*/)<0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "datatype conversion failed")
-
- continue;
- }
-
- if(H5T_BKG_YES == need_bkg) {
-#ifdef H5S_DEBUG
- H5_timer_begin(&timer);
-#endif
- n = H5D_select_mgath(buf, chunk_info->mspace, &bkg_iter, smine_nelmts, dxpl_cache, bkg_buf/*out*/);
-#ifdef H5S_DEBUG
- H5_timer_end(&(io_info->stats->stats[1].bkg_timer), &timer);
- io_info->stats->stats[1].bkg_nbytes += n * dst_type_size;
- io_info->stats->stats[1].bkg_ncalls++;
-#endif
- if(n != smine_nelmts)
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "mem gather failed")
- } /* end if */
-
- /*
- * Perform datatype conversion.
- */
- if(H5T_convert(tpath, src_id, dst_id, smine_nelmts, (size_t)0, (size_t)0, tconv_buf, bkg_buf, io_info->dxpl_id) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "datatype conversion failed")
-
- /* Do the data transform after the conversion (since we're using type mem_type) */
- if(!H5Z_xform_noop(dxpl_cache->data_xform_prop))
- if(H5Z_xform_eval(dxpl_cache->data_xform_prop, tconv_buf, smine_nelmts, mem_type) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Error performing data transform")
-
- /*
- * Scatter the data into memory.
- */
-#ifdef H5S_DEBUG
- H5_timer_begin(&timer);
-#endif
- status = H5D_select_mscat(tconv_buf, chunk_info->mspace, &mem_iter, smine_nelmts, dxpl_cache, buf/*out*/);
-#ifdef H5S_DEBUG
- H5_timer_end(&(io_info->stats->stats[1].scat_timer), &timer);
- io_info->stats->stats[1].scat_nbytes += smine_nelmts * dst_type_size;
- io_info->stats->stats[1].scat_ncalls++;
-#endif
- if(status < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "scatter failed")
- } /* end for */
-
- /* Release the cache lock on the chunk. */
- if(chunk) {
- accessed_bytes = chunk_info->chunk_points * src_type_size;
- if(H5D_istore_unlock(io_info, FALSE, idx_hint, chunk, accessed_bytes) < 0)
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to unlock raw data chunk")
- } /* end if */
-
- /* Release selection iterators */
- if(file_iter_init) {
- if(H5S_SELECT_ITER_RELEASE(&file_iter) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
- file_iter_init = FALSE;
- } /* end if */
- if(mem_iter_init) {
- if(H5S_SELECT_ITER_RELEASE(&mem_iter) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
- mem_iter_init = FALSE;
- } /* end if */
- if(bkg_iter_init) {
- if(H5S_SELECT_ITER_RELEASE(&bkg_iter) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
- bkg_iter_init = FALSE;
- } /* end if */
-
- /* Get the next chunk node in the skip list */
- chunk_node = H5D_CHUNK_GET_NEXT_NODE(fm, chunk_node);
- } /* end while */
-
-done:
- /* Release selection iterators, if necessary */
- if(file_iter_init) {
- if(H5S_SELECT_ITER_RELEASE(&file_iter) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
- } /* end if */
- if(mem_iter_init) {
- if(H5S_SELECT_ITER_RELEASE(&mem_iter) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
- } /* end if */
- if(bkg_iter_init) {
- if(H5S_SELECT_ITER_RELEASE(&bkg_iter) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
- } /* end if */
-
- if(tconv_buf && NULL == dxpl_cache->tconv_buf)
- (void)H5FL_BLK_FREE(type_conv, tconv_buf);
- if(bkg_buf && NULL == dxpl_cache->bkgr_buf)
- (void)H5FL_BLK_FREE(type_conv, bkg_buf);
-
- /* Release chunk mapping information */
- if(H5D_destroy_chunk_map(&fm) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CANTRELEASE, FAIL, "can't release chunk mapping")
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5D_chunk_read() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_chunk_write
- *
- * Purpose: Writes to a chunked dataset.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Raymond Lu
- * Thursday, April 10, 2003
- *
- * Modification:
- * Raymond Lu
- * 20 July 2007
- * Moved H5D_istore_lock and H5D_istore_unlock to this level
- * from H5D_istore_writevv to avoid frequent lock and unlock
- * and to improve performance.
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5D_chunk_write(H5D_io_info_t *io_info, hsize_t nelmts,
- const H5T_t *mem_type, const H5S_t *mem_space,
- const H5S_t *file_space, H5T_path_t *tpath,
- hid_t src_id, hid_t dst_id, const void *buf)
-{
- H5D_t *dataset=io_info->dset; /* Local pointer to dataset info */
- const H5D_dxpl_cache_t *dxpl_cache=io_info->dxpl_cache; /* Local pointer to dataset transfer info */
- H5D_chunk_map_t fm; /* File<->memory mapping */
- H5SL_node_t *chunk_node; /* Current node in chunk skip list */
- herr_t status; /*function return status*/
-#ifdef H5S_DEBUG
- H5_timer_t timer;
-#endif
- size_t src_type_size; /*size of source type */
- size_t dst_type_size; /*size of destination type*/
- size_t max_type_size; /* Size of largest source/destination type */
- size_t target_size; /*desired buffer size */
- size_t request_nelmts; /*requested strip mine */
- size_t accessed_bytes; /*total accessed size in a chunk */
- hsize_t smine_start; /*strip mine start loc */
- size_t n, smine_nelmts; /*elements per strip */
- H5S_sel_iter_t mem_iter; /*memory selection iteration info*/
- hbool_t mem_iter_init=0; /*memory selection iteration info has been initialized */
- H5S_sel_iter_t bkg_iter; /*background iteration info*/
- hbool_t bkg_iter_init=0; /*background iteration info has been initialized */
- H5S_sel_iter_t file_iter; /*file selection iteration info*/
- hbool_t file_iter_init=0; /*file selection iteration info has been initialized */
- H5T_bkg_t need_bkg; /*type of background buf*/
- uint8_t *tconv_buf = NULL; /*datatype conv buffer */
- uint8_t *bkg_buf = NULL; /*background buffer */
- H5D_storage_t store; /*union of EFL and chunk pointer in file space */
- void *chunk = NULL;
- haddr_t chunk_addr; /* Chunk address on disk */
- H5D_istore_ud1_t udata; /*B-tree pass-through */
- unsigned idx_hint=0; /* Cache index hint */
- hbool_t relax=TRUE; /* Whether whole chunk is selected */
- herr_t ret_value = SUCCEED; /*return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5D_chunk_write)
-
- assert (buf);
-
- /* Map elements between file and memory for each chunk*/
- if(H5D_create_chunk_map(&fm, io_info, nelmts, file_space, mem_space, mem_type) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't build chunk mapping")
-
- /* Set dataset storage for I/O info */
- io_info->store=&store;
-
-#ifdef H5_HAVE_PARALLEL
- /* Additional sanity checks when operating in parallel */
- if(io_info->using_mpi_vfd) {
- if (chunk_addr==HADDR_UNDEF)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to locate raw data chunk")
- if (dataset->shared->dcpl_cache.pline.nused>0)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "cannot write to chunked storage with filters in parallel")
- } /* end if */
-#endif /* H5_HAVE_PARALLEL */
-
- /* Compute element sizes and other parameters */
- src_type_size = H5T_get_size(mem_type);
- dst_type_size = H5T_get_size(dataset->shared->type);
- max_type_size = MAX(src_type_size, dst_type_size);
-
- /*
- * If there is no type conversion then write directly from the
- * application's buffer. This saves at least one mem-to-mem copy.
- */
- if ( H5Z_xform_noop(dxpl_cache->data_xform_prop) && H5T_path_noop(tpath)) {
-#ifdef H5S_DEBUG
- H5_timer_begin(&timer);
-#endif
#ifdef H5_HAVE_PARALLEL
- /* Check whether the collective mode can be turned off globally*/
-#ifndef H5_MPI_SPECIAL_COLLECTIVE_IO_WORKS
- if(io_info->dxpl_cache->xfer_mode == H5FD_MPIO_COLLECTIVE) {
- if(H5D_mpio_chunk_adjust_iomode(io_info,&fm))
- HGOTO_ERROR(H5E_DATASET,H5E_CANTGET,FAIL,"can't adjust collective I/O")
- }
-#endif /* H5_MPI_SPECIAL_COLLECTIVE_IO_WORKS */
- /* Temporarily shut down collective IO for chunking */
- if(io_info->dxpl_cache->xfer_mode == H5FD_MPIO_COLLECTIVE) {
- if(H5D_chunk_collective_io(io_info,&fm,buf,TRUE) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "chunked write failed in collective mode");
- }
- else {/* sequential or independent write */
+ /* Determine if the file was opened with an MPI VFD */
+ io_info->using_mpi_vfd = IS_H5FD_MPI(dset->oloc.file);
#endif /* H5_HAVE_PARALLEL */
- /* Get first node in chunk skip list */
- chunk_node = H5D_CHUNK_GET_FIRST_NODE(fm);
-
- while(chunk_node) {
- H5D_chunk_info_t *chunk_info; /* Chunk information */
-
- /* Get the actual chunk information from the skip list node */
- chunk_info = H5D_CHUNK_GET_NODE_INFO(fm, chunk_node);
-
- /* Pass in chunk's coordinates in a union. */
- store.chunk.offset = chunk_info->coords;
- store.chunk.index = chunk_info->index;
-
- /* Load the chunk into cache. But if the whole chunk is written,
- * simply allocate space instead of load the chunk. */
- chunk_addr = H5D_istore_get_addr(io_info, &udata);
-
- if(H5D_istore_if_load(io_info, chunk_addr)) {
- accessed_bytes = chunk_info->chunk_points * dst_type_size;
- if(accessed_bytes != dataset->shared->layout.u.chunk.size)
- relax = FALSE;
-
- if(NULL == (chunk = H5D_istore_lock(io_info, &udata, relax, &idx_hint)))
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to read raw data chunk")
- } else
- chunk = NULL;
-
- /* Perform the actual read operation */
- if((io_info->ops.write)(io_info, chunk_info->chunk_points,
- dst_type_size, chunk_info->fspace,
- chunk_info->mspace, chunk_addr, chunk, buf) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, " chunked write failed")
-
- /* Release the cache lock on the chunk. */
- if(chunk) {
- if(H5D_istore_unlock(io_info, TRUE, idx_hint, chunk, accessed_bytes) < 0)
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to unlock raw data chunk")
- } /* end if */
- relax = TRUE;
-
- /* Advance to next chunk in list */
- chunk_node = H5D_CHUNK_GET_NEXT_NODE(fm, chunk_node);
- } /* end while */
-#ifdef H5_HAVE_PARALLEL
- }
-#endif
-
-#ifdef H5S_DEBUG
- H5_timer_end(&(io_info->stats->stats[0].write_timer), &timer);
- io_info->stats->stats[0].write_nbytes += nelmts * src_type_size;
- io_info->stats->stats[0].write_ncalls++;
-#endif
-
- /* direct xfer accomplished successfully */
- HGOTO_DONE(SUCCEED)
- } /* end if */
-
- /*
- * This is the general case (type conversion, usually).
- */
- if(nelmts==0)
- HGOTO_DONE(SUCCEED)
-
- /* Compute buffer sizes and other parameters */
- target_size = dxpl_cache->max_temp_buf;
- /* XXX: This could cause a problem if the user sets their buffer size
- * to the same size as the default, and then the dataset elements are
- * too large for the buffer... - QAK
- */
- if(target_size == H5D_TEMP_BUF_SIZE) {
- /* If the buffer is too small to hold even one element, make it bigger */
- if(target_size<max_type_size)
- target_size = max_type_size;
- /* If the buffer is too large to hold all the elements, make it smaller */
- else if(target_size>(nelmts*max_type_size))
- target_size=(size_t)(nelmts*max_type_size);
- } /* end if */
- request_nelmts = target_size / max_type_size;
-
- /* Sanity check elements in temporary buffer */
- if (request_nelmts==0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "temporary buffer max size is too small")
- /*
- * Get a temporary buffer for type conversion unless the app has already
- * supplied one through the xfer properties. Instead of allocating a
- * buffer which is the exact size, we allocate the target size. The
- * malloc() is usually less resource-intensive if we allocate/free the
- * same size over and over.
- */
- if(H5T_detect_class(dataset->shared->type, H5T_VLEN)) {
- /* Old data is retrieved into background buffer for VL datatype. The
- * data is used later for freeing heap objects. */
- need_bkg = H5T_BKG_YES;
- } else if (H5T_path_bkg(tpath)) {
- H5T_bkg_t path_bkg; /* Type conversion's background info */
-
- /* Retrieve the bkgr buffer property */
- need_bkg=dxpl_cache->bkgr_buf_type;
- path_bkg = H5T_path_bkg(tpath);
- need_bkg = MAX (path_bkg, need_bkg);
- } else {
- need_bkg = H5T_BKG_NO; /*never needed even if app says yes*/
- } /* end else */
- if(NULL == (tconv_buf = (uint8_t *)dxpl_cache->tconv_buf)) {
- /* Allocate temporary buffer */
- if(NULL == (tconv_buf = H5FL_BLK_MALLOC(type_conv, target_size)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for type conversion")
- } /* end if */
- if(need_bkg && NULL == (bkg_buf = (uint8_t *)dxpl_cache->bkgr_buf)) {
- /* Allocate background buffer */
- /* (Don't need calloc()-like call since file data is already initialized) */
- if(NULL == (bkg_buf = H5FL_BLK_MALLOC(type_conv, (request_nelmts * dst_type_size))))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for background conversion")
- } /* end if */
-
- /* Loop over all the chunks, performing I/O on each */
-
- /* Get first node in chunk skip list */
- chunk_node = H5D_CHUNK_GET_FIRST_NODE(fm);
-
- /* Iterate through chunks to be operated on */
- while(chunk_node) {
- H5D_chunk_info_t *chunk_info; /* chunk information */
-
- /* Get the actual chunk information from the skip list node */
- chunk_info = H5D_CHUNK_GET_NODE_INFO(fm, chunk_node);
-
- /* initialize selection iterator */
- if (H5S_select_iter_init(&file_iter, chunk_info->fspace, dst_type_size) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize file selection information")
- file_iter_init=1; /*file selection iteration info has been initialized */
- if (H5S_select_iter_init(&mem_iter, chunk_info->mspace, src_type_size) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize memory selection information")
- mem_iter_init=1; /*file selection iteration info has been initialized */
- if (H5S_select_iter_init(&bkg_iter, chunk_info->fspace, dst_type_size) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize background selection information")
- bkg_iter_init=1; /*file selection iteration info has been initialized */
-
- /*pass in chunk's coordinates in a union*/
- store.chunk.offset = chunk_info->coords;
- store.chunk.index = chunk_info->index;
-
- /* Load the chunk into cache. But if the whole chunk is written,
- * simply allocate space instead of load the chunk. */
- chunk_addr = H5D_istore_get_addr(io_info, &udata);
-
- if(H5D_istore_if_load(io_info, chunk_addr)) {
- accessed_bytes = chunk_info->chunk_points * dst_type_size;
- if(accessed_bytes != dataset->shared->layout.u.chunk.size)
- relax=FALSE;
- if(relax) {
- accessed_bytes = H5S_GET_SELECT_NPOINTS(chunk_info->mspace) * src_type_size;
- if(accessed_bytes != dataset->shared->layout.u.chunk.size)
- relax = FALSE;
- }
-
- if(NULL == (chunk = H5D_istore_lock(io_info, &udata, relax, &idx_hint)))
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to read raw data chunk")
- } else
- chunk = NULL;
-
- for(smine_start=0; smine_start<chunk_info->chunk_points; smine_start+=smine_nelmts) {
- /* Go figure out how many elements to read from the file */
- assert(H5S_SELECT_ITER_NELMTS(&file_iter)==(chunk_info->chunk_points-smine_start));
- smine_nelmts = (size_t)MIN(request_nelmts, (chunk_info->chunk_points-smine_start));
-
- /*
- * Gather the data from disk into the datatype conversion
- * buffer. Also gather data from application to background buffer
- * if necessary.
- */
-#ifdef H5S_DEBUG
- H5_timer_begin(&timer);
-#endif
- n = H5D_select_mgath(buf, chunk_info->mspace, &mem_iter,
- smine_nelmts, dxpl_cache, tconv_buf/*out*/);
-
-#ifdef H5S_DEBUG
- H5_timer_end(&(io_info->stats->stats[1].gath_timer), &timer);
- io_info->stats->stats[1].gath_nbytes += n * src_type_size;
- io_info->stats->stats[1].gath_ncalls++;
-#endif
- if (n!=smine_nelmts)
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "file gather failed")
-
- /* If the source and destination are compound types and the destination is
- * is a subset of the source and no conversion is needed, copy the data
- * directly into user's buffer and bypass the rest of steps. If the source
- * is a subset of the destination, the optimization is done in conversion
- * function H5T_conv_struct_opt to protect the background data. This
- * optimization is for Chicago company */
- if(H5T_SUBSET_DST==H5T_path_compound_subset(tpath)) {
- if(H5D_compound_opt_write(smine_nelmts, src_id, dst_id, tconv_buf)<0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "datatype conversion failed")
- } else {
- if (H5T_BKG_YES==need_bkg) {
-#ifdef H5S_DEBUG
- H5_timer_begin(&timer);
-#endif
- if(chunk) {
- n = H5D_select_mgath(chunk, chunk_info->fspace, &bkg_iter,
- smine_nelmts, dxpl_cache, bkg_buf/*out*/);
- } else {
- n = H5D_select_fgath(io_info, chunk_info->fspace, &bkg_iter, smine_nelmts,
- chunk_addr, NULL, bkg_buf/*out*/);
- }
-
-#ifdef H5S_DEBUG
- H5_timer_end(&(io_info->stats->stats[0].bkg_timer), &timer);
- io_info->stats->stats[0].bkg_nbytes += n * dst_type_size;
- io_info->stats->stats[0].bkg_ncalls++;
-#endif
- if (n!=smine_nelmts)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file gather failed")
- } /* end if */
-
- /*
- * Perform datatype conversion.
- */
- if(H5T_convert(tpath, src_id, dst_id, smine_nelmts, (size_t)0, (size_t)0, tconv_buf, bkg_buf, io_info->dxpl_id) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "datatype conversion failed")
-
- /* Do the data transform after the type conversion (since we're using dataset->shared->type) */
- if(!H5Z_xform_noop(dxpl_cache->data_xform_prop))
- if( H5Z_xform_eval(dxpl_cache->data_xform_prop, tconv_buf, smine_nelmts, dataset->shared->type) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Error performing data transform")
- }
-
- /*
- * Scatter the data out to the file.
- */
-#ifdef H5S_DEBUG
- H5_timer_begin(&timer);
-#endif
- status = H5D_select_fscat(io_info,
- chunk_info->fspace, &file_iter, smine_nelmts,
- chunk_addr, chunk, tconv_buf);
-
-#ifdef H5S_DEBUG
- H5_timer_end(&(io_info->stats->stats[0].scat_timer), &timer);
- io_info->stats->stats[0].scat_nbytes += n * dst_type_size;
- io_info->stats->stats[0].scat_ncalls++;
-#endif
- if (status<0)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "scatter failed")
- } /* end for */
-
- /* Release the cache lock on the chunk. */
- if(chunk) {
- accessed_bytes = chunk_info->chunk_points * dst_type_size;
- if(H5D_istore_unlock(io_info, TRUE, idx_hint, chunk, accessed_bytes) < 0)
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to unlock raw data chunk")
- } /* end if */
- relax = TRUE;
-
- /* Release selection iterators */
- if(file_iter_init) {
- if(H5S_SELECT_ITER_RELEASE(&file_iter) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
- file_iter_init=0;
- } /* end if */
- if(mem_iter_init) {
- if(H5S_SELECT_ITER_RELEASE(&mem_iter) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
- mem_iter_init=0;
- } /* end if */
- if(bkg_iter_init) {
- if(H5S_SELECT_ITER_RELEASE(&bkg_iter) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
- bkg_iter_init=0;
- } /* end if */
-
- /* Get the next chunk node in the skip list */
- chunk_node = H5D_CHUNK_GET_NEXT_NODE(fm, chunk_node);
- } /* end while */
-
-done:
- /* Release selection iterators, if necessary */
- if(file_iter_init) {
- if(H5S_SELECT_ITER_RELEASE(&file_iter) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
- } /* end if */
- if(mem_iter_init) {
- if(H5S_SELECT_ITER_RELEASE(&mem_iter) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
- } /* end if */
- if(bkg_iter_init) {
- if(H5S_SELECT_ITER_RELEASE(&bkg_iter) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
- } /* end if */
-
- if (tconv_buf && NULL==dxpl_cache->tconv_buf)
- (void)H5FL_BLK_FREE(type_conv,tconv_buf);
- if (bkg_buf && NULL==dxpl_cache->bkgr_buf)
- (void)H5FL_BLK_FREE(type_conv,bkg_buf);
-
- /* Release chunk mapping information */
- if(H5D_destroy_chunk_map(&fm) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CANTRELEASE, FAIL, "can't release chunk mapping")
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5D_chunk_write() */
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5D_ioinfo_init() */
/*-------------------------------------------------------------------------
- * Function: H5D_compound_opt_read
+ * Function: H5D_typeinfo_init
*
- * Purpose: A shortcut optimization for the Chicago company for
- * a special optimization case when the source and
- * destination members are a subset of each other, and
- * the order is the same, and no conversion is needed.
- * For example:
- * struct source { struct destination {
- * TYPE1 A; --> TYPE1 A;
- * TYPE2 B; --> TYPE2 B;
- * TYPE3 C; --> TYPE3 C;
- * }; TYPE4 D;
- * TYPE5 E;
- * };
- * or
- * struct destination { struct source {
- * TYPE1 A; <-- TYPE1 A;
- * TYPE2 B; <-- TYPE2 B;
- * TYPE3 C; <-- TYPE3 C;
- * }; TYPE4 D;
- * TYPE5 E;
- * };
- * The optimization is simply moving data to the appropriate
- * places in the buffer.
+ * Purpose: Routine for determining correct datatype information for
+ * each I/O action.
*
* Return: Non-negative on success/Negative on failure
*
- * Programmer: Raymond Lu
- * 11 June 2007
+ * Programmer: Quincey Koziol
+ * Tuesday, March 4, 2008
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5D_compound_opt_read(size_t nelmts, const H5S_t *space,
- H5S_sel_iter_t *iter, const H5D_dxpl_cache_t *dxpl_cache,
- hid_t src_id, hid_t dst_id, H5T_subset_t subset,
- void *data_buf, void *user_buf/*out*/)
+H5D_typeinfo_init(const H5D_t *dset, const H5D_dxpl_cache_t *dxpl_cache,
+ hid_t dxpl_id, hid_t mem_type_id, hbool_t do_write,
+ H5D_type_info_t *type_info)
{
- uint8_t *dbuf = (uint8_t *)data_buf; /*cast for pointer arithmetic */
- uint8_t *ubuf = (uint8_t *)user_buf; /*cast for pointer arithmetic */
- uint8_t *xdbuf;
- uint8_t *xubuf;
-
- hsize_t _off[H5D_IO_VECTOR_SIZE]; /* Array to store sequence offsets */
- hsize_t *off=NULL; /* Pointer to sequence offsets */
- size_t _len[H5D_IO_VECTOR_SIZE]; /* Array to store sequence lengths */
- size_t *len=NULL; /* Pointer to sequence lengths */
- size_t nseq; /* Number of sequences generated */
- size_t curr_off; /* offset of bytes left to process in sequence */
- size_t curr_seq; /* Current sequence being processed */
- size_t curr_len; /* Length of bytes left to process in sequence */
- size_t curr_nelmts; /* number of elements to process in sequence */
- size_t i;
-
- H5T_t *src, *dst;
- size_t src_stride, dst_stride, type_size = 0;
- size_t elmtno; /*element counter */
-
- herr_t ret_value = SUCCEED; /*return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5D_compound_opt_read)
-
- /* Check args */
- assert (data_buf);
- assert (user_buf);
- assert (space);
- assert (iter);
- assert (nelmts>0);
-
- /* Allocate the vector I/O arrays */
- if(dxpl_cache->vec_size != H5D_IO_VECTOR_SIZE) {
- if((len = H5FL_SEQ_MALLOC(size_t,dxpl_cache->vec_size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O length vector array");
- if((off = H5FL_SEQ_MALLOC(hsize_t,dxpl_cache->vec_size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O offset vector array");
- } /* end if */
- else {
- len=_len;
- off=_off;
- } /* end else */
-
- if (NULL == (src = (H5T_t *)H5I_object(src_id)) || NULL == (dst = (H5T_t *)H5I_object(dst_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
-
- src_stride = H5T_get_size(src);
- dst_stride = H5T_get_size(dst);
-
- if(H5T_SUBSET_SRC == subset)
- type_size = src_stride;
- else if(H5T_SUBSET_DST == subset)
- type_size = dst_stride;
-
- xdbuf = dbuf;
-
- /* Loop until all elements are written */
- while(nelmts>0) {
- /* Get list of sequences for selection to write */
- if(H5S_SELECT_GET_SEQ_LIST(space,0,iter,dxpl_cache->vec_size,nelmts,&nseq,&elmtno,off,len)<0)
- HGOTO_ERROR (H5E_INTERNAL, H5E_UNSUPPORTED, 0, "sequence length generation failed");
-
- /* Loop, while sequences left to process */
- for(curr_seq=0; curr_seq<nseq; curr_seq++) {
- /* Get the number of bytes and offset in sequence */
- curr_len=len[curr_seq];
- curr_off=off[curr_seq];
-
- /* Decide the number of elements and position in the buffer. */
- curr_nelmts = curr_len/dst_stride;
- xubuf = ubuf + curr_off;
+ const H5T_t *src_type; /* Source datatype */
+ const H5T_t *dst_type; /* Destination datatype */
+ herr_t ret_value = SUCCEED; /* Return value */
- /* Copy the data into the right place. */
- for(i=0; i<curr_nelmts; i++) {
- HDmemmove(xubuf, xdbuf, type_size);
+ FUNC_ENTER_NOAPI_NOINIT(H5D_typeinfo_init)
- /* Update pointers */
- xdbuf += src_stride;
- xubuf += dst_stride;
- }
+ /* check args */
+ HDassert(type_info);
+ HDassert(dset);
- } /* end for */
+ /* Initialize type info safely */
+ HDmemset(type_info, 0, sizeof(H5D_type_info_t));
- /* Decrement number of elements left to process */
- nelmts -= elmtno;
- } /* end while */
+ /* Get the memory & dataset datatypes */
+ if(NULL == (type_info->mem_type = (const H5T_t *)H5I_object_verify(mem_type_id, H5I_DATATYPE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
+ type_info->dset_type = dset->shared->type;
-done:
- if(dxpl_cache->vec_size != H5D_IO_VECTOR_SIZE) {
- if(len!=NULL)
- H5FL_SEQ_FREE(size_t,len);
- if(off!=NULL)
- H5FL_SEQ_FREE(hsize_t,off);
+ if(do_write) {
+ src_type = type_info->mem_type;
+ dst_type = dset->shared->type;
+ type_info->src_type_id = mem_type_id;
+ type_info->dst_type_id = dset->shared->type_id;
} /* end if */
+ else {
+ src_type = dset->shared->type;
+ dst_type = type_info->mem_type;
+ type_info->src_type_id = dset->shared->type_id;
+ type_info->dst_type_id = mem_type_id;
+ } /* end else */
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_compound_opt_read() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_compound_opt_write
- *
- * Purpose: A shortcut optimization for the Chicago company for
- * a special optimization case when the source and
- * destination members are a subset of each other, and
- * the order is the same, and no conversion is needed.
- * For example:
- * struct source { struct destination {
- * TYPE1 A; --> TYPE1 A;
- * TYPE2 B; --> TYPE2 B;
- * TYPE3 C; --> TYPE3 C;
- * }; TYPE4 D;
- * TYPE5 E;
- * };
- * or
- * struct destination { struct source {
- * TYPE1 A; <-- TYPE1 A;
- * TYPE2 B; <-- TYPE2 B;
- * TYPE3 C; <-- TYPE3 C;
- * }; TYPE4 D;
- * TYPE5 E;
- * };
- * The optimization is simply moving data to the appropriate
- * places in the buffer.
- *
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Raymond Lu
- * 11 June 2007
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5D_compound_opt_write(size_t nelmts, hid_t src_id, hid_t dst_id, void *data_buf)
-{
- uint8_t *dbuf = (uint8_t *)data_buf; /*cast for pointer arithmetic */
- uint8_t *xsbuf, *xdbuf;
- size_t i;
- H5T_t *src, *dst;
- size_t src_stride, dst_stride;
- herr_t ret_value = SUCCEED; /*return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5D_compound_opt_write)
-
- /* Check args */
- assert (data_buf);
- assert (nelmts>0);
-
- if (NULL == (src = (H5T_t *)H5I_object(src_id)) || NULL == (dst = (H5T_t *)H5I_object(dst_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
-
- src_stride = H5T_get_size(src);
- dst_stride = H5T_get_size(dst);
-
- xsbuf = dbuf;
- xdbuf = dbuf;
-
- /* Loop until all elements are written */
- for(i=0; i<nelmts; i++) {
- HDmemmove(xdbuf, xsbuf, dst_stride);
-
- /* Update pointers */
- xsbuf += src_stride;
- xdbuf += dst_stride;
- }
-
-done:
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_compound_opt_write() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_create_chunk_map
- *
- * Purpose: Creates the mapping between elements selected in each chunk
- * and the elements in the memory selection.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Raymond Lu
- * Thursday, April 10, 2003
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5D_create_chunk_map(H5D_chunk_map_t *fm, const H5D_io_info_t *io_info,
- hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space,
- const H5T_t *mem_type)
-{
- H5D_t *dataset=io_info->dset; /* Local pointer to dataset info */
- H5S_t *tmp_mspace = NULL; /* Temporary memory dataspace */
- hssize_t old_offset[H5O_LAYOUT_NDIMS]; /* Old selection offset */
- htri_t file_space_normalized = FALSE; /* File dataspace was normalized */
- hid_t f_tid = (-1); /* Temporary copy of file datatype for iteration */
- hbool_t iter_init = FALSE; /* Selection iteration info has been initialized */
- unsigned f_ndims; /* The number of dimensions of the file's dataspace */
- int sm_ndims; /* The number of dimensions of the memory buffer's dataspace (signed) */
- H5SL_node_t *curr_node; /* Current node in skip list */
- H5S_sel_type fsel_type; /* Selection type on disk */
- char bogus; /* "bogus" buffer to pass to selection iterator */
- unsigned u; /* Local index variable */
- hbool_t sel_hyper_flag;
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5D_create_chunk_map)
-
- /* Get layout for dataset */
- fm->layout = &(dataset->shared->layout);
- fm->nelmts = nelmts;
-
- /* Check if the memory space is scalar & make equivalent memory space */
- if((sm_ndims = H5S_GET_EXTENT_NDIMS(mem_space)) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get dimension number")
- /* Set the number of dimensions for the memory dataspace */
- H5_ASSIGN_OVERFLOW(fm->m_ndims, sm_ndims, int, unsigned);
-
- /* Get dim number and dimensionality for each dataspace */
- fm->f_ndims = f_ndims = dataset->shared->layout.u.chunk.ndims - 1;
- if(H5S_get_simple_extent_dims(file_space, fm->f_dims, NULL) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get dimensionality")
-
- /* Normalize hyperslab selections by adjusting them by the offset */
- /* (It might be worthwhile to normalize both the file and memory dataspaces
- * before any (contiguous, chunked, etc) file I/O operation, in order to
- * speed up hyperslab calculations by removing the extra checks and/or
- * additions involving the offset and the hyperslab selection -QAK)
+ /*
+ * Locate the type conversion function and data space conversion
+ * functions, and set up the element numbering information. If a data
+ * type conversion is necessary then register datatype atoms. Data type
+ * conversion is necessary if the user has set the `need_bkg' to a high
+ * enough value in xfer_parms since turning off datatype conversion also
+ * turns off background preservation.
*/
- if((file_space_normalized = H5S_hyper_normalize_offset((H5S_t *)file_space, old_offset)) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_BADSELECT, FAIL, "unable to normalize dataspace by offset")
-
- /* Decide the number of chunks in each dimension*/
- for(u=0; u<f_ndims; u++) {
- /* Keep the size of the chunk dimensions as hsize_t for various routines */
- fm->chunk_dim[u]=fm->layout->u.chunk.dim[u];
-
- /* Round up to the next integer # of chunks, to accomodate partial chunks */
- fm->chunks[u] = ((fm->f_dims[u]+dataset->shared->layout.u.chunk.dim[u])-1) / dataset->shared->layout.u.chunk.dim[u];
- } /* end for */
-
- /* Compute the "down" size of 'chunks' information */
- if(H5V_array_down(f_ndims,fm->chunks,fm->down_chunks) < 0)
- HGOTO_ERROR(H5E_INTERNAL, H5E_BADVALUE, FAIL, "can't compute 'down' sizes")
-
-#ifdef H5_HAVE_PARALLEL
- /* Calculate total chunk in file map*/
- fm->select_chunk = NULL;
- fm->total_chunks = 1;
- for(u = 0; u < fm->f_ndims; u++)
- fm->total_chunks = fm->total_chunks * fm->chunks[u];
- if(io_info->using_mpi_vfd) {
- H5_CHECK_OVERFLOW(fm->total_chunks, hsize_t, size_t);
- if(NULL == (fm->select_chunk = (hbool_t *)H5MM_calloc((size_t)fm->total_chunks * sizeof(hbool_t))))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate chunk info")
- } /* end if */
-#endif /* H5_HAVE_PARALLEL */
-
-
- /* Initialize "last chunk" information */
- fm->last_index = (hsize_t)-1;
- fm->last_chunk_info = NULL;
-
- /* Point at the dataspaces */
- fm->file_space = file_space;
- fm->mem_space = mem_space;
-
- /* Special case for only one element in selection */
- /* (usually appending a record) */
- if(nelmts == 1
-#ifdef H5_HAVE_PARALLEL
- && !(io_info->using_mpi_vfd)
-#endif /* H5_HAVE_PARALLEL */
- ) {
- /* Initialize skip list for chunk selections */
- fm->sel_chunks = NULL;
- fm->use_single = TRUE;
-
- /* Initialize single chunk dataspace */
- if(NULL == dataset->shared->cache.chunk.single_space) {
- /* Make a copy of the dataspace for the dataset */
- if((dataset->shared->cache.chunk.single_space = H5S_copy(file_space, TRUE, FALSE)) == NULL)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy file space")
-
- /* Resize chunk's dataspace dimensions to size of chunk */
- if(H5S_set_extent_real(dataset->shared->cache.chunk.single_space, fm->chunk_dim) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "can't adjust chunk dimensions")
-
- /* Set the single chunk dataspace to 'all' selection */
- if(H5S_select_all(dataset->shared->cache.chunk.single_space, TRUE) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTSELECT, FAIL, "unable to set all selection")
- } /* end if */
- fm->single_space = dataset->shared->cache.chunk.single_space;
- HDassert(fm->single_space);
-
- /* Allocate the single chunk information */
- if(NULL == dataset->shared->cache.chunk.single_chunk_info) {
- if(NULL == (dataset->shared->cache.chunk.single_chunk_info = H5FL_MALLOC(H5D_chunk_info_t)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate chunk info")
- } /* end if */
- fm->single_chunk_info = dataset->shared->cache.chunk.single_chunk_info;
- HDassert(fm->single_chunk_info);
-
- /* Reset chunk template information */
- fm->mchunk_tmpl = NULL;
+ if(NULL == (type_info->tpath = H5T_path_find(src_type, dst_type, NULL, NULL, dxpl_id, FALSE)))
+ HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dest datatype")
- /* Set up chunk mapping for single element */
- if(H5D_create_chunk_map_single(fm, io_info) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create chunk selections for single element")
+ /* Precompute some useful information */
+ type_info->src_type_size = H5T_get_size(src_type);
+ type_info->dst_type_size = H5T_get_size(dst_type);
+ type_info->max_type_size = MAX(type_info->src_type_size, type_info->dst_type_size);
+ type_info->is_conv_noop = H5T_path_noop(type_info->tpath);
+ type_info->is_xform_noop = H5Z_xform_noop(dxpl_cache->data_xform_prop);
+ if(type_info->is_xform_noop && type_info->is_conv_noop) {
+ type_info->cmpd_subset = H5T_SUBSET_FALSE;
+ type_info->need_bkg = H5T_BKG_NO;
} /* end if */
else {
- /* Initialize skip list for chunk selections */
- if(NULL == dataset->shared->cache.chunk.sel_chunks) {
- if(NULL == (dataset->shared->cache.chunk.sel_chunks = H5SL_create(H5SL_TYPE_HSIZE, 0.5, (size_t)H5D_DEFAULT_SKIPLIST_HEIGHT)))
- HGOTO_ERROR(H5E_DATASET, H5E_CANTCREATE, FAIL, "can't create skip list for chunk selections")
- } /* end if */
- fm->sel_chunks = dataset->shared->cache.chunk.sel_chunks;
- HDassert(fm->sel_chunks);
-
- /* We are not using single element mode */
- fm->use_single = FALSE;
+ size_t target_size; /* Desired buffer size */
- /* Get type of selection on disk & in memory */
- if((fsel_type = H5S_GET_SELECT_TYPE(file_space)) < H5S_SEL_NONE)
- HGOTO_ERROR(H5E_DATASET, H5E_BADSELECT, FAIL, "unable to get type of selection")
- if((fm->msel_type = H5S_GET_SELECT_TYPE(mem_space)) < H5S_SEL_NONE)
- HGOTO_ERROR(H5E_DATASET, H5E_BADSELECT, FAIL, "unable to get type of selection")
+ /* Check if the datatypes are compound subsets of one another */
+ type_info->cmpd_subset = H5T_path_compound_subset(type_info->tpath);
- /* If the selection is NONE or POINTS, set the flag to FALSE */
- if(fsel_type == H5S_SEL_POINTS || fsel_type == H5S_SEL_NONE)
- sel_hyper_flag = FALSE;
- else
- sel_hyper_flag = TRUE;
-
- /* Check if file selection is a not a hyperslab selection */
- if(sel_hyper_flag) {
- /* Build the file selection for each chunk */
- if(H5D_create_chunk_file_map_hyper(fm, io_info) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create file chunk selections")
-
- /* Clean file chunks' hyperslab span "scratch" information */
- curr_node=H5SL_first(fm->sel_chunks);
- while(curr_node) {
- H5D_chunk_info_t *chunk_info; /* Pointer chunk information */
-
- /* Get pointer to chunk's information */
- chunk_info = (H5D_chunk_info_t *)H5SL_item(curr_node);
- assert(chunk_info);
-
- /* Clean hyperslab span's "scratch" information */
- if(H5S_hyper_reset_scratch(chunk_info->fspace) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "unable to reset span scratch info")
-
- /* Get the next chunk node in the skip list */
- curr_node=H5SL_next(curr_node);
- } /* end while */
- } /* end if */
+ /* Check if we need a background buffer */
+ if(do_write && H5T_detect_class(dset->shared->type, H5T_VLEN))
+ type_info->need_bkg = H5T_BKG_YES;
else {
- /* Create temporary datatypes for selection iteration */
- if((f_tid = H5I_register(H5I_DATATYPE, H5T_copy(dataset->shared->type, H5T_COPY_ALL))) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register file datatype")
-
- /* Spaces might not be the same shape, iterate over the file selection directly */
- if(H5S_select_iterate(&bogus, f_tid, file_space, H5D_chunk_file_cb, fm) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create file chunk selections")
-
- /* Reset "last chunk" info */
- fm->last_index=(hsize_t)-1;
- fm->last_chunk_info=NULL;
- } /* end else */
-
- /* Build the memory selection for each chunk */
- if(sel_hyper_flag && H5S_select_shape_same(file_space, mem_space) == TRUE) {
- /* Reset chunk template information */
- fm->mchunk_tmpl = NULL;
-
- /* If the selections are the same shape, use the file chunk information
- * to generate the memory chunk information quickly.
- */
- if(H5D_create_chunk_mem_map_hyper(fm) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create memory chunk selections")
- } /* end if */
- else {
- size_t elmt_size; /* Memory datatype size */
-
- /* Make a copy of equivalent memory space */
- if((tmp_mspace = H5S_copy(mem_space, TRUE, FALSE)) == NULL)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy memory space")
-
- /* De-select the mem space copy */
- if(H5S_select_none(tmp_mspace) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to de-select memory space")
-
- /* Save chunk template information */
- fm->mchunk_tmpl=tmp_mspace;
+ H5T_bkg_t path_bkg; /* Type conversion's background info */
- /* Create temporary datatypes for selection iteration */
- if(f_tid<0) {
- if((f_tid = H5I_register(H5I_DATATYPE, H5T_copy(dataset->shared->type, H5T_COPY_ALL))) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register file datatype")
- } /* end if */
-
- /* Create selection iterator for memory selection */
- if((elmt_size=H5T_get_size(mem_type))==0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_BADSIZE, FAIL, "datatype size invalid")
- if(H5S_select_iter_init(&(fm->mem_iter), mem_space, elmt_size) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator")
- iter_init = TRUE; /* Selection iteration info has been initialized */
-
- /* Spaces aren't the same shape, iterate over the memory selection directly */
- if(H5S_select_iterate(&bogus, f_tid, file_space, H5D_chunk_mem_cb, fm) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create memory chunk selections")
-
- /* Clean up hyperslab stuff, if necessary */
- if(fm->msel_type != H5S_SEL_POINTS) {
- /* Clean memory chunks' hyperslab span "scratch" information */
- curr_node=H5SL_first(fm->sel_chunks);
- while(curr_node) {
- H5D_chunk_info_t *chunk_info; /* Pointer chunk information */
-
- /* Get pointer to chunk's information */
- chunk_info = (H5D_chunk_info_t *)H5SL_item(curr_node);
- assert(chunk_info);
-
- /* Clean hyperslab span's "scratch" information */
- if(H5S_hyper_reset_scratch(chunk_info->mspace) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "unable to reset span scratch info")
-
- /* Get the next chunk node in the skip list */
- curr_node=H5SL_next(curr_node);
- } /* end while */
+ if((path_bkg = H5T_path_bkg(type_info->tpath))) {
+ /* Retrieve the bkgr buffer property */
+ type_info->need_bkg = dxpl_cache->bkgr_buf_type;
+ type_info->need_bkg = MAX(path_bkg, type_info->need_bkg);
} /* end if */
+ else
+ type_info->need_bkg = H5T_BKG_NO; /*never needed even if app says yes*/
} /* end else */
- } /* end else */
-
-done:
- /* Release the [potentially partially built] chunk mapping information if an error occurs */
- if(ret_value<0) {
- if(tmp_mspace && !fm->mchunk_tmpl) {
- if(H5S_close(tmp_mspace) < 0)
- HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "can't release memory chunk dataspace template")
- } /* end if */
-
- if (H5D_destroy_chunk_map(fm) < 0)
- HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release chunk mapping")
- } /* end if */
-
- /* Reset the global dataspace info */
- fm->file_space = NULL;
- fm->mem_space = NULL;
-
- if(iter_init) {
- if(H5S_SELECT_ITER_RELEASE(&(fm->mem_iter)) < 0)
- HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator")
- } /* end if */
- if(f_tid!=(-1)) {
- if(H5I_dec_ref(f_tid) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't decrement temporary datatype ID")
- } /* end if */
- if(file_space_normalized) {
- if(H5S_hyper_denormalize_offset((H5S_t *)file_space, old_offset) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_BADSELECT, FAIL, "unable to normalize dataspace by offset")
- } /* end if */
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_create_chunk_map() */
-
-
-/*--------------------------------------------------------------------------
- NAME
- H5D_free_chunk_info
- PURPOSE
- Internal routine to destroy a chunk info node
- USAGE
- void H5D_free_chunk_info(chunk_info)
- void *chunk_info; IN: Pointer to chunk info to destroy
- RETURNS
- No return value
- DESCRIPTION
- Releases all the memory for a chunk info node. Called by H5SL_free
- GLOBAL VARIABLES
- COMMENTS, BUGS, ASSUMPTIONS
- EXAMPLES
- REVISION LOG
---------------------------------------------------------------------------*/
-static herr_t
-H5D_free_chunk_info(void *item, void UNUSED *key, void UNUSED *opdata)
-{
- H5D_chunk_info_t *chunk_info = (H5D_chunk_info_t *)item;
-
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_free_chunk_info)
-
- HDassert(chunk_info);
-
- /* Close the chunk's file dataspace, if it's not shared */
- if(!chunk_info->fspace_shared)
- (void)H5S_close(chunk_info->fspace);
- else
- H5S_select_all(chunk_info->fspace, TRUE);
-
- /* Close the chunk's memory dataspace, if it's not shared */
- if(!chunk_info->mspace_shared)
- (void)H5S_close(chunk_info->mspace);
-
- /* Free the actual chunk info */
- H5FL_FREE(H5D_chunk_info_t, chunk_info);
-
- FUNC_LEAVE_NOAPI(0);
-} /* H5D_free_chunk_info() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_destroy_chunk_map
- *
- * Purpose: Destroy chunk mapping information.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * Saturday, May 17, 2003
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5D_destroy_chunk_map(const H5D_chunk_map_t *fm)
-{
- herr_t ret_value = SUCCEED; /*return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5D_destroy_chunk_map)
-
- /* Single element I/O vs. multiple element I/O cleanup */
- if(fm->use_single) {
- /* Sanity checks */
- HDassert(fm->sel_chunks == NULL);
- HDassert(fm->single_chunk_info);
- HDassert(fm->single_chunk_info->fspace_shared);
- HDassert(fm->single_chunk_info->mspace_shared);
-
- /* Reset the selection for the single element I/O */
- H5S_select_all(fm->single_space, TRUE);
- } /* end if */
- else {
- /* Release the nodes on the list of selected chunks */
- if(fm->sel_chunks)
- if(H5SL_free(fm->sel_chunks, H5D_free_chunk_info, NULL) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTNEXT, FAIL, "can't iterate over chunks")
- } /* end else */
-
- /* Free the memory chunk dataspace template */
- if(fm->mchunk_tmpl)
- if(H5S_close(fm->mchunk_tmpl) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "can't release memory chunk dataspace template")
-#ifdef H5_HAVE_PARALLEL
- if(fm->select_chunk)
- H5MM_xfree(fm->select_chunk);
-#endif /* H5_HAVE_PARALLEL */
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_destroy_chunk_map() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_create_chunk_map_single
- *
- * Purpose: Create chunk selections when appending a single record
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * Tuesday, November 20, 2007
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5D_create_chunk_map_single(H5D_chunk_map_t *fm, const H5D_io_info_t
-#ifndef H5_HAVE_PARALLEL
- UNUSED
-#endif /* H5_HAVE_PARALLEL */
- *io_info)
-{
- H5D_chunk_info_t *chunk_info; /* Chunk information to insert into skip list */
- hsize_t sel_start[H5O_LAYOUT_NDIMS]; /* Offset of low bound of file selection */
- hsize_t sel_end[H5O_LAYOUT_NDIMS]; /* Offset of high bound of file selection */
- unsigned u; /* Local index variable */
- herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT(H5D_create_chunk_map_single)
+ /* Set up datatype conversion/background buffers */
- /* Sanity check */
- HDassert(fm->f_ndims > 0);
+ /* Get buffer size from DXPL */
+ target_size = dxpl_cache->max_temp_buf;
- /* Get coordinate for selection */
- if(H5S_SELECT_BOUNDS(fm->file_space, sel_start, sel_end) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get file selection bound info")
+ /* If the buffer is too small to hold even one element, try to make it bigger */
+ if(target_size < type_info->max_type_size) {
+ hbool_t default_buffer_info; /* Whether the buffer information are the defaults */
- /* Initialize the 'single chunk' file & memory chunk information */
- chunk_info = fm->single_chunk_info;
- chunk_info->chunk_points = 1;
+ /* Detect if we have all default settings for buffers */
+ default_buffer_info = (H5D_TEMP_BUF_SIZE == dxpl_cache->max_temp_buf)
+ && (NULL == dxpl_cache->tconv_buf) && (NULL == dxpl_cache->bkgr_buf);
- /* Set chunk location & hyperslab size */
- for(u = 0; u < fm->f_ndims; u++) {
- HDassert(sel_start[u] == sel_end[u]);
- chunk_info->coords[u] = (sel_start[u] / fm->layout->u.chunk.dim[u]) * fm->layout->u.chunk.dim[u];
- } /* end for */
- chunk_info->coords[fm->f_ndims] = 0;
-
- /* Calculate the index of this chunk */
- if(H5V_chunk_index(fm->f_ndims, chunk_info->coords, fm->layout->u.chunk.dim, fm->down_chunks, &chunk_info->index) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "can't get chunk index")
-
- /* Copy selection for file's dataspace into chunk dataspace */
- if(H5S_select_copy(fm->single_space, fm->file_space, FALSE) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy file selection")
-
- /* Move selection back to have correct offset in chunk */
- if(H5S_SELECT_ADJUST_U(fm->single_space, chunk_info->coords) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't adjust chunk selection")
-
-#ifdef H5_HAVE_PARALLEL
- /* store chunk selection information */
- if(io_info->using_mpi_vfd)
- fm->select_chunk[chunk_info->index] = TRUE;
-#endif /* H5_HAVE_PARALLEL */
-
- /* Set the file dataspace for the chunk to the shared 'single' dataspace */
- chunk_info->fspace = fm->single_space;
-
- /* Indicate that the chunk's file dataspace is shared */
- chunk_info->fspace_shared = TRUE;
-
- /* Just point at the memory dataspace & selection */
- /* (Casting away const OK -QAK) */
- chunk_info->mspace = (H5S_t *)fm->mem_space;
-
- /* Indicate that the chunk's memory dataspace is shared */
- chunk_info->mspace_shared = TRUE;
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_create_chunk_map_single() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_create_chunk_file_map_hyper
- *
- * Purpose: Create all chunk selections in file.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * Thursday, May 29, 2003
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5D_create_chunk_file_map_hyper(H5D_chunk_map_t *fm, const H5D_io_info_t
-#ifndef H5_HAVE_PARALLEL
- UNUSED
-#endif /* H5_HAVE_PARALLEL */
- *io_info)
-{
- hsize_t sel_start[H5O_LAYOUT_NDIMS]; /* Offset of low bound of file selection */
- hsize_t sel_end[H5O_LAYOUT_NDIMS]; /* Offset of high bound of file selection */
- hsize_t sel_points; /* Number of elements in file selection */
- hsize_t start_coords[H5O_LAYOUT_NDIMS]; /* Starting coordinates of selection */
- hsize_t coords[H5O_LAYOUT_NDIMS]; /* Current coordinates of chunk */
- hsize_t end[H5O_LAYOUT_NDIMS]; /* Current coordinates of chunk */
- hsize_t chunk_index; /* Index of chunk */
- int curr_dim; /* Current dimension to increment */
- unsigned u; /* Local index variable */
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5D_create_chunk_file_map_hyper)
-
- /* Sanity check */
- assert(fm->f_ndims>0);
-
- /* Get number of elements selected in file */
- sel_points = fm->nelmts;
-
- /* Get bounding box for selection (to reduce the number of chunks to iterate over) */
- if(H5S_SELECT_BOUNDS(fm->file_space, sel_start, sel_end) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get file selection bound info")
-
- /* Set initial chunk location & hyperslab size */
-
- for(u=0; u<fm->f_ndims; u++) {
- start_coords[u]=(sel_start[u]/fm->layout->u.chunk.dim[u])*fm->layout->u.chunk.dim[u];
- coords[u]=start_coords[u];
- end[u]=(coords[u]+fm->chunk_dim[u])-1;
- } /* end for */
-
-
- /* Calculate the index of this chunk */
- if(H5V_chunk_index(fm->f_ndims,coords,fm->layout->u.chunk.dim,fm->down_chunks,&chunk_index) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "can't get chunk index")
-
- /* Iterate through each chunk in the dataset */
- while(sel_points) {
- /* Check for intersection of temporary chunk and file selection */
- /* (Casting away const OK - QAK) */
- if(H5S_hyper_intersect_block((H5S_t *)fm->file_space,coords,end)==TRUE) {
- H5S_t *tmp_fchunk; /* Temporary file dataspace */
- H5D_chunk_info_t *new_chunk_info; /* chunk information to insert into skip list */
- hssize_t schunk_points; /* Number of elements in chunk selection */
-
- /* Create "temporary" chunk for selection operations (copy file space) */
- if((tmp_fchunk = H5S_copy(fm->file_space, TRUE, FALSE)) == NULL)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy memory space")
-
- /* Make certain selections are stored in span tree form (not "optimized hyperslab" or "all") */
- if(H5S_hyper_convert(tmp_fchunk) < 0) {
- (void)H5S_close(tmp_fchunk);
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to convert selection to span trees")
- } /* end if */
-
- /* "AND" temporary chunk and current chunk */
- if(H5S_select_hyperslab(tmp_fchunk,H5S_SELECT_AND,coords,NULL,fm->chunk_dim,NULL) < 0) {
- (void)H5S_close(tmp_fchunk);
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't create chunk selection")
- } /* end if */
-
- /* Resize chunk's dataspace dimensions to size of chunk */
- if(H5S_set_extent_real(tmp_fchunk,fm->chunk_dim) < 0) {
- (void)H5S_close(tmp_fchunk);
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't adjust chunk dimensions")
- } /* end if */
-
- /* Move selection back to have correct offset in chunk */
- if(H5S_SELECT_ADJUST_U(tmp_fchunk, coords) < 0) {
- (void)H5S_close(tmp_fchunk);
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't adjust chunk selection")
- } /* end if */
-
- /* Add temporary chunk to the list of chunks */
-
- /* Allocate the file & memory chunk information */
- if (NULL==(new_chunk_info = H5FL_MALLOC (H5D_chunk_info_t))) {
- (void)H5S_close(tmp_fchunk);
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate chunk info")
- } /* end if */
-
- /* Initialize the chunk information */
-
- /* Set the chunk index */
- new_chunk_info->index=chunk_index;
-
-#ifdef H5_HAVE_PARALLEL
- /* store chunk selection information */
- if(io_info->using_mpi_vfd)
- fm->select_chunk[chunk_index] = TRUE;
-#endif /* H5_HAVE_PARALLEL */
-
- /* Set the file chunk dataspace */
- new_chunk_info->fspace = tmp_fchunk;
- new_chunk_info->fspace_shared = FALSE;
-
- /* Set the memory chunk dataspace */
- new_chunk_info->mspace=NULL;
- new_chunk_info->mspace_shared = FALSE;
-
- /* Copy the chunk's coordinates */
- for(u=0; u<fm->f_ndims; u++)
- new_chunk_info->coords[u]=coords[u];
- new_chunk_info->coords[fm->f_ndims]=0;
-
- /* Insert the new chunk into the skip list */
- if(H5SL_insert(fm->sel_chunks,new_chunk_info,&new_chunk_info->index) < 0) {
- H5D_free_chunk_info(new_chunk_info,NULL,NULL);
- HGOTO_ERROR(H5E_DATASPACE,H5E_CANTINSERT,FAIL,"can't insert chunk into skip list")
- } /* end if */
-
- /* Get number of elements selected in chunk */
- if((schunk_points=H5S_GET_SELECT_NPOINTS(tmp_fchunk)) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get file selection # of elements")
- H5_ASSIGN_OVERFLOW(new_chunk_info->chunk_points,schunk_points,hssize_t,size_t);
-
- /* Decrement # of points left in file selection */
- sel_points-=(hsize_t)schunk_points;
-
- /* Leave if we are done */
- if(sel_points==0)
- HGOTO_DONE(SUCCEED)
- assert(sel_points>0);
+ /* Check if we are using the default buffer info */
+ if(default_buffer_info)
+ /* OK to get bigger for library default settings */
+ target_size = type_info->max_type_size;
+ else
+ /* Don't get bigger than the application has requested */
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "temporary buffer max size is too small")
} /* end if */
- /* Increment chunk index */
- chunk_index++;
-
- /* Set current increment dimension */
- curr_dim=(int)fm->f_ndims-1;
-
- /* Increment chunk location in fastest changing dimension */
- H5_CHECK_OVERFLOW(fm->chunk_dim[curr_dim],hsize_t,hssize_t);
- coords[curr_dim]+=fm->chunk_dim[curr_dim];
- end[curr_dim]+=fm->chunk_dim[curr_dim];
-
- /* Bring chunk location back into bounds, if necessary */
- if(coords[curr_dim]>sel_end[curr_dim]) {
- do {
- /* Reset current dimension's location to 0 */
- coords[curr_dim]=start_coords[curr_dim]; /*lint !e771 The start_coords will always be initialized */
- end[curr_dim]=(coords[curr_dim]+(hssize_t)fm->chunk_dim[curr_dim])-1;
-
- /* Decrement current dimension */
- curr_dim--;
-
- /* Increment chunk location in current dimension */
- coords[curr_dim]+=fm->chunk_dim[curr_dim];
- end[curr_dim]=(coords[curr_dim]+fm->chunk_dim[curr_dim])-1;
- } while(coords[curr_dim]>sel_end[curr_dim]);
-
- /* Re-Calculate the index of this chunk */
- if(H5V_chunk_index(fm->f_ndims,coords,fm->layout->u.chunk.dim,fm->down_chunks,&chunk_index) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "can't get chunk index")
- } /* end if */
- } /* end while */
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_create_chunk_file_map_hyper() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_create_chunk_mem_map_hyper
- *
- * Purpose: Create all chunk selections in memory by copying the file
- * chunk selections and adjusting their offsets to be correct
- * for the memory.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * Thursday, May 29, 2003
- *
- * Assumptions: That the file and memory selections are the same shape.
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5D_create_chunk_mem_map_hyper(const H5D_chunk_map_t *fm)
-{
- H5SL_node_t *curr_node; /* Current node in skip list */
- hsize_t file_sel_start[H5O_LAYOUT_NDIMS]; /* Offset of low bound of file selection */
- hsize_t file_sel_end[H5O_LAYOUT_NDIMS]; /* Offset of high bound of file selection */
- hsize_t mem_sel_start[H5O_LAYOUT_NDIMS]; /* Offset of low bound of file selection */
- hsize_t mem_sel_end[H5O_LAYOUT_NDIMS]; /* Offset of high bound of file selection */
- hssize_t adjust[H5O_LAYOUT_NDIMS]; /* Adjustment to make to all file chunks */
- hssize_t chunk_adjust[H5O_LAYOUT_NDIMS]; /* Adjustment to make to a particular chunk */
- unsigned u; /* Local index variable */
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5D_create_chunk_mem_map_hyper)
-
- /* Sanity check */
- assert(fm->f_ndims>0);
-
- /* Check for all I/O going to a single chunk */
- if(H5SL_count(fm->sel_chunks)==1) {
- H5D_chunk_info_t *chunk_info; /* Pointer to chunk information */
-
- /* Get the node */
- curr_node=H5SL_first(fm->sel_chunks);
-
- /* Get pointer to chunk's information */
- chunk_info = (H5D_chunk_info_t *)H5SL_item(curr_node);
- assert(chunk_info);
-
- /* Just point at the memory dataspace & selection */
- /* (Casting away const OK -QAK) */
- chunk_info->mspace=(H5S_t *)fm->mem_space;
-
- /* Indicate that the chunk's memory space is shared */
- chunk_info->mspace_shared = TRUE;
- } /* end if */
- else {
- /* Get bounding box for file selection */
- if(H5S_SELECT_BOUNDS(fm->file_space, file_sel_start, file_sel_end) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get file selection bound info")
-
- /* Get bounding box for memory selection */
- if(H5S_SELECT_BOUNDS(fm->mem_space, mem_sel_start, mem_sel_end) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get file selection bound info")
-
- /* Calculate the adjustment for memory selection from file selection */
- assert(fm->m_ndims==fm->f_ndims);
- for(u=0; u<fm->f_ndims; u++) {
- H5_CHECK_OVERFLOW(file_sel_start[u],hsize_t,hssize_t);
- H5_CHECK_OVERFLOW(mem_sel_start[u],hsize_t,hssize_t);
- adjust[u]=(hssize_t)file_sel_start[u]-(hssize_t)mem_sel_start[u];
- } /* end for */
-
- /* Iterate over each chunk in the chunk list */
- curr_node=H5SL_first(fm->sel_chunks);
- while(curr_node) {
- H5D_chunk_info_t *chunk_info; /* Pointer to chunk information */
-
- /* Get pointer to chunk's information */
- chunk_info = (H5D_chunk_info_t *)H5SL_item(curr_node);
- assert(chunk_info);
-
- /* Copy the information */
-
- /* Copy the memory dataspace */
- if((chunk_info->mspace = H5S_copy(fm->mem_space, TRUE, FALSE)) == NULL)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy memory space")
-
- /* Release the current selection */
- if(H5S_SELECT_RELEASE(chunk_info->mspace) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection")
-
- /* Copy the file chunk's selection */
- if(H5S_select_copy(chunk_info->mspace,chunk_info->fspace,FALSE) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy selection")
-
- /* Compensate for the chunk offset */
- for(u=0; u<fm->f_ndims; u++) {
- H5_CHECK_OVERFLOW(chunk_info->coords[u],hsize_t,hssize_t);
- chunk_adjust[u]=adjust[u]-(hssize_t)chunk_info->coords[u]; /*lint !e771 The adjust array will always be initialized */
- } /* end for */
-
- /* Adjust the selection */
- if(H5S_hyper_adjust_s(chunk_info->mspace,chunk_adjust) < 0) /*lint !e772 The chunk_adjust array will always be initialized */
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't adjust chunk selection")
-
- /* Get the next chunk node in the skip list */
- curr_node=H5SL_next(curr_node);
- } /* end while */
- } /* end else */
+ /* Compute the number of elements that will fit into buffer */
+ type_info->request_nelmts = target_size / type_info->max_type_size;
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_create_chunk_mem_map_hyper() */
+ /* Sanity check elements in temporary buffer */
+ if(type_info->request_nelmts == 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "temporary buffer max size is too small")
-
-/*-------------------------------------------------------------------------
- * Function: H5D_chunk_file_cb
- *
- * Purpose: Callback routine for file selection iterator. Used when
- * creating selections in file for each point selected.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * Wednesday, July 23, 2003
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5D_chunk_file_cb(void UNUSED *elem, hid_t UNUSED type_id, unsigned ndims, const hsize_t *coords, void *_fm)
-{
- H5D_chunk_map_t *fm = (H5D_chunk_map_t *)_fm; /* File<->memory chunk mapping info */
- H5D_chunk_info_t *chunk_info; /* Chunk information for current chunk */
- hsize_t coords_in_chunk[H5O_LAYOUT_NDIMS]; /* Coordinates of element in chunk */
- hsize_t chunk_index; /* Chunk index */
- unsigned u; /* Local index variable */
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5D_chunk_file_cb)
-
- /* Calculate the index of this chunk */
- if(H5V_chunk_index(ndims,coords,fm->layout->u.chunk.dim,fm->down_chunks,&chunk_index) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "can't get chunk index")
-
- /* Find correct chunk in file & memory skip list */
- if(chunk_index==fm->last_index) {
- /* If the chunk index is the same as the last chunk index we used,
- * get the cached info to operate on.
- */
- chunk_info=fm->last_chunk_info;
- } /* end if */
- else {
- /* If the chunk index is not the same as the last chunk index we used,
- * find the chunk in the skip list.
+ /*
+ * Get a temporary buffer for type conversion unless the app has already
+ * supplied one through the xfer properties. Instead of allocating a
+ * buffer which is the exact size, we allocate the target size. The
+ * malloc() is usually less resource-intensive if we allocate/free the
+ * same size over and over.
*/
- /* Get the chunk node from the skip list */
- if(NULL == (chunk_info = (H5D_chunk_info_t *)H5SL_search(fm->sel_chunks, &chunk_index))) {
- H5S_t *fspace; /* Memory chunk's dataspace */
-
- /* Allocate the file & memory chunk information */
- if (NULL==(chunk_info = H5FL_MALLOC (H5D_chunk_info_t)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate chunk info")
-
- /* Initialize the chunk information */
-
- /* Set the chunk index */
- chunk_info->index=chunk_index;
-
- /* Create a dataspace for the chunk */
- if((fspace = H5S_create_simple(fm->f_ndims,fm->chunk_dim,NULL))==NULL) {
- H5FL_FREE(H5D_chunk_info_t,chunk_info);
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "unable to create dataspace for chunk")
- } /* end if */
-
- /* De-select the chunk space */
- if(H5S_select_none(fspace) < 0) {
- (void)H5S_close(fspace);
- H5FL_FREE(H5D_chunk_info_t,chunk_info);
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to de-select dataspace")
- } /* end if */
-
- /* Set the file chunk dataspace */
- chunk_info->fspace = fspace;
- chunk_info->fspace_shared = FALSE;
-
- /* Set the memory chunk dataspace */
- chunk_info->mspace=NULL;
- chunk_info->mspace_shared = FALSE;
-
- /* Set the number of selected elements in chunk to zero */
- chunk_info->chunk_points=0;
-
- /* Compute the chunk's coordinates */
- for(u=0; u<fm->f_ndims; u++) {
- H5_CHECK_OVERFLOW(fm->layout->u.chunk.dim[u],hsize_t,hssize_t);
- chunk_info->coords[u]=(coords[u]/(hssize_t)fm->layout->u.chunk.dim[u])*(hssize_t)fm->layout->u.chunk.dim[u];
- } /* end for */
- chunk_info->coords[fm->f_ndims]=0;
-
- /* Insert the new chunk into the skip list */
- if(H5SL_insert(fm->sel_chunks,chunk_info,&chunk_info->index) < 0) {
- H5D_free_chunk_info(chunk_info,NULL,NULL);
- HGOTO_ERROR(H5E_DATASPACE,H5E_CANTINSERT,FAIL,"can't insert chunk into skip list")
- } /* end if */
+ if(NULL == (type_info->tconv_buf = (uint8_t *)dxpl_cache->tconv_buf)) {
+ /* Allocate temporary buffer */
+ if(NULL == (type_info->tconv_buf = H5FL_BLK_MALLOC(type_conv, target_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for type conversion")
+ type_info->tconv_buf_allocated = TRUE;
+ } /* end if */
+ if(type_info->need_bkg && NULL == (type_info->bkg_buf = (uint8_t *)dxpl_cache->bkgr_buf)) {
+ size_t bkg_size; /* Desired background buffer size */
+
+ /* Compute the background buffer size */
+ /* (don't try to use buffers smaller than the default size) */
+ bkg_size = type_info->request_nelmts * type_info->dst_type_size;
+ if(bkg_size < dxpl_cache->max_temp_buf)
+ bkg_size = dxpl_cache->max_temp_buf;
+
+ /* Allocate background buffer */
+ /* (Need calloc()-like call since memory needs to be initialized) */
+ if(NULL == (type_info->bkg_buf = H5FL_BLK_CALLOC(type_conv, bkg_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for background conversion")
+ type_info->bkg_buf_allocated = TRUE;
} /* end if */
-
- /* Update the "last chunk seen" information */
- fm->last_index=chunk_index;
- fm->last_chunk_info=chunk_info;
- } /* end else */
-
- /* Get the coordinates of the element in the chunk */
- for(u=0; u<fm->f_ndims; u++)
- coords_in_chunk[u]=coords[u]%fm->layout->u.chunk.dim[u];
-
- /* Add point to file selection for chunk */
- if(H5S_select_elements(chunk_info->fspace, H5S_SELECT_APPEND, (size_t)1, coords_in_chunk) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "unable to select element")
-
- /* Increment the number of elemented selected in chunk */
- chunk_info->chunk_points++;
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_chunk_file_cb() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_chunk_mem_cb
- *
- * Purpose: Callback routine for file selection iterator. Used when
- * creating selections in memory for each chunk.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Raymond Lu
- * Thursday, April 10, 2003
- *
- *-------------------------------------------------------------------------
- */
-/* ARGSUSED */
-static herr_t
-H5D_chunk_mem_cb(void UNUSED *elem, hid_t UNUSED type_id, unsigned ndims, const hsize_t *coords, void *_fm)
-{
- H5D_chunk_map_t *fm = (H5D_chunk_map_t *)_fm; /* File<->memory chunk mapping info */
- H5D_chunk_info_t *chunk_info; /* Chunk information for current chunk */
- hsize_t coords_in_mem[H5O_LAYOUT_NDIMS]; /* Coordinates of element in memory */
- hsize_t chunk_index; /* Chunk index */
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5D_chunk_mem_cb)
-
- /* Calculate the index of this chunk */
- if(H5V_chunk_index(ndims,coords,fm->layout->u.chunk.dim,fm->down_chunks,&chunk_index) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "can't get chunk index")
-
- /* Find correct chunk in file & memory skip list */
- if(chunk_index==fm->last_index) {
- /* If the chunk index is the same as the last chunk index we used,
- * get the cached spaces to operate on.
- */
- chunk_info=fm->last_chunk_info;
- } /* end if */
- else {
- /* If the chunk index is not the same as the last chunk index we used,
- * find the chunk in the skip list.
- */
- /* Get the chunk node from the skip list */
- if(NULL == (chunk_info = (H5D_chunk_info_t *)H5SL_search(fm->sel_chunks, &chunk_index)))
- HGOTO_ERROR(H5E_DATASPACE, H5E_NOTFOUND, FAIL, "can't locate chunk in skip list")
-
- /* Check if the chunk already has a memory space */
- if(chunk_info->mspace==NULL) {
- /* Copy the template memory chunk dataspace */
- if((chunk_info->mspace = H5S_copy(fm->mchunk_tmpl, FALSE, FALSE)) == NULL)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy file space")
- } /* end else */
-
- /* Update the "last chunk seen" information */
- fm->last_index=chunk_index;
- fm->last_chunk_info=chunk_info;
- } /* end else */
-
- /* Get coordinates of selection iterator for memory */
- if(H5S_SELECT_ITER_COORDS(&fm->mem_iter,coords_in_mem) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get iterator coordinates")
-
- /* Add point to memory selection for chunk */
- if(fm->msel_type==H5S_SEL_POINTS) {
- if(H5S_select_elements(chunk_info->mspace, H5S_SELECT_APPEND, (size_t)1, coords_in_mem) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "unable to select element")
- } /* end if */
- else {
- if(H5S_hyper_add_span_element(chunk_info->mspace, fm->m_ndims, coords_in_mem) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "unable to select element")
} /* end else */
- /* Move memory selection iterator to next element in selection */
- if(H5S_SELECT_ITER_NEXT(&fm->mem_iter, (size_t)1) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTNEXT, FAIL, "unable to move to next iterator location")
-
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_chunk_mem_cb() */
+} /* end H5D_typeinfo_init() */
+#ifdef H5_HAVE_PARALLEL
/*-------------------------------------------------------------------------
- * Function: H5D_ioinfo_init
+ * Function: H5D_ioinfo_adjust
*
- * Purpose: Routine for determining correct I/O operations for
- * each I/O action.
+ * Purpose: Adjust operation's I/O info for any parallel I/O
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
- * Thursday, September 30, 2004
+ * Thursday, March 27, 2008
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5D_ioinfo_init(H5D_t *dset, const H5D_dxpl_cache_t *dxpl_cache, hid_t dxpl_id,
- const H5S_t
-#if !(defined H5_HAVE_PARALLEL || defined H5S_DEBUG)
- UNUSED
-#endif /* H5_HAVE_PARALLEL */
- *mem_space, const H5S_t
-#if !(defined H5_HAVE_PARALLEL || defined H5S_DEBUG)
- UNUSED
-#endif /* H5_HAVE_PARALLEL */
- *file_space, H5T_path_t
-#ifndef H5_HAVE_PARALLEL
- UNUSED
-#endif /* H5_HAVE_PARALLEL */
- *tpath,
- H5D_io_info_t *io_info)
+H5D_ioinfo_adjust(H5D_io_info_t *io_info, const H5D_t *dset,
+ const H5D_dxpl_cache_t *dxpl_cache, hid_t dxpl_id,
+ const H5S_t *file_space, const H5S_t *mem_space,
+ const H5D_type_info_t *type_info, const H5D_chunk_map_t *fm)
{
herr_t ret_value = SUCCEED; /* Return value */
-#if defined H5_HAVE_PARALLEL || defined H5S_DEBUG
- FUNC_ENTER_NOAPI_NOINIT(H5D_ioinfo_init)
-#else /* defined H5_HAVE_PARALLEL || defined H5S_DEBUG */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_ioinfo_init)
-#endif /* defined H5_HAVE_PARALLEL || defined H5S_DEBUG */
+ FUNC_ENTER_NOAPI_NOINIT(H5D_ioinfo_adjust)
/* check args */
HDassert(dset);
HDassert(dset->oloc.file);
HDassert(mem_space);
HDassert(file_space);
- HDassert(tpath);
+ HDassert(type_info);
+ HDassert(type_info->tpath);
HDassert(io_info);
- /* Set up "normal" I/O fields */
- io_info->dset=dset;
- io_info->dxpl_cache=dxpl_cache;
- io_info->dxpl_id=dxpl_id;
- io_info->store=NULL; /* Set later in I/O routine? */
-
- /* Set I/O operations to initial values */
- io_info->ops=dset->shared->io_ops;
-
-#ifdef H5_HAVE_PARALLEL
- /* Start in the "not modified" xfer_mode state */
- io_info->xfer_mode_changed = FALSE;
- io_info->using_mpi_vfd = IS_H5FD_MPI(dset->oloc.file);
-
+ /* Make any parallel I/O adjustments */
if(io_info->using_mpi_vfd) {
htri_t opt; /* Flag whether a selection is optimizable */
+ /* Record the original state of parallel I/O transfer options */
+ io_info->orig.xfer_mode = io_info->dxpl_cache->xfer_mode;
+ io_info->orig.coll_opt_mode = io_info->dxpl_cache->coll_opt_mode;
+ io_info->orig.io_ops.single_read = io_info->io_ops.single_read;
+ io_info->orig.io_ops.single_write = io_info->io_ops.single_write;
+
/* Get MPI communicator */
- if((io_info->comm = H5F_mpi_get_comm(dset->oloc.file)) == MPI_COMM_NULL)
+ if(MPI_COMM_NULL == (io_info->comm = H5F_mpi_get_comm(dset->oloc.file)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't retrieve MPI communicator")
- /*
- * Check if we can set direct MPI-IO read/write functions
- */
- opt=H5D_mpio_opt_possible(io_info, mem_space, file_space, tpath);
- if(opt==FAIL)
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "invalid check for direct IO dataspace ");
+ /* Check if we can set direct MPI-IO read/write functions */
+ if((opt = H5D_mpio_opt_possible(io_info, file_space, mem_space, type_info, fm)) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "invalid check for direct IO dataspace ")
/* Check if we can use the optimized parallel I/O routines */
- if(opt==TRUE) {
- /* Set the pointers to the MPI-specific routines */
- io_info->ops.read = H5D_mpio_select_read;
- io_info->ops.write = H5D_mpio_select_write;
+ if(opt == TRUE) {
+ /* Override the I/O op pointers to the MPI-specific routines */
+ io_info->io_ops.multi_read = dset->shared->layout_ops->par_read;
+ io_info->io_ops.multi_write = dset->shared->layout_ops->par_write;
+ io_info->io_ops.single_read = H5D_mpio_select_read;
+ io_info->io_ops.single_write = H5D_mpio_select_write;
} /* end if */
else {
- /* Set the pointers to the non-MPI-specific routines */
- io_info->ops.read = H5D_select_read;
- io_info->ops.write = H5D_select_write;
-
/* If we won't be doing collective I/O, but the user asked for
* collective I/O, change the request to use independent I/O, but
* mark it so that we remember to revert the change.
*/
- if(io_info->dxpl_cache->xfer_mode==H5FD_MPIO_COLLECTIVE) {
+ if(io_info->dxpl_cache->xfer_mode == H5FD_MPIO_COLLECTIVE) {
H5P_genplist_t *dx_plist; /* Data transer property list */
/* Get the dataset transfer property list */
- if (NULL == (dx_plist = (H5P_genplist_t *)H5I_object(dxpl_id)))
+ if(NULL == (dx_plist = (H5P_genplist_t *)H5I_object(dxpl_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset creation property list")
/* Change the xfer_mode to independent for handling the I/O */
io_info->dxpl_cache->xfer_mode = H5FD_MPIO_INDEPENDENT;
- if(H5P_set (dx_plist, H5D_XFER_IO_XFER_MODE_NAME, &io_info->dxpl_cache->xfer_mode) < 0)
+ if(H5P_set(dx_plist, H5D_XFER_IO_XFER_MODE_NAME, &io_info->dxpl_cache->xfer_mode) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set transfer mode")
-
- /* Indicate that the transfer mode should be restored before returning
- * to user.
- */
- io_info->xfer_mode_changed = TRUE;
} /* end if */
} /* end else */
} /* end if */
- else {
- /* Set the pointers to the non-MPI-specific routines */
- io_info->ops.read = H5D_select_read;
- io_info->ops.write = H5D_select_write;
- } /* end else */
-#else /* H5_HAVE_PARALLEL */
- io_info->ops.read = H5D_select_read;
- io_info->ops.write = H5D_select_write;
-#endif /* H5_HAVE_PARALLEL */
-
-#ifdef H5S_DEBUG
- /* Get the information for the I/O statistics */
- if((io_info->stats=H5S_find(mem_space,file_space))==NULL)
- HGOTO_ERROR(H5E_DATASET, H5E_BADSELECT, FAIL, "can't set up selection statistics");
-#endif /* H5S_DEBUG */
-#if defined H5_HAVE_PARALLEL || defined H5S_DEBUG
done:
-#endif /* H5_HAVE_PARALLEL || H5S_DEBUG */
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_ioinfo_init() */
+} /* end H5D_ioinfo_adjust() */
-#ifdef H5_HAVE_PARALLEL
/*-------------------------------------------------------------------------
* Function: H5D_ioinfo_term
@@ -3438,23 +933,69 @@ H5D_ioinfo_term(H5D_io_info_t *io_info)
FUNC_ENTER_NOAPI_NOINIT(H5D_ioinfo_term)
- /* Check if we need to revert the change to the xfer mode */
- if (io_info->xfer_mode_changed) {
- H5P_genplist_t *dx_plist; /* Data transer property list */
+ /* Check if we used the MPI VFD for the I/O */
+ if(io_info->using_mpi_vfd) {
+ /* Check if we need to revert the change to the xfer mode */
+ if(io_info->orig.xfer_mode != io_info->dxpl_cache->xfer_mode) {
+ H5P_genplist_t *dx_plist; /* Data transer property list */
- /* Get the dataset transfer property list */
- if (NULL == (dx_plist = (H5P_genplist_t *)H5I_object(io_info->dxpl_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset transfer property list")
+ /* Get the dataset transfer property list */
+ if(NULL == (dx_plist = (H5P_genplist_t *)H5I_object(io_info->dxpl_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset transfer property list")
+
+ /* Restore the original parallel I/O mode */
+ if(H5P_set(dx_plist, H5D_XFER_IO_XFER_MODE_NAME, &io_info->orig.xfer_mode) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set transfer mode")
+ } /* end if */
- /* Restore the original parallel I/O mode */
- io_info->dxpl_cache->xfer_mode = H5FD_MPIO_COLLECTIVE;
- if(H5P_set (dx_plist, H5D_XFER_IO_XFER_MODE_NAME, &io_info->dxpl_cache->xfer_mode) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set transfer mode")
+ /* Check if we need to revert the change to the collective opt mode */
+ if(io_info->orig.coll_opt_mode != io_info->dxpl_cache->coll_opt_mode) {
+ H5P_genplist_t *dx_plist; /* Data transer property list */
+
+ /* Get the dataset transfer property list */
+ if(NULL == (dx_plist = (H5P_genplist_t *)H5I_object(io_info->dxpl_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset transfer property list")
+
+ /* Restore the original parallel I/O mode */
+ if(H5P_set(dx_plist, H5D_XFER_MPIO_COLLECTIVE_OPT_NAME, &io_info->orig.coll_opt_mode) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set collective option mode")
+ } /* end if */
} /* end if */
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D_ioinfo_term() */
-#endif
+#endif /* H5_HAVE_PARALLEL */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_typeinfo_term
+ *
+ * Purpose: Common logic for terminating a type info object
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, March 6, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_typeinfo_term(const H5D_type_info_t *type_info)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_typeinfo_term)
+
+ /* Check for releasing datatype conversion & background buffers */
+ if(type_info->tconv_buf_allocated) {
+ HDassert(type_info->tconv_buf);
+ (void)H5FL_BLK_FREE(type_conv, type_info->tconv_buf);
+ } /* end if */
+ if(type_info->bkg_buf_allocated) {
+ HDassert(type_info->bkg_buf);
+ (void)H5FL_BLK_FREE(type_conv, type_info->bkg_buf);
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5D_typeinfo_term() */
diff --git a/src/H5Distore.c b/src/H5Distore.c
index 47e4cab..efab271 100644
--- a/src/H5Distore.c
+++ b/src/H5Distore.c
@@ -104,30 +104,12 @@
*/
#define H5D_ISTORE_NDIMS(X) (((X)->sizeof_rkey-8)/8)
-#define H5D_HASH(D,ADDR) H5F_addr_hash(ADDR,(D)->cache.chunk.nslots)
-
#define H5D_ISTORE_DEFAULT_SKIPLIST_HEIGHT 8
/******************/
/* Local Typedefs */
/******************/
-/* Raw data chunks are cached. Each entry in the cache is: */
-typedef struct H5D_rdcc_ent_t {
- hbool_t locked; /*entry is locked in cache */
- hbool_t dirty; /*needs to be written to disk? */
- hsize_t offset[H5O_LAYOUT_NDIMS]; /*chunk name */
- size_t rd_count; /*bytes remaining to be read */
- size_t wr_count; /*bytes remaining to be written */
- size_t chunk_size; /*size of a chunk */
- size_t alloc_size; /*amount allocated for the chunk */
- uint8_t *chunk; /*the unfiltered chunk data */
- unsigned idx; /*index in hash table */
- struct H5D_rdcc_ent_t *next;/*next item in doubly-linked list */
- struct H5D_rdcc_ent_t *prev;/*previous item in doubly-linked list */
-} H5D_rdcc_ent_t;
-typedef H5D_rdcc_ent_t *H5D_rdcc_ent_ptr_t; /* For free lists */
-
/*
* Data exchange structure for indexed storage nodes. This structure is
* passed through the B-link tree layer to the methods for the objects
@@ -192,7 +174,7 @@ typedef struct H5D_istore_it_ud4_t {
/* B-tree callback info for iteration to obtain chunk address and the index of the chunk for all chunks in the B-tree. */
typedef struct H5D_istore_it_ud5_t {
H5D_istore_bt_ud_common_t common; /* Common info for B-tree user data (must be first) */
- hsize_t *down_chunks;
+ const hsize_t *down_chunks;
haddr_t *chunk_addr;
} H5D_istore_it_ud5_t;
@@ -1490,7 +1472,7 @@ H5D_istore_flush(H5D_t *dset, hid_t dxpl_id, unsigned flags)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't fill dxpl cache")
/* Construct dataset I/O info */
- H5D_BUILD_IO_INFO(&io_info, dset, dxpl_cache, dxpl_id, NULL);
+ H5D_BUILD_IO_INFO_WRT(&io_info, dset, dxpl_cache, dxpl_id, NULL, NULL);
/* Loop over all entries in the chunk cache */
for(ent = rdcc->head; ent; ent = next) {
@@ -1525,48 +1507,48 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5D_istore_dest (H5D_t *dset, hid_t dxpl_id)
+H5D_istore_dest(H5D_t *dset, hid_t dxpl_id)
{
H5D_io_info_t io_info; /* Temporary I/O info object */
H5D_dxpl_cache_t _dxpl_cache; /* Data transfer property cache buffer */
- H5D_dxpl_cache_t *dxpl_cache=&_dxpl_cache; /* Data transfer property cache */
- H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk);
- int nerrors=0;
- H5D_rdcc_ent_t *ent=NULL, *next=NULL;
- herr_t ret_value=SUCCEED; /* Return value */
+ H5D_dxpl_cache_t *dxpl_cache = &_dxpl_cache; /* Data transfer property cache */
+ H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk);
+ int nerrors = 0;
+ H5D_rdcc_ent_t *ent = NULL, *next = NULL;
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5D_istore_dest, FAIL)
- assert(dset);
+ HDassert(dset);
/* Fill the DXPL cache values for later use */
- if (H5D_get_dxpl_cache(dxpl_id,&dxpl_cache)<0)
+ if(H5D_get_dxpl_cache(dxpl_id, &dxpl_cache) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't fill dxpl cache")
/* Construct dataset I/O info */
- H5D_BUILD_IO_INFO(&io_info,dset,dxpl_cache,dxpl_id,NULL);
+ H5D_BUILD_IO_INFO_WRT(&io_info, dset, dxpl_cache, dxpl_id, NULL, NULL);
/* Flush all the cached chunks */
- for (ent=rdcc->head; ent; ent=next) {
+ for(ent = rdcc->head; ent; ent = next) {
#ifdef H5D_ISTORE_DEBUG
HDfputc('c', stderr);
HDfflush(stderr);
#endif
next = ent->next;
- if (H5D_istore_preempt(&io_info, ent, TRUE )<0)
+ if(H5D_istore_preempt(&io_info, ent, TRUE) < 0)
nerrors++;
- }
- if (nerrors)
+ } /* end for */
+ if(nerrors)
HGOTO_ERROR(H5E_IO, H5E_CANTFLUSH, FAIL, "unable to flush one or more raw data chunks")
if(rdcc->slot)
- H5FL_SEQ_FREE (H5D_rdcc_ent_ptr_t,rdcc->slot);
- HDmemset (rdcc, 0, sizeof(H5D_rdcc_t));
+ H5FL_SEQ_FREE(H5D_rdcc_ent_ptr_t, rdcc->slot);
+ HDmemset(rdcc, 0, sizeof(H5D_rdcc_t));
/* Free the raw B-tree node buffer */
- if(dset->shared->layout.u.chunk.btree_shared==NULL)
+ if(dset->shared->layout.u.chunk.btree_shared == NULL)
HGOTO_ERROR(H5E_IO, H5E_CANTFREE, FAIL, "ref-counted page nil")
- if(H5RC_DEC(dset->shared->layout.u.chunk.btree_shared)<0)
+ if(H5RC_DEC(dset->shared->layout.u.chunk.btree_shared) < 0)
HGOTO_ERROR(H5E_IO, H5E_CANTFREE, FAIL, "unable to decrement ref-counted page")
done:
@@ -1835,7 +1817,7 @@ H5D_istore_lock(const H5D_io_info_t *io_info, H5D_istore_ud1_t *udata,
/* Search for the chunk in the cache */
if(rdcc->nslots > 0) {
- idx = H5D_HASH(dset->shared,io_info->store->chunk.index);
+ idx = H5D_CHUNK_HASH(dset->shared, io_info->store->chunk.index);
ent = rdcc->slot[idx];
if(ent)
@@ -1950,10 +1932,8 @@ H5D_istore_lock(const H5D_io_info_t *io_info, H5D_istore_ud1_t *udata,
if(H5D_fill_refill_vl(&fb_info, fb_info.elmts_per_buf, io_info->dxpl_id) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, NULL, "can't refill fill value buffer")
} /* end if */
-#ifdef H5_CLEAR_MEMORY
else
HDmemset(chunk, 0, chunk_size);
-#endif /* H5_CLEAR_MEMORY */
#ifdef H5D_ISTORE_DEBUG
rdcc->ninits++;
#endif /* H5D_ISTORE_DEBUG */
@@ -2154,339 +2134,6 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5D_istore_if_load
- *
- * Purpose: A small internal function to if it's necessary to load the
- * chunk into cache.
- *
- * Return: TRUE or FALSE
- *
- * Programmer: Raymond Lu
- * 17 July 2007
- *
- *-------------------------------------------------------------------------
- */
-hbool_t
-H5D_istore_if_load(const H5D_io_info_t *io_info, haddr_t caddr)
-{
- const H5D_t *dataset = io_info->dset;
- hbool_t ret_value;
-
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_istore_if_load)
-
- HDassert(io_info);
- HDassert(dataset);
-
- /*
- * If the chunk is too large to load into the cache and it has no
- * filters in the pipeline (i.e. not compressed) and if the address
- * for the chunk has been defined, then don't load the chunk into the
- * cache, just write the data to it directly.
- *
- * If MPI based VFD is used, must bypass the
- * chunk-cache scheme because other MPI processes could be
- * writing to other elements in the same chunk. Do a direct
- * write-through of only the elements requested.
- */
- if(dataset->shared->dcpl_cache.pline.nused==0 &&
- ((dataset->shared->layout.u.chunk.size > dataset->shared->cache.chunk.nbytes && caddr != HADDR_UNDEF)
-#ifdef H5_HAVE_PARALLEL
- || (io_info->using_mpi_vfd && (H5F_ACC_RDWR & H5F_get_intent(dataset->oloc.file)))
-#endif /* H5_HAVE_PARALLEL */
- )) {
- ret_value = FALSE;
- } else
- ret_value = TRUE;
-
- FUNC_LEAVE_NOAPI(ret_value)
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_istore_readvv
- *
- * Purpose: Reads a multi-dimensional buffer from (part of) an indexed raw
- * storage array.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * Wednesday, May 7, 2003
- *
- * Modification:
- * Raymond Lu
- * 20 July 2007
- * Moved H5D_istore_lock and H5D_istore_unlock to H5D_chunk_read
- * from this function to avoid frequent lock and unlock.
- *
- *-------------------------------------------------------------------------
- */
-ssize_t
-H5D_istore_readvv(const H5D_io_info_t *io_info,
- size_t chunk_max_nseq, size_t *chunk_curr_seq, size_t chunk_len_arr[], hsize_t chunk_offset_arr[],
- size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[],
- haddr_t chunk_addr, void *chunk, void *buf)
-{
- H5D_t *dset=io_info->dset; /* Local pointer to the dataset info */
- size_t u; /* Local index variables */
- ssize_t ret_value; /* Return value */
-
- FUNC_ENTER_NOAPI(H5D_istore_readvv, FAIL)
-
- /* Check args */
- HDassert(io_info);
- HDassert(dset && H5D_CHUNKED==dset->shared->layout.type);
- HDassert(dset->shared->layout.u.chunk.ndims>0 && dset->shared->layout.u.chunk.ndims<=H5O_LAYOUT_NDIMS);
- HDassert(io_info->dxpl_cache);
- HDassert(io_info->store);
- HDassert(chunk_len_arr);
- HDassert(chunk_offset_arr);
- HDassert(mem_len_arr);
- HDassert(mem_offset_arr);
- HDassert(buf);
-
- /* Get the address of this chunk on disk */
-#ifdef QAK
-HDfprintf(stderr,"%s: io_info->store->chunk.offset={",FUNC);
-for(u=0; u<dset->shared->layout.u.chunk.ndims; u++)
- HDfprintf(stderr,"%Hd%s",io_info->store->chunk.offset[u],(u<(dset->shared->layout.u.chunk.ndims-1) ? ", " : "}\n"));
-
-HDfprintf(stderr,"%s: chunk_addr=%a, chunk_size=%Zu\n",FUNC,chunk_addr,dset->shared->layout.u.chunk.size);
-HDfprintf(stderr,"%s: chunk_len_arr[%Zu]=%Zu\n",FUNC,*chunk_curr_seq,chunk_len_arr[*chunk_curr_seq]);
-HDfprintf(stderr,"%s: chunk_offset_arr[%Zu]=%Hu\n",FUNC,*chunk_curr_seq,chunk_offset_arr[*chunk_curr_seq]);
-HDfprintf(stderr,"%s: mem_len_arr[%Zu]=%Zu\n",FUNC,*mem_curr_seq,mem_len_arr[*mem_curr_seq]);
-HDfprintf(stderr,"%s: mem_offset_arr[%Zu]=%Hu\n",FUNC,*mem_curr_seq,mem_offset_arr[*mem_curr_seq]);
-HDfprintf(stderr,"%s: buf=%p\n",FUNC,buf);
-#endif /* QAK */
-
- /*
- * If the chunk is too large to load into the cache and it has no
- * filters in the pipeline (i.e. not compressed) and if the address
- * for the chunk has been defined, then don't load the chunk into the
- * cache, just read the data from it directly.
- *
- * If MPI based VFD is used, must bypass the
- * chunk-cache scheme because other MPI processes could be
- * writing to other elements in the same chunk. Do a direct
- * read-through of only the elements requested.
- */
- if(!H5D_istore_if_load(io_info, chunk_addr)) {
- H5D_io_info_t chk_io_info; /* Temporary I/O info object */
- H5D_storage_t chk_store; /* Chunk storage information */
-
- /* Set up the storage information for the chunk */
- chk_store.contig.dset_addr=chunk_addr;
- chk_store.contig.dset_size=(hsize_t)dset->shared->layout.u.chunk.size;
-
- /* Set up new dataset I/O info */
- H5D_BUILD_IO_INFO(&chk_io_info,dset,io_info->dxpl_cache,io_info->dxpl_id,&chk_store);
-
- /* Do I/O directly on chunk without reading it into the cache */
- if ((ret_value=H5D_contig_readvv(&chk_io_info, chunk_max_nseq, chunk_curr_seq, chunk_len_arr,
- chunk_offset_arr, mem_max_nseq, mem_curr_seq, mem_len_arr, mem_offset_arr, (haddr_t)0, NULL, buf))<0)
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to read raw data to file")
- } /* end if */
- else {
- ssize_t naccessed; /* Number of bytes accessed in chunk */
-
- /* If the chunk address is not defined, check if the fill value is
- * undefined also. If both situations hold, don't bother copying
- * values to the destination buffer, since they will just be
- * garbage.
- *
- * Ideally, this will eventually be checked at a higher level and
- * the entire I/O operation on the chunk will be skipped. -QAK
- */
- if(!H5F_addr_defined(chunk_addr)) {
- H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk);/*raw data chunk cache*/
- hbool_t found = FALSE; /*already in cache? */
-
- /* Check if the chunk is in the cache (but hasn't been written to disk yet) */
- if(rdcc->nslots>0) {
- unsigned idx = H5D_HASH(dset->shared, io_info->store->chunk.index); /* Cache entry index */
- H5D_rdcc_ent_t *ent = rdcc->slot[idx]; /* Cache entry */
-
- /* Potential match... */
- if(ent) {
- for(u = 0, found = TRUE; u < dset->shared->layout.u.chunk.ndims; u++) {
- if(io_info->store->chunk.offset[u] != ent->offset[u]) {
- found = FALSE;
- break;
- } /* end if */
- } /* end for */
- } /* end if */
- } /* end if */
-
- /* If the chunk is in the cache, then it must have valid data */
- if(!found) {
- const H5O_fill_t *fill = &(dset->shared->dcpl_cache.fill); /* Fill value info */
- H5D_fill_value_t fill_status;
-
- /* Check if the fill value is defined */
- if(H5P_is_fill_value_defined(fill, &fill_status) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't tell if fill value defined")
-
- /* If we are never to return fill values, or if we would return them
- * but they aren't set, process the entire set of I/O vectors and
- * get out now.
- */
- if(fill->fill_time == H5D_FILL_TIME_NEVER ||
- (fill->fill_time == H5D_FILL_TIME_IFSET && fill_status!=H5D_FILL_VALUE_USER_DEFINED)) {
- size_t size; /* Size of sequence in bytes */
- size_t v; /* Local index variable */
- ssize_t bytes_processed = 0; /* Eventual return value */
-
- /* Work through all the sequences */
- for(u = *mem_curr_seq, v = *chunk_curr_seq; u < mem_max_nseq && v < chunk_max_nseq; ) {
- /* Choose smallest buffer to write */
- if(chunk_len_arr[v] < mem_len_arr[u])
- size = chunk_len_arr[v];
- else
- size = mem_len_arr[u];
-
- /* Update source information */
- chunk_len_arr[v] -= size;
- chunk_offset_arr[v] += size;
- if(chunk_len_arr[v] == 0)
- v++;
-
- /* Update destination information */
- mem_len_arr[u] -= size;
- mem_offset_arr[u] += size;
- if(mem_len_arr[u] == 0)
- u++;
-
- /* Increment number of bytes copied */
- bytes_processed += (ssize_t)size;
- } /* end for */
-
- /* Update current sequence vectors */
- *mem_curr_seq = u;
- *chunk_curr_seq = v;
-
- HGOTO_DONE(bytes_processed)
- } /* end if */
- } /* end if */
- } /* end if */
-
- /* Use the vectorized memory copy routine to do actual work */
- if((naccessed = H5V_memcpyvv(buf, mem_max_nseq, mem_curr_seq, mem_len_arr, mem_offset_arr, chunk, chunk_max_nseq, chunk_curr_seq, chunk_len_arr, chunk_offset_arr)) < 0)
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "vectorized memcpy failed")
-
- H5_CHECK_OVERFLOW(naccessed, ssize_t, size_t);
-
- /* Set return value */
- ret_value = naccessed;
- } /* end else */
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5D_istore_readvv() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_istore_writevv
- *
- * Purpose: Writes a multi-dimensional buffer to (part of) an indexed raw
- * storage array.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * Friday, May 2, 2003
- *
- * Modification:
- * Raymond Lu
- * 20 July 2007
- * Moved H5D_istore_lock and H5D_istore_unlock to H5D_chunk_write
- * from this function to avoid frequent lock and unlock.
- *
- *-------------------------------------------------------------------------
- */
-ssize_t
-H5D_istore_writevv(const H5D_io_info_t *io_info,
- size_t chunk_max_nseq, size_t *chunk_curr_seq, size_t chunk_len_arr[], hsize_t chunk_offset_arr[],
- size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[],
- haddr_t chunk_addr, void *chunk, const void *buf)
-{
- H5D_t *dset = io_info->dset; /* Local pointer to the dataset info */
- ssize_t ret_value; /* Return value */
-
- FUNC_ENTER_NOAPI(H5D_istore_writevv, FAIL)
-
- /* Check args */
- HDassert(io_info);
- HDassert(dset && H5D_CHUNKED==dset->shared->layout.type);
- HDassert(dset->shared->layout.u.chunk.ndims>0 && dset->shared->layout.u.chunk.ndims<=H5O_LAYOUT_NDIMS);
- HDassert(io_info->dxpl_cache);
- HDassert(io_info->store);
- HDassert(chunk_len_arr);
- HDassert(chunk_offset_arr);
- HDassert(mem_len_arr);
- HDassert(mem_offset_arr);
- HDassert(buf);
-
-#ifdef QAK
-{
-size_t u; /* Local index variables */
-
-HDfprintf(stderr,"%s: io_info->store->chunk.offset={",FUNC);
-for(u=0; u<dset->shared->layout.u.chunk.ndims; u++)
- HDfprintf(stderr,"%Hd%s",io_info->store->chunk.offset[u],(u<(dset->shared->layout.u.chunk.ndims-1) ? ", " : "}\n"));
-
-HDfprintf(stderr,"%s: chunk_addr=%a, chunk_size=%Zu\n",FUNC,chunk_addr,dset->shared->layout.u.chunk.size);
-HDfprintf(stderr,"%s: chunk_len_arr[%Zu]=%Zu\n",FUNC,*chunk_curr_seq,chunk_len_arr[*chunk_curr_seq]);
-HDfprintf(stderr,"%s: chunk_offset_arr[%Zu]=%Hu\n",FUNC,*chunk_curr_seq,chunk_offset_arr[*chunk_curr_seq]);
-HDfprintf(stderr,"%s: mem_len_arr[%Zu]=%Zu\n",FUNC,*mem_curr_seq,mem_len_arr[*mem_curr_seq]);
-HDfprintf(stderr,"%s: mem_offset_arr[%Zu]=%Hu\n",FUNC,*mem_curr_seq,mem_offset_arr[*mem_curr_seq]);
-}
-#endif /* QAK */
-
- /*
- * If the chunk is too large to load into the cache and it has no
- * filters in the pipeline (i.e. not compressed) and if the address
- * for the chunk has been defined, then don't load the chunk into the
- * cache, just write the data to it directly.
- *
- * If MPI based VFD is used, must bypass the
- * chunk-cache scheme because other MPI processes could be
- * writing to other elements in the same chunk. Do a direct
- * write-through of only the elements requested.
- */
- if(!H5D_istore_if_load(io_info, chunk_addr)) {
- H5D_io_info_t chk_io_info; /* Temporary I/O info object */
- H5D_storage_t chk_store; /* Chunk storage information */
-
- /* Set up the storage information for the chunk */
- chk_store.contig.dset_addr=chunk_addr;
- chk_store.contig.dset_size=(hsize_t)dset->shared->layout.u.chunk.size;
-
- /* Set up new dataset I/O info */
- H5D_BUILD_IO_INFO(&chk_io_info,dset,io_info->dxpl_cache,io_info->dxpl_id,&chk_store);
-
- /* Do I/O directly on chunk without reading it into the cache */
- if((ret_value = H5D_contig_writevv(&chk_io_info, chunk_max_nseq, chunk_curr_seq, chunk_len_arr, chunk_offset_arr, mem_max_nseq, mem_curr_seq, mem_len_arr, mem_offset_arr, (haddr_t)0, NULL, buf)) < 0)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to write raw data to file")
- } /* end if */
- else {
- ssize_t naccessed; /* Number of bytes accessed in chunk */
-
- /* Use the vectorized memory copy routine to do actual work */
- if((naccessed=H5V_memcpyvv(chunk,chunk_max_nseq,chunk_curr_seq,chunk_len_arr,chunk_offset_arr,buf,mem_max_nseq,mem_curr_seq,mem_len_arr,mem_offset_arr))<0)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "vectorized memcpy failed")
-
- H5_CHECK_OVERFLOW(naccessed,ssize_t,size_t);
-
- /* Set return value */
- ret_value=naccessed;
- } /* end else */
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5D_istore_writevv() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5D_istore_create
*
* Purpose: Creates a new indexed-storage B-tree and initializes the
@@ -2567,16 +2214,16 @@ H5D_istore_allocated(H5D_t *dset, hid_t dxpl_id)
HDassert(dset);
/* Fill the DXPL cache values for later use */
- if (H5D_get_dxpl_cache(dxpl_id,&dxpl_cache)<0)
+ if(H5D_get_dxpl_cache(dxpl_id,&dxpl_cache) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, 0, "can't fill dxpl cache")
/* Construct dataset I/O info */
- H5D_BUILD_IO_INFO(&io_info,dset,dxpl_cache,dxpl_id,NULL);
+ H5D_BUILD_IO_INFO_WRT(&io_info, dset, dxpl_cache, dxpl_id, NULL, NULL);
/* Search for cached chunks that haven't been written out */
for(ent = rdcc->head; ent; ent = ent->next) {
/* Flush the chunk out to disk, to make certain the size is correct later */
- if (H5D_istore_flush_entry(&io_info, ent, FALSE)<0)
+ if (H5D_istore_flush_entry(&io_info, ent, FALSE) < 0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, 0, "cannot flush indexed storage buffer")
} /* end for */
@@ -2609,7 +2256,7 @@ done:
*/
herr_t
H5D_istore_chunkmap(const H5D_io_info_t *io_info, haddr_t chunk_addr[],
- hsize_t down_chunks[])
+ const hsize_t down_chunks[])
{
H5D_t *dset = io_info->dset; /* Local pointer to dataset info */
H5D_istore_it_ud5_t udata;
@@ -2908,7 +2555,7 @@ H5D_istore_allocate(H5D_t *dset, hid_t dxpl_id, hbool_t full_overwrite)
/* Set up dataset I/O info */
store.chunk.offset = chunk_offset;
- H5D_BUILD_IO_INFO(&io_info, dset, dxpl_cache, data_dxpl_id, &store);
+ H5D_BUILD_IO_INFO_WRT(&io_info, dset, dxpl_cache, data_dxpl_id, &store, NULL);
/* Reset the chunk offset indices */
HDmemset(chunk_offset, 0, (layout->u.chunk.ndims * sizeof(chunk_offset[0])));
@@ -3574,7 +3221,7 @@ H5D_istore_initialize_by_extent(H5D_io_info_t *io_info)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize chunk selection information")
/* Scatter the data into memory */
- if(H5D_select_mscat(fb_info.fill_buf, space_chunk, &chunk_iter, (size_t)nelmts, io_info->dxpl_cache, chunk/*out*/) < 0) {
+ if(H5D_scatter_mem(fb_info.fill_buf, space_chunk, &chunk_iter, (size_t)nelmts, io_info->dxpl_cache, chunk/*out*/) < 0) {
H5S_SELECT_ITER_RELEASE(&chunk_iter);
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "scatter failed")
} /* end if */
@@ -3728,7 +3375,7 @@ H5D_istore_update_cache(H5D_t *dset, hid_t dxpl_id)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't fill dxpl cache")
/* Construct dataset I/O info */
- H5D_BUILD_IO_INFO(&io_info, dset, dxpl_cache, dxpl_id, NULL);
+ H5D_BUILD_IO_INFO_WRT(&io_info, dset, dxpl_cache, dxpl_id, NULL, NULL);
/* Recompute the index for each cached chunk that is in a dataset */
for(ent = rdcc->head; ent; ent = next) {
@@ -3744,7 +3391,7 @@ H5D_istore_update_cache(H5D_t *dset, hid_t dxpl_id)
/* Compute the index for the chunk entry */
old_idx=ent->idx; /* Save for later */
- ent->idx=H5D_HASH(dset->shared,idx);
+ ent->idx=H5D_CHUNK_HASH(dset->shared, idx);
if(old_idx != ent->idx) {
/* Check if there is already a chunk at this chunk's new location */
diff --git a/src/H5Dmpio.c b/src/H5Dmpio.c
index 22f32ab..889fbce 100644
--- a/src/H5Dmpio.c
+++ b/src/H5Dmpio.c
@@ -34,12 +34,12 @@
/* Headers */
/***********/
#include "H5private.h" /* Generic Functions */
-#include "H5Iprivate.h"
#include "H5Dpkg.h" /* Datasets */
#include "H5Eprivate.h" /* Error handling */
#include "H5Fprivate.h" /* File access */
#include "H5FDprivate.h" /* File drivers */
-#include "H5MMprivate.h"
+#include "H5Iprivate.h" /* IDs */
+#include "H5MMprivate.h" /* Memory management */
#include "H5Oprivate.h" /* Object headers */
#include "H5Pprivate.h" /* Property lists */
#include "H5Sprivate.h" /* Dataspaces */
@@ -86,6 +86,7 @@
#define H5D_CHUNK_SELECT_IRREG 2
#define H5D_CHUNK_SELECT_NONE 0
+
/******************/
/* Local Typedefs */
/******************/
@@ -95,66 +96,47 @@ typedef struct H5D_chunk_addr_info_t {
H5D_chunk_info_t chunk_info;
} H5D_chunk_addr_info_t;
-/* Combine all information that needs to know for collective MPI-IO of this selection. */
-typedef struct H5D_common_coll_info_t {
- hbool_t mbt_is_derived;
- hbool_t mft_is_derived;
- size_t mpi_buf_count;
- haddr_t chunk_addr;
-} H5D_common_coll_info_t;
-
/********************/
/* Local Prototypes */
/********************/
-
-static herr_t
-H5D_multi_chunk_collective_io(H5D_io_info_t *io_info,H5D_chunk_map_t *fm,const void *buf,
- hbool_t do_write);
-static herr_t
-H5D_multi_chunk_collective_io_no_opt(H5D_io_info_t *io_info,H5D_chunk_map_t *fm,const void *buf,
- hbool_t do_write);
-
-static herr_t
-H5D_link_chunk_collective_io(H5D_io_info_t *io_info,H5D_chunk_map_t *fm,const void *buf,
- hbool_t do_write,int sum_chunk);
-
-static herr_t
-H5D_inter_collective_io(H5D_io_info_t *io_info,const H5S_t *file_space,
- const H5S_t *mem_space,haddr_t addr,
- const void *buf, hbool_t do_write );
-
-static herr_t
-H5D_final_collective_io(H5D_io_info_t *io_info,MPI_Datatype*mpi_file_type,
- MPI_Datatype *mpi_buf_type,
- H5D_common_coll_info_t* coll_info,
- const void *buf, hbool_t do_write);
-static herr_t
-H5D_sort_chunk(H5D_io_info_t * io_info,
- H5D_chunk_map_t *fm,
- H5D_chunk_addr_info_t chunk_addr_info_array[],
- int many_chunk_opt);
-
-static herr_t
-H5D_obtain_mpio_mode(H5D_io_info_t* io_info,
- H5D_chunk_map_t *fm,
- uint8_t assign_io_mode[],
- haddr_t chunk_addr[]);
-
-static herr_t H5D_ioinfo_make_ind(H5D_io_info_t *io_info);
-static herr_t H5D_ioinfo_make_coll_opt(H5D_io_info_t *io_info);
-static herr_t H5D_ioinfo_make_coll(H5D_io_info_t *io_info);
+static herr_t H5D_chunk_collective_io(H5D_io_info_t *io_info,
+ const H5D_type_info_t *type_info, H5D_chunk_map_t *fm);
+static herr_t H5D_multi_chunk_collective_io(H5D_io_info_t *io_info,
+ const H5D_type_info_t *type_info, H5D_chunk_map_t *fm,
+ H5P_genplist_t *dx_plist);
+static herr_t H5D_multi_chunk_collective_io_no_opt(H5D_io_info_t *io_info,
+ const H5D_type_info_t *type_info, H5D_chunk_map_t *fm, H5P_genplist_t *dx_plist);
+#ifdef H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS
+static herr_t H5D_link_chunk_collective_io(H5D_io_info_t *io_info,
+ const H5D_type_info_t *type_info, H5D_chunk_map_t *fm, int sum_chunk);
+#endif /* H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS */
+static herr_t H5D_inter_collective_io(H5D_io_info_t *io_info,
+ const H5D_type_info_t *type_info, const H5S_t *file_space,
+ const H5S_t *mem_space);
+static herr_t H5D_final_collective_io(H5D_io_info_t *io_info,
+ const H5D_type_info_t *type_info, size_t nelmts, MPI_Datatype *mpi_file_type,
+ MPI_Datatype *mpi_buf_type);
+static herr_t H5D_sort_chunk(H5D_io_info_t *io_info, const H5D_chunk_map_t *fm,
+ H5D_chunk_addr_info_t chunk_addr_info_array[], int many_chunk_opt);
+static herr_t H5D_obtain_mpio_mode(H5D_io_info_t *io_info, H5D_chunk_map_t *fm,
+ H5P_genplist_t *dx_plist, uint8_t assign_io_mode[], haddr_t chunk_addr[]);
+static herr_t H5D_ioinfo_xfer_mode(H5D_io_info_t *io_info, H5P_genplist_t *dx_plist,
+ H5FD_mpio_xfer_t xfer_mode);
+static herr_t H5D_ioinfo_coll_opt_mode(H5D_io_info_t *io_info, H5P_genplist_t *dx_plist,
+ H5FD_mpio_collective_opt_t coll_opt_mode);
static herr_t H5D_mpio_get_min_chunk(const H5D_io_info_t *io_info,
const H5D_chunk_map_t *fm, int *min_chunkf);
static int H5D_cmp_chunk_addr(const void *addr1, const void *addr2);
static herr_t H5D_mpio_get_sum_chunk(const H5D_io_info_t *io_info,
- const H5D_chunk_map_t *fm, int *sum_chunkf);
+ const H5D_chunk_map_t *fm, int *sum_chunkf);
/*********************/
/* Package Variables */
/*********************/
+
/*******************/
/* Local Variables */
/*******************/
@@ -175,64 +157,77 @@ static herr_t H5D_mpio_get_sum_chunk(const H5D_io_info_t *io_info,
*-------------------------------------------------------------------------
*/
htri_t
-H5D_mpio_opt_possible( const H5D_io_info_t *io_info,
- const H5S_t *mem_space, const H5S_t *file_space, const H5T_path_t *tpath)
+H5D_mpio_opt_possible(const H5D_io_info_t *io_info, const H5S_t *file_space,
+ const H5S_t *mem_space, const H5D_type_info_t *type_info,
+ const H5D_chunk_map_t *fm)
{
- int local_opinion = TRUE; /* This process's idea of whether to perform collective I/O or not */
- int consensus; /* Consensus opinion of all processes */
- int mpi_code; /* MPI error code */
- htri_t ret_value=TRUE;
+ int local_opinion = TRUE; /* This process's idea of whether to perform collective I/O or not */
+ int consensus; /* Consensus opinion of all processes */
+ int mpi_code; /* MPI error code */
+ htri_t ret_value = TRUE;
- FUNC_ENTER_NOAPI(H5D_mpio_opt_possible, FAIL);
+ FUNC_ENTER_NOAPI(H5D_mpio_opt_possible, FAIL)
/* Check args */
- assert(io_info);
- assert(mem_space);
- assert(file_space);
+ HDassert(io_info);
+ HDassert(mem_space);
+ HDassert(file_space);
+ HDassert(type_info);
/* For independent I/O, get out quickly and don't try to form consensus */
- if (io_info->dxpl_cache->xfer_mode==H5FD_MPIO_INDEPENDENT)
+ if(io_info->dxpl_cache->xfer_mode == H5FD_MPIO_INDEPENDENT)
HGOTO_DONE(FALSE);
+ /* Don't allow collective operations if datatype conversions need to happen */
+ if(!type_info->is_conv_noop) {
+ local_opinion = FALSE;
+ goto broadcast;
+ } /* end if */
+
+ /* Don't allow collective operations if data transform operations should occur */
+ if(!type_info->is_xform_noop) {
+ local_opinion = FALSE;
+ goto broadcast;
+ } /* end if */
+
/* Optimized MPI types flag must be set and it must be collective IO */
/* (Don't allow parallel I/O for the MPI-posix driver, since it doesn't do real collective I/O) */
- if (!(H5S_mpi_opt_types_g && io_info->dxpl_cache->xfer_mode==H5FD_MPIO_COLLECTIVE && !IS_H5FD_MPIPOSIX(io_info->dset->oloc.file))) {
+ if(!(H5S_mpi_opt_types_g && io_info->dxpl_cache->xfer_mode == H5FD_MPIO_COLLECTIVE
+ && !IS_H5FD_MPIPOSIX(io_info->dset->oloc.file))) {
local_opinion = FALSE;
goto broadcast;
} /* end if */
/* Check whether these are both simple or scalar dataspaces */
- if (!((H5S_SIMPLE==H5S_GET_EXTENT_TYPE(mem_space) || H5S_SCALAR==H5S_GET_EXTENT_TYPE(mem_space))
- && (H5S_SIMPLE==H5S_GET_EXTENT_TYPE(file_space) || H5S_SCALAR==H5S_GET_EXTENT_TYPE(file_space)))) {
+ if(!((H5S_SIMPLE == H5S_GET_EXTENT_TYPE(mem_space) || H5S_SCALAR == H5S_GET_EXTENT_TYPE(mem_space))
+ && (H5S_SIMPLE == H5S_GET_EXTENT_TYPE(file_space) || H5S_SCALAR == H5S_GET_EXTENT_TYPE(file_space)))) {
local_opinion = FALSE;
goto broadcast;
} /* end if */
/* Can't currently handle point selections */
- if (H5S_SEL_POINTS==H5S_GET_SELECT_TYPE(mem_space) || H5S_SEL_POINTS==H5S_GET_SELECT_TYPE(file_space)) {
+ if(H5S_SEL_POINTS == H5S_GET_SELECT_TYPE(mem_space)
+ || H5S_SEL_POINTS == H5S_GET_SELECT_TYPE(file_space)) {
local_opinion = FALSE;
goto broadcast;
} /* end if */
/* Dataset storage must be contiguous or chunked */
- if (!(io_info->dset->shared->layout.type == H5D_CONTIGUOUS ||
+ if(!(io_info->dset->shared->layout.type == H5D_CONTIGUOUS ||
io_info->dset->shared->layout.type == H5D_CHUNKED)) {
local_opinion = FALSE;
goto broadcast;
} /* end if */
- /* The handling of memory space is different for chunking
- and contiguous storage,
- For contigous storage, mem_space and file_space won't
- change when it it is doing disk IO.
- For chunking storage, mem_space will change for different
- chunks. So for chunking storage, whether we can use
- collective IO will defer until each chunk IO is reached.
- For contiguous storage, if we find MPI-IO cannot
- support complicated MPI derived data type and the shape
- of data space is not regular, we will
- set use_par_opt_io = FALSE.
- */
+ /* The handling of memory space is different for chunking and contiguous
+ * storage. For contiguous storage, mem_space and file_space won't change
+ * when it it is doing disk IO. For chunking storage, mem_space will
+ * change for different chunks. So for chunking storage, whether we can
+ * use collective IO will defer until each chunk IO is reached. For
+ * contiguous storage, if we find MPI-IO cannot support complicated MPI
+ * derived data type and the shape of data space is not regular, we will
+ * set use_par_opt_io = FALSE.
+ */
#ifndef H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS
if(io_info->dset->shared->layout.type == H5D_CONTIGUOUS)
if((H5S_SELECT_IS_REGULAR(file_space) != TRUE) ||
@@ -243,81 +238,43 @@ H5D_mpio_opt_possible( const H5D_io_info_t *io_info,
#endif
/* Don't allow collective operations if filters need to be applied */
- if(io_info->dset->shared->layout.type == H5D_CHUNKED)
- if(io_info->dset->shared->dcpl_cache.pline.nused>0) {
+ if(io_info->dset->shared->layout.type == H5D_CHUNKED) {
+ if(io_info->dset->shared->dcpl_cache.pline.nused > 0) {
local_opinion = FALSE;
goto broadcast;
} /* end if */
- /* Don't allow collective operations if datatype conversions need to happen */
- if(!H5T_path_noop(tpath)) {
- local_opinion = FALSE;
- goto broadcast;
- } /* end if */
-
- /* Don't allow collective operations if data transform operations should occur */
- if(!H5Z_xform_noop(io_info->dxpl_cache->data_xform_prop)) {
- local_opinion = FALSE;
- goto broadcast;
+/* If H5_MPI_SPECIAL_COLLECTIVE_IO_WORKS and H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS
+ * are defined, the HDF5 library will do collective IO if the application
+ * asks for it.
+ *
+ * If H5_MPI_SPECIAL_COLLECTIVE_IO_WORKS is not defined and one or more
+ * processes are not participating in the IO, then collective IO is not
+ * assured. The library will check each process for the number of chunks
+ * it involves. If any process involves zero chunks, the library will use
+ * independent IO mode instead.
+ */
+#ifndef H5_MPI_SPECIAL_COLLECTIVE_IO_WORKS
+ /* Check the number of chunks to perform I/O on */
+ if(0 == H5SL_count(fm->sel_chunks)) {
+ local_opinion = FALSE;
+ goto broadcast;
+ } /* end if */
+#endif /* H5_MPI_SPECIAL_COLLECTIVE_IO_WORKS */
} /* end if */
broadcast:
/* Form consensus opinion among all processes about whether to perform
- * collective I/O */
- if (MPI_SUCCESS != (mpi_code = MPI_Allreduce(&local_opinion, &consensus, 1, MPI_INT, MPI_LAND, io_info->comm)))
+ * collective I/O
+ */
+ if(MPI_SUCCESS != (mpi_code = MPI_Allreduce(&local_opinion, &consensus, 1, MPI_INT, MPI_LAND, io_info->comm)))
HMPI_GOTO_ERROR(FAIL, "MPI_Allreduce failed", mpi_code)
ret_value = consensus > 0 ? TRUE : FALSE;
done:
- FUNC_LEAVE_NOAPI(ret_value);
-} /* H5D_mpio_opt_possible() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_mpio_chunk_adjust_iomode
- *
- * Decription: If H5_MPI_SPECIAL_COLLECTIVE_IO_WORKS and
- H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS are defined,
- the HDF5 library will do collective IO if the application asks for it.
-
- If H5_MPI_SPECIAL_COLLECTIVE_IO_WORKS is not defined
- and one or more processes are not participating in the IO,
- then collective IO is not assured. The library will check
- each process for the
- number of chunks it involves. If any process involves zero chunks,
- the library will use independent IO mode instead.
- This function is only used for linked chunk IO.
- * Purpose: Checks if it is possible to do collective IO
- *
- * Return: Success: Non-negative: TRUE or FALSE
- * Failure: Negative
- *
- * Programmer: Muqun Yang
- * Monday, Feb. 13th, 2006
- *
- *-------------------------------------------------------------------------
- */
-#ifndef H5_MPI_SPECIAL_COLLECTIVE_IO_WORKS
-herr_t
-H5D_mpio_chunk_adjust_iomode(H5D_io_info_t *io_info, const H5D_chunk_map_t *fm)
-{
- int min_chunk;
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI_NOINIT(H5D_mpio_chunk_adjust_iomode)
-
- if(H5D_mpio_get_min_chunk(io_info,fm,&min_chunk) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSWAP, FAIL, "unable to obtain the min chunk number of all processes");
- if(min_chunk == 0) {
- /* Switch to independent I/O */
- if(H5D_ioinfo_make_ind(io_info) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't switch to independent I/O")
- } /* end if */
-done:
FUNC_LEAVE_NOAPI(ret_value)
-}
-#endif
+} /* H5D_mpio_opt_possible() */
/*-------------------------------------------------------------------------
@@ -332,23 +289,20 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5D_mpio_select_read(H5D_io_info_t *io_info,
- size_t mpi_buf_count,
- const size_t UNUSED elmt_size,
- const H5S_t UNUSED *file_space,
- const H5S_t UNUSED *mem_space,
- haddr_t addr,
- void UNUSED *pointer,
- void *buf/*out*/)
+H5D_mpio_select_read(const H5D_io_info_t *io_info, const H5D_type_info_t UNUSED *type_info,
+ hsize_t mpi_buf_count, const H5S_t UNUSED *file_space, const H5S_t UNUSED *mem_space)
{
+ const H5D_contig_storage_t *store_contig = &(io_info->store->contig); /* Contiguous storage info for this I/O operation */
herr_t ret_value = SUCCEED;
- FUNC_ENTER_NOAPI(H5D_mpio_select_read,FAIL);
+ FUNC_ENTER_NOAPI(H5D_mpio_select_read, FAIL)
+
+ H5_CHECK_OVERFLOW(mpi_buf_count, hsize_t, size_t);
+ if(H5F_block_read(io_info->dset->oloc.file, H5FD_MEM_DRAW, store_contig->dset_addr, (size_t)mpi_buf_count, io_info->dxpl_id, io_info->u.rbuf) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "can't finish collective parallel read")
- if(H5F_block_read (io_info->dset->oloc.file, H5FD_MEM_DRAW, addr, mpi_buf_count, io_info->dxpl_id, buf) < 0)
- HGOTO_ERROR(H5E_IO,H5E_READERROR,FAIL,"can't finish collective parallel read");
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D_mpio_select_read() */
@@ -364,32 +318,28 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5D_mpio_select_write(H5D_io_info_t *io_info,
- size_t mpi_buf_count,
- const size_t UNUSED elmt_size,
- const H5S_t UNUSED *file_space,
- const H5S_t UNUSED *mem_space,
- haddr_t addr,
- void UNUSED *pointer,
- const void *buf)
+H5D_mpio_select_write(const H5D_io_info_t *io_info, const H5D_type_info_t UNUSED *type_info,
+ hsize_t mpi_buf_count, const H5S_t UNUSED *file_space, const H5S_t UNUSED *mem_space)
{
+ const H5D_contig_storage_t *store_contig = &(io_info->store->contig); /* Contiguous storage info for this I/O operation */
herr_t ret_value = SUCCEED;
- FUNC_ENTER_NOAPI(H5D_mpio_select_write,FAIL);
+ FUNC_ENTER_NOAPI(H5D_mpio_select_write, FAIL)
/*OKAY: CAST DISCARDS CONST QUALIFIER*/
- if(H5F_block_write (io_info->dset->oloc.file, H5FD_MEM_DRAW, addr, mpi_buf_count, io_info->dxpl_id, buf)<0)
- HGOTO_ERROR(H5E_IO,H5E_WRITEERROR,FAIL,"can't finish collective parallel write");
+ H5_CHECK_OVERFLOW(mpi_buf_count, hsize_t, size_t);
+ if(H5F_block_write(io_info->dset->oloc.file, H5FD_MEM_DRAW, store_contig->dset_addr, (size_t)mpi_buf_count, io_info->dxpl_id, io_info->u.wbuf) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "can't finish collective parallel write")
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D_mpio_select_write() */
/*-------------------------------------------------------------------------
- * Function: H5D_ioinfo_make_ind
+ * Function: H5D_ioinfo_xfer_mode
*
- * Purpose: Switch to MPI independent I/O
+ * Purpose: Switch to between collective & independent MPI I/O
*
* Return: Non-negative on success/Negative on failure
*
@@ -399,42 +349,42 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5D_ioinfo_make_ind(H5D_io_info_t *io_info)
+H5D_ioinfo_xfer_mode(H5D_io_info_t *io_info, H5P_genplist_t *dx_plist,
+ H5FD_mpio_xfer_t xfer_mode)
{
- H5P_genplist_t *dx_plist; /* Data transer property list */
herr_t ret_value = SUCCEED; /*return value */
- FUNC_ENTER_NOAPI_NOINIT(H5D_ioinfo_make_ind)
-
- /* Get the dataset transfer property list */
- if (NULL == (dx_plist = H5I_object(io_info->dxpl_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset transfer property list")
+ FUNC_ENTER_NOAPI_NOINIT(H5D_ioinfo_xfer_mode)
- /* Change the xfer_mode to independent, handle the request,
- * then set xfer_mode before return.
- */
- io_info->dxpl_cache->xfer_mode = H5FD_MPIO_INDEPENDENT;
- if(H5P_set (dx_plist, H5D_XFER_IO_XFER_MODE_NAME, &io_info->dxpl_cache->xfer_mode) < 0)
+ /* Change the xfer_mode */
+ io_info->dxpl_cache->xfer_mode = xfer_mode;
+ if(H5P_set(dx_plist, H5D_XFER_IO_XFER_MODE_NAME, &io_info->dxpl_cache->xfer_mode) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set transfer mode")
- /* Set the pointers to the non-MPI-specific routines */
- io_info->ops.read = H5D_select_read;
- io_info->ops.write = H5D_select_write;
+ /* Change the "single I/O" function pointers */
+ if(xfer_mode == H5FD_MPIO_INDEPENDENT) {
+ /* Set the pointers to the original, non-MPI-specific routines */
+ io_info->io_ops.single_read = io_info->orig.io_ops.single_read;
+ io_info->io_ops.single_write = io_info->orig.io_ops.single_write;
+ } /* end if */
+ else {
+ HDassert(xfer_mode == H5FD_MPIO_COLLECTIVE);
- /* Indicate that the transfer mode should be restored before returning
- * to user.
- */
- io_info->xfer_mode_changed=TRUE;
+ /* Set the pointers to the MPI-specific routines */
+ io_info->io_ops.single_read = H5D_mpio_select_read;
+ io_info->io_ops.single_write = H5D_mpio_select_write;
+ } /* end else */
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_ioinfo_make_ind() */
+} /* end H5D_ioinfo_xfer_mode() */
/*-------------------------------------------------------------------------
- * Function: H5D_ioinfo_make_coll_opt
+ * Function: H5D_ioinfo_coll_opt_mode
*
- * Purpose: Switch to MPI independent I/O with file set view
+ * Purpose: Switch between using collective & independent MPI I/O w/file
+ * set view
*
* Return: Non-negative on success/Negative on failure
*
@@ -444,87 +394,21 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5D_ioinfo_make_coll_opt(H5D_io_info_t *io_info)
+H5D_ioinfo_coll_opt_mode(H5D_io_info_t *io_info, H5P_genplist_t *dx_plist,
+ H5FD_mpio_collective_opt_t coll_opt_mode)
{
- H5P_genplist_t *dx_plist; /* Data transer property list */
herr_t ret_value = SUCCEED; /*return value */
- FUNC_ENTER_NOAPI_NOINIT(H5D_ioinfo_make_coll_opt)
+ FUNC_ENTER_NOAPI_NOINIT(H5D_ioinfo_coll_opt_mode)
- /* Get the dataset transfer property list */
- if (NULL == (dx_plist = H5I_object(io_info->dxpl_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset transfer property list")
-
- /* Change the optimial xfer_mode to independent, handle the request,
- * then set xfer_mode before return.
- */
- io_info->dxpl_cache->xfer_opt_mode = H5FD_MPIO_INDIVIDUAL_IO;
- if(H5P_set (dx_plist, H5D_XFER_IO_XFER_OPT_MODE_NAME, &io_info->dxpl_cache->xfer_opt_mode) < 0)
+ /* Change the optimal xfer_mode */
+ io_info->dxpl_cache->coll_opt_mode = coll_opt_mode;
+ if(H5P_set(dx_plist, H5D_XFER_MPIO_COLLECTIVE_OPT_NAME, &io_info->dxpl_cache->coll_opt_mode) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set transfer mode")
- /* Set the pointers to the non-MPI-specific routines */
- io_info->ops.read = H5D_mpio_select_read;
- io_info->ops.write = H5D_mpio_select_write;
-
- /* Indicate that the transfer mode should be restored before returning
- * to user.
- */
- io_info->xfer_opt_mode_changed = TRUE;
-
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_ioinfo_make_coll_opt() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_ioinfo_make_coll
- *
- * Purpose: Switch to MPI collective I/O
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * Friday, August 12, 2005
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5D_ioinfo_make_coll(H5D_io_info_t *io_info)
-{
- H5P_genplist_t *dx_plist; /* Data transer property list */
- herr_t ret_value = SUCCEED; /*return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5D_ioinfo_make_coll)
-
- /* Get the dataset transfer property list */
- if (NULL == (dx_plist = H5I_object(io_info->dxpl_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset transfer property list")
-
- /* Change the xfer_mode to independent, handle the request,
- * then set xfer_mode before return.
- */
- io_info->dxpl_cache->xfer_mode = H5FD_MPIO_COLLECTIVE;
- if(H5P_set (dx_plist, H5D_XFER_IO_XFER_MODE_NAME, &io_info->dxpl_cache->xfer_mode) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set transfer mode")
-
- io_info->dxpl_cache->xfer_opt_mode = H5FD_MPIO_COLLECTIVE_IO;
- if(H5P_set (dx_plist, H5D_XFER_IO_XFER_OPT_MODE_NAME, &io_info->dxpl_cache->xfer_opt_mode) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set transfer mode")
-
-
- /* Set the pointers to the MPI-specific routines */
- io_info->ops.read = H5D_mpio_select_read;
- io_info->ops.write = H5D_mpio_select_write;
-
- /* Indicate that the transfer mode should _NOT_ be restored before returning
- * to user.
- */
- io_info->xfer_mode_changed=FALSE;
- io_info->xfer_opt_mode_changed=FALSE;
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_ioinfo_make_coll() */
+} /* end H5D_ioinfo_coll_opt_mode() */
/*-------------------------------------------------------------------------
@@ -535,29 +419,30 @@ done:
*
* Return: Non-negative on success/Negative on failure
*
- * Programmer:
+ * Programmer: Muqun Yang
+ * Monday, Feb. 13th, 2006
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5D_mpio_get_min_chunk(const H5D_io_info_t *io_info,
- const H5D_chunk_map_t *fm, int *min_chunkf)
+H5D_mpio_get_min_chunk(const H5D_io_info_t *io_info, const H5D_chunk_map_t *fm,
+ int *min_chunkf)
{
int num_chunkf; /* Number of chunks to iterate over */
int mpi_code; /* MPI return code */
herr_t ret_value = SUCCEED;
- FUNC_ENTER_NOAPI_NOINIT(H5D_mpio_get_min_chunk);
+ FUNC_ENTER_NOAPI_NOINIT(H5D_mpio_get_min_chunk)
/* Get the number of chunks to perform I/O on */
num_chunkf = H5SL_count(fm->sel_chunks);
/* Determine the minimum # of chunks for all processes */
- if (MPI_SUCCESS != (mpi_code = MPI_Allreduce(&num_chunkf, min_chunkf, 1, MPI_INT, MPI_MIN, io_info->comm)))
+ if(MPI_SUCCESS != (mpi_code = MPI_Allreduce(&num_chunkf, min_chunkf, 1, MPI_INT, MPI_MIN, io_info->comm)))
HMPI_GOTO_ERROR(FAIL, "MPI_Allreduce failed", mpi_code)
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D_mpio_get_min_chunk() */
@@ -569,221 +454,252 @@ done:
*
* Return: Non-negative on success/Negative on failure
*
- * Programmer:
+ * Programmer: Muqun Yang
+ * Monday, Feb. 13th, 2006
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5D_mpio_get_sum_chunk(const H5D_io_info_t *io_info,
- const H5D_chunk_map_t *fm, int *sum_chunkf)
+H5D_mpio_get_sum_chunk(const H5D_io_info_t *io_info, const H5D_chunk_map_t *fm,
+ int *sum_chunkf)
{
int num_chunkf; /* Number of chunks to iterate over */
size_t ori_num_chunkf;
int mpi_code; /* MPI return code */
herr_t ret_value = SUCCEED;
- FUNC_ENTER_NOAPI_NOINIT(H5D_mpio_get_sum_chunk);
+ FUNC_ENTER_NOAPI_NOINIT(H5D_mpio_get_sum_chunk)
/* Get the number of chunks to perform I/O on */
num_chunkf = 0;
ori_num_chunkf = H5SL_count(fm->sel_chunks);
- H5_ASSIGN_OVERFLOW(num_chunkf,ori_num_chunkf,size_t,int);
+ H5_ASSIGN_OVERFLOW(num_chunkf, ori_num_chunkf, size_t, int);
/* Determine the summation of number of chunks for all processes */
- if (MPI_SUCCESS != (mpi_code = MPI_Allreduce(&num_chunkf, sum_chunkf, 1, MPI_INT, MPI_SUM, io_info->comm)))
+ if(MPI_SUCCESS != (mpi_code = MPI_Allreduce(&num_chunkf, sum_chunkf, 1, MPI_INT, MPI_SUM, io_info->comm)))
HMPI_GOTO_ERROR(FAIL, "MPI_Allreduce failed", mpi_code)
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D_mpio_get_sum_chunk() */
/*-------------------------------------------------------------------------
- * Function: H5D_contig_collective_io
+ * Function: H5D_contig_collective_read
*
- * Purpose: Wrapper Routine for H5D_inter_collective_io
- The starting file address of contiguous layout
- will be calculated and passed to H5D_inter_collective_io routine.
- *
+ * Purpose: Reads directly from contiguous data in file into application
+ * memory using collective I/O.
*
* Return: Non-negative on success/Negative on failure
*
- * Programmer:
- *
- * Modifications:
+ * Programmer: Quincey Koziol
+ * Tuesday, March 4, 2008
*
*-------------------------------------------------------------------------
*/
herr_t
-H5D_contig_collective_io(H5D_io_info_t *io_info,
- const H5S_t *file_space,
- const H5S_t *mem_space,
- const void *buf,
- hbool_t do_write)
+H5D_contig_collective_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
+ hsize_t UNUSED nelmts, const H5S_t *file_space, const H5S_t *mem_space,
+ H5D_chunk_map_t UNUSED *fm)
{
+ herr_t ret_value = SUCCEED; /* Return value */
+ FUNC_ENTER_NOAPI(H5D_contig_collective_read, FAIL)
- haddr_t addr = HADDR_UNDEF; /* Address of dataset (or selection) within file */
- herr_t ret_value = SUCCEED; /* return value */
+ /* Sanity check */
+ HDassert(IS_H5FD_MPIO(io_info->dset->oloc.file));
+ HDassert(TRUE == H5P_isa_class(io_info->dxpl_id, H5P_DATASET_XFER));
+
+ /* Call generic internal collective I/O routine */
+ if(H5D_inter_collective_io(io_info, type_info, file_space, mem_space) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "couldn't finish shared collective MPI-IO")
- FUNC_ENTER_NOAPI_NOINIT(H5D_contig_collective_io)
- assert (IS_H5FD_MPIO(io_info->dset->oloc.file));
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_contig_collective_read() */
- /* Make certain we have the correct type of property list */
- assert(TRUE==H5P_isa_class(io_info->dxpl_id,H5P_DATASET_XFER));
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_contig_collective_write
+ *
+ * Purpose: Write directly to contiguous data in file from application
+ * memory using collective I/O.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, March 4, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5D_contig_collective_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
+ hsize_t UNUSED nelmts, const H5S_t *file_space, const H5S_t *mem_space,
+ H5D_chunk_map_t UNUSED *fm)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
- /* Get the base address of the contiguous dataset */
- if(io_info->dset->shared->layout.type == H5D_CONTIGUOUS)
- addr = H5D_contig_get_addr(io_info->dset);
+ FUNC_ENTER_NOAPI(H5D_contig_collective_write, FAIL)
- if(H5D_inter_collective_io(io_info,file_space,mem_space,addr,buf,do_write)<0)
- HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL,"couldn't finish shared collective MPI-IO");
-
- done:
+ /* Sanity check */
+ HDassert(IS_H5FD_MPIO(io_info->dset->oloc.file));
+ HDassert(TRUE == H5P_isa_class(io_info->dxpl_id, H5P_DATASET_XFER));
+ /* Call generic internal collective I/O routine */
+ if(H5D_inter_collective_io(io_info, type_info, file_space, mem_space) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "couldn't finish shared collective MPI-IO")
+
+done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_contig_collective_io */
+} /* end H5D_contig_collective_write() */
/*-------------------------------------------------------------------------
* Function: H5D_chunk_collective_io
*
* Purpose: Routine for
- 1) choose an IO option:
- a) One collective IO defined by one MPI derived datatype to link through all chunks
- or b) multiple chunk IOs,to do MPI-IO for each chunk, the IO mode may be adjusted
- due to the selection pattern for each chunk.
+ * 1) choose an IO option:
+ * a) One collective IO defined by one MPI derived datatype to link through all chunks
+ * or b) multiple chunk IOs,to do MPI-IO for each chunk, the IO mode may be adjusted
+ * due to the selection pattern for each chunk.
* For option a)
- 1. Sort the chunk address, obtain chunk info according to the sorted chunk address
- 2. Build up MPI derived datatype for each chunk
- 3. Build up the final MPI derived datatype
- 4. Set up collective IO property list
- 5. Do IO
+ * 1. Sort the chunk address, obtain chunk info according to the sorted chunk address
+ * 2. Build up MPI derived datatype for each chunk
+ * 3. Build up the final MPI derived datatype
+ * 4. Set up collective IO property list
+ * 5. Do IO
* For option b)
- 1. Use MPI_gather and MPI_Bcast to obtain information of *collective/independent/none*
- IO mode for each chunk of the selection
- 2. Depending on whether the IO mode is collective or independent or none,
- Create either MPI derived datatype for each chunk to do collective IO or
- just do independent IO or independent IO with file set view
- 3. Set up collective IO property list for collective mode
- 4. DO IO
+ * 1. Use MPI_gather and MPI_Bcast to obtain information of *collective/independent/none*
+ * IO mode for each chunk of the selection
+ * 2. Depending on whether the IO mode is collective or independent or none,
+ * Create either MPI derived datatype for each chunk to do collective IO or
+ * just do independent IO or independent IO with file set view
+ * 3. Set up collective IO property list for collective mode
+ * 4. DO IO
*
* Return: Non-negative on success/Negative on failure
*
- * Programmer:
- *
- * Modifications:
+ * Programmer: Muqun Yang
+ * Monday, Feb. 13th, 2006
*
*-------------------------------------------------------------------------
*/
-herr_t
-H5D_chunk_collective_io(H5D_io_info_t *io_info,H5D_chunk_map_t *fm,const void *buf, hbool_t do_write)
+static herr_t
+H5D_chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
+ H5D_chunk_map_t *fm)
{
-
- int io_option = H5D_MULTI_CHUNK_IO_MORE_OPT;
- int sum_chunk = 0,mpi_size;
- unsigned one_link_chunk_io_threshold;
- H5P_genplist_t *plist;
+ H5P_genplist_t *dx_plist; /* Pointer to DXPL */
H5FD_mpio_chunk_opt_t chunk_opt_mode;
-
+ int io_option = H5D_MULTI_CHUNK_IO_MORE_OPT;
+ int sum_chunk = -1;
#ifdef H5_HAVE_INSTRUMENTED_LIBRARY
- htri_t check_prop,temp_not_link_io = FALSE;
- int new_value;
+ htri_t temp_not_link_io = FALSE;
#endif
- herr_t ret_value = SUCCEED;
+ herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI_NOINIT(H5D_chunk_collective_io)
- assert (IS_H5FD_MPIO(io_info->dset->oloc.file));
+ /* Sanity checks */
+ HDassert(io_info);
+ HDassert(io_info->using_mpi_vfd);
+ HDassert(type_info);
+ HDassert(fm);
/* Obtain the data transfer properties */
- if(NULL == (plist = H5I_object(io_info->dxpl_id)))
+ if(NULL == (dx_plist = H5I_object(io_info->dxpl_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list")
-
+
/* Check the optional property list on what to do with collective chunk IO. */
- chunk_opt_mode=(H5FD_mpio_chunk_opt_t)H5P_peek_unsigned(plist,H5D_XFER_MPIO_CHUNK_OPT_HARD_NAME);
-
+ chunk_opt_mode = (H5FD_mpio_chunk_opt_t)H5P_peek_unsigned(dx_plist, H5D_XFER_MPIO_CHUNK_OPT_HARD_NAME);
if(chunk_opt_mode == H5FD_MPIO_CHUNK_ONE_IO)
- io_option = H5D_ONE_LINK_CHUNK_IO;/*no opt*/
+ io_option = H5D_ONE_LINK_CHUNK_IO; /*no opt*/
else if(chunk_opt_mode == H5FD_MPIO_CHUNK_MULTI_IO)
- io_option = H5D_MULTI_CHUNK_IO;/*no opt */
+ io_option = H5D_MULTI_CHUNK_IO; /*no opt */
else {
- if(H5D_mpio_get_sum_chunk(io_info,fm,&sum_chunk)<0)
+ unsigned one_link_chunk_io_threshold; /* Threshhold to use single collective I/O for all chunks */
+ int mpi_size; /* Number of processes in MPI job */
+
+ if(H5D_mpio_get_sum_chunk(io_info, fm, &sum_chunk) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSWAP, FAIL, "unable to obtain the total chunk number of all processes");
- if((mpi_size = H5F_mpi_get_size(io_info->dset->oloc.file))<0)
- HGOTO_ERROR (H5E_IO, H5E_MPI, FAIL, "unable to obtain mpi size");
+ if((mpi_size = H5F_mpi_get_size(io_info->dset->oloc.file)) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_MPI, FAIL, "unable to obtain mpi size")
- if(NULL == (plist = H5I_object(io_info->dxpl_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list")
-
- one_link_chunk_io_threshold =H5P_peek_unsigned(plist,H5D_XFER_MPIO_CHUNK_OPT_NUM_NAME);
+ one_link_chunk_io_threshold = H5P_peek_unsigned(dx_plist, H5D_XFER_MPIO_CHUNK_OPT_NUM_NAME);
- /* step 1: choose an IO option */
- /* If the average number of chunk per process is greater than a threshold, we will do one link chunked IO. */
- if((unsigned)sum_chunk/mpi_size >= one_link_chunk_io_threshold)
+ /* step 1: choose an IO option */
+ /* If the average number of chunk per process is greater than a threshold, we will do one link chunked IO. */
+ if((unsigned)sum_chunk / mpi_size >= one_link_chunk_io_threshold)
io_option = H5D_ONE_LINK_CHUNK_IO_MORE_OPT;
#ifdef H5_HAVE_INSTRUMENTED_LIBRARY
- else
- temp_not_link_io = TRUE;
+ else
+ temp_not_link_io = TRUE;
+#endif
+ } /* end else */
+
+#ifndef H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS
+ if(io_option == H5D_ONE_LINK_CHUNK_IO)
+ io_option = H5D_MULTI_CHUNK_IO; /* We can not do this with one chunk IO. */
+ if(io_option == H5D_ONE_LINK_CHUNK_IO_MORE_OPT)
+ io_option = H5D_MULTI_CHUNK_IO_MORE_OPT;
#endif
- }
#ifdef H5_HAVE_INSTRUMENTED_LIBRARY
+{
+ htri_t check_prop;
+ int new_value;
+
/*** Test collective chunk user-input optimization APIs. ***/
- check_prop = H5Pexist(io_info->dxpl_id,H5D_XFER_COLL_CHUNK_LINK_HARD_NAME);
+ check_prop = H5Pexist(io_info->dxpl_id, H5D_XFER_COLL_CHUNK_LINK_HARD_NAME);
if(check_prop > 0) {
if(io_option == H5D_ONE_LINK_CHUNK_IO) {
- new_value = 0;
- if(H5Pset(io_info->dxpl_id,H5D_XFER_COLL_CHUNK_LINK_HARD_NAME,&new_value)<0)
- HGOTO_ERROR(H5E_PLIST, H5E_UNSUPPORTED, FAIL, "unable to get property value");
- }
- }
- check_prop = H5Pexist(io_info->dxpl_id,H5D_XFER_COLL_CHUNK_MULTI_HARD_NAME);
+ new_value = 0;
+ if(H5Pset(io_info->dxpl_id, H5D_XFER_COLL_CHUNK_LINK_HARD_NAME, &new_value) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_CANTSET, FAIL, "unable to set property value")
+ } /* end if */
+ } /* end if */
+ check_prop = H5Pexist(io_info->dxpl_id, H5D_XFER_COLL_CHUNK_MULTI_HARD_NAME);
if(check_prop > 0) {
- if(io_option == H5D_MULTI_CHUNK_IO) {
- new_value = 0;
- if(H5Pset(io_info->dxpl_id,H5D_XFER_COLL_CHUNK_MULTI_HARD_NAME,&new_value)<0)
- HGOTO_ERROR(H5E_PLIST, H5E_UNSUPPORTED, FAIL, "unable to get property value");
- }
- }
- check_prop = H5Pexist(io_info->dxpl_id,H5D_XFER_COLL_CHUNK_LINK_NUM_TRUE_NAME);
+ if(io_option == H5D_MULTI_CHUNK_IO) {
+ new_value = 0;
+ if(H5Pset(io_info->dxpl_id, H5D_XFER_COLL_CHUNK_MULTI_HARD_NAME, &new_value) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_CANTSET, FAIL, "unable to set property value")
+ } /* end if */
+ } /* end if */
+ check_prop = H5Pexist(io_info->dxpl_id, H5D_XFER_COLL_CHUNK_LINK_NUM_TRUE_NAME);
if(check_prop > 0) {
- if(io_option == H5D_ONE_LINK_CHUNK_IO_MORE_OPT) {
- new_value = 0;
- if(H5Pset(io_info->dxpl_id,H5D_XFER_COLL_CHUNK_LINK_NUM_TRUE_NAME,&new_value)<0)
- HGOTO_ERROR(H5E_PLIST, H5E_UNSUPPORTED, FAIL, "unable to get property value");
- }
- }
- check_prop = H5Pexist(io_info->dxpl_id,H5D_XFER_COLL_CHUNK_LINK_NUM_FALSE_NAME);
+ if(io_option == H5D_ONE_LINK_CHUNK_IO_MORE_OPT) {
+ new_value = 0;
+ if(H5Pset(io_info->dxpl_id, H5D_XFER_COLL_CHUNK_LINK_NUM_TRUE_NAME, &new_value) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_CANTSET, FAIL, "unable to set property value")
+ } /* end if */
+ } /* end if */
+ check_prop = H5Pexist(io_info->dxpl_id, H5D_XFER_COLL_CHUNK_LINK_NUM_FALSE_NAME);
if(check_prop > 0) {
- if(temp_not_link_io){
- new_value = 0;
- if(H5Pset(io_info->dxpl_id,H5D_XFER_COLL_CHUNK_LINK_NUM_FALSE_NAME,&new_value)<0)
- HGOTO_ERROR(H5E_PLIST, H5E_UNSUPPORTED, FAIL, "unable to get property value");
- }
- }
-#endif
-
-#ifndef H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS
- if(io_option == H5D_ONE_LINK_CHUNK_IO )
- io_option = H5D_MULTI_CHUNK_IO ;/* We can not do this with one chunk IO. */
- if(io_option == H5D_ONE_LINK_CHUNK_IO_MORE_OPT)
- io_option = H5D_MULTI_CHUNK_IO_MORE_OPT;
+ if(temp_not_link_io) {
+ new_value = 0;
+ if(H5Pset(io_info->dxpl_id, H5D_XFER_COLL_CHUNK_LINK_NUM_FALSE_NAME, &new_value) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_CANTSET, FAIL, "unable to set property value")
+ } /* end if */
+ } /* end if */
+}
#endif
/* step 2: Go ahead to do IO.*/
+#ifdef H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS
if(io_option == H5D_ONE_LINK_CHUNK_IO || io_option == H5D_ONE_LINK_CHUNK_IO_MORE_OPT) {
- if(H5D_link_chunk_collective_io(io_info,fm,buf,do_write,sum_chunk)<0)
- HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL,"couldn't finish linked chunk MPI-IO");
- }
- else if(io_option == H5D_MULTI_CHUNK_IO) {
- if(H5D_multi_chunk_collective_io_no_opt(io_info,fm,buf,do_write)<0)
- HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL,"couldn't finish multiple chunk MPI-IO");
- }
+ if(H5D_link_chunk_collective_io(io_info, type_info, fm, sum_chunk) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL, "couldn't finish linked chunk MPI-IO")
+ } /* end if */
+ else
+#endif /* H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS */
+ if(io_option == H5D_MULTI_CHUNK_IO) {
+ if(H5D_multi_chunk_collective_io_no_opt(io_info, type_info, fm, dx_plist) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL, "couldn't finish multiple chunk MPI-IO")
+ } /* end if */
else { /*multiple chunk IOs with opt */
- if(H5D_multi_chunk_collective_io(io_info,fm,buf,do_write)<0)
- HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL,"couldn't finish multiple chunk MPI-IO");
- }
+ if(H5D_multi_chunk_collective_io(io_info, type_info, fm, dx_plist) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL, "couldn't finish optimized multiple chunk MPI-IO")
+ } /* end else */
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -791,459 +707,583 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5D_link_chunk_collective_io
+ * Function: H5D_chunk_collective_read
*
- * Purpose: Routine for one collective IO with one MPI derived datatype to link with all chunks
+ * Purpose: Reads directly from chunks in file into application memory
+ * using collective I/O.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, March 4, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5D_chunk_collective_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
+ hsize_t UNUSED nelmts, const H5S_t UNUSED *file_space, const H5S_t UNUSED *mem_space,
+ H5D_chunk_map_t *fm)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
- 1. Sort the chunk address and chunk info
- 2. Build up MPI derived datatype for each chunk
- 3. Build up the final MPI derived datatype
- 4. Use common collective IO routine to do MPI-IO
+ FUNC_ENTER_NOAPI(H5D_chunk_collective_read, FAIL)
+ /* Call generic selection operation */
+ if(H5D_chunk_collective_io(io_info, type_info, fm) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_READERROR, FAIL, "read error")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_chunk_collective_read() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_chunk_collective_write
*
- * Return: Non-negative on success/Negative on failure
+ * Purpose: Write directly to chunks in file from application memory
+ * using collective I/O.
*
- * Programmer:
+ * Return: Non-negative on success/Negative on failure
*
- * Modifications:
+ * Programmer: Quincey Koziol
+ * Tuesday, March 4, 2008
*
*-------------------------------------------------------------------------
*/
+herr_t
+H5D_chunk_collective_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
+ hsize_t UNUSED nelmts, const H5S_t UNUSED *file_space, const H5S_t UNUSED *mem_space,
+ H5D_chunk_map_t *fm)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5D_chunk_collective_write, FAIL)
+
+ /* Call generic selection operation */
+ if(H5D_chunk_collective_io(io_info, type_info, fm) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_WRITEERROR, FAIL, "write error")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_chunk_collective_write() */
+#ifdef H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_link_chunk_collective_io
+ *
+ * Purpose: Routine for one collective IO with one MPI derived datatype to link with all chunks
+ *
+ * 1. Sort the chunk address and chunk info
+ * 2. Build up MPI derived datatype for each chunk
+ * 3. Build up the final MPI derived datatype
+ * 4. Use common collective IO routine to do MPI-IO
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Muqun Yang
+ * Monday, Feb. 13th, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
static herr_t
-H5D_link_chunk_collective_io(H5D_io_info_t *io_info,H5D_chunk_map_t *fm,const void *buf, hbool_t do_write,int sum_chunk)
+H5D_link_chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
+ H5D_chunk_map_t *fm, int sum_chunk)
{
- size_t src_type_size; /*size of source type */
- size_t dst_type_size; /*size of destination type*/
- hsize_t mpi_buf_extra_offset;
- hsize_t mpi_file_extra_offset;
- size_t mpi_buf_count;
- size_t mpi_file_count;
- hbool_t mbt_is_derived=0, /* Whether the buffer (memory) type is derived and needs to be free'd */
- mft_is_derived=0; /* Whether the file type is derived and needs to be free'd */
-
- int mpi_size,mpi_code; /* MPI return code */
-
- int i,num_chunk=0,total_chunks;
- size_t ori_num_chunk;
- hsize_t ori_total_chunks;
- haddr_t chunk_base_addr;
- haddr_t* total_chunk_addr_array=NULL;
- MPI_Datatype *chunk_mtype=NULL;
- MPI_Datatype *chunk_ftype=NULL;
- MPI_Datatype chunk_final_mtype;
- MPI_Datatype chunk_final_ftype;
- MPI_Aint *chunk_disp_array=NULL;
- MPI_Aint *chunk_mem_disp_array=NULL;
- int *blocklen=NULL;
- int blocklen_value;
- int actual_bsearch_coll_chunk_threshold;
- int bsearch_coll_chunk_threshold;
- int many_chunk_opt = 0;
-
- H5D_common_coll_info_t coll_info;
- H5D_chunk_addr_info_t* chunk_addr_info_array=NULL;
-
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI_NOINIT(H5D_link_chunk_collective_io)
- ori_total_chunks = fm->total_chunks;
- H5_ASSIGN_OVERFLOW(total_chunks,ori_total_chunks,hsize_t,int);
-
- /* Handle with a special case when only one chunk is covered by all processes */
- if(total_chunks == 1){
- H5SL_node_t *chunk_node;
- H5D_chunk_info_t *chunk_info;
- H5D_storage_t store;
+ H5D_chunk_addr_info_t *chunk_addr_info_array = NULL;
+ hbool_t mbt_is_derived = FALSE;
+ hbool_t mft_is_derived = FALSE;
+ MPI_Datatype chunk_final_mtype; /* Final memory MPI datatype for all chunks with seletion */
+ MPI_Datatype chunk_final_ftype; /* Final file MPI datatype for all chunks with seletion */
+ H5D_storage_t ctg_store; /* Storage info for "fake" contiguous dataset */
+ size_t total_chunks;
+ haddr_t *total_chunk_addr_array = NULL;
+ MPI_Datatype *chunk_mtype = NULL;
+ MPI_Datatype *chunk_ftype = NULL;
+ MPI_Aint *chunk_disp_array = NULL;
+ MPI_Aint *chunk_mem_disp_array = NULL;
+ int *blocklen = NULL;
+ int mpi_code; /* MPI return code */
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_link_chunk_collective_io)
+
+ /* Get the sum # of chunks, if not already available */
+ if(sum_chunk < 0) {
+ if(H5D_mpio_get_sum_chunk(io_info, fm, &sum_chunk) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSWAP, FAIL, "unable to obtain the total chunk number of all processes");
+ } /* end if */
+
+ /* Retrieve total # of chunks in dataset */
+ H5_ASSIGN_OVERFLOW(total_chunks, fm->total_chunks, hsize_t, size_t);
+
+ /* Handle special case when dataspace dimensions only allow one chunk in
+ * the dataset. [This sometimes is used by developers who want the
+ * equivalent of compressed contiguous datasets - QAK]
+ */
+ if(total_chunks == 1) {
+ H5D_storage_t chk_store; /* Temporary storage info for chunk address lookup */
+ hsize_t coords[H5O_LAYOUT_NDIMS]; /* Coordinates of chunk in file dataset's dataspace */
+ H5SL_node_t *chunk_node; /* Pointer to chunk node for selection */
+ H5S_t *fspace; /* Dataspace describing chunk & selection in it */
+ H5S_t *mspace; /* Dataspace describing selection in memory corresponding to this chunk */
+
+ /* Initialize the chunk coordinates */
+ /* (must be all zero, since there's only one chunk) */
+ HDmemset(coords, 0, sizeof(coords));
+
+ /* Look up address of chunk */
+ io_info->store = &chk_store;
+ chk_store.chunk.offset = coords;
+ chk_store.chunk.index = 0;
+ if(HADDR_UNDEF == (ctg_store.contig.dset_addr = H5D_istore_get_addr(io_info, NULL)))
+ HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL, "couldn't get chunk info from skipped list")
+ /* Check for this process having selection in this chunk */
chunk_node = H5SL_first(fm->sel_chunks);
if(chunk_node == NULL) {
- if(H5D_istore_chunkmap(io_info, &chunk_base_addr, fm->down_chunks) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get chunk address");
- if(H5D_inter_collective_io(io_info,NULL,NULL,chunk_base_addr,buf,do_write)<0)
- HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL,"couldn't finish shared collective MPI-IO");
- }
+ /* Set the dataspace info for I/O to NULL, this process doesn't have any I/O to perform */
+ fspace = mspace = NULL;
+ } /* end if */
else {
- if(NULL ==(chunk_info = H5SL_item(chunk_node)))
- HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL,"couldn't get chunk info from skipped list");
- io_info->store = &store;
- store.chunk.offset = chunk_info->coords;
- store.chunk.index = chunk_info->index;
+ H5D_chunk_info_t *chunk_info;
+
+ /* Get the chunk info, for the selection in the chunk */
+ if(NULL == (chunk_info = H5SL_item(chunk_node)))
+ HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL, "couldn't get chunk info from skipped list")
+
+ /* Set the dataspace info for I/O */
+ fspace = chunk_info->fspace;
+ mspace = chunk_info->mspace;
+ } /* end else */
+
+ /* Set up the base storage address for this chunk */
+ io_info->store = &ctg_store;
- if(HADDR_UNDEF==(chunk_base_addr = H5D_istore_get_addr(io_info,NULL)))
- HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL,"couldn't get chunk info from skipped list");
-
#ifdef H5D_DEBUG
- if(H5DEBUG(D))
- HDfprintf(H5DEBUG(D),"before inter_collective_io for total chunk = 1 \n");
+if(H5DEBUG(D))
+ HDfprintf(H5DEBUG(D),"before inter_collective_io for total chunk = 1 \n");
#endif
- if(H5D_inter_collective_io(io_info,chunk_info->fspace,chunk_info->mspace,chunk_base_addr,buf,do_write)<0)
- HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL,"couldn't finish shared collective MPI-IO");
- }
- goto done;
- }
- /* Allocate chunking information */
- ori_num_chunk = H5SL_count(fm->sel_chunks);
- H5_ASSIGN_OVERFLOW(num_chunk,ori_num_chunk,size_t,int);
+ /* Perform I/O */
+ if(H5D_inter_collective_io(io_info, type_info, fspace, mspace) < 0)
+ HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL, "couldn't finish shared collective MPI-IO")
+ } /* end if */
+ else {
+ size_t mpi_buf_count; /* Number of MPI types */
+ size_t num_chunk; /* Number of chunks for this process */
+ size_t u; /* Local index variable */
+
+ /* Get the number of chunks with a selection */
+ num_chunk = H5SL_count(fm->sel_chunks);
+ H5_CHECK_OVERFLOW(num_chunk, size_t, int);
#ifdef H5D_DEBUG
- if(H5DEBUG(D))
- HDfprintf(H5DEBUG(D),"total_chunks = %d\n",(int)total_chunks);
+if(H5DEBUG(D))
+ HDfprintf(H5DEBUG(D),"total_chunks = %Zu, num_chunk = %Zu\n", total_chunks, num_chunk);
#endif
-
- if(num_chunk == 0)
- total_chunk_addr_array = H5MM_malloc(sizeof(haddr_t)*total_chunks);
- else
- {
- chunk_addr_info_array= H5MM_malloc(num_chunk*sizeof(H5D_chunk_addr_info_t));
- chunk_mtype = H5MM_malloc(num_chunk*sizeof(MPI_Datatype));
- chunk_ftype = H5MM_malloc(num_chunk*sizeof(MPI_Datatype));
- chunk_disp_array = H5MM_malloc(num_chunk*sizeof(MPI_Aint));
- chunk_mem_disp_array = H5MM_calloc(num_chunk*sizeof(MPI_Aint));
- blocklen = H5MM_malloc(num_chunk*sizeof(int));
- }
-
- /* Obtain information to do collective IO,
- in order to do collective IO, no datatype conversion should happen. */
- if((src_type_size = H5T_get_size(io_info->dset->shared->type))==0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_BADSIZE, FAIL, "datatype size invalid");
- dst_type_size = src_type_size;
-
- bsearch_coll_chunk_threshold = H5D_ALL_CHUNK_ADDR_THRES_COL;
-
- if((mpi_size = H5F_mpi_get_size(io_info->dset->oloc.file))<0)
- HGOTO_ERROR (H5E_IO, H5E_MPI, FAIL, "unable to obtain mpi size");
-
- /* Calculate the actual threshold to obtain all chunk addresses collectively
- The bigger this number is, the more possible the use of obtaining chunk address collectively. */
- /* For non-optimization one-link IO,
- actual bsearch threshold is always 0,
- we would always want to obtain the chunk addresses individually
- for each process. */
- actual_bsearch_coll_chunk_threshold = sum_chunk*100/(total_chunks*mpi_size);
-
- if((actual_bsearch_coll_chunk_threshold > bsearch_coll_chunk_threshold)
- &&(sum_chunk/mpi_size >= H5D_ALL_CHUNK_ADDR_THRES_COL_NUM))
- many_chunk_opt = H5D_OBTAIN_ALL_CHUNK_ADDR_COL;
+
+ /* Set up MPI datatype for chunks selected */
+ if(num_chunk) {
+ hsize_t mpi_mem_extra_offset; /* Extra offset for memory MPI datatype */
+ hsize_t mpi_file_extra_offset; /* Extra offset for file MPI datatype */
+ size_t mpi_mem_count; /* Memory MPI datatype count */
+ size_t mpi_file_count; /* File MPI datatype count */
+ hbool_t locl_mbt_is_derived = FALSE, /* Whether the buffer (memory) type is derived and needs to be free'd */
+ local_mft_is_derived = FALSE; /* Whether the file type is derived and needs to be free'd */
+ int blocklen_value; /* Placeholder for array fill */
+
+ /* Allocate chunking information */
+ chunk_addr_info_array= H5MM_malloc(num_chunk * sizeof(H5D_chunk_addr_info_t));
+ chunk_mtype = H5MM_malloc(num_chunk * sizeof(MPI_Datatype));
+ chunk_ftype = H5MM_malloc(num_chunk * sizeof(MPI_Datatype));
+ chunk_disp_array = H5MM_malloc(num_chunk * sizeof(MPI_Aint));
+ chunk_mem_disp_array = H5MM_calloc(num_chunk * sizeof(MPI_Aint));
+ blocklen = H5MM_malloc(num_chunk * sizeof(int));
#ifdef H5D_DEBUG
- if(H5DEBUG(D))
+if(H5DEBUG(D))
HDfprintf(H5DEBUG(D),"before sorting the chunk address \n");
#endif
-
- /* Sort the chunk address
- when chunk optimization selection is either H5D_OBTAIN_*/
-
- if(num_chunk == 0){ /* special case: this process doesn't select anything */
- if(H5D_istore_chunkmap(io_info, total_chunk_addr_array, fm->down_chunks)<0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get chunk address");
- chunk_base_addr = total_chunk_addr_array[0];
- }
-
- else {
- if(H5D_sort_chunk(io_info,fm,chunk_addr_info_array,many_chunk_opt)<0)
- HGOTO_ERROR (H5E_DATASPACE, H5E_CANTSWAP, FAIL, "unable to sort chunk address");
- chunk_base_addr = chunk_addr_info_array[0].chunk_addr;
- }
+ /* Sort the chunk address */
+ if(H5D_sort_chunk(io_info, fm, chunk_addr_info_array, sum_chunk) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSWAP, FAIL, "unable to sort chunk address")
+ ctg_store.contig.dset_addr = chunk_addr_info_array[0].chunk_addr;
#ifdef H5D_DEBUG
- if(H5DEBUG(D))
+if(H5DEBUG(D))
HDfprintf(H5DEBUG(D),"after sorting the chunk address \n");
#endif
-
- /* Obtain MPI derived datatype from all individual chunks */
- for ( i = 0; i < num_chunk; i++) {
- /* Disk MPI derived datatype */
- if(H5S_mpio_space_type(chunk_addr_info_array[i].chunk_info.fspace,src_type_size,&chunk_ftype[i],
- &mpi_file_count,&mpi_file_extra_offset,&mft_is_derived)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL,"couldn't create MPI file type");
-
- /* Buffer MPI derived datatype */
- if(H5S_mpio_space_type(chunk_addr_info_array[i].chunk_info.mspace,dst_type_size,&chunk_mtype[i],
- &mpi_buf_count,&mpi_buf_extra_offset,&mbt_is_derived)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL,"couldn't create MPI buf type");
-
- /* Chunk address relative to the first chunk */
- chunk_addr_info_array[i].chunk_addr -= chunk_base_addr;
- H5_ASSIGN_OVERFLOW(chunk_disp_array[i],chunk_addr_info_array[i].chunk_addr,haddr_t,MPI_Aint);
- }
-
- blocklen_value = 1;
- if(num_chunk){
-
- /* initialize the buffer with the constant value 1; this algo. is very fast. */
- H5V_array_fill(blocklen,&blocklen_value,sizeof(int),(size_t)num_chunk);
-
- /* Create final MPI derived datatype */
- if(MPI_SUCCESS != (mpi_code = MPI_Type_struct(num_chunk,blocklen,chunk_disp_array,chunk_ftype,&chunk_final_ftype)))
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_struct failed", mpi_code);
- if(MPI_SUCCESS != (mpi_code = MPI_Type_commit(&chunk_final_ftype)))
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code);
-
- if(MPI_SUCCESS != (mpi_code = MPI_Type_struct(num_chunk,blocklen,chunk_mem_disp_array,chunk_mtype,&chunk_final_mtype)))
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_struct failed", mpi_code);
- if(MPI_SUCCESS != (mpi_code = MPI_Type_commit(&chunk_final_mtype)))
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code);
-
- for ( i = 0; i< num_chunk;i++){
- if (MPI_SUCCESS != (mpi_code= MPI_Type_free( chunk_mtype+i )))
- HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code);
-
- if (MPI_SUCCESS != (mpi_code= MPI_Type_free( chunk_ftype+i )))
- HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code);
- }
-
- /* buffer, file derived datatypes should be true */
- coll_info.mbt_is_derived = 1;
- coll_info.mft_is_derived = 1;
- coll_info.mpi_buf_count = 1;
- coll_info.chunk_addr = chunk_base_addr;
-
- }
-
- else {/* no selection at all for this process */
- chunk_final_ftype = MPI_BYTE;
- chunk_final_mtype = MPI_BYTE;
-
- /* buffer, file derived datatypes should be true */
- coll_info.mbt_is_derived = 0;
- coll_info.mft_is_derived = 0;
- coll_info.mpi_buf_count = 0;
- coll_info.chunk_addr = chunk_base_addr;
- }
+
+ /* Obtain MPI derived datatype from all individual chunks */
+ for(u = 0; u < num_chunk; u++) {
+ /* Disk MPI derived datatype */
+ if(H5S_mpio_space_type(chunk_addr_info_array[u].chunk_info.fspace,
+ type_info->src_type_size, &chunk_ftype[u], &mpi_file_count,
+ &mpi_file_extra_offset, &local_mft_is_derived) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "couldn't create MPI file type")
+
+ /* Buffer MPI derived datatype */
+ if(H5S_mpio_space_type(chunk_addr_info_array[u].chunk_info.mspace,
+ type_info->dst_type_size, &chunk_mtype[u], &mpi_mem_count,
+ &mpi_mem_extra_offset, &locl_mbt_is_derived) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "couldn't create MPI buf type")
+
+ /* Chunk address relative to the first chunk */
+ chunk_addr_info_array[u].chunk_addr -= ctg_store.contig.dset_addr;
+ H5_ASSIGN_OVERFLOW(chunk_disp_array[u], chunk_addr_info_array[u].chunk_addr, haddr_t, MPI_Aint);
+ } /* end for */
+
+ /* Initialize the buffer with the constant value 1 */
+ blocklen_value = 1;
+ H5V_array_fill(blocklen, &blocklen_value, sizeof(int), num_chunk);
+
+ /* Create final MPI derived datatype for the file */
+ if(MPI_SUCCESS != (mpi_code = MPI_Type_struct((int)num_chunk, blocklen, chunk_disp_array, chunk_ftype, &chunk_final_ftype)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Type_struct failed", mpi_code)
+ if(MPI_SUCCESS != (mpi_code = MPI_Type_commit(&chunk_final_ftype)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code)
+
+ /* Create final MPI derived datatype for memory */
+ if(MPI_SUCCESS != (mpi_code = MPI_Type_struct(num_chunk, blocklen, chunk_mem_disp_array, chunk_mtype, &chunk_final_mtype)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Type_struct failed", mpi_code)
+ if(MPI_SUCCESS != (mpi_code = MPI_Type_commit(&chunk_final_mtype)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code)
+
+ /* Free the file & memory MPI datatypes for each chunk */
+ for(u = 0; u < num_chunk; u++) {
+ if(MPI_SUCCESS != (mpi_code = MPI_Type_free(chunk_mtype + u)))
+ HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code)
+
+ if(MPI_SUCCESS != (mpi_code = MPI_Type_free(chunk_ftype + u)))
+ HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code)
+ } /* end for */
+
+ /* buffer, file derived datatypes should be true */
+ mbt_is_derived = TRUE;
+ mft_is_derived = TRUE;
+ mpi_buf_count = (size_t)1;
+ } /* end if */
+ else { /* no selection at all for this process */
+ /* Allocate chunking information */
+ total_chunk_addr_array = H5MM_malloc(sizeof(haddr_t) * total_chunks);
+
+ /* Retrieve chunk address map */
+ if(H5D_istore_chunkmap(io_info, total_chunk_addr_array, fm->down_chunks) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get chunk address")
+
+ /* Get chunk with lowest address */
+ ctg_store.contig.dset_addr = HADDR_MAX;
+ for(u = 0; u < total_chunks; u++)
+ if(total_chunk_addr_array[u] < ctg_store.contig.dset_addr)
+ ctg_store.contig.dset_addr = total_chunk_addr_array[u];
+ HDassert(ctg_store.contig.dset_addr != HADDR_MAX);
+
+ /* Set the MPI datatype */
+ chunk_final_ftype = MPI_BYTE;
+ chunk_final_mtype = MPI_BYTE;
+
+ /* buffer, file derived datatypes should be true */
+ mpi_buf_count = (size_t)0;
+ } /* end else */
#ifdef H5D_DEBUG
- if(H5DEBUG(D))
+if(H5DEBUG(D))
HDfprintf(H5DEBUG(D),"before coming to final collective IO\n");
#endif
- if(H5D_final_collective_io(io_info,&chunk_final_ftype,&chunk_final_mtype,&coll_info,buf,do_write)<0)
- HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL,"couldn't finish MPI-IO");
+ /* Set up the base storage address for this chunk */
+ io_info->store = &ctg_store;
+
+ /* Perform final collective I/O operation */
+ if(H5D_final_collective_io(io_info, type_info, mpi_buf_count, &chunk_final_ftype, &chunk_final_mtype) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL, "couldn't finish MPI-IO")
+ } /* end else */
done:
#ifdef H5D_DEBUG
- if(H5DEBUG(D))
- HDfprintf(H5DEBUG(D),"before freeing memory inside H5D_link_collective_io ret_value = %d\n",ret_value);
+if(H5DEBUG(D))
+ HDfprintf(H5DEBUG(D),"before freeing memory inside H5D_link_collective_io ret_value = %d\n", ret_value);
#endif
- if (fm->total_chunks != 1) {
- if(num_chunk == 0) HDfree(total_chunk_addr_array);
- else {
- HDfree(chunk_addr_info_array);
- HDfree(chunk_mtype);
- HDfree(chunk_ftype);
- HDfree(chunk_disp_array);
- HDfree(chunk_mem_disp_array);
- HDfree(blocklen);
- }
- }
- FUNC_LEAVE_NOAPI(ret_value)
+ if(total_chunk_addr_array)
+ H5MM_xfree(total_chunk_addr_array);
+ if(chunk_addr_info_array)
+ H5MM_xfree(chunk_addr_info_array);
+ if(chunk_mtype)
+ H5MM_xfree(chunk_mtype);
+ if(chunk_ftype)
+ H5MM_xfree(chunk_ftype);
+ if(chunk_disp_array)
+ H5MM_xfree(chunk_disp_array);
+ if(chunk_mem_disp_array)
+ H5MM_xfree(chunk_mem_disp_array);
+ if(blocklen)
+ H5MM_xfree(blocklen);
+
+ /* Free the MPI buf and file types, if they were derived */
+ if(mbt_is_derived && MPI_SUCCESS != (mpi_code = MPI_Type_free(&chunk_final_mtype)))
+ HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code)
+ if(mft_is_derived && MPI_SUCCESS != (mpi_code = MPI_Type_free(&chunk_final_ftype)))
+ HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code)
+
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D_link_chunk_collective_io */
+#endif /* H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS */
/*-------------------------------------------------------------------------
* Function: H5D_multi_chunk_collective_io
*
* Purpose: To do IO per chunk according to IO mode(collective/independent/none)
-
- 1. Use MPI_gather and MPI_Bcast to obtain IO mode in each chunk(collective/independent/none)
- 2. Depending on whether the IO mode is collective or independent or none,
- Create either MPI derived datatype for each chunk or just do independent IO
- 3. Use common collective IO routine to do MPI-IO
*
- * Return: Non-negative on success/Negative on failure
+ * 1. Use MPI_gather and MPI_Bcast to obtain IO mode in each chunk(collective/independent/none)
+ * 2. Depending on whether the IO mode is collective or independent or none,
+ * Create either MPI derived datatype for each chunk or just do independent IO
+ * 3. Use common collective IO routine to do MPI-IO
*
- * Programmer:
+ * Return: Non-negative on success/Negative on failure
*
- * Modifications:
+ * Programmer: Muqun Yang
+ * Monday, Feb. 13th, 2006
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5D_multi_chunk_collective_io(H5D_io_info_t *io_info,H5D_chunk_map_t *fm,const void *buf, hbool_t do_write)
+H5D_multi_chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
+ H5D_chunk_map_t *fm, H5P_genplist_t *dx_plist)
{
- unsigned i, total_chunk;
- hsize_t ori_total_chunk;
- uint8_t *chunk_io_option;
-
- H5SL_node_t *chunk_node; /* Current node in chunk skip list */
- H5D_chunk_info_t *chunk_info=NULL;
- haddr_t *chunk_addr;
- H5D_storage_t store; /* union of EFL and chunk pointer in file space */
- hbool_t select_chunk;
- hbool_t last_io_mode_coll = TRUE;
-
- void *chunk = NULL; /* Pointer to the data chunk in cache */
- H5D_t *dataset=io_info->dset;/* Local pointer to dataset info */
- H5D_istore_ud1_t udata; /*B-tree pass-through */
- haddr_t caddr; /* Address of the cached chunk */
- size_t accessed_bytes; /*total accessed size in a chunk */
- unsigned idx_hint=0; /* Cache index hint */
- hbool_t dirty = TRUE; /* Flag for cache flushing */
- hbool_t relax=TRUE; /* Whether whole chunk is selected */
-
- herr_t ret_value = SUCCEED;
+ H5D_t *dataset = io_info->dset;/* Local pointer to dataset info */
+ H5D_io_info_t ctg_io_info; /* Contiguous I/O info object */
+ H5D_storage_t ctg_store; /* Chunk storage information as contiguous dataset */
+ H5D_io_info_t cpt_io_info; /* Compact I/O info object */
+ H5D_storage_t cpt_store; /* Chunk storage information as compact dataset */
+ hbool_t cpt_dirty; /* Temporary placeholder for compact storage "dirty" flag */
+ uint8_t *chunk_io_option = NULL;
+ haddr_t *chunk_addr = NULL;
+ H5D_storage_t store; /* union of EFL and chunk pointer in file space */
+ H5FD_mpio_xfer_t last_xfer_mode = H5FD_MPIO_COLLECTIVE; /* Last parallel transfer for this request (H5D_XFER_IO_XFER_MODE_NAME) */
+ H5FD_mpio_collective_opt_t last_coll_opt_mode = H5FD_MPIO_COLLECTIVE_IO; /* Last parallel transfer with independent IO or collective IO with this mode */
+ size_t total_chunk; /* Total # of chunks in dataset */
#ifdef H5Dmpio_DEBUG
- int mpi_rank;
+ int mpi_rank;
#endif
+ size_t u; /* Local index variable */
+ herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI_NOINIT(H5D_multi_chunk_collective_io)
+ FUNC_ENTER_NOAPI_NOINIT(H5D_multi_chunk_collective_io)
#ifdef H5Dmpio_DEBUG
- mpi_rank = H5F_mpi_get_rank(io_info->dset->oloc.file);
+ mpi_rank = H5F_mpi_get_rank(io_info->dset->oloc.file);
#endif
- /* Allocate memories */
- ori_total_chunk = fm->total_chunks;
- H5_ASSIGN_OVERFLOW(total_chunk,ori_total_chunk,hsize_t,unsigned);
- HDassert(total_chunk!=0);
- chunk_io_option = (uint8_t *)H5MM_calloc(total_chunk*sizeof(MPI_BYTE));
- chunk_addr = (haddr_t *)H5MM_calloc(total_chunk*sizeof(haddr_t));
+ /* Retrieve total # of chunks in dataset */
+ H5_ASSIGN_OVERFLOW(total_chunk, fm->total_chunks, hsize_t, size_t);
+ HDassert(total_chunk != 0);
+
+ /* Allocate memories */
+ chunk_io_option = (uint8_t *)H5MM_calloc(total_chunk);
+ chunk_addr = (haddr_t *)H5MM_calloc(total_chunk * sizeof(haddr_t));
#ifdef H5D_DEBUG
- if(H5DEBUG(D))
- HDfprintf(H5DEBUG(D),"total_chunk %u\n",total_chunk);
+if(H5DEBUG(D))
+ HDfprintf(H5DEBUG(D), "total_chunk %Zu\n", total_chunk);
#endif
- /* obtain IO option for each chunk */
- if(H5D_obtain_mpio_mode(io_info,fm,chunk_io_option,chunk_addr)<0)
- HGOTO_ERROR (H5E_DATASET, H5E_CANTRECV, FAIL, "unable to obtain MPIO mode");
+ /* Obtain IO option for each chunk */
+ if(H5D_obtain_mpio_mode(io_info, fm, dx_plist, chunk_io_option, chunk_addr) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTRECV, FAIL, "unable to obtain MPIO mode")
+
+ /* Set up contiguous I/O info object */
+ HDmemcpy(&ctg_io_info, io_info, sizeof(ctg_io_info));
+ ctg_io_info.store = &ctg_store;
+ ctg_io_info.layout_ops = *H5D_LOPS_CONTIG;
+
+ /* Initialize temporary contiguous storage info */
+ ctg_store.contig.dset_size = (hsize_t)io_info->dset->shared->layout.u.chunk.size;
+
+ /* Set up compact I/O info object */
+ HDmemcpy(&cpt_io_info, io_info, sizeof(cpt_io_info));
+ cpt_io_info.store = &cpt_store;
+ cpt_io_info.layout_ops = *H5D_LOPS_COMPACT;
+
+ /* Initialize temporary compact storage info */
+ cpt_store.compact.dirty = &cpt_dirty;
+
+ /* Set dataset storage for I/O info */
+ io_info->store = &store;
+
+ /* Loop over _all_ the chunks */
+ for(u = 0; u < total_chunk; u++) {
+ H5D_chunk_info_t *chunk_info; /* Chunk info for current chunk */
+ H5S_t *fspace; /* Dataspace describing chunk & selection in it */
+ H5S_t *mspace; /* Dataspace describing selection in memory corresponding to this chunk */
- for(i = 0; i < total_chunk; i++) {
#ifdef H5D_DEBUG
- if(H5DEBUG(D))
- HDfprintf(H5DEBUG(D),"mpi_rank = %d, chunk index = %u\n",mpi_rank,i);
+if(H5DEBUG(D))
+ HDfprintf(H5DEBUG(D),"mpi_rank = %d, chunk index = %Zu\n", mpi_rank, u);
#endif
- select_chunk = fm->select_chunk[i];
- if(select_chunk == 1){/* Have selection elements in this chunk. Find the chunk info. */
- if(NULL ==(chunk_node = H5SL_first(fm->sel_chunks)))
- HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL,"couldn't get chunk node from skipped list");
-
- while(chunk_node){
- if(NULL ==(chunk_info = H5SL_item(chunk_node)))
- HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL,"couldn't get chunk info from skipped list");
- if(chunk_info->index == i) {
- /* Set dataset storage for I/O info */
- io_info->store=&store;
- /* Pass in chunk's coordinates in a union. */
- store.chunk.offset = chunk_info->coords;
- store.chunk.index = chunk_info->index;
- break;
- }
-
- chunk_node = H5SL_next(chunk_node);
- }
- }
-
- if(chunk_io_option[i] == 1){ /*collective IO for this chunk,
- note: even there is no selection for this process,
- the process still needs to contribute MPI NONE TYPE.*/
+ /* Get the chunk info for this chunk, if there are elements selected */
+ chunk_info = fm->select_chunk[u];
+
+ /* Set the storage information for chunks with selections */
+ if(chunk_info) {
+ HDassert(chunk_info->index == u);
+
+ /* Pass in chunk's coordinates in a union. */
+ store.chunk.offset = chunk_info->coords;
+ store.chunk.index = chunk_info->index;
+ } /* end if */
+
+ /* Collective IO for this chunk,
+ * Note: even there is no selection for this process, the process still
+ * needs to contribute MPI NONE TYPE.
+ */
+ if(chunk_io_option[u] == 1) {
#ifdef H5D_DEBUG
- if(H5DEBUG(D))
- HDfprintf(H5DEBUG(D),"inside collective chunk IO mpi_rank = %d, chunk index = %u\n",mpi_rank,i);
+if(H5DEBUG(D))
+ HDfprintf(H5DEBUG(D),"inside collective chunk IO mpi_rank = %d, chunk index = %Zu\n", mpi_rank, u);
#endif
- if(!last_io_mode_coll)
- /* Switch back to collective I/O */
- if(H5D_ioinfo_make_coll(io_info) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't switch to collective I/O")
+ /* Set the file & memory dataspaces */
+ if(chunk_info) {
+ fspace = chunk_info->fspace;
+ mspace = chunk_info->mspace;
+ } /* end if */
+ else {
+ fspace = mspace = NULL;
+ } /* end else */
+
+ /* Switch back to collective I/O */
+ if(last_xfer_mode != H5FD_MPIO_COLLECTIVE) {
+ if(H5D_ioinfo_xfer_mode(io_info, dx_plist, H5FD_MPIO_COLLECTIVE) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't switch to collective I/O")
+ last_xfer_mode = H5FD_MPIO_COLLECTIVE;
+ } /* end if */
+ if(last_coll_opt_mode != H5FD_MPIO_COLLECTIVE_IO) {
+ if(H5D_ioinfo_coll_opt_mode(io_info, dx_plist, H5FD_MPIO_COLLECTIVE_IO) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't switch to collective I/O")
+ last_coll_opt_mode = H5FD_MPIO_COLLECTIVE_IO;
+ } /* end if */
- if(select_chunk){
- if(H5D_inter_collective_io(io_info,chunk_info->fspace,chunk_info->mspace,
- chunk_addr[i],buf,do_write )<0)
- HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL,"couldn't finish shared collective MPI-IO");
-
- }
- else{
- if(H5D_inter_collective_io(io_info,NULL,NULL,
- chunk_addr[i],buf,do_write )<0)
- HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL,"couldn't finish shared collective MPI-IO");
-
- }
- last_io_mode_coll = TRUE;
-
- }
- else {/*possible independent IO for this chunk*/
+ /* Initialize temporary contiguous storage address */
+ ctg_store.contig.dset_addr = chunk_addr[u];
+
+ /* Perform the I/O */
+ if(H5D_inter_collective_io(&ctg_io_info, type_info, fspace, mspace) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL, "couldn't finish shared collective MPI-IO")
+ } /* end if */
+ else { /* possible independent IO for this chunk */
#ifdef H5D_DEBUG
- if(H5DEBUG(D))
- HDfprintf(H5DEBUG(D),"inside independent IO mpi_rank = %d, chunk index = %u\n",mpi_rank,i);
+if(H5DEBUG(D))
+ HDfprintf(H5DEBUG(D),"inside independent IO mpi_rank = %d, chunk index = %Zu\n", mpi_rank, u);
#endif
- HDassert(chunk_io_option[i] == 0);
+ HDassert(chunk_io_option[u] == 0);
#if !defined(H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS) || !defined(H5_MPI_SPECIAL_COLLECTIVE_IO_WORKS)
- if(!select_chunk)
- continue; /* this process has nothing to do with this chunk, continue! */
- if(last_io_mode_coll)
+ /* Check if this process has somethign to do with this chunk */
+ if(chunk_info) {
+ H5D_io_info_t *chk_io_info; /* Pointer to I/O info object for this chunk */
+ H5D_istore_ud1_t udata; /* B-tree pass-through */
+ void *chunk; /* Pointer to the data chunk in cache */
+ size_t accessed_bytes; /* Total accessed size in a chunk */
+ unsigned idx_hint = 0; /* Cache index hint */
+ haddr_t caddr; /* Address of the cached chunk */
+
/* Switch to independent I/O */
- if(H5D_ioinfo_make_ind(io_info) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't switch to independent I/O")
-
- /* Load the chunk into cache. But if the whole chunk is written,
- * simply allocate space instead of load the chunk. */
- if(HADDR_UNDEF==(caddr = H5D_istore_get_addr(io_info, &udata)))
- HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL,"couldn't get chunk info from skipped list");
-
- if(H5D_istore_if_load(io_info, caddr)) {
- accessed_bytes = chunk_info->chunk_points * H5T_get_size(dataset->shared->type);
- if((do_write && (accessed_bytes != dataset->shared->layout.u.chunk.size)) || !do_write)
- relax=FALSE;
-
- if(NULL == (chunk = H5D_istore_lock(io_info, &udata, relax, &idx_hint)))
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to read raw data chunk")
- } else
- chunk = NULL;
-
- if(do_write) {
- if((io_info->ops.write)(io_info,
- chunk_info->chunk_points,H5T_get_size(io_info->dset->shared->type),
- chunk_info->fspace,chunk_info->mspace,caddr,chunk, buf) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "optimized write failed")
- }
- else {
- if((io_info->ops.read)(io_info,
- chunk_info->chunk_points,H5T_get_size(io_info->dset->shared->type),
- chunk_info->fspace,chunk_info->mspace,caddr,chunk, buf) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "optimized read failed")
- }
+ if(last_xfer_mode != H5FD_MPIO_INDEPENDENT) {
+ if(H5D_ioinfo_xfer_mode(io_info, dx_plist, H5FD_MPIO_INDEPENDENT) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't switch to independent I/O")
+ last_xfer_mode = H5FD_MPIO_INDEPENDENT;
+ } /* end if */
- /* Release the cache lock on the chunk. */
- if(chunk) {
- if(!do_write)
- dirty = FALSE;
+ /* Load the chunk into cache. But if the whole chunk is written,
+ * simply allocate space instead of load the chunk.
+ */
+ if(HADDR_UNDEF == (caddr = H5D_istore_get_addr(io_info, &udata)))
+ HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL, "couldn't get chunk info from skipped list")
- if(H5D_istore_unlock(io_info, dirty, idx_hint, chunk, accessed_bytes) < 0)
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to unlock raw data chunk")
- } /* end if */
-#else
- if(!last_io_mode_coll)
- /* using independent I/O with file setview.*/
- if(H5D_ioinfo_make_coll_opt(io_info) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't switch to collective I/O")
- if(select_chunk){
- if(H5D_inter_collective_io(io_info,chunk_info->fspace,chunk_info->mspace,
- chunk_addr[i],buf,do_write )<0)
- HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL,"couldn't finish shared collective MPI-IO");
- }
+ /* Load the chunk into cache and lock it. */
+ if(H5D_chunk_cacheable(io_info, caddr)) {
+ hbool_t entire_chunk = TRUE; /* Whether whole chunk is selected */
+
+ /* Compute # of bytes accessed in chunk */
+ accessed_bytes = chunk_info->chunk_points * type_info->src_type_size;
+
+ /* Determine if we will access all the data in the chunk */
+ if(((io_info->op_type == H5D_IO_OP_WRITE) && (accessed_bytes != ctg_store.contig.dset_size))
+ || (io_info->op_type != H5D_IO_OP_WRITE))
+ entire_chunk = FALSE;
+
+ /* Lock the chunk into the cache */
+ if(NULL == (chunk = H5D_istore_lock(io_info, &udata, entire_chunk, &idx_hint)))
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to read raw data chunk")
+
+ /* Set up the storage buffer information for this chunk */
+ cpt_store.compact.buf = chunk;
+
+ /* Point I/O info at contiguous I/O info for this chunk */
+ chk_io_info = &cpt_io_info;
+ } /* end if */
+ else {
+ /* Set up the storage address information for this chunk */
+ ctg_store.contig.dset_addr = caddr;
+
+ /* No chunk cached */
+ chunk = NULL;
+
+ /* Point I/O info at temporary I/O info for this chunk */
+ chk_io_info = &ctg_io_info;
+ } /* end else */
+
+ if(io_info->op_type == H5D_IO_OP_WRITE) {
+ if((io_info->io_ops.single_write)(chk_io_info, type_info,
+ (hsize_t)chunk_info->chunk_points, chunk_info->fspace, chunk_info->mspace) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "optimized write failed")
+ } /* end if */
+ else {
+ if((io_info->io_ops.single_read)(chk_io_info, type_info,
+ (hsize_t)chunk_info->chunk_points, chunk_info->fspace, chunk_info->mspace) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "optimized read failed")
+ } /* end else */
+
+ /* Release the cache lock on the chunk. */
+ if(chunk && H5D_istore_unlock(io_info, (io_info->op_type == H5D_IO_OP_WRITE), idx_hint, chunk, accessed_bytes) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to unlock raw data chunk")
+ } /* end if */
+#else /* !defined(H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS) || !defined(H5_MPI_SPECIAL_COLLECTIVE_IO_WORKS) */
+ /* Set the file & memory dataspaces */
+ if(chunk_info) {
+ fspace = chunk_info->fspace;
+ mspace = chunk_info->mspace;
+ } /* end if */
else {
- if(H5D_inter_collective_io(io_info,NULL,NULL,
- chunk_addr[i],buf,do_write )<0)
- HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL,"couldn't finish shared collective MPI-IO");
- }
+ fspace = mspace = NULL;
+ } /* end else */
+
+ /* Using independent I/O with file setview.*/
+ if(last_coll_opt_mode != H5FD_MPIO_INDIVIDUAL_IO) {
+ if(H5D_ioinfo_coll_opt_mode(io_info, dx_plist, H5FD_MPIO_INDIVIDUAL_IO) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't switch to individual I/O")
+ last_coll_opt_mode = H5FD_MPIO_INDIVIDUAL_IO;
+ } /* end if */
+ /* Initialize temporary contiguous storage address */
+ ctg_store.contig.dset_addr = chunk_addr[u];
+
+ /* Perform the I/O */
+ if(H5D_inter_collective_io(&ctg_io_info, type_info, fspace, mspace) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL, "couldn't finish shared collective MPI-IO")
#ifdef H5D_DEBUG
if(H5DEBUG(D))
HDfprintf(H5DEBUG(D),"after inter collective IO\n");
#endif
-#endif
- last_io_mode_coll = FALSE;
- }
- }
- if(!last_io_mode_coll)
- /* Switch back to collective I/O */
- if(H5D_ioinfo_make_coll(io_info) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't switch to collective I/O")
+#endif /* !defined(H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS) || !defined(H5_MPI_SPECIAL_COLLECTIVE_IO_WORKS) */
+ } /* end else */
+ } /* end for */
+
done:
- HDfree(chunk_io_option);
- HDfree(chunk_addr);
+ if(chunk_io_option)
+ H5MM_xfree(chunk_io_option);
+ if(chunk_addr)
+ H5MM_xfree(chunk_addr);
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D_multi_chunk_collective_io */
@@ -1257,90 +1297,105 @@ done:
* non-contiguous(or with holes) storage efficiently.
* Under this case, the one independent IO call may consist of
* many small disk IOs. So we may use independent IO with derived datatype
- to replace the independent IO when we find this chunk is not good to
- do collective IO. However, according to our performance study,
- this approach may not overcome the overhead caused by MPI gather/scatter.
- So we decide to leave the original collective IO per chunk approach as
- an option for users. NO MPI gather/scatter calls are used.
- HDF5 will try to collective IO if possible.
- If users choose to use
- H5Pset_dxpl_mpio_chunk_opt(dxpl_id,H5FD_MPIO_OPT_MULTI_IO),
- this function will be called.
- The HDF5 library won't do any IO management but leave it to MPI-IO to figure
- out.
+ * to replace the independent IO when we find this chunk is not good to
+ * do collective IO. However, according to our performance study,
+ * this approach may not overcome the overhead caused by MPI gather/scatter.
+ * So we decide to leave the original collective IO per chunk approach as
+ * an option for users. NO MPI gather/scatter calls are used.
+ * HDF5 will try to collective IO if possible.
+ * If users choose to use
+ * H5Pset_dxpl_mpio_chunk_opt(dxpl_id,H5FD_MPIO_OPT_MULTI_IO),
+ * this function will be called.
+ * The HDF5 library won't do any IO management but leave it to MPI-IO to figure
+ * out.
*
* Return: Non-negative on success/Negative on failure
*
- * Programmer:
- *
- * Modifications:
+ * Programmer: Muqun Yang
+ * Monday, Feb. 13th, 2006
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5D_multi_chunk_collective_io_no_opt(H5D_io_info_t *io_info,H5D_chunk_map_t *fm,const void *buf, hbool_t do_write)
+H5D_multi_chunk_collective_io_no_opt(H5D_io_info_t *io_info,
+ const H5D_type_info_t *type_info, H5D_chunk_map_t *fm, H5P_genplist_t *dx_plist)
{
- int count_chunk,min_num_chunk;
- haddr_t chunk_addr;
- H5SL_node_t *chunk_node; /* Current node in chunk skip list */
- H5D_storage_t store; /* union of EFL and chunk pointer in file space */
- H5D_chunk_info_t *chunk_info; /* chunk information */
- hbool_t make_ind, make_coll; /* Flags to indicate that the MPI mode should change */
-
- void *chunk = NULL; /* Pointer to the data chunk in cache */
- H5D_t *dataset=io_info->dset;/* Local pointer to dataset info */
- H5D_istore_ud1_t udata; /*B-tree pass-through */
- size_t accessed_bytes; /*total accessed size in a chunk */
- unsigned idx_hint=0; /* Cache index hint */
- hbool_t dirty = TRUE; /* Flag for cache flushing */
- hbool_t relax=TRUE; /* Whether whole chunk is selected */
- herr_t ret_value = SUCCEED;
-
-#ifdef H5Dmpio_DEBUG
- int mpi_rank;
-#endif
+ H5D_t *dataset = io_info->dset;/* Local pointer to dataset info */
+ H5SL_node_t *chunk_node; /* Current node in chunk skip list */
+ H5D_io_info_t ctg_io_info; /* Contiguous I/O info object */
+ H5D_storage_t ctg_store; /* Chunk storage information as contiguous dataset */
+ H5D_io_info_t cpt_io_info; /* Compact I/O info object */
+ H5D_storage_t cpt_store; /* Chunk storage information as compact dataset */
+ hbool_t cpt_dirty; /* Temporary placeholder for compact storage "dirty" flag */
+ int min_chunk = -1; /* Minimum # of chunks all processes will operate on */
+ int count_chunk; /* How many chunks have we operated on? */
+ H5D_storage_t store; /* union of EFL and chunk pointer in file space */
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_multi_chunk_collective_io_no_opt)
- FUNC_ENTER_NOAPI_NOINIT(H5D_multi_chunk_collective_io_no_opt)
#ifdef H5D_DEBUG
- if(H5DEBUG(D)){
+if(H5DEBUG(D)) {
+ int mpi_rank;
+
mpi_rank = H5F_mpi_get_rank(io_info->dset->oloc.file);
- HDfprintf(H5DEBUG(D),"coming to multi_chunk_collective_io_no_opt\n");
- }
+ HDfprintf(H5DEBUG(D), "coming to multi_chunk_collective_io_no_opt\n");
+}
#endif
- if(H5D_mpio_get_min_chunk(io_info,fm,&min_num_chunk)<0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get minimum number of chunk");
- count_chunk = 0;
-
- /* Get first node in chunk skip list */
- chunk_node=H5SL_first(fm->sel_chunks);
-
- /* Iterate through chunks to be operated on */
- while(chunk_node) {
- H5D_chunk_info_t *chunk_info; /* chunk information */
- hbool_t make_ind, make_coll; /* Flags to indicate that the MPI mode should change */
-
- /* Get the actual chunk information from the skip list node */
- chunk_info=H5SL_item(chunk_node);
-
- /* Set dataset storage for I/O info */
- io_info->store=&store;
-
- /* Pass in chunk's coordinates in a union. */
- store.chunk.offset = chunk_info->coords;
- store.chunk.index = chunk_info->index;
-
- /* Reset flags for changing parallel I/O mode */
- make_ind = make_coll = FALSE;
-
- count_chunk++;
- /* If the number of chunk is greater than minimum number of chunk,
- Do independent read */
- if(count_chunk > min_num_chunk) {
- /* Switch to independent I/O (permanently) */
- make_ind = TRUE;
- }
+ /* Set up contiguous I/O info object */
+ HDmemcpy(&ctg_io_info, io_info, sizeof(ctg_io_info));
+ ctg_io_info.store = &ctg_store;
+ ctg_io_info.layout_ops = *H5D_LOPS_CONTIG;
+
+ /* Initialize temporary contiguous storage info */
+ ctg_store.contig.dset_size = (hsize_t)io_info->dset->shared->layout.u.chunk.size;
+
+ /* Set up compact I/O info object */
+ HDmemcpy(&cpt_io_info, io_info, sizeof(cpt_io_info));
+ cpt_io_info.store = &cpt_store;
+ cpt_io_info.layout_ops = *H5D_LOPS_COMPACT;
+
+ /* Initialize temporary compact storage info */
+ cpt_store.compact.dirty = &cpt_dirty;
+
+ /* Set dataset storage for I/O info */
+ io_info->store = &store;
+
+ /* Get the min. # of chunks */
+ if(H5D_mpio_get_min_chunk(io_info, fm, &min_chunk) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get minimum number of chunk")
+ HDassert(min_chunk >= 0);
+
+ /* Get first node in chunk skip list */
+ chunk_node = H5SL_first(fm->sel_chunks);
+ count_chunk = 0;
+
+ /* Iterate through chunks to be operated on */
+ while(chunk_node) {
+ H5D_chunk_info_t *chunk_info; /* chunk information */
+ haddr_t chunk_addr; /* Address of chunk in file */
+ H5D_istore_ud1_t udata; /* B-tree pass-through */
+ hbool_t make_ind, make_coll; /* Flags to indicate that the MPI mode should change */
+ /* Get the actual chunk information from the skip list node */
+ chunk_info = H5SL_item(chunk_node);
+
+ /* Pass in chunk's coordinates in a union. */
+ store.chunk.offset = chunk_info->coords;
+ store.chunk.index = chunk_info->index;
+
+ /* Reset flags for changing parallel I/O mode */
+ make_ind = make_coll = FALSE;
+
+ count_chunk++;
+
+ /* If the number of chunk is greater than minimum number of chunk,
+ * Do independent read.
+ */
+ if(count_chunk > min_chunk)
+ /* Switch to independent I/O (permanently) */
+ make_ind = TRUE;
#ifndef H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS
/* This case needs to be improved to check if the selected space
is regular. If all selections are regular, collective IO can still be done.
@@ -1349,67 +1404,92 @@ H5D_multi_chunk_collective_io_no_opt(H5D_io_info_t *io_info,H5D_chunk_map_t *fm,
we turn off this optimization but leave the following code
for future optimization. Otherwise, the following else {} doesn't make sense.
KY 2006/8/4/ */
- else {
- /* Switch to independent I/O (temporarily) */
- make_ind = TRUE;
- make_coll = TRUE;
- } /* end else */
+ else {
+ /* Switch to independent I/O (temporarily) */
+ make_ind = TRUE;
+ make_coll = TRUE;
+ } /* end else */
#endif /* H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS */
+ /* Retrieve the chunk's address */
+ if(HADDR_UNDEF == (chunk_addr = H5D_istore_get_addr(io_info, &udata)))
+ HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL,"couldn't get chunk info from skipped list")
+
+ /* Independent I/O */
+ if(make_ind) {
+ void *chunk; /* Pointer to the data chunk in cache */
+ H5D_io_info_t *chk_io_info; /* Pointer to I/O info object for this chunk */
+ size_t accessed_bytes = 0; /* Total accessed size in a chunk */
+ unsigned idx_hint = 0; /* Cache index hint */
+
/* Switch to independent I/O */
- if(make_ind)
- if(H5D_ioinfo_make_ind(io_info) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't switch to independent I/O")
+ if(H5D_ioinfo_xfer_mode(io_info, dx_plist, H5FD_MPIO_INDEPENDENT) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't switch to independent I/O")
- if(HADDR_UNDEF==(chunk_addr = H5D_istore_get_addr(io_info, &udata)))
- HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL,"couldn't get chunk info from skipped list");
+ /* Load the chunk into cache and lock it. */
+ if(H5D_chunk_cacheable(io_info, chunk_addr)) {
+ hbool_t entire_chunk = TRUE; /* Whether whole chunk is selected */
- if(make_ind) {/*independent I/O */
- /* Load the chunk into cache. But if the whole chunk is written,
- * simply allocate space instead of load the chunk. */
- if(H5D_istore_if_load(io_info, chunk_addr)) {
- accessed_bytes = chunk_info->chunk_points * H5T_get_size(dataset->shared->type);
- if((do_write && (accessed_bytes != dataset->shared->layout.u.chunk.size)) || !do_write)
- relax=FALSE;
-
- if(NULL == (chunk = H5D_istore_lock(io_info, &udata, relax, &idx_hint)))
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to read raw data chunk")
- } else
- chunk = NULL;
-
- if(do_write) {
- if((io_info->ops.write)(io_info,
- chunk_info->chunk_points,H5T_get_size(io_info->dset->shared->type),
- chunk_info->fspace,chunk_info->mspace, chunk_addr, chunk, buf) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "optimized write failed")
- } else {
- if((io_info->ops.read)(io_info,
- chunk_info->chunk_points,H5T_get_size(io_info->dset->shared->type),
- chunk_info->fspace,chunk_info->mspace, chunk_addr, chunk, buf) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "optimized read failed")
- }
+ /* Compute # of bytes accessed in chunk */
+ accessed_bytes = chunk_info->chunk_points * type_info->src_type_size;
- /* Release the cache lock on the chunk. */
- if(chunk) {
- if(!do_write)
- dirty = FALSE;
+ /* Determine if we will access all the data in the chunk */
+ if(((io_info->op_type == H5D_IO_OP_WRITE) && (accessed_bytes != ctg_store.contig.dset_size))
+ || (io_info->op_type != H5D_IO_OP_WRITE))
+ entire_chunk = FALSE;
+
+ /* Lock the chunk into the cache */
+ if(NULL == (chunk = H5D_istore_lock(io_info, &udata, entire_chunk, &idx_hint)))
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to read raw data chunk")
- if(H5D_istore_unlock(io_info, dirty, idx_hint, chunk, accessed_bytes) < 0)
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to unlock raw data chunk")
- } /* end if */
+ /* Set up the storage buffer information for this chunk */
+ cpt_store.compact.buf = chunk;
+
+ /* Point I/O info at contiguous I/O info for this chunk */
+ chk_io_info = &cpt_io_info;
} /* end if */
- else { /*collective I/O */
- if(H5D_inter_collective_io(io_info,chunk_info->fspace,chunk_info->mspace,
- chunk_addr,buf,do_write ) < 0)
- HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL,"couldn't finish shared collective MPI-IO");
- }
-
- if(make_coll)
- if(H5D_ioinfo_make_coll(io_info) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't switch to independent I/O")
- /* Get the next chunk node in the skip list */
- chunk_node=H5SL_next(chunk_node);
- } /* end while */
+ else {
+ /* Set up the storage address information for this chunk */
+ ctg_store.contig.dset_addr = chunk_addr;
+
+ /* No chunk cached */
+ chunk = NULL;
+
+ /* Point I/O info at temporary I/O info for this chunk */
+ chk_io_info = &ctg_io_info;
+ } /* end else */
+
+ if(io_info->op_type == H5D_IO_OP_WRITE) {
+ if((io_info->io_ops.single_write)(chk_io_info, type_info,
+ (hsize_t)chunk_info->chunk_points, chunk_info->fspace, chunk_info->mspace) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "optimized write failed")
+ } /* end if */
+ else {
+ if((io_info->io_ops.single_read)(chk_io_info, type_info,
+ (hsize_t)chunk_info->chunk_points, chunk_info->fspace, chunk_info->mspace) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "optimized read failed")
+ } /* end ese */
+
+ /* Release the cache lock on the chunk. */
+ if(chunk)
+ if(H5D_istore_unlock(io_info, (io_info->op_type == H5D_IO_OP_WRITE), idx_hint, chunk, accessed_bytes) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to unlock raw data chunk")
+ } /* end if */
+ else { /*collective I/O */
+ /* Set up the storage address information for this chunk */
+ ctg_store.contig.dset_addr = chunk_addr;
+
+ if(H5D_inter_collective_io(&ctg_io_info, type_info, chunk_info->fspace, chunk_info->mspace) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL,"couldn't finish shared collective MPI-IO")
+ } /* end else */
+
+ if(make_coll)
+ if(H5D_ioinfo_xfer_mode(io_info, dx_plist, H5FD_MPIO_COLLECTIVE) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't switch to independent I/O")
+
+ /* Get the next chunk node in the skip list */
+ chunk_node = H5SL_next(chunk_node);
+ } /* end while */
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -1420,303 +1500,266 @@ done:
* Function: H5D_inter_collective_io
*
* Purpose: Routine for the shared part of collective IO between multiple chunk
- collective IO and contiguous collective IO
-
+ * collective IO and contiguous collective IO
*
* Return: Non-negative on success/Negative on failure
*
- * Programmer:
- *
- * Modifications:
+ * Programmer: Muqun Yang
+ * Monday, Feb. 13th, 2006
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5D_inter_collective_io(H5D_io_info_t *io_info,const H5S_t *file_space,const H5S_t *mem_space,
- haddr_t addr, const void *buf, hbool_t do_write )
+H5D_inter_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
+ const H5S_t *file_space, const H5S_t *mem_space)
{
+ size_t mpi_buf_count; /* # of MPI types */
+ hbool_t mbt_is_derived = FALSE;
+ hbool_t mft_is_derived = FALSE;
+ MPI_Datatype mpi_file_type, mpi_buf_type;
+ int mpi_code; /* MPI return code */
+ herr_t ret_value = SUCCEED; /* return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_inter_collective_io)
+
+ if((file_space != NULL) && (mem_space != NULL)) {
+ hsize_t mpi_buf_offset, mpi_file_offset; /* Offset within dataset where selection (ie. MPI type) begins */
+ size_t mpi_file_count; /* Number of file "objects" to transfer */
- size_t mpi_buf_count, mpi_file_count; /* Number of "objects" to transfer */
- MPI_Datatype mpi_file_type,mpi_buf_type;
- hsize_t mpi_buf_offset, mpi_file_offset; /* Offset within dataset where selection (ie. MPI type) begins */
- hbool_t mbt_is_derived=0, /* Whether the buffer (memory) type is derived and needs to be free'd */
- mft_is_derived=0; /* Whether the file type is derived and needs to be free'd */
- H5D_common_coll_info_t coll_info;
- herr_t ret_value = SUCCEED; /* return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5D_inter_collective_io)
- if((file_space!=NULL) && (mem_space != NULL)) {
- /*Obtain disk and memory MPI derived datatype */
- if(H5S_mpio_space_type(file_space,H5T_get_size(io_info->dset->shared->type),
- &mpi_file_type,&mpi_file_count,&mpi_file_offset,&mft_is_derived)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL,"couldn't create MPI file type");
-
- if(H5S_mpio_space_type(mem_space,H5T_get_size(io_info->dset->shared->type),
- &mpi_buf_type,&mpi_buf_count,&mpi_buf_offset,&mbt_is_derived)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL,"couldn't create MPI buffer type");
-
- }
- else {
- /* For non-selection, participate with a none MPI derived datatype, the count is 0. */
- mpi_buf_type = MPI_BYTE;
- mpi_file_type = MPI_BYTE;
- mpi_file_count = 0;
- mpi_buf_count = 0;
- }
-
- coll_info.mbt_is_derived = mbt_is_derived;
- coll_info.mft_is_derived = mft_is_derived;
- coll_info.mpi_buf_count = mpi_buf_count;
- coll_info.chunk_addr = addr;
+ /* Obtain disk and memory MPI derived datatype */
+ if(H5S_mpio_space_type(file_space, type_info->src_type_size,
+ &mpi_file_type, &mpi_file_count, &mpi_file_offset, &mft_is_derived) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "couldn't create MPI file type")
+ if(H5S_mpio_space_type(mem_space, type_info->src_type_size,
+ &mpi_buf_type, &mpi_buf_count, &mpi_buf_offset, &mbt_is_derived) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "couldn't create MPI buffer type")
+ } /* end if */
+ else {
+ /* For non-selection, participate with a none MPI derived datatype, the count is 0. */
+ mpi_buf_type = MPI_BYTE;
+ mpi_file_type = MPI_BYTE;
+ mpi_buf_count = (size_t)0;
+ mbt_is_derived = FALSE;
+ mft_is_derived = FALSE;
+ } /* end else */
#ifdef H5D_DEBUG
- if(H5DEBUG(D))
- HDfprintf(H5DEBUG(D),"before final collective IO \n");
+if(H5DEBUG(D))
+ HDfprintf(H5DEBUG(D),"before final collective IO \n");
#endif
- if(H5D_final_collective_io(io_info,&mpi_file_type,&mpi_buf_type,&coll_info,buf,do_write)<0)
- HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL,"couldn't finish collective MPI-IO");
- done:
+ /* Perform final collective I/O operation */
+ if(H5D_final_collective_io(io_info, type_info, mpi_buf_count, &mpi_file_type, &mpi_buf_type) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL, "couldn't finish collective MPI-IO")
+
+done:
+ /* Free the MPI buf and file types, if they were derived */
+ if(mbt_is_derived && MPI_SUCCESS != (mpi_code = MPI_Type_free(&mpi_buf_type)))
+ HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code)
+ if(mft_is_derived && MPI_SUCCESS != (mpi_code = MPI_Type_free(&mpi_file_type)))
+ HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code)
+
#ifdef H5D_DEBUG
- if(H5DEBUG(D))
+if(H5DEBUG(D))
HDfprintf(H5DEBUG(D),"before leaving inter_collective_io ret_value = %d\n",ret_value);
#endif
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_inter_collective_io */
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_inter_collective_io() */
/*-------------------------------------------------------------------------
* Function: H5D_final_collective_io
*
* Purpose: Routine for the common part of collective IO with different storages.
-
*
* Return: Non-negative on success/Negative on failure
*
- * Programmer:
- *
- * Modifications:
+ * Programmer: Muqun Yang
+ * Monday, Feb. 13th, 2006
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5D_final_collective_io(H5D_io_info_t *io_info,MPI_Datatype*mpi_file_type,MPI_Datatype *mpi_buf_type,
- H5D_common_coll_info_t* coll_info, const void *buf, hbool_t do_write)
+H5D_final_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
+ size_t mpi_buf_count, MPI_Datatype *mpi_file_type, MPI_Datatype *mpi_buf_type)
{
-
-
- int mpi_code; /* MPI return code */
- hbool_t plist_is_setup=0; /* Whether the dxpl has been customized */
- herr_t ret_value = SUCCEED;
-
+ int mpi_code; /* MPI return code */
+ hbool_t plist_is_setup = FALSE; /* Whether the dxpl has been customized */
+ herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI_NOINIT(H5D_final_collective_io)
- /*
- * Pass buf type, file type to the file driver.
- */
-
- if(H5FD_mpi_setup_collective(io_info->dxpl_id, *mpi_buf_type, *mpi_file_type)<0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set MPI-I/O properties");
+ /* Pass buf type, file type to the file driver. */
+ if(H5FD_mpi_setup_collective(io_info->dxpl_id, *mpi_buf_type, *mpi_file_type) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set MPI-I/O properties")
+ plist_is_setup = TRUE;
- plist_is_setup=1;
-#ifdef H5D_DEBUG
- if(H5DEBUG(D)){
- HDfprintf(H5DEBUG(D),"chunk addr %Hu\n",coll_info->chunk_addr);
- HDfprintf(H5DEBUG(D),"mpi_buf_count %d\n",coll_info->mpi_buf_count);
- }
-
-#endif
-
- if(do_write) {
- if((io_info->ops.write)(io_info,
- coll_info->mpi_buf_count,0,NULL,NULL,coll_info->chunk_addr,
- NULL, buf) < 0)
+ if(io_info->op_type == H5D_IO_OP_WRITE) {
+ if((io_info->io_ops.single_write)(io_info, type_info,
+ (hsize_t)mpi_buf_count, NULL, NULL) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "optimized write failed")
- }
+ } /* end if */
else {
- if((io_info->ops.read)(io_info,
- coll_info->mpi_buf_count,0,NULL,NULL,coll_info->chunk_addr,
- NULL, buf) < 0)
+ if((io_info->io_ops.single_read)(io_info, type_info,
+ (hsize_t)mpi_buf_count, NULL, NULL) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "optimized read failed")
- }
+ } /* end else */
done:
- /* Reset the dxpl settings */
- if(plist_is_setup) {
- if(H5FD_mpi_teardown_collective(io_info->dxpl_id)<0)
- HDONE_ERROR(H5E_DATASPACE, H5E_CANTFREE, FAIL, "unable to reset dxpl values");
- } /* end if */
-
- /* free the MPI buf and file types */
- if (coll_info->mbt_is_derived) {
- if (MPI_SUCCESS != (mpi_code= MPI_Type_free( mpi_buf_type )))
- HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code);
- }
- if (coll_info->mft_is_derived) {
- if (MPI_SUCCESS != (mpi_code= MPI_Type_free( mpi_file_type )))
- HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code);
- }
+ /* Reset the dxpl settings */
+ if(plist_is_setup)
+ if(H5FD_mpi_teardown_collective(io_info->dxpl_id) < 0)
+ HDONE_ERROR(H5E_DATASPACE, H5E_CANTFREE, FAIL, "unable to reset dxpl values")
+
#ifdef H5D_DEBUG
- if(H5DEBUG(D))
+if(H5DEBUG(D))
HDfprintf(H5DEBUG(D),"ret_value before leaving final_collective_io=%d\n",ret_value);
#endif
-
FUNC_LEAVE_NOAPI(ret_value)
-}/* end H5D_final_collective_io */
+} /* end H5D_final_collective_io */
/*-------------------------------------------------------------------------
* Function: H5D_sort_chunk
*
* Purpose: Routine to sort chunks in increasing order of chunk address
- Each chunk address is also obtained.
-
- Description:
- For most cases, the chunk address has already been sorted in increasing order.
- The special sorting flag is used to optimize this common case.
- quick sort is used for necessary sorting.
-
- Parameters:
- Input: H5D_io_info_t* io_info,
- H5D_chunk_map_t *fm(global chunk map struct)
- Input/Output: H5D_chunk_addr_info_t chunk_addr_info_array[] : array to store chunk address and information
- many_chunk_opt : flag to optimize the way to obtain chunk addresses
- for many chunks
+ * Each chunk address is also obtained.
*
- * Return: Non-negative on success/Negative on failure
+ * Description:
+ * For most cases, the chunk address has already been sorted in increasing order.
+ * The special sorting flag is used to optimize this common case.
+ * quick sort is used for necessary sorting.
*
- * Programmer:
+ * Parameters:
+ * Input: H5D_io_info_t* io_info,
+ * H5D_chunk_map_t *fm(global chunk map struct)
+ * Input/Output: H5D_chunk_addr_info_t chunk_addr_info_array[] : array to store chunk address and information
+ * many_chunk_opt : flag to optimize the way to obtain chunk addresses
+ * for many chunks
*
- * Modifications:
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Muqun Yang
+ * Monday, Feb. 13th, 2006
*
*-------------------------------------------------------------------------
*/
-
static herr_t
-H5D_sort_chunk(H5D_io_info_t * io_info,
- H5D_chunk_map_t *fm,
- H5D_chunk_addr_info_t chunk_addr_info_array[],
- int many_chunk_opt)
+H5D_sort_chunk(H5D_io_info_t *io_info, const H5D_chunk_map_t *fm,
+ H5D_chunk_addr_info_t chunk_addr_info_array[], int sum_chunk)
{
-
-
- H5SL_node_t *chunk_node; /* Current node in chunk skip list */
+ H5SL_node_t *chunk_node; /* Current node in chunk skip list */
H5D_chunk_info_t *chunk_info; /* Current chunking info. of this node. */
- haddr_t chunk_addr; /* Current chunking address of this node */
- haddr_t *total_chunk_addr_array=NULL; /* The array of chunk address for the total number of chunk */
- int i,mpi_code;
- int total_chunks;
- size_t num_chunks;
- int mpi_type_cleanup = 0;
- int tchunk_addr_cleanup = 0;
- MPI_Datatype chunk_addrtype;
- H5D_storage_t store; /*union of EFL and chunk pointer in file space */
- hbool_t do_sort = FALSE;
- herr_t ret_value = SUCCEED; /*return value */
+ haddr_t chunk_addr; /* Current chunking address of this node */
+ haddr_t *total_chunk_addr_array = NULL; /* The array of chunk address for the total number of chunk */
+ H5D_storage_t store; /*union of EFL and chunk pointer in file space */
+ hbool_t do_sort = FALSE; /* Whether the addresses need to be sorted */
+ int bsearch_coll_chunk_threshold;
+ int many_chunk_opt = H5D_OBTAIN_ONE_CHUNK_ADDR_IND;
+ int mpi_size; /* Number of MPI processes */
+ int mpi_code; /* MPI return code */
+ int i; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5D_sort_chunk)
- num_chunks = H5SL_count(fm->sel_chunks);
+ /* Retrieve # of MPI processes */
+ if((mpi_size = H5F_mpi_get_size(io_info->dset->oloc.file)) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_MPI, FAIL, "unable to obtain mpi size")
+
+ /* Calculate the actual threshold to obtain all chunk addresses collectively
+ * The bigger this number is, the more possible the use of obtaining chunk
+ * address collectively.
+ */
+ /* For non-optimization one-link IO, actual bsearch threshold is always
+ * 0, we would always want to obtain the chunk addresses individually
+ * for each process.
+ */
+ bsearch_coll_chunk_threshold = (sum_chunk * 100) / ((int)fm->total_chunks * mpi_size);
+ if((bsearch_coll_chunk_threshold > H5D_ALL_CHUNK_ADDR_THRES_COL)
+ && ((sum_chunk / mpi_size) >= H5D_ALL_CHUNK_ADDR_THRES_COL_NUM))
+ many_chunk_opt = H5D_OBTAIN_ALL_CHUNK_ADDR_COL;
+
#ifdef H5D_DEBUG
- if(H5DEBUG(D))
- HDfprintf(H5DEBUG(D),"many_chunk_opt= %d\n",many_chunk_opt);
+if(H5DEBUG(D))
+ HDfprintf(H5DEBUG(D), "many_chunk_opt= %d\n", many_chunk_opt);
#endif
/* If we need to optimize the way to obtain the chunk address */
- if(many_chunk_opt != H5D_OBTAIN_ONE_CHUNK_ADDR_IND){
+ if(many_chunk_opt != H5D_OBTAIN_ONE_CHUNK_ADDR_IND) {
+ int mpi_rank;
- int mpi_rank, root;
- total_chunks = (int)fm->total_chunks;
- total_chunk_addr_array = H5MM_malloc(sizeof(haddr_t)*total_chunks);
- tchunk_addr_cleanup = 1;
#ifdef H5D_DEBUG
- if(H5DEBUG(D))
- HDfprintf(H5DEBUG(D),"Coming inside H5D_OBTAIN_ALL_CHUNK_ADDR_COL\n");
+if(H5DEBUG(D))
+ HDfprintf(H5DEBUG(D), "Coming inside H5D_OBTAIN_ALL_CHUNK_ADDR_COL\n");
#endif
- root = 0;
- if((mpi_rank = H5F_mpi_get_rank(io_info->dset->oloc.file))<0)
- HGOTO_ERROR (H5E_IO, H5E_MPI, FAIL, "unable to obtain mpi rank");
-
- /*Create received MPI derived datatype */
- if(MPI_SUCCESS !=(mpi_code = MPI_Type_contiguous((int)(sizeof(haddr_t)*total_chunks), MPI_BYTE, &chunk_addrtype)))
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_contiguous failed", mpi_code);
- if(MPI_SUCCESS !=(mpi_code = MPI_Type_commit(&chunk_addrtype)))
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code);
-
- mpi_type_cleanup = 1;
-
- if(mpi_rank == root) {
- if(H5D_istore_chunkmap(io_info, total_chunk_addr_array, fm->down_chunks)<0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get chunk address");
- }
+ /* Allocate array for chunk addresses */
+ if(NULL == (total_chunk_addr_array = H5MM_malloc(sizeof(haddr_t) * (size_t)fm->total_chunks)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate memory chunk address array")
+
+ /* Retrieve all the chunk addresses with process 0 */
+ if((mpi_rank = H5F_mpi_get_rank(io_info->dset->oloc.file)) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_MPI, FAIL, "unable to obtain mpi rank")
+ if(mpi_rank == 0) {
+ if(H5D_istore_chunkmap(io_info, total_chunk_addr_array, fm->down_chunks) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get chunk address")
+ } /* end if */
+
/* Broadcasting the MPI_IO option info. and chunk address info. */
- if(MPI_SUCCESS !=(mpi_code = MPI_Bcast(total_chunk_addr_array,1,chunk_addrtype,root,io_info->comm)))
- HMPI_GOTO_ERROR(FAIL, "MPI_BCast failed", mpi_code);
+ if(MPI_SUCCESS != (mpi_code = MPI_Bcast(total_chunk_addr_array, (int)(sizeof(haddr_t) * fm->total_chunks), MPI_BYTE, (int)0, io_info->comm)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_BCast failed", mpi_code)
} /* end if */
- /* Get first node in chunk skip list */
- if(NULL ==(chunk_node = H5SL_first(fm->sel_chunks)))
- HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL,"couldn't get chunk node from skipped list");
/* Set dataset storage for I/O info */
io_info->store = &store;
- if(NULL ==(chunk_info = H5SL_item(chunk_node)))
- HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL,"couldn't get chunk info from skipped list");
- store.chunk.offset = chunk_info->coords;
- store.chunk.index = chunk_info->index;
+
+ /* Start at first node in chunk skip list */
i = 0;
- if(many_chunk_opt == H5D_OBTAIN_ONE_CHUNK_ADDR_IND){
- if(HADDR_UNDEF==(chunk_addr = H5D_istore_get_addr(io_info,NULL)))
- HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL,"couldn't get chunk info from skipped list");
+ if(NULL == (chunk_node = H5SL_first(fm->sel_chunks)))
+ HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL,"couldn't get chunk node from skipped list")
-#ifdef H5D_DEBUG
- if(H5DEBUG(D))
- HDfprintf(H5DEBUG(D),"coming to obtain each chunk address individually \n");
-#endif
- }
- else
- chunk_addr = total_chunk_addr_array[chunk_info->index];
+ /* Iterate over all chunks for this process */
+ while(chunk_node) {
+ if(NULL == (chunk_info = H5SL_item(chunk_node)))
+ HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL,"couldn't get chunk info from skipped list")
+
+ if(many_chunk_opt == H5D_OBTAIN_ONE_CHUNK_ADDR_IND) {
+ store.chunk.offset = chunk_info->coords;
+ store.chunk.index = chunk_info->index;
+ if(HADDR_UNDEF == (chunk_addr = H5D_istore_get_addr(io_info, NULL)))
+ HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL, "couldn't get chunk info from skipped list")
+ } /* end if */
+ else
+ chunk_addr = total_chunk_addr_array[chunk_info->index];
- chunk_addr_info_array[i].chunk_addr = chunk_addr;
- chunk_addr_info_array[i].chunk_info = *chunk_info;
+ /* Check if chunk addresses are not in increasing order in the file */
+ if(i > 0 && chunk_addr < chunk_addr_info_array[i - 1].chunk_addr)
+ do_sort = TRUE;
- chunk_node = H5SL_next(chunk_node);
+ /* Set the address & info for this chunk */
+ chunk_addr_info_array[i].chunk_addr = chunk_addr;
+ chunk_addr_info_array[i].chunk_info = *chunk_info;
- while(chunk_node) {
+ /* Advance to next chunk in list */
+ i++;
+ chunk_node = H5SL_next(chunk_node);
+ } /* end while */
- chunk_info = H5SL_item(chunk_node);
- store.chunk.offset = chunk_info->coords;
- store.chunk.index = chunk_info->index;
-
- if(many_chunk_opt == H5D_OBTAIN_ONE_CHUNK_ADDR_IND){
- if(HADDR_UNDEF==(chunk_addr = H5D_istore_get_addr(io_info,NULL)))
- HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL,"couldn't get chunk info from skipped list");
- }
- else
- chunk_addr = total_chunk_addr_array[chunk_info->index];
-
- if(chunk_addr < chunk_addr_info_array[i].chunk_addr) do_sort = TRUE;
- chunk_addr_info_array[i+1].chunk_addr = chunk_addr;
- chunk_addr_info_array[i+1].chunk_info =*chunk_info;
- i++;
- chunk_node = H5SL_next(chunk_node);
- }
#ifdef H5D_DEBUG
- if(H5DEBUG(D))
- HDfprintf(H5DEBUG(D),"before Qsort\n");
+if(H5DEBUG(D))
+ HDfprintf(H5DEBUG(D), "before Qsort\n");
#endif
- if(do_sort)
- HDqsort(chunk_addr_info_array,num_chunks,sizeof(chunk_addr_info_array),H5D_cmp_chunk_addr);
+ if(do_sort) {
+ size_t num_chunks = H5SL_count(fm->sel_chunks);
+
+ HDqsort(chunk_addr_info_array, num_chunks, sizeof(chunk_addr_info_array[0]), H5D_cmp_chunk_addr);
+ } /* end if */
done:
+ if(total_chunk_addr_array)
+ H5MM_xfree(total_chunk_addr_array);
- if(tchunk_addr_cleanup)
- HDfree(total_chunk_addr_array);
- if(mpi_type_cleanup) {
- if (MPI_SUCCESS != (mpi_code= MPI_Type_free( &chunk_addrtype )))
- HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code);
- }
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D_sort_chunk() */
@@ -1725,310 +1768,244 @@ done:
* Function: H5D_obtain_mpio_mode
*
* Purpose: Routine to obtain each io mode(collective,independent or none) for each chunk;
- Each chunk address is also obtained.
-
- Description:
-
- 1) Each process provides two piece of information for all chunks having selection
- a) chunk index
- b) wheather this chunk is regular(for MPI derived datatype not working case)
-
- 2) Gather all the information to the root process
-
- 3) Root process will do the following:
- a) Obtain chunk addresses for all chunks in this data space
- b) With the consideration of the user option, calculate IO mode for each chunk
- c) Build MPI derived datatype to combine "chunk address" and "assign_io" information
- in order to do MPI Bcast only once
- d) MPI Bcast the IO mode and chunk address information for each chunk.
- 4) Each process then retrieves IO mode and chunk address information to assign_io_mode and chunk_addr.
-
- Parameters:
-
- Input: H5D_io_info_t* io_info,
- H5D_chunk_map_t *fm,(global chunk map struct)
- Output: uint8_t assign_io_mode[], : IO mode, collective, independent or none
- haddr_t chunk_addr[], : chunk address array for each chunk
+ * Each chunk address is also obtained.
*
- * Return: Non-negative on success/Negative on failure
+ * Description:
*
- * Programmer:
+ * 1) Each process provides two piece of information for all chunks having selection
+ * a) chunk index
+ * b) wheather this chunk is regular(for MPI derived datatype not working case)
+ *
+ * 2) Gather all the information to the root process
*
- * Modifications:
+ * 3) Root process will do the following:
+ * a) Obtain chunk addresses for all chunks in this data space
+ * b) With the consideration of the user option, calculate IO mode for each chunk
+ * c) Build MPI derived datatype to combine "chunk address" and "assign_io" information
+ * in order to do MPI Bcast only once
+ * d) MPI Bcast the IO mode and chunk address information for each chunk.
+ * 4) Each process then retrieves IO mode and chunk address information to assign_io_mode and chunk_addr.
+ *
+ * Parameters:
+ *
+ * Input: H5D_io_info_t* io_info,
+ * H5D_chunk_map_t *fm,(global chunk map struct)
+ * Output: uint8_t assign_io_mode[], : IO mode, collective, independent or none
+ * haddr_t chunk_addr[], : chunk address array for each chunk
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Muqun Yang
+ * Monday, Feb. 13th, 2006
*
*-------------------------------------------------------------------------
*/
-
static herr_t
-H5D_obtain_mpio_mode(H5D_io_info_t* io_info,
- H5D_chunk_map_t *fm,
- uint8_t assign_io_mode[],
- haddr_t chunk_addr[])
+H5D_obtain_mpio_mode(H5D_io_info_t* io_info, H5D_chunk_map_t *fm,
+ H5P_genplist_t *dx_plist, uint8_t assign_io_mode[], haddr_t chunk_addr[])
{
-
- int total_chunks;
- hsize_t ori_total_chunks;
- unsigned percent_nproc_per_chunk,threshold_nproc_per_chunk;
- H5FD_mpio_chunk_opt_t chunk_opt_mode;
- uint8_t* io_mode_info=NULL;
- uint8_t* recv_io_mode_info=NULL;
- uint8_t* mergebuf=NULL;
- uint8_t* tempbuf;
-
- H5SL_node_t* chunk_node;
- H5D_chunk_info_t* chunk_info;
-
- MPI_Datatype bastype[2];
- MPI_Datatype chunk_addrtype;
- int bascount;
- int basblock[2];
- MPI_Aint basdisp[2];
- MPI_Datatype rtype;
- MPI_Datatype stype;
- int mpi_size,mpi_rank;
- MPI_Comm comm;
- int ic,root;
- int mpi_code;
- H5P_genplist_t *plist;
- int mem_cleanup = 0,
- mpi_type_cleanup = 0;
-
+ int total_chunks;
+ unsigned percent_nproc_per_chunk,threshold_nproc_per_chunk;
+ H5FD_mpio_chunk_opt_t chunk_opt_mode;
+ uint8_t* io_mode_info=NULL;
+ uint8_t* recv_io_mode_info=NULL;
+ uint8_t* mergebuf=NULL;
+ uint8_t* tempbuf;
+ H5SL_node_t* chunk_node;
+ H5D_chunk_info_t* chunk_info;
+ int mpi_size,mpi_rank;
+ MPI_Comm comm;
+ int ic,root;
+ int mpi_code;
+ int mem_cleanup = 0;
#ifdef H5_HAVE_INSTRUMENTED_LIBRARY
- int new_value;
- htri_t check_prop;
+ int new_value;
+ htri_t check_prop;
#endif
+ herr_t ret_value = SUCCEED;
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI_NOINIT(H5D_obtain_mpio_mode)
+ FUNC_ENTER_NOAPI_NOINIT(H5D_obtain_mpio_mode)
- /* Assign the rank 0 to the root */
- root = 0;
- comm = io_info->comm;
+ /* Assign the rank 0 to the root */
+ root = 0;
+ comm = io_info->comm;
- /* Obtain the number of process and the current rank of the process */
- if((mpi_rank = H5F_mpi_get_rank(io_info->dset->oloc.file))<0)
- HGOTO_ERROR (H5E_IO, H5E_MPI, FAIL, "unable to obtain mpi rank");
- if((mpi_size = H5F_mpi_get_size(io_info->dset->oloc.file))<0)
- HGOTO_ERROR (H5E_IO, H5E_MPI, FAIL, "unable to obtain mpi size");
+ /* Obtain the number of process and the current rank of the process */
+ if((mpi_rank = H5F_mpi_get_rank(io_info->dset->oloc.file)) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_MPI, FAIL, "unable to obtain mpi rank")
+ if((mpi_size = H5F_mpi_get_size(io_info->dset->oloc.file)) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_MPI, FAIL, "unable to obtain mpi size")
- /* Allocate memory */
- ori_total_chunks = fm->total_chunks;
- H5_ASSIGN_OVERFLOW(total_chunks,ori_total_chunks,hsize_t,int);
-
- /* Obtain the data transfer properties */
- if(NULL == (plist = H5I_object(io_info->dxpl_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list")
-
- percent_nproc_per_chunk=H5P_peek_unsigned(plist,H5D_XFER_MPIO_CHUNK_OPT_RATIO_NAME);
+ /* Setup parameters */
+ H5_ASSIGN_OVERFLOW(total_chunks, fm->total_chunks, hsize_t, int);
+ percent_nproc_per_chunk = H5P_peek_unsigned(dx_plist, H5D_XFER_MPIO_CHUNK_OPT_RATIO_NAME);
#if defined(H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS) && defined(H5_MPI_SPECIAL_COLLECTIVE_IO_WORKS)
-
- chunk_opt_mode=(H5FD_mpio_chunk_opt_t)H5P_peek_unsigned(plist,H5D_XFER_MPIO_CHUNK_OPT_HARD_NAME);
-
- if((chunk_opt_mode == H5FD_MPIO_CHUNK_MULTI_IO) || (percent_nproc_per_chunk == 0)){
- if(H5D_istore_chunkmap(io_info, chunk_addr, fm->down_chunks) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get chunk address");
- for(ic = 0; ic<total_chunks;ic++)
- assign_io_mode[ic] = H5D_CHUNK_IO_MODE_COL;
- goto done;
- }
+ chunk_opt_mode = (H5FD_mpio_chunk_opt_t)H5P_peek_unsigned(dx_plist, H5D_XFER_MPIO_CHUNK_OPT_HARD_NAME);
+ if((chunk_opt_mode == H5FD_MPIO_CHUNK_MULTI_IO) || (percent_nproc_per_chunk == 0)) {
+ if(H5D_istore_chunkmap(io_info, chunk_addr, fm->down_chunks) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get chunk address");
+ for(ic = 0; ic < total_chunks; ic++)
+ assign_io_mode[ic] = H5D_CHUNK_IO_MODE_COL;
+
+ HGOTO_DONE(SUCCEED)
+ } /* end if */
#endif
- threshold_nproc_per_chunk = mpi_size * percent_nproc_per_chunk/100;
-
- io_mode_info = (uint8_t *)H5MM_calloc(total_chunks*sizeof(MPI_BYTE));
- mergebuf = H5MM_malloc((sizeof(haddr_t)+sizeof(MPI_BYTE))*total_chunks);
- tempbuf = mergebuf + sizeof(MPI_BYTE)*total_chunks;
- if(mpi_rank == root)
- recv_io_mode_info = (uint8_t *)H5MM_malloc(total_chunks*sizeof(MPI_BYTE)*mpi_size);
+ threshold_nproc_per_chunk = mpi_size * percent_nproc_per_chunk/100;
+
+ /* Allocate memory */
+ io_mode_info = (uint8_t *)H5MM_calloc(total_chunks);
+ mergebuf = H5MM_malloc((sizeof(haddr_t) + 1) * total_chunks);
+ tempbuf = mergebuf + total_chunks;
+ if(mpi_rank == root)
+ recv_io_mode_info = (uint8_t *)H5MM_malloc(total_chunks * mpi_size);
- mem_cleanup = 1;
+ mem_cleanup = 1;
- chunk_node = H5SL_first(fm->sel_chunks);
-
- /*Obtain the regularity and selection information for all chunks in this process. */
- while(chunk_node){
-
- chunk_info = H5SL_item(chunk_node);
+ /* Obtain the regularity and selection information for all chunks in this process. */
+ chunk_node = H5SL_first(fm->sel_chunks);
+ while(chunk_node) {
+ chunk_info = H5SL_item(chunk_node);
#ifndef H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS
- /* regularity information: 1, selection information: 2 */
- if(H5S_SELECT_IS_REGULAR(chunk_info->fspace) == TRUE &&
- H5S_SELECT_IS_REGULAR(chunk_info->mspace) == TRUE)
+ /* regularity information: 1, selection information: 2 */
+ if(H5S_SELECT_IS_REGULAR(chunk_info->fspace) == TRUE &&
+ H5S_SELECT_IS_REGULAR(chunk_info->mspace) == TRUE)
#endif
- io_mode_info[chunk_info->index] = H5D_CHUNK_SELECT_REG; /* this chunk is selected and is "regular" without defining H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS. */
+ io_mode_info[chunk_info->index] = H5D_CHUNK_SELECT_REG; /* this chunk is selected and is "regular" without defining H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS. */
#ifndef H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS
- else
- io_mode_info[chunk_info->index] = H5D_CHUNK_SELECT_IRREG; /* this chunk is selected and is irregular*/
+ else
+ io_mode_info[chunk_info->index] = H5D_CHUNK_SELECT_IRREG; /* this chunk is selected and is irregular*/
#endif
-
- chunk_node = H5SL_next(chunk_node);
- }
+ chunk_node = H5SL_next(chunk_node);
+ } /* end while */
- /*Create sent MPI derived datatype */
- if(MPI_SUCCESS !=(mpi_code = MPI_Type_contiguous(total_chunks,MPI_BYTE,&stype)))
- HMPI_GOTO_ERROR(FAIL, "MPI_Comm_rank failed", mpi_code);
- if(MPI_SUCCESS != (mpi_code = MPI_Type_commit(&stype)))
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code);
-
- /*Create received basic MPI derived datatype */
- bascount = 2;
- basblock[0] = total_chunks;
- basblock[1] = total_chunks;
- basdisp[0] = 0;
- basdisp[1] = (MPI_Aint)(sizeof(MPI_BYTE)*total_chunks);/* may need to check overflow */
- bastype[0] = MPI_BYTE;
-
- if(MPI_SUCCESS !=(mpi_code = MPI_Type_contiguous(sizeof(haddr_t),MPI_BYTE,&chunk_addrtype)))
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_contiguous failed", mpi_code);
- if(MPI_SUCCESS != (mpi_code = MPI_Type_commit(&chunk_addrtype)))
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code);
- bastype[1] = chunk_addrtype;
-
- if(MPI_SUCCESS !=(mpi_code = MPI_Type_struct(bascount,basblock,basdisp,bastype,&rtype)))
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_struct failed", mpi_code);
- if(MPI_SUCCESS !=(mpi_code = MPI_Type_commit(&rtype)))
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code);
-
- /* Set up a flag to clean up the MPI derived datatype later */
- mpi_type_cleanup = 1;
-
- /*Gather all the information */
- if(MPI_SUCCESS !=(mpi_code = MPI_Gather(io_mode_info,1,stype,recv_io_mode_info,1,stype,root,comm)))
- HMPI_GOTO_ERROR(FAIL, "MPI_Gather failed", mpi_code);
-
- /* Calculate the mode for IO(collective, independent or none) at root process */
- if(mpi_rank == root) {
-
- int nproc;
- int* nproc_per_chunk;
+ /*Gather all the information */
+ if(MPI_SUCCESS != (mpi_code = MPI_Gather(io_mode_info, total_chunks, MPI_BYTE, recv_io_mode_info, total_chunks, MPI_BYTE, root, comm)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Gather failed", mpi_code)
+
+ /* Calculate the mode for IO(collective, independent or none) at root process */
+ if(mpi_rank == root) {
+ int nproc;
+ int* nproc_per_chunk;
#if !defined(H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS) || !defined(H5_MPI_SPECIAL_COLLECTIVE_IO_WORKS)
- int* ind_this_chunk;
+ int* ind_this_chunk;
#endif
- /* pre-computing: calculate number of processes and
- regularity of the selection occupied in each chunk */
- nproc_per_chunk = (int*)H5MM_calloc(total_chunks*sizeof(int));
+ /* pre-computing: calculate number of processes and
+ regularity of the selection occupied in each chunk */
+ nproc_per_chunk = (int*)H5MM_calloc(total_chunks * sizeof(int));
#if !defined(H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS) || !defined(H5_MPI_SPECIAL_COLLECTIVE_IO_WORKS)
- ind_this_chunk = (int*)H5MM_calloc(total_chunks*sizeof(int));
+ ind_this_chunk = (int*)H5MM_calloc(total_chunks * sizeof(int));
#endif
- /* calculating the chunk address */
- if(H5D_istore_chunkmap(io_info, chunk_addr, fm->down_chunks)<0){
- HDfree(nproc_per_chunk);
+ /* calculating the chunk address */
+ if(H5D_istore_chunkmap(io_info, chunk_addr, fm->down_chunks) < 0) {
+ HDfree(nproc_per_chunk);
#if !defined(H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS) || !defined(H5_MPI_SPECIAL_COLLECTIVE_IO_WORKS)
- HDfree(ind_this_chunk);
+ HDfree(ind_this_chunk);
#endif
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get chunk address");
- }
-
- /* checking for number of process per chunk and regularity of the selection*/
- for (nproc = 0;nproc <mpi_size;nproc++){
- uint8_t *tmp_recv_io_mode_info = recv_io_mode_info + nproc*total_chunks;
- /* calculate the number of process per chunk and adding irregular selection option */
- for(ic = 0; ic < total_chunks; ic++, tmp_recv_io_mode_info++){
- if(*tmp_recv_io_mode_info != 0) {
- nproc_per_chunk[ic]++;
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get chunk address")
+ } /* end if */
+
+ /* checking for number of process per chunk and regularity of the selection*/
+ for(nproc = 0; nproc < mpi_size; nproc++) {
+ uint8_t *tmp_recv_io_mode_info = recv_io_mode_info + (nproc * total_chunks);
+
+ /* Calculate the number of process per chunk and adding irregular selection option */
+ for(ic = 0; ic < total_chunks; ic++, tmp_recv_io_mode_info++) {
+ if(*tmp_recv_io_mode_info != 0) {
+ nproc_per_chunk[ic]++;
#ifndef H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS
- if(*tmp_recv_io_mode_info == H5D_CHUNK_SELECT_IRREG)
- ind_this_chunk[ic] = 1;
+ if(*tmp_recv_io_mode_info == H5D_CHUNK_SELECT_IRREG)
+ ind_this_chunk[ic] = 1;
#endif
- }
+ } /* end if */
#ifndef H5_MPI_SPECIAL_COLLECTIVE_IO_WORKS
else {
- /*checking whether we have a selection in this chunk */
- ind_this_chunk[ic] = 1;
- }
+ /*checking whether we have a selection in this chunk */
+ ind_this_chunk[ic] = 1;
+ } /* end else */
#endif
- }
+ } /* end for */
+ } /* end for */
- }
-
- /* Calculating MPIO mode for each chunk (collective, independent, none) */
- for(ic = 0; ic < total_chunks; ic++){
- if(nproc_per_chunk[ic]>MAX(1,threshold_nproc_per_chunk)){
+ /* Calculating MPIO mode for each chunk (collective, independent, none) */
+ for(ic = 0; ic < total_chunks; ic++) {
+ if(nproc_per_chunk[ic] > MAX(1, threshold_nproc_per_chunk)) {
#if !defined(H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS) || !defined(H5_MPI_SPECIAL_COLLECTIVE_IO_WORKS)
- if(!ind_this_chunk[ic]) assign_io_mode[ic] = H5D_CHUNK_IO_MODE_COL;
+ if(!ind_this_chunk[ic])
+ assign_io_mode[ic] = H5D_CHUNK_IO_MODE_COL;
#else
- assign_io_mode[ic] = H5D_CHUNK_IO_MODE_COL;
+ assign_io_mode[ic] = H5D_CHUNK_IO_MODE_COL;
#endif
- }
- }
+ } /* end if */
+ } /* end for */
- /* merge buffer io_mode info and chunk addr into one */
- HDmemcpy(mergebuf,assign_io_mode,sizeof(MPI_BYTE)*total_chunks);
- HDmemcpy(tempbuf,chunk_addr,sizeof(haddr_t)*total_chunks);
+ /* merge buffer io_mode info and chunk addr into one */
+ HDmemcpy(mergebuf, assign_io_mode, total_chunks);
+ HDmemcpy(tempbuf, chunk_addr, sizeof(haddr_t) * total_chunks);
- HDfree(nproc_per_chunk);
+ HDfree(nproc_per_chunk);
#if !defined(H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS) || !defined(H5_MPI_SPECIAL_COLLECTIVE_IO_WORKS)
- HDfree(ind_this_chunk);
+ HDfree(ind_this_chunk);
#endif
- }
+ } /* end if */
- /* Broadcasting the MPI_IO option info. and chunk address info. */
- if(MPI_SUCCESS !=(mpi_code = MPI_Bcast(mergebuf,1,rtype,root,comm)))
- HMPI_GOTO_ERROR(FAIL, "MPI_BCast failed", mpi_code);
+ /* Broadcasting the MPI_IO option info. and chunk address info. */
+ if(MPI_SUCCESS != (mpi_code = MPI_Bcast(mergebuf, ((sizeof(haddr_t) + 1) * total_chunks), MPI_BYTE, root, comm)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_BCast failed", mpi_code)
- HDmemcpy(assign_io_mode,mergebuf,sizeof(MPI_BYTE)*total_chunks);
- HDmemcpy(chunk_addr,tempbuf,sizeof(haddr_t)*total_chunks);
+ HDmemcpy(assign_io_mode, mergebuf, total_chunks);
+ HDmemcpy(chunk_addr, tempbuf, sizeof(haddr_t) * total_chunks);
#ifdef H5_HAVE_INSTRUMENTED_LIBRARY
- check_prop = H5Pexist(io_info->dxpl_id,H5D_XFER_COLL_CHUNK_MULTI_RATIO_COLL_NAME);
+ check_prop = H5Pexist(io_info->dxpl_id, H5D_XFER_COLL_CHUNK_MULTI_RATIO_COLL_NAME);
if(check_prop > 0) {
#if !defined(H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS) || !defined(H5_MPI_SPECIAL_COLLECTIVE_IO_WORKS)
- new_value = 0;
- if(H5Pset(io_info->dxpl_id,H5D_XFER_COLL_CHUNK_MULTI_RATIO_COLL_NAME,&new_value)<0)
- HGOTO_ERROR(H5E_PLIST, H5E_UNSUPPORTED, FAIL, "unable to set property value");
+ new_value = 0;
+ if(H5Pset(io_info->dxpl_id, H5D_XFER_COLL_CHUNK_MULTI_RATIO_COLL_NAME, &new_value) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_UNSUPPORTED, FAIL, "unable to set property value")
#else
- for(ic = 0; ic < total_chunks; ic++){
- if(assign_io_mode[ic] == H5D_CHUNK_IO_MODE_COL) {
- new_value = 0;
- if(H5Pset(io_info->dxpl_id,H5D_XFER_COLL_CHUNK_MULTI_RATIO_COLL_NAME,&new_value)<0)
- HGOTO_ERROR(H5E_PLIST, H5E_UNSUPPORTED, FAIL, "unable to set property value");
- break;
- }
- }
+ for(ic = 0; ic < total_chunks; ic++) {
+ if(assign_io_mode[ic] == H5D_CHUNK_IO_MODE_COL) {
+ new_value = 0;
+ if(H5Pset(io_info->dxpl_id,H5D_XFER_COLL_CHUNK_MULTI_RATIO_COLL_NAME,&new_value) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_UNSUPPORTED, FAIL, "unable to set property value")
+ break;
+ } /* end if */
+ } /* end for */
#endif
- }
- check_prop = H5Pexist(io_info->dxpl_id,H5D_XFER_COLL_CHUNK_MULTI_RATIO_IND_NAME);
- if(check_prop > 0) {
- int temp_count = 0;
- for(ic = 0; ic < total_chunks; ic++){
- if(assign_io_mode[ic] == H5D_CHUNK_IO_MODE_COL) {
- temp_count++;
- break;
- }
- }
- if(temp_count==0){
- new_value = 0;
- if(H5Pset(io_info->dxpl_id,H5D_XFER_COLL_CHUNK_MULTI_RATIO_IND_NAME,&new_value)<0)
- HGOTO_ERROR(H5E_PLIST, H5E_UNSUPPORTED, FAIL, "unable to set property value");
- }
- }
+ } /* end if */
+
+ check_prop = H5Pexist(io_info->dxpl_id, H5D_XFER_COLL_CHUNK_MULTI_RATIO_IND_NAME);
+ if(check_prop > 0) {
+ int temp_count = 0;
+
+ for(ic = 0; ic < total_chunks; ic++) {
+ if(assign_io_mode[ic] == H5D_CHUNK_IO_MODE_COL) {
+ temp_count++;
+ break;
+ } /* end if */
+ } /* end for */
+ if(temp_count == 0) {
+ new_value = 0;
+ if(H5Pset(io_info->dxpl_id, H5D_XFER_COLL_CHUNK_MULTI_RATIO_IND_NAME, &new_value) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_UNSUPPORTED, FAIL, "unable to set property value")
+ } /* end if */
+ } /* end if */
#endif
done:
-
- if(mpi_type_cleanup) {
- if (MPI_SUCCESS != (mpi_code= MPI_Type_free( &chunk_addrtype )))
- HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code);
-
- if (MPI_SUCCESS != (mpi_code= MPI_Type_free( &stype )))
- HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code);
-
- if (MPI_SUCCESS != (mpi_code= MPI_Type_free( &rtype )))
- HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code);
- }
-
- if(mem_cleanup){
- HDfree(io_mode_info);
- HDfree(mergebuf);
- if(mpi_rank == root)
- HDfree(recv_io_mode_info);
- }
+ if(mem_cleanup) {
+ HDfree(io_mode_info);
+ HDfree(mergebuf);
+ if(mpi_rank == root)
+ HDfree(recv_io_mode_info);
+ } /* end if */
FUNC_LEAVE_NOAPI(ret_value)
-}/* end H5D_obtain_mpio_mode*/
+} /* end H5D_obtain_mpio_mode() */
static int
H5D_cmp_chunk_addr(const void *chunk_addr_info1, const void *chunk_addr_info2)
@@ -2041,7 +2018,6 @@ H5D_cmp_chunk_addr(const void *chunk_addr_info1, const void *chunk_addr_info2)
addr2 = ((const H5D_chunk_addr_info_t *)chunk_addr_info2)->chunk_addr;
FUNC_LEAVE_NOAPI(H5F_addr_cmp(addr1, addr2))
-
}
#endif /* H5_HAVE_PARALLEL */
diff --git a/src/H5Doh.c b/src/H5Doh.c
index 01447a3..37f011b 100644
--- a/src/H5Doh.c
+++ b/src/H5Doh.c
@@ -316,7 +316,7 @@ H5O_dset_get_oloc(hid_t obj_id)
FUNC_ENTER_NOAPI_NOINIT(H5O_dset_get_oloc)
/* Get the dataset */
- if(NULL == (dset = H5I_object(obj_id)))
+ if(NULL == (dset = (H5D_t *)H5I_object(obj_id)))
HGOTO_ERROR(H5E_OHDR, H5E_BADATOM, NULL, "couldn't get object from ID")
/* Get the dataset's object header location */
diff --git a/src/H5Dpkg.h b/src/H5Dpkg.h
index aec5e19..97dcacf 100644
--- a/src/H5Dpkg.h
+++ b/src/H5Dpkg.h
@@ -49,74 +49,156 @@
#define H5D_MINHDR_SIZE 256
/* [Simple] Macro to construct a H5D_io_info_t from it's components */
-#define H5D_BUILD_IO_INFO(io_info,ds,dxpl_c,dxpl_i,str) \
- (io_info)->dset=ds; \
- (io_info)->dxpl_cache=dxpl_c; \
- (io_info)->dxpl_id=dxpl_i; \
- (io_info)->store=str
+#define H5D_BUILD_IO_INFO_WRT(io_info, ds, dxpl_c, dxpl_i, str, buf) \
+ (io_info)->dset = ds; \
+ (io_info)->dxpl_cache = dxpl_c; \
+ (io_info)->dxpl_id = dxpl_i; \
+ (io_info)->store = str; \
+ (io_info)->op_type = H5D_IO_OP_WRITE; \
+ (io_info)->u.wbuf = buf
+#define H5D_BUILD_IO_INFO_RD(io_info, ds, dxpl_c, dxpl_i, str, buf) \
+ (io_info)->dset = ds; \
+ (io_info)->dxpl_cache = dxpl_c; \
+ (io_info)->dxpl_id = dxpl_i; \
+ (io_info)->store = str; \
+ (io_info)->op_type = H5D_IO_OP_READ; \
+ (io_info)->u.rbuf = buf
+
+#define H5D_CHUNK_HASH(D, ADDR) H5F_addr_hash(ADDR, (D)->cache.chunk.nslots)
/****************************/
/* Package Private Typedefs */
/****************************/
-/*
- * If there is no data type conversion then it might be possible to
- * transfer data points between application memory and the file in one
- * step without going through the data type conversion buffer.
- */
-
-/* Read from file to application w/o intermediate scratch buffer */
+/* Typedef for datatype information for raw data I/O operation */
+typedef struct H5D_type_info_t {
+ /* Initial values */
+ const H5T_t *mem_type; /* Pointer to memory datatype */
+ const H5T_t *dset_type; /* Pointer to dataset datatype */
+ H5T_path_t *tpath; /* Datatype conversion path */
+ hid_t src_type_id; /* Source datatype ID */
+ hid_t dst_type_id; /* Destination datatype ID */
+
+ /* Computed/derived values */
+ size_t src_type_size; /* Size of source type */
+ size_t dst_type_size; /* Size of destination type*/
+ size_t max_type_size; /* Size of largest source/destination type */
+ hbool_t is_conv_noop; /* Whether the type conversion is a NOOP */
+ hbool_t is_xform_noop; /* Whether the data transform is a NOOP */
+ H5T_subset_t cmpd_subset; /* Whether (and which) the source/destination datatypes are compound subsets of one another */
+ H5T_bkg_t need_bkg; /* Type of background buf needed */
+ size_t request_nelmts; /* Requested strip mine */
+ uint8_t *tconv_buf; /* Datatype conv buffer */
+ hbool_t tconv_buf_allocated; /* Whether the type conversion buffer was allocated */
+ uint8_t *bkg_buf; /* Background buffer */
+ hbool_t bkg_buf_allocated; /* Whether the background buffer was allocated */
+} H5D_type_info_t;
+
+/* Forward declaration of structs used below */
struct H5D_io_info_t;
-typedef herr_t (*H5D_io_read_func_t)(struct H5D_io_info_t *io_info,
- size_t nelmts, size_t elmt_size,
- const H5S_t *file_space, const H5S_t *mem_space, haddr_t addr,
- void *chunk, void *buf/*out*/);
-
-
-/* Write directly from app buffer to file */
-typedef herr_t (*H5D_io_write_func_t)(struct H5D_io_info_t *io_info,
- size_t nelmts, size_t elmt_size,
- const H5S_t *file_space, const H5S_t *mem_space, haddr_t addr,
- void *chunk, const void *buf);
+struct H5D_chunk_map_t;
/* Function pointers for I/O on particular types of dataset layouts */
-typedef ssize_t (*H5D_io_readvv_func_t)(const struct H5D_io_info_t *io_info,
+typedef herr_t (*H5D_layout_init_func_t)(const struct H5D_io_info_t *io_info,
+ const H5D_type_info_t *type_info,
+ hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space,
+ struct H5D_chunk_map_t *cm);
+typedef herr_t (*H5D_layout_read_func_t)(struct H5D_io_info_t *io_info,
+ const H5D_type_info_t *type_info, hsize_t nelmts, const H5S_t *file_space,
+ const H5S_t *mem_space, struct H5D_chunk_map_t *fm);
+typedef herr_t (*H5D_layout_write_func_t)(struct H5D_io_info_t *io_info,
+ const H5D_type_info_t *type_info, hsize_t nelmts, const H5S_t *file_space,
+ const H5S_t *mem_space, struct H5D_chunk_map_t *fm);
+typedef ssize_t (*H5D_layout_readvv_func_t)(const struct H5D_io_info_t *io_info,
size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_len_arr[], hsize_t dset_offset_arr[],
- size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[],
- haddr_t chunk_addr, void *chunk, void *buf);
-typedef ssize_t (*H5D_io_writevv_func_t)(const struct H5D_io_info_t *io_info,
+ size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[]);
+typedef ssize_t (*H5D_layout_writevv_func_t)(const struct H5D_io_info_t *io_info,
size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_len_arr[], hsize_t dset_offset_arr[],
- size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[],
- haddr_t chunk_addr, void *chunk, const void *buf);
+ size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[]);
+typedef herr_t (*H5D_layout_term_func_t)(const struct H5D_chunk_map_t *cm);
+
+/* Typedef for grouping layout I/O routines */
+typedef struct H5D_layout_ops_t {
+ H5D_layout_init_func_t init; /* I/O initialization routine */
+ H5D_layout_read_func_t ser_read; /* High-level I/O routine for reading data in serial */
+ H5D_layout_write_func_t ser_write; /* High-level I/O routine for writing data in serial */
+#ifdef H5_HAVE_PARALLEL
+ H5D_layout_read_func_t par_read; /* High-level I/O routine for reading data in parallel */
+ H5D_layout_write_func_t par_write; /* High-level I/O routine for writing data in parallel */
+#endif /* H5_HAVE_PARALLEL */
+ H5D_layout_readvv_func_t readvv; /* Low-level I/O routine for reading data */
+ H5D_layout_writevv_func_t writevv; /* Low-level I/O routine for writing data */
+ H5D_layout_term_func_t term; /* I/O shutdown routine */
+} H5D_layout_ops_t;
+
+/* Function pointers for either multiple or single block I/O access */
+typedef herr_t (*H5D_io_single_read_func_t)(const struct H5D_io_info_t *io_info,
+ const H5D_type_info_t *type_info,
+ hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space);
+typedef herr_t (*H5D_io_single_write_func_t)(const struct H5D_io_info_t *io_info,
+ const H5D_type_info_t *type_info,
+ hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space);
/* Typedef for raw data I/O framework info */
typedef struct H5D_io_ops_t {
- H5D_io_read_func_t read; /* Direct I/O routine for reading */
- H5D_io_write_func_t write; /* Direct I/O routine for writing */
- H5D_io_readvv_func_t readvv; /* I/O routine for reading data */
- H5D_io_writevv_func_t writevv; /* I/O routine for writing data */
+ H5D_layout_read_func_t multi_read; /* High-level I/O routine for reading data */
+ H5D_layout_write_func_t multi_write; /* High-level I/O routine for writing data */
+ H5D_io_single_read_func_t single_read; /* I/O routine for reading single block */
+ H5D_io_single_write_func_t single_write; /* I/O routine for writing single block */
} H5D_io_ops_t;
+/* Typedefs for dataset storage information */
+typedef struct {
+ haddr_t dset_addr; /* Address of dataset in file */
+ hsize_t dset_size; /* Total size of dataset in file */
+} H5D_contig_storage_t;
+
+typedef struct {
+ hsize_t index; /* "Index" of chunk in dataset (must be first for TBBT routines) */
+ hsize_t *offset; /* Chunk's coordinates in elements */
+} H5D_chunk_storage_t;
+
+typedef struct {
+ void *buf; /* Buffer for compact dataset */
+ hbool_t *dirty; /* Pointer to dirty flag to mark */
+} H5D_compact_storage_t;
+
+typedef union H5D_storage_t {
+ H5D_contig_storage_t contig; /* Contiguous information for dataset */
+ H5D_chunk_storage_t chunk; /* Chunk information for dataset */
+ H5D_compact_storage_t compact; /* Compact information for dataset */
+ H5O_efl_t efl; /* External file list information for dataset */
+} H5D_storage_t;
+
/* Typedef for raw data I/O operation info */
typedef struct H5D_io_info_t {
H5D_t *dset; /* Pointer to dataset being operated on */
#ifndef H5_HAVE_PARALLEL
const
#endif /* H5_HAVE_PARALLEL */
- H5D_dxpl_cache_t *dxpl_cache; /* Pointer to cache DXPL info */
+ H5D_dxpl_cache_t *dxpl_cache; /* Pointer to cached DXPL info */
hid_t dxpl_id; /* Original DXPL ID */
#ifdef H5_HAVE_PARALLEL
MPI_Comm comm; /* MPI communicator for file */
- hbool_t xfer_mode_changed; /* Whether the transfer mode was changed */
- hbool_t xfer_opt_mode_changed;
hbool_t using_mpi_vfd; /* Whether the file is using an MPI-based VFD */
+ struct {
+ H5FD_mpio_xfer_t xfer_mode; /* Parallel transfer for this request (H5D_XFER_IO_XFER_MODE_NAME) */
+ H5FD_mpio_collective_opt_t coll_opt_mode; /* Parallel transfer with independent IO or collective IO with this mode */
+ H5D_io_ops_t io_ops; /* I/O operation function pointers */
+ } orig;
#endif /* H5_HAVE_PARALLEL */
- const H5D_storage_t *store; /* Dataset storage info */
- H5D_io_ops_t ops; /* I/O operation function pointers */
-#ifdef H5S_DEBUG
- H5S_iostats_t *stats; /* I/O statistics */
-#endif /* H5S_DEBUG */
+ H5D_storage_t *store; /* Dataset storage info */
+ H5D_layout_ops_t layout_ops; /* Dataset layout I/O operation function pointers */
+ H5D_io_ops_t io_ops; /* I/O operation function pointers */
+ enum {
+ H5D_IO_OP_READ, /* Read operation */
+ H5D_IO_OP_WRITE /* Write operation */
+ } op_type;
+ union {
+ void *rbuf; /* Pointer to buffer for read */
+ const void *wbuf; /* Pointer to buffer to write */
+ } u;
} H5D_io_info_t;
/* Structure holding information about a chunk's selection for mapping */
@@ -183,8 +265,8 @@ typedef struct H5D_shared_t {
hbool_t layout_dirty; /* Whether the layout info needs to be flushed to the file */
hid_t dcpl_id; /* dataset creation property id */
H5D_dcpl_cache_t dcpl_cache; /* Cached DCPL values */
- H5D_io_ops_t io_ops; /* I/O operations */
H5O_layout_t layout; /* data layout */
+ const H5D_layout_ops_t *layout_ops; /* Pointer to data layout I/O operations */
hbool_t checked_filters;/* TRUE if dataset passes can_apply check */
/* Buffered/cached information for types of raw data storage*/
@@ -229,18 +311,21 @@ typedef struct H5D_chunk_map_t {
H5S_sel_type msel_type; /* Selection type in memory */
H5SL_t *sel_chunks; /* Skip list containing information for each chunk selected */
+
H5S_t *single_space; /* Dataspace for single chunk */
H5D_chunk_info_t *single_chunk_info; /* Pointer to single chunk's info */
hbool_t use_single; /* Whether I/O is on a single element */
+
hsize_t last_index; /* Index of last chunk operated on */
H5D_chunk_info_t *last_chunk_info; /* Pointer to last chunk's info */
+
hsize_t chunks[H5O_LAYOUT_NDIMS]; /* Number of chunks in each dimension */
hsize_t chunk_dim[H5O_LAYOUT_NDIMS]; /* Size of chunk in each dimension */
hsize_t down_chunks[H5O_LAYOUT_NDIMS]; /* "down" size of number of chunks in each dimension */
#ifdef H5_HAVE_PARALLEL
- hsize_t total_chunks; /* Number of total chunks */
- hbool_t *select_chunk; /* store the information about whether this chunk is selected or not */
+ hsize_t total_chunks; /* Number of chunks covered by dataspace */
+ H5D_chunk_info_t **select_chunk; /* Store the information about whether this chunk is selected or not */
#endif /* H5_HAVE_PARALLEL */
} H5D_chunk_map_t;
@@ -332,12 +417,34 @@ typedef struct {
hsize_t size; /* Accumulated number of bytes for the selection */
} H5D_vlen_bufsize_t;
+/* Raw data chunks are cached. Each entry in the cache is: */
+typedef struct H5D_rdcc_ent_t {
+ hbool_t locked; /*entry is locked in cache */
+ hbool_t dirty; /*needs to be written to disk? */
+ hsize_t offset[H5O_LAYOUT_NDIMS]; /*chunk name */
+ size_t rd_count; /*bytes remaining to be read */
+ size_t wr_count; /*bytes remaining to be written */
+ size_t chunk_size; /*size of a chunk */
+ size_t alloc_size; /*amount allocated for the chunk */
+ uint8_t *chunk; /*the unfiltered chunk data */
+ unsigned idx; /*index in hash table */
+ struct H5D_rdcc_ent_t *next;/*next item in doubly-linked list */
+ struct H5D_rdcc_ent_t *prev;/*previous item in doubly-linked list */
+} H5D_rdcc_ent_t;
+typedef H5D_rdcc_ent_t *H5D_rdcc_ent_ptr_t; /* For free lists */
+
/*****************************/
/* Package Private Variables */
/*****************************/
extern H5D_dxpl_cache_t H5D_def_dxpl_cache;
+/* Storage layout classes */
+H5_DLLVAR const H5D_layout_ops_t H5D_LOPS_CONTIG[1];
+H5_DLLVAR const H5D_layout_ops_t H5D_LOPS_EFL[1];
+H5_DLLVAR const H5D_layout_ops_t H5D_LOPS_COMPACT[1];
+H5_DLLVAR const H5D_layout_ops_t H5D_LOPS_CHUNK[1];
+
/******************************/
/* Package Private Prototypes */
@@ -361,54 +468,51 @@ H5_DLL herr_t H5D_vlen_get_buf_size(void *elem, hid_t type_id, unsigned ndim,
const hsize_t *point, void *op_data);
H5_DLL herr_t H5D_check_filters(H5D_t *dataset);
H5_DLL herr_t H5D_set_extent(H5D_t *dataset, const hsize_t *size, hid_t dxpl_id);
-
-/* Functions that perform serial I/O operations */
-H5_DLL herr_t H5D_select_fscat(H5D_io_info_t *io_info,
- const H5S_t *file_space, H5S_sel_iter_t *file_iter, size_t nelmts,
- haddr_t chunk_addr, void *chunk, const void *_buf);
-H5_DLL size_t H5D_select_fgath(H5D_io_info_t *io_info,
- const H5S_t *file_space, H5S_sel_iter_t *file_iter, size_t nelmts,
- haddr_t chunk_addr, void *chunk, void *buf);
-H5_DLL herr_t H5D_select_mscat(const void *_tscat_buf,
+H5_DLL herr_t H5D_get_dxpl_cache(hid_t dxpl_id, H5D_dxpl_cache_t **cache);
+
+/* Functions that perform direct serial I/O operations */
+H5_DLL herr_t H5D_select_read(const H5D_io_info_t *io_info,
+ const H5D_type_info_t *type_info,
+ hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space);
+H5_DLL herr_t H5D_select_write(const H5D_io_info_t *io_info,
+ const H5D_type_info_t *type_info,
+ hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space);
+
+/* Functions that perform scatter-gather serial I/O operations */
+H5_DLL herr_t H5D_scatter_mem(const void *_tscat_buf,
const H5S_t *space, H5S_sel_iter_t *iter, size_t nelmts,
- const H5D_dxpl_cache_t *dxpl_cache, void *_buf/*out*/);
-H5_DLL size_t H5D_select_mgath(const void *_buf,
- const H5S_t *space, H5S_sel_iter_t *iter, size_t nelmts,
- const H5D_dxpl_cache_t *dxpl_cache, void *_tgath_buf/*out*/);
-H5_DLL herr_t H5D_select_read(H5D_io_info_t *io_info,
- size_t nelmts, size_t elmt_size,
- const H5S_t *file_space, const H5S_t *mem_space,
- haddr_t addr, void *chunk/*in*/, void *buf/*out*/);
-H5_DLL herr_t H5D_select_write(H5D_io_info_t *io_info,
- size_t nelmts, size_t elmt_size,
- const H5S_t *file_space, const H5S_t *mem_space,
- haddr_t addr, void *chunk/*in*/, const void *buf/*out*/);
+ const H5D_dxpl_cache_t *dxpl_cache, void *_buf);
+H5_DLL herr_t H5D_scatgath_read(const H5D_io_info_t *io_info,
+ const H5D_type_info_t *type_info,
+ hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space);
+H5_DLL herr_t H5D_scatgath_write(const H5D_io_info_t *io_info,
+ const H5D_type_info_t *type_info,
+ hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space);
/* Functions that operate on contiguous storage */
H5_DLL herr_t H5D_contig_create(H5F_t *f, hid_t dxpl_id, H5O_layout_t *layout);
H5_DLL herr_t H5D_contig_fill(H5D_t *dset, hid_t dxpl_id);
H5_DLL haddr_t H5D_contig_get_addr(const H5D_t *dset);
+H5_DLL herr_t H5D_contig_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
+ hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space,
+ H5D_chunk_map_t *fm);
+H5_DLL herr_t H5D_contig_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
+ hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space,
+ H5D_chunk_map_t *fm);
H5_DLL ssize_t H5D_contig_readvv(const H5D_io_info_t *io_info,
size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_len_arr[], hsize_t dset_offset_arr[],
- size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[],
- haddr_t UNUSED address, void UNUSED *pointer, void *buf);
+ size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[]);
H5_DLL ssize_t H5D_contig_writevv(const H5D_io_info_t *io_info,
size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_len_arr[], hsize_t dset_offset_arr[],
- size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[],
- haddr_t UNUSED address, void UNUSED *pointer, const void *buf);
+ size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[]);
H5_DLL herr_t H5D_contig_copy(H5F_t *f_src, const H5O_layout_t *layout_src, H5F_t *f_dst,
H5O_layout_t *layout_dst, H5T_t *src_dtype, H5O_copy_t *cpy_info, hid_t dxpl_id);
+/* Functions that operate on chunked dataset storage */
+H5_DLL hbool_t H5D_chunk_cacheable(const H5D_io_info_t *io_info, haddr_t caddr);
+
/* Functions that operate on compact dataset storage */
H5_DLL herr_t H5D_compact_fill(H5D_t *dset, hid_t dxpl_id);
-H5_DLL ssize_t H5D_compact_readvv(const H5D_io_info_t *io_info,
- size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_size_arr[], hsize_t dset_offset_arr[],
- size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_size_arr[], hsize_t mem_offset_arr[],
- haddr_t UNUSED addr, void UNUSED *pointer/*in*/, void *buf);
-H5_DLL ssize_t H5D_compact_writevv(const H5D_io_info_t *io_info,
- size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_size_arr[], hsize_t dset_offset_arr[],
- size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_size_arr[], hsize_t mem_offset_arr[],
- haddr_t UNUSED addr, void UNUSED *pointer/*in*/, const void *buf);
H5_DLL herr_t H5D_compact_copy(H5F_t *f_src, H5O_layout_t *layout_src,
H5F_t *f_dst, H5O_layout_t *layout_dst, H5T_t *src_dtype, H5O_copy_t *cpy_info, hid_t dxpl_id);
@@ -430,19 +534,11 @@ H5_DLL herr_t H5D_istore_initialize_by_extent(H5D_io_info_t *io_info);
H5_DLL herr_t H5D_istore_update_cache(H5D_t *dset, hid_t dxpl_id);
H5_DLL herr_t H5D_istore_dump_btree(H5F_t *f, hid_t dxpl_id, FILE *stream, unsigned ndims,
haddr_t addr);
-H5_DLL herr_t H5D_istore_chunkmap(const H5D_io_info_t *io_info, haddr_t chunk_addr[],hsize_t down_chunks[] );
+H5_DLL herr_t H5D_istore_chunkmap(const H5D_io_info_t *io_info,
+ haddr_t chunk_addr[], const hsize_t down_chunks[]);
#ifdef H5D_ISTORE_DEBUG
H5_DLL herr_t H5D_istore_stats (H5D_t *dset, hbool_t headers);
#endif /* H5D_ISTORE_DEBUG */
-H5_DLL ssize_t H5D_istore_readvv(const H5D_io_info_t *io_info,
- size_t chunk_max_nseq, size_t *chunk_curr_seq, size_t chunk_len_arr[],
- hsize_t chunk_offset_arr[], size_t mem_max_nseq, size_t *mem_curr_seq,
- size_t mem_len_arr[], hsize_t mem_offset_arr[], haddr_t chunk_addr, void *chunk, void *buf);
-H5_DLL ssize_t H5D_istore_writevv(const H5D_io_info_t *io_info,
- size_t chunk_max_nseq, size_t *chunk_curr_seq, size_t chunk_len_arr[],
- hsize_t chunk_offset_arr[], size_t mem_max_nseq, size_t *mem_curr_seq,
- size_t mem_len_arr[], hsize_t mem_offset_arr[], haddr_t chunk_addr, void *chunk,
- const void *buf);
H5_DLL haddr_t H5D_istore_get_addr(const H5D_io_info_t *io_info,
struct H5D_istore_ud1_t *_udata);
H5_DLL herr_t H5D_istore_copy(H5F_t *f_src, H5O_layout_t *layout_src,
@@ -452,17 +548,6 @@ H5_DLL void * H5D_istore_lock(const H5D_io_info_t *io_info, H5D_istore_ud1_t *ud
hbool_t relax, unsigned *idx_hint/*in,out*/);
H5_DLL herr_t H5D_istore_unlock(const H5D_io_info_t *io_info,
hbool_t dirty, unsigned idx_hint, void *chunk, size_t naccessed);
-H5_DLL hbool_t H5D_istore_if_load(const H5D_io_info_t *io_info, haddr_t caddr);
-
-/* Functions that operate on external file list (efl) storage */
-H5_DLL ssize_t H5D_efl_readvv(const H5D_io_info_t *io_info,
- size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_len_arr[], hsize_t dset_offset_arr[],
- size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[],
- haddr_t UNUSED addr, void UNUSED *pointer/*in*/, void *buf);
-H5_DLL ssize_t H5D_efl_writevv(const H5D_io_info_t *io_info,
- size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_len_arr[], hsize_t dset_offset_arr[],
- size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[],
- haddr_t UNUSED addr, void UNUSED *pointer/*in*/, const void *buf);
/* Functions that perform fill value operations on datasets */
H5_DLL herr_t H5D_fill(const void *fill, const H5T_t *fill_type, void *buf,
@@ -485,36 +570,37 @@ H5_DLL herr_t H5D_fill_term(H5D_fill_buf_info_t *fb_info);
#define H5Dmpio_DEBUG
#endif /*H5Dmpio_DEBUG*/
#endif/*H5S_DEBUG*/
-/* MPI-IO function to read , it will select either regular or irregular read */
-H5_DLL herr_t H5D_mpio_select_read(H5D_io_info_t *io_info,
- size_t nelmts, size_t elmt_size,
- const struct H5S_t *file_space, const struct H5S_t *mem_space,
- haddr_t addr, void UNUSED *pointer/*in*/, void *buf/*out*/);
-
-/* MPI-IO function to read , it will select either regular or irregular read */
-H5_DLL herr_t H5D_mpio_select_write(H5D_io_info_t *io_info,
- size_t nelmts, size_t elmt_size,
- const struct H5S_t *file_space, const struct H5S_t *mem_space,
- haddr_t addr, void UNUSED *pointer/*in*/, const void *buf);
-
-/* MPI-IO function to handle contiguous collective IO */
-H5_DLL herr_t
-H5D_contig_collective_io(H5D_io_info_t *io_info,
- const H5S_t *file_space,const H5S_t *mem_space,
- const void *_buf,hbool_t do_write);
-
-/* MPI-IO function to handle chunked collective IO */
-H5_DLL herr_t
-H5D_chunk_collective_io(H5D_io_info_t * io_info, H5D_chunk_map_t *fm, const void*buf,
- hbool_t do_write);
+/* MPI-IO function to read, it will select either regular or irregular read */
+H5_DLL herr_t H5D_mpio_select_read(const H5D_io_info_t *io_info,
+ const H5D_type_info_t *type_info,
+ hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space);
+
+/* MPI-IO function to write, it will select either regular or irregular read */
+H5_DLL herr_t H5D_mpio_select_write(const H5D_io_info_t *io_info,
+ const H5D_type_info_t *type_info,
+ hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space);
+
+/* MPI-IO functions to handle contiguous collective IO */
+H5_DLL herr_t H5D_contig_collective_read(H5D_io_info_t *io_info,
+ const H5D_type_info_t *type_info, hsize_t nelmts, const H5S_t *file_space,
+ const H5S_t *mem_space, H5D_chunk_map_t *fm);
+H5_DLL herr_t H5D_contig_collective_write(H5D_io_info_t *io_info,
+ const H5D_type_info_t *type_info, hsize_t nelmts, const H5S_t *file_space,
+ const H5S_t *mem_space, H5D_chunk_map_t *fm);
+
+/* MPI-IO functions to handle chunked collective IO */
+H5_DLL herr_t H5D_chunk_collective_read(H5D_io_info_t *io_info,
+ const H5D_type_info_t *type_info, hsize_t nelmts, const H5S_t *file_space,
+ const H5S_t *mem_space, H5D_chunk_map_t *fm);
+H5_DLL herr_t H5D_chunk_collective_write(H5D_io_info_t *io_info,
+ const H5D_type_info_t *type_info, hsize_t nelmts, const H5S_t *file_space,
+ const H5S_t *mem_space, H5D_chunk_map_t *fm);
+
/* MPI-IO function to check if a direct I/O transfer is possible between
* memory and the file */
-H5_DLL htri_t H5D_mpio_opt_possible(const H5D_io_info_t *io_info, const H5S_t *mem_space,
- const H5S_t *file_space, const H5T_path_t *tpath);
-
-#ifndef H5_MPI_SPECIAL_COLLECTIVE_IO_WORKS
-H5_DLL herr_t H5D_mpio_chunk_adjust_iomode(H5D_io_info_t *io_info, const H5D_chunk_map_t *fm);
-#endif /* H5_MPI_SPECIAL_COLLECTIVE_IO_WORKS */
+H5_DLL htri_t H5D_mpio_opt_possible(const H5D_io_info_t *io_info,
+ const H5S_t *file_space, const H5S_t *mem_space,
+ const H5D_type_info_t *type_info, const H5D_chunk_map_t *fm);
#endif /* H5_HAVE_PARALLEL */
diff --git a/src/H5Dprivate.h b/src/H5Dprivate.h
index 410dc43..8cf134f 100644
--- a/src/H5Dprivate.h
+++ b/src/H5Dprivate.h
@@ -65,7 +65,6 @@
#define H5D_XFER_HYPER_VECTOR_SIZE_NAME "vec_size" /* Hyperslab vector size */
#ifdef H5_HAVE_PARALLEL
#define H5D_XFER_IO_XFER_MODE_NAME "io_xfer_mode" /* I/O transfer mode */
-#define H5D_XFER_IO_XFER_OPT_MODE_NAME "io_xfer_opt_mode" /* I/O optimization transfer mode (using MPI-IO independent IO with file set view) */
#define H5D_XFER_MPIO_COLLECTIVE_OPT_NAME "mpio_collective_opt" /* Optimization of MPI-IO transfer mode */
#define H5D_XFER_MPIO_CHUNK_OPT_HARD_NAME "mpio_chunk_opt_hard"
#define H5D_XFER_MPIO_CHUNK_OPT_NUM_NAME "mpio_chunk_opt_num"
@@ -107,23 +106,6 @@
/* Typedef for dataset in memory (defined in H5Dpkg.h) */
typedef struct H5D_t H5D_t;
-/* Typedef for dataset storage information */
-typedef struct {
- hsize_t index; /* "Index" of chunk in dataset (must be first for TBBT routines) */
- hsize_t *offset; /* Chunk's coordinates in elements */
-} H5D_chunk_storage_t;
-
-typedef struct {
- haddr_t dset_addr; /* Address of dataset in file */
- hsize_t dset_size; /* Total size of dataset in file */
-} H5D_contig_storage_t;
-
-typedef union H5D_storage_t {
- H5O_efl_t efl; /* External file list information for dataset */
- H5D_chunk_storage_t chunk; /* Chunk information for dataset */
- H5D_contig_storage_t contig; /* Contiguous information for dataset */
-} H5D_storage_t;
-
/* Typedef for cached dataset transfer property list information */
typedef struct H5D_dxpl_cache_t {
size_t max_temp_buf; /* Maximum temporary buffer size (H5D_XFER_MAX_TEMP_BUF_NAME) */
@@ -135,7 +117,7 @@ typedef struct H5D_dxpl_cache_t {
size_t vec_size; /* Size of hyperslab vector (H5D_XFER_HYPER_VECTOR_SIZE_NAME) */
#ifdef H5_HAVE_PARALLEL
H5FD_mpio_xfer_t xfer_mode; /* Parallel transfer for this request (H5D_XFER_IO_XFER_MODE_NAME) */
- H5FD_mpio_collective_opt_t xfer_opt_mode; /* Parallel transfer with independent IO or collective IO with this mode */
+ H5FD_mpio_collective_opt_t coll_opt_mode; /* Parallel transfer with independent IO or collective IO with this mode */
#endif /*H5_HAVE_PARALLEL*/
H5Z_cb_t filter_cb; /* Filter callback function (H5D_XFER_FILTER_CB_NAME) */
H5Z_data_xform_t *data_xform_prop; /* Data transform prop (H5D_XFER_XFORM_NAME) */
@@ -163,8 +145,6 @@ H5_DLL H5O_loc_t *H5D_oloc(H5D_t *dataset);
H5_DLL H5G_name_t *H5D_nameof(H5D_t *dataset);
H5_DLL H5T_t *H5D_typeof(const H5D_t *dset);
H5_DLL herr_t H5D_flush(const H5F_t *f, hid_t dxpl_id, unsigned flags);
-H5_DLL herr_t H5D_get_dxpl_cache(hid_t dxpl_id, H5D_dxpl_cache_t **cache);
-H5_DLL herr_t H5D_get_dxpl_cache_real(hid_t dxpl_id, H5D_dxpl_cache_t *cache);
/* Functions that operate on vlen data */
H5_DLL herr_t H5D_vlen_reclaim(hid_t type_id, H5S_t *space, hid_t plist_id,
diff --git a/src/H5Dscatgath.c b/src/H5Dscatgath.c
new file mode 100644
index 0000000..3ea4c69
--- /dev/null
+++ b/src/H5Dscatgath.c
@@ -0,0 +1,899 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the files COPYING and Copyright.html. COPYING can be found at the root *
+ * of the source code distribution tree; Copyright.html can be found at the *
+ * root level of an installed copy of the electronic HDF5 document set and *
+ * is linked from the top-level documents page. It can also be found at *
+ * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#define H5D_PACKAGE /*suppress error about including H5Dpkg */
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Dpkg.h" /* Dataset functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5FLprivate.h" /* Free Lists */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+static size_t H5D_gather_file(const H5D_io_info_t *io_info,
+ const H5S_t *file_space, H5S_sel_iter_t *file_iter, size_t nelmts,
+ void *buf);
+static herr_t H5D_scatter_file(const H5D_io_info_t *io_info,
+ const H5S_t *file_space, H5S_sel_iter_t *file_iter, size_t nelmts,
+ const void *buf);
+static size_t H5D_gather_mem(const void *_buf,
+ const H5S_t *space, H5S_sel_iter_t *iter, size_t nelmts,
+ const H5D_dxpl_cache_t *dxpl_cache, void *_tgath_buf/*out*/);
+static herr_t H5D_compound_opt_read(size_t nelmts, const H5S_t *mem_space,
+ H5S_sel_iter_t *iter, const H5D_dxpl_cache_t *dxpl_cache,
+ const H5D_type_info_t *type_info, void *user_buf/*out*/);
+static herr_t H5D_compound_opt_write(size_t nelmts, const H5D_type_info_t *type_info);
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+/* Declare a free list to manage sequences of size_t */
+H5FL_SEQ_EXTERN(size_t);
+
+/* Declare a free list to manage sequences of hsize_t */
+H5FL_SEQ_EXTERN(hsize_t);
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_scatter_file
+ *
+ * Purpose: Scatters dataset elements from the type conversion buffer BUF
+ * to the file F where the data points are arranged according to
+ * the file dataspace FILE_SPACE and stored according to
+ * LAYOUT and EFL. Each element is ELMT_SIZE bytes.
+ * The caller is requesting that NELMTS elements are copied.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, June 20, 2002
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_scatter_file(const H5D_io_info_t *_io_info,
+ const H5S_t *space, H5S_sel_iter_t *iter, size_t nelmts,
+ const void *_buf)
+{
+ H5D_io_info_t tmp_io_info; /* Temporary I/O info object */
+ hsize_t _off[H5D_IO_VECTOR_SIZE]; /* Array to store sequence offsets */
+ hsize_t *off = NULL; /* Pointer to sequence offsets */
+ hsize_t mem_off; /* Offset in memory */
+ size_t mem_curr_seq; /* "Current sequence" in memory */
+ size_t dset_curr_seq; /* "Current sequence" in dataset */
+ size_t _len[H5D_IO_VECTOR_SIZE]; /* Array to store sequence lengths */
+ size_t *len = NULL; /* Array to store sequence lengths */
+ size_t orig_mem_len, mem_len; /* Length of sequence in memory */
+ size_t nseq; /* Number of sequences generated */
+ size_t nelem; /* Number of elements used in sequences */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_scatter_file)
+
+ /* Check args */
+ HDassert(_io_info);
+ HDassert(space);
+ HDassert(iter);
+ HDassert(nelmts > 0);
+ HDassert(_buf);
+
+ /* Set up temporary I/O info object */
+ HDmemcpy(&tmp_io_info, _io_info, sizeof(*_io_info));
+ tmp_io_info.op_type = H5D_IO_OP_WRITE;
+ tmp_io_info.u.wbuf = _buf;
+
+ /* Allocate the vector I/O arrays */
+ if(tmp_io_info.dxpl_cache->vec_size > H5D_IO_VECTOR_SIZE) {
+ if(NULL == (len = H5FL_SEQ_MALLOC(size_t, tmp_io_info.dxpl_cache->vec_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O length vector array")
+ if(NULL == (off = H5FL_SEQ_MALLOC(hsize_t, tmp_io_info.dxpl_cache->vec_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O offset vector array")
+ } /* end if */
+ else {
+ len = _len;
+ off = _off;
+ } /* end else */
+
+ /* Loop until all elements are written */
+ while(nelmts > 0) {
+ /* Get list of sequences for selection to write */
+ if(H5S_SELECT_GET_SEQ_LIST(space, H5S_GET_SEQ_LIST_SORTED, iter, tmp_io_info.dxpl_cache->vec_size, nelmts, &nseq, &nelem, off, len) < 0)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed")
+
+ /* Reset the current sequence information */
+ mem_curr_seq = dset_curr_seq = 0;
+ orig_mem_len = mem_len = nelem * iter->elmt_size;
+ mem_off = 0;
+
+ /* Write sequence list out */
+ if((*tmp_io_info.layout_ops.writevv)(&tmp_io_info, nseq, &dset_curr_seq,
+ len, off, (size_t)1, &mem_curr_seq, &mem_len, &mem_off) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_WRITEERROR, FAIL, "write error")
+
+ /* Update buffer */
+ tmp_io_info.u.wbuf = (const uint8_t *)tmp_io_info.u.wbuf + orig_mem_len;
+
+ /* Decrement number of elements left to process */
+ nelmts -= nelem;
+ } /* end while */
+
+done:
+ /* Release resources, if allocated */
+ if(len && len != _len)
+ H5FL_SEQ_FREE(size_t, len);
+ if(off && off != _off)
+ H5FL_SEQ_FREE(hsize_t, off);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5D_scatter_file() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_gather_file
+ *
+ * Purpose: Gathers data points from file F and accumulates them in the
+ * type conversion buffer BUF. The LAYOUT argument describes
+ * how the data is stored on disk and EFL describes how the data
+ * is organized in external files. ELMT_SIZE is the size in
+ * bytes of a datum which this function treats as opaque.
+ * FILE_SPACE describes the dataspace of the dataset on disk
+ * and the elements that have been selected for reading (via
+ * hyperslab, etc). This function will copy at most NELMTS
+ * elements.
+ *
+ * Return: Success: Number of elements copied.
+ * Failure: 0
+ *
+ * Programmer: Quincey Koziol
+ * Monday, June 24, 2002
+ *
+ *-------------------------------------------------------------------------
+ */
+static size_t
+H5D_gather_file(const H5D_io_info_t *_io_info,
+ const H5S_t *space, H5S_sel_iter_t *iter, size_t nelmts,
+ void *_buf/*out*/)
+{
+ H5D_io_info_t tmp_io_info; /* Temporary I/O info object */
+ hsize_t _off[H5D_IO_VECTOR_SIZE]; /* Array to store sequence offsets */
+ hsize_t *off = NULL; /* Pointer to sequence offsets */
+ hsize_t mem_off; /* Offset in memory */
+ size_t mem_curr_seq; /* "Current sequence" in memory */
+ size_t dset_curr_seq; /* "Current sequence" in dataset */
+ size_t _len[H5D_IO_VECTOR_SIZE]; /* Array to store sequence lengths */
+ size_t *len = NULL; /* Pointer to sequence lengths */
+ size_t orig_mem_len, mem_len; /* Length of sequence in memory */
+ size_t nseq; /* Number of sequences generated */
+ size_t nelem; /* Number of elements used in sequences */
+ size_t ret_value = nelmts; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_gather_file)
+
+ /* Check args */
+ HDassert(_io_info);
+ HDassert(_io_info->dset);
+ HDassert(_io_info->store);
+ HDassert(space);
+ HDassert(iter);
+ HDassert(nelmts > 0);
+ HDassert(_buf);
+
+ /* Set up temporary I/O info object */
+ HDmemcpy(&tmp_io_info, _io_info, sizeof(*_io_info));
+ tmp_io_info.op_type = H5D_IO_OP_READ;
+ tmp_io_info.u.rbuf = _buf;
+
+ /* Allocate the vector I/O arrays */
+ if(tmp_io_info.dxpl_cache->vec_size > H5D_IO_VECTOR_SIZE) {
+ if(NULL == (len = H5FL_SEQ_MALLOC(size_t, tmp_io_info.dxpl_cache->vec_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 0, "can't allocate I/O length vector array")
+ if(NULL == (off = H5FL_SEQ_MALLOC(hsize_t, tmp_io_info.dxpl_cache->vec_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 0, "can't allocate I/O offset vector array")
+ } /* end if */
+ else {
+ len = _len;
+ off = _off;
+ } /* end else */
+
+ /* Loop until all elements are read */
+ while(nelmts > 0) {
+ /* Get list of sequences for selection to read */
+ if(H5S_SELECT_GET_SEQ_LIST(space, H5S_GET_SEQ_LIST_SORTED, iter, tmp_io_info.dxpl_cache->vec_size, nelmts, &nseq, &nelem, off, len) < 0)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, 0, "sequence length generation failed")
+
+ /* Reset the current sequence information */
+ mem_curr_seq = dset_curr_seq = 0;
+ orig_mem_len = mem_len = nelem * iter->elmt_size;
+ mem_off = 0;
+
+ /* Read sequence list in */
+ if((*tmp_io_info.layout_ops.readvv)(&tmp_io_info, nseq, &dset_curr_seq,
+ len, off, (size_t)1, &mem_curr_seq, &mem_len, &mem_off) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_READERROR, 0, "read error")
+
+ /* Update buffer */
+ tmp_io_info.u.rbuf = (uint8_t *)tmp_io_info.u.rbuf + orig_mem_len;
+
+ /* Decrement number of elements left to process */
+ nelmts -= nelem;
+ } /* end while */
+
+done:
+ /* Release resources, if allocated */
+ if(len && len != _len)
+ H5FL_SEQ_FREE(size_t, len);
+ if(off && off != _off)
+ H5FL_SEQ_FREE(hsize_t, off);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5D_gather_file() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_scatter_mem
+ *
+ * Purpose: Scatters NELMTS data points from the scatter buffer
+ * TSCAT_BUF to the application buffer BUF. Each element is
+ * ELMT_SIZE bytes and they are organized in application memory
+ * according to SPACE.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Monday, July 8, 2002
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5D_scatter_mem (const void *_tscat_buf, const H5S_t *space,
+ H5S_sel_iter_t *iter, size_t nelmts, const H5D_dxpl_cache_t *dxpl_cache,
+ void *_buf/*out*/)
+{
+ uint8_t *buf = (uint8_t *)_buf; /* Get local copies for address arithmetic */
+ const uint8_t *tscat_buf = (const uint8_t *)_tscat_buf;
+ hsize_t _off[H5D_IO_VECTOR_SIZE]; /* Array to store sequence offsets */
+ hsize_t *off = NULL; /* Pointer to sequence offsets */
+ size_t _len[H5D_IO_VECTOR_SIZE]; /* Array to store sequence lengths */
+ size_t *len = NULL; /* Pointer to sequence lengths */
+ size_t curr_len; /* Length of bytes left to process in sequence */
+ size_t nseq; /* Number of sequences generated */
+ size_t curr_seq; /* Current sequence being processed */
+ size_t nelem; /* Number of elements used in sequences */
+ herr_t ret_value = SUCCEED; /* Number of elements scattered */
+
+ FUNC_ENTER_NOAPI(H5D_scatter_mem, FAIL)
+
+ /* Check args */
+ HDassert(tscat_buf);
+ HDassert(space);
+ HDassert(iter);
+ HDassert(nelmts > 0);
+ HDassert(buf);
+
+ /* Allocate the vector I/O arrays */
+ if(dxpl_cache->vec_size > H5D_IO_VECTOR_SIZE) {
+ if(NULL == (len = H5FL_SEQ_MALLOC(size_t, dxpl_cache->vec_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O length vector array")
+ if(NULL == (off = H5FL_SEQ_MALLOC(hsize_t, dxpl_cache->vec_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O offset vector array")
+ } /* end if */
+ else {
+ len = _len;
+ off = _off;
+ } /* end else */
+
+ /* Loop until all elements are written */
+ while(nelmts > 0) {
+ /* Get list of sequences for selection to write */
+ if(H5S_SELECT_GET_SEQ_LIST(space, 0, iter, dxpl_cache->vec_size, nelmts, &nseq, &nelem, off, len) < 0)
+ HGOTO_ERROR (H5E_INTERNAL, H5E_UNSUPPORTED, 0, "sequence length generation failed")
+
+ /* Loop, while sequences left to process */
+ for(curr_seq = 0; curr_seq < nseq; curr_seq++) {
+ /* Get the number of bytes in sequence */
+ curr_len = len[curr_seq];
+
+ HDmemcpy(buf + off[curr_seq], tscat_buf, curr_len);
+
+ /* Advance offset in destination buffer */
+ tscat_buf += curr_len;
+ } /* end for */
+
+ /* Decrement number of elements left to process */
+ nelmts -= nelem;
+ } /* end while */
+
+done:
+ /* Release resources, if allocated */
+ if(len && len != _len)
+ H5FL_SEQ_FREE(size_t, len);
+ if(off && off != _off)
+ H5FL_SEQ_FREE(hsize_t, off);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5D_scatter_mem() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_gather_mem
+ *
+ * Purpose: Gathers dataset elements from application memory BUF and
+ * copies them into the gather buffer TGATH_BUF.
+ * Each element is ELMT_SIZE bytes and arranged in application
+ * memory according to SPACE.
+ * The caller is requesting that at most NELMTS be gathered.
+ *
+ * Return: Success: Number of elements copied.
+ * Failure: 0
+ *
+ * Programmer: Quincey Koziol
+ * Monday, June 24, 2002
+ *
+ *-------------------------------------------------------------------------
+ */
+static size_t
+H5D_gather_mem(const void *_buf, const H5S_t *space,
+ H5S_sel_iter_t *iter, size_t nelmts, const H5D_dxpl_cache_t *dxpl_cache,
+ void *_tgath_buf/*out*/)
+{
+ const uint8_t *buf = (const uint8_t *)_buf; /* Get local copies for address arithmetic */
+ uint8_t *tgath_buf = (uint8_t *)_tgath_buf;
+ hsize_t _off[H5D_IO_VECTOR_SIZE]; /* Array to store sequence offsets */
+ hsize_t *off = NULL; /* Pointer to sequence offsets */
+ size_t _len[H5D_IO_VECTOR_SIZE]; /* Array to store sequence lengths */
+ size_t *len = NULL; /* Pointer to sequence lengths */
+ size_t curr_len; /* Length of bytes left to process in sequence */
+ size_t nseq; /* Number of sequences generated */
+ size_t curr_seq; /* Current sequence being processed */
+ size_t nelem; /* Number of elements used in sequences */
+ size_t ret_value = nelmts; /* Number of elements gathered */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_gather_mem)
+
+ /* Check args */
+ HDassert(buf);
+ HDassert(space);
+ HDassert(iter);
+ HDassert(nelmts > 0);
+ HDassert(tgath_buf);
+
+ /* Allocate the vector I/O arrays */
+ if(dxpl_cache->vec_size > H5D_IO_VECTOR_SIZE) {
+ if(NULL == (len = H5FL_SEQ_MALLOC(size_t, dxpl_cache->vec_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 0, "can't allocate I/O length vector array")
+ if(NULL == (off = H5FL_SEQ_MALLOC(hsize_t, dxpl_cache->vec_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 0, "can't allocate I/O offset vector array")
+ } /* end if */
+ else {
+ len = _len;
+ off = _off;
+ } /* end else */
+
+ /* Loop until all elements are written */
+ while(nelmts > 0) {
+ /* Get list of sequences for selection to write */
+ if(H5S_SELECT_GET_SEQ_LIST(space, 0, iter, dxpl_cache->vec_size, nelmts, &nseq, &nelem, off, len) < 0)
+ HGOTO_ERROR (H5E_INTERNAL, H5E_UNSUPPORTED, 0, "sequence length generation failed")
+
+ /* Loop, while sequences left to process */
+ for(curr_seq = 0; curr_seq < nseq; curr_seq++) {
+ /* Get the number of bytes in sequence */
+ curr_len = len[curr_seq];
+
+ HDmemcpy(tgath_buf, buf + off[curr_seq], curr_len);
+
+ /* Advance offset in gather buffer */
+ tgath_buf += curr_len;
+ } /* end for */
+
+ /* Decrement number of elements left to process */
+ nelmts -= nelem;
+ } /* end while */
+
+done:
+ /* Release resources, if allocated */
+ if(len && len != _len)
+ H5FL_SEQ_FREE(size_t, len);
+ if(off && off != _off)
+ H5FL_SEQ_FREE(hsize_t, off);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5D_gather_mem() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_scatgath_read
+ *
+ * Purpose: Perform scatter/gather ead from a contiguous [piece of a] dataset.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, March 6, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5D_scatgath_read(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
+ hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space)
+{
+ const H5D_dxpl_cache_t *dxpl_cache = io_info->dxpl_cache; /* Local pointer to dataset transfer info */
+ void *buf = io_info->u.rbuf; /* Local pointer to application buffer */
+ H5S_sel_iter_t mem_iter; /*memory selection iteration info*/
+ hbool_t mem_iter_init = FALSE; /*memory selection iteration info has been initialized */
+ H5S_sel_iter_t bkg_iter; /*background iteration info*/
+ hbool_t bkg_iter_init = FALSE; /*background iteration info has been initialized */
+ H5S_sel_iter_t file_iter; /*file selection iteration info*/
+ hbool_t file_iter_init = FALSE; /*file selection iteration info has been initialized */
+ hsize_t smine_start; /*strip mine start loc */
+ size_t smine_nelmts; /*elements per strip */
+ herr_t ret_value = SUCCEED; /*return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_scatgath_read)
+
+ /* Sanity check */
+ HDassert(io_info);
+ HDassert(type_info);
+ HDassert(mem_space);
+ HDassert(file_space);
+ HDassert(buf);
+
+ /* Check for NOOP read */
+ if(nelmts == 0)
+ HGOTO_DONE(SUCCEED)
+
+ /* Figure out the strip mine size. */
+ if(H5S_select_iter_init(&file_iter, file_space, type_info->src_type_size) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize file selection information")
+ file_iter_init = TRUE; /*file selection iteration info has been initialized */
+ if(H5S_select_iter_init(&mem_iter, mem_space, type_info->dst_type_size) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize memory selection information")
+ mem_iter_init = TRUE; /*file selection iteration info has been initialized */
+ if(H5S_select_iter_init(&bkg_iter, mem_space, type_info->dst_type_size) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize background selection information")
+ bkg_iter_init = TRUE; /*file selection iteration info has been initialized */
+
+ /* Start strip mining... */
+ for(smine_start = 0; smine_start < nelmts; smine_start += smine_nelmts) {
+ size_t n; /* Elements operated on */
+
+ /* Go figure out how many elements to read from the file */
+ HDassert(H5S_SELECT_ITER_NELMTS(&file_iter) == (nelmts - smine_start));
+ smine_nelmts = (size_t)MIN(type_info->request_nelmts, (nelmts - smine_start));
+
+ /*
+ * Gather the data from disk into the datatype conversion
+ * buffer. Also gather data from application to background buffer
+ * if necessary.
+ */
+
+ /*
+ * Gather data
+ */
+ n = H5D_gather_file(io_info, file_space, &file_iter, smine_nelmts,
+ type_info->tconv_buf/*out*/);
+ if(n != smine_nelmts)
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "file gather failed")
+
+ /* If the source and destination are compound types and subset of each other
+ * and no conversion is needed, copy the data directly into user's buffer and
+ * bypass the rest of steps.
+ */
+ if(H5T_SUBSET_FALSE != type_info->cmpd_subset) {
+ if(H5D_compound_opt_read(smine_nelmts, mem_space, &mem_iter, dxpl_cache,
+ type_info, buf /*out*/) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "datatype conversion failed")
+ } /* end if */
+ else {
+ if(H5T_BKG_YES == type_info->need_bkg) {
+ n = H5D_gather_mem(buf, mem_space, &bkg_iter, smine_nelmts,
+ dxpl_cache, type_info->bkg_buf/*out*/);
+ if(n != smine_nelmts)
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "mem gather failed")
+ } /* end if */
+
+ /*
+ * Perform datatype conversion.
+ */
+ if(H5T_convert(type_info->tpath, type_info->src_type_id, type_info->dst_type_id,
+ smine_nelmts, (size_t)0, (size_t)0, type_info->tconv_buf,
+ type_info->bkg_buf, io_info->dxpl_id) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "datatype conversion failed")
+
+ /* Do the data transform after the conversion (since we're using type mem_type) */
+ if(!type_info->is_xform_noop)
+ if(H5Z_xform_eval(dxpl_cache->data_xform_prop, type_info->tconv_buf, smine_nelmts, type_info->mem_type) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Error performing data transform")
+
+ /*
+ * Scatter the data into memory.
+ */
+ if(H5D_scatter_mem(type_info->tconv_buf, mem_space, &mem_iter,
+ smine_nelmts, dxpl_cache, buf/*out*/) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "scatter failed")
+ } /* end else */
+ } /* end for */
+
+done:
+ /* Release selection iterators */
+ if(file_iter_init) {
+ if(H5S_SELECT_ITER_RELEASE(&file_iter) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
+ } /* end if */
+ if(mem_iter_init) {
+ if(H5S_SELECT_ITER_RELEASE(&mem_iter) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
+ } /* end if */
+ if(bkg_iter_init) {
+ if(H5S_SELECT_ITER_RELEASE(&bkg_iter) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_scatgath_read() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_scatgath_write
+ *
+ * Purpose: Perform scatter/gather write to a contiguous [piece of a] dataset.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, March 6, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5D_scatgath_write(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
+ hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space)
+{
+ const H5D_dxpl_cache_t *dxpl_cache = io_info->dxpl_cache; /* Local pointer to dataset transfer info */
+ const void *buf = io_info->u.wbuf; /* Local pointer to application buffer */
+ H5S_sel_iter_t mem_iter; /*memory selection iteration info*/
+ hbool_t mem_iter_init = FALSE; /*memory selection iteration info has been initialized */
+ H5S_sel_iter_t bkg_iter; /*background iteration info*/
+ hbool_t bkg_iter_init = FALSE; /*background iteration info has been initialized */
+ H5S_sel_iter_t file_iter; /*file selection iteration info*/
+ hbool_t file_iter_init = FALSE; /*file selection iteration info has been initialized */
+ hsize_t smine_start; /*strip mine start loc */
+ size_t smine_nelmts; /*elements per strip */
+ herr_t ret_value = SUCCEED; /*return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_scatgath_write)
+
+ /* Sanity check */
+ HDassert(io_info);
+ HDassert(type_info);
+ HDassert(mem_space);
+ HDassert(file_space);
+ HDassert(buf);
+
+ /* Check for NOOP write */
+ if(nelmts == 0)
+ HGOTO_DONE(SUCCEED)
+
+ /* Figure out the strip mine size. */
+ if(H5S_select_iter_init(&file_iter, file_space, type_info->dst_type_size) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize file selection information")
+ file_iter_init = TRUE; /*file selection iteration info has been initialized */
+ if(H5S_select_iter_init(&mem_iter, mem_space, type_info->src_type_size) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize memory selection information")
+ mem_iter_init = TRUE; /*file selection iteration info has been initialized */
+ if(H5S_select_iter_init(&bkg_iter, file_space, type_info->dst_type_size) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize background selection information")
+ bkg_iter_init = TRUE; /*file selection iteration info has been initialized */
+
+ /* Start strip mining... */
+ for(smine_start = 0; smine_start < nelmts; smine_start += smine_nelmts) {
+ size_t n; /* Elements operated on */
+
+ /* Go figure out how many elements to read from the file */
+ HDassert(H5S_SELECT_ITER_NELMTS(&file_iter) == (nelmts - smine_start));
+ smine_nelmts = (size_t)MIN(type_info->request_nelmts, (nelmts - smine_start));
+
+ /*
+ * Gather data from application buffer into the datatype conversion
+ * buffer. Also gather data from the file into the background buffer
+ * if necessary.
+ */
+ n = H5D_gather_mem(buf, mem_space, &mem_iter, smine_nelmts,
+ dxpl_cache, type_info->tconv_buf/*out*/);
+ if(n != smine_nelmts)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "mem gather failed")
+
+ /* If the source and destination are compound types and the destination is
+ * is a subset of the source and no conversion is needed, copy the data
+ * directly into user's buffer and bypass the rest of steps. If the source
+ * is a subset of the destination, the optimization is done in conversion
+ * function H5T_conv_struct_opt to protect the background data.
+ */
+ if(H5T_SUBSET_DST == type_info->cmpd_subset) {
+ if(H5D_compound_opt_write(smine_nelmts, type_info) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "datatype conversion failed")
+ } /* end if */
+ else {
+ if(H5T_BKG_YES == type_info->need_bkg) {
+ n = H5D_gather_file(io_info, file_space, &bkg_iter, smine_nelmts,
+ type_info->bkg_buf/*out*/);
+ if(n != smine_nelmts)
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "file gather failed")
+ } /* end if */
+
+ /*
+ * Perform datatype conversion.
+ */
+ if(H5T_convert(type_info->tpath, type_info->src_type_id, type_info->dst_type_id,
+ smine_nelmts, (size_t)0, (size_t)0, type_info->tconv_buf,
+ type_info->bkg_buf, io_info->dxpl_id) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "datatype conversion failed")
+
+ /* Do the data transform after the type conversion (since we're using dataset->shared->type). */
+ if(!type_info->is_xform_noop)
+ if(H5Z_xform_eval(dxpl_cache->data_xform_prop, type_info->tconv_buf, smine_nelmts, type_info->dset_type) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Error performing data transform")
+ } /* end else */
+
+ /*
+ * Scatter the data out to the file.
+ */
+ if(H5D_scatter_file(io_info, file_space, &file_iter, smine_nelmts,
+ type_info->tconv_buf) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "scatter failed")
+ } /* end for */
+
+done:
+ /* Release selection iterators */
+ if(file_iter_init) {
+ if(H5S_SELECT_ITER_RELEASE(&file_iter) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
+ } /* end if */
+ if(mem_iter_init) {
+ if(H5S_SELECT_ITER_RELEASE(&mem_iter) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
+ } /* end if */
+ if(bkg_iter_init) {
+ if(H5S_SELECT_ITER_RELEASE(&bkg_iter) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_scatgath_write() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_compound_opt_read
+ *
+ * Purpose: A special optimization case when the source and
+ * destination members are a subset of each other, and
+ * the order is the same, and no conversion is needed.
+ * For example:
+ * struct source { struct destination {
+ * TYPE1 A; --> TYPE1 A;
+ * TYPE2 B; --> TYPE2 B;
+ * TYPE3 C; --> TYPE3 C;
+ * }; TYPE4 D;
+ * TYPE5 E;
+ * };
+ * or
+ * struct destination { struct source {
+ * TYPE1 A; <-- TYPE1 A;
+ * TYPE2 B; <-- TYPE2 B;
+ * TYPE3 C; <-- TYPE3 C;
+ * }; TYPE4 D;
+ * TYPE5 E;
+ * };
+ * The optimization is simply moving data to the appropriate
+ * places in the buffer.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Raymond Lu
+ * 11 June 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_compound_opt_read(size_t nelmts, const H5S_t *space,
+ H5S_sel_iter_t *iter, const H5D_dxpl_cache_t *dxpl_cache,
+ const H5D_type_info_t *type_info, void *user_buf/*out*/)
+{
+ uint8_t *ubuf = (uint8_t *)user_buf; /* Cast for pointer arithmetic */
+ uint8_t *xdbuf; /* Pointer into dataset buffer */
+ hsize_t _off[H5D_IO_VECTOR_SIZE]; /* Array to store sequence offsets */
+ hsize_t *off = NULL; /* Pointer to sequence offsets */
+ size_t _len[H5D_IO_VECTOR_SIZE]; /* Array to store sequence lengths */
+ size_t *len = NULL; /* Pointer to sequence lengths */
+ size_t src_stride, dst_stride, type_size;
+ herr_t ret_value = SUCCEED; /*return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_compound_opt_read)
+
+ /* Check args */
+ HDassert(nelmts > 0);
+ HDassert(space);
+ HDassert(iter);
+ HDassert(dxpl_cache);
+ HDassert(type_info);
+ HDassert(user_buf);
+
+ /* Allocate the vector I/O arrays */
+ if(dxpl_cache->vec_size > H5D_IO_VECTOR_SIZE) {
+ if(NULL == (len = H5FL_SEQ_MALLOC(size_t, dxpl_cache->vec_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O length vector array")
+ if(NULL == (off = H5FL_SEQ_MALLOC(hsize_t, dxpl_cache->vec_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O offset vector array")
+ } /* end if */
+ else {
+ len = _len;
+ off = _off;
+ } /* end else */
+
+ /* Get source & destination strides */
+ src_stride = type_info->src_type_size;
+ dst_stride = type_info->dst_type_size;
+
+ if(H5T_SUBSET_SRC == type_info->cmpd_subset)
+ type_size = src_stride;
+ else {
+ HDassert(H5T_SUBSET_DST == type_info->cmpd_subset);
+ type_size = dst_stride;
+ } /* end else */
+
+ /* Loop until all elements are written */
+ xdbuf = type_info->tconv_buf;
+ while(nelmts > 0) {
+ size_t nseq; /* Number of sequences generated */
+ size_t curr_seq; /* Current sequence being processed */
+ size_t elmtno; /* Element counter */
+
+ /* Get list of sequences for selection to write */
+ if(H5S_SELECT_GET_SEQ_LIST(space, 0, iter, dxpl_cache->vec_size, nelmts, &nseq, &elmtno, off, len) < 0)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, 0, "sequence length generation failed")
+
+ /* Loop, while sequences left to process */
+ for(curr_seq = 0; curr_seq < nseq; curr_seq++) {
+ size_t curr_off; /* Offset of bytes left to process in sequence */
+ size_t curr_len; /* Length of bytes left to process in sequence */
+ size_t curr_nelmts; /* Number of elements to process in sequence */
+ uint8_t *xubuf;
+ size_t i; /* Local index variable */
+
+ /* Get the number of bytes and offset in sequence */
+ curr_len = len[curr_seq];
+ curr_off = off[curr_seq];
+
+ /* Decide the number of elements and position in the buffer. */
+ curr_nelmts = curr_len / dst_stride;
+ xubuf = ubuf + curr_off;
+
+ /* Copy the data into the right place. */
+ for(i = 0; i < curr_nelmts; i++) {
+ HDmemmove(xubuf, xdbuf, type_size);
+
+ /* Update pointers */
+ xdbuf += src_stride;
+ xubuf += dst_stride;
+ } /* end for */
+ } /* end for */
+
+ /* Decrement number of elements left to process */
+ nelmts -= elmtno;
+ } /* end while */
+
+done:
+ /* Release resources, if allocated */
+ if(len && len != _len)
+ H5FL_SEQ_FREE(size_t, len);
+ if(off && off != _off)
+ H5FL_SEQ_FREE(hsize_t, off);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_compound_opt_read() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_compound_opt_write
+ *
+ * Purpose: A special optimization case when the source and
+ * destination members are a subset of each other, and
+ * the order is the same, and no conversion is needed.
+ * For example:
+ * struct source { struct destination {
+ * TYPE1 A; --> TYPE1 A;
+ * TYPE2 B; --> TYPE2 B;
+ * TYPE3 C; --> TYPE3 C;
+ * }; TYPE4 D;
+ * TYPE5 E;
+ * };
+ * or
+ * struct destination { struct source {
+ * TYPE1 A; <-- TYPE1 A;
+ * TYPE2 B; <-- TYPE2 B;
+ * TYPE3 C; <-- TYPE3 C;
+ * }; TYPE4 D;
+ * TYPE5 E;
+ * };
+ * The optimization is simply moving data to the appropriate
+ * places in the buffer.
+ *
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Raymond Lu
+ * 11 June 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_compound_opt_write(size_t nelmts, const H5D_type_info_t *type_info)
+{
+ uint8_t *xsbuf, *xdbuf; /* Source & destination pointers into dataset buffer */
+ size_t src_stride, dst_stride; /* Strides through source & destination datatypes */
+ size_t i; /* Local index variable */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_compound_opt_write)
+
+ /* Check args */
+ HDassert(nelmts > 0);
+ HDassert(type_info);
+
+ /* Initialize values for loop */
+ src_stride = type_info->src_type_size;
+ dst_stride = type_info->dst_type_size;
+
+ /* Loop until all elements are written */
+ xsbuf = (uint8_t *)type_info->tconv_buf;
+ xdbuf = (uint8_t *)type_info->tconv_buf;
+ for(i = 0; i < nelmts; i++) {
+ HDmemmove(xdbuf, xsbuf, dst_stride);
+
+ /* Update pointers */
+ xsbuf += src_stride;
+ xdbuf += dst_stride;
+ } /* end for */
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5D_compound_opt_write() */
+
diff --git a/src/H5Dselect.c b/src/H5Dselect.c
index f08672f..947c81e 100644
--- a/src/H5Dselect.c
+++ b/src/H5Dselect.c
@@ -34,400 +34,37 @@
#include "H5Eprivate.h" /* Error handling */
#include "H5FLprivate.h" /* Free Lists */
+
/****************/
/* Local Macros */
/****************/
+
/******************/
/* Local Typedefs */
/******************/
+
/********************/
/* Local Prototypes */
/********************/
-/* Struct for holding the vectorized I/O operation buffers "loosely" */
-typedef struct {
- enum {
- H5S_SELECT_READ, /* Read selection */
- H5S_SELECT_WRITE /* Write selection */
- } op_type;
- union {
- void *rbuf; /* Buffer for read */
- const void *wbuf; /* Buffer to write */
- } u;
-} H5D_select_buf_t;
/*********************/
/* Package Variables */
/*********************/
+
/*******************/
/* Local Variables */
/*******************/
/* Declare a free list to manage sequences of size_t */
-H5FL_SEQ_DEFINE_STATIC(size_t);
+H5FL_SEQ_DEFINE(size_t);
/* Declare a free list to manage sequences of hsize_t */
-H5FL_SEQ_DEFINE_STATIC(hsize_t);
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_select_fscat
- *
- * Purpose: Scatters dataset elements from the type conversion buffer BUF
- * to the file F where the data points are arranged according to
- * the file dataspace FILE_SPACE and stored according to
- * LAYOUT and EFL. Each element is ELMT_SIZE bytes.
- * The caller is requesting that NELMTS elements are copied.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * Thursday, June 20, 2002
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5D_select_fscat (H5D_io_info_t *io_info,
- const H5S_t *space, H5S_sel_iter_t *iter, size_t nelmts,
- haddr_t chunk_addr, void *chunk/*in*/, const void *_buf)
-{
- const uint8_t *buf=_buf; /* Alias for pointer arithmetic */
- hsize_t _off[H5D_IO_VECTOR_SIZE]; /* Array to store sequence offsets */
- hsize_t *off=NULL; /* Pointer to sequence offsets */
- hsize_t mem_off; /* Offset in memory */
- size_t mem_curr_seq; /* "Current sequence" in memory */
- size_t dset_curr_seq; /* "Current sequence" in dataset */
- size_t _len[H5D_IO_VECTOR_SIZE]; /* Array to store sequence lengths */
- size_t *len=NULL; /* Array to store sequence lengths */
- size_t orig_mem_len, mem_len; /* Length of sequence in memory */
- size_t nseq; /* Number of sequences generated */
- size_t nelem; /* Number of elements used in sequences */
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5D_select_fscat, FAIL);
-
- /* Check args */
- assert (io_info);
- assert (space);
- assert (iter);
- assert (nelmts>0);
- assert (_buf);
- assert(TRUE==H5P_isa_class(io_info->dxpl_id,H5P_DATASET_XFER));
-
- /* Allocate the vector I/O arrays */
- if(io_info->dxpl_cache->vec_size != H5D_IO_VECTOR_SIZE) {
- if((len = H5FL_SEQ_MALLOC(size_t,io_info->dxpl_cache->vec_size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O length vector array");
- if((off = H5FL_SEQ_MALLOC(hsize_t,io_info->dxpl_cache->vec_size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O offset vector array");
- } /* end if */
- else {
- len=_len;
- off=_off;
- } /* end else */
-
- /* Loop until all elements are written */
- while(nelmts>0) {
- /* Get list of sequences for selection to write */
- if(H5S_SELECT_GET_SEQ_LIST(space,H5S_GET_SEQ_LIST_SORTED,iter,io_info->dxpl_cache->vec_size,nelmts,&nseq,&nelem,off,len)<0)
- HGOTO_ERROR (H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed");
-
- /* Reset the current sequence information */
- mem_curr_seq=dset_curr_seq=0;
- orig_mem_len=mem_len=nelem*iter->elmt_size;
- mem_off=0;
-
- /* Write sequence list out */
- if((*io_info->ops.writevv)(io_info, nseq, &dset_curr_seq, len, off, (size_t)1, &mem_curr_seq, &mem_len, &mem_off, chunk_addr, chunk, buf) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_WRITEERROR, FAIL, "write error");
-
- /* Update buffer */
- buf += orig_mem_len;
-
- /* Decrement number of elements left to process */
- nelmts -= nelem;
- } /* end while */
-
-done:
- if(io_info->dxpl_cache->vec_size != H5D_IO_VECTOR_SIZE) {
- if(len!=NULL)
- H5FL_SEQ_FREE(size_t,len);
- if(off!=NULL)
- H5FL_SEQ_FREE(hsize_t,off);
- } /* end if */
- FUNC_LEAVE_NOAPI(ret_value);
-} /* H5D_select_fscat() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_select_fgath
- *
- * Purpose: Gathers data points from file F and accumulates them in the
- * type conversion buffer BUF. The LAYOUT argument describes
- * how the data is stored on disk and EFL describes how the data
- * is organized in external files. ELMT_SIZE is the size in
- * bytes of a datum which this function treats as opaque.
- * FILE_SPACE describes the dataspace of the dataset on disk
- * and the elements that have been selected for reading (via
- * hyperslab, etc). This function will copy at most NELMTS
- * elements.
- *
- * Return: Success: Number of elements copied.
- * Failure: 0
- *
- * Programmer: Quincey Koziol
- * Monday, June 24, 2002
- *
- *-------------------------------------------------------------------------
- */
-size_t
-H5D_select_fgath (H5D_io_info_t *io_info,
- const H5S_t *space, H5S_sel_iter_t *iter, size_t nelmts,
- haddr_t chunk_addr, void *chunk/*in*/, void *_buf/*out*/)
-{
- uint8_t *buf=(uint8_t*)_buf; /* Alias for pointer arithmetic */
- hsize_t _off[H5D_IO_VECTOR_SIZE]; /* Array to store sequence offsets */
- hsize_t *off=NULL; /* Pointer to sequence offsets */
- hsize_t mem_off; /* Offset in memory */
- size_t mem_curr_seq; /* "Current sequence" in memory */
- size_t dset_curr_seq; /* "Current sequence" in dataset */
- size_t _len[H5D_IO_VECTOR_SIZE]; /* Array to store sequence lengths */
- size_t *len=NULL; /* Pointer to sequence lengths */
- size_t orig_mem_len, mem_len; /* Length of sequence in memory */
- size_t nseq; /* Number of sequences generated */
- size_t nelem; /* Number of elements used in sequences */
- size_t ret_value=nelmts; /* Return value */
-
- FUNC_ENTER_NOAPI(H5D_select_fgath, 0);
-
- /* Check args */
- assert (io_info);
- assert (io_info->dset);
- assert (io_info->store);
- assert (space);
- assert (iter);
- assert (nelmts>0);
- assert (_buf);
-
- /* Allocate the vector I/O arrays */
- if(io_info->dxpl_cache->vec_size != H5D_IO_VECTOR_SIZE) {
- if((len = H5FL_SEQ_MALLOC(size_t,io_info->dxpl_cache->vec_size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 0, "can't allocate I/O length vector array");
- if((off = H5FL_SEQ_MALLOC(hsize_t,io_info->dxpl_cache->vec_size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 0, "can't allocate I/O offset vector array");
- } /* end if */
- else {
- len=_len;
- off=_off;
- } /* end else */
-
- /* Loop until all elements are read */
- while(nelmts>0) {
- /* Get list of sequences for selection to read */
- if(H5S_SELECT_GET_SEQ_LIST(space,H5S_GET_SEQ_LIST_SORTED,iter,io_info->dxpl_cache->vec_size,nelmts,&nseq,&nelem,off,len)<0)
- HGOTO_ERROR (H5E_INTERNAL, H5E_UNSUPPORTED, 0, "sequence length generation failed");
-
- /* Reset the current sequence information */
- mem_curr_seq=dset_curr_seq=0;
- orig_mem_len=mem_len=nelem*iter->elmt_size;
- mem_off=0;
-
- /* Read sequence list in */
- if((*io_info->ops.readvv)(io_info, nseq, &dset_curr_seq, len, off, (size_t)1,
- &mem_curr_seq, &mem_len, &mem_off, chunk_addr, chunk, buf) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_READERROR, 0, "read error");
-
- /* Update buffer */
- buf += orig_mem_len;
-
- /* Decrement number of elements left to process */
- nelmts -= nelem;
- } /* end while */
-
-done:
- if(io_info->dxpl_cache->vec_size != H5D_IO_VECTOR_SIZE) {
- if(len!=NULL)
- H5FL_SEQ_FREE(size_t,len);
- if(off!=NULL)
- H5FL_SEQ_FREE(hsize_t,off);
- } /* end if */
- FUNC_LEAVE_NOAPI(ret_value);
-} /* H5D_select_fgath() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_select_mscat
- *
- * Purpose: Scatters NELMTS data points from the scatter buffer
- * TSCAT_BUF to the application buffer BUF. Each element is
- * ELMT_SIZE bytes and they are organized in application memory
- * according to SPACE.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * Monday, July 8, 2002
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5D_select_mscat (const void *_tscat_buf, const H5S_t *space,
- H5S_sel_iter_t *iter, size_t nelmts, const H5D_dxpl_cache_t *dxpl_cache,
- void *_buf/*out*/)
-{
- uint8_t *buf=(uint8_t *)_buf; /* Get local copies for address arithmetic */
- const uint8_t *tscat_buf=(const uint8_t *)_tscat_buf;
- hsize_t _off[H5D_IO_VECTOR_SIZE]; /* Array to store sequence offsets */
- hsize_t *off=NULL; /* Pointer to sequence offsets */
- size_t _len[H5D_IO_VECTOR_SIZE]; /* Array to store sequence lengths */
- size_t *len=NULL; /* Pointer to sequence lengths */
- size_t curr_len; /* Length of bytes left to process in sequence */
- size_t nseq; /* Number of sequences generated */
- size_t curr_seq; /* Current sequence being processed */
- size_t nelem; /* Number of elements used in sequences */
- herr_t ret_value=SUCCEED; /* Number of elements scattered */
-
- FUNC_ENTER_NOAPI(H5D_select_mscat, FAIL);
-
- /* Check args */
- assert (tscat_buf);
- assert (space);
- assert (iter);
- assert (nelmts>0);
- assert (buf);
-
- /* Allocate the vector I/O arrays */
- if(dxpl_cache->vec_size != H5D_IO_VECTOR_SIZE) {
- if((len = H5FL_SEQ_MALLOC(size_t,dxpl_cache->vec_size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O length vector array");
- if((off = H5FL_SEQ_MALLOC(hsize_t,dxpl_cache->vec_size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O offset vector array");
- } /* end if */
- else {
- len=_len;
- off=_off;
- } /* end else */
-
- /* Loop until all elements are written */
- while(nelmts>0) {
- /* Get list of sequences for selection to write */
- if(H5S_SELECT_GET_SEQ_LIST(space,0,iter,dxpl_cache->vec_size,nelmts,&nseq,&nelem,off,len)<0)
- HGOTO_ERROR (H5E_INTERNAL, H5E_UNSUPPORTED, 0, "sequence length generation failed");
-
- /* Loop, while sequences left to process */
- for(curr_seq=0; curr_seq<nseq; curr_seq++) {
- /* Get the number of bytes in sequence */
- curr_len=len[curr_seq];
+H5FL_SEQ_DEFINE(hsize_t);
- HDmemcpy(buf+off[curr_seq],tscat_buf,curr_len);
-
- /* Advance offset in destination buffer */
- tscat_buf+=curr_len;
- } /* end for */
-
- /* Decrement number of elements left to process */
- nelmts -= nelem;
- } /* end while */
-
-done:
- if(dxpl_cache->vec_size != H5D_IO_VECTOR_SIZE) {
- if(len!=NULL)
- H5FL_SEQ_FREE(size_t,len);
- if(off!=NULL)
- H5FL_SEQ_FREE(hsize_t,off);
- } /* end if */
- FUNC_LEAVE_NOAPI(ret_value);
-} /* H5D_select_mscat() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_select_mgath
- *
- * Purpose: Gathers dataset elements from application memory BUF and
- * copies them into the gather buffer TGATH_BUF.
- * Each element is ELMT_SIZE bytes and arranged in application
- * memory according to SPACE.
- * The caller is requesting that at most NELMTS be gathered.
- *
- * Return: Success: Number of elements copied.
- * Failure: 0
- *
- * Programmer: Quincey Koziol
- * Monday, June 24, 2002
- *
- *-------------------------------------------------------------------------
- */
-size_t
-H5D_select_mgath (const void *_buf, const H5S_t *space,
- H5S_sel_iter_t *iter, size_t nelmts, const H5D_dxpl_cache_t *dxpl_cache,
- void *_tgath_buf/*out*/)
-{
- const uint8_t *buf=(const uint8_t *)_buf; /* Get local copies for address arithmetic */
- uint8_t *tgath_buf=(uint8_t *)_tgath_buf;
- hsize_t _off[H5D_IO_VECTOR_SIZE]; /* Array to store sequence offsets */
- hsize_t *off=NULL; /* Pointer to sequence offsets */
- size_t _len[H5D_IO_VECTOR_SIZE]; /* Array to store sequence lengths */
- size_t *len=NULL; /* Pointer to sequence lengths */
- size_t curr_len; /* Length of bytes left to process in sequence */
- size_t nseq; /* Number of sequences generated */
- size_t curr_seq; /* Current sequence being processed */
- size_t nelem; /* Number of elements used in sequences */
- size_t ret_value=nelmts; /* Number of elements gathered */
-
- FUNC_ENTER_NOAPI(H5D_select_mgath, 0);
-
- /* Check args */
- assert (buf);
- assert (space);
- assert (iter);
- assert (nelmts>0);
- assert (tgath_buf);
-
- /* Allocate the vector I/O arrays */
- if(dxpl_cache->vec_size != H5D_IO_VECTOR_SIZE) {
- if((len = H5FL_SEQ_MALLOC(size_t,dxpl_cache->vec_size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 0, "can't allocate I/O length vector array");
- if((off = H5FL_SEQ_MALLOC(hsize_t,dxpl_cache->vec_size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 0, "can't allocate I/O offset vector array");
- } /* end if */
- else {
- len=_len;
- off=_off;
- } /* end else */
-
- /* Loop until all elements are written */
- while(nelmts>0) {
- /* Get list of sequences for selection to write */
- if(H5S_SELECT_GET_SEQ_LIST(space,0,iter,dxpl_cache->vec_size,nelmts,&nseq,&nelem,off,len)<0)
- HGOTO_ERROR (H5E_INTERNAL, H5E_UNSUPPORTED, 0, "sequence length generation failed");
-
- /* Loop, while sequences left to process */
- for(curr_seq=0; curr_seq<nseq; curr_seq++) {
- /* Get the number of bytes in sequence */
- curr_len=len[curr_seq];
-
- HDmemcpy(tgath_buf,buf+off[curr_seq],curr_len);
-
- /* Advance offset in gather buffer */
- tgath_buf+=curr_len;
- } /* end for */
-
- /* Decrement number of elements left to process */
- nelmts -= nelem;
- } /* end while */
-
-done:
- if(dxpl_cache->vec_size != H5D_IO_VECTOR_SIZE) {
- if(len!=NULL)
- H5FL_SEQ_FREE(size_t,len);
- if(off!=NULL)
- H5FL_SEQ_FREE(hsize_t,off);
- } /* end if */
- FUNC_LEAVE_NOAPI(ret_value);
-} /* H5D_select_mgath() */
/*-------------------------------------------------------------------------
@@ -443,11 +80,8 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5D_select_io(H5D_io_info_t *io_info,
- size_t nelmts, size_t elmt_size,
- const H5S_t *file_space, const H5S_t *mem_space,
- haddr_t addr, void *chunk/*in*/,
- const H5D_select_buf_t *io_buf)
+H5D_select_io(const H5D_io_info_t *io_info, size_t elmt_size,
+ size_t nelmts, const H5S_t *file_space, const H5S_t *mem_space)
{
H5S_sel_iter_t mem_iter; /* Memory selection iteration info */
hbool_t mem_iter_init = 0; /* Memory selection iteration info has been initialized */
@@ -475,10 +109,10 @@ H5D_select_io(H5D_io_info_t *io_info,
HDassert(io_info->dset);
HDassert(io_info->store);
HDassert(TRUE == H5P_isa_class(io_info->dxpl_id, H5P_DATASET_XFER));
- HDassert(io_buf->u.rbuf);
+ HDassert(io_info->u.rbuf);
/* Allocate the vector I/O arrays */
- if(io_info->dxpl_cache->vec_size != H5D_IO_VECTOR_SIZE) {
+ if(io_info->dxpl_cache->vec_size > H5D_IO_VECTOR_SIZE) {
if(NULL == (mem_len = H5FL_SEQ_MALLOC(size_t,io_info->dxpl_cache->vec_size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O length vector array")
if(NULL == (mem_off = H5FL_SEQ_MALLOC(hsize_t,io_info->dxpl_cache->vec_size)))
@@ -511,19 +145,17 @@ H5D_select_io(H5D_io_info_t *io_info,
*file_len = *mem_len = elmt_size;
/* Perform I/O on memory and file sequences */
- if(io_buf->op_type == H5S_SELECT_READ) {
- if((tmp_file_len = (*io_info->ops.readvv)(io_info,
+ if(io_info->op_type == H5D_IO_OP_READ) {
+ if((tmp_file_len = (*io_info->layout_ops.readvv)(io_info,
file_nseq, &curr_file_seq, file_len, file_off,
- mem_nseq, &curr_mem_seq, mem_len, mem_off,
- addr, chunk, io_buf->u.rbuf)) < 0)
+ mem_nseq, &curr_mem_seq, mem_len, mem_off)) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_READERROR, FAIL, "read error")
} /* end if */
else {
- HDassert(io_buf->op_type == H5S_SELECT_WRITE);
- if((tmp_file_len = (*io_info->ops.writevv)(io_info,
+ HDassert(io_info->op_type == H5D_IO_OP_WRITE);
+ if((tmp_file_len = (*io_info->layout_ops.writevv)(io_info,
file_nseq, &curr_file_seq, file_len, file_off,
- mem_nseq, &curr_mem_seq, mem_len, mem_off,
- addr, chunk, io_buf->u.wbuf)) < 0)
+ mem_nseq, &curr_mem_seq, mem_len, mem_off)) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_WRITEERROR, FAIL, "write error")
} /* end else */
@@ -571,19 +203,17 @@ H5D_select_io(H5D_io_info_t *io_info,
} /* end if */
/* Perform I/O on memory and file sequences */
- if(io_buf->op_type == H5S_SELECT_READ) {
- if((tmp_file_len = (*io_info->ops.readvv)(io_info,
+ if(io_info->op_type == H5D_IO_OP_READ) {
+ if((tmp_file_len = (*io_info->layout_ops.readvv)(io_info,
file_nseq, &curr_file_seq, file_len, file_off,
- mem_nseq, &curr_mem_seq, mem_len, mem_off,
- addr, chunk, io_buf->u.rbuf)) < 0)
+ mem_nseq, &curr_mem_seq, mem_len, mem_off)) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_READERROR, FAIL, "read error")
} /* end if */
else {
- HDassert(io_buf->op_type == H5S_SELECT_WRITE);
- if((tmp_file_len = (*io_info->ops.writevv)(io_info,
+ HDassert(io_info->op_type == H5D_IO_OP_WRITE);
+ if((tmp_file_len = (*io_info->layout_ops.writevv)(io_info,
file_nseq, &curr_file_seq, file_len, file_off,
- mem_nseq, &curr_mem_seq, mem_len, mem_off,
- addr, chunk, io_buf->u.wbuf)) < 0)
+ mem_nseq, &curr_mem_seq, mem_len, mem_off)) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_WRITEERROR, FAIL, "write error")
} /* end else */
@@ -604,17 +234,15 @@ done:
if(H5S_SELECT_ITER_RELEASE(&mem_iter) < 0)
HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator")
- /* Free vector arrays */
- if(io_info->dxpl_cache->vec_size != H5D_IO_VECTOR_SIZE) {
- if(file_len != NULL)
- H5FL_SEQ_FREE(size_t, file_len);
- if(file_off != NULL)
- H5FL_SEQ_FREE(hsize_t, file_off);
- if(mem_len != NULL)
- H5FL_SEQ_FREE(size_t, mem_len);
- if(mem_off != NULL)
- H5FL_SEQ_FREE(hsize_t, mem_off);
- } /* end if */
+ /* Release vector arrays, if allocated */
+ if(file_len && file_len != _file_len)
+ H5FL_SEQ_FREE(size_t, file_len);
+ if(file_off && file_off != _file_off)
+ H5FL_SEQ_FREE(hsize_t, file_off);
+ if(mem_len && mem_len != _mem_len)
+ H5FL_SEQ_FREE(size_t, mem_len);
+ if(mem_off && mem_off != _mem_off)
+ H5FL_SEQ_FREE(hsize_t, mem_off);
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D_select_io() */
@@ -633,23 +261,17 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5D_select_read(H5D_io_info_t *io_info,
- size_t nelmts, size_t elmt_size,
- const H5S_t *file_space, const H5S_t *mem_space,
- haddr_t addr, void *chunk/*in*/,
- void *buf/*out*/)
+H5D_select_read(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
+ hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space)
{
- H5D_select_buf_t io_buf; /* Selection I/O operation to perform */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5D_select_read, FAIL)
- /* Construct proper I/O operation */
- io_buf.op_type = H5S_SELECT_READ;
- io_buf.u.rbuf = buf;
-
/* Call generic selection operation */
- if(H5D_select_io(io_info, nelmts, elmt_size, file_space, mem_space, addr, chunk, &io_buf) < 0)
+ H5_CHECK_OVERFLOW(nelmts, hsize_t, size_t);
+ if(H5D_select_io(io_info, type_info->src_type_size, (size_t)nelmts,
+ file_space, mem_space) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_READERROR, FAIL, "read error")
done:
@@ -670,23 +292,17 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5D_select_write(H5D_io_info_t *io_info,
- size_t nelmts, size_t elmt_size,
- const H5S_t *file_space, const H5S_t *mem_space,
- haddr_t addr, void *chunk/*in*/,
- const void *buf/*out*/)
+H5D_select_write(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
+ hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space)
{
- H5D_select_buf_t io_buf; /* Selection I/O operation to perform */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5D_select_write, FAIL)
- /* Construct proper I/O operation */
- io_buf.op_type = H5S_SELECT_WRITE;
- io_buf.u.wbuf = buf;
-
/* Call generic selection operation */
- if(H5D_select_io(io_info, nelmts, elmt_size, file_space, mem_space, addr, chunk, &io_buf) < 0)
+ H5_CHECK_OVERFLOW(nelmts, hsize_t, size_t);
+ if(H5D_select_io(io_info, type_info->dst_type_size, (size_t)nelmts,
+ file_space, mem_space) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_WRITEERROR, FAIL, "write error")
done:
diff --git a/src/H5F.c b/src/H5F.c
index cb9e3b8..80c28bc 100644
--- a/src/H5F.c
+++ b/src/H5F.c
@@ -978,6 +978,9 @@ done:
* Programmer: Robb Matzke
* matzke@llnl.gov
* Jul 18 1997
+ * Modifications:
+ * Vailin Choi, April 2, 2008
+ * Free f->extpath
*
*-------------------------------------------------------------------------
*/
@@ -1068,6 +1071,7 @@ H5F_dest(H5F_t *f, hid_t dxpl_id)
/* Free the non-shared part of the file */
f->name = H5MM_xfree(f->name);
+ f->extpath = H5MM_xfree(f->extpath);
f->mtab.child = H5MM_xfree(f->mtab.child);
f->mtab.nalloc = 0;
if(H5FO_top_dest(f) < 0)
@@ -1078,6 +1082,8 @@ H5F_dest(H5F_t *f, hid_t dxpl_id)
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5F_dest() */
+
+
/*-------------------------------------------------------------------------
* Function: H5F_open
@@ -1157,6 +1163,9 @@ H5F_dest(H5F_t *f, hid_t dxpl_id)
* Modified H5F_flush call to take one flag instead of
* multiple Boolean flags.
*
+ * Vailin Choi, 2008-04-02
+ * To formulate path for later searching of target file for external link
+ * via H5_build_extpath().
*-------------------------------------------------------------------------
*/
H5F_t *
@@ -1353,6 +1362,10 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, hid_t d
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "file close degree doesn't match")
} /* end if */
+ /* formulate the absolute path for later search of target file for external link */
+ if (H5_build_extpath(name, &file->extpath) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to build extpath")
+
/* Success */
ret_value = file;
@@ -2140,6 +2153,33 @@ H5F_get_intent(const H5F_t *f)
/*-------------------------------------------------------------------------
+ * Function: H5F_get_extpath
+ *
+ * Purpose: Retrieve the file's 'extpath' flags
+ * This is used by H5L_extern_traverse() to retrieve the main file's location
+ * when searching the target file.
+ *
+ * Return: 'extpath' on success/abort on failure (shouldn't fail)
+ *
+ * Programmer: Vailin Choi, April 2, 2008
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+char *
+H5F_get_extpath(const H5F_t *f)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_get_extpath)
+
+ HDassert(f);
+
+ FUNC_LEAVE_NOAPI(f->extpath)
+} /* end H5F_get_extpath() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5F_sizeof_addr
*
* Purpose: Quick and dirty routine to retrieve the size of the file's size_t
@@ -3618,4 +3658,3 @@ H5Fget_info(hid_t obj_id, H5F_info_t *finfo)
done:
FUNC_LEAVE_API(ret_value)
} /* end H5Fget_info() */
-
diff --git a/src/H5FDmpi.h b/src/H5FDmpi.h
index 90aa0e2..0384018 100644
--- a/src/H5FDmpi.h
+++ b/src/H5FDmpi.h
@@ -42,14 +42,14 @@ typedef enum H5FD_mpio_xfer_t {
H5FD_MPIO_COLLECTIVE
} H5FD_mpio_xfer_t;
-/* Type of I/O for data transfer properties */
+/* Type of chunked dataset I/O */
typedef enum H5FD_mpio_chunk_opt_t {
H5FD_MPIO_CHUNK_DEFAULT = 0,
H5FD_MPIO_CHUNK_ONE_IO, /*zero is the default*/
H5FD_MPIO_CHUNK_MULTI_IO
} H5FD_mpio_chunk_opt_t;
-/* Type of I/O for data transfer properties */
+/* Type of collective I/O */
typedef enum H5FD_mpio_collective_opt_t {
H5FD_MPIO_COLLECTIVE_IO = 0,
H5FD_MPIO_INDIVIDUAL_IO /*zero is the default*/
diff --git a/src/H5FDmpio.c b/src/H5FDmpio.c
index c8087bb..89a8637 100644
--- a/src/H5FDmpio.c
+++ b/src/H5FDmpio.c
@@ -572,15 +572,15 @@ H5Pset_dxpl_mpio_collective_opt(hid_t dxpl_id, H5FD_mpio_collective_opt_t opt_mo
HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a dxpl")
/* Set the transfer mode */
- if (H5P_set(plist,H5D_XFER_MPIO_COLLECTIVE_OPT_NAME,&opt_mode)<0)
+ if(H5P_set(plist, H5D_XFER_MPIO_COLLECTIVE_OPT_NAME, &opt_mode) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to set value")
/* Initialize driver-specific properties */
- ret_value= H5P_set_driver(plist, H5FD_MPIO, NULL);
+ ret_value = H5P_set_driver(plist, H5FD_MPIO, NULL);
done:
FUNC_LEAVE_API(ret_value)
-}
+} /* end H5Pset_dxpl_mpio_collective_opt() */
/*-------------------------------------------------------------------------
@@ -1413,8 +1413,8 @@ H5FD_mpio_read(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t dxpl_id, haddr_t add
int type_size; /* MPI datatype used for I/O's size */
int io_size; /* Actual number of bytes requested */
H5P_genplist_t *plist; /* Property list pointer */
- unsigned use_view_this_time=0;
- herr_t ret_value=SUCCEED;
+ hbool_t use_view_this_time = FALSE;
+ herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(H5FD_mpio_read, FAIL)
@@ -1464,7 +1464,7 @@ H5FD_mpio_read(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t dxpl_id, haddr_t add
MPI_Datatype file_type;
/* Remember that views are used */
- use_view_this_time=TRUE;
+ use_view_this_time = TRUE;
/* prepare for a full-blown xfer using btype, ftype, and disp */
if(H5P_get(plist,H5FD_MPI_XFER_MEM_MPI_TYPE_NAME,&buf_type)<0)
@@ -1487,9 +1487,9 @@ H5FD_mpio_read(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t dxpl_id, haddr_t add
} /* end if */
/* Read the data. */
- if (use_view_this_time) {
+ if(use_view_this_time) {
H5FD_mpio_collective_opt_t coll_opt_mode;
- H5FD_mpio_collective_opt_t xfer_opt_mode;
+
#ifdef H5FDmpio_DEBUG
if (H5FD_mpio_Debug[(int)'t'])
fprintf(stdout, "H5FD_mpio_read: using MPIO collective mode\n");
@@ -1497,28 +1497,23 @@ H5FD_mpio_read(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t dxpl_id, haddr_t add
/* Peek the collective_opt property to check whether the application wants to do IO individually. */
coll_opt_mode = (H5FD_mpio_collective_opt_t)H5P_peek_unsigned(plist, H5D_XFER_MPIO_COLLECTIVE_OPT_NAME);
- /* Peek the xfer_opt_mode property to check whether the application wants to do IO individually. */
- xfer_opt_mode = (H5FD_mpio_collective_opt_t)H5P_peek_unsigned(plist, H5D_XFER_IO_XFER_OPT_MODE_NAME);
-
- if(coll_opt_mode == H5FD_MPIO_COLLECTIVE_IO && xfer_opt_mode == H5FD_MPIO_COLLECTIVE_IO) {
+ if(coll_opt_mode == H5FD_MPIO_COLLECTIVE_IO) {
#ifdef H5FDmpio_DEBUG
- if (H5FD_mpio_Debug[(int)'t'])
- fprintf(stdout, "H5FD_mpio_read: doing MPI collective IO\n");
+ if(H5FD_mpio_Debug[(int)'t'])
+ fprintf(stdout, "H5FD_mpio_read: doing MPI collective IO\n");
#endif
-/* Temporarily change to read_at_all
- if (MPI_SUCCESS!= (mpi_code=MPI_File_read_at_all(file->f, mpi_off, buf, size_i, buf_type, &mpi_stat )))*/
- if (MPI_SUCCESS!= (mpi_code=MPI_File_read_at_all(file->f, mpi_off, buf, size_i, buf_type, &mpi_stat )))
- HMPI_GOTO_ERROR(FAIL, "MPI_File_read_at_all failed", mpi_code)
- }
+ if(MPI_SUCCESS != (mpi_code = MPI_File_read_at_all(file->f, mpi_off, buf, size_i, buf_type, &mpi_stat)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_File_read_at_all failed", mpi_code)
+ } /* end if */
else {
#ifdef H5FDmpio_DEBUG
- if (H5FD_mpio_Debug[(int)'t'])
- fprintf(stdout, "H5FD_mpio_read: doing MPI independent IO\n");
+ if(H5FD_mpio_Debug[(int)'t'])
+ fprintf(stdout, "H5FD_mpio_read: doing MPI independent IO\n");
#endif
- if (MPI_SUCCESS!= (mpi_code=MPI_File_read_at(file->f, mpi_off, buf, size_i, buf_type, &mpi_stat )))
- HMPI_GOTO_ERROR(FAIL, "MPI_File_read_at failed", mpi_code)
- }
+ if(MPI_SUCCESS != (mpi_code = MPI_File_read_at(file->f, mpi_off, buf, size_i, buf_type, &mpi_stat)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_File_read_at failed", mpi_code)
+ } /* end else */
/*
* Reset the file view when we used MPI derived types
@@ -1700,7 +1695,7 @@ H5FD_mpio_write(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr,
int size_i, bytes_written;
int type_size; /* MPI datatype used for I/O's size */
int io_size; /* Actual number of bytes requested */
- unsigned use_view_this_time=0;
+ hbool_t use_view_this_time = FALSE;
H5P_genplist_t *plist; /* Property list pointer */
herr_t ret_value=SUCCEED;
@@ -1718,26 +1713,25 @@ H5FD_mpio_write(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr,
assert(buf);
/* Portably initialize MPI status variable */
- HDmemset(&mpi_stat,0,sizeof(MPI_Status));
+ HDmemset(&mpi_stat, 0, sizeof(MPI_Status));
/* some numeric conversions */
- if (H5FD_mpi_haddr_to_MPIOff(addr, &mpi_off)<0)
+ if(H5FD_mpi_haddr_to_MPIOff(addr, &mpi_off) < 0)
HGOTO_ERROR(H5E_INTERNAL, H5E_BADRANGE, FAIL, "can't convert from haddr to MPI off")
size_i = (int)size;
- if ((hsize_t)size_i != size)
+ if((hsize_t)size_i != size)
HGOTO_ERROR(H5E_INTERNAL, H5E_BADRANGE, FAIL, "can't convert from size to size_i")
#ifdef H5FDmpio_DEBUG
- if (H5FD_mpio_Debug[(int)'w'])
- fprintf(stdout, "in H5FD_mpio_write mpi_off=%ld size_i=%d\n",
- (long)mpi_off, size_i);
+ if(H5FD_mpio_Debug[(int)'w'])
+ fprintf(stdout, "in H5FD_mpio_write mpi_off=%ld size_i=%d\n", (long)mpi_off, size_i);
#endif
/* Obtain the data transfer properties */
if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list")
- if(type==H5FD_MEM_DRAW) {
+ if(type == H5FD_MEM_DRAW) {
H5FD_mpio_xfer_t xfer_mode; /* I/O tranfer mode */
/* Obtain the data transfer properties */
@@ -1749,114 +1743,71 @@ H5FD_mpio_write(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr,
* us to test that btype=ftype=MPI_BYTE (or even MPI_TYPE_NULL, which
* could mean "use MPI_BYTE" by convention).
*/
- if(xfer_mode==H5FD_MPIO_COLLECTIVE) {
+ if(xfer_mode == H5FD_MPIO_COLLECTIVE) {
MPI_Datatype file_type;
/* Remember that views are used */
- use_view_this_time=TRUE;
+ use_view_this_time = TRUE;
/* prepare for a full-blown xfer using btype, ftype, and disp */
- if(H5P_get(plist,H5FD_MPI_XFER_MEM_MPI_TYPE_NAME,&buf_type)<0)
+ if(H5P_get(plist, H5FD_MPI_XFER_MEM_MPI_TYPE_NAME, &buf_type) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get MPI-I/O type property")
- if(H5P_get(plist,H5FD_MPI_XFER_FILE_MPI_TYPE_NAME,&file_type)<0)
+ if(H5P_get(plist, H5FD_MPI_XFER_FILE_MPI_TYPE_NAME, &file_type) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get MPI-I/O type property")
/*
* Set the file view when we are using MPI derived types
*/
/*OKAY: CAST DISCARDS CONST QUALIFIER*/
- if (MPI_SUCCESS != (mpi_code=MPI_File_set_view(file->f, mpi_off, MPI_BYTE, file_type, H5FD_mpi_native_g, file->info)))
+ if(MPI_SUCCESS != (mpi_code = MPI_File_set_view(file->f, mpi_off, MPI_BYTE, file_type, H5FD_mpi_native_g, file->info)))
HMPI_GOTO_ERROR(FAIL, "MPI_File_set_view failed", mpi_code)
/* When using types, use the address as the displacement for
* MPI_File_set_view and reset the address for the read to zero
*/
- mpi_off=0;
+ mpi_off = 0;
} /* end if */
} /* end if */
else {
- unsigned block_before_meta_write=0; /* Whether to block before a metadata write */
-
- /* Check if we need to syncronize all processes before attempting metadata write
- * (Prevents race condition where the process writing the metadata goes ahead
- * and writes the metadata to the file before all the processes have
- * read the data, "transmitting" data from the "future" to the reading
- * process. -QAK )
- *
- * The only time we don't want to block before a metadata write is when
- * we are flushing out a bunch of metadata. Then, we block before the
- * first write and don't block for further writes in the sequence.
- */
- if(H5P_exist_plist(plist,H5AC_BLOCK_BEFORE_META_WRITE_NAME)>0)
- if(H5P_get(plist,H5AC_BLOCK_BEFORE_META_WRITE_NAME,&block_before_meta_write)<0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get H5AC property")
-
-#if 0 /* JRM */
- /* The metadata cache now only writes from process 0, which makes
- * this synchronization incorrect. I'm leaving this code commented
- * out instead of deleting it to remind us that we should re-write
- * this function so that a metadata write from any other process
- * should flag an error.
- * -- JRM 9/1/05
- */
- if(block_before_meta_write)
- if (MPI_SUCCESS!= (mpi_code=MPI_Barrier(file->comm)))
- HMPI_GOTO_ERROR(FAIL, "MPI_Barrier failed", mpi_code)
-#endif /* JRM */
-
- /* Only one process will do the actual write if all procs in comm write same metadata */
- if (file->mpi_rank != H5_PAR_META_WRITE) {
-#ifdef H5FDmpio_DEBUG
- if (H5FD_mpio_Debug[(int)'w']) {
- fprintf(stdout,
- " proc %d: in H5FD_mpio_write (write omitted)\n",
- file->mpi_rank );
- }
-#endif
+ /* Only one process can do the actual metadata write */
+ if(file->mpi_rank != H5_PAR_META_WRITE)
+#ifdef LATER
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "can't write metadata from non-zero rank")
+#else /* LATER */
HGOTO_DONE(SUCCEED) /* skip the actual write */
- } /* end if */
+#endif /* LATER */
} /* end if */
/* Write the data. */
- if (use_view_this_time) {
- H5FD_mpio_collective_opt_t coll_opt_mode;
- H5FD_mpio_collective_opt_t xfer_opt_mode;
+ if(use_view_this_time) {
+ H5FD_mpio_collective_opt_t coll_opt_mode;
+
#ifdef H5FDmpio_DEBUG
- if (H5FD_mpio_Debug[(int)'t'])
+ if(H5FD_mpio_Debug[(int)'t'])
fprintf(stdout, "H5FD_mpio_write: using MPIO collective mode\n");
#endif
/* Peek the collective_opt property to check whether the application wants to do IO individually. */
- coll_opt_mode = (H5FD_mpio_collective_opt_t)H5P_peek_unsigned(plist,H5D_XFER_MPIO_COLLECTIVE_OPT_NAME);
-
- /* Peek the xfer_opt_mode property to check whether the application wants to do IO individually. */
- xfer_opt_mode = (H5FD_mpio_collective_opt_t)H5P_peek_unsigned(plist,H5D_XFER_IO_XFER_OPT_MODE_NAME);
+ coll_opt_mode = (H5FD_mpio_collective_opt_t)H5P_peek_unsigned(plist, H5D_XFER_MPIO_COLLECTIVE_OPT_NAME);
/*OKAY: CAST DISCARDS CONST QUALIFIER*/
- if(coll_opt_mode == H5FD_MPIO_COLLECTIVE_IO && xfer_opt_mode == H5FD_MPIO_COLLECTIVE_IO ) {
+ if(coll_opt_mode == H5FD_MPIO_COLLECTIVE_IO) {
#ifdef H5FDmpio_DEBUG
- if (H5FD_mpio_Debug[(int)'t'])
- fprintf(stdout, "H5FD_mpio_write: doing MPI collective IO\n");
+ if(H5FD_mpio_Debug[(int)'t'])
+ fprintf(stdout, "H5FD_mpio_write: doing MPI collective IO\n");
#endif
- /* Temporarily change to _at
-if (MPI_SUCCESS != (mpi_code=MPI_File_write_at_all(file->f, mpi_off, (void*)buf, size_i, buf_type, &mpi_stat)))
-*/
- if (MPI_SUCCESS != (mpi_code=MPI_File_write_at_all(file->f, mpi_off, (void*)buf, size_i, buf_type, &mpi_stat)))
- HMPI_GOTO_ERROR(FAIL, "MPI_File_write_at_all failed", mpi_code)
- }
+ if(MPI_SUCCESS != (mpi_code = MPI_File_write_at_all(file->f, mpi_off, (void*)buf, size_i, buf_type, &mpi_stat)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_File_write_at_all failed", mpi_code)
+ } /* end if */
else {
#ifdef H5FDmpio_DEBUG
- if (H5FD_mpio_Debug[(int)'t'])
- fprintf(stdout, "H5FD_mpio_write: doing MPI independent IO\n");
+ if(H5FD_mpio_Debug[(int)'t'])
+ fprintf(stdout, "H5FD_mpio_write: doing MPI independent IO\n");
#endif
-
- if (MPI_SUCCESS != (mpi_code=MPI_File_write_at(file->f, mpi_off, (void*)buf, size_i, buf_type, &mpi_stat)))
- HMPI_GOTO_ERROR(FAIL, "MPI_File_write_at failed", mpi_code)
- }
-
+ if(MPI_SUCCESS != (mpi_code = MPI_File_write_at(file->f, mpi_off, (void*)buf, size_i, buf_type, &mpi_stat)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_File_write_at failed", mpi_code)
+ } /* end else */
- /*
- * Reset the file view when we used MPI derived types
- */
+ /* Reset the file view when we used MPI derived types */
/*OKAY: CAST DISCARDS CONST QUALIFIER*/
if(MPI_SUCCESS != (mpi_code = MPI_File_set_view(file->f, (MPI_Offset)0, MPI_BYTE, MPI_BYTE, H5FD_mpi_native_g, file->info)))
HMPI_GOTO_ERROR(FAIL, "MPI_File_set_view failed", mpi_code)
@@ -1872,48 +1823,31 @@ if (MPI_SUCCESS != (mpi_code=MPI_File_write_at_all(file->f, mpi_off, (void*)buf,
* datatype in this call though... (We aren't because using it causes
* the LANL "qsc" machine to dump core - 12/19/03) - QAK]
*/
- if (MPI_SUCCESS != (mpi_code=MPI_Get_elements(&mpi_stat, MPI_BYTE, &bytes_written)))
+ if(MPI_SUCCESS != (mpi_code = MPI_Get_elements(&mpi_stat, MPI_BYTE, &bytes_written)))
HMPI_GOTO_ERROR(FAIL, "MPI_Get_elements failed", mpi_code)
/* Get the type's size */
- if (MPI_SUCCESS != (mpi_code=MPI_Type_size(buf_type,&type_size)))
+ if(MPI_SUCCESS != (mpi_code = MPI_Type_size(buf_type, &type_size)))
HMPI_GOTO_ERROR(FAIL, "MPI_Type_size failed", mpi_code)
/* Compute the actual number of bytes requested */
- io_size=type_size*size_i;
+ io_size = type_size * size_i;
/* Check for write failure */
- if (bytes_written != io_size)
+ if(bytes_written != io_size)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file write failed")
/* Forget the EOF value (see H5FD_mpio_get_eof()) --rpm 1999-08-06 */
file->eof = HADDR_UNDEF;
done:
-
-#if 0 /* JRM */
- /* Since metadata writes are now done by process 0 only, this broadcast
- * is no longer needed. I leave it in and commented out to remind us
- * that we need to re-work this function to reflect this reallity.
- *
- * -- JRM 9/1/05
- */
- /* if only one process writes, need to broadcast the ret_value to
- * other processes
- */
- if(type != H5FD_MEM_DRAW) {
- if(MPI_SUCCESS != (mpi_code = MPI_Bcast(&ret_value, (int)sizeof(ret_value), MPI_BYTE, H5_PAR_META_WRITE, file->comm)))
- HMPI_DONE_ERROR(FAIL, "MPI_Bcast failed", mpi_code)
- } /* end if */
-#endif /* JRM */
-
#ifdef H5FDmpio_DEBUG
- if (H5FD_mpio_Debug[(int)'t'])
+ if(H5FD_mpio_Debug[(int)'t'])
fprintf(stdout, "proc %d: Leaving H5FD_mpio_write with ret_value=%d\n",
file->mpi_rank, ret_value );
#endif
FUNC_LEAVE_NOAPI(ret_value)
-}
+} /* end H5FD_mpio_write() */
/*-------------------------------------------------------------------------
diff --git a/src/H5FScache.c b/src/H5FScache.c
index 74a9aab..8ad9631 100644
--- a/src/H5FScache.c
+++ b/src/H5FScache.c
@@ -606,7 +606,7 @@ HDfprintf(stderr, "%s: fspace->addr = %a, fs_addr = %a\n", FUNC, fspace->addr, f
unsigned sect_cnt_size; /* The size of the section size counts */
/* Compute the size of the section counts */
- sect_cnt_size = MAX(1, (H5V_log2_gen(fspace->serial_sect_count) + 7) / 8);
+ sect_cnt_size = H5V_limit_enc_size((uint64_t)fspace->serial_sect_count);
#ifdef QAK
HDfprintf(stderr, "%s: sect_cnt_size = %u\n", FUNC, sect_cnt_size);
HDfprintf(stderr, "%s: fspace->sect_len_size = %u\n", FUNC, fspace->sect_len_size);
@@ -905,7 +905,7 @@ HDfprintf(stderr, "%s: sinfo->fspace->addr = %a\n", FUNC, sinfo->fspace->addr);
/* Set up user data for iterator */
udata.sinfo = sinfo;
udata.p = &p;
- udata.sect_cnt_size = MAX(1, (H5V_log2_gen(sinfo->fspace->serial_sect_count) + 7) / 8);
+ udata.sect_cnt_size = H5V_limit_enc_size((uint64_t)sinfo->fspace->serial_sect_count);
#ifdef QAK
HDfprintf(stderr, "%s: udata.sect_cnt_size = %u\n", FUNC, udata.sect_cnt_size);
#endif /* QAK */
diff --git a/src/H5FSsection.c b/src/H5FSsection.c
index c589aa0..34da067 100644
--- a/src/H5FSsection.c
+++ b/src/H5FSsection.c
@@ -147,7 +147,7 @@ H5FS_sinfo_new(H5F_t *f, H5FS_t *fspace)
sinfo->nbins = H5V_log2_gen(fspace->max_sect_size);
sinfo->sect_prefix_size = H5FS_SINFO_PREFIX_SIZE(f);
sinfo->sect_off_size = (fspace->max_sect_addr + 7) / 8;
- sinfo->sect_len_size = (H5V_log2_gen(fspace->max_sect_size) + 7) / 8;
+ sinfo->sect_len_size = H5V_limit_enc_size((uint64_t)fspace->max_sect_size);
sinfo->fspace = fspace;
#ifdef QAK
HDfprintf(stderr, "%s: sinfo->nbins = %u\n", FUNC, sinfo->nbins);
@@ -1300,7 +1300,7 @@ HDfprintf(stderr, "%s: fspace->sinfo->serial_size_count = %Zu\n", FUNC, fspace->
HDfprintf(stderr, "%s: fspace->sinfo->serial_size_count = %Zu\n", FUNC, fspace->sinfo->serial_size_count);
HDfprintf(stderr, "%s: fspace->serial_sect_count = %Hu\n", FUNC, fspace->serial_sect_count);
#endif /* QAK */
- sect_buf_size += fspace->sinfo->serial_size_count * MAX(1, ((H5V_log2_gen(fspace->serial_sect_count) + 7) / 8));
+ sect_buf_size += fspace->sinfo->serial_size_count * H5V_limit_enc_size((uint64_t)fspace->serial_sect_count);
/* Size for each differently sized serializable section */
sect_buf_size += fspace->sinfo->serial_size_count * fspace->sinfo->sect_len_size;
diff --git a/src/H5Fpkg.h b/src/H5Fpkg.h
index 3f10e1a..288ef8a 100644
--- a/src/H5Fpkg.h
+++ b/src/H5Fpkg.h
@@ -142,6 +142,7 @@ typedef struct H5F_mtab_t {
struct H5F_t {
unsigned intent; /* The flags passed to H5F_open()*/
char *name; /* Name used to open file */
+ char *extpath; /* Path for searching target external link file */
H5F_file_t *shared; /* The shared file info */
unsigned nopen_objs; /* Number of open object headers*/
H5FO_t *obj_count; /* # of time each object is opened through top file structure */
diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h
index 1044b14..27b45f2 100644
--- a/src/H5Fprivate.h
+++ b/src/H5Fprivate.h
@@ -265,6 +265,7 @@ typedef struct H5F_t H5F_t;
#define H5F_GC_REF(F) ((F)->shared->gc_ref)
#define H5F_USE_LATEST_FORMAT(F) ((F)->shared->latest_format)
#define H5F_INTENT(F) ((F)->intent)
+#define H5F_EXTPATH(F) ((F)->extpath)
#define H5F_GET_FC_DEGREE(F) ((F)->shared->fc_degree)
#define H5F_STORE_MSG_CRT_IDX(F) ((F)->shared->store_msg_crt_idx)
#define H5F_GET_FILENO(F,FILENUM) ((FILENUM) = (F)->shared->lf->fileno)
@@ -284,6 +285,7 @@ typedef struct H5F_t H5F_t;
#define H5F_GC_REF(F) (H5F_gc_ref(F))
#define H5F_USE_LATEST_FORMAT(F) (H5F_use_latest_format(F))
#define H5F_INTENT(F) (H5F_get_intent(F))
+#define H5F_EXTPATH(F) (H5F_get_extpath(F))
#define H5F_GET_FC_DEGREE(F) (H5F_get_fc_degree(F))
#define H5F_STORE_MSG_CRT_IDX(F) (H5F_store_msg_crt_idx(F))
#define H5F_GET_FILENO(F,FILENUM) (H5F_get_filenum((F), &(FILENUM)))
@@ -417,6 +419,7 @@ H5_DLL herr_t H5F_try_close(H5F_t *f);
H5_DLL hid_t H5F_get_driver_id(const H5F_t *f);
H5_DLL hid_t H5F_get_access_plist(H5F_t *f);
H5_DLL unsigned H5F_get_intent(const H5F_t *f);
+H5_DLL char *H5F_get_extpath(const H5F_t *f);
H5_DLL herr_t H5F_get_fileno(const H5F_t *f, unsigned long *filenum);
H5_DLL hid_t H5F_get_id(H5F_t *file);
H5_DLL unsigned H5F_get_obj_count(const H5F_t *f, unsigned types);
diff --git a/src/H5HFhdr.c b/src/H5HFhdr.c
index c1b856b..60d5002 100644
--- a/src/H5HFhdr.c
+++ b/src/H5HFhdr.c
@@ -225,7 +225,7 @@ H5HF_hdr_finish_init_phase1(H5HF_hdr_t *hdr)
/* Set the size of heap IDs */
hdr->heap_len_size = MIN(hdr->man_dtable.max_dir_blk_off_size,
- ((H5V_log2_gen((uint64_t)hdr->max_man_size) + 7) / 8));
+ H5V_limit_enc_size((uint64_t)hdr->max_man_size));
done:
FUNC_LEAVE_NOAPI(ret_value)
diff --git a/src/H5HFiblock.c b/src/H5HFiblock.c
index 70133aa..7fedc48 100644
--- a/src/H5HFiblock.c
+++ b/src/H5HFiblock.c
@@ -1591,7 +1591,7 @@ done:
*/
herr_t
H5HF_man_iblock_size(H5F_t *f, hid_t dxpl_id, H5HF_hdr_t *hdr, haddr_t iblock_addr,
- unsigned nrows, hsize_t *heap_size)
+ unsigned nrows, H5HF_indirect_t *par_iblock, unsigned par_entry, hsize_t *heap_size)
{
H5HF_indirect_t *iblock = NULL; /* Pointer to indirect block */
hbool_t did_protect; /* Whether we protected the indirect block or not */
@@ -1608,7 +1608,7 @@ H5HF_man_iblock_size(H5F_t *f, hid_t dxpl_id, H5HF_hdr_t *hdr, haddr_t iblock_ad
HDassert(heap_size);
/* Protect the indirect block */
- if(NULL == (iblock = H5HF_man_iblock_protect(hdr, dxpl_id, iblock_addr, nrows, NULL, 0, FALSE, H5AC_READ, &did_protect)))
+ if(NULL == (iblock = H5HF_man_iblock_protect(hdr, dxpl_id, iblock_addr, nrows, par_iblock, par_entry, FALSE, H5AC_READ, &did_protect)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load fractal heap indirect block")
/* Accumulate size of this indirect block */
@@ -1624,13 +1624,14 @@ H5HF_man_iblock_size(H5F_t *f, hid_t dxpl_id, H5HF_hdr_t *hdr, haddr_t iblock_ad
entry = hdr->man_dtable.max_direct_rows * hdr->man_dtable.cparam.width;
first_row_bits = H5V_log2_of2((uint32_t)hdr->man_dtable.cparam.start_block_size) +
H5V_log2_of2(hdr->man_dtable.cparam.width);
- num_indirect_rows = (H5V_log2_gen(hdr->man_dtable.row_block_size[u]) - first_row_bits) + 1;
+ num_indirect_rows =
+ (H5V_log2_gen(hdr->man_dtable.row_block_size[hdr->man_dtable.max_direct_rows]) - first_row_bits) + 1;
for(u = hdr->man_dtable.max_direct_rows; u < iblock->nrows; u++, num_indirect_rows++) {
size_t v; /* Local index variable */
for(v = 0; v < hdr->man_dtable.cparam.width; v++, entry++)
if(H5F_addr_defined(iblock->ents[entry].addr))
- if(H5HF_man_iblock_size(f, dxpl_id, hdr, iblock->ents[entry].addr, num_indirect_rows, heap_size) < 0)
+ if(H5HF_man_iblock_size(f, dxpl_id, hdr, iblock->ents[entry].addr, num_indirect_rows, iblock, entry, heap_size) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to get fractal heap storage info for indirect block")
} /* end for */
} /* end if */
@@ -1639,6 +1640,7 @@ done:
/* Release the indirect block */
if(iblock && H5HF_man_iblock_unprotect(iblock, dxpl_id, H5AC__NO_FLAGS_SET, did_protect) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block")
+ iblock = NULL;
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HF_man_iblock_size() */
diff --git a/src/H5HFpkg.h b/src/H5HFpkg.h
index 702ce08..fd332e5 100644
--- a/src/H5HFpkg.h
+++ b/src/H5HFpkg.h
@@ -601,7 +601,7 @@ H5_DLL herr_t H5HF_man_iblock_delete(H5HF_hdr_t *hdr, hid_t dxpl_id,
haddr_t iblock_addr, unsigned iblock_nrows, H5HF_indirect_t *par_iblock,
unsigned par_entry);
H5_DLL herr_t H5HF_man_iblock_size(H5F_t *f, hid_t dxpl_id, H5HF_hdr_t *hdr,
- haddr_t iblock_addr, unsigned nrows, hsize_t *heap_size/*out*/);
+ haddr_t iblock_addr, unsigned nrows, H5HF_indirect_t *par_iblock, unsigned par_entry, hsize_t *heap_size/*out*/);
/* Direct block routines */
H5_DLL herr_t H5HF_man_dblock_new(H5HF_hdr_t *fh, hid_t dxpl_id, size_t request,
diff --git a/src/H5HFstat.c b/src/H5HFstat.c
index 2e3e189..d151b47 100644
--- a/src/H5HFstat.c
+++ b/src/H5HFstat.c
@@ -128,6 +128,7 @@ H5HF_size(const H5HF_t *fh, hid_t dxpl_id, hsize_t *heap_size)
{
H5HF_hdr_t *hdr; /* Fractal heap header */
herr_t ret_value = SUCCEED; /* Return value */
+ hsize_t meta_size = 0; /* free space storage size */
FUNC_ENTER_NOAPI(H5HF_size, FAIL)
@@ -147,7 +148,7 @@ H5HF_size(const H5HF_t *fh, hid_t dxpl_id, hsize_t *heap_size)
/* Check for indirect blocks for managed objects */
if(H5F_addr_defined(hdr->man_dtable.table_addr) && hdr->man_dtable.curr_root_rows != 0)
- if(H5HF_man_iblock_size(hdr->f, dxpl_id, hdr, hdr->man_dtable.table_addr, hdr->man_dtable.curr_root_rows, heap_size) < 0)
+ if(H5HF_man_iblock_size(hdr->f, dxpl_id, hdr, hdr->man_dtable.table_addr, hdr->man_dtable.curr_root_rows, NULL, 0, heap_size) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "unable to get fractal heap storage info for indirect block")
/* Get B-tree storage for huge objects in fractal heap */
@@ -172,9 +173,11 @@ H5HF_size(const H5HF_t *fh, hid_t dxpl_id, hsize_t *heap_size)
} /* end if */
/* Get storage for free-space tracking info */
- if(H5F_addr_defined(hdr->fs_addr))
- if(H5HF_space_size(hdr, dxpl_id, heap_size) < 0)
+ if(H5F_addr_defined(hdr->fs_addr)) {
+ if(H5HF_space_size(hdr, dxpl_id, &meta_size) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTGET, FAIL, "can't retrieve FS meta storage info")
+ *heap_size += meta_size;
+ }
done:
FUNC_LEAVE_NOAPI(ret_value)
diff --git a/src/H5Lexternal.c b/src/H5Lexternal.c
index 5a8eb33..4e355bb 100644
--- a/src/H5Lexternal.c
+++ b/src/H5Lexternal.c
@@ -76,6 +76,81 @@ H5L_init_extern_interface(void)
} /* H5L_init_extern_interface() */
+
+/*--------------------------------------------------------------------------
+ * Function: H5L_getenv_prefix_name --
+ *
+ * Purpose: Get the first pathname in the list of pathnames stored in ENV_PREFIX,
+ * which is separated by the environment delimiter.
+ * ENV_PREFIX is modified to point to the remaining pathnames
+ * in the list.
+ *
+ * Return: A pointer to a pathname
+ *
+ * Programmer: Vailin Choi, April 2, 2008
+ *
+--------------------------------------------------------------------------*/
+static char *
+H5L_getenv_prefix_name(char **env_prefix/*in,out*/)
+{
+ char *retptr=NULL;
+ char *strret=NULL;
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5L_getenv_prefix_name)
+
+ strret = HDstrchr(*env_prefix, COLON_SEPC);
+ if (strret == NULL) {
+ retptr = *env_prefix;
+ *env_prefix = strret;
+ } else {
+ retptr = *env_prefix;
+ *env_prefix = strret + 1;
+ *strret = '\0';
+ }
+ return(retptr);
+ FUNC_LEAVE_NOAPI(retptr)
+}
+
+
+/*--------------------------------------------------------------------------
+ * Function: H5L_build_name
+ *
+ * Purpose: Prepend PREFIX to FILE_NAME and store in FULL_NAME
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Vailin Choi, April 2, 2008
+ *
+--------------------------------------------------------------------------*/
+static herr_t
+H5L_build_name(char *prefix, char *file_name, char **full_name/*out*/)
+{
+ size_t prefix_len; /* length of prefix */
+ size_t fname_len; /* Length of external link file name */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5L_build_name)
+
+ prefix_len = HDstrlen(prefix);
+ fname_len = HDstrlen(file_name);
+
+ /* Allocate a buffer to hold the filename + prefix + possibly the delimiter + terminating null byte */
+ if(NULL == (*full_name = H5MM_malloc(prefix_len + fname_len + 2)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate filename buffer")
+
+ /* Copy the prefix into the buffer */
+ HDstrcpy(*full_name, prefix);
+ if (!CHECK_DELIMITER(prefix[prefix_len-1]))
+ HDstrcat(*full_name, DIR_SEPS);
+
+ /* Add the external link's filename to the prefix supplied */
+ HDstrcat(*full_name, file_name);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5L_build_name() */
+
+
/*-------------------------------------------------------------------------
* Function: H5L_extern_traverse
*
@@ -92,6 +167,10 @@ H5L_init_extern_interface(void)
*
* Programmer: James Laird
* Monday, July 10, 2006
+ * Modifications:
+ * Vailin Choi, April 2, 2008
+ * Add handling to search for the target file
+ * See description in RM: H5Lcreate_external
*
*-------------------------------------------------------------------------
*/
@@ -114,6 +193,11 @@ H5L_extern_traverse(const char UNUSED *link_name, hid_t cur_group,
hid_t ext_obj = -1; /* ID for external link's object */
hid_t ret_value; /* Return value */
+ char *tempname=NULL, *ptr=NULL, *extpath=NULL;
+ char *env_prefix=NULL, *tmp_env_prefix=NULL;
+ char *out_prefix_name=NULL, *pp=NULL;
+
+
FUNC_ENTER_NOAPI(H5L_extern_traverse, FAIL)
/* Sanity checks */
@@ -135,28 +219,6 @@ H5L_extern_traverse(const char UNUSED *link_name, hid_t cur_group,
if(NULL == (plist = H5P_object_verify(lapl_id, H5P_LINK_ACCESS)))
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
- /* Get the current prefix */
- if(H5P_get(plist, H5L_ACS_ELINK_PREFIX_NAME, &my_prefix) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get external link prefix")
-
- /* Check for prefix being set, if so, prepend it to the filename */
- if(my_prefix) {
- size_t prefix_len = HDstrlen(my_prefix);
-
- /* Allocate a buffer to hold the filename plus prefix */
- if(NULL == (full_name = H5MM_malloc(prefix_len + fname_len + 1)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate filename buffer")
-
- /* Copy the prefix into the buffer */
- HDstrcpy(full_name, my_prefix);
-
- /* Add the external link's filename to the prefix supplied */
- HDstrcat(full_name, (const char *)p);
-
- /* Point to name w/prefix */
- file_name = full_name;
- } /* end if */
-
/* Get the location for the group holding the external link */
if(H5G_loc(cur_group, &loc) < 0)
HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "can't get object location")
@@ -183,10 +245,92 @@ H5L_extern_traverse(const char UNUSED *link_name, hid_t cur_group,
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set file close degree")
} /* end if */
- /* Open the external file */
- /* (extra work with file intent to mask off inappropriate flags) */
- if(NULL == (ext_file = H5F_open(file_name, ((intent & H5F_ACC_RDWR) ? H5F_ACC_RDWR : H5F_ACC_RDONLY), H5P_FILE_CREATE_DEFAULT, fapl_id, H5AC_dxpl_id)))
- HGOTO_ERROR(H5E_LINK, H5E_CANTOPENFILE, FAIL, "unable to open external file")
+ /*
+ * Start searching for the target file
+ */
+ if ((tempname=H5MM_strdup(file_name)) == NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+
+ /* target file_name is an absolute pathname: see RM for detailed description */
+ if (CHECK_ABSOLUTE(file_name) || CHECK_ABS_PATH(file_name)) {
+ if(NULL == (ext_file = H5F_open(file_name, ((intent & H5F_ACC_RDWR) ? H5F_ACC_RDWR : H5F_ACC_RDONLY),
+ H5P_FILE_CREATE_DEFAULT, fapl_id, H5AC_dxpl_id))) {
+ H5E_clear_stack(NULL);
+ /* get last component of file_name */
+ GET_LAST_DELIMITER(file_name, ptr)
+ HDassert(ptr);
+ HDstrcpy(tempname, ++ptr);
+ }
+ } else if (CHECK_ABS_DRIVE(file_name)) {
+ if(NULL == (ext_file = H5F_open(file_name, ((intent & H5F_ACC_RDWR) ? H5F_ACC_RDWR : H5F_ACC_RDONLY),
+ H5P_FILE_CREATE_DEFAULT, fapl_id, H5AC_dxpl_id))) {
+ H5E_clear_stack(NULL);
+ /* strip "<drive-letter>:" */
+ HDstrcpy(tempname, &file_name[2]);
+ }
+ }
+
+ /* try searching from paths set in the environment variable */
+ if ((ext_file == NULL) && (env_prefix=HDgetenv("HDF5_EXT_PREFIX"))) {
+
+ tmp_env_prefix = H5MM_strdup(env_prefix);
+ pp = tmp_env_prefix;
+
+ while ((tmp_env_prefix) && (*tmp_env_prefix)) {
+ out_prefix_name = H5L_getenv_prefix_name(&tmp_env_prefix/*in,out*/);
+ if ((out_prefix_name) && (*out_prefix_name)) {
+
+ if (H5L_build_name(out_prefix_name, tempname, &full_name/*out*/) < 0)
+ HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "can't prepend prefix to filename")
+
+ ext_file = H5F_open(full_name, ((intent & H5F_ACC_RDWR) ? H5F_ACC_RDWR : H5F_ACC_RDONLY),
+ H5P_FILE_CREATE_DEFAULT, fapl_id, H5AC_dxpl_id);
+ if (full_name)
+ H5MM_xfree(full_name);
+ if (ext_file != NULL)
+ break;
+ H5E_clear_stack(NULL);
+ }
+ } /* end while */
+ if (pp)
+ H5MM_xfree(pp);
+ }
+
+ /* try searching from property list */
+ if (ext_file == NULL) {
+ if(H5P_get(plist, H5L_ACS_ELINK_PREFIX_NAME, &my_prefix) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get external link prefix")
+ if (my_prefix) {
+ if (H5L_build_name(my_prefix, tempname, &full_name/*out*/) < 0)
+ HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "can't prepend prefix to filename")
+ if ((ext_file=H5F_open(full_name, ((intent & H5F_ACC_RDWR) ? H5F_ACC_RDWR : H5F_ACC_RDONLY),
+ H5P_FILE_CREATE_DEFAULT, fapl_id, H5AC_dxpl_id)) == NULL)
+ H5E_clear_stack(NULL);
+ if (full_name)
+ H5MM_xfree(full_name);
+ }
+ }
+
+ /* try searching from main file's "extpath":see description in H5F_open() & H5_build_extpath() */
+ if ((ext_file == NULL) && (extpath=H5F_EXTPATH(loc.oloc->file))) {
+ if (H5L_build_name(extpath, tempname, &full_name/*out*/) < 0)
+ HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "can't prepend prefix to filename")
+ if ((ext_file = H5F_open(full_name, ((intent & H5F_ACC_RDWR) ? H5F_ACC_RDWR : H5F_ACC_RDONLY),
+ H5P_FILE_CREATE_DEFAULT, fapl_id, H5AC_dxpl_id)) == NULL)
+ H5E_clear_stack(NULL);
+ if (full_name)
+ H5MM_xfree(full_name);
+ }
+
+ /* try the relative file_name stored in tempname */
+ if (ext_file == NULL) {
+ if ((ext_file=H5F_open(tempname, ((intent & H5F_ACC_RDWR) ? H5F_ACC_RDWR : H5F_ACC_RDONLY),
+ H5P_FILE_CREATE_DEFAULT, fapl_id, H5AC_dxpl_id)) == NULL)
+ HGOTO_ERROR(H5E_LINK, H5E_CANTOPENFILE, FAIL, "unable to open external file")
+ }
+
+ if (tempname)
+ H5MM_xfree(tempname);
/* Increment the number of open objects, to hold the file open */
H5F_incr_nopen_objs(ext_file);
@@ -219,10 +363,6 @@ done:
if(ext_file && H5F_try_close(ext_file) < 0)
HDONE_ERROR(H5E_LINK, H5E_CANTCLOSEFILE, FAIL, "problem closing external file")
- /* Free full_name if it's been allocated */
- if(full_name)
- H5MM_xfree(full_name);
-
/* Close object if it's open and something failed */
if(ret_value < 0 && ext_obj >= 0 && H5I_dec_ref(ext_obj) < 0)
HDONE_ERROR(H5E_ATOM, H5E_CANTRELEASE, FAIL, "unable to close atom for external object")
diff --git a/src/H5Odtype.c b/src/H5Odtype.c
index ac07edf..ba343bc 100644
--- a/src/H5Odtype.c
+++ b/src/H5Odtype.c
@@ -232,10 +232,11 @@ H5O_dtype_decode_helper(H5F_t *f, const uint8_t **pp, H5T_t *dt)
case H5T_COMPOUND:
{
unsigned offset_nbytes; /* Size needed to encode member offsets */
+ size_t max_memb_pos = 0; /* Maximum member covered, so far */
unsigned j;
/* Compute the # of bytes required to store a member offset */
- offset_nbytes = (H5V_log2_gen((uint64_t)dt->shared->size) + 7) / 8;
+ offset_nbytes = H5V_limit_enc_size((uint64_t)dt->shared->size);
/*
* Compound datatypes...
@@ -336,6 +337,18 @@ H5O_dtype_decode_helper(H5F_t *f, const uint8_t **pp, H5T_t *dt)
/* Set the field datatype (finally :-) */
dt->shared->u.compnd.memb[i].type = temp_type;
+ /* Check if this field overlaps with a prior field */
+ /* (probably indicates that the file is corrupt) */
+ if(i > 0 && dt->shared->u.compnd.memb[i].offset < max_memb_pos) {
+ for(j = 0; j < i; j++)
+ if(dt->shared->u.compnd.memb[i].offset >= dt->shared->u.compnd.memb[j].offset
+ && dt->shared->u.compnd.memb[i].offset < (dt->shared->u.compnd.memb[j].offset + dt->shared->u.compnd.memb[j].size))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, FAIL, "member overlaps with previous member")
+ } /* end if */
+
+ /* Update the maximum member position covered */
+ max_memb_pos = MAX(max_memb_pos, (dt->shared->u.compnd.memb[i].offset + dt->shared->u.compnd.memb[i].size));
+
/* Check if the datatype stayed packed */
if(dt->shared->u.compnd.packed) {
/* Check if the member type is packed */
@@ -734,7 +747,7 @@ H5O_dtype_encode_helper(const H5F_t *f, uint8_t **pp, const H5T_t *dt)
unsigned offset_nbytes; /* Size needed to encode member offsets */
/* Compute the # of bytes required to store a member offset */
- offset_nbytes = (H5V_log2_gen((uint64_t)dt->shared->size) + 7) / 8;
+ offset_nbytes = H5V_limit_enc_size((uint64_t)dt->shared->size);
/*
* Compound datatypes...
@@ -1097,7 +1110,7 @@ H5O_dtype_size(const H5F_t *f, const void *_mesg)
unsigned offset_nbytes; /* Size needed to encode member offsets */
/* Compute the # of bytes required to store a member offset */
- offset_nbytes = (H5V_log2_gen((uint64_t)dt->shared->size) + 7) / 8;
+ offset_nbytes = H5V_limit_enc_size((uint64_t)dt->shared->size);
/* Compute the total size needed to encode compound datatype */
for(u = 0; u < dt->shared->u.compnd.nmembs; u++) {
diff --git a/src/H5Pdxpl.c b/src/H5Pdxpl.c
index 6affcad..8bc263a 100644
--- a/src/H5Pdxpl.c
+++ b/src/H5Pdxpl.c
@@ -90,9 +90,6 @@
/* Definitions for I/O transfer mode property */
#define H5D_XFER_IO_XFER_MODE_SIZE sizeof(H5FD_mpio_xfer_t)
#define H5D_XFER_IO_XFER_MODE_DEF H5FD_MPIO_INDEPENDENT
-/* Definitions for I/O optimization transfer mode property(using MPI-IO independent IO with file set view) */
-#define H5D_XFER_IO_XFER_OPT_MODE_SIZE sizeof(H5FD_mpio_collective_opt_t)
-#define H5D_XFER_IO_XFER_OPT_MODE_DEF H5FD_MPIO_COLLECTIVE_IO
/* Definitions for optimization of MPI-IO transfer mode property */
#define H5D_XFER_MPIO_COLLECTIVE_OPT_SIZE sizeof(H5FD_mpio_collective_opt_t)
#define H5D_XFER_MPIO_COLLECTIVE_OPT_DEF H5FD_MPIO_COLLECTIVE_IO
@@ -199,7 +196,6 @@ H5P_dxfr_reg_prop(H5P_genclass_t *pclass)
size_t def_hyp_vec_size = H5D_XFER_HYPER_VECTOR_SIZE_DEF; /* Default value for vector size */
#ifdef H5_HAVE_PARALLEL
H5FD_mpio_xfer_t def_io_xfer_mode = H5D_XFER_IO_XFER_MODE_DEF; /* Default value for I/O transfer mode */
- H5FD_mpio_collective_opt_t def_io_xfer_opt_mode = H5D_XFER_IO_XFER_OPT_MODE_DEF;
H5FD_mpio_chunk_opt_t def_mpio_chunk_opt_mode = H5D_XFER_MPIO_CHUNK_OPT_HARD_DEF;
H5FD_mpio_collective_opt_t def_mpio_collective_opt_mode = H5D_XFER_MPIO_COLLECTIVE_OPT_DEF;
unsigned def_mpio_chunk_opt_num = H5D_XFER_MPIO_CHUNK_OPT_NUM_DEF;
@@ -265,8 +261,6 @@ H5P_dxfr_reg_prop(H5P_genclass_t *pclass)
/* Register the I/O transfer mode property */
if(H5P_register(pclass, H5D_XFER_IO_XFER_MODE_NAME, H5D_XFER_IO_XFER_MODE_SIZE, &def_io_xfer_mode, NULL, NULL, NULL, NULL, NULL, NULL, NULL) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
- if(H5P_register(pclass, H5D_XFER_IO_XFER_OPT_MODE_NAME, H5D_XFER_IO_XFER_OPT_MODE_SIZE, &def_io_xfer_opt_mode, NULL, NULL, NULL, NULL, NULL, NULL, NULL) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
if(H5P_register(pclass, H5D_XFER_MPIO_COLLECTIVE_OPT_NAME, H5D_XFER_MPIO_COLLECTIVE_OPT_SIZE, &def_mpio_collective_opt_mode, NULL, NULL, NULL, NULL, NULL, NULL, NULL) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
if(H5P_register(pclass, H5D_XFER_MPIO_CHUNK_OPT_HARD_NAME, H5D_XFER_MPIO_CHUNK_OPT_HARD_SIZE, &def_mpio_chunk_opt_mode, NULL, NULL, NULL, NULL, NULL, NULL, NULL) < 0)
diff --git a/src/H5S.c b/src/H5S.c
index 8a58cba..4996f1f 100644
--- a/src/H5S.c
+++ b/src/H5S.c
@@ -45,18 +45,6 @@ static herr_t H5S_encode(H5S_t *obj, unsigned char *buf, size_t *nalloc);
static H5S_t *H5S_decode(const unsigned char *buf);
static htri_t H5S_extent_equal(const H5S_t *ds1, const H5S_t *ds2);
-#ifdef H5S_DEBUG
-/* Names of the selection names, for debugging */
-static const char *H5S_sel_names[]={
- "none", "point", "hyperslab", "all"
-};
-
-/* The path table, variable length */
-static H5S_iostats_t **H5S_iostats_g = NULL;
-static size_t H5S_aiostats_g = 0; /*entries allocated*/
-static size_t H5S_niostats_g = 0; /*entries used*/
-#endif /* H5S_DEBUG */
-
#ifdef H5_HAVE_PARALLEL
/* Global vars whose value can be set from environment variable also */
hbool_t H5S_mpi_opt_types_g = TRUE;
@@ -87,9 +75,9 @@ DESCRIPTION
static herr_t
H5S_init_interface(void)
{
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT(H5S_init_interface);
+ FUNC_ENTER_NOAPI_NOINIT(H5S_init_interface)
/* Initialize the atom group for the file IDs */
if(H5I_register_type(H5I_DATASPACE, (size_t)H5I_DATASPACEID_HASHSIZE, H5S_RESERVED_ATOMS, (H5I_free_t)H5S_close) < 0)
@@ -105,8 +93,8 @@ H5S_init_interface(void)
#endif /* H5_HAVE_PARALLEL */
done:
- FUNC_LEAVE_NOAPI(ret_value);
-}
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5S_init_interface() */
/*--------------------------------------------------------------------------
@@ -129,156 +117,26 @@ done:
int
H5S_term_interface(void)
{
- int n=0;
-#ifdef H5S_DEBUG
- size_t i;
- int j, nprints=0;
- H5S_iostats_t *path=NULL;
- char buf[256];
-#endif /* H5S_DEBUG */
-
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_term_interface);
-
- if (H5_interface_initialize_g) {
- if ((n=H5I_nmembers(H5I_DATASPACE))) {
- H5I_clear_type(H5I_DATASPACE, FALSE);
- } else {
-#ifdef H5S_DEBUG
- /*
- * Print statistics about each conversion path.
- */
- if (H5DEBUG(S)) {
- for (i=0; i<H5S_niostats_g; i++) {
- path = H5S_iostats_g[i];
- for (j=0; j<2; j++) {
- if (0==path->stats[j].gath_ncalls &&
- 0==path->stats[j].scat_ncalls &&
- 0==path->stats[j].bkg_ncalls &&
- 0==path->stats[j].read_ncalls &&
- 0==path->stats[j].write_ncalls) {
- continue;
- }
- if (0==nprints++) {
- fprintf(H5DEBUG(S), "H5S: data space conversion "
- "statistics:\n");
- fprintf(H5DEBUG(S),
- " %-16s %10s %10s %8s %8s %8s %10s\n",
- "Memory <> File", "Bytes", "Calls",
- "User", "System", "Elapsed", "Bandwidth");
- fprintf(H5DEBUG(S),
- " %-16s %10s %10s %8s %8s %8s %10s\n",
- "--------------", "-----", "-----",
- "----", "------", "-------", "---------");
- }
-
- /* Summary */
- sprintf(buf, "%s %c %s",
- H5S_sel_names[path->mtype], 0==j?'>':'<', H5S_sel_names[path->ftype]);
- fprintf(H5DEBUG(S), " %-16s\n", buf);
-
- /* Gather */
- if (path->stats[j].gath_ncalls) {
- H5_bandwidth(buf,
- (double)(path->stats[j].gath_nbytes),
- path->stats[j].gath_timer.etime);
- HDfprintf(H5DEBUG(S),
- " %16s %10Hu %10Hu %8.2f %8.2f %8.2f "
- "%10s\n", "gather",
- path->stats[j].gath_nbytes,
- path->stats[j].gath_ncalls,
- path->stats[j].gath_timer.utime,
- path->stats[j].gath_timer.stime,
- path->stats[j].gath_timer.etime,
- buf);
- }
-
- /* Scatter */
- if (path->stats[j].scat_ncalls) {
- H5_bandwidth(buf,
- (double)(path->stats[j].scat_nbytes),
- path->stats[j].scat_timer.etime);
- HDfprintf(H5DEBUG(S),
- " %16s %10Hu %10Hu %8.2f %8.2f %8.2f "
- "%10s\n", "scatter",
- path->stats[j].scat_nbytes,
- path->stats[j].scat_ncalls,
- path->stats[j].scat_timer.utime,
- path->stats[j].scat_timer.stime,
- path->stats[j].scat_timer.etime,
- buf);
- }
-
- /* Background */
- if (path->stats[j].bkg_ncalls) {
- H5_bandwidth(buf,
- (double)(path->stats[j].bkg_nbytes),
- path->stats[j].bkg_timer.etime);
- HDfprintf(H5DEBUG(S),
- " %16s %10Hu %10Hu %8.2f %8.2f %8.2f "
- "%10s\n", "background",
- path->stats[j].bkg_nbytes,
- path->stats[j].bkg_ncalls,
- path->stats[j].bkg_timer.utime,
- path->stats[j].bkg_timer.stime,
- path->stats[j].bkg_timer.etime,
- buf);
- }
-
- /* Read */
- if (path->stats[j].read_ncalls) {
- H5_bandwidth(buf,
- (double)(path->stats[j].read_nbytes),
- path->stats[j].read_timer.etime);
- HDfprintf(H5DEBUG(S),
- " %16s %10Hu %10Hu %8.2f %8.2f %8.2f "
- "%10s\n", "read",
- path->stats[j].read_nbytes,
- path->stats[j].read_ncalls,
- path->stats[j].read_timer.utime,
- path->stats[j].read_timer.stime,
- path->stats[j].read_timer.etime,
- buf);
- }
-
- /* Write */
- if (path->stats[j].write_ncalls) {
- H5_bandwidth(buf,
- (double)(path->stats[j].write_nbytes),
- path->stats[j].write_timer.etime);
- HDfprintf(H5DEBUG(S),
- " %16s %10Hu %10Hu %8.2f %8.2f %8.2f "
- "%10s\n", "write",
- path->stats[j].write_nbytes,
- path->stats[j].write_ncalls,
- path->stats[j].write_timer.utime,
- path->stats[j].write_timer.stime,
- path->stats[j].write_timer.etime,
- buf);
- }
- }
- }
- }
-#endif /* H5S_DEBUG */
+ int n = 0;
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_term_interface)
+ if(H5_interface_initialize_g) {
+ if((n = H5I_nmembers(H5I_DATASPACE))) {
+ H5I_clear_type(H5I_DATASPACE, FALSE);
+ } /* end if */
+ else {
/* Free data types */
H5I_dec_type_ref(H5I_DATASPACE);
-#ifdef H5S_DEBUG
- /* Clear/free conversion table */
- for (i=0; i<H5S_niostats_g; i++)
- H5MM_xfree(H5S_iostats_g[i]);
- H5S_iostats_g = H5MM_xfree(H5S_iostats_g);
- H5S_niostats_g = H5S_aiostats_g = 0;
-#endif /* H5S_DEBUG */
-
/* Shut down interface */
H5_interface_initialize_g = 0;
n = 1; /*H5I*/
- }
- }
+ } /* end else */
+ } /* end if */
- FUNC_LEAVE_NOAPI(n);
-}
+ FUNC_LEAVE_NOAPI(n)
+} /* end H5S_term_interface() */
/*--------------------------------------------------------------------------
@@ -1384,105 +1242,6 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5S_set_extent_simple() */
-#ifdef H5S_DEBUG
-
-/*-------------------------------------------------------------------------
- * Function: H5S_find
- *
- * Purpose: Given two data spaces (MEM_SPACE and FILE_SPACE) this
- * function returns a pointer to the conversion path information,
- * creating a new conversion path entry if necessary.
- *
- * Return: Success: Ptr to a conversion path entry
- *
- * Failure: NULL
- *
- * Programmer: Robb Matzke
- * Wednesday, January 21, 1998
- *
- * Modifications:
- *
- * Quincey Koziol
- * Instead of returning a point into the data space conversion table we
- * copy all the information into a user-supplied CONV buffer and return
- * non-negative on success or negative on failure.
- *
- * Robb Matzke, 11 Aug 1998
- * Returns a pointer into the conversion path table. A path entry
- * contains pointers to the memory and file half of the conversion (the
- * pointers registered in the H5S_fconv_g[] and H5S_mconv_g[] tables)
- * along with other data whose scope is the conversion path (like path
- * statistics).
- *
- * John Mainzer, 8/30/04
- * Modified code to check with all other processes that have the
- * file open before OKing collective I/O.
- *
- *-------------------------------------------------------------------------
- */
-H5S_iostats_t *
-H5S_find (const H5S_t *mem_space, const H5S_t *file_space)
-{
- H5S_iostats_t *path=NULL; /* Space conversion path */
- size_t u; /* Index variable */
- H5S_iostats_t *ret_value; /* Return value */
-
- FUNC_ENTER_NOAPI(H5S_find, NULL);
-
- /* Check args */
- assert (mem_space && (H5S_SIMPLE==H5S_GET_EXTENT_TYPE(mem_space) ||
- H5S_NULL==H5S_GET_EXTENT_TYPE(mem_space) ||
- H5S_SCALAR==H5S_GET_EXTENT_TYPE(mem_space)));
- assert (file_space && (H5S_SIMPLE==H5S_GET_EXTENT_TYPE(file_space) ||
- H5S_NULL==H5S_GET_EXTENT_TYPE(file_space) ||
- H5S_SCALAR==H5S_GET_EXTENT_TYPE(file_space)));
-
- /*
- * Is this path already present in the data space conversion path table?
- * If so then return a pointer to that entry.
- */
- for (u=0; u<H5S_niostats_g; u++)
- if (H5S_iostats_g[u]->ftype==H5S_GET_SELECT_TYPE(file_space) &&
- H5S_iostats_g[u]->mtype==H5S_GET_SELECT_TYPE(mem_space))
- HGOTO_DONE(H5S_iostats_g[u]);
-
- /*
- * The path wasn't found. Create a new path.
- */
- if (NULL==(path = H5MM_calloc(sizeof(*path))))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for data space conversion path")
-
- /* Initialize file & memory conversion functions */
- path->ftype = H5S_GET_SELECT_TYPE(file_space);
- path->mtype = H5S_GET_SELECT_TYPE(mem_space);
-
- /*
- * Add the new path to the table.
- */
- if (H5S_niostats_g>=H5S_aiostats_g) {
- size_t n = MAX(10, 2*H5S_aiostats_g);
- H5S_iostats_t **p = H5MM_realloc(H5S_iostats_g, n*sizeof(H5S_iostats_g[0]));
-
- if (NULL==p)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for data space conversion path table")
- H5S_aiostats_g = n;
- H5S_iostats_g = p;
- } /* end if */
- H5S_iostats_g[H5S_niostats_g++] = path;
-
- /* Set the return value */
- ret_value=path;
-
-done:
- if(ret_value==NULL) {
- if(path!=NULL)
- H5MM_xfree(path);
- } /* end if */
-
- FUNC_LEAVE_NOAPI(ret_value);
-} /* end H5S_find() */
-#endif /* H5S_DEBUG */
-
/*-------------------------------------------------------------------------
* Function: H5Screate_simple
diff --git a/src/H5Smpio.c b/src/H5Smpio.c
index cc89b49..725b8fc 100644
--- a/src/H5Smpio.c
+++ b/src/H5Smpio.c
@@ -123,7 +123,7 @@ H5S_mpio_all_type( const H5S_t *space, size_t elmt_size,
*new_type = MPI_BYTE;
H5_ASSIGN_OVERFLOW(*count, total_bytes, hsize_t, size_t);
*extra_offset = 0;
- *is_derived_type = 0;
+ *is_derived_type = FALSE;
done:
FUNC_LEAVE_NOAPI(ret_value);
@@ -163,7 +163,7 @@ H5S_mpio_none_type( const H5S_t UNUSED *space, size_t UNUSED elmt_size,
*new_type = MPI_BYTE;
*count = 0;
*extra_offset = 0;
- *is_derived_type = 0;
+ *is_derived_type = FALSE;
FUNC_LEAVE_NOAPI(SUCCEED);
} /* H5S_mpio_none_type() */
@@ -456,7 +456,7 @@ H5S_mpio_hyper_type( const H5S_t *space, size_t elmt_size,
/* fill in the remaining return values */
*count = 1; /* only have to move one of these suckers! */
*extra_offset = 0;
- *is_derived_type = 1;
+ *is_derived_type = TRUE;
HGOTO_DONE(SUCCEED);
empty:
@@ -464,7 +464,7 @@ empty:
*new_type = MPI_BYTE;
*count = 0;
*extra_offset = 0;
- *is_derived_type = 0;
+ *is_derived_type = FALSE;
done:
/* Release selection iterator */
@@ -475,7 +475,7 @@ done:
#ifdef H5S_DEBUG
if(H5DEBUG(S)){
- HDfprintf(H5DEBUG(S), "Leave %s, count=%ld is_derived_type=%d\n",
+ HDfprintf(H5DEBUG(S), "Leave %s, count=%ld is_derived_type=%t\n",
FUNC, *count, *is_derived_type );
}
#endif
@@ -556,7 +556,7 @@ H5S_mpio_span_hyper_type( const H5S_t *space,
/* fill in the remaining return values */
*count = 1;
*extra_offset = 0;
- *is_derived_type = 1;
+ *is_derived_type = TRUE;
HGOTO_DONE(SUCCEED);
@@ -565,7 +565,7 @@ empty:
*new_type = MPI_BYTE;
*count = 0;
*extra_offset = 0;
- *is_derived_type = 0;
+ *is_derived_type = FALSE;
done:
FUNC_LEAVE_NOAPI(ret_value);
diff --git a/src/H5Sprivate.h b/src/H5Sprivate.h
index bd27f09..8744872 100644
--- a/src/H5Sprivate.h
+++ b/src/H5Sprivate.h
@@ -115,31 +115,6 @@ typedef struct H5S_sel_iter_t {
} u;
} H5S_sel_iter_t;
-#ifdef H5S_DEBUG
-typedef struct H5S_iostats_t {
- H5S_sel_type ftype;
- H5S_sel_type mtype;
-
- struct {
- H5_timer_t scat_timer; /*time spent scattering */
- hsize_t scat_nbytes; /*scatter throughput */
- hsize_t scat_ncalls; /*number of calls */
- H5_timer_t gath_timer; /*time spent gathering */
- hsize_t gath_nbytes; /*gather throughput */
- hsize_t gath_ncalls; /*number of calls */
- H5_timer_t bkg_timer; /*time for background */
- hsize_t bkg_nbytes; /*background throughput */
- hsize_t bkg_ncalls; /*number of calls */
- H5_timer_t read_timer; /*time for read calls */
- hsize_t read_nbytes; /*total bytes read */
- hsize_t read_ncalls; /*number of calls */
- H5_timer_t write_timer; /*time for write calls */
- hsize_t write_nbytes; /*total bytes written */
- hsize_t write_ncalls; /*number of calls */
- } stats[2]; /* 0=output, 1=input */
-} H5S_iostats_t;
-#endif
-
/* If the module using this macro is allowed access to the private variables, access them directly */
#ifdef H5S_PACKAGE
#define H5S_GET_EXTENT_TYPE(S) ((S)->extent.type)
@@ -198,9 +173,6 @@ typedef struct H5S_iostats_t {
/* Operations on dataspaces */
H5_DLL H5S_t *H5S_copy(const H5S_t *src, hbool_t share_selection, hbool_t copy_max);
H5_DLL herr_t H5S_close(H5S_t *ds);
-#ifdef H5S_DEBUG
-H5_DLL H5S_iostats_t *H5S_find(const H5S_t *mem_space, const H5S_t *file_space);
-#endif /* H5S_DEBUG */
H5_DLL H5S_class_t H5S_get_simple_extent_type(const H5S_t *ds);
H5_DLL hssize_t H5S_get_simple_extent_npoints(const H5S_t *ds);
H5_DLL hsize_t H5S_get_npoints_max(const H5S_t *ds);
diff --git a/src/H5T.c b/src/H5T.c
index 04d6c0b..c726e5c 100644
--- a/src/H5T.c
+++ b/src/H5T.c
@@ -4552,7 +4552,7 @@ H5T_path_compound_subset(const H5T_path_t *p)
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5T_path_compound_subset);
- assert(p);
+ HDassert(p);
if(p->are_compounds)
ret_value = H5T_conv_struct_subset(&(p->cdata));
diff --git a/src/H5Tconv.c b/src/H5Tconv.c
index 0da4d53..7803d07 100644
--- a/src/H5Tconv.c
+++ b/src/H5Tconv.c
@@ -1890,17 +1890,15 @@ H5T_subset_t
H5T_conv_struct_subset(const H5T_cdata_t *cdata)
{
H5T_conv_struct_t *priv;
- H5T_subset_t ret_value; /* Return value */
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5T_conv_struct_subset)
HDassert(cdata);
HDassert(cdata->priv);
- priv = (H5T_conv_struct_t*)(cdata->priv);
- ret_value = priv->smembs_subset;
+ priv = (H5T_conv_struct_t *)(cdata->priv);
- FUNC_LEAVE_NOAPI(ret_value)
+ FUNC_LEAVE_NOAPI(priv->smembs_subset)
} /* end H5T_conv_struct_subset() */
diff --git a/src/H5Tprivate.h b/src/H5Tprivate.h
index dfe2367..2fe4c3a 100644
--- a/src/H5Tprivate.h
+++ b/src/H5Tprivate.h
@@ -69,7 +69,7 @@ typedef struct H5T_conv_cb_t {
/* Values for the optimization of compound data reading and writing. They indicate
* whether the fields of the source and destination are subset of each other and
- * there is no conversion needed. It's for the Chicago company.
+ * there is no conversion needed.
*/
typedef enum {
H5T_SUBSET_BADVALUE = -1, /* Invalid value */
diff --git a/src/H5Vprivate.h b/src/H5Vprivate.h
index 94b3699..b92266c 100644
--- a/src/H5Vprivate.h
+++ b/src/H5Vprivate.h
@@ -410,5 +410,25 @@ H5V_log2_of2(uint32_t n)
return(MultiplyDeBruijnBitPosition[(n * (uint32_t)0x077CB531UL) >> 27]);
} /* H5V_log2_of2() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5V_limit_enc_size
+ *
+ * Purpose: Determine the # of bytes needed to encode values within a
+ * range from 0 to a given limit
+ *
+ * Return: Number of bytes needed
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, March 13, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static H5_inline unsigned UNUSED
+H5V_limit_enc_size(uint64_t limit)
+{
+ return (H5V_log2_gen(limit) / 8) + 1;
+} /* end H5V_limit_enc_size() */
+
#endif /* H5Vprivate_H */
diff --git a/src/H5config.h.in b/src/H5config.h.in
index 5c767ef..77a3b23 100644
--- a/src/H5config.h.in
+++ b/src/H5config.h.in
@@ -368,6 +368,9 @@
/* Define to 1 if you have the `waitpid' function. */
#undef HAVE_WAITPID
+/* Define if your system has window style path name. */
+#undef HAVE_WINDOW_PATH
+
/* Define to 1 if you have the <winsock.h> header file. */
#undef HAVE_WINSOCK_H
diff --git a/src/H5private.h b/src/H5private.h
index 11f3037..b60c50a 100644
--- a/src/H5private.h
+++ b/src/H5private.h
@@ -638,7 +638,15 @@ H5_DLL int HDfprintf (FILE *stream, const char *fmt, ...);
#define HDfwrite(M,Z,N,F) fwrite(M,Z,N,F)
#define HDgetc(F) getc(F)
#define HDgetchar() getchar()
+#ifdef _WIN32
+#define HDgetcwd(S,Z) _getcwd(S,Z)
+#define HDgetdcwd(D,S,Z) _getdcwd(D,S,Z)
+#define HDgetdrive() _getdrive()
+#else
#define HDgetcwd(S,Z) getcwd(S,Z)
+#define HDgetdcwd(D,S,Z) getcwd(S,Z)
+#define HDgetdrive() 0
+#endif
#define HDgetegid() getegid()
#define HDgetenv(S) getenv(S)
#define HDgeteuid() geteuid()
@@ -911,6 +919,42 @@ extern char *strdup(const char *s);
#endif /* _WIN32 */
+#ifdef H5_HAVE_WINDOW_PATH
+
+/* directory delimiter for Windows: slash and backslash are acceptable on Windows */
+#define DIR_SLASH_SEPC '/'
+#define DIR_SEPC '\\'
+#define DIR_SEPS "\\"
+#define CHECK_DELIMITER(SS) ((SS == DIR_SEPC)||(SS == DIR_SLASH_SEPC))
+#define CHECK_ABSOLUTE(NAME) ((isalpha(NAME[0])) && (NAME[1] == ':') && (CHECK_DELIMITER(NAME[2])))
+#define CHECK_ABS_DRIVE(NAME) ((isalpha(NAME[0])) && (NAME[1] == ':'))
+#define CHECK_ABS_PATH(NAME) (CHECK_DELIMITER(NAME[0]))
+
+#define GET_LAST_DELIMITER(NAME, ptr) { \
+ char *slash, *backslash; \
+ slash = strrchr(NAME, DIR_SLASH_SEPC); \
+ backslash = strrchr(NAME, DIR_SEPC); \
+ if (backslash > slash) \
+ (ptr = backslash); \
+ else \
+ (ptr = slash); \
+}
+
+#else
+
+#define DIR_SEPC '/'
+#define DIR_SEPS "/"
+#define CHECK_DELIMITER(SS) (SS == DIR_SEPC)
+#define CHECK_ABSOLUTE(NAME) (CHECK_DELIMITER(*NAME))
+#define CHECK_ABS_DRIVE(NAME) (0)
+#define CHECK_ABS_PATH(NAME) (0)
+#define GET_LAST_DELIMITER(NAME, ptr) ptr = strrchr(NAME, DIR_SEPC);
+
+#endif
+
+#define COLON_SEPC ':'
+H5_DLL herr_t H5_build_extpath(const char *, char ** /*out*/ );
+
/*
* These macros check whether debugging has been requested for a certain
diff --git a/src/H5public.h b/src/H5public.h
index 06060dd..5606171 100644
--- a/src/H5public.h
+++ b/src/H5public.h
@@ -70,11 +70,11 @@ extern "C" {
/* Version numbers */
#define H5_VERS_MAJOR 1 /* For major interface/format changes */
-#define H5_VERS_MINOR 8 /* For minor interface/format changes */
-#define H5_VERS_RELEASE 0 /* For tweaks, bug-fixes, or development */
+#define H5_VERS_MINOR 9 /* For minor interface/format changes */
+#define H5_VERS_RELEASE 5 /* 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.8.0" /* Full version string */
+#define H5_VERS_INFO "HDF5 library version: 1.9.5" /* Full version string */
#define H5check() H5check_version(H5_VERS_MAJOR,H5_VERS_MINOR, \
H5_VERS_RELEASE)
diff --git a/src/H5system.c b/src/H5system.c
index 5eae11d..4a49d71 100644
--- a/src/H5system.c
+++ b/src/H5system.c
@@ -35,6 +35,8 @@
#include "H5private.h" /* Generic Functions */
#include "H5Fprivate.h" /* File access */
#include "H5MMprivate.h" /* Memory management */
+#include "H5Eprivate.h"
+
/****************/
@@ -578,4 +580,100 @@ HDremove_all(const char *fname)
}
#endif
+
+/*
+ *-------------------------------------------------------------------------
+ *
+ * Function: H5_build_extpath
+ *
+ * Purpose: To build the path for later searching of target file for external link.
+ * This path can be either:
+ * 1. The absolute path of NAME
+ * or
+ * 2. The current working directory + relative path of NAME
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ * Programmer: Vailin Choi
+ * April 2, 2008
+ *-------------------------------------------------------------------------
+ */
+#define MAX_PATH_LEN 1024
+
+herr_t
+H5_build_extpath(const char *name, char **extpath/*out*/)
+{
+ char *full_path=NULL, *ptr=NULL;
+ char *retcwd=NULL, *cwdpath=NULL, *new_name=NULL;
+ int drive;
+ size_t cwdlen, path_len;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5_build_extpath)
+
+ *extpath = NULL;
+
+ /*
+ * Unix: name[0] is a "/"
+ * Windows: name[0-2] is "<drive letter>:\" or "<drive-letter>:/"
+ */
+ if (CHECK_ABSOLUTE(name)) {
+ if ((full_path=H5MM_strdup(name)) == NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+ } else { /* relative pathname */
+ if ((cwdpath=H5MM_malloc(MAX_PATH_LEN)) == NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+ if ((new_name=H5MM_strdup(name)) == NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+
+ /*
+ * Windows: name[0-1] is "<drive-letter>:"
+ * Get current working directory on the drive specified in NAME
+ * Unix: does not apply
+ */
+ if (CHECK_ABS_DRIVE(name)) {
+ drive = name[0] - 'A' + 1;
+ retcwd = HDgetdcwd(drive, cwdpath, MAX_PATH_LEN);
+ HDstrcpy(new_name, &name[2]);
+ /*
+ * Windows: name[0] is a '/' or '\'
+ * Get current drive
+ * Unix: does not apply
+ */
+ } else if (CHECK_ABS_PATH(name) && (drive=HDgetdrive())) {
+ sprintf(cwdpath, "%c:%c", (drive+'A'-1), name[0]);
+ retcwd = cwdpath;
+ HDstrcpy(new_name, &name[1]);
+ } else /* totally relative for both Unix and Windows: get current working directory */
+ retcwd = HDgetcwd(cwdpath, MAX_PATH_LEN);
+
+ if (retcwd != NULL) {
+ cwdlen = HDstrlen(cwdpath);
+ HDassert(cwdlen);
+ path_len = cwdlen + HDstrlen(new_name) + 2;
+ if ((full_path=H5MM_malloc(path_len)) == NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+
+ HDstrcpy(full_path, cwdpath);
+ if (!CHECK_DELIMITER(cwdpath[cwdlen-1]))
+ HDstrcat(full_path, DIR_SEPS);
+ HDstrcat(full_path, new_name);
+ }
+ }
+
+ /* strip out the last component (the file name itself) from the path */
+ if (full_path) {
+ GET_LAST_DELIMITER(full_path, ptr)
+ HDassert(ptr);
+ *++ptr = '\0';
+ *extpath = full_path;
+ }
+done:
+ if (cwdpath)
+ H5MM_xfree(cwdpath);
+ if (new_name)
+ H5MM_xfree(new_name);
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5_build_extpath() */
diff --git a/src/Makefile.am b/src/Makefile.am
index 0e5030b..fcb47e2 100755
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -46,10 +46,10 @@ libhdf5_la_SOURCES= H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \
H5AC.c H5B.c H5Bcache.c \
H5B2.c H5B2cache.c H5B2dbg.c H5B2int.c H5B2stat.c H5B2test.c \
H5C.c H5CS.c \
- H5D.c H5Dcompact.c H5Dcontig.c H5Ddbg.c \
+ H5D.c H5Dchunk.c H5Dcompact.c H5Dcontig.c H5Ddbg.c \
H5Ddeprec.c H5Defl.c H5Dfill.c H5Dint.c \
H5Dio.c \
- H5Distore.c H5Dmpio.c H5Doh.c H5Dselect.c H5Dtest.c \
+ H5Distore.c H5Dmpio.c H5Doh.c H5Dscatgath.c H5Dselect.c H5Dtest.c \
H5E.c H5Edeprec.c H5Eint.c \
H5F.c H5Fdbg.c H5Ffake.c H5Fmount.c H5Fsfile.c H5Fsuper.c H5Ftest.c \
H5FD.c H5FDcore.c \
diff --git a/src/Makefile.in b/src/Makefile.in
index 085bf96..8e8f339 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -82,19 +82,20 @@ am_libhdf5_la_OBJECTS = H5.lo H5checksum.lo H5dbg.lo H5system.lo \
H5timer.lo H5trace.lo H5A.lo H5Abtree2.lo H5Adense.lo \
H5Adeprec.lo H5Aint.lo H5Atest.lo H5AC.lo H5B.lo H5Bcache.lo \
H5B2.lo H5B2cache.lo H5B2dbg.lo H5B2int.lo H5B2stat.lo \
- H5B2test.lo H5C.lo H5CS.lo H5D.lo H5Dcompact.lo H5Dcontig.lo \
- H5Ddbg.lo H5Ddeprec.lo H5Defl.lo H5Dfill.lo H5Dint.lo H5Dio.lo \
- H5Distore.lo H5Dmpio.lo H5Doh.lo H5Dselect.lo H5Dtest.lo \
- H5E.lo H5Edeprec.lo H5Eint.lo H5F.lo H5Fdbg.lo H5Ffake.lo \
- H5Fmount.lo H5Fsfile.lo H5Fsuper.lo H5Ftest.lo H5FD.lo \
- H5FDcore.lo H5FDdirect.lo H5FDfamily.lo H5FDlog.lo H5FDmpi.lo \
- H5FDmpio.lo H5FDmpiposix.lo H5FDmulti.lo H5FDsec2.lo \
- H5FDspace.lo H5FDstdio.lo H5FL.lo H5FO.lo H5FS.lo H5FScache.lo \
- H5FSdbg.lo H5FSsection.lo H5G.lo H5Gbtree2.lo H5Gcompact.lo \
- H5Gdense.lo H5Gdeprec.lo H5Gent.lo H5Gint.lo H5Glink.lo \
- H5Gloc.lo H5Gname.lo H5Gnode.lo H5Gobj.lo H5Goh.lo H5Gstab.lo \
- H5Gtest.lo H5Gtraverse.lo H5HF.lo H5HFbtree2.lo H5HFcache.lo \
- H5HFdbg.lo H5HFdblock.lo H5HFdtable.lo H5HFhdr.lo H5HFhuge.lo \
+ H5B2test.lo H5C.lo H5CS.lo H5D.lo H5Dchunk.lo H5Dcompact.lo \
+ H5Dcontig.lo H5Ddbg.lo H5Ddeprec.lo H5Defl.lo H5Dfill.lo \
+ H5Dint.lo H5Dio.lo H5Distore.lo H5Dmpio.lo H5Doh.lo \
+ H5Dscatgath.lo H5Dselect.lo H5Dtest.lo H5E.lo H5Edeprec.lo \
+ H5Eint.lo H5F.lo H5Fdbg.lo H5Ffake.lo H5Fmount.lo H5Fsfile.lo \
+ H5Fsuper.lo H5Ftest.lo H5FD.lo H5FDcore.lo H5FDdirect.lo \
+ H5FDfamily.lo H5FDlog.lo H5FDmpi.lo H5FDmpio.lo \
+ H5FDmpiposix.lo H5FDmulti.lo H5FDsec2.lo H5FDspace.lo \
+ H5FDstdio.lo H5FL.lo H5FO.lo H5FS.lo H5FScache.lo H5FSdbg.lo \
+ H5FSsection.lo H5G.lo H5Gbtree2.lo H5Gcompact.lo H5Gdense.lo \
+ H5Gdeprec.lo H5Gent.lo H5Gint.lo H5Glink.lo H5Gloc.lo \
+ H5Gname.lo H5Gnode.lo H5Gobj.lo H5Goh.lo H5Gstab.lo H5Gtest.lo \
+ H5Gtraverse.lo H5HF.lo H5HFbtree2.lo H5HFcache.lo H5HFdbg.lo \
+ H5HFdblock.lo H5HFdtable.lo H5HFhdr.lo H5HFhuge.lo \
H5HFiblock.lo H5HFiter.lo H5HFman.lo H5HFsection.lo \
H5HFspace.lo H5HFstat.lo H5HFtest.lo H5HFtiny.lo H5HG.lo \
H5HGdbg.lo H5HL.lo H5HLdbg.lo H5HP.lo H5I.lo H5L.lo \
@@ -383,7 +384,7 @@ CHECK_CLEANFILES = *.chkexe *.chklog *.clog
# Add libtool shared library version numbers to the HDF5 library
# See libtool versioning documentation online.
LT_VERS_INTERFACE = 5
-LT_VERS_REVISION = 0
+LT_VERS_REVISION = 6
LT_VERS_AGE = 0
H5detect_CFLAGS = -g
@@ -404,10 +405,10 @@ libhdf5_la_SOURCES = H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \
H5AC.c H5B.c H5Bcache.c \
H5B2.c H5B2cache.c H5B2dbg.c H5B2int.c H5B2stat.c H5B2test.c \
H5C.c H5CS.c \
- H5D.c H5Dcompact.c H5Dcontig.c H5Ddbg.c \
+ H5D.c H5Dchunk.c H5Dcompact.c H5Dcontig.c H5Ddbg.c \
H5Ddeprec.c H5Defl.c H5Dfill.c H5Dint.c \
H5Dio.c \
- H5Distore.c H5Dmpio.c H5Doh.c H5Dselect.c H5Dtest.c \
+ H5Distore.c H5Dmpio.c H5Doh.c H5Dscatgath.c H5Dselect.c H5Dtest.c \
H5E.c H5Edeprec.c H5Eint.c \
H5F.c H5Fdbg.c H5Ffake.c H5Fmount.c H5Fsfile.c H5Fsuper.c H5Ftest.c \
H5FD.c H5FDcore.c \
@@ -602,6 +603,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5C.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5CS.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5D.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Dchunk.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Dcompact.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Dcontig.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Ddbg.Plo@am__quote@
@@ -613,6 +615,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Distore.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Dmpio.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Doh.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Dscatgath.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Dselect.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Dtest.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5E.Plo@am__quote@