diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2003-05-17 21:50:55 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2003-05-17 21:50:55 (GMT) |
commit | ad3ace3d16435c18667c48f2f6df2143aa7bc189 (patch) | |
tree | c52eaf9aece7f2c3460dc03a0d9c2571edf3cf9c | |
parent | dddf167923a28c9cf65b05da565e1b7197b0cd37 (diff) | |
download | hdf5-ad3ace3d16435c18667c48f2f6df2143aa7bc189.zip hdf5-ad3ace3d16435c18667c48f2f6df2143aa7bc189.tar.gz hdf5-ad3ace3d16435c18667c48f2f6df2143aa7bc189.tar.bz2 |
[svn-r6891] Purpose:
Bug fix
Description:
Raw data I/O on chunked datasets would attempt to allocate data structures
proportional to the number of chunks in the dataset on disk, instead of just
the number of chunks that the I/O operation would interact with, causing
operations on datasets with large #'s of chunks to fail (or become very slow),
even though the actual I/O operation was very modest.
Solution:
This is the "scalability fix" for chunked datasets that I've mentioned
we need to do, althought it's not the complete fix for the issue. Read on
for the details...
Only create data structures for the chunks that the I/O operation will
actually act on, reducing the amount of information allocated in memory,
normally.
I say "normally", because this algorithm has the same problems as the
original algorithm (worse actually, since the data structure for each chunk
is larger now) if _all_ the chunks in a dataset with a lot of chunks are
actually involved in the I/O operation. If that is the case, this code
will fail in a similar way.
To truly fix the problem, we would need to only create data structures for
a particular number of chunks, perform the I/O on just those chunks, then
release the data structures for those chunks and create data structures for
the next set of chunks to access, etc. However, I think this case is pretty
rare right now and we should worry about it after the 1.6.0 release.
Platforms tested:
h5committested
-rw-r--r-- | src/H5Dio.c | 938 |
1 files changed, 639 insertions, 299 deletions
diff --git a/src/H5Dio.c b/src/H5Dio.c index 6d66ae3..06d5a15 100644 --- a/src/H5Dio.c +++ b/src/H5Dio.c @@ -21,6 +21,7 @@ #include "H5Iprivate.h" /* IDs */ #include "H5MMprivate.h" /* Memory management */ #include "H5Sprivate.h" /* Dataspace functions */ +#include "H5TBprivate.h" /* Threaded, balanced, binary trees (TBBTs) */ #include "H5Vprivate.h" /* Vector and array functions */ /*#define H5D_DEBUG*/ @@ -44,18 +45,36 @@ /* Local typedefs */ -/*information for mapping between file space and memory space*/ +/* Information for mapping between file space and memory space */ + +/* Structure holding information about a file chunk's selection for mapping */ +typedef struct H5D_fchunk_info_t { + hsize_t index; /* "Index" of chunk in dataset (must be first for TBBT routines) */ + H5S_t *space; /* Dataspace describing chunk & selection in it */ + hssize_t coords[H5O_LAYOUT_NDIMS]; /* Coordinates of chunk in file dataset's dataspace */ +} H5D_fchunk_info_t; + +/* Structure holding information about a memory chunk's selection for mapping */ +typedef struct H5D_mchunk_info_t { + hsize_t index; /* "Index" of chunk in dataset (must be first for TBBT routines) */ + H5S_t *space; /* Dataspace describing chunk & selection in it */ +} H5D_mchunk_info_t; + +/* Main structure holding the mapping between file chunks and memory */ typedef struct fm_map { - H5S_t **fspace; /*file spaces for all chunks*/ - H5S_t **mspace; /*memory spaces for all chunks*/ - hsize_t elmt_count; /*indicate which element is being processed*/ - hsize_t nchunks; /*total number of chunks*/ + H5TB_TREE *fsel; /* TBBT containing file dataspaces for all chunks */ + H5TB_TREE *msel; /* TBBT containing memory dataspaces for all chunks */ + hsize_t last_index; /* Index of last chunk operated on */ + H5S_t *last_fchunk; /* Pointer to last file chunk's dataspace */ + H5S_t *last_mchunk; /* Pointer to last memory chunk's dataspace */ + H5S_t *fchunk_tmpl; /* Dataspace template for new file chunks */ + H5S_t *mchunk_tmpl; /* Dataspace template for new memory chunks */ + unsigned f_ndims; /* Number of dimensions for file dataspace */ H5S_sel_iter_t mem_iter; /* Iterator for elements in memory selection */ unsigned m_ndims; /* Number of dimensions for memory dataspace */ hsize_t chunks[H5O_LAYOUT_NDIMS]; /* Number of chunks in each dimension */ hsize_t down_chunks[H5O_LAYOUT_NDIMS]; /* "down" size of number of chunks in each dimension */ - hssize_t *chunk_coords; /*coordinates for all chunks*/ - H5O_layout_t *layout; /*dataset layout information*/ + H5O_layout_t *layout; /* Dataset layout information*/ } fm_map; /* Interface initialization */ @@ -94,11 +113,13 @@ static herr_t H5D_io_assist_mpio(H5P_genplist_t *dx_plist, hbool_t doing_mpio, H5FD_mpio_xfer_t xfer_mode, hbool_t *xfer_mode_changed); #endif /*H5_HAVE_PARALLEL*/ -static herr_t -H5D_chunk_mem_file_map(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *file_space, - const H5S_t *mem_space, fm_map *fm); +static herr_t H5D_create_chunk_map(H5D_t *dataset, const H5T_t *mem_type, + const H5S_t *file_space, const H5S_t *mem_space, fm_map *fm); +static herr_t H5D_destroy_chunk_map(fm_map *fm); +static void H5D_free_fchunk_info(void *fchunk_info); +static void H5D_free_mchunk_info(void *mchunk_info); static herr_t H5D_chunk_coords_assist(hssize_t *coords, size_t ndims, - hsize_t chunks[], hsize_t chunk_ptr); + hsize_t chunks[], hsize_t chunk_idx); static herr_t H5D_chunk_cb(void *elem, hid_t type_id, hsize_t ndims, hssize_t *coords, void *fm); static herr_t H5D_fill(const void *fill, const H5T_t *fill_type, void *buf, @@ -111,6 +132,12 @@ H5FL_BLK_DEFINE(type_elem); /* Declare a free list to manage blocks of type conversion data */ H5FL_BLK_DEFINE(type_conv); +/* Declare a free list to manage the H5D_fchunk_info_t struct */ +H5FL_DEFINE_STATIC(H5D_fchunk_info_t); + +/* Declare a free list to manage the H5D_mchunk_info_t struct */ +H5FL_DEFINE_STATIC(H5D_mchunk_info_t); + /*-------------------------------------------------------------------------- NAME @@ -1419,6 +1446,8 @@ H5D_chunk_read(hsize_t nelmts, H5D_t *dataset, const H5T_t *mem_type, const H5S_ xfer_mode, hid_t src_id, hid_t dst_id, void *buf/*out*/) { fm_map fm; /* File<->memory mapping */ + H5TB_NODE *fchunk_node; /* Current node in file chunk TBBT */ + H5TB_NODE *mchunk_node; /* Current node in memory chunk TBBT */ herr_t status; /*function return status*/ #ifdef H5S_DEBUG H5_timer_t timer; @@ -1439,7 +1468,6 @@ H5D_chunk_read(hsize_t nelmts, H5D_t *dataset, const H5T_t *mem_type, const H5S_ uint8_t *tconv_buf = NULL; /*data type conv buffer */ uint8_t *bkg_buf = NULL; /*background buffer */ H5D_storage_t store; /*union of EFL and chunk pointer in file space */ - hsize_t h; /* Local index variable */ #ifdef H5_HAVE_PARALLEL hbool_t xfer_mode_changed; /* Whether the transfer mode was changed */ #endif /*H5_HAVE_PARALLEL*/ @@ -1447,12 +1475,9 @@ H5D_chunk_read(hsize_t nelmts, H5D_t *dataset, const H5T_t *mem_type, const H5S_ FUNC_ENTER_NOINIT(H5D_chunk_read); - /* Initialize fm_map*/ - HDmemset(&fm, 0, sizeof(fm_map)); - fm.layout = &(dataset->layout); - /* Map elements between file and memory for each chunk*/ - H5D_chunk_mem_file_map(dataset, mem_type, file_space, mem_space, &fm); + if(H5D_create_chunk_map(dataset, mem_type, file_space, mem_space, &fm)<0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't build chunk mapping"); /* * If there is no type conversion then read directly into the @@ -1466,22 +1491,47 @@ H5D_chunk_read(hsize_t nelmts, H5D_t *dataset, const H5T_t *mem_type, const H5S_ assert(dataset->layout.addr!=HADDR_UNDEF || dataset->efl.nused>0 || dataset->layout.type==H5D_COMPACT); - /*loop through each chunk, read data*/ - for(h=0; h<fm.nchunks; h++) { - if(H5S_get_select_npoints(fm.fspace[h]) > 0) { - /*pass in chunk's coordinates in a union. LAYOUT puts datatype size as an extra dimension, - * have to take it out.*/ - store.chunk_coords = fm.chunk_coords + h*dataset->layout.ndims; + /* Get first node in chunk trees */ + fchunk_node=H5TB_first(fm.fsel->root); + mchunk_node=H5TB_first(fm.msel->root); - status = (sconv->read)(dataset->ent.file, &(dataset->layout), - dc_plist, &store, H5T_get_size(dataset->type), - fm.fspace[h], fm.mspace[h], dxpl_id, buf/*out*/); + /* Sanity check that we either have both file & memory chunk information + * or _don't_ have both file & memory chunk information + * (i.e. don't run out of one kind of chunk before the other) + */ + assert((fchunk_node && mchunk_node) || (!fchunk_node && !mchunk_node)); - /* Check return value from optimized read */ - if (status<0) - HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "optimized read failed"); - } /* end if */ - } /* end for */ + /* Iterate through chunks to be operated on */ + while(fchunk_node) { + H5D_fchunk_info_t *fchunk_info; /* File chunk information */ + H5D_mchunk_info_t *mchunk_info; /* Memory chunk information */ + + /* Get the actual chunk information from the tree nodes */ + fchunk_info=fchunk_node->data; + mchunk_info=mchunk_node->data; + + /* Pass in chunk's coordinates in a union. */ + store.chunk_coords = fchunk_info->coords; + + /* Perform the actual read operation */ + status = (sconv->read)(dataset->ent.file, &(dataset->layout), + dc_plist, &store, H5T_get_size(dataset->type), + fchunk_info->space, mchunk_info->space, dxpl_id, buf); + + /* Check return value from optimized read */ + if (status<0) + HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "optimized read failed"); + + /* Get the next chunk nodes in the trees */ + fchunk_node=H5TB_next(fchunk_node); + mchunk_node=H5TB_next(mchunk_node); + + /* Sanity check that we either have both file & memory chunk information + * or _don't_ have both file & memory chunk information + * (i.e. don't run out of one kind of chunk before the other) + */ + assert((fchunk_node && mchunk_node) || (!fchunk_node && !mchunk_node)); + } /* end while */ #ifdef H5S_DEBUG H5_timer_end(&(sconv->stats[1].read_timer), &timer); @@ -1546,109 +1596,136 @@ H5D_chunk_read(hsize_t nelmts, H5D_t *dataset, const H5T_t *mem_type, const H5S_ } /* end if */ /* Loop over all the chunks, performing I/O on each */ - for(h=0; h<fm.nchunks; h++) { + + /* Get first node in chunk trees */ + fchunk_node=H5TB_first(fm.fsel->root); + mchunk_node=H5TB_first(fm.msel->root); + + /* Sanity check that we either have both file & memory chunk information + * or _don't_ have both file & memory chunk information + * (i.e. don't run out of one kind of chunk before the other) + */ + assert((fchunk_node && mchunk_node) || (!fchunk_node && !mchunk_node)); + + /* Iterate through chunks to be operated on */ + while(fchunk_node) { hsize_t chunk_nelmts; /* Number of elements selected in current chunk */ + H5D_fchunk_info_t *fchunk_info; /* File chunk information */ + H5D_mchunk_info_t *mchunk_info; /* Memory chunk information */ + + /* Get the actual chunk information from the tree nodes */ + fchunk_info=fchunk_node->data; + mchunk_info=mchunk_node->data; /* Get the number of elements selected in this chunk */ - chunk_nelmts=H5S_get_select_npoints(fm.fspace[h]); + chunk_nelmts=H5S_get_select_npoints(fchunk_info->space); assert(chunk_nelmts<=nelmts); - if(chunk_nelmts > 0) { - /* initialize selection iterator */ - if (H5S_select_iter_init(&file_iter, fm.fspace[h], 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, fm.mspace[h], 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, fm.mspace[h], 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_coords = fm.chunk_coords + h*dataset->layout.ndims; - - for (smine_start=0; smine_start<chunk_nelmts; smine_start+=smine_nelmts) { - /* Go figure out how many elements to read from the file */ - assert(H5S_select_iter_nelmts(&file_iter)==(chunk_nelmts-smine_start)); - smine_nelmts = MIN(request_nelmts, (chunk_nelmts-smine_start)); - - /* - * Gather the data from disk into the data type conversion - * buffer. Also gather data from application to background buffer - * if necessary. - */ + + /* initialize selection iterator */ + if (H5S_select_iter_init(&file_iter, fchunk_info->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, mchunk_info->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, mchunk_info->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 */ + + /* Pass in chunk's coordinates in a union*/ + store.chunk_coords = fchunk_info->coords; + + for (smine_start=0; smine_start<chunk_nelmts; smine_start+=smine_nelmts) { + /* Go figure out how many elements to read from the file */ + assert(H5S_select_iter_nelmts(&file_iter)==(chunk_nelmts-smine_start)); + smine_nelmts = MIN(request_nelmts, (chunk_nelmts-smine_start)); + + /* + * Gather the data from disk into the data type conversion + * buffer. Also gather data from application to background buffer + * if necessary. + */ #ifdef H5S_DEBUG - H5_timer_begin(&timer); + H5_timer_begin(&timer); #endif - /* Sanity check that space is allocated, then read data from it */ - assert(dataset->layout.addr!=HADDR_UNDEF || dataset->efl.nused>0 || - dataset->layout.type==H5D_COMPACT); - n = H5S_select_fgath(dataset->ent.file, &(dataset->layout), - dc_plist, &store, src_type_size, fm.fspace[h], - &file_iter, smine_nelmts, dxpl_id, tconv_buf/*out*/); + /* Sanity check that space is allocated, then read data from it */ + assert(dataset->layout.addr!=HADDR_UNDEF || dataset->efl.nused>0 || + dataset->layout.type==H5D_COMPACT); + n = H5S_select_fgath(dataset->ent.file, &(dataset->layout), + dc_plist, &store, src_type_size, fchunk_info->space, + &file_iter, smine_nelmts, dxpl_id, tconv_buf/*out*/); #ifdef H5S_DEBUG - H5_timer_end(&(sconv->stats[1].gath_timer), &timer); - sconv->stats[1].gath_nbytes += n * src_type_size; - sconv->stats[1].gath_ncalls++; + H5_timer_end(&(sconv->stats[1].gath_timer), &timer); + sconv->stats[1].gath_nbytes += n * src_type_size; + sconv->stats[1].gath_ncalls++; #endif - if (n!=smine_nelmts) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "file gather failed"); + if (n!=smine_nelmts) + HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "file gather failed"); - if (need_bkg) { + if (need_bkg) { #ifdef H5S_DEBUG - H5_timer_begin(&timer); + H5_timer_begin(&timer); #endif - n = H5S_select_mgath(buf, dst_type_size, fm.mspace[h], &bkg_iter, - smine_nelmts, dxpl_id, bkg_buf/*out*/); + n = H5S_select_mgath(buf, dst_type_size, mchunk_info->space, &bkg_iter, + smine_nelmts, dxpl_id, bkg_buf/*out*/); #ifdef H5S_DEBUG - H5_timer_end(&(sconv->stats[1].bkg_timer), &timer); - sconv->stats[1].bkg_nbytes += n * dst_type_size; - sconv->stats[1].bkg_ncalls++; + H5_timer_end(&(sconv->stats[1].bkg_timer), &timer); + sconv->stats[1].bkg_nbytes += n * dst_type_size; + sconv->stats[1].bkg_ncalls++; #endif - if (n!=smine_nelmts) - HGOTO_ERROR (H5E_IO, H5E_READERROR, FAIL, "mem gather failed"); - } /* end if */ - - /* - * Perform data type conversion. - */ - if (H5T_convert(tpath, src_id, dst_id, smine_nelmts, 0, 0, - tconv_buf, bkg_buf, dxpl_id)<0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "data type conversion failed"); - - /* - * Scatter the data into memory. - */ + if (n!=smine_nelmts) + HGOTO_ERROR (H5E_IO, H5E_READERROR, FAIL, "mem gather failed"); + } /* end if */ + + /* + * Perform data type conversion. + */ + if (H5T_convert(tpath, src_id, dst_id, smine_nelmts, 0, 0, + tconv_buf, bkg_buf, dxpl_id)<0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "data type conversion failed"); + + /* + * Scatter the data into memory. + */ #ifdef H5S_DEBUG - H5_timer_begin(&timer); + H5_timer_begin(&timer); #endif - status = H5S_select_mscat(tconv_buf, dst_type_size, fm.mspace[h], - &mem_iter, smine_nelmts, dxpl_id, buf/*out*/); + status = H5S_select_mscat(tconv_buf, dst_type_size, mchunk_info->space, + &mem_iter, smine_nelmts, dxpl_id, buf/*out*/); #ifdef H5S_DEBUG - H5_timer_end(&(sconv->stats[1].scat_timer), &timer); - sconv->stats[1].scat_nbytes += smine_nelmts * dst_type_size; - sconv->stats[1].scat_ncalls++; + H5_timer_end(&(sconv->stats[1].scat_timer), &timer); + sconv->stats[1].scat_nbytes += smine_nelmts * dst_type_size; + sconv->stats[1].scat_ncalls++; #endif - if (status<0) - HGOTO_ERROR (H5E_DATASET, H5E_READERROR, FAIL, "scatter failed"); - } /* end for */ - - /* Release selection iterators */ - if(file_iter_init) { - H5S_select_iter_release(&file_iter); - file_iter_init=0; - } /* end if */ - if(mem_iter_init) { - H5S_select_iter_release(&mem_iter); - mem_iter_init=0; - } /* end if */ - if(bkg_iter_init) { - H5S_select_iter_release(&bkg_iter); - bkg_iter_init=0; - } /* end if */ + if (status<0) + HGOTO_ERROR (H5E_DATASET, H5E_READERROR, FAIL, "scatter failed"); + } /* end for */ + + /* Release selection iterators */ + if(file_iter_init) { + H5S_select_iter_release(&file_iter); + file_iter_init=0; } /* end if */ - } /* end for */ + if(mem_iter_init) { + H5S_select_iter_release(&mem_iter); + mem_iter_init=0; + } /* end if */ + if(bkg_iter_init) { + H5S_select_iter_release(&bkg_iter); + bkg_iter_init=0; + } /* end if */ + + /* Get the next chunk nodes in the trees */ + fchunk_node=H5TB_next(fchunk_node); + mchunk_node=H5TB_next(mchunk_node); + + /* Sanity check that we either have both file & memory chunk information + * or _don't_ have both file & memory chunk information + * (i.e. don't run out of one kind of chunk before the other) + */ + assert((fchunk_node && mchunk_node) || (!fchunk_node && !mchunk_node)); + } /* end while */ done: #ifdef H5_HAVE_PARALLEL @@ -1660,7 +1737,7 @@ done: #endif xfer_mode = H5FD_MPIO_COLLECTIVE; if(H5P_set (dx_plist, H5D_XFER_IO_XFER_MODE_NAME, &xfer_mode) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set transfer mode"); + HDONE_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set transfer mode"); } /* end if */ #endif /*H5_HAVE_PARALLEL*/ @@ -1678,19 +1755,9 @@ done: if(bkg_iter_init) H5S_select_iter_release(&bkg_iter); - /* Close file space and memory space for each chunk*/ - for(h=0; h<fm.nchunks; h++) { - if(fm.mspace[h]) - H5S_close(fm.mspace[h]); - if(fm.fspace[h]) - H5S_close(fm.fspace[h]); - } - if(fm.chunk_coords) - H5MM_free(fm.chunk_coords); - if(fm.fspace) - H5MM_free(fm.fspace); - if(fm.mspace) - H5MM_free(fm.mspace); + /* 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() */ @@ -1726,6 +1793,8 @@ H5D_chunk_write(hsize_t nelmts, H5D_t *dataset, const H5T_t *mem_type, const H5S xfer_mode, hid_t src_id, hid_t dst_id, const void *buf) { fm_map fm; /* File<->memory mapping */ + H5TB_NODE *fchunk_node; /* Current node in file chunk TBBT */ + H5TB_NODE *mchunk_node; /* Current node in memory chunk TBBT */ herr_t status; /*function return status*/ #ifdef H5S_DEBUG H5_timer_t timer; @@ -1746,7 +1815,6 @@ H5D_chunk_write(hsize_t nelmts, H5D_t *dataset, const H5T_t *mem_type, const H5S uint8_t *tconv_buf = NULL; /*data type conv buffer */ uint8_t *bkg_buf = NULL; /*background buffer */ H5D_storage_t store; /*union of EFL and chunk pointer in file space */ - hsize_t h; /* Local index variable */ #ifdef H5_HAVE_PARALLEL hbool_t xfer_mode_changed; /* Whether the transfer mode was changed */ #endif /*H5_HAVE_PARALLEL*/ @@ -1754,12 +1822,9 @@ H5D_chunk_write(hsize_t nelmts, H5D_t *dataset, const H5T_t *mem_type, const H5S FUNC_ENTER_NOINIT(H5D_chunk_write); - /* Initialize fm_map*/ - HDmemset(&fm, 0, sizeof(fm_map)); - fm.layout = &(dataset->layout); - /* Map elements between file and memory for each chunk*/ - H5D_chunk_mem_file_map(dataset, mem_type, file_space, mem_space, &fm); + if(H5D_create_chunk_map(dataset, mem_type, file_space, mem_space, &fm)<0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't build chunk mapping"); /* * If there is no type conversion then write directly from the @@ -1769,22 +1834,47 @@ H5D_chunk_write(hsize_t nelmts, H5D_t *dataset, const H5T_t *mem_type, const H5S #ifdef H5S_DEBUG H5_timer_begin(&timer); #endif - /*loop through each chunk, write data*/ - for(h=0; h<fm.nchunks; h++) { - if(H5S_get_select_npoints(fm.fspace[h]) > 0) { - /*pass in chunk's coordinates in a union. LAYOUT puts datatype size as an extra dimension, - * have to take it out.*/ - store.chunk_coords = fm.chunk_coords + h*dataset->layout.ndims; - - status = (sconv->write)(dataset->ent.file, &(dataset->layout), - dc_plist, &store, H5T_get_size(dataset->type), - fm.fspace[h], fm.mspace[h], dxpl_id, buf); - - /* Check return value from optimized write */ - if (status<0) - HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "optimized write failed"); - } - } + /* Get first node in chunk trees */ + fchunk_node=H5TB_first(fm.fsel->root); + mchunk_node=H5TB_first(fm.msel->root); + + /* Sanity check that we either have both file & memory chunk information + * or _don't_ have both file & memory chunk information + * (i.e. don't run out of one kind of chunk before the other) + */ + assert((fchunk_node && mchunk_node) || (!fchunk_node && !mchunk_node)); + + /* Iterate through chunks to be operated on */ + while(fchunk_node) { + H5D_fchunk_info_t *fchunk_info; /* File chunk information */ + H5D_mchunk_info_t *mchunk_info; /* Memory chunk information */ + + /* Get the actual chunk information from the tree nodes */ + fchunk_info=fchunk_node->data; + mchunk_info=mchunk_node->data; + + /* Pass in chunk's coordinates in a union. */ + store.chunk_coords = fchunk_info->coords; + + /* Perform the actual write operation */ + status = (sconv->write)(dataset->ent.file, &(dataset->layout), + dc_plist, &store, H5T_get_size(dataset->type), + fchunk_info->space, mchunk_info->space, dxpl_id, buf); + + /* Check return value from optimized write */ + if (status<0) + HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "optimized write failed"); + + /* Get the next chunk nodes in the trees */ + fchunk_node=H5TB_next(fchunk_node); + mchunk_node=H5TB_next(mchunk_node); + + /* Sanity check that we either have both file & memory chunk information + * or _don't_ have both file & memory chunk information + * (i.e. don't run out of one kind of chunk before the other) + */ + assert((fchunk_node && mchunk_node) || (!fchunk_node && !mchunk_node)); + } /* end while */ #ifdef H5S_DEBUG H5_timer_end(&(sconv->stats[0].write_timer), &timer); @@ -1853,110 +1943,136 @@ H5D_chunk_write(hsize_t nelmts, H5D_t *dataset, const H5T_t *mem_type, const H5S } /* end if */ /* Loop over all the chunks, performing I/O on each */ - for(h=0; h<fm.nchunks; h++) { + + /* Get first node in chunk trees */ + fchunk_node=H5TB_first(fm.fsel->root); + mchunk_node=H5TB_first(fm.msel->root); + + /* Sanity check that we either have both file & memory chunk information + * or _don't_ have both file & memory chunk information + * (i.e. don't run out of one kind of chunk before the other) + */ + assert((fchunk_node && mchunk_node) || (!fchunk_node && !mchunk_node)); + + /* Iterate through chunks to be operated on */ + while(fchunk_node) { hsize_t chunk_nelmts; /* Number of elements selected in current chunk */ + H5D_fchunk_info_t *fchunk_info; /* File chunk information */ + H5D_mchunk_info_t *mchunk_info; /* Memory chunk information */ + + /* Get the actual chunk information from the tree nodes */ + fchunk_info=fchunk_node->data; + mchunk_info=mchunk_node->data; /* Get the number of elements selected in this chunk */ - chunk_nelmts=H5S_get_select_npoints(fm.fspace[h]); + chunk_nelmts=H5S_get_select_npoints(fchunk_info->space); assert(chunk_nelmts<=nelmts); - if(chunk_nelmts > 0) { - - /* initialize selection iterator */ - if (H5S_select_iter_init(&file_iter, fm.fspace[h], 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, fm.mspace[h], 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, fm.fspace[h], 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 */ + + /* initialize selection iterator */ + if (H5S_select_iter_init(&file_iter, fchunk_info->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, mchunk_info->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, fchunk_info->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 */ + + /*pass in chunk's coordinates in a union*/ + store.chunk_coords = fchunk_info->coords; + + for (smine_start=0; smine_start<chunk_nelmts; smine_start+=smine_nelmts) { + /* Go figure out how many elements to read from the file */ + assert(H5S_select_iter_nelmts(&file_iter)==(chunk_nelmts-smine_start)); + smine_nelmts = MIN(request_nelmts, (chunk_nelmts-smine_start)); - /*pass in chunk's coordinates in a union*/ - store.chunk_coords = fm.chunk_coords + h*dataset->layout.ndims; - - for (smine_start=0; smine_start<chunk_nelmts; smine_start+=smine_nelmts) { - /* Go figure out how many elements to read from the file */ - assert(H5S_select_iter_nelmts(&file_iter)==(chunk_nelmts-smine_start)); - smine_nelmts = MIN(request_nelmts, (chunk_nelmts-smine_start)); - - /* - * Gather the data from disk into the data type conversion - * buffer. Also gather data from application to background buffer - * if necessary. - */ + /* + * Gather the data from disk into the data type conversion + * buffer. Also gather data from application to background buffer + * if necessary. + */ #ifdef H5S_DEBUG - H5_timer_begin(&timer); + H5_timer_begin(&timer); #endif - n = H5S_select_mgath(buf, src_type_size, fm.mspace[h], &mem_iter, - smine_nelmts, dxpl_id, tconv_buf/*out*/); - + n = H5S_select_mgath(buf, src_type_size, mchunk_info->space, &mem_iter, + smine_nelmts, dxpl_id, tconv_buf/*out*/); + #ifdef H5S_DEBUG - H5_timer_end(&(sconv->stats[1].gath_timer), &timer); - sconv->stats[1].gath_nbytes += n * src_type_size; - sconv->stats[1].gath_ncalls++; + H5_timer_end(&(sconv->stats[1].gath_timer), &timer); + sconv->stats[1].gath_nbytes += n * src_type_size; + sconv->stats[1].gath_ncalls++; #endif - if (n!=smine_nelmts) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "file gather failed"); + if (n!=smine_nelmts) + HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "file gather failed"); - if (need_bkg) { + if (need_bkg) { #ifdef H5S_DEBUG - H5_timer_begin(&timer); + H5_timer_begin(&timer); #endif - n = H5S_select_fgath(dataset->ent.file, &(dataset->layout), - dc_plist, &store, dst_type_size, fm.fspace[h], - &bkg_iter, smine_nelmts, dxpl_id, bkg_buf/*out*/); + n = H5S_select_fgath(dataset->ent.file, &(dataset->layout), + dc_plist, &store, dst_type_size, fchunk_info->space, + &bkg_iter, smine_nelmts, dxpl_id, bkg_buf/*out*/); #ifdef H5S_DEBUG - H5_timer_end(&(sconv->stats[0].bkg_timer), &timer); - sconv->stats[0].bkg_nbytes += n * dst_type_size; - sconv->stats[0].bkg_ncalls++; + H5_timer_end(&(sconv->stats[0].bkg_timer), &timer); + sconv->stats[0].bkg_nbytes += n * dst_type_size; + sconv->stats[0].bkg_ncalls++; #endif - if (n!=smine_nelmts) - HGOTO_ERROR (H5E_IO, H5E_WRITEERROR, FAIL, "file gather failed"); - } /* end if */ - - /* - * Perform data type conversion. - */ - if (H5T_convert(tpath, src_id, dst_id, smine_nelmts, 0, 0, - tconv_buf, bkg_buf, dxpl_id)<0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "data type conversion failed"); - - /* - * Scatter the data out to the file. - */ + if (n!=smine_nelmts) + HGOTO_ERROR (H5E_IO, H5E_WRITEERROR, FAIL, "file gather failed"); + } /* end if */ + + /* + * Perform data type conversion. + */ + if (H5T_convert(tpath, src_id, dst_id, smine_nelmts, 0, 0, + tconv_buf, bkg_buf, dxpl_id)<0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "data type conversion failed"); + + /* + * Scatter the data out to the file. + */ #ifdef H5S_DEBUG - H5_timer_begin(&timer); + H5_timer_begin(&timer); #endif - status = H5S_select_fscat(dataset->ent.file, &(dataset->layout), - dc_plist, &store, dst_type_size, fm.fspace[h], - &file_iter, smine_nelmts, dxpl_id, tconv_buf); + status = H5S_select_fscat(dataset->ent.file, &(dataset->layout), + dc_plist, &store, dst_type_size, fchunk_info->space, + &file_iter, smine_nelmts, dxpl_id, tconv_buf); #ifdef H5S_DEBUG - H5_timer_end(&(sconv->stats[0].scat_timer), &timer); - sconv->stats[0].scat_nbytes += n * dst_type_size; - sconv->stats[0].scat_ncalls++; + H5_timer_end(&(sconv->stats[0].scat_timer), &timer); + sconv->stats[0].scat_nbytes += n * dst_type_size; + sconv->stats[0].scat_ncalls++; #endif - if (status<0) - HGOTO_ERROR (H5E_IO, H5E_WRITEERROR, FAIL, "scatter failed"); - } /* end for */ - - /* Release selection iterators */ - if(file_iter_init) { - H5S_select_iter_release(&file_iter); - file_iter_init=0; - } /* end if */ - if(mem_iter_init) { - H5S_select_iter_release(&mem_iter); - mem_iter_init=0; - } /* end if */ - if(bkg_iter_init) { - H5S_select_iter_release(&bkg_iter); - bkg_iter_init=0; - } /* end if */ + if (status<0) + HGOTO_ERROR (H5E_IO, H5E_WRITEERROR, FAIL, "scatter failed"); + } /* end for */ + + /* Release selection iterators */ + if(file_iter_init) { + H5S_select_iter_release(&file_iter); + file_iter_init=0; + } /* end if */ + if(mem_iter_init) { + H5S_select_iter_release(&mem_iter); + mem_iter_init=0; + } /* end if */ + if(bkg_iter_init) { + H5S_select_iter_release(&bkg_iter); + bkg_iter_init=0; } /* end if */ - } /* end for */ + + /* Get the next chunk nodes in the trees */ + fchunk_node=H5TB_next(fchunk_node); + mchunk_node=H5TB_next(mchunk_node); + + /* Sanity check that we either have both file & memory chunk information + * or _don't_ have both file & memory chunk information + * (i.e. don't run out of one kind of chunk before the other) + */ + assert((fchunk_node && mchunk_node) || (!fchunk_node && !mchunk_node)); + } /* end while */ done: #ifdef H5_HAVE_PARALLEL @@ -1968,7 +2084,7 @@ done: #endif xfer_mode = H5FD_MPIO_COLLECTIVE; if(H5P_set (dx_plist, H5D_XFER_IO_XFER_MODE_NAME, &xfer_mode) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set transfer mode"); + HDONE_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set transfer mode"); } /* end if */ #endif /*H5_HAVE_PARALLEL*/ @@ -1986,19 +2102,9 @@ done: if(bkg_iter_init) H5S_select_iter_release(&bkg_iter); - /* Close file space and memory space for each chunk*/ - for(h=0; h<fm.nchunks; h++) { - if(fm.mspace[h]) - H5S_close(fm.mspace[h]); - if(fm.fspace[h]) - H5S_close(fm.fspace[h]); - } - if(fm.chunk_coords) - H5MM_free(fm.chunk_coords); - if(fm.fspace) - H5MM_free(fm.fspace); - if(fm.mspace) - H5MM_free(fm.mspace); + /* 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() */ @@ -2060,7 +2166,7 @@ done: /*------------------------------------------------------------------------- * Function: H5D_chunk_coords_assist * - * Purpose: Compute the coords for a particular chunk (in CHUNK_PTR), + * Purpose: Compute the coords for a particular chunk (in CHUNK_IDX), * based on the size of the dataset's dataspace (given in * NDIMS and CHUNKS), putting the resulting chunk's coordinate * offsets in the COORDS array. @@ -2075,7 +2181,7 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5D_chunk_coords_assist(hssize_t *coords, size_t ndims, hsize_t chunks[], hsize_t chunk_ptr) +H5D_chunk_coords_assist(hssize_t *coords, size_t ndims, hsize_t chunks[], hsize_t chunk_idx) { hsize_t tmp; /* Size of "down elements" in each dimension */ size_t i, j; /* Local index variables */ @@ -2086,8 +2192,8 @@ H5D_chunk_coords_assist(hssize_t *coords, size_t ndims, hsize_t chunks[], hsize_ tmp=1; for(j=i+1; j<ndims; j++) tmp *= chunks[j]; - coords[i] = (hssize_t)(chunk_ptr / tmp); - chunk_ptr = chunk_ptr % tmp; + coords[i] = (hssize_t)(chunk_idx / tmp); + chunk_idx = chunk_idx % tmp; } coords[ndims] = 0; @@ -2096,7 +2202,7 @@ H5D_chunk_coords_assist(hssize_t *coords, size_t ndims, hsize_t chunks[], hsize_ /*------------------------------------------------------------------------- - * Function: H5D_chunk_mem_file_map + * Function: H5D_create_chunk_map * * Purpose: Creates the mapping between elements selected in each chunk * and the elements in the memory selection. @@ -2113,7 +2219,7 @@ H5D_chunk_coords_assist(hssize_t *coords, size_t ndims, hsize_t chunks[], hsize_ *------------------------------------------------------------------------- */ static herr_t -H5D_chunk_mem_file_map(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *file_space, +H5D_create_chunk_map(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *file_space, const H5S_t *mem_space, fm_map *fm) { H5S_t *tmp_fspace=NULL, /* Temporary file dataspace */ @@ -2124,12 +2230,19 @@ H5D_chunk_mem_file_map(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *file_ 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) */ hsize_t f_dims[H5O_LAYOUT_NDIMS]; /* Dimensionality of file dataspace */ + hsize_t nchunks, last_nchunks; /* Number of chunks in dataset */ + H5TB_NODE *curr_node; /* Current node in TBBT */ char bogus; /* "bogus" buffer to pass to selection iterator */ unsigned u; /* Local index variable */ - hsize_t j; /* Local index variable */ herr_t ret_value = SUCCEED; /*return value */ - FUNC_ENTER_NOINIT(H5D_chunk_mem_file_map); + FUNC_ENTER_NOINIT(H5D_create_chunk_map); + + /* Initialize fm_map structure */ + HDmemset(fm, 0, sizeof(fm_map)); + + /* Get layout for dataset */ + fm->layout = &(dataset->layout); /* Create a file space of a chunk's size, instead of whole file space*/ if(NULL==(tmp_fspace=H5S_create_simple((dataset->layout.ndims-1),dataset->layout.dim,NULL))) @@ -2146,7 +2259,7 @@ H5D_chunk_mem_file_map(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *file_ HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to de-select memory space"); /* Get dim number and dimensionality for each dataspace */ - f_ndims=dataset->layout.ndims-1; + fm->f_ndims=f_ndims=dataset->layout.ndims-1; if((sm_ndims = H5S_get_simple_extent_ndims(tmp_mspace))<0) HGOTO_ERROR (H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get dimension number"); fm->m_ndims=sm_ndims; @@ -2155,41 +2268,37 @@ H5D_chunk_mem_file_map(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *file_ HGOTO_ERROR (H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get dimensionality"); /* Decide the number of chunks in each dimension*/ - fm->nchunks = 1; + last_nchunks=0; + nchunks=1; for(u=0; u<f_ndims; u++) { fm->chunks[u] = ((f_dims[u]+dataset->layout.dim[u])-1) / dataset->layout.dim[u]; - fm->nchunks *= fm->chunks[u]; - } + + /* Track total number of chunks in dataset */ + nchunks *= fm->chunks[u]; + + /* Check if the chunk indices will overflow */ + if(nchunks<last_nchunks) + HGOTO_ERROR (H5E_DATASET, H5E_OVERFLOW, FAIL, "too many chunks"); + last_nchunks=nchunks; + } /* 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"); - /* Allocate arrays to hold each chunk's dataspace & selection, for both the - * file and memory */ - H5_CHECK_OVERFLOW((sizeof(H5S_t*)*fm->nchunks),hsize_t,size_t); - fm->fspace = (H5S_t**)H5MM_malloc((size_t)(sizeof(H5S_t*)*fm->nchunks)); - fm->mspace = (H5S_t**)H5MM_malloc((size_t)(sizeof(H5S_t*)*fm->nchunks)); - fm->elmt_count = 0; + /* Initialize TBBT's for file & memory chunk selections */ + if((fm->fsel=H5TB_fast_dmake(H5TB_FAST_HSIZE_COMPARE))==NULL) + HGOTO_ERROR(H5E_DATASET,H5E_CANTMAKETREE,FAIL,"can't create TBBT for file chunk selections"); + if((fm->msel=H5TB_fast_dmake(H5TB_FAST_HSIZE_COMPARE))==NULL) + HGOTO_ERROR(H5E_DATASET,H5E_CANTMAKETREE,FAIL,"can't create TBBT for memory chunk selections"); - /* Allocate array to hold coordinates of each chunk in file's dataspace */ - H5_CHECK_OVERFLOW((sizeof(hsize_t)*fm->nchunks*(f_ndims+1)),hsize_t,size_t); - fm->chunk_coords = (hssize_t*)H5MM_malloc((size_t)(sizeof(hsize_t)*fm->nchunks*(f_ndims+1))); - - /* Make per-chunk copies of memory and chunk dataspaces - * (with each one's selection set to "none" - */ - for(j=0; j<fm->nchunks; j++) { - if((fm->mspace[j] = H5S_copy(tmp_mspace))==NULL) - HGOTO_ERROR (H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy memory space"); - if((fm->fspace[j] = H5S_copy(tmp_fspace))==NULL) - HGOTO_ERROR (H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy file space"); - - /* Initialize chunk_coords for each chunk. each stride is the number of - * file space dimensions, with fast-growing dimension at the last - */ - H5D_chunk_coords_assist(fm->chunk_coords+j*(f_ndims+1), f_ndims, fm->chunks, j); - } + /* Save chunk template information */ + fm->fchunk_tmpl=tmp_fspace; + fm->mchunk_tmpl=tmp_mspace; + + /* Initialize "last chunk" information */ + fm->last_index=(hsize_t)-1; + fm->last_fchunk=fm->last_mchunk=NULL; /* Create temporary datatypes for selection iteration */ if((f_tid = H5I_register(H5I_DATATYPE, H5T_copy(dataset->type, H5T_COPY_ALL)))<0) @@ -2206,28 +2315,176 @@ H5D_chunk_mem_file_map(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *file_ if(H5S_select_iterate(&bogus, f_tid, file_space, H5D_chunk_cb, fm)<0) HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, "unable to iterate file space"); - /* Clean hyperslab span "scratch" information */ - for(j=0; j<fm->nchunks; j++) { - if(H5S_hyper_reset_scratch(fm->fspace[j])<0) + /* Clean file chunks' hyperslab span "scratch" information */ + curr_node=H5TB_first(fm->fsel->root); + while(curr_node) { + H5D_fchunk_info_t *chunk_info; /* Pointer chunk information */ + + /* Get pointer to chunk's information */ + chunk_info=curr_node->data; + assert(chunk_info); + + /* Clean hyperslab span's "scratch" information */ + if(H5S_hyper_reset_scratch(chunk_info->space)<0) HGOTO_ERROR (H5E_DATASET, H5E_CANTFREE, FAIL, "unable to reset span scratch info"); - if(H5S_hyper_reset_scratch(fm->mspace[j])<0) + + /* Get the next chunk node in the TBBT */ + curr_node=H5TB_next(curr_node); + } /* end while */ + + /* Clean memory chunks' hyperslab span "scratch" information */ + curr_node=H5TB_first(fm->msel->root); + while(curr_node) { + H5D_mchunk_info_t *chunk_info; /* Pointer chunk information */ + + /* Get pointer to chunk's information */ + chunk_info=curr_node->data; + assert(chunk_info); + + /* Clean hyperslab span's "scratch" information */ + if(H5S_hyper_reset_scratch(chunk_info->space)<0) HGOTO_ERROR (H5E_DATASET, H5E_CANTFREE, FAIL, "unable to reset span scratch info"); - } /* end for */ + + /* Get the next chunk node in the TBBT */ + curr_node=H5TB_next(curr_node); + } /* end while */ done: + /* Release the [potentially partially built] chunk mapping information if an error occurs */ + if(ret_value<0) { + if(tmp_fspace && !fm->fchunk_tmpl) { + if(H5S_close(tmp_fspace)<0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "can't release file chunk dataspace template"); + } /* end if */ + + if(tmp_mspace && !fm->mchunk_tmpl) { + if(H5S_close(tmp_mspace)<0) + HGOTO_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 */ + if(iter_init) { if (H5S_select_iter_release(&(fm->mem_iter))<0) HDONE_ERROR (H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator"); } - if(tmp_fspace) - H5S_close(tmp_fspace); - if(tmp_mspace) - H5S_close(tmp_mspace); if(f_tid!=(-1)) H5Tclose(f_tid); FUNC_LEAVE_NOAPI(ret_value); -} /* end H5D_chunk_mem_file_map() */ +} /* end H5D_create_chunk_map() */ + + +/*-------------------------------------------------------------------------- + NAME + H5D_free_fchunk_info + PURPOSE + Internal routine to destroy a file chunk info node (Wrapper for compatibility + with H5TB_dfree) + USAGE + void H5D_free_fchunk_info(fchunk_info) + void *fchunk_info; IN: Pointer to file chunk info to destroy + RETURNS + No return value + DESCRIPTION + Releases all the memory for a file chunk info node. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +static void +H5D_free_fchunk_info(void *_fchunk_info) +{ + H5D_fchunk_info_t *fchunk_info=(H5D_fchunk_info_t *)_fchunk_info; + + FUNC_ENTER_NOINIT(H5D_free_fchunk_info); + + assert(fchunk_info); + + H5S_close(fchunk_info->space); + + FUNC_LEAVE_NOAPI_VOID; +} /* H5D_free_fchunk_info() */ + + +/*-------------------------------------------------------------------------- + NAME + H5D_free_mchunk_info + PURPOSE + Internal routine to destroy a file chunk info node (Wrapper for compatibility + with H5TB_dfree) + USAGE + void H5D_free_mchunk_info(mchunk_info) + void *mchunk_info; IN: Pointer to memory chunk info to destroy + RETURNS + No return value + DESCRIPTION + Releases all the memory for a memory chunk info node. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +static void +H5D_free_mchunk_info(void *_mchunk_info) +{ + H5D_mchunk_info_t *mchunk_info=(H5D_mchunk_info_t *)_mchunk_info; + + FUNC_ENTER_NOINIT(H5D_free_mchunk_info); + + assert(mchunk_info); + + H5S_close(mchunk_info->space); + + FUNC_LEAVE_NOAPI_VOID; +} /* H5D_free_mchunk_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 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5D_destroy_chunk_map(fm_map *fm) +{ + herr_t ret_value = SUCCEED; /*return value */ + + FUNC_ENTER_NOINIT(H5D_destroy_chunk_map); + + /* Free the file chunk info tree */ + if(fm->fsel) + H5TB_dfree(fm->fsel,H5D_free_fchunk_info,NULL); + + /* Free the memory chunk info tree */ + if(fm->msel) + H5TB_dfree(fm->msel,H5D_free_mchunk_info,NULL); + + /* Free the file chunk dataspace template */ + if(fm->fchunk_tmpl) + if(H5S_close(fm->fchunk_tmpl)<0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "can't release file chunk dataspace template"); + + /* 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"); + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5D_destroy_chunk_map() */ /*------------------------------------------------------------------------- @@ -2251,9 +2508,11 @@ static herr_t H5D_chunk_cb(void UNUSED *elem, hid_t UNUSED type_id, hsize_t ndims, hssize_t *coords, void *_fm) { fm_map *fm = (fm_map*)_fm; /* File<->memory chunk mapping info */ + H5S_t *fspace; /* File chunk's dataspace */ + H5S_t *mspace; /* Memory chunk's dataspace */ hssize_t coords_in_chunk[H5O_LAYOUT_NDIMS]; /* Coordinates of element in chunk */ hssize_t coords_in_mem[H5O_LAYOUT_NDIMS]; /* Coordinates of element in memory */ - hsize_t chunk_idx; /* Chunk index */ + hsize_t chunk_index; /* Chunk index */ hsize_t u; /* Local index variables */ herr_t ret_value = SUCCEED; /* Return value */ @@ -2268,10 +2527,10 @@ H5D_chunk_cb(void UNUSED *elem, hid_t UNUSED type_id, hsize_t ndims, hssize_t *c #endif /* QAK */ /* Calculate the index of this chunk */ - if(H5V_chunk_index((unsigned)ndims,coords,fm->layout->dim,fm->chunks,fm->down_chunks,&chunk_idx)<0) + if(H5V_chunk_index((unsigned)ndims,coords,fm->layout->dim,fm->chunks,fm->down_chunks,&chunk_index)<0) HGOTO_ERROR (H5E_DATASPACE, H5E_BADRANGE, FAIL, "can't get chunk index"); #ifdef QAK -HDfprintf(stderr,"%s: chunk_idx=%Hu\n",FUNC,chunk_idx); +HDfprintf(stderr,"%s: chunk_index=%Hu\n",FUNC,chunk_index); #endif /* QAK */ /*convert coords from relative to whole file space to relative to its chunk space, @@ -2287,8 +2546,89 @@ HDfprintf(stderr,"%s: chunk_idx=%Hu\n",FUNC,chunk_idx); HDfprintf(stderr,"%Hd%s",coords_in_chunk[u],(u<(ndims-1)?", ":"}\n")); } #endif /* QAK */ + + /* Find correct chunk in file & memory TBBTs */ + 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. + */ + fspace=fm->last_fchunk; + mspace=fm->last_mchunk; + } /* end if */ + else { + H5TB_NODE *chunk_node; /* TBBT node holding chunk information */ + /* If the chunk index is not the same as the last chunk index we used, + * find the chunk in the tree. + */ + /* Get the chunk node from the TBBT */ + if((chunk_node=H5TB_dfind(fm->fsel,&chunk_index,NULL))!=NULL) { + /* We found the correct chunk already in the tree */ + + /* Get the file space information from the node */ + fspace=((H5D_fchunk_info_t *)(chunk_node->data))->space; + + /* Look up the memory space information for the chunk */ + if((chunk_node=H5TB_dfind(fm->msel,&chunk_index,NULL))==NULL) + HGOTO_ERROR (H5E_DATASPACE, H5E_NOTFOUND, FAIL, "can't find memory chunk info"); + + /* Get the file space information from the node */ + mspace=((H5D_mchunk_info_t *)(chunk_node->data))->space; + } /* end if */ + else { + H5D_fchunk_info_t *new_fchunk_info; /* File chunk information to insert into tree */ + H5D_mchunk_info_t *new_mchunk_info; /* Memory chunk information to insert into tree */ + + /* The correct chunk is not already in the tree, create a new node */ + /* in both the file and memory chunk trees */ + + /* Allocate the file & memory chunk information */ + if (NULL==(new_fchunk_info = H5FL_MALLOC (H5D_fchunk_info_t))) + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate file chunk info"); + if (NULL==(new_mchunk_info = H5FL_MALLOC (H5D_mchunk_info_t))) + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate memory chunk info"); + + /* Initialize the file chunk information */ + + /* Set the chunk index */ + new_fchunk_info->index=chunk_index; + + /* Copy the template file chunk dataspace */ + if((new_fchunk_info->space = H5S_copy(fm->fchunk_tmpl))==NULL) + HGOTO_ERROR (H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy file space"); + + /* Compute the chunk's coordinates */ + H5D_chunk_coords_assist(new_fchunk_info->coords, fm->f_ndims, fm->chunks, chunk_index); + + /* Insert the new file chunk into the TBBT tree */ + if(H5TB_dins(fm->fsel,new_fchunk_info,new_fchunk_info)==NULL) + HGOTO_ERROR(H5E_DATASPACE,H5E_CANTINSERT,FAIL,"can't insert file chunk into TBBT"); + + /* Initialize the memory chunk information */ + + /* Set the chunk index */ + new_mchunk_info->index=chunk_index; + + /* Copy the template memory chunk dataspace */ + if((new_mchunk_info->space = H5S_copy(fm->mchunk_tmpl))==NULL) + HGOTO_ERROR (H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy file space"); + + /* Insert the new memory chunk into the TBBT tree */ + if(H5TB_dins(fm->msel,new_mchunk_info,new_mchunk_info)==NULL) + HGOTO_ERROR(H5E_DATASPACE,H5E_CANTINSERT,FAIL,"can't insert memory chunk into TBBT"); + + /* Get the dataspaces for use in this routine */ + fspace=new_fchunk_info->space; + mspace=new_mchunk_info->space; + } /* end else */ + + /* Update the "last chunk seen" information */ + fm->last_index=chunk_index; + fm->last_fchunk=fspace; + fm->last_mchunk=mspace; + } /* end else */ + /* Add point to file selection for chunk */ - if(H5S_hyper_add_span_element(fm->fspace[chunk_idx], (unsigned)ndims, coords_in_chunk)<0) + if(H5S_hyper_add_span_element(fspace, fm->f_ndims, coords_in_chunk)<0) HGOTO_ERROR (H5E_DATASPACE, H5E_CANTSELECT, FAIL, "unable to select element"); /* Get coordinates of selection iterator for memory */ @@ -2304,7 +2644,7 @@ HDfprintf(stderr,"%s: chunk_idx=%Hu\n",FUNC,chunk_idx); } #endif /* QAK */ /* Add point to memory selection for chunk */ - if(H5S_hyper_add_span_element(fm->mspace[chunk_idx], fm->m_ndims, coords_in_mem)<0) + if(H5S_hyper_add_span_element(mspace, fm->m_ndims, coords_in_mem)<0) HGOTO_ERROR (H5E_DATASPACE, H5E_CANTSELECT, FAIL, "unable to select element"); /* Move memory selection iterator to next element in selection */ |