diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/H5Dchunk.c | 102 | ||||
-rw-r--r-- | src/H5Dio.c | 169 | ||||
-rw-r--r-- | src/H5Dprivate.h | 3 | ||||
-rw-r--r-- | src/H5Dpublic.h | 6 | ||||
-rw-r--r-- | src/H5Pdxpl.c | 38 |
5 files changed, 283 insertions, 35 deletions
diff --git a/src/H5Dchunk.c b/src/H5Dchunk.c index 7a06477..e3f060a 100644 --- a/src/H5Dchunk.c +++ b/src/H5Dchunk.c @@ -281,6 +281,108 @@ H5FL_DEFINE(H5D_chunk_info_t); /* Declare a free list to manage the chunk sequence information */ H5FL_BLK_DEFINE_STATIC(chunk); + +/*------------------------------------------------------------------------- + * Function: H5D__chunk_direct_write + * + * Purpose: Internal routine to write a chunk + * directly into the file. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Raymond Lu + * 30 July 2012 + * + *------------------------------------------------------------------------- + */ +herr_t +H5D__chunk_direct_write(const H5D_t *dset, hid_t dxpl_id, uint32_t filters, hsize_t *offset, + size_t data_size, const void *buf) +{ + const H5O_layout_t *layout = &(dset->shared->layout); /* Dataset layout */ + H5D_chunk_ud_t udata; /* User data for querying chunk info */ + hsize_t chunk_idx; + H5D_dxpl_cache_t _dxpl_cache; /* Data transfer property cache buffer */ + H5D_dxpl_cache_t *dxpl_cache = &_dxpl_cache; /* Data transfer property cache */ + const H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk); /*raw data chunk cache */ + int space_ndims; /* Dataset's space rank */ + hsize_t space_dim[H5O_LAYOUT_NDIMS]; /* Dataset's dataspace dimensions */ + H5FD_t *lf; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC_TAG(dxpl_id, dset->oloc.addr, FAIL) + + /* Allocate data space and initialize it if it hasn't been. */ + if(!(*dset->shared->layout.ops->is_space_alloc)(&dset->shared->layout.storage)) { + /* Allocate storage */ + if(H5D__alloc_storage(dset, dxpl_id, H5D_ALLOC_WRITE, FALSE, NULL) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize storage") + } /* end if */ + + + /* Retrieve the dataset dimensions */ + if((space_ndims = H5S_get_simple_extent_dims(dset->shared->space, space_dim, NULL)) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to get simple dataspace info") + + /* Calculate the index of this chunk */ + if(H5V_chunk_index((unsigned)space_ndims, offset, + layout->u.chunk.dim, layout->u.chunk.down_chunks, &chunk_idx) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't get chunk index") + + /* Find out the file address of the chunk */ + if(H5D__chunk_lookup(dset, dxpl_id, offset, chunk_idx, + &udata) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error looking up chunk address") + + udata.filter_mask = filters; + + /* Check if the chunk needs to be 'inserted' (could exist already and + * the 'insert' operation could resize it) + */ + { + H5D_chk_idx_info_t idx_info; /* Chunked index info */ + + /* Compose chunked index info struct */ + idx_info.f = dset->oloc.file; + idx_info.dxpl_id = dxpl_id; + idx_info.pline = &(dset->shared->dcpl_cache.pline); + idx_info.layout = &(dset->shared->layout.u.chunk); + idx_info.storage = &(dset->shared->layout.storage.u.chunk); + + /* Set up the size of chunk for user data */ + udata.nbytes = data_size; + + /* Create the chunk it if it doesn't exist, or reallocate the chunk + * if its size changed. + */ + if((dset->shared->layout.storage.u.chunk.ops->insert)(&idx_info, &udata) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, FAIL, "unable to insert/resize chunk") + + /* Make sure the address of the chunk is returned. */ + if(!H5F_addr_defined(udata.addr)) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "chunk address isn't defined") + } /* end if */ + + /* Fill the DXPL cache values for later use */ + if(H5D__get_dxpl_cache(dxpl_id, &dxpl_cache) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't fill dxpl cache") + + /* Evict the entry from the cache if present, but do not flush + * it to disk */ + if(UINT_MAX != udata.idx_hint) { + if(H5D__chunk_cache_evict(dset, dxpl_id, dxpl_cache, + rdcc->slot[udata.idx_hint], FALSE) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTREMOVE, FAIL, "unable to evict chunk") + } /* end if */ + + /* Write the data to the file */ + if(H5F_block_write(dset->oloc.file, H5FD_MEM_DRAW, udata.addr, data_size, dxpl_id, buf) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to write raw data to file") + + +done: + FUNC_LEAVE_NOAPI_TAG(ret_value, FAIL) +} /*------------------------------------------------------------------------- diff --git a/src/H5Dio.c b/src/H5Dio.c index 1bd6dae..8b6d380 100644 --- a/src/H5Dio.c +++ b/src/H5Dio.c @@ -28,6 +28,8 @@ #include "H5Eprivate.h" /* Error handling */ #include "H5FLprivate.h" /* Free Lists */ #include "H5Iprivate.h" /* IDs */ +#include "H5MMprivate.h" /* Memory management */ +#include "H5Sprivate.h" /* Dataspace */ #ifdef H5_HAVE_PARALLEL /* Remove this if H5R_DATASET_REGION is no longer used in this file */ @@ -56,6 +58,8 @@ static herr_t H5D__read(H5D_t *dataset, hid_t mem_type_id, static herr_t H5D__write(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space, const H5S_t *file_space, hid_t dset_xfer_plist, const void *buf); +static herr_t H5D__pre_write(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id, + hid_t file_space_id, hid_t dxpl_id, const void *buf); /* Setup/teardown routines */ static herr_t H5D__ioinfo_init(H5D_t *dset, const H5D_dxpl_cache_t *dxpl_cache, @@ -136,6 +140,10 @@ H5Dread(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id, HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset") if(NULL == dset->oloc.file) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset") + + if(mem_space_id < 0 || file_space_id < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space") + if(H5S_ALL != mem_space_id) { if(NULL == (mem_space = (const H5S_t *)H5I_object_verify(mem_space_id, H5I_DATASPACE))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space") @@ -213,37 +221,51 @@ herr_t H5Dwrite(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id, hid_t file_space_id, hid_t dxpl_id, const void *buf) { - H5D_t *dset = NULL; - const H5S_t *mem_space = NULL; - const H5S_t *file_space = NULL; - char fake_char; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(FAIL) H5TRACE6("e", "iiiii*x", dset_id, mem_type_id, mem_space_id, file_space_id, dxpl_id, buf); + if(!dset_id) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset") + + if(H5D__pre_write(dset_id, mem_type_id, mem_space_id, file_space_id, dxpl_id, buf) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't prepare for writing data") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Dwrite() */ + + +/*------------------------------------------------------------------------- + * Function: H5D__pre_write + * + * Purpose: Preparation for writing data. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Raymond Lu + * 2 November 2012 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5D__pre_write(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id, + hid_t file_space_id, hid_t dxpl_id, const void *buf) +{ + H5D_t *dset = NULL; + H5P_genplist_t *plist; /* Property list pointer */ + hbool_t direct_write = FALSE; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC + /* check arguments */ if(NULL == (dset = (H5D_t *)H5I_object_verify(dset_id, H5I_DATASET))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset") if(NULL == dset->oloc.file) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset") - if(H5S_ALL != mem_space_id) { - if(NULL == (mem_space = (const H5S_t *)H5I_object_verify(mem_space_id, H5I_DATASPACE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space") - - /* Check for valid selection */ - 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) { - if(NULL == (file_space = (const H5S_t *)H5I_object_verify(file_space_id, H5I_DATASPACE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space") - - /* Check for valid selection */ - if(H5S_SELECT_VALID(file_space) != TRUE) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "file selection+offset not within extent") - } /* end if */ + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file") /* Get the default dataset transfer property list if the user didn't provide one */ if(H5P_DEFAULT == dxpl_id) @@ -251,23 +273,102 @@ H5Dwrite(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id, else if(TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER)) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not xfer parms") - if(!buf && (NULL == file_space || 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) - buf = &fake_char; + /* Get the plist structure */ + if(NULL == (plist = H5P_object_verify(dxpl_id, H5P_DATASET_XFER))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + + if(H5P_get(plist, H5D_XFER_DIRECT_CHUNK_WRITE_FLAG_NAME, &direct_write) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "error getting flag for direct chunk write") + + /* Direct chunk write */ + if(direct_write) { + uint32_t direct_filters = 0; + hsize_t *direct_offset; + size_t direct_datasize = 0; + int ndims = 0; + hsize_t dims[H5O_LAYOUT_NDIMS]; + hsize_t internal_offset[H5O_LAYOUT_NDIMS]; + int i; + + if(H5D_CHUNKED != dset->shared->layout.type) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a chunked dataset") + + if(H5P_get(plist, H5D_XFER_DIRECT_CHUNK_WRITE_FILTERS_NAME, &direct_filters) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "error getting filter info for direct chunk write") + + if(H5P_get(plist, H5D_XFER_DIRECT_CHUNK_WRITE_OFFSET_NAME, &direct_offset) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "error getting offset info for direct chunk write") + + if(H5P_get(plist, H5D_XFER_DIRECT_CHUNK_WRITE_DATASIZE_NAME, &direct_datasize) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "error getting data size for direct chunk write") + + /* The library's chunking code requires the offset terminates with a zero. So transfer the + * offset array to an internal offset array */ + if((ndims = H5S_get_simple_extent_dims(dset->shared->space, dims, NULL)) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't retrieve dataspace extent dims") + + for(i=0; i<ndims; i++) { + /* Make sure the offset doesn't exceed the dataset's dimensions */ + if(direct_offset[i] > dims[i]) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "offset exceeds dimensions of dataset") + + /* Make sure the offset fall right on a chunk's boundary */ + if(direct_offset[i] % dset->shared->layout.u.chunk.dim[i]) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "offset doesn't fall on chunks's boundary") + + internal_offset[i] = direct_offset[i]; + } + + /* Terminate the offset with a zero */ + internal_offset[ndims] = 0; + + /* write raw data */ + if(H5D__chunk_direct_write(dset, dxpl_id, direct_filters, internal_offset, direct_datasize, buf) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't write chunk directly") + } else { /* Normal write */ + const H5S_t *mem_space = NULL; + const H5S_t *file_space = NULL; + char fake_char; + + if(mem_space_id < 0 || file_space_id < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space") - /* write raw data */ - if(H5D__write(dset, mem_type_id, mem_space, file_space, dxpl_id, buf) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't write data") + if(H5S_ALL != mem_space_id) { + if(NULL == (mem_space = (const H5S_t *)H5I_object_verify(mem_space_id, H5I_DATASPACE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space") + + /* Check for valid selection */ + 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) { + if(NULL == (file_space = (const H5S_t *)H5I_object_verify(file_space_id, H5I_DATASPACE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space") + + /* Check for valid selection */ + if(H5S_SELECT_VALID(file_space) != TRUE) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "file selection+offset not within extent") + } /* end if */ + + if(!buf && (NULL == file_space || 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) + buf = &fake_char; + + /* write raw data */ + if(H5D__write(dset, mem_type_id, mem_space, file_space, dxpl_id, buf) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't write data") + } done: - FUNC_LEAVE_API(ret_value) -} /* end H5Dwrite() */ + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5D__pre_write() */ /*------------------------------------------------------------------------- diff --git a/src/H5Dprivate.h b/src/H5Dprivate.h index 5acf43f..1e2b91d 100644 --- a/src/H5Dprivate.h +++ b/src/H5Dprivate.h @@ -174,5 +174,8 @@ H5_DLL herr_t H5D_chunk_idx_reset(H5O_storage_chunk_t *storage, hbool_t reset_ad H5_DLL herr_t H5D_btree_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE * stream, int indent, int fwidth, unsigned ndims); +H5_DLL herr_t H5D__chunk_direct_write(const H5D_t *dset, hid_t dxpl_id, uint32_t filters, + hsize_t *offset, size_t data_size, const void *buf); + #endif /* _H5Dprivate_H */ diff --git a/src/H5Dpublic.h b/src/H5Dpublic.h index c878d4a..523f2b2 100644 --- a/src/H5Dpublic.h +++ b/src/H5Dpublic.h @@ -34,6 +34,12 @@ #define H5D_CHUNK_CACHE_NBYTES_DEFAULT ((size_t) -1) #define H5D_CHUNK_CACHE_W0_DEFAULT -1. +/* Property names for H5LTDdirect_chunk_write */ +#define H5D_XFER_DIRECT_CHUNK_WRITE_FLAG_NAME "direct_chunk_flag" +#define H5D_XFER_DIRECT_CHUNK_WRITE_FILTERS_NAME "direct_chunk_filters" +#define H5D_XFER_DIRECT_CHUNK_WRITE_OFFSET_NAME "direct_chunk_offset" +#define H5D_XFER_DIRECT_CHUNK_WRITE_DATASIZE_NAME "direct_chunk_datasize" + /*******************/ /* Public Typedefs */ /*******************/ diff --git a/src/H5Pdxpl.c b/src/H5Pdxpl.c index 04ff54a..552ea63 100644 --- a/src/H5Pdxpl.c +++ b/src/H5Pdxpl.c @@ -158,6 +158,15 @@ #define H5D_XFER_XFORM_COPY H5P__dxfr_xform_copy #define H5D_XFER_XFORM_CMP H5P__dxfr_xform_cmp #define H5D_XFER_XFORM_CLOSE H5P__dxfr_xform_close +/* Definitions for properties of direct chunk write */ +#define H5D_XFER_DIRECT_CHUNK_WRITE_FLAG_SIZE sizeof(hbool_t) +#define H5D_XFER_DIRECT_CHUNK_WRITE_FLAG_DEF FALSE +#define H5D_XFER_DIRECT_CHUNK_WRITE_FILTERS_SIZE sizeof(uint32_t) +#define H5D_XFER_DIRECT_CHUNK_WRITE_FILTERS_DEF 0 +#define H5D_XFER_DIRECT_CHUNK_WRITE_OFFSET_SIZE sizeof(hsize_t *) +#define H5D_XFER_DIRECT_CHUNK_WRITE_OFFSET_DEF NULL +#define H5D_XFER_DIRECT_CHUNK_WRITE_DATASIZE_SIZE sizeof(size_t) +#define H5D_XFER_DIRECT_CHUNK_WRITE_DATASIZE_DEF 0 /******************/ /* Local Typedefs */ @@ -255,7 +264,10 @@ static const H5Z_EDC_t H5D_def_enable_edc_g = H5D_XFER_EDC_DEF; /* De static const H5Z_cb_t H5D_def_filter_cb_g = H5D_XFER_FILTER_CB_DEF; /* Default value for filter callback */ static const H5T_conv_cb_t H5D_def_conv_cb_g = H5D_XFER_CONV_CB_DEF; /* Default value for datatype conversion callback */ static const void *H5D_def_xfer_xform_g = H5D_XFER_XFORM_DEF; /* Default value for data transform */ - +static const hbool_t H5D_def_direct_chunk_flag_g = H5D_XFER_DIRECT_CHUNK_WRITE_FLAG_DEF; /* Default value for the flag of direct chunk write */ +static const uint32_t H5D_def_direct_chunk_filters_g = H5D_XFER_DIRECT_CHUNK_WRITE_FILTERS_DEF; /* Default value for the filters of direct chunk write */ +static const hsize_t *H5D_def_direct_chunk_offset_g = H5D_XFER_DIRECT_CHUNK_WRITE_OFFSET_DEF; /* Default value for the offset of direct chunk write */ +static const size_t H5D_def_direct_chunk_datasize_g = H5D_XFER_DIRECT_CHUNK_WRITE_DATASIZE_DEF; /* Default value for the datasize of direct chunk write */ /*------------------------------------------------------------------------- @@ -426,6 +438,30 @@ H5P__dxfr_reg_prop(H5P_genclass_t *pclass) H5D_XFER_XFORM_DEL, H5D_XFER_XFORM_COPY, H5D_XFER_XFORM_CMP, H5D_XFER_XFORM_CLOSE) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class") + /* Register the property of flag for direct chunk write */ + /* (Note: this property should not have an encode/decode callback -QAK) */ + if(H5P_register_real(pclass, H5D_XFER_DIRECT_CHUNK_WRITE_FLAG_NAME, H5D_XFER_DIRECT_CHUNK_WRITE_FLAG_SIZE, &H5D_def_direct_chunk_flag_g, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class") + + /* Register the property of filter for direct chunk write */ + /* (Note: this property should not have an encode/decode callback -QAK) */ + if(H5P_register_real(pclass, H5D_XFER_DIRECT_CHUNK_WRITE_FILTERS_NAME, H5D_XFER_DIRECT_CHUNK_WRITE_FILTERS_SIZE, &H5D_def_direct_chunk_filters_g, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class") + + /* Register the property of offset for direct chunk write */ + /* (Note: this property should not have an encode/decode callback -QAK) */ + if(H5P_register_real(pclass, H5D_XFER_DIRECT_CHUNK_WRITE_OFFSET_NAME, H5D_XFER_DIRECT_CHUNK_WRITE_OFFSET_SIZE, &H5D_def_direct_chunk_offset_g, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class") + + /* Register the property of datasize for direct chunk write */ + /* (Note: this property should not have an encode/decode callback -QAK) */ + if(H5P_register_real(pclass, H5D_XFER_DIRECT_CHUNK_WRITE_DATASIZE_NAME, H5D_XFER_DIRECT_CHUNK_WRITE_DATASIZE_SIZE, &H5D_def_direct_chunk_datasize_g, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class") + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5P__dxfr_reg_prop() */ |