diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2008-06-16 22:17:29 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2008-06-16 22:17:29 (GMT) |
commit | db2c4c497abab139485dbf6797e56b1340e4577d (patch) | |
tree | f7dfb321a3643658ed24aaf776ec4c1e48bc76a3 /src | |
parent | 55af47c47c3c0c7bc17266968f5e0e782189e819 (diff) | |
download | hdf5-db2c4c497abab139485dbf6797e56b1340e4577d.zip hdf5-db2c4c497abab139485dbf6797e56b1340e4577d.tar.gz hdf5-db2c4c497abab139485dbf6797e56b1340e4577d.tar.bz2 |
[svn-r15221] Description:
Bring changes from trunk from the time the branch was created (r14280)
up to the 1.8.0 release (r14525) back into the metadata journaling branch.
Tested on:
FreeBSD/32 6.2 (duty) in debug mode
FreeBSD/64 6.2 (liberty) w/C++ & FORTRAN, in debug mode
Linux/32 2.6 (kagiso) w/PGI compilers, w/C++ & FORTRAN, w/threadsafe,
in debug mode
Linux/64-amd64 2.6 (smirom) w/default API=1.6.x, w/C++ & FORTRAN,
in production mode
Linux/64-ia64 2.6 (cobalt) w/Intel compilers, w/C++ & FORTRAN,
in production mode
Solaris/32 2.10 (linew) w/deprecated symbols disabled, w/C++ & FORTRAN,
w/szip filter, in production mode
Linux/64-ia64 2.4 (tg-login3) w/parallel, w/FORTRAN, in production mode
Diffstat (limited to 'src')
80 files changed, 5497 insertions, 3347 deletions
diff --git a/src/H5C2journal.c b/src/H5C2journal.c index a481e4d..84dcd8f 100644 --- a/src/H5C2journal.c +++ b/src/H5C2journal.c @@ -3517,7 +3517,7 @@ H5Pset_journal(hid_t fapl_id, const char *journal_file) HDstrcpy(mdj_config.journal_file_path, journal_file); /* set latest format */ - if (H5Pset_latest_format(fapl_id, TRUE) < 0) + if (H5Pset_libver_bounds(fapl_id, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set 'latest format'") /* set cache config struct information */ @@ -990,7 +990,7 @@ done: *------------------------------------------------------------------------- */ herr_t -H5Dset_extent(hid_t dset_id, const hsize_t *size) +H5Dset_extent(hid_t dset_id, const hsize_t size[]) { H5D_t *dset; /* Dataset for this operation */ herr_t ret_value = SUCCEED; /* Return value */ diff --git a/src/H5Dcontig.c b/src/H5Dcontig.c index 8a081c3..5cb1df9 100644 --- a/src/H5Dcontig.c +++ b/src/H5Dcontig.c @@ -661,7 +661,7 @@ H5D_contig_writevv(const H5D_io_info_t *io_info, 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=_buf; /* Pointer to buffer to fill */ + 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 size; /* Size of sequence in bytes */ @@ -1204,11 +1204,11 @@ done: if(H5I_dec_ref(tid_mem) < 0) HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't decrement temporary datatype ID") if(buf) - H5FL_BLK_FREE(type_conv, buf); + (void)H5FL_BLK_FREE(type_conv, buf); if(reclaim_buf) - H5FL_BLK_FREE(type_conv, reclaim_buf); + (void)H5FL_BLK_FREE(type_conv, reclaim_buf); if(bkg) - H5FL_BLK_FREE(type_conv, bkg); + (void)H5FL_BLK_FREE(type_conv, bkg); FUNC_LEAVE_NOAPI(ret_value) } /* end H5D_contig_copy() */ diff --git a/src/H5Ddeprec.c b/src/H5Ddeprec.c index 2810f5a..9fcf367 100644 --- a/src/H5Ddeprec.c +++ b/src/H5Ddeprec.c @@ -280,7 +280,7 @@ done: *------------------------------------------------------------------------- */ herr_t -H5Dextend(hid_t dset_id, const hsize_t *size) +H5Dextend(hid_t dset_id, const hsize_t size[]) { H5D_t *dset; herr_t ret_value = SUCCEED; /* Return value */ @@ -346,10 +346,6 @@ H5D_extend(H5D_t *dataset, const hsize_t *size, hid_t dxpl_id) /* Updated the dataset's info if the dataspace was successfully extended */ if(changed) { - /* Save the new dataspace in the file if necessary */ - if(H5S_write(&(dataset->oloc), space, TRUE, dxpl_id) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to update file with new dataspace") - /* Update the index values for the cached chunks for this dataset */ if(H5D_CHUNKED == dataset->shared->layout.type) if(H5D_istore_update_cache(dataset, dxpl_id) < 0) @@ -358,8 +354,11 @@ H5D_extend(H5D_t *dataset, const hsize_t *size, hid_t dxpl_id) /* Allocate space for the new parts of the dataset, if appropriate */ fill = &dataset->shared->dcpl_cache.fill; if(fill->alloc_time == H5D_ALLOC_TIME_EARLY) - if(H5D_alloc_storage(dataset->oloc.file, dxpl_id, dataset, H5D_ALLOC_EXTEND, TRUE, FALSE) < 0) + if(H5D_alloc_storage(dataset->oloc.file, dxpl_id, dataset, H5D_ALLOC_EXTEND, FALSE) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize dataset with fill value") + + /* Mark the dataspace as dirty, for later writing to the file */ + dataset->shared->space_dirty = TRUE; } /* end if */ done: diff --git a/src/H5Dint.c b/src/H5Dint.c index 94b53d3..a5ea398 100644 --- a/src/H5Dint.c +++ b/src/H5Dint.c @@ -65,6 +65,7 @@ static herr_t H5D_init_type(H5F_t *file, const H5D_t *dset, hid_t type_id, static herr_t H5D_init_space(H5F_t *file, const H5D_t *dset, const H5S_t *space); static herr_t H5D_update_oh_info(H5F_t *file, hid_t dxpl_id, H5D_t *dset); 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); /*********************/ @@ -97,6 +98,9 @@ H5FL_DEFINE_STATIC(H5D_shared_t); /* Declare the external PQ free list for the sieve buffer information */ H5FL_BLK_EXTERN(sieve_buf); +/* Declare the external free list to manage the H5D_chunk_info_t struct */ +H5FL_EXTERN(H5D_chunk_info_t); + /* Define a static "default" dataset structure to use to initialize new datasets */ static H5D_shared_t H5D_def_dset; @@ -567,7 +571,7 @@ done: static herr_t H5D_update_oh_info(H5F_t *file, hid_t dxpl_id, H5D_t *dset) { - struct H5O_t *oh = NULL; /* Pointer to dataset's object header */ + H5O_t *oh = NULL; /* Pointer to dataset's object header */ size_t ohdr_size = H5D_MINHDR_SIZE; /* Size of dataset's object header */ H5O_loc_t *oloc = NULL; /* Dataset's object location */ H5O_layout_t *layout; /* Dataset's layout information */ @@ -653,10 +657,10 @@ H5D_update_oh_info(H5F_t *file, hid_t dxpl_id, H5D_t *dset) /* Get a pointer to the object header itself */ if((oh = H5O_protect(oloc, dxpl_id)) == NULL) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to protect dataset object header") + HGOTO_ERROR(H5E_DATASET, H5E_CANTPROTECT, FAIL, "unable to protect dataset object header") /* Write new fill value message */ - if(H5O_msg_append(file, dxpl_id, oh, H5O_FILL_NEW_ID, H5O_MSG_FLAG_CONSTANT, 0, fill_prop) < 0) + if(H5O_msg_append_oh(file, dxpl_id, oh, H5O_FILL_NEW_ID, H5O_MSG_FLAG_CONSTANT, 0, fill_prop) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update new fill value header message") /* If there is valid information for the old fill value struct, add it */ @@ -672,12 +676,12 @@ H5D_update_oh_info(H5F_t *file, hid_t dxpl_id, H5D_t *dset) H5O_msg_reset_share(H5O_FILL_ID, &old_fill_prop); /* Write old fill value */ - if(H5O_msg_append(file, dxpl_id, oh, H5O_FILL_ID, H5O_MSG_FLAG_CONSTANT, 0, &old_fill_prop) < 0) + if(H5O_msg_append_oh(file, dxpl_id, oh, H5O_FILL_ID, H5O_MSG_FLAG_CONSTANT, 0, &old_fill_prop) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update old fill value header message") } /* end if */ /* Update the datatype and dataspace header messages */ - if(H5O_msg_append(file, dxpl_id, oh, H5O_DTYPE_ID, H5O_MSG_FLAG_CONSTANT, 0, type) < 0) + if(H5O_msg_append_oh(file, dxpl_id, oh, H5O_DTYPE_ID, H5O_MSG_FLAG_CONSTANT, 0, type) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update datatype header message") if(H5S_append(file, dxpl_id, oh, dset->shared->space) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update dataspace header message") @@ -687,7 +691,7 @@ H5D_update_oh_info(H5F_t *file, hid_t dxpl_id, H5D_t *dset) H5O_pline_t *pline; /* Dataset's I/O pipeline information */ pline = &dset->shared->dcpl_cache.pline; - if(pline->nused > 0 && H5O_msg_append(file, dxpl_id, oh, H5O_PLINE_ID, H5O_MSG_FLAG_CONSTANT, 0, pline) < 0) + if(pline->nused > 0 && H5O_msg_append_oh(file, dxpl_id, oh, H5O_PLINE_ID, H5O_MSG_FLAG_CONSTANT, 0, pline) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update filter header message") } /* end if */ @@ -696,7 +700,7 @@ H5D_update_oh_info(H5F_t *file, hid_t dxpl_id, H5D_t *dset) * allocation until later. */ if(fill_prop->alloc_time == H5D_ALLOC_TIME_EARLY) - if(H5D_alloc_storage(file, dxpl_id, dset, H5D_ALLOC_CREATE, FALSE, FALSE) < 0) + if(H5D_alloc_storage(file, dxpl_id, dset, H5D_ALLOC_CREATE, FALSE) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize storage") /* Update external storage message, if it's used */ @@ -716,7 +720,7 @@ H5D_update_oh_info(H5F_t *file, hid_t dxpl_id, H5D_t *dset) /* Pin the heap down in memory */ if(NULL == (heap = H5HL_protect(file, dxpl_id, efl->heap_addr, H5AC_WRITE))) - HGOTO_ERROR(H5E_DATASET, H5E_PROTECT, FAIL, "unable to protect EFL file name heap") + HGOTO_ERROR(H5E_DATASET, H5E_CANTPROTECT, FAIL, "unable to protect EFL file name heap") /* Insert "empty" name first */ if((size_t)(-1) == H5HL_insert(file, dxpl_id, heap, (size_t)1, "")) { @@ -741,18 +745,18 @@ H5D_update_oh_info(H5F_t *file, hid_t dxpl_id, H5D_t *dset) /* Release the heap */ if(H5HL_unprotect(file, dxpl_id, heap, efl->heap_addr) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_PROTECT, FAIL, "unable to unprotect EFL file name heap") + HGOTO_ERROR(H5E_DATASET, H5E_CANTUNPROTECT, FAIL, "unable to unprotect EFL file name heap") heap = NULL; /* Insert EFL message into dataset object header */ - if(H5O_msg_append(file, dxpl_id, oh, H5O_EFL_ID, H5O_MSG_FLAG_CONSTANT, 0, efl) < 0) + if(H5O_msg_append_oh(file, dxpl_id, oh, H5O_EFL_ID, H5O_MSG_FLAG_CONSTANT, 0, efl) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update external file list message") } /* end if */ /* Create layout message */ /* (Don't make layout message constant unless allocation time is early, since space may not be allocated) */ /* (Note: this is relying on H5D_alloc_storage not calling H5O_msg_write during dataset creation) */ - if(H5O_msg_append(file, dxpl_id, oh, H5O_LAYOUT_ID, ((fill_prop->alloc_time == H5D_ALLOC_TIME_EARLY && H5D_COMPACT != layout->type) ? H5O_MSG_FLAG_CONSTANT : 0), 0, layout) < 0) + if(H5O_msg_append_oh(file, dxpl_id, oh, H5O_LAYOUT_ID, ((fill_prop->alloc_time == H5D_ALLOC_TIME_EARLY && H5D_COMPACT != layout->type) ? H5O_MSG_FLAG_CONSTANT : 0), 0, layout) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update layout") #ifdef H5O_ENABLE_BOGUS @@ -778,15 +782,16 @@ H5D_update_oh_info(H5F_t *file, hid_t dxpl_id, H5D_t *dset) } #endif /* H5O_ENABLE_BOGUS */ - /* Add a modification time message. */ - if(H5O_touch_oh(file, dxpl_id, oh, TRUE) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update modification time message") + /* Add a modification time message, if using older format. */ + if(!use_latest_format) + if(H5O_touch_oh(file, dxpl_id, oh, TRUE) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update modification time message") done: /* Release pointer to object header itself */ if(oloc != NULL && oh != NULL) if(H5O_unprotect(oloc, oh) < 0) - HDONE_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to unprotect dataset object header") + HDONE_ERROR(H5E_DATASET, H5E_CANTUNPROTECT, FAIL, "unable to unprotect dataset object header") FUNC_LEAVE_NOAPI(ret_value) } /* end H5D_update_oh_info() */ @@ -1428,7 +1433,7 @@ H5D_open_oid(H5D_t *dataset, hid_t dxpl_id) && ((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))) && IS_H5FD_MPI(dataset->oloc.file)) { - if(H5D_alloc_storage(dataset->oloc.file, dxpl_id, dataset, H5D_ALLOC_OPEN, TRUE, FALSE) < 0) + if(H5D_alloc_storage(dataset->oloc.file, dxpl_id, dataset, H5D_ALLOC_OPEN, FALSE) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize file storage") } /* end if */ @@ -1491,28 +1496,14 @@ H5D_close(H5D_t *dataset) dataset->shared->fo_count--; if(dataset->shared->fo_count == 0) { - /* Update the dataspace on disk, if it's been changed */ - if(dataset->shared->space_dirty) { - if(H5S_write(&(dataset->oloc), dataset->shared->space, TRUE, H5AC_dxpl_id) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to update file with new dataspace") - dataset->shared->space_dirty = FALSE; - } /* end if */ + /* Flush the dataset's information */ + if(H5D_flush_real(dataset, H5AC_dxpl_id, H5F_FLUSH_NONE) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to flush cached dataset info") /* Free the data sieve buffer, if it's been allocated */ if(dataset->shared->cache.contig.sieve_buf) { HDassert(dataset->shared->layout.type != H5D_COMPACT); /* We should never have a sieve buffer for compact storage */ - /* Flush the raw data buffer, if its dirty */ - if(dataset->shared->cache.contig.sieve_dirty) { - /* Write dirty data sieve buffer to file */ - if(H5F_block_write(dataset->oloc.file, H5FD_MEM_DRAW, dataset->shared->cache.contig.sieve_loc, - dataset->shared->cache.contig.sieve_size, H5AC_dxpl_id, dataset->shared->cache.contig.sieve_buf) < 0) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed") - - /* Reset sieve buffer dirty flag */ - dataset->shared->cache.contig.sieve_dirty = FALSE; - } /* end if */ - dataset->shared->cache.contig.sieve_buf = (unsigned char *)H5FL_BLK_FREE(sieve_buf,dataset->shared->cache.contig.sieve_buf); } /* end if */ @@ -1522,19 +1513,31 @@ H5D_close(H5D_t *dataset) break; case H5D_CHUNKED: + /* Check for skip list for iterating over chunks during I/O to close */ + if(dataset->shared->cache.chunk.sel_chunks) { + HDassert(H5SL_count(dataset->shared->cache.chunk.sel_chunks) == 0); + H5SL_close(dataset->shared->cache.chunk.sel_chunks); + dataset->shared->cache.chunk.sel_chunks = NULL; + } /* end if */ + + /* Check for cached single chunk dataspace */ + if(dataset->shared->cache.chunk.single_space) { + (void)H5S_close(dataset->shared->cache.chunk.single_space); + dataset->shared->cache.chunk.single_space = NULL; + } /* end if */ + + /* Check for cached single element chunk info */ + if(dataset->shared->cache.chunk.single_chunk_info) { + (void)H5FL_FREE(H5D_chunk_info_t, dataset->shared->cache.chunk.single_chunk_info); + dataset->shared->cache.chunk.single_chunk_info = NULL; + } /* end if */ + /* Flush and destroy chunks in the cache */ - if(H5D_istore_dest(dataset,H5AC_dxpl_id) < 0) + if(H5D_istore_dest(dataset, H5AC_dxpl_id) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTRELEASE, FAIL, "unable to destroy chunk cache") break; case H5D_COMPACT: - /* Update header message of layout for compact dataset. */ - if(dataset->shared->layout.u.compact.dirty) { - if(H5O_msg_write(&(dataset->oloc), H5O_LAYOUT_ID, 0, H5O_UPDATE_TIME, &(dataset->shared->layout), H5AC_dxpl_id) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTRELEASE, FAIL, "unable to update layout message") - dataset->shared->layout.u.compact.dirty = FALSE; - } /* end if */ - /* Free the buffer for the raw data for compact datasets */ dataset->shared->layout.u.compact.buf = H5MM_xfree(dataset->shared->layout.u.compact.buf); break; @@ -1716,7 +1719,7 @@ H5D_get_file(const H5D_t *dset) */ herr_t H5D_alloc_storage(H5F_t *f, hid_t dxpl_id, H5D_t *dset/*in,out*/, H5D_time_alloc_t time_alloc, - hbool_t update_time, hbool_t full_overwrite) + hbool_t full_overwrite) { struct H5O_layout_t *layout; /* The dataset's layout information */ hbool_t must_init_space = FALSE; /* Flag to indicate that space should be initialized */ @@ -1771,7 +1774,7 @@ H5D_alloc_storage(H5F_t *f, hid_t dxpl_id, H5D_t *dset/*in,out*/, H5D_time_alloc */ if(dset->shared->dcpl_cache.fill.alloc_time == H5D_ALLOC_TIME_EARLY && time_alloc == H5D_ALLOC_EXTEND) - must_init_space = 1; + must_init_space = TRUE; break; case H5D_COMPACT: @@ -1833,12 +1836,15 @@ H5D_alloc_storage(H5F_t *f, hid_t dxpl_id, H5D_t *dset/*in,out*/, H5D_time_alloc } /* end else */ } /* end if */ - /* Also update header message for layout with new address, if we - * set the address. (this is improves forward compatibility). + /* If we set the address (and aren't in the middle of creating the + * dataset), mark the layout header message for later writing to + * the file. (this improves forward compatibility). + */ + /* (The layout message is already in the dataset's object header, this + * operation just sets the address and makes it constant) */ if(time_alloc != H5D_ALLOC_CREATE && addr_set) - if(H5O_msg_write(&dset->oloc, H5O_LAYOUT_ID, H5O_MSG_FLAG_CONSTANT, update_time, &dset->shared->layout, dxpl_id) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update layout message") + dset->shared->layout_dirty = TRUE; } /* end if */ done: @@ -2171,7 +2177,7 @@ H5D_vlen_get_buf_size(void UNUSED *elem, hid_t type_id, unsigned UNUSED ndim, co HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't resize tbuf") /* Select point to read in */ - if(H5Sselect_elements(vlen_bufsize->fspace_id, H5S_SELECT_SET, (size_t)1, (const hsize_t **)point) < 0) + if(H5Sselect_elements(vlen_bufsize->fspace_id, H5S_SELECT_SET, (size_t)1, point) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "can't select point") /* Read in the point (with the custom VL memory allocator) */ @@ -2309,7 +2315,7 @@ H5D_set_extent(H5D_t *dset, const hsize_t *size, hid_t dxpl_id) /* Allocate space for the new parts of the dataset, if appropriate */ if(expand && dset->shared->dcpl_cache.fill.alloc_time == H5D_ALLOC_TIME_EARLY) - if(H5D_alloc_storage(dset->oloc.file, dxpl_id, dset, H5D_ALLOC_EXTEND, TRUE, FALSE) < 0) + if(H5D_alloc_storage(dset->oloc.file, dxpl_id, dset, H5D_ALLOC_EXTEND, FALSE) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize dataset storage") @@ -2349,7 +2355,7 @@ done: /*------------------------------------------------------------------------- - * Function: H5D_flush_cb + * Function: H5D_flush_real * * Purpose: Flush any dataset information cached in memory * @@ -2357,69 +2363,132 @@ done: * Failure: Negative * * Programmer: Quincey Koziol - * November 8, 2007 + * December 6, 2007 * *------------------------------------------------------------------------- */ -static int -H5D_flush_cb(void *_dataset, hid_t UNUSED id, void *_udata) +static herr_t +H5D_flush_real(H5D_t *dataset, hid_t dxpl_id, unsigned flags) { - H5D_t *dataset = (H5D_t *)_dataset; /* Dataset pointer */ - H5D_flush_ud_t *udata = (H5D_flush_ud_t *)_udata; /* User data for callback */ - int ret_value = H5_ITER_CONT; /* Return value */ + H5O_t *oh = NULL; /* Pointer to dataset's object header */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5D_flush_cb) + FUNC_ENTER_NOAPI_NOINIT(H5D_flush_real) /* Check args */ HDassert(dataset); - /* Check for dataset in same file */ - if(udata->f == dataset->oloc.file) { + /* Check for metadata changes that will require updating the object's modification time */ + if(dataset->shared->layout_dirty || dataset->shared->space_dirty) { + unsigned update_flags = H5O_UPDATE_TIME; /* Modification time flag */ + + /* Get a pointer to the dataset's object header */ + if((oh = H5O_protect(&dataset->oloc, dxpl_id)) == NULL) + HGOTO_ERROR(H5E_DATASET, H5E_CANTPROTECT, FAIL, "unable to protect dataset object header") + + /* Update the layout on disk, if it's been changed */ + if(dataset->shared->layout_dirty) { + if(H5O_msg_write_oh(dataset->oloc.file, dxpl_id, oh, H5O_LAYOUT_ID, H5O_MSG_FLAG_CONSTANT, update_flags, &dataset->shared->layout) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to update layout message") + dataset->shared->layout_dirty = FALSE; + + /* Reset the "update the modification time" flag, so we only do it once */ + update_flags = 0; + } /* end if */ + /* Update the dataspace on disk, if it's been changed */ if(dataset->shared->space_dirty) { - if(H5S_write(&(dataset->oloc), dataset->shared->space, TRUE, udata->dxpl_id) < 0) + if(H5S_write(dataset->oloc.file, dxpl_id, oh, update_flags, dataset->shared->space) < 0) HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to update file with new dataspace") dataset->shared->space_dirty = FALSE; + + /* Reset the "update the modification time" flag, so we only do it once */ + update_flags = 0; } /* end if */ - /* Flush the raw data buffer, if we have a dirty one */ - if(dataset->shared->cache.contig.sieve_buf && dataset->shared->cache.contig.sieve_dirty) { - HDassert(dataset->shared->layout.type != H5D_COMPACT); /* We should never have a sieve buffer for compact storage */ + /* _Somebody_ should have update the modification time! */ + HDassert(update_flags == 0); + } /* end if */ - /* Write dirty data sieve buffer to file */ - if(H5F_block_write(udata->f, H5FD_MEM_DRAW, dataset->shared->cache.contig.sieve_loc, - dataset->shared->cache.contig.sieve_size, udata->dxpl_id, dataset->shared->cache.contig.sieve_buf) < 0) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed") + /* Flush the raw data buffer, if we have a dirty one */ + if(dataset->shared->cache.contig.sieve_buf && dataset->shared->cache.contig.sieve_dirty) { + HDassert(dataset->shared->layout.type != H5D_COMPACT); /* We should never have a sieve buffer for compact storage */ - /* Reset sieve buffer dirty flag */ - dataset->shared->cache.contig.sieve_dirty = FALSE; - } /* end if */ + /* Write dirty data sieve buffer to file */ + if(H5F_block_write(dataset->oloc.file, H5FD_MEM_DRAW, dataset->shared->cache.contig.sieve_loc, + dataset->shared->cache.contig.sieve_size, dxpl_id, dataset->shared->cache.contig.sieve_buf) < 0) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed") - /* Flush cached information for each kind of dataset */ - switch(dataset->shared->layout.type) { - case H5D_CONTIGUOUS: - break; + /* Reset sieve buffer dirty flag */ + dataset->shared->cache.contig.sieve_dirty = FALSE; + } /* end if */ - case H5D_CHUNKED: - /* Flush the raw data cache */ - if(H5D_istore_flush(dataset, udata->dxpl_id, udata->flags & H5F_FLUSH_INVALIDATE) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush raw data cache") - break; + /* Flush cached information for each kind of dataset */ + switch(dataset->shared->layout.type) { + case H5D_CONTIGUOUS: + break; - case H5D_COMPACT: - if(dataset->shared->layout.u.compact.dirty) { - if(H5O_msg_write(&(dataset->oloc), H5O_LAYOUT_ID, 0, H5O_UPDATE_TIME, &(dataset->shared->layout), udata->dxpl_id) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to update layout message") - dataset->shared->layout.u.compact.dirty = FALSE; - } /* end if */ - break; + case H5D_CHUNKED: + /* Flush the raw data cache */ + if(H5D_istore_flush(dataset, dxpl_id, flags & H5F_FLUSH_INVALIDATE) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush raw data cache") + break; - default: - HDassert("not implemented yet" && 0); + case H5D_COMPACT: + if(dataset->shared->layout.u.compact.dirty) { + if(H5O_msg_write(&(dataset->oloc), H5O_LAYOUT_ID, 0, H5O_UPDATE_TIME, &(dataset->shared->layout), dxpl_id) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to update layout message") + dataset->shared->layout.u.compact.dirty = FALSE; + } /* end if */ + break; + + default: + HDassert("not implemented yet" && 0); #ifdef NDEBUG - HGOTO_ERROR(H5E_IO, H5E_UNSUPPORTED, FAIL, "unsupported storage layout") + HGOTO_ERROR(H5E_IO, H5E_UNSUPPORTED, FAIL, "unsupported storage layout") #endif /* NDEBUG */ - } /* end switch */ /*lint !e788 All appropriate cases are covered */ + } /* end switch */ /*lint !e788 All appropriate cases are covered */ + +done: + /* Release pointer to object header */ + if(oh != NULL) + if(H5O_unprotect(&(dataset->oloc), oh) < 0) + HDONE_ERROR(H5E_DATASET, H5E_CANTUNPROTECT, FAIL, "unable to unprotect dataset object header") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5D_flush_real() */ + + +/*------------------------------------------------------------------------- + * Function: H5D_flush_cb + * + * Purpose: Flush any dataset information cached in memory + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * November 8, 2007 + * + *------------------------------------------------------------------------- + */ +static int +H5D_flush_cb(void *_dataset, hid_t UNUSED id, void *_udata) +{ + H5D_t *dataset = (H5D_t *)_dataset; /* Dataset pointer */ + H5D_flush_ud_t *udata = (H5D_flush_ud_t *)_udata; /* User data for callback */ + int ret_value = H5_ITER_CONT; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5D_flush_cb) + + /* Check args */ + HDassert(dataset); + + /* Check for dataset in same file */ + if(udata->f == dataset->oloc.file) { + /* Flush the dataset's information */ + if(H5D_flush_real(dataset, udata->dxpl_id, udata->flags) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, H5_ITER_ERROR, "unable to flush cached dataset info") } /* end if */ done: @@ -2460,7 +2529,6 @@ H5D_flush(const H5F_t *f, hid_t dxpl_id, unsigned flags) H5I_search(H5I_DATASET, H5D_flush_cb, &udata); done: - FUNC_LEAVE_NOAPI(ret_value) } /* end H5D_flush() */ diff --git a/src/H5Dio.c b/src/H5Dio.c index 78140e0..cef34ee 100644 --- a/src/H5Dio.c +++ b/src/H5Dio.c @@ -45,6 +45,12 @@ #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 */ /******************/ @@ -120,7 +126,7 @@ static herr_t H5D_chunk_mem_cb(void *elem, hid_t type_id, unsigned ndims, H5FL_BLK_DEFINE(type_conv); /* Declare a free list to manage the H5D_chunk_info_t struct */ -H5FL_DEFINE_STATIC(H5D_chunk_info_t); +H5FL_DEFINE(H5D_chunk_info_t); /* Declare a free list to manage sequences of size_t */ H5FL_SEQ_DEFINE_STATIC(size_t); @@ -161,7 +167,7 @@ H5D_get_dxpl_cache_real(hid_t dxpl_id, H5D_dxpl_cache_t *cache) assert(cache); /* Get the dataset transfer property list */ - if (NULL == (dx_plist = 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 transfer property list") /* Get maximum temporary buffer size */ @@ -302,12 +308,12 @@ H5Dread(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id, plist_id, buf); /* check arguments */ - if(NULL == (dset = H5I_object_verify(dset_id, H5I_DATASET))) + 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 = H5I_object_verify(mem_space_id, H5I_DATASPACE))) + 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 */ @@ -315,7 +321,7 @@ H5Dread(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id, HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "selection+offset not within extent") } /* end if */ if(H5S_ALL != file_space_id) { - if(NULL == (file_space = H5I_object_verify(file_space_id, H5I_DATASPACE))) + 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 */ @@ -394,12 +400,12 @@ H5Dwrite(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id, plist_id, buf); /* check arguments */ - if(NULL == (dset = H5I_object_verify(dset_id, H5I_DATASET))) + 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 = H5I_object_verify(mem_space_id, H5I_DATASPACE))) + 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 */ @@ -407,7 +413,7 @@ H5Dwrite(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id, 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 = H5I_object_verify(file_space_id, H5I_DATASPACE))) + 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 */ @@ -475,7 +481,7 @@ H5D_read(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space, HDassert(dataset && dataset->oloc.file); /* Get memory datatype */ - if(NULL == (mem_type = H5I_object_verify(mem_type_id, H5I_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) @@ -617,7 +623,7 @@ H5D_write(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space, HDassert(dataset && dataset->oloc.file); /* Get the memory datatype */ - if(NULL == (mem_type = H5I_object_verify(mem_type_id, H5I_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. */ @@ -701,7 +707,7 @@ H5D_write(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space, full_overwrite = (hsize_t)file_nelmts==nelmts ? TRUE : FALSE; /* Allocate storage */ - if(H5D_alloc_storage(dataset->oloc.file, dxpl_id, dataset, H5D_ALLOC_WRITE, TRUE, full_overwrite) < 0) + 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 */ @@ -918,15 +924,15 @@ H5D_contig_read(H5D_io_info_t *io_info, hsize_t nelmts, } else { need_bkg = H5T_BKG_NO; /*never needed even if app says yes*/ } /* end else */ - if (NULL==(tconv_buf=dxpl_cache->tconv_buf)) { + if(NULL == (tconv_buf = (uint8_t *)dxpl_cache->tconv_buf)) { /* Allocate temporary buffer */ - if((tconv_buf=H5FL_BLK_MALLOC(type_conv,target_size))==NULL) + 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=dxpl_cache->bkgr_buf)) { + 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((bkg_buf=H5FL_BLK_CALLOC(type_conv,(request_nelmts*dst_type_size)))==NULL) + 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 */ @@ -1035,9 +1041,9 @@ done: } /* end if */ if (tconv_buf && NULL==dxpl_cache->tconv_buf) - H5FL_BLK_FREE(type_conv,tconv_buf); + (void)H5FL_BLK_FREE(type_conv,tconv_buf); if (bkg_buf && NULL==dxpl_cache->bkgr_buf) - H5FL_BLK_FREE(type_conv,bkg_buf); + (void)H5FL_BLK_FREE(type_conv,bkg_buf); FUNC_LEAVE_NOAPI(ret_value) } /* end H5D_contig_read() */ @@ -1196,15 +1202,15 @@ H5D_contig_write(H5D_io_info_t *io_info, hsize_t nelmts, } else { need_bkg = H5T_BKG_NO; /*never needed even if app says yes*/ } /* end else */ - if (NULL==(tconv_buf=dxpl_cache->tconv_buf)) { + if(NULL == (tconv_buf = (uint8_t *)dxpl_cache->tconv_buf)) { /* Allocate temporary buffer */ - if((tconv_buf=H5FL_BLK_MALLOC(type_conv,target_size))==NULL) + 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=dxpl_cache->bkgr_buf)) { + 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((bkg_buf=H5FL_BLK_MALLOC(type_conv,(request_nelmts*dst_type_size)))==NULL) + 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 */ @@ -1303,9 +1309,9 @@ done: } /* end if */ if (tconv_buf && NULL==dxpl_cache->tconv_buf) - H5FL_BLK_FREE(type_conv,tconv_buf); + (void)H5FL_BLK_FREE(type_conv,tconv_buf); if (bkg_buf && NULL==dxpl_cache->bkgr_buf) - H5FL_BLK_FREE(type_conv,bkg_buf); + (void)H5FL_BLK_FREE(type_conv,bkg_buf); FUNC_LEAVE_NOAPI(ret_value) } /* end H5D_contig_write() */ @@ -1378,6 +1384,11 @@ H5D_chunk_read(H5D_io_info_t *io_info, hsize_t nelmts, /* 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. @@ -1408,13 +1419,13 @@ H5D_chunk_read(H5D_io_info_t *io_info, hsize_t nelmts, else {/* sequential or independent read */ #endif /* Get first node in chunk skip list */ - chunk_node = H5SL_first(fm.fsel); + 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 = H5SL_item(chunk_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; @@ -1430,19 +1441,19 @@ H5D_chunk_read(H5D_io_info_t *io_info, hsize_t nelmts, /* Perform the actual read operation */ if((io_info->ops.read)(io_info, chunk_info->chunk_points, - H5T_get_size(dataset->shared->type), chunk_info->fspace, + 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 * H5T_get_size(dataset->shared->type); + 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 = H5SL_next(chunk_node); + chunk_node = H5D_CHUNK_GET_NEXT_NODE(fm, chunk_node); } /* end while */ #ifdef H5_HAVE_PARALLEL } @@ -1451,7 +1462,7 @@ H5D_chunk_read(H5D_io_info_t *io_info, hsize_t nelmts, #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_nbytes += nelmts * src_type_size; io_info->stats->stats[1].read_ncalls++; #endif @@ -1465,10 +1476,7 @@ H5D_chunk_read(H5D_io_info_t *io_info, hsize_t nelmts, 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); + /* 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 @@ -1505,29 +1513,29 @@ H5D_chunk_read(H5D_io_info_t *io_info, hsize_t nelmts, } else { need_bkg = H5T_BKG_NO; /*never needed even if app says yes*/ } /* end else */ - if (NULL==(tconv_buf=dxpl_cache->tconv_buf)) { + if(NULL == (tconv_buf = (uint8_t *)dxpl_cache->tconv_buf)) { /* Allocate temporary buffer */ - if((tconv_buf=H5FL_BLK_MALLOC(type_conv,target_size))==NULL) + 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=dxpl_cache->bkgr_buf)) { + 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((bkg_buf=H5FL_BLK_CALLOC(type_conv,(request_nelmts*dst_type_size)))==NULL) + 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=H5SL_first(fm.fsel); + 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=H5SL_item(chunk_node); + 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) @@ -1647,7 +1655,7 @@ H5D_chunk_read(H5D_io_info_t *io_info, hsize_t nelmts, /* Release the cache lock on the chunk. */ if(chunk) { - accessed_bytes = chunk_info->chunk_points * H5T_get_size(dataset->shared->type); + 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 */ @@ -1670,7 +1678,7 @@ H5D_chunk_read(H5D_io_info_t *io_info, hsize_t nelmts, } /* end if */ /* Get the next chunk node in the skip list */ - chunk_node=H5SL_next(chunk_node); + chunk_node = H5D_CHUNK_GET_NEXT_NODE(fm, chunk_node); } /* end while */ done: @@ -1689,9 +1697,9 @@ done: } /* end if */ if(tconv_buf && NULL == dxpl_cache->tconv_buf) - H5FL_BLK_FREE(type_conv, tconv_buf); + (void)H5FL_BLK_FREE(type_conv, tconv_buf); if(bkg_buf && NULL == dxpl_cache->bkgr_buf) - H5FL_BLK_FREE(type_conv, bkg_buf); + (void)H5FL_BLK_FREE(type_conv, bkg_buf); /* Release chunk mapping information */ if(H5D_destroy_chunk_map(&fm) < 0) @@ -1779,6 +1787,11 @@ H5D_chunk_write(H5D_io_info_t *io_info, hsize_t nelmts, } /* 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. @@ -1804,13 +1817,13 @@ H5D_chunk_write(H5D_io_info_t *io_info, hsize_t nelmts, else {/* sequential or independent write */ #endif /* H5_HAVE_PARALLEL */ /* Get first node in chunk skip list */ - chunk_node=H5SL_first(fm.fsel); + 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=H5SL_item(chunk_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; @@ -1821,7 +1834,7 @@ H5D_chunk_write(H5D_io_info_t *io_info, hsize_t nelmts, chunk_addr = H5D_istore_get_addr(io_info, &udata); if(H5D_istore_if_load(io_info, chunk_addr)) { - accessed_bytes = chunk_info->chunk_points * H5T_get_size(dataset->shared->type); + accessed_bytes = chunk_info->chunk_points * dst_type_size; if(accessed_bytes != dataset->shared->layout.u.chunk.size) relax = FALSE; @@ -1832,7 +1845,7 @@ H5D_chunk_write(H5D_io_info_t *io_info, hsize_t nelmts, /* Perform the actual read operation */ if((io_info->ops.write)(io_info, chunk_info->chunk_points, - H5T_get_size(dataset->shared->type), chunk_info->fspace, + dst_type_size, chunk_info->fspace, chunk_info->mspace, chunk_addr, chunk, buf) < 0) HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, " chunked write failed") @@ -1844,7 +1857,7 @@ H5D_chunk_write(H5D_io_info_t *io_info, hsize_t nelmts, relax = TRUE; /* Advance to next chunk in list */ - chunk_node = H5SL_next(chunk_node); + chunk_node = H5D_CHUNK_GET_NEXT_NODE(fm, chunk_node); } /* end while */ #ifdef H5_HAVE_PARALLEL } @@ -1852,7 +1865,7 @@ H5D_chunk_write(H5D_io_info_t *io_info, hsize_t nelmts, #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_nbytes += nelmts * src_type_size; io_info->stats->stats[0].write_ncalls++; #endif @@ -1866,10 +1879,7 @@ H5D_chunk_write(H5D_io_info_t *io_info, hsize_t nelmts, 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); + /* 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 @@ -1910,29 +1920,29 @@ H5D_chunk_write(H5D_io_info_t *io_info, hsize_t nelmts, } else { need_bkg = H5T_BKG_NO; /*never needed even if app says yes*/ } /* end else */ - if (NULL==(tconv_buf=dxpl_cache->tconv_buf)) { + if(NULL == (tconv_buf = (uint8_t *)dxpl_cache->tconv_buf)) { /* Allocate temporary buffer */ - if((tconv_buf=H5FL_BLK_MALLOC(type_conv,target_size))==NULL) + 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=dxpl_cache->bkgr_buf)) { + 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((bkg_buf=H5FL_BLK_MALLOC(type_conv,(request_nelmts*dst_type_size)))==NULL) + if(NULL == (bkg_buf = H5FL_BLK_MALLOC(type_conv, (request_nelmts * dst_type_size)))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for background conversion") } /* end if */ /* Loop over all the chunks, performing I/O on each */ /* Get first node in chunk skip list */ - chunk_node=H5SL_first(fm.fsel); + 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=H5SL_item(chunk_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) @@ -1954,11 +1964,11 @@ H5D_chunk_write(H5D_io_info_t *io_info, hsize_t nelmts, chunk_addr = H5D_istore_get_addr(io_info, &udata); if(H5D_istore_if_load(io_info, chunk_addr)) { - accessed_bytes = chunk_info->chunk_points * H5T_get_size(dataset->shared->type); + 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)*H5T_get_size(mem_type); + accessed_bytes = H5S_GET_SELECT_NPOINTS(chunk_info->mspace) * src_type_size; if(accessed_bytes != dataset->shared->layout.u.chunk.size) relax = FALSE; } @@ -2056,7 +2066,7 @@ H5D_chunk_write(H5D_io_info_t *io_info, hsize_t nelmts, /* Release the cache lock on the chunk. */ if(chunk) { - accessed_bytes = chunk_info->chunk_points * H5T_get_size(dataset->shared->type); + 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 */ @@ -2080,7 +2090,7 @@ H5D_chunk_write(H5D_io_info_t *io_info, hsize_t nelmts, } /* end if */ /* Get the next chunk node in the skip list */ - chunk_node=H5SL_next(chunk_node); + chunk_node = H5D_CHUNK_GET_NEXT_NODE(fm, chunk_node); } /* end while */ done: @@ -2099,9 +2109,9 @@ done: } /* end if */ if (tconv_buf && NULL==dxpl_cache->tconv_buf) - H5FL_BLK_FREE(type_conv,tconv_buf); + (void)H5FL_BLK_FREE(type_conv,tconv_buf); if (bkg_buf && NULL==dxpl_cache->bkgr_buf) - H5FL_BLK_FREE(type_conv,bkg_buf); + (void)H5FL_BLK_FREE(type_conv,bkg_buf); /* Release chunk mapping information */ if(H5D_destroy_chunk_map(&fm) < 0) @@ -2193,7 +2203,7 @@ H5D_compound_opt_read(size_t nelmts, const H5S_t *space, off=_off; } /* end else */ - if (NULL == (src = H5I_object(src_id)) || NULL == (dst = H5I_object(dst_id))) + 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); @@ -2299,7 +2309,7 @@ H5D_compound_opt_write(size_t nelmts, hid_t src_id, hid_t dst_id, void *data_buf assert (data_buf); assert (nelmts>0); - if (NULL == (src = H5I_object(src_id)) || NULL == (dst = H5I_object(dst_id))) + 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); @@ -2344,7 +2354,7 @@ H5D_create_chunk_map(H5D_chunk_map_t *fm, const H5D_io_info_t *io_info, 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 */ - hbool_t file_space_normalized = FALSE; /* File dataspace was normalized */ + 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 */ @@ -2379,9 +2389,8 @@ H5D_create_chunk_map(H5D_chunk_map_t *fm, const H5D_io_info_t *io_info, * speed up hyperslab calculations by removing the extra checks and/or * additions involving the offset and the hyperslab selection -QAK) */ - if(H5S_hyper_normalize_offset((H5S_t *)file_space, old_offset) < 0) + 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") - file_space_normalized = TRUE; /* Decide the number of chunks in each dimension*/ for(u=0; u<f_ndims; u++) { @@ -2410,10 +2419,6 @@ H5D_create_chunk_map(H5D_chunk_map_t *fm, const H5D_io_info_t *io_info, #endif /* H5_HAVE_PARALLEL */ - /* Initialize skip list for chunk selections */ - if((fm->fsel = H5SL_create(H5SL_TYPE_HSIZE, 0.5, (size_t)H5D_DEFAULT_SKIPLIST_HEIGHT))==NULL) - HGOTO_ERROR(H5E_DATASET,H5E_CANTCREATE,FAIL,"can't create skip list for chunk selections") - /* Initialize "last chunk" information */ fm->last_index = (hsize_t)-1; fm->last_chunk_info = NULL; @@ -2424,7 +2429,40 @@ H5D_create_chunk_map(H5D_chunk_map_t *fm, const H5D_io_info_t *io_info, /* Special case for only one element in selection */ /* (usually appending a record) */ - if(nelmts == 1) { + 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; @@ -2433,6 +2471,17 @@ H5D_create_chunk_map(H5D_chunk_map_t *fm, const H5D_io_info_t *io_info, 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") @@ -2452,12 +2501,12 @@ H5D_create_chunk_map(H5D_chunk_map_t *fm, const H5D_io_info_t *io_info, 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->fsel); + 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=H5SL_item(curr_node); + chunk_info = (H5D_chunk_info_t *)H5SL_item(curr_node); assert(chunk_info); /* Clean hyperslab span's "scratch" information */ @@ -2527,12 +2576,12 @@ H5D_create_chunk_map(H5D_chunk_map_t *fm, const H5D_io_info_t *io_info, /* 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->fsel); + 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=H5SL_item(curr_node); + chunk_info = (H5D_chunk_info_t *)H5SL_item(curr_node); assert(chunk_info); /* Clean hyperslab span's "scratch" information */ @@ -2590,7 +2639,7 @@ done: RETURNS No return value DESCRIPTION - Releases all the memory for a chunk info node. Called by H5SL_iterate + Releases all the memory for a chunk info node. Called by H5SL_free GLOBAL VARIABLES COMMENTS, BUGS, ASSUMPTIONS EXAMPLES @@ -2599,21 +2648,24 @@ done: 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; + H5D_chunk_info_t *chunk_info = (H5D_chunk_info_t *)item; FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_free_chunk_info) - assert(chunk_info); + HDassert(chunk_info); - /* Close the chunk's file dataspace */ - (void)H5S_close(chunk_info->fspace); + /* 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); + H5FL_FREE(H5D_chunk_info_t, chunk_info); FUNC_LEAVE_NOAPI(0); } /* H5D_free_chunk_info() */ @@ -2638,14 +2690,23 @@ H5D_destroy_chunk_map(const H5D_chunk_map_t *fm) FUNC_ENTER_NOAPI_NOINIT(H5D_destroy_chunk_map) - /* Free the chunk info skip list */ - if(fm->fsel) { - if(H5SL_count(fm->fsel)>0) - if(H5SL_iterate(fm->fsel,H5D_free_chunk_info,NULL) < 0) - HGOTO_ERROR(H5E_PLIST,H5E_CANTNEXT,FAIL,"can't iterate over chunks") + /* 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); - H5SL_close(fm->fsel); + /* 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) @@ -2680,8 +2741,7 @@ H5D_create_chunk_map_single(H5D_chunk_map_t *fm, const H5D_io_info_t #endif /* H5_HAVE_PARALLEL */ *io_info) { - H5S_t *tmp_fchunk = NULL; /* Temporary file dataspace */ - H5D_chunk_info_t *new_chunk_info = NULL; /* chunk information to insert into skip list */ + 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 */ @@ -2696,62 +2756,49 @@ H5D_create_chunk_map_single(H5D_chunk_map_t *fm, const H5D_io_info_t 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") - /* Allocate the file & memory chunk information */ - if(NULL == (new_chunk_info = H5FL_MALLOC(H5D_chunk_info_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate chunk info") - new_chunk_info->chunk_points = 1; + /* 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]); - new_chunk_info->coords[u] = (sel_start[u] / fm->layout->u.chunk.dim[u]) * fm->layout->u.chunk.dim[u]; + chunk_info->coords[u] = (sel_start[u] / fm->layout->u.chunk.dim[u]) * fm->layout->u.chunk.dim[u]; } /* end for */ - new_chunk_info->coords[fm->f_ndims] = 0; + chunk_info->coords[fm->f_ndims] = 0; /* Calculate the index of this chunk */ - if(H5V_chunk_index(fm->f_ndims, new_chunk_info->coords, fm->layout->u.chunk.dim, fm->down_chunks, &new_chunk_info->index) < 0) + 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") - /* Create chunk dataspace for selection operations (copy file space) */ - if((tmp_fchunk = H5S_copy(fm->file_space, FALSE, FALSE)) == NULL) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy memory space") - - /* Resize chunk's dataspace dimensions to size of chunk */ - if(H5S_set_extent_real(tmp_fchunk, fm->chunk_dim) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't adjust chunk dimensions") + /* 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(tmp_fchunk, new_chunk_info->coords) < 0) + 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[new_chunk_info->index] = TRUE; + fm->select_chunk[chunk_info->index] = TRUE; #endif /* H5_HAVE_PARALLEL */ - /* Set the file chunk dataspace */ - new_chunk_info->fspace = tmp_fchunk; + /* 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) */ - new_chunk_info->mspace = (H5S_t *)fm->mem_space; - - /* Indicate that the chunk's memory space is shared */ - new_chunk_info->mspace_shared = 1; + chunk_info->mspace = (H5S_t *)fm->mem_space; - /* Insert the new chunk into the skip list */ - if(H5SL_insert(fm->fsel, new_chunk_info, &new_chunk_info->index) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert chunk into skip list") + /* Indicate that the chunk's memory dataspace is shared */ + chunk_info->mspace_shared = TRUE; done: - if(ret_value < 0) { - if(new_chunk_info) - (void)H5D_free_chunk_info(new_chunk_info, NULL, NULL); - if(tmp_fchunk) - (void)H5S_close(tmp_fchunk); - } /* end if */ - FUNC_LEAVE_NOAPI(ret_value) } /* end H5D_create_chunk_map_single() */ @@ -2868,11 +2915,12 @@ H5D_create_chunk_file_map_hyper(H5D_chunk_map_t *fm, const H5D_io_info_t #endif /* H5_HAVE_PARALLEL */ /* Set the file chunk dataspace */ - new_chunk_info->fspace=tmp_fchunk; + 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=0; + new_chunk_info->mspace_shared = FALSE; /* Copy the chunk's coordinates */ for(u=0; u<fm->f_ndims; u++) @@ -2880,7 +2928,7 @@ H5D_create_chunk_file_map_hyper(H5D_chunk_map_t *fm, const H5D_io_info_t new_chunk_info->coords[fm->f_ndims]=0; /* Insert the new chunk into the skip list */ - if(H5SL_insert(fm->fsel,new_chunk_info,&new_chunk_info->index) < 0) { + 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 */ @@ -2971,14 +3019,14 @@ H5D_create_chunk_mem_map_hyper(const H5D_chunk_map_t *fm) assert(fm->f_ndims>0); /* Check for all I/O going to a single chunk */ - if(H5SL_count(fm->fsel)==1) { + 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->fsel); + curr_node=H5SL_first(fm->sel_chunks); /* Get pointer to chunk's information */ - chunk_info=H5SL_item(curr_node); + chunk_info = (H5D_chunk_info_t *)H5SL_item(curr_node); assert(chunk_info); /* Just point at the memory dataspace & selection */ @@ -2986,7 +3034,7 @@ H5D_create_chunk_mem_map_hyper(const H5D_chunk_map_t *fm) chunk_info->mspace=(H5S_t *)fm->mem_space; /* Indicate that the chunk's memory space is shared */ - chunk_info->mspace_shared=1; + chunk_info->mspace_shared = TRUE; } /* end if */ else { /* Get bounding box for file selection */ @@ -3006,12 +3054,12 @@ H5D_create_chunk_mem_map_hyper(const H5D_chunk_map_t *fm) } /* end for */ /* Iterate over each chunk in the chunk list */ - curr_node=H5SL_first(fm->fsel); + 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=H5SL_item(curr_node); + chunk_info = (H5D_chunk_info_t *)H5SL_item(curr_node); assert(chunk_info); /* Copy the information */ @@ -3089,7 +3137,7 @@ H5D_chunk_file_cb(void UNUSED *elem, hid_t UNUSED type_id, unsigned ndims, const * find the chunk in the skip list. */ /* Get the chunk node from the skip list */ - if((chunk_info=H5SL_search(fm->fsel,&chunk_index))==NULL) { + 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 */ @@ -3115,11 +3163,12 @@ H5D_chunk_file_cb(void UNUSED *elem, hid_t UNUSED type_id, unsigned ndims, const } /* end if */ /* Set the file chunk dataspace */ - chunk_info->fspace=fspace; + chunk_info->fspace = fspace; + chunk_info->fspace_shared = FALSE; /* Set the memory chunk dataspace */ chunk_info->mspace=NULL; - chunk_info->mspace_shared=0; + chunk_info->mspace_shared = FALSE; /* Set the number of selected elements in chunk to zero */ chunk_info->chunk_points=0; @@ -3132,7 +3181,7 @@ H5D_chunk_file_cb(void UNUSED *elem, hid_t UNUSED type_id, unsigned ndims, const chunk_info->coords[fm->f_ndims]=0; /* Insert the new chunk into the skip list */ - if(H5SL_insert(fm->fsel,chunk_info,&chunk_info->index) < 0) { + 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 */ @@ -3148,7 +3197,7 @@ H5D_chunk_file_cb(void UNUSED *elem, hid_t UNUSED type_id, unsigned ndims, const 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, (const hsize_t **)coords_in_chunk) < 0) + 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 */ @@ -3200,8 +3249,8 @@ H5D_chunk_mem_cb(void UNUSED *elem, hid_t UNUSED type_id, unsigned ndims, const * find the chunk in the skip list. */ /* Get the chunk node from the skip list */ - if((chunk_info=H5SL_search(fm->fsel,&chunk_index))==NULL) - HGOTO_ERROR(H5E_DATASPACE,H5E_NOTFOUND,FAIL,"can't locate chunk in 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) { @@ -3221,7 +3270,7 @@ H5D_chunk_mem_cb(void UNUSED *elem, hid_t UNUSED type_id, unsigned ndims, const /* 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, (const hsize_t **)coords_in_mem) < 0) + 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 { @@ -3331,7 +3380,7 @@ H5D_ioinfo_init(H5D_t *dset, const H5D_dxpl_cache_t *dxpl_cache, hid_t dxpl_id, H5P_genplist_t *dx_plist; /* Data transer property list */ /* Get the dataset transfer property list */ - if (NULL == (dx_plist = 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 */ @@ -3395,7 +3444,7 @@ H5D_ioinfo_term(H5D_io_info_t *io_info) H5P_genplist_t *dx_plist; /* Data transer property list */ /* Get the dataset transfer property list */ - if (NULL == (dx_plist = H5I_object(io_info->dxpl_id))) + 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 */ @@ -3409,3 +3458,4 @@ done: } /* end H5D_ioinfo_term() */ #endif + diff --git a/src/H5Distore.c b/src/H5Distore.c index 8a3c1b0..3b8fba7 100644 --- a/src/H5Distore.c +++ b/src/H5Distore.c @@ -540,22 +540,20 @@ H5D_istore_cmp3(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, void *_lt_key, void *_uda /* slightly odd way the library initializes the right-most node in the */ /* indexed storage B-tree... */ /* (Dump the B-tree with h5debug to look at it) -QAK */ - if(udata->mesg->u.chunk.ndims==2) { - if(udata->key.offset[0]>rt_key->offset[0]) - ret_value=1; - else if(udata->key.offset[0]==rt_key->offset[0] && - udata->key.offset[1]>=rt_key->offset[1]) - ret_value=1; - else if(udata->key.offset[0]<lt_key->offset[0]) - ret_value=(-1); + if(udata->mesg->u.chunk.ndims == 2) { + if(udata->offset[0] > rt_key->offset[0]) + ret_value = 1; + else if(udata->offset[0] == rt_key->offset[0] && + udata->offset[1] >= rt_key->offset[1]) + ret_value = 1; + else if(udata->offset[0] < lt_key->offset[0]) + ret_value = (-1); } /* end if */ else { - if (H5V_vector_ge_u(udata->mesg->u.chunk.ndims, udata->key.offset, - rt_key->offset)) + if(H5V_vector_ge_u(udata->mesg->u.chunk.ndims, udata->offset, rt_key->offset)) ret_value = 1; - else if (H5V_vector_lt_u(udata->mesg->u.chunk.ndims, udata->key.offset, - lt_key->offset)) - ret_value = -1; + else if(H5V_vector_lt_u(udata->mesg->u.chunk.ndims, udata->offset, lt_key->offset)) + ret_value = (-1); } /* end else */ FUNC_LEAVE_NOAPI(ret_value) @@ -602,9 +600,9 @@ H5D_istore_new_node(H5F_t *f, hid_t dxpl_id, H5B_ins_t op, HDassert(addr_p); /* Allocate new storage */ - HDassert(udata->common.key.nbytes > 0); - H5_CHECK_OVERFLOW(udata->common.key.nbytes ,size_t, hsize_t); - if(HADDR_UNDEF == (*addr_p = H5MF_alloc(f, H5FD_MEM_DRAW, dxpl_id, (hsize_t)udata->common.key.nbytes))) + HDassert(udata->nbytes > 0); + H5_CHECK_OVERFLOW(udata->nbytes, size_t, hsize_t); + if(HADDR_UNDEF == (*addr_p = H5MF_alloc(f, H5FD_MEM_DRAW, dxpl_id, (hsize_t)udata->nbytes))) HGOTO_ERROR(H5E_IO, H5E_CANTINIT, FAIL, "couldn't allocate new file storage") udata->addr = *addr_p; @@ -612,24 +610,24 @@ H5D_istore_new_node(H5F_t *f, hid_t dxpl_id, H5B_ins_t op, * The left key describes the storage of the UDATA chunk being * inserted into the tree. */ - lt_key->nbytes = udata->common.key.nbytes; - lt_key->filter_mask = udata->common.key.filter_mask; - for (u=0; u<udata->common.mesg->u.chunk.ndims; u++) - lt_key->offset[u] = udata->common.key.offset[u]; + lt_key->nbytes = udata->nbytes; + lt_key->filter_mask = udata->filter_mask; + for(u = 0; u < udata->common.mesg->u.chunk.ndims; u++) + lt_key->offset[u] = udata->common.offset[u]; /* * The right key might already be present. If not, then add a zero-width * chunk. */ - if (H5B_INS_LEFT != op) { + if(H5B_INS_LEFT != op) { rt_key->nbytes = 0; rt_key->filter_mask = 0; - for (u=0; u<udata->common.mesg->u.chunk.ndims; u++) { - HDassert(udata->common.key.offset[u]+udata->common.mesg->u.chunk.dim[u] > - udata->common.key.offset[u]); - rt_key->offset[u] = udata->common.key.offset[u] + udata->common.mesg->u.chunk.dim[u]; - } - } + for(u = 0; u < udata->common.mesg->u.chunk.ndims; u++) { + HDassert(udata->common.offset[u] + udata->common.mesg->u.chunk.dim[u] > + udata->common.offset[u]); + rt_key->offset[u] = udata->common.offset[u] + udata->common.mesg->u.chunk.dim[u]; + } /* end if */ + } /* end if */ done: FUNC_LEAVE_NOAPI(ret_value) @@ -680,16 +678,14 @@ H5D_istore_found(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, haddr_t addr, const void /* Is this *really* the requested chunk? */ for(u = 0; u < udata->common.mesg->u.chunk.ndims; u++) - if(udata->common.key.offset[u] >= lt_key->offset[u] + udata->common.mesg->u.chunk.dim[u]) + if(udata->common.offset[u] >= lt_key->offset[u] + udata->common.mesg->u.chunk.dim[u]) HGOTO_DONE(FAIL) /* Initialize return values */ + HDassert(lt_key->nbytes > 0); udata->addr = addr; - udata->common.key.nbytes = lt_key->nbytes; - udata->common.key.filter_mask = lt_key->filter_mask; - HDassert(lt_key->nbytes>0); - for(u = 0; u < udata->common.mesg->u.chunk.ndims; u++) - udata->common.key.offset[u] = lt_key->offset[u]; + udata->nbytes = lt_key->nbytes; + udata->filter_mask = lt_key->filter_mask; done: FUNC_LEAVE_NOAPI(ret_value) @@ -755,18 +751,18 @@ H5D_istore_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key, cmp = H5D_istore_cmp3(f, dxpl_id, lt_key, udata, rt_key); HDassert(cmp <= 0); - if (cmp < 0) { + if(cmp < 0) { /* Negative indices not supported yet */ HGOTO_ERROR(H5E_STORAGE, H5E_UNSUPPORTED, H5B_INS_ERROR, "internal error") - } else if (H5V_vector_eq_u (udata->common.mesg->u.chunk.ndims, - udata->common.key.offset, lt_key->offset) && - lt_key->nbytes>0) { + } else if(H5V_vector_eq_u(udata->common.mesg->u.chunk.ndims, + udata->common.offset, lt_key->offset) && + lt_key->nbytes > 0) { /* * Already exists. If the new size is not the same as the old size * then we should reallocate storage. */ - if (lt_key->nbytes != udata->common.key.nbytes) { + if(lt_key->nbytes != udata->nbytes) { /* Currently, the old chunk data is "thrown away" after the space is reallocated, * so avoid data copy in H5MF_realloc() call by just free'ing the space and * allocating new space. @@ -778,18 +774,18 @@ H5D_istore_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key, */ #ifdef OLD_WAY if(HADDR_UNDEF == (*new_node_p = H5MF_realloc(f, H5FD_MEM_DRAW, addr, - (hsize_t)lt_key->nbytes, (hsize_t)udata->common.key.nbytes))) + (hsize_t)lt_key->nbytes, (hsize_t)udata->nbytes))) HGOTO_ERROR(H5E_STORAGE, H5E_NOSPACE, H5B_INS_ERROR, "unable to reallocate chunk storage") #else /* OLD_WAY */ H5_CHECK_OVERFLOW( lt_key->nbytes ,size_t, hsize_t); if(H5MF_xfree(f, H5FD_MEM_DRAW, dxpl_id, addr, (hsize_t)lt_key->nbytes)<0) HGOTO_ERROR(H5E_STORAGE, H5E_CANTFREE, H5B_INS_ERROR, "unable to free chunk") - H5_CHECK_OVERFLOW(udata->common.key.nbytes ,size_t, hsize_t); - if(HADDR_UNDEF == (*new_node_p = H5MF_alloc(f, H5FD_MEM_DRAW, dxpl_id, (hsize_t)udata->common.key.nbytes))) + H5_CHECK_OVERFLOW(udata->nbytes ,size_t, hsize_t); + if(HADDR_UNDEF == (*new_node_p = H5MF_alloc(f, H5FD_MEM_DRAW, dxpl_id, (hsize_t)udata->nbytes))) HGOTO_ERROR(H5E_STORAGE, H5E_NOSPACE, H5B_INS_ERROR, "unable to reallocate chunk") #endif /* OLD_WAY */ - lt_key->nbytes = udata->common.key.nbytes; - lt_key->filter_mask = udata->common.key.filter_mask; + lt_key->nbytes = udata->nbytes; + lt_key->filter_mask = udata->filter_mask; *lt_key_changed = TRUE; udata->addr = *new_node_p; ret_value = H5B_INS_CHANGE; @@ -800,26 +796,26 @@ H5D_istore_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key, } else if (H5V_hyper_disjointp(udata->common.mesg->u.chunk.ndims, lt_key->offset, udata->common.mesg->u.chunk.dim, - udata->common.key.offset, udata->common.mesg->u.chunk.dim)) { + udata->common.offset, udata->common.mesg->u.chunk.dim)) { HDassert(H5V_hyper_disjointp(udata->common.mesg->u.chunk.ndims, rt_key->offset, udata->common.mesg->u.chunk.dim, - udata->common.key.offset, udata->common.mesg->u.chunk.dim)); + udata->common.offset, udata->common.mesg->u.chunk.dim)); /* * Split this node, inserting the new new node to the right of the * current node. The MD_KEY is where the split occurs. */ - md_key->nbytes = udata->common.key.nbytes; - md_key->filter_mask = udata->common.key.filter_mask; + md_key->nbytes = udata->nbytes; + md_key->filter_mask = udata->filter_mask; for(u = 0; u < udata->common.mesg->u.chunk.ndims; u++) { - HDassert(0 == udata->common.key.offset[u] % udata->common.mesg->u.chunk.dim[u]); - md_key->offset[u] = udata->common.key.offset[u]; - } + HDassert(0 == udata->common.offset[u] % udata->common.mesg->u.chunk.dim[u]); + md_key->offset[u] = udata->common.offset[u]; + } /* end for */ /* * Allocate storage for the new chunk */ - H5_CHECK_OVERFLOW(udata->common.key.nbytes ,size_t, hsize_t); - if(HADDR_UNDEF == (*new_node_p = H5MF_alloc(f, H5FD_MEM_DRAW, dxpl_id, (hsize_t)udata->common.key.nbytes))) + H5_CHECK_OVERFLOW(udata->nbytes, size_t, hsize_t); + if(HADDR_UNDEF == (*new_node_p = H5MF_alloc(f, H5FD_MEM_DRAW, dxpl_id, (hsize_t)udata->nbytes))) HGOTO_ERROR(H5E_STORAGE, H5E_NOSPACE, H5B_INS_ERROR, "file allocation failed") udata->addr = *new_node_p; ret_value = H5B_INS_RIGHT; @@ -898,7 +894,7 @@ H5D_istore_iter_chunkmap (H5F_t UNUSED *f, hid_t UNUSED dxpl_id, const void *_lt done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5D_istore_iter_allocated() */ +} /* H5D_istore_iter_chunkmap() */ /*------------------------------------------------------------------------- @@ -1082,17 +1078,19 @@ H5D_istore_iter_copy(H5F_t *f_src, hid_t dxpl_id, const void *_lt_key, HDmemcpy(buf, bkg, buf_size); } /* end if */ - /* Copy source chunk callback information for insertion */ - HDmemset(&udata_dst, 0, sizeof(udata_dst)); - HDmemcpy(&(udata_dst.common.key), lt_key, sizeof(H5D_istore_key_t)); + /* Set up destination chunk callback information for insertion */ udata_dst.common.mesg = udata->common.mesg; /* Share this pointer for a short while */ + udata_dst.common.offset = lt_key->offset; + udata_dst.nbytes = lt_key->nbytes; + udata_dst.filter_mask = lt_key->filter_mask; + udata_dst.addr = HADDR_UNDEF; /* Need to compress variable-length & reference data elements before writing to file */ if(is_compressed && (is_vlen || fix_ref) ) { - if(H5Z_pipeline(pline, 0, &(udata_dst.common.key.filter_mask), edc_read, + if(H5Z_pipeline(pline, 0, &(udata_dst.filter_mask), edc_read, cb_struct, &nbytes, &buf_size, &buf) < 0) HGOTO_ERROR(H5E_PLINE, H5E_CANTFILTER, H5_ITER_ERROR, "output pipeline failed") - udata_dst.common.key.nbytes = nbytes; + udata_dst.nbytes = nbytes; udata->buf = buf; udata->buf_size = buf_size; } /* end if */ @@ -1112,6 +1110,120 @@ done: /*------------------------------------------------------------------------- + * Function: H5D_istore_cinfo_cache_reset + * + * Purpose: Reset the cached chunk info + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * November 27, 2007 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5D_istore_cinfo_cache_reset(H5D_chunk_cached_t *last) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_istore_cinfo_cache_reset) + + /* Sanity check */ + HDassert(last); + + /* Indicate that the cached info is not valid */ + last->valid = FALSE; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* H5D_istore_cinfo_cache_reset() */ + + +/*------------------------------------------------------------------------- + * Function: H5D_istore_cinfo_cache_update + * + * Purpose: Update the cached chunk info + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * November 27, 2007 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5D_istore_cinfo_cache_update(H5D_chunk_cached_t *last, const H5D_istore_ud1_t *udata) +{ + unsigned u; /* Local index variable */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_istore_cinfo_cache_update) + + /* Sanity check */ + HDassert(last); + HDassert(udata); + HDassert(udata->common.mesg); + HDassert(udata->common.offset); + + /* Stored the information to cache */ + for(u = 0; u < udata->common.mesg->u.chunk.ndims; u++) + last->offset[u] = udata->common.offset[u]; + last->nbytes = udata->nbytes; + last->filter_mask = udata->filter_mask; + last->addr = udata->addr; + + /* Indicate that the cached info is valid */ + last->valid = TRUE; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* H5D_istore_cinfo_cache_update() */ + + +/*------------------------------------------------------------------------- + * Function: H5D_istore_cinfo_cache_found + * + * Purpose: Look for chunk info in cache + * + * Return: TRUE/FALSE/FAIL + * + * Programmer: Quincey Koziol + * November 27, 2007 + * + *------------------------------------------------------------------------- + */ +static hbool_t +H5D_istore_cinfo_cache_found(const H5D_chunk_cached_t *last, H5D_istore_ud1_t *udata) +{ + hbool_t ret_value = FALSE; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_istore_cinfo_cache_found) + + /* Sanity check */ + HDassert(last); + HDassert(udata); + HDassert(udata->common.mesg); + HDassert(udata->common.offset); + + /* Check if the cached information is what is desired */ + if(last->valid) { + unsigned u; /* Local index variable */ + + /* Check that the offset is the same */ + for(u = 0; u < udata->common.mesg->u.chunk.ndims; u++) + if(last->offset[u] != udata->common.offset[u]) + HGOTO_DONE(FALSE) + + /* Retrieve the information from the cache */ + udata->nbytes = last->nbytes; + udata->filter_mask = last->filter_mask; + udata->addr = last->addr; + + /* Indicate that the data was found */ + HGOTO_DONE(TRUE) + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5D_istore_cinfo_cache_found() */ + + +/*------------------------------------------------------------------------- * Function: H5D_istore_init * * Purpose: Initialize the raw data chunk cache for a dataset. This is @@ -1125,23 +1237,26 @@ done: *------------------------------------------------------------------------- */ herr_t -H5D_istore_init (const H5F_t *f, const H5D_t *dset) +H5D_istore_init(const H5F_t *f, const H5D_t *dset) { H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk); - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5D_istore_init, FAIL) - if (H5F_RDCC_NBYTES(f)>0 && H5F_RDCC_NELMTS(f)>0) { - rdcc->nbytes=H5F_RDCC_NBYTES(f); + if(H5F_RDCC_NBYTES(f) > 0 && H5F_RDCC_NELMTS(f) > 0) { + rdcc->nbytes = H5F_RDCC_NBYTES(f); rdcc->nslots = H5F_RDCC_NELMTS(f); rdcc->slot = H5FL_SEQ_CALLOC (H5D_rdcc_ent_ptr_t,rdcc->nslots); - if (NULL==rdcc->slot) + if(NULL==rdcc->slot) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + + /* Reset any cached chunk info for this dataset */ + H5D_istore_cinfo_cache_reset(&(rdcc->last)); } /* end if */ /* Allocate the shared structure */ - if(H5D_istore_shared_create(f, &dset->shared->layout)<0) + if(H5D_istore_shared_create(f, &dset->shared->layout) < 0) HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't create wrapper for shared B-tree info") done: FUNC_LEAVE_NOAPI(ret_value) @@ -1166,11 +1281,10 @@ done: static herr_t H5D_istore_flush_entry(const H5D_io_info_t *io_info, H5D_rdcc_ent_t *ent, hbool_t reset) { - herr_t ret_value=SUCCEED; /*return value */ - unsigned u; /*counters */ - void *buf=NULL; /*temporary buffer */ + void *buf = NULL; /*temporary buffer */ size_t alloc; /*bytes allocated for BUF */ hbool_t point_of_no_return = FALSE; + herr_t ret_value = SUCCEED; /*return value */ FUNC_ENTER_NOAPI_NOINIT(H5D_istore_flush_entry) @@ -1180,30 +1294,33 @@ H5D_istore_flush_entry(const H5D_io_info_t *io_info, H5D_rdcc_ent_t *ent, hbool_ assert(!ent->locked); buf = ent->chunk; - if (ent->dirty) { + if(ent->dirty) { H5D_istore_ud1_t udata; /*pass through B-tree */ + /* Initial buffer size */ + alloc = ent->alloc_size; + + /* Set up user data for B-tree callbacks */ udata.common.mesg = &io_info->dset->shared->layout; - udata.common.key.filter_mask = 0; + udata.common.offset = ent->offset; + udata.filter_mask = 0; + udata.nbytes = ent->chunk_size; udata.addr = HADDR_UNDEF; - udata.common.key.nbytes = ent->chunk_size; - for (u=0; u<io_info->dset->shared->layout.u.chunk.ndims; u++) - udata.common.key.offset[u] = ent->offset[u]; - alloc = ent->alloc_size; /* Should the chunk be filtered before writing it to disk? */ - if (io_info->dset->shared->dcpl_cache.pline.nused) { - if (!reset) { + if(io_info->dset->shared->dcpl_cache.pline.nused) { + if(!reset) { /* * Copy the chunk to a new buffer before running it through * the pipeline because we'll want to save the original buffer * for later. */ alloc = ent->chunk_size; - if (NULL==(buf = H5MM_malloc(alloc))) + if(NULL == (buf = H5MM_malloc(alloc))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for pipeline") HDmemcpy(buf, ent->chunk, ent->chunk_size); - } else { + } /* end if */ + else { /* * If we are reseting and something goes wrong after this * point then it's too late to recover because we may have @@ -1213,11 +1330,11 @@ H5D_istore_flush_entry(const H5D_io_info_t *io_info, H5D_rdcc_ent_t *ent, hbool_ */ point_of_no_return = TRUE; ent->chunk = NULL; - } - if (H5Z_pipeline(&(io_info->dset->shared->dcpl_cache.pline), 0, &(udata.common.key.filter_mask), io_info->dxpl_cache->err_detect, - io_info->dxpl_cache->filter_cb, &(udata.common.key.nbytes), &alloc, &buf)<0) + } /* end else */ + if(H5Z_pipeline(&(io_info->dset->shared->dcpl_cache.pline), 0, &(udata.filter_mask), io_info->dxpl_cache->err_detect, + io_info->dxpl_cache->filter_cb, &(udata.nbytes), &alloc, &buf) < 0) HGOTO_ERROR(H5E_PLINE, H5E_CANTFILTER, FAIL, "output pipeline failed") - } + } /* end if */ /* * Create the chunk it if it doesn't exist, or reallocate the chunk if @@ -1225,9 +1342,12 @@ H5D_istore_flush_entry(const H5D_io_info_t *io_info, H5D_rdcc_ent_t *ent, hbool_ */ if(H5B_insert(io_info->dset->oloc.file, io_info->dxpl_id, H5B_ISTORE, io_info->dset->shared->layout.u.chunk.addr, &udata)<0) HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to allocate chunk") - if(H5F_block_write(io_info->dset->oloc.file, H5FD_MEM_DRAW, udata.addr, udata.common.key.nbytes, io_info->dxpl_id, buf) < 0) + if(H5F_block_write(io_info->dset->oloc.file, H5FD_MEM_DRAW, udata.addr, udata.nbytes, io_info->dxpl_id, buf) < 0) HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to write raw data to file") + /* Cache the chunk's info, in case it's accessed again shortly */ + H5D_istore_cinfo_cache_update(&io_info->dset->shared->cache.chunk.last, &udata); + /* Mark cache entry as clean */ ent->dirty = FALSE; #ifdef H5D_ISTORE_DEBUG @@ -1236,17 +1356,17 @@ H5D_istore_flush_entry(const H5D_io_info_t *io_info, H5D_rdcc_ent_t *ent, hbool_ } /* end if */ /* Reset, but do not free or removed from list */ - if (reset) { + if(reset) { point_of_no_return = FALSE; - if(buf==ent->chunk) + if(buf == ent->chunk) buf = NULL; - if(ent->chunk!=NULL) - ent->chunk = H5D_istore_chunk_xfree(ent->chunk,&(io_info->dset->shared->dcpl_cache.pline)); + if(ent->chunk != NULL) + ent->chunk = (uint8_t *)H5D_istore_chunk_xfree(ent->chunk, &(io_info->dset->shared->dcpl_cache.pline)); } /* end if */ done: /* Free the temp buffer only if it's different than the entry chunk */ - if (buf!=ent->chunk) + if(buf != ent->chunk) H5MM_xfree(buf); /* @@ -1255,9 +1375,9 @@ done: * output pipeline failed. Do not free the entry or remove it from the * list. */ - if (ret_value<0 && point_of_no_return) { + if(ret_value < 0 && point_of_no_return) { if(ent->chunk) - ent->chunk = H5D_istore_chunk_xfree(ent->chunk,&(io_info->dset->shared->dcpl_cache.pline)); + ent->chunk = (uint8_t *)H5D_istore_chunk_xfree(ent->chunk, &(io_info->dset->shared->dcpl_cache.pline)); } /* end if */ FUNC_LEAVE_NOAPI(ret_value) @@ -1294,12 +1414,12 @@ H5D_istore_preempt(const H5D_io_info_t *io_info, H5D_rdcc_ent_t * ent, hbool_t f /* Flush */ if(H5D_istore_flush_entry(io_info, ent, TRUE) < 0) HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "cannot flush indexed storage buffer") - } + } /* end if */ else { /* Don't flush, just free chunk */ if(ent->chunk != NULL) - ent->chunk = H5D_istore_chunk_xfree(ent->chunk,&(io_info->dset->shared->dcpl_cache.pline)); - } + ent->chunk = (uint8_t *)H5D_istore_chunk_xfree(ent->chunk, &(io_info->dset->shared->dcpl_cache.pline)); + } /* end else */ /* Unlink from list */ if(ent->prev) @@ -1520,13 +1640,13 @@ H5D_istore_shared_free (void *_shared) FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_istore_shared_free) /* Free the raw B-tree node buffer */ - H5FL_BLK_FREE(chunk_page,shared->page); + (void)H5FL_BLK_FREE(chunk_page, shared->page); /* Free the B-tree native key offsets buffer */ - H5FL_SEQ_FREE(size_t,shared->nkey); + H5FL_SEQ_FREE(size_t, shared->nkey); /* Free the shared B-tree info */ - H5FL_FREE(H5B_shared_t,shared); + H5FL_FREE(H5B_shared_t, shared); FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5D_istore_shared_free() */ @@ -1770,15 +1890,15 @@ H5D_istore_lock(const H5D_io_info_t *io_info, H5D_istore_ud1_t *udata, */ /* Chunk size on disk isn't [likely] the same size as the final chunk * size in memory, so allocate memory big enough. */ - chunk_alloc = udata->common.key.nbytes; + chunk_alloc = udata->nbytes; if(NULL == (chunk = H5D_istore_chunk_alloc (chunk_alloc, pline))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for raw data chunk") - if(H5F_block_read(dset->oloc.file, H5FD_MEM_DRAW, chunk_addr, udata->common.key.nbytes, io_info->dxpl_id, chunk) < 0) + if(H5F_block_read(dset->oloc.file, H5FD_MEM_DRAW, chunk_addr, udata->nbytes, io_info->dxpl_id, chunk) < 0) HGOTO_ERROR(H5E_IO, H5E_READERROR, NULL, "unable to read raw data chunk") if(pline->nused) - if(H5Z_pipeline(pline, H5Z_FLAG_REVERSE, &(udata->common.key.filter_mask), io_info->dxpl_cache->err_detect, - io_info->dxpl_cache->filter_cb, &(udata->common.key.nbytes), &chunk_alloc, &chunk) < 0) + if(H5Z_pipeline(pline, H5Z_FLAG_REVERSE, &(udata->filter_mask), io_info->dxpl_cache->err_detect, + io_info->dxpl_cache->filter_cb, &(udata->nbytes), &chunk_alloc, &chunk) < 0) HGOTO_ERROR(H5E_PLINE, H5E_CANTFILTER, NULL, "data pipeline read failed") #ifdef H5D_ISTORE_DEBUG rdcc->nmisses++; @@ -2336,7 +2456,7 @@ HDfprintf(stderr,"%s: mem_offset_arr[%Zu]=%Hu\n",FUNC,*mem_curr_seq,mem_offset_a 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) + 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 { @@ -2524,7 +2644,6 @@ H5D_istore_get_addr(const H5D_io_info_t *io_info, H5D_istore_ud1_t *_udata) { H5D_istore_ud1_t tmp_udata; /* Information about a chunk */ H5D_istore_ud1_t *udata; /* Pointer to information about a chunk */ - unsigned u; haddr_t ret_value; /* Return value */ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_istore_get_addr) @@ -2538,28 +2657,39 @@ H5D_istore_get_addr(const H5D_io_info_t *io_info, H5D_istore_ud1_t *_udata) udata = (_udata != NULL ? _udata : &tmp_udata); /* Initialize the information about the chunk we are looking for */ - for(u = 0; u < io_info->dset->shared->layout.u.chunk.ndims; u++) - udata->common.key.offset[u] = io_info->store->chunk.offset[u]; udata->common.mesg = &(io_info->dset->shared->layout); + udata->common.offset = io_info->store->chunk.offset; + udata->nbytes = 0; + udata->filter_mask = 0; udata->addr = HADDR_UNDEF; - /* Go get the chunk information */ - if (H5B_find (io_info->dset->oloc.file, io_info->dxpl_id, H5B_ISTORE, io_info->dset->shared->layout.u.chunk.addr, udata)<0) { - /* Note: don't push error on stack, leave that to next higher level, - * since many times the B-tree is searched in order to determine - * if a chunk exists in the B-tree or not. -QAK - */ + /* Check for cached information */ + if(!H5D_istore_cinfo_cache_found(&io_info->dset->shared->cache.chunk.last, udata)) { + /* Go get the chunk information */ + if(H5B_find(io_info->dset->oloc.file, io_info->dxpl_id, H5B_ISTORE, io_info->dset->shared->layout.u.chunk.addr, udata) < 0) { + /* Note: don't push error on stack, leave that to next higher level, + * since many times the B-tree is searched in order to determine + * if a chunk exists in the B-tree or not. -QAK + */ #ifdef OLD_WAY - H5E_clear_stack(NULL); + H5E_clear_stack(NULL); - HGOTO_ERROR(H5E_BTREE,H5E_NOTFOUND,HADDR_UNDEF,"Can't locate chunk info") + HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, HADDR_UNDEF, "Can't locate chunk info") #else /* OLD_WAY */ - HGOTO_DONE(HADDR_UNDEF) + /* Cache the fact that the chunk is not in the B-tree */ + H5D_istore_cinfo_cache_update(&io_info->dset->shared->cache.chunk.last, udata); + + HGOTO_DONE(HADDR_UNDEF) #endif /* OLD_WAY */ - } /* end if */ + } /* end if */ + + /* Cache the information retrieved */ + HDassert(H5F_addr_defined(udata->addr)); + H5D_istore_cinfo_cache_update(&io_info->dset->shared->cache.chunk.last, udata); + } /* end else */ /* Success! Set the return value */ - ret_value=udata->addr; + ret_value = udata->addr; done: FUNC_LEAVE_NOAPI(ret_value) @@ -2624,7 +2754,7 @@ H5D_istore_chunk_xfree(void *chk, const H5O_pline_t *pline) if(pline->nused > 0) H5MM_xfree(chk); else - H5FL_BLK_FREE(chunk, chk); + (void)H5FL_BLK_FREE(chunk, chk); } /* end if */ FUNC_LEAVE_NOAPI(NULL) @@ -2834,11 +2964,10 @@ H5D_istore_allocate(H5D_t *dset, hid_t dxpl_id, hbool_t full_overwrite) /* Initialize the chunk information */ udata.common.mesg = layout; - udata.common.key.filter_mask = filter_mask; + udata.common.offset = chunk_offset; + udata.nbytes = chunk_size; + udata.filter_mask = filter_mask; udata.addr = HADDR_UNDEF; - udata.common.key.nbytes = chunk_size; - for(u = 0; u < layout->u.chunk.ndims; u++) - udata.common.key.offset[u] = chunk_offset[u]; /* Allocate the chunk with all processes */ if(H5B_insert(dset->oloc.file, dxpl_id, H5B_ISTORE, layout->u.chunk.addr, &udata) < 0) @@ -2855,7 +2984,7 @@ H5D_istore_allocate(H5D_t *dset, hid_t dxpl_id, hbool_t full_overwrite) /* Write the chunks out from only one process */ /* !! Use the internal "independent" DXPL!! -QAK */ if(H5_PAR_META_WRITE == mpi_rank) - if(H5F_block_write(dset->oloc.file, H5FD_MEM_DRAW, udata.addr, udata.common.key.nbytes, data_dxpl_id, fb_info.fill_buf) < 0) + if(H5F_block_write(dset->oloc.file, H5FD_MEM_DRAW, udata.addr, udata.nbytes, data_dxpl_id, fb_info.fill_buf) < 0) HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to write raw data to file") /* Indicate that blocks are being written */ @@ -2863,7 +2992,7 @@ H5D_istore_allocate(H5D_t *dset, hid_t dxpl_id, hbool_t full_overwrite) } /* end if */ else { #endif /* H5_HAVE_PARALLEL */ - if(H5F_block_write(dset->oloc.file, H5FD_MEM_DRAW, udata.addr, udata.common.key.nbytes, data_dxpl_id, fb_info.fill_buf) < 0) + if(H5F_block_write(dset->oloc.file, H5FD_MEM_DRAW, udata.addr, udata.nbytes, data_dxpl_id, fb_info.fill_buf) < 0) HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to write raw data to file") #ifdef H5_HAVE_PARALLEL } /* end else */ @@ -2902,6 +3031,9 @@ H5D_istore_allocate(H5D_t *dset, hid_t dxpl_id, hbool_t full_overwrite) } /* end if */ #endif /* H5_HAVE_PARALLEL */ + /* Reset any cached chunk info for this dataset */ + H5D_istore_cinfo_cache_reset(&dset->shared->cache.chunk.last); + done: /* Release the fill buffer info, if it's been initialized */ if(fb_info_init && H5D_fill_term(&fb_info) < 0) @@ -3002,9 +3134,8 @@ H5D_istore_prune_remove(void *item, void UNUSED *key, void *op_data) HDassert(rm_info); /* Initialize the user data for the B-tree callback */ - HDmemset(&bt_udata, 0, sizeof bt_udata); - bt_udata.key = sl_node->key; bt_udata.mesg = rm_info->mesg; + bt_udata.offset = sl_node->key.offset; /* Remove */ if(H5B_remove(rm_info->f, rm_info->dxpl_id, H5B_ISTORE, rm_info->mesg->u.chunk.addr, &bt_udata) < 0) @@ -3212,6 +3343,9 @@ H5D_istore_prune_by_extent(const H5D_io_info_t *io_info, const hsize_t *old_dims /* Destroy the skip list, deleting the chunks in the callback */ H5SL_destroy(udata.outside, H5D_istore_prune_remove, &rm_info); + /* Reset any cached chunk info for this dataset */ + H5D_istore_cinfo_cache_reset(&dset->shared->cache.chunk.last); + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5D_istore_prune_by_extent() */ @@ -3406,7 +3540,7 @@ H5D_istore_initialize_by_extent(H5D_io_info_t *io_info) /* Lock the chunk into the cache, to get a pointer to the chunk buffer */ store.chunk.offset = chunk_offset; - if(NULL == (chunk = H5D_istore_lock(io_info, NULL, FALSE, &idx_hint))) + if(NULL == (chunk = (uint8_t *)H5D_istore_lock(io_info, NULL, FALSE, &idx_hint))) HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to read raw data chunk") @@ -3546,39 +3680,46 @@ H5D_istore_update_cache(H5D_t *dset, hid_t dxpl_id) H5D_rdcc_ent_t *ent, *next; /*cache entry */ H5D_rdcc_ent_t *old_ent; /* Old cache entry */ H5D_dxpl_cache_t _dxpl_cache; /* Data transfer property cache buffer */ - H5D_dxpl_cache_t *dxpl_cache=&_dxpl_cache; /* Data transfer property cache */ - unsigned rank; /*current # of dimensions */ + H5D_dxpl_cache_t *dxpl_cache = &_dxpl_cache; /* Data transfer property cache */ + unsigned rank; /*current # of dimensions */ hsize_t curr_dims[H5O_LAYOUT_NDIMS]; /*current dataspace dimensions */ hsize_t chunks[H5O_LAYOUT_NDIMS]; /*current number of chunks in each dimension */ hsize_t down_chunks[H5O_LAYOUT_NDIMS]; /* "down" size of number of elements in each dimension */ - unsigned u; /*counters */ - herr_t ret_value=SUCCEED; /* Return value */ + unsigned u; /*counters */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5D_istore_update_cache, FAIL) /* Check args */ - assert(dset && H5D_CHUNKED == dset->shared->layout.type); - assert(dset->shared->layout.u.chunk.ndims > 0 && dset->shared->layout.u.chunk.ndims <= H5O_LAYOUT_NDIMS); + 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); - /* Go get the rank & dimensions */ + /* Get the rank */ rank = dset->shared->layout.u.chunk.ndims-1; + HDassert(rank > 0); + + /* 1-D dataset's chunks can't have their index change */ + if(rank == 1) + HGOTO_DONE(SUCCEED) + + /* Go get the dimensions */ if(H5S_get_simple_extent_dims(dset->shared->space, curr_dims, NULL) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get dataset dimensions") /* Round up to the next integer # of chunks, to accomodate partial chunks */ for(u = 0; u < rank; u++) - chunks[u] = ((curr_dims[u]+dset->shared->layout.u.chunk.dim[u])-1) / dset->shared->layout.u.chunk.dim[u]; + chunks[u] = ((curr_dims[u] + dset->shared->layout.u.chunk.dim[u]) - 1) / dset->shared->layout.u.chunk.dim[u]; /* Get the "down" sizes for each dimension */ - if(H5V_array_down(rank,chunks,down_chunks) < 0) + if(H5V_array_down(rank, chunks, down_chunks) < 0) HGOTO_ERROR(H5E_INTERNAL, H5E_BADVALUE, FAIL, "can't compute 'down' sizes") /* Fill the DXPL cache values for later use */ - if (H5D_get_dxpl_cache(dxpl_id,&dxpl_cache) < 0) + if(H5D_get_dxpl_cache(dxpl_id, &dxpl_cache) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't fill dxpl cache") /* Construct dataset I/O info */ - H5D_BUILD_IO_INFO(&io_info,dset,dxpl_cache,dxpl_id,NULL); + H5D_BUILD_IO_INFO(&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) { @@ -3596,26 +3737,26 @@ H5D_istore_update_cache(H5D_t *dset, hid_t dxpl_id) old_idx=ent->idx; /* Save for later */ ent->idx=H5D_HASH(dset->shared,idx); - if(old_idx!=ent->idx) { + if(old_idx != ent->idx) { /* Check if there is already a chunk at this chunk's new location */ old_ent = rdcc->slot[ent->idx]; - if(old_ent!=NULL) { - assert(old_ent->locked==0); + if(old_ent != NULL) { + HDassert(old_ent->locked == 0); /* Check if we are removing the entry we would walk to next */ - if(old_ent==next) - next=old_ent->next; + if(old_ent == next) + next = old_ent->next; /* Remove the old entry from the cache */ - if (H5D_istore_preempt(&io_info, old_ent, TRUE )<0) + if(H5D_istore_preempt(&io_info, old_ent, TRUE) < 0) HGOTO_ERROR(H5E_IO, H5E_CANTFLUSH, FAIL, "unable to flush one or more raw data chunks") } /* end if */ /* Insert this chunk into correct location in hash table */ - rdcc->slot[ent->idx]=ent; + rdcc->slot[ent->idx] = ent; /* Null out previous location */ - rdcc->slot[old_idx]=NULL; + rdcc->slot[old_idx] = NULL; } /* end if */ } /* end for */ diff --git a/src/H5Dmpio.c b/src/H5Dmpio.c index ccfaac9..22f32ab 100644 --- a/src/H5Dmpio.c +++ b/src/H5Dmpio.c @@ -550,7 +550,7 @@ H5D_mpio_get_min_chunk(const H5D_io_info_t *io_info, FUNC_ENTER_NOAPI_NOINIT(H5D_mpio_get_min_chunk); /* Get the number of chunks to perform I/O on */ - num_chunkf = H5SL_count(fm->fsel); + 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))) @@ -586,7 +586,7 @@ H5D_mpio_get_sum_chunk(const H5D_io_info_t *io_info, /* Get the number of chunks to perform I/O on */ num_chunkf = 0; - ori_num_chunkf = H5SL_count(fm->fsel); + ori_num_chunkf = H5SL_count(fm->sel_chunks); H5_ASSIGN_OVERFLOW(num_chunkf,ori_num_chunkf,size_t,int); /* Determine the summation of number of chunks for all processes */ @@ -856,7 +856,7 @@ H5D_link_chunk_collective_io(H5D_io_info_t *io_info,H5D_chunk_map_t *fm,const vo H5D_chunk_info_t *chunk_info; H5D_storage_t store; - chunk_node = H5SL_first(fm->fsel); + chunk_node = H5SL_first(fm->sel_chunks); if(chunk_node == NULL) { if(H5D_istore_chunkmap(io_info, &chunk_base_addr, fm->down_chunks) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get chunk address"); @@ -884,7 +884,7 @@ H5D_link_chunk_collective_io(H5D_io_info_t *io_info,H5D_chunk_map_t *fm,const vo } /* Allocate chunking information */ - ori_num_chunk = H5SL_count(fm->fsel); + ori_num_chunk = H5SL_count(fm->sel_chunks); H5_ASSIGN_OVERFLOW(num_chunk,ori_num_chunk,size_t,int); #ifdef H5D_DEBUG @@ -1114,7 +1114,7 @@ H5D_multi_chunk_collective_io(H5D_io_info_t *io_info,H5D_chunk_map_t *fm,const v #endif select_chunk = fm->select_chunk[i]; if(select_chunk == 1){/* Have selection elements in this chunk. Find the chunk info. */ - if(NULL ==(chunk_node = H5SL_first(fm->fsel))) + 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){ @@ -1313,7 +1313,7 @@ H5D_multi_chunk_collective_io_no_opt(H5D_io_info_t *io_info,H5D_chunk_map_t *fm, count_chunk = 0; /* Get first node in chunk skip list */ - chunk_node=H5SL_first(fm->fsel); + chunk_node=H5SL_first(fm->sel_chunks); /* Iterate through chunks to be operated on */ while(chunk_node) { @@ -1618,7 +1618,7 @@ H5D_sort_chunk(H5D_io_info_t * io_info, FUNC_ENTER_NOAPI_NOINIT(H5D_sort_chunk) - num_chunks = H5SL_count(fm->fsel); + num_chunks = H5SL_count(fm->sel_chunks); #ifdef H5D_DEBUG if(H5DEBUG(D)) HDfprintf(H5DEBUG(D),"many_chunk_opt= %d\n",many_chunk_opt); @@ -1657,7 +1657,7 @@ H5D_sort_chunk(H5D_io_info_t * io_info, } /* end if */ /* Get first node in chunk skip list */ - if(NULL ==(chunk_node = H5SL_first(fm->fsel))) + 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; @@ -1843,7 +1843,7 @@ H5D_obtain_mpio_mode(H5D_io_info_t* io_info, mem_cleanup = 1; - chunk_node = H5SL_first(fm->fsel); + chunk_node = H5SL_first(fm->sel_chunks); /*Obtain the regularity and selection information for all chunks in this process. */ while(chunk_node){ diff --git a/src/H5Dpkg.h b/src/H5Dpkg.h index 4fbec67..aec5e19 100644 --- a/src/H5Dpkg.h +++ b/src/H5Dpkg.h @@ -119,6 +119,26 @@ typedef struct H5D_io_info_t { #endif /* H5S_DEBUG */ } H5D_io_info_t; +/* Structure holding information about a chunk's selection for mapping */ +typedef struct H5D_chunk_info_t { + hsize_t index; /* "Index" of chunk in dataset */ + size_t chunk_points; /* Number of elements selected in chunk */ + hsize_t coords[H5O_LAYOUT_NDIMS]; /* Coordinates of chunk in file dataset's dataspace */ + H5S_t *fspace; /* Dataspace describing chunk & selection in it */ + unsigned fspace_shared; /* Indicate that the file space for a chunk is shared and shouldn't be freed */ + H5S_t *mspace; /* Dataspace describing selection in memory corresponding to this chunk */ + unsigned mspace_shared; /* Indicate that the memory space for a chunk is shared and shouldn't be freed */ +} H5D_chunk_info_t; + +/* Cached information about a particular chunk */ +typedef struct { + hbool_t valid; /*whether cache info is valid*/ + hsize_t offset[H5O_LAYOUT_NDIMS]; /*logical offset to start*/ + size_t nbytes; /*size of stored data */ + unsigned filter_mask; /*excluded filters */ + haddr_t addr; /*file address of chunk */ +} H5D_chunk_cached_t; + /* The raw data chunk cache */ typedef struct H5D_rdcc_t { #ifdef H5D_ISTORE_DEBUG @@ -132,7 +152,11 @@ typedef struct H5D_rdcc_t { struct H5D_rdcc_ent_t *head; /* Head of doubly linked list */ struct H5D_rdcc_ent_t *tail; /* Tail of doubly linked list */ int nused; /* Number of chunk slots in use */ + H5D_chunk_cached_t last; /* Cached copy of last chunk information */ struct H5D_rdcc_ent_t **slot; /* Chunk slots, each points to a chunk*/ + H5SL_t *sel_chunks; /* Skip list containing information for each chunk selected */ + H5S_t *single_space; /* Dataspace for single element I/O on chunks */ + H5D_chunk_info_t *single_chunk_info; /* Pointer to single chunk's info */ } H5D_rdcc_t; /* The raw data contiguous data cache */ @@ -156,6 +180,7 @@ typedef struct H5D_shared_t { H5T_t *type; /* datatype of this dataset */ H5S_t *space; /* dataspace of this dataset */ hbool_t space_dirty; /* Whether the dataspace info needs to be flushed to the file */ + 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 */ @@ -188,16 +213,6 @@ typedef enum { } H5D_time_alloc_t; -/* Structure holding information about a chunk's selection for mapping */ -typedef struct H5D_chunk_info_t { - hsize_t index; /* "Index" of chunk in dataset */ - size_t chunk_points; /* Number of elements selected in chunk */ - H5S_t *fspace; /* Dataspace describing chunk & selection in it */ - hsize_t coords[H5O_LAYOUT_NDIMS]; /* Coordinates of chunk in file dataset's dataspace */ - H5S_t *mspace; /* Dataspace describing selection in memory corresponding to this chunk */ - unsigned mspace_shared; /* Indicate that the memory space for a chunk is shared and shouldn't be freed */ -} H5D_chunk_info_t; - /* Main structure holding the mapping between file chunks and memory */ typedef struct H5D_chunk_map_t { H5O_layout_t *layout; /* Dataset layout information*/ @@ -213,7 +228,10 @@ typedef struct H5D_chunk_map_t { unsigned m_ndims; /* Number of dimensions for memory dataspace */ H5S_sel_type msel_type; /* Selection type in memory */ - H5SL_t *fsel; /* Skip list containing file dataspaces for all chunks */ + 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 */ @@ -289,14 +307,18 @@ typedef struct H5D_istore_key_t { */ typedef struct H5D_istore_bt_ud_common_t { /* downward */ - H5D_istore_key_t key; /*key values */ - const H5O_layout_t *mesg; /*layout message */ + const H5O_layout_t *mesg; /*layout message */ + const hsize_t *offset; /*logical offset of chunk*/ } H5D_istore_bt_ud_common_t; /* B-tree callback info for various operations */ typedef struct H5D_istore_ud1_t { H5D_istore_bt_ud_common_t common; /* Common info for B-tree user data (must be first) */ - haddr_t addr; /*file address of chunk */ + + /* Upward */ + size_t nbytes; /*size of stored data */ + unsigned filter_mask; /*excluded filters */ + haddr_t addr; /*file address of chunk */ } H5D_istore_ud1_t; /* Internal data structure for computing variable-length dataset's total size */ @@ -329,7 +351,7 @@ H5_DLL H5D_t *H5D_create_named(const H5G_loc_t *loc, const char *name, H5_DLL herr_t H5D_get_space_status(H5D_t *dset, H5D_space_status_t *allocation, hid_t dxpl_id); H5_DLL herr_t H5D_alloc_storage(H5F_t *f, hid_t dxpl_id, H5D_t *dset, H5D_time_alloc_t time_alloc, - hbool_t update_time, hbool_t full_overwrite); + hbool_t full_overwrite); H5_DLL hsize_t H5D_get_storage_size(H5D_t *dset, hid_t dxpl_id); H5_DLL haddr_t H5D_get_offset(const H5D_t *dset); H5_DLL herr_t H5D_iterate(void *buf, hid_t type_id, const H5S_t *space, diff --git a/src/H5Dpublic.h b/src/H5Dpublic.h index d7f6574..0d8b63f 100644 --- a/src/H5Dpublic.h +++ b/src/H5Dpublic.h @@ -113,7 +113,7 @@ H5_DLL herr_t H5Dvlen_reclaim(hid_t type_id, hid_t space_id, hid_t plist_id, voi H5_DLL herr_t H5Dvlen_get_buf_size(hid_t dataset_id, hid_t type_id, hid_t space_id, hsize_t *size); H5_DLL herr_t H5Dfill(const void *fill, hid_t fill_type, void *buf, hid_t buf_type, hid_t space); -H5_DLL herr_t H5Dset_extent(hid_t dset_id, const hsize_t *size); +H5_DLL herr_t H5Dset_extent(hid_t dset_id, const hsize_t size[]); H5_DLL herr_t H5Ddebug(hid_t dset_id); /* Symbols defined for compatibility with previous versions of the HDF5 API. @@ -132,7 +132,7 @@ H5_DLL herr_t H5Ddebug(hid_t dset_id); H5_DLL hid_t H5Dcreate1(hid_t file_id, const char *name, hid_t type_id, hid_t space_id, hid_t dcpl_id); H5_DLL hid_t H5Dopen1(hid_t file_id, const char *name); -H5_DLL herr_t H5Dextend(hid_t dset_id, const hsize_t *size); +H5_DLL herr_t H5Dextend(hid_t dset_id, const hsize_t size[]); #endif /* H5_NO_DEPRECATED_SYMBOLS */ diff --git a/src/H5Dselect.c b/src/H5Dselect.c index 105b4e5..f08672f 100644 --- a/src/H5Dselect.c +++ b/src/H5Dselect.c @@ -46,6 +46,18 @@ /* 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 */ /*********************/ @@ -419,153 +431,199 @@ done: /*------------------------------------------------------------------------- - * Function: H5D_select_read + * Function: H5D_select_io * - * Purpose: Reads directly from file into application memory. + * Purpose: Perform I/O directly from application memory and a file * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol - * Tuesday, July 23, 2002 + * Tuesday, November 27, 2007 * *------------------------------------------------------------------------- */ -herr_t -H5D_select_read(H5D_io_info_t *io_info, +static herr_t +H5D_select_io(H5D_io_info_t *io_info, size_t nelmts, size_t elmt_size, const H5S_t *file_space, const H5S_t *mem_space, haddr_t addr, void *chunk/*in*/, - void *buf/*out*/) + 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 */ + hbool_t mem_iter_init = 0; /* Memory selection 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 */ + hbool_t file_iter_init = 0; /* File selection iteration info has been initialized */ hsize_t _mem_off[H5D_IO_VECTOR_SIZE]; /* Array to store sequence offsets in memory */ - hsize_t *mem_off=NULL; /* Pointer to sequence offsets in memory */ + hsize_t *mem_off = NULL; /* Pointer to sequence offsets in memory */ hsize_t _file_off[H5D_IO_VECTOR_SIZE]; /* Array to store sequence offsets in the file */ - hsize_t *file_off=NULL; /* Pointer to sequence offsets in the file */ + hsize_t *file_off = NULL; /* Pointer to sequence offsets in the file */ size_t _mem_len[H5D_IO_VECTOR_SIZE]; /* Array to store sequence lengths in memory */ - size_t *mem_len=NULL; /* Pointer to sequence lengths in memory */ + size_t *mem_len = NULL; /* Pointer to sequence lengths in memory */ size_t _file_len[H5D_IO_VECTOR_SIZE]; /* Array to store sequence lengths in the file */ - size_t *file_len=NULL; /* Pointer to sequence lengths in the file */ - size_t mem_nseq; /* Number of sequences generated in the file */ - size_t file_nseq; /* Number of sequences generated in memory */ - size_t mem_nelem; /* Number of elements used in memory sequences */ - size_t file_nelem; /* Number of elements used in file sequences */ + size_t *file_len = NULL; /* Pointer to sequence lengths in the file */ size_t curr_mem_seq; /* Current memory sequence to operate on */ size_t curr_file_seq; /* Current file sequence to operate on */ + size_t mem_nseq; /* Number of sequences generated in the file */ + size_t file_nseq; /* Number of sequences generated in memory */ ssize_t tmp_file_len; /* Temporary number of bytes in file sequence */ - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5D_select_read, FAIL); + FUNC_ENTER_NOAPI(H5D_select_io, FAIL) /* Check args */ - assert(io_info); - assert(io_info->dset); - assert(io_info->dxpl_cache); - assert(io_info->store); - assert(buf); - assert(TRUE==H5P_isa_class(io_info->dxpl_id,H5P_DATASET_XFER)); - - /* Initialize file iterator */ - if (H5S_select_iter_init(&file_iter, file_space, elmt_size)<0) - HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator"); - file_iter_init=1; /* File selection iteration info has been initialized */ - - /* Initialize memory iterator */ - if (H5S_select_iter_init(&mem_iter, mem_space, elmt_size)<0) - HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator"); - mem_iter_init=1; /* Memory selection iteration info has been initialized */ + HDassert(io_info); + HDassert(io_info->dset); + HDassert(io_info->store); + HDassert(TRUE == H5P_isa_class(io_info->dxpl_id, H5P_DATASET_XFER)); + HDassert(io_buf->u.rbuf); /* Allocate the vector I/O arrays */ if(io_info->dxpl_cache->vec_size != H5D_IO_VECTOR_SIZE) { - if((mem_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((mem_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"); - if((file_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((file_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"); + 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))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O offset vector array") + if(NULL == (file_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 == (file_off = H5FL_SEQ_MALLOC(hsize_t,io_info->dxpl_cache->vec_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O offset vector array") } /* end if */ else { - mem_len=_mem_len; - mem_off=_mem_off; - file_len=_file_len; - file_off=_file_off; + mem_len = _mem_len; + mem_off = _mem_off; + file_len = _file_len; + file_off = _file_off; } /* end else */ - /* Initialize sequence counts */ - curr_mem_seq=curr_file_seq=0; - mem_nseq=file_nseq=0; - - /* Loop, until all bytes are processed */ - while(nelmts>0) { - /* Check if more file sequences are needed */ - if(curr_file_seq>=file_nseq) { - /* Get sequences for file selection */ - if(H5S_SELECT_GET_SEQ_LIST(file_space,H5S_GET_SEQ_LIST_SORTED,&file_iter,io_info->dxpl_cache->vec_size,nelmts,&file_nseq,&file_nelem,file_off,file_len)<0) - HGOTO_ERROR (H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed"); - - /* Start at the beginning of the sequences again */ - curr_file_seq=0; + /* Check for only one element in selection */ + if(nelmts == 1) { + /* Get offset of first element in selections */ + if(H5S_SELECT_OFFSET(file_space, file_off) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "can't retrieve file selection offset") + if(H5S_SELECT_OFFSET(mem_space, mem_off) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "can't retrieve memory selection offset") + + /* Set up necessary information for I/O operation */ + file_nseq = mem_nseq = 1; + curr_mem_seq = curr_file_seq = 0; + *file_off *= elmt_size; + *mem_off *= elmt_size; + *file_len = *mem_len = elmt_size; + + /* Perform I/O on memory and file sequences */ + if(io_buf->op_type == H5S_SELECT_READ) { + if((tmp_file_len = (*io_info->ops.readvv)(io_info, + file_nseq, &curr_file_seq, file_len, file_off, + mem_nseq, &curr_mem_seq, mem_len, mem_off, + addr, chunk, io_buf->u.rbuf)) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_READERROR, FAIL, "read error") } /* end if */ - - /* Check if more memory sequences are needed */ - if(curr_mem_seq>=mem_nseq) { - /* Get sequences for memory selection */ - if(H5S_SELECT_GET_SEQ_LIST(mem_space,0,&mem_iter,io_info->dxpl_cache->vec_size,nelmts,&mem_nseq,&mem_nelem,mem_off,mem_len)<0) - HGOTO_ERROR (H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed"); - - /* Start at the beginning of the sequences again */ - curr_mem_seq=0; - } /* end if */ - - /* Read file sequences into current memory sequence */ - 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, - addr, chunk, buf))<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_READERROR, FAIL, "read error"); + else { + 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, + addr, chunk, io_buf->u.wbuf)) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_WRITEERROR, FAIL, "write error") + } /* end else */ /* Decrement number of elements left to process */ - assert((tmp_file_len%elmt_size)==0); - nelmts-=(tmp_file_len/elmt_size); - } /* end while */ + HDassert((tmp_file_len % elmt_size) == 0); + } /* end if */ + else { + size_t mem_nelem; /* Number of elements used in memory sequences */ + size_t file_nelem; /* Number of elements used in file sequences */ + + /* Initialize file iterator */ + if(H5S_select_iter_init(&file_iter, file_space, elmt_size) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator") + file_iter_init = 1; /* File selection iteration info has been initialized */ + + /* Initialize memory iterator */ + if(H5S_select_iter_init(&mem_iter, mem_space, elmt_size) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator") + mem_iter_init = 1; /* Memory selection iteration info has been initialized */ + + /* Initialize sequence counts */ + curr_mem_seq = curr_file_seq = 0; + mem_nseq = file_nseq = 0; + + /* Loop, until all bytes are processed */ + while(nelmts > 0) { + /* Check if more file sequences are needed */ + if(curr_file_seq >= file_nseq) { + /* Get sequences for file selection */ + if(H5S_SELECT_GET_SEQ_LIST(file_space, H5S_GET_SEQ_LIST_SORTED, &file_iter, io_info->dxpl_cache->vec_size, nelmts, &file_nseq, &file_nelem, file_off, file_len) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed") + + /* Start at the beginning of the sequences again */ + curr_file_seq = 0; + } /* end if */ + + /* Check if more memory sequences are needed */ + if(curr_mem_seq >= mem_nseq) { + /* Get sequences for memory selection */ + if(H5S_SELECT_GET_SEQ_LIST(mem_space, 0, &mem_iter, io_info->dxpl_cache->vec_size, nelmts, &mem_nseq, &mem_nelem, mem_off, mem_len) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed") + + /* Start at the beginning of the sequences again */ + curr_mem_seq = 0; + } /* end if */ + + /* Perform I/O on memory and file sequences */ + if(io_buf->op_type == H5S_SELECT_READ) { + if((tmp_file_len = (*io_info->ops.readvv)(io_info, + file_nseq, &curr_file_seq, file_len, file_off, + mem_nseq, &curr_mem_seq, mem_len, mem_off, + addr, chunk, io_buf->u.rbuf)) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_READERROR, FAIL, "read error") + } /* end if */ + else { + HDassert(io_buf->op_type == H5S_SELECT_WRITE); + if((tmp_file_len = (*io_info->ops.writevv)(io_info, + file_nseq, &curr_file_seq, file_len, file_off, + mem_nseq, &curr_mem_seq, mem_len, mem_off, + addr, chunk, io_buf->u.wbuf)) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_WRITEERROR, FAIL, "write error") + } /* end else */ + + /* Decrement number of elements left to process */ + HDassert((tmp_file_len % elmt_size) == 0); + nelmts -= (tmp_file_len / elmt_size); + } /* end while */ + } /* end else */ done: /* Release file selection iterator */ - if(file_iter_init) { - if (H5S_SELECT_ITER_RELEASE(&file_iter)<0) - HDONE_ERROR (H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator"); - } /* end if */ + if(file_iter_init) + if(H5S_SELECT_ITER_RELEASE(&file_iter) < 0) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator") /* Release memory selection iterator */ - if(mem_iter_init) { - if (H5S_SELECT_ITER_RELEASE(&mem_iter)<0) - HDONE_ERROR (H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator"); - } /* end if */ + if(mem_iter_init) + if(H5S_SELECT_ITER_RELEASE(&mem_iter) < 0) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator") /* Free vector arrays */ if(io_info->dxpl_cache->vec_size != H5D_IO_VECTOR_SIZE) { - if(file_len!=NULL) - H5FL_SEQ_FREE(size_t,file_len); - if(file_off!=NULL) - H5FL_SEQ_FREE(hsize_t,file_off); - if(mem_len!=NULL) - H5FL_SEQ_FREE(size_t,mem_len); - if(mem_off!=NULL) - H5FL_SEQ_FREE(hsize_t,mem_off); + 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_read() */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5D_select_io() */ /*------------------------------------------------------------------------- - * Function: H5D_select_write + * Function: H5D_select_read * - * Purpose: Writes directly from application memory into a file + * Purpose: Reads directly from file into application memory. * * Return: Non-negative on success/Negative on failure * @@ -575,133 +633,63 @@ done: *------------------------------------------------------------------------- */ herr_t -H5D_select_write(H5D_io_info_t *io_info, +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*/, - const void *buf/*out*/) + void *buf/*out*/) { - 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 file_iter; /* File selection iteration info */ - hbool_t file_iter_init=0; /* File selection iteration info has been initialized */ - hsize_t _mem_off[H5D_IO_VECTOR_SIZE]; /* Array to store sequence offsets in memory */ - hsize_t *mem_off=NULL; /* Pointer to sequence offsets in memory */ - hsize_t _file_off[H5D_IO_VECTOR_SIZE]; /* Array to store sequence offsets in the file */ - hsize_t *file_off=NULL; /* Pointer to sequence offsets in the file */ - size_t _mem_len[H5D_IO_VECTOR_SIZE]; /* Array to store sequence lengths in memory */ - size_t *mem_len=NULL; /* Pointer to sequence lengths in memory */ - size_t _file_len[H5D_IO_VECTOR_SIZE]; /* Array to store sequence lengths in the file */ - size_t *file_len=NULL; /* Pointer to sequence lengths in the file */ - size_t mem_nseq; /* Number of sequences generated in the file */ - size_t file_nseq; /* Number of sequences generated in memory */ - size_t mem_nelem; /* Number of elements used in memory sequences */ - size_t file_nelem; /* Number of elements used in file sequences */ - size_t curr_mem_seq; /* Current memory sequence to operate on */ - size_t curr_file_seq; /* Current file sequence to operate on */ - ssize_t tmp_file_len; /* Temporary number of bytes in file sequence */ - herr_t ret_value=SUCCEED; /* Return value */ + 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); + FUNC_ENTER_NOAPI(H5D_select_read, FAIL) - /* Check args */ - assert(io_info); - assert(io_info->dset); - assert(io_info->store); - assert(TRUE==H5P_isa_class(io_info->dxpl_id,H5P_DATASET_XFER)); - assert(buf); - - /* Allocate the vector I/O arrays */ - if(io_info->dxpl_cache->vec_size != H5D_IO_VECTOR_SIZE) { - if((mem_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((mem_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"); - if((file_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((file_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 { - mem_len=_mem_len; - mem_off=_mem_off; - file_len=_file_len; - file_off=_file_off; - } /* end else */ - - /* Initialize file iterator */ - if (H5S_select_iter_init(&file_iter, file_space, elmt_size)<0) - HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator"); - file_iter_init=1; /* File selection iteration info has been initialized */ - - /* Initialize memory iterator */ - if (H5S_select_iter_init(&mem_iter, mem_space, elmt_size)<0) - HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator"); - mem_iter_init=1; /* Memory selection iteration info has been initialized */ + /* Construct proper I/O operation */ + io_buf.op_type = H5S_SELECT_READ; + io_buf.u.rbuf = buf; - /* Initialize sequence counts */ - curr_mem_seq=curr_file_seq=0; - mem_nseq=file_nseq=0; + /* Call generic selection operation */ + 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") - /* Loop, until all bytes are processed */ - while(nelmts>0) { - /* Check if more file sequences are needed */ - if(curr_file_seq>=file_nseq) { - /* Get sequences for file selection */ - if(H5S_SELECT_GET_SEQ_LIST(file_space,H5S_GET_SEQ_LIST_SORTED,&file_iter,io_info->dxpl_cache->vec_size,nelmts,&file_nseq,&file_nelem,file_off,file_len)<0) - HGOTO_ERROR (H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed"); - - /* Start at the beginning of the sequences again */ - curr_file_seq=0; - } /* end if */ +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5D_select_read() */ - /* Check if more memory sequences are needed */ - if(curr_mem_seq>=mem_nseq) { - /* Get sequences for memory selection */ - if(H5S_SELECT_GET_SEQ_LIST(mem_space,0,&mem_iter,io_info->dxpl_cache->vec_size,nelmts,&mem_nseq,&mem_nelem,mem_off,mem_len)<0) - HGOTO_ERROR (H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed"); + +/*------------------------------------------------------------------------- + * Function: H5D_select_write + * + * Purpose: Writes directly from application memory into a file + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Tuesday, July 23, 2002 + * + *------------------------------------------------------------------------- + */ +herr_t +H5D_select_write(H5D_io_info_t *io_info, + size_t nelmts, size_t elmt_size, + const H5S_t *file_space, const H5S_t *mem_space, + haddr_t addr, void *chunk/*in*/, + const void *buf/*out*/) +{ + H5D_select_buf_t io_buf; /* Selection I/O operation to perform */ + herr_t ret_value = SUCCEED; /* Return value */ - /* Start at the beginning of the sequences again */ - curr_mem_seq=0; - } /* end if */ + FUNC_ENTER_NOAPI(H5D_select_write, FAIL) - /* Write memory sequences into file sequences */ - 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, - addr, chunk, buf))<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_WRITEERROR, FAIL, "write error"); + /* Construct proper I/O operation */ + io_buf.op_type = H5S_SELECT_WRITE; + io_buf.u.wbuf = buf; - /* Decrement number of elements left to process */ - assert((tmp_file_len%elmt_size)==0); - nelmts-=(tmp_file_len/elmt_size); - } /* end while */ + /* Call generic selection operation */ + 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: - /* Release file selection iterator */ - if(file_iter_init) { - if (H5S_SELECT_ITER_RELEASE(&file_iter)<0) - HDONE_ERROR (H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator"); - } /* end if */ - - /* Release memory selection iterator */ - if(mem_iter_init) { - if (H5S_SELECT_ITER_RELEASE(&mem_iter)<0) - HDONE_ERROR (H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator"); - } /* end if */ - - /* 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); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5D_select_write() */ @@ -308,7 +308,7 @@ H5F_get_access_plist(H5F_t *f) /* Copy properties of the file access property list */ if(H5P_set(new_plist, H5F_ACS_META_CACHE_INIT_CONFIG_NAME, &(f->shared->mdc_initCacheCfg)) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set initial meta data cache resize config.") + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set initial metadata cache resize config.") if(H5P_set(new_plist, H5F_ACS_DATA_CACHE_ELMT_SIZE_NAME, &(f->shared->rdcc_nelmts)) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set data cache element size") if(H5P_set(new_plist, H5F_ACS_DATA_CACHE_BYTE_SIZE_NAME, &(f->shared->rdcc_nbytes)) < 0) @@ -321,11 +321,11 @@ H5F_get_access_plist(H5F_t *f) HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set alignment") if(H5P_set(new_plist, H5F_ACS_GARBG_COLCT_REF_NAME, &(f->shared->gc_ref)) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set garbage collect reference") - if(H5P_set(new_plist, H5F_ACS_META_BLOCK_SIZE_NAME, &(f->shared->lf->def_meta_block_size)) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set meta data cache size") + if(H5P_set(new_plist, H5F_ACS_META_BLOCK_SIZE_NAME, &(f->shared->lf->meta_aggr.alloc_size)) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set metadata cache size") if(H5P_set(new_plist, H5F_ACS_SIEVE_BUF_SIZE_NAME, &(f->shared->sieve_buf_size)) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't sieve buffer size") - if(H5P_set(new_plist, H5F_ACS_SDATA_BLOCK_SIZE_NAME, &(f->shared->lf->def_sdata_block_size)) < 0) + if(H5P_set(new_plist, H5F_ACS_SDATA_BLOCK_SIZE_NAME, &(f->shared->lf->sdata_aggr.alloc_size)) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set 'small data' cache size") if(H5P_set(new_plist, H5F_ACS_LATEST_FORMAT_NAME, &(f->shared->latest_format)) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set 'latest format' flag") @@ -882,7 +882,7 @@ H5F_new(H5F_file_t *shared, hid_t fcpl_id, hid_t fapl_id, H5FD_t *lf) if(NULL == (plist = H5I_object(fapl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not file access property list") if(H5P_get(plist, H5F_ACS_META_CACHE_INIT_CONFIG_NAME, &(f->shared->mdc_initCacheCfg)) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get initial meta data cache resize config") + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get initial metadata cache resize config") if(H5P_get(plist, H5F_ACS_DATA_CACHE_ELMT_SIZE_NAME, &(f->shared->rdcc_nelmts)) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get data cache element size") if(H5P_get(plist, H5F_ACS_DATA_CACHE_BYTE_SIZE_NAME, &(f->shared->rdcc_nbytes)) < 0) @@ -900,6 +900,11 @@ H5F_new(H5F_file_t *shared, hid_t fcpl_id, hid_t fapl_id, H5FD_t *lf) if(H5P_get(plist, H5F_ACS_LATEST_FORMAT_NAME, &(f->shared->latest_format)) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get 'latest format' flag") + /* Get the VFD values to cache */ + f->shared->maxaddr = H5FD_get_maxaddr(lf); + if(!H5F_addr_defined(f->shared->maxaddr)) + HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad maximum address from VFD") + /* Bump superblock version if we are to use the latest version of the format */ if(f->shared->latest_format) super_vers = HDF5_SUPERBLOCK_VERSION_LATEST; @@ -924,12 +929,12 @@ H5F_new(H5F_file_t *shared, hid_t fcpl_id, hid_t fapl_id, H5FD_t *lf) } /* end if */ /* - * Create a meta data cache with the specified number of elements. + * Create a metadata cache with the specified number of elements. * The cache might be created with a different number of elements and * the access property list should be updated to reflect that. */ if(SUCCEED != H5AC_create(f, &(f->shared->mdc_initCacheCfg))) - HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create meta data cache") + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create metadata cache") /* Create a metadata cache with modified API along side the regular * version. For now, this is just for testing. Once we get it @@ -1728,7 +1733,7 @@ H5F_flush(H5F_t *f, hid_t dxpl_id, H5F_scope_t scope, unsigned flags) if(H5D_flush(f, dxpl_id, flags) < 0) HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush dataset cache") - /* flush (and invalidate, if requested) the entire meta data cache */ + /* flush (and invalidate, if requested) the entire metadata cache */ H5AC_flags = 0; if((flags & H5F_FLUSH_INVALIDATE) != 0 ) H5AC_flags |= H5AC__FLUSH_INVALIDATE_FLAG; @@ -1743,29 +1748,11 @@ H5F_flush(H5F_t *f, hid_t dxpl_id, H5F_scope_t scope, unsigned flags) * "small data" blocks back to the free lists in the file. */ if(flags & H5F_FLUSH_INVALIDATE) { - if(f->shared->lf->feature_flags & H5FD_FEAT_AGGREGATE_METADATA) { - /* Return the unused portion of the metadata block to a free list */ - if(f->shared->lf->eoma != 0) - if(H5FD_free(f->shared->lf, H5FD_MEM_DEFAULT, dxpl_id, - f->shared->lf->eoma, f->shared->lf->cur_meta_block_size) < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, FAIL, "can't free metadata block") - - /* Reset metadata block information, just in case */ - f->shared->lf->eoma = 0; - f->shared->lf->cur_meta_block_size = 0; - } /* end if */ - - if(f->shared->lf->feature_flags & H5FD_FEAT_AGGREGATE_SMALLDATA) { - /* Return the unused portion of the "small data" block to a free list */ - if(f->shared->lf->eosda != 0) - if(H5FD_free(f->shared->lf, H5FD_MEM_DRAW, dxpl_id, - f->shared->lf->eosda, f->shared->lf->cur_sdata_block_size) < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, FAIL, "can't free 'small data' block") + if(H5FD_aggr_reset(f->shared->lf, &(f->shared->lf->meta_aggr), dxpl_id) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, FAIL, "can't reset metadata block") - /* Reset "small data" block information, just in case */ - f->shared->lf->eosda = 0; - f->shared->lf->cur_sdata_block_size = 0; - } /* end if */ + if(H5FD_aggr_reset(f->shared->lf, &(f->shared->lf->sdata_aggr), dxpl_id) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, FAIL, "can't reset 'small data' block") } /* end if */ /* Write the superblock to disk */ @@ -2479,8 +2466,6 @@ H5F_get_driver_id(const H5F_t *f) * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu> * March 27, 2002 * - * Modifications: - * *------------------------------------------------------------------------- */ herr_t @@ -2490,13 +2475,13 @@ H5F_get_fileno(const H5F_t *f, unsigned long *filenum) FUNC_ENTER_NOAPI(H5F_get_fileno, FAIL) - assert(f); - assert(f->shared); - assert(f->shared->lf); - assert(filenum); + HDassert(f); + HDassert(f->shared); + HDassert(f->shared->lf); + HDassert(filenum); /* Retrieve the file's serial number */ - if(H5FD_get_fileno(f->shared->lf,filenum) < 0) + if(H5FD_get_fileno(f->shared->lf, filenum) < 0) HGOTO_ERROR(H5E_FILE, H5E_BADRANGE, FAIL, "can't retrieve fileno") done: @@ -24,18 +24,25 @@ * file driver layer. */ +/****************/ +/* Module Setup */ +/****************/ + #define H5F_PACKAGE /*suppress error about including H5Fpkg */ +#define H5FD_PACKAGE /*suppress error about including H5FDpkg */ /* Interface initialization */ #define H5_INTERFACE_INIT_FUNC H5FD_init_interface -/* Packages needed by this file */ +/***********/ +/* Headers */ +/***********/ #include "H5private.h" /* Generic Functions */ #include "H5Dprivate.h" /* Datasets */ #include "H5Eprivate.h" /* Error handling */ #include "H5Fpkg.h" /* File access */ -#include "H5FDprivate.h" /* File drivers */ +#include "H5FDpkg.h" /* File Drivers */ #include "H5FDcore.h" /* Files stored entirely in memory */ #include "H5FDfamily.h" /* File families */ #include "H5FDlog.h" /* sec2 driver with I/O logging (for debugging) */ @@ -47,41 +54,50 @@ #include "H5FDwindows.h" /* Windows buffered I/O */ #endif #include "H5FDdirect.h" /* Direct file I/O */ -#include "H5FLprivate.h" /* Free lists */ #include "H5Iprivate.h" /* IDs */ #include "H5MMprivate.h" /* Memory management */ #include "H5Pprivate.h" /* Property lists */ -/* static prototypes */ +/****************/ +/* Local Macros */ +/****************/ + +/* Metadata accumulator controls */ +#define H5FD_ACCUM_THROTTLE 8 +#define H5FD_ACCUM_THRESHOLD 2048 + +/******************/ +/* Local Typedefs */ +/******************/ + + +/********************/ +/* Package Typedefs */ +/********************/ + + +/********************/ +/* Local Prototypes */ +/********************/ static herr_t H5FD_pl_copy(void *(*copy_func)(const void *), size_t pl_size, const void *old_pl, void **copied_pl); static herr_t H5FD_pl_close(hid_t driver_id, herr_t (*free_func)(void *), void *pl); static herr_t H5FD_free_cls(H5FD_class_t *cls); -static haddr_t H5FD_alloc_from_free_list(H5FD_t *file, H5FD_mem_t type, - hsize_t size); -static haddr_t H5FD_alloc_metadata(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, - hsize_t size); -static haddr_t H5FD_alloc_raw(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, - hsize_t size); -static haddr_t H5FD_real_alloc(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size); -static herr_t H5FD_free_freelist(H5FD_t *file); -static haddr_t H5FD_update_eoa(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size); - -/* Declare a free list to manage the H5FD_free_t struct */ -H5FL_DEFINE(H5FD_free_t); - -/* Declare a PQ free list to manage the metadata accumulator buffer */ -H5FL_BLK_DEFINE_STATIC(meta_accum); - -/* Local macro definitions */ -#define H5FD_ACCUM_THROTTLE 8 -#define H5FD_ACCUM_THRESHOLD 2048 -/* Define this to display information about file allocations */ -/* #define H5FD_ALLOC_DEBUG */ +/*********************/ +/* Package Variables */ +/*********************/ + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + -/* Static local variables */ +/*******************/ +/* Local Variables */ +/*******************/ /* * Global count of the number of H5FD_t's handed out. This is used as a @@ -99,6 +115,32 @@ static unsigned long file_serial_no; /*------------------------------------------------------------------------- + * Function: H5FD_init + * + * Purpose: Initialize the interface from some other package. + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: Quincey Koziol + * Thursday, January 3, 2007 + * + *------------------------------------------------------------------------- + */ +herr_t +H5FD_init(void) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5FD_init, FAIL) + /* FUNC_ENTER() does all the work */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD_init() */ + + +/*------------------------------------------------------------------------- * Function: H5FD_init_interface * * Purpose: Initialize the virtual file layer. @@ -1055,10 +1097,12 @@ H5FD_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr) HDmemset(file->fl, 0, sizeof(file->fl)); if(H5P_get(plist, H5F_ACS_META_BLOCK_SIZE_NAME, &(meta_block_size)) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get meta data block size") - file->def_meta_block_size = meta_block_size; + file->meta_aggr.feature_flag = H5FD_FEAT_AGGREGATE_METADATA; + file->meta_aggr.alloc_size = meta_block_size; if(H5P_get(plist, H5F_ACS_SDATA_BLOCK_SIZE_NAME, &(sdata_block_size)) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get 'small data' block size") - file->def_sdata_block_size = sdata_block_size; + file->sdata_aggr.feature_flag = H5FD_FEAT_AGGREGATE_SMALLDATA; + file->sdata_aggr.alloc_size = sdata_block_size; file->accum_loc = HADDR_UNDEF; if(H5P_get(plist, H5F_ACS_ALIGN_THRHD_NAME, &(file->threshold)) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get alignment threshold") @@ -1182,74 +1226,6 @@ done: /*------------------------------------------------------------------------- - * Function: H5FD_free_freelist - * Purpose: Split off from H5FD_close(). Free the elements in the - * free list for this file driver. - * Return: Success: SUCCEED - * Failure: Never fails - * Programmer: Bill Wendling - * 17. February 2003 - * Modifications: - *------------------------------------------------------------------------- - */ -static herr_t -H5FD_free_freelist(H5FD_t *file) -{ - H5FD_mem_t i; -#ifdef H5F_DEBUG - unsigned nblocks = 0; - hsize_t nbytes = 0; -#endif /* H5F_DEBUG */ - - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FD_free_freelist) - - /* check args */ - HDassert(file && file->cls); - - /* - * Free all free-lists, leaking any memory thus described. Also leaks - * file space allocated but not used when metadata aggregation is - * turned on. - */ - for(i = H5FD_MEM_DEFAULT; i < H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t, i)) { - H5FD_free_t *cur, *next; - - for( cur = file->fl[i]; cur; cur = next) { -#ifdef H5F_DEBUG - ++nblocks; - nbytes += cur->size; -#endif /* H5F_DEBUG */ - next = cur->next; - H5FL_FREE(H5FD_free_t, cur); - } /* end for */ - - file->fl[i] = NULL; - } /* end for */ - -#ifdef H5F_DEBUG - if(nblocks && H5DEBUG(F)) - HDfprintf(H5DEBUG(F), - "H5F: leaked %Hu bytes of file memory in %u blocks\n", - nbytes, nblocks); -#endif /* H5F_DEBUG */ - - /* Check if we need to reset the metadata accumulator information */ - if(file->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) { - /* Free the buffer */ - if(file->meta_accum) - file->meta_accum = H5FL_BLK_FREE(meta_accum, file->meta_accum); - - /* Reset the buffer sizes & location */ - file->accum_buf_size = file->accum_size = 0; - file->accum_loc = HADDR_UNDEF; - file->accum_dirty = 0; - } /* end if */ - - FUNC_LEAVE_NOAPI(SUCCEED) -} /* end H5FD_free_freelist() */ - - -/*------------------------------------------------------------------------- * Function: H5FDcmp * * Purpose: Compare the keys of two files using the file driver callback @@ -1481,719 +1457,6 @@ done: /*------------------------------------------------------------------------- - * Function: H5FD_alloc - * Purpose: Private version of H5FDalloc(). - * Return: Success: The format address of the new file memory. - * Failure: The undefined address HADDR_UNDEF - * Programmer: Robb Matzke - * Wednesday, August 4, 1999 - * Modifications: - * Albert Cheng, 2001/05/01 - * Implement the allocation by alignment/threshold. - * - * Bill Wendling, 2002/12/02 - * Split apart into subfunctions for each separate task. - * - * Bill Wendling, 2003/02/19 - * Added support for FPHDF5. - * - * John Mainzer, 2004/04/13 - * Moved much of the FPHDF5 specific code into H5FP_client_alloc(), - * and re-worked it to get rid of a race condition on the eoa. - * - *------------------------------------------------------------------------- - */ -haddr_t -H5FD_alloc(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size) -{ - haddr_t ret_value = HADDR_UNDEF; - - FUNC_ENTER_NOAPI(H5FD_alloc, HADDR_UNDEF) -#ifdef H5FD_ALLOC_DEBUG -HDfprintf(stderr, "%s: type = %u, size = %Hu\n", FUNC, (unsigned)type, size); -#endif /* H5FD_ALLOC_DEBUG */ - - /* check args */ - assert(file); - assert(file->cls); - assert(type >= H5FD_MEM_DEFAULT && type < H5FD_MEM_NTYPES); - assert(size > 0); - -#ifdef H5F_DEBUG - if(H5DEBUG(F)) - HDfprintf(H5DEBUG(F), "%s: alignment=%Hd, threshold=%Hd, size=%Hd\n", - FUNC, file->alignment, file->threshold, size); -#endif /* H5F_DEBUG */ - - /* Try to allocate from the free list first */ - if((ret_value = H5FD_alloc_from_free_list(file, type, size)) != HADDR_UNDEF) - HGOTO_DONE(ret_value) - -#ifdef H5F_DEBUG - if(H5DEBUG(F)) - HDfprintf(H5DEBUG(F), "%s: Could not allocate from freelists\n", FUNC); -#endif /* H5F_DEBUG */ - - if(type != H5FD_MEM_DRAW) { - /* Handle metadata differently from "raw" data */ - if((ret_value = H5FD_alloc_metadata(file, type, dxpl_id, size)) == HADDR_UNDEF) - HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate for metadata") - } else { - /* Allocate "raw" data */ - if((ret_value = H5FD_alloc_raw(file, type, dxpl_id, size)) == HADDR_UNDEF) - HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate for raw data") - } - -done: -#ifdef H5FD_ALLOC_DEBUG -HDfprintf(stderr, "%s: ret_value = %a\n", FUNC, ret_value); -#endif /* H5FD_ALLOC_DEBUG */ - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5FD_alloc() */ - - -/*------------------------------------------------------------------------- - * Function: H5FD_alloc_from_free_list - * Purpose: Try to allocate SIZE bytes of memory from the free list - * if possible. - * - * This is split from H5FD_alloc(). - * Return: Success: The format address of the new file memory. - * Failure: The undefined address HADDR_UNDEF - * Programmer: Bill Wendling - * 02. December, 2002 - * Modifications: - *------------------------------------------------------------------------- - */ -static haddr_t -H5FD_alloc_from_free_list(H5FD_t *file, H5FD_mem_t type, hsize_t size) -{ - H5FD_mem_t mapped_type; - haddr_t ret_value = HADDR_UNDEF; - - FUNC_ENTER_NOAPI(H5FD_alloc_from_free_list, HADDR_UNDEF) -#ifdef H5FD_ALLOC_DEBUG -HDfprintf(stderr, "%s: type = %u, size = %Hu\n", FUNC, (unsigned)type, size); -#endif /* H5FD_ALLOC_DEBUG */ - - assert(file); - assert(type >= H5FD_MEM_DEFAULT && type < H5FD_MEM_NTYPES); - assert(size > 0); - - /* Map the allocation request to a free list */ - if(H5FD_MEM_DEFAULT == file->cls->fl_map[type]) - mapped_type = type; - else - mapped_type = file->cls->fl_map[type]; - - /* - * Try to satisfy the request from the free list. Only perform the - * search if the free list has the potential of satisfying the - * request. - * - * Here, aligned requests are requests that are >= threshold and - * alignment > 1. - * - * For non-aligned request, first try to find an exact match, - * otherwise use the best match which is the smallest size that meets - * the requested size. - * - * For aligned address request, find a block in the following order - * of preferences: - * - * 1. block address is aligned and exact match in size; - * 2. block address is aligned with smallest size > requested size; - * 3. block address is not aligned with smallest size >= requested size. - */ - if(mapped_type >= H5FD_MEM_DEFAULT && (file->maxsize == 0 || size <= file->maxsize)) { - H5FD_free_t *prev = NULL, *best = NULL; - H5FD_free_t *cur = file->fl[mapped_type]; - hbool_t found_aligned = FALSE; - hbool_t need_aligned; - hsize_t head; - - need_aligned = file->alignment > 1 && size >= file->threshold; - - while(cur) { - if(cur->size > file->maxsize) - file->maxsize = cur->size; - - if(need_aligned) { - if((head = cur->addr % file->alignment) == 0) { - /* - * Aligned address - */ - if(cur->size >= size) { - if(cur->size == size) { - /* exact match */ - ret_value = cur->addr; - - /* - * Make certain we don't hand out a block of raw data - * from the free list which overlaps with the metadata - * aggregation buffer (if it's turned on) - */ - if(type == H5FD_MEM_DRAW && - (file->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) && - H5F_addr_overlap(ret_value, size, - file->accum_loc, file->accum_size)) { - ret_value = HADDR_UNDEF; - } else { - if(prev) - prev->next = cur->next; - else - file->fl[mapped_type] = cur->next; - - H5FL_FREE(H5FD_free_t, cur); - - if(size == file->maxsize) - file->maxsize = 0; /*unknown*/ - -#ifdef H5FD_ALLOC_DEBUG -HDfprintf(stderr, "%s: Exact size match (aligned)\n", FUNC); -#endif /* H5FD_ALLOC_DEBUG */ - HGOTO_DONE(ret_value) - } - } - else - /* Favor smallest block, that's closest to the beginning of the file */ - if(!best || !found_aligned || cur->size < best->size || - (cur->size == best->size && H5F_addr_lt(cur->addr, best->addr))) { - best = cur; - found_aligned = TRUE; - } - } /* end if */ - } else { - /* - * Non-aligned address - * - * Check to see if this block is big enough to skip - * to the next aligned address and is still big - * enough for the requested size. The extra - * (cur->size > head) is for preventing unsigned - * underflow. (This could be improved by checking for - * an exact match after excluding the head. Such - * match is as good as the found_aligned case above.) - */ - head = file->alignment - head; /* actual head size */ - - if(!found_aligned && cur->size > head && cur->size-head >= size) { - /* Favor smallest block, that's closest to the beginning of the file */ - if(!best || cur->size < best->size || - (cur->size == best->size && H5F_addr_lt(cur->addr, best->addr))) - best = cur; - } /* end if */ - } /* end else */ - } else { - /* !need_aligned */ - if(cur->size >= size) { - if(cur->size == size) { - /* exact match */ - ret_value = cur->addr; - - /* - * Make certain we don't hand out a block of raw data - * from the free list which overlaps with the metadata - * aggregation buffer (if it's turned on) - */ - if(type == H5FD_MEM_DRAW && - (file->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) && - H5F_addr_overlap(ret_value, size, file->accum_loc, - file->accum_size)) { - ret_value = HADDR_UNDEF; - } else { - if(prev) - prev->next = cur->next; - else - file->fl[mapped_type] = cur->next; - - H5FL_FREE(H5FD_free_t, cur); - - if(size == file->maxsize) - file->maxsize = 0; /*unknown*/ - -#ifdef H5FD_ALLOC_DEBUG -HDfprintf(stderr, "%s: Exact size match (unaligned)\n", FUNC); -#endif /* H5FD_ALLOC_DEBUG */ - HGOTO_DONE(ret_value) - } - } /* end if */ - else { - /* Favor smallest block, that's closest to the beginning of the file */ - if(!best || cur->size < best->size || - (cur->size == best->size && H5F_addr_lt(cur->addr, best->addr))) - best = cur; - } /* end else */ - } /* end if */ - } /* end else */ - - prev = cur; - cur = cur->next; - } /* end while */ - - /* Couldn't find exact match, use best fitting piece found */ - if(best) { -#ifdef H5FD_ALLOC_DEBUG -HDfprintf(stderr, "%s: Splitting %Hu byte sized block\n", FUNC, best->size); -#endif /* H5FD_ALLOC_DEBUG */ - if(best->size == file->maxsize) - file->maxsize = 0; /*unknown*/ - - if(!need_aligned || found_aligned) { - /* free only tail */ - ret_value = best->addr; - - /* - * Make certain we don't hand out a block of raw data - * from the free list which overlaps with the metadata - * aggregation buffer (if it's turned on) - */ - if(type == H5FD_MEM_DRAW && - (file->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) && - H5F_addr_overlap(ret_value, size, file->accum_loc, - file->accum_size)) { - ret_value = HADDR_UNDEF; - } else { - best->addr += size; /* Reduce size of block on free list */ - best->size -= size; - HGOTO_DONE(ret_value) - } - } else { - /* - * Split into 3 pieces. Keep the the head and tail in the - * freelist. - */ - H5FD_free_t *tmp = NULL; - - head = file->alignment - (best->addr % file->alignment); - ret_value = best->addr + head; - - /* - * Make certain we don't hand out a block of raw data - * from the free list which overlaps with the metadata - * aggregation buffer (if it's turned on) - */ - if(type == H5FD_MEM_DRAW && - (file->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) && - H5F_addr_overlap(ret_value, size, file->accum_loc, file->accum_size)) { - ret_value = HADDR_UNDEF; - } else { - /* Attempt to allocate memory for temporary node */ - if((tmp = H5FL_MALLOC(H5FD_free_t))==NULL) - HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF, "free block allocation failed") - - if((tmp->size = (best->size - (head + size)))!=0) { - tmp->addr = best->addr + (head + size); - tmp->next = best->next; - best->next = tmp; - } else { - /* no tail piece */ - H5FL_FREE(H5FD_free_t,tmp); - } - - best->size = head; - HGOTO_DONE(ret_value) - } /* end else */ - } /* end else */ - } /* end if */ - } /* end if */ - -done: -#ifdef H5FD_ALLOC_DEBUG -HDfprintf(stderr, "%s: ret_value = %a\n", FUNC, ret_value); -#endif /* H5FD_ALLOC_DEBUG */ - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5FD_alloc_from_free_list() */ - - -/*------------------------------------------------------------------------- - * Function: H5FD_alloc_metadata - * Purpose: Try to allocate SIZE bytes of memory from the metadata - * block if possible. - * - * This is split from H5FD_alloc(). - * Return: Success: The format address of the new file memory. - * Failure: The undefined address HADDR_UNDEF - * Programmer: Bill Wendling - * 2. December, 2002 - * Modifications: - * - *------------------------------------------------------------------------- - */ -static haddr_t -H5FD_alloc_metadata(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size) -{ - haddr_t ret_value = HADDR_UNDEF; - - FUNC_ENTER_NOAPI(H5FD_alloc_metadata, HADDR_UNDEF) -#ifdef H5FD_ALLOC_DEBUG -HDfprintf(stderr, "%s: type = %u, size = %Hu\n", FUNC, (unsigned)type, size); -#endif /* H5FD_ALLOC_DEBUG */ - - /* check args */ - assert(file); - assert(type >= H5FD_MEM_DEFAULT && type < H5FD_MEM_NTYPES); - assert(size > 0); - - /* - * If the metadata aggregation feature is enabled for this VFL - * driver, allocate "generic" metadata space and sub-allocate out of - * that, if possible. Otherwise just allocate through - * H5FD_real_alloc() - */ - - /* - * Allocate all types of metadata out of the metadata block - */ - if(file->feature_flags & H5FD_FEAT_AGGREGATE_METADATA) { - /* - * Check if the space requested is larger than the space left in - * the block - */ - if(size > file->cur_meta_block_size) { - haddr_t new_meta; /* Address for new metadata */ - - /* - * Check if the block asked for is too large for a metadata - * block - */ - if(size >= file->def_meta_block_size) { - /* Allocate more room for this new block the regular way */ - if(HADDR_UNDEF==(new_meta = H5FD_real_alloc(file, type, dxpl_id, size))) - HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate metadata block") - - /* - * Check if the new metadata is at the end of the current - * metadata block - */ - if(file->eoma + file->cur_meta_block_size == new_meta) { - /* - * Treat the allocation request as if the current - * metadata block grew by the amount allocated and - * just update the eoma address. Don't bother - * updating the cur_meta_block_size since it will - * just grow and shrink by the same amount. - */ - ret_value = file->eoma; - file->eoma += size; - } else { - /* Use the new metadata block for the space allocated */ - ret_value = new_meta; - } - } else { - /* Allocate another metadata block */ -#ifdef H5FD_ALLOC_DEBUG -HDfprintf(stderr, "%s: Allocating 'metadata' block\n", FUNC); -#endif /* H5FD_ALLOC_DEBUG */ - if(HADDR_UNDEF==(new_meta = H5FD_real_alloc(file, H5FD_MEM_DEFAULT, dxpl_id, - file->def_meta_block_size))) - HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate metadata block") - - /* - * Check if the new metadata is at the end of the current - * metadata block - */ - if(file->eoma + file->cur_meta_block_size == new_meta) { - file->cur_meta_block_size += file->def_meta_block_size; - } else { - /* - * Return the unused portion of the metadata block to - * a free list - */ - if(file->eoma != 0) - if(H5FD_free(file, H5FD_MEM_DEFAULT, dxpl_id, file->eoma, - file->cur_meta_block_size) < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "can't free metadata block") - - /* Point the metadata block at the newly allocated block */ - file->eoma = new_meta; - file->cur_meta_block_size = file->def_meta_block_size; - } - - /* Allocate space out of the metadata block */ - ret_value = file->eoma; - file->cur_meta_block_size -= size; - file->eoma += size; - } - } else { - /* Allocate space out of the metadata block */ - ret_value = file->eoma; - file->cur_meta_block_size -= size; - file->eoma += size; - } - } else { - /* Allocate data the regular way */ - if(HADDR_UNDEF==(ret_value = H5FD_real_alloc(file, type, dxpl_id, size))) - HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate metadata block") - } - -done: -#ifdef H5FD_ALLOC_DEBUG -HDfprintf(stderr, "%s: ret_value = %a\n", FUNC, ret_value); -#endif /* H5FD_ALLOC_DEBUG */ - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5FD_alloc_metadata() */ - - -/*------------------------------------------------------------------------- - * Function: H5FD_alloc_raw - * Purpose: Try to allocate SIZE bytes of raw data. - * - * This is split from H5FD_alloc(). - * Return: Success: The format address of the new file memory. - * Failure: The undefined address HADDR_UNDEF - * Programmer: Bill Wendling - * 2. December, 2002 - * Modifications: - *------------------------------------------------------------------------- - */ -static haddr_t -H5FD_alloc_raw(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size) -{ - haddr_t ret_value = HADDR_UNDEF; - - FUNC_ENTER_NOAPI(H5FD_alloc_raw, HADDR_UNDEF) -#ifdef H5FD_ALLOC_DEBUG -HDfprintf(stderr, "%s: type = %u, size = %Hu\n", FUNC, (unsigned)type, size); -#endif /* H5FD_ALLOC_DEBUG */ - - /* check args */ - assert(file); - assert(type >= H5FD_MEM_DEFAULT && type < H5FD_MEM_NTYPES); - assert(size > 0); - - /* - * If the "small data" aggregation feature is enabled for this VFL driver, - * allocate "small data" space and sub-allocate out of that, if - * possible. Otherwise just allocate through H5FD_real_alloc() - */ - if(file->feature_flags & H5FD_FEAT_AGGREGATE_SMALLDATA) { - /* - * Check if the space requested is larger than the space left in - * the block - */ - if(size > file->cur_sdata_block_size) { - haddr_t new_data; /* Address for new raw data block */ - - /* Check if the block asked for is too large for the "small data" block */ - if(size >= file->def_sdata_block_size) { - /* Allocate more room for this new block the regular way */ - if(HADDR_UNDEF==(new_data = H5FD_real_alloc(file, type, dxpl_id, size))) - HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate raw data block") - - /* - * Check if the new raw data is at the end of the current - * "small data" block - */ - if(file->eosda + file->cur_sdata_block_size == new_data) { - /* - * Treat the allocation request as if the current - * "small data" block grew by the amount allocated - * and just update the eosda address. Don't bother - * updating the cur_sdata_block_size since it will - * just grow and shrink by the same amount. - */ - ret_value = file->eosda; - file->eosda += size; - } else { - /* Use the new "small data" block for the space allocated */ - ret_value = new_data; - } - } else { - /* Allocate another "small data" block */ -#ifdef H5FD_ALLOC_DEBUG -HDfprintf(stderr, "%s: Allocating 'small data' block\n", FUNC); -#endif /* H5FD_ALLOC_DEBUG */ - if(HADDR_UNDEF==(new_data = H5FD_real_alloc(file, type, dxpl_id, - file->def_sdata_block_size))) - HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate raw data block") - - /* - * Check if the new raw data is at the end of the current - * "small data" block - */ - if(file->eosda + file->cur_sdata_block_size == new_data) { - file->cur_sdata_block_size += file->def_sdata_block_size; - } else { - /* - * Return the unused portion of the "small data" - * block to a free list - */ - if(file->eosda != 0) - if(H5FD_free(file, H5FD_MEM_DRAW, dxpl_id, file->eosda, - file->cur_sdata_block_size) < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "can't free 'small data' block") - - /* - * Point the "small data" block at the newly - * allocated block - */ - file->eosda = new_data; - file->cur_sdata_block_size = file->def_sdata_block_size; - } - - /* Allocate space out of the "small data" block */ - ret_value = file->eosda; - file->cur_sdata_block_size -= size; - file->eosda += size; - } - } else { - /* Allocate space out of the "small data" block */ - ret_value = file->eosda; - file->cur_sdata_block_size -= size; - file->eosda += size; - } - } else { - /* Allocate data the regular way */ - if(HADDR_UNDEF==(ret_value = H5FD_real_alloc(file, type, dxpl_id, size))) - HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate raw data block") - } - -done: -#ifdef H5FD_ALLOC_DEBUG -HDfprintf(stderr, "%s: ret_value = %a\n", FUNC, ret_value); -#endif /* H5FD_ALLOC_DEBUG */ - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5FD_alloc_raw() */ - - -/*------------------------------------------------------------------------- - * Function: H5FD_real_alloc - * - * Purpose: Double private version of H5FDalloc() :-) - * - * Return: Success: The format address of the new file memory. - * - * Failure: The undefined address HADDR_UNDEF - * - * Programmer: Quincey Koziol - * Friday, August 25, 2000 - * - * Modifications: - * Albert Cheng, 2001/05/01 - * Implement the allocation by alignment/threshold. - * - *------------------------------------------------------------------------- - */ -static haddr_t -H5FD_real_alloc(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size) -{ - haddr_t ret_value = HADDR_UNDEF; - - FUNC_ENTER_NOAPI_NOINIT(H5FD_real_alloc) -#ifdef H5FD_ALLOC_DEBUG -HDfprintf(stderr, "%s: type = %u, size = %Hu\n", FUNC, (unsigned)type, size); -#endif /* H5FD_ALLOC_DEBUG */ - - /* check args */ - assert(file); - assert(file->cls); - assert(type >= H5FD_MEM_DEFAULT && type < H5FD_MEM_NTYPES); - assert(size > 0); - - /* - * Dispatch to driver `alloc' callback or extend the end-of-address - * marker - */ - if(file->cls->alloc) { - if((ret_value = (file->cls->alloc)(file, type, dxpl_id, size)) == HADDR_UNDEF) - HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF, "driver allocation request failed") - } else { - if((ret_value = H5FD_update_eoa(file, type, dxpl_id, size)) == HADDR_UNDEF) - HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF, "driver eoa update request failed") - } - -done: -#ifdef H5FD_ALLOC_DEBUG -HDfprintf(stderr, "%s: ret_value = %a\n", FUNC, ret_value); -#endif /* H5FD_ALLOC_DEBUG */ - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5FD_real_alloc() */ - - -/*------------------------------------------------------------------------- - * Function: H5FD_update_eoa - * Purpose: Update the EOA field of the file's memory. - * - * This was split off from the H5FD_real_alloc function to - * make life easier for all. - * Return: Success: The format address of the new file memory. - * Failure: The undefined address HADDR_UNDEF - * Programmer: Bill Wendling - * Wednesday, 04. December, 2002 - * Modifications: - * - *------------------------------------------------------------------------- - */ -static haddr_t -H5FD_update_eoa(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size) -{ - haddr_t eoa, oldeoa = 0; - hsize_t wasted; - haddr_t ret_value = HADDR_UNDEF; - - FUNC_ENTER_NOAPI_NOINIT(H5FD_update_eoa) - - /* check args */ - assert(file); - assert(file->cls); - assert(type >= H5FD_MEM_DEFAULT && type < H5FD_MEM_NTYPES); - assert(size > 0); - - eoa = file->cls->get_eoa(file, type); - -#ifdef H5F_DEBUG - if(file->alignment * file->threshold != 1 && H5DEBUG(F)) - HDfprintf(H5DEBUG(F), - "%s: alignment=%Hd, threshold=%Hd, size=%Hd, Begin eoa=%a\n", - FUNC, file->alignment, file->threshold, size, eoa); -#endif /* H5F_DEBUG */ - - /* Wasted is 0 if not exceeding threshold or eoa happens to be aligned */ - wasted = (size >= file->threshold) ? (eoa % file->alignment) : 0; - if(wasted) { - wasted = file->alignment - wasted; /* actual waste */ - oldeoa = eoa; /* save it for later freeing */ - - /* Advance eoa to the next alignment by allocating the wasted */ - if(H5F_addr_overflow(eoa, size) || (eoa + wasted) > file->maxaddr) - HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF, "file allocation request failed") - - eoa += wasted; - - if(file->cls->set_eoa(file, type, eoa) < 0) - HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF, "file allocation request failed") - } /* end if */ - - /* allocate the aligned memory */ - if(H5F_addr_overflow(eoa, size) || eoa + size > file->maxaddr) - HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF, "file allocation request failed") - - ret_value = eoa; - eoa += size; - - if(file->cls->set_eoa(file, type, eoa) < 0) - HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF, "file allocation request failed") - - /* Free the wasted memory */ - if(wasted) { - if(H5FD_free(file, type, dxpl_id, oldeoa, wasted) < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "file deallocation request failed") - } /* end if */ - -#ifdef H5F_DEBUG - if(file->alignment * file->threshold != 1 && H5DEBUG(F)) - HDfprintf(H5DEBUG(F), - "%s: ret_value=%a, wasted=%Hd, Ended eoa=%a\n", - FUNC, ret_value, wasted, eoa); -#endif /* H5F_DEBUG */ - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5FD_update_eoa() */ - - -/*------------------------------------------------------------------------- * Function: H5FDfree * * Purpose: Frees format addresses starting with ADDR and continuing for @@ -2243,305 +1506,6 @@ done: /*------------------------------------------------------------------------- - * Function: H5FD_free - * - * Purpose: Private version of H5FDfree() - * - * Return: Success: Non-negative - * - * Failure: Negative - * - * Programmer: Robb Matzke - * Wednesday, August 4, 1999 - * - * Modifications: - * Bill Wendling, February 20, 2003 - * Added support for Flexible PHDF5. If the process is the - * Set-Aside-Process, then we execute this function. Clients - * don't. - * - *------------------------------------------------------------------------- - */ -herr_t -H5FD_free(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, hsize_t size) -{ - H5FD_mem_t mapped_type; - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(H5FD_free, FAIL) -#ifdef H5FD_ALLOC_DEBUG -HDfprintf(stderr, "%s: type = %u, addr = %a, size = %Hu\n", FUNC, (unsigned)type, addr, size); -#endif /* H5FD_ALLOC_DEBUG */ - - /* Check args */ - HDassert(file); - HDassert(file->cls); - HDassert(type >= H5FD_MEM_DEFAULT && type < H5FD_MEM_NTYPES); - - if(!H5F_addr_defined(addr) || addr > file->maxaddr || - H5F_addr_overflow(addr, size) || (addr + size) > file->maxaddr) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid region") - - /* Allow 0-sized free's to occur without penalty */ - if(0 == size) - HGOTO_DONE(SUCCEED) - - /* Map request type to free list */ - if(H5FD_MEM_DEFAULT==file->cls->fl_map[type]) - mapped_type = type; - else - mapped_type = file->cls->fl_map[type]; - - /* - * If the request maps to a free list then add memory to the free list - * without ever telling the driver that it was freed. Otherwise let the - * driver deallocate the memory. - */ - if(mapped_type >= H5FD_MEM_DEFAULT) { - H5FD_free_t *last; /* Last merged node */ - H5FD_free_t *last_prev = NULL;/* Pointer to node before merged node */ - H5FD_free_t *curr; /* Current free block being inspected */ - H5FD_free_t *prev; /* Previous free block being inspected */ - - /* Adjust the metadata accumulator to remove the freed block, if it overlaps */ - if((file->feature_flags&H5FD_FEAT_ACCUMULATE_METADATA) - && H5F_addr_overlap(addr, size, file->accum_loc, file->accum_size)) { - size_t overlap_size; /* Size of overlap with accumulator */ - - /* Check for overlapping the beginning of the accumulator */ - if(H5F_addr_le(addr, file->accum_loc)) { - /* Check for completely overlapping the accumulator */ - if(H5F_addr_ge(addr + size, file->accum_loc + file->accum_size)) { - /* Reset the entire accumulator */ - file->accum_loc=HADDR_UNDEF; - file->accum_size=FALSE; - file->accum_dirty=FALSE; - } /* end if */ - /* Block to free must end within the accumulator */ - else { - size_t new_accum_size; /* Size of new accumulator buffer */ - - /* Calculate the size of the overlap with the accumulator, etc. */ - H5_ASSIGN_OVERFLOW(overlap_size,(addr+size)-file->accum_loc,haddr_t,size_t); - new_accum_size=file->accum_size-overlap_size; - - /* Move the accumulator buffer information to eliminate the freed block */ - HDmemmove(file->meta_accum,file->meta_accum+overlap_size,new_accum_size); - - /* Adjust the accumulator information */ - file->accum_loc+=overlap_size; - file->accum_size=new_accum_size; - } /* end else */ - } /* end if */ - /* Block to free must start within the accumulator */ - else { - /* Calculate the size of the overlap with the accumulator */ - H5_ASSIGN_OVERFLOW(overlap_size,(file->accum_loc+file->accum_size)-addr,haddr_t,size_t); - - /* Block to free is in the middle of the accumulator */ - if(H5F_addr_lt((addr + size), file->accum_loc + file->accum_size)) { - haddr_t tail_addr; - size_t tail_size; - - /* Calculate the address & size of the tail to write */ - tail_addr=addr+size; - H5_ASSIGN_OVERFLOW(tail_size,(file->accum_loc+file->accum_size)-tail_addr,haddr_t,size_t); - - /* Write out the part of the accumulator after the block to free */ - /* (Use the driver's write call directly - to avoid looping back and writing to metadata accumulator) */ - if((file->cls->write)(file, H5FD_MEM_DEFAULT, dxpl_id, tail_addr, tail_size, file->meta_accum+(tail_addr-file->accum_loc)) < 0) - HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "file write request failed") - } /* end if */ - - /* Adjust the accumulator information */ - file->accum_size=file->accum_size-overlap_size; - } /* end else */ - } /* end if */ - - /* Scan through the existing blocks for the mapped type to see if we can extend one */ - curr = file->fl[mapped_type]; - last = prev = NULL; - while(curr != NULL) { - /* Check if the block to free adjoins the start of the current block */ - if((addr + size) == curr->addr) { - /* If we previously found & merged a node, eliminate it from the list & free it */ - if(last != NULL) { - /* Check if there was a previous block in the list */ - if(last_prev != NULL) - /* Eliminate the merged block from the list */ - last_prev->next = last->next; - /* No previous block, this must be the head of the list */ - else - /* Eliminate the merged block from the list */ - file->fl[mapped_type] = last->next; - - /* Check for eliminating the block before the 'current' one */ - if(last == prev) - prev = last_prev; - - /* Free the memory for the merged block */ - H5FL_FREE(H5FD_free_t, last); - } /* end if */ - - /* Adjust the address and size of the block found */ - curr->addr = addr; - curr->size += size; - - /* Adjust the information about to memory block to include the merged block */ - addr = curr->addr; - size = curr->size; - - /* Update the information about the merged node */ - last = curr; - last_prev = prev; - } /* end if */ - else { - /* Check if the block to free adjoins the end of the current block */ - if((curr->addr + curr->size) == addr) { - /* If we previously found & merged a node, eliminate it from the list & free it */ - if(last != NULL) { - /* Check if there was a previous block in the list */ - if(last_prev != NULL) - /* Eliminate the merged block from the list */ - last_prev->next = last->next; - /* No previous block, this must be the head of the list */ - else - /* Eliminate the merged block from the list */ - file->fl[mapped_type] = last->next; - - /* Check for eliminating the block before the 'current' one */ - if(last == prev) - prev = last_prev; - - /* Free the memory for the merged block */ - H5FL_FREE(H5FD_free_t, last); - } /* end if */ - - /* Adjust the size of the block found */ - curr->size += size; - - /* Adjust the information about to memory block to include the merged block */ - addr = curr->addr; - size = curr->size; - - /* Update the information about the merged node */ - last = curr; - last_prev = prev; - } /* end if */ - } /* end else */ - - /* Advance to next node in list */ - prev = curr; - curr = curr->next; - } /* end while */ - - /* Check if we adjusted an existing block */ - if(last != NULL) { - /* Move the node found to the front, if it wasn't already there */ - if(last_prev != NULL) { - last_prev->next = last->next; - last->next = file->fl[mapped_type]; - file->fl[mapped_type] = last; - } /* end if */ - } /* end if */ - else { - /* Allocate a new node to hold the free block's information */ - if(NULL == (last = H5FL_MALLOC(H5FD_free_t))) - HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, FAIL, "can't allocate node for free space info") - - last->addr = addr; - last->size = size; - last->next = file->fl[mapped_type]; - file->fl[mapped_type] = last; - } /* end else */ - - /* Check if we increased the size of the largest block on the list */ - file->maxsize = MAX(file->maxsize, last->size); - - /* Check if this free block adjoins the "metadata aggregator" */ - if(file->feature_flags & H5FD_FEAT_AGGREGATE_METADATA && file->eoma != 0) { - hbool_t adjoins = FALSE; /* Whether the block adjoined the metadata aggregator */ - - /* Does the new block adjoin the end of the metadata aggregator */ - if((file->eoma + file->cur_meta_block_size) == last->addr) { - last->addr = file->eoma; - adjoins = TRUE; - } /* end if */ - /* Does the new block adjoin the beginning of the metadata aggregator */ - else if((last->addr + last->size) == file->eoma) - adjoins = TRUE; - - /* Reset metadata aggregator information, if adjoined */ - if(adjoins) { -#ifdef H5FD_ALLOC_DEBUG -HDfprintf(stderr, "%s: Adjoined metadata aggregator\n", FUNC); -#endif /* H5FD_ALLOC_DEBUG */ - last->size += file->cur_meta_block_size; - file->eoma = 0; - file->cur_meta_block_size = 0; - } /* end if */ - } /* end if */ - - /* Check if this free block adjoins the "small data aggregator" */ - if(file->feature_flags & H5FD_FEAT_AGGREGATE_SMALLDATA && file->eosda != 0) { - hbool_t adjoins = FALSE; /* Whether the block adjoined the small-data aggregator */ - - /* Does the new block adjoin the end of the small-data aggregator */ - if((file->eosda + file->cur_sdata_block_size) == last->addr) { - last->addr = file->eosda; - adjoins = TRUE; - } /* end if */ - /* Does the new block adjoin the beginning of the small-data aggregator */ - else if((last->addr + last->size) == file->eosda) - adjoins = TRUE; - - /* Reset small-data aggregator information, if adjoined */ - if(adjoins) { -#ifdef H5FD_ALLOC_DEBUG -HDfprintf(stderr, "%s: Adjoined small data aggregator\n", FUNC); -#endif /* H5FD_ALLOC_DEBUG */ - last->size += file->cur_sdata_block_size; - file->eosda = 0; - file->cur_sdata_block_size = 0; - } /* end if */ - } /* end if */ - - /* Check if this free block is at the end of file allocated space. - * Truncate it if this is true. */ - if(file->cls->get_eoa) { - haddr_t eoa; - - eoa = file->cls->get_eoa(file, type); - if(eoa == (last->addr + last->size)) { -#ifdef H5FD_ALLOC_DEBUG -HDfprintf(stderr, "%s: Reducing file size to = %a\n", FUNC, last->addr); -#endif /* H5FD_ALLOC_DEBUG */ - if(file->cls->set_eoa(file, type, last->addr) < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "set end of space allocation request failed") - - /* Remove this free block from the list */ - file->fl[mapped_type] = last->next; - if(file->maxsize == last->size) - file->maxsize = 0; /*unknown*/ - H5FL_FREE(H5FD_free_t, last); - } /* end if */ - } /* end if */ - } else if(file->cls->free) { - if((file->cls->free)(file, type, dxpl_id, addr, size) < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver free request failed") - } else { - /* leak memory */ -#ifdef H5F_DEBUG -HDfprintf(stderr, "%s: LEAKED MEMORY!!! type = %u, addr = %a, size = %Hu\n", FUNC, (unsigned)type, addr, size); -#endif /* H5F_DEBUG */ - } /* end else */ - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5FD_free() */ - - -/*------------------------------------------------------------------------- * Function: H5FDrealloc * * Purpose: Changes the size of an allocated chunk of memory, possibly @@ -2584,318 +1548,6 @@ done: /*------------------------------------------------------------------------- - * Function: H5FD_realloc - * - * Purpose: Private version of H5FDrealloc() - * - * Return: Success: New address of the block of memory, not - * necessarily the same as the original address. - * - * Failure: HADDR_UNDEF - * - * Programmer: Robb Matzke - * Wednesday, August 4, 1999 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -haddr_t -H5FD_realloc(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t old_addr, hsize_t old_size, - hsize_t new_size) -{ - haddr_t new_addr=old_addr; - uint8_t _buf[8192]; - uint8_t *buf=_buf; - haddr_t ret_value; /* Return value */ - - FUNC_ENTER_NOAPI(H5FD_realloc, HADDR_UNDEF) - - if(new_size == old_size) { - /*nothing to do*/ - } else if(0 == old_size) { - /* allocate memory */ - HDassert(!H5F_addr_defined(old_addr)); - if(HADDR_UNDEF == (new_addr = H5FD_alloc(file, type, dxpl_id, new_size))) - HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, HADDR_UNDEF, "file allocation failed") - } else if(0==new_size) { - /* free memory */ - HDassert(H5F_addr_defined(old_addr)); - if(H5FD_free(file, type, dxpl_id, old_addr, old_size) < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "file deallocation request failed") - new_addr = HADDR_UNDEF; - } else if(new_size<old_size) { - /* free the end of the block */ - if(H5FD_free(file, type, dxpl_id, old_addr+old_size, old_size-new_size) < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "file deallocation request failed") - } else { - /* move memory to new location */ - /* Note! This may fail if sizeof(hsize_t)>sizeof(size_t) and the - * object on disk is too large to read into a memory buffer all at one - * time. This chunk of code would have to be re-written using a loop - * to move pieces of the realloced data through a fixed size buffer, etc. - * -QAK, 6/20/01 - */ - if(HADDR_UNDEF == (new_addr = H5FD_alloc(file, type, dxpl_id, new_size))) - HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, HADDR_UNDEF, "file allocation failed") - H5_CHECK_OVERFLOW(old_size,hsize_t,size_t); - if(old_size > sizeof(_buf) && NULL == (buf = H5MM_malloc((size_t)old_size))) { - (void)H5FD_free(file, type, dxpl_id, new_addr, new_size); - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, HADDR_UNDEF, "memory allocation failed") - } /* end if */ - if(H5FD_read(file, type, dxpl_id, old_addr, (size_t)old_size, buf) < 0 || - H5FD_write(file, type, dxpl_id, new_addr, (size_t)old_size, buf) < 0) { - (void)H5FD_free(file, type, dxpl_id, new_addr, new_size); - if(buf != _buf) - H5MM_xfree(buf); - HGOTO_ERROR(H5E_FILE, H5E_READERROR, HADDR_UNDEF, "unable to move file block") - } /* end if */ - - if(buf != _buf) - H5MM_xfree(buf); - if(H5FD_free(file, type, dxpl_id, old_addr, old_size) < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "file deallocation request failed") - } /* end else */ - - /* Set return value */ - ret_value = new_addr; - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5FD_realloc() */ - - -/*------------------------------------------------------------------------- - * Function: H5FD_can_extend - * - * Purpose: Check if a block in the file can be extended. - * - * Return: Success: TRUE(1)/FALSE(0) - * - * Failure: FAIL - * - * Programmer: Quincey Koziol - * Friday, June 11, 2004 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -htri_t -H5FD_can_extend(const H5FD_t *file, H5FD_mem_t type, haddr_t addr, hsize_t size, hsize_t extra_requested) -{ - haddr_t eoa; /* End of address space in the file */ - htri_t ret_value=FALSE; /* Return value */ - - FUNC_ENTER_NOAPI(H5FD_can_extend, FAIL) - - /* Retrieve the end of the address space */ - if(HADDR_UNDEF==(eoa=H5FD_get_eoa(file, type))) - HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver get_eoa request failed") - - /* Check if the block is exactly at the end of the file */ - if((addr+size)==eoa) - HGOTO_DONE(TRUE) - else { - H5FD_free_t *curr; /* Current free block being inspected */ - H5FD_mem_t mapped_type; /* Memory type, after mapping */ - haddr_t end; /* End of block in file */ - - /* Map request type to free list */ - if(H5FD_MEM_DEFAULT==file->cls->fl_map[type]) - mapped_type = type; - else - mapped_type = file->cls->fl_map[type]; - - /* Check if block is inside the metadata or small data accumulator */ - if(mapped_type!=H5FD_MEM_DRAW) { - if(file->feature_flags & H5FD_FEAT_AGGREGATE_METADATA) { - /* If the metadata block is at the end of the file, and - * the block to test adjoins the beginning of the metadata - * block, then it's extendable - */ - if(file->eoma + file->cur_meta_block_size == eoa && - (addr+size)==file->eoma) - HGOTO_DONE(TRUE) - } /* end if */ - } /* end if */ - else { - if(file->feature_flags & H5FD_FEAT_AGGREGATE_SMALLDATA) { - /* If the small data block is at the end of the file, and - * the block to test adjoins the beginning of the small data - * block, then it's extendable - */ - if(file->eosda + file->cur_sdata_block_size == eoa && - (addr+size)==file->eosda) - HGOTO_DONE(TRUE) - } /* end if */ - } /* end else */ - - /* Scan through the existing blocks for the mapped type to see if we can extend one */ - if(mapped_type >= H5FD_MEM_DEFAULT) { - curr = file->fl[mapped_type]; - end = addr + size; - while(curr != NULL) { - if(end == curr->addr) { - if(extra_requested <= curr->size) - HGOTO_DONE(TRUE) - else - HGOTO_DONE(FALSE) - } /* end if */ - - /* Advance to next node in list */ - curr=curr->next; - } /* end while */ - } /* end if */ - } /* end else */ - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5FD_can_extend() */ - - -/*------------------------------------------------------------------------- - * Function: H5FD_extend - * - * Purpose: Extend a block in the file. - * - * Return: Success: Non-negative - * - * Failure: Negative - * - * Programmer: Quincey Koziol - * Saturday, June 12, 2004 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -herr_t -H5FD_extend(H5FD_t *file, H5FD_mem_t type, haddr_t addr, hsize_t size, hsize_t extra_requested) -{ - haddr_t eoa; /* End of address space in the file */ - haddr_t end; /* End of block in file */ - hbool_t update_eoma=FALSE; /* Whether we need to update the eoma */ - hbool_t update_eosda=FALSE; /* Whether we need to update the eosda */ - hbool_t at_end=FALSE; /* Block is at end of file */ - H5FD_mem_t mapped_type; /* Memory type, after mapping */ - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(H5FD_extend, FAIL) -#ifdef H5FD_ALLOC_DEBUG -HDfprintf(stderr, "%s: type = %u, addr = %a, size = %Hu, extra_requested = %Hu\n", FUNC, (unsigned)type, addr, size, extra_requested); -#endif /* H5FD_ALLOC_DEBUG */ - - /* Retrieve the end of the address space */ - if(HADDR_UNDEF==(eoa=H5FD_get_eoa(file, type))) - HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver get_eoa request failed") - - /* Map request type to free list */ - if(H5FD_MEM_DEFAULT==file->cls->fl_map[type]) - mapped_type = type; - else - mapped_type = file->cls->fl_map[type]; - - /* Compute end of block */ - end = addr + size; - - /* Check if the block is exactly at the end of the file */ - if(end == eoa) - at_end = TRUE; - else { - /* (Check if block is inside the metadata or small data accumulator) */ - if(mapped_type!=H5FD_MEM_DRAW) { - if(file->feature_flags & H5FD_FEAT_AGGREGATE_METADATA) - /* If the metadata block is at the end of the file, and - * the block to test adjoins the beginning of the metadata - * block, then it's extendable - */ - if((file->eoma + file->cur_meta_block_size) == eoa && - end == file->eoma) - update_eoma=TRUE; - } /* end if */ - else { - if(file->feature_flags & H5FD_FEAT_AGGREGATE_SMALLDATA) - /* If the small data block is at the end of the file, and - * the block to test adjoins the beginning of the small data - * block, then it's extendable - */ - if((file->eosda + file->cur_sdata_block_size) == eoa && - end == file->eosda) - update_eosda=TRUE; - } /* end else */ - } /* end else */ - - /* Block is at end of file, we are extending the eoma or eosda */ - if(update_eoma || update_eosda || at_end) { - /* Check for overflowing the file */ - if(H5F_addr_overflow(eoa, extra_requested) || eoa + extra_requested > file->maxaddr) - HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, FAIL, "file allocation request failed") - - /* Extend the file */ - eoa += extra_requested; - if(file->cls->set_eoa(file, type, eoa) < 0) - HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, FAIL, "file allocation request failed") - - /* Update the metadata and/or small data block */ - assert(!(update_eoma && update_eosda)); - if(update_eoma) - file->eoma+=extra_requested; - if(update_eosda) - file->eosda+=extra_requested; - } /* end if */ - /* If the block we are extending isn't at the end of the file, find a free block to extend into */ - else { - H5FD_free_t *curr; /* Current free block being inspected */ - H5FD_free_t *prev; /* Current free block being inspected */ - - /* Walk through free list, looking for block to merge with */ - curr = file->fl[mapped_type]; - prev = NULL; - while(curr!=NULL) { - /* Found block that ajoins end of block to extend */ - if(end == curr->addr) { - /* Check if free space is large enough */ - if(extra_requested <= curr->size) { - /* Check for exact match */ - if(extra_requested == curr->size) { - /* Unlink node from free list */ - if(prev == NULL) - file->fl[mapped_type] = curr->next; - else - prev->next = curr->next; - - /* Free the memory for the used block */ - H5FL_FREE(H5FD_free_t, curr); - } /* end if */ - else { - curr->addr += extra_requested; - curr->size -= extra_requested; - } /* end else */ - - /* Leave now */ - break; - } /* end if */ - else - HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, FAIL, "can't extend block") - } /* end if */ - - /* Advance to next node in list */ - prev = curr; - curr = curr->next; - } /* end while */ - - /* Couldn't find block to extend */ - if(curr == NULL) - HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, FAIL, "can't extend block") - } /* end else */ - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5FD_extend() */ - - -/*------------------------------------------------------------------------- * Function: H5FDget_eoa * * Purpose: Returns the address of the first byte after the last @@ -3154,6 +1806,36 @@ done: /*------------------------------------------------------------------------- + * Function: H5FD_get_maxaddr + * + * Purpose: Private version of H5FDget_eof() + * + * Return: Success: The maximum address allowed in the file. + * Failure: HADDR_UNDEF + * + * Programmer: Quincey Koziol + * Thursday, January 3, 2008 + * + *------------------------------------------------------------------------- + */ +haddr_t +H5FD_get_maxaddr(const H5FD_t *file) +{ + haddr_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5FD_get_maxaddr, HADDR_UNDEF) + + HDassert(file); + + /* Set return value */ + ret_value = file->maxaddr; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD_get_maxaddr() */ + + +/*------------------------------------------------------------------------- * Function: H5FDread * * Purpose: Reads SIZE bytes from FILE beginning at address ADDR @@ -3795,22 +2477,20 @@ done: * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu> * March 27, 2002 * - * Modifications: - * *------------------------------------------------------------------------- */ herr_t H5FD_get_fileno(const H5FD_t *file, unsigned long *filenum) { - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5FD_get_fileno, FAIL) - assert(file); - assert(filenum); + HDassert(file); + HDassert(filenum); /* Retrieve the file's serial number */ - HDmemcpy(filenum,&file->fileno,sizeof(file->fileno)); + *filenum = file->fileno; done: FUNC_LEAVE_NOAPI(ret_value) @@ -3883,103 +2563,3 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5FD_get_vfd_handle() */ - -/*------------------------------------------------------------------------- - * Function: H5FD_get_freespace - * - * Purpose: Retrieve the amount of free space in a file. - * - * Return: Success: Amount of free space in file - * Failure: Negative - * - * Programmer: Quincey Koziol - * Monday, October 6, 2003 - * - * Modifications: - * Raymond Lu - * 5 January 2007 - * Due to the complexity EOA for Multi driver, this function - * is made failed for now. - * - *------------------------------------------------------------------------- - */ -hssize_t -H5FD_get_freespace(const H5FD_t *file) -{ - H5FD_free_t *free_node; /* Pointer to node on free list */ - H5FD_mem_t type; /* Type of memory */ - haddr_t ma_addr = HADDR_UNDEF; /* Base "metadata aggregator" address */ - hsize_t ma_size = 0; /* Size of "metadata aggregator" */ - haddr_t sda_addr = HADDR_UNDEF; /* Base "small data aggregator" address */ - hsize_t sda_size = 0; /* Size of "small data aggregator" */ - haddr_t eoa = 0; /* End of allocated space in the file */ - hssize_t ret_value = 0; /* Return value */ - - FUNC_ENTER_NOAPI(H5FD_get_freespace, FAIL) - - /* check args */ - HDassert(file); - HDassert(file->cls); - - /* Multi driver doesn't support this function because of the complexity. - * It doesn't have eoa for the whole file. */ - if(file->driver_id == H5FD_MULTI) - HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "Multi driver doesn't support this function") - - /* Retrieve the 'eoa' for the file */ - eoa = file->cls->get_eoa(file, H5FD_MEM_DEFAULT); - - /* Check for aggregating metadata allocations */ - if(file->feature_flags & H5FD_FEAT_AGGREGATE_METADATA) { - ma_addr = file->eoma; - ma_size = file->cur_meta_block_size; - } /* end if */ - - /* Check for aggregating small data allocations */ - if(file->feature_flags & H5FD_FEAT_AGGREGATE_SMALLDATA) { - sda_addr = file->eosda; - sda_size = file->cur_sdata_block_size; - } /* end if */ - - /* Iterate over all the types of memory, to retrieve amount of free space for each */ - for(type = H5FD_MEM_DEFAULT; type < H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t,type)) { - /* Iterate through the free list, accumulating the amount of free space for this type */ - free_node = file->fl[type]; - while(free_node) { - /* Check for current node adjoining the metadata & small data aggregators */ - if(H5F_addr_eq(free_node->addr + free_node->size, ma_addr)) { - ma_addr -= free_node->size; - ma_size += free_node->size; - } else if(H5F_addr_eq(free_node->addr + free_node->size, sda_addr)) { - sda_addr -= free_node->size; - sda_size += free_node->size; - } else if(H5F_addr_eq(ma_addr + ma_size, free_node->addr)) - ma_size += free_node->size; - else if(H5F_addr_eq(sda_addr + sda_size, free_node->addr)) - sda_size += free_node->size; - else - ret_value += (hssize_t)free_node->size; - free_node = free_node->next; - } /* end while */ - } /* end for */ - - /* Check for aggregating metadata allocations */ - if(H5F_addr_defined(ma_addr)) { - /* Add in the reserved space for metadata to the available free space */ - /* (if it's not at the tail of the file) */ - if(H5F_addr_ne(ma_addr + ma_size, eoa)) - ret_value += ma_size; - } /* end if */ - - /* Check for aggregating small data allocations */ - if(H5F_addr_defined(sda_addr)) { - /* Add in the reserved space for metadata to the available free space */ - /* (if it's not at the tail of the file) */ - if(H5F_addr_ne(sda_addr + sda_size, eoa)) - ret_value += sda_size; - } /* end if */ - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5FD_get_freespace() */ - diff --git a/src/H5FDlog.c b/src/H5FDlog.c index 3109e09..df07c0a 100644 --- a/src/H5FDlog.c +++ b/src/H5FDlog.c @@ -234,7 +234,11 @@ static const H5FD_class_t H5FD_log_g = { H5FD_log_flush, /*flush */ NULL, /*lock */ NULL, /*unlock */ +#ifdef OLD_WAY H5FD_FLMAP_NOLIST /*fl_map */ +#else /* OLD_WAY */ + H5FD_FLMAP_SINGLE /*fl_map */ +#endif /* OLD_WAY */ }; diff --git a/src/H5FDmpio.c b/src/H5FDmpio.c index 5d5f092..c8087bb 100644 --- a/src/H5FDmpio.c +++ b/src/H5FDmpio.c @@ -322,13 +322,13 @@ H5Pset_fapl_mpio(hid_t fapl_id, MPI_Comm comm, MPI_Info info) FUNC_ENTER_API(H5Pset_fapl_mpio, FAIL) H5TRACE3("e", "iMcMi", fapl_id, comm, info); - if(fapl_id==H5P_DEFAULT) + if(fapl_id == H5P_DEFAULT) HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "can't set values in default property list") /* Check arguments */ - if(NULL == (plist = H5P_object_verify(fapl_id,H5P_FILE_ACCESS))) + if(NULL == (plist = (H5P_genplist_t *)H5P_object_verify(fapl_id, H5P_FILE_ACCESS))) HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a file access list") - if (MPI_COMM_NULL == comm) + if(MPI_COMM_NULL == comm) HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a valid communicator") /* Initialize driver specific properties */ @@ -393,11 +393,11 @@ H5Pget_fapl_mpio(hid_t fapl_id, MPI_Comm *comm/*out*/, MPI_Info *info/*out*/) FUNC_ENTER_API(H5Pget_fapl_mpio, FAIL) H5TRACE3("e", "ixx", fapl_id, comm, info); - if(NULL == (plist = H5P_object_verify(fapl_id,H5P_FILE_ACCESS))) + if(NULL == (plist = (H5P_genplist_t *)H5P_object_verify(fapl_id, H5P_FILE_ACCESS))) HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a file access list") - if (H5FD_MPIO!=H5P_get_driver(plist)) + if(H5FD_MPIO != H5P_get_driver(plist)) HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "incorrect VFL driver") - if (NULL==(fa=H5P_get_driver_info(plist))) + if(NULL == (fa = (H5FD_mpio_fapl_t *)H5P_get_driver_info(plist))) HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "bad VFL driver info") /* Store the duplicated communicator in a temporary variable for error */ @@ -471,9 +471,9 @@ H5Pset_dxpl_mpio(hid_t dxpl_id, H5FD_mpio_xfer_t xfer_mode) HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "can't set values in default property list") /* Check arguments */ - if(NULL == (plist = H5P_object_verify(dxpl_id,H5P_DATASET_XFER))) + if(NULL == (plist = (H5P_genplist_t *)H5P_object_verify(dxpl_id, H5P_DATASET_XFER))) HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a dxpl") - if (H5FD_MPIO_INDEPENDENT!=xfer_mode && H5FD_MPIO_COLLECTIVE!=xfer_mode) + if(H5FD_MPIO_INDEPENDENT != xfer_mode && H5FD_MPIO_COLLECTIVE != xfer_mode) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "incorrect xfer_mode") /* Set the transfer mode */ @@ -517,9 +517,9 @@ H5Pget_dxpl_mpio(hid_t dxpl_id, H5FD_mpio_xfer_t *xfer_mode/*out*/) FUNC_ENTER_API(H5Pget_dxpl_mpio, FAIL) H5TRACE2("e", "ix", dxpl_id, xfer_mode); - if(NULL == (plist = H5P_object_verify(dxpl_id,H5P_DATASET_XFER))) + if(NULL == (plist = (H5P_genplist_t *)H5P_object_verify(dxpl_id, H5P_DATASET_XFER))) HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a dxpl") - if (H5FD_MPIO!=H5P_get_driver(plist)) + if(H5FD_MPIO != H5P_get_driver(plist)) HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "incorrect VFL driver") /* Get the transfer mode */ @@ -563,13 +563,12 @@ H5Pset_dxpl_mpio_collective_opt(hid_t dxpl_id, H5FD_mpio_collective_opt_t opt_mo FUNC_ENTER_API(H5Pset_dxpl_mpio_collective_opt, FAIL) H5TRACE2("e", "iDc", dxpl_id, opt_mode); -/* H5TRACE2("e","iDt",dxpl_id,xfer_mode);*/ - if(dxpl_id==H5P_DEFAULT) + if(dxpl_id == H5P_DEFAULT) HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "can't set values in default property list") /* Check arguments */ - if(NULL == (plist = H5P_object_verify(dxpl_id,H5P_DATASET_XFER))) + if(NULL == (plist = (H5P_genplist_t *)H5P_object_verify(dxpl_id, H5P_DATASET_XFER))) HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a dxpl") /* Set the transfer mode */ @@ -616,13 +615,12 @@ H5Pset_dxpl_mpio_chunk_opt(hid_t dxpl_id, H5FD_mpio_chunk_opt_t opt_mode) FUNC_ENTER_API(H5Pset_dxpl_mpio_chunk_opt, FAIL) H5TRACE2("e", "iDh", dxpl_id, opt_mode); -/* H5TRACE2("e","iDt",dxpl_id,xfer_mode);*/ - if(dxpl_id==H5P_DEFAULT) + if(dxpl_id == H5P_DEFAULT) HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "can't set values in default property list") /* Check arguments */ - if(NULL == (plist = H5P_object_verify(dxpl_id,H5P_DATASET_XFER))) + if(NULL == (plist = (H5P_genplist_t *)H5P_object_verify(dxpl_id, H5P_DATASET_XFER))) HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a dxpl") /* Set the transfer mode */ @@ -666,11 +664,11 @@ H5Pset_dxpl_mpio_chunk_opt_num(hid_t dxpl_id, unsigned num_chunk_per_proc) FUNC_ENTER_API(H5Pset_dxpl_mpio_chunk_opt_num, FAIL) H5TRACE2("e", "iIu", dxpl_id, num_chunk_per_proc); - if(dxpl_id==H5P_DEFAULT) + if(dxpl_id == H5P_DEFAULT) HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "can't set values in default property list") /* Check arguments */ - if(NULL == (plist = H5P_object_verify(dxpl_id,H5P_DATASET_XFER))) + if(NULL == (plist = (H5P_genplist_t *)H5P_object_verify(dxpl_id, H5P_DATASET_XFER))) HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a dxpl") /* Set the transfer mode */ @@ -713,11 +711,11 @@ H5Pset_dxpl_mpio_chunk_opt_ratio(hid_t dxpl_id, unsigned percent_num_proc_per_ch FUNC_ENTER_API(H5Pset_dxpl_mpio_chunk_opt_ratio, FAIL) H5TRACE2("e", "iIu", dxpl_id, percent_num_proc_per_chunk); - if(dxpl_id==H5P_DEFAULT) + if(dxpl_id == H5P_DEFAULT) HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "can't set values in default property list") /* Check arguments */ - if(NULL == (plist = H5P_object_verify(dxpl_id,H5P_DATASET_XFER))) + if(NULL == (plist = (H5P_genplist_t *)H5P_object_verify(dxpl_id, H5P_DATASET_XFER))) HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a dxpl") /* Set the transfer mode */ @@ -761,19 +759,18 @@ H5FD_mpio_fapl_get(H5FD_t *_file) FUNC_ENTER_NOAPI(H5FD_mpio_fapl_get, NULL) - assert(file); - assert(H5FD_MPIO==file->pub.driver_id); + HDassert(file); + HDassert(H5FD_MPIO == file->pub.driver_id); - if (NULL==(fa=H5MM_calloc(sizeof(H5FD_mpio_fapl_t)))) + if(NULL == (fa = (H5FD_mpio_fapl_t *)H5MM_calloc(sizeof(H5FD_mpio_fapl_t)))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") /* Duplicate communicator and Info object. */ - if (FAIL==H5FD_mpi_comm_info_dup(file->comm, file->info, - &fa->comm, &fa->info)) + if(FAIL == H5FD_mpi_comm_info_dup(file->comm, file->info, &fa->comm, &fa->info)) HGOTO_ERROR(H5E_INTERNAL, H5E_CANTCOPY, NULL, "Communicator/Info duplicate failed") /* Set return value */ - ret_value=fa; + ret_value = fa; done: FUNC_LEAVE_NOAPI(ret_value) @@ -809,15 +806,14 @@ if (H5FD_mpio_Debug[(int)'t']) fprintf(stderr, "enter H5FD_mpio_fapl_copy\n"); #endif - if (NULL==(new_fa=H5MM_malloc(sizeof(H5FD_mpio_fapl_t)))) + if(NULL == (new_fa = (H5FD_mpio_fapl_t *)H5MM_malloc(sizeof(H5FD_mpio_fapl_t)))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") /* Copy the general information */ HDmemcpy(new_fa, old_fa, sizeof(H5FD_mpio_fapl_t)); /* Duplicate communicator and Info object. */ - if (FAIL==H5FD_mpi_comm_info_dup(old_fa->comm, old_fa->info, - &new_fa->comm, &new_fa->info)) + if(FAIL == H5FD_mpi_comm_info_dup(old_fa->comm, old_fa->info, &new_fa->comm, &new_fa->info)) HGOTO_ERROR(H5E_INTERNAL, H5E_CANTCOPY, NULL, "Communicator/Info duplicate failed") ret_value = new_fa; @@ -956,14 +952,14 @@ H5FD_mpio_open(const char *name, unsigned flags, hid_t fapl_id, #endif /* Obtain a pointer to mpio-specific file access properties */ - if(NULL == (plist = H5P_object_verify(fapl_id,H5P_FILE_ACCESS))) + if(NULL == (plist = (H5P_genplist_t *)H5P_object_verify(fapl_id, H5P_FILE_ACCESS))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list") - if (H5P_FILE_ACCESS_DEFAULT==fapl_id || H5FD_MPIO!=H5P_get_driver(plist)) { + if(H5P_FILE_ACCESS_DEFAULT == fapl_id || H5FD_MPIO != H5P_get_driver(plist)) { _fa.comm = MPI_COMM_SELF; /*default*/ _fa.info = MPI_INFO_NULL; /*default*/ fa = &_fa; } else { - fa = H5P_get_driver_info(plist); + fa = (const H5FD_mpio_fapl_t *)H5P_get_driver_info(plist); assert(fa); } @@ -998,7 +994,7 @@ H5FD_mpio_open(const char *name, unsigned flags, hid_t fapl_id, #endif /*OKAY: CAST DISCARDS CONST*/ - if (MPI_SUCCESS != (mpi_code=MPI_File_open(comm_dup, (char*)name, mpi_amode, info_dup, &fh))) + if(MPI_SUCCESS != (mpi_code = MPI_File_open(comm_dup, (char*)name, mpi_amode, info_dup, &fh))) HMPI_GOTO_ERROR(NULL, "MPI_File_open failed", mpi_code) file_opened=1; @@ -1009,7 +1005,7 @@ H5FD_mpio_open(const char *name, unsigned flags, hid_t fapl_id, HMPI_GOTO_ERROR(NULL, "MPI_Comm_size failed", mpi_code) /* Build the return value and initialize it */ - if (NULL==(file=H5MM_calloc(sizeof(H5FD_mpio_t)))) + if(NULL == (file = (H5FD_mpio_t *)H5MM_calloc(sizeof(H5FD_mpio_t)))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") file->f = fh; file->comm = comm_dup; @@ -1034,7 +1030,7 @@ H5FD_mpio_open(const char *name, unsigned flags, hid_t fapl_id, } /* end if */ /* Broadcast file size */ - if (MPI_SUCCESS != (mpi_code=MPI_Bcast(&size, sizeof(MPI_Offset), MPI_BYTE, 0, comm_dup))) + if(MPI_SUCCESS != (mpi_code = MPI_Bcast(&size, (int)sizeof(MPI_Offset), MPI_BYTE, 0, comm_dup))) HMPI_GOTO_ERROR(NULL, "MPI_Bcast failed", mpi_code) /* Determine if the file should be truncated */ @@ -1454,9 +1450,9 @@ H5FD_mpio_read(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t dxpl_id, haddr_t add H5FD_mpio_xfer_t xfer_mode; /* I/O tranfer mode */ /* Obtain the data transfer properties */ - if(NULL == (plist = H5I_object(dxpl_id))) + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list") - xfer_mode=(H5FD_mpio_xfer_t)H5P_peek_unsigned(plist, H5D_XFER_IO_XFER_MODE_NAME); + xfer_mode = (H5FD_mpio_xfer_t)H5P_peek_unsigned(plist, H5D_XFER_IO_XFER_MODE_NAME); /* * Set up for a fancy xfer using complex types, or single byte block. We @@ -1499,10 +1495,10 @@ H5FD_mpio_read(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t dxpl_id, haddr_t add fprintf(stdout, "H5FD_mpio_read: 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); + 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 @@ -1528,10 +1524,10 @@ H5FD_mpio_read(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t dxpl_id, haddr_t add * 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, 0, MPI_BYTE, MPI_BYTE, H5FD_mpi_native_g, file->info))) + 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) } else { - if (MPI_SUCCESS!= (mpi_code=MPI_File_read_at(file->f, mpi_off, buf, size_i, buf_type, &mpi_stat))) + 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) } @@ -1738,7 +1734,7 @@ H5FD_mpio_write(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, #endif /* Obtain the data transfer properties */ - if(NULL == (plist = H5I_object(dxpl_id))) + 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) { @@ -1830,15 +1826,12 @@ H5FD_mpio_write(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, 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); - - + 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 && xfer_opt_mode == H5FD_MPIO_COLLECTIVE_IO ) { #ifdef H5FDmpio_DEBUG if (H5FD_mpio_Debug[(int)'t']) @@ -1865,11 +1858,11 @@ if (MPI_SUCCESS != (mpi_code=MPI_File_write_at_all(file->f, mpi_off, (void*)buf, * 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, 0, MPI_BYTE, MPI_BYTE, H5FD_mpi_native_g, file->info))) + 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) } else { /*OKAY: CAST DISCARDS CONST QUALIFIER*/ - if (MPI_SUCCESS != (mpi_code=MPI_File_write_at(file->f, mpi_off, (void*)buf, size_i, buf_type, &mpi_stat))) + 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) } @@ -1908,8 +1901,8 @@ done: /* 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, sizeof(ret_value), MPI_BYTE, H5_PAR_META_WRITE, file->comm))) + 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 */ diff --git a/src/H5FDpkg.h b/src/H5FDpkg.h new file mode 100644 index 0000000..700ec1d --- /dev/null +++ b/src/H5FDpkg.h @@ -0,0 +1,67 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Programmer: Quincey Koziol <koziol@hdfgroup.org> + * Thursday, January 3, 2008 + * + * Purpose: This file contains declarations which are visible only within + * the H5FD package. Source files outside the H5FD package should + * include H5FDprivate.h instead. + */ +#ifndef H5FD_PACKAGE +#error "Do not include this file outside the H5FD package!" +#endif + +#ifndef _H5FDpkg_H +#define _H5FDpkg_H + +/* Get package's private header */ +#include "H5FDprivate.h" /* File drivers */ + +/* Other private headers needed by this file */ +#include "H5FLprivate.h" /* Free lists */ + +/**************************/ +/* Package Private Macros */ +/**************************/ + + +/****************************/ +/* Package Private Typedefs */ +/****************************/ + + +/*****************************/ +/* Package Private Variables */ +/*****************************/ + +/* Declare a PQ free list to manage the metadata accumulator buffer */ +H5FL_BLK_EXTERN(meta_accum); + + +/******************************/ +/* Package Private Prototypes */ +/******************************/ +H5_DLL herr_t H5FD_init(void); +H5_DLL herr_t H5FD_free_freelist(H5FD_t *file); + + +/* Testing routines */ +#ifdef H5FD_TESTING +#endif /* H5FD_TESTING */ + +#endif /* _H5FDpkg_H */ + diff --git a/src/H5FDprivate.h b/src/H5FDprivate.h index 202b7d1..4c8c28e 100644 --- a/src/H5FDprivate.h +++ b/src/H5FDprivate.h @@ -62,6 +62,7 @@ H5_DLL haddr_t H5FD_realloc(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_ H5_DLL haddr_t H5FD_get_eoa(const H5FD_t *file, H5FD_mem_t type); H5_DLL herr_t H5FD_set_eoa(H5FD_t *file, H5FD_mem_t type, haddr_t addr); H5_DLL haddr_t H5FD_get_eof(const H5FD_t *file); +H5_DLL haddr_t H5FD_get_maxaddr(const H5FD_t *file); H5_DLL herr_t H5FD_read(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t size, void *buf/*out*/); H5_DLL herr_t H5FD_write(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t size, @@ -74,5 +75,7 @@ H5_DLL htri_t H5FD_can_extend(const H5FD_t *file, H5FD_mem_t type, haddr_t addr, hsize_t size, hsize_t extra_requested); H5_DLL herr_t H5FD_extend(H5FD_t *file, H5FD_mem_t type, haddr_t addr, hsize_t size, hsize_t extra_requested); +H5_DLL herr_t H5FD_aggr_reset(H5FD_t *file, H5FD_blk_aggr_t *aggr, hid_t dxpl_id); #endif /* !_H5FDprivate_H */ + diff --git a/src/H5FDpublic.h b/src/H5FDpublic.h index b68f141..839c8a3 100644 --- a/src/H5FDpublic.h +++ b/src/H5FDpublic.h @@ -229,6 +229,15 @@ typedef struct H5FD_free_t { struct H5FD_free_t *next; } H5FD_free_t; +/* Structure for metadata & "small [raw] data" block aggregation fields */ +typedef struct H5FD_blk_aggr_t { + unsigned long feature_flag; /* Feature flag type */ + hsize_t alloc_size; /* Size for allocating new blocks */ + hsize_t tot_size; /* Total amount of bytes aggregated into block */ + hsize_t size; /* Current size of block left */ + haddr_t addr; /* Location of block left */ +} H5FD_blk_aggr_t; + /* * The main datatype for each driver. Public fields common to all drivers * are declared here and the driver appends private fields in memory. @@ -241,27 +250,11 @@ struct H5FD_t { hsize_t threshold; /* Threshold for alignment */ hsize_t alignment; /* Allocation alignment */ - /* Metadata aggregation fields */ - hsize_t def_meta_block_size; /* Metadata allocation - * block size (if - * aggregating metadata) */ - hsize_t cur_meta_block_size; /* Current size of metadata - * allocation region left */ - haddr_t eoma; /* End of metadata - * allocated region */ - /* (ie. beginning of space available) */ - - /* "Small data" aggregation fields */ - hsize_t def_sdata_block_size; /* "Small data" - * allocation block size - * (if aggregating "small - * data") */ - hsize_t cur_sdata_block_size; /* Current size of "small - * data" allocation - * region left */ - haddr_t eosda; /* End of "small data" - * allocated region */ - /* (ie. beginning of space available) */ + /* Block aggregation info */ + H5FD_blk_aggr_t meta_aggr; /* Metadata aggregation info */ + /* (if aggregating metadata allocations) */ + H5FD_blk_aggr_t sdata_aggr; /* "Small data" aggregation info */ + /* (if aggregating "small data" allocations) */ /* Metadata accumulator fields */ unsigned char *meta_accum; /* Buffer to hold the accumulated metadata */ @@ -311,3 +304,4 @@ H5_DLL herr_t H5FDflush(H5FD_t *file, hid_t dxpl_id, unsigned closing); } #endif #endif + diff --git a/src/H5FDspace.c b/src/H5FDspace.c new file mode 100644 index 0000000..7bd72cc --- /dev/null +++ b/src/H5FDspace.c @@ -0,0 +1,1738 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/*------------------------------------------------------------------------- + * + * Created: H5FDspace.c + * Jan 3 2008 + * Quincey Koziol <koziol@hdfgroup.org> + * + * Purpose: Space allocation routines for the file. + * + *------------------------------------------------------------------------- + */ + +/****************/ +/* Module Setup */ +/****************/ + +#define H5FD_PACKAGE /*suppress error about including H5FDpkg */ + +/* Interface initialization */ +#define H5_INTERFACE_INIT_FUNC H5FD_space_init_interface + + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5Fprivate.h" /* File access */ +#include "H5FDpkg.h" /* File Drivers */ +#include "H5FDmulti.h" /* Usage-partitioned file family */ +#include "H5MMprivate.h" /* Memory management */ + + +/****************/ +/* Local Macros */ +/****************/ + +/* Define this to display information about file allocations */ +/* #define H5FD_ALLOC_DEBUG */ + + +/******************/ +/* Local Typedefs */ +/******************/ + + +/********************/ +/* Package Typedefs */ +/********************/ + + +/********************/ +/* Local Prototypes */ +/********************/ +static haddr_t H5FD_alloc_from_free_list(H5FD_t *file, H5FD_mem_t type, + hsize_t size); +static haddr_t H5FD_aggr_alloc(H5FD_t *file, H5FD_blk_aggr_t *aggr, + H5FD_blk_aggr_t *other_aggr, H5FD_mem_t type, hid_t dxpl_id, hsize_t size); +static herr_t H5FD_aggr_adjoin(const H5FD_t *file, H5FD_blk_aggr_t *aggr, + H5FD_free_t *last); +static htri_t H5FD_aggr_can_extend(const H5FD_t *file, const H5FD_blk_aggr_t *aggr, + haddr_t eoa, haddr_t end); +static herr_t H5FD_aggr_shift(H5FD_blk_aggr_t *aggr, hsize_t extra); +static herr_t H5FD_aggr_query(const H5FD_t *file, const H5FD_blk_aggr_t *aggr, + haddr_t *addr, hsize_t *size); +static haddr_t H5FD_real_alloc(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size); +static haddr_t H5FD_update_eoa(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size); + + +/*********************/ +/* Package Variables */ +/*********************/ + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + +/* Declare a free list to manage the H5FD_free_t struct */ +H5FL_DEFINE(H5FD_free_t); + +/* Declare a PQ free list to manage the metadata accumulator buffer */ +H5FL_BLK_DEFINE(meta_accum); + + + +/*-------------------------------------------------------------------------- +NAME + H5FD_space_init_interface -- Initialize interface-specific information +USAGE + herr_t H5FD_space_init_interface() + +RETURNS + Non-negative on success/Negative on failure +DESCRIPTION + Initializes any interface-specific data or routines. (Just calls + H5FD_init_iterface currently). + +--------------------------------------------------------------------------*/ +static herr_t +H5FD_space_init_interface(void) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FD_space_init_interface) + + FUNC_LEAVE_NOAPI(H5FD_init()) +} /* H5FD_space_init_interface() */ + + +/*------------------------------------------------------------------------- + * Function: H5FD_free_freelist + * + * Purpose: Split off from H5FD_close(). Free the elements in the + * free list for this file driver. + * + * Return: Success: SUCCEED + * Failure: Never fails + * + * Programmer: Bill Wendling + * 17. February 2003 + * + *------------------------------------------------------------------------- + */ +herr_t +H5FD_free_freelist(H5FD_t *file) +{ + H5FD_mem_t i; +#ifdef H5FD_ALLOC_DEBUG + unsigned nblocks = 0; + hsize_t nbytes = 0; +#endif /* H5FD_ALLOC_DEBUG */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FD_free_freelist) + + /* check args */ + HDassert(file && file->cls); + + /* + * Free all free-lists, leaking any memory thus described. Also leaks + * file space allocated but not used when metadata aggregation is + * turned on. + */ + for(i = H5FD_MEM_DEFAULT; i < H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t, i)) { + H5FD_free_t *cur, *next; + + for( cur = file->fl[i]; cur; cur = next) { +#ifdef H5FD_ALLOC_DEBUG + ++nblocks; + nbytes += cur->size; +#endif /* H5FD_ALLOC_DEBUG */ + next = cur->next; + H5FL_FREE(H5FD_free_t, cur); + } /* end for */ + + file->fl[i] = NULL; + } /* end for */ + +#ifdef H5FD_ALLOC_DEBUG + if(nblocks) + HDfprintf(stderr, "%s: leaked %Hu bytes of file memory in %u blocks\n", + "H5FD_free_freelist", nbytes, nblocks); +#endif /* H5FD_ALLOC_DEBUG */ + + /* Check if we need to reset the metadata accumulator information */ + if(file->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) { + /* Free the buffer */ + if(file->meta_accum) + file->meta_accum = H5FL_BLK_FREE(meta_accum, file->meta_accum); + + /* Reset the buffer sizes & location */ + file->accum_buf_size = file->accum_size = 0; + file->accum_loc = HADDR_UNDEF; + file->accum_dirty = 0; + } /* end if */ + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5FD_free_freelist() */ + + +/*------------------------------------------------------------------------- + * Function: H5FD_alloc + * + * Purpose: Private version of H5FDalloc(). + * + * Return: Success: The format address of the new file memory. + * Failure: The undefined address HADDR_UNDEF + * + * Programmer: Robb Matzke + * Wednesday, August 4, 1999 + * + *------------------------------------------------------------------------- + */ +haddr_t +H5FD_alloc(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size) +{ + haddr_t ret_value = HADDR_UNDEF; + + FUNC_ENTER_NOAPI(H5FD_alloc, HADDR_UNDEF) +#ifdef H5FD_ALLOC_DEBUG +HDfprintf(stderr, "%s: type = %u, size = %Hu\n", FUNC, (unsigned)type, size); +#endif /* H5FD_ALLOC_DEBUG */ + + /* check args */ + assert(file); + assert(file->cls); + assert(type >= H5FD_MEM_DEFAULT && type < H5FD_MEM_NTYPES); + assert(size > 0); + +#ifdef H5F_DEBUG + if(H5DEBUG(F)) + HDfprintf(H5DEBUG(F), "%s: alignment=%Hd, threshold=%Hd, size=%Hd\n", + FUNC, file->alignment, file->threshold, size); +#endif /* H5F_DEBUG */ + + /* Try to allocate from the free list first */ + if((ret_value = H5FD_alloc_from_free_list(file, type, size)) != HADDR_UNDEF) + HGOTO_DONE(ret_value) + +#ifdef H5F_DEBUG + if(H5DEBUG(F)) + HDfprintf(H5DEBUG(F), "%s: Could not allocate from freelists\n", FUNC); +#endif /* H5F_DEBUG */ + + if(type != H5FD_MEM_DRAW) { + /* Handle metadata differently from "raw" data */ + if(HADDR_UNDEF == (ret_value = H5FD_aggr_alloc(file, &(file->meta_aggr), &(file->sdata_aggr), type, dxpl_id, size))) + HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate metadata") + } /* end if */ + else { + /* Allocate "raw" data */ + if(HADDR_UNDEF == (ret_value = H5FD_aggr_alloc(file, &(file->sdata_aggr), &(file->meta_aggr), type, dxpl_id, size))) + HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate raw data") + } /* end else */ + +done: +#ifdef H5FD_ALLOC_DEBUG +HDfprintf(stderr, "%s: ret_value = %a\n", FUNC, ret_value); +#endif /* H5FD_ALLOC_DEBUG */ + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD_alloc() */ + + +/*------------------------------------------------------------------------- + * Function: H5FD_alloc_from_free_list + * + * Purpose: Try to allocate SIZE bytes of memory from the free list + * if possible. + * + * This is split from H5FD_alloc(). + * + * Return: Success: The format address of the new file memory. + * Failure: The undefined address HADDR_UNDEF + * + * Programmer: Bill Wendling + * 02. December, 2002 + * + *------------------------------------------------------------------------- + */ +static haddr_t +H5FD_alloc_from_free_list(H5FD_t *file, H5FD_mem_t type, hsize_t size) +{ + H5FD_mem_t mapped_type; + haddr_t ret_value = HADDR_UNDEF; + + FUNC_ENTER_NOAPI(H5FD_alloc_from_free_list, HADDR_UNDEF) +#ifdef H5FD_ALLOC_DEBUG +HDfprintf(stderr, "%s: type = %u, size = %Hu\n", FUNC, (unsigned)type, size); +#endif /* H5FD_ALLOC_DEBUG */ + + assert(file); + assert(type >= H5FD_MEM_DEFAULT && type < H5FD_MEM_NTYPES); + assert(size > 0); + + /* Map the allocation request to a free list */ + if(H5FD_MEM_DEFAULT == file->cls->fl_map[type]) + mapped_type = type; + else + mapped_type = file->cls->fl_map[type]; + + /* + * Try to satisfy the request from the free list. Only perform the + * search if the free list has the potential of satisfying the + * request. + * + * Here, aligned requests are requests that are >= threshold and + * alignment > 1. + * + * For non-aligned request, first try to find an exact match, + * otherwise use the best match which is the smallest size that meets + * the requested size. + * + * For aligned address request, find a block in the following order + * of preferences: + * + * 1. block address is aligned and exact match in size; + * 2. block address is aligned with smallest size > requested size; + * 3. block address is not aligned with smallest size >= requested size. + */ + if(mapped_type >= H5FD_MEM_DEFAULT && (file->maxsize == 0 || size <= file->maxsize)) { + H5FD_free_t *prev = NULL, *best = NULL; + H5FD_free_t *cur = file->fl[mapped_type]; + hbool_t found_aligned = FALSE; + hbool_t need_aligned; + hsize_t head; + + need_aligned = file->alignment > 1 && size >= file->threshold; + + while(cur) { + if(cur->size > file->maxsize) + file->maxsize = cur->size; + + if(need_aligned) { + if((head = cur->addr % file->alignment) == 0) { + /* + * Aligned address + */ + if(cur->size >= size) { + if(cur->size == size) { + /* exact match */ + ret_value = cur->addr; + + /* + * Make certain we don't hand out a block of raw data + * from the free list which overlaps with the metadata + * aggregation buffer (if it's turned on) + */ + if(type == H5FD_MEM_DRAW && + (file->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) && + H5F_addr_overlap(ret_value, size, + file->accum_loc, file->accum_size)) { + ret_value = HADDR_UNDEF; + } else { + if(prev) + prev->next = cur->next; + else + file->fl[mapped_type] = cur->next; + + H5FL_FREE(H5FD_free_t, cur); + + if(size == file->maxsize) + file->maxsize = 0; /*unknown*/ + +#ifdef H5FD_ALLOC_DEBUG +HDfprintf(stderr, "%s: Exact size match (aligned)\n", FUNC); +#endif /* H5FD_ALLOC_DEBUG */ + HGOTO_DONE(ret_value) + } + } + else + /* Favor smallest block, that's closest to the beginning of the file */ + if(!best || !found_aligned || cur->size < best->size || + (cur->size == best->size && H5F_addr_lt(cur->addr, best->addr))) { + best = cur; + found_aligned = TRUE; + } + } /* end if */ + } else { + /* + * Non-aligned address + * + * Check to see if this block is big enough to skip + * to the next aligned address and is still big + * enough for the requested size. The extra + * (cur->size > head) is for preventing unsigned + * underflow. (This could be improved by checking for + * an exact match after excluding the head. Such + * match is as good as the found_aligned case above.) + */ + head = file->alignment - head; /* actual head size */ + + if(!found_aligned && cur->size > head && cur->size-head >= size) { + /* Favor smallest block, that's closest to the beginning of the file */ + if(!best || cur->size < best->size || + (cur->size == best->size && H5F_addr_lt(cur->addr, best->addr))) + best = cur; + } /* end if */ + } /* end else */ + } else { + /* !need_aligned */ + if(cur->size >= size) { + if(cur->size == size) { + /* exact match */ + ret_value = cur->addr; + + /* + * Make certain we don't hand out a block of raw data + * from the free list which overlaps with the metadata + * aggregation buffer (if it's turned on) + */ + if(type == H5FD_MEM_DRAW && + (file->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) && + H5F_addr_overlap(ret_value, size, file->accum_loc, + file->accum_size)) { + ret_value = HADDR_UNDEF; + } else { + if(prev) + prev->next = cur->next; + else + file->fl[mapped_type] = cur->next; + + H5FL_FREE(H5FD_free_t, cur); + + if(size == file->maxsize) + file->maxsize = 0; /*unknown*/ + +#ifdef H5FD_ALLOC_DEBUG +HDfprintf(stderr, "%s: Exact size match (unaligned)\n", FUNC); +#endif /* H5FD_ALLOC_DEBUG */ + HGOTO_DONE(ret_value) + } + } /* end if */ + else { + /* Favor smallest block, that's closest to the beginning of the file */ + if(!best || cur->size < best->size || + (cur->size == best->size && H5F_addr_lt(cur->addr, best->addr))) + best = cur; + } /* end else */ + } /* end if */ + } /* end else */ + + prev = cur; + cur = cur->next; + } /* end while */ + + /* Couldn't find exact match, use best fitting piece found */ + if(best) { +#ifdef H5FD_ALLOC_DEBUG +HDfprintf(stderr, "%s: Splitting %Hu byte sized block\n", FUNC, best->size); +#endif /* H5FD_ALLOC_DEBUG */ + if(best->size == file->maxsize) + file->maxsize = 0; /*unknown*/ + + if(!need_aligned || found_aligned) { + /* free only tail */ + ret_value = best->addr; + + /* + * Make certain we don't hand out a block of raw data + * from the free list which overlaps with the metadata + * aggregation buffer (if it's turned on) + */ + if(type == H5FD_MEM_DRAW && + (file->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) && + H5F_addr_overlap(ret_value, size, file->accum_loc, + file->accum_size)) { + ret_value = HADDR_UNDEF; + } else { + best->addr += size; /* Reduce size of block on free list */ + best->size -= size; + HGOTO_DONE(ret_value) + } + } else { + /* + * Split into 3 pieces. Keep the the head and tail in the + * freelist. + */ + H5FD_free_t *tmp = NULL; + + head = file->alignment - (best->addr % file->alignment); + ret_value = best->addr + head; + + /* + * Make certain we don't hand out a block of raw data + * from the free list which overlaps with the metadata + * aggregation buffer (if it's turned on) + */ + if(type == H5FD_MEM_DRAW && + (file->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) && + H5F_addr_overlap(ret_value, size, file->accum_loc, file->accum_size)) { + ret_value = HADDR_UNDEF; + } else { + /* Attempt to allocate memory for temporary node */ + if((tmp = H5FL_MALLOC(H5FD_free_t))==NULL) + HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF, "free block allocation failed") + + if((tmp->size = (best->size - (head + size)))!=0) { + tmp->addr = best->addr + (head + size); + tmp->next = best->next; + best->next = tmp; + } else { + /* no tail piece */ + H5FL_FREE(H5FD_free_t,tmp); + } + + best->size = head; + HGOTO_DONE(ret_value) + } /* end else */ + } /* end else */ + } /* end if */ + } /* end if */ + +done: +#ifdef H5FD_ALLOC_DEBUG +HDfprintf(stderr, "%s: ret_value = %a\n", FUNC, ret_value); +#endif /* H5FD_ALLOC_DEBUG */ + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD_alloc_from_free_list() */ + + +/*------------------------------------------------------------------------- + * Function: H5FD_aggr_alloc + * + * Purpose: Try to allocate SIZE bytes of memory from an aggregator + * block if possible. + * + * This is split from H5FD_alloc(). + * + * Return: Success: The format address of the new file memory. + * Failure: The undefined address HADDR_UNDEF + * + * Programmer: Bill Wendling + * 2. December, 2002 + * + *------------------------------------------------------------------------- + */ +static haddr_t +H5FD_aggr_alloc(H5FD_t *file, H5FD_blk_aggr_t *aggr, H5FD_blk_aggr_t *other_aggr, + H5FD_mem_t type, hid_t dxpl_id, hsize_t size) +{ + haddr_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5FD_aggr_alloc) +#ifdef H5FD_ALLOC_DEBUG +HDfprintf(stderr, "%s: type = %u, size = %Hu\n", FUNC, (unsigned)type, size); +#endif /* H5FD_ALLOC_DEBUG */ + + /* check args */ + HDassert(file); + HDassert(aggr); + HDassert(aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA || aggr->feature_flag == H5FD_FEAT_AGGREGATE_SMALLDATA); + HDassert(other_aggr); + HDassert(other_aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA || other_aggr->feature_flag == H5FD_FEAT_AGGREGATE_SMALLDATA); + HDassert(other_aggr->feature_flag != aggr->feature_flag); + HDassert(type >= H5FD_MEM_DEFAULT && type < H5FD_MEM_NTYPES); + HDassert(size > 0); + + /* + * If the aggregation feature is enabled for this VFL + * driver, allocate "generic" space and sub-allocate out of + * that, if possible. Otherwise just allocate through + * H5FD_real_alloc() + */ + if(file->feature_flags & aggr->feature_flag) { +#ifdef H5FD_ALLOC_DEBUG +HDfprintf(stderr, "%s: aggr = {%a, %Hu, %Hu}\n", FUNC, aggr->addr, aggr->tot_size, aggr->size); +#endif /* H5FD_ALLOC_DEBUG */ + /* Check if the space requested is larger than the space left in the block */ + if(size > aggr->size) { + haddr_t new_space; /* Address for newly allocated space */ + + /* Check if the block asked for is too large for 'normal' aggregator block */ + if(size >= aggr->alloc_size) { + /* Allocate more room for this new block the regular way */ + if(HADDR_UNDEF == (new_space = H5FD_real_alloc(file, type, dxpl_id, size))) + HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate aggregation block") + + /* Check if the new space is at the end of the current block */ + if((aggr->addr + aggr->size) == new_space) { + /* + * Treat the allocation request as if the current block + * grew by the amount allocated and just update the address. + * + * Don't bother updating the block's size since it will + * just grow and shrink by the same amount. + * + * _Do_ add to the total size aggregated. + * + */ + ret_value = aggr->addr; + aggr->addr += size; + aggr->tot_size += size; + } /* end if */ + else { + /* Check if the new space is at the end of the _other_ block */ + if(other_aggr->size > 0 && (other_aggr->addr + other_aggr->size) == new_space) { +#ifdef H5FD_ALLOC_DEBUG +HDfprintf(stderr, "%s: New block is at end of 'other' block: other_aggr = {%a, %Hu, %Hu}\n", FUNC, other_aggr->addr, other_aggr->tot_size, other_aggr->size); +#endif /* H5FD_ALLOC_DEBUG */ + /* If the other block has used at least the + * 'allocation' amount for that block, shift the + * newly allocated space down over the remainder + * in the 'other block', shift the 'other block' + * up by the same amount and free it. (Which + * should amount to "bubbling" the remainder in + * the 'other block' to the end of the file and + * then "popping" the bubble by shrinking the + * file) + */ + if((other_aggr->tot_size - other_aggr->size) >= other_aggr->alloc_size) { + H5FD_mem_t alloc_type = (other_aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA ? H5FD_MEM_DEFAULT : H5FD_MEM_DRAW); /* Type of file memory to work with */ + haddr_t free_addr = (new_space + size) - other_aggr->size; /* Address of free space in 'other block' shifted toward end of the file */ + hsize_t free_size = other_aggr->size; /* Size of the free space in 'other block' */ + +#ifdef H5FD_ALLOC_DEBUG +HDfprintf(stderr, "%s: Freeing 'other' block\n", FUNC); +#endif /* H5FD_ALLOC_DEBUG */ + /* Reset 'other' block's info */ + other_aggr->addr = 0; + other_aggr->tot_size = 0; + other_aggr->size = 0; + + /* Shift newly allocated space down */ + new_space -= free_size; + + /* Return the unused portion of the 'other' block to a free list */ + if(H5FD_free(file, alloc_type, dxpl_id, free_addr, free_size) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "can't free aggregation block") + } /* end if */ + } /* end if */ + + /* Use the new space allocated, leaving the old block */ + ret_value = new_space; + } /* end else */ + } /* end if */ + else { + H5FD_mem_t alloc_type = (aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA ? H5FD_MEM_DEFAULT : H5FD_MEM_DRAW); /* Type of file memory to work with */ + + /* Allocate another block */ +#ifdef H5FD_ALLOC_DEBUG +HDfprintf(stderr, "%s: Allocating block\n", FUNC); +#endif /* H5FD_ALLOC_DEBUG */ + if(HADDR_UNDEF == (new_space = H5FD_real_alloc(file, alloc_type, dxpl_id, aggr->alloc_size))) + HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate aggregation block") + + /* Check if the new space is at the end of the current block */ + if(aggr->addr + aggr->size == new_space) { + aggr->size += aggr->alloc_size; + aggr->tot_size += aggr->alloc_size; + } /* end if */ + else { + hsize_t new_size; /* Size of new aggregator block */ + + /* Return the unused portion of the block to a free list */ + if(aggr->size > 0) + if(H5FD_free(file, alloc_type, dxpl_id, aggr->addr, aggr->size) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "can't free aggregation block") + + /* Check if the new space is at the end of the _other_ block */ + if(other_aggr->size > 0 && (other_aggr->addr + other_aggr->size) == new_space) { +#ifdef H5FD_ALLOC_DEBUG +HDfprintf(stderr, "%s: New block is at end of 'other' block: other_aggr = {%a, %Hu, %Hu}\n", FUNC, other_aggr->addr, other_aggr->tot_size, other_aggr->size); +#endif /* H5FD_ALLOC_DEBUG */ +#ifdef QAK + /* If the other block has used at least the + * 'allocation' amount for that block, give the + * remaining free space in the 'other' block to + * the new space allocated for 'this' block. + */ + if((other_aggr->tot_size - other_aggr->size) >= other_aggr->alloc_size) { +#ifdef H5FD_ALLOC_DEBUG +HDfprintf(stderr, "%s: Absorbing 'other' block\n", FUNC); +#endif /* H5FD_ALLOC_DEBUG */ + /* Absorb the remaining free space into newly allocated block */ + new_space -= other_aggr->size; + new_size = aggr->alloc_size + other_aggr->size; + + /* Reset the info for the 'other' block */ + other_aggr->addr = 0; + other_aggr->tot_size = 0; + other_aggr->size = 0; + } /* end if */ + else + new_size = aggr->alloc_size; +#else /* QAK */ + /* If the other block has used at least the + * 'allocation' amount for that block, shift the + * newly allocated space down over the remainder + * in the 'other block', shift the 'other block' + * up by the same amount and free it. (Which + * should amount to "bubbling" the remainder in + * the 'other block' to the end of the file and + * then "popping" the bubble by shrinking the + * file) + */ + if((other_aggr->tot_size - other_aggr->size) >= other_aggr->alloc_size) { + H5FD_mem_t other_type = (other_aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA ? H5FD_MEM_DEFAULT : H5FD_MEM_DRAW); /* Type of file memory to work with */ + haddr_t free_addr = (new_space + aggr->alloc_size) - other_aggr->size; /* Address of free space in 'other block' shifted toward end of the file */ + hsize_t free_size = other_aggr->size; /* Size of the free space in 'other block' */ + +#ifdef H5FD_ALLOC_DEBUG +HDfprintf(stderr, "%s: Freeing 'other' block\n", FUNC); +#endif /* H5FD_ALLOC_DEBUG */ + /* Reset 'other' block's info */ + other_aggr->addr = 0; + other_aggr->tot_size = 0; + other_aggr->size = 0; + + /* Shift newly allocated space down */ + new_space -= free_size; + + /* Return the unused portion of the 'other' block to a free list */ + if(H5FD_free(file, other_type, dxpl_id, free_addr, free_size) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "can't free aggregation block") + } /* end if */ + new_size = aggr->alloc_size; +#endif /* QAK */ + } /* end if */ + else + new_size = aggr->alloc_size; + + /* Point the aggregator at the newly allocated block */ + aggr->addr = new_space; + aggr->size = new_size; + aggr->tot_size = new_size; + } /* end else */ + + /* Allocate space out of the metadata block */ + ret_value = aggr->addr; + aggr->size -= size; + aggr->addr += size; + } /* end else */ + } /* end if */ + else { + /* Allocate space out of the block */ + ret_value = aggr->addr; + aggr->size -= size; + aggr->addr += size; + } + } /* end if */ + else { + /* Allocate data the regular way */ + if(HADDR_UNDEF == (ret_value = H5FD_real_alloc(file, type, dxpl_id, size))) + HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate file space") + } /* end else */ + +done: +#ifdef H5FD_ALLOC_DEBUG +HDfprintf(stderr, "%s: ret_value = %a\n", FUNC, ret_value); +#endif /* H5FD_ALLOC_DEBUG */ + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD_aggr_alloc() */ + + +/*------------------------------------------------------------------------- + * Function: H5FD_aggr_adjoin + * + * Purpose: Check if a newly freed block of space in the file adjoins an + * aggregator block + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * Thursday, December 13, 2007 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5FD_aggr_adjoin(const H5FD_t *file, H5FD_blk_aggr_t *aggr, H5FD_free_t *last) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FD_aggr_adjoin) + + /* Check args */ + HDassert(file); + HDassert(file->cls); + HDassert(aggr); + HDassert(aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA || aggr->feature_flag == H5FD_FEAT_AGGREGATE_SMALLDATA); + HDassert(last); + + /* Check if this free block adjoins the aggregator */ + if((file->feature_flags & aggr->feature_flag) && aggr->size > 0) { + hbool_t adjoins = FALSE; /* Whether the block adjoined the aggregator */ + + /* Does the newly freed space adjoin the end of the aggregator */ + if((aggr->addr + aggr->size) == last->addr) { + last->addr = aggr->addr; + adjoins = TRUE; + } /* end if */ + /* Does the newly freed space adjoin the beginning of the aggregator */ + else if((last->addr + last->size) == aggr->addr) + adjoins = TRUE; + + /* Reset aggregator information, if adjoined */ + if(adjoins) { +#ifdef H5FD_ALLOC_DEBUG +HDfprintf(stderr, "%s: Adjoined flag = %lx aggregator\n", "H5FD_aggr_adjoin", aggr->feature_flag); +#endif /* H5FD_ALLOC_DEBUG */ + last->size += aggr->size; + aggr->addr = 0; + aggr->size = 0; + } /* end if */ + } /* end if */ + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5FD_aggr_adjoin() */ + + +/*------------------------------------------------------------------------- + * Function: H5FD_aggr_can_extend + * + * Purpose: Check is an aggregator block can be extended + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * Thursday, December 13, 2007 + * + *------------------------------------------------------------------------- + */ +static htri_t +H5FD_aggr_can_extend(const H5FD_t *file, const H5FD_blk_aggr_t *aggr, haddr_t eoa, + haddr_t end) +{ + htri_t ret_value = FALSE; + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FD_aggr_can_extend) + + /* Check args */ + HDassert(file); + HDassert(aggr); + HDassert(aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA || aggr->feature_flag == H5FD_FEAT_AGGREGATE_SMALLDATA); + + /* Check if this aggregator is active */ + if(file->feature_flags & aggr->feature_flag) { + /* If the aggregator block is at the end of the file, and the block to + * test adjoins the beginning of the aggregator block, then it's + * extendable + */ + if((aggr->addr + aggr->size) == eoa && end == aggr->addr) + HGOTO_DONE(TRUE) + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD_aggr_can_extend() */ + + +/*------------------------------------------------------------------------- + * Function: H5FD_aggr_extend + * + * Purpose: Shift an aggregator block in the file + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * Thursday, December 13, 2007 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5FD_aggr_shift(H5FD_blk_aggr_t *aggr, hsize_t extra) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FD_aggr_shift) + + /* Check args */ + HDassert(aggr); + HDassert(aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA || aggr->feature_flag == H5FD_FEAT_AGGREGATE_SMALLDATA); + + /* Shift the aggregator block by the extra amount */ + aggr->addr += extra; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5FD_aggr_shift() */ + + +/*------------------------------------------------------------------------- + * Function: H5FD_aggr_query + * + * Purpose: Query a block aggregator's current address & size info + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * Thursday, December 13, 2007 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5FD_aggr_query(const H5FD_t *file, const H5FD_blk_aggr_t *aggr, haddr_t *addr, + hsize_t *size) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FD_aggr_query) + + /* Check args */ + HDassert(file); + HDassert(aggr); + HDassert(aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA || aggr->feature_flag == H5FD_FEAT_AGGREGATE_SMALLDATA); + + /* Check if this aggregator is active */ + if(file->feature_flags & aggr->feature_flag) { + *addr = aggr->addr; + *size = aggr->size; + } /* end if */ + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5FD_aggr_query() */ + + +/*------------------------------------------------------------------------- + * Function: H5FD_aggr_reset + * + * Purpose: Reset a block aggregator, returning any space back to file + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * Thursday, December 13, 2007 + * + *------------------------------------------------------------------------- + */ +herr_t +H5FD_aggr_reset(H5FD_t *file, H5FD_blk_aggr_t *aggr, hid_t dxpl_id) +{ + H5FD_mem_t alloc_type; /* Type of file memory to work with */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5FD_aggr_reset, FAIL) + + /* Check args */ + HDassert(file); + HDassert(aggr); + HDassert(aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA || aggr->feature_flag == H5FD_FEAT_AGGREGATE_SMALLDATA); + + /* Set the type of memory in the file */ + alloc_type = (aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA ? H5FD_MEM_DEFAULT : H5FD_MEM_DRAW); /* Type of file memory to work with */ + + /* Check if this aggregator is active */ + if(file->feature_flags & aggr->feature_flag) { + /* Return the unused portion of the metadata block to a free list */ + if(aggr->size > 0) + if(H5FD_free(file, alloc_type, dxpl_id, aggr->addr, aggr->size) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, FAIL, "can't free aggregator block") + + /* Reset aggregator block information */ + aggr->tot_size = 0; + aggr->addr = 0; + aggr->size = 0; + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD_aggr_reset() */ + + +/*------------------------------------------------------------------------- + * Function: H5FD_real_alloc + * + * Purpose: Double private version of H5FDalloc() :-) + * + * Return: Success: The format address of the new file memory. + * Failure: The undefined address HADDR_UNDEF + * + * Programmer: Quincey Koziol + * Friday, August 25, 2000 + * + *------------------------------------------------------------------------- + */ +static haddr_t +H5FD_real_alloc(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size) +{ + haddr_t ret_value = HADDR_UNDEF; + + FUNC_ENTER_NOAPI_NOINIT(H5FD_real_alloc) +#ifdef H5FD_ALLOC_DEBUG +HDfprintf(stderr, "%s: type = %u, size = %Hu\n", FUNC, (unsigned)type, size); +#endif /* H5FD_ALLOC_DEBUG */ + + /* check args */ + assert(file); + assert(file->cls); + assert(type >= H5FD_MEM_DEFAULT && type < H5FD_MEM_NTYPES); + assert(size > 0); + + /* + * Dispatch to driver `alloc' callback or extend the end-of-address + * marker + */ + if(file->cls->alloc) { + if((ret_value = (file->cls->alloc)(file, type, dxpl_id, size)) == HADDR_UNDEF) + HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF, "driver allocation request failed") + } else { + if((ret_value = H5FD_update_eoa(file, type, dxpl_id, size)) == HADDR_UNDEF) + HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF, "driver eoa update request failed") + } + +done: +#ifdef H5FD_ALLOC_DEBUG +HDfprintf(stderr, "%s: ret_value = %a\n", FUNC, ret_value); +#endif /* H5FD_ALLOC_DEBUG */ + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD_real_alloc() */ + + +/*------------------------------------------------------------------------- + * Function: H5FD_update_eoa + * + * Purpose: Update the EOA field of the file's memory. + * + * This was split off from the H5FD_real_alloc function to + * make life easier for all. + * + * Return: Success: The format address of the new file memory. + * Failure: The undefined address HADDR_UNDEF + * + * Programmer: Bill Wendling + * Wednesday, 04. December, 2002 + * + *------------------------------------------------------------------------- + */ +static haddr_t +H5FD_update_eoa(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size) +{ + haddr_t eoa, oldeoa = 0; + hsize_t wasted; + haddr_t ret_value = HADDR_UNDEF; + + FUNC_ENTER_NOAPI_NOINIT(H5FD_update_eoa) + + /* check args */ + assert(file); + assert(file->cls); + assert(type >= H5FD_MEM_DEFAULT && type < H5FD_MEM_NTYPES); + assert(size > 0); + + eoa = file->cls->get_eoa(file, type); + +#ifdef H5F_DEBUG + if(file->alignment * file->threshold != 1 && H5DEBUG(F)) + HDfprintf(H5DEBUG(F), + "%s: alignment=%Hd, threshold=%Hd, size=%Hd, Begin eoa=%a\n", + FUNC, file->alignment, file->threshold, size, eoa); +#endif /* H5F_DEBUG */ + + /* Wasted is 0 if not exceeding threshold or eoa happens to be aligned */ + wasted = (size >= file->threshold) ? (eoa % file->alignment) : 0; + if(wasted) { + wasted = file->alignment - wasted; /* actual waste */ + oldeoa = eoa; /* save it for later freeing */ + + /* Advance eoa to the next alignment by allocating the wasted */ + if(H5F_addr_overflow(eoa, size) || (eoa + wasted) > file->maxaddr) + HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF, "file allocation request failed") + + eoa += wasted; + + if(file->cls->set_eoa(file, type, eoa) < 0) + HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF, "file allocation request failed") + } /* end if */ + + /* allocate the aligned memory */ + if(H5F_addr_overflow(eoa, size) || eoa + size > file->maxaddr) + HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF, "file allocation request failed") + + ret_value = eoa; + eoa += size; + + if(file->cls->set_eoa(file, type, eoa) < 0) + HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF, "file allocation request failed") + + /* Free the wasted memory */ + if(wasted) { + if(H5FD_free(file, type, dxpl_id, oldeoa, wasted) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "file deallocation request failed") + } /* end if */ + +#ifdef H5F_DEBUG + if(file->alignment * file->threshold != 1 && H5DEBUG(F)) + HDfprintf(H5DEBUG(F), + "%s: ret_value=%a, wasted=%Hd, Ended eoa=%a\n", + FUNC, ret_value, wasted, eoa); +#endif /* H5F_DEBUG */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD_update_eoa() */ + + +/*------------------------------------------------------------------------- + * Function: H5FD_free + * + * Purpose: Private version of H5FDfree() + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Robb Matzke + * Wednesday, August 4, 1999 + * + *------------------------------------------------------------------------- + */ +herr_t +H5FD_free(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, hsize_t size) +{ + H5FD_mem_t mapped_type; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5FD_free, FAIL) + + /* Check args */ + HDassert(file); + HDassert(file->cls); + HDassert(type >= H5FD_MEM_DEFAULT && type < H5FD_MEM_NTYPES); + +#ifdef H5FD_ALLOC_DEBUG +HDfprintf(stderr, "%s: type = %u, addr = %a, size = %Hu\n", FUNC, (unsigned)type, addr, size); +#endif /* H5FD_ALLOC_DEBUG */ + + if(!H5F_addr_defined(addr) || addr > file->maxaddr || + H5F_addr_overflow(addr, size) || (addr + size) > file->maxaddr) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid region") + + /* Allow 0-sized free's to occur without penalty */ + if(0 == size) + HGOTO_DONE(SUCCEED) + + /* Map request type to free list */ + if(H5FD_MEM_DEFAULT==file->cls->fl_map[type]) + mapped_type = type; + else + mapped_type = file->cls->fl_map[type]; +#ifdef H5FD_ALLOC_DEBUG +HDfprintf(stderr, "%s: mapped_type = %u\n", FUNC, (unsigned)mapped_type); +#endif /* H5FD_ALLOC_DEBUG */ + + /* + * If the request maps to a free list then add memory to the free list + * without ever telling the driver that it was freed. Otherwise let the + * driver deallocate the memory. + */ + if(mapped_type >= H5FD_MEM_DEFAULT) { + H5FD_free_t *last; /* Last merged node */ + H5FD_free_t *last_prev = NULL;/* Pointer to node before merged node */ + H5FD_free_t *curr; /* Current free block being inspected */ + H5FD_free_t *prev; /* Previous free block being inspected */ + + /* Adjust the metadata accumulator to remove the freed block, if it overlaps */ + if((file->feature_flags&H5FD_FEAT_ACCUMULATE_METADATA) + && H5F_addr_overlap(addr, size, file->accum_loc, file->accum_size)) { + size_t overlap_size; /* Size of overlap with accumulator */ + + /* Check for overlapping the beginning of the accumulator */ + if(H5F_addr_le(addr, file->accum_loc)) { + /* Check for completely overlapping the accumulator */ + if(H5F_addr_ge(addr + size, file->accum_loc + file->accum_size)) { + /* Reset the entire accumulator */ + file->accum_loc=HADDR_UNDEF; + file->accum_size=FALSE; + file->accum_dirty=FALSE; + } /* end if */ + /* Block to free must end within the accumulator */ + else { + size_t new_accum_size; /* Size of new accumulator buffer */ + + /* Calculate the size of the overlap with the accumulator, etc. */ + H5_ASSIGN_OVERFLOW(overlap_size,(addr+size)-file->accum_loc,haddr_t,size_t); + new_accum_size=file->accum_size-overlap_size; + + /* Move the accumulator buffer information to eliminate the freed block */ + HDmemmove(file->meta_accum,file->meta_accum+overlap_size,new_accum_size); + + /* Adjust the accumulator information */ + file->accum_loc+=overlap_size; + file->accum_size=new_accum_size; + } /* end else */ + } /* end if */ + /* Block to free must start within the accumulator */ + else { + /* Calculate the size of the overlap with the accumulator */ + H5_ASSIGN_OVERFLOW(overlap_size,(file->accum_loc+file->accum_size)-addr,haddr_t,size_t); + + /* Block to free is in the middle of the accumulator */ + if(H5F_addr_lt((addr + size), file->accum_loc + file->accum_size)) { + haddr_t tail_addr; + size_t tail_size; + + /* Calculate the address & size of the tail to write */ + tail_addr=addr+size; + H5_ASSIGN_OVERFLOW(tail_size,(file->accum_loc+file->accum_size)-tail_addr,haddr_t,size_t); + + /* Write out the part of the accumulator after the block to free */ + /* (Use the driver's write call directly - to avoid looping back and writing to metadata accumulator) */ + if((file->cls->write)(file, H5FD_MEM_DEFAULT, dxpl_id, tail_addr, tail_size, file->meta_accum+(tail_addr-file->accum_loc)) < 0) + HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "file write request failed") + } /* end if */ + + /* Adjust the accumulator information */ + file->accum_size=file->accum_size-overlap_size; + } /* end else */ + } /* end if */ + + /* Scan through the existing blocks for the mapped type to see if we can extend one */ + curr = file->fl[mapped_type]; + last = prev = NULL; + while(curr != NULL) { + /* Check if the block to free adjoins the start of the current block */ + if((addr + size) == curr->addr) { + /* If we previously found & merged a node, eliminate it from the list & free it */ + if(last != NULL) { + /* Check if there was a previous block in the list */ + if(last_prev != NULL) + /* Eliminate the merged block from the list */ + last_prev->next = last->next; + /* No previous block, this must be the head of the list */ + else + /* Eliminate the merged block from the list */ + file->fl[mapped_type] = last->next; + + /* Check for eliminating the block before the 'current' one */ + if(last == prev) + prev = last_prev; + + /* Free the memory for the merged block */ + H5FL_FREE(H5FD_free_t, last); + } /* end if */ + + /* Adjust the address and size of the block found */ + curr->addr = addr; + curr->size += size; + + /* Adjust the information about to memory block to include the merged block */ + addr = curr->addr; + size = curr->size; + + /* Update the information about the merged node */ + last = curr; + last_prev = prev; + } /* end if */ + else { + /* Check if the block to free adjoins the end of the current block */ + if((curr->addr + curr->size) == addr) { + /* If we previously found & merged a node, eliminate it from the list & free it */ + if(last != NULL) { + /* Check if there was a previous block in the list */ + if(last_prev != NULL) + /* Eliminate the merged block from the list */ + last_prev->next = last->next; + /* No previous block, this must be the head of the list */ + else + /* Eliminate the merged block from the list */ + file->fl[mapped_type] = last->next; + + /* Check for eliminating the block before the 'current' one */ + if(last == prev) + prev = last_prev; + + /* Free the memory for the merged block */ + H5FL_FREE(H5FD_free_t, last); + } /* end if */ + + /* Adjust the size of the block found */ + curr->size += size; + + /* Adjust the information about to memory block to include the merged block */ + addr = curr->addr; + size = curr->size; + + /* Update the information about the merged node */ + last = curr; + last_prev = prev; + } /* end if */ + } /* end else */ + + /* Advance to next node in list */ + prev = curr; + curr = curr->next; + } /* end while */ + + /* Check if we adjusted an existing block */ + if(last != NULL) { + /* Move the node found to the front, if it wasn't already there */ + if(last_prev != NULL) { + last_prev->next = last->next; + last->next = file->fl[mapped_type]; + file->fl[mapped_type] = last; + } /* end if */ + } /* end if */ + else { + /* Allocate a new node to hold the free block's information */ + if(NULL == (last = H5FL_MALLOC(H5FD_free_t))) + HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, FAIL, "can't allocate node for free space info") + + last->addr = addr; + last->size = size; + last->next = file->fl[mapped_type]; + file->fl[mapped_type] = last; + } /* end else */ +#ifdef H5FD_ALLOC_DEBUG +HDfprintf(stderr, "%s: mapped_type = %u, last = {%a, %Hu}\n", FUNC, (unsigned)mapped_type, last->addr, last->size); +#endif /* H5FD_ALLOC_DEBUG */ + + /* Check if we increased the size of the largest block on the list */ + file->maxsize = MAX(file->maxsize, last->size); + + /* Check if this free block adjoins the "metadata aggregator" */ + if(H5FD_aggr_adjoin(file, &(file->meta_aggr), last) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, FAIL, "aggregator deallocation request failed") + + /* Check if this free block adjoins the "small data aggregator" */ + if(H5FD_aggr_adjoin(file, &(file->sdata_aggr), last) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, FAIL, "aggregator deallocation request failed") + + /* Check if this free block is at the end of file allocated space. + * Truncate it if this is true. */ + if(file->cls->get_eoa) { + haddr_t eoa; + + eoa = file->cls->get_eoa(file, type); +#ifdef H5FD_ALLOC_DEBUG +HDfprintf(stderr, "%s: eoa = %a\n", FUNC, eoa); +#endif /* H5FD_ALLOC_DEBUG */ + if(eoa == (last->addr + last->size)) { +#ifdef H5FD_ALLOC_DEBUG +HDfprintf(stderr, "%s: Reducing file size to = %a\n", FUNC, last->addr); +#endif /* H5FD_ALLOC_DEBUG */ + if(file->cls->set_eoa(file, type, last->addr) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "set end of space allocation request failed") + + /* Remove this free block from the list */ + file->fl[mapped_type] = last->next; + if(file->maxsize == last->size) + file->maxsize = 0; /*unknown*/ + H5FL_FREE(H5FD_free_t, last); + } /* end if */ + } /* end if */ + } else if(file->cls->free) { +#ifdef H5FD_ALLOC_DEBUG +HDfprintf(stderr, "%s: Letting VFD free space\n", FUNC); +#endif /* H5FD_ALLOC_DEBUG */ + if((file->cls->free)(file, type, dxpl_id, addr, size) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver free request failed") + } else { + /* leak memory */ +#ifdef H5FD_ALLOC_DEBUG +HDfprintf(stderr, "%s: LEAKED MEMORY!!! type = %u, addr = %a, size = %Hu\n", FUNC, (unsigned)type, addr, size); +#endif /* H5FD_ALLOC_DEBUG */ + } /* end else */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD_free() */ + + +/*------------------------------------------------------------------------- + * Function: H5FD_realloc + * + * Purpose: Private version of H5FDrealloc() + * + * Return: Success: New address of the block of memory, not + * necessarily the same as the original address. + * Failure: HADDR_UNDEF + * + * Programmer: Robb Matzke + * Wednesday, August 4, 1999 + * + *------------------------------------------------------------------------- + */ +haddr_t +H5FD_realloc(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t old_addr, hsize_t old_size, + hsize_t new_size) +{ + haddr_t new_addr=old_addr; + uint8_t _buf[8192]; + uint8_t *buf=_buf; + haddr_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5FD_realloc, HADDR_UNDEF) + + if(new_size == old_size) { + /*nothing to do*/ + } else if(0 == old_size) { + /* allocate memory */ + HDassert(!H5F_addr_defined(old_addr)); + if(HADDR_UNDEF == (new_addr = H5FD_alloc(file, type, dxpl_id, new_size))) + HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, HADDR_UNDEF, "file allocation failed") + } else if(0==new_size) { + /* free memory */ + HDassert(H5F_addr_defined(old_addr)); + if(H5FD_free(file, type, dxpl_id, old_addr, old_size) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "file deallocation request failed") + new_addr = HADDR_UNDEF; + } else if(new_size<old_size) { + /* free the end of the block */ + if(H5FD_free(file, type, dxpl_id, old_addr+old_size, old_size-new_size) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "file deallocation request failed") + } else { + /* move memory to new location */ + /* Note! This may fail if sizeof(hsize_t)>sizeof(size_t) and the + * object on disk is too large to read into a memory buffer all at one + * time. This chunk of code would have to be re-written using a loop + * to move pieces of the realloced data through a fixed size buffer, etc. + * -QAK, 6/20/01 + */ + if(HADDR_UNDEF == (new_addr = H5FD_alloc(file, type, dxpl_id, new_size))) + HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, HADDR_UNDEF, "file allocation failed") + H5_CHECK_OVERFLOW(old_size,hsize_t,size_t); + if(old_size > sizeof(_buf) && NULL == (buf = H5MM_malloc((size_t)old_size))) { + (void)H5FD_free(file, type, dxpl_id, new_addr, new_size); + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, HADDR_UNDEF, "memory allocation failed") + } /* end if */ + if(H5FD_read(file, type, dxpl_id, old_addr, (size_t)old_size, buf) < 0 || + H5FD_write(file, type, dxpl_id, new_addr, (size_t)old_size, buf) < 0) { + (void)H5FD_free(file, type, dxpl_id, new_addr, new_size); + if(buf != _buf) + H5MM_xfree(buf); + HGOTO_ERROR(H5E_FILE, H5E_READERROR, HADDR_UNDEF, "unable to move file block") + } /* end if */ + + if(buf != _buf) + H5MM_xfree(buf); + if(H5FD_free(file, type, dxpl_id, old_addr, old_size) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "file deallocation request failed") + } /* end else */ + + /* Set return value */ + ret_value = new_addr; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD_realloc() */ + + +/*------------------------------------------------------------------------- + * Function: H5FD_can_extend + * + * Purpose: Check if a block in the file can be extended. + * + * Return: Success: TRUE(1)/FALSE(0) + * Failure: FAIL + * + * Programmer: Quincey Koziol + * Friday, June 11, 2004 + * + *------------------------------------------------------------------------- + */ +htri_t +H5FD_can_extend(const H5FD_t *file, H5FD_mem_t type, haddr_t addr, hsize_t size, hsize_t extra_requested) +{ + haddr_t end; /* End of block in file */ + haddr_t eoa; /* End of address space in the file */ + htri_t ret_value = FALSE; /* Return value */ + + FUNC_ENTER_NOAPI(H5FD_can_extend, FAIL) + + /* Retrieve the end of the address space */ + if(HADDR_UNDEF == (eoa = H5FD_get_eoa(file, type))) + HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver get_eoa request failed") + + /* Compute end of block */ + end = addr + size; + + /* Check if the block is exactly at the end of the file */ + if(end == eoa) + HGOTO_DONE(TRUE) + else { + H5FD_free_t *curr; /* Current free block being inspected */ + H5FD_mem_t mapped_type; /* Memory type, after mapping */ + + /* Map request type to free list */ + if(H5FD_MEM_DEFAULT==file->cls->fl_map[type]) + mapped_type = type; + else + mapped_type = file->cls->fl_map[type]; + + /* Check if block is inside the metadata or small data aggregator */ + if(mapped_type!=H5FD_MEM_DRAW) { + /* Check for test block able to extend metadata aggregation block */ + if((ret_value = H5FD_aggr_can_extend(file, &(file->meta_aggr), eoa, end)) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "can't determine if metadata aggregation block can be extended") + else if(ret_value > 0) + HGOTO_DONE(TRUE) + } /* end if */ + else { + /* Check for test block able to extend metadata aggregation block */ + if((ret_value = H5FD_aggr_can_extend(file, &(file->sdata_aggr), eoa, end)) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "can't determine if 'small data' aggregation block can be extended") + else if(ret_value > 0) + HGOTO_DONE(TRUE) + } /* end else */ + + /* Scan through the existing blocks for the mapped type to see if we can extend one */ + if(mapped_type >= H5FD_MEM_DEFAULT) { + curr = file->fl[mapped_type]; + while(curr != NULL) { + if(end == curr->addr) { + if(extra_requested <= curr->size) + HGOTO_DONE(TRUE) + else + HGOTO_DONE(FALSE) + } /* end if */ + + /* Advance to next node in list */ + curr=curr->next; + } /* end while */ + } /* end if */ + } /* end else */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD_can_extend() */ + + +/*------------------------------------------------------------------------- + * Function: H5FD_extend + * + * Purpose: Extend a block in the file. + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * Saturday, June 12, 2004 + * + *------------------------------------------------------------------------- + */ +herr_t +H5FD_extend(H5FD_t *file, H5FD_mem_t type, haddr_t addr, hsize_t size, hsize_t extra_requested) +{ + haddr_t eoa; /* End of address space in the file */ + haddr_t end; /* End of block in file */ + hbool_t update_eoma=FALSE; /* Whether we need to update the eoma */ + hbool_t update_eosda=FALSE; /* Whether we need to update the eosda */ + hbool_t at_end=FALSE; /* Block is at end of file */ + H5FD_mem_t mapped_type; /* Memory type, after mapping */ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5FD_extend, FAIL) +#ifdef H5FD_ALLOC_DEBUG +HDfprintf(stderr, "%s: type = %u, addr = %a, size = %Hu, extra_requested = %Hu\n", FUNC, (unsigned)type, addr, size, extra_requested); +#endif /* H5FD_ALLOC_DEBUG */ + + /* Retrieve the end of the address space */ + if(HADDR_UNDEF==(eoa=H5FD_get_eoa(file, type))) + HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver get_eoa request failed") + + /* Map request type to free list */ + if(H5FD_MEM_DEFAULT==file->cls->fl_map[type]) + mapped_type = type; + else + mapped_type = file->cls->fl_map[type]; + + /* Compute end of block */ + end = addr + size; + + /* Check if the block is exactly at the end of the file */ + if(end == eoa) + at_end = TRUE; + else { + /* (Check if block is inside the metadata or small data accumulator) */ + if(mapped_type!=H5FD_MEM_DRAW) { + /* Check for test block able to extend metadata aggregation block */ + if((ret_value = H5FD_aggr_can_extend(file, &(file->meta_aggr), eoa, end)) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "can't determine if metadata aggregation block can be extended") + else if(ret_value > 0) + update_eoma = TRUE; + } /* end if */ + else { + /* Check for test block able to extend metadata aggregation block */ + if((ret_value = H5FD_aggr_can_extend(file, &(file->sdata_aggr), eoa, end)) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "can't determine if metadata aggregation block can be extended") + else if(ret_value > 0) + update_eosda = TRUE; + } /* end else */ + } /* end else */ + + /* Block is at end of file, we are extending the eoma or eosda */ + if(update_eoma || update_eosda || at_end) { + /* Check for overflowing the file */ + if(H5F_addr_overflow(eoa, extra_requested) || eoa + extra_requested > file->maxaddr) + HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, FAIL, "file allocation request failed") + + /* Extend the file */ + eoa += extra_requested; + if(file->cls->set_eoa(file, type, eoa) < 0) + HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, FAIL, "file allocation request failed") + + /* Update the metadata and/or small data block */ + HDassert(!(update_eoma && update_eosda)); + if(update_eoma) + H5FD_aggr_shift(&(file->meta_aggr), extra_requested); + if(update_eosda) + H5FD_aggr_shift(&(file->sdata_aggr), extra_requested); + } /* end if */ + /* If the block we are extending isn't at the end of the file, find a free block to extend into */ + else { + H5FD_free_t *curr; /* Current free block being inspected */ + H5FD_free_t *prev; /* Current free block being inspected */ + + /* Walk through free list, looking for block to merge with */ + curr = file->fl[mapped_type]; + prev = NULL; + while(curr!=NULL) { + /* Found block that ajoins end of block to extend */ + if(end == curr->addr) { + /* Check if free space is large enough */ + if(extra_requested <= curr->size) { + /* Check for exact match */ + if(extra_requested == curr->size) { + /* Unlink node from free list */ + if(prev == NULL) + file->fl[mapped_type] = curr->next; + else + prev->next = curr->next; + + /* Free the memory for the used block */ + H5FL_FREE(H5FD_free_t, curr); + } /* end if */ + else { + curr->addr += extra_requested; + curr->size -= extra_requested; + } /* end else */ + + /* Leave now */ + break; + } /* end if */ + else + HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, FAIL, "can't extend block") + } /* end if */ + + /* Advance to next node in list */ + prev = curr; + curr = curr->next; + } /* end while */ + + /* Couldn't find block to extend */ + if(curr == NULL) + HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, FAIL, "can't extend block") + } /* end else */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD_extend() */ + + +/*------------------------------------------------------------------------- + * Function: H5FD_get_freespace + * + * Purpose: Retrieve the amount of free space in a file. + * + * Return: Success: Amount of free space in file + * Failure: Negative + * + * Programmer: Quincey Koziol + * Monday, October 6, 2003 + * + * Note: + * Raymond Lu + * 5 January 2007 + * Due to the complexity EOA for Multi driver, this function + * is made failed for now. + * + *------------------------------------------------------------------------- + */ +hssize_t +H5FD_get_freespace(const H5FD_t *file) +{ + H5FD_free_t *free_node; /* Pointer to node on free list */ + H5FD_mem_t type; /* Type of memory */ + haddr_t ma_addr = HADDR_UNDEF; /* Base "metadata aggregator" address */ + hsize_t ma_size = 0; /* Size of "metadata aggregator" */ + haddr_t sda_addr = HADDR_UNDEF; /* Base "small data aggregator" address */ + hsize_t sda_size = 0; /* Size of "small data aggregator" */ + haddr_t eoa = 0; /* End of allocated space in the file */ + hssize_t ret_value = 0; /* Return value */ + + FUNC_ENTER_NOAPI(H5FD_get_freespace, FAIL) + + /* check args */ + HDassert(file); + HDassert(file->cls); + + /* Multi driver doesn't support this function because of the complexity. + * It doesn't have eoa for the whole file. */ + if(file->driver_id == H5FD_MULTI) + HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "Multi driver doesn't support this function") + + /* Retrieve the 'eoa' for the file */ + eoa = file->cls->get_eoa(file, H5FD_MEM_DEFAULT); + + /* Retrieve metadata aggregator info, if available */ + H5FD_aggr_query(file, &(file->meta_aggr), &ma_addr, &ma_size); + + /* Retrieve 'small data' aggregator info, if available */ + H5FD_aggr_query(file, &(file->sdata_aggr), &sda_addr, &sda_size); + + /* Iterate over all the types of memory, to retrieve amount of free space for each */ + for(type = H5FD_MEM_DEFAULT; type < H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t,type)) { + /* Iterate through the free list, accumulating the amount of free space for this type */ + free_node = file->fl[type]; + while(free_node) { + /* Check for current node adjoining the metadata & small data aggregators */ + if(H5F_addr_eq(free_node->addr + free_node->size, ma_addr)) { + ma_addr -= free_node->size; + ma_size += free_node->size; + } else if(H5F_addr_eq(free_node->addr + free_node->size, sda_addr)) { + sda_addr -= free_node->size; + sda_size += free_node->size; + } else if(H5F_addr_eq(ma_addr + ma_size, free_node->addr)) + ma_size += free_node->size; + else if(H5F_addr_eq(sda_addr + sda_size, free_node->addr)) + sda_size += free_node->size; + else + ret_value += (hssize_t)free_node->size; + free_node = free_node->next; + } /* end while */ + } /* end for */ + + /* Check for aggregating metadata allocations */ + if(ma_size > 0) { + /* Add in the reserved space for metadata to the available free space */ + /* (if it's not at the tail of the file) */ + if(H5F_addr_ne(ma_addr + ma_size, eoa)) + ret_value += ma_size; + } /* end if */ + + /* Check for aggregating small data allocations */ + if(sda_size > 0) { + /* Add in the reserved space for metadata to the available free space */ + /* (if it's not at the tail of the file) */ + if(H5F_addr_ne(sda_addr + sda_size, eoa)) + ret_value += sda_size; + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD_get_freespace() */ + @@ -101,6 +101,9 @@ H5FS_create(H5F_t *f, hid_t dxpl_id, haddr_t *fs_addr, const H5FS_create_t *fs_c H5FS_t *ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5FS_create, NULL) +#ifdef QAK +HDfprintf(stderr, "%s: Creating free space manager, nclasses = %Zu\n", FUNC, nclasses); +#endif /* QAK */ /* Check arguments. */ HDassert(fs_addr); @@ -373,13 +376,13 @@ HDfprintf(stderr, "%s: fspace->tot_sect_count = %Hu\n", FUNC, fspace->tot_sect_c else { unsigned sect_status = 0; /* Free space section's status in the metadata cache */ - /* Check the free space section's status in the metadata cache */ - if(H5AC_get_entry_status(f, fspace->sect_addr, §_status) < 0) + /* Check if we've allocated any section info in the file & if it's still in the cache */ + if(H5F_addr_defined(fspace->sect_addr) && H5AC_get_entry_status(f, fspace->sect_addr, §_status) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTGET, FAIL, "unable to check metadata cache status for free space header") - /* If this free list header's section info is still in the cache, don't - * unpin the header - let the section info do it, when the section - * into is evicted from the cache. -QAK + /* If this free list header's section info exists and is still in the + * cache, don't unpin the header - let the section info do it, + * when the section info is evicted from the cache. -QAK */ if(!(sect_status & H5AC_ES__IN_CACHE)) { /* Unpin the free space header in the cache */ diff --git a/src/H5FSsection.c b/src/H5FSsection.c index 505223a..c589aa0 100644 --- a/src/H5FSsection.c +++ b/src/H5FSsection.c @@ -187,6 +187,9 @@ H5FS_sinfo_pin(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace) H5FS_sinfo_t *ret_value; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5FS_sinfo_pin) +#ifdef QAK +HDfprintf(stderr, "%s: Called, fspace->sect_addr = %a\n", FUNC, fspace->sect_addr); +#endif /* QAK */ /* Check arguments. */ HDassert(f); @@ -194,6 +197,9 @@ H5FS_sinfo_pin(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace) /* Create new section info, if it doesn't exist yet */ if(!H5F_addr_defined(fspace->sect_addr)) { +#ifdef QAK +HDfprintf(stderr, "%s: Allocating new section info\n", FUNC); +#endif /* QAK */ /* Sanity check */ HDassert(fspace->tot_sect_count == 0); HDassert(fspace->serial_sect_count == 0); @@ -208,6 +214,9 @@ H5FS_sinfo_pin(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace) fspace->alloc_sect_size = (size_t)fspace->sect_size; if(HADDR_UNDEF == (fspace->sect_addr = H5MF_alloc(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, fspace->alloc_sect_size))) HGOTO_ERROR(H5E_STORAGE, H5E_NOSPACE, NULL, "file allocation failed for free space sections") +#ifdef QAK +HDfprintf(stderr, "%s: New section info, addr = %a, size = %Hu\n", FUNC, fspace->sect_addr, fspace->alloc_sect_size); +#endif /* QAK */ /* Cache the new free space section info (pinned) */ if(H5AC_set(f, dxpl_id, H5AC_FSPACE_SINFO, fspace->sect_addr, sinfo, H5AC__PIN_ENTRY_FLAG) < 0) @@ -1209,12 +1218,6 @@ HDfprintf(stderr, "%s: request = %Hu\n", FUNC, request); HDassert(request); HDassert(node); - /* Check if we need to go get the sections */ - if(fspace->sinfo == NULL) { - if(NULL == (fspace->sinfo = H5FS_sinfo_pin(f, dxpl_id, fspace))) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTDECODE, FAIL, "can't pin sections") - } /* end if */ - /* Check for any sections on free space list */ #ifdef QAK HDfprintf(stderr, "%s: fspace->tot_sect_count = %Hu\n", FUNC, fspace->tot_sect_count); @@ -1222,6 +1225,12 @@ HDfprintf(stderr, "%s: fspace->serial_sect_count = %Hu\n", FUNC, fspace->serial_ HDfprintf(stderr, "%s: fspace->ghost_sect_count = %Hu\n", FUNC, fspace->ghost_sect_count); #endif /* QAK */ if(fspace->tot_sect_count > 0) { + /* Check if we need to go get the sections */ + if(fspace->sinfo == NULL) { + if(NULL == (fspace->sinfo = H5FS_sinfo_pin(f, dxpl_id, fspace))) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTDECODE, FAIL, "can't pin sections") + } /* end if */ + /* Look for node in bins */ if((ret_value = H5FS_sect_find_node(fspace, request, node)) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "can't remove section from bins") diff --git a/src/H5Fpkg.h b/src/H5Fpkg.h index 9df85bb..bea0579 100644 --- a/src/H5Fpkg.h +++ b/src/H5Fpkg.h @@ -90,7 +90,7 @@ typedef struct H5F_file_t { unsigned sohm_vers; /* Version of shared message table on disk */ unsigned sohm_nindexes; /* Number of shared messages indexes in the table */ haddr_t driver_addr; /* File driver information block address*/ - hbool_t fam_to_sec2; /* Is h5repart changing driver from family to sec2 */ + haddr_t maxaddr; /* Maximum address for file */ H5AC_t *cache; /* The object cache */ H5AC2_t *cache2; /* test cache */ @@ -109,7 +109,8 @@ typedef struct H5F_file_t { hsize_t alignment; /* Alignment */ unsigned gc_ref; /* Garbage-collect references? */ hbool_t latest_format; /* Always use the latest format? */ - hbool_t store_msg_crt_idx; /* Store creation index for object header messages? */ + hbool_t store_msg_crt_idx; /* Store creation index for object header messages? */ + hbool_t fam_to_sec2; /* Is h5repart changing driver from family to sec2? */ int ncwfs; /* Num entries on cwfs list */ struct H5HG_heap_t **cwfs; /* Global heap cache */ struct H5G_t *root_grp; /* Open root group */ diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h index 903f56d..b61773a 100644 --- a/src/H5Fprivate.h +++ b/src/H5Fprivate.h @@ -267,6 +267,7 @@ typedef struct H5F_t H5F_t; #define H5F_INTENT(F) ((F)->intent) #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) #else /* H5F_PACKAGE */ #define H5F_FCPL(F) (H5F_get_fcpl(F)) #define H5F_SIZEOF_ADDR(F) (H5F_sizeof_addr(F)) @@ -285,6 +286,7 @@ typedef struct H5F_t H5F_t; #define H5F_INTENT(F) (H5F_get_intent(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))) #endif /* H5F_PACKAGE */ diff --git a/src/H5Fpublic.h b/src/H5Fpublic.h index 1d98330..a055d46 100644 --- a/src/H5Fpublic.h +++ b/src/H5Fpublic.h @@ -107,6 +107,12 @@ typedef struct H5F_info_t { } sohm; } H5F_info_t; +/* Library's file format versions */ +typedef enum H5F_libver_t { + H5F_LIBVER_EARLIEST, /* Use the earliest possible format for storing objects */ + H5F_LIBVER_LATEST /* Use the latest possible format available for storing objects*/ +} H5F_libver_t; + #ifdef __cplusplus extern "C" { #endif @@ -88,6 +88,7 @@ #include "H5Gpkg.h" /* Groups */ #include "H5Iprivate.h" /* IDs */ #include "H5Lprivate.h" /* Links */ +#include "H5MMprivate.h" /* Memory management */ #include "H5Pprivate.h" /* Property lists */ #include "H5AC2private.h" /* Metadata cache */ @@ -101,14 +102,43 @@ typedef struct { H5G_loc_t *loc; /* Pointer to the location for insertion */ } H5G_trav_ins_t; +/* User data for application-style iteration over links in a group */ +typedef struct { + hid_t gid; /* The group ID for the application callback */ + H5G_link_iterate_t lnk_op; /* Application callback */ + void *op_data; /* Application's op data */ +} H5G_iter_appcall_ud_t; + +/* User data for recursive traversal over links from a group */ +typedef struct { + hid_t gid; /* The group ID for the starting group */ + H5G_loc_t *curr_loc; /* Location of starting group */ + hid_t lapl_id; /* LAPL for walking across links */ + hid_t dxpl_id; /* DXPL for operations */ + H5_index_t idx_type; /* Index to use */ + H5_iter_order_t order; /* Iteration order within index */ + H5SL_t *visited; /* Skip list for tracking visited nodes */ + char *path; /* Path name of the link */ + size_t curr_path_len; /* Current length of the path in the buffer */ + size_t path_buf_size; /* Size of path buffer */ + H5L_iterate_t op; /* Application callback */ + void *op_data; /* Application's op data */ +} H5G_iter_visit_ud_t; + + /* Package variables */ + /* Local variables */ /* Declare a free list to manage the H5G_t struct */ H5FL_DEFINE(H5G_t); H5FL_DEFINE(H5G_shared_t); +/* Declare the free list to manage H5_obj_t's */ +H5FL_DEFINE(H5_obj_t); + + /* Private prototypes */ static herr_t H5G_open_oid(H5G_t *grp, hid_t dxpl_id); @@ -367,7 +397,7 @@ H5Gopen2(hid_t loc_id, const char *name, hid_t gapl_id) if((grp = H5G_open_name(&loc, name, gapl_id, H5AC_dxpl_id)) == NULL) HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open group") - /* Register an atom for the group */ + /* Register an ID for the group */ if((ret_value = H5I_register(H5I_GROUP, grp)) < 0) HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register group") @@ -1021,8 +1051,8 @@ H5G_open_name(const H5G_loc_t *loc, const char *name, hid_t gapl_id, H5G_loc_t grp_loc; /* Location used to open group */ H5G_name_t grp_path; /* Opened object group hier. path */ H5O_loc_t grp_oloc; /* Opened object object location */ - H5O_type_t obj_type; /* Type of object at location */ hbool_t loc_found = FALSE; /* Location at 'name' found */ + H5O_type_t obj_type; /* Type of object at location */ H5G_t *ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5G_open_name, NULL) @@ -1147,7 +1177,7 @@ H5G_open(const H5G_loc_t *loc, hid_t dxpl_id) ret_value = grp; done: - if (!ret_value && grp) { + if(!ret_value && grp) { H5O_loc_free(&(grp->oloc)); H5G_name_free(&(grp->path)); H5FL_FREE(H5G_t,grp); @@ -1524,3 +1554,453 @@ H5G_unmount(H5G_t *grp) FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5G_unmount() */ + +/*------------------------------------------------------------------------- + * Function: H5G_iterate_cb + * + * Purpose: Callback function for iterating over links in a group + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * Oct 3, 2005 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5G_iterate_cb(const H5O_link_t *lnk, void *_udata) +{ + H5G_iter_appcall_ud_t *udata = (H5G_iter_appcall_ud_t *)_udata; /* User data for callback */ + herr_t ret_value = H5_ITER_ERROR; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5G_iterate_cb) + + /* Sanity check */ + HDassert(lnk); + HDassert(udata); + + switch(udata->lnk_op.op_type) { +#ifndef H5_NO_DEPRECATED_SYMBOLS + case H5G_LINK_OP_OLD: + /* Make the old-type application callback */ + ret_value = (udata->lnk_op.op_func.op_old)(udata->gid, lnk->name, udata->op_data); + break; +#endif /* H5_NO_DEPRECATED_SYMBOLS */ + + case H5G_LINK_OP_NEW: + { + H5L_info_t info; /* Link info */ + + /* Retrieve the info for the link */ + if(H5G_link_to_info(lnk, &info) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5_ITER_ERROR, "unable to get info for link") + + /* Make the application callback */ + ret_value = (udata->lnk_op.op_func.op_new)(udata->gid, lnk->name, &info, udata->op_data); + } + break; + } /* end switch */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_iterate_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_iterate + * + * Purpose: Private function for iterating over links in a group + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * Oct 3, 2005 + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_iterate(hid_t loc_id, const char *group_name, + H5_index_t idx_type, H5_iter_order_t order, hsize_t skip, hsize_t *last_lnk, + const H5G_link_iterate_t *lnk_op, void *op_data, hid_t lapl_id, hid_t dxpl_id) +{ + H5G_loc_t loc; /* Location of parent for group */ + hid_t gid = -1; /* ID of group to iterate over */ + H5G_t *grp; /* Pointer to group data structure to iterate over */ + H5G_iter_appcall_ud_t udata; /* User data for callback */ + herr_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5G_iterate, FAIL) + + /* Sanity check */ + HDassert(group_name); + HDassert(last_lnk); + HDassert(lnk_op && lnk_op->op_func.op_new); + + /* + * Open the group on which to operate. We also create a group ID which + * we can pass to the application-defined operator. + */ + if(H5G_loc(loc_id, &loc) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") + if(NULL == (grp = H5G_open_name(&loc, group_name, lapl_id, dxpl_id))) + HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open group") + if((gid = H5I_register(H5I_GROUP, grp)) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register group") + + /* Set up user data for callback */ + udata.gid = gid; + udata.lnk_op = *lnk_op; + udata.op_data = op_data; + + /* Call the real group iteration routine */ + if((ret_value = H5G_obj_iterate(&(grp->oloc), idx_type, order, skip, last_lnk, H5G_iterate_cb, &udata, dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "error iterating over links") + +done: + /* Release the group opened */ + if(gid > 0) { + if(H5I_dec_ref(gid) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "unable to close group") + } /* end if */ + else if(grp && H5G_close(grp) < 0) + HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "unable to release group") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_iterate() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_free_visit_visited + * + * Purpose: Free the key for an object visited during a group traversal + * + * Return: Non-negative on success, negative on failure + * + * Programmer: Quincey Koziol + * Nov 4, 2007 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5G_free_visit_visited(void *item, void UNUSED *key, void UNUSED *operator_data/*in,out*/) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_free_visit_visited) + + H5FL_FREE(H5_obj_t, item); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5G_free_visit_visited() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_visit_cb + * + * Purpose: Callback function for recursively visiting links from a group + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * Nov 4, 2007 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5G_visit_cb(const H5O_link_t *lnk, void *_udata) +{ + H5G_iter_visit_ud_t *udata = (H5G_iter_visit_ud_t *)_udata; /* User data for callback */ + H5L_info_t info; /* Link info */ + H5G_loc_t obj_loc; /* Location of object */ + H5G_name_t obj_path; /* Object's group hier. path */ + H5O_loc_t obj_oloc; /* Object's object location */ + hbool_t obj_found = FALSE; /* Object at 'name' found */ + size_t old_path_len = udata->curr_path_len; /* Length of path before appending this link's name */ + size_t link_name_len; /* Length of link's name */ + size_t len_needed; /* Length of path string needed */ + herr_t ret_value = H5_ITER_CONT; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5G_visit_cb) + + /* Sanity check */ + HDassert(lnk); + HDassert(udata); + + /* Check if we will need more space to store this link's relative path */ + /* ("+2" is for string terminator and possible '/' for group separator later) */ + link_name_len = HDstrlen(lnk->name); + len_needed = udata->curr_path_len + link_name_len + 2; + if(len_needed > udata->path_buf_size) { + void *new_path; /* Pointer to new path buffer */ + + /* Attempt to allocate larger buffer for path */ + if(NULL == (new_path = H5MM_realloc(udata->path, len_needed))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, H5_ITER_ERROR, "can't allocate path string") + udata->path = new_path; + udata->path_buf_size = len_needed; + } /* end if */ + + /* Build the link's relative path name */ + HDassert(udata->path[old_path_len] == '\0'); + HDstrcpy(&(udata->path[old_path_len]), lnk->name); + udata->curr_path_len += link_name_len; + + /* Construct the link info from the link message */ + if(H5G_link_to_info(lnk, &info) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5_ITER_ERROR, "unable to get info for link") + + /* Make the application callback */ + ret_value = (udata->op)(udata->gid, udata->path, &info, udata->op_data); + + /* Check for doing more work */ + if(ret_value == H5_ITER_CONT && lnk->type == H5L_TYPE_HARD) { + H5_obj_t obj_pos; /* Object "position" for this object */ + + /* Set up opened group location to fill in */ + obj_loc.oloc = &obj_oloc; + obj_loc.path = &obj_path; + H5G_loc_reset(&obj_loc); + + /* Find the object using the LAPL passed in */ + /* (Correctly handles mounted files) */ + if(H5G_loc_find(udata->curr_loc, lnk->name, &obj_loc/*out*/, udata->lapl_id, udata->dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, H5_ITER_ERROR, "object not found") + obj_found = TRUE; + + /* Construct unique "position" for this object */ + H5F_GET_FILENO(obj_oloc.file, obj_pos.fileno); + obj_pos.addr = obj_oloc.addr; + + /* Check if we've seen the object the link references before */ + if(NULL == H5SL_search(udata->visited, &obj_pos)) { + H5O_type_t otype; /* Basic object type (group, dataset, etc.) */ + unsigned rc; /* Reference count of object */ + + /* Get the object's reference count and type */ + if(H5O_get_rc_and_type(&obj_oloc, udata->dxpl_id, &rc, &otype) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5_ITER_ERROR, "unable to get object info") + + /* If its ref count is > 1, we add it to the list of visited objects */ + /* (because it could come up again during traversal) */ + if(rc > 1) { + H5_obj_t *new_node; /* New object node for visited list */ + + /* Allocate new object "position" node */ + if((new_node = H5FL_MALLOC(H5_obj_t)) == NULL) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, H5_ITER_ERROR, "can't allocate object node") + + /* Set node information */ + *new_node = obj_pos; + + /* Add to list of visited objects */ + if(H5SL_insert(udata->visited, new_node, new_node) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, H5_ITER_ERROR, "can't insert object node into visited list") + } /* end if */ + + /* If it's a group, we recurse into it */ + if(otype == H5O_TYPE_GROUP) { + H5G_loc_t *old_loc = udata->curr_loc; /* Pointer to previous group location info */ + H5_index_t idx_type = udata->idx_type; /* Type of index to use */ + H5O_linfo_t linfo; /* Link info message */ + + /* Add the path separator to the current path */ + HDassert(udata->path[udata->curr_path_len] == '\0'); + HDstrcpy(&(udata->path[udata->curr_path_len]), "/"); + udata->curr_path_len++; + + /* Attempt to get the link info for this group */ + if(H5G_obj_get_linfo(&obj_oloc, &linfo, udata->dxpl_id)) { + /* Check for creation order tracking, if creation order index lookup requested */ + if(idx_type == H5_INDEX_CRT_ORDER) { + /* Check if creation order is tracked */ + if(!linfo.track_corder) + /* Switch to name order for this group */ + idx_type = H5_INDEX_NAME; + } /* end if */ + else + HDassert(idx_type == H5_INDEX_NAME); + } /* end if */ + else { + /* Clear error stack from not finding the link info message */ + H5E_clear_stack(NULL); + + /* Can only perform name lookups on groups with symbol tables */ + if(idx_type != H5_INDEX_NAME) + /* Switch to name order for this group */ + idx_type = H5_INDEX_NAME; + } /* end if */ + + /* Point to this group's location info */ + udata->curr_loc = &obj_loc; + + /* Iterate over links in group */ + ret_value = H5G_obj_iterate(&obj_oloc, idx_type, udata->order, (hsize_t)0, NULL, H5G_visit_cb, udata, udata->dxpl_id); + + /* Restore location */ + udata->curr_loc = old_loc; + } /* end if */ + } /* end if */ + } /* end if */ + +done: + /* Reset path back to incoming path */ + udata->path[old_path_len] = '\0'; + udata->curr_path_len = old_path_len; + + /* Release resources */ + if(obj_found && H5G_loc_free(&obj_loc) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTRELEASE, H5_ITER_ERROR, "can't free location") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_visit_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_visit + * + * Purpose: Recursively visit all the links in a group and all + * the groups that are linked to from that group. Links within + * each group are visited according to the order within the + * specified index (unless the specified index does not exist for + * a particular group, then the "name" index is used). + * + * NOTE: Each _link_ reachable from the initial group will only be + * visited once. However, because an object may be reached from + * more than one link, the visitation may call the application's + * callback with more than one link that points to a particular + * _object_. + * + * Return: Success: The return value of the first operator that + * returns non-zero, or zero if all members were + * processed with no operator returning non-zero. + * + * Failure: Negative if something goes wrong within the + * library, or the negative value returned by one + * of the operators. + * + * + * + * Programmer: Quincey Koziol + * November 4 2007 + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_visit(hid_t loc_id, const char *group_name, H5_index_t idx_type, + H5_iter_order_t order, H5L_iterate_t op, void *op_data, hid_t lapl_id, + hid_t dxpl_id) +{ + H5G_iter_visit_ud_t udata; /* User data for callback */ + H5O_linfo_t linfo; /* Link info message */ + hid_t gid = (-1); /* Group ID */ + H5G_t *grp = NULL; /* Group opened */ + H5G_loc_t loc; /* Location of group passed in */ + H5G_loc_t start_loc; /* Location of starting group */ + H5O_type_t otype; /* Basic object type (group, dataset, etc.) */ + unsigned rc; /* Reference count of object */ + herr_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5G_visit, FAIL) + + /* Check args */ + if(H5G_loc(loc_id, &loc) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") + + /* Open the group to begin visiting within */ + if((grp = H5G_open_name(&loc, group_name, lapl_id, dxpl_id)) == NULL) + HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open group") + + /* Register an ID for the starting group */ + if((gid = H5I_register(H5I_GROUP, grp)) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register group") + + /* Get the location of the starting group */ + if(H5G_loc(gid, &start_loc) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") + + /* Set up user data */ + udata.gid = gid; + udata.curr_loc = &start_loc; + udata.lapl_id = lapl_id; + udata.dxpl_id = dxpl_id; + udata.idx_type = idx_type; + udata.order = order; + udata.op = op; + udata.op_data = op_data; + + /* Allocate space for the path name */ + if(NULL == (udata.path = H5MM_strdup(""))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate path name buffer") + udata.path_buf_size = 1; + udata.curr_path_len = 0; + + /* Create skip list to store visited object information */ + if((udata.visited = H5SL_create(H5SL_TYPE_OBJ, 0.5, (size_t)16)) == NULL) + HGOTO_ERROR(H5E_SYM, H5E_CANTCREATE, FAIL, "can't create skip list for visited objects") + + /* Get the group's reference count and type */ + if(H5O_get_rc_and_type(&grp->oloc, dxpl_id, &rc, &otype) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to get object info") + + /* If its ref count is > 1, we add it to the list of visited objects */ + /* (because it could come up again during traversal) */ + if(rc > 1) { + H5_obj_t *obj_pos; /* New object node for visited list */ + + /* Allocate new object "position" node */ + if((obj_pos = H5FL_MALLOC(H5_obj_t)) == NULL) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate object node") + + /* Construct unique "position" for this object */ + H5F_GET_FILENO(grp->oloc.file, obj_pos->fileno); + obj_pos->addr = grp->oloc.addr; + + /* Add to list of visited objects */ + if(H5SL_insert(udata.visited, obj_pos, obj_pos) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, FAIL, "can't insert object node into visited list") + } /* end if */ + + /* Attempt to get the link info for this group */ + if(H5G_obj_get_linfo(&(grp->oloc), &linfo, dxpl_id)) { + /* Check for creation order tracking, if creation order index lookup requested */ + if(idx_type == H5_INDEX_CRT_ORDER) { + /* Check if creation order is tracked */ + if(!linfo.track_corder) + /* Switch to name order for this group */ + idx_type = H5_INDEX_NAME; + } /* end if */ + else + HDassert(idx_type == H5_INDEX_NAME); + } /* end if */ + else { + /* Clear error stack from not finding the link info message */ + H5E_clear_stack(NULL); + + /* Can only perform name lookups on groups with symbol tables */ + if(idx_type != H5_INDEX_NAME) + /* Switch to name order for this group */ + idx_type = H5_INDEX_NAME; + } /* end if */ + + /* Call the link iteration routine */ + if((ret_value = H5G_obj_iterate(&(grp->oloc), idx_type, order, (hsize_t)0, NULL, H5G_visit_cb, &udata, dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "can't visit links") + +done: + /* Release user data resources */ + H5MM_xfree(udata.path); + if(udata.visited) + H5SL_destroy(udata.visited, H5G_free_visit_visited, NULL); + + /* Release the group opened */ + if(gid > 0) { + if(H5I_dec_ref(gid) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "unable to close group") + } /* end if */ + else if(grp && H5G_close(grp) < 0) + HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "unable to release group") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_visit() */ + diff --git a/src/H5Gcompact.c b/src/H5Gcompact.c index 042d29a..b0340a7 100644 --- a/src/H5Gcompact.c +++ b/src/H5Gcompact.c @@ -406,9 +406,9 @@ done: *------------------------------------------------------------------------- */ herr_t -H5G_compact_iterate(H5O_loc_t *oloc, hid_t dxpl_id, const H5O_linfo_t *linfo, +H5G_compact_iterate(const H5O_loc_t *oloc, hid_t dxpl_id, const H5O_linfo_t *linfo, H5_index_t idx_type, H5_iter_order_t order, hsize_t skip, hsize_t *last_lnk, - hid_t gid, H5G_link_iterate_t *lnk_op, void *op_data) + H5G_lib_iterate_t op, void *op_data) { H5G_link_table_t ltable = {0, NULL}; /* Link table */ herr_t ret_value; /* Return value */ @@ -418,14 +418,14 @@ H5G_compact_iterate(H5O_loc_t *oloc, hid_t dxpl_id, const H5O_linfo_t *linfo, /* Sanity check */ HDassert(oloc); HDassert(linfo); - HDassert(lnk_op && lnk_op->u.lib_op); + HDassert(op); /* Build table of all link messages */ if(H5G_compact_build_table(oloc, dxpl_id, linfo, idx_type, order, <able) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create link message table") /* Iterate over links in table */ - if((ret_value = H5G_link_iterate_table(<able, skip, last_lnk, gid, lnk_op, op_data)) < 0) + if((ret_value = H5G_link_iterate_table(<able, skip, last_lnk, op, op_data)) < 0) HERROR(H5E_SYM, H5E_CANTNEXT, "iteration operator failed"); done: diff --git a/src/H5Gdense.c b/src/H5Gdense.c index 2b7493b..ed53a47 100644 --- a/src/H5Gdense.c +++ b/src/H5Gdense.c @@ -90,9 +90,8 @@ typedef struct { hsize_t count; /* # of links examined */ /* downward (from application) */ - hid_t gid; /* Group ID for application callback */ hsize_t skip; /* Number of links to skip */ - const H5G_link_iterate_t *lnk_op; /* Callback for each link */ + H5G_lib_iterate_t op; /* Callback for each link */ void *op_data; /* Callback data for each link */ /* upward */ @@ -799,7 +798,6 @@ H5G_dense_build_table(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo, /* Allocate space for the table entries */ if(ltable->nlinks > 0) { H5G_dense_bt_ud_t udata; /* User data for iteration callback */ - H5G_link_iterate_t lnk_op; /* Link operator */ /* Allocate the table to store the links */ if((ltable->lnks = H5MM_malloc(sizeof(H5O_link_t) * ltable->nlinks)) == NULL) @@ -809,12 +807,8 @@ H5G_dense_build_table(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo, udata.ltable = ltable; udata.curr_lnk = 0; - /* Build iterator operator */ - lnk_op.op_type = H5G_LINK_OP_LIB; - lnk_op.u.lib_op = H5G_dense_build_table_cb; - /* Iterate over the links in the group, building a table of the link messages */ - if(H5G_dense_iterate(f, dxpl_id, linfo, H5_INDEX_NAME, H5_ITER_NATIVE, (hsize_t)0, NULL, (hid_t)0, &lnk_op, &udata) < 0) + if(H5G_dense_iterate(f, dxpl_id, linfo, H5_INDEX_NAME, H5_ITER_NATIVE, (hsize_t)0, NULL, H5G_dense_build_table_cb, &udata) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTNEXT, FAIL, "error iterating over links") /* Sort link table in correct iteration order */ @@ -904,32 +898,8 @@ H5G_dense_iterate_bt2_cb(const void *_record, void *_bt2_udata) H5G_dense_iterate_fh_cb, &fh_udata) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTOPERATE, H5_ITER_ERROR, "heap op callback failed") - /* Check which type of callback to make */ - switch(bt2_udata->lnk_op->op_type) { -#ifndef H5_NO_DEPRECATED_SYMBOLS - case H5G_LINK_OP_OLD: - /* Make the old-type application callback */ - ret_value = (bt2_udata->lnk_op->u.old_op)(bt2_udata->gid, fh_udata.lnk->name, bt2_udata->op_data); - break; -#endif /* H5_NO_DEPRECATED_SYMBOLS */ - - case H5G_LINK_OP_APP: - { - H5L_info_t info; /* Link info */ - - /* Retrieve the info for the link */ - if(H5G_link_to_info(fh_udata.lnk, &info) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5_ITER_ERROR, "unable to get info for link") - - /* Make the application callback */ - ret_value = (bt2_udata->lnk_op->u.app_op)(bt2_udata->gid, fh_udata.lnk->name, &info, bt2_udata->op_data); - } - break; - - case H5G_LINK_OP_LIB: - /* Call the library's callback */ - ret_value = (bt2_udata->lnk_op->u.lib_op)(fh_udata.lnk, bt2_udata->op_data); - } /* end switch */ + /* Make the callback */ + ret_value = (bt2_udata->op)(fh_udata.lnk, bt2_udata->op_data); /* Release the space allocated for the link */ H5O_msg_free(H5O_LINK_ID, fh_udata.lnk); @@ -964,7 +934,7 @@ done: herr_t H5G_dense_iterate(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo, H5_index_t idx_type, H5_iter_order_t order, hsize_t skip, hsize_t *last_lnk, - hid_t gid, const H5G_link_iterate_t *lnk_op, void *op_data) + H5G_lib_iterate_t op, void *op_data) { H5HF_t *fheap = NULL; /* Fractal heap handle */ H5G_link_table_t ltable = {0, NULL}; /* Table of links */ @@ -979,7 +949,7 @@ H5G_dense_iterate(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo, */ HDassert(f); HDassert(linfo); - HDassert(lnk_op && lnk_op->u.lib_op); + HDassert(op); /* Determine the address of the index to use */ if(idx_type == H5_INDEX_NAME) { @@ -1018,10 +988,9 @@ H5G_dense_iterate(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo, udata.f = f; udata.dxpl_id = dxpl_id; udata.fheap = fheap; - udata.gid = gid; udata.skip = skip; udata.count = 0; - udata.lnk_op = lnk_op; + udata.op = op; udata.op_data = op_data; /* Iterate over the records in the v2 B-tree's "native" order */ @@ -1039,7 +1008,7 @@ H5G_dense_iterate(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo, HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "error building table of links") /* Iterate over links in table */ - if((ret_value = H5G_link_iterate_table(<able, skip, last_lnk, gid, lnk_op, op_data)) < 0) + if((ret_value = H5G_link_iterate_table(<able, skip, last_lnk, op, op_data)) < 0) HERROR(H5E_SYM, H5E_CANTNEXT, "iteration operator failed"); } /* end else */ diff --git a/src/H5Gdeprec.c b/src/H5Gdeprec.c index bc635be..ffcc0e5 100644 --- a/src/H5Gdeprec.c +++ b/src/H5Gdeprec.c @@ -771,10 +771,10 @@ H5Giterate(hid_t loc_id, const char *name, int *idx_p, H5G_iterate_t op, /* Build link operator info */ lnk_op.op_type = H5G_LINK_OP_OLD; - lnk_op.u.old_op = op; + lnk_op.op_func.op_old = op; /* Call private function. */ - if((ret_value = H5G_obj_iterate(loc_id, name, H5_INDEX_NAME, H5_ITER_INC, idx, &last_obj, &lnk_op, op_data, H5P_DEFAULT, H5AC_ind_dxpl_id)) < 0) + if((ret_value = H5G_iterate(loc_id, name, H5_INDEX_NAME, H5_ITER_INC, idx, &last_obj, &lnk_op, op_data, H5P_DEFAULT, H5AC_ind_dxpl_id)) < 0) HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "group iteration failed") /* Set the index we stopped at */ diff --git a/src/H5Glink.c b/src/H5Glink.c index 7292245..75a3e83 100644 --- a/src/H5Glink.c +++ b/src/H5Glink.c @@ -603,7 +603,7 @@ H5G_link_sort_table(H5G_link_table_t *ltable, H5_index_t idx_type, */ herr_t H5G_link_iterate_table(const H5G_link_table_t *ltable, hsize_t skip, - hsize_t *last_lnk, hid_t gid, const H5G_link_iterate_t *lnk_op, void *op_data) + hsize_t *last_lnk, const H5G_lib_iterate_t op, void *op_data) { size_t u; /* Local index variable */ herr_t ret_value = H5_ITER_CONT; /* Return value */ @@ -612,7 +612,7 @@ H5G_link_iterate_table(const H5G_link_table_t *ltable, hsize_t skip, /* Sanity check */ HDassert(ltable); - HDassert(lnk_op); + HDassert(op); /* Skip over links, if requested */ if(last_lnk) @@ -621,32 +621,8 @@ H5G_link_iterate_table(const H5G_link_table_t *ltable, hsize_t skip, /* Iterate over link messages */ H5_ASSIGN_OVERFLOW(/* To: */ u, /* From: */ skip, /* From: */ hsize_t, /* To: */ size_t) for(; u < ltable->nlinks && !ret_value; u++) { - /* Check which kind of callback to make */ - switch(lnk_op->op_type) { -#ifndef H5_NO_DEPRECATED_SYMBOLS - case H5G_LINK_OP_OLD: - /* Make the old-type application callback */ - ret_value = (lnk_op->u.old_op)(gid, ltable->lnks[u].name, op_data); - break; -#endif /* H5_NO_DEPRECATED_SYMBOLS */ - - case H5G_LINK_OP_APP: - { - H5L_info_t info; /* Link info */ - - /* Retrieve the info for the link */ - if(H5G_link_to_info(&(ltable->lnks[u]), &info) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5_ITER_ERROR, "unable to get info for link") - - /* Make the application callback */ - ret_value = (lnk_op->u.app_op)(gid, ltable->lnks[u].name, &info, op_data); - } - break; - - case H5G_LINK_OP_LIB: - /* Call the library's callback */ - ret_value = (lnk_op->u.lib_op)(&(ltable->lnks[u]), op_data); - } /* end switch */ + /* Make the callback */ + ret_value = (op)(&(ltable->lnks[u]), op_data); /* Increment the number of entries passed through */ if(last_lnk) @@ -657,7 +633,6 @@ H5G_link_iterate_table(const H5G_link_table_t *ltable, hsize_t skip, if(ret_value < 0) HERROR(H5E_SYM, H5E_CANTNEXT, "iteration operator failed"); -done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5G_link_iterate_table() */ diff --git a/src/H5Gname.c b/src/H5Gname.c index e341ee7..bde9e23 100644 --- a/src/H5Gname.c +++ b/src/H5Gname.c @@ -50,21 +50,15 @@ typedef struct H5G_names_t { } H5G_names_t; /* Info to pass to the iteration function when building name */ -typedef struct H5G_ref_path_iter_t { +typedef struct H5G_gnba_iter_t { /* In */ - hid_t file; /* File id where it came from */ + const H5O_loc_t *loc; /* The location of the object we're looking for */ hid_t lapl_id; /* LAPL for operations */ hid_t dxpl_id; /* DXPL for operations */ - hbool_t is_root_group; /* Flag to indicate that the root group is being looked at */ - const H5O_loc_t *loc; /* The location of the object we're looking for */ - - /* In/Out */ - H5SL_t *ref_path_table; /* Skip list for tracking visited nodes */ - size_t max_container_len; /* Maximum size of container */ /* Out */ - char *container; /* full name of the container object */ -} H5G_ref_path_iter_t; + char *path; /* Name of the object */ +} H5G_gnba_iter_t; /* Private macros */ @@ -85,9 +79,6 @@ static H5RS_str_t *H5G_build_fullpath_refstr_refstr(const H5RS_str_t *prefix_r, static herr_t H5G_name_move_path(H5RS_str_t **path_r_ptr, const char *full_suffix, const char *src_path, const char *dst_path); static int H5G_name_replace_cb(void *obj_ptr, hid_t obj_id, void *key); -static herr_t H5G_refname_iterator(hid_t group, const char *name, - const H5L_info_t *link_info, void *_udata); -static herr_t H5G_free_ref_path_node(void *item, void *key, void *operator_data/*in,out*/); /*------------------------------------------------------------------------- @@ -468,7 +459,7 @@ H5G_get_name(hid_t id, char *name/*out*/, size_t size, hid_t lapl_id, HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't retrieve file ID") /* Search for name of object */ - if((len = H5G_get_refobj_name(file, lapl_id, dxpl_id, loc.oloc, name, size)) < 0) { + if((len = H5G_get_name_by_addr(file, lapl_id, dxpl_id, loc.oloc, name, size)) < 0) { H5I_dec_ref(file); HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't determine name") } /* end if */ @@ -1039,222 +1030,139 @@ done: /*------------------------------------------------------------------------- - * Function: H5G_refname_iterator + * Function: H5G_get_name_by_addr_cb * - * Purpose: The iterator which traverses all objects in a file looking for - * one that matches the object that is being looked for. + * Purpose: Callback for retrieving object's name by address * - * Return: 1 on success, 0 to continue searching, negative on failure. - * - * Programmer: Leon Arber, Nov 1, 2006. + * Return: Positive if path is for object desired + * 0 if not correct object + * negative on failure. * - * Modifications: - * Quincey Koziol, Nov. 3, 2006 - * Cleaned up code. + * Programmer: Quincey Koziol + * November 4 2007 * *------------------------------------------------------------------------- */ static herr_t -H5G_refname_iterator(hid_t group, const char *name, const H5L_info_t *link_info, +H5G_get_name_by_addr_cb(hid_t gid, const char *path, const H5L_info_t *linfo, void *_udata) { - H5G_ref_path_iter_t *udata = (H5G_ref_path_iter_t*)_udata; - herr_t ret_value = H5_ITER_CONT; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5G_refname_iterator) - - /* We only care about hard links */ - if(link_info->type == H5L_TYPE_HARD) { - H5G_loc_t loc; /* Group location of parent */ - - /* Look up group's location */ - if(H5G_loc(group, &loc) < 0) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5_ITER_ERROR, "not a location") - - /* Check for finding the object */ - /* (checks against the file in the location as well, to make certain that - * the correct object is found in a mounted file hierarchy) - */ - if(udata->loc->addr == link_info->u.address && udata->loc->file == loc.oloc->file) { - size_t len_needed; /* Length of container string needed */ - - /* Build the object's full name */ - len_needed = HDstrlen(udata->container) + HDstrlen(name) + 2; - if(len_needed > udata->max_container_len) { - void *new_container; /* Pointer to new container */ - - if(NULL == (new_container = H5MM_realloc(udata->container, len_needed))) - HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, H5_ITER_ERROR, "can't allocate path string") - udata->container = new_container; - udata->max_container_len = len_needed; - } /* end if */ - HDstrcat(udata->container, name); + H5G_gnba_iter_t *udata = (H5G_gnba_iter_t *)_udata; /* User data for iteration */ + H5G_loc_t obj_loc; /* Location of object */ + H5G_name_t obj_path; /* Object's group hier. path */ + H5O_loc_t obj_oloc; /* Object's object location */ + hbool_t obj_found = FALSE; /* Object at 'path' found */ + herr_t ret_value = H5_ITER_CONT; /* Return value */ - /* We found a match so we return immediately */ - HGOTO_DONE(H5_ITER_STOP) - } /* end if */ - else { - H5O_info_t oinfo; /* Object information */ - H5O_loc_t tmp_oloc; /* Temporary object location */ + FUNC_ENTER_NOAPI_NOINIT(H5G_get_name_by_addr_cb) - /* Check if we've seen this object before */ - if(H5SL_search(udata->ref_path_table, &link_info->u.address)) - HGOTO_DONE(H5_ITER_CONT) + /* Sanity check */ + HDassert(path); + HDassert(linfo); + HDassert(udata->loc); + HDassert(udata->path == NULL); - /* Go retrieve the object information */ - tmp_oloc.file = loc.oloc->file; - tmp_oloc.addr = link_info->u.address; - if(H5O_get_info(&tmp_oloc, udata->dxpl_id, FALSE, &oinfo) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, H5_ITER_ERROR, "unable to get object info") + /* Check for hard link with correct address */ + if(linfo->type == H5L_TYPE_HARD && udata->loc->addr == linfo->u.address) { + H5G_loc_t grp_loc; /* Location of group */ - /* If its ref count is > 1, we add it to the list of visited objects */ - if(oinfo.rc > 1) { - haddr_t *new_node; /* New path node for table */ + /* Get group's location */ + if(H5G_loc(gid, &grp_loc) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5_ITER_ERROR, "bad group location") - /* Allocate new path node */ - if((new_node = H5FL_MALLOC(haddr_t)) == NULL) - HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, H5_ITER_ERROR, "can't allocate path node") + /* Set up opened object location to fill in */ + obj_loc.oloc = &obj_oloc; + obj_loc.path = &obj_path; + H5G_loc_reset(&obj_loc); - /* Set node information */ - *new_node = link_info->u.address; + /* Find the object */ + if(H5G_loc_find(&grp_loc, path, &obj_loc/*out*/, udata->lapl_id, udata->dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, H5_ITER_ERROR, "object not found") + obj_found = TRUE; - /* Insert into skip list */ - if(H5SL_insert(udata->ref_path_table, new_node, new_node) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, H5_ITER_ERROR, "can't insert path node into table") - } /* end if */ + /* Check for object in same file (handles mounted files) */ + /* (re-verify address, in case we traversed a file mount) */ + if(udata->loc->addr == obj_loc.oloc->addr && udata->loc->file == obj_loc.oloc->file) { + udata->path = H5MM_strdup(path); - /* If it's a group, we recurse into it */ - if(oinfo.type == H5O_TYPE_GROUP) { - H5G_link_iterate_t lnk_op; /* Link operator */ - hsize_t last_obj; - size_t len_needed; /* Length of container string needed */ - size_t len; - - /* Build full path name of group to recurse into */ - len = HDstrlen(udata->container); - len_needed = len + HDstrlen(name) + 2; - if(len_needed > udata->max_container_len) { - void *new_container; /* Pointer to new container */ - - if(NULL == (new_container = H5MM_realloc(udata->container, len_needed))) - HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, H5_ITER_ERROR, "can't allocate path string") - udata->container = new_container; - udata->max_container_len = len_needed; - } /* end if */ - if(!udata->is_root_group) - HDstrcat(udata->container, name); - else - udata->is_root_group = FALSE; - HDstrcat(udata->container, "/"); - - /* Build iterator operator */ - lnk_op.op_type = H5G_LINK_OP_APP; - lnk_op.u.app_op = H5G_refname_iterator; - - ret_value = H5G_obj_iterate(udata->file, udata->container, H5_INDEX_NAME, H5_ITER_NATIVE, (hsize_t)0, &last_obj, &lnk_op, udata, udata->lapl_id, udata->dxpl_id); - - /* If we didn't find the object, truncate the name to not include group name anymore */ - if(!ret_value) - udata->container[len] = '\0'; - } /* end if */ - } /* end else */ + /* We found a match so we return immediately */ + HGOTO_DONE(H5_ITER_STOP) + } /* end if */ } /* end if */ + +done: + if(obj_found && H5G_loc_free(&obj_loc) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTRELEASE, H5_ITER_ERROR, "can't free location") -done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5G_refname_iterator() */ +} /* end H5G_get_name_by_addr_cb() */ /*------------------------------------------------------------------------- - * Function: H5G_free_ref_path_node - * - * Purpose: Free the key for a reference path table node - * - * Return: Non-negative on success, negative on failure + * Function: H5G_get_name_by_addr * - * Programmer: Quincey Koziol - * - * Modifications: - * Leon Arber, Oct. 25, 2006. Moved into H5G from h5ls - * tools lib for looking up path to reference. - * - * Quincey Koziol, Nov. 3, 2006 - * Cleaned up code. - * - *------------------------------------------------------------------------- - */ -static herr_t -H5G_free_ref_path_node(void *item, void UNUSED *key, void UNUSED *operator_data/*in,out*/) -{ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_free_ref_path_node) - - H5FL_FREE(haddr_t, item); - - FUNC_LEAVE_NOAPI(SUCCEED) -} /* end H5G_free_ref_path_node() */ - - -/*------------------------------------------------------------------------- - * Function: H5G_get_refobj_name - * - * Purpose: Tries to figure out the path to a reference. + * Purpose: Tries to figure out the path to an object from it's address * * Return: returns size of path name, and copies it into buffer * pointed to by name if that buffer is big enough. * 0 if it cannot find the path * negative on failure. * - * Programmer: Leon Arber, Nov 1, 2006. - * - * Modifications: - * Quincey Koziol, Nov. 3, 2006 - * Cleaned up code. + * Programmer: Quincey Koziol + * November 4 2007 * *------------------------------------------------------------------------- */ ssize_t -H5G_get_refobj_name(hid_t file, hid_t lapl_id, hid_t dxpl_id, const H5O_loc_t *loc, +H5G_get_name_by_addr(hid_t file, hid_t lapl_id, hid_t dxpl_id, const H5O_loc_t *loc, char *name, size_t size) { - H5G_ref_path_iter_t udata; /* User data for iteration */ - H5G_loc_t root_loc; /* Root location */ - H5L_info_t root_info; /* Link info for root group */ + H5G_gnba_iter_t udata; /* User data for iteration */ + H5G_loc_t root_loc; /* Root group's location */ + hbool_t found_obj = FALSE; /* If we found the object */ herr_t status; /* Status from iteration */ ssize_t ret_value; /* Return value */ - FUNC_ENTER_NOAPI(H5G_get_refobj_name, FAIL) + FUNC_ENTER_NOAPI(H5G_get_name_by_addr, FAIL) - /* Construct the link info for the root group */ + /* Construct the link info for the file's root group */ if(H5G_loc(file, &root_loc) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get root group's location") - HDmemset(&root_info, 0, sizeof(root_info)); - root_info.type = H5L_TYPE_HARD; - root_info.u.address = root_loc.oloc->addr; - - /* Set up user data for iterator */ - udata.file = file; - udata.lapl_id = lapl_id; - udata.dxpl_id = dxpl_id; - udata.is_root_group = TRUE; - if(NULL == (udata.container = H5MM_strdup(""))) - HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate root group name") - udata.max_container_len = 1; - udata.loc = loc; - - /* Create skip list to store reference path information */ - if((udata.ref_path_table = H5SL_create(H5SL_TYPE_HADDR, 0.5, (size_t)16)) == NULL) - HGOTO_ERROR(H5E_SYM, H5E_CANTCREATE, FAIL, "can't create skip list for path nodes") - - /* Iterate over all the objects in the file */ - if((status = H5G_refname_iterator(file, "/", &root_info, &udata)) < 0) - HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "group iteration failed while looking for object name") - else if(status > 0) { + + /* Check for root group being the object looked for */ + if(root_loc.oloc->addr == loc->addr && root_loc.oloc->file == loc->file) { + udata.path = H5MM_strdup(""); + found_obj = TRUE; + } /* end if */ + else { + /* Set up user data for iterator */ + udata.loc = loc; + udata.lapl_id = lapl_id; + udata.dxpl_id = dxpl_id; + udata.path = NULL; + + /* Visit all the links in the file */ + if((status = H5G_visit(file, "/", H5_INDEX_NAME, H5_ITER_NATIVE, H5G_get_name_by_addr_cb, &udata, lapl_id, dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "group traversal failed while looking for object name") + else if(status > 0) + found_obj = TRUE; + } /* end else */ + + /* Check for finding the object */ + if(found_obj) { + size_t full_path_len = HDstrlen(udata.path) + 1; /* Length of path + 1 (for "/") */ + /* Set the length of the full path */ - ret_value = HDstrlen(udata.container); + ret_value = full_path_len; /* If there's a buffer provided, copy into it, up to the limit of its size */ if(name) { - HDstrncpy(name, udata.container, size); + /* Copy the initial path separator */ + HDstrcpy(name, "/"); + + /* Append the rest of the path */ + /* (less one character, for the initial path separator) */ + HDstrncat(name, udata.path, (size - 1)); if((size_t)ret_value >= size) name[size - 1] = '\0'; } /* end if */ @@ -1264,10 +1172,8 @@ H5G_get_refobj_name(hid_t file, hid_t lapl_id, hid_t dxpl_id, const H5O_loc_t *l done: /* Release resources */ - H5MM_xfree(udata.container); - if(udata.ref_path_table) - H5SL_destroy(udata.ref_path_table, H5G_free_ref_path_node, NULL); + H5MM_xfree(udata.path); FUNC_LEAVE_NOAPI(ret_value) -} /* end H5G_get_refobj_name() */ +} /* end H5G_get_name_by_addr() */ diff --git a/src/H5Gnode.c b/src/H5Gnode.c index 442cbf2..86585a0 100644 --- a/src/H5Gnode.c +++ b/src/H5Gnode.c @@ -1275,51 +1275,23 @@ H5G_node_iterate(H5F_t *f, hid_t dxpl_id, const void UNUSED *_lt_key, haddr_t ad if(udata->skip > 0) --udata->skip; else { - const char *name; /* Pointer to link name in heap */ + H5O_link_t lnk; /* Link for entry */ + const char *name; /* Pointer to link name in heap */ /* Get the pointer to the name of the link in the heap */ name = H5HL_offset_into(f, udata->heap, ents[u].name_off); HDassert(name); - /* Check which type of callback to make */ - switch(udata->lnk_op->op_type) { -#ifndef H5_NO_DEPRECATED_SYMBOLS - case H5G_LINK_OP_OLD: - /* Make the old-type application callback */ - ret_value = (udata->lnk_op->u.old_op)(udata->group_id, name, udata->op_data); - break; -#endif /* H5_NO_DEPRECATED_SYMBOLS */ - - case H5G_LINK_OP_APP: - { - H5L_info_t info; /* Link info for entry */ - - /* Make a link info for an entry */ - if(H5G_ent_to_info(f, &info, udata->heap, &ents[u]) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5_ITER_ERROR, "unable to get info for symbol table entry") - - /* Make the application callback */ - ret_value = (udata->lnk_op->u.app_op)(udata->group_id, name, &info, udata->op_data); - } - break; - - case H5G_LINK_OP_LIB: - /* Call the library's callback */ - { - H5O_link_t lnk; /* Link for entry */ - - /* Convert the entry to a link */ - if(H5G_ent_to_link(f, &lnk, udata->heap, &ents[u], name) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTCONVERT, H5_ITER_ERROR, "unable to convert symbol table entry to link") - - /* Call the library's callback */ - ret_value = (udata->lnk_op->u.lib_op)(&lnk, udata->op_data); - - /* Release memory for link object */ - if(H5O_msg_reset(H5O_LINK_ID, &lnk) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, H5_ITER_ERROR, "unable to release link message") - } - } /* end switch */ + /* Convert the entry to a link */ + if(H5G_ent_to_link(f, &lnk, udata->heap, &ents[u], name) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTCONVERT, H5_ITER_ERROR, "unable to convert symbol table entry to link") + + /* Make the callback */ + ret_value = (udata->op)(&lnk, udata->op_data); + + /* Release memory for link object */ + if(H5O_msg_reset(H5O_LINK_ID, &lnk) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, H5_ITER_ERROR, "unable to release link message") } /* end else */ /* Increment the number of entries passed through */ diff --git a/src/H5Gobj.c b/src/H5Gobj.c index 00bac73..8ca8c52 100644 --- a/src/H5Gobj.c +++ b/src/H5Gobj.c @@ -533,7 +533,6 @@ H5G_obj_insert(const H5O_loc_t *grp_oloc, const char *name, H5O_link_t *obj_lnk, H5O_linfo_t new_linfo = H5G_CRT_LINK_INFO_DEF; /* Link information */ H5O_ginfo_t new_ginfo = H5G_CRT_GROUP_INFO_DEF; /* Group information */ H5G_obj_stab_it_ud1_t udata; /* User data for iteration */ - H5G_link_iterate_t lnk_op; /* Link operator */ /* Convert group to "new format" group, in order to hold the information */ @@ -549,12 +548,8 @@ H5G_obj_insert(const H5O_loc_t *grp_oloc, const char *name, H5O_link_t *obj_lnk, udata.grp_oloc = grp_oloc; udata.dxpl_id = dxpl_id; - /* Build iterator operator */ - lnk_op.op_type = H5G_LINK_OP_LIB; - lnk_op.u.lib_op = H5G_obj_stab_to_new_cb; - /* Iterate through all links in "old format" group and insert them into new format */ - if(H5G_stab_iterate(grp_oloc, dxpl_id, H5_ITER_NATIVE, (hsize_t)0, NULL, (hid_t)0, &lnk_op, &udata) < 0) + if(H5G_stab_iterate(grp_oloc, dxpl_id, H5_ITER_NATIVE, (hsize_t)0, NULL, H5G_obj_stab_to_new_cb, &udata) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTNEXT, FAIL, "error iterating over old format links") /* Remove the symbol table message from the group */ @@ -636,36 +631,21 @@ done: *------------------------------------------------------------------------- */ herr_t -H5G_obj_iterate(hid_t loc_id, const char *group_name, +H5G_obj_iterate(const H5O_loc_t *grp_oloc, H5_index_t idx_type, H5_iter_order_t order, hsize_t skip, hsize_t *last_lnk, - H5G_link_iterate_t *lnk_op, void *op_data, hid_t lapl_id, hid_t dxpl_id) + H5G_lib_iterate_t op, void *op_data, hid_t dxpl_id) { - H5G_loc_t loc; /* Location of parent for group */ H5O_linfo_t linfo; /* Link info message */ - hid_t gid = -1; /* ID of group to iterate over */ - H5G_t *grp; /* Pointer to group data structure to iterate over */ herr_t ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5G_obj_iterate, FAIL) /* Sanity check */ - HDassert(group_name); - HDassert(last_lnk); - HDassert(lnk_op && lnk_op->u.lib_op); - - /* - * Open the group on which to operate. We also create a group ID which - * we can pass to the application-defined operator. - */ - if(H5G_loc(loc_id, &loc) < 0) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") - if(NULL == (grp = H5G_open_name(&loc, group_name, lapl_id, dxpl_id))) - HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open group") - if((gid = H5I_register(H5I_GROUP, grp)) < 0) - HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register group") + HDassert(grp_oloc); + HDassert(op); /* Attempt to get the link info for this group */ - if(H5G_obj_get_linfo(&(grp->oloc), &linfo, dxpl_id)) { + if(H5G_obj_get_linfo(grp_oloc, &linfo, dxpl_id)) { /* Check for going out of bounds */ if(skip > 0 && (size_t)skip >= linfo.nlinks) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "index out of bound") @@ -679,13 +659,13 @@ H5G_obj_iterate(hid_t loc_id, const char *group_name, if(H5F_addr_defined(linfo.fheap_addr)) { /* Iterate over the links in the group, building a table of the link messages */ - if((ret_value = H5G_dense_iterate(grp->oloc.file, dxpl_id, &linfo, idx_type, order, skip, last_lnk, gid, lnk_op, op_data)) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTNEXT, FAIL, "error iterating over links") + if((ret_value = H5G_dense_iterate(grp_oloc->file, dxpl_id, &linfo, idx_type, order, skip, last_lnk, op, op_data)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "can't iterate over dense links") } /* end if */ else { /* Get the object's name from the link messages */ - if((ret_value = H5G_compact_iterate(&(grp->oloc), dxpl_id, &linfo, idx_type, order, skip, last_lnk, gid, lnk_op, op_data)) < 0) - HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "can't iterate over links") + if((ret_value = H5G_compact_iterate(grp_oloc, dxpl_id, &linfo, idx_type, order, skip, last_lnk, op, op_data)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "can't iterate over compact links") } /* end else */ } /* end if */ else { @@ -697,14 +677,11 @@ H5G_obj_iterate(hid_t loc_id, const char *group_name, HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "no creation order index to query") /* Iterate over symbol table */ - if((ret_value = H5G_stab_iterate(&(grp->oloc), dxpl_id, order, skip, last_lnk, gid, lnk_op, op_data)) < 0) + if((ret_value = H5G_stab_iterate(grp_oloc, dxpl_id, order, skip, last_lnk, op, op_data)) < 0) HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "can't iterate over symbol table") } /* end else */ done: - if(gid > 0) - H5I_dec_ref(gid); /*also closes 'grp'*/ - FUNC_LEAVE_NOAPI(ret_value) } /* end H5G_obj_iterate() */ @@ -904,7 +881,7 @@ H5G_obj_remove_update_linfo(H5O_loc_t *oloc, H5O_linfo_t *linfo, hid_t dxpl_id) if(can_convert) { /* Insert link messages into group */ for(u = 0; u < linfo->nlinks; u++) - if(H5O_msg_append(oloc->file, dxpl_id, oh, H5O_LINK_ID, 0, H5O_UPDATE_TIME, &(ltable.lnks[u])) < 0) { + if(H5O_msg_append_oh(oloc->file, dxpl_id, oh, H5O_LINK_ID, 0, H5O_UPDATE_TIME, &(ltable.lnks[u])) < 0) { /* Release object header */ if(H5O_unprotect(oloc, oh) < 0) HDONE_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to unprotect dataset object header") diff --git a/src/H5Gpkg.h b/src/H5Gpkg.h index cc017b9..53692c5 100644 --- a/src/H5Gpkg.h +++ b/src/H5Gpkg.h @@ -132,18 +132,16 @@ typedef herr_t (*H5G_lib_iterate_t)(const H5O_link_t *lnk, void *op_data); typedef struct { enum { #ifndef H5_NO_DEPRECATED_SYMBOLS - H5G_LINK_OP_OLD, /* Old application callback */ + H5G_LINK_OP_OLD, /* "Old" application callback */ #endif /* H5_NO_DEPRECATED_SYMBOLS */ - H5G_LINK_OP_APP, /* Application callback */ - H5G_LINK_OP_LIB /* Library internal callback */ + H5G_LINK_OP_NEW /* "New" application callback */ } op_type; union { #ifndef H5_NO_DEPRECATED_SYMBOLS - H5G_iterate_t old_op; /* Old application callback for each link */ + H5G_iterate_t op_old; /* "Old" application callback for each link */ #endif /* H5_NO_DEPRECATED_SYMBOLS */ - H5L_iterate_t app_op; /* Application callback for each link */ - H5G_lib_iterate_t lib_op; /* Library internal callback for each link */ - } u; + H5L_iterate_t op_new; /* "New" application callback for each link */ + } op_func; } H5G_link_iterate_t; /* Data structure to hold table of links for a group */ @@ -208,10 +206,9 @@ typedef struct H5G_bt_lkp_t { */ typedef struct H5G_bt_it_it_t { /* downward */ - hid_t group_id; /*group id to pass to iteration operator */ H5HL_t *heap; /*symbol table heap */ hsize_t skip; /*initial entries to skip */ - H5G_link_iterate_t *lnk_op; /*iteration operator */ + H5G_lib_iterate_t op; /*iteration operator */ void *op_data; /*user-defined operator data */ /* upward */ @@ -337,6 +334,9 @@ H5_DLL H5G_t *H5G_create_named(const H5G_loc_t *loc, const char *name, hid_t lcpl_id, hid_t gcpl_id, hid_t gapl_id, hid_t dxpl_id); H5_DLL H5G_t *H5G_open_name(const H5G_loc_t *loc, const char *name, hid_t gapl_id, hid_t dxpl_id); +H5_DLL herr_t H5G_iterate(hid_t loc_id, const char *group_name, + H5_index_t idx_type, H5_iter_order_t order, hsize_t skip, hsize_t *last_lnk, + const H5G_link_iterate_t *lnk_op, void *op_data, hid_t lapl_id, hid_t dxpl_id); /* * Group hierarchy traversal routines @@ -369,9 +369,8 @@ H5_DLL herr_t H5G_stab_insert(const H5O_loc_t *grp_oloc, const char *name, H5_DLL herr_t H5G_stab_insert_real(H5F_t *f, H5O_stab_t *stab, const char *name, H5O_link_t *obj_lnk, hid_t dxpl_id); H5_DLL herr_t H5G_stab_delete(H5F_t *f, hid_t dxpl_id, const H5O_stab_t *stab); -H5_DLL herr_t H5G_stab_iterate(const H5O_loc_t *oloc, hid_t dxpl_id, - H5_iter_order_t order, hsize_t skip, hsize_t *last_lnk, hid_t gid, - H5G_link_iterate_t *lnk_op, void *op_data); +H5_DLL herr_t H5G_stab_iterate(const H5O_loc_t *oloc, hid_t dxpl_id, H5_iter_order_t order, + hsize_t skip, hsize_t *last_lnk, H5G_lib_iterate_t op, void *op_data); H5_DLL herr_t H5G_stab_count(struct H5O_loc_t *oloc, hsize_t *num_objs, hid_t dxpl_id); H5_DLL herr_t H5G_stab_bh_size(H5F_t *f, hid_t dxpl_id, const H5O_stab_t *stab, H5_ih_info_t *bh_info); @@ -439,8 +438,7 @@ H5_DLL herr_t H5G_link_copy_file(H5F_t *dst_file, hid_t dxpl_id, H5_DLL herr_t H5G_link_sort_table(H5G_link_table_t *ltable, H5_index_t idx_type, H5_iter_order_t order); H5_DLL herr_t H5G_link_iterate_table(const H5G_link_table_t *ltable, - hsize_t skip, hsize_t *last_lnk, hid_t gid, const H5G_link_iterate_t *lnk_op, - void *op_data); + hsize_t skip, hsize_t *last_lnk, const H5G_lib_iterate_t op, void *op_data); H5_DLL herr_t H5G_link_release_table(H5G_link_table_t *ltable); H5_DLL herr_t H5G_link_name_replace(H5F_t *file, hid_t dxpl_id, H5RS_str_t *grp_full_path_r, const H5O_link_t *lnk); @@ -456,9 +454,9 @@ H5_DLL herr_t H5G_compact_remove(const H5O_loc_t *oloc, hid_t dxpl_id, H5_DLL herr_t H5G_compact_remove_by_idx(const H5O_loc_t *oloc, hid_t dxpl_id, const H5O_linfo_t *linfo, H5RS_str_t *grp_full_path_r, H5_index_t idx_type, H5_iter_order_t order, hsize_t n); -H5_DLL herr_t H5G_compact_iterate(H5O_loc_t *oloc, hid_t dxpl_id, const H5O_linfo_t *linfo, - H5_index_t idx_type, H5_iter_order_t order, hsize_t skip, hsize_t *last_lnk, - hid_t gid, H5G_link_iterate_t *lnk_op, void *op_data); +H5_DLL herr_t H5G_compact_iterate(const H5O_loc_t *oloc, hid_t dxpl_id, + const H5O_linfo_t *linfo, H5_index_t idx_type, H5_iter_order_t order, + hsize_t skip, hsize_t *last_lnk, H5G_lib_iterate_t op, void *op_data); H5_DLL herr_t H5G_compact_lookup(H5O_loc_t *grp_oloc, const char *name, H5O_link_t *lnk, hid_t dxpl_id); H5_DLL herr_t H5G_compact_lookup_by_idx(H5O_loc_t *oloc, hid_t dxpl_id, @@ -482,7 +480,7 @@ H5_DLL herr_t H5G_dense_lookup_by_idx(H5F_t *f, hid_t dxpl_id, hsize_t n, H5O_link_t *lnk); H5_DLL herr_t H5G_dense_iterate(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo, H5_index_t idx_type, H5_iter_order_t order, hsize_t skip, hsize_t *last_lnk, - hid_t gid, const H5G_link_iterate_t *lnk_op, void *op_data); + H5G_lib_iterate_t op, void *op_data); H5_DLL ssize_t H5G_dense_get_name_by_idx(H5F_t *f, hid_t dxpl_id, H5O_linfo_t *linfo, H5_index_t idx_type, H5_iter_order_t order, hsize_t n, char *name, size_t size); @@ -505,9 +503,9 @@ H5_DLL H5O_linfo_t * H5G_obj_get_linfo(const H5O_loc_t *grp_oloc, H5O_linfo_t *linfo, hid_t dxpl_id); H5_DLL herr_t H5G_obj_insert(const H5O_loc_t *grp_oloc, const char *name, H5O_link_t *obj_lnk, hbool_t adj_link, hid_t dxpl_id); -H5_DLL herr_t H5G_obj_iterate(hid_t loc_id, const char *group_name, - H5_index_t idx_type, H5_iter_order_t order, hsize_t skip, hsize_t *last_obj, - H5G_link_iterate_t *lnk_op, void *op_data, hid_t lapl_id, hid_t dxpl_id); +H5_DLL herr_t H5G_obj_iterate(const H5O_loc_t *grp_oloc, + H5_index_t idx_type, H5_iter_order_t order, hsize_t skip, hsize_t *last_lnk, + H5G_lib_iterate_t op, void *op_data, hid_t dxpl_id); H5_DLL herr_t H5G_obj_info(H5O_loc_t *oloc, H5G_info_t *grp_info, hid_t dxpl_id); H5_DLL ssize_t H5G_obj_get_name_by_idx(H5O_loc_t *oloc, H5_index_t idx_type, H5_iter_order_t order, hsize_t n, char* name, size_t size, hid_t dxpl_id); diff --git a/src/H5Gprivate.h b/src/H5Gprivate.h index 9717b77..c54f11d 100644 --- a/src/H5Gprivate.h +++ b/src/H5Gprivate.h @@ -162,6 +162,9 @@ H5_DLL herr_t H5G_unmount(H5G_t *grp); #ifndef H5_NO_DEPRECATED_SYMBOLS H5_DLL H5G_obj_t H5G_map_obj_type(H5O_type_t obj_type); #endif /* H5_NO_DEPRECATED_SYMBOLS */ +H5_DLL herr_t H5G_visit(hid_t loc_id, const char *group_name, + H5_index_t idx_type, H5_iter_order_t order, H5L_iterate_t op, void *op_data, + hid_t lapl_id, hid_t dxpl_id); /* * These functions operate on symbol table nodes. @@ -189,7 +192,7 @@ H5_DLL herr_t H5G_name_copy(H5G_name_t *dst, const H5G_name_t *src, H5_copy_dept H5_DLL herr_t H5G_name_free(H5G_name_t *name); H5_DLL ssize_t H5G_get_name(hid_t id, char *name/*out*/, size_t size, hid_t lapl_id, hid_t dxpl_id); -H5_DLL ssize_t H5G_get_refobj_name(hid_t fid, hid_t lapl_id, hid_t dxpl_id, +H5_DLL ssize_t H5G_get_name_by_addr(hid_t fid, hid_t lapl_id, hid_t dxpl_id, const struct H5O_loc_t *loc, char* name, size_t size); /* diff --git a/src/H5Gstab.c b/src/H5Gstab.c index 1887943..61af068 100644 --- a/src/H5Gstab.c +++ b/src/H5Gstab.c @@ -484,8 +484,7 @@ done: */ herr_t H5G_stab_iterate(const H5O_loc_t *oloc, hid_t dxpl_id, H5_iter_order_t order, - hsize_t skip, hsize_t *last_lnk, hid_t gid, - H5G_link_iterate_t *lnk_op, void *op_data) + hsize_t skip, hsize_t *last_lnk, H5G_lib_iterate_t op, void *op_data) { H5HL_t *heap = NULL; /* Local heap for group */ H5O_stab_t stab; /* Info about symbol table */ @@ -496,7 +495,7 @@ H5G_stab_iterate(const H5O_loc_t *oloc, hid_t dxpl_id, H5_iter_order_t order, /* Sanity check */ HDassert(oloc); - HDassert(lnk_op && lnk_op->u.app_op); + HDassert(op); /* Get the B-tree info */ if(NULL == H5O_msg_read(oloc, H5O_STAB_ID, &stab, dxpl_id)) @@ -512,11 +511,10 @@ H5G_stab_iterate(const H5O_loc_t *oloc, hid_t dxpl_id, H5_iter_order_t order, H5G_bt_it_it_t udata; /* User data to pass to B-tree callback */ /* Build udata to pass through H5B_iterate() to H5G_node_iterate() */ - udata.group_id = gid; udata.heap = heap; udata.skip = skip; udata.final_ent = last_lnk; - udata.lnk_op = lnk_op; + udata.op = op; udata.op_data = op_data; /* Iterate over the group members */ @@ -550,7 +548,7 @@ H5G_stab_iterate(const H5O_loc_t *oloc, hid_t dxpl_id, H5_iter_order_t order, HGOTO_ERROR(H5E_SYM, H5E_CANTSORT, FAIL, "error sorting link messages") /* Iterate over links in table */ - if((ret_value = H5G_link_iterate_table(<able, skip, last_lnk, gid, lnk_op, op_data)) < 0) + if((ret_value = H5G_link_iterate_table(<able, skip, last_lnk, op, op_data)) < 0) HERROR(H5E_SYM, H5E_CANTNEXT, "iteration operator failed"); } /* end else */ diff --git a/src/H5HFdbg.c b/src/H5HFdbg.c index 3a7288f..bbbe26f 100644 --- a/src/H5HFdbg.c +++ b/src/H5HFdbg.c @@ -394,7 +394,6 @@ H5HF_dblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, { H5HF_hdr_t *hdr = NULL; /* Fractal heap header info */ H5HF_direct_t *dblock = NULL; /* Fractal heap direct block info */ - H5HF_debug_iter_ud1_t udata; /* User data for callbacks */ size_t blk_prefix_size; /* Size of prefix for block */ size_t amount_free; /* Amount of free space in block */ uint8_t *marker = NULL; /* Track free space for block */ @@ -450,36 +449,43 @@ H5HF_dblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") /* Initialize the free space information for the heap */ - if(H5HF_space_start(hdr, dxpl_id) < 0) + if(H5HF_space_start(hdr, dxpl_id, FALSE) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize heap free space") - /* Prepare user data for section iteration callback */ - udata.stream = stream; - udata.indent = indent; - udata.fwidth = fwidth; - udata.dblock_addr = dblock->block_off; - udata.dblock_size = block_size; - udata.marker = marker; - udata.sect_count = 0; - udata.amount_free = 0; - - /* Print header */ - HDfprintf(stream, "%*sFree Blocks (offset, size):\n", indent, ""); - - /* Iterate over the free space sections, to detect overlaps with this block */ - if(H5FS_sect_iterate(f, dxpl_id, hdr->fspace, H5HF_dblock_debug_cb, &udata) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_BADITER, FAIL, "can't iterate over heap's free space") - - /* Close the free space information */ - if(H5HF_space_close(hdr, dxpl_id) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't release free space info") - - /* Keep the amount of space free */ - amount_free = udata.amount_free; - - /* Check for no free space */ - if(amount_free == 0) - HDfprintf(stream, "%*s<none>\n", indent + 3, ""); + /* If there is a free space manager for the heap, check for sections that overlap this block */ + if(hdr->fspace) { + H5HF_debug_iter_ud1_t udata; /* User data for callbacks */ + + /* Prepare user data for section iteration callback */ + udata.stream = stream; + udata.indent = indent; + udata.fwidth = fwidth; + udata.dblock_addr = dblock->block_off; + udata.dblock_size = block_size; + udata.marker = marker; + udata.sect_count = 0; + udata.amount_free = 0; + + /* Print header */ + HDfprintf(stream, "%*sFree Blocks (offset, size):\n", indent, ""); + + /* Iterate over the free space sections, to detect overlaps with this block */ + if(H5FS_sect_iterate(f, dxpl_id, hdr->fspace, H5HF_dblock_debug_cb, &udata) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_BADITER, FAIL, "can't iterate over heap's free space") + + /* Close the free space information */ + if(H5HF_space_close(hdr, dxpl_id) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't release free space info") + + /* Keep the amount of space free */ + amount_free = udata.amount_free; + + /* Check for no free space */ + if(amount_free == 0) + HDfprintf(stream, "%*s<none>\n", indent + 3, ""); + } /* end if */ + else + amount_free = 0; HDfprintf(stream, "%*s%-*s %.2f%%\n", indent, "", fwidth, "Percent of available space for data used:", @@ -709,7 +715,6 @@ H5HF_sects_debug(H5F_t *f, hid_t dxpl_id, haddr_t fh_addr, FILE *stream, int indent, int fwidth) { H5HF_hdr_t *hdr = NULL; /* Fractal heap header info */ - H5HF_debug_iter_ud2_t udata; /* User data for callbacks */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5HF_sects_debug, FAIL) @@ -730,22 +735,27 @@ H5HF_sects_debug(H5F_t *f, hid_t dxpl_id, haddr_t fh_addr, HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load fractal heap header") /* Initialize the free space information for the heap */ - if(H5HF_space_start(hdr, dxpl_id) < 0) + if(H5HF_space_start(hdr, dxpl_id, FALSE) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize heap free space") - /* Prepare user data for section iteration callback */ - udata.fspace = hdr->fspace; - udata.stream = stream; - udata.indent = indent; - udata.fwidth = fwidth; + /* If there is a free space manager for the heap, iterate over them */ + if(hdr->fspace) { + H5HF_debug_iter_ud2_t udata; /* User data for callbacks */ - /* Iterate over all the free space sections */ - if(H5FS_sect_iterate(f, dxpl_id, hdr->fspace, H5HF_sects_debug_cb, &udata) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_BADITER, FAIL, "can't iterate over heap's free space") + /* Prepare user data for section iteration callback */ + udata.fspace = hdr->fspace; + udata.stream = stream; + udata.indent = indent; + udata.fwidth = fwidth; - /* Close the free space information */ - if(H5HF_space_close(hdr, dxpl_id) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't release free space info") + /* Iterate over all the free space sections */ + if(H5FS_sect_iterate(f, dxpl_id, hdr->fspace, H5HF_sects_debug_cb, &udata) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_BADITER, FAIL, "can't iterate over heap's free space") + + /* Close the free space information */ + if(H5HF_space_close(hdr, dxpl_id) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't release free space info") + } /* end if */ done: if(hdr && H5AC_unprotect(f, dxpl_id, H5AC_FHEAP_HDR, fh_addr, hdr, H5AC__NO_FLAGS_SET) < 0) diff --git a/src/H5HFpkg.h b/src/H5HFpkg.h index 461cba7..702ce08 100644 --- a/src/H5HFpkg.h +++ b/src/H5HFpkg.h @@ -692,7 +692,7 @@ H5_DLL herr_t H5HF_man_iter_offset(H5HF_hdr_t *hdr, H5HF_block_iter_t *biter, H5_DLL hbool_t H5HF_man_iter_ready(H5HF_block_iter_t *biter); /* Free space manipulation routines */ -H5_DLL herr_t H5HF_space_start(H5HF_hdr_t *hdr, hid_t dxpl_id); +H5_DLL herr_t H5HF_space_start(H5HF_hdr_t *hdr, hid_t dxpl_id, hbool_t may_create); H5_DLL herr_t H5HF_space_add(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *node, unsigned flags); H5_DLL htri_t H5HF_space_find(H5HF_hdr_t *hdr, hid_t dxpl_id, hsize_t request, diff --git a/src/H5HFspace.c b/src/H5HFspace.c index 16eae51..77d8b1b 100644 --- a/src/H5HFspace.c +++ b/src/H5HFspace.c @@ -94,7 +94,7 @@ *------------------------------------------------------------------------- */ herr_t -H5HF_space_start(H5HF_hdr_t *hdr, hid_t dxpl_id) +H5HF_space_start(H5HF_hdr_t *hdr, hid_t dxpl_id, hbool_t may_create) { const H5FS_section_class_t *classes[] = { /* Free space section classes implemented for fractal heap */ H5HF_FSPACE_SECT_CLS_SINGLE, @@ -118,19 +118,22 @@ H5HF_space_start(H5HF_hdr_t *hdr, hid_t dxpl_id) HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize free space info") } /* end if */ else { - H5FS_create_t fs_create; /* Free space creation parameters */ - - /* Set the free space creation parameters */ - fs_create.client = H5FS_CLIENT_FHEAP_ID; - fs_create.shrink_percent = H5HF_FSPACE_SHRINK; - fs_create.expand_percent = H5HF_FSPACE_EXPAND; - fs_create.max_sect_size = hdr->man_dtable.cparam.max_direct_size; - fs_create.max_sect_addr = hdr->man_dtable.cparam.max_index; - - /* Create the free space structure for the heap */ - if(NULL == (hdr->fspace = H5FS_create(hdr->f, dxpl_id, &hdr->fs_addr, - &fs_create, NELMTS(classes), classes, hdr))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize free space info") + /* Check if we are allowed to create the free space manager */ + if(may_create) { + H5FS_create_t fs_create; /* Free space creation parameters */ + + /* Set the free space creation parameters */ + fs_create.client = H5FS_CLIENT_FHEAP_ID; + fs_create.shrink_percent = H5HF_FSPACE_SHRINK; + fs_create.expand_percent = H5HF_FSPACE_EXPAND; + fs_create.max_sect_size = hdr->man_dtable.cparam.max_direct_size; + fs_create.max_sect_addr = hdr->man_dtable.cparam.max_index; + + /* Create the free space structure for the heap */ + if(NULL == (hdr->fspace = H5FS_create(hdr->f, dxpl_id, &hdr->fs_addr, + &fs_create, NELMTS(classes), classes, hdr))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize free space info") + } /* end if */ } /* end else */ done: @@ -170,7 +173,7 @@ H5HF_space_add(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *node, /* Check if the free space for the heap has been initialized */ if(!hdr->fspace) - if(H5HF_space_start(hdr, dxpl_id) < 0) + if(H5HF_space_start(hdr, dxpl_id, TRUE) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize heap free space") /* Construct user data */ @@ -204,7 +207,7 @@ done: htri_t H5HF_space_find(H5HF_hdr_t *hdr, hid_t dxpl_id, hsize_t request, H5HF_free_section_t **node) { - htri_t node_found; /* Whether an existing free list node was found */ + htri_t node_found = FALSE; /* Whether an existing free list node was found */ htri_t ret_value; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5HF_space_find) @@ -218,12 +221,13 @@ H5HF_space_find(H5HF_hdr_t *hdr, hid_t dxpl_id, hsize_t request, H5HF_free_secti /* Check if the free space for the heap has been initialized */ if(!hdr->fspace) - if(H5HF_space_start(hdr, dxpl_id) < 0) + if(H5HF_space_start(hdr, dxpl_id, FALSE) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize heap free space") /* Search for free space in the heap */ - if((node_found = H5FS_sect_find(hdr->f, dxpl_id, hdr->fspace, request, (H5FS_section_info_t **)node)) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't locate free space in fractal heap") + if(hdr->fspace) + if((node_found = H5FS_sect_find(hdr->f, dxpl_id, hdr->fspace, request, (H5FS_section_info_t **)node)) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't locate free space in fractal heap") /* Set return value */ ret_value = node_found; @@ -262,12 +266,16 @@ H5HF_space_size(H5HF_hdr_t *hdr, hid_t dxpl_id, hsize_t *fs_size) /* Check if the free space for the heap has been initialized */ if(!hdr->fspace) - if(H5HF_space_start(hdr, dxpl_id) < 0) + if(H5HF_space_start(hdr, dxpl_id, FALSE) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize heap free space") /* Get free space metadata size */ - if(H5FS_size(hdr->f, hdr->fspace, fs_size) < 0) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTGET, FAIL, "can't retrieve FS meta storage info") + if(hdr->fspace) { + if(H5FS_size(hdr->f, hdr->fspace, fs_size) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTGET, FAIL, "can't retrieve FS meta storage info") + } /* end if */ + else + *fs_size = 0; done: FUNC_LEAVE_NOAPI(ret_value) @@ -213,87 +213,91 @@ H5HL_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * udata1, size_t free_block = H5HL_FREE_NULL; H5HL_t *ret_value; - FUNC_ENTER_NOAPI(H5HL_load, NULL); + FUNC_ENTER_NOAPI(H5HL_load, NULL) /* check arguments */ - assert(f); - assert(H5F_addr_defined(addr)); - assert(!udata1); - assert(!udata2); + HDassert(f); + HDassert(H5F_addr_defined(addr)); + HDassert(!udata1); + HDassert(!udata2); /* Cache this for later */ - sizeof_hdr= H5HL_SIZEOF_HDR(f); - assert(sizeof_hdr <= sizeof(hdr)); + sizeof_hdr = H5HL_SIZEOF_HDR(f); + HDassert(sizeof_hdr <= sizeof(hdr)); /* Get the local heap's header */ - if (H5F_block_read(f, H5FD_MEM_LHEAP, addr, sizeof_hdr, dxpl_id, hdr) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_READERROR, NULL, "unable to read heap header"); + if(H5F_block_read(f, H5FD_MEM_LHEAP, addr, sizeof_hdr, dxpl_id, hdr) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_READERROR, NULL, "unable to read heap header") p = hdr; /* Check magic number */ if(HDmemcmp(hdr, H5HL_MAGIC, (size_t)H5HL_SIZEOF_MAGIC)) - HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "bad heap signature"); + HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "bad heap signature") p += H5HL_SIZEOF_MAGIC; /* Version */ - if (H5HL_VERSION!=*p++) - HGOTO_ERROR (H5E_HEAP, H5E_CANTLOAD, NULL, "wrong version number in global heap"); + if(H5HL_VERSION != *p++) + HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "wrong version number in global heap") /* Reserved */ p += 3; /* Allocate space in memory for the heap */ - if (NULL==(heap = H5FL_CALLOC(H5HL_t))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); + if(NULL == (heap = H5FL_CALLOC(H5HL_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") /* heap data size */ H5F_DECODE_LENGTH(f, p, heap->heap_alloc); /* free list head */ H5F_DECODE_LENGTH(f, p, free_block); - if (free_block != H5HL_FREE_NULL && free_block >= heap->heap_alloc) - HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "bad heap free list"); + if(free_block != H5HL_FREE_NULL && free_block >= heap->heap_alloc) + HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "bad heap free list") /* data */ H5F_addr_decode(f, &p, &(heap->addr)); - if (NULL==(heap->chunk = H5FL_BLK_CALLOC(heap_chunk,(sizeof_hdr + heap->heap_alloc)))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); - if (heap->heap_alloc && + if(NULL == (heap->chunk = H5FL_BLK_CALLOC(heap_chunk, (sizeof_hdr + heap->heap_alloc)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + if(heap->heap_alloc && H5F_block_read(f, H5FD_MEM_LHEAP, heap->addr, heap->heap_alloc, dxpl_id, heap->chunk + sizeof_hdr) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "unable to read heap data"); + HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "unable to read heap data") /* Build free list */ - while (H5HL_FREE_NULL != free_block) { - if (free_block >= heap->heap_alloc) - HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "bad heap free list"); - if (NULL==(fl = H5FL_MALLOC(H5HL_free_t))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); + while(H5HL_FREE_NULL != free_block) { + if(free_block >= heap->heap_alloc) + HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "bad heap free list") + if(NULL == (fl = H5FL_MALLOC(H5HL_free_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") fl->offset = free_block; fl->prev = tail; fl->next = NULL; - if (tail) tail->next = fl; + if(tail) + tail->next = fl; tail = fl; - if (!heap->freelist) heap->freelist = fl; + if(!heap->freelist) + heap->freelist = fl; p = heap->chunk + sizeof_hdr + free_block; + H5F_DECODE_LENGTH(f, p, free_block); - H5F_DECODE_LENGTH(f, p, fl->size); + if(free_block == 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "free block size is zero?") + H5F_DECODE_LENGTH(f, p, fl->size); if (fl->offset + fl->size > heap->heap_alloc) - HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "bad heap free list"); - } + HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "bad heap free list") + } /* end while */ /* Set return value */ ret_value = heap; done: - if (!ret_value && heap) { - if(H5HL_dest(f,heap)<0) - HDONE_ERROR(H5E_HEAP, H5E_CANTFREE, NULL, "unable to destroy local heap collection"); - } + if(!ret_value && heap) + if(H5HL_dest(f,heap) < 0) + HDONE_ERROR(H5E_HEAP, H5E_CANTFREE, NULL, "unable to destroy local heap collection") - FUNC_LEAVE_NOAPI(ret_value); -} + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HL_load() */ /*------------------------------------------------------------------------- @@ -963,6 +967,45 @@ H5HL_insert(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t buf_size, const void * need_more = need_size; new_heap_alloc = heap->heap_alloc + need_more; +#if 0 /* JRM */ /* delete this once we are convinced that the general + * fix will do the job. + */ +/* + * XXX: This is a _total_ hack, a real kludge. :-/ The metadata cache currently + * responds very poorly when an object is inserted into the cache (or + * resized) that is larger than the current cache size. It waits through + * an entire 'epoch' of cache operations to resize the cache larger (getting + * _very_ poor performance), instead of immediately accommodating the large + * object by increasing the cache size. + * + * So, what we are doing here is to look at the current cache size, check + * if the new local heap will overwhelm the cache and, if so, resize the + * cache to be large enough to hold the new local heap block along with + * leaving room for other objects in the cache. + * + * John will be working on a fix inside the cache itself, so this special + * case code here can be removed when he's finished. - QAK, 2007/12/21 + */ +{ + H5AC_cache_config_t mdc_config; + + /* Retrieve the current cache information */ + mdc_config.version = H5AC__CURR_CACHE_CONFIG_VERSION; + if(H5AC_get_cache_auto_resize_config(f->shared->cache, &mdc_config) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, (size_t)-1, "H5AC_get_cache_auto_resize_config() failed.") + + /* Check if the current cache will get blown out by adding this heap + * block and resize it if so. + */ + if((2 * new_heap_alloc) >= mdc_config.initial_size) { + mdc_config.set_initial_size = TRUE; + mdc_config.initial_size = 2 * new_heap_alloc; + + if(H5AC_set_cache_auto_resize_config(f->shared->cache, &mdc_config) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, (size_t)-1, "H5AC_set_cache_auto_resize_config() failed.") + } /* end if */ +} +#endif /* JRM */ HDassert(heap->heap_alloc < new_heap_alloc); H5_CHECK_OVERFLOW(heap->heap_alloc, size_t, hsize_t); H5_CHECK_OVERFLOW(new_heap_alloc, size_t, hsize_t); @@ -1171,11 +1171,11 @@ H5Literate(hid_t grp_id, H5_index_t idx_type, H5_iter_order_t order, last_lnk = 0; /* Build link operator info */ - lnk_op.op_type = H5G_LINK_OP_APP; - lnk_op.u.app_op = op; + lnk_op.op_type = H5G_LINK_OP_NEW; + lnk_op.op_func.op_new = op; /* Iterate over the links */ - if((ret_value = H5G_obj_iterate(grp_id, ".", idx_type, order, idx, &last_lnk, &lnk_op, op_data, H5P_DEFAULT, H5AC_ind_dxpl_id)) < 0) + if((ret_value = H5G_iterate(grp_id, ".", idx_type, order, idx, &last_lnk, &lnk_op, op_data, H5P_DEFAULT, H5AC_ind_dxpl_id)) < 0) HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "link iteration failed") /* Set the index we stopped at */ @@ -1243,11 +1243,11 @@ H5Literate_by_name(hid_t loc_id, const char *group_name, last_lnk = 0; /* Build link operator info */ - lnk_op.op_type = H5G_LINK_OP_APP; - lnk_op.u.app_op = op; + lnk_op.op_type = H5G_LINK_OP_NEW; + lnk_op.op_func.op_new = op; /* Iterate over the links */ - if((ret_value = H5G_obj_iterate(loc_id, group_name, idx_type, order, idx, &last_lnk, &lnk_op, op_data, lapl_id, H5AC_ind_dxpl_id)) < 0) + if((ret_value = H5G_iterate(loc_id, group_name, idx_type, order, idx, &last_lnk, &lnk_op, op_data, lapl_id, H5AC_ind_dxpl_id)) < 0) HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "link iteration failed") /* Set the index we stopped at */ @@ -1258,6 +1258,126 @@ done: FUNC_LEAVE_API(ret_value) } /* end H5Literate_by_name() */ + +/*------------------------------------------------------------------------- + * Function: H5Lvisit + * + * Purpose: Recursively visit all the links in a group and all + * the groups that are linked to from that group. Links within + * each group are visited according to the order within the + * specified index (unless the specified index does not exist for + * a particular group, then the "name" index is used). + * + * NOTE: Each _link_ reachable from the initial group will only be + * visited once. However, because an object may be reached from + * more than one link, the visitation may call the application's + * callback with more than one link that points to a particular + * _object_. + * + * Return: Success: The return value of the first operator that + * returns non-zero, or zero if all members were + * processed with no operator returning non-zero. + * + * Failure: Negative if something goes wrong within the + * library, or the negative value returned by one + * of the operators. + * + * Programmer: Quincey Koziol + * November 24 2007 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Lvisit(hid_t grp_id, H5_index_t idx_type, H5_iter_order_t order, + H5L_iterate_t op, void *op_data) +{ + H5I_type_t id_type; /* Type of ID */ + herr_t ret_value; /* Return value */ + + FUNC_ENTER_API(H5Lvisit, FAIL) + H5TRACE5("e", "iIiIox*x", grp_id, idx_type, order, op, op_data); + + /* Check args */ + id_type = H5I_get_type(grp_id); + if(!(H5I_GROUP == id_type || H5I_FILE == id_type)) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid argument") + if(idx_type <= H5_INDEX_UNKNOWN || idx_type >= H5_INDEX_N) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index type specified") + if(order <= H5_ITER_UNKNOWN || order >= H5_ITER_N) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid iteration order specified") + if(!op) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no callback operator specified") + + /* Call internal group visitation routine */ + if((ret_value = H5G_visit(grp_id, ".", idx_type, order, op, op_data, H5P_DEFAULT, H5AC_ind_dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "link visitation failed") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Lvisit() */ + + +/*------------------------------------------------------------------------- + * Function: H5Lvisit_by_name + * + * Purpose: Recursively visit all the links in a group and all + * the groups that are linked to from that group. Links within + * each group are visited according to the order within the + * specified index (unless the specified index does not exist for + * a particular group, then the "name" index is used). + * + * NOTE: Each _link_ reachable from the initial group will only be + * visited once. However, because an object may be reached from + * more than one link, the visitation may call the application's + * callback with more than one link that points to a particular + * _object_. + * + * Return: Success: The return value of the first operator that + * returns non-zero, or zero if all members were + * processed with no operator returning non-zero. + * + * Failure: Negative if something goes wrong within the + * library, or the negative value returned by one + * of the operators. + * + * Programmer: Quincey Koziol + * November 3 2007 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Lvisit_by_name(hid_t loc_id, const char *group_name, H5_index_t idx_type, + H5_iter_order_t order, H5L_iterate_t op, void *op_data, hid_t lapl_id) +{ + herr_t ret_value; /* Return value */ + + FUNC_ENTER_API(H5Lvisit_by_name, FAIL) + H5TRACE7("e", "i*sIiIox*xi", loc_id, group_name, idx_type, order, op, op_data, + lapl_id); + + /* Check args */ + if(!group_name || !*group_name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified") + if(idx_type <= H5_INDEX_UNKNOWN || idx_type >= H5_INDEX_N) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index type specified") + if(order <= H5_ITER_UNKNOWN || order >= H5_ITER_N) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid iteration order specified") + if(!op) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no callback operator specified") + if(H5P_DEFAULT == lapl_id) + lapl_id = H5P_LINK_ACCESS_DEFAULT; + else + if(TRUE != H5P_isa_class(lapl_id, H5P_LINK_ACCESS)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not link access property list ID") + + /* Call internal group visitation routine */ + if((ret_value = H5G_visit(loc_id, group_name, idx_type, order, op, op_data, lapl_id, H5AC_ind_dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "link visitation failed") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Lvisit_by_name() */ + /* *------------------------------------------------------------------------- *------------------------------------------------------------------------- diff --git a/src/H5Lpublic.h b/src/H5Lpublic.h index 1645e4b..823b046 100644 --- a/src/H5Lpublic.h +++ b/src/H5Lpublic.h @@ -170,6 +170,11 @@ H5_DLL herr_t H5Literate(hid_t grp_id, H5_index_t idx_type, H5_DLL herr_t H5Literate_by_name(hid_t loc_id, const char *group_name, H5_index_t idx_type, H5_iter_order_t order, hsize_t *idx, H5L_iterate_t op, void *op_data, hid_t lapl_id); +H5_DLL herr_t H5Lvisit(hid_t grp_id, H5_index_t idx_type, H5_iter_order_t order, + H5L_iterate_t op, void *op_data); +H5_DLL herr_t H5Lvisit_by_name(hid_t loc_id, const char *group_name, + H5_index_t idx_type, H5_iter_order_t order, H5L_iterate_t op, + void *op_data, hid_t lapl_id); /* UD link functions */ H5_DLL herr_t H5Lcreate_ud(hid_t link_loc_id, const char *link_name, @@ -21,25 +21,59 @@ * * Purpose: File memory management functions. * - * Modifications: - * Robb Matzke, 5 Aug 1997 - * Added calls to H5E. - * - * Robb Matzke, 8 Jun 1998 - * Implemented a very simple free list which is not persistent and which - * is lossy. - * *------------------------------------------------------------------------- */ + +/****************/ +/* Module Setup */ +/****************/ + #define H5F_PACKAGE /*suppress error about including H5Fpkg */ -#include "H5private.h" -#include "H5Eprivate.h" -#include "H5Fpkg.h" -#include "H5FDprivate.h" -#include "H5MFprivate.h" -#include "H5FDmulti.h" /*multiple files partitioned by mem usage */ +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5Fpkg.h" /* File access */ +#include "H5MFprivate.h" /* File memory management */ + + +/****************/ +/* Local Macros */ +/****************/ + + +/******************/ +/* Local Typedefs */ +/******************/ + + +/********************/ +/* Package Typedefs */ +/********************/ + + +/********************/ +/* Local Prototypes */ +/********************/ +static hbool_t H5MF_alloc_overflow(const H5F_t *f, hsize_t size); + + +/*********************/ +/* Package Variables */ +/*********************/ + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ /*------------------------------------------------------------------------- @@ -51,16 +85,12 @@ * is being requested. * * Return: Success: The file address of new chunk. - * * Failure: HADDR_UNDEF * * Programmer: Robb Matzke * matzke@llnl.gov * Jul 11 1997 * - * Modifications: - * Robb Matzke, 1999-08-04 - * Modified to work with the virtual file layer. *------------------------------------------------------------------------- */ haddr_t @@ -68,33 +98,29 @@ H5MF_alloc(const H5F_t *f, H5FD_mem_t type, hid_t dxpl_id, hsize_t size) { haddr_t ret_value; - FUNC_ENTER_NOAPI(H5MF_alloc, HADDR_UNDEF); + FUNC_ENTER_NOAPI(H5MF_alloc, HADDR_UNDEF) /* check arguments */ - assert(f); - assert(size > 0); + HDassert(f); + HDassert(size > 0); /* Fail if we don't have write access */ - if (0==(f->intent & H5F_ACC_RDWR)) - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, HADDR_UNDEF, "file is read-only"); - - /* Check that the file can address the new space */ - if( H5MF_alloc_overflow(f, size) ) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, HADDR_UNDEF, "not enough address space in file"); + if(0 == (f->intent & H5F_ACC_RDWR)) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, HADDR_UNDEF, "file is read-only") /* Allocate space from the virtual file layer */ - if (HADDR_UNDEF==(ret_value=H5FD_alloc(f->shared->lf, type, dxpl_id, size))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, HADDR_UNDEF, "file allocation failed"); + if(HADDR_UNDEF == (ret_value = H5FD_alloc(f->shared->lf, type, dxpl_id, size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, HADDR_UNDEF, "file allocation failed") /* Convert absolute file address to relative file address */ - assert(ret_value>=f->shared->base_addr); + HDassert(ret_value >= f->shared->base_addr); /* Set return value */ ret_value -= f->shared->base_addr; done: - FUNC_LEAVE_NOAPI(ret_value); -} + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5MF_alloc() */ /*------------------------------------------------------------------------- @@ -109,44 +135,35 @@ done: * matzke@llnl.gov * Jul 17 1997 * - * Modifications: - * Robb Matzke, 1999-07-28 - * The ADDR argument is passed by value - * - * Robb Matzke, 1999-08-03 - * Modified to use the virtual file layer. *------------------------------------------------------------------------- */ herr_t H5MF_xfree(const H5F_t *f, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, hsize_t size) { - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOFUNC(H5MF_xfree); + FUNC_ENTER_NOAPI_NOFUNC(H5MF_xfree) /* check arguments */ - assert(f); - if (!H5F_addr_defined(addr) || 0 == size) + HDassert(f); + if(!H5F_addr_defined(addr) || 0 == size) HGOTO_DONE(SUCCEED); - assert(addr!=0); + HDassert(addr != 0); /* Convert relative address to absolute address */ addr += f->shared->base_addr; /* Allow virtual file layer to free block */ - if (H5FD_free(f->shared->lf, type, dxpl_id, addr, size)<0) { + if(H5FD_free(f->shared->lf, type, dxpl_id, addr, size) < 0) { #ifdef H5MF_DEBUG - if (H5DEBUG(MF)) { - fprintf(H5DEBUG(MF), - "H5MF_free: lost %lu bytes of file storage\n", - (unsigned long)size); - } + if(H5DEBUG(MF)) + fprintf(H5DEBUG(MF), "H5MF_free: lost %lu bytes of file storage\n", (unsigned long)size); #endif - } + } /* end if */ done: - FUNC_LEAVE_NOAPI(ret_value); -} + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5MF_xfree() */ /*------------------------------------------------------------------------- @@ -169,19 +186,11 @@ done: * circumstances the library may return the same address. * * Return: Success: The relative file address of the new block. - * * Failure: HADDR_UNDEF * * Programmer: Robb Matzke * Thursday, April 16, 1998 * - * Modifications: - * Robb Matzke, 1999-07-28 - * The ORIG_ADDR is passed by value. The name of NEW_ADDR has - * been changed to NEW_ADDR_P - * - * Robb Matzke, 1999-08-04 - * Modified to work with the virtual file layer. *------------------------------------------------------------------------- */ haddr_t @@ -190,31 +199,25 @@ H5MF_realloc(H5F_t *f, H5FD_mem_t type, hid_t dxpl_id, haddr_t old_addr, hsize_t { haddr_t ret_value; - FUNC_ENTER_NOAPI(H5MF_realloc, HADDR_UNDEF); + FUNC_ENTER_NOAPI(H5MF_realloc, HADDR_UNDEF) /* Convert old relative address to absolute address */ old_addr += f->shared->base_addr; - /* Check that the file can address the new space. */ - /* In the worst case, this means adding new_size bytes to the end of the file. */ - if( H5MF_alloc_overflow(f, new_size) ) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, HADDR_UNDEF, "not enough address space in file"); - /* Reallocate memory from the virtual file layer */ - ret_value = H5FD_realloc(f->shared->lf, type, dxpl_id, old_addr, old_size, - new_size); - if (HADDR_UNDEF==ret_value) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, HADDR_UNDEF, "unable to allocate new file memory"); + ret_value = H5FD_realloc(f->shared->lf, type, dxpl_id, old_addr, old_size, new_size); + if(HADDR_UNDEF == ret_value) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, HADDR_UNDEF, "unable to allocate new file memory") /* Convert return value to relative address */ - assert(ret_value>=f->shared->base_addr); + HDassert(ret_value >= f->shared->base_addr); /* Set return value */ ret_value -= f->shared->base_addr; done: - FUNC_LEAVE_NOAPI(ret_value); -} + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5MF_realloc() */ /*------------------------------------------------------------------------- @@ -224,8 +227,8 @@ done: * F is the file whose space is being allocated, SIZE is the amount * of space needed. * - * Return: 0 if no overflow would result - * 1 if overflow would result (the allocation should not be allowed) + * Return: FALSE if no overflow would result + * TRUE if overflow would result (the allocation should not be allowed) * * Programmer: James Laird * Nat Furrer @@ -233,46 +236,33 @@ done: * *------------------------------------------------------------------------- */ -hbool_t +static hbool_t H5MF_alloc_overflow(const H5F_t *f, hsize_t size) { - hsize_t space_needed = 0; /* Accumulator variable */ - size_t c; /* Local index variable */ - hbool_t ret_value; /* Return value */ + haddr_t eoa; /* End-of-allocation in the file */ + haddr_t space_avail; /* Unallocated space still available in file */ + hbool_t ret_value; /* Return value */ - FUNC_ENTER_NOAPI_NOFUNC(H5MF_alloc_overflow) + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5MF_alloc_overflow) /* Start with the current end of the file's address. */ - space_needed = (hsize_t)H5F_get_eoa(f); - - HDassert(H5F_addr_defined(space_needed)); + eoa = H5F_get_eoa(f); + HDassert(H5F_addr_defined(eoa)); - /* Subtract the file's base address to get the actual amount of - * space being used: - * (end of allocated space - beginning of allocated space) + /* Subtract EOA from the file's maximum address to get the actual amount of + * addressable space left in the file. */ - HDassert(H5F_BASE_ADDR(f) < space_needed); - space_needed -= (hsize_t)H5F_BASE_ADDR(f); + HDassert(f->shared->maxaddr >= eoa); + space_avail = (hsize_t)(f->shared->maxaddr - eoa); - /* Add the amount of space requested for this allocation */ - space_needed += size; - - /* Ensure that this final number is less than the file's - * address space. We do this by shifting in multiples - * of 16 bits because some systems will do nothing if - * we shift by 64 bits all at once (<cough> Linux <cough>). - * Thus, we break one shift into several smaller shifts. - */ - for(c=0; c < H5F_SIZEOF_ADDR(f); c += 2) - space_needed = space_needed >> 16; - - if(space_needed != 0) + /* Ensure that there's enough room left in the file for something of this size */ + if(size > space_avail) ret_value = TRUE; else ret_value = FALSE; FUNC_LEAVE_NOAPI(ret_value) -} +} /* end H5MF_alloc_overflow() */ /*------------------------------------------------------------------------- @@ -281,14 +271,11 @@ H5MF_alloc_overflow(const H5F_t *f, hsize_t size) * Purpose: Check if a block in the file can be extended. * * Return: Success: TRUE(1)/FALSE(0) - * * Failure: FAIL * * Programmer: Quincey Koziol * Friday, June 11, 2004 * - * Modifications: - * *------------------------------------------------------------------------- */ htri_t @@ -296,21 +283,17 @@ H5MF_can_extend(H5F_t *f, H5FD_mem_t type, haddr_t addr, hsize_t size, hsize_t e { htri_t ret_value; /* Return value */ - FUNC_ENTER_NOAPI(H5MF_can_extend, FAIL); + FUNC_ENTER_NOAPI(H5MF_can_extend, FAIL) /* Convert old relative address to absolute address */ addr += H5F_BASE_ADDR(f); /* Pass the request down to the virtual file layer */ - if((ret_value=H5FD_can_extend(f->shared->lf, type, addr, size, extra_requested))<0) + if((ret_value = H5FD_can_extend(f->shared->lf, type, addr, size, extra_requested)) < 0) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate new file memory"); - /* Make sure there is enough addressable space to satisfy the request */ - if (ret_value == TRUE) - ret_value = !H5MF_alloc_overflow(f, extra_requested); - done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5MF_can_extend() */ @@ -320,14 +303,11 @@ done: * Purpose: Extend a block in the file. * * Return: Success: Non-negative - * * Failure: Negative * * Programmer: Quincey Koziol * Saturday, June 12, 2004 * - * Modifications: - * *------------------------------------------------------------------------- */ herr_t @@ -335,19 +315,16 @@ H5MF_extend(H5F_t *f, H5FD_mem_t type, haddr_t addr, hsize_t size, hsize_t extra { herr_t ret_value; /* Return value */ - FUNC_ENTER_NOAPI(H5MF_extend, FAIL); - - /* Make sure there is enough addressable space to satisfy the request */ - if ( H5MF_alloc_overflow(f, extra_requested) ) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate new file memory: out of address space"); + FUNC_ENTER_NOAPI(H5MF_extend, FAIL) - /* Convert old relative address to absolute address */ + /* Convert relative address to absolute address */ addr += H5F_BASE_ADDR(f); /* Pass the request down to the virtual file layer */ - if((ret_value=H5FD_extend(f->shared->lf, type, addr, size, extra_requested))<0) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate new file memory"); + if((ret_value = H5FD_extend(f->shared->lf, type, addr, size, extra_requested)) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate new file memory") done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5MF_extend() */ + diff --git a/src/H5MFprivate.h b/src/H5MFprivate.h index b3f0d17..e01a9f6 100644 --- a/src/H5MFprivate.h +++ b/src/H5MFprivate.h @@ -29,9 +29,8 @@ #define _H5MFprivate_H /* Private headers needed by this file */ -#include "H5private.h" -#include "H5Fprivate.h" -#include "H5FDprivate.h" /*file driver */ +#include "H5Fprivate.h" /* File access */ +#include "H5FDprivate.h" /* File Drivers */ /* * Feature: Define H5MF_DEBUG on the compiler command line if you want to @@ -49,10 +48,10 @@ H5_DLL herr_t H5MF_xfree(const H5F_t *f, H5FD_mem_t type, hid_t dxpl_id, haddr_t hsize_t size); H5_DLL haddr_t H5MF_realloc(H5F_t *f, H5FD_mem_t type, hid_t dxpl_id, haddr_t old_addr, hsize_t old_size, hsize_t new_size); -H5_DLL hbool_t H5MF_alloc_overflow(const H5F_t *f, hsize_t size); H5_DLL htri_t H5MF_can_extend(H5F_t *f, H5FD_mem_t type, haddr_t addr, hsize_t size, hsize_t extra_requested); H5_DLL herr_t H5MF_extend(H5F_t *f, H5FD_mem_t type, haddr_t addr, hsize_t size, hsize_t extra_requested); -#endif +#endif /* end _H5MFprivate_H */ + @@ -58,6 +58,17 @@ /* Local Typedefs */ /******************/ +/* User data for recursive traversal over objects from a group */ +typedef struct { + hid_t obj_id; /* The ID for the starting group */ + H5G_loc_t *start_loc; /* Location of starting group */ + hid_t lapl_id; /* LAPL for walking across links */ + hid_t dxpl_id; /* DXPL for operations */ + H5SL_t *visited; /* Skip list for tracking visited nodes */ + H5O_iterate_t op; /* Application callback */ + void *op_data; /* Application's op data */ +} H5O_iter_visit_ud_t; + /********************/ /* Package Typedefs */ @@ -71,6 +82,9 @@ static herr_t H5O_delete_oh(H5F_t *f, hid_t dxpl_id, H5O_t *oh); static const H5O_obj_class_t *H5O_obj_class(const H5O_loc_t *loc, hid_t dxpl_id); static herr_t H5O_obj_type_real(H5O_t *oh, H5O_type_t *obj_type); +static herr_t H5O_visit(hid_t loc_id, const char *obj_name, H5_index_t idx_type, + H5_iter_order_t order, H5O_iterate_t op, void *op_data, hid_t lapl_id, + hid_t dxpl_id); /*********************/ @@ -79,9 +93,11 @@ static herr_t H5O_obj_type_real(H5O_t *oh, H5O_type_t *obj_type); /* Header message ID to class mapping */ -/* Remember to increment H5O_MSG_TYPES in H5Opkg.h when adding a new + +/* Remember to increment H5O_MSG_TYPES in H5Opkg.h when adding a new * message. */ + const H5O_msg_class_t *const H5O_msg_class_g[] = { H5O_MSG_NULL, /*0x0000 Null */ H5O_MSG_SDSPACE, /*0x0001 Dataspace */ @@ -148,6 +164,9 @@ H5FL_BLK_DEFINE(chunk_image); /* Declare external the free list for time_t's */ H5FL_EXTERN(time_t); +/* Declare external the free list for H5_obj_t's */ +H5FL_EXTERN(H5_obj_t); + /*******************/ /* Local Variables */ @@ -841,6 +860,130 @@ done: /*------------------------------------------------------------------------- + * Function: H5Ovisit + * + * Purpose: Recursively visit an object and all the objects reachable + * from it. If the starting object is a group, all the objects + * linked to from that group will be visited. Links within + * each group are visited according to the order within the + * specified index (unless the specified index does not exist for + * a particular group, then the "name" index is used). + * + * NOTE: Soft links and user-defined links are ignored during + * this operation. + * + * NOTE: Each _object_ reachable from the initial group will only + * be visited once. If multiple hard links point to the same + * object, the first link to the object's path (according to the + * iteration index and iteration order given) will be used to in + * the callback about the object. + * + * Return: Success: The return value of the first operator that + * returns non-zero, or zero if all members were + * processed with no operator returning non-zero. + * + * Failure: Negative if something goes wrong within the + * library, or the negative value returned by one + * of the operators. + * + * Programmer: Quincey Koziol + * November 25 2007 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Ovisit(hid_t obj_id, H5_index_t idx_type, H5_iter_order_t order, + H5O_iterate_t op, void *op_data) +{ + herr_t ret_value; /* Return value */ + + FUNC_ENTER_API(H5Ovisit, FAIL) + H5TRACE5("e", "iIiIox*x", obj_id, idx_type, order, op, op_data); + + /* Check args */ + if(idx_type <= H5_INDEX_UNKNOWN || idx_type >= H5_INDEX_N) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index type specified") + if(order <= H5_ITER_UNKNOWN || order >= H5_ITER_N) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid iteration order specified") + if(!op) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no callback operator specified") + + /* Call internal object visitation routine */ + if((ret_value = H5O_visit(obj_id, ".", idx_type, order, op, op_data, H5P_LINK_ACCESS_DEFAULT, H5AC_ind_dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "object visitation failed") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Ovisit() */ + + +/*------------------------------------------------------------------------- + * Function: H5Ovisit_by_name + * + * Purpose: Recursively visit an object and all the objects reachable + * from it. If the starting object is a group, all the objects + * linked to from that group will be visited. Links within + * each group are visited according to the order within the + * specified index (unless the specified index does not exist for + * a particular group, then the "name" index is used). + * + * NOTE: Soft links and user-defined links are ignored during + * this operation. + * + * NOTE: Each _object_ reachable from the initial group will only + * be visited once. If multiple hard links point to the same + * object, the first link to the object's path (according to the + * iteration index and iteration order given) will be used to in + * the callback about the object. + * + * Return: Success: The return value of the first operator that + * returns non-zero, or zero if all members were + * processed with no operator returning non-zero. + * + * Failure: Negative if something goes wrong within the + * library, or the negative value returned by one + * of the operators. + * + * Programmer: Quincey Koziol + * November 24 2007 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Ovisit_by_name(hid_t loc_id, const char *obj_name, H5_index_t idx_type, + H5_iter_order_t order, H5O_iterate_t op, void *op_data, hid_t lapl_id) +{ + herr_t ret_value; /* Return value */ + + FUNC_ENTER_API(H5Ovisit_by_name, FAIL) + H5TRACE7("e", "i*sIiIox*xi", loc_id, obj_name, idx_type, order, op, op_data, + lapl_id); + + /* Check args */ + if(!obj_name || !*obj_name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name") + if(idx_type <= H5_INDEX_UNKNOWN || idx_type >= H5_INDEX_N) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index type specified") + if(order <= H5_ITER_UNKNOWN || order >= H5_ITER_N) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid iteration order specified") + if(!op) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no callback operator specified") + if(H5P_DEFAULT == lapl_id) + lapl_id = H5P_LINK_ACCESS_DEFAULT; + else + if(TRUE != H5P_isa_class(lapl_id, H5P_LINK_ACCESS)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not link access property list ID") + + /* Call internal object visitation routine */ + if((ret_value = H5O_visit(loc_id, obj_name, idx_type, order, op, op_data, lapl_id, H5AC_ind_dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "object visitation failed") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Ovisit_by_name() */ + + +/*------------------------------------------------------------------------- * Function: H5Oclose * * Purpose: Close an open file object. @@ -953,6 +1096,14 @@ H5O_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, hid_t ocpl_id, oh->version = H5O_VERSION_1; oh->sizeof_size = H5F_SIZEOF_SIZE(f); oh->sizeof_addr = H5F_SIZEOF_ADDR(f); +#ifdef H5O_ENABLE_BAD_MESG_COUNT + /* Check whether the "bad message count" property is set */ + if(H5P_exist_plist(oc_plist, H5O_BAD_MESG_COUNT_NAME) > 0) { + /* Retrieve bad message count flag */ + if(H5P_get(oc_plist, H5O_BAD_MESG_COUNT_NAME, &oh->store_bad_mesg_count) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't get bad message count flag") + } /* end if */ +#endif /* H5O_ENABLE_BAD_MESG_COUNT */ /* Set initial status flags */ oh->flags = oh_flags; @@ -1141,7 +1292,7 @@ H5O_open_name(H5G_loc_t *loc, const char *name, hid_t lapl_id) loc_found = TRUE; /* Open the object */ - if((ret_value = H5O_open_by_loc(&obj_loc, H5AC_dxpl_id)) < 0) + if((ret_value = H5O_open_by_loc(&obj_loc, H5AC_ind_dxpl_id)) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open object") done: @@ -2138,8 +2289,7 @@ H5O_get_info(H5O_loc_t *oloc, hid_t dxpl_id, hbool_t want_ih_info, H5O_info_t *o HDmemset(oinfo, 0, sizeof(*oinfo)); /* Retrieve the file's fileno */ - if(H5F_get_fileno(oloc->file, &oinfo->fileno) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "unable to read fileno") + H5F_GET_FILENO(oloc->file, oinfo->fileno); /* Set the object's address */ oinfo->addr = oloc->addr; @@ -2429,3 +2579,300 @@ H5O_get_oh_addr(const H5O_t *oh) FUNC_LEAVE_NOAPI(oh->chunk[0].addr) } /* end H5O_get_oh_addr() */ + +/*------------------------------------------------------------------------- + * Function: H5O_get_rc_and_type + * + * Purpose: Retrieve an object's reference count and type + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * November 4 2007 + * + *------------------------------------------------------------------------- + */ +herr_t +H5O_get_rc_and_type(const H5O_loc_t *oloc, hid_t dxpl_id, unsigned *rc, H5O_type_t *otype) +{ + H5O_t *oh = NULL; /* Object header */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5O_get_rc_and_type, FAIL) + + /* Check args */ + HDassert(oloc); + HDassert(rc); + HDassert(otype); + + /* Get the object header */ + if(NULL == (oh = H5AC_protect(oloc->file, dxpl_id, H5AC_OHDR, oloc->addr, NULL, NULL, H5AC_READ))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header") + + /* Set the object's reference count */ + *rc = oh->nlink; + + /* Retrieve the type of the object */ + if(H5O_obj_type_real(oh, otype) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to determine object type") + +done: + if(oh && H5AC_unprotect(oloc->file, dxpl_id, H5AC_OHDR, oloc->addr, oh, H5AC__NO_FLAGS_SET) < 0) + HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_get_rc_and_type() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_free_visit_visited + * + * Purpose: Free the key for an object visited during a group traversal + * + * Return: Non-negative on success, negative on failure + * + * Programmer: Quincey Koziol + * Nov 25, 2007 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_free_visit_visited(void *item, void UNUSED *key, void UNUSED *operator_data/*in,out*/) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_free_visit_visited) + + H5FL_FREE(H5_obj_t, item); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5O_free_visit_visited() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_visit_cb + * + * Purpose: Callback function for recursively visiting objects from a group + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * Nov 25, 2007 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_visit_cb(hid_t UNUSED group, const char *name, const H5L_info_t *linfo, + void *_udata) +{ + H5O_iter_visit_ud_t *udata = (H5O_iter_visit_ud_t *)_udata; /* User data for callback */ + H5G_loc_t obj_loc; /* Location of object */ + H5G_name_t obj_path; /* Object's group hier. path */ + H5O_loc_t obj_oloc; /* Object's object location */ + hbool_t obj_found = FALSE; /* Object at 'name' found */ + herr_t ret_value = H5_ITER_CONT; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5O_visit_cb) + + /* Sanity check */ + HDassert(name); + HDassert(linfo); + HDassert(udata); + + /* Check if this is a hard link */ + if(linfo->type == H5L_TYPE_HARD) { + H5_obj_t obj_pos; /* Object "position" for this object */ + + /* Set up opened group location to fill in */ + obj_loc.oloc = &obj_oloc; + obj_loc.path = &obj_path; + H5G_loc_reset(&obj_loc); + + /* Find the object using the LAPL passed in */ + /* (Correctly handles mounted files) */ + if(H5G_loc_find(udata->start_loc, name, &obj_loc/*out*/, udata->lapl_id, udata->dxpl_id) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, H5_ITER_ERROR, "object not found") + obj_found = TRUE; + + /* Construct unique "position" for this object */ + H5F_GET_FILENO(obj_oloc.file, obj_pos.fileno); + obj_pos.addr = obj_oloc.addr; + + /* Check if we've seen the object the link references before */ + if(NULL == H5SL_search(udata->visited, &obj_pos)) { + H5O_info_t oinfo; /* Object info */ + + /* Get the object's info */ + if(H5O_get_info(&obj_oloc, udata->dxpl_id, TRUE, &oinfo) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, H5_ITER_ERROR, "unable to get object info") + + /* Make the application callback */ + ret_value = (udata->op)(udata->obj_id, name, &oinfo, udata->op_data); + + /* Check for continuing to visit objects */ + if(ret_value == H5_ITER_CONT) { + /* If its ref count is > 1, we add it to the list of visited objects */ + /* (because it could come up again during traversal) */ + if(oinfo.rc > 1) { + H5_obj_t *new_node; /* New object node for visited list */ + + /* Allocate new object "position" node */ + if((new_node = H5FL_MALLOC(H5_obj_t)) == NULL) + HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, H5_ITER_ERROR, "can't allocate object node") + + /* Set node information */ + *new_node = obj_pos; + + /* Add to list of visited objects */ + if(H5SL_insert(udata->visited, new_node, new_node) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, H5_ITER_ERROR, "can't insert object node into visited list") + } /* end if */ + } /* end if */ + } /* end if */ + } /* end if */ + +done: + /* Release resources */ + if(obj_found && H5G_loc_free(&obj_loc) < 0) + HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, H5_ITER_ERROR, "can't free location") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_visit_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_visit + * + * Purpose: Recursively visit an object and all the objects reachable + * from it. If the starting object is a group, all the objects + * linked to from that group will be visited. Links within + * each group are visited according to the order within the + * specified index (unless the specified index does not exist for + * a particular group, then the "name" index is used). + * + * NOTE: Soft links and user-defined links are ignored during + * this operation. + * + * NOTE: Each _object_ reachable from the initial group will only + * be visited once. If multiple hard links point to the same + * object, the first link to the object's path (according to the + * iteration index and iteration order given) will be used to in + * the callback about the object. + * + * Return: Success: The return value of the first operator that + * returns non-zero, or zero if all members were + * processed with no operator returning non-zero. + * + * Failure: Negative if something goes wrong within the + * library, or the negative value returned by one + * of the operators. + * + * Programmer: Quincey Koziol + * November 24 2007 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_visit(hid_t loc_id, const char *obj_name, H5_index_t idx_type, + H5_iter_order_t order, H5O_iterate_t op, void *op_data, hid_t lapl_id, + hid_t dxpl_id) +{ + H5O_iter_visit_ud_t udata; /* User data for callback */ + H5G_loc_t loc; /* Location of reference object */ + H5G_loc_t obj_loc; /* Location used to open object */ + H5G_name_t obj_path; /* Opened object group hier. path */ + H5O_loc_t obj_oloc; /* Opened object object location */ + hbool_t loc_found = FALSE; /* Entry at 'name' found */ + H5O_info_t oinfo; /* Object info struct */ + hid_t obj_id = (-1); /* ID of object */ + herr_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5O_visit, FAIL) + + /* Portably initialize user data struct to zeros */ + HDmemset(&udata, 0, sizeof(udata)); + + /* Check args */ + if(H5G_loc(loc_id, &loc) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") + + /* Set up opened group location to fill in */ + obj_loc.oloc = &obj_oloc; + obj_loc.path = &obj_path; + H5G_loc_reset(&obj_loc); + + /* Find the object's location */ + if(H5G_loc_find(&loc, obj_name, &obj_loc/*out*/, lapl_id, dxpl_id) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "object not found") + loc_found = TRUE; + + /* Get the object's info */ + if(H5O_get_info(&obj_oloc, dxpl_id, TRUE, &oinfo) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to get object info") + + /* Open the object */ + /* (Takes ownership of the obj_loc information) */ + if((obj_id = H5O_open_by_loc(&obj_loc, dxpl_id)) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, FAIL, "unable to open object") + + /* Make callback for starting object */ + if((ret_value = op(obj_id, ".", &oinfo, op_data)) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_BADITER, FAIL, "can't visit objects") + + /* Check for object being a group */ + if(oinfo.type == H5O_TYPE_GROUP) { + H5G_loc_t start_loc; /* Location of starting group */ + + /* Get the location of the starting group */ + if(H5G_loc(obj_id, &start_loc) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") + + /* Set up user data for visiting links */ + udata.obj_id = obj_id; + udata.start_loc = &start_loc; + udata.lapl_id = lapl_id; + udata.dxpl_id = dxpl_id; + udata.op = op; + udata.op_data = op_data; + + /* Create skip list to store visited object information */ + if((udata.visited = H5SL_create(H5SL_TYPE_OBJ, 0.5, (size_t)16)) == NULL) + HGOTO_ERROR(H5E_OHDR, H5E_CANTCREATE, FAIL, "can't create skip list for visited objects") + + /* If its ref count is > 1, we add it to the list of visited objects */ + /* (because it could come up again during traversal) */ + if(oinfo.rc > 1) { + H5_obj_t *obj_pos; /* New object node for visited list */ + + /* Allocate new object "position" node */ + if((obj_pos = H5FL_MALLOC(H5_obj_t)) == NULL) + HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, FAIL, "can't allocate object node") + + /* Construct unique "position" for this object */ + obj_pos->fileno = oinfo.fileno; + obj_pos->addr = oinfo.addr; + + /* Add to list of visited objects */ + if(H5SL_insert(udata.visited, obj_pos, obj_pos) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "can't insert object node into visited list") + } /* end if */ + + /* Call internal group visitation routine */ + if((ret_value = H5G_visit(obj_id, ".", idx_type, order, H5O_visit_cb, &udata, lapl_id, dxpl_id)) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_BADITER, FAIL, "object visitation failed") + } /* end if */ + +done: + if(obj_id > 0) { + if(H5I_dec_ref(obj_id) < 0) + HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "unable to close object") + } /* end if */ + else if(loc_found && H5G_loc_free(&obj_loc) < 0) + HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "can't free location") + if(udata.visited) + H5SL_destroy(udata.visited, H5O_free_visit_visited, NULL); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_visit() */ + + diff --git a/src/H5Ocache.c b/src/H5Ocache.c index b5c8c7d..0d5765e 100644 --- a/src/H5Ocache.c +++ b/src/H5Ocache.c @@ -580,10 +580,25 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1, if(merged_null_msgs) oh->cache_info.is_dirty = TRUE; +/* Don't check for the incorrect # of object header messages bug unless we've + * enabled strict format checking. This allows for older files, created with + * a version of the library that had a bug in tracking the correct # of header + * messages to be read in without the library fussing about things. -QAK + */ +#ifdef H5_STRICT_FORMAT_CHECKS /* Sanity check for the correct # of messages in object header */ if(oh->version == H5O_VERSION_1) if((oh->nmesgs + merged_null_msgs) != nmesgs) HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "corrupt object header - too few messages") +#else /* H5_STRICT_FORMAT_CHECKS */ + /* Check for incorrect # of messages in object header and if we have write + * access on the file, flag the object header as dirty, so it gets fixed. + */ + if(oh->version == H5O_VERSION_1) + if((oh->nmesgs + merged_null_msgs) != nmesgs && + (H5F_get_intent(f) & H5F_ACC_RDWR)) + oh->cache_info.is_dirty = TRUE; +#endif /* H5_STRICT_FORMAT_CHECKS */ #ifdef H5O_DEBUG H5O_assert(oh); @@ -710,7 +725,12 @@ H5O_assert(oh); *p++ = 0; /* Number of messages */ - UINT16ENCODE(p, oh->nmesgs); +#ifdef H5O_ENABLE_BAD_MESG_COUNT + if(oh->store_bad_mesg_count) + UINT16ENCODE(p, (oh->nmesgs - 1)) + else +#endif /* H5O_ENABLE_BAD_MESG_COUNT */ + UINT16ENCODE(p, oh->nmesgs); /* Link count */ UINT32ENCODE(p, oh->nlink); diff --git a/src/H5Olinfo.c b/src/H5Olinfo.c index 660b0e1..384353c 100644 --- a/src/H5Olinfo.c +++ b/src/H5Olinfo.c @@ -513,7 +513,6 @@ H5O_linfo_post_copy_file(const H5O_loc_t *src_oloc, const void *mesg_src, /* Check for copying dense link storage */ if(H5F_addr_defined(linfo_src->fheap_addr)) { H5O_linfo_postcopy_ud_t udata; /* User data for iteration callback */ - H5G_link_iterate_t lnk_op; /* Link operator */ /* Set up dense link iteration user data */ udata.src_oloc = src_oloc; @@ -522,12 +521,8 @@ H5O_linfo_post_copy_file(const H5O_loc_t *src_oloc, const void *mesg_src, udata.dxpl_id = dxpl_id; udata.cpy_info = cpy_info; - /* Build iterator operator */ - lnk_op.op_type = H5G_LINK_OP_LIB; - lnk_op.u.lib_op = H5O_linfo_post_copy_file_cb; - /* Iterate over the links in the group, building a table of the link messages */ - if(H5G_dense_iterate(src_oloc->file, dxpl_id, linfo_src, H5_INDEX_NAME, H5_ITER_NATIVE, (hsize_t)0, NULL, (hid_t)0, &lnk_op, &udata) < 0) + if(H5G_dense_iterate(src_oloc->file, dxpl_id, linfo_src, H5_INDEX_NAME, H5_ITER_NATIVE, (hsize_t)0, NULL, H5O_linfo_post_copy_file_cb, &udata) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTNEXT, FAIL, "error iterating over links") } /* end if */ diff --git a/src/H5Omessage.c b/src/H5Omessage.c index b3d94d9..29a7e79 100644 --- a/src/H5Omessage.c +++ b/src/H5Omessage.c @@ -136,7 +136,7 @@ H5O_msg_create(const H5O_loc_t *loc, unsigned type_id, unsigned mesg_flags, HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header") /* Go append message to object header */ - if(H5O_msg_append(loc->file, dxpl_id, oh, type_id, mesg_flags, update_flags, mesg) < 0) + if(H5O_msg_append_oh(loc->file, dxpl_id, oh, type_id, mesg_flags, update_flags, mesg) < 0) HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to append to object header") done: @@ -148,7 +148,7 @@ done: /*------------------------------------------------------------------------- - * Function: H5O_msg_append + * Function: H5O_msg_append_oh * * Purpose: Simplified version of H5O_msg_create, used when creating a new * object header message (usually during object creation) and @@ -165,13 +165,13 @@ done: *------------------------------------------------------------------------- */ herr_t -H5O_msg_append(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned type_id, +H5O_msg_append_oh(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned type_id, unsigned mesg_flags, unsigned update_flags, void *mesg) { const H5O_msg_class_t *type; /* Original H5O class type for the ID */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5O_msg_append, FAIL) + FUNC_ENTER_NOAPI(H5O_msg_append_oh, FAIL) /* check args */ HDassert(f); @@ -189,7 +189,7 @@ H5O_msg_append(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned type_id, done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5O_msg_append() */ +} /* end H5O_msg_append_oh() */ /*------------------------------------------------------------------------- @@ -301,6 +301,53 @@ done: /*------------------------------------------------------------------------- + * Function: H5O_msg_write_oh + * + * Purpose: Modifies an existing message or creates a new message. + * + * The UPDATE_FLAGS argument are flags that allow the caller + * to skip updating the modification time or reseting the message + * data. This is useful when several calls to H5O_msg_write will be + * made in a sequence. + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Dec 6 2007 + * + *------------------------------------------------------------------------- + */ +herr_t +H5O_msg_write_oh(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned type_id, + unsigned mesg_flags, unsigned update_flags, void *mesg) +{ + const H5O_msg_class_t *type; /* Actual H5O class type for the ID */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5O_msg_write_oh, FAIL) + + /* check args */ + HDassert(f); + HDassert(oh); + HDassert(H5O_ATTR_ID != type_id); /* Attributes are modified in another routine */ + HDassert(type_id < NELMTS(H5O_msg_class_g)); + type = H5O_msg_class_g[type_id]; /* map the type ID to the actual type object */ + HDassert(type); + HDassert(mesg); + HDassert(0 == (mesg_flags & ~H5O_MSG_FLAG_BITS)); + + /* Call the "real" modify routine */ + if(H5O_msg_write_real(f, dxpl_id, oh, type, mesg_flags, update_flags, mesg) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to write object header message") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_msg_write_oh() */ + + +/*------------------------------------------------------------------------- * Function: H5O_msg_write_real * * Purpose: Modifies an existing message or creates a new message. diff --git a/src/H5Opkg.h b/src/H5Opkg.h index 94af802..69feff4 100644 --- a/src/H5Opkg.h +++ b/src/H5Opkg.h @@ -253,6 +253,12 @@ struct H5O_t { /* File-specific information (not stored) */ size_t sizeof_size; /* Size of file sizes */ size_t sizeof_addr; /* Size of file addresses */ +#ifdef H5O_ENABLE_BAD_MESG_COUNT + hbool_t store_bad_mesg_count; /* Flag to indicate that a bad message count should be stored */ + /* (This is to simulate a bug in earlier + * versions of the library) + */ +#endif /* H5O_ENABLE_BAD_MESG_COUNT */ /* Object information (stored) */ hbool_t has_refcount_msg; /* Whether the object has a ref. count message */ diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h index 393d4e1..19da881 100644 --- a/src/H5Oprivate.h +++ b/src/H5Oprivate.h @@ -93,6 +93,10 @@ typedef struct H5O_t H5O_t; #define H5O_BOGUS_MSG_FLAGS_NAME "bogus msg flags" /* Flags for 'bogus' message */ #define H5O_BOGUS_MSG_FLAGS_SIZE sizeof(uint8_t) #endif /* H5O_ENABLE_BOGUS */ +#ifdef H5O_ENABLE_BAD_MESG_COUNT +#define H5O_BAD_MESG_COUNT_NAME "bad message count" /* Flag setting bad message count */ +#define H5O_BAD_MESG_COUNT_SIZE sizeof(hbool_t) +#endif /* H5O_ENABLE_BAD_MESG_COUNT */ /* ========= Object Copy properties ============ */ #define H5O_CPY_OPTION_NAME "copy object" /* Copy options */ @@ -571,13 +575,13 @@ H5_DLL herr_t H5O_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, H5_DLL herr_t H5O_open(H5O_loc_t *loc); H5_DLL herr_t H5O_close(H5O_loc_t *loc); H5_DLL int H5O_link(const H5O_loc_t *loc, int adjust, hid_t dxpl_id); -H5_DLL struct H5O_t *H5O_protect(H5O_loc_t *loc, hid_t dxpl_id); -H5_DLL herr_t H5O_unprotect(H5O_loc_t *loc, struct H5O_t *oh); +H5_DLL H5O_t *H5O_protect(H5O_loc_t *loc, hid_t dxpl_id); +H5_DLL herr_t H5O_unprotect(H5O_loc_t *loc, H5O_t *oh); H5_DLL herr_t H5O_touch(H5O_loc_t *loc, hbool_t force, hid_t dxpl_id); -H5_DLL herr_t H5O_touch_oh(H5F_t *f, hid_t dxpl_id, struct H5O_t *oh, +H5_DLL herr_t H5O_touch_oh(H5F_t *f, hid_t dxpl_id, H5O_t *oh, hbool_t force); #ifdef H5O_ENABLE_BOGUS -H5_DLL herr_t H5O_bogus_oh(H5F_t *f, hid_t dxpl_id, struct H5O_t *oh, unsigned mesg_flags); +H5_DLL herr_t H5O_bogus_oh(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned mesg_flags); #endif /* H5O_ENABLE_BOGUS */ H5_DLL herr_t H5O_delete(H5F_t *f, hid_t dxpl_id, haddr_t addr); H5_DLL herr_t H5O_get_info(H5O_loc_t *oloc, hid_t dxpl_id, hbool_t want_ih_info, @@ -588,14 +592,17 @@ H5_DLL hid_t H5O_open_name(H5G_loc_t *loc, const char *name, hid_t lapl_id); H5_DLL herr_t H5O_get_nlinks(const H5O_loc_t *loc, hid_t dxpl_id, hsize_t *nlinks); H5_DLL void *H5O_obj_create(H5F_t *f, H5O_type_t obj_type, void *crt_info, H5G_loc_t *obj_loc, hid_t dxpl_id); H5_DLL haddr_t H5O_get_oh_addr(const H5O_t *oh); +H5_DLL herr_t H5O_get_rc_and_type(const H5O_loc_t *oloc, hid_t dxpl_id, unsigned *rc, H5O_type_t *otype); /* Object header message routines */ H5_DLL herr_t H5O_msg_create(const H5O_loc_t *loc, unsigned type_id, unsigned mesg_flags, unsigned update_flags, void *mesg, hid_t dxpl_id); -H5_DLL herr_t H5O_msg_append(H5F_t *f, hid_t dxpl_id, struct H5O_t *oh, unsigned type_id, +H5_DLL herr_t H5O_msg_append_oh(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned type_id, unsigned mesg_flags, unsigned update_flags, void *mesg); -H5_DLL herr_t H5O_msg_write(const H5O_loc_t *loc, unsigned type_id, unsigned flags, - unsigned update_flags, void *mesg, hid_t dxpl_id); +H5_DLL herr_t H5O_msg_write(const H5O_loc_t *loc, unsigned type_id, + unsigned mesg_flags, unsigned update_flags, void *mesg, hid_t dxpl_id); +H5_DLL herr_t H5O_msg_write_oh(H5F_t *f, hid_t dxpl_id, H5O_t *oh, + unsigned type_id, unsigned mesg_flags, unsigned update_flags, void *mesg); H5_DLL void *H5O_msg_read(const H5O_loc_t *loc, unsigned type_id, void *mesg, hid_t dxpl_id); H5_DLL herr_t H5O_msg_reset(unsigned type_id, void *native); diff --git a/src/H5Opublic.h b/src/H5Opublic.h index 6ddd565..acce42c 100644 --- a/src/H5Opublic.h +++ b/src/H5Opublic.h @@ -52,13 +52,13 @@ * but we need to assign each kind of message to a different bit so that * one index can hold multiple types.) */ -#define H5O_MESG_NONE_FLAG 0x0000 /* No shared messages */ -#define H5O_MESG_SDSPACE_FLAG 0x0001 /* Simple Dataspace Message. */ -#define H5O_MESG_DTYPE_FLAG 0x0002 /* Datatype Message. */ -#define H5O_MESG_FILL_FLAG 0x0004 /* Fill Value Message. */ -#define H5O_MESG_PLINE_FLAG 0x0008 /* Filter pipeline message. */ -#define H5O_MESG_ATTR_FLAG 0x0010 /* Attribute Message. */ -#define H5O_MESG_ALL_FLAG (H5O_MESG_SDSPACE_FLAG | H5O_MESG_DTYPE_FLAG | H5O_MESG_FILL_FLAG | H5O_MESG_PLINE_FLAG | H5O_MESG_ATTR_FLAG) +#define H5O_SHMESG_NONE_FLAG 0x0000 /* No shared messages */ +#define H5O_SHMESG_SDSPACE_FLAG ((unsigned)1 << 0x0001) /* Simple Dataspace Message. */ +#define H5O_SHMESG_DTYPE_FLAG ((unsigned)1 << 0x0003) /* Datatype Message. */ +#define H5O_SHMESG_FILL_FLAG ((unsigned)1 << 0x0005) /* Fill Value Message. */ +#define H5O_SHMESG_PLINE_FLAG ((unsigned)1 << 0x000b) /* Filter pipeline message. */ +#define H5O_SHMESG_ATTR_FLAG ((unsigned)1 << 0x000c) /* Attribute Message. */ +#define H5O_SHMESG_ALL_FLAG (H5O_SHMESG_SDSPACE_FLAG | H5O_SHMESG_DTYPE_FLAG | H5O_SHMESG_FILL_FLAG | H5O_SHMESG_PLINE_FLAG | H5O_SHMESG_ATTR_FLAG) /* Object header status flag definitions */ #define H5O_HDR_CHUNK0_SIZE 0x03 /* 2-bit field indicating # of bytes to store the size of chunk 0's data */ @@ -124,6 +124,10 @@ typedef struct H5O_info_t { /* Typedef for message creation indexes */ typedef uint32_t H5O_msg_crt_idx_t; +/* Prototype for H5Ovisit/H5Ovisit_by_name() operator */ +typedef herr_t (*H5O_iterate_t)(hid_t obj, const char *name, const H5O_info_t *info, + void *op_data); + /********************/ /* Public Variables */ @@ -159,6 +163,11 @@ H5_DLL herr_t H5Oset_comment_by_name(hid_t loc_id, const char *name, H5_DLL ssize_t H5Oget_comment(hid_t obj_id, char *comment, size_t bufsize); H5_DLL ssize_t H5Oget_comment_by_name(hid_t loc_id, const char *name, char *comment, size_t bufsize, hid_t lapl_id); +H5_DLL herr_t H5Ovisit(hid_t obj_id, H5_index_t idx_type, H5_iter_order_t order, + H5O_iterate_t op, void *op_data); +H5_DLL herr_t H5Ovisit_by_name(hid_t loc_id, const char *obj_name, + H5_index_t idx_type, H5_iter_order_t order, H5O_iterate_t op, + void *op_data, hid_t lapl_id); H5_DLL herr_t H5Oclose(hid_t object_id); /* Symbols defined for compatibility with previous versions of the HDF5 API. diff --git a/src/H5Pfapl.c b/src/H5Pfapl.c index 44ac3c4..f31d1a4 100644 --- a/src/H5Pfapl.c +++ b/src/H5Pfapl.c @@ -1877,76 +1877,163 @@ done: /*------------------------------------------------------------------------- - * Function: H5Pset_latest_format - * - * Purpose: Indicates that the library should always use the latest version - * of the file format when creating objects. If this flag is not set, - * the library will always use the most backwardly compatibly format - * possible that can store the information about an object. - * - * The default value is set to FALSE (creating backwardly compatible files) + * Function: H5Pset_libver_bounds + * + * Purpose: Indicates which versions of the file format the library should + * use when creating objects. LOW is the earliest version of the HDF5 + * library that is guaranteed to be able to access the objects created + * (the format of some objects in an HDF5 file may not have changed between + * versions of the HDF5 library, possibly allowing earlier versions of the + * HDF5 library to access those objects) and HIGH is the latest version + * of the library required to access the objects created (later versions + * of the HDF5 library will also be able to access those objects). + * + * LOW is used to require that objects use a more modern format and HIGH + * is used to restrict objects from using a more modern format. + * + * The special values of H5F_FORMAT_EARLIEST and H5F_FORMAT_LATEST can be + * used in the following manner: Setting LOW and HIGH to H5F_FORMAT_LATEST + * will produce files whose objects use the latest version of the file + * format available in the current HDF5 library for each object created. + * Setting LOW and HIGH to H5F_FORMAT_EARLIEST will produce files that that + * always require the use of the earliest version of the file format for + * each object created. [NOTE! LOW=HIGH=H5F_FORMAT_EARLIEST is not + * implemented as of version 1.8.0 and setting LOW and HIGH to + * H5F_FORMAT_EARLIEST will produce an error currently]. + * + * Currently, the only two valid combinations for this routine are: + * LOW = H5F_FORMAT_EARLIEST and HIGH = H5F_FORMAT_LATEST (the default + * setting, which creates objects with the ealiest version possible for + * each object, but no upper limit on the version allowed to be created if + * a newer version of an object's format is required to support a feature + * requested with an HDF5 library API routine), and LOW = H5F_FORMAT_LATEST + * and HIGH = H5F_FORMAT_LATEST (which is described above). + * + * The LOW and HIGH values set with this routine at imposed with each + * HDF5 library API call that creates objects in the file. API calls that + * would violate the LOW or HIGH format bound will fail. + * + * Setting the LOW and HIGH values will not affect reading/writing existing + * objects, only the creation of new objects. + * + * Note: Eventually we want to add more values to the H5F_libver_t + * enumerated type that indicate library release values where the file + * format was changed (like "H5F_FORMAT_1_2_0" for the file format changes + * in the 1.2.x release branch and possily even "H5F_FORMAT_1_4_2" for + * a change mid-way through the 1.4.x release branch, etc). + * + * Adding more values will allow applications to make settings like the + * following: + * LOW = H5F_FORMAT_EARLIEST, HIGH = H5F_FORMAT_1_2_0 => Create objects + * with the earliest possible format and don't allow any objects + * to be created that require a library version greater than 1.2.x + * (This is the "make certain that <application> linked with v1.2.x + * of the library can read the file produced" use case) + * + * LOW = H5F_FORMAT_1_4_2, HIGH = H5F_FORMAT_LATEST => create objects + * with at least the version of their format that the 1.4.2 library + * uses and allow any later version of the object's format + * necessary to represent features used. + * (This is the "make certain to take advantage of <new feature> + * in the file format" use case (maybe <new feature> is smaller + * or scales better than an ealier version, which would otherwise + * be used)) + * + * LOW = H5F_FORMAT_1_2_0, HIGH = H5F_FORMAT_1_6_0 => creates objects + * with at least the version of their format that the 1.2.x library + * uses and don't allow any objects to be created that require a + * library version greater than 1.6.x. + * (Not certain of a particular use case for these settings, + * although its probably just the logical combination of the + * previous two; it just falls out as possible/logical (if it turns + * out to be hard to implement in some way, we can always disallow + * it)) + * + * Note #2: We talked about whether to include enum values for only library + * versions where the format changed and decided it would be less confusing + * for application developers if we include enum values for _all_ library + * releases and then map down to the previous actual library release which + * had a format change. * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol - * Friday, September 9, 2006 + * Sunday, December 30, 2007 * *------------------------------------------------------------------------- */ herr_t -H5Pset_latest_format(hid_t plist_id, hbool_t latest) +H5Pset_libver_bounds(hid_t plist_id, H5F_libver_t low, + H5F_libver_t high) { H5P_genplist_t *plist; /* Property list pointer */ + hbool_t latest; /* Whether to use the latest version or not */ herr_t ret_value = SUCCEED; /* return value */ - FUNC_ENTER_API(H5Pset_latest_format, FAIL) - H5TRACE2("e", "ib", plist_id, latest); + FUNC_ENTER_API(H5Pset_libver_bounds, FAIL) + H5TRACE3("e", "iFvFv", plist_id, low, high); + + /* Check args */ + /* (Note that this is _really_ restricted right now, we'll want to loosen + * this up more as we add features - QAK) + */ + if(high != H5F_LIBVER_LATEST) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid high library version bound") /* Get the plist structure */ if(NULL == (plist = H5P_object_verify(plist_id, H5P_FILE_ACCESS))) HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") /* Set values */ + latest = (low == H5F_LIBVER_LATEST) ? TRUE : FALSE; if(H5P_set(plist, H5F_ACS_LATEST_FORMAT_NAME, &latest) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set 'latest format' flag") + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set library version bounds") done: FUNC_LEAVE_API(ret_value) -} /* end H5Pset_latest_format() */ +} /* end H5Pset_libver_bounds() */ /*------------------------------------------------------------------------- - * Function: H5Pget_latest_format + * Function: H5Pget_libver_bounds * - * Purpose: Returns the current settings for the 'latest format' flag + * Purpose: Returns the current settings for the library version format bounds * from a file access property list. * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol - * Friday, September 9, 2006 + * Thursday, January 3, 2008 * *------------------------------------------------------------------------- */ herr_t -H5Pget_latest_format(hid_t plist_id, hbool_t *latest/*out*/) +H5Pget_libver_bounds(hid_t plist_id, H5F_libver_t *low/*out*/, + H5F_libver_t *high/*out*/) { H5P_genplist_t *plist; /* Property list pointer */ + hbool_t latest; /* Whether to use the latest version or not */ herr_t ret_value = SUCCEED; /* return value */ - FUNC_ENTER_API(H5Pget_latest_format, FAIL) - H5TRACE2("e", "ix", plist_id, latest); + FUNC_ENTER_API(H5Pget_libver_bounds, FAIL) + H5TRACE3("e", "ixx", plist_id, low, high); /* Get the plist structure */ if(NULL == (plist = H5P_object_verify(plist_id, H5P_FILE_ACCESS))) HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") /* Get value */ - if(latest) - if(H5P_get(plist, H5F_ACS_LATEST_FORMAT_NAME, latest) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get 'latest format' flag") + if(H5P_get(plist, H5F_ACS_LATEST_FORMAT_NAME, &latest) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get library version bounds") + + /* Check for setting values to return */ + /* (Again, this is restricted now, we'll need to open it up later -QAK) */ + if(low) + *low = latest ? H5F_LIBVER_LATEST : H5F_LIBVER_EARLIEST; + if(high) + *high = H5F_LIBVER_LATEST; done: FUNC_LEAVE_API(ret_value) -} /* end H5Pget_latest_format() */ +} /* end H5Pget_libver_bounds() */ diff --git a/src/H5Pfcpl.c b/src/H5Pfcpl.c index 6345961..8fd4909 100644 --- a/src/H5Pfcpl.c +++ b/src/H5Pfcpl.c @@ -757,7 +757,7 @@ H5Pset_shared_mesg_index(hid_t plist_id, unsigned index_num, unsigned mesg_type_ H5TRACE4("e", "iIuIuIu", plist_id, index_num, mesg_type_flags, min_mesg_size); /* Check arguments */ - if(mesg_type_flags > H5O_MESG_ALL_FLAG) + if(mesg_type_flags > H5O_SHMESG_ALL_FLAG) HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "unrecognized flags in mesg_type_flags"); /* Get the plist structure */ diff --git a/src/H5Ppublic.h b/src/H5Ppublic.h index 214aaec..8382101 100644 --- a/src/H5Ppublic.h +++ b/src/H5Ppublic.h @@ -265,14 +265,16 @@ H5_DLL herr_t H5Pset_sieve_buf_size(hid_t fapl_id, size_t size); H5_DLL herr_t H5Pget_sieve_buf_size(hid_t fapl_id, size_t *size/*out*/); H5_DLL herr_t H5Pset_small_data_block_size(hid_t fapl_id, hsize_t size); H5_DLL herr_t H5Pget_small_data_block_size(hid_t fapl_id, hsize_t *size/*out*/); -H5_DLL herr_t H5Pset_latest_format(hid_t plist_id, hbool_t latest); -H5_DLL herr_t H5Pget_latest_format(hid_t plist_id, hbool_t *latest); +H5_DLL herr_t H5Pset_libver_bounds(hid_t plist_id, H5F_libver_t low, + H5F_libver_t high); +H5_DLL herr_t H5Pget_libver_bounds(hid_t plist_id, H5F_libver_t *low, + H5F_libver_t *high); H5_DLL herr_t H5Pset_journal(hid_t fapl_id, const char *journal_file); /* Dataset creation property list (DCPL) routines */ H5_DLL herr_t H5Pset_layout(hid_t plist_id, H5D_layout_t layout); H5_DLL H5D_layout_t H5Pget_layout(hid_t plist_id); -H5_DLL herr_t H5Pset_chunk(hid_t plist_id, int ndims, const hsize_t dim[]); +H5_DLL herr_t H5Pset_chunk(hid_t plist_id, int ndims, const hsize_t dim[/*ndims*/]); H5_DLL int H5Pget_chunk(hid_t plist_id, int max_ndims, hsize_t dim[]/*out*/); H5_DLL herr_t H5Pset_external(hid_t plist_id, const char *name, off_t offset, hsize_t size); @@ -887,7 +887,7 @@ H5R_get_name(H5F_t *f, hid_t lapl_id, hid_t dxpl_id, hid_t id, H5R_type_t ref_ty HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, FAIL, "can't retrieve file ID") /* Get name, length, etc. */ - if((ret_value = H5G_get_refobj_name(file_id, lapl_id, dxpl_id, &oloc, name, size)) < 0) + if((ret_value = H5G_get_name_by_addr(file_id, lapl_id, dxpl_id, &oloc, name, size)) < 0) HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, FAIL, "can't determine name") done: @@ -1055,27 +1055,20 @@ done: *------------------------------------------------------------------------- */ herr_t -H5S_write(H5O_loc_t *loc, const H5S_t *ds, hbool_t update_time, hid_t dxpl_id) +H5S_write(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned update_flags, H5S_t *ds) { herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5S_write, FAIL) - HDassert(loc); + HDassert(f); + HDassert(oh); HDassert(ds); + HDassert(H5S_GET_EXTENT_TYPE(ds) >= 0); - switch(H5S_GET_EXTENT_TYPE(ds)) { - case H5S_NULL: - case H5S_SCALAR: - case H5S_SIMPLE: - if(H5O_msg_write(loc, H5O_SDSPACE_ID, 0, update_time, &(ds->extent), dxpl_id) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "can't update simple dataspace message") - break; - - default: - HDassert("unknown dataspace class" && 0); - break; - } /* end switch */ + /* Write the current dataspace extent to the dataspace message */ + if(H5O_msg_write_oh(f, dxpl_id, oh, H5O_SDSPACE_ID, 0, update_flags, &(ds->extent)) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "can't update simple dataspace message") done: FUNC_LEAVE_NOAPI(ret_value) @@ -1103,7 +1096,7 @@ done: *------------------------------------------------------------------------- */ herr_t -H5S_append(H5F_t *f, hid_t dxpl_id, struct H5O_t *oh, const H5S_t *ds) +H5S_append(H5F_t *f, hid_t dxpl_id, H5O_t *oh, H5S_t *ds) { herr_t ret_value = SUCCEED; /* Return value */ @@ -1112,19 +1105,11 @@ H5S_append(H5F_t *f, hid_t dxpl_id, struct H5O_t *oh, const H5S_t *ds) HDassert(f); HDassert(oh); HDassert(ds); + HDassert(H5S_GET_EXTENT_TYPE(ds) >= 0); - switch (H5S_GET_EXTENT_TYPE(ds)) { - case H5S_NULL: - case H5S_SCALAR: - case H5S_SIMPLE: - if(H5O_msg_append(f, dxpl_id, oh, H5O_SDSPACE_ID, 0, 0, &(ds->extent)) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "can't update simple data space message") - break; - - default: - assert("unknown data space class" && 0); - break; - } + /* Add the dataspace message to the object header */ + if(H5O_msg_append_oh(f, dxpl_id, oh, H5O_SDSPACE_ID, 0, 0, &(ds->extent)) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "can't add simple dataspace message") done: FUNC_LEAVE_NOAPI(ret_value) @@ -1388,6 +1373,7 @@ H5S_set_extent_simple(H5S_t *space, unsigned rank, const hsize_t *dims, /* Set offset to zeros */ for(u = 0; u < space->extent.rank; u++) space->select.offset[u] = 0; + space->select.offset_changed = FALSE; /* If the selection is 'all', update the number of elements selected */ if(H5S_GET_SELECT_TYPE(space) == H5S_SEL_ALL) @@ -90,61 +90,93 @@ #define H5SL_LOCATE_FIND_FOUND(SLIST,X,UPDATE,I) \ HGOTO_DONE(X); -/* Define a code template for updating the "update" vector for the "DOUPDATE" in the H5SL_LOCATE macro */ -#define H5SL_LOCATE_YES_UPDATE(X,UPDATE,I) \ - UPDATE[I]=&X->forward[I]; -/* Define a code template for _NOT_ updating the "update" vector for the "DOUPDATE" in the H5SL_LOCATE macro */ -#define H5SL_LOCATE_NO_UPDATE(X,UPDATE,I) +/* Define a code template for "OP"s that update the "update" vector for the H5SL_LOCATE macro */ +#define H5SL_LOCATE_INSERT_UPDATE(X, UPDATE, I) \ + UPDATE[I] = &X->forward[I]; +#define H5SL_LOCATE_REMOVE_UPDATE(X, UPDATE, I) \ + UPDATE[I] = &X->forward[I]; + +/* Define a code template for "OP"s that _DON'T_ update the "update" vector for the H5SL_LOCATE macro */ +#define H5SL_LOCATE_SEARCH_UPDATE(X, UPDATE, I) +#define H5SL_LOCATE_FIND_UPDATE(X, UPDATE, I) + /* Define a code template for comparing scalar keys for the "CMP" in the H5SL_LOCATE macro */ -#define H5SL_LOCATE_SCALAR_CMP(TYPE,PKEY1,PKEY2) \ - (*(TYPE *)PKEY1<*(TYPE *)PKEY2) +#define H5SL_LOCATE_SCALAR_CMP(TYPE, PNODE, PKEY, HASHVAL) \ + (*(TYPE *)((PNODE)->key) < *(TYPE *)PKEY) /* Define a code template for comparing string keys for the "CMP" in the H5SL_LOCATE macro */ -#define H5SL_LOCATE_STRING_CMP(TYPE,PKEY1,PKEY2) \ - (HDstrcmp(PKEY1,PKEY2)<0) +#define H5SL_LOCATE_STRING_CMP(TYPE, PNODE, PKEY, HASHVAL) \ + (((PNODE)->hashval == HASHVAL) ? (HDstrcmp((PNODE)->key, PKEY) < 0) : ((PNODE)->hashval < HASHVAL)) + +/* Define a code template for comparing H5_obj_t keys for the "CMP" in the H5SL_LOCATE macro */ +#define H5SL_LOCATE_OBJ_CMP(TYPE, PNODE, PKEY, HASHVAL) \ + ((((TYPE *)((PNODE)->key))->fileno < ((TYPE *)PKEY)->fileno) ? TRUE : (((TYPE *)((PNODE)->key))->addr < ((TYPE *)PKEY)->addr)) + /* Define a code template for comparing scalar keys for the "EQ" in the H5SL_LOCATE macro */ -#define H5SL_LOCATE_SCALAR_EQ(TYPE,PKEY1,PKEY2) \ - (*(TYPE *)PKEY1==*(TYPE *)PKEY2) +#define H5SL_LOCATE_SCALAR_EQ(TYPE, PNODE, PKEY, HASHVAL) \ + (*(TYPE *)((PNODE)->key) == *(TYPE *)PKEY) /* Define a code template for comparing string keys for the "EQ" in the H5SL_LOCATE macro */ -#define H5SL_LOCATE_STRING_EQ(TYPE,PKEY1,PKEY2) \ - (HDstrcmp(PKEY1,PKEY2)==0) +#define H5SL_LOCATE_STRING_EQ(TYPE, PNODE, PKEY, HASHVAL) \ + (((PNODE)->hashval == HASHVAL) && (HDstrcmp(((PNODE)->key), PKEY) == 0)) + +/* Define a code template for comparing H5_obj_t keys for the "EQ" in the H5SL_LOCATE macro */ +#define H5SL_LOCATE_OBJ_EQ(TYPE, PNODE, PKEY, HASHVAL) \ + ((((TYPE *)((PNODE)->key))->fileno == ((TYPE *)PKEY)->fileno) && (((TYPE *)((PNODE)->key))->addr == ((TYPE *)PKEY)->addr)) + + +/* Define a code template for initializing the hash value for scalar keys for the "HASHINIT" in the H5SL_LOCATE macro */ +#define H5SL_LOCATE_SCALAR_HASHINIT(KEY, HASHVAL) + +/* Define a code template for initializing the hash value for string keys for the "HASHINIT" in the H5SL_LOCATE macro */ +#define H5SL_LOCATE_STRING_HASHINIT(KEY, HASHVAL) \ + HASHVAL = H5_hash_string(KEY); + +/* Define a code template for initializing the hash value for H5_obj_t keys for the "HASHINIT" in the H5SL_LOCATE macro */ +#define H5SL_LOCATE_OBJ_HASHINIT(KEY, HASHVAL) + /* Macro used to find node for operation */ -#define H5SL_LOCATE(OP,DOUPDATE,CMP,SLIST,X,UPDATE,I,TYPE,KEY,CHECKED) \ - CHECKED=NULL; \ - for(I=(int)SLIST->curr_level; I>=0; I--) { \ - if(X->forward[I]!=CHECKED) { \ - while(X->forward[I] && H5_GLUE3(H5SL_LOCATE_,CMP,_CMP)(TYPE,X->forward[I]->key,KEY) ) \ - X=X->forward[I]; \ - CHECKED=X->forward[I]; \ +#define H5SL_LOCATE(OP, CMP, SLIST, X, UPDATE, TYPE, KEY, HASHVAL) \ +{ \ + H5SL_node_t *_checked; /* Pointer to last node checked */ \ + int _i; /* Local index variable */ \ + \ + _checked = NULL; \ + H5_GLUE3(H5SL_LOCATE_,CMP,_HASHINIT)(KEY, HASHVAL) \ + for(_i = (int)SLIST->curr_level; _i >= 0; _i--) { \ + if(X->forward[_i] != _checked) { \ + while(X->forward[_i] && H5_GLUE3(H5SL_LOCATE_,CMP,_CMP)(TYPE, X->forward[_i], KEY, HASHVAL) ) \ + X = X->forward[_i]; \ + _checked = X->forward[_i]; \ } /* end if */ \ - H5_GLUE3(H5SL_LOCATE_,DOUPDATE,_UPDATE)(X,UPDATE,I) \ + H5_GLUE3(H5SL_LOCATE_,OP,_UPDATE)(X, UPDATE, _i) \ } /* end for */ \ - X=X->forward[0]; \ - if(X!=NULL && H5_GLUE3(H5SL_LOCATE_,CMP,_EQ)(TYPE,X->key,KEY) ) { \ + X = X->forward[0]; \ + if(X != NULL && H5_GLUE3(H5SL_LOCATE_,CMP,_EQ)(TYPE, X, KEY, HASHVAL) ) { \ /* What to do when a node is found */ \ - H5_GLUE3(H5SL_LOCATE_,OP,_FOUND)(SLIST,X,UPDATE,I) \ - } /* end if */ + H5_GLUE3(H5SL_LOCATE_,OP,_FOUND)(SLIST, X, UPDATE, _i) \ + } /* end if */ \ +} /* Macro used to insert node */ -#define H5SL_INSERT(CMP, SLIST, X, UPDATE, I, TYPE, KEY, CHECKED) \ - H5SL_LOCATE(INSERT, YES, CMP, SLIST, X, UPDATE, I, TYPE, KEY, CHECKED) +#define H5SL_INSERT(CMP, SLIST, X, UPDATE, TYPE, KEY, HASHVAL) \ + H5SL_LOCATE(INSERT, CMP, SLIST, X, UPDATE, TYPE, KEY, HASHVAL) /* Macro used to remove node */ -#define H5SL_REMOVE(CMP, SLIST, X, UPDATE, I, TYPE, KEY, CHECKED) \ - H5SL_LOCATE(REMOVE, YES, CMP, SLIST, X, UPDATE, I, TYPE, KEY, CHECKED) +#define H5SL_REMOVE(CMP, SLIST, X, UPDATE, TYPE, KEY, HASHVAL) \ + H5SL_LOCATE(REMOVE, CMP, SLIST, X, UPDATE, TYPE, KEY, HASHVAL) /* Macro used to search for node */ -#define H5SL_SEARCH(CMP, SLIST, X, UPDATE, I, TYPE, KEY, CHECKED) \ - H5SL_LOCATE(SEARCH, NO, CMP, SLIST, X, UPDATE, I, TYPE, KEY, CHECKED) +#define H5SL_SEARCH(CMP, SLIST, X, UPDATE, TYPE, KEY, HASHVAL) \ + H5SL_LOCATE(SEARCH, CMP, SLIST, X, UPDATE, TYPE, KEY, HASHVAL) /* Macro used to find a node */ -#define H5SL_FIND(CMP, SLIST, X, UPDATE, I, TYPE, KEY, CHECKED) \ - H5SL_LOCATE(FIND, NO, CMP, SLIST, X, UPDATE, I, TYPE, KEY, CHECKED) +#define H5SL_FIND(CMP, SLIST, X, UPDATE, TYPE, KEY, HASHVAL) \ + H5SL_LOCATE(FIND, CMP, SLIST, X, UPDATE, TYPE, KEY, HASHVAL) /* Private typedefs & structs */ @@ -154,6 +186,7 @@ struct H5SL_node_t { const void *key; /* Pointer to node's key */ void *item; /* Pointer to node's item */ size_t level; /* The level of this node */ + uint32_t hashval; /* Hash value for key (only for strings, currently) */ struct H5SL_node_t **forward; /* Array of forward pointers from this node */ struct H5SL_node_t *backward; /* Backward pointer from this node */ }; @@ -175,7 +208,7 @@ struct H5SL_t { /* Static functions */ static size_t H5SL_random_level(int p1, size_t max_level); -static H5SL_node_t * H5SL_new_node(size_t lvl, void *item, const void *key); +static H5SL_node_t * H5SL_new_node(size_t lvl, void *item, const void *key, uint32_t hashval); static H5SL_node_t *H5SL_insert_common(H5SL_t *slist, void *item, const void *key); static herr_t H5SL_release_common(H5SL_t *slist, H5SL_operator_t op, void *op_data); static herr_t H5SL_close_common(H5SL_t *slist, H5SL_operator_t op, void *op_data); @@ -287,24 +320,25 @@ H5SL_random_level(int p1, size_t max_level) REVISION LOG --------------------------------------------------------------------------*/ static H5SL_node_t * -H5SL_new_node(size_t lvl, void *item, const void *key) +H5SL_new_node(size_t lvl, void *item, const void *key, uint32_t hashval) { H5SL_node_t *ret_value; /* New skip list node */ - FUNC_ENTER_NOAPI_NOINIT(H5SL_new_node); + FUNC_ENTER_NOAPI_NOINIT(H5SL_new_node) /* Allocate the node */ - if((ret_value=H5FL_ARR_MALLOC(H5SL_node_ptr_t,(lvl+1)))==NULL) - HGOTO_ERROR(H5E_SLIST,H5E_NOSPACE,NULL,"memory allocation failed"); + if(NULL == (ret_value = H5FL_ARR_MALLOC(H5SL_node_ptr_t, (lvl + 1)))) + HGOTO_ERROR(H5E_SLIST, H5E_NOSPACE, NULL, "memory allocation failed") /* Initialize node */ - ret_value->key=key; - ret_value->item=item; - ret_value->level=lvl; - ret_value->forward=(H5SL_node_t **)((unsigned char *)ret_value+sizeof(H5SL_node_t)); + ret_value->key = key; + ret_value->item = item; + ret_value->level = lvl; + ret_value->hashval = hashval; + ret_value->forward = (H5SL_node_t **)((unsigned char *)ret_value + sizeof(H5SL_node_t)); done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5SL_new_node() */ @@ -333,8 +367,8 @@ static H5SL_node_t * H5SL_insert_common(H5SL_t *slist, void *item, const void *key) { H5SL_node_t **update[H5SL_LEVEL_MAX]; /* 'update' vector */ - H5SL_node_t *checked; /* Pointer to last node checked */ H5SL_node_t *x; /* Current node to examine */ + uint32_t hashval = 0; /* Hash value for key */ size_t lvl; /* Level of new node */ int i; /* Local index value */ H5SL_node_t *ret_value; /* Return value */ @@ -356,27 +390,31 @@ H5SL_insert_common(H5SL_t *slist, void *item, const void *key) x=slist->header; switch(slist->type) { case H5SL_TYPE_INT: - H5SL_INSERT(SCALAR, slist, x, update, i, const int, key, checked) + H5SL_INSERT(SCALAR, slist, x, update, const int, key, -) break; case H5SL_TYPE_HADDR: - H5SL_INSERT(SCALAR, slist, x, update, i, const haddr_t, key, checked) + H5SL_INSERT(SCALAR, slist, x, update, const haddr_t, key, -) break; case H5SL_TYPE_STR: - H5SL_INSERT(STRING, slist, x, update, i, char *, key, checked) + H5SL_INSERT(STRING, slist, x, update, char *, key, hashval) break; case H5SL_TYPE_HSIZE: - H5SL_INSERT(SCALAR, slist, x, update, i, const hsize_t, key, checked) + H5SL_INSERT(SCALAR, slist, x, update, const hsize_t, key, -) break; case H5SL_TYPE_UNSIGNED: - H5SL_INSERT(SCALAR, slist, x, update, i, const unsigned, key, checked) + H5SL_INSERT(SCALAR, slist, x, update, const unsigned, key, -) break; case H5SL_TYPE_SIZE: - H5SL_INSERT(SCALAR, slist, x, update, i, const size_t, key, checked) + H5SL_INSERT(SCALAR, slist, x, update, const size_t, key, -) + break; + + case H5SL_TYPE_OBJ: + H5SL_INSERT(OBJ, slist, x, update, const H5_obj_t, key, -) break; } /* end switch */ @@ -396,8 +434,8 @@ H5SL_insert_common(H5SL_t *slist, void *item, const void *key) } /* end if */ /* Create new node of proper level */ - if((x=H5SL_new_node(lvl,item,key))==NULL) - HGOTO_ERROR(H5E_SLIST,H5E_NOSPACE,NULL,"can't create new skip list node"); + if(NULL == (x = H5SL_new_node(lvl, item, key, hashval))) + HGOTO_ERROR(H5E_SLIST ,H5E_NOSPACE, NULL, "can't create new skip list node") /* Update the backward links */ if(*update[0]!=NULL) { @@ -571,7 +609,7 @@ H5SL_create(H5SL_type_t type, double p, size_t max_level) /* Check args */ HDassert(p>0.0 && p<1.0); HDassert(max_level>0 && max_level<=H5SL_LEVEL_MAX); - HDassert(type>=H5SL_TYPE_INT && type<=H5SL_TYPE_SIZE); + HDassert(type>=H5SL_TYPE_INT && type<=H5SL_TYPE_OBJ); /* Allocate skip list structure */ if((new_slist=H5FL_MALLOC(H5SL_t))==NULL) @@ -588,8 +626,8 @@ H5SL_create(H5SL_type_t type, double p, size_t max_level) new_slist->nobjs=0; /* Allocate the header node */ - if((header=H5SL_new_node(max_level-1,NULL,NULL))==NULL) - HGOTO_ERROR(H5E_SLIST,H5E_NOSPACE,NULL,"memory allocation failed"); + if(NULL == (header = H5SL_new_node((max_level - 1), NULL, NULL, ULONG_MAX))) + HGOTO_ERROR(H5E_SLIST ,H5E_NOSPACE, NULL, "can't create new skip list node") /* Initialize header node's forward pointers */ for(u=0; u<max_level; u++) @@ -764,9 +802,8 @@ void * H5SL_remove(H5SL_t *slist, const void *key) { H5SL_node_t **update[H5SL_LEVEL_MAX]; /* 'update' vector */ - H5SL_node_t *checked; /* Pointer to last node checked */ H5SL_node_t *x; /* Current node to examine */ - int i; /* Local index value */ + uint32_t hashval = 0; /* Hash value for key */ void *ret_value=NULL; /* Return value */ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SL_remove); @@ -786,27 +823,31 @@ H5SL_remove(H5SL_t *slist, const void *key) x=slist->header; switch(slist->type) { case H5SL_TYPE_INT: - H5SL_REMOVE(SCALAR, slist, x, update, i, const int, key, checked) + H5SL_REMOVE(SCALAR, slist, x, update, const int, key, -) break; case H5SL_TYPE_HADDR: - H5SL_REMOVE(SCALAR, slist, x, update, i, const haddr_t, key, checked) + H5SL_REMOVE(SCALAR, slist, x, update, const haddr_t, key, -) break; case H5SL_TYPE_STR: - H5SL_REMOVE(STRING, slist, x, update, i, char *, key, checked) + H5SL_REMOVE(STRING, slist, x, update, char *, key, hashval) break; case H5SL_TYPE_HSIZE: - H5SL_REMOVE(SCALAR, slist, x, update, i, const hsize_t, key, checked) + H5SL_REMOVE(SCALAR, slist, x, update, const hsize_t, key, -) break; case H5SL_TYPE_UNSIGNED: - H5SL_REMOVE(SCALAR, slist, x, update, i, const unsigned, key, checked) + H5SL_REMOVE(SCALAR, slist, x, update, const unsigned, key, -) break; case H5SL_TYPE_SIZE: - H5SL_REMOVE(SCALAR, slist, x, update, i, const size_t, key, checked) + H5SL_REMOVE(SCALAR, slist, x, update, const size_t, key, -) + break; + + case H5SL_TYPE_OBJ: + H5SL_REMOVE(OBJ, slist, x, update, const H5_obj_t, key, -) break; } /* end switch */ @@ -911,9 +952,8 @@ H5SL_remove_first(H5SL_t *slist) void * H5SL_search(H5SL_t *slist, const void *key) { - H5SL_node_t *checked; /* Pointer to last node checked */ H5SL_node_t *x; /* Current node to examine */ - int i; /* Local index value */ + uint32_t hashval = 0; /* Hash value for key */ void *ret_value; /* Return value */ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SL_search); @@ -933,27 +973,31 @@ H5SL_search(H5SL_t *slist, const void *key) x=slist->header; switch(slist->type) { case H5SL_TYPE_INT: - H5SL_SEARCH(SCALAR, slist, x, -, i, const int, key, checked) + H5SL_SEARCH(SCALAR, slist, x, -, const int, key, -) break; case H5SL_TYPE_HADDR: - H5SL_SEARCH(SCALAR, slist, x, -, i, const haddr_t, key, checked) + H5SL_SEARCH(SCALAR, slist, x, -, const haddr_t, key, -) break; case H5SL_TYPE_STR: - H5SL_SEARCH(STRING, slist, x, -, i, char *, key, checked) + H5SL_SEARCH(STRING, slist, x, -, char *, key, hashval) break; case H5SL_TYPE_HSIZE: - H5SL_SEARCH(SCALAR, slist, x, -, i, const hsize_t, key, checked) + H5SL_SEARCH(SCALAR, slist, x, -, const hsize_t, key, -) break; case H5SL_TYPE_UNSIGNED: - H5SL_SEARCH(SCALAR, slist, x, -, i, const unsigned, key, checked) + H5SL_SEARCH(SCALAR, slist, x, -, const unsigned, key, -) break; case H5SL_TYPE_SIZE: - H5SL_SEARCH(SCALAR, slist, x, -, i, const size_t, key, checked) + H5SL_SEARCH(SCALAR, slist, x, -, const size_t, key, -) + break; + + case H5SL_TYPE_OBJ: + H5SL_SEARCH(OBJ, slist, x, -, const H5_obj_t, key, -) break; } /* end switch */ @@ -990,9 +1034,8 @@ done: void * H5SL_less(H5SL_t *slist, const void *key) { - H5SL_node_t *checked; /* Pointer to last node checked */ H5SL_node_t *x; /* Current node to examine */ - int i; /* Local index value */ + uint32_t hashval = 0; /* Hash value for key */ void *ret_value; /* Return value */ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SL_less); @@ -1012,27 +1055,31 @@ H5SL_less(H5SL_t *slist, const void *key) x=slist->header; switch(slist->type) { case H5SL_TYPE_INT: - H5SL_SEARCH(SCALAR, slist, x, -, i, const int, key, checked) + H5SL_SEARCH(SCALAR, slist, x, -, const int, key, -) break; case H5SL_TYPE_HADDR: - H5SL_SEARCH(SCALAR, slist, x, -, i, const haddr_t, key, checked) + H5SL_SEARCH(SCALAR, slist, x, -, const haddr_t, key, -) break; case H5SL_TYPE_STR: - H5SL_SEARCH(STRING, slist, x, -, i, char *, key, checked) + H5SL_SEARCH(STRING, slist, x, -, char *, key, hashval) break; case H5SL_TYPE_HSIZE: - H5SL_SEARCH(SCALAR, slist, x, -, i, const hsize_t, key, checked) + H5SL_SEARCH(SCALAR, slist, x, -, const hsize_t, key, -) break; case H5SL_TYPE_UNSIGNED: - H5SL_SEARCH(SCALAR, slist, x, -, i, const unsigned, key, checked) + H5SL_SEARCH(SCALAR, slist, x, -, const unsigned, key, -) break; case H5SL_TYPE_SIZE: - H5SL_SEARCH(SCALAR, slist, x, -, i, const size_t, key, checked) + H5SL_SEARCH(SCALAR, slist, x, -, const size_t, key, -) + break; + + case H5SL_TYPE_OBJ: + H5SL_SEARCH(OBJ, slist, x, -, const H5_obj_t, key, -) break; } /* end switch */ @@ -1082,9 +1129,8 @@ done: void * H5SL_greater(H5SL_t *slist, const void *key) { - H5SL_node_t *checked; /* Pointer to last node checked */ H5SL_node_t *x; /* Current node to examine */ - int i; /* Local index value */ + uint32_t hashval = 0; /* Hash value for key */ void *ret_value; /* Return value */ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SL_greater); @@ -1104,27 +1150,31 @@ H5SL_greater(H5SL_t *slist, const void *key) x = slist->header; switch(slist->type) { case H5SL_TYPE_INT: - H5SL_SEARCH(SCALAR, slist, x, -, i, const int, key, checked) + H5SL_SEARCH(SCALAR, slist, x, -, const int, key, -) break; case H5SL_TYPE_HADDR: - H5SL_SEARCH(SCALAR, slist, x, -, i, const haddr_t, key, checked) + H5SL_SEARCH(SCALAR, slist, x, -, const haddr_t, key, -) break; case H5SL_TYPE_STR: - H5SL_SEARCH(STRING, slist, x, -, i, char *, key, checked) + H5SL_SEARCH(STRING, slist, x, -, char *, key, hashval) break; case H5SL_TYPE_HSIZE: - H5SL_SEARCH(SCALAR, slist, x, -, i, const hsize_t, key, checked) + H5SL_SEARCH(SCALAR, slist, x, -, const hsize_t, key, -) break; case H5SL_TYPE_UNSIGNED: - H5SL_SEARCH(SCALAR, slist, x, -, i, const unsigned, key, checked) + H5SL_SEARCH(SCALAR, slist, x, -, const unsigned, key, -) break; case H5SL_TYPE_SIZE: - H5SL_SEARCH(SCALAR, slist, x, -, i, const size_t, key, checked) + H5SL_SEARCH(SCALAR, slist, x, -, const size_t, key, -) + break; + + case H5SL_TYPE_OBJ: + H5SL_SEARCH(OBJ, slist, x, -, const H5_obj_t, key, -) break; } /* end switch */ @@ -1164,9 +1214,8 @@ done: H5SL_node_t * H5SL_find(H5SL_t *slist, const void *key) { - H5SL_node_t *checked; /* Pointer to last node checked */ H5SL_node_t *x; /* Current node to examine */ - int i; /* Local index value */ + uint32_t hashval = 0; /* Hash value for key */ H5SL_node_t *ret_value; /* Return value */ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SL_find); @@ -1186,27 +1235,31 @@ H5SL_find(H5SL_t *slist, const void *key) x=slist->header; switch(slist->type) { case H5SL_TYPE_INT: - H5SL_FIND(SCALAR, slist, x, -, i, const int, key, checked) + H5SL_FIND(SCALAR, slist, x, -, const int, key, -) break; case H5SL_TYPE_HADDR: - H5SL_FIND(SCALAR, slist, x, -, i, const haddr_t, key, checked) + H5SL_FIND(SCALAR, slist, x, -, const haddr_t, key, -) break; case H5SL_TYPE_STR: - H5SL_FIND(STRING, slist, x, -, i, char *, key, checked) + H5SL_FIND(STRING, slist, x, -, char *, key, hashval) break; case H5SL_TYPE_HSIZE: - H5SL_FIND(SCALAR, slist, x, -, i, const hsize_t, key, checked) + H5SL_FIND(SCALAR, slist, x, -, const hsize_t, key, -) break; case H5SL_TYPE_UNSIGNED: - H5SL_FIND(SCALAR, slist, x, -, i, const unsigned, key, checked) + H5SL_FIND(SCALAR, slist, x, -, const unsigned, key, -) break; case H5SL_TYPE_SIZE: - H5SL_FIND(SCALAR, slist, x, -, i, const size_t, key, checked) + H5SL_FIND(SCALAR, slist, x, -, const size_t, key, -) + break; + + case H5SL_TYPE_OBJ: + H5SL_FIND(OBJ, slist, x, -, const H5_obj_t, key, -) break; } /* end switch */ diff --git a/src/H5SLprivate.h b/src/H5SLprivate.h index 98c1b84..9f73893 100644 --- a/src/H5SLprivate.h +++ b/src/H5SLprivate.h @@ -46,7 +46,8 @@ typedef enum { H5SL_TYPE_STR, /* Skip list keys are 'char *'s (ie. strings) */ H5SL_TYPE_HSIZE, /* Skip list keys are 'hsize_t's */ H5SL_TYPE_UNSIGNED, /* Skip list keys are 'unsigned's */ - H5SL_TYPE_SIZE /* Skip list keys are 'size_t's */ + H5SL_TYPE_SIZE, /* Skip list keys are 'size_t's */ + H5SL_TYPE_OBJ /* Skip list keys are 'H5_obj_t's */ } H5SL_type_t; /**********/ @@ -220,7 +220,7 @@ H5SM_init(H5F_t *f, H5P_genplist_t * fc_plist, const H5O_loc_t *ext_loc, hid_t d /* Check for sharing attributes in this file, which means that creation * indices must be tracked on object header message in the file. */ - if(type_flags_used & H5O_MESG_ATTR_FLAG) + if(type_flags_used & H5O_SHMESG_ATTR_FLAG) f->shared->store_msg_crt_idx = TRUE; /* Write shared message information to the superblock extension */ @@ -263,22 +263,18 @@ H5SM_type_to_flag(unsigned type_id, unsigned *type_flag) /* Translate the H5O type_id into an H5SM type flag */ switch(type_id) { + case H5O_FILL_ID: + type_id = H5O_FILL_NEW_ID; + /* Fall through... */ + case H5O_SDSPACE_ID: - *type_flag = H5O_MESG_SDSPACE_FLAG; - break; case H5O_DTYPE_ID: - *type_flag = H5O_MESG_DTYPE_FLAG; - break; - case H5O_FILL_ID: case H5O_FILL_NEW_ID: - *type_flag = H5O_MESG_FILL_FLAG; - break; case H5O_PLINE_ID: - *type_flag = H5O_MESG_PLINE_FLAG; - break; case H5O_ATTR_ID: - *type_flag = H5O_MESG_ATTR_FLAG; + *type_flag = (unsigned)1 << type_id; break; + default: HGOTO_ERROR(H5E_OHDR, H5E_BADTYPE, FAIL, "unknown message type ID") } /* end switch */ @@ -307,7 +303,7 @@ done: ssize_t H5SM_get_index(const H5SM_master_table_t *table, unsigned type_id) { - ssize_t x; + size_t x; unsigned type_flag; ssize_t ret_value = FAIL; @@ -322,7 +318,7 @@ H5SM_get_index(const H5SM_master_table_t *table, unsigned type_id) */ for(x = 0; x < table->num_indexes; ++x) if(table->indexes[x].mesg_types & type_flag) - HGOTO_DONE(x) + HGOTO_DONE((ssize_t)x) /* At this point, ret_value is either the location of the correct * index or it's still FAIL because we didn't find an index. @@ -1828,7 +1824,7 @@ H5SM_get_info(const H5O_loc_t *ext_loc, H5P_genplist_t *fc_plist, hid_t dxpl_id) /* Check for sharing attributes in this file, which means that creation * indices must be tracked on object header message in the file. */ - if(index_flags[u] & H5O_MESG_ATTR_FLAG) + if(index_flags[u] & H5O_SHMESG_ATTR_FLAG) shared->store_msg_crt_idx = TRUE; } /* end for */ diff --git a/src/H5Sall.c b/src/H5Sall.c index 5d01fec..c603251 100644 --- a/src/H5Sall.c +++ b/src/H5Sall.c @@ -42,6 +42,7 @@ static hssize_t H5S_all_serial_size(const H5S_t *space); static herr_t H5S_all_serialize(const H5S_t *space, uint8_t *buf); static herr_t H5S_all_deserialize(H5S_t *space, const uint8_t *buf); static herr_t H5S_all_bounds(const H5S_t *space, hsize_t *start, hsize_t *end); +static herr_t H5S_all_offset(const H5S_t *space, hsize_t *off); static htri_t H5S_all_is_contiguous(const H5S_t *space); static htri_t H5S_all_is_single(const H5S_t *space); static htri_t H5S_all_is_regular(const H5S_t *space); @@ -70,6 +71,7 @@ const H5S_select_class_t H5S_sel_all[1] = {{ H5S_all_serialize, H5S_all_deserialize, H5S_all_bounds, + H5S_all_offset, H5S_all_is_contiguous, H5S_all_is_single, H5S_all_is_regular, @@ -585,26 +587,61 @@ done: herr_t H5S_all_bounds(const H5S_t *space, hsize_t *start, hsize_t *end) { - int rank; /* Dataspace rank */ - int i; /* index variable */ + unsigned rank; /* Dataspace rank */ + unsigned i; /* index variable */ - FUNC_ENTER_NOAPI_NOFUNC(H5S_all_bounds); + FUNC_ENTER_NOAPI_NOFUNC(H5S_all_bounds) - assert(space); - assert(start); - assert(end); + HDassert(space); + HDassert(start); + HDassert(end); /* Get the dataspace extent rank */ - rank=space->extent.rank; + rank = space->extent.rank; /* Just copy over the complete extent */ - for(i=0; i<rank; i++) { - start[i]=0; - end[i]=space->extent.size[i]-1; + for(i = 0; i < rank; i++) { + start[i] = 0; + end[i] = space->extent.size[i] - 1; } /* end for */ - FUNC_LEAVE_NOAPI(SUCCEED); -} /* H5Sget_all_bounds() */ + FUNC_LEAVE_NOAPI(SUCCEED) +} /* H5S_all_bounds() */ + + +/*-------------------------------------------------------------------------- + NAME + H5S_all_offset + PURPOSE + Gets the linear offset of the first element for the selection. + USAGE + herr_t H5S_all_offset(space, offset) + const H5S_t *space; IN: Dataspace pointer of selection to query + hsize_t *offset; OUT: Linear offset of first element in selection + RETURNS + Non-negative on success, negative on failure + DESCRIPTION + Retrieves the linear offset (in "units" of elements) of the first element + selected within the dataspace. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + Calling this function on a "none" selection returns fail. + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5S_all_offset(const H5S_t *space, hsize_t *offset) +{ + FUNC_ENTER_NOAPI_NOFUNC(H5S_all_offset) + + HDassert(space); + HDassert(offset); + + /* 'All' selections always start at offset 0 */ + *offset = 0; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* H5S_all_offset() */ /*-------------------------------------------------------------------------- diff --git a/src/H5Shyper.c b/src/H5Shyper.c index 8acbfd5..455a251 100644 --- a/src/H5Shyper.c +++ b/src/H5Shyper.c @@ -57,6 +57,7 @@ static hssize_t H5S_hyper_serial_size(const H5S_t *space); static herr_t H5S_hyper_serialize(const H5S_t *space, uint8_t *buf); static herr_t H5S_hyper_deserialize(H5S_t *space, const uint8_t *buf); static herr_t H5S_hyper_bounds(const H5S_t *space, hsize_t *start, hsize_t *end); +static herr_t H5S_hyper_offset(const H5S_t *space, hsize_t *offset); static htri_t H5S_hyper_is_contiguous(const H5S_t *space); static htri_t H5S_hyper_is_single(const H5S_t *space); static htri_t H5S_hyper_is_regular(const H5S_t *space); @@ -90,6 +91,7 @@ const H5S_select_class_t H5S_sel_hyper[1] = {{ H5S_hyper_serialize, H5S_hyper_deserialize, H5S_hyper_bounds, + H5S_hyper_offset, H5S_hyper_is_contiguous, H5S_hyper_is_single, H5S_hyper_is_regular, @@ -275,12 +277,17 @@ H5S_hyper_iter_init(H5S_sel_iter_t *iter, const H5S_t *space) /* Don't flatten adjacent elements into contiguous block if the * element size is 0. This is for the H5S_select_shape_same() code. */ - if(iter->elmt_size>0) { + if(iter->elmt_size > 0) { /* Check for any "contiguous" blocks that can be flattened */ - for(u=rank-1; u>0; u--) { - if(tdiminfo[u].count==1 && tdiminfo[u].block==mem_size[u]) + for(u = (rank - 1); u > 0; u--) { + if(tdiminfo[u].count == 1 && tdiminfo[u].block == mem_size[u]) { cont_dim++; + iter->u.hyp.flattened[u] = TRUE; + } /* end if */ + else + iter->u.hyp.flattened[u] = FALSE; } /* end for */ + iter->u.hyp.flattened[0] = FALSE; } /* end if */ /* Check if the regular selection can be "flattened" */ @@ -430,23 +437,59 @@ H5S_hyper_iter_coords (const H5S_sel_iter_t *iter, hsize_t *coords) /* Check for a single "regular" hyperslab */ if(iter->u.hyp.diminfo_valid) { /* Check if this is a "flattened" regular hyperslab selection */ - if(iter->u.hyp.iter_rank!=0 && iter->u.hyp.iter_rank<iter->rank) { - unsigned flat_dim; /* The rank of the flattened dimension */ + if(iter->u.hyp.iter_rank != 0 && iter->u.hyp.iter_rank < iter->rank) { + int u, v; /* Dimension indices */ + + /* Set the starting rank of both the "natural" & "flattened" dimensions */ + u = iter->rank - 1; + v = iter->u.hyp.iter_rank - 1; + + /* Construct the "natural" dimensions from a set of flattened coordinates */ + while(u >= 0) { + if(iter->u.hyp.flattened[u]) { + int begin = u; /* The rank of the first flattened dimension */ + + /* Walk up through as many flattened dimensions as possible */ + do { + u--; + } while(u >= 0 && iter->u.hyp.flattened[u]); - /* Get the rank of the flattened dimension */ - flat_dim=iter->u.hyp.iter_rank-1; + /* Compensate for possibly overshooting dim 0 */ + if(u < 0) + u = 0; - /* Copy the coordinates up to where things got flattened */ - HDmemcpy(coords,iter->u.hyp.off,sizeof(hsize_t)*flat_dim); + /* Sanity check */ + HDassert(v >= 0); - /* Compute the coordinates for the flattened dimensions */ - H5V_array_calc(iter->u.hyp.off[flat_dim],iter->rank-flat_dim,&(iter->dims[flat_dim]),&(coords[flat_dim])); + /* Compute the coords for the flattened dimensions */ + H5V_array_calc(iter->u.hyp.off[v], (unsigned)((begin - u) + 1), &(iter->dims[u]), &(coords[u])); + + /* Continue to faster dimension in both indices */ + u--; + v--; + } /* end if */ + else { + /* Walk up through as many non-flattened dimensions as possible */ + while(u >= 0 && !iter->u.hyp.flattened[u]) { + /* Sanity check */ + HDassert(v >= 0); + + /* Copy the coordinate */ + coords[u] = iter->u.hyp.off[v]; + + /* Continue to faster dimension in both indices */ + u--; + v--; + } /* end while */ + } /* end else */ + } /* end while */ + HDassert(v < 0); } /* end if */ else - HDmemcpy(coords,iter->u.hyp.off,sizeof(hsize_t)*iter->rank); + HDmemcpy(coords, iter->u.hyp.off, sizeof(hsize_t) * iter->rank); } /* end if */ else - HDmemcpy(coords,iter->u.hyp.off,sizeof(hsize_t)*iter->rank); + HDmemcpy(coords, iter->u.hyp.off, sizeof(hsize_t) * iter->rank); FUNC_LEAVE_NOAPI(SUCCEED); } /* H5S_hyper_iter_coords() */ @@ -2515,7 +2558,7 @@ H5S_get_select_hyper_blocklist(H5S_t *space, hbool_t internal, hsize_t startbloc hid_t dsid; IN: Dataspace ID of selection to query hsize_t startblock; IN: Hyperslab block to start with hsize_t numblocks; IN: Number of hyperslab blocks to get - hsize_t *buf; OUT: List of hyperslab blocks selected + hsize_t buf[]; OUT: List of hyperslab blocks selected RETURNS Non-negative on success, negative on failure DESCRIPTION @@ -2536,13 +2579,14 @@ H5S_get_select_hyper_blocklist(H5S_t *space, hbool_t internal, hsize_t startbloc REVISION LOG --------------------------------------------------------------------------*/ herr_t -H5Sget_select_hyper_blocklist(hid_t spaceid, hsize_t startblock, hsize_t numblocks, hsize_t *buf) +H5Sget_select_hyper_blocklist(hid_t spaceid, hsize_t startblock, + hsize_t numblocks, hsize_t buf[/*numblocks*/]) { H5S_t *space = NULL; /* Dataspace to modify selection of */ herr_t ret_value; /* return value */ FUNC_ENTER_API(H5Sget_select_hyper_blocklist, FAIL); - H5TRACE4("e", "ihh*h", spaceid, startblock, numblocks, buf); + H5TRACE4("e", "ihh*[a2]h", spaceid, startblock, numblocks, buf); /* Check args */ if(buf==NULL) @@ -2708,6 +2752,114 @@ done: /*-------------------------------------------------------------------------- NAME + H5S_hyper_offset + PURPOSE + Gets the linear offset of the first element for the selection. + USAGE + herr_t H5S_hyper_offset(space, offset) + const H5S_t *space; IN: Dataspace pointer of selection to query + hsize_t *offset; OUT: Linear offset of first element in selection + RETURNS + Non-negative on success, negative on failure + DESCRIPTION + Retrieves the linear offset (in "units" of elements) of the first element + selected within the dataspace. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + Calling this function on a "none" selection returns fail. + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5S_hyper_offset(const H5S_t *space, hsize_t *offset) +{ + const hssize_t *sel_offset; /* Pointer to the selection's offset */ + const hsize_t *dim_size; /* Pointer to a dataspace's extent */ + hsize_t accum; /* Accumulator for dimension sizes */ + int rank; /* Dataspace rank */ + int i; /* index variable */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5S_hyper_offset, FAIL) + + HDassert(space); + HDassert(offset); + + /* Start at linear offset 0 */ + *offset = 0; + + /* Set up pointers to arrays of values */ + rank = space->extent.rank; + sel_offset = space->select.offset; + dim_size = space->extent.size; + + /* Check for a "regular" hyperslab selection */ + if(space->select.sel_info.hslab->diminfo_valid) { + const H5S_hyper_dim_t *diminfo = space->select.sel_info.hslab->opt_diminfo; /* Local alias for diminfo */ + + /* Loop through starting coordinates, calculating the linear offset */ + accum = 1; + for(i = (rank - 1); i >= 0; i--) { + hssize_t hyp_offset = (hssize_t)diminfo[i].start + sel_offset[i]; /* Hyperslab's offset in this dimension */ + + /* Check for offset moving selection out of the dataspace */ + if(hyp_offset < 0 || (hsize_t)hyp_offset >= dim_size[i]) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "offset moves selection out of bounds") + + /* Add the hyperslab's offset in this dimension to the total linear offset */ + *offset += hyp_offset * accum; + + /* Increase the accumulator */ + accum *= dim_size[i]; + } /* end for */ + } /* end if */ + else { + const H5S_hyper_span_t *span; /* Hyperslab span node */ + hsize_t dim_accum[H5S_MAX_RANK]; /* Accumulators, for each dimension */ + + /* Calculate the accumulator for each dimension */ + accum = 1; + for(i = (rank - 1); i >= 0; i--) { + /* Set the accumulator for this dimension */ + dim_accum[i] = accum; + + /* Increase the accumulator */ + accum *= dim_size[i]; + } /* end for */ + + /* Get information for the first span, in the slowest changing dimension */ + span = space->select.sel_info.hslab->span_lst->head; + + /* Work down the spans, computing the linear offset */ + i = 0; + while(span) { + hssize_t hyp_offset = (hssize_t)span->low + sel_offset[i]; /* Hyperslab's offset in this dimension */ + + /* Check for offset moving selection out of the dataspace */ + if(hyp_offset < 0 || (hsize_t)hyp_offset >= dim_size[i]) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "offset moves selection out of bounds") + + /* Add the hyperslab's offset in this dimension to the total linear offset */ + *offset += hyp_offset * dim_accum[i]; + + /* Advance to first span in "down" dimension */ + if(span->down) { + HDassert(span->down->head); + span = span->down->head; + } /* end if */ + else + span = NULL; + i++; + } /* end while */ + } /* end else */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5S_hyper_offset() */ + + +/*-------------------------------------------------------------------------- + NAME H5S_hyper_is_contiguous PURPOSE Check if a hyperslab selection is contiguous within the dataspace extent. @@ -2727,12 +2879,10 @@ done: htri_t H5S_hyper_is_contiguous(const H5S_t *space) { - H5S_hyper_span_info_t *spans; /* Hyperslab span info node */ - H5S_hyper_span_t *span; /* Hyperslab span node */ - unsigned u; /* index variable */ unsigned small_contiguous, /* Flag for small contiguous block */ large_contiguous; /* Flag for large contiguous block */ - htri_t ret_value=FALSE; /* return value */ + unsigned u; /* index variable */ + htri_t ret_value = FALSE; /* Return value */ FUNC_ENTER_NOAPI_NOFUNC(H5S_hyper_is_contiguous); @@ -2791,6 +2941,9 @@ H5S_hyper_is_contiguous(const H5S_t *space) ret_value=TRUE; } /* end if */ else { + H5S_hyper_span_info_t *spans; /* Hyperslab span info node */ + H5S_hyper_span_t *span; /* Hyperslab span node */ + /* * For a hyperslab to be contiguous, it must have only one block and * (either it's size must be the same as the dataspace extent's in all @@ -4127,35 +4280,37 @@ done: EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ -herr_t +htri_t H5S_hyper_normalize_offset(H5S_t *space, hssize_t *old_offset) { unsigned u; /* Local index variable */ - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = FALSE; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5S_hyper_normalize_offset); + FUNC_ENTER_NOAPI_NOINIT(H5S_hyper_normalize_offset) - assert(space); + HDassert(space); - /* Check for 'all' selection, instead of a hyperslab selection */ - /* (Technically, this check shouldn't be in the "hyperslab" routines...) */ - if(H5S_GET_SELECT_TYPE(space)==H5S_SEL_HYPERSLABS) { + /* Check for hyperslab selection & offset changed */ + if(H5S_GET_SELECT_TYPE(space) == H5S_SEL_HYPERSLABS && space->select.offset_changed) { /* Copy & invert the selection offset */ - for(u=0; u<space->extent.rank; u++) { + for(u = 0; u<space->extent.rank; u++) { old_offset[u] = space->select.offset[u]; space->select.offset[u] = -space->select.offset[u]; } /* end for */ /* Call the existing 'adjust' routine */ - if(H5S_hyper_adjust_s(space, space->select.offset)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADSELECT, FAIL, "can't perform hyperslab normalization"); + if(H5S_hyper_adjust_s(space, space->select.offset) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADSELECT, FAIL, "can't perform hyperslab normalization") /* Zero out the selection offset */ HDmemset(space->select.offset, 0, sizeof(hssize_t) * space->extent.rank); + + /* Indicate that the offset was normalized */ + ret_value = TRUE; } /* end if */ done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* H5S_hyper_normalize_offset() */ @@ -4183,25 +4338,22 @@ done: herr_t H5S_hyper_denormalize_offset(H5S_t *space, const hssize_t *old_offset) { - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5S_hyper_denormalize_offset); + FUNC_ENTER_NOAPI_NOINIT(H5S_hyper_denormalize_offset) - assert(space); + HDassert(space); + HDassert(H5S_GET_SELECT_TYPE(space) == H5S_SEL_HYPERSLABS); - /* Check for 'all' selection, instead of a hyperslab selection */ - /* (Technically, this check shouldn't be in the "hyperslab" routines...) */ - if(H5S_GET_SELECT_TYPE(space)==H5S_SEL_HYPERSLABS) { - /* Call the existing 'adjust' routine */ - if(H5S_hyper_adjust_s(space, old_offset)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADSELECT, FAIL, "can't perform hyperslab normalization"); + /* Call the existing 'adjust' routine */ + if(H5S_hyper_adjust_s(space, old_offset) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADSELECT, FAIL, "can't perform hyperslab normalization") - /* Copy the selection offset over */ - HDmemcpy(space->select.offset, old_offset, sizeof(hssize_t) * space->extent.rank); - } /* end if */ + /* Copy the selection offset over */ + HDmemcpy(space->select.offset, old_offset, sizeof(hssize_t) * space->extent.rank); done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* H5S_hyper_denormalize_offset() */ diff --git a/src/H5Snone.c b/src/H5Snone.c index 89a1875..88ab67f 100644 --- a/src/H5Snone.c +++ b/src/H5Snone.c @@ -43,6 +43,7 @@ static hssize_t H5S_none_serial_size(const H5S_t *space); static herr_t H5S_none_serialize(const H5S_t *space, uint8_t *buf); static herr_t H5S_none_deserialize(H5S_t *space, const uint8_t *buf); static herr_t H5S_none_bounds(const H5S_t *space, hsize_t *start, hsize_t *end); +static herr_t H5S_none_offset(const H5S_t *space, hsize_t *off); static htri_t H5S_none_is_contiguous(const H5S_t *space); static htri_t H5S_none_is_single(const H5S_t *space); static htri_t H5S_none_is_regular(const H5S_t *space); @@ -71,6 +72,7 @@ const H5S_select_class_t H5S_sel_none[1] = {{ H5S_none_serialize, H5S_none_deserialize, H5S_none_bounds, + H5S_none_offset, H5S_none_is_contiguous, H5S_none_is_single, H5S_none_is_regular, @@ -565,11 +567,43 @@ H5S_none_bounds(const H5S_t UNUSED *space, hsize_t UNUSED *start, hsize_t UNUSED /*-------------------------------------------------------------------------- NAME + H5S_none_offset + PURPOSE + Gets the linear offset of the first element for the selection. + USAGE + herr_t H5S_none_offset(space, offset) + const H5S_t *space; IN: Dataspace pointer of selection to query + hsize_t *offset; OUT: Linear offset of first element in selection + RETURNS + Non-negative on success, negative on failure + DESCRIPTION + Retrieves the linear offset (in "units" of elements) of the first element + selected within the dataspace. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + Calling this function on a "none" selection returns fail. + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5S_none_offset(const H5S_t *space, hsize_t *offset) +{ + FUNC_ENTER_NOAPI_NOFUNC(H5S_none_offset) + + HDassert(space); + HDassert(offset); + + FUNC_LEAVE_NOAPI(FAIL) +} /* H5S_none_offset() */ + + +/*-------------------------------------------------------------------------- + NAME H5S_none_is_contiguous PURPOSE Check if a "none" selection is contiguous within the dataspace extent. USAGE - htri_t H5S_all_is_contiguous(space) + htri_t H5S_none_is_contiguous(space) H5S_t *space; IN: Dataspace pointer to check RETURNS TRUE/FALSE/FAIL @@ -767,7 +801,7 @@ done: PURPOSE Create a list of offsets & lengths for a selection USAGE - herr_t H5S_all_get_seq_list(space,flags,iter,maxseq,maxelem,nseq,nelem,off,len) + herr_t H5S_none_get_seq_list(space,flags,iter,maxseq,maxelem,nseq,nelem,off,len) H5S_t *space; IN: Dataspace containing selection to use. unsigned flags; IN: Flags for extra information about operation H5S_sel_iter_t *iter; IN/OUT: Selection iterator describing last @@ -816,4 +850,5 @@ H5S_none_get_seq_list(const H5S_t UNUSED *space, unsigned UNUSED flags, H5S_sel_ *nelem=0; FUNC_LEAVE_NOAPI(SUCCEED); -} /* end H5S_all_get_seq_list() */ +} /* end H5S_none_get_seq_list() */ + diff --git a/src/H5Spkg.h b/src/H5Spkg.h index 71cc43b..e13e6be 100644 --- a/src/H5Spkg.h +++ b/src/H5Spkg.h @@ -133,8 +133,10 @@ typedef hssize_t (*H5S_sel_serial_size_func_t)(const H5S_t *space); typedef herr_t (*H5S_sel_serialize_func_t)(const H5S_t *space, uint8_t *buf); /* Method to store create selection from "serialized" form (a byte sequence suitable for storing on disk) */ typedef herr_t (*H5S_sel_deserialize_func_t)(H5S_t *space, const uint8_t *buf); -/* Method to determine to smallest n-D bounding box containing the current selection */ +/* Method to determine smallest n-D bounding box containing the current selection */ typedef herr_t (*H5S_sel_bounds_func_t)(const H5S_t *space, hsize_t *start, hsize_t *end); +/* Method to determine linear offset of initial element in selection within dataspace */ +typedef herr_t (*H5S_sel_offset_func_t)(const H5S_t *space, hsize_t *offset); /* Method to determine if current selection is contiguous */ typedef htri_t (*H5S_sel_is_contiguous_func_t)(const H5S_t *space); /* Method to determine if current selection is a single block */ @@ -159,6 +161,7 @@ typedef struct { H5S_sel_serialize_func_t serialize; /* Method to store current selection in "serialized" form (a byte sequence suitable for storing on disk) */ H5S_sel_deserialize_func_t deserialize; /* Method to store create selection from "serialized" form (a byte sequence suitable for storing on disk) */ H5S_sel_bounds_func_t bounds; /* Method to determine to smallest n-D bounding box containing the current selection */ + H5S_sel_offset_func_t offset; /* Method to determine linear offset of initial element in selection within dataspace */ H5S_sel_is_contiguous_func_t is_contiguous; /* Method to determine if current selection is contiguous */ H5S_sel_is_single_func_t is_single; /* Method to determine if current selection is a single block */ H5S_sel_is_regular_func_t is_regular; /* Method to determine if current selection is "regular" */ @@ -169,6 +172,7 @@ typedef struct { /* Selection information object */ typedef struct { const H5S_select_class_t *type; /* Pointer to selection's class info */ + hbool_t offset_changed; /* Indicate that the offset for the selection has been changed */ hssize_t offset[H5S_MAX_RANK]; /* Offset within the extent */ hsize_t num_elem; /* Number of elements in selection */ union { diff --git a/src/H5Spoint.c b/src/H5Spoint.c index eb37945..cf7751e 100644 --- a/src/H5Spoint.c +++ b/src/H5Spoint.c @@ -44,6 +44,7 @@ static hssize_t H5S_point_serial_size(const H5S_t *space); static herr_t H5S_point_serialize(const H5S_t *space, uint8_t *buf); static herr_t H5S_point_deserialize(H5S_t *space, const uint8_t *buf); static herr_t H5S_point_bounds(const H5S_t *space, hsize_t *start, hsize_t *end); +static herr_t H5S_point_offset(const H5S_t *space, hsize_t *off); static htri_t H5S_point_is_contiguous(const H5S_t *space); static htri_t H5S_point_is_single(const H5S_t *space); static htri_t H5S_point_is_regular(const H5S_t *space); @@ -72,6 +73,7 @@ const H5S_select_class_t H5S_sel_point[1] = {{ H5S_point_serialize, H5S_point_deserialize, H5S_point_bounds, + H5S_point_offset, H5S_point_is_contiguous, H5S_point_is_single, H5S_point_is_regular, @@ -380,71 +382,70 @@ H5S_point_iter_release (H5S_sel_iter_t UNUSED * iter) REVISION LOG --------------------------------------------------------------------------*/ static herr_t -H5S_point_add (H5S_t *space, H5S_seloper_t op, size_t num_elem, const hsize_t **_coord) +H5S_point_add(H5S_t *space, H5S_seloper_t op, size_t num_elem, const hsize_t *coord) { H5S_pnt_node_t *top, *curr, *new_node; /* Point selection nodes */ - const hsize_t *coord=(const hsize_t *)_coord; /* Pointer to the actual coordinates */ - unsigned i; /* Counter */ - herr_t ret_value=SUCCEED; /* Return value */ + unsigned i; /* Counter */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5S_point_add); + FUNC_ENTER_NOAPI_NOINIT(H5S_point_add) - assert(space); - assert(num_elem>0); - assert(coord); - assert(op==H5S_SELECT_SET || op==H5S_SELECT_APPEND || op==H5S_SELECT_PREPEND); + HDassert(space); + HDassert(num_elem > 0); + HDassert(coord); + HDassert(op == H5S_SELECT_SET || op == H5S_SELECT_APPEND || op == H5S_SELECT_PREPEND); - top=curr=NULL; - for(i=0; i<num_elem; i++) { + top = curr = NULL; + for(i = 0; i < num_elem; i++) { /* Allocate space for the new node */ - if((new_node = H5FL_MALLOC(H5S_pnt_node_t))==NULL) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate point node"); + if(NULL == (new_node = H5FL_MALLOC(H5S_pnt_node_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate point node") - if((new_node->pnt = H5MM_malloc(space->extent.rank*sizeof(hsize_t)))==NULL) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate coordinate information"); + if(NULL == (new_node->pnt = H5MM_malloc(space->extent.rank * sizeof(hsize_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate coordinate information") /* Copy over the coordinates */ - HDmemcpy(new_node->pnt,coord+(i*space->extent.rank),(space->extent.rank*sizeof(hsize_t))); + HDmemcpy(new_node->pnt, coord + (i * space->extent.rank), (space->extent.rank * sizeof(hsize_t))); /* Link into list */ - new_node->next=NULL; - if(top==NULL) - top=new_node; + new_node->next = NULL; + if(top == NULL) + top = new_node; else - curr->next=new_node; - curr=new_node; + curr->next = new_node; + curr = new_node; } /* end for */ /* Insert the list of points selected in the proper place */ - if(op==H5S_SELECT_SET || op==H5S_SELECT_PREPEND) { + if(op == H5S_SELECT_SET || op == H5S_SELECT_PREPEND) { /* Append current list, if there is one */ - if(space->select.sel_info.pnt_lst->head!=NULL) - curr->next=space->select.sel_info.pnt_lst->head; + if(space->select.sel_info.pnt_lst->head != NULL) + curr->next = space->select.sel_info.pnt_lst->head; /* Put new list in point selection */ - space->select.sel_info.pnt_lst->head=top; + space->select.sel_info.pnt_lst->head = top; } /* end if */ else { /* op==H5S_SELECT_APPEND */ - new_node=space->select.sel_info.pnt_lst->head; - if(new_node!=NULL) { - while(new_node->next!=NULL) - new_node=new_node->next; + new_node = space->select.sel_info.pnt_lst->head; + if(new_node != NULL) { + while(new_node->next != NULL) + new_node = new_node->next; /* Append new list to point selection */ - new_node->next=top; + new_node->next = top; } /* end if */ else - space->select.sel_info.pnt_lst->head=top; + space->select.sel_info.pnt_lst->head = top; } /* end else */ /* Set the number of elements in the new selection */ - if(op==H5S_SELECT_SET) - space->select.num_elem=num_elem; + if(op == H5S_SELECT_SET) + space->select.num_elem = num_elem; else - space->select.num_elem+=num_elem; + space->select.num_elem += num_elem; done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* H5S_point_add() */ @@ -505,7 +506,7 @@ H5S_point_release (H5S_t *space) hid_t dsid; IN: Dataspace ID of selection to modify H5S_seloper_t op; IN: Operation to perform on current selection size_t num_elem; IN: Number of elements in COORD array. - const hsize_t **coord; IN: The location of each element selected + const hsize_t *coord; IN: The location of each element selected RETURNS Non-negative on success/Negative on failure DESCRIPTION @@ -526,40 +527,38 @@ H5S_point_release (H5S_t *space) REVISION LOG --------------------------------------------------------------------------*/ herr_t -H5S_select_elements (H5S_t *space, H5S_seloper_t op, size_t num_elem, - const hsize_t **coord) +H5S_select_elements(H5S_t *space, H5S_seloper_t op, size_t num_elem, + const hsize_t *coord) { - herr_t ret_value=SUCCEED; /* return value */ + herr_t ret_value = SUCCEED; /* return value */ - FUNC_ENTER_NOAPI_NOINIT(H5S_select_elements); + FUNC_ENTER_NOAPI_NOINIT(H5S_select_elements) /* Check args */ - assert(space); - assert(num_elem); - assert(coord); - assert(op==H5S_SELECT_SET || op==H5S_SELECT_APPEND || op==H5S_SELECT_PREPEND); + HDassert(space); + HDassert(num_elem); + HDassert(coord); + HDassert(op == H5S_SELECT_SET || op == H5S_SELECT_APPEND || op == H5S_SELECT_PREPEND); /* If we are setting a new selection, remove current selection first */ - if(op==H5S_SELECT_SET || H5S_GET_SELECT_TYPE(space)!=H5S_SEL_POINTS) { - if(H5S_SELECT_RELEASE(space)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't release point selection"); - } /* end if */ + if(op == H5S_SELECT_SET || H5S_GET_SELECT_TYPE(space) != H5S_SEL_POINTS) + if(H5S_SELECT_RELEASE(space) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't release point selection") /* Allocate space for the point selection information if necessary */ - if(H5S_GET_SELECT_TYPE(space)!=H5S_SEL_POINTS || space->select.sel_info.pnt_lst==NULL) { - if((space->select.sel_info.pnt_lst = H5FL_CALLOC(H5S_pnt_list_t))==NULL) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate element information"); - } /* end if */ + if(H5S_GET_SELECT_TYPE(space) != H5S_SEL_POINTS || space->select.sel_info.pnt_lst == NULL) + if(NULL == (space->select.sel_info.pnt_lst = H5FL_CALLOC(H5S_pnt_list_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate element information") /* Add points to selection */ - if(H5S_point_add(space,op,num_elem,coord)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert elements"); + if(H5S_point_add(space, op, num_elem, coord) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert elements") /* Set selection type */ - space->select.type=H5S_sel_point; + space->select.type = H5S_sel_point; done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* H5S_select_elements() */ @@ -965,7 +964,7 @@ H5S_get_select_elem_pointlist(H5S_t *space, hsize_t startpoint, hsize_t numpoint hid_t dsid; IN: Dataspace ID of selection to query hsize_t startpoint; IN: Element point to start with hsize_t numpoints; IN: Number of element points to get - hsize_t *buf; OUT: List of element points selected + hsize_t buf[]; OUT: List of element points selected RETURNS Non-negative on success, negative on failure DESCRIPTION @@ -985,13 +984,14 @@ H5S_get_select_elem_pointlist(H5S_t *space, hsize_t startpoint, hsize_t numpoint REVISION LOG --------------------------------------------------------------------------*/ herr_t -H5Sget_select_elem_pointlist(hid_t spaceid, hsize_t startpoint, hsize_t numpoints, hsize_t *buf) +H5Sget_select_elem_pointlist(hid_t spaceid, hsize_t startpoint, + hsize_t numpoints, hsize_t buf[/*numpoints*/]) { H5S_t *space = NULL; /* Dataspace to modify selection of */ herr_t ret_value; /* return value */ FUNC_ENTER_API(H5Sget_select_elem_pointlist, FAIL); - H5TRACE4("e", "ihh*h", spaceid, startpoint, numpoints, buf); + H5TRACE4("e", "ihh*[a2]h", spaceid, startpoint, numpoints, buf); /* Check args */ if(buf==NULL) @@ -1038,48 +1038,114 @@ static herr_t H5S_point_bounds(const H5S_t *space, hsize_t *start, hsize_t *end) { H5S_pnt_node_t *node; /* Point node */ - int rank; /* Dataspace rank */ - int i; /* index variable */ - herr_t ret_value=SUCCEED; /* Return value */ + unsigned rank; /* Dataspace rank */ + unsigned u; /* index variable */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5S_point_bounds); + FUNC_ENTER_NOAPI_NOINIT(H5S_point_bounds) - assert(space); - assert(start); - assert(end); + HDassert(space); + HDassert(start); + HDassert(end); /* Get the dataspace extent rank */ - rank=space->extent.rank; + rank = space->extent.rank; /* Set the start and end arrays up */ - for(i=0; i<rank; i++) { - start[i]=HSIZET_MAX; - end[i]=0; + for(u = 0; u < rank; u++) { + start[u] = HSIZET_MAX; + end[u] = 0; } /* end for */ /* Iterate through the node, checking the bounds on each element */ - node=space->select.sel_info.pnt_lst->head; - while(node!=NULL) { - for(i=0; i<rank; i++) { + node = space->select.sel_info.pnt_lst->head; + while(node != NULL) { + for(u = 0; u < rank; u++) { /* Check for offset moving selection negative */ - if(((hssize_t)node->pnt[i]+space->select.offset[i])<0) + if(((hssize_t)node->pnt[u] + space->select.offset[u]) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "offset moves selection out of bounds") - if(start[i]>(node->pnt[i]+space->select.offset[i])) - start[i]=node->pnt[i]+space->select.offset[i]; - if(end[i]<(node->pnt[i]+space->select.offset[i])) - end[i]=node->pnt[i]+space->select.offset[i]; + if(start[u] > (node->pnt[u] + space->select.offset[u])) + start[u] = node->pnt[u] + space->select.offset[u]; + if(end[u] < (node->pnt[u] + space->select.offset[u])) + end[u] = node->pnt[u] + space->select.offset[u]; } /* end for */ - node=node->next; + node = node->next; } /* end while */ done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* H5S_point_bounds() */ /*-------------------------------------------------------------------------- NAME + H5S_point_offset + PURPOSE + Gets the linear offset of the first element for the selection. + USAGE + herr_t H5S_point_offset(space, offset) + const H5S_t *space; IN: Dataspace pointer of selection to query + hsize_t *offset; OUT: Linear offset of first element in selection + RETURNS + Non-negative on success, negative on failure + DESCRIPTION + Retrieves the linear offset (in "units" of elements) of the first element + selected within the dataspace. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + Calling this function on a "none" selection returns fail. + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5S_point_offset(const H5S_t *space, hsize_t *offset) +{ + const hsize_t *pnt; /* Pointer to a selected point's coordinates */ + const hssize_t *sel_offset; /* Pointer to the selection's offset */ + const hsize_t *dim_size; /* Pointer to a dataspace's extent */ + hsize_t accum; /* Accumulator for dimension sizes */ + int rank; /* Dataspace rank */ + int i; /* index variable */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5S_point_offset, FAIL) + + HDassert(space); + HDassert(offset); + + /* Start at linear offset 0 */ + *offset = 0; + + /* Set up pointers to arrays of values */ + pnt = space->select.sel_info.pnt_lst->head->pnt; + sel_offset = space->select.offset; + dim_size = space->extent.size; + + /* Loop through coordinates, calculating the linear offset */ + rank = space->extent.rank; + accum = 1; + for(i = (rank - 1); i >= 0; i--) { + hssize_t pnt_offset = (hssize_t)pnt[i] + sel_offset[i]; /* Point's offset in this dimension */ + + /* Check for offset moving selection out of the dataspace */ + if(pnt_offset < 0 || (hsize_t)pnt_offset >= dim_size[i]) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "offset moves selection out of bounds") + + /* Add the point's offset in this dimension to the total linear offset */ + *offset += pnt_offset * accum; + + /* Increase the accumulator */ + accum *= dim_size[i]; + } /* end for */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5S_point_offset() */ + + +/*-------------------------------------------------------------------------- + NAME H5S_point_is_contiguous PURPOSE Check if a point selection is contiguous within the dataspace extent. @@ -1258,7 +1324,7 @@ H5S_point_adjust_u(H5S_t *space, const hsize_t *offset) hid_t dsid; IN: Dataspace ID of selection to modify H5S_seloper_t op; IN: Operation to perform on current selection size_t num_elem; IN: Number of elements in COORD array. - const hsize_t **coord; IN: The location of each element selected + const hsize_t *coord; IN: The location of each element selected RETURNS Non-negative on success/Negative on failure DESCRIPTION @@ -1280,32 +1346,32 @@ H5S_point_adjust_u(H5S_t *space, const hsize_t *offset) --------------------------------------------------------------------------*/ herr_t H5Sselect_elements(hid_t spaceid, H5S_seloper_t op, size_t num_elem, - const hsize_t **coord) + const hsize_t *coord) { - H5S_t *space = NULL; /* Dataspace to modify selection of */ - herr_t ret_value; /* return value */ + H5S_t *space = NULL; /* Dataspace to modify selection of */ + herr_t ret_value; /* Return value */ - FUNC_ENTER_API(H5Sselect_elements, FAIL); - H5TRACE4("e", "iSsz**h", spaceid, op, num_elem, coord); + FUNC_ENTER_API(H5Sselect_elements, FAIL) + H5TRACE4("e", "iSsz*h", spaceid, op, num_elem, coord); /* Check args */ - if (NULL == (space=H5I_object_verify(spaceid, H5I_DATASPACE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace"); - if (H5S_SCALAR==H5S_GET_EXTENT_TYPE(space)) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "point doesn't support H5S_SCALAR space"); - if (H5S_NULL==H5S_GET_EXTENT_TYPE(space)) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "point doesn't support H5S_NULL space"); - if(coord==NULL || num_elem==0) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "elements not specified"); - if(!(op==H5S_SELECT_SET || op==H5S_SELECT_APPEND || op==H5S_SELECT_PREPEND)) - HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "unsupported operation attempted"); + if(NULL == (space = H5I_object_verify(spaceid, H5I_DATASPACE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace") + if(H5S_SCALAR == H5S_GET_EXTENT_TYPE(space)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "point doesn't support H5S_SCALAR space") + if(H5S_NULL == H5S_GET_EXTENT_TYPE(space)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "point doesn't support H5S_NULL space") + if(coord == NULL || num_elem == 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "elements not specified") + if(!(op == H5S_SELECT_SET || op == H5S_SELECT_APPEND || op == H5S_SELECT_PREPEND)) + HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "unsupported operation attempted") /* Call the real element selection routine */ - if((ret_value=H5S_select_elements(space,op,num_elem,coord))<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't select elements"); + if((ret_value = H5S_select_elements(space, op, num_elem, coord)) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't select elements") done: - FUNC_LEAVE_API(ret_value); + FUNC_LEAVE_API(ret_value) } /* H5Sselect_elements() */ diff --git a/src/H5Sprivate.h b/src/H5Sprivate.h index ec48de9..bd27f09 100644 --- a/src/H5Sprivate.h +++ b/src/H5Sprivate.h @@ -78,8 +78,9 @@ typedef struct { /* "Flattened" regular hyperslab selection fields */ H5S_hyper_dim_t diminfo[H5S_MAX_RANK]; /* "Flattened" regular selection information */ - hsize_t size[H5S_MAX_RANK]; /* "Flattened" dataspace extent information */ - hssize_t sel_off[H5S_MAX_RANK]; /* "Flattened" selection offset information */ + hsize_t size[H5S_MAX_RANK]; /* "Flattened" dataspace extent information */ + hssize_t sel_off[H5S_MAX_RANK]; /* "Flattened" selection offset information */ + hbool_t flattened[H5S_MAX_RANK]; /* Whether this dimension has been flattened */ /* Irregular hyperslab selection fields */ H5S_hyper_span_info_t *spans; /* Pointer to copy of the span tree */ @@ -152,6 +153,7 @@ typedef struct H5S_iostats_t { #define H5S_SELECT_SERIAL_SIZE(S) ((*(S)->select.type->serial_size)(S)) #define H5S_SELECT_SERIALIZE(S,BUF) ((*(S)->select.type->serialize)(S,BUF)) #define H5S_SELECT_BOUNDS(S,START,END) ((*(S)->select.type->bounds)(S,START,END)) +#define H5S_SELECT_OFFSET(S, OFFSET) ((*(S)->select.type->offset)(S, OFFSET)) #define H5S_SELECT_IS_CONTIGUOUS(S) ((*(S)->select.type->is_contiguous)(S)) #define H5S_SELECT_IS_SINGLE(S) ((*(S)->select.type->is_single)(S)) #define H5S_SELECT_IS_REGULAR(S) ((*(S)->select.type->is_regular)(S)) @@ -175,6 +177,7 @@ typedef struct H5S_iostats_t { #define H5S_SELECT_SERIAL_SIZE(S) (H5S_select_serial_size(S)) #define H5S_SELECT_SERIALIZE(S,BUF) (H5S_select_serialize(S,BUF)) #define H5S_SELECT_BOUNDS(S,START,END) (H5S_get_select_bounds(S,START,END)) +#define H5S_SELECT_OFFSET(S, OFFSET) (H5S_get_select_offset(S, OFFSET)) #define H5S_SELECT_IS_CONTIGUOUS(S) (H5S_select_is_contiguous(S)) #define H5S_SELECT_IS_SINGLE(S) (H5S_select_is_single(S)) #define H5S_SELECT_IS_REGULAR(S) (H5S_select_is_regular(S)) @@ -205,10 +208,9 @@ H5_DLL hbool_t H5S_has_extent(const H5S_t *ds); H5_DLL int H5S_get_simple_extent_ndims(const H5S_t *ds); H5_DLL int H5S_get_simple_extent_dims(const H5S_t *ds, hsize_t dims[]/*out*/, hsize_t max_dims[]/*out*/); -H5_DLL herr_t H5S_write(struct H5O_loc_t *loc, const H5S_t *space, - hbool_t update_time, hid_t dxpl_id); -H5_DLL herr_t H5S_append(H5F_t *f, hid_t dxpl_id, struct H5O_t *oh, - const H5S_t *ds); +H5_DLL herr_t H5S_write(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned update_flags, + H5S_t *ds); +H5_DLL herr_t H5S_append(H5F_t *f, hid_t dxpl_id, struct H5O_t *oh, H5S_t *ds); H5_DLL H5S_t *H5S_read(const struct H5O_loc_t *loc, hid_t dxpl_id); H5_DLL int H5S_set_extent(H5S_t *space, const hsize_t *size); H5_DLL herr_t H5S_set_extent_real(H5S_t *space, const hsize_t *size); @@ -234,6 +236,7 @@ H5_DLL herr_t H5S_select_fill(const void *fill, size_t fill_size, H5_DLL htri_t H5S_select_valid(const H5S_t *space); H5_DLL hssize_t H5S_get_select_npoints(const H5S_t *space); H5_DLL herr_t H5S_get_select_bounds(const H5S_t *space, hsize_t *start, hsize_t *end); +H5_DLL herr_t H5S_get_select_offset(const H5S_t *space, hsize_t *offset); H5_DLL herr_t H5S_select_offset(H5S_t *space, const hssize_t *offset); H5_DLL herr_t H5S_select_copy(H5S_t *dst, const H5S_t *src, hbool_t share_selection); H5_DLL htri_t H5S_select_shape_same(const H5S_t *space1, const H5S_t *space2); @@ -255,8 +258,8 @@ H5_DLL herr_t H5S_select_all(H5S_t *space, hbool_t rel_prev); H5_DLL herr_t H5S_select_none(H5S_t *space); /* Operations on point selections */ -H5_DLL herr_t H5S_select_elements (H5S_t *space, H5S_seloper_t op, - size_t num_elem, const hsize_t **coord); +H5_DLL herr_t H5S_select_elements(H5S_t *space, H5S_seloper_t op, + size_t num_elem, const hsize_t *coord); /* Operations on hyperslab selections */ H5_DLL herr_t H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op, const hsize_t start[], @@ -271,7 +274,7 @@ H5_DLL htri_t H5S_hyper_intersect (H5S_t *space1, H5S_t *space2); H5_DLL htri_t H5S_hyper_intersect_block (H5S_t *space, hsize_t *start, hsize_t *end); H5_DLL herr_t H5S_hyper_adjust_s(H5S_t *space, const hssize_t *offset); H5_DLL herr_t H5S_hyper_move(H5S_t *space, const hssize_t *offset); -H5_DLL herr_t H5S_hyper_normalize_offset(H5S_t *space, hssize_t *old_offset); +H5_DLL htri_t H5S_hyper_normalize_offset(H5S_t *space, hssize_t *old_offset); H5_DLL herr_t H5S_hyper_denormalize_offset(H5S_t *space, const hssize_t *old_offset); /* Operations on selection iterators */ diff --git a/src/H5Spublic.h b/src/H5Spublic.h index 4a49da2..43f79b9 100644 --- a/src/H5Spublic.h +++ b/src/H5Spublic.h @@ -126,8 +126,7 @@ H5_DLL hid_t H5Scombine_select(hid_t space1_id, H5S_seloper_t op, hid_t space2_id); #endif /* NEW_HYPERSLAB_API */ H5_DLL herr_t H5Sselect_elements(hid_t space_id, H5S_seloper_t op, - size_t num_elemn, - const hsize_t **coord); + size_t num_elem, const hsize_t *coord); H5_DLL H5S_class_t H5Sget_simple_extent_type(hid_t space_id); H5_DLL herr_t H5Sset_extent_none(hid_t space_id); H5_DLL herr_t H5Sextent_copy(hid_t dst_id,hid_t src_id); @@ -138,9 +137,12 @@ H5_DLL herr_t H5Soffset_simple(hid_t space_id, const hssize_t *offset); H5_DLL htri_t H5Sselect_valid(hid_t spaceid); H5_DLL hssize_t H5Sget_select_hyper_nblocks(hid_t spaceid); H5_DLL hssize_t H5Sget_select_elem_npoints(hid_t spaceid); -H5_DLL herr_t H5Sget_select_hyper_blocklist(hid_t spaceid, hsize_t startblock, hsize_t numblocks, hsize_t *buf); -H5_DLL herr_t H5Sget_select_elem_pointlist(hid_t spaceid, hsize_t startpoint, hsize_t numpoints, hsize_t *buf); -H5_DLL herr_t H5Sget_select_bounds(hid_t spaceid, hsize_t *start, hsize_t *end); +H5_DLL herr_t H5Sget_select_hyper_blocklist(hid_t spaceid, hsize_t startblock, + hsize_t numblocks, hsize_t buf[/*numblocks*/]); +H5_DLL herr_t H5Sget_select_elem_pointlist(hid_t spaceid, hsize_t startpoint, + hsize_t numpoints, hsize_t buf[/*numpoints*/]); +H5_DLL herr_t H5Sget_select_bounds(hid_t spaceid, hsize_t start[], + hsize_t end[]); H5_DLL H5S_sel_type H5Sget_select_type(hid_t spaceid); #ifdef __cplusplus diff --git a/src/H5Sselect.c b/src/H5Sselect.c index 31fd05e..ed3c740 100644 --- a/src/H5Sselect.c +++ b/src/H5Sselect.c @@ -62,17 +62,20 @@ static herr_t H5S_select_iter_next_block(H5S_sel_iter_t *iter); herr_t H5S_select_offset(H5S_t *space, const hssize_t *offset) { - FUNC_ENTER_NOAPI_NOFUNC(H5S_select_offset); + FUNC_ENTER_NOAPI_NOFUNC(H5S_select_offset) /* Check args */ - assert(space); - assert(space->extent.rank); - assert(offset); + HDassert(space); + HDassert(space->extent.rank); + HDassert(offset); /* Copy the offset over */ - HDmemcpy(space->select.offset,offset,sizeof(hssize_t)*space->extent.rank); + HDmemcpy(space->select.offset, offset, sizeof(hssize_t)*space->extent.rank); - FUNC_LEAVE_NOAPI(SUCCEED); + /* Indicate that the offset was changed */ + space->select.offset_changed = TRUE; + + FUNC_LEAVE_NOAPI(SUCCEED) } /* H5S_select_offset() */ @@ -488,8 +491,8 @@ done: USAGE herr_t H5S_get_select_bounds(space, start, end) hid_t dsid; IN: Dataspace ID of selection to query - hsize_t *start; OUT: Starting coordinate of bounding box - hsize_t *end; OUT: Opposite coordinate of bounding box + hsize_t start[]; OUT: Starting coordinate of bounding box + hsize_t end[]; OUT: Opposite coordinate of bounding box RETURNS Non-negative on success, negative on failure DESCRIPTION @@ -511,7 +514,7 @@ done: REVISION LOG --------------------------------------------------------------------------*/ herr_t -H5Sget_select_bounds(hid_t spaceid, hsize_t *start, hsize_t *end) +H5Sget_select_bounds(hid_t spaceid, hsize_t start[], hsize_t end[]) { H5S_t *space = NULL; /* Dataspace to modify selection of */ herr_t ret_value; /* return value */ @@ -579,6 +582,46 @@ H5S_get_select_bounds(const H5S_t *space, hsize_t *start, hsize_t *end) /*-------------------------------------------------------------------------- NAME + H5S_get_select_offset + PURPOSE + Gets the linear offset of the first element for the selection. + USAGE + herr_t H5S_get_select_offset(space, offset) + const H5S_t *space; IN: Dataspace pointer of selection to query + hsize_t *offset; OUT: Linear offset of first element in selection + RETURNS + Non-negative on success, negative on failure + DESCRIPTION + Retrieves the linear offset (in "units" of elements) of the first element + selected within the dataspace. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + The offset calculation _does_ include the current offset of the + selection within the dataspace extent. + + Calling this function on a "none" selection returns fail. + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5S_get_select_offset(const H5S_t *space, hsize_t *offset) +{ + herr_t ret_value; /* return value */ + + FUNC_ENTER_NOAPI_NOFUNC(H5S_get_select_offset) + + /* Check args */ + HDassert(space); + HDassert(offset); + + ret_value = (*space->select.type->offset)(space, offset); + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5S_get_select_offset() */ + + +/*-------------------------------------------------------------------------- + NAME H5S_select_is_contiguous PURPOSE Determines if a selection is contiguous in the dataspace @@ -758,10 +801,9 @@ H5S_select_iter_init(H5S_sel_iter_t *sel_iter, const H5S_t *space, size_t elmt_s /* Save the dataspace's rank */ sel_iter->rank=space->extent.rank; - if(sel_iter->rank>0) { - /* Point to the dataspace dimensions */ - sel_iter->dims=space->extent.size; - } /* end if */ + /* Point to the dataspace dimensions, if there are any */ + if(sel_iter->rank > 0) + sel_iter->dims = space->extent.size; else sel_iter->dims = NULL; @@ -96,10 +96,6 @@ H5TS_first_thread_init(void) { H5_g.H5_libinit_g = FALSE; - /* set the owner objects to initial values */ - H5_g.init_lock.owner_thread = pthread_self(); - H5_g.init_lock.owner_valid = FALSE; - /* initialize global API mutex lock */ pthread_mutex_init(&H5_g.init_lock.atomic_lock, NULL); pthread_cond_init(&H5_g.init_lock.cond_var, NULL); @@ -150,26 +146,17 @@ H5TS_mutex_lock(H5TS_mutex_t *mutex) if (ret_value) return ret_value; - if (mutex->owner_valid && pthread_equal(pthread_self(), mutex->owner_thread)) { + if(mutex->lock_count && pthread_equal(pthread_self(), mutex->owner_thread)) { /* already owned by self - increment count */ mutex->lock_count++; - } else if (!mutex->owner_valid) { - /* no one else has locked it - set owner and grab lock */ + } else { + /* if owned by other thread, wait for condition signal */ + while(mutex->lock_count) + pthread_cond_wait(&mutex->cond_var, &mutex->atomic_lock); + + /* After we've received the signal, take ownership of the mutex */ mutex->owner_thread = pthread_self(); - mutex->owner_valid = TRUE; mutex->lock_count = 1; - } else { - /* if already locked by someone else */ - for (;;) { - pthread_cond_wait(&mutex->cond_var, &mutex->atomic_lock); - - if (!mutex->owner_valid) { - mutex->owner_thread = pthread_self(); - mutex->owner_valid = TRUE; - mutex->lock_count = 1; - break; - } - } } return pthread_mutex_unlock(&mutex->atomic_lock); @@ -204,26 +191,26 @@ H5TS_mutex_lock(H5TS_mutex_t *mutex) herr_t H5TS_mutex_unlock(H5TS_mutex_t *mutex) { - herr_t ret_value; + herr_t ret_value; /* Return value */ ret_value = pthread_mutex_lock(&mutex->atomic_lock); - if (ret_value) - return ret_value; + if(ret_value) + return ret_value; mutex->lock_count--; - if (mutex->lock_count == 0) { - mutex->owner_valid = FALSE; - ret_value = pthread_cond_signal(&mutex->cond_var); + ret_value = pthread_mutex_unlock(&mutex->atomic_lock); - if (ret_value) { - pthread_mutex_unlock(&mutex->atomic_lock); - return ret_value; - } - } + if(mutex->lock_count == 0) { + int err; - return pthread_mutex_unlock(&mutex->atomic_lock); + err = pthread_cond_signal(&mutex->cond_var); + if(err != 0) + ret_value = err; + } /* end if */ + + return ret_value; } /*-------------------------------------------------------------------------- diff --git a/src/H5TSprivate.h b/src/H5TSprivate.h index f817120..0d0b620 100644 --- a/src/H5TSprivate.h +++ b/src/H5TSprivate.h @@ -37,7 +37,6 @@ typedef struct H5TS_mutex_struct { pthread_t owner_thread; /* current lock owner */ - unsigned owner_valid; /* if current lock owner info is valid */ pthread_mutex_t atomic_lock; /* lock for atomicity of new mechanism */ pthread_cond_t cond_var; /* condition variable */ unsigned int lock_count; diff --git a/src/H5Znbit.c b/src/H5Znbit.c index 7a29d45..1b9265d 100644 --- a/src/H5Znbit.c +++ b/src/H5Znbit.c @@ -96,7 +96,6 @@ H5Z_class_t H5Z_NBIT[1] = {{ #define H5Z_NBIT_ARRAY 2 /* Array datatype class */ #define H5Z_NBIT_COMPOUND 3 /* Compound datatype class */ #define H5Z_NBIT_NOOPTYPE 4 /* Other datatype class: nbit does no compression */ -#define H5Z_NBIT_USER_NPARMS 0 /* Number of parameters that users can set */ #define H5Z_NBIT_MAX_NPARMS 4096 /* Max number of parameters for filter */ #define H5Z_NBIT_ORDER_LE 0 /* Little endian for datatype byte order */ #define H5Z_NBIT_ORDER_BE 1 /* Big endian for datatype byte order */ @@ -1409,4 +1408,4 @@ static void H5Z_nbit_compress(unsigned char *data, unsigned d_nelmts, unsigned c *buffer_size = j + 1; /* sometimes is catually j, but to be safe */ } -#endif /* H5_HAVE_FILTER_NZIP */ +#endif /* H5_HAVE_FILTER_NBIT */ diff --git a/src/H5Zpublic.h b/src/H5Zpublic.h index 1fac71c..7211a2b 100644 --- a/src/H5Zpublic.h +++ b/src/H5Zpublic.h @@ -74,6 +74,25 @@ typedef int H5Z_filter_t; #define H5_SZIP_NN_OPTION_MASK 32 #define H5_SZIP_MAX_PIXELS_PER_BLOCK 32 +/* Macros for the shuffle filter */ +#define H5Z_SHUFFLE_USER_NPARMS 0 /* Number of parameters that users can set */ +#define H5Z_SHUFFLE_TOTAL_NPARMS 1 /* Total number of parameters for filter */ + +/* Macros for the szip filter */ +#define H5Z_SZIP_USER_NPARMS 2 /* Number of parameters that users can set */ +#define H5Z_SZIP_TOTAL_NPARMS 4 /* Total number of parameters for filter */ +#define H5Z_SZIP_PARM_MASK 0 /* "User" parameter for option mask */ +#define H5Z_SZIP_PARM_PPB 1 /* "User" parameter for pixels-per-block */ +#define H5Z_SZIP_PARM_BPP 2 /* "Local" parameter for bits-per-pixel */ +#define H5Z_SZIP_PARM_PPS 3 /* "Local" parameter for pixels-per-scanline */ + +/* Macros for the nbit filter */ +#define H5Z_NBIT_USER_NPARMS 0 /* Number of parameters that users can set */ + +/* Macros for the scale offset filter */ +#define H5Z_SCALEOFFSET_USER_NPARMS 2 /* Number of parameters that users can set */ + + /* Special parameters for ScaleOffset filter*/ #define H5Z_SO_INT_MINBITS_DEFAULT 0 typedef enum H5Z_SO_scale_type_t { diff --git a/src/H5Zscaleoffset.c b/src/H5Zscaleoffset.c index b970cdf..5ef3e7a 100644 --- a/src/H5Zscaleoffset.c +++ b/src/H5Zscaleoffset.c @@ -93,7 +93,6 @@ H5Z_class_t H5Z_SCALEOFFSET[1] = {{ }}; /* Local macros */ -#define H5Z_SCALEOFFSET_USER_NPARMS 2 /* Number of parameters that users can set */ #define H5Z_SCALEOFFSET_TOTAL_NPARMS 20 /* Total number of parameters for filter */ #define H5Z_SCALEOFFSET_PARM_SCALETYPE 0 /* "User" parameter for scale type */ #define H5Z_SCALEOFFSET_PARM_SCALEFACTOR 1 /* "User" parameter for scale factor */ diff --git a/src/H5Zshuffle.c b/src/H5Zshuffle.c index c203ed9..3f40707 100644 --- a/src/H5Zshuffle.c +++ b/src/H5Zshuffle.c @@ -44,8 +44,6 @@ const H5Z_class_t H5Z_SHUFFLE[1] = {{ }}; /* Local macros */ -#define H5Z_SHUFFLE_USER_NPARMS 0 /* Number of parameters that users can set */ -#define H5Z_SHUFFLE_TOTAL_NPARMS 1 /* Total number of parameters for filter */ #define H5Z_SHUFFLE_PARM_SIZE 0 /* "Local" parameter for shuffling size */ diff --git a/src/H5Zszip.c b/src/H5Zszip.c index cdc26aa..9201a80 100644 --- a/src/H5Zszip.c +++ b/src/H5Zszip.c @@ -51,13 +51,6 @@ H5Z_class_t H5Z_SZIP[1] = {{ H5Z_filter_szip, /* The actual filter function */ }}; -/* Local macros */ -#define H5Z_SZIP_USER_NPARMS 2 /* Number of parameters that users can set */ -#define H5Z_SZIP_TOTAL_NPARMS 4 /* Total number of parameters for filter */ -#define H5Z_SZIP_PARM_MASK 0 /* "User" parameter for option mask */ -#define H5Z_SZIP_PARM_PPB 1 /* "User" parameter for pixels-per-block */ -#define H5Z_SZIP_PARM_BPP 2 /* "Local" parameter for bits-per-pixel */ -#define H5Z_SZIP_PARM_PPS 3 /* "Local" parameter for pixels-per-scanline */ /*------------------------------------------------------------------------- diff --git a/src/H5checksum.c b/src/H5checksum.c index f2e344d..e42f152 100644 --- a/src/H5checksum.c +++ b/src/H5checksum.c @@ -459,3 +459,36 @@ H5_checksum_metadata(const void *data, size_t len, uint32_t initval) FUNC_LEAVE_NOAPI(H5_checksum_lookup3(data, len, initval)) } /* end H5_checksum_metadata() */ + +/*------------------------------------------------------------------------- + * Function: H5_hash_string + * + * Purpose: Provide a simple & fast routine for hashing strings + * + * Note: This algorithm is the 'djb2' algorithm described on this page: + * http://www.cse.yorku.ca/~oz/hash.html + * + * Return: hash of input string (can't fail) + * + * Programmer: Quincey Koziol + * Tuesday, December 11, 2007 + * + *------------------------------------------------------------------------- + */ +uint32_t +H5_hash_string(const char *str) +{ + uint32_t hash = 5381; + int c; + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5_hash_string) + + /* Sanity check */ + HDassert(str); + + while(c = *str++) + hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ + + FUNC_LEAVE_NOAPI(hash) +} /* end H5_hash_string() */ + diff --git a/src/H5config.h.in b/src/H5config.h.in index 0c89e98..5c767ef 100644 --- a/src/H5config.h.in +++ b/src/H5config.h.in @@ -570,6 +570,9 @@ /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS +/* Define if strict file format checks are enabled */ +#undef STRICT_FORMAT_CHECKS + /* Define if your system supports pthread_attr_setscope(&attribute, PTHREAD_SCOPE_SYSTEM) call. */ #undef SYSTEM_SCOPE_THREADS diff --git a/src/H5private.h b/src/H5private.h index ebbad21..343e652 100644 --- a/src/H5private.h +++ b/src/H5private.h @@ -485,6 +485,12 @@ typedef enum { H5_COPY_DEEP /* Deep copy from source to destination, including duplicating fields pointed to */ } H5_copy_depth_t; +/* Unique object "position" */ +typedef struct { + unsigned long fileno; /* The unique identifier for the file of the object */ + haddr_t addr; /* The unique address of the object's header in that file */ +} H5_obj_t; + /* * Redefine all the POSIX functions. We should never see a POSIX * function (or any other non-HDF5 function) in the source! @@ -1473,6 +1479,7 @@ H5_DLL uint32_t H5_checksum_fletcher32(const void *data, size_t len); H5_DLL uint32_t H5_checksum_crc(const void *data, size_t len); H5_DLL uint32_t H5_checksum_lookup3(const void *data, size_t len, uint32_t initval); H5_DLL uint32_t H5_checksum_metadata(const void *data, size_t len, uint32_t initval); +H5_DLL uint32_t H5_hash_string(const char *str); /* Functions for debugging */ H5_DLL herr_t H5_buffer_dump(FILE *stream, int indent, uint8_t *buf, diff --git a/src/H5public.h b/src/H5public.h index 608e52c..06060dd 100644 --- a/src/H5public.h +++ b/src/H5public.h @@ -72,9 +72,9 @@ extern "C" { #define H5_VERS_MAJOR 1 /* For major interface/format changes */ #define H5_VERS_MINOR 8 /* For minor interface/format changes */ #define H5_VERS_RELEASE 0 /* For tweaks, bug-fixes, or development */ -#define H5_VERS_SUBRELEASE "beta4post1" /* For pre-releases like snap0 */ +#define H5_VERS_SUBRELEASE "" /* For pre-releases like snap0 */ /* Empty string for real releases. */ -#define H5_VERS_INFO "HDF5 library version: 1.8.0-beta4post1" /* 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/H5trace.c b/src/H5trace.c index 0ad99b2..926a590 100644 --- a/src/H5trace.c +++ b/src/H5trace.c @@ -647,6 +647,26 @@ H5_trace (const double *returning, const char *func, const char *type, ...) } break; + case 'v': + if(ptr) { + if(vp) + fprintf(out, "0x%lx", (unsigned long)vp); + else + fprintf(out, "NULL"); + } else { + H5F_libver_t libver_vers = va_arg(ap, H5F_libver_t); /*lint !e64 Type mismatch not really occuring */ + + switch(libver_vers) { + case H5F_LIBVER_EARLIEST: + fprintf(out, "H5F_LIBVER_EARLIEST"); + break; + case H5F_LIBVER_LATEST: + fprintf(out, "H5F_LIBVER_LATEST"); + break; + } + } + break; + default: fprintf(out, "BADTYPE(F%c)", type[1]); goto error; diff --git a/src/Makefile.am b/src/Makefile.am index 75f84e6..5671533 100755 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -54,7 +54,7 @@ libhdf5_la_SOURCES= H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \ H5F.c H5Fdbg.c H5Ffake.c H5Fmount.c H5Fsfile.c H5Fsuper.c H5Ftest.c \ H5FD.c H5FDcore.c \ H5FDdirect.c H5FDfamily.c H5FDlog.c H5FDmpi.c H5FDmpio.c \ - H5FDmpiposix.c H5FDmulti.c H5FDsec2.c H5FDstdio.c \ + H5FDmpiposix.c H5FDmulti.c H5FDsec2.c H5FDspace.c H5FDstdio.c \ H5FL.c H5FO.c H5FS.c H5FScache.c H5FSdbg.c H5FSsection.c \ H5G.c H5Gbtree2.c H5Gcompact.c H5Gdense.c H5Gdeprec.c H5Gent.c \ H5Gint.c H5Glink.c \ diff --git a/src/Makefile.in b/src/Makefile.in index 79d8f07..197191e 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -89,37 +89,38 @@ am_libhdf5_la_OBJECTS = H5.lo H5checksum.lo H5dbg.lo H5system.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 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 H5Lexternal.lo H5MF.lo H5MM.lo H5MP.lo \ - H5MPtest.lo H5O.lo H5Oainfo.lo H5Oalloc.lo H5Oattr.lo \ - H5Oattribute.lo H5Obogus.lo H5Obtreek.lo H5Ocache.lo \ - H5Ocont.lo H5Ocopy.lo H5Odbg.lo H5Odrvinfo.lo H5Odtype.lo \ - H5Oefl.lo H5Ofill.lo H5Oginfo.lo H5Olayout.lo H5Olinfo.lo \ - H5Olink.lo H5Omdj_msg.lo H5Omessage.lo H5Omtime.lo H5Oname.lo \ - H5Onull.lo H5Opline.lo H5Orefcount.lo H5Osdspace.lo \ - H5Oshared.lo H5Ostab.lo H5Oshmesg.lo H5Otest.lo H5Ounknown.lo \ - H5P.lo H5Pacpl.lo H5Pdcpl.lo H5Pdeprec.lo H5Pdxpl.lo \ - H5Pfapl.lo H5Pfcpl.lo H5Pfmpl.lo H5Pgcpl.lo H5Pint.lo \ - H5Plapl.lo H5Plcpl.lo H5Pocpl.lo H5Pocpypl.lo H5Pstrcpl.lo \ - H5Ptest.lo H5R.lo H5Rdeprec.lo H5RC.lo H5RS.lo H5S.lo \ - H5Sall.lo H5Sdbg.lo H5Shyper.lo H5Smpio.lo H5Snone.lo \ - H5Spoint.lo H5Sselect.lo H5Stest.lo H5SL.lo H5SM.lo \ - H5SMbtree2.lo H5SMcache.lo H5SMtest.lo H5ST.lo H5T.lo \ - H5Tarray.lo H5Tbit.lo H5Tcommit.lo H5Tcompound.lo H5Tconv.lo \ - H5Tcset.lo H5Tdbg.lo H5Tdeprec.lo H5Tenum.lo H5Tfields.lo \ - H5Tfixed.lo H5Tfloat.lo H5Tinit.lo H5Tnative.lo H5Toffset.lo \ - H5Toh.lo H5Topaque.lo H5Torder.lo H5Tpad.lo H5Tprecis.lo \ - H5Tstrpad.lo H5Tvisit.lo H5Tvlen.lo H5TS.lo H5V.lo H5WB.lo \ - H5Z.lo H5Zdeflate.lo H5Zfletcher32.lo H5Znbit.lo H5Zshuffle.lo \ - H5Zszip.lo H5Zscaleoffset.lo H5Ztrans.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 \ + H5Lexternal.lo H5MF.lo H5MM.lo H5MP.lo H5MPtest.lo H5O.lo \ + H5Oainfo.lo H5Oalloc.lo H5Oattr.lo H5Oattribute.lo H5Obogus.lo \ + H5Obtreek.lo H5Ocache.lo H5Ocont.lo H5Ocopy.lo H5Odbg.lo \ + H5Odrvinfo.lo H5Odtype.lo H5Oefl.lo H5Ofill.lo H5Oginfo.lo \ + H5Olayout.lo H5Olinfo.lo H5Olink.lo H5Omdj_msg.lo \ + H5Omessage.lo H5Omtime.lo H5Oname.lo H5Onull.lo H5Opline.lo \ + H5Orefcount.lo H5Osdspace.lo H5Oshared.lo H5Ostab.lo \ + H5Oshmesg.lo H5Otest.lo H5Ounknown.lo H5P.lo H5Pacpl.lo \ + H5Pdcpl.lo H5Pdeprec.lo H5Pdxpl.lo H5Pfapl.lo H5Pfcpl.lo \ + H5Pfmpl.lo H5Pgcpl.lo H5Pint.lo H5Plapl.lo H5Plcpl.lo \ + H5Pocpl.lo H5Pocpypl.lo H5Pstrcpl.lo H5Ptest.lo H5R.lo \ + H5Rdeprec.lo H5RC.lo H5RS.lo H5S.lo H5Sall.lo H5Sdbg.lo \ + H5Shyper.lo H5Smpio.lo H5Snone.lo H5Spoint.lo H5Sselect.lo \ + H5Stest.lo H5SL.lo H5SM.lo H5SMbtree2.lo H5SMcache.lo \ + H5SMtest.lo H5ST.lo H5T.lo H5Tarray.lo H5Tbit.lo H5Tcommit.lo \ + H5Tcompound.lo H5Tconv.lo H5Tcset.lo H5Tdbg.lo H5Tdeprec.lo \ + H5Tenum.lo H5Tfields.lo H5Tfixed.lo H5Tfloat.lo H5Tinit.lo \ + H5Tnative.lo H5Toffset.lo H5Toh.lo H5Topaque.lo H5Torder.lo \ + H5Tpad.lo H5Tprecis.lo H5Tstrpad.lo H5Tvisit.lo H5Tvlen.lo \ + H5TS.lo H5V.lo H5WB.lo H5Z.lo H5Zdeflate.lo H5Zfletcher32.lo \ + H5Znbit.lo H5Zshuffle.lo H5Zszip.lo H5Zscaleoffset.lo \ + H5Ztrans.lo libhdf5_la_OBJECTS = $(am_libhdf5_la_OBJECTS) libhdf5_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ @@ -270,6 +271,7 @@ SET_MAKE = @SET_MAKE@ SHELL = /bin/sh SIZE_T = @SIZE_T@ STATIC_SHARED = @STATIC_SHARED@ +STRICT_FORMAT_CHECKS = @STRICT_FORMAT_CHECKS@ STRIP = @STRIP@ TESTPARALLEL = @TESTPARALLEL@ TIME = @TIME@ @@ -382,9 +384,9 @@ CHECK_CLEANFILES = *.chkexe *.chklog *.clog # Add libtool shared library version numbers to the HDF5 library # See libtool versioning documentation online. -LT_VERS_INTERFACE = 4 -LT_VERS_REVISION = 4 -LT_VERS_AGE = 3 +LT_VERS_INTERFACE = 5 +LT_VERS_REVISION = 0 +LT_VERS_AGE = 0 H5detect_CFLAGS = -g # Our main target, the HDF5 library @@ -412,7 +414,7 @@ libhdf5_la_SOURCES = H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \ H5F.c H5Fdbg.c H5Ffake.c H5Fmount.c H5Fsfile.c H5Fsuper.c H5Ftest.c \ H5FD.c H5FDcore.c \ H5FDdirect.c H5FDfamily.c H5FDlog.c H5FDmpi.c H5FDmpio.c \ - H5FDmpiposix.c H5FDmulti.c H5FDsec2.c H5FDstdio.c \ + H5FDmpiposix.c H5FDmulti.c H5FDsec2.c H5FDspace.c H5FDstdio.c \ H5FL.c H5FO.c H5FS.c H5FScache.c H5FSdbg.c H5FSsection.c \ H5G.c H5Gbtree2.c H5Gcompact.c H5Gdense.c H5Gdeprec.c H5Gent.c \ H5Gint.c H5Glink.c \ @@ -632,6 +634,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FDmpiposix.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FDmulti.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FDsec2.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FDspace.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FDstdio.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FL.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FO.Plo@am__quote@ |