diff options
author | Scot Breitenfeld <brtnfld@hdfgroup.org> | 2008-04-30 19:23:26 (GMT) |
---|---|---|
committer | Scot Breitenfeld <brtnfld@hdfgroup.org> | 2008-04-30 19:23:26 (GMT) |
commit | 5773fd34bc5adf59b4530d95ac9f0c0585902803 (patch) | |
tree | 456ad239799382e1f083fb7fc74399e43b471912 /src | |
parent | 0138995d1ce2068db1f790503435a2121132d3ad (diff) | |
download | hdf5-5773fd34bc5adf59b4530d95ac9f0c0585902803.zip hdf5-5773fd34bc5adf59b4530d95ac9f0c0585902803.tar.gz hdf5-5773fd34bc5adf59b4530d95ac9f0c0585902803.tar.bz2 |
[svn-r14902] Merged fortran_1_8 branch changes r14505:14901 into the trunk. New fortran wrappers added.
Diffstat (limited to 'src')
45 files changed, 5936 insertions, 5634 deletions
diff --git a/src/H5Adeprec.c b/src/H5Adeprec.c index 85cef2f..9f888c8 100644 --- a/src/H5Adeprec.c +++ b/src/H5Adeprec.c @@ -312,8 +312,6 @@ 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 eae1291..2625c63 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_limit_enc_size((uint64_t)shared->node_info[0].max_nrec); + shared->max_nrec_size = (H5V_log2_gen((uint64_t)shared->node_info[0].max_nrec) + 7) / 8; 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_limit_enc_size((uint64_t)shared->node_info[u].cum_max_nrec); + shared->node_info[u].cum_max_nrec_size = (H5V_log2_gen((uint64_t)shared->node_info[u].cum_max_nrec) + 7) / 8; 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_limit_enc_size((uint64_t)shared->node_info[shared->depth].cum_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; 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) @@ -625,7 +625,7 @@ H5Dget_create_plist(hid_t dset_id) H5I_dec_ref(src_id); H5I_dec_ref(dst_id); if(bkg_buf) - (void)H5FL_BLK_FREE(type_conv, bkg_buf); + 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) - (void)H5FL_BLK_FREE(type_conv, bkg_buf); + H5FL_BLK_FREE(type_conv, bkg_buf); } /* end if */ } /* end if */ diff --git a/src/H5Dchunk.c b/src/H5Dchunk.c deleted file mode 100644 index baaa5f1..0000000 --- a/src/H5Dchunk.c +++ /dev/null @@ -1,1515 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * 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 c3abab6..2e4d3f7 100644 --- a/src/H5Dcompact.c +++ b/src/H5Dcompact.c @@ -41,52 +41,22 @@ #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 */ /*******************/ @@ -94,7 +64,6 @@ const H5D_layout_ops_t H5D_LOPS_COMPACT[1] = {{ /* Declare extern the free list to manage blocks of type conversion data */ H5FL_BLK_EXTERN(type_conv); - /*------------------------------------------------------------------------- * Function: H5D_compact_fill @@ -149,32 +118,6 @@ 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. @@ -192,19 +135,20 @@ H5D_compact_io_init(const H5D_io_info_t *io_info, const H5D_type_info_t UNUSED * * *------------------------------------------------------------------------- */ -static ssize_t +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[]) + 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) { - ssize_t ret_value; /* Return value */ + ssize_t ret_value; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5D_compact_readvv) + FUNC_ENTER_NOAPI(H5D_compact_readvv, FAIL) - HDassert(io_info); + assert(io_info->dset); /* Use the vectorized memory copy routine to do actual work */ - 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) + 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) HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "vectorized memcpy failed") done: @@ -233,23 +177,24 @@ done: * *------------------------------------------------------------------------- */ -static ssize_t +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[]) + 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) { - ssize_t ret_value; /* Return value */ + ssize_t ret_value; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5D_compact_writevv) + FUNC_ENTER_NOAPI(H5D_compact_writevv, FAIL) - HDassert(io_info); + assert(io_info->dset); /* Use the vectorized memory copy routine to do actual work */ - 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) + 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) HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "vectorized memcpy failed") /* Mark the compact dataset's buffer as dirty */ - *io_info->store->compact.dirty = TRUE; + io_info->dset->shared->layout.u.compact.dirty = TRUE; done: FUNC_LEAVE_NOAPI(ret_value) @@ -426,11 +371,11 @@ done: if(H5I_dec_ref(tid_mem) < 0) HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't decrement temporary datatype ID") if(buf) - (void)H5FL_BLK_FREE(type_conv, buf); + H5FL_BLK_FREE(type_conv, buf); if(reclaim_buf) - (void)H5FL_BLK_FREE(type_conv, reclaim_buf); + H5FL_BLK_FREE(type_conv, reclaim_buf); if(bkg) - (void)H5FL_BLK_FREE(type_conv, bkg); + 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 1a3fda5..bdb8294 100644 --- a/src/H5Dcontig.c +++ b/src/H5Dcontig.c @@ -45,50 +45,24 @@ #include "H5Pprivate.h" /* Property lists */ #include "H5Vprivate.h" /* Vector and array functions */ - /****************/ /* Local Macros */ /****************/ - /******************/ /* Local Typedefs */ /******************/ - /********************/ /* Local Prototypes */ /********************/ - -/* 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); - +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); /*********************/ /* 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 */ /*******************/ @@ -99,7 +73,6 @@ 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 @@ -148,8 +121,7 @@ done: herr_t H5D_contig_fill(H5D_t *dset, hid_t dxpl_id) { - H5D_io_info_t ioinfo; /* Dataset I/O info */ - H5D_storage_t store; /* Union of storage info for dataset */ + 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) */ @@ -226,9 +198,6 @@ 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 @@ -256,7 +225,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_one(&ioinfo, offset, size) < 0) + if(H5D_contig_write(dset, dxpl_cache, my_dxpl_id, &store, offset, size, fb_info.fill_buf) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to write fill value to dataset") /* Indicate that blocks are being written */ @@ -265,7 +234,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_one(&ioinfo, offset, size) < 0) + if(H5D_contig_write(dset, dxpl_cache, my_dxpl_id, &store, offset, size, fb_info.fill_buf) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to write fill value to dataset") #ifdef H5_HAVE_PARALLEL } /* end else */ @@ -355,108 +324,8 @@ 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. @@ -469,27 +338,34 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5D_contig_write_one(H5D_io_info_t *io_info, hsize_t offset, size_t size) +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) { - 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) + 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) HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "vector write failed") done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5D_contig_write_one() */ +} /* end H5D_contig_write() */ /*------------------------------------------------------------------------- @@ -513,76 +389,67 @@ 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[]) + 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) { 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 *)io_info->u.rbuf; /* 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 *)_buf; /* 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 */ - HDassert(io_info); - HDassert(io_info->dset); - HDassert(io_info->store); - HDassert(buf); + assert(io_info); + assert(io_info->dset); + assert(io_info->store); + assert(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 *)io_info->u.rbuf + mem_offset_arr[v]; + buf = (unsigned char *)_buf + 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 { @@ -598,40 +465,40 @@ for(u = 0; u < mem_max_nseq; u++) 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 { @@ -643,16 +510,16 @@ for(u = 0; u < mem_max_nseq; u++) /* 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 */ @@ -694,72 +561,72 @@ for(u = 0; u < mem_max_nseq; u++) 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 *)io_info->u.rbuf + mem_offset_arr[v]; + buf = (unsigned char *)_buf + 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) @@ -787,14 +654,15 @@ 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[]) + 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) { 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 *)io_info->u.wbuf; /* 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 *)_buf; /* 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 */ @@ -803,10 +671,10 @@ H5D_contig_writevv(const H5D_io_info_t *io_info, FUNC_ENTER_NOAPI(H5D_contig_writevv, FAIL) /* Check args */ - HDassert(io_info); - HDassert(io_info->dset); - HDassert(io_info->store); - HDassert(buf); + assert(io_info); + assert(io_info->dset); + assert(io_info->store); + assert(buf); /* Check if data sieving is enabled */ if(H5F_HAS_FEATURE(file,H5FD_FEAT_DATA_SIEVE)) { @@ -840,18 +708,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 *)io_info->u.wbuf + mem_offset_arr[v]; + buf = (const unsigned char *)_buf + 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) @@ -882,15 +750,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 { @@ -899,13 +767,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 { @@ -930,7 +798,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 */ @@ -940,30 +808,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 { @@ -1007,73 +875,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 *)io_info->u.wbuf + mem_offset_arr[v]; + buf = (const unsigned char *)_buf + 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 fd1d2e8..8f8aa50 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 = (const H5S_t *)H5I_object_verify(space_id,H5I_DATASPACE))) + if(NULL == (space = 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 7dac29b..c8d1098 100644 --- a/src/H5Defl.c +++ b/src/H5Defl.c @@ -33,88 +33,30 @@ #include "H5Eprivate.h" /* Error handling */ #include "H5Fprivate.h" /* Files */ - /****************/ /* Local Macros */ /****************/ - /******************/ /* Local Typedefs */ /******************/ - /********************/ /* Local Prototypes */ /********************/ - -/* 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, +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 @@ -135,26 +77,26 @@ H5D_efl_io_init(const H5D_io_info_t *io_info, const H5D_type_info_t UNUSED *type *------------------------------------------------------------------------- */ 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 */ - HDassert(efl && efl->nused>0); - HDassert(H5F_addr_defined(addr)); - HDassert(size < SIZET_MAX); - HDassert(buf || 0 == size); + assert (efl && efl->nused>0); + assert (H5F_addr_defined (addr)); + assert (size < SIZET_MAX); + assert (buf || 0==size); /* Find the first efl member from which to read */ for (u=0, cur=0; u<efl->nused; u++) { @@ -167,7 +109,7 @@ H5D_efl_read(const H5O_efl_t *efl, haddr_t addr, size_t size, uint8_t *buf) /* Read the data */ while (size) { - HDassert(buf); + assert(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)) @@ -223,25 +165,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 */ - HDassert(efl && efl->nused>0); - HDassert(H5F_addr_defined(addr)); - HDassert(size < SIZET_MAX); - HDassert(buf || 0 == size); + assert (efl && efl->nused>0); + assert (H5F_addr_defined (addr)); + assert (size < SIZET_MAX); + assert (buf || 0==size); /* Find the first efl member in which to write */ for (u=0, cur=0; u<efl->nused; u++) { @@ -306,68 +248,71 @@ done: * Programmer: Quincey Koziol * Wednesday, May 7, 2003 * + * Modifications: + * *------------------------------------------------------------------------- */ -static ssize_t +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[]) + 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) { - 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_NOINIT(H5D_efl_readvv) + FUNC_ENTER_NOAPI(H5D_efl_readvv, FAIL) /* Check args */ - HDassert(efl && efl->nused > 0); - HDassert(io_info->u.rbuf); + assert (efl && efl->nused>0); + assert (_buf); /* 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 *)io_info->u.rbuf + mem_offset_arr[v]; + buf = (unsigned char *)_buf + 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) @@ -387,68 +332,71 @@ done: * Programmer: Quincey Koziol * Friday, May 2, 2003 * + * Modifications: + * *------------------------------------------------------------------------- */ -static ssize_t +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[]) + 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) { - 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_NOINIT(H5D_efl_writevv) + FUNC_ENTER_NOAPI(H5D_efl_writevv, FAIL) /* Check args */ - HDassert(efl && efl->nused > 0); - HDassert(io_info->u.wbuf); + assert (efl && efl->nused>0); + assert (_buf); /* 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 *)io_info->u.wbuf + mem_offset_arr[v]; + buf = (const unsigned char *)_buf + 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 4879f4d..bfb4354 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_scatter_mem(tmp_buf, space, &mem_iter, (size_t)nelmts, dxpl_cache, buf/*out*/) < 0) { + if(H5D_select_mscat(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) - (void)H5FL_BLK_FREE(type_conv, tmp_buf); + 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) - (void)H5FL_BLK_FREE(type_conv, bkg_buf); + 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) - (void)H5FL_BLK_FREE(non_zero_fill, fb_info->fill_buf); + H5FL_BLK_FREE(non_zero_fill, fb_info->fill_buf); else - (void)H5FL_BLK_FREE(zero_fill, fb_info->fill_buf); + 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) - (void)H5FL_BLK_FREE(type_conv, fb_info->bkg_buf); + 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 acb95d2..a5ea398 100644 --- a/src/H5Dint.c +++ b/src/H5Dint.c @@ -59,12 +59,10 @@ 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); @@ -252,133 +250,6 @@ 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 * @@ -685,54 +556,6 @@ 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 @@ -1156,10 +979,18 @@ 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 */ @@ -1211,6 +1042,10 @@ 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") @@ -1238,6 +1073,10 @@ 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; @@ -1245,10 +1084,6 @@ 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") @@ -1417,9 +1252,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) @@ -1450,17 +1285,13 @@ 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 */ - 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) + 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) 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: @@ -1485,6 +1316,10 @@ 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; @@ -1509,34 +1344,33 @@ 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, "unknown storage method") + HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "not implemented yet") } /* 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((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 { + if(NULL == H5O_msg_read(&(dataset->oloc), H5O_FILL_NEW_ID, fill_prop, dxpl_id)) { + H5E_clear_stack(NULL); + /* For backward compatibility, try to retrieve the old fill value message */ - 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 { + if(NULL == H5O_msg_read(&(dataset->oloc), H5O_FILL_ID, fill_prop, dxpl_id)) { + H5E_clear_stack(NULL); + /* Set the space allocation time appropriately, based on the type of dataset storage */ switch(dataset->shared->layout.type) { case H5D_COMPACT: @@ -1554,7 +1388,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 else */ + } /* end if */ /* If "old" fill value size is 0 (undefined), map it to -1 */ if(fill_prop->size == 0) @@ -1578,23 +1412,18 @@ 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((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(NULL != H5O_msg_read(&(dataset->oloc), H5O_EFL_ID, &dataset->shared->dcpl_cache.efl, dxpl_id)) { 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 @@ -2505,7 +2334,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_RD(&io_info, dset, dxpl_cache, dxpl_id, NULL, NULL); + H5D_BUILD_IO_INFO(&io_info, dset, dxpl_cache, dxpl_id, 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 17bab19..8576464 100644 --- a/src/H5Dio.c +++ b/src/H5Dio.c @@ -28,17 +28,27 @@ #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 */ @@ -49,36 +59,64 @@ /* 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); + 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); -/* 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 */ /*******************/ @@ -86,6 +124,142 @@ static herr_t H5D_typeinfo_term(const H5D_type_info_t *type_info); /* 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() */ /*------------------------------------------------------------------------- @@ -126,7 +300,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, @@ -142,7 +316,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) { @@ -150,33 +324,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() */ +} /*------------------------------------------------------------------------- @@ -218,7 +392,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, @@ -234,7 +408,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) { @@ -242,7 +416,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 */ @@ -250,16 +424,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 */ @@ -268,7 +442,7 @@ H5Dwrite(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id, done: FUNC_LEAVE_API(ret_value) -} /* end H5Dwrite() */ +} /*------------------------------------------------------------------------- @@ -288,18 +462,16 @@ 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) @@ -307,6 +479,10 @@ 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) @@ -316,27 +492,23 @@ 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 */ @@ -367,56 +539,49 @@ 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, type_info.mem_type, mem_space, dxpl_id) < 0) + if(H5D_fill(dataset->shared->dcpl_cache.fill.buf, dataset->shared->type, buf, 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 */ - 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) + 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") #ifdef H5_HAVE_PARALLEL io_info_init = TRUE; #endif /*H5_HAVE_PARALLEL*/ - /* 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") + /* 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 */ 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() */ @@ -439,18 +604,16 @@ 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) @@ -458,33 +621,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_INTENT(dataset->oloc.file) & H5F_ACC_RDWR)) + if(0==(H5F_get_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(type_info.mem_type, H5T_VLEN) > 0) + if(H5T_detect_class(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. */ @@ -493,48 +656,42 @@ 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(type_info.mem_type, TRUE) == H5T_REFERENCE && - H5T_get_ref_type(type_info.mem_type) == H5R_DATASET_REGION) + if (H5T_get_class(mem_type, TRUE)==H5T_REFERENCE && + H5T_get_ref_type(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*/ - /* Initialize dataspace information */ - if(!file_space) + 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 */ @@ -546,36 +703,42 @@ 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 */ - 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") + 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") #ifdef H5_HAVE_PARALLEL io_info_init = TRUE; #endif /*H5_HAVE_PARALLEL*/ - /* 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") + /* 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 */ #ifdef OLD_WAY /* @@ -593,325 +756,2667 @@ 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 && H5D_ioinfo_term(&io_info) < 0) - HDONE_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "can't shut down io_info") + 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_write() */ /*------------------------------------------------------------------------- - * Function: H5D_ioinfo_init + * Function: H5D_contig_read * - * Purpose: Routine for determining correct I/O operations for - * each I/O action. + * Purpose: Read from a contiguous dataset. * * Return: Non-negative on success/Negative on failure * - * Programmer: Quincey Koziol - * Thursday, September 30, 2004 + * Programmer: Raymond Lu + * Thursday, April 10, 2003 * *------------------------------------------------------------------------- */ 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) +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*/) { - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_ioinfo_init) + 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 */ - /* check args */ - HDassert(dset); - HDassert(dset->oloc.file); - 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 = store; + herr_t ret_value = SUCCEED; /*return value */ - /* Set I/O operations to initial values */ - io_info->layout_ops = *dset->shared->layout_ops; + 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 */ - /* 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; + /* + * 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 */ + + /* 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)); - /* Set the I/O operations for reading/writing single blocks on disk */ - if(type_info->is_xform_noop && type_info->is_conv_noop) { /* - * 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. + * Gather the data from disk into the datatype conversion + * buffer. Also gather data from application to background buffer + * if necessary. */ - io_info->io_ops.single_read = H5D_select_read; - io_info->io_ops.single_write = H5D_select_write; +#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 */ + + /* + * 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, 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") } /* 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)); + /* - * This is the general case (type conversion, usually). + * Gather data from application buffer into the datatype conversion + * buffer. Also gather data from the file into the background buffer + * if necessary. */ - io_info->io_ops.single_read = H5D_scatgath_read; - io_info->io_ops.single_write = H5D_scatgath_write; - } /* end else */ +#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. + */ +#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 - /* 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 */ + /* 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 - FUNC_LEAVE_NOAPI(SUCCEED) -} /* end H5D_ioinfo_init() */ + +#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*/ + } /* 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_typeinfo_init + * Function: H5D_chunk_write * - * Purpose: Routine for determining correct datatype information for - * each I/O action. + * Purpose: Writes to a chunked dataset. * * Return: Non-negative on success/Negative on failure * - * Programmer: Quincey Koziol - * Tuesday, March 4, 2008 + * 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_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) +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) { - const H5T_t *src_type; /* Source datatype */ - const H5T_t *dst_type; /* Destination datatype */ - herr_t ret_value = SUCCEED; /* Return value */ + 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_typeinfo_init) + FUNC_ENTER_NOAPI_NOINIT(H5D_chunk_write) - /* check args */ - HDassert(type_info); - HDassert(dset); + assert (buf); - /* Initialize type info safely */ - HDmemset(type_info, 0, sizeof(H5D_type_info_t)); + /* 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") - /* 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; + /* 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 */ +#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 */ - 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; + /* 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() */ + + +/*------------------------------------------------------------------------- + * Function: H5D_compound_opt_read + * + * 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_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*/) +{ + 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 { - 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; + len=_len; + off=_off; } /* end else */ - /* - * 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 == (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; + + /* 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 */ + + /* Decrement number of elements left to process */ + nelmts -= elmtno; + } /* 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) +} /* 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) */ - 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") + 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]; - /* 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; + /* 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; + + /* 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 { - size_t target_size; /* Desired buffer size */ + /* 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; - /* Check if the datatypes are compound subsets of one another */ - type_info->cmpd_subset = H5T_path_compound_subset(type_info->tpath); + /* 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 we need a background buffer */ - if(do_write && H5T_detect_class(dset->shared->type, H5T_VLEN)) - type_info->need_bkg = H5T_BKG_YES; + /* 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 */ else { - H5T_bkg_t path_bkg; /* Type conversion's background info */ + /* 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; - 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); + /* 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 */ } /* 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 */ - /* Set up datatype conversion/background buffers */ + FUNC_ENTER_NOAPI_NOINIT(H5D_create_chunk_map_single) - /* Get buffer size from DXPL */ - target_size = dxpl_cache->max_temp_buf; + /* Sanity check */ + HDassert(fm->f_ndims > 0); - /* 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 */ + /* 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") - /* 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); + /* Initialize the 'single chunk' file & memory chunk information */ + chunk_info = fm->single_chunk_info; + chunk_info->chunk_points = 1; - /* 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") + /* 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); } /* end if */ - /* Compute the number of elements that will fit into buffer */ - type_info->request_nelmts = target_size / type_info->max_type_size; + /* Increment chunk index */ + chunk_index++; - /* 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") + /* Set current increment dimension */ + curr_dim=(int)fm->f_ndims-1; - /* - * 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(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; + /* 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 */ - 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 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_typeinfo_init() */ +} /* end H5D_chunk_file_cb() */ -#ifdef H5_HAVE_PARALLEL /*------------------------------------------------------------------------- - * Function: H5D_ioinfo_adjust + * Function: H5D_chunk_mem_cb * - * Purpose: Adjust operation's I/O info for any parallel I/O + * 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_ioinfo_init + * + * Purpose: Routine for determining correct I/O operations for + * each I/O action. * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol - * Thursday, March 27, 2008 + * Thursday, September 30, 2004 * *------------------------------------------------------------------------- */ 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) +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) { herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5D_ioinfo_adjust) +#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 */ /* check args */ HDassert(dset); HDassert(dset->oloc.file); HDassert(mem_space); HDassert(file_space); - HDassert(type_info); - HDassert(type_info->tpath); + HDassert(tpath); HDassert(io_info); - /* Make any parallel I/O adjustments */ + /* 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); + 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(MPI_COMM_NULL == (io_info->comm = H5F_mpi_get_comm(dset->oloc.file))) + if((io_info->comm = H5F_mpi_get_comm(dset->oloc.file)) == MPI_COMM_NULL) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't retrieve MPI communicator") - /* 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 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 use the optimized parallel I/O routines */ - 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; + 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; } /* 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_adjust() */ +} /* end H5D_ioinfo_init() */ +#ifdef H5_HAVE_PARALLEL /*------------------------------------------------------------------------- * Function: H5D_ioinfo_term @@ -933,69 +3438,23 @@ H5D_ioinfo_term(H5D_io_info_t *io_info) FUNC_ENTER_NOAPI_NOINIT(H5D_ioinfo_term) - /* 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 */ + /* 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 */ - /* 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 */ + /* 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") - /* 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 */ + /* 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") } /* end if */ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5D_ioinfo_term() */ -#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() */ +#endif diff --git a/src/H5Distore.c b/src/H5Distore.c index efab271..47e4cab 100644 --- a/src/H5Distore.c +++ b/src/H5Distore.c @@ -104,12 +104,30 @@ */ #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 @@ -174,7 +192,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) */ - const hsize_t *down_chunks; + hsize_t *down_chunks; haddr_t *chunk_addr; } H5D_istore_it_ud5_t; @@ -1472,7 +1490,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_WRT(&io_info, dset, dxpl_cache, dxpl_id, NULL, NULL); + H5D_BUILD_IO_INFO(&io_info, dset, dxpl_cache, dxpl_id, NULL); /* Loop over all entries in the chunk cache */ for(ent = rdcc->head; ent; ent = next) { @@ -1507,48 +1525,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) - HDassert(dset); + assert(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_WRT(&io_info, dset, dxpl_cache, dxpl_id, NULL, NULL); + H5D_BUILD_IO_INFO(&io_info,dset,dxpl_cache,dxpl_id,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++; - } /* end for */ - if(nerrors) + } + 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: @@ -1817,7 +1835,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_CHUNK_HASH(dset->shared, io_info->store->chunk.index); + idx = H5D_HASH(dset->shared,io_info->store->chunk.index); ent = rdcc->slot[idx]; if(ent) @@ -1932,8 +1950,10 @@ 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 */ @@ -2134,6 +2154,339 @@ 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 @@ -2214,16 +2567,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_WRT(&io_info, dset, dxpl_cache, dxpl_id, NULL, NULL); + H5D_BUILD_IO_INFO(&io_info,dset,dxpl_cache,dxpl_id,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 */ @@ -2256,7 +2609,7 @@ done: */ herr_t H5D_istore_chunkmap(const H5D_io_info_t *io_info, haddr_t chunk_addr[], - const hsize_t down_chunks[]) + hsize_t down_chunks[]) { H5D_t *dset = io_info->dset; /* Local pointer to dataset info */ H5D_istore_it_ud5_t udata; @@ -2555,7 +2908,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_WRT(&io_info, dset, dxpl_cache, data_dxpl_id, &store, NULL); + H5D_BUILD_IO_INFO(&io_info, dset, dxpl_cache, data_dxpl_id, &store); /* Reset the chunk offset indices */ HDmemset(chunk_offset, 0, (layout->u.chunk.ndims * sizeof(chunk_offset[0]))); @@ -3221,7 +3574,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_scatter_mem(fb_info.fill_buf, space_chunk, &chunk_iter, (size_t)nelmts, io_info->dxpl_cache, chunk/*out*/) < 0) { + if(H5D_select_mscat(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 */ @@ -3375,7 +3728,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_WRT(&io_info, dset, dxpl_cache, dxpl_id, NULL, NULL); + H5D_BUILD_IO_INFO(&io_info, dset, dxpl_cache, dxpl_id, NULL); /* Recompute the index for each cached chunk that is in a dataset */ for(ent = rdcc->head; ent; ent = next) { @@ -3391,7 +3744,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_CHUNK_HASH(dset->shared, idx); + ent->idx=H5D_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 889fbce..22f32ab 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 "H5Iprivate.h" /* IDs */ -#include "H5MMprivate.h" /* Memory management */ +#include "H5MMprivate.h" #include "H5Oprivate.h" /* Object headers */ #include "H5Pprivate.h" /* Property lists */ #include "H5Sprivate.h" /* Dataspaces */ @@ -86,7 +86,6 @@ #define H5D_CHUNK_SELECT_IRREG 2 #define H5D_CHUNK_SELECT_NONE 0 - /******************/ /* Local Typedefs */ /******************/ @@ -96,47 +95,66 @@ 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_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_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_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 */ /*******************/ @@ -157,77 +175,64 @@ 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 *file_space, - const H5S_t *mem_space, const H5D_type_info_t *type_info, - const H5D_chunk_map_t *fm) +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) { - 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 */ - HDassert(io_info); - HDassert(mem_space); - HDassert(file_space); - HDassert(type_info); + assert(io_info); + assert(mem_space); + assert(file_space); /* 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 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. - */ + /* 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. + */ #ifndef H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS if(io_info->dset->shared->layout.type == H5D_CONTIGUOUS) if((H5S_SELECT_IS_REGULAR(file_space) != TRUE) || @@ -238,46 +243,84 @@ H5D_mpio_opt_possible(const H5D_io_info_t *io_info, const H5S_t *file_space, #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 */ -/* 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 */ + /* 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; } /* 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) + 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 + + +/*------------------------------------------------------------------------- * Function: H5D_mpio_select_read * * Purpose: MPI-IO function to read directly from app buffer to file. @@ -289,20 +332,23 @@ done: *------------------------------------------------------------------------- */ herr_t -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) +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*/) { - 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) - - 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") + FUNC_ENTER_NOAPI(H5D_mpio_select_read,FAIL); + 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() */ @@ -318,28 +364,32 @@ done: *------------------------------------------------------------------------- */ herr_t -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) +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) { - 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*/ - 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") + 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"); done: - FUNC_LEAVE_NOAPI(ret_value) + FUNC_LEAVE_NOAPI(ret_value); } /* end H5D_mpio_select_write() */ /*------------------------------------------------------------------------- - * Function: H5D_ioinfo_xfer_mode + * Function: H5D_ioinfo_make_ind * - * Purpose: Switch to between collective & independent MPI I/O + * Purpose: Switch to MPI independent I/O * * Return: Non-negative on success/Negative on failure * @@ -349,42 +399,42 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5D_ioinfo_xfer_mode(H5D_io_info_t *io_info, H5P_genplist_t *dx_plist, - H5FD_mpio_xfer_t xfer_mode) +H5D_ioinfo_make_ind(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_xfer_mode) + 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") - /* 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) + /* 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) HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set transfer mode") - /* 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); + /* Set the pointers to the non-MPI-specific routines */ + io_info->ops.read = H5D_select_read; + io_info->ops.write = H5D_select_write; - /* 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 */ + /* Indicate that the transfer mode should be restored before returning + * to user. + */ + io_info->xfer_mode_changed=TRUE; done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5D_ioinfo_xfer_mode() */ +} /* end H5D_ioinfo_make_ind() */ /*------------------------------------------------------------------------- - * Function: H5D_ioinfo_coll_opt_mode + * Function: H5D_ioinfo_make_coll_opt * - * Purpose: Switch between using collective & independent MPI I/O w/file - * set view + * Purpose: Switch to MPI independent I/O with file set view * * Return: Non-negative on success/Negative on failure * @@ -394,21 +444,87 @@ done: *------------------------------------------------------------------------- */ 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) +H5D_ioinfo_make_coll_opt(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_coll_opt_mode) + FUNC_ENTER_NOAPI_NOINIT(H5D_ioinfo_make_coll_opt) - /* 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) + /* 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) 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_coll_opt_mode() */ +} /* 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() */ /*------------------------------------------------------------------------- @@ -419,30 +535,29 @@ done: * * Return: Non-negative on success/Negative on failure * - * Programmer: Muqun Yang - * Monday, Feb. 13th, 2006 + * Programmer: * *------------------------------------------------------------------------- */ 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() */ @@ -454,252 +569,221 @@ done: * * Return: Non-negative on success/Negative on failure * - * Programmer: Muqun Yang - * Monday, Feb. 13th, 2006 + * Programmer: * *------------------------------------------------------------------------- */ 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_read + * Function: H5D_contig_collective_io * - * Purpose: Reads directly from contiguous data in file into application - * memory using collective I/O. + * 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. + * * * Return: Non-negative on success/Negative on failure * - * Programmer: Quincey Koziol - * Tuesday, March 4, 2008 + * Programmer: + * + * Modifications: * *------------------------------------------------------------------------- */ herr_t -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) +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) { - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(H5D_contig_collective_read, FAIL) - - /* 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") -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5D_contig_collective_read() */ + haddr_t addr = HADDR_UNDEF; /* Address of dataset (or selection) within file */ + herr_t ret_value = SUCCEED; /* return value */ - -/*------------------------------------------------------------------------- - * 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 */ + FUNC_ENTER_NOAPI_NOINIT(H5D_contig_collective_io) + assert (IS_H5FD_MPIO(io_info->dset->oloc.file)); - FUNC_ENTER_NOAPI(H5D_contig_collective_write, FAIL) + /* Make certain we have the correct type of property list */ + assert(TRUE==H5P_isa_class(io_info->dxpl_id,H5P_DATASET_XFER)); - /* Sanity check */ - HDassert(IS_H5FD_MPIO(io_info->dset->oloc.file)); - HDassert(TRUE == H5P_isa_class(io_info->dxpl_id, H5P_DATASET_XFER)); + /* 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); - /* 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") + 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: -done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5D_contig_collective_write() */ +} /* end H5D_contig_collective_io */ /*------------------------------------------------------------------------- * 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: Muqun Yang - * Monday, Feb. 13th, 2006 + * Programmer: + * + * Modifications: * *------------------------------------------------------------------------- */ -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) +herr_t +H5D_chunk_collective_io(H5D_io_info_t *io_info,H5D_chunk_map_t *fm,const void *buf, hbool_t do_write) { - H5P_genplist_t *dx_plist; /* Pointer to DXPL */ + + 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; 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 temp_not_link_io = FALSE; + htri_t check_prop,temp_not_link_io = FALSE; + int new_value; #endif - herr_t ret_value = SUCCEED; + herr_t ret_value = SUCCEED; FUNC_ENTER_NOAPI_NOINIT(H5D_chunk_collective_io) - /* Sanity checks */ - HDassert(io_info); - HDassert(io_info->using_mpi_vfd); - HDassert(type_info); - HDassert(fm); + assert (IS_H5FD_MPIO(io_info->dset->oloc.file)); /* Obtain the data transfer properties */ - if(NULL == (dx_plist = H5I_object(io_info->dxpl_id))) + if(NULL == (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(dx_plist, H5D_XFER_MPIO_CHUNK_OPT_HARD_NAME); + 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_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 { - 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) + 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"); - one_link_chunk_io_threshold = H5P_peek_unsigned(dx_plist, H5D_XFER_MPIO_CHUNK_OPT_NUM_NAME); + 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); - /* 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; -#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; + else + temp_not_link_io = TRUE; #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_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); + 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); 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_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(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(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_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(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(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_IO, H5E_CANTSET, FAIL, "unable to set property value") - } /* end if */ - } /* end if */ -} + 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; #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, 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 */ + 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"); + } else { /*multiple chunk IOs with opt */ - 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 */ + 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"); + } done: FUNC_LEAVE_NOAPI(ret_value) @@ -707,583 +791,459 @@ done: /*------------------------------------------------------------------------- - * Function: H5D_chunk_collective_read - * - * 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 + * Function: H5D_link_chunk_collective_io * - *------------------------------------------------------------------------- - */ -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 */ - - FUNC_ENTER_NOAPI(H5D_chunk_collective_read, FAIL) + * Purpose: Routine for one collective IO with one MPI derived datatype to link with all chunks - /* Call generic selection operation */ - if(H5D_chunk_collective_io(io_info, type_info, fm) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_READERROR, FAIL, "read error") + 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 -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5D_chunk_collective_read() */ - - -/*------------------------------------------------------------------------- - * Function: H5D_chunk_collective_write - * - * Purpose: Write directly to chunks 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_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: * - * Programmer: Muqun Yang - * Monday, Feb. 13th, 2006 + * Modifications: * *------------------------------------------------------------------------- */ + 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) +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_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") + 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; - /* Check for this process having selection in this chunk */ chunk_node = H5SL_first(fm->sel_chunks); if(chunk_node == NULL) { - /* Set the dataspace info for I/O to NULL, this process doesn't have any I/O to perform */ - fspace = mspace = NULL; - } /* end if */ + 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"); + } else { - 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(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; + 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; + } - /* 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); + /* Allocate chunking information */ + ori_num_chunk = H5SL_count(fm->sel_chunks); + H5_ASSIGN_OVERFLOW(num_chunk,ori_num_chunk,size_t,int); #ifdef H5D_DEBUG -if(H5DEBUG(D)) - HDfprintf(H5DEBUG(D),"total_chunks = %Zu, num_chunk = %Zu\n", total_chunks, num_chunk); + if(H5DEBUG(D)) + HDfprintf(H5DEBUG(D),"total_chunks = %d\n",(int)total_chunks); #endif - - /* 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)); + + 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; #ifdef H5D_DEBUG -if(H5DEBUG(D)) + if(H5DEBUG(D)) HDfprintf(H5DEBUG(D),"before sorting the chunk address \n"); #endif - /* 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; + + /* 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; + } #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(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 */ + + /* 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; + } #ifdef H5D_DEBUG -if(H5DEBUG(D)) + if(H5DEBUG(D)) HDfprintf(H5DEBUG(D),"before coming to final collective IO\n"); #endif - /* 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 */ + 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"); 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(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) + 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) } /* 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 + + 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 * - * Programmer: Muqun Yang - * Monday, Feb. 13th, 2006 + * Programmer: + * + * Modifications: * *------------------------------------------------------------------------- */ 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) +H5D_multi_chunk_collective_io(H5D_io_info_t *io_info,H5D_chunk_map_t *fm,const void *buf, hbool_t do_write) { - 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 */ + 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; #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 - /* 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)); + /* 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)); #ifdef H5D_DEBUG -if(H5DEBUG(D)) - HDfprintf(H5DEBUG(D), "total_chunk %Zu\n", total_chunk); + if(H5DEBUG(D)) + HDfprintf(H5DEBUG(D),"total_chunk %u\n",total_chunk); #endif - /* 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 */ + /* 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"); + for(i = 0; i < total_chunk; i++) { #ifdef H5D_DEBUG -if(H5DEBUG(D)) - HDfprintf(H5DEBUG(D),"mpi_rank = %d, chunk index = %Zu\n", mpi_rank, u); + if(H5DEBUG(D)) + HDfprintf(H5DEBUG(D),"mpi_rank = %d, chunk index = %u\n",mpi_rank,i); #endif - /* 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) { + 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.*/ #ifdef H5D_DEBUG -if(H5DEBUG(D)) - HDfprintf(H5DEBUG(D),"inside collective chunk IO mpi_rank = %d, chunk index = %Zu\n", mpi_rank, u); + if(H5DEBUG(D)) + HDfprintf(H5DEBUG(D),"inside collective chunk IO mpi_rank = %d, chunk index = %u\n",mpi_rank,i); #endif - /* 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(!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") - /* 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 */ + 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*/ #ifdef H5D_DEBUG -if(H5DEBUG(D)) - HDfprintf(H5DEBUG(D),"inside independent IO mpi_rank = %d, chunk index = %Zu\n", mpi_rank, u); + if(H5DEBUG(D)) + HDfprintf(H5DEBUG(D),"inside independent IO mpi_rank = %d, chunk index = %u\n",mpi_rank,i); #endif - HDassert(chunk_io_option[u] == 0); + HDassert(chunk_io_option[i] == 0); #if !defined(H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS) || !defined(H5_MPI_SPECIAL_COLLECTIVE_IO_WORKS) - /* 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 */ - + if(!select_chunk) + continue; /* this process has nothing to do with this chunk, continue! */ + if(last_io_mode_coll) /* Switch to independent I/O */ - 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 */ - - /* 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") - - /* 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(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(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) { + if(!do_write) + dirty = FALSE; - /* 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 */ + 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"); + } else { - 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 */ + 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"); + } - /* 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 /* !defined(H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS) || !defined(H5_MPI_SPECIAL_COLLECTIVE_IO_WORKS) */ - } /* end else */ - } /* end for */ - +#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") done: - if(chunk_io_option) - H5MM_xfree(chunk_io_option); - if(chunk_addr) - H5MM_xfree(chunk_addr); + HDfree(chunk_io_option); + HDfree(chunk_addr); FUNC_LEAVE_NOAPI(ret_value) } /* end H5D_multi_chunk_collective_io */ @@ -1297,105 +1257,90 @@ 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: Muqun Yang - * Monday, Feb. 13th, 2006 + * Programmer: + * + * Modifications: * *------------------------------------------------------------------------- */ 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) +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_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) + 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 H5D_DEBUG -if(H5DEBUG(D)) { - int mpi_rank; +#ifdef H5Dmpio_DEBUG + int mpi_rank; +#endif + FUNC_ENTER_NOAPI_NOINIT(H5D_multi_chunk_collective_io_no_opt) +#ifdef H5D_DEBUG + if(H5DEBUG(D)){ 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 - /* 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; + 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; + } - /* 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. @@ -1404,92 +1349,67 @@ if(H5DEBUG(D)) { 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(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") - - /* 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 */ - - /* Compute # of bytes accessed in chunk */ - accessed_bytes = chunk_info->chunk_points * type_info->src_type_size; + 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") - /* 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; + 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"); - /* 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 = chunk_addr; - - /* No chunk cached */ - chunk = NULL; + 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") + } - /* Point I/O info at temporary I/O info for this chunk */ - chk_io_info = &ctg_io_info; - } /* end else */ + /* Release the cache lock on the chunk. */ + if(chunk) { + if(!do_write) + dirty = FALSE; - 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") + 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 */ } /* 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 */ + 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 */ done: FUNC_LEAVE_NOAPI(ret_value) @@ -1500,266 +1420,303 @@ 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: Muqun Yang - * Monday, Feb. 13th, 2006 + * Programmer: + * + * Modifications: * *------------------------------------------------------------------------- */ 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) +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 ) { - 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 */ - /* 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 */ + 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; #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 - /* 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) - + 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: #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: Muqun Yang - * Monday, Feb. 13th, 2006 + * Programmer: + * + * Modifications: * *------------------------------------------------------------------------- */ static herr_t -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) +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) { - int mpi_code; /* MPI return code */ - hbool_t plist_is_setup = FALSE; /* Whether the dxpl has been customized */ - herr_t ret_value = SUCCEED; + + + int mpi_code; /* MPI return code */ + hbool_t plist_is_setup=0; /* 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") - plist_is_setup = TRUE; + /* + * 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"); - 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) + 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) HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "optimized write failed") - } /* end if */ + } else { - if((io_info->io_ops.single_read)(io_info, type_info, - (hsize_t)mpi_buf_count, NULL, NULL) < 0) + if((io_info->ops.read)(io_info, + coll_info->mpi_buf_count,0,NULL,NULL,coll_info->chunk_addr, + NULL, buf) < 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") - + /* 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); + } #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. + + 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 * * Return: Non-negative on success/Negative on failure * - * Programmer: Muqun Yang - * Monday, Feb. 13th, 2006 + * Programmer: + * + * Modifications: * *------------------------------------------------------------------------- */ + 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 sum_chunk) +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) { - 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 */ - 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 */ + 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 */ FUNC_ENTER_NOAPI_NOINIT(H5D_sort_chunk) - /* 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; - + num_chunks = H5SL_count(fm->sel_chunks); #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) { - int mpi_rank; + if(many_chunk_opt != H5D_OBTAIN_ONE_CHUNK_ADDR_IND){ + 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 - /* 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 */ - + 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"); + } /* Broadcasting the MPI_IO option info. and chunk address info. */ - 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) + 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); } /* 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; - - /* Start at first node in chunk skip list */ + 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; i = 0; - if(NULL == (chunk_node = H5SL_first(fm->sel_chunks))) - HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL,"couldn't get chunk node from skipped list") + 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"); - /* 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]; +#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]; - /* 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_addr_info_array[i].chunk_addr = chunk_addr; + chunk_addr_info_array[i].chunk_info = *chunk_info; - /* 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; + chunk_node = H5SL_next(chunk_node); - /* Advance to next chunk in list */ - i++; - chunk_node = H5SL_next(chunk_node); - } /* end while */ + while(chunk_node) { + 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) { - 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 */ + if(do_sort) + HDqsort(chunk_addr_info_array,num_chunks,sizeof(chunk_addr_info_array),H5D_cmp_chunk_addr); 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() */ @@ -1768,244 +1725,310 @@ 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. + + 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 * * Return: Non-negative on success/Negative on failure * - * Programmer: Muqun Yang - * Monday, Feb. 13th, 2006 + * Programmer: + * + * Modifications: * *------------------------------------------------------------------------- */ + 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[]) +H5D_obtain_mpio_mode(H5D_io_info_t* io_info, + H5D_chunk_map_t *fm, + uint8_t assign_io_mode[], + haddr_t chunk_addr[]) { - 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; + + 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; + #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; - FUNC_ENTER_NOAPI_NOINIT(H5D_obtain_mpio_mode) + herr_t ret_value = SUCCEED; - /* Assign the rank 0 to the root */ - root = 0; - comm = io_info->comm; + FUNC_ENTER_NOAPI_NOINIT(H5D_obtain_mpio_mode) - /* 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") + /* 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"); - /* 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); + /* 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); #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(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 */ + + 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; + } #endif - 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); + 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); - mem_cleanup = 1; + mem_cleanup = 1; - /* 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); + 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); #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); - } /* end while */ + + chunk_node = H5SL_next(chunk_node); + } - /*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; + /*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; #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") - } /* 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]++; + 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]++; #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; - } /* end else */ + /*checking whether we have a selection in this chunk */ + ind_this_chunk[ic] = 1; + } #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, 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,sizeof(MPI_BYTE)*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, ((sizeof(haddr_t) + 1) * total_chunks), MPI_BYTE, 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,1,rtype,root,comm))) + HMPI_GOTO_ERROR(FAIL, "MPI_BCast failed", mpi_code); - HDmemcpy(assign_io_mode, mergebuf, total_chunks); - HDmemcpy(chunk_addr, tempbuf, sizeof(haddr_t) * total_chunks); + HDmemcpy(assign_io_mode,mergebuf,sizeof(MPI_BYTE)*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; - } /* end if */ - } /* end for */ + 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; + } + } #endif - } /* 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 */ + } + 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"); + } + } #endif done: - if(mem_cleanup) { - HDfree(io_mode_info); - HDfree(mergebuf); - if(mpi_rank == root) - HDfree(recv_io_mode_info); - } /* end if */ + + 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); + } 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) @@ -2018,6 +2041,7 @@ 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 37f011b..01447a3 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 = (H5D_t *)H5I_object(obj_id))) + if(NULL == (dset = 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 97dcacf..aec5e19 100644 --- a/src/H5Dpkg.h +++ b/src/H5Dpkg.h @@ -49,156 +49,74 @@ #define H5D_MINHDR_SIZE 256 /* [Simple] Macro to construct a H5D_io_info_t from it's components */ -#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) +#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 /****************************/ /* Package Private Typedefs */ /****************************/ -/* 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 */ +/* + * 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 */ struct H5D_io_info_t; -struct H5D_chunk_map_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); /* Function pointers for I/O on particular types of dataset layouts */ -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, +typedef ssize_t (*H5D_io_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[]); -typedef ssize_t (*H5D_layout_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[], + 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 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[]); -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); + 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); /* Typedef for raw data I/O framework info */ typedef struct H5D_io_ops_t { - 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_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_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 cached DXPL info */ + H5D_dxpl_cache_t *dxpl_cache; /* Pointer to cache 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 */ - 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; + 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_io_info_t; /* Structure holding information about a chunk's selection for mapping */ @@ -265,8 +183,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*/ @@ -311,21 +229,18 @@ 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 chunks covered by dataspace */ - H5D_chunk_info_t **select_chunk; /* Store the information about whether this chunk is selected or not */ + hsize_t total_chunks; /* Number of total chunks */ + hbool_t *select_chunk; /* store the information about whether this chunk is selected or not */ #endif /* H5_HAVE_PARALLEL */ } H5D_chunk_map_t; @@ -417,34 +332,12 @@ 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 */ @@ -468,51 +361,54 @@ 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); -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, + +/* 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, const H5S_t *space, H5S_sel_iter_t *iter, size_t nelmts, - 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); + 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*/); /* 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[]); + 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); 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[]); + 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); 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); @@ -534,11 +430,19 @@ 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[], const hsize_t down_chunks[]); +H5_DLL herr_t H5D_istore_chunkmap(const H5D_io_info_t *io_info, haddr_t chunk_addr[],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, @@ -548,6 +452,17 @@ 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, @@ -570,37 +485,36 @@ 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(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 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 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 *file_space, const H5S_t *mem_space, - const H5D_type_info_t *type_info, const H5D_chunk_map_t *fm); +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 */ #endif /* H5_HAVE_PARALLEL */ diff --git a/src/H5Dprivate.h b/src/H5Dprivate.h index 8cf134f..410dc43 100644 --- a/src/H5Dprivate.h +++ b/src/H5Dprivate.h @@ -65,6 +65,7 @@ #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" @@ -106,6 +107,23 @@ /* 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) */ @@ -117,7 +135,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 coll_opt_mode; /* Parallel transfer with independent IO or collective IO with this mode */ + H5FD_mpio_collective_opt_t xfer_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) */ @@ -145,6 +163,8 @@ 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 deleted file mode 100644 index 3ea4c69..0000000 --- a/src/H5Dscatgath.c +++ /dev/null @@ -1,899 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * 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 947c81e..f08672f 100644 --- a/src/H5Dselect.c +++ b/src/H5Dselect.c @@ -34,37 +34,400 @@ #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(size_t); +H5FL_SEQ_DEFINE_STATIC(size_t); /* Declare a free list to manage sequences of hsize_t */ -H5FL_SEQ_DEFINE(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]; + 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() */ /*------------------------------------------------------------------------- @@ -80,8 +443,11 @@ H5FL_SEQ_DEFINE(hsize_t); *------------------------------------------------------------------------- */ static herr_t -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) +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) { H5S_sel_iter_t mem_iter; /* Memory selection iteration info */ hbool_t mem_iter_init = 0; /* Memory selection iteration info has been initialized */ @@ -109,10 +475,10 @@ H5D_select_io(const H5D_io_info_t *io_info, size_t elmt_size, HDassert(io_info->dset); HDassert(io_info->store); HDassert(TRUE == H5P_isa_class(io_info->dxpl_id, H5P_DATASET_XFER)); - HDassert(io_info->u.rbuf); + HDassert(io_buf->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))) @@ -145,17 +511,19 @@ H5D_select_io(const H5D_io_info_t *io_info, size_t elmt_size, *file_len = *mem_len = elmt_size; /* Perform I/O on memory and file sequences */ - if(io_info->op_type == H5D_IO_OP_READ) { - if((tmp_file_len = (*io_info->layout_ops.readvv)(io_info, + if(io_buf->op_type == H5S_SELECT_READ) { + if((tmp_file_len = (*io_info->ops.readvv)(io_info, file_nseq, &curr_file_seq, file_len, file_off, - mem_nseq, &curr_mem_seq, mem_len, mem_off)) < 0) + mem_nseq, &curr_mem_seq, mem_len, mem_off, + addr, chunk, io_buf->u.rbuf)) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_READERROR, FAIL, "read error") } /* end if */ else { - HDassert(io_info->op_type == H5D_IO_OP_WRITE); - if((tmp_file_len = (*io_info->layout_ops.writevv)(io_info, + HDassert(io_buf->op_type == H5S_SELECT_WRITE); + if((tmp_file_len = (*io_info->ops.writevv)(io_info, file_nseq, &curr_file_seq, file_len, file_off, - mem_nseq, &curr_mem_seq, mem_len, mem_off)) < 0) + mem_nseq, &curr_mem_seq, mem_len, mem_off, + addr, chunk, io_buf->u.wbuf)) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_WRITEERROR, FAIL, "write error") } /* end else */ @@ -203,17 +571,19 @@ H5D_select_io(const H5D_io_info_t *io_info, size_t elmt_size, } /* end if */ /* Perform I/O on memory and file sequences */ - if(io_info->op_type == H5D_IO_OP_READ) { - if((tmp_file_len = (*io_info->layout_ops.readvv)(io_info, + if(io_buf->op_type == H5S_SELECT_READ) { + if((tmp_file_len = (*io_info->ops.readvv)(io_info, file_nseq, &curr_file_seq, file_len, file_off, - mem_nseq, &curr_mem_seq, mem_len, mem_off)) < 0) + mem_nseq, &curr_mem_seq, mem_len, mem_off, + addr, chunk, io_buf->u.rbuf)) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_READERROR, FAIL, "read error") } /* end if */ else { - HDassert(io_info->op_type == H5D_IO_OP_WRITE); - if((tmp_file_len = (*io_info->layout_ops.writevv)(io_info, + HDassert(io_buf->op_type == H5S_SELECT_WRITE); + if((tmp_file_len = (*io_info->ops.writevv)(io_info, file_nseq, &curr_file_seq, file_len, file_off, - mem_nseq, &curr_mem_seq, mem_len, mem_off)) < 0) + mem_nseq, &curr_mem_seq, mem_len, mem_off, + addr, chunk, io_buf->u.wbuf)) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_WRITEERROR, FAIL, "write error") } /* end else */ @@ -234,15 +604,17 @@ done: if(H5S_SELECT_ITER_RELEASE(&mem_iter) < 0) HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator") - /* 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); + /* 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 */ FUNC_LEAVE_NOAPI(ret_value) } /* end H5D_select_io() */ @@ -261,17 +633,23 @@ done: *------------------------------------------------------------------------- */ 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) +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_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 */ - 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) + if(H5D_select_io(io_info, nelmts, elmt_size, file_space, mem_space, addr, chunk, &io_buf) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_READERROR, FAIL, "read error") done: @@ -292,17 +670,23 @@ done: *------------------------------------------------------------------------- */ 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) +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_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 */ - 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) + if(H5D_select_io(io_info, nelmts, elmt_size, file_space, mem_space, addr, chunk, &io_buf) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_WRITEERROR, FAIL, "write error") done: @@ -978,9 +978,6 @@ done: * Programmer: Robb Matzke * matzke@llnl.gov * Jul 18 1997 - * Modifications: - * Vailin Choi, April 2, 2008 - * Free f->extpath * *------------------------------------------------------------------------- */ @@ -1071,7 +1068,6 @@ 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) @@ -1082,8 +1078,6 @@ H5F_dest(H5F_t *f, hid_t dxpl_id) FUNC_LEAVE_NOAPI(ret_value) } /* end H5F_dest() */ - - /*------------------------------------------------------------------------- * Function: H5F_open @@ -1163,9 +1157,6 @@ 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 * @@ -1362,10 +1353,6 @@ 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; @@ -2153,33 +2140,6 @@ 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 @@ -3658,3 +3618,4 @@ 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 0384018..90aa0e2 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 chunked dataset I/O */ +/* Type of I/O for data transfer properties */ 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 collective I/O */ +/* Type of I/O for data transfer properties */ 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 89a8637..c8087bb 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 */ - hbool_t use_view_this_time = FALSE; - herr_t ret_value = SUCCEED; + unsigned use_view_this_time=0; + 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,23 +1497,28 @@ 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); - if(coll_opt_mode == H5FD_MPIO_COLLECTIVE_IO) { + /* 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) { #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 - 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 */ +/* 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) + } 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) - } /* end else */ + 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) + } /* * Reset the file view when we used MPI derived types @@ -1695,7 +1700,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 */ - hbool_t use_view_this_time = FALSE; + unsigned use_view_this_time=0; H5P_genplist_t *plist; /* Property list pointer */ herr_t ret_value=SUCCEED; @@ -1713,25 +1718,26 @@ 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 */ @@ -1743,71 +1749,114 @@ 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 { - /* 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 */ + 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 HGOTO_DONE(SUCCEED) /* skip the actual write */ -#endif /* LATER */ + } /* end if */ } /* end if */ /* Write the data. */ - if(use_view_this_time) { - H5FD_mpio_collective_opt_t coll_opt_mode; - + 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']) + 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); + 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); /*OKAY: CAST DISCARDS CONST QUALIFIER*/ - if(coll_opt_mode == H5FD_MPIO_COLLECTIVE_IO) { + if(coll_opt_mode == H5FD_MPIO_COLLECTIVE_IO && xfer_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 - 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 */ + /* 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) + } 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) - } /* end else */ + + 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) + } + - /* 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) @@ -1823,31 +1872,48 @@ H5FD_mpio_write(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, * 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 8ad9631..74a9aab 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 = H5V_limit_enc_size((uint64_t)fspace->serial_sect_count); + sect_cnt_size = MAX(1, (H5V_log2_gen(fspace->serial_sect_count) + 7) / 8); #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 = H5V_limit_enc_size((uint64_t)sinfo->fspace->serial_sect_count); + udata.sect_cnt_size = MAX(1, (H5V_log2_gen(sinfo->fspace->serial_sect_count) + 7) / 8); #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 34da067..c589aa0 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_limit_enc_size((uint64_t)fspace->max_sect_size); + sinfo->sect_len_size = (H5V_log2_gen(fspace->max_sect_size) + 7) / 8; 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 * H5V_limit_enc_size((uint64_t)fspace->serial_sect_count); + sect_buf_size += fspace->sinfo->serial_size_count * MAX(1, ((H5V_log2_gen(fspace->serial_sect_count) + 7) / 8)); /* 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 288ef8a..3f10e1a 100644 --- a/src/H5Fpkg.h +++ b/src/H5Fpkg.h @@ -142,7 +142,6 @@ 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 27b45f2..1044b14 100644 --- a/src/H5Fprivate.h +++ b/src/H5Fprivate.h @@ -265,7 +265,6 @@ 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) @@ -285,7 +284,6 @@ 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))) @@ -419,7 +417,6 @@ 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 60d5002..c1b856b 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_limit_enc_size((uint64_t)hdr->max_man_size)); + ((H5V_log2_gen((uint64_t)hdr->max_man_size) + 7) / 8)); done: FUNC_LEAVE_NOAPI(ret_value) diff --git a/src/H5HFiblock.c b/src/H5HFiblock.c index 7fedc48..70133aa 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, H5HF_indirect_t *par_iblock, unsigned par_entry, hsize_t *heap_size) + unsigned nrows, 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, par_iblock, par_entry, FALSE, H5AC_READ, &did_protect))) + if(NULL == (iblock = H5HF_man_iblock_protect(hdr, dxpl_id, iblock_addr, nrows, NULL, 0, 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,14 +1624,13 @@ 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[hdr->man_dtable.max_direct_rows]) - first_row_bits) + 1; + num_indirect_rows = (H5V_log2_gen(hdr->man_dtable.row_block_size[u]) - 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, iblock, entry, heap_size) < 0) + if(H5HF_man_iblock_size(f, dxpl_id, hdr, iblock->ents[entry].addr, num_indirect_rows, heap_size) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to get fractal heap storage info for indirect block") } /* end for */ } /* end if */ @@ -1640,7 +1639,6 @@ 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 fd332e5..702ce08 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, H5HF_indirect_t *par_iblock, unsigned par_entry, hsize_t *heap_size/*out*/); + haddr_t iblock_addr, unsigned nrows, 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 d151b47..2e3e189 100644 --- a/src/H5HFstat.c +++ b/src/H5HFstat.c @@ -128,7 +128,6 @@ 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) @@ -148,7 +147,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, NULL, 0, heap_size) < 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) 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 */ @@ -173,11 +172,9 @@ 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, &meta_size) < 0) + if(H5F_addr_defined(hdr->fs_addr)) + if(H5HF_space_size(hdr, dxpl_id, heap_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 4e355bb..5a8eb33 100644 --- a/src/H5Lexternal.c +++ b/src/H5Lexternal.c @@ -76,81 +76,6 @@ 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 * @@ -167,10 +92,6 @@ done: * * 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 * *------------------------------------------------------------------------- */ @@ -193,11 +114,6 @@ 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 */ @@ -219,6 +135,28 @@ 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") @@ -245,92 +183,10 @@ 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 */ - /* - * 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); + /* 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") /* Increment the number of open objects, to hold the file open */ H5F_incr_nopen_objs(ext_file); @@ -363,6 +219,10 @@ 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 ba343bc..ac07edf 100644 --- a/src/H5Odtype.c +++ b/src/H5Odtype.c @@ -232,11 +232,10 @@ 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_limit_enc_size((uint64_t)dt->shared->size); + offset_nbytes = (H5V_log2_gen((uint64_t)dt->shared->size) + 7) / 8; /* * Compound datatypes... @@ -337,18 +336,6 @@ 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 */ @@ -747,7 +734,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_limit_enc_size((uint64_t)dt->shared->size); + offset_nbytes = (H5V_log2_gen((uint64_t)dt->shared->size) + 7) / 8; /* * Compound datatypes... @@ -1110,7 +1097,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_limit_enc_size((uint64_t)dt->shared->size); + offset_nbytes = (H5V_log2_gen((uint64_t)dt->shared->size) + 7) / 8; /* 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 8bc263a..6affcad 100644 --- a/src/H5Pdxpl.c +++ b/src/H5Pdxpl.c @@ -90,6 +90,9 @@ /* 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 @@ -196,6 +199,7 @@ 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; @@ -261,6 +265,8 @@ 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) @@ -45,6 +45,18 @@ 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; @@ -75,9 +87,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) @@ -93,8 +105,8 @@ H5S_init_interface(void) #endif /* H5_HAVE_PARALLEL */ done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5S_init_interface() */ + FUNC_LEAVE_NOAPI(ret_value); +} /*-------------------------------------------------------------------------- @@ -117,26 +129,156 @@ done: int H5S_term_interface(void) { - int n = 0; - - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_term_interface) - - if(H5_interface_initialize_g) { - if((n = H5I_nmembers(H5I_DATASPACE))) { + 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); - } /* end if */ - else { + } 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 */ + /* 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) -} /* end H5S_term_interface() */ + FUNC_LEAVE_NOAPI(n); +} /*-------------------------------------------------------------------------- @@ -1242,6 +1384,105 @@ 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 725b8fc..cc89b49 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 = FALSE; + *is_derived_type = 0; 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 = FALSE; + *is_derived_type = 0; 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 = TRUE; + *is_derived_type = 1; HGOTO_DONE(SUCCEED); empty: @@ -464,7 +464,7 @@ empty: *new_type = MPI_BYTE; *count = 0; *extra_offset = 0; - *is_derived_type = FALSE; + *is_derived_type = 0; 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=%t\n", + HDfprintf(H5DEBUG(S), "Leave %s, count=%ld is_derived_type=%d\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 = TRUE; + *is_derived_type = 1; HGOTO_DONE(SUCCEED); @@ -565,7 +565,7 @@ empty: *new_type = MPI_BYTE; *count = 0; *extra_offset = 0; - *is_derived_type = FALSE; + *is_derived_type = 0; done: FUNC_LEAVE_NOAPI(ret_value); diff --git a/src/H5Sprivate.h b/src/H5Sprivate.h index 8744872..bd27f09 100644 --- a/src/H5Sprivate.h +++ b/src/H5Sprivate.h @@ -115,6 +115,31 @@ 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) @@ -173,6 +198,9 @@ typedef struct H5S_sel_iter_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); @@ -4552,7 +4552,7 @@ H5T_path_compound_subset(const H5T_path_t *p) FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5T_path_compound_subset); - HDassert(p); + assert(p); if(p->are_compounds) ret_value = H5T_conv_struct_subset(&(p->cdata)); diff --git a/src/H5Tconv.c b/src/H5Tconv.c index 7803d07..0da4d53 100644 --- a/src/H5Tconv.c +++ b/src/H5Tconv.c @@ -1890,15 +1890,17 @@ 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); + priv = (H5T_conv_struct_t*)(cdata->priv); + ret_value = priv->smembs_subset; - FUNC_LEAVE_NOAPI(priv->smembs_subset) + FUNC_LEAVE_NOAPI(ret_value) } /* end H5T_conv_struct_subset() */ diff --git a/src/H5Tprivate.h b/src/H5Tprivate.h index 2fe4c3a..dfe2367 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. + * there is no conversion needed. It's for the Chicago company. */ typedef enum { H5T_SUBSET_BADVALUE = -1, /* Invalid value */ diff --git a/src/H5Vprivate.h b/src/H5Vprivate.h index b92266c..94b3699 100644 --- a/src/H5Vprivate.h +++ b/src/H5Vprivate.h @@ -410,25 +410,5 @@ 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 77a3b23..5c767ef 100644 --- a/src/H5config.h.in +++ b/src/H5config.h.in @@ -368,9 +368,6 @@ /* 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 b60c50a..11f3037 100644 --- a/src/H5private.h +++ b/src/H5private.h @@ -638,15 +638,7 @@ 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() @@ -919,42 +911,6 @@ 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 5606171..06060dd 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 9 /* For minor interface/format changes */ -#define H5_VERS_RELEASE 5 /* For tweaks, bug-fixes, or development */ +#define H5_VERS_MINOR 8 /* For minor interface/format changes */ +#define H5_VERS_RELEASE 0 /* For tweaks, bug-fixes, or development */ #define H5_VERS_SUBRELEASE "" /* For pre-releases like snap0 */ /* Empty string for real releases. */ -#define H5_VERS_INFO "HDF5 library version: 1.9.5" /* Full version string */ +#define H5_VERS_INFO "HDF5 library version: 1.8.0" /* 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 4a49d71..5eae11d 100644 --- a/src/H5system.c +++ b/src/H5system.c @@ -35,8 +35,6 @@ #include "H5private.h" /* Generic Functions */ #include "H5Fprivate.h" /* File access */ #include "H5MMprivate.h" /* Memory management */ -#include "H5Eprivate.h" - /****************/ @@ -580,100 +578,4 @@ 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 fcb47e2..0e5030b 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 H5Dchunk.c H5Dcompact.c H5Dcontig.c H5Ddbg.c \ + H5D.c H5Dcompact.c H5Dcontig.c H5Ddbg.c \ H5Ddeprec.c H5Defl.c H5Dfill.c H5Dint.c \ H5Dio.c \ - H5Distore.c H5Dmpio.c H5Doh.c H5Dscatgath.c H5Dselect.c H5Dtest.c \ + H5Distore.c H5Dmpio.c H5Doh.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 8e8f339..085bf96 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -82,20 +82,19 @@ 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 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 \ + 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 \ 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 \ @@ -384,7 +383,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 = 6 +LT_VERS_REVISION = 0 LT_VERS_AGE = 0 H5detect_CFLAGS = -g @@ -405,10 +404,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 H5Dchunk.c H5Dcompact.c H5Dcontig.c H5Ddbg.c \ + H5D.c H5Dcompact.c H5Dcontig.c H5Ddbg.c \ H5Ddeprec.c H5Defl.c H5Dfill.c H5Dint.c \ H5Dio.c \ - H5Distore.c H5Dmpio.c H5Doh.c H5Dscatgath.c H5Dselect.c H5Dtest.c \ + H5Distore.c H5Dmpio.c H5Doh.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 \ @@ -603,7 +602,6 @@ 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@ @@ -615,7 +613,6 @@ 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@ |